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