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 #include "applications.h"
45 #include "lock.h"
46 
47 
adjustForFax()48 bool Fax::adjustForFax()
49 {
50     /* Don't worry, let the man work */
51     DBG(FUNC, PVT_FMT(_pvt->target(),"Channel is now being adjusted for fax!"));
52 
53     try
54     {
55         ScopedPvtLock lock(_pvt);
56 
57         _pvt->echoCancellation(false);
58         _pvt->dtmfSuppression(false);
59         _pvt->autoGainControl(false);
60 
61         _pvt->call()->_input_volume = 0;
62         _pvt->setVolume("input" , 0);
63         _pvt->call()->_output_volume = 0;
64         _pvt->setVolume("output", 0);
65     }
66     catch (ScopedLockFailed & err)
67     {
68         LOG(ERROR, PVT_FMT(_pvt->target(), "r (unable to lock: %s!)") %  err._msg.c_str());
69         return false;
70     }
71 
72     return true;
73 }
74 
sendFax(switch_core_session_t * session,const char * data)75 bool Fax::sendFax(switch_core_session_t * session, const char *data)
76 {
77     DBG(FUNC, PVT_FMT(_pvt->target(), "c (%s)") % data);
78 
79     try
80     {
81         switch_channel_t *channel = _pvt->getFSChannel(session);
82 
83         switch_channel_set_variable(channel, "KFaxSent", "no");
84         switch_channel_set_variable(channel, "KFaxResult", "none");
85 
86         std::string           fax_string((const char *)data);
87         Strings::vector_type  fax_args;
88         Strings::vector_type  fax_files;
89 
90         Strings::tokenize(fax_string, fax_args, "|,");
91 
92         if(fax_args.size() != 1 && fax_args.size() != 2)
93         {
94             LOG(ERROR, PVT_FMT(_pvt->target(), "r (invalid string '%s': wrong number of separators.)") % fax_string);
95             return false;
96         }
97 
98         Strings::tokenize(fax_args[0], fax_files, ":");
99 
100         if(fax_files.size() <= 0)
101         {
102             LOG(ERROR, PVT_FMT(_pvt->target(), "r (invalid string '%s': wrong number of separators.)") % fax_string);
103             return false;
104         }
105 
106         ScopedPvtLock lock(_pvt);
107 
108         std::string id;
109 
110         if(fax_args.size() == 2)
111         {
112             id = fax_args[1];
113         }
114         else if(!_pvt->call()->_orig_addr.empty())
115         {
116             id = _pvt->call()->_orig_addr;
117         }
118 
119         const char * orig_addr = id.empty() ? NULL : id.c_str();
120 
121         int timeout = 5;
122 
123         if(!_pvt->call()->_flags.check(Kflags::REALLY_CONNECTED) && !_pvt->loopWhileFlagTimed(Kflags::REALLY_CONNECTED, timeout, false))
124             return false;
125 
126         if(!startFaxTX(orig_addr))
127         {
128             LOG(ERROR, PVT_FMT(_pvt->target(), "r (unable to start send fax)"));
129             return false;
130         }
131 
132         for(unsigned int i = 0; i < fax_files.size() ; ++i)
133         {
134             if (!addFaxFile(fax_files[i].c_str(), (i == fax_files.size()-1)? true : false))
135             {
136                 DBG(FUNC, D("unable to add fax file='%s'")
137                         % fax_files[i].c_str());
138             }
139         }
140 
141         _fax_cond.reset();
142 
143         lock.unlock();
144 
145         _fax_cond.wait();
146 
147         switch_channel_set_variable(channel, "KFaxSent", ((_fax_result == kfaxrEndOfTransmission) ? "yes" : "no"));
148         switch_channel_set_variable(channel, "KFaxResult", (Verbose::faxResult((KFaxResult)_fax_result).c_str()));
149 
150     }
151     catch (ScopedLockFailed & err)
152     {
153         LOG(ERROR, PVT_FMT(_pvt->target(), "r (unable to lock: %s!)") %  err._msg.c_str());
154         return false;
155     }
156     catch(Board::KhompPvt::InvalidSwitchChannel & err)
157     {
158         LOG(ERROR, PVT_FMT(_pvt->target(), "r (%s)") % err._msg.c_str());
159         return false;
160     }
161 
162     DBG(FUNC, PVT_FMT(_pvt->target(), "r"));
163     return true;
164 }
165 
166 
receiveFax(switch_core_session_t * session,const char * data)167 bool Fax::receiveFax(switch_core_session_t * session, const char *data)
168 {
169     DBG(FUNC, PVT_FMT(_pvt->target(), "c (%s)") % data);
170 
171     try
172     {
173         switch_channel_t *channel = _pvt->getFSChannel(session);
174 
175         switch_channel_set_variable(channel, "KFaxReceived", "no");
176         switch_channel_set_variable(channel, "KFaxResult", "none");
177 
178         std::string          fax_string((const char *)data);
179         Strings::vector_type fax_args;
180 
181         Strings::tokenize(fax_string, fax_args, "|,");
182 
183         if(fax_args.size() != 1 && fax_args.size() != 2)
184         {
185             LOG(ERROR, PVT_FMT(_pvt->target(), "r (invalid string '%s': wrong number of separators.)") % fax_string);
186             return false;
187         }
188 
189         ScopedPvtLock lock(_pvt);
190 
191         std::string id;
192 
193         if(fax_args.size() == 2)
194         {
195             id = fax_args[1];
196         }
197         else if(!_pvt->call()->_dest_addr.empty())
198         {
199             id = _pvt->call()->_dest_addr;
200         }
201 
202         const char * orig_addr = id.empty() ? NULL : id.c_str();
203 
204         int timeout = 5;
205 
206         if(!_pvt->call()->_flags.check(Kflags::REALLY_CONNECTED) && !_pvt->loopWhileFlagTimed(Kflags::REALLY_CONNECTED, timeout, false))
207             return false;
208 
209         if(!startFaxRX(fax_args[0].c_str(), orig_addr))
210         {
211             LOG(ERROR, PVT_FMT(_pvt->target(), "r (unable to start receive fax)"));
212             return false;
213         }
214 
215         _fax_cond.reset();
216 
217         lock.unlock();
218 
219         _fax_cond.wait();
220 
221         switch_channel_set_variable(channel, "KFaxReceived", ((_fax_result == kfaxrEndOfReception) ? "yes" : "no"));
222         switch_channel_set_variable(channel, "KFaxResult", (Verbose::faxResult((KFaxResult)_fax_result).c_str()));
223 
224     }
225     catch (ScopedLockFailed & err)
226     {
227         LOG(ERROR, PVT_FMT(_pvt->target(), "r (unable to lock: %s!)") %  err._msg.c_str());
228         return false;
229     }
230     catch(Board::KhompPvt::InvalidSwitchChannel & err)
231     {
232         LOG(ERROR, PVT_FMT(_pvt->target(), "r (%s)") % err._msg.c_str());
233         return false;
234     }
235 
236     DBG(FUNC, PVT_FMT(_pvt->target(), "r"));
237 
238     return true;
239 }
240 
onFaxChannelRelease(K3L_EVENT * e)241 bool Fax::onFaxChannelRelease(K3L_EVENT *e)
242 {
243     DBG(FUNC, PVT_FMT(_pvt->target(), "c"));
244 
245     try
246     {
247         ScopedPvtLock lock(_pvt);
248 
249         if (_pvt->call()->_flags.check(Kflags::FAX_SENDING))
250         {
251             _pvt->call()->_flags.clear(Kflags::FAX_SENDING);
252 
253             /* make audio come back.. */
254             _pvt->startStream(false);
255             _pvt->startListen();
256         }
257         else if (_pvt->call()->_flags.check(Kflags::FAX_RECEIVING))
258         {
259             _pvt->call()->_flags.clear(Kflags::FAX_RECEIVING);
260 
261             /* make audio come back.. */
262             _pvt->startStream(false);
263             _pvt->startListen();
264         }
265 
266         _fax_result = (KFaxResult)e->AddInfo;
267 
268         _fax_cond.signal();
269 
270     }
271     catch (ScopedLockFailed & err)
272     {
273         LOG(ERROR, PVT_FMT(_pvt->target(), "r (unable to lock %s!)") % err._msg.c_str());
274         return false;
275     };
276 
277     DBG(FUNC, PVT_FMT(_pvt->target(), "r"));
278 
279     return true;
280 }
281 
startFaxTX(const char * orig_addr)282 bool Fax::startFaxTX(const char * orig_addr)
283 {
284     /* no audio after this point, so stop streams! */
285     _pvt->stopStream(false);
286     _pvt->stopListen();
287 
288     std::string id;
289 
290     if(orig_addr)
291         id = STG(FMT("orig_addr=\"%s\"") % orig_addr);
292 
293     const char * param = id.empty() ? NULL : id.c_str();
294 
295 
296     if (!_pvt->command(KHOMP_LOG, CM_START_FAX_TX, param))
297     {
298         _pvt->startStream(false);
299         _pvt->startListen();
300         return false;
301     }
302 
303     _pvt->call()->_flags.set(Kflags::FAX_SENDING);
304 
305     return true;
306 
307 }
308 
stopFaxTX(void)309 bool Fax::stopFaxTX(void)
310 {
311     /* EV_FAX_CHANNEL_FREE , EV_FAX_FILE_FAIL */
312     if (!_pvt->command(KHOMP_LOG, CM_STOP_FAX_TX))
313         return false;
314 
315     _pvt->call()->_flags.clear(Kflags::FAX_SENDING);
316 
317     /* make audio come back.. */
318     _pvt->startStream(false);
319     _pvt->startListen();
320 
321     return true;
322 }
323 
324 
325 
startFaxRX(const char * filename,const char * orig_addr)326 bool Fax::startFaxRX(const char * filename, const char * orig_addr)
327 {
328     if(!filename)
329         return false;
330 
331     std::string param = STG(FMT("filename=\"%s\"") % filename);
332 
333     if(orig_addr)
334         param += STG(FMT(" orig_addr=\"%s\"") % orig_addr);
335 
336     /* no audio after this point, so stop streams! */
337     _pvt->stopStream(false);
338     _pvt->stopListen();
339 
340     if (!_pvt->command(KHOMP_LOG, CM_START_FAX_RX, param.c_str()))
341     {
342         _pvt->startStream(false);
343         _pvt->startListen();
344         return false;
345     }
346 
347     _pvt->call()->_flags.set(Kflags::FAX_RECEIVING);
348 
349     return true;
350 }
351 
stopFaxRX()352 bool Fax::stopFaxRX()
353 {
354     /* Events: EV_FAX_CHANNEL_FREE */
355     if (!_pvt->command(KHOMP_LOG, CM_STOP_FAX_RX))
356         return false;
357 
358     _pvt->call()->_flags.clear(Kflags::FAX_RECEIVING);
359 
360     /* make audio come back.. */
361     _pvt->startStream(false);
362     _pvt->startListen();
363 
364     return true;
365 }
366 
addFaxFile(const char * filename,bool last)367 bool Fax::addFaxFile(const char * filename, bool last)
368 {
369     /* Events: EV_FAX_FILE_SENT , EV_FAX_FILE_FAIL , EV_FAX_TX_TIMEOUT */
370     if(!filename)
371         return false;
372 
373     std::string params = STG(FMT("filename=\"%s\" last=\"%s\"") % filename
374             % (last ? "true": "false"));
375 
376     if (!_pvt->command(KHOMP_LOG, CM_ADD_FAX_FILE, params.c_str()))
377         return false;
378 
379     return true;
380 }
381 
382 /******************************************************************************/
383 SMS::_SMSEvent SMS::SMSEvent;
384 
justAlloc(unsigned int count)385 bool SMS::justAlloc(unsigned int count)
386 {
387     /* incoming contexts */
388     MatchExtension::ContextListType contexts;
389 
390     contexts.push_back(Opt::_options._context_gsm_sms());
391 
392     /* temporary variables */
393     std::string context;
394     std::string exten("s");
395 
396     const K3L_DEVICE_CONFIG & dev_cfg = Globals::k3lapi.device_config(_pvt->_target);
397 
398     for (MatchExtension::ContextListType::iterator i = contexts.begin(); i != contexts.end(); i++)
399     {
400         replaceTemplate((*i), "DD", _pvt->_target.device);
401         replaceTemplate((*i), "CC", _pvt->_target.object);
402         replaceTemplate((*i), "SSSS", atoi(dev_cfg.SerialNumber));
403     }
404 
405     //switch(_pvt->findExtension(exten, context, contexts, _got_sms._type, _got_sms._from, false, true))
406     switch(MatchExtension::findExtension(exten, context, contexts, exten, _got_sms._from, false, true))
407     {
408     case MatchExtension::MATCH_NONE:
409         if( _got_sms._type != "broadcast")
410         {
411             LOG(WARNING, PVT_FMT(_pvt->target(), "unable to find context/exten for incoming SMS (s/%s), processing disabled for this channel.")
412                     % (contexts.size() >= 1 ? contexts[0] : "default"));
413 
414         }
415 
416         return false;
417 
418     default:
419         DBG(FUNC, PVT_FMT(_pvt->target(), "our: context '%s', exten '%s'") % context % exten);
420         break;
421     }
422 
423     for(unsigned int c = 0; c < count; c++)
424     {
425 
426 #if SWITCH_LESS_THAN(1,0,6)
427         switch_core_session_t *session = switch_core_session_request(Globals::khomp_sms_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, NULL);
428 #else
429         switch_core_session_t *session = switch_core_session_request(Globals::khomp_sms_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, SOF_NONE, NULL);
430 #endif
431 
432         if(!session)
433         {
434             LOG(ERROR, PVT_FMT(_pvt->target(), "Initilization Error, session not created!"));
435             return false;
436         }
437 
438         switch_core_session_add_stream(session, NULL);
439 
440         switch_core_session_set_private(session, _pvt);
441 
442         switch_caller_profile_t *caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
443                 "Khomp_SMS",                       //username
444                 Opt::_options._dialplan().c_str(), //dialplan
445                 NULL,                              //caller_id_name
446                 _got_sms._from.c_str(),            //caller_id_number
447                 NULL,                              //network_addr
448                 _got_sms._from.c_str(),            //ani
449                 NULL,                              //aniii
450                 NULL,                              //rdnis
451                 (char *) "mod_khomp",              //source
452                 context.c_str(),                   //context
453                 exten.c_str());                    //destination_number
454 
455         if(!caller_profile)
456         {
457             _pvt->destroy(session);
458             LOG(ERROR, PVT_FMT(_pvt->target(), "r (Cannot create caller profile)"));
459             return false;
460         }
461 
462         switch_channel_t *channel = switch_core_session_get_channel(session);
463 
464         if(!channel)
465         {
466             _pvt->destroy(session);
467             LOG(ERROR, PVT_FMT(_pvt->target(), "r (Cannot get channel)"));
468             return false;
469         }
470 
471         std::string name = STG(FMT("Khomp_SMS/%d/%d")
472                 % _pvt->target().device
473                 % _pvt->target().object);
474 
475         switch_channel_set_name(channel, name.c_str());
476         switch_channel_set_caller_profile(channel, caller_profile);
477 
478         //DBG(FUNC, PVT_FMT(_pvt->target(), "Connect inbound SMS channel %s") % name.c_str());
479 
480         switch_channel_set_state(channel, CS_INIT);
481 
482 
483         _owners.push_front(session);
484     }
485 
486     return true;
487 }
488 
justStart()489 bool SMS::justStart()
490 {
491     OwnersList::iterator i = _owners.begin();
492 
493     if(i == _owners.end())
494     {
495         LOG(ERROR, PVT_FMT(_pvt->target(), "Cannot get session"));
496         return false;
497     }
498 
499     switch_core_session_t *session = (*i);
500 
501     _owners.pop_front();
502 
503     if(!session)
504     {
505         LOG(ERROR, PVT_FMT(_pvt->target(), "Cannot get session"));
506         return false;
507     }
508 
509     switch_channel_t *channel = switch_core_session_get_channel(session);
510 
511     if(!channel)
512     {
513         _pvt->destroy(session);
514         LOG(ERROR, PVT_FMT(_pvt->target(), "r (Cannot get channel)"));
515         return false;
516     }
517 
518     switch_channel_set_variable(channel, "KSmsType", _got_sms._type.c_str());
519 
520     if (_got_sms._type == "message" || _got_sms._type == "confirm")
521     {
522         switch_channel_set_variable(channel, "KSmsFrom", _got_sms._from.c_str());
523         switch_channel_set_variable(channel, "KSmsDate", _got_sms._date.c_str());
524     }
525 
526     if(_got_sms._type == "confirm")
527     {
528         switch_channel_set_variable(channel, "KSmsDelivery", _got_sms._sc_date.c_str());
529         switch_channel_set_variable(channel, "KSmsStatus", _got_sms._status.c_str());
530     }
531     else
532     {
533         if(_got_sms._type == "broadcast")
534         {
535             switch_channel_set_variable(channel, "KSmsSerial", _got_sms._serial.c_str());
536             switch_channel_set_variable(channel, "KSmsPage", _got_sms._page.c_str());
537             switch_channel_set_variable(channel, "KSmsPages", _got_sms._pages.c_str());
538         }
539         switch_channel_set_variable(channel, "KSmsSize", _got_sms._size.c_str());
540         switch_channel_set_variable(channel, "KSmsMode", _got_sms._coding.c_str());
541         switch_channel_set_variable(channel, "KSmsBody", _got_sms._body.c_str());
542     }
543 
544 
545     if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS)
546     {
547         _pvt->destroy(session);
548         LOG(ERROR, PVT_FMT(_pvt->target(), "Error spawning thread"));
549         return false;
550     }
551 
552     return true;
553 }
554 
sendSMS(switch_core_session_t * session,const char * data)555 bool SMS::sendSMS(switch_core_session_t * session, const char *data)
556 {
557     DBG(FUNC, PVT_FMT(_pvt->target(), "(SMS) c"));
558 
559     volatile bool finished = false;
560     volatile KGsmCallCause result = kgccNone;
561 
562     try
563     {
564         //ScopedAllocLock alloc_lock;
565 
566         if(!_can_send)
567         {
568             LOG(ERROR, PVT_FMT(_pvt->target(), "(SMS) r (cannot send SMS messages, modem NOT initialized!)"));
569             return false;
570         }
571 
572         std::string           sms_string((const char *)data);
573         Strings::vector_type  sms_args;
574 
575         Strings::tokenize(sms_string, sms_args, "/|,", 3);
576 
577         if (sms_args.size() != 3)
578         {
579             LOG(ERROR, PVT_FMT(_pvt->target(), "(SMS) r (invalid dial string '%s': wrong number of separators.)") % sms_string);
580             return false;
581         }
582 
583         std::string dest(sms_args[1]);
584 
585         bool conf = false;
586 
587         if (dest[0] == '!')
588         {
589             dest.erase(0,1);
590             conf = true;
591         }
592 
593         if (dest[dest.size()-1] == '!')
594         {
595             dest.erase(dest.size()-1,1);
596             conf = true;
597         }
598 
599         // get options/values
600 
601         _send_sms._dest = dest;
602         _send_sms._conf = conf;
603         _send_sms._body = sms_args[2];
604 
605         Request request_sms(_send_sms, &finished, &result);
606 
607         _mutex.lock();
608         bool status = _buffer.provide(request_sms);
609         _mutex.unlock();
610 
611         _pvt->_mutex.unlock();
612 
613         if(status)
614             _cond.signal();
615 
616         while (!finished)
617         {
618             usleep(200000);
619         }
620 
621         _pvt->_mutex.lock();
622 
623         switch_channel_t *channel = _pvt->getFSChannel(session);
624 
625         switch_channel_set_variable(channel, "KSmsDelivered", ((KGsmSmsCause)result == ((KGsmSmsCause)0) ? "yes" : "no"));
626         switch_channel_set_variable(channel, "KSmsErrorCode", STG(FMT("%d") % result).c_str());
627         switch_channel_set_variable(channel, "KSmsErrorName", ((KGsmSmsCause)result == ((KGsmSmsCause)0) ? "None" : Verbose::gsmSmsCause((KGsmSmsCause)result).c_str()));
628 
629     }
630     catch(ScopedLockFailed & err)
631     {
632         LOG(ERROR, PVT_FMT(_pvt->target(), "(SMS) r (unable to global alloc lock)"));
633         return false;
634     }
635     catch(Board::KhompPvt::InvalidSwitchChannel & err)
636     {
637         LOG(ERROR, PVT_FMT(_pvt->target(), "(SMS) %s") % err._msg.c_str());
638         //return false;
639     }
640 
641     bool ret = ((KGsmSmsCause)result == ((KGsmSmsCause)0));
642 
643     DBG(FUNC, PVT_FMT(_pvt->target(), "(SMS) r (%s)") % (ret ? "true" : "false"));
644 
645     //return (KGsmSmsCause)result;
646     return ret;
647 }
648 
onNewSMS(K3L_EVENT * e)649 bool SMS::onNewSMS(K3L_EVENT *e)
650 {
651     DBG(FUNC, PVT_FMT(_pvt->target(), "(SMS) c"));
652 
653     bool ret = true;
654 
655     try
656     {
657         ScopedPvtLock lock(_pvt);
658 
659         if(!_can_receive)
660         {
661             DBG(FUNC, PVT_FMT(_pvt->target(), "(SMS) received new SMS message(s), but receiving is disabled. keeping the message(s) at the SIM card."));
662             ret = false;
663         }
664         else if(!justAlloc(e->AddInfo))
665         {
666             LOG(WARNING, PVT_FMT(_pvt->target(), "(SMS) unable to allocate channel for new SMS message(s). disabling processing to prevent messages from being lost."));
667             _can_receive = false;
668             ret = false;
669         }
670         else
671         {
672 
673             DBG(FUNC, PVT_FMT(_pvt->target(), "downloading %d SMS message(s) on the SIM card.") % e->AddInfo);
674 
675             _pvt->command(KHOMP_LOG, CM_GET_SMS);
676         }
677 
678     }
679     catch (ScopedLockFailed & err)
680     {
681         LOG(ERROR, PVT_FMT(_pvt->target(), "(SMS) r (unable to lock %s!)") % err._msg.c_str() );
682         return false;
683     }
684 
685     DBG(FUNC, PVT_FMT(_pvt->target(), "(SMS) r"));
686 
687     return ret;
688 }
689 
onSMSInfo(K3L_EVENT * e)690 bool SMS::onSMSInfo(K3L_EVENT *e)
691 {
692     DBG(FUNC, PVT_FMT(_pvt->target(), "(SMS) c"));
693 
694     try
695     {
696         ScopedPvtLock lock(_pvt);
697 
698         Globals::k3lapi.get_param(e, "sms_type",    _got_sms._type);
699         Globals::k3lapi.get_param(e, "sms_from",    _got_sms._from);
700         Globals::k3lapi.get_param(e, "sms_date",    _got_sms._date);
701         Globals::k3lapi.get_param(e, "sms_size",    _got_sms._size);
702         Globals::k3lapi.get_param(e, "sms_coding",  _got_sms._coding);
703         Globals::k3lapi.get_param(e, "sms_serial",  _got_sms._serial);
704         Globals::k3lapi.get_param(e, "sms_id",      _got_sms._id);
705         Globals::k3lapi.get_param(e, "sms_page",    _got_sms._page);
706         Globals::k3lapi.get_param(e, "sms_pages",   _got_sms._pages);
707         Globals::k3lapi.get_param(e, "sms_sc_date", _got_sms._sc_date);
708         Globals::k3lapi.get_param(e, "sms_status",  _got_sms._status);
709 
710         //DBG(FUNC, PVT_FMT(_pvt->target(), "(SMS) type=%s from=%s date=%s size=%s coding=%s serial=%s id=%s page=%s pages=%s sc_date=%s status=%s") % _got_sms._type % _got_sms._from % _got_sms._date % _got_sms._size % _got_sms._coding % _got_sms._serial % _got_sms._id % _got_sms._page % _got_sms._pages % _got_sms._sc_date % _got_sms._status);
711 
712         if (_owners.empty() && !justAlloc(1) && (_got_sms._type.compare("broadcast") != 0))
713         {
714             // this error is fatal
715             LOG(ERROR, PVT_FMT(_pvt->target(), "unable to allocate channel, new SMS message from %s will not be sent to dialplan!") % _got_sms._from);
716             return false;
717         }
718     }
719     catch (ScopedLockFailed & err)
720     {
721         LOG(ERROR, PVT_FMT(_pvt->target(), "(SMS) r (unable to lock %s!)") % err._msg.c_str() );
722         return false;
723     }
724 
725     DBG(FUNC, PVT_FMT(_pvt->target(), "(SMS) r"));
726 
727     return true;
728 }
729 
onSMSData(K3L_EVENT * e)730 bool SMS::onSMSData(K3L_EVENT *e)
731 {
732     DBG(FUNC, PVT_FMT(_pvt->target(), "(SMS) c"));
733 
734     try
735     {
736         ScopedPvtLock lock(_pvt);
737 
738         if (_owners.empty())
739         {
740             if(_got_sms._type != "broadcast")
741             {
742                 LOG(WARNING, PVT_FMT(_pvt->target(), "unable to allocate channel for new SMS message(s). disabling processing to prevent messages from being lost."));
743                 _can_receive = false;
744             }
745         }
746         else
747         {
748             _got_sms._body = (const char *)(e->Params ? e->Params : "");
749 
750             SMSEvent(_pvt, _got_sms);
751 
752             if(!justStart())
753             {
754                 if(_got_sms._type != "broadcast")
755                 {
756                     LOG(ERROR, PVT_FMT(_pvt->target(), "unable to receive SMS from '%s', something wrong!") % _got_sms._from);
757                     LOG(ERROR, PVT_FMT(_pvt->target(), "disabling SMS processing to prevent messages from being lost."));
758 
759                     _can_receive = false;
760                 }
761             }
762         }
763 
764         if(_can_receive)
765         {
766             /* stats update! */
767             if(_got_sms._type == "message")
768             {
769                 statistics<SMSStatistics>()->incrementIncoming();
770             }
771             else if(_got_sms._type == "confirm")
772             {
773                 statistics<SMSStatistics>()->incrementConfirm();
774             }
775             else
776             {
777                 statistics<SMSStatistics>()->incrementBroadcast();
778             }
779         }
780 
781         /* reset data stuff */
782         _got_sms.clear();
783     }
784     catch (ScopedLockFailed & err)
785     {
786         LOG(ERROR, PVT_FMT(_pvt->target(), "(SMS) r (unable to lock %s!)") % err._msg.c_str() );
787         return false;
788     }
789 
790     DBG(FUNC, PVT_FMT(_pvt->target(), "(SMS) r"));
791     return true;
792 }
793 
onSMSSendResult(K3L_EVENT * e)794 bool SMS::onSMSSendResult(K3L_EVENT *e)
795 {
796     DBG(FUNC, PVT_FMT(_pvt->target(), "(SMS) c"));
797 
798     try
799     {
800         ScopedPvtLock lock(_pvt);
801 
802         _result = (KGsmCallCause)e->AddInfo;
803         _pvt->call()->_flags.clear(Kflags::SMS_DOING_UPLOAD);
804 
805     }
806     catch (ScopedLockFailed & err)
807     {
808         LOG(ERROR, PVT_FMT(_pvt->target(), "(SMS) r (unable to lock %s!)") % err._msg.c_str() );
809         return false;
810     }
811 
812     DBG(FUNC, PVT_FMT(_pvt->target(), "(SMS) r"));
813 
814     return true;
815 }
816 
smsThread(void * sms_ptr)817 int SMS::smsThread(void * sms_ptr)
818 {
819     SMS * sms = static_cast < SMS * > (sms_ptr);
820 
821     Board::KhompPvt * pvt = static_cast < Board::KhompPvt * > (sms->_pvt);
822 
823     DBG(THRD, PVT_FMT(pvt->target(), "c"));
824 
825     bool loop = true;
826 
827     while(loop)
828     {
829         if(sms->_cond.wait(1000))
830         {
831             if(sms->_shutdown)
832                 return 0;
833         }
834 
835         try
836         {
837             ScopedPvtLock lock(pvt);
838 
839             K3L_CHANNEL_STATUS status;
840 
841             KLibraryStatus ret = (KLibraryStatus) k3lGetDeviceStatus(
842                     pvt->_target.device,
843                     pvt->_target.object + ksoChannel,
844                     &status,
845                     sizeof(status));
846 
847             if (ret == ksSuccess)
848             {
849                 switch (status.AddInfo)
850                 {
851                     case kgsmModemError:
852                     case kgsmSIMCardError:
853                         return 0;
854 
855                     case kgsmIdle:
856                     {
857                         /* pede registro do canal.. */
858                         pvt->command(KHOMP_LOG, CM_SEND_TO_MODEM, "AT+COPS?");
859 
860                         /* pede estado da antena.. */
861                         pvt->command(KHOMP_LOG, CM_SEND_TO_MODEM, "AT+CSQ?");
862 
863                         /* forca tipo padrao a ser message... */
864                         sms->_got_sms._type = "message";
865 
866                         /* pre-aloca canal para receber mensagens SMS. */
867                         if (sms->justAlloc())
868                         {
869                             /* habilita processamento de SMSs entrantes */
870                             sms->_can_receive = true;
871 
872                             /* envia comando para "limpar" SMSs do SIM card */
873                             pvt->command(KHOMP_LOG, CM_CHECK_NEW_SMS);
874                         }
875 
876                         sms->_got_sms.clear();
877 
878                         /* sai fora do loop! */
879                         loop = false;
880                     }
881                     default:
882                         break;
883                 }
884             }
885         }
886         catch (ScopedLockFailed & err)
887         {
888             DBG(FUNC, PVT_FMT(pvt->_target, "unable to obtain lock: %s") % err._msg.c_str());
889         }
890 
891     }
892 
893     sms->_can_send = true;
894 
895     while(true)
896     {
897         Request request_sms;
898 
899         DBG(THRD, PVT_FMT(pvt->_target, "begin"));
900 
901         while(!sms->_buffer.consume(request_sms))
902         {
903             DBG(THRD, PVT_FMT(pvt->_target, "buffer empty"));
904 
905             sms->_cond.wait();
906 
907             DBG(THRD, PVT_FMT(pvt->_target, "waked up!"));
908 
909             if(sms->_shutdown)
910                 return 0;
911         }
912 
913         DBG(THRD, PVT_FMT(pvt->_target, "processing buffer..."));
914 
915         try
916         {
917             int timeout = 30;
918 
919             ScopedPvtLock lock(pvt);
920 
921             pvt->call()->_flags.set(Kflags::SMS_DOING_UPLOAD);
922 
923             if (pvt->command(KHOMP_LOG, CM_PREPARE_SMS, request_sms._send_sms._body.c_str()))
924             {
925                 std::string extra = (request_sms._send_sms._conf ? " sms_confirm=\"TRUE\"" : "");
926 
927                 if (pvt->command(KHOMP_LOG, CM_SEND_SMS,
928                             STG(FMT("sms_to=\"%s\"%s") % request_sms._send_sms._dest % extra).c_str()))
929                 {
930                     if (!pvt->loopWhileFlagTimed(Kflags::SMS_DOING_UPLOAD, timeout))
931                         break;
932                 }
933                 else
934                 {
935                     sms->_result = kgccResourceUnavailable;
936                 }
937             }
938             else
939             {
940                 sms->_result = kgccInvalidMessage;
941             }
942 
943             pvt->call()->_flags.clear(Kflags::SMS_DOING_UPLOAD);
944 
945             if (request_sms._cause)
946                 *(request_sms._cause) = (KGsmCallCause)sms->_result;
947 
948             if (request_sms._finished)
949                 *(request_sms._finished) = true;
950 
951             if (sms->_result == kgccNone)
952             {
953                 sms->SMSEvent(pvt, sms->_send_sms);
954 
955                 /* stats update if sent! */
956                 sms->statistics<SMSStatistics>()->incrementOutgoing();
957             }
958 
959             sms->_send_sms.clear();
960 
961         }
962         catch (ScopedLockFailed & err)
963         {
964             DBG(FUNC, PVT_FMT(pvt->_target, "unable to obtain lock: %s") % err._msg.c_str());
965         }
966 
967         DBG(FUNC, PVT_FMT(pvt->target(), "ok, going to loop..."));
968 
969     }
970 
971 
972     DBG(FUNC, PVT_FMT(pvt->target(), "r"));
973 
974     return 0;
975 }
976 
977