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 "khomp_pvt_kxe1.h"
45 #include "lock.h"
46 #include "logger.h"
47 
48 
isOK()49 bool BoardE1::KhompPvtE1::isOK()
50 {
51     try
52     {
53         ScopedPvtLock lock(this);
54 
55         K3L_CHANNEL_STATUS status;
56 
57         if (k3lGetDeviceStatus (_target.device, _target.object + ksoChannel, &status, sizeof (status)) != ksSuccess)
58             return false;
59 
60         return   ((status.AddInfo == kecsFree) ||
61                 (!(status.AddInfo & kecsLocalFail) &&
62                  !(status.AddInfo & kecsRemoteLock)));
63     }
64     catch (ScopedLockFailed & err)
65     {
66         LOG(ERROR, PVT_FMT(target(), "unable to lock %s!") % err._msg.c_str() );
67     }
68 
69     return false;
70 }
71 
onChannelRelease(K3L_EVENT * e)72 bool BoardE1::KhompPvtE1::onChannelRelease(K3L_EVENT *e)
73 {
74     DBG(FUNC, PVT_FMT(_target, "(E1) c"));
75 
76     bool ret = true;
77 
78     try
79     {
80         ScopedPvtLock lock(this);
81 
82         if (call()->_flags.check(Kflags::FAX_SENDING))
83         {
84             DBG(FUNC, PVT_FMT(_target, "stopping fax tx"));
85             _fax->stopFaxTX();
86         }
87         else if (call()->_flags.check(Kflags::FAX_RECEIVING))
88         {
89             DBG(FUNC, PVT_FMT(_target, "stopping fax rx"));
90             _fax->stopFaxRX();
91         }
92 
93         call()->_flags.clear(Kflags::HAS_PRE_AUDIO);
94 
95         command(KHOMP_LOG, CM_ENABLE_CALL_ANSWER_INFO);
96 
97         ret = KhompPvt::onChannelRelease(e);
98 
99     }
100     catch(ScopedLockFailed & err)
101     {
102         LOG(ERROR, PVT_FMT(target(), "(E1) r (unable to lock %s!)") % err._msg.c_str() );
103         return false;
104     }
105 
106     DBG(FUNC, PVT_FMT(_target, "(E1) r"));
107     return ret;
108 }
109 
onCallSuccess(K3L_EVENT * e)110 bool BoardE1::KhompPvtE1::onCallSuccess(K3L_EVENT *e)
111 {
112     DBG(FUNC, PVT_FMT(_target, "(E1) c"));
113 
114     bool ret;
115 
116     try
117     {
118         ScopedPvtLock lock(this);
119 
120         ret = KhompPvt::onCallSuccess(e);
121 
122         if (call()->_pre_answer)
123         {
124             dtmfSuppression(Opt::_options._out_of_band_dtmfs()&& !call()->_flags.check(Kflags::FAX_DETECTED));
125 
126             startListen();
127             startStream();
128             switch_channel_mark_pre_answered(getFSChannel());
129         }
130         else
131         {
132             call()->_flags.set(Kflags::GEN_PBX_RING);
133             call()->_idx_pbx_ring = Board::board(_target.device)->_timers.add(Opt::_options._ringback_pbx_delay(),
134                                              &Board::KhompPvt::pbxRingGen,this, TM_VAL_CALL);
135         }
136 
137     }
138     catch (ScopedLockFailed & err)
139     {
140         LOG(ERROR, PVT_FMT(_target, "(E1) r (unable to lock %s!)") % err._msg.c_str() );
141         return false;
142     }
143     catch (K3LAPITraits::invalid_device & err)
144     {
145         LOG(ERROR, PVT_FMT(_target, "(E1) r (unable to get device: %d!)") % err.device);
146         return false;
147     }
148 
149     DBG(FUNC, PVT_FMT(_target, "(E1) r"));
150 
151     return ret;
152 }
153 
onAudioStatus(K3L_EVENT * e)154 bool BoardE1::KhompPvtE1::onAudioStatus(K3L_EVENT *e)
155 {
156     DBG(STRM, PVT_FMT(_target, "(E1) c"));
157 
158     try
159     {
160         //ScopedPvtLock lock(this);
161 
162         if(e->AddInfo == kmtFax)
163         {
164             DBG(STRM, PVT_FMT(_target, "Fax detected"));
165 
166             /* hadn't we did this already? */
167             bool already_detected = call()->_flags.check(Kflags::FAX_DETECTED);
168 
169             time_t time_was = call()->_call_statistics->_base_time;
170             time_t time_now = time(NULL);
171 
172             bool detection_timeout = (time_now > (time_was + (time_t) (Opt::_options._fax_adjustment_timeout())));
173 
174             DBG(STRM, PVT_FMT(_target, "is set? (%s) timeout? (%s)")
175                             % (already_detected ? "true" : "false") % (detection_timeout ? "true" : "false"));
176 
177             BEGIN_CONTEXT
178             {
179                 ScopedPvtLock lock(this);
180 
181                 /* already adjusted? do not adjust again. */
182                 if (already_detected || detection_timeout)
183                     break;
184 
185                 if (callE1()->_call_info_drop != 0 || callE1()->_call_info_report)
186                 {
187                     /* we did not detected fax yet, send answer info! */
188                     setAnswerInfo(Board::KhompPvt::CI_FAX);
189 
190                     if (callE1()->_call_info_drop & Board::KhompPvt::CI_FAX)
191                     {
192                         /* fastest way to force a disconnection */
193                         command(KHOMP_LOG,CM_DISCONNECT);//,SCE_HIDE);
194                     }
195                 }
196 
197                 if (Opt::_options._auto_fax_adjustment())
198                 {
199                     DBG(FUNC, PVT_FMT(_target, "communication will be adjusted for fax!"));
200                     _fax->adjustForFax();
201                 }
202             }
203             END_CONTEXT
204 
205             if (!already_detected)
206             {
207                 ScopedPvtLock lock(this);
208 
209                 /* adjust the flag */
210                 call()->_flags.set(Kflags::FAX_DETECTED);
211             }
212         }
213     }
214     catch (ScopedLockFailed & err)
215     {
216         LOG(ERROR, PVT_FMT(_target, "unable to lock %s!") % err._msg.c_str() );
217         return false;
218     }
219 
220     bool ret = KhompPvt::onAudioStatus(e);
221 
222     DBG(STRM, PVT_FMT(_target, "(E1) r"));
223 
224     return ret;
225 }
226 
onCallAnswerInfo(K3L_EVENT * e)227 bool BoardE1::KhompPvtE1::onCallAnswerInfo(K3L_EVENT *e)
228 {
229     DBG(FUNC, PVT_FMT(_target, "(E1) c"));
230     try
231     {
232         ScopedPvtLock lock(this);
233 
234         int info_code = -1;
235 
236         switch (e->AddInfo)
237         {
238             case kcsiCellPhoneMessageBox:
239                 info_code = CI_MESSAGE_BOX;
240                 break;
241             case kcsiHumanAnswer:
242                 info_code = CI_HUMAN_ANSWER;
243                 break;
244             case kcsiAnsweringMachine:
245                 info_code = CI_ANSWERING_MACHINE;
246                 break;
247             case kcsiCarrierMessage:
248                 info_code = CI_CARRIER_MESSAGE;
249                 break;
250             case kcsiUnknown:
251                 info_code = CI_UNKNOWN;
252                 break;
253             default:
254                 DBG(FUNC, PVT_FMT(_target, "got an unknown call answer info '%d', ignoring...") % e->AddInfo);
255                 break;
256         }
257 
258         if (info_code != -1)
259         {
260             if (callE1()->_call_info_report)
261             {
262                 //TODO: HOW WE TREAT THAT
263                 // make the channel export this
264                 setAnswerInfo(info_code);
265             }
266 
267             if (callE1()->_call_info_drop & info_code)
268             {
269                 // fastest way to force a disconnection
270                 //K::util::sendCmd(pvt->boardid, pvt->objectid, CM_DISCONNECT, true, false);
271                 command(KHOMP_LOG,CM_DISCONNECT/*,SCE_HIDE ?*/);
272             }
273         }
274     }
275     catch (ScopedLockFailed & err)
276     {
277         LOG(ERROR, PVT_FMT(_target, "(E1) r (unable to lock %s!)") % err._msg.c_str() );
278         return false;
279     }
280 
281     DBG(FUNC, PVT_FMT(_target, "(E1) r"));
282     return true;
283 }
284 
onDisconnect(K3L_EVENT * e)285 bool BoardE1::KhompPvtE1::onDisconnect(K3L_EVENT *e)
286 {
287     DBG(FUNC, PVT_FMT(_target, "(E1) c"));
288 
289     bool ret = true;
290 
291     try
292     {
293         ScopedPvtLock lock(this);
294 
295         if (call()->_flags.check(Kflags::IS_OUTGOING) ||
296             call()->_flags.check(Kflags::IS_INCOMING))
297         {
298             if(Opt::_options._disconnect_delay()== 0)
299             {
300                 DBG(FUNC, PVT_FMT(_target, "queueing disconnecting outgoing channel!"));
301                 command(KHOMP_LOG, CM_DISCONNECT);
302             }
303             else
304             {
305                 callE1()->_idx_disconnect = Board::board(_target.device)->_timers.add(
306                     1000 * Opt::_options._disconnect_delay(),&BoardE1::KhompPvtE1::delayedDisconnect,this);
307             }
308         }
309         else
310         {
311             /* in the case of a disconnect confirm is needed and a call
312             was not started e.g. just after a ev_seizure_start */
313             command(KHOMP_LOG, CM_DISCONNECT);
314         }
315 
316         ret = KhompPvt::onDisconnect(e);
317 
318     }
319     catch (ScopedLockFailed & err)
320     {
321         LOG(ERROR, PVT_FMT(_target, "(E1) r (unable to lock %s!)") % err._msg.c_str() );
322         return false;
323     }
324     catch (K3LAPITraits::invalid_device & err)
325     {
326         LOG(ERROR, PVT_FMT(_target, "(E1) r (unable to get device: %d!)") % err.device);
327         return false;
328     }
329 
330     DBG(FUNC,PVT_FMT(_target, "(E1) r"));
331     return ret;
332 }
333 
delayedDisconnect(Board::KhompPvt * pvt)334 void BoardE1::KhompPvtE1::delayedDisconnect(Board::KhompPvt * pvt)
335 {
336     DBG(FUNC,PVT_FMT(pvt->target(), "Delayed disconnect"));
337 
338     try
339     {
340         ScopedPvtLock lock(pvt);
341 
342         DBG(FUNC, PVT_FMT(pvt->target(), "queueing disconnecting outgoing channel after delaying!"));
343 
344         pvt->command(KHOMP_LOG,CM_DISCONNECT);
345         pvt->cleanup(CLN_HARD);
346     }
347     catch (...)
348     {
349         LOG(ERROR, PVT_FMT(pvt->target(), "r (unable to lock the pvt !)"));
350     }
351 }
352 
onLinkStatus(K3L_EVENT * e)353 bool BoardE1::onLinkStatus(K3L_EVENT *e)
354 {
355     DBG(FUNC, D("Link %02d on board %02d changed") % e->AddInfo % e->DeviceId);
356 
357     /* Fire a custom event about this */
358     /*
359     switch_event_t * event;
360     if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, KHOMP_EVENT_MAINT) == SWITCH_STATUS_SUCCESS)
361     {
362         //khomp_add_event_board_data(e->AddInfo, event);
363         Board::khomp_add_event_board_data(K3LAPI::target(Globals::k3lapi, K3LAPI::target::LINK, e->DeviceId, e->AddInfo), event);
364 
365         switch_event_add_header(event, SWITCH_STACK_BOTTOM, "EV_LINK_STATUS", "%d", e->AddInfo);
366         switch_event_fire(&event);
367     }
368     */
369 
370     return true;
371 }
372 
onSyncUserInformation(K3L_EVENT * e)373 bool BoardE1::KhompPvtISDN::onSyncUserInformation(K3L_EVENT *e)
374 {
375     DBG(FUNC,PVT_FMT(_target, "Synchronizing"));
376 
377     if(callISDN()->_uui_extended)
378     {
379         KUserInformationEx * info = (KUserInformationEx *) (((char*)e) + sizeof(K3L_EVENT));
380         callISDN()->_uui_descriptor = (long int) info->ProtocolDescriptor;
381 
382         /* clean string */
383         callISDN()->_uui_information.clear();
384 
385         if (info->UserInfoLength)
386         {
387             /* append to a clean string */
388             for (unsigned int i = 0; i < info->UserInfoLength; ++i)
389                 callISDN()->_uui_information += STG(FMT("%02hhx") % ((unsigned char) info->UserInfo[i]));
390         }
391     }
392     else
393     {
394         KUserInformation * info = (KUserInformation *) (((char*)e) + sizeof(K3L_EVENT));
395         callISDN()->_uui_descriptor = info->ProtocolDescriptor;
396 
397         /* clean string */
398         callISDN()->_uui_information.clear();
399 
400         if (info->UserInfoLength)
401         {
402             for (unsigned int i = 0; i < info->UserInfoLength; ++i)
403                 callISDN()->_uui_information += STG(FMT("%02hhx") % ((unsigned char) info->UserInfo[i]));
404         }
405     }
406 
407     return true;
408 }
409 
onIsdnProgressIndicator(K3L_EVENT * e)410 bool BoardE1::KhompPvtISDN::onIsdnProgressIndicator(K3L_EVENT *e)
411 {
412     //TODO: Do we need return something ?
413     try
414     {
415         ScopedPvtLock lock(this);
416 
417         switch (e->AddInfo)
418         {
419             case kq931pTonesMaybeAvailable:
420             case kq931pTonesAvailable:
421                 if (!call()->_is_progress_sent)
422                 {
423                     call()->_is_progress_sent = true;
424 
425                     //Sinaliza para o Freeswitch PROGRESS
426                     DBG(FUNC, PVT_FMT(_target, "Pre answer"));
427 
428                     //pvt->signal_state(SWITCH_CONTROL_PROGRESS);
429                     //switch_channel_pre_answer(channel);
430                     switch_channel_mark_pre_answered(getFSChannel());
431 
432                 }
433                 break;
434             case kq931pDestinationIsNonIsdn:
435             case kq931pOriginationIsNonIsdn:
436             case kq931pCallReturnedToIsdn:
437             default:
438                 break;
439         }
440     }
441     catch (ScopedLockFailed & err)
442     {
443         LOG(ERROR, PVT_FMT(target(), "unable to lock %s!") % err._msg.c_str() );
444         return false;
445     }
446     catch(Board::KhompPvt::InvalidSwitchChannel & err)
447     {
448         LOG(ERROR,PVT_FMT(_target, "No valid channel: %s") % err._msg.c_str());
449         return false;
450     }
451 
452     return true;
453 }
454 
onNewCall(K3L_EVENT * e)455 bool BoardE1::KhompPvtISDN::onNewCall(K3L_EVENT *e)
456 {
457     DBG(FUNC,PVT_FMT(_target, "(ISDN) c"));
458 
459     bool isdn_reverse_charge = false;
460     std::string isdn_reverse_charge_str;
461     bool ret;
462 
463     try
464     {
465         callISDN()->_isdn_orig_type_of_number = Globals::k3lapi.get_param(e, "isdn_orig_type_of_number");
466         callISDN()->_isdn_orig_numbering_plan = Globals::k3lapi.get_param(e, "isdn_orig_numbering_plan");
467         callISDN()->_isdn_dest_type_of_number = Globals::k3lapi.get_param(e, "isdn_dest_type_of_number");
468         callISDN()->_isdn_dest_numbering_plan = Globals::k3lapi.get_param(e, "isdn_dest_numbering_plan");
469         callISDN()->_isdn_orig_presentation   = Globals::k3lapi.get_param(e, "isdn_orig_presentation");
470         isdn_reverse_charge_str = Globals::k3lapi.get_param(e, "isdn_reverse_charge");
471         isdn_reverse_charge = Strings::toboolean(isdn_reverse_charge_str);
472     }
473     catch(K3LAPI::get_param_failed & err)
474     {
475         LOG(WARNING, PVT_FMT(_target, "maybe the parameter is not sent (%s)'") % err.name.c_str());
476     }
477     catch (Strings::invalid_value & err)
478     {
479         LOG(ERROR, PVT_FMT(_target, "unable to get param '%s'") % err.value().c_str());
480     }
481 
482     try
483     {
484         ScopedPvtLock lock(this);
485 
486         if(session())
487         {
488             bool pvt_locked = true;
489             bool is_ok = false;
490 
491             DBG(FUNC, PVT_FMT(_target, "Session has not been destroyed yet, waiting for khompDestroy"));
492 
493             for(unsigned int sleeps = 0; sleeps < 20; sleeps++)
494             {
495                 /* unlock our pvt struct */
496                 if(pvt_locked)
497                 {
498                     _mutex.unlock();
499                     pvt_locked = false;
500                 }
501 
502                 /* wait a little while (100ms is good?) */
503                 usleep (100000);
504 
505                 /* re-lock pvt struct */
506                 switch (_mutex.lock())
507                 {
508                 case SimpleLock::ISINUSE:
509                 case SimpleLock::FAILURE:
510                     LOG(ERROR, PVT_FMT(_target, "unable to lock pvt_mutex, trying again."));
511                     sched_yield();
512                     continue;
513 
514                 default:
515                     break;
516                 }
517 
518                 pvt_locked = true;
519 
520                 if(!session())
521                 {
522                     is_ok = true;
523                     break;
524                 }
525             }
526 
527             if(is_ok)
528             {
529                 DBG(FUNC, PVT_FMT(_target, "Session destroyed properly"));
530             }
531             else
532             {
533                 LOG(ERROR, PVT_FMT(target(), "(ISDN) r (Session was not destroyed, stopping to wait)"));
534                 return false;
535             }
536         }
537 
538         if(isdn_reverse_charge)
539         {
540             call()->_collect_call = true;
541         }
542 
543         ret = KhompPvtE1::onNewCall(e);
544     }
545     catch(ScopedLockFailed & err)
546     {
547         LOG(ERROR, PVT_FMT(target(), "(ISDN) r (unable to lock %s!)") % err._msg.c_str() );
548         return false;
549     }
550 
551     DBG(FUNC, PVT_FMT(_target, "(ISDN) r"));
552 
553     return ret;
554 }
555 
onCallSuccess(K3L_EVENT * e)556 bool BoardE1::KhompPvtISDN::onCallSuccess(K3L_EVENT *e)
557 {
558     bool ret = true;
559 
560     try
561     {
562         ScopedPvtLock lock(this);
563 
564         if(e->AddInfo > 0)
565         {
566             callISDN()->_isdn_cause = e->AddInfo;
567             setFSChannelVar("KISDNGotCause", Verbose::isdnCause((KQ931Cause)callISDN()->_isdn_cause).c_str());
568         }
569 
570         ret = KhompPvtE1::onCallSuccess(e);
571 
572     }
573     catch (ScopedLockFailed & err)
574     {
575         LOG(ERROR, PVT_FMT(target(), "unable to lock %s!") % err._msg.c_str() );
576         return false;
577     }
578     catch(Board::KhompPvt::InvalidSwitchChannel & err)
579     {
580         LOG(ERROR,PVT_FMT(_target, "%s") % err._msg.c_str());
581         return false;
582     }
583 
584     return ret;
585 }
586 
onCallFail(K3L_EVENT * e)587 bool BoardE1::KhompPvtISDN::onCallFail(K3L_EVENT *e)
588 {
589     bool ret = true;
590 
591     try
592     {
593         ScopedPvtLock lock(this);
594 
595         if(e->AddInfo > 0)
596         {
597             callISDN()->_isdn_cause = e->AddInfo;
598             setFSChannelVar("KISDNGotCause", Verbose::isdnCause((KQ931Cause)callISDN()->_isdn_cause).c_str());
599         }
600 
601         setHangupCause(causeFromCallFail(e->AddInfo),true);
602 
603         ret = KhompPvtE1::onCallFail(e);
604 
605     }
606     catch (ScopedLockFailed & err)
607     {
608         LOG(ERROR, PVT_FMT(target(), "unable to lock %s!") % err._msg.c_str() );
609         return false;
610     }
611     catch(Board::KhompPvt::InvalidSwitchChannel & err)
612     {
613         LOG(ERROR,PVT_FMT(_target, "%s") % err._msg.c_str());
614         return false;
615     }
616 
617     return ret;
618 }
619 
sendRingBackStatus(int rb_value)620 RingbackDefs::RingbackStType BoardE1::KhompPvtISDN::sendRingBackStatus(int rb_value)
621 {
622     DBG(FUNC, PVT_FMT(target(), "this is the rdsi ringback procedure"));
623 
624 
625     std::string cause = (rb_value == -1 ? "" : STG(FMT("isdn_cause=\"%d\"") % rb_value));
626     return (command(KHOMP_LOG, CM_RINGBACK, cause.c_str()) ?
627             RingbackDefs::RBST_SUCCESS : RingbackDefs::RBST_FAILURE);
628 }
629 
sendPreAudio(int rb_value)630 bool BoardE1::KhompPvtISDN::sendPreAudio(int rb_value)
631 {
632     if(!KhompPvtE1::sendPreAudio(rb_value))
633         return false;
634 
635 
636     DBG(FUNC,PVT_FMT(_target, "doing the ISDN pre_connect"));
637 
638     if (call()->_flags.check(Kflags::HAS_PRE_AUDIO))
639     {
640         DBG(FUNC, PVT_FMT(target(), "already pre_connect"));
641         return true;
642     }
643     else
644     {
645         bool result = command(KHOMP_LOG, CM_PRE_CONNECT);
646 
647         if (result)
648             call()->_flags.set(Kflags::HAS_PRE_AUDIO);
649 
650         return result;
651     }
652 }
653 
application(ApplicationType type,switch_core_session_t * session,const char * data)654 bool BoardE1::KhompPvtISDN::application(ApplicationType type, switch_core_session_t * session, const char *data)
655 {
656     switch(type)
657     {
658         case USER_TRANSFER:
659             return _transfer->userTransfer(session, data);
660         default:
661             return KhompPvtE1::application(type, session, data);
662     }
663 
664     return true;
665 }
666 
sendDtmf(std::string digit)667 bool BoardE1::KhompPvtISDN::sendDtmf(std::string digit)
668 {
669     if(_transfer->checkUserXferUnlocked(digit))
670     {
671         DBG(FUNC, PVT_FMT(target(), "started (or waiting for) an user xfer"));
672         return true;
673     }
674 
675     bool ret = KhompPvtE1::sendDtmf(callISDN()->_digits_buffer);
676 
677     callISDN()->_digits_buffer.clear();
678 
679     return ret;
680 }
681 
makeCall(std::string params)682 int BoardE1::KhompPvtE1::makeCall(std::string params)
683 {
684     if(callE1()->_call_info_drop == 0 && !callE1()->_call_info_report)
685     {
686         command(KHOMP_LOG, CM_DISABLE_CALL_ANSWER_INFO);
687     }
688 
689     if(!_call->_orig_addr.empty())
690         params += STG(FMT(" orig_addr=\"%s\"") % _call->_orig_addr);
691 
692     int ret = KhompPvt::makeCall(params);
693 
694     if(ret == ksSuccess)
695     {
696         startListen();
697     }
698     else
699     {
700         LOG(ERROR, PVT_FMT(target(), "Fail on make call"));
701     }
702 
703     return ret;
704 }
705 
indicateBusyUnlocked(int cause,bool sent_signaling)706 bool BoardE1::KhompPvtE1::indicateBusyUnlocked(int cause, bool sent_signaling)
707 {
708     DBG(FUNC, PVT_FMT(_target, "(E1) c"));
709 
710     if(!KhompPvt::indicateBusyUnlocked(cause, sent_signaling))
711     {
712         DBG(FUNC, PVT_FMT(_target, "(E1) r (false)"));
713         return false;
714     }
715 
716     if(call()->_flags.check(Kflags::IS_INCOMING))
717     {
718         if(!call()->_flags.check(Kflags::CONNECTED) && !sent_signaling)
719         {
720             if(!call()->_flags.check(Kflags::HAS_PRE_AUDIO))
721             {
722                 int rb_value = callFailFromCause(call()->_hangup_cause);
723                 DBG(FUNC, PVT_FMT(target(), "sending the busy status"));
724 
725                 if (sendRingBackStatus(rb_value) == RingbackDefs::RBST_UNSUPPORTED)
726                 {
727                     DBG(FUNC, PVT_FMT(target(), "falling back to audio indication!"));
728                     /* stop the line audio */
729                     stopStream();
730 
731                     /* just pre connect, no ringback */
732                     if (!sendPreAudio())
733                         DBG(FUNC, PVT_FMT(target(), "everything else failed, just sending audio indication..."));
734 
735                     /* be very specific about the situation. */
736                     mixer(KHOMP_LOG, 1, kmsGenerator, kmtBusy);
737                 }
738             }
739             else
740             {
741                 DBG(FUNC, PVT_FMT(target(), "going to play busy"));
742 
743                 /* stop the line audio */
744                 stopStream();
745 
746                 /* be very specific about the situation. */
747                 mixer(KHOMP_LOG, 1, kmsGenerator, kmtBusy);
748 
749             }
750         }
751         else
752         {
753             /* already connected or sent signaling... */
754             mixer(KHOMP_LOG, 1, kmsGenerator, kmtBusy);
755         }
756 
757     }
758     else if(call()->_flags.check(Kflags::IS_OUTGOING))
759     {
760         /* already connected or sent signaling... */
761         mixer(KHOMP_LOG, 1, kmsGenerator, kmtBusy);
762     }
763 
764     DBG(FUNC,PVT_FMT(_target, "(E1) r"));
765 
766     return true;
767 }
768 
setAnswerInfo(int answer_info)769 void BoardE1::KhompPvtE1::setAnswerInfo(int answer_info)
770 {
771     const char * value = answerInfoToString(answer_info);
772 
773     if (value == NULL)
774     {
775         DBG(FUNC, PVT_FMT(_target, "signaled unknown call answer info '%d', using 'Unknown'...") % answer_info);
776         value = "Unknown";
777     }
778 
779     DBG(FUNC,PVT_FMT(_target, "KCallAnswerInfo: %s") % value);
780 
781     try
782     {
783         setFSChannelVar("KCallAnswerInfo",value);
784     }
785     catch(Board::KhompPvt::InvalidSwitchChannel & err)
786     {
787         LOG(ERROR,PVT_FMT(_target, "%s") % err._msg.c_str());
788     }
789 }
790 
setupConnection()791 bool BoardE1::KhompPvtE1::setupConnection()
792 {
793     if(!call()->_flags.check(Kflags::IS_INCOMING) && !call()->_flags.check(Kflags::IS_OUTGOING))
794     {
795         DBG(FUNC,PVT_FMT(_target, "Channel already disconnected"));
796         return false;
797     }
798 
799     /* if received some disconnect from 'drop collect call'
800        feature of some pbx, then leave the call rock and rolling */
801     Board::board(_target.device)->_timers.del(callE1()->_idx_disconnect);
802 
803     bool fax_detected = callE1()->_flags.check(Kflags::FAX_DETECTED) || (callE1()->_var_fax_adjust == T_TRUE);
804 
805     bool res_out_of_band_dtmf = (call()->_var_dtmf_state == T_UNKNOWN || fax_detected ?
806         Opt::_options._suppression_delay()&& Opt::_options._out_of_band_dtmfs()&& !fax_detected : (call()->_var_dtmf_state == T_TRUE));
807 
808     bool res_echo_cancellator = (call()->_var_echo_state == T_UNKNOWN || fax_detected ?
809         Opt::_options._echo_canceller()&& !fax_detected : (call()->_var_echo_state == T_TRUE));
810 
811     bool res_auto_gain_cntrol = (call()->_var_gain_state == T_UNKNOWN || fax_detected ?
812         Opt::_options._auto_gain_control()&& !fax_detected : (call()->_var_gain_state == T_TRUE));
813 
814     if (!call()->_flags.check(Kflags::REALLY_CONNECTED))
815     {
816         obtainRX(res_out_of_band_dtmf);
817 
818         /* esvazia buffers de leitura/escrita */
819         cleanupBuffers();
820 
821         if (!call()->_flags.check(Kflags::KEEP_DTMF_SUPPRESSION))
822             dtmfSuppression(res_out_of_band_dtmf);
823 
824         if (!call()->_flags.check(Kflags::KEEP_ECHO_CANCELLATION))
825             echoCancellation(res_echo_cancellator);
826 
827         if (!call()->_flags.check(Kflags::KEEP_AUTO_GAIN_CONTROL))
828             autoGainControl(res_auto_gain_cntrol);
829 
830         startListen(false);
831 
832         startStream();
833 
834         DBG(FUNC, PVT_FMT(_target, "(E1) Audio callbacks initialized successfully"));
835     }
836 
837     return Board::KhompPvt::setupConnection();
838 }
839 
application(ApplicationType type,switch_core_session_t * session,const char * data)840 bool BoardE1::KhompPvtE1::application(ApplicationType type, switch_core_session_t * session, const char *data)
841 {
842     switch(type)
843     {
844         case FAX_ADJUST:
845             return _fax->adjustForFax();
846         case FAX_SEND:
847             return _fax->sendFax(session, data);
848         case FAX_RECEIVE:
849             return _fax->receiveFax(session, data);
850         default:
851             return KhompPvt::application(type, session, data);
852     }
853 
854     return true;
855 }
856 
validContexts(MatchExtension::ContextListType & contexts,std::string extra_context)857 bool BoardE1::KhompPvtE1::validContexts(
858         MatchExtension::ContextListType & contexts, std::string extra_context)
859 {
860     DBG(FUNC,PVT_FMT(_target, "(E1) c"));
861 
862     if(!_group_context.empty())
863     {
864         contexts.push_back(_group_context);
865     }
866 
867     contexts.push_back(Opt::_options._context_digital());
868 
869     for (MatchExtension::ContextListType::iterator i = contexts.begin(); i != contexts.end(); i++)
870     {
871         replaceTemplate((*i), "LL", ((_target.object)/30));
872         replaceTemplate((*i), "CCC", _target.object);
873     }
874 
875     bool ret = Board::KhompPvt::validContexts(contexts,extra_context);
876 
877     DBG(FUNC,PVT_FMT(_target, "(E1) r"));
878 
879     return ret;
880 }
881 
makeCall(std::string params)882 int BoardE1::KhompPvtISDN::makeCall(std::string params)
883 {
884     DBG(FUNC,PVT_FMT(_target, "(ISDN) c"));
885 
886     CallISDN * call = callISDN();
887 
888     if(call->_uui_descriptor != -1)
889     {
890         DBG(FUNC,PVT_FMT(_target, "got userinfo"));
891 
892         /* grab this information first, avoiding latter side-effects */
893         const bool        info_extd = call->_uui_extended;
894         const long int    info_desc = call->_uui_descriptor;
895         const std::string info_data = call->_uui_information.c_str();
896         const size_t      info_size = std::min<size_t>(call->_uui_information.size(), (info_extd ? KMAX_USER_USER_EX_LEN : KMAX_USER_USER_LEN) << 1) >> 1;
897 
898         bool res = true;
899 
900         if(info_extd)
901         {
902             KUserInformationEx info;
903 
904             info.ProtocolDescriptor = info_desc;
905             info.UserInfoLength = info_size;
906 
907             for (unsigned int pos = 0u, index = 0u; pos < info_size; index+=2, ++pos)
908                 info.UserInfo[pos] = (unsigned char)Strings::toulong(info_data.substr(index,2), 16);
909 
910             if (!command(KHOMP_LOG, CM_USER_INFORMATION_EX, (const char *) &info))
911             {
912                 LOG(ERROR,PVT_FMT(_target, "UUI could not be sent before dialing!"));
913             }
914         }
915         else
916         {
917             KUserInformation info;
918 
919             info.ProtocolDescriptor = info_desc;
920             info.UserInfoLength = info_size;
921 
922             for (unsigned int pos = 0u, index = 0u; pos < info_size; index+=2, ++pos)
923                 info.UserInfo[pos] = (unsigned char)Strings::toulong(info_data.substr(index,2), 16);
924 
925             if (!command(KHOMP_LOG, CM_USER_INFORMATION, (const char *) &info))
926             {
927                 LOG(ERROR,PVT_FMT(_target, "UUI could not be sent before dialing!"));
928             }
929         }
930 
931         call->_uui_extended = false;
932         call->_uui_descriptor = -1;
933         call->_uui_information.clear();
934     }
935 
936     if (!callISDN()->_isdn_orig_type_of_number.empty())
937     {
938         params += "isdn_orig_type_of_number=\"";
939         params += callISDN()->_isdn_orig_type_of_number;
940         params += "\" ";
941     }
942 
943     if (!callISDN()->_isdn_dest_type_of_number.empty())
944     {
945         params += "isdn_dest_type_of_number=\"";
946         params += callISDN()->_isdn_dest_type_of_number;
947         params += "\" ";
948     }
949 
950     if (!callISDN()->_isdn_orig_numbering_plan.empty())
951     {
952         params += "isdn_orig_numbering_plan=\"";
953         params += callISDN()->_isdn_orig_numbering_plan;
954         params += "\" ";
955     }
956 
957     if (!callISDN()->_isdn_dest_numbering_plan.empty())
958     {
959         params += "isdn_dest_numbering_plan=\"";
960         params += callISDN()->_isdn_dest_numbering_plan;
961         params += "\" ";
962     }
963 
964     if (!callISDN()->_isdn_orig_presentation.empty())
965     {
966         params += "isdn_orig_presentation=\"";
967         params += callISDN()->_isdn_orig_presentation;
968         params += "\" ";
969     }
970 
971     int ret = KhompPvtE1::makeCall(params);
972 
973     call->_cleanup_upon_hangup = (ret == ksInvalidParams || ret == ksBusy);
974 
975     DBG(FUNC,PVT_FMT(_target, "(ISDN) r"));
976 
977     return ret;
978 }
979 
reportFailToReceive(int fail_code)980 void BoardE1::KhompPvtISDN::reportFailToReceive(int fail_code)
981 {
982     KhompPvt::reportFailToReceive(fail_code);
983 
984     if(fail_code != -1)
985     {
986         DBG(FUNC,PVT_FMT(_target, "sending a 'unknown number' message/audio"));
987 
988         if(sendRingBackStatus(fail_code) == RingbackDefs::RBST_UNSUPPORTED)
989         {
990             sendPreAudio(RingbackDefs::RB_SEND_DEFAULT);
991             startCadence(PLAY_FASTBUSY);
992         }
993     }
994     else
995     {
996         DBG(FUNC, PVT_FMT(_target, "sending fast busy audio directly"));
997 
998         sendPreAudio(RingbackDefs::RB_SEND_DEFAULT);
999         startCadence(PLAY_FASTBUSY);
1000     }
1001 }
1002 
doChannelAnswer(CommandRequest & cmd)1003 bool BoardE1::KhompPvtISDN::doChannelAnswer(CommandRequest &cmd)
1004 {
1005     bool ret = true;
1006 
1007     try
1008     {
1009         ScopedPvtLock lock(this);
1010 
1011         // is this a collect call?
1012         bool has_recv_collect_call = _call->_collect_call;
1013 
1014         if(has_recv_collect_call)
1015             DBG(FUNC, PVT_FMT(target(), "receive a collect call"));
1016 
1017         if(call()->_flags.check(Kflags::DROP_COLLECT))
1018             DBG(FUNC, PVT_FMT(target(), "flag DROP_COLLECT == true"));
1019 
1020         // do we have to drop collect calls?
1021         bool has_drop_collect_call = call()->_flags.check(Kflags::DROP_COLLECT);
1022 
1023         // do we have to drop THIS call?
1024         bool do_drop_call = has_drop_collect_call && has_recv_collect_call;
1025 
1026         if(!do_drop_call)
1027         {
1028             command(KHOMP_LOG, CM_CONNECT);
1029         }
1030         else
1031         {
1032             usleep(75000);
1033 
1034             DBG(FUNC, PVT_FMT(target(), "disconnecting collect call doChannelAnswer ISDN"));
1035             command(KHOMP_LOG,CM_DISCONNECT);
1036 
1037             // thou shalt not talk anymore!
1038             stopListen();
1039             stopStream();
1040         }
1041 
1042         ret = KhompPvtE1::doChannelAnswer(cmd);
1043     }
1044     catch (ScopedLockFailed & err)
1045     {
1046         LOG(ERROR, PVT_FMT(_target, "unable to lock %s!") % err._msg.c_str() );
1047         return false;
1048     }
1049 
1050     return ret;
1051 }
1052 
makeCall(std::string params)1053 int BoardE1::KhompPvtR2::makeCall(std::string params)
1054 {
1055     DBG(FUNC,PVT_FMT(_target, "(R2) c"));
1056 
1057     if (callR2()->_r2_category != -1)
1058         params += STG(FMT(" r2_categ_a=\"%ld\"")
1059                 % callR2()->_r2_category);
1060 
1061     int ret = KhompPvtE1::makeCall(params);
1062 
1063     call()->_cleanup_upon_hangup = (ret == ksInvalidParams);
1064 
1065     DBG(FUNC,PVT_FMT(_target, "(R2) r"));
1066 
1067     return ret;
1068 }
1069 
doChannelAnswer(CommandRequest & cmd)1070 bool BoardE1::KhompPvtR2::doChannelAnswer(CommandRequest &cmd)
1071 {
1072     bool ret = true;
1073 
1074     try
1075     {
1076         ScopedPvtLock lock(this);
1077 
1078         // is this a collect call?
1079         bool has_recv_collect_call = _call->_collect_call;
1080 
1081         // do we have to drop collect calls?
1082         bool has_drop_collect_call = call()->_flags.check(Kflags::DROP_COLLECT);
1083 
1084         // do we have to drop THIS call?
1085         bool do_drop_call = has_drop_collect_call && has_recv_collect_call;
1086 
1087         bool do_send_ring = call()->_flags.check(Kflags::NEEDS_RINGBACK_CMD);
1088 
1089         // do we have to send ringback? yes we need !!!
1090         if(do_send_ring)
1091         {
1092             call()->_flags.clear(Kflags::NEEDS_RINGBACK_CMD);
1093 
1094             //TODO: callFailFromCause ??
1095             std::string cause = ( do_drop_call ? STG(FMT("r2_cond_b=\"%d\"") % kgbBusy) : "" );
1096             command(KHOMP_LOG,CM_RINGBACK,cause.c_str());
1097 
1098             usleep(75000);
1099         }
1100 
1101         if(!do_drop_call)
1102         {
1103             command(KHOMP_LOG, CM_CONNECT);
1104         }
1105 
1106         if(!do_send_ring && has_drop_collect_call)
1107         {
1108             usleep(75000);
1109 
1110             if(has_recv_collect_call)
1111             {
1112                 // thou shalt not talk anymore!
1113                 stopListen();
1114                 stopStream();
1115 
1116                 if (call()->_indication == INDICA_NONE)
1117                 {
1118                     call()->_indication = INDICA_BUSY;
1119                     mixer(KHOMP_LOG, 1, kmsGenerator, kmtBusy);
1120                 }
1121 
1122                 DBG(FUNC, PVT_FMT(_target,"forcing disconnect for collect call"));
1123                 forceDisconnect();
1124             }
1125             else
1126             {
1127                 DBG(FUNC, PVT_FMT(target(), "dropping collect call at doChannelAnswer"));
1128                 command(KHOMP_LOG, CM_DROP_COLLECT_CALL);
1129             }
1130         }
1131 
1132         ret = KhompPvtE1::doChannelAnswer(cmd);
1133     }
1134     catch (ScopedLockFailed & err)
1135     {
1136         LOG(ERROR,PVT_FMT(_target, "unable to lock %s!") % err._msg.c_str() );
1137         return false;
1138     }
1139 
1140     return ret;
1141 }
1142 
doChannelHangup(CommandRequest & cmd)1143 bool BoardE1::KhompPvtR2::doChannelHangup(CommandRequest &cmd)
1144 {
1145     DBG(FUNC, PVT_FMT(_target, "(R2) c"));
1146 
1147     bool answered     = true;
1148     bool disconnected = false;
1149 
1150     try
1151     {
1152         ScopedPvtLock lock(this);
1153 
1154         if (call()->_flags.check(Kflags::IS_INCOMING))
1155         {
1156             DBG(FUNC,PVT_FMT(_target, "disconnecting incoming channel"));
1157 
1158             //disconnected = command(KHOMP_LOG, CM_DISCONNECT);
1159         }
1160         else if (call()->_flags.check(Kflags::IS_OUTGOING))
1161         {
1162             if(call()->_cleanup_upon_hangup)
1163             {
1164                 DBG(FUNC,PVT_FMT(_target, "disconnecting not allocated outgoing channel..."));
1165 
1166                 disconnected = command(KHOMP_LOG, CM_DISCONNECT);
1167                 cleanup(KhompPvt::CLN_HARD);
1168                 answered = false;
1169 
1170             }
1171             else
1172             {
1173                 DBG(FUNC,PVT_FMT(_target, "disconnecting outgoing channel..."));
1174 
1175                 disconnected = command(KHOMP_LOG, CM_DISCONNECT);
1176             }
1177         }
1178         else
1179         {
1180             DBG(FUNC,PVT_FMT(_target, "already disconnected"));
1181             return true;
1182         }
1183 
1184         if(answered)
1185         {
1186             indicateBusyUnlocked(SWITCH_CAUSE_USER_BUSY, disconnected);
1187         }
1188 
1189         if (call()->_flags.check(Kflags::IS_INCOMING) && !call()->_flags.check(Kflags::NEEDS_RINGBACK_CMD))
1190         {
1191             DBG(FUNC,PVT_FMT(_target, "disconnecting incoming channel..."));
1192             disconnected = command(KHOMP_LOG, CM_DISCONNECT);
1193         }
1194 
1195         stopStream();
1196 
1197         stopListen();
1198 
1199     }
1200     catch (ScopedLockFailed & err)
1201     {
1202         LOG(ERROR, PVT_FMT(_target, "(R2) r (unable to lock %s!)") % err._msg.c_str() );
1203         return false;
1204     }
1205 
1206 
1207     DBG(FUNC, PVT_FMT(_target, "(R2) r"));
1208     return true;
1209 }
1210 
causeFromCallFail(int fail)1211 int BoardE1::KhompPvtISDN::causeFromCallFail(int fail)
1212 {
1213     int switch_cause = SWITCH_CAUSE_USER_BUSY;
1214 
1215     if (fail <= 127)
1216         switch_cause = fail;
1217     else
1218         switch_cause = SWITCH_CAUSE_INTERWORKING;
1219 
1220     return switch_cause;
1221 }
1222 
reportFailToReceive(int fail_code)1223 void BoardE1::KhompPvtR2::reportFailToReceive(int fail_code)
1224 {
1225     KhompPvt::reportFailToReceive(fail_code);
1226 
1227     if (Opt::_options._r2_strict_behaviour()&& fail_code != -1)
1228     {
1229         DBG(FUNC,PVT_FMT(_target, "sending a 'unknown number' message/audio"));
1230 
1231         if(sendRingBackStatus(fail_code) == RingbackDefs::RBST_UNSUPPORTED)
1232         {
1233             sendPreAudio(RingbackDefs::RB_SEND_DEFAULT);
1234             startCadence(PLAY_FASTBUSY);
1235         }
1236     }
1237     else
1238     {
1239         DBG(FUNC, PVT_FMT(_target, "sending fast busy audio directly"));
1240 
1241         sendPreAudio(RingbackDefs::RB_SEND_DEFAULT);
1242         startCadence(PLAY_FASTBUSY);
1243     }
1244 }
1245 
causeFromCallFail(int fail)1246 int BoardE1::KhompPvtR2::causeFromCallFail(int fail)
1247 {
1248     int switch_cause = SWITCH_CAUSE_USER_BUSY;
1249 
1250     try
1251     {
1252         bool handled = false;
1253 
1254         switch (_r2_country)
1255         {
1256             case Verbose::R2_COUNTRY_ARG:
1257                 switch (fail)
1258                 {
1259                     case kgbArBusy:
1260                         switch_cause = SWITCH_CAUSE_USER_BUSY;
1261                         break;
1262                     case kgbArNumberChanged:
1263                         switch_cause = SWITCH_CAUSE_NUMBER_CHANGED;
1264                         break;
1265                     case kgbArCongestion:
1266                         switch_cause = SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION;
1267                         break;
1268                     case kgbArInvalidNumber:
1269                         switch_cause = SWITCH_CAUSE_UNALLOCATED_NUMBER;
1270                         break;
1271                     case kgbArLineOutOfOrder:
1272                         switch_cause = SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL;
1273                         break;
1274                 }
1275                 handled = true;
1276                 break;
1277 
1278             case Verbose::R2_COUNTRY_BRA:
1279                 switch (fail)
1280                 {
1281                     case kgbBrBusy:
1282                         switch_cause = SWITCH_CAUSE_USER_BUSY;
1283                         break;
1284                     case kgbBrNumberChanged:
1285                         switch_cause = SWITCH_CAUSE_NUMBER_CHANGED;
1286                         break;
1287                     case kgbBrCongestion:
1288                         switch_cause = SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION;
1289                         break;
1290                     case kgbBrInvalidNumber:
1291                         switch_cause = SWITCH_CAUSE_UNALLOCATED_NUMBER;
1292                         break;
1293                     case kgbBrLineOutOfOrder:
1294                         switch_cause = SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL;
1295                         break;
1296                 }
1297                 handled = true;
1298                 break;
1299             case Verbose::R2_COUNTRY_CHI:
1300                     switch (fail)
1301                     {
1302                         case kgbClBusy:
1303                             switch_cause = SWITCH_CAUSE_USER_BUSY;
1304                             break;
1305                         case kgbClNumberChanged:
1306                             switch_cause = SWITCH_CAUSE_NUMBER_CHANGED;
1307                             break;
1308                         case kgbClCongestion:
1309                             switch_cause = SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION;
1310                             break;
1311                         case kgbClInvalidNumber:
1312                             switch_cause = SWITCH_CAUSE_UNALLOCATED_NUMBER;
1313                             break;
1314                         case kgbClLineOutOfOrder:
1315                             switch_cause = SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL;
1316                             break;
1317                     }
1318                 handled = true;
1319                 break;
1320 
1321             case Verbose::R2_COUNTRY_MEX:
1322                 switch (fail)
1323                 {
1324                     case kgbMxBusy:
1325                         switch_cause = SWITCH_CAUSE_USER_BUSY;
1326                         break;
1327                 }
1328                 handled = true;
1329                 break;
1330 
1331             case Verbose::R2_COUNTRY_URY:
1332                 switch (fail)
1333                 {
1334                     case kgbUyBusy:
1335                         switch_cause = SWITCH_CAUSE_USER_BUSY;
1336                         break;
1337                     case kgbUyNumberChanged:
1338                         switch_cause = SWITCH_CAUSE_NUMBER_CHANGED;
1339                         break;
1340                     case kgbUyCongestion:
1341                         switch_cause = SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION;
1342                         break;
1343                     case kgbUyInvalidNumber:
1344                         switch_cause = SWITCH_CAUSE_UNALLOCATED_NUMBER;
1345                         break;
1346                     case kgbUyLineOutOfOrder:
1347                         switch_cause = SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL;
1348                         break;
1349                 }
1350                 handled = true;
1351                 break;
1352             case Verbose::R2_COUNTRY_VEN:
1353                 switch (fail)
1354                 {
1355                     case kgbVeBusy:
1356                         switch_cause = SWITCH_CAUSE_USER_BUSY;
1357                         break;
1358                     case kgbVeNumberChanged:
1359                         switch_cause = SWITCH_CAUSE_NUMBER_CHANGED;
1360                         break;
1361                     case kgbVeCongestion:
1362                         switch_cause = SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION;
1363                         break;
1364                     case kgbVeLineBlocked:
1365                         switch_cause = SWITCH_CAUSE_OUTGOING_CALL_BARRED;
1366                         break;
1367                 }
1368                 handled = true;
1369                 break;
1370         }
1371 
1372         if (!handled)
1373             throw std::runtime_error("");
1374     }
1375     catch (...)
1376     {
1377         LOG(ERROR,
1378                 PVT_FMT(_target, "country signaling not found, unable to report R2 hangup code.."));
1379     }
1380 
1381     return switch_cause;
1382 
1383 }
1384 
callFailFromCause(int cause)1385 int BoardE1::KhompPvtR2::callFailFromCause(int cause)
1386 {
1387     int k3l_fail = -1; // default
1388 
1389     try
1390     {
1391         bool handled = false;
1392 
1393         switch (_r2_country)
1394         {
1395             case Verbose::R2_COUNTRY_ARG:
1396                 switch (cause)
1397                 {
1398                     case SWITCH_CAUSE_UNALLOCATED_NUMBER:
1399                     case SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET:
1400                     case SWITCH_CAUSE_NO_ROUTE_DESTINATION:
1401                     case SWITCH_CAUSE_INVALID_NUMBER_FORMAT:
1402                     case SWITCH_CAUSE_INVALID_GATEWAY:
1403                     case SWITCH_CAUSE_INVALID_URL:
1404                     case SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED:
1405                     case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION:
1406 
1407                     case SWITCH_CAUSE_INCOMING_CALL_BARRED: /* ?? */
1408                     case SWITCH_CAUSE_OUTGOING_CALL_BARRED: /* ?? */
1409                         k3l_fail = kgbArInvalidNumber;
1410                         break;
1411 
1412                     case SWITCH_CAUSE_USER_BUSY:
1413                     case SWITCH_CAUSE_NO_USER_RESPONSE:
1414                     case SWITCH_CAUSE_CALL_REJECTED:
1415                         k3l_fail = kgbArBusy;
1416                         break;
1417 
1418                     case SWITCH_CAUSE_NUMBER_CHANGED:
1419                         k3l_fail = kgbArNumberChanged;
1420                         break;
1421 
1422                     case SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION:
1423                     case SWITCH_CAUSE_SWITCH_CONGESTION:
1424 
1425                     case SWITCH_CAUSE_NORMAL_CLEARING:
1426                     case SWITCH_CAUSE_NORMAL_UNSPECIFIED:
1427                     case SWITCH_CAUSE_CALL_AWARDED_DELIVERED: /* ?? */
1428                         // this preserves semantics..
1429                         k3l_fail = kgbArCongestion;
1430                         break;
1431 
1432                     case SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL:
1433                     case SWITCH_CAUSE_CHANNEL_UNACCEPTABLE:
1434                     case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER:
1435                     case SWITCH_CAUSE_INVALID_PROFILE:
1436                     case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER:
1437                     case SWITCH_CAUSE_GATEWAY_DOWN:
1438                     case SWITCH_CAUSE_FACILITY_REJECTED:
1439                     case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED:
1440                     case SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED:
1441                     default:
1442                         k3l_fail = kgbArLineOutOfOrder;
1443                         break;
1444                 }
1445                 handled = true;
1446                 break;
1447 
1448             case Verbose::R2_COUNTRY_BRA:
1449                 switch (cause)
1450                 {
1451                     case SWITCH_CAUSE_UNALLOCATED_NUMBER:
1452                     case SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET:
1453                     case SWITCH_CAUSE_NO_ROUTE_DESTINATION:
1454                     case SWITCH_CAUSE_INVALID_NUMBER_FORMAT:
1455                     case SWITCH_CAUSE_INVALID_GATEWAY:
1456                     case SWITCH_CAUSE_INVALID_URL:
1457                     case SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED:
1458                     case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION:
1459 
1460                     case SWITCH_CAUSE_INCOMING_CALL_BARRED: /* ?? */
1461                     case SWITCH_CAUSE_OUTGOING_CALL_BARRED: /* ?? */
1462                         k3l_fail = kgbBrInvalidNumber;
1463                         break;
1464 
1465                     case SWITCH_CAUSE_USER_BUSY:
1466                     case SWITCH_CAUSE_NO_USER_RESPONSE:
1467                     case SWITCH_CAUSE_CALL_REJECTED:
1468                         k3l_fail = kgbBrBusy;
1469                         break;
1470 
1471                     case SWITCH_CAUSE_NUMBER_CHANGED:
1472                         k3l_fail = kgbBrNumberChanged;
1473                         break;
1474 
1475                     case SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION:
1476                     case SWITCH_CAUSE_SWITCH_CONGESTION:
1477 
1478                     case SWITCH_CAUSE_NORMAL_CLEARING:
1479                     case SWITCH_CAUSE_NORMAL_UNSPECIFIED:
1480                     case SWITCH_CAUSE_CALL_AWARDED_DELIVERED: /* ?? */
1481                         // this preserves semantics..
1482                         k3l_fail = kgbBrCongestion;
1483                         break;
1484 
1485                     case SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL:
1486                     case SWITCH_CAUSE_CHANNEL_UNACCEPTABLE:
1487                     case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER:
1488                     case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER:
1489                     case SWITCH_CAUSE_GATEWAY_DOWN:
1490                     case SWITCH_CAUSE_FACILITY_REJECTED:
1491                     case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED:
1492                     case SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED:
1493                     default:
1494                         k3l_fail = kgbBrLineOutOfOrder;
1495                         break;
1496                 }
1497                 handled = true;
1498                 break;
1499 
1500             case Verbose::R2_COUNTRY_CHI:
1501                 switch (cause)
1502                 {
1503                     case SWITCH_CAUSE_UNALLOCATED_NUMBER:
1504                     case SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET:
1505                     case SWITCH_CAUSE_NO_ROUTE_DESTINATION:
1506                     case SWITCH_CAUSE_INVALID_NUMBER_FORMAT:
1507                     case SWITCH_CAUSE_INVALID_GATEWAY:
1508                     case SWITCH_CAUSE_INVALID_URL:
1509                     case SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED:
1510                     case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION:
1511 
1512                     case SWITCH_CAUSE_INCOMING_CALL_BARRED: /* ?? */
1513                     case SWITCH_CAUSE_OUTGOING_CALL_BARRED: /* ?? */
1514                         k3l_fail = kgbClInvalidNumber;
1515                         break;
1516 
1517                     case SWITCH_CAUSE_USER_BUSY:
1518                     case SWITCH_CAUSE_NO_USER_RESPONSE:
1519                     case SWITCH_CAUSE_CALL_REJECTED:
1520                         k3l_fail = kgbClBusy;
1521                         break;
1522 
1523                     case SWITCH_CAUSE_NUMBER_CHANGED:
1524                         k3l_fail = kgbClNumberChanged;
1525                         break;
1526 
1527                     case SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION:
1528                     case SWITCH_CAUSE_SWITCH_CONGESTION:
1529 
1530                     case SWITCH_CAUSE_NORMAL_CLEARING:
1531                     case SWITCH_CAUSE_NORMAL_UNSPECIFIED:
1532                     case SWITCH_CAUSE_CALL_AWARDED_DELIVERED: /* ?? */
1533                         // this preserves semantics..
1534                         k3l_fail = kgbClCongestion;
1535                         break;
1536 
1537                     case SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL:
1538                     case SWITCH_CAUSE_CHANNEL_UNACCEPTABLE:
1539                     case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER:
1540                     case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER:
1541                     case SWITCH_CAUSE_GATEWAY_DOWN:
1542                     case SWITCH_CAUSE_FACILITY_REJECTED:
1543                     case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED:
1544                     case SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED:
1545                     default:
1546                         k3l_fail = kgbClLineOutOfOrder;
1547                         break;
1548                 }
1549                 handled = true;
1550                 break;
1551 
1552 
1553             case Verbose::R2_COUNTRY_MEX:
1554                 k3l_fail = kgbMxBusy;
1555                 handled = true;
1556                 break;
1557 
1558 
1559             case Verbose::R2_COUNTRY_URY:
1560                 switch (cause)
1561                 {
1562                     case SWITCH_CAUSE_UNALLOCATED_NUMBER:
1563                     case SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET:
1564                     case SWITCH_CAUSE_NO_ROUTE_DESTINATION:
1565                     case SWITCH_CAUSE_INVALID_NUMBER_FORMAT:
1566                     case SWITCH_CAUSE_INVALID_GATEWAY:
1567                     case SWITCH_CAUSE_INVALID_URL:
1568                     case SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED:
1569                     case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION:
1570 
1571                     case SWITCH_CAUSE_INCOMING_CALL_BARRED: /* ?? */
1572                     case SWITCH_CAUSE_OUTGOING_CALL_BARRED: /* ?? */
1573                         k3l_fail = kgbUyInvalidNumber;
1574                         break;
1575 
1576                     case SWITCH_CAUSE_USER_BUSY:
1577                     case SWITCH_CAUSE_NO_USER_RESPONSE:
1578                     case SWITCH_CAUSE_CALL_REJECTED:
1579                         k3l_fail = kgbUyBusy;
1580                         break;
1581 
1582                     case SWITCH_CAUSE_NUMBER_CHANGED:
1583                         k3l_fail = kgbUyNumberChanged;
1584                         break;
1585 
1586                     case SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION:
1587                     case SWITCH_CAUSE_SWITCH_CONGESTION:
1588 
1589                     case SWITCH_CAUSE_NORMAL_CLEARING:
1590                     case SWITCH_CAUSE_NORMAL_UNSPECIFIED:
1591                     case SWITCH_CAUSE_CALL_AWARDED_DELIVERED: /* ?? */
1592                         // this preserves semantics..
1593                         k3l_fail = kgbUyCongestion;
1594                         break;
1595 
1596                     case SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL:
1597                     case SWITCH_CAUSE_CHANNEL_UNACCEPTABLE:
1598                     case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER:
1599                     case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER:
1600                     case SWITCH_CAUSE_GATEWAY_DOWN:
1601                     case SWITCH_CAUSE_FACILITY_REJECTED:
1602                     case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED:
1603                     case SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED:
1604                     default:
1605                         k3l_fail = kgbUyLineOutOfOrder;
1606                         break;
1607                 }
1608                 handled = true;
1609                 break;
1610 
1611 
1612             case Verbose::R2_COUNTRY_VEN:
1613                 switch (cause)
1614                 {
1615                     case SWITCH_CAUSE_INCOMING_CALL_BARRED:
1616                     case SWITCH_CAUSE_OUTGOING_CALL_BARRED:
1617                         k3l_fail = kgbVeLineBlocked;
1618                         break;
1619 
1620                     case SWITCH_CAUSE_NUMBER_CHANGED:
1621                         k3l_fail = kgbVeNumberChanged;
1622                         break;
1623 
1624                     case SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION:
1625                     case SWITCH_CAUSE_SWITCH_CONGESTION:
1626 
1627                     case SWITCH_CAUSE_NORMAL_CLEARING:
1628                     case SWITCH_CAUSE_NORMAL_UNSPECIFIED:
1629                     case SWITCH_CAUSE_CALL_AWARDED_DELIVERED: /* ?? */
1630                         // this preserves semantics..
1631                         k3l_fail = kgbVeCongestion;
1632                         break;
1633 
1634                     case SWITCH_CAUSE_UNALLOCATED_NUMBER:
1635                     case SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET:
1636                     case SWITCH_CAUSE_NO_ROUTE_DESTINATION:
1637                     case SWITCH_CAUSE_INVALID_NUMBER_FORMAT:
1638                     case SWITCH_CAUSE_INVALID_GATEWAY:
1639                     case SWITCH_CAUSE_INVALID_URL:
1640                     case SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED:
1641                     case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION:
1642 
1643                     case SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL:
1644                     case SWITCH_CAUSE_CHANNEL_UNACCEPTABLE:
1645                     case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER:
1646                     case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER:
1647                     case SWITCH_CAUSE_GATEWAY_DOWN:
1648                     case SWITCH_CAUSE_FACILITY_REJECTED:
1649                     case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED:
1650                     case SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED:
1651 
1652                     case SWITCH_CAUSE_USER_BUSY:
1653                     case SWITCH_CAUSE_NO_USER_RESPONSE:
1654                     case SWITCH_CAUSE_CALL_REJECTED:
1655                     default:
1656                         k3l_fail = kgbVeBusy;
1657                         break;
1658                 }
1659 
1660                 handled = true;
1661                 break;
1662 
1663         }
1664 
1665         if (!handled)
1666             throw std::runtime_error("");
1667     }
1668     catch(...)
1669     {
1670         LOG(ERROR,PVT_FMT(_target, "country signaling not found, unable to report R2 hangup code."));
1671     }
1672 
1673     return k3l_fail;
1674 }
1675 
callFailFromCause(int cause)1676 int BoardE1::KhompPvtISDN::callFailFromCause(int cause)
1677 {
1678     int k3l_fail = -1; // default
1679 
1680     if (cause <= 127)
1681         k3l_fail = cause;
1682     else
1683         k3l_fail = kq931cInterworking;
1684 
1685     return k3l_fail;
1686 }
1687 
sendRingBackStatus(int rb_value)1688 RingbackDefs::RingbackStType BoardE1::KhompPvtR2::sendRingBackStatus(int rb_value)
1689 {
1690     DBG(FUNC,PVT_FMT(_target, "(p=%p) this is the r2 ringback procedure") % this);
1691 
1692     std::string cause = (rb_value == -1 ? "" : STG(FMT("r2_cond_b=\"%d\"") % rb_value));
1693     return (command(KHOMP_LOG, CM_RINGBACK, cause.c_str()) ?
1694             RingbackDefs::RBST_SUCCESS : RingbackDefs::RBST_FAILURE);
1695 }
1696 
sendPreAudio(int rb_value)1697 bool BoardE1::KhompPvtR2::sendPreAudio(int rb_value)
1698 {
1699     DBG(FUNC,PVT_FMT(_target, "must send R2 preaudio ?"));
1700     if(!KhompPvtE1::sendPreAudio(rb_value))
1701         return false;
1702 
1703 
1704     DBG(FUNC,PVT_FMT(_target, "doing the R2 pre_connect wait..."));
1705 
1706     /* wait some ms, just to be sure the command has been sent. */
1707     usleep(Opt::_options._r2_preconnect_wait()* 1000);
1708 
1709     if (call()->_flags.check(Kflags::HAS_PRE_AUDIO))
1710     {
1711         DBG(FUNC, PVT_FMT(target(), "(p=%p) already pre_connect") % this);
1712         return true;
1713     }
1714     else
1715     {
1716         bool result = command(KHOMP_LOG, CM_PRE_CONNECT);
1717 
1718         if (result)
1719             call()->_flags.set(Kflags::HAS_PRE_AUDIO);
1720 
1721         return result;
1722     }
1723 }
1724 
numberDialTimer(Board::KhompPvt * pvt)1725 void BoardE1::KhompPvtR2::numberDialTimer(Board::KhompPvt * pvt)
1726 {
1727     try
1728     {
1729         ScopedPvtLock lock(pvt);
1730 
1731         if (!pvt->call()->_flags.check(Kflags::NUMBER_DIAL_ONGOING) ||
1732              pvt->call()->_flags.check(Kflags::NUMBER_DIAL_FINISHD))
1733         {
1734             return;
1735         }
1736 
1737         pvt->call()->_flags.set(Kflags::NUMBER_DIAL_FINISHD);
1738 
1739         static_cast<BoardE1::KhompPvtR2*>(pvt)->callR2()->_incoming_exten.clear();
1740         pvt->command(KHOMP_LOG, CM_END_OF_NUMBER);
1741     }
1742     catch (...)
1743     {
1744         // TODO: log something.
1745     }
1746 }
1747 
indicateRinging()1748 bool BoardE1::KhompPvtR2::indicateRinging()
1749 {
1750     DBG(FUNC, PVT_FMT(_target, "(R2) c"));
1751 
1752     bool ret = false;
1753     try
1754     {
1755         ScopedPvtLock lock(this);
1756 
1757         /* already playing! */
1758         if (call()->_indication != INDICA_NONE)
1759         {
1760             DBG(FUNC, PVT_FMT(_target, "(R2) r (already playing something: %d)") % call()->_indication);
1761             return false;
1762         }
1763 
1764         // any collect calls ?
1765         setCollectCall();
1766 
1767         call()->_indication = INDICA_RING;
1768 
1769         bool send_ringback = true;
1770 
1771         if (!call()->_flags.check(Kflags::CONNECTED))
1772         {
1773             int ringback_value = RingbackDefs::RB_SEND_DEFAULT;
1774 
1775             bool do_drop_call = Opt::_options._drop_collect_call()
1776                                         || call()->_flags.check(Kflags::DROP_COLLECT);
1777 
1778             if (do_drop_call && call()->_collect_call)
1779             {
1780                 ringback_value = kgbBusy;
1781                 DBG(FUNC, PVT_FMT(_target, "ringback value adjusted to refuse collect call: %d") % ringback_value);
1782             }
1783 
1784             const char *condition_string = getFSChannelVar("KR2SendCondition");
1785 
1786             try
1787             {
1788                 if (condition_string)
1789                 {
1790                     ringback_value = Strings::toulong(condition_string);
1791                     DBG(FUNC, PVT_FMT(_target, "KR2SendCondition adjusted ringback value to %d") % ringback_value);
1792                 }
1793             }
1794             catch (Strings::invalid_value e)
1795             {
1796                 LOG(ERROR, PVT_FMT(_target, "invalid value '%s', adjusted in KR2SendCondition: not a valid number.")
1797                         % condition_string);
1798             }
1799 
1800             if (Opt::_options._r2_strict_behaviour())
1801             {
1802                 /* send ringback too? */
1803                 send_ringback = sendPreAudio(ringback_value);
1804 
1805                 if (!send_ringback)
1806                 {
1807                     /* warn the developer which may be debugging some "i do not have ringback!" issue. */
1808                     DBG(FUNC, PVT_FMT(_target, "not sending pre connection audio"));
1809                 }
1810 
1811                 call()->_flags.clear(Kflags::NEEDS_RINGBACK_CMD);
1812             }
1813 
1814         }
1815 
1816         if (send_ringback)
1817         {
1818             DBG(FUNC, PVT_FMT(_target, "Send ringback!"));
1819 
1820             call()->_flags.set(Kflags::GEN_CO_RING);
1821             call()->_idx_co_ring = Board::board(_target.device)->_timers.add(Opt::_options._ringback_co_delay(), &Board::KhompPvt::coRingGen,this);
1822 
1823             /* start grabbing audio */
1824             startListen();
1825 
1826             /* start stream if it is not already */
1827             startStream();
1828 
1829             ret = true;
1830         }
1831 
1832     }
1833     catch (ScopedLockFailed & err)
1834     {
1835         LOG(ERROR, PVT_FMT(_target, "(R2) r (unable to lock %s!)") % err._msg.c_str() );
1836         return false;
1837     }
1838     catch(Board::KhompPvt::InvalidSwitchChannel & err)
1839     {
1840         LOG(ERROR,PVT_FMT(_target, "(R2) r (%s)") % err._msg.c_str());
1841         return false;
1842     }
1843     catch (K3LAPITraits::invalid_device & err)
1844     {
1845         LOG(ERROR, PVT_FMT(_target, "(R2) r (unable to get device: %d!)") % err.device);
1846         return false;
1847     }
1848 
1849     DBG(FUNC, PVT_FMT(_target, "(R2) r"));
1850     return ret;
1851 }
1852 
onNewCall(K3L_EVENT * e)1853 bool BoardE1::KhompPvtR2::onNewCall(K3L_EVENT *e)
1854 {
1855     DBG(FUNC,PVT_FMT(_target, "(R2) c"));
1856 
1857     std::string r2_categ_a;
1858 
1859     int status = Globals::k3lapi.get_param(e, "r2_categ_a", r2_categ_a);
1860 
1861     try
1862     {
1863         ScopedPvtLock lock(this);
1864 
1865         if (status == ksSuccess && !r2_categ_a.empty())
1866         {
1867 
1868             try
1869             {
1870                 callR2()->_r2_category = Strings::toulong(r2_categ_a);
1871             }
1872             catch (Strings::invalid_value e)
1873             {
1874                 /* do nothing */
1875             };
1876 
1877             /* channel will know if is a collect call or not */
1878             if (callR2()->_r2_category == kg2CollectCall)
1879             {
1880                 call()->_collect_call = true;
1881             }
1882         }
1883 
1884         bool ret = KhompPvtE1::onNewCall(e);
1885 
1886         if(!ret)
1887             return false;
1888 
1889         if (!Opt::_options._r2_strict_behaviour())
1890         {
1891             bool do_drop_collect = Opt::_options._drop_collect_call();
1892             const char* drop_str = getFSGlobalVar("KDropCollectCall");
1893 
1894             if(checkTrueString(drop_str))
1895             {
1896                 do_drop_collect = true;
1897                 call()->_flags.set(Kflags::DROP_COLLECT);
1898                 DBG(FUNC,PVT_FMT(_target, "Setting DROP_COLLECT flag"));
1899             }
1900 
1901             freeFSGlobalVar(&drop_str);
1902 
1903             // keeping the hardcore mode
1904             if (do_drop_collect && call()->_collect_call)
1905             {
1906                 // kill, kill, kill!!!
1907                 DBG(FUNC,PVT_FMT(_target, "dropping collect call at onNewCall"));
1908                 sendRingBackStatus(callFailFromCause(SWITCH_CAUSE_CALL_REJECTED));
1909                 usleep(75000);
1910             }
1911             else
1912             {
1913                 // send ringback too!
1914                 sendPreAudio(RingbackDefs::RB_SEND_DEFAULT);
1915                 startStream();
1916             }
1917         }
1918         else
1919         {
1920             _call->_flags.set(Kflags::NEEDS_RINGBACK_CMD);
1921         }
1922     }
1923     catch(ScopedLockFailed & err)
1924     {
1925         LOG(ERROR, PVT_FMT(target(), "(R2) r (unable to lock %s!)") % err._msg.c_str() );
1926         return false;
1927     }
1928 
1929     DBG(FUNC,PVT_FMT(_target, "(R2) r"));
1930 
1931     return true;
1932 }
1933 
onCallSuccess(K3L_EVENT * e)1934 bool BoardE1::KhompPvtR2::onCallSuccess(K3L_EVENT *e)
1935 {
1936     try
1937     {
1938         ScopedPvtLock lock(this);
1939 
1940         if(e->AddInfo > 0)
1941         {
1942             callR2()->_r2_condition = e->AddInfo;
1943             setFSChannelVar("KR2GotCondition", Verbose::signGroupB((KSignGroupB)callR2()->_r2_condition).c_str());
1944         }
1945 
1946         KhompPvtE1::onCallSuccess(e);
1947 
1948     }
1949     catch (ScopedLockFailed & err)
1950     {
1951         LOG(ERROR, PVT_FMT(target(), "unable to lock %s!") % err._msg.c_str() );
1952         return false;
1953     }
1954     catch(Board::KhompPvt::InvalidSwitchChannel & err)
1955     {
1956         LOG(ERROR,PVT_FMT(_target, "%s") % err._msg.c_str());
1957         return false;
1958     }
1959 
1960     return true;
1961 }
1962 
onCallFail(K3L_EVENT * e)1963 bool BoardE1::KhompPvtR2::onCallFail(K3L_EVENT *e)
1964 {
1965     bool ret = true;
1966 
1967     try
1968     {
1969         ScopedPvtLock lock(this);
1970 
1971         if(e->AddInfo > 0)
1972         {
1973             callR2()->_r2_condition = e->AddInfo;
1974             setFSChannelVar("KR2GotCondition", Verbose::signGroupB((KSignGroupB)callR2()->_r2_condition).c_str());
1975         }
1976 
1977         setHangupCause(causeFromCallFail(e->AddInfo),true);
1978 
1979         ret = KhompPvtE1::onCallFail(e);
1980 
1981     }
1982     catch (ScopedLockFailed & err)
1983     {
1984         LOG(ERROR, PVT_FMT(target(), "unable to lock %s!") % err._msg.c_str() );
1985         return false;
1986     }
1987     catch(Board::KhompPvt::InvalidSwitchChannel & err)
1988     {
1989         LOG(ERROR,PVT_FMT(_target, "%s") % err._msg.c_str());
1990         return false;
1991     }
1992 
1993     return ret;
1994 }
1995 
onNumberDetected(K3L_EVENT * e)1996 bool BoardE1::KhompPvtR2::onNumberDetected(K3L_EVENT *e)
1997 {
1998     DBG(FUNC, PVT_FMT(_target, "(digit=%d) c") % e->AddInfo);
1999 
2000     try
2001     {
2002         ScopedPvtLock lock(this);
2003 
2004         if (call()->_flags.check(Kflags::NUMBER_DIAL_FINISHD))
2005             return false;
2006 
2007         if (!call()->_flags.check(Kflags::NUMBER_DIAL_ONGOING))
2008         {
2009             DBG(FUNC, PVT_FMT(_target, "incoming number start..."));
2010 
2011             call()->_flags.set(Kflags::NUMBER_DIAL_ONGOING);
2012             callR2()->_incoming_exten.clear();
2013 
2014             callR2()->_idx_number_dial = Board::board(_target.device)->_timers.add(4000,
2015                 &BoardE1::KhompPvtR2::numberDialTimer, this, TM_VAL_CALL);
2016         }
2017         else
2018         {
2019             Board::board(_target.device)->_timers.restart(callR2()->_idx_number_dial);
2020         }
2021 
2022         callR2()->_incoming_exten += e->AddInfo;
2023 
2024         DBG(FUNC, PVT_FMT(_target, "incoming exten %s") % callR2()->_incoming_exten);
2025 
2026         /* begin context adjusting + processing */
2027         MatchExtension::ContextListType contexts;
2028 
2029         validContexts(contexts);
2030 
2031         /* temporary */
2032         std::string tmp_exten;
2033         std::string tmp_context;
2034         std::string tmp_orig("");
2035 
2036         switch (MatchExtension::findExtension(tmp_exten, tmp_context, contexts, callR2()->_incoming_exten,tmp_orig, false, false))
2037         {
2038             case MatchExtension::MATCH_EXACT:
2039             case MatchExtension::MATCH_NONE:
2040                 call()->_flags.set(Kflags::NUMBER_DIAL_FINISHD);
2041 
2042                 DBG(FUNC,FMT("incoming exten matched: %s") % callR2()->_incoming_exten);
2043 
2044                 callR2()->_incoming_exten.clear();
2045                 command(KHOMP_LOG,CM_END_OF_NUMBER);
2046                 break;
2047 
2048             case MatchExtension::MATCH_MORE:
2049                 DBG(FUNC, "didn't match exact extension, waiting...");
2050                 // cannot say anything exact about the number, do nothing...
2051                 break;
2052         }
2053     }
2054     catch (ScopedLockFailed & err)
2055     {
2056         LOG(ERROR, PVT_FMT(target(), "unable to lock %s!") % err._msg.c_str() );
2057         return false;
2058     }
2059     catch (K3LAPITraits::invalid_device & err)
2060     {
2061         LOG(ERROR, PVT_FMT(_target, "unable to get device: %d!") % err.device);
2062         return false;
2063     }
2064 
2065     return true;
2066 }
2067 
application(ApplicationType type,switch_core_session_t * session,const char * data)2068 bool BoardE1::KhompPvtFlash::application(ApplicationType type, switch_core_session_t * session, const char *data)
2069 {
2070     switch(type)
2071     {
2072         case USER_TRANSFER:
2073             return _transfer->userTransfer(session, data);
2074         default:
2075             return KhompPvtR2::application(type, session, data);
2076     }
2077 
2078     return true;
2079 }
2080 
sendDtmf(std::string digit)2081 bool BoardE1::KhompPvtFlash::sendDtmf(std::string digit)
2082 {
2083     if(_transfer->checkUserXferUnlocked(digit))
2084     {
2085         DBG(FUNC, PVT_FMT(target(), "started (or waiting for) an user xfer"));
2086         return true;
2087     }
2088 
2089     bool ret = KhompPvtR2::sendDtmf(callFlash()->_digits_buffer);
2090 
2091     callFlash()->_digits_buffer.clear();
2092 
2093     return ret;
2094 }
2095 
generateNseqMap()2096 OrigToNseqMapType BoardE1::KhompPvtFXS::generateNseqMap()
2097 {
2098     OrigToNseqMapType fxs_nseq; /* sequence numbers on FXS */
2099 
2100     fxs_nseq.insert(OrigToNseqPairType("", 0)); /* global sequence */
2101 
2102     for (BoardToOrigMapType::iterator i = Opt::_fxs_orig_base.begin(); i != Opt::_fxs_orig_base.end(); i++)
2103     {
2104         fxs_nseq.insert(OrigToNseqPairType((*i).second, 0));
2105     }
2106 
2107     return fxs_nseq;
2108 }
2109 
2110 
load(OrigToNseqMapType & fxs_nseq)2111 void BoardE1::KhompPvtFXS::load(OrigToNseqMapType & fxs_nseq)
2112 {
2113     BoardToOrigMapType::iterator it1 = Opt::_fxs_orig_base.find(_target.device);
2114     OrigToNseqMapType::iterator  it2;
2115 
2116     std::string orig_base("invalid"); /* will have orig base */
2117 
2118     if (it1 == Opt::_fxs_orig_base.end())
2119     {
2120         it2 = fxs_nseq.find("");
2121         orig_base = Opt::_options._fxs_global_orig_base();
2122     }
2123     else
2124     {
2125         it2 = fxs_nseq.find((*it1).second);
2126         orig_base = (*it1).second;
2127     }
2128 
2129     if (it2 == fxs_nseq.end())
2130     {
2131         LOG(ERROR, PVT_FMT(_target, "could not find sequence number for FXS channel"));
2132 
2133         /* Ok, load the default options */
2134         loadOptions();
2135     }
2136     else
2137     {
2138         try
2139         {
2140             /* generate orig_addr, padding to the original size (adding zeros at left) */
2141             _fxs_fisical_addr = padOrig(orig_base, (*it2).second);
2142 
2143             /* Set this branch options to get right callerid before mapping */
2144             loadOptions();
2145 
2146             /* makes a "reverse mapping" for Dial using 'r' identifiers */
2147             Opt::_fxs_branch_map.insert(BranchToObjectPairType(_fxs_orig_addr,
2148                 ObjectIdType(_target.device, _target.object)));
2149 
2150             /* increment sequence number */
2151             ++((*it2).second);
2152         }
2153         catch (Strings::invalid_value e)
2154         {
2155             LOG(ERROR, PVT_FMT(_target, "expected an integer, got string '%s'")
2156                 % e.value() );
2157         }
2158     }
2159 }
2160 
loadOptions()2161 void BoardE1::KhompPvtFXS::loadOptions()
2162 {
2163     /* the fxs_orig_addr can be reset on parse_branch_options */
2164     _fxs_orig_addr = _fxs_fisical_addr;
2165 
2166     /* Initialize fxs default options */
2167     _calleridname.clear();
2168     //_amaflags = Opt::_amaflags;
2169     _callgroup = Opt::_options._callgroup();
2170     _pickupgroup = Opt::_options._pickupgroup();
2171     _context.clear();
2172     _input_volume = Opt::_options._input_volume();
2173     _output_volume = Opt::_options._output_volume();
2174     _mailbox.clear();
2175     _flash = Opt::_options._flash();
2176 
2177     BranchToOptMapType::iterator it3 = Opt::_branch_options.find(_fxs_orig_addr);
2178 
2179     if (it3 != Opt::_branch_options.end())
2180     {
2181         parseBranchOptions(it3->second);
2182     }
2183 
2184     //TODO: Implementar o setVolume para levar em consideracao que o
2185     //       padrao pode ser o da FXS
2186     if (_input_volume != Opt::_options._input_volume())
2187         setVolume("input", _input_volume);
2188     if (_output_volume != Opt::_options._output_volume())
2189         setVolume("output", _output_volume);
2190 }
2191 
parseBranchOptions(std::string options_str)2192 bool BoardE1::KhompPvtFXS::parseBranchOptions(std::string options_str)
2193 {
2194     Strings::vector_type options;
2195     Strings::tokenize(options_str, options, "|/");
2196 
2197     if (options.size() < 1)
2198     {
2199         DBG(FUNC, PVT_FMT(_target, "[fxs-options] no options are set for branch %s.") %
2200                 _fxs_orig_addr.c_str());
2201         return false;
2202     }
2203 
2204     try
2205     {
2206         for (Strings::vector_type::iterator it = options.begin(); it != options.end(); it++)
2207         {
2208             Strings::vector_type par;
2209             Strings::tokenize(Strings::trim(*it), par, ":");
2210 
2211             if ( par.size() != 2 )
2212             {
2213                 LOG(WARNING, PVT_FMT(_target, "[fxs-options] error on parsing options for branch %s.") % _fxs_orig_addr.c_str());
2214                 return false;
2215             }
2216 
2217             std::string opt_name = Strings::trim(par.at(0));
2218             std::string opt_value = Strings::trim(par.at(1));
2219 
2220             if (opt_name == "pickupgroup")
2221             {
2222                _pickupgroup = opt_value;//ast_get_group(opt_value.c_str());
2223             }
2224             else if (opt_name == "callgroup")
2225             {
2226                _callgroup = opt_value;//ast_get_group(opt_value.c_str());
2227             }
2228             /*
2229                else if (opt_name == "amaflags")
2230                {
2231                int amaflags = ast_cdr_amaflags2int(opt_value.c_str());
2232 
2233                if (amaflags < 0)
2234                DBG(FUNC, PVT_FMT(_target, "[fxs-options] invalid AMA flags on branch %s.") % _fxs_orig_addr.c_str());
2235                else
2236                _amaflags = amaflags;
2237                }
2238             */
2239             else if (opt_name == "context")
2240             {
2241                 _context = opt_value;
2242             }
2243             else if (opt_name == "input-volume")
2244             {
2245                 long long volume = Strings::tolong(opt_value);
2246 
2247                 if ( (volume < -10) || (volume > 10) )
2248                 {
2249                     DBG(FUNC, PVT_FMT(_target, "[fxs-options] input-volume on branch %s.") % _fxs_orig_addr.c_str());
2250                 }
2251                 else
2252                 {
2253                     _input_volume = volume;
2254                 }
2255             }
2256             else if (opt_name == "output-volume")
2257             {
2258                 long long volume = Strings::tolong(opt_value);
2259 
2260                 if ( (volume < -10) || (volume > 10) )
2261                 {
2262                     DBG(FUNC, PVT_FMT(_target, "[fxs-options] ouput-volume on branch %s.") % _fxs_orig_addr.c_str());
2263                 }
2264                 else
2265                 {
2266                     _output_volume = volume;
2267                 }
2268             }
2269             else if (opt_name == "language")
2270             {
2271                 _language = opt_value;
2272             }
2273             else if (opt_name == "mohclass")
2274             {
2275                 _mohclass = opt_value;
2276             }
2277             else if (opt_name == "accountcode")
2278             {
2279                 _accountcode = opt_value;
2280             }
2281             else if (opt_name == "calleridnum") // conscious ultra chuncho!
2282             {
2283                 BranchToOptMapType::iterator it3 = Opt::_branch_options.find(_fxs_orig_addr);
2284 
2285                 if (it3 != Opt::_branch_options.end())
2286                 {
2287                     Opt::_branch_options.insert(BranchToOptPairType(opt_value, it3->second));
2288 
2289                     Opt::_branch_options.erase(it3);
2290                 }
2291 
2292                 _fxs_orig_addr = opt_value;
2293             }
2294             else if (opt_name == "calleridname")
2295             {
2296                 _calleridname = opt_value;
2297             }
2298             else if (opt_name == "mailbox")
2299             {
2300                 _mailbox = opt_value;
2301             }
2302             else if (opt_name == "flash-to-digits")
2303             {
2304                 _flash = opt_value;
2305             }
2306             else
2307             {
2308                 DBG(FUNC, PVT_FMT(_target, "[fxs-options] invalid option on branch %s: \"%s\".") % _fxs_orig_addr.c_str() % opt_name.c_str());
2309             }
2310         }
2311     }
2312     catch (Strings::invalid_value e)
2313     {
2314         LOG(WARNING, PVT_FMT(_target, "[fxs-options] number expected on Khomp configuration file, got '%s'.") % e.value().c_str());
2315         return false;
2316     }
2317 
2318     return true;
2319 }
2320 
alloc()2321 bool BoardE1::KhompPvtFXS::alloc()
2322 {
2323     DBG(FUNC, PVT_FMT(_target, "(FXS) c"));
2324 
2325     callFXS()->_flags.set(Kflags::FXS_DIAL_FINISHD);
2326 
2327     if(justStart(/*need_context*/) != SWITCH_STATUS_SUCCESS)
2328     {
2329         int fail_code = callFailFromCause(SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL);
2330         setHangupCause(SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL);
2331         cleanup(CLN_FAIL);
2332         reportFailToReceive(fail_code);
2333         LOG(ERROR, PVT_FMT(target(), "(FXS) r (Initilization Error on start!)"));
2334         return false;
2335     }
2336 
2337     startListen();
2338     startStream();
2339 
2340     /* do this procedures early (as audio is already being heard) */
2341     dtmfSuppression(Opt::_options._out_of_band_dtmfs() && !callFXS()->_flags.check(Kflags::FAX_DETECTED));
2342     echoCancellation(Opt::_options._echo_canceller() && !callFXS()->_flags.check(Kflags::FAX_DETECTED));
2343     autoGainControl(Opt::_options._auto_gain_control() && !callFXS()->_flags.check(Kflags::FAX_DETECTED));
2344 
2345     //TODO: NEED RECORD HERE !?
2346     /* if it does not need context, probably it's a pickupcall and will
2347        not pass throw setup_connection, so we start recording here*/
2348     //if (!need_context && K::opt::recording && !pvt->is_recording)
2349     //startRecord();
2350 
2351     DBG(FUNC, "(FXS) r");
2352     return true;
2353 }
2354 
onSeizureStart(K3L_EVENT * e)2355 bool BoardE1::KhompPvtFXS::onSeizureStart(K3L_EVENT *e)
2356 {
2357     DBG(FUNC, PVT_FMT(_target, "(FXS) c"));
2358 
2359     bool ret = true;
2360 
2361     try
2362     {
2363         ScopedPvtLock lock(this);
2364 
2365         /* we always have audio */
2366         call()->_flags.set(Kflags::HAS_PRE_AUDIO);
2367 
2368         ret = KhompPvt::onSeizureStart(e);
2369 
2370         if (justAlloc(true) != SWITCH_STATUS_SUCCESS)
2371         {
2372             int fail_code = callFailFromCause(SWITCH_CAUSE_UNALLOCATED_NUMBER);
2373             setHangupCause(SWITCH_CAUSE_UNALLOCATED_NUMBER);
2374             cleanup(CLN_FAIL);
2375             reportFailToReceive(fail_code);
2376             LOG(ERROR,PVT_FMT(_target, "(FXS) r (Initilization Error on alloc!)"));
2377             return false;
2378         }
2379 
2380         /* disable to avoid problems with DTMF detection */
2381         echoCancellation(false);
2382         autoGainControl(false);
2383 
2384         call()->_orig_addr = _fxs_orig_addr;
2385 
2386         OrigToDestMapType::iterator i = Opt::_fxs_hotline.find(_fxs_orig_addr);
2387 
2388         if (i != Opt::_fxs_hotline.end())
2389         {
2390             /* make it burn! */
2391             call()->_dest_addr = (*i).second;
2392             alloc();
2393         }
2394         else
2395         {
2396             /* normal line */
2397             if (!_mailbox.empty() /*&& (ast_app_has_voicemail(pvt->fxs_opt.mailbox.c_str(), NULL) == 1)*/)
2398                 startCadence(PLAY_VM_TONE);
2399             else
2400                 startCadence(PLAY_PBX_TONE);
2401 
2402             call()->_flags.clear(Kflags::FXS_DIAL_ONGOING);
2403             call()->_flags.set(Kflags::FXS_OFFHOOK);
2404         }
2405     }
2406     catch (ScopedLockFailed & err)
2407     {
2408         LOG(ERROR,PVT_FMT(_target, "(FXS) r (unable to lock %s!)") % err._msg.c_str() );
2409         return false;
2410     }
2411 
2412     DBG(FUNC, PVT_FMT(_target, "(FXS) r"));
2413 
2414     return ret;
2415 }
2416 
onCallSuccess(K3L_EVENT * e)2417 bool BoardE1::KhompPvtFXS::onCallSuccess(K3L_EVENT *e)
2418 {
2419     DBG(FUNC, PVT_FMT(_target, "(FXS) c"));
2420 
2421     bool ret;
2422 
2423     try
2424     {
2425         ScopedPvtLock lock(this);
2426 
2427         ret = KhompPvt::onCallSuccess(e);
2428 
2429         if (call()->_pre_answer)
2430         {
2431             dtmfSuppression(Opt::_options._out_of_band_dtmfs());
2432 
2433             startListen();
2434             startStream();
2435             switch_channel_mark_pre_answered(getFSChannel());
2436         }
2437         else
2438         {
2439             call()->_flags.set(Kflags::GEN_PBX_RING);
2440             call()->_idx_pbx_ring = Board::board(_target.device)->_timers.add(
2441                     Opt::_options._ringback_pbx_delay(),
2442                     &Board::KhompPvt::pbxRingGen,
2443                     this,
2444                     TM_VAL_CALL);
2445         }
2446 
2447     }
2448     catch (ScopedLockFailed & err)
2449     {
2450         LOG(ERROR, PVT_FMT(_target, "(FXS) r (unable to lock %s!)") % err._msg.c_str() );
2451         return false;
2452     }
2453     catch (K3LAPITraits::invalid_device & err)
2454     {
2455         LOG(ERROR, PVT_FMT(_target, "(FXS) r (unable to get device: %d!)") % err.device);
2456         return false;
2457     }
2458     catch (Board::KhompPvt::InvalidSwitchChannel & err)
2459     {
2460         LOG(ERROR, PVT_FMT(target(), "(FXS) r (%s)") % err._msg.c_str() );
2461         return false;
2462     }
2463 
2464     DBG(FUNC, PVT_FMT(_target, "(FXS) r"));
2465 
2466     return ret;
2467 }
2468 
dialTimer(KhompPvt * pvt)2469 void BoardE1::KhompPvtFXS::dialTimer(KhompPvt * pvt)
2470 {
2471     DBG(FUNC, PVT_FMT(pvt->target(), "FXS Dial timer"));
2472 
2473     try
2474     {
2475         ScopedPvtLock lock(pvt);
2476 
2477         KhompPvtFXS * pvt_fxs = static_cast<BoardE1::KhompPvtFXS*>(pvt);
2478 
2479         if(!pvt_fxs->callFXS()->_flags.check(Kflags::FXS_DIAL_ONGOING)
2480             || pvt_fxs->callFXS()->_flags.check(Kflags::FXS_DIAL_FINISHD))
2481             return;
2482 
2483         pvt_fxs->call()->_dest_addr = pvt_fxs->callFXS()->_incoming_exten;
2484         pvt_fxs->alloc();
2485 
2486     }
2487     catch (ScopedLockFailed & err)
2488     {
2489         LOG(ERROR, PVT_FMT(pvt->target(), "unable to lock %s!") % err._msg.c_str());
2490     }
2491 
2492 }
2493 
2494 /*
2495 void BoardE1::KhompPvtFXS::transferTimer(KhompPvt * pvt)
2496 {
2497     DBG(FUNC, PVT_FMT(pvt->target(), "c"));
2498 
2499     try
2500     {
2501         ScopedPvtLock lock(pvt);
2502 
2503         KhompPvtFXS * pvt_fxs = static_cast<BoardE1::KhompPvtFXS*>(pvt);
2504 
2505         if(!pvt_fxs->callFXS()->_flags.check(Kflags::FXS_FLASH_TRANSFER))
2506         {
2507             DBG(FUNC, PVT_FMT(pvt->target(), "r (Flag not set)"));
2508             return;
2509         }
2510 
2511         pvt_fxs->callFXS()->_flags.clear(Kflags::FXS_FLASH_TRANSFER);
2512 
2513         if(pvt_fxs->callFXS()->_flash_transfer.empty())
2514         {
2515             DBG(FUNC, PVT_FMT(pvt->target(), "r (Number is empty)"));
2516 
2517             if(!pvt_fxs->stopTransfer())
2518             {
2519                 pvt_fxs->cleanup(KhompPvt::CLN_HARD);
2520                 DBG(FUNC, PVT_FMT(pvt_fxs->target(), "r (unable to stop transfer)"));
2521                 return;
2522             }
2523 
2524             return;
2525         }
2526 
2527         // begin context adjusting + processing
2528         MatchExtension::ContextListType contexts;
2529 
2530         pvt_fxs->validContexts(contexts);
2531 
2532         std::string tmp_exten;
2533         std::string tmp_context;
2534 
2535         switch (MatchExtension::findExtension(tmp_exten, tmp_context, contexts, pvt_fxs->callFXS()->_flash_transfer, pvt_fxs->call()->_orig_addr, false, false))
2536         {
2537             case MatchExtension::MATCH_EXACT:
2538             case MatchExtension::MATCH_MORE:
2539             {
2540                 pvt_fxs->callFXS()->_flash_transfer = tmp_exten;
2541                 DBG(FUNC,FMT("incoming exten matched: %s") % pvt_fxs->callFXS()->_flash_transfer);
2542 
2543                 if(!pvt_fxs->transfer(tmp_context))
2544                 {
2545                     pvt_fxs->cleanup(KhompPvt::CLN_HARD);
2546                     DBG(FUNC, PVT_FMT(pvt_fxs->target(), "r (unable to transfer)"));
2547                     return;
2548                 }
2549 
2550                 break;
2551             }
2552             case MatchExtension::MATCH_NONE:
2553             {
2554                 DBG(FUNC, PVT_FMT(pvt_fxs->target(), "match none!"));
2555 
2556                 if(!pvt_fxs->stopTransfer())
2557                 {
2558                     pvt_fxs->cleanup(KhompPvt::CLN_HARD);
2559                     DBG(FUNC, PVT_FMT(pvt_fxs->target(), "r (unable to stop transfer)"));
2560                     return;
2561                 }
2562 
2563                 break;
2564             }
2565         }
2566     }
2567     catch (ScopedLockFailed & err)
2568     {
2569         LOG(ERROR, PVT_FMT(pvt->target(), "r (unable to lock %s!)") % err._msg.c_str());
2570         return;
2571     }
2572 
2573     DBG(FUNC, PVT_FMT(pvt->target(), "r"));
2574 
2575 }
2576 */
2577 
onChannelRelease(K3L_EVENT * e)2578 bool BoardE1::KhompPvtFXS::onChannelRelease(K3L_EVENT *e)
2579 {
2580     DBG(FUNC, PVT_FMT(_target, "(FXS) c"));
2581 
2582     bool ret = true;
2583 
2584     try
2585     {
2586         ScopedPvtLock lock(this);
2587 
2588         /*
2589         if(!callFXS()->_uuid_other_session.empty() && session())
2590         {
2591 
2592             //switch_core_session_t *hold_session;
2593 
2594             //if ((hold_session = switch_core_session_locate(callFXS()->_uuid_other_session.c_str())))
2595             //{
2596             //    switch_channel_t * hold = switch_core_session_get_channel(hold_session);
2597             //    switch_channel_stop_broadcast(hold);
2598             //    switch_channel_wait_for_flag(hold, CF_BROADCAST, SWITCH_FALSE, 5000, NULL);
2599             //    switch_core_session_rwunlock(hold_session);
2600             //}
2601 
2602             try
2603             {
2604                 // get other side of the bridge
2605                 switch_core_session_t * peer_session = getFSLockedPartnerSession();
2606                 unlockPartner(peer_session);
2607                 DBG(FUNC, PVT_FMT(target(), "bridge with the new session"));
2608                 switch_ivr_uuid_bridge(getUUID(peer_session), callFXS()->_uuid_other_session.c_str());
2609 
2610             }
2611             catch(Board::KhompPvt::InvalidSwitchChannel & err)
2612             {
2613                 DBG(FUNC, PVT_FMT(target(), "no partner: %s!") % err._msg.c_str());
2614             }
2615 
2616             callFXS()->_uuid_other_session.clear();
2617         }
2618         */
2619 
2620         ret = KhompPvt::onChannelRelease(e);
2621 
2622     }
2623     catch(ScopedLockFailed & err)
2624     {
2625         LOG(ERROR, PVT_FMT(target(), "(FXS) r (unable to lock %s!)") % err._msg.c_str() );
2626         return false;
2627     }
2628 
2629     DBG(FUNC, PVT_FMT(_target, "(FXS) r"));
2630     return ret;
2631 
2632 }
2633 /*
2634 bool BoardE1::KhompPvtFXS::startTransfer()
2635 {
2636     DBG(FUNC, PVT_FMT(target(), "c"));
2637 
2638     try
2639     {
2640         switch_core_session_t *peer_session = getFSLockedPartnerSession();
2641         switch_channel_t *peer_channel = getFSChannel(peer_session);
2642 
2643         const char *stream = NULL;
2644 
2645         if (!(stream = getFSChannelVar(peer_channel, SWITCH_HOLD_MUSIC_VARIABLE)))
2646         {
2647             stream = "silence";
2648         }
2649 
2650         unlockPartner(peer_session);
2651 
2652         DBG(FUNC, PVT_FMT(target(), "stream=%s") % stream);
2653 
2654         if (stream && strcasecmp(stream, "silence"))
2655         {
2656             // Freeswitch not get/put frames
2657             //switch_channel_set_flag(channel, CF_HOLD);
2658             switch_ivr_broadcast(getUUID(peer_session), stream, SMF_ECHO_ALEG | SMF_LOOP);
2659         }
2660 
2661         callFXS()->_flags.set(Kflags::FXS_FLASH_TRANSFER);
2662 
2663         startCadence(PLAY_PBX_TONE);
2664 
2665         callFXS()->_idx_transfer = Board::board(_target.device)->_timers.add(Opt::_options._fxs_digit_timeout()* 1000, &BoardE1::KhompPvtFXS::transferTimer, this, TM_VAL_CALL);
2666 
2667     }
2668     catch(Board::KhompPvt::InvalidSwitchChannel & err)
2669     {
2670         //cleanup(KhompPvt::CLN_HARD);
2671         LOG(ERROR, PVT_FMT(target(), "r (no valid partner %s!)") % err._msg.c_str());
2672         return false;
2673     }
2674     catch (K3LAPITraits::invalid_device & err)
2675     {
2676         LOG(ERROR, PVT_FMT(_target, "unable to get device: %d!") % err.device);
2677     }
2678 
2679     //switch_ivr_hold_uuid(switch_core_session_get_uuid(session()), NULL, SWITCH_TRUE);
2680     DBG(FUNC, PVT_FMT(target(), "r"));
2681 
2682     return true;
2683 }
2684 
2685 bool BoardE1::KhompPvtFXS::stopTransfer()
2686 {
2687     DBG(FUNC, PVT_FMT(target(), "c"));
2688 
2689     callFXS()->_flags.clear(Kflags::FXS_FLASH_TRANSFER);
2690 
2691     callFXS()->_flash_transfer.clear();
2692 
2693     stopCadence();
2694 
2695     try
2696     {
2697         Board::board(_target.device)->_timers.del(callFXS()->_idx_transfer);
2698     }
2699     catch (K3LAPITraits::invalid_device & err)
2700     {
2701         LOG(ERROR, PVT_FMT(_target, "unable to get device: %d!") % err.device);
2702     }
2703 
2704     try
2705     {
2706         // get other side of the bridge
2707         switch_core_session_t * peer_session = getFSLockedPartnerSession();
2708         switch_channel_t * peer_channel = getFSChannel(peer_session);
2709 
2710         switch_channel_stop_broadcast(peer_channel);
2711         switch_channel_wait_for_flag(peer_channel, CF_BROADCAST, SWITCH_FALSE, 5000, NULL);
2712 
2713         unlockPartner(peer_session);
2714 
2715         //switch_ivr_unhold_uuid(switch_core_session_get_uuid(session()));
2716     }
2717     catch(Board::KhompPvt::InvalidSwitchChannel & err)
2718     {
2719         LOG(ERROR, PVT_FMT(target(), "r (no valid partner %s!)") % err._msg.c_str());
2720         return false;
2721     }
2722 
2723     DBG(FUNC, PVT_FMT(target(), "r"));
2724     return true;
2725 }
2726 
2727 static switch_status_t xferHook(switch_core_session_t *session)
2728 {
2729     switch_channel_t *channel = switch_core_session_get_channel(session);
2730     switch_channel_state_t state = switch_channel_get_state(channel);
2731 
2732     DBG(FUNC, D("state change=%d") % state);
2733 
2734     if (state == CS_PARK)
2735     {
2736         switch_core_event_hook_remove_state_change(session, xferHook);
2737 
2738         BoardE1::KhompPvtFXS * pvt = static_cast<BoardE1::KhompPvtFXS*>(switch_core_session_get_private(session));
2739 
2740         if(!pvt)
2741         {
2742             DBG(FUNC, D("pvt is NULL"));
2743             return SWITCH_STATUS_FALSE;
2744         }
2745 
2746         try
2747         {
2748             ScopedPvtLock lock(pvt);
2749 
2750             if(!pvt->callFXS()->_uuid_other_session.empty())
2751             {
2752                 DBG(FUNC, D("bridge after park"));
2753                 std::string number = pvt->callFXS()->_uuid_other_session;
2754                 pvt->callFXS()->_uuid_other_session.clear();
2755 
2756                 switch_ivr_uuid_bridge(pvt->getUUID(), number.c_str());
2757             }
2758         }
2759         catch(ScopedLockFailed & err)
2760         {
2761             LOG(ERROR, PVT_FMT(pvt->target(), "unable to lock: %s!") %  err._msg.c_str());
2762             return SWITCH_STATUS_FALSE;
2763         }
2764         catch(Board::KhompPvt::InvalidSwitchChannel & err)
2765         {
2766             LOG(ERROR, PVT_FMT(pvt->target(), "%s!") %  err._msg.c_str());
2767             return SWITCH_STATUS_FALSE;
2768         }
2769 
2770     }
2771     else if (state == CS_HANGUP)
2772     {
2773         switch_core_event_hook_remove_state_change(session, xferHook);
2774 
2775         //BoardE1::KhompPvtFXS * pvt = static_cast<BoardE1::KhompPvtFXS*>(switch_core_session_get_private(session));
2776         //
2777         //if(!pvt)
2778         //{
2779         //    DBG(FUNC, D("pvt is NULL"));
2780         //    return SWITCH_STATUS_FALSE;
2781         //}
2782 
2783         //try
2784         //{
2785         //    ScopedPvtLock lock(pvt);
2786 
2787         //    if(!pvt->callFXS()->_uuid_other_session.empty())
2788         //    {
2789         //        DBG(FUNC, D("bridge after hangup"));
2790         //        std::string number = pvt->callFXS()->_uuid_other_session;
2791         //        pvt->callFXS()->_uuid_other_session.clear();
2792 
2793         //        switch_ivr_uuid_bridge(switch_core_session_get_uuid(session), number.c_str());
2794         //    }
2795         //}
2796         //catch(ScopedLockFailed & err)
2797         //{
2798         //   LOG(ERROR, PVT_FMT(pvt->target(), "unable to lock: %s!") %  err._msg.c_str());
2799         //}
2800 
2801     }
2802 
2803     return SWITCH_STATUS_SUCCESS;
2804 }
2805 
2806 bool BoardE1::KhompPvtFXS::transfer(std::string & context, bool blind)
2807 {
2808     DBG(FUNC, PVT_FMT(target(), "c"));
2809 
2810     callFXS()->_flags.clear(Kflags::FXS_FLASH_TRANSFER);
2811 
2812     std::string number = callFXS()->_flash_transfer;
2813     callFXS()->_flash_transfer.clear();
2814 
2815     try
2816     {
2817         Board::board(_target.device)->_timers.del(callFXS()->_idx_transfer);
2818     }
2819     catch (K3LAPITraits::invalid_device & err)
2820     {
2821         LOG(ERROR, PVT_FMT(_target, "unable to get device: %d!") % err.device);
2822     }
2823 
2824     try
2825     {
2826         // get other side of the bridge
2827         switch_core_session_t * peer_session = getFSLockedPartnerSession();
2828         switch_channel_t * peer_channel = getFSChannel(peer_session);
2829 
2830         switch_channel_stop_broadcast(peer_channel);
2831         switch_channel_wait_for_flag(peer_channel, CF_BROADCAST, SWITCH_FALSE, 5000, NULL);
2832 
2833         unlockPartner(peer_session);
2834 
2835         if(blind)
2836         {
2837             DBG(FUNC, PVT_FMT(_target, "Blind Transfer"));
2838             switch_ivr_session_transfer(peer_session, number.c_str(), Opt::_options._dialplan().c_str(), context.c_str());
2839         }
2840         else
2841         {
2842             DBG(FUNC, PVT_FMT(_target, "Attended Transfer"));
2843 
2844             if(!callFXS()->_uuid_other_session.empty())
2845             {
2846                 DBG(FUNC, PVT_FMT(target(), "second transfer, hang up session"));
2847             }
2848             else
2849             {
2850                 DBG(FUNC, PVT_FMT(target(), "first transfer"));
2851                 callFXS()->_uuid_other_session = getUUID(peer_session);
2852                 const char *stream = NULL;
2853 
2854                 if (!(stream = switch_channel_get_hold_music(peer_channel)))
2855                 {
2856                     stream = "silence";
2857                 }
2858 
2859                 DBG(FUNC, PVT_FMT(target(), "transfer stream=%s") % stream);
2860 
2861                 if (stream && strcasecmp(stream, "silence"))
2862                 {
2863                     std::string moh = STR(FMT("endless_playback:%s,park") % stream);
2864                     switch_ivr_session_transfer(peer_session, moh.c_str(), "inline", NULL);
2865                 }
2866                 else
2867                 {
2868                     switch_ivr_session_transfer(peer_session, "endless_playback:local_stream://moh,park", "inline", NULL);
2869                     //switch_ivr_session_transfer(peer_session, "park", "inline", NULL);
2870                 }
2871             }
2872 
2873             switch_channel_t * channel = getFSChannel();
2874             switch_channel_set_variable(channel, SWITCH_PARK_AFTER_BRIDGE_VARIABLE, "true");
2875             switch_core_event_hook_add_state_change(session(), xferHook);
2876 
2877             switch_ivr_session_transfer(session(), number.c_str(), Opt::_options._dialplan().c_str(), context.c_str());
2878 
2879             DBG(FUNC, PVT_FMT(target(), "Generating ring"));
2880             call()->_indication = INDICA_RING;
2881             call()->_flags.set(Kflags::GEN_CO_RING);
2882             startCadence(PLAY_RINGBACK);
2883 
2884 
2885             //try
2886             //{
2887             //    call()->_idx_co_ring = Board::board(_target.device)->_timers.add(Opt::_options._ringback_co_delay(), &Board::KhompPvt::coRingGen,this);
2888             //}
2889             //catch (K3LAPITraits::invalid_device & err)
2890             //{
2891              //   LOG(ERROR, PVT_FMT(_target, "unable to get device: %d!") % err.device);
2892             //}
2893 
2894         }
2895     }
2896     catch(Board::KhompPvt::InvalidSwitchChannel & err)
2897     {
2898         LOG(ERROR, PVT_FMT(target(), "r (no valid partner %s!)") % err._msg.c_str());
2899         return false;
2900     }
2901 
2902     DBG(FUNC, PVT_FMT(target(), "r"));
2903 
2904     return true;
2905 }
2906 */
2907 
onDtmfDetected(K3L_EVENT * e)2908 bool BoardE1::KhompPvtFXS::onDtmfDetected(K3L_EVENT *e)
2909 {
2910     DBG(FUNC, PVT_FMT(_target, "(FXS) c (dtmf=%c)") % (char) e->AddInfo);
2911 
2912     bool ret = true;
2913 
2914     try
2915     {
2916         ScopedPvtLock lock(this);
2917 
2918         if (call()->_flags.check(Kflags::IS_INCOMING) &&
2919                 callFXS()->_flags.check(Kflags::FXS_OFFHOOK) &&
2920                 !callFXS()->_flags.check(Kflags::FXS_DIAL_FINISHD))
2921         {
2922             DBG(FUNC, PVT_FMT(_target, "dialing"));
2923 
2924             if (call()->_cadence == PLAY_PBX_TONE)
2925             {
2926                 stopCadence();
2927             }
2928 
2929             if (call()->_cadence == PLAY_PUB_TONE)
2930             {
2931                 stopCadence();
2932                 //call()->_cadence = PLAY_NONE;
2933                 //mixer(KHOMP_LOG, 1, kmsGenerator, kmtSilence);
2934             }
2935 
2936             if (!callFXS()->_flags.check(Kflags::FXS_DIAL_ONGOING))
2937             {
2938                 DBG(FUNC, PVT_FMT(_target, "dialing started now, clearing stuff.."));
2939 
2940                 callFXS()->_flags.set(Kflags::FXS_DIAL_ONGOING);
2941 
2942                 callFXS()->_incoming_exten.clear();
2943 
2944                 mixer(KHOMP_LOG, 1, kmsGenerator, kmtSilence);
2945 
2946                 callFXS()->_idx_dial = Board::board(_target.device)->_timers.add(Opt::_options._fxs_digit_timeout()* 1000, &BoardE1::KhompPvtFXS::dialTimer, this, TM_VAL_CALL);
2947             }
2948             else
2949             {
2950                 Board::board(_target.device)->_timers.restart(callFXS()->_idx_dial);
2951             }
2952 
2953             callFXS()->_incoming_exten += e->AddInfo;
2954 
2955             /* begin context adjusting + processing */
2956             MatchExtension::ContextListType contexts;
2957 
2958             validContexts(contexts);
2959 
2960             std::string tmp_exten;
2961             std::string tmp_context;
2962 
2963             switch (MatchExtension::findExtension(tmp_exten, tmp_context, contexts, callFXS()->_incoming_exten, call()->_orig_addr, false, false))
2964             {
2965                 case MatchExtension::MATCH_EXACT:
2966                     callFXS()->_incoming_exten = tmp_exten;
2967                     DBG(FUNC,FMT("incoming exten matched: %s") % callFXS()->_incoming_exten);
2968                     Board::board(_target.device)->_timers.del(callFXS()->_idx_dial);
2969                     call()->_dest_addr = callFXS()->_incoming_exten;
2970                     call()->_incoming_context = tmp_context;
2971 
2972                     alloc();
2973                     break;
2974 
2975                 case MatchExtension::MATCH_MORE:
2976                     DBG(FUNC, PVT_FMT(target(), "match more..."));
2977 
2978                     /* can match, will match more, and it's an external call? */
2979                     for (DestVectorType::const_iterator i = Opt::_options._fxs_co_dialtone().begin(); i != Opt::_options._fxs_co_dialtone().end(); i++)
2980                     {
2981                         if (callFXS()->_incoming_exten == (*i))
2982                         {
2983                             startCadence(PLAY_PUB_TONE);
2984                             break;
2985                         }
2986                     }
2987 
2988                     break;
2989                 case MatchExtension::MATCH_NONE:
2990                     DBG(FUNC, PVT_FMT(target(), "match none!"));
2991 
2992                     std::string invalid = "i";
2993 
2994                     Board::board(_target.device)->_timers.del(callFXS()->_idx_dial);
2995 
2996                     switch (MatchExtension::findExtension(tmp_exten, tmp_context, contexts, invalid, call()->_orig_addr, true, false))
2997                     {
2998                         case MatchExtension::MATCH_EXACT:
2999                             // this dialing is invalid, and we can handle it...
3000                             call()->_dest_addr = invalid;
3001                             call()->_incoming_context = tmp_context;
3002                             alloc();
3003                             break;
3004                         case MatchExtension::MATCH_MORE:
3005                         case MatchExtension::MATCH_NONE:
3006                             callFXS()->_flags.set(Kflags::FXS_DIAL_FINISHD);
3007                             startCadence(PLAY_FASTBUSY);
3008                             break;
3009                     }
3010                     break;
3011             }
3012         }
3013         /*
3014         else if(callFXS()->_flags.check(Kflags::FXS_OFFHOOK) &&
3015                 callFXS()->_flags.check(Kflags::FXS_FLASH_TRANSFER))
3016         {
3017             Board::board(_target.device)->_timers.restart(callFXS()->_idx_transfer);
3018             DBG(FUNC, PVT_FMT(target(), "Flash Transfer"));
3019 
3020             if (call()->_cadence == PLAY_PBX_TONE)
3021             {
3022                 stopCadence();
3023             }
3024 
3025             if (call()->_cadence == PLAY_PUB_TONE)
3026             {
3027                 stopCadence();
3028                 //call()->_cadence = PLAY_NONE;
3029                 //mixer(KHOMP_LOG, 1, kmsGenerator, kmtSilence);
3030             }
3031 
3032             callFXS()->_flash_transfer += e->AddInfo;
3033 
3034             // begin context adjusting + processing
3035             MatchExtension::ContextListType contexts;
3036 
3037             validContexts(contexts);
3038 
3039             std::string tmp_exten;
3040             std::string tmp_context;
3041 
3042             switch (MatchExtension::findExtension(tmp_exten, tmp_context, contexts, callFXS()->_flash_transfer, call()->_orig_addr, false, false))
3043             {
3044                 case MatchExtension::MATCH_EXACT:
3045                 {
3046                     callFXS()->_flash_transfer = tmp_exten;
3047                     DBG(FUNC,FMT("incoming exten matched: %s") % callFXS()->_flash_transfer);
3048 
3049                     if(!transfer(tmp_context))
3050                     {
3051                         cleanup(KhompPvt::CLN_HARD);
3052                         DBG(FUNC, PVT_FMT(target(), "(FXS) r (unable to transfer)"));
3053                         return false;
3054                     }
3055 
3056                     break;
3057                 }
3058                 case MatchExtension::MATCH_MORE:
3059                     DBG(FUNC, PVT_FMT(target(), "match more..."));
3060 
3061                     // can match, will match more, and it's an external call?
3062                     for (DestVectorType::const_iterator i = Opt::_options._fxs_co_dialtone().begin(); i != Opt::_options._fxs_co_dialtone().end(); i++)
3063                     {
3064                         if (callFXS()->_flash_transfer == (*i))
3065                         {
3066                             startCadence(PLAY_PUB_TONE);
3067                             break;
3068                         }
3069                     }
3070 
3071                     break;
3072                 case MatchExtension::MATCH_NONE:
3073                 {
3074                     DBG(FUNC, PVT_FMT(target(), "match none!"));
3075 
3076                     if(!stopTransfer())
3077                     {
3078                         cleanup(KhompPvt::CLN_HARD);
3079                         DBG(FUNC, PVT_FMT(target(), "(FXS) r (unable to stop transfer)"));
3080                         return false;
3081                     }
3082 
3083                     break;
3084                 }
3085             }
3086         }
3087         */
3088         else
3089         {
3090             ret = KhompPvt::onDtmfDetected(e);
3091         }
3092 
3093     }
3094     catch (ScopedLockFailed & err)
3095     {
3096         LOG(ERROR, PVT_FMT(_target, "(FXS) r (unable to lock %s!)") % err._msg.c_str() );
3097         return false;
3098     }
3099     catch (K3LAPITraits::invalid_device & err)
3100     {
3101         LOG(ERROR, PVT_FMT(_target, "(FXS) r (unable to get device: %d!)") % err.device);
3102         return false;
3103     }
3104 
3105     DBG(FUNC, PVT_FMT(_target, "(FXS) r"));
3106 
3107     return ret;
3108 }
3109 
3110 /*
3111 bool BoardE1::KhompPvtFXS::onDtmfSendFinish(K3L_EVENT *e)
3112 {
3113     DBG(FUNC, PVT_FMT(_target, "(FXS) c"));
3114 
3115     bool ret = true;
3116 
3117     try
3118     {
3119         ScopedPvtLock lock(this);
3120 
3121         ret = KhompPvt::onDtmfSendFinish(e);
3122 
3123     }
3124     catch (ScopedLockFailed & err)
3125     {
3126         LOG(ERROR, PVT_FMT(_target, "(FXS) r (unable to lock %s!)") % err._msg.c_str() );
3127         return false;
3128     }
3129 
3130     DBG(FUNC, PVT_FMT(_target, "(FXS) r"));
3131 
3132     return ret;
3133 }
3134 */
3135 
onFlashDetected(K3L_EVENT * e)3136 bool BoardE1::KhompPvtFXS::onFlashDetected(K3L_EVENT *e)
3137 {
3138     DBG(FUNC, PVT_FMT(_target, "(FXS) c (%s)") % _flash);
3139 
3140     try
3141     {
3142         ScopedPvtLock lock(this);
3143 
3144         for(std::string::const_iterator it = _flash.begin(); it != _flash.end(); it++)
3145         {
3146             signalDTMF(*it);
3147         }
3148 
3149         DBG(FUNC, PVT_FMT(_target, "(FXS) r"));
3150 
3151         return true;
3152 
3153 /******************************************************************************/
3154         //Old implementation, not used
3155         /*
3156         if(callFXS()->_flags.check(Kflags::FXS_FLASH_TRANSFER))
3157         {
3158             DBG(FUNC, PVT_FMT(_target, "(FXS) transfer canceled"));
3159 
3160             if(!stopTransfer())
3161             {
3162                 cleanup(KhompPvt::CLN_HARD);
3163                 DBG(FUNC, PVT_FMT(target(), "(FXS) r (unable to stop transfer)"));
3164                 return false;
3165             }
3166 
3167             DBG(FUNC, PVT_FMT(target(), "(FXS) r"));
3168             return true;
3169         }
3170 
3171         if(call()->_flags.check(Kflags::IS_INCOMING))
3172         {
3173             DBG(FUNC, PVT_FMT(_target, "incoming call"));
3174         }
3175         else if(call()->_flags.check(Kflags::IS_OUTGOING))
3176         {
3177             DBG(FUNC, PVT_FMT(_target, "outgoing call"));
3178         }
3179         else
3180         {
3181             DBG(FUNC, PVT_FMT(_target, "(FXS) r (!incoming and !outgoing call)"));
3182             return true;
3183         }
3184 
3185         echoCancellation(false);
3186 
3187         if(!startTransfer())
3188         {
3189             DBG(FUNC, PVT_FMT(target(), "(FXS) r (unable to start transfer)"));
3190             return false;
3191         }
3192         */
3193 /******************************************************************************/
3194 
3195     }
3196     catch (ScopedLockFailed & err)
3197     {
3198         LOG(ERROR, PVT_FMT(_target, "(FXS) r (unable to lock %s!)") % err._msg.c_str() );
3199         return false;
3200     }
3201 
3202     DBG(FUNC, PVT_FMT(_target, "(FXS) r"));
3203 
3204     return true;
3205 }
3206 
makeCall(std::string params)3207 int BoardE1::KhompPvtFXS::makeCall(std::string params)
3208 {
3209     DBG(FUNC,PVT_FMT(_target, "(FXS) c"));
3210 
3211     /* we always have audio */
3212     call()->_flags.set(Kflags::HAS_PRE_AUDIO);
3213 
3214     if (Opt::_options._fxs_bina()&& !call()->_orig_addr.empty())
3215     {
3216         /* Sending Bina DTMF*/
3217         callFXS()->_flags.set(Kflags::WAIT_SEND_DTMF);
3218 
3219         std::stringstream dial_bina;
3220 
3221         dial_bina << "A1" << call()->_orig_addr << "C";
3222 
3223         if (!command(KHOMP_LOG, CM_DIAL_DTMF, dial_bina.str().c_str()))
3224         {
3225             return ksFail;
3226             //throw call_error("something went while sending BINA digits to FXS branch");
3227         }
3228 
3229         int timeout = 150;
3230 
3231         if(!loopWhileFlagTimed(Kflags::WAIT_SEND_DTMF, timeout))
3232             return ksFail;
3233         //throw call_error("call has been dropped while sending digits");
3234 
3235         if(timeout <= 0)
3236             return ksFail;
3237         //throw call_error("sending number of A caused timeout of this call");
3238     }
3239 
3240     if(!call()->_orig_addr.empty())
3241         params += STG(FMT(" orig_addr=\"%s\"") % _call->_orig_addr);
3242 
3243     if (callFXS()->_ring_on != -1)
3244         params += STG(FMT(" ring_on=\"%ld\"") % callFXS()->_ring_on);
3245 
3246     if (callFXS()->_ring_off != -1)
3247         params += STG(FMT(" ring_off=\"%ld\"") % callFXS()->_ring_off);
3248 
3249     if (callFXS()->_ring_on_ext != -1)
3250         params += STG(FMT(" ring_on_ext=\"%ld\"") % callFXS()->_ring_on_ext);
3251 
3252     if (callFXS()->_ring_off_ext != -1)
3253         params += STG(FMT(" ring_off_ext=\"%ld\"") % callFXS()->_ring_off_ext);
3254 
3255     int ret = KhompPvt::makeCall(params);
3256 
3257     if(ret == ksSuccess)
3258     {
3259         try
3260         {
3261             switch_channel_mark_ring_ready(getFSChannel());
3262         //signal_state(AST_CONTROL_RINGING);
3263         }
3264         catch(Board::KhompPvt::InvalidSwitchChannel & err)
3265         {
3266             LOG(ERROR, PVT_FMT(_target, "No valid channel: %s") % err._msg.c_str());
3267         }
3268     }
3269     else
3270     {
3271         LOG(ERROR, PVT_FMT(target(), "Fail on make call"));
3272     }
3273 
3274     call()->_cleanup_upon_hangup = (ret == ksInvalidParams || ret == ksInvalidState);
3275 
3276     DBG(FUNC,PVT_FMT(_target, "(FXS) r"));
3277     return ret;
3278 }
3279 
doChannelAnswer(CommandRequest & cmd)3280 bool BoardE1::KhompPvtFXS::doChannelAnswer(CommandRequest &cmd)
3281 {
3282     DBG(FUNC, PVT_FMT(_target, "(FXS) c"));
3283 
3284     bool ret = true;
3285 
3286     try
3287     {
3288         ScopedPvtLock lock(this);
3289 
3290         setupConnection();
3291 
3292         ret = KhompPvt::doChannelAnswer(cmd);
3293     }
3294     catch (ScopedLockFailed & err)
3295     {
3296         LOG(ERROR,PVT_FMT(_target, "(FXS) r (unable to lock %s!)") % err._msg.c_str() );
3297         return false;
3298     }
3299     catch (Board::KhompPvt::InvalidSwitchChannel & err)
3300     {
3301         LOG(ERROR, PVT_FMT(target(), "r (%s)") % err._msg.c_str() );
3302         return false;
3303     }
3304 
3305     DBG(FUNC, PVT_FMT(_target, "(FXS) r"));
3306 
3307     return ret;
3308 }
3309 
doChannelHangup(CommandRequest & cmd)3310 bool BoardE1::KhompPvtFXS::doChannelHangup(CommandRequest &cmd)
3311 {
3312     DBG(FUNC, PVT_FMT(_target, "(FXS) c"));
3313 
3314     bool ret = true;
3315 
3316     bool answered     = true;
3317     bool disconnected = false;
3318 
3319     try
3320     {
3321         ScopedPvtLock lock(this);
3322 
3323         /*
3324         if(!callFXS()->_uuid_other_session.empty())
3325         {
3326             DBG(FUNC,PVT_FMT(_target, "unable to transfer"));
3327 
3328             switch_core_session_t *hold_session;
3329 
3330             if ((hold_session = switch_core_session_locate(callFXS()->_uuid_other_session.c_str())))
3331             {
3332                 switch_channel_t *hold_channel = switch_core_session_get_channel(hold_session);
3333                 switch_core_session_rwunlock(hold_session);
3334 
3335                 if(hold_channel)
3336                     switch_channel_hangup(hold_channel, (switch_call_cause_t)call()->_hangup_cause);
3337                 //switch_channel_hangup(hold_channel, SWITCH_CAUSE_ATTENDED_TRANSFER);
3338             }
3339             callFXS()->_uuid_other_session.clear();
3340         }
3341         */
3342 
3343         if (call()->_flags.check(Kflags::IS_INCOMING))
3344         {
3345             DBG(FUNC,PVT_FMT(_target, "disconnecting incoming channel"));
3346 
3347         }
3348         else if (call()->_flags.check(Kflags::IS_OUTGOING))
3349         {
3350             if (!call()->_flags.check(Kflags::FXS_OFFHOOK))
3351             {
3352                 DBG(FUNC, PVT_FMT(_target, "disconnecting not answered outgoing FXS channel..."));
3353                 disconnected = command(KHOMP_LOG, CM_DISCONNECT);
3354                 cleanup(KhompPvt::CLN_HARD);
3355                 answered = false;
3356 
3357             }
3358             else if(call()->_cleanup_upon_hangup)
3359             {
3360                 DBG(FUNC,PVT_FMT(_target, "disconnecting not allocated outgoing channel..."));
3361 
3362                 disconnected = command(KHOMP_LOG, CM_DISCONNECT);
3363                 cleanup(KhompPvt::CLN_HARD);
3364                 answered = false;
3365 
3366             }
3367             else
3368             {
3369                 DBG(FUNC,PVT_FMT(_target, "disconnecting outgoing channel..."));
3370 
3371                 disconnected = command(KHOMP_LOG, CM_DISCONNECT);
3372             }
3373         }
3374         else
3375         {
3376             DBG(FUNC,PVT_FMT(_target, "already disconnected"));
3377             return true;
3378         }
3379 
3380         if(answered)
3381         {
3382             indicateBusyUnlocked(SWITCH_CAUSE_USER_BUSY, disconnected);
3383         }
3384 
3385         if (call()->_flags.check(Kflags::IS_INCOMING) && !call()->_flags.check(Kflags::NEEDS_RINGBACK_CMD))
3386         {
3387             DBG(FUNC,PVT_FMT(_target, "disconnecting incoming channel..."));
3388             disconnected = command(KHOMP_LOG, CM_DISCONNECT);
3389         }
3390 
3391         stopStream();
3392 
3393         stopListen();
3394 
3395         //ret = KhompPvt::doChannelHangup(cmd);
3396     }
3397     catch (ScopedLockFailed & err)
3398     {
3399         LOG(ERROR,PVT_FMT(_target, "(FXS) r (unable to lock %s!)") % err._msg.c_str() );
3400         return false;
3401     }
3402 
3403     DBG(FUNC, PVT_FMT(_target, "(FXS) r"));
3404 
3405     return ret;
3406 }
3407 
setupConnection()3408 bool BoardE1::KhompPvtFXS::setupConnection()
3409 {
3410     if(!call()->_flags.check(Kflags::IS_INCOMING) && !call()->_flags.check(Kflags::IS_OUTGOING))
3411     {
3412         DBG(FUNC,PVT_FMT(_target, "Channel already disconnected"));
3413         return false;
3414     }
3415 
3416     bool res_out_of_band_dtmf = (call()->_var_dtmf_state == T_UNKNOWN ?
3417         Opt::_options._suppression_delay() && Opt::_options._out_of_band_dtmfs(): (call()->_var_dtmf_state == T_TRUE));
3418 
3419     bool res_echo_cancellator = (call()->_var_echo_state == T_UNKNOWN ?
3420         Opt::_options._echo_canceller() : (call()->_var_echo_state == T_TRUE));
3421 
3422 
3423     bool res_auto_gain_cntrol = (call()->_var_gain_state == T_UNKNOWN ?
3424         Opt::_options._auto_gain_control() : (call()->_var_gain_state == T_TRUE));
3425 
3426 
3427     if (!call()->_flags.check(Kflags::REALLY_CONNECTED))
3428     {
3429         obtainRX(res_out_of_band_dtmf);
3430 
3431         /* esvazia buffers de leitura/escrita */
3432         cleanupBuffers();
3433 
3434         if (!call()->_flags.check(Kflags::KEEP_DTMF_SUPPRESSION))
3435             dtmfSuppression(res_out_of_band_dtmf);
3436 
3437         if (!call()->_flags.check(Kflags::KEEP_ECHO_CANCELLATION))
3438             echoCancellation(res_echo_cancellator);
3439 
3440         if (!call()->_flags.check(Kflags::KEEP_AUTO_GAIN_CONTROL))
3441             autoGainControl(res_auto_gain_cntrol);
3442 
3443         startListen(false);
3444 
3445         startStream();
3446 
3447         DBG(FUNC, PVT_FMT(_target, "(FXS) Audio callbacks initialized successfully"));
3448     }
3449 
3450     call()->_flags.set(Kflags::FXS_OFFHOOK);
3451 
3452     return KhompPvt::setupConnection();
3453 }
3454 
indicateBusyUnlocked(int cause,bool sent_signaling)3455 bool BoardE1::KhompPvtFXS::indicateBusyUnlocked(int cause, bool sent_signaling)
3456 {
3457     DBG(FUNC, PVT_FMT(_target, "(FXS) c"));
3458 
3459     if(!KhompPvt::indicateBusyUnlocked(cause, sent_signaling))
3460     {
3461         DBG(FUNC, PVT_FMT(_target, "(FXS) r (false)"));
3462         return false;
3463     }
3464 
3465     if(call()->_flags.check(Kflags::IS_INCOMING))
3466     {
3467         if(!call()->_flags.check(Kflags::CONNECTED) && !sent_signaling)
3468         {
3469             if(!call()->_flags.check(Kflags::HAS_PRE_AUDIO))
3470             {
3471                 int rb_value = callFailFromCause(call()->_hangup_cause);
3472                 DBG(FUNC, PVT_FMT(target(), "sending the busy status"));
3473 
3474                 if (sendRingBackStatus(rb_value) == RingbackDefs::RBST_UNSUPPORTED)
3475                 {
3476                     DBG(FUNC, PVT_FMT(target(), "falling back to audio indication!"));
3477                     /* stop the line audio */
3478                     stopStream();
3479 
3480                     /* just pre connect, no ringback */
3481                     if (!sendPreAudio())
3482                         DBG(FUNC, PVT_FMT(target(), "everything else failed, just sending audio indication..."));
3483 
3484                     /* be very specific about the situation. */
3485                     mixer(KHOMP_LOG, 1, kmsGenerator, kmtBusy);
3486                 }
3487             }
3488             else
3489             {
3490                 DBG(FUNC, PVT_FMT(target(), "going to play busy"));
3491 
3492                 /* stop the line audio */
3493                 stopStream();
3494 
3495                 /* be very specific about the situation. */
3496                 mixer(KHOMP_LOG, 1, kmsGenerator, kmtBusy);
3497 
3498             }
3499         }
3500         else
3501         {
3502             /* already connected or sent signaling... */
3503             mixer(KHOMP_LOG, 1, kmsGenerator, kmtBusy);
3504         }
3505 
3506     }
3507     else if(call()->_flags.check(Kflags::IS_OUTGOING))
3508     {
3509         /* already connected or sent signaling... */
3510         mixer(KHOMP_LOG, 1, kmsGenerator, kmtBusy);
3511     }
3512 
3513     DBG(FUNC,PVT_FMT(_target, "(FXS) r"));
3514 
3515     return true;
3516 }
3517 
reportFailToReceive(int fail_code)3518 void BoardE1::KhompPvtFXS::reportFailToReceive(int fail_code)
3519 {
3520     KhompPvt::reportFailToReceive(fail_code);
3521 
3522     if(fail_code != -1)
3523     {
3524         DBG(FUNC,PVT_FMT(_target, "sending a 'unknown number' message/audio"));
3525 
3526         if(sendRingBackStatus(fail_code) == RingbackDefs::RBST_UNSUPPORTED)
3527         {
3528             sendPreAudio(RingbackDefs::RB_SEND_DEFAULT);
3529             startCadence(PLAY_FASTBUSY);
3530         }
3531     }
3532     else
3533     {
3534         DBG(FUNC, PVT_FMT(_target, "sending fast busy audio directly"));
3535 
3536         sendPreAudio(RingbackDefs::RB_SEND_DEFAULT);
3537         startCadence(PLAY_FASTBUSY);
3538     }
3539 }
3540 
validContexts(MatchExtension::ContextListType & contexts,std::string extra_context)3541 bool BoardE1::KhompPvtFXS::validContexts(
3542         MatchExtension::ContextListType & contexts, std::string extra_context)
3543 {
3544     DBG(FUNC,PVT_FMT(_target, "(FXS) c"));
3545 
3546     if(!_context.empty())
3547         contexts.push_back(_context);
3548 
3549     if(!_group_context.empty())
3550     {
3551         contexts.push_back(_group_context);
3552     }
3553 
3554     contexts.push_back(Opt::_options._context_fxs());
3555     contexts.push_back(Opt::_options._context2_fxs());
3556 
3557     for (MatchExtension::ContextListType::iterator i = contexts.begin(); i != contexts.end(); i++)
3558     {
3559         replaceTemplate((*i), "CC", _target.object);
3560     }
3561 
3562     bool ret = Board::KhompPvt::validContexts(contexts,extra_context);
3563 
3564     DBG(FUNC,PVT_FMT(_target, "(FXS) r"));
3565 
3566     return ret;
3567 }
3568 
isOK()3569 bool BoardE1::KhompPvtFXS::isOK()
3570 {
3571     try
3572     {
3573         ScopedPvtLock lock(this);
3574 
3575         K3L_CHANNEL_STATUS status;
3576 
3577         if (k3lGetDeviceStatus (_target.device, _target.object + ksoChannel, &status, sizeof (status)) != ksSuccess)
3578             return false;
3579 
3580         return (status.AddInfo != kfxsFail);
3581     }
3582     catch (ScopedLockFailed & err)
3583     {
3584         LOG(ERROR, PVT_FMT(target(), "unable to lock %s!") % err._msg.c_str() );
3585     }
3586 
3587     return false;
3588 }
3589 
3590 
3591