1 /*******************************************************************************
2
3 KHOMP generic endpoint/channel library.
4 Copyright (C) 2007-2010 Khomp Ind. & Com.
5
6 The contents of this file are subject to the Mozilla Public License
7 Version 1.1 (the "License"); you may not use this file except in compliance
8 with the License. You may obtain a copy of the License at
9 http://www.mozilla.org/MPL/
10
11 Software distributed under the License is distributed on an "AS IS" basis,
12 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
13 the specific language governing rights and limitations under the License.
14
15 Alternatively, the contents of this file may be used under the terms of the
16 "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
17 case the provisions of "LGPL License" are applicable instead of those above.
18
19 If you wish to allow use of your version of this file only under the terms of
20 the LGPL License and not to allow others to use your version of this file
21 under the MPL, indicate your decision by deleting the provisions above and
22 replace them with the notice and other provisions required by the LGPL
23 License. If you do not delete the provisions above, a recipient may use your
24 version of this file under either the MPL or the LGPL License.
25
26 The LGPL header follows below:
27
28 This library is free software; you can redistribute it and/or
29 modify it under the terms of the GNU Lesser General Public
30 License as published by the Free Software Foundation; either
31 version 2.1 of the License, or (at your option) any later version.
32
33 This library is distributed in the hope that it will be useful,
34 but WITHOUT ANY WARRANTY; without even the implied warranty of
35 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36 Lesser General Public License for more details.
37
38 You should have received a copy of the GNU Lesser General Public License
39 along with this library; if not, write to the Free Software Foundation,
40 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
41
42 *******************************************************************************/
43
44 #ifndef _UTILS_H_
45 #define _UTILS_H_
46
47 #include <bitset>
48 #include <refcounter.hpp>
49 #include <ringbuffer.hpp>
50 #include <simple_lock.hpp>
51 #include <saved_condition.hpp>
52 #include <thread.hpp>
53 #include "globals.h"
54 #include "logger.h"
55 #include "defs.h"
56
57 /******************************************************************************/
58 /************************** Defining applications *****************************/
59
60 typedef enum
61 {
62 FAX_ADJUST,
63 FAX_SEND,
64 FAX_RECEIVE,
65 USER_TRANSFER,
66 SMS_CHECK,
67 SMS_SEND,
68 SELECT_SIM_CARD,
69 }
70 ApplicationType;
71
72 /******************************************************************************/
73 /***************** Abstraction for defining channel flags *********************/
74
75 struct Kflags
76 {
77 typedef enum
78 {
79 CONNECTED = 0,
80 REALLY_CONNECTED,
81
82 IS_OUTGOING,
83 IS_INCOMING,
84
85 STREAM_UP,
86 LISTEN_UP,
87
88 GEN_CO_RING,
89 GEN_PBX_RING,
90
91 HAS_PRE_AUDIO,
92 HAS_CALL_FAIL,
93
94 DROP_COLLECT,
95
96 NEEDS_RINGBACK_CMD, //R2
97 EARLY_RINGBACK, //FXO
98
99 FAX_DETECTED, //Digital, FXO
100 FAX_SENDING, //Digital, FXO
101 FAX_RECEIVING, //Digital, FXO
102
103 OUT_OF_BAND_DTMFS,
104
105 KEEP_DTMF_SUPPRESSION,
106 KEEP_ECHO_CANCELLATION,
107 KEEP_AUTO_GAIN_CONTROL,
108
109 WAIT_SEND_DTMF,
110
111 CALL_WAIT_SEIZE, //FXO
112
113 NUMBER_DIAL_FINISHD, //R2
114 NUMBER_DIAL_ONGOING, //R2
115
116 FXS_OFFHOOK, //FXS
117 FXS_DIAL_FINISHD, //FXS
118 FXS_DIAL_ONGOING, //FXS
119 FXS_FLASH_TRANSFER, //FXS
120
121 XFER_QSIG_DIALING, //ISDN
122 XFER_DIALING, //ISDN, FXO
123
124 SMS_DOING_UPLOAD, //GSM
125
126 /*
127 NOW LOADING ...
128
129 BRIDGED,
130 */
131
132 /* Do not remove this last FLAG */
133 INVALID_FLAG
134 }
135 FlagType;
136
137 struct Flag
138 {
139 const char *_name;
140 bool _value;
141 };
142
KflagsKflags143 Kflags() { init(); };
144
145 void init();
146
nameKflags147 inline const char * name(FlagType bit) { return _flags[bit]._name; }
148
checkKflags149 inline bool check(FlagType bit)
150 {
151 #ifdef DEBUG_FLAGS
152 DBG(FUNC, D("Flag %s=%s") % name(bit) %
153 (_flags[bit]._value ? "TRUE" : "FALSE"));
154 #endif
155 return _flags[bit]._value;
156 }
157
setKflags158 inline void set(FlagType bit)
159 {
160 #ifdef DEBUG_FLAGS
161 DBG(FUNC, D("Flag %s") % name(bit));
162 #endif
163 _flags[bit]._value = true;
164 }
165
clearKflags166 inline void clear(FlagType bit)
167 {
168 #ifdef DEBUG_FLAGS
169 DBG(FUNC, D("Flag %s") % name(bit));
170 #endif
171 _flags[bit]._value = false;
172 }
173
clearAllKflags174 inline void clearAll()
175 {
176 unsigned int index = 0;
177 for(; (FlagType)index < INVALID_FLAG; index++)
178 {
179 if(_flags[index]._value)
180 {
181 DBG(FUNC, D("Flag %s was not clean!") % name((FlagType)index));
182 clear((FlagType)index);
183 }
184 }
185 }
186
187 protected:
188 Flag _flags[INVALID_FLAG+1];
189 };
190
191 /******************************************************************************/
192 /************************* Commands and Events Handler ************************/
193 struct CommandRequest
194 {
195 typedef enum
196 {
197 NONE = 0,
198 COMMAND,
199 ACTION
200 }
201 ReqType;
202
203 typedef enum
204 {
205 CNONE = 0,
206
207 /* Commands */
208 CMD_CALL,
209 CMD_ANSWER,
210 CMD_HANGUP,
211
212 /* Actions */
213 FLUSH_REC_STREAM,
214 FLUSH_REC_BRIDGE,
215 START_RECORD,
216 STOP_RECORD
217
218 }
219 CodeType;
220
221 typedef enum
222 {
223 RFA_CLOSE,
224 RFA_KEEP_OPEN,
225 RFA_REMOVE
226 }
227 RecFlagType;
228
229 /* "empty" constructor */
CommandRequestCommandRequest230 CommandRequest() :
231 _type(NONE),
232 _code(CNONE),
233 _obj(-1)
234 {}
235
CommandRequestCommandRequest236 CommandRequest(ReqType type, CodeType code, int obj) :
237 _type(type),
238 _code(code),
239 _obj(obj)
240 {}
241
CommandRequestCommandRequest242 CommandRequest(const CommandRequest & cmd) :
243 _type(cmd._type),
244 _code(cmd._code),
245 _obj(cmd._obj)
246 {}
247
~CommandRequestCommandRequest248 ~CommandRequest() {}
249
250 void operator=(const CommandRequest & cmd)
251 {
252 _type = cmd._type;
253 _code = cmd._code;
254 _obj = cmd._obj;
255 }
256
mirrorCommandRequest257 void mirror(const CommandRequest & cmd_request)
258 {
259 _type = cmd_request._type;
260 _code = cmd_request._code;
261 _obj = cmd_request._obj;
262 }
263
typeCommandRequest264 short type() { return _type; }
265
codeCommandRequest266 short code() { return _code; }
267
objCommandRequest268 int obj() { return _obj; }
269
270 private:
271 short _type;
272 short _code;
273 int _obj;
274 };
275
276 struct EventRequest
277 {
278 /* "empty" constructor */
279 EventRequest(bool can_delete = true) :
_deleteEventRequest280 _delete(can_delete),
281 _obj(-1)
282 {
283 if(can_delete)
284 _event = new K3L_EVENT();
285 }
286
287 /* Temporary constructor */
EventRequestEventRequest288 EventRequest(int obj, K3L_EVENT * ev) :
289 _delete(false),
290 _obj(obj),
291 _event(ev)
292 {}
293
294 //EventRequest(const EventRequest & ev) : _obj(ev._obj) {}
295
~EventRequestEventRequest296 ~EventRequest()
297 {
298
299 if(!_delete || !_event)
300 return;
301
302 if(_event->ParamSize)
303 free(_event->Params);
304
305 delete _event;
306 }
307
308 void operator=(const EventRequest & ev)
309 {
310 _delete = false;
311 _obj = ev._obj;
312 _event = ev._event;
313
314 }
315
mirrorEventRequest316 void mirror(const EventRequest & ev_request)
317 {
318 //Checar o _event
319
320 if(_event->ParamSize)
321 {
322 free(_event->Params);
323 }
324
325 _event->Params = NULL;
326
327 _obj = ev_request._obj;
328
329 K3L_EVENT * ev = ev_request._event;
330
331 if(!ev)
332 {
333 clearEvent();
334 return;
335 }
336
337 _event->Code = ev->Code; // API code
338 _event->AddInfo = ev->AddInfo; // Parameter 1
339 _event->DeviceId = ev->DeviceId; // Hardware information
340 _event->ObjectInfo = ev->ObjectInfo; // Additional object information
341 _event->ParamSize = ev->ParamSize; // Size of parameter buffer
342 _event->ObjectId = ev->ObjectId; // KEventObjectId: Event thrower object id
343
344 if(ev->ParamSize)
345 {
346 // Pointer to the parameter buffer
347 _event->Params = malloc(ev->ParamSize+1);
348 memcpy(_event->Params, ev->Params, ev->ParamSize);
349 ((char *)(_event->Params))[ev->ParamSize] = 0;
350 }
351 }
352
clearEventEventRequest353 bool clearEvent()
354 {
355 _event->Code = -1;
356 _event->AddInfo = -1;
357 _event->DeviceId = -1;
358 _event->ObjectInfo = -1;
359 _event->ParamSize = 0;
360 _event->ObjectId = -1;
361 }
362
objEventRequest363 int obj() { return _obj; }
364
eventEventRequest365 K3L_EVENT * event() { return _event; }
366
367
368 private:
369 bool _delete;
370 int _obj;
371 K3L_EVENT * _event;
372 };
373
374 template < typename R, int S >
375 struct GenericFifo
376 {
377 typedef R RequestType;
378 typedef SimpleNonBlockLock<25,100> LockType;
379
GenericFifoGenericFifo380 GenericFifo(int device) :
381 _device(device),
382 _shutdown(false),
383 _buffer(S),
384 _mutex(Globals::module_pool),
385 _cond(Globals::module_pool)
386 {};
387
388 int _device;
389 bool _shutdown;
390 Ringbuffer < RequestType > _buffer;
391 LockType _mutex; /* to sync write acess to event list */
392 SavedCondition _cond;
393 Thread *_thread;
394
395 };
396
397 typedef GenericFifo < CommandRequest, 250 > CommandFifo;
398 typedef GenericFifo < EventRequest, 500 > EventFifo;
399
400 /* Used inside KhompPvt to represent an command handler */
401 struct ChanCommandHandler: NEW_REFCOUNTER(ChanCommandHandler)
402 {
403 typedef int (HandlerType)(void *);
404
ChanCommandHandlerChanCommandHandler405 ChanCommandHandler(int device, HandlerType * handler)
406 {
407 _fifo = new CommandFifo(device);
408 /* device event handler */
409 _fifo->_thread = new Thread(handler, (void *)this, Globals::module_pool);
410 if(_fifo->_thread->start())
411 {
412 DBG(FUNC,"Device command handler started");
413 }
414 else
415 {
416 LOG(ERROR, "Device command handler error");
417 }
418 }
419
ChanCommandHandlerChanCommandHandler420 ChanCommandHandler(const ChanCommandHandler & cmd)
421 : INC_REFCOUNTER(cmd, ChanCommandHandler),
422 _fifo(cmd._fifo)
423 {};
424
425 void unreference();
426
fifoChanCommandHandler427 CommandFifo * fifo()
428 {
429 return _fifo;
430 }
431
signalChanCommandHandler432 void signal()
433 {
434 _fifo->_cond.signal();
435 };
436
437 bool writeNoSignal(const CommandRequest &);
438 bool write(const CommandRequest &);
439
440 protected:
441 CommandFifo * _fifo;
442 };
443
444 /* Used inside KhompPvt to represent an event handler */
445 struct ChanEventHandler: NEW_REFCOUNTER(ChanEventHandler)
446 {
447 typedef int (HandlerType)(void *);
448
ChanEventHandlerChanEventHandler449 ChanEventHandler(int device, HandlerType * handler)
450 {
451 _fifo = new EventFifo(device);
452 /* device event handler */
453 _fifo->_thread = new Thread(handler, (void *)this, Globals::module_pool);
454 if(_fifo->_thread->start())
455 {
456 DBG(FUNC,"Device event handler started");
457 }
458 else
459 {
460 LOG(ERROR, "Device event handler error");
461 }
462 }
463
ChanEventHandlerChanEventHandler464 ChanEventHandler(const ChanEventHandler & evt)
465 : INC_REFCOUNTER(evt, ChanEventHandler),
466 _fifo(evt._fifo)
467 {};
468
469 void unreference();
470
fifoChanEventHandler471 EventFifo * fifo()
472 {
473 return _fifo;
474 }
475
signalChanEventHandler476 void signal()
477 {
478 _fifo->_cond.signal();
479 };
480
481 bool provide(const EventRequest &);
482 bool writeNoSignal(const EventRequest &);
483 bool write(const EventRequest &);
484
485 protected:
486 EventFifo * _fifo;
487 };
488
489
490 /******************************************************************************/
491 /****************************** Internal **************************************/
492 struct RingbackDefs
493 {
494 enum
495 {
496 RB_SEND_DEFAULT = -1,
497 RB_SEND_NOTHING = -2,
498 };
499
500 typedef enum
501 {
502 RBST_SUCCESS,
503 RBST_UNSUPPORTED,
504 RBST_FAILURE,
505 }
506 RingbackStType;
507 };
508
509 /******************************************************************************/
510 /******************************* Others ***************************************/
checkTrueString(const char * str)511 static bool checkTrueString(const char * str)
512 {
513 if (str && *str)
514 {
515 if (!SAFE_strcasecmp(str, "yes") || !SAFE_strcasecmp(str, "true") ||
516 !SAFE_strcasecmp(str, "enabled") || !SAFE_strcasecmp(str, "sim"))
517 {
518 return true;
519 }
520 }
521
522 return false;
523 }
524
checkFalseString(const char * str)525 static bool checkFalseString(const char * str)
526 {
527 if (str && *str)
528 {
529 if (!SAFE_strcasecmp(str, "no") || !SAFE_strcasecmp(str, "false") ||
530 !SAFE_strcasecmp(str, "disabled") || !SAFE_strcasecmp(str, "não"))
531 {
532 return true;
533 }
534 }
535
536 return false;
537 }
538
getTriStateValue(const char * str)539 static TriState getTriStateValue(const char * str)
540 {
541 if (str)
542 {
543 /**/ if (checkTrueString(str)) return T_TRUE;
544 else if (checkFalseString(str)) return T_FALSE;
545 else /***********************************/ return T_UNKNOWN;
546 }
547
548 return T_UNKNOWN;
549 }
550
551 const char * answerInfoToString(int answer_info);
552
replaceTemplate(std::string & haystack,const std::string & needed,int value)553 static bool replaceTemplate(std::string & haystack, const std::string & needed, int value)
554 {
555 Regex::Expression e(std::string(needed).c_str());
556 Regex::Match r(haystack,e);
557
558 if(!r.matched()) return false;
559
560 int len;
561 std::string fmt;
562 std::string tmp;
563
564 // if needed isn't "SSSS" the length of needed will give string format
565 // if needed is "SSSS" the length of value will give string format
566 std::string ssss("SSSS");
567
568 if (ssss != needed)
569 {
570 len = needed.size();
571 fmt = STG(FMT("%%0%dd") % len);
572 tmp = STG(FMT(fmt) % value);
573 }
574 else
575 {
576 len = (STG(FMT("%d") % value)).size();
577 fmt = STG(FMT("%%%dd") % len);
578 tmp = STG(FMT(fmt) % value);
579 }
580
581 haystack = r.replace(STG(FMT(fmt) % value));
582
583 DBG(FUNC,FMT("haystack: %s") % haystack);
584 return true;
585 }
586
587
timeToString(time_t time_value)588 static std::string timeToString (time_t time_value)
589 {
590 int horas = (int)time_value / 3600;
591
592 if (horas > 0)
593 time_value -= horas * 3600;
594
595 int minutos = (int)time_value / 60;
596
597 if (minutos > 0)
598 time_value -= minutos * 60;
599
600 return STG(FMT("%02d:%02d:%02d") % horas % minutos % (int)time_value);
601 }
602 /******************************************************************************/
603 /******************************* Match functions ******************************/
604 struct MatchExtension
605 {
606 typedef std::vector<std::string> ContextListType;
607 typedef std::vector<std::string> ExtenListType;
608
609 typedef enum
610 {
611 MATCH_NONE,
612 MATCH_EXACT,
613 MATCH_MORE
614 }
615 MatchType;
616
617 static bool canMatch(std::string & context, std::string & exten,
618 std::string & caller_id, bool match_more = false);
619
620 static MatchType matchExtension(std::string &, std::string &,
621 std::string &, bool match_only = false);
622
623 static MatchType findExtension(std::string &, std::string &,
624 ContextListType &, std::string &, std::string &,
625 bool default_ctx = true, bool default_ext = true);
626
627 };
628 /******************************************************************************/
629 /************************** Thread helper functions ***************************/
630 typedef int (HandlerType)(void *);
threadCreate(HandlerType * handler,void * arg)631 static Thread * threadCreate(HandlerType * handler,void * arg)
632 {
633 Thread *t = new Thread(handler, (void *) arg, Globals::module_pool);
634 return t;
635 }
636
637 /******************************************************************************/
638 /******************************** Kommuter ************************************/
639 struct Kommuter
640 {
KommuterKommuter641 Kommuter() :
642 _kommuter_count(-1),
643 _kwtd_timer_on(false)
644 {}
645
startKommuter646 bool start()
647 {
648 /* Checks for kommuter */
649 try
650 {
651 Globals::k3lapi.command(-1,-1,CM_WATCHDOG_COUNT);
652 }
653 catch(K3LAPI::failed_command & e)
654 {
655 LOG(WARNING , "libkwd.so used by Kommuter devices is not available.");
656 return false;
657 }
658
659 return true;
660 }
661
662 bool stop();
663
664 bool initialize(K3L_EVENT *e);
665
666 /* Index of the WatchDog timer */
667 TimerTraits::Index _kwtd_timer_index;
668 int _kommuter_count;
669 bool _kwtd_timer_on;
670
671 /* Timer to control our dog (totó) */
672 static void wtdKickTimer(void *);
673
674 };
675
676 /******************************************************************************/
677 /******************************* Statistics ***********************************/
678 struct Statistics
679 {
680 typedef enum
681 {
682 DETAILED = 0,
683 ROW
684 }
685 Type;
686
getDetailedStatistics687 virtual std::string getDetailed() { return ""; }
clearStatistics688 virtual void clear() {}
689 };
690 /******************************************************************************/
691 /****************************** ESL - Events **********************************/
692
693 struct ESL
694 {
695
696 typedef std::vector <std::string> VectorEvents;
697
698 ESL(std::string type);
699
700 ~ESL();
701
createESL702 switch_event_t * create(const std::string type)
703 {
704 switch_event_t *event;
705
706 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, type.c_str()) != SWITCH_STATUS_SUCCESS)
707 {
708 return NULL;
709 }
710
711 return event;
712 }
713
createESL714 switch_event_t * create()
715 {
716 return create(_type);
717 }
718
addESL719 bool add(switch_event_t *event, const std::string key,
720 const std::string value) const
721 {
722 if(!event) return false;
723
724 switch_status_t res = switch_event_add_header_string(event,
725 SWITCH_STACK_BOTTOM,
726 key.c_str(),
727 value.c_str());
728
729 return (res == SWITCH_STATUS_SUCCESS ? true : false);
730 }
731
addESL732 bool add(switch_event_t *event, K3LAPIBase::GenericTarget & target)
733 {
734 bool ok = add(event, "Device", STR(FMT("%d") % target.device));
735
736 if(!ok)
737 return ok;
738
739 std::string type;
740
741 switch(target.type)
742 {
743 case K3LAPIBase::GenericTarget::CHANNEL:
744 type = "Channel";
745 break;
746 case K3LAPIBase::GenericTarget::MIXER:
747 type = "Mixer";
748 break;
749 case K3LAPIBase::GenericTarget::LINK:
750 type = "Link";
751 break;
752 default:
753 type = "Other";
754 break;
755 }
756
757 return add(event, type, STR(FMT("%d") % target.object));
758 }
759
fireESL760 bool fire(switch_event_t **event) const
761 {
762 if(!event || !*event) return false;
763
764 switch_status_t res = switch_event_fire(event);
765
766 *event = NULL;
767
768 return (res == SWITCH_STATUS_SUCCESS ? true : false);
769 }
770
771 static bool registerEvents();
772
773 static bool unregisterEvents();
774
775 protected:
776 const std::string _type;
777 static VectorEvents * _events;
778 };
779
780 /******************************************************************************/
781 /******************************************************************************/
782
783 #endif /* _UTILS_H_ */
784