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