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