From 380fd060ef719b1d8f8781422e84d2a32066351d Mon Sep 17 00:00:00 2001 From: Andrey Volk Date: Thu, 19 Aug 2021 01:12:54 +0300 Subject: [PATCH] [Build-System] Remove freetdm from the FreeSWITCH tree. Use out-of-tree module https://github.com/freeswitch/freetdm instead. --- .gitignore | 9 - bootstrap.sh | 2 +- build/modules.conf.in | 2 +- configure.ac | 1 - libs/.gitignore | 6 - libs/freetdm/.gitignore | 39 - libs/freetdm/.update | 1 - libs/freetdm/AUTHORS | 0 libs/freetdm/CMakeLists.txt | 244 - libs/freetdm/ChangeLog | 0 libs/freetdm/Makefile.am | 290 - libs/freetdm/NEWS | 0 libs/freetdm/README | 3 - libs/freetdm/TODO | 22 - libs/freetdm/acinclude.m4 | 2 - libs/freetdm/bootstrap | 6 - libs/freetdm/build/ax_compiler_vendor.m4 | 15 - libs/freetdm/build/libpcap.m4 | 150 - libs/freetdm/conf/freetdm.conf | 82 - libs/freetdm/conf/freetdm.conf.xml | 633 -- libs/freetdm/conf/pika.conf | 43 - libs/freetdm/conf/tones.conf | 142 - libs/freetdm/conf/wanpipe.conf | 13 - libs/freetdm/conf/zt.conf | 8 - libs/freetdm/configure.ac | 480 -- libs/freetdm/configure.gnu | 3 - libs/freetdm/cyginstall.sh | 14 - libs/freetdm/docs/Doxygen.conf | 265 - libs/freetdm/docs/PRI-BRI-Debug.pdf | Bin 399483 -> 0 bytes libs/freetdm/docs/async.txt | 15 - libs/freetdm/docs/ftdm-open-issues.txt | 76 - libs/freetdm/docs/glare.txt | 25 - libs/freetdm/docs/io_modules.txt | 13 - libs/freetdm/docs/locking.txt | 125 - libs/freetdm/docs/sigstatus.txt | 59 - libs/freetdm/docs/ss7-native-bridge.txt | 43 - libs/freetdm/docs/variables.txt | 122 - libs/freetdm/freetdm.2008.sln | 155 - libs/freetdm/freetdm.2010.sln | 127 - libs/freetdm/freetdm.2012.sln | 127 - libs/freetdm/freetdm.pc.in | 18 - libs/freetdm/mkrelease.sh | 144 - libs/freetdm/mod_freetdm/CMakeLists.txt | 32 - libs/freetdm/mod_freetdm/Makefile.in | 24 - libs/freetdm/mod_freetdm/clean.sh | 6 - .../mod_freetdm/mod_freetdm.2008.vcproj | 369 - .../mod_freetdm.2010.vcxproj.filters | 14 - libs/freetdm/mod_freetdm/mod_freetdm.c | 5715 -------------- .../mod_freetdm/mod_openzap.2005.vcproj | 201 - libs/freetdm/mod_freetdm/tdm.c | 719 -- libs/freetdm/msvc/freetdm.2008.vcproj | 499 -- .../freetdm/msvc/freetdm.2010.vcxproj.filters | 137 - libs/freetdm/msvc/openzap.2005.vcproj | 301 - .../msvc/testanalog/testanalog.2005.vcproj | 193 - .../msvc/testanalog/testanalog.2008.vcproj | 349 - .../testanalog.2010.vcxproj.filters | 14 - .../msvc/testboost/testboost.2008.vcproj | 354 - .../testboost/testboost.2010.vcxproj.filters | 14 - .../testboost/testsangomaboost.2008.vcproj | 354 - .../testsangomaboost.2010.vcxproj.filters | 14 - .../msvc/testisdn/testisdn.2005.vcproj | 193 - .../msvc/testisdn/testisdn.2008.vcproj | 349 - .../testisdn/testisdn.2010.vcxproj.filters | 14 - libs/freetdm/sample/CMakeLists.txt | 7 - libs/freetdm/sample/dso/CMakeLists.txt | 12 - libs/freetdm/sample/dso/Makefile | 14 - libs/freetdm/sample/dso/ftdmload.c | 168 - libs/freetdm/sample/sched/CMakeLists.txt | 12 - libs/freetdm/sample/sched/ftdmsched.c | 110 - libs/freetdm/src/detect_dtmf.c | 54 - libs/freetdm/src/detect_tones.c | 32 - libs/freetdm/src/fsk.c | 351 - libs/freetdm/src/ftdm_backtrace.c | 78 - libs/freetdm/src/ftdm_buffer.c | 308 - libs/freetdm/src/ftdm_call_utils.c | 237 - libs/freetdm/src/ftdm_callerid.c | 307 - libs/freetdm/src/ftdm_config.c | 383 - libs/freetdm/src/ftdm_cpu_monitor.c | 307 - libs/freetdm/src/ftdm_dso.c | 126 - libs/freetdm/src/ftdm_io.c | 7027 ----------------- libs/freetdm/src/ftdm_queue.c | 234 - libs/freetdm/src/ftdm_sched.c | 576 -- libs/freetdm/src/ftdm_state.c | 575 -- libs/freetdm/src/ftdm_threadmutex.c | 635 -- libs/freetdm/src/ftdm_variables.c | 151 - .../src/ftmod/ftmod_analog/ftdm_analog.h | 75 - .../ftmod_analog/ftmod_analog.2008.vcproj | 353 - .../ftmod_analog.2010.vcxproj.filters | 23 - .../src/ftmod/ftmod_analog/ftmod_analog.c | 1270 --- .../ftmod/ftmod_analog_em/ftdm_analog_em.h | 77 - .../ftmod_analog_em.2008.vcproj | 353 - .../ftmod_analog_em.2010.vcxproj.filters | 23 - .../ftmod/ftmod_analog_em/ftmod_analog_em.c | 1160 --- libs/freetdm/src/ftmod/ftmod_gsm/ftmod_gsm.c | 1592 ---- .../ftmod/ftmod_isdn/ftmod_isdn.2008.vcproj | 465 -- .../ftmod_isdn.2010.vcxproj.filters | 110 - .../freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c | 2927 ------- .../freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h | 100 - .../src/ftmod/ftmod_libpri/ftmod_libpri.c | 3248 -------- .../src/ftmod/ftmod_libpri/ftmod_libpri.h | 151 - .../src/ftmod/ftmod_libpri/lpwrap_pri.c | 464 -- .../src/ftmod/ftmod_libpri/lpwrap_pri.h | 144 - .../src/ftmod/ftmod_misdn/ftmod_misdn.c | 2837 ------- libs/freetdm/src/ftmod/ftmod_pika/ftdm_pika.h | 132 - .../ftmod/ftmod_pika/ftmod_pika.2008.vcproj | 353 - .../ftmod_pika.2010.vcxproj.filters | 23 - .../freetdm/src/ftmod/ftmod_pika/ftmod_pika.c | 1469 ---- .../ftmod/ftmod_pika/ozmod_pika.2005.vcproj | 197 - .../src/ftmod/ftmod_pritap/ftmod_pritap.c | 1189 --- .../src/ftmod/ftmod_r2/ftmod_r2.2008.vcproj | 196 - .../ftmod_r2/ftmod_r2.2010.vcxproj.filters | 22 - libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 2437 ------ .../src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.c | 163 - .../src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.h | 73 - .../ftmod_sangoma_isdn.2008.vcproj | 249 - .../ftmod_sangoma_isdn.2010.vcxproj.filters | 57 - .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.c | 1563 ---- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.h | 613 -- .../ftmod_sangoma_isdn_cfg.c | 657 -- .../ftmod_sangoma_isdn_cntrl.c | 98 - .../ftmod_sangoma_isdn_stack_cfg.c | 1273 --- .../ftmod_sangoma_isdn_stack_cntrl.c | 403 - .../ftmod_sangoma_isdn_stack_hndl.c | 1437 ---- .../ftmod_sangoma_isdn_stack_out.c | 588 -- .../ftmod_sangoma_isdn_stack_rcv.c | 1134 --- .../ftmod_sangoma_isdn_support.c | 1643 ---- .../ftmod_sangoma_isdn_trace.c | 996 --- .../ftmod_sangoma_isdn_trace.h | 599 -- .../ftmod_sangoma_isdn_transfer.c | 281 - .../ftmod_sangoma_isdn_user.h | 154 - .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c | 1745 ---- .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c | 4007 ---------- .../ftmod_sangoma_ss7_cntrl.c | 921 --- .../ftmod_sangoma_ss7_handle.c | 2750 ------- .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c | 722 -- .../ftmod_sangoma_ss7_logger.c | 1155 --- .../ftmod_sangoma_ss7_m2ua.c | 1773 ----- .../ftmod_sangoma_ss7_m2ua.h | 136 - .../ftmod_sangoma_ss7_m2ua_xml.c | 690 -- .../ftmod_sangoma_ss7_main.c | 2766 ------- .../ftmod_sangoma_ss7_main.h | 1246 --- .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c | 1052 --- .../ftmod_sangoma_ss7_relay.c | 345 - .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c | 240 - .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c | 61 - .../ftmod_sangoma_ss7_support.c | 3415 -------- .../ftmod_sangoma_ss7_timers.c | 163 - .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c | 3454 -------- .../freetdm/src/ftmod/ftmod_skel/ftmod_skel.c | 183 - .../ftmod_wanpipe/ftmod_wanpipe.2008.vcproj | 355 - .../ftmod_wanpipe.2010.vcxproj.filters | 18 - .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 1807 ----- libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c | 1571 ---- libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.h | 393 - libs/freetdm/src/g711.c | 104 - libs/freetdm/src/hashtable.c | 340 - libs/freetdm/src/hashtable_itr.c | 186 - libs/freetdm/src/include/freetdm.h | 2023 ----- libs/freetdm/src/include/ftdm_call_utils.h | 154 - libs/freetdm/src/include/ftdm_declare.h | 299 - libs/freetdm/src/include/ftdm_dso.h | 54 - libs/freetdm/src/include/ftdm_os.h | 205 - libs/freetdm/src/include/ftdm_threadmutex.h | 78 - libs/freetdm/src/include/private/fsk.h | 121 - .../freetdm/src/include/private/ftdm_buffer.h | 154 - .../freetdm/src/include/private/ftdm_config.h | 145 - libs/freetdm/src/include/private/ftdm_core.h | 803 -- .../src/include/private/ftdm_cpu_monitor.h | 75 - libs/freetdm/src/include/private/ftdm_sched.h | 119 - libs/freetdm/src/include/private/ftdm_state.h | 247 - libs/freetdm/src/include/private/ftdm_types.h | 390 - libs/freetdm/src/include/private/g711.h | 395 - libs/freetdm/src/include/private/hashtable.h | 235 - .../src/include/private/hashtable_itr.h | 134 - .../src/include/private/hashtable_private.h | 110 - .../freetdm/src/include/private/libteletone.h | 161 - .../src/include/private/libteletone_detect.h | 282 - .../include/private/libteletone_generate.h | 316 - .../src/include/private/sangoma_tdm_api.h | 321 - libs/freetdm/src/include/private/uart.h | 83 - libs/freetdm/src/isdn/5ESSStateNT.c | 132 - libs/freetdm/src/isdn/5ESSStateTE.c | 291 - libs/freetdm/src/isdn/5ESSmes.c | 361 - libs/freetdm/src/isdn/DMSStateNT.c | 126 - libs/freetdm/src/isdn/DMSStateTE.c | 284 - libs/freetdm/src/isdn/DMSmes.c | 344 - libs/freetdm/src/isdn/EuroISDNStateNT.c | 44 - libs/freetdm/src/isdn/EuroISDNStateTE.c | 58 - libs/freetdm/src/isdn/Q921.c | 3518 --------- libs/freetdm/src/isdn/Q931.c | 888 --- libs/freetdm/src/isdn/Q931StateNT.c | 1218 --- libs/freetdm/src/isdn/Q931StateTE.c | 1310 --- libs/freetdm/src/isdn/Q931api.c | 598 -- libs/freetdm/src/isdn/Q931ie.c | 3074 ------- libs/freetdm/src/isdn/Q931mes.c | 1870 ----- libs/freetdm/src/isdn/Q932mes.c | 286 - libs/freetdm/src/isdn/include/5ESS.h | 103 - libs/freetdm/src/isdn/include/DMS.h | 91 - libs/freetdm/src/isdn/include/Q921.h | 227 - libs/freetdm/src/isdn/include/Q921priv.h | 321 - libs/freetdm/src/isdn/include/Q931.h | 1175 --- libs/freetdm/src/isdn/include/Q931ie.h | 1205 --- libs/freetdm/src/isdn/include/Q932.h | 95 - libs/freetdm/src/isdn/include/mfifo.h | 85 - libs/freetdm/src/isdn/include/national.h | 86 - libs/freetdm/src/isdn/mfifo.c | 399 - libs/freetdm/src/isdn/nationalStateNT.c | 130 - libs/freetdm/src/isdn/nationalStateTE.c | 217 - libs/freetdm/src/isdn/nationalmes.c | 269 - libs/freetdm/src/libteletone_detect.c | 485 -- libs/freetdm/src/libteletone_generate.c | 505 -- libs/freetdm/src/priserver.c | 328 - libs/freetdm/src/sangoma_pri.c | 251 - libs/freetdm/src/sangoma_pri.h | 100 - libs/freetdm/src/ss7/README | 3 - libs/freetdm/src/testanalog.c | 138 - libs/freetdm/src/testapp.c | 89 - libs/freetdm/src/testcid.c | 109 - libs/freetdm/src/testisdn.c | 74 - libs/freetdm/src/testpri.c | 174 - libs/freetdm/src/testr2.c | 169 - libs/freetdm/src/testtones.c | 76 - libs/freetdm/src/uart.c | 125 - 223 files changed, 2 insertions(+), 118395 deletions(-) delete mode 100644 libs/freetdm/.gitignore delete mode 100644 libs/freetdm/.update delete mode 100644 libs/freetdm/AUTHORS delete mode 100644 libs/freetdm/CMakeLists.txt delete mode 100644 libs/freetdm/ChangeLog delete mode 100644 libs/freetdm/Makefile.am delete mode 100644 libs/freetdm/NEWS delete mode 100644 libs/freetdm/README delete mode 100644 libs/freetdm/TODO delete mode 100644 libs/freetdm/acinclude.m4 delete mode 100755 libs/freetdm/bootstrap delete mode 100644 libs/freetdm/build/ax_compiler_vendor.m4 delete mode 100644 libs/freetdm/build/libpcap.m4 delete mode 100644 libs/freetdm/conf/freetdm.conf delete mode 100644 libs/freetdm/conf/freetdm.conf.xml delete mode 100644 libs/freetdm/conf/pika.conf delete mode 100644 libs/freetdm/conf/tones.conf delete mode 100644 libs/freetdm/conf/wanpipe.conf delete mode 100644 libs/freetdm/conf/zt.conf delete mode 100644 libs/freetdm/configure.ac delete mode 100755 libs/freetdm/configure.gnu delete mode 100755 libs/freetdm/cyginstall.sh delete mode 100644 libs/freetdm/docs/Doxygen.conf delete mode 100755 libs/freetdm/docs/PRI-BRI-Debug.pdf delete mode 100644 libs/freetdm/docs/async.txt delete mode 100644 libs/freetdm/docs/ftdm-open-issues.txt delete mode 100644 libs/freetdm/docs/glare.txt delete mode 100644 libs/freetdm/docs/io_modules.txt delete mode 100644 libs/freetdm/docs/locking.txt delete mode 100644 libs/freetdm/docs/sigstatus.txt delete mode 100644 libs/freetdm/docs/ss7-native-bridge.txt delete mode 100644 libs/freetdm/docs/variables.txt delete mode 100644 libs/freetdm/freetdm.2008.sln delete mode 100644 libs/freetdm/freetdm.2010.sln delete mode 100644 libs/freetdm/freetdm.2012.sln delete mode 100644 libs/freetdm/freetdm.pc.in delete mode 100755 libs/freetdm/mkrelease.sh delete mode 100644 libs/freetdm/mod_freetdm/CMakeLists.txt delete mode 100644 libs/freetdm/mod_freetdm/Makefile.in delete mode 100755 libs/freetdm/mod_freetdm/clean.sh delete mode 100644 libs/freetdm/mod_freetdm/mod_freetdm.2008.vcproj delete mode 100644 libs/freetdm/mod_freetdm/mod_freetdm.2010.vcxproj.filters delete mode 100644 libs/freetdm/mod_freetdm/mod_freetdm.c delete mode 100644 libs/freetdm/mod_freetdm/mod_openzap.2005.vcproj delete mode 100644 libs/freetdm/mod_freetdm/tdm.c delete mode 100644 libs/freetdm/msvc/freetdm.2008.vcproj delete mode 100644 libs/freetdm/msvc/freetdm.2010.vcxproj.filters delete mode 100644 libs/freetdm/msvc/openzap.2005.vcproj delete mode 100644 libs/freetdm/msvc/testanalog/testanalog.2005.vcproj delete mode 100644 libs/freetdm/msvc/testanalog/testanalog.2008.vcproj delete mode 100644 libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj.filters delete mode 100644 libs/freetdm/msvc/testboost/testboost.2008.vcproj delete mode 100644 libs/freetdm/msvc/testboost/testboost.2010.vcxproj.filters delete mode 100644 libs/freetdm/msvc/testboost/testsangomaboost.2008.vcproj delete mode 100644 libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj.filters delete mode 100644 libs/freetdm/msvc/testisdn/testisdn.2005.vcproj delete mode 100644 libs/freetdm/msvc/testisdn/testisdn.2008.vcproj delete mode 100644 libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj.filters delete mode 100644 libs/freetdm/sample/CMakeLists.txt delete mode 100644 libs/freetdm/sample/dso/CMakeLists.txt delete mode 100644 libs/freetdm/sample/dso/Makefile delete mode 100644 libs/freetdm/sample/dso/ftdmload.c delete mode 100644 libs/freetdm/sample/sched/CMakeLists.txt delete mode 100644 libs/freetdm/sample/sched/ftdmsched.c delete mode 100644 libs/freetdm/src/detect_dtmf.c delete mode 100644 libs/freetdm/src/detect_tones.c delete mode 100644 libs/freetdm/src/fsk.c delete mode 100644 libs/freetdm/src/ftdm_backtrace.c delete mode 100644 libs/freetdm/src/ftdm_buffer.c delete mode 100644 libs/freetdm/src/ftdm_call_utils.c delete mode 100644 libs/freetdm/src/ftdm_callerid.c delete mode 100644 libs/freetdm/src/ftdm_config.c delete mode 100644 libs/freetdm/src/ftdm_cpu_monitor.c delete mode 100755 libs/freetdm/src/ftdm_dso.c delete mode 100644 libs/freetdm/src/ftdm_io.c delete mode 100644 libs/freetdm/src/ftdm_queue.c delete mode 100644 libs/freetdm/src/ftdm_sched.c delete mode 100644 libs/freetdm/src/ftdm_state.c delete mode 100644 libs/freetdm/src/ftdm_threadmutex.c delete mode 100644 libs/freetdm/src/ftdm_variables.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h delete mode 100644 libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2008.vcproj delete mode 100644 libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj.filters delete mode 100644 libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_analog_em/ftdm_analog_em.h delete mode 100644 libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2008.vcproj delete mode 100644 libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj.filters delete mode 100644 libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c delete mode 100755 libs/freetdm/src/ftmod/ftmod_gsm/ftmod_gsm.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2008.vcproj delete mode 100644 libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj.filters delete mode 100644 libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h delete mode 100644 libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h delete mode 100644 libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.h delete mode 100644 libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_pika/ftdm_pika.h delete mode 100644 libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2008.vcproj delete mode 100644 libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj.filters delete mode 100644 libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_pika/ozmod_pika.2005.vcproj delete mode 100644 libs/freetdm/src/ftmod/ftmod_pritap/ftmod_pritap.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2008.vcproj delete mode 100644 libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj.filters delete mode 100755 libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c delete mode 100755 libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.c delete mode 100755 libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.h delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2008.vcproj delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj.filters delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_transfer.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_user.h delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_m2ua.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_m2ua.h delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_m2ua_xml.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_relay.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_skel/ftmod_skel.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2008.vcproj delete mode 100644 libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj.filters delete mode 100755 libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.h delete mode 100644 libs/freetdm/src/g711.c delete mode 100644 libs/freetdm/src/hashtable.c delete mode 100644 libs/freetdm/src/hashtable_itr.c delete mode 100755 libs/freetdm/src/include/freetdm.h delete mode 100644 libs/freetdm/src/include/ftdm_call_utils.h delete mode 100644 libs/freetdm/src/include/ftdm_declare.h delete mode 100755 libs/freetdm/src/include/ftdm_dso.h delete mode 100644 libs/freetdm/src/include/ftdm_os.h delete mode 100644 libs/freetdm/src/include/ftdm_threadmutex.h delete mode 100644 libs/freetdm/src/include/private/fsk.h delete mode 100644 libs/freetdm/src/include/private/ftdm_buffer.h delete mode 100644 libs/freetdm/src/include/private/ftdm_config.h delete mode 100644 libs/freetdm/src/include/private/ftdm_core.h delete mode 100644 libs/freetdm/src/include/private/ftdm_cpu_monitor.h delete mode 100644 libs/freetdm/src/include/private/ftdm_sched.h delete mode 100644 libs/freetdm/src/include/private/ftdm_state.h delete mode 100755 libs/freetdm/src/include/private/ftdm_types.h delete mode 100644 libs/freetdm/src/include/private/g711.h delete mode 100644 libs/freetdm/src/include/private/hashtable.h delete mode 100644 libs/freetdm/src/include/private/hashtable_itr.h delete mode 100644 libs/freetdm/src/include/private/hashtable_private.h delete mode 100644 libs/freetdm/src/include/private/libteletone.h delete mode 100644 libs/freetdm/src/include/private/libteletone_detect.h delete mode 100644 libs/freetdm/src/include/private/libteletone_generate.h delete mode 100644 libs/freetdm/src/include/private/sangoma_tdm_api.h delete mode 100644 libs/freetdm/src/include/private/uart.h delete mode 100644 libs/freetdm/src/isdn/5ESSStateNT.c delete mode 100644 libs/freetdm/src/isdn/5ESSStateTE.c delete mode 100644 libs/freetdm/src/isdn/5ESSmes.c delete mode 100644 libs/freetdm/src/isdn/DMSStateNT.c delete mode 100644 libs/freetdm/src/isdn/DMSStateTE.c delete mode 100644 libs/freetdm/src/isdn/DMSmes.c delete mode 100644 libs/freetdm/src/isdn/EuroISDNStateNT.c delete mode 100644 libs/freetdm/src/isdn/EuroISDNStateTE.c delete mode 100644 libs/freetdm/src/isdn/Q921.c delete mode 100644 libs/freetdm/src/isdn/Q931.c delete mode 100644 libs/freetdm/src/isdn/Q931StateNT.c delete mode 100644 libs/freetdm/src/isdn/Q931StateTE.c delete mode 100644 libs/freetdm/src/isdn/Q931api.c delete mode 100644 libs/freetdm/src/isdn/Q931ie.c delete mode 100644 libs/freetdm/src/isdn/Q931mes.c delete mode 100644 libs/freetdm/src/isdn/Q932mes.c delete mode 100644 libs/freetdm/src/isdn/include/5ESS.h delete mode 100644 libs/freetdm/src/isdn/include/DMS.h delete mode 100644 libs/freetdm/src/isdn/include/Q921.h delete mode 100644 libs/freetdm/src/isdn/include/Q921priv.h delete mode 100644 libs/freetdm/src/isdn/include/Q931.h delete mode 100644 libs/freetdm/src/isdn/include/Q931ie.h delete mode 100644 libs/freetdm/src/isdn/include/Q932.h delete mode 100644 libs/freetdm/src/isdn/include/mfifo.h delete mode 100644 libs/freetdm/src/isdn/include/national.h delete mode 100644 libs/freetdm/src/isdn/mfifo.c delete mode 100644 libs/freetdm/src/isdn/nationalStateNT.c delete mode 100644 libs/freetdm/src/isdn/nationalStateTE.c delete mode 100644 libs/freetdm/src/isdn/nationalmes.c delete mode 100644 libs/freetdm/src/libteletone_detect.c delete mode 100644 libs/freetdm/src/libteletone_generate.c delete mode 100644 libs/freetdm/src/priserver.c delete mode 100644 libs/freetdm/src/sangoma_pri.c delete mode 100644 libs/freetdm/src/sangoma_pri.h delete mode 100644 libs/freetdm/src/ss7/README delete mode 100644 libs/freetdm/src/testanalog.c delete mode 100644 libs/freetdm/src/testapp.c delete mode 100644 libs/freetdm/src/testcid.c delete mode 100644 libs/freetdm/src/testisdn.c delete mode 100644 libs/freetdm/src/testpri.c delete mode 100644 libs/freetdm/src/testr2.c delete mode 100644 libs/freetdm/src/testtones.c delete mode 100644 libs/freetdm/src/uart.c diff --git a/.gitignore b/.gitignore index a4fb5ca6f6..a6cbd8cb92 100644 --- a/.gitignore +++ b/.gitignore @@ -115,15 +115,6 @@ Release/ /libs/esl/fs_ivrd /libs/esl/testclient /libs/esl/testserver -/libs/freetdm/detect_dtmf -/libs/freetdm/detect_tones -/libs/freetdm/testanalog -/libs/freetdm/testapp -/libs/freetdm/testcid -/libs/freetdm/testpri -/libs/freetdm/testr2 -/libs/freetdm/testsangomaboost -/libs/freetdm/testtones /libs/fsg729-*-installer /libs/g729/ /libs/libcodec2/compile diff --git a/bootstrap.sh b/bootstrap.sh index fa7e10ad88..b19a522044 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -10,7 +10,7 @@ BGJOB=false VERBOSE=false BASEDIR=`pwd`; LIBDIR=${BASEDIR}/libs; -SUBDIRS="apr libzrtp iksemel libdingaling srtp freetdm unimrcp fs"; +SUBDIRS="apr libzrtp iksemel libdingaling srtp unimrcp fs"; while getopts 'jhd:v' o; do case "$o" in diff --git a/build/modules.conf.in b/build/modules.conf.in index 14ad5dd080..b38900047b 100644 --- a/build/modules.conf.in +++ b/build/modules.conf.in @@ -168,7 +168,7 @@ xml_int/mod_xml_cdr xml_int/mod_xml_rpc xml_int/mod_xml_scgi -#../../libs/freetdm/mod_freetdm +#mod_freetdm|https://github.com/freeswitch/freetdm.git -b master ## Experimental Modules (don't cry if they're broken) #../../contrib/mod/xml_int/mod_xml_odbc diff --git a/configure.ac b/configure.ac index 5ea8e3921e..c6a634eb95 100644 --- a/configure.ac +++ b/configure.ac @@ -2124,7 +2124,6 @@ if test "$use_system_aprutil" != "yes"; then fi AC_CONFIG_SUBDIRS([libs/iksemel]) AC_CONFIG_SUBDIRS([libs/libdingaling]) -AC_CONFIG_SUBDIRS([libs/freetdm]) AC_CONFIG_SUBDIRS([libs/unimrcp]) if test "x${enable_zrtp}" = "xyes"; then AC_CONFIG_SUBDIRS([libs/libzrtp]) diff --git a/libs/.gitignore b/libs/.gitignore index 392aaffdbd..5a83438d92 100644 --- a/libs/.gitignore +++ b/libs/.gitignore @@ -85,12 +85,6 @@ opal /esl/Release/ /flite-*/ /freeradius-client-*/ -/freetdm/build/compile -/freetdm/COPYING -/freetdm/INSTALL -/freetdm/Makefile.in -/freetdm/msvc/Debug/ -/freetdm/msvc/Release/ /iksemel/build/compile /iksemel/doc/Makefile /iksemel/doc/Makefile.in diff --git a/libs/freetdm/.gitignore b/libs/freetdm/.gitignore deleted file mode 100644 index da2caa7d87..0000000000 --- a/libs/freetdm/.gitignore +++ /dev/null @@ -1,39 +0,0 @@ -*.o -*.lo -*.so -*.a -*.orig -*.rej -*.log - -Makefile -config.* -configure -libtool -aclocal.m4 -build/libtool.m4 -build/ltoptions.m4 -build/ltsugar.m4 -build/ltversion.m4 -build/lt~obsolete.m4 - -testanalog -testapp -testboost -testcid -testpri -testr2 -testsangomaboost -testtones - -!/msvc/testanalog/ -!/msvc/testboost/ - -!/sample/boost/Makefile -!/sample/dso/Makefile - -freetdm.2010.sdf -/mod_freetdm/Win32/ -/msvc/Win32/ -/src/ftmod/*/Win32/ -/src/ftmod/*/x64/ diff --git a/libs/freetdm/.update b/libs/freetdm/.update deleted file mode 100644 index b537cc4f2d..0000000000 --- a/libs/freetdm/.update +++ /dev/null @@ -1 +0,0 @@ -Fri Feb 3 11:55:29 PST 2012 diff --git a/libs/freetdm/AUTHORS b/libs/freetdm/AUTHORS deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libs/freetdm/CMakeLists.txt b/libs/freetdm/CMakeLists.txt deleted file mode 100644 index 24cbf7c9eb..0000000000 --- a/libs/freetdm/CMakeLists.txt +++ /dev/null @@ -1,244 +0,0 @@ -# -# cmake file that generate build files for freetdm. -# this automatically includes the tests and also -# mod_freetdm -# -# Arnaldo M Pereira -# -CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -PROJECT(freetdm) - -ADD_SUBDIRECTORY(sample) -ADD_SUBDIRECTORY(mod_freetdm) - -# includes -SET(freetdm_INCLUDES - ${PROJECT_SOURCE_DIR}/src/include - ${PROJECT_SOURCE_DIR}/src/isdn/include - ${PROJECT_SOURCE_DIR}/src/include/private - ${PROJECT_SOURCE_DIR}/src/ftmod/ftmod_sangoma_boost -) -INCLUDE_DIRECTORIES(${freetdm_INCLUDES}) -LINK_DIRECTORIES(${freetdm_BINARY_DIR}) - -# optional includes -IF(DEFINED SNGSS7) - SET(freetdm_INCLUDES ${freetdm_INCLUDES} /usr/include/sng_ss7) -ENDIF(DEFINED SNGSS7) - -IF(DEFINED SNGISDN) - SET(freetdm_INCLUDES ${freetdm_INCLUDES} /usr/include/sng_isdn) -ENDIF(DEFINED SNGISDN) - -# definitions / CFLAGS -ADD_DEFINITIONS(-DFTDM_CONFIG_DIR="/FIXME" -DFTDM_MOD_DIR="/FIXME") -IF(DEFINED WIN32) - ADD_DEFINITIONS(-DFREETDM_EXPORTS -DTELETONE_EXPORTS -DMOD_EXPORTS -DDLL_EXPORTS) -ENDIF(DEFINED WIN32) -IF(DEFINED SNGISDN) - SET(freetdm_INCLUDES ${freetdm_INCLUDES} /usr/include/sng_isdn) -ENDIF(DEFINED SNGISDN) - -# lib sources -SET(freetdm_SOURCES - ${PROJECT_SOURCE_DIR}/src/hashtable.c - ${PROJECT_SOURCE_DIR}/src/hashtable_itr.c - ${PROJECT_SOURCE_DIR}/src/ftdm_io.c - ${PROJECT_SOURCE_DIR}/src/ftdm_queue.c - ${PROJECT_SOURCE_DIR}/src/ftdm_sched.c - ${PROJECT_SOURCE_DIR}/src/ftdm_call_utils.c - ${PROJECT_SOURCE_DIR}/src/ftdm_config.c - ${PROJECT_SOURCE_DIR}/src/ftdm_callerid.c - ${PROJECT_SOURCE_DIR}/src/fsk.c - ${PROJECT_SOURCE_DIR}/src/uart.c - ${PROJECT_SOURCE_DIR}/src/g711.c - ${PROJECT_SOURCE_DIR}/src/libteletone_detect.c - ${PROJECT_SOURCE_DIR}/src/libteletone_generate.c - ${PROJECT_SOURCE_DIR}/src/ftdm_buffer.c - ${PROJECT_SOURCE_DIR}/src/ftdm_threadmutex.c - ${PROJECT_SOURCE_DIR}/src/ftdm_dso.c - ${PROJECT_SOURCE_DIR}/src/ftdm_cpu_monitor.c -) - -# libfreetdm.so -ADD_LIBRARY(${PROJECT_NAME} SHARED ${freetdm_SOURCES}) - -IF(NOT DEFINED WIN32) - TARGET_LINK_LIBRARIES(${PROJECT_NAME} m pthread dl) -ENDIF(NOT DEFINED WIN32) - -REMOVE_DEFINITIONS(-DLL_EXPORTS) - -# tools & tests -IF(NOT DEFINED WIN32) - FOREACH(TOOL testtones testpri testr2 testapp testcid) - ADD_EXECUTABLE(${TOOL} ${PROJECT_SOURCE_DIR}/src/${TOOL}.c) - TARGET_LINK_LIBRARIES(${TOOL} -l${PROJECT_NAME}) - ADD_DEPENDENCIES(${TOOL} ${PROJECT_NAME}) - ENDFOREACH(TOOL) - - ADD_EXECUTABLE(detect_dtmf - ${PROJECT_SOURCE_DIR}/src/detect_dtmf.c - ${PROJECT_SOURCE_DIR}/src/libteletone_detect.c - ) - TARGET_LINK_LIBRARIES(detect_dtmf ${PROJECT_NAME}) - ADD_DEPENDENCIES(detect_dtmf ${PROJECT_NAME}) - - ADD_EXECUTABLE(detect_tones - ${PROJECT_SOURCE_DIR}/src/detect_tones.c - ${PROJECT_SOURCE_DIR}/src/libteletone_detect.c - ) - TARGET_LINK_LIBRARIES(detect_tones ${PROJECT_NAME}) - ADD_DEPENDENCIES(detect_tones ${PROJECT_NAME}) - - ADD_EXECUTABLE(testanalog - ${PROJECT_SOURCE_DIR}/src/testanalog.c - ) - TARGET_LINK_LIBRARIES(testanalog -l${PROJECT_NAME}) - ADD_DEPENDENCIES(testanalog ${PROJECT_NAME}) - - # optional tests/tools - IF(HAVE_SCTP) - ADD_EXECUTABLE(testboost src/testboost.c) - TARGET_LINK_LIBRARIES(testboost ${PROJECT_NAME}) - ENDIF(HAVE_SCTP) -ELSE(NOT DEFINED WIN32) - MESSAGE(WARNING "Not building tools/tests on WIN32 yet.") -ENDIF(NOT DEFINED WIN32) - -# -# ftmod modules -# -SET(ftmod_DIR ${PROJECT_SOURCE_DIR}/src/ftmod) - -IF(DEFINED WIN32) - SET(ftmod_ADDITIONAL_SOURCES - ${PROJECT_SOURCE_DIR}/src/ftdm_io.c - ${PROJECT_SOURCE_DIR}/src/ftdm_config.c - ${PROJECT_SOURCE_DIR}/src/ftdm_queue.c - ${PROJECT_SOURCE_DIR}/src/g711.c - ) - SET(module_list skel analog analog_em) -ELSE(DEFINED WIN32) - SET(module_list skel analog analog_em zt) -ENDIF(DEFINED WIN32) - -# build default modules -FOREACH(module ${module_list}) - ADD_LIBRARY(ftmod_${module} MODULE ${ftmod_DIR}/ftmod_${module}/ftmod_${module}.c ${ftmod_ADDITIONAL_SOURCES}) - TARGET_LINK_LIBRARIES(ftmod_${module} ${PROJECT_NAME}) -ENDFOREACH(module) - -# build isdn ftmod -IF(DEFINED BUILD_FTMOD_ISDN) - SET(ftmod_isdn_SOURCES - ${PROJECT_SOURCE_DIR}/src/isdn/EuroISDNStateNT.c - ${PROJECT_SOURCE_DIR}/src/isdn/EuroISDNStateTE.c - ${PROJECT_SOURCE_DIR}/src/isdn/mfifo.c - ${PROJECT_SOURCE_DIR}/src/isdn/Q921.c - ${PROJECT_SOURCE_DIR}/src/isdn/Q931api.c - ${PROJECT_SOURCE_DIR}/src/isdn/Q931.c - ${PROJECT_SOURCE_DIR}/src/isdn/Q931ie.c - ${PROJECT_SOURCE_DIR}/src/isdn/Q931mes.c - ${PROJECT_SOURCE_DIR}/src/isdn/Q931StateNT.c - ${PROJECT_SOURCE_DIR}/src/isdn/Q931StateTE.c - ${PROJECT_SOURCE_DIR}/src/isdn/nationalmes.c - ${PROJECT_SOURCE_DIR}/src/isdn/nationalStateNT.c - ${PROJECT_SOURCE_DIR}/src/isdn/nationalStateTE.c - ${PROJECT_SOURCE_DIR}/src/isdn/DMSmes.c - ${PROJECT_SOURCE_DIR}/src/isdn/DMSStateNT.c - ${PROJECT_SOURCE_DIR}/src/isdn/DMSStateTE.c - ${PROJECT_SOURCE_DIR}/src/isdn/5ESSmes.c - ${PROJECT_SOURCE_DIR}/src/isdn/5ESSStateNT.c - ${PROJECT_SOURCE_DIR}/src/isdn/5ESSStateTE.c - ${PROJECT_SOURCE_DIR}/src/isdn/Q932mes.c - ${ftmod_DIR}/ftmod_isdn/ftmod_isdn.c - ) - IF(NOT DEFINED WIN32) - ADD_DEFINITIONS(-D_GNU_SOURCE) - ENDIF(NOT DEFINED WIN32) - ADD_LIBRARY(ftmod_isdn MODULE ${ftmod_isdn_SOURCES}) - TARGET_LINK_LIBRARIES(ftmod_isdn ${PROJECT_NAME}) -ENDIF(DEFINED BUILD_FTMOD_ISDN) - -# from now on, optionals -IF(DEFINED LIBSANGOMA) - ADD_LIBRARY(ftmod_wanpipe MODULE ${ftmod_DIR}/ftmod_wanpipe/ftmod_wanpipe.c) - IF(DEFINED WIN32) - MESSAGE(WARNING "FIXME: look for wanpipe headers on win32") - ELSE(DEFINED WIN32) - ADD_DEFINITIONS(-D__LINUX__) - INCLUDE_DIRECTORIES(/usr/include/wanpipe) - ENDIF(DEFINED WIN32) - TARGET_LINK_LIBRARIES(ftmod_wanpipe sangoma ${PROJECT_NAME}) -ENDIF(DEFINED LIBSANGOMA) - -IF(DEFINED HAVE_SCTP) - ADD_LIBRARY(ftmod_sangoma_boost MODULE - ${ftmod_DIR}/ftmod_sangoma_boost/sangoma_boost_client.c - ${ftmod_DIR}/ftmod_sangoma_boost/ftmod_sangoma_boost.c - ) - TARGET_LINK_LIBRARIES(ftmod_sangoma_boost ${PROJECT_NAME}) -ENDIF(DEFINED HAVE_SCTP) - -IF(DEFINED LIBPRI) - ADD_LIBRARY(ftmod_libpri MODULE - ${ftmod_DIR}/ftmod_libpri/libpri_client.c - ${ftmod_DIR}/ftmod_libpri/ftmod_libpri.c - ) - TARGET_LINK_LIBRARIES(ftmod_libpri ${PROJECT_NAME}) -ENDIF(DEFINED LIBPRI) - -IF(DEFINED PRITAP) - ADD_LIBRARY(ftmod_pritap MODULE - ${ftmod_DIR}/ftmod_pritap/pritap_client.c - ${ftmod_DIR}/ftmod_pritap/ftmod_pritap.c - ) - TARGET_LINK_LIBRARIES(ftmod_pritap ${PROJECT_NAME} pri) -ENDIF(DEFINED PRITAP) - -IF(DEFINED SNGSS7) - ADD_LIBRARY(ftmod_sangoma_ss7 MODULE - ${ftmod_DIR}/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c - ${ftmod_DIR}/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c - ${ftmod_DIR}/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c - ${ftmod_DIR}/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c - ${ftmod_DIR}/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c - ${ftmod_DIR}/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c - ${ftmod_DIR}/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c - ${ftmod_DIR}/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c - ${ftmod_DIR}/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c - ${ftmod_DIR}/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c - ${ftmod_DIR}/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c - ${ftmod_DIR}/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c - ${ftmod_DIR}/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c - ) - IF(NOT DEFINED WIN32) - ADD_DEFINITIONS(-D_GNU_SOURCE) - ENDIF(NOT DEFINED WIN32) - TARGET_LINK_LIBRARIES(ftmod_sangoma_ss7 ${PROJECT_NAME} sng_ss7) -ENDIF(DEFINED SNGSS7) - -IF(DEFINED SNGISDN) - ADD_LIBRARY(ftmod_sangoma_isdn MODULE - ${ftmod_DIR}/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c - ${ftmod_DIR}/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c - ${ftmod_DIR}/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c - ${ftmod_DIR}/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c - ${ftmod_DIR}/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c - ${ftmod_DIR}/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c - ${ftmod_DIR}/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c - ${ftmod_DIR}/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c - ${ftmod_DIR}/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c - ${ftmod_DIR}/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c - ) - IF(NOT DEFINED WIN32) - ADD_DEFINITIONS(-D_GNU_SOURCE) - ENDIF(NOT DEFINED WIN32) - TARGET_LINK_LIBRARIES(ftmod_sangoma_isdn ${PROJECT_NAME} sng_isdn) -ENDIF(DEFINED SNGISDN) - -IF(DEFINED OPENR2) - ADD_LIBRARY(ftmod_r2 MODULE ${ftmod_DIR}/ftmod_r2/ftmod_r2.c) - TARGET_LINK_LIBRARIES(ftmod_r2 ${PROJECT_NAME} openr2) -ENDIF(DEFINED OPENR2) diff --git a/libs/freetdm/ChangeLog b/libs/freetdm/ChangeLog deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libs/freetdm/Makefile.am b/libs/freetdm/Makefile.am deleted file mode 100644 index f6211e58e8..0000000000 --- a/libs/freetdm/Makefile.am +++ /dev/null @@ -1,290 +0,0 @@ -# Copyright (c) 2007-2014, Anthony Minessale II -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# * Neither the name of the original author; nor the names of any contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -ACLOCAL_AMFLAGS = -I build -AUTOMAKE_OPTIONS = foreign - -SRC = src - -moddir = @modinstdir@ -libdir = @libdir@ -library_includedir = $(prefix)/include - -INCS = -I$(FT_SRCDIR)/$(SRC)/include -I$(FT_SRCDIR)/$(SRC)/include/private - -# we needed to separate CFLAGS in FTDM_COMPAT_CFLAGS and FTDM_CFLAGS due to -c99 which causes problems with wanpipe headers -FTDM_COMPAT_CFLAGS = $(INCS) -DFTDM_CONFIG_DIR=\"@confdir@\" -DFTDM_MOD_DIR=\"$(moddir)\" @COMP_VENDOR_COMPAT_CFLAGS@ @DEFS@ -FTDM_CFLAGS = $(INCS) -DFTDM_CONFIG_DIR=\"@confdir@\" -DFTDM_MOD_DIR=\"$(moddir)\" @COMP_VENDOR_CFLAGS@ @DEFS@ -COMPILE = $(CC) $(FTDM_CFLAGS) -LTCOMPILE = $(LIBTOOL) --mode=compile --tag=CC $(COMPILE) -LINK = $(LIBTOOL) --mode=link --tag=CC $(CC) $(FTDM_CFLAGS) $(LDFLAGS) -o $@ - - -# -# GNU pkgconfig file -# -EXTRA_DIST = freetdm.pc.in - -pkgconfigdir = @pkgconfigdir@ -pkgconfig_DATA = freetdm.pc - - -# -# libfreetdm -# -libfreetdm_la_SOURCES = \ - $(SRC)/hashtable.c \ - $(SRC)/hashtable_itr.c \ - $(SRC)/ftdm_io.c \ - $(SRC)/ftdm_state.c \ - $(SRC)/ftdm_queue.c \ - $(SRC)/ftdm_sched.c \ - $(SRC)/ftdm_call_utils.c \ - $(SRC)/ftdm_variables.c \ - $(SRC)/ftdm_config.c \ - $(SRC)/ftdm_callerid.c \ - $(SRC)/fsk.c \ - $(SRC)/uart.c \ - $(SRC)/g711.c \ - $(SRC)/libteletone_detect.c \ - $(SRC)/libteletone_generate.c \ - $(SRC)/ftdm_buffer.c \ - $(SRC)/ftdm_threadmutex.c \ - $(SRC)/ftdm_dso.c \ - $(SRC)/ftdm_cpu_monitor.c \ - $(SRC)/ftdm_backtrace.c - -library_include_HEADERS = \ - $(SRC)/include/freetdm.h \ - $(SRC)/include/ftdm_declare.h \ - $(SRC)/include/ftdm_threadmutex.h \ - $(SRC)/include/ftdm_os.h \ - $(SRC)/include/ftdm_call_utils.h \ - $(SRC)/include/ftdm_dso.h - -lib_LTLIBRARIES = libfreetdm.la -libfreetdm_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) -libfreetdm_la_LDFLAGS = -version-info 1:0:0 $(AM_LDFLAGS) -libfreetdm_la_LIBADD = $(LIBS) - -core: libfreetdm.la -core-install: install-libLTLIBRARIES - -# -# tools & test programs -# -noinst_PROGRAMS = testtones detect_tones detect_dtmf testpri testr2 testanalog testapp testcid - -testapp_SOURCES = $(SRC)/testapp.c -testapp_LDADD = libfreetdm.la -testapp_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) - -testcid_SOURCES = $(SRC)/testcid.c -testcid_LDADD = libfreetdm.la -testcid_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) - -testtones_SOURCES = $(SRC)/testtones.c -testtones_LDADD = libfreetdm.la -testtones_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) - -detect_tones_SOURCES = $(SRC)/detect_tones.c -detect_tones_LDADD = libfreetdm.la -detect_tones_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) - -detect_dtmf_SOURCES = $(SRC)/detect_dtmf.c -detect_dtmf_LDADD = libfreetdm.la -detect_dtmf_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) - -#testisdn_SOURCES = $(SRC)/testisdn.c -#testisdn_LDADD = libfreetdm.la -#testisdn_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) - -testpri_SOURCES = $(SRC)/testpri.c -testpri_LDADD = libfreetdm.la -testpri_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) - -testr2_SOURCES = $(SRC)/testr2.c -testr2_LDADD = libfreetdm.la -testr2_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) - -testanalog_SOURCES = $(SRC)/testanalog.c -testanalog_LDADD = libfreetdm.la -testanalog_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) - -# -# ftmod modules -# -mod_LTLIBRARIES = ftmod_zt.la ftmod_skel.la ftmod_analog.la ftmod_analog_em.la - -ftmod_zt_la_SOURCES = $(SRC)/ftmod/ftmod_zt/ftmod_zt.c -ftmod_zt_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) -ftmod_zt_la_LDFLAGS = -shared -module -avoid-version -ftmod_zt_la_LIBADD = libfreetdm.la - -ftmod_skel_la_SOURCES = $(SRC)/ftmod/ftmod_skel/ftmod_skel.c -ftmod_skel_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) -ftmod_skel_la_LDFLAGS = -shared -module -avoid-version -ftmod_skel_la_LIBADD = libfreetdm.la - -ftmod_analog_la_SOURCES = $(SRC)/ftmod/ftmod_analog/ftmod_analog.c -ftmod_analog_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) -ftmod_analog_la_LDFLAGS = -shared -module -avoid-version -ftmod_analog_la_LIBADD = libfreetdm.la - -ftmod_analog_em_la_SOURCES = $(SRC)/ftmod/ftmod_analog_em/ftmod_analog_em.c -ftmod_analog_em_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) -ftmod_analog_em_la_LDFLAGS = -shared -module -avoid-version -ftmod_analog_em_la_LIBADD = libfreetdm.la - -if HAVE_LIBSANGOMA -mod_LTLIBRARIES += ftmod_wanpipe.la -ftmod_wanpipe_la_SOURCES = $(SRC)/ftmod/ftmod_wanpipe/ftmod_wanpipe.c -# some structures within Wanpipe drivers are not c99 compatible, so we need to compile ftmod_wanpipe -# without c99 flags, use FTDM_COMPAT_CFLAGS instead -ftmod_wanpipe_la_CFLAGS = $(FTDM_COMPAT_CFLAGS) $(AM_CFLAGS) -D__LINUX__ -I/usr/include/wanpipe -ftmod_wanpipe_la_LDFLAGS = -shared -module -avoid-version -ftmod_wanpipe_la_LIBADD = libfreetdm.la -lsangoma -endif - -if HAVE_LIBISDN -mod_LTLIBRARIES += ftmod_isdn.la -ftmod_isdn_la_SOURCES = $(SRC)/ftmod/ftmod_isdn/ftmod_isdn.c -ftmod_isdn_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) -D_GNU_SOURCE $(LIBISDN_CPPFLAGS) $(PCAP_CPPFLAGS) -ftmod_isdn_la_LDFLAGS = -shared -module -avoid-version $(LIBISDN_LDFLAGS) $(PCAP_LDFLAGS) -ftmod_isdn_la_LIBADD = libfreetdm.la $(LIBISDN_LIBS) $(PCAP_LIBS) -endif - -if HAVE_LIBPRI -mod_LTLIBRARIES += ftmod_libpri.la -ftmod_libpri_la_SOURCES = $(SRC)/ftmod/ftmod_libpri/ftmod_libpri.c $(SRC)/ftmod/ftmod_libpri/lpwrap_pri.c -ftmod_libpri_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) $(LIBPRI_CPPFLAGS) -ftmod_libpri_la_LDFLAGS = -shared -module -avoid-version $(LIBPRI_LDFLAGS) -ftmod_libpri_la_LIBADD = libfreetdm.la $(LIBPRI_LIBS) -endif - -if HAVE_PRITAP -mod_LTLIBRARIES += ftmod_pritap.la -ftmod_pritap_la_SOURCES = $(SRC)/ftmod/ftmod_pritap/ftmod_pritap.c -ftmod_pritap_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) -ftmod_pritap_la_LDFLAGS = -shared -module -avoid-version -ftmod_pritap_la_LIBADD = libfreetdm.la -lpri -endif - -if HAVE_SNG_SS7 -mod_LTLIBRARIES += ftmod_sangoma_ss7.la -ftmod_sangoma_ss7_la_SOURCES = \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_m2ua_xml.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_m2ua.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_relay.c - -ftmod_sangoma_ss7_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) -D_GNU_SOURCE -ftmod_sangoma_ss7_la_LDFLAGS = -shared -module -avoid-version -ftmod_sangoma_ss7_la_LIBADD = libfreetdm.la -lsng_ss7 -endif - -if HAVE_SNG_ISDN -mod_LTLIBRARIES += ftmod_sangoma_isdn.la -ftmod_sangoma_isdn_la_SOURCES = \ - $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c \ - $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c \ - $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c \ - $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c \ - $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_transfer.c \ - $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c \ - $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c \ - $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c \ - $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c \ - $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c \ - $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c - -ftmod_sangoma_isdn_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) -D_GNU_SOURCE -ftmod_sangoma_isdn_la_LDFLAGS = -shared -module -avoid-version -ftmod_sangoma_isdn_la_LIBADD = libfreetdm.la -lsng_isdn -endif - -if HAVE_OPENR2 -mod_LTLIBRARIES += ftmod_r2.la -ftmod_r2_la_SOURCES = $(SRC)/ftmod/ftmod_r2/ftmod_r2.c $(SRC)/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.c -ftmod_r2_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) -ftmod_r2_la_LDFLAGS = -shared -module -avoid-version -ftmod_r2_la_LIBADD = libfreetdm.la -lopenr2 -endif - -if HAVE_WAT -mod_LTLIBRARIES += ftmod_gsm.la -ftmod_gsm_la_SOURCES = $(SRC)/ftmod/ftmod_gsm/ftmod_gsm.c -ftmod_gsm_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) -ftmod_gsm_la_LDFLAGS = -shared -module -avoid-version -ftmod_gsm_la_LIBADD = libfreetdm.la -lwat -endif - -if HAVE_MISDN -mod_LTLIBRARIES += ftmod_misdn.la -ftmod_misdn_la_SOURCES = $(SRC)/ftmod/ftmod_misdn/ftmod_misdn.c -ftmod_misdn_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) $(MISDN_CFLAGS) -D_GNU_SOURCE -ftmod_misdn_la_LDFLAGS = -shared -module -avoid-version -ftmod_misdn_la_LIBADD = libfreetdm.la -endif - -dox doxygen: - doxygen $(FT_SRCDIR)/docs/Doxygen.conf - -mod_freetdm/mod_freetdm.so: libfreetdm.la mod_freetdm/mod_freetdm.c - $(MAKE) -C mod_freetdm - -mod_freetdm: mod_freetdm/mod_freetdm.so - -mod_freetdm-install: mod_freetdm - $(MAKE) -C mod_freetdm install - -mod_freetdm-clean: - @if [ -f mod_freetdm/mod_freetdm.so ] ; then \ - $(MAKE) -C mod_freetdm clean ; \ - fi - -install-data-local: - $(mkinstalldirs) $(DESTDIR)$(prefix) - $(mkinstalldirs) $(DESTDIR)@confdir@ - @[ -f "$(DESTDIR)@confdir@/freetdm.conf" ] || ( cp conf/*.conf $(DESTDIR)@confdir@) - @echo FreeTDM Installed diff --git a/libs/freetdm/NEWS b/libs/freetdm/NEWS deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libs/freetdm/README b/libs/freetdm/README deleted file mode 100644 index 4ca13d19c9..0000000000 --- a/libs/freetdm/README +++ /dev/null @@ -1,3 +0,0 @@ -FreeTDM -http://wiki.freeswitch.org/wiki/FreeTDM - diff --git a/libs/freetdm/TODO b/libs/freetdm/TODO deleted file mode 100644 index 6b4cf71f5f..0000000000 --- a/libs/freetdm/TODO +++ /dev/null @@ -1,22 +0,0 @@ -== Interface inconsistency == -- enum_id member of ftdm_event_t is inconsistent. Most of the time is just for OOB events, the only other - type of event as of now is FTDM_EVENT_DTMF and is not using the enum_id member. I think we can get rid - of the FTDM_EVENT_DTMF and create ftdm_dtmf_event_t type instead of reusing ftdm_event_t - then ftdm_event_t would be renamed to ftdm_oob_event_t and the enum_id renamed to type, then ftdm_span_next_event() - will only return OOB events - -- Deprecate last_error members. - It requires a lot of discipline to set the last_error string for every failure. - It does not add much value to the user either, most of the errors are criptic and - cannot be shown to end users, we already provide extensive logging for problem - troubleshooting. - -- Implement threaded IO. - Currently IO modules only work on-demand, where the user (ie, FreeSWITCH) drives the read/write - of media. If the user stops reading, some functions are not possible - (DTMF detection or Hangup tone detection). It would be useful to implement a FreeTDM mode - where the media is driven by a group of threads that are always reading (and possibly writing) - then when the user does ftdm_channel_read(), the media would be read from the buffers filled - by the media thread and not from the underlying IO device, this gives a chance to FreeTDM to - still perform hangup detection or other media services even if the application is not reading. - diff --git a/libs/freetdm/acinclude.m4 b/libs/freetdm/acinclude.m4 deleted file mode 100644 index 097278b6ef..0000000000 --- a/libs/freetdm/acinclude.m4 +++ /dev/null @@ -1,2 +0,0 @@ -m4_include([build/ax_compiler_vendor.m4]) -m4_include([build/libpcap.m4]) diff --git a/libs/freetdm/bootstrap b/libs/freetdm/bootstrap deleted file mode 100755 index 247d396da5..0000000000 --- a/libs/freetdm/bootstrap +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -autoheader -libtoolize --force --copy -aclocal -automake -f --copy --add-missing -autoconf diff --git a/libs/freetdm/build/ax_compiler_vendor.m4 b/libs/freetdm/build/ax_compiler_vendor.m4 deleted file mode 100644 index a24a58da0f..0000000000 --- a/libs/freetdm/build/ax_compiler_vendor.m4 +++ /dev/null @@ -1,15 +0,0 @@ -AC_DEFUN([AX_COMPILER_VENDOR], -[ -AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, - [ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=unknown - # note: don't check for gcc first since some other compilers define __GNUC__ - for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do - vencpp="defined("`echo $ventest | cut -d: -f2 | sed 's/,/) || defined(/g'`")" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ -#if !($vencpp) - thisisanerror; -#endif -])], [ax_cv_]_AC_LANG_ABBREV[_compiler_vendor=`echo $ventest | cut -d: -f1`; break]) - done - ]) -]) diff --git a/libs/freetdm/build/libpcap.m4 b/libs/freetdm/build/libpcap.m4 deleted file mode 100644 index ea7581e69b..0000000000 --- a/libs/freetdm/build/libpcap.m4 +++ /dev/null @@ -1,150 +0,0 @@ -dnl libpcap.m4--PCAP libraries and includes -dnl Derrick Brashear -dnl from KTH krb and Arla -dnl $Id: libpcap.m4,v 1.4 2006/01/20 20:21:09 snsimon Exp $ -dnl 2010/10/31 (stkn): -dnl rename: PCAP_INC_FLAGS -> PCAP_CPPFLAGS -dnl rename: PCAP_LIB_FLAGS -> PCAP_LDFLAGS (-L flags only) -dnl add: PCAP_LIBS (libs only) - -AC_DEFUN([PCAP_INC_WHERE1], [ -ac_cv_found_pcap_inc=no -if test -f "$1/pcap.h" ; then - ac_cv_found_pcap_inc=yes -fi -]) - -AC_DEFUN([PCAP_INC_WHERE], [ - for i in $1; do - AC_MSG_CHECKING(for pcap header in $i) - PCAP_INC_WHERE1($i) - if test "$ac_cv_found_pcap_inc" = "yes"; then - ac_cv_pcap_where_inc=$i - AC_MSG_RESULT(found) - break - else - AC_MSG_RESULT(no found) - fi - done -]) - -AC_DEFUN([PCAP_LIB_WHERE1], [ -saved_LIBS=$LIBS -LIBS="$saved_LIBS -L$1 -lpcap" -AC_TRY_LINK(, -[pcap_lookupdev("");], -[ac_cv_found_pcap_lib=yes], -ac_cv_found_pcap_lib=no) -LIBS=$saved_LIBS -]) - -AC_DEFUN([TEST_LIBPATH], [ -changequote(<<, >>) -define(<>, translit(ac_cv_found_$2_lib, <<- *>>, <<__p>>)) -changequote([, ]) -if test "$AC_CV_FOUND" = "yes"; then - if test \! -r "$1/lib$2.a" -a \! -r "$1/lib$2.so" -a \! -r "$1/lib$2.sl" -a \! -r "$1/lib$2.dylib"; then - AC_CV_FOUND=no - fi -fi -]) - - -AC_DEFUN([PCAP_LIB_WHERE], [ - for i in $1; do - AC_MSG_CHECKING(for pcap library in $i) - PCAP_LIB_WHERE1($i) - TEST_LIBPATH($i, pcap) - if test "$ac_cv_found_pcap_lib" = "yes" ; then - ac_cv_pcap_where_lib=$i - AC_MSG_RESULT(found) - break - else - AC_MSG_RESULT(no found) - fi - done -]) - -AC_DEFUN([FIND_LIB_SUBDIR], -[dnl -AC_ARG_WITH([lib-subdir], AC_HELP_STRING([--with-lib-subdir=DIR],[Find libraries in DIR instead of lib])) -AC_CHECK_SIZEOF(long) -AC_CACHE_CHECK([what directory libraries are found in], [ac_cv_cmu_lib_subdir], -[test "X$with_lib_subdir" = "Xyes" && with_lib_subdir= -test "X$with_lib_subdir" = "Xno" && with_lib_subdir= - if test "X$with_lib_subdir" = "X" ; then - ac_cv_cmu_lib_subdir=lib - if test $ac_cv_sizeof_long -eq 4 ; then - test -d /usr/lib32 && ac_cv_cmu_lib_subdir=lib32 - test -r /usr/lib/libpcap.so && ac_cv_cmu_lib_subdir=lib - fi - if test $ac_cv_sizeof_long -eq 8 ; then - test -d /usr/lib64 && ac_cv_cmu_lib_subdir=lib64 - fi - else - ac_cv_cmu_lib_subdir=$with_lib_subdir - fi]) - AC_SUBST(LIB_SUBDIR, $ac_cv_cmu_lib_subdir) - ]) - - -AC_DEFUN([AX_LIB_PCAP], [ -AC_REQUIRE([FIND_LIB_SUBDIR]) -AC_ARG_WITH(pcap, - [ --with-pcap=PREFIX Compile with PCAP support], - [if test "X$with_pcap" = "X"; then - with_pcap=yes - fi]) -AC_ARG_WITH(pcap-lib, - [ --with-pcap-lib=dir use pcap libraries in dir], - [if test "$withval" = "yes" -o "$withval" = "no"; then - AC_MSG_ERROR([No argument for --with-pcap-lib]) - fi]) -AC_ARG_WITH(pcap-include, - [ --with-pcap-include=dir use pcap headers in dir], - [if test "$withval" = "yes" -o "$withval" = "no"; then - AC_MSG_ERROR([No argument for --with-pcap-include]) - fi]) - - if test "X$with_pcap" != "X"; then - if test "$with_pcap" != "yes"; then - ac_cv_pcap_where_lib=$with_pcap - ac_cv_pcap_where_inc=$with_pcap/include - fi - fi - - if test "X$with_pcap_lib" != "X"; then - ac_cv_pcap_where_lib=$with_pcap_lib - fi - if test "X$ac_cv_pcap_where_lib" = "X"; then - PCAP_LIB_WHERE(/usr/$LIB_SUBDIR /usr/local/$LIB_SUBDIR) - fi - - if test "X$with_pcap_include" != "X"; then - ac_cv_pcap_where_inc=$with_pcap_include - fi - if test "X$ac_cv_pcap_where_inc" = "X"; then - PCAP_INC_WHERE(/usr/ng/include /usr/include /usr/local/include) - fi - - AC_MSG_CHECKING(whether to include pcap) - if test "X$ac_cv_pcap_where_lib" != "X" -a "X$ac_cv_pcap_where_inc" != "X"; then - ac_cv_found_pcap=yes - AC_MSG_RESULT(yes) - PCAP_INC_DIR=$ac_cv_pcap_where_inc - PCAP_LIB_DIR=$ac_cv_pcap_where_lib - PCAP_CPPFLAGS="-I${PCAP_INC_DIR}" - PCAP_LDFLAGS="-L${PCAP_LIB_DIR}" - PCAP_LIBS="-lpcap" - AC_SUBST(PCAP_INC_DIR) - AC_SUBST(PCAP_LIB_DIR) - AC_SUBST(PCAP_CPPFLAGS) - AC_SUBST(PCAP_LDFLAGS) - AC_SUBST(PCAP_LIBS) - AC_DEFINE([HAVE_LIBPCAP],[1],[libpcap]) - else - ac_cv_found_pcap=no - AC_MSG_RESULT(no) - fi - ]) - diff --git a/libs/freetdm/conf/freetdm.conf b/libs/freetdm/conf/freetdm.conf deleted file mode 100644 index 0d53992979..0000000000 --- a/libs/freetdm/conf/freetdm.conf +++ /dev/null @@ -1,82 +0,0 @@ -; !! THIS IS A SAMPLE CONFIGURATION ONLY !! - -; refer to http://wiki.freeswitch.org/wiki/FreeTDM for further documentation - -[general] -; whether to launch a thread for CPU usage monitoring -cpu_monitor => no - -; How often (in milliseconds) monitor CPU usage -cpu_monitoring_interval => 1000 - -; At what CPU percentage raise a CPU alarm -cpu_set_alarm_threshold => 80 - -; At what CPU percentage stop the CPU alarm -cpu_clear_alarm_threshold => 70 - -; Which action to take when the CPU alarm is raised -; it can be warn and/or reject calls -; cpu_alarm_action => warn,reject -cpu_alarm_action => warn - -; Where to dump DTMF debug files (see per span debugdtmf=yes option) -debugdtmf_directory=/full/path/to/dtmf/directory - -; spans are defined with [span ] -; the span type can either be zt, wanpipe or pika -; the span name can be any unique string -[span wanpipe myWanpipe] - -; valid trunk types are: FXO, FXS, EM, E1, T1, J1, BRI, BRI_PTMP -trunk_type => FXS - -; add FXS channels from 3 to 4 at wanpipe span 1 to this freetdm span -fxs-channel => 1:3-4 - -; IO stats. Defaults to yes, you can print the stats with ftdm iostats print -; This feature depends on the span IO type, currently only Wanpipe spans support it -; This may cause a warning to be printed once in a while if audio is not provided fast enough -; and causes the driver to transmit an idle frame (when there is no data provided by the application) -iostats => yes - -[span wanpipe myWanpipe2] -trunk_type => FXO -; This number will be used as DNIS for FXO devices -fxo-channel => 1:1-2 - -[span zt myZaptelSpan] -number => 9999 -fxs-channel => 1 - -[span zt mySecondZaptelSpan] -; This number will be used as DNIS for FXO devices -number => 2 -fxo-channel => 3 - -; MFC-R2 typical span configuration - -; MFC-R2 with wanpipe (Sangoma) -[span wanpipe myWanpipeSpan] -trunk_type => E1 -cas-channel => 1-15:1101 -cas-channel => 17-31:1101 - -; MFC-R2 with Zaptel/DAHDI -[span zt myWanpipeSpan] -trunk_type => E1 -cas-channel => 1-15:1101 -cas-channel => 17-31:1101 - -; generic channel parameters -; this parameters are accepted by any type of span/channel -; remember that for generic channel parameters only channels -; below the parameter within the span will be affected - -; Channel audio gain -; rxgain => 0.0 -; txgain => 0.0 - -; Whether to perform media dumps for DTMF debugging -; debugdtmf => yes - diff --git a/libs/freetdm/conf/freetdm.conf.xml b/libs/freetdm/conf/freetdm.conf.xml deleted file mode 100644 index 0b006dc704..0000000000 --- a/libs/freetdm/conf/freetdm.conf.xml +++ /dev/null @@ -1,633 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/conf/pika.conf b/libs/freetdm/conf/pika.conf deleted file mode 100644 index 01629fd08e..0000000000 --- a/libs/freetdm/conf/pika.conf +++ /dev/null @@ -1,43 +0,0 @@ -; you dont need this file unless you use PIKA boards - -; each category is a config profile -; to apply the profile append it to a channel def in -; freetdm.conf with @ -; e.g. -; [span pika] -; name => pika -; number => pika -; fxs-channel => 1:0:1-12@default - -[default] -; region is na or eu -;region => na -;rx-gain => 0.00 -;rx-agc-enabled => false -;rx-agc-targetPower => -15.00 -;rx-agc-minGain => -6.00 -;rx-agc-maxGain => 18.00 -;rx-agc-attackRate => 170 -;rx-agc-decayRate => 750 -;rx-agc-speechThreshold => -36.00 -;rx-vad-enabled => false -;rx-vad-activationThreshold => -40.00 -;rx-vad-activationDebounceTime => 72 -;rx-vad-deactivationThreshold => -40.00 -;rx-vad-deactivationDebounceTime => 984 -;rx-vad-preSpeechBufferSize => 240 -;tx-gain => 0.00 -;tx-agc-enabled => true -;tx-agc-targetPower => -15.00 -;tx-agc-minGain => -6.00 -;tx-agc-maxGain => 18.00 -;tx-agc-attackRate => 170 -;tx-agc-decayRate => 750 -;tx-agc-speechThreshold => -36.00 -;ec-enabled => false -;ec-doubleTalkerThreshold => -6.00 -;ec-speechPresentThreshold => -40.00 -;ec-echoSuppressionThreshold => -18.00 -;ec-echoSuppressionEnabled => true -;ec-comfortNoiseEnabled => true -;ec-adaptationModeEnabled => true diff --git a/libs/freetdm/conf/tones.conf b/libs/freetdm/conf/tones.conf deleted file mode 100644 index 9bb0b43e92..0000000000 --- a/libs/freetdm/conf/tones.conf +++ /dev/null @@ -1,142 +0,0 @@ -[us] -generate-dial => v=-7;%(1000,0,350,440) -detect-dial => 350,440 - -generate-ring => v=-7;%(2000,4000,440,480) -detect-ring => 440,480 - -generate-busy => v=-7;%(500,500,480,620) -detect-busy => 480,620 - -generate-attn => v=0;%(100,100,1400,2060,2450,2600) -detect-attn => 1400,2060,2450,2600 - -generate-callwaiting-sas => v=0;%(300,0,440) -detect-callwaiting-sas => 440 - -generate-callwaiting-cas => v=0;%(80,0,2750,2130) -detect-callwaiting-cas => 2750,2130 - -detect-fail1 => 913.8 -detect-fail2 => 1370.6 -detect-fail3 => 1776.7 - - -[sg] -generate-dial => v=-7;%(1000,0,425) -detect-dial => 425 - -generate-ring => v=-7;%(2000,4000,425) -detect-ring => 425 - -generate-busy => v=-7;%(750,750,425) -detect-busy => 425 - -generate-attn => v=0;%(100,100,1400,2060,2450,2600) -detect-attn => 1400,2060,2450,2600 - -generate-callwaiting-sas => v=0;%(300,0,440) -detect-callwaiting-sas => 440 - -generate-callwaiting-cas => v=0;%(80,0,2750,2130) -detect-callwaiting-cas => 2750,2130 - -detect-fail1 => 913.8 -detect-fail2 => 1370.6 -detect-fail3 => 1776.7 - - -[ru] -generate-dial => v=-7;%(1000,425) -detect-dial => 0 - -generate-ring => v=-7;%(800,5000,425,0) -detect-ring => 425,0 - -generate-busy => v=-7;%(350,350,425,0) -detect-busy => 425,0 - -generate-attn => v=0;%(100,100,1400,2060,2450,2600) -detect-attn => 1400,2060,2450,2600 - -generate-callwaiting-sas => v=0;%(300,0,440) -detect-callwaiting-sas => 440,480 - -generate-callwaiting-cas => v=0;%(80,0,2750,2130) -detect-callwaiting-cas => 2750,2130 - -detect-fail1 => 913.8 -detect-fail2 => 1370.6 -detect-fail3 => 1776.7 - - -[in] -generate-dial => v=-7;%(1000,0,375,425) -detect-dial => 375,425 - -generate-ring => v=-7;%(2000,4000,440,480) -detect-ring => 440,480 - -generate-busy => v=-7;%(500,500,480,620) -detect-busy => 480,620 - -generate-attn => v=0;%(100,100,1400,2060,2450,2600) -detect-attn => 1400,2060,2450,2600 - -generate-callwaiting-sas => v=0;%(300,0,440) -detect-callwaiting-sas => 440 - -generate-callwaiting-cas => v=0;%(80,0,2750,2130) -detect-callwaiting-cas => 2750,2130 - -detect-fail1 => 913.8 -detect-fail2 => 1370.6 -detect-fail3 => 776.7 - - -[th] -generate-dial => v=-7;%(1000,0,400,400) -detect-dial => 400,400 - -generate-ring => v=-7;%(2000,4000,400,400) -detect-ring => 400,400 - -generate-busy => v=-7;%(500,500,480,620) -detect-busy => 480,620 - -generate-attn => v=0;%(100,100,1400,2060,2450,2600) -detect-attn => 1400,2060,2450,2600 - -generate-callwaiting-sas => v=0;%(300,0,440) -detect-callwaiting-sas => 440 - -generate-callwaiting-cas => v=0;%(80,0,2750,2130) -detect-callwaiting-cas => 2750,2130 - -detect-fail1 => 913.8 -detect-fail2 => 1370.6 -detect-fail3 => 1776.7 - - -[au] -generate-dial => v=-7;%(1000,0,413,438) -detect-dial => 413,438 - -generate-ring => v=-7;%(400,200,413,438);%(400,2000,413,438) -detect-ring => 413,438 - -generate-busy => v=-7;%(375,375,425) -detect-busy => 425 - -generate-attn => v=0;%(100,100,1400,2060,2450,2600) -detect-attn => 1400,2060,2450,2600 - -generate-callwaiting-sas => v=0;%(300,0,440) -detect-callwaiting-sas => 440 - -generate-callwaiting-cas => v=0;%(80,0,2750,2130) -detect-callwaiting-cas => 2750,2130 - -detect-fail1 => 913.8 -detect-fail2 => 1370.6 -detect-fail3 => 776.7 diff --git a/libs/freetdm/conf/wanpipe.conf b/libs/freetdm/conf/wanpipe.conf deleted file mode 100644 index 3784eaf17a..0000000000 --- a/libs/freetdm/conf/wanpipe.conf +++ /dev/null @@ -1,13 +0,0 @@ -[defaults] -; User space interval at which data will be delivered -codec_ms => 20 - -; wink and flash interval -wink_ms => 150 -flash_ms => 750 - -; size of the driver queue of elements of MTU size -; typical case is 10 elements of 80 bytes each (10ms of ulaw/alaw) -; don't mess with this if you don't know what you're doing -; txqueue_size => 10 -; rxqueue_size => 10 diff --git a/libs/freetdm/conf/zt.conf b/libs/freetdm/conf/zt.conf deleted file mode 100644 index a060a40315..0000000000 --- a/libs/freetdm/conf/zt.conf +++ /dev/null @@ -1,8 +0,0 @@ -[defaults] -codec_ms => 20 -wink_ms => 150 -flash_ms => 750 -echo_cancel_level => 64 -rxgain => 0.0 -txgain => 0.0 - diff --git a/libs/freetdm/configure.ac b/libs/freetdm/configure.ac deleted file mode 100644 index e6aad59e52..0000000000 --- a/libs/freetdm/configure.ac +++ /dev/null @@ -1,480 +0,0 @@ -# -*- Autoconf -*- -# Process this file with autoconf to produce a configure script. - -AC_PREREQ([2.59]) -AC_INIT([freetdm], [0.1], [bugs@freeswitch.org]) -AC_CONFIG_SRCDIR([src/ftdm_io.c]) - -AC_CONFIG_AUX_DIR([build]) -AC_CONFIG_MACRO_DIR([build]) -AM_INIT_AUTOMAKE - -# >=automake-1.11 -m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) - -# override some default libtool behavior and invoke AC_PROG_LIBTOOL -# (see http://lists.gnu.org/archive/html/libtool/2007-03/msg00000.html) -m4_defun([_LT_AC_LANG_F77_CONFIG], [:]) -m4_defun([_LT_AC_LANG_GCJ_CONFIG], [:]) -m4_defun([_LT_AC_LANG_RC_CONFIG], [:]) - -# Checks for programs. -AC_PROG_CC -AC_PROG_MAKE_SET -AM_PROG_CC_C_O -AC_PROG_LIBTOOL -AC_PROG_INSTALL - -# NOTE: pkg-config is used to detect libisdn -m4_ifdef([PKG_PROG_PKG_CONFIG], - [PKG_PROG_PKG_CONFIG], - [AC_MSG_WARN([pkg-config missing (required for libisdn detection)])] -) - -AX_COMPILER_VENDOR - -# AC_PREFIX_DEFAULT does not get expanded until too late so we need -# to do this to use prefix in this script -AC_PREFIX_DEFAULT([/usr/local/freetdm]) -if test "x${prefix}" = "xNONE" ; then - prefix='/usr/local/freetdm' -fi - -# Absolute source/build directory -FT_SRCDIR=`(cd $srcdir && pwd)` -ft_builddir=`pwd` -AC_SUBST([FT_SRCDIR]) -AC_SUBST([ft_builddir]) - -if test "$sysconfdir" = "\${prefix}/etc" ; then - confdir="$prefix/conf" -else - confdir="$sysconfdir" -fi - -AC_SUBST([confdir]) - -DEFAULT_INCLUDES="-I. -I./src/include -I\$(srcdir)" -AC_SUBST([DEFAULT_INCLUDES]) - -# Where to install the modules -AC_ARG_WITH([modinstdir], - [AS_HELP_STRING([--with-modinstdir=DIR], [Install modules into this location (default: ${prefix}/mod)])], - [case "${withval}" in - no|yes) AC_MSG_ERROR([Invalid value \"${withval}\", option requires a valid path]) ;; - *) modinstdir="${withval}" ;; - esac], - [modinstdir="${prefix}/mod"] -) -AC_SUBST([modinstdir]) - -# freetdm.pc pkgconfig file -AC_ARG_WITH([pkgconfigdir], - [AS_HELP_STRING([--with-pkgconfigdir=DIR], [Installation directory for pkgconfig file (default: ${libdir}/pkgconfig)])], - [case "${withval}" in - yes|no) AC_MSG_ERROR([Invalid value ${withval} for option --with-pkgconfigdir]) ;; - *) pkgconfigdir="${withval}" ;; - esac - ], - [pkgconfigdir="${libdir}/pkgconfig"] -) -AC_SUBST([pkgconfigdir]) - -AC_ARG_ENABLE([enable_64], - [AS_HELP_STRING([--enable-64], [Enable 64bit compilation])], - [enable_64="${enableval}"], - [enable_64="no"] -) - -case "${ax_cv_c_compiler_vendor}" in -gnu) - COMP_VENDOR_CFLAGS="-ffast-math -Wall -Werror -Wunused-variable -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -O0" - ;; -sun) - COMP_VENDOR_CFLAGS="-xc99=all -mt -xCC -xvpara" - if test "$enable_64" != "no" ; then - COMP_VENDOR_CFLAGS="-m64 $COMP_VENDOR_CFLAGS" - fi - ;; -*) - COMP_VENDOR_COMPAT_CFLAGS="-Wall -Werror -Wunused-variable -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes" - COMP_VENDOR_CFLAGS="-std=c99 $COMP_VENDOR_COMPAT_CFLAGS" - ;; -esac -AC_SUBST([COMP_VENDOR_COMPAT_CFLAGS]) -AC_SUBST([COMP_VENDOR_CFLAGS]) - - -# Enable debugging -AC_ARG_ENABLE([debug], - [AC_HELP_STRING([--enable-debug], [build with debug information])], - [enable_debug="${enableval}"], - [enable_debug="yes"] -) -if test "${enable_debug}" != "no"; then - AC_DEFINE([DEBUG], [], [Enable extra debugging.]) - - if test "x${ax_cv_c_compiler_vendor}" = "xgnu" ; then - COMP_VENDOR_CFLAGS="$COMP_VENDOR_CFLAGS -g -ggdb" - fi -fi -AC_SUBST([COMP_VENDOR_CFLAGS]) - -AC_CHECK_LIB([dl], [dlopen]) -AC_CHECK_LIB([pthread], [pthread_create]) -AC_CHECK_LIB([m], [cos]) - -AC_CHECK_HEADERS([netdb.h sys/select.h execinfo.h]) - -AC_CHECK_FUNC([gethostbyname_r], - [], [AC_CHECK_LIB([nsl], [gethostbyname_r])] -) -if test "$ac_cv_func_gethostbyname_r" = "yes" -o "$ac_cv_lib_nsl_gethostbyname_r" = "yes" -then - AC_MSG_CHECKING([whether gethostbyname_r requires five arguments]) - - ac_cv_func_gethostbyname_r_five_args="no" - - AC_TRY_COMPILE([#include ], - [char *name; - struct hostent *he, *res; - char buffer[2048]; - int buflen = 2048; - (void)gethostbyname_r(name, he, buffer, buflen, &res)], - [ac_cv_func_gethostbyname_r_five_args="yes" - AC_DEFINE([HAVE_GETHOSTBYNAME_R_FIVE], [1], [gethostbyname_r has five arguments])] - ) - - AC_MSG_RESULT([$ac_cv_func_gethostbyname_r_five_args]) - AC_DEFINE([HAVE_GETHOSTBYNAME_R], [1], [threadsafe gethostbyname]) -fi - -## -## Modules and optional features -## -AC_MSG_RESULT([${as_nl}<<>> Modules and optional features]) - -## -# pritap (TODO: add checks) -# -HAVE_PRITAP="no" -AC_ARG_WITH([pritap], - [AS_HELP_STRING([--with-pritap], [Install ftmod_pritap])], - [case "${withval}" in - no) enable_pritap="no" ;; - *) enable_pritap="yes" ;; - esac], - [enable_pritap="no"] -) -HAVE_PRITAP="${enable_pritap}" -AM_CONDITIONAL([HAVE_PRITAP],[test "${enable_pritap}" = "yes"]) - -## -# OpenR2 stack -# -HAVE_OPENR2="no" -AC_CHECK_LIB([openr2], [openr2_context_set_io_type], [HAVE_OPENR2="yes"]) -AC_MSG_RESULT([checking whether to build ftmod_r2... ${HAVE_OPENR2}]) -AM_CONDITIONAL([HAVE_OPENR2], [test "${HAVE_OPENR2}" = "yes"]) - -## -# WAT GSM stack -# -HAVE_WAT="no" -AC_CHECK_LIB([wat], [wat_version], [HAVE_WAT="yes"]) -AC_MSG_RESULT([checking whether to build ftmod_wat... ${HAVE_WAT}]) -AM_CONDITIONAL([HAVE_WAT], [test "${HAVE_WAT}" = "yes"]) - -## -# Digium libpri (TODO: add checks) -# -HAVE_LIBPRI="no" -AC_ARG_WITH([libpri], - [AS_HELP_STRING([--with-libpri@<:@=PREFIX@:>@], [Install ftmod_libpri])], - [case "${withval}" in - no|yes) with_libpri="${withval}" ;; - *) AS_IF([test -d "${withval}"], - [with_libpri="${withval}"], - [AC_MSG_ERROR([Invalid argument for --with-libpri, \"${withval}\" is not a directory])] - ) ;; - esac], - [with_libpri="no"] -) -if test "x${with_libpri}" != "xno" -then - save_LIBS="${LIBS}" - save_CPPFLAGS="${CPPFLAGS}" - save_LDFLAGS="${LDFLAGS}" - - LIBPRI_CPPFLAGS="" - LIBPRI_LDFLAGS="" - - AC_MSG_RESULT([${as_nl}<<>> Digium libpri]) - - AS_IF([test "x${with_libpri}" != "xyes"], - [LIBPRI_CPPFLAGS="-I${with_libpri}/include" - LIBPRI_LDFLAGS="-L${with_libpri}/lib"], - ) - - LDFLAGS="${save_LDFLAGS} ${LIBPRI_LDFLAGS}" - CPPFLAGS="${save_CPPFLAGS} ${LIBPRI_CPPFLAGS}" - LIBS="${LIBS} -lpri" - - AC_MSG_CHECKING([whether libpri is usable]) - AC_LINK_IFELSE( - [AC_LANG_PROGRAM( - [#include ], - [const char *version = pri_get_version(); - (void)version;] - )], - [AC_MSG_RESULT([yes]) - HAVE_LIBPRI="yes"], - [AC_MSG_RESULT([no]) - AC_MSG_ERROR([libpri not found or unusable (see config.log for details)])] - ) - - AC_MSG_CHECKING([whether libpri is too old]) - AC_PREPROC_IFELSE( - [AC_LANG_PROGRAM( - [#include ], - [#if !defined(PRI_IO_FUNCS) - #error "libpri is lacking PRI_IO_FUNCS" - #elif !defined(PRI_NEW_SET_API) - #error "libpri is lacking PRI_NEW_SET_API" - #endif] - )], - [AC_MSG_RESULT([no])], - [AC_MSG_RESULT([yes]) - AC_MSG_ERROR([Your version of libpri is too old (pre 1.2), please update!])] - ) - - AC_MSG_CHECKING([whether libpri has BRI support]) - AC_LINK_IFELSE( - [AC_LANG_PROGRAM( - [extern void pri_new_bri_cb(void);], - [pri_new_bri_cb();] - )], - [AC_DEFINE([HAVE_LIBPRI_BRI], [1], [libpri has BRI support]) - AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no]) - AC_MSG_NOTICE([You will need libpri-1.4.12_beta1 or newer for BRI support])] - ) - - AC_MSG_CHECKING([whether libpri has AOC event support]) - AC_LINK_IFELSE( - [AC_LANG_PROGRAM( - [extern void pri_aoc_events_enable(void);], - [pri_aoc_events_enable();] - )], - [AC_DEFINE([HAVE_LIBPRI_AOC], [1], [libpri has AOC event support]) - AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no]) - AC_MSG_NOTICE([You will need libpri-1.4.12_beta1 or newer for AOC event support])] - ) - - - AC_MSG_CHECKING([whether libpri has pri_maintenance_service()]) - AC_LINK_IFELSE( - [AC_LANG_PROGRAM( - [extern int pri_maintenance_service(void);], - [pri_maintenance_service();] - )], - [AC_DEFINE([HAVE_LIBPRI_MAINT_SERVICE], [1], [libpri has pri_maintenance_service()]) - AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no]) - AC_MSG_NOTICE([You will need libpri-1.4.11 or newer for the ftdm libpri maintenance set of commands])] - ) - - # libpri is available, set variables for Makefile(.am) - AC_SUBST([LIBPRI_LIBS], [-lpri]) - AC_SUBST([LIBPRI_LDFLAGS]) - AC_SUBST([LIBPRI_CPPFLAGS]) - - LIBS="${save_LIBS}" - LDFLAGS="${save_LDFLAGS}" - CPPFLAGS="${save_CPPFLAGS}" -fi -AM_CONDITIONAL([HAVE_LIBPRI],[test "x${HAVE_LIBPRI}" = "xyes"]) - -## -# Sangoma Wanpipe -# -HAVE_LIBSANGOMA="no" -AC_MSG_RESULT([${as_nl}<<>> Sangoma Wanpipe]) -AC_CHECK_LIB([sangoma], [sangoma_span_chan_toif], [HAVE_LIBSANGOMA="yes"]) -AC_MSG_RESULT([checking whether to build ftmod_wanpipe... ${HAVE_LIBSANGOMA}]) -AM_CONDITIONAL([HAVE_LIBSANGOMA], [test "${HAVE_LIBSANGOMA}" = "yes"]) - -## -# Sangoma ISDN stack -# -HAVE_SNG_ISDN="no" -AC_MSG_RESULT([${as_nl}<<>> Sangoma ISDN stack]) -AC_CHECK_LIB([sng_isdn], [sng_isdn_init], [HAVE_SNG_ISDN="yes"]) -AC_MSG_RESULT([checking whether to build ftmod_sangoma_isdn... ${HAVE_SNG_ISDN}]) -AM_CONDITIONAL([HAVE_SNG_ISDN], [test "${HAVE_SNG_ISDN}" = "yes"]) - -if test "${HAVE_SNG_ISDN}" = "yes"; then - if test "${build}" = "${host}" - then - case "${host}" in - x86_64-*) - # X86_64 machines need additional flags when compiling against libsng_isdn - CFLAGS="$CFLAGS -DBIT_64 -DALIGN_64BIT" - ;; - esac - fi -fi - -## -# Sangoma SS7 stack -# -HAVE_SNG_SS7="no" -AC_MSG_RESULT([${as_nl}<<>> Sangoma SS7 stack]) -AC_CHECK_LIB([sng_ss7], [sng_isup_init_gen], [HAVE_SNG_SS7="yes"]) -AC_MSG_RESULT([checking whether to build ftmod_sangoma_ss7... ${HAVE_SNG_SS7}]) -AM_CONDITIONAL([HAVE_SNG_SS7], [test "${HAVE_SNG_SS7}" = "yes"]) - -if test "${HAVE_SNG_SS7}" = "yes"; then - if test "${build}" = "${host}" - then - case "${host}" in - x86_64-*) - # X86_64 machines need additional flags when compiling against libsng_isdn - CFLAGS="$CFLAGS -DBIT_64 -DALIGN_64BIT" - ;; - esac - fi -fi - - -## -# zlib (required for Sangoma SS7 Transparent IAM) -# -HAVE_ZLIB="no" -AC_MSG_RESULT([${as_nl}<<>> zlib]) -AC_CHECK_LIB([z], [compress], [HAVE_ZLIB="yes"]) -AC_MSG_RESULT([checking whether zlib is installed... ${HAVE_ZLIB}]) -AM_CONDITIONAL([HAVE_ZLIB], [test "{HAVE_ZLIB]" = "yes"]) -if test "${HAVE_ZLIB}" = "yes"; then - CFLAGS="$CFLAGS -DHAVE_ZLIB" -fi - -## -# libisdn -# -HAVE_LIBISDN="no" -AC_ARG_WITH([libisdn], - [AS_HELP_STRING([--with-libisdn], [Install ftmod_isdn (libisdn stack)])], - [case "${withval}" in - no) with_libisdn="no" ;; - *) with_libisdn="yes" ;; - esac - ], - [with_libisdn="no"] -) -if test "${with_libisdn}" != "no" -then - AC_MSG_RESULT([${as_nl}<<>> ftmod_isdn (libisdn stack)]) - m4_ifdef([PKG_CHECK_MODULES], - [PKG_CHECK_MODULES([libisdn], - [libisdn >= 0.0.1], - [AC_MSG_CHECKING([libisdn version]) - LIBISDN_VERSION="`${PKG_CONFIG} --modversion libisdn`" - if test -z "${LIBISDN_VERSION}"; then - AC_MSG_ERROR([Failed to retrieve libisdn version]) - fi - AC_MSG_RESULT([${LIBISDN_VERSION}]) - - # check features - AC_MSG_CHECKING([for new experimental API]) - AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [#include - #if !LIBISDN_FEATURE(API2) - #error "libisdn API v2 not available" - #endif - ], - [;] - )], - [AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no])] - ) - - HAVE_LIBISDN="yes" - AC_DEFINE([HAVE_LIBISDN], [1], [libisdn support]) - AC_SUBST([LIBISDN_CFLAGS], [${libisdn_CFLAGS}]) - AC_SUBST([LIBISDN_CPPFLAGS],[${libisdn_CPPFLAGS}]) - AC_SUBST([LIBISDN_LDFLAGS], [${libisdn_LDFLAGS}]) - AC_SUBST([LIBISDN_LIBS], [${libisdn_LIBS}]) - AC_SUBST([LIBISDN_VERSION]) - ], - [AC_MSG_ERROR([Need libisdn-0.0.1 or higher])] - ) - AX_LIB_PCAP], - [AC_MSG_WARN([pkg-config missing (required for libisdn detection)])] - ) -fi -AM_CONDITIONAL([HAVE_LIBISDN], [test "${HAVE_LIBISDN}" = "yes"]) - - -## -# mISDN dependencies -# -HAVE_MISDN="no" -AC_ARG_WITH([misdn], - [AS_HELP_STRING([--with-misdn], [Install ftmod_misdn (mISDN I/O plugin)])], - [case "${withval}" in - no|yes) with_misdn="${withval}" ;; - *) AC_MSG_ERROR([Invalid value \"${with_misdn}\" for --with-misdn option]) ;; - esac], - [with_misdn="auto"] -) -AS_IF([test "${with_misdn}" != "no"], - [AC_MSG_RESULT([${as_nl}<<>> ftmod_misdn (Linux mISDN I/O plugin)]) - AC_CHECK_HEADER([mISDN/mISDNif.h], - [HAVE_MISDN="yes" - AC_CHECK_LIB([rt], [clock_gettime])], - [AS_IF([test "${with_misdn}" = "yes"], - [AC_MSG_ERROR([mISDN/mISDNif.h not found])], - [AC_MSG_NOTICE([mISDN/mISDNif.h not found])] - )], - [#include ] - )] -) -AM_CONDITIONAL([HAVE_MISDN], [test "${HAVE_MISDN}" = "yes"]) - - -AC_MSG_RESULT([${as_nl}<<>> Creating output files]) -AC_CONFIG_FILES([ - Makefile - freetdm.pc - mod_freetdm/Makefile -]) -AC_OUTPUT - -# -# summary screen -# -AC_MSG_RESULT([ -============================ FreeTDM configuration ============================ - -+ Modules - - Signalling: - ftmod_analog....................... yes - ftmod_analog_em.................... yes - ftmod_isdn......................... ${HAVE_LIBISDN} - ftmod_libpri....................... ${HAVE_LIBPRI} - ftmod_sangoma_isdn................. ${HAVE_SNG_ISDN} - ftmod_sangoma_ss7.................. ${HAVE_SNG_SS7} - ftmod_r2........................... ${HAVE_OPENR2} - ftmod_gsm.......................... ${HAVE_WAT} - ftmod_pritap....................... ${HAVE_PRITAP} - I/O: - ftmod_zt........................... yes - ftmod_wanpipe...................... ${HAVE_LIBSANGOMA} - ftmod_misdn........................ ${HAVE_MISDN} - -=============================================================================== -]) diff --git a/libs/freetdm/configure.gnu b/libs/freetdm/configure.gnu deleted file mode 100755 index d00cd18473..0000000000 --- a/libs/freetdm/configure.gnu +++ /dev/null @@ -1,3 +0,0 @@ -#! /bin/sh -srcpath=$(dirname $0 2>/dev/null ) || srcpath="." -$srcpath/configure "$@" --with-pic diff --git a/libs/freetdm/cyginstall.sh b/libs/freetdm/cyginstall.sh deleted file mode 100755 index e7953675b6..0000000000 --- a/libs/freetdm/cyginstall.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -# this script must be run from freetdm root dir and it is assuming -# FreeSWITCH is trunk is located at ../../ -fsdir=../.. -set -x -cp Debug/mod/*.dll $fsdir/Debug/mod/ -cp mod_freetdm/Debug/*.pdb $fsdir/Debug/mod/ -cp Debug/freetdm.dll $fsdir/Debug/ -cp Debug/ftmod_*.dll $fsdir/Debug/mod/ -cp Debug/*.pdb $fsdir/Debug/mod/ -#cp Debug/testsangomaboost.exe $fsdir/Debug/ -echo "FRIENDLY REMINDER: RECOMPILE ftmod_wanpipe WHENEVER YOU INSTALL NEW DRIVERS" -set +x - diff --git a/libs/freetdm/docs/Doxygen.conf b/libs/freetdm/docs/Doxygen.conf deleted file mode 100644 index 1f69952879..0000000000 --- a/libs/freetdm/docs/Doxygen.conf +++ /dev/null @@ -1,265 +0,0 @@ -# Doxyfile 1.4.6 - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -PROJECT_NAME = FreeTDM -PROJECT_NUMBER = -OUTPUT_DIRECTORY = docs/ -CREATE_SUBDIRS = NO -OUTPUT_LANGUAGE = English -USE_WINDOWS_ENCODING = YES -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = NO -STRIP_FROM_PATH = -STRIP_FROM_INC_PATH = -SHORT_NAMES = NO -JAVADOC_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -DETAILS_AT_TOP = NO -INHERIT_DOCS = YES -SEPARATE_MEMBER_PAGES = NO -TAB_SIZE = 8 -ALIASES = -OPTIMIZE_OUTPUT_FOR_C = YES -OPTIMIZE_OUTPUT_JAVA = NO -DISTRIBUTE_GROUP_DOC = NO -SUBGROUPING = YES -IGNORE_PREFIX = ftdm_ FTDM_ Q921 Q931 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- -EXTRACT_ALL = YES -EXTRACT_PRIVATE = YES -EXTRACT_STATIC = YES -EXTRACT_LOCAL_CLASSES = YES -EXTRACT_LOCAL_METHODS = YES -HIDE_UNDOC_MEMBERS = YES -HIDE_UNDOC_CLASSES = YES -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = NO -HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = YES -INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -SORT_BRIEF_DOCS = NO -SORT_BY_SCOPE_NAME = NO -GENERATE_TODOLIST = YES -GENERATE_TESTLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -ENABLED_SECTIONS = -MAX_INITIALIZER_LINES = 30 -SHOW_USED_FILES = YES -SHOW_DIRECTORIES = YES -FILE_VERSION_FILTER = -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = YES -WARN_IF_DOC_ERROR = YES -WARN_NO_PARAMDOC = NO -WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = src/include/freetdm.h - -FILE_PATTERNS = *.c \ - *.cc \ - *.cxx \ - *.cpp \ - *.c++ \ - *.d \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ - *.h \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ \ - *.idl \ - *.odl \ - *.cs \ - *.php \ - *.php3 \ - *.inc \ - *.m \ - *.mm \ - *.dox \ - *.py -RECURSIVE = NO -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXAMPLE_PATH = -EXAMPLE_PATTERNS = -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = -INPUT_FILTER = -FILTER_PATTERNS = -FILTER_SOURCE_FILES = NO -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- -SOURCE_BROWSER = NO -INLINE_SOURCES = YES -STRIP_CODE_COMMENTS = YES -REFERENCED_BY_RELATION = YES -REFERENCES_RELATION = YES -USE_HTAGS = YES -VERBATIM_HEADERS = NO -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = YES -COLS_IN_ALPHA_INDEX = 1 -IGNORE_PREFIX = ftdm_ -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- -GENERATE_HTML = YES -HTML_OUTPUT = html -HTML_FILE_EXTENSION = .html -HTML_HEADER = -HTML_FOOTER = -HTML_STYLESHEET = -HTML_ALIGN_MEMBERS = YES -GENERATE_HTMLHELP = NO -CHM_FILE = freetdm.chm -HHC_LOCATION = -GENERATE_CHI = YES -BINARY_TOC = NO -TOC_EXPAND = NO -DISABLE_INDEX = NO -ENUM_VALUES_PER_LINE = 4 -GENERATE_TREEVIEW = YES -TREEVIEW_WIDTH = 250 - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- -GENERATE_LATEX = NO -LATEX_OUTPUT = latex -LATEX_CMD_NAME = latex -MAKEINDEX_CMD_NAME = makeindex -COMPACT_LATEX = NO -PAPER_TYPE = a4wide -EXTRA_PACKAGES = -LATEX_HEADER = -PDF_HYPERLINKS = NO -USE_PDFLATEX = NO -LATEX_BATCHMODE = NO -LATEX_HIDE_INDICES = NO -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- -GENERATE_RTF = NO -RTF_OUTPUT = rtf -COMPACT_RTF = NO -RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- -GENERATE_MAN = NO -MAN_OUTPUT = man -MAN_EXTENSION = .3 -MAN_LINKS = NO -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- -GENERATE_XML = NO -XML_OUTPUT = xml -XML_SCHEMA = -XML_DTD = -XML_PROGRAMLISTING = YES -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- -GENERATE_AUTOGEN_DEF = NO -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- -GENERATE_PERLMOD = NO -PERLMOD_LATEX = NO -PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = YES -EXPAND_ONLY_PREDEF = NO -SEARCH_INCLUDES = NO -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = *.h -PREDEFINED = FT_DECLARE(x)=x \ - FT_MOD_DECLARE(x)=x \ - DoxyDefine(x)=x - -EXPAND_AS_DEFINED = NO -SKIP_FUNCTION_MACROS = NO -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- -TAGFILES = -GENERATE_TAGFILE = -ALLEXTERNALS = NO -EXTERNAL_GROUPS = YES -PERL_PATH = /usr/bin/perl -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- -CLASS_DIAGRAMS = YES -HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = YES -CLASS_GRAPH = YES -COLLABORATION_GRAPH = YES -GROUP_GRAPHS = YES -UML_LOOK = YES -TEMPLATE_RELATIONS = YES -INCLUDE_GRAPH = YES -INCLUDED_BY_GRAPH = YES -CALL_GRAPH = YES -GRAPHICAL_HIERARCHY = YES -DIRECTORY_GRAPH = YES -DOT_IMAGE_FORMAT = jpg -DOT_PATH = -DOTFILE_DIRS = -MAX_DOT_GRAPH_WIDTH = 1024 -MAX_DOT_GRAPH_HEIGHT = 1024 -MAX_DOT_GRAPH_DEPTH = 1000 -DOT_TRANSPARENT = NO -DOT_MULTI_TARGETS = NO -GENERATE_LEGEND = YES -DOT_CLEANUP = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- -SEARCHENGINE = NO diff --git a/libs/freetdm/docs/PRI-BRI-Debug.pdf b/libs/freetdm/docs/PRI-BRI-Debug.pdf deleted file mode 100755 index 53386b1b52eb580ef551c5e26954d5d6b202b119..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc-jL100001 literal 399483 zc-rKCLeROkQ#0;otPw#Gl}fc{wdXC)R9I~QAL z02_;pg|U+s0Q{o~0EqqP1N=)2{4=KWyT-u(tg)wmjwVly{UV35iIbg+qmhZzQxS1H zTjw7SAmC?PEaD&lkoA`k7y$gGyf_;G$o5N!9RTF`CBy*$a{UtG1b}|l5D;KdbhI;4 zF>%&nc^V%URTFn-7Ac#j?uCDOi2U-9`XMljoQbi8fv}ys7T`x^j;F3Txj{OBC#`Lr zpG0*6{L-U@qn(TWud4ivu&A)8IvUtI+5b?<$b&^hg+o91b6isa0bVFVtk5!toCr{D- zPH!+R5#1}~#r@93_LUrtm>o+I;$6|5A^j<5<8^FDN|8I+ikX8QW7x5e;h~oca0gS~ z7S2EPfN67j-O1)_K0_OxlIrA4(&nbekm!W!*?d%S?Y$iH=bN*wF6*o2nRquqd2@YM z5Ed>?z(6gMoG?}%xEN0xK;V-5eW=8b`_3}M^w8*ZSVWh~!hGAGFH@R$oo3E;`OC*m z%>|?6z|2Xzeo_Fffp8Ux01e~*%ZF$HhC}WW8&d10a%~E7iy=*6Hs}Ta%^kAVCs9OW z5t4zEE~N|zV|~DDcFkamUYyk;LQ=}|jCp2XZvGpyzC2?=-nS&r-Xc&!;`rZa%xbLF zPrV0xbUyR#M4T-^5hRP3XlX+)vOGhI5LLEUI*<5+m-vvg`?|HeC5{NXVh)N-K zvPKHuI=uV$(gBT=dypg;RWHq~iSWJdi6L4o!_HT3=lDMuEFH23HZ~Xx=qFpoClUou zw}wdFtT}ZOJ-BF@5#bO8CZ?Obe|cOqY^H0&c*~7ur%OaLT5X*Oo3S!+c7{S$Z!PET zZmcUK9~fxqaD$ra6(q*u9t(|rbc2}UIWcTSxsa|3=bAo8Q@^y%q5}fuc zRMzP;EOBr@uAw*up=7y&jAAIP8nAeeLGgiOC^in4OR;tUyk+r@PV?I)DakM&{4*(H znzqTS<84G((IkI$k1!ndl^0&Lk|(Z%EjZrog|WC;p)5c)yo6`3yNv5^j)Tx4-F)+} zC3)n8*{Os-57C87AhJ&B`SP|3BkrA78(TKg3$lAC)lDvaM>N*h^fM-fCJ}%EdiaA@ zaHznH@czVTg&Y+$T~MyDtkJXlFdXWHZ~7fiymF9Jxkq3h#0ZuW}2xlhp9z zZ=X^JRwU=a@-|b{2p5@HK zq=JVaAD&7<=4FD-?)-T?8SGK{DSi2(N?5P8kHPCIwk|U_En{2p`KH4H-0xA&T}(zqn_Ta? z{HjhSXiZlAfVQ9qRlNZDi1ezu-lX>Aebno{o}-C6K;dPBwyFRW2xMTX4aNNaghe97 zT5=M<^3|2U`>=i>J`}guY2*Y1@=ckR_aJR|1*5ZOnCh5BIyQSLB&&OfmwT=vgHYfD zQ8p_);b|0s`}|OVW6y&pgk2M5{CT=N8C)EUQEUAjXF~swLKmF20`rT=fVdbX{9R2}HPE(){92NIt>_V;by8BlZ|UTQJ&iO2+u z;J&Y+19J^Y6r73b=4ji9xXvsKO4XaKE<*$EyO~3*{fl#BE+KnjvU&mlnyWj`Q35LI zG(>}PuxNC5ECo64BG1e{yoOG{qa+8w_9a;5d?SH#8^4Y!gU5juU(WY?^m)&6xsgPP}c0NPm1fQu64)<@8Tm`r*#B}Pb;8b_~JDd z#q9LjXaCPJG1<+hi!_Qcs7g@l&m88jRq}djj(UT(TF*4A(Bc;hy+YwpJ+keXafNhC z=_PS*PQ@?;uV=jA^6vZ%iwyzSq>@$;f_~*jYSA|6^(xQCoo=+%xR5&_MWk^ z8%cdwD(A%=tmWnG~Q+hjJmfV1*Wxr!Rzq) zo?Od+uDs`rVdG^=vy2-vO`Fx>2U_~DJ^QYakk^)7gN3q~4ru&#XK(xok8}(os6|SV zs_PSS9wnnzDT7&g9Bl(%a;fpvB?z5{4bs%bbn5B*?z^n2BJf(lT_PCf)ehC(q@py+ zoFkF9miHgHGa=Ej-q@FT_RzcFJGj}ZwV&UipkE3W;<(h3UWX1r8`^)&0VXrDW1c?` zt(26D5}|^3`5^;_@dcK8=2oQJFTt4@F#(r2Z(Zd7v5rt z=c$l1!mEcnBb(&1y-@NM0Y;R4j^(Cz2p{l|a5#>;0lO<9h$p<;4C0xB-#d$RC_nV{ zJC;Vy!zz;!xps-2zNpAP!kO7NVHKFH3D($2sq{%*G<8nJbwO`0nz|@h>adOo7)>^# zjYsLrKscrXaxHgWmjfK}P{sDQ} zR>?Q{bz0;&%ikTAm|k*e$3<@Vo&_70Cr0^J;tq$oWMbzt&R={nLePjVW9z)!KVOw` zMSl}ZdmI<#rz9qqBoqD$SB^l>fKSJig}aQ;Xr7J8q+?z!eCSb#SZQ@_ctsIo_Knl7 zvP*g=hN9-4o_VhdK7sVQV74y1#(9ninrb442NZnUsvog zxo((9+clyiw4`N%LYzWBLut9<)cb;rEvkBFslTYy?y6R|Oj}dTLu%^_O;e{tptd?5 zk;ZB?^VYTMHSTtpd(~14Q}fj9W_nc( zjYe}>K}uTf^NYdieOT{ZX7(e4RsN@Ek8%!%(+xqICkfqq$usoInFF^r@mGaG-IefO zmuH^r(#z7tyLSe8JTJO{l_y>k&epY!RcBVlN@ z+Q?kO)U-O#-h^7|>7k=L#7! zP36qYqjy&KhKDfTijn9PJ-|9|Ra5Nyu5}9+7wqV1>g{i`MYs~yh%M`rSad$6du7&`xm{77MC5jJo# z`I#&vEFvl<#vo!~W9VpMz#?Y*WUE`)nz2Y3Kam3qXAdUHC#&Dd=&5Z3Tjw7&oB+QN z6IDAkTZW?ErtHPEWOdXyIsK?`-D?_$e=oI)DxM zN5Q#%BbOlD31Fo;F!iPl;e3E7%in*dl@gnl644B%#G{Tmw2045L!^u&Jc zB~2{M%$)(8oLnqIu4d{M#!noJ1IW%IXW;%zgbmCF`q`iQFD2QY21(;@wLnh|syvO= z%cm+o%LxBuicCN@PWGQYJkd1{t{;s*F~%SHPrS|q^wh*32ks}A{TDBtql?MU)So(w zgZ}sTPu;>+$kxf?@9{rC2n7BDtc9bKvxvEYH;P z;r`F&$6r~${_-RNbNqIauyglZutca!8vi~o6&u!H}oG>G*-GCBXSX8jA369oK& z&B@03CmDeMFgih?KU$q2(7!Z0f05+BXLf?X|IF?LvHfaz{>fqnf&W{UCy4F;)&dP; z|IZvT|M0c^!^83quggDtGF(rF)}Q<@V(!ioD$WMZCQmI%sDPewIRAg}%z!xlTdo-p z$6xc!aB{Q$-ZwL#`O0oZ63Z7o=21{zm#W+LdV~f(*k7B}*v<5Lh?`!9Shr+?oM;k1 z6@S*xkTD&;J*Viw9yBrb z7~P_3>+rb=kXT^7NuHb*U%>Uf-`R;MUutemtKC=e%{Fski#EHIgQQez$XHogTOGIE zD_*`IX>#J%>WQA>dlTz^1u>c4))Mk6ov&=K*z)E08^`+dLzt1vh@^8BL>z?)Yh=9z zF>X9mg97!wMm-N(1gkEdq?yj+W)#~!%ocV!D69I8yaS*%}eY)`$kW`)&aIw~u(OD`7Y7m%xDI>2aVcQBl8ZQQ3TO0wJ+BW`IhGkCF*;;z>Wn_ZYH zt>&OqqBzG?Q!II`eCg|B8k~I^C=*VUtMY|VC(Rp{DK4sgPTF{pd+2>l-Kw=}1P42V zv0Vt)tMqtpBcK>RUS2NzS*R3g%K+A325_r^XGkrFToC6&_c2?zT7Ry#Qc+vJlBxN? z0FvAdyu&w>mpk2k*=+6O9HFNv2@NJvtAu6_pHXOGOL108j7U?R0jgX{l(&d)^U}Y8 zUi6&v+6ADI4;2zub~u-N?^GTd){|p*c3H6J(I<5?v9^!I2)x}Xz>N(o>JTx&IK(C5 ziIX-gl65cW`D7(Gq#lX`_fgf6e}cDW-MeXXmhV_ z9+(9gr(>HYSQ_WFPlZ#}dGCYcY~*w|t4MlyVW);_gX$9ImN~NsQh+Jafm@+vE`bQe&9Kw)(2`uD%WmB!0Zx%v~ zIG;_L8=cx0_8lkN8J`6b7HBNR8Fx>SmSv_*;%`A)8pw8g77u$ypG>oFgA6e8}0EZ+)o^JyC(&@LeP6-9^jO9%NpwO(_#4615$t z;o@u`QPo;J^xj-BlB`+`V-wIxI{CPZ=QRgw^d9S8Bn^elJU>HmxEjl*lfPPEDil`z zZl-nTUKY=ZAyT0){ALwpkf>b4y0`UGPMrPo%&4K34juT#0I#N6mTNVI2@UGjCU{m# zA1fuOe{eR;il#q{r}We8$Wxmxhsi3)U!W$IOEE4TNFzL#45bTgK%X6jEcF^8AF0YL zabPtmlQ;zFCd(x(RdT~$JHxd{`iF3kGf;w5qKIvIzrD-I!)xSDU>QIhbmqC)9# z_Q8rufdkD|%5oYO7Kdn1Mblkof#i{ zNjc$>6|5CiTTDG;7`KFi2?EkcK;}ZF3XC>%%nhX{bv3r{nqTBdy`XWR@CfH5n*1b+ z)R(~1AC_v6>{)^(cm47$0k`Rb<>c^$gZLM0kKowrF}Gz{+*t&7ycW7Ne?g?5HTAxLJv+p`F2(b6nO|+-sQ&tYwC#zrskMXiD*bxfr|(UKVetL3V_m zg5UQ4QrCN%gp^YTZgX(YVc5>&u{MP#A}tk4zr4zS_s+U%>w&wn8L|lp>m-bepY$S9 zku?B6KqZPiZ)QD0I%Ie+Z>sPZn{yFrd?|RWohIK7T^~6pBO{c!2*y1)tESyo`b|Oo z<82??QIH|UrX3D%U=)z+1HP*?m|N{L>>91x4b8WhB5&R!abjzg#EC7n^yUFtV|bCk zO_)@PU_jtEeUv?I2ZL|I!%oacD+8t6L$zW^dNb;_!>%Hu9ZukJUX4rF+(`?d@1lF| zW}po7R>YSf)7c3j3TS0%#)uh+3Cdo)t9Vh`@MuO@UiFf1?LM)6v~&j-;O%bh27h~U zUG5kd;>`SJ1e}BI<+6)cAoNCd@!f=5S#1Ln8C7-}c4J z_xAhFyS0$XKy6GM*?#+QP`&OkCM05gbz@MQ=eQ`}%nf2%IS z9WxA{_^)0~>eS7|ts5CL?k7G3-1b(# z$EbRY2ZzBvDg@YwKDJOS*YlGHo#FX!dv;$p);!g(j|Q?4?Y>SnTyM)n-;}EFwvu@r zoqhj$;yCdIJ$176dUG-%Ir)VD_R9_UK!?=3s&kxgXlQ}^-8~-K`()gAk6&*2E*3qb zKSg9dD!871zI8*!xVqb=%|kKi{!|s(yuPeX+CG-#Hx0F9yK_ElbX}vkO;R?IIw>@d zl)TpRQm#)>%4^Ph=!-oKN%L|I(=g6l$S4|jAiB(I%)5=(JYOQ%`9ubY&v3`2cNZ(> z9TUm`k!cg*mhohYxq6Ct3+h#^Y4B2ZU&gs#!t>P*J?vW9IedCf3SDc2ZY$<~giJr$ zT8JRlz0<%XRsx;4Y{YUBb)Xv2%`UeOn7wLvcO{@L-8>+!geBUmVGZ~=CfFxzfWhz{ z?K3ud^+?`ib@k>6qIRxuM4y-IA?WZJTyTv8?=sk1lq)`x+^pN^CKoXcP`hGF`?&f% zNeE{N#Qz1kVTq(Hy(8SFhX%P}M&~%biXjx5?sz~~uLr_hR1@w1=YvM>#FRvn)y7Md zwR$S9;ZvqI;if<@k6eWTTMKU`BJ0;H(}Q1mU1jYYqAk~WzBuHd%9-sC;_A=C4F;C0 zr{@{VxGy5L>Ga6D!bhQPnKkr$B7OcMa9|rggfuY<8q=-u<2ymz*HVsN)~WX;r|1K& z<1+hk6&}nrN_6NgbwjqudRT@#W+-fe&*6?Bi6AiuMVL}y+I06~Uic^MJ_tIsw)UCT zHCeVAsLr_9|N$2bZ%2eu9w1eTzh*2gYw)YWq_j?u3^$t@^>iJjXg zb-r0_o6Vs}l!qdJPNyuknq;0vp@tI7sS}M zDMWqT&0UIPX~{Hn6=uoAjd!xWW&{E9hE@blxRC8UKA@`a5?aTomLTt3NRnCI=Ir83 znJ}Eb(??I{LKyPna;HpoZS<-tDh=MVhJ|hcQ!;}{p{A%RR7rl7NXG#PX3FsGwbJ*1 zD*yCF5jrGI1BgEN*G;J^i}cxaFfX~#^yf!}>&pP3x6!d=lx%lW>Mz+}+tTYw76ypQ z^Tw&>w6^d*yNTYMV%3)n%}}yi1{h016e;r9mI%lp&HE$1F6yV?Am1=3Kc%CLhmc89 zY$g*a#XC=Zzz_DsbiB8y66lqYWN~0iKEVo)kw`vHzElCzpzN&TE_mdK`qgW2hjf9! z33RYGaf-T!9#Hjo$>*v43kv7>)Lm?GU2z66D+j9jGzO}X-%>XC=Ym_Wc#X#gzH)0b z`L{QYhi)8jAvIVX=`-iB1GAcUpv-e)wsTrD+v8a<4V(|G6}3vv87UAAt$LY^g*`pr z8B7q5a5B~w?GaTgfaC0(pF`N5fB1IU7jLB*M{()hIXPeLln_w&Y<)sArpr!?skQ!D zB^1eurKie#9%R{NIz36B)F5i!=dJKMSU_vdU>A^Q>sv=bjcOLqp7c#ExM{X`7q|FvCv6O(lMiGZ<=Od{PW7Qt@sf-t1xJD0gH8Gfg!q4kZY= zwX%Ny?hL9Bk=vY6nbeZX-}N6p3~JKOEq_nTX!ACRIq^`C^Wk*nGCIKg3QI(+dTYv_ zGrq1FS^aaT96@COJk(;UjQxm;tS3`XIVw^}B4*1V9N(}++Xn;ss!SB$NFoNwiLLdQ zJ~A$fz|C82E%0lVLh`yw?!A)-ij2w72p@{kfqdpYO9TR+H~HV7_G4)1MNtkOMGpz{ zL&=d29h8S!Q5p_Wvto7|-;QF$CM=-w@cr`LNSF^dRiV`E8r}tScU=*}Tg2>! zAX3G*ve4v5wOz$=yi#}{CpV{yzm`u?d1DV$)4n%MUK7e{nOORYpgK`yoK=C~Sa|tvd=paH^loEs3@tip7^hv>h0$0Rk-k4=N}M~Kx40J< z=x-fiIEVZ3%%T-W8a+3^LxR2oHoVQus;iRXHG!%Jw#rFg~ zazqhwLigD4)K%|!JJt~qF=Mf;D5o(?5nNy(udAzO&S^u9yv~NhM9XSIEC=Hz73oe2 zbDM*Ua2UEnguXPi8fp$$RBy|P zI9HjYVZNkbR@6{op{fhv4CRfv#gys@J-SJ>ItD!CLd zos>M6k)<@UOT~MkALcDaXKAdgn&UJDoLK$(k}Hvmv3x8hLC9owRUes^$wr6fMD@Au`CkQR9IaB=hdIQiz-ge{{3*{(kDtda1@ug7g_ z>Vr~Hp>Ks!)nT6Lu)Gqzstm=p%#9AjtkYt7~C5=54ZuwV&}-u^GV--A}^4 zM2cOuBAg?PhtDS3W7@~c0bX0&xihcoVIEHY*>|$#@LVgwJKfrLJQXX}@PH33L^aB9 z@2Kh&_*}`9*&w&yo+<_@eL}W7Uh!k5eL-?);UsCbRnR^{)QYXJ9I#{VQ6lA~xC2L* zJt`qeRl(FfV5s(PBB3QMh8|J=ZF&?2w2h?Xp^-&26W#r-fk>bl0{2z>cMUJ!w@%d> zEA$*bfodwx0mKIFokC$%1Omj!uqA}f&&<|KgOKvFW???_7dP?9*V3sCP%h7aM7Q{) zye3>EGSi$64!bYd;KOqeG>D)PMmbp7Ei~)6AQJtv6rjfpQ*9h}IlOZ9us&c$)OqKL zSHg6c-6dUe-q@EaoQmW;+w@p7kzZ&hxlk76r?c&h=sW-r zR;c3Cw@V)IDdp9&8&<;BW^3xR?}bK{87qXI?wo#!T9iq4q@8zBYP4K2U_sp&U)c~{ zRncJuE5U?)cB`(KiO!Q(K4f1eQ({E7kt=fU!FmP~w#Xh>dZtd8o-wbXc@Lj?-ToDX zXWdmkoW*6zEZm&Q$%bbUxntW_Yi`1H1|D?G_`;f$A zwr+)#QpAv9goMJaV(S}X*cKEGAM^}5&BQ=$?mSUu2@A2Y=?z&}Dj!O%F{_0&)MAzV z+j|!3x5HolDZK{&hhDose=GIxkq#kSTRZ0;UwQrQUgBS1A^$Ze9Qdy};ea6EA3l&8 zP?vLB;lSv$5`TnjjU_>*LGaz3Z?Sxy$tGvGv+c~s2rE@#F)A{B`EA2(BOpOkD>6Z4 z$OsVzuib7#fHB7{;$ZtsohgB3Mw0R6Oc)mFJssxl^f@%9S8XIzZA-R1U+F<1N@u9R zC&4gJALFwzyP1)<^{iE{glA*0FkHPLv6Qrr^a1$7%ueXeNA-4oC_(Q%F{27>eQ73{$o!-JwkTwdUG|OfC7L zLFqgSuP9ejLe;|;wp(BK6}|dc+5xDpIwMgDGvi!-PG3jJ5b1w9eVnISg+zS5JAvSN z{9O3}^1Dh{u=Mx6xV*5zocc>921*93Y1Cb4J6AI{U>GN@34WP|7XXTTp<84O-A zN)ZT760y688kzS>Qle;pr|*z*eFE?h&Pky~0*glUP3|i#84fU-PaE+{zGtOJ@|=~tDh=c$&YhW3rk2# ziDefy*ldOahM5Ui#y5Ueob0k z^>8PdO@_FAhx9VSj#*gql~X)ys$6@a!uASc(?^|m@x~*s>Tas!hdIVdQDW;MUYNWS zn^j7k4kHqUhLU#>gV$J8r~1lXrohqMfAif!V&#!qMhGihfxd*}(f)CqAo`W#X&duc z>^p^+>FLjtSHvOImkdg_w`eZ#{H9E0S7k1H1PeZXmBVi8qr6Loweq z$7o5Gb<@9GEaLFPoC;DS-KxMdF77gddNNXi8`bg9t0+7pju$hZpLr~h1(%~Sv|?pb zW65Dks=WCoys*Y$|0Nnc9TQzEBZNWiJj5LxSLH55IHr+lA)`)P*yhEydt*9D>6ICx zsmTm{U(t-O9e2U}Y7V0n*X8ZA>_jXN$9BCHo%PJGsRc~LD?k<<+`{q_#tCYV`;0gV zR8Gr^MJf8g3ykBpV50g$*O(xYmGVHONL-CfGU3~55#mxhvt{aqgO5qK&pEdST^qyQ zcwM8{%92ZNbe*#KEOx$0;9+IDm~s=+}i=$jI5k&h}|#R#TSx z@uM|&cDCnXVX=5x%pGkFteKq*Y|ZR!4494VY*r- z+De`@cYaEFc!ZFHuz)avaD=dfaC-WgLO4TIK>#4spTdq1#!n#-1S|$i{?{)t><+%USwgm=* zf4^(_C~H{-vf}toRu3CpE6ReZ0lo9eCkA-CSI}(SuDy}u%kYo)hVlzlOj?2;KY2ID zU|Wycl(vV#RlCOE$~GJ~)Ul$$GrZ=g`O5YYsFs-#HT-CzM})=Yz#ff#QD_Svx5wu0 z)aOtK*5NP7ea(y2p#j@8j=lbu(yH_wm|DVw}jLBz>z+_&Bf|Qrg#5Is|hUc66n=hO_#nET6B7k%%wdaXfI4 zL=p2al!9rm-buhed~%EOyI^Y)a`iNR#GE9UZW0JEN<|p6XT&xjh%(7LaqDOaQxH** zi6zPB7&xSR84({Lf7hlm7~6FFm`6Zkl9CXLtm0r4jvHr8M}@Der7g->-N-m+fxF$K z*$nG@es|7-zG1<|R7^0Qr}@r~^u^@jKb=8rtbYj?Zf*_`_-_#)00aVqK!3R7bL4~Q zuDa8Da+?X3p#hIDj##HMg1MIz;zo??P*FytK!~qvjG^lgsEnZuFat#gV6omnz=hx%~zOD1_ zTI>Ba^Tur^B$hvfAR`t5f*S6-qOu|M4d|0WAjBM#8m<$4_Ls-Gc8H;@KFGGzcV&kQ ze)mIr{@icx>pD_h&WRY_cg~=n=#sDkImfNF70EY}R*}Y+sv)ax#_q(;d;@O}m?0c- zvZvQQOeCT&tNM2!OsFBO?e-cwU6a_?Lv&pILqn3UD_YL3!;q_BOWd&pXBzU1e9%Q9 zu1K&Q-kA=heNHBGH|kM`SfhlX@pDrTd7P>2HPH4$yTWtH?>&htgZ$}T&xwQ}*Uo#2nZwzie;<=nG{pJQH13Hs1IZWS}1+oTn0 ze#O&|fIyOXu-`x#_0wJR`LqXHY$<2PWL8rO1qbDSo`4?d1usr;V_Hn@Z6lWyc8~g;1T@TL!^H#~QE4l*c0A*d zJYLrK!q%Q##fuTiSwvb0GG2-j%swgy_(9SGP#((#=OI0gI5g-!zfL?N%S}IAoXnMN zLV_8Dew&=B0>>Z%;w2+oBGu^SLoKbFV~se(xrsTcUh={3#Rz7-dxRcm#J@4Cn#>BA z_S^k#fFOe3dr}R@f$RFH@Rc0pXZ)#L(0>-ZoAF0A^gbzW+~|EKJ&p_rBs1cLKBAo> zgM1?3RDsy^-SBg)$h*QMY=YR%J<=^mRj)tme-+)_t38ms-5yRGi5=62jq2dxij&RA z{)P7&ipM=_g!U_j8Iew z%poQOyLo_Srl=9d+tA%Eupcr?_shlL=}J}v-l7W_-}O(ni_q8IowRF@YaACZP&Ovc zH*g=+O-nv3@94D|pW@n7GEE?-5$?V(&EzjPHEpb}%hRT1$o!ZoFrlKXt*Wv4-ff55 z$*Jz9Vm$JqVHSsZ$v{C`Hne%*6_aT^kYg}s!6HAO?NCxJNSQpj7Ui|IAtqDegj%_% zl}UTaNAHaH%$B=vCtSkyYq+^O*N&}65TmemIuL-3hSoag7zor%c>#~RF&-4@Ww+z6 ze1ZA7OFakcwQ^U@o5aAXx}}dbVY2kTlfBG$S!)K@5p6uPyw;Et zjF^XMbZ83RiUHEJ4h;Ys^Jmy16G=&9HfIRk{llD1+|ek9!EE!=*$A~FIX8kZlq4K4 zp(xx3P)IrRM5HuPGbqCDWvPG^!1n`8dfyRvj@?I0ycKu!2GnlU^Ca$%@qBomos{$m zn3GwX&$lZjaOg0QR@#v&OT2VU)QK&Dkb)G6wVW*}g-YHhph#1uK#VN1T*iRLRN5DS zUbDp=P|K^yCxLw*;@g*%62aexP03sA3Mr2)1%#xlK~z$rqlZqfsm6JOhUvN(QYQiD zhW1(i6>s&a(?b+PnphJwJPKsG=G+?9;KF=k9unD`#dVwFk5^JbaFe=oHe~%ABr8z~ z=TkX)dDm`kjWcZI#~J9is)-XT#FQLU{vFb@=Y}|F5p5p}-jY<*RW!`(Zf+xe{qxcj&$1123FQ-YyGT zB-$XnnKX7_)kSl4o|f*M&_so%3EAotb!wXm2=#nUw{cV=R=)oz1eUA4v9&C{yzQGH z8!;@$Wx5jy+SKSwSYV)5v7%TbBuV#mRe^yEF1E^ zb+lP4NYk(%&pB^k+RR@TuWAyAfn6h?UdQ3;9yi{0Ft_h$I4l|9AdIOtui7nJfrl^W z_PW%+)gL+$eFVL)`UDrkme!M1=GyLjhj^I1W`JGp))d-yWebuE$Iy8%?^NBE`!cfB zEB&Lox=>6ry z>n4(4iu&;vEbH7ZVeykC8vOO;o&^fv; z7s#}{;-f5OUMr`Du0U*eJ%tsjRU~5FgCjv`e_Ys_6o0RS-ARUhznjUlHe-)Vj?7ep zw`Ei~Gd)Xup&Z8Kp0{6bs-(hvoPA+vjsi!9o+UCK;WZZ!Mrg*p=E$AAz@ampcE(y- zZCnRpV~?2gHa`{gqOnU~uDB7uu2AGmihkQfw9novIDjG1w1AFi>}6zij!EM0)_|b&e;s`s;(}kUsh7@A|wULuAPI;6+JfIfFE2*)kt@LnwxQ z+LyW^C6b*`n8+33cC|*&CI=nBbWQo5MT;9tLf1kw35AW`FU=zGfvo_vRO&K&ST%cC zVkM@D+-3;*!+zuAO)AVecdqYR{m-%l8a$|Vx^0K9a|vzJN+gjh=oIqN9h*=HTf7f= zlnTOQOIK)BKCYXSC$Mo?Z}n+H$tzph?`0CZx-_j!t$_Be`;8L{r@l&R3C_G}Zey&J z>6O%~!G?M+NrFpP=6Ik}m|*O}%pAHgnv~SNTR7je3E|x&ulgx!x~K)j1=$&>Q@^i! z;zeYeh~^W^tnvZ{brp^;(0OKBTKec&zOtE%eh=cfdVVkiqTFC31r@H&ryc*7QcMey zEDdsf*zhf%NmKyO)B9FhQ)y@xPe_#glX~pv`#BghFgIq!r4D;~LQBRJ5WX=`SjMRo zc3M*J(l4IM3vtpq)o`{kNdX0CAsjh-XS6C1qXEn1=Ysb(@@=U zQ)Qqb77OCQmaL4f6piKUBYD0%mFPy& zeu-$b)CGIkJNl`7EFZBv7MTm`uqerk=U6_vc_Gw1R8xUiKC*eYRBh^c?NpxWqHfa8 zA)@fqp5>zORBd8;>9I(K^~d+hGau!28N^x)PH7elVG?*-Q`wABWKk@$&_yDa}NA@jjIEzh}V=L zjA*uW>GAt<=<&cD16w0kU^69|u`4UD5H!cG@8auF8gd_)(+v#22wEf3J|H|G+yiD$ zApDLzrcSR>bXLP9W#z+5ng+@D9#2wxBEO z75ORdc%F#ky1@7aaorOCBv{?(1xfR>OHi4f^Wx4`$>>qt52Wzz&C1Fzv5DQKgn3#%>l_hJygIXXSS*su|M>Zg=9>XmFHk;XZS$cWcXmd81|A{NEc`O zjgT$+S->Wrddwc|WvWnC&;Ey?p0mb98jO$&g!pKhbOL0fft(ToRO~l=0ZPDFWqS&Y zxqWZ&7Y?Yv{K3r^F$6UNdh9ggzs}eAt^<%ynYNvjgpnuSh+k2qm)Wgeq%ORYD!T=0U|EQ1(`ht zQTe<9W>{GKy+a)74HGYl3Ot{o#Uqdh-+j^HesQ0zFm=BkMc=)zDdVttF7rf&0pWyapoU3I6rj6H@b;iIGolN zo6;0|KKP`FBAsr(;}2r-ON!v6-{w{ptvh|UDYc%fL=eq_ z7ZRnE8PPn}? zay;FyGi-5t)d%hPu0mVn3W~fs-bi^*YxopDj&r0|1c~s~PVSvIx(WQN!{ELyg@j)E z{l`A6J&#NFB){X5NW3VXxYDZ=rTkZ0)j6Ehw&C&OPA^6rJPr@16fXC_Mt`V?Co}xi zSHU>B4;;@i!WFQ%tG#d@&E__ZI`6nZ6e?E>S&t`WY$x`@uR5B-*+A6i?ZPtxtxiB2(#F*lAWeV|LFR^So3P#us3Ou&Y_{$~2~ z5bfUns^~F!kZ~M>)&t@)u~Qo6Y&iIhw)r$0C5{BR9^&&BLE4{M&oysbJDg-SJ)Ond zI3l9o?>3HTJ0lg#$%Z#Qw-Bm|2d@)MS=v=!`?8eJ9k7>4Hj3v)ey9Pp!m%K{4Y+)M zX^d&}Ov%csQG>21F#6cU52kC5em2K+Zux*!XRf!Yw914m2wv^l$`3k?QdEvjIB8xS zE01xsg*N{^u}RE;IQOKE%a>RuugUwZRiZr{lf57(_{p%nsO;(c!9Rv*F{ee3No{*0-#I7*j<)TMBJ?@t3(-4>Q{$|V#VQ=hHywGaOC<;=M)d+XqE#`iq{^QUU zjAn`^@+OKV00$)p`8@f1p$f5#w;DkyA^W1^LgV79JQ70%n#g8-jB+UpKqjZWAEF&|)neIvL%j%ouC(5_kk1^xP4|~(6 zB`)awCSVxs2$~PV3s4&~-QOEr>P!8h#WxbGx?9LpglF4Ec6db)W?;&PtQ|}*6GcDD z&sy(#5jOc5e0w*iNEkr&b?^bThK@bQKJH1>1GudQr~TUAnH;e1 zDC-jbQ^h3>npF^1%ipt7gtj`c`SnqS?YAsH8chFJnJ*mXp8hcOpZ>=MG3ifIM(YFK zVqZpkcpr|A^!4FqLE5cf@PoI&y!V6GhqPZ`XWkHPpf`e)Eqydm=9HX))rOm-h99we z7>}!wXPL0*$zSNPq5E(NQ1E>$Yhp|QZnv1DpH|<>Q^q=^)gELYDA76FSbZK(q0EJw&2%qpOH$iMg=Wle_44m9Qm*WxzBR2(-(8(uaZhAs56H9vV5qza-# zj~mE?CLD4WGDrHE%epZ)=z>2i0hx`X8TU_&kbVz0sO;WDFFZUVmi|688}Q+f_yN5` zI)LPW@~qW#U-)sC99!RCH_`Sdv&i-u%=9YGbv&SZcL&9fH+K#gWzM-5}TX+I?04^ecwfZ(Bo?UT|Ndhqc^#(zRKm zYldJirEhOHjTGqBe(qf@*%p-*>dMsX#O4Wy5l@UJ>y1E%4A6+K&NY;1p-(5 z2`CcXJ4Z9L111`nquRO|C@AJKgE^u)S_YL!)O?S+Pl zqHj+k2uA9HGGOQVeET2CL7}uw^=dGqjmX@+!d4eB=`Xt7y z;(`;DuZonJs-hI~g(4T`BNWv2fdlnbZN{eQgbQ$F?hj9AZ*0>zHPyIYnn81-+@&>F zsHhrr9x6M%8MQDK8{~#vlv0TcVWW3>J@@YJ!i62RFvcT|?{=0sbI#sf33u@ee^!yA z^PyaGz&3+K!d8Sg3tvPc=N(Y6stwY9Cr=DnJc)ahe&>CYdbCT}ZczJ0psOpZ6j-!U z(DIPeoA=VvQ#$t2QU*k?We;1toEH|dH^k~UD4+1qpsNbGj_HxsLa-i7rc%Xp0wxlM z6_luDwkgZ{s8$`@sZQq>$51-!`|YxLSmNoiaL@{A6sZ}FPu#Q*d%d|ick{Iygfg$D zyty}YlIU-sN7Q@tKB;vTTlNR;e(g@(spu*Xyn@?Gr^p|75Dft1jTxT>BC1gx-D#+F zYVNT!_Hxq7<});)HX8TR4p@mfqtuPRVW)QOj@Hkm;-D}~XD+AGanZY|NuH3fxsNMY z5I4)(x@b;pk)?0gjO!2mjq;FEDep%&b|ot?R9qZILo>ak{ZufX zn!>S##uUY!lwqw*xAGowx(`gS+I}-%WJ@GiIF691u_59`*VR(bFqqe}D3`Q$P*RHK zl}e#TOmJpPsch;%_7#@^<6r!TtqemPH9%xW<#t(X&t( zjL+ku%$hkDT^1s@9i1n~D=$h;C%S1m+2$&`9hZZ%PPe+rl$KdOmmR^El}JYX&^-ds zS$n}W`E)zrG-!1+RcLhD=>-E4ExV^;iX$UeFT*mXrMEH0jR^@>=H;&<-Q{gOIBhWWYV ztz`;*X>f~|L7mHV~db_RLb>UUDO1W73^a~0Ff>(UaCs|;e}iWbia zVV~2`V+evGx2y`oFR_Iq53359Wca3G)?iV$Ik`rzExI16O78~nw7cM3u z1vMk5=czdI>->7w(%06#-#?*LpE4LGo1W8^S0QmAI1PGg_DT8i}{KGrgio5QOI zL7{CPQjy;%ButD(KA#@9@wSl#cg5ydFk%s;M&3IF#+G^W7tP^cokU!#77vWFm%@&w ziin~pngz?*_7nwvg=5nVku+k%7DH81k0u)_R+_;~-`EP%qYJ)+8_s(Nt!TkupA;le z%9I|H7)7U#pjb1Hfa{p5snhvHsP&vBsTNXeb}e+?%H7V|RH+??yCf-be6-eFkLRc` zOrvrWN3c#+PSsUF6TXa7P%_SVcia}@78-k*?I03xx;Pmfm95ZI*DeWj&qdF7V-;Es zzuNqvxS}r+3e8#G{mX`Jfi%_BYs+nD+*i@KQEjM_9?_g(M6%*ki_cho_hcQLH-g&; zj19hh(#AGZCrtjfU)BE*vlDm+8_bNX6?M%Kb;T;7bb$R=W`uP+~5NWjg_Fn}RHByxp8PPkD}L}-doNkQRYfh86Q z#9=UmRIyBap4GwF0hyg;=*(dX+fS_a+89^cyi&*P`OC7aF^YQgaH&|-BH^@X&S`8Z zzMY&rJSHN7UD-t&CS5T(ZEdKGL93zaT=R%S3blRf3|x)Q)a{@xZ{;A2UE~ntC539- zx{wR8TL~J*1fH9itNM;iZ`90(hx$>G8?$4gO!aOkie{vo4E!rXyXmu(vbe#YHACS3 za+o0@vbm>>jhb4>Je;00EXlp!k`JNqcaZ^r;wWJqKBg=|L5F+cEIU!|980r#x$$J} zxdwDKnRVJ374nI>Ij5$-BO~2tJ$QX`bDNoc zQ6=?TZ;Y*)h*?_Ie))>nm067|vT{UiphwvU}19pCAc{xC1?BdTfeqkI@M8nutHA zk7VvbOTnv86$G~cqfV`>5B6xjw`pkX7;IOj6j%TJ2wW##%l$ES6*QSGzK3Z4OZ*n` z-JFP8&YScW?Hnn>X=*&V!QGnr<{Y#M>f_c8sT2;MU86 z2x&1LW^XhKZhrv~SqH6ZX;&_XO4C3X#+z8p$Q7=6t^@(fv2XP#k-A z*rqS8ul-c0R7UXL(NH2rzQe#?Hex@>1>`nhDE7{ZfnsE&K&& zS1DmIo8M33wHyrJefH6ntvH-1Js`Y8rF>3N9iX{a>I@S{qBB1sJsVM+CqF5s*{H50 z5N?PoG9QS%eC>}PKeIxm+u1Q(WpMnaw^Z2=ND^}_z8g7@%J0n`8NZKpFh4W)Kt z@v>}I=pdl5fMWuZsY9Nd)z+(xI*FN0_m2E|(aC%b@kPNg!87#z{r`r{Rl&QzEJd5u6@e3ls)o3CM-(EZ8ya~z@j`WfXbvs%NOD6Gg6|CiM zjh2MPawdY-y_!mb6fQ?H_4U0G{CmP7!JX(BnRz7jC$M;ysea+<+-O6@+!{q~K9 zm-9YGxLzK<2r-+Hz-|9YU3f#$^4(`Fjo0_1zuz4`ND_l<+HU+%mCSB^+ ziPW0De;;Us%;jaH84|EA=d5>|8cH!8a5%uxuDsnj$c zz2Uc=vA{%K{MH}h+~kjOoQWaN))}8V4ql&EqPKn?_vHm~_4CG?j^xU8{GMW8*In#N zr*L;YoqnXJtp)eQ&_%qzScG1c*ul|$jON@YIuys#GK)fMRZ3;4ccG9fH}<< z7252{$*(rq?j%7`HWoj6)IABVJ>|AHJ~N-*OWAJf;Wv>IL{A+e^^P*ZAHSN_pWj@; z*Vh9!L(S?BMPsm?KE`;`wcL-fZfyUSl$shZrlt-NxT^Iq{(X1pQ)fA_mXuL4N;1xq zTDFltV8dsiVa)9!&8=7~RkBR_U>M!YzE~<&bZR_-`K&?8M7#|nf81P*R zU6&o-QMKy+?6BY<(xBy~+8iFK5GxrjBg*psmdecdZo1)d-{MJ@C^V@*^ltmhU4Ryi zRNM}^ccPvJYCJM72~O7X9DTA=h##aBdaij--3s(b@REP!vu+Z96o^5cN*k*fc=cm? z-ZoJ28qJ`Z9!XcHDNR@wH;{^*O7C~3aKr|3LP46WBk=>n1dYk{>L0iGE==n;}z!IBV{*=N5t-&Z-eX;>_2Wy z2K4#F6V}F0)O@US6##?5cjM6Sbszo(x@X`bX)0@za|;4LC+;eM%QQ3fm&TDv{{MHN{V6Ck6fRLFPfw* zr`}J5d7!+BcnVEail^8lB(26_bO3qo5-r1zwpH8+lfU?=dJqUK>@W8h;$(Kwe8C zGT5k~BN&3g6MwJaZrIivvz1Vka_=!f8l8B5w{=y-S?mQeF1;i66XBR8ve1}@_C$3e z%pK`2KWo54QxIEbO8-yn|8VLo{qLAJw{a{pou!AbtJ=p5apL-T4z9|uTs8nqoWp_8 zj+DgwU~~fpx7m863*I}YJQ`omFXv$^DjdO48Pb>db)yKT6}0&S;qgEO<)Il9Cj%44 za{aC=vD#Txs>L3cgMl@~a7!TWsj+z%T8$x;wYgfMgX1KVI!Q-%wT$SD%2nx2ZK~98 zdDg>oK27_y#it?%UB-v#%QD|*L>5Ji3oo*d`N7d91U+B=^)K2L8i!t$n$5pVe5!;s z#C@;s>C9GEKK9kbW##&mFL~d()k;f^)Dop|CaSSX5tWD!%4F{97A6ZSjmvBU4|6#* zkFPJN6s8#u30?`H75YijOctg*M-UR~vK$SF-XLlS+WHupg=maR`7BLPy!T2O3QfxX zyg25DK8lh)Am4`L=ySi0PP7IGrAq3PLmtr@V4e!e(b#EzFUq?c z=mVqGvuf5xn(#fKo`4}5jUllFP3)S9Xw(Nq7h66ycH`HCOw=ch3$C&yHir_`m|RvE@@P>{i#?eIdZ|kOy>XSd z{rZ+VZDQa~s>j4S#K8PJgQutRN0ZEy^g_$Z2O^PhNpqk4Ir7^e@zJh({Vy|0!XU=;jt^y+r_54j*{lx+MG@H^+~(Zu zQH$_ZF%Z^eibyb#>bEOeO#~Ow3^bGXvUR-v$cGm*OaEipqwi7DrX7>SHb3c|~ z_f`?F3Olj)oX&S0>D$0*kl=kAri!KMrE?v(_KcH>;e1q!uw^~e=b8E+jQLM1yiURc zVfx8U!j&td4f2!%W3m&DwK56vfYrFH=0a7PrL0kyq3P5 zOq;S(hNDsGdO3$pA6!1N=6zh#hYucJEq;rKGc2<9?Nh-s4flS#T4w-GujQD8EAy5K zgWN?En%1}JVYtvutpfn(x#WBI7*bDQYLHIK%%`_`c& z%~KmFI`+Iaa>NY(F>>l&*`ol<*tkiVU79@n{HIA-<<>qU#DsMmD<6b=1qc}j#TT3^ zv-V1tLuqdH`pshiDO579Z{O83pG9bOno9dQP$QB9+qF*xkr=|yF?k8584xs z+14ppd4pskW4#xgZ!%>c@?jkIZ^SlH@F~fPIjRdTro0JR*bCNFw<~2U;y0_bS$UP? zhPNqZxQXIjJe=l*JxtTQEi1-CSqvllUu7T^)=e=TA=~G6oASD<>R0yS30sh})q2y5 z7hW=GRQ5QmwF5_U@so$8EC2&lwy!zVY@BCP4g1C~&{!xotK_DB`A8pN-Y53h^^+&=J~4hyiyj{_CXJ8?A)(8JB4t=2wcF>g-1r!%3k za`85kIdNF}dZCGL<k> z!;QF4c(K^JYsYZQMc`nrCnuY?esC+(S>QP9gar#Ppk6%7xfL_=2~*V=g2?vTJ|myV zHTlVbq!#6f4El9*8Bpb{mDW@s&WjPt^sa(|8vq5k*K=Lu_**%KwT{B#%{uKw{g#)4 zc#=JabMC1Ts^WxBSc8{K)82B{zmZy8&}wA_X2{+{;@$N=N-p_Yd+3jDD(xC8$%Yx2ui$vdn)XK z3-;6-R9yyhTw_6~cb{Z7e%T05UC<{yV>j`sDAI}$FL64^=iy7XAz3luS_|=ooK;Dr z4cnc@)ZYzkzN>v5p$nv+5`U==rxb@Z}ev2dV28>{bC#19FQB z(7~J5yp#H63+nbSaTvE*fpdO9P05cA=ngN)ZQ$M)oCIFL%juqXdeuJD9`~QF#=eh_ zJ!`OA&%VyzU6lWoEUVuO^xih^wB}Rb@10%HTk$>VADb44E>-`3MfiYr$p*Z*7R6&p zW%QM%XNs#h^8T_Vb!+u|fdlv;bm@ZL4(@&NxcSa_QzVXuMWvojH0bTxGvSsc3srYm zHLqw?uS{B?$XC*8mL3FxXe6mtrD#MBFHCEARIM1FtrVspIcv2Bdv`2j7OePSHw{v~ z>_hP&X&xNvnWd492|3xP6j>-2Jm+Wm?c>-2eD?- zGoU9;vPT=7&SYZ}m&!K^D+pUCWr_TyK+GtzrZ8*BYXM@YV<}TuDi)DpBG4|79yE9A z4Phu;9w&)gBA3B$pzsr5rYMk?gz8o)#7@FDPl{Y3vnI3X=EFkPDiTpfI27Ke`l2{a zq7W~ht0}0|QX)UJua;1jJC~ng;7qMh!YWsQ9W_4)SY0eptKz`;&sJ`eaM?H(5=+~Id--W7pbktxkRStTLP@yhe&b_DugT|OPF@nsw_HR-9bvXCH!@(r!dJYfRI!0tRWLkRG(S2_ZP{n4&1@M^ zQ#NanJVsk+0j*O6msCF>#M$axCBLyFMP@;+QsGZ>f;q;MeO5$9!`R$Lb@*S* z;4)J(jbcIyW@RR(>IH=4Z>iR0hg4$9G!!X9aiK~5Z#}j3JBb42;o)HIG;__$q^9cV zl@=O}&5YmHmUHj+c2N0E2~zQAhkMH&tM(hOH#Y?_o>VVXa= zST(<@>j>^C%RB;AFD_Gsr397N9GltaG!sp$YinCi=-~()#Y$c(G->cjiX=q*_lKR_lNC@l_>bh*>E!LWh%7=%Ui6Cu4-uh$65ca_h4-n-QmpSMMz)q|XUJ z*D1yWhb)ZrFBW?TMh}Y6OZF>WxD~|kX0tBSZPRUKwKF=F_8Zilv8B^kQK?Pl5qdOB zxkPtAQdrcwQKQwOg;A?5@sFcwVZ@_}b;U%+iZWJ*eLJmj%vGHnGzV;}C@FOnq^;=a zfzr4{G9o)yU6DoPMQ-2OYjxcV3^Ab{Aho#(z6jaou-XFiG`3FfxRjpDEGoqfFLBfB z3=UtupQ&c?OSm)yAP1j=B+BA#Ye`&HX)W33bLvFm3XIOjIHPj6XDo)n~8O^jXhy9mfod0$rd#Katg%SDMa-cx&} zI6GCPJ)dM!o&m^oo`1h{h@ljcQ4kh!7NNtI%>4^b^pPNKcxW6&vnWiU=JaUmbOCe} zraD7eB^4A*8W_HzyWr;A(23}iuPFhzV#zym+P!u53f}XyK-TK2sI071_V_!WK;6J7WK;Xl{#*CNQ7KLm6S_1*oMH#? z>)ccpv4~4__i~80aAJaC3k~*+JeS?o1{g!*HIUsTfxFf&CH+W}`zVc8d}4IpB%SIQ zg-$;rN%a6Hlyn3tbXGcm%G%(ZBgIDVoF#>4dg1g84b_NMQg$v$Qm;I?m?x!yXX|bv zVgf2Xqj;POXKDd~3TJS^D@9|_)`B&mq~2AlgAnX19L)^O6kMfrR01)N0CXiQ>PcUD zPDaCO$d^e#M#}9k#_LZKR?y3G@K7)-z_|$aHVk51-XS21RF#c;M?lmbseOG*U}l*5 zaK+ww3-<=!HHou7oAj~N=jgFC)~-OV9kNx|>&DttRz_2XX$t;KmSP|FVnuTP_%r3~ zzUckzUdh$z%|=j2oxklPaQ+&eNGLTDUg+gTNwk%>D%Pgfle)v(T;Itvk-VeZ+}G*D zuvVy*mxr^%+fv@?Bc^ht@j=4rBNnq@(>1ej)Acsm#@Cu)eoVlac*4{!HI@u-O&BmU zr+XttvQ@*(BtqVDe(!wDkz1p(T4cG}UBc=ANxT=qBgw1NtM*gSL#l(vi`QLKtRd%~ z=4F*qS*}euh28t7F<0-arbJ^KMPd)5;4VrB84@v!DK}vzm5FINDI+H%J|j6JRpbG~ z96D~Hn6ItSKqEkj%PFtjZPqIIacg>)lkW7tXji zJMY&wfd!72ix@&ty+jhRyx#)dOC5CiIfgn07)CG#Gy|$>TO8$>*@W5jT6{gDq3sC& z5{|$}v(N{1Tv&{wxM6JxiAc5nM*kVv395O$P$)VI%x?cmJX-t3RLs<29-N$OjP2Hp zedkDXtS9wqmTImlp2xyUSIXzMs~X8QEO+UVG$+PD)IEl!K-;1gT}z(v$wENAqfXYt z#`foSJDB0^In9PmED<%U{pYoSzUeF9-}Qk^)}!n!pBSE*t7+Jzd0V-w z$}O;a+o#WGXvdsazt^Z&tH6oM33;SNY?Q)zxs3sd(}T{$~k(iT^n zyV*n8$<~Scbn$fawDffKG-pPxrB8W#;al|y<23iQszwuaNXlc1Jhh?by@pEDRqxF= z-1VJU#6~N1XpQWFP4`U?^mX??TabG6pWV}bqx1VZlrFsUQUlSu`?$!bYdo$V^gb7I zG`A#$=gUBdT&Q>XV&L%ot};i zM57qCj#?rOcdl*^mV`XFVfTFl;#A>Ku7eqrRHR3l$9AQ4W5k2PV zO0)!X{VT=#%#g;)acySjjcQncdMp_3C2Xrn&~^4|0$L8NkYN;ZZ!MPga2h6xGAyET zJ(=vGmpxgD03oJzqk?qctinyKCK*H%-8usluCL#l*gjG&;Q);Y++E!h4f(e`Z@~_c zi1J443e9g%^yuPH!Y*t2dzz`ZWe*VQ$ih##sI$ny`E_SysU8-J#kAf;;p0Gsqtd28 z;d3e$L8MCRJWBIx_1%toI%aRfw~<37U94H#jNWo*ZHs;Tq4`6DB_S#+(IYI{k+ulK zuufL7utrq`17~FIP0)C*2&flD48rpbdV?vKq|lsvg)%ACKf(gCb|v)Jcd!1En{_Ki3sX7N}CC=q2y|KO-5 z)}1$BAUPGika3%;RKQ-f|5bW9h*n8ppYbARvb7N@_YgNz+JXgS!9GT zm1}XrrMF-z+#<>r%L`fG--0N4(xO+sWeV?wF?<2HB!vF}1oWk~e)&ZL*n! zvX8Zm-fVHxynOcGT(!R4(qFsli-DG%$Wh`=2Nby<+8-IMjc>GI$Y%2+|K_Up-e~G( zy#G$l_BD-Y2^;+Xk^?lxOW9-2c=Ft0ZpJzGx&#H0S+gY;^B8F`aR(X%6ZVQjd7tbI`+eO z`YDcS#gZAp7G;tPf3l4Sd$WauF*?$UlqgNpO;Yk+)Yi-h6I&z~AhcI$0PYGJs#vd0 zhD*Rv3I!e(D4Mz&iQS>gPc1Vo6Iad<=b{DeiS!%p6ZFIJk^q8`gGvHE-n;yj z0)(=63qk?Rx(D3VH|Pfs00qv2x>p8e=A)K_P)`Mk1)B7;28>+;!btDBqE31JZT)Qh zDa$_K&Om>uc>q~4{$auVr41KCvzWh2?52{p1Ey3k4eJI(3!vKr{p15G1F7)Gj4B7a z@GI{7+s81~j6I72bT#|b7o!W3>emac&A^@qq{N5$+;7cCW5-FS$_A^;oBgS{Z*-5l zXWFNuhc^fJiR}jIrtU`jhO(!;mt@EG#ssLhV-qIMl930+9GvJ%`dybbbej36fMXBltyuCEteeUem9-k429YfP9e) z?gGLKk^`~fp9@->_ocj-I`#wQ26_hM6aBU`^uU_-^Lrzfa5uc;1@K7;fX_pF#cYH5 zJwTiTgpCh+#E1Qy0wM=O!AG5S#O#MU2ke2bb9R6PB*d@-RP_7y?l5T3i(L-13)l&$ z7ggpV)NdF6$CE4ez#aQl$?R~p@H4s2{|5rVe4iSuEmCZ^@mm`!-}0}Mbx=+8pg%&N zTGJ^MR#f6$)u1Ce;CCI2TFf&_p9B#7KpRvU+D23?2&_P7J%U+(+vwbj{ZZ~8mvkEF zP-(z1Ffm}0Q!EPrB0u-z4pjyWn+N*H2NL%i-H!-A_&Zh(AH}a!zx2hR)YYK$C4ql{ zhYj9-onidrRf*{>}>2mlB?C{G{!FF%Sr%ramLe~vSg{}cy@L8+fi;FfXM1&Iy?1IpmH-}hUOC=PN9#%Le83yh5z+1}Jo)=y{8GM@|?GC?y4 zEkPC3(yzIXV~>8%eh)GaMGf8xhy^4w=wUq5pSn*)533Gm4VVkE30M}G7sUfX`TvP$ z{E91nrS(KFaD-zdpi{4V_C3Wt+dk92(?0h-=sbv5#CTG$_`lL@xdtHMKq!9DfIqnM z#f-(MZyb96iU7hP9B?A|FFX`1GJzK{Bi`jh&p=yCfsmskxsGQQgYw}5Q= zUH8E?aYHsi`X`yrovQD#>!ATa07!bQ8@^Ci{NMjQ4FE&{0|4s89px45{=*+M?%4T} zH|(>PV3Xj;7gXIh@*d&Q6YF@FU^l$QHJ&%*6VHzq1& z$C(HJC+H!p;1of4_HRUvC^B~}*+%gHfynAd^mO3 zPn3SieT97weKdPuP2FLqvVN_8yC9-|t@1ydT)yzwU^~DZ{;uJfc*3}Qkz+7h{WJH@ zMJc*6Bbd6sbo#TKqo?S&g)O9I6A>4o$$Ed!y{r0z9)+DdHw-()MKR-m$K-voO!x}z zzWC8RzBK|!7gx zPL={SMc`#-aI-SF*_b`;ES~q4y22D62xX@KxzOwlp7oyF)4XX+aw8KfAxKw+v$VK{ zL~oz!1UataY_=$!Fkke&-7?M|PWvPUPJucBq<1q=>>S|=n2F)^=}NVq^k)agV^W$j z`pl*I(}Qy-`ev7OP0Ir|%Xsssf34d)m}M4*Iv=w^D`$tU(K%slNlWcjy!vuihylJqv!aL=3wS_TkF7Q|IJ?(V(k7K8{pR*R22kE-mC~0>-?^o-=|8Ksr6t+ z%OSNXL}zXbf{@WYQqwK45BL?>GjJPYye`m(|LQ!%eCXbdkew@G8*BW3PHq=?j-!7& zybII`WYmur=oZu$gao6zSIU?`S9@f;G(r>^iv%jxG~@QVBNG^x1F{W1Hw!M_v}sfCBI4Z$mn2> z_xVWd7zzLE7`k=+`+xG?cbtpagyL$89+eKB72N&>bj$onw2#e;Q3s^xR}N%D^eNS} z4K@XGf`73ceX6y`-$eTh;4^sm6*4Lv)Ox5M)1K{ifRizLKH3SW`eoO9(oOaOr~5blV`jPsx0KM4Z zzSw*HH#xrp}Vfm(x>K`A&1Kt_&V#7c{*szbaIsC~?ARDR2allpPwFYvRc|O!OSaumFh?Ah_ zVn{Wcz3k!R^7FeRHuSh-w(qv;f%9@p^^|qxE!w%kJ9}5*v~|h8jDud0)Z}7F5@&jO zUTd57$$A9H=%$0WO$B`0v6^aiVtG7oQ5JS`aTk?`{_9#xN|-|%h2x9xbjP*Sb2a-$ z+qJ`W`@D%R8?~fTs+oZWwT1?dUX`O+Ooy+fJ(sxW=p&&BzH{zmx;$+Fa4^wIu+^+JN*(|m2Y zgg@ZqVT`?f*V!EuG9g&@jjeae^)iz0-v8xQS~C z+ueV81(m4zL5SUxT|3yQGmSRGds^2#P9BwW>4Gghd7O3I@`~Q4MSt1O?Mrlnl0C%W zitIgLw;F|;^}?my6TZ4%pZb-nO(Xbpzj55f@;A}gf(Pluf+rH!3odsQ4Iun@AoqHSw^2k&)U&8(L{tZ)a`=F9nw>^QE#z_q3^R zauN6ncmGP$6MB0H;r5$%C>C%?$NfaAKf2^&H6(k-_=%kfxb25&$EQUrD*aw~oks8T z9pI2|mT?f$h!K zhI_Ev^q{Ivbw+G-*8W=SOPUS-w6hlD7O(|vmv4!-Z!kJJS8$7{b+O~x{?bs#?;}2{ zioO`)dI+U-FD>HPeCr+k{j#S~^~hc0xcd}i+ZR2urL?WCg`j(=uATGcv-;-em6&3? za4*gA&A-YU1b-+~<$6u?@PshiK|3|cp8h)O&3i}PYIKwmwUrRB$>1O)~3WhIgLi zKR=&Ts;Ayqq5E(3|Miuq&ql9z6#c;eDe3Xv+z;bkc7I#PtMm3_RxWm1yYgM!TW_gx zz(aha_>T~j5#|4j$cdq-h>L);ePN@F}P+Bip*-yni!SEz(Zu4>w+%SJ1F z$;V_Y4w904;gYneRVzRCFW}l-MMk?jcS*YVvGa7aq3D&|A=bWD6V7fXypsz@Ehsv< znU{NAm2&2KKX6JsTHcZyC&ILIxwN`n^{0>Q45z06=NYVKru)%s$c^^saHE-Y5RUf0 zbZbX3U$#nOdbB%-7jcJGxI(Y@0ZXET(Tc4H^hx!wg|Cdbqv+oO_FM=yQM`CO*Vmqf zt+&xTJ**xdH%}|w^O`RsLft*AmS_iVU9fmg*MhHfJO^HauTFL2wd1Q-C^nVr5FZA- zU2q?UP;f&^Qi34lQZLc)P`TyoYf!icX`ri901>*z4&4-1O83Tu{|7Z}R8`fmk37VT zLb8FC9>8RUH`=kx^tb<;pF5R|g2$>p|^j>aFUY1lRdR`y^895hcBC9imDOJ z-DHre5w&TYoChDP{58>flv#bxHCyF-72^L-;(Z#o+gv&wv|fCM%1v*9e;)p3!{6ev zhJvfQnSqz(97_wd7i**bhOk0{jI|scFg=)!sO~lBJjB^Iq2xyORo6wgkzCSKNRyR< z%N2i(8rlJ{L*@!Xx=V~H4qOOru~{Yq*p=c-BfJbk4hN$+u^n+%Lk*P@WTzav`Z7NR zMn^pcd2}qf5lP#hSw?MLy)aYuoYZoIp2VqwnI+URg^;SG4{+*u!XxeIQ}(mXhKto= zT>IaNX+oK$n)bKbKvWMXv?7z+;BJSX%tD`})Mkf1>?l>rAh9^4Oo>>bRfv z)S{jY>B7M3*Vg&Hue$PjPN4g7_iqD;NX5&MN-JC8p?ndrv3GE=3rKvt+t}0ceMxrw z)ZPBV4O?M{4BnB1#qc@(O7&cU`cIx7&&p$a;Iq95totTT?^&7vo-HT}_%bfFzz=eF zhbLRZFC;=1N`sHWurE>9wg*BM-7iVNavS&$A=OB#0V6%-)QFpr zl@A-Oi_@$B8hy+xoD4%E>97i04~Qy;Z}qc?6Q*zFv(3ZKVGeDO>uAsZ=SNIv6X!s5 z;`8vO5#(%k2hHd968yox2EG~c*b45vL)Z$m*^0C+^Xv_W0Qhd>@B%5?={c8r^^D!* zx+t!3R!`o2)U#Nni8wEMtu%eyi5o3f>MlPM)ZTV(;9d~E!ep5TZsXCjC==uIZ^}fu$jp+KGu(4y_ zP(lnpJ+4Os6j)Lu4^8T88kn{bA%svS@~cU#1icwiZKWlBBzWq{u9Adyk9QAPIsCir z+G8KQ2V0JO_7jY%J#|c{zH4ywrjXStkCaXqqr$Ng=}0hYWJ?~G{|BvZ0Tox%w2Q`o z;1Dc$fFQvkxF%?D2+R!b?t?qQ9TMC%*bF|nJHa6^xCD0#u5-xye&28R-22Npcdgn_ zS3g}<(|dNWmfG9EV$oo8hq zNx1RKv;q(^H%e2!;Sb1Jj*wCQVLNq0c^XCR+gP*Ljs+ZYI--NgutnGCQ%4=UpP6;1 z)BUG9c35WgY#5ZEbk|!WDu=de>V3k%M_gs_%Vsr%!=+w9%fgYmAJ5v7%>qHMj>Qn5 zUK7Ecc|xHL_050SJ8PSEESoOZm4Sd_cN4yQ&|bgI?3{2z9$hVW!fdi_eWi(_{znCnT?n->>^LV@+nzQ$|%(xW|#STiD4CyMH%rFqQ^sZ-j z2DvHk(%c+@?RXF22$g$E^rV7AbfQ9@ZG^3w>d4dc9}?Y1YxiBX(Y;{vnhpLhoPrTAwV=t&=2(yim;q8zGJ6#piRw0L&Q9u%%* zM;pW$EX{&pLbqx37y9R z&r{h7b`PU1lnf0Id`lDV9&T*VAmX(OTPO)h+o;!w{sVq#3H2IbX&Vi*;tM4aY0maA zLfgbOQzTp9rs>9yVTx7L#Xo$FJ#6@|I1ARoynCCbIt$jJe~kY@mc*o$ZvAaJykYtn zDIo3K5%!9g2@IpKt<6kx2E(vyd6Lp>Hcd_bME3sIFs!`ue?=G?zNw$}u$>wnZmgfx zw&m#_7O0=a;bn4!aq@b8Npp6DvDyMxO@;sR{Hs???iBPw%fiFy$6{IFZ?~+yoLS?B zceK4N6ZJqvr(*EnqHoHwL&KK4^v0vx<2^t2BKpTL&!32oVMT1Gy8ix0w1!k1$nx7& zWXbZoReqCgP(}ajQ4!#iMVIae$3K&P=NRv>&VUV$xBbIw^2v%yzXQj=lHOTi*yEQa zlHU2n;K)B<8vS{b!6f=;pURZu-VWkAmkIH(&<=BTY!>&HAeEcqU>d+gO zUJ5Q#c5PB7!KIZOIfK3LbM^<{y8_}?c~LHDU0%F@HHy+ltJ^Nu(cC>amoYa+@}eWB zKULquVN_qr!NFeJfo&geNbV52sH9~z^l*b^FM_11lU5LA)uYC_^ALY3An$tc=AdIv z{MchOBgePE%C4PMM^H^r%QM*%d%CqhxuKVA#Y1?rfk)5t`vrp$;kMTH-D|SFIq+Qd z1dCG44NR|Apk%N!b8BZXuua zX}MtarW|*TIko+>)>|A+*p6MIdS416-imC@71m^p`v8}>&b*hdiN^NklB)HvHjyY} z7F$kb7_}q}&MUKiybOpQjIWh5fiYN5Ei2FXqoOh0Jx60|mNG!6V<`Dx;P^m^mUilj z54=Lb2WD6B`$`)i{Y@l4))3M`1au76Bg-o4E0oIWew~|l}Z@}j^@c~J=`$HMy{z$^2fK~2E9Lzs5+IK1HE^W3Z{Ux+Q}yp zTy!pt=nePkz~#NN_XPpBmdGPN+Jm-*4GlMK;@r_WZCO2hXEMNMQp9x%y^C+x5=|DW zBIlXbT;zY$s~Ru(%cn&wk-C`8rEuDO3?7y|LT`G%Kg7^g+h2i{Qe!1%N*=2*pL-b? zmf~z0uQ6{t)9(lp z7jD~)`93c9EcWv{8=$t zGq@~k_{_& z`W>H6z^c9y3un<-RAfqnrHTV#`rILQx@J&}ohH@DYd}hE}E6`MtMu zO(&~*u>n-AN;U&%`eOk9s*By1;W#7#n5WMz>y^_@BryE&b(Ssp-TN3BU#gpheYB zOrXafZ?!+&5&`O6{==aM+wGHkWA>iHzip=Xg5zjKYsbgVgwxkL5y$;Ur~!G<=! zre929a_WOkT#t85{n6u%#!pMSXT(oSxMRliO8%qw(m^_EGw%+y7{C_C390h+4OPC1 z->{``H<~Vb?Y@tU>>l>(J0ot7?X!2$M?)ISkDT5oBo;f-Ch#a6hx#zGD9x}f%I9yG zw^fJ93POFrU+NcXK#eJ~gKCYjvT2Z|Z`C*DhY4lA!@3s1vb^#$Ob4MZL@q}OBhhN9 z?vJEabyG#M?3U_|HRB??L3uUJoX$)ONFeQhW4rSl??RSWX+|fx9(2=ZUhcGM^;nl^ zLMM{&%uiSh3dvmz3iHe-eJloacMKVI?owNRVvZknB8~s4K6Vwl@TaTgRe!pwTPIao zWtHXd&)WfbAGIB+)=D;^MHD-UB#adN#KgOJCzz`fw0Ij2(}O8BP|X2~_ElL6e)g2l z7B1i%FlsB$7M9$Y%*g!yzZ|aS;$Dt!;KUT!p(;b4p$U z?iTziBMHB;l(l};g5QC!?Dp+gA}{KC8NkeQ%X2t@1L!+2)xQmF z_pgEN9s}R*>K~;(_eVdo}7$)VfkCr1C=?+xjJ(qE2Z(w5R+)F8k;$2^|WRAWum8J1+_Eu z!sP&^n)2sTehaASV;bBCcq@4T@<-~JHw+0ZtxVw~>(fUnYpN+uIwpLK=q;MneJtm4=Llp`uJm$*mfL$?VcDd}gpSnF|TcvG| z%y`)~rS^s7Dm{Kw<~n^cGdZ%Qg7>1Mb-Nu>QFGW{q0UR-*m=^JXJ5UBq#jwfI$7a1 z2D~CiNvOp1#ftctyIE;p@!KxLiXv%a6A5-TI5(r>b1?qV+uCm}?*67OM9{D>E#bXM z*Ja4%-B{lv`hjR5&_)!wo^3jLHdY6N#or`eQH$U&ytr+WB;-G-r38lqHW zXJ_VHrk4|+B};9uqP>?Nm?>S)&uaV~$}&kb-2?t1`;pf0E%3Az-fXAP+Es(jP8gkv zP&pN~e2^YS6kSttBl0$VC+}kZPe|zXvL-A`ulWa??m7`0#9fH5crz@!VUt*B%j@x+ zX=Rn^`Vf1uk{F|D6)1al{fH*_m1{c`TvB;XO^S#UTk$oxp5%#pA098Hb$*sMRN@te;P4|?& zjUm?%{X-;2B+4-A={Gk{^9RcD)97pw_oqv=Rh;J7({zIN&uzOE>i?t-Tg86^OFAt} zI&A96U9-_!RewLfqA%$Y@WP?&3;~ zS(D@LH0^DE??t!arl;M}QP|(v2>pm?%^N<=Kk~S^JodhOg1r)Qh3gZUl}$-{zm&CV zcE!)LvV1~$h2#_V=Uv3A!5tdX9ZB0s{7=JB}%{l zB`d40&Xj5?sak3dAyBBvEe3MI!wWRW)&A#XLG%WEM_+N5MV%}?S%812Q1Rn)#h&?N zm-Jv-J{ohyjIew@^vA7OdIVj1$mw{b>#t|puges|!s3%Zv52Fyb_kB6ResZqc3t5N zjhaOJXDZUzp1Z8W)1C#mD$q^;Jba1bfjiPciGD^_r}l#@pfN~9TsPlEXoNE z(vvarlKJVlZ}9s}F_jOk8qxfg%}fF~41Tf>v-^Akn>f$N5oTgOu6!y|tJ2!vJHlJr zkm~4ht??}@s+$!&dg$Ibd9~5ojGnaOU^M67P|5VI1Af>dbxTpw?OeZ9<6?tid#nR> zFZr$a5pX&)H^VqR{flSeu(X^u*^0%ZRFch?>A3Fc15f)h@++ksPr~_thC8c3->Bnq z+z0N?HmR%Wmk5#-J(~Xx`F6IC9-$)aH8?YE?yp2}rRMkVfvSOHh~76mYh`OD(6`U` z7ts|hkI@rESjY(z{;|~^9rN!(YG20xJ``M_Zx&dd2<*o^XGcOYWGtYHei8dA2WtY1 zgVjsrCTyzz?^DD>9ol4m9?it3?3B{03}jJA>Y+vzFZ)*czMl}1#o*af6Rwr=q0)yu z_p<#mih11dRD`#E3;Al{NfzlRZW2cic3$V9ktYPSyk--3mTAD9sznP=E$l1QUocmf`{i;o`ON^d*U z(%*PW`qJ(?cC626pJ)`zC=s1*?Ubs89buZn)9pmC%80R0ETxW%)=J%&(?Qn=cv1T< zK>vJmNB`7`9Yss?)C=B&%s2BhH3`bf)84TOt`I^=>+ASUW=(-I2pt2qe9j>s0J{Lp zXqr8NY8e2?`efj4$>QZ`@kmvrs`o_Qj#j6N3&_$eXwcBC$tC*1aeRHwePmP`b{b({ zX~sNJTkjI)spnj8!dM$0&XR8^2d*#SwvDX0egK)5Pnz1-xHmlxW9_{g*@MTCeEw%7 zpXu27L&E2Wb7Ok{F_3Nd$#0tcJrWin66hhf-h7?cQn|af#Fu*;J}nF7AZJi{BNVg< zr_bcP(6Givd9cl&rl@uN;es_gLN(8CEErhUSIi#A{9Y7#?L^}dY%7CTXszL`_D1U? z=q?S8eE5K`Ow_I-QG!{74X3?7GC&fC+QrmK;4PB{cVbuF-i$|;`LD8=8V31M!pNB) zE?-Qo3i%QLpQ-psBMv*v{}cF~B=zv~haSnb9F4EVI$P9T{CV!T@@~1V?Vm(O*1fAe}voGG}CL-NDL{ zUtLykqg&(jA<)x;}f7MWMV0{Qc{TM;)j~ zBa(b4iR@s;tM75=)wo8`d>_6`YMXhvf#>_Xw=jGI@Vwdb3kdV=^2!|2@r7)kyTHf< zI5YaxDZOw_hV zm8xWcsPe;3RR=O&?YNXAf&K}&b4Z}XZGUIYsv#{EQ*9dPK zks%0ZnUJ7qlK;`!Rb^2}%@r!(FS&c@wvTp@Fo#jbvq^H`XR5QKeF+E>H?q)(M zGt~@F29%XPZi#+ga4qxT4 z9Qr@9@)!N(R2;1jv;?p-)d$&CpGLW4j*rmH!R==)F+G6w;q#>%E|>O=E;X}^H5!Sl zpyC$b$yZ4sV_a;FZgE1D4MvKeBjR)Jp9HZjKwHLeehp_uU`8C^FI6!G@DD1{%Cy1s z5&nJqU+PBDzfcWUiK#@&r^Drw_}Gy5zsb&;T1Wrwes=j+-Ro|g@T-6MXyy)8i#-xo zD16|^8^gr9i{T-%k1FC=9@2~F_DX5RLMXuO1oU{$nep2?d8XSf=SD1u8>|-f*DF$e zCHY?68PZ#QJu)V_=2RBK<1rVCISR7m1+8d)9N4ibv%goYb})}NX?j{Caow7DJ&}eN zPx7~$+zY0T$N}Gm!41~qUd|NRUMPa~fDAOU#x06FdcS0O5t^}2zOuiYHsEGbC{&*c z>D3`GT5>dntM(OJ1vV}W#*DfyMTWQOes8I7tg8&~E6c41QwWY2^||l!okyu^nPfSo zH})1={b%qH(d76vCRYG~;5U21@nUSB8HO7Ef?&+NwDRL50P4S6s4UeIyGbLsN7)r_aV(Jd*$wc-B(KD{{7f@|hxWCxLJHsEHKXqVoT zdOixGM{?VgY&0S-4cyEYec9la74aXywsE`QzXF$yZsq?45d1W6NAq1DZ(GS(B!nfC z>AL_(EfoDn1K7bfJ)M+(tGB-a+<+_aOKx++Nu_8c(6Q&WWPW~8#U$-bil7%!YhUHj zp4py9&v%e;uKidkJCbd{JQcEQdxkyH0w%Z~mrs#D%CC=ZFMXcD*$I5mu)9X} zSud~OHzO$=^V}gV`MI7u8eQQ4yQIg^tbQ4(qi4128IV`}B(0_>5=2&U#kj#Z9S-3x&p7`u-K&J6n9EL~i z$NvslGN1$8V6}Rd1ZWs+Y&X&QRmJG4k&uTzb1$s^grx#!DMYg3bz=MHPwkxQSWNn~ zUQZCFI>#iDEm~1hk$B$49eAdGmS6&J-+DYm|hk z--FS@C;G;Rt^bDMZ;??*|4yg)8IQg=EN-$}#&Y#7H#jzxPo~8oBk8kha_PMJ(J`S# z`S7UwlG9F=T^gTCEvi;6tR=u^N;{+BYt5F^RQkk@DyBCiM~V9?#O7|*V=AGp9sf-F zwuk)eUh!i2h^3CPJ8X&}JF%{F_4Q3lx({37^5D*;!~aI@`P9r4RabB_#ig6tD>s26 zboqcSvL!`Zux(ey12t@+Zq=1WJ&3We8&`?V0KryUvO+(|+!-VLYD)L|+M9fu0*?g3 zep$apM<7x0p@>H6U$0#X$LM=Lw?0cf_1Ro;GhK7LGxR<*qnO(A;xQ1RpUlEFJ*OG4 zmOR0|2ffU_l4(o}e!W+rhX4fJ(f>?q;qr;?Rr-0mBNIOx%{i}PDmY**opQhcBR8qd z8*=%dlRbJ9S5_px3Tx#Scid5J1t-&752+8JGbwe>;nY(eqbOuBvP*f_lJiUx7U{IX zT4R}YuIMa)sReI`=}d2>i(LV{&#De9_?cZJcd`qgO^_=gd{1M_VhM0#_9OjTj32$l z(k!fQL}skaco}8sg&9G~%8aIZpG!E;Fuztu5c&Rmm&m9V5st3&2ULP>ru6n4U9Iew zSZ22`U-!EZA52>)1v*>>^S)Ppn)k~|H|wdH!^mtk)tp?*Mf=9mS$k=<>Mx$6;NqpT zSnL*OTIdRmc~Fc&z%;P)O78O)Oj(hT3|-HDqOqrXogm#NK1E?U0$pr2{hXcZ@@Mdp z8wq^PtB9a1^&oZ})z+oSxnSt6EYmzgTK{Tl(ZRDB{8_(_Awx*BF~xETLmo6=aaEmCZ&w zdo@I&6J^#4= zB3pf;7D^99z!@GkvIaf{*v5nFI3+qSwC8Dc}%d*Jq%v8hgBj0iWM59`-m- zu|)P)+e)wOm>%ZC5w(9*NJM$#KY&TfVEhH4LN?YML}s!>l3aVTqX&YDpF@xZxGJea z%f>+#!;Np(e{GxFL?A~SdI-#&r)|`E1c(lEe7hJbbNriJos!r$sansIaE6mQH|&uf zAJ&RyJwZXc&Eu2mQp1b+}(z{QZ9B3F-I_)*Ktv z8h37g)He9N=0YUaUR&dtQ5jc_L>Gu|z) zm9L2>Q~j41|ejCCoy+I?2Pr zi!(~8;H01HAz3O6U-r8)b{a< zM0y#|fnn5Tp}QY0WC^ro!1)4YP86Vb8;nNvvO#mTym@o=x3;4>N~N@@cAxw8TE=O8 zPj_W&J@O<&N$fDVmtI>ob4^>RprH`N3g!4bnzOCyE7!^G9mZT?P_2V?Vy3{jN9^|>a zP#Kl-4)dSGWJV_Vp)2B#yWV4*z5<7R1IV)2{e)OXmdC5&t(1Xv?y9fRlL;j_pDQFI z`-d-`RK7--P2Wi%o@IBw=l)^KX&e&zLXjY+U6`7h`HmK@L*2O)R4>sG%)A#0j!J^wj z-6ylvn8#>+x*IL!uzTq%ylo%ePVK{Uv$?u@Q@rNk3n3vWv62Ti;l2%k#WT(lcRs=Z zmH8YE;O|1ryfuS1mvH=aeo}dpP1LLVUUOErt45?i=g-dEZ!Y|Ga`seL;n%=XeVQXB zgDi!s8PgfDjh2LaR_nYh8*SH+6Z@bT{zcA@qIb|SXvG*Z=fewVAkZuz&xva+I=k1% zdPI;Nd+GV+u*RpJQ;`E|b?e_&HF5gOvOp;1??wWVDSnsoJuk6a&=si{a#j~%oFlZK z0d5>`c?QL}XB2N6NY5a<72DEXYMNeO-hGnb`QgC%c_J^BJr4c{(QWMK`ftc`efJFQ zIF(c5$sm^DQ^ri_5D6jN>=9O`P=WfTJK2$lrFNmag zzWb~YT>2(`r1JeQ`7%esz7bPTW}DFIl7tHrvD&=M36|$oh8PP^T|33e22I2b`>AMv zak$X_P`GioC8wcte{f6xtIgWCNNK+ux2fc?=%P{dwiR%aQW*Cv7z;+2&&klvg^1(S zbLqw)T*QFXW;P@6p;r1tH$PMv^qVsQ;BVfonmwp`9PUF$fnMroJV(tIP-tA0X=qpt zXP6YT%k9@hol96U-VGsn6h;xDrPR3L= zx8r6@DbBd?t>sSc7nyjrFzoO0K<{rZjm1@QL+;@Xy2IM#rnVrh`(mMBPiRUT{{nkN4U`wXl_xe@mq?_?yk612UxE8i9pe}KO$ew^V8OU_yaZ^)Cp|*byN`|PyNB)Uw4f3?B@K< zT)MyY&JlE9;kg;Kvo-I6v9zCtyg zu70;$iuG?KI&-Q#U?<>sjdJ)(`u)Rrq#f59X(L2O@U19cQ3XK84GLBeBbO(d!g>5+-t_jY&szz$hpaM$6dQpUbVot&lsHJ2 zchqQ;h+XA=*2? zbV{_L9jwirDD~@_1tAw!k_T2^$x@!GuAf#YnAtf?eroAEpHTZ2sru=ZC@5yo>Wip{vNb^-mGec>S0|(15JIuxe!LQom1DZ+?=Zejb?5dSoeK;COWrY!l2eZ} z)IKy#X=6XAQv5Mt>u8fy^D&nDyCLR|)5IopmgqcHL!5EyE0)!#kU3tNgS77#l7;-H zPIFcTzGp2~`P0n7DXkj1=?(JiNvObgMn%Hsc$qJts~npR#;6DSx|BWcU9%KajOsnn z28wuU%SP(`(K#sKO`eVgy5#v6HTp<@i*V@sX;jD&#~JmA7k%>4i_;AKR=gosF^o|_ zhx;C_oq&ry>@)^5Jo`lzpu#9KB}QL6iM`c2NPygvD-N344;Wr&4AF)+FQ>Nmu(G;< z`wfQID;65RT#7KKQ+RLTK*mptq(<}1g3e0DCN~25Ns~JN%GFt_{2)MU5TgPytfK{K z=Zv{6Blp7mMC`J&Nb8r8*O)9UnGX~^7LfS$$bLlPSL!^Q1y6DG3M_&8u6AGRaj!u~ zqRLajYH48k$4RA^hH_C3b6{6Azb&HkrtC7uIjBzZ(*q*SJ;Qj<5mqx!#{Yw4%chd` z^g=xeuLbwWZr`T5?5wrA*E2$bE!x)Xi08uAFlI1wu$er)DS*kVcj>xwH62U$KK!&c zmC0_qF{G7bz;yA8*uwWV$$(NM>(ZJt-lAPl6fnOI{&N}1=w6fXAio|x4epWAMtIm| zIMWO`#PJ5Wer=hV8=1md@}${XSRY=8)9EU#!!egwv=0azX$_N^_6@C`o8`NoTiF!@ zVx&dsrR;knmW(zLKyVQ`p5wlt#7uMq)deR(%WgY&vk%^F8?Q*ukZ(yP8&s*pMi^8!A_)z)@cDGeb|S}@rA7p$9j5wc?Ou*A z%ayg+NULw&Qo@#n)#<-K*xFS!GYxF;;3hmC%q1ovUsTddXP}qy=m4*>>&@Px?aO7K zrt6z#JHEOzod!_W>S@C=>T033L23~}40xD#);6%=*bEmSCUHv;uIX8iF+;P?e*0R* zb^`B~?21tP4P+mk--ly!hW|i6Tch^231@^KZrg%m0+Q%j$k9~ScOWspKv>4clTzUMK+8AZ!b3H~Y3hpU+dd)>#HLOxF&m=Q%$g#RU_7dq5k*K_{ z6VYOY81>QGej^oD?oM(3rH~94rnnZ3Ag#<5C}r|UDQ&p5W$l1CqUmEbpfjFxZ*WgnFz(hCTo=oa)(C)g~pf8Y&u;9~YTy38mrI4#X5^rYF3 zs^B#oA?}1yHIsDm^K8B7(LcdBTE_J3z+1^ZKYsU?7-7#5s~cUdWavq~fHhn(;|1IO zbc6R@^rQ8A)Oq<%p19W?I8yB2=Ut0*1BjO8DWiE$E?&EONa62O+MVTo(ZwH&ct-Ad z_WesH{#e{IkI#}y1-JnQ9;#z3$j)~P#>)p^qgvQ23q3VID4}m#5D1qR7M{}`>UKK7 z%+18jhIZVV2Gn69Y$KZT>6iz*JGO?lY;K(eW<0{Mov0|rKzX|=;YtNILUcjIh`Vcg z7x~tUCF2B9r6H<;E(v${6WZLWE0l$rLJIsG<=UBN>#AA929PZqJtjFAb3P zZfPsqB9JA1&$Iz?U7u5E6b!5JZ_KnLQ**s%PfqL zpYQ=)%pS`NeIy9|m&3?4g~Ttk`d7WrVQjwL&SgO|*2^z>pFYt0{>gvV6CC>UEj+*M zpj$fSx5jncz9#b!k*>{=na{~MAg_o!U>jqQ9->m6jD2Srw#pBLC977Gi&~;oeH#Bq zVkU4*L_y|t8EmvPxfh^sW+infea29OLT&2pcO6zQ)QiV z0QI-wl9o|obz$s;s7APXQ|fOcB|9HU+FW(9nA&g((0CK02Z%O0*1K88fg!$=o$pn& zf1Uwf7gA&4FEw$;Z?e&PxSU_k7?QXP zOyw7EeHCp*B2qTe{;?M^OEG$3JZJ3_?X+8pa6VFv3u$tydyfJWO$!ij*q)qImNO0x zlfN$=Q;;xKTVSSGM}(}HF&uKa1s-H|VQ@$^W7vt&H21X9xuuQY1)VPCcoS`Qc$o)Z z&MZG$e{~|V#TxuLDiS*wui}MT{2X~=>pa$;r7FM4M(Yg^wB>-M(UFES;^eKDg9i9Dvnkg^>QSe;6P_9^LZL;A03 zdW^>5N1X}mOOrwz<6367+H^6SobK_>$?d(+P&@~NOtc#PE<)?qHG|uO0Mq6^jwQld z*4iWFUWJ5L1xhNa`COl8hY3g(vVH{l5$dw7JDatgrSFOi@nvJv7CduQnX(zf5|ltc zZS;57>1Zx{)2fv`PqX(=e@n80a* zJ-U@+h>Q9#CIbc(hJL8VFnOrO1T@^@9Et=oB|7#vl;NzQaV(Lqk#D5)OJKZT+i_>E ziOf%|T#unyupuL&96QpSILc(q_P&qWydlkLThaDqlH3v9kx2qHooCadZ+d()tMTwq z&Vp%r>#~V8=sM|LY6ouyk1gP6l8RZ0n_IoK!OSVeb>j9flL{ftWOw5b(aE3*Mrhc2~#}ObFqZcedyEWP`bTD!vsGK+gS%b$UTRx-VB676vM*DXRNjWIR(Z$UTUb0~1 z1W{G9Q=>IGWiJj{&;pCP(Gt{i!pA}6IEXHXN?=VJX#LvAysdr!xQ}2ixNw&;<2gJe zM!7LnBfG#htztsI;EI##k9j`}6-sLOod9c=V*82OP;^V?d3%FVtYX%_&GKBjgQ2RvJbJH4efv z`b$)Us*(g=SkFe(sM9iKzGkA(F{|N#*_3!OYWN22pO`woHo6D&r$S>Blp={2x3gG0 zuSt^^r=#dC6Rgpj#V$MnH_z;e zT0*=T#Wr!uXUCB0tju;qpjHfZPOiton_fX!cz-Mj2|H)6q@bJXTAfQz z@K-BU8$EtGFB(#pjk?s^>uZ1ztUl@#O2#gETl9Hca*X2cpR-wt*(bmvMD3lm(V}&N zrc(7J9?Q9e+`W&iAdTHU&+~++&-rs|#TPy>9AiTNZW|L@LVpI^_>`BqtUM4>N$0#G zTYPvFr(j3=F0vzhJd(nc_D9K!l!Q01SH?hpwE~_2QWF>dA;qt=sGNcyP3eE^zeve= zGe9~Fl@AzF`oWVd+`I@y)Hm?)gFQ2K^ni(iL*88#m!@c4isy-d_0A7v!8yj9pu7-*I{JRXSiKY{*!HLch6viz1pe_o2-+&bv+6 ze&BNQC0R0_XLCH1H{U!r^xzZ6Iv$m%G3|fS@aF3vQi4>2F6a3&t4C`@I(zsZQI=8s zFu1|s&>7MLG6=9*XBVyo9!!^ombjBr$*W-}FAYo^C_Q5Qh=TLWK5yk%U z>4I?jpoBqOm}#0dSEL~J+Q?1W)5EE~FBnczATbnMks|7an>nB@d6)D04NbxDCTkQ&E8#{Hj zhO?Lpw+uw@C@;zVECzKW6FcPiD-OjgL#Oj=0N~Ia{4xfWql!>!%6~d==>3{XuejJ| z!^vRvd#c+zzV17&l`b{Zbx4x@KG*muoyU^Y==`<~>0Dmcz%HO&(?eb9C=_jTn~+1C zEXgyPEXNhsgXj;`Mr0o3nl)`}1ZGP90h{k;q>iI8G&A1FwU|GfUbaN63%`#ZYYIiU zALVHu%^jyZSd$J3^V;Slp`WDdx+$^=(I=N0b+cM)C}H9a2um+X#^~kujgGH95w?9r zKelFGHURnFmvB}e%V_lkF!cmd^0a{w8cP9kxxU~Sa;W`@MvBP%QCn86Yl@Kn0n|=7 zF+CVwuRKaM}01f;v+Z|Hg^Dnlp12VUiCq$jP6Erh=Y&oFNONP2>$| z8@pVXzZTY{YP}d0K@0$>XigztsSv;THGGghr-A&Oq^y4kVejq0s-Z)3Ltcqf1Yx5O zU0cc@?@M~TMu5RAMw&ejGA-nT&^lLxQJtChiK>l?N}-ucwtl z8xziM?Os!%DEfPJ*5o}?9M-~b^pGU&&YSDhxZUM4cxJE;1Q0S=+dZOGH_Bmh93L=@ zp`ZA2%NYm@Pj9@y94T9$IbJ!Ja-&hQ3gx^`PI>mAb(jwAAm|l0adYzb)PKX6WpaE+g6oQPu;hV(y~6K3*hD zY{*r$X|t*RR&Ge~ecB*dU{dLnPmjWsj}_Yo^?_sw$()1kH+UyMa4Q3g#Njy(@xR|? z329s>=tTpg9oFCNvI7{E0MZbe4PN-TWxbGUlv>{a3=W292T$^<1vM*20So&h;KaKa z*W~94&IM$JBS5pk!AbsIZTAKNy$m**T`_`0P>~%J{QGv7^IXThrtz~5y>C$&XnL@J zR|@dX4!{f5TDP$bZxmn3IRt{;V;c2@-yEsNKs2wvc*qLV`W9pYMh7f*d3Wo6uW!zDb3!HTe8u{B8md{L^r0!iJ z;!q5q-etlA`f-0?g<;i%uQLwTBKO0A?IhIG>W|U1?Z_>nzGi6>OfjTX^=hnbm|EqY z8#Q!!jC-gYRwk;;t?M!wu*B&e1$YuMXmHhR6Ppm+H<|}Kgg+=(E0Y7N>$ho~O~?Br z=O-m4o4mXyxmyFgeVk!OQp>}PhiUswI*Uh56Rw3fVQhyHP|M|(*4s%ny@aEW=N091 zya3_Vv`tS5;oY??$O-(4LN(@^;!?Qm@jCES6khS{xYRl?u?s%JhAd70@>FQqwmNGm z^f}Vn_S9=R)Y_LT61@iAOcgh@#@j(HPrMB%zrS+vZIbY|q%_4=vAIz8ESfXGhQ+7} z9^@V1Lb^nzM1bBVly+I!F0=G=d6N{L)!wNlvxW18S}3z-^J^uo7aK0!jFo-!cqLR9 z*!$4Z9GA&Vb4-|Bg3elozc@1Wk<-@E+&%enJy;RP48^P%BB&^i1* z{yx&VK*z4lBC2M&Hc1n2-{is)`cv1aywVniuq>~$t>c|bD{0zixggx5n6J^<)AcO8 z4|2}RsBEi(>(TKT0xy6Q2oF?7G zR8d?eUB|#O&wPh{W6!JGIz%-AipT_%p z&`o)*={5beUA6Az@_yUA$AsPnBIP_2fr~Jj;zX=H^p#@Y*F4ad!XM1;&ZkHarw>FW zZPy4&SG{MHlHXeIf#>pk&t#IzGRuf#?Zw~Vlm%kG@&B?A^5qRRH8om9cv)`QKqVSl zS+4(fWB6mOv$5(B!nEu0gfTlieMMQ3iqRnqjpFQbQZVlJ&D*D!2*7<~!OcNqW7863 ztGKLKbDg=?MG#@HTYDjZaM7)~;Ga*=0M^2$XRXMcF8FUt#796Qpechb(k;@x(9=@K z8G&6gY&s3m7g{Lux32<({ky!P{PFyGujY`5nmVUvqnw|&N-wb5DlNy^Qo1JFMYM6-X7kzx-M)SS}r#olDL*0(YR(bjn@qC5}? zX}fC6GK;cxr|22Qg4fXhMRGYu*TFUazOik$Nt@&(jjg7!ZQHiZ#{J!{Zk=p9FBvuEgwO{Y(1O-?tB_%U?lu?=~lQTKbv&(D=sXr}i1Bdw5f$ zw@~}yb?$ee_WAjE@#X^l`x)vx=ojFt)O$u&lzMjb)&B<7J>i%CC0zTcSG9Wf_!aM& zICB@fkbA-Kk$UmTz3CV7ClBqV7TE;}?WJ}0IYs+Q-)r7${_+|i8qECkL-iw=d74EfLjs@XDs}2z zL41Wt$>O;i0FVp%eAcqgo-x zR`ylXZh!Dx6Iy>N!ro{xOtzUw`?(!*HjeQ4A8^L-nZ(>Sw_-nCFo(`OwRo++@G0(K z;wBykgqwi>B(giMTkUWZ>1E4u&jY&}0J2x=!U<}NF94FVqyaIf;O%I|n;DP69k-)# znDR7E{v;;nUqBH+ySLj$eM3QS$c{)1G`BCSr|w86$d~%79XsjZlG-|@6-!K27h&R- z-qd4|+-4Ts0$8hYPY@W{b_jWs+02&{UN7OLR`OP^2VQHkN{6aRH-Z)K zwD;*|Q3}-)hFuY?56c-&np_+C25KZ+F!gxkUwpnlESMurwR>8;-c1;GulZE4Q{5p; z^NcVx$bKHun6?S8o7jQdZ8J{d)U;HX3>xmdcRYI%2XSc40+!swCi;8}y}WK)o)2F3 zlH{KIES_}>AYu3pV4u6*t($VpR@}q7(7H@^@_`-17)Bt?kj0lKkVZ@qbg*I+YBu0t zdbpl3_d85`YrkD4`H$7Z5P{9+5iR`qUAJEkb|$RVikfR%Nh@9#PI3uSahZ)rb*+%u zJLl7}6Hzq`zcY{|SrBX{Ka?(<1g^%c>gP+X{jFjQ;wcCXugh;rc}F@iM-K%X1Wlfq z3tb-oN|7y2JKjwYl`l2No)#V^wOOQOpSy&MM541Xe+RckWJ+WhRJR-q=qiwjJpdXL%hM5tL6 z4bxBnu`|Ai$@@GcpC2KY_rx{9fTH&EvtsZ87~Mi40wr}bLo|NU*)GmuU2p0X!b_-q zAdt>Ed?t#Cs|Z_~Uk!^KK7CRO#nJP(U7XsemH9>sWVa-dZLD-`{ZBmx!;LTYq$xYc zKbj9o2@wJ6QiTQuZX_bdal#jU1H=}##ETQiEMT2OZE_z?+g`-0>G=?OTdQ0*mjsJS z^0qH<%&j3}_AKXXq#7`@|H}?h`?aL5sBgJy!Fh1=+=i{Kn9=dy*t%O0=hD?@{@m-H zHt_D_^L1QLa=bIGXY+lA2lr_E_=VarOT$QWirmH)p{?+=ajJHEM~(XZI2?NI*uRy2 zf)TGymG}`=Ox+N{!tTE1mW6tYr#{Qa6gff+CC}$Q4Ua7R_>tbx7eU=iBOnddK}7xP zI&0znmOIzy%*S9WVPeqW>FBMY-R94rb#SiQ>&Vr)ilf3z#cj z?C5}bFH7zwuM>OzlJ0C%q=qj4asEl2G47?Kc#4>M3J0MbOQea?`ZfCt1oGL1IXx0Z z@BD+QhfaX(zzfMVVS=Bvy=8vaGxneRr#j!883GS>qhDseT|e!zcyg<@fWF9oj)BGP z6s1;oh5HdizM@jo)Yf0huhnXX^u>p{>CZip?Uv_bg2Cw_o~Z-)K=EUDgtC7u1-Ezw zm!jN}S04)_5b~?<{cK{!+Fg2IT{P}g$#)?PrFt}Gmq$1RET9GjC%k0$NAbf<8K&RB zrDu_*GIeP!L(kzfk=GbUqCB?3v(X9sH;x;s*`|NKYG4^rg94Y5;G3U2CsP;^ON11$ zzMYXn;Aly`SJ>ajPQ;mh7mgpMrq;zpiaSpR3SVijJHr}wg`8kX0xhVFw}yxMa6==y zSst1+zoQ4w*B;p%(WcO{luh8GrDYXx&;UjNkBbJ!hyP^`WF z+peBtQR}Q*{<~>PE4IOXk7P!C@IAGgDYLs&J_D)9-OT$_3(;eHf*DMq_j-FH85*-w z#Id2NS29y{4wc_6relxn-6}eZ9b?Gs)1A50%ySH68P<(~!7boUg{7ozGjqtDiW#;& z=?Z=fxOZQ!JtOWrxz0urSSTrOhca7vYIe+a=fMeVF3!?i&0@+91YV~*)o?h8Nd3NC zCoW}sagn&zpuAK4@Ft%v1CAH!N;_X4I{MPr&AZiSiCr~B@p9AS_YaJ4R4#F49V0p6 zHjQ=FBB^6~;3bj+<6dp5_Z&3u**t%&Lb6z$36iQ!r)sfwx4S<}xf8#__=dfXTAbXw zuxL>;Lw2?Pm6#&-?*_Bn6zr;{)r5>p**y*DR>JF^-1v2BEGoWCb%i|sj+_w+pX$+f zGq9j2|G?F#q&A!4Er2kM;#F+KYkU&jaW)R#?mBVsuI?j7OELD41D$%RKFF9J&sNIs zR3hdk^X48}XYyuqnv8X+ir;?vWw2~Q*cnqpYhA{mWX=*>RvYA&-)U5Gr2WC2jM8rG&5_?nfMi<#LuPV=Fkjdoe!NHwl`Bl_L9 z#VMAPqCSba)H#JX{w3VmpW+0JFt$I{NiaGeHYX)fY2@VPRt^Ys;CA zl7y?|j;lo=V|MC1GR|kp0P(~yUTIKjH=zkzYmk3mWBQb_`Y8RGc|VmlpqG40-ymn} zFFKsXt6c-l0{XCWXIs;Y1&WBiN~x_dW8c#^fNy#ud7bY3c6s*3nSBCk!;f(!Ef^Xb z5=IJNfaD^*dB>lTKkt4OULLe;IVCM+N@WQCVfI=6MkwBGfxa!^W5GS0H}1?aU0lu@ ztDEO_M%EOHJ7<<8b2GnMr*-=6Qk9$frwx{`LI`T4WdW=Y)xHSbo5C7-vM*+}h}p|q z1VllP#*Hv5uFw!0xrj9OqKMjUlKSt^NS%EthhMek%mHew=~J{BTjR7D(kD1Frl1H) zx7+{xK7x|P1ZiDxYJZvY8et0YgZdif!*~^wf3xLEd{ed|(PS=1UoLK=XQf9q^zz~| z(|E0CxJP8A(XP34{H?1-RLLuaPl~PWM-B9lyf3BXMoS zZD>X9`DAfLzU6P=p$gO2WTjzOp=RaEolkPj!VzAhw*~{EvtBcI|a*u%~==bJ3f$kEx5w#jOCwE_IH9u>H1q$LBFHNvS217roNB?POox8?dOgBT!! zdg|Rdo*It<)q2M1l2e8{2lsT=@rq5?+c387r(s9pnRC;%>mmzg2GT0%KI%TIdER4Q!`jAC*Gadr zg>y5@W<~YH>BPw@vqx^Wr6rS%w2I+j@Xf#~OyjJ7qda#3sfzDSkSw&$g0(ViSG2hQ^s_IykLG#oq>+*TI3FV`CEu;Zn0ZvPg$P^d zYr;;o5eHrSA2*hgF%2%1FsssUSD}j~^Gm3OSR{qYH5F-#mNGVk76Q2Qc~2A>4mUI3 z@_2m=4)QxcHeNt%Tlh{%)PsS(rna=0Up+mMloGjj$rMAZ$Zr3i^f02u<2E)a<}*CYcVh z7rq-Pok4h_tDWS*Sp35^CM{kZtRr}Ux8`|6vZmofeCK(iwWj2QwOWz(B2IX%yE;SA z49Ct9yI91pp5-sY=tjk_cbN48t^^Qf*y`vDGDEkLd`XPW>qS<}=mEx}){ z5WesiM#H!NbIs%BF(6u`-w0B?5{XRdr_)5To!^)jc*EF>U7V#}W;mR`fzFS%ie;aX zqZ5e=|M8*{2KG|$M@fwmQ+G8_Xx{JHth!dqQ^_6_`o+% zb?jCAAZ?dJU;Y04Z{PILH?j@ob%(x$eAHqe_0YYv4a=c4@+|y4N!|Yh)a0I#5pFgF zq?X~O%_&r_m*oX0 z$RDRhyJBQQ5+$+u0jEZ!1*icY0iys)Mt%_VFl-JouaxX=dmp(YR3wyNX-7aRWNja~ zwy#o|AEddp21zt|p zoOW}qW{Xjugr0=N&2sqAEdE%7lg~F|*JFkL0CQp!cn$a^maj@LOXJ=l-z|b)Ge0?s zKB_){EBem(qN?dN>HXZ)HD(a4>fL1cvBH0u8h?!Wo(m6-_++TC0dM-^0D4V(L%saA zeM!{7Mqs#K9)rG63B^x}MXx2Fl#1??zDR&Bo8HK_oAnz7pZEXHSnB%Zm>ENBsuG=7 zNH?V0TmI*deP3h0;3TyTS`5?VZbS$EdVYZzt4p@<&J|sx*U~5MU~RivF+`%v-$h-+ zU&KFp>w5c~b_{O%bS|5o^OfJPYVAw)Hi6`+K~DzaF>9mtZoth^jEmq;temIWCyAmP zKqNO!ZiV1USw#ixvI?6Dadzdt3Z#odv$B6j0pgmn9ss8(bV4P=vOG=@t#E)wx*6y9 zaD{NP_$`e@zMsN4O*(OqX<4xVi#<_AXi^1XxhRN3HM;zt0Q(a17-e)uMM}l5!#<9s znO!1FH19-&*6wrvN)i<@NhMRC1La0Se8HT`jsc*IOHgkoH<_AO8R?SxqjER3$fIg^ zyd&8%p4xlmm$-pHq5l$WML?Tp0AUnJXek7qUl~P+8?Ss1-lLvS;Orce4HNS_O>n!m zPK>(I68_6*g#$c`ZgeS-z!?TSeQp}uE3yqa&dP>j@Ktmj>>ZjBf_<&<{KIFLZtE=Q zT;PyLj4z7O6j-m^h)5vGsmBKch78#e8=1U_ z^ZS4uKwnjSP-Rze0TxfOp+97)uPPCC)#>LlV`Xvt|J>0q>s)!XDjilrrj+tEo0BT1 zf(rrFlc_WX>o5Kh=TaX6x4_t-Y#OAg2wSk6V**A`juM#xAtwsplGTxrqM1?_E1@rA zdbfnTJbZJ@A_in3YZYvL(3I~ft5r((lRy^s7w1)$YZCI$jDMi3>?iU3phXBZ9`4g^ zf0=-+tQlFeq4R6!un+H2D#0h$H;QJ6neV{_`^fn;Ga)k})O+G)*pj~KEU*B*qYu*J z>|O21IIQdoah_Ek4)SJ+88X0p`*M1ecPXda_fekgv!(I$y)BXK?9S|T=Ny*F^bq13 zhij2nGoD6_JKqyuZJ$1mZ+CFna0&@rGunrDarfwoIVV#>6S17J-=BLq{RFDSvc=*V z>X@5Z)d}eTyI@p(;}x?-X2>O-aCstsz}bdEx1}c_+m`&?J$|QNu8I?-L-7nndO#j8 zd{eNj09Sw|E#8VoDH)+<&9$A<8T{8-Q=eegy0L2)Oh6j=6-tk)BVC@4k&hA1!_1nH5kilmgE(F`X9CZ{%}QwCKNCNY zoKJfeIH!_d>Hk?oJd59rS9tF(x__&HZ9C`6dvNJ4y4Fo#@N5u##W-+13h(ue;t~np zAPnDtih1CA7=F_*m}It$o3tJ!hZJ#$cviig!|3QwR5HoP1Qb4P7(Oi(^B-A5Z|&4; zNah)1&QX67NCT&hld}4$+p!7{ zXQC2186~eLsN0DO51IZGERxp{NgvSH=Mrl_JtK00{C=Q2VRpl3N<^A7v6c2hahO4J zFhGoaQdv`W3)c37x#OHE;~o_2qBsIdwU~2c;c|S#Hs(6(s{5bR`oIv@R(Y3b3InnF zT2NM*F3W2DB~T8vp&v%Om(Fk4>?G#zEaEHko_Vh*bp(HRGC{f=gQkkOHeq0=JdkuA zNT;m>jvY$fo8kIXY6C8%k*uu?%Lhg~M-=!i)eV-OU;JeL#~QtJT2B}l?)xKs)KVuz zIau&yv9?a%eczMImwhXVL*oTocB?+Dx?m(TIuy8hJ-H{b%)&Ylni8@F22q zlA8Vthp1H}g4$6g-B^<@-N@UHX?Gna-J41GZvKPEfT&frgU5}&3zu=K^M9UWtv%ua zy%zL=sRixkF-cnCte~)z0-O&U|FcSn#n$2qa-AZIQRI2jFVw%U^#hmgso!T{R${Sq zgz+lqXRuBLc2t~Uu5Tzi`hhwRp}n!ENPd0}5L^9*@LNd3^1)=Vl;}v5_81EU^q~~l zk;BEHSV-D%C|dlWN~3-h!+w;Sp={k>BM_glaB^k8YGCE+hMV^_5d-O@hr0EsDEs}e z(t-?+=g6k^TtN}zhRivA*mdEI>O-u&VLW}mELl>+P3RS5rqEe-d!=|0F2Arjg$SKO z=%Zz3iBe(|5kC9WE&Dx^42C0vc3)5MmjA!gIoI)ehS&+?U7z4Qm zMgBugXBe}%2H}s9h5jr5*O$aK$oT(7BAYSFIrV`taW(~(G2{mXfxn&vjGsL0o?Ee$ zi*bQ;5x$1lO2DQ%d+4TO%TKkEN#_@yi5L)C>fjlsM@SdswK`YIhhr8ooLfN_yjw#S z@-x#bJ{#-Bp`uayUwZ%dChrWz!^S%e!ryvH42nLla<6i2wPR}bk20^61HE)W(X`k@ zv8Ac1I3%|q=!&?^LrTeH4d%$uF&{^=pX+zDmX@l+#mY#bglUiVH_wF-M zyFmOkWItSdWlH=d+;hw|L{bygrEOI3NdO7x2Jy1sI$(QO`6Ni`3a0c8b7}(46sC!U z6Vg|O&7Rjj%Mw}^TK4aq(k@j5(g*TL^0$#+fSDF+{tqU7JqLX~mA;{hz#y3Z{)#~| ztJPqBRB!2k*x|$$tiFkXsfjm6+KZ{Gsg^-ka!~i4X?1#L@jBMkzrWznf5R+rl@>s2 zAabvP;pgSJz8+hDPl=#mn=0A6?YnJVVEU7E9pqpqX1da&Av?~j^@IWYa^!l_urY=2(ywyMhZz|(WS_Cd0wY{bfI-9iCtkJGtIyxovLfV76o{U}+ifU!F z-wa`FrHyupnh_cXYLZVB=%dE z@-$}uH05zwc4i|vV#=aQT)0z$iGUl?H{;5uTEed+&6|7#?Thfc0DbyFR=?lyW z^bYWZP3R4PX@)}54928~#XJ8-|A028r^-NahzTk{1{J8uxA>L&1!eaj#w`8gQZ%zK zY6V#XVU@UJ(-qZBCAZT6(FP?;+3AXCrjln;$DWIc$5bBdN`(TJVU^x+e()VB{QmCmPqZiXXB6(*SX~LSkuo`!O`@)Z zbN9>Lz7+accDX;>QULQ?kmR=@Me$L_GU!nk|6gfh!^d}JKP%3E2FVO_yJU5Y4ck{h zA1g1XD*>p6B?5ZO7qJbHODjl@l5gZ3g zod2-nTs$~>{(u=QH|#HmE#SrT*BIsw%I*gd`Ql7|(DW0We-q)v+t}+gB6qar~~tZTy|7kz$y#oT{PfXQ}~}Zen4o(VYFB^^QJiPnX%Q>UXTk zJ<)s|pfSwcSaHRB%nJ)Xm^n~h^%(GoV4m*Sv`5LDFlJBQyL5Ig5^F7G}D}c0=4szLu19;CJB9AGy|aqx-nna$#N5xv43AyLNTs zVRJ@ngL8Nkd*(ds?dTQUZzpAA#|~C(T1p^1*W~^??JN&x5srGnn5G^9dp}q0OxsrN zLZmITdeyhceeQ%_lK2NN!M1~FOTZI-c~R(5-qLtwzJ$^;ny4H*ywrv(qFj+ zj)Qa7PpYw-1vdd^rP*NPl$;Qd--=)8P~E7s55K!niLZE&i9g>T$kn=0di^N5ex1Br zShNo!cOy#tgUF=-0wb!=jxV&wxtp`+@8G|F@NUVXvB*y^0GE~Av)Mjgj#HE+CA-zl zAHdq@LB5jMAJYeKoG!~$4+!Taehd5xXr>7|X%Z_a*<{?g%;_AihC6HN1V(12Q7-9B zrp!jtNIIAu&|mTTQD;;5ENM)x@H(U #IK^-IYf2l&U)e1Zpp2h;%8Kdcb-l%bT0 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�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%0AmcBAo+gN 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%0D_S}66b)Pj~mExsRyi|&pN|~uryd?ex{TYD1 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 diff --git a/libs/freetdm/docs/async.txt b/libs/freetdm/docs/async.txt deleted file mode 100644 index c5d706ecba..0000000000 --- a/libs/freetdm/docs/async.txt +++ /dev/null @@ -1,15 +0,0 @@ -APIs that result in an event when the API returns FTDM_SUCCESS - -ftdm_channel_call_answer() -ftdm_channel_call_indicate() -ftdm_channel_call_transfer() - FTDM_SIGEVENT_INDICATION_COMPLETED - *note that FTDM_SIGEVENT_INDICATION_COMPLETED has associated data to indicate the result of the indication - *note this event is only delivered on non-blocking channels - -ftdm_call_place - FTDM_SIGEVENT_DIALING - -ftdm_channel_call_hangup - FTDM_SIGEVENT_RELEASED - diff --git a/libs/freetdm/docs/ftdm-open-issues.txt b/libs/freetdm/docs/ftdm-open-issues.txt deleted file mode 100644 index 8088c85bd0..0000000000 --- a/libs/freetdm/docs/ftdm-open-issues.txt +++ /dev/null @@ -1,76 +0,0 @@ -== This is an email sent to stkn responding to his post http://stkn.techmage.de/archives/200 == - -1. FreeTDM open channels immediately. - -Yes, this seems to come from the early days of Freetdm where probably the analog modules were implemented first and was dragged incorrectly to ISDN. -The open API also sets the flag in use so others cannot use it. We should decouple this open and reserve operations. Does not seem very hard to do, -I'll take a look at it on my way back to Toronto this week or earlier if possible, I'll create a git branch for it and send you the url for peer review. -Feel free to do the opposite if you are in a hurry. - -2. FreeTDM does not completely close the channel on hangup. - -As long as the signaling module calls ftdm_channel_close() the fio->close API will be called where the IO module is responsible -for turning off ec or any other operations to leave the channel unused/idle (not really closed). There was indeed a bug where ftdm_zt module -was not properly closing the channel, if that is what you mean, then it means that was already fixed by you with your audio mode turn off patch. - -Now, a more lengthy response ... - -When we, Sangoma, took over freetdm and renamed it to freetdm, it was not just a name change, many API cleanups were done so API users cannot access - -the internal data structures and cannot explicitly move between channel states. Also, some order on the state transitions has been put into place. - -We've tried to keep backwards compatibility though, so old modules may not follow all of the conventions. Some unwritten conventions are: - -1. Signaling modules are responsible for calling ftdm_channel_close() when done with the channel. In fact, signaling modules should not - call ftdm_channel_done unless they really know what they're doing. ftdm_channel_close will call ftdm_channel_done anyways. - -2. When remote end hangs up a call, signaling module should go to TERMINATING state and send SIGEVENT_STOP to the user. The signaling stack - should not acknowledge the hangup until the user implicitly moves us to HANGUP (via ftdm_channel_call_hangup()). There is a core timer - that will ensure we move from TERMINATING to HANGUP if the user does not moves us fast enough (arbitrarely 3000ms), although that is considered - a bug in the user application (at some point we saw that in FreeSWITCH) and we complain loudly when that happens. - -3. Signaling modules should leave the channel with NO pending states once they unlock it. This means, whenever you have a message to process - you must lock the channel, check its current state (the user may have already changed the state to something else), process any pending - state set by the user, then process your message and if required move the channel to a new state and process that state before releasing the lock. - There is a chance of a deadlock due to the callbacks we use to notify users of messages if we call those callbacks with the channel lock held and - that is why new signaling modules should use the FTDM_SPAN_USE_SIGNALS_QUEUE to defer the notification to the user when the ftdm_channel_t is not - locked calling ftdm_span_trigger_signals() at the end of their processing loop which delivers the callback notifications to users. - -Having said that, there is a major architectural change coming, probably early 2011, and I'd like to have your input. - -== Decoupling calls from IO channels == - -We've also found that the concept of a channel and a call are unnecesarily coupled together in FreeTDM. I've never asked Anthony the reasoning -for this, but it seems the API was meant to be used with, or without calls. That is, a user should be able to just 'open' a channel and start -reading and writing raw data without ever launching one of the provided signaling stacks on top, may be just because the user is using their -own signaling stack and just needs freetdm as an I/O API. In fact, signaling modules work like this (but there are defects there). -The problem is, as you have noticed, the way ftdm_channel_open_xx APIs has been implemented is abusing this concept. - -Problems with current implementation. - -1. Exclusive channel is the only way we can request channels to the ISDN network. There is no room to change the channel later on easily. -2. Multi-rate calls cannot be done. We need to associate multiple B-channels to a single call. -3. Low-bit-rate calls (not sure what is the proper name for them) where a single B-channel can feed media to multiple calls with a low bit-rate - codec (I know of at least one request from a big company for this to support some Q.SIG stuff for Eurocontrol). - - -What do we need? - -I think there should be only one open() API that wraps calls around fio->open(), the other current open_xx functions that do hunting, should -be eliminated and some extra arguments provided to ftdm_channel_call_place to provide information about the channel where we would like to -place the call or group hunting information and the API would return immediately providing a ftdm_call_t reference pointer that can be used -to further track the status of that call, or in the case where a channel exclusivity was requested and we know for a fact is not available, -just return failure. At that point there is no I/O channel involved yet. Eventually after the signaling stack hunts the channel and -negotiaties its availability with the network, an I/O channel can be attached to that call, or even attach multiple channels (for the case -of multi rate calls?). - -This involves heavy changes. The state machine should be moved out of the ftdm_channel_t structure along with probably some other members -and stuffed into a new ftdm_call_t structure. Signaling modules would have to be updated to run their state machines with this call -structure and then at some point attach IO channels to the call. There would be 2 type of read/write APIs, one low level ftdm_channel_read -which receives an ftdm_channel_t as parameter and an ftdm_call_read() which receives an ftdm_call_t as parameter, for the case of multi-rate -calls or low-bit-rate multiplexed calls in the same B-channel this API would return just the media corresponding to that call already -demultiplexed or concatenated, or whatever needs to be done with the media from the multiple low-level IO channels. - -This is fairly disruptive, but I believe should be done sooner or later. - - diff --git a/libs/freetdm/docs/glare.txt b/libs/freetdm/docs/glare.txt deleted file mode 100644 index 0753db817f..0000000000 --- a/libs/freetdm/docs/glare.txt +++ /dev/null @@ -1,25 +0,0 @@ -Glare is a PITA. - -Although configuration of ISDN links can be done to minimize glare, we also must have a clear policy -on how the FreeTDM API is supposed to behave on glare across signaling modules. - -There is a well-known race in the FreeTDM API since the beginning. When a user wants to place a call with -the old APIs: - -1. ftdm_channel_open_xx (to hunt the channel by group, span or select a channel individually) -2. ftdm_channel_call_place() to place the actual call. - -Since the user has no access to channel locking, between opening a channel and placing a call, an incoming call could be -received. Therefore things can get complicated and that is why you should STOP USING those 2 deprecated functions. - -The replacement is ftdm_call_place(). - -ftdm_call_place receives the information required to hunt the channel and place the call. - -If glare is detected after placing the call and the signaling stack decides to drop the local call, a regular -SIGEVENT_STOP will be sent with the hangup cause FTDM_CAUSE_REQUESTED_CHAN_UNAVAIL. - -ftdm_call_place may return FTDM_BREAK if glare is detected while placing the call, in such cases you can try -calling ftdm_call_place again to hunt another channel. - - diff --git a/libs/freetdm/docs/io_modules.txt b/libs/freetdm/docs/io_modules.txt deleted file mode 100644 index a164bbb249..0000000000 --- a/libs/freetdm/docs/io_modules.txt +++ /dev/null @@ -1,13 +0,0 @@ -Last Updated: Jan 19, 2011 - -== BACKGROUND == - -The IO module provides an abstracted IO interface to FreeTDM. - -== SHUTDOWN == -Upon global shutdown, for each channel FIO_CLOSE_FUNCTION will be called. -When FIO_CLOSE_FUNCTION is called, all waiters on this channel shall be signalled. -If FIO_WAIT_FUNCTION is called on a function that has already been closed, this function shall return FTDM_TIMEOUT without blocking. -FIO_CHANNEL_DESTROY will eventually be called, and IO module is responsible for clearing all internal states and free allocated memory upon channel destroy. - - diff --git a/libs/freetdm/docs/locking.txt b/libs/freetdm/docs/locking.txt deleted file mode 100644 index 851d045b41..0000000000 --- a/libs/freetdm/docs/locking.txt +++ /dev/null @@ -1,125 +0,0 @@ -Last Updated: Fri 30 Dec, 2010 - -== Background == - -FreeTDM is a threaded library. As such, locking considerations must be taken when using it and when writing code inside the library. - -At the moment locks are not exposed to users. This means API users cannot acquire a lock on a channel or span structure. There is no -need for users to lock channels or spans since all their interactions with those structures should be done thru the FreeTDM API which -can (and in most cases must) internally lock on their behalf. - -Internally, locking can be done either by the core or the signaling modules. To better understand the locking considerations we must -understand first the threading model of FreeTDM. - -== Threading Model == - -At startup, when the user calls ftdm_global_init(), just one timing thread is created to dispatch internal timers. If you write -a signaling module or any other code using the scheduling API, you can choose to run your schedule in this timing thread or in -a thread of your choice. This is the only thread launched at initialization. - -If the application decides to use ftdm_global_configuration(), which reads freetdm.conf to create the spans and channels data -structures, then possibly another thread will be launched for CPU usage monitoring (only if enabled in the configuration cpu_monitor=yes -This thread sole purpose is to check the CPU and raise an alarm if reaches a configurable threshold, the alarm then is checked to avoid -placing or receiving further calls. - -At this point FreeTDM has initialized and configured its channels input output configuration. - -The user is then supposed to configure the signaling via ftdm_configure_span_signaling() and then start the signaling work -using ftdm_span_start(). This will typically launch at least 1 thread per span. Some signaling modules (actually just the analog one) -launches another thread per channel when receiving a call. The rest of the signaling modules currently launch only one thread per -span and the signaling for all channels within the span is handled in that thread. We call that thread 'the signaling thread'. - -At this point the user can start placing calls using the FreeTDM call API ftdm_channel_call_place(). Any of the possible threads in -which the user calls the FreeTDM API is called 'the user thread', depending on the application thread model (the application using FreeTDM) -this user thread may be different each time or the same all the time, we cannot make any assumptions. In the case of FreeSWITCH, the most -common user of FreeTDM, the user thread is most of the cases a thread for each new call leg. - -At this point we have identified 4 types of threads. - -1. The timing thread (the core thread that triggers timers). - Its responsibility is simply check for timers that were scheduled and trigger them when the time comes. This means that if you decide - to use the scheduling API in freerun mode (where you use the core timer thread) you callbacks will be executed in this global thread - and you MUST not block at all since there might be other events waiting. - -2. The CPU thread (we don't really care about this one as it does not interact with channels or spans). - -3. The signaling thread. - There is one thread of this per span. This thread takes care of reading signaling specific messages from the network (ISDN network, etc) and - changing the channel call state accordingly and processing state changes caused by user API calls (like ftdm_channel_call_hangup for example). - -4. The user thread. - This is a thread in which the user decides to execute FreeTDM APIs, in some cases it might even be the same than the signaling thread (because - most SIGEVENT notifications are delivered by the signaling thread, however we are advicing users to not use FreeTDM unsafe APIs from the - thread where they receive SIGEVENT notifications as some APIs may block for a few milliseconds, effectively blocking the whole signaling thread - that is servicing a span. - -== Application Locking == - -Users of the FreeTDM API will typically have locking of their own for their own application-specific data structures (in the case of FreeSWITCH, the -session lock for example). Other application-specific locks may be involved. - -== DeadLocks == - -As soon as we think of application locks, and we mix them with the FreeTDM internal locks, the possibility of deadlocks arise. - -A typical deadlock scenario when 2 locks are involved is: - -- User Thread - - Signaling Thread - -1. Application locks applock. 1. A network message is received for a channel. - -2. Aplication invokes a FreeTDM call API (ie: ftdm_channel_call_hangup()). 2. The involved channel is locked. - -3. The FreeTDM API attempts to acquire the channel lock and stalls because 3. The message processing results in a notification - the signaling thread just acquired it. to be delivered to the user via the callback function - provided for that purpose. The callback is then called. - -4. The thread is now deadlocked because the signaling thread will never 4. The application callback attempts to acquire its application - release the channel lock. lock but deadlocks because the user thread already has it. - -To avoid this signaling modules should not deliver signals to the user while holding the channel lock. An easy way to avoid this is -to not deliver signals while processing a state change, but rather defer them until the channel lock is released. Most new signaling modules -accomplish this by setting the span flag FTDM_SPAN_USE_SIGNALS_QUEUE, this flag tells the core to enqueue signals (ie FTDM_SIGEVENT_START) -when ftdm_span_send_signal() is called and not deliver them until ftdm_span_trigger_signals() is called, which is done by the signaling module -in its signaling thread when no channel lock is being held. - -== State changes while locking == - -Only 2 types of threads should be performing state changes. - -User threads. -The user thread is a random thread that was crated by the API user. We do not know what threading model users of FreeTDM will follow -and therefore cannot make assumptions about it. The user should be free to call FreeTDM APIs from any thread, except threads that -are under our control, like the signaling threads. Although it may work in most situations, is discouraged for users to try -to use FreeTDM APIs from the signaling thread, that is, the thread where the signaling callback provided during configuration -is called (the callback where FTDM_SIGEVENT_XXX signals are delivered). - -A user thread may request state changes implicitly through calls to FreeTDM API's. The idea of state changes is internal to freetdm -and should not be exposed to users of the API (except for debugging purposes, like the ftdm_channel_get_state, ftdm_channel_get_state_str etc) - -This is an example of the API's that implicitly request a state change. - -ftdm_channel_call_answer() - -Signaling modules should guarantee that upon releasing a lock on a channel, any state changes will be already processed and -not deferred to other threads, otherwise that leads to a situation where a state change requested by the signaling module is pending -to be serviced by another signaling module thread but a user thread wins the channel lock and attempts to perform a state change which will -fail because another state change is pending (and user threads are not meant to process signaling states). - -ONLY one signaling thread per channel should try to perform state changes and processing of the states, -otherwise complexity arises and is not worth it! - -At some point before we stablished this policies we could have 3 different threads doing state changes. - -1. A user random thread could implcitly try to change the state in response to a call API. -2. The ftmod signaling thread could try to change the state in response to other state changes. -3. The lower level signaling stack threads could try to change the state in response to stack events. - -As a result, lower level signaling stack thread could set a state and then let the signaling thread to -process it, but when unlocking the channel, the user thread may win the lock over the signaling thread and -may try to set a state change of its own and fail (due to the unprocessed state change)! - -The rule is, the signaling module should never unlock a channel with states pending to process this way the user, -when acquiring a channel lock (inside ftdm_channel_call_answer for example) it will always find a consistent state -for the channel and not in the middle of state processing. - - diff --git a/libs/freetdm/docs/sigstatus.txt b/libs/freetdm/docs/sigstatus.txt deleted file mode 100644 index 10561bfb5b..0000000000 --- a/libs/freetdm/docs/sigstatus.txt +++ /dev/null @@ -1,59 +0,0 @@ -FreeTDM can both notify and set signaling status changes in the different protocols thru a unified interface. More -specific details on the C data types and function prototypes are found in freetdm.h - -The API provides the following functions and data types to do it: - -The signaling status in any channel/span is represented thru ftdm_signaling_status_t - - /* The signaling link is down (no d-chans up in the span/group, MFC-R2 bit pattern unidentified) */ - FTDM_SIG_STATE_DOWN, - /* The signaling link is suspended (MFC-R2 bit pattern blocked, PRI maintenance, ss7 blocked?) */ - FTDM_SIG_STATE_SUSPENDED, - /* The signaling link is ready and calls can be placed (ie: d-chan up, MFC-R2 both rx and tx in IDLE) */ - FTDM_SIG_STATE_UP, - /* Invalid status */ - FTDM_SIG_STATE_INVALID - -Changes in the signaling status are notified to the user using the standard callback notification function provided -during configuration using the sigevent type FTDM_SIGEVENT_SIGSTATUS_CHANGED which is sent when the line status changes. - -On startup the signalling status default is FTDM_SIG_STATE_DOWN, and no notification is provided until the state change, -so applications must assume the status is down unless told otherwise. - -When ftdm_span_start is called, the signaling stack takes care of attempting to bring the status to UP -but it will ultimately depend on the other side too. - -== Setting the signaling status == - -Users can set the signaling status on a given channel/span thru FreeTDM the following API functions: - -ftdm_channel_set_sig_status -ftdm_span_set_sig_status - -If the user calls ftdm_channel_set_sig_status(chan, FTDM_SIG_STATE_SUSPENDED), the signaling stack will try to set -the status of the line to the one requested, if successful, it will result in a SIGEVENT_SIGSTATUS_CHANGED notification -being sent with status FTDM_SIG_STATE_SUSPENDED. - -** MFC-R2 Signaling Notes ** -For MFC-R2, calling ftdm_span_start() results in setting the tx CAS bits to IDLE. However, if the rx bits are in BLOCKED state -the signaling status will be reported as SUSPENDED. - -If the user calls ftdm_channel_set_sig_status(chan, SUSPENDED), the tx CAS bits will be set to BLOCKED and, if, the current rx bits -are IDLE then a SIGEVENT_SIGSTATUS_CHANGED with state SUSPENDED will be sent. If the rx bits are already in blocked then no further -SIGEVENT_SIGSTATUS_CHANGED notification is needed (because it was already sent when the rx bits were initially detected as BLOCKED). - -If the user calls ftdm_channel_set_sig_status(chan, UP), the tx CAS bits will be set to IDLE and, if, the current rx bits -are IDLE, then SIGEVENT_SIGSTATUS_CHANGED with state UP will be sent. If the rx bits are BLOCKED, then no notification is -sent at all until the rx bits change. - -Bottom line is, for MFC-R2, SIGEVENT_SIGSTATUS_CHANGED UP is only sent to the user when both the rx and tx bits are in IDLE, and -SIGEVENT_SIGSTATUS_CHANGED SUSPENDED is only sent to the user when any of the rx or tx bits are in BLOCKED. - -== Getting the signaling status == -Users can get the signaling status on a given channel/span thru FreeTDM the following API functions: - -ftdm_channel_get_sig_status -ftdm_span_get_sig_status - -The line status returned should be the same as the last time a SIGEVENT_SIGSTATUS_CHANGED was reported. - diff --git a/libs/freetdm/docs/ss7-native-bridge.txt b/libs/freetdm/docs/ss7-native-bridge.txt deleted file mode 100644 index d44b067b0a..0000000000 --- a/libs/freetdm/docs/ss7-native-bridge.txt +++ /dev/null @@ -1,43 +0,0 @@ -SS7 Native Bridge - -Native bridge is enabled on 2 conditions: - -* The SIP header FreeTDM-TransUUID is set in the originating leg and matches a freetdm channel -* The variable freetdm_native_sigbridge is true and the originating leg is also a freetdm channel - -Some coding rules apply to this feature: - -- Each channel is responsible for clearning its own peer_data and event queue - at the end of the call (when moving to DOWN state) - -- Each channel dequeues messages only from its own queue and enqueues messages - in the peer's queue, with the only exception being messages received before - the bridge is stablished (IAM for sure and possible SAM messages) because - if the bridge is not yet stablished the messages must be queued by the channel - in its own queue temporarily until the bridge is ready - -- When the bridge is ready it is the responsibility of the incoming channel to - move the messages that stored temporarily in its own queue to the bridged peer queue - -- During hangup, each channel is responsible for moving itself to DOWN. The procedure - however differs slightly depending on the hangup conditions - - If the user requests hangup (ie, FreeSWITCH) the request will be noted by setting the - FTDM_CHANNEL_USER_HANGUP flag but will not be processed yet because call control is - driven only by the link messages (so no hangup from ESL or command line allowed) - - When REL message comes, the channel receiving it must move to TERMINATING state and: - - - If the user has not hangup yet (FTDM_CHANNEL_USER_HANGUP flag not set) then - notify the user via SIGEVENT_STOP and wait for the user to move to HANGUP - state by calling ftdm_channel_call_hangup() before sending RLC - - - If the user did hangup already (FTDM_CHANNEL_USER_HANGUP flag is set) then - skip user notification and move to HANGUP state directly where the RLC message - will be sent - -- On HANGUP state the RLC is sent and the channel is moved to DOWN, final state - The peer channel will forward the REL message and wait for RLC from the network, when - RLC is received the channel can move straight to DOWN itself because the peer channel - is completing its own shutdown procedure when it received the REL message - diff --git a/libs/freetdm/docs/variables.txt b/libs/freetdm/docs/variables.txt deleted file mode 100644 index cb518e14d8..0000000000 --- a/libs/freetdm/docs/variables.txt +++ /dev/null @@ -1,122 +0,0 @@ -Using FreeTDM Variables - -1. User application sending variables or raw buffer to FreeTDM -============================================================== - -The User can include a ftdm_usrmsg_t before sending an event to freetdm. - -example #1a - Making an outbound call: --------------------------------------- - -To make an outbound call: - ftdm_usrmsg_t usrmsg; - memset(&usrmsg, 0, sizeof(usrmsg)); - - /* Attach variable to usrmsg */ - ftdm_usrmsg_add_var(&usrmsg, "isdn.prog_ind.descr", "inband-info-available"); - - ftdm_channel_call_place_ex(ftdmchan, &usrmsg); - -example #1b - Adding a variable: --------------------------------- -When using ftmod_sangoma_isdn, user want to specify progress indicator inside PROCEED message. - - - ftdm_usrmsg_t usrmsg; - memset(&usrmsg, 0, sizeof(usrmsg)); - - /* Attach variable to usrmsg */ - ftdm_usrmsg_add_var(&usrmsg, "isdn.prog_ind.descr", "inband-info-available"); - - /* Request FreeTDM to send a PROCEED msg */ - ftdm_channel_call_indicate_ex(ftdmchan, FTDM_CHANNEL_INDICATE_PROCEED, &usrmsg); - - -example #2 - Setting raw data: --------------------------------------------------------- - -When using ftmod_sangoma_isdn, user wants to transmit a custom Facility IE, inside a FACILITY message. - - ftdm_usrmsg_t usrmsg; - - uint8_t *my_facility_ie = ftdm_calloc(1, 200); /*memory has to be allocated using ftdm_calloc !! */ - unsigned my_facility_ie_len = 0; - - memset(&usrmsg, 0, sizeof(usrmsg)); - - /* Fill my_facility_ie with custom data here */ - my_facility_ie[my_facility_ie_len++] = 0x1C; /* Q.931 Facility IE ID */ - my_facility_ie[my_facility_ie_len++] = 0x03; /* Length of facility IE */ - my_facility_ie[my_facility_ie_len++] = 0x01; - my_facility_ie[my_facility_ie_len++] = 0x02; - my_facility_ie[my_facility_ie_len++] = 0x03; - - ftdm_usrmsg_set_raw_data(&usrmsg, my_facility_ie, my_facility_ie_len); - - ftdm_channel_call_indicate_ex(ftdmchan, FTDM_CHANNEL_INDICATE_FACILITY, &usrmsg); - - /* FreeTDM will automatically free my_facility_ie */ - - -2. User application receiving variables and raw buffer from FreeTDM -================================================================== - -example #1 - print all variables received from FreeTDM ------------------------------------------------------- - - /* Inside event call-back function */ - ftdm_iterator_t *iter = NULL; - ftdm_iterator_t *curr = NULL; - const char *var_name = NULL; - const char *var_value = NULL; - - /* Read all variables attached to this event */ - iter = ftdm_sigmsg_get_var_iterator(sigmsg, iter); - for (curr = iter ; curr; curr = ftdm_iterator_next(curr)) { - ftdm_get_current_var(curr, &var_name, &var_value); - fprintf("Call Variable: %s=%s\n", var_name, var_value); - } - ftdm_iterator_free(iter); - - -example #2 - accessing a specific variable ------------------------------------------- - - /* Inside event call-back function */ - char *string = NULL; - string = ftdm_sigmsg_get_var(sigmsg, "isdn.prog_ind.descr"); - if (string && *string) { - fprintf("Progress indicator:%s\n", string); - } - - -example #3a - accessing raw data -------------------------------- - - /* Inside event call-back function */ - ftdm_size_t len; - uint8_t *mydata; - if (ftdm_sigmsg_get_raw_data(sigmsg, (void**)&mydata, &len) == FTDM_SUCCESS) { - /* raw data is available, do something with mydata here */ - } - /* Once this function returns, raw data will be free'd inside FreeTDM */ - - -example #3b - accessing raw data -------------------------------- - - /* Inside event call-back function */ - ftdm_size_t len; - uint8_t *mydata; - if (ftdm_sigmsg_get_raw_data_detached(sigmsg, (void**)&mydata, &len) == FTDM_SUCCESS) { - /* raw data is available, do something with mydata here */ - - } - - : - : - : - - /* User owns raw data and is responsible for free'ing it*/ - ftdm_safe_free(mydata); - diff --git a/libs/freetdm/freetdm.2008.sln b/libs/freetdm/freetdm.2008.sln deleted file mode 100644 index 4bf2c795a6..0000000000 --- a/libs/freetdm/freetdm.2008.sln +++ /dev/null @@ -1,155 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "freetdm", "msvc\freetdm.2008.vcproj", "{93B8812C-3EC4-4F78-8970-FFBFC99E167D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testanalog", "msvc\testanalog\testanalog.2008.vcproj", "{BB833648-BAFF-4BE2-94DB-F8BB043C588C}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testisdn", "msvc\testisdn\testisdn.2008.vcproj", "{6DA6FD42-641D-4147-92F5-3BC4AAA6589B}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_freetdm", "mod_freetdm\mod_freetdm.2008.vcproj", "{FE3540C5-3303-46E0-A69E-D92F775687F1}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_analog", "src\ftmod\ftmod_analog\ftmod_analog.2008.vcproj", "{37C94798-6E33-4B4F-8EE0-C72A7DC91157}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_analog_em", "src\ftmod\ftmod_analog_em\ftmod_analog_em.2008.vcproj", "{B3F49375-2834-4937-9D8C-4AC2EC911010}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_isdn", "src\ftmod\ftmod_isdn\ftmod_isdn.2008.vcproj", "{729344A5-D5E9-434D-8EE8-AF8C6C795D15}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_pika", "src\ftmod\ftmod_pika\ftmod_pika.2008.vcproj", "{E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_wanpipe", "src\ftmod\ftmod_wanpipe\ftmod_wanpipe.2008.vcproj", "{1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_sangoma_isdn", "src\ftmod\ftmod_sangoma_isdn\ftmod_sangoma_isdn.2008.vcproj", "{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_r2", "src\ftmod\ftmod_r2\ftmod_r2.2008.vcproj", "{08C3EA27-A51D-47F8-B47D-B189C649CF30}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|Win32.ActiveCfg = Debug|Win32 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|Win32.Build.0 = Debug|Win32 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|x64.ActiveCfg = Debug|x64 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|x64.Build.0 = Debug|x64 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|Win32.ActiveCfg = Release|Win32 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|Win32.Build.0 = Release|Win32 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|x64.ActiveCfg = Release|x64 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|x64.Build.0 = Release|x64 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|Win32.ActiveCfg = Debug|Win32 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|Win32.Build.0 = Debug|Win32 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|x64.ActiveCfg = Debug|x64 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|x64.Build.0 = Debug|x64 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|Win32.ActiveCfg = Release|Win32 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|Win32.Build.0 = Release|Win32 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|x64.ActiveCfg = Release|x64 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|x64.Build.0 = Release|x64 - {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|Win32.ActiveCfg = Debug|Win32 - {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|x64.ActiveCfg = Debug|x64 - {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|Win32.ActiveCfg = Release|Win32 - {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|x64.ActiveCfg = Release|x64 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.ActiveCfg = Debug|Win32 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.Build.0 = Debug|Win32 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|x64.ActiveCfg = Debug|x64 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|x64.Build.0 = Debug|x64 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|Win32.ActiveCfg = Release|Win32 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|Win32.Build.0 = Release|Win32 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|x64.ActiveCfg = Release|x64 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|x64.Build.0 = Release|x64 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|Win32.ActiveCfg = Debug|Win32 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|Win32.Build.0 = Debug|Win32 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|x64.ActiveCfg = Debug|x64 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|x64.Build.0 = Debug|x64 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|Win32.ActiveCfg = Release|Win32 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|Win32.Build.0 = Release|Win32 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|x64.ActiveCfg = Release|x64 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|x64.Build.0 = Release|x64 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|Win32.ActiveCfg = Debug|Win32 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|Win32.Build.0 = Debug|Win32 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|x64.ActiveCfg = Debug|x64 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|x64.Build.0 = Debug|x64 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|Win32.ActiveCfg = Release|Win32 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|Win32.Build.0 = Release|Win32 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|x64.ActiveCfg = Release|x64 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|x64.Build.0 = Release|x64 - {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|Win32.ActiveCfg = Debug|Win32 - {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|x64.ActiveCfg = Debug|x64 - {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|Win32.ActiveCfg = Release|Win32 - {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|x64.ActiveCfg = Release|x64 - {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Debug|Win32.ActiveCfg = Debug|Win32 - {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Debug|x64.ActiveCfg = Debug|x64 - {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Release|Win32.ActiveCfg = Release|Win32 - {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Release|x64.ActiveCfg = Release|x64 - {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|Win32.ActiveCfg = Debug|Win32 - {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|Win32.Build.0 = Debug|Win32 - {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|x64.ActiveCfg = Debug|x64 - {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|Win32.ActiveCfg = Release|Win32 - {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|x64.ActiveCfg = Release|x64 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|Win32.ActiveCfg = Debug|Win32 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|x64.ActiveCfg = Debug|x64 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|x64.Build.0 = Debug|x64 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|Win32.ActiveCfg = Release|Win32 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|Win32.Build.0 = Release|Win32 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|x64.ActiveCfg = Release|x64 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|x64.Build.0 = Release|x64 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|Win32.ActiveCfg = Debug|Win32 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|x64.ActiveCfg = Debug|x64 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|x64.Build.0 = Debug|x64 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|Win32.ActiveCfg = Release|Win32 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|Win32.Build.0 = Release|Win32 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|x64.ActiveCfg = Release|x64 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|x64.Build.0 = Release|x64 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|Win32.ActiveCfg = Debug|Win32 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|x64.ActiveCfg = Debug|x64 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|x64.Build.0 = Debug|x64 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|Win32.ActiveCfg = Release|Win32 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|Win32.Build.0 = Release|Win32 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.ActiveCfg = Release|x64 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.Build.0 = Release|x64 - {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.ActiveCfg = Debug|Win32 - {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|x64.ActiveCfg = Debug|Win32 - {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.ActiveCfg = Release|Win32 - {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.Build.0 = Release|Win32 - {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|x64.ActiveCfg = Release|Win32 - {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.ActiveCfg = Debug|Win32 - {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|x64.ActiveCfg = Debug|Win32 - {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|Win32.ActiveCfg = Release|Win32 - {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|x64.ActiveCfg = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/libs/freetdm/freetdm.2010.sln b/libs/freetdm/freetdm.2010.sln deleted file mode 100644 index b6259e5960..0000000000 --- a/libs/freetdm/freetdm.2010.sln +++ /dev/null @@ -1,127 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "freetdm", "msvc\freetdm.2010.vcxproj", "{93B8812C-3EC4-4F78-8970-FFBFC99E167D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testanalog", "msvc\testanalog\testanalog.2010.vcxproj", "{BB833648-BAFF-4BE2-94DB-F8BB043C588C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testisdn", "msvc\testisdn\testisdn.2010.vcxproj", "{6DA6FD42-641D-4147-92F5-3BC4AAA6589B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_freetdm", "mod_freetdm\mod_freetdm.2010.vcxproj", "{FE3540C5-3303-46E0-A69E-D92F775687F1}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_analog", "src\ftmod\ftmod_analog\ftmod_analog.2010.vcxproj", "{37C94798-6E33-4B4F-8EE0-C72A7DC91157}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_analog_em", "src\ftmod\ftmod_analog_em\ftmod_analog_em.2010.vcxproj", "{B3F49375-2834-4937-9D8C-4AC2EC911010}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_isdn", "src\ftmod\ftmod_isdn\ftmod_isdn.2010.vcxproj", "{729344A5-D5E9-434D-8EE8-AF8C6C795D15}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_pika", "src\ftmod\ftmod_pika\ftmod_pika.2010.vcxproj", "{E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_wanpipe", "src\ftmod\ftmod_wanpipe\ftmod_wanpipe.2010.vcxproj", "{1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_sangoma_isdn", "src\ftmod\ftmod_sangoma_isdn\ftmod_sangoma_isdn.2010.vcxproj", "{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_r2", "src\ftmod\ftmod_r2\ftmod_r2.2010.vcxproj", "{08C3EA27-A51D-47F8-B47D-B189C649CF30}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|Win32.ActiveCfg = Debug|Win32 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|Win32.Build.0 = Debug|Win32 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|x64.ActiveCfg = Debug|x64 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|x64.Build.0 = Debug|x64 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|Win32.ActiveCfg = Release|Win32 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|Win32.Build.0 = Release|Win32 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|x64.ActiveCfg = Release|x64 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|x64.Build.0 = Release|x64 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|Win32.ActiveCfg = Debug|Win32 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|Win32.Build.0 = Debug|Win32 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|x64.ActiveCfg = Debug|x64 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|x64.Build.0 = Debug|x64 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|Win32.ActiveCfg = Release|Win32 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|Win32.Build.0 = Release|Win32 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|x64.ActiveCfg = Release|x64 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|x64.Build.0 = Release|x64 - {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|Win32.ActiveCfg = Debug|Win32 - {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|x64.ActiveCfg = Debug|x64 - {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|Win32.ActiveCfg = Release|Win32 - {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|x64.ActiveCfg = Release|x64 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.ActiveCfg = Debug|Win32 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.Build.0 = Debug|Win32 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|x64.ActiveCfg = Debug|x64 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|x64.Build.0 = Debug|x64 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|Win32.ActiveCfg = Release|Win32 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|Win32.Build.0 = Release|Win32 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|x64.ActiveCfg = Release|x64 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|x64.Build.0 = Release|x64 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|Win32.ActiveCfg = Debug|Win32 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|Win32.Build.0 = Debug|Win32 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|x64.ActiveCfg = Debug|x64 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|x64.Build.0 = Debug|x64 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|Win32.ActiveCfg = Release|Win32 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|Win32.Build.0 = Release|Win32 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|x64.ActiveCfg = Release|x64 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|x64.Build.0 = Release|x64 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|Win32.ActiveCfg = Debug|Win32 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|Win32.Build.0 = Debug|Win32 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|x64.ActiveCfg = Debug|x64 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|x64.Build.0 = Debug|x64 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|Win32.ActiveCfg = Release|Win32 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|Win32.Build.0 = Release|Win32 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|x64.ActiveCfg = Release|x64 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|x64.Build.0 = Release|x64 - {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|Win32.ActiveCfg = Debug|Win32 - {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|x64.ActiveCfg = Debug|x64 - {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|Win32.ActiveCfg = Release|Win32 - {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|x64.ActiveCfg = Release|x64 - {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Debug|Win32.ActiveCfg = Debug|Win32 - {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Debug|x64.ActiveCfg = Debug|x64 - {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Release|Win32.ActiveCfg = Release|Win32 - {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Release|x64.ActiveCfg = Release|x64 - {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|Win32.ActiveCfg = Debug|Win32 - {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|Win32.Build.0 = Debug|Win32 - {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|x64.ActiveCfg = Debug|x64 - {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|Win32.ActiveCfg = Release|Win32 - {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|x64.ActiveCfg = Release|x64 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|Win32.ActiveCfg = Debug|Win32 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|Win32.Build.0 = Debug|Win32 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|x64.ActiveCfg = Debug|x64 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|x64.Build.0 = Debug|x64 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|Win32.ActiveCfg = Release|Win32 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|Win32.Build.0 = Release|Win32 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|x64.ActiveCfg = Release|x64 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|x64.Build.0 = Release|x64 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|Win32.ActiveCfg = Debug|Win32 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|Win32.Build.0 = Debug|Win32 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|x64.ActiveCfg = Debug|x64 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|x64.Build.0 = Debug|x64 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|Win32.ActiveCfg = Release|Win32 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|Win32.Build.0 = Release|Win32 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|x64.ActiveCfg = Release|x64 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|x64.Build.0 = Release|x64 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|Win32.ActiveCfg = Debug|Win32 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|Win32.Build.0 = Debug|Win32 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|x64.ActiveCfg = Debug|x64 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|x64.Build.0 = Debug|x64 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|Win32.ActiveCfg = Release|Win32 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|Win32.Build.0 = Release|Win32 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.ActiveCfg = Release|x64 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.Build.0 = Release|x64 - {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.ActiveCfg = Debug|Win32 - {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|x64.ActiveCfg = Debug|x64 - {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.ActiveCfg = Release|Win32 - {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|x64.ActiveCfg = Release|x64 - {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.ActiveCfg = Debug|Win32 - {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|x64.ActiveCfg = Debug|x64 - {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|Win32.ActiveCfg = Release|Win32 - {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|x64.ActiveCfg = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/libs/freetdm/freetdm.2012.sln b/libs/freetdm/freetdm.2012.sln deleted file mode 100644 index 1d4c335a8d..0000000000 --- a/libs/freetdm/freetdm.2012.sln +++ /dev/null @@ -1,127 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2012 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "freetdm", "msvc\freetdm.2012.vcxproj", "{93B8812C-3EC4-4F78-8970-FFBFC99E167D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testanalog", "msvc\testanalog\testanalog.2012.vcxproj", "{BB833648-BAFF-4BE2-94DB-F8BB043C588C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testisdn", "msvc\testisdn\testisdn.2012.vcxproj", "{6DA6FD42-641D-4147-92F5-3BC4AAA6589B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_freetdm", "mod_freetdm\mod_freetdm.2012.vcxproj", "{FE3540C5-3303-46E0-A69E-D92F775687F1}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_analog", "src\ftmod\ftmod_analog\ftmod_analog.2012.vcxproj", "{37C94798-6E33-4B4F-8EE0-C72A7DC91157}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_analog_em", "src\ftmod\ftmod_analog_em\ftmod_analog_em.2012.vcxproj", "{B3F49375-2834-4937-9D8C-4AC2EC911010}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_isdn", "src\ftmod\ftmod_isdn\ftmod_isdn.2012.vcxproj", "{729344A5-D5E9-434D-8EE8-AF8C6C795D15}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_pika", "src\ftmod\ftmod_pika\ftmod_pika.2012.vcxproj", "{E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_wanpipe", "src\ftmod\ftmod_wanpipe\ftmod_wanpipe.2012.vcxproj", "{1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_sangoma_isdn", "src\ftmod\ftmod_sangoma_isdn\ftmod_sangoma_isdn.2012.vcxproj", "{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_r2", "src\ftmod\ftmod_r2\ftmod_r2.2012.vcxproj", "{08C3EA27-A51D-47F8-B47D-B189C649CF30}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|Win32.ActiveCfg = Debug|Win32 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|Win32.Build.0 = Debug|Win32 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|x64.ActiveCfg = Debug|x64 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|x64.Build.0 = Debug|x64 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|Win32.ActiveCfg = Release|Win32 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|Win32.Build.0 = Release|Win32 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|x64.ActiveCfg = Release|x64 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|x64.Build.0 = Release|x64 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|Win32.ActiveCfg = Debug|Win32 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|Win32.Build.0 = Debug|Win32 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|x64.ActiveCfg = Debug|x64 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|x64.Build.0 = Debug|x64 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|Win32.ActiveCfg = Release|Win32 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|Win32.Build.0 = Release|Win32 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|x64.ActiveCfg = Release|x64 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|x64.Build.0 = Release|x64 - {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|Win32.ActiveCfg = Debug|Win32 - {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|x64.ActiveCfg = Debug|x64 - {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|Win32.ActiveCfg = Release|Win32 - {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|x64.ActiveCfg = Release|x64 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.ActiveCfg = Debug|Win32 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.Build.0 = Debug|Win32 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|x64.ActiveCfg = Debug|x64 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|x64.Build.0 = Debug|x64 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|Win32.ActiveCfg = Release|Win32 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|Win32.Build.0 = Release|Win32 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|x64.ActiveCfg = Release|x64 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|x64.Build.0 = Release|x64 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|Win32.ActiveCfg = Debug|Win32 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|Win32.Build.0 = Debug|Win32 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|x64.ActiveCfg = Debug|x64 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|x64.Build.0 = Debug|x64 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|Win32.ActiveCfg = Release|Win32 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|Win32.Build.0 = Release|Win32 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|x64.ActiveCfg = Release|x64 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|x64.Build.0 = Release|x64 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|Win32.ActiveCfg = Debug|Win32 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|Win32.Build.0 = Debug|Win32 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|x64.ActiveCfg = Debug|x64 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|x64.Build.0 = Debug|x64 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|Win32.ActiveCfg = Release|Win32 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|Win32.Build.0 = Release|Win32 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|x64.ActiveCfg = Release|x64 - {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|x64.Build.0 = Release|x64 - {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|Win32.ActiveCfg = Debug|Win32 - {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|x64.ActiveCfg = Debug|x64 - {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|Win32.ActiveCfg = Release|Win32 - {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|x64.ActiveCfg = Release|x64 - {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Debug|Win32.ActiveCfg = Debug|Win32 - {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Debug|x64.ActiveCfg = Debug|x64 - {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Release|Win32.ActiveCfg = Release|Win32 - {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Release|x64.ActiveCfg = Release|x64 - {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|Win32.ActiveCfg = Debug|Win32 - {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|Win32.Build.0 = Debug|Win32 - {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|x64.ActiveCfg = Debug|x64 - {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|Win32.ActiveCfg = Release|Win32 - {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|x64.ActiveCfg = Release|x64 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|Win32.ActiveCfg = Debug|Win32 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|Win32.Build.0 = Debug|Win32 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|x64.ActiveCfg = Debug|x64 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|x64.Build.0 = Debug|x64 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|Win32.ActiveCfg = Release|Win32 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|Win32.Build.0 = Release|Win32 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|x64.ActiveCfg = Release|x64 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|x64.Build.0 = Release|x64 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|Win32.ActiveCfg = Debug|Win32 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|Win32.Build.0 = Debug|Win32 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|x64.ActiveCfg = Debug|x64 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|x64.Build.0 = Debug|x64 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|Win32.ActiveCfg = Release|Win32 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|Win32.Build.0 = Release|Win32 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|x64.ActiveCfg = Release|x64 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|x64.Build.0 = Release|x64 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|Win32.ActiveCfg = Debug|Win32 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|Win32.Build.0 = Debug|Win32 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|x64.ActiveCfg = Debug|x64 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|x64.Build.0 = Debug|x64 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|Win32.ActiveCfg = Release|Win32 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|Win32.Build.0 = Release|Win32 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.ActiveCfg = Release|x64 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.Build.0 = Release|x64 - {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.ActiveCfg = Debug|Win32 - {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|x64.ActiveCfg = Debug|x64 - {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.ActiveCfg = Release|Win32 - {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|x64.ActiveCfg = Release|x64 - {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.ActiveCfg = Debug|Win32 - {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|x64.ActiveCfg = Debug|x64 - {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|Win32.ActiveCfg = Release|Win32 - {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|x64.ActiveCfg = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/libs/freetdm/freetdm.pc.in b/libs/freetdm/freetdm.pc.in deleted file mode 100644 index 0b563f9840..0000000000 --- a/libs/freetdm/freetdm.pc.in +++ /dev/null @@ -1,18 +0,0 @@ -# -# FreeTDM pkg-config file -# -prefix=@prefix@ -exec_prefix=${prefix} -libdir=${exec_prefix}/lib -includedir=${prefix}/include -modulesdir=@modinstdir@ - -Name: FreeTDM -Description: -Version: @PACKAGE_VERSION@ -URL: http://www.openzap.org/ -Requires: -Conflicts: -Libs: -L${libdir} -lfreetdm -Libs.private: -lm -Cflags: -I${includedir} diff --git a/libs/freetdm/mkrelease.sh b/libs/freetdm/mkrelease.sh deleted file mode 100755 index b079158541..0000000000 --- a/libs/freetdm/mkrelease.sh +++ /dev/null @@ -1,144 +0,0 @@ -#!/bin/bash -INSTALLPREFIX="/usr/local/freetdm" -VERSION="" -NODOCS="NO" - -for i in $* -do - case $i in - --version=*) - VERSION=`echo $i | sed 's/[-a-zA-Z0-9]*=//'` - ;; - --prefix=*) - INSTALLPREFIX=`echo $i | sed 's/[-a-zA-Z0-9]*=//'` - ;; - --nodocs) - NODOCS="YES" - ;; - *) - # unknown option - echo "Unknown option $i" - exit - ;; - esac -done - -if [ "x$VERSION" = "x" ] -then - echo "Provide a version number with --version=" - exit 1 -fi - -arch=$(uname -m) - -# defs -LIBSNG_ISDN_URL=ftp://ftp.sangoma.com/linux/libsng_isdn -LIBSNG_ISDN_NAME=libsng_isdn-7-current -LIBSNG_SS7_URL=ftp://ftp.sangoma.com/linux/libsng_ss7 -LIBSNG_SS7_NAME=libsng_ss7-3-current -LIBSNG_ISDN_DIR="$LIBSNG_ISDN_NAME.$arch" -LIBSNG_SS7_DIR="$LIBSNG_SS7_NAME.$arch" - -# download and decompress a tarball -# $1 = prefix_url, such as ftp://ftp.sangoma.com/foo/bar -# $2 = package name, such as libsng_isdn-7.0.0.x86_64 -function download() { - wget $1/$2.tgz - if [ $? = 0 ] - then - tardir=$(tar -tf $2.tgz | head -n1 | sed 's,\/,,g') - tar -xvzf $2.tgz || echo "FAILED to decompress $2.tgz" - if [ "$tardir" != "$2" ] - then - mv $tardir $2 || echo "FAILED to move $tardir to $2" - fi - echo "SUCCESSFULLY downloaded $2" - else - echo "FAILED to download $1/$2.tgz" - fi -} - -# download and build libsng-ss7 -fullname="$LIBSNG_ISDN_NAME.$arch" -if [ -d $fullname ] -then - echo "skipping isdn download since $fullname directory already exists ... remove if you want this step to be performed" -else - download $LIBSNG_ISDN_URL $fullname -fi - -cd $LIBSNG_ISDN_DIR -make DESTDIR=$INSTALLPREFIX install || echo "Failed to build libsng-isdn" -cd .. - -# download and build libsng-ss7 -fullname="$LIBSNG_SS7_NAME.$arch" -if [ -d $fullname ] -then - echo "skipping ss7 download since $fullname directory already exists ... remove if you want this step to be performed" -else - download $LIBSNG_SS7_URL $fullname -fi - -cd $LIBSNG_SS7_DIR -make DESTDIR=$INSTALLPREFIX install || echo "Failed to build libsng-ss7" -cd .. - -if [ ! -d $INSTALLPREFIX ] -then - mkdir -p $INSTALLPREFIX || exit 1 -fi - -if [ ! -d $INSTALLPREFIX/bin-releases ] -then - mkdir -p $INSTALLPREFIX/bin-releases || exit 1 -fi - -# attempt to compile freetdm -echo "Build freetdm and mod_freetdm now..." -make all mod_freetdm || exit 1 -echo "freetdm built OK" - -major=$(echo "$VERSION" | cut -d. -f1) -minor=$(echo "$VERSION" | cut -d. -f2) -micro=$(echo "$VERSION" | cut -d. -f3) -release="freetdm-$VERSION" - -# ABI compatibility check -if [ -x /usr/local/bin/ftdm_abi_check.py ]; then - /usr/local/bin/ftdm_abi_check.py --release_path=$(pwd) --archive_path=$INSTALLPREFIX/bin-releases --version=$VERSION - - if [ $? -ne 0 ]; then - echo "ABI compabitility test failed, not creating release. Either increment the major version number or fix the interface." - exit 1 - fi -else - echo -ne "\n\nWARNING: /usr/local/bin/ftdm_abi_check.py not found, skipping ABI compatibility test\n\n" -fi - -if [ $NODOCS = "NO" ] -then - make dox || exit 1 -fi - -echo "Creating $release ($major.$minor.$micro) at $INSTALLPREFIX/$release (directory will be removed if exists already) ... " - -mkdir -p $INSTALLPREFIX/$release $INSTALLPREFIX/bin-releases/$major/$release - -cp -r ./* $INSTALLPREFIX/bin-releases/$major/$release -cp -r ./.libs $INSTALLPREFIX/bin-releases/$major/$release - -make clean -make mod_freetdm-clean - -cp -r ./* $INSTALLPREFIX/$release - -# copy ABI compatibility reports to release -if [ -d compat_reports ]; then - mv ./compat_reports $INSTALLPREFIX/$release -fi - -rm -rf $INSTALLPREFIX/$release/{$LIBSNG_ISDN_DIR,$LIBSNG_SS7_DIR,*.tgz} -rm -rf $INSTALLPREFIX/bin-releases/$major/$release/{$LIBSNG_ISDN_DIR,$LIBSNG_SS7_DIR,*.tgz} - -tar -C $INSTALLPREFIX -czf $INSTALLPREFIX/$release.tar.gz $release/ diff --git a/libs/freetdm/mod_freetdm/CMakeLists.txt b/libs/freetdm/mod_freetdm/CMakeLists.txt deleted file mode 100644 index 25847e713f..0000000000 --- a/libs/freetdm/mod_freetdm/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -# -# Arnaldo M Pereira -# -CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -PROJECT(mod_freetdm) - -IF(NOT DEFINED WIN32) - ADD_DEFINITIONS(-g -O2 -ffast-math -Wall -Werror -Wunused-variable -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -O0 -g -ggdb -DPACKAGE_NAME=\"freetdm\" -DPACKAGE_TARNAME=\"freetdm\" -DPACKAGE_VERSION=\"pre-alpha\" -DPACKAGE_STRING=\"freetdm\ pre-alpha\" -DPACKAGE_BUGREPORT=\"bugs@freeswitch.org\" -DPACKAGE_URL=\"\" -DPACKAGE=\"libfreetdm\" -DVERSION=\"0.1\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -DHAVE_LIBDL=1 -DHAVE_LIBPTHREAD=1 -DHAVE_LIBM=1 -DSIZEOF_LONG=8 -DHAVE_NETINET_SCTP_H=1 -DHAVE_NETDB_H=1 -DHAVE_SYS_SELECT_H=1 -DHAVE_GETHOSTBYNAME_R=1) # -DDEBUG=/\*\*/) -ENDIF(NOT DEFINED WIN32) - -# includes -SET(mod_freetdm_INCLUDES - ${PROJECT_SOURCE_DIR}/../src/include - ${PROJECT_SOURCE_DIR}/../src/isdn/include - ${PROJECT_SOURCE_DIR}/../../libteletone/src - ${PROJECT_SOURCE_DIR}/../../../src/include -) -INCLUDE_DIRECTORIES(${mod_freetdm_INCLUDES}) - -LINK_DIRECTORIES(${PROJECT_SOURCE_DIR}/..) -ADD_LIBRARY(${PROJECT_NAME} SHARED mod_freetdm.c) -TARGET_LINK_LIBRARIES(${PROJECT_NAME} freetdm -fPIC -Werror -fvisibility=hidden) - -IF(DEFINED WIN32) - SET(EXT lib) -ELSE(DEFINED WIN32) - SET(EXT so) -ENDIF(DEFINED WIN32) - -ADD_CUSTOM_COMMAND(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E rename lib${PROJECT_NAME}.${EXT} ${PROJECT_NAME}.${EXT} -) diff --git a/libs/freetdm/mod_freetdm/Makefile.in b/libs/freetdm/mod_freetdm/Makefile.in deleted file mode 100644 index 33ca03b440..0000000000 --- a/libs/freetdm/mod_freetdm/Makefile.in +++ /dev/null @@ -1,24 +0,0 @@ -FT_CFLAGS=@CFLAGS@ @COMP_VENDOR_CFLAGS@ @DEFS@ - -BASE=../../.. -FT_DIR=.. -VERBOSE=1 -FTLA=$(FT_DIR)/libfreetdm.la -LOCAL_OBJS=tdm.o -LOCAL_CFLAGS=-I$(FT_DIR)/src/include -I$(FT_DIR)/src/isdn/include $(FT_CFLAGS) -LOCAL_LDFLAGS=-L$(FT_DIR) -lfreetdm -include $(BASE)/build/modmake.rules - -local_depend: $(FTLA) - -$(FTLA): $(FT_DIR)/.update - cd $(FT_DIR) && $(MAKE) - -local_install: - cd $(FT_DIR) && $(MAKE) install - [ -f $(DESTDIR)@confdir@/autoload_configs/freetdm.conf.xml ] || cp -f $(FT_DIR)/conf/freetdm.conf.xml $(DESTDIR)@confdir@/autoload_configs - -local_clean: - cd $(FT_DIR) && $(MAKE) clean - - diff --git a/libs/freetdm/mod_freetdm/clean.sh b/libs/freetdm/mod_freetdm/clean.sh deleted file mode 100755 index 7e531ac7ff..0000000000 --- a/libs/freetdm/mod_freetdm/clean.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -rm -rf mod_freetdm.so -rm -rf .libs/mod_freetdm.so -rm -rf mod_freetdm.o -rm -rf .libs/mod_freetdm.o -rm -rf mod_freetdm.lo diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.2008.vcproj b/libs/freetdm/mod_freetdm/mod_freetdm.2008.vcproj deleted file mode 100644 index 3fdd92af05..0000000000 --- a/libs/freetdm/mod_freetdm/mod_freetdm.2008.vcproj +++ /dev/null @@ -1,369 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.2010.vcxproj.filters b/libs/freetdm/mod_freetdm/mod_freetdm.2010.vcxproj.filters deleted file mode 100644 index 92ac5ead47..0000000000 --- a/libs/freetdm/mod_freetdm/mod_freetdm.2010.vcxproj.filters +++ /dev/null @@ -1,14 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Source Files - - - \ No newline at end of file diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c deleted file mode 100644 index 5126a3690a..0000000000 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ /dev/null @@ -1,5715 +0,0 @@ -/* - * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005-2014, Anthony Minessale II - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * - * The Initial Developer of the Original Code is - * Anthony Minessale II - * Portions created by the Initial Developer are Copyright (C) - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Anthony Minessale II - * Moises Silva - * David Yat Sin - * James Zhang - * Gideon Sadan - * - * mod_freetdm.c -- FreeTDM Endpoint Module - * - */ -#include -#include "freetdm.h" - -//#define BACKTRACE_DEBUG - -#define FREETDM_LIMIT_REALM "__freetdm" -#define FREETDM_VAR_PREFIX "freetdm_" -#define FREETDM_VAR_PREFIX_LEN (sizeof(FREETDM_VAR_PREFIX)-1) - -/* How many consecutive IO errors before giving up */ -#define FTDM_MAX_READ_WRITE_ERRORS 10 - -#define get_ss7_config_node(_cfg, _confname) _get_ss7_config_node(cfg, confname, "ISUP") - -SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load); -SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_freetdm_shutdown); -SWITCH_MODULE_DEFINITION(mod_freetdm, mod_freetdm_load, mod_freetdm_shutdown, NULL); - -switch_endpoint_interface_t *freetdm_endpoint_interface; - -static switch_memory_pool_t *module_pool = NULL; - -typedef enum { - ANALOG_OPTION_NONE = 0, - ANALOG_OPTION_3WAY = (1 << 0), - ANALOG_OPTION_CALL_SWAP = (1 << 1) -} analog_option_t; - -typedef enum { - FTDM_LIMIT_RESET_ON_TIMEOUT = 0, - FTDM_LIMIT_RESET_ON_ANSWER = 1 -} limit_reset_event_t; - -typedef enum { - TFLAG_IO = (1 << 0), - TFLAG_DTMF = (1 << 1), - TFLAG_CODEC = (1 << 2), - TFLAG_BREAK = (1 << 3), - TFLAG_HOLD = (1 << 4), - TFLAG_DEAD = (1 << 5), - TFLAG_TRANSFER = (1 << 6), -} TFLAGS; - -static struct { - int debug; - char *dialplan; - char *codec_string; - char *codec_order[SWITCH_MAX_CODECS]; - int codec_order_last; - char *codec_rates_string; - char *codec_rates[SWITCH_MAX_CODECS]; - int codec_rates_last; - unsigned int flags; - int fd; - int calls; - char hold_music[256]; - switch_mutex_t *mutex; - analog_option_t analog_options; - switch_hash_t *ss7_configs; - int sip_headers; - uint8_t crash_on_assert; - uint8_t fail_on_error; - uint8_t config_error; -} globals; - -/* private data attached to each fs session */ -struct private_object { - unsigned int flags; - switch_codec_t read_codec; - switch_codec_t write_codec; - switch_frame_t read_frame; - unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; - switch_frame_t cng_frame; - unsigned char cng_databuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; - switch_core_session_t *session; - switch_caller_profile_t *caller_profile; - unsigned int codec; - unsigned int codecs; - unsigned short samprate; - switch_mutex_t *mutex; - switch_mutex_t *flag_mutex; - ftdm_channel_t *ftdmchan; - uint32_t write_error; - uint32_t read_error; - char network_peer_uuid[SWITCH_UUID_FORMATTED_LENGTH + 1]; -}; - -/* private data attached to FTDM channels (only FXS for now) */ -typedef struct chan_pvt { - unsigned int flags; -} chan_pvt_t; - -typedef struct private_object private_t; - -struct span_config { - ftdm_span_t *span; - char dialplan[80]; - char context[80]; - char dial_regex[256]; - char fail_dial_regex[256]; - char hold_music[256]; - char type[256]; - analog_option_t analog_options; - const char *limit_backend; - int limit_calls; - int limit_seconds; - limit_reset_event_t limit_reset_event; - /* digital codec and digital sampling rate are used to configure the codec - * when bearer capability is set to unrestricted digital */ - const char *digital_codec; - int digital_sampling_rate; - chan_pvt_t pvts[FTDM_MAX_CHANNELS_SPAN]; -}; - -static struct span_config SPAN_CONFIG[FTDM_MAX_SPANS_INTERFACE] = {{0}}; - -static switch_status_t channel_on_init(switch_core_session_t *session); -static switch_status_t channel_on_hangup(switch_core_session_t *session); -static switch_status_t channel_on_destroy(switch_core_session_t *session); -static switch_status_t channel_on_routing(switch_core_session_t *session); -static switch_status_t channel_on_exchange_media(switch_core_session_t *session); -static switch_status_t channel_on_soft_execute(switch_core_session_t *session); -static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, - switch_caller_profile_t *outbound_profile, - switch_core_session_t **new_session, - switch_memory_pool_t **pool, - switch_originate_flag_t flags, switch_call_cause_t *cancel_cause); -static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id); -static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id); -static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig); -static const char* channel_get_variable(switch_core_session_t *session, switch_event_t *var_event, const char *variable_name); -ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session_t **sp); -void dump_chan(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream); -void dump_chan_xml(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream); -#if 0 -void ctdm_init(switch_loadable_module_interface_t *module_interface); -#endif - -static switch_core_session_t *ftdm_channel_get_session(ftdm_channel_t *channel, int32_t id) -{ - switch_core_session_t *session = NULL; - const char *token = ftdm_channel_get_token(channel, id); - - if (!zstr(token)) { - if (!(session = switch_core_session_locate(token))) { - ftdm_channel_clear_token(channel, token); - } - } - - return session; -} - -static const char *ftdm_channel_get_uuid(ftdm_channel_t *channel, int32_t id) -{ - return ftdm_channel_get_token(channel, id); -} - -static void stop_hold(switch_core_session_t *session_a, const char *uuid) -{ - switch_core_session_t *session; - switch_channel_t *channel, *channel_a; - - if (!uuid) { - return; - } - - if ((session = switch_core_session_locate(uuid))) { - channel = switch_core_session_get_channel(session); - - if (switch_channel_test_flag(channel, CF_HOLD)) { - channel_a = switch_core_session_get_channel(session_a); - switch_ivr_unhold(session); - switch_channel_clear_flag(channel_a, CF_SUSPEND); - switch_channel_clear_flag(channel_a, CF_HOLD); - } else { - switch_channel_stop_broadcast(channel); - switch_channel_wait_for_flag(channel, CF_BROADCAST, SWITCH_FALSE, 2000, NULL); - } - - switch_core_session_rwunlock(session); - } -} - -static void start_hold(ftdm_channel_t *ftdmchan, switch_core_session_t *session_a, const char *uuid, const char *stream) -{ - switch_core_session_t *session; - switch_channel_t *channel, *channel_a; - int32_t spanid = 0; - - if (!uuid) { - return; - } - - spanid = ftdm_channel_get_span_id(ftdmchan); - if ((session = switch_core_session_locate(uuid))) { - channel = switch_core_session_get_channel(session); - if (zstr(stream)) { - if (!strcasecmp(globals.hold_music, "indicate_hold")) { - stream = "indicate_hold"; - } - if (!strcasecmp(SPAN_CONFIG[spanid].hold_music, "indicate_hold")) { - stream = "indicate_hold"; - } - } - - if (zstr(stream)) { - stream = switch_channel_get_variable(channel, SWITCH_HOLD_MUSIC_VARIABLE); - } - - if (zstr(stream)) { - stream = SPAN_CONFIG[spanid].hold_music; - } - - if (zstr(stream)) { - stream = globals.hold_music; - } - - if (zstr(stream) && !(stream = switch_channel_get_variable(channel, SWITCH_HOLD_MUSIC_VARIABLE))) { - stream = globals.hold_music; - } - - if (!zstr(stream)) { - if (!strcasecmp(stream, "indicate_hold")) { - channel_a = switch_core_session_get_channel(session_a); - switch_ivr_hold_uuid(uuid, NULL, 0); - switch_channel_set_flag(channel_a, CF_SUSPEND); - switch_channel_set_flag(channel_a, CF_HOLD); - } else { - switch_ivr_broadcast(switch_core_session_get_uuid(session), stream, SMF_ECHO_ALEG | SMF_LOOP); - } - } - - switch_core_session_rwunlock(session); - } -} - - -static void cycle_foreground(ftdm_channel_t *ftdmchan, int flash, const char *bcast) { - uint32_t i = 0; - switch_core_session_t *session; - switch_channel_t *channel; - private_t *tech_pvt; - uint32_t tokencnt = ftdm_channel_get_token_count(ftdmchan); - - for (i = 0; i < tokencnt; i++) { - if ((session = ftdm_channel_get_session(ftdmchan, i))) { - const char *buuid; - tech_pvt = switch_core_session_get_private(session); - channel = switch_core_session_get_channel(session); - buuid = switch_channel_get_partner_uuid(channel); - - if (tokencnt == 1 && flash) { - if (switch_test_flag(tech_pvt, TFLAG_HOLD)) { - stop_hold(session, buuid); - switch_clear_flag_locked(tech_pvt, TFLAG_HOLD); - } else { - start_hold(ftdmchan, session, buuid, bcast); - switch_set_flag_locked(tech_pvt, TFLAG_HOLD); - } - } else if (i) { - start_hold(ftdmchan, session, buuid, bcast); - switch_set_flag_locked(tech_pvt, TFLAG_HOLD); - } else { - stop_hold(session, buuid); - switch_clear_flag_locked(tech_pvt, TFLAG_HOLD); - if (!switch_channel_test_flag(channel, CF_ANSWERED)) { - switch_channel_mark_answered(channel); - } - } - switch_core_session_rwunlock(session); - } - } -} - -static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *session, ftdm_channel_t *ftdmchan, ftdm_caller_data_t *caller_data) -{ - const char *dname = NULL; - uint32_t interval = 0, srate = 8000; - uint32_t span_id; - ftdm_codec_t codec; - - tech_pvt->ftdmchan = ftdmchan; - tech_pvt->read_frame.data = tech_pvt->databuf; - tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf); - tech_pvt->cng_frame.data = tech_pvt->cng_databuf; - tech_pvt->cng_frame.buflen = sizeof(tech_pvt->cng_databuf); - tech_pvt->cng_frame.flags = SFF_CNG; - tech_pvt->cng_frame.codec = &tech_pvt->read_codec; - memset(tech_pvt->cng_frame.data, 255, tech_pvt->cng_frame.buflen); - switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); - switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); - switch_core_session_set_private(session, tech_pvt); - tech_pvt->session = session; - - if (FTDM_SUCCESS != ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to retrieve channel interval.\n"); - return SWITCH_STATUS_GENERR; - } - - span_id = ftdm_channel_get_span_id(ftdmchan); - if (caller_data->bearer_capability == FTDM_BEARER_CAP_UNRESTRICTED - && SPAN_CONFIG[span_id].digital_codec) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Initializing digital call with codec %s at %dhz.\n", - SPAN_CONFIG[span_id].digital_codec, SPAN_CONFIG[span_id].digital_sampling_rate); - dname = SPAN_CONFIG[span_id].digital_codec; - srate = SPAN_CONFIG[span_id].digital_sampling_rate; - goto init_codecs; - } - - if (FTDM_SUCCESS != ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_CODEC, &codec)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to retrieve channel codec.\n"); - return SWITCH_STATUS_GENERR; - } - - switch (codec) { - case FTDM_CODEC_ULAW: - { - dname = "PCMU"; - } - break; - case FTDM_CODEC_ALAW: - { - dname = "PCMA"; - } - break; - case FTDM_CODEC_SLIN: - { - dname = "L16"; - } - break; - default: - { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid codec value retrieved from channel, codec value: %d\n", codec); - return SWITCH_STATUS_GENERR; - } - } - -init_codecs: - - if (switch_core_codec_init(&tech_pvt->read_codec, - dname, - NULL, - NULL, - srate, - interval, - 1, - SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, - NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); - return SWITCH_STATUS_GENERR; - } else { - if (switch_core_codec_init(&tech_pvt->write_codec, - dname, - NULL, - NULL, - srate, - interval, - 1, - SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, - NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); - switch_core_codec_destroy(&tech_pvt->read_codec); - return SWITCH_STATUS_GENERR; - } - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set codec %s %dms\n", dname, interval); - switch_core_session_set_read_codec(tech_pvt->session, &tech_pvt->read_codec); - switch_core_session_set_write_codec(tech_pvt->session, &tech_pvt->write_codec); - switch_set_flag_locked(tech_pvt, TFLAG_CODEC); - tech_pvt->read_frame.codec = &tech_pvt->read_codec; - switch_set_flag_locked(tech_pvt, TFLAG_IO); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_on_init(switch_core_session_t *session) -{ - switch_channel_t *channel; - private_t *tech_pvt = NULL; - - tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - if (switch_test_flag(tech_pvt, TFLAG_DEAD)) { - switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE); - return SWITCH_STATUS_SUCCESS; - } - - /* Move channel's state machine to ROUTING */ - switch_channel_set_state(channel, CS_ROUTING); - switch_mutex_lock(globals.mutex); - globals.calls++; - switch_mutex_unlock(globals.mutex); - - //switch_channel_set_flag(channel, CF_ACCEPT_CNG); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_on_routing(switch_core_session_t *session) -{ - switch_channel_t *channel = NULL; - private_t *tech_pvt = NULL; - - channel = switch_core_session_get_channel(session); - switch_assert(channel != NULL); - - tech_pvt = switch_core_session_get_private(session); - switch_assert(tech_pvt != NULL); - - switch_assert(tech_pvt->ftdmchan != NULL); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel)); - - if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { - ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROCEED); - } - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_on_execute(switch_core_session_t *session) -{ - - switch_channel_t *channel = NULL; - private_t *tech_pvt = NULL; - - channel = switch_core_session_get_channel(session); - switch_assert(channel != NULL); - - tech_pvt = switch_core_session_get_private(session); - switch_assert(tech_pvt != NULL); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL EXECUTE\n", switch_channel_get_name(channel)); - - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_on_destroy(switch_core_session_t *session) -{ - private_t *tech_pvt = NULL; - - if ((tech_pvt = switch_core_session_get_private(session))) { - - if (tech_pvt->read_codec.implementation) { - switch_core_codec_destroy(&tech_pvt->read_codec); - } - - if (tech_pvt->write_codec.implementation) { - switch_core_codec_destroy(&tech_pvt->write_codec); - } - - switch_core_session_unset_read_codec(session); - switch_core_session_unset_write_codec(session); - - } - - return SWITCH_STATUS_SUCCESS; -} - -#ifdef BACKTRACE_DEBUG -struct debug_trace_priv { - const char *name; - int span_id; - int chan_id; -}; - -static void debug_trace(const int tid, const void *addr, const char *symbol, void *priv) -{ - struct debug_trace_priv *data = priv; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%d:%d][tid:%d] %s -> %s\n", - data->span_id, data->chan_id, tid, data->name, symbol); -} -#endif - -static switch_status_t channel_on_hangup(switch_core_session_t *session) -{ - switch_channel_t *channel = NULL; - private_t *tech_pvt = NULL; - ftdm_chan_type_t chantype; - const char *name = NULL; - int span_id = 0; - int chan_id = 0; - uint32_t t = 0; - uint32_t tokencnt; - char *uuid = NULL; - const char *token = NULL; - uint8_t uuid_found = 0; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); - - /* ignore any further I/O requests, we're hanging up already! */ - switch_clear_flag_locked(tech_pvt, TFLAG_IO); - - name = switch_channel_get_name(channel); - - span_id = tech_pvt->ftdmchan ? ftdm_channel_get_span_id(tech_pvt->ftdmchan) : 0; - chan_id = tech_pvt->ftdmchan ? ftdm_channel_get_id(tech_pvt->ftdmchan) : 0; - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%d:%d] %s CHANNEL HANGUP ENTER\n", span_id, chan_id, name); - - /* First verify this call has a device attached */ - if (!tech_pvt->ftdmchan) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s does not have any ftdmchan attached\n", name); - goto end; - } - - /* Now verify the device is still attached to this call :-) - * Sometimes the FS core takes too long (more than 3 seconds) in calling - * channel_on_hangup() and the FreeTDM core decides to take the brute - * force approach and hangup and detach themselves from the call. Later - * when FS finally comes around, we might end up hanging up the device - * attached to another call, this verification avoids that. */ - uuid = switch_core_session_get_uuid(session); - tokencnt = ftdm_channel_get_token_count(tech_pvt->ftdmchan); - for (t = 0; t < tokencnt; t++) { - token = ftdm_channel_get_token(tech_pvt->ftdmchan, t); - if (!zstr(token) && !strcasecmp(uuid, token)) { - uuid_found = 1; - break; - } - } - - if (!uuid_found) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Device [%d:%d] is no longer attached to %s\n", span_id, chan_id, name); - goto end; - } - -#ifdef BACKTRACE_DEBUG - { - struct debug_trace_priv trace_data; - trace_data.name = name; - trace_data.span_id = span_id; - trace_data.chan_id = chan_id; - ftdm_backtrace_walk(&debug_trace, &trace_data); - } -#endif - - ftdm_channel_clear_token(tech_pvt->ftdmchan, switch_core_session_get_uuid(session)); - - chantype = ftdm_channel_get_type(tech_pvt->ftdmchan); - switch (chantype) { - case FTDM_CHAN_TYPE_FXO: - case FTDM_CHAN_TYPE_EM: - { - ftdm_channel_call_hangup(tech_pvt->ftdmchan); - } - break; - case FTDM_CHAN_TYPE_FXS: - { - tokencnt = ftdm_channel_get_token_count(tech_pvt->ftdmchan); - if (!ftdm_channel_call_check_busy(tech_pvt->ftdmchan) && !ftdm_channel_call_check_done(tech_pvt->ftdmchan)) { - if (tokencnt) { - cycle_foreground(tech_pvt->ftdmchan, 0, NULL); - } else { - ftdm_channel_call_hangup(tech_pvt->ftdmchan); - } - } - } - break; - case FTDM_CHAN_TYPE_CAS: - case FTDM_CHAN_TYPE_B: - { - const char *var = NULL; - switch_call_cause_t ccause = switch_channel_get_cause_q850(channel); - ftdm_call_cause_t hcause; - if (ccause < 1 || ccause > 127) { - hcause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER; - } else { - hcause = (ftdm_call_cause_t)ccause; - } - var = switch_channel_get_variable(channel, "ss7_rel_loc"); - if (var) { - ftdm_usrmsg_t usrmsg; - memset(&usrmsg, 0, sizeof(ftdm_usrmsg_t)); - ftdm_usrmsg_add_var(&usrmsg, "ss7_rel_loc", var); - ftdm_channel_call_hangup_with_cause_ex(tech_pvt->ftdmchan, hcause, &usrmsg); - } else { - ftdm_channel_call_hangup_with_cause(tech_pvt->ftdmchan, hcause); - } - } - break; - default: - { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Unhandled channel type %d for channel %s\n", chantype, switch_channel_get_name(channel)); - } - break; - } - - end: - - switch_mutex_lock(globals.mutex); - globals.calls--; - if (globals.calls < 0) { - globals.calls = 0; - } - switch_mutex_unlock(globals.mutex); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%d:%d] %s CHANNEL HANGUP EXIT\n", span_id, chan_id, name); - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig) -{ - switch_channel_t *channel = NULL; - private_t *tech_pvt = NULL; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); - - switch (sig) { - case SWITCH_SIG_KILL: - switch_clear_flag_locked(tech_pvt, TFLAG_IO); - switch_set_flag_locked(tech_pvt, TFLAG_DEAD); - break; - case SWITCH_SIG_BREAK: - switch_set_flag_locked(tech_pvt, TFLAG_BREAK); - break; - default: - break; - } - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_on_exchange_media(switch_core_session_t *session) -{ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHANNEL EXCHANGE_MEDIA\n"); - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_on_soft_execute(switch_core_session_t *session) -{ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHANNEL SOFT_EXECUTE\n"); - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf) -{ - private_t *tech_pvt = NULL; - char tmp[2] = ""; - - tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); - - if (switch_test_flag(tech_pvt, TFLAG_DEAD)) { - switch_channel_hangup(switch_core_session_get_channel(session), SWITCH_CAUSE_LOSE_RACE); - return SWITCH_STATUS_FALSE; - } - - tmp[0] = dtmf->digit; - ftdm_channel_command(tech_pvt->ftdmchan, FTDM_COMMAND_SEND_DTMF, tmp); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id) -{ - switch_channel_t *channel = NULL; - private_t *tech_pvt = NULL; - ftdm_size_t len; - ftdm_wait_flag_t wflags = FTDM_READ; - char dtmf[128] = ""; - ftdm_status_t status; - int total_to; - int chunk, do_break = 0; - uint32_t span_id, chan_id; - const char *name = NULL; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); - - name = switch_channel_get_name(channel); - if (!tech_pvt->ftdmchan) { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "no ftdmchan set in channel %s!\n", name); - return SWITCH_STATUS_FALSE; - } - - span_id = ftdm_channel_get_span_id(tech_pvt->ftdmchan); - chan_id = ftdm_channel_get_id(tech_pvt->ftdmchan); - if (switch_test_flag(tech_pvt, TFLAG_DEAD)) { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "TFLAG_DEAD is set in channel %s device %d:%d!\n", name, span_id, chan_id); - return SWITCH_STATUS_FALSE; - } - - /* Digium Cards sometimes timeout several times in a row here. - Yes, we support digium cards, ain't we nice....... - 6 double length intervals should compensate */ - chunk = ftdm_channel_get_io_interval(tech_pvt->ftdmchan) * 2; - total_to = chunk * 6; - - top: - - if (switch_channel_test_flag(channel, CF_SUSPEND)) { - do_break = 1; - } - - if (switch_test_flag(tech_pvt, TFLAG_BREAK)) { - switch_clear_flag_locked(tech_pvt, TFLAG_BREAK); - do_break = 1; - } - - if (switch_test_flag(tech_pvt, TFLAG_HOLD) || do_break) { - switch_yield(ftdm_channel_get_io_interval(tech_pvt->ftdmchan) * 1000); - tech_pvt->cng_frame.datalen = ftdm_channel_get_io_packet_len(tech_pvt->ftdmchan); - tech_pvt->cng_frame.samples = tech_pvt->cng_frame.datalen; - tech_pvt->cng_frame.flags = SFF_CNG; - *frame = &tech_pvt->cng_frame; - if (ftdm_channel_get_codec(tech_pvt->ftdmchan) == FTDM_CODEC_SLIN) { - tech_pvt->cng_frame.samples /= 2; - } - return SWITCH_STATUS_SUCCESS; - } - - if (!switch_test_flag(tech_pvt, TFLAG_IO)) { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "TFLAG_IO is not set in channel %s device %d:%d!\n", name, span_id, chan_id); - goto fail; - } - - wflags = FTDM_READ; - status = ftdm_channel_wait(tech_pvt->ftdmchan, &wflags, chunk); - - if (status == FTDM_FAIL) { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_ERROR, "Failed to read from channel %s device %d:%d!\n", name, span_id, chan_id); - goto fail; - } - - if (status == FTDM_TIMEOUT) { - if (!switch_test_flag(tech_pvt, TFLAG_HOLD)) { - total_to -= chunk; - if (total_to <= 0) { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "Too many timeouts while waiting I/O in channel %s device %d:%d!\n", name, span_id, chan_id); - goto fail; - } - } - goto top; - } - - if (!(wflags & FTDM_READ)) { - goto top; - } - - len = tech_pvt->read_frame.buflen; - if (ftdm_channel_read(tech_pvt->ftdmchan, tech_pvt->read_frame.data, &len) != FTDM_SUCCESS) { - if (switch_test_flag(tech_pvt, TFLAG_DEAD)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Failed to read from dead channel %s device %d:%d\n", name, span_id, chan_id); - goto normal_failure; - } - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "Failed to read from channel %s device %d:%d!\n", name, span_id, chan_id); - if (++tech_pvt->read_error > FTDM_MAX_READ_WRITE_ERRORS) { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_ERROR, "too many I/O read errors on channel %s device %d:%d!\n", name, span_id, chan_id); - goto fail; - } - - } else { - tech_pvt->read_error = 0; - } - - *frame = &tech_pvt->read_frame; - tech_pvt->read_frame.datalen = (uint32_t)len; - tech_pvt->read_frame.samples = tech_pvt->read_frame.datalen; - - if (ftdm_channel_get_codec(tech_pvt->ftdmchan) == FTDM_CODEC_SLIN) { - tech_pvt->read_frame.samples /= 2; - } - - while (ftdm_channel_dequeue_dtmf(tech_pvt->ftdmchan, dtmf, sizeof(dtmf))) { - switch_dtmf_t _dtmf = { 0, switch_core_default_dtmf_duration(0) }; - char *p; - for (p = dtmf; p && *p; p++) { - if (is_dtmf(*p)) { - _dtmf.digit = *p; - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Queuing DTMF [%c] in channel %s device %d:%d\n", *p, name, span_id, chan_id); - switch_channel_queue_dtmf(channel, &_dtmf); - } - } - } - - return SWITCH_STATUS_SUCCESS; - -fail: - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_ERROR, "clearing IO in channel %s device %d:%d!\n", name, span_id, chan_id); -normal_failure: - switch_clear_flag_locked(tech_pvt, TFLAG_IO); - return SWITCH_STATUS_GENERR; -} - -static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id) -{ - switch_channel_t *channel = NULL; - private_t *tech_pvt = NULL; - ftdm_size_t len; - unsigned char data[SWITCH_RECOMMENDED_BUFFER_SIZE] = {0}; - const char *name = "(none)"; - ftdm_wait_flag_t wflags = FTDM_WRITE; - uint32_t span_id = 0, chan_id = 0; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); - - name = switch_channel_get_name(channel); - if (!tech_pvt->ftdmchan) { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "no ftdmchan set in channel %s!\n", name); - return SWITCH_STATUS_FALSE; - } - - span_id = ftdm_channel_get_span_id(tech_pvt->ftdmchan); - chan_id = ftdm_channel_get_id(tech_pvt->ftdmchan); - - if (switch_test_flag(tech_pvt, TFLAG_DEAD)) { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "TFLAG_DEAD is set in channel %s device %d:%d!\n", name, span_id, chan_id); - return SWITCH_STATUS_FALSE; - } - - if (switch_test_flag(tech_pvt, TFLAG_HOLD)) { - return SWITCH_STATUS_SUCCESS; - } - - if (!switch_test_flag(tech_pvt, TFLAG_IO)) { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "TFLAG_IO is not set in channel %s device %d:%d!\n", name, span_id, chan_id); - goto fail; - } - - if (switch_test_flag(frame, SFF_CNG)) { - frame->data = data; - frame->buflen = sizeof(data); - if ((frame->datalen = tech_pvt->write_codec.implementation->encoded_bytes_per_packet) > frame->buflen) { - goto fail; - } - memset(data, 255, frame->datalen); - } - - - wflags = FTDM_WRITE; - ftdm_channel_wait(tech_pvt->ftdmchan, &wflags, ftdm_channel_get_io_interval(tech_pvt->ftdmchan) * 10); - - if (!(wflags & FTDM_WRITE)) { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Dropping frame! (write not ready) in channel %s device %d:%d!\n", name, span_id, chan_id); - return SWITCH_STATUS_SUCCESS; - } - - len = frame->datalen; - if (ftdm_channel_write(tech_pvt->ftdmchan, frame->data, frame->buflen, &len) != FTDM_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Failed to write to channel %s device %d:%d!\n", name, span_id, chan_id); - if (++tech_pvt->write_error > FTDM_MAX_READ_WRITE_ERRORS) { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), - SWITCH_LOG_ERROR, "Too many I/O write errors on channel %s device %d:%d!\n", name, span_id, chan_id); - goto fail; - } - } else { - tech_pvt->write_error = 0; - } - - return SWITCH_STATUS_SUCCESS; - - fail: - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Error writing to channel %s device %d:%d!\n", name, span_id, chan_id); - switch_clear_flag_locked(tech_pvt, TFLAG_IO); - return SWITCH_STATUS_GENERR; - -} - -static switch_status_t channel_receive_message_cas(switch_core_session_t *session, switch_core_session_message_t *msg) -{ - switch_channel_t *channel; - private_t *tech_pvt; - uint32_t phy_id; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = (private_t *) switch_core_session_get_private(session); - assert(tech_pvt != NULL); - - if (switch_test_flag(tech_pvt, TFLAG_DEAD)) { - switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE); - return SWITCH_STATUS_FALSE; - } - - phy_id = ftdm_channel_get_ph_id(tech_pvt->ftdmchan); - ftdm_log(FTDM_LOG_DEBUG, "Got Freeswitch message in R2 channel %d [%d]\n", phy_id, msg->message_id); - - if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { - return SWITCH_STATUS_SUCCESS; - } - - switch (msg->message_id) { - case SWITCH_MESSAGE_INDICATE_RINGING: - { - ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROGRESS); - } - break; - case SWITCH_MESSAGE_INDICATE_PROGRESS: - { - ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA); - } - break; - case SWITCH_MESSAGE_INDICATE_ANSWER: - { - ftdm_channel_call_answer(tech_pvt->ftdmchan); - } - break; - default: - break; - } - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_receive_message_b(switch_core_session_t *session, switch_core_session_message_t *msg) -{ - switch_channel_t *channel; - private_t *tech_pvt; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = (private_t *) switch_core_session_get_private(session); - assert(tech_pvt != NULL); - - if (switch_test_flag(tech_pvt, TFLAG_DEAD)) { - switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE); - return SWITCH_STATUS_FALSE; - } - - if (ftdm_channel_call_check_hangup(tech_pvt->ftdmchan)) { - return SWITCH_STATUS_SUCCESS; - } - - if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { - return SWITCH_STATUS_SUCCESS; - } - - switch (msg->message_id) { - case SWITCH_MESSAGE_INDICATE_RINGING: - { - ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_RINGING); - } - break; - case SWITCH_MESSAGE_INDICATE_PROGRESS: - { - ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA); - } - break; - case SWITCH_MESSAGE_INDICATE_ANSWER: - { - ftdm_channel_call_answer(tech_pvt->ftdmchan); - } - break; - case SWITCH_MESSAGE_INDICATE_REDIRECT: - case SWITCH_MESSAGE_INDICATE_DEFLECT: - { - ftdm_usrmsg_t usrmsg; - const char *val = NULL; - - memset(&usrmsg, 0, sizeof(usrmsg)); - - if ((val = switch_channel_get_variable(channel, "freetdm_transfer_data"))) { - ftdm_usrmsg_add_var(&usrmsg, "transfer_data", val); - } - - switch_set_flag(tech_pvt, TFLAG_TRANSFER); - if (ftdm_channel_call_transfer_ex(tech_pvt->ftdmchan, msg->string_arg, &usrmsg) != FTDM_SUCCESS) { - switch_clear_flag(tech_pvt, TFLAG_TRANSFER); - } - while (switch_test_flag(tech_pvt, TFLAG_TRANSFER)) { - switch_yield(100000); - } - } - default: - break; - } - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_receive_message_fxo(switch_core_session_t *session, switch_core_session_message_t *msg) -{ - switch_channel_t *channel; - private_t *tech_pvt; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = (private_t *) switch_core_session_get_private(session); - assert(tech_pvt != NULL); - - if (switch_test_flag(tech_pvt, TFLAG_DEAD)) { - switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE); - return SWITCH_STATUS_FALSE; - } - - if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { - return SWITCH_STATUS_SUCCESS; - } - - switch (msg->message_id) { - case SWITCH_MESSAGE_INDICATE_PROGRESS: - case SWITCH_MESSAGE_INDICATE_ANSWER: - ftdm_channel_call_answer(tech_pvt->ftdmchan); - break; - default: - break; - } - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_receive_message_fxs(switch_core_session_t *session, switch_core_session_message_t *msg) -{ - switch_channel_t *channel; - private_t *tech_pvt; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = (private_t *) switch_core_session_get_private(session); - assert(tech_pvt != NULL); - - if (switch_test_flag(tech_pvt, TFLAG_DEAD)) { - switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE); - return SWITCH_STATUS_FALSE; - } - - if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { - return SWITCH_STATUS_SUCCESS; - } - - switch (msg->message_id) { - case SWITCH_MESSAGE_INDICATE_PROGRESS: - case SWITCH_MESSAGE_INDICATE_ANSWER: - ftdm_channel_call_answer(tech_pvt->ftdmchan); - switch_channel_mark_answered(channel); - break; - case SWITCH_MESSAGE_INDICATE_RINGING: - if (!switch_channel_test_flag(channel, CF_ANSWERED) && - !switch_channel_test_flag(channel, CF_EARLY_MEDIA) && - !switch_channel_test_flag(channel, CF_RING_READY) - ) { - ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_RINGING); - switch_channel_mark_ring_ready(channel); - } - break; - default: - break; - } - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg) -{ - private_t *tech_pvt; - switch_status_t status; - switch_channel_t *channel; - const char *var; - ftdm_channel_t *ftdmchan = NULL; - - tech_pvt = (private_t *) switch_core_session_get_private(session); - assert(tech_pvt != NULL); - - channel = switch_core_session_get_channel(session); - - if (switch_test_flag(tech_pvt, TFLAG_DEAD)) { - switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE); - return SWITCH_STATUS_FALSE; - } - - if (!(ftdmchan = tech_pvt->ftdmchan)) { - switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE); - return SWITCH_STATUS_FALSE; - } - - if (!tech_pvt->ftdmchan) { - switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE); - return SWITCH_STATUS_FALSE; - } - - switch (msg->message_id) { - case SWITCH_MESSAGE_INDICATE_PROGRESS: - case SWITCH_MESSAGE_INDICATE_ANSWER: - if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { - if ((var = switch_channel_get_variable(channel, "freetdm_pre_buffer_size"))) { - int tmp = atoi(var); - if (tmp > -1) { - ftdm_channel_command(tech_pvt->ftdmchan, FTDM_COMMAND_SET_PRE_BUFFER_SIZE, &tmp); - } - } - if ((var = switch_channel_get_variable(channel, "freetdm_disable_dtmf"))) { - ftdm_channel_command(tech_pvt->ftdmchan, FTDM_COMMAND_DISABLE_DTMF_DETECT, NULL); - } - } - break; - case SWITCH_MESSAGE_INDICATE_UUID_CHANGE: - { - ftdm_channel_replace_token(tech_pvt->ftdmchan, msg->string_array_arg[0], msg->string_array_arg[1]); - } - break; - default: - break; - } - - switch (ftdm_channel_get_type(tech_pvt->ftdmchan)) { - case FTDM_CHAN_TYPE_FXS: - case FTDM_CHAN_TYPE_EM: - status = channel_receive_message_fxs(session, msg); - break; - case FTDM_CHAN_TYPE_FXO: - status = channel_receive_message_fxo(session, msg); - break; - case FTDM_CHAN_TYPE_B: - status = channel_receive_message_b(session, msg); - break; - case FTDM_CHAN_TYPE_CAS: - status = channel_receive_message_cas(session, msg); - break; - default: - status = SWITCH_STATUS_FALSE; - break; - } - - return status; -} - -switch_state_handler_table_t freetdm_state_handlers = { - /*.on_init */ channel_on_init, - /*.on_routing */ channel_on_routing, - /*.on_execute */ channel_on_execute, - /*.on_hangup */ channel_on_hangup, - /*.on_exchange_media */ channel_on_exchange_media, - /*.on_soft_execute */ channel_on_soft_execute, - /*.on_consume_media */ NULL, - /*.on_hibernate */ NULL, - /*.on_reset */ NULL, - /*.on_park*/ NULL, - /*.on_reporting*/ NULL, - /*.on_destroy*/ channel_on_destroy -}; - -switch_io_routines_t freetdm_io_routines = { - /*.outgoing_channel */ channel_outgoing_channel, - /*.read_frame */ channel_read_frame, - /*.write_frame */ channel_write_frame, - /*.kill_channel */ channel_kill_channel, - /*.send_dtmf */ channel_send_dtmf, - /*.receive_message*/ channel_receive_message -}; - -static const char* channel_get_variable(switch_core_session_t *session, switch_event_t *var_event, const char *variable_name) -{ - const char *variable = NULL; - - if (var_event) { - if ((variable = switch_event_get_header(var_event, variable_name))) { - return variable; - } - } - - if (session) { - switch_channel_t *channel = switch_core_session_get_channel(session); - if ((variable = switch_channel_get_variable(channel, variable_name))) { - return variable; - } - } - return NULL; -} - -typedef struct { - switch_event_t *var_event; - switch_core_session_t *new_session; - private_t *tech_pvt; - switch_caller_profile_t *caller_profile; -} hunt_data_t; - -static ftdm_status_t on_channel_found(ftdm_channel_t *fchan, ftdm_caller_data_t *caller_data) -{ - uint32_t span_id, chan_id; - const char *var; - char *sess_uuid; - char name[128]; - ftdm_status_t status; - hunt_data_t *hdata = caller_data->priv; - switch_channel_t *channel = switch_core_session_get_channel(hdata->new_session); - - if ((var = switch_event_get_header(hdata->var_event, "freetdm_pre_buffer_size"))) { - int tmp = atoi(var); - if (tmp > -1) { - ftdm_channel_command(fchan, FTDM_COMMAND_SET_PRE_BUFFER_SIZE, &tmp); - } - } - - span_id = ftdm_channel_get_span_id(fchan); - chan_id = ftdm_channel_get_id(fchan); - - tech_init(hdata->tech_pvt, hdata->new_session, fchan, caller_data); - - snprintf(name, sizeof(name), "FreeTDM/%u:%u/%s", span_id, chan_id, caller_data->dnis.digits); - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Connect outbound channel %s\n", name); - switch_channel_set_name(channel, name); - switch_channel_set_variable(channel, "freetdm_span_name", ftdm_channel_get_span_name(fchan)); - switch_channel_set_variable_printf(channel, "freetdm_span_number", "%d", span_id); - switch_channel_set_variable_printf(channel, "freetdm_chan_number", "%d", chan_id); - - switch_channel_set_caller_profile(channel, hdata->caller_profile); - hdata->tech_pvt->caller_profile = hdata->caller_profile; - - switch_channel_set_state(channel, CS_INIT); - sess_uuid = switch_core_session_get_uuid(hdata->new_session); - status = ftdm_channel_add_token(fchan, sess_uuid, ftdm_channel_get_token_count(fchan)); - switch_assert(status == FTDM_SUCCESS); - - if (SPAN_CONFIG[span_id].limit_calls) { - char spanresource[512]; - snprintf(spanresource, sizeof(spanresource), "span_%s_%s", ftdm_channel_get_span_name(fchan), - caller_data->dnis.digits); - - ftdm_log(FTDM_LOG_DEBUG, "Adding rate limit resource on channel %d:%d (%s/%s/%d/%d)\n", - span_id, chan_id, FREETDM_LIMIT_REALM, - spanresource, SPAN_CONFIG[span_id].limit_calls, SPAN_CONFIG[span_id].limit_seconds); - - if (switch_limit_incr("hash", hdata->new_session, FREETDM_LIMIT_REALM, spanresource, - SPAN_CONFIG[span_id].limit_calls, SPAN_CONFIG[span_id].limit_seconds) != SWITCH_STATUS_SUCCESS) { - return FTDM_BREAK; - } - } - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Attached session %s to channel %d:%d\n", sess_uuid, span_id, chan_id); - return FTDM_SUCCESS; -} - -/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines -that allocate memory or you will have 1 channel with memory allocated from another channel's pool! -*/ -static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, - switch_caller_profile_t *outbound_profile, - switch_core_session_t **new_session, switch_memory_pool_t **pool, - switch_originate_flag_t flags, switch_call_cause_t *cancel_cause) -{ - hunt_data_t hunt_data; - const char *dest = NULL; - char *data = NULL; - int span_id = -1, group_id = -1, chan_id = 0; - switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; - ftdm_status_t status; - ftdm_hunt_direction_t direction = FTDM_HUNT_BOTTOM_UP; - ftdm_caller_data_t caller_data = {{ 0 }}; - char *span_name = NULL; - switch_event_header_t *h; - char *argv[3]; - int argc = 0; - const char *var; - const char *dest_num = NULL, *callerid_num = NULL; - const char *network_peer_uuid = NULL; - char sigbridge_peer[255]; - switch_channel_t *peer_chan = NULL; - switch_channel_t *our_chan = NULL; - ftdm_hunting_scheme_t hunting; - ftdm_usrmsg_t usrmsg; - - memset(&usrmsg, 0, sizeof(ftdm_usrmsg_t)); - memset(sigbridge_peer, 0, sizeof(sigbridge_peer)); - - if (!outbound_profile) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing caller profile\n"); - return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; - } - - if (zstr(outbound_profile->destination_number)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid dial string\n"); - return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; - } - - - data = switch_core_strdup(outbound_profile->pool, outbound_profile->destination_number); - - if (!zstr(outbound_profile->destination_number)) { - dest_num = switch_sanitize_number(switch_core_strdup(outbound_profile->pool, outbound_profile->destination_number)); - } - - if (!zstr(outbound_profile->caller_id_number)) { - callerid_num = switch_sanitize_number(switch_core_strdup(outbound_profile->pool, outbound_profile->caller_id_number)); - if ( callerid_num && *callerid_num == '+' ) { - callerid_num++; - } - } - - if (!zstr(callerid_num) && !strcmp(callerid_num, SWITCH_DEFAULT_CLID_NUMBER)) { - callerid_num = NULL; - } - - if ((argc = switch_separate_string(data, '/', argv, (sizeof(argv) / sizeof(argv[0])))) < 2) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid dial string\n"); - return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; - } - - if (switch_is_number(argv[0])) { - span_id = atoi(argv[0]); - } else { - span_name = argv[0]; - } - - if (*argv[1] == 'a') { - direction = FTDM_HUNT_BOTTOM_UP; - } else if (*argv[1] == 'A') { - direction = FTDM_HUNT_TOP_DOWN; - } else if (*argv[1] == 'R') { - direction = FTDM_HUNT_RR_DOWN; - } else if (*argv[1] == 'r') { - direction = FTDM_HUNT_RR_UP; - } else { - chan_id = atoi(argv[1]); - } - - if (!(dest = argv[2])) { - dest = ""; - } - - if (span_id == 0 && chan_id != 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Span 0 is used to pick the first available span, selecting a channel is not supported (and doesn't make sense)\n"); - return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; - } - - if (span_id == -1 && !zstr(span_name)) { - ftdm_span_t *span; - ftdm_status_t zstatus = ftdm_span_find_by_name(span_name, &span); - if (zstatus == FTDM_SUCCESS && span) { - span_id = ftdm_span_get_id(span); - } - } - - if (span_id == -1) { - //Look for a group - ftdm_group_t *group; - ftdm_status_t zstatus = ftdm_group_find_by_name(span_name, &group); - if (zstatus == FTDM_SUCCESS && group) { - group_id = ftdm_group_get_id(group); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing ftdm span or group: %s\n", span_name); - return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; - } - } - - if (group_id < 0 && chan_id < 0) { - direction = FTDM_HUNT_BOTTOM_UP; - chan_id = 0; - } - - if (session && globals.sip_headers && !switch_core_session_check_interface (session,freetdm_endpoint_interface) ) { - switch_channel_t *channel = switch_core_session_get_channel(session); - const char *sipvar; - - network_peer_uuid = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-TransUUID"); - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-CallerName"); - if (sipvar) { - ftdm_set_string(caller_data.cid_name, sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-CallerNumber"); - if (sipvar) { - if ( *sipvar == '+' ) { - sipvar++; - } - ftdm_set_string(caller_data.cid_num.digits, sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-ANI"); - if (sipvar) { - ftdm_set_string(caller_data.ani.digits, sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-ANI-TON"); - if (sipvar) { - caller_data.ani.type = (uint8_t)atoi(sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-ANI-Plan"); - if (sipvar) { - caller_data.ani.plan = (uint8_t)atoi(sipvar); - } - - /* Used by ftmod_sangoma_ss7 only */ - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-ANI-NADI"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_clg_nadi", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-ANI2"); - if (sipvar) { - ftdm_set_string(caller_data.aniII, sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-DNIS"); - if (sipvar) { - ftdm_set_string(caller_data.dnis.digits, sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-LOC"); - if (sipvar) { - ftdm_set_string(caller_data.loc.digits, sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-Access-Transport-URLENC"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_access_transport_urlenc", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-LOC-Screen"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_loc_screen_ind", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-LOC-Presentation"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_loc_pres_ind", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-LOC-NADI"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_loc_nadi", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-DNIS-TON"); - if (sipvar) { - caller_data.dnis.type = (uint8_t)atoi(sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-DNIS-Plan"); - if (sipvar) { - caller_data.dnis.plan = (uint8_t)atoi(sipvar); - } - - /* Used by ftmod_sangoma_ss7 only */ - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-DNIS-NADI"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_cld_nadi", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-RDNIS"); - if (sipvar) { - ftdm_set_string(caller_data.rdnis.digits, sipvar); - ftdm_usrmsg_add_var(&usrmsg, "ss7_rdnis_digits", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-RDNIS-Plan"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_rdnis_plan", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-RDNIS-NADI"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_rdnis_nadi", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-RDNIS-Screen"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_rdnis_screen_ind", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-RDNIS-Presentation"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_rdnis_pres_ind", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-GN"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_gn_digits", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-GN-NumQual"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_gn_numqual", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-GN-NADI"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_gn_nadi", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-GN-Screen"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_gn_screen_ind", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-GN-Presentation"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_gn_pres_ind", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-GN-Plan"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_gn_npi", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-GN-NumInComp"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_gn_num_inc_ind", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-Screen"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_screen_ind", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-Presentation"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_pres_ind", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-CPC"); - if (sipvar) { - ftdm_set_calling_party_category(sipvar, (uint8_t *)&caller_data.cpc); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-IAM"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_iam", sipvar); - } - - /* redirection information */ - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-RDINF-Indicator"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_rdinfo_indicator", sipvar); - } - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-RDINF-OrigReason"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_rdinfo_orig", sipvar); - } - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-RDINF-Count"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_rdinfo_count", sipvar); - } - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-RDINF-Reason"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_rdinfo_reason", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-OCN"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_ocn", sipvar); - } - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-OCN-NADI"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_ocn_nadi", sipvar); - } - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-OCN-Plan"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_ocn_plan", sipvar); - } - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-OCN-Presentation"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_ocn_pres", sipvar); - } - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-IAM-FWD-IND-HEX"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_iam_fwd_ind_hex", sipvar); - } - - sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-IAM-NATURE-CONN-HEX"); - if (sipvar) { - ftdm_usrmsg_add_var(&usrmsg, "ss7_iam_nature_connection_hex", sipvar); - } - } - - if (switch_test_flag(outbound_profile, SWITCH_CPF_SCREEN)) { - caller_data.screen = FTDM_SCREENING_VERIFIED_PASSED; - } - - if (switch_test_flag(outbound_profile, SWITCH_CPF_HIDE_NUMBER)) { - caller_data.pres = FTDM_PRES_RESTRICTED; - } - - if ((var = channel_get_variable(session, var_event, "freetdm_iam_fwd_ind_isdn_access_ind"))) { - ftdm_usrmsg_add_var(&usrmsg, "iam_fwd_ind_isdn_access_ind", var); - } - - if ((var = channel_get_variable(session, var_event, "freetdm_bearer_capability"))) { - caller_data.bearer_capability = (uint8_t)atoi(var); - } - - if ((var = channel_get_variable(session, var_event, "freetdm_bearer_layer1"))) { - caller_data.bearer_layer1 = (uint8_t)atoi(var); - } - - if ((var = channel_get_variable(session, var_event, "freetdm_screening_ind"))) { - ftdm_set_screening_ind(var, &caller_data.screen); - } - - if ((var = channel_get_variable(session, var_event, "freetdm_presentation_ind"))) { - ftdm_set_presentation_ind(var, &caller_data.pres); - } - - if ((var = channel_get_variable(session, var_event, "freetdm_outbound_ton"))) { - ftdm_set_ton(var, &caller_data.dnis.type); - } else { - caller_data.dnis.type = outbound_profile->destination_number_ton; - } - - if ((var = channel_get_variable(session, var_event, "freetdm_outbound_npi"))) { - ftdm_set_npi(var, &caller_data.dnis.plan); - } else { - caller_data.dnis.plan = outbound_profile->destination_number_numplan; - } - - if ((var = channel_get_variable(session, var_event, "freetdm_calling_party_category"))) { - ftdm_set_calling_party_category(var, (uint8_t *)&caller_data.cpc); - } - - if (!zstr(dest)) { - ftdm_set_string(caller_data.dnis.digits, dest); - } - - caller_data.dnis.plan = outbound_profile->destination_number_numplan; - - /* blindly copy data from outbound_profile. They will be overwritten - * by calling ftdm_caller_data if needed after */ - caller_data.cid_num.type = outbound_profile->caller_ton; - caller_data.cid_num.plan = outbound_profile->caller_numplan; - caller_data.rdnis.type = outbound_profile->rdnis_ton; - caller_data.rdnis.plan = outbound_profile->rdnis_numplan; - - ftdm_set_string(caller_data.cid_name, outbound_profile->caller_id_name); - ftdm_set_string(caller_data.cid_num.digits, switch_str_nil(callerid_num)); - - memset(&hunting, 0, sizeof(hunting)); - - if (group_id >= 0) { - hunting.mode = FTDM_HUNT_GROUP; - hunting.mode_data.group.group_id = group_id; - hunting.mode_data.group.direction = direction; - } else if (chan_id) { - hunting.mode = FTDM_HUNT_CHAN; - hunting.mode_data.chan.span_id = span_id; - hunting.mode_data.chan.chan_id = chan_id; - } else { - hunting.mode = FTDM_HUNT_SPAN; - hunting.mode_data.span.span_id = span_id; - hunting.mode_data.span.direction = direction; - } - - for (h = var_event->headers; h; h = h->next) { - if (!strncasecmp(h->name, FREETDM_VAR_PREFIX, FREETDM_VAR_PREFIX_LEN)) { - char *v = h->name + FREETDM_VAR_PREFIX_LEN; - if (!zstr(v)) { - if (!strcasecmp(v, "ss7_iam")) { - /* Do not print the value of ss7_iam as it is very long */ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding outbound freetdm variable %s to channel %d:%d\n", v, span_id, chan_id); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding outbound freetdm variable %s=%s to channel %d:%d\n", v, h->value, span_id, chan_id); - } - - ftdm_usrmsg_add_var(&usrmsg, v, h->value); - } - } - } - - if ((*new_session = switch_core_session_request(freetdm_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool)) != 0) { - private_t *tech_pvt; - switch_caller_profile_t *caller_profile; - - switch_core_session_add_stream(*new_session, NULL); - if (!(tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t)))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n"); - switch_core_session_destroy(new_session); - cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; - goto fail; - } - - our_chan = switch_core_session_get_channel(*new_session); - - switch_channel_set_flag(our_chan, CF_AUDIO); - - /* Figure out if there is a native bridge requested through SIP x headers */ - if (network_peer_uuid) { - switch_core_session_t *network_peer = switch_core_session_locate(network_peer_uuid); - if (network_peer) { - const char *my_uuid = switch_core_session_get_uuid(*new_session); - private_t *peer_private = switch_core_session_get_private(network_peer); - peer_chan = switch_core_session_get_channel(network_peer); - switch_set_string(tech_pvt->network_peer_uuid, network_peer_uuid); - switch_set_string(peer_private->network_peer_uuid, my_uuid); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Session %s is network-bridged with %s\n", - my_uuid, network_peer_uuid); - - snprintf(sigbridge_peer, sizeof(sigbridge_peer), "%u:%u", - ftdm_channel_get_span_id(peer_private->ftdmchan), ftdm_channel_get_id(peer_private->ftdmchan)); - switch_core_session_rwunlock(network_peer); - } - /* Figure out if there is a native bridge requested through dial plan variable and the originating channel is also freetdm (not going through SIP) */ - } else if (session - && (var = channel_get_variable(session, var_event, FREETDM_VAR_PREFIX "native_sigbridge")) - && switch_true(var) - && switch_core_session_compare(*new_session, session)) { - private_t *peer_pvt = switch_core_session_get_private(session); - peer_chan = switch_core_session_get_channel(session); - snprintf(sigbridge_peer, sizeof(sigbridge_peer), "%u:%u", - ftdm_channel_get_span_id(peer_pvt->ftdmchan), ftdm_channel_get_id(peer_pvt->ftdmchan)); - } - - caller_profile = switch_caller_profile_clone(*new_session, outbound_profile); - caller_profile->destination_number = switch_core_strdup(caller_profile->pool, switch_str_nil(dest_num)); - caller_profile->caller_id_number = switch_core_strdup(caller_profile->pool, switch_str_nil(callerid_num)); - - hunting.result_cb = on_channel_found; - hunt_data.var_event = var_event; - hunt_data.new_session = *new_session; - hunt_data.caller_profile = caller_profile; - hunt_data.tech_pvt = tech_pvt; - caller_data.priv = &hunt_data; - - if (session && !zstr(sigbridge_peer)) { - peer_chan = switch_core_session_get_channel(session); - ftdm_usrmsg_add_var(&usrmsg, "sigbridge_peer", sigbridge_peer); - } - - if ((status = ftdm_call_place_ex(&caller_data, &hunting, &usrmsg)) != FTDM_SUCCESS) { - if (tech_pvt->read_codec.implementation) { - switch_core_codec_destroy(&tech_pvt->read_codec); - } - - if (tech_pvt->write_codec.implementation) { - switch_core_codec_destroy(&tech_pvt->write_codec); - } - switch_core_session_destroy(new_session); - if (status == FTDM_BREAK || status == FTDM_EBUSY) { - cause = SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION; - } else { - cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; - } - goto fail; - } - - if (our_chan && peer_chan) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, - "Bridging native signaling of channel %s to channel %s\n", - switch_channel_get_name(peer_chan), switch_channel_get_name(our_chan)); - } - - return SWITCH_CAUSE_SUCCESS; - } - -fail: - return cause; -} - -static void ftdm_enable_channel_dtmf(ftdm_channel_t *fchan, switch_channel_t *channel) -{ - if (channel) { - const char *var; - if ((var = switch_channel_get_variable(channel, "freetdm_disable_dtmf"))) { - if (switch_true(var)) { - ftdm_channel_command(fchan, FTDM_COMMAND_DISABLE_DTMF_DETECT, NULL); - ftdm_log(FTDM_LOG_INFO, "DTMF detection disabled in channel %d:%d\n", ftdm_channel_get_span_id(fchan), ftdm_channel_get_id(fchan)); - return; - } - } - /* the variable is not present or has a negative value then proceed to enable DTMF ... */ - } - if (ftdm_channel_command(fchan, FTDM_COMMAND_ENABLE_DTMF_DETECT, NULL) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Failed to enable DTMF detection in channel %d:%d\n", ftdm_channel_get_span_id(fchan), ftdm_channel_get_id(fchan)); - } -} - -ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session_t **sp) -{ - switch_core_session_t *session = NULL; - private_t *tech_pvt = NULL; - switch_channel_t *channel = NULL; - ftdm_iterator_t *iter = NULL; - ftdm_iterator_t *curr = NULL; - const char *var_name = NULL; - const char *var_value = NULL; - uint32_t spanid, chanid; - char name[128]; - ftdm_caller_data_t *channel_caller_data = ftdm_channel_get_caller_data(sigmsg->channel); - - *sp = NULL; - - spanid = ftdm_channel_get_span_id(sigmsg->channel); - chanid = ftdm_channel_get_id(sigmsg->channel); - - if (!(session = switch_core_session_request(freetdm_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, SOF_NONE, NULL))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Initilization Error!\n"); - return FTDM_FAIL; - } - - /* I guess we always want DTMF detection */ - ftdm_enable_channel_dtmf(sigmsg->channel, NULL); - - switch_core_session_add_stream(session, NULL); - - tech_pvt = (private_t *) switch_core_session_alloc(session, sizeof(private_t)); - assert(tech_pvt != NULL); - channel = switch_core_session_get_channel(session); - if (tech_init(tech_pvt, session, sigmsg->channel, channel_caller_data) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Initilization Error!\n"); - switch_core_session_destroy(&session); - return FTDM_FAIL; - } - - switch_channel_set_flag(channel, CF_AUDIO); - - channel_caller_data->collected[0] = '\0'; - - if (zstr(channel_caller_data->cid_name)) { - switch_set_string(channel_caller_data->cid_name, ftdm_channel_get_name(sigmsg->channel)); - } - - if (zstr(channel_caller_data->cid_num.digits)) { - if (!zstr(channel_caller_data->ani.digits)) { - switch_set_string(channel_caller_data->cid_num.digits, channel_caller_data->ani.digits); - } else { - switch_set_string(channel_caller_data->cid_num.digits, ftdm_channel_get_number(sigmsg->channel)); - } - } - - tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session), - "FreeTDM", - SPAN_CONFIG[spanid].dialplan, - channel_caller_data->cid_name, - channel_caller_data->cid_num.digits, - NULL, - channel_caller_data->ani.digits, - channel_caller_data->aniII, - channel_caller_data->rdnis.digits, - (char *)modname, - SPAN_CONFIG[spanid].context, - channel_caller_data->dnis.digits); - - assert(tech_pvt->caller_profile != NULL); - - if (channel_caller_data->screen == 1 || channel_caller_data->screen == 3) { - switch_set_flag(tech_pvt->caller_profile, SWITCH_CPF_SCREEN); - } - - tech_pvt->caller_profile->caller_ton = channel_caller_data->cid_num.type; - tech_pvt->caller_profile->caller_numplan = channel_caller_data->cid_num.plan; - tech_pvt->caller_profile->ani_ton = channel_caller_data->ani.type; - tech_pvt->caller_profile->ani_numplan = channel_caller_data->ani.plan; - tech_pvt->caller_profile->destination_number_ton = channel_caller_data->dnis.type; - tech_pvt->caller_profile->destination_number_numplan = channel_caller_data->dnis.plan; - tech_pvt->caller_profile->rdnis_ton = channel_caller_data->rdnis.type; - tech_pvt->caller_profile->rdnis_numplan = channel_caller_data->rdnis.plan; - - if (channel_caller_data->pres) { - switch_set_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NAME | SWITCH_CPF_HIDE_NUMBER); - } - - snprintf(name, sizeof(name), "FreeTDM/%u:%u/%s", spanid, chanid, tech_pvt->caller_profile->destination_number); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connect inbound channel %s\n", name); - switch_channel_set_name(channel, name); - switch_channel_set_caller_profile(channel, tech_pvt->caller_profile); - - switch_channel_set_variable(channel, "freetdm_span_name", ftdm_channel_get_span_name(sigmsg->channel)); - switch_channel_set_variable_printf(channel, "freetdm_span_number", "%d", spanid); - switch_channel_set_variable_printf(channel, "freetdm_chan_number", "%d", chanid); - switch_channel_set_variable_printf(channel, "freetdm_bearer_capability", "%d", channel_caller_data->bearer_capability); - switch_channel_set_variable_printf(channel, "freetdm_bearer_layer1", "%d", channel_caller_data->bearer_layer1); - switch_channel_set_variable_printf(channel, "freetdm_calling_party_category", ftdm_calling_party_category2str(channel_caller_data->cpc)); - switch_channel_set_variable_printf(channel, "screening_ind", ftdm_screening2str(channel_caller_data->screen)); - switch_channel_set_variable_printf(channel, "presentation_ind", ftdm_presentation2str(channel_caller_data->pres)); - - if (globals.sip_headers) { - switch_channel_set_variable(channel, "sip_h_X-FreeTDM-SpanName", ftdm_channel_get_span_name(sigmsg->channel)); - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-SpanNumber", "%d", spanid); - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-TransUUID", "%s",switch_core_session_get_uuid(session)); - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-SpanNumber", "%d", spanid); - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-ChanNumber", "%d", chanid); - - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-CallerName", "%s", channel_caller_data->cid_name); - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-CallerNumber", "%s", channel_caller_data->cid_num.digits); - - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-ANI", "%s", channel_caller_data->ani.digits); - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-ANI-TON", "%d", channel_caller_data->ani.type); - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-ANI-Plan", "%d", channel_caller_data->ani.plan); - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-ANI2", "%s", channel_caller_data->aniII); - - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-DNIS", "%s", channel_caller_data->dnis.digits); - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-DNIS-TON", "%d", channel_caller_data->dnis.type); - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-DNIS-Plan", "%d", channel_caller_data->dnis.plan); - - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-RDNIS", "%s", channel_caller_data->rdnis.digits); - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-RDNIS-NADI", "%d", channel_caller_data->rdnis.type); - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-RDNIS-Plan", "%d", channel_caller_data->rdnis.plan); - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-CPC", "%s", ftdm_calling_party_category2str(channel_caller_data->cpc)); - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_iam_nature_connection_hex"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-IAM-NATURE-CONN-HEX", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_iam_fwd_ind_hex"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-IAM-FWD-IND-HEX", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_access_transport_urlenc"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-Access-Transport-URLENC", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_rdinfo_indicator"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-RDINF-Indicator", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_rdinfo_orig"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-RDINF-OrigReason", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_rdinfo_count"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-RDINF-Count", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_rdinfo_reason"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-RDINF-Reason", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_clg_nadi"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-NADI", "%s", var_value); - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-ANI-NADI", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_cld_nadi"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-DNIS-NADI", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_rdnis_screen_ind"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-RDNIS-Screen", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_rdnis_pres_ind"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-RDNIS-Presentation", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_gn_digits"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-GN", "%s", var_value); - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_gn_numqual"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-GN-NumQual", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_gn_nadi"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-GN-NADI", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_gn_screen_ind"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-GN-Screen", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_gn_pres_ind"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-GN-Presentation", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_gn_npi"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-GN-Plan", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_gn_num_inc_ind"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-GN-NumInComp", "%s", var_value); - } - } /* End - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_gn_digits"); */ - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_iam"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-IAM", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_cic"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-CIC", "%s", var_value); - } - - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-Screen", "%d", channel_caller_data->screen); - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-Presentation", "%d", channel_caller_data->pres); - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-CallReference", "%d", channel_caller_data->call_reference); - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_opc"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-OPC", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_loc_digits"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-LOC", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_loc_screen_ind"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-LOC-Screen", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_loc_pres_ind"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-LOC-Presentation", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_loc_nadi"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-LOC-NADI", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_ocn"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-OCN", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_ocn_nadi"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-OCN-NADI", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_ocn_plan"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-OCN-Plan", "%s", var_value); - } - - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_ocn_pres"); - if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-OCN-Presentation", "%s", var_value); - } - } - - /* Add any call variable to the dial plan */ - iter = ftdm_sigmsg_get_var_iterator(sigmsg, iter); - for (curr = iter ; curr; curr = ftdm_iterator_next(curr)) { - ftdm_get_current_var(curr, &var_name, &var_value); - snprintf(name, sizeof(name), FREETDM_VAR_PREFIX "%s", var_name); - switch_channel_set_variable_printf(channel, name, "%s", var_value); - if (!strcasecmp(var_name, "ss7_iam")) { - /* Do not print freetdm_ss7_iam as it is a very long variable */ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Call Variable: %s is present\n", name); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Call Variable: %s = %s\n", name, var_value); - } - } - ftdm_iterator_free(iter); - - switch_channel_set_state(channel, CS_INIT); - if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error spawning thread\n"); - switch_core_session_destroy(&session); - return FTDM_FAIL; - } - - if (ftdm_channel_add_token(sigmsg->channel, switch_core_session_get_uuid(session), 0) != FTDM_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error adding token\n"); - switch_core_session_destroy(&session); - return FTDM_FAIL; - } - *sp = session; - - return FTDM_SUCCESS; -} - -static FIO_SIGNAL_CB_FUNCTION(on_common_signal) -{ - uint32_t chanid, spanid; - switch_event_t *event = NULL; - ftdm_alarm_flag_t alarmbits = FTDM_ALARM_NONE; - - chanid = ftdm_channel_get_id(sigmsg->channel); - spanid = ftdm_channel_get_span_id(sigmsg->channel); - - switch (sigmsg->event_id) { - case FTDM_SIGEVENT_SMS: - { - ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(sigmsg->channel); - ftdm_sms_data_t *sms = (ftdm_sms_data_t*) caller_data->priv; - - ftdm_log(FTDM_LOG_INFO, "SMS received on %d:%d from %s: %s", spanid, chanid, sms->from, sms->body); - if (switch_event_create(&event, SWITCH_EVENT_TRAP) != SWITCH_STATUS_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "failed to create SMS event\n"); - return FTDM_FAIL; - } - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", sms->from); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "body", sms->body); - alarmbits = 0; - } - //return FTDM_BREAK; - break; - case FTDM_SIGEVENT_ALARM_CLEAR: - case FTDM_SIGEVENT_ALARM_TRAP: - { - if (ftdm_channel_get_alarms(sigmsg->channel, &alarmbits) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "failed to retrieve alarms\n"); - return FTDM_FAIL; - } - if (switch_event_create(&event, SWITCH_EVENT_TRAP) != SWITCH_STATUS_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "failed to create alarms events\n"); - return FTDM_FAIL; - } - if (sigmsg->event_id == FTDM_SIGEVENT_ALARM_CLEAR) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-clear"); - } else { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-trap"); - } - } - break; - case FTDM_SIGEVENT_UP: - { - /* clear any rate limit resource for this span */ - char spanresource[512]; - if (SPAN_CONFIG[spanid].limit_reset_event == FTDM_LIMIT_RESET_ON_ANSWER && SPAN_CONFIG[spanid].limit_calls) { - ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(sigmsg->channel); - snprintf(spanresource, sizeof(spanresource), "span_%s_%s", ftdm_channel_get_span_name(sigmsg->channel), caller_data->dnis.digits); - ftdm_log(FTDM_LOG_DEBUG, "Clearing rate limit resource on channel %d:%d (%s/%s)\n", spanid, chanid, FREETDM_LIMIT_REALM, spanresource); - switch_limit_interval_reset("hash", FREETDM_LIMIT_REALM, spanresource); - } - return FTDM_SUCCESS; - } - break; - case FTDM_SIGEVENT_TRANSFER_COMPLETED: - { - switch_core_session_t *session = NULL; - switch_channel_t *channel = NULL; - private_t *tech_pvt = NULL; - - if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) { - channel = switch_core_session_get_channel(session); - tech_pvt = switch_core_session_get_private(session); - - switch_clear_flag_locked(tech_pvt, TFLAG_TRANSFER); - switch_channel_set_variable(channel, "freetdm_transfer_response", ftdm_transfer_response2str(sigmsg->ev_data.transfer_completed.response)); - switch_core_session_rwunlock(session); - } - return FTDM_SUCCESS; - } - break; - case FTDM_SIGEVENT_RELEASED: - case FTDM_SIGEVENT_INDICATION_COMPLETED: - case FTDM_SIGEVENT_DIALING: - { - /* Swallow these events */ - return FTDM_BREAK; - } - break; - case FTDM_SIGEVENT_STOP: - case FTDM_SIGEVENT_RESTART: - { - switch_core_session_t *session = NULL; - private_t *tech_pvt = NULL; - while ((session = ftdm_channel_get_session(sigmsg->channel, 0))) { - tech_pvt = switch_core_session_get_private(session); - - switch_clear_flag_locked(tech_pvt, TFLAG_TRANSFER); - switch_core_session_rwunlock(session); - return FTDM_SUCCESS; - } - } - break; - default: - return FTDM_SUCCESS; - break; - } - - if (event) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-name", "%s", ftdm_channel_get_span_name(sigmsg->channel)); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-number", "%d", ftdm_channel_get_span_id(sigmsg->channel)); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "chan-number", "%d", ftdm_channel_get_id(sigmsg->channel)); - - if (alarmbits & FTDM_ALARM_RED) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "red"); - } - if (alarmbits & FTDM_ALARM_YELLOW) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "yellow"); - } - if (alarmbits & FTDM_ALARM_RAI) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "rai"); - } - if (alarmbits & FTDM_ALARM_BLUE) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "blue"); - } - if (alarmbits & FTDM_ALARM_AIS) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "ais"); - } - if (alarmbits & FTDM_ALARM_GENERAL) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "general"); - } - switch_event_fire(&event); - } - - return FTDM_BREAK; -} - -static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal) -{ - switch_core_session_t *session = NULL; - switch_channel_t *channel = NULL; - ftdm_status_t status = FTDM_SUCCESS; - uint32_t spanid; - uint32_t chanid; - ftdm_caller_data_t *caller_data; - - spanid = ftdm_channel_get_span_id(sigmsg->channel); - chanid = ftdm_channel_get_id(sigmsg->channel); - caller_data = ftdm_channel_get_caller_data(sigmsg->channel); - - ftdm_log(FTDM_LOG_DEBUG, "got FXO sig %d:%d [%s]\n", spanid, chanid, ftdm_signal_event2str(sigmsg->event_id)); - - switch (sigmsg->event_id) { - case FTDM_SIGEVENT_PROGRESS_MEDIA: - { - if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) { - channel = switch_core_session_get_channel(session); - switch_channel_mark_pre_answered(channel); - switch_core_session_rwunlock(session); - } - } - break; - case FTDM_SIGEVENT_STOP: - { - private_t *tech_pvt = NULL; - while ((session = ftdm_channel_get_session(sigmsg->channel, 0))) { - tech_pvt = switch_core_session_get_private(session); - switch_set_flag_locked(tech_pvt, TFLAG_DEAD); - ftdm_channel_clear_token(sigmsg->channel, 0); - channel = switch_core_session_get_channel(session); - switch_channel_hangup(channel, caller_data->hangup_cause); - ftdm_channel_clear_token(sigmsg->channel, switch_core_session_get_uuid(session)); - switch_core_session_rwunlock(session); - } - } - break; - case FTDM_SIGEVENT_UP: - { - if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) { - channel = switch_core_session_get_channel(session); - switch_channel_mark_answered(channel); - ftdm_enable_channel_dtmf(sigmsg->channel, channel); - switch_core_session_rwunlock(session); - } - } - break; - case FTDM_SIGEVENT_START: - { - status = ftdm_channel_from_event(sigmsg, &session); - if (status != FTDM_SUCCESS) { - ftdm_channel_call_hangup(sigmsg->channel); - } - } - break; - case FTDM_SIGEVENT_COLLECTED_DIGIT: /* Analog E&M */ - { - int span_id = ftdm_channel_get_span_id(sigmsg->channel); - char *dtmf = sigmsg->ev_data.collected.digits; - char *regex = SPAN_CONFIG[span_id].dial_regex; - char *fail_regex = SPAN_CONFIG[span_id].fail_dial_regex; - ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(sigmsg->channel); - - if (zstr(regex)) { - regex = NULL; - } - - if (zstr(fail_regex)) { - fail_regex = NULL; - } - - ftdm_log(FTDM_LOG_DEBUG, "got DTMF sig [%s]\n", dtmf); - switch_set_string(caller_data->collected, dtmf); - - if ((regex || fail_regex) && !zstr(dtmf)) { - switch_regex_t *re = NULL; - int ovector[30]; - int match = 0; - - if (fail_regex) { - match = switch_regex_perform(dtmf, fail_regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])); - status = match ? FTDM_SUCCESS : FTDM_BREAK; - switch_regex_safe_free(re); - ftdm_log(FTDM_LOG_DEBUG, "DTMF [%s] vs fail regex %s %s\n", dtmf, fail_regex, match ? "matched" : "did not match"); - } - - if (status == FTDM_SUCCESS && regex) { - match = switch_regex_perform(dtmf, regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])); - status = match ? FTDM_BREAK : FTDM_SUCCESS; - switch_regex_safe_free(re); - ftdm_log(FTDM_LOG_DEBUG, "DTMF [%s] vs dial regex %s %s\n", dtmf, regex, match ? "matched" : "did not match"); - } - ftdm_log(FTDM_LOG_DEBUG, "returning %s to COLLECT event with DTMF %s\n", status == FTDM_SUCCESS ? "success" : "break", dtmf); - } - } - break; - case FTDM_SIGEVENT_SIGSTATUS_CHANGED: - /* span signaling status changed ... nothing to do here .. */ - break; - default: - { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled msg type %d for channel %d:%d\n", - sigmsg->event_id, spanid, chanid); - } - break; - } - - return status; -} - -static FIO_SIGNAL_CB_FUNCTION(on_fxs_signal) -{ - switch_core_session_t *session = NULL; - switch_channel_t *channel = NULL; - ftdm_status_t status = FTDM_SUCCESS; - uint32_t chanid, spanid, tokencount; - - chanid = ftdm_channel_get_id(sigmsg->channel); - spanid = ftdm_channel_get_span_id(sigmsg->channel); - tokencount = ftdm_channel_get_token_count(sigmsg->channel); - - ftdm_log(FTDM_LOG_DEBUG, "got FXS sig [%s]\n", ftdm_signal_event2str(sigmsg->event_id)); - - switch (sigmsg->event_id) { - case FTDM_SIGEVENT_UP: - { - if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) { - channel = switch_core_session_get_channel(session); - switch_channel_mark_answered(channel); - ftdm_enable_channel_dtmf(sigmsg->channel, channel); - switch_core_session_rwunlock(session); - } - } - break; - case FTDM_SIGEVENT_PROGRESS: - { - if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) { - channel = switch_core_session_get_channel(session); - switch_channel_mark_ring_ready(channel); - switch_core_session_rwunlock(session); - } - } - break; - case FTDM_SIGEVENT_START: - { - status = ftdm_channel_from_event(sigmsg, &session); - if (status != FTDM_SUCCESS) { - ftdm_channel_call_indicate(sigmsg->channel, FTDM_CHANNEL_INDICATE_BUSY); - } - } - break; - case FTDM_SIGEVENT_STOP: - { - private_t *tech_pvt = NULL; - switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING; - if (tokencount) { - ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(sigmsg->channel); - switch_core_session_t *session_a, *session_b, *session_t = NULL; - switch_channel_t *channel_a = NULL, *channel_b = NULL; - int digits = !zstr(caller_data->collected); - const char *br_a_uuid = NULL, *br_b_uuid = NULL; - private_t *tech_pvt = NULL; - - - if ((session_a = switch_core_session_locate(ftdm_channel_get_token(sigmsg->channel, 0)))) { - channel_a = switch_core_session_get_channel(session_a); - br_a_uuid = switch_channel_get_partner_uuid(channel_a); - - tech_pvt = switch_core_session_get_private(session_a); - stop_hold(session_a, switch_channel_get_partner_uuid(channel_a)); - switch_clear_flag_locked(tech_pvt, TFLAG_HOLD); - } - - if ((session_b = switch_core_session_locate(ftdm_channel_get_token(sigmsg->channel, 1)))) { - channel_b = switch_core_session_get_channel(session_b); - br_b_uuid = switch_channel_get_partner_uuid(channel_b); - - tech_pvt = switch_core_session_get_private(session_b); - stop_hold(session_a, switch_channel_get_partner_uuid(channel_b)); - switch_clear_flag_locked(tech_pvt, TFLAG_HOLD); - } - - if (channel_a && channel_b && switch_channel_direction(channel_a) == SWITCH_CALL_DIRECTION_INBOUND && - switch_channel_direction(channel_b) == SWITCH_CALL_DIRECTION_INBOUND) { - - cause = SWITCH_CAUSE_ATTENDED_TRANSFER; - if (br_a_uuid && br_b_uuid) { - switch_ivr_uuid_bridge(br_a_uuid, br_b_uuid); - } else if (br_a_uuid && digits) { - session_t = switch_core_session_locate(br_a_uuid); - } else if (br_b_uuid && digits) { - session_t = switch_core_session_locate(br_b_uuid); - } - } - - if (session_t) { - switch_ivr_session_transfer(session_t, caller_data->collected, NULL, NULL); - switch_core_session_rwunlock(session_t); - } - - if (session_a) { - switch_core_session_rwunlock(session_a); - } - - if (session_b) { - switch_core_session_rwunlock(session_b); - } - } - - while ((session = ftdm_channel_get_session(sigmsg->channel, 0))) { - tech_pvt = switch_core_session_get_private(session); - switch_set_flag_locked(tech_pvt, TFLAG_DEAD); - channel = switch_core_session_get_channel(session); - switch_channel_hangup(channel, cause); - ftdm_channel_clear_token(sigmsg->channel, switch_core_session_get_uuid(session)); - switch_core_session_rwunlock(session); - } - ftdm_channel_clear_token(sigmsg->channel, NULL); - } - break; - case FTDM_SIGEVENT_ADD_CALL: - { - cycle_foreground(sigmsg->channel, 1, NULL); - } - break; - case FTDM_SIGEVENT_FLASH: - { - chan_pvt_t *chanpvt = ftdm_channel_get_private(sigmsg->channel); - if (!chanpvt) { - ftdm_log(FTDM_LOG_ERROR, "%d:%d has no private data, can't handle FXS features! (this is a bug)\n", - chanid, spanid); - break; - } - if (ftdm_channel_call_check_hold(sigmsg->channel) && tokencount == 1) { - switch_core_session_t *session; - if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) { - const char *buuid; - switch_channel_t *channel; - private_t *tech_pvt; - - tech_pvt = switch_core_session_get_private(session); - channel = switch_core_session_get_channel(session); - buuid = switch_channel_get_partner_uuid(channel); - ftdm_channel_call_unhold(sigmsg->channel); - stop_hold(session, buuid); - switch_clear_flag_locked(tech_pvt, TFLAG_HOLD); - switch_core_session_rwunlock(session); - } - } else if (tokencount == 2 && (SPAN_CONFIG[sigmsg->span_id].analog_options & ANALOG_OPTION_3WAY)) { - if (switch_test_flag(chanpvt, ANALOG_OPTION_3WAY)) { - switch_clear_flag(chanpvt, ANALOG_OPTION_3WAY); - if ((session = ftdm_channel_get_session(sigmsg->channel, 1))) { - channel = switch_core_session_get_channel(session); - switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); - ftdm_channel_clear_token(sigmsg->channel, switch_core_session_get_uuid(session)); - switch_core_session_rwunlock(session); - } - cycle_foreground(sigmsg->channel, 1, NULL); - } else { - char *cmd; - cmd = switch_mprintf("three_way::%s", ftdm_channel_get_token(sigmsg->channel, 0)); - switch_set_flag(chanpvt, ANALOG_OPTION_3WAY); - cycle_foreground(sigmsg->channel, 1, cmd); - free(cmd); - } - } else if ((SPAN_CONFIG[sigmsg->span_id].analog_options & ANALOG_OPTION_CALL_SWAP) - || (SPAN_CONFIG[sigmsg->span_id].analog_options & ANALOG_OPTION_3WAY) - ) { - cycle_foreground(sigmsg->channel, 1, NULL); - if (tokencount == 1) { - ftdm_channel_call_hold(sigmsg->channel); - } - } - } - break; - case FTDM_SIGEVENT_COLLECTED_DIGIT: - { - int span_id = ftdm_channel_get_span_id(sigmsg->channel); - char *dtmf = sigmsg->ev_data.collected.digits; - char *regex = SPAN_CONFIG[span_id].dial_regex; - char *fail_regex = SPAN_CONFIG[span_id].fail_dial_regex; - ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(sigmsg->channel); - - if (zstr(regex)) { - regex = NULL; - } - - if (zstr(fail_regex)) { - fail_regex = NULL; - } - - ftdm_log(FTDM_LOG_DEBUG, "got DTMF sig [%s]\n", dtmf); - switch_set_string(caller_data->collected, dtmf); - - if ((regex || fail_regex) && !zstr(dtmf)) { - switch_regex_t *re = NULL; - int ovector[30]; - int match = 0; - - if (fail_regex) { - match = switch_regex_perform(dtmf, fail_regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])); - status = match ? FTDM_SUCCESS : FTDM_BREAK; - switch_regex_safe_free(re); - ftdm_log(FTDM_LOG_DEBUG, "DTMF [%s] vs fail regex %s %s\n", dtmf, fail_regex, match ? "matched" : "did not match"); - } - - if (status == FTDM_SUCCESS && regex) { - match = switch_regex_perform(dtmf, regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])); - status = match ? FTDM_BREAK : FTDM_SUCCESS; - switch_regex_safe_free(re); - ftdm_log(FTDM_LOG_DEBUG, "DTMF [%s] vs dial regex %s %s\n", dtmf, regex, match ? "matched" : "did not match"); - } - ftdm_log(FTDM_LOG_DEBUG, "returning %s to COLLECT event with DTMF %s\n", status == FTDM_SUCCESS ? "success" : "break", dtmf); - } - } - break; - default: - { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled msg type %d for channel %d:%d\n", - sigmsg->event_id, spanid, chanid); - } - break; - } - - return status; -} - -static FIO_SIGNAL_CB_FUNCTION(on_r2_signal) -{ - uint32_t phyid, chanid, spanid; - switch_core_session_t *session = NULL; - switch_channel_t *channel = NULL; - ftdm_status_t status = FTDM_SUCCESS; - ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(sigmsg->channel); - - phyid = ftdm_channel_get_ph_id(sigmsg->channel); - chanid = ftdm_channel_get_id(sigmsg->channel); - spanid = ftdm_channel_get_span_id(sigmsg->channel); - - ftdm_log(FTDM_LOG_DEBUG, "Got R2 channel sig [%s] in channel %d\n", ftdm_signal_event2str(sigmsg->event_id), phyid); - - if (on_common_signal(sigmsg) == FTDM_BREAK) { - return FTDM_SUCCESS; - } - - switch (sigmsg->event_id) { - case FTDM_SIGEVENT_STOP: /* on_call_disconnect from the R2 side */ - { - private_t *tech_pvt = NULL; - while ((session = ftdm_channel_get_session(sigmsg->channel, 0))) { - tech_pvt = switch_core_session_get_private(session); - switch_set_flag_locked(tech_pvt, TFLAG_DEAD); - channel = switch_core_session_get_channel(session); - switch_channel_hangup(channel, caller_data->hangup_cause); - switch_core_session_rwunlock(session); - } - } - break; - case FTDM_SIGEVENT_START: /* on_call_offered from the R2 side */ - { - status = ftdm_channel_from_event(sigmsg, &session); - } - break; - case FTDM_SIGEVENT_COLLECTED_DIGIT: /* on DNIS received from the R2 forward side, return status == FTDM_BREAK to stop requesting DNIS */ - { - ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(sigmsg->channel); - int span_id = ftdm_channel_get_span_id(sigmsg->channel); - char *regex = SPAN_CONFIG[span_id].dial_regex; - char *fail_regex = SPAN_CONFIG[span_id].fail_dial_regex; - - if (zstr(regex)) { - regex = NULL; - } - - if (zstr(fail_regex)) { - fail_regex = NULL; - } - - ftdm_log(FTDM_LOG_DEBUG, "R2 DNIS so far [%s]\n", caller_data->dnis.digits); - - if ((regex || fail_regex) && !zstr(caller_data->dnis.digits)) { - switch_regex_t *re = NULL; - int ovector[30]; - int match = 0; - - if (fail_regex) { - match = switch_regex_perform(caller_data->dnis.digits, fail_regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])); - status = match ? FTDM_SUCCESS : FTDM_BREAK; - switch_regex_safe_free(re); - } - - if (status == FTDM_SUCCESS && regex) { - match = switch_regex_perform(caller_data->dnis.digits, regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])); - status = match ? FTDM_BREAK : FTDM_SUCCESS; - } - - switch_regex_safe_free(re); - } - } - break; - case FTDM_SIGEVENT_PROGRESS: - { - if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) { - channel = switch_core_session_get_channel(session); - switch_channel_mark_ring_ready(channel); - switch_core_session_rwunlock(session); - } - } - break; - case FTDM_SIGEVENT_PROGRESS_MEDIA: - { - if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) { - channel = switch_core_session_get_channel(session); - switch_channel_mark_pre_answered(channel); - switch_core_session_rwunlock(session); - } - } - break; - case FTDM_SIGEVENT_UP: - { - if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) { - channel = switch_core_session_get_channel(session); - switch_channel_mark_answered(channel); - ftdm_enable_channel_dtmf(sigmsg->channel, channel); - switch_core_session_rwunlock(session); - } - } - break; - case FTDM_SIGEVENT_SIGSTATUS_CHANGED: - { - ftdm_signaling_status_t sigstatus = sigmsg->ev_data.sigstatus.status; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%d:%d signalling changed to: %s\n", - spanid, chanid, ftdm_signaling_status2str(sigstatus)); - } - break; - case FTDM_SIGEVENT_PROCEED: - case FTDM_SIGEVENT_INDICATION_COMPLETED: - break; - default: - { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled event %d from R2 for channel %d:%d\n", - sigmsg->event_id, spanid, chanid); - } - break; - } - - return status; -} - -static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal) -{ - switch_core_session_t *session = NULL; - switch_channel_t *channel = NULL; - ftdm_caller_data_t *caller_data; - uint32_t spanid, chanid; - - ftdm_log(FTDM_LOG_DEBUG, "got clear channel sig [%s]\n", ftdm_signal_event2str(sigmsg->event_id)); - - caller_data = ftdm_channel_get_caller_data(sigmsg->channel); - chanid = ftdm_channel_get_id(sigmsg->channel); - spanid = ftdm_channel_get_span_id(sigmsg->channel); - - if (on_common_signal(sigmsg) == FTDM_BREAK) { - return FTDM_SUCCESS; - } - - switch (sigmsg->event_id) { - case FTDM_SIGEVENT_START: - { - return ftdm_channel_from_event(sigmsg, &session); - } - break; - case FTDM_SIGEVENT_STOP: - case FTDM_SIGEVENT_RESTART: - { - private_t *tech_pvt = NULL; - while ((session = ftdm_channel_get_session(sigmsg->channel, 0))) { - tech_pvt = switch_core_session_get_private(session); - switch_set_flag_locked(tech_pvt, TFLAG_DEAD); - channel = switch_core_session_get_channel(session); - switch_channel_hangup(channel, caller_data->hangup_cause); - switch_core_session_rwunlock(session); - } - } - break; - case FTDM_SIGEVENT_UP: - { - if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) { - channel = switch_core_session_get_channel(session); - switch_channel_mark_answered(channel); - ftdm_enable_channel_dtmf(sigmsg->channel, channel); - switch_core_session_rwunlock(session); - } else { - const char *uuid = ftdm_channel_get_uuid(sigmsg->channel, 0); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session for channel %d:%d not found [UUID: %s]\n", - spanid, chanid, (uuid) ? uuid : "N/A"); - } - } - break; - case FTDM_SIGEVENT_PROGRESS_MEDIA: - { - if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) { - channel = switch_core_session_get_channel(session); - switch_channel_mark_pre_answered(channel); - switch_core_session_rwunlock(session); - } else { - const char *uuid = ftdm_channel_get_uuid(sigmsg->channel, 0); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session for channel %d:%d not found [UUID: %s]\n", - spanid, chanid, (uuid) ? uuid : "N/A"); - } - } - break; - case FTDM_SIGEVENT_PROGRESS: - case FTDM_SIGEVENT_RINGING: - { - if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) { - channel = switch_core_session_get_channel(session); - switch_channel_mark_ring_ready(channel); - switch_core_session_rwunlock(session); - } else { - const char *uuid = ftdm_channel_get_uuid(sigmsg->channel, 0); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session for channel %d:%d not found [UUID: %s]\n", - spanid, chanid, (uuid) ? uuid : "N/A"); - } - } - break; - case FTDM_SIGEVENT_SIGSTATUS_CHANGED: - { - ftdm_signaling_status_t sigstatus = sigmsg->ev_data.sigstatus.status; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%d:%d signalling changed to :%s\n", - spanid, chanid, ftdm_signaling_status2str(sigstatus)); - } - break; - case FTDM_SIGEVENT_PROCEED: - case FTDM_SIGEVENT_FACILITY: - case FTDM_SIGEVENT_TRANSFER_COMPLETED: - /* FS does not have handlers for these messages, so ignore them for now */ - break; - default: - { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled msg type %d for channel %d:%d\n", - sigmsg->event_id, spanid, chanid); - } - break; - } - - return FTDM_SUCCESS; -} - -static FIO_SIGNAL_CB_FUNCTION(on_analog_signal) -{ - uint32_t spanid, chanid; - ftdm_chan_type_t type; - ftdm_status_t status = FTDM_FAIL; - - spanid = ftdm_channel_get_span_id(sigmsg->channel); - chanid = ftdm_channel_get_span_id(sigmsg->channel); - type = ftdm_channel_get_type(sigmsg->channel); - - if (on_common_signal(sigmsg) == FTDM_BREAK) { - return FTDM_SUCCESS; - } - - switch (type) { - case FTDM_CHAN_TYPE_FXO: - case FTDM_CHAN_TYPE_EM: - { - status = on_fxo_signal(sigmsg); - } - break; - case FTDM_CHAN_TYPE_FXS: - { - status = on_fxs_signal(sigmsg); - } - break; - default: - { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled analog channel type %d for channel %d:%d\n", - type, spanid, chanid); - } - break; - } - - return status; -} - -static void ftdm_logger(const char *file, const char *func, int line, int level, const char *fmt, ...) -{ - char *data = NULL; - va_list ap; - - va_start(ap, fmt); - - if (switch_vasprintf(&data, fmt, ap) != -1) { - switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, (char *)func, line, NULL, level, "%s", data); - } - if (data) { - free(data); - } - - va_end(ap); -} - -static uint32_t enable_analog_option(const char *str, uint32_t current_options) -{ - if (!strcasecmp(str, "3-way")) { - current_options |= ANALOG_OPTION_3WAY; - current_options &= ~ANALOG_OPTION_CALL_SWAP; - } else if (!strcasecmp(str, "call-swap")) { - current_options |= ANALOG_OPTION_CALL_SWAP; - current_options &= ~ANALOG_OPTION_3WAY; - } - - return current_options; -} - -#define LOAD_ERROR(...) { \ - ftdm_log(FTDM_LOG_ERROR, __VA_ARGS__); \ - globals.config_error = 1; \ - } - -/* - * Create ftdm_conf_node_t tree based on a fixed pattern XML configuration list. - * Last 2 args are for limited aka dumb recursivity. - */ -static int add_config_list_nodes(switch_xml_t swnode, ftdm_conf_node_t *rootnode, - const char *list_name, const char *list_element_name, - const char *sub_list_name, const char *sub_list_element_name) -{ - char *var, *val; - switch_xml_t list; - switch_xml_t element; - switch_xml_t param; - - ftdm_conf_node_t *n_list; - ftdm_conf_node_t *n_element; - - list = switch_xml_child(swnode, list_name); - if (!list) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no list %s found\n", list_name); - return -1; - } - - if ((FTDM_SUCCESS != ftdm_conf_node_create(list_name, &n_list, rootnode))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create %s node\n", list_name); - return -1; - } - - for (element = switch_xml_child(list, list_element_name); element; element = element->next) { - char *element_name = (char *) switch_xml_attr(element, "name"); - - if (!element_name) { - continue; - } - - if ((FTDM_SUCCESS != ftdm_conf_node_create(list_element_name, &n_element, n_list))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create %s node for %s\n", list_element_name, element_name); - return -1; - } - ftdm_conf_node_add_param(n_element, "name", element_name); - - for (param = switch_xml_child(element, "param"); param; param = param->next) { - var = (char *) switch_xml_attr_soft(param, "name"); - val = (char *) switch_xml_attr_soft(param, "value"); - ftdm_conf_node_add_param(n_element, var, val); - } - - if (sub_list_name && sub_list_element_name) { - if (add_config_list_nodes(element, n_element, sub_list_name, sub_list_element_name, NULL, NULL)) { - return -1; - } - } - } - - return 0; -} - -/* - * Create ftdm_conf_node_t tree based on a fixed pattern XML configuration list. - * Last arg is to specify if we have any sublist for e.g.: - * - * - * - * - * - * - * - * - * - */ -static int add_config_nodes(switch_xml_t swnode, ftdm_conf_node_t *rootnode, - const char *list_name, const char *list_element_name, const char *sub_list_name) -{ - char *var, *val; - switch_xml_t list; - switch_xml_t sub_list; - switch_xml_t element; - switch_xml_t param; - - ftdm_conf_node_t *n_list; - ftdm_conf_node_t *n_element; - - list = switch_xml_child(swnode, list_name); - if (!list) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no list %s found\n", list_name); - return -1; - } - - if ((FTDM_SUCCESS != ftdm_conf_node_create(list_name, &n_list, rootnode))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create %s node\n", list_name); - return -1; - } - - for (element = switch_xml_child(list, list_element_name); element; element = element->next) { - char *element_name = (char *) switch_xml_attr(element, "name"); - - if (!element_name) { - continue; - } - - if ((FTDM_SUCCESS != ftdm_conf_node_create(list_element_name, &n_element, n_list))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create %s node for %s\n", list_element_name, element_name); - return -1; - } - ftdm_conf_node_add_param(n_element, "name", element_name); - - for (param = switch_xml_child(element, "param"); param; param = param->next) { - var = (char *) switch_xml_attr_soft(param, "name"); - val = (char *) switch_xml_attr_soft(param, "value"); - ftdm_conf_node_add_param(n_element, var, val); - } - - /*If we have single node list */ - if (sub_list_name ) { - sub_list = switch_xml_child(element, sub_list_name); - if (!sub_list) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no sub_list %s found\n", sub_list_name); - return -1; - } - for (param = switch_xml_child(sub_list, "param"); param; param = param->next) { - var = (char *) switch_xml_attr_soft(param, "name"); - val = (char *) switch_xml_attr_soft(param, "value"); - ftdm_conf_node_add_param(n_element, var, val); - } - } - } - - return 0; -} - -static ftdm_conf_node_t *_get_ss7_config_node(switch_xml_t cfg, const char *confname, const char *operating_mode) -{ - switch_xml_t signode, ss7configs, isup, gen, param; - ftdm_conf_node_t *rootnode, *list; - char *var, *val; - int is_isup = 0x00; - - /* try to find the conf in the hash first */ - rootnode = switch_core_hash_find(globals.ss7_configs, confname); - if (rootnode) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "ss7 config %s was found in the hash already\n", confname); - return rootnode; - } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "not found %s config in hash, searching in xml ...\n", confname); - - signode = switch_xml_child(cfg, "signaling_configs"); - if (!signode) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "not found 'signaling_configs' XML config section\n"); - return NULL; - } - - ss7configs = switch_xml_child(signode, "sngss7_configs"); - if (!ss7configs) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "not found 'sngss7_configs' XML config section\n"); - return NULL; - } - - /* sng_isup and ss7config xml childs are treated the same way. sng_isup was used initially, but does not make sense - * for configurations that do not have an ISUP layer, sng_isup is kept for backward compatibility */ - - /* search the ss7config */ - for (isup = switch_xml_child(ss7configs, "sngss7_config"); isup; isup = isup->next) { - char *name = (char *) switch_xml_attr(isup, "name"); - if (!name) { - continue; - } - if (!strcasecmp(name, confname)) { - break; - } - } - - if (!isup) { - /* search the isup config */ - for (isup = switch_xml_child(ss7configs, "sng_isup"); isup; isup = isup->next) { - char *name = (char *) switch_xml_attr(isup, "name"); - if (!name) { - continue; - } - if (!strcasecmp(name, confname)) { - break; - } - } - - if (!isup) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "not found '%s' ss7config or sng_isup XML config section\n", confname); - return NULL; - } - } - - /* found our XML chunk, create the root node */ - if ((FTDM_SUCCESS != ftdm_conf_node_create("sng_isup", &rootnode, NULL))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create root node for sng_isup config %s\n", confname); - return NULL; - } - - /* operating mode , M2UA or ISUP */ - if (operating_mode && ('\0' != operating_mode[0])) { - if (!strcasecmp(operating_mode, "ISUP")) { - is_isup = 0x01; - } - else if (!strcasecmp(operating_mode, "M2UA_SG")) { - is_isup = 0x00; - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid operating Mode[%s] \n", operating_mode); - ftdm_conf_node_destroy(rootnode); - return NULL; - } - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Operating mode not specified, default to ISUP \n"); - is_isup = 0x01; - } - - /* add sng_gen */ - gen = switch_xml_child(isup, "sng_gen"); - if (gen == NULL) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process sng_gen for sng_isup config %s\n", confname); - ftdm_conf_node_destroy(rootnode); - return NULL; - } - - if ((FTDM_SUCCESS != ftdm_conf_node_create("sng_gen", &list, rootnode))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create %s node for %s\n", "sng_gen", confname); - ftdm_conf_node_destroy(rootnode); - return NULL; - } - - for (param = switch_xml_child(gen, "param"); param; param = param->next) { - var = (char *) switch_xml_attr_soft(param, "name"); - val = (char *) switch_xml_attr_soft(param, "value"); - ftdm_conf_node_add_param(list, var, val); - } - - /* add relay channels */ - if (add_config_list_nodes(isup, rootnode, "sng_relay", "relay_channel", NULL, NULL)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process sng_relay for sng_isup config %s\n", confname); - ftdm_conf_node_destroy(rootnode); - return NULL; - } - - /* add mtp1 links */ - if (add_config_list_nodes(isup, rootnode, "mtp1_links", "mtp1_link", NULL, NULL)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process mtp1_links for sng_isup config %s\n", confname); - ftdm_conf_node_destroy(rootnode); - return NULL; - } - - /* add mtp2 links */ - if (add_config_list_nodes(isup, rootnode, "mtp2_links", "mtp2_link", NULL, NULL)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process mtp2_links for sng_isup config %s\n", confname); - ftdm_conf_node_destroy(rootnode); - return NULL; - } - - if (is_isup) { - /* add mtp3 links */ - if (add_config_list_nodes(isup, rootnode, "mtp3_links", "mtp3_link", NULL, NULL)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process mtp3_links for sng_isup config %s\n", confname); - ftdm_conf_node_destroy(rootnode); - return NULL; - } - - /* add mtp linksets */ - if (add_config_list_nodes(isup, rootnode, "mtp_linksets", "mtp_linkset", NULL, NULL)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process mtp_linksets for sng_isup config %s\n", confname); - ftdm_conf_node_destroy(rootnode); - return NULL; - } - - /* add mtp routes */ - if (add_config_list_nodes(isup, rootnode, "mtp_routes", "mtp_route", "linksets", "linkset")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process mtp_routes for sng_isup config %s\n", confname); - ftdm_conf_node_destroy(rootnode); - return NULL; - } - - /* add isup interfaces */ - if (add_config_list_nodes(isup, rootnode, "isup_interfaces", "isup_interface", NULL, NULL)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process isup_interfaces for sng_isup config %s\n", confname); - ftdm_conf_node_destroy(rootnode); - return NULL; - } - - /* add cc spans */ - if (add_config_list_nodes(isup, rootnode, "cc_spans", "cc_span", NULL, NULL)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process cc_spans for sng_isup config %s\n", confname); - ftdm_conf_node_destroy(rootnode); - return NULL; - } - } else { - /* add sctp links */ - if (add_config_nodes(isup, rootnode, "sng_sctp_interfaces", "sng_sctp_interface", "sng_source_addresses")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process sng_sctp_interface for sng_isup config %s\n", confname); - ftdm_conf_node_destroy(rootnode); - return NULL; - } - - if (add_config_list_nodes(isup, rootnode, "sng_nif_interfaces", "sng_nif_interface", NULL, NULL)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process sng_nif_interfaces for sng_isup config %s\n", confname); - ftdm_conf_node_destroy(rootnode); - return NULL; - } - - if (add_config_list_nodes(isup, rootnode, "sng_m2ua_interfaces", "sng_m2ua_interface", NULL, NULL)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process sng_m2ua_interfaces for sng_isup config %s\n", confname); - ftdm_conf_node_destroy(rootnode); - return NULL; - } - - if (add_config_nodes(isup, rootnode, "sng_m2ua_peer_interfaces", "sng_m2ua_peer_interface", "sng_destination_addresses")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process sng_m2ua_peer_interfaces for sng_isup config %s\n", confname); - ftdm_conf_node_destroy(rootnode); - return NULL; - } - - if (add_config_nodes(isup, rootnode, "sng_m2ua_cluster_interfaces", "sng_m2ua_cluster_interface", "sng_m2ua_peers")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process sng_m2ua_cluster_interfaces for sng_isup config %s\n", confname); - ftdm_conf_node_destroy(rootnode); - return NULL; - } - } - - switch_core_hash_insert(globals.ss7_configs, confname, rootnode); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Added SS7 node configuration %s\n", confname); - return rootnode; -} - -static int add_profile_parameters(switch_xml_t cfg, const char *profname, ftdm_conf_parameter_t *parameters, int len) -{ - switch_xml_t profnode, profile, param; - int paramindex = 0; - - profnode = switch_xml_child(cfg, "config_profiles"); - if (!profnode) { - LOAD_ERROR("cannot find profile '%s', there is no 'config_profiles' XML section\n", profname); - return 0; - } - - /* search the profile */ - for (profile = switch_xml_child(profnode, "profile"); profile; profile = profile->next) { - char *name = (char *) switch_xml_attr(profile, "name"); - if (!name) { - continue; - } - if (!strcasecmp(name, profname)) { - break; - } - } - - if (!profile) { - LOAD_ERROR("failed to find profile '%s'\n", profname); - return 0; - } - - for (param = switch_xml_child(profile, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - if (!var || !val) { - continue; - } - parameters[paramindex].var = var; - parameters[paramindex].val = val; - paramindex++; - } - - return paramindex; -} - -static void parse_gsm_spans(switch_xml_t cfg, switch_xml_t spans) -{ - switch_xml_t myspan, param; - - for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) { - ftdm_status_t zstatus = FTDM_FAIL; - const char *context = "default"; - const char *dialplan = "XML"; - ftdm_conf_parameter_t spanparameters[FTDM_MAX_SIG_PARAMETERS]; - char *id = (char *) switch_xml_attr(myspan, "id"); - char *name = (char *) switch_xml_attr(myspan, "name"); - char *configname = (char *) switch_xml_attr(myspan, "cfgprofile"); - ftdm_span_t *span = NULL; - uint32_t span_id = 0; - unsigned paramindex = 0; - - if (!name && !id) { - LOAD_ERROR("GSM span missing required attribute 'id' or 'name', skipping ...\n"); - continue; - } - - if (name) { - zstatus = ftdm_span_find_by_name(name, &span); - } else { - if (switch_is_number(id)) { - span_id = atoi(id); - zstatus = ftdm_span_find(span_id, &span); - } - - if (zstatus != FTDM_SUCCESS) { - zstatus = ftdm_span_find_by_name(id, &span); - } - } - - if (zstatus != FTDM_SUCCESS) { - LOAD_ERROR("Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name)); - continue; - } - - if (!span_id) { - span_id = ftdm_span_get_id(span); - } - - memset(spanparameters, 0, sizeof(spanparameters)); - paramindex = 0; - - if (configname) { - paramindex = add_profile_parameters(cfg, configname, spanparameters, ftdm_array_len(spanparameters)); - if (paramindex) { - ftdm_log(FTDM_LOG_DEBUG, "Added %d parameters from profile %s for span %d\n", paramindex, configname, span_id); - } - } - - for (param = switch_xml_child(myspan, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - - if (ftdm_array_len(spanparameters) - 1 == paramindex) { - LOAD_ERROR("Too many parameters for GSM span, ignoring any parameter after %s\n", var); - break; - } - - if (!strcasecmp(var, "context")) { - context = val; - } else if (!strcasecmp(var, "dialplan")) { - dialplan = val; - } else { - spanparameters[paramindex].var = var; - spanparameters[paramindex].val = val; - paramindex++; - } - } - - if (ftdm_configure_span_signaling(span, - "gsm", - on_clear_channel_signal, - spanparameters) != FTDM_SUCCESS) { - LOAD_ERROR("Error configuring Sangoma GSM FreeTDM span %d\n", span_id); - continue; - } - - SPAN_CONFIG[span_id].span = span; - switch_copy_string(SPAN_CONFIG[span_id].context, context, sizeof(SPAN_CONFIG[span_id].context)); - switch_copy_string(SPAN_CONFIG[span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span_id].dialplan)); - switch_copy_string(SPAN_CONFIG[span_id].type, "GSM", sizeof(SPAN_CONFIG[span_id].type)); - - ftdm_log(FTDM_LOG_DEBUG, "Configured GSM FreeTDM span %d\n", span_id); - ftdm_span_start(span); - } -} - -static void parse_bri_pri_spans(switch_xml_t cfg, switch_xml_t spans) -{ - switch_xml_t myspan, param; - - for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) { - ftdm_status_t zstatus = FTDM_FAIL; - const char *context = "default"; - const char *dialplan = "XML"; - ftdm_conf_parameter_t spanparameters[FTDM_MAX_SIG_PARAMETERS]; - char *id = (char *) switch_xml_attr(myspan, "id"); - char *name = (char *) switch_xml_attr(myspan, "name"); - char *configname = (char *) switch_xml_attr(myspan, "cfgprofile"); - ftdm_span_t *span = NULL; - uint32_t span_id = 0; - unsigned paramindex = 0; - - if (!name && !id) { - LOAD_ERROR("sangoma isdn span missing required attribute 'id' or 'name', skipping ...\n"); - continue; - } - - if (name) { - zstatus = ftdm_span_find_by_name(name, &span); - } else { - if (switch_is_number(id)) { - span_id = atoi(id); - zstatus = ftdm_span_find(span_id, &span); - } - - if (zstatus != FTDM_SUCCESS) { - zstatus = ftdm_span_find_by_name(id, &span); - } - } - - if (zstatus != FTDM_SUCCESS) { - LOAD_ERROR("Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name)); - continue; - } - - if (!span_id) { - span_id = ftdm_span_get_id(span); - } - - memset(spanparameters, 0, sizeof(spanparameters)); - paramindex = 0; - - if (configname) { - paramindex = add_profile_parameters(cfg, configname, spanparameters, ftdm_array_len(spanparameters)); - if (paramindex) { - ftdm_log(FTDM_LOG_DEBUG, "Added %d parameters from profile %s for span %d\n", paramindex, configname, span_id); - } - } - - /* some defaults first */ - SPAN_CONFIG[span_id].limit_backend = "hash"; - SPAN_CONFIG[span_id].limit_reset_event = FTDM_LIMIT_RESET_ON_TIMEOUT; - SPAN_CONFIG[span_id].digital_sampling_rate = 8000; - - for (param = switch_xml_child(myspan, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - - if (ftdm_array_len(spanparameters) - 1 == paramindex) { - LOAD_ERROR("Too many parameters for ss7 span, ignoring any parameter after %s\n", var); - break; - } - - if (!strcasecmp(var, "context")) { - context = val; - } else if (!strcasecmp(var, "dialplan")) { - dialplan = val; - } else if (!strcasecmp(var, "unrestricted-digital-codec")) { - //switch_core_strdup(pool, val); - const switch_codec_implementation_t *codec = NULL; - int num_codecs; - num_codecs = switch_loadable_module_get_codecs_sorted(&codec, NULL, 1, &val, 1); - if (num_codecs != 1 || !codec) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, - "Failed finding codec %s for unrestricted digital calls\n", val); - } else { - SPAN_CONFIG[span_id].digital_codec = switch_core_strdup(module_pool, codec->iananame); - SPAN_CONFIG[span_id].digital_sampling_rate = codec->samples_per_second; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, - "Unrestricted digital codec is %s at %dhz for span %d\n", - SPAN_CONFIG[span_id].digital_codec, SPAN_CONFIG[span_id].digital_sampling_rate, span_id); - } - } else if (!strcasecmp(var, "call_limit_backend")) { - SPAN_CONFIG[span_id].limit_backend = val; - ftdm_log(FTDM_LOG_DEBUG, "Using limit backend %s for span %d\n", SPAN_CONFIG[span_id].limit_backend, span_id); - } else if (!strcasecmp(var, "call_limit_rate")) { - int calls; - int seconds; - if (sscanf(val, "%d/%d", &calls, &seconds) != 2) { - LOAD_ERROR("Invalid %s parameter, format example: 3/1 for 3 calls per second\n", var); - } else { - if (calls < 1 || seconds < 1) { - LOAD_ERROR("Invalid %s parameter value, minimum call limit must be 1 per second\n", var); - } else { - SPAN_CONFIG[span_id].limit_calls = calls; - SPAN_CONFIG[span_id].limit_seconds = seconds; - } - } - } else if (!strcasecmp(var, "call_limit_reset_event")) { - if (!strcasecmp(val, "answer")) { - SPAN_CONFIG[span_id].limit_reset_event = FTDM_LIMIT_RESET_ON_ANSWER; - } else { - LOAD_ERROR("Invalid %s parameter value, only accepted event is 'answer'\n", var); - } - } else { - spanparameters[paramindex].var = var; - spanparameters[paramindex].val = val; - paramindex++; - } - } - - if (ftdm_configure_span_signaling(span, - "sangoma_isdn", - on_clear_channel_signal, - spanparameters) != FTDM_SUCCESS) { - LOAD_ERROR("Error configuring Sangoma ISDN FreeTDM span %d\n", span_id); - continue; - } - - SPAN_CONFIG[span_id].span = span; - switch_copy_string(SPAN_CONFIG[span_id].context, context, sizeof(SPAN_CONFIG[span_id].context)); - switch_copy_string(SPAN_CONFIG[span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span_id].dialplan)); - switch_copy_string(SPAN_CONFIG[span_id].type, "Sangoma (ISDN)", sizeof(SPAN_CONFIG[span_id].type)); - - ftdm_log(FTDM_LOG_DEBUG, "Configured Sangoma ISDN FreeTDM span %d\n", span_id); - ftdm_span_start(span); - } -} -static switch_status_t load_config_path(void) -{ - const char *cf = "freetdm.conf"; - switch_xml_t cfg, xml, settings, param; - if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf); - return SWITCH_STATUS_TERM; - } - - if ((settings = switch_xml_child(cfg, "settings"))) { - for (param = switch_xml_child(settings, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - - if (!strcasecmp(var, "mod-dir")) { - ftdm_global_set_mod_directory(val); - } else if (!strcasecmp(var, "conf-dir")) { - ftdm_global_set_config_directory(val); - } - } - } - - switch_xml_free(xml); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t load_config(void) -{ - const char *cf = "freetdm.conf"; - switch_xml_t cfg, xml, settings, param, spans, myspan; - ftdm_conf_node_t *ss7confnode = NULL; - unsigned int i = 0; - ftdm_channel_t *fchan = NULL; - ftdm_iterator_t *chaniter = NULL; - ftdm_iterator_t *curr = NULL; - - memset(&globals, 0, sizeof(globals)); - switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, module_pool); - - if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf); - return SWITCH_STATUS_TERM; - } - - if ((settings = switch_xml_child(cfg, "settings"))) { - for (param = switch_xml_child(settings, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - - if (!strcasecmp(var, "debug")) { - globals.debug = atoi(val); - } else if (!strcasecmp(var, "hold-music")) { - switch_set_string(globals.hold_music, val); - } else if (!strcasecmp(var, "crash-on-assert")) { - globals.crash_on_assert = (uint8_t)switch_true(val); - } else if (!strcasecmp(var, "fail-on-error")) { - globals.fail_on_error = (uint8_t)switch_true(val); - } else if (!strcasecmp(var, "sip-headers")) { - globals.sip_headers = switch_true(val); - } else if (!strcasecmp(var, "enable-analog-option")) { - globals.analog_options = enable_analog_option(val, globals.analog_options); - } - } - } - - if ((spans = switch_xml_child(cfg, "sangoma_pri_spans"))) { - parse_bri_pri_spans(cfg, spans); - } - - if ((spans = switch_xml_child(cfg, "sangoma_bri_spans"))) { - parse_bri_pri_spans(cfg, spans); - } - - if ((spans = switch_xml_child(cfg, "gsm_spans"))) { - parse_gsm_spans(cfg, spans); - } - - switch_core_hash_init(&globals.ss7_configs); - if ((spans = switch_xml_child(cfg, "sangoma_ss7_spans"))) { - for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) { - ftdm_status_t zstatus = FTDM_FAIL; - const char *context = "default"; - const char *dialplan = "XML"; - ftdm_conf_parameter_t spanparameters[FTDM_MAX_SIG_PARAMETERS]; - char *id = (char *) switch_xml_attr(myspan, "id"); - char *name = (char *) switch_xml_attr(myspan, "name"); - char *configname = (char *) switch_xml_attr(myspan, "cfgprofile"); - char *operating_mode = (char *) switch_xml_attr(myspan, "operating_mode"); - ftdm_span_t *span = NULL; - uint32_t span_id = 0; - unsigned paramindex = 0; - if (!name && !id) { - LOAD_ERROR("ss7 span missing required attribute 'id' or 'name', skipping ...\n"); - continue; - } - if (!configname) { - LOAD_ERROR("ss7 span missing required attribute, skipping ...\n"); - continue; - } - if (name) { - zstatus = ftdm_span_find_by_name(name, &span); - } else { - if (switch_is_number(id)) { - span_id = atoi(id); - zstatus = ftdm_span_find(span_id, &span); - } - - if (zstatus != FTDM_SUCCESS) { - zstatus = ftdm_span_find_by_name(id, &span); - } - } - - if (zstatus != FTDM_SUCCESS) { - LOAD_ERROR("Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name)); - continue; - } - - if (!span_id) { - span_id = ftdm_span_get_id(span); - } - - ss7confnode = _get_ss7_config_node(cfg, configname, operating_mode); - if (!ss7confnode) { - LOAD_ERROR("Error finding ss7config '%s' for FreeTDM span id: %s\n", configname, switch_str_nil(id)); - continue; - } - - memset(spanparameters, 0, sizeof(spanparameters)); - paramindex = 0; - - if (operating_mode) { - spanparameters[paramindex].var = "operating-mode"; - spanparameters[paramindex].val = operating_mode; - paramindex++; - } - - spanparameters[paramindex].var = "confnode"; - spanparameters[paramindex].ptr = ss7confnode; - paramindex++; - - for (param = switch_xml_child(myspan, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - - if (ftdm_array_len(spanparameters) - 1 == paramindex) { - LOAD_ERROR("Too many parameters for ss7 span, ignoring any parameter after %s\n", var); - break; - } - - if (!strcasecmp(var, "context")) { - context = val; - } else if (!strcasecmp(var, "dialplan")) { - dialplan = val; - } else { - spanparameters[paramindex].var = var; - spanparameters[paramindex].val = val; - paramindex++; - } - } - - if (ftdm_configure_span_signaling(span, - "sangoma_ss7", - on_clear_channel_signal, - spanparameters) != FTDM_SUCCESS) { - LOAD_ERROR("Error configuring ss7 FreeTDM span %d\n", span_id); - continue; - } - - SPAN_CONFIG[span_id].span = span; - - switch_copy_string(SPAN_CONFIG[span_id].context, context, sizeof(SPAN_CONFIG[span_id].context)); - switch_copy_string(SPAN_CONFIG[span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span_id].dialplan)); - switch_copy_string(SPAN_CONFIG[span_id].type, "Sangoma (SS7)", sizeof(SPAN_CONFIG[span_id].type)); - - ftdm_log(FTDM_LOG_DEBUG, "Configured ss7 FreeTDM span %d with config node %s\n", span_id, configname); - - if (FTDM_SUCCESS != ftdm_span_start(span)) { - LOAD_ERROR("Error Starting ss7 FreeTDM span %d\n", span_id); - continue; - } - } - } - - if ((spans = switch_xml_child(cfg, "analog_spans"))) { - for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) { - char *id = (char *) switch_xml_attr(myspan, "id"); - char *name = (char *) switch_xml_attr(myspan, "name"); - ftdm_status_t zstatus = FTDM_FAIL; - const char *context = "default"; - const char *dialplan = "XML"; - const char *tonegroup = NULL; - char *digit_timeout = NULL; - char *max_digits = NULL; - char *hotline = NULL; - char *dial_regex = NULL; - char *hold_music = NULL; - char *fail_dial_regex = NULL; - const char *enable_callerid = "true"; - const char *answer_polarity = "false"; - const char *hangup_polarity = "false"; - const char *polarity_callerid = "false"; - int polarity_delay = 600; - int callwaiting = 1; - int dialtone_timeout = 5000; - - uint32_t span_id = 0, to = 0, max = 0; - ftdm_span_t *span = NULL; - analog_option_t analog_options = ANALOG_OPTION_NONE; - - if (name) { - zstatus = ftdm_span_find_by_name(name, &span); - } else { - if (switch_is_number(id)) { - span_id = atoi(id); - zstatus = ftdm_span_find(span_id, &span); - } - - if (zstatus != FTDM_SUCCESS) { - zstatus = ftdm_span_find_by_name(id, &span); - } - } - - if (zstatus != FTDM_SUCCESS) { - LOAD_ERROR("Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name)); - continue; - } - - if (!span_id) { - span_id = ftdm_span_get_id(span); - } - - /* some defaults first */ - SPAN_CONFIG[span_id].limit_backend = "hash"; - SPAN_CONFIG[span_id].limit_reset_event = FTDM_LIMIT_RESET_ON_TIMEOUT; - - for (param = switch_xml_child(myspan, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "analog_spans var = %s\n", var); - if (!strcasecmp(var, "tonegroup")) { - tonegroup = val; - } else if (!strcasecmp(var, "digit_timeout") || !strcasecmp(var, "digit-timeout")) { - digit_timeout = val; - } else if (!strcasecmp(var, "wait-dialtone-timeout")) { - dialtone_timeout = atoi(val); - } else if (!strcasecmp(var, "context")) { - context = val; - } else if (!strcasecmp(var, "dialplan")) { - dialplan = val; - } else if (!strcasecmp(var, "call_limit_backend")) { - SPAN_CONFIG[span_id].limit_backend = val; - ftdm_log(FTDM_LOG_DEBUG, "Using limit backend %s for span %d\n", SPAN_CONFIG[span_id].limit_backend, span_id); - } else if (!strcasecmp(var, "call_limit_rate")) { - int calls; - int seconds; - if (sscanf(val, "%d/%d", &calls, &seconds) != 2) { - LOAD_ERROR("Invalid %s parameter, format example: 3/1 for 3 calls per second\n", var); - } else { - if (calls < 1 || seconds < 1) { - LOAD_ERROR("Invalid %s parameter value, minimum call limit must be 1 per second\n", var); - } else { - SPAN_CONFIG[span_id].limit_calls = calls; - SPAN_CONFIG[span_id].limit_seconds = seconds; - } - } - } else if (!strcasecmp(var, "call_limit_reset_event")) { - if (!strcasecmp(val, "answer")) { - SPAN_CONFIG[span_id].limit_reset_event = FTDM_LIMIT_RESET_ON_ANSWER; - } else { - LOAD_ERROR("Invalid %s parameter value, only accepted event is 'answer'\n", var); - } - } else if (!strcasecmp(var, "dial-regex")) { - dial_regex = val; - } else if (!strcasecmp(var, "enable-callerid")) { - enable_callerid = val; - } else if (!strcasecmp(var, "answer-polarity-reverse")) { - answer_polarity = val; - } else if (!strcasecmp(var, "hangup-polarity-reverse")) { - hangup_polarity = val; - } else if (!strcasecmp(var, "polarity-delay")) { - polarity_delay = atoi(val); - } else if (!strcasecmp(var, "polarity-callerid")) { - polarity_callerid = val; - } else if (!strcasecmp(var, "fail-dial-regex")) { - fail_dial_regex = val; - } else if (!strcasecmp(var, "hold-music")) { - hold_music = val; - } else if (!strcasecmp(var, "max_digits") || !strcasecmp(var, "max-digits")) { - max_digits = val; - } else if (!strcasecmp(var, "hotline")) { - hotline = val; - } else if (!strcasecmp(var, "callwaiting")) { - callwaiting = switch_true(val) ? 1 : 0; - } else if (!strcasecmp(var, "enable-analog-option")) { - analog_options = enable_analog_option(val, analog_options); - } - } - - if (!id && !name) { - LOAD_ERROR("span missing required param 'id'\n"); - continue; - } - - if (!tonegroup) { - tonegroup = "us"; - } - - if (digit_timeout) { - to = atoi(digit_timeout); - } - - if (max_digits) { - max = atoi(max_digits); - } - - if (name) { - zstatus = ftdm_span_find_by_name(name, &span); - } else { - if (switch_is_number(id)) { - span_id = atoi(id); - zstatus = ftdm_span_find(span_id, &span); - } - - if (zstatus != FTDM_SUCCESS) { - zstatus = ftdm_span_find_by_name(id, &span); - } - } - - if (zstatus != FTDM_SUCCESS) { - LOAD_ERROR("Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name)); - continue; - } - - if (!span_id) { - span_id = ftdm_span_get_id(span); - } - - if (ftdm_configure_span(span, "analog", on_analog_signal, - "tonemap", tonegroup, - "digit_timeout", &to, - "max_dialstr", &max, - "hotline", hotline ? hotline : "", - "enable_callerid", enable_callerid, - "answer_polarity_reverse", answer_polarity, - "hangup_polarity_reverse", hangup_polarity, - "polarity_callerid", polarity_callerid, - "polarity_delay", &polarity_delay, - "callwaiting", &callwaiting, - "wait_dialtone_timeout", &dialtone_timeout, - FTDM_TAG_END) != FTDM_SUCCESS) { - LOAD_ERROR("Error configuring FreeTDM analog span %s\n", ftdm_span_get_name(span)); - continue; - } - - SPAN_CONFIG[span_id].span = span; - switch_set_string(SPAN_CONFIG[span_id].context, context); - switch_set_string(SPAN_CONFIG[span_id].dialplan, dialplan); - SPAN_CONFIG[span_id].analog_options = analog_options | globals.analog_options; - - chaniter = ftdm_span_get_chan_iterator(span, NULL); - for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { - fchan = ftdm_iterator_current(curr); - ftdm_channel_set_private(fchan, &SPAN_CONFIG[span_id].pvts[i]); - } - ftdm_iterator_free(chaniter); - - if (dial_regex) { - switch_set_string(SPAN_CONFIG[span_id].dial_regex, dial_regex); - } - - if (fail_dial_regex) { - switch_set_string(SPAN_CONFIG[span_id].fail_dial_regex, fail_dial_regex); - } - - if (hold_music) { - switch_set_string(SPAN_CONFIG[span_id].hold_music, hold_music); - } - switch_copy_string(SPAN_CONFIG[span_id].type, "analog", sizeof(SPAN_CONFIG[span_id].type)); - ftdm_span_start(span); - } - } - - if ((spans = switch_xml_child(cfg, "analog_em_spans"))) { - for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) { - char *id = (char *) switch_xml_attr(myspan, "id"); - char *name = (char *) switch_xml_attr(myspan, "name"); - ftdm_status_t zstatus = FTDM_FAIL; - const char *context = "default"; - const char *dialplan = "XML"; - const char *tonegroup = NULL; - char *digit_timeout = NULL; - char *dial_timeout = NULL; - char *release_guard_time_ms = NULL; - char *max_digits = NULL; - char *dial_regex = NULL; - char *hold_music = NULL; - char *fail_dial_regex = NULL; - char str_false[] = "false"; - char str_empty[] = ""; - char *answer_supervision = str_false; - char *immediate_ringback = str_false; - char *ringback_file = str_empty; - uint32_t span_id = 0, to = 0, max = 0, dial_timeout_int = 0, release_guard_time_ms_int = 0; - ftdm_span_t *span = NULL; - analog_option_t analog_options = ANALOG_OPTION_NONE; - - for (param = switch_xml_child(myspan, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - - if (!strcasecmp(var, "tonegroup")) { - tonegroup = val; - } else if (!strcasecmp(var, "digit_timeout") || !strcasecmp(var, "digit-timeout")) { - digit_timeout = val; - } else if (!strcasecmp(var, "dial-timeout")) { - dial_timeout = val; - } else if (!strcasecmp(var, "release-guard-time-ms")) { - release_guard_time_ms = val; - } else if (!strcasecmp(var, "context")) { - context = val; - } else if (!strcasecmp(var, "dialplan")) { - dialplan = val; - } else if (!strcasecmp(var, "dial-regex")) { - dial_regex = val; - } else if (!strcasecmp(var, "fail-dial-regex")) { - fail_dial_regex = val; - } else if (!strcasecmp(var, "hold-music")) { - hold_music = val; - } else if (!strcasecmp(var, "max_digits") || !strcasecmp(var, "max-digits")) { - max_digits = val; - } else if (!strcasecmp(var, "answer-supervision")) { - answer_supervision = val; - } else if (!strcasecmp(var, "immediate-ringback")) { - immediate_ringback = val; - } else if (!strcasecmp(var, "ringback-file")) { - ringback_file = val; - } else if (!strcasecmp(var, "enable-analog-option")) { - analog_options = enable_analog_option(val, analog_options); - } - } - - if (!id && !name) { - LOAD_ERROR("span missing required param 'id'\n"); - continue; - } - - if (!tonegroup) { - tonegroup = "us"; - } - - if (digit_timeout) { - to = atoi(digit_timeout); - } - - if (dial_timeout) { - dial_timeout_int = atoi(dial_timeout); - } - - if (release_guard_time_ms) { - release_guard_time_ms_int = atoi(release_guard_time_ms); - } - - if (max_digits) { - max = atoi(max_digits); - } - - - if (name) { - zstatus = ftdm_span_find_by_name(name, &span); - } else { - if (switch_is_number(id)) { - span_id = atoi(id); - zstatus = ftdm_span_find(span_id, &span); - } - - if (zstatus != FTDM_SUCCESS) { - zstatus = ftdm_span_find_by_name(id, &span); - } - } - - if (zstatus != FTDM_SUCCESS) { - LOAD_ERROR("Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name)); - continue; - } - - if (!span_id) { - span_id = ftdm_span_get_id(span); - } - - - if (ftdm_configure_span(span, "analog_em", on_analog_signal, - "tonemap", tonegroup, - "answer_supervision", answer_supervision, - "immediate_ringback", immediate_ringback, - "ringback_file", ringback_file, - "digit_timeout", &to, - "dial_timeout", &dial_timeout_int, - "release_guard_time_ms", &release_guard_time_ms_int, - "max_dialstr", &max, - FTDM_TAG_END) != FTDM_SUCCESS) { - LOAD_ERROR("Error starting FreeTDM span %d\n", span_id); - continue; - } - - SPAN_CONFIG[span_id].span = span; - switch_set_string(SPAN_CONFIG[span_id].context, context); - switch_set_string(SPAN_CONFIG[span_id].dialplan, dialplan); - SPAN_CONFIG[span_id].analog_options = analog_options | globals.analog_options; - - if (dial_regex) { - switch_set_string(SPAN_CONFIG[span_id].dial_regex, dial_regex); - } - - if (fail_dial_regex) { - switch_set_string(SPAN_CONFIG[span_id].fail_dial_regex, fail_dial_regex); - } - - if (hold_music) { - switch_set_string(SPAN_CONFIG[span_id].hold_music, hold_music); - } - switch_copy_string(SPAN_CONFIG[span_id].type, "analog_em", sizeof(SPAN_CONFIG[span_id].type)); - ftdm_span_start(span); - } - } - - if ((spans = switch_xml_child(cfg, "pri_spans"))) { - for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) { - char *name = (char *) switch_xml_attr(myspan, "name"); - ftdm_conf_parameter_t spanparameters[FTDM_MAX_SIG_PARAMETERS]; - ftdm_status_t zstatus = FTDM_FAIL; - const char *context = "default"; - const char *dialplan = "XML"; - unsigned paramindex = 0; - ftdm_span_t *span = NULL; - uint32_t span_id = 0; - - if (!name) { - LOAD_ERROR("span missing required attribute 'name'\n"); - continue; - } - - memset(spanparameters, 0, sizeof(spanparameters)); - - for (param = switch_xml_child(myspan, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - - if (ftdm_array_len(spanparameters) - 1 == paramindex) { - LOAD_ERROR("Too many parameters for pri span '%s', ignoring everything after '%s'\n", name, var); - break; - } - - if (ftdm_strlen_zero(var) || ftdm_strlen_zero(val)) { - ftdm_log(FTDM_LOG_WARNING, "Skipping parameter with empty name or value\n"); - continue; - } - - if (!strcasecmp(var, "context")) { - context = val; - } else if (!strcasecmp(var, "dialplan")) { - dialplan = val; - } else { - spanparameters[paramindex].var = var; - spanparameters[paramindex].val = val; - paramindex++; - } - } - - zstatus = ftdm_span_find_by_name(name, &span); - if (zstatus != FTDM_SUCCESS) { - LOAD_ERROR("Error finding FreeTDM span %s\n", name); - continue; - } - - span_id = ftdm_span_get_id(span); - if (ftdm_configure_span_signaling(span, "isdn", on_clear_channel_signal, spanparameters) != FTDM_SUCCESS) { - LOAD_ERROR("Error configuring FreeTDM span %s\n", name); - continue; - } - - SPAN_CONFIG[span_id].span = span; - switch_copy_string(SPAN_CONFIG[span_id].context, context, sizeof(SPAN_CONFIG[span_id].context)); - switch_copy_string(SPAN_CONFIG[span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span_id].dialplan)); - switch_copy_string(SPAN_CONFIG[span_id].type, "isdn", sizeof(SPAN_CONFIG[span_id].type)); - - ftdm_span_start(span); - } - } - - if ((spans = switch_xml_child(cfg, "pritap_spans"))) { - for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) { - - char *name = (char *) switch_xml_attr(myspan, "name"); - - ftdm_status_t zstatus = FTDM_FAIL; - unsigned paramindex = 0; - ftdm_conf_parameter_t spanparameters[FTDM_MAX_SIG_PARAMETERS]; - const char *context = "default"; - const char *dialplan = "XML"; - ftdm_span_t *span = NULL; - int span_id = 0; - - if (!name) { - LOAD_ERROR("span missing required attribute 'name'\n"); - continue; - } - - memset(spanparameters, 0, sizeof(spanparameters)); - - for (param = switch_xml_child(myspan, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - - if (ftdm_array_len(spanparameters) - 1 == paramindex) { - LOAD_ERROR("Too many parameters for pritap span '%s', ignoring everything after '%s'\n", name, var); - break; - } - - if (!strcasecmp(var, "context")) { - context = val; - } else if (!strcasecmp(var, "dialplan")) { - dialplan = val; - } else { - spanparameters[paramindex].var = var; - spanparameters[paramindex].val = val; - paramindex++; - } - } - - zstatus = ftdm_span_find_by_name(name, &span); - if (zstatus != FTDM_SUCCESS) { - LOAD_ERROR("Error finding FreeTDM span %s\n", name); - continue; - } - - span_id = ftdm_span_get_id(span); - if (ftdm_configure_span_signaling(span, "pritap", on_clear_channel_signal, spanparameters) != FTDM_SUCCESS) { - LOAD_ERROR("Error configuring FreeTDM span %s\n", name); - continue; - } - - SPAN_CONFIG[span_id].span = span; - switch_copy_string(SPAN_CONFIG[span_id].context, context, sizeof(SPAN_CONFIG[span_id].context)); - switch_copy_string(SPAN_CONFIG[span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span_id].dialplan)); - switch_copy_string(SPAN_CONFIG[span_id].type, "isdn", sizeof(SPAN_CONFIG[span_id].type)); - - ftdm_span_start(span); - } - } - - - if ((spans = switch_xml_child(cfg, "libpri_spans"))) { - for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) { - char *name = (char *) switch_xml_attr(myspan, "name"); - ftdm_conf_parameter_t spanparameters[FTDM_MAX_SIG_PARAMETERS]; - ftdm_status_t zstatus = FTDM_FAIL; - const char *context = "default"; - const char *dialplan = "XML"; - unsigned paramindex = 0; - ftdm_span_t *span = NULL; - uint32_t span_id = 0; - - if (!name) { - LOAD_ERROR("span missing required attribute 'name'\n"); - continue; - } - - memset(spanparameters, 0, sizeof(spanparameters)); - - for (param = switch_xml_child(myspan, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - - if (ftdm_array_len(spanparameters) - 1 == paramindex) { - LOAD_ERROR("Too many parameters for libpri span, ignoring everything after '%s'\n", var); - break; - } - - if (ftdm_strlen_zero(var) || ftdm_strlen_zero(val)) { - ftdm_log(FTDM_LOG_WARNING, "Skipping parameter with empty name or value\n"); - continue; - } - - if (!strcasecmp(var, "context")) { - context = val; - } else if (!strcasecmp(var, "dialplan")) { - dialplan = val; - } else { - spanparameters[paramindex].var = var; - spanparameters[paramindex].val = val; - paramindex++; - } - } - - zstatus = ftdm_span_find_by_name(name, &span); - if (zstatus != FTDM_SUCCESS) { - LOAD_ERROR("Error finding FreeTDM span %s\n", name); - continue; - } - - span_id = ftdm_span_get_id(span); - if (ftdm_configure_span_signaling(span, "libpri", on_clear_channel_signal, spanparameters) != FTDM_SUCCESS) { - LOAD_ERROR("Error configuring FreeTDM span %s\n", name); - continue; - } - - SPAN_CONFIG[span_id].span = span; - switch_copy_string(SPAN_CONFIG[span_id].context, context, sizeof(SPAN_CONFIG[span_id].context)); - switch_copy_string(SPAN_CONFIG[span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span_id].dialplan)); - switch_copy_string(SPAN_CONFIG[span_id].type, "isdn", sizeof(SPAN_CONFIG[span_id].type)); - - ftdm_span_start(span); - } - } - - if ((spans = switch_xml_child(cfg, "r2_spans"))) { - for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) { - char *name = (char *) switch_xml_attr(myspan, "name"); - char *configname = (char *) switch_xml_attr(myspan, "cfgprofile"); - ftdm_status_t zstatus = FTDM_FAIL; - - /* common non r2 stuff */ - const char *context = "default"; - const char *dialplan = "XML"; - char *dial_regex = NULL; - char *fail_dial_regex = NULL; - uint32_t span_id = 0; - ftdm_span_t *span = NULL; - - ftdm_conf_parameter_t spanparameters[FTDM_MAX_SIG_PARAMETERS]; - unsigned paramindex = 0; - - if (!name) { - LOAD_ERROR("'name' attribute required for R2 spans!\n"); - continue; - } - - memset(spanparameters, 0, sizeof(spanparameters)); - - if (configname) { - paramindex = add_profile_parameters(cfg, configname, spanparameters, ftdm_array_len(spanparameters)); - if (paramindex) { - ftdm_log(FTDM_LOG_DEBUG, "Added %d parameters from profile %s for span %d\n", paramindex, configname, span_id); - } - } - - for (param = switch_xml_child(myspan, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - - /* string parameters */ - if (!strcasecmp(var, "context")) { - context = val; - } else if (!strcasecmp(var, "dialplan")) { - dialplan = val; - } else if (!strcasecmp(var, "dial-regex")) { - dial_regex = val; - } else if (!strcasecmp(var, "fail-dial-regex")) { - fail_dial_regex = val; - } else { - spanparameters[paramindex].var = var; - spanparameters[paramindex].val = val; - paramindex++; - } - } - - zstatus = ftdm_span_find_by_name(name, &span); - if (zstatus != FTDM_SUCCESS) { - LOAD_ERROR("Error finding FreeTDM R2 Span '%s'\n", name); - continue; - } - span_id = ftdm_span_get_id(span); - - if (ftdm_configure_span_signaling(span, "r2", on_r2_signal, spanparameters) != FTDM_SUCCESS) { - LOAD_ERROR("Error configuring FreeTDM R2 span %s, error: %s\n", name, ftdm_span_get_last_error(span)); - continue; - } - - if (dial_regex) { - switch_set_string(SPAN_CONFIG[span_id].dial_regex, dial_regex); - } - - if (fail_dial_regex) { - switch_set_string(SPAN_CONFIG[span_id].fail_dial_regex, fail_dial_regex); - } - - SPAN_CONFIG[span_id].span = span; - switch_copy_string(SPAN_CONFIG[span_id].context, context, sizeof(SPAN_CONFIG[span_id].context)); - switch_copy_string(SPAN_CONFIG[span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span_id].dialplan)); - switch_copy_string(SPAN_CONFIG[span_id].type, "R2", sizeof(SPAN_CONFIG[span_id].type)); - - if (ftdm_span_start(span) == FTDM_FAIL) { - LOAD_ERROR("Error starting FreeTDM R2 span %s, error: %s\n", name, ftdm_span_get_last_error(span)); - continue; - } - } - } - - if (globals.crash_on_assert) { - ftdm_log(FTDM_LOG_WARNING, "Crash on assert enabled\n"); - ftdm_global_set_crash_policy(FTDM_CRASH_ON_ASSERT); - } - - switch_xml_free(xml); - - if (globals.fail_on_error && globals.config_error) { - ftdm_log(FTDM_LOG_ERROR, "Refusing to load module with errors\n"); - return SWITCH_STATUS_TERM; - } - - return SWITCH_STATUS_SUCCESS; -} - -void dump_chan(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream) -{ - uint32_t span_id; - uint32_t phspan_id, phchan_id; - const char *chan_type; - const char *state; - const char *last_state; - const char *uuid = NULL; - char sessionid[255]; - float txgain, rxgain; - switch_core_session_t *session = NULL; - ftdm_alarm_flag_t alarmflag; - ftdm_caller_data_t *caller_data; - ftdm_channel_t *ftdmchan; - ftdm_signaling_status_t sigstatus = FTDM_SIG_STATE_DOWN; - - if (chan_id > ftdm_span_get_chan_count(span)) { - return; - } - - strcpy(sessionid, "(none)"); - ftdmchan = ftdm_span_get_channel(span, chan_id); - span_id = ftdm_span_get_id(span); - - phspan_id = ftdm_channel_get_ph_span_id(ftdmchan); - phchan_id = ftdm_channel_get_ph_id(ftdmchan); - chan_type = ftdm_chan_type2str(ftdm_channel_get_type(ftdmchan)); - state = ftdm_channel_get_state_str(ftdmchan); - last_state = ftdm_channel_get_last_state_str(ftdmchan); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_RX_GAIN, &rxgain); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_TX_GAIN, &txgain); - caller_data = ftdm_channel_get_caller_data(ftdmchan); - ftdm_channel_get_sig_status(ftdmchan, &sigstatus); - ftdm_channel_get_alarms(ftdmchan, &alarmflag); - - uuid = ftdm_channel_get_uuid(ftdmchan, 0); - if (!zstr(uuid)) { - if (!(session = switch_core_session_locate(uuid))) { - snprintf(sessionid, sizeof(sessionid), "%s (dead)", uuid); - } else { - snprintf(sessionid, sizeof(sessionid), "%s", uuid); - switch_core_session_rwunlock(session); - } - } - - stream->write_function(stream, - "span_id: %u\n" - "chan_id: %u\n" - "physical_span_id: %u\n" - "physical_chan_id: %u\n" - "physical_status: %s\n" - "physical_status_red: %d\n" - "physical_status_yellow: %d\n" - "physical_status_rai: %d\n" - "physical_status_blue: %d\n" - "physical_status_ais: %d\n" - "physical_status_general: %d\n" - "signaling_status: %s\n" - "type: %s\n" - "state: %s\n" - "last_state: %s\n" - "txgain: %3.2f\n" - "rxgain: %3.2f\n" - "cid_date: %s\n" - "cid_name: %s\n" - "cid_num: %s\n" - "ani: %s\n" - "aniII: %s\n" - "dnis: %s\n" - "rdnis: %s\n" - "cause: %s\n" - "session: %s\n\n", - span_id, - chan_id, - phspan_id, - phchan_id, - alarmflag ? "alarmed" : "ok", - (alarmflag & FTDM_ALARM_RED) ? 1 : 0, - (alarmflag & FTDM_ALARM_YELLOW) ? 1 : 0, - (alarmflag & FTDM_ALARM_RAI) ? 1 : 0, - (alarmflag & FTDM_ALARM_BLUE) ? 1 : 0, - (alarmflag & FTDM_ALARM_AIS) ? 1 : 0, - (alarmflag & FTDM_ALARM_GENERAL) ? 1 : 0, - ftdm_signaling_status2str(sigstatus), - chan_type, - state, - last_state, - txgain, - rxgain, - caller_data->cid_date, - caller_data->cid_name, - caller_data->cid_num.digits, - caller_data->ani.digits, - caller_data->aniII, - caller_data->dnis.digits, - caller_data->rdnis.digits, - switch_channel_cause2str(caller_data->hangup_cause), - sessionid); -} - -void dump_chan_xml(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream) -{ - uint32_t span_id; - uint32_t phspan_id, phchan_id; - const char *chan_type; - const char *state; - const char *last_state; - float txgain, rxgain; - ftdm_caller_data_t *caller_data; - ftdm_channel_t *ftdmchan; - ftdm_alarm_flag_t alarmflag; - ftdm_signaling_status_t sigstatus = FTDM_SIG_STATE_DOWN; - - if (chan_id > ftdm_span_get_chan_count(span)) { - return; - } - - ftdmchan = ftdm_span_get_channel(span, chan_id); - span_id = ftdm_span_get_id(span); - - phspan_id = ftdm_channel_get_ph_span_id(ftdmchan); - phchan_id = ftdm_channel_get_ph_id(ftdmchan); - chan_type = ftdm_chan_type2str(ftdm_channel_get_type(ftdmchan)); - state = ftdm_channel_get_state_str(ftdmchan); - last_state = ftdm_channel_get_last_state_str(ftdmchan); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_RX_GAIN, &rxgain); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_TX_GAIN, &txgain); - caller_data = ftdm_channel_get_caller_data(ftdmchan); - ftdm_channel_get_sig_status(ftdmchan, &sigstatus); - ftdm_channel_get_alarms(ftdmchan, &alarmflag); - - - stream->write_function(stream, - " \n" - " %u\n" - " %u>\n" - " %u\n" - " %u\n" - " %s\n" - " %d\n" - " %d\n" - " %d\n" - " %d\n" - " %d\n" - " %d\n" - " %s\n" - " %s\n" - " %s\n" - " %s\n" - " %3.2f\n" - " %3.2f\n" - " %s\n" - " %s\n" - " %s\n" - " %s\n" - " %s\n" - " %s\n" - " %s\n" - " %s\n" - " \n", - span_id, - chan_id, - phspan_id, - phchan_id, - alarmflag ? "alarmed" : "ok", - (alarmflag & FTDM_ALARM_RED) ? 1 : 0, - (alarmflag & FTDM_ALARM_YELLOW) ? 1 : 0, - (alarmflag & FTDM_ALARM_RAI) ? 1 : 0, - (alarmflag & FTDM_ALARM_BLUE) ? 1 : 0, - (alarmflag & FTDM_ALARM_AIS) ? 1 : 0, - (alarmflag & FTDM_ALARM_GENERAL) ? 1 : 0, - ftdm_signaling_status2str(sigstatus), - chan_type, - state, - last_state, - txgain, - rxgain, - caller_data->cid_date, - caller_data->cid_name, - caller_data->cid_num.digits, - caller_data->ani.digits, - caller_data->aniII, - caller_data->dnis.digits, - caller_data->rdnis.digits, - switch_channel_cause2str(caller_data->hangup_cause)); -} - -typedef struct ftdm_cli_entry ftdm_cli_entry_t; -typedef switch_status_t (*ftdm_cli_function_t)(ftdm_cli_entry_t *cli, const char *cmd, switch_core_session_t *session, - switch_stream_handle_t *stream, int argc, char *argv[]); -#define FTDM_CLI_DECLARE(name) static switch_status_t name(ftdm_cli_entry_t *cli, const char *cmd, \ - switch_core_session_t *session, switch_stream_handle_t *stream, \ - int argc, char *argv[]) -static void print_usage(switch_stream_handle_t *stream, ftdm_cli_entry_t *cli); - - -typedef struct cmd_ioread_data { - int num_times; - uint32_t interval; - ftdm_span_t *span; - ftdm_channel_t *fchan; - switch_memory_pool_t *pool; - int already_open; -} cmd_ioread_data_t; - -static void *SWITCH_THREAD_FUNC ioread_thread(switch_thread_t *thread, void *obj) -{ - ftdm_wait_flag_t wflags = FTDM_READ; - ftdm_status_t status = FTDM_FAIL; - unsigned char iobuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; - cmd_ioread_data_t *data = obj; - int span_id = ftdm_span_get_id(data->span); - int chan_id = ftdm_channel_get_id(data->fchan); - ftdm_size_t len = ftdm_channel_get_io_packet_len(data->fchan); - ftdm_size_t origlen = len; - unsigned int pbuf[5]; - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, - "Started ioread thread (times = %d, interval = %ums, len = %"FTDM_SIZE_FMT", span = %d, chan = %d\n", - data->num_times, data->interval, len, span_id, chan_id); - - while (ftdm_running() && data->num_times > 0) { - data->num_times--; - - wflags = FTDM_READ; - status = ftdm_channel_wait(data->fchan, &wflags, (data->interval * 10)); - - if (status == FTDM_FAIL) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to wait for IO in device %d:%d!\n", span_id, chan_id); - continue; - } - - if (status == FTDM_TIMEOUT) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Timed out while waiting I/O in device %d:%d!\n", span_id, chan_id); - continue; - } - - len = origlen; - if (ftdm_channel_read(data->fchan, iobuf, &len) != FTDM_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to read from device %d:%d!\n", span_id, chan_id); - continue; - } - pbuf[0] = iobuf[0]; - pbuf[1] = iobuf[1]; - pbuf[2] = iobuf[2]; - pbuf[3] = iobuf[3]; - pbuf[4] = iobuf[4]; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Read 0x%1X 0x%1X 0x%1X 0x%1X 0x%1X\n", - pbuf[0], pbuf[1], pbuf[2], pbuf[3], pbuf[4]); - } - - if (!data->already_open) { - ftdm_channel_close(&data->fchan); - } - - switch_core_destroy_memory_pool(&data->pool); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, - "Done ioread thread (times = %d, interval = %ums, len = %"FTDM_SIZE_FMT", span = %d, chan = %d\n", - data->num_times, data->interval, origlen, span_id, chan_id); - return NULL; -} - -FTDM_CLI_DECLARE(ftdm_cmd_ioread) -{ - char *span_name = NULL; - int channo = 0; - ftdm_status_t status = FTDM_SUCCESS; - switch_threadattr_t *attr = NULL; - switch_thread_t *thread = NULL; - - cmd_ioread_data_t *thdata; - cmd_ioread_data_t data; - - memset(&data, 0, sizeof(data)); - data.num_times = 1; - - if (argc < 3) { - print_usage(stream, cli); - goto end; - } - - span_name = argv[1]; - - ftdm_span_find_by_name(span_name, &data.span); - if (!data.span) { - stream->write_function(stream, "-ERR span %s not found\n", span_name); - goto end; - } - - channo = atoi(argv[2]); - - status = ftdm_channel_open(ftdm_span_get_id(data.span), channo, &data.fchan); - if (!data.fchan || (status != FTDM_SUCCESS && status != FTDM_EBUSY)) { - stream->write_function(stream, "-ERR Failed to open channel %d in span %s\n", channo, span_name); - goto end; - } - - if (status == FTDM_EBUSY) { - data.already_open = 1; - } - - if (argc > 3) { - data.num_times = atoi(argv[3]); - if (data.num_times < 1) { - data.num_times = 1; - } - } - - if (argc > 4) { - data.interval = atoi(argv[4]); - } - - if (data.interval <= 0 || data.interval > 10000) { - data.interval = ftdm_channel_get_io_interval(data.fchan); - } - - switch_core_new_memory_pool(&data.pool); - - thdata = switch_core_alloc(data.pool, sizeof(data)); - memcpy(thdata, &data, sizeof(*thdata)); - - switch_threadattr_create(&attr, data.pool); - switch_threadattr_detach_set(attr, 1); - switch_threadattr_stacksize_set(attr, SWITCH_THREAD_STACKSIZE); - switch_thread_create(&thread, attr, ioread_thread, thdata, data.pool); - -end: - return SWITCH_STATUS_SUCCESS; -} - -FTDM_CLI_DECLARE(ftdm_cmd_list) -{ - int j; - - for (j = 0 ; j < FTDM_MAX_SPANS_INTERFACE; j++) { - ftdm_channel_t *fchan; - ftdm_alarm_flag_t alarmbits = FTDM_ALARM_NONE; - const char *flags = "none"; - ftdm_signaling_status_t sigstatus; - - if (!SPAN_CONFIG[j].span) { - continue; - } - - if (SPAN_CONFIG[j].analog_options & ANALOG_OPTION_3WAY) { - flags = "3way"; - } else if (SPAN_CONFIG[j].analog_options & ANALOG_OPTION_CALL_SWAP) { - flags = "call swap"; - } - fchan = ftdm_span_get_channel(SPAN_CONFIG[j].span, 1); - ftdm_channel_get_alarms(fchan, &alarmbits); - - if ((FTDM_SUCCESS == ftdm_span_get_sig_status(SPAN_CONFIG[j].span, &sigstatus))) { - stream->write_function(stream, - "+OK\n" - "span: %u (%s)\n" - "type: %s\n" - "physical_status: %s\n" - "signaling_status: %s\n" - "chan_count: %u\n" - "dialplan: %s\n" - "context: %s\n" - "dial_regex: %s\n" - "fail_dial_regex: %s\n" - "hold_music: %s\n" - "analog_options: %s\n", - j, - ftdm_span_get_name(SPAN_CONFIG[j].span), - SPAN_CONFIG[j].type, - alarmbits ? "alarmed" : "ok", - ftdm_signaling_status2str(sigstatus), - ftdm_span_get_chan_count(SPAN_CONFIG[j].span), - SPAN_CONFIG[j].dialplan, - SPAN_CONFIG[j].context, - SPAN_CONFIG[j].dial_regex, - SPAN_CONFIG[j].fail_dial_regex, - SPAN_CONFIG[j].hold_music, - flags - ); - } else { - stream->write_function(stream, - "+OK\n" - "span: %u (%s)\n" - "type: %s\n" - "physical_status: %s\n" - "chan_count: %u\n" - "dialplan: %s\n" - "context: %s\n" - "dial_regex: %s\n" - "fail_dial_regex: %s\n" - "hold_music: %s\n" - "analog_options: %s\n", - j, - ftdm_span_get_name(SPAN_CONFIG[j].span), - SPAN_CONFIG[j].type, - alarmbits ? "alarmed" : "ok", - ftdm_span_get_chan_count(SPAN_CONFIG[j].span), - SPAN_CONFIG[j].dialplan, - SPAN_CONFIG[j].context, - SPAN_CONFIG[j].dial_regex, - SPAN_CONFIG[j].fail_dial_regex, - SPAN_CONFIG[j].hold_music, - flags); - } - } - return SWITCH_STATUS_SUCCESS; -} - -FTDM_CLI_DECLARE(ftdm_cmd_start_stop) -{ - char *span_name = argv[1]; - ftdm_span_t *span = NULL; - ftdm_status_t status; - - if (argc < 2) { - print_usage(stream, cli); - goto end; - } - - ftdm_span_find_by_name(span_name, &span); - if (!span) { - stream->write_function(stream, "-ERR span %s not found\n", span_name); - goto end; - } - - if (!strcasecmp(argv[0], "stop")) { - status = ftdm_span_stop(span); - } else { - status = ftdm_span_start(span); - } - - stream->write_function(stream, status == FTDM_SUCCESS ? "+OK\n" : "-ERR failure\n"); -end: - return SWITCH_STATUS_SUCCESS; -} - -FTDM_CLI_DECLARE(ftdm_cmd_reset) -{ - uint32_t chan_id = 0; - uint32_t ccount = 0; - ftdm_channel_t *chan; - ftdm_span_t *span = NULL; - - if (argc < 2) { - print_usage(stream, cli); - goto end; - } - - ftdm_span_find_by_name(argv[1], &span); - if (!span) { - stream->write_function(stream, "-ERR span %s not found\n", argv[1]); - goto end; - } - - if (argc > 2) { - chan_id = atoi(argv[2]); - if (chan_id > ftdm_span_get_chan_count(span)) { - stream->write_function(stream, "-ERR invalid channel %d\n", chan_id); - goto end; - } - } - - if (chan_id) { - chan = ftdm_span_get_channel(span, chan_id); - if (!chan) { - stream->write_function(stream, "-ERR Could not find channel %d\n", chan_id); - goto end; - } - stream->write_function(stream, "Resetting channel %s:%s\n", argv[1], argv[2]); - ftdm_channel_reset(chan); - } else { - uint32_t i = 0; - ccount = ftdm_span_get_chan_count(span); - for (i = 1; i < ccount; i++) { - chan = ftdm_span_get_channel(span, i); - stream->write_function(stream, "Resetting channel %s:%d\n", argv[1], i); - ftdm_channel_reset(chan); - } - } - -end: - - return SWITCH_STATUS_SUCCESS; -} - -FTDM_CLI_DECLARE(ftdm_cmd_dump) -{ - ftdm_iterator_t *chaniter = NULL; - ftdm_iterator_t *curr = NULL; - uint32_t chan_id = 0; - ftdm_span_t *span; - char *as = NULL; - - if (argc < 2) { - print_usage(stream, cli); - goto end; - } - - ftdm_span_find_by_name(argv[1], &span); - if (argc > 2) { - if (argv[3] && !strcasecmp(argv[2], "as")) { - as = argv[3]; - } else { - chan_id = atoi(argv[2]); - } - } - - if (argv[4] && !strcasecmp(argv[3], "as")) { - as = argv[4]; - } - - if (!zstr(as) && !strcasecmp(as, "xml")) { - stream->write_function(stream, "\n"); - if (!span) { - stream->write_function(stream, "invalid span\n"); - } else { - if (chan_id) { - if (chan_id > ftdm_span_get_chan_count(span)) { - stream->write_function(stream, "invalid channel\n"); - } else { - dump_chan_xml(span, chan_id, stream); - } - } else { - chaniter = ftdm_span_get_chan_iterator(span, NULL); - for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { - dump_chan_xml(span, ftdm_channel_get_id(ftdm_iterator_current(curr)), stream); - } - ftdm_iterator_free(chaniter); - } - } - stream->write_function(stream, "\n"); - } else { - if (!span) { - stream->write_function(stream, "-ERR invalid span\n"); - } else { - if (chan_id) { - if (chan_id > ftdm_span_get_chan_count(span)) { - stream->write_function(stream, "-ERR invalid channel\n"); - } else { - char *dbgstr = NULL; - ftdm_channel_t *fchan = ftdm_span_get_channel(span, chan_id); - dump_chan(span, chan_id, stream); - dbgstr = ftdm_channel_get_history_str(fchan); - stream->write_function(stream, "%s\n", dbgstr); - ftdm_free(dbgstr); - } - } else { - stream->write_function(stream, "+OK\n"); - chaniter = ftdm_span_get_chan_iterator(span, NULL); - for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { - dump_chan(span, ftdm_channel_get_id(ftdm_iterator_current(curr)), stream); - } - ftdm_iterator_free(chaniter); - } - } - } - -end: - return SWITCH_STATUS_SUCCESS; -} - -FTDM_CLI_DECLARE(ftdm_cmd_alarms) -{ - ftdm_alarm_flag_t alarmbits = FTDM_ALARM_NONE; - uint32_t chan_id = 0; - ftdm_span_t *span; - - if (argc < 3) { - print_usage(stream, cli); - goto end; - } - - ftdm_span_find_by_name(argv[1], &span); - chan_id = atoi(argv[2]); - if (!span) { - stream->write_function(stream, "-ERR invalid span\n"); - } else if (chan_id) { - if (chan_id > ftdm_span_get_chan_count(span)) { - stream->write_function(stream, "-ERR invalid channel\n"); - } else { - ftdm_channel_t *chan = ftdm_span_get_channel(span, chan_id); - if (!chan) { - stream->write_function(stream, "-ERR channel not configured\n"); - } else { - ftdm_channel_get_alarms(chan, &alarmbits); - if (!strlen(ftdm_channel_get_last_error(chan))) { - stream->write_function(stream, "+OK No alarms\n"); - } else { - stream->write_function(stream, "-ERR %s on %s:%d\n", ftdm_channel_get_last_error(chan), argv[1], chan); - } - } - } - } -end: - return SWITCH_STATUS_SUCCESS; -} - -FTDM_CLI_DECLARE(ftdm_cmd_sigstatus) -{ - ftdm_span_t *span = NULL; - ftdm_signaling_status_t sigstatus; - - if (argc < 3) { - print_usage(stream, cli); - goto end; - } - - if (!strcasecmp(argv[1], "get") && argc < 3) { - print_usage(stream, cli); - goto end; - } - - if (!strcasecmp(argv[1], "set") && argc != 5) { - print_usage(stream, cli); - goto end; - } - - ftdm_span_find_by_name(argv[2], &span); - if (!span) { - stream->write_function(stream, "-ERR invalid span %s\n", argv[2]); - goto end; - } - - if (!strcasecmp(argv[1], "get")) { - if (argc == 4) { - uint32_t chan_id = atol(argv[3]); - ftdm_channel_t *fchan = ftdm_span_get_channel(span, chan_id); - if (!fchan) { - stream->write_function(stream, "-ERR invalid channel id '%d'\n", chan_id); - goto end; - } - - if ((FTDM_SUCCESS == ftdm_channel_get_sig_status(fchan, &sigstatus))) { - stream->write_function(stream, "Channel %d signaling status: %s\n", chan_id, ftdm_signaling_status2str(sigstatus)); - } else { - stream->write_function(stream, "-ERR failed to get channel signaling status\n"); - } - goto end; - } else { - if ((FTDM_SUCCESS == ftdm_span_get_sig_status(span, &sigstatus))) { - stream->write_function(stream, "signaling_status: %s\n", ftdm_signaling_status2str(sigstatus)); - } else { - stream->write_function(stream, "-ERR failed to read span signaling status: %s\n", ftdm_span_get_last_error(span)); - } - } - goto end; - } - if (!strcasecmp(argv[1], "set")) { - sigstatus = ftdm_str2ftdm_signaling_status(argv[4]); - - if (!strcasecmp(argv[3], "all")) { - if ((FTDM_SUCCESS == ftdm_span_set_sig_status(span, sigstatus))) { - stream->write_function(stream, "Signaling status of all channels from span %s set to %s\n", - ftdm_span_get_name(span), ftdm_signaling_status2str(sigstatus)); - } else { - stream->write_function(stream, "-ERR failed to set span sigstatus to '%s'\n", ftdm_signaling_status2str(sigstatus)); - } - goto end; - } else { - uint32_t chan_id = atol(argv[3]); - ftdm_channel_t *fchan = ftdm_span_get_channel(span, chan_id); - if (!fchan) { - stream->write_function(stream, "-ERR failed to get channel id '%d'\n", chan_id); - goto end; - } - - if ((FTDM_SUCCESS == ftdm_channel_set_sig_status(fchan, sigstatus))) { - stream->write_function(stream, "Signaling status of channel %d set to %s\n", chan_id, - ftdm_signaling_status2str(sigstatus)); - } else { - stream->write_function(stream, "-ERR failed to set span sigstatus to '%s'\n", ftdm_signaling_status2str(sigstatus)); - } - goto end; - } - } - -end: - return SWITCH_STATUS_SUCCESS; -} - -FTDM_CLI_DECLARE(ftdm_cmd_trace) -{ - char tracepath[255]; - unsigned i = 0; - uint32_t chan_id = 0; - uint32_t span_id = 0; - uint32_t chan_count = 0; - ftdm_status_t status; - ftdm_span_t *span = NULL; - ftdm_channel_t *chan = NULL; - - if (argc < 3) { - print_usage(stream, cli); - goto end; - } - - ftdm_span_find_by_name(argv[2], &span); - if (!span) { - stream->write_function(stream, "-ERR failed to find span %s\n", argv[2]); - goto end; - } - - chan_count = ftdm_span_get_chan_count(span); - - if (argc > 3) { - chan_id = atoi(argv[3]); - if (chan_id > chan_count) { - stream->write_function(stream, "-ERR invalid channel\n"); - goto end; - } - } - - span_id = ftdm_span_get_id(span); - - if (chan_id) { - chan = ftdm_span_get_channel(span, chan_id); - - snprintf(tracepath, sizeof(tracepath), "%s-in-s%dc%d", argv[1], span_id, chan_id); - status = ftdm_channel_command(chan, FTDM_COMMAND_TRACE_INPUT, tracepath); - if (status != FTDM_SUCCESS) { - stream->write_function(stream, "-ERR failed to enable input trace at path %s\n", tracepath); - goto end; - } - - snprintf(tracepath, sizeof(tracepath), "%s-out-s%dc%d", argv[1], span_id, chan_id); - status = ftdm_channel_command(chan, FTDM_COMMAND_TRACE_OUTPUT, tracepath); - if (status != FTDM_SUCCESS) { - stream->write_function(stream, "-ERR failed to enable output trace at path %s\n", tracepath); - ftdm_channel_command(chan, FTDM_COMMAND_TRACE_END_ALL, NULL); - goto end; - } - } else { - for (i = 1; i <= chan_count; i++) { - chan = ftdm_span_get_channel(span, i); - - snprintf(tracepath, sizeof(tracepath), "%s-in-s%dc%d", argv[1], span_id, i); - status = ftdm_channel_command(chan, FTDM_COMMAND_TRACE_INPUT, tracepath); - if (status != FTDM_SUCCESS) { - stream->write_function(stream, "-ERR failed to enable input trace at path %s\n", tracepath); - goto end; - } - - snprintf(tracepath, sizeof(tracepath), "%s-out-s%dc%d", argv[1], span_id, i); - status = ftdm_channel_command(chan, FTDM_COMMAND_TRACE_OUTPUT, tracepath); - if (status != FTDM_SUCCESS) { - stream->write_function(stream, "-ERR failed to enable output trace at path %s\n", tracepath); - ftdm_channel_command(chan, FTDM_COMMAND_TRACE_END_ALL, NULL); - goto end; - } - } - } - stream->write_function(stream, "+OK trace enabled with prefix path %s\n", argv[1]); -end: - return SWITCH_STATUS_SUCCESS; -} - -FTDM_CLI_DECLARE(ftdm_cmd_notrace) -{ - uint32_t i = 0; - uint32_t chan_id = 0; - uint32_t chan_count = 0; - ftdm_channel_t *fchan = NULL; - ftdm_span_t *span = NULL; - - if (argc < 2) { - print_usage(stream, cli); - goto end; - } - - ftdm_span_find_by_name(argv[1], &span); - if (!span) { - stream->write_function(stream, "-ERR failed to find span %s\n", argv[1]); - goto end; - } - - chan_count = ftdm_span_get_chan_count(span); - - if (argc > 2) { - chan_id = atoi(argv[2]); - if (chan_id > chan_count) { - stream->write_function(stream, "-ERR invalid channel\n"); - goto end; - } - } - - if (chan_id) { - fchan = ftdm_span_get_channel(span, chan_id); - ftdm_channel_command(fchan, FTDM_COMMAND_TRACE_END_ALL, NULL); - } else { - for (i = 1; i <= chan_count; i++) { - fchan = ftdm_span_get_channel(span, i); - ftdm_channel_command(fchan, FTDM_COMMAND_TRACE_END_ALL, NULL); - } - } - stream->write_function(stream, "+OK trace disabled\n"); - -end: - return SWITCH_STATUS_SUCCESS; -} - -FTDM_CLI_DECLARE(ftdm_cmd_gains) -{ - unsigned int i = 0; - float txgain = 0.0; - float rxgain = 0.0; - uint32_t chan_id = 0; - uint32_t ccount = 0; - ftdm_channel_t *chan; - ftdm_span_t *span = NULL; - - if (argc < 4) { - print_usage(stream, cli); - goto end; - } - - ftdm_span_find_by_name(argv[3], &span); - if (!span) { - stream->write_function(stream, "-ERR failed to find span %s\n", argv[3]); - goto end; - } - - if (argc > 4) { - chan_id = atoi(argv[4]); - if (chan_id > ftdm_span_get_chan_count(span)) { - stream->write_function(stream, "-ERR invalid channel\n"); - goto end; - } - } - - i = sscanf(argv[1], "%f", &rxgain); - i += sscanf(argv[2], "%f", &txgain); - if (i != 2) { - stream->write_function(stream, "-ERR invalid gains\n"); - goto end; - } - - if (chan_id) { - chan = ftdm_span_get_channel(span, chan_id); - ftdm_channel_command(chan, FTDM_COMMAND_SET_RX_GAIN, &rxgain); - ftdm_channel_command(chan, FTDM_COMMAND_SET_TX_GAIN, &txgain); - } else { - ccount = ftdm_span_get_chan_count(span); - for (i = 1; i < ccount; i++) { - chan = ftdm_span_get_channel(span, i); - ftdm_channel_command(chan, FTDM_COMMAND_SET_RX_GAIN, &rxgain); - ftdm_channel_command(chan, FTDM_COMMAND_SET_TX_GAIN, &txgain); - } - } - stream->write_function(stream, "+OK gains set to Rx %f and Tx %f\n", rxgain, txgain); -end: - return SWITCH_STATUS_SUCCESS; -} - -FTDM_CLI_DECLARE(ftdm_cmd_dtmf) -{ - unsigned i = 0; - uint32_t chan_id = 0; - unsigned schan_count = 0; - ftdm_span_t *span = NULL; - ftdm_command_t fcmd = FTDM_COMMAND_ENABLE_DTMF_DETECT; - ftdm_channel_t *fchan; - - if (argc < 3) { - print_usage(stream, cli); - goto end; - } - - if (switch_true(argv[1])) { - fcmd = FTDM_COMMAND_ENABLE_DTMF_DETECT; - } else { - fcmd = FTDM_COMMAND_DISABLE_DTMF_DETECT; - } - - ftdm_span_find_by_name(argv[2], &span); - if (!span) { - stream->write_function(stream, "-ERR failed to find span %s\n", argv[2]); - goto end; - } - - schan_count = ftdm_span_get_chan_count(span); - if (argc > 3) { - chan_id = atoi(argv[3]); - if (chan_id > schan_count) { - stream->write_function(stream, "-ERR invalid channel\n"); - goto end; - } - } - - if (chan_id) { - fchan = ftdm_span_get_channel(span, chan_id); - ftdm_channel_command(fchan, fcmd, NULL); - } else { - for (i = 1; i <= schan_count; i++) { - fchan = ftdm_span_get_channel(span, i); - ftdm_channel_command(fchan, fcmd, NULL); - } - } - - stream->write_function(stream, "+OK DTMF detection was %s\n", fcmd == FTDM_COMMAND_ENABLE_DTMF_DETECT ? "enabled" : "disabled"); -end: - return SWITCH_STATUS_SUCCESS; -} - -FTDM_CLI_DECLARE(ftdm_cmd_queuesize) -{ - unsigned int i = 0; - uint32_t rxsize = 10; - uint32_t txsize = 10; - uint32_t chan_id = 0; - uint32_t ccount = 0; - ftdm_channel_t *chan; - ftdm_span_t *span = NULL; - - if (argc < 4) { - print_usage(stream, cli); - goto end; - } - - ftdm_span_find_by_name(argv[3], &span); - if (!span) { - stream->write_function(stream, "-ERR failed to find span %s\n", argv[3]); - goto end; - } - - if (argc > 4) { - chan_id = atoi(argv[4]); - if (chan_id > ftdm_span_get_chan_count(span)) { - stream->write_function(stream, "-ERR invalid channel\n"); - goto end; - } - } - - i = sscanf(argv[1], "%u", &rxsize); - i += sscanf(argv[2], "%u", &txsize); - if (i != 2) { - stream->write_function(stream, "-ERR invalid queue sizes provided\n"); - goto end; - } - - if (chan_id) { - chan = ftdm_span_get_channel(span, chan_id); - ftdm_channel_command(chan, FTDM_COMMAND_SET_RX_QUEUE_SIZE, &rxsize); - ftdm_channel_command(chan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &txsize); - } else { - ccount = ftdm_span_get_chan_count(span); - for (i = 1; i < ccount; i++) { - chan = ftdm_span_get_channel(span, i); - ftdm_channel_command(chan, FTDM_COMMAND_SET_RX_QUEUE_SIZE, &rxsize); - ftdm_channel_command(chan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &txsize); - } - } - stream->write_function(stream, "+OK queue sizes set to Rx %d and Tx %d\n", rxsize, txsize); -end: - return SWITCH_STATUS_SUCCESS; -} - -static void exec_io_command(const char *cmd, switch_stream_handle_t *stream, ftdm_channel_t *fchan) -{ - int enable = 0; - ftdm_channel_iostats_t stats; - - if (!strcasecmp("enable", cmd)) { - enable = 1; - ftdm_channel_command(fchan, FTDM_COMMAND_SWITCH_IOSTATS, &enable); - } else if (!strcasecmp("disable", cmd)) { - enable = 0; - ftdm_channel_command(fchan, FTDM_COMMAND_SWITCH_IOSTATS, &enable); - } else if (!strcasecmp("flush", cmd)) { - ftdm_channel_command(fchan, FTDM_COMMAND_FLUSH_IOSTATS, NULL); - } else { - ftdm_channel_command(fchan, FTDM_COMMAND_GET_IOSTATS, &stats); - stream->write_function(stream, "-- IO statistics for channel %d:%d --\n", - ftdm_channel_get_span_id(fchan), ftdm_channel_get_id(fchan)); - stream->write_function(stream, "Rx errors: %u\n", stats.rx.errors); - stream->write_function(stream, "Rx queue size: %u\n", stats.rx.queue_size); - stream->write_function(stream, "Rx queue len: %u\n", stats.rx.queue_len); - stream->write_function(stream, "Rx count: %lu\n", stats.rx.packets); - - stream->write_function(stream, "Tx errors: %u\n", stats.tx.errors); - stream->write_function(stream, "Tx queue size: %u\n", stats.tx.queue_size); - stream->write_function(stream, "Tx queue len: %u\n", stats.tx.queue_len); - stream->write_function(stream, "Tx count: %lu\n", stats.tx.packets); - stream->write_function(stream, "Tx idle: %u\n", stats.tx.idle_packets); - } -} - -FTDM_CLI_DECLARE(ftdm_cmd_iostats) -{ - uint32_t chan_id = 0; - ftdm_channel_t *chan; - ftdm_iterator_t *iter = NULL; - ftdm_iterator_t *curr = NULL; - ftdm_span_t *span = NULL; - - if (argc < 3) { - print_usage(stream, cli); - goto end; - } - - ftdm_span_find_by_name(argv[2], &span); - if (!span) { - stream->write_function(stream, "-ERR failed to find span %s\n", argv[2]); - goto end; - } - - if (argc > 3) { - chan_id = atoi(argv[3]); - if (chan_id > ftdm_span_get_chan_count(span)) { - stream->write_function(stream, "-ERR invalid channel\n"); - goto end; - } - chan = ftdm_span_get_channel(span, chan_id); - exec_io_command(argv[1], stream, chan); - } else { - iter = ftdm_span_get_chan_iterator(span, NULL); - for (curr = iter; curr; curr = ftdm_iterator_next(curr)) { - chan = ftdm_iterator_current(curr); - exec_io_command(argv[1], stream, chan); - } - ftdm_iterator_free(iter); - } - stream->write_function(stream, "+OK\n"); -end: - return SWITCH_STATUS_SUCCESS; -} - -#define CASINTS(cas) ((cas) & (1 << 3)) ? 1 : 0, \ - ((cas) & (1 << 2)) ? 1 : 0, \ - ((cas) & (1 << 1)) ? 1 : 0, \ - ((cas) & (1 << 0)) ? 1 : 0 -FTDM_CLI_DECLARE(ftdm_cmd_cas) -{ - uint32_t chan_id = 0; - switch_bool_t do_read = SWITCH_FALSE; - ftdm_channel_t *chan; - ftdm_iterator_t *iter = NULL; - ftdm_iterator_t *curr = NULL; - ftdm_span_t *span = NULL; - const char *write_bits_str = ""; - int32_t abcd_bits = 0; - - if (argc < 3) { - print_usage(stream, cli); - goto end; - } - - if (!strcasecmp(argv[1], "read")) { - do_read = SWITCH_TRUE; - chan_id = argc > 3 ? atoi(argv[3]) : 0; - } else if (!strcasecmp(argv[1], "write") && argc >= 4) { - const char *str = NULL; - int mask = 0x08; - do_read = SWITCH_FALSE; - if (argc == 4) { - chan_id = 0; - write_bits_str = argv[3]; - } else { - chan_id = atoi(argv[3]); - write_bits_str = argv[4]; - } - if (strlen(write_bits_str) != 4) { - stream->write_function(stream, "-ERR Invalid CAS bits '%s'. CAS ABCD string must be composed of only four 1's and 0's (e.g. 1101)\n", write_bits_str); - goto end; - } - str = write_bits_str; - while (*str) { - if (*str == '1') { - abcd_bits |= mask; - } else if (*str != '0') { - stream->write_function(stream, "-ERR Invalid CAS bits '%s'. CAS ABCD string must be composed of only four 1's and 0's (e.g. 1101)\n", write_bits_str); - goto end; - } - str++; - mask = (mask >> 1); - } - } else { - print_usage(stream, cli); - goto end; - } - - ftdm_span_find_by_name(argv[2], &span); - if (!span) { - stream->write_function(stream, "-ERR failed to find span %s\n", argv[2]); - goto end; - } - - if (chan_id) { - if (chan_id > ftdm_span_get_chan_count(span)) { - stream->write_function(stream, "-ERR invalid channel\n"); - goto end; - } - chan = ftdm_span_get_channel(span, chan_id); - if (do_read) { - ftdm_channel_command(chan, FTDM_COMMAND_GET_CAS_BITS, &abcd_bits); - stream->write_function(stream, "Read CAS bits from channel %d: %d%d%d%d (0x0%X)\n", chan_id, CASINTS(abcd_bits), abcd_bits); - } else { - stream->write_function(stream, "Writing 0x0%X to channel %d\n", abcd_bits, chan_id); - } - } else { - iter = ftdm_span_get_chan_iterator(span, NULL); - for (curr = iter; curr; curr = ftdm_iterator_next(curr)) { - chan = ftdm_iterator_current(curr); - //ftdm_channel_command(); - chan_id = ftdm_channel_get_id(chan); - if (do_read) { - ftdm_channel_command(chan, FTDM_COMMAND_GET_CAS_BITS, &abcd_bits); - stream->write_function(stream, "Read CAS bits from channel %d: %d%d%d%d (0x0%X)\n", chan_id, CASINTS(abcd_bits), abcd_bits); - } else { - stream->write_function(stream, "Writing 0x0%X to channel %d\n", abcd_bits, chan_id); - } - } - ftdm_iterator_free(iter); - } - stream->write_function(stream, "+OK\n"); -end: - return SWITCH_STATUS_SUCCESS; -} - -SWITCH_STANDARD_API(ftdm_api_exec_usage) -{ - char *mycmd = NULL, *argv[10] = { 0 }; - int argc = 0; - uint32_t chan_id = 0; - ftdm_channel_t *chan = NULL; - ftdm_span_t *span = NULL; - uint32_t tokencnt = 0; - /*ftdm_cli_entry_t *entry = NULL;*/ - - if (!zstr(cmd) && (mycmd = strdup(cmd))) { - argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); - } - - if (!argc) { - stream->write_function(stream, "-ERR invalid args\n"); - goto end; - } - - if (argc < 2) { - stream->write_function(stream, "-ERR invalid args\n"); - goto end; - } - - ftdm_span_find_by_name(argv[0], &span); - chan_id = atoi(argv[1]); - if (!span) { - stream->write_function(stream, "-ERR invalid span\n"); - goto end; - } - - if (chan_id <= 0) { - stream->write_function(stream, "-ERR invalid channel\n"); - goto end; - } - - if (chan_id > ftdm_span_get_chan_count(span)) { - stream->write_function(stream, "-ERR invalid channel\n"); - goto end; - } - - chan = ftdm_span_get_channel(span, chan_id); - if (!chan) { - stream->write_function(stream, "-ERR channel not configured\n"); - goto end; - } - - tokencnt = ftdm_channel_get_token_count(chan); - stream->write_function(stream, "%d", tokencnt); - -end: - switch_safe_free(mycmd); - return SWITCH_STATUS_SUCCESS; -} - -struct ftdm_cli_entry { - const char *name; - const char *args; - const char *complete; - const char *desc; - ftdm_cli_function_t execute; - switch_api_function_t execute_api; -}; - -static ftdm_cli_entry_t ftdm_cli_options[] = -{ - { "list", "", "", NULL, ftdm_cmd_list, NULL }, - { "start", "", "", NULL, ftdm_cmd_start_stop, NULL }, - { "stop", "", "", NULL, ftdm_cmd_start_stop, NULL }, - { "reset", " []", "", NULL, ftdm_cmd_reset, NULL }, - { "alarms", " ", "", NULL, ftdm_cmd_alarms, NULL }, - { "dump", " []", "", NULL, ftdm_cmd_dump, NULL }, - { "sigstatus", "get|set [] []", "::[set:get", NULL, ftdm_cmd_sigstatus, NULL }, - { "trace", " []", "", NULL, ftdm_cmd_trace, NULL }, - { "notrace", " []", "", NULL, ftdm_cmd_notrace, NULL }, - { "gains", " []", "", NULL, ftdm_cmd_gains, NULL }, - { "dtmf", "on|off []", "::[on:off", NULL, ftdm_cmd_dtmf, NULL }, - { "queuesize", " []", "", NULL, ftdm_cmd_queuesize, NULL }, - { "iostats", "enable|disable|flush|print ", "::[enable:disable:flush:print", NULL, ftdm_cmd_iostats, NULL }, - { "ioread", " [num_times] [interval]", "", NULL, ftdm_cmd_ioread, NULL }, - { "cas", "read|write [] []", "::[read:write", NULL, ftdm_cmd_cas, NULL }, - - /* Stand-alone commands (not part of the generic ftdm API */ - { "ftdm_usage", " ", "", "Return channel call count", NULL, ftdm_api_exec_usage }, - - /* Fake handlers as they are handled within freetdm library, - * we should provide a way inside freetdm to query for completions from signaling modules */ - { "core state", "[!]", "", NULL, NULL, NULL }, - { "core flag", "[!] [] []", "", NULL, NULL, NULL }, - { "core spanflag", "[!] []", "", NULL, NULL, NULL }, - { "core calls", "", "", NULL, NULL, NULL }, -}; - -static void print_usage(switch_stream_handle_t *stream, ftdm_cli_entry_t *cli) -{ - stream->write_function(stream, "-ERR Usage: ftdm %s %s\n", cli->name, cli->args); -} - -static void print_full_usage(switch_stream_handle_t *stream) -{ - int i = 0; - ftdm_cli_entry_t *entry = NULL; - - stream->write_function(stream, "USAGE:\n"); - stream->write_function(stream, "--------------------------------------------------------------------------------\n"); - for (i = 0 ; i < ftdm_array_len(ftdm_cli_options); i++) { - entry = &ftdm_cli_options[i]; - if (entry->execute_api) { - continue; - } - stream->write_function(stream, "ftdm %s %s\n", entry->name, entry->args); - } - stream->write_function(stream, "--------------------------------------------------------------------------------\n"); -} - -SWITCH_STANDARD_API(ftdm_api_exec) -{ - char *mycmd = NULL, *argv[10] = { 0 }; - int argc = 0; - int i = 0; - ftdm_cli_entry_t *entry = NULL; - - if (!zstr(cmd) && (mycmd = strdup(cmd))) { - argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); - } - - if (!argc) { - print_full_usage(stream); - goto end; - } - - for (i = 0 ; i < ftdm_array_len(ftdm_cli_options); i++) { - entry = &ftdm_cli_options[i]; - if (!strcasecmp(argv[0], entry->name) && entry->execute) { - entry->execute(entry, cmd, session, stream, argc, argv); - break; - } - } - - /* if the command was not found in the main CLI entries, try to execute it as a FreeTDM API */ - if (i == ftdm_array_len(ftdm_cli_options)) { - char *rply = ftdm_api_execute(cmd); - if (rply) { - stream->write_function(stream, "%s", rply); - ftdm_free(rply); - } else { - print_full_usage(stream); - } - } - -end: - switch_safe_free(mycmd); - return SWITCH_STATUS_SUCCESS; -} - -SWITCH_STANDARD_APP(enable_dtmf_function) -{ - private_t *tech_pvt; - - if (!switch_core_session_check_interface(session, freetdm_endpoint_interface)) { - ftdm_log(FTDM_LOG_ERROR, "This application is only for FreeTDM channels.\n"); - return; - } - - tech_pvt = switch_core_session_get_private(session); - - if (switch_test_flag(tech_pvt, TFLAG_DEAD)) { - switch_channel_hangup(switch_core_session_get_channel(session), SWITCH_CAUSE_LOSE_RACE); - return; - } - - ftdm_channel_command(tech_pvt->ftdmchan, FTDM_COMMAND_ENABLE_DTMF_DETECT, NULL); - ftdm_log(FTDM_LOG_INFO, "DTMF detection enabled in channel %d:%d\n", ftdm_channel_get_id(tech_pvt->ftdmchan), ftdm_channel_get_span_id(tech_pvt->ftdmchan)); -} - -SWITCH_STANDARD_APP(disable_dtmf_function) -{ - private_t *tech_pvt; - - if (!switch_core_session_check_interface(session, freetdm_endpoint_interface)) { - ftdm_log(FTDM_LOG_ERROR, "This application is only for FreeTDM channels.\n"); - return; - } - - tech_pvt = switch_core_session_get_private(session); - - if (switch_test_flag(tech_pvt, TFLAG_DEAD)) { - switch_channel_hangup(switch_core_session_get_channel(session), SWITCH_CAUSE_LOSE_RACE); - return; - } - - ftdm_channel_command(tech_pvt->ftdmchan, FTDM_COMMAND_DISABLE_DTMF_DETECT, NULL); - ftdm_log(FTDM_LOG_INFO, "DTMF detection Disabled in channel %d:%d\n", ftdm_channel_get_id(tech_pvt->ftdmchan), ftdm_channel_get_span_id(tech_pvt->ftdmchan)); -} - -SWITCH_STANDARD_APP(disable_ec_function) -{ - private_t *tech_pvt; - int x = 0; - - if (!switch_core_session_check_interface(session, freetdm_endpoint_interface)) { - ftdm_log(FTDM_LOG_ERROR, "This application is only for FreeTDM channels.\n"); - return; - } - - tech_pvt = switch_core_session_get_private(session); - - if (switch_test_flag(tech_pvt, TFLAG_DEAD)) { - switch_channel_hangup(switch_core_session_get_channel(session), SWITCH_CAUSE_LOSE_RACE); - return; - } - - ftdm_channel_command(tech_pvt->ftdmchan, FTDM_COMMAND_DISABLE_ECHOCANCEL, &x); - ftdm_channel_command(tech_pvt->ftdmchan, FTDM_COMMAND_DISABLE_ECHOTRAIN, &x); - ftdm_log(FTDM_LOG_INFO, "Echo Canceller Disabled\n"); -} - - -SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load) -{ - int i = 0; - ftdm_cli_entry_t *entry = NULL; - switch_api_interface_t *commands_api_interface = NULL; - switch_application_interface_t *app_interface = NULL; - - module_pool = pool; - - ftdm_global_set_logger(ftdm_logger); - - ftdm_global_set_mod_directory(SWITCH_GLOBAL_dirs.mod_dir); - - ftdm_global_set_config_directory(SWITCH_GLOBAL_dirs.conf_dir); - - if (load_config_path() != SWITCH_STATUS_SUCCESS) { - ftdm_global_destroy(); - return SWITCH_STATUS_TERM; - } - - if (ftdm_global_init() != FTDM_SUCCESS) { - ftdm_global_destroy(); - ftdm_log(FTDM_LOG_ERROR, "Error loading FreeTDM\n"); - return SWITCH_STATUS_TERM; - } - - if (ftdm_global_configuration() != FTDM_SUCCESS) { - ftdm_global_destroy(); - ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM\n"); - return SWITCH_STATUS_TERM; - } - - if (load_config() != SWITCH_STATUS_SUCCESS) { - ftdm_global_destroy(); - return SWITCH_STATUS_TERM; - } - - *module_interface = switch_loadable_module_create_module_interface(pool, modname); - freetdm_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE); - freetdm_endpoint_interface->interface_name = "freetdm"; - freetdm_endpoint_interface->io_routines = &freetdm_io_routines; - freetdm_endpoint_interface->state_handler = &freetdm_state_handlers; - - SWITCH_ADD_API(commands_api_interface, "ftdm", "FreeTDM commands", ftdm_api_exec, " "); - for (i = 0 ; i < ftdm_array_len(ftdm_cli_options); i++) { - char complete_cli[512]; - entry = &ftdm_cli_options[i]; - if (entry->execute_api) { - /* This is a stand-alone API */ - SWITCH_ADD_API(commands_api_interface, entry->name, entry->desc, ftdm_api_exec_usage, entry->args); - snprintf(complete_cli, sizeof(complete_cli), "add %s %s", entry->name, entry->complete); - switch_console_set_complete(complete_cli); - } else { - snprintf(complete_cli, sizeof(complete_cli), "add ftdm %s %s", entry->name, entry->complete); - switch_console_set_complete(complete_cli); - } - } - - SWITCH_ADD_APP(app_interface, "disable_ec", "Disable Echo Canceller", "Disable Echo Canceller", disable_ec_function, "", SAF_NONE); - SWITCH_ADD_APP(app_interface, "disable_dtmf", "Disable DTMF Detection", "Disable DTMF Detection", disable_dtmf_function, "", SAF_NONE); - SWITCH_ADD_APP(app_interface, "enable_dtmf", "Enable DTMF Detection", "Enable DTMF Detection", enable_dtmf_function, "", SAF_NONE); -#if 0 - ctdm_init(*module_interface); -#endif - /* indicate that the module should continue to be loaded */ - return SWITCH_STATUS_SUCCESS; -} - -SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_freetdm_shutdown) -{ - switch_hash_index_t *hi; - const void *var; - void *val; - - /* destroy ss7 configs */ - for (hi = switch_core_hash_first(globals.ss7_configs); hi; hi = switch_core_hash_next(&hi)) { - switch_core_hash_this(hi, &var, NULL, &val); - ftdm_conf_node_destroy(val); - } - - switch_core_hash_destroy(&globals.ss7_configs); - ftdm_global_destroy(); - - // this breaks pika but they are MIA so *shrug* - //return SWITCH_STATUS_NOUNLOAD; - return SWITCH_STATUS_SUCCESS; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/mod_freetdm/mod_openzap.2005.vcproj b/libs/freetdm/mod_freetdm/mod_openzap.2005.vcproj deleted file mode 100644 index 491d0d574a..0000000000 --- a/libs/freetdm/mod_freetdm/mod_openzap.2005.vcproj +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/mod_freetdm/tdm.c b/libs/freetdm/mod_freetdm/tdm.c deleted file mode 100644 index d53c8a584b..0000000000 --- a/libs/freetdm/mod_freetdm/tdm.c +++ /dev/null @@ -1,719 +0,0 @@ -/* -* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application -* Copyright (C) 2005-2011, Anthony Minessale II -* -* Version: MPL 1.1 -* -* The contents of this file are subject to the Mozilla Public License Version -* 1.1 (the "License"); you may not use this file except in compliance with -* the License. You may obtain a copy of the License at -* http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS IS" basis, -* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -* for the specific language governing rights and limitations under the -* License. -* -* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application -* -* The Initial Developer of the Original Code is -* Anthony Minessale II -* Portions created by the Initial Developer are Copyright (C) -* the Initial Developer. All Rights Reserved. -* -* Contributor(s): -* -* Mathieu Rene -* -* tdm.c -- FreeTDM Controllable Channel Module -* -*/ - -#include -#include "freetdm.h" - -void ctdm_init(switch_loadable_module_interface_t *module_interface); - -/* Parameters */ - -#define kSPAN_ID "span" -#define kCHAN_ID "chan" -#define kSPAN_NAME "span_name" -#define kPREBUFFER_LEN "prebuffer_len" -#define kECHOCANCEL "echo_cancel" - - -static struct { - switch_memory_pool_t *pool; - switch_endpoint_interface_t *endpoint_interface; -} ctdm; - -typedef struct { - int span_id; - int chan_id; - ftdm_channel_t *ftdm_channel; - switch_core_session_t *session; - switch_codec_t read_codec, write_codec; - switch_frame_t read_frame; - int prebuffer_len; - - unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; -} ctdm_private_t; - -static switch_status_t channel_on_init(switch_core_session_t *session); -static switch_status_t channel_on_destroy(switch_core_session_t *session); -static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, - switch_caller_profile_t *outbound_profile, - switch_core_session_t **new_session, - switch_memory_pool_t **pool, - switch_originate_flag_t flags, switch_call_cause_t *cancel_cause); -static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id); -static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id); -static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg); -static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event); -static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf); - - -static ftdm_status_t ctdm_span_prepare(ftdm_span_t *span); - -switch_state_handler_table_t ctdm_state_handlers = { - .on_init = channel_on_init, - .on_destroy = channel_on_destroy -}; - -switch_io_routines_t ctdm_io_routines = { - .send_dtmf = channel_send_dtmf, - .outgoing_channel = channel_outgoing_channel, - .read_frame = channel_read_frame, - .write_frame = channel_write_frame, - .receive_message = channel_receive_message, - .receive_event = channel_receive_event -}; - -static void ctdm_report_alarms(ftdm_channel_t *channel) -{ - switch_event_t *event = NULL; - ftdm_alarm_flag_t alarmflag = 0; - - if (switch_event_create(&event, SWITCH_EVENT_TRAP) != SWITCH_STATUS_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "failed to create alarms events\n"); - return; - } - - if (ftdm_channel_get_alarms(channel, &alarmflag) != FTDM_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to retrieve alarms %s:%d\n", ftdm_channel_get_span_name(channel), ftdm_channel_get_id(channel)); - return; - } - - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-name", "%s", ftdm_channel_get_span_name(channel)); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-number", "%d", ftdm_channel_get_span_id(channel)); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "chan-number", "%d", ftdm_channel_get_id(channel)); - - if (alarmflag) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-trap"); - } else { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-clear"); - } - - if (alarmflag & FTDM_ALARM_RED) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "red"); - } - if (alarmflag & FTDM_ALARM_YELLOW) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "yellow"); - } - if (alarmflag & FTDM_ALARM_RAI) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "rai"); - } - if (alarmflag & FTDM_ALARM_BLUE) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "blue"); - } - if (alarmflag & FTDM_ALARM_AIS) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "ais"); - } - if (alarmflag & FTDM_ALARM_GENERAL) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "general"); - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Reporting [%s] alarms for %s:%d\n", - (alarmflag?"ftdm-alarm-trap":"ftdm-alarm-clear"), ftdm_channel_get_span_name(channel), ftdm_channel_get_id(channel)); - - switch_event_fire(&event); - return; -} - -static ftdm_channel_t *ctdm_get_channel_from_event(switch_event_t *event, ftdm_span_t *span) -{ - uint32_t chan_id = 0; - const char *chan_number = NULL; - - chan_number = switch_event_get_header(event, "chan-number"); - - if (zstr(chan_number)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No channel number specified\n"); - return NULL; - } - chan_id = atoi(chan_number); - if (!chan_id) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid channel number:%s\n", chan_number); - return NULL; - } - - return ftdm_span_get_channel_ph(span, chan_id); -} - - -static void ctdm_event_handler(switch_event_t *event) -{ - ftdm_status_t status = FTDM_FAIL; - switch(event->event_id) { - case SWITCH_EVENT_TRAP: - { - ftdm_span_t *span = NULL; - ftdm_channel_t *channel = NULL; - const char *span_name = NULL; - - const char *cond = switch_event_get_header(event, "condition"); - const char *command = switch_event_get_header(event, "command"); - if (zstr(cond)) { - return; - } - - span_name = switch_event_get_header(event, "span-name"); - - if (ftdm_span_find_by_name(span_name, &span) != FTDM_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find span [%s]\n", span_name); - return; - } - - if (!strcmp(cond, "mg-tdm-prepare")) { - status = ctdm_span_prepare(span); - if (status == FTDM_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s:prepared successfully\n", span_name); - } else if (status != FTDM_EINVAL) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s:Failed to prepare span\n", span_name); - } - } else if (!strcmp(cond, "mg-tdm-check")) { - channel = ctdm_get_channel_from_event(event, span); - if (!channel) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find channel\n"); - return; - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Requesting alarm status for %s:%d\n", - ftdm_channel_get_span_name(channel), ftdm_channel_get_id(channel)); - - ctdm_report_alarms(channel); - } else if (!strcmp(cond, "mg-tdm-dtmfremoval")) { - uint8_t enable = 0; - channel = ctdm_get_channel_from_event(event, span); - if (!channel) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find channel\n"); - return; - } - - if (zstr(command)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s:No command specified for mg-tdm-dtmfremoval\n", span_name); - return; - } - - if (!strcmp(command, "enable")) { - enable = 1; - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s DTMF-removal for %s:%d\n", - enable ? "Enabling" : "Disabling", ftdm_channel_get_span_name(channel), ftdm_channel_get_id(channel)); - - ftdm_channel_command(channel, enable ? FTDM_COMMAND_ENABLE_DTMF_REMOVAL : FTDM_COMMAND_DISABLE_DTMF_REMOVAL, 0); - } - } - break; - default: - break; - } - return; -} - -void ctdm_init(switch_loadable_module_interface_t *module_interface) -{ - switch_endpoint_interface_t *endpoint_interface; - ctdm.pool = module_interface->pool; - endpoint_interface = switch_loadable_module_create_interface(module_interface, SWITCH_ENDPOINT_INTERFACE); - endpoint_interface->interface_name = "tdm"; - endpoint_interface->io_routines = &ctdm_io_routines; - endpoint_interface->state_handler = &ctdm_state_handlers; - ctdm.endpoint_interface = endpoint_interface; - - switch_event_bind("mod_freetdm", SWITCH_EVENT_TRAP, SWITCH_EVENT_SUBCLASS_ANY, ctdm_event_handler, NULL); -} - -static FIO_SIGNAL_CB_FUNCTION(on_signal_cb) -{ - uint32_t chanid, spanid; - switch_event_t *event = NULL; - ftdm_alarm_flag_t alarmbits = FTDM_ALARM_NONE; - - chanid = ftdm_channel_get_id(sigmsg->channel); - spanid = ftdm_channel_get_span_id(sigmsg->channel); - - switch(sigmsg->event_id) { - case FTDM_SIGEVENT_ALARM_CLEAR: - case FTDM_SIGEVENT_ALARM_TRAP: - { - if (ftdm_channel_get_alarms(sigmsg->channel, &alarmbits) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "failed to retrieve alarms\n"); - return FTDM_FAIL; - } - - if (switch_event_create(&event, SWITCH_EVENT_TRAP) != SWITCH_STATUS_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "failed to create alarms events\n"); - return FTDM_FAIL; - } - if (sigmsg->event_id == FTDM_SIGEVENT_ALARM_CLEAR) { - ftdm_log(FTDM_LOG_NOTICE, "Alarm cleared on channel %d:%d\n", spanid, chanid); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-clear"); - } else { - ftdm_log(FTDM_LOG_NOTICE, "Alarm raised on channel %d:%d\n", spanid, chanid); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-trap"); - } - } - break; - default: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unhandled event %d\n", sigmsg->event_id); - break; - } - - if (event) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-name", "%s", ftdm_channel_get_span_name(sigmsg->channel)); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-number", "%d", ftdm_channel_get_span_id(sigmsg->channel)); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "chan-number", "%d", ftdm_channel_get_id(sigmsg->channel)); - - if (alarmbits & FTDM_ALARM_RED) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "red"); - } - if (alarmbits & FTDM_ALARM_YELLOW) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "yellow"); - } - if (alarmbits & FTDM_ALARM_RAI) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "rai"); - } - if (alarmbits & FTDM_ALARM_BLUE) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "blue"); - } - if (alarmbits & FTDM_ALARM_AIS) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "ais"); - } - if (alarmbits & FTDM_ALARM_GENERAL) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "general"); - } - - switch_event_fire(&event); - } - return FTDM_SUCCESS; -} - -static ftdm_status_t ctdm_span_prepare(ftdm_span_t *span) -{ - if (ftdm_span_register_signal_cb(span, on_signal_cb) != FTDM_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register signal CB\n"); - return FTDM_FAIL; - } - return ftdm_span_start(span); -} - -static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, - switch_caller_profile_t *outbound_profile, - switch_core_session_t **new_session, - switch_memory_pool_t **pool, - switch_originate_flag_t flags, switch_call_cause_t *cancel_cause) -{ - const char *szchanid = switch_event_get_header(var_event, kCHAN_ID), - *span_name = switch_event_get_header(var_event, kSPAN_NAME), - *szprebuffer_len = switch_event_get_header(var_event, kPREBUFFER_LEN); - int chan_id; - int span_id; - switch_caller_profile_t *caller_profile; - ftdm_span_t *span; - ftdm_channel_t *chan; - switch_channel_t *channel; - char name[128]; - const char *dname; - ftdm_codec_t codec; - uint32_t interval; - ctdm_private_t *tech_pvt = NULL; - - if (zstr(szchanid) || zstr(span_name)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Both ["kSPAN_ID"] and ["kCHAN_ID"] have to be set.\n"); - goto fail; - } - - chan_id = atoi(szchanid); - - if (ftdm_span_find_by_name(span_name, &span) == FTDM_SUCCESS) { - span_id = ftdm_span_get_id(span); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find span [%s]\n", span_name); - goto fail; - } - - if (!(*new_session = switch_core_session_request(ctdm.endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, 0, pool))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't request session.\n"); - goto fail; - } - - channel = switch_core_session_get_channel(*new_session); - - if (ftdm_channel_open_ph(span_id, chan_id, &chan) != FTDM_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't open span or channel.\n"); - goto fail; - } - - switch_channel_set_flag(channel, CF_AUDIO); - - span = ftdm_channel_get_span(chan); - - tech_pvt = switch_core_session_alloc(*new_session, sizeof *tech_pvt); - tech_pvt->chan_id = chan_id; - tech_pvt->span_id = span_id; - tech_pvt->ftdm_channel = chan; - tech_pvt->session = *new_session; - tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf); - tech_pvt->read_frame.data = tech_pvt->databuf; - tech_pvt->prebuffer_len = zstr(szprebuffer_len) ? 0 : atoi(szprebuffer_len); - switch_core_session_set_private(*new_session, tech_pvt); - - - caller_profile = switch_caller_profile_clone(*new_session, outbound_profile); - switch_channel_set_caller_profile(channel, caller_profile); - - snprintf(name, sizeof(name), "tdm/%d:%d", span_id, chan_id); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connect outbound channel %s\n", name); - switch_channel_set_name(channel, name); - - switch_channel_set_state(channel, CS_INIT); - - if (FTDM_SUCCESS != ftdm_channel_command(chan, FTDM_COMMAND_GET_CODEC, &codec)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to retrieve channel codec.\n"); - return SWITCH_CAUSE_NETWORK_OUT_OF_ORDER; - } - - if (FTDM_SUCCESS != ftdm_channel_command(chan, FTDM_COMMAND_GET_INTERVAL, &interval)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to retrieve channel interval.\n"); - return SWITCH_CAUSE_NETWORK_OUT_OF_ORDER; - } - - if (FTDM_SUCCESS != ftdm_channel_command(chan, FTDM_COMMAND_SET_PRE_BUFFER_SIZE, &tech_pvt->prebuffer_len)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set channel pre buffer size.\n"); - return SWITCH_CAUSE_NETWORK_OUT_OF_ORDER; - } - - if (FTDM_SUCCESS != ftdm_channel_command(tech_pvt->ftdm_channel, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to set enable echo cancellation.\n"); - } - - switch(codec) { - case FTDM_CODEC_ULAW: - { - dname = "PCMU"; - } - break; - case FTDM_CODEC_ALAW: - { - dname = "PCMA"; - } - break; - case FTDM_CODEC_SLIN: - { - dname = "L16"; - } - break; - default: - { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid codec value retrieved from channel, codec value: %d\n", codec); - goto fail; - } - } - - - if (switch_core_codec_init(&tech_pvt->read_codec, - dname, - NULL, - NULL, - 8000, - interval, - 1, - SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, - NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); - goto fail; - } else { - if (switch_core_codec_init(&tech_pvt->write_codec, - dname, - NULL, - NULL, - 8000, - interval, - 1, - SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, - NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); - switch_core_codec_destroy(&tech_pvt->read_codec); - goto fail; - } - } - - if (switch_core_session_set_read_codec(*new_session, &tech_pvt->read_codec) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set read codec?\n"); - goto fail; - } - - if (switch_core_session_set_write_codec(*new_session, &tech_pvt->write_codec) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set write codec?\n"); - } - - if (switch_core_session_thread_launch(*new_session) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't start session thread.\n"); - goto fail; - } - - switch_channel_mark_answered(channel); - - return SWITCH_CAUSE_SUCCESS; - -fail: - - if (tech_pvt) { - if (tech_pvt->ftdm_channel) { - ftdm_channel_close(&tech_pvt->ftdm_channel); - } - - if (tech_pvt->read_codec.implementation) { - switch_core_codec_destroy(&tech_pvt->read_codec); - } - - if (tech_pvt->write_codec.implementation) { - switch_core_codec_destroy(&tech_pvt->write_codec); - } - } - - if (*new_session) { - switch_core_session_destroy(new_session); - } - return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; -} - -static switch_status_t channel_on_init(switch_core_session_t *session) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - - switch_channel_set_state(channel, CS_CONSUME_MEDIA); - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_on_destroy(switch_core_session_t *session) -{ - ctdm_private_t *tech_pvt = switch_core_session_get_private(session); - - if ((tech_pvt = switch_core_session_get_private(session))) { - - if (FTDM_SUCCESS != ftdm_channel_command(tech_pvt->ftdm_channel, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to enable echo cancellation.\n"); - } - - if (tech_pvt->read_codec.implementation) { - switch_core_codec_destroy(&tech_pvt->read_codec); - } - - if (tech_pvt->write_codec.implementation) { - switch_core_codec_destroy(&tech_pvt->write_codec); - } - - switch_core_session_unset_read_codec(session); - switch_core_session_unset_write_codec(session); - - ftdm_channel_close(&tech_pvt->ftdm_channel); - } - - return SWITCH_STATUS_SUCCESS; -} - - -static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id) -{ - ftdm_wait_flag_t wflags = FTDM_READ; - ftdm_status_t status; - ctdm_private_t *tech_pvt; - const char *name; - switch_channel_t *channel; - int chunk; - uint32_t span_id, chan_id; - ftdm_size_t len; - char dtmf[128] = ""; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); - - name = switch_channel_get_name(channel); - -top: - wflags = FTDM_READ; - chunk = ftdm_channel_get_io_interval(tech_pvt->ftdm_channel) * 2; - status = ftdm_channel_wait(tech_pvt->ftdm_channel, &wflags, chunk); - - - span_id = ftdm_channel_get_span_id(tech_pvt->ftdm_channel); - chan_id = ftdm_channel_get_id(tech_pvt->ftdm_channel); - - if (status == FTDM_FAIL) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read from channel %s device %d:%d!\n", name, span_id, chan_id); - goto fail; - } - - if (status == FTDM_TIMEOUT) { - goto top; - } - - if (!(wflags & FTDM_READ)) { - goto top; - } - - len = tech_pvt->read_frame.buflen; - if (ftdm_channel_read(tech_pvt->ftdm_channel, tech_pvt->read_frame.data, &len) != FTDM_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to read from channel %s device %d:%d!\n", name, span_id, chan_id); - } - - *frame = &tech_pvt->read_frame; - tech_pvt->read_frame.datalen = (uint32_t)len; - tech_pvt->read_frame.samples = tech_pvt->read_frame.datalen; - tech_pvt->read_frame.codec = &tech_pvt->read_codec; - - if (ftdm_channel_get_codec(tech_pvt->ftdm_channel) == FTDM_CODEC_SLIN) { - tech_pvt->read_frame.samples /= 2; - } - - while (ftdm_channel_dequeue_dtmf(tech_pvt->ftdm_channel, dtmf, sizeof(dtmf))) { - switch_dtmf_t _dtmf = { 0, switch_core_default_dtmf_duration(0) }; - char *p; - for (p = dtmf; p && *p; p++) { - if (is_dtmf(*p)) { - _dtmf.digit = *p; - ftdm_log(FTDM_LOG_DEBUG, "Queuing DTMF [%c] in channel %s device %d:%d\n", *p, name, span_id, chan_id); - switch_channel_queue_dtmf(channel, &_dtmf); - } - } - } - - return SWITCH_STATUS_SUCCESS; - -fail: - return SWITCH_STATUS_GENERR; -} - -static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id) -{ - ftdm_wait_flag_t wflags = FTDM_WRITE; - ctdm_private_t *tech_pvt; - const char *name; - switch_channel_t *channel; - uint32_t span_id, chan_id; - ftdm_size_t len; - unsigned char data[SWITCH_RECOMMENDED_BUFFER_SIZE] = {0}; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); - - span_id = ftdm_channel_get_span_id(tech_pvt->ftdm_channel); - chan_id = ftdm_channel_get_id(tech_pvt->ftdm_channel); - - name = switch_channel_get_name(channel); - - if (switch_test_flag(frame, SFF_CNG)) { - frame->data = data; - frame->buflen = sizeof(data); - if ((frame->datalen = tech_pvt->write_codec.implementation->encoded_bytes_per_packet) > frame->buflen) { - goto fail; - } - memset(data, 255, frame->datalen); - } - - wflags = FTDM_WRITE; - ftdm_channel_wait(tech_pvt->ftdm_channel, &wflags, ftdm_channel_get_io_interval(tech_pvt->ftdm_channel) * 10); - - if (!(wflags & FTDM_WRITE)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Dropping frame! (write not ready) in channel %s device %d:%d!\n", name, span_id, chan_id); - return SWITCH_STATUS_SUCCESS; - } - - len = frame->datalen; - if (ftdm_channel_write(tech_pvt->ftdm_channel, frame->data, frame->buflen, &len) != FTDM_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Failed to write to channel %s device %d:%d!\n", name, span_id, chan_id); - } - - return SWITCH_STATUS_SUCCESS; - -fail: - return SWITCH_STATUS_GENERR; -} - -static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf) -{ - ctdm_private_t *tech_pvt = NULL; - char tmp[2] = ""; - - tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); - - tmp[0] = dtmf->digit; - ftdm_channel_command(tech_pvt->ftdm_channel, FTDM_COMMAND_SEND_DTMF, tmp); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg) -{ - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event) -{ - const char *command = switch_event_get_header(event, "command"); - ctdm_private_t *tech_pvt = switch_core_session_get_private(session); - - if (!zstr(command)) { - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeTDM received %s command \n",command); - - if (!strcasecmp(command, kPREBUFFER_LEN)) { - const char *szval = switch_event_get_header(event, kPREBUFFER_LEN); - int val = !zstr(szval) ? atoi(szval) : 0; - - if (tech_pvt->prebuffer_len == val) { - tech_pvt->prebuffer_len = val; - if (FTDM_SUCCESS != ftdm_channel_command(tech_pvt->ftdm_channel, FTDM_COMMAND_SET_PRE_BUFFER_SIZE, &tech_pvt->prebuffer_len)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set channel pre buffer size.\n"); - return SWITCH_STATUS_GENERR; - } - } - } else if (!strcasecmp(command, kECHOCANCEL)) { - const char *szval = switch_event_get_header(event, kECHOCANCEL); - int enabled = !!switch_true(szval); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeTDM sending echo cancel [%s] command \n",enabled ? "enable" : "disable"); - - if (FTDM_SUCCESS != ftdm_channel_command(tech_pvt->ftdm_channel, enabled ? FTDM_COMMAND_ENABLE_ECHOCANCEL : FTDM_COMMAND_DISABLE_ECHOCANCEL, NULL)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to %s echo cancellation.\n", enabled ? "enable" : "disable"); - } - - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeTDM received unknown command [%s] \n",command); - } - } - - return SWITCH_STATUS_SUCCESS; -} - diff --git a/libs/freetdm/msvc/freetdm.2008.vcproj b/libs/freetdm/msvc/freetdm.2008.vcproj deleted file mode 100644 index 46594bf38c..0000000000 --- a/libs/freetdm/msvc/freetdm.2008.vcproj +++ /dev/null @@ -1,499 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/msvc/freetdm.2010.vcxproj.filters b/libs/freetdm/msvc/freetdm.2010.vcxproj.filters deleted file mode 100644 index 9f15c9c737..0000000000 --- a/libs/freetdm/msvc/freetdm.2010.vcxproj.filters +++ /dev/null @@ -1,137 +0,0 @@ - - - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - diff --git a/libs/freetdm/msvc/openzap.2005.vcproj b/libs/freetdm/msvc/openzap.2005.vcproj deleted file mode 100644 index 85d4a89206..0000000000 --- a/libs/freetdm/msvc/openzap.2005.vcproj +++ /dev/null @@ -1,301 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/msvc/testanalog/testanalog.2005.vcproj b/libs/freetdm/msvc/testanalog/testanalog.2005.vcproj deleted file mode 100644 index 93553d2a5f..0000000000 --- a/libs/freetdm/msvc/testanalog/testanalog.2005.vcproj +++ /dev/null @@ -1,193 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/msvc/testanalog/testanalog.2008.vcproj b/libs/freetdm/msvc/testanalog/testanalog.2008.vcproj deleted file mode 100644 index 24f418ab19..0000000000 --- a/libs/freetdm/msvc/testanalog/testanalog.2008.vcproj +++ /dev/null @@ -1,349 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj.filters b/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj.filters deleted file mode 100644 index 7ac3635cc5..0000000000 --- a/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj.filters +++ /dev/null @@ -1,14 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Source Files - - - \ No newline at end of file diff --git a/libs/freetdm/msvc/testboost/testboost.2008.vcproj b/libs/freetdm/msvc/testboost/testboost.2008.vcproj deleted file mode 100644 index c273b3c02b..0000000000 --- a/libs/freetdm/msvc/testboost/testboost.2008.vcproj +++ /dev/null @@ -1,354 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/msvc/testboost/testboost.2010.vcxproj.filters b/libs/freetdm/msvc/testboost/testboost.2010.vcxproj.filters deleted file mode 100644 index 74181d60a8..0000000000 --- a/libs/freetdm/msvc/testboost/testboost.2010.vcxproj.filters +++ /dev/null @@ -1,14 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Source Files - - - \ No newline at end of file diff --git a/libs/freetdm/msvc/testboost/testsangomaboost.2008.vcproj b/libs/freetdm/msvc/testboost/testsangomaboost.2008.vcproj deleted file mode 100644 index 77ca1594df..0000000000 --- a/libs/freetdm/msvc/testboost/testsangomaboost.2008.vcproj +++ /dev/null @@ -1,354 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj.filters b/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj.filters deleted file mode 100644 index e72f14e161..0000000000 --- a/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj.filters +++ /dev/null @@ -1,14 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Source Files - - - \ No newline at end of file diff --git a/libs/freetdm/msvc/testisdn/testisdn.2005.vcproj b/libs/freetdm/msvc/testisdn/testisdn.2005.vcproj deleted file mode 100644 index 133557166b..0000000000 --- a/libs/freetdm/msvc/testisdn/testisdn.2005.vcproj +++ /dev/null @@ -1,193 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/msvc/testisdn/testisdn.2008.vcproj b/libs/freetdm/msvc/testisdn/testisdn.2008.vcproj deleted file mode 100644 index 86698ec3e4..0000000000 --- a/libs/freetdm/msvc/testisdn/testisdn.2008.vcproj +++ /dev/null @@ -1,349 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj.filters b/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj.filters deleted file mode 100644 index 9d48828d4a..0000000000 --- a/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj.filters +++ /dev/null @@ -1,14 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Source Files - - - \ No newline at end of file diff --git a/libs/freetdm/sample/CMakeLists.txt b/libs/freetdm/sample/CMakeLists.txt deleted file mode 100644 index 9baf1bdf16..0000000000 --- a/libs/freetdm/sample/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# -# Arnaldo M Pereira -# -CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -PROJECT(sample) - -#ADD_SUBDIRECTORY(sched) FIXME: this code doesnt compile diff --git a/libs/freetdm/sample/dso/CMakeLists.txt b/libs/freetdm/sample/dso/CMakeLists.txt deleted file mode 100644 index defcc5c7f5..0000000000 --- a/libs/freetdm/sample/dso/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# -# Arnaldo M Pereira -# -CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -PROJECT(dso) - -IF(NOT DEFINED WIN32) - INCLUDE_DIRECTORIES(/usr/local/freeswitch/include) - ADD_DEFINITIONS(-Wall) - ADD_EXECUTABLE(ftdmload ftdmload.c) - TARGET_LINK_LIBRARIES(ftdmload freetdm) -ENDIF(NOT DEFINED WIN32) diff --git a/libs/freetdm/sample/dso/Makefile b/libs/freetdm/sample/dso/Makefile deleted file mode 100644 index 51067191d2..0000000000 --- a/libs/freetdm/sample/dso/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -CC=gcc -CFLAGS=-Wall -I/usr/local/freeswitch/include -LDFLAGS=-L/usr/local/freeswitch/lib -lfreetdm - -ftdmload: ftdmload.o - -clean: - rm -rf ftdmload.o - rm -rf ftdmload - -export: - export LD_LIBRARY_PATH=/usr/local/freeswitch/lib - - diff --git a/libs/freetdm/sample/dso/ftdmload.c b/libs/freetdm/sample/dso/ftdmload.c deleted file mode 100644 index 80bcc02fc0..0000000000 --- a/libs/freetdm/sample/dso/ftdmload.c +++ /dev/null @@ -1,168 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include - -#define ARRLEN(obj) (sizeof(obj)/sizeof(obj[0])) - -struct dso_entry { - char name[25]; - ftdm_dso_lib_t lib; -}; - -struct dso_entry loaded[10]; - -static void *(*real_dlopen)(const char *filename, int flag) = NULL; -static int (*real_dlclose)(void *handle) = NULL; - -static void print_stack() -{ - void *stacktrace[100]; - char **symbols; - int size; - int i; - size = backtrace(stacktrace, ARRLEN(stacktrace)); - symbols = backtrace_symbols(stacktrace, size); - if (!symbols) { - return; - } - for (i = 0; i < size; i++) { - ftdm_log(FTDM_LOG_DEBUG, "%s\n", symbols[i]); - } - free(symbols); -} - -void *dlopen(const char *filename, int flag) -{ - char *msg = NULL; - void *handle = NULL; - print_stack(); - if (real_dlopen == NULL) { - dlerror(); - real_dlopen = dlsym(RTLD_NEXT, "dlopen"); - if ((msg = dlerror()) != NULL) { - fprintf(stderr, "dlsym failed: %s\n", msg); - exit(1); - } - fprintf(stderr, "Real dlopen at addr %p\n", real_dlopen); - } - handle = real_dlopen(filename, flag); - if (!handle) { - return NULL; - } - ftdm_log(FTDM_LOG_NOTICE, "Loaded %s with handle %p\n", filename, handle); - return handle; -} - -int dlclose(void *handle) -{ - char *msg = NULL; - print_stack(); - if (real_dlclose == NULL) { - dlerror(); - real_dlclose = dlsym(RTLD_NEXT, "dlclose"); - if ((msg = dlerror()) != NULL) { - fprintf(stderr, "dlsym failed: %s\n", msg); - exit(1); - } - fprintf(stderr, "Real dlclose at addr %p\n", real_dlclose); - } - ftdm_log(FTDM_LOG_NOTICE, "Unloading %p\n", handle); - return real_dlclose(handle); -} - -int load(char *name) -{ - char path[255]; - char *err; - struct dso_entry *entry = NULL; - int i; - - for (i = 0; i < ARRLEN(loaded); i++) { - if (!loaded[i].lib) { - entry = &loaded[i]; - break; - } - } - - if (!entry) { - ftdm_log(FTDM_LOG_CRIT, "Cannot load more libraries\n"); - return -1; - } - - ftdm_build_dso_path(name, path, sizeof(path)); - ftdm_log(FTDM_LOG_DEBUG, "Loading %s!\n", path); - entry->lib = ftdm_dso_open(path, &err); - if (!entry->lib) { - ftdm_log(FTDM_LOG_CRIT, "Cannot load library '%s': %s\n", path, err); - return -1; - } - strncpy(entry->name, name, sizeof(entry->name)-1); - entry->name[sizeof(entry->name)-1] = 0; - return 0; -} - -int unload(char *name) -{ - int i; - struct dso_entry *entry = NULL; - ftdm_log(FTDM_LOG_DEBUG, "Unloading %s!\n", name); - for (i = 0; i < ARRLEN(loaded); i++) { - if (loaded[i].lib && !strcasecmp(loaded[i].name, name)) { - entry = &loaded[i]; - break; - } - } - - if (!entry) { - ftdm_log(FTDM_LOG_CRIT, "Library %s not found\n", name); - return -1; - } - - ftdm_dso_destroy(&entry->lib); - entry->lib = NULL; - return 0; -} - -int main(int argc, char *argv[]) -{ - char cmdline[255]; - char name[255]; - - ftdm_global_set_default_logger(FTDM_LOG_LEVEL_DEBUG); - - if (ftdm_global_init() != FTDM_SUCCESS) { - fprintf(stderr, "Error loading FreeTDM\n"); - exit(-1); - } - - memset(loaded, 0, sizeof(loaded)); - - printf("CLI> "); - while (fgets(cmdline, sizeof(cmdline), stdin)) { - if (sscanf(cmdline, "load=%s\n", name) == 1) { - load(name); - } else if (sscanf(cmdline, "unload=%s\n", name) == 1) { - unload(name); - } else if (!strncasecmp(cmdline, "exit", sizeof("exit")-1)) { - printf("Quitting ...\n"); - sleep(1); - break; - } else { - fprintf(stderr, "load= | unload= | exit\n"); - } - printf("\nCLI> "); - } - - - ftdm_global_destroy(); - - printf("Done, press any key to die!\n"); - - getchar(); - return 0; -} - diff --git a/libs/freetdm/sample/sched/CMakeLists.txt b/libs/freetdm/sample/sched/CMakeLists.txt deleted file mode 100644 index d769925be0..0000000000 --- a/libs/freetdm/sample/sched/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# -# Arnaldo M Pereira -# -CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -PROJECT(sched) - -IF(NOT DEFINED WIN32) - INCLUDE_DIRECTORIES(/usr/local/freeswitch/include) - ADD_DEFINITIONS(-Wall) - ADD_EXECUTABLE(ftdmsched ftdmsched.c) - TARGET_LINK_LIBRARIES(ftdmsched freetdm) -ENDIF(NOT DEFINED WIN32) diff --git a/libs/freetdm/sample/sched/ftdmsched.c b/libs/freetdm/sample/sched/ftdmsched.c deleted file mode 100644 index e6e391ee4b..0000000000 --- a/libs/freetdm/sample/sched/ftdmsched.c +++ /dev/null @@ -1,110 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include -#include "../../src/include/private/ftdm_core.h" - -static int running = 1; - -typedef struct custom_data { - ftdm_timer_t *heartbeat_timer; - int beat; - int counter; - ftdm_sched_callback_t callback; - ftdm_sched_t *sched; -} custom_data_t; - -void trap(int signal) -{ - running = 0; -} - -void handle_heartbeat(void *usrdata) -{ - ftdm_status_t status; - custom_data_t *data = usrdata; - - printf("beep (elapsed %dms count= %d)\n", data->beat, data->counter); - if (data->beat > 1000) { - data->beat -= 1000; - } else if (data->beat <= 1000 && data->beat > 200) { - data->beat -= 100; - } else if (data->beat <= 200 && data->beat > 100) { - if (!data->counter--) { - data->counter = 5; - data->beat -= 100; - } - } else if (data->beat <= 100 && data->beat > 10) { - if (!data->counter--) { - data->counter = 10; - data->beat -= 10; - if (data->beat == 10) { - data->counter = 200; - } - } - } else { - if (!data->counter--) { - data->counter = 5; - data->beat--; - } - } - - if (!data->beat) { - printf("beeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep you're dead!\n"); - return; - } - - data->heartbeat_timer = NULL; - status = ftdm_sched_timer(data->sched, "heartbeat", data->beat, data->callback, data, &data->heartbeat_timer); - if (status != FTDM_SUCCESS) { - fprintf(stderr, "Error creating heartbeat timer\n"); - running = 0; - return; - } -} - -int main(int argc, char *argv[]) -{ - ftdm_status_t status; - custom_data_t data; - - ftdm_sched_t *sched; - signal(SIGINT, trap); - - ftdm_global_set_default_logger(FTDM_LOG_LEVEL_DEBUG); - - if (ftdm_global_init() != FTDM_SUCCESS) { - fprintf(stderr, "Error loading FreeTDM\n"); - exit(-1); - } - - status = ftdm_sched_create(&sched, "testsched"); - if (status != FTDM_SUCCESS) { - fprintf(stderr, "Error creating sched\n"); - exit(-1); - } - - data.sched = sched; - data.counter = 10; - data.beat = 5000; - data.callback = handle_heartbeat; - status = ftdm_sched_timer(sched, "heartbeat", data.beat, data.callback, &data, &data.heartbeat_timer); - if (status != FTDM_SUCCESS) { - fprintf(stderr, "Error creating heartbeat timer\n"); - exit(-1); - } - - ftdm_sched_free_run(sched); - - while (running) { - ftdm_sleep(10); - } - - ftdm_global_destroy(); - - printf("Done, press any key to die!\n"); - - getchar(); - return 0; -} - diff --git a/libs/freetdm/src/detect_dtmf.c b/libs/freetdm/src/detect_dtmf.c deleted file mode 100644 index 34335256f0..0000000000 --- a/libs/freetdm/src/detect_dtmf.c +++ /dev/null @@ -1,54 +0,0 @@ -//#include "freetdm.h" -#include "libteletone_detect.h" - -int main(int argc, char *argv[]) -{ - int fd, b; - short sln[512] = {0}; - teletone_dtmf_detect_state_t dtmf_detect = {0}; - teletone_hit_type_t hit; - - if (argc < 2) { - fprintf(stderr, "Arg Error!\n"); - exit(-1); - } - - teletone_dtmf_detect_init (&dtmf_detect, 8000); - - if ((fd = open(argv[1], O_RDONLY)) < 0) { - fprintf(stderr, "File Error! [%s]\n", strerror(errno)); - exit(-1); - } - - while((b = read(fd, sln, 320)) > 0) { - char digit_char; - unsigned int dur; - - teletone_dtmf_detect(&dtmf_detect, sln, b / 2); - if ((hit = teletone_dtmf_get(&dtmf_detect, &digit_char, &dur))) { - const char *hs = NULL; - - - switch(hit) { - case TT_HIT_BEGIN: - hs = "begin"; - break; - - case TT_HIT_MIDDLE: - hs = "middle"; - break; - - case TT_HIT_END: - hs = "end"; - break; - default: - break; - } - - printf("%s digit: %c\n", hs, digit_char); - } - } - close(fd); - return 0; -} - diff --git a/libs/freetdm/src/detect_tones.c b/libs/freetdm/src/detect_tones.c deleted file mode 100644 index 5cd52d4d99..0000000000 --- a/libs/freetdm/src/detect_tones.c +++ /dev/null @@ -1,32 +0,0 @@ -//#include "freetdm.h" -#include "libteletone_detect.h" - -int main(int argc, char *argv[]) -{ - teletone_multi_tone_t mt = {0}; - teletone_tone_map_t map = {{0}}; - - int fd, b; - short sln[512] = {0}; - - if (argc < 2) { - fprintf(stderr, "Arg Error!\n"); - exit(-1); - } - - map.freqs[0] = atof("350"); - map.freqs[1] = atof("440"); - teletone_multi_tone_init(&mt, &map); - - if ((fd = open(argv[1], O_RDONLY)) < 0) { - fprintf(stderr, "File Error! [%s]\n", strerror(errno)); - exit(-1); - } - - while((b = read(fd, sln, 320)) > 0) { - printf("TEST %d %d\n", b, teletone_multi_tone_detect(&mt, sln, b / 2)); - } - close(fd); - return 0; -} - diff --git a/libs/freetdm/src/fsk.c b/libs/freetdm/src/fsk.c deleted file mode 100644 index 9e6f97287e..0000000000 --- a/libs/freetdm/src/fsk.c +++ /dev/null @@ -1,351 +0,0 @@ - -/* - * bell202.c - * - * Copyright (c) 2005 Robert Krten. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This module contains a Bell-202 1200-baud FSK decoder, suitable for - * use in a library. The general style of the library calls is modeled - * after the POSIX pthread_*() functions. - * - * 2005 03 20 R. Krten created -*/ -#include -#include -#include -#include -#include -#include - -#include "fsk.h" -#include "uart.h" - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -fsk_modem_definition_t fsk_modem_definitions[] = -{ - { /* FSK_V23_FORWARD_MODE1 */ 1700, 1300, 600 }, - { /* FSK_V23_FORWARD_MODE2 */ 2100, 1300, 1200 }, - { /* FSK_V23_BACKWARD */ 450, 390, 75 }, - { /* FSK_BELL202 */ 2200, 1200, 1200 }, -}; - -/* - * dsp_fsk_attr_init - * - * Initializes the attributes structure; this must be done before the - * attributes structure is used. -*/ - -void dsp_fsk_attr_init (dsp_fsk_attr_t *attr) -{ - memset(attr, 0, sizeof(*attr)); -} - -/* - * dsp_fsk_attr_get_bithandler - * dsp_fsk_attr_set_bithandler - * dsp_fsk_attr_get_bytehandler - * dsp_fsk_attr_set_bytehandler - * dsp_fsk_attr_getsamplerate - * dsp_fsk_attr_setsamplerate - * - * These functions get and set their respective elements from the - * attributes structure. If an error code is returned, it is just - * zero == ok, -1 == fail. -*/ - -bithandler_func_t dsp_fsk_attr_get_bithandler(dsp_fsk_attr_t *attr, void **bithandler_arg) -{ - *bithandler_arg = attr->bithandler_arg; - return attr->bithandler; -} - -void dsp_fsk_attr_set_bithandler(dsp_fsk_attr_t *attr, bithandler_func_t bithandler, void *bithandler_arg) -{ - attr->bithandler = bithandler; - attr->bithandler_arg = bithandler_arg; -} - -bytehandler_func_t dsp_fsk_attr_get_bytehandler(dsp_fsk_attr_t *attr, void **bytehandler_arg) -{ - *bytehandler_arg = attr->bytehandler_arg; - return attr->bytehandler; -} - -void dsp_fsk_attr_set_bytehandler(dsp_fsk_attr_t *attr, bytehandler_func_t bytehandler, void *bytehandler_arg) -{ - attr->bytehandler = bytehandler; - attr->bytehandler_arg = bytehandler_arg; -} - -int dsp_fsk_attr_get_samplerate (dsp_fsk_attr_t *attr) -{ - return attr->sample_rate; -} - -int dsp_fsk_attr_set_samplerate (dsp_fsk_attr_t *attr, int samplerate) -{ - if (samplerate <= 0) { - return -1; - } - attr->sample_rate = samplerate; - return 0; -} - -/* - * dsp_fsk_create - * - * Creates a handle for subsequent use. The handle is created to contain - * a context data structure for use by the sample handler function. The - * function expects an initialized attributes structure, and returns the - * handle or a NULL if there were errors. - * - * Once created, the handle can be used until it is destroyed. -*/ - -dsp_fsk_handle_t *dsp_fsk_create(dsp_fsk_attr_t *attr) -{ - int i; - double phi_mark, phi_space; - dsp_fsk_handle_t *handle; - - handle = ftdm_malloc(sizeof(*handle)); - if (!handle) { - return NULL; - } - - memset(handle, 0, sizeof(*handle)); - - /* fill the attributes member */ - memcpy(&handle->attr, attr, sizeof(*attr)); - - /* see if we can do downsampling. We only really need 6 samples to "match" */ - if (attr->sample_rate / fsk_modem_definitions[FSK_BELL202].freq_mark > 6) { - handle->downsampling_count = attr->sample_rate / fsk_modem_definitions[FSK_BELL202].freq_mark / 6; - } else { - handle->downsampling_count = 1; - } - handle->current_downsample = 1; - - /* calculate the correlate size (number of samples required for slowest wave) */ - handle->corrsize = attr->sample_rate / handle->downsampling_count / fsk_modem_definitions[FSK_BELL202].freq_mark; - - /* allocate the correlation sin/cos arrays and initialize */ - for (i = 0; i < 4; i++) { - handle->correlates[i] = ftdm_malloc(sizeof(double) * handle->corrsize); - if (handle->correlates[i] == NULL) { - /* some failed, back out memory allocations */ - dsp_fsk_destroy(&handle); - return NULL; - } - } - - /* now initialize them */ - phi_mark = 2. * M_PI / ((double) attr->sample_rate / (double) handle->downsampling_count / (double) fsk_modem_definitions[FSK_BELL202].freq_mark); - phi_space = 2. * M_PI / ((double) attr->sample_rate / (double) handle->downsampling_count / (double) fsk_modem_definitions[FSK_BELL202].freq_space); - - for (i = 0; i < handle->corrsize; i++) { - handle->correlates[0][i] = sin(phi_mark * (double) i); - handle->correlates[1][i] = cos(phi_mark * (double) i); - handle->correlates[2][i] = sin(phi_space * (double) i); - handle->correlates[3][i] = cos(phi_space * (double) i); - } - - /* initialize the ring buffer */ - handle->buffer = ftdm_malloc(sizeof(double) * handle->corrsize); - if (!handle->buffer) { /* failed; back out memory allocations */ - dsp_fsk_destroy(&handle); - return NULL; - } - memset(handle->buffer, 0, sizeof(double) * handle->corrsize); - handle->ringstart = 0; - - /* initalize intra-cell position */ - handle->cellpos = 0; - handle->celladj = fsk_modem_definitions[FSK_BELL202].baud_rate / (double) attr->sample_rate * (double) handle->downsampling_count; - - /* if they have provided a byte handler, add a UART to the processing chain */ - if (handle->attr.bytehandler) { - dsp_uart_attr_t uart_attr; - dsp_uart_handle_t *uart_handle; - - dsp_uart_attr_init(&uart_attr); - dsp_uart_attr_set_bytehandler(&uart_attr, handle->attr.bytehandler, handle->attr.bytehandler_arg); - uart_handle = dsp_uart_create(&uart_attr); - if (uart_handle == NULL) { - dsp_fsk_destroy(&handle); - return NULL; - } - handle->attr.bithandler = dsp_uart_bit_handler; - handle->attr.bithandler_arg = uart_handle; - } - - return handle; -} - -/* - * dsp_fsk_destroy - * - * Destroys a handle, releasing any associated memory. Sets handle pointer to NULL - * so A destroyed handle can not be used for anything after the destroy. -*/ - -void dsp_fsk_destroy(dsp_fsk_handle_t **handle) -{ - int i; - - /* if empty handle, just return */ - if (*handle == NULL) { - return; - } - - for (i = 0; i < 4; i++) { - if ((*handle)->correlates[i] != NULL) { - ftdm_safe_free((*handle)->correlates[i]); - (*handle)->correlates[i] = NULL; - } - } - - if ((*handle)->buffer != NULL) { - ftdm_safe_free((*handle)->buffer); - (*handle)->buffer = NULL; - } - - if ((*handle)->attr.bytehandler) { - dsp_uart_handle_t** dhandle = (void *)(&(*handle)->attr.bithandler_arg); - dsp_uart_destroy(dhandle); - } - - ftdm_safe_free(*handle); - *handle = NULL; -} - -/* - * dsp_fsk_sample - * - * This is the main processing entry point. The function accepts a normalized - * sample (i.e., one whose range is between -1 and +1). The function performs - * the Bell-202 FSK modem decode processing, and, if it detects a valid bit, - * will call the bithandler associated with the attributes structure. - * - * For the Bell-202 standard, a logical zero (space) is 2200 Hz, and a logical - * one (mark) is 1200 Hz. -*/ - -void -dsp_fsk_sample (dsp_fsk_handle_t *handle, double normalized_sample) -{ - double val; - double factors[4]; - int i, j; - - /* if we can avoid processing samples, do so */ - if (handle->downsampling_count != 1) { - if (handle->current_downsample < handle->downsampling_count) { - handle->current_downsample++; - return; /* throw this sample out */ - } - handle->current_downsample = 1; - } - - /* store sample in buffer */ - handle->buffer[handle->ringstart++] = normalized_sample; - if (handle->ringstart >= handle->corrsize) { - handle->ringstart = 0; - } - - /* do the correlation calculation */ - factors[0] = factors[1] = factors[2] = factors[3] = 0; /* clear out intermediate sums */ - j = handle->ringstart; - for (i = 0; i < handle->corrsize; i++) { - if (j >= handle->corrsize) { - j = 0; - } - val = handle->buffer[j]; - factors[0] += handle->correlates[0][i] * val; - factors[1] += handle->correlates[1][i] * val; - factors[2] += handle->correlates[2][i] * val; - factors[3] += handle->correlates[3][i] * val; - j++; - } - - /* store the bit (bit value is comparison of the two sets of correlate factors) */ - handle->previous_bit = handle->current_bit; - handle->current_bit = (factors[0] * factors[0] + factors[1] * factors[1] > factors[2] * factors[2] + factors[3] * factors[3]); - - /* if there's a transition, we can synchronize the cell position */ - if (handle->previous_bit != handle->current_bit) { - handle->cellpos = 0.5; /* adjust cell position to be in the middle of the cell */ - } - handle->cellpos += handle->celladj; /* walk the cell along */ - - if (handle->cellpos > 1.0) { - handle->cellpos -= 1.0; - - switch (handle->state) { - case FSK_STATE_DATA: - { - - (*handle->attr.bithandler) (handle->attr.bithandler_arg, handle->current_bit); - } - break; - case FSK_STATE_CHANSEIZE: - { - - if (handle->last_bit != handle->current_bit) { - handle->conscutive_state_bits++; - } else { - handle->conscutive_state_bits = 0; - } - - if (handle->conscutive_state_bits > 15) { - handle->state = FSK_STATE_CARRIERSIG; - handle->conscutive_state_bits = 0; - } - } - break; - case FSK_STATE_CARRIERSIG: - { - if (handle->current_bit) { - handle->conscutive_state_bits++; - } else { - handle->conscutive_state_bits = 0; - } - - if (handle->conscutive_state_bits > 15) { - handle->state = FSK_STATE_DATA; - handle->conscutive_state_bits = 0; - } - } - break; - } - - handle->last_bit = handle->current_bit; - } -} - diff --git a/libs/freetdm/src/ftdm_backtrace.c b/libs/freetdm/src/ftdm_backtrace.c deleted file mode 100644 index 8f6756d939..0000000000 --- a/libs/freetdm/src/ftdm_backtrace.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * - * - */ -#ifndef _DEFAULT_SOURCE -#define _DEFAULT_SOURCE -#endif -#define _BSD_SOURCE -#include "private/ftdm_core.h" - -#if defined(HAVE_EXECINFO_H) && !defined(__FreeBSD__) -#include -#include -#include -#include - -#define FTDM_BACKTRACE_MAX 50 - -FT_DECLARE(ftdm_status_t) ftdm_backtrace_walk(void (* callback)(const int tid, const void *addr, const char *symbol, void *priv), void *priv) -{ - void *stacktrace[FTDM_BACKTRACE_MAX]; - char **symbols = NULL; - size_t size = 0; - pid_t tid = 0; - int si = 0; - - if (!callback) { - return FTDM_EINVAL; - } - - tid = syscall(SYS_gettid); - - size = backtrace(stacktrace, ftdm_array_len(stacktrace)); - symbols = backtrace_symbols(stacktrace, size); - - for (si = 0; si < size; si++) { - callback(tid, stacktrace[si], symbols[si], priv); - } - - free(symbols); - return FTDM_SUCCESS; -} - -#else /* !HAVE_EXECINFO_H */ - -FT_DECLARE(ftdm_status_t) ftdm_backtrace_walk(void (* callback)(const int tid, const void *addr, const char *symbol, void *priv), void *priv) -{ - ftdm_log(FTDM_LOG_DEBUG, "Stack traces are not available on this platform!\n"); - return FTDM_NOTIMPL; -} - -#endif - - -static void span_backtrace(const int tid, const void *addr, const char *symbol, void *priv) -{ - ftdm_span_t *span = priv; - ftdm_log(FTDM_LOG_DEBUG, "[%d][tid:%d] %p -> %s\n", - ftdm_span_get_id(span), tid, addr, symbol); -} - -FT_DECLARE(ftdm_status_t) ftdm_backtrace_span(ftdm_span_t *span) -{ - return ftdm_backtrace_walk(&span_backtrace, span); -} - - -static void chan_backtrace(const int tid, const void *addr, const char *symbol, void *priv) -{ - ftdm_channel_t *chan = priv; - ftdm_log(FTDM_LOG_DEBUG, "[%d:%d][tid:%d] %p -> %s\n", - ftdm_channel_get_span_id(chan), ftdm_channel_get_id(chan), tid, addr, symbol); -} - -FT_DECLARE(ftdm_status_t) ftdm_backtrace_chan(ftdm_channel_t *chan) -{ - return ftdm_backtrace_walk(&chan_backtrace, chan); -} diff --git a/libs/freetdm/src/ftdm_buffer.c b/libs/freetdm/src/ftdm_buffer.c deleted file mode 100644 index 42d5fbaec6..0000000000 --- a/libs/freetdm/src/ftdm_buffer.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "private/ftdm_core.h" -#include "ftdm_buffer.h" - -static unsigned buffer_id = 0; - -struct ftdm_buffer { - unsigned char *data; - unsigned char *head; - ftdm_size_t used; - ftdm_size_t actually_used; - ftdm_size_t datalen; - ftdm_size_t max_len; - ftdm_size_t blocksize; - unsigned id; - int loops; -}; - - -FT_DECLARE(ftdm_status_t) ftdm_buffer_create(ftdm_buffer_t **buffer, ftdm_size_t blocksize, ftdm_size_t start_len, ftdm_size_t max_len) -{ - ftdm_buffer_t *new_buffer; - - new_buffer = ftdm_malloc(sizeof(*new_buffer)); - if (new_buffer) { - memset(new_buffer, 0, sizeof(*new_buffer)); - - if (!start_len) { - start_len = 250; - } - - if (!blocksize) { - blocksize = start_len; - } - - new_buffer->data = ftdm_malloc(start_len); - if (!new_buffer->data) { - ftdm_safe_free(new_buffer); - return FTDM_MEMERR; - } - memset(new_buffer->data, 0, start_len); - - new_buffer->max_len = max_len; - new_buffer->datalen = start_len; - new_buffer->id = buffer_id++; - new_buffer->blocksize = blocksize; - new_buffer->head = new_buffer->data; - - *buffer = new_buffer; - return FTDM_SUCCESS; - } - - return FTDM_MEMERR; -} - -FT_DECLARE(ftdm_size_t) ftdm_buffer_len(ftdm_buffer_t *buffer) -{ - - assert(buffer != NULL); - - return buffer->datalen; - -} - - -FT_DECLARE(ftdm_size_t) ftdm_buffer_freespace(ftdm_buffer_t *buffer) -{ - assert(buffer != NULL); - - - if (buffer->max_len) { - return (ftdm_size_t) (buffer->max_len - buffer->used); - } - return 1000000; - -} - -FT_DECLARE(ftdm_size_t) ftdm_buffer_inuse(ftdm_buffer_t *buffer) -{ - assert(buffer != NULL); - - return buffer->used; -} - -FT_DECLARE(ftdm_size_t) ftdm_buffer_seek(ftdm_buffer_t *buffer, ftdm_size_t datalen) -{ - ftdm_size_t reading = 0; - - assert(buffer != NULL); - - if (buffer->used < 1) { - buffer->used = 0; - return 0; - } else if (buffer->used >= datalen) { - reading = datalen; - } else { - reading = buffer->used; - } - - buffer->used = buffer->actually_used - reading; - buffer->head = buffer->data + reading; - - return reading; -} - -FT_DECLARE(ftdm_size_t) ftdm_buffer_toss(ftdm_buffer_t *buffer, ftdm_size_t datalen) -{ - ftdm_size_t reading = 0; - - assert(buffer != NULL); - - if (buffer->used < 1) { - buffer->used = 0; - return 0; - } else if (buffer->used >= datalen) { - reading = datalen; - } else { - reading = buffer->used; - } - - buffer->used -= reading; - buffer->head += reading; - - return buffer->used; -} - -FT_DECLARE(void) ftdm_buffer_set_loops(ftdm_buffer_t *buffer, int loops) -{ - buffer->loops = loops; -} - -FT_DECLARE(ftdm_size_t) ftdm_buffer_read_loop(ftdm_buffer_t *buffer, void *data, ftdm_size_t datalen) -{ - ftdm_size_t len; - if ((len = ftdm_buffer_read(buffer, data, datalen)) < datalen) { - if (buffer->loops == 0) { - return len; - } - buffer->head = buffer->data; - buffer->used = buffer->actually_used; - len = ftdm_buffer_read(buffer, (char*)data + len, datalen - len); - buffer->loops--; - } - return len; -} - -FT_DECLARE(ftdm_size_t) ftdm_buffer_read(ftdm_buffer_t *buffer, void *data, ftdm_size_t datalen) -{ - ftdm_size_t reading = 0; - - assert(buffer != NULL); - assert(data != NULL); - - - if (buffer->used < 1) { - buffer->used = 0; - return 0; - } else if (buffer->used >= datalen) { - reading = datalen; - } else { - reading = buffer->used; - } - - memcpy(data, buffer->head, reading); - buffer->used -= reading; - buffer->head += reading; - - /* if (buffer->id == 4) printf("%u o %d = %d\n", buffer->id, (unsigned)reading, (unsigned)buffer->used); */ - return reading; -} - -FT_DECLARE(ftdm_size_t) ftdm_buffer_write(ftdm_buffer_t *buffer, const void *data, ftdm_size_t datalen) -{ - ftdm_size_t freespace, actual_freespace; - - assert(buffer != NULL); - assert(data != NULL); - assert(buffer->data != NULL); - - if (!datalen) { - return buffer->used; - } - - actual_freespace = buffer->datalen - buffer->actually_used; - if (actual_freespace < datalen && (!buffer->max_len || (buffer->used + datalen <= buffer->max_len))) { - memmove(buffer->data, buffer->head, buffer->used); - buffer->head = buffer->data; - buffer->actually_used = buffer->used; - } - - freespace = buffer->datalen - buffer->used; - - /* - if (buffer->data != buffer->head) { - memmove(buffer->data, buffer->head, buffer->used); - buffer->head = buffer->data; - } - */ - - if (freespace < datalen) { - ftdm_size_t new_size, new_block_size; - void *data; - - new_size = buffer->datalen + datalen; - new_block_size = buffer->datalen + buffer->blocksize; - - if (new_block_size > new_size) { - new_size = new_block_size; - } - buffer->head = buffer->data; - data = realloc(buffer->data, new_size); - if (!data) { - return 0; - } - buffer->data = data; - buffer->head = buffer->data; - buffer->datalen = new_size; - } - - - freespace = buffer->datalen - buffer->used; - - if (freespace < datalen) { - return 0; - } else { - memcpy(buffer->head + buffer->used, data, datalen); - buffer->used += datalen; - buffer->actually_used += datalen; - } - /* if (buffer->id == 4) printf("%u i %d = %d\n", buffer->id, (unsigned)datalen, (unsigned)buffer->used); */ - - return buffer->used; -} - -FT_DECLARE(void) ftdm_buffer_zero(ftdm_buffer_t *buffer) -{ - assert(buffer != NULL); - assert(buffer->data != NULL); - - buffer->used = 0; - buffer->actually_used = 0; - buffer->head = buffer->data; -} - -FT_DECLARE(ftdm_size_t) ftdm_buffer_zwrite(ftdm_buffer_t *buffer, const void *data, ftdm_size_t datalen) -{ - ftdm_size_t w; - - if (!(w = ftdm_buffer_write(buffer, data, datalen))) { - ftdm_buffer_zero(buffer); - return ftdm_buffer_write(buffer, data, datalen); - } - - return w; -} - -FT_DECLARE(void) ftdm_buffer_destroy(ftdm_buffer_t **buffer) -{ - if (*buffer) { - ftdm_safe_free((*buffer)->data); - ftdm_safe_free(*buffer); - } - - *buffer = NULL; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftdm_call_utils.c b/libs/freetdm/src/ftdm_call_utils.c deleted file mode 100644 index d23c95af4e..0000000000 --- a/libs/freetdm/src/ftdm_call_utils.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * David Yat Sin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Contributors: - * - * Moises Silva - * Ricardo Barroetaveña - * - */ - -#include "private/ftdm_core.h" -#include - - - - -FT_DECLARE(char *) ftdm_url_encode(const char *url, char *buf, ftdm_size_t len) -{ - /* This implementation of url_encode is slightly different compared to the - * Freeswitch one. This is because this implementation accepts the full - * range of values (0x00 - 0xFF) compared to the Freeswitch implementation - * that does not accept 0x00 */ - - const char *p; - size_t x = 0,y = 0; - const char urlunsafe[] = "\r\n \"#%&+:;<=>?@[\\]^`{|}"; - const char hex[] = "0123456789ABCDEF"; - - if (!buf) { - return 0; - } - - if (!url) { - return 0; - } - - len--; - - for (p = url; y <= len; p++) { - if (*p < ' ' || *p > '~' || strchr(urlunsafe, *p)) { - buf[x++] = '%'; - buf[x++] = hex[(*p >> 4) & 0x0f]; - buf[x++] = hex[*p & 0x0f]; - } else { - buf[x++] = *p; - } - y++; - } - buf[x] = '\0'; - return buf; -} - - -FT_DECLARE(char *) ftdm_url_decode(char *s, ftdm_size_t *len) -{ - /* This implementation of url_decode is slightly different compared to the - * Freeswitch one. This is because this implementation accepts the full - * range of values (0x00 - 0xFF) compared to the Freeswitch implementation - * that does not accept 0x00 */ - - char *o; - unsigned int tmp; - ftdm_size_t mylen = 0; - - if (ftdm_strlen_zero(s)) { - return s; - } - - for (o = s; *s; s++, o++) { - if (*s == '%' && strlen(s) > 2 && sscanf(s + 1, "%2x", &tmp) == 1) { - *o = (char) tmp; - s += 2; - } else { - *o = *s; - } - mylen++; - } - *o = '\0'; - *len = mylen; - return s; -} - -FT_DECLARE(ftdm_status_t) ftdm_set_npi(const char *string, uint8_t *target) -{ - uint8_t val; - ftdm_status_t status = FTDM_SUCCESS; - - val = ftdm_str2ftdm_npi(string); - if (val == FTDM_NPI_INVALID) { - ftdm_log(FTDM_LOG_WARNING, "Invalid NPI string (%s)\n", string); - status = FTDM_FAIL; - val = FTDM_NPI_UNKNOWN; - } - *target = val; - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_set_ton(const char *string, uint8_t *target) -{ - uint8_t val; - ftdm_status_t status = FTDM_SUCCESS; - - val = ftdm_str2ftdm_ton(string); - if (val == FTDM_TON_INVALID) { - ftdm_log(FTDM_LOG_WARNING, "Invalid TON string (%s)\n", string); - status = FTDM_FAIL; - val = FTDM_TON_UNKNOWN; - } - *target = val; - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_set_bearer_capability(const char *string, uint8_t *target) -{ - uint8_t val; - ftdm_status_t status = FTDM_SUCCESS; - - val = ftdm_str2ftdm_bearer_cap(string); - if (val == FTDM_NPI_INVALID) { - ftdm_log(FTDM_LOG_WARNING, "Invalid Bearer-Capability string (%s)\n", string); - status = FTDM_FAIL; - val = FTDM_BEARER_CAP_SPEECH; - } - - *target = val; - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_set_bearer_layer1(const char *string, uint8_t *target) -{ - uint8_t val; - ftdm_status_t status = FTDM_SUCCESS; - - val = ftdm_str2ftdm_usr_layer1_prot(string); - if (val == FTDM_USER_LAYER1_PROT_INVALID) { - ftdm_log(FTDM_LOG_WARNING, "Invalid Bearer Layer 1 Protocol string (%s)\n", string); - status = FTDM_FAIL; - val = FTDM_USER_LAYER1_PROT_ULAW; - } - - *target = val; - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_set_screening_ind(const char *string, uint8_t *target) -{ - uint8_t val; - ftdm_status_t status = FTDM_SUCCESS; - - val = ftdm_str2ftdm_screening(string); - if (val == FTDM_SCREENING_INVALID) { - ftdm_log(FTDM_LOG_WARNING, "Invalid screening indicator string (%s)\n", string); - status = FTDM_FAIL; - val = FTDM_SCREENING_NOT_SCREENED; - } - - *target = val; - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_set_presentation_ind(const char *string, uint8_t *target) -{ - uint8_t val; - ftdm_status_t status = FTDM_SUCCESS; - - val = ftdm_str2ftdm_presentation(string); - if (val == FTDM_PRES_INVALID) { - ftdm_log(FTDM_LOG_WARNING, "Invalid presentation string (%s)\n", string); - status = FTDM_FAIL; - val = FTDM_PRES_ALLOWED; - } - - *target = val; - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_is_number(const char *number) -{ - if (!number) { - return FTDM_FAIL; - } - - for ( ; *number; number++) { - if (!isdigit(*number)) { - return FTDM_FAIL; - } - } - return FTDM_SUCCESS; -} - - -FT_DECLARE(ftdm_status_t) ftdm_set_calling_party_category(const char *string, uint8_t *target) -{ - uint8_t val; - ftdm_status_t status = FTDM_SUCCESS; - - val = ftdm_str2ftdm_calling_party_category(string); - if (val == FTDM_CPC_INVALID) { - ftdm_log(FTDM_LOG_WARNING, "Invalid category string (%s)\n", string); - val = FTDM_CPC_ORDINARY; - status = FTDM_FAIL; - } - - *target = val; - return status; -} - diff --git a/libs/freetdm/src/ftdm_callerid.c b/libs/freetdm/src/ftdm_callerid.c deleted file mode 100644 index d3223502f4..0000000000 --- a/libs/freetdm/src/ftdm_callerid.c +++ /dev/null @@ -1,307 +0,0 @@ -#include "private/ftdm_core.h" -#include "fsk.h" -#include "uart.h" - - - -static void fsk_byte_handler (void *x, int data) -{ - ftdm_fsk_data_state_t *state = (ftdm_fsk_data_state_t *) x; - uint8_t byte = (uint8_t)data; - - top: - - if (state->init == 3) { - return; - } - - if (state->dlen) { - goto add_byte; - } - - if (state->bpos == 1) { - state->blen = byte; - - if ((uint32_t)(state->dlen = state->bpos + byte + 2) > state->bufsize) { - state->dlen = state->bufsize; - } - goto top; - } - - add_byte: - - if (state->bpos <= state->dlen) { - state->buf[state->bpos++] = byte; - } else { - state->init = 3; - } -} - -FT_DECLARE(ftdm_status_t) ftdm_fsk_data_init(ftdm_fsk_data_state_t *state, uint8_t *data, uint32_t datalen) -{ - memset(state, 0, sizeof(*state)); - state->buf = data; - state->bufsize = datalen; - state->bpos = 2; - - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_fsk_data_add_sdmf(ftdm_fsk_data_state_t *state, const char *date, char *number) -{ - size_t dlen = strlen(date); - size_t nlen = strlen(number); - - state->buf[0] = FTDM_CID_TYPE_SDMF; - memcpy(&state->buf[state->bpos], date, dlen); - state->bpos += dlen; - memcpy(&state->buf[state->bpos], number, nlen); - state->bpos += nlen; - - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_fsk_data_add_mdmf(ftdm_fsk_data_state_t *state, ftdm_mdmf_type_t type, const uint8_t *data, uint32_t datalen) -{ - state->buf[0] = FTDM_CID_TYPE_MDMF; - state->buf[state->bpos++] = type; - state->buf[state->bpos++] = (uint8_t)datalen; - memcpy(&state->buf[state->bpos], data, datalen); - state->bpos += datalen; - return FTDM_SUCCESS; -} - - -FT_DECLARE(ftdm_status_t) ftdm_fsk_data_add_checksum(ftdm_fsk_data_state_t *state) -{ - uint32_t i; - uint8_t check = 0; - - state->buf[1] = (uint8_t)(state->bpos - 2); - - for (i = 0; i < state->bpos; i++) { - check = check + state->buf[i]; - } - - state->checksum = state->buf[state->bpos] = (uint8_t)(256 - check); - state->bpos++; - - state->dlen = state->bpos; - state->blen = state->buf[1]; - - return FTDM_SUCCESS; -} - - -FT_DECLARE(ftdm_status_t) ftdm_fsk_data_parse(ftdm_fsk_data_state_t *state, ftdm_size_t *type, char **data, ftdm_size_t *len) -{ - - ftdm_size_t i; - int sum = 0; - - top: - - if (state->checksum != 0 || state->ppos >= state->dlen - 1) { - return FTDM_FAIL; - } - - if (!state->ppos) { - for(i = 0; i < state->bpos; i++) { - sum += state->buf[i]; - } - state->checksum = sum % 256; - state->ppos = 2; - - if (state->buf[0] != FTDM_CID_TYPE_MDMF && state->buf[0] != FTDM_CID_TYPE_SDMF) { - state->checksum = -1; - } - goto top; - } - - if (state->buf[0] == FTDM_CID_TYPE_SDMF) { - /* convert sdmf to mdmf so we don't need 2 parsers */ - if (state->ppos == 2) { - *type = MDMF_DATETIME; - *len = 8; - } else { - if (state->buf[state->ppos] == 'P' || state->buf[state->ppos] == 'O') { - *type = MDMF_NO_NUM; - *len = 1; - } else { - *type = MDMF_PHONE_NUM; - *len = state->blen - 8; - } - } - *data = (char *)&state->buf[state->ppos]; - state->ppos += *len; - return FTDM_SUCCESS; - } else if (state->buf[0] == FTDM_CID_TYPE_MDMF) { - *type = state->buf[state->ppos++]; - *len = state->buf[state->ppos++]; - *data = (char *)&state->buf[state->ppos]; - state->ppos += *len; - return FTDM_SUCCESS; - } - - return FTDM_FAIL; -} - -FT_DECLARE(ftdm_status_t) ftdm_fsk_demod_feed(ftdm_fsk_data_state_t *state, int16_t *data, ftdm_size_t samples) -{ - uint32_t x; - int16_t *sp = data; - - if (state->init == 3) { - return FTDM_FAIL; - } - - for (x = 0; x < samples; x++) { - dsp_fsk_sample (state->fsk1200_handle, (double) *sp++ / 32767.0); - if (state->dlen && state->bpos >= state->dlen) { - state->init = 3; - return FTDM_FAIL; - } - } - - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_fsk_demod_destroy(ftdm_fsk_data_state_t *state) -{ - dsp_fsk_destroy(&state->fsk1200_handle); - memset(state, 0, sizeof(*state)); - return FTDM_SUCCESS; -} - -FT_DECLARE(int) ftdm_fsk_demod_init(ftdm_fsk_data_state_t *state, int rate, uint8_t *buf, ftdm_size_t bufsize) -{ - - dsp_fsk_attr_t fsk1200_attr; - - if (state->fsk1200_handle) { - dsp_fsk_destroy(&state->fsk1200_handle); - } - - memset(state, 0, sizeof(*state)); - memset(buf, 0, bufsize); - state->buf = buf; - state->bufsize = bufsize; - - dsp_fsk_attr_init (&fsk1200_attr); - dsp_fsk_attr_set_samplerate (&fsk1200_attr, rate); - dsp_fsk_attr_set_bytehandler (&fsk1200_attr, fsk_byte_handler, state); - state->fsk1200_handle = dsp_fsk_create (&fsk1200_attr); - - if (state->fsk1200_handle == NULL) { - return FTDM_FAIL; - } - - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_size_t) ftdm_fsk_modulator_generate_bit(ftdm_fsk_modulator_t *fsk_trans, int8_t bit, int16_t *buf, ftdm_size_t buflen) -{ - ftdm_size_t i; - - for(i = 0 ; i < buflen; i++) { - fsk_trans->bit_accum += fsk_trans->bit_factor; - if (fsk_trans->bit_accum >= FTDM_FSK_MOD_FACTOR) { - fsk_trans->bit_accum -= (FTDM_FSK_MOD_FACTOR + fsk_trans->bit_factor); - break; - } - - buf[i] = teletone_dds_state_modulate_sample(&fsk_trans->dds, bit); - } - - return i; -} - - -FT_DECLARE(int32_t) ftdm_fsk_modulator_generate_carrier_bits(ftdm_fsk_modulator_t *fsk_trans, uint32_t bits) -{ - uint32_t i = 0; - ftdm_size_t r = 0; - int8_t bit = 1; - - for (i = 0; i < bits; i++) { - if ((r = ftdm_fsk_modulator_generate_bit(fsk_trans, bit, fsk_trans->sample_buffer, sizeof(fsk_trans->sample_buffer) / 2))) { - if (fsk_trans->write_sample_callback(fsk_trans->sample_buffer, r, fsk_trans->user_data) != FTDM_SUCCESS) { - break; - } - } else { - break; - } - } - - return i; -} - - -FT_DECLARE(void) ftdm_fsk_modulator_generate_chan_sieze(ftdm_fsk_modulator_t *fsk_trans) -{ - uint32_t i = 0; - ftdm_size_t r = 0; - int8_t bit = 0; - - for (i = 0; i < fsk_trans->chan_sieze_bits; i++) { - if ((r = ftdm_fsk_modulator_generate_bit(fsk_trans, bit, fsk_trans->sample_buffer, sizeof(fsk_trans->sample_buffer) / 2))) { - if (fsk_trans->write_sample_callback(fsk_trans->sample_buffer, r, fsk_trans->user_data) != FTDM_SUCCESS) { - break; - } - } else { - break; - } - bit = !bit; - } - - -} - - -FT_DECLARE(void) ftdm_fsk_modulator_send_data(ftdm_fsk_modulator_t *fsk_trans) -{ - ftdm_size_t r = 0; - int8_t bit = 0; - - while((bit = ftdm_bitstream_get_bit(&fsk_trans->bs)) > -1) { - if ((r = ftdm_fsk_modulator_generate_bit(fsk_trans, bit, fsk_trans->sample_buffer, sizeof(fsk_trans->sample_buffer) / 2))) { - if (fsk_trans->write_sample_callback(fsk_trans->sample_buffer, r, fsk_trans->user_data) != FTDM_SUCCESS) { - break; - } - } else { - break; - } - } -} - - -FT_DECLARE(ftdm_status_t) ftdm_fsk_modulator_init(ftdm_fsk_modulator_t *fsk_trans, - fsk_modem_types_t modem_type, - uint32_t sample_rate, - ftdm_fsk_data_state_t *fsk_data, - float db_level, - uint32_t carrier_bits_start, - uint32_t carrier_bits_stop, - uint32_t chan_sieze_bits, - ftdm_fsk_write_sample_t write_sample_callback, - void *user_data) -{ - memset(fsk_trans, 0, sizeof(*fsk_trans)); - fsk_trans->modem_type = modem_type; - teletone_dds_state_set_tone(&fsk_trans->dds, fsk_modem_definitions[fsk_trans->modem_type].freq_space, sample_rate, 0); - teletone_dds_state_set_tone(&fsk_trans->dds, fsk_modem_definitions[fsk_trans->modem_type].freq_mark, sample_rate, 1); - fsk_trans->bit_factor = (uint32_t)((fsk_modem_definitions[fsk_trans->modem_type].baud_rate * FTDM_FSK_MOD_FACTOR) / (float)sample_rate); - fsk_trans->samples_per_bit = (uint32_t) (sample_rate / fsk_modem_definitions[fsk_trans->modem_type].baud_rate); - fsk_trans->est_bytes = (int32_t)(((fsk_data->dlen * 10) + carrier_bits_start + carrier_bits_stop + chan_sieze_bits) * ((fsk_trans->samples_per_bit + 1) * 2)); - fsk_trans->bit_accum = 0; - fsk_trans->fsk_data = fsk_data; - teletone_dds_state_set_tx_level(&fsk_trans->dds, db_level); - ftdm_bitstream_init(&fsk_trans->bs, fsk_trans->fsk_data->buf, (uint32_t)fsk_trans->fsk_data->dlen, FTDM_ENDIAN_BIG, 1); - fsk_trans->carrier_bits_start = carrier_bits_start; - fsk_trans->carrier_bits_stop = carrier_bits_stop; - fsk_trans->chan_sieze_bits = chan_sieze_bits; - fsk_trans->write_sample_callback = write_sample_callback; - fsk_trans->user_data = user_data; - return FTDM_SUCCESS; -} - diff --git a/libs/freetdm/src/ftdm_config.c b/libs/freetdm/src/ftdm_config.c deleted file mode 100644 index 9352284edf..0000000000 --- a/libs/freetdm/src/ftdm_config.c +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Contributors: - * - * Moises Silva - */ - -#include "private/ftdm_core.h" - -#ifndef FTDM_MOD_DIR -#define FTDM_MOD_DIR "." -#endif - -#define FTDM_MAX_CONF_DIR 512 - -static char g_ftdm_config_dir[FTDM_MAX_CONF_DIR] = FTDM_CONFIG_DIR; -static char g_ftdm_mod_dir[FTDM_MAX_CONF_DIR] = FTDM_MOD_DIR; - -FT_DECLARE(void) ftdm_global_set_mod_directory(const char *path) -{ - snprintf(g_ftdm_mod_dir, sizeof(g_ftdm_mod_dir), "%s", path); - ftdm_log(FTDM_LOG_DEBUG, "New mod directory: %s\n", g_ftdm_mod_dir); -} - -FT_DECLARE(void) ftdm_global_set_config_directory(const char *path) -{ - snprintf(g_ftdm_config_dir, sizeof(g_ftdm_config_dir), "%s", path); - ftdm_log(FTDM_LOG_DEBUG, "New config directory: %s\n", g_ftdm_config_dir); -} - -int ftdm_config_open_file(ftdm_config_t *cfg, const char *file_path) -{ - FILE *f; - const char *path = NULL; - char path_buf[1024]; - - if (file_path[0] == '/') { - path = file_path; - } else { - snprintf(path_buf, sizeof(path_buf), "%s%s%s", g_ftdm_config_dir, FTDM_PATH_SEPARATOR, file_path); - path = path_buf; - } - - if (!path) { - return 0; - } - - memset(cfg, 0, sizeof(*cfg)); - cfg->lockto = -1; - ftdm_log(FTDM_LOG_DEBUG, "Configuration file is %s\n", path); - f = fopen(path, "r"); - - if (!f) { - if (file_path[0] != '/') { - int last = -1; - char *var, *val; - - snprintf(path_buf, sizeof(path_buf), "%s%sfreetdm.conf", g_ftdm_config_dir, FTDM_PATH_SEPARATOR); - path = path_buf; - - if ((f = fopen(path, "r")) == 0) { - return 0; - } - - cfg->file = f; - ftdm_set_string(cfg->path, path); - - while (ftdm_config_next_pair(cfg, &var, &val)) { - if ((cfg->sectno != last) && !strcmp(cfg->section, file_path)) { - cfg->lockto = cfg->sectno; - return 1; - } - } - - ftdm_config_close_file(cfg); - memset(cfg, 0, sizeof(*cfg)); - return 0; - } - - return 0; - } else { - cfg->file = f; - ftdm_set_string(cfg->path, path); - return 1; - } -} - -void ftdm_config_close_file(ftdm_config_t *cfg) -{ - - if (cfg->file) { - fclose(cfg->file); - } - - memset(cfg, 0, sizeof(*cfg)); -} - - - -int ftdm_config_next_pair(ftdm_config_t *cfg, char **var, char **val) -{ - int ret = 0; - char *p, *end; - - *var = *val = NULL; - - if (!cfg->path) { - return 0; - } - - for (;;) { - cfg->lineno++; - - if (!fgets(cfg->buf, sizeof(cfg->buf), cfg->file)) { - ret = 0; - break; - } - *var = cfg->buf; - - if (**var == '[' && (end = strchr(*var, ']')) != 0) { - *end = '\0'; - (*var)++; - if (**var == '+') { - (*var)++; - ftdm_copy_string(cfg->section, *var, sizeof(cfg->section)); - cfg->sectno++; - - if (cfg->lockto > -1 && cfg->sectno != cfg->lockto) { - break; - } - cfg->catno = 0; - cfg->lineno = 0; - *var = (char *) ""; - *val = (char *) ""; - return 1; - } else { - ftdm_copy_string(cfg->category, *var, sizeof(cfg->category)); - cfg->catno++; - } - continue; - } - - - - if (**var == '#' || **var == ';' || **var == '\n' || **var == '\r') { - continue; - } - - if (!strncmp(*var, "__END__", 7)) { - break; - } - - - if ((end = strchr(*var, ';')) && *(end+1) == *end) { - *end = '\0'; - end--; - } else if ((end = strchr(*var, '\n')) != 0) { - if (*(end - 1) == '\r') { - end--; - } - *end = '\0'; - } - - p = *var; - while ((*p == ' ' || *p == '\t') && p != end) { - *p = '\0'; - p++; - } - *var = p; - - - if ((*val = strchr(*var, '=')) == 0) { - ret = -1; - /* log_printf(0, server.log, "Invalid syntax on %s: line %d\n", cfg->path, cfg->lineno); */ - continue; - } else { - p = *val - 1; - *(*val) = '\0'; - (*val)++; - if (*(*val) == '>') { - *(*val) = '\0'; - (*val)++; - } - - while ((*p == ' ' || *p == '\t') && p != *var) { - *p = '\0'; - p--; - } - - p = *val; - while ((*p == ' ' || *p == '\t') && p != end) { - *p = '\0'; - p++; - } - *val = p; - ret = 1; - break; - } - } - - - return ret; - -} - -FT_DECLARE (int) ftdm_config_get_cas_bits(char *strvalue, unsigned char *outbits) -{ - char cas_bits[5]; - unsigned char bit = 0x8; - int x = 0; - char *double_colon = strchr(strvalue, ':'); - if (!double_colon) { - ftdm_log(FTDM_LOG_ERROR, "No CAS bits specified: %s, :xxxx definition expected, where x is 1 or 0\n", strvalue); - return -1; - } - double_colon++; - *outbits = 0; - cas_bits[4] = 0; - if (sscanf(double_colon, "%c%c%c%c", &cas_bits[0], &cas_bits[1], &cas_bits[2], &cas_bits[3]) != 4) { - ftdm_log(FTDM_LOG_ERROR, "Invalid CAS bits specified: '%s', :xxxx definition expected, where x is 1 or 0\n", double_colon); - return -1; - } - ftdm_log(FTDM_LOG_DEBUG, "CAS bits specification found: %s\n", cas_bits); - for (; cas_bits[x]; x++) { - if ('1' == cas_bits[x]) { - *outbits |= bit; - } else if ('0' != cas_bits[x]) { - ftdm_log(FTDM_LOG_ERROR, "Invalid CAS pattern specified: %s, just 0 or 1 allowed for each bit\n", - strvalue); - return -1; - } - bit >>= 1; - } - return 0; -} - -#define PARAMETERS_CHUNK_SIZE 20 -FT_DECLARE(ftdm_status_t) ftdm_conf_node_create(const char *name, ftdm_conf_node_t **node, ftdm_conf_node_t *parent) -{ - ftdm_conf_node_t *newnode; - ftdm_conf_node_t *sibling = NULL; - - ftdm_assert_return(name != NULL, FTDM_FAIL, "null node name"); - - newnode = ftdm_calloc(1, sizeof(**node)); - if (!newnode) { - return FTDM_MEMERR; - } - - strncpy(newnode->name, name, sizeof(newnode->name)-1); - newnode->name[sizeof(newnode->name)-1] = 0; - - newnode->parameters = ftdm_calloc(PARAMETERS_CHUNK_SIZE, sizeof(*newnode->parameters)); - if (!newnode->parameters) { - ftdm_safe_free(newnode); - return FTDM_MEMERR; - } - newnode->t_parameters = PARAMETERS_CHUNK_SIZE; - - if (parent) { - /* store who my parent is */ - newnode->parent = parent; - - /* arrange them in FIFO order (newnode should be last) */ - if (!parent->child) { - /* we're the first node being added */ - parent->child = newnode; - } else { - if (!parent->last) { - /* we're the second node being added */ - parent->last = newnode; - parent->child->next = newnode; - newnode->prev = parent->child; - } else { - /* we're the third or Nth node to be added */ - sibling = parent->last; - sibling->next = newnode; - parent->last = newnode; - newnode->prev = sibling; - } - } - } - - *node = newnode; - - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_conf_node_add_param(ftdm_conf_node_t *node, const char *param, const char *val) -{ - void *newparameters; - - ftdm_assert_return(param != NULL, FTDM_FAIL, "param is null"); - ftdm_assert_return(val != NULL, FTDM_FAIL, "val is null"); - - if (node->n_parameters == node->t_parameters) { - newparameters = ftdm_realloc(node->parameters, (node->t_parameters + PARAMETERS_CHUNK_SIZE) * sizeof(*node->parameters)); - if (!newparameters) { - return FTDM_MEMERR; - } - node->parameters = newparameters; - node->t_parameters = node->n_parameters + PARAMETERS_CHUNK_SIZE; - } - node->parameters[node->n_parameters].var = param; - node->parameters[node->n_parameters].val = val; - node->n_parameters++; - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_conf_node_destroy(ftdm_conf_node_t *node) -{ - ftdm_conf_node_t *curr = NULL; - ftdm_conf_node_t *child = node->child; - while (child) { - curr = child; - child = curr->next; - ftdm_conf_node_destroy(curr); - } - ftdm_free(node->parameters); - ftdm_free(node); - return FTDM_SUCCESS; -} - -FT_DECLARE(char *) ftdm_build_dso_path(const char *name, char *path, ftdm_size_t len) -{ -#ifdef WIN32 - const char *ext = ".dll"; - //const char *EXT = ".DLL"; -#elif defined (MACOSX) || defined (DARWIN) - const char *ext = ".dylib"; - //const char *EXT = ".DYLIB"; -#else - const char *ext = ".so"; - //const char *EXT = ".SO"; -#endif - if (*name == *FTDM_PATH_SEPARATOR) { - snprintf(path, len, "%s%s", name, ext); - } else { - snprintf(path, len, "%s%s%s%s", g_ftdm_mod_dir, FTDM_PATH_SEPARATOR, name, ext); - } - return path; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftdm_cpu_monitor.c b/libs/freetdm/src/ftdm_cpu_monitor.c deleted file mode 100644 index 1aa9b16c41..0000000000 --- a/libs/freetdm/src/ftdm_cpu_monitor.c +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * Moises Silva - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Contributors: - * David Yat Sin - * - */ - -#ifdef WIN32 -# if (_WIN32_WINNT < 0x0501) -# error "Need to target at least Windows XP/Server 2003 because GetSystemTimes is needed" -# endif -# include -#else /* LINUX */ - -#include -#include -#include -#include -#include -#include -#include -#endif - -#include "private/ftdm_core.h" -#include "ftdm_cpu_monitor.h" -struct ftdm_cpu_monitor_stats -{ - /* bool, just used to retrieve the values for the first time and not calculate the percentage of idle time */ - int valid_last_times; - - /* last calculated percentage of idle time */ - double last_percentage_of_idle_time; - -#ifdef __linux__ - /* the cpu feature gets disabled on errors */ - int disabled; - - /* all of these are the Linux jiffies last retrieved count */ - unsigned long long last_user_time; - unsigned long long last_system_time; - unsigned long long last_idle_time; - - unsigned long long last_nice_time; - unsigned long long last_irq_time; - unsigned long long last_soft_irq_time; - unsigned long long last_io_wait_time; - unsigned long long last_steal_time; - - /* /proc/stat file descriptor used to retrieve the counters */ - int procfd; - int initd; -#elif defined (WIN32) || defined (WIN64) - __int64 i64LastUserTime; - __int64 i64LastKernelTime; - __int64 i64LastIdleTime; -#else -/* Unsupported */ -#endif -}; - -#ifdef __linux__ -static ftdm_status_t ftdm_cpu_read_stats(struct ftdm_cpu_monitor_stats *p, - unsigned long long *user, - unsigned long long *nice, - unsigned long long *system, - unsigned long long *idle, - unsigned long long *iowait, - unsigned long long *irq, - unsigned long long *softirq, - unsigned long long *steal) -{ -// the output of proc should not change that often from one kernel to other -// see fs/proc/proc_misc.c or fs/proc/stat.c in the Linux kernel for more details -// also man 5 proc is useful. -#define CPU_ELEMENTS_1 7 // change this if you change the format string -#define CPU_INFO_FORMAT_1 "cpu %llu %llu %llu %llu %llu %llu %llu" - -#define CPU_ELEMENTS_2 8 // change this if you change the format string -#define CPU_INFO_FORMAT_2 "cpu %llu %llu %llu %llu %llu %llu %llu %llu" - -#define CPU_ELEMENTS_3 9 // change this if you change the format string -#define CPU_INFO_FORMAT_3 "cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu" - - static const char procfile[] = "/proc/stat"; - int rc = 0; - int myerrno = 0; - int elements = 0; - const char *cpustr = NULL; - char statbuff[1024]; - unsigned long long guest = 0; - - if (!p->initd) { - p->procfd = open(procfile, O_RDONLY, 0); - if(p->procfd == -1) { - ftdm_log(FTDM_LOG_ERROR, "Failed to open CPU statistics file %s: %s\n", procfile, strerror(myerrno)); - return FTDM_FAIL; - } - p->initd = 1; - } else { - lseek(p->procfd, 0L, SEEK_SET); - } - - rc = read(p->procfd, statbuff, sizeof(statbuff) - 1); - if (rc <= 0) { - myerrno = errno; - ftdm_log(FTDM_LOG_ERROR, "Failed to read CPU statistics file %s: %s\n", procfile, strerror(myerrno)); - return FTDM_FAIL; - } - - cpustr = strstr(statbuff, "cpu "); - if (!cpustr) { - ftdm_log(FTDM_LOG_ERROR, "wrong format for Linux proc cpu statistics: missing cpu string\n"); - return FTDM_FAIL; - } - - /* test each of the known formats starting from the bigger one */ - elements = sscanf(cpustr, CPU_INFO_FORMAT_3, user, nice, system, idle, iowait, irq, softirq, steal, &guest); - if (elements == CPU_ELEMENTS_3) { - user += guest; /* guest operating system's run in user space */ - return FTDM_SUCCESS; - } - - elements = sscanf(cpustr, CPU_INFO_FORMAT_2, user, nice, system, idle, iowait, irq, softirq, steal); - if (elements == CPU_ELEMENTS_2) { - return FTDM_SUCCESS; - } - - elements = sscanf(cpustr, CPU_INFO_FORMAT_1, user, nice, system, idle, iowait, irq, softirq); - if (elements == CPU_ELEMENTS_1) { - *steal = 0; - return FTDM_SUCCESS; - } - - ftdm_log(FTDM_LOG_ERROR, "Unexpected format for Linux proc cpu statistics:%s\n", cpustr); - return FTDM_FAIL; -} -#endif - -#ifdef __linux__ -FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time (struct ftdm_cpu_monitor_stats *p, double *idle_percentage) -{ - unsigned long long user, nice, system, idle, iowait, irq, softirq, steal; - unsigned long long usertime, kerneltime, idletime, totaltime, halftime; - - *idle_percentage = 100.0; - if (p->disabled) { - return FTDM_FAIL; - } - if (ftdm_cpu_read_stats(p, &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal)) { - ftdm_log(FTDM_LOG_ERROR, "Failed to retrieve Linux CPU statistics - disabling cpu monitor\n"); - p->disabled = 1; - return FTDM_FAIL; - } - - if (!p->valid_last_times) { - // we dont strictly need to save all of them but I feel code is more clear if we do - p->valid_last_times = 1; - p->last_user_time = user; - p->last_nice_time = nice; - p->last_system_time = system; - p->last_irq_time = irq; - p->last_soft_irq_time = softirq; - p->last_io_wait_time = iowait; - p->last_steal_time = steal; - p->last_idle_time = idle; - p->last_percentage_of_idle_time = 100.0; - *idle_percentage = p->last_percentage_of_idle_time; - return FTDM_SUCCESS; - } - - usertime = (user - p->last_user_time) + (nice - p->last_nice_time); - kerneltime = (system - p->last_system_time) + (irq - p->last_irq_time) + (softirq - p->last_soft_irq_time); - kerneltime += (iowait - p->last_io_wait_time); - kerneltime += (steal - p->last_steal_time); - idletime = (idle - p->last_idle_time); - - totaltime = usertime + kerneltime + idletime; - - if (totaltime <= 0) { - // this may happen if not enough time has elapsed and the jiffies counters are the same than the last time we checked - // jiffies depend on timer interrupts which depend on the number of HZ compile time setting of the kernel - // typical configs set HZ to 100 (that means, 100 jiffies updates per second, that is one each 10ms) - // avoid an arithmetic exception and return the same values - *idle_percentage = p->last_percentage_of_idle_time; - return FTDM_SUCCESS; - } - - halftime = totaltime / 2UL; - - p->last_percentage_of_idle_time = ((100 * idletime + halftime) / totaltime); - *idle_percentage = p->last_percentage_of_idle_time; - - p->last_user_time = user; - p->last_nice_time = nice; - p->last_system_time = system; - p->last_irq_time = irq; - p->last_soft_irq_time = softirq; - p->last_io_wait_time = iowait; - p->last_steal_time = steal; - p->last_idle_time = idle; - - return FTDM_SUCCESS; -} - -#elif defined (__WINDOWS__) -FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time(struct ftdm_cpu_monitor_stats *p, double *idle_percentage) -{ - FILETIME idleTime; - FILETIME kernelTime; - FILETIME userTime; - int64_t i64UserTime; - int64_t i64KernelTime; - int64_t i64IdleTime; - - if (!GetSystemTimes(&idleTime, &kernelTime, &userTime)) { - return FTDM_FAIL; - } - - i64UserTime = (int64_t)userTime.dwLowDateTime | ((int64_t)userTime.dwHighDateTime << 32); - - i64KernelTime = (int64_t)kernelTime.dwLowDateTime | ((int64_t)kernelTime.dwHighDateTime << 32); - - i64IdleTime = (int64_t)idleTime.dwLowDateTime | ((int64_t)idleTime.dwHighDateTime << 32); - - if (p->valid_last_times) { - int64_t i64User = i64UserTime - p->i64LastUserTime; - int64_t i64Kernel = i64KernelTime - p->i64LastKernelTime; - int64_t i64Idle = i64IdleTime - p->i64LastIdleTime; - int64_t i64System = i64User + i64Kernel; - *idle_percentage = 100.0 * i64Idle / i64System; - } else { - *idle_percentage = 100.0; - p->valid_last_times = 1; - } - - /* Remember current value for the next call */ - p->i64LastUserTime = i64UserTime; - p->i64LastKernelTime = i64KernelTime; - p->i64LastIdleTime = i64IdleTime; - - /* Success */ - return FTDM_SUCCESS; -} -#else -/* Unsupported */ -FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time(struct ftdm_cpu_monitor_stats *p, double *idle_percentage) -{ - *idle_percentage = 100.0; - return FTDM_FAIL; -} -#endif - -FT_DECLARE(struct ftdm_cpu_monitor_stats*) ftdm_new_cpu_monitor(void) -{ - return calloc(1, sizeof(struct ftdm_cpu_monitor_stats)); -} - -FT_DECLARE(void) ftdm_delete_cpu_monitor(struct ftdm_cpu_monitor_stats *p) -{ -#ifdef __linux__ - close(p->procfd); -#endif - free(p); -} - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftdm_dso.c b/libs/freetdm/src/ftdm_dso.c deleted file mode 100755 index a646ed3469..0000000000 --- a/libs/freetdm/src/ftdm_dso.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Cross Platform dso/dll load abstraction - * Copyright(C) 2008 Michael Jerris - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so. - * - * This work is provided under this license on an "as is" basis, without warranty of any kind, - * either expressed or implied, including, without limitation, warranties that the covered code - * is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire - * risk as to the quality and performance of the covered code is with you. Should any covered - * code prove defective in any respect, you (not the initial developer or any other contributor) - * assume the cost of any necessary servicing, repair or correction. This disclaimer of warranty - * constitutes an essential part of this license. No use of any covered code is authorized hereunder - * except under this disclaimer. - * - */ - -#include "private/ftdm_core.h" -#include "ftdm_dso.h" -#include -#include - -#ifdef WIN32 -#include -#include - - -FT_DECLARE(ftdm_status_t) ftdm_dso_destroy(ftdm_dso_lib_t *lib) { - if (lib && *lib) { - FreeLibrary(*lib); - *lib = NULL; - } - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_dso_lib_t) ftdm_dso_open(const char *path, char **err) { - HINSTANCE lib; - - lib = LoadLibraryEx(path, NULL, 0); - - if (!lib) { - LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); - } - - if (!lib) { - DWORD error = GetLastError(); - char tmp[80]; - sprintf(tmp, "dll open error [%ul]\n", error); - *err = ftdm_strdup(tmp); - } - - return lib; -} - -FT_DECLARE(void*) ftdm_dso_func_sym(ftdm_dso_lib_t lib, const char *sym, char **err) { - FARPROC func = GetProcAddress(lib, sym); - if (!func) { - DWORD error = GetLastError(); - char tmp[80]; - sprintf(tmp, "dll sym error [%ul]\n", error); - *err = ftdm_strdup(tmp); - } - return (void *)(intptr_t)func; // this should really be addr - ftdm_dso_func_data -} - -#else - -/* -** {======================================================================== -** This is an implementation of loadlib based on the dlfcn interface. -** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, -** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least -** as an emulation layer on top of native functions. -** ========================================================================= -*/ - - -#include - -FT_DECLARE(ftdm_status_t) ftdm_dso_destroy(ftdm_dso_lib_t *lib) { - int rc; - if (lib && *lib) { - rc = dlclose(*lib); - if (rc) { - ftdm_log(FTDM_LOG_ERROR, "Failed to close lib %p: %s\n", *lib, dlerror()); - return FTDM_FAIL; - } - ftdm_log(FTDM_LOG_DEBUG, "lib %p was closed with success\n", *lib); - *lib = NULL; - return FTDM_SUCCESS; - } - ftdm_log(FTDM_LOG_ERROR, "Invalid pointer provided to ftdm_dso_destroy\n"); - return FTDM_FAIL; -} - -FT_DECLARE(ftdm_dso_lib_t) ftdm_dso_open(const char *path, char **err) { - void *lib = dlopen(path, RTLD_NOW | RTLD_LOCAL); - if (lib == NULL) { - *err = ftdm_strdup(dlerror()); - } - return lib; -} - -FT_DECLARE(void *) ftdm_dso_func_sym(ftdm_dso_lib_t lib, const char *sym, char **err) { - void *func = dlsym(lib, sym); - if (!func) { - *err = ftdm_strdup(dlerror()); - } - return func; -} -#endif - -/* }====================================================== */ - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c deleted file mode 100644 index 9adcd27509..0000000000 --- a/libs/freetdm/src/ftdm_io.c +++ /dev/null @@ -1,7027 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Contributors: - * - * Moises Silva - * David Yat Sin - * - */ -#define _GNU_SOURCE -#include "private/ftdm_core.h" -#include -#include -#ifdef WIN32 -#include -#endif -#ifdef FTDM_PIKA_SUPPORT -#include "ftdm_pika.h" -#endif -#include "ftdm_cpu_monitor.h" - -#ifndef localtime_r -struct tm *localtime_r(const time_t *clock, struct tm *result); -#endif - -#define FORCE_HANGUP_TIMER 30000 -#define FTDM_READ_TRACE_INDEX 0 -#define FTDM_WRITE_TRACE_INDEX 1 -#define MAX_CALLIDS 6000 -#define FTDM_HALF_DTMF_PAUSE 500 -#define FTDM_FULL_DTMF_PAUSE 1000 - -#define FTDM_CHANNEL_SW_DTMF_ALLOWED(ftdmchan) (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT) && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_DTMF_DETECTION)) - -ftdm_time_t time_last_throttle_log = 0; -ftdm_time_t time_current_throttle_log = 0; - -typedef struct val_str { - const char *str; - unsigned long long val; -} val_str_t; - -static val_str_t channel_flag_strs[] = { - { "configured" , FTDM_CHANNEL_CONFIGURED}, - { "ready", FTDM_CHANNEL_READY}, - { "open", FTDM_CHANNEL_OPEN}, - { "dtmf-detect", FTDM_CHANNEL_DTMF_DETECT}, - { "suppress-dtmf", FTDM_CHANNEL_SUPRESS_DTMF}, - { "transcode", FTDM_CHANNEL_TRANSCODE}, - { "buffer", FTDM_CHANNEL_BUFFER}, - { "in-thread", FTDM_CHANNEL_INTHREAD}, - { "wink", FTDM_CHANNEL_WINK}, - { "flash", FTDM_CHANNEL_FLASH}, - { "state-change", FTDM_CHANNEL_STATE_CHANGE}, - { "hold", FTDM_CHANNEL_HOLD}, - { "in-use", FTDM_CHANNEL_INUSE}, - { "off-hook", FTDM_CHANNEL_OFFHOOK}, - { "ringing", FTDM_CHANNEL_RINGING}, - { "progress-detect", FTDM_CHANNEL_PROGRESS_DETECT}, - { "callerid-detect", FTDM_CHANNEL_CALLERID_DETECT}, - { "outbound", FTDM_CHANNEL_OUTBOUND}, - { "suspended", FTDM_CHANNEL_SUSPENDED}, - { "3-way", FTDM_CHANNEL_3WAY}, - { "progress", FTDM_CHANNEL_PROGRESS}, - { "media", FTDM_CHANNEL_MEDIA}, - { "answered", FTDM_CHANNEL_ANSWERED}, - { "mute", FTDM_CHANNEL_MUTE}, - { "use-rx-gain", FTDM_CHANNEL_USE_RX_GAIN}, - { "use-tx-gain", FTDM_CHANNEL_USE_TX_GAIN}, - { "in-alarm", FTDM_CHANNEL_IN_ALARM}, - { "sig-up", FTDM_CHANNEL_SIG_UP}, - { "user-hangup", FTDM_CHANNEL_USER_HANGUP}, - { "rx-disabled", FTDM_CHANNEL_RX_DISABLED}, - { "tx-disabled", FTDM_CHANNEL_TX_DISABLED}, - { "call-started", FTDM_CHANNEL_CALL_STARTED}, - { "non-block", FTDM_CHANNEL_NONBLOCK}, - { "ind-ack-pending", FTDM_CHANNEL_IND_ACK_PENDING}, - { "blocking", FTDM_CHANNEL_BLOCKING}, - { "media", FTDM_CHANNEL_DIGITAL_MEDIA}, - { "native-sigbridge", FTDM_CHANNEL_NATIVE_SIGBRIDGE}, - { "sig-dtmf-detection", FTDM_CHANNEL_SIG_DTMF_DETECTION}, - { "invalid", FTDM_CHANNEL_MAX_FLAG}, -}; - -static val_str_t span_flag_strs[] = { - { "configured", FTDM_SPAN_CONFIGURED}, - { "started", FTDM_SPAN_STARTED}, - { "state-change", FTDM_SPAN_STATE_CHANGE}, - { "suspended", FTDM_SPAN_SUSPENDED}, - { "in-thread", FTDM_SPAN_IN_THREAD}, - { "stop-thread", FTDM_SPAN_STOP_THREAD}, - { "use-chan-queue", FTDM_SPAN_USE_CHAN_QUEUE}, - { "suggest-chan-id", FTDM_SPAN_SUGGEST_CHAN_ID}, - { "use-av-rate", FTDM_SPAN_USE_AV_RATE}, - { "power-saving", FTDM_SPAN_PWR_SAVING}, - { "signals-queue", FTDM_SPAN_USE_SIGNALS_QUEUE}, - { "proceed-state", FTDM_SPAN_USE_PROCEED_STATE}, - { "skip-state", FTDM_SPAN_USE_SKIP_STATES}, - { "non-stoppable", FTDM_SPAN_NON_STOPPABLE}, - { "use-transfer", FTDM_SPAN_USE_TRANSFER}, -}; - -static ftdm_status_t ftdm_call_set_call_id(ftdm_channel_t *fchan, ftdm_caller_data_t *caller_data); -static ftdm_status_t ftdm_call_clear_call_id(ftdm_caller_data_t *caller_data); -static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan); -static ftdm_status_t ftdm_channel_sig_indicate(ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication, ftdm_usrmsg_t *usrmsg); - -static const char *ftdm_val2str(unsigned long long val, val_str_t *val_str_table, ftdm_size_t array_size, const char *default_str); -static unsigned long long ftdm_str2val(const char *str, val_str_t *val_str_table, ftdm_size_t array_size, unsigned long long default_val); - - -static int time_is_init = 0; - -static void time_init(void) -{ -#ifdef WIN32 - timeBeginPeriod(1); -#endif - time_is_init = 1; -} - -static void time_end(void) -{ -#ifdef WIN32 - timeEndPeriod(1); -#endif - time_is_init = 0; -} - -FT_DECLARE(ftdm_time_t) ftdm_current_time_in_ms(void) -{ -#ifdef WIN32 - return timeGetTime(); -#else - struct timeval tv; - gettimeofday(&tv, NULL); - return ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)); -#endif -} - -static void write_chan_io_dump(ftdm_io_dump_t *dump, char *dataptr, int dlen) -{ - int windex = dump->windex; - int avail = (int)dump->size - windex; - - if (!dump->buffer) { - return; - } - - if (dlen > avail) { - int diff = dlen - avail; - - ftdm_assert(diff < (int)dump->size, "Very small buffer or very big IO chunk!\n"); - - /* write only what we can and the rest at the beginning of the buffer */ - memcpy(&dump->buffer[windex], dataptr, avail); - memcpy(&dump->buffer[0], &dataptr[avail], diff); - windex = diff; - - /*ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "wrapping around dump buffer %p up to index %d\n\n", dump, windex);*/ - dump->wrapped = 1; - } else { - memcpy(&dump->buffer[windex], dataptr, dlen); - windex += dlen; - } - - if (windex == (int)dump->size) { - /*ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "wrapping around dump buffer %p\n", dump);*/ - windex = 0; - dump->wrapped = 1; - } - - dump->windex = windex; -} - -static void dump_chan_io_to_file(ftdm_channel_t *fchan, ftdm_io_dump_t *dump, FILE *file) -{ - /* write the saved audio buffer */ - ftdm_size_t rc = 0; - ftdm_size_t towrite = 0; - - if (!dump->buffer) { - return; - } - - towrite = dump->size - dump->windex; - - if (dump->wrapped) { - rc = fwrite(&dump->buffer[dump->windex], 1, towrite, file); - if (rc != towrite) { - ftdm_log_chan(fchan, FTDM_LOG_ERROR, "only wrote %"FTDM_SIZE_FMT" out of %"FTDM_SIZE_FMT" bytes in io dump buffer: %s\n", - rc, towrite, strerror(errno)); - } - } - if (dump->windex) { - towrite = dump->windex; - rc = fwrite(&dump->buffer[0], 1, towrite, file); - if (rc != towrite) { - ftdm_log_chan(fchan, FTDM_LOG_ERROR, "only wrote %"FTDM_SIZE_FMT" out of %"FTDM_SIZE_FMT" bytes in io dump buffer: %s\n", - rc, towrite, strerror(errno)); - } - } - dump->windex = 0; - dump->wrapped = 0; -} - -static void stop_chan_io_dump(ftdm_io_dump_t *dump) -{ - if (!dump->buffer) { - return; - } - ftdm_safe_free(dump->buffer); - memset(dump, 0, sizeof(*dump)); -} - -static ftdm_status_t start_chan_io_dump(ftdm_channel_t *chan, ftdm_io_dump_t *dump, ftdm_size_t size) -{ - if (dump->buffer) { - ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "IO dump is already started\n"); - return FTDM_FAIL; - } - memset(dump, 0, sizeof(*dump)); - dump->buffer = ftdm_malloc(size); - if (!dump->buffer) { - return FTDM_FAIL; - } - dump->size = size; - return FTDM_SUCCESS; -} - - -static void close_dtmf_debug_file(ftdm_channel_t *ftdmchan) -{ - if (ftdmchan->dtmfdbg.file) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "closing debug dtmf file\n"); - fclose(ftdmchan->dtmfdbg.file); - ftdmchan->dtmfdbg.file = NULL; - } -} - -static ftdm_status_t disable_dtmf_debug(ftdm_channel_t *ftdmchan) -{ - if (!ftdmchan->dtmfdbg.enabled) { - return FTDM_SUCCESS; - } - - if (!ftdmchan->rxdump.buffer) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "DTMF debug enabled but no rx dump?\n"); - return FTDM_FAIL; - } - - close_dtmf_debug_file(ftdmchan); - stop_chan_io_dump(&ftdmchan->rxdump); - ftdmchan->dtmfdbg.enabled = 0; - return FTDM_SUCCESS; -} - -typedef struct { - uint8_t enabled; - uint8_t running; - uint8_t alarm; - uint32_t interval; - uint8_t alarm_action_flags; - uint8_t set_alarm_threshold; - uint8_t clear_alarm_threshold; - ftdm_interrupt_t *interrupt; -} cpu_monitor_t; - -static struct { - ftdm_hash_t *interface_hash; - ftdm_hash_t *module_hash; - ftdm_hash_t *span_hash; - ftdm_hash_t *group_hash; - ftdm_mutex_t *mutex; - ftdm_mutex_t *span_mutex; - ftdm_mutex_t *group_mutex; - ftdm_sched_t *timingsched; - uint32_t span_index; - uint32_t group_index; - uint32_t running; - ftdm_span_t *spans; - ftdm_group_t *groups; - cpu_monitor_t cpu_monitor; - - ftdm_caller_data_t *call_ids[MAX_CALLIDS+1]; - ftdm_mutex_t *call_id_mutex; - uint32_t last_call_id; - char dtmfdebug_directory[1024]; -} globals; - -enum ftdm_enum_cpu_alarm_action_flags -{ - FTDM_CPU_ALARM_ACTION_WARN = (1 << 0), - FTDM_CPU_ALARM_ACTION_REJECT = (1 << 1) -}; - -/* enum lookup funcs */ -FTDM_ENUM_NAMES(TONEMAP_NAMES, TONEMAP_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_tonemap, ftdm_tonemap2str, ftdm_tonemap_t, TONEMAP_NAMES, FTDM_TONEMAP_INVALID) - -FTDM_ENUM_NAMES(OOB_NAMES, OOB_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_oob_event, ftdm_oob_event2str, ftdm_oob_event_t, OOB_NAMES, FTDM_OOB_INVALID) - -FTDM_ENUM_NAMES(TRUNK_TYPE_NAMES, TRUNK_TYPE_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_trunk_type, ftdm_trunk_type2str, ftdm_trunk_type_t, TRUNK_TYPE_NAMES, FTDM_TRUNK_NONE) - -FTDM_ENUM_NAMES(TRUNK_MODE_NAMES, TRUNK_MODE_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_trunk_mode, ftdm_trunk_mode2str, ftdm_trunk_mode_t, TRUNK_MODE_NAMES, FTDM_TRUNK_MODE_INVALID) - -FTDM_ENUM_NAMES(START_TYPE_NAMES, START_TYPE_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_analog_start_type, ftdm_analog_start_type2str, ftdm_analog_start_type_t, START_TYPE_NAMES, FTDM_ANALOG_START_NA) - -FTDM_ENUM_NAMES(SIGNAL_NAMES, SIGNAL_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_signal_event, ftdm_signal_event2str, ftdm_signal_event_t, SIGNAL_NAMES, FTDM_SIGEVENT_INVALID) - -FTDM_ENUM_NAMES(MDMF_TYPE_NAMES, MDMF_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_mdmf_type, ftdm_mdmf_type2str, ftdm_mdmf_type_t, MDMF_TYPE_NAMES, MDMF_INVALID) - -FTDM_ENUM_NAMES(CHAN_TYPE_NAMES, CHAN_TYPE_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_chan_type, ftdm_chan_type2str, ftdm_chan_type_t, CHAN_TYPE_NAMES, FTDM_CHAN_TYPE_COUNT) - -FTDM_ENUM_NAMES(SIGNALING_STATUS_NAMES, SIGSTATUS_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_signaling_status, ftdm_signaling_status2str, ftdm_signaling_status_t, SIGNALING_STATUS_NAMES, FTDM_SIG_STATE_INVALID) - -FTDM_ENUM_NAMES(TRACE_DIR_NAMES, TRACE_DIR_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_trace_dir, ftdm_trace_dir2str, ftdm_trace_dir_t, TRACE_DIR_NAMES, FTDM_TRACE_DIR_INVALID) - -FTDM_ENUM_NAMES(TRACE_TYPE_NAMES, TRACE_TYPE_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_trace_type, ftdm_trace_type2str, ftdm_trace_type_t, TRACE_TYPE_NAMES, FTDM_TRACE_TYPE_INVALID) - -FTDM_ENUM_NAMES(TON_NAMES, TON_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_ton, ftdm_ton2str, ftdm_ton_t, TON_NAMES, FTDM_TON_INVALID) - -FTDM_ENUM_NAMES(NPI_NAMES, NPI_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_npi, ftdm_npi2str, ftdm_npi_t, NPI_NAMES, FTDM_NPI_INVALID) - -FTDM_ENUM_NAMES(PRESENTATION_NAMES, PRESENTATION_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_presentation, ftdm_presentation2str, ftdm_presentation_t, PRESENTATION_NAMES, FTDM_PRES_INVALID) - -FTDM_ENUM_NAMES(SCREENING_NAMES, SCREENING_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_screening, ftdm_screening2str, ftdm_screening_t, SCREENING_NAMES, FTDM_SCREENING_INVALID) - -FTDM_ENUM_NAMES(BEARER_CAP_NAMES, BEARER_CAP_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_bearer_cap, ftdm_bearer_cap2str, ftdm_bearer_cap_t, BEARER_CAP_NAMES, FTDM_BEARER_CAP_INVALID) - -FTDM_ENUM_NAMES(USER_LAYER1_PROT_NAMES, USER_LAYER1_PROT_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_usr_layer1_prot, ftdm_user_layer1_prot2str, ftdm_user_layer1_prot_t, USER_LAYER1_PROT_NAMES, FTDM_USER_LAYER1_PROT_INVALID) - -FTDM_ENUM_NAMES(CALLING_PARTY_CATEGORY_NAMES, CALLING_PARTY_CATEGORY_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_calling_party_category, ftdm_calling_party_category2str, ftdm_calling_party_category_t, CALLING_PARTY_CATEGORY_NAMES, FTDM_CPC_INVALID) - -FTDM_ENUM_NAMES(INDICATION_NAMES, INDICATION_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_channel_indication, ftdm_channel_indication2str, ftdm_channel_indication_t, INDICATION_NAMES, FTDM_CHANNEL_INDICATE_INVALID) - -FTDM_ENUM_NAMES(TRANSFER_RESPONSE_NAMES, TRANSFER_RESPONSE_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_transfer_response, ftdm_transfer_response2str, ftdm_transfer_response_t, TRANSFER_RESPONSE_NAMES, FTDM_TRANSFER_RESPONSE_INVALID) - -static ftdm_status_t ftdm_group_add_channels(ftdm_span_t* span, int currindex, const char* name); - -static void null_logger(const char *file, const char *func, int line, int level, const char *fmt, ...) -{ - ftdm_unused_arg(file); - ftdm_unused_arg(func); - ftdm_unused_arg(line); - ftdm_unused_arg(level); - ftdm_unused_arg(fmt); -} - - -const char *FTDM_LEVEL_NAMES[9] = { - "EMERG", - "ALERT", - "CRIT", - "ERROR", - "WARNING", - "NOTICE", - "INFO", - "DEBUG", - NULL -}; - -static int ftdm_log_level = FTDM_LOG_LEVEL_DEBUG; - -static void default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...) -{ - char data[1024]; - va_list ap; - - if (level < 0 || level > 7) { - level = 7; - } - if (level > ftdm_log_level) { - return; - } - - va_start(ap, fmt); - - vsnprintf(data, sizeof(data), fmt, ap); - - fprintf(stderr, "[%s] %s:%d %s() %s", FTDM_LEVEL_NAMES[level], file, line, func, data); - - va_end(ap); - -} - -static __inline__ void *ftdm_std_malloc(void *pool, ftdm_size_t size) -{ - void *ptr = malloc(size); - ftdm_unused_arg(pool); - ftdm_assert_return(ptr != NULL, NULL, "Out of memory\n"); - return ptr; -} - -static __inline__ void *ftdm_std_calloc(void *pool, ftdm_size_t elements, ftdm_size_t size) -{ - void *ptr = calloc(elements, size); - ftdm_unused_arg(pool); - ftdm_assert_return(ptr != NULL, NULL, "Out of memory\n"); - return ptr; -} - -static __inline__ void *ftdm_std_realloc(void *pool, void *buff, ftdm_size_t size) -{ - buff = realloc(buff, size); - ftdm_unused_arg(pool); - ftdm_assert_return(buff != NULL, NULL, "Out of memory\n"); - return buff; -} - -static __inline__ void ftdm_std_free(void *pool, void *ptr) -{ - ftdm_unused_arg(pool); - ftdm_assert_return(ptr != NULL, , "Attempted to free null pointer"); - free(ptr); -} - -FT_DECLARE(void) ftdm_set_echocancel_call_begin(ftdm_channel_t *chan) -{ - ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan); - if (ftdm_channel_test_feature(chan, FTDM_CHANNEL_FEATURE_HWEC)) { - if (ftdm_channel_test_feature(chan, FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE)) { - /* If the ec is disabled on idle, we need to enable it unless is a digital call */ - if (caller_data->bearer_capability != FTDM_BEARER_CAP_UNRESTRICTED) { - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Enabling ec for call in channel state %s\n", ftdm_channel_state2str(chan->state)); - ftdm_channel_command(chan, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL); - } - } else { - /* If the ec is enabled on idle, we do nothing unless is a digital call that needs it disabled */ - if (caller_data->bearer_capability == FTDM_BEARER_CAP_UNRESTRICTED) { - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Disabling ec for digital call in channel state %s\n", ftdm_channel_state2str(chan->state)); - ftdm_channel_command(chan, FTDM_COMMAND_DISABLE_ECHOCANCEL, NULL); - } - } - } -} - -FT_DECLARE(void) ftdm_set_echocancel_call_end(ftdm_channel_t *chan) -{ - if (ftdm_channel_test_feature(chan, FTDM_CHANNEL_FEATURE_HWEC)) { - if (ftdm_channel_test_feature(chan, FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE)) { - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Disabling ec on call end in channel state %s\n", ftdm_channel_state2str(chan->state)); - ftdm_channel_command(chan, FTDM_COMMAND_DISABLE_ECHOCANCEL, NULL); - } else { - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Enabling ec back on call end in channel state %s\n", ftdm_channel_state2str(chan->state)); - ftdm_channel_command(chan, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL); - } - } -} - -FT_DECLARE_DATA ftdm_memory_handler_t g_ftdm_mem_handler = -{ - /*.pool =*/ NULL, - /*.malloc =*/ ftdm_std_malloc, - /*.calloc =*/ ftdm_std_calloc, - /*.realloc =*/ ftdm_std_realloc, - /*.free =*/ ftdm_std_free -}; - -FT_DECLARE_DATA ftdm_crash_policy_t g_ftdm_crash_policy = FTDM_CRASH_NEVER; - -static ftdm_status_t ftdm_set_caller_data(ftdm_span_t *span, ftdm_caller_data_t *caller_data) -{ - if (!caller_data) { - ftdm_log(FTDM_LOG_CRIT, "Error: trying to set caller data, but no caller_data!\n"); - return FTDM_FAIL; - } - - if (caller_data->dnis.plan >= FTDM_NPI_INVALID) { - caller_data->dnis.plan = span->default_caller_data.dnis.plan; - } - - if (caller_data->dnis.type >= FTDM_TON_INVALID) { - caller_data->dnis.type = span->default_caller_data.dnis.type; - } - - if (caller_data->cid_num.plan >= FTDM_NPI_INVALID) { - caller_data->cid_num.plan = span->default_caller_data.cid_num.plan; - } - - if (caller_data->cid_num.type >= FTDM_TON_INVALID) { - caller_data->cid_num.type = span->default_caller_data.cid_num.type; - } - - if (caller_data->ani.plan >= FTDM_NPI_INVALID) { - caller_data->ani.plan = span->default_caller_data.ani.plan; - } - - if (caller_data->ani.type >= FTDM_TON_INVALID) { - caller_data->ani.type = span->default_caller_data.ani.type; - } - - if (caller_data->rdnis.plan >= FTDM_NPI_INVALID) { - caller_data->rdnis.plan = span->default_caller_data.rdnis.plan; - } - - if (caller_data->rdnis.type >= FTDM_NPI_INVALID) { - caller_data->rdnis.type = span->default_caller_data.rdnis.type; - } - - if (caller_data->bearer_capability >= FTDM_BEARER_CAP_INVALID) { - caller_data->bearer_capability = span->default_caller_data.bearer_capability; - } - - if (caller_data->bearer_layer1 >= FTDM_USER_LAYER1_PROT_INVALID) { - caller_data->bearer_layer1 = span->default_caller_data.bearer_layer1; - } - - if (FTDM_FAIL == ftdm_is_number(caller_data->cid_num.digits)) { - ftdm_log(FTDM_LOG_DEBUG, "dropping caller id number %s since we only accept digits\n", caller_data->cid_num.digits); - caller_data->cid_num.digits[0] = '\0'; - } - - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_set_caller_data(ftdm_channel_t *ftdmchan, ftdm_caller_data_t *caller_data) -{ - ftdm_status_t err = FTDM_SUCCESS; - if (!ftdmchan) { - ftdm_log(FTDM_LOG_CRIT, "trying to set caller data, but no ftdmchan!\n"); - return FTDM_FAIL; - } - if ((err = ftdm_set_caller_data(ftdmchan->span, caller_data)) != FTDM_SUCCESS) { - return err; - } - ftdmchan->caller_data = *caller_data; - if (ftdmchan->caller_data.bearer_capability == FTDM_BEARER_CAP_UNRESTRICTED) { - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_DIGITAL_MEDIA); - } - return FTDM_SUCCESS; -} - -FT_DECLARE_DATA ftdm_logger_t ftdm_log = null_logger; - -FT_DECLARE(void) ftdm_global_set_crash_policy(ftdm_crash_policy_t policy) -{ - g_ftdm_crash_policy |= policy; -} - -FT_DECLARE(ftdm_status_t) ftdm_global_set_memory_handler(ftdm_memory_handler_t *handler) -{ - if (!handler) { - return FTDM_FAIL; - } - if (!handler->malloc) { - return FTDM_FAIL; - } - if (!handler->calloc) { - return FTDM_FAIL; - } - if (!handler->free) { - return FTDM_FAIL; - } - memcpy(&g_ftdm_mem_handler, handler, sizeof(*handler)); - return FTDM_SUCCESS; -} - -FT_DECLARE(void) ftdm_global_set_logger(ftdm_logger_t logger) -{ - if (logger) { - ftdm_log = logger; - } else { - ftdm_log = null_logger; - } -} - -FT_DECLARE(void) ftdm_global_set_default_logger(int level) -{ - if (level < 0 || level > 7) { - level = 7; - } - - ftdm_log = default_logger; - ftdm_log_level = level; -} - -FT_DECLARE_NONSTD(int) ftdm_hash_equalkeys(void *k1, void *k2) -{ - return strcmp((char *) k1, (char *) k2) ? 0 : 1; -} - -FT_DECLARE_NONSTD(uint32_t) ftdm_hash_hashfromstring(void *ky) -{ - unsigned char *str = (unsigned char *) ky; - uint32_t hash = 0; - int c; - - while ((c = *str++)) { - hash = c + (hash << 6) + (hash << 16) - hash; - } - - return hash; -} - -static ftdm_status_t ftdm_channel_destroy(ftdm_channel_t *ftdmchan) -{ - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CONFIGURED)) { - - while (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INTHREAD)) { - ftdm_log(FTDM_LOG_INFO, "Waiting for thread to exit on channel %u:%u\n", ftdmchan->span_id, ftdmchan->chan_id); - ftdm_sleep(500); - } - - ftdm_mutex_lock(ftdmchan->pre_buffer_mutex); - ftdm_buffer_destroy(&ftdmchan->pre_buffer); - ftdm_mutex_unlock(ftdmchan->pre_buffer_mutex); - - ftdm_buffer_destroy(&ftdmchan->digit_buffer); - ftdm_buffer_destroy(&ftdmchan->gen_dtmf_buffer); - ftdm_buffer_destroy(&ftdmchan->dtmf_buffer); - ftdm_buffer_destroy(&ftdmchan->fsk_buffer); - ftdmchan->pre_buffer_size = 0; - - ftdm_safe_free(ftdmchan->dtmf_hangup_buf); - - if (ftdmchan->tone_session.buffer) { - teletone_destroy_session(&ftdmchan->tone_session); - memset(&ftdmchan->tone_session, 0, sizeof(ftdmchan->tone_session)); - } - - - if (ftdmchan->span->fio->channel_destroy) { - ftdm_log(FTDM_LOG_INFO, "Closing channel %s:%u:%u fd:%d\n", ftdmchan->span->type, ftdmchan->span_id, ftdmchan->chan_id, ftdmchan->sockfd); - if (ftdmchan->span->fio->channel_destroy(ftdmchan) == FTDM_SUCCESS) { - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_CONFIGURED); - } else { - ftdm_log(FTDM_LOG_ERROR, "Error Closing channel %u:%u fd:%d\n", ftdmchan->span_id, ftdmchan->chan_id, ftdmchan->sockfd); - } - } - - ftdm_mutex_destroy(&ftdmchan->mutex); - ftdm_mutex_destroy(&ftdmchan->pre_buffer_mutex); - if (ftdmchan->state_completed_interrupt) { - ftdm_interrupt_destroy(&ftdmchan->state_completed_interrupt); - } - } - - return FTDM_SUCCESS; -} - -static ftdm_status_t ftdm_span_destroy(ftdm_span_t *span) -{ - ftdm_status_t status = FTDM_SUCCESS; - unsigned j; - - /* The signaling must be already stopped (this is just a sanity check, should never happen) */ - ftdm_assert_return(!ftdm_test_flag(span, FTDM_SPAN_STARTED), FTDM_FAIL, "Signaling for span %s has not been stopped, refusing to destroy span\n"); - - ftdm_mutex_lock(span->mutex); - - /* destroy the channels */ - ftdm_clear_flag(span, FTDM_SPAN_CONFIGURED); - for(j = 1; j <= span->chan_count && span->channels[j]; j++) { - ftdm_channel_t *cur_chan = span->channels[j]; - if (cur_chan) { - if (ftdm_test_flag(cur_chan, FTDM_CHANNEL_CONFIGURED)) { - ftdm_channel_destroy(cur_chan); - } - ftdm_safe_free(cur_chan); - cur_chan = NULL; - } - } - - /* destroy the I/O for the span */ - if (span->fio && span->fio->span_destroy) { - ftdm_log(FTDM_LOG_INFO, "Destroying span %u type (%s)\n", span->span_id, span->type); - if (span->fio->span_destroy(span) != FTDM_SUCCESS) { - status = FTDM_FAIL; - } - } - - /* destroy final basic resources of the span data structure */ - if (span->pendingchans) { - ftdm_queue_destroy(&span->pendingchans); - } - if (span->pendingsignals) { - ftdm_sigmsg_t *sigmsg = NULL; - while ((sigmsg = ftdm_queue_dequeue(span->pendingsignals))) { - ftdm_sigmsg_free(&sigmsg); - } - ftdm_queue_destroy(&span->pendingsignals); - } - ftdm_mutex_unlock(span->mutex); - ftdm_mutex_destroy(&span->mutex); - - /* Give the span a chance to destroy its own signaling data */ - if (span->destroy) { - span->destroy(span); - } else if (span->signal_data) { - /* We take care of their dirty business ... */ - ftdm_free(span->signal_data); - } - - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_get_alarms(ftdm_channel_t *ftdmchan, ftdm_alarm_flag_t *alarmbits) -{ - ftdm_status_t status = FTDM_FAIL; - - ftdm_assert_return(alarmbits != NULL, FTDM_EINVAL, "null alarmbits argument\n"); - ftdm_assert_return(ftdmchan != NULL, FTDM_EINVAL, "null channel argument\n"); - ftdm_assert_return(ftdmchan->span != NULL, FTDM_EINVAL, "null span\n"); - ftdm_assert_return(ftdmchan->span->fio != NULL, FTDM_EINVAL, "null io\n"); - - *alarmbits = FTDM_ALARM_NONE; - - if (!ftdmchan->span->fio->get_alarms) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "No get_alarms interface for this channel\n"); - return FTDM_ENOSYS; - } - - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CONFIGURED)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Cannot get alarms from an unconfigured channel\n"); - return FTDM_EINVAL; - } - - ftdm_channel_lock(ftdmchan); - - if ((status = ftdmchan->span->fio->get_alarms(ftdmchan)) != FTDM_SUCCESS) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to get alarms from channel\n"); - goto done; - } - - *ftdmchan->last_error = '\0'; - *alarmbits = ftdmchan->alarm_flags; - if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_RED)) { - snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "RED/"); - } - if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_YELLOW)) { - snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "YELLOW/"); - } - if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_RAI)) { - snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "RAI/"); - } - if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_BLUE)) { - snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "BLUE/"); - } - if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_AIS)) { - snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "AIS/"); - } - if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_GENERAL)) { - snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "GENERAL"); - } - *(ftdmchan->last_error + strlen(ftdmchan->last_error) - 1) = '\0'; - -done: - - ftdm_channel_unlock(ftdmchan); - - return status; -} - -static void ftdm_span_add(ftdm_span_t *span) -{ - ftdm_span_t *sp; - ftdm_mutex_lock(globals.span_mutex); - for (sp = globals.spans; sp && sp->next; sp = sp->next); - if (sp) { - sp->next = span; - } else { - globals.spans = span; - } - hashtable_insert(globals.span_hash, (void *)span->name, span, HASHTABLE_FLAG_FREE_VALUE); - ftdm_mutex_unlock(globals.span_mutex); -} - -FT_DECLARE(ftdm_status_t) ftdm_span_stop(ftdm_span_t *span) -{ - ftdm_status_t status = FTDM_SUCCESS; - - ftdm_mutex_lock(span->mutex); - - if (ftdm_test_flag(span, FTDM_SPAN_NON_STOPPABLE)) { - status = FTDM_NOTIMPL; - goto done; - } - - if (!ftdm_test_flag(span, FTDM_SPAN_STARTED)) { - status = FTDM_EINVAL; - goto done; - } - - if (!span->stop) { - status = FTDM_ENOSYS; - goto done; - } - - /* Stop SIG */ - status = span->stop(span); - if (status == FTDM_SUCCESS) { - ftdm_clear_flag(span, FTDM_SPAN_STARTED); - } - - /* Stop I/O */ - if (span->fio && span->fio->span_stop) { - status = span->fio->span_stop(span); - } -done: - ftdm_mutex_unlock(span->mutex); - - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_span_create(const char *iotype, const char *name, ftdm_span_t **span) -{ - ftdm_span_t *new_span = NULL; - ftdm_io_interface_t *fio = NULL; - ftdm_status_t status = FTDM_FAIL; - char buf[128] = ""; - - ftdm_assert_return(iotype != NULL, FTDM_FAIL, "No IO type provided\n"); - ftdm_assert_return(name != NULL, FTDM_FAIL, "No span name provided\n"); - - *span = NULL; - - fio = ftdm_global_get_io_interface(iotype, FTDM_TRUE); - if (!fio) { - ftdm_log(FTDM_LOG_CRIT, "failure creating span, no such I/O type '%s'\n", iotype); - return FTDM_FAIL; - } - - if (!fio->configure_span) { - ftdm_log(FTDM_LOG_CRIT, "failure creating span, no configure_span method for I/O type '%s'\n", iotype); - return FTDM_FAIL; - } - - ftdm_mutex_lock(globals.mutex); - if (globals.span_index < FTDM_MAX_SPANS_INTERFACE) { - new_span = ftdm_calloc(sizeof(*new_span), 1); - - ftdm_assert(new_span, "allocating span failed\n"); - - status = ftdm_mutex_create(&new_span->mutex); - ftdm_assert(status == FTDM_SUCCESS, "mutex creation failed\n"); - - ftdm_set_flag(new_span, FTDM_SPAN_CONFIGURED); - new_span->span_id = ++globals.span_index; - new_span->fio = fio; - ftdm_copy_string(new_span->tone_map[FTDM_TONEMAP_DIAL], "%(1000,0,350,440)", FTDM_TONEMAP_LEN); - ftdm_copy_string(new_span->tone_map[FTDM_TONEMAP_RING], "%(2000,4000,440,480)", FTDM_TONEMAP_LEN); - ftdm_copy_string(new_span->tone_map[FTDM_TONEMAP_BUSY], "%(500,500,480,620)", FTDM_TONEMAP_LEN); - ftdm_copy_string(new_span->tone_map[FTDM_TONEMAP_ATTN], "%(100,100,1400,2060,2450,2600)", FTDM_TONEMAP_LEN); - new_span->trunk_type = FTDM_TRUNK_NONE; - new_span->trunk_mode = FTDM_TRUNK_MODE_CPE; - new_span->data_type = FTDM_TYPE_SPAN; - - ftdm_mutex_lock(globals.span_mutex); - if (!ftdm_strlen_zero(name) && hashtable_search(globals.span_hash, (void *)name)) { - ftdm_log(FTDM_LOG_WARNING, "name %s is already used, substituting 'span%d' as the name\n", name, new_span->span_id); - name = NULL; - } - ftdm_mutex_unlock(globals.span_mutex); - - if (!name) { - snprintf(buf, sizeof(buf), "span%d", new_span->span_id); - name = buf; - } - new_span->name = ftdm_strdup(name); - new_span->type = ftdm_strdup(iotype); - ftdm_span_add(new_span); - *span = new_span; - status = FTDM_SUCCESS; - } - ftdm_mutex_unlock(globals.mutex); - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_span_close_all(void) -{ - ftdm_span_t *span; - uint32_t i = 0, j; - - ftdm_mutex_lock(globals.span_mutex); - for (span = globals.spans; span; span = span->next) { - if (ftdm_test_flag(span, FTDM_SPAN_CONFIGURED)) { - for(j = 1; j <= span->chan_count && span->channels[j]; j++) { - ftdm_channel_t *toclose = span->channels[j]; - if (ftdm_test_flag(toclose, FTDM_CHANNEL_INUSE)) { - ftdm_channel_close(&toclose); - } - i++; - } - } - } - ftdm_mutex_unlock(globals.span_mutex); - - return i ? FTDM_SUCCESS : FTDM_FAIL; -} - -FT_DECLARE(ftdm_status_t) ftdm_span_load_tones(ftdm_span_t *span, const char *mapname) -{ - ftdm_config_t cfg; - char *var, *val; - int x = 0; - - if (!ftdm_config_open_file(&cfg, "tones.conf")) { - snprintf(span->last_error, sizeof(span->last_error), "error loading tones."); - return FTDM_FAIL; - } - - while (ftdm_config_next_pair(&cfg, &var, &val)) { - int detect = 0; - - if (!strcasecmp(cfg.category, mapname) && var && val) { - uint32_t index; - char *name = NULL; - - if (!strncasecmp(var, "detect-", 7)) { - name = var + 7; - detect = 1; - } else if (!strncasecmp(var, "generate-", 9)) { - name = var + 9; - } else { - ftdm_log(FTDM_LOG_WARNING, "Unknown tone name %s\n", var); - continue; - } - - index = ftdm_str2ftdm_tonemap(name); - - if (index >= FTDM_TONEMAP_INVALID || index == FTDM_TONEMAP_NONE) { - ftdm_log(FTDM_LOG_WARNING, "Unknown tone name %s\n", name); - } else { - if (detect) { - char *p = val, *next; - int i = 0; - do { - teletone_process_t this; - next = strchr(p, ','); - this = (teletone_process_t)atof(p); - span->tone_detect_map[index].freqs[i++] = this; - if (next) { - p = next + 1; - } - } while (next); - ftdm_log(FTDM_LOG_DEBUG, "added tone detect [%s] = [%s]\n", name, val); - } else { - ftdm_log(FTDM_LOG_DEBUG, "added tone generation [%s] = [%s]\n", name, val); - ftdm_copy_string(span->tone_map[index], val, sizeof(span->tone_map[index])); - } - x++; - } - } - } - - ftdm_config_close_file(&cfg); - - if (!x) { - snprintf(span->last_error, sizeof(span->last_error), "error loading tones."); - return FTDM_FAIL; - } - - return FTDM_SUCCESS; - -} - -#define FTDM_SLINEAR_MAX_VALUE 32767 -#define FTDM_SLINEAR_MIN_VALUE -32767 -static void reset_gain_table(uint8_t *gain_table, float new_gain, ftdm_codec_t codec_gain) -{ - /* sample value */ - uint8_t sv = 0; - /* linear gain factor */ - float lingain = 0; - /* linear value for each table sample */ - float linvalue = 0; - /* amplified (or attenuated in case of negative amplification) sample value */ - int ampvalue = 0; - - /* gain tables are only for alaw and ulaw */ - if (codec_gain != FTDM_CODEC_ALAW && codec_gain != FTDM_CODEC_ULAW) { - ftdm_log(FTDM_LOG_DEBUG, "Not resetting gain table because codec is not ALAW or ULAW but %d\n", codec_gain); - return; - } - - if (!new_gain) { - /* for a 0.0db gain table, each alaw/ulaw sample value is left untouched (0 ==0, 1 == 1, 2 == 2 etc)*/ - sv = 0; - while (1) { - gain_table[sv] = sv; - if (sv == (FTDM_GAINS_TABLE_SIZE-1)) { - break; - } - sv++; - } - return; - } - - /* use the 20log rule to increase the gain: http://en.wikipedia.org/wiki/Gain, http:/en.wipedia.org/wiki/20_log_rule#Definitions */ - lingain = (float)pow(10.0, new_gain/ 20.0); - sv = 0; - while (1) { - /* get the linear value for this alaw/ulaw sample value */ - linvalue = codec_gain == FTDM_CODEC_ALAW ? (float)alaw_to_linear(sv) : (float)ulaw_to_linear(sv); - - /* multiply the linear value and the previously calculated linear gain */ - ampvalue = (int)(linvalue * lingain); - - /* chop it if goes beyond the limits */ - if (ampvalue > FTDM_SLINEAR_MAX_VALUE) { - ampvalue = FTDM_SLINEAR_MAX_VALUE; - } - - if (ampvalue < FTDM_SLINEAR_MIN_VALUE) { - ampvalue = FTDM_SLINEAR_MIN_VALUE; - } - gain_table[sv] = codec_gain == FTDM_CODEC_ALAW ? linear_to_alaw(ampvalue) : linear_to_ulaw(ampvalue); - if (sv == (FTDM_GAINS_TABLE_SIZE-1)) { - break; - } - sv++; - } -} - -FT_DECLARE(ftdm_status_t) ftdm_span_add_channel(ftdm_span_t *span, ftdm_socket_t sockfd, ftdm_chan_type_t type, ftdm_channel_t **chan) -{ - unsigned char i = 0; - if (span->chan_count < FTDM_MAX_CHANNELS_SPAN) { - ftdm_channel_t *new_chan = span->channels[++span->chan_count]; - - if (!new_chan) { -#ifdef FTDM_DEBUG_CHAN_MEMORY - void *chanmem = NULL; - int pages = 1; - int pagesize = sysconf(_SC_PAGE_SIZE); - if (sizeof(*new_chan) > pagesize) { - pages = sizeof(*new_chan)/pagesize; - pages++; - } - ftdm_log(FTDM_LOG_DEBUG, "Allocating %d pages of %d bytes for channel of size %d\n", pages, pagesize, sizeof(*new_chan)); - if (posix_memalign(&chanmem, pagesize, pagesize*pages)) { - return FTDM_FAIL; - } - ftdm_log(FTDM_LOG_DEBUG, "Channel pages allocated start at mem %p\n", chanmem); - memset(chanmem, 0, sizeof(*new_chan)); - new_chan = chanmem; -#else - if (!(new_chan = ftdm_calloc(1, sizeof(*new_chan)))) { - return FTDM_FAIL; - } -#endif - span->channels[span->chan_count] = new_chan; - } - - new_chan->type = type; - new_chan->sockfd = sockfd; - new_chan->fio = span->fio; - new_chan->span_id = span->span_id; - new_chan->chan_id = span->chan_count; - new_chan->span = span; - new_chan->fds[FTDM_READ_TRACE_INDEX] = -1; - new_chan->fds[FTDM_WRITE_TRACE_INDEX] = -1; - new_chan->data_type = FTDM_TYPE_CHANNEL; - if (!new_chan->dtmf_on) { - new_chan->dtmf_on = FTDM_DEFAULT_DTMF_ON; - } - - if (!new_chan->dtmf_off) { - new_chan->dtmf_off = FTDM_DEFAULT_DTMF_OFF; - } - - ftdm_mutex_create(&new_chan->mutex); - ftdm_mutex_create(&new_chan->pre_buffer_mutex); - - ftdm_buffer_create(&new_chan->digit_buffer, 128, 128, 0); - ftdm_buffer_create(&new_chan->gen_dtmf_buffer, 128, 128, 0); - - new_chan->dtmf_hangup_buf = ftdm_calloc (span->dtmf_hangup_len + 1, sizeof (char)); - - /* set 0.0db gain table */ - i = 0; - while (1) { - new_chan->txgain_table[i] = i; - new_chan->rxgain_table[i] = i; - if (i == (sizeof(new_chan->txgain_table)-1)) { - break; - } - i++; - } - - ftdm_set_flag(new_chan, FTDM_CHANNEL_CONFIGURED | FTDM_CHANNEL_READY); - new_chan->state = FTDM_CHANNEL_STATE_DOWN; - new_chan->state_status = FTDM_STATE_STATUS_COMPLETED; - *chan = new_chan; - return FTDM_SUCCESS; - } - - return FTDM_FAIL; -} - -FT_DECLARE(ftdm_status_t) ftdm_span_find_by_name(const char *name, ftdm_span_t **span) -{ - ftdm_status_t status = FTDM_FAIL; - - ftdm_mutex_lock(globals.span_mutex); - if (!ftdm_strlen_zero(name)) { - if ((*span = hashtable_search(globals.span_hash, (void *)name))) { - status = FTDM_SUCCESS; - } else { - int span_id = atoi(name); - - ftdm_span_find(span_id, span); - if (*span) { - status = FTDM_SUCCESS; - } - } - } - ftdm_mutex_unlock(globals.span_mutex); - - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_span_find(uint32_t id, ftdm_span_t **span) -{ - ftdm_span_t *fspan = NULL, *sp; - - if (id > FTDM_MAX_SPANS_INTERFACE) { - return FTDM_FAIL; - } - - ftdm_mutex_lock(globals.span_mutex); - for (sp = globals.spans; sp; sp = sp->next) { - if (sp->span_id == id) { - fspan = sp; - break; - } - } - ftdm_mutex_unlock(globals.span_mutex); - - if (!fspan || !ftdm_test_flag(fspan, FTDM_SPAN_CONFIGURED)) { - return FTDM_FAIL; - } - - *span = fspan; - - return FTDM_SUCCESS; - -} - -FT_DECLARE(ftdm_status_t) ftdm_span_poll_event(ftdm_span_t *span, uint32_t ms, short *poll_events) -{ - assert(span->fio != NULL); - - if (span->fio->poll_event) { - return span->fio->poll_event(span, ms, poll_events); - } else { - ftdm_log(FTDM_LOG_ERROR, "poll_event method not implemented in module %s!", span->fio->name); - } - - return FTDM_NOTIMPL; -} - -/* handle oob events and send the proper SIGEVENT signal to user, when applicable */ -static __inline__ ftdm_status_t ftdm_event_handle_oob(ftdm_event_t *event) -{ - ftdm_sigmsg_t sigmsg; - ftdm_status_t status = FTDM_SUCCESS; - ftdm_channel_t *fchan = event->channel; - ftdm_span_t *span = fchan->span; - - memset(&sigmsg, 0, sizeof(sigmsg)); - sigmsg.span_id = span->span_id; - sigmsg.chan_id = fchan->chan_id; - sigmsg.channel = fchan; - switch (event->enum_id) { - case FTDM_OOB_ALARM_CLEAR: - { - sigmsg.event_id = FTDM_SIGEVENT_ALARM_CLEAR; - ftdm_clear_flag_locked(fchan, FTDM_CHANNEL_IN_ALARM); - status = ftdm_span_send_signal(span, &sigmsg); - } - break; - case FTDM_OOB_ALARM_TRAP: - { - sigmsg.event_id = FTDM_SIGEVENT_ALARM_TRAP; - ftdm_set_flag_locked(fchan, FTDM_CHANNEL_IN_ALARM); - status = ftdm_span_send_signal(span, &sigmsg); - } - break; - default: - /* NOOP */ - break; - } - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_span_next_event(ftdm_span_t *span, ftdm_event_t **event) -{ - ftdm_status_t status = FTDM_FAIL; - ftdm_assert_return(span->fio != NULL, FTDM_FAIL, "No I/O module attached to this span!\n"); - - if (!span->fio->next_event) { - ftdm_log(FTDM_LOG_ERROR, "next_event method not implemented in module %s!", span->fio->name); - return FTDM_NOTIMPL; - } - - status = span->fio->next_event(span, event); - if (status != FTDM_SUCCESS) { - return status; - } - - status = ftdm_event_handle_oob(*event); - if (status != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "failed to handle event %d\n", (*event)->e_type); - } - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_read_event(ftdm_channel_t *ftdmchan, ftdm_event_t **event) -{ - ftdm_status_t status = FTDM_FAIL; - ftdm_span_t *span = ftdmchan->span; - ftdm_assert_return(span->fio != NULL, FTDM_FAIL, "No I/O module attached to this span!\n"); - - ftdm_channel_lock(ftdmchan); - - if (!span->fio->channel_next_event) { - ftdm_log(FTDM_LOG_ERROR, "channel_next_event method not implemented in module %s!\n", span->fio->name); - status = FTDM_NOTIMPL; - goto done; - } - - if (ftdm_test_io_flag(ftdmchan, FTDM_CHANNEL_IO_EVENT)) { - ftdm_clear_io_flag(ftdmchan, FTDM_CHANNEL_IO_EVENT); - } - - status = span->fio->channel_next_event(ftdmchan, event); - if (status != FTDM_SUCCESS) { - goto done; - } - - status = ftdm_event_handle_oob(*event); - if (status != FTDM_SUCCESS) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "failed to handle event %d\n", (*event)->e_type); - } - -done: - ftdm_channel_unlock(ftdmchan); - return status; -} - -static ftdm_status_t ftdmchan_fsk_write_sample(int16_t *buf, ftdm_size_t buflen, void *user_data) -{ - ftdm_channel_t *ftdmchan = (ftdm_channel_t *) user_data; - ftdm_buffer_write(ftdmchan->fsk_buffer, buf, buflen * 2); - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_send_fsk_data(ftdm_channel_t *ftdmchan, ftdm_fsk_data_state_t *fsk_data, float db_level) -{ - struct ftdm_fsk_modulator fsk_trans; - - if (!ftdmchan->fsk_buffer) { - ftdm_buffer_create(&ftdmchan->fsk_buffer, 128, 128, 0); - } else { - ftdm_buffer_zero(ftdmchan->fsk_buffer); - } - - if (ftdmchan->token_count > 1) { - ftdm_fsk_modulator_init(&fsk_trans, FSK_BELL202, ftdmchan->rate, fsk_data, db_level, 80, 5, 0, ftdmchan_fsk_write_sample, ftdmchan); - ftdm_fsk_modulator_send_all((&fsk_trans)); - } else { - ftdm_fsk_modulator_init(&fsk_trans, FSK_BELL202, ftdmchan->rate, fsk_data, db_level, 180, 5, 300, ftdmchan_fsk_write_sample, ftdmchan); - ftdm_fsk_modulator_send_all((&fsk_trans)); - ftdmchan->buffer_delay = 3500 / ftdmchan->effective_interval; - } - - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_clear_token(ftdm_channel_t *ftdmchan, const char *token) -{ - ftdm_status_t status = FTDM_FAIL; - - ftdm_mutex_lock(ftdmchan->mutex); - if (token == NULL) { - memset(ftdmchan->tokens, 0, sizeof(ftdmchan->tokens)); - ftdmchan->token_count = 0; - } else if (*token != '\0') { - char tokens[FTDM_MAX_TOKENS][FTDM_TOKEN_STRLEN]; - int32_t i, count = ftdmchan->token_count; - memcpy(tokens, ftdmchan->tokens, sizeof(tokens)); - memset(ftdmchan->tokens, 0, sizeof(ftdmchan->tokens)); - ftdmchan->token_count = 0; - - for (i = 0; i < count; i++) { - if (strcmp(tokens[i], token)) { - ftdm_copy_string(ftdmchan->tokens[ftdmchan->token_count], tokens[i], sizeof(ftdmchan->tokens[ftdmchan->token_count])); - ftdmchan->token_count++; - } - } - - status = FTDM_SUCCESS; - } - ftdm_mutex_unlock(ftdmchan->mutex); - - return status; -} - -FT_DECLARE(void) ftdm_channel_rotate_tokens(ftdm_channel_t *ftdmchan) -{ - if (ftdmchan->token_count) { - memmove(ftdmchan->tokens[1], ftdmchan->tokens[0], ftdmchan->token_count * FTDM_TOKEN_STRLEN); - ftdm_copy_string(ftdmchan->tokens[0], ftdmchan->tokens[ftdmchan->token_count], FTDM_TOKEN_STRLEN); - *ftdmchan->tokens[ftdmchan->token_count] = '\0'; - } -} - -FT_DECLARE(void) ftdm_channel_replace_token(ftdm_channel_t *ftdmchan, const char *old_token, const char *new_token) -{ - unsigned int i; - - if (ftdmchan->token_count) { - for(i = 0; i < ftdmchan->token_count; i++) { - if (!strcmp(ftdmchan->tokens[i], old_token)) { - ftdm_copy_string(ftdmchan->tokens[i], new_token, FTDM_TOKEN_STRLEN); - break; - } - } - } -} - -FT_DECLARE(void) ftdm_channel_set_private(ftdm_channel_t *ftdmchan, void *pvt) -{ - ftdmchan->user_private = pvt; -} - -FT_DECLARE(void *) ftdm_channel_get_private(const ftdm_channel_t *ftdmchan) -{ - return ftdmchan->user_private; -} - -FT_DECLARE(uint32_t) ftdm_channel_get_token_count(const ftdm_channel_t *ftdmchan) -{ - uint32_t count; - ftdm_mutex_lock(ftdmchan->mutex); - count = ftdmchan->token_count; - ftdm_mutex_unlock(ftdmchan->mutex); - return count; -} - -FT_DECLARE(uint32_t) ftdm_channel_get_io_interval(const ftdm_channel_t *ftdmchan) -{ - uint32_t count; - ftdm_mutex_lock(ftdmchan->mutex); - count = ftdmchan->effective_interval; - ftdm_mutex_unlock(ftdmchan->mutex); - return count; -} - -FT_DECLARE(uint32_t) ftdm_channel_get_io_packet_len(const ftdm_channel_t *ftdmchan) -{ - uint32_t count; - ftdm_mutex_lock(ftdmchan->mutex); - count = ftdmchan->packet_len; - ftdm_mutex_unlock(ftdmchan->mutex); - return count; -} - -FT_DECLARE(uint32_t) ftdm_channel_get_type(const ftdm_channel_t *ftdmchan) -{ - return ftdmchan->type; -} - -FT_DECLARE(ftdm_codec_t) ftdm_channel_get_codec(const ftdm_channel_t *ftdmchan) -{ - return ftdmchan->effective_codec; -} - -FT_DECLARE(const char *) ftdm_channel_get_token(const ftdm_channel_t *ftdmchan, uint32_t tokenid) -{ - const char *token = NULL; - ftdm_mutex_lock(ftdmchan->mutex); - - if (ftdmchan->token_count <= tokenid) { - ftdm_mutex_unlock(ftdmchan->mutex); - return NULL; - } - - token = ftdmchan->tokens[tokenid]; - ftdm_mutex_unlock(ftdmchan->mutex); - return token; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_add_token(ftdm_channel_t *ftdmchan, char *token, int end) -{ - ftdm_status_t status = FTDM_FAIL; - - ftdm_mutex_lock(ftdmchan->mutex); - if (ftdmchan->token_count < FTDM_MAX_TOKENS) { - if (end) { - ftdm_copy_string(ftdmchan->tokens[ftdmchan->token_count++], token, FTDM_TOKEN_STRLEN); - } else { - memmove(ftdmchan->tokens[1], ftdmchan->tokens[0], ftdmchan->token_count * FTDM_TOKEN_STRLEN); - ftdm_copy_string(ftdmchan->tokens[0], token, FTDM_TOKEN_STRLEN); - ftdmchan->token_count++; - } - status = FTDM_SUCCESS; - } - ftdm_mutex_unlock(ftdmchan->mutex); - - return status; -} - - -FT_DECLARE(uint32_t) ftdm_group_get_id(const ftdm_group_t *group) -{ - return group->group_id; -} - -FT_DECLARE(ftdm_status_t) ftdm_group_channel_use_count(ftdm_group_t *group, uint32_t *count) -{ - uint32_t j; - - *count = 0; - - if (!group) { - return FTDM_FAIL; - } - - for(j = 0; j < group->chan_count && group->channels[j]; j++) { - if (group->channels[j]) { - if (ftdm_test_flag(group->channels[j], FTDM_CHANNEL_INUSE)) { - (*count)++; - } - } - } - - return FTDM_SUCCESS; -} - -static __inline__ int chan_is_avail(ftdm_channel_t *check) -{ - if ((check->span->signal_type == FTDM_SIGTYPE_M2UA) || - (check->span->signal_type == FTDM_SIGTYPE_NONE)) { - if (!ftdm_test_flag(check, FTDM_CHANNEL_READY) || - ftdm_test_flag(check, FTDM_CHANNEL_INUSE) || - ftdm_test_flag(check, FTDM_CHANNEL_SUSPENDED) || - ftdm_test_flag(check, FTDM_CHANNEL_IN_ALARM) || - check->state != FTDM_CHANNEL_STATE_DOWN) { - return 0; - } - } else { - if (!ftdm_test_flag(check, FTDM_CHANNEL_READY) || - !ftdm_test_flag(check, FTDM_CHANNEL_SIG_UP) || - ftdm_test_flag(check, FTDM_CHANNEL_INUSE) || - ftdm_test_flag(check, FTDM_CHANNEL_SUSPENDED) || - ftdm_test_flag(check, FTDM_CHANNEL_IN_ALARM) || - check->state != FTDM_CHANNEL_STATE_DOWN) { - return 0; - } - } - /* release guard time check */ - if (check->span->sig_release_guard_time_ms && check->last_release_time) { - ftdm_time_t time_diff = (ftdm_current_time_in_ms() - check->last_release_time); - if (time_diff < check->span->sig_release_guard_time_ms) { - return 0; - } - /* circuit now available for outbound dialing */ - check->last_release_time = 0; - ftdm_log_chan(check, FTDM_LOG_DEBUG, "Channel is now available, release guard timer expired %" FTDM_UINT64_FMT "ms ago\n", (time_diff - check->span->sig_release_guard_time_ms)); - } - return 1; -} - -static __inline__ int chan_voice_is_avail(ftdm_channel_t *check) -{ - if (!FTDM_IS_VOICE_CHANNEL(check)) { - return 0; - } - return chan_is_avail(check); -} - -static __inline__ int request_voice_channel(ftdm_channel_t *check, ftdm_channel_t **ftdmchan, - ftdm_caller_data_t *caller_data, ftdm_hunt_direction_t direction) -{ - ftdm_status_t status; - if (chan_voice_is_avail(check)) { - /* unlocked testing passed, try again with the channel locked */ - ftdm_mutex_lock(check->mutex); - if (chan_voice_is_avail(check)) { - if (check->span && check->span->channel_request) { - /* I am only unlocking here cuz this function is called - * sometimes with the group or span lock held and were - * blocking anyone hunting for channels available and - * I believe teh channel_request() function may take - * a bit of time. However channel_request is a callback - * used by boost and may be only a few other old sig mods - * and it should be deprecated */ - ftdm_mutex_unlock(check->mutex); - ftdm_set_caller_data(check->span, caller_data); - status = check->span->channel_request(check->span, check->chan_id, - direction, caller_data, ftdmchan); - if (status == FTDM_SUCCESS) { - return 1; - } - } else { - status = ftdm_channel_open_chan(check); - if (status == FTDM_SUCCESS) { - *ftdmchan = check; - ftdm_set_flag(check, FTDM_CHANNEL_OUTBOUND); -#if 0 - ftdm_mutex_unlock(check->mutex); -#endif - return 1; - } - } - } - ftdm_mutex_unlock(check->mutex); - } - return 0; -} - -static void __inline__ calculate_best_rate(ftdm_channel_t *check, ftdm_channel_t **best_rated, int *best_rate) -{ - if (ftdm_test_flag(check->span, FTDM_SPAN_USE_AV_RATE)) { - ftdm_mutex_lock(check->mutex); - if (ftdm_test_flag(check, FTDM_CHANNEL_INUSE)) { - /* twiddle */ - } else if (ftdm_test_flag(check, FTDM_CHANNEL_SIG_UP)) { - /* twiddle */ - } else if (check->availability_rate > *best_rate){ - /* the channel is not in use and the signaling status is down, - * it is a potential candidate to place a call */ - *best_rated = check; - *best_rate = check->availability_rate; - } - ftdm_mutex_unlock(check->mutex); - } -} - -static ftdm_status_t __inline__ get_best_rated(ftdm_channel_t **fchan, ftdm_channel_t *best_rated) -{ - ftdm_status_t status; - - if (!best_rated) { - return FTDM_FAIL; - } - - ftdm_mutex_lock(best_rated->mutex); - - if (ftdm_test_flag(best_rated, FTDM_CHANNEL_INUSE)) { - ftdm_mutex_unlock(best_rated->mutex); - return FTDM_FAIL; - } - - ftdm_log_chan_msg(best_rated, FTDM_LOG_DEBUG, "I may not be available but I had the best availability rate, trying to open I/O now\n"); - - status = ftdm_channel_open_chan(best_rated); - if (status != FTDM_SUCCESS) { - ftdm_mutex_unlock(best_rated->mutex); - return FTDM_FAIL; - } - *fchan = best_rated; - ftdm_set_flag(best_rated, FTDM_CHANNEL_OUTBOUND); -#if 0 - ftdm_mutex_unlock(best_rated->mutex); -#endif - return FTDM_SUCCESS; -} - -static uint32_t __inline__ rr_next(uint32_t last, uint32_t min, uint32_t max, ftdm_hunt_direction_t direction) -{ - uint32_t next = min; - - ftdm_log(FTDM_LOG_DEBUG, "last = %d, min = %d, max = %d\n", last, min, max); - - if (direction == FTDM_HUNT_RR_UP) { - next = (last >= max) ? min : ++last; - } else { - next = (last <= min) ? max : --last; - } - return next; -} - - -FT_DECLARE(int) ftdm_channel_get_availability(ftdm_channel_t *ftdmchan) -{ - int availability = -1; - ftdm_channel_lock(ftdmchan); - if (ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_AV_RATE)) { - availability = ftdmchan->availability_rate; - } - ftdm_channel_unlock(ftdmchan); - return availability; -} - -static ftdm_status_t _ftdm_channel_open_by_group(uint32_t group_id, ftdm_hunt_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan) -{ - ftdm_status_t status = FTDM_FAIL; - ftdm_channel_t *check = NULL; - ftdm_channel_t *best_rated = NULL; - ftdm_group_t *group = NULL; - int best_rate = 0; - uint32_t i = 0; - uint32_t count = 0; - uint32_t first_channel = 0; - - if (group_id) { - ftdm_group_find(group_id, &group); - } - - if (!group) { - ftdm_log(FTDM_LOG_ERROR, "Group %d not defined!\n", group_id); - *ftdmchan = NULL; - return FTDM_FAIL; - } - - ftdm_group_channel_use_count(group, &count); - - if (count >= group->chan_count) { - ftdm_log(FTDM_LOG_WARNING, "All circuits are busy (%d channels used out of %d available).\n", count, group->chan_count); - *ftdmchan = NULL; - return FTDM_FAIL; - } - - - if (direction == FTDM_HUNT_BOTTOM_UP) { - i = 0; - } else if (direction == FTDM_HUNT_RR_DOWN || direction == FTDM_HUNT_RR_UP) { - i = rr_next(group->last_used_index, 0, group->chan_count - 1, direction); - first_channel = i; - } else { - i = group->chan_count-1; - } - - ftdm_mutex_lock(group->mutex); - for (;;) { - - if (!(check = group->channels[i])) { - status = FTDM_FAIL; - break; - } - - if (request_voice_channel(check, ftdmchan, caller_data, direction)) { - status = FTDM_SUCCESS; - if (direction == FTDM_HUNT_RR_UP || direction == FTDM_HUNT_RR_DOWN) { - group->last_used_index = i; - } - break; - } - - calculate_best_rate(check, &best_rated, &best_rate); - - if (direction == FTDM_HUNT_BOTTOM_UP) { - if (i >= (group->chan_count - 1)) { - break; - } - i++; - } else if (direction == FTDM_HUNT_RR_DOWN || direction == FTDM_HUNT_RR_UP) { - if (check == best_rated) { - group->last_used_index = i; - } - i = rr_next(i, 0, group->chan_count - 1, direction); - if (first_channel == i) { - break; - } - } else { - if (i == 0) { - break; - } - i--; - } - } - - if (status == FTDM_FAIL) { - status = get_best_rated(ftdmchan, best_rated); - } - - ftdm_mutex_unlock(group->mutex); - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_group(uint32_t group_id, ftdm_hunt_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan) -{ - ftdm_status_t status; - status = _ftdm_channel_open_by_group(group_id, direction, caller_data, ftdmchan); - if (status == FTDM_SUCCESS) { - ftdm_channel_t *fchan = *ftdmchan; - ftdm_channel_unlock(fchan); - } - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_span_channel_use_count(ftdm_span_t *span, uint32_t *count) -{ - uint32_t j; - - *count = 0; - - if (!span || !ftdm_test_flag(span, FTDM_SPAN_CONFIGURED)) { - return FTDM_FAIL; - } - - for(j = 1; j <= span->chan_count && span->channels[j]; j++) { - if (span->channels[j]) { - if (ftdm_test_flag(span->channels[j], FTDM_CHANNEL_INUSE)) { - (*count)++; - } - } - } - - return FTDM_SUCCESS; -} - -/* Hunt a channel by span, if successful the channel is returned locked */ -static ftdm_status_t _ftdm_channel_open_by_span(uint32_t span_id, ftdm_hunt_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan) -{ - ftdm_status_t status = FTDM_FAIL; - ftdm_channel_t *check = NULL; - ftdm_channel_t *best_rated = NULL; - ftdm_span_t *span = NULL; - int best_rate = 0; - uint32_t i = 0; - uint32_t count = 0; - uint32_t first_channel = 0; - - *ftdmchan = NULL; - - if (!span_id) { - ftdm_log(FTDM_LOG_CRIT, "No span supplied\n"); - return FTDM_FAIL; - } - - ftdm_span_find(span_id, &span); - - if (!span || !ftdm_test_flag(span, FTDM_SPAN_CONFIGURED)) { - ftdm_log(FTDM_LOG_CRIT, "span %d not defined or configured!\n", span_id); - return FTDM_FAIL; - } - - ftdm_span_channel_use_count(span, &count); - - if (count >= span->chan_count) { - ftdm_log(FTDM_LOG_WARNING, "All circuits are busy: active=%i max=%i.\n", count, span->chan_count); - return FTDM_FAIL; - } - - if (span->channel_request && !ftdm_test_flag(span, FTDM_SPAN_SUGGEST_CHAN_ID)) { - ftdm_set_caller_data(span, caller_data); - return span->channel_request(span, 0, direction, caller_data, ftdmchan); - } - - ftdm_mutex_lock(span->mutex); - - if (direction == FTDM_HUNT_BOTTOM_UP) { - i = 1; - } else if (direction == FTDM_HUNT_RR_DOWN || direction == FTDM_HUNT_RR_UP) { - i = rr_next(span->last_used_index, 1, span->chan_count, direction); - first_channel = i; - } else { - i = span->chan_count; - } - - for(;;) { - - if (direction == FTDM_HUNT_BOTTOM_UP) { - if (i > span->chan_count) { - break; - } - } else { - if (i == 0) { - break; - } - } - - if (!(check = span->channels[i])) { - status = FTDM_FAIL; - break; - } - - if (request_voice_channel(check, ftdmchan, caller_data, direction)) { - status = FTDM_SUCCESS; - if (direction == FTDM_HUNT_RR_UP || direction == FTDM_HUNT_RR_DOWN) { - span->last_used_index = i; - } - break; - } - - calculate_best_rate(check, &best_rated, &best_rate); - - if (direction == FTDM_HUNT_BOTTOM_UP) { - i++; - } else if (direction == FTDM_HUNT_RR_DOWN || direction == FTDM_HUNT_RR_UP) { - if (check == best_rated) { - span->last_used_index = i; - } - i = rr_next(i, 1, span->chan_count, direction); - if (first_channel == i) { - break; - } - } else { - i--; - } - } - - if (status == FTDM_FAIL) { - status = get_best_rated(ftdmchan, best_rated); - } - - ftdm_mutex_unlock(span->mutex); - - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_hunt_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan) -{ - ftdm_status_t status; - status = _ftdm_channel_open_by_span(span_id, direction, caller_data, ftdmchan); - if (status == FTDM_SUCCESS) { - ftdm_channel_t *fchan = *ftdmchan; - ftdm_channel_unlock(fchan); - } - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan) -{ - ftdm_status_t status = FTDM_FAIL; - - ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "invalid ftdmchan pointer\n"); - - ftdm_mutex_lock(ftdmchan->mutex); - - if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) { - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is suspended\n"); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is suspended\n"); - goto done; - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM) && !ftdm_test_flag(ftdmchan->span, FTDM_SPAN_PWR_SAVING)) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is alarmed\n"); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is alarmed\n"); - goto done; - } - - if (globals.cpu_monitor.alarm && - globals.cpu_monitor.alarm_action_flags & FTDM_CPU_ALARM_ACTION_REJECT) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "CPU usage alarm is on - refusing to open channel\n"); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "CPU usage alarm is on - refusing to open channel\n"); - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_SWITCH_CONGESTION; - goto done; - } - } - - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_READY)) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Channel is not ready"); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is not ready\n"); - goto done; - } - - status = ftdmchan->fio->open(ftdmchan); - if (status == FTDM_SUCCESS) { - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_OPEN | FTDM_CHANNEL_INUSE); - } else { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "IO open failed: %d\n", status); - } - -done: - - ftdm_mutex_unlock(ftdmchan->mutex); - - return status; -} - -static ftdm_status_t _ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan, uint8_t physical) -{ - ftdm_channel_t *check = NULL; - ftdm_span_t *span = NULL; - ftdm_channel_t *best_rated = NULL; - ftdm_status_t status = FTDM_FAIL; - int best_rate = 0; - - *ftdmchan = NULL; - - ftdm_mutex_lock(globals.mutex); - - ftdm_span_find(span_id, &span); - - if (!span) { - ftdm_log(FTDM_LOG_CRIT, "Could not find span!\n"); - goto done; - } - - if (!ftdm_test_flag(span, FTDM_SPAN_CONFIGURED)) { - ftdm_log(FTDM_LOG_CRIT, "Span %d is not configured\n", span_id); - goto done; - } - - if (span->channel_request) { - ftdm_log(FTDM_LOG_ERROR, "Individual channel selection not implemented on this span.\n"); - goto done; - } - - if (physical) { /* Open by physical */ - ftdm_channel_t *fchan = NULL; - ftdm_iterator_t *citer = NULL; - ftdm_iterator_t *curr = NULL; - - if (chan_id < 1) { - ftdm_log(FTDM_LOG_ERROR, "Invalid physical channel %d to open in span %d\n", chan_id, span_id); - status = FTDM_FAIL; - goto done; - } - - citer = ftdm_span_get_chan_iterator(span, NULL); - if (!citer) { - status = ENOMEM; - goto done; - } - - for (curr = citer ; curr; curr = ftdm_iterator_next(curr)) { - fchan = ftdm_iterator_current(curr); - if (fchan->physical_chan_id == chan_id) { - check = fchan; - break; - } - } - - ftdm_iterator_free(citer); - if (!check) { - ftdm_log(FTDM_LOG_CRIT, "Wow, no physical channel %d in span %d\n", chan_id, span_id); - goto done; - } - } else { /* Open by logical */ - if (chan_id < 1 || chan_id > span->chan_count) { - ftdm_log(FTDM_LOG_ERROR, "Invalid channel %d to open in span %d\n", chan_id, span_id); - goto done; - } - - if (!(check = span->channels[chan_id])) { - ftdm_log(FTDM_LOG_CRIT, "Wow, no channel %d in span %d\n", chan_id, span_id); - goto done; - } - } - - ftdm_channel_lock(check); - - if (ftdm_test_flag(check, FTDM_CHANNEL_OPEN)) { - /* let them know is already open, but return the channel anyway */ - status = FTDM_EBUSY; - *ftdmchan = check; - goto unlockchan; - } - - /* The following if's and gotos replace a big if (this || this || this || this) else { nothing; } */ - - /* if it is not a voice channel, nothing else to check to open it */ - if (!FTDM_IS_VOICE_CHANNEL(check)) { - goto openchan; - } - - /* if it's an FXS device with a call active and has callwaiting enabled, we allow to open it twice */ - if (check->type == FTDM_CHAN_TYPE_FXS - && check->token_count == 1 - && ftdm_channel_test_feature(check, FTDM_CHANNEL_FEATURE_CALLWAITING)) { - goto openchan; - } - - /* if channel is available, time to open it */ - if (chan_is_avail(check)) { - goto openchan; - } - - /* not available, but still might be available ... */ - calculate_best_rate(check, &best_rated, &best_rate); - if (best_rated) { - goto openchan; - } - - /* channel is unavailable, do not open the channel */ - goto unlockchan; - -openchan: - if (!ftdm_test_flag(check, FTDM_CHANNEL_OPEN)) { - status = check->fio->open(check); - if (status == FTDM_SUCCESS) { - ftdm_set_flag(check, FTDM_CHANNEL_OPEN); - } - } else { - status = FTDM_SUCCESS; - } - ftdm_set_flag(check, FTDM_CHANNEL_INUSE); - ftdm_set_flag(check, FTDM_CHANNEL_OUTBOUND); - *ftdmchan = check; - - /* we've got the channel, do not unlock it */ - goto done; - -unlockchan: - ftdm_channel_unlock(check); - -done: - ftdm_mutex_unlock(globals.mutex); - if (status != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Failed to open channel %d:%d\n", span_id, chan_id); - } - - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan) -{ - ftdm_status_t status; - status = _ftdm_channel_open(span_id, chan_id, ftdmchan, 0); - if (status == FTDM_SUCCESS) { - ftdm_channel_t *fchan = *ftdmchan; - ftdm_channel_unlock(fchan); - } - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_open_ph(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan) -{ - ftdm_status_t status; - status = _ftdm_channel_open(span_id, chan_id, ftdmchan, 1); - if (status == FTDM_SUCCESS) { - ftdm_channel_t *fchan = *ftdmchan; - ftdm_channel_unlock(fchan); - } - return status; -} - -FT_DECLARE(uint32_t) ftdm_channel_get_id(const ftdm_channel_t *ftdmchan) -{ - return ftdmchan->chan_id; -} - -FT_DECLARE(uint32_t) ftdm_channel_get_ph_id(const ftdm_channel_t *ftdmchan) -{ - return ftdmchan->physical_chan_id; -} - -FT_DECLARE(uint32_t) ftdm_channel_get_span_id(const ftdm_channel_t *ftdmchan) -{ - return ftdmchan->span_id; -} - -FT_DECLARE(ftdm_span_t *) ftdm_channel_get_span(const ftdm_channel_t *ftdmchan) -{ - return ftdmchan->span; -} - -FT_DECLARE(const char *) ftdm_channel_get_span_name(const ftdm_channel_t *ftdmchan) -{ - return ftdmchan->span->name; -} - -FT_DECLARE(void) ftdm_span_set_trunk_type(ftdm_span_t *span, ftdm_trunk_type_t type) -{ - span->trunk_type = type; -} - -FT_DECLARE(ftdm_status_t) ftdm_span_set_blocking_mode(const ftdm_span_t *span, ftdm_bool_t enabled) -{ - ftdm_channel_t *fchan = NULL; - ftdm_iterator_t *citer = NULL; - ftdm_iterator_t *curr = NULL; - - citer = ftdm_span_get_chan_iterator(span, NULL); - if (!citer) { - return FTDM_ENOMEM; - } - - for (curr = citer ; curr; curr = ftdm_iterator_next(curr)) { - fchan = ftdm_iterator_current(curr); - if (enabled) { - ftdm_clear_flag_locked(fchan, FTDM_CHANNEL_NONBLOCK); - } else { - ftdm_set_flag_locked(fchan, FTDM_CHANNEL_NONBLOCK); - } - } - ftdm_iterator_free(citer); - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_trunk_type_t) ftdm_span_get_trunk_type(const ftdm_span_t *span) -{ - return span->trunk_type; -} - -FT_DECLARE(const char *) ftdm_span_get_trunk_type_str(const ftdm_span_t *span) -{ - return ftdm_trunk_type2str(span->trunk_type); -} - -FT_DECLARE(void) ftdm_span_set_trunk_mode(ftdm_span_t *span, ftdm_trunk_mode_t mode) -{ - span->trunk_mode = mode; -} - -FT_DECLARE(ftdm_trunk_mode_t) ftdm_span_get_trunk_mode(const ftdm_span_t *span) -{ - return span->trunk_mode; -} - -FT_DECLARE(const char *) ftdm_span_get_trunk_mode_str(const ftdm_span_t *span) -{ - return ftdm_trunk_mode2str(span->trunk_mode); -} - -FT_DECLARE(uint32_t) ftdm_span_get_id(const ftdm_span_t *span) -{ - return span->span_id; -} - -FT_DECLARE(const char *) ftdm_span_get_name(const ftdm_span_t *span) -{ - return span->name; -} - -FT_DECLARE(const char *) ftdm_channel_get_name(const ftdm_channel_t *ftdmchan) -{ - return ftdmchan->chan_name; -} - -FT_DECLARE(const char *) ftdm_channel_get_number(const ftdm_channel_t *ftdmchan) -{ - return ftdmchan->chan_number; -} - -FT_DECLARE(ftdm_bool_t) ftdm_channel_call_check_hold(const ftdm_channel_t *ftdmchan) -{ - ftdm_bool_t condition; - ftdm_channel_lock(ftdmchan); - condition = ftdm_test_flag(ftdmchan, FTDM_CHANNEL_HOLD) ? FTDM_TRUE : FTDM_FALSE; - ftdm_channel_unlock(ftdmchan); - return condition; -} - -FT_DECLARE(ftdm_bool_t) ftdm_channel_call_check_answered(const ftdm_channel_t *ftdmchan) -{ - ftdm_bool_t condition = FTDM_FALSE; - - ftdm_channel_lock(ftdmchan); - condition = (ftdmchan->state == FTDM_CHANNEL_STATE_UP) ? FTDM_TRUE : FTDM_FALSE; - ftdm_channel_unlock(ftdmchan); - - return condition; -} - -FT_DECLARE(ftdm_bool_t) ftdm_channel_call_check_busy(const ftdm_channel_t *ftdmchan) -{ - ftdm_bool_t condition = FTDM_FALSE; - - ftdm_channel_lock(ftdmchan); - condition = (ftdmchan->state == FTDM_CHANNEL_STATE_BUSY) ? FTDM_TRUE : FTDM_FALSE; - ftdm_channel_unlock(ftdmchan); - - return condition; -} - -FT_DECLARE(ftdm_bool_t) ftdm_channel_call_check_hangup(const ftdm_channel_t *ftdmchan) -{ - ftdm_bool_t condition = FTDM_FALSE; - - ftdm_channel_lock(ftdmchan); - condition = (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP || ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) - ? FTDM_TRUE : FTDM_FALSE; - ftdm_channel_unlock(ftdmchan); - - return condition; -} - -FT_DECLARE(ftdm_bool_t) ftdm_channel_call_check_done(const ftdm_channel_t *ftdmchan) -{ - ftdm_bool_t condition = FTDM_FALSE; - - ftdm_channel_lock(ftdmchan); - condition = (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) ? FTDM_TRUE : FTDM_FALSE; - ftdm_channel_unlock(ftdmchan); - - return condition; -} - -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hold(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg) -{ - ftdm_status_t status; - ftdm_channel_lock(ftdmchan); - - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_HOLD); - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_DIALTONE, 0, usrmsg); - ftdm_channel_unlock(ftdmchan); - - return status; -} - -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_unhold(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg) -{ - ftdm_status_t status; - - ftdm_channel_lock(ftdmchan); - - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_UP, 0, usrmsg); - - ftdm_channel_unlock(ftdmchan); - - return status; -} - -FT_DECLARE(void) ftdm_ack_indication(ftdm_channel_t *fchan, ftdm_channel_indication_t indication, ftdm_status_t status) -{ - ftdm_sigmsg_t msg; - - if (!ftdm_test_flag(fchan, FTDM_CHANNEL_IND_ACK_PENDING)) { - return; - } - - ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Acknowledging indication %s in state %s (rc = %d)\n", - ftdm_channel_indication2str(indication), ftdm_channel_state2str(fchan->state), status); - ftdm_clear_flag(fchan, FTDM_CHANNEL_IND_ACK_PENDING); - memset(&msg, 0, sizeof(msg)); - msg.channel = fchan; - msg.event_id = FTDM_SIGEVENT_INDICATION_COMPLETED; - msg.ev_data.indication_completed.indication = indication; - msg.ev_data.indication_completed.status = status; - ftdm_span_send_signal(fchan->span, &msg); -} - -/*! Answer call without locking the channel. The caller must have locked first */ -static ftdm_status_t _ftdm_channel_call_answer_nl(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg) -{ - ftdm_status_t status = FTDM_SUCCESS; - - if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_SKIP_STATES)) { - /* We will fail RFC's if we not skip states, but some modules apart from ftmod_sangoma_isdn - * expect the call to always to go PROGRESS and PROGRESS MEDIA state before going to UP, so - * use FTDM_SPAN_USE_SKIP_STATES for now while we update the sig modules */ - - if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) { - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1, usrmsg); - if (status != FTDM_SUCCESS) { - status = FTDM_ECANCELED; - goto done; - } - } - - /* set state unlocks the channel so we need to re-confirm that the channel hasn't gone to hell */ - if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call has moved to TERMINATING while we're moving to PROGRESS\n"); - status = FTDM_ECANCELED; - goto done; - } - - if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS_MEDIA) { - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1, usrmsg); - if (status != FTDM_SUCCESS) { - status = FTDM_ECANCELED; - goto done; - } - } - - /* set state unlocks the channel so we need to re-confirm that the channel hasn't gone to hell */ - if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call has moved to TERMINATING while we're moving to UP\n"); - status = FTDM_ECANCELED; - goto done; - } - } - - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_UP, 1, usrmsg); - if (status != FTDM_SUCCESS) { - status = FTDM_ECANCELED; - goto done; - } - -done: - - return status; -} - -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg) -{ - ftdm_status_t status; - - /* we leave the locking up to ftdm_channel_call_indicate, DO NOT lock here since ftdm_channel_call_indicate expects - * the lock recursivity to be 1 */ - status = _ftdm_channel_call_indicate(file, func, line, ftdmchan, FTDM_CHANNEL_INDICATE_ANSWER, usrmsg); - - return status; -} - -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_transfer(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, const char* arg, ftdm_usrmsg_t *usrmsg) -{ - ftdm_status_t status; - ftdm_usrmsg_t *msg = NULL; - ftdm_bool_t free_msg = FTDM_FALSE; - - if (!usrmsg) { - msg = ftdm_calloc(1, sizeof(*msg)); - ftdm_assert_return(msg, FTDM_FAIL, "Failed to allocate usr msg"); - memset(msg, 0, sizeof(*msg)); - free_msg = FTDM_TRUE; - } else { - msg = usrmsg; - } - - ftdm_usrmsg_add_var(msg, "transfer_arg", arg); - /* we leave the locking up to ftdm_channel_call_indicate, DO NOT lock here since ftdm_channel_call_indicate expects - * the lock recursivity to be 1 */ - status = _ftdm_channel_call_indicate(file, func, line, ftdmchan, FTDM_CHANNEL_INDICATE_TRANSFER, msg); - if (free_msg == FTDM_TRUE) { - ftdm_safe_free(msg); - } - return status; -} - -/* lock must be acquired by the caller! */ -static ftdm_status_t _ftdm_channel_call_hangup_nl(const char *file, const char *func, int line, ftdm_channel_t *chan, ftdm_usrmsg_t *usrmsg) -{ - ftdm_status_t status = FTDM_SUCCESS; - - /* In native sigbridge mode we ignore hangup requests from the user and hangup only when the signaling module decides it */ - if (ftdm_test_flag(chan, FTDM_CHANNEL_NATIVE_SIGBRIDGE) && chan->state != FTDM_CHANNEL_STATE_TERMINATING) { - - ftdm_log_chan_ex(chan, file, func, line, FTDM_LOG_LEVEL_DEBUG, - "Ignoring hangup in channel in state %s (native bridge enabled)\n", ftdm_channel_state2str(chan->state)); - ftdm_set_flag(chan, FTDM_CHANNEL_USER_HANGUP); - goto done; - } - - if (chan->state != FTDM_CHANNEL_STATE_DOWN) { - if (chan->state == FTDM_CHANNEL_STATE_HANGUP) { - /* make user's life easier, and just ignore double hangup requests */ - return FTDM_SUCCESS; - } - if (chan->hangup_timer) { - ftdm_sched_cancel_timer(globals.timingsched, chan->hangup_timer); - } - ftdm_set_flag(chan, FTDM_CHANNEL_USER_HANGUP); - /* if a state change requested by the user was pending, a hangup certainly cancels that request */ - if (ftdm_test_flag(chan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_channel_cancel_state(file, func, line, chan); - } - status = ftdm_channel_set_state(file, func, line, chan, FTDM_CHANNEL_STATE_HANGUP, 1, usrmsg); - } else { - /* the signaling stack did not touch the state, - * core is responsible from clearing flags and stuff, however, because ftmod_analog - * is a bitch in a serious need of refactoring, we also check whether the channel is open - * to avoid an spurious warning about the channel not being open. This is because ftmod_analog - * does not follow our convention of sending SIGEVENT_STOP and waiting for the user to move - * to HANGUP (implicitly through ftdm_channel_call_hangup(), as soon as ftmod_analog is fixed - * this check can be removed */ - if (ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) { - ftdm_channel_close(&chan); - } - } - -done: - return status; -} - -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup_with_cause(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_call_cause_t cause, ftdm_usrmsg_t *usrmsg) -{ - ftdm_status_t status = FTDM_SUCCESS; - ftdm_channel_lock(ftdmchan); - - ftdmchan->caller_data.hangup_cause = cause; - - status = _ftdm_channel_call_hangup_nl(file, func, line, ftdmchan, usrmsg); - - ftdm_channel_unlock(ftdmchan); - return status; -} - -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg) -{ - ftdm_status_t status = FTDM_SUCCESS; - - ftdm_channel_lock(ftdmchan); - - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING; - - status = _ftdm_channel_call_hangup_nl(file, func, line, ftdmchan, usrmsg); - - ftdm_channel_unlock(ftdmchan); - return status; -} - -FT_DECLARE(const char *) ftdm_channel_get_last_error(const ftdm_channel_t *ftdmchan) -{ - return ftdmchan->last_error; -} - -FT_DECLARE(const char *) ftdm_span_get_last_error(const ftdm_span_t *span) -{ - return span->last_error; -} - -FT_DECLARE(ftdm_caller_data_t *) ftdm_channel_get_caller_data(ftdm_channel_t *ftdmchan) -{ - return &ftdmchan->caller_data; -} - -FT_DECLARE(ftdm_channel_t *) ftdm_span_get_channel(const ftdm_span_t *span, uint32_t chanid) -{ - ftdm_channel_t *chan; - ftdm_mutex_lock(span->mutex); - if (chanid == 0 || chanid > span->chan_count) { - ftdm_mutex_unlock(span->mutex); - return NULL; - } - chan = span->channels[chanid]; - ftdm_mutex_unlock(span->mutex); - return chan; -} - -FT_DECLARE(ftdm_channel_t *) ftdm_span_get_channel_ph(const ftdm_span_t *span, uint32_t chanid) -{ - ftdm_channel_t *chan = NULL; - ftdm_channel_t *fchan = NULL; - ftdm_iterator_t *citer = NULL; - ftdm_iterator_t *curr = NULL; - - ftdm_mutex_lock(span->mutex); - if (chanid == 0) { - ftdm_mutex_unlock(span->mutex); - return NULL; - } - - citer = ftdm_span_get_chan_iterator(span, NULL); - if (!citer) { - ftdm_mutex_unlock(span->mutex); - return NULL; - } - - for (curr = citer ; curr; curr = ftdm_iterator_next(curr)) { - fchan = ftdm_iterator_current(curr); - if (fchan->physical_chan_id == chanid) { - chan = fchan; - break; - } - } - - ftdm_iterator_free(citer); - - ftdm_mutex_unlock(span->mutex); - return chan; -} - -FT_DECLARE(uint32_t) ftdm_span_get_chan_count(const ftdm_span_t *span) -{ - uint32_t count; - ftdm_mutex_lock(span->mutex); - count = span->chan_count; - ftdm_mutex_unlock(span->mutex); - return count; -} - -FT_DECLARE(uint32_t) ftdm_channel_get_ph_span_id(const ftdm_channel_t *ftdmchan) -{ - uint32_t id; - ftdm_channel_lock(ftdmchan); - id = ftdmchan->physical_span_id; - ftdm_channel_unlock(ftdmchan); - return id; -} - -/* - * Every user requested indication *MUST* be acknowledged with the proper status (ftdm_status_t) - * However, if the indication fails before we notify the signaling stack, we don't need to ack - * but if we already notified the signaling stack about the indication, the signaling stack is - * responsible for the acknowledge. Bottom line is, whenever this function returns FTDM_SUCCESS - * someone *MUST* acknowledge the indication, either the signaling stack, this function or the core - * at some later point - * */ -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication, ftdm_usrmsg_t *usrmsg) -{ - ftdm_status_t status = FTDM_SUCCESS; - - ftdm_assert_return(ftdmchan, FTDM_FAIL, "Null channel\n"); - - ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Indicating %s in state %s\n", - ftdm_channel_indication2str(indication), ftdm_channel_state2str(ftdmchan->state)); - - ftdm_channel_lock(ftdmchan); - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) { - ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, - "Ignoring indication %s in channel in state %s (native bridge enabled)\n", - ftdm_channel_indication2str(indication), - ftdm_channel_state2str(ftdmchan->state)); - status = FTDM_SUCCESS; - goto done; - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IND_ACK_PENDING)) { - ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "Cannot indicate %s in channel with indication %s still pending in state %s\n", - ftdm_channel_indication2str(indication), - ftdm_channel_indication2str(ftdmchan->indication), - ftdm_channel_state2str(ftdmchan->state)); - status = FTDM_EBUSY; - goto done; - } - - ftdmchan->indication = indication; - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NONBLOCK)) { - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_IND_ACK_PENDING); - } - - if (indication != FTDM_CHANNEL_INDICATE_FACILITY && - ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - - ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "Cannot indicate %s in outgoing channel in state %s\n", - ftdm_channel_indication2str(indication), ftdm_channel_state2str(ftdmchan->state)); - status = FTDM_EINVAL; - goto done; - } - - if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) { - ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Ignoring indication %s because the call is in %s state\n", - ftdm_channel_indication2str(indication), ftdm_channel_state2str(ftdmchan->state)); - status = FTDM_ECANCELED; - goto done; - } - - switch (indication) { - /* FIXME: ring and busy cannot be used with all signaling stacks - * (particularly isdn stacks I think, we should emulate or just move to hangup with busy cause) */ - case FTDM_CHANNEL_INDICATE_RINGING: - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RINGING, 1, usrmsg); - break; - case FTDM_CHANNEL_INDICATE_BUSY: - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_BUSY, 1, usrmsg); - break; - case FTDM_CHANNEL_INDICATE_PROCEED: - if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_PROCEED_STATE) || - ftdmchan->state >= FTDM_CHANNEL_STATE_PROCEED) { - ftdm_ack_indication(ftdmchan, indication, status); - goto done; - } - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROCEED, 1, usrmsg); - break; - case FTDM_CHANNEL_INDICATE_PROGRESS: - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1, usrmsg); - break; - case FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA: - if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_SKIP_STATES)) { - if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) { - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1, usrmsg); - if (status != FTDM_SUCCESS) { - goto done; - } - } - - /* set state unlocks the channel so we need to re-confirm that the channel hasn't gone to hell */ - if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) { - ftdm_log_chan_ex_msg(ftdmchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Ignoring progress media because the call is terminating\n"); - goto done; - } - } - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1, usrmsg); - break; - case FTDM_CHANNEL_INDICATE_ANSWER: - status = _ftdm_channel_call_answer_nl(file, func, line, ftdmchan, usrmsg); - break; - case FTDM_CHANNEL_INDICATE_TRANSFER: - if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_TRANSFER)) { - ftdm_log_chan_ex_msg(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "Transfer not supported\n"); - status = FTDM_EINVAL; - goto done; - } - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_TRANSFER, 1, usrmsg); - break; - default: - /* See if signalling module can provide this indication */ - status = ftdm_channel_sig_indicate(ftdmchan, indication, usrmsg); - break; - } - -done: - ftdm_channel_unlock(ftdmchan); - - return status; -} - -FT_DECLARE(ftdm_status_t) _ftdm_channel_reset(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg) -{ - ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel"); - - ftdm_channel_lock(ftdmchan); - ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RESET, 1, usrmsg); - ftdm_channel_unlock(ftdmchan); - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_get_channel_from_string(const char *string_id, ftdm_span_t **out_span, ftdm_channel_t **out_channel) -{ - ftdm_status_t status = FTDM_SUCCESS; - int rc = 0; - ftdm_span_t *span = NULL; - ftdm_channel_t *ftdmchan = NULL; - unsigned span_id = 0; - unsigned chan_id = 0; - - *out_span = NULL; - *out_channel = NULL; - - if (!string_id) { - ftdm_log(FTDM_LOG_ERROR, "Cannot parse NULL channel id string\n"); - status = FTDM_EINVAL; - goto done; - } - - rc = sscanf(string_id, "%u:%u", &span_id, &chan_id); - if (rc != 2) { - ftdm_log(FTDM_LOG_ERROR, "Failed to parse channel id string '%s'\n", string_id); - status = FTDM_EINVAL; - goto done; - } - - status = ftdm_span_find(span_id, &span); - if (status != FTDM_SUCCESS || !span) { - ftdm_log(FTDM_LOG_ERROR, "Failed to find span for channel id string '%s'\n", string_id); - status = FTDM_EINVAL; - goto done; - } - - if (chan_id > (FTDM_MAX_CHANNELS_SPAN+1) || !(ftdmchan = span->channels[chan_id])) { - ftdm_log(FTDM_LOG_ERROR, "Invalid channel id string '%s'\n", string_id); - status = FTDM_EINVAL; - goto done; - } - - status = FTDM_SUCCESS; - *out_span = span; - *out_channel = ftdmchan; -done: - return status; -} - -/* this function MUST be called with the channel lock held with lock recursivity of 1 exactly, - * and the caller must be aware we might unlock the channel for a brief period of time and then lock it again */ -static ftdm_status_t _ftdm_channel_call_place_nl(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg) -{ - const char *var = NULL; - ftdm_status_t status = FTDM_FAIL; - - ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel"); - ftdm_assert_return(ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND), FTDM_FAIL, "Call place, but outbound flag not set\n"); - - if (!ftdmchan->span->outgoing_call) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "outgoing_call method not implemented in this span!\n"); - status = FTDM_ENOSYS; - goto done; - } - - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Cannot place call in channel that is not open!\n"); - goto done; - } - - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot place call in non outbound channel in state %s!\n", ftdm_channel_state2str(ftdmchan->state)); - goto done; - } - - status = ftdmchan->span->outgoing_call(ftdmchan); - if (status == FTDM_BREAK) { - /* the signaling module detected glare on time */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Glare detected, you should hunt in another channel!\n"); - goto done; - } - - if (status != FTDM_SUCCESS) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to place call!\n"); - goto done; - } - - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED); - ftdm_call_set_call_id(ftdmchan, &ftdmchan->caller_data); - var = ftdm_usrmsg_get_var(usrmsg, "sigbridge_peer"); - if (var) { - ftdm_span_t *peer_span = NULL; - ftdm_channel_t *peer_chan = NULL; - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE); - ftdm_get_channel_from_string(var, &peer_span, &peer_chan); - if (peer_chan) { - ftdm_set_flag(peer_chan, FTDM_CHANNEL_NATIVE_SIGBRIDGE); - } - } - - /* if the signaling stack left the channel in state down on success, is expecting us to move to DIALING */ - if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) { - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NONBLOCK)) { - ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_DIALING, 1, usrmsg); - } else { - ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_DIALING, 0, usrmsg); - } - } else if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE) && - !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NONBLOCK)) { - - ftdm_channel_unlock(ftdmchan); - - ftdm_interrupt_wait(ftdmchan->state_completed_interrupt, 500); - - ftdm_channel_lock(ftdmchan); - } - -done: - ftdm_unused_arg(file); - ftdm_unused_arg(func); - ftdm_unused_arg(line); - return status; -} - -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg) -{ - ftdm_status_t status; - ftdm_channel_lock(ftdmchan); - - /* be aware that _ftdm_channl_call_place_nl can unlock/lock the channel quickly if working in blocking mode */ - status = _ftdm_channel_call_place_nl(file, func, line, ftdmchan, usrmsg); - - ftdm_channel_unlock(ftdmchan); - return status; -} - -FT_DECLARE(ftdm_status_t) _ftdm_call_place(const char *file, const char *func, int line, - ftdm_caller_data_t *caller_data, ftdm_hunting_scheme_t *hunting, ftdm_usrmsg_t *usrmsg) -{ - ftdm_status_t status = FTDM_SUCCESS; - ftdm_channel_t *fchan = NULL; - - ftdm_assert_return(caller_data, FTDM_EINVAL, "Invalid caller data\n"); - ftdm_assert_return(hunting, FTDM_EINVAL, "Invalid hunting scheme\n"); - - if (hunting->mode == FTDM_HUNT_SPAN) { - status = _ftdm_channel_open_by_span(hunting->mode_data.span.span_id, - hunting->mode_data.span.direction, caller_data, &fchan); - } else if (hunting->mode == FTDM_HUNT_GROUP) { - status = _ftdm_channel_open_by_group(hunting->mode_data.group.group_id, - hunting->mode_data.group.direction, caller_data, &fchan); - } else if (hunting->mode == FTDM_HUNT_CHAN) { - status = _ftdm_channel_open(hunting->mode_data.chan.span_id, hunting->mode_data.chan.chan_id, &fchan, 0); - } else { - ftdm_log(FTDM_LOG_ERROR, "Cannot make outbound call with invalid hunting mode %d\n", hunting->mode); - return FTDM_EINVAL; - } - - if (status != FTDM_SUCCESS) { - return FTDM_EBUSY; - } - - /* we have a locked channel and are not afraid of using it! */ - if (hunting->result_cb) { - status = hunting->result_cb(fchan, caller_data); - if (status != FTDM_SUCCESS) { - status = FTDM_ECANCELED; - goto done; - } - } - - ftdm_channel_set_caller_data(fchan, caller_data); - - /* be aware that _ftdm_channl_call_place_nl can unlock/lock the channel quickly if working in blocking mode */ - status = _ftdm_channel_call_place_nl(file, func, line, fchan, usrmsg); - if (status != FTDM_SUCCESS) { - _ftdm_channel_call_hangup_nl(file, func, line, fchan, usrmsg); - goto done; - } - - /* let the user know which channel was picked and which call id was generated */ - caller_data->fchan = fchan; - caller_data->call_id = fchan->caller_data.call_id; -done: - ftdm_channel_unlock(fchan); - - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_set_sig_status(ftdm_channel_t *fchan, ftdm_signaling_status_t sigstatus) -{ - ftdm_status_t res; - - ftdm_assert_return(fchan != NULL, FTDM_FAIL, "Null channel\n"); - ftdm_assert_return(fchan->span != NULL, FTDM_FAIL, "Null span\n"); - ftdm_assert_return(fchan->span->set_channel_sig_status != NULL, FTDM_ENOSYS, "Not implemented\n"); - - ftdm_channel_lock(fchan); - - res = fchan->span->set_channel_sig_status(fchan, sigstatus); - - ftdm_channel_unlock(fchan); - - return res; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_get_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t *sigstatus) -{ - ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel\n"); - ftdm_assert_return(ftdmchan->span != NULL, FTDM_FAIL, "Null span\n"); - ftdm_assert_return(sigstatus != NULL, FTDM_FAIL, "Null sig status parameter\n"); - - if (ftdmchan->span->get_channel_sig_status) { - ftdm_status_t res; - ftdm_channel_lock(ftdmchan); - res = ftdmchan->span->get_channel_sig_status(ftdmchan, sigstatus); - ftdm_channel_unlock(ftdmchan); - return res; - } else { - /* don't log error here, it can be called just to test if its supported */ - return FTDM_NOTIMPL; - } -} - -FT_DECLARE(ftdm_status_t) ftdm_span_set_sig_status(ftdm_span_t *span, ftdm_signaling_status_t sigstatus) -{ - ftdm_assert_return(span != NULL, FTDM_FAIL, "Null span\n"); - - if (sigstatus == FTDM_SIG_STATE_DOWN) { - ftdm_log(FTDM_LOG_WARNING, "The user is not allowed to set the signaling status to DOWN, valid states are UP or SUSPENDED\n"); - return FTDM_FAIL; - } - - if (span->set_span_sig_status) { - return span->set_span_sig_status(span, sigstatus); - } else { - ftdm_log(FTDM_LOG_ERROR, "set_span_sig_status method not implemented!\n"); - return FTDM_FAIL; - } -} - -FT_DECLARE(ftdm_status_t) ftdm_span_get_sig_status(ftdm_span_t *span, ftdm_signaling_status_t *sigstatus) -{ - ftdm_assert_return(span != NULL, FTDM_FAIL, "Null span\n"); - ftdm_assert_return(sigstatus != NULL, FTDM_FAIL, "Null sig status parameter\n"); - - if (span->get_span_sig_status) { - return span->get_span_sig_status(span, sigstatus); - } else { - return FTDM_FAIL; - } -} - -static ftdm_status_t ftdm_channel_sig_indicate(ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication, ftdm_usrmsg_t *usrmsg) -{ - ftdm_status_t status = FTDM_FAIL; - if (ftdmchan->span->indicate) { - - ftdm_channel_save_usrmsg(ftdmchan, usrmsg); - - status = ftdmchan->span->indicate(ftdmchan, indication); - if (status == FTDM_NOTIMPL) { - ftdm_log(FTDM_LOG_WARNING, "Do not know how to indicate %s\n", ftdm_channel_indication2str(indication)); - } else if (status != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_WARNING, "Failed to indicate %s\n", ftdm_channel_indication2str(indication)); - } else { /* SUCCESS */ - ftdm_ack_indication(ftdmchan, indication, FTDM_SUCCESS); - } - ftdm_usrmsg_free(&ftdmchan->usrmsg); - } else { - return FTDM_NOTIMPL; - } - return status; -} - - -/* this function must be called with the channel lock */ -static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan) -{ - ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel can't be done!\n"); - - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OPEN); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_INUSE); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_WINK); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_FLASH); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_HOLD); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_RINGING); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_PROGRESS_DETECT); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_3WAY); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_PROGRESS); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_MEDIA); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_ANSWERED); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_USER_HANGUP); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DIGITAL_MEDIA); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE); - ftdm_mutex_lock(ftdmchan->pre_buffer_mutex); - ftdm_buffer_destroy(&ftdmchan->pre_buffer); - ftdmchan->pre_buffer_size = 0; - ftdm_mutex_unlock(ftdmchan->pre_buffer_mutex); - - if (ftdmchan->hangup_timer) { - ftdm_sched_cancel_timer(globals.timingsched, ftdmchan->hangup_timer); - } - - ftdmchan->init_state = FTDM_CHANNEL_STATE_DOWN; - ftdmchan->state = FTDM_CHANNEL_STATE_DOWN; - ftdmchan->state_status = FTDM_STATE_STATUS_COMPLETED; - - ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_DEBUG_DTMF, NULL); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_INPUT_DUMP, NULL); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_OUTPUT_DUMP, NULL); - - if (FTDM_IS_VOICE_CHANNEL(ftdmchan) && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED)) { - ftdm_sigmsg_t sigmsg; - memset(&sigmsg, 0, sizeof(sigmsg)); - sigmsg.span_id = ftdmchan->span_id; - sigmsg.chan_id = ftdmchan->chan_id; - sigmsg.channel = ftdmchan; - sigmsg.event_id = FTDM_SIGEVENT_RELEASED; - ftdm_span_send_signal(ftdmchan->span, &sigmsg); - ftdm_call_clear_call_id(&ftdmchan->caller_data); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED); - } - - if (ftdmchan->txdrops || ftdmchan->rxdrops) { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "channel dropped data: txdrops = %d, rxdrops = %d\n", - ftdmchan->txdrops, ftdmchan->rxdrops); - } - - memset(&ftdmchan->caller_data, 0, sizeof(ftdmchan->caller_data)); - - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_HOLD); - - memset(ftdmchan->tokens, 0, sizeof(ftdmchan->tokens)); - ftdmchan->token_count = 0; - - ftdm_channel_flush_dtmf(ftdmchan); - - if (ftdmchan->gen_dtmf_buffer) { - ftdm_buffer_zero(ftdmchan->gen_dtmf_buffer); - } - - if (ftdmchan->dtmf_buffer) { - ftdm_buffer_zero(ftdmchan->dtmf_buffer); - } - - if (ftdmchan->digit_buffer) { - ftdm_buffer_zero(ftdmchan->digit_buffer); - } - - if (!ftdmchan->dtmf_on) { - ftdmchan->dtmf_on = FTDM_DEFAULT_DTMF_ON; - } - - if (!ftdmchan->dtmf_off) { - ftdmchan->dtmf_off = FTDM_DEFAULT_DTMF_OFF; - } - - memset(ftdmchan->dtmf_hangup_buf, '\0', ftdmchan->span->dtmf_hangup_len); - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE)) { - ftdmchan->effective_codec = ftdmchan->native_codec; - ftdmchan->packet_len = ftdmchan->native_interval * (ftdmchan->effective_codec == FTDM_CODEC_SLIN ? 16 : 8); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE); - } - - if (ftdmchan->span->sig_release_guard_time_ms) { - ftdmchan->last_release_time = ftdm_current_time_in_ms(); - } - - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "channel done\n"); - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_use(ftdm_channel_t *ftdmchan) -{ - - ftdm_assert(ftdmchan != NULL, "Null channel\n"); - - ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_INUSE); - - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_close(ftdm_channel_t **ftdmchan) -{ - ftdm_channel_t *check; - ftdm_status_t status = FTDM_FAIL; - - ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel double pointer provided!\n"); - ftdm_assert_return(*ftdmchan != NULL, FTDM_FAIL, "null channel pointer provided!\n"); - - check = *ftdmchan; - *ftdmchan = NULL; - - if (ftdm_test_flag(check, FTDM_CHANNEL_CONFIGURED)) { - ftdm_mutex_lock(check->mutex); - if (!ftdm_test_flag(check, FTDM_CHANNEL_OPEN)) { - ftdm_log_chan_msg(check, FTDM_LOG_WARNING, "Channel not opened, proceeding anyway\n"); - } - status = check->fio->close(check); - ftdm_assert(status == FTDM_SUCCESS, "Failed to close channel!\n"); - ftdm_channel_done(check); - *ftdmchan = NULL; - check->ring_count = 0; - ftdm_mutex_unlock(check->mutex); - } - - return status; -} - -static ftdm_status_t ftdmchan_activate_dtmf_buffer(ftdm_channel_t *ftdmchan) -{ - if (!ftdmchan->dtmf_buffer) { - if (ftdm_buffer_create(&ftdmchan->dtmf_buffer, 1024, 3192, 0) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Failed to allocate DTMF Buffer!\n"); - return FTDM_FAIL; - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Created DTMF buffer\n"); - } - } - - - if (!ftdmchan->tone_session.buffer) { - memset(&ftdmchan->tone_session, 0, sizeof(ftdmchan->tone_session)); - teletone_init_session(&ftdmchan->tone_session, 0, NULL, NULL); - } - - ftdmchan->tone_session.rate = ftdmchan->rate; - ftdmchan->tone_session.duration = ftdmchan->dtmf_on * (ftdmchan->tone_session.rate / 1000); - ftdmchan->tone_session.wait = ftdmchan->dtmf_off * (ftdmchan->tone_session.rate / 1000); - ftdmchan->tone_session.volume = -7; - - /* - ftdmchan->tone_session.debug = 1; - ftdmchan->tone_session.debug_stream = stdout; - */ - - return FTDM_SUCCESS; -} - -/* - * ftdmchan_activate_dtmf_buffer to initialize ftdmchan->dtmf_buffer should be called prior to - * calling ftdm_insert_dtmf_pause - */ -static ftdm_status_t ftdm_insert_dtmf_pause(ftdm_channel_t *ftdmchan, ftdm_size_t pausems) -{ - void *data = NULL; - ftdm_size_t datalen = pausems * sizeof(uint16_t); - - data = ftdm_malloc(datalen); - ftdm_assert(data, "Failed to allocate memory\n"); - - memset(data, FTDM_SILENCE_VALUE(ftdmchan), datalen); - - ftdm_buffer_write(ftdmchan->dtmf_buffer, data, datalen); - ftdm_safe_free(data); - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_command_t command, void *obj) -{ - ftdm_status_t status = FTDM_FAIL; - - ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "No channel\n"); - ftdm_assert_return(ftdmchan->fio != NULL, FTDM_FAIL, "No IO attached to channel\n"); - - ftdm_channel_lock(ftdmchan); - - switch (command) { - - case FTDM_COMMAND_ENABLE_CALLERID_DETECT: - { - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_CALLERID)) { - if (ftdm_fsk_demod_init(&ftdmchan->fsk, ftdmchan->rate, ftdmchan->fsk_buf, sizeof(ftdmchan->fsk_buf)) != FTDM_SUCCESS) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno)); - GOTO_STATUS(done, FTDM_FAIL); - } - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT); - GOTO_STATUS(done, FTDM_SUCCESS); - } - } - break; - case FTDM_COMMAND_DISABLE_CALLERID_DETECT: - { - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_CALLERID)) { - ftdm_fsk_demod_destroy(&ftdmchan->fsk); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT); - GOTO_STATUS(done, FTDM_SUCCESS); - } - } - break; - case FTDM_COMMAND_TRACE_INPUT: - { - char *path = FTDM_COMMAND_OBJ_CHAR_P; - if (ftdmchan->fds[FTDM_READ_TRACE_INDEX] > 0) { - close(ftdmchan->fds[FTDM_READ_TRACE_INDEX]); - ftdmchan->fds[FTDM_READ_TRACE_INDEX] = -1; - } - if ((ftdmchan->fds[FTDM_READ_TRACE_INDEX] = open(path, O_WRONLY | O_CREAT | O_TRUNC - | FTDM_O_BINARY, S_IRUSR | S_IWUSR)) > -1) { - ftdm_log(FTDM_LOG_DEBUG, "Tracing channel %u:%u input to [%s]\n", ftdmchan->span_id, ftdmchan->chan_id, path); - GOTO_STATUS(done, FTDM_SUCCESS); - } - - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno)); - GOTO_STATUS(done, FTDM_FAIL); - } - break; - case FTDM_COMMAND_TRACE_OUTPUT: - { - char *path = (char *) obj; - if (ftdmchan->fds[FTDM_WRITE_TRACE_INDEX] > 0) { - close(ftdmchan->fds[FTDM_WRITE_TRACE_INDEX]); - ftdmchan->fds[FTDM_WRITE_TRACE_INDEX] = -1; - } - if ((ftdmchan->fds[FTDM_WRITE_TRACE_INDEX] = open(path, O_WRONLY | O_CREAT | O_TRUNC - | FTDM_O_BINARY, S_IRUSR | S_IWUSR)) > -1) { - ftdm_log(FTDM_LOG_DEBUG, "Tracing channel %u:%u output to [%s]\n", ftdmchan->span_id, ftdmchan->chan_id, path); - GOTO_STATUS(done, FTDM_SUCCESS); - } - - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno)); - GOTO_STATUS(done, FTDM_FAIL); - } - break; - case FTDM_COMMAND_TRACE_END_ALL: - { - if (ftdmchan->fds[FTDM_READ_TRACE_INDEX] > 0) { - close(ftdmchan->fds[FTDM_READ_TRACE_INDEX]); - ftdmchan->fds[FTDM_READ_TRACE_INDEX] = -1; - } - if (ftdmchan->fds[FTDM_WRITE_TRACE_INDEX] > 0) { - close(ftdmchan->fds[FTDM_WRITE_TRACE_INDEX]); - ftdmchan->fds[FTDM_WRITE_TRACE_INDEX] = -1; - } - GOTO_STATUS(done, FTDM_SUCCESS); - } - break; - - /*!< Enable DTMF debugging */ - case FTDM_COMMAND_ENABLE_DEBUG_DTMF: - { - if (ftdmchan->dtmfdbg.enabled) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Cannot enable debug DTMF again\n"); - GOTO_STATUS(done, FTDM_FAIL); - } - if (ftdmchan->rxdump.buffer) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Cannot debug DTMF if Rx dumping is already enabled\n"); - GOTO_STATUS(done, FTDM_FAIL); - } - if (start_chan_io_dump(ftdmchan, &ftdmchan->rxdump, FTDM_IO_DUMP_DEFAULT_BUFF_SIZE) != FTDM_SUCCESS) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to enable rx dump for DTMF debugging\n"); - GOTO_STATUS(done, FTDM_FAIL); - } - ftdmchan->dtmfdbg.enabled = 1; - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Enabled DTMF debugging\n"); - GOTO_STATUS(done, FTDM_SUCCESS); - } - break; - - /*!< Disable DTMF debugging (if not disabled explicitly, it is disabled automatically when calls hangup) */ - case FTDM_COMMAND_DISABLE_DEBUG_DTMF: - { - if (!ftdmchan->dtmfdbg.enabled) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "DTMF debug is already disabled\n"); - GOTO_STATUS(done, FTDM_SUCCESS); - } - if (disable_dtmf_debug(ftdmchan) != FTDM_SUCCESS) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to disable DTMF debug\n"); - GOTO_STATUS(done, FTDM_FAIL); - } - GOTO_STATUS(done, FTDM_SUCCESS); - } - break; - - /*!< Start dumping all input to a circular buffer. The size of the circular buffer can be specified, default used otherwise */ - case FTDM_COMMAND_ENABLE_INPUT_DUMP: - { - ftdm_size_t size = obj ? FTDM_COMMAND_OBJ_SIZE : FTDM_IO_DUMP_DEFAULT_BUFF_SIZE; - if (ftdmchan->rxdump.buffer) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Input dump is already enabled\n"); - GOTO_STATUS(done, FTDM_FAIL); - } - if (start_chan_io_dump(ftdmchan, &ftdmchan->rxdump, size) != FTDM_SUCCESS) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to enable input dump of size %"FTDM_SIZE_FMT"\n", size); - GOTO_STATUS(done, FTDM_FAIL); - } - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Enabled input dump with size %"FTDM_SIZE_FMT"\n", size); - GOTO_STATUS(done, FTDM_SUCCESS); - } - break; - - /*!< Stop dumping all input to a circular buffer. */ - case FTDM_COMMAND_DISABLE_INPUT_DUMP: - { - if (!ftdmchan->rxdump.buffer) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No need to disable input dump\n"); - GOTO_STATUS(done, FTDM_SUCCESS); - } - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Disabled input dump of size %"FTDM_SIZE_FMT"\n", - ftdmchan->rxdump.size); - stop_chan_io_dump(&ftdmchan->rxdump); - GOTO_STATUS(done, FTDM_SUCCESS); - } - break; - - /*!< Start dumping all output to a circular buffer. The size of the circular buffer can be specified, default used otherwise */ - case FTDM_COMMAND_ENABLE_OUTPUT_DUMP: - { - ftdm_size_t size = obj ? FTDM_COMMAND_OBJ_SIZE : FTDM_IO_DUMP_DEFAULT_BUFF_SIZE; - if (ftdmchan->txdump.buffer) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Output dump is already enabled\n"); - GOTO_STATUS(done, FTDM_FAIL); - } - if (start_chan_io_dump(ftdmchan, &ftdmchan->txdump, size) != FTDM_SUCCESS) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to enable output dump of size %"FTDM_SIZE_FMT"\n", size); - GOTO_STATUS(done, FTDM_FAIL); - } - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Enabled output dump with size %"FTDM_SIZE_FMT"\n", size); - GOTO_STATUS(done, FTDM_SUCCESS); - } - break; - - /*!< Stop dumping all output to a circular buffer. */ - case FTDM_COMMAND_DISABLE_OUTPUT_DUMP: - { - if (!ftdmchan->txdump.buffer) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No need to disable output dump\n"); - GOTO_STATUS(done, FTDM_SUCCESS); - } - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Disabled output dump of size %"FTDM_SIZE_FMT"\n", ftdmchan->rxdump.size); - stop_chan_io_dump(&ftdmchan->txdump); - GOTO_STATUS(done, FTDM_SUCCESS); - } - break; - - /*!< Dump the current input circular buffer to the specified FILE* structure */ - case FTDM_COMMAND_DUMP_INPUT: - { - if (!obj) { - GOTO_STATUS(done, FTDM_FAIL); - } - if (!ftdmchan->rxdump.buffer) { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Not dumped input to file %p, input dump is not enabled\n", obj); - GOTO_STATUS(done, FTDM_FAIL); - } - dump_chan_io_to_file(ftdmchan, &ftdmchan->rxdump, obj); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Dumped input of size %"FTDM_SIZE_FMT" to file %p\n", ftdmchan->rxdump.size, obj); - GOTO_STATUS(done, FTDM_SUCCESS); - } - break; - - /*!< Dump the current output circular buffer to the specified FILE* structure */ - case FTDM_COMMAND_DUMP_OUTPUT: - { - if (!obj) { - GOTO_STATUS(done, FTDM_FAIL); - } - if (!ftdmchan->txdump.buffer) { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Not dumped output to file %p, output dump is not enabled\n", obj); - GOTO_STATUS(done, FTDM_FAIL); - } - dump_chan_io_to_file(ftdmchan, &ftdmchan->txdump, obj); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Dumped input of size %"FTDM_SIZE_FMT" to file %p\n", ftdmchan->txdump.size, obj); - GOTO_STATUS(done, FTDM_SUCCESS); - } - break; - - case FTDM_COMMAND_SET_INTERVAL: - { - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_INTERVAL)) { - ftdmchan->effective_interval = FTDM_COMMAND_OBJ_INT; - if (ftdmchan->effective_interval == ftdmchan->native_interval) { - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_BUFFER); - } else { - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_BUFFER); - } - ftdmchan->packet_len = ftdmchan->native_interval * (ftdmchan->effective_codec == FTDM_CODEC_SLIN ? 16 : 8); - GOTO_STATUS(done, FTDM_SUCCESS); - } - } - break; - case FTDM_COMMAND_GET_INTERVAL: - { - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_INTERVAL)) { - FTDM_COMMAND_OBJ_INT = ftdmchan->effective_interval; - GOTO_STATUS(done, FTDM_SUCCESS); - } - } - break; - case FTDM_COMMAND_SET_CODEC: - { - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_CODECS)) { - ftdmchan->effective_codec = FTDM_COMMAND_OBJ_INT; - - if (ftdmchan->effective_codec == ftdmchan->native_codec) { - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE); - } else { - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE); - } - ftdmchan->packet_len = ftdmchan->native_interval * (ftdmchan->effective_codec == FTDM_CODEC_SLIN ? 16 : 8); - GOTO_STATUS(done, FTDM_SUCCESS); - } - } - break; - - case FTDM_COMMAND_SET_NATIVE_CODEC: - { - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_CODECS)) { - ftdmchan->effective_codec = ftdmchan->native_codec; - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE); - ftdmchan->packet_len = ftdmchan->native_interval * (ftdmchan->effective_codec == FTDM_CODEC_SLIN ? 16 : 8); - GOTO_STATUS(done, FTDM_SUCCESS); - } - } - break; - - case FTDM_COMMAND_GET_CODEC: - { - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_CODECS)) { - FTDM_COMMAND_OBJ_INT = ftdmchan->effective_codec; - GOTO_STATUS(done, FTDM_SUCCESS); - } - } - break; - case FTDM_COMMAND_GET_NATIVE_CODEC: - { - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_CODECS)) { - FTDM_COMMAND_OBJ_INT = ftdmchan->native_codec; - GOTO_STATUS(done, FTDM_SUCCESS); - } - } - break; - case FTDM_COMMAND_ENABLE_PROGRESS_DETECT: - { - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_PROGRESS)) { - /* if they don't have thier own, use ours */ - ftdm_channel_clear_detected_tones(ftdmchan); - ftdm_channel_clear_needed_tones(ftdmchan); - teletone_multi_tone_init(&ftdmchan->span->tone_finder[FTDM_TONEMAP_DIAL], &ftdmchan->span->tone_detect_map[FTDM_TONEMAP_DIAL]); - teletone_multi_tone_init(&ftdmchan->span->tone_finder[FTDM_TONEMAP_RING], &ftdmchan->span->tone_detect_map[FTDM_TONEMAP_RING]); - teletone_multi_tone_init(&ftdmchan->span->tone_finder[FTDM_TONEMAP_BUSY], &ftdmchan->span->tone_detect_map[FTDM_TONEMAP_BUSY]); - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS_DETECT); - GOTO_STATUS(done, FTDM_SUCCESS); - } - } - break; - case FTDM_COMMAND_DISABLE_PROGRESS_DETECT: - { - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_PROGRESS)) { - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_PROGRESS_DETECT); - ftdm_channel_clear_detected_tones(ftdmchan); - ftdm_channel_clear_needed_tones(ftdmchan); - GOTO_STATUS(done, FTDM_SUCCESS); - } - } - break; - case FTDM_COMMAND_ENABLE_DTMF_DETECT: - { - /* if they don't have thier own, use ours */ - if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) { - if (FTDM_CHANNEL_SW_DTMF_ALLOWED(ftdmchan)) { - teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate); - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT); - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Enabled software DTMF detector\n"); - GOTO_STATUS(done, FTDM_SUCCESS); - } - } - } - break; - case FTDM_COMMAND_DISABLE_DTMF_DETECT: - { - if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) { - if (FTDM_CHANNEL_SW_DTMF_ALLOWED(ftdmchan)) { - teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Disabled software DTMF detector\n"); - GOTO_STATUS(done, FTDM_SUCCESS); - } - } - } - break; - case FTDM_COMMAND_SET_PRE_BUFFER_SIZE: - { - int val = FTDM_COMMAND_OBJ_INT; - - if (val < 0) { - val = 0; - } - - ftdmchan->pre_buffer_size = val * 8; - - ftdm_mutex_lock(ftdmchan->pre_buffer_mutex); - if (!ftdmchan->pre_buffer_size) { - ftdm_buffer_destroy(&ftdmchan->pre_buffer); - } else if (!ftdmchan->pre_buffer) { - ftdm_buffer_create(&ftdmchan->pre_buffer, 1024, ftdmchan->pre_buffer_size, 0); - } - ftdm_mutex_unlock(ftdmchan->pre_buffer_mutex); - - GOTO_STATUS(done, FTDM_SUCCESS); - - } - break; - case FTDM_COMMAND_GET_DTMF_ON_PERIOD: - { - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_GENERATE)) { - FTDM_COMMAND_OBJ_INT = ftdmchan->dtmf_on; - GOTO_STATUS(done, FTDM_SUCCESS); - } - } - break; - case FTDM_COMMAND_GET_DTMF_OFF_PERIOD: - { - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_GENERATE)) { - FTDM_COMMAND_OBJ_INT = ftdmchan->dtmf_on; - GOTO_STATUS(done, FTDM_SUCCESS); - } - } - break; - case FTDM_COMMAND_SET_DTMF_ON_PERIOD: - { - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_GENERATE)) { - int val = FTDM_COMMAND_OBJ_INT; - if (val > 10 && val < 1000) { - ftdmchan->dtmf_on = val; - GOTO_STATUS(done, FTDM_SUCCESS); - } else { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "invalid value %d range 10-1000", val); - GOTO_STATUS(done, FTDM_FAIL); - } - } - } - break; - case FTDM_COMMAND_SET_DTMF_OFF_PERIOD: - { - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_GENERATE)) { - int val = FTDM_COMMAND_OBJ_INT; - if (val > 10 && val < 1000) { - ftdmchan->dtmf_off = val; - GOTO_STATUS(done, FTDM_SUCCESS); - } else { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "invalid value %d range 10-1000", val); - GOTO_STATUS(done, FTDM_FAIL); - } - } - } - break; - case FTDM_COMMAND_SEND_DTMF: - { - char *digits = FTDM_COMMAND_OBJ_CHAR_P; - if (ftdmchan->span->sig_send_dtmf) { - status = ftdmchan->span->sig_send_dtmf(ftdmchan, digits); - GOTO_STATUS(done, status); - } else if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_GENERATE)) { - - if ((status = ftdmchan_activate_dtmf_buffer(ftdmchan)) != FTDM_SUCCESS) { - GOTO_STATUS(done, status); - } - - ftdm_buffer_write(ftdmchan->gen_dtmf_buffer, digits, strlen(digits)); - - GOTO_STATUS(done, FTDM_SUCCESS); - } - } - break; - - case FTDM_COMMAND_DISABLE_ECHOCANCEL: - { - ftdm_mutex_lock(ftdmchan->pre_buffer_mutex); - ftdm_buffer_destroy(&ftdmchan->pre_buffer); - ftdmchan->pre_buffer_size = 0; - ftdm_mutex_unlock(ftdmchan->pre_buffer_mutex); - } - break; - - case FTDM_COMMAND_SET_RX_GAIN: - { - if (!FTDM_IS_VOICE_CHANNEL(ftdmchan)) { - ftdm_log(FTDM_LOG_ERROR, "Cannot set rx gain in non-voice channel of type: %s\n", ftdm_chan_type2str(ftdmchan->type)); - GOTO_STATUS(done, FTDM_FAIL); - } - ftdmchan->rxgain = FTDM_COMMAND_OBJ_FLOAT; - reset_gain_table(ftdmchan->rxgain_table, ftdmchan->rxgain, ftdmchan->native_codec); - if (ftdmchan->rxgain == 0.0) { - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_USE_RX_GAIN); - } else { - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_USE_RX_GAIN); - } - GOTO_STATUS(done, FTDM_SUCCESS); - } - break; - case FTDM_COMMAND_GET_RX_GAIN: - { - FTDM_COMMAND_OBJ_FLOAT = ftdmchan->rxgain; - GOTO_STATUS(done, FTDM_SUCCESS); - } - break; - case FTDM_COMMAND_SET_TX_GAIN: - { - if (!FTDM_IS_VOICE_CHANNEL(ftdmchan)) { - ftdm_log(FTDM_LOG_ERROR, "Cannot set tx gain in non-voice channel of type: %s\n", ftdm_chan_type2str(ftdmchan->type)); - GOTO_STATUS(done, FTDM_FAIL); - } - ftdmchan->txgain = FTDM_COMMAND_OBJ_FLOAT; - reset_gain_table(ftdmchan->txgain_table, ftdmchan->txgain, ftdmchan->native_codec); - if (ftdmchan->txgain == 0.0) { - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_USE_TX_GAIN); - } else { - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_USE_TX_GAIN); - } - GOTO_STATUS(done, FTDM_SUCCESS); - } - break; - case FTDM_COMMAND_GET_TX_GAIN: - { - FTDM_COMMAND_OBJ_FLOAT = ftdmchan->txgain; - GOTO_STATUS(done, FTDM_SUCCESS); - } - break; - case FTDM_COMMAND_GET_IOSTATS: - { - if (!obj) { - GOTO_STATUS(done, FTDM_EINVAL); - } - memcpy(obj, &ftdmchan->iostats, sizeof(ftdmchan->iostats)); - GOTO_STATUS(done, FTDM_SUCCESS); - } - break; - case FTDM_COMMAND_SWITCH_IOSTATS: - { - ftdm_bool_t enable = *(ftdm_bool_t *)obj; - if (enable) { - ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); - } else { - ftdm_channel_clear_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); - } - GOTO_STATUS(done, FTDM_SUCCESS); - } - break; - default: - break; - } - - if (!ftdmchan->fio->command) { - ftdm_log(FTDM_LOG_ERROR, "no command function defined by the I/O freetdm module!\n"); - GOTO_STATUS(done, FTDM_FAIL); - } - - status = ftdmchan->fio->command(ftdmchan, command, obj); - - if (status == FTDM_NOTIMPL) { - ftdm_log(FTDM_LOG_ERROR, "I/O backend does not support command %d!\n", command); - } - -done: - ftdm_channel_unlock(ftdmchan); - - return status; - -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_wait(ftdm_channel_t *ftdmchan, ftdm_wait_flag_t *flags, int32_t to) -{ - ftdm_status_t status = FTDM_FAIL; - ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel\n"); - ftdm_assert_return(ftdmchan->fio != NULL, FTDM_FAIL, "Null io interface\n"); - ftdm_assert_return(ftdmchan->fio->wait != NULL, FTDM_NOTIMPL, "wait method not implemented\n"); - - status = ftdmchan->fio->wait(ftdmchan, flags, to); - if (status == FTDM_TIMEOUT) { - /* make sure the flags are cleared on timeout */ - *flags = 0; - } - return status; -} - -/*******************************/ -FIO_CODEC_FUNCTION(fio_slin2ulaw) -{ - int16_t sln_buf[512] = {0}, *sln = sln_buf; - uint8_t *lp = data; - uint32_t i; - ftdm_size_t len = *datalen; - - if (max > len) { - max = len; - } - - memcpy(sln, data, max); - - for(i = 0; i < max; i++) { - *lp++ = linear_to_ulaw(*sln++); - } - - *datalen = max / 2; - - return FTDM_SUCCESS; - -} - - -FIO_CODEC_FUNCTION(fio_ulaw2slin) -{ - int16_t *sln = data; - uint8_t law[1024] = {0}, *lp = law; - uint32_t i; - ftdm_size_t len = *datalen; - - if (max > len) { - max = len; - } - - memcpy(law, data, max); - - for(i = 0; i < max; i++) { - *sln++ = ulaw_to_linear(*lp++); - } - - *datalen = max * 2; - - return FTDM_SUCCESS; -} - -FIO_CODEC_FUNCTION(fio_slin2alaw) -{ - int16_t sln_buf[512] = {0}, *sln = sln_buf; - uint8_t *lp = data; - uint32_t i; - ftdm_size_t len = *datalen; - - if (max > len) { - max = len; - } - - memcpy(sln, data, max); - - for(i = 0; i < max; i++) { - *lp++ = linear_to_alaw(*sln++); - } - - *datalen = max / 2; - - return FTDM_SUCCESS; - -} - - -FIO_CODEC_FUNCTION(fio_alaw2slin) -{ - int16_t *sln = data; - uint8_t law[1024] = {0}, *lp = law; - uint32_t i; - ftdm_size_t len = *datalen; - - if (max > len) { - max = len; - } - - memcpy(law, data, max); - - for(i = 0; i < max; i++) { - *sln++ = alaw_to_linear(*lp++); - } - - *datalen = max * 2; - - return FTDM_SUCCESS; -} - -FIO_CODEC_FUNCTION(fio_ulaw2alaw) -{ - ftdm_size_t len = *datalen; - uint32_t i; - uint8_t *lp = data; - - if (max > len) { - max = len; - } - - for(i = 0; i < max; i++) { - *lp = ulaw_to_alaw(*lp); - lp++; - } - - return FTDM_SUCCESS; -} - -FIO_CODEC_FUNCTION(fio_alaw2ulaw) -{ - ftdm_size_t len = *datalen; - uint32_t i; - uint8_t *lp = data; - - if (max > len) { - max = len; - } - - for(i = 0; i < max; i++) { - *lp = alaw_to_ulaw(*lp); - lp++; - } - - return FTDM_SUCCESS; -} - -/******************************/ - -FT_DECLARE(void) ftdm_channel_clear_detected_tones(ftdm_channel_t *ftdmchan) -{ - uint32_t i; - - memset(ftdmchan->detected_tones, 0, sizeof(ftdmchan->detected_tones[0]) * FTDM_TONEMAP_INVALID); - - for (i = 1; i < FTDM_TONEMAP_INVALID; i++) { - ftdmchan->span->tone_finder[i].tone_count = 0; - } -} - -FT_DECLARE(void) ftdm_channel_clear_needed_tones(ftdm_channel_t *ftdmchan) -{ - memset(ftdmchan->needed_tones, 0, sizeof(ftdmchan->needed_tones[0]) * FTDM_TONEMAP_INVALID); -} - -FT_DECLARE(ftdm_size_t) ftdm_channel_dequeue_dtmf(ftdm_channel_t *ftdmchan, char *dtmf, ftdm_size_t len) -{ - ftdm_size_t bytes = 0; - - assert(ftdmchan != NULL); - - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_READY)) { - return 0; - } - - if (ftdmchan->digit_buffer && ftdm_buffer_inuse(ftdmchan->digit_buffer)) { - ftdm_mutex_lock(ftdmchan->mutex); - if ((bytes = ftdm_buffer_read(ftdmchan->digit_buffer, dtmf, len)) > 0) { - *(dtmf + bytes) = '\0'; - } - ftdm_mutex_unlock(ftdmchan->mutex); - } - - return bytes; -} - -FT_DECLARE(void) ftdm_channel_flush_dtmf(ftdm_channel_t *ftdmchan) -{ - if (ftdmchan->digit_buffer && ftdm_buffer_inuse(ftdmchan->digit_buffer)) { - ftdm_mutex_lock(ftdmchan->mutex); - ftdm_buffer_zero(ftdmchan->digit_buffer); - ftdm_mutex_unlock(ftdmchan->mutex); - } -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, const char *dtmf) -{ - ftdm_status_t status; - register ftdm_size_t len, inuse; - ftdm_size_t wr = 0; - const char *p; - - ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "No channel\n"); - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Queuing DTMF %s (debug = %d)\n", dtmf, ftdmchan->dtmfdbg.enabled); - - if (ftdmchan->span->sig_queue_dtmf && (ftdmchan->span->sig_queue_dtmf(ftdmchan, dtmf) == FTDM_BREAK)) { - /* Signalling module wants to absorb this DTMF event */ - return FTDM_SUCCESS; - } - - if (!ftdmchan->dtmfdbg.enabled) { - goto skipdebug; - } - - if (!ftdmchan->dtmfdbg.file) { - struct tm currtime; - time_t currsec; - char dfile[1138]; - - currsec = time(NULL); - -#ifdef WIN32 - _tzset(); - _localtime64_s(&currtime, &currsec); -#else - localtime_r(&currsec, &currtime); -#endif - - if (ftdm_strlen_zero(globals.dtmfdebug_directory)) { - snprintf(dfile, sizeof(dfile), "dtmf-s%dc%d-20%d-%d-%d-%d%d%d.%s", - ftdmchan->span_id, ftdmchan->chan_id, - currtime.tm_year-100, currtime.tm_mon+1, currtime.tm_mday, - currtime.tm_hour, currtime.tm_min, currtime.tm_sec, ftdmchan->native_codec == FTDM_CODEC_ULAW ? "ulaw" : ftdmchan->native_codec == FTDM_CODEC_ALAW ? "alaw" : "sln"); - } else { - snprintf(dfile, sizeof(dfile), "%s/dtmf-s%dc%d-20%d-%d-%d-%d%d%d.%s", - globals.dtmfdebug_directory, - ftdmchan->span_id, ftdmchan->chan_id, - currtime.tm_year-100, currtime.tm_mon+1, currtime.tm_mday, - currtime.tm_hour, currtime.tm_min, currtime.tm_sec, ftdmchan->native_codec == FTDM_CODEC_ULAW ? "ulaw" : ftdmchan->native_codec == FTDM_CODEC_ALAW ? "alaw" : "sln"); - } - ftdmchan->dtmfdbg.file = fopen(dfile, "wb"); - if (!ftdmchan->dtmfdbg.file) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "failed to open debug dtmf file %s\n", dfile); - } else { - ftdmchan->dtmfdbg.closetimeout = DTMF_DEBUG_TIMEOUT; - ftdm_channel_command(ftdmchan, FTDM_COMMAND_DUMP_INPUT, ftdmchan->dtmfdbg.file); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Dumped initial DTMF output to %s\n", dfile); - } - } else { - ftdmchan->dtmfdbg.closetimeout = DTMF_DEBUG_TIMEOUT; - } - -skipdebug: - - if (ftdmchan->pre_buffer) { - ftdm_buffer_zero(ftdmchan->pre_buffer); - } - - ftdm_mutex_lock(ftdmchan->mutex); - - inuse = ftdm_buffer_inuse(ftdmchan->digit_buffer); - len = strlen(dtmf); - - if (len + inuse > ftdm_buffer_len(ftdmchan->digit_buffer)) { - ftdm_buffer_toss(ftdmchan->digit_buffer, strlen(dtmf)); - } - - if (ftdmchan->span->dtmf_hangup_len) { - for (p = dtmf; ftdm_is_dtmf(*p); p++) { - memmove (ftdmchan->dtmf_hangup_buf, ftdmchan->dtmf_hangup_buf + 1, ftdmchan->span->dtmf_hangup_len - 1); - ftdmchan->dtmf_hangup_buf[ftdmchan->span->dtmf_hangup_len - 1] = *p; - if (!strcmp(ftdmchan->dtmf_hangup_buf, ftdmchan->span->dtmf_hangup)) { - ftdm_log(FTDM_LOG_DEBUG, "DTMF hangup detected.\n"); - - ftdm_channel_set_state(__FILE__, __FTDM_FUNC__, __LINE__, ftdmchan, FTDM_CHANNEL_STATE_HANGUP, 0, NULL); - break; - } - } - } - - p = dtmf; - while (wr < len && p) { - if (ftdm_is_dtmf(*p)) { - wr++; - } else { - break; - } - p++; - } - - status = ftdm_buffer_write(ftdmchan->digit_buffer, dtmf, wr) ? FTDM_SUCCESS : FTDM_FAIL; - ftdm_mutex_unlock(ftdmchan->mutex); - - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_raw_write (ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen) -{ - int dlen = (int) *datalen; - - if (ftdm_test_io_flag(ftdmchan, FTDM_CHANNEL_IO_WRITE)) { - ftdm_clear_io_flag(ftdmchan, FTDM_CHANNEL_IO_WRITE); - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TX_DISABLED)) { - ftdmchan->txdrops++; - if (ftdmchan->txdrops <= 10) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "cannot write in channel with tx disabled\n"); - } - if (ftdmchan->txdrops == 10) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Too many tx drops, not printing anymore\n"); - } - return FTDM_FAIL; - } - if (ftdmchan->fds[FTDM_WRITE_TRACE_INDEX] > -1) { - if ((write(ftdmchan->fds[FTDM_WRITE_TRACE_INDEX], data, dlen)) != dlen) { - ftdm_log(FTDM_LOG_WARNING, "Raw output trace failed to write all of the %d bytes\n", dlen); - } - } - write_chan_io_dump(&ftdmchan->txdump, data, dlen); - return ftdmchan->fio->write(ftdmchan, data, datalen); -} - -FT_DECLARE(ftdm_status_t) ftdm_raw_read (ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen) -{ - ftdm_status_t status; - - if (ftdm_test_io_flag(ftdmchan, FTDM_CHANNEL_IO_READ)) { - ftdm_clear_io_flag(ftdmchan, FTDM_CHANNEL_IO_READ); - } - status = ftdmchan->fio->read(ftdmchan, data, datalen); - - if (status == FTDM_SUCCESS && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_USE_RX_GAIN) - && (ftdmchan->native_codec == FTDM_CODEC_ALAW || ftdmchan->native_codec == FTDM_CODEC_ULAW)) { - ftdm_size_t i = 0; - unsigned char *rdata = data; - for (i = 0; i < *datalen; i++) { - rdata[i] = ftdmchan->rxgain_table[rdata[i]]; - } - } - - if (status == FTDM_SUCCESS && ftdmchan->fds[FTDM_READ_TRACE_INDEX] > -1) { - ftdm_size_t dlen = *datalen; - if ((ftdm_size_t)write(ftdmchan->fds[FTDM_READ_TRACE_INDEX], data, (int)dlen) != dlen) { - ftdm_log(FTDM_LOG_WARNING, "Raw input trace failed to write all of the %"FTDM_SIZE_FMT" bytes\n", dlen); - } - } - - if (status == FTDM_SUCCESS && ftdmchan->span->sig_read) { - ftdmchan->span->sig_read(ftdmchan, data, *datalen); - } - - if (status == FTDM_SUCCESS) { - ftdm_size_t dlen = *datalen; - ftdm_size_t rc = 0; - - write_chan_io_dump(&ftdmchan->rxdump, data, (int)dlen); - - /* if dtmf debug is enabled and initialized, write there too */ - if (ftdmchan->dtmfdbg.file) { - rc = fwrite(data, 1, dlen, ftdmchan->dtmfdbg.file); - if (rc != dlen) { - ftdm_log(FTDM_LOG_WARNING, "DTMF debugger wrote only %"FTDM_SIZE_FMT" out of %"FTDM_SIZE_FMT" bytes: %s\n", - rc, *datalen, strerror(errno)); - } - ftdmchan->dtmfdbg.closetimeout--; - if (!ftdmchan->dtmfdbg.closetimeout) { - close_dtmf_debug_file(ftdmchan); - } - } - } - return status; -} - -/* This function takes care of automatically generating DTMF or FSK tones when needed */ -static ftdm_status_t handle_tone_generation(ftdm_channel_t *ftdmchan) -{ - /* - * datalen: size in bytes of the chunk of data the user requested to read (this function - * is called from the ftdm_channel_read function) - * dblen: size currently in use in any of the tone generation buffers (data available in the buffer) - * gen_dtmf_buffer: buffer holding the raw ASCII digits that the user requested to generate - * dtmf_buffer: raw linear tone data generated by teletone to be written to the devices - * fsk_buffer: raw linear FSK modulated data for caller id - */ - ftdm_buffer_t *buffer = NULL; - ftdm_size_t dblen = 0; - int wrote = 0; - - if (ftdmchan->gen_dtmf_buffer && (dblen = ftdm_buffer_inuse(ftdmchan->gen_dtmf_buffer))) { - char digits[128] = ""; - char *cur; - int x = 0; - - if (dblen > sizeof(digits) - 1) { - dblen = sizeof(digits) - 1; - } - - if (ftdm_buffer_read(ftdmchan->gen_dtmf_buffer, digits, dblen) && !ftdm_strlen_zero_buf(digits)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generating DTMF [%s]\n", digits); - - cur = digits; - - for (; *cur; cur++) { - if (*cur == 'F') { - ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLASH, NULL); - } else if (*cur == 'w') { - ftdm_insert_dtmf_pause(ftdmchan, FTDM_HALF_DTMF_PAUSE); - } else if (*cur == 'W') { - ftdm_insert_dtmf_pause(ftdmchan, FTDM_FULL_DTMF_PAUSE); - } else { - if ((wrote = teletone_mux_tones(&ftdmchan->tone_session, &ftdmchan->tone_session.TONES[(int)*cur]))) { - ftdm_buffer_write(ftdmchan->dtmf_buffer, ftdmchan->tone_session.buffer, wrote * 2); - x++; - } else { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Problem adding DTMF sequence [%s]\n", digits); - return FTDM_FAIL; - } - } - if (x) { - ftdmchan->skip_read_frames = (wrote / (ftdmchan->effective_interval * 8)) + 4; - } - } - } - } - - if (!ftdmchan->buffer_delay || --ftdmchan->buffer_delay == 0) { - /* time to pick a buffer, either the dtmf or fsk buffer */ - if (ftdmchan->dtmf_buffer && (dblen = ftdm_buffer_inuse(ftdmchan->dtmf_buffer))) { - buffer = ftdmchan->dtmf_buffer; - } else if (ftdmchan->fsk_buffer && (dblen = ftdm_buffer_inuse(ftdmchan->fsk_buffer))) { - buffer = ftdmchan->fsk_buffer; - } - } - - /* if we picked a buffer, time to read from it and write the linear data to the device */ - if (buffer) { - uint8_t auxbuf[1024]; - ftdm_size_t dlen = ftdmchan->packet_len; - ftdm_size_t len, br, max = sizeof(auxbuf); - - /* if the codec is not linear, then data is really twice as much cuz - tone generation is done in linear (we assume anything different than linear is G.711) */ - if (ftdmchan->native_codec != FTDM_CODEC_SLIN) { - dlen *= 2; - } - - /* we do not expect the user chunks to be bigger than auxbuf */ - ftdm_assert((dlen <= sizeof(auxbuf)), "Unexpected size for user data chunk size\n"); - - /* dblen is the size in use for dtmf_buffer or fsk_buffer, and dlen is the size - * of the io chunks to write, we pick the smaller one */ - len = dblen > dlen ? dlen : dblen; - - /* we can't read more than the size of our auxiliary buffer */ - ftdm_assert((len <= sizeof(auxbuf)), "Unexpected size to read into auxbuf\n"); - - br = ftdm_buffer_read(buffer, auxbuf, len); - - /* the amount read can't possibly be bigger than what we requested */ - ftdm_assert((br <= len), "Unexpected size read from tone generation buffer\n"); - - /* if we read less than the chunk size, we must fill in with silence the rest */ - if (br < dlen) { - memset(auxbuf + br, 0, dlen - br); - } - - /* finally we convert to the native format for the channel if necessary */ - if (ftdmchan->native_codec != FTDM_CODEC_SLIN) { - if (ftdmchan->native_codec == FTDM_CODEC_ULAW) { - fio_slin2ulaw(auxbuf, max, &dlen); - } else if (ftdmchan->native_codec == FTDM_CODEC_ALAW) { - fio_slin2alaw(auxbuf, max, &dlen); - } - } - - /* write the tone to the channel */ - return ftdm_raw_write(ftdmchan, auxbuf, &dlen); - } - - return FTDM_SUCCESS; - -} - - -FT_DECLARE(void) ftdm_generate_sln_silence(int16_t *data, uint32_t samples, uint32_t divisor) -{ - int16_t x; - uint32_t i; - int sum_rnd = 0; - int16_t rnd2 = (int16_t) ftdm_current_time_in_ms() * (int16_t) (intptr_t) data; - - assert(divisor); - - for (i = 0; i < samples; i++, sum_rnd = 0) { - for (x = 0; x < 6; x++) { - rnd2 = rnd2 * 31821U + 13849U; - sum_rnd += rnd2 ; - } - //switch_normalize_to_16bit(sum_rnd); - *data = (int16_t) ((int16_t) sum_rnd / (int) divisor); - - data++; - } -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen) -{ - fio_codec_t codec_func = NULL; - ftdm_size_t max = *datalen; - - handle_tone_generation(ftdmchan); - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DIGITAL_MEDIA)) { - goto done; - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE) && ftdmchan->effective_codec != ftdmchan->native_codec) { - if (ftdmchan->native_codec == FTDM_CODEC_ULAW && ftdmchan->effective_codec == FTDM_CODEC_SLIN) { - codec_func = fio_ulaw2slin; - } else if (ftdmchan->native_codec == FTDM_CODEC_ULAW && ftdmchan->effective_codec == FTDM_CODEC_ALAW) { - codec_func = fio_ulaw2alaw; - } else if (ftdmchan->native_codec == FTDM_CODEC_ALAW && ftdmchan->effective_codec == FTDM_CODEC_SLIN) { - codec_func = fio_alaw2slin; - } else if (ftdmchan->native_codec == FTDM_CODEC_ALAW && ftdmchan->effective_codec == FTDM_CODEC_ULAW) { - codec_func = fio_alaw2ulaw; - } - - if (codec_func) { - codec_func(data, max, datalen); - } else { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "codec error!"); - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "no codec function to perform transcoding from %d to %d\n", ftdmchan->native_codec, ftdmchan->effective_codec); - } - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT) || - ftdm_test_flag(ftdmchan, FTDM_CHANNEL_PROGRESS_DETECT) || - ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT)) { - - uint8_t sln_buf[1024] = {0}; - int16_t *sln; - ftdm_size_t slen = 0; - - if (ftdmchan->effective_codec == FTDM_CODEC_SLIN) { - sln = data; - slen = *datalen / 2; - } else { - ftdm_size_t len = *datalen; - uint32_t i; - uint8_t *lp = data; - - slen = sizeof(sln_buf) / 2; - if (len > slen) { - len = slen; - } - - sln = (int16_t *) sln_buf; - for(i = 0; i < len; i++) { - if (ftdmchan->effective_codec == FTDM_CODEC_ULAW) { - *sln++ = ulaw_to_linear(*lp++); - } else if (ftdmchan->effective_codec == FTDM_CODEC_ALAW) { - *sln++ = alaw_to_linear(*lp++); - } else { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "codec error!"); - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "invalid effective codec %d\n", ftdmchan->effective_codec); - goto done; - } - } - sln = (int16_t *) sln_buf; - slen = len; - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT)) { - if (ftdm_fsk_demod_feed(&ftdmchan->fsk, sln, slen) != FTDM_SUCCESS) { - ftdm_size_t type, mlen; - char str[128], *sp; - - while(ftdm_fsk_data_parse(&ftdmchan->fsk, &type, &sp, &mlen) == FTDM_SUCCESS) { - *(str+mlen) = '\0'; - ftdm_copy_string(str, sp, ++mlen); - ftdm_clean_string(str); - - ftdm_log(FTDM_LOG_DEBUG, "FSK: TYPE %s LEN %"FTDM_SIZE_FMT" VAL [%s]\n", - ftdm_mdmf_type2str(type), mlen-1, str); - - switch(type) { - case MDMF_DDN: - case MDMF_PHONE_NUM: - { - if (mlen > sizeof(ftdmchan->caller_data.ani)) { - mlen = sizeof(ftdmchan->caller_data.ani); - } - ftdm_set_string(ftdmchan->caller_data.ani.digits, str); - ftdm_set_string(ftdmchan->caller_data.cid_num.digits, ftdmchan->caller_data.ani.digits); - } - break; - case MDMF_NO_NUM: - { - ftdm_set_string(ftdmchan->caller_data.ani.digits, *str == 'P' ? "private" : "unknown"); - ftdm_set_string(ftdmchan->caller_data.cid_name, ftdmchan->caller_data.ani.digits); - } - break; - case MDMF_PHONE_NAME: - { - if (mlen > sizeof(ftdmchan->caller_data.cid_name)) { - mlen = sizeof(ftdmchan->caller_data.cid_name); - } - ftdm_set_string(ftdmchan->caller_data.cid_name, str); - } - break; - case MDMF_NO_NAME: - { - ftdm_set_string(ftdmchan->caller_data.cid_name, *str == 'P' ? "private" : "unknown"); - } - case MDMF_DATETIME: - { - if (mlen > sizeof(ftdmchan->caller_data.cid_date)) { - mlen = sizeof(ftdmchan->caller_data.cid_date); - } - ftdm_set_string(ftdmchan->caller_data.cid_date, str); - } - break; - } - } - ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_CALLERID_DETECT, NULL); - } - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_PROGRESS_DETECT) && !ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_PROGRESS)) { - uint32_t i; - - for (i = 1; i < FTDM_TONEMAP_INVALID; i++) { - if (ftdmchan->span->tone_finder[i].tone_count) { - if (ftdmchan->needed_tones[i] && teletone_multi_tone_detect(&ftdmchan->span->tone_finder[i], sln, (int)slen)) { - if (++ftdmchan->detected_tones[i]) { - ftdmchan->needed_tones[i] = 0; - ftdmchan->detected_tones[0]++; - } - } - } - } - } - - if (FTDM_CHANNEL_SW_DTMF_ALLOWED(ftdmchan) && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT)) { - teletone_hit_type_t hit; - char digit_char; - uint32_t dur; - - if ((hit = teletone_dtmf_detect(&ftdmchan->dtmf_detect, sln, (int)slen)) == TT_HIT_END) { - teletone_dtmf_get(&ftdmchan->dtmf_detect, &digit_char, &dur); - - if (ftdmchan->state == FTDM_CHANNEL_STATE_CALLWAITING && (digit_char == 'D' || digit_char == 'A')) { - ftdmchan->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK]++; - } else { - char digit_str[2] = { 0 }; - - digit_str[0] = digit_char; - - ftdm_channel_queue_dtmf(ftdmchan, digit_str); - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF)) { - ftdmchan->skip_read_frames = 20; - } - } - } - } - } - - if (ftdmchan->skip_read_frames > 0 || ftdm_test_flag(ftdmchan, FTDM_CHANNEL_MUTE)) { - - ftdm_mutex_lock(ftdmchan->pre_buffer_mutex); - if (ftdmchan->pre_buffer && ftdm_buffer_inuse(ftdmchan->pre_buffer)) { - ftdm_buffer_zero(ftdmchan->pre_buffer); - } - ftdm_mutex_unlock(ftdmchan->pre_buffer_mutex); - - memset(data, FTDM_SILENCE_VALUE(ftdmchan), *datalen); - - if (ftdmchan->skip_read_frames > 0) { - ftdmchan->skip_read_frames--; - } - } else { - ftdm_mutex_lock(ftdmchan->pre_buffer_mutex); - if (ftdmchan->pre_buffer_size && ftdmchan->pre_buffer) { - ftdm_buffer_write(ftdmchan->pre_buffer, data, *datalen); - if (ftdm_buffer_inuse(ftdmchan->pre_buffer) >= ftdmchan->pre_buffer_size) { - ftdm_buffer_read(ftdmchan->pre_buffer, data, *datalen); - } else { - memset(data, FTDM_SILENCE_VALUE(ftdmchan), *datalen); - } - } - ftdm_mutex_unlock(ftdmchan->pre_buffer_mutex); - } - -done: - return FTDM_SUCCESS; -} - - -FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen) -{ - - ftdm_status_t status = FTDM_FAIL; - - ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "ftdmchan is null\n"); - ftdm_assert_return(ftdmchan->fio != NULL, FTDM_FAIL, "No I/O module attached to ftdmchan\n"); - - ftdm_channel_lock(ftdmchan); - - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "cannot read from channel that is not open\n"); - status = FTDM_FAIL; - goto done; - } - - if (!ftdmchan->fio->read) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "read method not implemented\n"); - status = FTDM_FAIL; - goto done; - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED)) { - ftdmchan->rxdrops++; - if (ftdmchan->rxdrops <= 10) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "cannot read from channel with rx disabled\n"); - } - if (ftdmchan->rxdrops == 10) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "too many rx drops, not logging anymore\n"); - } - status = FTDM_FAIL; - goto done; - } - status = ftdm_raw_read(ftdmchan, data, datalen); - if (status != FTDM_SUCCESS) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "raw I/O read filed\n"); - goto done; - } - - status = ftdm_channel_process_media(ftdmchan, data, datalen); - if (status != FTDM_SUCCESS) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to process media\n"); - } -done: - ftdm_channel_unlock(ftdmchan); - return status; -} - - -FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t datasize, ftdm_size_t *datalen) -{ - ftdm_status_t status = FTDM_SUCCESS; - fio_codec_t codec_func = NULL; - ftdm_size_t max = datasize; - unsigned int i = 0; - - ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel on write!\n"); - ftdm_assert_return(ftdmchan->fio != NULL, FTDM_FAIL, "null I/O on write!\n"); - - ftdm_channel_lock(ftdmchan); - - if (!ftdmchan->buffer_delay && - ((ftdmchan->dtmf_buffer && ftdm_buffer_inuse(ftdmchan->dtmf_buffer)) || - (ftdmchan->fsk_buffer && ftdm_buffer_inuse(ftdmchan->fsk_buffer)))) { - /* generating some kind of tone at the moment (see handle_tone_generation), - * we ignore user data ... */ - goto done; - } - - - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "cannot write in channel not open\n"); - status = FTDM_FAIL; - goto done; - } - - if (!ftdmchan->fio->write) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "write method not implemented\n"); - status = FTDM_FAIL; - goto done; - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DIGITAL_MEDIA)) { - goto do_write; - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE) && ftdmchan->effective_codec != ftdmchan->native_codec) { - if (ftdmchan->native_codec == FTDM_CODEC_ULAW && ftdmchan->effective_codec == FTDM_CODEC_SLIN) { - codec_func = fio_slin2ulaw; - } else if (ftdmchan->native_codec == FTDM_CODEC_ULAW && ftdmchan->effective_codec == FTDM_CODEC_ALAW) { - codec_func = fio_alaw2ulaw; - } else if (ftdmchan->native_codec == FTDM_CODEC_ALAW && ftdmchan->effective_codec == FTDM_CODEC_SLIN) { - codec_func = fio_slin2alaw; - } else if (ftdmchan->native_codec == FTDM_CODEC_ALAW && ftdmchan->effective_codec == FTDM_CODEC_ULAW) { - codec_func = fio_ulaw2alaw; - } - - if (codec_func) { - status = codec_func(data, max, datalen); - } else { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Do not know how to handle transcoding from %d to %d\n", - ftdmchan->effective_codec, ftdmchan->native_codec); - status = FTDM_FAIL; - goto done; - } - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_USE_TX_GAIN) - && (ftdmchan->native_codec == FTDM_CODEC_ALAW || ftdmchan->native_codec == FTDM_CODEC_ULAW)) { - unsigned char *wdata = data; - for (i = 0; i < *datalen; i++) { - wdata[i] = ftdmchan->txgain_table[wdata[i]]; - } - } - -do_write: - - if (ftdmchan->span->sig_write) { - status = ftdmchan->span->sig_write(ftdmchan, data, *datalen); - if (status == FTDM_BREAK) { - /* signaling module decided to drop user frame */ - status = FTDM_SUCCESS; - goto done; - } - } - - status = ftdm_raw_write(ftdmchan, data, datalen); - -done: - ftdm_channel_unlock(ftdmchan); - - return status; -} - -FT_DECLARE(ftdm_iterator_t *) ftdm_get_iterator(ftdm_iterator_type_t type, ftdm_iterator_t *iter) -{ - int allocated = 0; - if (iter) { - if (iter->type != type) { - ftdm_log(FTDM_LOG_ERROR, "Cannot switch iterator types\n"); - return NULL; - } - allocated = iter->allocated; - memset(iter, 0, sizeof(*iter)); - iter->type = type; - iter->allocated = allocated; - return iter; - } - - iter = ftdm_calloc(1, sizeof(*iter)); - if (!iter) { - return NULL; - } - iter->type = type; - iter->allocated = 1; - return iter; -} - -FT_DECLARE(ftdm_iterator_t *) ftdm_get_span_iterator(ftdm_iterator_t *iter) -{ - if (!(iter = ftdm_get_iterator(FTDM_ITERATOR_SPANS, iter))) { - return NULL; - } - - iter->pvt.hashiter = hashtable_first(globals.span_hash); - return iter; -} - -FT_DECLARE(ftdm_iterator_t *) ftdm_span_get_chan_iterator(const ftdm_span_t *span, ftdm_iterator_t *iter) -{ - if (!span->chan_count) { - return NULL; - } - if (!(iter = ftdm_get_iterator(FTDM_ITERATOR_CHANS, iter))) { - return NULL; - } - iter->pvt.chaniter.index = 1; - iter->pvt.chaniter.span = span; - return iter; -} - -FT_DECLARE(ftdm_iterator_t *) ftdm_iterator_next(ftdm_iterator_t *iter) -{ - ftdm_assert_return(iter && iter->type, NULL, "Invalid iterator\n"); - - switch (iter->type) { - case FTDM_ITERATOR_VARS: - case FTDM_ITERATOR_SPANS: - if (!iter->pvt.hashiter) { - return NULL; - } - iter->pvt.hashiter = hashtable_next(iter->pvt.hashiter); - if (!iter->pvt.hashiter) { - return NULL; - } - return iter; - case FTDM_ITERATOR_CHANS: - ftdm_assert_return(iter->pvt.chaniter.index, NULL, "channel iterator index cannot be zero!\n"); - if (iter->pvt.chaniter.index == iter->pvt.chaniter.span->chan_count) { - return NULL; - } - iter->pvt.chaniter.index++; - return iter; - default: - break; - } - - ftdm_assert_return(0, NULL, "Unknown iterator type\n"); - return NULL; -} - -FT_DECLARE(void *) ftdm_iterator_current(ftdm_iterator_t *iter) -{ - const void *key = NULL; - void *val = NULL; - - ftdm_assert_return(iter && iter->type, NULL, "Invalid iterator\n"); - - switch (iter->type) { - case FTDM_ITERATOR_VARS: - hashtable_this(iter->pvt.hashiter, &key, NULL, &val); - /* I decided to return the key instead of the value since the value can be retrieved using the key */ - return (void *)key; - case FTDM_ITERATOR_SPANS: - hashtable_this(iter->pvt.hashiter, &key, NULL, &val); - return (void *)val; - case FTDM_ITERATOR_CHANS: - ftdm_assert_return(iter->pvt.chaniter.index, NULL, "channel iterator index cannot be zero!\n"); - ftdm_assert_return(iter->pvt.chaniter.index <= iter->pvt.chaniter.span->chan_count, NULL, "channel iterator index bigger than span chan count!\n"); - return iter->pvt.chaniter.span->channels[iter->pvt.chaniter.index]; - default: - break; - } - - ftdm_assert_return(0, NULL, "Unknown iterator type\n"); - return NULL; -} - -FT_DECLARE(ftdm_status_t) ftdm_iterator_free(ftdm_iterator_t *iter) -{ - /* it's valid to pass a NULL iterator, do not return failure */ - if (!iter) { - return FTDM_SUCCESS; - } - - if (!iter->allocated) { - memset(iter, 0, sizeof(*iter)); - return FTDM_SUCCESS; - } - - ftdm_assert_return(iter->type, FTDM_FAIL, "Cannot free invalid iterator\n"); - ftdm_safe_free(iter); - - return FTDM_SUCCESS; -} - - -static const char *print_neg_char[] = { "", "!" }; -static const char *print_flag_state[] = { "OFF", "ON" }; - -static void print_channels_by_flag(ftdm_stream_handle_t *stream, ftdm_span_t *inspan, uint32_t inchan_id, uint64_t flagval, int not, int *count) -{ - ftdm_bool_t neg = !!not; - const char *negind = print_neg_char[neg]; - const char *flagname; - uint64_t flag = ((uint64_t)1 << flagval); - int mycount = 0; - - flagname = ftdm_val2str(flag, channel_flag_strs, ftdm_array_len(channel_flag_strs), "invalid"); - - ftdm_mutex_lock(globals.mutex); - - if (inspan) { - ftdm_iterator_t *c_iter, *c_cur; - - c_iter = ftdm_span_get_chan_iterator(inspan, NULL); - - for (c_cur = c_iter; c_cur; c_cur = ftdm_iterator_next(c_cur)) { - ftdm_channel_t *fchan; - ftdm_bool_t cond; - - fchan = ftdm_iterator_current(c_cur); - if (inchan_id && inchan_id != fchan->chan_id) { - continue; - } - - cond = !!ftdm_test_flag(fchan, flag); - if (neg ^ cond) { - mycount++; - } - - stream->write_function(stream, "[s%dc%d][%d:%d] flag %s%"FTDM_UINT64_FMT"(%s%s) %s\n", - fchan->span_id, fchan->chan_id, - fchan->physical_span_id, fchan->physical_chan_id, - negind, flagval, negind, flagname, - print_flag_state[cond]); - } - - ftdm_iterator_free(c_iter); - - } else { - ftdm_iterator_t *s_iter, *s_cur; - - s_iter = ftdm_get_span_iterator(NULL); - - for (s_cur = s_iter; s_cur; s_cur = ftdm_iterator_next(s_cur)) { - ftdm_iterator_t *c_iter, *c_cur; - ftdm_span_t *span; - - span = ftdm_iterator_current(s_cur); - if (!span) { - break; - } - - c_iter = ftdm_span_get_chan_iterator(span, NULL); - - for (c_cur = c_iter; c_cur; c_cur = ftdm_iterator_next(c_cur)) { - ftdm_channel_t *fchan; - - fchan = ftdm_iterator_current(c_cur); - - if (neg ^ !!ftdm_test_flag(fchan, flag)) { - stream->write_function(stream, "[s%dc%d][%d:%d] flag %s%"FTDM_UINT64_FMT"(%s%s)\n", - fchan->span_id, fchan->chan_id, - fchan->physical_span_id, fchan->physical_chan_id, - negind, flagval, negind, flagname); - mycount++; - } - } - - ftdm_iterator_free(c_iter); - } - - ftdm_iterator_free(s_iter); - } - - *count = mycount; - ftdm_mutex_unlock(globals.mutex); -} - -static void print_spans_by_flag(ftdm_stream_handle_t *stream, ftdm_span_t *inspan, uint64_t flagval, int not, int *count) -{ - ftdm_bool_t neg = !!not; - const char *negind = print_neg_char[neg]; - const char *flagname; - uint64_t flag = ((uint64_t)1 << flagval); - int mycount = 0; - - flagname = ftdm_val2str(flag, span_flag_strs, ftdm_array_len(span_flag_strs), "invalid"); - - ftdm_mutex_lock(globals.mutex); - - if (inspan) { - ftdm_bool_t cond; - - cond = !!ftdm_test_flag(inspan, flag); - if (neg ^ cond) { - mycount++; - } - - stream->write_function(stream, "[s%d] flag %s%"FTDM_UINT64_FMT"(%s%s) %s\n", - inspan->span_id, negind, flagval, negind, flagname, - print_flag_state[cond]); - } else { - ftdm_iterator_t *s_iter, *s_cur; - - s_iter = ftdm_get_span_iterator(NULL); - - for (s_cur = s_iter; s_cur; s_cur = ftdm_iterator_next(s_cur)) { - ftdm_span_t *span; - - span = ftdm_iterator_current(s_cur); - if (!span) { - break; - } - - if (neg ^ !!ftdm_test_flag(span, flag)) { - stream->write_function(stream, "[s%d] flag %s%"FTDM_UINT64_FMT"(%s%s)\n", - span->span_id, negind, flagval, negind, flagname); - mycount++; - } - } - - ftdm_iterator_free(s_iter); - } - - *count = mycount; - ftdm_mutex_unlock(globals.mutex); -} - -static void print_channels_by_state(ftdm_stream_handle_t *stream, ftdm_channel_state_t state, int not, int *count) -{ - ftdm_iterator_t *s_iter, *s_cur; - ftdm_bool_t neg = !!not; - int mycount = 0; - - s_iter = ftdm_get_span_iterator(NULL); - - ftdm_mutex_lock(globals.mutex); - - for (s_cur = s_iter; s_cur; s_cur = ftdm_iterator_next(s_cur)) { - ftdm_iterator_t *c_iter, *c_cur; - ftdm_span_t *span; - - span = ftdm_iterator_current(s_cur); - if (!span) { - break; - } - - c_iter = ftdm_span_get_chan_iterator(span, NULL); - - for (c_cur = c_iter ; c_cur; c_cur = ftdm_iterator_next(c_cur)) { - ftdm_channel_t *fchan = ftdm_iterator_current(c_cur); - - if (neg ^ (fchan->state == state)) { - stream->write_function(stream, "[s%dc%d][%d:%d] in state %s\n", - fchan->span_id, fchan->chan_id, - fchan->physical_span_id, fchan->physical_chan_id, ftdm_channel_state2str(fchan->state)); - mycount++; - } - } - - ftdm_iterator_free(c_iter); - } - - *count = mycount; - ftdm_mutex_unlock(globals.mutex); - - ftdm_iterator_free(s_iter); -} - -static void print_core_usage(ftdm_stream_handle_t *stream) -{ - stream->write_function(stream, - "--------------------------------------------------------------------------------\n" - "ftdm core state [!] - List all channels in or not in the given state\n" - "ftdm core flag [!] [] [] - List all channels with the given flag value set\n" - "ftdm core spanflag [!] [] - List all spans with the given span flag value set\n" - "ftdm core calls - List all known calls to the FreeTDM core\n" - "--------------------------------------------------------------------------------\n"); -} - - -static unsigned long long ftdm_str2val(const char *str, val_str_t *val_str_table, ftdm_size_t array_size, unsigned long long default_val) -{ - ftdm_size_t i; - for (i = 0; i < array_size; i++) { - if (!strcasecmp(val_str_table[i].str, str)) { - return val_str_table[i].val; - } - } - return default_val; -} - -static const char *ftdm_val2str(unsigned long long val, val_str_t *val_str_table, ftdm_size_t array_size, const char *default_str) -{ - ftdm_size_t i; - for (i = 0; i < array_size; i++) { - if (val_str_table[i].val == val) { - return val_str_table[i].str; - } - } - return default_str; -} - -static void print_channel_flag_values(ftdm_stream_handle_t *stream) -{ - int i; - for (i = 0; i < ftdm_array_len(channel_flag_strs); i++) { - stream->write_function(stream, "%s\n", channel_flag_strs[i].str); - } -} - -static void print_span_flag_values(ftdm_stream_handle_t *stream) -{ - int i; - for (i = 0; i < ftdm_array_len(span_flag_strs); i++) { - stream->write_function(stream, "%s\n", span_flag_strs[i].str); - } -} - -/** - * Compute log2 of 64bit integer v - * - * Bit Twiddling Hacks - * http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog - */ -static int ftdm_log2_64(uint64_t v) -{ - unsigned int shift; - uint64_t r; - - r = (v > 0xFFFFFFFF) << 5; v >>= r; - shift = (v > 0xFFFF ) << 4; v >>= shift; r |= shift; - shift = (v > 0xFF ) << 3; v >>= shift; r |= shift; - shift = (v > 0xF ) << 2; v >>= shift; r |= shift; - shift = (v > 0x3 ) << 1; v >>= shift; r |= shift; - - return ((int)(r | (v >> 1))); -} - -static char *handle_core_command(const char *cmd) -{ - char *mycmd = NULL; - int argc = 0; - int count = 0; - int not = 0; - char *argv[10] = { 0 }; - char *flag = NULL; - uint64_t flagval = 0; - ftdm_channel_t *fchan = NULL; - ftdm_span_t *fspan = NULL; - ftdm_stream_handle_t stream = { 0 }; - - FTDM_STANDARD_STREAM(stream); - - if (!ftdm_strlen_zero(cmd)) { - mycmd = ftdm_strdup(cmd); - argc = ftdm_separate_string(mycmd, ' ', argv, ftdm_array_len(argv)); - } else { - print_core_usage(&stream); - goto done; - } - - if (!argc) { - print_core_usage(&stream); - goto done; - } - - if (!strcasecmp(argv[0], "state")) { - ftdm_channel_state_t st = FTDM_CHANNEL_STATE_INVALID; - char *state = NULL; - - if (argc < 2) { - stream.write_function(&stream, "core state command requires an argument\n"); - print_core_usage(&stream); - goto done; - } - - state = argv[1]; - if (state[0] == '!') { - not = 1; - state++; - } - - for (st = FTDM_CHANNEL_STATE_DOWN; st < FTDM_CHANNEL_STATE_INVALID; st++) { - if (!strcasecmp(state, ftdm_channel_state2str(st))) { - break; - } - } - if (st == FTDM_CHANNEL_STATE_INVALID) { - stream.write_function(&stream, "invalid state %s\n", state); - goto done; - } - print_channels_by_state(&stream, st, not, &count); - stream.write_function(&stream, "\nTotal channels %s state %s: %d\n", - not ? "not in" : "in", ftdm_channel_state2str(st), count); - } else if (!strcasecmp(argv[0], "flag")) { - uint32_t chan_id = 0; - - if (argc < 2) { - stream.write_function(&stream, "core flag command requires an argument\n"); - print_core_usage(&stream); - goto done; - } - - flag = argv[1]; - if (flag[0] == '!') { - not = 1; - flag++; - } - - if (isalpha(flag[0])) { - flagval = ftdm_str2val(flag, channel_flag_strs, ftdm_array_len(channel_flag_strs), FTDM_CHANNEL_MAX_FLAG); - if (flagval == FTDM_CHANNEL_MAX_FLAG) { - stream.write_function(&stream, "\nInvalid channel flag value. Possible channel flags:\n"); - print_channel_flag_values(&stream); - goto done; - } - flagval = ftdm_log2_64(flagval); - } else { - flagval = atoi(flag); - } - - /* Specific span specified */ - if (argv[2]) { - ftdm_span_find_by_name(argv[2], &fspan); - if (!fspan) { - stream.write_function(&stream, "-ERR span:%s not found\n", argv[2]); - goto done; - } - } - - /* Specific channel specified */ - if (argv[3]) { - chan_id = atoi(argv[3]); - if (chan_id == 0 || chan_id >= ftdm_span_get_chan_count(fspan)) { - stream.write_function(&stream, "-ERR invalid channel %u\n", chan_id); - goto done; - } - } - - print_channels_by_flag(&stream, fspan, chan_id, flagval, not, &count); - stream.write_function(&stream, "\nTotal channels %s flag %"FTDM_UINT64_FMT": %d\n", not ? "without" : "with", flagval, count); - } else if (!strcasecmp(argv[0], "spanflag")) { - if (argc < 2) { - stream.write_function(&stream, "core spanflag command requires an argument\n"); - print_core_usage(&stream); - goto done; - } - - flag = argv[1]; - if (flag[0] == '!') { - not = 1; - flag++; - } - - if (isalpha(flag[0])) { - flagval = ftdm_str2val(flag, span_flag_strs, ftdm_array_len(span_flag_strs), FTDM_SPAN_MAX_FLAG); - if (flagval == FTDM_SPAN_MAX_FLAG) { - stream.write_function(&stream, "\nInvalid span flag value. Possible span flags\n"); - print_span_flag_values(&stream); - goto done; - } - flagval = ftdm_log2_64(flagval); - } else { - flagval = atoi(flag); - } - - /* Specific span specified */ - if (argv[2]) { - ftdm_span_find_by_name(argv[2], &fspan); - if (!fspan) { - stream.write_function(&stream, "-ERR span:%s not found\n", argv[2]); - goto done; - } - } - - print_spans_by_flag(&stream, fspan, flagval, not, &count); - if (!fspan) { - stream.write_function(&stream, "\nTotal spans %s flag %"FTDM_UINT64_FMT": %d\n", not ? "without" : "with", flagval, count); - } - } else if (!strcasecmp(argv[0], "calls")) { - uint32_t current_call_id = 0; - - ftdm_mutex_lock(globals.call_id_mutex); - for (current_call_id = 0; current_call_id <= MAX_CALLIDS; current_call_id++) { - ftdm_caller_data_t *calldata = NULL; - - if (!globals.call_ids[current_call_id]) { - continue; - } - - calldata = globals.call_ids[current_call_id]; - fchan = calldata->fchan; - if (fchan) { - stream.write_function(&stream, "Call %u on channel %d:%d\n", current_call_id, - fchan->span_id, fchan->chan_id); - } else { - stream.write_function(&stream, "Call %u without a channel?\n", current_call_id); - } - count++; - } - ftdm_mutex_unlock(globals.call_id_mutex); - stream.write_function(&stream, "\nTotal calls: %d\n", count); - } else { - stream.write_function(&stream, "invalid core command %s\n", argv[0]); - print_core_usage(&stream); - } - -done: - ftdm_safe_free(mycmd); - - return stream.data; -} - -FT_DECLARE(char *) ftdm_api_execute(const char *cmd) -{ - ftdm_io_interface_t *fio = NULL; - char *dup = NULL, *p; - char *rval = NULL; - char *type = NULL; - - dup = ftdm_strdup(cmd); - if ((p = strchr(dup, ' '))) { - *p++ = '\0'; - cmd = p; - } else { - cmd = ""; - } - - type = dup; - - if (!strcasecmp(type, "core")) { - return handle_core_command(cmd); - } - - fio = ftdm_global_get_io_interface(type, FTDM_TRUE); - if (fio && fio->api) { - ftdm_stream_handle_t stream = { 0 }; - ftdm_status_t status; - FTDM_STANDARD_STREAM(stream); - - status = fio->api(&stream, cmd); - if (status != FTDM_SUCCESS) { - ftdm_safe_free(stream.data); - } else { - rval = (char *) stream.data; - } - } - - ftdm_safe_free(dup); - - return rval; -} - -static ftdm_status_t ftdm_set_channels_gains(ftdm_span_t *span, int currindex, float rxgain, float txgain) -{ - unsigned chan_index = 0; - - if (!span->chan_count) { - ftdm_log(FTDM_LOG_ERROR, "Failed to set channel gains because span %s has no channels\n", span->name); - return FTDM_FAIL; - } - - for (chan_index = currindex+1; chan_index <= span->chan_count; chan_index++) { - if (!FTDM_IS_VOICE_CHANNEL(span->channels[chan_index])) { - continue; - } - if (ftdm_channel_command(span->channels[chan_index], FTDM_COMMAND_SET_RX_GAIN, &rxgain) != FTDM_SUCCESS) { - return FTDM_FAIL; - } - if (ftdm_channel_command(span->channels[chan_index], FTDM_COMMAND_SET_TX_GAIN, &txgain) != FTDM_SUCCESS) { - return FTDM_FAIL; - } - } - return FTDM_SUCCESS; -} - -static ftdm_status_t ftdm_report_initial_channels_alarms(ftdm_span_t *span) -{ - ftdm_channel_t *fchan = NULL; - ftdm_iterator_t *curr = NULL; - ftdm_status_t status = FTDM_SUCCESS; - ftdm_alarm_flag_t alarmbits; - ftdm_event_t fake_event; - ftdm_iterator_t *citer = ftdm_span_get_chan_iterator(span, NULL); - - if (!citer) { - status = FTDM_ENOMEM; - goto done; - } - - memset(&fake_event, 0, sizeof(fake_event)); - fake_event.e_type = FTDM_EVENT_OOB; - - for (curr = citer; curr; curr = ftdm_iterator_next(curr)) { - fchan = ftdm_iterator_current(curr); - status = ftdm_channel_get_alarms(fchan, &alarmbits); - if (status != FTDM_SUCCESS) { - ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Failed to initialize alarms\n"); - continue; - } - fake_event.channel = fchan; - fake_event.enum_id = fchan->alarm_flags ? FTDM_OOB_ALARM_TRAP : FTDM_OOB_ALARM_CLEAR; - ftdm_event_handle_oob(&fake_event); - } - -done: - - ftdm_iterator_free(citer); - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_configure_span_channels(ftdm_span_t *span, const char* str, ftdm_channel_config_t *chan_config, unsigned *configured) -{ - int currindex; - unsigned chan_index = 0; - - ftdm_assert_return(span != NULL, FTDM_EINVAL, "span is null\n"); - ftdm_assert_return(chan_config != NULL, FTDM_EINVAL, "config is null\n"); - ftdm_assert_return(configured != NULL, FTDM_EINVAL, "configured pointer is null\n"); - ftdm_assert_return(span->fio != NULL, FTDM_EINVAL, "span with no I/O configured\n"); - ftdm_assert_return(span->fio->configure_span != NULL, FTDM_NOTIMPL, "span I/O with no channel configuration implemented\n"); - - currindex = span->chan_count; - *configured = 0; - *configured = span->fio->configure_span(span, str, chan_config->type, chan_config->name, chan_config->number); - if (!*configured) { - ftdm_log(FTDM_LOG_ERROR, "%d:Failed to configure span\n", span->span_id); - return FTDM_FAIL; - } - - if (chan_config->group_name[0]) { - if (ftdm_group_add_channels(span, currindex, chan_config->group_name) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "%d:Failed to add channels to group %s\n", span->span_id, chan_config->group_name); - return FTDM_FAIL; - } - } - - if (ftdm_set_channels_gains(span, currindex, chan_config->rxgain, chan_config->txgain) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "%d:Failed to set channel gains\n", span->span_id); - return FTDM_FAIL; - } - - for (chan_index = currindex + 1; chan_index <= span->chan_count; chan_index++) { - if (chan_config->iostats) { - ftdm_channel_set_feature(span->channels[chan_index], FTDM_CHANNEL_FEATURE_IO_STATS); - } - - if (!FTDM_IS_VOICE_CHANNEL(span->channels[chan_index])) { - continue; - } - - if (chan_config->debugdtmf) { - span->channels[chan_index]->dtmfdbg.requested = 1; - } - - span->channels[chan_index]->dtmfdetect.duration_ms = chan_config->dtmfdetect_ms; - if (chan_config->dtmf_on_start) { - span->channels[chan_index]->dtmfdetect.trigger_on_start = 1; - } - if (chan_config->dtmf_time_on) { - ftdm_channel_command(span->channels[chan_index], FTDM_COMMAND_SET_DTMF_ON_PERIOD, &chan_config->dtmf_time_on); - } - if (chan_config->dtmf_time_off) { - ftdm_channel_command(span->channels[chan_index], FTDM_COMMAND_SET_DTMF_OFF_PERIOD, &chan_config->dtmf_time_off); - } - } - - return FTDM_SUCCESS; -} - - -static ftdm_status_t load_config(void) -{ - const char cfg_name[] = "freetdm.conf"; - ftdm_config_t cfg; - char *var, *val; - int catno = -1; - int intparam = 0; - ftdm_span_t *span = NULL; - unsigned configured = 0, d = 0; - ftdm_analog_start_type_t tmp; - ftdm_size_t len = 0; - ftdm_channel_config_t chan_config; - ftdm_status_t ret = FTDM_SUCCESS; - - memset(&chan_config, 0, sizeof(chan_config)); - sprintf(chan_config.group_name, "__default"); - - if (!ftdm_config_open_file(&cfg, cfg_name)) { - ftdm_log(FTDM_LOG_ERROR, "Failed to open configuration file %s\n", cfg_name); - return FTDM_FAIL; - } - - ftdm_log(FTDM_LOG_DEBUG, "Reading FreeTDM configuration file\n"); - - while (ftdm_config_next_pair(&cfg, &var, &val)) { - if (*cfg.category == '#') { - if (cfg.catno != catno) { - ftdm_log(FTDM_LOG_DEBUG, "Skipping %s\n", cfg.category); - catno = cfg.catno; - } - } else if (!strncasecmp(cfg.category, "span", 4)) { - if (cfg.catno != catno) { - char *type = cfg.category + 4; - char *name; - - if (*type == ' ') { - type++; - } - - ftdm_log(FTDM_LOG_DEBUG, "found config for span\n"); - catno = cfg.catno; - - if (ftdm_strlen_zero(type)) { - ftdm_log(FTDM_LOG_CRIT, "failure creating span, no type specified.\n"); - span = NULL; - continue; - } - - if ((name = strchr(type, ' '))) { - *name++ = '\0'; - } - - /* Verify if trunk_type was specified for previous span */ - if (span && span->trunk_type == FTDM_TRUNK_NONE) { - ftdm_log(FTDM_LOG_ERROR, "trunk_type not specified for span %d (%s)\n", span->span_id, span->name); - ret = FTDM_FAIL; - goto done; - } - - if (ftdm_span_create(type, name, &span) == FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_DEBUG, "created span %d (%s) of type %s\n", span->span_id, span->name, type); - d = 0; - /* it is confusing that parameters from one span affect others, so let's clear them */ - memset(&chan_config, 0, sizeof(chan_config)); - sprintf(chan_config.group_name, "__default"); - /* default to storing iostats */ - chan_config.iostats = FTDM_TRUE; - } else { - ftdm_log(FTDM_LOG_CRIT, "failure creating span of type %s\n", type); - span = NULL; - continue; - } - } - - if (!span) { - continue; - } - - ftdm_log(FTDM_LOG_DEBUG, "span %d [%s]=[%s]\n", span->span_id, var, val); - - if (!strcasecmp(var, "trunk_type")) { - ftdm_trunk_type_t trtype = ftdm_str2ftdm_trunk_type(val); - ftdm_span_set_trunk_type(span, trtype); - ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s'\n", ftdm_trunk_type2str(trtype)); - } else if (!strcasecmp(var, "trunk_mode")) { - ftdm_trunk_mode_t trmode = ftdm_str2ftdm_trunk_mode(val); - ftdm_span_set_trunk_mode(span, trmode); - ftdm_log(FTDM_LOG_DEBUG, "setting trunk mode to '%s'\n", ftdm_trunk_mode2str(trmode)); - } else if (!strcasecmp(var, "name")) { - if (!strcasecmp(val, "undef")) { - chan_config.name[0] = '\0'; - } else { - ftdm_copy_string(chan_config.name, val, FTDM_MAX_NAME_STR_SZ); - } - } else if (!strcasecmp(var, "number")) { - if (!strcasecmp(val, "undef")) { - chan_config.number[0] = '\0'; - } else { - ftdm_copy_string(chan_config.number, val, FTDM_MAX_NUMBER_STR_SZ); - } - } else if (!strcasecmp(var, "analog-start-type")) { - if (span->trunk_type == FTDM_TRUNK_FXS || span->trunk_type == FTDM_TRUNK_FXO || span->trunk_type == FTDM_TRUNK_EM) { - if ((tmp = ftdm_str2ftdm_analog_start_type(val)) != FTDM_ANALOG_START_NA) { - span->start_type = tmp; - ftdm_log(FTDM_LOG_DEBUG, "changing start type to '%s'\n", ftdm_analog_start_type2str(span->start_type)); - } - } else { - ftdm_log(FTDM_LOG_ERROR, "This option is only valid on analog trunks!\n"); - } - } else if (!strcasecmp(var, "fxo-channel")) { - if (span->trunk_type == FTDM_TRUNK_NONE) { - span->trunk_type = FTDM_TRUNK_FXO; - span->trunk_mode = FTDM_TRUNK_MODE_CPE; - ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s' start(%s), mode(%s)\n", ftdm_trunk_type2str(span->trunk_type), - ftdm_analog_start_type2str(span->start_type), ftdm_trunk_mode2str(span->trunk_mode)); - } - if (span->trunk_type == FTDM_TRUNK_FXO) { - unsigned chans_configured = 0; - chan_config.type = FTDM_CHAN_TYPE_FXO; - if (ftdm_configure_span_channels(span, val, &chan_config, &chans_configured) == FTDM_SUCCESS) { - configured += chans_configured; - } - } else { - ftdm_log(FTDM_LOG_WARNING, "Cannot add FXO channels to a %s trunk!\n", ftdm_trunk_type2str(span->trunk_type)); - } - } else if (!strcasecmp(var, "fxs-channel")) { - if (span->trunk_type == FTDM_TRUNK_NONE) { - span->trunk_type = FTDM_TRUNK_FXS; - span->trunk_mode = FTDM_TRUNK_MODE_NET; - ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s' start(%s), mode(%s)\n", ftdm_trunk_type2str(span->trunk_type), - ftdm_analog_start_type2str(span->start_type), ftdm_trunk_mode2str(span->trunk_mode)); - } - if (span->trunk_type == FTDM_TRUNK_FXS) { - unsigned chans_configured = 0; - chan_config.type = FTDM_CHAN_TYPE_FXS; - if (ftdm_configure_span_channels(span, val, &chan_config, &chans_configured) == FTDM_SUCCESS) { - configured += chans_configured; - } - } else { - ftdm_log(FTDM_LOG_WARNING, "Cannot add FXS channels to a %s trunk!\n", ftdm_trunk_type2str(span->trunk_type)); - } - } else if (!strcasecmp(var, "em-channel")) { - if (span->trunk_type == FTDM_TRUNK_NONE) { - span->trunk_type = FTDM_TRUNK_EM; - span->trunk_mode = FTDM_TRUNK_MODE_CPE; - ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s' start(%s), mode(%s)\n", ftdm_trunk_type2str(span->trunk_type), - ftdm_analog_start_type2str(span->start_type), ftdm_trunk_mode2str(span->trunk_mode)); - } - if (span->trunk_type == FTDM_TRUNK_EM) { - unsigned chans_configured = 0; - chan_config.type = FTDM_CHAN_TYPE_EM; - if (ftdm_configure_span_channels(span, val, &chan_config, &chans_configured) == FTDM_SUCCESS) { - configured += chans_configured; - } - } else { - ftdm_log(FTDM_LOG_WARNING, "Cannot add EM channels to a %s trunk!\n", ftdm_trunk_type2str(span->trunk_type)); - } - } else if (!strcasecmp(var, "b-channel")) { - if (span->trunk_type == FTDM_TRUNK_NONE) { - ftdm_log(FTDM_LOG_ERROR, "No trunk type specified in configuration file\n"); - break; - } - if (FTDM_SPAN_IS_DIGITAL(span)) { - unsigned chans_configured = 0; - chan_config.type = FTDM_CHAN_TYPE_B; - if (ftdm_configure_span_channels(span, val, &chan_config, &chans_configured) == FTDM_SUCCESS) { - configured += chans_configured; - } - } else { - ftdm_log(FTDM_LOG_WARNING, "Cannot add B channels to a %s trunk!\n", ftdm_trunk_type2str(span->trunk_type)); - } - } else if (!strcasecmp(var, "d-channel")) { - if (span->trunk_type == FTDM_TRUNK_NONE) { - ftdm_log(FTDM_LOG_ERROR, "No trunk type specified in configuration file\n"); - break; - } - if (FTDM_SPAN_IS_DIGITAL(span)) { - unsigned chans_configured = 0; - if (d) { - ftdm_log(FTDM_LOG_WARNING, "ignoring extra d-channel\n"); - continue; - } - if (!strncasecmp(val, "lapd:", 5)) { - chan_config.type = FTDM_CHAN_TYPE_DQ931; - val += 5; - } else { - chan_config.type = FTDM_CHAN_TYPE_DQ921; - } - if (ftdm_configure_span_channels(span, val, &chan_config, &chans_configured) == FTDM_SUCCESS) { - configured += chans_configured; - } - d++; - } else { - ftdm_log(FTDM_LOG_WARNING, "Cannot add D channels to a %s trunk!\n", ftdm_trunk_type2str(span->trunk_type)); - } - } else if (!strcasecmp(var, "cas-channel")) { - unsigned chans_configured = 0; - chan_config.type = FTDM_CHAN_TYPE_CAS; - if (ftdm_configure_span_channels(span, val, &chan_config, &chans_configured) == FTDM_SUCCESS) { - configured += chans_configured; - } - } else if (!strcasecmp(var, "dtmf_hangup")) { - span->dtmf_hangup = ftdm_strdup(val); - span->dtmf_hangup_len = strlen(val); - } else if (!strcasecmp(var, "txgain")) { - if (sscanf(val, "%f", &(chan_config.txgain)) != 1) { - ftdm_log(FTDM_LOG_ERROR, "invalid txgain: '%s'\n", val); - } - } else if (!strcasecmp(var, "rxgain")) { - if (sscanf(val, "%f", &(chan_config.rxgain)) != 1) { - ftdm_log(FTDM_LOG_ERROR, "invalid rxgain: '%s'\n", val); - } - } else if (!strcasecmp(var, "debugdtmf")) { - chan_config.debugdtmf = ftdm_true(val); - ftdm_log(FTDM_LOG_DEBUG, "Setting debugdtmf to '%s'\n", chan_config.debugdtmf ? "yes" : "no"); - } else if (!strncasecmp(var, "dtmfdetect_ms", sizeof("dtmfdetect_ms")-1)) { - if (chan_config.dtmf_on_start == FTDM_TRUE) { - chan_config.dtmf_on_start = FTDM_FALSE; - ftdm_log(FTDM_LOG_WARNING, "dtmf_on_start parameter disabled because dtmfdetect_ms specified\n"); - } - if (sscanf(val, "%d", &(chan_config.dtmfdetect_ms)) != 1) { - ftdm_log(FTDM_LOG_ERROR, "invalid dtmfdetect_ms: '%s'\n", val); - } - } else if (!strncasecmp(var, "dtmf_on_start", sizeof("dtmf_on_start")-1)) { - if (chan_config.dtmfdetect_ms) { - ftdm_log(FTDM_LOG_WARNING, "dtmf_on_start parameter ignored because dtmf_detect_ms specified\n"); - } else { - if (ftdm_true(val)) { - chan_config.dtmf_on_start = FTDM_TRUE; - } else { - chan_config.dtmf_on_start = FTDM_FALSE; - } - } - } else if (!strcasecmp(var, "dtmf_time_on")) { - if (sscanf(val, "%u", &(chan_config.dtmf_time_on)) != 1) { - ftdm_log(FTDM_LOG_ERROR, "invalid dtmf_time_on: '%s'\n", val); - } - } else if (!strcasecmp(var, "dtmf_time_off")) { - if (sscanf(val, "%u", &(chan_config.dtmf_time_off)) != 1) { - ftdm_log(FTDM_LOG_ERROR, "invalid dtmf_time_off: '%s'\n", val); - } - } else if (!strncasecmp(var, "iostats", sizeof("iostats")-1)) { - if (ftdm_true(val)) { - chan_config.iostats = FTDM_TRUE; - } else { - chan_config.iostats = FTDM_FALSE; - } - ftdm_log(FTDM_LOG_DEBUG, "Setting iostats to '%s'\n", chan_config.iostats ? "yes" : "no"); - } else if (!strcasecmp(var, "group")) { - len = strlen(val); - if (len >= FTDM_MAX_NAME_STR_SZ) { - len = FTDM_MAX_NAME_STR_SZ - 1; - ftdm_log(FTDM_LOG_WARNING, "Truncating group name %s to %"FTDM_SIZE_FMT" length\n", val, len); - } - memcpy(chan_config.group_name, val, len); - chan_config.group_name[len] = '\0'; - } else { - ftdm_log(FTDM_LOG_ERROR, "unknown span variable '%s'\n", var); - } - } else if (!strncasecmp(cfg.category, "general", 7)) { - if (!strncasecmp(var, "cpu_monitor", sizeof("cpu_monitor")-1)) { - if (!strncasecmp(val, "yes", 3)) { - globals.cpu_monitor.enabled = 1; - if (!globals.cpu_monitor.alarm_action_flags) { - globals.cpu_monitor.alarm_action_flags |= FTDM_CPU_ALARM_ACTION_WARN; - } - } - } else if (!strncasecmp(var, "debugdtmf_directory", sizeof("debugdtmf_directory")-1)) { - ftdm_set_string(globals.dtmfdebug_directory, val); - ftdm_log(FTDM_LOG_DEBUG, "Debug DTMF directory set to '%s'\n", globals.dtmfdebug_directory); - } else if (!strncasecmp(var, "cpu_monitoring_interval", sizeof("cpu_monitoring_interval")-1)) { - if (atoi(val) > 0) { - globals.cpu_monitor.interval = atoi(val); - } else { - ftdm_log(FTDM_LOG_ERROR, "Invalid cpu monitoring interval %s\n", val); - } - } else if (!strncasecmp(var, "cpu_set_alarm_threshold", sizeof("cpu_set_alarm_threshold")-1)) { - intparam = atoi(val); - if (intparam > 0 && intparam < 100) { - globals.cpu_monitor.set_alarm_threshold = (uint8_t)intparam; - } else { - ftdm_log(FTDM_LOG_ERROR, "Invalid cpu alarm set threshold %s\n", val); - } - } else if (!strncasecmp(var, "cpu_reset_alarm_threshold", sizeof("cpu_reset_alarm_threshold")-1) || - !strncasecmp(var, "cpu_clear_alarm_threshold", sizeof("cpu_clear_alarm_threshold")-1)) { - intparam = atoi(val); - if (intparam > 0 && intparam < 100) { - globals.cpu_monitor.clear_alarm_threshold = (uint8_t)intparam; - if (globals.cpu_monitor.clear_alarm_threshold > globals.cpu_monitor.set_alarm_threshold) { - globals.cpu_monitor.clear_alarm_threshold = globals.cpu_monitor.set_alarm_threshold - 10; - ftdm_log(FTDM_LOG_ERROR, "Cpu alarm clear threshold must be lower than set threshold, " - "setting clear threshold to %d\n", globals.cpu_monitor.clear_alarm_threshold); - } - } else { - ftdm_log(FTDM_LOG_ERROR, "Invalid cpu alarm reset threshold %s\n", val); - } - } else if (!strncasecmp(var, "cpu_alarm_action", sizeof("cpu_alarm_action")-1)) { - char* p = val; - do { - if (!strncasecmp(p, "reject", sizeof("reject")-1)) { - globals.cpu_monitor.alarm_action_flags |= FTDM_CPU_ALARM_ACTION_REJECT; - } else if (!strncasecmp(p, "warn", sizeof("warn")-1)) { - globals.cpu_monitor.alarm_action_flags |= FTDM_CPU_ALARM_ACTION_WARN; - } - p = strchr(p, ','); - if (p) { - while(*p++) if (*p != 0x20) break; - } - } while (p); - } - } else { - ftdm_log(FTDM_LOG_ERROR, "unknown param [%s] '%s' / '%s'\n", cfg.category, var, val); - } - } - - /* Verify is trunk_type was specified for the last span */ - if (span && span->trunk_type == FTDM_TRUNK_NONE) { - ftdm_log(FTDM_LOG_ERROR, "trunk_type not specified for span %d (%s)\n", span->span_id, span->name); - ret = FTDM_FAIL; - } - -done: - ftdm_config_close_file(&cfg); - - ftdm_log(FTDM_LOG_INFO, "Configured %u channel(s)\n", configured); - if (!configured) { - ret = FTDM_FAIL; - } - - return ret; -} - -static ftdm_status_t process_module_config(ftdm_io_interface_t *fio) -{ - ftdm_config_t cfg; - char *var, *val; - char filename[256] = ""; - - ftdm_assert_return(fio != NULL, FTDM_FAIL, "fio argument is null\n"); - - snprintf(filename, sizeof(filename), "%s.conf", fio->name); - - if (!fio->configure) { - ftdm_log(FTDM_LOG_DEBUG, "Module %s does not support configuration.\n", fio->name); - return FTDM_FAIL; - } - - if (!ftdm_config_open_file(&cfg, filename)) { - /* This is normal if the user did not provide a configuration for this module */ - ftdm_log(FTDM_LOG_DEBUG, "File %s is not available\n", filename); - return FTDM_FAIL; - } - - while (ftdm_config_next_pair(&cfg, &var, &val)) { - fio->configure(cfg.category, var, val, cfg.lineno); - } - - ftdm_config_close_file(&cfg); - - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_global_add_io_interface(ftdm_io_interface_t *interface1) -{ - ftdm_status_t ret = FTDM_SUCCESS; - ftdm_mutex_lock(globals.mutex); - if (hashtable_search(globals.interface_hash, (void *)interface1->name)) { - ftdm_log(FTDM_LOG_ERROR, "Interface %s already loaded!\n", interface1->name); - } else { - hashtable_insert(globals.interface_hash, (void *)interface1->name, interface1, HASHTABLE_FLAG_NONE); - } - ftdm_mutex_unlock(globals.mutex); - return ret; -} - -FT_DECLARE(ftdm_io_interface_t *) ftdm_global_get_io_interface(const char *iotype, ftdm_bool_t autoload) -{ - ftdm_io_interface_t *fio = NULL; - - ftdm_mutex_lock(globals.mutex); - - fio = (ftdm_io_interface_t *) hashtable_search(globals.interface_hash, (void *)iotype); - if (!fio && autoload) { - ftdm_load_module_assume(iotype); - fio = (ftdm_io_interface_t *) hashtable_search(globals.interface_hash, (void *)iotype); - if (fio) { - ftdm_log(FTDM_LOG_INFO, "Auto-loaded I/O module '%s'\n", iotype); - } - } - - ftdm_mutex_unlock(globals.mutex); - return fio; -} - -FT_DECLARE(int) ftdm_load_module(const char *name) -{ - ftdm_dso_lib_t lib; - int count = 0; - ftdm_bool_t load_proceed = FTDM_TRUE; - char path[512] = ""; - char *err; - ftdm_module_t *mod; - - ftdm_build_dso_path(name, path, sizeof(path)); - - if (!(lib = ftdm_dso_open(path, &err))) { - ftdm_log(FTDM_LOG_ERROR, "Error loading %s [%s]\n", path, err); - ftdm_safe_free(err); - return 0; - } - - if (!(mod = (ftdm_module_t *) ftdm_dso_func_sym(lib, "ftdm_module", &err))) { - ftdm_log(FTDM_LOG_ERROR, "Error loading %s [%s]\n", path, err); - ftdm_safe_free(err); - return 0; - } - - if (mod->io_load) { - ftdm_io_interface_t *interface1 = NULL; /* name conflict w/windows here */ - - if (mod->io_load(&interface1) != FTDM_SUCCESS || !interface1 || !interface1->name) { - ftdm_log(FTDM_LOG_ERROR, "Error loading %s\n", path); - load_proceed = FTDM_FALSE; - } else { - ftdm_log(FTDM_LOG_INFO, "Loading IO from %s [%s]\n", path, interface1->name); - if (ftdm_global_add_io_interface(interface1) == FTDM_SUCCESS) { - process_module_config(interface1); - } - } - } - - if (mod->sig_load) { - if (mod->sig_load() != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error loading %s\n", path); - load_proceed = FTDM_FALSE; - } else { - ftdm_log(FTDM_LOG_INFO, "Loading SIG from %s\n", path); - } - } - - if (load_proceed) { - char *p; - mod->lib = lib; - ftdm_set_string(mod->path, path); - if (mod->name[0] == '\0') { - if (!(p = strrchr(path, *FTDM_PATH_SEPARATOR))) { - p = path; - } - ftdm_set_string(mod->name, p); - } - - ftdm_mutex_lock(globals.mutex); - if (hashtable_search(globals.module_hash, (void *)mod->name)) { - ftdm_log(FTDM_LOG_ERROR, "Module %s already loaded!\n", mod->name); - ftdm_dso_destroy(&lib); - } else { - hashtable_insert(globals.module_hash, (void *)mod->name, mod, HASHTABLE_FLAG_NONE); - count++; - } - ftdm_mutex_unlock(globals.mutex); - } else { - ftdm_log(FTDM_LOG_ERROR, "Errors during module load. Unloading %s\n", path); - ftdm_dso_destroy(&lib); - } - - return count; -} - -FT_DECLARE(int) ftdm_load_module_assume(const char *name) -{ - char buf[256] = ""; - - snprintf(buf, sizeof(buf), "ftmod_%s", name); - return ftdm_load_module(buf); -} - -FT_DECLARE(int) ftdm_load_modules(void) -{ - char cfg_name[] = "modules.conf"; - ftdm_config_t cfg; - char *var, *val; - int count = 0; - - if (!ftdm_config_open_file(&cfg, cfg_name)) { - return FTDM_FAIL; - } - - while (ftdm_config_next_pair(&cfg, &var, &val)) { - if (!strcasecmp(cfg.category, "modules")) { - if (!strcasecmp(var, "load")) { - count += ftdm_load_module(val); - } - } - } - - return count; -} - -FT_DECLARE(ftdm_status_t) ftdm_unload_modules(void) -{ - ftdm_hash_iterator_t *i = NULL; - ftdm_dso_lib_t lib = NULL; - char modpath[256] = { 0 }; - - /* stop signaling interfaces first as signaling depends on I/O and not the other way around */ - for (i = hashtable_first(globals.module_hash); i; i = hashtable_next(i)) { - const void *key = NULL; - void *val = NULL; - ftdm_module_t *mod = NULL; - - hashtable_this(i, &key, NULL, &val); - - if (!key || !val) { - continue; - } - - mod = (ftdm_module_t *) val; - - if (!mod->sig_unload) { - continue; - } - - ftdm_log(FTDM_LOG_INFO, "Unloading signaling interface %s\n", mod->name); - - if (mod->sig_unload() != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error unloading signaling interface %s\n", mod->name); - continue; - } - - ftdm_log(FTDM_LOG_INFO, "Unloaded signaling interface %s\n", mod->name); - } - - /* Now go ahead with I/O interfaces */ - for (i = hashtable_first(globals.module_hash); i; i = hashtable_next(i)) { - const void *key = NULL; - void *val = NULL; - ftdm_module_t *mod = NULL; - - hashtable_this(i, &key, NULL, &val); - - if (!key || !val) { - continue; - } - - mod = (ftdm_module_t *) val; - - if (!mod->io_unload) { - continue; - } - - ftdm_log(FTDM_LOG_INFO, "Unloading I/O interface %s\n", mod->name); - - if (mod->io_unload() != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error unloading I/O interface %s\n", mod->name); - continue; - } - - ftdm_log(FTDM_LOG_INFO, "Unloaded I/O interface %s\n", mod->name); - } - - /* Now unload the actual shared object/dll */ - for (i = hashtable_first(globals.module_hash); i; i = hashtable_next(i)) { - ftdm_module_t *mod = NULL; - const void *key = NULL; - void *val = NULL; - - hashtable_this(i, &key, NULL, &val); - - if (!key || !val) { - continue; - } - - mod = (ftdm_module_t *) val; - - lib = mod->lib; - snprintf(modpath, sizeof(modpath), "%s", mod->path); - ftdm_log(FTDM_LOG_INFO, "Unloading module %s\n", modpath); - ftdm_dso_destroy(&lib); - ftdm_log(FTDM_LOG_INFO, "Unloaded module %s\n", modpath); - } - - return FTDM_SUCCESS; -} - -static ftdm_status_t post_configure_span_channels(ftdm_span_t *span) -{ - unsigned i = 0; - ftdm_status_t status = FTDM_SUCCESS; - ftdm_signaling_status_t sigstatus = FTDM_SIG_STATE_DOWN; - for (i = 1; i <= span->chan_count; i++) { - sigstatus = FTDM_SIG_STATE_DOWN; - ftdm_channel_get_sig_status(span->channels[i], &sigstatus); - if (sigstatus == FTDM_SIG_STATE_UP) { - ftdm_set_flag(span->channels[i], FTDM_CHANNEL_SIG_UP); - } - } - if (ftdm_test_flag(span, FTDM_SPAN_USE_CHAN_QUEUE)) { - status = ftdm_queue_create(&span->pendingchans, SPAN_PENDING_CHANS_QUEUE_SIZE); - } - if (status == FTDM_SUCCESS && ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE)) { - status = ftdm_queue_create(&span->pendingsignals, SPAN_PENDING_SIGNALS_QUEUE_SIZE); - } - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_configure_span(ftdm_span_t *span, const char *type, fio_signal_cb_t sig_cb, ...) -{ - ftdm_module_t *mod = (ftdm_module_t *) hashtable_search(globals.module_hash, (void *)type); - ftdm_status_t status = FTDM_FAIL; - - if (!span->chan_count) { - ftdm_log(FTDM_LOG_WARNING, "Cannot configure signaling on span with no channels\n"); - return FTDM_FAIL; - } - - if (!mod) { - ftdm_load_module_assume(type); - if ((mod = (ftdm_module_t *) hashtable_search(globals.module_hash, (void *)type))) { - ftdm_log(FTDM_LOG_INFO, "auto-loaded '%s'\n", type); - } else { - ftdm_log(FTDM_LOG_ERROR, "can't load '%s'\n", type); - return FTDM_FAIL; - } - } - - if (mod->sig_configure) { - va_list ap; - va_start(ap, sig_cb); - status = mod->sig_configure(span, sig_cb, ap); - va_end(ap); - if (status == FTDM_SUCCESS) { - status = post_configure_span_channels(span); - } - } else { - ftdm_log(FTDM_LOG_CRIT, "module '%s' did not implement the sig_configure method\n", type); - status = FTDM_FAIL; - } - - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_configure_span_signaling(ftdm_span_t *span, const char *type, fio_signal_cb_t sig_cb, ftdm_conf_parameter_t *parameters) -{ - ftdm_module_t *mod = (ftdm_module_t *) hashtable_search(globals.module_hash, (void *)type); - ftdm_status_t status = FTDM_FAIL; - - ftdm_assert_return(type != NULL, FTDM_FAIL, "No signaling type"); - ftdm_assert_return(span != NULL, FTDM_FAIL, "No span"); - ftdm_assert_return(sig_cb != NULL, FTDM_FAIL, "No signaling callback"); - ftdm_assert_return(parameters != NULL, FTDM_FAIL, "No parameters"); - - if (!span->chan_count) { - ftdm_log(FTDM_LOG_WARNING, "Cannot configure signaling on span %s with no channels\n", span->name); - return FTDM_FAIL; - } - - if (!mod) { - ftdm_load_module_assume(type); - if ((mod = (ftdm_module_t *) hashtable_search(globals.module_hash, (void *)type))) { - ftdm_log(FTDM_LOG_INFO, "auto-loaded '%s'\n", type); - } - } - - if (!mod) { - ftdm_log(FTDM_LOG_ERROR, "Failed to load module type: %s\n", type); - return FTDM_FAIL; - } - - if (mod->configure_span_signaling) { - status = mod->configure_span_signaling(span, sig_cb, parameters); - if (status == FTDM_SUCCESS) { - status = post_configure_span_channels(span); - } - } else { - ftdm_log(FTDM_LOG_ERROR, "Module %s did not implement the signaling configuration method\n", type); - } - - return status; -} - -static void *ftdm_span_service_events(ftdm_thread_t *me, void *obj) -{ - uint32_t i; - unsigned waitms; - ftdm_event_t *event; - ftdm_status_t status = FTDM_SUCCESS; - ftdm_span_t *span = (ftdm_span_t*) obj; - short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count); - - if (me == 0) {}; - - memset(poll_events, 0, sizeof(short) * span->chan_count); - - for(i = 1; i <= span->chan_count; i++) { - poll_events[i] |= FTDM_EVENTS; - } - - while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) { - waitms = 1000; - status = ftdm_span_poll_event(span, waitms, poll_events); - switch (status) { - case FTDM_FAIL: - ftdm_log(FTDM_LOG_CRIT, "%s:Failed to poll span for events\n", span->name); - break; - case FTDM_TIMEOUT: - break; - case FTDM_SUCCESS: - /* Check if there are any channels that have events available */ - while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS); - break; - default: - ftdm_log(FTDM_LOG_CRIT, "%s:Unhandled IO event\n", span->name); - } - } - return NULL; -} - -FT_DECLARE(ftdm_status_t) ftdm_span_register_signal_cb(ftdm_span_t *span, fio_signal_cb_t sig_cb) -{ - span->signal_cb = sig_cb; - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_span_start(ftdm_span_t *span) -{ - ftdm_status_t status = FTDM_FAIL; - ftdm_mutex_lock(span->mutex); - - if (ftdm_test_flag(span, FTDM_SPAN_STARTED)) { - status = FTDM_EINVAL; - goto done; - } - if (span->signal_type == FTDM_SIGTYPE_NONE) { - /* If there is no signalling component, start a thread to poll events */ - status = ftdm_thread_create_detached(ftdm_span_service_events, span); - if (status != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT,"Failed to start span event monitor thread!\n"); - goto done; - } - - //ftdm_report_initial_channels_alarms(span); - ftdm_set_flag_locked(span, FTDM_SPAN_STARTED); - goto done; - } - - if (!span->start) { - status = FTDM_ENOSYS; - goto done; - } - - /* Start I/O */ - if (span->fio && span->fio->span_start) { - status = span->fio->span_start(span); - if (status != FTDM_SUCCESS) - goto done; - } - - /* Start SIG */ - status = ftdm_report_initial_channels_alarms(span); - if (status != FTDM_SUCCESS) { - goto done; - } - - status = span->start(span); - if (status == FTDM_SUCCESS) { - ftdm_set_flag_locked(span, FTDM_SPAN_STARTED); - } -done: - ftdm_mutex_unlock(span->mutex); - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_add_to_group(const char* name, ftdm_channel_t* ftdmchan) -{ - unsigned int i; - ftdm_group_t* group = NULL; - - ftdm_mutex_lock(globals.group_mutex); - - ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Cannot add a null channel to a group\n"); - - if (ftdm_group_find_by_name(name, &group) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_DEBUG, "Creating new group:%s\n", name); - ftdm_group_create(&group, name); - } - - /*verify that group does not already include this channel first */ - for(i = 0; i < group->chan_count; i++) { - if (group->channels[i]->physical_span_id == ftdmchan->physical_span_id && - group->channels[i]->physical_chan_id == ftdmchan->physical_chan_id) { - - ftdm_mutex_unlock(globals.group_mutex); - ftdm_log(FTDM_LOG_DEBUG, "Channel %d:%d is already added to group %s\n", - group->channels[i]->physical_span_id, - group->channels[i]->physical_chan_id, - name); - return FTDM_SUCCESS; - } - } - - if (group->chan_count >= FTDM_MAX_CHANNELS_GROUP) { - ftdm_log(FTDM_LOG_ERROR, "Max number of channels exceeded (max:%d)\n", FTDM_MAX_CHANNELS_GROUP); - ftdm_mutex_unlock(globals.group_mutex); - return FTDM_FAIL; - } - - group->channels[group->chan_count++] = ftdmchan; - ftdm_mutex_unlock(globals.group_mutex); - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_remove_from_group(ftdm_group_t* group, ftdm_channel_t* ftdmchan) -{ - unsigned int i, j; - //Need to test this function - ftdm_mutex_lock(globals.group_mutex); - - for (i=0; i < group->chan_count; i++) { - if (group->channels[i]->physical_span_id == ftdmchan->physical_span_id && - group->channels[i]->physical_chan_id == ftdmchan->physical_chan_id) { - - j=i; - while(j < group->chan_count-1) { - group->channels[j] = group->channels[j+1]; - j++; - } - group->channels[group->chan_count--] = NULL; - if (group->chan_count <=0) { - /* Delete group if it is empty */ - hashtable_remove(globals.group_hash, (void *)group->name); - } - ftdm_mutex_unlock(globals.group_mutex); - return FTDM_SUCCESS; - } - } - - ftdm_mutex_unlock(globals.group_mutex); - //Group does not contain this channel - return FTDM_FAIL; -} - -static ftdm_status_t ftdm_group_add_channels(ftdm_span_t* span, int currindex, const char* name) -{ - unsigned chan_index = 0; - - ftdm_assert_return(strlen(name) > 0, FTDM_FAIL, "Invalid group name provided\n"); - ftdm_assert_return(currindex >= 0, FTDM_FAIL, "Invalid current channel index provided\n"); - - if (!span->chan_count) { - return FTDM_SUCCESS; - } - - for (chan_index = currindex+1; chan_index <= span->chan_count; chan_index++) { - if (!FTDM_IS_VOICE_CHANNEL(span->channels[chan_index])) { - continue; - } - if (ftdm_channel_add_to_group(name, span->channels[chan_index])) { - ftdm_log(FTDM_LOG_ERROR, "Failed to add chan:%d to group:%s\n", chan_index, name); - } - } - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_group_find(uint32_t id, ftdm_group_t **group) -{ - ftdm_group_t *fgroup = NULL, *grp; - - if (id > FTDM_MAX_GROUPS_INTERFACE) { - return FTDM_FAIL; - } - - - ftdm_mutex_lock(globals.group_mutex); - for (grp = globals.groups; grp; grp = grp->next) { - if (grp->group_id == id) { - fgroup = grp; - break; - } - } - ftdm_mutex_unlock(globals.group_mutex); - - if (!fgroup) { - return FTDM_FAIL; - } - - *group = fgroup; - - return FTDM_SUCCESS; - -} - -FT_DECLARE(ftdm_status_t) ftdm_group_find_by_name(const char *name, ftdm_group_t **group) -{ - ftdm_status_t status = FTDM_FAIL; - *group = NULL; - ftdm_mutex_lock(globals.group_mutex); - if (!ftdm_strlen_zero(name)) { - if ((*group = hashtable_search(globals.group_hash, (void *) name))) { - status = FTDM_SUCCESS; - } - } - ftdm_mutex_unlock(globals.group_mutex); - return status; -} - -static void ftdm_group_add(ftdm_group_t *group) -{ - ftdm_group_t *grp; - ftdm_mutex_lock(globals.group_mutex); - - for (grp = globals.groups; grp && grp->next; grp = grp->next); - - if (grp) { - grp->next = group; - } else { - globals.groups = group; - } - hashtable_insert(globals.group_hash, (void *)group->name, group, HASHTABLE_FLAG_NONE); - - ftdm_mutex_unlock(globals.group_mutex); -} - -FT_DECLARE(ftdm_status_t) ftdm_group_create(ftdm_group_t **group, const char *name) -{ - ftdm_group_t *new_group = NULL; - ftdm_status_t status = FTDM_FAIL; - - ftdm_mutex_lock(globals.mutex); - if (globals.group_index < FTDM_MAX_GROUPS_INTERFACE) { - new_group = ftdm_calloc(1, sizeof(*new_group)); - - ftdm_assert(new_group != NULL, "Failed to create new ftdm group, expect a crash\n"); - - status = ftdm_mutex_create(&new_group->mutex); - - ftdm_assert(status == FTDM_SUCCESS, "Failed to create group mutex, expect a crash\n"); - - new_group->group_id = ++globals.group_index; - new_group->name = ftdm_strdup(name); - ftdm_group_add(new_group); - *group = new_group; - status = FTDM_SUCCESS; - } else { - ftdm_log(FTDM_LOG_ERROR, "Group %s was not added, we exceeded the max number of groups\n", name); - } - ftdm_mutex_unlock(globals.mutex); - return status; -} - -static void ftdm_group_destroy(ftdm_group_t **group) -{ - ftdm_group_t *grp = NULL; - ftdm_assert(group != NULL, "Group must not be null\n"); - grp = *group; - ftdm_mutex_destroy(&grp->mutex); - ftdm_safe_free(grp->name); - ftdm_safe_free(grp); - *group = NULL; -} - -static ftdm_status_t ftdm_span_trigger_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg) -{ - if (!span->signal_cb) { - return FTDM_FAIL; - } - return span->signal_cb(sigmsg); -} - -static ftdm_status_t ftdm_span_queue_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg) -{ - ftdm_sigmsg_t *new_sigmsg = NULL; - - new_sigmsg = ftdm_calloc(1, sizeof(*sigmsg)); - if (!new_sigmsg) { - return FTDM_FAIL; - } - memcpy(new_sigmsg, sigmsg, sizeof(*sigmsg)); - - ftdm_queue_enqueue(span->pendingsignals, new_sigmsg); - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_span_trigger_signals(const ftdm_span_t *span) -{ - ftdm_sigmsg_t *sigmsg = NULL; - while ((sigmsg = ftdm_queue_dequeue(span->pendingsignals))) { - ftdm_span_trigger_signal(span, sigmsg); - ftdm_sigmsg_free(&sigmsg); - } - return FTDM_SUCCESS; -} - -static void execute_safety_hangup(void *data) -{ - ftdm_channel_t *fchan = data; - ftdm_channel_lock(fchan); - fchan->hangup_timer = 0; - if (fchan->state == FTDM_CHANNEL_STATE_TERMINATING) { - ftdm_log_chan(fchan, FTDM_LOG_WARNING, "Forcing hangup since the user did not confirmed our hangup after %dms\n", FORCE_HANGUP_TIMER); - _ftdm_channel_call_hangup_nl(__FILE__, __FTDM_FUNC__, __LINE__, fchan, NULL); - } else { - ftdm_log_chan(fchan, FTDM_LOG_CRIT, "Not performing safety hangup, channel state is %s\n", ftdm_channel_state2str(fchan->state)); - } - ftdm_channel_unlock(fchan); -} - -FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t *sigmsg) -{ - ftdm_channel_t *fchan = NULL; - ftdm_status_t status = FTDM_SUCCESS; - if (sigmsg->channel) { - fchan = sigmsg->channel; - ftdm_channel_lock(fchan); - } - - /* some core things to do on special events */ - switch (sigmsg->event_id) { - - case FTDM_SIGEVENT_SIGSTATUS_CHANGED: - { - if (sigmsg->ev_data.sigstatus.status == FTDM_SIG_STATE_UP) { - ftdm_set_flag(fchan, FTDM_CHANNEL_SIG_UP); - ftdm_clear_flag(fchan, FTDM_CHANNEL_SUSPENDED); - } else { - ftdm_clear_flag(fchan, FTDM_CHANNEL_SIG_UP); - if (sigmsg->ev_data.sigstatus.status == FTDM_SIG_STATE_SUSPENDED) { - ftdm_set_flag(fchan, FTDM_CHANNEL_SUSPENDED); - } else { - ftdm_clear_flag(fchan, FTDM_CHANNEL_SUSPENDED); - } - } - } - break; - - case FTDM_SIGEVENT_START: - { - ftdm_assert(!ftdm_test_flag(fchan, FTDM_CHANNEL_CALL_STARTED), "Started call twice!\n"); - - if (ftdm_test_flag(fchan, FTDM_CHANNEL_OUTBOUND)) { - ftdm_log_chan_msg(fchan, FTDM_LOG_WARNING, "Inbound call taking over outbound channel\n"); - ftdm_clear_flag(fchan, FTDM_CHANNEL_OUTBOUND); - } - ftdm_set_flag(fchan, FTDM_CHANNEL_CALL_STARTED); - ftdm_call_set_call_id(fchan, &fchan->caller_data); - /* when cleaning up the public API I added this because mod_freetdm.c on_fxs_signal was - * doing it during SIGEVENT_START, but now that flags are private they can't, wonder if - * is needed at all? */ - ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_HOLD); - if (sigmsg->channel->caller_data.bearer_capability == FTDM_BEARER_CAP_UNRESTRICTED) { - ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_DIGITAL_MEDIA); - } - } - break; - - case FTDM_SIGEVENT_PROGRESS_MEDIA: - { - /* test signaling module compliance */ - if (fchan->state != FTDM_CHANNEL_STATE_PROGRESS_MEDIA) { - ftdm_log_chan(fchan, FTDM_LOG_WARNING, "FTDM_SIGEVENT_PROGRESS_MEDIA sent in state %s\n", ftdm_channel_state2str(fchan->state)); - } - } - break; - - case FTDM_SIGEVENT_UP: - { - /* test signaling module compliance */ - if (fchan->state != FTDM_CHANNEL_STATE_UP) { - ftdm_log_chan(fchan, FTDM_LOG_WARNING, "FTDM_SIGEVENT_UP sent in state %s\n", ftdm_channel_state2str(fchan->state)); - } - } - break; - - case FTDM_SIGEVENT_STOP: - { - /* TODO: we could test for compliance here and check the state is FTDM_CHANNEL_STATE_TERMINATING - * but several modules need to be updated first */ - - /* if the call was never started, do not send SIGEVENT_STOP - this happens for FXS devices in ftmod_analog which blindly send SIGEVENT_STOP, we should fix it there ... */ - if (!ftdm_test_flag(fchan, FTDM_CHANNEL_CALL_STARTED)) { - ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Ignoring SIGEVENT_STOP since user never knew about a call in this channel\n"); - goto done; - } - - if (ftdm_test_flag(fchan, FTDM_CHANNEL_USER_HANGUP)) { - ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Ignoring SIGEVENT_STOP since user already requested hangup\n"); - goto done; - } - - if (fchan->state == FTDM_CHANNEL_STATE_TERMINATING) { - ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Scheduling safety hangup timer\n"); - /* if the user does not move us to hangup in 2 seconds, we will do it ourselves */ - ftdm_sched_timer(globals.timingsched, "safety-hangup", FORCE_HANGUP_TIMER, execute_safety_hangup, fchan, &fchan->hangup_timer); - } - } - break; - - default: - break; - - } - - if (fchan) { - /* set members of the sigmsg that must be present for all events */ - sigmsg->chan_id = fchan->chan_id; - sigmsg->span_id = fchan->span_id; - sigmsg->call_id = fchan->caller_data.call_id; - sigmsg->call_priv = fchan->caller_data.priv; - } - - /* if the signaling module uses a queue for signaling notifications, then enqueue it */ - if (ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE)) { - ftdm_span_queue_signal(span, sigmsg); - } else { - status = ftdm_span_trigger_signal(span, sigmsg); - } - -done: - - if (fchan) { - ftdm_channel_unlock(fchan); - } - - return status; -} - -static void *ftdm_cpu_monitor_run(ftdm_thread_t *me, void *obj) -{ - cpu_monitor_t *monitor = (cpu_monitor_t *)obj; - struct ftdm_cpu_monitor_stats *cpu_stats = ftdm_new_cpu_monitor(); - - ftdm_log(FTDM_LOG_DEBUG, "CPU monitor thread is now running\n"); - if (!cpu_stats) { - goto done; - } - monitor->running = 1; - - while (ftdm_running()) { - double idle_time = 0.0; - int cpu_usage = 0; - - if (ftdm_cpu_get_system_idle_time(cpu_stats, &idle_time)) { - break; - } - - cpu_usage = (int)(100 - idle_time); - if (monitor->alarm) { - if (cpu_usage <= monitor->clear_alarm_threshold) { - ftdm_log(FTDM_LOG_DEBUG, "CPU alarm is now OFF (cpu usage: %d)\n", cpu_usage); - monitor->alarm = 0; - } else if (monitor->alarm_action_flags & FTDM_CPU_ALARM_ACTION_WARN) { - ftdm_log(FTDM_LOG_WARNING, "CPU alarm is still ON (cpu usage: %d)\n", cpu_usage); - } - } else { - if (cpu_usage >= monitor->set_alarm_threshold) { - ftdm_log(FTDM_LOG_WARNING, "CPU alarm is now ON (cpu usage: %d)\n", cpu_usage); - monitor->alarm = 1; - } - } - ftdm_interrupt_wait(monitor->interrupt, monitor->interval); - } - - ftdm_delete_cpu_monitor(cpu_stats); - monitor->running = 0; - -done: - ftdm_unused_arg(me); - ftdm_log(FTDM_LOG_DEBUG, "CPU monitor thread is now terminating\n"); - return NULL; -} - -static ftdm_status_t ftdm_cpu_monitor_start(void) -{ - if (ftdm_interrupt_create(&globals.cpu_monitor.interrupt, FTDM_INVALID_SOCKET, FTDM_NO_FLAGS) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Failed to create CPU monitor interrupt\n"); - return FTDM_FAIL; - } - - if (ftdm_thread_create_detached(ftdm_cpu_monitor_run, &globals.cpu_monitor) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Failed to create cpu monitor thread!!\n"); - return FTDM_FAIL; - } - return FTDM_SUCCESS; -} - -static void ftdm_cpu_monitor_stop(void) -{ - if (!globals.cpu_monitor.interrupt) { - return; - } - - if (!globals.cpu_monitor.running) { - return; - } - - if (ftdm_interrupt_signal(globals.cpu_monitor.interrupt) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Failed to interrupt the CPU monitor\n"); - return; - } - - while (globals.cpu_monitor.running) { - ftdm_sleep(10); - } - - ftdm_interrupt_destroy(&globals.cpu_monitor.interrupt); -} - -FT_DECLARE(ftdm_status_t) ftdm_global_init(void) -{ - memset(&globals, 0, sizeof(globals)); - - time_init(); - - ftdm_thread_override_default_stacksize(FTDM_THREAD_STACKSIZE); - - globals.interface_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); - globals.module_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); - globals.span_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); - globals.group_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); - ftdm_mutex_create(&globals.mutex); - ftdm_mutex_create(&globals.span_mutex); - ftdm_mutex_create(&globals.group_mutex); - ftdm_mutex_create(&globals.call_id_mutex); - - ftdm_sched_global_init(); - globals.running = 1; - if (ftdm_sched_create(&globals.timingsched, "freetdm-master") != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Failed to create master timing schedule context\n"); - goto global_init_fail; - } - if (ftdm_sched_free_run(globals.timingsched) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Failed to run master timing schedule context\n"); - goto global_init_fail; - } - - return FTDM_SUCCESS; - -global_init_fail: - globals.running = 0; - ftdm_mutex_destroy(&globals.mutex); - ftdm_mutex_destroy(&globals.span_mutex); - ftdm_mutex_destroy(&globals.group_mutex); - ftdm_mutex_destroy(&globals.call_id_mutex); - hashtable_destroy(globals.interface_hash); - hashtable_destroy(globals.module_hash); - hashtable_destroy(globals.span_hash); - hashtable_destroy(globals.group_hash); - - return FTDM_FAIL; -} - -FT_DECLARE(ftdm_status_t) ftdm_global_configuration(void) -{ - int modcount = 0; - - if (!globals.running) { - return FTDM_FAIL; - } - - modcount = ftdm_load_modules(); - - ftdm_log(FTDM_LOG_NOTICE, "Modules configured: %d \n", modcount); - - globals.cpu_monitor.enabled = 0; - globals.cpu_monitor.interval = 1000; - globals.cpu_monitor.alarm_action_flags = 0; - globals.cpu_monitor.set_alarm_threshold = 92; - globals.cpu_monitor.clear_alarm_threshold = 82; - - if (load_config() != FTDM_SUCCESS) { - globals.running = 0; - ftdm_log(FTDM_LOG_ERROR, "FreeTDM global configuration failed!\n"); - return FTDM_FAIL; - } - - if (globals.cpu_monitor.enabled) { - ftdm_log(FTDM_LOG_INFO, "CPU Monitor is running interval:%d set-thres:%d clear-thres:%d\n", - globals.cpu_monitor.interval, - globals.cpu_monitor.set_alarm_threshold, - globals.cpu_monitor.clear_alarm_threshold); - - if (ftdm_cpu_monitor_start() != FTDM_SUCCESS) { - return FTDM_FAIL; - } - } - - - return FTDM_SUCCESS; -} - -FT_DECLARE(uint32_t) ftdm_running(void) -{ - return globals.running; -} - -static void destroy_span(ftdm_span_t *span) -{ - if (ftdm_test_flag(span, FTDM_SPAN_CONFIGURED)) { - ftdm_span_destroy(span); - } - hashtable_remove(globals.span_hash, (void *)span->name); - ftdm_safe_free(span->dtmf_hangup); - ftdm_safe_free(span->type); - ftdm_safe_free(span->name); - ftdm_safe_free(span); -} - -static void force_stop_span(ftdm_span_t *span) -{ - /* This is a forced stop */ - ftdm_clear_flag(span, FTDM_SPAN_NON_STOPPABLE); - ftdm_span_stop(span); -} - -static void span_for_each(void (*func)(ftdm_span_t *span)) -{ - ftdm_span_t *sp = NULL, *next = NULL; - for (sp = globals.spans; sp; sp = next) { - next = sp->next; - func(sp); - } -} - -FT_DECLARE(ftdm_status_t) ftdm_global_destroy(void) -{ - ftdm_group_t *grp = NULL, *next_grp = NULL; - - time_end(); - - /* many freetdm event loops rely on this variable to decide when to stop, do this first */ - globals.running = 0; - - /* stop the scheduling thread */ - ftdm_free_sched_stop(); - - /* stop the cpu monitor thread */ - ftdm_cpu_monitor_stop(); - - /* now destroy channels and spans */ - globals.span_index = 0; - - ftdm_span_close_all(); - - /* Stop and destroy alls pans */ - ftdm_mutex_lock(globals.span_mutex); - - span_for_each(force_stop_span); - span_for_each(destroy_span); - globals.spans = NULL; - - ftdm_mutex_unlock(globals.span_mutex); - - /* destroy signaling and io modules */ - ftdm_unload_modules(); - - /* Destroy hunting groups */ - ftdm_mutex_lock(globals.group_mutex); - grp = globals.groups; - while (grp) { - next_grp = grp->next; - ftdm_group_destroy(&grp); - grp = next_grp; - } - ftdm_mutex_unlock(globals.group_mutex); - - /* finally destroy the globals */ - ftdm_mutex_lock(globals.mutex); - - ftdm_sched_destroy(&globals.timingsched); - - hashtable_destroy(globals.interface_hash); - hashtable_destroy(globals.module_hash); - hashtable_destroy(globals.span_hash); - hashtable_destroy(globals.group_hash); - - ftdm_mutex_destroy(&globals.span_mutex); - ftdm_mutex_destroy(&globals.group_mutex); - ftdm_mutex_destroy(&globals.call_id_mutex); - - ftdm_mutex_unlock(globals.mutex); - - ftdm_mutex_destroy(&globals.mutex); - - ftdm_sched_global_destroy(); - - ftdm_global_set_logger(NULL); - memset(&globals, 0, sizeof(globals)); - return FTDM_SUCCESS; -} - - -FT_DECLARE(uint32_t) ftdm_separate_string(char *buf, char delim, char **array, int arraylen) -{ - int argc; - char *ptr; - int quot = 0; - char qc = '\''; - int x; - - if (!buf || !array || !arraylen) { - return 0; - } - - memset(array, 0, arraylen * sizeof(*array)); - - ptr = buf; - - /* we swallow separators that are contiguous */ - while (*ptr == delim) ptr++; - - for (argc = 0; *ptr && (argc < arraylen - 1); argc++) { - array[argc] = ptr; - for (; *ptr; ptr++) { - if (*ptr == qc) { - if (quot) { - quot--; - } else { - quot++; - } - } else if ((*ptr == delim) && !quot) { - *ptr++ = '\0'; - /* we swallow separators that are contiguous */ - while (*ptr == delim) ptr++; - break; - } - } - } - - if (*ptr) { - array[argc++] = ptr; - } - - /* strip quotes */ - for (x = 0; x < argc; x++) { - char *p = array[x]; - while((p = strchr(array[x], qc))) { - memmove(p, p+1, strlen(p)); - p++; - } - } - - return argc; -} - -FT_DECLARE(void) ftdm_bitstream_init(ftdm_bitstream_t *bsp, uint8_t *data, uint32_t datalen, ftdm_endian_t endian, uint8_t ss) -{ - memset(bsp, 0, sizeof(*bsp)); - bsp->data = data; - bsp->datalen = datalen; - bsp->endian = endian; - bsp->ss = ss; - - if (endian < 0) { - bsp->top = bsp->bit_index = 7; - bsp->bot = 0; - } else { - bsp->top = bsp->bit_index = 0; - bsp->bot = 7; - } - -} - -FT_DECLARE(int8_t) ftdm_bitstream_get_bit(ftdm_bitstream_t *bsp) -{ - int8_t bit = -1; - - - if (bsp->byte_index >= bsp->datalen) { - goto done; - } - - if (bsp->ss) { - if (!bsp->ssv) { - bsp->ssv = 1; - return 0; - } else if (bsp->ssv == 2) { - bsp->byte_index++; - bsp->ssv = 0; - return 1; - } - } - - - - - bit = (bsp->data[bsp->byte_index] >> (bsp->bit_index)) & 1; - - if (bsp->bit_index == bsp->bot) { - bsp->bit_index = bsp->top; - if (bsp->ss) { - bsp->ssv = 2; - goto done; - } - - if (++bsp->byte_index > bsp->datalen) { - bit = -1; - goto done; - } - - } else { - bsp->bit_index = bsp->bit_index + bsp->endian; - } - - - done: - return bit; -} - -FT_DECLARE(void) print_hex_bytes(uint8_t *data, ftdm_size_t dlen, char *buf, ftdm_size_t blen) -{ - char *bp = buf; - uint8_t *byte = data; - uint32_t i, j = 0; - - if (blen < (dlen * 3) + 2) { - return; - } - - *bp++ = '['; - j++; - - for(i = 0; i < dlen; i++) { - snprintf(bp, blen-j, "%02x ", *byte++); - bp += 3; - j += 3; - } - - *--bp = ']'; - -} - -FT_DECLARE(void) print_bits(uint8_t *b, int bl, char *buf, int blen, ftdm_endian_t e, uint8_t ss) -{ - ftdm_bitstream_t bs; - int j = 0, c = 0; - int8_t bit; - uint32_t last; - - if (blen < (bl * 10) + 2) { - return; - } - - ftdm_bitstream_init(&bs, b, bl, e, ss); - last = bs.byte_index; - while((bit = ftdm_bitstream_get_bit(&bs)) > -1) { - buf[j++] = bit ? '1' : '0'; - if (bs.byte_index != last) { - buf[j++] = ' '; - last = bs.byte_index; - if (++c == 8) { - buf[j++] = '\n'; - c = 0; - } - } - } - -} - - - -FT_DECLARE_NONSTD(ftdm_status_t) ftdm_console_stream_raw_write(ftdm_stream_handle_t *handle, uint8_t *data, ftdm_size_t datalen) -{ - ftdm_size_t need = handle->data_len + datalen; - - if (need >= handle->data_size) { - void *new_data; - need += handle->alloc_chunk; - - if (!(new_data = realloc(handle->data, need))) { - return FTDM_MEMERR; - } - - handle->data = new_data; - handle->data_size = need; - } - - memcpy((uint8_t *) (handle->data) + handle->data_len, data, datalen); - handle->data_len += datalen; - handle->end = (uint8_t *) (handle->data) + handle->data_len; - *(uint8_t *)handle->end = '\0'; - - return FTDM_SUCCESS; -} - -FT_DECLARE(int) ftdm_vasprintf(char **ret, const char *fmt, va_list ap) /* code from switch_apr.c */ -{ -#ifdef HAVE_VASPRINTF - return vasprintf(ret, fmt, ap); -#else - char *buf; - int len; - size_t buflen; - va_list ap2; - char *tmp = NULL; - -#ifdef _MSC_VER -#if _MSC_VER >= 1500 - /* hack for incorrect assumption in msvc header files for code analysis */ - __analysis_assume(tmp); -#endif - ap2 = ap; -#else - va_copy(ap2, ap); -#endif - - len = vsnprintf(tmp, 0, fmt, ap2); - - if (len > 0 && (buf = ftdm_malloc((buflen = (size_t) (len + 1)))) != NULL) { - len = vsnprintf(buf, buflen, fmt, ap); - *ret = buf; - } else { - *ret = NULL; - len = -1; - } - - va_end(ap2); - return len; -#endif -} - -FT_DECLARE_NONSTD(ftdm_status_t) ftdm_console_stream_write(ftdm_stream_handle_t *handle, const char *fmt, ...) -{ - va_list ap; - char *buf = handle->data; - char *end = handle->end; - int ret = 0; - char *data = NULL; - - if (handle->data_len >= handle->data_size) { - return FTDM_FAIL; - } - - va_start(ap, fmt); - ret = ftdm_vasprintf(&data, fmt, ap); - va_end(ap); - - if (data) { - ftdm_size_t remaining = handle->data_size - handle->data_len; - ftdm_size_t need = strlen(data) + 1; - - if ((remaining < need) && handle->alloc_len) { - ftdm_size_t new_len; - void *new_data; - - new_len = handle->data_size + need + handle->alloc_chunk; - if ((new_data = ftdm_realloc(handle->data, new_len))) { - handle->data_size = handle->alloc_len = new_len; - handle->data = new_data; - buf = handle->data; - remaining = handle->data_size - handle->data_len; - handle->end = (uint8_t *) (handle->data) + handle->data_len; - end = handle->end; - } else { - ftdm_log(FTDM_LOG_CRIT, "Memory Error!\n"); - ftdm_safe_free(data); - return FTDM_FAIL; - } - } - - if (remaining < need) { - ret = -1; - } else { - ret = 0; - snprintf(end, remaining, "%s", data); - handle->data_len = strlen(buf); - handle->end = (uint8_t *) (handle->data) + handle->data_len; - } - ftdm_safe_free(data); - } - - return ret ? FTDM_FAIL : FTDM_SUCCESS; -} - -FT_DECLARE(char *) ftdm_strdup(const char *str) -{ - ftdm_size_t len = strlen(str) + 1; - void *new = ftdm_malloc(len); - - if (!new) { - return NULL; - } - - return (char *)memcpy(new, str, len); -} - -FT_DECLARE(char *) ftdm_strndup(const char *str, ftdm_size_t inlen) -{ - char *new = NULL; - ftdm_size_t len = strlen(str) + 1; - if (len > (inlen+1)) { - len = inlen+1; - } - new = (char *)ftdm_malloc(len); - - if (!new) { - return NULL; - } - - memcpy(new, str, len-1); - new[len-1] = 0; - return new; -} - -static ftdm_status_t ftdm_call_set_call_id(ftdm_channel_t *fchan, ftdm_caller_data_t *caller_data) -{ - uint32_t current_call_id; - - ftdm_assert_return(!caller_data->call_id, FTDM_FAIL, "Overwriting non-cleared call-id\n"); - - ftdm_mutex_lock(globals.call_id_mutex); - - current_call_id = globals.last_call_id; - - for (current_call_id = globals.last_call_id + 1; - current_call_id != globals.last_call_id; - current_call_id++ ) { - if (current_call_id > MAX_CALLIDS) { - current_call_id = 1; - } - if (globals.call_ids[current_call_id] == NULL) { - break; - } - } - - ftdm_assert_return(globals.call_ids[current_call_id] == NULL, FTDM_FAIL, "We ran out of call ids\n"); - - globals.last_call_id = current_call_id; - caller_data->call_id = current_call_id; - - globals.call_ids[current_call_id] = caller_data; - caller_data->fchan = fchan; - - ftdm_mutex_unlock(globals.call_id_mutex); - return FTDM_SUCCESS; -} - -static ftdm_status_t ftdm_call_clear_call_id(ftdm_caller_data_t *caller_data) -{ - if (caller_data->call_id) { - ftdm_assert_return((caller_data->call_id <= MAX_CALLIDS), FTDM_FAIL, "Cannot clear call with invalid call-id\n"); - } else { - /* there might not be a call at all */ - return FTDM_SUCCESS; - } - - ftdm_mutex_lock(globals.call_id_mutex); - if (globals.call_ids[caller_data->call_id]) { - ftdm_log(FTDM_LOG_DEBUG, "Cleared call with id %u\n", caller_data->call_id); - globals.call_ids[caller_data->call_id] = NULL; - caller_data->call_id = 0; - } else { - ftdm_log(FTDM_LOG_CRIT, "call-id did not exist %u\n", caller_data->call_id); - } - ftdm_mutex_unlock(globals.call_id_mutex); - - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_sigmsg_get_raw_data(ftdm_sigmsg_t *sigmsg, void **data, ftdm_size_t *datalen) -{ - if (!sigmsg || !sigmsg->raw.len) { - return FTDM_FAIL; - } - - *data = sigmsg->raw.data; - *datalen = sigmsg->raw.len; - - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_sigmsg_get_raw_data_detached(ftdm_sigmsg_t *sigmsg, void **data, ftdm_size_t *datalen) -{ - if (!sigmsg || !sigmsg->raw.len) { - return FTDM_FAIL; - } - - *data = sigmsg->raw.data; - *datalen = sigmsg->raw.len; - - sigmsg->raw.data = NULL; - sigmsg->raw.len = 0; - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_sigmsg_set_raw_data(ftdm_sigmsg_t *sigmsg, void *data, ftdm_size_t datalen) -{ - ftdm_assert_return(sigmsg, FTDM_FAIL, "Trying to set raw data on a NULL event\n"); - ftdm_assert_return(!sigmsg->raw.len, FTDM_FAIL, "Overwriting existing raw data\n"); - ftdm_assert_return(datalen, FTDM_FAIL, "Data length not set\n"); - - sigmsg->raw.data = data; - sigmsg->raw.len = datalen; - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_usrmsg_get_raw_data(ftdm_usrmsg_t *usrmsg, void **data, ftdm_size_t *datalen) -{ - if (!usrmsg || !usrmsg->raw.len) { - return FTDM_FAIL; - } - - *data = usrmsg->raw.data; - *datalen = usrmsg->raw.len; - - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_usrmsg_set_raw_data(ftdm_usrmsg_t *usrmsg, void *data, ftdm_size_t datalen) -{ - ftdm_assert_return(usrmsg, FTDM_FAIL, "Trying to set raw data on a NULL event\n"); - ftdm_assert_return(!usrmsg->raw.len, FTDM_FAIL, "Overwriting existing raw data\n"); - ftdm_assert_return(datalen, FTDM_FAIL, "Data length not set\n"); - - usrmsg->raw.data = data; - usrmsg->raw.len = datalen; - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_save_usrmsg(ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg) -{ - ftdm_assert_return(!ftdmchan->usrmsg, FTDM_FAIL, "Info from previous event was not cleared\n"); - if (usrmsg) { - /* Copy sigmsg from user to internal copy so user can set new variables without race condition */ - ftdmchan->usrmsg = ftdm_calloc(1, sizeof(ftdm_usrmsg_t)); - memcpy(ftdmchan->usrmsg, usrmsg, sizeof(ftdm_usrmsg_t)); - - if (usrmsg->raw.data) { - usrmsg->raw.data = NULL; - usrmsg->raw.len = 0; - } - if (usrmsg->variables) { - usrmsg->variables = NULL; - } - } - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_sigmsg_free(ftdm_sigmsg_t **sigmsg) -{ - if (!*sigmsg) { - return FTDM_SUCCESS; - } - - if ((*sigmsg)->variables) { - hashtable_destroy((*sigmsg)->variables); - (*sigmsg)->variables = NULL; - } - - if ((*sigmsg)->raw.data) { - ftdm_safe_free((*sigmsg)->raw.data); - (*sigmsg)->raw.data = NULL; - (*sigmsg)->raw.len = 0; - } - - ftdm_safe_free(*sigmsg); - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_usrmsg_free(ftdm_usrmsg_t **usrmsg) -{ - if (!*usrmsg) { - return FTDM_SUCCESS; - } - - if ((*usrmsg)->variables) { - hashtable_destroy((*usrmsg)->variables); - (*usrmsg)->variables = NULL; - } - - if ((*usrmsg)->raw.data) { - ftdm_safe_free((*usrmsg)->raw.data); - (*usrmsg)->raw.data = NULL; - (*usrmsg)->raw.len = 0; - } - - ftdm_safe_free(*usrmsg); - return FTDM_SUCCESS; -} - - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftdm_queue.c b/libs/freetdm/src/ftdm_queue.c deleted file mode 100644 index c4c6524064..0000000000 --- a/libs/freetdm/src/ftdm_queue.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2009, Sangoma Technologies - * Moises Silva - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "private/ftdm_core.h" - -static ftdm_status_t ftdm_std_queue_create(ftdm_queue_t **outqueue, ftdm_size_t capacity); -static ftdm_status_t ftdm_std_queue_enqueue(ftdm_queue_t *queue, void *obj); -static void *ftdm_std_queue_dequeue(ftdm_queue_t *queue); -static ftdm_status_t ftdm_std_queue_wait(ftdm_queue_t *queue, int ms); -static ftdm_status_t ftdm_std_queue_get_interrupt(ftdm_queue_t *queue, ftdm_interrupt_t **interrupt); -static ftdm_status_t ftdm_std_queue_destroy(ftdm_queue_t **inqueue); - -struct ftdm_queue { - ftdm_mutex_t *mutex; - ftdm_interrupt_t *interrupt; - ftdm_size_t capacity; - ftdm_size_t size; - unsigned rindex; - unsigned windex; - void **elements; -}; - -FT_DECLARE_DATA ftdm_queue_handler_t g_ftdm_queue_handler = -{ - /*.create = */ ftdm_std_queue_create, - /*.enqueue = */ ftdm_std_queue_enqueue, - /*.dequeue = */ ftdm_std_queue_dequeue, - /*.wait = */ ftdm_std_queue_wait, - /*.get_interrupt = */ ftdm_std_queue_get_interrupt, - /*.destroy = */ ftdm_std_queue_destroy -}; - -FT_DECLARE(ftdm_status_t) ftdm_global_set_queue_handler(ftdm_queue_handler_t *handler) -{ - if (!handler || - !handler->create || - !handler->enqueue || - !handler->dequeue || - !handler->wait || - !handler->get_interrupt || - !handler->destroy) { - return FTDM_FAIL; - } - memcpy(&g_ftdm_queue_handler, handler, sizeof(*handler)); - return FTDM_SUCCESS; -} - -static ftdm_status_t ftdm_std_queue_create(ftdm_queue_t **outqueue, ftdm_size_t capacity) -{ - ftdm_queue_t *queue = NULL; - ftdm_assert_return(outqueue, FTDM_FAIL, "Queue double pointer is null\n"); - ftdm_assert_return(capacity > 0, FTDM_FAIL, "Queue capacity is not bigger than 0\n"); - - *outqueue = NULL; - queue = ftdm_calloc(1, sizeof(*queue)); - if (!queue) { - return FTDM_FAIL; - } - - queue->elements = ftdm_calloc(1, (sizeof(void*)*capacity)); - if (!queue->elements) { - goto failed; - } - queue->capacity = capacity; - - if (ftdm_mutex_create(&queue->mutex) != FTDM_SUCCESS) { - goto failed; - } - - if (ftdm_interrupt_create(&queue->interrupt, FTDM_INVALID_SOCKET, FTDM_NO_FLAGS) != FTDM_SUCCESS) { - goto failed; - } - - *outqueue = queue; - return FTDM_SUCCESS; - -failed: - if (queue) { - if (queue->interrupt) { - ftdm_interrupt_destroy(&queue->interrupt); - } - if (queue->mutex) { - ftdm_mutex_destroy(&queue->mutex); - } - ftdm_safe_free(queue->elements); - ftdm_safe_free(queue); - } - return FTDM_FAIL; -} - -static ftdm_status_t ftdm_std_queue_enqueue(ftdm_queue_t *queue, void *obj) -{ - ftdm_status_t status = FTDM_FAIL; - - ftdm_assert_return(queue != NULL, FTDM_FAIL, "Queue is null!"); - - ftdm_mutex_lock(queue->mutex); - - if (queue->windex == queue->capacity) { - /* try to see if we can wrap around */ - queue->windex = 0; - } - - if (queue->size != 0 && queue->windex == queue->rindex) { - ftdm_log(FTDM_LOG_ERROR, "Failed to enqueue obj %p in queue %p, no more room! windex == rindex == %d!\n", obj, queue, queue->windex); - goto done; - } - - queue->elements[queue->windex++] = obj; - queue->size++; - status = FTDM_SUCCESS; - - /* wake up queue reader */ - ftdm_interrupt_signal(queue->interrupt); - -done: - - ftdm_mutex_unlock(queue->mutex); - - return status; -} - -static void *ftdm_std_queue_dequeue(ftdm_queue_t *queue) -{ - void *obj = NULL; - - ftdm_assert_return(queue != NULL, NULL, "Queue is null!"); - - ftdm_mutex_lock(queue->mutex); - - if (queue->size == 0) { - goto done; - } - - obj = queue->elements[queue->rindex]; - queue->elements[queue->rindex++] = NULL; - queue->size--; - if (queue->rindex == queue->capacity) { - queue->rindex = 0; - } - -done: - - ftdm_mutex_unlock(queue->mutex); - - return obj; -} - -static ftdm_status_t ftdm_std_queue_wait(ftdm_queue_t *queue, int ms) -{ - ftdm_status_t ret; - ftdm_assert_return(queue != NULL, FTDM_FAIL, "Queue is null!"); - - ftdm_mutex_lock(queue->mutex); - - /* if there is elements in the queue, no need to wait */ - if (queue->size != 0) { - ftdm_mutex_unlock(queue->mutex); - return FTDM_SUCCESS; - } - - /* no elements on the queue, wait for someone to write an element */ - ret = ftdm_interrupt_wait(queue->interrupt, ms); - - /* got an element or timeout, bail out */ - ftdm_mutex_unlock(queue->mutex); - - return ret; -} - -static ftdm_status_t ftdm_std_queue_get_interrupt(ftdm_queue_t *queue, ftdm_interrupt_t **interrupt) -{ - ftdm_assert_return(queue != NULL, FTDM_FAIL, "Queue is null!\n"); - ftdm_assert_return(interrupt != NULL, FTDM_FAIL, "Queue is null!\n"); - *interrupt = queue->interrupt; - return FTDM_SUCCESS; -} - -static ftdm_status_t ftdm_std_queue_destroy(ftdm_queue_t **inqueue) -{ - ftdm_queue_t *queue = NULL; - ftdm_assert_return(inqueue != NULL, FTDM_FAIL, "Queue is null!\n"); - ftdm_assert_return(*inqueue != NULL, FTDM_FAIL, "Queue is null!\n"); - - queue = *inqueue; - ftdm_interrupt_destroy(&queue->interrupt); - ftdm_mutex_destroy(&queue->mutex); - ftdm_safe_free(queue->elements); - ftdm_safe_free(queue); - *inqueue = NULL; - return FTDM_SUCCESS; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftdm_sched.c b/libs/freetdm/src/ftdm_sched.c deleted file mode 100644 index 324073976c..0000000000 --- a/libs/freetdm/src/ftdm_sched.c +++ /dev/null @@ -1,576 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * Moises Silva - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "private/ftdm_core.h" - -#ifdef __WINDOWS__ -struct ftdm_timezone { - int tz_minuteswest; /* minutes W of Greenwich */ - int tz_dsttime; /* type of dst correction */ -}; -int gettimeofday(struct timeval *tv, struct ftdm_timezone *tz) -{ - FILETIME ft; - unsigned __int64 tmpres = 0; - static int tzflag; - if (NULL != tv) { - GetSystemTimeAsFileTime(&ft); - tmpres |= ft.dwHighDateTime; - tmpres <<= 32; - tmpres |= ft.dwLowDateTime; - - /*converting file time to unix epoch */ - tmpres /= 10; /*convert into microseconds */ - tmpres -= DELTA_EPOCH_IN_MICROSECS; - tv->tv_sec = (long) (tmpres / 1000000UL); - tv->tv_usec = (long) (tmpres % 1000000UL); - } - if (NULL != tz) { - if (!tzflag) { - _tzset(); - tzflag++; - } - tz->tz_minuteswest = _timezone / 60; - tz->tz_dsttime = _daylight; - } - return 0; -} -#endif /* __WINDOWS__ */ - -typedef struct ftdm_timer ftdm_timer_t; - -static struct { - ftdm_sched_t *freeruns; - ftdm_mutex_t *mutex; - ftdm_bool_t running; -} sched_globals; - -struct ftdm_sched { - char name[80]; - ftdm_timer_id_t currid; - ftdm_mutex_t *mutex; - ftdm_timer_t *timers; - int freerun; - ftdm_sched_t *next; - ftdm_sched_t *prev; -}; - -struct ftdm_timer { - char name[80]; - ftdm_timer_id_t id; - struct timeval time; - void *usrdata; - ftdm_sched_callback_t callback; - ftdm_timer_t *next; - ftdm_timer_t *prev; -}; - -/* FIXME: use ftdm_interrupt_t to wait for new schedules to monitor */ -#define SCHED_MAX_SLEEP 100 -static void *run_main_schedule(ftdm_thread_t *thread, void *data) -{ - int32_t timeto; - int32_t sleepms; - ftdm_status_t status; - ftdm_sched_t *current = NULL; - - ftdm_unused_arg(data); - ftdm_unused_arg(thread); - - while (ftdm_running()) { - - sleepms = SCHED_MAX_SLEEP; - - ftdm_mutex_lock(sched_globals.mutex); - - if (!sched_globals.freeruns) { - - /* there are no free runs, wait a bit and check again (FIXME: use ftdm_interrupt_t for this) */ - ftdm_mutex_unlock(sched_globals.mutex); - - if (ftdm_running()) { - ftdm_sleep(sleepms); - } - } - - for (current = sched_globals.freeruns; current; current = current->next) { - if (!ftdm_running()) { - break; - } - - /* first run the schedule */ - ftdm_sched_run(current); - - /* now find out how much time to sleep until running them again */ - status = ftdm_sched_get_time_to_next_timer(current, &timeto); - if (status != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_WARNING, "Failed to get time to next timer for schedule %s, skipping\n", current->name); - continue; - } - - /* if timeto == -1 we don't want to sleep forever, so keep the last sleepms */ - if (timeto != -1 && sleepms > timeto) { - sleepms = timeto; - } - } - - ftdm_mutex_unlock(sched_globals.mutex); - - if (ftdm_running()) { - ftdm_sleep(sleepms); - } - } - ftdm_log(FTDM_LOG_NOTICE, "Main scheduling thread going out ...\n"); - sched_globals.running = 0; - return NULL; -} - -FT_DECLARE(ftdm_status_t) ftdm_sched_global_init() -{ - ftdm_log(FTDM_LOG_DEBUG, "Initializing scheduling API\n"); - memset(&sched_globals, 0, sizeof(sched_globals)); - if (ftdm_mutex_create(&sched_globals.mutex) == FTDM_SUCCESS) { - return FTDM_SUCCESS; - } - return FTDM_FAIL; -} - -FT_DECLARE(ftdm_status_t) ftdm_sched_global_destroy() -{ - ftdm_mutex_destroy(&sched_globals.mutex); - memset(&sched_globals, 0, sizeof(sched_globals)); - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_sched_free_run(ftdm_sched_t *sched) -{ - ftdm_status_t status = FTDM_FAIL; - ftdm_assert_return(sched != NULL, FTDM_EINVAL, "invalid pointer\n"); - - ftdm_mutex_lock(sched->mutex); - - ftdm_mutex_lock(sched_globals.mutex); - - if (sched->freerun) { - ftdm_log(FTDM_LOG_ERROR, "Schedule %s is already running in free run\n", sched->name); - goto done; - } - sched->freerun = 1; - - if (sched_globals.running == FTDM_FALSE) { - ftdm_log(FTDM_LOG_NOTICE, "Launching main schedule thread\n"); - status = ftdm_thread_create_detached(run_main_schedule, NULL); - if (status != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Failed to launch main schedule thread\n"); - goto done; - } - sched_globals.running = FTDM_TRUE; - } - - ftdm_log(FTDM_LOG_DEBUG, "Running schedule %s in the main schedule thread\n", sched->name); - status = FTDM_SUCCESS; - - /* Add the schedule to the global list of free runs */ - if (!sched_globals.freeruns) { - sched_globals.freeruns = sched; - } else { - sched->next = sched_globals.freeruns; - sched_globals.freeruns->prev = sched; - sched_globals.freeruns = sched; - } - -done: - ftdm_mutex_unlock(sched_globals.mutex); - - ftdm_mutex_unlock(sched->mutex); - return status; -} - -FT_DECLARE(ftdm_bool_t) ftdm_free_sched_running(void) -{ - return sched_globals.running; -} - -FT_DECLARE(ftdm_bool_t) ftdm_free_sched_stop(void) -{ - /* currently we really dont stop the thread here, we rely on freetdm being shutdown and ftdm_running() to be false - * so the scheduling thread dies and we just wait for it here */ - uint32_t sanity = 100; - while (ftdm_free_sched_running() && --sanity) { - ftdm_log(FTDM_LOG_DEBUG, "Waiting for main schedule thread to finish\n"); - ftdm_sleep(100); - } - - if (!sanity) { - ftdm_log(FTDM_LOG_CRIT, "schedule thread did not stop running, we may crash on shutdown\n"); - return FTDM_FALSE; - } - - return FTDM_TRUE; -} - -FT_DECLARE(ftdm_status_t) ftdm_sched_create(ftdm_sched_t **sched, const char *name) -{ - ftdm_sched_t *newsched = NULL; - - ftdm_assert_return(sched != NULL, FTDM_EINVAL, "invalid pointer\n"); - ftdm_assert_return(name != NULL, FTDM_EINVAL, "invalid sched name\n"); - - *sched = NULL; - - newsched = ftdm_calloc(1, sizeof(*newsched)); - if (!newsched) { - return FTDM_MEMERR; - } - - if (ftdm_mutex_create(&newsched->mutex) != FTDM_SUCCESS) { - goto failed; - } - - ftdm_set_string(newsched->name, name); - newsched->currid = 1; - - *sched = newsched; - ftdm_log(FTDM_LOG_DEBUG, "Created schedule %s\n", name); - return FTDM_SUCCESS; - -failed: - ftdm_log(FTDM_LOG_CRIT, "Failed to create schedule\n"); - - if (newsched) { - if (newsched->mutex) { - ftdm_mutex_destroy(&newsched->mutex); - } - ftdm_safe_free(newsched); - } - return FTDM_FAIL; -} - -FT_DECLARE(ftdm_status_t) ftdm_sched_run(ftdm_sched_t *sched) -{ - ftdm_status_t status = FTDM_FAIL; - ftdm_timer_t *runtimer; - ftdm_timer_t *timer; - ftdm_sched_callback_t callback; - int ms = 0; - int rc = -1; - void *data; - struct timeval now; - - ftdm_assert_return(sched != NULL, FTDM_EINVAL, "sched is null!\n"); - -tryagain: - - ftdm_mutex_lock(sched->mutex); - - rc = gettimeofday(&now, NULL); - if (rc == -1) { - ftdm_log(FTDM_LOG_ERROR, "Failed to retrieve time of day\n"); - goto done; - } - - timer = sched->timers; - while (timer) { - runtimer = timer; - timer = runtimer->next; - - ms = ((runtimer->time.tv_sec - now.tv_sec) * 1000) + - ((runtimer->time.tv_usec - now.tv_usec) / 1000); - - if (ms <= 0) { - - if (runtimer == sched->timers) { - sched->timers = runtimer->next; - if (sched->timers) { - sched->timers->prev = NULL; - } - } - - callback = runtimer->callback; - data = runtimer->usrdata; - if (runtimer->next) { - runtimer->next->prev = runtimer->prev; - } - if (runtimer->prev) { - runtimer->prev->next = runtimer->next; - } - - runtimer->id = 0; - ftdm_safe_free(runtimer); - - /* avoid deadlocks by releasing the sched lock before triggering callbacks */ - ftdm_mutex_unlock(sched->mutex); - - callback(data); - /* after calling a callback we must start the scanning again since the - * callback or some other thread may have added or cancelled timers to - * the linked list */ - goto tryagain; - } - } - - status = FTDM_SUCCESS; -done: - ftdm_mutex_unlock(sched->mutex); - ftdm_unused_arg(sched); - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_sched_timer(ftdm_sched_t *sched, const char *name, - int ms, ftdm_sched_callback_t callback, void *data, ftdm_timer_id_t *timerid) -{ - ftdm_status_t status = FTDM_FAIL; - struct timeval now; - int rc = 0; - ftdm_timer_t *newtimer; - - ftdm_assert_return(sched != NULL, FTDM_EINVAL, "sched is null!\n"); - ftdm_assert_return(name != NULL, FTDM_EINVAL, "timer name is null!\n"); - ftdm_assert_return(callback != NULL, FTDM_EINVAL, "sched callback is null!\n"); - ftdm_assert_return(ms > 0, FTDM_EINVAL, "milliseconds must be bigger than 0!\n"); - - if (timerid) { - *timerid = 0; - } - - rc = gettimeofday(&now, NULL); - if (rc == -1) { - ftdm_log(FTDM_LOG_ERROR, "Failed to retrieve time of day\n"); - return FTDM_FAIL; - } - - ftdm_mutex_lock(sched->mutex); - - newtimer = ftdm_calloc(1, sizeof(*newtimer)); - if (!newtimer) { - goto done; - } - newtimer->id = sched->currid; - sched->currid++; - if (!sched->currid) { - ftdm_log(FTDM_LOG_NOTICE, "Timer id wrap around for sched %s\n", sched->name); - /* we do not want currid to be zero since is an invalid id - * TODO: check that currid does not exists already in the context, it'd be insane - * though, having a timer to live all that time */ - sched->currid++; - } - - ftdm_set_string(newtimer->name, name); - newtimer->callback = callback; - newtimer->usrdata = data; - - newtimer->time.tv_sec = now.tv_sec + (ms / 1000); - newtimer->time.tv_usec = now.tv_usec + (ms % 1000) * 1000; - if (newtimer->time.tv_usec >= FTDM_MICROSECONDS_PER_SECOND) { - newtimer->time.tv_sec += 1; - newtimer->time.tv_usec -= FTDM_MICROSECONDS_PER_SECOND; - } - - if (!sched->timers) { - sched->timers = newtimer; - } else { - newtimer->next = sched->timers; - sched->timers->prev = newtimer; - sched->timers = newtimer; - } - - if (timerid) { - *timerid = newtimer->id; - } - - status = FTDM_SUCCESS; -done: - ftdm_mutex_unlock(sched->mutex); - ftdm_unused_arg(sched); - ftdm_unused_arg(name); - ftdm_unused_arg(ms); - ftdm_unused_arg(callback); - ftdm_unused_arg(data); - ftdm_unused_arg(timerid); - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_sched_get_time_to_next_timer(const ftdm_sched_t *sched, int32_t *timeto) -{ - ftdm_status_t status = FTDM_FAIL; - int res = -1; - int ms = 0; - struct timeval currtime; - ftdm_timer_t *current = NULL; - ftdm_timer_t *winner = NULL; - - /* forever by default */ - *timeto = -1; - - ftdm_mutex_lock(sched->mutex); - - res = gettimeofday(&currtime, NULL); - if (-1 == res) { - ftdm_log(FTDM_LOG_ERROR, "Failed to get next event time\n"); - goto done; - } - status = FTDM_SUCCESS; - current = sched->timers; - while (current) { - /* if no winner, set this as winner */ - if (!winner) { - winner = current; - } - current = current->next; - /* if no more timers, return the winner */ - if (!current) { - ms = (((winner->time.tv_sec - currtime.tv_sec) * 1000) + - ((winner->time.tv_usec - currtime.tv_usec) / 1000)); - - /* if the timer is expired already, return 0 to attend immediately */ - if (ms < 0) { - *timeto = 0; - break; - } - *timeto = ms; - break; - } - - /* if the winner timer is after the current timer, then we have a new winner */ - if (winner->time.tv_sec > current->time.tv_sec - || (winner->time.tv_sec == current->time.tv_sec && - winner->time.tv_usec > current->time.tv_usec)) { - winner = current; - } - } - -done: - ftdm_mutex_unlock(sched->mutex); - ftdm_unused_arg(timeto); - ftdm_unused_arg(sched); - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_sched_cancel_timer(ftdm_sched_t *sched, ftdm_timer_id_t timerid) -{ - ftdm_status_t status = FTDM_FAIL; - ftdm_timer_t *timer; - - ftdm_assert_return(sched != NULL, FTDM_EINVAL, "sched is null!\n"); - - if (!timerid) { - return FTDM_SUCCESS; - } - - ftdm_mutex_lock(sched->mutex); - - /* look for the timer and destroy it */ - for (timer = sched->timers; timer; timer = timer->next) { - if (timer->id == timerid) { - if (timer == sched->timers) { - /* it's the head timer, put a new head */ - sched->timers = timer->next; - } - if (timer->prev) { - timer->prev->next = timer->next; - } - if (timer->next) { - timer->next->prev = timer->prev; - } - ftdm_safe_free(timer); - status = FTDM_SUCCESS; - break; - } - } - - ftdm_mutex_unlock(sched->mutex); - - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_sched_destroy(ftdm_sched_t **insched) -{ - ftdm_sched_t *sched = NULL; - ftdm_timer_t *timer; - ftdm_timer_t *deltimer; - ftdm_assert_return(insched != NULL, FTDM_EINVAL, "sched is null!\n"); - ftdm_assert_return(*insched != NULL, FTDM_EINVAL, "sched is null!\n"); - - sched = *insched; - - /* since destroying a sched may affect the global list, we gotta check */ - ftdm_mutex_lock(sched_globals.mutex); - - /* if we're head, replace head with our next (whatever our next is, even null will do) */ - if (sched == sched_globals.freeruns) { - sched_globals.freeruns = sched->next; - } - /* if we have a previous member (then we were not head) set our previous next to our next */ - if (sched->prev) { - sched->prev->next = sched->next; - } - /* if we have a next then set their prev to our prev (if we were head prev will be null and sched->next is already the new head) */ - if (sched->next) { - sched->next->prev = sched->prev; - } - - ftdm_mutex_unlock(sched_globals.mutex); - - /* now grab the sched mutex */ - ftdm_mutex_lock(sched->mutex); - - timer = sched->timers; - while (timer) { - deltimer = timer; - timer = timer->next; - ftdm_safe_free(deltimer); - } - - ftdm_log(FTDM_LOG_DEBUG, "Destroying schedule %s\n", sched->name); - - ftdm_mutex_unlock(sched->mutex); - - ftdm_mutex_destroy(&sched->mutex); - - ftdm_safe_free(sched); - - *insched = NULL; - return FTDM_SUCCESS; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftdm_state.c b/libs/freetdm/src/ftdm_state.c deleted file mode 100644 index f6bc0ef4c4..0000000000 --- a/libs/freetdm/src/ftdm_state.c +++ /dev/null @@ -1,575 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * Moises Silva - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "private/ftdm_core.h" - -FTDM_ENUM_NAMES(CHANNEL_STATE_NAMES, CHANNEL_STATE_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_channel_state, ftdm_channel_state2str, ftdm_channel_state_t, CHANNEL_STATE_NAMES, FTDM_CHANNEL_STATE_INVALID) - -FTDM_ENUM_NAMES(CHANNEL_STATE_STATUS_NAMES, CHANNEL_STATE_STATUS_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_state_status, ftdm_state_status2str, ftdm_state_status_t, CHANNEL_STATE_STATUS_NAMES, FTDM_STATE_STATUS_INVALID) - -static ftdm_status_t ftdm_core_set_state(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_state_t state, int waitrq); - -FT_DECLARE(ftdm_status_t) _ftdm_channel_complete_state(const char *file, const char *func, int line, ftdm_channel_t *fchan) -{ - uint8_t hindex = 0; - ftdm_time_t diff = 0; - ftdm_channel_state_t state = fchan->state; - -#if 0 - /* I could not perform this sanity check without more disruptive changes. Ideally we should check here if the signaling module completing the state - executed a state processor (called ftdm_channel_advance_states() which call fchan->span->state_processor(fchan)) for the state. That is just a - sanity check, as in the past we had at least one bug where the signaling module set the state and then accidentally changed the state to a new one - without calling ftdm_channel_advance_states(), meaning the state processor for the first state was not executed and that lead to unexpected behavior. - - If we want to be able to perform this kind of sanity check it would be nice to add a new state status (FTDM_STATE_STATUS_PROCESSING), the function - ftdm_channel_advance_states() would set the state_status to PROCESSING and then the check below for STATUS_NEW would be valid. Currently is not - valid because the signaling module may be completing the state at the end of the state_processor callback and therefore the state will still be - in STATUS_NEW, and is perfectly valid ... */ - - if (fchan->state_status == FTDM_STATE_STATUS_NEW) { - ftdm_log_chan_ex(fchan, file, func, line, FTDM_LOG_LEVEL_CRIT, - "Asking to complete state change from %s to %s in %llums, but the state is still unprocessed (this might be a bug!)\n", - ftdm_channel_state2str(fchan->last_state), ftdm_channel_state2str(state), diff); - } -#endif - - if (fchan->state_status == FTDM_STATE_STATUS_COMPLETED) { - ftdm_assert_return(!ftdm_test_flag(fchan, FTDM_CHANNEL_STATE_CHANGE), FTDM_FAIL, "State change flag set but state is already completed\n"); - return FTDM_SUCCESS; - } - - ftdm_usrmsg_free(&fchan->usrmsg); - - ftdm_clear_flag(fchan, FTDM_CHANNEL_STATE_CHANGE); - - if (state == FTDM_CHANNEL_STATE_PROGRESS) { - ftdm_set_flag(fchan, FTDM_CHANNEL_PROGRESS); - } else if (state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA) { - ftdm_set_flag(fchan, FTDM_CHANNEL_PROGRESS); - ftdm_test_and_set_media(fchan); - } else if (state == FTDM_CHANNEL_STATE_UP) { - ftdm_set_flag(fchan, FTDM_CHANNEL_PROGRESS); - ftdm_set_flag(fchan, FTDM_CHANNEL_ANSWERED); - ftdm_test_and_set_media(fchan); - } else if (state == FTDM_CHANNEL_STATE_DIALING) { - ftdm_sigmsg_t msg; - memset(&msg, 0, sizeof(msg)); - msg.channel = fchan; - msg.event_id = FTDM_SIGEVENT_DIALING; - ftdm_span_send_signal(fchan->span, &msg); - } else if (state == FTDM_CHANNEL_STATE_HANGUP) { - ftdm_set_echocancel_call_end(fchan); - } - - /* MAINTENANCE WARNING - * we're assuming an indication performed - * via state change will involve a single state change */ - ftdm_ack_indication(fchan, fchan->indication, FTDM_SUCCESS); - - hindex = (fchan->hindex == 0) ? (ftdm_array_len(fchan->history) - 1) : (fchan->hindex - 1); - - ftdm_assert(!fchan->history[hindex].end_time, "End time should be zero!\n"); - - fchan->history[hindex].end_time = ftdm_current_time_in_ms(); - fchan->last_state_change_time = ftdm_current_time_in_ms(); - - fchan->state_status = FTDM_STATE_STATUS_COMPLETED; - - diff = fchan->history[hindex].end_time - fchan->history[hindex].time; - - ftdm_log_chan_ex(fchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Completed state change from %s to %s in %"FTDM_TIME_FMT" ms\n", - ftdm_channel_state2str(fchan->last_state), ftdm_channel_state2str(state), diff); - - - if (ftdm_test_flag(fchan, FTDM_CHANNEL_BLOCKING)) { - ftdm_clear_flag(fchan, FTDM_CHANNEL_BLOCKING); - ftdm_interrupt_signal(fchan->state_completed_interrupt); - } - - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) _ftdm_set_state(const char *file, const char *func, int line, - ftdm_channel_t *fchan, ftdm_channel_state_t state) -{ - if (fchan->state_status != FTDM_STATE_STATUS_COMPLETED) { - /* the current state is not completed, setting a new state from a signaling module - when the current state is not completed is equivalent to implicitly acknowledging - the current state */ - _ftdm_channel_complete_state(file, func, line, fchan); - } - return ftdm_core_set_state(file, func, line, fchan, state, 0); -} - -static int ftdm_parse_state_map(ftdm_channel_t *ftdmchan, ftdm_channel_state_t state, ftdm_state_map_t *state_map) -{ - int x = 0, ok = 0; - ftdm_state_direction_t direction = ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? ZSD_OUTBOUND : ZSD_INBOUND; - - for(x = 0; x < FTDM_MAP_NODE_SIZE; x++) { - int i = 0, proceed = 0; - if (!state_map->nodes[x].type) { - break; - } - - if (state_map->nodes[x].direction != direction) { - continue; - } - - if (state_map->nodes[x].check_states[0] == FTDM_CHANNEL_STATE_ANY) { - proceed = 1; - } else { - for(i = 0; i < FTDM_MAP_MAX; i++) { - if (state_map->nodes[x].check_states[i] == ftdmchan->state) { - proceed = 1; - break; - } - } - } - - if (!proceed) { - continue; - } - - for(i = 0; i < FTDM_MAP_MAX; i++) { - ok = (state_map->nodes[x].type == ZSM_ACCEPTABLE); - if (state_map->nodes[x].states[i] == FTDM_CHANNEL_STATE_END) { - break; - } - if (state_map->nodes[x].states[i] == state) { - ok = !ok; - goto end; - } - } - } - end: - - return ok; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_cancel_state(const char *file, const char *func, int line, ftdm_channel_t *fchan) -{ - ftdm_time_t diff; - ftdm_channel_state_t state; - ftdm_channel_state_t last_state; - uint8_t hindex = 0; - - if (!ftdm_test_flag(fchan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_log_chan(fchan, FTDM_LOG_WARNING, "Cannot cancel state change from %s to %s, it was already processed\n", - ftdm_channel_state2str(fchan->last_state), ftdm_channel_state2str(fchan->state)); - return FTDM_FAIL; - } - - if (fchan->state_status != FTDM_STATE_STATUS_NEW) { - ftdm_log_chan(fchan, FTDM_LOG_WARNING, "Failed to cancel state change from %s to %s, state is not new anymore\n", - ftdm_channel_state2str(fchan->last_state), ftdm_channel_state2str(fchan->state)); - return FTDM_FAIL; - } - - /* compute the last history index */ - hindex = (fchan->hindex == 0) ? (ftdm_array_len(fchan->history) - 1) : (fchan->hindex - 1); - diff = fchan->history[hindex].end_time - fchan->history[hindex].time; - - /* go back in time and revert the state to the previous state */ - state = fchan->state; - last_state = fchan->last_state; - - fchan->state = fchan->last_state; - fchan->state_status = FTDM_STATE_STATUS_COMPLETED; - fchan->last_state = fchan->history[hindex].last_state; - fchan->hindex = hindex; - - /* clear the state change flag */ - ftdm_clear_flag(fchan, FTDM_CHANNEL_STATE_CHANGE); - - /* ack any pending indications as cancelled */ - ftdm_ack_indication(fchan, fchan->indication, FTDM_ECANCELED); - - /* wake up anyone sleeping waiting for the state change to complete, it won't ever be completed */ - if (ftdm_test_flag(fchan, FTDM_CHANNEL_BLOCKING)) { - ftdm_clear_flag(fchan, FTDM_CHANNEL_BLOCKING); - ftdm_interrupt_signal(fchan->state_completed_interrupt); - } - - /* NOTE - * we could potentially also take out the channel from the pendingchans queue, but I believe is easier just leave it, - * the only side effect will be a call to ftdm_channel_advance_states() for a channel that has nothing to advance */ - ftdm_log_chan_ex(fchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Cancelled state change from %s to %s in %"FTDM_TIME_FMT" ms\n", - ftdm_channel_state2str(last_state), ftdm_channel_state2str(state), diff); - - return FTDM_SUCCESS; -} - - -FT_DECLARE(ftdm_status_t) ftdm_channel_set_state(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_state_t state, int waitrq, ftdm_usrmsg_t *usrmsg) -{ - ftdm_channel_save_usrmsg(ftdmchan, usrmsg); - - if (ftdm_core_set_state(file, func, line, ftdmchan, state, waitrq) != FTDM_SUCCESS) { - ftdm_usrmsg_free(&ftdmchan->usrmsg); - } - return FTDM_SUCCESS; -} - -/* this function MUST be called with the channel lock held. If waitrq == 1, the channel will be unlocked/locked (never call it with waitrq == 1 with an lock recursivity > 1) */ -#define DEFAULT_WAIT_TIME 1000 -static ftdm_status_t ftdm_core_set_state(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_state_t state, int waitrq) -{ - ftdm_status_t status; - int ok = 1; - int waitms = DEFAULT_WAIT_TIME; - - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_READY)) { - ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_ERROR, "Ignored state change request from %s to %s, the channel is not ready\n", - ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state)); - return FTDM_FAIL; - } - - if (ftdmchan->state_status != FTDM_STATE_STATUS_COMPLETED) { - ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_ERROR, - "Ignored state change request from %s to %s, the previous state change has not been processed yet (status = %s)\n", - ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state), - ftdm_state_status2str(ftdmchan->state_status)); - return FTDM_FAIL; - } - - if (ftdmchan->state == state) { - ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "Why bother changing state from %s to %s\n", ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state)); - return FTDM_FAIL; - } - - if (!ftdmchan->state_completed_interrupt) { - status = ftdm_interrupt_create(&ftdmchan->state_completed_interrupt, FTDM_INVALID_SOCKET, FTDM_NO_FLAGS); - if (status != FTDM_SUCCESS) { - ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_CRIT, - "Failed to create state change interrupt when moving from %s to %s\n", ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state)); - return status; - } - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) { - goto perform_state_change; - } - - if (ftdmchan->span->state_map) { - ok = ftdm_parse_state_map(ftdmchan, state, ftdmchan->span->state_map); - goto end; - } - - /* basic core state validation (by-passed if the signaling module provides a state_map) */ - switch(ftdmchan->state) { - case FTDM_CHANNEL_STATE_HANGUP: - case FTDM_CHANNEL_STATE_TERMINATING: - { - ok = 0; - switch(state) { - case FTDM_CHANNEL_STATE_DOWN: - case FTDM_CHANNEL_STATE_BUSY: - case FTDM_CHANNEL_STATE_RESTART: - ok = 1; - break; - default: - break; - } - } - break; - case FTDM_CHANNEL_STATE_UP: - { - ok = 1; - switch(state) { - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - case FTDM_CHANNEL_STATE_RING: - ok = 0; - break; - default: - break; - } - } - break; - case FTDM_CHANNEL_STATE_DOWN: - { - ok = 0; - - switch(state) { - case FTDM_CHANNEL_STATE_DIALTONE: - case FTDM_CHANNEL_STATE_COLLECT: - case FTDM_CHANNEL_STATE_DIALING: - case FTDM_CHANNEL_STATE_RING: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_IDLE: - case FTDM_CHANNEL_STATE_GET_CALLERID: - case FTDM_CHANNEL_STATE_GENRING: - ok = 1; - break; - default: - break; - } - } - break; - case FTDM_CHANNEL_STATE_BUSY: - { - switch(state) { - case FTDM_CHANNEL_STATE_UP: - ok = 0; - break; - default: - break; - } - } - break; - case FTDM_CHANNEL_STATE_RING: - { - switch(state) { - case FTDM_CHANNEL_STATE_UP: - ok = 1; - break; - default: - break; - } - } - break; - default: - break; - } - -end: - - if (!ok) { - ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "VETO state change from %s to %s\n", ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state)); - goto done; - } - -perform_state_change: - - ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Changed state from %s to %s\n", ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state)); - ftdmchan->last_state = ftdmchan->state; - ftdmchan->state = state; - ftdmchan->state_status = FTDM_STATE_STATUS_NEW; - ftdmchan->history[ftdmchan->hindex].file = file; - ftdmchan->history[ftdmchan->hindex].func = func; - ftdmchan->history[ftdmchan->hindex].line = line; - ftdmchan->history[ftdmchan->hindex].state = ftdmchan->state; - ftdmchan->history[ftdmchan->hindex].last_state = ftdmchan->last_state; - ftdmchan->history[ftdmchan->hindex].time = ftdm_current_time_in_ms(); - ftdmchan->history[ftdmchan->hindex].end_time = 0; - ftdmchan->hindex++; - if (ftdmchan->hindex == ftdm_array_len(ftdmchan->history)) { - ftdmchan->hindex = 0; - } - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); - - if (ftdmchan->span->pendingchans) { - ftdm_queue_enqueue(ftdmchan->span->pendingchans, ftdmchan); - } else { - /* there is a potential deadlock here, if a signaling module is processing - * state changes while the ftdm_span_stop() function is called, the signaling - * thread will block until it can acquire the span lock, but the thread calling - * ftdm_span_stop() which holds the span lock is waiting on the signaling thread - * to finish ... The only reason to acquire the span lock is this flag, new - * signaling modules should use the pendingchans queue instead of this flag, - * as of today a few modules need still to be updated before we can get rid of - * this flag (ie, ftmod_libpri, ftmod_isdn, ftmod_analog) */ - ftdm_set_flag_locked(ftdmchan->span, FTDM_SPAN_STATE_CHANGE); - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NONBLOCK)) { - /* the channel should not block waiting for state processing */ - goto done; - } - - if (!waitrq) { - /* no waiting was requested */ - goto done; - } - - /* let's wait for the state change to be completed by the signaling stack */ - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_BLOCKING); - - ftdm_mutex_unlock(ftdmchan->mutex); - - status = ftdm_interrupt_wait(ftdmchan->state_completed_interrupt, waitms); - - ftdm_mutex_lock(ftdmchan->mutex); - - if (status != FTDM_SUCCESS) { - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_BLOCKING); - ftdm_log_chan_ex(ftdmchan, file, func, line, - FTDM_LOG_LEVEL_WARNING, "state change from %s to %s was most likely not completed after aprox %dms\n", - ftdm_channel_state2str(ftdmchan->last_state), ftdm_channel_state2str(state), DEFAULT_WAIT_TIME); - ok = 0; - goto done; - } -done: - return ok ? FTDM_SUCCESS : FTDM_FAIL; -} - -FT_DECLARE(int) ftdm_channel_get_state(const ftdm_channel_t *ftdmchan) -{ - int state; - ftdm_channel_lock(ftdmchan); - state = ftdmchan->state; - ftdm_channel_unlock(ftdmchan); - return state; -} - -FT_DECLARE(const char *) ftdm_channel_get_state_str(const ftdm_channel_t *ftdmchan) -{ - const char *state; - ftdm_channel_lock(ftdmchan); - state = ftdm_channel_state2str(ftdmchan->state); - ftdm_channel_unlock(ftdmchan); - return state; -} - -FT_DECLARE(int) ftdm_channel_get_last_state(const ftdm_channel_t *ftdmchan) -{ - int last_state; - ftdm_channel_lock(ftdmchan); - last_state = ftdmchan->last_state; - ftdm_channel_unlock(ftdmchan); - return last_state; -} - -FT_DECLARE(const char *) ftdm_channel_get_last_state_str(const ftdm_channel_t *ftdmchan) -{ - const char *state; - ftdm_channel_lock(ftdmchan); - state = ftdm_channel_state2str(ftdmchan->last_state); - ftdm_channel_unlock(ftdmchan); - return state; -} - -static void write_history_entry(const ftdm_channel_t *fchan, ftdm_stream_handle_t *stream, int i, ftdm_time_t *prevtime) -{ - char func[255]; - char line[255]; - char states[255]; - const char *filename = NULL; - snprintf(states, sizeof(states), "%-5.15s => %-5.15s", ftdm_channel_state2str(fchan->history[i].last_state), ftdm_channel_state2str(fchan->history[i].state)); - snprintf(func, sizeof(func), "[%s]", fchan->history[i].func); - filename = strrchr(fchan->history[i].file, *FTDM_PATH_SEPARATOR); - if (!filename) { - filename = fchan->history[i].file; - } else { - filename++; - } - if (!(*prevtime)) { - *prevtime = fchan->history[i].time; - } - snprintf(line, sizeof(func), "[%s:%d]", filename, fchan->history[i].line); - stream->write_function(stream, "%-30.30s %-30.30s %-30.30s %lums\n", states, func, line, (fchan->history[i].time - *prevtime)); - *prevtime = fchan->history[i].time; -} - -FT_DECLARE(char *) ftdm_channel_get_history_str(const ftdm_channel_t *fchan) -{ - uint8_t i = 0; - ftdm_time_t currtime = 0; - ftdm_time_t prevtime = 0; - - ftdm_stream_handle_t stream = { 0 }; - FTDM_STANDARD_STREAM(stream); - if (!fchan->history[0].file) { - stream.write_function(&stream, "-- No state history --\n"); - return stream.data; - } - - stream.write_function(&stream, "%-30.30s %-30.30s %-30.30s %s", - "-- States --", "-- Function --", "-- Location --", "-- Time Offset --\n"); - - for (i = fchan->hindex; i < ftdm_array_len(fchan->history); i++) { - if (!fchan->history[i].file) { - break; - } - write_history_entry(fchan, &stream, i, &prevtime); - } - - for (i = 0; i < fchan->hindex; i++) { - write_history_entry(fchan, &stream, i, &prevtime); - } - - currtime = ftdm_current_time_in_ms(); - - stream.write_function(&stream, "\nTime since last state change: %lums\n", (currtime - prevtime)); - - return stream.data; -} - -FT_DECLARE(ftdm_status_t) ftdm_channel_advance_states(ftdm_channel_t *fchan) -{ - ftdm_channel_state_t state; - - ftdm_assert_return(fchan->span->state_processor, FTDM_FAIL, "Cannot process states without a state processor!\n"); - - while (fchan->state_status == FTDM_STATE_STATUS_NEW) { - state = fchan->state; - ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Executing state processor for %s\n", ftdm_channel_state2str(fchan->state)); - fchan->span->state_processor(fchan); - if (state == fchan->state && fchan->state_status == FTDM_STATE_STATUS_NEW) { - /* if the state did not change and is still NEW, the state status must go to PROCESSED - * otherwise we don't touch it since is a new state and the old state was - * already completed implicitly by the state_processor() function via some internal - * call to ftdm_set_state() */ - fchan->state_status = FTDM_STATE_STATUS_PROCESSED; - } - } - - return FTDM_SUCCESS; -} - -FT_DECLARE(int) ftdm_check_state_all(ftdm_span_t *span, ftdm_channel_state_t state) -{ - uint32_t j; - for(j = 1; j <= span->chan_count; j++) { - if (span->channels[j]->state != state || ftdm_test_flag(span->channels[j], FTDM_CHANNEL_STATE_CHANGE)) { - return 0; - } - } - return 1; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftdm_threadmutex.c b/libs/freetdm/src/ftdm_threadmutex.c deleted file mode 100644 index 6dc2c64f8f..0000000000 --- a/libs/freetdm/src/ftdm_threadmutex.c +++ /dev/null @@ -1,635 +0,0 @@ -/* - * Cross Platform Thread/Mutex abstraction - * Copyright(C) 2007 Michael Jerris - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so. - * - * This work is provided under this license on an "as is" basis, without warranty of any kind, - * either expressed or implied, including, without limitation, warranties that the covered code - * is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire - * risk as to the quality and performance of the covered code is with you. Should any covered - * code prove defective in any respect, you (not the initial developer or any other contributor) - * assume the cost of any necessary servicing, repair or correction. This disclaimer of warranty - * constitutes an essential part of this license. No use of any covered code is authorized hereunder - * except under this disclaimer. - * - * Contributors: - * - * Moises Silva - * - */ - -#ifdef WIN32 -# if (_WIN32_WINNT < 0x0400) -# error "Need to target at least Windows 95/WINNT 4.0 because TryEnterCriticalSection is needed" -# endif -# include -#endif -/*#define FTDM_DEBUG_MUTEX 0*/ - -#include "private/ftdm_core.h" -#include "ftdm_threadmutex.h" - -#ifdef WIN32 -#include - -#define FTDM_THREAD_CALLING_CONVENTION __stdcall - -struct ftdm_mutex { - CRITICAL_SECTION mutex; -}; - -#else -#include -#include - -#define FTDM_THREAD_CALLING_CONVENTION - -#ifdef FTDM_DEBUG_MUTEX -#define FTDM_MUTEX_MAX_REENTRANCY 30 -typedef struct ftdm_lock_entry { - const char *file; - const char *func; - uint32_t line; -} ftdm_lock_entry_t; - -typedef struct ftdm_lock_history { - ftdm_lock_entry_t locked; - ftdm_lock_entry_t unlocked; -} ftdm_lock_history_t; -#endif - -struct ftdm_mutex { - pthread_mutex_t mutex; -#ifdef FTDM_DEBUG_MUTEX - ftdm_lock_history_t lock_history[FTDM_MUTEX_MAX_REENTRANCY]; - uint8_t reentrancy; -#endif -}; - -#endif - -struct ftdm_interrupt { - ftdm_socket_t device; - ftdm_wait_flag_t device_input_flags; - ftdm_wait_flag_t device_output_flags; -#ifdef WIN32 - /* for generic interruption */ - HANDLE event; -#else - /* In theory we could be using thread conditions for generic interruption, - * however, Linux does not have a primitive like Windows WaitForMultipleObjects - * to wait for both thread condition and file descriptors, therefore we decided - * to use a dummy pipe for generic interruption/condition logic - * */ - int readfd; - int writefd; -#endif -}; - -struct ftdm_thread { -#ifdef WIN32 - void *handle; -#else - pthread_t handle; -#endif - void *private_data; - ftdm_thread_function_t function; - ftdm_size_t stack_size; -#ifndef WIN32 - pthread_attr_t attribute; -#endif -}; - -ftdm_size_t thread_default_stacksize = 0; - -FT_DECLARE(void) ftdm_thread_override_default_stacksize(ftdm_size_t size) -{ - thread_default_stacksize = size; -} - -static void * FTDM_THREAD_CALLING_CONVENTION thread_launch(void *args) -{ - void *exit_val; - ftdm_thread_t *thread = (ftdm_thread_t *)args; - exit_val = thread->function(thread, thread->private_data); -#ifndef WIN32 - pthread_attr_destroy(&thread->attribute); -#endif - ftdm_safe_free(thread); - - return exit_val; -} - -FT_DECLARE(ftdm_status_t) ftdm_thread_create_detached(ftdm_thread_function_t func, void *data) -{ - return ftdm_thread_create_detached_ex(func, data, thread_default_stacksize); -} - -FT_DECLARE(ftdm_status_t) ftdm_thread_create_detached_ex(ftdm_thread_function_t func, void *data, ftdm_size_t stack_size) -{ - ftdm_thread_t *thread = NULL; - ftdm_status_t status = FTDM_FAIL; - - if (!func || !(thread = (ftdm_thread_t *)ftdm_calloc(1, sizeof(ftdm_thread_t)))) { - goto done; - } - - thread->private_data = data; - thread->function = func; - thread->stack_size = stack_size; - -#if defined(WIN32) - thread->handle = (void *)_beginthreadex(NULL, (unsigned)thread->stack_size, (unsigned int (__stdcall *)(void *))thread_launch, thread, 0, NULL); - if (!thread->handle) { - goto fail; - } - CloseHandle(thread->handle); - - status = FTDM_SUCCESS; - goto done; -#else - - if (pthread_attr_init(&thread->attribute) != 0) goto fail; - - if (pthread_attr_setdetachstate(&thread->attribute, PTHREAD_CREATE_DETACHED) != 0) goto failpthread; - - if (thread->stack_size && pthread_attr_setstacksize(&thread->attribute, thread->stack_size) != 0) goto failpthread; - - if (pthread_create(&thread->handle, &thread->attribute, thread_launch, thread) != 0) goto failpthread; - - status = FTDM_SUCCESS; - goto done; - failpthread: - pthread_attr_destroy(&thread->attribute); -#endif - - fail: - if (thread) { - ftdm_safe_free(thread); - } - done: - return status; -} - - -FT_DECLARE(ftdm_status_t) ftdm_mutex_create(ftdm_mutex_t **mutex) -{ - ftdm_status_t status = FTDM_FAIL; -#ifndef WIN32 - pthread_mutexattr_t attr; -#endif - ftdm_mutex_t *check = NULL; - - check = (ftdm_mutex_t *)ftdm_calloc(1, sizeof(**mutex)); - if (!check) - goto done; -#ifdef WIN32 - InitializeCriticalSection(&check->mutex); -#else - if (pthread_mutexattr_init(&attr)) - goto done; - - if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) - goto fail; - - if (pthread_mutex_init(&check->mutex, &attr)) - goto fail; - - goto success; - - fail: - pthread_mutexattr_destroy(&attr); - goto done; - - success: -#endif - *mutex = check; - status = FTDM_SUCCESS; - - done: - return status; -} - -FT_DECLARE(ftdm_status_t) ftdm_mutex_destroy(ftdm_mutex_t **mutex) -{ - ftdm_mutex_t *mp = *mutex; - *mutex = NULL; - if (!mp) { - return FTDM_FAIL; - } -#ifdef WIN32 - DeleteCriticalSection(&mp->mutex); -#else - if (pthread_mutex_destroy(&mp->mutex)) - return FTDM_FAIL; -#endif - ftdm_safe_free(mp); - return FTDM_SUCCESS; -} - -#define ADD_LOCK_HISTORY(mutex, file, line, func) \ - { \ - if ((mutex)->reentrancy < FTDM_MUTEX_MAX_REENTRANCY) { \ - (mutex)->lock_history[mutex->reentrancy].locked.file = (file); \ - (mutex)->lock_history[mutex->reentrancy].locked.func = (func); \ - (mutex)->lock_history[mutex->reentrancy].locked.line = (line); \ - (mutex)->lock_history[mutex->reentrancy].unlocked.file = NULL; \ - (mutex)->lock_history[mutex->reentrancy].unlocked.func = NULL; \ - (mutex)->lock_history[mutex->reentrancy].unlocked.line = 0; \ - (mutex)->reentrancy++; \ - if ((mutex)->reentrancy == FTDM_MUTEX_MAX_REENTRANCY) { \ - ftdm_log((file), (func), (line), FTDM_LOG_LEVEL_ERROR, "Max reentrancy reached for mutex %p\n", (mutex)); \ - } \ - } \ - } - -FT_DECLARE(ftdm_status_t) _ftdm_mutex_lock(const char *file, int line, const char *func, ftdm_mutex_t *mutex) -{ -#ifdef WIN32 - ftdm_unused_arg(file); - ftdm_unused_arg(line); - ftdm_unused_arg(func); - - EnterCriticalSection(&mutex->mutex); -#else - int err; - if ((err = pthread_mutex_lock(&mutex->mutex))) { - ftdm_log(file, func, line, FTDM_LOG_LEVEL_ERROR, "Failed to lock mutex %d:%s\n", err, strerror(err)); - return FTDM_FAIL; - } -#endif -#ifdef FTDM_DEBUG_MUTEX - ADD_LOCK_HISTORY(mutex, file, line, func); -#endif - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) _ftdm_mutex_trylock(const char *file, int line, const char *func, ftdm_mutex_t *mutex) -{ - ftdm_unused_arg(file); - ftdm_unused_arg(line); - ftdm_unused_arg(func); -#ifdef WIN32 - if (!TryEnterCriticalSection(&mutex->mutex)) - return FTDM_FAIL; -#else - if (pthread_mutex_trylock(&mutex->mutex)) - return FTDM_FAIL; -#endif -#ifdef FTDM_DEBUG_MUTEX - ADD_LOCK_HISTORY(mutex, file, line, func); -#endif - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) _ftdm_mutex_unlock(const char *file, int line, const char *func, ftdm_mutex_t *mutex) -{ -#ifdef FTDM_DEBUG_MUTEX - int i = 0; - if (mutex->reentrancy == 0) { - ftdm_log(file, func, line, FTDM_LOG_LEVEL_ERROR, "Cannot unlock something that is not locked!\n"); - return FTDM_FAIL; - } - i = mutex->reentrancy - 1; - /* I think this is a fair assumption when debugging */ - if (func != mutex->lock_history[i].locked.func) { - ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "Mutex %p was suspiciously locked at %s->%s:%d but unlocked at %s->%s:%d!\n", - mutex, mutex->lock_history[i].locked.func, mutex->lock_history[i].locked.file, mutex->lock_history[i].locked.line, - func, file, line); - } - mutex->lock_history[i].unlocked.file = file; - mutex->lock_history[i].unlocked.line = line; - mutex->lock_history[i].unlocked.func = func; - mutex->reentrancy--; -#endif -#ifdef WIN32 - ftdm_unused_arg(file); - ftdm_unused_arg(line); - ftdm_unused_arg(func); - - LeaveCriticalSection(&mutex->mutex); -#else - if (pthread_mutex_unlock(&mutex->mutex)) { - ftdm_log(file, func, line, FTDM_LOG_LEVEL_ERROR, "Failed to unlock mutex: %s\n", strerror(errno)); -#ifdef FTDM_DEBUG_MUTEX - mutex->reentrancy++; -#endif - return FTDM_FAIL; - } -#endif - return FTDM_SUCCESS; -} - - -FT_DECLARE(ftdm_status_t) ftdm_interrupt_create(ftdm_interrupt_t **ininterrupt, ftdm_socket_t device, ftdm_wait_flag_t device_flags) -{ - ftdm_status_t status = FTDM_SUCCESS; - ftdm_interrupt_t *interrupt = NULL; -#ifndef WIN32 - int fds[2]; -#endif - - ftdm_assert_return(ininterrupt != NULL, FTDM_FAIL, "interrupt double pointer is null!\n"); - - interrupt = ftdm_calloc(1, sizeof(*interrupt)); - if (!interrupt) { - ftdm_log(FTDM_LOG_ERROR, "Failed to allocate interrupt memory\n"); - return FTDM_ENOMEM; - } - - interrupt->device = device; - interrupt->device_input_flags = device_flags; -#ifdef WIN32 - interrupt->event = CreateEvent(NULL, FALSE, FALSE, NULL); - if (!interrupt->event) { - ftdm_log(FTDM_LOG_ERROR, "Failed to allocate interrupt event\n"); - status = FTDM_ENOMEM; - goto failed; - } -#else - if (pipe(fds)) { - ftdm_log(FTDM_LOG_ERROR, "Failed to allocate interrupt pipe: %s\n", strerror(errno)); - status = FTDM_FAIL; - goto failed; - } - interrupt->readfd = fds[0]; - interrupt->writefd = fds[1]; -#endif - - *ininterrupt = interrupt; - return FTDM_SUCCESS; - -failed: - if (interrupt) { -#ifndef WIN32 - if (interrupt->readfd) { - close(interrupt->readfd); - close(interrupt->writefd); - interrupt->readfd = -1; - interrupt->writefd = -1; - } -#endif - ftdm_safe_free(interrupt); - } - return status; -} - -#define ONE_BILLION 1000000000 - -FT_DECLARE(ftdm_status_t) ftdm_interrupt_wait(ftdm_interrupt_t *interrupt, int ms) -{ - int num = 1; -#ifdef WIN32 - DWORD res = 0; - HANDLE ints[2]; -#else - int res = 0; - struct pollfd ints[2]; - char pipebuf[255]; -#endif - - ftdm_assert_return(interrupt != NULL, FTDM_FAIL, "Interrupt is null!\n"); - - interrupt->device_output_flags = FTDM_NO_FLAGS; - /* start implementation */ -#ifdef WIN32 - ints[0] = interrupt->event; - if (interrupt->device != FTDM_INVALID_SOCKET) { - num++; - ints[1] = interrupt->device; - ftdm_log(FTDM_LOG_CRIT, "implement me! (Windows support for device_output_flags member!)\n"); - } - res = WaitForMultipleObjects(num, ints, FALSE, ms >= 0 ? ms : INFINITE); - switch (res) { - case WAIT_TIMEOUT: - return FTDM_TIMEOUT; - case WAIT_FAILED: - case WAIT_ABANDONED: /* is it right to fail with abandoned? */ - return FTDM_FAIL; - default: - if (res >= (sizeof(ints)/sizeof(ints[0]))) { - ftdm_log(FTDM_LOG_ERROR, "Error waiting for freetdm interrupt event (WaitForSingleObject returned %d)\n", res); - return FTDM_FAIL; - } - return FTDM_SUCCESS; - } -#else -pollagain: - ints[0].fd = interrupt->readfd; - ints[0].events = POLLIN; - ints[0].revents = 0; - - if (interrupt->device != FTDM_INVALID_SOCKET) { - num++; - ints[1].fd = interrupt->device; - ints[1].events = interrupt->device_input_flags; - ints[1].revents = 0; - } - - res = poll(ints, num, ms); - - if (res == -1) { - if (errno == EINTR) { - goto pollagain; - } - ftdm_log(FTDM_LOG_CRIT, "interrupt poll failed (%s)\n", strerror(errno)); - return FTDM_FAIL; - } - - if (res == 0) { - return FTDM_TIMEOUT; - } - - if (ints[0].revents & POLLIN) { - res = read(ints[0].fd, pipebuf, sizeof(pipebuf)); - if (res == -1) { - ftdm_log(FTDM_LOG_CRIT, "reading interrupt descriptor failed (%s)\n", strerror(errno)); - } - } - if (interrupt->device != FTDM_INVALID_SOCKET) { - if (ints[1].revents & POLLIN) { - interrupt->device_output_flags |= FTDM_READ; - } - if (ints[1].revents & POLLOUT) { - interrupt->device_output_flags |= FTDM_WRITE; - } - if (ints[1].revents & POLLPRI) { - interrupt->device_output_flags |= FTDM_EVENTS; - } - } - return FTDM_SUCCESS; -#endif -} - -FT_DECLARE(ftdm_status_t) ftdm_interrupt_signal(ftdm_interrupt_t *interrupt) -{ - ftdm_assert_return(interrupt != NULL, FTDM_FAIL, "Interrupt is null!\n"); -#ifdef WIN32 - if (!SetEvent(interrupt->event)) { - ftdm_log(FTDM_LOG_ERROR, "Failed to signal interrupt\n"); - return FTDM_FAIL; - - } -#else - int err; - struct pollfd testpoll; - testpoll.revents = 0; - testpoll.events = POLLIN; - testpoll.fd = interrupt->readfd; - err = poll(&testpoll, 1, 0); - if (err == 0 && !(testpoll.revents & POLLIN)) { - /* we just try to notify if there is nothing on the read fd already, - * otherwise users that never call interrupt wait eventually will - * eventually have the pipe buffer filled */ - if ((err = write(interrupt->writefd, "w", 1)) != 1) { - ftdm_log(FTDM_LOG_ERROR, "Failed to signal interrupt: %s\n", strerror(errno)); - return FTDM_FAIL; - } - } -#endif - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_interrupt_destroy(ftdm_interrupt_t **ininterrupt) -{ - ftdm_interrupt_t *interrupt = NULL; - ftdm_assert_return(ininterrupt != NULL, FTDM_FAIL, "Interrupt null when destroying!\n"); - interrupt = *ininterrupt; -#ifdef WIN32 - CloseHandle(interrupt->event); -#else - close(interrupt->readfd); - close(interrupt->writefd); - - interrupt->readfd = -1; - interrupt->writefd = -1; -#endif - ftdm_safe_free(interrupt); - *ininterrupt = NULL; - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interrupts[], ftdm_size_t size, int ms) -{ - int numdevices = 0; - unsigned i = 0; - -#if defined(__WINDOWS__) - DWORD res = 0; - HANDLE ints[20]; - if (size > (ftdm_array_len(ints)/2)) { - /* improve if needed: dynamically allocate the list of interrupts *only* when exceeding the default size */ - ftdm_log(FTDM_LOG_CRIT, "Unsupported size of interrupts: %d, implement me!\n", size); - return FTDM_FAIL; - } - - for (i = 0; i < size; i++) { - ints[i] = interrupts[i]->event; - interrupts[i]->device_output_flags = FTDM_NO_FLAGS; - if (interrupts[i]->device != FTDM_INVALID_SOCKET) { - /* WARNING: if the device is ready for data we must implement for Windows the device_output_flags member */ - ints[size+numdevices] = interrupts[i]->device; - numdevices++; - ftdm_log(FTDM_LOG_CRIT, "implement me! (Windows support for device_data_ready member!)\n", size); - } - } - - res = WaitForMultipleObjects((DWORD)size+numdevices, ints, FALSE, ms >= 0 ? ms : INFINITE); - - switch (res) { - case WAIT_TIMEOUT: - return FTDM_TIMEOUT; - case WAIT_FAILED: - case WAIT_ABANDONED: /* is it right to fail with abandoned? */ - return FTDM_FAIL; - default: - if (res >= (size+numdevices)) { - ftdm_log(FTDM_LOG_ERROR, "Error waiting for freetdm interrupt event (WaitForSingleObject returned %d)\n", res); - return FTDM_FAIL; - } - /* fall-through to FTDM_SUCCESS at the end of the function */ - } -#elif defined(__linux__) || defined(__FreeBSD__) - int res = 0; - char pipebuf[255]; - struct pollfd ints[size*2]; - - memset(&ints, 0, sizeof(ints)); -pollagain: - for (i = 0; i < size; i++) { - ints[i].events = POLLIN; - ints[i].revents = 0; - ints[i].fd = interrupts[i]->readfd; - interrupts[i]->device_output_flags = FTDM_NO_FLAGS; - if (interrupts[i]->device != FTDM_INVALID_SOCKET) { - ints[size+numdevices].events = interrupts[i]->device_input_flags; - ints[size+numdevices].revents = 0; - ints[size+numdevices].fd = interrupts[i]->device; - numdevices++; - } - } - - res = poll(ints, size + numdevices, ms); - if (res == -1) { - if (errno == EINTR) { - goto pollagain; - } - ftdm_log(FTDM_LOG_CRIT, "interrupt poll failed (%s)\n", strerror(errno)); - return FTDM_FAIL; - } - - if (res == 0) { - return FTDM_TIMEOUT; - } - - /* check for events in the pipes and in the devices, but service only the pipes */ - numdevices = 0; - for (i = 0; i < size; i++) { - if (ints[i].revents & POLLIN) { - res = read(ints[i].fd, pipebuf, sizeof(pipebuf)); - if (res == -1) { - ftdm_log(FTDM_LOG_CRIT, "reading interrupt descriptor failed (%s)\n", strerror(errno)); - } - } - if (interrupts[i]->device != FTDM_INVALID_SOCKET) { - if (ints[size+numdevices].revents & POLLIN) { - interrupts[i]->device_output_flags |= FTDM_READ; - } - if (ints[size+numdevices].revents & POLLOUT) { - interrupts[i]->device_output_flags |= FTDM_WRITE; - } - if (ints[size+numdevices].revents & POLLPRI) { - interrupts[i]->device_output_flags |= FTDM_EVENTS; - } - numdevices++; - } - } -#else - /* for MacOS compilation, unused vars */ - numdevices = i; -#endif - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_wait_flag_t) ftdm_interrupt_device_ready(ftdm_interrupt_t *interrupt) -{ -#if defined(__WINDOWS__) - /* device output flags are not currently filled for Windows upon returning from a wait function */ - ftdm_log(FTDM_LOG_CRIT, "IMPLEMENT ME!\n"); -#endif - return interrupt->device_output_flags; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftdm_variables.c b/libs/freetdm/src/ftdm_variables.c deleted file mode 100644 index a2899c4ca9..0000000000 --- a/libs/freetdm/src/ftdm_variables.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * David Yat Sin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Contributors: - * - * Moises Silva - * - */ - -#include "private/ftdm_core.h" - -FT_DECLARE(ftdm_status_t) ftdm_sigmsg_add_var(ftdm_sigmsg_t *sigmsg, const char *var_name, const char *value) -{ - char *t_name = 0, *t_val = 0; - - if (!sigmsg || !var_name || !value) { - return FTDM_FAIL; - } - - if (!sigmsg->variables) { - /* initialize on first use */ - sigmsg->variables = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); - ftdm_assert_return(sigmsg->variables, FTDM_FAIL, "Failed to create hash table\n"); - } - - t_name = ftdm_strdup(var_name); - t_val = ftdm_strdup(value); - hashtable_insert(sigmsg->variables, t_name, t_val, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_FLAG_FREE_VALUE); - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_sigmsg_remove_var(ftdm_sigmsg_t *sigmsg, const char *var_name) -{ - if (sigmsg && sigmsg->variables) { - hashtable_remove(sigmsg->variables, (void *)var_name); - } - return FTDM_SUCCESS; -} - -FT_DECLARE(const char *) ftdm_sigmsg_get_var(ftdm_sigmsg_t *sigmsg, const char *var_name) -{ - const char *var = NULL; - - if (!sigmsg || !sigmsg->variables || !var_name) { - return NULL; - } - - var = (const char *)hashtable_search(((struct hashtable*)sigmsg->variables), (void *)var_name); - return var; -} - -FT_DECLARE(ftdm_iterator_t *) ftdm_sigmsg_get_var_iterator(const ftdm_sigmsg_t *sigmsg, ftdm_iterator_t *iter) -{ - ftdm_hash_iterator_t *hashiter = NULL; - if (!sigmsg) { - return NULL; - } - - hashiter = sigmsg->variables == NULL ? NULL : hashtable_first(sigmsg->variables); - - if (hashiter == NULL) { - return NULL; - } - - if (!(iter = ftdm_get_iterator(FTDM_ITERATOR_VARS, iter))) { - return NULL; - } - iter->pvt.hashiter = hashiter; - return iter; -} - -FT_DECLARE(ftdm_status_t) ftdm_get_current_var(ftdm_iterator_t *iter, const char **var_name, const char **var_val) -{ - const void *key = NULL; - void *val = NULL; - - *var_name = NULL; - *var_val = NULL; - - ftdm_assert_return(iter && (iter->type == FTDM_ITERATOR_VARS) && iter->pvt.hashiter, FTDM_FAIL, "Cannot get variable from invalid iterator!\n"); - - hashtable_this(iter->pvt.hashiter, &key, NULL, &val); - - *var_name = key; - *var_val = val; - - return FTDM_SUCCESS; -} - - -FT_DECLARE(ftdm_status_t) ftdm_usrmsg_add_var(ftdm_usrmsg_t *usrmsg, const char *var_name, const char *value) -{ - char *t_name = 0, *t_val = 0; - - if (!usrmsg || !var_name || !value) { - return FTDM_FAIL; - } - - if (!usrmsg->variables) { - /* initialize on first use */ - usrmsg->variables = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); - ftdm_assert_return(usrmsg->variables, FTDM_FAIL, "Failed to create hash table\n"); - } - - t_name = ftdm_strdup(var_name); - t_val = ftdm_strdup(value); - hashtable_insert(usrmsg->variables, t_name, t_val, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_FLAG_FREE_VALUE); - return FTDM_SUCCESS; -} - -FT_DECLARE(const char *) ftdm_usrmsg_get_var(ftdm_usrmsg_t *usrmsg, const char *var_name) -{ - const char *var = NULL; - - if (!usrmsg || !usrmsg->variables || !var_name) { - return NULL; - } - - var = (const char *)hashtable_search(((struct hashtable*)usrmsg->variables), (void *)var_name); - return var; -} diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h b/libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h deleted file mode 100644 index 2bc1717556..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef FTDM_ANALOG_H -#define FTDM_ANALOG_H -#include "freetdm.h" - -typedef enum { - FTDM_ANALOG_RUNNING = (1 << 0), - FTDM_ANALOG_CALLERID = (1 << 1), - FTDM_ANALOG_ANSWER_POLARITY_REVERSE = (1 << 2), - FTDM_ANALOG_HANGUP_POLARITY_REVERSE = (1 << 3), - FTDM_ANALOG_POLARITY_CALLERID = (1 << 4) -} ftdm_analog_flag_t; - -#define FTDM_MAX_HOTLINE_STR 32 -#define MAX_DTMF 256 - -struct ftdm_analog_data { - uint32_t flags; - uint32_t max_dialstr; - uint32_t wait_dialtone_timeout; - uint32_t polarity_delay; - uint32_t digit_timeout; - char hotline[FTDM_MAX_HOTLINE_STR]; -}; - -/* Analog flags to be set in the sflags (signaling flags) channel memeber */ -#define AF_POLARITY_REVERSE (1 << 0) - -static void *ftdm_analog_run(ftdm_thread_t *me, void *obj); -typedef struct ftdm_analog_data ftdm_analog_data_t; - -#endif - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2008.vcproj deleted file mode 100644 index 09349fc05f..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2008.vcproj +++ /dev/null @@ -1,353 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj.filters deleted file mode 100644 index b6fed5927a..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj.filters +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Source Files - - - - - Header Files - - - \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c deleted file mode 100644 index 065e12a0d0..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c +++ /dev/null @@ -1,1270 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "private/ftdm_core.h" -#include "ftdm_analog.h" - -#ifndef localtime_r -struct tm * localtime_r(const time_t *clock, struct tm *result); -#endif - -static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj); - -/** - * \brief Starts an FXO channel thread (outgoing call) - * \param ftdmchan Channel to initiate call on - * \return Success or failure - * - * Initialises state, starts tone progress detection and runs the channel in a new a thread. - */ -static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(analog_fxo_outgoing_call) -{ - ftdm_analog_data_t *analog_data = ftdmchan->span->signal_data; - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INTHREAD)) { - ftdm_channel_clear_needed_tones(ftdmchan); - ftdm_channel_clear_detected_tones(ftdmchan); - - ftdm_channel_command(ftdmchan, FTDM_COMMAND_OFFHOOK, NULL); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_PROGRESS_DETECT, NULL); - if (analog_data->wait_dialtone_timeout) { - ftdmchan->needed_tones[FTDM_TONEMAP_DIAL] = 1; - } - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DIALING); - ftdm_thread_create_detached(ftdm_analog_channel_run, ftdmchan); - return FTDM_SUCCESS; - } - - return FTDM_FAIL; -} - -/** - * \brief Starts an FXS channel thread (outgoing call) - * \param ftdmchan Channel to initiate call on - * \return Success or failure - * - * Indicates call waiting if channel is already in use, otherwise runs the channel in a new thread. - */ -static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(analog_fxs_outgoing_call) -{ - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INTHREAD)) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CALLWAITING); - } else { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_GENRING); - ftdm_thread_create_detached(ftdm_analog_channel_run, ftdmchan); - } - - return FTDM_SUCCESS; -} - -/** - * \brief Returns the signalling status on a channel - * \param ftdmchan Channel to get status on - * \param status Pointer to set signalling status - * \return Success or failure - */ - -static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(analog_get_channel_sig_status) -{ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) { - *status = FTDM_SIG_STATE_DOWN; - return FTDM_SUCCESS; - } - *status = FTDM_SIG_STATE_UP; - return FTDM_SUCCESS; -} - -/** - * \brief Returns the signalling status on a span - * \param span Span to get status on - * \param status Pointer to set signalling status - * \return Success or failure - */ - -static FIO_SPAN_GET_SIG_STATUS_FUNCTION(analog_get_span_sig_status) -{ - ftdm_iterator_t *citer = NULL; - ftdm_iterator_t *chaniter = ftdm_span_get_chan_iterator(span, NULL); - if (!chaniter) { - ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name); - return FTDM_FAIL; - } - /* if ALL channels are in alarm, report DOWN, UP otherwise. */ - *status = FTDM_SIG_STATE_DOWN; - for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) { - ftdm_channel_t *fchan = ftdm_iterator_current(citer); - ftdm_channel_lock(fchan); - if (!ftdm_test_flag(fchan, FTDM_CHANNEL_IN_ALARM)) { - *status = FTDM_SIG_STATE_UP; - ftdm_channel_unlock(fchan); - break; - } - ftdm_channel_unlock(fchan); - } - ftdm_iterator_free(chaniter); - return FTDM_SUCCESS; -} - -/** - * \brief Starts an analog span thread (monitor) - * \param span Span to monitor - * \return Success or failure - */ -static ftdm_status_t ftdm_analog_start(ftdm_span_t *span) -{ - ftdm_analog_data_t *analog_data = span->signal_data; - ftdm_set_flag(analog_data, FTDM_ANALOG_RUNNING); - return ftdm_thread_create_detached(ftdm_analog_run, span); -} - -/** - * \brief Stops the analog span thread (monitor) - * \param span Span to stop - * \return Success or failure - */ -static ftdm_status_t ftdm_analog_stop(ftdm_span_t *span) -{ - ftdm_analog_data_t *analog_data = span->signal_data; - int32_t sanity = 100; - while (ftdm_test_flag(analog_data, FTDM_ANALOG_RUNNING) && sanity--) { - ftdm_sleep(100); - ftdm_log(FTDM_LOG_DEBUG, "Waiting for analog thread for span %s to stop\n", span->name); - } - - if (!sanity) { - ftdm_log(FTDM_LOG_ERROR, "The analog thread for span %s is probably still running, we may crash :(\n", span->name); - return FTDM_FAIL; - } - return FTDM_SUCCESS; -} - -/** - * \brief Initialises an analog span from configuration variables - * \param span Span to configure - * \param sig_cb Callback function for event signals - * \param ap List of configuration variables - * \return Success or failure - */ -static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span) -//ftdm_status_t ftdm_analog_configure_span(ftdm_span_t *span, char *tonemap, uint32_t digit_timeout, uint32_t max_dialstr, fio_signal_cb_t sig_cb) -{ - ftdm_analog_data_t *analog_data; - const char *tonemap = "us"; - const char *hotline = ""; - uint32_t digit_timeout = 10; - uint32_t wait_dialtone_timeout = 5000; - uint32_t max_dialstr = MAX_DTMF; - uint32_t polarity_delay = 600; - const char *var, *val; - int *intval; - uint32_t flags = FTDM_ANALOG_CALLERID; - int callwaiting = 1; - unsigned int i = 0; - - assert(sig_cb != NULL); - ftdm_log(FTDM_LOG_DEBUG, "Configuring span %s for analog signaling ...\n", span->name); - - if (span->signal_type) { - ftdm_log(FTDM_LOG_ERROR, "Span %s is already configured for signaling %d\n", span->name, span->signal_type); - snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling."); - return FTDM_FAIL; - } - - analog_data = ftdm_malloc(sizeof(*analog_data)); - - ftdm_assert_return(analog_data != NULL, FTDM_FAIL, "malloc failure\n"); - - memset(analog_data, 0, sizeof(*analog_data)); - - while ((var = va_arg(ap, char *))) { - ftdm_log(FTDM_LOG_DEBUG, "Analog config var = %s\n", var); - if (!strcasecmp(var, "tonemap")) { - if (!(val = va_arg(ap, char *))) { - break; - } - tonemap = val; - } else if (!strcasecmp(var, "digit_timeout")) { - if (!(intval = va_arg(ap, int *))) { - break; - } - digit_timeout = *intval; - } else if (!strcasecmp(var, "wait_dialtone_timeout")) { - if (!(intval = va_arg(ap, int *))) { - break; - } - wait_dialtone_timeout = ftdm_max(0, *intval); - ftdm_log(FTDM_LOG_DEBUG, "Wait dial tone ms = %d\n", wait_dialtone_timeout); - } else if (!strcasecmp(var, "enable_callerid")) { - if (!(val = va_arg(ap, char *))) { - break; - } - - if (ftdm_true(val)) { - flags |= FTDM_ANALOG_CALLERID; - } else { - flags &= ~FTDM_ANALOG_CALLERID; - } - } else if (!strcasecmp(var, "answer_polarity_reverse")) { - if (!(val = va_arg(ap, char *))) { - break; - } - if (ftdm_true(val)) { - flags |= FTDM_ANALOG_ANSWER_POLARITY_REVERSE; - } else { - flags &= ~FTDM_ANALOG_ANSWER_POLARITY_REVERSE; - } - } else if (!strcasecmp(var, "hangup_polarity_reverse")) { - if (!(val = va_arg(ap, char *))) { - break; - } - if (ftdm_true(val)) { - flags |= FTDM_ANALOG_HANGUP_POLARITY_REVERSE; - } else { - flags &= ~FTDM_ANALOG_HANGUP_POLARITY_REVERSE; - } - } else if (!strcasecmp(var, "polarity_delay")) { - if (!(intval = va_arg(ap, int *))) { - break; - } - polarity_delay = *intval; - } else if (!strcasecmp(var, "callwaiting")) { - if (!(intval = va_arg(ap, int *))) { - break; - } - callwaiting = *intval; - } else if (!strcasecmp(var, "max_dialstr")) { - if (!(intval = va_arg(ap, int *))) { - break; - } - max_dialstr = *intval; - } else if (!strcasecmp(var, "hotline")) { - if (!(val = va_arg(ap, char *))) { - break; - } - hotline = val; - } else if (!strcasecmp(var, "polarity_callerid")) { - if (!(val = va_arg(ap, char *))) { - break; - } - if (ftdm_true(val)) { - flags |= FTDM_ANALOG_POLARITY_CALLERID; - } else { - flags &= ~FTDM_ANALOG_POLARITY_CALLERID; - } - } else { - ftdm_log(FTDM_LOG_ERROR, "Unknown parameter %s in span %s\n", var, span->name); - } - } - - if (digit_timeout < 2000 || digit_timeout > 10000) { - digit_timeout = 2000; - } - - if ((max_dialstr < 1 && !strlen(hotline)) || max_dialstr > MAX_DTMF) { - max_dialstr = MAX_DTMF; - } - - if (callwaiting) { - for (i = 1; i <= span->chan_count; i++) { - ftdm_log_chan_msg(span->channels[i], FTDM_LOG_DEBUG, "Enabled call waiting\n"); - ftdm_channel_set_feature(span->channels[i], FTDM_CHANNEL_FEATURE_CALLWAITING); - } - } - - span->start = ftdm_analog_start; - span->stop = ftdm_analog_stop; - analog_data->flags = flags; - analog_data->digit_timeout = digit_timeout; - analog_data->wait_dialtone_timeout = wait_dialtone_timeout; - analog_data->polarity_delay = polarity_delay; - analog_data->max_dialstr = max_dialstr; - span->signal_cb = sig_cb; - strncpy(analog_data->hotline, hotline, sizeof(analog_data->hotline)); - span->signal_type = FTDM_SIGTYPE_ANALOG; - span->signal_data = analog_data; - span->outgoing_call = span->trunk_type == FTDM_TRUNK_FXS ? analog_fxs_outgoing_call : analog_fxo_outgoing_call; - span->get_channel_sig_status = analog_get_channel_sig_status; - span->get_span_sig_status = analog_get_span_sig_status; - - ftdm_span_load_tones(span, tonemap); - - ftdm_log(FTDM_LOG_DEBUG, "Configuration of analog signaling for span %s is done\n", span->name); - return FTDM_SUCCESS; - -} - -/** - * \brief Retrieves tone generation output to be sent - * \param ts Teletone generator - * \param map Tone map - * \return -1 on error, 0 on success - */ -static int teletone_handler(teletone_generation_session_t *ts, teletone_tone_map_t *map) -{ - ftdm_buffer_t *dt_buffer = ts->user_data; - int wrote; - - if (!dt_buffer) { - return -1; - } - wrote = teletone_mux_tones(ts, map); - ftdm_buffer_write(dt_buffer, ts->buffer, wrote * 2); - return 0; -} - -/** - * \brief Sends caller id on an analog channel (FSK coded) - * \param ftdmchan Channel to send caller id on - */ -static void send_caller_id(ftdm_channel_t *ftdmchan) -{ - ftdm_fsk_data_state_t fsk_data; - uint8_t databuf[1024] = ""; - char time_str[9]; - struct tm tm; - time_t now; - ftdm_mdmf_type_t mt = MDMF_INVALID; - - time(&now); -#ifdef WIN32 - _tzset(); - _localtime64_s(&tm, &now); -#else - localtime_r(&now, &tm); -#endif - strftime(time_str, sizeof(time_str), "%m%d%H%M", &tm); - - ftdm_fsk_data_init(&fsk_data, databuf, sizeof(databuf)); - ftdm_fsk_data_add_mdmf(&fsk_data, MDMF_DATETIME, (uint8_t *) time_str, 8); - - if (ftdm_strlen_zero(ftdmchan->caller_data.cid_num.digits)) { - mt = MDMF_NO_NUM; - ftdm_set_string(ftdmchan->caller_data.cid_num.digits, "O"); - } else if (!strcasecmp(ftdmchan->caller_data.cid_num.digits, "P") || !strcasecmp(ftdmchan->caller_data.cid_num.digits, "O")) { - mt = MDMF_NO_NUM; - } else { - mt = MDMF_PHONE_NUM; - } - ftdm_fsk_data_add_mdmf(&fsk_data, mt, (uint8_t *) ftdmchan->caller_data.cid_num.digits, (uint8_t)strlen(ftdmchan->caller_data.cid_num.digits)); - - if (ftdm_strlen_zero(ftdmchan->caller_data.cid_name)) { - mt = MDMF_NO_NAME; - ftdm_set_string(ftdmchan->caller_data.cid_name, "O"); - } else if (!strcasecmp(ftdmchan->caller_data.cid_name, "P") || !strcasecmp(ftdmchan->caller_data.cid_name, "O")) { - mt = MDMF_NO_NAME; - } else { - mt = MDMF_PHONE_NAME; - } - ftdm_fsk_data_add_mdmf(&fsk_data, mt, (uint8_t *) ftdmchan->caller_data.cid_name, (uint8_t)strlen(ftdmchan->caller_data.cid_name)); - - ftdm_fsk_data_add_checksum(&fsk_data); - ftdm_channel_send_fsk_data(ftdmchan, &fsk_data, -14); -} - -static void analog_dial(ftdm_channel_t *ftdmchan, uint32_t *state_counter, uint32_t *dial_timeout) -{ - if (ftdm_strlen_zero(ftdmchan->caller_data.dnis.digits)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No digits to send, moving to UP!\n"); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); - } else { - if (ftdm_channel_command(ftdmchan, FTDM_COMMAND_SEND_DTMF, ftdmchan->caller_data.dnis.digits) != FTDM_SUCCESS) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Send Digits Failed [%s]\n", ftdmchan->last_error); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); - } else { - *state_counter = 0; - ftdmchan->needed_tones[FTDM_TONEMAP_RING] = 1; - ftdmchan->needed_tones[FTDM_TONEMAP_BUSY] = 1; - ftdmchan->needed_tones[FTDM_TONEMAP_FAIL1] = 1; - ftdmchan->needed_tones[FTDM_TONEMAP_FAIL2] = 1; - ftdmchan->needed_tones[FTDM_TONEMAP_FAIL3] = 1; - *dial_timeout = (uint32_t)((ftdmchan->dtmf_on + ftdmchan->dtmf_off) * strlen(ftdmchan->caller_data.dnis.digits)) + 2000; - } - } -} - -/** - * \brief Main thread function for analog channel (outgoing call) - * \param me Current thread - * \param obj Channel to run in this thread - */ -static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) -{ - ftdm_channel_t *ftdmchan = (ftdm_channel_t *) obj; - ftdm_buffer_t *dt_buffer = NULL; - teletone_generation_session_t ts; - uint8_t frame[1024]; - ftdm_size_t len, rlen; - ftdm_tone_type_t tt = FTDM_TONE_DTMF; - char dtmf[MAX_DTMF+1] = ""; - ftdm_size_t dtmf_offset = 0; - ftdm_analog_data_t *analog_data = ftdmchan->span->signal_data; - ftdm_channel_t *closed_chan; - uint32_t state_counter = 0, elapsed = 0, collecting = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = analog_data->wait_dialtone_timeout; - uint32_t answer_on_polarity_counter = 0; - ftdm_sigmsg_t sig; - - ftdm_unused_arg(me); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "ANALOG CHANNEL thread starting.\n"); - - ts.buffer = NULL; - - if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "OPEN ERROR [%s]\n", ftdmchan->last_error); - goto done; - } - - if (ftdm_buffer_create(&dt_buffer, 1024, 3192, 0) != FTDM_SUCCESS) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "memory error!"); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "MEM ERROR\n"); - goto done; - } - - if (ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_DTMF_DETECT, &tt) != FTDM_SUCCESS) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "error initilizing tone detector!"); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "failed to initialize DTMF detector\n"); - goto done; - } - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Initialized DTMF detection\n"); - - ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_INTHREAD); - teletone_init_session(&ts, 0, teletone_handler, dt_buffer); - ts.rate = 8000; -#if 0 - ts.debug = 1; - ts.debug_stream = stdout; -#endif - ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval); - ftdm_buffer_set_loops(dt_buffer, -1); - - memset(&sig, 0, sizeof(sig)); - sig.chan_id = ftdmchan->chan_id; - sig.span_id = ftdmchan->span_id; - sig.channel = ftdmchan; - - ftdm_assert(interval != 0, "Invalid interval"); - - if (!dial_timeout) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Not waiting for dial tone to dial number %s\n", ftdmchan->caller_data.dnis.digits); - } - - while (ftdm_running() && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INTHREAD)) { - ftdm_wait_flag_t flags = FTDM_READ; - ftdm_size_t dlen = 0; - - len = sizeof(frame); - - elapsed += interval; - state_counter += interval; - - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - switch(ftdmchan->state) { - case FTDM_CHANNEL_STATE_GET_CALLERID: - { - if (state_counter > 5000 || !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT)) { - ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_CALLERID_DETECT, NULL); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); - } - } - break; - case FTDM_CHANNEL_STATE_DIALING: - { - if (state_counter > dial_timeout) { - if (ftdmchan->needed_tones[FTDM_TONEMAP_DIAL]) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); - } else { - /* do not go up if we're waiting for polarity reversal */ - if (ftdm_test_flag(analog_data, FTDM_ANALOG_ANSWER_POLARITY_REVERSE)) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); - } else { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); - } - } - } - } - break; - case FTDM_CHANNEL_STATE_GENRING: - { - if (state_counter > 60000) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } else if (!ftdmchan->fsk_buffer || !ftdm_buffer_inuse(ftdmchan->fsk_buffer)) { - ftdm_sleep(interval); - continue; - } - } - break; - case FTDM_CHANNEL_STATE_DIALTONE: - { - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_HOLD) && state_counter > 10000) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); - } - } - break; - case FTDM_CHANNEL_STATE_BUSY: - { - if (state_counter > 20000) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_ATTN); - } - } - break; - case FTDM_CHANNEL_STATE_ATTN: - { - if (state_counter > 20000) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - } - break; - case FTDM_CHANNEL_STATE_HANGUP: - { - if (state_counter > 500) { - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_RINGING)) { - ftdm_channel_command(ftdmchan, FTDM_COMMAND_GENERATE_RING_OFF, NULL); - } - - if (ftdmchan->type == FTDM_CHAN_TYPE_FXS && - ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) && - (ftdmchan->last_state == FTDM_CHANNEL_STATE_RINGING - || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE - || ftdmchan->last_state == FTDM_CHANNEL_STATE_RING - || ftdmchan->last_state == FTDM_CHANNEL_STATE_UP)) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); - } else { - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING; - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - } - } - break; - case FTDM_CHANNEL_STATE_CALLWAITING: - { - int done = 0; - - if (ftdmchan->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK] == 1) { - send_caller_id(ftdmchan); - ftdmchan->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK]++; - } else if (state_counter > 600 && !ftdmchan->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK]) { - send_caller_id(ftdmchan); - ftdmchan->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK]++; - } else if (state_counter > 1000 && !ftdmchan->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK]) { - done = 1; - } else if (state_counter > 10000) { - if (ftdmchan->fsk_buffer) { - ftdm_buffer_zero(ftdmchan->fsk_buffer); - } else { - ftdm_buffer_create(&ftdmchan->fsk_buffer, 128, 128, 0); - } - - ts.user_data = ftdmchan->fsk_buffer; - teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_CALLWAITING_SAS]); - ts.user_data = dt_buffer; - done = 1; - } - - if (done) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); - ftdm_clear_flag_locked(ftdmchan->span, FTDM_SPAN_STATE_CHANGE); - ftdm_channel_complete_state(ftdmchan); - ftdmchan->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK] = 0; - } - } - case FTDM_CHANNEL_STATE_UP: - case FTDM_CHANNEL_STATE_RING: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - { - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) && - ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA && - ftdm_test_sflag(ftdmchan, AF_POLARITY_REVERSE)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Answering on polarity reverse\n"); - ftdm_clear_sflag(ftdmchan, AF_POLARITY_REVERSE); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); - answer_on_polarity_counter = state_counter; - } else if (ftdmchan->state == FTDM_CHANNEL_STATE_UP - && ftdm_test_sflag(ftdmchan, AF_POLARITY_REVERSE)){ - /* if this polarity reverse is close to the answer polarity reverse, ignore it */ - if (answer_on_polarity_counter - && (state_counter - answer_on_polarity_counter) > analog_data->polarity_delay) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Hanging up on polarity reverse\n"); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, - "Not hanging up on polarity reverse, too close to Answer reverse\n"); - } - ftdm_clear_sflag(ftdmchan, AF_POLARITY_REVERSE); - } else { - ftdm_sleep(interval); - } - continue; - } - break; - case FTDM_CHANNEL_STATE_DOWN: - { - goto done; - } - break; - default: - break; - } - } else { - ftdm_clear_flag_locked(ftdmchan->span, FTDM_SPAN_STATE_CHANGE); - ftdm_channel_complete_state(ftdmchan); - indicate = 0; - state_counter = 0; - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Executing state handler on %d:%d for %s\n", - ftdmchan->span_id, ftdmchan->chan_id, - ftdm_channel_state2str(ftdmchan->state)); - switch(ftdmchan->state) { - case FTDM_CHANNEL_STATE_UP: - { - ftdm_channel_use(ftdmchan); - ftdm_channel_clear_needed_tones(ftdmchan); - ftdm_channel_flush_dtmf(ftdmchan); - - if (ftdmchan->type == FTDM_CHAN_TYPE_FXO && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK)) { - ftdm_channel_command(ftdmchan, FTDM_COMMAND_OFFHOOK, NULL); - } - - if (ftdmchan->fsk_buffer && ftdm_buffer_inuse(ftdmchan->fsk_buffer)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Cancel FSK transmit due to early answer.\n"); - ftdm_buffer_zero(ftdmchan->fsk_buffer); - } - - if (ftdmchan->type == FTDM_CHAN_TYPE_FXS && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_RINGING)) { - ftdm_channel_command(ftdmchan, FTDM_COMMAND_GENERATE_RING_OFF, NULL); - } - - if (ftdmchan->token_count == 1) { - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_HOLD); - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_HOLD)) { - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_HOLD); - sig.event_id = FTDM_SIGEVENT_ADD_CALL; - } else { - sig.event_id = FTDM_SIGEVENT_UP; - } - - if (ftdmchan->type == FTDM_CHAN_TYPE_FXS && - !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) && - ftdm_test_flag(analog_data, FTDM_ANALOG_ANSWER_POLARITY_REVERSE)) { - ftdm_polarity_t polarity = FTDM_POLARITY_REVERSE; - if (ftdmchan->polarity == FTDM_POLARITY_FORWARD) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Reversing polarity on answer\n"); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_POLARITY, &polarity); - } else { - /* the polarity may be already reversed if this is the second time we - * answer (ie, due to 2 calls being on the same line) */ - } - } - - ftdm_span_send_signal(ftdmchan->span, &sig); - continue; - } - break; - case FTDM_CHANNEL_STATE_DIALING: - { - ftdm_channel_use(ftdmchan); - } - break; - case FTDM_CHANNEL_STATE_RING: - { - ftdm_channel_use(ftdmchan); - sig.event_id = FTDM_SIGEVENT_START; - - if (ftdmchan->type == FTDM_CHAN_TYPE_FXO) { - ftdm_set_string(ftdmchan->caller_data.dnis.digits, ftdmchan->chan_number); - } else { - ftdm_set_string(ftdmchan->caller_data.dnis.digits, dtmf); - } - - ftdm_span_send_signal(ftdmchan->span, &sig); - continue; - } - break; - - case FTDM_CHANNEL_STATE_HANGUP: - /* this state is only used when the user hangup, if the device hang up (onhook) we currently - * go straight to DOWN. If we ever change this (as other signaling modules do) by using this - * state for both user and device hangup, we should check here for the type of hangup since - * some actions (polarity reverse) do not make sense if the device hung up */ - if (ftdmchan->type == FTDM_CHAN_TYPE_FXS && - ftdmchan->last_state == FTDM_CHANNEL_STATE_UP && - ftdm_test_flag(analog_data, FTDM_ANALOG_HANGUP_POLARITY_REVERSE)) { - ftdm_polarity_t polarity = ftdmchan->polarity == FTDM_POLARITY_REVERSE - ? FTDM_POLARITY_FORWARD : FTDM_POLARITY_REVERSE; - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Reversing polarity on hangup\n"); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_POLARITY, &polarity); - } - break; - - case FTDM_CHANNEL_STATE_DOWN: - { - sig.event_id = FTDM_SIGEVENT_STOP; - ftdm_span_send_signal(ftdmchan->span, &sig); - goto done; - } - break; - case FTDM_CHANNEL_STATE_DIALTONE: - { - memset(&ftdmchan->caller_data, 0, sizeof(ftdmchan->caller_data)); - *dtmf = '\0'; - dtmf_offset = 0; - ftdm_buffer_zero(dt_buffer); - teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_DIAL]); - indicate = 1; - } - break; - case FTDM_CHANNEL_STATE_CALLWAITING: - { - ftdmchan->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK] = 0; - if (ftdmchan->fsk_buffer) { - ftdm_buffer_zero(ftdmchan->fsk_buffer); - } else { - ftdm_buffer_create(&ftdmchan->fsk_buffer, 128, 128, 0); - } - - ts.user_data = ftdmchan->fsk_buffer; - teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_CALLWAITING_SAS]); - teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_CALLWAITING_CAS]); - ts.user_data = dt_buffer; - } - break; - case FTDM_CHANNEL_STATE_GENRING: - { - ftdm_sigmsg_t sig; - - send_caller_id(ftdmchan); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_GENERATE_RING_ON, NULL); - - memset(&sig, 0, sizeof(sig)); - sig.chan_id = ftdmchan->chan_id; - sig.span_id = ftdmchan->span_id; - sig.channel = ftdmchan; - sig.event_id = FTDM_SIGEVENT_PROGRESS; - ftdm_span_send_signal(ftdmchan->span, &sig); - - } - break; - case FTDM_CHANNEL_STATE_GET_CALLERID: - { - memset(&ftdmchan->caller_data, 0, sizeof(ftdmchan->caller_data)); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Initializing cid data!\n"); - ftdm_set_string(ftdmchan->caller_data.ani.digits, "unknown"); - ftdm_set_string(ftdmchan->caller_data.cid_name, ftdmchan->caller_data.ani.digits); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_CALLERID_DETECT, NULL); - continue; - } - break; - case FTDM_CHANNEL_STATE_RINGING: - { - ftdm_buffer_zero(dt_buffer); - teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_RING]); - indicate = 1; - - } - break; - case FTDM_CHANNEL_STATE_BUSY: - { - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CIRCUIT_CONGESTION; - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - ftdm_buffer_zero(dt_buffer); - teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_BUSY]); - indicate = 1; - } else { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - } - break; - case FTDM_CHANNEL_STATE_ATTN: - { - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - ftdm_buffer_zero(dt_buffer); - teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_ATTN]); - indicate = 1; - } else { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - } - break; - default: - break; - } - } - - - if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALTONE || ftdmchan->state == FTDM_CHANNEL_STATE_COLLECT) { - if ((dlen = ftdm_channel_dequeue_dtmf(ftdmchan, dtmf + dtmf_offset, sizeof(dtmf) - strlen(dtmf)))) { - - if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALTONE) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); - collecting = 1; - } - dtmf_offset = strlen(dtmf); - last_digit = elapsed; - sig.event_id = FTDM_SIGEVENT_COLLECTED_DIGIT; - ftdm_set_string(sig.ev_data.collected.digits, dtmf); - if (ftdm_span_send_signal(ftdmchan->span, &sig) == FTDM_BREAK) { - collecting = 0; - } - } - else if(!analog_data->max_dialstr) - { - last_digit = elapsed; - collecting = 0; - strcpy(dtmf, analog_data->hotline); - } - } - - - if (last_digit && (!collecting || ((elapsed - last_digit > analog_data->digit_timeout) || strlen(dtmf) >= analog_data->max_dialstr))) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Number obtained [%s]\n", dtmf); - if (ftdmchan->state == FTDM_CHANNEL_STATE_COLLECT && ftdmchan->state_status != FTDM_STATE_STATUS_COMPLETED) { - ftdm_channel_complete_state(ftdmchan); - } - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); - last_digit = 0; - collecting = 0; - } - - if (ftdm_channel_wait(ftdmchan, &flags, interval * 2) != FTDM_SUCCESS) { - continue; - } - - if (!(flags & FTDM_READ)) { - continue; - } - - if (ftdm_channel_read(ftdmchan, frame, &len) != FTDM_SUCCESS) { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "read error [%s]\n", ftdmchan->last_error); - continue; - } - - if (ftdmchan->type == FTDM_CHAN_TYPE_FXO && ftdmchan->detected_tones[0]) { - int i; - - for (i = 1; i < FTDM_TONEMAP_INVALID; i++) { - if (ftdmchan->detected_tones[i]) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Detected tone %s on %d:%d\n", ftdm_tonemap2str(i), ftdmchan->span_id, ftdmchan->chan_id); - } - } - - if (ftdmchan->detected_tones[FTDM_TONEMAP_BUSY] || - ftdmchan->detected_tones[FTDM_TONEMAP_FAIL1] || - ftdmchan->detected_tones[FTDM_TONEMAP_FAIL2] || - ftdmchan->detected_tones[FTDM_TONEMAP_FAIL3] || - ftdmchan->detected_tones[FTDM_TONEMAP_ATTN] - ) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failure indication detected!\n"); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); - } else if (ftdmchan->detected_tones[FTDM_TONEMAP_DIAL]) { - analog_dial(ftdmchan, &state_counter, &dial_timeout); - } else if (ftdmchan->detected_tones[FTDM_TONEMAP_RING]) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); - } - - ftdm_channel_clear_detected_tones(ftdmchan); - } else if (!dial_timeout) { - /* we were requested not to wait for dial tone, we can dial immediately */ - analog_dial(ftdmchan, &state_counter, &dial_timeout); - } - - if ((ftdmchan->dtmf_buffer && ftdm_buffer_inuse(ftdmchan->dtmf_buffer)) || (ftdmchan->fsk_buffer && ftdm_buffer_inuse(ftdmchan->fsk_buffer))) { - //rlen = len; - //memset(frame, 0, len); - //ftdm_channel_write(ftdmchan, frame, sizeof(frame), &rlen); - continue; - } - - if (!indicate) { - continue; - } - - if (ftdmchan->type == FTDM_CHAN_TYPE_FXO && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK)) { - ftdm_channel_command(ftdmchan, FTDM_COMMAND_OFFHOOK, NULL); - } - - if (ftdmchan->effective_codec != FTDM_CODEC_SLIN) { - len *= 2; - } - - rlen = ftdm_buffer_read_loop(dt_buffer, frame, len); - - if (ftdmchan->effective_codec != FTDM_CODEC_SLIN) { - fio_codec_t codec_func = NULL; - - if (ftdmchan->native_codec == FTDM_CODEC_ULAW) { - codec_func = fio_slin2ulaw; - } else if (ftdmchan->native_codec == FTDM_CODEC_ALAW) { - codec_func = fio_slin2alaw; - } - - if (codec_func) { - codec_func(frame, sizeof(frame), &rlen); - } else { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "codec error!"); - goto done; - } - } - - ftdm_channel_write(ftdmchan, frame, sizeof(frame), &rlen); - } - - done: - - closed_chan = ftdmchan; - - ftdm_channel_lock(closed_chan); - - if (ftdmchan->type == FTDM_CHAN_TYPE_FXO && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Going onhook\n"); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_ONHOOK, NULL); - } - - if (ftdmchan->type == FTDM_CHAN_TYPE_FXS && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_RINGING)) { - ftdm_channel_command(ftdmchan, FTDM_COMMAND_GENERATE_RING_OFF, NULL); - } - - - ftdm_clear_sflag(ftdmchan, AF_POLARITY_REVERSE); - - ftdm_channel_close(&ftdmchan); - - ftdm_channel_command(closed_chan, FTDM_COMMAND_SET_NATIVE_CODEC, NULL); - - if (ts.buffer) { - teletone_destroy_session(&ts); - } - - if (dt_buffer) { - ftdm_buffer_destroy(&dt_buffer); - } - - if (closed_chan->state != FTDM_CHANNEL_STATE_DOWN) { - ftdm_set_state_locked(closed_chan, FTDM_CHANNEL_STATE_DOWN); - } - - ftdm_log_chan(closed_chan, FTDM_LOG_DEBUG, "ANALOG CHANNEL %d:%d thread ended.\n", closed_chan->span_id, closed_chan->chan_id); - - ftdm_clear_flag(closed_chan, FTDM_CHANNEL_INTHREAD); - - ftdm_channel_unlock(closed_chan); - - return NULL; -} - -/** - * \brief Processes freetdm event - * \param span Span on which the event was fired - * \param event Event to be treated - * \return Success or failure - */ -static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *event) -{ - ftdm_sigmsg_t sig; - ftdm_analog_data_t *analog_data = event->channel->span->signal_data; - int locked = 0; - - memset(&sig, 0, sizeof(sig)); - sig.chan_id = event->channel->chan_id; - sig.span_id = event->channel->span_id; - sig.channel = event->channel; - - - ftdm_log_chan(event->channel, FTDM_LOG_DEBUG, "Received event [%s] in state [%s]\n", ftdm_oob_event2str(event->enum_id), ftdm_channel_state2str(event->channel->state)); - - ftdm_mutex_lock(event->channel->mutex); - locked++; - - /* MAINTENANCE WARNING: - * 1. Be aware you are working on the locked channel - * 2. We should not be calling ftdm_span_send_signal or ftdm_set_state when there is already a channel thread running - * however, since this is old code I am not changing it now, but new code should adhere to that convention - * otherwise, we have possible races where we compete with the user for state changes, ie, the user requests - * a state change and then we process an event, the state change from the user is pending so our ftdm_set_state - * operation will fail. In cases where we win the race, our state change will be accepted but if a user requests - * a state change before the state change we requested here is processed by the channel thread, we'll end up - * rejecting the user request. - * - * See docs/locking.txt for further information about what guarantees should signaling modules provide when - * locking/unlocking a channel - * */ - switch(event->enum_id) { - case FTDM_OOB_RING_START: - { - if (event->channel->type != FTDM_CHAN_TYPE_FXO) { - ftdm_log_chan_msg(event->channel, FTDM_LOG_ERROR, "Cannot get a RING_START event on a non-fxo channel, please check your config.\n"); - ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DOWN); - goto end; - } - if (!event->channel->ring_count && (event->channel->state == FTDM_CHANNEL_STATE_DOWN && !ftdm_test_flag(event->channel, FTDM_CHANNEL_INTHREAD))) { - if (ftdm_test_flag(analog_data, FTDM_ANALOG_CALLERID)) { - ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_GET_CALLERID); - } else { - ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_RING); - } - event->channel->ring_count = 1; - ftdm_mutex_unlock(event->channel->mutex); - locked = 0; - ftdm_thread_create_detached(ftdm_analog_channel_run, event->channel); - } else { - event->channel->ring_count++; - } - } - break; - case FTDM_OOB_ONHOOK: - { - if (ftdm_test_flag(event->channel, FTDM_CHANNEL_RINGING)) { - ftdm_channel_command(event->channel, FTDM_COMMAND_GENERATE_RING_OFF, NULL); - } - - if (event->channel->state != FTDM_CHANNEL_STATE_DOWN) { - if (event->channel->state == FTDM_CHANNEL_STATE_HANGUP && - ftdm_test_flag(event->channel, FTDM_CHANNEL_STATE_CHANGE)) { - /* we do not need to process HANGUP since the device also hangup already */ - ftdm_channel_complete_state(event->channel); - } - ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DOWN); - } - if (event->channel->type == FTDM_CHAN_TYPE_FXS) { - /* we always return to forward when the device goes onhook */ - ftdm_polarity_t forward_polarity = FTDM_POLARITY_FORWARD; - ftdm_channel_command(event->channel, FTDM_COMMAND_SET_POLARITY, &forward_polarity); - } - } - break; - case FTDM_OOB_FLASH: - { - if (event->channel->state == FTDM_CHANNEL_STATE_CALLWAITING) { - ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_UP); - ftdm_clear_flag(event->channel->span, FTDM_SPAN_STATE_CHANGE); - ftdm_channel_complete_state(event->channel); - event->channel->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK] = 0; - } - - ftdm_channel_rotate_tokens(event->channel); - - if (ftdm_test_flag(event->channel, FTDM_CHANNEL_HOLD) && event->channel->token_count != 1) { - ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_UP); - } else { - sig.event_id = FTDM_SIGEVENT_FLASH; - ftdm_span_send_signal(span, &sig); - } - } - break; - case FTDM_OOB_OFFHOOK: - { - if (event->channel->type == FTDM_CHAN_TYPE_FXS) { - if (ftdm_test_flag(event->channel, FTDM_CHANNEL_INTHREAD)) { - if (ftdm_test_flag(event->channel, FTDM_CHANNEL_RINGING)) { - ftdm_channel_command(event->channel, FTDM_COMMAND_GENERATE_RING_OFF, NULL); - } - ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_UP); - } else { - if(!analog_data->max_dialstr) { - ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_COLLECT); - } else { - ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DIALTONE); - } - ftdm_mutex_unlock(event->channel->mutex); - locked = 0; - ftdm_thread_create_detached(ftdm_analog_channel_run, event->channel); - } - } else { - if (!ftdm_test_flag(event->channel, FTDM_CHANNEL_INTHREAD)) { - if (ftdm_test_flag(event->channel, FTDM_CHANNEL_OFFHOOK)) { - ftdm_channel_command(event->channel, FTDM_COMMAND_ONHOOK, NULL); - } - } - ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DOWN); - } - } - break; - case FTDM_OOB_ALARM_TRAP: - { - sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sig.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN; - ftdm_span_send_signal(span, &sig); - } - break; - case FTDM_OOB_ALARM_CLEAR: - { - sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sig.ev_data.sigstatus.status = FTDM_SIG_STATE_UP; - ftdm_span_send_signal(span, &sig); - } - break; - case FTDM_OOB_POLARITY_REVERSE: - { - if (event->channel->type != FTDM_CHAN_TYPE_FXO) { - ftdm_log_chan_msg(event->channel, FTDM_LOG_WARNING, - "Ignoring polarity reversal, this should not happen in non-FXO channels!\n"); - break; - } - if (!ftdm_test_flag(event->channel, FTDM_CHANNEL_INTHREAD) && - ftdm_test_flag(event->channel, FTDM_CHANNEL_OFFHOOK)) { - ftdm_log_chan_msg(event->channel, FTDM_LOG_WARNING, - "Forcing onhook in channel not in thread after polarity reversal\n"); - ftdm_channel_command(event->channel, FTDM_COMMAND_ONHOOK, NULL); - break; - } - if (!ftdm_test_flag(analog_data, FTDM_ANALOG_ANSWER_POLARITY_REVERSE) - && !ftdm_test_flag(analog_data, FTDM_ANALOG_HANGUP_POLARITY_REVERSE)) { - ftdm_log_chan_msg(event->channel, FTDM_LOG_DEBUG, - "Ignoring polarity reversal because this channel is not configured for it\n"); - break; - } - if (event->channel->state == FTDM_CHANNEL_STATE_DOWN) { - if (ftdm_test_flag(analog_data, FTDM_ANALOG_CALLERID) - && ftdm_test_flag(analog_data, FTDM_ANALOG_POLARITY_CALLERID)) { - ftdm_log_chan_msg(event->channel, FTDM_LOG_DEBUG, "Polarity reversal detected while down, getting caller id now\n"); - ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_GET_CALLERID); - event->channel->ring_count = 1; - ftdm_mutex_unlock(event->channel->mutex); - locked = 0; - ftdm_thread_create_detached(ftdm_analog_channel_run, event->channel); - } else { - ftdm_log_chan_msg(event->channel, FTDM_LOG_DEBUG, - "Ignoring polarity reversal because this channel is down\n"); - } - break; - } - /* we have a good channel, set the polarity flag and let the channel thread deal with it */ - ftdm_set_sflag(event->channel, AF_POLARITY_REVERSE); - } - break; - default: - { - ftdm_log_chan(event->channel, FTDM_LOG_DEBUG, "Ignoring event [%s] in state [%s]\n", ftdm_oob_event2str(event->enum_id), ftdm_channel_state2str(event->channel->state)); - } - break; - } - - end: - - if (locked) { - ftdm_mutex_unlock(event->channel->mutex); - } - return FTDM_SUCCESS; -} - -/** - * \brief Main thread function for analog span (monitor) - * \param me Current thread - * \param obj Span to run in this thread - */ -static void *ftdm_analog_run(ftdm_thread_t *me, void *obj) -{ - ftdm_span_t *span = (ftdm_span_t *) obj; - ftdm_analog_data_t *analog_data = span->signal_data; - int errs = 0; - - ftdm_unused_arg(me); - ftdm_log(FTDM_LOG_DEBUG, "ANALOG thread starting.\n"); - - while(ftdm_running() && ftdm_test_flag(analog_data, FTDM_ANALOG_RUNNING)) { - int waitms = 1000; - ftdm_status_t status; - - if ((status = ftdm_span_poll_event(span, waitms, NULL)) != FTDM_FAIL) { - errs = 0; - } - - switch(status) { - case FTDM_SUCCESS: - { - ftdm_event_t *event; - while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) { - if (event->enum_id == FTDM_OOB_NOOP) { - continue; - } - if (process_event(span, event) != FTDM_SUCCESS) { - goto end; - } - } - } - break; - case FTDM_FAIL: - { - ftdm_log(FTDM_LOG_ERROR, "Failure Polling event! [%s]\n", span->last_error); - if (++errs > 300) { - ftdm_log(FTDM_LOG_CRIT, "Too Many Errors!\n"); - goto end; - } - } - break; - default: - break; - } - - } - - end: - - ftdm_clear_flag(analog_data, FTDM_ANALOG_RUNNING); - - ftdm_log(FTDM_LOG_DEBUG, "ANALOG thread ending.\n"); - - return NULL; -} - -/** - * \brief FreeTDM analog signaling module initialisation - * \return Success - */ -static FIO_SIG_LOAD_FUNCTION(ftdm_analog_init) -{ - return FTDM_SUCCESS; -} - -/** - * \brief FreeTDM analog signaling module definition - */ -EX_DECLARE_DATA ftdm_module_t ftdm_module = { - "analog", - NULL, - NULL, - ftdm_analog_init, - ftdm_analog_configure_span, - NULL -}; - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftdm_analog_em.h b/libs/freetdm/src/ftmod/ftmod_analog_em/ftdm_analog_em.h deleted file mode 100644 index e52a319155..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_analog_em/ftdm_analog_em.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2008-2012, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Contributor(s): - * - * John Wehle (john@feith.com) - * Moises Silva (moy@sangoma.com) - * - */ - -#ifndef FTDM_ANALOG_EM_H -#define FTDM_ANALOG_EM_H -#include "freetdm.h" - -#define MAX_DIALSTRING 256 - -typedef enum { - FTDM_ANALOG_EM_RUNNING = (1 << 0), - FTDM_ANALOG_EM_LOCAL_WRITE = (1 << 2), - FTDM_ANALOG_EM_LOCAL_SUSPEND = (1 << 3), - FTDM_ANALOG_EM_REMOTE_SUSPEND = (1 << 4), -} ftdm_analog_em_flag_t; - -struct ftdm_analog_data { - uint32_t flags; - uint32_t max_dialstr; - uint32_t digit_timeout; - uint32_t dial_timeout; - ftdm_bool_t answer_supervision; - ftdm_bool_t immediate_ringback; - char ringback_file[512]; -}; - -static void *ftdm_analog_em_run(ftdm_thread_t *me, void *obj); -typedef struct ftdm_analog_data ftdm_analog_em_data_t; - -#endif - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2008.vcproj deleted file mode 100644 index 837ba7de0f..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2008.vcproj +++ /dev/null @@ -1,353 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj.filters deleted file mode 100644 index 3326f9fd16..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj.filters +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Source Files - - - - - Header Files - - - \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c deleted file mode 100644 index 98fde2a514..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c +++ /dev/null @@ -1,1160 +0,0 @@ -/* - * Copyright (c) 2008-2012, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Contributor(s): - * - * John Wehle (john@feith.com) - * Moises Silva (moy@sangoma.com) - * - */ - -#include "private/ftdm_core.h" -#include "ftdm_analog_em.h" - -#ifndef localtime_r -struct tm * localtime_r(const time_t *clock, struct tm *result); -#endif - -static FIO_SPAN_SET_SIG_STATUS_FUNCTION(analog_em_set_span_sig_status); - -/* check if the given file is a wave file and skip the header if it is */ -#define WAVE_CHUNK_ID "RIFF" -#define WAVE_FMT "WAVEfmt " -#define WAVE_HEADER_LEN 44 -static int skip_wave_header(const char *fname, FILE *f) -{ - char rbuff[10] = { 0 }; - unsigned int hz = 0; - unsigned int hs = 0; - unsigned short fmt = 0; - unsigned short chans = 0; - unsigned int size = 0; - - /* check chunk id */ - if (fread(rbuff, 1, 4, f) != 4) { - ftdm_log(FTDM_LOG_ERROR, "Unable to read wav chunk id from file %s\n", fname); - goto error; - } - rbuff[4] = 0; - - if (strncasecmp(rbuff, WAVE_CHUNK_ID, sizeof(WAVE_CHUNK_ID)-1)) { - goto notwave; - } - - /* read chunk size */ - if (fread(&size, 1, 4, f) != 4) { - ftdm_log(FTDM_LOG_ERROR, "Unable to read wav chunk size from file %s\n", fname); - goto error; - } - - /* check format and sub chunk id */ - if (fread(rbuff, 1, 8, f) != 8) { - ftdm_log(FTDM_LOG_ERROR, "Unable to read wav format and sub chunk id from file %s\n", fname); - goto error; - } - rbuff[8] = 0; - - if (strncasecmp(rbuff, WAVE_FMT, sizeof(WAVE_FMT)-1)) { - goto notwave; - } - - /* At this point we know is a wav file ... */ - - /* validate sub chunk size */ - if (fread(&hs, 1, 4, f) != 4) { - ftdm_log(FTDM_LOG_ERROR, "Unable to read wav sub chunk size from file %s\n", fname); - goto error; - } - - if (hs != 16) { - ftdm_log(FTDM_LOG_ERROR, "Unsupported wav sub chunk size %d from file %s\n", hs, fname); - goto error; - } - - /* validate audio format */ - if (fread(&fmt, 1, 2, f) != 2) { - ftdm_log(FTDM_LOG_ERROR, "Unable to read wav audio format from file %s\n", fname); - goto error; - } - - if (fmt != 1) { - ftdm_log(FTDM_LOG_ERROR, "Unsupported wav audio format %d in file %s, we only support PCM\n", fmt, fname); - goto error; - } - - /* validate channels */ - if (fread(&chans, 1, 2, f) != 2) { - ftdm_log(FTDM_LOG_ERROR, "Unable to read wav channels from file %s\n", fname); - goto error; - } - - if (chans != 1) { - ftdm_log(FTDM_LOG_ERROR, "Unsupported number of channels %d in file %s, we only support 1 (mono)\n", chans, fname); - goto error; - } - - /* validate sampling rate */ - if (fread(&hz, 1, 2, f) != 2) { - ftdm_log(FTDM_LOG_ERROR, "Unable to read wav sampling rate from file %s\n", fname); - goto error; - } - - if (hz != 8000) { - ftdm_log(FTDM_LOG_ERROR, "Invalid input wav sampling rate %dHz, only 8000Hz supported\n", hz); - goto error; - } - - ftdm_log(FTDM_LOG_DEBUG, "Found input file %s. PCM mono wav of %d bytes at %dHz, skipping header ...\n", fname, size, hz); - fseek(f, WAVE_HEADER_LEN, SEEK_SET); - - return 0; - -notwave: - ftdm_log(FTDM_LOG_ERROR, "File %s is not a wav file\n", fname); - return -1; - -error: - return -1; -} - -static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj); - -/** - * \brief Starts an EM channel thread (outgoing call) - * \param ftdmchan Channel to initiate call on - * \return Success or failure - * - * Initialises state, starts tone progress detection and runs the channel in a new a thread. - */ -static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(analog_em_outgoing_call) -{ - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INTHREAD)) { - ftdm_channel_clear_needed_tones(ftdmchan); - ftdm_channel_clear_detected_tones(ftdmchan); - - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND); - - ftdm_channel_command(ftdmchan, FTDM_COMMAND_OFFHOOK, NULL); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_PROGRESS_DETECT, NULL); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DIALING); - ftdm_thread_create_detached(ftdm_analog_em_channel_run, ftdmchan); - return FTDM_SUCCESS; - } - - return FTDM_FAIL; -} - -static ftdm_status_t ftdm_analog_em_sig_write(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t size) -{ - ftdm_analog_em_data_t *analog_data = ftdmchan->span->signal_data; - if (ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA - && analog_data->immediate_ringback - && ftdm_test_sflag(ftdmchan, FTDM_ANALOG_EM_LOCAL_WRITE)) { - /* ringback is being played in the analog thread, ignore user data for now */ - return FTDM_BREAK; - } - return FTDM_SUCCESS; -} - -/** - * \brief Starts an EM span thread (monitor) - * \param span Span to monitor - * \return Success or failure - */ -static ftdm_status_t ftdm_analog_em_start(ftdm_span_t *span) -{ - ftdm_analog_em_data_t *analog_data = span->signal_data; - ftdm_set_flag(analog_data, FTDM_ANALOG_EM_RUNNING); - return ftdm_thread_create_detached(ftdm_analog_em_run, span); -} - -static void ftdm_analog_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status) -{ - ftdm_sigmsg_t sig; - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Signalling link status changed to %s\n", ftdm_signaling_status2str(status)); - - memset(&sig, 0, sizeof(sig)); - sig.chan_id = ftdmchan->chan_id; - sig.span_id = ftdmchan->span_id; - sig.channel = ftdmchan; - sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sig.ev_data.sigstatus.status = status; - if (ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to change channel status to %s\n", ftdm_signaling_status2str(status)); - } - return; -} - -/** - * \brief Stops EM span thread (monitor) - * \param span Span to monitor - * \return Success or failure - */ -static ftdm_status_t ftdm_analog_em_stop(ftdm_span_t *span) -{ - ftdm_analog_em_data_t *analog_data = span->signal_data; - ftdm_clear_flag(analog_data, FTDM_ANALOG_EM_RUNNING); - ftdm_sleep(100); - analog_em_set_span_sig_status(span, FTDM_SIG_STATE_SUSPENDED); - return FTDM_SUCCESS; -} - -/** - * \brief Returns the signalling status on a channel - * \param ftdmchan Channel to get status on - * \param status Pointer to set signalling status - * \return Success or failure - */ -static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(analog_em_get_channel_sig_status) -{ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) { - *status = FTDM_SIG_STATE_DOWN; - return FTDM_SUCCESS; - } - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) { - *status = FTDM_SIG_STATE_SUSPENDED; - return FTDM_SUCCESS; - } - *status = FTDM_SIG_STATE_UP; - return FTDM_SUCCESS; -} - -/** - * \brief Returns the signalling status on a span - * \param span Span to get status on - * \param status Pointer to set signalling status - * \return Success or failure - */ -static FIO_SPAN_GET_SIG_STATUS_FUNCTION(analog_em_get_span_sig_status) -{ - ftdm_iterator_t *citer = NULL; - ftdm_iterator_t *chaniter = ftdm_span_get_chan_iterator(span, NULL); - if (!chaniter) { - ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name); - return FTDM_FAIL; - } - /* if ALL channels are in alarm, report DOWN, UP otherwise. */ - *status = FTDM_SIG_STATE_DOWN; - for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) { - ftdm_channel_t *fchan = ftdm_iterator_current(citer); - ftdm_channel_lock(fchan); - if (!ftdm_test_flag(fchan, FTDM_CHANNEL_IN_ALARM)) { - if (!ftdm_test_flag(fchan, FTDM_CHANNEL_SUSPENDED)) { - *status = FTDM_SIG_STATE_UP; - ftdm_channel_unlock(fchan); - break; - } else { - *status = FTDM_SIG_STATE_SUSPENDED; - } - } - ftdm_channel_unlock(fchan); - } - ftdm_iterator_free(chaniter); - return FTDM_SUCCESS; -} - -static ftdm_status_t analog_em_set_channel_sig_status_ex(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status, ftdm_bool_t remote) -{ - switch (status) { - case FTDM_SIG_STATE_DOWN: - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot bring channel down, perhaps you want to try '%s'\n", ftdm_signaling_status2str(FTDM_SIG_STATE_SUSPENDED)); - return FTDM_FAIL; - case FTDM_SIG_STATE_SUSPENDED: - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) { - int cas_bits = 0xFF; - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_CAS_BITS, &cas_bits); - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK)) { - ftdm_channel_command(ftdmchan, FTDM_COMMAND_OFFHOOK, NULL); - } - ftdm_analog_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_SUSPENDED); - } - if (remote) { - ftdm_set_sflag(ftdmchan, FTDM_ANALOG_EM_REMOTE_SUSPEND); - } else { - ftdm_set_sflag(ftdmchan, FTDM_ANALOG_EM_LOCAL_SUSPEND); - } - break; - case FTDM_SIG_STATE_UP: - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) { - if (remote) { - ftdm_clear_sflag(ftdmchan, FTDM_ANALOG_EM_REMOTE_SUSPEND); - } else { - ftdm_clear_sflag(ftdmchan, FTDM_ANALOG_EM_LOCAL_SUSPEND); - } - if (!ftdm_test_sflag(ftdmchan, FTDM_ANALOG_EM_REMOTE_SUSPEND) && - !ftdm_test_sflag(ftdmchan, FTDM_ANALOG_EM_LOCAL_SUSPEND)) { - int cas_bits = 0x00; - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_CAS_BITS, &cas_bits); - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK)) { - ftdm_channel_command(ftdmchan, FTDM_COMMAND_ONHOOK, NULL); - } - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) { - ftdm_analog_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP); - } - } - } - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%d'\n", status); - return FTDM_FAIL; - } - return FTDM_SUCCESS; -} - -static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(analog_em_set_channel_sig_status) -{ - return analog_em_set_channel_sig_status_ex(ftdmchan, status, FTDM_FALSE); -} - -static FIO_SPAN_SET_SIG_STATUS_FUNCTION(analog_em_set_span_sig_status) -{ - ftdm_iterator_t *chaniter = NULL; - ftdm_iterator_t *citer = NULL; - - chaniter = ftdm_span_get_chan_iterator(span, NULL); - if (!chaniter) { - ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name); - return FTDM_FAIL; - } - /* iterate over all channels, setting them to the requested state */ - for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) { - ftdm_channel_t *fchan = ftdm_iterator_current(citer); - /* we set channel's state through analog_em_set_channel_sig_status(), since it already takes care of notifying the user when appropriate */ - ftdm_channel_lock(fchan); - if ((analog_em_set_channel_sig_status_ex(fchan, status, FTDM_FALSE)) != FTDM_SUCCESS) { - ftdm_log_chan(fchan, FTDM_LOG_ERROR, "Failed to set signaling status to %s\n", ftdm_signaling_status2str(status)); - } - ftdm_channel_unlock(fchan); - } - ftdm_iterator_free(chaniter); - return FTDM_SUCCESS; -} - -/** - * \brief Initialises an EM span from configuration variables - * \param span Span to configure - * \param sig_cb Callback function for event signals - * \param ap List of configuration variables - * \return Success or failure - */ -static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_em_configure_span) -//ftdm_status_t ftdm_analog_em_configure_span(ftdm_span_t *span, char *tonemap, uint32_t digit_timeout, uint32_t max_dialstr, fio_signal_cb_t sig_cb) -{ - ftdm_analog_em_data_t *analog_data = NULL; - const char *tonemap = "us"; - const char *ringback_file = ""; - ftdm_bool_t immediate_ringback = FTDM_FALSE; - uint32_t digit_timeout = 2000; - uint32_t max_dialstr = 11; - uint32_t dial_timeout = 0; - uint32_t release_guard_time_ms = 500; - ftdm_bool_t answer_supervision = FTDM_FALSE; - const char *var, *val; - int *intval; - - assert(sig_cb != NULL); - - if (span->signal_type) { - snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling."); - return FTDM_FAIL; - } - - analog_data = ftdm_calloc(1, sizeof(*analog_data)); - assert(analog_data != NULL); - - while((var = va_arg(ap, char *))) { - ftdm_log(FTDM_LOG_DEBUG, "Parsing analog em parameter '%s'\n", var); - if (!strcasecmp(var, "tonemap")) { - if (!(val = va_arg(ap, char *))) { - break; - } - tonemap = val; - } else if (!strcasecmp(var, "immediate_ringback")) { - if (!(val = va_arg(ap, char *))) { - break; - } - immediate_ringback = ftdm_true(val); - } else if (!strcasecmp(var, "ringback_file")) { - if (!(val = va_arg(ap, char *))) { - break; - } - ringback_file = val; - } else if (!strcasecmp(var, "answer_supervision")) { - if (!(val = va_arg(ap, char *))) { - break; - } - answer_supervision = ftdm_true(val); - } else if (!strcasecmp(var, "dial_timeout")) { - if (!(intval = va_arg(ap, int *))) { - break; - } - dial_timeout = *intval; - } else if (!strcasecmp(var, "digit_timeout")) { - if (!(intval = va_arg(ap, int *))) { - break; - } - digit_timeout = *intval; - } else if (!strcasecmp(var, "max_dialstr")) { - if (!(intval = va_arg(ap, int *))) { - break; - } - max_dialstr = *intval; - } else if (!strcasecmp(var, "release_guard_time_ms")) { - if (!(intval = va_arg(ap, int *))) { - break; - } - release_guard_time_ms = *intval; - } else { - ftdm_log(FTDM_LOG_ERROR, "Invalid parameter for analog em span: '%s'\n", var); - return FTDM_FAIL; - } - } - - - if (digit_timeout < 2000 || digit_timeout > 10000) { - digit_timeout = 2000; - } - - if (max_dialstr < 2 || max_dialstr > MAX_DIALSTRING) { - ftdm_log(FTDM_LOG_ERROR, "Invalid max_dialstr, setting to %d\n", MAX_DIALSTRING); - max_dialstr = MAX_DIALSTRING; - } - - span->start = ftdm_analog_em_start; - span->stop = ftdm_analog_em_stop; - span->sig_write = ftdm_analog_em_sig_write; - analog_data->digit_timeout = digit_timeout; - analog_data->max_dialstr = max_dialstr; - analog_data->dial_timeout = dial_timeout; - analog_data->answer_supervision = answer_supervision; - span->signal_cb = sig_cb; - span->signal_type = FTDM_SIGTYPE_ANALOG; - span->signal_data = analog_data; - span->outgoing_call = analog_em_outgoing_call; - span->get_channel_sig_status = analog_em_get_channel_sig_status; - span->get_span_sig_status = analog_em_get_span_sig_status; - span->set_channel_sig_status = analog_em_set_channel_sig_status; - span->set_span_sig_status = analog_em_set_span_sig_status; - span->sig_release_guard_time_ms = release_guard_time_ms; - ftdm_span_load_tones(span, tonemap); - if (immediate_ringback || !ftdm_strlen_zero(ringback_file)) { - analog_data->immediate_ringback = FTDM_TRUE; - ftdm_set_string(analog_data->ringback_file, ringback_file); - } - - return FTDM_SUCCESS; - -} - -/** - * \brief Retrieves tone generation output to be sent - * \param ts Teletone generator - * \param map Tone map - * \return -1 on error, 0 on success - */ -static int teletone_handler(teletone_generation_session_t *ts, teletone_tone_map_t *map) -{ - ftdm_buffer_t *dt_buffer = ts->user_data; - int wrote; - - if (!dt_buffer) { - return -1; - } - wrote = teletone_mux_tones(ts, map); - ftdm_buffer_write(dt_buffer, ts->buffer, wrote * 2); - return 0; -} - -/** - * \brief Main thread function for EM channel (outgoing call) - * \param me Current thread - * \param obj Channel to run in this thread - */ -static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj) -{ - ftdm_channel_t *ftdmchan = (ftdm_channel_t *) obj; - ftdm_buffer_t *dt_buffer = NULL; - teletone_generation_session_t ts; - uint8_t frame[1024]; - ftdm_size_t len, rlen; - ftdm_tone_type_t tt = FTDM_TONE_DTMF; - char dtmf[128] = ""; - ftdm_size_t dtmf_offset = 0; - ftdm_analog_em_data_t *analog_data = ftdmchan->span->signal_data; - ftdm_channel_t *closed_chan; - uint32_t state_counter = 0, elapsed = 0, collecting = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = 30000; - ftdm_sigmsg_t sig; - int cas_bits = 0; - uint32_t cas_answer = 0; - uint32_t cas_hangup = 0; - int cas_answer_ms = 500; - int cas_hangup_ms = 500; - ftdm_bool_t busy_timeout = FTDM_FALSE; - FILE *ringback_f = NULL; - ftdm_bool_t digits_sent = FTDM_FALSE; - - ftdm_unused_arg(me); - ftdm_log(FTDM_LOG_DEBUG, "ANALOG EM CHANNEL thread starting.\n"); - - ts.buffer = NULL; - - if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "OPEN ERROR [%s]\n", ftdmchan->last_error); - goto done; - } - - if (ftdm_buffer_create(&dt_buffer, 1024, 3192, 0) != FTDM_SUCCESS) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "memory error!"); - ftdm_log(FTDM_LOG_ERROR, "MEM ERROR\n"); - goto done; - } - - if (ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_DTMF_DETECT, &tt) != FTDM_SUCCESS) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "error initilizing tone detector!"); - ftdm_log(FTDM_LOG_ERROR, "TONE ERROR\n"); - goto done; - } - - ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_INTHREAD); - teletone_init_session(&ts, 0, teletone_handler, dt_buffer); - ts.rate = 8000; -#if 0 - ts.debug = 1; - ts.debug_stream = stdout; -#endif - ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval); - ftdm_buffer_set_loops(dt_buffer, -1); - - memset(&sig, 0, sizeof(sig)); - sig.chan_id = ftdmchan->chan_id; - sig.span_id = ftdmchan->span_id; - sig.channel = ftdmchan; - - assert(interval != 0); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "IO Interval: %u\n", interval); - - if (analog_data->immediate_ringback && !ftdm_strlen_zero(analog_data->ringback_file)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Using ringback file '%s'\n", analog_data->ringback_file); - ringback_f = fopen(analog_data->ringback_file, "rb"); - if (!ringback_f) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to open ringback file '%s'\n", analog_data->ringback_file); - } else { - if (skip_wave_header(analog_data->ringback_file, ringback_f)) { - ringback_f = NULL; - } - } - } - - while (ftdm_running() && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INTHREAD)) { - ftdm_wait_flag_t flags = FTDM_READ; - ftdm_size_t dlen = 0; - - elapsed += interval; - state_counter += interval; - - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - switch(ftdmchan->state) { - case FTDM_CHANNEL_STATE_DIALING: - { - if (! ftdmchan->needed_tones[FTDM_TONEMAP_RING] - && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_WINK) - && !digits_sent) { - if (ftdm_strlen_zero(ftdmchan->caller_data.dnis.digits)) { - ftdm_log(FTDM_LOG_ERROR, "No Digits to send!\n"); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); - } else { - if (ftdm_channel_command(ftdmchan, FTDM_COMMAND_SEND_DTMF, ftdmchan->caller_data.dnis.digits) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Send Digits Failed [%s]\n", ftdmchan->last_error); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); - } else { - state_counter = 0; - digits_sent = FTDM_TRUE; - ftdmchan->needed_tones[FTDM_TONEMAP_RING] = 1; - ftdmchan->needed_tones[FTDM_TONEMAP_BUSY] = 1; - ftdmchan->needed_tones[FTDM_TONEMAP_FAIL1] = 1; - ftdmchan->needed_tones[FTDM_TONEMAP_FAIL2] = 1; - ftdmchan->needed_tones[FTDM_TONEMAP_FAIL3] = 1; - dial_timeout = ((ftdmchan->dtmf_on + ftdmchan->dtmf_off) * strlen(ftdmchan->caller_data.dnis.digits)) + 2000; - if (analog_data->dial_timeout) { - dial_timeout += analog_data->dial_timeout; - } - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Outbound dialing timeout: %dms\n", dial_timeout); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Outbound CAS answer timeout: %dms\n", cas_answer_ms); - } - } - break; - } - if (state_counter > dial_timeout) { - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_WINK)) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); - } else if (!analog_data->answer_supervision) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); - } - } - cas_bits = 0; - ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_CAS_BITS, &cas_bits); - if (!(state_counter % 1000)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "CAS bits: 0x%X\n", cas_bits); - } - if (cas_bits == 0xF) { - cas_answer += interval; - if (cas_answer >= cas_answer_ms) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Answering on CAS answer signal persistence!\n"); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); - } - } else if (cas_answer) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Resetting cas answer to 0: 0x%X!\n", cas_bits); - cas_answer = 0; - } - } - break; - case FTDM_CHANNEL_STATE_DIALTONE: - { - if (state_counter > 10000) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); - } - } - break; - case FTDM_CHANNEL_STATE_BUSY: - { - if (state_counter > 20000) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_ATTN); - } - } - break; - case FTDM_CHANNEL_STATE_ATTN: - { - if (state_counter > 20000) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - } - break; - case FTDM_CHANNEL_STATE_HANGUP: - { - if (state_counter > 500) { - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) && - (ftdmchan->last_state == FTDM_CHANNEL_STATE_RINGING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE - || ftdmchan->last_state == FTDM_CHANNEL_STATE_RING)) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); - } else { - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING; - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - } - } - break; - case FTDM_CHANNEL_STATE_UP: - case FTDM_CHANNEL_STATE_RING: - { - ftdm_sleep(interval); - if (ftdmchan->state == FTDM_CHANNEL_STATE_UP) { - cas_bits = 0; - ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_CAS_BITS, &cas_bits); - if (cas_bits == 0x0) { - cas_hangup += interval; - if (cas_hangup >= cas_hangup_ms) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Hanging up on CAS hangup signal persistence\n"); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - } - } else if (cas_hangup) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Resetting cas hangup to 0: 0x%X!\n", cas_bits); - cas_hangup = 0; - } - } - continue; - } - break; - case FTDM_CHANNEL_STATE_DOWN: - { - goto done; - } - break; - default: - break; - } - } else { - ftdm_clear_flag_locked(ftdmchan->span, FTDM_SPAN_STATE_CHANGE); - ftdm_channel_complete_state(ftdmchan); - indicate = 0; - state_counter = 0; - - ftdm_log(FTDM_LOG_DEBUG, "Executing state handler on %d:%d for %s\n", - ftdmchan->span_id, ftdmchan->chan_id, - ftdm_channel_state2str(ftdmchan->state)); - switch(ftdmchan->state) { - case FTDM_CHANNEL_STATE_UP: - { - ftdm_channel_use(ftdmchan); - ftdm_channel_clear_needed_tones(ftdmchan); - ftdm_channel_flush_dtmf(ftdmchan); - - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK)) { - ftdm_channel_command(ftdmchan, FTDM_COMMAND_OFFHOOK, NULL); - } - - sig.event_id = FTDM_SIGEVENT_UP; - - ftdm_span_send_signal(ftdmchan->span, &sig); - continue; - } - break; - case FTDM_CHANNEL_STATE_DIALING: - { - ftdm_channel_use(ftdmchan); - } - break; - case FTDM_CHANNEL_STATE_RING: - { - ftdm_channel_use(ftdmchan); - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - ftdm_set_string(ftdmchan->caller_data.dnis.digits, ftdmchan->chan_number); - } else { - ftdm_set_string(ftdmchan->caller_data.dnis.digits, dtmf); - } - - sig.event_id = FTDM_SIGEVENT_START; - - ftdm_span_send_signal(ftdmchan->span, &sig); - continue; - } - break; - case FTDM_CHANNEL_STATE_DOWN: - { - sig.event_id = FTDM_SIGEVENT_STOP; - ftdm_span_send_signal(ftdmchan->span, &sig); - goto done; - } - break; - case FTDM_CHANNEL_STATE_DIALTONE: - { - memset(&ftdmchan->caller_data, 0, sizeof(ftdmchan->caller_data)); - *dtmf = '\0'; - dtmf_offset = 0; - ftdm_buffer_zero(dt_buffer); - teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_DIAL]); - indicate = 1; - - ftdm_channel_command(ftdmchan, FTDM_COMMAND_WINK, NULL); - } - break; - case FTDM_CHANNEL_STATE_RINGING: - { - if (!analog_data->immediate_ringback) { - ftdm_buffer_zero(dt_buffer); - teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_RING]); - indicate = 1; - } - } - break; - case FTDM_CHANNEL_STATE_BUSY: - { - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CIRCUIT_CONGESTION; - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - ftdm_buffer_zero(dt_buffer); - teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_BUSY]); - indicate = 1; - } else { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - busy_timeout = FTDM_TRUE; - } - } - break; - case FTDM_CHANNEL_STATE_ATTN: - { - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - ftdm_buffer_zero(dt_buffer); - teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_ATTN]); - indicate = 1; - } else { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - } - break; - default: - break; - } - } - - - if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALTONE || ftdmchan->state == FTDM_CHANNEL_STATE_COLLECT) { - if ((dlen = ftdm_channel_dequeue_dtmf(ftdmchan, dtmf + dtmf_offset, sizeof(dtmf) - strlen(dtmf)))) { - - if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALTONE) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); - collecting = 1; - } - dtmf_offset = strlen(dtmf); - last_digit = elapsed; - sig.event_id = FTDM_SIGEVENT_COLLECTED_DIGIT; - ftdm_set_string(sig.ev_data.collected.digits, dtmf); - if (ftdm_span_send_signal(ftdmchan->span, &sig) == FTDM_BREAK) { - collecting = 0; - } - } - } - - if (last_digit && (!collecting || ((elapsed - last_digit > analog_data->digit_timeout) || strlen(dtmf) > analog_data->max_dialstr))) { - ftdm_log(FTDM_LOG_DEBUG, "Number obtained [%s]\n", dtmf); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); - last_digit = 0; - collecting = 0; - } - - if (ftdm_channel_wait(ftdmchan, &flags, interval * 2) != FTDM_SUCCESS) { - continue; - } - - if (!(flags & FTDM_READ)) { - continue; - } - - /* Do not try to read more than the proper interval size */ - len = ftdmchan->packet_len * 2; - if (ftdm_channel_read(ftdmchan, frame, &len) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "READ ERROR [%s]\n", ftdmchan->last_error); - goto done; - } - - if (0 == len) { - ftdm_log(FTDM_LOG_DEBUG, "Nothing read\n"); - continue; - } - - if (len >= (sizeof(frame)/2)) { - ftdm_log(FTDM_LOG_CRIT, "Ignoring big read of %zd bytes!\n", len); - continue; - } - - if (ftdmchan->detected_tones[0]) { - int i; - - for (i = 1; i < FTDM_TONEMAP_INVALID; i++) { - if (ftdmchan->detected_tones[i]) { - ftdm_log(FTDM_LOG_DEBUG, "Detected tone %s on %d:%d\n", ftdm_tonemap2str(i), ftdmchan->span_id, ftdmchan->chan_id); - } - } - - if (ftdmchan->detected_tones[FTDM_TONEMAP_BUSY] || - ftdmchan->detected_tones[FTDM_TONEMAP_FAIL1] || - ftdmchan->detected_tones[FTDM_TONEMAP_FAIL2] || - ftdmchan->detected_tones[FTDM_TONEMAP_FAIL3] || - ftdmchan->detected_tones[FTDM_TONEMAP_ATTN] - ) { - ftdm_log(FTDM_LOG_ERROR, "Failure indication detected!\n"); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); - } else if (ftdmchan->detected_tones[FTDM_TONEMAP_RING]) { - if (!analog_data->answer_supervision) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ringing, but not answering since answer supervision is enabled\n"); - } - } - - ftdm_channel_clear_detected_tones(ftdmchan); - } - - if ((ftdmchan->dtmf_buffer && ftdm_buffer_inuse(ftdmchan->dtmf_buffer))) { - rlen = len; - memset(frame, 0, len); - ftdm_channel_write(ftdmchan, frame, sizeof(frame), &rlen); - continue; - } - - if (analog_data->immediate_ringback && - (ftdmchan->state == FTDM_CHANNEL_STATE_COLLECT || - ftdmchan->state == FTDM_CHANNEL_STATE_RING || - ftdmchan->state == FTDM_CHANNEL_STATE_RINGING || - ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS || - ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA - )) { - indicate = 1; - if (!ringback_f) { - ftdm_buffer_zero(dt_buffer); - teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_RING]); - } - } - - if (!indicate) { - continue; - } - - if (ftdmchan->effective_codec != FTDM_CODEC_SLIN) { - len *= 2; - } - - if (ringback_f) { - uint8_t failed_read = 0; -read_try: - rlen = fread(frame, 1, len, ringback_f); - if (rlen != len) { - if (!feof(ringback_f)) { - ftdm_log(FTDM_LOG_ERROR, "Error reading from ringback file: %zd != %zd\n", rlen, len); - } - if (failed_read) { - continue; - } - /* return cursor to start of wav file */ - fseek(ringback_f, WAVE_HEADER_LEN, SEEK_SET); - failed_read++; - goto read_try; - } - } else { - rlen = ftdm_buffer_read_loop(dt_buffer, frame, len); - } - - if (ftdmchan->effective_codec != FTDM_CODEC_SLIN) { - fio_codec_t codec_func = NULL; - - if (ftdmchan->native_codec == FTDM_CODEC_ULAW) { - codec_func = fio_slin2ulaw; - } else if (ftdmchan->native_codec == FTDM_CODEC_ALAW) { - codec_func = fio_slin2alaw; - } - - if (codec_func) { - codec_func(frame, sizeof(frame), &rlen); - } else { - ftdm_log(FTDM_LOG_ERROR, "codec error, no codec function for native codec %d!", ftdmchan->native_codec); - goto done; - } - } - - /* we must lock the channel and make sure we let our own generated audio thru (FTDM_ANALOG_EM_LOCAL_WRITE is tested in the ftdm_analog_em_sig_write handler)*/ - ftdm_channel_lock(ftdmchan); - ftdm_set_sflag(ftdmchan, FTDM_ANALOG_EM_LOCAL_WRITE); - ftdm_channel_write(ftdmchan, frame, sizeof(frame), &rlen); - ftdm_clear_sflag(ftdmchan, FTDM_ANALOG_EM_LOCAL_WRITE); - ftdm_channel_unlock(ftdmchan); - } - - done: - - ftdm_channel_command(ftdmchan, FTDM_COMMAND_ONHOOK, NULL); - if (busy_timeout) { - ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_CAS_BITS, &cas_bits); - if (cas_bits == 0XF) { - /* the remote end never sent any digits, neither moved to onhook, let's stay suspended */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Moving channel to suspended after timeout, remote end still offhook\n"); - analog_em_set_channel_sig_status_ex(ftdmchan, FTDM_SIG_STATE_SUSPENDED, FTDM_TRUE); - } - } - - closed_chan = ftdmchan; - ftdm_channel_close(&ftdmchan); - - ftdm_channel_command(closed_chan, FTDM_COMMAND_SET_NATIVE_CODEC, NULL); - - if (ts.buffer) { - teletone_destroy_session(&ts); - } - - if (dt_buffer) { - ftdm_buffer_destroy(&dt_buffer); - } - - if (ringback_f) { - fclose(ringback_f); - } - - ftdm_clear_flag(closed_chan, FTDM_CHANNEL_INTHREAD); - - ftdm_log(FTDM_LOG_DEBUG, "ANALOG EM CHANNEL thread ended.\n"); - - return NULL; -} - -/** - * \brief Processes EM events coming from ftdmtel/dahdi - * \param span Span on which the event was fired - * \param event Event to be treated - * \return Success or failure - */ -static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *event) -{ - ftdm_sigmsg_t sig; - int locked = 0; - - memset(&sig, 0, sizeof(sig)); - sig.chan_id = event->channel->chan_id; - sig.span_id = event->channel->span_id; - sig.channel = event->channel; - - ftdm_unused_arg(span); - ftdm_log(FTDM_LOG_DEBUG, "EVENT [%s][%d:%d] STATE [%s]\n", - ftdm_oob_event2str(event->enum_id), event->channel->span_id, event->channel->chan_id, ftdm_channel_state2str(event->channel->state)); - - ftdm_mutex_lock(event->channel->mutex); - locked++; - - if (event->enum_id == FTDM_OOB_ONHOOK && ftdm_test_sflag(event->channel, FTDM_ANALOG_EM_REMOTE_SUSPEND)) { - /* We've got remote suspend, now we're back on hook, lift the remote suspend status */ - analog_em_set_channel_sig_status_ex(event->channel, FTDM_SIG_STATE_UP, FTDM_TRUE); - } - - if (ftdm_test_flag(event->channel, FTDM_CHANNEL_SUSPENDED)) { - ftdm_log(FTDM_LOG_WARNING, "Ignoring event %s on channel %d:%d in state %s, channel is suspended\n", - ftdm_oob_event2str(event->enum_id), event->channel->span_id, event->channel->chan_id, ftdm_channel_state2str(event->channel->state)); - goto done; - } - - switch(event->enum_id) { - case FTDM_OOB_ONHOOK: - { - if (event->channel->state != FTDM_CHANNEL_STATE_DOWN) { - ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_DOWN); - } - - } - break; - case FTDM_OOB_OFFHOOK: - { - if (ftdm_test_flag(event->channel, FTDM_CHANNEL_INTHREAD)) { - if (event->channel->state < FTDM_CHANNEL_STATE_UP) { - ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_UP); - } - } else { - ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_DIALTONE); - ftdm_mutex_unlock(event->channel->mutex); - locked = 0; - ftdm_thread_create_detached(ftdm_analog_em_channel_run, event->channel); - } - break; - } - case FTDM_OOB_WINK: - { - if (event->channel->state != FTDM_CHANNEL_STATE_DIALING) { - ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_DOWN); - } else { - ftdm_set_flag_locked(event->channel, FTDM_CHANNEL_WINK); - } - - } - break; - } - -done: - - if (locked) { - ftdm_mutex_unlock(event->channel->mutex); - } - return FTDM_SUCCESS; -} - -/** - * \brief Main thread function for EM span (monitor) - * \param me Current thread - * \param obj Span to run in this thread - */ -static void *ftdm_analog_em_run(ftdm_thread_t *me, void *obj) -{ - ftdm_span_t *span = (ftdm_span_t *) obj; - ftdm_analog_em_data_t *analog_data = span->signal_data; - - ftdm_unused_arg(me); - ftdm_log(FTDM_LOG_DEBUG, "ANALOG EM thread starting.\n"); - analog_em_set_span_sig_status(span, FTDM_SIG_STATE_UP); - - while(ftdm_running() && ftdm_test_flag(analog_data, FTDM_ANALOG_EM_RUNNING)) { - int waitms = 10; - ftdm_status_t status; - - status = ftdm_span_poll_event(span, waitms, NULL); - - switch(status) { - case FTDM_SUCCESS: - { - ftdm_event_t *event; - while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) { - if (event->enum_id == FTDM_OOB_NOOP) { - continue; - } - if (process_event(span, event) != FTDM_SUCCESS) { - goto end; - } - } - } - break; - case FTDM_FAIL: - { - ftdm_log(FTDM_LOG_ERROR, "Failure Polling event! [%s]\n", span->last_error); - } - break; - default: - break; - } - - } - - end: - - ftdm_clear_flag(analog_data, FTDM_ANALOG_EM_RUNNING); - - ftdm_log(FTDM_LOG_DEBUG, "ANALOG EM thread ending.\n"); - - return NULL; -} - -/** - * \brief FreeTDM analog EM module initialisation - * \return Success - */ -static FIO_SIG_LOAD_FUNCTION(ftdm_analog_em_init) -{ - return FTDM_SUCCESS; -} - -/** - * \brief FreeTDM analog EM module definition - */ -EX_DECLARE_DATA ftdm_module_t ftdm_module = { - "analog_em", - NULL, - NULL, - ftdm_analog_em_init, - ftdm_analog_em_configure_span, - NULL -}; - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftmod/ftmod_gsm/ftmod_gsm.c b/libs/freetdm/src/ftmod/ftmod_gsm/ftmod_gsm.c deleted file mode 100755 index 0dbe1e647b..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_gsm/ftmod_gsm.c +++ /dev/null @@ -1,1592 +0,0 @@ -/* - * Copyright (c) 2011, Sangoma Technologies - * All rights reserved. - * - Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Contributors: - * - * Gideon Sadan - * Moises Silva - * - */ - - -#define _GNU_SOURCE - -#include -#include - -#ifndef __WINDOWS__ -#include -#include -#include -#endif - -#include -#include -#include -/*========================*/ - -#include -#include -#include - -#include - -/********************************************************************************/ -/* */ -/* MACROS */ -/* */ -/********************************************************************************/ -// Macro to send signals -#define SEND_STATE_SIGNAL(sig) \ - { \ - ftdm_sigmsg_t sigev; \ - memset(&sigev, 0, sizeof(sigev)); \ - sigev.event_id = sig; \ - sigev.channel = ftdmchan; \ - ftdm_span_send_signal(ftdmchan->span, &sigev); \ - } - -// Syntax message -#define FT_SYNTAX "USAGE:\n" \ -"--------------------------------------------------------------------------------\n" \ -"ftdm gsm version \n" \ -"ftdm gsm status \n" \ -"ftdm gsm sms \n" \ -"ftdm gsm exec \n" \ -"ftdm gsm call [number]\n" \ -"--------------------------------------------------------------------------------\n" - -// Used to declare command handler -#define COMMAND_HANDLER(name) \ - static ftdm_status_t gsm_cmd_##name(ftdm_stream_handle_t *stream, char *argv[], int argc); \ - ftdm_status_t gsm_cmd_##name(ftdm_stream_handle_t *stream, char *argv[], int argc) - -// Used to define command entry in the command map -#define COMMAND(name, argc) {#name, argc, gsm_cmd_##name} - -/********************************************************************************/ -/* */ -/* types */ -/* */ -/********************************************************************************/ - -typedef enum { - FTDM_GSM_RUNNING = (1 << 0), - FTDM_GSM_SPAN_STARTED = (1 << 1), -} ftdm_gsm_flag_t; - -// private data -typedef struct ftdm_gsm_span_data_s { - ftdm_span_t *span; - ftdm_channel_t *dchan; - ftdm_channel_t *bchan; - int32_t call_id; - uint32_t sms_id; - char conditional_forward_prefix[10]; - char conditional_forward_number[50]; - char immediate_forward_prefix[10]; - struct { - char number[50]; - char span[50]; - } immediate_forward_numbers[10]; - char disable_forward_number[50]; - ftdm_sched_t *sched; - ftdm_timer_id_t conditional_forwarding_timer; - ftdm_timer_id_t immediate_forwarding_timer; - ftdm_bool_t init_conditional_forwarding; - ftdm_bool_t startup_forwarding_disabled; - char startup_commands[20][50]; - ftdm_gsm_flag_t flags; - ftdm_bool_t sig_up; -} ftdm_gsm_span_data_t; - -// command handler function type. -typedef ftdm_status_t (*command_handler_t)(ftdm_stream_handle_t *stream, char *argv[], int argc); - -typedef struct ftdm_gsm_exec_helper { - ftdm_span_t *span; - ftdm_stream_handle_t *stream; - uint8_t cmd_pending; -} ftdm_gsm_exec_helper_t; - -/********************************************************************************/ -/* */ -/* function declaration */ -/* */ -/********************************************************************************/ -static ftdm_status_t init_wat_lib(void); -static int wat_lib_initialized = 0; -static FIO_API_FUNCTION(ftdm_gsm_api); - -/* ugh, wasteful since unlikely anyone will ever have more than 4 or 8 GSM spans, but we couldn't use ftdm_find_span() - * because during the stop sequence the internal span lock is held and we end up deadlocked, ideally libwat would just give - * us a pointer we provide instead of a span id */ -static ftdm_span_t * span_map[255] = { 0 }; - -/* wat callbacks */ -static int on_wat_span_write(unsigned char span_id, void *buffer, unsigned len); - -static void on_wat_con_ind(unsigned char span_id, uint8_t call_id, wat_con_event_t *con_event); -static void on_wat_con_sts(unsigned char span_id, uint8_t call_id, wat_con_status_t *status); -static void on_wat_rel_ind(unsigned char span_id, uint8_t call_id, wat_rel_event_t *rel_event); -static void on_wat_rel_cfm(unsigned char span_id, uint8_t call_id); -static void on_wat_sms_ind(unsigned char span_id, wat_sms_event_t *sms_event); -static void on_wat_sms_sts(unsigned char span_id, uint8_t sms_id, wat_sms_status_t *status); - -static void on_wat_log(uint8_t level, char *fmt, ...); -static void *on_wat_malloc(size_t size); -static void *on_wat_calloc(size_t nmemb, size_t size); -static void on_wat_free(void *ptr); -static void on_wat_log_span(uint8_t span_id, uint8_t level, char *fmt, ...); - -static ftdm_span_t *get_span_by_id(uint8_t span_id, ftdm_gsm_span_data_t **gsm_data); - -static void *ftdm_gsm_run(ftdm_thread_t *me, void *obj); - -/********************************************************************************/ -/* */ -/* static & global data */ -/* */ -/********************************************************************************/ - -/* At the moment we support only one concurrent call per span, so no need to have different ids */ -#define GSM_OUTBOUND_CALL_ID 8 - -/* IO interface for the command API */ -static ftdm_io_interface_t g_ftdm_gsm_interface; - -/********************************************************************************/ -/* */ -/* implementation */ -/* */ -/********************************************************************************/ -static int on_wat_span_write(unsigned char span_id, void *buffer, unsigned len) -{ - ftdm_span_t *span = NULL; - ftdm_status_t status = FTDM_FAIL; - ftdm_gsm_span_data_t *gsm_data = NULL; - ftdm_size_t outsize = len; - - status = ftdm_span_find(span_id, &span); - if (status != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Failed to find span %d to write %d bytes\n", span_id, len); - return -1; - } - - gsm_data = span->signal_data; - status = ftdm_channel_write(gsm_data->dchan, (void *)buffer, len, &outsize); - if (status != FTDM_SUCCESS) { - char errbuf[255]; - ftdm_log(FTDM_LOG_ERROR, "Failed to write %d bytes to d-channel in span %s: %s\n", len, span->name, strerror_r(errno, errbuf, sizeof(errbuf))); - return -1; - } - return len; -} - -static void ftdm_gsm_make_raw_call(ftdm_gsm_span_data_t *gsm_data, const char *number) -{ - wat_con_event_t con_event; - - ftdm_channel_lock(gsm_data->bchan); - - if (ftdm_test_flag(gsm_data->bchan, FTDM_CHANNEL_INUSE)) { - ftdm_log_chan(gsm_data->bchan, FTDM_LOG_ERROR, "Failed to place raw call to %s: channel busy\n", number); - goto done; - } - - ftdm_log_chan(gsm_data->bchan, FTDM_LOG_INFO, "Placing raw call to %s\n", number); - ftdm_set_flag(gsm_data->bchan, FTDM_CHANNEL_INUSE); - - gsm_data->call_id = GSM_OUTBOUND_CALL_ID; - memset(&con_event, 0, sizeof(con_event)); - ftdm_set_string(con_event.called_num.digits, number); - wat_con_req(gsm_data->span->span_id, gsm_data->call_id , &con_event); - -done: - ftdm_channel_unlock(gsm_data->bchan); -} - -static void ftdm_gsm_enable_conditional_forwarding(void *data) -{ - char number[255]; - ftdm_gsm_span_data_t *gsm_data = data; - snprintf(number, sizeof(number), "%s%s", gsm_data->conditional_forward_prefix, gsm_data->conditional_forward_number); - ftdm_log_chan(gsm_data->bchan, FTDM_LOG_INFO, "Enabling conditional forwarding to %s\n", number); - ftdm_gsm_make_raw_call(data, number); -} - -static void on_wat_span_status(unsigned char span_id, wat_span_status_t *status) -{ - ftdm_gsm_span_data_t *gsm_data = NULL; - ftdm_span_t *span = get_span_by_id(span_id, &gsm_data); - - switch (status->type) { - case WAT_SPAN_STS_READY: - { - int i = 0; - ftdm_log(FTDM_LOG_INFO, "span %s: Ready\n", span->name); - for (i = 0; !ftdm_strlen_zero_buf(gsm_data->startup_commands[i]); i++) { - ftdm_log(FTDM_LOG_INFO, "span %d: Executing startup command '%s'\n", span_id, gsm_data->startup_commands[i]); - if (WAT_SUCCESS != wat_cmd_req(span_id, gsm_data->startup_commands[i], NULL, NULL)) { - ftdm_log(FTDM_LOG_ERROR, "span %d: Failed requesting execution of command '%s'\n", span_id, gsm_data->startup_commands[i]); - } - } - } - break; - case WAT_SPAN_STS_SIGSTATUS: - { - if (status->sts.sigstatus == WAT_SIGSTATUS_UP) { - ftdm_log_chan_msg(gsm_data->bchan, FTDM_LOG_INFO, "Signaling is now up\n"); - gsm_data->sig_up = FTDM_TRUE; - } else { - ftdm_log_chan_msg(gsm_data->bchan, FTDM_LOG_INFO, "Signaling is now down\n"); - gsm_data->sig_up = FTDM_FALSE; - } - if (gsm_data->init_conditional_forwarding == FTDM_TRUE && !ftdm_strlen_zero_buf(gsm_data->conditional_forward_number)) { - ftdm_sched_timer(gsm_data->sched, "conditional_forwarding_delay", 1000, - ftdm_gsm_enable_conditional_forwarding, - gsm_data, - &gsm_data->conditional_forwarding_timer); - gsm_data->init_conditional_forwarding = FTDM_FALSE; - } - } - break; - case WAT_SPAN_STS_SIM_INFO_READY: - { - const wat_sim_info_t *sim_info = NULL; - ftdm_log(FTDM_LOG_INFO, "span %s: SIM information ready\n", span->name); - sim_info = wat_span_get_sim_info(span->span_id); - if (!ftdm_strlen_zero(sim_info->subscriber.digits)) { - ftdm_set_string(gsm_data->bchan->chan_number, sim_info->subscriber.digits); - } - } - break; - case WAT_SPAN_STS_ALARM: - { - ftdm_log(FTDM_LOG_INFO, "span %s: Alarm received\n", span->name); - } - break; - default: - { - ftdm_log(FTDM_LOG_INFO, "span %s: Unhandled span status notification %d\n", span->name, status->type); - } - break; - } -} - -static void on_wat_con_ind(uint8_t span_id, uint8_t call_id, wat_con_event_t *con_event) -{ - ftdm_span_t *span = NULL; - ftdm_gsm_span_data_t *gsm_data = NULL; - - ftdm_log(FTDM_LOG_INFO, "s%d: Incoming call (id:%d) Calling Number:%s Calling Name:\"%s\" type:%d plan:%d\n", span_id, call_id, con_event->calling_num.digits, con_event->calling_name, con_event->calling_num.type, con_event->calling_num.plan); - - span = get_span_by_id(span_id, &gsm_data); - - gsm_data->call_id = call_id; - - // cid name - ftdm_set_string(gsm_data->bchan->caller_data.cid_name, con_event->calling_name); - - // cid number - ftdm_set_string(gsm_data->bchan->caller_data.cid_num.digits, con_event->calling_num.digits); - - // destination number - ftdm_set_string(gsm_data->bchan->caller_data.dnis.digits, gsm_data->bchan->chan_number); - - ftdm_set_state(gsm_data->bchan, FTDM_CHANNEL_STATE_RING); - - if (ftdm_channel_open_chan(gsm_data->bchan) != FTDM_SUCCESS) { - ftdm_log_chan(gsm_data->bchan, FTDM_LOG_ERROR, "Failed to open GSM b-channel of span %s!\n", span->name); - } - -} - -static ftdm_span_t *get_span_by_id(unsigned char span_id, ftdm_gsm_span_data_t **gsm_data) -{ - ftdm_span_t *span = NULL; - - if (gsm_data) { - (*gsm_data) = NULL; - } - - span = span_map[span_id]; - if (gsm_data) { - (*gsm_data) = span->signal_data; - } - return span; -} - -static void on_wat_con_sts(unsigned char span_id, uint8_t call_id, wat_con_status_t *status) -{ - ftdm_span_t *span = NULL; - ftdm_channel_state_t state = FTDM_CHANNEL_STATE_END; - ftdm_gsm_span_data_t *gsm_data = NULL; - - if (!(span = get_span_by_id(span_id, &gsm_data))) { - return; - } - - switch (status->type) { - case WAT_CON_STATUS_TYPE_RINGING: - ftdm_log_chan_msg(gsm_data->bchan, FTDM_LOG_INFO, "Received ringing indication\n"); - state = FTDM_CHANNEL_STATE_RINGING; - break; - - case WAT_CON_STATUS_TYPE_ANSWER: - ftdm_log_chan_msg(gsm_data->bchan, FTDM_LOG_INFO, "Received answer indication\n"); - state = FTDM_CHANNEL_STATE_PROGRESS_MEDIA; - break; - - default: - ftdm_log_chan(gsm_data->bchan, FTDM_LOG_WARNING, "Unhandled indication status %d\n", status->type); - break; - - } - - if (state != FTDM_CHANNEL_STATE_END && gsm_data->bchan->state != FTDM_CHANNEL_STATE_DOWN) { - ftdm_set_state(gsm_data->bchan, state); - } -} - -static void on_wat_rel_ind(unsigned char span_id, uint8_t call_id, wat_rel_event_t *rel_event) -{ - ftdm_span_t *span = NULL; - ftdm_gsm_span_data_t *gsm_data = NULL; - - ftdm_log(FTDM_LOG_INFO, "s%d: Call hangup (id:%d) cause:%d\n", span_id, call_id, rel_event->cause); - - if (!(span = get_span_by_id(span_id, &gsm_data))) { - return; - } - - if (gsm_data->bchan->state == FTDM_CHANNEL_STATE_DOWN) { - /* This is most likely due to a call to enable call - * forwarding, which does not run the state machine */ - ftdm_clear_flag(gsm_data->bchan, FTDM_CHANNEL_INUSE); - wat_rel_req(span_id, call_id); - return; - } - - if (gsm_data->bchan->state > FTDM_CHANNEL_STATE_DOWN && - gsm_data->bchan->state < FTDM_CHANNEL_STATE_HANGUP) { - ftdm_set_state(gsm_data->bchan, FTDM_CHANNEL_STATE_HANGUP); - } -} - -static void on_wat_rel_cfm(unsigned char span_id, uint8_t call_id) -{ - ftdm_span_t *span = NULL; - ftdm_gsm_span_data_t *gsm_data = NULL; - - ftdm_log(FTDM_LOG_INFO, "s%d: Call hangup complete (id:%d)\n", span_id, call_id); - - if (!(span = get_span_by_id(span_id, &gsm_data))) { - return; - } - - if (gsm_data->bchan->state == FTDM_CHANNEL_STATE_DOWN) { - /* This is most likely due to a call to enable call - * forwarding, which does not run the state machine */ - ftdm_clear_flag(gsm_data->bchan, FTDM_CHANNEL_INUSE); - return; - } - - switch(gsm_data->dchan->state) { - case FTDM_CHANNEL_STATE_UP: - ftdm_set_state(gsm_data->bchan, FTDM_CHANNEL_STATE_HANGUP); - break; - default: - ftdm_set_state(gsm_data->bchan, FTDM_CHANNEL_STATE_DOWN); - break; - } -} - -static void on_wat_sms_ind(unsigned char span_id, wat_sms_event_t *sms_event) -{ - ftdm_span_t *span = NULL; - ftdm_channel_t *ftdmchan; - - ftdm_gsm_span_data_t *gsm_data = NULL; - - if(!(span = get_span_by_id(span_id, &gsm_data))) { - return; - } - - ftdmchan = gsm_data->dchan; - - { - ftdm_sms_data_t sms_data; - ftdm_sigmsg_t sigev; - memset(&sms_data, 0, sizeof(sms_data)); - - strncpy(sms_data.from, sms_event->from.digits, sizeof(sms_data.from)); - strncpy(sms_data.body, sms_event->content.data, sizeof(sms_data.body)); - - memset(&sigev, 0, sizeof(sigev)); - sigev.event_id = FTDM_SIGEVENT_SMS; - sigev.channel = ftdmchan ; - gsm_data->dchan->caller_data.priv = (void *)&sms_data; - ftdm_span_send_signal(span, &sigev); - } - return; -} - -static void on_wat_sms_sts(unsigned char span_id, uint8_t sms_id, wat_sms_status_t *status) -{ - if (status->success) { - ftdm_log(FTDM_LOG_INFO, "Span %d SMS Send - OK\n", span_id ); - } else { - ftdm_log(FTDM_LOG_CRIT, "Span %d SMS Send - FAIL (%s)\n", span_id, status->error); - } -} - -static void on_wat_dtmf_ind(unsigned char span_id, const char *dtmf) -{ - ftdm_span_t *span = NULL; - ftdm_gsm_span_data_t *gsm_data = NULL; - - if (!(span = get_span_by_id(span_id, &gsm_data))) { - return; - } - - ftdm_channel_queue_dtmf(gsm_data->bchan, dtmf); -} - - -static void on_wat_log(uint8_t level, char *fmt, ...) -{ - int ftdm_level; - char buff[4096]; - - va_list argptr; - va_start(argptr, fmt); - - switch(level) { - case WAT_LOG_CRIT: ftdm_level = FTDM_LOG_LEVEL_CRIT; break; - case WAT_LOG_ERROR: ftdm_level = FTDM_LOG_LEVEL_ERROR; break; - case WAT_LOG_WARNING: ftdm_level = FTDM_LOG_LEVEL_WARNING; break; - case WAT_LOG_INFO: ftdm_level = FTDM_LOG_LEVEL_INFO; break; - case WAT_LOG_NOTICE: ftdm_level = FTDM_LOG_LEVEL_NOTICE; break; - case WAT_LOG_DEBUG: ftdm_level = FTDM_LOG_LEVEL_DEBUG; break; - default: ftdm_level = FTDM_LOG_LEVEL_ERROR; break; - }; - - - vsprintf(buff, fmt, argptr); - - ftdm_log(FTDM_PRE, ftdm_level, "%s", buff); - - va_end(argptr); -} - - -static void *on_wat_malloc(size_t size) -{ - return ftdm_malloc(size); -} - -static void *on_wat_calloc(size_t nmemb, size_t size) -{ - return ftdm_calloc(nmemb, size); -} - -static void on_wat_free(void *ptr) -{ - ftdm_free(ptr); -} - -static void on_wat_log_span(uint8_t span_id, uint8_t level, char *fmt, ...) -{ - ftdm_span_t *span = NULL; - ftdm_gsm_span_data_t *gsm_data = NULL; - int ftdm_level; - char buff[4096]; - va_list argptr; - - if (!(span = get_span_by_id(span_id, &gsm_data))) { - return; - } - - va_start(argptr, fmt); - - switch(level) { - case WAT_LOG_CRIT: ftdm_level = FTDM_LOG_LEVEL_CRIT; break; - case WAT_LOG_ERROR: ftdm_level = FTDM_LOG_LEVEL_ERROR; break; - case WAT_LOG_WARNING: ftdm_level = FTDM_LOG_LEVEL_WARNING; break; - case WAT_LOG_INFO: ftdm_level = FTDM_LOG_LEVEL_INFO; break; - case WAT_LOG_NOTICE: ftdm_level = FTDM_LOG_LEVEL_NOTICE; break; - case WAT_LOG_DEBUG: ftdm_level = FTDM_LOG_LEVEL_DEBUG; break; - default: ftdm_level = FTDM_LOG_LEVEL_ERROR; break; - }; - - vsprintf(buff, fmt, argptr); - - ftdm_log_chan_ex(gsm_data->bchan, __FILE__, __FTDM_FUNC__, __LINE__, ftdm_level, "%s", buff); - - va_end(argptr); -} - - -/* END wat callbacks */ - -/* span monitor thread */ -static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(gsm_outgoing_call) -{ - return FTDM_SUCCESS; -} - -static ftdm_status_t ftdm_gsm_start(ftdm_span_t *span) -{ - ftdm_gsm_span_data_t *gsm_data = span->signal_data; - ftdm_set_flag(gsm_data, FTDM_GSM_SPAN_STARTED); - return ftdm_thread_create_detached(ftdm_gsm_run, span); -} - -static ftdm_status_t ftdm_gsm_stop(ftdm_span_t *span) -{ - ftdm_gsm_span_data_t *gsm_data = span->signal_data; - ftdm_clear_flag(gsm_data, FTDM_GSM_SPAN_STARTED); - while (ftdm_test_flag(gsm_data, FTDM_GSM_RUNNING)) { - ftdm_log(FTDM_LOG_DEBUG, "Waiting for GSM span %s\n", span->name); - ftdm_sleep(100); - } - return FTDM_SUCCESS; -} - -static ftdm_status_t ftdm_gsm_destroy(ftdm_span_t *span) -{ - ftdm_gsm_span_data_t *gsm_data = span->signal_data; - ftdm_assert_return(gsm_data != NULL, FTDM_FAIL, "Span does not have GSM data!\n"); - if (gsm_data->sched) { - ftdm_sched_destroy(&gsm_data->sched); - } - ftdm_free(gsm_data); - return FTDM_SUCCESS; -} - -static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_gsm_get_channel_sig_status) -{ - ftdm_gsm_span_data_t *gsm_data = ftdmchan->span->signal_data; - *status = gsm_data->sig_up ? FTDM_SIG_STATE_UP : FTDM_SIG_STATE_DOWN; - return FTDM_SUCCESS; -} - -static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_gsm_set_channel_sig_status) -{ - ftdm_log(FTDM_LOG_ERROR, "You cannot set the signaling status for GSM channels (%s)\n", ftdmchan->span->name); - return FTDM_FAIL; -} - -static FIO_SPAN_GET_SIG_STATUS_FUNCTION(ftdm_gsm_get_span_sig_status) -{ - ftdm_gsm_span_data_t *gsm_data = span->signal_data; - *status = gsm_data->sig_up ? FTDM_SIG_STATE_UP : FTDM_SIG_STATE_DOWN; - return FTDM_SUCCESS; -} - -static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_gsm_set_span_sig_status) -{ - ftdm_log(FTDM_LOG_ERROR, "You cannot set the signaling status for GSM spans (%s)\n", span->name); - return FTDM_FAIL; -} - -static ftdm_state_map_t gsm_state_map = { - { - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_ANY, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - }, - - /* Outbound states */ - - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_ANY, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_END} - }, - - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END} - }, - - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_END} - }, - - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_END} - }, - - - - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END} - }, - - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END} - }, - - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END} - }, - - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END} - }, - } -}; - -#define immediate_forward_enabled(gsm_data) !ftdm_strlen_zero_buf(gsm_data->immediate_forward_numbers[0].number) - -static void perform_enable_immediate_forward(void *data) -{ - ftdm_span_t *fwd_span = NULL; - ftdm_gsm_span_data_t *fwd_gsm_data = NULL; - char *fwd_span_name = NULL; - char *number = NULL; - char cmd[100]; - int i = 0; - ftdm_channel_t *ftdmchan = data; - ftdm_gsm_span_data_t *gsm_data = ftdmchan->span->signal_data; - - for (i = 0; i < ftdm_array_len(gsm_data->immediate_forward_numbers); i++) { - fwd_span_name = gsm_data->immediate_forward_numbers[i].span; - fwd_span = NULL; - if (!ftdm_strlen_zero_buf(fwd_span_name) && - ftdm_span_find_by_name(fwd_span_name, &fwd_span) != FTDM_SUCCESS) { - continue; - } - fwd_gsm_data = fwd_span ? fwd_span->signal_data : NULL; - if (fwd_gsm_data && fwd_gsm_data->call_id) { - /* span busy, do not forward here */ - continue; - } - number = gsm_data->immediate_forward_numbers[i].number; - break; - } - - if (!number) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "No numbers available to enable immediate forwarding\n"); - return; - } - - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Enabling immediate forwarding to %s\n", number); - snprintf(cmd, sizeof(cmd), "ATD%s%s", gsm_data->immediate_forward_prefix, number); - wat_cmd_req(ftdmchan->span->span_id, cmd, NULL, NULL); -} - -static __inline__ void enable_immediate_forward(ftdm_channel_t *ftdmchan) -{ - ftdm_gsm_span_data_t *gsm_data = ftdmchan->span->signal_data; - ftdm_sched_timer(gsm_data->sched, "immediate_forwarding_delay", 1000, - perform_enable_immediate_forward, - ftdmchan, - &gsm_data->immediate_forwarding_timer); -} - -static __inline__ void disable_all_forwarding(ftdm_channel_t *ftdmchan) -{ - char cmd[100]; - ftdm_gsm_span_data_t *gsm_data = ftdmchan->span->signal_data; - - if (ftdm_strlen_zero_buf(gsm_data->disable_forward_number)) { - return; - } - - snprintf(cmd, sizeof(cmd), "ATD%s", gsm_data->disable_forward_number); - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Disabling GSM immediate forward dialing %s\n", gsm_data->disable_forward_number); - wat_cmd_req(ftdmchan->span->span_id, cmd, NULL, NULL); -} - -static ftdm_status_t ftdm_gsm_state_advance(ftdm_channel_t *ftdmchan) -{ - ftdm_gsm_span_data_t *gsm_data = ftdmchan->span->signal_data; - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Executing GSM state handler for %s\n", ftdm_channel_state2str(ftdmchan->state)); - - ftdm_channel_complete_state(ftdmchan); - - switch (ftdmchan->state) { - - /* starting an outgoing call */ - case FTDM_CHANNEL_STATE_DIALING: - { - uint32_t interval = 0; - wat_con_event_t con_event; - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Starting outgoing call with interval %d\n", interval); - - gsm_data->call_id = GSM_OUTBOUND_CALL_ID; - memset(&con_event, 0, sizeof(con_event)); - ftdm_set_string(con_event.called_num.digits, ftdmchan->caller_data.dnis.digits); - ftdm_log(FTDM_LOG_DEBUG, "Dialing number %s\n", con_event.called_num.digits); - wat_con_req(ftdmchan->span->span_id, gsm_data->call_id , &con_event); - - SEND_STATE_SIGNAL(FTDM_SIGEVENT_DIALING); - } - break; - - /* incoming call was offered */ - case FTDM_CHANNEL_STATE_RING: - { - /* notify the user about the new call */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Inbound call detected\n"); - SEND_STATE_SIGNAL(FTDM_SIGEVENT_START); - } - break; - - /* the call is making progress */ - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - { - SEND_STATE_SIGNAL(FTDM_SIGEVENT_PROGRESS_MEDIA); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); - } - break; - - /* the call was answered */ - case FTDM_CHANNEL_STATE_UP: - { - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - SEND_STATE_SIGNAL(FTDM_SIGEVENT_UP); - } else { - wat_con_cfm(ftdmchan->span->span_id, gsm_data->call_id); - } - if (immediate_forward_enabled(gsm_data)) { - enable_immediate_forward(ftdmchan); - } - } - break; - - /* just got hangup */ - case FTDM_CHANNEL_STATE_HANGUP: - { - wat_rel_req(ftdmchan->span->span_id, gsm_data->call_id); - SEND_STATE_SIGNAL(FTDM_SIGEVENT_STOP); - } - break; - - /* finished call for good */ - case FTDM_CHANNEL_STATE_DOWN: - { - ftdm_channel_t *closed_chan; - gsm_data->call_id = 0; - closed_chan = ftdmchan; - ftdm_channel_close(&closed_chan); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "State processing ended.\n"); - SEND_STATE_SIGNAL(FTDM_SIGEVENT_STOP); - if (immediate_forward_enabled(gsm_data)) { - disable_all_forwarding(ftdmchan); - } - } - break; - - /* Outbound call is ringing */ - case FTDM_CHANNEL_STATE_RINGING: - { - SEND_STATE_SIGNAL(FTDM_SIGEVENT_RINGING); - } - break; - - case FTDM_CHANNEL_STATE_RESET: - { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - break; - - default: - { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Unhandled channel state: %s\n", ftdm_channel_state2str(ftdmchan->state)); - } - break; - } - - return FTDM_SUCCESS; -} - -static ftdm_status_t init_wat_lib(void) -{ - wat_interface_t wat_interface; - - if (wat_lib_initialized) { - return FTDM_SUCCESS; - } - - ftdm_log(FTDM_LOG_DEBUG, "Registering interface to WAT Library...\n"); - - memset(&wat_interface, 0, sizeof(wat_interface)); - wat_interface.wat_span_write = on_wat_span_write; - - wat_interface.wat_log = on_wat_log; - wat_interface.wat_log_span = on_wat_log_span; - wat_interface.wat_malloc = on_wat_malloc; - wat_interface.wat_calloc = on_wat_calloc; - wat_interface.wat_free = on_wat_free; - - wat_interface.wat_con_ind = on_wat_con_ind; - wat_interface.wat_con_sts = on_wat_con_sts; - wat_interface.wat_rel_ind = on_wat_rel_ind; - wat_interface.wat_rel_cfm = on_wat_rel_cfm; - wat_interface.wat_sms_ind = on_wat_sms_ind; - wat_interface.wat_sms_sts = on_wat_sms_sts; - wat_interface.wat_span_sts = on_wat_span_status; - wat_interface.wat_dtmf_ind = on_wat_dtmf_ind; - - if (wat_register(&wat_interface)) { - ftdm_log(FTDM_LOG_DEBUG, "Failed registering interface to WAT library ...\n"); - return FTDM_FAIL; - } - - ftdm_log(FTDM_LOG_DEBUG, "Registered interface to WAT library\n"); - - wat_lib_initialized = 1; - return FTDM_SUCCESS; -} - -WAT_AT_CMD_RESPONSE_FUNC(on_dtmf_sent) -{ - ftdm_channel_t *ftdmchan = obj; - ftdm_span_t *span = ftdmchan->span; - int i = 0; - - if (success == WAT_TRUE) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "DTMF successfully transmitted on span %s\n", span->name); - } else { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Command execution failed on span %s. Err: %s\n", span->name, error); - } - - for (i = 0; tokens[i]; i++) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "%s\n", tokens[i]); - } - return i; -} - -static ftdm_status_t ftdm_gsm_send_dtmf(ftdm_channel_t *ftdmchan, const char* dtmf) -{ - ftdm_gsm_span_data_t *gsm_data = ftdmchan->span->signal_data; - wat_send_dtmf(ftdmchan->span->span_id, gsm_data->call_id, dtmf, on_dtmf_sent, ftdmchan); - return FTDM_SUCCESS; -} - -static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling) -{ - wat_span_config_t span_config; - ftdm_gsm_span_data_t *gsm_data = NULL; - ftdm_iterator_t *chaniter = NULL; - ftdm_iterator_t *citer = NULL; - ftdm_channel_t *ftdmchan = NULL; - ftdm_channel_t *dchan = NULL; - ftdm_channel_t *bchan = NULL; - ftdm_bool_t hwdtmf_detect = FTDM_FALSE; - ftdm_bool_t hwdtmf_generate = FTDM_FALSE; - - unsigned paramindex = 0; - const char *var = NULL; - const char *val = NULL; - char schedname[255]; - int cmdindex = 0; - - int codec = FTDM_CODEC_SLIN; - int interval = 20; - - /* libwat is smart enough to set good default values for the timers if they are set to 0 */ - memset(&span_config, 0, sizeof(span_config)); - - /* set some span defaults */ - span_config.moduletype = WAT_MODULE_TELIT; - span_config.hardware_dtmf = WAT_FALSE; - - if (FTDM_SUCCESS != init_wat_lib()) { - return FTDM_FAIL; - } - - if (!sig_cb) { - ftdm_log(FTDM_LOG_ERROR, "No signaling callback provided\n"); - return FTDM_FAIL; - } - - if (span->signal_type) { - ftdm_log(FTDM_LOG_ERROR, "Span %s is already configured for another signaling\n", span->name); - return FTDM_FAIL; - } - - /* verify the span has one d-channel */ - chaniter = ftdm_span_get_chan_iterator(span, NULL); - - if (!chaniter) { - ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name); - return FTDM_FAIL; - } - - citer = ftdm_span_get_chan_iterator(span, chaniter); - for ( ; citer; citer = ftdm_iterator_next(citer)) { - ftdmchan = ftdm_iterator_current(citer); - - if ((NULL == dchan) && FTDM_IS_DCHAN(ftdmchan)) { - dchan = ftdmchan; - } - if ((NULL == bchan) && FTDM_IS_VOICE_CHANNEL(ftdmchan)) { - bchan = ftdmchan; - } - - } - ftdm_iterator_free(chaniter); - - if (!dchan) { - ftdm_log(FTDM_LOG_CRIT, "Could not find a d-channel for GSM span %s!\n", span->name); - return FTDM_FAIL; - } - if (!bchan) { - ftdm_log(FTDM_LOG_CRIT, "Could not find a b-channel for GSM span %s!\n", span->name); - return FTDM_FAIL; - } - - gsm_data = ftdm_calloc(1, sizeof(*gsm_data)); - if (!gsm_data) { - return FTDM_FAIL; - } - gsm_data->dchan = dchan; - gsm_data->bchan = bchan; - - cmdindex = 0; - for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) { - var = ftdm_parameters[paramindex].var; - val = ftdm_parameters[paramindex].val; - if (ftdm_strlen_zero_buf(val)) { - ftdm_log(FTDM_LOG_WARNING, "Ignoring empty GSM parameter %s for span %s\n", var, span->name); - continue; - } - ftdm_log(FTDM_LOG_DEBUG, "Reading GSM parameter %s=%s for span %s\n", var, val, span->name); - if (!strcasecmp(var, "moduletype")) { - span_config.moduletype = wat_str2wat_moduletype(val); - if (span_config.moduletype == WAT_MODULE_INVALID) { - ftdm_log(FTDM_LOG_ERROR, "Unknown GSM module type %s for span %s\n", val, span->name); - continue; - } - ftdm_log(FTDM_LOG_DEBUG, "Configuring GSM span %s with moduletype %s\n", span->name, val); - } else if (!strcasecmp(var, "debug")) { - span_config.debug_mask = wat_str2debug(val); - ftdm_log(FTDM_LOG_DEBUG, "Configuring GSM span %s with debug mask %s == 0x%X\n", span->name, val, span_config.debug_mask); - } else if (!strcasecmp(var, "hwdtmf")) { - hwdtmf_detect = FTDM_FALSE; - hwdtmf_generate = FTDM_FALSE; - if (!strcasecmp(val, "generate")) { - hwdtmf_generate = FTDM_TRUE; - } else if (!strcasecmp(val, "detect")) { - hwdtmf_detect = FTDM_TRUE; - } else if (!strcasecmp(val, "both") || ftdm_true(val)) { - hwdtmf_detect = FTDM_TRUE; - hwdtmf_generate = FTDM_TRUE; - } else { - span_config.hardware_dtmf = WAT_FALSE; - } - ftdm_log(FTDM_LOG_DEBUG, "Configuring GSM span %s with hardware dtmf %s\n", span->name, val); - } else if (!strcasecmp(var, "conditional-forwarding-number")) { - ftdm_set_string(gsm_data->conditional_forward_number, val); - gsm_data->init_conditional_forwarding = FTDM_TRUE; - } else if (!strcasecmp(var, "conditional-forwarding-prefix")) { - ftdm_set_string(gsm_data->conditional_forward_prefix, val); - } else if (!strcasecmp(var, "immediate-forwarding-numbers")) { - char *state = NULL; - char *span_end = NULL; - char *number = NULL; - char *span_name = NULL; - int f = 0; - char *valdup = ftdm_strdup(val); - char *s = valdup; - - if (!ftdm_strlen_zero_buf(gsm_data->immediate_forward_numbers[0].number)) { - ftdm_log(FTDM_LOG_ERROR, "immediate-forwarding-numbers already parsed! failed to parse: %s\n", val); - goto ifn_parse_done; - } - - /* The string must be in the form [:], optionally multiple elements separated by comma */ - while ((number = strtok_r(s, ",", &state))) { - if (f == ftdm_array_len(gsm_data->immediate_forward_numbers)) { - ftdm_log(FTDM_LOG_ERROR, "Max number (%d) of immediate forwarding numbers reached!\n", f); - break; - } - - s = NULL; - span_end = strchr(number, ':'); - if (span_end) { - *span_end = '\0'; - span_name = number; - number = (span_end + 1); - ftdm_set_string(gsm_data->immediate_forward_numbers[f].span, span_name); - ftdm_log(FTDM_LOG_DEBUG, "Parsed immediate forwarding to span %s number %s\n", span_name, number); - } else { - ftdm_log(FTDM_LOG_DEBUG, "Parsed immediate forwarding to number %s\n", number); - } - ftdm_set_string(gsm_data->immediate_forward_numbers[f].number, number); - f++; - } -ifn_parse_done: - ftdm_safe_free(valdup); - } else if (!strcasecmp(var, "immediate-forwarding-prefix")) { - ftdm_set_string(gsm_data->immediate_forward_prefix, val); - } else if (!strcasecmp(var, "disable-forwarding-number")) { - ftdm_set_string(gsm_data->disable_forward_number, val); - } else if (!strcasecmp(var, "startup-command")) { - if (cmdindex < (ftdm_array_len(gsm_data->startup_commands) - 1)) { - ftdm_set_string(gsm_data->startup_commands[cmdindex], val); - ftdm_log(FTDM_LOG_DEBUG, "Adding startup command '%s' to GSM span %s\n", gsm_data->startup_commands[cmdindex], span->name); - cmdindex++; - } else { - ftdm_log(FTDM_LOG_ERROR, "Ignoring startup command '%s' ... max commands limit reached", val); - } - } else { - ftdm_log(FTDM_LOG_ERROR, "Ignoring unknown GSM parameter '%s'", var); - } - } - - /* Bind function pointers for control operations */ - span->start = ftdm_gsm_start; - span->stop = ftdm_gsm_stop; - span->destroy = ftdm_gsm_destroy; - span->sig_read = NULL; - span->sig_write = NULL; - if (hwdtmf_detect || hwdtmf_generate) { - span_config.hardware_dtmf = WAT_TRUE; - if (hwdtmf_generate) { - span->sig_send_dtmf = ftdm_gsm_send_dtmf; - } - if (hwdtmf_detect) { - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SIG_DTMF_DETECTION); - } - } - span->signal_cb = sig_cb; - span->signal_type = FTDM_SIGTYPE_GSM; - span->signal_data = gsm_data; - span->outgoing_call = gsm_outgoing_call; - span->get_span_sig_status = ftdm_gsm_get_span_sig_status; - span->set_span_sig_status = ftdm_gsm_set_span_sig_status; - span->get_channel_sig_status = ftdm_gsm_get_channel_sig_status; - span->set_channel_sig_status = ftdm_gsm_set_channel_sig_status; - - span->state_map = &gsm_state_map; - span->state_processor = ftdm_gsm_state_advance; - - /* use signals queue */ - ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE); - ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE); - - /* we can skip states (going straight from RING to UP) */ - ftdm_set_flag(span, FTDM_SPAN_USE_SKIP_STATES); - - gsm_data->span = span; - span_map[span->span_id] = span; - - /* Setup the scheduler */ - snprintf(schedname, sizeof(schedname), "ftmod_gsm_%s", span->name); - if (ftdm_sched_create(&gsm_data->sched, schedname) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Failed to setup scheduler for span %s!\n", span->name); - ftdm_gsm_destroy(span); - return FTDM_FAIL; - } - - /* Start the signaling stack */ - if (wat_span_config(span->span_id, &span_config)) { - ftdm_log(FTDM_LOG_ERROR, "Failed to configure span %s for GSM signaling!!\n", span->name); - ftdm_gsm_destroy(span); - return FTDM_FAIL; - } - - ftdm_channel_command(gsm_data->bchan, FTDM_COMMAND_SET_NATIVE_CODEC, &codec); - ftdm_channel_command(gsm_data->bchan, FTDM_COMMAND_SET_CODEC, &codec); - ftdm_channel_command(gsm_data->bchan, FTDM_COMMAND_SET_INTERVAL, &interval); - - return FTDM_SUCCESS; - -} - -#define GSM_POLL_INTERVAL_MS 20 -static void *ftdm_gsm_run(ftdm_thread_t *me, void *obj) -{ - ftdm_channel_t *ftdmchan = NULL; - ftdm_span_t *span = (ftdm_span_t *) obj; - ftdm_gsm_span_data_t *gsm_data = NULL; - ftdm_interrupt_t *data_sources[2] = {NULL, NULL}; - ftdm_wait_flag_t flags = FTDM_READ | FTDM_EVENTS; - ftdm_status_t status = FTDM_SUCCESS; - ftdm_alarm_flag_t alarms; - char buffer[1024] = { 0 }; - ftdm_size_t bufsize = 0; - int waitms = 0; - - gsm_data = span->signal_data; - ftdm_assert_return(gsm_data != NULL, NULL, "No gsm data attached to span\n"); - - /* as long as this thread is running, this flag is set */ - ftdm_set_flag(gsm_data, FTDM_GSM_RUNNING); - - ftdm_log(FTDM_LOG_DEBUG, "GSM monitor thread for span %s started\n", span->name); - if (!gsm_data->dchan || ftdm_channel_open_chan(gsm_data->dchan) != FTDM_SUCCESS) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to open GSM d-channel of span %s!\n", span->name); - gsm_data->dchan = NULL; - goto done; - } - - /* Do not start if the link layer is not ready yet */ - ftdm_channel_get_alarms(gsm_data->dchan, &alarms); - if (alarms != FTDM_ALARM_NONE) { - ftdm_log(FTDM_LOG_WARNING, "Delaying initialization of span %s until alarms are cleared\n", span->name); - while (ftdm_running() && ftdm_test_flag(gsm_data, FTDM_GSM_SPAN_STARTED) && alarms != FTDM_ALARM_NONE) { - ftdm_channel_get_alarms(gsm_data->dchan, &alarms); - ftdm_sleep(100); - } - if (!ftdm_running() || !ftdm_test_flag(gsm_data, FTDM_GSM_SPAN_STARTED)) { - goto done; - } - } - - if (wat_span_start(span->span_id)) { - ftdm_log(FTDM_LOG_ERROR, "Failed to start span %s!\n", span->name); - goto done; - } - - while (ftdm_running() && ftdm_test_flag(gsm_data, FTDM_GSM_SPAN_STARTED)) { - wat_span_run(span->span_id); - ftdm_sched_run(gsm_data->sched); - - waitms = wat_span_schedule_next(span->span_id); - if (waitms > GSM_POLL_INTERVAL_MS) { - waitms = GSM_POLL_INTERVAL_MS; - } - - flags = FTDM_READ | FTDM_EVENTS; - status = ftdm_channel_wait(gsm_data->dchan, &flags, waitms); - - /* check if this channel has a state change pending and process it if needed */ - ftdm_channel_lock(gsm_data->bchan); - ftdm_channel_advance_states(gsm_data->bchan); - - if (FTDM_SUCCESS == status && (flags & FTDM_READ)) { - bufsize = sizeof(buffer); - status = ftdm_channel_read(gsm_data->dchan, buffer, &bufsize); - if (status == FTDM_SUCCESS && bufsize > 0) { - wat_span_process_read(span->span_id, buffer, bufsize); - buffer[0] = 0; - } - } - - ftdm_channel_advance_states(gsm_data->bchan); - ftdm_channel_unlock(gsm_data->bchan); - - ftdm_span_trigger_signals(span); - - } - - if (wat_span_stop(span->span_id)) { - ftdm_log(FTDM_LOG_ERROR, "Failed to stop GSM span %s!\n", span->name); - } - - if (wat_span_unconfig(span->span_id)) { - ftdm_log(FTDM_LOG_ERROR, "Failed to unconfigure GSM span %s!\n", span->name); - } - -done: - if (data_sources[0]) { - ftdm_interrupt_destroy(&data_sources[0]); - } - - ftdm_log(FTDM_LOG_DEBUG, "GSM thread ending\n"); - ftdm_clear_flag(gsm_data, FTDM_GSM_RUNNING); - - return NULL; -} - - - -static FIO_IO_LOAD_FUNCTION(ftdm_gsm_io_init) -{ - assert(fio != NULL); - memset(&g_ftdm_gsm_interface, 0, sizeof(g_ftdm_gsm_interface)); - - g_ftdm_gsm_interface.name = "gsm"; - g_ftdm_gsm_interface.api = ftdm_gsm_api; - - *fio = &g_ftdm_gsm_interface; - - return (FTDM_SUCCESS); -} - -EX_DECLARE_DATA ftdm_module_t ftdm_module = { - /* .name */ "gsm", - /* .io_load */ ftdm_gsm_io_init, - /* .io_unload */ NULL, - /* .sig_load */ NULL, - /* .sig_configure */ NULL, - /* .sig_unload */ NULL, - /* .configure_span_signaling */ ftdm_gsm_configure_span_signaling -}; - -/********************************************************************************/ -/* */ -/* COMMAND HANDLERS */ -/* */ -/********************************************************************************/ - - -// Version Command Handler -COMMAND_HANDLER(version) -{ - uint8_t current = 0, revision = 0, age = 0; - wat_version(¤t, &revision, &age); - stream->write_function(stream, "libwat version: %d.%d.%d\n", current, revision, age); - stream->write_function(stream, "+OK.\n"); - return FTDM_SUCCESS; -} - - -// Status Command Handler -COMMAND_HANDLER(status) -{ - int span_id = 0; - ftdm_span_t *span = NULL; - const wat_chip_info_t *chip_info = NULL; - const wat_sim_info_t *sim_info = NULL; - const wat_net_info_t *net_info = NULL; - const wat_sig_info_t *sig_info = NULL; - wat_pin_stat_t pin_stat = 0; - - span_id = atoi(argv[0]); - if (ftdm_span_find_by_name(argv[0], &span) != FTDM_SUCCESS && ftdm_span_find(span_id, &span) != FTDM_SUCCESS) { - stream->write_function(stream, "-ERR Failed to find GSM span '%s'\n", argv[1]); - return FTDM_FAIL; - } - - if (!span || !span->signal_data || (span->start != ftdm_gsm_start)) { - stream->write_function(stream, "-ERR '%s' is not a valid GSM span\n", argv[1]); - return FTDM_FAIL; - } - - chip_info = wat_span_get_chip_info(span->span_id); - sim_info = wat_span_get_sim_info(span->span_id); - net_info = wat_span_get_net_info(span->span_id); - sig_info = wat_span_get_sig_info(span->span_id); - - /* This is absolutely retarded and should be fixed in libwat - * why the hell would you return a pointer to an internal state enum instead of a copy? - * probably the same applies to the rest of the info (sim_info, chip_info, net_info, etc), - * but at least there you could have the lame excuse that you don't need to copy the whole struct */ - pin_stat = *wat_span_get_pin_info(span->span_id); - - stream->write_function(stream, "Span %d (%s):\n", span->span_id, span->name); - - stream->write_function(stream, "CHIP type - %s (%s), revision %s, serial %s \n", - chip_info->manufacturer, - chip_info->model, - chip_info->revision, - chip_info->serial); - - stream->write_function(stream, "SIM - Subscriber type %s, imsi %s\n", sim_info->subscriber_type, sim_info->imsi); - - stream->write_function(stream, "Subscriber - Number %s, Plan %s, validity %s\n", - sim_info->subscriber.digits, - wat_number_type2str(sim_info->subscriber.type), - wat_number_plan2str(sim_info->subscriber.plan), - wat_number_validity2str(sim_info->subscriber.validity)); - - stream->write_function(stream, "Network - status %s, Area Code %d, Cell ID %d, Operator %s\n", - wat_net_stat2str(net_info->stat), net_info->lac, net_info->ci, net_info->operator_name); - - - stream->write_function(stream, "Sig Info: rssi(%d) ber(%d)\n", sig_info->rssi, sig_info->ber); - - stream->write_function(stream, "PIN Status: %s\n", wat_pin_stat2str(pin_stat)); - - stream->write_function(stream, "\n"); - - stream->write_function(stream, "+OK.\n"); - - return FTDM_SUCCESS; -} - -// SMS Command Handler -COMMAND_HANDLER(sms) -{ - int span_id = 0, i; - uint32_t sms_id = 0; - ftdm_span_t *span = NULL; - wat_sms_event_t sms; - ftdm_gsm_span_data_t *gsm_data = NULL; - - span_id = atoi(argv[0]); - if (ftdm_span_find_by_name(argv[0], &span) != FTDM_SUCCESS && ftdm_span_find(span_id, &span) != FTDM_SUCCESS) { - stream->write_function(stream, "-ERR Failed to find GSM span '%s'\n", argv[1]); - return FTDM_FAIL; - } - - if (!span || !span->signal_data || (span->start != ftdm_gsm_start)) { - stream->write_function(stream, "-ERR '%s' is not a valid GSM span\n", argv[1]); - return FTDM_FAIL; - } - gsm_data = span->signal_data; - - memset(&sms, 0, sizeof(sms)); - strcpy(sms.to.digits, argv[1]); - sms.type = WAT_SMS_TXT; - sms.content.data[0] = '\0'; - for(i=2;ibchan); - - sms_id = gsm_data->sms_id >= WAT_MAX_SMSS_PER_SPAN ? 0 : gsm_data->sms_id; - gsm_data->sms_id++; - - ftdm_channel_unlock(gsm_data->bchan); - - if (WAT_SUCCESS != wat_sms_req(span->span_id, sms_id, &sms)) { - stream->write_function(stream, "Failed to Send SMS \n"); - } else { - stream->write_function(stream, "SMS Sent.\n"); - } - return FTDM_SUCCESS; -} - -WAT_AT_CMD_RESPONSE_FUNC(gsm_exec_cb) -{ - ftdm_gsm_exec_helper_t *helper = (ftdm_gsm_exec_helper_t *)obj; - ftdm_stream_handle_t *stream = helper->stream; - ftdm_span_t *span = helper->span; - int i = 0; - - if (success == WAT_TRUE) { - stream->write_function(stream, "Command executed successfully on span %s\n", span->name); - } else { - stream->write_function(stream, "Command execution failed on span %s. Err: %s\n", span->name, error); - } - - for (i = 0; tokens[i]; i++) { - stream->write_function(stream, "%s\n", tokens[i]); - } - - helper->cmd_pending = 0; - return i; -} - -// AT Command Handler -COMMAND_HANDLER(exec) -{ - int span_id = 0; - int sanity = 100; - ftdm_span_t *span = NULL; - ftdm_gsm_exec_helper_t helper; - - span_id = atoi(argv[0]); - if (ftdm_span_find_by_name(argv[0], &span) != FTDM_SUCCESS && ftdm_span_find(span_id, &span) != FTDM_SUCCESS) { - stream->write_function(stream, "-ERR Failed to find GSM span '%s'\n", argv[0]); - return FTDM_FAIL; - } - - if (!span || !span->signal_data || (span->start != ftdm_gsm_start)) { - stream->write_function(stream, "-ERR '%s' is not a valid GSM span\n", argv[0]); - return FTDM_FAIL; - } - - helper.stream = stream; - helper.span = span; - helper.cmd_pending = 1; - if (WAT_SUCCESS != wat_cmd_req(span->span_id, argv[1], gsm_exec_cb, &helper)) { - stream->write_function(stream, "Failed to send AT command on span %s\n", span->name); - } else { - stream->write_function(stream, "AT command sent on span %s\n", span->name); - } - - while (helper.cmd_pending && (--sanity > 0)) { - ftdm_sleep(100); - } - - if (sanity < 0) { - stream->write_function(stream, "Timed out waiting for respons for AT command on span %s\n", span->name); - } - return FTDM_SUCCESS; -} - -// AT Command Handler -COMMAND_HANDLER(call) -{ - int span_id = 0; - ftdm_span_t *span = NULL; - - span_id = atoi(argv[0]); - if (ftdm_span_find_by_name(argv[0], &span) != FTDM_SUCCESS && ftdm_span_find(span_id, &span) != FTDM_SUCCESS) { - stream->write_function(stream, "-ERR Failed to find GSM span '%s'\n", argv[0]); - return FTDM_FAIL; - } - - if (!span || !span->signal_data || (span->start != ftdm_gsm_start)) { - stream->write_function(stream, "-ERR '%s' is not a valid GSM span\n", argv[0]); - return FTDM_FAIL; - } - - ftdm_gsm_make_raw_call(span->signal_data, argv[1]); - stream->write_function(stream, "+OK\n"); - return FTDM_SUCCESS; -} - -// command map -static struct { - const char *cmd; // command - int argc; // minimum args - command_handler_t handler; // handling function -} GSM_COMMANDS[] = { - COMMAND(version, 0), - COMMAND(status, 1), - COMMAND(sms, 3), - COMMAND(exec, 2), - COMMAND(call, 2), -}; - -// main command API entry point -static FIO_API_FUNCTION(ftdm_gsm_api) -{ - - char *mycmd = NULL, *argv[10] = { 0 }; - int argc = 0; - int i; - ftdm_status_t status = FTDM_FAIL; - ftdm_status_t syntax = FTDM_FAIL; - - - if (data) { - mycmd = ftdm_strdup(data); - argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); - } - - if (argc > 0) { - for (i = 0; i< ftdm_array_len(GSM_COMMANDS); i++) { - if (strcasecmp(argv[0], GSM_COMMANDS[i].cmd) == 0) { - if (argc -1 >= GSM_COMMANDS[i].argc) { - syntax = FTDM_SUCCESS; - status = GSM_COMMANDS[i].handler(stream, &argv[1], argc-1); - } - break; - } - } - } - - if (FTDM_SUCCESS != syntax) { - stream->write_function(stream, "%s", FT_SYNTAX); - } else if (FTDM_SUCCESS != status) { - stream->write_function(stream, "%s Command Failed\r\n", GSM_COMMANDS[i].cmd); - } - - ftdm_safe_free(mycmd); - - return FTDM_SUCCESS; -} - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2008.vcproj deleted file mode 100644 index 0177d4246a..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2008.vcproj +++ /dev/null @@ -1,465 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj.filters deleted file mode 100644 index 30824888fc..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj.filters +++ /dev/null @@ -1,110 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c deleted file mode 100644 index fba15eaca2..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c +++ /dev/null @@ -1,2927 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include -#include - -#ifdef WIN32 -#include -#else -#include -#endif - -#include "ftmod_isdn.h" - -#define LINE "--------------------------------------------------------------------------------" - -/* helper macros */ -#define FTDM_SPAN_IS_NT(x) (((ftdm_isdn_data_t *)(x)->signal_data)->mode == Q921_NT) - -#define DEFAULT_NATIONAL_PREFIX "0" -#define DEFAULT_INTERNATIONAL_PREFIX "00" - -/***************************************************************************************** - * PCAP - * Based on Helmut Kuper's () implementation, - * but using a different approach (needs a recent libpcap + wireshark) - *****************************************************************************************/ -#ifdef HAVE_PCAP -#include /* htons() */ -#include - -#define PCAP_SNAPLEN 1500 - -struct pcap_context { - pcap_dumper_t *dump; /*!< pcap file handle */ - pcap_t *handle; /*!< pcap lib context */ - char *filename; /*!< capture file name */ -}; - -static inline ftdm_status_t isdn_pcap_is_open(struct ftdm_isdn_data *isdn) -{ - return (isdn->pcap) ? 1 : 0; -} - -static inline ftdm_status_t isdn_pcap_capture_both(struct ftdm_isdn_data *isdn) -{ - return ((isdn->flags & (FTDM_ISDN_CAPTURE | FTDM_ISDN_CAPTURE_L3ONLY)) == FTDM_ISDN_CAPTURE) ? 1 : 0; -} - -static inline ftdm_status_t isdn_pcap_capture_l3only(struct ftdm_isdn_data *isdn) -{ - return ((isdn->flags & FTDM_ISDN_CAPTURE) && (isdn->flags & FTDM_ISDN_CAPTURE_L3ONLY)) ? 1 : 0; -} - -static ftdm_status_t isdn_pcap_open(struct ftdm_isdn_data *isdn, char *filename) -{ - struct pcap_context *pcap = NULL; - - if (!isdn || ftdm_strlen_zero(filename)) - return FTDM_FAIL; - - pcap = malloc(sizeof(struct pcap_context)); - if (!pcap) { - ftdm_log(FTDM_LOG_ERROR, "Failed to allocate isdn pcap context\n"); - return FTDM_FAIL; - } - - memset(pcap, 0, sizeof(struct pcap_context)); - - pcap->filename = strdup(filename); - - pcap->handle = pcap_open_dead(DLT_LINUX_LAPD, PCAP_SNAPLEN); - if (!pcap->handle) { - ftdm_log(FTDM_LOG_ERROR, "Failed to open pcap handle\n"); - goto error; - } - - pcap->dump = pcap_dump_open(pcap->handle, pcap->filename); - if (!pcap->dump) { - ftdm_log(FTDM_LOG_ERROR, "Failed to open capture file: '%s'\n", pcap_geterr(pcap->handle)); - goto error; - } - - ftdm_log(FTDM_LOG_INFO, "Capture file '%s' opened\n", pcap->filename); - - isdn->pcap = pcap; - - return FTDM_SUCCESS; -error: - if (pcap->handle) - pcap_close(pcap->handle); - if (pcap->filename) - free(pcap->filename); - - free(pcap); - - return FTDM_FAIL; -} - -static ftdm_status_t isdn_pcap_close(struct ftdm_isdn_data *isdn) -{ - struct pcap_context *pcap = NULL; - long size; - - if (!isdn || !isdn->pcap) - return FTDM_FAIL; - - pcap = isdn->pcap; - - isdn->flags &= ~(FTDM_ISDN_CAPTURE | FTDM_ISDN_CAPTURE_L3ONLY); - isdn->pcap = NULL; - - pcap_dump_flush(pcap->dump); - - size = pcap_dump_ftell(pcap->dump); - ftdm_log(FTDM_LOG_INFO, "File '%s' captured %ld bytes of data\n", pcap->filename, size); - - pcap_dump_close(pcap->dump); - pcap_close(pcap->handle); - - free(pcap->filename); - free(pcap); - - return FTDM_SUCCESS; -} - -static inline void isdn_pcap_start(struct ftdm_isdn_data *isdn) -{ - if (!isdn->pcap) - return; - - isdn->flags |= FTDM_ISDN_CAPTURE; -} - -static inline void isdn_pcap_stop(struct ftdm_isdn_data *isdn) -{ - isdn->flags &= ~FTDM_ISDN_CAPTURE; -} - -#ifndef ETH_P_LAPD -#define ETH_P_LAPD 0x0030 -#endif - -struct isdn_sll_hdr { - uint16_t slltype; - uint16_t sllhatype; - uint16_t slladdrlen; - uint8_t slladdr[8]; - uint16_t sllproto; -}; - -/* Fake Q.921 I-frame */ -//static const char q921_fake_frame[] = { 0x00, 0x00, 0x00, 0x00 }; - -enum { - ISDN_PCAP_INCOMING = 0, - ISDN_PCAP_INCOMING_BCAST = 1, - ISDN_PCAP_OUTGOING = 4, -}; - -static ftdm_status_t isdn_pcap_write(struct ftdm_isdn_data *isdn, unsigned char *buf, ftdm_ssize_t len, int direction) -{ - unsigned char frame[PCAP_SNAPLEN]; - struct pcap_context *pcap; - struct isdn_sll_hdr *sll_hdr = (struct isdn_sll_hdr *)frame; - struct pcap_pkthdr hdr; - int offset = sizeof(struct isdn_sll_hdr); - int nbytes; - - if (!isdn || !isdn->pcap || !buf || !len) - return FTDM_FAIL; - - pcap = isdn->pcap; - - /* Update SLL header */ - sll_hdr->slltype = htons(direction); - sll_hdr->sllhatype = 0; - sll_hdr->slladdrlen = 1; - sll_hdr->slladdr[0] = (isdn->mode == Q921_NT) ? 1 : 0; /* TODO: NT/TE */ - sll_hdr->sllproto = htons(ETH_P_LAPD); - -#if 0 - /* Q.931-only mode: copy fake Q.921 header */ - if (isdn->flags & FTDM_ISDN_CAPTURE_L3ONLY) { - /* copy fake q921 header */ - memcpy(frame + offset, q921_fake_frame, sizeof(q921_fake_frame)); - offset += sizeof(q921_fake_frame); - } -#endif - - /* Copy data */ - nbytes = (len > (PCAP_SNAPLEN - offset)) ? (PCAP_SNAPLEN - offset) : len; - memcpy(frame + offset, buf, nbytes); - - /* Update timestamp */ - memset(&hdr, 0, sizeof(struct pcap_pkthdr)); - gettimeofday(&hdr.ts, NULL); - hdr.caplen = offset + nbytes; - hdr.len = hdr.caplen; - - /* Write packet */ - pcap_dump((unsigned char *)pcap->dump, &hdr, frame); - - return FTDM_SUCCESS; -} -#endif /* HAVE_PCAP */ - - -static L2ULONG ftdm_time_now(void) -{ - return (L2ULONG)ftdm_current_time_in_ms(); -} - -/** - * \brief Returns the signalling status on a channel - * \param ftdmchan Channel to get status on - * \param status Pointer to set signalling status - * \return Success or failure - */ -static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(isdn_get_channel_sig_status) -{ - *status = FTDM_SIG_STATE_DOWN; - - ftdm_isdn_data_t *isdn_data = ftdmchan->span->signal_data; - if (ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING)) { - *status = FTDM_SIG_STATE_UP; - } - return FTDM_SUCCESS; -} - -/** - * \brief Returns the signalling status on a span - * \param span Span to get status on - * \param status Pointer to set signalling status - * \return Success or failure - */ -static FIO_SPAN_GET_SIG_STATUS_FUNCTION(isdn_get_span_sig_status) -{ - *status = FTDM_SIG_STATE_DOWN; - - ftdm_isdn_data_t *isdn_data = span->signal_data; - if (ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING)) { - *status = FTDM_SIG_STATE_UP; - } - return FTDM_SUCCESS; -} - -/** - * \brief Create outgoing channel - * \param ftdmchan Channel to create outgoing call on - * \return Success or failure - */ -static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(isdn_outgoing_call) -{ - return FTDM_SUCCESS; -} - -/** - * \brief Create outgoing channel, let module select the channel to use - * \param span Span to create outgoing call on - * \param caller_data - * \return Success or failure - */ -#ifdef __TODO__ -static FIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request) -{ -#if 1 /* FIXME caller_data.raw_data does not exist anymore, see docs/variables.txt for more info */ - Q931mes_Generic empty_gen; - Q931mes_Generic *gen = &empty_gen; - - memset(&empty_gen, 0, sizeof(empty_gen)) ; -#else - Q931mes_Generic *gen = (Q931mes_Generic *) caller_data->raw_data; -#endif - Q931ie_BearerCap BearerCap; - Q931ie_ChanID ChanID = { 0 }; - Q931ie_CallingNum CallingNum; - Q931ie_CallingNum *ptrCallingNum; - Q931ie_CalledNum CalledNum; - Q931ie_CalledNum *ptrCalledNum; - Q931ie_Display Display, *ptrDisplay; - Q931ie_HLComp HLComp; /* High-Layer Compatibility IE */ - Q931ie_ProgInd Progress; /* Progress Indicator IE */ - ftdm_status_t status = FTDM_FAIL; - ftdm_isdn_data_t *isdn_data = span->signal_data; - int sanity = 60000; - int codec = 0; - - /* - * get codec type - */ - ftdm_channel_command(span->channels[chan_id], FTDM_COMMAND_GET_NATIVE_CODEC, &codec); - - /* - * Q.931 Setup Message - */ - Q931InitMesGeneric(gen); - gen->MesType = Q931mes_SETUP; - gen->CRVFlag = 0; /* outgoing call */ - - /* - * Bearer Capability IE - */ - Q931InitIEBearerCap(&BearerCap); - BearerCap.CodStand = Q931_CODING_ITU; /* ITU-T = 0, ISO/IEC = 1, National = 2, Network = 3 */ - BearerCap.ITC = Q931_ITC_SPEECH; /* Speech */ - BearerCap.TransMode = 0; /* Circuit = 0, Packet = 1 */ - BearerCap.ITR = Q931_ITR_64K; /* 64k */ - BearerCap.Layer1Ident = 1; - BearerCap.UIL1Prot = (codec == FTDM_CODEC_ALAW) ? Q931_UIL1P_G711A : Q931_UIL1P_G711U; /* U-law = 2, A-law = 3 */ - gen->BearerCap = Q931AppendIE(gen, (L3UCHAR *) &BearerCap); - - /* - * Channel ID IE - */ - Q931InitIEChanID(&ChanID); - ChanID.IntType = FTDM_SPAN_IS_BRI(span) ? 0 : 1; /* PRI = 1, BRI = 0 */ - - if (!FTDM_SPAN_IS_NT(span)) { - ChanID.PrefExcl = (isdn_data->opts & FTDM_ISDN_OPT_SUGGEST_CHANNEL) ? 0 : 1; /* 0 = preferred, 1 exclusive */ - } else { - ChanID.PrefExcl = 1; /* always exclusive in NT-mode */ - } - - if (ChanID.IntType) { - ChanID.InfoChanSel = 1; /* None = 0, See Slot = 1, Any = 3 */ - ChanID.ChanMapType = 3; /* B-Chan */ - ChanID.ChanSlot = (unsigned char)chan_id; - } else { - ChanID.InfoChanSel = (unsigned char)chan_id & 0x03; /* None = 0, B1 = 1, B2 = 2, Any = 3 */ - } - gen->ChanID = Q931AppendIE(gen, (L3UCHAR *) &ChanID); - - /* - * Progress IE - */ - Q931InitIEProgInd(&Progress); - Progress.CodStand = Q931_CODING_ITU; /* 0 = ITU */ - Progress.Location = 0; /* 0 = User, 1 = Private Network */ - Progress.ProgDesc = 3; /* 1 = Not end-to-end ISDN */ - gen->ProgInd = Q931AppendIE(gen, (L3UCHAR *)&Progress); - - /* - * Display IE - */ - if (!(isdn_data->opts & FTDM_ISDN_OPT_OMIT_DISPLAY_IE) && FTDM_SPAN_IS_NT(span)) { - Q931InitIEDisplay(&Display); - Display.Size = Display.Size + (unsigned char)strlen(caller_data->cid_name); - gen->Display = Q931AppendIE(gen, (L3UCHAR *) &Display); - ptrDisplay = Q931GetIEPtr(gen->Display, gen->buf); - ftdm_copy_string((char *)ptrDisplay->Display, caller_data->cid_name, strlen(caller_data->cid_name)+1); - } - - /* - * Calling Number IE - */ - Q931InitIECallingNum(&CallingNum); - CallingNum.TypNum = Q931_TON_UNKNOWN; - CallingNum.NumPlanID = Q931_NUMPLAN_E164; - CallingNum.PresInd = Q931_PRES_ALLOWED; - CallingNum.ScreenInd = Q931_SCREEN_USER_NOT_SCREENED; - CallingNum.Size = CallingNum.Size + (unsigned char)strlen(caller_data->cid_num.digits); - gen->CallingNum = Q931AppendIE(gen, (L3UCHAR *) &CallingNum); - ptrCallingNum = Q931GetIEPtr(gen->CallingNum, gen->buf); - ftdm_copy_string((char *)ptrCallingNum->Digit, caller_data->cid_num.digits, strlen(caller_data->cid_num.digits)+1); - - - /* - * Called number IE - */ - Q931InitIECalledNum(&CalledNum); - CalledNum.TypNum = Q931_TON_UNKNOWN; - CalledNum.NumPlanID = Q931_NUMPLAN_E164; - CalledNum.Size = CalledNum.Size + (unsigned char)strlen(caller_data->ani.digits); - gen->CalledNum = Q931AppendIE(gen, (L3UCHAR *) &CalledNum); - ptrCalledNum = Q931GetIEPtr(gen->CalledNum, gen->buf); - ftdm_copy_string((char *)ptrCalledNum->Digit, caller_data->ani.digits, strlen(caller_data->ani.digits)+1); - - /* - * High-Layer Compatibility IE (Note: Required for AVM FritzBox) - */ - Q931InitIEHLComp(&HLComp); - HLComp.CodStand = Q931_CODING_ITU; /* ITU */ - HLComp.Interpret = 4; /* only possible value */ - HLComp.PresMeth = 1; /* High-layer protocol profile */ - HLComp.HLCharID = 1; /* Telephony = 1, Fax G2+3 = 4, Fax G4 = 65 (Class I)/ 68 (Class II or III) */ - gen->HLComp = Q931AppendIE(gen, (L3UCHAR *) &HLComp); - - caller_data->call_state = FTDM_CALLER_STATE_DIALING; - Q931Rx43(&isdn_data->q931, gen, gen->Size); - - isdn_data->outbound_crv[gen->CRV] = caller_data; - //isdn_data->channels_local_crv[gen->CRV] = ftdmchan; - - while (ftdm_running() && caller_data->call_state == FTDM_CALLER_STATE_DIALING) { - ftdm_sleep(1); - - if (!--sanity) { - caller_data->call_state = FTDM_CALLER_STATE_FAIL; - break; - } - } - isdn_data->outbound_crv[gen->CRV] = NULL; - - if (caller_data->call_state == FTDM_CALLER_STATE_SUCCESS) { - ftdm_channel_t *new_chan = NULL; - int fail = 1; - - new_chan = NULL; - if (caller_data->chan_id > 0 && caller_data->chan_id <= ftdm_span_get_chan_count(span)) { - new_chan = ftdm_span_get_channel(span, caller_data->chan_id); - } - - if (new_chan && (status = ftdm_channel_open_chan(new_chan) == FTDM_SUCCESS)) { - if (ftdm_test_flag(new_chan, FTDM_CHANNEL_INUSE) || new_chan->state != FTDM_CHANNEL_STATE_DOWN) { - if (new_chan->state == FTDM_CHANNEL_STATE_DOWN || new_chan->state >= FTDM_CHANNEL_STATE_TERMINATING) { - int x = 0; - ftdm_log(FTDM_LOG_WARNING, "Channel %d:%d ~ %d:%d is already in use waiting for it to become available.\n"); - - for (x = 0; x < 200; x++) { - if (!ftdm_test_flag(new_chan, FTDM_CHANNEL_INUSE)) { - break; - } - ftdm_sleep(5); - } - } - if (ftdm_test_flag(new_chan, FTDM_CHANNEL_INUSE)) { - ftdm_log(FTDM_LOG_ERROR, "Channel %d:%d ~ %d:%d is already in use.\n", - new_chan->span_id, - new_chan->chan_id, - new_chan->physical_span_id, - new_chan->physical_chan_id - ); - new_chan = NULL; - } - } - - if (new_chan && new_chan->state == FTDM_CHANNEL_STATE_DOWN) { - struct Q931_Call *call = NULL; - - memset(&new_chan->caller_data, 0, sizeof(new_chan->caller_data)); - ftdm_set_flag(new_chan, FTDM_CHANNEL_OUTBOUND); - ftdm_set_state_locked(new_chan, FTDM_CHANNEL_STATE_DIALING); - - call = Q931GetCallByCRV(&isdn_data->q931, gen->CRV); - Q931CallSetPrivate(call, new_chan); - - switch(gen->MesType) { - case Q931mes_ALERTING: - new_chan->init_state = FTDM_CHANNEL_STATE_PROGRESS_MEDIA; - break; - case Q931mes_CONNECT: - new_chan->init_state = FTDM_CHANNEL_STATE_UP; - break; - default: - new_chan->init_state = FTDM_CHANNEL_STATE_PROGRESS; - break; - } - - fail = 0; - } - } - - if (!fail) { - *ftdmchan = new_chan; - return FTDM_SUCCESS; - } else { - Q931ie_Cause cause; - gen->MesType = Q931mes_DISCONNECT; - cause.IEId = Q931ie_CAUSE; - cause.Size = sizeof(Q931ie_Cause); - cause.CodStand = 0; - cause.Location = 1; - cause.Recom = 1; - //should we be casting here.. or do we need to translate value? - cause.Value = (unsigned char) FTDM_CAUSE_WRONG_CALL_STATE; - *cause.Diag = '\0'; - gen->Cause = Q931AppendIE(gen, (L3UCHAR *) &cause); - Q931Rx43(&isdn_data->q931, gen, gen->Size); - - if (gen->CRV) { - Q931ReleaseCRV(&isdn_data->q931, gen->CRV); - } - - if (new_chan) { - ftdm_log(FTDM_LOG_CRIT, "Channel is busy\n"); - } else { - ftdm_log(FTDM_LOG_CRIT, "Failed to open channel for new setup message\n"); - } - } - } - - *ftdmchan = NULL; - return FTDM_FAIL; - -} -#endif /* __TODO__ */ - -static L3INT ftdm_isdn_931_err(void *pvt, L3INT id, L3INT p1, L3INT p2) -{ - ftdm_log(FTDM_LOG_ERROR, "ERROR: [%s] [%d] [%d]\n", q931_error_to_name(id), p1, p2); - return 0; -} - -/** - * \brief The new call event handler - * \note W000t!!! \o/ ;D - * \todo A lot - */ -static void ftdm_isdn_call_event(struct Q931_Call *call, struct Q931_CallEvent *event, void *priv) -{ - Q931_TrunkInfo_t *trunk = NULL; - ftdm_isdn_data_t *isdn_data = NULL; - ftdm_span_t *span = priv; - - assert(span); - assert(call); - assert(event); - - trunk = Q931CallGetTrunk(call); - assert(trunk); - - isdn_data = span->signal_data; - assert(isdn_data); - - if (Q931CallIsGlobal(call)) { - /* - * Global event - */ - ftdm_log(FTDM_LOG_DEBUG, "Received global event from Q.931\n"); - } else { - ftdm_channel_t *ftdmchan = NULL; - ftdm_sigmsg_t sig; - int call_crv = Q931CallGetCRV(call); - int type; - - /* - * Call-specific event - */ - ftdm_log(FTDM_LOG_DEBUG, "Received call-specific event from Q.931 for call %d [%hu]\n", Q931CallGetCRV(call), Q931CallGetCRV(call)); - - /* - * Try to get associated zap channel - * and init sigmsg struct if there is one - */ - ftdmchan = Q931CallGetPrivate(call); - if (ftdmchan) { - memset(&sig, 0, sizeof(ftdm_sigmsg_t)); - sig.chan_id = ftdmchan->chan_id; - sig.span_id = ftdmchan->span_id; - sig.channel = ftdmchan; - } - - type = Q931CallEventGetType(event); - - if (type == Q931_EVENT_TYPE_CRV) { - - ftdm_log(FTDM_LOG_DEBUG, "\tCRV event\n"); - - switch (Q931CallEventGetId(event)) { - case Q931_EVENT_RELEASE_CRV: - { - /* WARNING contains old interface code, yuck! */ - if (!ftdmchan) { - ftdm_log(FTDM_LOG_DEBUG, "Call %d [0x%x] not associated to zap channel\n", call_crv, call_crv); - return; - } - - if (ftdm_channel_get_state(ftdmchan) != FTDM_CHANNEL_STATE_DOWN && - ftdm_channel_get_state(ftdmchan) != FTDM_CHANNEL_STATE_HANGUP_COMPLETE) - { - ftdm_log(FTDM_LOG_DEBUG, "Channel %d:%d not in DOWN state, cleaning up\n", - ftdm_channel_get_span_id(ftdmchan), - ftdm_channel_get_id(ftdmchan)); - - /* - * Send hangup signal to mod_freetdm - */ - if (!sig.channel->caller_data.hangup_cause) { - sig.channel->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING; - } - - sig.event_id = FTDM_SIGEVENT_STOP; - ftdm_span_send_signal(ftdm_channel_get_span(ftdmchan), &sig); - - /* Release zap channel */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - return; - } - break; - default: - ftdm_log(FTDM_LOG_ERROR, "Unknown CRV event: %d\n", Q931CallEventGetId(event)); - return; - } - } - else if (type == Q931_EVENT_TYPE_TIMER) { - struct Q931_CallTimerEvent *timer_evt = Q931CallEventGetData(event); - - ftdm_log(FTDM_LOG_DEBUG, "\tTimer event\n"); - assert(timer_evt->id); - - switch (timer_evt->id) { - case Q931_TIMER_T303: - /* - * SETUP timeout - * - * TE-mode: Q931_EVENT_SETUP_CONFIRM (error) - * NT-mode: Q931_EVENT_RELEASE_INDICATION - */ - { - /* WARNING contains old interface code, yuck! */ - if (!ftdmchan) { - ftdm_log(FTDM_LOG_ERROR, "Call %d [0x%x] not associated to zap channel\n", call_crv, call_crv); - return; - } - - ftdm_log(FTDM_LOG_DEBUG, "Call setup failed on channel %d:%d\n", - ftdm_channel_get_span_id(ftdmchan), - ftdm_channel_get_id(ftdmchan)); - - /* - * Send signal to mod_freetdm - */ - sig.channel->caller_data.hangup_cause = FTDM_CAUSE_NETWORK_OUT_OF_ORDER; - - sig.event_id = FTDM_SIGEVENT_STOP; - ftdm_span_send_signal(ftdm_channel_get_span(ftdmchan), &sig); - - /* Release zap channel */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - return; - } - break; - - default: - ftdm_log(FTDM_LOG_ERROR, "Unhandled timer event %d\n", timer_evt->id); - } - } - else if (type == Q931_EVENT_TYPE_MESSAGE) { - struct Q931_CallMessageEvent *msg_evt = Q931CallEventGetData(event); - - ftdm_log(FTDM_LOG_DEBUG, "\tMessage event\n"); - assert(msg_evt); - - /* - * Slowly move stuff from the old event handler into this part... - */ - switch (Q931CallEventGetId(event)) { - case Q931_EVENT_SETUP_CONFIRM: - case Q931_EVENT_SETUP_COMPLETE_INDICATION: /* CONNECT */ - { - /* WARNING contains old interface code, yuck! */ - if (!ftdmchan) { - ftdm_log(FTDM_LOG_ERROR, "Call %d [0x%x] not associated to zap channel\n", call_crv, call_crv); - return; - } - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); - } - break; - - default: - ftdm_log(FTDM_LOG_DEBUG, "Not yet handled message event %d\n", Q931CallEventGetId(event)); - } - } - else { - ftdm_log(FTDM_LOG_ERROR, "Unknown event type %d\n", type); - } - } -} - -/** - * Copy callednum, readding prefix as needed - */ -static void __isdn_get_number(const char *digits, const int ton, char *buf, int size) -{ - int offset = 0; - - if (!digits || !buf || size <= 0) - return; - - switch (ton) { - case Q931_TON_NATIONAL: - offset = strlen(DEFAULT_NATIONAL_PREFIX); - memcpy(buf, DEFAULT_NATIONAL_PREFIX, offset); - break; - case Q931_TON_INTERNATIONAL: - offset = strlen(DEFAULT_INTERNATIONAL_PREFIX); - memcpy(buf, DEFAULT_INTERNATIONAL_PREFIX, offset); - break; - default: - break; - } - - strncpy(&buf[offset], digits, size - (offset + 1)); - buf[size - 1] = '\0'; -} - -#define isdn_get_number(num, buf) \ - __isdn_get_number((const char *)(num)->Digit, (num)->TypNum, (char *)buf, sizeof(buf)) - - -/** - * \brief The old call event handler (err, call message handler) - * \todo This one must die! - */ -static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic *msg, int mlen) -{ - Q931mes_Generic *gen = (Q931mes_Generic *) msg; - ftdm_span_t *span = (ftdm_span_t *) pvt; - ftdm_isdn_data_t *isdn_data = span->signal_data; - ftdm_channel_t *ftdmchan = NULL; - int chan_id = 0; - int chan_hunt = 0; - - if (Q931IsIEPresent(gen->ChanID)) { - Q931ie_ChanID *chanid = Q931GetIEPtr(gen->ChanID, gen->buf); - - if (chanid->IntType) - chan_id = chanid->ChanSlot; - else - chan_id = chanid->InfoChanSel; - - /* "any" channel specified */ - if (chanid->InfoChanSel == 3) { - chan_hunt++; - } - } else if (FTDM_SPAN_IS_NT(span)) { - /* no channel ie */ - chan_hunt++; - } - - assert(span != NULL); - assert(isdn_data != NULL); - - /* ftdm channel is stored in call private */ - if (call) { - ftdmchan = Q931CallGetPrivate(call); - if (!ftdmchan) { - ftdm_log(FTDM_LOG_DEBUG, "[s%d] No channel associated to call [%#x] private\n", - ftdm_span_get_id(span), Q931CallGetCRV(call)); - } - } - - ftdm_log(FTDM_LOG_DEBUG, "Yay I got an event! Type:[%02x] Size:[%d] CRV: %d (%#hx, CTX: %s)\n", - gen->MesType, gen->Size, gen->CRV, gen->CRV, gen->CRVFlag ? "Terminator" : "Originator"); - -#ifdef __TODO__ - /* - * This code block is needed for isdn_channel_request() - * isdn_data->outbound_crv has been removed so another way to pass data around is required - */ - if (gen->CRVFlag && (caller_data = isdn_data->outbound_crv[gen->CRV])) { - if (chan_id) { - caller_data->chan_id = chan_id; - } - - switch(gen->MesType) { - case Q931mes_STATUS: - case Q931mes_CALL_PROCEEDING: - break; - case Q931mes_ALERTING: - case Q931mes_PROGRESS: - case Q931mes_CONNECT: - caller_data->call_state = FTDM_CALLER_STATE_SUCCESS; - break; - default: - caller_data->call_state = FTDM_CALLER_STATE_FAIL; - break; - } - - return 0; - } -#endif - ftdm_log(FTDM_LOG_DEBUG, "ftdmchan %p (%d:%d) via CRV[%#hx]\n", - ftdmchan, - ((ftdmchan) ? ftdm_channel_get_span_id(ftdmchan) : -1), - ((ftdmchan) ? ftdm_channel_get_id(ftdmchan) : -1), - gen->CRV); - - if (gen->ProtDisc == 3) { - switch(gen->MesType) { - case Q931mes_SERVICE: - { - Q931ie_ChangeStatus *changestatus = Q931GetIEPtr(gen->ChangeStatus, gen->buf); - if (ftdmchan) { - switch (changestatus->NewStatus) { - case 0: /* change status to "in service" */ - { - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_SUSPENDED); - ftdm_log(FTDM_LOG_DEBUG, "Channel %d:%d in service\n", - ftdm_channel_get_span_id(ftdmchan), - ftdm_channel_get_id(ftdmchan)); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - } - break; - case 1: - { /* change status to "maintenance" */ - ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_SUSPENDED); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - } - break; - case 2: - { /* change status to "out of service" */ - ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_SUSPENDED); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - } - break; - default: /* unknown */ - { - break; - } - } - } - } - break; - default: - break; - } - } else { - switch(gen->MesType) { - case Q931mes_RESTART: - { - if (chan_id) { - ftdmchan = ftdm_span_get_channel(span, chan_id); - } - if (ftdmchan) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - } else { - uint32_t i; - - for (i = 1; i < ftdm_span_get_chan_count(span); i++) { - ftdmchan = ftdm_span_get_channel(span, chan_id); - - /* Skip channels that are down and D-Channels (#OpenZAP-39) */ - if (ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_DOWN || - ftdm_channel_get_type(ftdmchan) == FTDM_CHAN_TYPE_DQ921) - continue; - - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - } - } - } - break; - case Q931mes_RELEASE: - case Q931mes_RELEASE_COMPLETE: - { - const char *what = gen->MesType == Q931mes_RELEASE ? "Release" : "Release Complete"; - if (ftdmchan) { - if (ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_TERMINATING || - ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_HANGUP) - { - if (gen->MesType == Q931mes_RELEASE) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); - } else { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - } - else if (gen->MesType == Q931mes_RELEASE_COMPLETE && ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_DIALTONE) { - /* Go DOWN */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - else if ((gen->MesType == Q931mes_RELEASE && ftdm_channel_get_state(ftdmchan) <= FTDM_CHANNEL_STATE_UP) || - (gen->MesType == Q931mes_RELEASE_COMPLETE && ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_DIALING)) { - - /* - * Don't keep inbound channels open if the remote side hangs up before we answered - */ - Q931ie_Cause *cause = Q931GetIEPtr(gen->Cause, gen->buf); - ftdm_sigmsg_t sig; - - memset(&sig, 0, sizeof(sig)); - sig.span_id = ftdm_channel_get_span_id(ftdmchan); - sig.chan_id = ftdm_channel_get_id(ftdmchan); - sig.channel = ftdmchan; - sig.channel->caller_data.hangup_cause = (cause) ? cause->Value : FTDM_CAUSE_NORMAL_UNSPECIFIED; - - sig.event_id = FTDM_SIGEVENT_STOP; - ftdm_span_send_signal(span, &sig); - - ftdm_log(FTDM_LOG_DEBUG, "Received %s in state %s, requested hangup for channel %d:%d\n", what, - ftdm_channel_get_state_str(ftdmchan), - ftdm_channel_get_span_id(ftdmchan), - ftdm_channel_get_id(ftdmchan)); - } else { - ftdm_log(FTDM_LOG_DEBUG, "Ignoring %s on channel %d in state %s\n", what, - ftdm_channel_get_id(ftdmchan), ftdm_channel_get_state_str(ftdmchan)); - } - } else { - ftdm_log(FTDM_LOG_CRIT, "Received %s with no matching channel %d\n", what, chan_id); - } - } - break; - case Q931mes_DISCONNECT: - { - if (ftdmchan) { - Q931ie_Cause *cause = Q931GetIEPtr(gen->Cause, gen->buf); - ftdmchan->caller_data.hangup_cause = cause->Value; - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - } else { - ftdm_log(FTDM_LOG_CRIT, "Received Disconnect with no matching channel %d\n", chan_id); - } - } - break; - case Q931mes_ALERTING: - { - if (ftdmchan) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); - } else { - ftdm_log(FTDM_LOG_CRIT, "Received Alerting with no matching channel %d\n", chan_id); - } - } - break; - case Q931mes_PROGRESS: - { - if (ftdmchan) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); - } else { - ftdm_log(FTDM_LOG_CRIT, "Received Progress with no matching channel %d\n", chan_id); - } - } - break; - case Q931mes_CONNECT: -#if 0 /* Handled by new event code */ - { - if (ftdmchan) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); - -#if 0 /* Auto-Ack is enabled, we actually don't need this */ - gen->MesType = Q931mes_CONNECT_ACKNOWLEDGE; - gen->CRVFlag = 0; /* outbound */ - Q931Rx43(&isdn_data->q931, gen, gen->Size); -#endif - } else { - ftdm_log(FTDM_LOG_CRIT, "Received Connect with no matching channel %d\n", chan_id); - } - } -#endif - break; - case Q931mes_SETUP: - { - Q931ie_CallingNum *callingnum = Q931GetIEPtr(gen->CallingNum, gen->buf); - Q931ie_CalledNum *callednum = Q931GetIEPtr(gen->CalledNum, gen->buf); - int overlap_dial = 0; - int fail_cause = 0; - int fail = 1; - - if (ftdmchan && ftdmchan == Q931CallGetPrivate(call)) { - ftdm_log(FTDM_LOG_INFO, "Duplicate SETUP message(?) for Channel %d:%d ~ %d:%d in state %s [ignoring]\n", - ftdm_channel_get_span_id(ftdmchan), - ftdm_channel_get_id(ftdmchan), - ftdm_channel_get_ph_span_id(ftdmchan), - ftdm_channel_get_ph_id(ftdmchan), - ftdm_channel_get_state_str(ftdmchan)); - break; - } - - ftdmchan = NULL; - /* - * Channel selection for incoming calls: - */ - if (FTDM_SPAN_IS_NT(span) && chan_hunt) { - int x; - - /* - * In NT-mode with channel selection "any", - * try to find a free channel - */ - for (x = 1; x <= ftdm_span_get_chan_count(span); x++) { - ftdm_channel_t *zc = ftdm_span_get_channel(span, x); - - if (!ftdm_test_flag(zc, FTDM_CHANNEL_INUSE) && ftdm_channel_get_state(zc) == FTDM_CHANNEL_STATE_DOWN) { - ftdmchan = zc; - break; - } - } - } - else if (!FTDM_SPAN_IS_NT(span) && chan_hunt) { - /* - * In TE-mode this ("any") is invalid - */ - fail_cause = FTDM_CAUSE_CHANNEL_UNACCEPTABLE; - - ftdm_log(FTDM_LOG_ERROR, "Invalid channel selection in incoming call (network side didn't specify a channel)\n"); - } - else { - /* - * Otherwise simply try to select the channel we've been told - * - * TODO: NT mode is abled to select a different channel if the one chosen - * by the TE side is already in use - */ - if (chan_id > 0 && chan_id < FTDM_MAX_CHANNELS_SPAN && chan_id <= ftdm_span_get_chan_count(span)) { - ftdmchan = ftdm_span_get_channel(span, chan_id); - } - else { - /* invalid channel id */ - fail_cause = FTDM_CAUSE_CHANNEL_UNACCEPTABLE; - - ftdm_log(FTDM_LOG_ERROR, "Invalid channel selection in incoming call (none selected or out of bounds)\n"); - } - } - - if (!callednum || ftdm_strlen_zero((char *)callednum->Digit)) { - if (FTDM_SPAN_IS_NT(span)) { - ftdm_log(FTDM_LOG_NOTICE, "No destination number found, assuming overlap dial\n"); - overlap_dial++; - } else { - ftdm_log(FTDM_LOG_ERROR, "No destination number found\n"); - ftdmchan = NULL; - } - } - - if (ftdmchan) { - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE) || ftdm_channel_get_state(ftdmchan) != FTDM_CHANNEL_STATE_DOWN) { - if (ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_DOWN || ftdm_channel_get_state(ftdmchan) >= FTDM_CHANNEL_STATE_TERMINATING) - { - int x = 0; - ftdm_log(FTDM_LOG_WARNING, "Channel %d:%d ~ %d:%d is already in use waiting for it to become available.\n", - ftdm_channel_get_span_id(ftdmchan), - ftdm_channel_get_id(ftdmchan), - ftdm_channel_get_ph_span_id(ftdmchan), - ftdm_channel_get_ph_id(ftdmchan)); - - for (x = 0; x < 200; x++) { - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) { - break; - } - ftdm_sleep(5); - } - } - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) { - ftdm_log(FTDM_LOG_ERROR, "Channel %d:%d ~ %d:%d is already in use.\n", - ftdm_channel_get_span_id(ftdmchan), - ftdm_channel_get_id(ftdmchan), - ftdm_channel_get_ph_span_id(ftdmchan), - ftdm_channel_get_ph_id(ftdmchan)); - ftdmchan = NULL; - } - } - - if (ftdmchan && ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_DOWN) { - ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(ftdmchan); - - memset(&ftdmchan->caller_data, 0, sizeof(ftdmchan->caller_data)); - - if (ftdmchan->call_data) { - memset(ftdmchan->call_data, 0, sizeof(ftdm_isdn_bchan_data_t)); - } - - /* copy number readd prefix as needed */ - isdn_get_number(callingnum, caller_data->cid_num.digits); - isdn_get_number(callingnum, caller_data->cid_name); - isdn_get_number(callingnum, caller_data->ani.digits); - - if (!overlap_dial) { - isdn_get_number(callednum, caller_data->dnis.digits); - } - - ftdmchan->caller_data.call_reference = gen->CRV; - Q931CallSetPrivate(call, ftdmchan); - - gen->CRVFlag = !(gen->CRVFlag); - - fail = 0; - } - } - - if (fail) { - Q931ie_Cause cause; - - gen->MesType = Q931mes_DISCONNECT; - gen->CRVFlag = 1; /* inbound call */ - - cause.IEId = Q931ie_CAUSE; - cause.Size = sizeof(Q931ie_Cause); - cause.CodStand = Q931_CODING_ITU; - cause.Location = 1; - cause.Recom = 1; - //should we be casting here.. or do we need to translate value? - cause.Value = (unsigned char)((fail_cause) ? fail_cause : FTDM_CAUSE_WRONG_CALL_STATE); - *cause.Diag = '\0'; - gen->Cause = Q931AppendIE(gen, (L3UCHAR *) &cause); - Q931Rx43(&isdn_data->q931, gen, gen->Size); - - if (gen->CRV) { - Q931ReleaseCRV(&isdn_data->q931, gen->CRV); - } - - if (ftdmchan) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Channel is busy\n"); - } else { - ftdm_log(FTDM_LOG_CRIT, "Failed to open channel for new setup message\n"); - } - - } else { - Q931ie_ChanID ChanID; - - /* - * Update Channel ID IE - */ - Q931InitIEChanID(&ChanID); - ChanID.IntType = FTDM_SPAN_IS_BRI(ftdmchan->span) ? 0 : 1; /* PRI = 1, BRI = 0 */ - ChanID.PrefExcl = FTDM_SPAN_IS_NT(ftdmchan->span) ? 1 : 0; /* Exclusive in NT-mode = 1, Preferred otherwise = 0 */ - if (ChanID.IntType) { - ChanID.InfoChanSel = 1; /* None = 0, See Slot = 1, Any = 3 */ - ChanID.ChanMapType = 3; /* B-Chan */ - ChanID.ChanSlot = (unsigned char)ftdm_channel_get_id(ftdmchan); - } else { - ChanID.InfoChanSel = (unsigned char)ftdm_channel_get_id(ftdmchan) & 0x03; /* None = 0, B1 = 1, B2 = 2, Any = 3 */ - } - gen->ChanID = Q931AppendIE(gen, (L3UCHAR *) &ChanID); - - if (overlap_dial) { - Q931ie_ProgInd progress; - - /* - * Setup Progress indicator - */ - progress.IEId = Q931ie_PROGRESS_INDICATOR; - progress.Size = sizeof(Q931ie_ProgInd); - progress.CodStand = Q931_CODING_ITU; /* ITU */ - progress.Location = 1; /* private network serving the local user */ - progress.ProgDesc = 8; /* call is not end-to-end isdn = 1, in-band information available = 8 */ - gen->ProgInd = Q931AppendIE(gen, (L3UCHAR *) &progress); - - /* - * Send SETUP ACK - */ - gen->MesType = Q931mes_SETUP_ACKNOWLEDGE; - gen->CRVFlag = 1; /* inbound call */ - Q931Rx43(&isdn_data->q931, gen, gen->Size); - - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DIALTONE); - } else { - /* - * Advance to RING state - */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); - } - } - } - break; - - case Q931mes_CALL_PROCEEDING: - { - if (ftdmchan) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Received CALL PROCEEDING message for channel\n"); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); - } else { - ftdm_log(FTDM_LOG_CRIT, "Received CALL PROCEEDING with no matching channel %d\n", chan_id); - } - } - break; - case Q931mes_CONNECT_ACKNOWLEDGE: - { - if (ftdmchan) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Received CONNECT_ACK message for channel\n"); - } else { - ftdm_log(FTDM_LOG_DEBUG, "Received CONNECT_ACK with no matching channel %d\n", chan_id); - } - } - break; - - case Q931mes_INFORMATION: - { - if (ftdmchan) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Received INFORMATION message for channel\n"); - - if (ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_DIALTONE) { - char digit = '\0'; - - /* - * overlap dial digit indication - */ - if (Q931IsIEPresent(gen->CalledNum)) { - ftdm_isdn_bchan_data_t *data = (ftdm_isdn_bchan_data_t *)ftdmchan->call_data; - Q931ie_CalledNum *callednum = Q931GetIEPtr(gen->CalledNum, gen->buf); - int pos; - - digit = callednum->Digit[strlen((char *)callednum->Digit) - 1]; - if (digit == '#') { - callednum->Digit[strlen((char *)callednum->Digit) - 1] = '\0'; - } - - /* TODO: make this more safe with strncat() */ - pos = strlen(ftdmchan->caller_data.dnis.digits); - strcat(&ftdmchan->caller_data.dnis.digits[pos], (char *)callednum->Digit); - - /* update timer */ - data->digit_timeout = ftdm_time_now() + isdn_data->digit_timeout; - - ftdm_log(FTDM_LOG_DEBUG, "Received new overlap digit (%s), destination number: %s\n", callednum->Digit, ftdmchan->caller_data.dnis.digits); - } - - if (Q931IsIEPresent(gen->SendComplete) || digit == '#') { - ftdm_log(FTDM_LOG_DEBUG, "Leaving overlap dial mode\n"); - - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); - } - } - } else { - ftdm_log(FTDM_LOG_CRIT, "Received INFORMATION message with no matching channel\n"); - } - } - break; - - default: - ftdm_log(FTDM_LOG_CRIT, "Received unhandled message %d (%#x)\n", (int)gen->MesType, (int)gen->MesType); - break; - } - } - - return 0; -} - -static int ftdm_isdn_921_23(void *pvt, Q921DLMsg_t ind, L2UCHAR tei, L2UCHAR *msg, L2INT mlen) -{ - ftdm_span_t *span = pvt; - ftdm_isdn_data_t *isdn_data = span->signal_data; - int ret, offset = (ind == Q921_DL_DATA) ? 4 : 3; - char bb[4096] = ""; - - switch(ind) { - case Q921_DL_DATA: - case Q921_DL_UNIT_DATA: - print_hex_bytes(msg + offset, mlen - offset, bb, sizeof(bb)); - ftdm_log(FTDM_LOG_DEBUG, "READ %d\n%s\n%s\n\n", (int)mlen - offset, LINE, bb); -#ifdef HAVE_PCAP - if (isdn_pcap_capture_l3only(isdn_data)) { - isdn_pcap_write(isdn_data, msg, mlen, (ind == Q921_DL_UNIT_DATA) ? ISDN_PCAP_INCOMING_BCAST : ISDN_PCAP_INCOMING); - } -#endif - default: - ret = Q931Rx23(&isdn_data->q931, ind, tei, msg, mlen); - if (ret != 0) - ftdm_log(FTDM_LOG_DEBUG, "931 parse error [%d] [%s]\n", ret, q931_error_to_name(ret)); - break; - } - - return ((ret >= 0) ? 1 : 0); -} - -static int ftdm_isdn_921_21(void *pvt, L2UCHAR *msg, L2INT mlen) -{ - ftdm_span_t *span = (ftdm_span_t *) pvt; - ftdm_size_t len = (ftdm_size_t) mlen; - ftdm_isdn_data_t *isdn_data = span->signal_data; - - assert(span != NULL); - -#ifdef HAVE_PCAP - if (isdn_pcap_capture_both(isdn_data)) { - isdn_pcap_write(isdn_data, msg, mlen, ISDN_PCAP_OUTGOING); - } -#endif - return ftdm_channel_write(isdn_data->dchan, msg, len, &len) == FTDM_SUCCESS ? 0 : -1; -} - -static __inline__ void state_advance(ftdm_channel_t *ftdmchan) -{ - ftdm_span_t *span = ftdm_channel_get_span(ftdmchan); - ftdm_isdn_data_t *isdn_data = NULL; - ftdm_sigmsg_t sig; - ftdm_status_t status; - - Q931mes_Generic empty_gen; - Q931mes_Generic *gen = &empty_gen; - struct Q931_Call *call = NULL; - - Q931InitMesGeneric(gen); - - isdn_data = span->signal_data; - assert(isdn_data); - - call = Q931GetCallByCRV(&isdn_data->q931, ftdmchan->caller_data.call_reference); - if (call) { - gen->CRV = Q931CallGetCRV(call); - gen->CRVFlag = Q931CallGetDirection(call) == Q931_DIRECTION_INBOUND ? 1 : 0; - } - - ftdm_log(FTDM_LOG_DEBUG, "%d:%d STATE [%s]\n", - ftdm_channel_get_span_id(ftdmchan), - ftdm_channel_get_id(ftdmchan), - ftdm_channel_get_state_str(ftdmchan)); - - memset(&sig, 0, sizeof(sig)); - sig.span_id = ftdm_channel_get_span_id(ftdmchan); - sig.chan_id = ftdm_channel_get_id(ftdmchan); - sig.channel = ftdmchan; - - /* Acknowledge channel state change */ - ftdm_channel_complete_state(ftdmchan); - - switch (ftdm_channel_get_state(ftdmchan)) { - case FTDM_CHANNEL_STATE_DOWN: - { - if (gen->CRV) { - Q931CallSetPrivate(call, NULL); - Q931ReleaseCRV(&isdn_data->q931, gen->CRV); - } - ftdmchan->caller_data.call_reference = 0; - ftdm_channel_close(&ftdmchan); - } - break; - case FTDM_CHANNEL_STATE_PROGRESS: - { - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - sig.event_id = FTDM_SIGEVENT_PROGRESS; - if ((status = ftdm_span_send_signal(ftdm_channel_get_span(ftdmchan), &sig) != FTDM_SUCCESS)) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - } - } else { - gen->MesType = Q931mes_CALL_PROCEEDING; - - if (FTDM_SPAN_IS_NT(ftdm_channel_get_span(ftdmchan))) { - Q931ie_ChanID ChanID; - - /* - * Set new Channel ID - */ - Q931InitIEChanID(&ChanID); - ChanID.IntType = FTDM_SPAN_IS_BRI(ftdm_channel_get_span(ftdmchan)) ? 0 : 1; /* PRI = 1, BRI = 0 */ - ChanID.PrefExcl = 1; /* always exclusive in NT-mode */ - - if (ChanID.IntType) { - ChanID.InfoChanSel = 1; /* None = 0, See Slot = 1, Any = 3 */ - ChanID.ChanMapType = 3; /* B-Chan */ - ChanID.ChanSlot = (unsigned char)ftdm_channel_get_id(ftdmchan); - } else { - ChanID.InfoChanSel = (unsigned char)ftdm_channel_get_id(ftdmchan) & 0x03; /* None = 0, B1 = 1, B2 = 2, Any = 3 */ - } - gen->ChanID = Q931AppendIE(gen, (L3UCHAR *) &ChanID); - } - - Q931Rx43(&isdn_data->q931, gen, gen->Size); - } - } - break; - case FTDM_CHANNEL_STATE_DIALTONE: - { - ftdm_isdn_bchan_data_t *data = (ftdm_isdn_bchan_data_t *)ftdmchan->call_data; - - if (data) { - data->digit_timeout = ftdm_time_now() + isdn_data->digit_timeout; - } - } - break; - case FTDM_CHANNEL_STATE_RING: - { - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - sig.event_id = FTDM_SIGEVENT_START; - if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - } - } - } - break; - case FTDM_CHANNEL_STATE_RESTART: - { - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_UNSPECIFIED; - sig.event_id = FTDM_SIGEVENT_RESTART; - status = ftdm_span_send_signal(span, &sig); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - break; - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - { - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - sig.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA; - if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - } - } else { - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { - if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - return; - } - } - gen->MesType = Q931mes_ALERTING; - Q931Rx43(&isdn_data->q931, gen, gen->Size); - } - } - break; - case FTDM_CHANNEL_STATE_UP: - { - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - sig.event_id = FTDM_SIGEVENT_UP; - if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - } - } else { - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { - if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - return; - } - } - - gen->MesType = Q931mes_CONNECT; - - Q931Rx43(&isdn_data->q931, gen, gen->Size); - } - } - break; - case FTDM_CHANNEL_STATE_DIALING: - if (!(isdn_data->opts & FTDM_ISDN_OPT_SUGGEST_CHANNEL)) { - ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(ftdmchan); - Q931ie_BearerCap BearerCap; - Q931ie_ChanID ChanID; - Q931ie_CallingNum CallingNum; - Q931ie_CallingNum *ptrCallingNum; - Q931ie_CalledNum CalledNum; - Q931ie_CalledNum *ptrCalledNum; - Q931ie_Display Display, *ptrDisplay; - Q931ie_HLComp HLComp; /* High-Layer Compatibility IE */ - Q931ie_ProgInd Progress; /* Progress Indicator IE */ - int codec = 0; - - /* - * get codec type - */ - ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_NATIVE_CODEC, &codec); - - /* - * Q.931 Setup Message - */ - Q931InitMesGeneric(gen); - gen->MesType = Q931mes_SETUP; - gen->CRVFlag = 0; /* outbound(?) */ - - /* - * Bearer Capability IE - */ - Q931InitIEBearerCap(&BearerCap); - BearerCap.CodStand = Q931_CODING_ITU; /* ITU-T = 0, ISO/IEC = 1, National = 2, Network = 3 */ - BearerCap.ITC = Q931_ITC_SPEECH; /* Speech */ - BearerCap.TransMode = 0; /* Circuit = 0, Packet = 1 */ - BearerCap.ITR = Q931_ITR_64K; /* 64k = 16, Packet mode = 0 */ - BearerCap.Layer1Ident = 1; - BearerCap.UIL1Prot = (codec == FTDM_CODEC_ALAW) ? 3 : 2; /* U-law = 2, A-law = 3 */ - gen->BearerCap = Q931AppendIE(gen, (L3UCHAR *) &BearerCap); - - /* - * ChannelID IE - */ - Q931InitIEChanID(&ChanID); - ChanID.IntType = FTDM_SPAN_IS_BRI(ftdm_channel_get_span(ftdmchan)) ? 0 : 1; /* PRI = 1, BRI = 0 */ - ChanID.PrefExcl = FTDM_SPAN_IS_NT(ftdm_channel_get_span(ftdmchan)) ? 1 : 0; /* Exclusive in NT-mode = 1, Preferred otherwise = 0 */ - if (ChanID.IntType) { - ChanID.InfoChanSel = 1; /* None = 0, See Slot = 1, Any = 3 */ - ChanID.ChanMapType = 3; /* B-Chan */ - ChanID.ChanSlot = (unsigned char)ftdm_channel_get_id(ftdmchan); - } else { - ChanID.InfoChanSel = (unsigned char)ftdm_channel_get_id(ftdmchan) & 0x03; /* None = 0, B1 = 1, B2 = 2, Any = 3 */ - } - gen->ChanID = Q931AppendIE(gen, (L3UCHAR *) &ChanID); - - /* - * Progress IE - */ - Q931InitIEProgInd(&Progress); - Progress.CodStand = Q931_CODING_ITU; /* 0 = ITU */ - Progress.Location = 0; /* 0 = User, 1 = Private Network */ - Progress.ProgDesc = 3; /* 1 = Not end-to-end ISDN */ - gen->ProgInd = Q931AppendIE(gen, (L3UCHAR *)&Progress); - - /* - * Display IE - */ - if (!(isdn_data->opts & FTDM_ISDN_OPT_OMIT_DISPLAY_IE) && FTDM_SPAN_IS_NT(ftdm_channel_get_span(ftdmchan))) { - Q931InitIEDisplay(&Display); - Display.Size = Display.Size + (unsigned char)strlen(caller_data->cid_name); - gen->Display = Q931AppendIE(gen, (L3UCHAR *) &Display); - ptrDisplay = Q931GetIEPtr(gen->Display, gen->buf); - ftdm_copy_string((char *)ptrDisplay->Display, caller_data->cid_name, strlen(caller_data->cid_name) + 1); - } - - /* - * CallingNum IE - */ - Q931InitIECallingNum(&CallingNum); - CallingNum.TypNum = caller_data->ani.type; - CallingNum.NumPlanID = Q931_NUMPLAN_E164; - CallingNum.PresInd = Q931_PRES_ALLOWED; - CallingNum.ScreenInd = Q931_SCREEN_USER_NOT_SCREENED; - CallingNum.Size = CallingNum.Size + (unsigned char)strlen(caller_data->cid_num.digits); - gen->CallingNum = Q931AppendIE(gen, (L3UCHAR *) &CallingNum); - ptrCallingNum = Q931GetIEPtr(gen->CallingNum, gen->buf); - ftdm_copy_string((char *)ptrCallingNum->Digit, caller_data->cid_num.digits, strlen(caller_data->cid_num.digits) + 1); - - /* - * CalledNum IE - */ - Q931InitIECalledNum(&CalledNum); - CalledNum.TypNum = Q931_TON_UNKNOWN; - CalledNum.NumPlanID = Q931_NUMPLAN_E164; - CalledNum.Size = CalledNum.Size + (unsigned char)strlen(caller_data->ani.digits); - gen->CalledNum = Q931AppendIE(gen, (L3UCHAR *) &CalledNum); - ptrCalledNum = Q931GetIEPtr(gen->CalledNum, gen->buf); - ftdm_copy_string((char *)ptrCalledNum->Digit, caller_data->ani.digits, strlen(caller_data->ani.digits) + 1); - - /* - * High-Layer Compatibility IE (Note: Required for AVM FritzBox) - */ - Q931InitIEHLComp(&HLComp); - HLComp.CodStand = Q931_CODING_ITU; /* ITU */ - HLComp.Interpret = 4; /* only possible value */ - HLComp.PresMeth = 1; /* High-layer protocol profile */ - HLComp.HLCharID = Q931_HLCHAR_TELEPHONY; /* Telephony = 1, Fax G2+3 = 4, Fax G4 = 65 (Class I)/ 68 (Class II or III) */ /* TODO: make accessible from user layer */ - gen->HLComp = Q931AppendIE(gen, (L3UCHAR *) &HLComp); - - Q931Rx43(&isdn_data->q931, gen, gen->Size); - - /* - * Support code for the new event handling system - * Remove this as soon as we have the new api to set up calls - */ - if (gen->CRV) { - call = Q931GetCallByCRV(&isdn_data->q931, gen->CRV); - if (call) { - ftdm_log(FTDM_LOG_DEBUG, "Storing reference to current span in call %d [0x%x]\n", gen->CRV, gen->CRV); - - Q931CallSetPrivate(call, ftdmchan); - ftdmchan->caller_data.call_reference = gen->CRV; - } - } - } - break; - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - { - /* reply RELEASE with RELEASE_COMPLETE message */ - if (ftdm_channel_get_last_state(ftdmchan) == FTDM_CHANNEL_STATE_HANGUP) { - gen->MesType = Q931mes_RELEASE_COMPLETE; - - Q931Rx43(&isdn_data->q931, gen, gen->Size); - } - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - break; - case FTDM_CHANNEL_STATE_HANGUP: - { - ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(ftdmchan); - Q931ie_Cause cause; - - ftdm_log(FTDM_LOG_DEBUG, "Hangup: Call direction %s\n", - ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? "Outbound" : "Inbound"); - - cause.IEId = Q931ie_CAUSE; - cause.Size = sizeof(Q931ie_Cause); - cause.CodStand = Q931_CODING_ITU; /* ITU */ - cause.Location = 1; /* private network */ - cause.Recom = 1; /* */ - - /* - * BRI PTMP needs special handling here... - * TODO: cleanup / refine (see above) - */ - if (ftdm_channel_get_last_state(ftdmchan) == FTDM_CHANNEL_STATE_RING) { - /* - * inbound call [was: number unknown (= not found in routing state)] - * (in Q.931 spec terms: Reject request) - */ - if (!FTDM_SPAN_IS_NT(span)) { - gen->MesType = Q931mes_RELEASE_COMPLETE; /* TE mode: Reject call */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } else { - gen->MesType = Q931mes_DISCONNECT; /* NT mode: Disconnect and wait */ - //ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); - } - - //cause.Value = (unsigned char) FTDM_CAUSE_UNALLOCATED; - cause.Value = (unsigned char) caller_data->hangup_cause; - *cause.Diag = '\0'; - gen->Cause = Q931AppendIE(gen, (L3UCHAR *) &cause); - Q931Rx43(&isdn_data->q931, gen, gen->Size); - - /* we're done, release channel */ - ////ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); - //ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - else if (ftdm_channel_get_last_state(ftdmchan) <= FTDM_CHANNEL_STATE_PROGRESS) { - /* - * just release all unanswered calls [was: inbound call, remote side hung up before we answered] - */ - gen->MesType = Q931mes_RELEASE; - - cause.Value = (unsigned char) caller_data->hangup_cause; - *cause.Diag = '\0'; - gen->Cause = Q931AppendIE(gen, (L3UCHAR *) &cause); - Q931Rx43(&isdn_data->q931, gen, gen->Size); - - /* this will be triggered by the RELEASE_COMPLETE reply */ - /* ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); */ - } - else { - /* - * call connected, hangup - */ - gen->MesType = Q931mes_DISCONNECT; - - cause.Value = (unsigned char) caller_data->hangup_cause; - *cause.Diag = '\0'; - gen->Cause = Q931AppendIE(gen, (L3UCHAR *) &cause); - Q931Rx43(&isdn_data->q931, gen, gen->Size); - } - } - break; - case FTDM_CHANNEL_STATE_TERMINATING: - { - ftdm_log(FTDM_LOG_DEBUG, "Terminating: Call direction %s\n", - ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? "Outbound" : "Inbound"); - - sig.event_id = FTDM_SIGEVENT_STOP; - status = ftdm_span_send_signal(span, &sig); - - gen->MesType = Q931mes_RELEASE; - Q931Rx43(&isdn_data->q931, gen, gen->Size); - } - default: - break; - } -} - -static __inline__ void check_state(ftdm_span_t *span) -{ - if (ftdm_test_flag(span, FTDM_SPAN_STATE_CHANGE)) { - uint32_t j; - - ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE); - - for (j = 1; j <= ftdm_span_get_chan_count(span); j++) { - ftdm_channel_t *chan = ftdm_span_get_channel(span, j); - - if (ftdm_test_flag(chan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_channel_lock(chan); - ftdm_clear_flag(chan, FTDM_CHANNEL_STATE_CHANGE); - state_advance(chan); - ftdm_channel_unlock(chan); - } - } - } -} - - -static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *event) -{ - ftdm_alarm_flag_t alarmbits; - ftdm_sigmsg_t sig; - - memset(&sig, 0, sizeof(sig)); - sig.span_id = ftdm_channel_get_span_id(event->channel); - sig.chan_id = ftdm_channel_get_id(event->channel); - sig.channel = event->channel; - - ftdm_log(FTDM_LOG_DEBUG, "EVENT [%s][%d:%d] STATE [%s]\n", - ftdm_oob_event2str(event->enum_id), - ftdm_channel_get_span_id(event->channel), - ftdm_channel_get_id(event->channel), - ftdm_channel_get_state_str(event->channel)); - - switch (event->enum_id) { - case FTDM_OOB_ALARM_TRAP: - { - sig.event_id = FTDM_OOB_ALARM_TRAP; - if (ftdm_channel_get_state(event->channel) != FTDM_CHANNEL_STATE_DOWN) { - ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_RESTART); - } - ftdm_set_flag(event->channel, FTDM_CHANNEL_SUSPENDED); - ftdm_channel_get_alarms(event->channel, &alarmbits); - ftdm_span_send_signal(span, &sig); - - ftdm_log(FTDM_LOG_WARNING, "channel %d:%d (%d:%d) has alarms [%s]\n", - ftdm_channel_get_span_id(event->channel), - ftdm_channel_get_id(event->channel), - ftdm_channel_get_ph_span_id(event->channel), - ftdm_channel_get_ph_id(event->channel), - ftdm_channel_get_last_error(event->channel)); - } - break; - case FTDM_OOB_ALARM_CLEAR: - { - sig.event_id = FTDM_OOB_ALARM_CLEAR; - ftdm_clear_flag(event->channel, FTDM_CHANNEL_SUSPENDED); - ftdm_channel_get_alarms(event->channel, &alarmbits); - ftdm_span_send_signal(span, &sig); - } - break; -#ifdef __BROKEN_BY_FREETDM_CONVERSION__ - case FTDM_OOB_DTMF: /* Taken from ozmod_analog, minus the CALLWAITING state handling */ - { - const char * digit_str = (const char *)event->data; - - if (digit_str) { - fio_event_cb_t event_callback = NULL; - - ftdm_channel_queue_dtmf(event->channel, digit_str); - if (span->event_callback) { - event_callback = span->event_callback; - } else if (event->channel->event_callback) { - event_callback = event->channel->event_callback; - } - - if (event_callback) { - event->channel->event_header.channel = event->channel; - event->channel->event_header.e_type = FTDM_EVENT_DTMF; - event->channel->event_header.data = (void *)digit_str; - event_callback(event->channel, &event->channel->event_header); - event->channel->event_header.e_type = FTDM_EVENT_NONE; - event->channel->event_header.data = NULL; - } - ftdm_safe_free(event->data); - } - } - break; -#endif - } - - return FTDM_SUCCESS; -} - - -static __inline__ void check_events(ftdm_span_t *span) -{ - ftdm_status_t status = ftdm_span_poll_event(span, 5, NULL); - - switch (status) { - case FTDM_SUCCESS: - { - ftdm_event_t *event; - - while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) { - if (event->enum_id == FTDM_OOB_NOOP) { - continue; - } - if (process_event(span, event) != FTDM_SUCCESS) { - break; - } - } - } - break; - case FTDM_FAIL: - { - ftdm_log(FTDM_LOG_DEBUG, "Event Failure! %d\n", ftdm_running()); - } - break; - default: - break; - } -} - - -static int teletone_handler(teletone_generation_session_t *ts, teletone_tone_map_t *map) -{ - ftdm_buffer_t *dt_buffer = ts->user_data; - int wrote; - - if (!dt_buffer) { - return -1; - } - - wrote = teletone_mux_tones(ts, map); - ftdm_buffer_write(dt_buffer, ts->buffer, wrote * 2); - return 0; -} - -static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj) -{ - ftdm_span_t *span = (ftdm_span_t *) obj; - ftdm_isdn_data_t *isdn_data = span->signal_data; - ftdm_buffer_t *dt_buffer = NULL; - teletone_generation_session_t ts = {{{{0}}}};; - unsigned char frame[1024]; - int x, interval; - - ftdm_log(FTDM_LOG_DEBUG, "ISDN tones thread starting.\n"); - ftdm_set_flag(isdn_data, FTDM_ISDN_TONES_RUNNING); - - if (ftdm_buffer_create(&dt_buffer, 1024, 1024, 0) != FTDM_SUCCESS) { - snprintf(isdn_data->dchan->last_error, sizeof(isdn_data->dchan->last_error), "memory error!"); - ftdm_log(FTDM_LOG_ERROR, "MEM ERROR\n"); - goto done; - } - ftdm_buffer_set_loops(dt_buffer, -1); - - /* get a tone generation friendly interval to avoid distortions */ - for (x = 1; x <= ftdm_span_get_chan_count(span); x++) { - ftdm_channel_t *chan = ftdm_span_get_channel(span, x); - - if (ftdm_channel_get_type(chan) != FTDM_CHAN_TYPE_DQ921) { - ftdm_channel_command(chan, FTDM_COMMAND_GET_INTERVAL, &interval); - break; - } - } - if (!interval) { - interval = 20; - } - ftdm_log(FTDM_LOG_NOTICE, "Tone generating interval %d\n", interval); - - /* init teletone */ - teletone_init_session(&ts, 0, teletone_handler, dt_buffer); - ts.rate = 8000; - ts.duration = ts.rate; - - /* main loop */ - while (ftdm_running() && ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING)) { - ftdm_wait_flag_t flags; - ftdm_status_t status; - int last_chan_state = 0; - int gated = 0; - L2ULONG now = ftdm_time_now(); - - /* - * check b-channel states and generate & send tones if neccessary - */ - for (x = 1; x <= ftdm_span_get_chan_count(span); x++) { - ftdm_channel_t *chan = ftdm_span_get_channel(span, x); - ftdm_size_t len = sizeof(frame), rlen; - ftdm_isdn_bchan_data_t *data = chan->call_data; - - if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_DQ921) { - continue; - } - - /* - * Generate tones based on current bchan state - * (Recycle buffer content if succeeding channels share the - * same state, this saves some cpu cycles) - */ - switch (ftdm_channel_get_state(chan)) { - case FTDM_CHANNEL_STATE_DIALTONE: - { - ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan); - - /* check overlap dial timeout first before generating tone */ - if (data && data->digit_timeout && data->digit_timeout <= now) { - if (strlen(caller_data->dnis.digits) > 0) { - ftdm_log(FTDM_LOG_DEBUG, "Overlap dial timeout, advancing to RING state\n"); - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RING); - } else { - /* no digits received, hangup */ - ftdm_log(FTDM_LOG_DEBUG, "Overlap dial timeout, no digits received, going to HANGUP state\n"); - caller_data->hangup_cause = FTDM_CAUSE_RECOVERY_ON_TIMER_EXPIRE; /* TODO: probably wrong cause value */ - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP); - } - data->digit_timeout = 0; - continue; - } - - if (last_chan_state != ftdm_channel_get_state(chan)) { - ftdm_buffer_zero(dt_buffer); - teletone_run(&ts, span->tone_map[FTDM_TONEMAP_DIAL]); - last_chan_state = ftdm_channel_get_state(chan); - } - } - break; - - case FTDM_CHANNEL_STATE_RING: - { - if (last_chan_state != ftdm_channel_get_state(chan)) { - ftdm_buffer_zero(dt_buffer); - teletone_run(&ts, span->tone_map[FTDM_TONEMAP_RING]); - last_chan_state = ftdm_channel_get_state(chan); - } - } - break; - - default: /* Not in a tone generating state, go to next round */ - continue; - } - - if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) { - if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) { - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP); - continue; - } - ftdm_log(FTDM_LOG_NOTICE, "Successfully opened channel %d:%d\n", - ftdm_channel_get_span_id(chan), - ftdm_channel_get_id(chan)); - } - - flags = FTDM_READ; - - status = ftdm_channel_wait(chan, &flags, (gated) ? 0 : interval); - switch (status) { - case FTDM_FAIL: - continue; - - case FTDM_TIMEOUT: - gated = 1; - continue; - - default: - if (!(flags & FTDM_READ)) { - continue; - } - } - gated = 1; - - status = ftdm_channel_read(chan, frame, &len); - if (status != FTDM_SUCCESS || len <= 0) { - continue; - } - - /* - * Teletone operates on SLIN data (2 bytes per sample). - * Convert the length of non-SLIN codecs, so we read - * the right amount of samples from the buffer. - */ - if (chan->effective_codec != FTDM_CODEC_SLIN) { - len *= 2; - } - - /* seek to current offset */ - ftdm_buffer_seek(dt_buffer, data->offset); - - /* - * ftdm_channel_read() can read up to sizeof(frame) bytes - * (in certain situations). Avoid overflowing the stack (and smashing dt_buffer) - * if the codec is not slin and we had to double the length. - */ - len = ftdm_min(len, sizeof(frame)); - rlen = ftdm_buffer_read_loop(dt_buffer, frame, len); - - if (chan->effective_codec != FTDM_CODEC_SLIN) { - fio_codec_t codec_func = NULL; - - if (chan->native_codec == FTDM_CODEC_ULAW) { - codec_func = fio_slin2ulaw; - } else if (chan->native_codec == FTDM_CODEC_ALAW) { - codec_func = fio_slin2alaw; - } - - /* - * Convert SLIN to native format (a-law/u-law), - * input size is 2 bytes per sample, output size - * (after conversion) is one byte per sample - * (= max. half the input size). - */ - if (codec_func) { - status = codec_func(frame, sizeof(frame), &rlen); - } else { - snprintf(chan->last_error, sizeof(chan->last_error), "codec error!"); - goto done; - } - } - - if (ftdm_channel_write(chan, frame, sizeof(frame), &rlen) == FTDM_SUCCESS) { - /* - * Advance offset in teletone buffer by amount - * of data actually written to channel. - */ - if (chan->effective_codec != FTDM_CODEC_SLIN) { - data->offset += rlen << 1; /* Teletone buffer is in SLIN (= rlen * 2) */ - } else { - data->offset += rlen; - } - - /* Limit offset to [0..Rate(Samples/s)-1] in SLIN (2 bytes per sample) units. */ - data->offset %= (ts.rate << 1); - } - } - - /* - * sleep a bit if there was nothing to do - */ - if (!gated) { - ftdm_sleep(interval); - } - } - -done: - if (ts.buffer) { - teletone_destroy_session(&ts); - } - - if (dt_buffer) { - ftdm_buffer_destroy(&dt_buffer); - } - - ftdm_log(FTDM_LOG_DEBUG, "ISDN tone thread ended.\n"); - ftdm_clear_flag(isdn_data, FTDM_ISDN_TONES_RUNNING); - - return NULL; -} - -static void *ftdm_isdn_run(ftdm_thread_t *me, void *obj) -{ - ftdm_span_t *span = (ftdm_span_t *) obj; - ftdm_isdn_data_t *isdn_data = span->signal_data; - unsigned char frame[1024]; - ftdm_size_t len = sizeof(frame); - int errs = 0; - -#ifdef WIN32 - timeBeginPeriod(1); -#endif - - ftdm_log(FTDM_LOG_DEBUG, "ISDN thread starting.\n"); - ftdm_set_flag(isdn_data, FTDM_ISDN_RUNNING); - - Q921Start(&isdn_data->q921); - Q931Start(&isdn_data->q931); - - while (ftdm_running() && ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING)) { - ftdm_wait_flag_t flags = FTDM_READ; - ftdm_status_t status = ftdm_channel_wait(isdn_data->dchan, &flags, 100); - - Q921TimerTick(&isdn_data->q921); - Q931TimerTick(&isdn_data->q931); - check_state(span); - check_events(span); - - /* - * - */ - switch (status) { - case FTDM_FAIL: - { - ftdm_log(FTDM_LOG_ERROR, "D-Chan Read Error!\n"); - snprintf(span->last_error, sizeof(span->last_error), "D-Chan Read Error!"); - if (++errs == 10) { - isdn_data->dchan->state = FTDM_CHANNEL_STATE_UP; - goto done; - } - } - break; - case FTDM_TIMEOUT: - { - errs = 0; - } - break; - default: - { - if (flags & FTDM_READ) { - len = sizeof(frame); - if (ftdm_channel_read(isdn_data->dchan, frame, &len) != FTDM_SUCCESS) { - ftdm_log_chan_msg(isdn_data->dchan, FTDM_LOG_ERROR, "Failed to read from D-Channel\n"); - continue; - } - if (len > 0) { -#ifdef HAVE_PCAP - if (isdn_pcap_capture_both(isdn_data)) { - isdn_pcap_write(isdn_data, frame, len, ISDN_PCAP_INCOMING); - } -#endif - Q921QueueHDLCFrame(&isdn_data->q921, frame, (int)len); - Q921Rx12(&isdn_data->q921); - - /* Successful read, reset error counter */ - errs = 0; - } - } else { - ftdm_log(FTDM_LOG_DEBUG, "No Read FLAG!\n"); - } - } - break; - } - } - -done: - ftdm_channel_close(&isdn_data->dchan); - ftdm_clear_flag(isdn_data, FTDM_ISDN_RUNNING); - -#ifdef WIN32 - timeEndPeriod(1); -#endif -#ifdef HAVE_PCAP - if (isdn_pcap_is_open(isdn_data)) { - isdn_pcap_close(isdn_data); - } -#endif - ftdm_log(FTDM_LOG_DEBUG, "ISDN thread ended.\n"); - return NULL; -} - -static int q931_rx_32(void *pvt, Q921DLMsg_t ind, L3UCHAR tei, L3UCHAR *msg, L3INT mlen) -{ - ftdm_span_t *span = pvt; - ftdm_isdn_data_t *isdn_data = span->signal_data; - int offset = 4; - char bb[4096] = ""; - - switch(ind) { - case Q921_DL_UNIT_DATA: - offset = 3; - - case Q921_DL_DATA: - print_hex_bytes(msg + offset, mlen - offset, bb, sizeof(bb)); - ftdm_log(FTDM_LOG_DEBUG, "WRITE %d\n%s\n%s\n\n", (int)mlen - offset, LINE, bb); - break; - - default: - break; - } - -#ifdef HAVE_PCAP - if (isdn_pcap_capture_l3only(isdn_data)) { - isdn_pcap_write(isdn_data, msg, mlen, ISDN_PCAP_OUTGOING); - } -#endif - return Q921Rx32(&isdn_data->q921, ind, tei, msg, mlen); -} - -static int ftdm_isdn_q921_log(void *pvt, Q921LogLevel_t level, char *msg, L2INT size) -{ - ftdm_span_t *span = (ftdm_span_t *) pvt; - - ftdm_log("Span", "Q.921", span->span_id, (int)level, "%s", msg); - return 0; -} - -static L3INT ftdm_isdn_q931_log(void *pvt, Q931LogLevel_t level, const char *msg, L3INT size) -{ - ftdm_span_t *span = (ftdm_span_t *) pvt; - - ftdm_log("Span", "Q.931", span->span_id, (int)level, "%s", msg); - return 0; -} - -static ftdm_state_map_t isdn_state_map = { - { - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_ANY}, - {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END} - }, - - /****************************************/ - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_ANY}, - {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DIALTONE, FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DIALTONE, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, - FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - }, - } -}; - -/** - * \brief Stop signalling on span - */ -static ftdm_status_t ftdm_isdn_stop(ftdm_span_t *span) -{ - ftdm_isdn_data_t *isdn_data = span->signal_data; - - if (!ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING)) { - return FTDM_FAIL; - } - - ftdm_set_flag(isdn_data, FTDM_ISDN_STOP); - - while (ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING)) { - ftdm_sleep(100); - } - - while (ftdm_test_flag(isdn_data, FTDM_ISDN_TONES_RUNNING)) { - ftdm_sleep(100); - } - - return FTDM_SUCCESS; -} - -/** - * \brief Start signalling on span - */ -static ftdm_status_t ftdm_isdn_start(ftdm_span_t *span) -{ - ftdm_isdn_data_t *isdn_data = span->signal_data; - ftdm_status_t ret; - - if (ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING)) { - return FTDM_FAIL; - } - - ftdm_clear_flag(isdn_data, FTDM_ISDN_STOP); - ret = ftdm_thread_create_detached(ftdm_isdn_run, span); - - if (ret != FTDM_SUCCESS) { - return ret; - } - - if (FTDM_SPAN_IS_NT(span) && !(isdn_data->opts & FTDM_ISDN_OPT_DISABLE_TONES)) { - ret = ftdm_thread_create_detached(ftdm_isdn_tones_run, span); - } - return ret; -} - - -/*###################################################################* - * (text) value parsing / translation - *###################################################################*/ - -static int32_t parse_loglevel(const char *level) -{ - if (!level) - return -1; - - if (!strcasecmp(level, "debug")) { - return FTDM_LOG_LEVEL_DEBUG; - } else if (!strcasecmp(level, "info")) { - return FTDM_LOG_LEVEL_INFO; - } else if (!strcasecmp(level, "notice")) { - return FTDM_LOG_LEVEL_NOTICE; - } else if (!strcasecmp(level, "warning")) { - return FTDM_LOG_LEVEL_WARNING; - } else if (!strcasecmp(level, "error")) { - return FTDM_LOG_LEVEL_ERROR; - } else if (!strcasecmp(level, "alert")) { - return FTDM_LOG_LEVEL_ALERT; - } else if (!strcasecmp(level, "crit")) { - return FTDM_LOG_LEVEL_CRIT; - } else if (!strcasecmp(level, "emerg")) { - return FTDM_LOG_LEVEL_EMERG; - } else { - return -1; - } -} - -static int parse_opts(const char *in, uint32_t *flags) -{ - if (!in || !flags) - return -1; - - if (strstr(in, "suggest_channel")) { - *flags |= FTDM_ISDN_OPT_SUGGEST_CHANNEL; - } - if (strstr(in, "omit_display")) { - *flags |= FTDM_ISDN_OPT_OMIT_DISPLAY_IE; - } - if (strstr(in, "disable_tones")) { - *flags |= FTDM_ISDN_OPT_DISABLE_TONES; - } - - return 0; -} - -static int parse_dialect(const char *in, uint32_t *dialect) -{ - if (!in || !dialect) - return -1; - -#if __UNSUPPORTED__ - if (!strcasecmp(in, "national")) { - *dialect = Q931_Dialect_National; - return 0; - } - if (!strcasecmp(in, "dms")) { - *dialect = Q931_Dialect_DMS; - return 0; - } -#endif - if (!strcasecmp(in, "5ess")) { - *dialect = Q931_Dialect_5ESS; - return 0; - } - if (!strcasecmp(in, "dss1") || !strcasecmp(in, "euroisdn")) { - *dialect = Q931_Dialect_DSS1; - return 0; - } - if (!strcasecmp(in, "q931")) { - *dialect = Q931_Dialect_Q931; - return 0; - } - - return -1; -} - - -/*###################################################################* - * API commands - *###################################################################*/ - -static const char isdn_api_usage[] = -#ifdef HAVE_PCAP - "isdn capture [q931only]\n" - "isdn capture \n" -#endif - "isdn loglevel \n" - "isdn dump calls\n" - "isdn help"; - - -/** - * isdn_api - */ -static FIO_API_FUNCTION(isdn_api) -{ - char *mycmd = NULL, *argv[10] = { 0 }; - int argc = 0; - - if (data) { - mycmd = strdup(data); - argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); - } - - if (!argc || !strcasecmp(argv[0], "help")) { - stream->write_function(stream, "%s\n", isdn_api_usage); - goto done; - } - else if (!strcasecmp(argv[0], "dump")) { - ftdm_isdn_data_t *isdn_data = NULL; - ftdm_span_t *span = NULL; - int span_id = 0; - - /* dump calls */ - - if (argc < 3) { - stream->write_function(stream, "-ERR not enough arguments.\n"); - goto done; - } - - span_id = atoi(argv[1]); - - if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) { - isdn_data = span->signal_data; - } else { - stream->write_function(stream, "-ERR invalid span.\n"); - goto done; - } - - if (!strcasecmp(argv[2], "calls")) { - /* dump all calls to log */ - Q931DumpAllCalls(&isdn_data->q931); - stream->write_function(stream, "+OK call information dumped to log\n"); - goto done; - } - } - else if (!strcasecmp(argv[0], "loglevel")) { - ftdm_isdn_data_t *isdn_data = NULL; - ftdm_span_t *span = NULL; - int span_id = 0; - int layer = 0; - int level = 0; - - /* loglevel [level] */ - - if (argc < 3) { - stream->write_function(stream, "-ERR not enough arguments.\n"); - goto done; - } - - span_id = atoi(argv[1]); - - if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) { - isdn_data = span->signal_data; - } else { - stream->write_function(stream, "-ERR invalid span.\n"); - goto done; - } - - if (!strcasecmp(argv[2], "q921")) { - layer = 0x01; - } else if (!strcasecmp(argv[2], "q931")) { - layer = 0x02; - } else if (!strcasecmp(argv[2], "all")) { - layer = 0x03; - } else { - stream->write_function(stream, "-ERR invalid layer\n"); - goto done; - } - - if (argc > 3) { - /* set loglevel */ - if ((level = parse_loglevel(argv[3])) < 0) { - stream->write_function(stream, "-ERR invalid loglevel\n"); - goto done; - } - - if (layer & 0x01) { /* q921 */ - Q921SetLogLevel(&isdn_data->q921, (Q921LogLevel_t)level); - } - if (layer & 0x02) { /* q931 */ - Q931SetLogLevel(&isdn_data->q931, (Q931LogLevel_t)level); - } - stream->write_function(stream, "+OK loglevel set"); - } else { - /* get loglevel */ - if (layer & 0x01) { - stream->write_function(stream, "Q.921 loglevel: %s\n", - Q921GetLogLevelName(&isdn_data->q921)); - } - if (layer & 0x02) { - stream->write_function(stream, "Q.931 loglevel: %s\n", - Q931GetLogLevelName(&isdn_data->q931)); - } - stream->write_function(stream, "+OK"); - } - goto done; - } -#ifdef HAVE_PCAP - else if (!strcasecmp(argv[0], "capture")) { - ftdm_isdn_data_t *isdn_data = NULL; - ftdm_span_t *span = NULL; - int span_id = 0; - - /* capture [q931only] */ - /* capture */ - - if (argc < 3) { - stream->write_function(stream, "-ERR not enough arguments.\n"); - goto done; - } - - span_id = atoi(argv[1]); - - if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) { - isdn_data = span->signal_data; - } else { - stream->write_function(stream, "-ERR invalid span.\n"); - goto done; - } - - if (!strcasecmp(argv[2], "start")) { - char *filename = NULL; - - if (argc < 4) { - stream->write_function(stream, "-ERR not enough parameters.\n"); - goto done; - } - - if (isdn_pcap_is_open(isdn_data)) { - stream->write_function(stream, "-ERR capture is already running.\n"); - goto done; - } - - filename = argv[3]; - - if (isdn_pcap_open(isdn_data, filename) != FTDM_SUCCESS) { - stream->write_function(stream, "-ERR failed to open capture file.\n"); - goto done; - } - - if (argc > 4 && !strcasecmp(argv[4], "q931only")) { - isdn_data->flags |= FTDM_ISDN_CAPTURE_L3ONLY; - } - isdn_pcap_start(isdn_data); - - stream->write_function(stream, "+OK capture started.\n"); - goto done; - } - else if (!strcasecmp(argv[2], "stop")) { - - if (!isdn_pcap_is_open(isdn_data)) { - stream->write_function(stream, "-ERR capture is not running.\n"); - goto done; - } - - isdn_pcap_stop(isdn_data); - isdn_pcap_close(isdn_data); - - stream->write_function(stream, "+OK capture stopped.\n"); - goto done; - } - else if (!strcasecmp(argv[2], "suspend")) { - - if (!isdn_pcap_is_open(isdn_data)) { - stream->write_function(stream, "-ERR capture is not running.\n"); - goto done; - } - isdn_pcap_stop(isdn_data); - - stream->write_function(stream, "+OK capture suspended.\n"); - goto done; - } - else if (!strcasecmp(argv[2], "resume")) { - - if (!isdn_pcap_is_open(isdn_data)) { - stream->write_function(stream, "-ERR capture is not running.\n"); - goto done; - } - isdn_pcap_start(isdn_data); - - stream->write_function(stream, "+OK capture resumed.\n"); - goto done; - } - else { - stream->write_function(stream, "-ERR wrong action.\n"); - goto done; - } - } -#endif - else { - stream->write_function(stream, "-ERR invalid command.\n"); - } -done: - ftdm_safe_free(mycmd); - - return FTDM_SUCCESS; -} - -static int parse_mode(const char *mode) -{ - if (!mode) - return -1; - - if (!strcasecmp(mode, "user") || !strcasecmp(mode, "cpe")) { - return Q931_TE; - } - if (!strcasecmp(mode, "net") || !strcasecmp(mode, "network")) { - return Q931_NT; - } - - return -1; -} - -static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(isdn_configure_span) -{ - Q931Dialect_t dialect = Q931_Dialect_National; - ftdm_channel_t *dchan = NULL; - ftdm_isdn_data_t *isdn_data; - int32_t digit_timeout = 0; - const char *tonemap = "us"; - int dchan_count = 0, bchan_count = 0; - int q921loglevel = -1; - int q931loglevel = -1; - uint32_t i; - - if (span->signal_type) { - ftdm_log(FTDM_LOG_ERROR, "Span is already configured for signalling [%d]\n", span->signal_type); - snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling [%d]", span->signal_type); - return FTDM_FAIL; - } - - if (ftdm_span_get_trunk_type(span) >= FTDM_TRUNK_NONE) { - ftdm_log(FTDM_LOG_WARNING, "Invalid trunk type '%s' defaulting to T1\n", ftdm_span_get_trunk_type_str(span)); - span->trunk_type = FTDM_TRUNK_T1; - } - - for (i = 1; i <= ftdm_span_get_chan_count(span); i++) { - ftdm_channel_t *chan = ftdm_span_get_channel(span, i); - - switch (ftdm_channel_get_type(chan)) { - case FTDM_CHAN_TYPE_DQ921: - if (dchan_count > 1) { - ftdm_log(FTDM_LOG_ERROR, "Span has more than 1 D-Channel!\n"); - snprintf(span->last_error, sizeof(span->last_error), "Span has more than 1 D-Channel!"); - return FTDM_FAIL; - } - - if (ftdm_channel_open(ftdm_span_get_id(span), i, &dchan) == FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_DEBUG, "opening d-channel #%d %d:%d\n", dchan_count, - ftdm_channel_get_span_id(dchan), ftdm_channel_get_id(dchan)); - dchan->state = FTDM_CHANNEL_STATE_UP; - } - - dchan_count++; - break; - - case FTDM_CHAN_TYPE_B: - bchan_count++; - break; - - default: - break; - } - } - if (!dchan_count) { - ftdm_log(FTDM_LOG_ERROR, "Span has no D-Channel!\n"); - snprintf(span->last_error, sizeof(span->last_error), "Span has no D-Channel!"); - return FTDM_FAIL; - } - if (!bchan_count) { - ftdm_log(FTDM_LOG_ERROR, "Span has no B-Channels!\n"); - snprintf(span->last_error, sizeof(span->last_error), "Span has no B-Channels!"); - return FTDM_FAIL; - } - - isdn_data = malloc(sizeof(*isdn_data)); - assert(isdn_data != NULL); - - memset(isdn_data, 0, sizeof(*isdn_data)); - dialect = Q931_Dialect_Q931; - - /* Use trunk_mode span parameter to set default */ - switch (ftdm_span_get_trunk_mode(span)) { - case FTDM_TRUNK_MODE_NET: - ftdm_log(FTDM_LOG_INFO, "Span '%s' [s%d] defaulting to NET mode\n", - ftdm_span_get_name(span), ftdm_span_get_id(span)); - isdn_data->mode = Q931_NT; - break; - default: - ftdm_log(FTDM_LOG_INFO, "Span '%s' [s%d] defaulting to USER mode\n", - ftdm_span_get_name(span), ftdm_span_get_id(span)); - isdn_data->mode = Q931_TE; - break; - } - - for (i = 0; ftdm_parameters[i].var; i++) { - const char *var = ftdm_parameters[i].var; - const char *val = ftdm_parameters[i].val; - - if (ftdm_strlen_zero(var)) { - ftdm_log(FTDM_LOG_WARNING, "Skipping variable with no name\n"); - continue; - } - - if (ftdm_strlen_zero(val)) { - ftdm_log(FTDM_LOG_ERROR, "Variable '%s' has no value\n", var); - return FTDM_FAIL; - } - - if (!strcasecmp(var, "mode")) { - if ((isdn_data->mode = parse_mode(val)) < 0) { - ftdm_log(FTDM_LOG_ERROR, "Invalid/unknown mode '%s'\n", val); - snprintf(span->last_error, sizeof(span->last_error), "Invalid/unknown mode [%s]!", val); - return FTDM_FAIL; - } - } else if (!strcasecmp(var, "dialect")) { - if (parse_dialect(val, &dialect) < 0) { - ftdm_log(FTDM_LOG_ERROR, "Invalid/unknown dialect '%s'\n", val); - snprintf(span->last_error, sizeof(span->last_error), "Invalid/unknown dialect [%s]!", val); - return FTDM_FAIL; - } - } else if (!strcasecmp(var, "opts")) { - if (parse_opts(val, &isdn_data->opts) < 0) { - ftdm_log(FTDM_LOG_ERROR, "Invalid/unknown options '%s'\n", val); - snprintf(span->last_error, sizeof(span->last_error), "Invalid/unknown options [%s]!", val); - return FTDM_FAIL; - } - } else if (!strcasecmp(var, "tonemap")) { - tonemap = (const char *)val; - } else if (!strcasecmp(var, "digit_timeout")) { - digit_timeout = atoi(val); - if (digit_timeout < 3000 || digit_timeout > 30000) { - ftdm_log(FTDM_LOG_WARNING, "Digit timeout %d ms outside of range (3000 - 30000 ms), using default (10000 ms)\n", digit_timeout); - digit_timeout = DEFAULT_DIGIT_TIMEOUT; - } - } else if (!strcasecmp(var, "q921loglevel")) { - if ((q921loglevel = parse_loglevel(val)) < 0) { - ftdm_log(FTDM_LOG_ERROR, "Invalid/unknown loglevel '%s'\n", val); - snprintf(span->last_error, sizeof(span->last_error), "Invalid/unknown loglevel [%s]!", val); - return FTDM_FAIL; - } - } else if (!strcasecmp(var, "q931loglevel")) { - if ((q931loglevel = parse_loglevel(val)) < 0) { - ftdm_log(FTDM_LOG_ERROR, "Invalid/unknown loglevel '%s'\n", val); - snprintf(span->last_error, sizeof(span->last_error), "Invalid/unknown loglevel [%s]!", val); - return FTDM_FAIL; - } - } else { - ftdm_log(FTDM_LOG_ERROR, "Unknown parameter '%s'\n", var); - snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var); - return FTDM_FAIL; - } - } - - if (!digit_timeout) { - digit_timeout = DEFAULT_DIGIT_TIMEOUT; - } - - /* Check if modes match and log a message if they do not. Just to be on the safe side. */ - if (isdn_data->mode == Q931_TE && ftdm_span_get_trunk_mode(span) == FTDM_TRUNK_MODE_NET) { - ftdm_log(FTDM_LOG_WARNING, "Span '%s' signalling set up for TE/CPE/USER mode, while port is running in NT/NET mode. You may want to check your 'trunk_mode' settings.\n", - ftdm_span_get_name(span)); - } - else if (isdn_data->mode == Q931_NT && ftdm_span_get_trunk_mode(span) == FTDM_TRUNK_MODE_CPE) { - ftdm_log(FTDM_LOG_WARNING, "Span '%s' signalling set up for NT/NET mode, while port is running in TE/CPE/USER mode. You may want to check your 'trunk_mode' settings.\n", - ftdm_span_get_name(span)); - } - - /* allocate per b-chan data */ - if (isdn_data->mode == Q931_NT) { - ftdm_isdn_bchan_data_t *data; - - data = malloc(bchan_count * sizeof(ftdm_isdn_bchan_data_t)); - if (!data) { - return FTDM_FAIL; - } - - for (i = 1; i <= ftdm_span_get_chan_count(span); i++, data++) { - ftdm_channel_t *chan = ftdm_span_get_channel(span, i); - - if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_B) { - chan->call_data = data; - memset(data, 0, sizeof(ftdm_isdn_bchan_data_t)); - } - } - } - - isdn_data->dchan = dchan; - isdn_data->digit_timeout = digit_timeout; - - Q921_InitTrunk(&isdn_data->q921, - 0, - 0, - isdn_data->mode, - (ftdm_span_get_trunk_type(span) == FTDM_TRUNK_BRI_PTMP) ? Q921_PTMP : Q921_PTP, - 0, - ftdm_isdn_921_21, - (Q921Tx23CB_t)ftdm_isdn_921_23, - span, - span); - - Q921SetLogCB(&isdn_data->q921, &ftdm_isdn_q921_log, span); - Q921SetLogLevel(&isdn_data->q921, (Q921LogLevel_t)q921loglevel); - - Q931InitTrunk(&isdn_data->q931, - dialect, - isdn_data->mode, - span->trunk_type, - ftdm_isdn_931_34, - (Q931Tx32CB_t)q931_rx_32, - ftdm_isdn_931_err, - span, - span); - - Q931SetLogCB(&isdn_data->q931, &ftdm_isdn_q931_log, span); - Q931SetLogLevel(&isdn_data->q931, (Q931LogLevel_t)q931loglevel); - - /* Register new event hander CB */ - Q931SetCallEventCB(&isdn_data->q931, ftdm_isdn_call_event, span); - - /* TODO: hmm, maybe drop the "Trunk" prefix */ - Q931TrunkSetAutoRestartAck(&isdn_data->q931, 1); - Q931TrunkSetAutoConnectAck(&isdn_data->q931, 1); - Q931TrunkSetAutoServiceAck(&isdn_data->q931, 1); - Q931TrunkSetStatusEnquiry(&isdn_data->q931, 0); - - span->state_map = &isdn_state_map; - span->signal_data = isdn_data; - span->signal_type = FTDM_SIGTYPE_ISDN; - span->signal_cb = sig_cb; - span->start = ftdm_isdn_start; - span->stop = ftdm_isdn_stop; - span->outgoing_call = isdn_outgoing_call; - - span->get_channel_sig_status = isdn_get_channel_sig_status; - span->get_span_sig_status = isdn_get_span_sig_status; - -#ifdef __TODO__ - if ((isdn_data->opts & FTDM_ISDN_OPT_SUGGEST_CHANNEL)) { - span->channel_request = isdn_channel_request; - span->flags |= FTDM_SPAN_SUGGEST_CHAN_ID; - } -#endif - ftdm_span_load_tones(span, tonemap); - - return FTDM_SUCCESS; -} - -/** - * ISDN module io interface - * \note This is really ugly... - */ -static ftdm_io_interface_t isdn_interface = { - .name = "isdn", - .api = isdn_api -}; - -/** - * \brief ISDN module io interface init callback - */ -static FIO_IO_LOAD_FUNCTION(isdn_io_load) -{ - assert(fio != NULL); - - *fio = &isdn_interface; - - return FTDM_SUCCESS; -} - -/** - * \brief ISDN module load callback - */ -static FIO_SIG_LOAD_FUNCTION(isdn_load) -{ - Q931Initialize(); - - Q921SetGetTimeCB(ftdm_time_now); - Q931SetGetTimeCB(ftdm_time_now); - - return FTDM_SUCCESS; -} - -/** - * \brief ISDN module shutdown callback - */ -static FIO_SIG_UNLOAD_FUNCTION(isdn_unload) -{ - return FTDM_SUCCESS; -}; - -ftdm_module_t ftdm_module = { - .name = "isdn", - .io_load = isdn_io_load, - .io_unload = NULL, - .sig_load = isdn_load, - .sig_unload = isdn_unload, - .configure_span_signaling = isdn_configure_span -}; - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet expandtab: - */ diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h deleted file mode 100644 index 378f901320..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef FTDM_ISDN_H -#define FTDM_ISDN_H - -#define DEFAULT_DIGIT_TIMEOUT 10000 /* default overlap timeout: 10 seconds */ - - -typedef enum { - FTDM_ISDN_OPT_NONE = 0, - FTDM_ISDN_OPT_SUGGEST_CHANNEL = (1 << 0), - FTDM_ISDN_OPT_OMIT_DISPLAY_IE = (1 << 1), /*!< Do not send Caller name in outgoing SETUP message (= Display IE) */ - FTDM_ISDN_OPT_DISABLE_TONES = (1 << 2), /*!< Disable tone generating thread (NT mode) */ - - FTDM_ISDN_OPT_MAX = (2 << 0) -} ftdm_isdn_opts_t; - -typedef enum { - FTDM_ISDN_RUNNING = (1 << 0), - FTDM_ISDN_TONES_RUNNING = (1 << 1), - FTDM_ISDN_STOP = (1 << 2), - - FTDM_ISDN_CAPTURE = (1 << 3), - FTDM_ISDN_CAPTURE_L3ONLY = (1 << 4) -} ftdm_isdn_flag_t; - -#ifdef HAVE_PCAP -struct pcap_context; -#endif - -struct ftdm_isdn_data { - Q921Data_t q921; - Q931_TrunkInfo_t q931; - ftdm_channel_t *dchan; - uint32_t flags; - int32_t mode; - int32_t digit_timeout; - ftdm_isdn_opts_t opts; -#ifdef HAVE_PCAP - struct pcap_context *pcap; -#endif -}; - -typedef struct ftdm_isdn_data ftdm_isdn_data_t; - - -/* b-channel private data */ -struct ftdm_isdn_bchan_data -{ - ftdm_time_t digit_timeout; - int offset; /* offset in teletone buffer */ -}; - -typedef struct ftdm_isdn_bchan_data ftdm_isdn_bchan_data_t; - - -#endif - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet expandtab: - */ - diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c deleted file mode 100644 index 03f2fc3c8b..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ /dev/null @@ -1,3248 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * Copyright (c) 2010, Stefan Knoblich - * Copyright (c) 2012-2013, Stefan Knoblich - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "private/ftdm_core.h" -#include "ftmod_libpri.h" - - -static ftdm_status_t ftdm_libpri_start(ftdm_span_t *span); -static ftdm_io_interface_t ftdm_libpri_interface; - -static int on_timeout_t302(struct lpwrap_pri *spri, struct lpwrap_timer *timer); -static int on_timeout_t316(struct lpwrap_pri *spri, struct lpwrap_timer *timer); -static int on_timeout_t3xx(struct lpwrap_pri *spri, struct lpwrap_timer *timer); - - -static void _ftdm_channel_set_state_force(ftdm_channel_t *chan, const ftdm_channel_state_t state) -{ - assert(chan); - chan->state = state; -} - -/** - * \brief Unloads libpri IO module - * \return Success - */ -static FIO_IO_UNLOAD_FUNCTION(ftdm_libpri_unload) -{ - return FTDM_SUCCESS; -} - -/** - * \brief Returns the signalling status on a channel - * \param ftdmchan Channel to get status on - * \param status Pointer to set signalling status - * \return Success or failure - */ - -static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(isdn_get_channel_sig_status) -{ - *status = FTDM_SIG_STATE_DOWN; - - ftdm_libpri_data_t *isdn_data = ftdmchan->span->signal_data; - if (ftdm_test_flag(&(isdn_data->spri), LPWRAP_PRI_READY)) { - *status = FTDM_SIG_STATE_UP; - } - return FTDM_SUCCESS; -} - -/** - * \brief Returns the signalling status on a span - * \param span Span to get status on - * \param status Pointer to set signalling status - * \return Success or failure - */ - -static FIO_SPAN_GET_SIG_STATUS_FUNCTION(isdn_get_span_sig_status) -{ - *status = FTDM_SIG_STATE_DOWN; - - ftdm_libpri_data_t *isdn_data = span->signal_data; - if (ftdm_test_flag(&(isdn_data->spri), LPWRAP_PRI_READY)) { - *status = FTDM_SIG_STATE_UP; - } - return FTDM_SUCCESS; -} - - -/** - * \brief Starts a libpri channel (outgoing call) - * \param ftdmchan Channel to initiate call on - * \return Success or failure - */ -static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(isdn_outgoing_call) -{ - ftdm_unused_arg(ftdmchan); - return FTDM_SUCCESS; -} - -/** - * \brief Requests an libpri channel on a span (outgoing call) - * \param span Span where to get a channel (unused) - * \param chan_id Specific channel to get (0 for any) (unused) - * \param direction Call direction (unused) - * \param caller_data Caller information (unused) - * \param ftdmchan Channel to initialise (unused) - * \return Failure - */ -static FIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request) -{ - ftdm_unused_arg(span); - ftdm_unused_arg(chan_id); - ftdm_unused_arg(direction); - ftdm_unused_arg(caller_data); - ftdm_unused_arg(ftdmchan); - return FTDM_FAIL; -} - - -/** - * \brief Logs a libpri message - * \param pri libpri structure - * \param s Message string - */ -static void s_pri_message(struct pri *pri, char *s) -{ - struct lpwrap_pri *spri = pri_get_userdata(pri); - - if (spri && spri->dchan) { - ftdm_log_chan(spri->dchan, FTDM_LOG_DEBUG, "%s", s); - } else { - ftdm_log(FTDM_LOG_DEBUG, "%s", s); - } -} - -/** - * \brief Logs a libpri error - * \param pri libpri structure - * \param s Error string - */ -static void s_pri_error(struct pri *pri, char *s) -{ - struct lpwrap_pri *spri = pri_get_userdata(pri); - - if (spri && spri->dchan) { - ftdm_log_chan(spri->dchan, FTDM_LOG_ERROR, "%s", s); - } else { - ftdm_log(FTDM_LOG_ERROR, "%s", s); - } -} - - -#define PRI_DEBUG_Q921_ALL (PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE) -#define PRI_DEBUG_Q931_ALL (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | PRI_DEBUG_Q931_ANOMALY) - -static const struct ftdm_libpri_debug { - const char *name; - const int flags; -} ftdm_libpri_debug[] = { - /* NOTE: order is important for print_debug() */ - { "q921_all", PRI_DEBUG_Q921_ALL }, - { "q921_raw", PRI_DEBUG_Q921_RAW }, - { "q921_dump", PRI_DEBUG_Q921_DUMP }, - { "q921_state", PRI_DEBUG_Q921_STATE }, - - { "q931_all", PRI_DEBUG_Q931_ALL }, - { "q931_dump", PRI_DEBUG_Q931_DUMP }, - { "q931_state", PRI_DEBUG_Q931_STATE }, - { "q931_anomaly", PRI_DEBUG_Q931_ANOMALY }, - - { "config", PRI_DEBUG_CONFIG }, - { "apdu", PRI_DEBUG_APDU }, - { "aoc", PRI_DEBUG_AOC } -}; - -/** - * \brief Parses a debug string to flags - * \param in Debug string to parse for - * \return Flags or -1 if nothing matched - */ -static int parse_debug(const char *in, uint32_t *flags) -{ - int res = -1; - int i; - - if (!in || !flags) - return -1; - - if (!strcmp(in, "all")) { - *flags = PRI_DEBUG_ALL; - return 0; - } - if (strstr(in, "none")) { - *flags = 0; - return 0; - } - - for (i = 0; i < ftdm_array_len(ftdm_libpri_debug); i++) { - if (strstr(in, ftdm_libpri_debug[i].name)) { - *flags |= ftdm_libpri_debug[i].flags; - res = 0; - } - } - return res; -} - -#ifdef HAVE_LIBPRI_MAINT_SERVICE -/** - * \brief Parses a change status string to flags - * \param in change status string to parse for - * \return Flags - */ -static int parse_change_status(const char *in) -{ - int flags = 0; - if (!in) { - return 0; - } - - if (strstr(in, "in_service") || strstr(in, "in")) { - flags = SERVICE_CHANGE_STATUS_INSERVICE; - } - if (strstr(in, "maintenance") || strstr(in, "maint")) { - flags = SERVICE_CHANGE_STATUS_MAINTENANCE; - } - if (strstr(in, "out_of_service") || strstr(in, "out")) { - flags = SERVICE_CHANGE_STATUS_OUTOFSERVICE; - } - - - return flags; -} -#endif - - -static int print_debug(uint32_t flags, char *tmp, const int size) -{ - int offset = 0; - int res = 0; - int i; - - if ((flags & PRI_DEBUG_ALL) == PRI_DEBUG_ALL) { - strcat(tmp, "all"); - return 0; - } - else if (!flags) { - strcat(tmp, "none"); - return 0; - } - - for (i = 0; i < ftdm_array_len(ftdm_libpri_debug); i++) { - if ((flags & ftdm_libpri_debug[i].flags) == ftdm_libpri_debug[i].flags) { - res = snprintf(&tmp[offset], size - offset, "%s,", ftdm_libpri_debug[i].name); - if (res <= 0 || res == (size - offset)) - goto out; - offset += res; - flags &= ~ftdm_libpri_debug[i].flags; /* remove detected flags to make *_all work correctly */ - } - } - -out: - tmp[offset - 1] = '\0'; - return 0; -} - - -/*************************************************************** - * MSN filter - ***************************************************************/ - -/** - * Initialize MSN filter data structures - * \param[in] isdn_data Span private data - * \return FTDM_SUCCESS, FTDM_FAIL - */ -static int msn_filter_init(ftdm_libpri_data_t *isdn_data) -{ - if (!isdn_data) - return FTDM_FAIL; - - isdn_data->msn_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); - if (!isdn_data->msn_hash) - return FTDM_FAIL; - - if (ftdm_mutex_create(&isdn_data->msn_mutex)) { - hashtable_destroy(isdn_data->msn_hash); - return FTDM_FAIL; - } - - return FTDM_SUCCESS; -} - -/** - * Destroy MSN filter data structures - * \param[in] isdn_data Span private data - * \return FTDM_SUCCESS, FTDM_FAIL - */ -static int msn_filter_destroy(ftdm_libpri_data_t *isdn_data) -{ - if (!isdn_data) - return FTDM_FAIL; - - if (isdn_data->msn_hash) - hashtable_destroy(isdn_data->msn_hash); - if (isdn_data->msn_mutex) - ftdm_mutex_destroy(&isdn_data->msn_mutex); - - return FTDM_SUCCESS; -} - -/** - * Check if the given string is a valid MSN/DDI - * (i.e.: Not empty, not longer than FDM_DIGITS_LIMIT and all numbers) - * \param[in] str String to check - * \return FTDM_SUCCESS, FTDM_FAIL - */ -static int msn_filter_verify(const char *str) -{ - if (ftdm_strlen_zero(str) || strlen(str) >= FTDM_DIGITS_LIMIT) - return FTDM_FALSE; - - if (ftdm_is_number(str) != FTDM_SUCCESS) - return FTDM_FALSE; - - return FTDM_TRUE; -} - -/** - * Add a new MSN/DDI to the filter - * \param[in] isdn_data Span private data - * \param[in] msn New MSN/DDI to add - * \return FTDM_SUCCESS, FTDM_FAIL - */ -static int msn_filter_add(ftdm_libpri_data_t *isdn_data, const char *msn) -{ - static const int value = 0xdeadbeef; - char *key = NULL; - int ret = FTDM_SUCCESS; - - if (!isdn_data || !msn_filter_verify(msn)) - return FTDM_FAIL; - - ftdm_mutex_lock(isdn_data->msn_mutex); - - /* check for duplicates (ignore if already in set) */ - if (hashtable_search(isdn_data->msn_hash, (void *)msn)) { - ret = FTDM_SUCCESS; - goto out; - } - - /* Copy MSN (transient string), hashtable will free it in hashtable_destroy() */ - key = ftdm_strdup(msn); - if (!key) { - ret = FTDM_FAIL; - goto out; - } - - /* add MSN to list/hash */ - if (!hashtable_insert(isdn_data->msn_hash, (void *)key, (void *)&value, HASHTABLE_FLAG_FREE_KEY)) { - ftdm_safe_free(key); - ret = FTDM_FAIL; - } -out: - ftdm_mutex_unlock(isdn_data->msn_mutex); - return ret; -} - - -/** - * Check if a DNIS (destination number) is a valid MSN/DDI - * \param[in] isdn_data Span private data - * \param[in] msn Number to check - * \retval FTDM_TRUE \p msn is a valid MSN/DDI or filter list is empty - * \retval FTDM_FALSE \p msn is not a valid MSN/DDI - */ -static int msn_filter_match(ftdm_libpri_data_t *isdn_data, const char *msn) -{ - int ret = FTDM_FALSE; - - if (!isdn_data) - return FTDM_FALSE; - /* No number? return match found */ - if (ftdm_strlen_zero(msn)) - return FTDM_TRUE; - - ftdm_mutex_lock(isdn_data->msn_mutex); - - /* No MSN configured? */ - if (hashtable_count(isdn_data->msn_hash) <= 0) { - ret = FTDM_TRUE; - goto out; - } - /* Search for a matching MSN */ - if (hashtable_search(isdn_data->msn_hash, (void *)msn)) - ret = FTDM_TRUE; -out: - ftdm_mutex_unlock(isdn_data->msn_mutex); - return ret; -} - -/** - * Helper function to iterate over MSNs in the filter hash (handles locking) - * \param[in] isdn_data Span private data - * \param[in] func Callback function that is invoked for each entry - * \param[in] data Private data passed to callback - * \return FTDM_SUCCESS, FTDM_FAIL - */ -static int msn_filter_foreach(ftdm_libpri_data_t *isdn_data, int (* func)(const char *, void *), void *data) -{ - ftdm_hash_iterator_t *iter = NULL; - int ret = FTDM_SUCCESS; - - if (!isdn_data || !func) - return FTDM_FAIL; - - /* iterate over MSNs */ - ftdm_mutex_lock(isdn_data->msn_mutex); - - for (iter = hashtable_first(isdn_data->msn_hash); iter; iter = hashtable_next(iter)) { - const void *msn = NULL; - - hashtable_this(iter, &msn, NULL, NULL); - - if (ftdm_strlen_zero((const char *)msn)) - break; - if ((ret = func(msn, data)) != FTDM_SUCCESS) - break; - } - - ftdm_mutex_unlock(isdn_data->msn_mutex); - return ret; -} - - -/*************************************************************** - * Module API (CLI) interface - ***************************************************************/ - -static const char *ftdm_libpri_usage = - "Usage:\n" - "libpri kill \n" - "libpri reset \n" - "libpri restart \n" -#ifdef HAVE_LIBPRI_MAINT_SERVICE - "libpri maintenance \n" -#endif - "libpri debug [all|none|flag,...flagN]\n" - "libpri msn \n" - "\n" - "Possible debug flags:\n" - "\tq921_raw - Q.921 Raw messages\n" - "\tq921_dump - Q.921 Decoded messages\n" - "\tq921_state - Q.921 State machine changes\n" - "\tq921_all - Enable all Q.921 debug options\n" - "\n" - "\tq931_dump - Q.931 Messages\n" - "\tq931_state - Q.931 State machine changes\n" - "\tq931_anomaly - Q.931 Anomalies\n" - "\tq931_all - Enable all Q.931 debug options\n" - "\n" - "\tapdu - Application protocol data unit\n" - "\taoc - Advice of Charge messages\n" - "\tconfig - Configuration\n" - "\n" - "\tnone - Disable debugging\n" - "\tall - Enable all debug options\n"; - - -/** - * Custom data handle for list iterator functions - */ -struct msn_list_cb_private { - ftdm_stream_handle_t *stream; - unsigned int count; -}; - -/** - * "ftdm libpri msn " API command callback - * function for msn_filter_foreach() - */ -static int msn_list_cb(const char *msn, void *priv) -{ - struct msn_list_cb_private *data = priv; - ftdm_stream_handle_t *stream = data->stream; - - if (!stream || ftdm_strlen_zero(msn)) - return FTDM_FAIL; - - stream->write_function(stream, "\t%s\n", msn); - data->count++; - return FTDM_SUCCESS; -} - - -/** - * \brief API function to kill or debug a libpri span - * \param stream API stream handler - * \param data String containing argurments - * \return Flags - */ -static FIO_API_FUNCTION(ftdm_libpri_api) -{ - char *mycmd = NULL, *argv[10] = { 0 }; - int argc = 0; - - if (data) { - mycmd = ftdm_strdup(data); - argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); - } - - if (argc == 1) { - if (!strcasecmp(argv[0], "help") || !strcasecmp(argv[0], "usage")) { - stream->write_function(stream, ftdm_libpri_usage); - goto done; - } - } else if (argc == 2) { - if (!strcasecmp(argv[0], "kill")) { - int span_id = atoi(argv[1]); - ftdm_span_t *span = NULL; - - if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) { - ftdm_libpri_data_t *isdn_data = span->signal_data; - - if (span->start != ftdm_libpri_start) { - stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n", - __FILE__, ftdm_span_get_name(span)); - goto done; - } - - ftdm_clear_flag(&(isdn_data->spri), LPWRAP_PRI_READY); - stream->write_function(stream, "%s: +OK killed.\n", __FILE__); - goto done; - } else { - stream->write_function(stream, "%s: -ERR span '%s' not found.\n", - __FILE__, argv[0]); - goto done; - } - } - if (!strcasecmp(argv[0], "msn")) { - ftdm_span_t *span = NULL; - struct msn_list_cb_private data; - data.stream = stream; - data.count = 0; - - if (ftdm_span_find_by_name(argv[1], &span) != FTDM_SUCCESS) { - stream->write_function(stream, "%s: -ERR span '%s' not found.\n", - __FILE__, argv[1]); - goto done; - } - if (span->start != ftdm_libpri_start) { - stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n", - __FILE__, ftdm_span_get_name(span)); - goto done; - } - - /* header */ - stream->write_function(stream, "------------------------------------------------------------------------------\n"); - - if (msn_filter_foreach(span->signal_data, msn_list_cb, &data)) { - stream->write_function(stream, "-ERR: Failed to list MSN(s)\n"); - goto done; - } - if (data.count == 0) { - stream->write_function(stream, "\t\t\t -- no entries --\n"); - } - - /* footer */ - stream->write_function(stream, "---------------------------------------------------------------[ %02d MSN(s) ]--\n", - data.count); - stream->write_function(stream, "+OK"); - goto done; - } - } else if (argc >= 2) { - if (!strcasecmp(argv[0], "debug")) { - ftdm_span_t *span = NULL; - - if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) { - ftdm_libpri_data_t *isdn_data = span->signal_data; - uint32_t flags = 0; - - if (span->start != ftdm_libpri_start) { - stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n", - __FILE__, ftdm_span_get_name(span)); - goto done; - } - - if (argc == 2) { - char tmp[100] = { 0 }; - print_debug(pri_get_debug(isdn_data->spri.pri), tmp, sizeof(tmp)); - stream->write_function(stream, "%s: +OK current debug flags: '%s'\n", __FILE__, tmp); - goto done; - } - - if (parse_debug(argv[2], &flags) == -1) { - stream->write_function(stream, "%s: -ERR invalid debug flags given\n", __FILE__); - goto done; - } - - pri_set_debug(isdn_data->spri.pri, flags); - stream->write_function(stream, "%s: +OK debug %s.\n", __FILE__, (flags) ? "enabled" : "disabled"); - goto done; - } else { - stream->write_function(stream, "%s: -ERR span '%s' not found.\n", - __FILE__, argv[0]); - goto done; - } - } - if (!strcasecmp(argv[0], "reset")) { - ftdm_span_t *span = NULL; - if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) { - ftdm_libpri_data_t *isdn_data = span->signal_data; - - if (span->start != ftdm_libpri_start) { - stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n", - __FILE__, ftdm_span_get_name(span)); - goto done; - } - - pri_restart(isdn_data->spri.pri); - stream->write_function(stream, "%s: +OK reset.\n", __FILE__); - goto done; - } else { - stream->write_function(stream, "%s: -ERR span '%s' not found.\n", - __FILE__, argv[0]); - goto done; - } - } - if (!strcasecmp(argv[0], "restart") && argc == 3) { - ftdm_span_t *span = NULL; - if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) { - ftdm_libpri_data_t *isdn_data = span->signal_data; - - if (span->start != ftdm_libpri_start) { - stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n", - __FILE__, ftdm_span_get_name(span)); - goto done; - } - if (!strcasecmp(argv[2], "all")) { - int j; - for(j = 1; j <= span->chan_count; j++) { - pri_reset(isdn_data->spri.pri, j); - ftdm_sleep(50); - } - } else { - pri_reset(isdn_data->spri.pri, atoi(argv[2])); - } - stream->write_function(stream, "%s: +OK restart set.\n", __FILE__); - goto done; - } else { - stream->write_function(stream, "%s: -ERR span '%s' not found.\n", - __FILE__, argv[0]); - goto done; - } - } -#ifdef HAVE_LIBPRI_MAINT_SERVICE - if (!strcasecmp(argv[0], "maintenance") && argc > 3) { - ftdm_span_t *span = NULL; - if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) { - ftdm_libpri_data_t *isdn_data = span->signal_data; - - if (span->start != ftdm_libpri_start) { - stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n", - __FILE__, ftdm_span_get_name(span)); - goto done; - } - if (!isdn_data->service_message_support) { - stream->write_function(stream, "%s: -ERR service message support is disabled\n", __FILE__); - goto done; - } - if (!strcasecmp(argv[2], "all")) { - int j; - for(j = 1; j <= span->chan_count; j++) { - pri_maintenance_service(isdn_data->spri.pri, atoi(argv[1]), j, parse_change_status(argv[3])); - ftdm_sleep(50); - } - } else { - pri_maintenance_service(isdn_data->spri.pri, atoi(argv[1]), atoi(argv[2]), parse_change_status(argv[3])); - } - stream->write_function(stream, "%s: +OK change status set.\n", __FILE__); - goto done; - } else { - stream->write_function(stream, "%s: -ERR span '%s' not found.\n", - __FILE__, argv[0]); - goto done; - } - } -#endif - } else { - /* zero args print usage */ - stream->write_function(stream, ftdm_libpri_usage); - goto done; - } - - stream->write_function(stream, "%s: -ERR invalid command.\n", __FILE__); - -done: - ftdm_safe_free(mycmd); - - return FTDM_SUCCESS; -} - - -/** - * \brief Loads libpri IO module - * \param fio FreeTDM IO interface - * \return Success - */ -static FIO_IO_LOAD_FUNCTION(ftdm_libpri_io_init) -{ - assert(fio != NULL); - - memset(&ftdm_libpri_interface, 0, sizeof(ftdm_libpri_interface)); - ftdm_libpri_interface.name = "libpri"; - ftdm_libpri_interface.api = &ftdm_libpri_api; - - *fio = &ftdm_libpri_interface; - - return FTDM_SUCCESS; -} - -/** - * \brief Loads libpri signaling module - * \param fio FreeTDM IO interface - * \return Success - */ -static FIO_SIG_LOAD_FUNCTION(ftdm_libpri_init) -{ - pri_set_error(s_pri_error); - pri_set_message(s_pri_message); - return FTDM_SUCCESS; -} - -/** - * \brief libpri state map - */ -static ftdm_state_map_t isdn_state_map = { - { - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_ANY}, - {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, - FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_PROGRESS, - FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, - FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, - FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, - FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - }, - - /****************************************/ - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_ANY}, - {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DIALTONE, FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DIALTONE, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, - FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, - FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - }, - } -}; - -/** - * \brief Handler for channel state change - * \param ftdmchan Channel to handle - * \note This function MUST be called with the channel locked - */ -static ftdm_status_t state_advance(ftdm_channel_t *chan) -{ - ftdm_span_t *span = ftdm_channel_get_span(chan); - ftdm_libpri_data_t *isdn_data = span->signal_data; - ftdm_libpri_b_chan_t *chan_priv = chan->call_data; - q931_call *call = chan_priv->call; - ftdm_status_t status; - ftdm_sigmsg_t sig; - - ftdm_log(FTDM_LOG_DEBUG, "-- %d:%d STATE [%s]\n", - ftdm_channel_get_span_id(chan), ftdm_channel_get_id(chan), ftdm_channel_get_state_str(chan)); - - memset(&sig, 0, sizeof(sig)); - sig.chan_id = ftdm_channel_get_id(chan); - sig.span_id = ftdm_channel_get_span_id(chan); - sig.channel = chan; - - ftdm_channel_complete_state(chan); - - switch (ftdm_channel_get_state(chan)) { - case FTDM_CHANNEL_STATE_DOWN: - { - if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_B) { - ftdm_channel_t *chtmp = chan; - - if (call) { - /* pri call destroy is done by libpri itself (on release_ack) */ - chan_priv->call = NULL; - } - - /* Stop T302 */ - lpwrap_stop_timer(&isdn_data->spri, &chan_priv->t302); - - /* Stop T316 and reset counter */ - lpwrap_stop_timer(&isdn_data->spri, &chan_priv->t316); - chan_priv->t316_timeout_cnt = 0; - - /* Unset remote hangup */ - chan_priv->peerhangup = 0; - - if (ftdm_channel_close(&chtmp) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_WARNING, "-- Failed to close channel %d:%d\n", - ftdm_channel_get_span_id(chan), - ftdm_channel_get_id(chan)); - } else { - ftdm_log(FTDM_LOG_DEBUG, "-- Closed channel %d:%d\n", - ftdm_channel_get_span_id(chan), - ftdm_channel_get_id(chan)); - } - } - } - break; - - case FTDM_CHANNEL_STATE_PROGRESS: - { - if (ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) { - sig.event_id = FTDM_SIGEVENT_PROGRESS; - if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) { - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP); - } - } else if (call) { - /* - * Even if we have no media, sending progress without PI is forbidden - * by Q.931 3.1.8, so a protocol error will be issued from libpri - * and from remote equipment. - * So just pretend we have PI. - */ - pri_progress(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 1); - } else { - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART); - } - } - break; - - case FTDM_CHANNEL_STATE_RINGING: - { - if (ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) { - sig.event_id = FTDM_SIGEVENT_RINGING; - if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) { - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP); - } - } else if (call) { -// pri_progress(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 1); - pri_acknowledge(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 0); - } else { - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART); - } - } - break; - - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - { - if (ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) { - sig.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA; - if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) { - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP); - } - } else if (call) { - /* make sure channel is open in this state (outbound handled in on_proceeding()) */ - if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) { - ftdm_channel_open_chan(chan); - } - pri_progress(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 1); - } else { - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART); - } - } - break; - - case FTDM_CHANNEL_STATE_PROCEED: - { - if (ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) { - /* PROCEED from other end, notify user */ - sig.event_id = FTDM_SIGEVENT_PROCEED; - if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) { - ftdm_log(FTDM_LOG_ERROR, "Failed to send PROCEED sigevent on Channel %d:%d\n", - ftdm_channel_get_span_id(chan), - ftdm_channel_get_id(chan)); - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP); - } - } else if (call) { - pri_proceeding(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 0); - } else { - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART); - } - } - break; - - case FTDM_CHANNEL_STATE_COLLECT: /* Overlap receive */ - { - if (!ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) { - if (!call) { - ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "No call handle\n"); - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART); - } - else if (pri_need_more_info(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 0)) { - ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan); - - ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "Failed to send INFORMATION request\n"); - - /* hangup call */ - caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER; - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP); - } - else { - /* Start T302 */ - lpwrap_start_timer(&isdn_data->spri, &chan_priv->t302, - isdn_data->overlap_timeout_ms, &on_timeout_t302); - } - } else { - ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "Overlap receiving on outbound call?\n"); - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART); - } - } - break; - - case FTDM_CHANNEL_STATE_RING: - { - /* - * This needs more auditing for BRI PTMP: - * does pri_acknowledge() steal the call from other devices? (yes, it does) - */ - if (!ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) { - if (call) { - pri_proceeding(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 0); -// pri_acknowledge(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 0); - sig.event_id = FTDM_SIGEVENT_START; - if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) { - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP); - } - } else { - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART); - } - } - } - break; - - case FTDM_CHANNEL_STATE_RESTART: - { - if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_B) { - chan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_UNSPECIFIED; - sig.event_id = FTDM_SIGEVENT_RESTART; - status = ftdm_span_send_signal(span, &sig); - - if (ftdm_span_get_trunk_type(span) == FTDM_TRUNK_BRI_PTMP) { - /* Just put the channel into DOWN state, libpri won't send RESTART on BRI PTMP */ - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_DOWN); - - } else if (!(chan_priv->flags & FTDM_LIBPRI_B_REMOTE_RESTART)) { - /* Locally triggered restart, send RESTART to remote, wait for ACK */ - pri_reset(isdn_data->spri.pri, ftdm_channel_get_id(chan)); - /* Start T316 */ - lpwrap_start_timer(&isdn_data->spri, &chan_priv->t316, isdn_data->t316_timeout_ms, &on_timeout_t316); - } else { - /* Remote restart complete, clear flag (RESTART ACK already sent by libpri) */ - chan_priv->flags &= ~FTDM_LIBPRI_B_REMOTE_RESTART; - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_DOWN); - } - } - } - break; - - case FTDM_CHANNEL_STATE_UP: - { - if (ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) { - sig.event_id = FTDM_SIGEVENT_UP; - if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) { - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP); - } - } else if (call) { - /* make sure channel is open in this state (outbound handled in on_answer()) */ - if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) { - ftdm_channel_open_chan(chan); - } - pri_answer(isdn_data->spri.pri, call, 0, 1); - } else { - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART); - } - } - break; - - case FTDM_CHANNEL_STATE_DIALING: - if (isdn_data) { - ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan); - struct pri_sr *sr; - int caller_ton; - int called_ton; - - if (!(call = pri_new_call(isdn_data->spri.pri))) { - ftdm_log(FTDM_LOG_ERROR, "Failed to create new call on channel %d:%d\n", - ftdm_channel_get_span_id(chan), ftdm_channel_get_id(chan)); - /* TODO: set hangup cause? */ - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART); - return FTDM_SUCCESS; - } - - caller_ton = caller_data->cid_num.type; - switch (caller_ton) { - case FTDM_TON_NATIONAL: - caller_ton = PRI_NATIONAL_ISDN; - break; - case FTDM_TON_INTERNATIONAL: - caller_ton = PRI_INTERNATIONAL_ISDN; - break; - case FTDM_TON_SUBSCRIBER_NUMBER: - caller_ton = PRI_LOCAL_ISDN; - break; - default: - caller_ton = isdn_data->ton; - } - - called_ton = caller_data->dnis.type; - switch (called_ton) { - case FTDM_TON_NATIONAL: - called_ton = PRI_NATIONAL_ISDN; - break; - case FTDM_TON_INTERNATIONAL: - called_ton = PRI_INTERNATIONAL_ISDN; - break; - case FTDM_TON_SUBSCRIBER_NUMBER: - called_ton = PRI_LOCAL_ISDN; - break; - default: - called_ton = isdn_data->ton; - } - - chan_priv->call = call; - - sr = pri_sr_new(); - if (!sr) { - ftdm_log(FTDM_LOG_ERROR, "Failed to create new setup request on channel %d:%d\n", - ftdm_channel_get_span_id(chan), ftdm_channel_get_id(chan)); - /* TODO: handle error properly */ - } - assert(sr); - - pri_sr_set_channel(sr, ftdm_channel_get_id(chan), 1, 0); - pri_sr_set_bearer(sr, PRI_TRANS_CAP_SPEECH, isdn_data->layer1); - - pri_sr_set_called(sr, caller_data->dnis.digits, called_ton, 1); - pri_sr_set_caller(sr, caller_data->cid_num.digits, - ((isdn_data->opts & FTMOD_LIBPRI_OPT_OMIT_DISPLAY_IE) ? NULL : caller_data->cid_name), - caller_ton, - ((caller_data->pres != 1) ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_PROHIB_USER_NUMBER_NOT_SCREENED)); - - if (!(isdn_data->opts & FTMOD_LIBPRI_OPT_OMIT_REDIRECTING_NUMBER_IE)) { - pri_sr_set_redirecting(sr, caller_data->cid_num.digits, caller_ton, - PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, PRI_REDIR_UNCONDITIONAL); - } -#ifdef HAVE_LIBPRI_AOC - if (isdn_data->opts & FTMOD_LIBPRI_OPT_FACILITY_AOC) { - /* request AOC on call */ - pri_sr_set_aoc_charging_request(sr, (PRI_AOC_REQUEST_S | PRI_AOC_REQUEST_E | PRI_AOC_REQUEST_D)); - ftdm_log(FTDM_LOG_DEBUG, "Requesting AOC-S/D/E on call\n"); - } -#endif - if (pri_setup(isdn_data->spri.pri, call, sr)) { - caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER; - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP); - } - - pri_sr_free(sr); - } - break; - - case FTDM_CHANNEL_STATE_HANGUP: - { - if (call) { - ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan); - pri_hangup(isdn_data->spri.pri, call, caller_data->hangup_cause); - - if (chan_priv->peerhangup) { - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); - } - } - } - break; - - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - { -// if (call) { -// pri_destroycall(isdn_data->spri.pri, call); -// chan_priv->call = NULL; -// } - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_DOWN); - } - break; - - case FTDM_CHANNEL_STATE_TERMINATING: - { - sig.event_id = FTDM_SIGEVENT_STOP; - status = ftdm_span_send_signal(span, &sig); - /* user moves us to HANGUP and from there we go to DOWN */ - } - default: - break; - } - return FTDM_SUCCESS; -} - -/** - * \brief Checks current state on a span - * \param span Span to check status on - */ -static __inline__ void check_state(ftdm_span_t *span) -{ - if (ftdm_test_flag(span, FTDM_SPAN_STATE_CHANGE)) { - uint32_t j; - - ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE); - - for (j = 1; j <= ftdm_span_get_chan_count(span); j++) { - ftdm_channel_t *chan = ftdm_span_get_channel(span, j); - ftdm_channel_lock(chan); - ftdm_channel_advance_states(chan); - ftdm_channel_unlock(chan); - } - } -} - - -/** - * \brief Handler for libpri keypad digit event - * \param spri Pri wrapper structure (libpri, span, dchan) - * \param event_type Event type (unused) - * \param pevent Event - * \return 0 - */ -static int on_keypad_digit(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) -{ - ftdm_span_t *span = spri->span; - ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->ring.channel); - - ftdm_unused_arg(event_type); - - if (!chan) { - ftdm_log(FTDM_LOG_ERROR, "-- Keypad event on invalid channel %d:%d\n", - ftdm_span_get_id(span), pevent->ring.channel); - return 0; - } - - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "-- Keypad event received, incoming digits: '%s'\n", - pevent->digit.digits); - - /* Enqueue DTMF digits on channel */ - ftdm_channel_queue_dtmf(chan, pevent->digit.digits); - return 0; -} - - -/** - * \brief Handler for libpri information event (overlap receiving) - * \param spri Pri wrapper structure (libpri, span, dchan) - * \param event_type Event type (unused) - * \param pevent Event - * \return 0 - */ -static int on_information(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) -{ - ftdm_span_t *span = spri->span; - ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->ring.channel); - ftdm_libpri_b_chan_t *chan_priv = NULL; - ftdm_caller_data_t *caller_data = NULL; - ftdm_libpri_data_t *isdn_data = span->signal_data; - - ftdm_unused_arg(event_type); - - if (!chan) { - ftdm_log(FTDM_LOG_CRIT, "-- Info on channel %d:%d but it's not in use?\n", ftdm_span_get_id(span), pevent->ring.channel); - return 0; - } - - caller_data = ftdm_channel_get_caller_data(chan); - chan_priv = chan->call_data; - - switch (ftdm_channel_get_state(chan)) { - case FTDM_CHANNEL_STATE_COLLECT: /* TE-mode overlap receiving */ - case FTDM_CHANNEL_STATE_DIALTONE: /* NT-mode overlap receiving */ - - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "-- Incoming INFORMATION indication, received digits: '%s', number complete: %c, collected digits: '%s'\n", - pevent->ring.callednum, - pevent->ring.complete ? 'Y' : 'N', - caller_data->dnis.digits); - - /* Stop T302 */ - lpwrap_stop_timer(spri, &chan_priv->t302); - - /* append digits to dnis */ - if (!ftdm_strlen_zero(pevent->ring.callednum)) { - int digits = strlen(pevent->ring.callednum); - int offset = strlen(caller_data->dnis.digits); - int len = 0; - - if (strchr(pevent->ring.callednum, '#')) { - pevent->ring.complete = 1; - digits--; - } - - len = ftdm_min(sizeof(caller_data->dnis.digits) - 1 - offset, digits); /* max. length without terminator */ - if (len < digits) { - ftdm_log_chan(chan, FTDM_LOG_WARNING, "Digit string of length %d exceeds available space %d of DNIS, truncating!\n", - digits, len); - } - if (len) { - ftdm_copy_string(&caller_data->dnis.digits[offset], (char *)pevent->ring.callednum, len + 1); /* max. length with terminator */ - caller_data->dnis.digits[offset + len] = '\0'; - } - } - if (pevent->ring.complete) { - ftdm_log_chan_msg(chan, FTDM_LOG_DEBUG, "Number complete indication received, moving channel to RING state\n"); - /* notify switch */ - ftdm_set_state(chan, FTDM_CHANNEL_STATE_RING); - } else { - /* Restart T302 */ - lpwrap_start_timer(spri, &chan_priv->t302, isdn_data->overlap_timeout_ms, &on_timeout_t302); - } - break; - default: - ftdm_log_chan(chan, FTDM_LOG_ERROR, "-- INFORMATION indication in invalid state '%s'\n", - ftdm_channel_get_state_str(chan)); - } - return 0; -} - -/** - * \brief Handler for libpri hangup event - * \param spri Pri wrapper structure (libpri, span, dchan) - * \param event_type Event type (unused) - * \param pevent Event - * \return 0 - */ -static int on_hangup(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) -{ - ftdm_span_t *span = spri->span; - ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->hangup.channel); - ftdm_libpri_b_chan_t *chan_priv = chan->call_data; - - if (!chan) { - ftdm_log(FTDM_LOG_CRIT, "-- Hangup on channel %d:%d but it's not in use?\n", ftdm_span_get_id(spri->span), pevent->hangup.channel); - return 0; - } - - ftdm_channel_lock(chan); - - switch (event_type) { - case LPWRAP_PRI_EVENT_HANGUP_REQ: /* DISCONNECT */ - if (ftdm_channel_get_state(chan) >= FTDM_CHANNEL_STATE_TERMINATING) { - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Ignoring remote hangup in state %s\n", - ftdm_channel_get_state_str(chan)); - goto done; - } - ftdm_log(FTDM_LOG_DEBUG, "-- Hangup REQ on channel %d:%d\n", - ftdm_span_get_id(spri->span), pevent->hangup.channel); - - chan->caller_data.hangup_cause = pevent->hangup.cause; - - switch (ftdm_channel_get_state(chan)) { - case FTDM_CHANNEL_STATE_DIALTONE: - case FTDM_CHANNEL_STATE_COLLECT: - ftdm_set_state(chan, FTDM_CHANNEL_STATE_HANGUP); - break; - default: - ftdm_set_state(chan, FTDM_CHANNEL_STATE_TERMINATING); - } - break; - - case LPWRAP_PRI_EVENT_HANGUP_ACK: /* RELEASE_COMPLETE */ - ftdm_log(FTDM_LOG_DEBUG, "-- Hangup ACK on channel %d:%d\n", - ftdm_span_get_id(spri->span), pevent->hangup.channel); - - switch (ftdm_channel_get_state(chan)) { - case FTDM_CHANNEL_STATE_RESTART: - /* ACK caused by DL FAILURE in DISC REQ */ - ftdm_set_state(chan, FTDM_CHANNEL_STATE_DOWN); - break; - default: - ftdm_set_state(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); - break; - } - break; - - case LPWRAP_PRI_EVENT_HANGUP: /* "RELEASE/RELEASE_COMPLETE/other" */ - ftdm_log(FTDM_LOG_DEBUG, "-- Hangup on channel %d:%d\n", - ftdm_span_get_id(spri->span), pevent->hangup.channel); - - chan_priv->peerhangup = 1; - - switch (ftdm_channel_get_state(chan)) { - case FTDM_CHANNEL_STATE_DIALING: - case FTDM_CHANNEL_STATE_RINGING: - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - case FTDM_CHANNEL_STATE_PROCEED: - case FTDM_CHANNEL_STATE_UP: - chan->caller_data.hangup_cause = pevent->hangup.cause; - ftdm_set_state(chan, FTDM_CHANNEL_STATE_TERMINATING); - break; - case FTDM_CHANNEL_STATE_HANGUP: - /* this will send "RELEASE_COMPLETE", eventually */ - pri_hangup(spri->pri, pevent->hangup.call, chan->caller_data.hangup_cause); - chan->caller_data.hangup_cause = pevent->hangup.cause; - ftdm_set_state(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); - break; - case FTDM_CHANNEL_STATE_RESTART: - /* - * We got an hungup doing a restart, normally beacause link has been lost during - * a call and the T309 timer has expired. So destroy it :) (DL_RELEASE_IND) - */ - pri_destroycall(spri->pri, pevent->hangup.call); - ftdm_set_state(chan, FTDM_CHANNEL_STATE_DOWN); - break; -// case FTDM_CHANNEL_STATE_TERMINATING: -// ftdm_set_state(chan, FTDM_CHANNEL_STATE_HANGUP); -// break; -// case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: -// ftdm_set_state(chan, FTDM_CHANNEL_STATE_DOWN); -// break; - } - break; - default: - break; - } - -done: - ftdm_channel_unlock(chan); - return 0; -} - -/** - * \brief Handler for libpri answer event - * \param spri Pri wrapper structure (libpri, span, dchan) - * \param event_type Event type (unused) - * \param pevent Event - * \return 0 - */ -static int on_answer(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) -{ - ftdm_span_t *span = spri->span; - ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->answer.channel); - - ftdm_unused_arg(event_type); - - if (chan) { - if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) { - ftdm_log(FTDM_LOG_DEBUG, "-- Call answered, opening B-Channel %d:%d\n", - ftdm_channel_get_span_id(chan), - ftdm_channel_get_id(chan)); - - if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) { - ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan); - - ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n", - ftdm_channel_get_span_id(chan), - ftdm_channel_get_id(chan)); - - caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER; - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING); - goto out; - } - } - ftdm_log(FTDM_LOG_DEBUG, "-- Answer on channel %d:%d\n", ftdm_span_get_id(span), pevent->answer.channel); - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_UP); - } else { - ftdm_log(FTDM_LOG_DEBUG, "-- Answer on channel %d:%d but it's not in the span?\n", - ftdm_span_get_id(span), pevent->answer.channel); - } -out: - return 0; -} - -/** - * \brief Handler for libpri proceeding event - * \param spri Pri wrapper structure (libpri, span, dchan) - * \param event_type Event type (unused) - * \param pevent Event - * \return 0 - */ -static int on_proceeding(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) -{ - ftdm_span_t *span = spri->span; - ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->proceeding.channel); - - ftdm_unused_arg(event_type); - - if (chan) { - /* Open channel if inband information is available */ - if (pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE || pevent->proceeding.progressmask & PRI_PROG_CALL_NOT_E2E_ISDN) { - ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, B-Channel %d:%d\n", - ftdm_channel_get_span_id(chan), - ftdm_channel_get_id(chan)); - - if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN) && (ftdm_channel_open_chan(chan) != FTDM_SUCCESS)) { - ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan); - - ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n", - ftdm_channel_get_span_id(chan), - ftdm_channel_get_id(chan)); - - caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER; - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING); - goto out; - } - } - ftdm_log(FTDM_LOG_DEBUG, "-- Proceeding on channel %d:%d\n", ftdm_span_get_id(span), pevent->proceeding.channel); - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROCEED); - } else { - ftdm_log(FTDM_LOG_DEBUG, "-- Proceeding on channel %d:%d but it's not in the span?\n", - ftdm_span_get_id(span), pevent->proceeding.channel); - } -out: - return 0; -} - -/** - * \brief Handler for libpri progress event - * \param spri Pri wrapper structure (libpri, span, dchan) - * \param event_type Event type (unused) - * \param pevent Event - * \return 0 - * \note also uses pri_event->proceeding - */ -static int on_progress(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) -{ - ftdm_span_t *span = spri->span; - ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->proceeding.channel); - - ftdm_unused_arg(event_type); - - if (chan) { - /* Open channel if inband information is available */ - if (pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE || pevent->proceeding.progressmask & PRI_PROG_CALL_NOT_E2E_ISDN) { - ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, B-Channel %d:%d\n", - ftdm_channel_get_span_id(chan), - ftdm_channel_get_id(chan)); - - if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN) && (ftdm_channel_open_chan(chan) != FTDM_SUCCESS)) { - ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan); - - ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n", - ftdm_channel_get_span_id(chan), - ftdm_channel_get_id(chan)); - - caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER; - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING); - goto out; - } - ftdm_log(FTDM_LOG_DEBUG, "-- Progress on channel %d:%d with media\n", ftdm_span_get_id(span), pevent->proceeding.channel); - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); - } else { - ftdm_log(FTDM_LOG_DEBUG, "-- Progress on channel %d:%d\n", ftdm_span_get_id(span), pevent->proceeding.channel); - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS); - } - } else { - ftdm_log(FTDM_LOG_DEBUG, "-- Progress on channel %d:%d but it's not in the span?\n", - ftdm_span_get_id(span), pevent->proceeding.channel); - } -out: - return 0; -} - -/** - * \brief Handler for libpri ringing event - * \param spri Pri wrapper structure (libpri, span, dchan) - * \param event_type Event type (unused) - * \param pevent Event - * \return 0 - */ -static int on_ringing(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) -{ - ftdm_span_t *span = spri->span; - ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->ringing.channel); - - ftdm_unused_arg(event_type); - - if (chan) { - /* we may get on_ringing even when we're already in FTDM_CHANNEL_STATE_PROGRESS_MEDIA */ -// if (ftdm_channel_get_state(chan) == FTDM_CHANNEL_STATE_PROGRESS_MEDIA) { -// /* dont try to move to STATE_PROGRESS to avoid annoying veto warning */ -// return 0; -// } - - /* Open channel if inband information is available */ - if ((pevent->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE)) { - ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, B-Channel %d:%d\n", - ftdm_channel_get_span_id(chan), - ftdm_channel_get_id(chan)); - - if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN) && (ftdm_channel_open_chan(chan) != FTDM_SUCCESS)) { - ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan); - - ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n", - ftdm_channel_get_span_id(chan), - ftdm_channel_get_id(chan)); - - caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER; - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING); - goto out; - } - ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d with media\n", ftdm_span_get_id(span), pevent->proceeding.channel); - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); - } else { -// ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS); - ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d\n", ftdm_span_get_id(span), pevent->proceeding.channel); - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RINGING); - } - } else { - ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d but it's not in the span?\n", - ftdm_span_get_id(span), pevent->ringing.channel); - } -out: - return 0; -} - - -/** - * Look up FreeTDM channel by call reference value - * \param[in] span Span object - * \param[in] crv CRV to search for - * \return Channel on success, NULL otherwise - */ -static ftdm_channel_t *find_channel_by_cref(ftdm_span_t *span, const int cref) -{ - ftdm_iterator_t *c_iter, *c_cur; - ftdm_channel_t *chan = NULL; - - if (!span || cref <= 0) - return NULL; - - ftdm_mutex_lock(span->mutex); - - c_iter = ftdm_span_get_chan_iterator(span, NULL); - - /* Iterate over all channels on this span */ - for (c_cur = c_iter; c_cur; c_cur = ftdm_iterator_next(c_cur)) { - ftdm_channel_t *cur = ftdm_iterator_current(c_cur); - ftdm_caller_data_t *caller_data = NULL; - - if (ftdm_channel_get_type(cur) != FTDM_CHAN_TYPE_B) - continue; - - caller_data = ftdm_channel_get_caller_data(cur); - - if (caller_data->call_reference == cref) { - chan = cur; - break; - } - } - - ftdm_iterator_free(c_iter); - ftdm_mutex_unlock(span->mutex); - return chan; -} - - -/** - * Hunt for free channel (NT-mode only) - * \param[in] span Span to hunt on - * \param[in] hint Channel ID hint (preferred by remote end) - * \param[in] excl Is the hint exclusive (or preferred)? - * \param[out] chan Selected channel - * \retval FTDM_SUCCESS A free channel has been found - * \retval FTDM_FAIL No free channels could be found on the span - * \retval FTDM_EBUSY The channel indicated in the exclusive hint is already in use - */ -static ftdm_status_t hunt_channel(ftdm_span_t *span, const int hint, const ftdm_bool_t excl, ftdm_channel_t **chan) -{ - ftdm_iterator_t *c_iter, *c_cur; - ftdm_channel_t *tmp = NULL; - int ret = FTDM_FAIL; - - /* lock span */ - ftdm_mutex_lock(span->mutex); - - /* Check hint */ - if (hint > 0) { - tmp = ftdm_span_get_channel(span, hint); - if (!tmp) { - ftdm_log(FTDM_LOG_NOTICE, "Invalid channel hint '%d' given (out of bounds)\n", hint); - } - else if (!ftdm_test_flag(tmp, FTDM_CHANNEL_INUSE) && ftdm_channel_get_type(tmp) == FTDM_CHAN_TYPE_B) { - ftdm_log(FTDM_LOG_DEBUG, "Using channel '%d' from hint\n", ftdm_channel_get_id(tmp)); - ftdm_channel_use(tmp); - ret = FTDM_SUCCESS; - *chan = tmp; - goto out; - } - else if (excl) { - ftdm_log(FTDM_LOG_NOTICE, "Channel '%d' in exclusive hint is not available\n", - ftdm_channel_get_id(tmp)); - ret = FTDM_EBUSY; - goto out; - } - } - - c_iter = ftdm_span_get_chan_iterator(span, NULL); - - /* Iterate over all channels on this span */ - for (c_cur = c_iter; c_cur; c_cur = ftdm_iterator_next(c_cur)) { - tmp = ftdm_iterator_current(c_cur); - - if (ftdm_channel_get_type(tmp) != FTDM_CHAN_TYPE_B) - continue; - - if (!ftdm_test_flag(tmp, FTDM_CHANNEL_INUSE)) { - ftdm_channel_use(tmp); - ret = FTDM_SUCCESS; - *chan = tmp; - break; - } - } - - ftdm_iterator_free(c_iter); -out: - ftdm_mutex_unlock(span->mutex); - return ret; -} - - -/** - * \brief Handler for libpri ring event - * \param spri Pri wrapper structure (libpri, span, dchan) - * \param event_type Event type (unused) - * \param pevent Event - * \return 0 on success - */ -static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) -{ - ftdm_span_t *span = spri->span; - ftdm_libpri_data_t *isdn_data = span->signal_data; - ftdm_libpri_b_chan_t *chan_priv = NULL; - ftdm_channel_t *chan = NULL; - ftdm_caller_data_t *caller_data = NULL; - int ret = 0; - - ftdm_unused_arg(event_type); - - /* - * Check if call has an associated channel (duplicate ring event) - */ - if ((chan = find_channel_by_cref(span, pevent->ring.cref))) { - ftdm_log_chan_msg(chan, FTDM_LOG_NOTICE, "-- Duplicate ring received (ignored)\n"); - return ret; - } - - if (isdn_data->mode == PRI_NETWORK) { - /* - * Always hunt for a free channel in NT-mode, - * but use the pre-selected one as hint - */ - switch (hunt_channel(span, pevent->ring.channel, !pevent->ring.flexible, &chan)) { - case FTDM_SUCCESS: /* OK channel found */ - break; - case FTDM_EBUSY: /* Exclusive channel hint is not available */ - ftdm_log(FTDM_LOG_ERROR, "-- New call without channel on span '%s' [NOTE: Initial SETUP w/o channel selection is not supported by FreeTDM]\n", - ftdm_span_get_name(span)); - pri_hangup(spri->pri, pevent->ring.call, PRI_CAUSE_CHANNEL_UNACCEPTABLE); - return ret; - default: - ftdm_log(FTDM_LOG_ERROR, "-- New call without channel on span '%s' [NOTE: Initial SETUP w/o channel selection is not supported by FreeTDM]\n", - ftdm_span_get_name(span)); - pri_hangup(spri->pri, pevent->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); - return ret; - } - - ftdm_channel_lock(chan); - - } else if (pevent->ring.channel == -1) { - /* - * TE-mode incoming call without channel selection (not supported) - */ - ftdm_log(FTDM_LOG_ERROR, "-- New call without channel on span '%s' [NOTE: Initial SETUP w/o channel selection is not supported by FreeTDM]\n", - ftdm_span_get_name(span)); - pri_destroycall(spri->pri, pevent->ring.call); - return ret; - } else { - /* - * TE-mode, check MSN filter, ignore calls that aren't for this PTMP terminal - */ - if (!msn_filter_match(isdn_data, pevent->ring.callednum)) { - ftdm_log(FTDM_LOG_INFO, "-- MSN filter not matching incoming DNIS '%s', ignoring call\n", - pevent->ring.callednum); - pri_destroycall(spri->pri, pevent->ring.call); - return ret; - } - - /* - * TE-mode channel selection, use whatever the NT tells us to - */ - chan = ftdm_span_get_channel(span, pevent->ring.channel); - if (!chan) { - ftdm_log(FTDM_LOG_ERROR, "-- Unable to get channel %d:%d\n", - ftdm_span_get_id(span), pevent->ring.channel); - pri_hangup(spri->pri, pevent->ring.call, PRI_CAUSE_DESTINATION_OUT_OF_ORDER); - return ret; - } - - ftdm_channel_lock(chan); - - if (ftdm_channel_get_state(chan) != FTDM_CHANNEL_STATE_DOWN || ftdm_test_flag(chan, FTDM_CHANNEL_INUSE)) { - ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "-- Selected channel is already in use\n"); - pri_hangup(spri->pri, pevent->ring.call, PRI_CAUSE_DESTINATION_OUT_OF_ORDER); - goto done; - } - - /* Reserve channel */ - if (ftdm_channel_use(chan) != FTDM_SUCCESS) { - ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "-- Error reserving channel\n"); - pri_hangup(spri->pri, pevent->ring.call, PRI_CAUSE_DESTINATION_OUT_OF_ORDER); - goto done; - } - } - - /* Get per-channel private data */ - chan_priv = chan->call_data; - - if (chan_priv->call) { - /* we could drop the incoming call, but most likely the pointer is just a ghost of the past, - * this check is just to detect potentially unreleased pointers */ - ftdm_log_chan(chan, FTDM_LOG_WARNING, "Channel already has call %p!\n", chan_priv->call); - chan_priv->call = NULL; - } - - caller_data = ftdm_channel_get_caller_data(chan); - - memset(caller_data, 0, sizeof(*caller_data)); - - /* Save CRV, so we can do proper duplicate RING detection */ - caller_data->call_reference = pevent->ring.cref; - - ftdm_set_string(caller_data->cid_num.digits, (char *)pevent->ring.callingnum); - ftdm_set_string(caller_data->ani.digits, (char *)pevent->ring.callingani); - ftdm_set_string(caller_data->dnis.digits, (char *)pevent->ring.callednum); - ftdm_set_string(caller_data->rdnis.digits, (char *)pevent->ring.redirectingnum); - - if (pevent->ring.callingpres == PRES_ALLOWED_USER_NUMBER_NOT_SCREENED) { - caller_data->pres = FTDM_PRES_ALLOWED; - caller_data->screen = FTDM_SCREENING_NOT_SCREENED; - } else if (pevent->ring.callingpres == PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN) { - caller_data->pres = FTDM_PRES_ALLOWED; - caller_data->screen = FTDM_SCREENING_VERIFIED_PASSED; - } else if (pevent->ring.callingpres == PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN) { - caller_data->pres = FTDM_PRES_ALLOWED; - caller_data->screen = FTDM_SCREENING_VERIFIED_FAILED; - } else if (pevent->ring.callingpres == PRES_ALLOWED_NETWORK_NUMBER) { - caller_data->pres = FTDM_PRES_ALLOWED; - caller_data->screen = FTDM_SCREENING_NETWORK_PROVIDED; - } else if (pevent->ring.callingpres == PRES_PROHIB_USER_NUMBER_NOT_SCREENED) { - caller_data->pres = FTDM_PRES_RESTRICTED; - caller_data->screen = FTDM_SCREENING_NOT_SCREENED; - } else if (pevent->ring.callingpres == PRES_PROHIB_USER_NUMBER_PASSED_SCREEN) { - caller_data->pres = FTDM_PRES_RESTRICTED; - caller_data->screen = FTDM_SCREENING_VERIFIED_PASSED; - } else if (pevent->ring.callingpres == PRES_PROHIB_USER_NUMBER_FAILED_SCREEN) { - caller_data->pres = FTDM_PRES_RESTRICTED; - caller_data->screen = FTDM_SCREENING_VERIFIED_FAILED; - } else if (pevent->ring.callingpres == PRES_PROHIB_NETWORK_NUMBER) { - caller_data->pres = FTDM_PRES_RESTRICTED; - caller_data->screen = FTDM_SCREENING_NETWORK_PROVIDED; - } else if (pevent->ring.callingpres == PRES_NUMBER_NOT_AVAILABLE) { - caller_data->pres = FTDM_PRES_NOT_AVAILABLE; - caller_data->screen = FTDM_SCREENING_NETWORK_PROVIDED; - } else { - caller_data->pres = FTDM_PRES_INVALID; - caller_data->screen = FTDM_SCREENING_INVALID; - } - - if (pevent->ring.callingplanani != -1) { - caller_data->ani.type = pevent->ring.callingplanani >> 4; - caller_data->ani.plan = pevent->ring.callingplanani & 0x0F; - } else { - /* the remote party did not sent a valid (according to libpri) ANI ton, - * so let's use the callingplan ton/type and hope is correct. - */ - caller_data->ani.type = pevent->ring.callingplan >> 4; - caller_data->ani.plan = pevent->ring.callingplan & 0x0F; - } - - caller_data->cid_num.type = pevent->ring.callingplan >> 4; - caller_data->cid_num.plan = pevent->ring.callingplan & 0x0F; - - caller_data->dnis.type = pevent->ring.calledplan >> 4; - caller_data->dnis.plan = pevent->ring.calledplan & 0x0F; - - if (!ftdm_strlen_zero((char *)pevent->ring.callingname)) { - ftdm_set_string(caller_data->cid_name, (char *)pevent->ring.callingname); - } else { - ftdm_set_string(caller_data->cid_name, (char *)pevent->ring.callingnum); - } - - if (pevent->ring.ani2 >= 0) { - snprintf(caller_data->aniII, 5, "%.2d", pevent->ring.ani2); - } - - // scary to trust this pointer, you'd think they would give you a copy of the call data so you own it...... - /* hurr, this is valid as along as nobody releases the call */ - chan_priv->call = pevent->ring.call; - - /* Open Channel if inband information is available */ - if ((pevent->ring.progressmask & PRI_PROG_INBAND_AVAILABLE)) { - /* Open channel if inband information is available */ - ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, opening B-Channel %d:%d\n", - ftdm_channel_get_span_id(chan), - ftdm_channel_get_id(chan)); - - if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN) && ftdm_channel_open_chan(chan) != FTDM_SUCCESS) { -// ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan); - - ftdm_log(FTDM_LOG_WARNING, "-- Error opening channel %d:%d (ignored)\n", - ftdm_channel_get_span_id(chan), - ftdm_channel_get_id(chan)); - -// caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER; -// ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING); -// goto done; - } - } - - ftdm_log(FTDM_LOG_NOTICE, "-- Ring on channel %d:%d (from %s to %s)\n", ftdm_span_get_id(span), pevent->ring.channel, - pevent->ring.callingnum, pevent->ring.callednum); - - /* Only go to RING state if we have the complete called number (indicated via pevent->complete flag) */ - if (!pevent->ring.complete && (isdn_data->overlap & FTMOD_LIBPRI_OVERLAP_RECEIVE)) { - ftdm_log(FTDM_LOG_DEBUG, "RING event without complete indicator, waiting for more digits\n"); - ftdm_set_state(chan, FTDM_CHANNEL_STATE_COLLECT); - } else { - ftdm_log(FTDM_LOG_DEBUG, "RING event with complete indicator (or overlap receive disabled)\n"); - ftdm_set_state(chan, FTDM_CHANNEL_STATE_RING); - } -done: - ftdm_channel_unlock(chan); - return ret; -} - - -/** - * Timeout handler for T302 (overlap receiving) - */ -static int on_timeout_t302(struct lpwrap_pri *spri, struct lpwrap_timer *timer) -{ - ftdm_libpri_b_chan_t *chan_priv = ftdm_container_of(timer, ftdm_libpri_b_chan_t, t302); - ftdm_channel_t *chan = chan_priv->channel; - - ftdm_unused_arg(spri); - - ftdm_log_chan_msg(chan, FTDM_LOG_INFO, "-- T302 timed out, going to state RING\n"); - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RING); - return 0; -} - -/** - * Timeout handler for T316 (RESTART ACK timer) - */ -static int on_timeout_t316(struct lpwrap_pri *spri, struct lpwrap_timer *timer) -{ - ftdm_libpri_b_chan_t *chan_priv = ftdm_container_of(timer, ftdm_libpri_b_chan_t, t316); - ftdm_libpri_data_t *isdn_data = ftdm_container_of(spri, ftdm_libpri_data_t, spri); - ftdm_channel_t *chan = chan_priv->channel; - - if (++chan_priv->t316_timeout_cnt > isdn_data->t316_max_attempts) { - ftdm_log_chan(chan, FTDM_LOG_ERROR, "-- T316 timed out, channel reached restart attempt limit '%d' and is suspended\n", - isdn_data->t316_max_attempts); - - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_SUSPENDED); - } else { - ftdm_log_chan_msg(chan, FTDM_LOG_WARNING, "-- T316 timed out, resending RESTART request\n"); - pri_reset(spri->pri, ftdm_channel_get_id(chan)); - - /* Restart T316 */ - lpwrap_start_timer(spri, timer, isdn_data->t316_timeout_ms, &on_timeout_t316); - } - return 0; -} - - -/** - * Timeout handler for T3xx (NT-mode idle restart) - */ -static int on_timeout_t3xx(struct lpwrap_pri *spri, struct lpwrap_timer *timer) -{ - ftdm_span_t *span = spri->span; - ftdm_libpri_data_t *isdn_data = span->signal_data; - ftdm_iterator_t *c_iter, *c_cur; - - ftdm_log_chan_msg(isdn_data->dchan, FTDM_LOG_INFO, "-- T3xx timed out, restarting idle b-channels\n"); - ftdm_mutex_lock(span->mutex); - - c_iter = ftdm_span_get_chan_iterator(span, NULL); - - /* Iterate b-channels */ - for (c_cur = c_iter; c_cur; c_cur = ftdm_iterator_next(c_cur)) { - ftdm_channel_t *cur = ftdm_iterator_current(c_cur); - /* Skip non-b-channels */ - if (ftdm_channel_get_type(cur) != FTDM_CHAN_TYPE_B) - continue; - /* Restart idle b-channels */ - if (ftdm_channel_get_state(cur) == FTDM_CHANNEL_STATE_DOWN && !ftdm_test_flag(cur, FTDM_CHANNEL_INUSE)) { - ftdm_set_state_locked(cur, FTDM_CHANNEL_STATE_RESTART); - } - } - ftdm_iterator_free(c_iter); - ftdm_mutex_unlock(span->mutex); - - /* Start timer again */ - lpwrap_start_timer(spri, timer, isdn_data->idle_restart_timeout_ms, &on_timeout_t3xx); - return 0; -} - - -/** - * \brief Processes freetdm event - * \param span Span on which the event was fired - * \param event Event to be treated - * \return Success or failure - */ -static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *event) -{ - ftdm_alarm_flag_t alarmbits; - - ftdm_unused_arg(span); - - ftdm_log(FTDM_LOG_DEBUG, "EVENT [%s][%d][%d:%d] STATE [%s]\n", - ftdm_oob_event2str(event->enum_id), - event->enum_id, - ftdm_channel_get_span_id(event->channel), - ftdm_channel_get_id(event->channel), - ftdm_channel_get_state_str(event->channel)); - - switch (event->enum_id) { - case FTDM_OOB_ALARM_TRAP: - { - if (ftdm_channel_get_state(event->channel) != FTDM_CHANNEL_STATE_DOWN) { - if (ftdm_channel_get_type(event->channel) == FTDM_CHAN_TYPE_B) { - ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_RESTART); - } - } - - ftdm_set_flag(event->channel, FTDM_CHANNEL_SUSPENDED); - ftdm_channel_get_alarms(event->channel, &alarmbits); - ftdm_log_chan_msg(event->channel, FTDM_LOG_WARNING, "channel has alarms!\n"); - } - break; - case FTDM_OOB_ALARM_CLEAR: - { - ftdm_clear_flag(event->channel, FTDM_CHANNEL_SUSPENDED); - ftdm_channel_get_alarms(event->channel, &alarmbits); - ftdm_log_chan_msg(event->channel, FTDM_LOG_WARNING, "channel alarms cleared!\n"); - } - break; - } - return FTDM_SUCCESS; -} - -/** - * \brief Checks for events on a span - * \param span Span to check for events - */ -static __inline__ void check_events(ftdm_span_t *span) -{ - ftdm_status_t status; - - status = ftdm_span_poll_event(span, 5, NULL); - - switch (status) { - case FTDM_SUCCESS: - { - ftdm_event_t *event; - - while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) { - if (event->enum_id == FTDM_OOB_NOOP) { - continue; - } - if (process_event(span, event) != FTDM_SUCCESS) { - break; - } - } - } - break; - - case FTDM_FAIL: - ftdm_log(FTDM_LOG_DEBUG, "Event Failure! %d\n", ftdm_running()); - ftdm_sleep(2000); - break; - - default: - break; - } -} - -/** - * \brief Checks flags on a pri span - * \param spri Pri wrapper structure (libpri, span, dchan) - * \return 0 on success, -1 on error - */ -static int check_flags(lpwrap_pri_t *spri) -{ - ftdm_span_t *span = spri->span; - check_state(span); - check_events(span); - return 0; -} - -/** - * \brief Handler for libpri restart event - * \param spri Pri wrapper structure (libpri, span, dchan) - * \param event_type Event type (unused) - * \param pevent Event - * \return 0 - */ -static int on_restart(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) -{ - ftdm_channel_t *chan = NULL; - ftdm_span_t *span = spri->span; - int i; - - ftdm_unused_arg(event_type); - - if (pevent->restart.channel < 1) { - ftdm_log_chan_msg(spri->dchan, FTDM_LOG_DEBUG, "-- Restarting interface\n"); - - for (i = 1; i <= ftdm_span_get_chan_count(span); i++) { - chan = ftdm_span_get_channel(span, i); - if (!chan) - continue; - if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_B) { - ftdm_libpri_b_chan_t *chan_priv = chan->call_data; - chan_priv->flags |= FTDM_LIBPRI_B_REMOTE_RESTART; /* Remote triggered RESTART, set flag */ - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART); - } - } - } - else if ((chan = ftdm_span_get_channel(span, pevent->restart.channel))) { - if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_B) { - ftdm_libpri_b_chan_t *chan_priv = chan->call_data; - - ftdm_log_chan_msg(chan, FTDM_LOG_DEBUG, "-- Restarting single channel\n"); - chan_priv->flags |= FTDM_LIBPRI_B_REMOTE_RESTART; - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART); - } else { - ftdm_log_chan_msg(chan, FTDM_LOG_NOTICE, "Ignoring RESTART on D-Channel\n"); - } - } - else { - ftdm_log(FTDM_LOG_ERROR, "Invalid restart indicator / channel id '%d' received\n", - pevent->restart.channel); - } - - _ftdm_channel_set_state_force(spri->dchan, FTDM_CHANNEL_STATE_UP); - return 0; -} - -/** - * \brief Handler for libpri restart acknowledge event - * \param spri Pri wrapper structure (libpri, span, dchan) - * \param event_type Event type (unused) - * \param pevent Event - * \return 0 - */ -static int on_restart_ack(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) -{ - ftdm_channel_t *chan = NULL; - ftdm_span_t *span = spri->span; - int i; - - ftdm_unused_arg(event_type); - - if (pevent->restartack.channel < 1) { - ftdm_log_chan_msg(spri->dchan, FTDM_LOG_DEBUG, "-- Restart of interface completed\n"); - - for (i = 1; i <= ftdm_span_get_chan_count(span); i++) { - chan = ftdm_span_get_channel(span, i); - if (!chan) - continue; - if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_B) { - ftdm_libpri_b_chan_t *chan_priv = chan->call_data; - if (!(chan_priv->flags & FTDM_LIBPRI_B_REMOTE_RESTART)) { - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_DOWN); - } - } - } - } - else if ((chan = ftdm_span_get_channel(span, pevent->restart.channel))) { - if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_B) { - ftdm_log_chan_msg(chan, FTDM_LOG_DEBUG, "-- Restart of channel completed\n"); - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_DOWN); - } else { - ftdm_log_chan_msg(chan, FTDM_LOG_NOTICE, "Ignoring RESTART ACK on D-Channel\n"); - } - } - else { - ftdm_log(FTDM_LOG_ERROR, "Invalid restart indicator / channel id '%d' received\n", - pevent->restartack.channel); - } - - _ftdm_channel_set_state_force(spri->dchan, FTDM_CHANNEL_STATE_UP); - return 0; -} - - - - -/* - * FACILITY Advice-On-Charge handler - */ -#if defined(HAVE_LIBPRI_AOC) && defined(PRI_EVENT_FACILITY) -static const char *aoc_billing_id(const int id) -{ - switch (id) { - case PRI_AOC_E_BILLING_ID_NOT_AVAILABLE: - return "not available"; - case PRI_AOC_E_BILLING_ID_NORMAL: - return "normal"; - case PRI_AOC_E_BILLING_ID_REVERSE: - return "reverse"; - case PRI_AOC_E_BILLING_ID_CREDIT_CARD: - return "credit card"; - case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_UNCONDITIONAL: - return "call forwarding unconditional"; - case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_BUSY: - return "call forwarding busy"; - case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_NO_REPLY: - return "call forwarding no reply"; - case PRI_AOC_E_BILLING_ID_CALL_DEFLECTION: - return "call deflection"; - case PRI_AOC_E_BILLING_ID_CALL_TRANSFER: - return "call transfer"; - default: - return "unknown\n"; - } -} - -static float aoc_money_amount(const struct pri_aoc_amount *amount) -{ - switch (amount->multiplier) { - case PRI_AOC_MULTIPLIER_THOUSANDTH: - return amount->cost * 0.001f; - case PRI_AOC_MULTIPLIER_HUNDREDTH: - return amount->cost * 0.01f; - case PRI_AOC_MULTIPLIER_TENTH: - return amount->cost * 0.1f; - case PRI_AOC_MULTIPLIER_TEN: - return amount->cost * 10.0f; - case PRI_AOC_MULTIPLIER_HUNDRED: - return amount->cost * 100.0f; - case PRI_AOC_MULTIPLIER_THOUSAND: - return amount->cost * 1000.0f; - default: - return amount->cost; - } -} - -static int handle_facility_aoc_s(const struct pri_subcmd_aoc_s *aoc_s) -{ - /* Left as an excercise to the reader */ - ftdm_unused_arg(aoc_s); - return 0; -} - -static int handle_facility_aoc_d(const struct pri_subcmd_aoc_d *aoc_d) -{ - /* Left as an excercise to the reader */ - ftdm_unused_arg(aoc_d); - return 0; -} - -static int handle_facility_aoc_e(const struct pri_subcmd_aoc_e *aoc_e) -{ - char tmp[1024] = { 0 }; - int x = 0, offset = 0; - - switch (aoc_e->charge) { - case PRI_AOC_DE_CHARGE_FREE: - strcat(tmp, "\tcharge-type: none\n"); - offset = strlen(tmp); - break; - - case PRI_AOC_DE_CHARGE_CURRENCY: - sprintf(tmp, "\tcharge-type: money\n\tcharge-amount: %.2f\n\tcharge-currency: %s\n", - aoc_money_amount(&aoc_e->recorded.money.amount), - aoc_e->recorded.money.currency); - offset = strlen(tmp); - break; - - case PRI_AOC_DE_CHARGE_UNITS: - strcat(tmp, "\tcharge-type: units\n"); - offset = strlen(tmp); - - for (x = 0; x < aoc_e->recorded.unit.num_items; x++) { - sprintf(&tmp[offset], "\tcharge-amount: %ld (type: %d)\n", - aoc_e->recorded.unit.item[x].number, - aoc_e->recorded.unit.item[x].type); - offset += strlen(&tmp[offset]); - } - break; - - default: - strcat(tmp, "\tcharge-type: not available\n"); - offset = strlen(tmp); - } - - sprintf(&tmp[offset], "\tbilling-id: %s\n", aoc_billing_id(aoc_e->billing_id)); - offset += strlen(&tmp[offset]); - - strcat(&tmp[offset], "\tassociation-type: "); - offset += strlen(&tmp[offset]); - - switch (aoc_e->associated.charging_type) { - case PRI_AOC_E_CHARGING_ASSOCIATION_NOT_AVAILABLE: - strcat(&tmp[offset], "not available\n"); - break; - case PRI_AOC_E_CHARGING_ASSOCIATION_NUMBER: - sprintf(&tmp[offset], "number\n\tassociation-number: %s\n", aoc_e->associated.charge.number.str); - break; - case PRI_AOC_E_CHARGING_ASSOCIATION_ID: - sprintf(&tmp[offset], "id\n\tassociation-id: %d\n", aoc_e->associated.charge.id); - break; - default: - strcat(&tmp[offset], "unknown\n"); - } - - ftdm_log(FTDM_LOG_INFO, "AOC-E:\n%s", tmp); - return 0; -} -#endif - -#ifdef PRI_EVENT_FACILITY -/** - * \brief Handler for libpri facility events - * \param spri Pri wrapper structure (libpri, span, dchan) - * \param event_type Event type (unused) - * \param pevent Event - * \return 0 - */ -static int on_facility(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) -{ - struct pri_event_facility *pfac = &pevent->facility; - int i = 0; - - if (!pevent) - return 0; - - ftdm_log(FTDM_LOG_DEBUG, "Got a FACILITY event on span %d:%d\n", ftdm_span_get_id(spri->span), pfac->channel); - - if (!pfac->subcmds || pfac->subcmds->counter_subcmd <= 0) - return 0; - - for (i = 0; i < pfac->subcmds->counter_subcmd; i++) { - struct pri_subcommand *sub = &pfac->subcmds->subcmd[i]; - int res = -1; - - switch (sub->cmd) { -#ifdef HAVE_LIBPRI_AOC - case PRI_SUBCMD_AOC_S: /* AOC-S: Start of call */ - res = handle_facility_aoc_s(&sub->u.aoc_s); - break; - case PRI_SUBCMD_AOC_D: /* AOC-D: During call */ - res = handle_facility_aoc_d(&sub->u.aoc_d); - break; - case PRI_SUBCMD_AOC_E: /* AOC-E: End of call */ - res = handle_facility_aoc_e(&sub->u.aoc_e); - break; - case PRI_SUBCMD_AOC_CHARGING_REQ: - ftdm_log(FTDM_LOG_NOTICE, "AOC Charging Request received\n"); - break; - case PRI_SUBCMD_AOC_CHARGING_REQ_RSP: - ftdm_log(FTDM_LOG_NOTICE, "AOC Charging Request Response received [aoc_s data: %s, req: %x, resp: %x]\n", - sub->u.aoc_request_response.valid_aoc_s ? "yes" : "no", - sub->u.aoc_request_response.charging_request, - sub->u.aoc_request_response.charging_response); - break; -#endif - default: - ftdm_log(FTDM_LOG_DEBUG, "FACILITY subcommand %d is not implemented, ignoring\n", sub->cmd); - } - - ftdm_log(FTDM_LOG_DEBUG, "FACILITY subcommand %d handler returned %d\n", sub->cmd, res); - } - - ftdm_log(FTDM_LOG_DEBUG, "Caught Event on span %d %u (%s)\n", ftdm_span_get_id(spri->span), event_type, lpwrap_pri_event_str(event_type)); - return 0; -} -#endif - -/** - * \brief Handler for libpri dchan up event - * \param spri Pri wrapper structure (libpri, span, dchan) - * \param event_type Event type (unused) - * \param pevent Event - * \return 0 - */ -static int on_dchan_up(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) -{ - ftdm_unused_arg(event_type); - ftdm_unused_arg(pevent); - - if (!ftdm_test_flag(spri, LPWRAP_PRI_READY)) { - ftdm_signaling_status_t status = FTDM_SIG_STATE_UP; - ftdm_span_t *span = spri->span; - ftdm_libpri_data_t *isdn_data = span->signal_data; - ftdm_sigmsg_t sig; - int i; - - ftdm_log(FTDM_LOG_INFO, "Span %d D-Channel UP!\n", ftdm_span_get_id(span)); - ftdm_set_flag(spri, LPWRAP_PRI_READY); - ftdm_set_state_all(span, FTDM_CHANNEL_STATE_RESTART); - - ftdm_log(FTDM_LOG_NOTICE, "%d:Signaling link status changed to %s\n", ftdm_span_get_id(span), ftdm_signaling_status2str(status)); - - for (i = 1; i <= ftdm_span_get_chan_count(span); i++) { - ftdm_channel_t *chan = ftdm_span_get_channel(span, i); - - memset(&sig, 0, sizeof(sig)); - sig.span_id = ftdm_channel_get_span_id(chan); - sig.chan_id = ftdm_channel_get_id(chan); - sig.channel = chan; - sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sig.ev_data.sigstatus.status = status; - ftdm_span_send_signal(span, &sig); - } - - /* NT-mode idle b-channel restart timer */ - if (ftdm_span_get_trunk_type(span) != FTDM_TRUNK_BRI_PTMP && - isdn_data->mode == PRI_NETWORK && isdn_data->idle_restart_timeout_ms > 0) - { - ftdm_log_chan(isdn_data->dchan, FTDM_LOG_INFO, "Starting NT-mode idle b-channel restart timer (%d ms)\n", - isdn_data->idle_restart_timeout_ms); - lpwrap_start_timer(&isdn_data->spri, &isdn_data->t3xx, isdn_data->idle_restart_timeout_ms, &on_timeout_t3xx); - } - } - return 0; -} - -/** - * \brief Handler for libpri dchan down event - * \param spri Pri wrapper structure (libpri, span, dchan) - * \param event_type Event type (unused) - * \param pevent Event - * \return 0 - */ -static int on_dchan_down(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) -{ - ftdm_unused_arg(event_type); - ftdm_unused_arg(pevent); - - if (ftdm_test_flag(spri, LPWRAP_PRI_READY)) { - ftdm_signaling_status_t status = FTDM_SIG_STATE_DOWN; - ftdm_span_t *span = spri->span; - ftdm_libpri_data_t *isdn_data = span->signal_data; - ftdm_sigmsg_t sig; - int i; - - ftdm_log(FTDM_LOG_INFO, "Span %d D-Channel DOWN!\n", ftdm_span_get_id(span)); - ftdm_clear_flag(spri, LPWRAP_PRI_READY); - ftdm_set_state_all(span, FTDM_CHANNEL_STATE_RESTART); - - ftdm_log(FTDM_LOG_NOTICE, "%d:Signaling link status changed to %s\n", ftdm_span_get_id(span), ftdm_signaling_status2str(status)); - - for (i = 1; i <= ftdm_span_get_chan_count(span); i++) { - ftdm_channel_t *chan = ftdm_span_get_channel(span, i); - - memset(&sig, 0, sizeof(sig)); - sig.span_id = ftdm_channel_get_span_id(chan); - sig.chan_id = ftdm_channel_get_id(chan); - sig.channel = chan; - sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sig.ev_data.sigstatus.status = status; - - ftdm_span_send_signal(span, &sig); - - if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_B) { - ftdm_libpri_b_chan_t *chan_priv = chan->call_data; - /* Stop T316 and reset counter */ - lpwrap_stop_timer(spri, &chan_priv->t316); - chan_priv->t316_timeout_cnt = 0; - } - } - - /* NT-mode idle b-channel restart timer */ - ftdm_log_chan_msg(isdn_data->dchan, FTDM_LOG_INFO, "Stopping NT-mode idle b-channel restart timer\n"); - lpwrap_stop_timer(&isdn_data->spri, &isdn_data->t3xx); - } - return 0; -} - -/** - * \brief Handler for any libpri event - * \param spri Pri wrapper structure (libpri, span, dchan) - * \param event_type Event type (unused) - * \param pevent Event - * \return 0 - */ -static int on_anything(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) -{ - ftdm_log(FTDM_LOG_DEBUG, "-- Caught Event span %d %u (%s)\n", ftdm_span_get_id(spri->span), event_type, lpwrap_pri_event_str(event_type)); - switch (pevent->e) { - case PRI_EVENT_CONFIG_ERR: - { - ftdm_log(FTDM_LOG_WARNING, "-- PRI error event: %s\n", pevent->err.err); - } - break; - } - return 0; -} - -/** - * \brief Handler for libpri io fail event - * \param spri Pri wrapper structure (libpri, span, dchan) - * \param event_type Event type (unused) - * \param pevent Event - * \return 0 - */ -static int on_io_fail(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) -{ - ftdm_unused_arg(pevent); - - ftdm_log(FTDM_LOG_DEBUG, "-- Caught Event span %d %u (%s)\n", ftdm_span_get_id(spri->span), event_type, lpwrap_pri_event_str(event_type)); - return 0; -} - -/** - * \brief Main thread function for libpri span (monitor) - * \param me Current thread - * \param obj Span to run in this thread - * - * \todo Move all init stuff outside of loop or into ftdm_libpri_configure_span() - */ -static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj) -{ - ftdm_span_t *span = (ftdm_span_t *) obj; - ftdm_libpri_data_t *isdn_data = span->signal_data; - int down = 0; - int res = 0; - int i; - - ftdm_unused_arg(me); - - ftdm_set_flag(span, FTDM_SPAN_IN_THREAD); - isdn_data->dchan = NULL; - - /* - * Open D-Channel - */ - for (i = 1; i <= ftdm_span_get_chan_count(span); i++) { - ftdm_channel_t *chan = ftdm_span_get_channel(span, i); - - if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_DQ921) { - if (ftdm_channel_open(ftdm_span_get_id(span), i, &isdn_data->dchan) == FTDM_SUCCESS) { - ftdm_log_chan_msg(chan, FTDM_LOG_DEBUG, "Opened D-Channel\n"); - break; - } else { - ftdm_log_chan_msg(chan, FTDM_LOG_CRIT, "Failed to open D-Channel\n"); - goto out; - } - } - } - - /* - * Initialize BRI/PRI context - */ - res = lpwrap_init_pri(&isdn_data->spri, span, isdn_data->dchan, - isdn_data->dialect, isdn_data->mode, isdn_data->debug_mask); - - if (res) { - ftdm_log(FTDM_LOG_CRIT, "Failed to initialize BRI/PRI on span %d\n", - ftdm_span_get_id(span)); - goto out; - } - -#ifdef HAVE_LIBPRI_AOC - /* - * Only enable facility on trunk if really required, - * this may help avoid problems on troublesome lines. - */ - if (isdn_data->opts & FTMOD_LIBPRI_OPT_FACILITY_AOC) { - pri_facility_enable(isdn_data->spri.pri); - } -#endif -#ifdef HAVE_LIBPRI_MAINT_SERVICE - /* Support the different switch of service status */ - if (isdn_data->service_message_support) { - pri_set_service_message_support(isdn_data->spri.pri, 1); - } -#endif - - /* Callbacks for libpri events */ - LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_ANY, on_anything); - LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RING, on_ring); - LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RINGING, on_ringing); - LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_PROCEEDING, on_proceeding); - LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_PROGRESS, on_progress); - LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_ANSWER, on_answer); - LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_DCHAN_UP, on_dchan_up); - LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_DCHAN_DOWN, on_dchan_down); - LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_HANGUP_REQ, on_hangup); - LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_HANGUP_ACK, on_hangup); - LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_HANGUP, on_hangup); - LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_INFO_RECEIVED, on_information); - LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_KEYPAD_DIGIT, on_keypad_digit); - LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RESTART, on_restart); - LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RESTART_ACK, on_restart_ack); - LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_IO_FAIL, on_io_fail); -#ifdef PRI_EVENT_FACILITY - LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_FACILITY, on_facility); -#endif - - /* Callback invoked on each iteration of the lpwrap_run_pri() event loop */ - isdn_data->spri.on_loop = check_flags; - - /* - * Event loop - */ - while (ftdm_running() && !ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD)) { - if (down) { - ftdm_log(FTDM_LOG_INFO, "PRI back up on span %d\n", ftdm_span_get_id(span)); - ftdm_set_state_all(span, FTDM_CHANNEL_STATE_RESTART); - down = 0; - } - - lpwrap_run_pri(&isdn_data->spri); - - if (!ftdm_running() || ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD)) { - break; - } - - ftdm_log(FTDM_LOG_CRIT, "PRI down on span %d\n", ftdm_span_get_id(span)); - if (isdn_data->spri.dchan) { - _ftdm_channel_set_state_force(isdn_data->spri.dchan, FTDM_CHANNEL_STATE_DOWN); - } - - if (!down) { - ftdm_set_state_all(span, FTDM_CHANNEL_STATE_RESTART); - check_state(span); - } - - check_state(span); - check_events(span); - - down = 1; - ftdm_sleep(5000); - } -out: - /* close d-channel, if set */ - if (isdn_data->dchan) { - if (ftdm_channel_close(&isdn_data->dchan) != FTDM_SUCCESS) { - ftdm_log_chan_msg(isdn_data->dchan, FTDM_LOG_ERROR, "Failed to close D-Channel\n"); - } - } - - ftdm_log(FTDM_LOG_DEBUG, "PRI thread ended on span %d\n", ftdm_span_get_id(span)); - - ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD); - ftdm_clear_flag(isdn_data, FTMOD_LIBPRI_RUNNING); - - lpwrap_destroy_pri(&isdn_data->spri); - return NULL; -} - -/** - * \brief Stops a libpri span - * \param span Span to halt - * \return Success - * - * Sets a stop flag and waits for the thread to end - */ -static ftdm_status_t ftdm_libpri_stop(ftdm_span_t *span) -{ - ftdm_libpri_data_t *isdn_data = span->signal_data; - - if (!ftdm_test_flag(isdn_data, FTMOD_LIBPRI_RUNNING)) { - ftdm_log(FTDM_LOG_DEBUG, "Span %d already stopped, continuing anyway...\n", ftdm_span_get_id(span)); - return FTDM_SUCCESS; - } - - ftdm_log(FTDM_LOG_INFO, "Stopping span [s%d][%s]\n", - ftdm_span_get_id(span), ftdm_span_get_name(span)); - - ftdm_set_state_all(span, FTDM_CHANNEL_STATE_RESTART); - check_state(span); - - ftdm_set_flag(span, FTDM_SPAN_STOP_THREAD); - lpwrap_stop_pri(&isdn_data->spri); - - while (ftdm_test_flag(span, FTDM_SPAN_IN_THREAD)) { - ftdm_sleep(100); - } - - check_state(span); - - return FTDM_SUCCESS; -} - -/** - * \brief Starts a libpri span - * \param span Span to halt - * \return Success or failure - * - * Launches a thread to monitor the span - */ -static ftdm_status_t ftdm_libpri_start(ftdm_span_t *span) -{ - ftdm_libpri_data_t *isdn_data = span->signal_data; - - if (ftdm_test_flag(isdn_data, FTMOD_LIBPRI_RUNNING)) { - return FTDM_FAIL; - } - - ftdm_log(FTDM_LOG_INFO, "Starting span [s%d][%s]\n", - ftdm_span_get_id(span), ftdm_span_get_name(span)); - - ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD); - ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD); - - ftdm_set_flag(isdn_data, FTMOD_LIBPRI_RUNNING); - - return ftdm_thread_create_detached(ftdm_libpri_run, span); -} - -/** - * \brief Converts a node string to node value - * \param node Node string to convert - * \return -1 on failure, node value on success - */ -static int parse_mode(const char *mode) -{ - if (!strcasecmp(mode, "cpe") || !strcasecmp(mode, "user")) - return PRI_CPE; - if (!strcasecmp(mode, "network") || !strcasecmp(mode, "net")) - return PRI_NETWORK; - - return -1; -} - -/** - * \brief Converts a switch string to switch value - * \param swtype Swtype string to convert - * \return Switch value - */ -static int parse_dialect(const char *dialect) -{ - if (!strcasecmp(dialect, "ni1")) - return PRI_SWITCH_NI1; - if (!strcasecmp(dialect, "ni2")) - return PRI_SWITCH_NI2; - if (!strcasecmp(dialect, "dms100")) - return PRI_SWITCH_DMS100; - if (!strcasecmp(dialect, "lucent5e") || !strcasecmp(dialect, "5ess")) - return PRI_SWITCH_LUCENT5E; - if (!strcasecmp(dialect, "att4ess") || !strcasecmp(dialect, "4ess")) - return PRI_SWITCH_ATT4ESS; - if (!strcasecmp(dialect, "euroisdn") || !strcasecmp(dialect, "q931")) - return PRI_SWITCH_EUROISDN_E1; - if (!strcasecmp(dialect, "gr303eoc")) - return PRI_SWITCH_GR303_EOC; - if (!strcasecmp(dialect, "gr303tmc")) - return PRI_SWITCH_GR303_TMC; - - return PRI_SWITCH_DMS100; -} - -/** - * \brief Converts a L1 string to L1 value - * \param l1 L1 string to convert - * \return L1 value - */ -static int parse_layer1(const char *val) -{ - if (!strcasecmp(val, "alaw")) - return PRI_LAYER_1_ALAW; - - return PRI_LAYER_1_ULAW; -} - -/** - * \brief Converts a DP string to DP value - * \param dp DP string to convert - * \return DP value - */ -static int parse_ton(const char *ton) -{ - if (!strcasecmp(ton, "international")) - return PRI_INTERNATIONAL_ISDN; - if (!strcasecmp(ton, "national")) - return PRI_NATIONAL_ISDN; - if (!strcasecmp(ton, "local")) - return PRI_LOCAL_ISDN; - if (!strcasecmp(ton, "private")) - return PRI_PRIVATE; - if (!strcasecmp(ton, "unknown")) - return PRI_UNKNOWN; - - return PRI_UNKNOWN; -} - -/** - * \brief Parse overlap string to value - * \param val String to parse - * \return Overlap flags - */ -static int parse_overlap_dial(const char *val) -{ - if (!strcasecmp(val, "yes") || !strcasecmp(val, "both")) - return FTMOD_LIBPRI_OVERLAP_BOTH; - if (!strcasecmp(val, "incoming") || !strcasecmp(val, "receive")) - return FTMOD_LIBPRI_OVERLAP_RECEIVE; - if (!strcasecmp(val, "outgoing") || !strcasecmp(val, "send")) - return FTMOD_LIBPRI_OVERLAP_SEND; - if (!strcasecmp(val, "no")) - return FTMOD_LIBPRI_OVERLAP_NONE; - - return -1; -} - -/** - * \brief Parses an option string to flags - * \param in String to parse for configuration options - * \return Flags - */ -static uint32_t parse_opts(const char *in) -{ - uint32_t flags = 0; - - if (!in) { - return 0; - } - - if (strstr(in, "suggest_channel")) { - flags |= FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL; - } - if (strstr(in, "omit_display")) { - flags |= FTMOD_LIBPRI_OPT_OMIT_DISPLAY_IE; - } - if (strstr(in, "omit_redirecting_number")) { - flags |= FTMOD_LIBPRI_OPT_OMIT_REDIRECTING_NUMBER_IE; - } - if (strstr(in, "aoc")) { - flags |= FTMOD_LIBPRI_OPT_FACILITY_AOC; - } - return flags; -} - -/** - * Parse timeout value with (convenience) modifier suffix - * \param[in] in Input string, e.g. '1d' = 1 day, '7w' = 7 weeks, '3s' = 3 seconds - * \todo Could be simplified by using strtol() instead of atoi() - */ -static int parse_timeout(const char *in) -{ - const char *p_end = NULL, *p_start = in; - int msec = 0; - - if (ftdm_strlen_zero(in)) - return 0; - - p_end = in + strlen(in); - - /* skip whitespace at start */ - while (p_start != p_end && *p_start == ' ') - p_start++; - - /* skip whitespace at end */ - while (p_end != p_start && (*p_end == ' ' || *p_end == '\0')) - p_end--; - - msec = atoi(p_start); - - switch (p_end[0]) { - case 's': /* seconds */ - msec *= 1000; - break; - case 'm': /* minutes */ - if (p_end[1] != 's') msec *= 60 * 1000; - break; - case 'h': /* hours */ - msec *= 3600 * 1000; - break; - case 'd': /* days */ - msec *= 86400 * 1000; - break; - case 'w': /* weeks */ - msec *= 604800 * 1000; - break; - default: /* miliseconds */ - break; - } - return msec; -} - -/** - * \brief Initialises a libpri span from configuration variables - * \param span Span to configure - * \param sig_cb Callback function for event signals - * \param ftdm_parameters List of configuration variables - * \return Success or failure - */ -static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span) -{ - ftdm_libpri_data_t *isdn_data = NULL; - uint32_t bchan_count = 0; - uint32_t dchan_count = 0; - uint32_t i; - - if (ftdm_span_get_trunk_type(span) >= FTDM_TRUNK_NONE) { - ftdm_log(FTDM_LOG_WARNING, "Invalid trunk type '%s' defaulting to T1.\n", ftdm_span_get_trunk_type_str(span)); - ftdm_span_set_trunk_type(span, FTDM_TRUNK_T1); - } - - for (i = 1; i <= ftdm_span_get_chan_count(span); i++) { - ftdm_channel_t *chan = ftdm_span_get_channel(span, i); - - switch (ftdm_channel_get_type(chan)) { - case FTDM_CHAN_TYPE_DQ921: - if (dchan_count > 1) { - ftdm_log(FTDM_LOG_ERROR, "Span has more than 2 D-Channels!\n"); - return FTDM_FAIL; - } - dchan_count++; - break; - case FTDM_CHAN_TYPE_B: - bchan_count++; - break; - default: /* Ignore other channel types */ - break; - } - } - if (!dchan_count) { - ftdm_log(FTDM_LOG_ERROR, "Span has no D-Channel!\n"); - return FTDM_FAIL; - } - if (!bchan_count) { - ftdm_log(FTDM_LOG_ERROR, "Span has no B-Channels!\n"); - return FTDM_FAIL; - } - - isdn_data = ftdm_malloc(sizeof(*isdn_data)); - assert(isdn_data != NULL); - memset(isdn_data, 0, sizeof(*isdn_data)); - - /* set some default values */ - isdn_data->ton = PRI_UNKNOWN; - isdn_data->overlap_timeout_ms = OVERLAP_TIMEOUT_MS_DEFAULT; - isdn_data->idle_restart_timeout_ms = IDLE_RESTART_TIMEOUT_MS_DEFAULT; - - /* - * T316 restart ack timeout and retry limit - * (ITU-T Q.931 05/98 Paragraph 5.5.1 and Table 9-1) - */ - isdn_data->t316_timeout_ms = T316_TIMEOUT_MS_DEFAULT; - isdn_data->t316_max_attempts = T316_ATTEMPT_LIMIT_DEFAULT; - - - /* Use span's trunk_mode as a reference for the default libpri mode */ - if (ftdm_span_get_trunk_mode(span) == FTDM_TRUNK_MODE_NET) { - isdn_data->mode = PRI_NETWORK; - } else { - isdn_data->mode = PRI_CPE; - } - - switch (ftdm_span_get_trunk_type(span)) { - case FTDM_TRUNK_BRI: - case FTDM_TRUNK_BRI_PTMP: -#ifndef HAVE_LIBPRI_BRI - ftdm_log(FTDM_LOG_ERROR, "Unsupported trunk type: '%s', libpri too old\n", ftdm_span_get_trunk_type_str(span)); - goto error; -#endif - case FTDM_TRUNK_E1: - ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ALAW since this is an E1/BRI/BRI PTMP trunk\n"); - isdn_data->layer1 = PRI_LAYER_1_ALAW; - isdn_data->dialect = PRI_SWITCH_EUROISDN_E1; - break; - case FTDM_TRUNK_T1: - case FTDM_TRUNK_J1: - ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ULAW since this is a T1/J1 trunk\n"); - isdn_data->layer1 = PRI_LAYER_1_ULAW; - isdn_data->dialect = PRI_SWITCH_LUCENT5E; - break; - default: - ftdm_log(FTDM_LOG_ERROR, "Invalid trunk type: '%s'\n", ftdm_span_get_trunk_type_str(span)); - goto error; - } - - /* - * Init MSN filter - */ - if (msn_filter_init(isdn_data) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Failed to init MSN filter\n"); - goto error; - } - - for (i = 0; ftdm_parameters[i].var; i++) { - const char *var = ftdm_parameters[i].var; - const char *val = ftdm_parameters[i].val; - - if (ftdm_strlen_zero(var)) { - ftdm_log(FTDM_LOG_WARNING, "Skipping parameter with no name\n"); - continue; - } - - if (ftdm_strlen_zero(val)) { - ftdm_log(FTDM_LOG_ERROR, "Parameter '%s' has no value\n", var); - goto error; - } - - if (!strcasecmp(var, "node") || !strcasecmp(var, "mode")) { - if ((isdn_data->mode = parse_mode(val)) == -1) { - ftdm_log(FTDM_LOG_ERROR, "Unknown node type '%s'\n", val); - goto error; - } - } - else if (!strcasecmp(var, "switch") || !strcasecmp(var, "dialect")) { - isdn_data->dialect = parse_dialect(val); - } - else if (!strcasecmp(var, "opts")) { - isdn_data->opts = parse_opts(val); - } - else if (!strcasecmp(var, "dp") || !strcasecmp(var, "ton")) { - isdn_data->ton = parse_ton(val); - } - else if (!strcasecmp(var, "l1") || !strcasecmp(var, "layer1")) { - isdn_data->layer1 = parse_layer1(val); - } - else if (!strcasecmp(var, "overlapdial")) { - if ((isdn_data->overlap = parse_overlap_dial(val)) == -1) { - ftdm_log(FTDM_LOG_ERROR, "Invalid overlap flag, ignoring parameter\n"); - isdn_data->overlap = FTMOD_LIBPRI_OVERLAP_NONE; - } - } - else if (!strcasecmp(var, "digit_timeout") || !strcasecmp(var, "t302")) { - int tmp = parse_timeout(val); - if (!tmp) { - isdn_data->overlap_timeout_ms = 0; /* disabled */ - } - else if ((isdn_data->overlap_timeout_ms = ftdm_clamp(tmp, OVERLAP_TIMEOUT_MS_MIN, OVERLAP_TIMEOUT_MS_MAX)) != tmp) { - ftdm_log(FTDM_LOG_WARNING, "'%s' value %d ms ('%s') outside of range [%d:%d] ms, using %d ms instead\n", - var, tmp, val, OVERLAP_TIMEOUT_MS_MIN, OVERLAP_TIMEOUT_MS_MAX, - isdn_data->overlap_timeout_ms); - } - } - else if (!strcasecmp(var, "idle_restart_interval")) { - int tmp = parse_timeout(val); - if (!tmp) { - isdn_data->idle_restart_timeout_ms = 0; /* disabled */ - } - else if ((isdn_data->idle_restart_timeout_ms = ftdm_clamp(tmp, IDLE_RESTART_TIMEOUT_MS_MIN, IDLE_RESTART_TIMEOUT_MS_MAX)) != tmp) { - ftdm_log(FTDM_LOG_WARNING, "'%s' value %d ms ('%s') outside of range [%d:%d] ms, using %d ms instead\n", - var, tmp, val, IDLE_RESTART_TIMEOUT_MS_MIN, IDLE_RESTART_TIMEOUT_MS_MAX, - isdn_data->idle_restart_timeout_ms); - } - } - else if (!strcasecmp(var, "restart_timeout") || !strcasecmp(var, "t316")) { - int tmp = parse_timeout(val); - if (tmp <= 0) { - ftdm_log(FTDM_LOG_ERROR, "'%s' value '%s' is invalid\n", var, val); - goto error; - } - else if ((isdn_data->t316_timeout_ms = ftdm_clamp(tmp, T316_TIMEOUT_MS_MIN, T316_TIMEOUT_MS_MAX)) != tmp) { - ftdm_log(FTDM_LOG_WARNING, "'%s' value %d ms ('%s') outside of range [%d:%d] ms, using %d ms instead\n", - var, tmp, val, T316_TIMEOUT_MS_MIN, T316_TIMEOUT_MS_MAX, - isdn_data->t316_timeout_ms); - } - } - else if (!strcasecmp(var, "restart_attempts") || !strcasecmp(var, "t316_limit")) { - int tmp = atoi(val); - if (tmp <= 0) { - ftdm_log(FTDM_LOG_ERROR, "'%s' value '%s' is invalid\n", var, val); - goto error; - } - else if ((isdn_data->t316_max_attempts = ftdm_clamp(tmp, T316_ATTEMPT_LIMIT_MIN, T316_ATTEMPT_LIMIT_MAX)) != tmp) { - ftdm_log(FTDM_LOG_WARNING, "'%s' value %d ('%s') outside of range [%d:%d], using %d instead\n", - var, tmp, val, T316_ATTEMPT_LIMIT_MIN, T316_ATTEMPT_LIMIT_MAX, - isdn_data->t316_max_attempts); - } - } - else if (!strcasecmp(var, "debug")) { - if (parse_debug(val, &isdn_data->debug_mask) == -1) { - ftdm_log(FTDM_LOG_ERROR, "Invalid debug flag, ignoring parameter\n"); - isdn_data->debug_mask = 0; - } - } - else if (!strcasecmp(var, "service_message_support")) { - if (ftdm_true(val)) { - isdn_data->service_message_support = 1; - } - } - else if (!strcasecmp(var, "local-number") || !strcasecmp(var, "msn")) { - if (msn_filter_add(isdn_data, val) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Invalid MSN/DDI(s) '%s' specified\n", val); - goto error; - } - } - else { - ftdm_log(FTDM_LOG_ERROR, "Unknown parameter '%s', aborting configuration\n", var); - goto error; - } - } - - /* Check if modes match and log a message if they do not. Just to be on the safe side. */ - if (isdn_data->mode == PRI_CPE && ftdm_span_get_trunk_mode(span) == FTDM_TRUNK_MODE_NET) { - ftdm_log(FTDM_LOG_WARNING, "Span '%s' signalling set up for TE/CPE/USER mode, while port is running in NT/NET mode. You may want to check your 'trunk_mode' settings.\n", - ftdm_span_get_name(span)); - } - else if (isdn_data->mode == PRI_NETWORK && ftdm_span_get_trunk_mode(span) == FTDM_TRUNK_MODE_CPE) { - ftdm_log(FTDM_LOG_WARNING, "Span '%s' signalling set up for NT/NET mode, while port is running in TE/CPE/USER mode. You may want to check your 'trunk_mode' settings.\n", - ftdm_span_get_name(span)); - } - - span->start = ftdm_libpri_start; - span->stop = ftdm_libpri_stop; - span->signal_cb = sig_cb; - - span->signal_data = isdn_data; - span->signal_type = FTDM_SIGTYPE_ISDN; - span->outgoing_call = isdn_outgoing_call; - - span->state_map = &isdn_state_map; - span->state_processor = state_advance; - - span->get_channel_sig_status = isdn_get_channel_sig_status; - span->get_span_sig_status = isdn_get_span_sig_status; - - /* move calls to PROCEED state when they hit dialplan (ROUTING state in FreeSWITCH) */ - ftdm_set_flag(span, FTDM_SPAN_USE_PROCEED_STATE); - - if ((isdn_data->opts & FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL)) { - span->channel_request = isdn_channel_request; - ftdm_set_flag(span, FTDM_SPAN_SUGGEST_CHAN_ID); - } - - /* Allocate per-channel private data */ - for (i = 1; i <= ftdm_span_get_chan_count(span); i++) { - ftdm_channel_t *chan = ftdm_span_get_channel(span, i); - - if (!chan) - continue; - - if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_B) { - ftdm_libpri_b_chan_t *priv = NULL; - - priv = calloc(1, sizeof(*priv)); - if (!priv) { - ftdm_log_chan_msg(chan, FTDM_LOG_CRIT, "Failed to allocate per-channel private data\n"); - goto error; - } - priv->channel = chan; - chan->call_data = priv; - } - } - return FTDM_SUCCESS; -error: - /* TODO: free per-channel private data */ - msn_filter_destroy(isdn_data); - ftdm_safe_free(isdn_data); - return FTDM_FAIL; -} - -/** - * \brief FreeTDM libpri signaling and IO module definition - */ -ftdm_module_t ftdm_module = { - "libpri", - ftdm_libpri_io_init, - ftdm_libpri_unload, - ftdm_libpri_init, - NULL, - NULL, - ftdm_libpri_configure_span -}; - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h deleted file mode 100644 index 8ace29693b..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2009-2012, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef FTMOD_LIBPRI_H -#define FTMOD_LIBPRI_H -#include "freetdm.h" -#include "lpwrap_pri.h" - -/* T302 Overlap receiving inter-digit timeout */ -#define OVERLAP_TIMEOUT_MS_DEFAULT 5000 /* 5 sec */ -#define OVERLAP_TIMEOUT_MS_MIN 3000 /* 3 sec */ -#define OVERLAP_TIMEOUT_MS_MAX 30000 /* 30 sec */ - -/* NT-mode idle b-channel restart timer */ -#define IDLE_RESTART_TIMEOUT_MS_DEFAULT 0 /* disabled */ -#define IDLE_RESTART_TIMEOUT_MS_MIN 10000 /* 10 sec */ -#define IDLE_RESTART_TIMEOUT_MS_MAX 86400000 /* 1 day */ - -/* T316 RESTART ACK wait timer */ -#define T316_TIMEOUT_MS_DEFAULT 30000 /* 30 sec */ -#define T316_TIMEOUT_MS_MIN 10000 /* 10 sec */ -#define T316_TIMEOUT_MS_MAX 300000 /* 5 min */ - -/* T316 restart attempts until channel is suspended */ -#define T316_ATTEMPT_LIMIT_DEFAULT 3 -#define T316_ATTEMPT_LIMIT_MIN 1 -#define T316_ATTEMPT_LIMIT_MAX 10 - - -typedef enum { - SERVICE_CHANGE_STATUS_INSERVICE = 0, - SERVICE_CHANGE_STATUS_MAINTENANCE, - SERVICE_CHANGE_STATUS_OUTOFSERVICE -} service_change_status_t; - -typedef enum { - FTMOD_LIBPRI_OPT_NONE = 0, - FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL = (1 << 0), - FTMOD_LIBPRI_OPT_OMIT_DISPLAY_IE = (1 << 1), - FTMOD_LIBPRI_OPT_OMIT_REDIRECTING_NUMBER_IE = (1 << 2), - FTMOD_LIBPRI_OPT_FACILITY_AOC = (1 << 3), - - FTMOD_LIBPRI_OPT_MAX = (1 << 4) -} ftdm_isdn_opts_t; - -typedef enum { - FTMOD_LIBPRI_RUNNING = (1 << 0) -} ftdm_isdn_flag_t; - -typedef enum { - FTMOD_LIBPRI_OVERLAP_NONE = 0, - FTMOD_LIBPRI_OVERLAP_RECEIVE = (1 << 0), - FTMOD_LIBPRI_OVERLAP_SEND = (1 << 1) -#define FTMOD_LIBPRI_OVERLAP_BOTH (FTMOD_LIBPRI_OVERLAP_RECEIVE | FTMOD_LIBPRI_OVERLAP_SEND) -} ftdm_isdn_overlap_t; - -struct ftdm_libpri_data { - ftdm_channel_t *dchan; - ftdm_isdn_opts_t opts; - uint32_t flags; - uint32_t debug_mask; - - int mode; - int dialect; - int overlap; /*!< Overlap dial flags */ - int overlap_timeout_ms; /*!< Overlap dial timeout */ - int idle_restart_timeout_ms; /*!< NT-mode idle b-channel restart */ - int t316_timeout_ms; /*!< T316 RESTART ACK timeout */ - int t316_max_attempts; /*!< T316 timeout limit */ - unsigned int layer1; - unsigned int ton; - unsigned int service_message_support; - - lpwrap_pri_t spri; - - /* MSN filter */ - ftdm_hash_t *msn_hash; - ftdm_mutex_t *msn_mutex; - - /* NT-mode idle restart timer */ - struct lpwrap_timer t3xx; -}; - -typedef struct ftdm_libpri_data ftdm_libpri_data_t; - - -/* - * b-channel flags - */ -enum { - FTDM_LIBPRI_B_NONE = 0, - FTDM_LIBPRI_B_REMOTE_RESTART = (1 << 0), /*!< Remote triggered channel restart */ -}; - -/** - * Per-b-channel private data - */ -struct ftdm_libpri_b_chan { - struct lpwrap_timer t302; /*!< T302 overlap receive timer */ - struct lpwrap_timer t316; /*!< T316 restart ack timer */ - ftdm_channel_t *channel; /*!< back-pointer to b-channel */ - q931_call *call; /*!< libpri opaque call handle */ - uint32_t flags; /*!< channel flags */ - uint32_t t316_timeout_cnt; /*!< T316 timeout counter */ - int peerhangup; /*!< hangup requested from libpri (RELEASE/RELEASE_ACK/DL_RELEASE/TIMERS EXPIRY) */ -}; - -typedef struct ftdm_libpri_b_chan ftdm_libpri_b_chan_t; - -#endif - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c b/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c deleted file mode 100644 index a59baccbe5..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c +++ /dev/null @@ -1,464 +0,0 @@ -/* - * Copyright (c) 2009-2012, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -//#define IODEBUG - -#include "private/ftdm_core.h" -#include "lpwrap_pri.h" - -static struct lpwrap_pri_event_list LPWRAP_PRI_EVENT_LIST[LPWRAP_PRI_EVENT_MAX] = { - {0, LPWRAP_PRI_EVENT_ANY, "ANY"}, - {1, LPWRAP_PRI_EVENT_DCHAN_UP, "DCHAN_UP"}, - {2, LPWRAP_PRI_EVENT_DCHAN_DOWN, "DCHAN_DOWN"}, - {3, LPWRAP_PRI_EVENT_RESTART, "RESTART"}, - {4, LPWRAP_PRI_EVENT_CONFIG_ERR, "CONFIG_ERR"}, - {5, LPWRAP_PRI_EVENT_RING, "RING"}, - {6, LPWRAP_PRI_EVENT_HANGUP, "HANGUP"}, - {7, LPWRAP_PRI_EVENT_RINGING, "RINGING"}, - {8, LPWRAP_PRI_EVENT_ANSWER, "ANSWER"}, - {9, LPWRAP_PRI_EVENT_HANGUP_ACK, "HANGUP_ACK"}, - {10, LPWRAP_PRI_EVENT_RESTART_ACK, "RESTART_ACK"}, - {11, LPWRAP_PRI_EVENT_FACILITY, "FACILITY"}, - {12, LPWRAP_PRI_EVENT_INFO_RECEIVED, "INFO_RECEIVED"}, - {13, LPWRAP_PRI_EVENT_PROCEEDING, "PROCEEDING"}, - {14, LPWRAP_PRI_EVENT_SETUP_ACK, "SETUP_ACK"}, - {15, LPWRAP_PRI_EVENT_HANGUP_REQ, "HANGUP_REQ"}, - {16, LPWRAP_PRI_EVENT_NOTIFY, "NOTIFY"}, - {17, LPWRAP_PRI_EVENT_PROGRESS, "PROGRESS"}, - {18, LPWRAP_PRI_EVENT_KEYPAD_DIGIT, "KEYPAD_DIGIT"}, - {19, LPWRAP_PRI_EVENT_IO_FAIL, "IO_FAIL"}, -}; - -const char *lpwrap_pri_event_str(lpwrap_pri_event_t event_id) -{ - if (event_id >= LPWRAP_PRI_EVENT_MAX) - return ""; - - return LPWRAP_PRI_EVENT_LIST[event_id].name; -} - -static int __pri_lpwrap_read(struct pri *pri, void *buf, int buflen) -{ - struct lpwrap_pri *spri = (struct lpwrap_pri *) pri_get_userdata(pri); - ftdm_size_t len = buflen; - ftdm_status_t zst; - int res; - - if ((zst = ftdm_channel_read(spri->dchan, buf, &len)) != FTDM_SUCCESS) { - if (zst == FTDM_FAIL) { - ftdm_log(FTDM_LOG_CRIT, "span %d D-READ FAIL! [%s]\n", spri->span->span_id, spri->dchan->last_error); - spri->errs++; - } else { - ftdm_log(FTDM_LOG_CRIT, "span %d D-READ TIMEOUT\n", spri->span->span_id); - } - /* we cannot return -1, libpri seems to expect values >= 0 */ - return 0; - } - spri->errs = 0; - res = (int)len; - - if (res > 0) { - memset(&((unsigned char*)buf)[res], 0, 2); - res += 2; -#ifdef IODEBUG - { - char bb[2048] = { 0 }; - - print_hex_bytes(buf, res - 2, bb, sizeof(bb)); - ftdm_log(FTDM_LOG_DEBUG, "READ %d\n", res - 2); - } -#endif - } - return res; -} - -static int __pri_lpwrap_write(struct pri *pri, void *buf, int buflen) -{ - struct lpwrap_pri *spri = (struct lpwrap_pri *) pri_get_userdata(pri); - ftdm_size_t len = buflen - 2; - - if (ftdm_channel_write(spri->dchan, buf, buflen, &len) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "span %d D-WRITE FAIL! [%s]\n", spri->span->span_id, spri->dchan->last_error); - /* we cannot return -1, libpri seems to expect values >= 0 */ - return 0; - } - -#ifdef IODEBUG - { - char bb[2048] = { 0 }; - - print_hex_bytes(buf, buflen - 2, bb, sizeof(bb)); - ftdm_log(FTDM_LOG_DEBUG, "WRITE %d\n", (int)buflen - 2); - } -#endif - return (int)buflen; -} - - -/* - * Unified init function for BRI + PRI libpri spans - */ -int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int debug) -{ - int ret = -1; - - memset(spri, 0, sizeof(struct lpwrap_pri)); - spri->dchan = dchan; - spri->span = span; - - if (!spri->dchan) { - ftdm_log(FTDM_LOG_ERROR, "No D-Channel available, unable to create BRI/PRI\n"); - return ret; - } - - if (ftdm_mutex_create(&spri->timer_mutex) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Failed to create timer list mutex\n"); - return ret; - } - - switch (ftdm_span_get_trunk_type(span)) { - case FTDM_TRUNK_E1: - case FTDM_TRUNK_J1: - case FTDM_TRUNK_T1: - spri->pri = pri_new_cb(spri->dchan->sockfd, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri); - break; -#ifdef HAVE_LIBPRI_BRI - case FTDM_TRUNK_BRI: - spri->pri = pri_new_bri_cb(spri->dchan->sockfd, 1, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri); - break; - case FTDM_TRUNK_BRI_PTMP: - spri->pri = pri_new_bri_cb(spri->dchan->sockfd, 0, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri); - break; -#endif - default: - ftdm_log(FTDM_LOG_CRIT, "Invalid/unsupported trunk type '%s'\n", - ftdm_span_get_trunk_type_str(span)); - ftdm_mutex_destroy(&spri->timer_mutex); - return ret; - } - - if (spri->pri) { - pri_set_debug(spri->pri, debug); -#ifdef HAVE_LIBPRI_BRI - /* "follow Q.931 Section 5.3.2 call hangup better" */ - pri_hangup_fix_enable(spri->pri, 1); -#endif -#ifdef HAVE_LIBPRI_AOC - pri_aoc_events_enable(spri->pri, 1); -#endif - ret = 0; - } else { - ftdm_log(FTDM_LOG_CRIT, "Unable to create BRI/PRI\n"); - ftdm_mutex_destroy(&spri->timer_mutex); - } - return ret; -} - - -#define timeval_to_ms(x) \ - (ftdm_time_t)(((x)->tv_sec * 1000) + ((x)->tv_usec / 1000)) - -int lpwrap_start_timer(struct lpwrap_pri *spri, struct lpwrap_timer *timer, const uint32_t timeout_ms, timeout_handler callback) -{ - struct lpwrap_timer **prev, *cur; - - if (!spri || !timer || timer->timeout) - return -1; - - ftdm_log_chan(spri->dchan, FTDM_LOG_DEBUG, "-- Starting timer %p with timeout %u ms\n", - timer, timeout_ms); - - timer->timeout = ftdm_current_time_in_ms() + timeout_ms; - timer->callback = callback; - timer->next = NULL; - - ftdm_mutex_lock(spri->timer_mutex); - - for (prev = &spri->timer_list, cur = spri->timer_list; cur; prev = &(*prev)->next, cur = cur->next) { - if (cur->timeout > timer->timeout) { - *prev = timer; - timer->next = cur; - break; - } - } - if (!cur) { - *prev = timer; - } - - ftdm_mutex_unlock(spri->timer_mutex); - return 0; -} - -int lpwrap_stop_timer(struct lpwrap_pri *spri, struct lpwrap_timer *timer) -{ - struct lpwrap_timer **prev, *cur; - - if (!spri || !timer) - return -1; - - if (!timer->timeout) - return 0; - - ftdm_log_chan(spri->dchan, FTDM_LOG_DEBUG, "-- Stopping timer %p\n", timer); - - ftdm_mutex_lock(spri->timer_mutex); - - for (prev = &spri->timer_list, cur = spri->timer_list; cur; prev = &(*prev)->next, cur = cur->next) { - if (cur == timer) { - *prev = cur->next; - break; - } - } - - ftdm_mutex_unlock(spri->timer_mutex); - - if (!cur) { - ftdm_log_chan(spri->dchan, FTDM_LOG_WARNING, "-- Timer %p not found in list\n", timer); - } - - timer->next = NULL; - timer->timeout = 0; - timer->callback = NULL; - return 0; -} - -static struct lpwrap_timer *lpwrap_timer_next(struct lpwrap_pri *spri) -{ - return spri ? spri->timer_list : NULL; -} - -static int lpwrap_run_expired(struct lpwrap_pri *spri, ftdm_time_t now_ms) -{ - struct lpwrap_timer *expired_list = NULL; - struct lpwrap_timer **prev, *cur; - - if (!spri || !spri->timer_list) - return 0; - - ftdm_mutex_lock(spri->timer_mutex); - - /* Move all timers to expired list */ - expired_list = spri->timer_list; - - for (prev = &expired_list, cur = expired_list; cur; prev = &(*prev)->next, cur = cur->next) { - if (cur->timeout > now_ms) { - *prev = NULL; - break; - } - } - /* Move non-expired timer to front of timer_list (or clear list if there are none) */ - spri->timer_list = cur; - - ftdm_mutex_unlock(spri->timer_mutex); - - /* fire callbacks */ - while ((cur = expired_list)) { - timeout_handler handler = cur->callback; - expired_list = cur->next; - - /* Stop timer */ - cur->next = NULL; - cur->timeout = 0; - cur->callback = NULL; - - if (handler) - handler(spri, cur); - } - return 0; -} - - -#define LPWRAP_MAX_TIMEOUT_MS 100 -#define LPWRAP_MAX_ERRORS 2 - -int lpwrap_run_pri_once(struct lpwrap_pri *spri) -{ - struct timeval *next = NULL; - struct lpwrap_timer *timer = NULL; - pri_event *event = NULL; - ftdm_wait_flag_t flags; - ftdm_time_t now_ms, next_ms, timeout_ms, tmp_ms; - int ret; - - if (spri->on_loop) { - if ((ret = spri->on_loop(spri)) < 0) - return FTDM_FAIL; - } - - /* Default timeout when no scheduled events are pending */ - timeout_ms = LPWRAP_MAX_TIMEOUT_MS; - next_ms = 0; - now_ms = ftdm_current_time_in_ms(); - - /* - * Get the next scheduled timer from libpri to set the maximum timeout, - * but limit it to MAX_TIMEOUT_MS (100ms). - */ - if ((next = pri_schedule_next(spri->pri))) { - next_ms = timeval_to_ms(next); - if (now_ms >= next_ms) { - /* Already late, handle timeout */ - timeout_ms = 0; - } else { - /* Calculate new timeout and limit it to MAX_TIMEOUT_MS miliseconds */ - tmp_ms = ftdm_min(next_ms - now_ms, LPWRAP_MAX_TIMEOUT_MS); - timeout_ms = ftdm_min(timeout_ms, tmp_ms); - } - } - - /* - * Next lpwrap_timer timeout - */ - if ((timer = lpwrap_timer_next(spri))) { - if (now_ms >= timer->timeout) { - /* Already late, handle timeout */ - timeout_ms = 0; - } else { - /* Calculate new timeout and limit it to MAX_TIMEOUT_MS miliseconds */ - tmp_ms = ftdm_min(timer->timeout - now_ms, LPWRAP_MAX_TIMEOUT_MS); - timeout_ms = ftdm_min(timeout_ms, tmp_ms); - } - } - - /* */ - if (timeout_ms > 0) { - flags = FTDM_READ | FTDM_EVENTS; - ret = ftdm_channel_wait(spri->dchan, &flags, timeout_ms); - - if (spri->flags & LPWRAP_PRI_ABORT) - return FTDM_SUCCESS; - - if (ret == FTDM_TIMEOUT) { - now_ms = ftdm_current_time_in_ms(); - - if (next) { - if (next_ms < now_ms) { - ftdm_log_chan(spri->dchan, FTDM_LOG_DEBUG, "pri timer %d ms late\n", - (int)(now_ms - next_ms)); - } - event = pri_schedule_run(spri->pri); - } - if (timer) { - if (timer->timeout < now_ms) { - ftdm_log_chan(spri->dchan, FTDM_LOG_DEBUG, "lpwrap timer %d ms late\n", - (int)(now_ms - timer->timeout)); - } - lpwrap_run_expired(spri, now_ms); - } - } else if (flags & (FTDM_READ | FTDM_EVENTS)) { - event = pri_check_event(spri->pri); - } - } else { - /* - * Scheduled event has already expired, handle it immediately - */ - if (next) { - event = pri_schedule_run(spri->pri); - } - if (timer) { - lpwrap_run_expired(spri, now_ms); - } - } - - if (spri->flags & LPWRAP_PRI_ABORT) - return FTDM_SUCCESS; - - if (event) { - event_handler handler; - - /* 0 is catchall event handler */ - if (event->e < 0 || event->e >= LPWRAP_PRI_EVENT_MAX) { - handler = spri->eventmap[0]; - } else if (spri->eventmap[event->e]) { - handler = spri->eventmap[event->e]; - } else { - handler = spri->eventmap[0]; - } - - if (handler) { - handler(spri, event->e, event); - } else { - ftdm_log(FTDM_LOG_CRIT, "No event handler found for event %d.\n", event->e); - } - } - - return FTDM_SUCCESS; -} - -int lpwrap_run_pri(struct lpwrap_pri *spri) -{ - int ret = 0; - - while (!(spri->flags & LPWRAP_PRI_ABORT)) { - ret = lpwrap_run_pri_once(spri); - if (ret) { - ftdm_log(FTDM_LOG_ERROR, "Error = %d, [%s]\n", - ret, strerror(errno)); - spri->errs++; - } else { - spri->errs = 0; - } - if (!ftdm_running()) - break; - if (spri->errs >= LPWRAP_MAX_ERRORS) { - ftdm_log(FTDM_LOG_CRIT, "Too many errors on span, restarting\n"); - spri->errs = 0; - break; - } - } - return ret; -} - -int lpwrap_stop_pri(struct lpwrap_pri *spri) -{ - spri->flags |= LPWRAP_PRI_ABORT; - return FTDM_SUCCESS; -} - -int lpwrap_destroy_pri(struct lpwrap_pri *spri) -{ - if (spri->timer_mutex) - ftdm_mutex_destroy(&spri->timer_mutex); - return FTDM_SUCCESS; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.h b/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.h deleted file mode 100644 index 89708da270..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2009-2012, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _LPWRAP_PRI_H -#define _LPWRAP_PRI_H -#include -#include - - -#define LPWRAP_MAX_CHAN_PER_SPAN 32 - -typedef enum { - LPWRAP_PRI_EVENT_ANY = 0, - LPWRAP_PRI_EVENT_DCHAN_UP = PRI_EVENT_DCHAN_UP, - LPWRAP_PRI_EVENT_DCHAN_DOWN = PRI_EVENT_DCHAN_DOWN, - LPWRAP_PRI_EVENT_RESTART = PRI_EVENT_RESTART, - LPWRAP_PRI_EVENT_CONFIG_ERR = PRI_EVENT_CONFIG_ERR, - LPWRAP_PRI_EVENT_RING = PRI_EVENT_RING, - LPWRAP_PRI_EVENT_HANGUP = PRI_EVENT_HANGUP, - LPWRAP_PRI_EVENT_RINGING = PRI_EVENT_RINGING, - LPWRAP_PRI_EVENT_ANSWER = PRI_EVENT_ANSWER, - LPWRAP_PRI_EVENT_HANGUP_ACK = PRI_EVENT_HANGUP_ACK, - LPWRAP_PRI_EVENT_RESTART_ACK = PRI_EVENT_RESTART_ACK, -#ifdef PRI_EVENT_FACILITY - LPWRAP_PRI_EVENT_FACILITY = PRI_EVENT_FACILITY, -#else - LPWRAP_PRI_EVENT_FACILITY = PRI_EVENT_FACNAME, -#endif - LPWRAP_PRI_EVENT_INFO_RECEIVED = PRI_EVENT_INFO_RECEIVED, - LPWRAP_PRI_EVENT_PROCEEDING = PRI_EVENT_PROCEEDING, - LPWRAP_PRI_EVENT_SETUP_ACK = PRI_EVENT_SETUP_ACK, - LPWRAP_PRI_EVENT_HANGUP_REQ = PRI_EVENT_HANGUP_REQ, - LPWRAP_PRI_EVENT_NOTIFY = PRI_EVENT_NOTIFY, - LPWRAP_PRI_EVENT_PROGRESS = PRI_EVENT_PROGRESS, - LPWRAP_PRI_EVENT_KEYPAD_DIGIT = PRI_EVENT_KEYPAD_DIGIT, - LPWRAP_PRI_EVENT_IO_FAIL = 19, - - /* don't touch */ - LPWRAP_PRI_EVENT_MAX -} lpwrap_pri_event_t; - -typedef enum { - LPWRAP_PRI_NETWORK = PRI_NETWORK, - LPWRAP_PRI_CPE = PRI_CPE -} lpwrap_pri_node_t; - -typedef enum { - LPWRAP_PRI_SWITCH_UNKNOWN = PRI_SWITCH_UNKNOWN, - LPWRAP_PRI_SWITCH_NI2 = PRI_SWITCH_NI2, - LPWRAP_PRI_SWITCH_DMS100 = PRI_SWITCH_DMS100, - LPWRAP_PRI_SWITCH_LUCENT5E = PRI_SWITCH_LUCENT5E, - LPWRAP_PRI_SWITCH_ATT4ESS = PRI_SWITCH_ATT4ESS, - LPWRAP_PRI_SWITCH_EUROISDN_E1 = PRI_SWITCH_EUROISDN_E1, - LPWRAP_PRI_SWITCH_EUROISDN_T1 = PRI_SWITCH_EUROISDN_T1, - LPWRAP_PRI_SWITCH_NI1 = PRI_SWITCH_NI1, - LPWRAP_PRI_SWITCH_GR303_EOC = PRI_SWITCH_GR303_EOC, - LPWRAP_PRI_SWITCH_GR303_TMC = PRI_SWITCH_GR303_TMC, - LPWRAP_PRI_SWITCH_QSIG = PRI_SWITCH_QSIG, - - /* don't touch */ - LPWRAP_PRI_SWITCH_MAX -} lpwrap_pri_switch_t; - -typedef enum { - LPWRAP_PRI_READY = (1 << 0), - LPWRAP_PRI_ABORT = (1 << 1) -} lpwrap_pri_flag_t; - -struct lpwrap_pri; -struct lpwrap_timer; - -typedef int (*timeout_handler)(struct lpwrap_pri *, struct lpwrap_timer *); -typedef int (*event_handler)(struct lpwrap_pri *, lpwrap_pri_event_t, pri_event *); -typedef int (*loop_handler)(struct lpwrap_pri *); - -struct lpwrap_pri { - struct pri *pri; - ftdm_span_t *span; - ftdm_channel_t *dchan; - unsigned int flags; - void *private_info; - event_handler eventmap[LPWRAP_PRI_EVENT_MAX]; - loop_handler on_loop; - int errs; - struct lpwrap_timer *timer_list; - ftdm_mutex_t *timer_mutex; -}; - -typedef struct lpwrap_pri lpwrap_pri_t; - -struct lpwrap_pri_event_list { - int event_id; - int pri_event; - const char *name; -}; - -struct lpwrap_timer { - struct lpwrap_timer *next; - ftdm_time_t timeout; - timeout_handler callback; -}; - -int lpwrap_start_timer(struct lpwrap_pri *spri, struct lpwrap_timer *timer, const uint32_t timeout_ms, timeout_handler callback); -int lpwrap_stop_timer(struct lpwrap_pri *spri, struct lpwrap_timer *timer); - -#define LPWRAP_MAP_PRI_EVENT(spri, event, func) spri.eventmap[event] = func; -const char *lpwrap_pri_event_str(lpwrap_pri_event_t event_id); - -int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int debug); -int lpwrap_destroy_pri(struct lpwrap_pri *spri); -int lpwrap_run_pri_once(struct lpwrap_pri *spri); -int lpwrap_run_pri(struct lpwrap_pri *spri); -int lpwrap_stop_pri(struct lpwrap_pri *spri); -#endif diff --git a/libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c b/libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c deleted file mode 100644 index 4909595a0b..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c +++ /dev/null @@ -1,2837 +0,0 @@ -/** - * mISDN HW interface - * - * Copyright (c) 2011, Stefan Knoblich - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * NOTE: This is intended as a Layer 1 interface only, signaling - * is handled by other modules (e.g. ftmod_libpri or ftmod_isdn). - */ -/* - * TODO: - * - Use a fifo and PH_DATA_CNF for b-channel write polling (drop timerfd) - * - * - Disable L1 idle deactivation on BRI PTMP with IMGL1HOLD ioctl(? optional) - * - * - Add hfcsusb specific state + flag defines and try to do something useful with - * it in misdn_handle_mph_information_ind(). - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* this is how it should have been... -#ifdef HAVE_FREETDM_FREETDM_H -#include -#else -#include -#endif -*/ -/* ... and this is how it is */ -#include - -#include - -/* - * mISDNcompat.h replaces these with references to an extern int, - * which is exported by libmisdn... unset them and use the official - * AF ID "34" - */ -#undef PF_ISDN -#undef AF_ISDN -#define AF_ISDN 34 -#define PF_ISDN AF_ISDN - -//#define MISDN_DEBUG_EVENTS -//#define MISDN_DEBUG_IO - -#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) - -typedef enum { - MISDN_CAPS_NONE = 0, - - /* D-Channel */ - MISDN_CAPS_PRI = (1 << 0), - MISDN_CAPS_BRI = (1 << 1), - MISDN_CAPS_UP0 = (1 << 2), - MISDN_CAPS_NT = (1 << 3), - MISDN_CAPS_TE = (1 << 4), - - /* B-Channel */ - MISDN_CAPS_RAW = (1 << 10), - MISDN_CAPS_HDLC = (1 << 11), -} misdn_capability_flags_t; - -#define MISDN_IS_BRI(x) (x & MISDN_CAPS_BRI) -#define MISDN_IS_PRI(x) (x & MISDN_CAPS_PRI) - -#define MISDN_IS_TE(x) (x & MISDN_CAPS_TE) -#define MISDN_IS_NT(x) (x & MISDN_CAPS_NT) - -#define MISDN_IS_RAW(x) (x & MISDN_CAPS_RAW) -#define MISDN_IS_HDLC(x) (x & MISDN_CAPS_HDLC) - -#define MISDN_MSG_DATA(x) ((void *)((unsigned char *)(x) + MISDN_HEADER_LEN)) - -const static struct { - const int id; - const char *name; -} misdn_event_types[] = { -#define MISDN_EVENT_TYPE(x) { x, #x } - MISDN_EVENT_TYPE(PH_DATA_REQ), - MISDN_EVENT_TYPE(PH_DATA_IND), - MISDN_EVENT_TYPE(PH_DATA_CNF), - MISDN_EVENT_TYPE(PH_DATA_E_IND), - MISDN_EVENT_TYPE(PH_CONTROL_REQ), - MISDN_EVENT_TYPE(PH_CONTROL_IND), - MISDN_EVENT_TYPE(PH_CONTROL_CNF), - MISDN_EVENT_TYPE(PH_ACTIVATE_REQ), - MISDN_EVENT_TYPE(PH_ACTIVATE_IND), - MISDN_EVENT_TYPE(PH_ACTIVATE_CNF), - MISDN_EVENT_TYPE(PH_DEACTIVATE_REQ), - MISDN_EVENT_TYPE(PH_DEACTIVATE_IND), - MISDN_EVENT_TYPE(PH_DEACTIVATE_CNF), - MISDN_EVENT_TYPE(MPH_ACTIVATE_REQ), - MISDN_EVENT_TYPE(MPH_ACTIVATE_IND), - MISDN_EVENT_TYPE(MPH_DEACTIVATE_REQ), - MISDN_EVENT_TYPE(MPH_DEACTIVATE_IND), - MISDN_EVENT_TYPE(MPH_INFORMATION_REQ), - MISDN_EVENT_TYPE(MPH_INFORMATION_IND), -#undef MISDN_EVENT_TYPE -}; - -static const char *misdn_event2str(const int event) -{ - int x; - - for (x = 0; x < ftdm_array_len(misdn_event_types); x++) { - if (event == misdn_event_types[x].id) - return misdn_event_types[x].name; - } - return "unknown"; -} - - -const static struct { - const int id; - const char *name; -} misdn_control_types[] = { -#define MISDN_CONTROL_TYPE(x) { x, #x } - MISDN_CONTROL_TYPE(DTMF_HFC_COEF), - MISDN_CONTROL_TYPE(DSP_CONF_JOIN), - MISDN_CONTROL_TYPE(DSP_CONF_SPLIT), - MISDN_CONTROL_TYPE(DSP_RECEIVE_OFF), - MISDN_CONTROL_TYPE(DSP_RECEIVE_ON), - MISDN_CONTROL_TYPE(DSP_ECHO_ON), - MISDN_CONTROL_TYPE(DSP_ECHO_OFF), - MISDN_CONTROL_TYPE(DSP_MIX_ON), - MISDN_CONTROL_TYPE(DSP_MIX_OFF), - MISDN_CONTROL_TYPE(DSP_DELAY), - MISDN_CONTROL_TYPE(DSP_JITTER), - MISDN_CONTROL_TYPE(DSP_TXDATA_ON), - MISDN_CONTROL_TYPE(DSP_TXDATA_OFF), - MISDN_CONTROL_TYPE(DSP_TX_DEJITTER), - MISDN_CONTROL_TYPE(DSP_TX_DEJ_OFF), - MISDN_CONTROL_TYPE(DSP_TONE_PATT_ON), - MISDN_CONTROL_TYPE(DSP_TONE_PATT_OFF), - MISDN_CONTROL_TYPE(DSP_VOL_CHANGE_TX), - MISDN_CONTROL_TYPE(DSP_VOL_CHANGE_RX), - MISDN_CONTROL_TYPE(DSP_BF_ENABLE_KEY), - MISDN_CONTROL_TYPE(DSP_BF_DISABLE), - MISDN_CONTROL_TYPE(DSP_BF_ACCEPT), - MISDN_CONTROL_TYPE(DSP_BF_REJECT), - MISDN_CONTROL_TYPE(DSP_PIPELINE_CFG), - MISDN_CONTROL_TYPE(HFC_VOL_CHANGE_TX), - MISDN_CONTROL_TYPE(HFC_VOL_CHANGE_RX), - MISDN_CONTROL_TYPE(HFC_SPL_LOOP_ON), - MISDN_CONTROL_TYPE(HFC_SPL_LOOP_OFF), -#undef MISDN_CONTROL_TYPE -}; - -static const char *misdn_control2str(const int ctrl) -{ - int x; - - for (x = 0; x < ftdm_array_len(misdn_control_types); x++) { - if (ctrl == misdn_control_types[x].id) - return misdn_control_types[x].name; - } - return "unknown"; -} - - -/*********************************************************************************** - * mISDN <-> FreeTDM audio conversion - ***********************************************************************************/ - -/* - * Code used to generate table values taken from - * Linux Call Router (LCR) http://www.linux-call-router.de/ - * - * chan_lcr.c:3488 ff., load_module() - */ -static const unsigned char conv_audio_tbl[256] = { - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, - 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, - 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, - 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, - 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, - 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, - 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, - 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, - 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, - 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, - 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, - 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, - 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, - 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, - 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, - 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, -}; - -/* Convert ISDN_P_B_RAW audio data to/from a-/u-law */ -static inline void misdn_convert_audio_bits(char *buf, int buflen) -{ - int i; - - for (i = 0; i < buflen; i++) { - buf[i] = conv_audio_tbl[(unsigned char)buf[i]]; - } -} - - -/*********************************************************************************** - * mISDN <-> FreeTDM data structures - ***********************************************************************************/ - -typedef enum { - MISDN_CMD_NONE = 0, - MISDN_CMD_STOP, /*!< Stop the I/O thread */ -} misdn_cmd_t; - -struct misdn_command { - misdn_cmd_t type; -/* union { } cmd; */ /*!< Command-specific parameters */ -}; - -enum { - MISDN_SPAN_NONE = 0, - MISDN_SPAN_RUNNING = (1 << 0), - MISDN_SPAN_STOPPED = (1 << 1) -}; - -struct misdn_span_private { - int flags; - int running; - - int event_pipe_in; - int event_pipe_out; - - /* event conditional */ - pthread_mutex_t event_cond_mutex; - pthread_cond_t event_cond; - - /* start / stop feedback */ - pthread_mutex_t ctrl_cond_mutex; - pthread_cond_t ctrl_cond; -}; - -struct misdn_event_queue; - -struct misdn_chan_private { - /* */ - int debugfd; - int active; - - /* hw addr of channel */ - struct sockaddr_mISDN addr; - - /* audio tx pipe (= socketpair ends) */ - int tx_audio_pipe_in; - int tx_audio_pipe_out; - int rx_audio_pipe_in; - int rx_audio_pipe_out; - - /* counters */ - unsigned long tx_cnt; - unsigned long tx_ack_cnt; - unsigned long rx_cnt; - unsigned long slip_rx_cnt; - unsigned long slip_tx_cnt; - - unsigned long tx_pipe_wr_bytes; /*!< Number of bytes written into tx audio pipe */ - unsigned long tx_pipe_rd_bytes; /*!< Number of bytes read from tx audio pipe */ - unsigned long tx_miss_bytes; /*!< Number of bytes missing in short reads from tx audio pipe */ - unsigned long tx_lost_bytes; /*!< Number of bytes lost in short writes to the mISDN B-Channel */ - unsigned long tx_sent_bytes; /*!< Number of bytes successfully sent to the mISDN B-Channel */ - unsigned long tx_pipe_under_cnt; /*!< Number of tx audio pipe underflows */ - unsigned long tx_pipe_over_cnt; /*!< Number of tx audio pipe overflows */ - - struct misdn_event_queue *events; -}; - -#define ftdm_chan_io_private(x) ((x)->io_data) -#define ftdm_span_io_private(x) ((x)->io_data) - -static ftdm_status_t misdn_handle_incoming(ftdm_channel_t *ftdmchan, const char *rbuf, const int size); -static int misdn_handle_mph_information_ind(ftdm_channel_t *chan, const struct mISDNhead *hh, const void *data, const int data_len); - -static const char *ftdm_channel_get_type_str(const ftdm_channel_t *chan) -{ - return ftdm_chan_type2str(ftdm_channel_get_type(chan)); -} - -/*********************************************************************************** - * mISDN interface functions - ***********************************************************************************/ - -/* - * Event Queue - */ -#define MISDN_EVENTS_MAX 8 - -struct misdn_event { - int id; -}; - -struct misdn_event_queue { - int read_pos; - int write_pos; - pthread_mutex_t mutex; - - struct misdn_event events[MISDN_EVENTS_MAX]; -}; - -/** - * Initialize event queue - */ -static ftdm_status_t misdn_event_queue_create(struct misdn_event_queue **queue) -{ - struct misdn_event_queue *tmp = NULL; - - if (!queue) - return FTDM_FAIL; - - tmp = calloc(1, sizeof(*tmp)); - if (!tmp) - return FTDM_FAIL; - - pthread_mutex_init(&tmp->mutex, NULL); - - *queue = tmp; - return FTDM_SUCCESS; -} - -/** - * Destroy event queue - */ -static ftdm_status_t misdn_event_queue_destroy(struct misdn_event_queue **queue) -{ - if (!queue || !*queue) - return FTDM_FAIL; - - pthread_mutex_destroy(&(*queue)->mutex); - ftdm_safe_free(*queue); - *queue = NULL; - - return FTDM_SUCCESS; -} - -static ftdm_status_t misdn_event_queue_reset(struct misdn_event_queue *queue) -{ - if (!queue) - return FTDM_FAIL; - pthread_mutex_lock(&queue->mutex); - - memset(queue->events, 0, sizeof(queue->events)); - queue->read_pos = queue->write_pos = 0; - - pthread_mutex_unlock(&queue->mutex); - return FTDM_SUCCESS; -} - -static ftdm_bool_t misdn_event_queue_has_data(const struct misdn_event_queue *queue) -{ - if (!queue) - return FTDM_FALSE; - - return (queue->read_pos == queue->write_pos) ? FTDM_FALSE : FTDM_TRUE; -} - -static struct misdn_event *misdn_event_queue_pop(struct misdn_event_queue *queue) -{ - struct misdn_event *evt = NULL; - int next_idx = 0; - - if (!queue) - return NULL; - - pthread_mutex_lock(&queue->mutex); - - next_idx = (queue->read_pos + 1) % MISDN_EVENTS_MAX; - - if (queue->read_pos == queue->write_pos) { -#ifdef MISDN_DEBUG_EVENTS - ftdm_log(FTDM_LOG_DEBUG, "mISDN queue %p: empty\n", queue); -#endif - pthread_mutex_unlock(&queue->mutex); - return NULL; - } - -#ifdef MISDN_DEBUG_EVENTS - ftdm_log(FTDM_LOG_DEBUG, "mISDN queue %p: read event (read_pos: %d, write_pos: %d, next_write_pos: %d)\n", - queue, queue->read_pos, queue->write_pos, next_idx); -#endif - /* update read pos */ - evt = &queue->events[queue->read_pos]; - queue->read_pos = next_idx; - - pthread_mutex_unlock(&queue->mutex); - return evt; -} - -static ftdm_status_t misdn_event_queue_push(struct misdn_event_queue *queue, struct misdn_event *evt) -{ - int next_idx = 0; - - if (!queue || !evt) - return FTDM_FAIL; - - pthread_mutex_lock(&queue->mutex); - - next_idx = (queue->write_pos + 1) % MISDN_EVENTS_MAX; - - if (next_idx == queue->read_pos) { -#ifdef MISDN_DEBUG_EVENTS - ftdm_log(FTDM_LOG_DEBUG, "mISDN queue %p: full\n", queue); -#endif - pthread_mutex_unlock(&queue->mutex); - return FTDM_FAIL; - } - -#ifdef MISDN_DEBUG_EVENTS - ftdm_log(FTDM_LOG_DEBUG, "mISDN queue %p: wrote event (read_pos: %d, write_pos: %d, next_write_pos: %d)\n", - queue, queue->read_pos, queue->write_pos, next_idx); -#endif - memcpy(&queue->events[queue->write_pos], evt, sizeof(*evt)); - queue->write_pos = next_idx; - - pthread_mutex_unlock(&queue->mutex); - return FTDM_SUCCESS; -} - -#if 0 /* unused for now */ -static void misdn_event_queue_print_info(const struct misdn_event_queue *queue) -{ - ftdm_log(FTDM_LOG_DEBUG, "Queue %p\n\tread idx: %d\n\twrite idx: %d\n", queue, - queue->read_pos, queue->write_pos); -} -#endif - -/*********************************************************************************** - * mISDN helper functions - ***********************************************************************************/ - -#define MISDN_PH_ACTIVATE_TIMEOUT_MS 10000 -#define MISDN_MPH_INFORMATION_TIMEOUT_MS 3000 - -static inline void ts_add_msec(struct timespec *a, int msec) -{ - a->tv_sec += (msec / 1000); - a->tv_nsec += (msec % 1000) * 1000000; - if (a->tv_nsec >= 1000000000) { - a->tv_sec++; - a->tv_nsec -= 1000000000; - } -} - -static inline int ts_sub_msec(struct timespec *a, struct timespec *b) -{ - int msec = 0; - msec += (a->tv_sec - b->tv_sec) * 1000; - msec += (a->tv_nsec - b->tv_nsec) / 1000000; - return msec; -} - -static inline int ts_after(struct timespec *a, struct timespec *b) -{ - if (a->tv_sec > b->tv_sec) return 1; - if (a->tv_sec == b->tv_sec && a->tv_nsec > b->tv_nsec) return 1; - return 0; -} - -static inline int ts_before(struct timespec *a, struct timespec *b) -{ - if (a->tv_sec < b->tv_sec) return 1; - if (a->tv_sec == b->tv_sec && a->tv_nsec < b->tv_nsec) return 1; - return 0; -} - -/* - * Asynchronous channel (de-)activation - */ -static ftdm_status_t _misdn_toggle_channel_nowait(ftdm_channel_t *chan, int activate) -{ - struct misdn_chan_private *priv = ftdm_chan_io_private(chan); - char buf[MAX_DATA_MEM] = { 0 }; - struct mISDNhead *hh = (struct mISDNhead *) buf; - int retval; - - /* NOTE: sending PH_DEACTIVATE_REQ to closed b-channels kills the d-channel (hfcsusb)... */ - if ((activate && priv->active) || (!activate && !priv->active)) - return FTDM_SUCCESS; - - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN sending %s request\n", - (activate) ? "activation" : "deactivation"); - - /* prepare + send request primitive */ - hh->prim = (activate) ? PH_ACTIVATE_REQ : PH_DEACTIVATE_REQ; - hh->id = MISDN_ID_ANY; - - if ((retval = sendto(chan->sockfd, hh, sizeof(*hh), 0, NULL, 0)) < sizeof(*hh)) { - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN failed to send activation request: %s\n", - strerror(errno)); - return FTDM_FAIL; - } - - return FTDM_SUCCESS; -} - -static ftdm_status_t misdn_activate_channel_nowait(ftdm_channel_t *chan) -{ - return _misdn_toggle_channel_nowait(chan, 1); -} - -static ftdm_status_t misdn_deactivate_channel_nowait(ftdm_channel_t *chan) -{ - return _misdn_toggle_channel_nowait(chan, 0); -} - -/* - * Synchronous channel (de-)activation - */ -static ftdm_status_t _misdn_toggle_channel(ftdm_channel_t *chan, int activate) -{ - struct misdn_chan_private *priv = ftdm_chan_io_private(chan); - char buf[MAX_DATA_MEM] = { 0 }; - struct mISDNhead *hh = (struct mISDNhead *) buf; - struct timespec abstimeout; - int req = 0, resp = 0, ms_left = MISDN_PH_ACTIVATE_TIMEOUT_MS; - int retval; - - /* NOTE: sending PH_DEACTIVATE_REQ to closed b-channels kills the d-channel (hfcsusb)... */ - if ((activate && priv->active) || (!activate && !priv->active)) - return FTDM_SUCCESS; - - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN sending %s request\n", - (activate) ? "activation" : "deactivation"); - - /* prepare + send request primitive */ - req = (activate) ? PH_ACTIVATE_REQ : PH_DEACTIVATE_REQ; - hh->prim = req; - hh->id = MISDN_ID_ANY; - - if ((retval = sendto(chan->sockfd, hh, sizeof(*hh), 0, NULL, 0)) < sizeof(*hh)) { - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN failed to send activation request: %s\n", - strerror(errno)); - return FTDM_FAIL; - } - - clock_gettime(CLOCK_MONOTONIC, &abstimeout); - ts_add_msec(&abstimeout, ms_left); - - /* wait for answer */ - while (1) { - struct timespec now; - struct pollfd pfd; - - pfd.fd = chan->sockfd; - pfd.events = POLLIN | POLLPRI; - pfd.revents = 0; - - switch ((retval = poll(&pfd, 1, ms_left))) { - case 0: /* timeout */ - goto out; - case -1: /* error */ - if (!(retval == EAGAIN || retval == EINTR)) { - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN polling for activation confirmation failed: %s\n", - strerror(errno)); - return FTDM_FAIL; - } - break; - default: /* read data */ - break; - } - - if (pfd.revents & (POLLIN | POLLPRI)) { - /* handle incoming message */ - if ((retval = recvfrom(chan->sockfd, buf, sizeof(buf), 0, NULL, NULL)) <= 0) { - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN failed to receive possible answer for %s request: %s\n", - (activate) ? "activation" : "deactivation", strerror(errno)); - return FTDM_FAIL; - } -#ifdef MISDN_DEBUG_EVENTS - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN got event '%s (%#x)', id %#x, while waiting for %s confirmation on %c-channel\n", - misdn_event2str(hh->prim), hh->prim, hh->id, (activate) ? "activation" : "deactivation", - ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_B ? 'B' : 'D'); -#endif - switch (hh->prim) { - case PH_ACTIVATE_IND: - case PH_ACTIVATE_CNF: - resp = hh->prim; - priv->active = 1; - if (activate) goto out; - break; - case PH_DEACTIVATE_CNF: - case PH_DEACTIVATE_IND: - resp = hh->prim; - priv->active = 0; - if (!activate) goto out; - break; - case PH_ACTIVATE_REQ: /* REQ echo, ignore */ - case PH_DEACTIVATE_REQ: - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN got '%s' echo while waiting for %s confirmation (id: %#x)\n", - misdn_event2str(hh->prim), (activate) ? "activation" : "deactivation", hh->id); - break; - case MPH_INFORMATION_IND: - misdn_handle_mph_information_ind(chan, hh, MISDN_MSG_DATA(buf), retval - MISDN_HEADER_LEN); - break; - case PH_DATA_IND: /* ignore */ - case PH_DATA_CNF: /* ignore */ - break; - default: /* other messages, ignore */ - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN ignoring event '%s (%#x)', id %#x, while waiting for %s confirmation\n", - misdn_event2str(hh->prim), hh->prim, hh->id, (activate) ? "activation" : "deactivation"); - break; - } - } - - /* check timeout */ - clock_gettime(CLOCK_MONOTONIC, &now); - - if (ts_after(&now, &abstimeout) || (ms_left = ts_sub_msec(&abstimeout, &now)) <= 0) - goto out; - } -out: - if (resp == 0) { - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN timeout waiting for %s confirmation\n", - (activate) ? "activation" : "deactivation"); - return FTDM_TIMEOUT; - } - if ((req == PH_ACTIVATE_REQ && !(resp == PH_ACTIVATE_CNF || resp == PH_ACTIVATE_IND)) || - (req == PH_DEACTIVATE_REQ && !(resp == PH_DEACTIVATE_CNF || resp == PH_DEACTIVATE_IND))) { - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN received '%s' while waiting for %s\n", - misdn_event2str(resp), (activate) ? "activation" : "deactivation"); - return FTDM_FAIL; - } - - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN received %s confirmation\n", - (activate) ? "activation" : "deactivation"); - return FTDM_SUCCESS; -} - -static ftdm_status_t misdn_activate_channel(ftdm_channel_t *chan) -{ - return _misdn_toggle_channel(chan, 1); -} - -static ftdm_status_t misdn_deactivate_channel(ftdm_channel_t *chan) -{ - return _misdn_toggle_channel(chan, 0); -} - - -#if 0 /* unused for now */ -static ftdm_status_t misdn_get_ph_info(ftdm_channel_t *chan, struct ph_info *info) -{ - char buf[MAX_DATA_MEM] = { 0 }; - struct mISDNhead *hh; - struct timespec abstimeout; - int req = 0, resp = 0, ms_left = MISDN_MPH_INFORMATION_TIMEOUT_MS; - int retval; - - /* prepare + send request primitive */ - req = MPH_INFORMATION_REQ; - hh = (struct mISDNhead *)buf; - hh->prim = req; - hh->id = MISDN_ID_ANY; - - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN sending %s request\n", - misdn_event2str(req)); - - if ((retval = sendto(chan->sockfd, &hh, sizeof(hh), 0, NULL, 0)) < sizeof(hh)) { - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN failed to send %s request: %s\n", - misdn_event2str(req), strerror(errno)); - return FTDM_FAIL; - } - - clock_gettime(CLOCK_MONOTONIC, &abstimeout); - ts_add_msec(&abstimeout, ms_left); - - /* wait for answer */ - while (1) { - struct timespec now; - struct pollfd pfd; - - pfd.fd = chan->sockfd; - pfd.events = POLLIN /* | POLLPRI */; - pfd.revents = 0; - - switch ((retval = poll(&pfd, 1, ms_left))) { - case 0: /* timeout */ - goto out; - case -1: /* error */ - if (!(retval == EAGAIN || retval == EINTR)) { - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN polling for %s answer failed: %s\n", - misdn_event2str(req), strerror(errno)); - return FTDM_FAIL; - } - break; - default: /* read data */ - break; - } - - if (pfd.revents & (POLLIN | POLLPRI)) { - /* handle incoming message */ - if ((retval = recvfrom(chan->sockfd, buf, sizeof(buf), 0, NULL, NULL)) <= 0) { - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN failed to receive possible answer for %s request: %s\n", - misdn_event2str(req), strerror(errno)); - return FTDM_FAIL; - } -#ifdef MISDN_DEBUG_EVENTS - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN got event '%s' while waiting for %s answer\n", - misdn_event2str(hh->prim), misdn_event2str(req)); -#endif - switch (hh->prim) { - case MPH_INFORMATION_IND: /* success */ - if (retval < MISDN_HEADER_LEN + sizeof(*info)) { - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN answer for %s is too short\n", - misdn_event2str(req)); - return FTDM_FAIL; - } - resp = hh->prim; - /* TODO */ - goto out; - case MPH_INFORMATION_REQ: /* REQ echo, ignore */ - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN got '%s' echo while waiting for %s answer\n", - misdn_event2str(hh->prim), misdn_event2str(req)); - break; - default: /* other messages, ignore */ - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN ignoring event '%s' while waiting for %s answer\n", - misdn_event2str(hh->prim), misdn_event2str(req)); - break; - } - } - - /* check timeout */ - clock_gettime(CLOCK_MONOTONIC, &now); - - if (ts_after(&now, &abstimeout) || (ms_left = ts_sub_msec(&abstimeout, &now)) <= 0) - goto out; - } -out: - if (resp == 0) { - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN timeout waiting for %s answer\n", - misdn_event2str(req)); - return FTDM_TIMEOUT; - } - - return FTDM_SUCCESS; -} -#endif - -static int misdn_handle_ph_control_ind(ftdm_channel_t *chan, const struct mISDNhead *hh, const void *data, const int data_len) -{ - ftdm_unused_arg(data); - - ftdm_log_chan(chan, FTDM_LOG_DEBUG, - "PH_CONTROL_IND:\n" - "\tMessage:\t%s (%#x)\n" - "\tPayload:\t%d\n", - misdn_control2str(hh->id), hh->id, data_len); - - switch (hh->id) { - case DTMF_HFC_COEF: - break; - default: - break; - } - - return FTDM_SUCCESS; -} - -/* - * TE/NT state names - * taken from linux-3.2.1/drivers/isdn/hardware/mISDN/hfcsusb.h - */ -static const char *misdn_layer1_te_states[] = { - "TE F0 - Reset", - "TE F1 - Reset", - "TE F2 - Sensing", - "TE F3 - Deactivated", - "TE F4 - Awaiting signal", - "TE F5 - Identifying input", - "TE F6 - Synchronized", - "TE F7 - Activated", - "TE F8 - Lost framing", -}; - -static const char *misdn_layer1_nt_states[] = { - "NT G0 - Reset", - "NT G1 - Deactive", - "NT G2 - Pending activation", - "NT G3 - Active", - "NT G4 - Pending deactivation", -}; - -static const char *misdn_hw_state_name(const int proto, const int id) -{ - if (IS_ISDN_P_TE(proto)) { - if (id < 0 || id >= ftdm_array_len(misdn_layer1_te_states)) - return NULL; - return misdn_layer1_te_states[id]; - } - else if (IS_ISDN_P_NT(proto)) { - if (id < 0 || id >= ftdm_array_len(misdn_layer1_nt_states)) - return NULL; - return misdn_layer1_nt_states[id]; - } - return NULL; -} - - -static const struct misdn_hw_flag { - const unsigned int flag; - const char *name; -} misdn_hw_flags[] = { -#define MISDN_HW_FLAG(v,n) { v, #n } - MISDN_HW_FLAG(0, FLG_TX_BUSY), - MISDN_HW_FLAG(1, FLG_TX_NEXT), - MISDN_HW_FLAG(2, FLG_L1_BUSY), - MISDN_HW_FLAG(3, FLG_L2_ACTIVATED), - MISDN_HW_FLAG(5, FLG_OPEN), - MISDN_HW_FLAG(6, FLG_ACTIVE), - MISDN_HW_FLAG(7, FLG_BUSY_TIMER), - MISDN_HW_FLAG(8, FLG_DCHANNEL), - MISDN_HW_FLAG(9, FLG_BCHANNEL), - MISDN_HW_FLAG(10, FLG_ECHANNEL), - MISDN_HW_FLAG(12, FLG_TRANSPARENT), - MISDN_HW_FLAG(13, FLG_HDLC), - MISDN_HW_FLAG(14, FLG_L2DATA), - MISDN_HW_FLAG(15, FLG_ORIGIN), - MISDN_HW_FLAG(16, FLG_FILLEMPTY), - MISDN_HW_FLAG(17, FLG_ARCOFI_TIMER), - MISDN_HW_FLAG(18, FLG_ARCOFI_ERROR), - MISDN_HW_FLAG(17, FLG_INITIALIZED), - MISDN_HW_FLAG(18, FLG_DLEETX), - MISDN_HW_FLAG(19, FLG_LASTDLE), - MISDN_HW_FLAG(20, FLG_FIRST), - MISDN_HW_FLAG(21, FLG_LASTDATA), - MISDN_HW_FLAG(22, FLG_NMD_DATA), - MISDN_HW_FLAG(23, FLG_FTI_RUN), - MISDN_HW_FLAG(24, FLG_LL_OK), - MISDN_HW_FLAG(25, FLG_LL_CONN), - MISDN_HW_FLAG(26, FLG_DTMFSEND), - MISDN_HW_FLAG(30, FLG_RECVQUEUE), - MISDN_HW_FLAG(31, FLG_PHCHANGE), -#undef MISDN_HW_FLAG -}; - -static const char *misdn_hw_print_flags(unsigned int flags, char *buf, int buflen) -{ - int i; - - buf[0] = '\0'; - for (i = 0; i < ftdm_array_len(misdn_hw_flags); i++) { - if ((1 << misdn_hw_flags[i].flag) & flags) { - strncat(buf, misdn_hw_flags[i].name, buflen); - flags &= ~(1 << misdn_hw_flags[i].flag); - if (!flags) break; - strncat(buf, ",", buflen); - } - } - return buf; -} - -static int misdn_handle_mph_information_ind(ftdm_channel_t *chan, const struct mISDNhead *hh, const void *data, const int data_len) -{ - struct misdn_chan_private *priv = ftdm_chan_io_private(chan); - - ftdm_unused_arg(hh); - - /* - * mISDN has some inconsistency issues here. - * - * There are only two drivers that emit MPH_INFORMATION_IND messages, - * hfcsusb and hfcmulti. The former sends a set of ph_info and ph_info_ch structures, - * while the latter just sends an int containing the current L1_SIGNAL_* event id. - * - * The flags and state information in the ph_info and ph_info_ch structures - * are defined in kernel internal hw-specific headers (mISDNhw.h). - * - * Use the payload size to guess the type of message. - */ - if (data_len >= sizeof(struct ph_info)) { - /* complete port status, hfcsusb sends this */ - struct ph_info *info = (struct ph_info *)data; - struct ph_info_ch *bch_info = NULL; - char tmp[1024] = { 0 }; - - if (data_len < (sizeof(*info) + info->dch.num_bch * sizeof(*bch_info))) { - ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "mISDN MPH_INFORMATION_IND message is too short\n"); - return FTDM_FAIL; - } - bch_info = &info->bch[0]; - - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN port state:\n\tD-Chan proto:\t%hu\n\tD-Chan state:\t%s (%hu)\n\tD-Chan flags:\t%#"FTDM_XINT64_FMT"\n\t\t\t%-70s\n", - info->dch.ch.protocol, - misdn_hw_state_name(info->dch.ch.protocol, info->dch.state), info->dch.state, - (uint64_t)info->dch.ch.Flags, - misdn_hw_print_flags(info->dch.ch.Flags, tmp, sizeof(tmp) - 1)); - - /* TODO: try to translate this to a usable set of alarm flags */ - - } else if (data_len == sizeof(int)) { - /* alarm info, sent by hfcmulti */ - int value = *(int *)data; - int alarm_flags = chan->alarm_flags; - - if (data_len < sizeof(value)) { - ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "mISDN MPH_INFORMATION_IND message is too short\n"); - return FTDM_FAIL; - } - - switch (value) { - case L1_SIGNAL_LOS_ON: - alarm_flags |= FTDM_ALARM_RED; - break; - case L1_SIGNAL_LOS_OFF: - alarm_flags &= ~FTDM_ALARM_RED; - break; - case L1_SIGNAL_AIS_ON: - alarm_flags |= FTDM_ALARM_AIS; - break; - case L1_SIGNAL_AIS_OFF: - alarm_flags &= ~FTDM_ALARM_AIS; - break; - case L1_SIGNAL_RDI_ON: - alarm_flags |= FTDM_ALARM_YELLOW; - break; - case L1_SIGNAL_RDI_OFF: - alarm_flags &= ~FTDM_ALARM_YELLOW; - break; - case L1_SIGNAL_SLIP_RX: - priv->slip_rx_cnt++; - break; - case L1_SIGNAL_SLIP_TX: - priv->slip_tx_cnt++; - break; - default: - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN unknown MPH_INFORMATION_IND signal: %#04x\n", - value); - return FTDM_FAIL; - } - - /* check whether alarm status has changed, update channel flags if it has */ - if ((value = (alarm_flags ^ chan->alarm_flags))) { - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN alarm flags have changed %#x -> %#x\n", - chan->alarm_flags, alarm_flags); - chan->alarm_flags ^= value; - } - } else { - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN sent MPH_INFORMATION_IND message with unknown size %d\n", - data_len); - return FTDM_FAIL; - } - - return FTDM_SUCCESS; -} - -/*********************************************************************************** - * mISDN <-> FreeTDM interface functions - ***********************************************************************************/ - -static struct misdn_globals { - int sockfd; -} globals; - -/** - * \brief Open channel - * \param ftdmchan FreeTDM channel to open - */ -static FIO_OPEN_FUNCTION(misdn_open) -{ - struct misdn_chan_private *chan_priv = ftdm_chan_io_private(ftdmchan); - ftdm_span_t *span = ftdm_channel_get_span(ftdmchan); - struct misdn_span_private *span_priv = ftdm_span_io_private(span); - ftdm_status_t ret = 0; - - assert(chan_priv); - assert(span_priv); - - if (chan_priv->active) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "mISDN channel is already open, skipping activation\n"); - return FTDM_SUCCESS; - } - - /* flush all events */ - misdn_event_queue_reset(chan_priv->events); - - /* - * Send activation request - */ - ret = misdn_activate_channel(ftdmchan); - if (ret != FTDM_SUCCESS) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to activate channel (socket: %d)\n", - ftdmchan->sockfd); - /* - * Ignore error, ftdm_channel_open() does not correctly handle return FTDM_FAIL cases. - * We will try to activate the channel later. - */ - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "mISDN channel activation request sent\n"); - - switch (ftdmchan->type) { - case FTDM_CHAN_TYPE_B: - case FTDM_CHAN_TYPE_DQ921: - chan_priv->active = 1; - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "mISDN invalid channel type '%s'\n", - ftdm_channel_get_type_str(ftdmchan)); - break; - } - } - return FTDM_SUCCESS; -} - -/** - * \brief Close channel - * \param ftdmchan FreeTDM channel to close - */ -static FIO_CLOSE_FUNCTION(misdn_close) -{ - struct misdn_chan_private *chan_priv = ftdm_chan_io_private(ftdmchan); - ftdm_status_t ret = 0; - - assert(chan_priv); - - ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "mISDN trying to close %c-channel\n", - ftdm_channel_get_type(ftdmchan) == FTDM_CHAN_TYPE_B ? 'B' : 'D'); - - if (chan_priv->active) { - - if (ftdm_channel_get_type(ftdmchan) == FTDM_CHAN_TYPE_B) { - ret = misdn_deactivate_channel(ftdmchan); - } else { - /* Don't wait for D-Channel deactivation */ - ret = misdn_deactivate_channel_nowait(ftdmchan); - } - - if (ret != FTDM_SUCCESS) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to deactivate %c-channel\n", - ftdm_channel_get_type(ftdmchan) == FTDM_CHAN_TYPE_B ? 'B' : 'D'); - /* Ignore error, channel might be closed already */ - } else { - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "mISDN %c-channel deactivated\n", - ftdm_channel_get_type(ftdmchan) == FTDM_CHAN_TYPE_B ? 'B' : 'D'); - } - - ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "mISDN tx stats: wr: %lu, rd: %lu, tx: %lu, tx-lost: %lu, tx-miss: %lu, tx-under#: %lu, tx-over#: %lu\n", - chan_priv->tx_pipe_wr_bytes, chan_priv->tx_pipe_rd_bytes, - chan_priv->tx_sent_bytes, chan_priv->tx_lost_bytes, chan_priv->tx_miss_bytes, - chan_priv->tx_pipe_over_cnt, chan_priv->tx_pipe_under_cnt); - - chan_priv->active = 0; - } - - return FTDM_SUCCESS; -} - -/** - * \brief Execute command - * \param ftdmchan FreeTDM channel - * \param command Command to execute - * \param obj Additional command data - */ -static FIO_COMMAND_FUNCTION(misdn_command) -{ - switch (command) { - case FTDM_COMMAND_NOOP: - break; - case FTDM_COMMAND_SET_INTERVAL: -// case FTDM_COMMAND_GET_INTERVAL: - case FTDM_COMMAND_SET_CODEC: - case FTDM_COMMAND_GET_CODEC: - case FTDM_COMMAND_SET_NATIVE_CODEC: - case FTDM_COMMAND_GET_NATIVE_CODEC: - case FTDM_COMMAND_ENABLE_DTMF_DETECT: - case FTDM_COMMAND_DISABLE_DTMF_DETECT: - case FTDM_COMMAND_SEND_DTMF: - case FTDM_COMMAND_SET_DTMF_ON_PERIOD: - case FTDM_COMMAND_GET_DTMF_ON_PERIOD: - case FTDM_COMMAND_SET_DTMF_OFF_PERIOD: - case FTDM_COMMAND_GET_DTMF_OFF_PERIOD: - case FTDM_COMMAND_SET_RX_GAIN: /* DSP_VOL_CHANGE_RX / HFC_VOL_CHANGE_RX */ - case FTDM_COMMAND_GET_RX_GAIN: - case FTDM_COMMAND_SET_TX_GAIN: /* DSP_VOL_CHANGE_TX / HFC_VOL_CHANGE_TX */ - case FTDM_COMMAND_GET_TX_GAIN: - case FTDM_COMMAND_FLUSH_TX_BUFFERS: - case FTDM_COMMAND_FLUSH_RX_BUFFERS: - case FTDM_COMMAND_FLUSH_BUFFERS: - case FTDM_COMMAND_FLUSH_IOSTATS: - case FTDM_COMMAND_SET_PRE_BUFFER_SIZE: - case FTDM_COMMAND_SET_LINK_STATUS: - case FTDM_COMMAND_GET_LINK_STATUS: - case FTDM_COMMAND_SET_RX_QUEUE_SIZE: - case FTDM_COMMAND_SET_TX_QUEUE_SIZE: - case FTDM_COMMAND_START_MF_PLAYBACK: - case FTDM_COMMAND_STOP_MF_PLAYBACK: - case FTDM_COMMAND_GET_IOSTATS: - case FTDM_COMMAND_SWITCH_IOSTATS: - /* Supported by mISDN */ - case FTDM_COMMAND_ENABLE_ECHOCANCEL: /* DSP_ECHO_ON */ - case FTDM_COMMAND_DISABLE_ECHOCANCEL: /* DSP_ECHO_OFF */ - case FTDM_COMMAND_ENABLE_LOOP: - case FTDM_COMMAND_DISABLE_LOOP: - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Received unimplemented command: %d\n", - command); - break; - - case FTDM_COMMAND_GET_INTERVAL: - FTDM_COMMAND_OBJ_INT = ftdm_channel_get_io_interval(ftdmchan); - ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Interval %d ms\n", - ftdm_channel_get_io_interval(ftdmchan)); - break; - - default: - ftdm_log(FTDM_LOG_ERROR, "Unknown command %d\n", command); - } - return FTDM_SUCCESS; -} - - -/** - * \brief Wait for new data - * \param ftdmchan FreeTDM channel to wait on - * \param flags Wait flags - * \param to Timeout - */ -static FIO_WAIT_FUNCTION(misdn_wait) -{ - struct misdn_chan_private *chan_priv = ftdm_chan_io_private(ftdmchan); - struct pollfd pfds[2]; - int nr_fds = 0; - int retval; - - memset(pfds, 0, sizeof(pfds)); - - switch (ftdm_channel_get_type(ftdmchan)) { - case FTDM_CHAN_TYPE_B: - if (*flags & FTDM_WRITE) { - pfds[nr_fds].fd = chan_priv->tx_audio_pipe_in; - pfds[nr_fds].events = POLLOUT; - nr_fds++; - } - if (*flags & FTDM_READ) { - pfds[nr_fds].fd = chan_priv->rx_audio_pipe_out; - pfds[nr_fds].events = POLLIN; - nr_fds++; - } -/* if (*flags & (FTDM_READ | FTDM_EVENTS)) { - pfds[nr_fds].fd = ftdmchan->sockfd; - pfds[nr_fds].events |= (*flags & FTDM_READ) ? POLLIN : 0; - pfds[nr_fds].events |= (*flags & FTDM_EVENTS) ? POLLPRI : 0; - nr_fds++; - } -*/ - break; - default: - if (*flags & FTDM_READ) - pfds[0].events |= POLLIN; - if (*flags & FTDM_WRITE) - pfds[0].events |= POLLOUT; - if (*flags & FTDM_EVENTS) - pfds[0].events |= POLLPRI; - pfds[0].fd = ftdmchan->sockfd; - nr_fds++; - break; - } - - *flags = FTDM_NO_FLAGS; - - if (!(pfds[0].events || pfds[1].events)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "mISDN poll(): no flags set!\n"); - return FTDM_SUCCESS; - } - - if ((retval = poll(pfds, nr_fds, to)) < 0) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "mISDN poll() failed: %s\n", - strerror(errno)); - return FTDM_FAIL; - } - if (retval == 0) - return FTDM_TIMEOUT; - - switch (ftdm_channel_get_type(ftdmchan)) { - case FTDM_CHAN_TYPE_B: - if ((pfds[0].revents & POLLOUT) || (pfds[1].revents & POLLOUT)) - *flags |= FTDM_WRITE; - if ((pfds[0].revents & POLLIN) || (pfds[1].revents & POLLIN)) - *flags |= FTDM_READ; - if ((pfds[0].revents & POLLPRI) || (pfds[1].revents & POLLPRI)) - *flags |= FTDM_EVENTS; - break; - default: - if (pfds[0].revents & POLLIN) - *flags |= FTDM_READ; - if (pfds[0].revents & POLLOUT) - *flags |= FTDM_WRITE; - if (pfds[0].revents & POLLPRI) - *flags |= FTDM_EVENTS; - break; - } - return FTDM_SUCCESS; -} - - -/** - * Handle incoming mISDN message on d-channel - * \param[in] ftdmchan - * \param[in] msg_buf - * \param[in] msg_len - * \internal - */ -static ftdm_status_t misdn_handle_incoming(ftdm_channel_t *ftdmchan, const char *msg_buf, const int msg_len) -{ - struct misdn_chan_private *priv = ftdm_chan_io_private(ftdmchan); - struct mISDNhead *hh = (struct mISDNhead *)msg_buf; - const char *data = msg_buf + sizeof(*hh); - int data_len = msg_len - sizeof(*hh); - - assert(msg_buf); - assert(priv); - - if (msg_len < sizeof(*hh)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "mISDN message to small (%d < %"FTDM_SIZE_FMT" bytes)\n", - msg_len, sizeof(*hh)); - return FTDM_FAIL; - } - -#ifdef MISDN_DEBUG_EVENTS - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "mISDN %c-channel received '%s' message (id: 0x%x, additional data: %d bytes)\n", - ftdm_channel_get_type(ftdmchan) == FTDM_CHAN_TYPE_B ? 'B' : 'D', misdn_event2str(hh->prim), hh->id, data_len); -#endif - - switch (hh->prim) { - /* data events */ - case PH_DATA_CNF: /* TX: ack */ - priv->tx_ack_cnt++; - break; - case PH_DATA_REQ: /* TX: request echo (ignore) */ - break; - case PH_DATA_E_IND: /* RX: e-channel data received (monitoring?) */ - break; - - /* control requests */ - case PH_CONTROL_IND: - return misdn_handle_ph_control_ind(ftdmchan, hh, data, data_len); - case PH_CONTROL_REQ: - case PH_CONTROL_CNF: - break; - - /* information */ - case MPH_INFORMATION_IND: - return misdn_handle_mph_information_ind(ftdmchan, hh, data, data_len); - - /* channel de-/activation */ - case PH_ACTIVATE_REQ: /* Echoed requests, ignore */ - case PH_DEACTIVATE_REQ: - break; - case PH_ACTIVATE_IND: - case PH_DEACTIVATE_IND: { - /* other events, enqueue and let misdn_event_next handle it */ - struct misdn_span_private *span_priv = ftdm_span_io_private(ftdmchan->span); - struct misdn_event evt = { 0 }; - evt.id = hh->prim; - - misdn_event_queue_push(priv->events, &evt); - - /* wake possible readers */ - pthread_cond_signal(&span_priv->event_cond); - break; - } - default: /* error? */ - ftdm_log(FTDM_LOG_DEBUG, "mISDN channel %d:%d received unknown event %d\n", - ftdm_channel_get_span_id(ftdmchan), ftdm_channel_get_id(ftdmchan), hh->prim); - break; - } - return FTDM_SUCCESS; -} - -/** - * \brief Read data - * \param ftdmchan FreeTDM channel - * \param data Buffer for data - * \param datalen Number of bytes to read (contains bytes read after return) - */ -static FIO_READ_FUNCTION(misdn_read) -{ - struct misdn_chan_private *priv = ftdm_chan_io_private(ftdmchan); - char rbuf[MAX_DATA_MEM] = { 0 }; - struct mISDNhead *hh = (struct mISDNhead *)rbuf; - int bytes = *datalen; - int retval; - int maxretry = 10; - - /* nothing read yet */ - *datalen = 0; - - /* - * try to read all messages, as long as we haven't received a PH_DATA_IND one - * we'll get a lot of "mISDN_send: error -12" message in dmesg otherwise - * (= b-channel receive queue overflowing) - */ - switch (ftdm_channel_get_type(ftdmchan)) { - case FTDM_CHAN_TYPE_DQ921: { - while (maxretry--) { - struct sockaddr_mISDN addr; - socklen_t addrlen = sizeof(addr); - - if ((retval = recvfrom(ftdmchan->sockfd, rbuf, sizeof(rbuf), 0, (struct sockaddr *)&addr, &addrlen)) < 0) { - if (errno == EWOULDBLOCK || errno == EAGAIN) break; - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "mISDN failed to receive incoming message: %s\n", - strerror(errno)); - return FTDM_FAIL; - } - - if (retval < MISDN_HEADER_LEN) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "mISDN received message too small\n"); - return FTDM_FAIL; - } - - if (hh->prim == PH_DATA_IND) { - *datalen = ftdm_clamp(retval - MISDN_HEADER_LEN, 0, bytes); - - if (*datalen <= 0) - continue; - - /* - * Copy data into ouput buffer (excluding the mISDN message header) - * NOTE: audio data needs to be converted to a-law / u-law! - */ - memcpy(data, rbuf + MISDN_HEADER_LEN, *datalen); - return FTDM_SUCCESS; - } else { - *datalen = 0; - /* event */ - misdn_handle_incoming(ftdmchan, rbuf, retval); - } - } - break; - } - case FTDM_CHAN_TYPE_B: { - if (!priv->active) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "mISDN ignoring read on closed b-channel\n"); - return FTDM_SUCCESS; - } - - if ((retval = read(priv->rx_audio_pipe_out, data, bytes)) < 0) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "mISDN failed to read audio data from rx pipe: %s\n", - strerror(errno)); - return FTDM_FAIL; - } - *datalen = retval; - break; - } - default: - break; - } - return FTDM_SUCCESS; -} - -/** - * \brief Write data - * \param ftdmchan FreeTDM channel - * \param data Buffer for data - * \param datalen Number of bytes to write (contains bytes written after return) - */ -static FIO_WRITE_FUNCTION(misdn_write) -{ - struct misdn_chan_private *priv = ftdm_chan_io_private(ftdmchan); - char wbuf[MAX_DATA_MEM]; - struct mISDNhead *hh = (struct mISDNhead *)wbuf; - int size = *datalen; - int retval = 0; - ftdm_wait_flag_t wflags; - - assert(priv); - - /* ignore empty writes */ - if (*datalen <= 0) - return FTDM_SUCCESS; - -#ifdef MISDN_DEBUG_IO - { - char hbuf[MAX_DATA_MEM] = { 0 }; - print_hex_bytes(data, *datalen, hbuf, sizeof(hbuf)); - ftdm_log(FTDM_LOG_DEBUG, "mISDN write data: %s\n", hbuf); - } -#endif - *datalen = 0; - - switch (ftdm_channel_get_type(ftdmchan)) { - case FTDM_CHAN_TYPE_B: - /* - * Check state, send activation request (async) if channel is not open - */ - if (!priv->active) { - misdn_activate_channel_nowait(ftdmchan); - return FTDM_SUCCESS; /* eat data */ - } - /* - * Write to audio pipe, misdn_read() will pull - * from there as needed and send it to the b-channel - * - * NOTE: can't use blocking I/O here since both parts are serviced - * from the same thread - */ - if ((retval = write(priv->tx_audio_pipe_in, data, size)) < 0) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "mISDN channel audio pipe write error [wr: %lu, rd: %lu: tx: %lu, tx-under#: %lu, tx-over#: %lu]: %s\n", - priv->tx_pipe_wr_bytes, priv->tx_pipe_rd_bytes, priv->tx_sent_bytes, - priv->tx_pipe_under_cnt, priv->tx_pipe_over_cnt, strerror(errno)); - return FTDM_FAIL; - } else if (retval < size) { - priv->tx_pipe_over_cnt++; - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "mISDN channel audio pipe short write [wr: %lu, rd: %lu: tx: %lu, tx-under#: %lu, tx-over#: %lu], expected: %d, written: %d\n", - priv->tx_pipe_wr_bytes, priv->tx_pipe_rd_bytes, priv->tx_sent_bytes, - priv->tx_pipe_under_cnt, priv->tx_pipe_over_cnt, size, retval); - } - ACCESS_ONCE(priv->tx_pipe_wr_bytes) += retval; - *datalen = retval; - break; - default: - hh->prim = PH_DATA_REQ; - hh->id = MISDN_ID_ANY; - - /* Avoid buffer overflow */ - size = ftdm_min(size, MAX_DATA_MEM - MISDN_HEADER_LEN); - - memcpy(wbuf + MISDN_HEADER_LEN, data, size); - size += MISDN_HEADER_LEN; - - /* - * Check state, send activation request (sync) if channel is not open - */ - if (!priv->active) { - retval = misdn_activate_channel(ftdmchan); - if (retval) { - *datalen = 0; - return FTDM_FAIL; - } - } - - /* wait for channel to get ready */ - wflags = FTDM_WRITE; - retval = misdn_wait(ftdmchan, &wflags, 20); - if (retval) { - /* timeout, io error */ - *datalen = 0; - return FTDM_FAIL; - } - -#ifdef MISDN_DEBUG_IO - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "mISDN writing %d bytes to channel socket %d [dev.ch: %d.%d]\n", - size, ftdmchan->sockfd, priv->addr.dev, priv->addr.channel); -#endif - - if ((retval = sendto(ftdmchan->sockfd, wbuf, size, 0, NULL, 0)) < size) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "mISDN channel socket write error: %s\n", - strerror(errno)); - return FTDM_FAIL; - } - *datalen = retval; - break; - } - - priv->tx_cnt++; - return FTDM_SUCCESS; -} - -/** - * Carefully choosen size for socket send/recv buffers - * larger values will add more latency, while lower values will cause deadlocks - * (see misdn_span_run() comments below for an explanation) - */ -#define SOCKETPAIR_BUFFER_SIZE 3072 - -static ftdm_status_t misdn_open_range(ftdm_span_t *span, ftdm_chan_type_t type, struct mISDN_devinfo *devinfo, int start, int end) -{ - int num_configured = 0; - int d_protocol, d_channel; - int x; - - ftdm_log(FTDM_LOG_DEBUG, "mISDN configuring card:range %d:%d->%d\n", - devinfo->id, start, end); - - switch (ftdm_span_get_trunk_type(span)) { - case FTDM_TRUNK_E1: - d_protocol = ftdm_span_get_trunk_mode(span) == FTDM_TRUNK_MODE_NET ? ISDN_P_NT_E1 : ISDN_P_TE_E1; - d_channel = 16; - break; - case FTDM_TRUNK_BRI: - case FTDM_TRUNK_BRI_PTMP: - d_protocol = ftdm_span_get_trunk_mode(span) == FTDM_TRUNK_MODE_NET ? ISDN_P_NT_S0 : ISDN_P_TE_S0; - d_channel = 0; - break; - default: - ftdm_log(FTDM_LOG_ERROR, "Unsupported span type %s\n", - ftdm_span_get_trunk_type_str(span)); - return FTDM_FAIL; - } - - for (x = start; x <= end; x++) { - struct misdn_chan_private *priv; - struct sockaddr_mISDN addr; - ftdm_channel_t *ftdmchan = NULL; - ftdm_socket_t sockfd = -1; - - ftdm_log(FTDM_LOG_DEBUG, "mISDN configuring card:channel => %d:%d\n", - devinfo->id, x); - - memset(&addr, 0, sizeof(addr)); - addr.family = AF_ISDN; - addr.dev = devinfo->id; - - switch (type) { - case FTDM_CHAN_TYPE_DQ931: /* unsupported */ - ftdm_log(FTDM_LOG_ERROR, "Unsupported channel type '%s'\n", - ftdm_chan_type2str(type)); - return FTDM_FAIL; - - case FTDM_CHAN_TYPE_DQ921: - /* No NT-mode support, since we have no idea which mode we should run in at this point */ - sockfd = socket(PF_ISDN, SOCK_DGRAM, d_protocol); - addr.channel = d_channel; /* 0 for S0 and 16 for E1 */ - break; - - case FTDM_CHAN_TYPE_B: - if (!test_channelmap(x, devinfo->channelmap)) { - ftdm_log(FTDM_LOG_ERROR, "Invalid B-Channel specified: %d\n", x); - return FTDM_FAIL; - } - sockfd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW); - addr.channel = x; - break; - - default: - ftdm_log(FTDM_LOG_ERROR, "Invalid/unsupported channel type '%s' (%d)\n", - ftdm_chan_type2str(type), type); - return FTDM_FAIL; - } - - if (sockfd < 0) { - ftdm_log(FTDM_LOG_ERROR, "Failed to open socket: %s\n", strerror(errno)); - return FTDM_FAIL; - } - - ftdm_log(FTDM_LOG_DEBUG, "mISDN opened socket (on chan:dev => %d:%d): %d\n", - addr.dev, addr.channel, sockfd); - - /* Set mISDN channel socket non-blocking */ - if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) { - ftdm_log(FTDM_LOG_ERROR, "mISDN Failed to set socket fd to non-blocking: %s\n", - strerror(errno)); - close(sockfd); - return FTDM_FAIL; - } - - /* - * Bind socket to card:channel - */ - if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - ftdm_log(FTDM_LOG_ERROR, "Failed to bind mISDN socket [%d:%d]: %s\n", - addr.dev, x, strerror(errno)); - close(sockfd); - return FTDM_FAIL; - } - - /* - * Add channel to span - */ - if (ftdm_span_add_channel(span, sockfd, type, &ftdmchan) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Failed to add mISDN ftdmchan to span\n"); - close(sockfd); - return FTDM_FAIL; - } - - priv = calloc(1, sizeof(*priv)); - if (!priv) { - ftdm_log(FTDM_LOG_ERROR, "mISDN failed to allocate channel private data\n"); - close(sockfd); - return FTDM_FAIL; - } - ftdm_chan_io_private(ftdmchan) = priv; - - priv->addr = addr; - priv->debugfd = -1; - - /* - * Create event queue - */ - misdn_event_queue_create(&priv->events); - - ftdmchan->rate = 8000; - ftdmchan->physical_span_id = devinfo->id; - ftdmchan->physical_chan_id = x; - - if (ftdmchan->type == FTDM_CHAN_TYPE_B) { - int pipefd[2] = { -1, -1 }; - - ftdmchan->packet_len = 30 /* ms */ * (ftdmchan->rate / 1000); - ftdmchan->effective_interval = ftdmchan->native_interval = ftdmchan->packet_len / 8; - ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_ALAW; - -// ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_INTERVAL); - -#ifdef USE_PIPE - /* - * Create audio tx pipe, use non-blocking I/O to avoid deadlock since both ends - * are used from the same thread - */ - if (pipe2(pipefd, 0 | O_NONBLOCK) < 0) { - ftdm_log(FTDM_LOG_ERROR, "Failed to create mISDN audio tx pipe [%d:%d]: %s\n", - addr.dev, x, strerror(errno)); - close(sockfd); - return FTDM_FAIL; - } - priv->tx_audio_pipe_in = pipefd[1]; - priv->tx_audio_pipe_out = pipefd[0]; - -#if 1 || defined(HAVE_F_SETPIPE_SZ) - if (fcntl(priv->tx_audio_pipe_in, F_SETPIPE_SZ, 4096) < 0) { - ftdm_log(FTDM_LOG_WARNING, "Failed to set mISDN audio tx pipe size [%d:%d]: %s\n", - addr.dev, x, strerror(errno)); - } -#endif - /* - * Create audio rx pipe, use non-blocking I/O to avoid deadlock since both ends - * are used from the same thread - */ - if (pipe2(pipefd, 0 | O_NONBLOCK) < 0) { - ftdm_log(FTDM_LOG_ERROR, "Failed to create mISDN audio rx pipe [%d:%d]: %s\n", - addr.dev, x, strerror(errno)); - close(sockfd); - return FTDM_FAIL; - } - priv->rx_audio_pipe_in = pipefd[1]; - priv->rx_audio_pipe_out = pipefd[0]; - -#if 1 || defined(HAVE_F_SETPIPE_SZ) - if (fcntl(priv->rx_audio_pipe_in, F_SETPIPE_SZ, 4096) < 0) { - ftdm_log(FTDM_LOG_WARNING, "Failed to set mISDN audio rx pipe size [%d:%d]: %s\n", - addr.dev, x, strerror(errno)); - } -#endif -#else /* !USE_PIPE */ - /* - * Use a socket pair for audio rx/tx, allows for more fine-grained control - * of latency (= amounts of data in buffers) - */ - if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) { - ftdm_log(FTDM_LOG_ERROR, "Failed to create mISDN audio socket pair [%d:%d]: %s\n", - addr.dev, x, strerror(errno)); - close(sockfd); - return FTDM_FAIL; - } else { - int opt = SOCKETPAIR_BUFFER_SIZE; - socklen_t optlen = sizeof(opt); - - if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) < 0) { - ftdm_log(FTDM_LOG_ERROR, "mISDN Failed to set socket pair fd[0] to non-blocking: %s\n", - strerror(errno)); - close(sockfd); - close(pipefd[0]); - close(pipefd[1]); - return FTDM_FAIL; - } - if (fcntl(pipefd[1], F_SETFL, O_NONBLOCK) < 0) { - ftdm_log(FTDM_LOG_ERROR, "mISDN Failed to set socket pair fd[1] to non-blocking: %s\n", - strerror(errno)); - close(sockfd); - close(pipefd[0]); - close(pipefd[1]); - return FTDM_FAIL; - } - - /* - * Set RX/TX buffer sizes on each end of the socket pair - */ - if (setsockopt(pipefd[0], SOL_SOCKET, SO_RCVBUF, &opt, optlen) < 0) { - ftdm_log(FTDM_LOG_WARNING, "mISDN Failed to set socket pair fd[0] RCVBUF: %s\n", - strerror(errno)); - } - if (setsockopt(pipefd[0], SOL_SOCKET, SO_SNDBUF, &opt, optlen) < 0) { - ftdm_log(FTDM_LOG_WARNING, "mISDN Failed to set socket pair fd[0] SNDBUF: %s\n", - strerror(errno)); - } - if (setsockopt(pipefd[1], SOL_SOCKET, SO_RCVBUF, &opt, optlen) < 0) { - ftdm_log(FTDM_LOG_WARNING, "mISDN Failed to set socket pair fd[1] RCVBUF: %s\n", - strerror(errno)); - } - if (setsockopt(pipefd[1], SOL_SOCKET, SO_SNDBUF, &opt, optlen) < 0) { - ftdm_log(FTDM_LOG_WARNING, "mISDN Failed to set socket pair fd[1] SNDBUF: %s\n", - strerror(errno)); - } - - priv->rx_audio_pipe_in = pipefd[1]; - priv->rx_audio_pipe_out = pipefd[0]; - - priv->tx_audio_pipe_in = pipefd[0]; - priv->tx_audio_pipe_out = pipefd[1]; - } -#endif - } else { - /* early activate D-Channel */ - misdn_activate_channel(ftdmchan); - ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_NONE; - } - num_configured++; - } - - return num_configured; -} - -static int misdn_find_device(const char *name, int nr_devices, struct mISDN_devinfo *info) -{ - struct mISDN_devinfo devinfo; - char *endp = NULL; - int port_id = -1; - int i; - - port_id = strtoul(name, &endp, 10); - if (endp == name || errno == EINVAL) - port_id = -1; - if (port_id < 0 || port_id >= nr_devices) - port_id = -1; - - for (i = 0; i < nr_devices; i++) { - memset(&devinfo, 0, sizeof(devinfo)); - devinfo.id = i; - - if (ioctl(globals.sockfd, IMGETDEVINFO, &devinfo) < 0) { - ftdm_log(FTDM_LOG_ERROR, "mISDN unable to get device %d info: %s\n", - devinfo.id, strerror(errno)); - return FTDM_FAIL; - } - if (devinfo.id == port_id) - break; - if (strlen(devinfo.name) <= 0) - continue; - if (!strcasecmp(devinfo.name, name)) - break; - } - if (i == nr_devices) - return FTDM_FAIL; - - if (info) *info = devinfo; - return FTDM_SUCCESS; -} - -#define MISDN_PH_TE_PROTOCOLS(x) \ - ((x) & ((1 << ISDN_P_TE_S0) | (1 << ISDN_P_TE_E1) | (1 << ISDN_P_TE_UP0))) -#define MISDN_PH_NT_PROTOCOLS(x) \ - ((x) & ((1 << ISDN_P_NT_S0) | (1 << ISDN_P_NT_E1) | (1 << ISDN_P_NT_UP0))) - -/** - * \brief Configure/open span ftmod_misdn settings - */ -static FIO_CONFIGURE_SPAN_FUNCTION(misdn_configure_span) -{ - struct misdn_span_private *span_priv = ftdm_span_io_private(span); - struct mISDN_devinfo devinfo; - int range_start = 0, range_end = 0; - int nr_ports = 0, nr_items = 0; - int res = 0, i; - char *chan_str, *ptr; - char *data = strdup(str); - char *item_list[10]; - - ftdm_unused_arg(name); - ftdm_unused_arg(number); - - /* only these are supported */ - switch (ftdm_span_get_trunk_type(span)) { - case FTDM_TRUNK_E1: - case FTDM_TRUNK_BRI: - case FTDM_TRUNK_BRI_PTMP: - break; - default: - ftdm_log(FTDM_LOG_ERROR, "Unsupported span type %s\n", - ftdm_span_get_trunk_type_str(span)); - return FTDM_FAIL; - } - - /* get port count */ - if (ioctl(globals.sockfd, IMGETCOUNT, &nr_ports) < 0) { - ftdm_log(FTDM_LOG_ERROR, "mISDN unable to get port count: %s\n", - strerror(errno)); - goto error; - } - if (nr_ports <= 0) { - ftdm_log(FTDM_LOG_ERROR, "No mISDN devices found\n"); - goto error; - } - - /* split configuration string into port ID and channel list */ - if (!(chan_str = strchr(data, ':'))) { - ftdm_log(FTDM_LOG_ERROR, "Invalid configuration string: %s\nExpected format :[-]\n", str); - goto error; - } - *chan_str++ = '\0'; - - /* lookup port id, by number first, then by name */ - if (misdn_find_device(data, nr_ports, &devinfo) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "No such mISDN device/port: %s\n", - data); - goto error; - } - if (devinfo.nrbchan == 0 || devinfo.channelmap == 0) { - ftdm_log(FTDM_LOG_ERROR, "mISDN device '%s' has no b-channels\n", - data); - goto error; - } - if (!MISDN_PH_TE_PROTOCOLS(devinfo.Dprotocols)) { - ftdm_log(FTDM_LOG_ERROR, "mISDN device '%s' does not support any ISDN TE modes\n", - data); - goto error; - } - - /* allocate span private */ - if (!span_priv) { - int pipe[2] = { -1, -1 }; - - /* - * Not perfect, there should be something like span_create too - */ - span_priv = calloc(1, sizeof(*span_priv)); - if (!span_priv) { - ftdm_log(FTDM_LOG_ERROR, "mISDN failed to allocate span private data\n"); - return FTDM_FAIL; - } - ftdm_span_io_private(span) = span_priv; - - /* init event condition */ - pthread_cond_init(&span_priv->event_cond, NULL); - pthread_mutex_init(&span_priv->event_cond_mutex, NULL); - - /* init control condition */ - pthread_cond_init(&span_priv->ctrl_cond, NULL); - pthread_mutex_init(&span_priv->ctrl_cond_mutex, NULL); - - /* create event pipe */ - if (pipe2(pipe, O_CLOEXEC) < 0) { - ftdm_log(FTDM_LOG_ERROR, "mISDN failed to create event pipe: %s\n", - strerror(errno)); - return FTDM_FAIL; - } - span_priv->event_pipe_in = pipe[0]; - span_priv->event_pipe_out = pipe[1]; - } - - /* split channel list by ',' */ - nr_items = ftdm_separate_string(chan_str, ',', item_list, ftdm_array_len(item_list)); - - for (i = 0; i < nr_items; i++) { - /* */ - if (!(ptr = strchr(item_list[i], '-'))) { - /* single channel */ - range_start = atoi(item_list[i]); - range_end = range_start; - } else { - *ptr++ = '\0'; - /* channel range */ - range_start = atoi(item_list[i]); - range_end = atoi(ptr); - } - - /* check if channel range/id is valid */ - if (range_start <= 0 || range_end <= 0 || range_end < range_start) { - ftdm_log(FTDM_LOG_ERROR, "Invalid configuration string: %s\n", - item_list[i]); - goto error; - } - - /* add range to span */ - res = misdn_open_range(span, type, &devinfo, range_start, range_end); - if (res <= 0) { - ftdm_log(FTDM_LOG_ERROR, "mISDN failed to configure channel(s)\n"); - goto error; - } - } - - ftdm_safe_free(data); - return res; -error: - ftdm_span_io_private(span) = NULL; - ftdm_safe_free(span_priv); - ftdm_safe_free(data); - return res; -} - -/** - * \brief Configure global ftmod_misdn settings - */ -static FIO_CONFIGURE_FUNCTION(misdn_configure) -{ - ftdm_unused_arg(category); - ftdm_unused_arg(var); - ftdm_unused_arg(val); - ftdm_unused_arg(lineno); - return FTDM_SUCCESS; -} - -/** - * \brief Retrieve alarm event information (if any) - * \param ftdmchan FreeTDM channel - */ -static FIO_GET_ALARMS_FUNCTION(misdn_get_alarms) -{ - ftdm_unused_arg(ftdmchan); -#if 0 -/* - Nope, this won't work... - - There's no way to create a separate "control" socket for a device - that can be used to send / receive MPH_INFORMATION_REQ/_IND without - having to care about PH_* messages in between... - - ... well, unless we use our own event loop (= thread) and - add event queues and data fifos, so we can sift all the - messages we get to forward them to the right receiver -*/ - char buf[MAX_DATA_MEM] = { 0 }; - struct sockaddr_mISDN addr; - struct mISDNhead *hh; - struct ph_info *phi = NULL; - struct pollfd pfd; - socklen_t addrlen = sizeof(addr); - int retval; - - /* use the global socket to query alarms */ - ftdm_log(FTDM_LOG_DEBUG, "mISDN getting alarms for channel %d:%d [%d:%d]\n", - ftdm_channel_get_span_id(ftdmchan), ftdm_channel_get_id(ftdmchan), - ftdm_channel_get_ph_span_id(ftdmchan), ftdm_channel_get_ph_id(ftdmchan)); - - memset(&addr, 0, sizeof(addr)); - addr.family = AF_ISDN; - addr.dev = ftdm_channel_get_ph_span_id(ftdmchan) - 1; - addr.channel = ftdm_channel_get_ph_id(ftdmchan) - 1; - - hh = (struct mISDNhead *)buf; - hh->prim = MPH_INFORMATION_REQ; - hh->id = MISDN_ID_ANY; - - /* */ - if ((retval = sendto(span_priv->ctrlsock, hh, sizeof(*hh), 0, (struct sockaddr *)&addr, addrlen)) <= 0) { - ftdm_log(FTDM_LOG_ERROR, "mISDN failed to send '%s' to channel %d:%d: %s\n", - misdn_event2str(hh->prim), ftdm_channel_get_span_id(ftdmchan), - ftdm_channel_get_id(ftdmchan), strerror(errno)); - return FTDM_FAIL; - } - - pfd.fd = span_priv->ctrlsock; - pfd.events = POLLIN /*| POLLPRI*/; - pfd.revents = 0; - - if ((retval = poll(&pfd, 1, -1)) <= 0) { - ftdm_log(FTDM_LOG_ERROR, "mISDN failed to poll for '%s' answer on channel %d:%d: %s\n", - misdn_event2str(hh->prim), ftdm_channel_get_span_id(ftdmchan), - ftdm_channel_get_id(ftdmchan), strerror(errno)); - return FTDM_FAIL; - } - - if (!(pfd.revents & (POLLIN | POLLPRI))) { - ftdm_log(FTDM_LOG_ERROR, "mISDN failed to poll for '%s' answer on channel %d:%d: %s\n", - misdn_event2str(hh->prim), ftdm_channel_get_span_id(ftdmchan), - ftdm_channel_get_id(ftdmchan), "No read/pri flag"); - return FTDM_FAIL; - } - - if ((retval = recvfrom(span_priv->ctrlsock, buf, sizeof(buf), 0, (struct sockaddr *)&addr, &addrlen)) < 0) { - ftdm_log(FTDM_LOG_ERROR, "mISDN failed to receive answer for '%s' on channel %d:%d: %s\n", - misdn_event2str(hh->prim), ftdm_channel_get_span_id(ftdmchan), - ftdm_channel_get_id(ftdmchan), strerror(errno)); - return FTDM_FAIL; - } - if (retval < MISDN_HEADER_LEN) { - ftdm_log(FTDM_LOG_ERROR, "mISDN short read on channel %d:%d\n", - ftdm_channel_get_span_id(ftdmchan), ftdm_channel_get_id(ftdmchan)); - return FTDM_FAIL; - } - - switch (hh->prim) { - case MPH_INFORMATION_IND: - ftdm_log(FTDM_LOG_DEBUG, "mISDN received '%s' on channel %d:%d, size %d bytes\n", - misdn_event2str(hh->prim), ftdm_channel_get_span_id(ftdmchan), - ftdm_channel_get_id(ftdmchan), retval); - break; - default: - ftdm_log(FTDM_LOG_ERROR, "mISDN received unexpected answer '%s' on channel %d:%d: %s\n", - misdn_event2str(hh->prim), ftdm_channel_get_span_id(ftdmchan), - ftdm_channel_get_id(ftdmchan), strerror(errno)); - return FTDM_FAIL; - } -#endif - return FTDM_SUCCESS; -} - - -/** - * \brief Poll for new events - * \param span FreeTDM span - * \param ms Timeout (in ms) - */ -static FIO_SPAN_POLL_EVENT_FUNCTION(misdn_poll_event) -{ - struct misdn_span_private *span_priv = ftdm_span_io_private(span); - struct timespec ts; - int retval = 0, nr_events = 0; - int i; - - ftdm_unused_arg(poll_events); - - for (i = 1; i <= ftdm_span_get_chan_count(span); i++) { - ftdm_channel_t *chan = ftdm_span_get_channel(span, i); - struct misdn_chan_private *chan_priv = ftdm_chan_io_private(chan); - - /* Skip channels that have event processing pending (Avoids event storms) */ - if (ftdm_test_io_flag(chan, FTDM_CHANNEL_IO_EVENT)) - continue; - - if (misdn_event_queue_has_data(chan_priv->events)) { -#ifdef MISDN_DEBUG_EVENTS - ftdm_log(FTDM_LOG_DEBUG, "mISDN channel %d:%d has event(s)\n", - ftdm_channel_get_span_id(chan), ftdm_channel_get_id(chan)); -#endif - ftdm_set_io_flag(chan, FTDM_CHANNEL_IO_EVENT); - chan->last_event_time = ftdm_current_time_in_ms(); - nr_events++; - } - } - if (nr_events) { -#ifdef MISDN_DEBUG_EVENTS - ftdm_log(FTDM_LOG_DEBUG, "mISDN span %d has %d new events pending (pre poll)\n", - ftdm_span_get_id(span), nr_events); -#endif - return FTDM_SUCCESS; - } - - -#ifdef MISDN_DEBUG_EVENTS - ftdm_log(FTDM_LOG_DEBUG, "mISDN span %d has no events pending, polling for new events with %d ms timeout\n", - ftdm_span_get_id(span), ms); -#endif - /* Wait at least 1 ms, max 1 s */ - ms = ftdm_clamp(ms, 1, 1000); - - clock_gettime(CLOCK_REALTIME, &ts); - ts_add_msec(&ts, ms); - - if ((retval = pthread_cond_timedwait(&span_priv->event_cond, &span_priv->event_cond_mutex, &ts))) { - switch (retval) { - case ETIMEDOUT: -#ifdef MISDN_DEBUG_EVENTS - ftdm_log(FTDM_LOG_DEBUG, "mISDN span %d: No events within %d ms\n", - ftdm_span_get_id(span), ms); -#endif - return FTDM_TIMEOUT; - default: - ftdm_log(FTDM_LOG_DEBUG, "mISDN failed to poll for events on span %d: %s\n", - ftdm_span_get_id(span), strerror(retval)); - return FTDM_FAIL; - } - } - -#ifdef MISDN_DEBUG_EVENTS - ftdm_log(FTDM_LOG_DEBUG, "mISDN span %d received new event notification, checking channel event queues\n", - ftdm_span_get_id(span)); -#endif - for (i = 1; i <= ftdm_span_get_chan_count(span); i++) { - ftdm_channel_t *chan = ftdm_span_get_channel(span, i); - struct misdn_chan_private *chan_priv = ftdm_chan_io_private(chan); - - /* Skip channels that have event processing pending (Avoids event storms) */ - if (ftdm_test_io_flag(chan, FTDM_CHANNEL_IO_EVENT)) - continue; - - if (misdn_event_queue_has_data(chan_priv->events)) { - ftdm_set_io_flag(chan, FTDM_CHANNEL_IO_EVENT); - chan->last_event_time = ftdm_current_time_in_ms(); - nr_events++; - } - } - return (nr_events) ? FTDM_SUCCESS : FTDM_TIMEOUT; /* no events? => timeout */ -} - -/** - * Retrieve event from channel - * \param ftdmchan Channel to retrieve event from - * \param event FreeTDM event to return - * \return Success or failure - */ -static FIO_CHANNEL_NEXT_EVENT_FUNCTION(misdn_channel_next_event) -{ - struct misdn_chan_private *chan_priv = ftdm_chan_io_private(ftdmchan); - struct misdn_event *evt = NULL; - ftdm_span_t *span = ftdm_channel_get_span(ftdmchan); - uint32_t event_id = FTDM_OOB_INVALID; - - ftdm_assert(span, "span == NULL"); - - ftdm_clear_io_flag(ftdmchan, FTDM_CHANNEL_IO_EVENT); - - if (!(evt = misdn_event_queue_pop(chan_priv->events))) { -#ifdef MISDN_DEBUG_EVENTS - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "mISDN channel event queue has no events\n"); -#endif - return FTDM_FAIL; - } - -#ifdef MISDN_DEBUG_EVENTS - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Got event '%s' from channel event queue\n", - misdn_event2str(evt->id)); -#endif - /* Convert from misdn event to ftdm */ - switch (evt->id) { - case PH_DEACTIVATE_IND: - event_id = FTDM_OOB_ALARM_TRAP; - ftdmchan->alarm_flags |= FTDM_ALARM_RED; - break; - case PH_ACTIVATE_IND: - event_id = FTDM_OOB_ALARM_CLEAR; - ftdmchan->alarm_flags &= ~FTDM_ALARM_RED; - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Unhandled event id %d (0x%x) %s\n", - evt->id, evt->id, misdn_event2str(evt->id)); - } - - ftdmchan->last_event_time = 0; - span->event_header.e_type = FTDM_EVENT_OOB; - span->event_header.enum_id = event_id; - span->event_header.channel = ftdmchan; - *event = &span->event_header; - return FTDM_SUCCESS; -} - -/** - * \brief Retrieve event - * \param span FreeTDM span - * \param event FreeTDM event - */ -static FIO_SPAN_NEXT_EVENT_FUNCTION(misdn_next_event) -{ - int32_t event_id = FTDM_OOB_INVALID; - int i; - - ftdm_log(FTDM_LOG_DEBUG, "Reading next event from span %d\n", - ftdm_span_get_id(span)); - - for (i = 1; i <= ftdm_span_get_chan_count(span); i++) { - ftdm_channel_t *chan = ftdm_span_get_channel(span, i); - struct misdn_chan_private *chan_priv = ftdm_chan_io_private(chan); - struct misdn_event *evt = NULL; - - ftdm_clear_io_flag(chan, FTDM_CHANNEL_IO_EVENT); - - if (!(evt = misdn_event_queue_pop(chan_priv->events))) { -#ifdef MISDN_DEBUG_EVENTS - ftdm_log_chan_msg(chan, FTDM_LOG_DEBUG, "mISDN channel event queue has no events\n"); -#endif - continue; - } - -#ifdef MISDN_DEBUG_EVENTS - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Got event '%s' from channel event queue\n", - misdn_event2str(evt->id)); -#endif - switch (evt->id) { - case PH_DEACTIVATE_IND: - event_id = FTDM_OOB_ALARM_TRAP; - chan->alarm_flags |= FTDM_ALARM_RED; - break; - case PH_ACTIVATE_IND: - event_id = FTDM_OOB_ALARM_CLEAR; - chan->alarm_flags &= ~FTDM_ALARM_RED; - break; - default: - ftdm_log(FTDM_LOG_ERROR, "Unhandled event id %d (0x%x) %s\n", - evt->id, evt->id, misdn_event2str(evt->id)); - continue; - } - - chan->last_event_time = 0; - span->event_header.e_type = FTDM_EVENT_OOB; - span->event_header.enum_id = event_id; - span->event_header.channel = chan; - *event = &span->event_header; - return FTDM_SUCCESS; - } - return FTDM_FAIL; -} - -/** - * \brief Shutdown ftmod_misdn channel - * \param ftdmchan FreeTDM channel - */ -static FIO_CHANNEL_DESTROY_FUNCTION(misdn_channel_destroy) -{ - struct misdn_chan_private *chan_priv = ftdm_chan_io_private(ftdmchan); - assert(chan_priv); - - ftdm_log(FTDM_LOG_DEBUG, "Destroying channel %d:%d\n", - ftdm_channel_get_span_id(ftdmchan), - ftdm_channel_get_id(ftdmchan)); - - if (ftdmchan->sockfd >= 0) { - close(ftdmchan->sockfd); - ftdmchan->sockfd = -1; - } - - /* - * Destroy fifo + event queue - */ - if (chan_priv->events) - misdn_event_queue_destroy(&chan_priv->events); - - ftdm_chan_io_private(ftdmchan) = NULL; - ftdm_safe_free(chan_priv); - - ftdm_log(FTDM_LOG_DEBUG, "mISDN channel %d:%d destroyed\n", - ftdm_channel_get_span_id(ftdmchan), ftdm_channel_get_id(ftdmchan)); - return FTDM_SUCCESS; -} - -/** - * \brief Shutdown ftmod_misdn span - * \param span FreeTDM span - */ -static FIO_SPAN_DESTROY_FUNCTION(misdn_span_destroy) -{ - struct misdn_span_private *span_priv = ftdm_span_io_private(span); - - /* free resources */ - ftdm_span_io_private(span) = NULL; - ftdm_safe_free(span_priv); - - ftdm_log(FTDM_LOG_DEBUG, "mISDN span %d (%s) destroyed\n", - ftdm_span_get_id(span), ftdm_span_get_name(span)); - return FTDM_SUCCESS; -} - - -/** - * Called by misdn_span_run() to handle incoming b-channel events - * \param[in] chan FreeTDM channel object - * \return FTDM_SUCCESS on success, FTDM_* on error - */ -static ftdm_status_t handle_b_channel_event(ftdm_channel_t *chan) -{ - struct misdn_chan_private *priv = ftdm_chan_io_private(chan); - char buf[MAX_DATA_MEM] = { 0 }; - struct mISDNhead *mh = (void *)buf; - int retval, retries = 5; - - do { - /* - * Retry reading multiple times if recvfrom() returns EAGAIN - */ - retval = recvfrom(chan->sockfd, buf, sizeof(buf), 0, NULL, NULL); - if (retval < 0 && errno != EAGAIN) - break; - - } while (retval < 0 && retries-- > 0); - - if (retval < 0) { - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN failed to receive message: %s\n", - strerror(errno)); - return FTDM_FAIL; - } - if (retval < MISDN_HEADER_LEN) { - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN message too short, min.: %d, read: %d\n", - (int)MISDN_HEADER_LEN, retval); - return FTDM_FAIL; - } - - switch (mh->prim) { - case PH_DATA_IND: { - int datalen = retval - MISDN_HEADER_LEN; - char *data = buf + MISDN_HEADER_LEN; - - /* Discard incoming audio if not active */ - if (priv->active) { - /* Convert audio data */ - misdn_convert_audio_bits(data, datalen); - - /* Write audio into receive pipe */ - if ((retval = write(priv->rx_audio_pipe_in, data, datalen)) < 0) { - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN failed to write audio data into rx pipe: %s\n", - strerror(errno)); - return FTDM_FAIL; - } else if (retval < datalen) { - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN short write into rx pipe, written: %d, expected: %d\n", - retval, datalen); - return FTDM_FAIL; - } - } - - /* Get receive buffer usage */ - if (ioctl(priv->tx_audio_pipe_out, FIONREAD, &retval) < 0) { - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN failed to get tx audio buffer usage: %s\n", - strerror(errno)); - return FTDM_FAIL; - } else if (retval < datalen) { -// ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN has not enough bytes in tx audio pipe, available: %d, requested: %d\n", -// retval, datalen); - priv->tx_pipe_under_cnt++; - return FTDM_SUCCESS; - } - -#ifdef MISDN_DEBUG_IO - ftdm_log_chan(chan, FTDM_LOG_INFO, "mISDN tx audio buffer usage: %d\n", - retval); -#endif - - /* Get audio from tx pipe */ - if ((retval = read(priv->tx_audio_pipe_out, data, datalen)) < 0) { - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN failed to read audio data from tx pipe: %s\n", - strerror(errno)); - return FTDM_FAIL; - } else if (retval == 0) { - ftdm_log_chan_msg(chan, FTDM_LOG_NOTICE, "mISDN tx pipe is empty\n"); - priv->tx_pipe_under_cnt++; - return FTDM_SUCCESS; - } else if (retval < datalen) { - ftdm_log_chan(chan, FTDM_LOG_NOTICE, "mISDN short read from tx pipe, read: %d, expected: %d\n", - retval, datalen); - priv->tx_pipe_under_cnt++; - priv->tx_miss_bytes += ftdm_max(0, datalen - retval); - datalen = retval; - } - priv->tx_pipe_rd_bytes += retval; - - if (!priv->active) { - /* discard */ - return FTDM_SUCCESS; - } - - /* Convert audio data */ - misdn_convert_audio_bits(data, datalen); - - /* Write to channel */ - mh->prim = PH_DATA_REQ; - mh->id = 0; - datalen += MISDN_HEADER_LEN; - - if ((retval = write(chan->sockfd, buf, datalen)) < 0) { - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN failed to write audio data into b-channel: %s\n", - strerror(errno)); - return FTDM_FAIL; - } else if (retval < datalen) { - ftdm_log_chan(chan, FTDM_LOG_WARNING, "mISDN short write into b-channel, written: %d, expected: %d\n", - retval, datalen); - priv->tx_lost_bytes += ftdm_max(0, datalen - retval - MISDN_HEADER_LEN); - } - priv->tx_sent_bytes += ftdm_max(0, retval - MISDN_HEADER_LEN); - break; - } - case PH_DATA_CNF: - priv->tx_ack_cnt++; - break; - case PH_DEACTIVATE_IND: - priv->active = 0; - break; - case PH_ACTIVATE_IND: - priv->active = 1; - break; - case PH_CONTROL_IND: { - int datalen = retval - MISDN_HEADER_LEN; - char *data = buf + MISDN_HEADER_LEN; - - misdn_handle_ph_control_ind(chan, mh, data, datalen); - break; - } - default: - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN received unknown/unhandled event primitive: (%d) %s\n", - mh->prim, misdn_event2str(mh->prim)); - break; - } - return FTDM_SUCCESS; -} - - -/** - * Timeout (miliseconds) for epoll_wait() - */ -#define MISDN_EPOLL_WAIT_MAX_MSEC 1000 - -/** - * mISDN I/O thread - * This thread handles all of the B-Channel I/O, this avoids all of the hazzles with - * intermixed data + control frames on mISDN sockets and the missing write poll support on B-Channels. - * - * Each channel uses a unix stream socketpair as a two-way, pipe replacement for incoming and outgoing - * data. Socketpairs allow a more fine grained tuning of the buffer sizes (pipe are restricted to multiples of - * the native page size (with the smallest possible size (4k) being already 500ms worth of audio). - * - * The socketpair buffer sizes and the send algorithm have been carefully tuned to: - * - * - Minimize the risk of sending too much data and making the mISDN drivers unhappy, by - * sending PH_DATA_REQ only when there is as much data available as we have received in - * the PH_DATA_IND. - * - * - Avoid deadlocks between ftdm_write() trying to fill an almust full socket buffer and - * the I/O thread not having enough data to send a PH_DATA_REQ message. - * (The write() call will return EAGAIN since there is not ehough space free to send all audio data.) - * - * \param thread FreeTDM thread handle - * \param data Private data pointer passed to ftdm_thread_create_detached() (the span object) - * \return Always returns NULL (unused) - * - * \note - * ftdm_span_start/_stop() locks the span mutex, - * use direct access to span members to avoid deadlocking - * - * \todo - * Move D-Channel handling into the I/O thread too. - * Use custom ring buffer structures instead of socketpairs - * (for even more fine grained size control). - */ -static void *misdn_span_run(ftdm_thread_t *thread, void *data) -{ - ftdm_span_t *span = data; - struct misdn_span_private *priv = ftdm_span_io_private(span); - struct epoll_event evh; - int epfd = -1; - int ret; - int i; - - ftdm_unused_arg(thread); - ftdm_log(FTDM_LOG_NOTICE, "mISDN[%d:%s] span thread initializing\n", - ftdm_span_get_id(span), ftdm_span_get_name(span)); - - /* Use epoll for event handling */ - epfd = epoll_create(1); - if (epfd < 0) { - ftdm_log(FTDM_LOG_ERROR, "mISDN[%d:%s] failed to create epoll context: %s\n", - ftdm_span_get_id(span), ftdm_span_get_name(span), strerror(errno)); - goto error; - } - - ftdm_log(FTDM_LOG_DEBUG, "mISDN[%d:%s] adding event pipe to epoll context\n", - ftdm_span_get_id(span), ftdm_span_get_name(span)); - - /* Add event pipe */ - evh.events = EPOLLIN | EPOLLPRI | EPOLLERR; - evh.data.fd = priv->event_pipe_out; - - ret = epoll_ctl(epfd, EPOLL_CTL_ADD, priv->event_pipe_out, &evh); - if (ret < 0) { - ftdm_log(FTDM_LOG_ERROR, "mISDN[%d:%s] failed to add event pipe to epoll context: %s\n", - ftdm_span_get_id(span), ftdm_span_get_name(span), strerror(errno)); - goto error; - } - - ftdm_log(FTDM_LOG_DEBUG, "mISDN[%d:%s] adding b-channels to epoll context\n", - ftdm_span_get_id(span), ftdm_span_get_name(span)); - - /* Add b-channels */ - for (i = 1; i <= span->chan_count; i++) { - ftdm_channel_t *chan = span->channels[i]; - ftdm_assert(chan, "channel == NULL"); - - if (ftdm_channel_get_type(chan) != FTDM_CHAN_TYPE_B) - continue; - - ftdm_log(FTDM_LOG_DEBUG, "mISDN[%d:%s] adding b-channel [%d:%d] to epoll context\n", - ftdm_span_get_id(span), ftdm_span_get_name(span), - ftdm_channel_get_id(chan), ftdm_channel_get_ph_id(chan)); - - evh.events = EPOLLIN | EPOLLPRI | EPOLLERR; - evh.data.ptr = chan; - - ret = epoll_ctl(epfd, EPOLL_CTL_ADD, chan->sockfd, &evh); - if (ret < 0) { - ftdm_log(FTDM_LOG_ERROR, "mISDN[%d:%s] failed to add b-channel [%d] socket to epoll context: %s\n", - ftdm_span_get_id(span), ftdm_span_get_name(span), ftdm_channel_get_id(chan), strerror(errno)); - goto error; - } - } - - ftdm_log(FTDM_LOG_NOTICE, "mISDN[%d:%s] span thread started\n", - ftdm_span_get_id(span), ftdm_span_get_name(span)); - - /* Notify world we're running */ - priv->running = 1; - pthread_cond_signal(&priv->ctrl_cond); - - while (priv->running > 0) { - struct epoll_event ev[10]; - int timeout_ms = MISDN_EPOLL_WAIT_MAX_MSEC; - - ret = epoll_wait(epfd, ev, ftdm_array_len(ev), timeout_ms); - if (ret < 0) { - switch (errno) { - case EAGAIN: - case EINTR: - continue; - default: - ftdm_log(FTDM_LOG_ERROR, "mISDN[%d:%s] epoll_wait() failed: %s\n", - ftdm_span_get_id(span), ftdm_span_get_name(span), strerror(errno)); - goto error; - } - } - /* Check events */ - for (i = 0; i < ret; i++) { - /* */ - if (ev[i].data.fd == priv->event_pipe_out) { - struct misdn_command cmd; - /* event pipe */ - ftdm_log(FTDM_LOG_DEBUG, "mISDN[%d:%s] event pipe notification\n", - ftdm_span_get_id(span), ftdm_span_get_name(span)); - ret = read(priv->event_pipe_out, &cmd, sizeof(cmd)); - if (ret < sizeof(cmd)) { - ftdm_log(FTDM_LOG_ERROR, "mISDN[%d:%s] failed to read span thread command\n", - ftdm_span_get_id(span), ftdm_span_get_name(span)); - continue; - } - - switch (cmd.type) { - case MISDN_CMD_STOP: - ftdm_log(FTDM_LOG_ERROR, "mISDN[%d:%s] got STOP command\n", - ftdm_span_get_id(span), ftdm_span_get_name(span)); - priv->running = -1; - break; - default: - ftdm_log(FTDM_LOG_ERROR, "mISDN[%d:%s] got unknown command: %d\n", - ftdm_span_get_id(span), ftdm_span_get_name(span), cmd.type); - } - - } else { - ftdm_channel_t *chan = ev[i].data.ptr; - handle_b_channel_event(chan); - } - } - } -error: - ftdm_log(FTDM_LOG_NOTICE, "mISDN[%d:%s] span thread stopped\n", - ftdm_span_get_id(span), ftdm_span_get_name(span)); - - /* Remove epoll event sources */ - for (i = 1; i <= span->chan_count; i++) { - ftdm_channel_t *chan = span->channels[i]; - ftdm_assert(chan, "channel == NULL"); - - if (ftdm_channel_get_type(chan) != FTDM_CHAN_TYPE_B) - continue; - - ret = epoll_ctl(epfd, EPOLL_CTL_DEL, chan->sockfd, NULL); - if (ret < 0) { - ftdm_log(FTDM_LOG_ERROR, "mISDN[%d:%s] failed to remove b-channel [%d] socket from epoll context: %s\n", - ftdm_span_get_id(span), ftdm_span_get_name(span), ftdm_channel_get_id(chan), strerror(errno)); - } - } - - /* Close epoll context */ - if (epfd >= 0) close(epfd); - - /* Notify world we stopped running */ - priv->running = 0; - pthread_cond_signal(&priv->ctrl_cond); - return NULL; -} - -/** - * Timeout (miliseconds) for span start/stop completion - */ -#define SPAN_DEFAULT_TIMEOUT_MSEC 10000 - -static FIO_SPAN_START_FUNCTION(misdn_span_start) -{ - struct misdn_span_private *span_priv = ftdm_span_io_private(span); - struct timespec timeout; - int retval; - - ftdm_log(FTDM_LOG_NOTICE, "mISDN starting span %d (%s)\n", - ftdm_span_get_id(span), ftdm_span_get_name(span)); - - span_priv->running = 0; - - if (ftdm_thread_create_detached(misdn_span_run, span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "mISDN failed to start span %d (%s)\n", - ftdm_span_get_id(span), ftdm_span_get_name(span)); - return FTDM_FAIL; - } - - /* - * Wait SPAN_DEFAULT_TIMEOUT_MSEC miliseconds for I/O thread to start up - */ - clock_gettime(CLOCK_REALTIME, &timeout); - ts_add_msec(&timeout, SPAN_DEFAULT_TIMEOUT_MSEC); - - pthread_mutex_lock(&span_priv->ctrl_cond_mutex); - - retval = pthread_cond_timedwait(&span_priv->ctrl_cond, &span_priv->ctrl_cond_mutex, &timeout); - if (retval == ETIMEDOUT) { - ftdm_log(FTDM_LOG_ERROR, "mISDN failed to start span %d (%s) in 10 seconds\n", - ftdm_span_get_id(span), ftdm_span_get_name(span)); - return FTDM_FAIL; - } else if (retval) { - ftdm_log(FTDM_LOG_ERROR, "mISDN failed to start span %d (%s): %s\n", - ftdm_span_get_id(span), ftdm_span_get_name(span), strerror(errno)); - return FTDM_FAIL; - } - - pthread_mutex_unlock(&span_priv->ctrl_cond_mutex); - return FTDM_SUCCESS; -} - -static FIO_SPAN_STOP_FUNCTION(misdn_span_stop) -{ - struct misdn_span_private *span_priv = ftdm_span_io_private(span); - struct timespec timeout; - struct misdn_command cmd; - int retval; - - ftdm_log(FTDM_LOG_NOTICE, "mISDN stopping span %d (%s)\n", - ftdm_span_get_id(span), ftdm_span_get_name(span)); - - span_priv->running = -1; - - /* Wake up thread */ - cmd.type = MISDN_CMD_STOP; - retval = write(span_priv->event_pipe_in, &cmd, sizeof(cmd)); - if (retval < sizeof(cmd)) { - ftdm_log(FTDM_LOG_WARNING, "mISDN failed to send STOP command to span thread\n"); - } - - /* - * Wait SPAN_DEFAULT_TIMEOUT_MSEC miliseconds for I/O thread to shut down - */ - clock_gettime(CLOCK_REALTIME, &timeout); - ts_add_msec(&timeout, SPAN_DEFAULT_TIMEOUT_MSEC); - - pthread_mutex_lock(&span_priv->ctrl_cond_mutex); - - retval = pthread_cond_timedwait(&span_priv->ctrl_cond, &span_priv->ctrl_cond_mutex, &timeout); - if (retval == ETIMEDOUT) { - ftdm_log(FTDM_LOG_ERROR, "mISDN failed to stop thread in 10 seconds\n"); - return FTDM_FAIL; - } else if (retval) { - ftdm_log(FTDM_LOG_ERROR, "mISDN failed to stop thread: %s\n", - strerror(errno)); - return FTDM_FAIL; - } - - pthread_mutex_unlock(&span_priv->ctrl_cond_mutex); - return FTDM_SUCCESS; -} - - -/** - * \brief ftmod_misdn interface - */ -static const ftdm_io_interface_t misdn_interface = { - .name = "misdn", - - .open = misdn_open, - .close = misdn_close, - .wait = misdn_wait, - .read = misdn_read, - .write = misdn_write, - - .poll_event = misdn_poll_event, - .next_event = misdn_next_event, - - .command = misdn_command, - .get_alarms = misdn_get_alarms, - .configure = misdn_configure, /* configure global parameters */ - .configure_span = misdn_configure_span, /* assign channels to span */ - .channel_next_event = misdn_channel_next_event, - .channel_destroy = misdn_channel_destroy, /* clean up channel */ - .span_destroy = misdn_span_destroy, /* clean up span */ - - .span_start = misdn_span_start, - .span_stop = misdn_span_stop, -}; - - -/** - * \brief ftmod_misdn module init function - */ -static FIO_IO_LOAD_FUNCTION(misdn_load) -{ - struct mISDNversion ver; - struct mISDN_devinfo devinfo; - int devcnt, usecnt; - int i; - - /* */ - globals.sockfd = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE); - if (globals.sockfd < 0) { - ftdm_log(FTDM_LOG_CRIT, "Unable to create mISDN base socket (are you sure this kernel has mISDN support?)\n"); - return FTDM_FAIL; - } - - if (ioctl(globals.sockfd, IMGETVERSION, &ver) < 0) { - ftdm_log(FTDM_LOG_CRIT, "Unable to retrieve mISDN version\n"); - goto error; - } - - ftdm_log(FTDM_LOG_INFO, "mISDN Interface version %hhd.%hhd.%hd\n", ver.major, ver.minor, ver.release); - - devcnt = 0; - if (ioctl(globals.sockfd, IMGETCOUNT, &devcnt) < 0) { - ftdm_log(FTDM_LOG_CRIT, "Unable to retrieve number of mISDN devices\n"); - goto error; - - } - - if (!devcnt) { - ftdm_log(FTDM_LOG_CRIT, "No mISDN devices found\n"); - goto error; - } - usecnt = devcnt; - - ftdm_log(FTDM_LOG_INFO, "Found %d mISDN devices:\n", devcnt); - - /* Output most important device information */ - for (i = 0; i < devcnt; i++) { - int caps = MISDN_CAPS_NONE; - - devinfo.id = i; - if (ioctl(globals.sockfd, IMGETDEVINFO, &devinfo) < 0) { - ftdm_log(FTDM_LOG_ERROR, "Failed to retrieve information for device %d\n", i); - continue; - } - - /* print */ - ftdm_log(FTDM_LOG_INFO, "<%d> Name: %s, B-Channels: %d\n", - devinfo.id, - ftdm_strlen_zero_buf(devinfo.name) ? "Unknown" : devinfo.name, - devinfo.nrbchan); - - /* D-Channels capabilities */ - if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1)) - caps |= MISDN_CAPS_TE | MISDN_CAPS_PRI; - if (devinfo.Dprotocols & (1 << ISDN_P_NT_E1)) - caps |= MISDN_CAPS_NT | MISDN_CAPS_PRI; - if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0)) - caps |= MISDN_CAPS_TE | MISDN_CAPS_BRI; - if (devinfo.Dprotocols & (1 << ISDN_P_NT_S0)) - caps |= MISDN_CAPS_NT | MISDN_CAPS_BRI; -#ifdef ISDN_P_TE_UP0 - if (devinfo.Dprotocols & (1 << ISDN_P_TE_UP0)) - caps |= MISDN_CAPS_TE | MISDN_CAPS_UP0 | MISDN_CAPS_BRI; -#endif -#ifdef ISDN_P_NT_UP0 - if (devinfo.Dprotocols & (1 << ISDN_P_NT_UP0)) - caps |= MISDN_CAPS_NT | MISDN_CAPS_UP0 | MISDN_CAPS_BRI; -#endif - /* B-Channel capabilities */ - if (devinfo.Bprotocols & (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK))) - caps |= MISDN_CAPS_RAW; - if (devinfo.Bprotocols & (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK))) - caps |= MISDN_CAPS_HDLC; - - ftdm_log(FTDM_LOG_INFO, " Type: %s, Modes: %s %s\n", - MISDN_IS_PRI(caps) ? "PRI" : "BRI", - MISDN_IS_NT(caps) ? "NT" : "", - MISDN_IS_TE(caps) ? "TE" : ""); - - ftdm_log(FTDM_LOG_INFO, " B-Channel modes: %s %s\n", - MISDN_IS_RAW(caps) ? "RAW" : "", - MISDN_IS_HDLC(caps) ? "HDLC" : ""); - - if (!(MISDN_IS_NT(caps) || MISDN_IS_TE(caps)) && !MISDN_IS_RAW(caps)) { - ftdm_log(FTDM_LOG_ERROR, " This device is unusable!\n"); - usecnt--; - } - } - if (!usecnt) { - ftdm_log(FTDM_LOG_CRIT, "No useable devices found!\n"); - goto error; - } - - ftdm_log(FTDM_LOG_INFO, "Found %d useable mISDN devices\n", usecnt); - - /* assign interface struct */ - *fio = (ftdm_io_interface_t *)&misdn_interface; - return FTDM_SUCCESS; -error: - if (globals.sockfd >= 0) - close(globals.sockfd); - return FTDM_FAIL; -} - -/** - * \brief ftmod_misdn module shutdown - */ -static FIO_IO_UNLOAD_FUNCTION(misdn_unload) -{ - if (globals.sockfd >= 0) - close(globals.sockfd); - return FTDM_SUCCESS; -} - -/** - * \brief ftmod_misdn module - */ -ftdm_module_t ftdm_module = { - .name = "misdn", - .io_load = misdn_load, - .io_unload = misdn_unload -}; diff --git a/libs/freetdm/src/ftmod/ftmod_pika/ftdm_pika.h b/libs/freetdm/src/ftmod/ftmod_pika/ftdm_pika.h deleted file mode 100644 index 54c550e8e7..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_pika/ftdm_pika.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef FTDM_PIKA_H -#define FTDM_PIKA_H -#include "freetdm.h" -#include "pikahmpapi.h" - - - -#define PIKA_STR2ENUM_P(_FUNC1, _FUNC2, _TYPE) _TYPE _FUNC1 (const char *name); const char * _FUNC2 (_TYPE type); -#define PIKA_STR2ENUM(_FUNC1, _FUNC2, _TYPE, _STRINGS, _MAX) \ - _TYPE _FUNC1 (const char *name) \ - { \ - int i; \ - _TYPE t = _MAX ; \ - \ - for (i = 0; i < _MAX ; i++) { \ - if (!strcasecmp(name, _STRINGS[i])) { \ - t = (_TYPE) i; \ - break; \ - } \ - } \ - \ - return t; \ - } \ - const char * _FUNC2 (_TYPE type) \ - { \ - if (type > _MAX) { \ - type = _MAX; \ - } \ - return _STRINGS[(int)type]; \ - } - - -typedef enum { - PIKA_SPAN_FRAMING_T1_D4, - PIKA_SPAN_FRAMING_T1_ESF, - PIKA_SPAN_FRAMING_E1_BASIC, - PIKA_SPAN_FRAMING_E1_CRC4, - PIKA_SPAN_INVALID -} PIKA_TSpanFraming; -#define PIKA_SPAN_STRINGS "T1_D4", "T1_ESF", "E1_BASIC", "E1_CRC4" -PIKA_STR2ENUM_P(pika_str2span, pika_span2str, PIKA_TSpanFraming) - -typedef enum { - PIKA_SPAN_ENCODING_T1_AMI_ZS_NONE, - PIKA_SPAN_ENCODING_T1_AMI_ZS_GTE, - PIKA_SPAN_ENCODING_T1_AMI_ZS_BELL, - PIKA_SPAN_ENCODING_T1_AMI_ZS_JAM8, - PIKA_SPAN_ENCODING_T1_B8ZS, - PIKA_SPAN_ENCODING_E1_AMI, - PIKA_SPAN_ENCODING_E1_HDB3, - PIKA_SPAN_ENCODING_INVALID -} PIKA_TSpanEncoding; -#define PIKA_SPAN_ENCODING_STRINGS "T1_AMI_ZS_NONE", "T1_AMI_ZS_GTE", "T1_AMI_ZS_BELL", "T1_AMI_ZS_JAM8", "T1_B8ZS", "E1_AMI", "E1_HDB3" -PIKA_STR2ENUM_P(pika_str2span_encoding, pika_span_encoding2str, PIKA_TSpanEncoding) - -typedef enum { - PIKA_SPAN_LOOP_LENGTH_SHORT_HAUL, - PIKA_SPAN_LOOP_LENGTH_LONG_HAUL, - PIKA_SPAN_LOOP_INVALID -} PIKA_TSpanLoopLength; -#define PIKA_LL_STRINGS "SHORT_HAUL", "LONG_HAUL" -PIKA_STR2ENUM_P(pika_str2loop_length, pika_loop_length2str, PIKA_TSpanLoopLength) - -typedef enum { - PIKA_SPAN_LBO_T1_LONG_0_DB, - PIKA_SPAN_LBO_T1_LONG_7_DB, - PIKA_SPAN_LBO_T1_LONG_15_DB, - PIKA_SPAN_LBO_T1_LONG_22_DB, - PIKA_SPAN_LBO_T1_SHORT_133_FT, - PIKA_SPAN_LBO_T1_SHORT_266_FT, - PIKA_SPAN_LBO_T1_SHORT_399_FT, - PIKA_SPAN_LBO_T1_SHORT_533_FT, - PIKA_SPAN_LBO_T1_SHORT_655_FT, - PIKA_SPAN_LBO_E1_WAVEFORM_120_OHM, - PIKA_SPAN_LBO_INVALID -} PIKA_TSpanBuildOut; -#define PIKA_LBO_STRINGS "T1_LONG_0_DB", "T1_LONG_7_DB", "T1_LONG_15_DB", "T1_LONG_22_DB", "T1_SHORT_133_FT", "T1_SHORT_266_FT", "T1_SHORT_399_FT", "T1_SHORT_533_FT", "T1_SHORT_655_FT", "E1_WAVEFORM_120_OHM" -PIKA_STR2ENUM_P(pika_str2lbo, pika_lbo2str, PIKA_TSpanBuildOut) - -typedef enum { - PIKA_SPAN_COMPAND_MODE_MU_LAW = 1, - PIKA_SPAN_COMPAND_MODE_A_LAW, - PIKA_SPAN_COMPAND_MODE_INVALID -} PIKA_TSpanCompandMode; -#define PIKA_SPAN_COMPAND_MODE_STRINGS "MU_LAW", "A_LAW" -PIKA_STR2ENUM_P(pika_str2compand_mode, pika_compand_mode2str, PIKA_TSpanCompandMode) - -#endif - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2008.vcproj deleted file mode 100644 index 7ad535ea3f..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2008.vcproj +++ /dev/null @@ -1,353 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj.filters deleted file mode 100644 index 4d4cec4668..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj.filters +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Source Files - - - - - Header Files - - - \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.c b/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.c deleted file mode 100644 index fcd5149814..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.c +++ /dev/null @@ -1,1469 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -#include "freetdm.h" -#include "ftdm_pika.h" - - -#define MAX_NUMBER_OF_TRUNKS 64 -#define PIKA_BLOCK_SIZE 160 -#define PIKA_BLOCK_LEN 20 -#define PIKA_NUM_BUFFERS 8 -#define TRY_OR_DIE(__code, __status, __label) if ((status = __code ) != __status) goto __label -#define pk_atof(__a) (PK_FLOAT) atof(__a) - -PK_VOID PK_CALLBACK media_out_callback(PKH_TPikaEvent *event); - -FTDM_ENUM_NAMES(PIKA_SPAN_NAMES, PIKA_SPAN_STRINGS) -PIKA_STR2ENUM(pika_str2span, pika_span2str, PIKA_TSpanFraming, PIKA_SPAN_NAMES, PIKA_SPAN_INVALID) - -FTDM_ENUM_NAMES(PIKA_SPAN_ENCODING_NAMES, PIKA_SPAN_ENCODING_STRINGS) -PIKA_STR2ENUM(pika_str2span_encoding, pika_span_encoding2str, PIKA_TSpanEncoding, PIKA_SPAN_ENCODING_NAMES, PIKA_SPAN_ENCODING_INVALID) - -FTDM_ENUM_NAMES(PIKA_LL_NAMES, PIKA_LL_STRINGS) -PIKA_STR2ENUM(pika_str2loop_length, pika_loop_length2str, PIKA_TSpanLoopLength, PIKA_LL_NAMES, PIKA_SPAN_LOOP_INVALID) - -FTDM_ENUM_NAMES(PIKA_LBO_NAMES, PIKA_LBO_STRINGS) -PIKA_STR2ENUM(pika_str2lbo, pika_lbo2str, PIKA_TSpanBuildOut, PIKA_LBO_NAMES, PIKA_SPAN_LBO_INVALID) - -FTDM_ENUM_NAMES(PIKA_SPAN_COMPAND_MODE_NAMES, PIKA_SPAN_COMPAND_MODE_STRINGS) -PIKA_STR2ENUM(pika_str2compand_mode, pika_compand_mode2str, PIKA_TSpanCompandMode, PIKA_SPAN_COMPAND_MODE_NAMES, PIKA_SPAN_COMPAND_MODE_INVALID) - - -typedef enum { - PK_FLAG_READY = (1 << 0), - PK_FLAG_LOCKED = (1 << 1) -} pk_flag_t; - -struct general_config { - uint32_t region; -}; -typedef struct general_config general_config_t; - -struct pika_channel_profile { - char name[80]; - PKH_TRecordConfig record_config; - PKH_TPlayConfig play_config; - int ec_enabled; - PKH_TECConfig ec_config; - PKH_TSpanConfig span_config; - general_config_t general_config; - int cust_span; -}; -typedef struct pika_channel_profile pika_channel_profile_t; - -static struct { - PKH_TSystemDeviceList board_list; - TPikaHandle open_boards[MAX_NUMBER_OF_TRUNKS]; - TPikaHandle system_handle; - PKH_TSystemConfig system_config; - PKH_TRecordConfig record_config; - PKH_TPlayConfig play_config; - PKH_TECConfig ec_config; - PKH_TSpanConfig t1_span_config; - PKH_TSpanConfig e1_span_config; - ftdm_hash_t *profile_hash; - general_config_t general_config; -} globals; - - -struct pika_span_data { - TPikaHandle event_queue; - PKH_TPikaEvent last_oob_event; - uint32_t boardno; - PKH_TSpanConfig span_config; - TPikaHandle handle; - uint32_t flags; -}; -typedef struct pika_span_data pika_span_data_t; - -struct pika_chan_data { - TPikaHandle handle; - TPikaHandle media_in; - TPikaHandle media_out; - TPikaHandle media_in_queue; - TPikaHandle media_out_queue; - PKH_TPikaEvent last_media_event; - PKH_TPikaEvent last_oob_event; - PKH_TRecordConfig record_config; - PKH_TPlayConfig play_config; - int ec_enabled; - PKH_TECConfig ec_config; - PKH_THDLCConfig hdlc_config; - ftdm_buffer_t *digit_buffer; - ftdm_mutex_t *digit_mutex; - ftdm_size_t dtmf_len; - uint32_t flags; - uint32_t hdlc_bytes; -}; -typedef struct pika_chan_data pika_chan_data_t; - -static const char *pika_board_type_string(PK_UINT type) -{ - if (type == PKH_BOARD_TYPE_DIGITAL_GATEWAY) { - return "digital_gateway"; - } - - if (type == PKH_BOARD_TYPE_ANALOG_GATEWAY) { - return "analog_gateway"; - } - - return "unknown"; -} - -/** - * \brief Process configuration variable for a pika profile - * \param category Pika profile name - * \param var Variable name - * \param val Variable value - * \param lineno Line number from configuration file (unused) - * \return Success - */ -static FIO_CONFIGURE_FUNCTION(pika_configure) -{ - pika_channel_profile_t *profile = NULL; - int ok = 1; - - if (!(profile = (pika_channel_profile_t *) hashtable_search(globals.profile_hash, (char *)category))) { - profile = ftdm_malloc(sizeof(*profile)); - memset(profile, 0, sizeof(*profile)); - ftdm_set_string(profile->name, category); - profile->ec_config = globals.ec_config; - profile->record_config = globals.record_config; - profile->play_config = globals.play_config; - hashtable_insert(globals.profile_hash, (void *)profile->name, profile, HASHTABLE_FLAG_NONE); - ftdm_log(FTDM_LOG_INFO, "creating profile [%s]\n", category); - } - - if (!strcasecmp(var, "rx-gain")) { - profile->record_config.gain = pk_atof(val); - } else if (!strcasecmp(var, "rx-agc-enabled")) { - profile->record_config.AGC.enabled = ftdm_true(val); - } else if (!strcasecmp(var, "rx-agc-targetPower")) { - profile->record_config.AGC.targetPower = pk_atof(val); - } else if (!strcasecmp(var, "rx-agc-minGain")) { - profile->record_config.AGC.minGain = pk_atof(val); - } else if (!strcasecmp(var, "rx-agc-maxGain")) { - profile->record_config.AGC.maxGain = pk_atof(val); - } else if (!strcasecmp(var, "rx-agc-attackRate")) { - profile->record_config.AGC.attackRate = atoi(val); - } else if (!strcasecmp(var, "rx-agc-decayRate")) { - profile->record_config.AGC.decayRate = atoi(val); - } else if (!strcasecmp(var, "rx-agc-speechThreshold")) { - profile->record_config.AGC.speechThreshold = pk_atof(val); - } else if (!strcasecmp(var, "rx-vad-enabled")) { - profile->record_config.VAD.enabled = ftdm_true(val); - } else if (!strcasecmp(var, "rx-vad-activationThreshold")) { - profile->record_config.VAD.activationThreshold = pk_atof(val); - } else if (!strcasecmp(var, "rx-vad-activationDebounceTime")) { - profile->record_config.VAD.activationDebounceTime = atoi(val); - } else if (!strcasecmp(var, "rx-vad-deactivationThreshold")) { - profile->record_config.VAD.deactivationThreshold = pk_atof(val); - } else if (!strcasecmp(var, "rx-vad-deactivationDebounceTime")) { - profile->record_config.VAD.deactivationDebounceTime = atoi(val); - } else if (!strcasecmp(var, "rx-vad-preSpeechBufferSize")) { - profile->record_config.VAD.preSpeechBufferSize = atoi(val); - } else if (!strcasecmp(var, "tx-gain")) { - profile->play_config.gain = pk_atof(val); - } else if (!strcasecmp(var, "tx-agc-enabled")) { - profile->play_config.AGC.enabled = ftdm_true(val); - } else if (!strcasecmp(var, "tx-agc-targetPower")) { - profile->play_config.AGC.targetPower = pk_atof(val); - } else if (!strcasecmp(var, "tx-agc-minGain")) { - profile->play_config.AGC.minGain = pk_atof(val); - } else if (!strcasecmp(var, "tx-agc-maxGain")) { - profile->play_config.AGC.maxGain = pk_atof(val); - } else if (!strcasecmp(var, "tx-agc-attackRate")) { - profile->play_config.AGC.attackRate = atoi(val); - } else if (!strcasecmp(var, "tx-agc-decayRate")) { - profile->play_config.AGC.decayRate = atoi(val); - } else if (!strcasecmp(var, "tx-agc-speechThreshold")) { - profile->play_config.AGC.speechThreshold = pk_atof(val); - } else if (!strcasecmp(var, "ec-enabled")) { - profile->ec_enabled = ftdm_true(val); - } else if (!strcasecmp(var, "ec-doubleTalkerThreshold")) { - profile->ec_config.doubleTalkerThreshold = pk_atof(val); - } else if (!strcasecmp(var, "ec-speechPresentThreshold")) { - profile->ec_config.speechPresentThreshold = pk_atof(val); - } else if (!strcasecmp(var, "ec-echoSuppressionThreshold")) { - profile->ec_config.echoSuppressionThreshold = pk_atof(val); - } else if (!strcasecmp(var, "ec-echoSuppressionEnabled")) { - profile->ec_config.echoSuppressionEnabled = ftdm_true(val); - } else if (!strcasecmp(var, "ec-comfortNoiseEnabled")) { - profile->ec_config.comfortNoiseEnabled = ftdm_true(val); - } else if (!strcasecmp(var, "ec-adaptationModeEnabled")) { - profile->ec_config.adaptationModeEnabled = ftdm_true(val); - } else if (!strcasecmp(var, "framing")) { - profile->span_config.framing = pika_str2span(val); - profile->cust_span++; - } else if (!strcasecmp(var, "encoding")) { - profile->span_config.encoding = pika_str2span_encoding(val); - profile->cust_span++; - } else if (!strcasecmp(var, "loopLength")) { - profile->span_config.loopLength = pika_str2loop_length(val); - profile->cust_span++; - } else if (!strcasecmp(var, "buildOut")) { - profile->span_config.buildOut = pika_str2lbo(val); - profile->cust_span++; - } else if (!strcasecmp(var, "compandMode")) { - profile->span_config.compandMode = pika_str2compand_mode(val); - profile->cust_span++; - } else if (!strcasecmp(var, "region")) { - if (!strcasecmp(val, "eu")) { - profile->general_config.region = PKH_TRUNK_EU; - } else { - profile->general_config.region = PKH_TRUNK_NA; - } - } else { - ok = 0; - } - - if (ok) { - ftdm_log(FTDM_LOG_INFO, "setting param [%s]=[%s] for profile [%s]\n", var, val, category); - } else { - ftdm_log(FTDM_LOG_ERROR, "unknown param [%s]\n", var); - } - - return FTDM_SUCCESS; -} - -/** - * \brief Pika event handler - * \param event Pika event - */ -PK_VOID PK_CALLBACK media_out_callback(PKH_TPikaEvent *event) -{ - PK_STATUS pk_status; - ftdm_channel_t *ftdmchan = event->userData; - pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data; - - //PK_CHAR event_text[PKH_EVENT_MAX_NAME_LENGTH]; - //PKH_EVENT_GetText(event->id, event_text, sizeof(event_text)); - //ftdm_log(FTDM_LOG_DEBUG, "Event: %s\n", event_text); - - switch (event->id) { - case PKH_EVENT_PLAY_IDLE: - { - while (ftdm_buffer_inuse(chan_data->digit_buffer)) { - char dtmf[128] = ""; - ftdm_mutex_lock(chan_data->digit_mutex); - chan_data->dtmf_len = ftdm_buffer_read(chan_data->digit_buffer, dtmf, sizeof(dtmf)); - pk_status = PKH_TG_PlayDTMF(chan_data->media_out, dtmf); - ftdm_mutex_unlock(chan_data->digit_mutex); - } - } - break; - case PKH_EVENT_TG_TONE_PLAYED: - { - - if (!event->p1) { - ftdm_mutex_lock(chan_data->digit_mutex); - PKH_PLAY_Start(chan_data->media_out); - chan_data->dtmf_len = 0; - ftdm_mutex_unlock(chan_data->digit_mutex); - } - - - } - break; - default: - break; - } - -} - -/** - * \brief Initialises a range of pika channels - * \param span FreeTDM span - * \param boardno Pika board number - * \param spanno Pika span number - * \param start Initial pika channel number - * \param end Final pika channel number - * \param type FreeTDM channel type - * \param name FreeTDM span name - * \param number FreeTDM span number - * \param profile Pika channel profile - * \return number of spans configured - */ -static unsigned pika_open_range(ftdm_span_t *span, unsigned boardno, unsigned spanno, unsigned start, unsigned end, - ftdm_chan_type_t type, char *name, char *number, pika_channel_profile_t *profile) -{ - unsigned configured = 0, x; - PK_STATUS status; - PK_CHAR error_text[PKH_ERROR_MAX_NAME_LENGTH]; - pika_span_data_t *span_data; - - if (boardno >= globals.board_list.numberOfBoards) { - ftdm_log(FTDM_LOG_ERROR, "Board %u is not present!\n", boardno); - return 0; - } - - if (!globals.open_boards[boardno]) { - status = PKH_BOARD_Open(globals.board_list.board[boardno].id, - NULL, - &globals.open_boards[boardno]); - if(status != PK_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error: PKH_BOARD_Open %d failed(%s)!\n", boardno, - PKH_ERROR_GetText(status, error_text, sizeof(error_text))); - return 0; - } - - ftdm_log(FTDM_LOG_DEBUG, "Open board %u\n", boardno); - - //PKH_BOARD_SetDebugTrace(globals.open_boards[boardno], 1, 0); - - } - - if (span->io_data) { - span_data = span->io_data; - } else { - span_data = ftdm_malloc(sizeof(*span_data)); - assert(span_data != NULL); - memset(span_data, 0, sizeof(*span_data)); - span_data->boardno = boardno; - - status = PKH_QUEUE_Create(PKH_QUEUE_TYPE_NORMAL, &span_data->event_queue); - - if (status != PK_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error: PKH_QUEUE_Create failed(%s)!\n", - PKH_ERROR_GetText(status, error_text, sizeof(error_text))); - ftdm_safe_free(span_data); - return 0; - } - - //PKH_QUEUE_Attach(span_data->event_queue, globals.open_boards[boardno], NULL); - - span->io_data = span_data; - } - - if (type == FTDM_CHAN_TYPE_FXS || type == FTDM_CHAN_TYPE_FXO) { - start--; - end--; - } - - for(x = start; x < end; x++) { - ftdm_channel_t *chan; - pika_chan_data_t *chan_data = NULL; - - chan_data = ftdm_malloc(sizeof *chan_data); - assert(chan_data); - memset(chan_data, 0, sizeof(*chan_data)); - ftdm_span_add_channel(span, 0, type, &chan); - chan->io_data = chan_data; - - if ((type == FTDM_CHAN_TYPE_B || type == FTDM_CHAN_TYPE_DQ921) && !span_data->handle) { - PKH_TBoardConfig boardConfig; - - TRY_OR_DIE(PKH_BOARD_GetConfig(globals.open_boards[boardno], &boardConfig), PK_SUCCESS, error); - if ((profile && profile->general_config.region == PKH_TRUNK_EU) || ftdm_test_flag(span_data, PK_FLAG_LOCKED)) { - if (span->trunk_type == FTDM_TRUNK_T1) { - ftdm_log(FTDM_LOG_WARNING, "Changing trunk type to E1 based on previous config.\n"); - } - span->trunk_type = FTDM_TRUNK_E1; - } - - if (span->trunk_type == FTDM_TRUNK_T1) { - if (ftdm_test_flag(span_data, PK_FLAG_LOCKED)) { - ftdm_log(FTDM_LOG_WARNING, "Already locked into E1 mode!\n"); - } - } else if (span->trunk_type == FTDM_TRUNK_E1) { - boardConfig.specific.DigitalGateway.interfaceType = PKH_BOARD_INTERFACE_TYPE_E1; - if ((status = PKH_BOARD_SetConfig(globals.open_boards[boardno], &boardConfig)) != PK_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error: [%s]\n", - PKH_ERROR_GetText(status, error_text, sizeof(error_text))); - } - ftdm_set_flag(span_data, PK_FLAG_LOCKED); - } - - TRY_OR_DIE(PKH_SPAN_Open(globals.open_boards[boardno], spanno, NULL, &span_data->handle), PK_SUCCESS, error); - TRY_OR_DIE(PKH_SPAN_GetConfig(span_data->handle, &span_data->span_config), PK_SUCCESS, error); - TRY_OR_DIE(PKH_QUEUE_Attach(span_data->event_queue, span_data->handle, (PK_VOID*) span), PK_SUCCESS, error); - } - - if (type == FTDM_CHAN_TYPE_FXO) { - PKH_TTrunkConfig trunkConfig; - - TRY_OR_DIE(PKH_TRUNK_Open(globals.open_boards[boardno], x, &chan_data->handle), PK_SUCCESS, error); - TRY_OR_DIE(PKH_TRUNK_Seize(chan_data->handle), PK_SUCCESS, error); - - if (profile && profile->general_config.region == PKH_TRUNK_EU) { - TRY_OR_DIE(PKH_TRUNK_GetConfig(chan_data->handle, &trunkConfig), PK_SUCCESS, error); - trunkConfig.internationalControl = PKH_PHONE_INTERNATIONAL_CONTROL_EU; - trunkConfig.audioFormat = PKH_AUDIO_ALAW; - trunkConfig.compandMode = PKH_PHONE_AUDIO_ALAW; - chan->native_codec = chan->effective_codec = FTDM_CODEC_ALAW; - TRY_OR_DIE(PKH_TRUNK_SetConfig(chan_data->handle, &trunkConfig), PK_SUCCESS, error); - } else { - chan->native_codec = chan->effective_codec = FTDM_CODEC_ULAW; - } - - - TRY_OR_DIE(PKH_QUEUE_Attach(span_data->event_queue, chan_data->handle, (PK_VOID*) chan), PK_SUCCESS, error); - TRY_OR_DIE(PKH_TRUNK_GetMediaStreams(chan_data->handle, &chan_data->media_in, &chan_data->media_out), PK_SUCCESS, error); - TRY_OR_DIE(PKH_QUEUE_Create(PKH_QUEUE_TYPE_NORMAL, &chan_data->media_in_queue), PK_SUCCESS, error); - TRY_OR_DIE(PKH_QUEUE_Attach(chan_data->media_in_queue, chan_data->media_in, (PK_VOID*) chan), PK_SUCCESS, error); - TRY_OR_DIE(PKH_QUEUE_Create(PKH_QUEUE_TYPE_CALLBACK, &chan_data->media_out_queue), PK_SUCCESS, error); - TRY_OR_DIE(PKH_QUEUE_SetEventHandler(chan_data->media_out_queue, media_out_callback), PK_SUCCESS, error); - TRY_OR_DIE(PKH_QUEUE_Attach(chan_data->media_out_queue, chan_data->media_out, (PK_VOID*) chan), PK_SUCCESS, error); - TRY_OR_DIE(PKH_TRUNK_Start(chan_data->handle), PK_SUCCESS, error); - } else if (type == FTDM_CHAN_TYPE_FXS) { - PKH_TPhoneConfig phoneConfig; - - if (profile && profile->general_config.region == PKH_TRUNK_EU) { - TRY_OR_DIE(PKH_PHONE_GetConfig(chan_data->handle, &phoneConfig), PK_SUCCESS, error); - phoneConfig.internationalControl = PKH_PHONE_INTERNATIONAL_CONTROL_EU; - phoneConfig.compandMode = PKH_PHONE_AUDIO_ALAW; - chan->native_codec = chan->effective_codec = FTDM_CODEC_ALAW; - TRY_OR_DIE(PKH_PHONE_SetConfig(chan_data->handle, &phoneConfig), PK_SUCCESS, error); - } else { - chan->native_codec = chan->effective_codec = FTDM_CODEC_ULAW; - } - - TRY_OR_DIE(PKH_PHONE_Open(globals.open_boards[boardno], x, &chan_data->handle), PK_SUCCESS, error); - TRY_OR_DIE(PKH_PHONE_Seize(chan_data->handle), PK_SUCCESS, error); - TRY_OR_DIE(PKH_PHONE_GetMediaStreams(chan_data->handle, &chan_data->media_in, &chan_data->media_out), PK_SUCCESS, error); - TRY_OR_DIE(PKH_QUEUE_Attach(span_data->event_queue, chan_data->handle, (PK_VOID*) chan), PK_SUCCESS, error); - TRY_OR_DIE(PKH_QUEUE_Create(PKH_QUEUE_TYPE_NORMAL, &chan_data->media_in_queue), PK_SUCCESS, error); - TRY_OR_DIE(PKH_QUEUE_Attach(chan_data->media_in_queue, chan_data->media_in, (PK_VOID*) chan), PK_SUCCESS, error); - TRY_OR_DIE(PKH_QUEUE_Create(PKH_QUEUE_TYPE_CALLBACK, &chan_data->media_out_queue), PK_SUCCESS, error); - TRY_OR_DIE(PKH_QUEUE_SetEventHandler(chan_data->media_out_queue, media_out_callback), PK_SUCCESS, error); - TRY_OR_DIE(PKH_QUEUE_Attach(chan_data->media_out_queue, chan_data->media_out, (PK_VOID*) chan), PK_SUCCESS, error); - TRY_OR_DIE(PKH_PHONE_Start(chan_data->handle), PK_SUCCESS, error); - } else if (type == FTDM_CHAN_TYPE_B) { - TRY_OR_DIE(PKH_SPAN_SeizeChannel(span_data->handle, x), PK_SUCCESS, error); - TRY_OR_DIE(PKH_SPAN_GetMediaStreams(span_data->handle, x, &chan_data->media_in, &chan_data->media_out), PK_SUCCESS, error); - TRY_OR_DIE(PKH_QUEUE_Create(PKH_QUEUE_TYPE_NORMAL, &chan_data->media_in_queue), PK_SUCCESS, error); - TRY_OR_DIE(PKH_QUEUE_Attach(chan_data->media_in_queue, chan_data->media_in, (PK_VOID*) chan), PK_SUCCESS, error); - TRY_OR_DIE(PKH_QUEUE_Create(PKH_QUEUE_TYPE_CALLBACK, &chan_data->media_out_queue), PK_SUCCESS, error); - TRY_OR_DIE(PKH_QUEUE_SetEventHandler(chan_data->media_out_queue, media_out_callback), PK_SUCCESS, error); - TRY_OR_DIE(PKH_QUEUE_Attach(chan_data->media_out_queue, chan_data->media_out, (PK_VOID*) chan), PK_SUCCESS, error); - } else if (type == FTDM_CHAN_TYPE_DQ921) { - TRY_OR_DIE(PKH_SPAN_HDLC_Open(span_data->handle, PKH_SPAN_HDLC_MODE_NORMAL, &chan_data->handle), PK_SUCCESS, error); - TRY_OR_DIE(PKH_SPAN_HDLC_GetConfig(chan_data->handle, &chan_data->hdlc_config), PK_SUCCESS, error); - chan_data->hdlc_config.channelId = x; - TRY_OR_DIE(PKH_SPAN_HDLC_SetConfig(chan_data->handle, &chan_data->hdlc_config), PK_SUCCESS, error); - TRY_OR_DIE(PKH_QUEUE_Create(PKH_QUEUE_TYPE_NORMAL, &chan_data->media_in_queue), PK_SUCCESS, error); - TRY_OR_DIE(PKH_QUEUE_Attach(chan_data->media_in_queue, chan_data->handle, (PK_VOID*) chan), PK_SUCCESS, error); - TRY_OR_DIE(PKH_QUEUE_Attach(span_data->event_queue, chan_data->handle, (PK_VOID*) chan), PK_SUCCESS, error); - - if (profile) { - if (profile->cust_span) { - span_data->span_config.framing = profile->span_config.framing; - span_data->span_config.encoding = profile->span_config.encoding; - span_data->span_config.loopLength = profile->span_config.loopLength; - span_data->span_config.buildOut = profile->span_config.buildOut; - span_data->span_config.compandMode = profile->span_config.compandMode; - } else { - if (profile->general_config.region == PKH_TRUNK_EU) { - span_data->span_config = globals.e1_span_config; - } else { - span_data->span_config = globals.t1_span_config; - } - } - } else { - if (span->trunk_type == FTDM_TRUNK_E1) { - span_data->span_config = globals.e1_span_config; - } else { - span_data->span_config = globals.t1_span_config; - } - } - - PKH_SPAN_SetConfig(span_data->handle, &span_data->span_config); - TRY_OR_DIE(PKH_SPAN_Start(span_data->handle), PK_SUCCESS, error); - } - - goto ok; - - error: - PKH_ERROR_GetText(status, error_text, sizeof(error_text)); - ftdm_log(FTDM_LOG_ERROR, "failure configuring device b%ds%dc%d [%s]\n", boardno, spanno, x, error_text); - continue; - ok: - ftdm_set_flag(chan_data, PK_FLAG_READY); - status = PKH_RECORD_GetConfig(chan_data->media_in, &chan_data->record_config); - chan_data->record_config.encoding = PKH_RECORD_ENCODING_MU_LAW; - chan_data->record_config.samplingRate = PKH_RECORD_SAMPLING_RATE_8KHZ; - chan_data->record_config.bufferSize = PIKA_BLOCK_SIZE; - chan_data->record_config.numberOfBuffers = PIKA_NUM_BUFFERS; - chan_data->record_config.VAD.enabled = PK_FALSE; - //chan_data->record_config.speechSegmentEventsEnabled = PK_FALSE; - //chan_data->record_config.gain = rxgain; - - status = PKH_PLAY_GetConfig(chan_data->media_out, &chan_data->play_config); - chan_data->play_config.encoding = PKH_RECORD_ENCODING_MU_LAW; - chan_data->play_config.samplingRate = PKH_RECORD_SAMPLING_RATE_8KHZ; - chan_data->play_config.AGC.enabled = PK_FALSE; - ftdm_log(FTDM_LOG_INFO, "configuring device b%ds%dc%d as FreeTDM device %d:%d\n", boardno, spanno, x, chan->span_id, chan->chan_id); - - if (profile) { - ftdm_log(FTDM_LOG_INFO, "applying config profile %s to device %d:%d\n", profile->name, chan->span_id, chan->chan_id); - chan_data->record_config.gain = profile->record_config.gain; - chan_data->record_config.AGC = profile->record_config.AGC; - chan_data->record_config.VAD = profile->record_config.VAD; - chan_data->play_config.gain = profile->play_config.gain; - chan_data->play_config.AGC = profile->play_config.AGC; - chan_data->ec_enabled = profile->ec_enabled; - chan_data->ec_config = profile->ec_config; - } - - if (type == FTDM_CHAN_TYPE_B) { - if (span_data->span_config.compandMode == PKH_SPAN_COMPAND_MODE_A_LAW) { - chan->native_codec = chan->effective_codec = FTDM_CODEC_ALAW; - } else { - chan->native_codec = chan->effective_codec = FTDM_CODEC_ULAW; - } - } - - status = PKH_RECORD_SetConfig(chan_data->media_in, &chan_data->record_config); - status = PKH_PLAY_SetConfig(chan_data->media_out, &chan_data->play_config); - - chan->physical_span_id = spanno; - chan->physical_chan_id = x; - - chan->rate = 8000; - chan->packet_len = (uint32_t)chan_data->record_config.bufferSize; - chan->effective_interval = chan->native_interval = chan->packet_len / 8; - - PKH_RECORD_Start(chan_data->media_in); - PKH_PLAY_Start(chan_data->media_out); - if (chan_data->ec_enabled) { - PKH_EC_SetConfig(chan_data->media_in, &chan_data->ec_config); - PKH_EC_Start(chan_data->media_in, chan_data->media_in, chan_data->media_out); - } - - if (!ftdm_strlen_zero(name)) { - ftdm_copy_string(chan->chan_name, name, sizeof(chan->chan_name)); - } - - if (!ftdm_strlen_zero(number)) { - ftdm_copy_string(chan->chan_number, number, sizeof(chan->chan_number)); - } - - ftdm_channel_set_feature(chan, FTDM_CHANNEL_FEATURE_DTMF_GENERATE); - ftdm_buffer_create(&chan_data->digit_buffer, 128, 128, 0); - ftdm_mutex_create(&chan_data->digit_mutex); - - configured++; - } - - - return configured; -} - -/** - * \brief Initialises an freetdm pika span from a configuration string - * \param span FreeTDM span - * \param str Configuration string - * \param type FreeTDM span type - * \param name FreeTDM span name - * \param number FreeTDM span number - * \return Success or failure - */ -static FIO_CONFIGURE_SPAN_FUNCTION(pika_configure_span) -{ - int items, i; - char *mydata, *item_list[10]; - char *bd, *sp, *ch = NULL, *mx; - int boardno; - int channo; - int spanno; - int top = 0; - unsigned configured = 0; - char *profile_name = NULL; - pika_channel_profile_t *profile = NULL; - - assert(str != NULL); - - mydata = ftdm_strdup(str); - assert(mydata != NULL); - - if ((profile_name = strchr(mydata, '@'))) { - *profile_name++ = '\0'; - if (!ftdm_strlen_zero(profile_name)) { - profile = (pika_channel_profile_t *) hashtable_search(globals.profile_hash, (char *)profile_name); - } - } - - items = ftdm_separate_string(mydata, ',', item_list, (sizeof(item_list) / sizeof(item_list[0]))); - - for(i = 0; i < items; i++) { - bd = item_list[i]; - if ((sp = strchr(bd, ':'))) { - *sp++ = '\0'; - if ((ch = strchr(sp, ':'))) { - *ch++ = '\0'; - } - } - - if (!(bd && sp && ch)) { - ftdm_log(FTDM_LOG_ERROR, "Invalid input\n"); - continue; - } - - boardno = atoi(bd); - channo = atoi(ch); - spanno = atoi(sp); - - - if (boardno < 0) { - ftdm_log(FTDM_LOG_ERROR, "Invalid board number %d\n", boardno); - continue; - } - - if (channo < 0) { - ftdm_log(FTDM_LOG_ERROR, "Invalid channel number %d\n", channo); - continue; - } - - if (spanno < 0) { - ftdm_log(FTDM_LOG_ERROR, "Invalid span number %d\n", channo); - continue; - } - - if ((mx = strchr(ch, '-'))) { - mx++; - top = atoi(mx) + 1; - } else { - top = channo + 1; - } - - - if (top < 0) { - ftdm_log(FTDM_LOG_ERROR, "Invalid range number %d\n", top); - continue; - } - - configured += pika_open_range(span, boardno, spanno, channo, top, type, name, number, profile); - - } - - ftdm_safe_free(mydata); - - return configured; -} - -/** - * \brief Opens Pika channel - * \param ftdmchan Channel to open - * \return Success or failure - */ -static FIO_OPEN_FUNCTION(pika_open) -{ - pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data; - - if (!chan_data && !ftdm_test_flag(chan_data, PK_FLAG_READY)) { - return FTDM_FAIL; - } - - if (chan_data->media_in_queue) { - PKH_QUEUE_Flush(chan_data->media_in_queue); - } - - if (ftdmchan->type == FTDM_CHAN_TYPE_FXS || ftdmchan->type == FTDM_CHAN_TYPE_FXO || ftdmchan->type == FTDM_CHAN_TYPE_B) { - PKH_PLAY_Start(chan_data->media_out); - } - return FTDM_SUCCESS; -} - -/** - * \brief Closes Pika channel - * \param ftdmchan Channel to close - * \return Success - */ -static FIO_CLOSE_FUNCTION(pika_close) -{ - return FTDM_SUCCESS; -} - -/** - * \brief Waits for an event on a Pika channel - * \param ftdmchan Channel to open - * \param flags Type of event to wait for - * \param to Time to wait (in ms) - * \return Success, failure or timeout - */ -static FIO_WAIT_FUNCTION(pika_wait) -{ - pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data; - PK_STATUS status; - ftdm_wait_flag_t myflags = *flags; - PK_CHAR event_text[PKH_EVENT_MAX_NAME_LENGTH]; - - *flags = FTDM_NO_FLAGS; - - if (myflags & FTDM_READ) { - if (chan_data->hdlc_bytes) { - *flags |= FTDM_READ; - return FTDM_SUCCESS; - } - status = PKH_QUEUE_WaitOnEvent(chan_data->media_in_queue, to, &chan_data->last_media_event); - - if (status == PK_SUCCESS) { - if (chan_data->last_media_event.id == PKH_EVENT_QUEUE_TIMEOUT || chan_data->last_media_event.id == PKH_EVENT_RECORD_BUFFER_OVERFLOW) { - return FTDM_TIMEOUT; - } - - *flags |= FTDM_READ; - return FTDM_SUCCESS; - } - - PKH_EVENT_GetText(chan_data->last_media_event.id, event_text, sizeof(event_text)); - ftdm_log(FTDM_LOG_DEBUG, "Event: %s\n", event_text); - } - - return FTDM_SUCCESS; -} - -/** - * \brief Reads data from a Pika channel - * \param ftdmchan Channel to read from - * \param data Data buffer - * \param datalen Size of data buffer - * \return Success or failure - */ -static FIO_READ_FUNCTION(pika_read) -{ - pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data; - PK_STATUS status; - PK_CHAR event_text[PKH_EVENT_MAX_NAME_LENGTH]; - uint32_t len; - - if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) { - if ((status = PKH_SPAN_HDLC_GetMessage(chan_data->handle, data, *datalen)) == PK_SUCCESS) { - *datalen = chan_data->hdlc_bytes; - chan_data->hdlc_bytes = 0; - return FTDM_SUCCESS; - } - return FTDM_FAIL; - } - - if (!(len = chan_data->last_media_event.p0)) { - len = ftdmchan->packet_len; - } - - if (len < *datalen) { - *datalen = len; - } - - if ((status = PKH_RECORD_GetData(chan_data->media_in, data, *datalen)) == PK_SUCCESS) { - return FTDM_SUCCESS; - } - - - PKH_ERROR_GetText(status, event_text, sizeof(event_text)); - ftdm_log(FTDM_LOG_DEBUG, "ERR: %s\n", event_text); - return FTDM_FAIL; -} - -/** - * \brief Writes data to a Pika channel - * \param ftdmchan Channel to write to - * \param data Data buffer - * \param datalen Size of data buffer - * \return Success or failure - */ -static FIO_WRITE_FUNCTION(pika_write) -{ - pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data; - PK_STATUS status; - - if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) { - if ((status = PKH_SPAN_HDLC_SendMessage(chan_data->handle, data, *datalen)) == PK_SUCCESS) { - return FTDM_SUCCESS; - } - return FTDM_FAIL; - } - - if (PKH_PLAY_AddData(chan_data->media_out, 0, data, *datalen) == PK_SUCCESS) { - return FTDM_SUCCESS; - } - - return FTDM_FAIL; -} - -/** - * \brief Executes an FreeTDM command on a Pika channel - * \param ftdmchan Channel to execute command on - * \param command FreeTDM command to execute - * \param obj Object (unused) - * \return Success or failure - */ -static FIO_COMMAND_FUNCTION(pika_command) -{ - pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data; - //pika_span_data_t *span_data = (pika_span_data_t *) ftdmchan->span->io_data; - PK_STATUS pk_status; - ftdm_status_t status = FTDM_SUCCESS; - - switch(command) { - case FTDM_COMMAND_OFFHOOK: - { - if ((pk_status = PKH_TRUNK_SetHookSwitch(chan_data->handle, PKH_TRUNK_OFFHOOK)) != PK_SUCCESS) { - PKH_ERROR_GetText(pk_status, ftdmchan->last_error, sizeof(ftdmchan->last_error)); - GOTO_STATUS(done, FTDM_FAIL); - } else { - ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK); - } - } - break; - case FTDM_COMMAND_ONHOOK: - { - if ((pk_status = PKH_TRUNK_SetHookSwitch(chan_data->handle, PKH_TRUNK_ONHOOK)) != PK_SUCCESS) { - PKH_ERROR_GetText(pk_status, ftdmchan->last_error, sizeof(ftdmchan->last_error)); - GOTO_STATUS(done, FTDM_FAIL); - } else { - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK); - } - } - break; - case FTDM_COMMAND_GENERATE_RING_ON: - { - if ((pk_status = PKH_PHONE_RingStart(chan_data->handle, 0, 0)) != PK_SUCCESS) { - PKH_ERROR_GetText(pk_status, ftdmchan->last_error, sizeof(ftdmchan->last_error)); - GOTO_STATUS(done, FTDM_FAIL); - } else { - ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_RINGING); - } - } - break; - case FTDM_COMMAND_GENERATE_RING_OFF: - { - if ((pk_status = PKH_PHONE_RingStop(chan_data->handle)) != PK_SUCCESS) { - PKH_ERROR_GetText(pk_status, ftdmchan->last_error, sizeof(ftdmchan->last_error)); - GOTO_STATUS(done, FTDM_FAIL); - } else { - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_RINGING); - } - } - break; - case FTDM_COMMAND_GET_INTERVAL: - { - - FTDM_COMMAND_OBJ_INT = ftdmchan->native_interval; - - } - break; - case FTDM_COMMAND_SET_INTERVAL: - { - int interval = FTDM_COMMAND_OBJ_INT; - int len = interval * 8; - chan_data->record_config.bufferSize = len; - chan_data->record_config.numberOfBuffers = (PK_UINT)chan_data->record_config.bufferSize; - ftdmchan->packet_len = (uint32_t)chan_data->record_config.bufferSize; - ftdmchan->effective_interval = ftdmchan->native_interval = ftdmchan->packet_len / 8; - PKH_RECORD_SetConfig(chan_data->media_in, &chan_data->record_config); - GOTO_STATUS(done, FTDM_SUCCESS); - } - break; - case FTDM_COMMAND_GET_DTMF_ON_PERIOD: - { - - FTDM_COMMAND_OBJ_INT = ftdmchan->dtmf_on; - GOTO_STATUS(done, FTDM_SUCCESS); - - } - break; - case FTDM_COMMAND_GET_DTMF_OFF_PERIOD: - { - FTDM_COMMAND_OBJ_INT = ftdmchan->dtmf_on; - GOTO_STATUS(done, FTDM_SUCCESS); - } - break; - case FTDM_COMMAND_SET_DTMF_ON_PERIOD: - { - int val = FTDM_COMMAND_OBJ_INT; - if (val > 10 && val < 1000) { - ftdmchan->dtmf_on = val; - GOTO_STATUS(done, FTDM_SUCCESS); - } else { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "invalid value %d range 10-1000", val); - GOTO_STATUS(done, FTDM_FAIL); - } - } - break; - case FTDM_COMMAND_SET_DTMF_OFF_PERIOD: - { - int val = FTDM_COMMAND_OBJ_INT; - if (val > 10 && val < 1000) { - ftdmchan->dtmf_off = val; - GOTO_STATUS(done, FTDM_SUCCESS); - } else { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "invalid value %d range 10-1000", val); - GOTO_STATUS(done, FTDM_FAIL); - } - } - break; - case FTDM_COMMAND_SEND_DTMF: - { - char *digits = FTDM_COMMAND_OBJ_CHAR_P; - ftdm_log(FTDM_LOG_DEBUG, "Adding DTMF SEQ [%s]\n", digits); - ftdm_mutex_lock(chan_data->digit_mutex); - ftdm_buffer_write(chan_data->digit_buffer, digits, strlen(digits)); - ftdm_mutex_unlock(chan_data->digit_mutex); - pk_status = PKH_PLAY_Stop(chan_data->media_out); - - if (pk_status != PK_SUCCESS) { - PKH_ERROR_GetText(pk_status, ftdmchan->last_error, sizeof(ftdmchan->last_error)); - GOTO_STATUS(done, FTDM_FAIL); - } - GOTO_STATUS(done, FTDM_SUCCESS); - } - break; - default: - break; - }; - - done: - return status; -} - -/** - * \brief Checks for events on a Pika span - * \param span Span to check for events - * \param ms Time to wait for event - * \return Success if event is waiting or failure if not - */ -static FIO_SPAN_POLL_EVENT_FUNCTION(pika_poll_event) -{ - pika_span_data_t *span_data = (pika_span_data_t *) span->io_data; - PK_STATUS status; - PK_CHAR event_text[PKH_EVENT_MAX_NAME_LENGTH]; - - status = PKH_QUEUE_WaitOnEvent(span_data->event_queue, ms, &span_data->last_oob_event); - - if (status == PK_SUCCESS) { - ftdm_channel_t *ftdmchan = NULL; - uint32_t *data = (uint32_t *) span_data->last_oob_event.userData; - ftdm_data_type_t data_type = FTDM_TYPE_NONE; - - if (span_data->last_oob_event.id == PKH_EVENT_QUEUE_TIMEOUT) { - return FTDM_TIMEOUT; - } - - if (data) { - data_type = *data; - } - - if (data_type == FTDM_TYPE_CHANNEL) { - ftdmchan = span_data->last_oob_event.userData; - } else if (data_type == FTDM_TYPE_SPAN) { - ftdm_time_t last_event_time = ftdm_current_time_in_ms(); - uint32_t event_id = 0; - - switch (span_data->last_oob_event.id) { - case PKH_EVENT_SPAN_ALARM_T1_RED: - case PKH_EVENT_SPAN_ALARM_T1_YELLOW: - case PKH_EVENT_SPAN_ALARM_T1_AIS: - case PKH_EVENT_SPAN_ALARM_E1_RED: - case PKH_EVENT_SPAN_ALARM_E1_RAI: - case PKH_EVENT_SPAN_ALARM_E1_AIS: - case PKH_EVENT_SPAN_ALARM_E1_RMAI: - case PKH_EVENT_SPAN_ALARM_E1_TS16AIS: - case PKH_EVENT_SPAN_ALARM_E1_TS16LOS: - case PKH_EVENT_SPAN_OUT_OF_SYNC: - case PKH_EVENT_SPAN_FRAMING_ERROR: - case PKH_EVENT_SPAN_LOSS_OF_SIGNAL: - case PKH_EVENT_SPAN_OUT_OF_CRC_MF_SYNC: - case PKH_EVENT_SPAN_OUT_OF_CAS_MF_SYNC: - event_id = FTDM_OOB_ALARM_TRAP; - break; - case PKH_EVENT_SPAN_ALARM_T1_RED_CLEAR: - case PKH_EVENT_SPAN_ALARM_T1_YELLOW_CLEAR: - case PKH_EVENT_SPAN_ALARM_T1_AIS_CLEAR: - case PKH_EVENT_SPAN_ALARM_E1_RED_CLEAR: - case PKH_EVENT_SPAN_ALARM_E1_RAI_CLEAR: - case PKH_EVENT_SPAN_ALARM_E1_AIS_CLEAR: - case PKH_EVENT_SPAN_ALARM_E1_RMAI_CLEAR: - case PKH_EVENT_SPAN_ALARM_E1_TS16AIS_CLEAR: - case PKH_EVENT_SPAN_ALARM_E1_TS16LOS_CLEAR: - case PKH_EVENT_SPAN_IN_SYNC: - case PKH_EVENT_SPAN_LOSS_OF_SIGNAL_CLEAR: - case PKH_EVENT_SPAN_IN_CRC_MF_SYNC: - case PKH_EVENT_SPAN_IN_CAS_MF_SYNC: - event_id = FTDM_OOB_ALARM_CLEAR; - break; - case PKH_EVENT_SPAN_MESSAGE: - case PKH_EVENT_SPAN_ABCD_SIGNAL_CHANGE: - break; - } - - if (event_id) { - uint32_t x = 0; - ftdm_channel_t *ftdmchan; - pika_chan_data_t *chan_data; - for(x = 1; x <= span->chan_count; x++) { - ftdmchan = span->channels[x]; - assert(ftdmchan != NULL); - chan_data = (pika_chan_data_t *) ftdmchan->io_data; - assert(chan_data != NULL); - - - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_EVENT); - ftdmchan->last_event_time = last_event_time; - chan_data->last_oob_event = span_data->last_oob_event; - } - - } - - } - - PKH_EVENT_GetText(span_data->last_oob_event.id, event_text, sizeof(event_text)); - //ftdm_log(FTDM_LOG_DEBUG, "Event: %s\n", event_text); - - if (ftdmchan) { - pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data; - - assert(chan_data != NULL); - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_EVENT); - ftdmchan->last_event_time = ftdm_current_time_in_ms(); - chan_data->last_oob_event = span_data->last_oob_event; - } - - return FTDM_SUCCESS; - } - - return FTDM_FAIL; -} - -/** - * \brief Retrieves an event from a Pika span - * \param span Span to retrieve event from - * \param event FreeTDM event to return - * \return Success or failure - */ -static FIO_SPAN_NEXT_EVENT_FUNCTION(pika_next_event) -{ - uint32_t i, event_id = 0; - - for(i = 1; i <= span->chan_count; i++) { - if (ftdm_test_flag(span->channels[i], FTDM_CHANNEL_EVENT)) { - pika_chan_data_t *chan_data = (pika_chan_data_t *) span->channels[i]->io_data; - PK_CHAR event_text[PKH_EVENT_MAX_NAME_LENGTH]; - - ftdm_clear_flag(span->channels[i], FTDM_CHANNEL_EVENT); - - PKH_EVENT_GetText(chan_data->last_oob_event.id, event_text, sizeof(event_text)); - - switch(chan_data->last_oob_event.id) { - case PKH_EVENT_HDLC_MESSAGE: - chan_data->hdlc_bytes = chan_data->last_oob_event.p2; - continue; - case PKH_EVENT_TRUNK_HOOKFLASH: - event_id = FTDM_OOB_FLASH; - break; - case PKH_EVENT_TRUNK_RING_OFF: - event_id = FTDM_OOB_RING_STOP; - break; - case PKH_EVENT_TRUNK_RING_ON: - event_id = FTDM_OOB_RING_START; - break; - - case PKH_EVENT_PHONE_OFFHOOK: - ftdm_set_flag_locked(span->channels[i], FTDM_CHANNEL_OFFHOOK); - event_id = FTDM_OOB_OFFHOOK; - break; - - case PKH_EVENT_TRUNK_BELOW_THRESHOLD: - case PKH_EVENT_TRUNK_ABOVE_THRESHOLD: - case PKH_EVENT_PHONE_ONHOOK: - ftdm_clear_flag_locked(span->channels[i], FTDM_CHANNEL_OFFHOOK); - event_id = FTDM_OOB_ONHOOK; - break; - - - - case PKH_EVENT_SPAN_ALARM_T1_RED: - ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_RED); - snprintf(span->channels[i]->last_error, sizeof(span->channels[i]->last_error), "RED ALARM"); - event_id = FTDM_OOB_ALARM_TRAP; - break; - case PKH_EVENT_SPAN_ALARM_T1_YELLOW: - ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_YELLOW); - snprintf(span->channels[i]->last_error, sizeof(span->channels[i]->last_error), "YELLOW ALARM"); - event_id = FTDM_OOB_ALARM_TRAP; - break; - case PKH_EVENT_SPAN_ALARM_T1_AIS: - ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_AIS); - snprintf(span->channels[i]->last_error, sizeof(span->channels[i]->last_error), "AIS ALARM"); - event_id = FTDM_OOB_ALARM_TRAP; - break; - case PKH_EVENT_SPAN_ALARM_E1_RED: - ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_RED); - snprintf(span->channels[i]->last_error, sizeof(span->channels[i]->last_error), "RED ALARM"); - event_id = FTDM_OOB_ALARM_TRAP; - break; - case PKH_EVENT_SPAN_ALARM_E1_RAI: - ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_RAI); - snprintf(span->channels[i]->last_error, sizeof(span->channels[i]->last_error), "RAI ALARM"); - event_id = FTDM_OOB_ALARM_TRAP; - break; - case PKH_EVENT_SPAN_ALARM_E1_AIS: - ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_AIS); - snprintf(span->channels[i]->last_error, sizeof(span->channels[i]->last_error), "AIS ALARM"); - event_id = FTDM_OOB_ALARM_TRAP; - break; - case PKH_EVENT_SPAN_ALARM_E1_RMAI: - case PKH_EVENT_SPAN_ALARM_E1_TS16AIS: - case PKH_EVENT_SPAN_ALARM_E1_TS16LOS: - case PKH_EVENT_SPAN_OUT_OF_SYNC: - case PKH_EVENT_SPAN_FRAMING_ERROR: - case PKH_EVENT_SPAN_LOSS_OF_SIGNAL: - case PKH_EVENT_SPAN_OUT_OF_CRC_MF_SYNC: - case PKH_EVENT_SPAN_OUT_OF_CAS_MF_SYNC: - ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_GENERAL); - snprintf(span->channels[i]->last_error, sizeof(span->channels[i]->last_error), "GENERAL ALARM"); - event_id = FTDM_OOB_ALARM_TRAP; - break; - case PKH_EVENT_SPAN_ALARM_T1_RED_CLEAR: - ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_RED); - case PKH_EVENT_SPAN_ALARM_T1_YELLOW_CLEAR: - ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_YELLOW); - case PKH_EVENT_SPAN_ALARM_T1_AIS_CLEAR: - ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_AIS); - case PKH_EVENT_SPAN_ALARM_E1_RED_CLEAR: - ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_RED); - case PKH_EVENT_SPAN_ALARM_E1_RAI_CLEAR: - ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_RAI); - case PKH_EVENT_SPAN_ALARM_E1_AIS_CLEAR: - ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_AIS); - case PKH_EVENT_SPAN_ALARM_E1_RMAI_CLEAR: - case PKH_EVENT_SPAN_ALARM_E1_TS16AIS_CLEAR: - case PKH_EVENT_SPAN_ALARM_E1_TS16LOS_CLEAR: - case PKH_EVENT_SPAN_IN_SYNC: - case PKH_EVENT_SPAN_LOSS_OF_SIGNAL_CLEAR: - case PKH_EVENT_SPAN_IN_CRC_MF_SYNC: - case PKH_EVENT_SPAN_IN_CAS_MF_SYNC: - ftdm_clear_alarm_flag(span->channels[i], FTDM_ALARM_GENERAL); - event_id = FTDM_OOB_ALARM_CLEAR; - break; - case PKH_EVENT_SPAN_MESSAGE: - case PKH_EVENT_SPAN_ABCD_SIGNAL_CHANGE: - break; - - - - - case PKH_EVENT_TRUNK_ONHOOK: - case PKH_EVENT_TRUNK_OFFHOOK: - case PKH_EVENT_TRUNK_DIALED : - case PKH_EVENT_TRUNK_REVERSAL: - case PKH_EVENT_TRUNK_LCSO: - case PKH_EVENT_TRUNK_DROPOUT: - case PKH_EVENT_TRUNK_LOF: - case PKH_EVENT_TRUNK_RX_OVERLOAD: - default: - ftdm_log(FTDM_LOG_DEBUG, "Unhandled event %d on channel %d [%s]\n", chan_data->last_oob_event.id, i, event_text); - event_id = FTDM_OOB_INVALID; - break; - } - - span->channels[i]->last_event_time = 0; - span->event_header.e_type = FTDM_EVENT_OOB; - span->event_header.enum_id = event_id; - span->event_header.channel = span->channels[i]; - *event = &span->event_header; - return FTDM_SUCCESS; - } - } - - return FTDM_FAIL; -} - -/** - * \brief Destroys a Pika Span - * \param span Span to destroy - * \return Success - */ -static FIO_SPAN_DESTROY_FUNCTION(pika_span_destroy) -{ - pika_span_data_t *span_data = (pika_span_data_t *) span->io_data; - - if (span_data) { - PKH_QUEUE_Destroy(span_data->event_queue); - ftdm_safe_free(span_data); - } - - return FTDM_SUCCESS; -} - -/** - * \brief Destroys a Pika Channel - * \param ftdmchan Channel to destroy - * \return Success or failure - */ -static FIO_CHANNEL_DESTROY_FUNCTION(pika_channel_destroy) -{ - pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data; - pika_span_data_t *span_data = (pika_span_data_t *) ftdmchan->span->io_data; - - if (!chan_data) { - return FTDM_FAIL; - } - - if (!ftdm_test_flag(chan_data, PK_FLAG_READY)) { - goto end; - } - - PKH_RECORD_Stop(chan_data->media_in); - PKH_PLAY_Stop(chan_data->media_out); - PKH_QUEUE_Destroy(chan_data->media_in_queue); - PKH_QUEUE_Destroy(chan_data->media_out_queue); - - switch(ftdmchan->type) { - case FTDM_CHAN_TYPE_FXS: - PKH_QUEUE_Detach(span_data->event_queue, chan_data->handle); - PKH_PHONE_Close(chan_data->handle); - break; - case FTDM_CHAN_TYPE_FXO: - PKH_QUEUE_Detach(span_data->event_queue, chan_data->handle); - PKH_TRUNK_Close(chan_data->handle); - break; - case FTDM_CHAN_TYPE_DQ921: - PKH_SPAN_Stop(span_data->handle); - break; - default: - break; - } - - - ftdm_mutex_destroy(&chan_data->digit_mutex); - ftdm_buffer_destroy(&chan_data->digit_buffer); - - end: - ftdm_safe_free(chan_data); - - return FTDM_SUCCESS; -} - -/** - * \brief Gets alarms from a Pika Channel (does nothing) - * \param ftdmchan Channel to get alarms from - * \return Failure - */ -static FIO_GET_ALARMS_FUNCTION(pika_get_alarms) -{ - return FTDM_FAIL; -} - -static ftdm_io_interface_t pika_interface; - -/** - * \brief Loads Pika IO module - * \param fio FreeTDM IO interface - * \return Success or failure - */ -static FIO_IO_LOAD_FUNCTION(pika_init) -{ - - PK_STATUS status; - PK_CHAR error_text[PKH_ERROR_MAX_NAME_LENGTH]; - uint32_t i; - int ok = 0; - PKH_TLogMasks m; - TPikaHandle tmpHandle; - - assert(fio != NULL); - memset(&pika_interface, 0, sizeof(pika_interface)); - memset(&globals, 0, sizeof(globals)); - globals.general_config.region = PKH_TRUNK_NA; - - globals.profile_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); - - // Open the system object, to enumerate boards configured for this system - if ((status = PKH_SYSTEM_Open(&globals.system_handle)) != PK_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error: PKH_SYSTEM_Open failed(%s)!\n", - PKH_ERROR_GetText(status, error_text, sizeof(error_text))); - return FTDM_FAIL; - } - - // Retrieves a list of all boards in this system, existing, - // or listed in pika.cfg - if ((status = PKH_SYSTEM_Detect(globals.system_handle, &globals.board_list)) != PK_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error: PKH_SYSTEM_Detect failed(%s)!\n", - PKH_ERROR_GetText(status, error_text, sizeof(error_text))); - return FTDM_FAIL; - } - - PKH_SYSTEM_GetConfig(globals.system_handle, &globals.system_config); - globals.system_config.maxAudioProcessBlockSize = PIKA_BLOCK_LEN; - globals.system_config.playBufferSize = PIKA_BLOCK_SIZE; - globals.system_config.recordBufferSize = PIKA_BLOCK_SIZE; - globals.system_config.recordNumberOfBuffers = PIKA_NUM_BUFFERS; - PKH_SYSTEM_SetConfig(globals.system_handle, &globals.system_config); - - status = PKH_MEDIA_STREAM_Create(&tmpHandle); - status = PKH_RECORD_GetConfig(tmpHandle, &globals.record_config); - status = PKH_PLAY_GetConfig(tmpHandle, &globals.play_config); - status = PKH_EC_GetConfig(tmpHandle, &globals.ec_config); - status = PKH_MEDIA_STREAM_Destroy(tmpHandle); - - - - ftdm_log(FTDM_LOG_DEBUG, "Found %u board%s\n", globals.board_list.numberOfBoards, globals.board_list.numberOfBoards == 1 ? "" : "s"); - for(i = 0; i < globals.board_list.numberOfBoards; ++i) { - ftdm_log(FTDM_LOG_INFO, "Found PIKA board type:[%s] id:[%u] serno:[%u]\n", - pika_board_type_string(globals.board_list.board[i].type), globals.board_list.board[i].id, (uint32_t) - globals.board_list.board[i].serialNumber); - - if (globals.board_list.board[i].type == PKH_BOARD_TYPE_DIGITAL_GATEWAY) { - TPikaHandle board_handle, span_handle; - PKH_TBoardConfig boardConfig; - PKH_BOARD_GetConfig(board_handle, &boardConfig); - PKH_BOARD_Open(globals.board_list.board[i].id, NULL, &board_handle); - PKH_SPAN_Open(board_handle, 0, NULL, &span_handle); - PKH_SPAN_GetConfig(span_handle, &globals.t1_span_config); - PKH_SPAN_Close(span_handle); - boardConfig.specific.DigitalGateway.interfaceType = PKH_BOARD_INTERFACE_TYPE_E1; - PKH_BOARD_SetConfig(board_handle, &boardConfig); - PKH_SPAN_Open(board_handle, 0, NULL, &span_handle); - PKH_SPAN_GetConfig(span_handle, &globals.e1_span_config); - PKH_SPAN_Close(span_handle); - boardConfig.specific.DigitalGateway.interfaceType = PKH_BOARD_INTERFACE_TYPE_T1; - PKH_BOARD_SetConfig(board_handle, &boardConfig); - PKH_BOARD_Close(board_handle); - } - ok++; - - } - - if (!ok) { - return FTDM_FAIL; - } - - pika_interface.name = "pika"; - pika_interface.configure = pika_configure; - pika_interface.configure_span = pika_configure_span; - pika_interface.open = pika_open; - pika_interface.close = pika_close; - pika_interface.wait = pika_wait; - pika_interface.read = pika_read; - pika_interface.write = pika_write; - pika_interface.command = pika_command; - pika_interface.poll_event = pika_poll_event; - pika_interface.next_event = pika_next_event; - pika_interface.channel_destroy = pika_channel_destroy; - pika_interface.span_destroy = pika_span_destroy; - pika_interface.get_alarms = pika_get_alarms; - *fio = &pika_interface; - - - ftdm_log(FTDM_LOG_INFO, "Dumping Default configs:\n"); - ftdm_log(FTDM_LOG_INFO, "rx-gain => %0.2f\n", (float)globals.record_config.gain); - ftdm_log(FTDM_LOG_INFO, "rx-agc-enabled => %s\n", globals.record_config.AGC.enabled ? "true" : "false"); - ftdm_log(FTDM_LOG_INFO, "rx-agc-targetPower => %0.2f\n", (float)globals.record_config.AGC.targetPower); - ftdm_log(FTDM_LOG_INFO, "rx-agc-minGain => %0.2f\n", (float)globals.record_config.AGC.minGain); - ftdm_log(FTDM_LOG_INFO, "rx-agc-maxGain => %0.2f\n", (float)globals.record_config.AGC.maxGain); - ftdm_log(FTDM_LOG_INFO, "rx-agc-attackRate => %d\n", (int)globals.record_config.AGC.attackRate); - ftdm_log(FTDM_LOG_INFO, "rx-agc-decayRate => %d\n", (int)globals.record_config.AGC.decayRate); - ftdm_log(FTDM_LOG_INFO, "rx-agc-speechThreshold => %0.2f\n", (float)globals.record_config.AGC.speechThreshold); - ftdm_log(FTDM_LOG_INFO, "rx-vad-enabled => %s\n", globals.record_config.VAD.enabled ? "true" : "false"); - ftdm_log(FTDM_LOG_INFO, "rx-vad-activationThreshold => %0.2f\n", (float)globals.record_config.VAD.activationThreshold); - ftdm_log(FTDM_LOG_INFO, "rx-vad-activationDebounceTime => %d\n", (int)globals.record_config.VAD.activationDebounceTime); - ftdm_log(FTDM_LOG_INFO, "rx-vad-deactivationThreshold => %0.2f\n", (float)globals.record_config.VAD.deactivationThreshold); - ftdm_log(FTDM_LOG_INFO, "rx-vad-deactivationDebounceTime => %d\n", (int)globals.record_config.VAD.deactivationDebounceTime); - ftdm_log(FTDM_LOG_INFO, "rx-vad-preSpeechBufferSize => %d\n", (int)globals.record_config.VAD.preSpeechBufferSize); - ftdm_log(FTDM_LOG_INFO, "tx-gain => %0.2f\n", (float)globals.play_config.gain); - ftdm_log(FTDM_LOG_INFO, "tx-agc-enabled => %s\n", globals.play_config.AGC.enabled ? "true" : "false"); - ftdm_log(FTDM_LOG_INFO, "tx-agc-targetPower => %0.2f\n", (float)globals.play_config.AGC.targetPower); - ftdm_log(FTDM_LOG_INFO, "tx-agc-minGain => %0.2f\n", (float)globals.play_config.AGC.minGain); - ftdm_log(FTDM_LOG_INFO, "tx-agc-maxGain => %0.2f\n", (float)globals.play_config.AGC.maxGain); - ftdm_log(FTDM_LOG_INFO, "tx-agc-attackRate => %d\n", (int)globals.play_config.AGC.attackRate); - ftdm_log(FTDM_LOG_INFO, "tx-agc-decayRate => %d\n", (int)globals.play_config.AGC.decayRate); - ftdm_log(FTDM_LOG_INFO, "tx-agc-speechThreshold => %0.2f\n", (float)globals.play_config.AGC.speechThreshold); - ftdm_log(FTDM_LOG_INFO, "ec-doubleTalkerThreshold => %0.2f\n", (float)globals.ec_config.doubleTalkerThreshold); - ftdm_log(FTDM_LOG_INFO, "ec-speechPresentThreshold => %0.2f\n", (float)globals.ec_config.speechPresentThreshold); - ftdm_log(FTDM_LOG_INFO, "ec-echoSuppressionThreshold => %0.2f\n", (float)globals.ec_config.echoSuppressionThreshold); - ftdm_log(FTDM_LOG_INFO, "ec-echoSuppressionEnabled => %s\n", globals.ec_config.echoSuppressionEnabled ? "true" : "false"); - ftdm_log(FTDM_LOG_INFO, "ec-comfortNoiseEnabled => %s\n", globals.ec_config.comfortNoiseEnabled ? "true" : "false"); - ftdm_log(FTDM_LOG_INFO, "ec-adaptationModeEnabled => %s\n", globals.ec_config.adaptationModeEnabled ? "true" : "false"); - - - - memset(&m, 0, sizeof(m)); - //m.apiMask = 0xffffffff; - //PKH_LOG_SetMasks(&m); - - return FTDM_SUCCESS; -} - -/** - * \brief Unloads Pika IO module - * \return Success - */ -static FIO_IO_UNLOAD_FUNCTION(pika_destroy) -{ - uint32_t x; - PK_STATUS status; - PK_CHAR error_text[PKH_ERROR_MAX_NAME_LENGTH]; - - for (x = 0; x < MAX_NUMBER_OF_TRUNKS; x++) { - if (globals.open_boards[x]) { - ftdm_log(FTDM_LOG_INFO, "Closing board %u\n", x); - PKH_BOARD_Close(globals.open_boards[x]); - } - } - - // The system can now be closed. - if ((status = PKH_SYSTEM_Close(globals.system_handle)) != PK_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error: PKH_SYSTEM_Close failed(%s)!\n", - PKH_ERROR_GetText(status, error_text, sizeof(error_text))); - } else { - ftdm_log(FTDM_LOG_INFO, "Closing system handle\n"); - } - - hashtable_destroy(globals.profile_hash); - - return FTDM_SUCCESS; -} - -/** - * \brief Pika IO module definition - */ -EX_DECLARE_DATA ftdm_module_t ftdm_module = { - "pika", - pika_init, - pika_destroy, -}; - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - diff --git a/libs/freetdm/src/ftmod/ftmod_pika/ozmod_pika.2005.vcproj b/libs/freetdm/src/ftmod/ftmod_pika/ozmod_pika.2005.vcproj deleted file mode 100644 index 646cc11428..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_pika/ozmod_pika.2005.vcproj +++ /dev/null @@ -1,197 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/src/ftmod/ftmod_pritap/ftmod_pritap.c b/libs/freetdm/src/ftmod/ftmod_pritap/ftmod_pritap.c deleted file mode 100644 index 38f9c48e84..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_pritap/ftmod_pritap.c +++ /dev/null @@ -1,1189 +0,0 @@ -/* - * Copyright (c) 2010, Moises Silva - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include "private/ftdm_core.h" - -#define PRI_SPAN(p) (((p) >> 8) & 0xff) -#define PRI_CHANNEL(p) ((p) & 0xff) - -#define PRITAP_NETWORK_ANSWER 0x1 - -typedef enum { - PRITAP_RUNNING = (1 << 0), - PRITAP_MASTER = (1 << 1), -} pritap_flags_t; - -typedef enum { - PRITAP_MIX_BOTH = 0, - PRITAP_MIX_PEER, - PRITAP_MIX_SELF, -} pritap_mix_mode_t; - -typedef struct { - void *callref; - ftdm_number_t callingnum; - ftdm_number_t callingani; - ftdm_number_t callednum; - ftdm_channel_t *fchan; - char callingname[80]; - uint8_t proceeding; - uint8_t inuse; -} passive_call_t; - -typedef enum pritap_iface { - PRITAP_IFACE_UNKNOWN = 0, - PRITAP_IFACE_CPE = 1, - PRITAP_IFACE_NET = 2, -} pritap_iface_t; - -typedef struct pritap { - int32_t flags; - struct pri *pri; - int debug; - pritap_mix_mode_t mixaudio; - ftdm_channel_t *dchan; - ftdm_span_t *span; - ftdm_span_t *peerspan; - ftdm_mutex_t *pcalls_lock; - passive_call_t pcalls[FTDM_MAX_CHANNELS_PHYSICAL_SPAN]; - pritap_iface_t iface; -} pritap_t; - -static FIO_IO_UNLOAD_FUNCTION(ftdm_pritap_unload) -{ - return FTDM_SUCCESS; -} - -static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(pritap_get_channel_sig_status) -{ - *status = FTDM_SIG_STATE_UP; - return FTDM_SUCCESS; -} - -static FIO_SPAN_GET_SIG_STATUS_FUNCTION(pritap_get_span_sig_status) -{ - *status = FTDM_SIG_STATE_UP; - return FTDM_SUCCESS; -} - - -static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(pritap_outgoing_call) -{ - ftdm_log(FTDM_LOG_ERROR, "Cannot dial on PRI tapping line!\n"); - return FTDM_FAIL; -} - -static void s_pri_error(struct pri *pri, char *s) -{ - pritap_t *pritap = pri_get_userdata(pri); - - if (pritap && pritap->dchan) { - ftdm_log_chan(pritap->dchan, FTDM_LOG_ERROR, "%s", s); - } else { - ftdm_log(FTDM_LOG_ERROR, "%s", s); - } -} - -static void s_pri_message(struct pri *pri, char *s) -{ - pritap_t *pritap = pri_get_userdata(pri); - - if (pritap && pritap->dchan) { - ftdm_log_chan(pritap->dchan, FTDM_LOG_DEBUG, "%s", s); - } else { - ftdm_log(FTDM_LOG_DEBUG, "%s", s); - } -} - -#define PRI_DEBUG_Q921_ALL (PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE) -#define PRI_DEBUG_Q931_ALL (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | PRI_DEBUG_Q931_ANOMALY) - -static int parse_debug(const char *in) -{ - int flags = 0; - - if (!in) { - return 0; - } - - if (!strcmp(in, "none")) { - return 0; - } - - if (!strcmp(in, "all")) { - return PRI_DEBUG_ALL; - } - - if (strstr(in, "q921_all")) { - flags |= PRI_DEBUG_Q921_ALL; - } - - if (strstr(in, "q921_raw")) { - flags |= PRI_DEBUG_Q921_RAW; - } - - if (strstr(in, "q921_dump")) { - flags |= PRI_DEBUG_Q921_DUMP; - } - - if (strstr(in, "q921_state")) { - flags |= PRI_DEBUG_Q921_STATE; - } - - if (strstr(in, "config")) { - flags |= PRI_DEBUG_CONFIG; - } - - if (strstr(in, "q931_all")) { - flags |= PRI_DEBUG_Q931_ALL; - } - - if (strstr(in, "q931_dump")) { - flags |= PRI_DEBUG_Q931_DUMP; - } - - if (strstr(in, "q931_state")) { - flags |= PRI_DEBUG_Q931_STATE; - } - - if (strstr(in, "q931_anomaly")) { - flags |= PRI_DEBUG_Q931_ANOMALY; - } - - if (strstr(in, "apdu")) { - flags |= PRI_DEBUG_APDU; - } - - if (strstr(in, "aoc")) { - flags |= PRI_DEBUG_AOC; - } - - return flags; -} - -static ftdm_io_interface_t ftdm_pritap_interface; - -static ftdm_status_t ftdm_pritap_start(ftdm_span_t *span); - -static FIO_API_FUNCTION(ftdm_pritap_api) -{ - char *mycmd = NULL, *argv[10] = { 0 }; - int argc = 0; - - if (data) { - mycmd = ftdm_strdup(data); - argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); - } - - if (argc > 2) { - if (!strcasecmp(argv[0], "debug")) { - ftdm_span_t *span = NULL; - - if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) { - pritap_t *pritap = span->signal_data; - if (span->start != ftdm_pritap_start) { - stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); - goto done; - } - - pri_set_debug(pritap->pri, parse_debug(argv[2])); - stream->write_function(stream, "%s: +OK debug set.\n", __FILE__); - goto done; - } else { - stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); - goto done; - } - } - - } - - stream->write_function(stream, "%s: -ERR invalid command.\n", __FILE__); - - done: - - ftdm_safe_free(mycmd); - - return FTDM_SUCCESS; -} - -static FIO_IO_LOAD_FUNCTION(ftdm_pritap_io_init) -{ - memset(&ftdm_pritap_interface, 0, sizeof(ftdm_pritap_interface)); - - ftdm_pritap_interface.name = "pritap"; - ftdm_pritap_interface.api = ftdm_pritap_api; - - *fio = &ftdm_pritap_interface; - - return FTDM_SUCCESS; -} - -static FIO_SIG_LOAD_FUNCTION(ftdm_pritap_init) -{ - pri_set_error(s_pri_error); - pri_set_message(s_pri_message); - return FTDM_SUCCESS; -} - -static ftdm_state_map_t pritap_state_map = { - { - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - }, - - } -}; - -#define PRITAP_GET_INTERFACE(iface) iface == PRITAP_IFACE_CPE ? "CPE" : \ - iface == PRITAP_IFACE_NET ? "NET" : "UNKNOWN" -static ftdm_status_t state_advance(ftdm_channel_t *ftdmchan) -{ - ftdm_status_t status; - ftdm_sigmsg_t sig; - pritap_t *pritap = ftdmchan->span->signal_data; - pritap_t *peer_pritap = pritap->peerspan->signal_data; - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "processing state %s\n", ftdm_channel_state2str(ftdmchan->state)); - - memset(&sig, 0, sizeof(sig)); - sig.chan_id = ftdmchan->chan_id; - sig.span_id = ftdmchan->span_id; - sig.channel = ftdmchan; - - ftdm_channel_complete_state(ftdmchan); - - switch (ftdmchan->state) { - case FTDM_CHANNEL_STATE_DOWN: - { - ftdm_channel_t *fchan = ftdmchan; - - /* Destroy the peer data first */ - if (fchan->call_data) { - ftdm_channel_t *peerchan = fchan->call_data; - ftdm_channel_t *pchan = peerchan; - - ftdm_channel_lock(peerchan); - - pchan->call_data = NULL; - pchan->pflags = 0; - ftdm_channel_close(&pchan); - - ftdm_channel_unlock(peerchan); - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "No call data?\n"); - } - - ftdmchan->call_data = NULL; - ftdmchan->pflags = 0; - ftdm_channel_close(&fchan); - } - break; - - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - case FTDM_CHANNEL_STATE_HANGUP: - break; - - case FTDM_CHANNEL_STATE_UP: - { - if (ftdm_test_pflag(ftdmchan, PRITAP_NETWORK_ANSWER)) { - ftdm_clear_pflag(ftdmchan, PRITAP_NETWORK_ANSWER); - sig.event_id = FTDM_SIGEVENT_UP; - ftdm_span_send_signal(ftdmchan->span, &sig); - } - } - break; - - case FTDM_CHANNEL_STATE_RING: - { - sig.event_id = FTDM_SIGEVENT_START; - /* The ring interface (where the setup was received) is the peer, since we RING the channel - * where PROCEED/PROGRESS is received */ - ftdm_sigmsg_add_var(&sig, "pritap_ring_interface", PRITAP_GET_INTERFACE(peer_pritap->iface)); - if ((status = ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS)) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - } - } - break; - - case FTDM_CHANNEL_STATE_TERMINATING: - { - if (ftdmchan->last_state != FTDM_CHANNEL_STATE_HANGUP) { - sig.event_id = FTDM_SIGEVENT_STOP; - status = ftdm_span_send_signal(ftdmchan->span, &sig); - } - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - break; - - default: - { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "ignoring state change from %s to %s\n", ftdm_channel_state2str(ftdmchan->last_state), ftdm_channel_state2str(ftdmchan->state)); - } - break; - } - - return FTDM_SUCCESS; -} - -static __inline__ void pritap_check_state(ftdm_span_t *span) -{ - if (ftdm_test_flag(span, FTDM_SPAN_STATE_CHANGE)) { - uint32_t j; - ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE); - for(j = 1; j <= span->chan_count; j++) { - ftdm_channel_lock(span->channels[j]); - ftdm_channel_advance_states(span->channels[j]); - ftdm_channel_unlock(span->channels[j]); - } - } -} - -static int pri_io_read(struct pri *pri, void *buf, int buflen) -{ - int res; - ftdm_status_t zst; - pritap_t *pritap = pri_get_userdata(pri); - ftdm_size_t len = buflen; - - if ((zst = ftdm_channel_read(pritap->dchan, buf, &len)) != FTDM_SUCCESS) { - if (zst == FTDM_FAIL) { - ftdm_log(FTDM_LOG_CRIT, "span %d D channel read fail! [%s]\n", pritap->span->span_id, pritap->dchan->last_error); - } else { - ftdm_log(FTDM_LOG_CRIT, "span %d D channel read timeout!\n", pritap->span->span_id); - } - return -1; - } - - res = (int)len; - - memset(&((unsigned char*)buf)[res],0,2); - res += 2; - - /* libpri passive q921 raw dump does not work for all frames */ - if (pritap->debug & PRI_DEBUG_Q921_RAW) { - char hbuf[2048] = { 0 }; - - print_hex_bytes(buf, len, hbuf, sizeof(hbuf)); - ftdm_log_chan(pritap->dchan, FTDM_LOG_DEBUG, "READ %"FTDM_SIZE_FMT"\n%s\n", len, hbuf); - } - return res; -} - -static int pri_io_write(struct pri *pri, void *buf, int buflen) -{ - pritap_t *pritap = pri_get_userdata(pri); - ftdm_size_t len = buflen - 2; - - /* libpri passive q921 raw dump does not work for all frames */ - if (pritap->debug & PRI_DEBUG_Q921_RAW) { - char hbuf[2048] = { 0 }; - - print_hex_bytes(buf, len, hbuf, sizeof(hbuf)); - ftdm_log_chan(pritap->dchan, FTDM_LOG_DEBUG, "WRITE %"FTDM_SIZE_FMT"\n%s\n", len, hbuf); - } - - if (ftdm_channel_write(pritap->dchan, buf, buflen, &len) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "span %d D channel write failed! [%s]\n", pritap->span->span_id, pritap->dchan->last_error); - return -1; - } - - return (int)buflen; -} - -static int tap_pri_get_crv(struct pri *ctrl, q931_call *call) -{ - int callmode = 0; - int crv = pri_get_crv(ctrl, call, &callmode); - crv <<= 3; - crv |= (callmode & 0x7); - return crv; -} - -static passive_call_t *tap_pri_get_pcall_bycrv(pritap_t *pritap, int crv) -{ - int i; - int tstcrv; - - ftdm_mutex_lock(pritap->pcalls_lock); - - for (i = 0; i < ftdm_array_len(pritap->pcalls); i++) { - tstcrv = pritap->pcalls[i].callref ? tap_pri_get_crv(pritap->pri, pritap->pcalls[i].callref) : 0; - if (pritap->pcalls[i].callref && tstcrv == crv) { - if (pritap->pcalls[i].inuse) { - ftdm_mutex_unlock(pritap->pcalls_lock); - return &pritap->pcalls[i]; - } - /* This just means the crv is being re-used in another call before this one was destroyed */ - ftdm_log(FTDM_LOG_DEBUG, "Found crv %d in slot %d of span %s with call %p but is no longer in use\n", - crv, i, pritap->span->name, pritap->pcalls[i].callref); - } - } - - ftdm_log(FTDM_LOG_DEBUG, "crv %d was not found active in span %s\n", crv, pritap->span->name); - - ftdm_mutex_unlock(pritap->pcalls_lock); - - return NULL; -} - -/* - * This is a tricky function with some side effects, some explanation needed ... - * - * The libpri stack process HDLC frames, then finds Q921 frames and Q931 events, each time - * it finds a new Q931 event, checks if the crv of that event matches a known call in the internal - * list found in the PRI control block (for us, one control block per span), if it does not find - * the call, allocates a new one and then sends the event up to the user (us, ftmod_pritap in this case) - * - * The user is then expected to destroy the call when done with it (on hangup), but things get tricky here - * because in ftmod_pritap we do not destroy the call right away to be sure we only destroy it when no one - * else needs that pointer, therefore we decide to delay the destruction of the call pointer until later - * when a new call comes which triggers the garbage collecting code in this function - * - * Now, what happens if a new call arrives right away with the same crv than the last call? the pri stack - * does *not* allocate a new call pointer because is still a known call and we must therefore re-use the - * same call pointer - * - * This function accepts a pointer to a callref, even a NULL one. When callref is NULL we search for an - * available slot so the caller of this function can use it to store a new callref pointer. In the process - * we also scan for slots that still have a callref pointer but are no longer in use (inuse=0) and we - * destroy that callref and clear the slot (memset). The trick is, we only do this if the callref to - * be garbage collected is NOT the one provided by the parameter callref, of course! otherwise we may - * be freeing a pointer to a callref for a new call that used an old (recycled) callref! - */ -static passive_call_t *tap_pri_get_pcall(pritap_t *pritap, void *callref) -{ - int i; - int crv; - - ftdm_mutex_lock(pritap->pcalls_lock); - - for (i = 0; i < ftdm_array_len(pritap->pcalls); i++) { - /* If this slot has a call reference - * and it is different than the *callref provided to us - * and is no longer in use, - * then it is time to garbage collect it ... */ - if (pritap->pcalls[i].callref && callref != pritap->pcalls[i].callref && !pritap->pcalls[i].inuse) { - crv = tap_pri_get_crv(pritap->pri, pritap->pcalls[i].callref); - /* garbage collection */ - ftdm_log(FTDM_LOG_DEBUG, "Garbage collecting callref %d/%p from span %s in slot %d\n", - crv, pritap->pcalls[i].callref, pritap->span->name, i); - pri_passive_destroycall(pritap->pri, pritap->pcalls[i].callref); - memset(&pritap->pcalls[i], 0, sizeof(pritap->pcalls[0])); - } - if (callref == pritap->pcalls[i].callref) { - if (callref == NULL) { - pritap->pcalls[i].inuse = 1; - ftdm_log(FTDM_LOG_DEBUG, "Enabling callref slot %d in span %s\n", i, pritap->span->name); - } else if (!pritap->pcalls[i].inuse) { - crv = tap_pri_get_crv(pritap->pri, callref); - ftdm_log(FTDM_LOG_DEBUG, "Recyclying callref slot %d in span %s for callref %d/%p\n", - i, pritap->span->name, crv, callref); - memset(&pritap->pcalls[i], 0, sizeof(pritap->pcalls[0])); - pritap->pcalls[i].callref = callref; - pritap->pcalls[i].inuse = 1; - } - - ftdm_mutex_unlock(pritap->pcalls_lock); - - return &pritap->pcalls[i]; - } - } - - ftdm_mutex_unlock(pritap->pcalls_lock); - - return NULL; -} - -static void tap_pri_put_pcall(pritap_t *pritap, void *callref) -{ - int i; - int crv; - int tstcrv; - - if (!callref) { - ftdm_log(FTDM_LOG_ERROR, "Cannot put pcall for null callref in span %s\n", pritap->span->name); - return; - } - - ftdm_mutex_lock(pritap->pcalls_lock); - - crv = tap_pri_get_crv(pritap->pri, callref); - for (i = 0; i < ftdm_array_len(pritap->pcalls); i++) { - if (!pritap->pcalls[i].callref) { - continue; - } - tstcrv = tap_pri_get_crv(pritap->pri, pritap->pcalls[i].callref); - if (tstcrv == crv) { - if (pritap->pcalls[i].inuse) { - ftdm_log(FTDM_LOG_DEBUG, "releasing slot %d in span %s used by callref %d/%p\n", i, - pritap->span->name, crv, pritap->pcalls[i].callref); - pritap->pcalls[i].inuse = 0; - } - } - } - - ftdm_mutex_unlock(pritap->pcalls_lock); -} - -static __inline__ ftdm_channel_t *tap_pri_get_fchan(pritap_t *pritap, passive_call_t *pcall, int channel) -{ - ftdm_channel_t *fchan = NULL; - int err = 0; - int chanpos = PRI_CHANNEL(channel); - if (!chanpos || chanpos > pritap->span->chan_count) { - ftdm_log(FTDM_LOG_CRIT, "Invalid pri tap channel %d requested in span %s\n", channel, pritap->span->name); - return NULL; - } - - fchan = pritap->span->channels[PRI_CHANNEL(channel)]; - - ftdm_channel_lock(fchan); - - if (ftdm_test_flag(fchan, FTDM_CHANNEL_INUSE)) { - ftdm_log(FTDM_LOG_ERROR, "Channel %d requested in span %s is already in use!\n", channel, pritap->span->name); - err = 1; - goto done; - } - - if (ftdm_channel_open_chan(fchan) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Could not open tap channel %d requested in span %s\n", channel, pritap->span->name); - err = 1; - goto done; - } - - memset(&fchan->caller_data, 0, sizeof(fchan->caller_data)); - - ftdm_set_string(fchan->caller_data.cid_num.digits, pcall->callingnum.digits); - if (!ftdm_strlen_zero(pcall->callingname)) { - ftdm_set_string(fchan->caller_data.cid_name, pcall->callingname); - } else { - ftdm_set_string(fchan->caller_data.cid_name, pcall->callingnum.digits); - } - ftdm_set_string(fchan->caller_data.ani.digits, pcall->callingani.digits); - ftdm_set_string(fchan->caller_data.dnis.digits, pcall->callednum.digits); - -done: - if (fchan) { - ftdm_channel_unlock(fchan); - } - - if (err) { - return NULL; - } - - return fchan; -} - -static void handle_pri_passive_event(pritap_t *pritap, pri_event *e) -{ - passive_call_t *pcall = NULL; - passive_call_t *peerpcall = NULL; - ftdm_channel_t *fchan = NULL; - ftdm_channel_t *peerfchan = NULL; - int layer1, transcap = 0; - int crv = 0; - pritap_t *peertap = pritap->peerspan->signal_data; - - switch (e->e) { - - case PRI_EVENT_RING: - /* we cannot use ftdm_channel_t because we still dont know which channel will be used - * (ie, flexible channel was requested), thus, we need our own list of call references */ - crv = tap_pri_get_crv(pritap->pri, e->ring.call); - ftdm_log(FTDM_LOG_DEBUG, "Ring on channel %s:%d:%d with callref %d\n", - pritap->span->name, PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), crv); - pcall = tap_pri_get_pcall_bycrv(pritap, crv); - if (pcall) { - ftdm_log(FTDM_LOG_WARNING, "There is a call with callref %d already, ignoring duplicated ring event\n", crv); - break; - } - - /* Try to get a recycled call (ie, e->ring.call is a call that the PRI stack allocated previously and then - * re-used for the next RING event because we did not destroy it fast enough) */ - pcall = tap_pri_get_pcall(pritap, e->ring.call); - if (!pcall) { - /* ok so the call is really not known to us, let's get a new one */ - pcall = tap_pri_get_pcall(pritap, NULL); - if (!pcall) { - ftdm_log(FTDM_LOG_ERROR, "Failed to get a free passive PRI call slot for callref %d, this is a bug!\n", crv); - break; - } - } - pcall->callref = e->ring.call; - ftdm_set_string(pcall->callingnum.digits, e->ring.callingnum); - ftdm_set_string(pcall->callingani.digits, e->ring.callingani); - ftdm_set_string(pcall->callednum.digits, e->ring.callednum); - ftdm_set_string(pcall->callingname, e->ring.callingname); - break; - - case PRI_EVENT_PROGRESS: - crv = tap_pri_get_crv(pritap->pri, e->proceeding.call); - ftdm_log(FTDM_LOG_DEBUG, "Progress on channel %s:%d:%d with callref %d\n", - pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv); - break; - - case PRI_EVENT_PROCEEDING: - crv = tap_pri_get_crv(pritap->pri, e->proceeding.call); - /* at this point we should know the real b chan that will be used and can therefore proceed to notify about the call, but - * only if a couple of call tests are passed first */ - ftdm_log(FTDM_LOG_DEBUG, "Proceeding on channel %s:%d:%d with callref %d\n", - pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv); - - /* check that we already know about this call in the peer PRI (which was the one receiving the PRI_EVENT_RING event) */ - if (!(pcall = tap_pri_get_pcall_bycrv(peertap, crv))) { - ftdm_log(FTDM_LOG_DEBUG, - "ignoring proceeding in channel %s:%d:%d for callref %d since we don't know about it\n", - pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv); - break; - } - if (pcall->proceeding) { - ftdm_log(FTDM_LOG_DEBUG, "Ignoring duplicated proceeding with callref %d\n", crv); - break; - } - pcall->proceeding = 1; - - /* This call should not be known to this PRI yet ... */ - if ((peerpcall = tap_pri_get_pcall_bycrv(pritap, crv))) { - ftdm_log(FTDM_LOG_ERROR, - "ignoring proceeding in channel %s:%d:%d for callref %d, dup???\n", - pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv); - break; - } - - /* Check if the call pointer is being recycled */ - peerpcall = tap_pri_get_pcall(pritap, e->proceeding.call); - if (!peerpcall) { - peerpcall = tap_pri_get_pcall(pritap, NULL); - if (!peerpcall) { - ftdm_log(FTDM_LOG_ERROR, "Failed to get a free peer PRI passive call slot for callref %d in span %s, this is a bug!\n", - crv, pritap->span->name); - break; - } - peerpcall->callref = e->proceeding.call; - } - - /* check that the layer 1 and trans capability are supported */ - layer1 = pri_get_layer1(peertap->pri, pcall->callref); - transcap = pri_get_transcap(peertap->pri, pcall->callref); - - if (PRI_LAYER_1_ULAW != layer1 && PRI_LAYER_1_ALAW != layer1) { - ftdm_log(FTDM_LOG_NOTICE, "Not monitoring callref %d with unsupported layer 1 format %d\n", crv, layer1); - break; - } - - if (transcap != PRI_TRANS_CAP_SPEECH && transcap != PRI_TRANS_CAP_3_1K_AUDIO && transcap != PRI_TRANS_CAP_7K_AUDIO) { - ftdm_log(FTDM_LOG_NOTICE, "Not monitoring callref %d with unsupported capability %d\n", crv, transcap); - break; - } - - fchan = tap_pri_get_fchan(pritap, pcall, e->proceeding.channel); - if (!fchan) { - ftdm_log(FTDM_LOG_ERROR, "Proceeding requested on odd/unavailable channel %s:%d:%d for callref %d\n", - pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv); - break; - } - - peerfchan = tap_pri_get_fchan(peertap, pcall, e->proceeding.channel); - if (!peerfchan) { - ftdm_log(FTDM_LOG_ERROR, "Proceeding requested on odd/unavailable channel %s:%d:%d for callref %d\n", - peertap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv); - break; - } - pcall->fchan = fchan; - peerpcall->fchan = fchan; - - ftdm_log_chan(fchan, FTDM_LOG_NOTICE, "Starting new tapped call with callref %d\n", crv); - - ftdm_channel_lock(fchan); - fchan->call_data = peerfchan; - ftdm_set_state(fchan, FTDM_CHANNEL_STATE_RING); - ftdm_channel_unlock(fchan); - - ftdm_channel_lock(peerfchan); - peerfchan->call_data = fchan; - ftdm_channel_unlock(peerfchan); - - break; - - case PRI_EVENT_ANSWER: - crv = tap_pri_get_crv(pritap->pri, e->answer.call); - ftdm_log(FTDM_LOG_DEBUG, "Answer on channel %s:%d:%d with callref %d\n", - pritap->span->name, PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), crv); - if (!(pcall = tap_pri_get_pcall_bycrv(pritap, crv))) { - ftdm_log(FTDM_LOG_DEBUG, - "ignoring answer in channel %s:%d:%d for callref %d since we don't know about it\n", - pritap->span->name, PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->proceeding.channel), crv); - break; - } - if (!pcall->fchan) { - ftdm_log(FTDM_LOG_ERROR, - "Received answer in channel %s:%d:%d for callref %d but we never got a channel\n", - pritap->span->name, PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), crv); - break; - } - ftdm_channel_lock(pcall->fchan); - ftdm_log_chan(pcall->fchan, FTDM_LOG_NOTICE, "Tapped call was answered in state %s\n", ftdm_channel_state2str(pcall->fchan->state)); - ftdm_set_pflag(pcall->fchan, PRITAP_NETWORK_ANSWER); - ftdm_set_state(pcall->fchan, FTDM_CHANNEL_STATE_UP); - ftdm_channel_unlock(pcall->fchan); - break; - - case PRI_EVENT_HANGUP_REQ: - crv = tap_pri_get_crv(pritap->pri, e->hangup.call); - - ftdm_log(FTDM_LOG_DEBUG, "Hangup on channel %s:%d:%d with callref %d\n", - pritap->span->name, PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), crv); - - if (!(pcall = tap_pri_get_pcall_bycrv(pritap, crv))) { - ftdm_log(FTDM_LOG_DEBUG, - "ignoring hangup in channel %s:%d:%d for callref %d since we don't know about it", - pritap->span->name, PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), crv); - break; - } - - if (pcall->fchan) { - fchan = pcall->fchan; - ftdm_channel_lock(fchan); - if (fchan->state < FTDM_CHANNEL_STATE_TERMINATING) { - ftdm_set_state(fchan, FTDM_CHANNEL_STATE_TERMINATING); - } - pcall->fchan = NULL; /* after this event we're not supposed to need to do anything with the channel anymore */ - ftdm_channel_unlock(fchan); - } - - tap_pri_put_pcall(pritap, e->hangup.call); - tap_pri_put_pcall(peertap, e->hangup.call); - break; - - case PRI_EVENT_HANGUP_ACK: - crv = tap_pri_get_crv(pritap->pri, e->hangup.call); - ftdm_log(FTDM_LOG_DEBUG, "Hangup ack on channel %s:%d:%d with callref %d\n", - pritap->span->name, PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), crv); - tap_pri_put_pcall(pritap, e->hangup.call); - tap_pri_put_pcall(peertap, e->hangup.call); - break; - - default: - ftdm_log(FTDM_LOG_DEBUG, "Ignoring passive event %s on span %s\n", pri_event2str(e->gen.e), pritap->span->name); - break; - - } -} - -static void *ftdm_pritap_run(ftdm_thread_t *me, void *obj) -{ - ftdm_span_t *span = (ftdm_span_t *) obj; - ftdm_span_t *peer = NULL; - pritap_t *pritap = span->signal_data; - pritap_t *p_pritap = NULL; - pri_event *event = NULL; - struct pollfd dpoll[2]; - int rc = 0; - - ftdm_log(FTDM_LOG_DEBUG, "Tapping PRI thread started on span %s\n", span->name); - - pritap->span = span; - - ftdm_set_flag(span, FTDM_SPAN_IN_THREAD); - - if (ftdm_channel_open(span->span_id, pritap->dchan->chan_id, &pritap->dchan) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Failed to open D-channel for span %s\n", span->name); - goto done; - } - - if ((pritap->pri = pri_new_cb(pritap->dchan->sockfd, PRI_NETWORK, PRI_SWITCH_NI2, pri_io_read, pri_io_write, pritap))){ - pri_set_debug(pritap->pri, pritap->debug); - } else { - ftdm_log(FTDM_LOG_CRIT, "Failed to create tapping PRI\n"); - goto done; - } - - /* The last span starting runs the show ... - * This simplifies locking and avoid races by having multiple threads for a single tapped link - * Since both threads really handle a single tapped link there is no benefit on multi-threading, just complications ... */ - peer = pritap->peerspan; - p_pritap = peer->signal_data; - if (!ftdm_test_flag(pritap, PRITAP_MASTER)) { - ftdm_log(FTDM_LOG_DEBUG, "Running dummy thread on span %s\n", span->name); - while (ftdm_running() && !ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD)) { - poll(NULL, 0, 100); - } - } else { - memset(&dpoll, 0, sizeof(dpoll)); - dpoll[0].fd = pritap->dchan->sockfd; - dpoll[1].fd = p_pritap->dchan->sockfd; - - ftdm_log(FTDM_LOG_DEBUG, "Master tapping thread on span %s (fd1=%d, fd2=%d)\n", span->name, - pritap->dchan->sockfd, p_pritap->dchan->sockfd); - - while (ftdm_running() && !ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD)) { - - pritap_check_state(span); - pritap_check_state(peer); - - dpoll[0].revents = 0; - dpoll[0].events = POLLIN; - - dpoll[1].revents = 0; - dpoll[1].events = POLLIN; - - rc = poll(&dpoll[0], 2, 10); - - if (rc < 0) { - if (errno == EINTR) { - ftdm_log(FTDM_LOG_DEBUG, "D-channel waiting interrupted, continuing ...\n"); - continue; - } - ftdm_log(FTDM_LOG_ERROR, "poll failed: %s\n", strerror(errno)); - continue; - } - - pri_schedule_run(pritap->pri); - pri_schedule_run(p_pritap->pri); - - pritap_check_state(span); - pritap_check_state(peer); - - if (rc) { - if (dpoll[0].revents & POLLIN) { - event = pri_read_event(pritap->pri); - if (event) { - handle_pri_passive_event(pritap, event); - pritap_check_state(span); - } - } - - if (dpoll[1].revents & POLLIN) { - event = pri_read_event(p_pritap->pri); - if (event) { - handle_pri_passive_event(p_pritap, event); - pritap_check_state(peer); - } - } - } - - } - } - - -done: - ftdm_log(FTDM_LOG_DEBUG, "Tapping PRI thread ended on span %s\n", span->name); - - ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD); - ftdm_clear_flag(pritap, PRITAP_RUNNING); - ftdm_clear_flag(pritap, PRITAP_MASTER); - - return NULL; -} - -static ftdm_status_t ftdm_pritap_stop(ftdm_span_t *span) -{ - pritap_t *pritap = span->signal_data; - - if (!ftdm_test_flag(pritap, PRITAP_RUNNING)) { - return FTDM_FAIL; - } - - ftdm_set_flag(span, FTDM_SPAN_STOP_THREAD); - - while (ftdm_test_flag(span, FTDM_SPAN_IN_THREAD)) { - ftdm_sleep(100); - } - - ftdm_mutex_destroy(&pritap->pcalls_lock); - return FTDM_SUCCESS; -} - -static ftdm_status_t ftdm_pritap_sig_read(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t size) -{ - ftdm_status_t status; - fio_codec_t codec_func; - ftdm_channel_t *peerchan = ftdmchan->call_data; - pritap_t *pritap = ftdmchan->span->signal_data; - int16_t chanbuf[size]; - int16_t peerbuf[size]; - int16_t mixedbuf[size]; - int i = 0; - ftdm_size_t sizeread = size; - - if (!FTDM_IS_VOICE_CHANNEL(ftdmchan) || !ftdmchan->call_data) { - return FTDM_SUCCESS; - } - - if (pritap->mixaudio == PRITAP_MIX_SELF) { - return FTDM_SUCCESS; - } - - if (pritap->mixaudio == PRITAP_MIX_PEER) { - /* start out by clearing the self audio to make sure we don't return audio we were - * not supposed to in an error condition */ - memset(data, FTDM_SILENCE_VALUE(ftdmchan), size); - } - - if (ftdmchan->native_codec != peerchan->native_codec) { - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Invalid peer channel with format %d, ours = %d\n", - peerchan->native_codec, ftdmchan->native_codec); - return FTDM_FAIL; - } - - memcpy(chanbuf, data, size); - status = peerchan->fio->read(peerchan, peerbuf, &sizeread); - if (status != FTDM_SUCCESS) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to read from peer channel!\n"); - return FTDM_FAIL; - } - if (sizeread != size) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "read from peer channel only %"FTDM_SIZE_FMT" bytes!\n", sizeread); - return FTDM_FAIL; - } - - if (pritap->mixaudio == PRITAP_MIX_PEER) { - /* only the peer audio is requested */ - memcpy(data, peerbuf, size); - return FTDM_SUCCESS; - } - - codec_func = peerchan->native_codec == FTDM_CODEC_ULAW ? fio_ulaw2slin : peerchan->native_codec == FTDM_CODEC_ALAW ? fio_alaw2slin : NULL; - if (codec_func) { - sizeread = size; - codec_func(chanbuf, sizeof(chanbuf), &sizeread); - sizeread = size; - codec_func(peerbuf, sizeof(peerbuf), &sizeread); - } - - for (i = 0; i < size; i++) { - mixedbuf[i] = ftdm_saturated_add(chanbuf[i], peerbuf[i]); - } - - codec_func = peerchan->native_codec == FTDM_CODEC_ULAW ? fio_slin2ulaw : peerchan->native_codec == FTDM_CODEC_ALAW ? fio_slin2alaw : NULL; - if (codec_func) { - size = sizeof(mixedbuf); - codec_func(mixedbuf, size, &size); - } - memcpy(data, mixedbuf, size); - return FTDM_SUCCESS; -} - -static ftdm_status_t ftdm_pritap_start(ftdm_span_t *span) -{ - ftdm_status_t ret; - pritap_t *pritap = span->signal_data; - pritap_t *p_pritap = pritap->peerspan->signal_data; - - if (ftdm_test_flag(pritap, PRITAP_RUNNING)) { - return FTDM_FAIL; - } - - ftdm_mutex_create(&pritap->pcalls_lock); - - ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD); - ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD); - - ftdm_set_flag(pritap, PRITAP_RUNNING); - if (p_pritap && ftdm_test_flag(p_pritap, PRITAP_RUNNING)) { - /* our peer already started, we're the master */ - ftdm_set_flag(pritap, PRITAP_MASTER); - } - ret = ftdm_thread_create_detached(ftdm_pritap_run, span); - - if (ret != FTDM_SUCCESS) { - return ret; - } - - return ret; -} - -static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_pritap_configure_span) -{ - uint32_t i; - const char *var, *val; - const char *debug = NULL; - pritap_mix_mode_t mixaudio = PRITAP_MIX_BOTH; - ftdm_channel_t *dchan = NULL; - pritap_t *pritap = NULL; - ftdm_span_t *peerspan = NULL; - pritap_iface_t iface = PRITAP_IFACE_UNKNOWN; - unsigned paramindex = 0; - - if (span->trunk_type >= FTDM_TRUNK_NONE) { - ftdm_log(FTDM_LOG_WARNING, "Invalid trunk type '%s' defaulting to T1.\n", ftdm_trunk_type2str(span->trunk_type)); - span->trunk_type = FTDM_TRUNK_T1; - } - - for (i = 1; i <= span->chan_count; i++) { - if (span->channels[i]->type == FTDM_CHAN_TYPE_DQ921) { - dchan = span->channels[i]; - } - } - - if (!dchan) { - ftdm_log(FTDM_LOG_ERROR, "No d-channel specified in freetdm.conf!\n"); - return FTDM_FAIL; - } - - for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) { - var = ftdm_parameters[paramindex].var; - val = ftdm_parameters[paramindex].val; - ftdm_log(FTDM_LOG_DEBUG, "Tapping PRI key=value, %s=%s\n", var, val); - - if (!strcasecmp(var, "debug")) { - debug = val; - } else if (!strcasecmp(var, "mixaudio")) { - if (ftdm_true(val) || !strcasecmp(val, "both")) { - ftdm_log(FTDM_LOG_DEBUG, "Setting mix audio mode to 'both' for span %s\n", span->name); - mixaudio = PRITAP_MIX_BOTH; - } else if (!strcasecmp(val, "peer")) { - ftdm_log(FTDM_LOG_DEBUG, "Setting mix audio mode to 'peer' for span %s\n", span->name); - mixaudio = PRITAP_MIX_PEER; - } else { - ftdm_log(FTDM_LOG_DEBUG, "Setting mix audio mode to 'self' for span %s\n", span->name); - mixaudio = PRITAP_MIX_SELF; - } - } else if (!strcasecmp(var, "interface")) { - if (!strcasecmp(val, "cpe")) { - iface = PRITAP_IFACE_CPE; - } else if (!strcasecmp(val, "net")) { - iface = PRITAP_IFACE_NET; - } else { - ftdm_log(FTDM_LOG_WARNING, "Ignoring invalid tapping interface type %s\n", val); - } - } else if (!strcasecmp(var, "peerspan")) { - if (ftdm_span_find_by_name(val, &peerspan) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Invalid tapping peer span %s\n", val); - break; - } - } else { - ftdm_log(FTDM_LOG_ERROR, "Unknown pri tapping parameter [%s]", var); - } - } - - if (!peerspan) { - ftdm_log(FTDM_LOG_ERROR, "No valid peerspan was specified!\n"); - return FTDM_FAIL; - } - - pritap = ftdm_calloc(1, sizeof(*pritap)); - if (!pritap) { - return FTDM_FAIL; - } - - pritap->debug = parse_debug(debug); - pritap->dchan = dchan; - pritap->peerspan = peerspan; - pritap->mixaudio = mixaudio; - pritap->iface = iface; - - span->start = ftdm_pritap_start; - span->stop = ftdm_pritap_stop; - span->sig_read = ftdm_pritap_sig_read; - span->signal_cb = sig_cb; - - span->signal_data = pritap; - span->signal_type = FTDM_SIGTYPE_ISDN; - span->outgoing_call = pritap_outgoing_call; - - span->get_channel_sig_status = pritap_get_channel_sig_status; - span->get_span_sig_status = pritap_get_span_sig_status; - - span->state_map = &pritap_state_map; - span->state_processor = state_advance; - - return FTDM_SUCCESS; -} - -/** - * \brief FreeTDM pritap signaling and IO module definition - */ -ftdm_module_t ftdm_module = { - "pritap", - ftdm_pritap_io_init, - ftdm_pritap_unload, - ftdm_pritap_init, - NULL, - NULL, - ftdm_pritap_configure_span, -}; - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2008.vcproj deleted file mode 100644 index 565a31e505..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2008.vcproj +++ /dev/null @@ -1,196 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj.filters deleted file mode 100644 index 9c91228e09..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj.filters +++ /dev/null @@ -1,22 +0,0 @@ - - - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Source Files - - - \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c deleted file mode 100755 index 8b36cdb8f3..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ /dev/null @@ -1,2437 +0,0 @@ -/* - * Copyright (c) 2009, Moises Silva - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Contributors: - * - * Arnaldo Pereira - * Ricardo Barroetaveña - * - */ - -#ifdef __linux__ -#ifndef _DEFAULT_SOURCE -#define _DEFAULT_SOURCE -#endif -#ifndef _BSD_SOURCE -#define _BSD_SOURCE /* for strsep() */ -#endif -#include -#include -#include -#endif -#include -#include -#include -#include - -#include "ftmod_r2_io_mf_lib.h" // ftdm_r2_get_native_channel_mf_generation_iface - -/* when the user stops a span, we clear FTDM_R2_SPAN_STARTED, so that the signaling thread - * knows it must stop, and we wait for FTDM_R2_RUNNING to be clear, which tells us the - * signaling thread is done. */ -/* FIXME: what about the calls that are already up-and-running? */ -typedef enum { - FTDM_R2_RUNNING = (1 << 0), - FTDM_R2_SPAN_STARTED = (1 << 1), -} ftdm_r2_flag_t; - -/* private call information stored in ftdmchan->call_data void* ptr, - * remember that each time you add a new member to this structure - * most likely you want to clear it in ft_r2_clean_call function - * */ -#define R2CALL(ftdmchan) ((ftdm_r2_call_t*)((ftdmchan)->call_data)) -typedef struct ftdm_r2_call_t { - openr2_chan_t *r2chan; - int accepted:1; - int answer_pending:1; - int disconnect_rcvd:1; - int protocol_error:1; - int localsuspend_on_alarm:1; - ftdm_size_t dnis_index; - ftdm_size_t ani_index; - char logname[255]; - char name[10]; - ftdm_timer_id_t protocol_error_recovery_timer; -} ftdm_r2_call_t; - -/* this is just used as place holder in the stack when configuring the span to avoid using bunch of locals */ -typedef struct ft_r2_conf_s { - /* openr2 types */ - openr2_variant_t variant; - openr2_calling_party_category_t category; - openr2_log_level_t loglevel; - - /* strings */ - char *logdir; - char *advanced_protocol_file; - - /* ints */ - int32_t max_ani; - int32_t max_dnis; - int32_t mfback_timeout; - int32_t metering_pulse_timeout; - ftdm_size_t mf_dump_size; - - /* booleans */ - int immediate_accept; - int skip_category; - int get_ani_first; - int call_files; - int double_answer; - int charge_calls; - int forced_release; - int allow_collect_calls; - int use_channel_native_mf_generation; -} ft_r2_conf_t; - -/* r2 configuration stored in span->signal_data */ -typedef struct ftdm_r2_data_s { - /* span flags */ - ftdm_r2_flag_t flags; - /* openr2 handle for the R2 variant context */ - openr2_context_t *r2context; - /* category to use when making calls */ - openr2_calling_party_category_t category; - /* whether to use OR2_CALL_WITH_CHARGE or OR2_CALL_NO_CHARGE when accepting a call */ - int charge_calls:1; - /* allow or reject collect calls */ - int allow_collect_calls:1; - /* whether to use forced release when hanging up */ - int forced_release:1; - /* whether accept the call when offered, or wait until the user decides to accept */ - int accept_on_offer:1; - /* Size of multi-frequency (or any media) dumps used during protocol errors */ - ftdm_size_t mf_dump_size; - /* max time spent in ms doing real work in a single loop */ - int32_t jobmax; - /* Total number of loops performed so far */ - uint64_t total_loops; - /* number of loops per 10ms increment from 0-9ms, 10-19ms .. 100ms and above */ - uint64_t loops[11]; - /* Total number of sleeps performed so far */ - uint64_t total_sleeps; - /* number of sleeps per 10ms increment from 0-9ms, 10-19ms .. 100ms and above */ - uint64_t sleeps[11]; - /* max time spent in ms sleeping in a single loop */ - int32_t sleepmax; - /* LWP */ - uint32_t monitor_thread_id; - /* Logging directory */ - char logdir[512]; - /* scheduling context */ - ftdm_sched_t *sched; -} ftdm_r2_data_t; - -/* one element per span will be stored in g_mod_data_hash global var to keep track of them - and destroy them on module unload */ -typedef struct ftdm_r2_span_pvt_s { - openr2_context_t *r2context; /* r2 context allocated for this span */ - ftdm_hash_t *r2calls; /* hash table of allocated call data per channel for this span */ - ftdm_sched_t *sched; /* schedule for the span */ -} ftdm_r2_span_pvt_t; - -/* span monitor thread */ -static void *ftdm_r2_run(ftdm_thread_t *me, void *obj); - -/* hash of all the private span allocations - we need to keep track of them to destroy them when unloading the module - since freetdm does not notify signaling modules when destroying a span - span -> ftdm_r2_mod_allocs_t */ -static ftdm_hash_t *g_mod_data_hash; - -/* IO interface for the command API */ -static ftdm_io_interface_t g_ftdm_r2_interface; - -static ftdm_status_t ftdm_r2_state_advance(ftdm_channel_t *ftdmchan); - -/* whether R2 call accept process is pending */ -#define IS_ACCEPTING_PENDING(ftdmchan) \ - ( (!ftdm_test_flag((ftdmchan), FTDM_CHANNEL_OUTBOUND)) && !R2CALL((ftdmchan))->accepted && \ - ((ftdmchan)->state == FTDM_CHANNEL_STATE_PROGRESS || \ - (ftdmchan)->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA || \ - (ftdmchan)->state == FTDM_CHANNEL_STATE_UP) ) - -/* functions not available on windows */ -#ifdef WIN32 -#include - -static __inline int gettimeofday(struct timeval *tp, void *nothing) -{ -#ifdef WITHOUT_MM_LIB - SYSTEMTIME st; - time_t tt; - struct tm tmtm; - /* mktime converts local to UTC */ - GetLocalTime (&st); - tmtm.tm_sec = st.wSecond; - tmtm.tm_min = st.wMinute; - tmtm.tm_hour = st.wHour; - tmtm.tm_mday = st.wDay; - tmtm.tm_mon = st.wMonth - 1; - tmtm.tm_year = st.wYear - 1900; tmtm.tm_isdst = -1; - tt = mktime (&tmtm); - tp->tv_sec = tt; - tp->tv_usec = st.wMilliseconds * 1000; -#else - /** - ** The earlier time calculations using GetLocalTime - ** had a time resolution of 10ms.The timeGetTime, part - ** of multimedia apis offer a better time resolution - ** of 1ms.Need to link against winmm.lib for this - **/ - unsigned long Ticks = 0; - unsigned long Sec =0; - unsigned long Usec = 0; - Ticks = timeGetTime(); - - Sec = Ticks/1000; - Usec = (Ticks - (Sec*1000))*1000; - tp->tv_sec = Sec; - tp->tv_usec = Usec; -#endif /* WITHOUT_MM_LIB */ - (void)nothing; - return 0; -} - -static char *strsep(char **stringp, const char *delim) -{ - char *start = *stringp; - char *ptr; - - if (!start) - return NULL; - - if (!*delim) - ptr = start + strlen(start); - else { - ptr = strpbrk(start, delim); - if (!ptr) { - *stringp = NULL; - return start; - } - } - - *ptr = '\0'; - *stringp = ptr + 1; - - return start; -} -#endif /* WIN32 */ - -static void ftdm_r2_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status) -{ - ftdm_sigmsg_t sig; - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Signalling link status changed to %s\n", ftdm_signaling_status2str(status)); - - memset(&sig, 0, sizeof(sig)); - sig.chan_id = ftdmchan->chan_id; - sig.span_id = ftdmchan->span_id; - sig.channel = ftdmchan; - sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sig.ev_data.sigstatus.status = status; - if (ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to change channel status to %s\n", ftdm_signaling_status2str(status)); - } - return; -} - -static ftdm_call_cause_t ftdm_r2_cause_to_ftdm_cause(ftdm_channel_t *fchan, openr2_call_disconnect_cause_t cause) -{ - switch (cause) { - - case OR2_CAUSE_NORMAL_CLEARING: - return FTDM_CAUSE_NORMAL_CLEARING; - - case OR2_CAUSE_BUSY_NUMBER: - return FTDM_CAUSE_USER_BUSY; - - case OR2_CAUSE_NETWORK_CONGESTION: - return FTDM_CAUSE_SWITCH_CONGESTION; - - case OR2_CAUSE_UNALLOCATED_NUMBER: - return FTDM_CAUSE_NO_ROUTE_DESTINATION; - - case OR2_CAUSE_NUMBER_CHANGED: - return FTDM_CAUSE_NUMBER_CHANGED; - - case OR2_CAUSE_OUT_OF_ORDER: - return FTDM_CAUSE_NETWORK_OUT_OF_ORDER; - - case OR2_CAUSE_NO_ANSWER: - return FTDM_CAUSE_NO_ANSWER; - - case OR2_CAUSE_UNSPECIFIED: - return FTDM_CAUSE_NORMAL_UNSPECIFIED; - - case OR2_CAUSE_FORCED_RELEASE: - return FTDM_CAUSE_NORMAL_CLEARING; - - case OR2_CAUSE_GLARE: - return FTDM_CAUSE_REQUESTED_CHAN_UNAVAIL; - } - ftdm_log_chan(fchan, FTDM_LOG_NOTICE, "Mapping openr2 cause %d to unspecified\n", cause); - return FTDM_CAUSE_NORMAL_UNSPECIFIED; -} - -static openr2_call_disconnect_cause_t ftdm_r2_ftdm_cause_to_openr2_cause(ftdm_channel_t *fchan) -{ - switch (fchan->caller_data.hangup_cause) { - - case FTDM_CAUSE_NORMAL_CLEARING: - return OR2_CAUSE_NORMAL_CLEARING; - - case FTDM_CAUSE_USER_BUSY: - case FTDM_CAUSE_CALL_REJECTED: - return OR2_CAUSE_BUSY_NUMBER; - - case FTDM_CAUSE_SWITCH_CONGESTION: - return OR2_CAUSE_NETWORK_CONGESTION; - - case FTDM_CAUSE_NO_ROUTE_DESTINATION: - return OR2_CAUSE_UNALLOCATED_NUMBER; - - case FTDM_CAUSE_NUMBER_CHANGED: - return OR2_CAUSE_NUMBER_CHANGED; - - case FTDM_CAUSE_NETWORK_OUT_OF_ORDER: - case FTDM_CAUSE_SERVICE_UNAVAILABLE: - case FTDM_CAUSE_PROTOCOL_ERROR: - return OR2_CAUSE_OUT_OF_ORDER; - - case FTDM_CAUSE_NO_ANSWER: - case FTDM_CAUSE_NO_USER_RESPONSE: - return OR2_CAUSE_NO_ANSWER; - - case FTDM_CAUSE_NORMAL_UNSPECIFIED: - return OR2_CAUSE_UNSPECIFIED; - - case FTDM_CAUSE_REQUESTED_CHAN_UNAVAIL: - return OR2_CAUSE_GLARE; - - } - ftdm_log_chan(fchan, FTDM_LOG_NOTICE, "freetdm hangup cause %d mapped to openr2 cause %s\n", - fchan->caller_data.hangup_cause, openr2_proto_get_disconnect_string(OR2_CAUSE_UNSPECIFIED)); - return OR2_CAUSE_UNSPECIFIED; -} - -static void ft_r2_clean_call(ftdm_r2_call_t *call) -{ - openr2_chan_t *r2chan = call->r2chan; - - /* Do not memset call structure, that clears values we do not want to clear, - * like the log name set in on_call_log_created() */ - call->r2chan = r2chan; - call->accepted = 0; - call->answer_pending = 0; - call->disconnect_rcvd = 0; - call->protocol_error = 0; - call->dnis_index = 0; - call->ani_index = 0; - call->name[0] = 0; - call->protocol_error_recovery_timer = 0; -} - -static void ft_r2_accept_call(ftdm_channel_t *ftdmchan) -{ - openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan; - ftdm_r2_data_t *r2data = ftdmchan->span->signal_data; - - // FIXME: we should check the return code from openr2_chan_accept_call and handle error condition - // hanging up the call with protocol error as the reason, this openr2 API will fail only when there something - // wrong at the I/O layer or the library itself - if (r2data->charge_calls) - openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE); - else - openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE); -} - -static void ft_r2_answer_call(ftdm_channel_t *ftdmchan) -{ - openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan; - // FIXME - // 1. check openr2_chan_answer_call return code - // 2. The openr2_chan_answer_call_with_mode should be used depending on user settings - // openr2_chan_answer_call_with_mode(r2chan, OR2_ANSWER_SIMPLE); - openr2_chan_answer_call(r2chan); - R2CALL(ftdmchan)->answer_pending = 0; -} - -static __inline__ ftdm_calling_party_category_t ftdm_openr2_cpc_to_r2_ftdm_cpc(openr2_calling_party_category_t cpc) -{ - switch (cpc) { - case OR2_CALLING_PARTY_CATEGORY_UNKNOWN: - return FTDM_CPC_UNKNOWN; - - case OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER: - return FTDM_CPC_ORDINARY; - - case OR2_CALLING_PARTY_CATEGORY_NATIONAL_PRIORITY_SUBSCRIBER: - return FTDM_CPC_PRIORITY; - - case OR2_CALLING_PARTY_CATEGORY_INTERNATIONAL_SUBSCRIBER: - return FTDM_CPC_UNKNOWN; - - case OR2_CALLING_PARTY_CATEGORY_INTERNATIONAL_PRIORITY_SUBSCRIBER: - return FTDM_CPC_UNKNOWN; - - case OR2_CALLING_PARTY_CATEGORY_TEST_EQUIPMENT: - return FTDM_CPC_TEST; - - case OR2_CALLING_PARTY_CATEGORY_PAY_PHONE: - return FTDM_CPC_PAYPHONE; - - case OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL: - return FTDM_CPC_OPERATOR; - } - return FTDM_CPC_INVALID; -} - -static __inline openr2_calling_party_category_t ftdm_r2_ftdm_cpc_to_openr2_cpc(ftdm_calling_party_category_t cpc) -{ - switch (cpc) { - case FTDM_CPC_UNKNOWN: - return OR2_CALLING_PARTY_CATEGORY_UNKNOWN; - - case FTDM_CPC_OPERATOR: - return OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL; - - case FTDM_CPC_ORDINARY: - return OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER; - - case FTDM_CPC_PRIORITY: - return OR2_CALLING_PARTY_CATEGORY_NATIONAL_PRIORITY_SUBSCRIBER; - - case FTDM_CPC_DATA: - return OR2_CALLING_PARTY_CATEGORY_UNKNOWN; - - case FTDM_CPC_TEST: - return OR2_CALLING_PARTY_CATEGORY_TEST_EQUIPMENT; - - case FTDM_CPC_PAYPHONE: - return OR2_CALLING_PARTY_CATEGORY_PAY_PHONE; - - case FTDM_CPC_OPERATOR_FRENCH: - case FTDM_CPC_OPERATOR_ENGLISH: - case FTDM_CPC_OPERATOR_GERMAN: - case FTDM_CPC_OPERATOR_RUSSIAN: - case FTDM_CPC_OPERATOR_SPANISH: - return OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL; - - case FTDM_CPC_INVALID: - return OR2_CALLING_PARTY_CATEGORY_UNKNOWN; - } - return OR2_CALLING_PARTY_CATEGORY_UNKNOWN; -} - -/* this function must be called with the chan mutex held! */ -static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call) -{ - int ret; - ftdm_r2_data_t *r2data; - openr2_calling_party_category_t category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER; - - r2data = ftdmchan->span->signal_data; - - ft_r2_clean_call(ftdmchan->call_data); - - if (ftdmchan->caller_data.cpc == FTDM_CPC_INVALID || ftdmchan->caller_data.cpc == FTDM_CPC_UNKNOWN) { - category = r2data->category; - } else { - category = ftdm_r2_ftdm_cpc_to_openr2_cpc(ftdmchan->caller_data.cpc); - } - - /* start io dump */ - if (r2data->mf_dump_size) { - ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_INPUT_DUMP, &r2data->mf_dump_size); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_OUTPUT_DUMP, &r2data->mf_dump_size); - } - - ret = openr2_chan_make_call(R2CALL(ftdmchan)->r2chan, - ftdmchan->caller_data.cid_num.digits, - ftdmchan->caller_data.dnis.digits, - category, - ftdmchan->caller_data.pres == FTDM_PRES_ALLOWED ? 0 : 1); - - if (ret) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to make call in R2 channel, openr2_chan_make_call failed\n"); - return FTDM_FAIL; - } - - ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLUSH_TX_BUFFERS, NULL); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLUSH_RX_BUFFERS, NULL); - return FTDM_SUCCESS; -} - -static ftdm_status_t ftdm_r2_start(ftdm_span_t *span) -{ - ftdm_r2_data_t *r2_data = span->signal_data; - ftdm_set_flag(r2_data, FTDM_R2_SPAN_STARTED); - return ftdm_thread_create_detached(ftdm_r2_run, span); -} - -static ftdm_status_t ftdm_r2_stop(ftdm_span_t *span) -{ - ftdm_r2_data_t *r2_data = span->signal_data; - ftdm_clear_flag(r2_data, FTDM_R2_SPAN_STARTED); - while (ftdm_test_flag(r2_data, FTDM_R2_RUNNING)) { - ftdm_log(FTDM_LOG_DEBUG, "Waiting for R2 span %s\n", span->name); - ftdm_sleep(100); - } - return FTDM_SUCCESS; -} - -static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_channel_sig_status) -{ - openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan; - openr2_cas_signal_t rxcas, txcas; - - /* get the current rx and tx cas bits */ - openr2_chan_get_cas(r2chan, &rxcas, &txcas); - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) { - *status = FTDM_SIG_STATE_UP; - } else if (rxcas == OR2_CAS_BLOCK || txcas == OR2_CAS_BLOCK) { - *status = FTDM_SIG_STATE_SUSPENDED; - } else { - *status = FTDM_SIG_STATE_DOWN; - } - - return FTDM_SUCCESS; -} - -static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_channel_sig_status) -{ - openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan; - openr2_cas_signal_t rxcas, txcas; - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, - "Received request to change sig status of alarmed channel to %s", ftdm_signaling_status2str(status)); - - switch (status) { - case FTDM_SIG_STATE_SUSPENDED: - openr2_chan_set_blocked(r2chan); - /* Need to send sig status change to SUSPENDED once out of alarm */ - R2CALL(ftdmchan)->localsuspend_on_alarm = 1; - break; - case FTDM_SIG_STATE_UP: - openr2_chan_set_blocked(r2chan); - /* DO NOT send sig status change to SUSPENDED once out of alarm */ - R2CALL(ftdmchan)->localsuspend_on_alarm = 0; - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%d'\n", status); - return FTDM_FAIL; - } - return FTDM_SUCCESS; - } - - /* get the current rx and tx cas bits */ - openr2_chan_get_cas(r2chan, &rxcas, &txcas); - - /* if we're already in the state the user asks us to be, we have nothing to do */ - if (status == FTDM_SIG_STATE_SUSPENDED && txcas == OR2_CAS_BLOCK) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Channel signaling status already in BLOCK state\n"); - return FTDM_SUCCESS; - } - if (status == FTDM_SIG_STATE_UP && txcas == OR2_CAS_IDLE) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Channel signaling status already in IDLE state\n"); - return FTDM_SUCCESS; - } - - /* set the signaling as requested and send SIGEVENT_SIGSTATUS_CHANGED, if applicable. - * see docs/sigstatus.txt for details */ - switch(status) { - case FTDM_SIG_STATE_SUSPENDED: - openr2_chan_set_blocked(r2chan); - if (rxcas == OR2_CAS_IDLE) { - ftdm_r2_set_chan_sig_status(ftdmchan, status); - } - break; - case FTDM_SIG_STATE_UP: - openr2_chan_set_idle(r2chan); - if (rxcas == OR2_CAS_IDLE) { - ftdm_r2_set_chan_sig_status(ftdmchan, status); - } - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%d'\n", status); - return FTDM_FAIL; - } - return FTDM_SUCCESS; -} - -static FIO_SPAN_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_span_sig_status) -{ - ftdm_iterator_t *citer = NULL; - ftdm_iterator_t *chaniter = ftdm_span_get_chan_iterator(span, NULL); - if (!chaniter) { - ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name); - return FTDM_FAIL; - } - /* if ALL channels are non-idle, report SUSPENDED. UP otherwise. */ - *status = FTDM_SIG_STATE_SUSPENDED; - for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) { - ftdm_channel_t *fchan = ftdm_iterator_current(citer); - ftdm_channel_lock(fchan); - if (ftdm_test_flag(fchan, FTDM_CHANNEL_IN_ALARM)) { - *status = FTDM_SIG_STATE_DOWN; - ftdm_channel_unlock(fchan); - break; - } - if (ftdm_test_flag(fchan, FTDM_CHANNEL_SIG_UP)) { - *status = FTDM_SIG_STATE_UP; - ftdm_channel_unlock(fchan); - break; - } - ftdm_channel_unlock(fchan); - } - ftdm_iterator_free(chaniter); - return FTDM_SUCCESS; -} - -static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_span_sig_status) -{ - ftdm_iterator_t *chaniter = NULL; - ftdm_iterator_t *citer = NULL; - - chaniter = ftdm_span_get_chan_iterator(span, NULL); - if (!chaniter) { - ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name); - return FTDM_FAIL; - } - /* iterate over all channels, setting them to the requested state */ - for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) { - ftdm_channel_t *fchan = ftdm_iterator_current(citer); - /* we set channel's state through ftdm_r2_set_channel_sig_status(), since it already takes - * care of notifying the user when appropriate */ - ftdm_channel_lock(fchan); - if ((ftdm_r2_set_channel_sig_status(fchan, status)) != FTDM_SUCCESS) { - ftdm_log_chan(fchan, FTDM_LOG_ERROR, "Failed to set signaling status to %s\n", ftdm_signaling_status2str(status)); - } - ftdm_channel_unlock(fchan); - } - ftdm_iterator_free(chaniter); - return FTDM_SUCCESS; -} - -/* always called from the monitor thread */ -static void ftdm_r2_on_call_init(openr2_chan_t *r2chan) -{ - ftdm_r2_call_t *r2call; - ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_r2_data_t *r2data = ftdmchan->span->signal_data; - - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Received request to start call\n"); - - if (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP) { - r2call = R2CALL(ftdmchan); - if (r2call->protocol_error) { - /* we had a protocol error and we were giving some recovery time, cancel the recovery timer now - * that is obvious that the other side recovered */ - ftdm_sched_cancel_timer(r2data->sched, r2call->protocol_error_recovery_timer); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Cancelled protocol error recovery timer\n"); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - ftdm_channel_advance_states(ftdmchan); - } - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Cannot start call when channel is in use (state = %s)\n", ftdm_channel_state2str(ftdmchan->state)); - return; - } - - if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot handle request to start call in state %s\n", ftdm_channel_state2str(ftdmchan->state)); - return; - } - - if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to open channel during incoming call! [%s]\n", ftdmchan->last_error); - return; - } - - memset(ftdmchan->caller_data.dnis.digits, 0, sizeof(ftdmchan->caller_data.collected)); - memset(ftdmchan->caller_data.ani.digits, 0, sizeof(ftdmchan->caller_data.collected)); - - ft_r2_clean_call(ftdmchan->call_data); - r2call = R2CALL(ftdmchan); - - /* start io dump */ - if (r2data->mf_dump_size) { - ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_INPUT_DUMP, &r2data->mf_dump_size); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_OUTPUT_DUMP, &r2data->mf_dump_size); - } - - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); - ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLUSH_TX_BUFFERS, NULL); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLUSH_RX_BUFFERS, NULL); -} - -static void dump_mf(openr2_chan_t *r2chan); -/* only called for incoming calls when the ANI, DNIS etc is complete and the user has to decide either to accept or reject the call */ -static void ftdm_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, - openr2_calling_party_category_t category, int ani_restricted) -{ - ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_r2_data_t *r2data = ftdmchan->span->signal_data; - - ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Call offered with ANI = %s, DNIS = %s, Category = %s, ANI restricted = %s\n", - ani, dnis, openr2_proto_get_category_string(category), ani_restricted ? "Yes" : "No"); - - /* check if this is a collect call and if we should accept it */ - if (!r2data->allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Rejecting collect call\n"); - openr2_chan_disconnect_call(r2chan, OR2_CAUSE_UNALLOCATED_NUMBER); - } else { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); - } - ftdmchan->caller_data.cpc = ftdm_openr2_cpc_to_r2_ftdm_cpc(category); - ftdmchan->caller_data.pres = ani_restricted ? FTDM_PRES_RESTRICTED : FTDM_PRES_ALLOWED; -} - -/* - * Accepting a call in R2 is a lengthy process due to MF tones, - * when the user sends PROGRESS indication (implicitly moving the - * ftdm channel to PROGRESS state) the R2 processing loop - * does not clear FTDM_CHANNEL_STATE_CHANGE immediately as it does - * for all the other states, instead has to wait for on_call_accepted - * callback from openr2, which means the MF has ended and the progress - * indication is done, in order to clear the flag. However, if - * a protocol error or call disconnection (which is indicated using CAS bits) - * occurrs while accepting, we must clear the pending flag, this function - * takes care of that - * */ -static void clear_accept_pending(ftdm_channel_t *fchan) -{ - if (IS_ACCEPTING_PENDING(fchan)) { - ftdm_channel_complete_state(fchan); - } else if (ftdm_test_flag(fchan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_log_chan(fchan, FTDM_LOG_CRIT, "State change flag set in state %s, last state = %s\n", - ftdm_channel_state2str(fchan->state), ftdm_channel_state2str(fchan->last_state)); - ftdm_channel_complete_state(fchan); - } -} - -static void dump_mf(openr2_chan_t *r2chan) -{ - char dfile[512]; - FILE *f = NULL; - int rc = 0; - ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_r2_data_t *r2data = ftdmchan->span->signal_data; - if (r2data->mf_dump_size) { - char *logname = R2CALL(ftdmchan)->logname; - - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO output in prefix %s\n", !ftdm_strlen_zero(logname) - ? logname : r2data->logdir); - snprintf(dfile, sizeof(dfile), !ftdm_strlen_zero(logname) ? "%s.s%dc%d.input.alaw" : "%s/s%dc%d.input.alaw", - !ftdm_strlen_zero(logname) ? logname : r2data->logdir, ftdmchan->span_id, ftdmchan->chan_id); - f = fopen(dfile, "wb"); - if (f) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO input in file %s\n", dfile); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_DUMP_INPUT, f); - rc = fclose(f); - if (rc) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failure closing IO input file %s: %s\n", dfile, strerror(errno)); - } - } else { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Could not dump IO input in file %s, error: %s", dfile, strerror(errno)); - } - - snprintf(dfile, sizeof(dfile), !ftdm_strlen_zero(logname) ? "%s.s%dc%d.output.alaw" : "%s/s%dc%d.output.alaw", - !ftdm_strlen_zero(logname) ? logname : r2data->logdir, ftdmchan->span_id, ftdmchan->chan_id); - f = fopen(dfile, "wb"); - if (f) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO output in file %s\n", dfile); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_DUMP_OUTPUT, f); - rc = fclose(f); - if (rc) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failure closing IO output file %s: %s\n", dfile, strerror(errno)); - } - } else { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Could not dump IO output in file %s, error: %s", dfile, strerror(errno)); - } - } -} - -static void ftdm_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode) -{ - ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_r2_data_t *r2data = ftdmchan->span->signal_data; - - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call accepted\n"); - - clear_accept_pending(ftdmchan); - - /* at this point the MF signaling has ended and there is no point on keep reading */ - openr2_chan_disable_read(r2chan); - - /* at this point we are no longer responsible for reading and writing, - * we are not interested in the stats anymore */ - ftdm_channel_clear_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); - - - R2CALL(ftdmchan)->accepted = 1; - - /* nothing went wrong during call setup, MF has ended, we can and must disable the MF dump */ - if (r2data->mf_dump_size) { - ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_INPUT_DUMP, NULL); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_OUTPUT_DUMP, NULL); - } - - if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) { - if (R2CALL(ftdmchan)->answer_pending) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Answer was pending, answering now.\n"); - ft_r2_answer_call(ftdmchan); - R2CALL(ftdmchan)->answer_pending = 0; - return; - } - } else { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); - } -} - -static void ftdm_r2_on_call_answered(openr2_chan_t *r2chan) -{ - ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call answered\n"); - /* notify the upper layer of progress in the outbound call */ - if (OR2_DIR_FORWARD == openr2_chan_get_direction(r2chan)) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); - } -} - -/* may be called in the signaling or media thread depending on whether the hangup is product of MF or CAS signaling */ -static void ftdm_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause) -{ - ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call disconnected\n"); - - clear_accept_pending(ftdmchan); - - R2CALL(ftdmchan)->disconnect_rcvd = 1; - - if (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call had been disconnected already by the user\n"); - /* just ack the hangup to trigger the on_call_end callback and go down */ - openr2_chan_disconnect_call(r2chan, OR2_CAUSE_NORMAL_CLEARING); - return; - } - - ftdmchan->caller_data.hangup_cause = ftdm_r2_cause_to_ftdm_cause(ftdmchan, cause); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); -} - -static void ftdm_r2_on_call_end(openr2_chan_t *r2chan) -{ - ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call finished\n"); - - /* the call is done as far as the stack is concerned, lets move to down here */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - - /* in some circumstances openr2 can call on_call_init right after this, so let's advance the state right here */ - ftdm_channel_advance_states(ftdmchan); -} - -static void ftdm_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen) -{ -#if 0 - ftdm_log(FTDM_LOG_NOTICE, "Call read data on chan %d\n", openr2_chan_get_number(r2chan)); -#endif -} - -static void ftdm_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm) -{ - ftdm_channel_t *fchan = openr2_chan_get_client_data(r2chan); - - ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Alarm notification %d when in state %s (sigstatus = %d)\n", - alarm, ftdm_channel_state2str(fchan->state), ftdm_test_flag(fchan, FTDM_CHANNEL_SIG_UP) ? 1 : 0); - - if (alarm) { - R2CALL(fchan)->localsuspend_on_alarm = ftdm_test_flag(fchan, FTDM_CHANNEL_SUSPENDED) ? 1 : 0; - if (ftdm_test_flag(fchan, FTDM_CHANNEL_SIG_UP) || ftdm_test_flag(fchan, FTDM_CHANNEL_SUSPENDED)) { - ftdm_r2_set_chan_sig_status(fchan, FTDM_SIG_STATE_DOWN); - } - } -} - -static void ftdm_r2_on_os_error(openr2_chan_t *r2chan, int errorcode) -{ - ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "OS error: %s\n", strerror(errorcode)); -} - -static void ftdm_r2_recover_from_protocol_error(void *data) -{ - openr2_chan_t *r2chan = data; - ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_channel_lock(ftdmchan); - if (ftdmchan->state != FTDM_CHANNEL_STATE_HANGUP) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Recovering from protocol error but state is %s!\n", ftdm_channel_state2str(ftdmchan->state)); - goto done; - } - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - ftdm_channel_advance_states(ftdmchan); -done: - ftdm_channel_unlock(ftdmchan); -} - -static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason) -{ - ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - - if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Got protocol error when we're already down!\n"); - return; - } - - dump_mf(r2chan); - - clear_accept_pending(ftdmchan); - - R2CALL(ftdmchan)->disconnect_rcvd = 1; - R2CALL(ftdmchan)->protocol_error = 1; - - if (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "The user already hung up, finishing call in protocol error\n"); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - return; - } - - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_PROTOCOL_ERROR; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); -} - -static void ftdm_r2_on_line_blocked(openr2_chan_t *r2chan) -{ - ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Far end blocked in state %s\n", ftdm_channel_state2str(ftdmchan->state)); - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP) - || !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) { - ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_SUSPENDED); - } -} - -static void ftdm_r2_on_line_idle(openr2_chan_t *r2chan) -{ - openr2_cas_signal_t rxcas, txcas; - ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - - /* get the current rx and tx cas bits */ - openr2_chan_get_cas(r2chan, &rxcas, &txcas); - ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Far end unblocked in state %s\n", ftdm_channel_state2str(ftdmchan->state)); - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP) - && txcas == OR2_CAS_IDLE) { - /* if txcas is not idle, it means we're still blocked as far as the user is concerned, do not send SIGEVENT UP, - * it will be done when the user set the line to IDLE (if the remote is still also IDLE) */ - ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP); - } else if (txcas == OR2_CAS_BLOCK && R2CALL(ftdmchan)->localsuspend_on_alarm) { - /* the user requested to block, we do not notify about state up until the user set the bits to IDLE, however - * if we're just getting back from alarmed condition, we notify about suspended again */ - ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_SUSPENDED); - } - R2CALL(ftdmchan)->localsuspend_on_alarm = 0; -} - -static void ftdm_r2_write_log(openr2_log_level_t level, const char *file, const char *function, int line, const char *message) -{ - switch (level) { - case OR2_LOG_NOTICE: - ftdm_log(file, function, line, FTDM_LOG_LEVEL_NOTICE, "%s", message); - break; - case OR2_LOG_WARNING: - ftdm_log(file, function, line, FTDM_LOG_LEVEL_WARNING, "%s", message); - break; - case OR2_LOG_ERROR: - ftdm_log(file, function, line, FTDM_LOG_LEVEL_ERROR, "%s", message); - break; - case OR2_LOG_STACK_TRACE: - case OR2_LOG_MF_TRACE: - case OR2_LOG_CAS_TRACE: - case OR2_LOG_DEBUG: - case OR2_LOG_EX_DEBUG: - ftdm_log(file, function, line, FTDM_LOG_LEVEL_DEBUG, "%s", message); - break; - default: - ftdm_log(FTDM_LOG_WARNING, "We should handle logging level %d here.\n", level); - ftdm_log(file, function, line, FTDM_LOG_LEVEL_DEBUG, "%s", message); - break; - } -} - -static void ftdm_r2_on_context_log(openr2_context_t *r2context, const char *file, const char *function, unsigned int line, - openr2_log_level_t level, const char *fmt, va_list ap) -{ -#define CONTEXT_TAG "Context - " - char logmsg[256]; - char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1]; - vsnprintf(logmsg, sizeof(logmsg), fmt, ap); - snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg); - ftdm_r2_write_log(level, file, function, line, completemsg); -#undef CONTEXT_TAG -} - -static void ftdm_r2_on_chan_log(openr2_chan_t *r2chan, const char *file, const char *function, unsigned int line, - openr2_log_level_t level, const char *fmt, va_list ap) -{ - ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - char logmsg[1024]; - char completemsg[sizeof(logmsg)]; - vsnprintf(logmsg, sizeof(logmsg), fmt, ap); - snprintf(completemsg, sizeof(completemsg), "[s%dc%d] [%d:%d] [%s] %s", - ftdmchan->span_id, ftdmchan->chan_id, ftdmchan->physical_span_id, ftdmchan->physical_chan_id, - ftdm_channel_state2str(ftdmchan->state), logmsg); - ftdm_r2_write_log(level, file, function, line, completemsg); -} - -static int ftdm_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit) -{ - ftdm_sigmsg_t sigev; - ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_size_t collected_len = R2CALL(ftdmchan)->dnis_index; - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "DNIS digit %c received\n", digit); - - /* save the digit we just received */ - ftdmchan->caller_data.dnis.digits[collected_len] = digit; - collected_len++; - ftdmchan->caller_data.dnis.digits[collected_len] = '\0'; - R2CALL(ftdmchan)->dnis_index = collected_len; - - /* notify the user about the new digit and check if we should stop requesting more DNIS */ - memset(&sigev, 0, sizeof(sigev)); - sigev.chan_id = ftdmchan->chan_id; - sigev.span_id = ftdmchan->span_id; - sigev.channel = ftdmchan; - sigev.event_id = FTDM_SIGEVENT_COLLECTED_DIGIT; - if (ftdm_span_send_signal(ftdmchan->span, &sigev) == FTDM_BREAK) { - ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Requested to stop getting DNIS. Current DNIS = %s\n", ftdmchan->caller_data.dnis.digits); - return OR2_STOP_DNIS_REQUEST; - } - - /* the only other reason to stop requesting DNIS is that there is no more room to save it */ - if (collected_len == (sizeof(ftdmchan->caller_data.dnis.digits) - 1)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "No more room for DNIS. Current DNIS = %s\n", ftdmchan->caller_data.dnis.digits); - return OR2_STOP_DNIS_REQUEST; - } - - return OR2_CONTINUE_DNIS_REQUEST; -} - -static void ftdm_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit) -{ - ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_size_t collected_len = R2CALL(ftdmchan)->ani_index; - - /* check if we should drop ANI */ - if (collected_len == (sizeof(ftdmchan->caller_data.ani.digits) - 1)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "No more room for ANI, digit dropped: %c\n", digit); - return; - } - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "ANI digit %c received\n", digit); - - /* save the digit we just received */ - ftdmchan->caller_data.ani.digits[collected_len] = digit; - collected_len++; - ftdmchan->caller_data.ani.digits[collected_len] = '\0'; - R2CALL(ftdmchan)->ani_index = collected_len; -} - -static void ftdm_r2_on_billing_pulse(openr2_chan_t *r2chan) {} - -static void ftdm_r2_on_call_log_created(openr2_chan_t *r2chan, const char *logname) -{ - ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_r2_call_t *r2call = R2CALL(ftdmchan); - /* this is used when dumping I/O for debugging */ - snprintf(r2call->logname, sizeof(r2call->logname), "%s", logname); -} - -static void ftdm_r2_on_call_proceed(openr2_chan_t *r2chan) -{ - ftdm_sigmsg_t sigev; - ftdm_channel_t *fchan = openr2_chan_get_client_data(r2chan); - memset(&sigev, 0, sizeof(sigev)); - sigev.event_id = FTDM_SIGEVENT_PROCEED; - sigev.channel = fchan; - ftdm_span_send_signal(fchan->span, &sigev); -} - -static openr2_event_interface_t ftdm_r2_event_iface = { - /* .on_call_init */ ftdm_r2_on_call_init, - /* .on_call_proceed */ ftdm_r2_on_call_proceed, - /* .on_call_offered */ ftdm_r2_on_call_offered, - /* .on_call_accepted */ ftdm_r2_on_call_accepted, - /* .on_call_answered */ ftdm_r2_on_call_answered, - /* .on_call_disconnect */ ftdm_r2_on_call_disconnect, - /* .on_call_end */ ftdm_r2_on_call_end, - /* .on_call_read */ ftdm_r2_on_call_read, - /* .on_hardware_alarm */ ftdm_r2_on_hardware_alarm, - /* .on_os_error */ ftdm_r2_on_os_error, - /* .on_protocol_error */ ftdm_r2_on_protocol_error, - /* .on_line_blocked */ ftdm_r2_on_line_blocked, - /* .on_line_idle */ ftdm_r2_on_line_idle, - - /* cast seems to be needed to get rid of the annoying warning regarding format attribute */ - /* .on_context_log */ (openr2_handle_context_logging_func)ftdm_r2_on_context_log, - /* .on_dnis_digit_received */ ftdm_r2_on_dnis_digit_received, - /* .on_ani_digit_received */ ftdm_r2_on_ani_digit_received, - - /* so far we do nothing with billing pulses */ - /* .on_billing_pulse_received */ ftdm_r2_on_billing_pulse, - /* .on_call_log_created */ ftdm_r2_on_call_log_created, -}; - -static int ftdm_r2_io_set_cas(openr2_chan_t *r2chan, int cas) -{ - ftdm_channel_t *ftdm_chan = openr2_chan_get_fd(r2chan); - ftdm_status_t status = ftdm_channel_command(ftdm_chan, FTDM_COMMAND_SET_CAS_BITS, &cas); - if (FTDM_FAIL == status) { - return -1; - } - return 0; -} - -static int ftdm_r2_io_get_cas(openr2_chan_t *r2chan, int *cas) -{ - ftdm_channel_t *ftdm_chan = openr2_chan_get_fd(r2chan); - ftdm_status_t status = ftdm_channel_command(ftdm_chan, FTDM_COMMAND_GET_CAS_BITS, cas); - if (FTDM_FAIL == status) { - return -1; - } - return 0; -} - -static int ftdm_r2_io_flush_write_buffers(openr2_chan_t *r2chan) -{ - ftdm_channel_t *ftdm_chan = openr2_chan_get_fd(r2chan); - ftdm_status_t status = ftdm_channel_command(ftdm_chan, FTDM_COMMAND_FLUSH_TX_BUFFERS, NULL); - if (FTDM_FAIL == status) { - return -1; - } - return 0; -} - -static int ftdm_r2_io_write(openr2_chan_t *r2chan, const void *buf, int size) -{ - ftdm_channel_t *ftdm_chan = openr2_chan_get_fd(r2chan); - ftdm_size_t outsize = size; - ftdm_status_t status = ftdm_channel_write(ftdm_chan, (void *)buf, size, &outsize); - if (FTDM_FAIL == status) { - return -1; - } - return (int)outsize; -} - -static int ftdm_r2_io_read(openr2_chan_t *r2chan, const void *buf, int size) -{ - ftdm_channel_t *ftdm_chan = openr2_chan_get_fd(r2chan); - ftdm_size_t outsize = size; - ftdm_status_t status = ftdm_channel_read(ftdm_chan, (void *)buf, &outsize); - if (FTDM_FAIL == status) { - return -1; - } - return (int)outsize; -} - -static int ftdm_r2_io_wait(openr2_chan_t *r2chan, int *flags, int block) -{ - ftdm_status_t status; - int32_t timeout; - ftdm_wait_flag_t ftdmflags = 0; - - ftdm_channel_t *fchan = openr2_chan_get_fd(r2chan); - timeout = block ? -1 : 0; - - if (*flags & OR2_IO_READ) { - ftdmflags |= FTDM_READ; - } - if (*flags & OR2_IO_WRITE) { - ftdmflags |= FTDM_WRITE; - } - if (*flags & OR2_IO_OOB_EVENT) { - ftdmflags |= FTDM_EVENTS; - } - - status = ftdm_channel_wait(fchan, &ftdmflags, timeout); - - if (FTDM_SUCCESS != status && FTDM_TIMEOUT != status) { - ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Failed to wait for events on channel\n"); - return -1; - } - - *flags = 0; - if (ftdmflags & FTDM_READ) { - *flags |= OR2_IO_READ; - } - if (ftdmflags & FTDM_WRITE) { - *flags |= OR2_IO_WRITE; - } - if (ftdmflags & FTDM_EVENTS) { - *flags |= OR2_IO_OOB_EVENT; - } - - return 0; -} - -/* The following openr2 hooks never get called, read on for reasoning ... */ -/* since freetdm takes care of opening the file descriptor and using openr2_chan_new_from_fd, openr2 should never call this hook */ -static openr2_io_fd_t ftdm_r2_io_open(openr2_context_t *r2context, int channo) -{ - ftdm_log(FTDM_LOG_ERROR, "I should not be called (I/O open)!!\n"); - return NULL; -} - -/* since freetdm takes care of closing the file descriptor and uses openr2_chan_new_from_fd, openr2 should never call this hook */ -static int ftdm_r2_io_close(openr2_chan_t *r2chan) -{ - ftdm_channel_t *fchan = openr2_chan_get_client_data(r2chan); - ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "I should not be called (I/O close)!!\n"); - return 0; -} - -/* since freetdm takes care of opening the file descriptor and using openr2_chan_new_from_fd, openr2 should never call this hook */ -static int ftdm_r2_io_setup(openr2_chan_t *r2chan) -{ - ftdm_channel_t *fchan = openr2_chan_get_client_data(r2chan); - ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "I should not be called (I/O Setup)!!\n"); - return 0; -} - -static int ftdm_r2_io_get_oob_event(openr2_chan_t *r2chan, openr2_oob_event_t *event) -{ - ftdm_status_t status; - ftdm_event_t *fevent = NULL; - ftdm_channel_t *ftdmchan = openr2_chan_get_fd(r2chan); - - *event = OR2_OOB_EVENT_NONE; - - status = ftdm_channel_read_event(ftdmchan, &fevent); - - if (status != FTDM_SUCCESS) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "failed to retrieve freetdm event!\n"); - return -1; - } - - if (fevent->e_type != FTDM_EVENT_OOB) { - return 0; - } - - switch (fevent->enum_id) { - case FTDM_OOB_CAS_BITS_CHANGE: - { - *event = OR2_OOB_EVENT_CAS_CHANGE; - } - break; - case FTDM_OOB_ALARM_TRAP: - { - *event = OR2_OOB_EVENT_ALARM_ON; - } - break; - case FTDM_OOB_ALARM_CLEAR: - { - *event = OR2_OOB_EVENT_ALARM_OFF; - } - break; - } - return 0; -} - -static int ftdm_r2_io_get_alarm_state(openr2_chan_t *r2chan, int *alarm) -{ - ftdm_channel_t *fchan = openr2_chan_get_fd(r2chan); - ftdm_assert_return(alarm, -1, "Alarm pointer is null\n"); - *alarm = ftdm_test_flag(fchan, FTDM_CHANNEL_IN_ALARM) ? 1 : 0; - return 0; -} - -static openr2_io_interface_t ftdm_r2_io_iface = { - /* .open */ ftdm_r2_io_open, /* never called */ - /* .close */ ftdm_r2_io_close, /* never called */ - /* .set_cas */ ftdm_r2_io_set_cas, - /* .get_cas */ ftdm_r2_io_get_cas, - /* .flush_write_buffers */ ftdm_r2_io_flush_write_buffers, - /* .write */ ftdm_r2_io_write, - /* .read */ ftdm_r2_io_read, - /* .setup */ ftdm_r2_io_setup, /* never called */ - /* .wait */ ftdm_r2_io_wait, - /* .get_oob_event */ ftdm_r2_io_get_oob_event, - /* .get_alarm_state */ ftdm_r2_io_get_alarm_state -}; - -/* resolve a loglevel string, such as "debug,notice,warning", to an openr2 log level integer */ -static openr2_log_level_t ftdm_r2_loglevel_from_string(const char *level) -{ - openr2_log_level_t tmplevel; - openr2_log_level_t newlevel = 0; - char *clevel = NULL; - char *logval = NULL; - - logval = ftdm_malloc(strlen(level)+1); /* alloca man page scared me, so better to use good ol' malloc */ - if (!logval) { - ftdm_log(FTDM_LOG_WARNING, "Ignoring R2 logging parameter: '%s', failed to alloc memory\n", level); - return newlevel; - } - strcpy(logval, level); - while (logval) { - clevel = strsep(&logval, ","); - if (-1 == (tmplevel = openr2_log_get_level(clevel))) { - ftdm_log(FTDM_LOG_WARNING, "Ignoring invalid R2 logging level: '%s'\n", clevel); - continue; - } - newlevel |= tmplevel; - } - ftdm_safe_free(logval); - return newlevel; -} - -static ftdm_state_map_t r2_state_map = { - { - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_ANY, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - }, - - /* Outbound states */ - - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_ANY, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_END} - }, - - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END} - }, - - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_END} - }, - - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_END} - }, - - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END} - }, - - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END} - }, - - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END} - }, - - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END} - }, - } -}; - -static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling) -{ - unsigned int i = 0; - int conf_failure = 0; - int intval = 0; - char schedname[255]; - const char *var = NULL, *val = NULL; - const char *log_level = "notice,warning,error"; /* default loglevel, if none is read from conf */ - ftdm_r2_data_t *r2data = NULL; - ftdm_r2_span_pvt_t *spanpvt = NULL; - ftdm_r2_call_t *r2call = NULL; - openr2_chan_t *r2chan = NULL; - unsigned paramindex = 0; - - ft_r2_conf_t r2conf = - { - /* .variant */ OR2_VAR_ITU, - /* .category */ OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER, - /* .loglevel */ OR2_LOG_ERROR | OR2_LOG_WARNING, -#ifdef WIN32 - /* .logdir */ (char *)"c:\\", -#else - /* .logdir */ (char *)"/tmp", -#endif - /* .advanced_protocol_file */ NULL, - /* .max_ani */ 10, - /* .max_dnis */ 4, - /* .mfback_timeout */ -1, - /* .metering_pulse_timeout */ -1, - /* .mf_dump_size */ 0, - /* .immediate_accept */ -1, - /* .skip_category */ -1, - /* .get_ani_first */ -1, - /* .call_files */ 0, - /* .double_answer */ -1, - /* .charge_calls */ -1, - /* .forced_release */ -1, - /* .allow_collect_calls */ -1, - /* .use_channel_native_mf_generation */ 0 - }; - - ftdm_assert_return(sig_cb != NULL, FTDM_FAIL, "No signaling cb provided\n"); - - if (span->signal_type) { - snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling."); - return FTDM_FAIL; - } - - for (; ftdm_parameters[paramindex].var; paramindex++) { - var = ftdm_parameters[paramindex].var; - val = ftdm_parameters[paramindex].val; - ftdm_log(FTDM_LOG_DEBUG, "Reading R2 parameter %s for span %d\n", var, span->span_id); - if (!strcasecmp(var, "variant")) { - if (!val) { - break; - } - if (ftdm_strlen_zero_buf(val)) { - ftdm_log(FTDM_LOG_NOTICE, "Ignoring empty R2 variant parameter\n"); - continue; - } - r2conf.variant = openr2_proto_get_variant(val); - if (r2conf.variant == OR2_VAR_UNKNOWN) { - ftdm_log(FTDM_LOG_ERROR, "Unknown R2 variant %s\n", val); - conf_failure = 1; - break; - } - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d for variant %s\n", span->span_id, val); - } else if (!strcasecmp(var, "category")) { - if (!val) { - break; - } - if (ftdm_strlen_zero_buf(val)) { - ftdm_log(FTDM_LOG_NOTICE, "Ignoring empty R2 category parameter\n"); - continue; - } - r2conf.category = openr2_proto_get_category(val); - if (r2conf.category == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) { - ftdm_log(FTDM_LOG_ERROR, "Unknown R2 caller category %s\n", val); - conf_failure = 1; - break; - } - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with default category %s\n", span->span_id, val); - } else if (!strcasecmp(var, "logdir")) { - if (!val) { - break; - } - if (ftdm_strlen_zero_buf(val)) { - ftdm_log(FTDM_LOG_NOTICE, "Ignoring empty R2 logdir parameter\n"); - continue; - } - r2conf.logdir = (char *)val; - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with logdir %s\n", span->span_id, val); - } else if (!strcasecmp(var, "logging")) { - if (!val) { - break; - } - if (ftdm_strlen_zero_buf(val)) { - ftdm_log(FTDM_LOG_NOTICE, "Ignoring empty R2 logging parameter\n"); - continue; - } - log_level = val; - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with loglevel %s\n", span->name, val); - } else if (!strcasecmp(var, "advanced_protocol_file")) { - if (!val) { - break; - } - if (ftdm_strlen_zero_buf(val)) { - ftdm_log(FTDM_LOG_NOTICE, "Ignoring empty R2 advanced_protocol_file parameter\n"); - continue; - } - r2conf.advanced_protocol_file = (char *)val; - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with advanced protocol file %s\n", span->name, val); - } else if (!strcasecmp(var, "mf_dump_size")) { - intval = atoi(val); - if (intval < 0) { - r2conf.mf_dump_size = FTDM_IO_DUMP_DEFAULT_BUFF_SIZE; - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with default mf_dump_size = %"FTDM_SIZE_FMT" bytes\n", span->name, r2conf.mf_dump_size); - } else { - r2conf.mf_dump_size = intval; - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with mf_dump_size = %"FTDM_SIZE_FMT" bytes\n", span->name, r2conf.mf_dump_size); - } - } else if (!strcasecmp(var, "allow_collect_calls")) { - r2conf.allow_collect_calls = ftdm_true(val); - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with allow collect calls max ani = %d\n", span->name, r2conf.allow_collect_calls); - } else if (!strcasecmp(var, "double_answer")) { - r2conf.double_answer = ftdm_true(val); - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with double answer = %d\n", span->name, r2conf.double_answer); - } else if (!strcasecmp(var, "immediate_accept")) { - r2conf.immediate_accept = ftdm_true(val); - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with immediate accept = %d\n", span->name, r2conf.immediate_accept); - } else if (!strcasecmp(var, "skip_category")) { - r2conf.skip_category = ftdm_true(val); - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with skip category = %d\n", span->name, r2conf.skip_category); - } else if (!strcasecmp(var, "forced_release")) { - r2conf.forced_release = ftdm_true(val); - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with forced release = %d\n", span->name, r2conf.forced_release); - } else if (!strcasecmp(var, "charge_calls")) { - r2conf.charge_calls = ftdm_true(val); - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with charge calls = %d\n", span->name, r2conf.charge_calls); - } else if (!strcasecmp(var, "get_ani_first")) { - r2conf.get_ani_first = ftdm_true(val); - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with get ani first = %d\n", span->name, r2conf.get_ani_first); - } else if (!strcasecmp(var, "call_files")) { - r2conf.call_files = ftdm_true(val); - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with call files = %d\n", span->name, r2conf.call_files); - } else if (!strcasecmp(var, "mfback_timeout")) { - r2conf.mfback_timeout = atoi(val); - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with MF backward timeout = %dms\n", span->name, r2conf.mfback_timeout); - } else if (!strcasecmp(var, "metering_pulse_timeout")) { - r2conf.metering_pulse_timeout = atoi(val); - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with metering pulse timeout = %dms\n", span->name, r2conf.metering_pulse_timeout); - } else if (!strcasecmp(var, "max_ani")) { - r2conf.max_ani = atoi(val); - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with max ani = %d\n", span->name, r2conf.max_ani); - } else if (!strcasecmp(var, "max_dnis")) { - r2conf.max_dnis = atoi(val); - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with max dnis = %d\n", span->name, r2conf.max_dnis); - } else if (!strcasecmp(var, "use_channel_native_mf_generation")) { - r2conf.use_channel_native_mf_generation = ftdm_true(val); - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with \"use native channel MF generation\" = %d\n", span->name, r2conf.use_channel_native_mf_generation); - } else { - snprintf(span->last_error, sizeof(span->last_error), "Unknown R2 parameter [%s]", var); - return FTDM_FAIL; - } - } - - if (conf_failure) { - snprintf(span->last_error, sizeof(span->last_error), "R2 configuration error"); - return FTDM_FAIL; - } - - /* set span log level */ - r2conf.loglevel = ftdm_r2_loglevel_from_string(log_level); - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with loglevel %s\n", span->span_id, log_level); - - r2data = ftdm_malloc(sizeof(*r2data)); - if (!r2data) { - snprintf(span->last_error, sizeof(span->last_error), "Failed to allocate R2 data."); - return FTDM_FAIL; - } - memset(r2data, 0, sizeof(*r2data)); - - spanpvt = ftdm_malloc(sizeof(*spanpvt)); - if (!spanpvt) { - snprintf(span->last_error, sizeof(span->last_error), "Failed to allocate private span data container."); - goto fail; - } - memset(spanpvt, 0, sizeof(*spanpvt)); - - r2data->r2context = openr2_context_new(r2conf.variant, &ftdm_r2_event_iface, r2conf.max_ani, r2conf.max_dnis); - if (!r2data->r2context) { - snprintf(span->last_error, sizeof(span->last_error), "Cannot create openr2 context for span."); - goto fail; - } - openr2_context_set_io_type(r2data->r2context, OR2_IO_CUSTOM, &ftdm_r2_io_iface); - openr2_context_set_log_level(r2data->r2context, r2conf.loglevel); - openr2_context_set_ani_first(r2data->r2context, r2conf.get_ani_first); - openr2_context_set_skip_category_request(r2data->r2context, r2conf.skip_category); - openr2_context_set_mf_back_timeout(r2data->r2context, r2conf.mfback_timeout); - openr2_context_set_metering_pulse_timeout(r2data->r2context, r2conf.metering_pulse_timeout); - openr2_context_set_double_answer(r2data->r2context, r2conf.double_answer); - openr2_context_set_immediate_accept(r2data->r2context, r2conf.immediate_accept); - - ftdm_log(FTDM_LOG_DEBUG, "Setting span %s logdir to %s\n", span->name, r2conf.logdir); - openr2_context_set_log_directory(r2data->r2context, r2conf.logdir); - snprintf(r2data->logdir, sizeof(r2data->logdir), "%s", r2conf.logdir); - - if (r2conf.advanced_protocol_file) { - openr2_context_configure_from_advanced_file(r2data->r2context, r2conf.advanced_protocol_file); - } - - if(r2conf.use_channel_native_mf_generation) { - openr2_context_set_mflib_interface(r2data->r2context, ftdm_r2_get_native_channel_mf_generation_iface()); - } - - spanpvt->r2calls = create_hashtable(FTDM_MAX_CHANNELS_SPAN, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); - if (!spanpvt->r2calls) { - snprintf(span->last_error, sizeof(span->last_error), "Cannot create channel calls hash for span."); - goto fail; - } - - for (i = 1; (i <= span->chan_count) && (i <= FTDM_MAX_CHANNELS_SPAN); i++) { - r2chan = openr2_chan_new_from_fd(r2data->r2context, span->channels[i], span->channels[i]->chan_id); - if (!r2chan) { - snprintf(span->last_error, sizeof(span->last_error), "Cannot create all openr2 channels for span."); - goto fail; - } - openr2_chan_set_log_level(r2chan, r2conf.loglevel); - if (r2conf.call_files) { - openr2_chan_enable_call_files(r2chan); - } - - if (r2conf.use_channel_native_mf_generation) { - /* Allocate a new write handle per r2chan */ - ftdm_r2_mf_write_handle_t *mf_write_handle = ftdm_calloc(1, sizeof(*mf_write_handle)); - /* Associate to the FreeTDM channel */ - mf_write_handle->ftdmchan = span->channels[i]; - /* Make sure the FreeTDM channel supports MF the generation feature */ - if (!ftdm_channel_test_feature(mf_write_handle->ftdmchan, FTDM_CHANNEL_FEATURE_MF_GENERATE)) { - ftdm_log_chan_msg(mf_write_handle->ftdmchan, FTDM_LOG_ERROR, - "FreeTDM channel does not support native MF generation: " - "\"use_channel_native_mf_generation\" configuration parameter cannot" - " be used\n"); - goto fail; - } - /* Associate the mf_write_handle to the openR2 channel */ - openr2_chan_set_mflib_handles(r2chan, mf_write_handle, NULL); - } - - r2call = ftdm_calloc(1, sizeof(*r2call)); - if (!r2call) { - snprintf(span->last_error, sizeof(span->last_error), "Cannot create all R2 call data structures for the span."); - ftdm_safe_free(r2chan); - goto fail; - } - openr2_chan_set_logging_func(r2chan, ftdm_r2_on_chan_log); - openr2_chan_set_client_data(r2chan, span->channels[i]); - r2call->r2chan = r2chan; - span->channels[i]->call_data = r2call; - /* value and key are the same so just free one of them */ - snprintf(r2call->name, sizeof(r2call->name), "chancall%d", i); - hashtable_insert(spanpvt->r2calls, (void *)r2call->name, r2call, HASHTABLE_FLAG_FREE_VALUE); - } - r2data->mf_dump_size = r2conf.mf_dump_size; - r2data->category = r2conf.category; - r2data->allow_collect_calls = r2conf.allow_collect_calls; - r2data->flags = 0; - r2data->charge_calls = r2conf.charge_calls; - r2data->forced_release = r2conf.forced_release; - spanpvt->r2context = r2data->r2context; - - /* just the value must be freed by the hash */ - hashtable_insert(g_mod_data_hash, (void *)span->name, spanpvt, HASHTABLE_FLAG_FREE_VALUE); - - span->start = ftdm_r2_start; - span->stop = ftdm_r2_stop; - span->sig_read = NULL; - span->sig_write = NULL; - - span->signal_cb = sig_cb; - span->signal_type = FTDM_SIGTYPE_R2; - span->signal_data = r2data; - span->outgoing_call = r2_outgoing_call; - span->get_span_sig_status = ftdm_r2_get_span_sig_status; - span->set_span_sig_status = ftdm_r2_set_span_sig_status; - span->get_channel_sig_status = ftdm_r2_get_channel_sig_status; - span->set_channel_sig_status = ftdm_r2_set_channel_sig_status; - - span->state_map = &r2_state_map; - span->state_processor = ftdm_r2_state_advance; - - /* use signals queue */ - ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE); - - /* we can skip states (going straight from RING to UP) */ - ftdm_set_flag(span, FTDM_SPAN_USE_SKIP_STATES); - - /* setup the scheduler */ - snprintf(schedname, sizeof(schedname), "ftmod_r2_%s", span->name); - ftdm_assert(ftdm_sched_create(&r2data->sched, schedname) == FTDM_SUCCESS, "Failed to create schedule!\n"); - spanpvt->sched = r2data->sched; - - return FTDM_SUCCESS; - -fail: - - if (r2data && r2data->r2context) { - openr2_context_delete(r2data->r2context); - } - if (spanpvt && spanpvt->r2calls) { - hashtable_destroy(spanpvt->r2calls); - } - ftdm_safe_free(r2data); - ftdm_safe_free(spanpvt); - return FTDM_FAIL; - -} - -/* the channel must be locked when calling this function */ -static ftdm_status_t ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) -{ - ftdm_sigmsg_t sigev; - ftdm_status_t ret; - ftdm_r2_call_t *r2call = R2CALL(ftdmchan); - openr2_chan_t *r2chan = r2call->r2chan; - ftdm_r2_data_t *r2data = ftdmchan->span->signal_data; - - memset(&sigev, 0, sizeof(sigev)); - sigev.chan_id = ftdmchan->chan_id; - sigev.span_id = ftdmchan->span_id; - sigev.channel = ftdmchan; - - ret = FTDM_SUCCESS; - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Executing state handler for %s\n", ftdm_channel_state2str(ftdmchan->state)); - - if (IS_ACCEPTING_PENDING(ftdmchan)) { - /* - Moving to PROGRESS, PROGRESS_MEDIA or UP means that we must accept the call first, and accepting - the call in R2 means sending a tone, then waiting for the acknowledge from the other end, - since all of that requires sending and detecting tones, it takes a few milliseconds (I'd say around 100) - which means during that time the user should not try to perform any operations like answer, hangup or anything - else, therefore we DO NOT clear the FTDM_CHANNEL_STATE_CHANGE flag here, we rely on ftdm_io.c to block - the user thread until we're done with the accept (see on_call_accepted callback) and then we clear the state change flag, - otherwise we have a race condition between freetdm calling openr2_chan_answer_call and openr2 accepting the call first, - if freetdm calls openr2_chan_answer_call before the accept cycle completes, openr2 will fail to answer the call */ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "State ack for state %s will have to wait a bit\n", ftdm_channel_state2str(ftdmchan->state)); - } else if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN){ - ftdm_channel_complete_state(ftdmchan); - } - - switch (ftdmchan->state) { - - /* starting an incoming call */ - case FTDM_CHANNEL_STATE_COLLECT: - { - uint32_t interval = 0; - ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval); - ftdm_assert(interval != 0, "Invalid interval!"); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Starting processing of incoming call with interval %d\n", interval); - openr2_chan_enable_read(r2chan); - } - break; - - /* starting an outgoing call */ - case FTDM_CHANNEL_STATE_DIALING: - { - uint32_t interval = 0; - ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval); - ftdm_assert(interval != 0, "Invalid interval!"); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Starting outgoing call with interval %d\n", interval); - openr2_chan_enable_read(r2chan); - } - break; - - /* incoming call was offered */ - case FTDM_CHANNEL_STATE_RING: - - /* notify the user about the new call */ - sigev.event_id = FTDM_SIGEVENT_START; - ftdm_span_send_signal(ftdmchan->span, &sigev); - break; - - /* the call is making progress */ - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - { - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - if (!r2call->accepted) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Accepting call\n"); - ft_r2_accept_call(ftdmchan); - } - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Notifying progress\n"); - sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA; - ftdm_span_send_signal(ftdmchan->span, &sigev); - } - } - break; - - /* the call was answered */ - case FTDM_CHANNEL_STATE_UP: - { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call was answered\n"); - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - if (!r2call->accepted) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call has not been accepted, need to accept first\n"); - // the answering will be done in the on_call_accepted handler - ft_r2_accept_call(ftdmchan); - r2call->answer_pending = 1; - } else { - ft_r2_answer_call(ftdmchan); - } - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Notifying of call answered\n"); - sigev.event_id = FTDM_SIGEVENT_UP; - ftdm_span_send_signal(ftdmchan->span, &sigev); - } - } - break; - - /* just got hangup */ - case FTDM_CHANNEL_STATE_HANGUP: - { - if (!r2call->disconnect_rcvd) { - openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan); - /* overwrite the hangup cause if this is an incoming call and forced_release is set */ - if (openr2_chan_get_direction(r2chan) == OR2_DIR_BACKWARD && r2data->forced_release) { - disconnect_cause = OR2_CAUSE_FORCED_RELEASE; - } - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause)); - /* this will disconnect the call, but need to wait for the call end before moving to DOWN */ - openr2_chan_disconnect_call(r2chan, disconnect_cause); - } else if (!r2call->protocol_error) { - /* just ack the hangup, on_call_end will be called by openr2 right after */ - openr2_chan_disconnect_call(r2chan, OR2_CAUSE_NORMAL_CLEARING); - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Clearing call due to protocol error\n"); - /* do not set to down yet, give some time for recovery */ - ftdm_sched_timer(r2data->sched, "protocolerr_recover", 100, - ftdm_r2_recover_from_protocol_error, r2chan, &r2call->protocol_error_recovery_timer); - } - } - break; - - case FTDM_CHANNEL_STATE_TERMINATING: - { - /* if the call has not been started yet we must go to HANGUP right here */ - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED)) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - } else { - openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause)); - /* notify the user of the call terminating and we wait for the user to move us to hangup */ - sigev.event_id = FTDM_SIGEVENT_STOP; - ftdm_span_send_signal(ftdmchan->span, &sigev); - } - } - break; - - /* finished call for good */ - case FTDM_CHANNEL_STATE_DOWN: - { - if (ftdmchan->last_state != FTDM_CHANNEL_STATE_RESET) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "R2 Call is down\n"); - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "R2 Reset Complete\n"); - } - ret = FTDM_BREAK; - } - break; - - /* INDICATE_RINGING doesn't apply to MFC/R2. maybe we could generate a tone */ - case FTDM_CHANNEL_STATE_RINGING: - { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "RINGING indicated, ignoring it as it doesn't apply to MFC/R2\n"); - } - break; - - /* put the r2 channel back to IDLE, close ftdmchan and set it's state as DOWN */ - case FTDM_CHANNEL_STATE_RESET: - { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "RESET indicated, putting the R2 channel back to IDLE\n"); - openr2_chan_set_idle(r2chan); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - break; - - default: - { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Unhandled channel state change: %s\n", ftdm_channel_state2str(ftdmchan->state)); - } - break; - } - - if (ret == FTDM_BREAK) { - ftdm_channel_t *closed_chan; - closed_chan = ftdmchan; - ftdm_channel_close(&closed_chan); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "State processing ended.\n"); - } - return ret; -} - -static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) -{ - openr2_chan_t *r2chan = NULL; - ftdm_channel_t *ftdmchan = NULL; - ftdm_r2_call_t *call = NULL; - ftdm_status_t status; - ftdm_span_t *span = (ftdm_span_t *) obj; - ftdm_r2_data_t *r2data = span->signal_data; - int waitms = 20; - unsigned int i; - int res, ms; - int index = 0; - struct timeval start, end; - ftdm_iterator_t *chaniter = NULL; - ftdm_iterator_t *citer = NULL; - uint32_t txqueue_size = 4; - short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count); - - /* as long as this thread is running, this flag is set */ - ftdm_set_flag(r2data, FTDM_R2_RUNNING); - -#ifdef __linux__ - r2data->monitor_thread_id = syscall(SYS_gettid); -#endif - - ftdm_log(FTDM_LOG_DEBUG, "OpenR2 monitor thread %u started.\n", r2data->monitor_thread_id); - r2chan = NULL; - chaniter = ftdm_span_get_chan_iterator(span, NULL); - if (!chaniter) { - ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name); - goto done; - } - for (i = 1, citer = chaniter; citer; citer = ftdm_iterator_next(citer), i++) { - ftdmchan = ftdm_iterator_current(citer); - ftdm_channel_lock(ftdmchan); - r2chan = R2CALL(ftdmchan)->r2chan; - openr2_chan_set_span_id(r2chan, span->span_id); - openr2_chan_set_idle(r2chan); - openr2_chan_process_cas_signaling(r2chan); - ftdm_channel_unlock(ftdmchan); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &txqueue_size); - } - - memset(&start, 0, sizeof(start)); - memset(&end, 0, sizeof(end)); - while (ftdm_running() && ftdm_test_flag(r2data, FTDM_R2_SPAN_STARTED)) { - res = gettimeofday(&end, NULL); - if (res) { - ftdm_log(FTDM_LOG_CRIT, "Failure gettimeofday [%s]\n", strerror(errno)); - } - if (start.tv_sec) { - ms = ((end.tv_sec - start.tv_sec) * 1000) - + ((( 1000000 + end.tv_usec - start.tv_usec) / 1000) - 1000); - if (ms < 0) { - ms = 0; - } - if (ms > r2data->jobmax) { - r2data->jobmax = ms; - } - index = (ms / 10); - index = (index > 10) ? 10 : index; - r2data->loops[index]++; - r2data->total_loops++; - } - - /* run any span timers */ - ftdm_sched_run(r2data->sched); - - /* deliver the actual channel events to the user now without any channel locking */ - ftdm_span_trigger_signals(span); - - /* figure out what event to poll each channel for. POLLPRI when the channel is down, - * POLLPRI|POLLIN|POLLOUT otherwise */ - memset(poll_events, 0, sizeof(short)*span->chan_count); - citer = ftdm_span_get_chan_iterator(span, chaniter); - if (!citer) { - ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name); - goto done; - } - for (i = 0; citer; citer = ftdm_iterator_next(citer), i++) { - ftdmchan = ftdm_iterator_current(citer); - r2chan = R2CALL(ftdmchan)->r2chan; - poll_events[i] = FTDM_EVENTS; - if (openr2_chan_get_read_enabled(r2chan)) { - poll_events[i] |= FTDM_READ; - } - } - status = ftdm_span_poll_event(span, waitms, poll_events); - - /* run any span timers */ - ftdm_sched_run(r2data->sched); - - res = gettimeofday(&start, NULL); - if (res) { - ftdm_log(FTDM_LOG_CRIT, "Failure gettimeofday [%s]\n", strerror(errno)); - } - - if (FTDM_FAIL == status) { - ftdm_log(FTDM_LOG_CRIT, "Failure waiting I/O! [%s]\n", span->channels[1]->last_error); - continue; - } - - ms = ((start.tv_sec - end.tv_sec) * 1000) - + ((( 1000000 + start.tv_usec - end.tv_usec) / 1000) - 1000); - if (ms < 0) { - ms = 0; - } - if (ms > r2data->sleepmax) { - r2data->sleepmax = ms; - } - index = (ms / 15); - index = (index > 10) ? 10 : index; - r2data->sleeps[index]++; - r2data->total_sleeps++; - - /* this main loop takes care of MF and CAS signaling during call setup and tear down - * for every single channel in the span, do not perform blocking operations here! */ - citer = ftdm_span_get_chan_iterator(span, chaniter); - for ( ; citer; citer = ftdm_iterator_next(citer)) { - ftdmchan = ftdm_iterator_current(citer); - - ftdm_channel_lock(ftdmchan); - - call = R2CALL(ftdmchan); - - /* This let knows the core and io signaling hooks know that - * read/writes come from us and should be allowed */ - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_TX_DISABLED); - - ftdm_channel_advance_states(ftdmchan); - - r2chan = call->r2chan; - openr2_chan_process_signaling(r2chan); - - ftdm_channel_advance_states(ftdmchan); - - if (!call->accepted) { - /* if the call is not accepted we do not want users reading */ - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED); - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_TX_DISABLED); - } - - ftdm_channel_unlock(ftdmchan); - } - } - -done: - citer = ftdm_span_get_chan_iterator(span, chaniter); - for ( ; citer; citer = ftdm_iterator_next(citer)) { - ftdmchan = ftdm_iterator_current(citer); - ftdm_channel_lock(ftdmchan); - r2chan = R2CALL(ftdmchan)->r2chan; - openr2_chan_set_blocked(r2chan); - ftdm_channel_unlock(ftdmchan); - } - - ftdm_iterator_free(chaniter); - ftdm_safe_free(poll_events); - - ftdm_clear_flag(r2data, FTDM_R2_RUNNING); - ftdm_log(FTDM_LOG_DEBUG, "R2 thread ending.\n"); - - return NULL; -} - -static void __inline__ block_channel(ftdm_channel_t *fchan, ftdm_stream_handle_t *stream) -{ - openr2_chan_t *r2chan = R2CALL(fchan)->r2chan; - ftdm_mutex_lock(fchan->mutex); - if (fchan->state != FTDM_CHANNEL_STATE_DOWN) { - stream->write_function(stream, "cannot block channel %d:%d because has a call in progress\n", - fchan->span_id, fchan->chan_id); - } else { - if (!openr2_chan_set_blocked(r2chan)) { - ftdm_set_flag(fchan, FTDM_CHANNEL_SUSPENDED); - stream->write_function(stream, "blocked channel %d:%d\n", - fchan->span_id, fchan->chan_id); - } else { - stream->write_function(stream, "failed to block channel %d:%d\n", - fchan->span_id, fchan->chan_id); - } - } - ftdm_mutex_unlock(fchan->mutex); -} - -static void __inline__ unblock_channel(ftdm_channel_t *fchan, ftdm_stream_handle_t *stream) -{ - openr2_chan_t *r2chan = R2CALL(fchan)->r2chan; - ftdm_mutex_lock(fchan->mutex); - if (!openr2_chan_set_idle(r2chan)) { - ftdm_clear_flag(fchan, FTDM_CHANNEL_SUSPENDED); - stream->write_function(stream, "unblocked channel %d:%d\n", - fchan->span_id, fchan->chan_id); - } else { - stream->write_function(stream, "failed to unblock channel %d:%d\n", - fchan->span_id, fchan->chan_id); - } - ftdm_mutex_unlock(fchan->mutex); -} - -#define FT_SYNTAX "USAGE:\n" \ -"--------------------------------------------------------------------------------\n" \ -"ftdm r2 status \n" \ -"ftdm r2 loopstats \n" \ -"ftdm r2 block|unblock []\n" \ -"ftdm r2 version\n" \ -"ftdm r2 variants\n" \ -"--------------------------------------------------------------------------------\n" -static FIO_API_FUNCTION(ftdm_r2_api) -{ - ftdm_span_t *span = NULL; - char *mycmd = NULL, *argv[10] = { 0 }; - int argc = 0; - int span_id = 0; - unsigned int chan_id = 0; - unsigned int i = 0; - ftdm_r2_data_t *r2data = NULL; - openr2_chan_t *r2chan = NULL; - openr2_context_t *r2context = NULL; - openr2_variant_t r2variant; - - if (data) { - mycmd = ftdm_strdup(data); - argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); - } - - if (argc >= 2) { - if (!strcasecmp(argv[0], "block")) { - int span_id = atoi(argv[1]); - - if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) { - - if (span->start != ftdm_r2_start) { - stream->write_function(stream, "-ERR invalid span.\n"); - goto done; - } - - if (argc > 2) { - chan_id = atoi(argv[2]); - if (chan_id && chan_id <= span->chan_count) { - block_channel(span->channels[chan_id], stream); - } else { - stream->write_function(stream, "-ERR invalid chan %d.\n", chan_id); - } - } else { - for (i = 1; i <= span->chan_count; i++) { - block_channel(span->channels[i], stream); - } - } - stream->write_function(stream, "+OK blocked.\n"); - goto done; - } else { - stream->write_function(stream, "-ERR invalid span.\n"); - goto done; - } - } - - if (!strcasecmp(argv[0], "unblock")) { - span_id = atoi(argv[1]); - if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) { - - if (span->start != ftdm_r2_start) { - stream->write_function(stream, "-ERR invalid span.\n"); - goto done; - } - - if (argc > 2) { - chan_id = atoi(argv[2]); - if (chan_id && chan_id <= span->chan_count) { - unblock_channel(span->channels[chan_id], stream); - } else { - stream->write_function(stream, "-ERR invalid chan %d.\n", chan_id); - } - } else { - for (i = 1; i <= span->chan_count; i++) { - unblock_channel(span->channels[i], stream); - } - } - - stream->write_function(stream, "+OK.\n"); - goto done; - } else { - stream->write_function(stream, "-ERR invalid span.\n"); - goto done; - } - - } - - if (!strcasecmp(argv[0], "status")) { - //openr2_chan_stats_t stats; - span_id = atoi(argv[1]); - - if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) { - if (span->start != ftdm_r2_start) { - stream->write_function(stream, "-ERR not an R2 span.\n"); - goto done; - } - if (!(r2data = span->signal_data)) { - stream->write_function(stream, "-ERR invalid span. No R2 signal data in span.\n"); - goto done; - } - r2context = r2data->r2context; - r2variant = openr2_context_get_variant(r2context); - stream->write_function(stream, - "Variant: %s\n" - "Max ANI: %d\n" - "Max DNIS: %d\n" - "ANI First: %s\n" - "Immediate Accept: %s\n" - "Job Thread: %u\n" - "Job Max ms: %d\n" - "Job Loops: %lu\n", - openr2_proto_get_variant_string(r2variant), - openr2_context_get_max_ani(r2context), - openr2_context_get_max_dnis(r2context), - openr2_context_get_ani_first(r2context) ? "Yes" : "No", - openr2_context_get_immediate_accept(r2context) ? "Yes" : "No", - r2data->monitor_thread_id, - r2data->jobmax, - r2data->total_loops); - stream->write_function(stream, "\n"); - stream->write_function(stream, "%4s %-12.12s %-12.12s\n", "Channel", "Tx CAS", "Rx CAS"); - for (i = 1; i <= span->chan_count; i++) { - r2chan = R2CALL(span->channels[i])->r2chan; - stream->write_function(stream, "%4d %-12.12s %-12.12s\n", - span->channels[i]->chan_id, - openr2_chan_get_tx_cas_string(r2chan), - openr2_chan_get_rx_cas_string(r2chan)); - } - stream->write_function(stream, "\n"); - stream->write_function(stream, "+OK.\n"); - goto done; - } else { - stream->write_function(stream, "-ERR invalid span.\n"); - goto done; - } - } - - if (!strcasecmp(argv[0], "loopstats")) { - int range; - float pct; - span_id = atoi(argv[1]); - - if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) { - if (span->start != ftdm_r2_start) { - stream->write_function(stream, "-ERR not an R2 span.\n"); - goto done; - } - if (!(r2data = span->signal_data)) { - stream->write_function(stream, "-ERR invalid span. No R2 signal data in span.\n"); - goto done; - } - stream->write_function(stream, "-- Working --\n"); - stream->write_function(stream, "Total loops: %llu\n", r2data->total_loops); - range = 0; - for (i = 0; i < ftdm_array_len(r2data->loops); i++) { - pct = 100*(float)r2data->loops[i]/r2data->total_loops; - if ((i + 1) == ftdm_array_len(r2data->loops)) { - stream->write_function(stream, ">= %dms: %llu - %.03lf%%\n", range, r2data->loops[i], pct); - } else { - stream->write_function(stream, "%d-%dms: %llu - %.03lf%%\n", range, range + 9, r2data->loops[i], pct); - } - range += 10; - } - stream->write_function(stream, "\n"); - - stream->write_function(stream, "-- Sleeping --\n"); - stream->write_function(stream, "Total sleeps: %llu\n", r2data->total_sleeps); - range = 0; - for (i = 0; i < ftdm_array_len(r2data->sleeps); i++) { - pct = 100*(float)r2data->sleeps[i]/r2data->total_sleeps; - if ((i + 1) == ftdm_array_len(r2data->sleeps)) { - stream->write_function(stream, ">= %dms: %llu - %.03lf%%\n", range, r2data->sleeps[i], pct); - } else { - stream->write_function(stream, "%d-%dms: %llu - %.03lf%%\n", range, range + 14, r2data->sleeps[i], pct); - } - range += 15; - } - stream->write_function(stream, "\n"); - - stream->write_function(stream, "+OK.\n"); - goto done; - } else { - stream->write_function(stream, "-ERR invalid span.\n"); - goto done; - } - } - - } - - if (argc == 1) { - if (!strcasecmp(argv[0], "version")) { - stream->write_function(stream, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision()); - stream->write_function(stream, "+OK.\n"); - goto done; - } - - if (!strcasecmp(argv[0], "variants")) { - int32_t numvariants = 0; - const openr2_variant_entry_t *variants = openr2_proto_get_variant_list(&numvariants); - if (!variants) { - stream->write_function(stream, "-ERR failed to retrieve openr2 variant list.\n"); - goto done; - } -#define VARIANT_FORMAT "%4s %40s\n" - stream->write_function(stream, VARIANT_FORMAT, "Variant Code", "Country"); - numvariants--; - for (; numvariants; numvariants--) { - stream->write_function(stream, VARIANT_FORMAT, variants[numvariants].name, variants[numvariants].country); - } - stream->write_function(stream, "+OK.\n"); -#undef VARIANT_FORMAT - goto done; - } - } - - stream->write_function(stream, "%s", FT_SYNTAX); - -done: - - ftdm_safe_free(mycmd); - - return FTDM_SUCCESS; - -} - -static FIO_IO_LOAD_FUNCTION(ftdm_r2_io_init) -{ - assert(fio != NULL); - memset(&g_ftdm_r2_interface, 0, sizeof(g_ftdm_r2_interface)); - - g_ftdm_r2_interface.name = "r2"; - g_ftdm_r2_interface.api = ftdm_r2_api; - - *fio = &g_ftdm_r2_interface; - - return FTDM_SUCCESS; -} - -static FIO_SIG_LOAD_FUNCTION(ftdm_r2_init) -{ - g_mod_data_hash = create_hashtable(10, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); - if (!g_mod_data_hash) { - return FTDM_FAIL; - } - return FTDM_SUCCESS; -} - -static FIO_SIG_UNLOAD_FUNCTION(ftdm_r2_destroy) -{ - ftdm_hash_iterator_t *i = NULL; - ftdm_r2_span_pvt_t *spanpvt = NULL; - const void *key = NULL; - void *val = NULL; - for (i = hashtable_first(g_mod_data_hash); i; i = hashtable_next(i)) { - hashtable_this(i, &key, NULL, &val); - if (key && val) { - spanpvt = val; - openr2_context_delete(spanpvt->r2context); - hashtable_destroy(spanpvt->r2calls); - ftdm_sched_destroy(&spanpvt->sched); - } - } - hashtable_destroy(g_mod_data_hash); - return FTDM_SUCCESS; -} - -EX_DECLARE_DATA ftdm_module_t ftdm_module = { - /* .name */ "r2", - /* .io_load */ ftdm_r2_io_init, - /* .io_unload */ NULL, - /* .sig_load */ ftdm_r2_init, - /* .sig_configure */ NULL, - /* .sig_unload */ ftdm_r2_destroy, - /* .configure_span_signaling */ ftdm_r2_configure_span_signaling -}; - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.c deleted file mode 100755 index 0b17885ba9..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2011 Sebastien Trottier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include -#include - -#include - -#include "ftmod_r2_io_mf_lib.h" - -/* Convert openr2 MF tone enum value to FreeTDM MF tone value - 1-15 bitwise OR FTDM_MF_DIRECTION_FORWARD/BACKWARD - 0 (stop playing) - openr2_mf_tone_t defined in r2proto.h -*/ -static int ftdm_r2_openr2_mf_tone_to_ftdm_mf_tone(openr2_mf_tone_t - openr2_tone_value, int forward_signals) -{ - int tone; - - switch (openr2_tone_value) { - case 0: return 0; -#define TONE_FROM_NAME(name) case OR2_MF_TONE_##name: tone = name; break; - TONE_FROM_NAME(1) - TONE_FROM_NAME(2) - TONE_FROM_NAME(3) - TONE_FROM_NAME(4) - TONE_FROM_NAME(5) - TONE_FROM_NAME(6) - TONE_FROM_NAME(7) - TONE_FROM_NAME(8) - TONE_FROM_NAME(9) - TONE_FROM_NAME(10) - TONE_FROM_NAME(11) - TONE_FROM_NAME(12) - TONE_FROM_NAME(13) - TONE_FROM_NAME(14) - TONE_FROM_NAME(15) -#undef TONE_FROM_NAME - default: - ftdm_assert(0, "Invalid openr2_tone_value\n"); - return -1; - } - - /* Add flag corresponding to direction */ - if (forward_signals) { - tone |= FTDM_MF_DIRECTION_FORWARD; - } else { - tone |= FTDM_MF_DIRECTION_BACKWARD; - } - - return tone; -} - -/* MF generation routines (using IO command of a FreeTDM channel) - write_init stores the direction of the MF to generate */ -static void *ftdm_r2_io_mf_write_init(ftdm_r2_mf_write_handle_t *handle, int forward_signals) -{ - ftdm_log_chan(handle->ftdmchan, FTDM_LOG_DEBUG, "ftdm_r2_io_mf_write_init, " - "forward = %d\n", forward_signals); - - handle->fwd = forward_signals; - return handle; -} - -static int ftdm_r2_io_mf_generate_tone(ftdm_r2_mf_write_handle_t *handle, int16_t buffer[], int samples) -{ - /* Our mf_want_generate implementation always return 0, so mf_generate_tone should never be called */ - ftdm_assert(0, "ftdm_r2_io_mf_generate_tone not implemented\n"); - return 0; -} - -/* \brief mf_select_tone starts tone generation or stops current tone - * \return 0 on success, -1 on error - */ -static int ftdm_r2_io_mf_select_tone(ftdm_r2_mf_write_handle_t *handle, char signal) -{ - int tone; /* (0, 1-15) (0 meaning to stop playing) */ - - ftdm_log_chan(handle->ftdmchan, FTDM_LOG_DEBUG, "ftdm_r2_io_mf_select_tone, " - "signal = %c\n", signal); - - if (-1 == (tone = ftdm_r2_openr2_mf_tone_to_ftdm_mf_tone(signal, handle->fwd))) { - return -1; - } - - /* Start/stop playback directly here, as select tone is called each time a tone - is started or stopped (called if tone changes, but silence is tone 0, - triggering a tone change) */ - if (tone > 0) { - ftdm_channel_command(handle->ftdmchan, FTDM_COMMAND_START_MF_PLAYBACK, &tone); - } else { - /* tone 0 means to stop current tone */ - ftdm_channel_command(handle->ftdmchan, FTDM_COMMAND_STOP_MF_PLAYBACK, NULL); - } - return 0; -} - -static int ftdm_r2_io_mf_want_generate(ftdm_r2_mf_write_handle_t *handle, int signal) -{ - /* Return 0, meaning mf_generate_tone doesn't need to be called */ - return 0; -} - -/* MF lib interface that generate MF tones via FreeTDM channel IO commands - MF detection using the default openr2 provider (r2engine) */ -static openr2_mflib_interface_t g_mf_ftdm_io_iface = { - /* .mf_read_init */ (openr2_mf_read_init_func)openr2_mf_rx_init, - /* .mf_write_init */ (openr2_mf_write_init_func)ftdm_r2_io_mf_write_init, - /* .mf_detect_tone */ (openr2_mf_detect_tone_func)openr2_mf_rx, - /* .mf_generate_tone */ (openr2_mf_generate_tone_func)ftdm_r2_io_mf_generate_tone, - /* .mf_select_tone */ (openr2_mf_select_tone_func)ftdm_r2_io_mf_select_tone, - /* .mf_want_generate */ (openr2_mf_want_generate_func)ftdm_r2_io_mf_want_generate, - /* .mf_read_dispose */ NULL, - /* .mf_write_dispose */ NULL -}; - -openr2_mflib_interface_t *ftdm_r2_get_native_channel_mf_generation_iface() -{ - return &g_mf_ftdm_io_iface; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet - */ diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.h b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.h deleted file mode 100755 index cf3c171c3d..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2011 Sebastien Trottier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef _FTMOD_R2_IO_MFLIB_H_ -#define _FTMOD_R2_IO_MFLIB_H_ - -#include - -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -/* MFC/R2 tone generator handle (mf_write_handle) */ -typedef struct { - /*! FTDM channel performing the MF generation */ - ftdm_channel_t *ftdmchan; - /*! 1 if generating forward tones, otherwise generating reverse tones. */ - int fwd; -} ftdm_r2_mf_write_handle_t; - -/* MF lib interface that generate MF tones via FreeTDM channel IO commands - MF detection using the default openr2 provider (r2engine) */ -openr2_mflib_interface_t *ftdm_r2_get_native_channel_mf_generation_iface(void); - -#if defined(__cplusplus) -} /* endif extern "C" */ -#endif - -#endif /* endif defined _FTMOD_R2_IO_MFLIB_H_ */ - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2008.vcproj deleted file mode 100644 index f6263907e1..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2008.vcproj +++ /dev/null @@ -1,249 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj.filters deleted file mode 100644 index 5f592fa9ef..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj.filters +++ /dev/null @@ -1,57 +0,0 @@ - - - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c deleted file mode 100644 index ed0a99dc95..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ /dev/null @@ -1,1563 +0,0 @@ - -/* - * Copyright (c) 2010, Sangoma Technologies - * David Yat Sin - * Moises Silva - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -#include "ftmod_sangoma_isdn.h" - -#ifdef FTDM_DEBUG_CHAN_MEMORY -#include -#endif - -static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj); -static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span); -static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span); -static ftdm_status_t ftdm_sangoma_isdn_dtmf(ftdm_channel_t *ftdmchan, const char* dtmf); - -ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event); -static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_event_t event); -static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan); -static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event); -static void ftdm_sangoma_isdn_wakeup_phy(ftdm_channel_t *dchan); -static void ftdm_sangoma_isdn_dchan_set_queue_size(ftdm_channel_t *ftdmchan); - -static ftdm_io_interface_t g_sngisdn_io_interface; -static sng_isdn_event_interface_t g_sngisdn_event_interface; - -ftdm_sngisdn_data_t g_sngisdn_data; - -SNGISDN_ENUM_NAMES(SNGISDN_TRANSFER_TYPE_NAMES, SNGISDN_TRANSFER_TYPE_STRINGS) -SNGISDN_STR2ENUM(ftdm_str2sngisdn_transfer_type, sngisdn_transfer_type2str, sngisdn_transfer_type_t, SNGISDN_TRANSFER_TYPE_NAMES, SNGISDN_TRANSFER_INVALID) - -ftdm_state_map_t sangoma_isdn_state_map = { - { - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_ANY, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_DIALING, - FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, - FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_GET_CALLERID, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_GET_CALLERID, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_IN_LOOP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_TRANSFER, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TRANSFER, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - }, - - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_TRANSFER, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_TERMINATING,FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_ANY, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_DIALING, - FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, - FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, - FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, - FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, - FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - } - } -}; - -static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_event_t event) -{ - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; - sngisdn_snd_event(signal_data, event); - - switch (event) { - /* Check if the span woke up from power-saving mode */ - case FTDM_OOB_ALARM_CLEAR: - if (FTDM_SPAN_IS_BRI(span)) { - ftdm_channel_t *ftdmchan; - sngisdn_chan_data_t *sngisdn_info; - ftdm_iterator_t *chaniter = NULL; - ftdm_iterator_t *curr = NULL; - - chaniter = ftdm_span_get_chan_iterator(span, NULL); - for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { - ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr); - sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data; - - if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)) { - ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING); - - ftdm_sched_timer(signal_data->sched, "delayed_setup", 1000, sngisdn_delayed_setup, (void*) ftdmchan->call_data, NULL); - } - } - ftdm_iterator_free(chaniter); - } - break; - default: - /* Ignore other events for now */ - break; - } -} - -static void ftdm_sangoma_isdn_dchan_set_queue_size(ftdm_channel_t *dchan) -{ - ftdm_status_t ret_status; - uint32_t queue_size; - - queue_size = SNGISDN_DCHAN_QUEUE_LEN; - ret_status = ftdm_channel_command(dchan, FTDM_COMMAND_SET_RX_QUEUE_SIZE, &queue_size); - ftdm_assert(ret_status == FTDM_SUCCESS, "Failed to set Rx Queue size"); - - queue_size = SNGISDN_DCHAN_QUEUE_LEN; - ret_status = ftdm_channel_command(dchan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &queue_size); - ftdm_assert(ret_status == FTDM_SUCCESS, "Failed to set Tx Queue size"); - - RETVOID; -} - -static void ftdm_sangoma_isdn_wakeup_phy(ftdm_channel_t *dchan) -{ - ftdm_status_t ret_status; - ftdm_channel_hw_link_status_t status = FTDM_HW_LINK_CONNECTED; - ret_status = ftdm_channel_command(dchan, FTDM_COMMAND_SET_LINK_STATUS, &status); - if (ret_status != FTDM_SUCCESS) { - ftdm_log_chan_msg(dchan, FTDM_LOG_WARNING, "Failed to wake-up link\n"); - } - return; -} - -static void *ftdm_sangoma_isdn_io_run(ftdm_thread_t *me, void *obj) -{ - uint8_t data[8192]; - unsigned i = 0; - ftdm_status_t status = FTDM_SUCCESS; - ftdm_span_t *span = (ftdm_span_t*) obj; - ftdm_size_t len = 0; - ftdm_channel_t *ftdmchan = NULL; - unsigned waitms = 10000; - ftdm_iterator_t *chaniter = NULL; - ftdm_iterator_t *citer = NULL; - ftdm_event_t *event; - short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count); - - /* Initialize the d-channel */ - chaniter = ftdm_span_get_chan_iterator(span, NULL); - if (!chaniter) { - ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name); - goto done; - } - - while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) { - len = 1000; - waitms = 1000; - memset(poll_events, 0, sizeof(short)*span->chan_count); - - for (i = 0, citer = ftdm_span_get_chan_iterator(span, chaniter); citer; citer = ftdm_iterator_next(citer), i++) { - ftdmchan = ftdm_iterator_current(citer); - - poll_events[i] |= FTDM_EVENTS; - if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) { - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED)) { - poll_events[i] |= FTDM_READ; - waitms = 20; - } - } else { - /* We always read the d-channel */ - poll_events[i] |= FTDM_READ; - } - } - - status = ftdm_span_poll_event(span, waitms, poll_events); - switch (status) { - case FTDM_FAIL: - ftdm_log(FTDM_LOG_CRIT, "Failed to poll span for IO\n"); - break; - case FTDM_TIMEOUT: - break; - case FTDM_SUCCESS: - /* Check if there are any channels that have data available */ - for (citer = ftdm_span_get_chan_iterator(span, chaniter); citer; citer = ftdm_iterator_next(citer)) { - len = sizeof(data); - ftdmchan = ftdm_iterator_current(citer); - if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) { - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED)) { - if (ftdm_test_io_flag(ftdmchan, FTDM_CHANNEL_IO_READ)) { - status = ftdm_raw_read(ftdmchan, data, &len); - if (status != FTDM_SUCCESS) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "raw I/O read failed\n"); - continue; - } - - status = ftdm_channel_process_media(ftdmchan, data, &len); - if (status != FTDM_SUCCESS) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to process media\n"); - continue; - } - } - } - } else { - if (ftdm_test_io_flag(ftdmchan, FTDM_CHANNEL_IO_READ)) { - status = ftdm_channel_read(ftdmchan, data, &len); - if (status == FTDM_SUCCESS) { - sngisdn_snd_data(ftdmchan, data, len); - } - } - } - } - - /* Check if there are any channels that have events available */ - while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) { - ftdm_sangoma_isdn_process_phy_events(span, event->enum_id); - } - - break; - default: - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Unhandled IO event\n"); - } - } -done: - ftdm_iterator_free(chaniter); - ftdm_safe_free(poll_events); - return NULL; -} - -static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj) -{ - ftdm_interrupt_t *ftdm_sangoma_isdn_int[3]; - ftdm_status_t ret_status; - ftdm_span_t *span = (ftdm_span_t *) obj; - ftdm_channel_t *ftdmchan = NULL; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - sngisdn_event_data_t *sngisdn_event = NULL; - int32_t sleep = SNGISDN_EVENT_POLL_RATE; - - ftdm_log(FTDM_LOG_INFO, "ftmod_sangoma_isdn monitor thread for span=%u started.\n", span->span_id); - - /* set IN_THREAD flag so that we know this thread is running */ - ftdm_set_flag(span, FTDM_SPAN_IN_THREAD); - - /* get an interrupt queue for this span */ - if (ftdm_queue_get_interrupt(span->pendingchans, &ftdm_sangoma_isdn_int[0]) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Failed to get a ftdm_interrupt for span = %s!\n", span->name); - goto ftdm_sangoma_isdn_run_exit; - } - - if (ftdm_queue_get_interrupt(span->pendingsignals, &ftdm_sangoma_isdn_int[1]) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Failed to get a signal interrupt for span = %s!\n", span->name); - goto ftdm_sangoma_isdn_run_exit; - } - - if (ftdm_queue_get_interrupt(signal_data->event_queue, &ftdm_sangoma_isdn_int[2]) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Failed to get a event interrupt for span = %s!\n", span->name); - goto ftdm_sangoma_isdn_run_exit; - } - - while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) { - /* Check if there are any timers to process */ - ftdm_sched_run(signal_data->sched); - ftdm_span_trigger_signals(span); - - if (ftdm_sched_get_time_to_next_timer(signal_data->sched, &sleep) == FTDM_SUCCESS) { - if (sleep < 0 || sleep > SNGISDN_EVENT_POLL_RATE) { - sleep = SNGISDN_EVENT_POLL_RATE; - } - } - ret_status = ftdm_interrupt_multiple_wait(ftdm_sangoma_isdn_int, 3, sleep); - /* find out why we returned from the interrupt queue */ - switch (ret_status) { - case FTDM_SUCCESS: /* there was a state change on the span */ - /* process all pending state changes */ - while ((ftdmchan = ftdm_queue_dequeue(span->pendingchans))) { - /* double check that this channel has a state change pending */ - ftdm_channel_lock(ftdmchan); - ftdm_channel_advance_states(ftdmchan); - ftdm_channel_unlock(ftdmchan); - } - - while ((sngisdn_event = ftdm_queue_dequeue(signal_data->event_queue))) { - ftdm_sangoma_isdn_process_stack_event(span, sngisdn_event); - ftdm_safe_free(sngisdn_event); - } - break; - case FTDM_TIMEOUT: - /* twiddle */ - break; - case FTDM_FAIL: - ftdm_log(FTDM_LOG_ERROR, "%s: ftdm_interrupt_wait returned error!\n", span->name); - break; - - default: - ftdm_log(FTDM_LOG_ERROR, "%s: ftdm_interrupt_wait returned with unknown code\n", span->name); - break; - } - } - - /* clear the IN_THREAD flag so that we know the thread is done */ - ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD); - - ftdm_log(FTDM_LOG_INFO, "ftmod_sangoma_isdn monitor thread for span %s stopping.\n", span->name); - - return NULL; - -ftdm_sangoma_isdn_run_exit: - - /* clear the IN_THREAD flag so that we know the thread is done */ - ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD); - - ftdm_log(FTDM_LOG_INFO, "ftmod_sangoma_isdn monitor thread for span %s stopping due to error.\n", span->name); - - return NULL; -} - - -/** - * \brief Checks if span has state changes pending and processes - * \param span Span where event was fired - * \param sngisdn_event Event to handle - * \return The locked FTDM channel associated to the event if any, NULL otherwise - */ - -ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event) -{ - ftdm_channel_t *ftdmchan = NULL; - switch (sngisdn_event->event_id) { - /* Events that do not have a channel associated to them */ - case SNGISDN_EVENT_SRV_IND: - case SNGISDN_EVENT_SRV_CFM: - case SNGISDN_EVENT_RST_CFM: - case SNGISDN_EVENT_RST_IND: - return NULL; - break; - case SNGISDN_EVENT_CON_IND: - case SNGISDN_EVENT_CON_CFM: - case SNGISDN_EVENT_CNST_IND: - case SNGISDN_EVENT_DISC_IND: - case SNGISDN_EVENT_REL_IND: - case SNGISDN_EVENT_DAT_IND: - case SNGISDN_EVENT_SSHL_IND: - case SNGISDN_EVENT_SSHL_CFM: - case SNGISDN_EVENT_RMRT_IND: - case SNGISDN_EVENT_RMRT_CFM: - case SNGISDN_EVENT_FLC_IND: - case SNGISDN_EVENT_FAC_IND: - case SNGISDN_EVENT_STA_CFM: - ftdmchan = sngisdn_event->sngisdn_info->ftdmchan; - ftdm_assert_return(ftdmchan, NULL,"Event should have a channel associated\n"); - break; - } - ftdm_channel_lock(ftdmchan); - ftdm_channel_advance_states(ftdmchan); - return ftdmchan; -} - - - -static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event) -{ - ftdm_channel_t *ftdmchan = NULL; - - ftdmchan = ftdm_sangoma_isdn_process_event_states(span, sngisdn_event); - switch(sngisdn_event->event_id) { - case SNGISDN_EVENT_CON_IND: - sngisdn_process_con_ind(sngisdn_event); - break; - case SNGISDN_EVENT_CON_CFM: - sngisdn_process_con_cfm(sngisdn_event); - break; - case SNGISDN_EVENT_CNST_IND: - sngisdn_process_cnst_ind(sngisdn_event); - break; - case SNGISDN_EVENT_DISC_IND: - sngisdn_process_disc_ind(sngisdn_event); - break; - case SNGISDN_EVENT_REL_IND: - sngisdn_process_rel_ind(sngisdn_event); - break; - case SNGISDN_EVENT_DAT_IND: - sngisdn_process_dat_ind(sngisdn_event); - break; - case SNGISDN_EVENT_SSHL_IND: - sngisdn_process_sshl_ind(sngisdn_event); - break; - case SNGISDN_EVENT_SSHL_CFM: - sngisdn_process_sshl_cfm(sngisdn_event); - break; - case SNGISDN_EVENT_RMRT_IND: - sngisdn_process_rmrt_ind(sngisdn_event); - break; - case SNGISDN_EVENT_RMRT_CFM: - sngisdn_process_rmrt_cfm(sngisdn_event); - break; - case SNGISDN_EVENT_FLC_IND: - sngisdn_process_flc_ind(sngisdn_event); - break; - case SNGISDN_EVENT_FAC_IND: - sngisdn_process_fac_ind(sngisdn_event); - break; - case SNGISDN_EVENT_STA_CFM: - sngisdn_process_sta_cfm(sngisdn_event); - break; - case SNGISDN_EVENT_SRV_IND: - sngisdn_process_srv_ind(sngisdn_event); - break; - case SNGISDN_EVENT_SRV_CFM: - sngisdn_process_srv_cfm(sngisdn_event); - break; - case SNGISDN_EVENT_RST_CFM: - sngisdn_process_rst_cfm(sngisdn_event); - break; - case SNGISDN_EVENT_RST_IND: - sngisdn_process_rst_ind(sngisdn_event); - break; - } - if (ftdmchan != NULL) { - ftdm_channel_advance_states(ftdmchan); - ftdm_channel_unlock(ftdmchan); - } -} - -/* this function is called with the channel already locked by the core */ -static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) -{ - ftdm_sigmsg_t sigev; - ftdm_channel_state_t initial_state; - sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; - uint8_t state_change = 0; - - memset(&sigev, 0, sizeof(sigev)); - - sigev.chan_id = ftdmchan->chan_id; - sigev.span_id = ftdmchan->span_id; - sigev.channel = ftdmchan; - -#ifdef FTDM_DEBUG_CHAN_MEMORY - if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) { - ftdm_assert(mprotect(ftdmchan, sizeof(*ftdmchan), PROT_READ) == 0, "Failed to mprotect"); - } -#endif - - /* Only needed for debugging */ - initial_state = ftdmchan->state; - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "processing state change to %s\n", ftdm_channel_state2str(ftdmchan->state)); - - switch (ftdmchan->state) { - case FTDM_CHANNEL_STATE_COLLECT: /* SETUP received but waiting on digits */ - { - /* TODO: Re-implement this. There is a way to re-evaluate new incoming digits from dialplan as they come */ - sngisdn_snd_setup_ack(ftdmchan); - /* Just wait in this state until we get enough digits or T302 timeout */ - } - break; - case FTDM_CHANNEL_STATE_GET_CALLERID: - { - /* By default, we do not send a progress indicator in the proceed */ - ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID}; - sngisdn_snd_proceed(ftdmchan, prog_ind); - - /* Wait in this state until we get FACILITY msg */ - } - break; - case FTDM_CHANNEL_STATE_RING: /* incoming call request */ - { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending incoming call from %s to %s to FTDM core\n", ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.dnis.digits); - - /* we have enough information to inform FTDM of the call*/ - sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_START); - } - break; - case FTDM_CHANNEL_STATE_DIALING: /* outgoing call request */ - { - if (FTDM_SPAN_IS_BRI(ftdmchan->span) && ftdm_test_flag(ftdmchan->span, FTDM_SPAN_PWR_SAVING)) { - ftdm_signaling_status_t sigstatus; - ftdm_span_get_sig_status(ftdmchan->span, &sigstatus); - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) { - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)ftdmchan->span->signal_data; - - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Requesting Physical Line activation\n"); - sngisdn_set_flag(sngisdn_info, FLAG_ACTIVATING); - ftdm_sangoma_isdn_wakeup_phy(ftdmchan); - ftdm_sched_timer(signal_data->sched, "timer_t3", signal_data->timer_t3*1000, sngisdn_t3_timeout, (void*) sngisdn_info, NULL); - } else if (sigstatus == FTDM_SIG_STATE_DOWN) { - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)ftdmchan->span->signal_data; - - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Requesting Q.921 Line activation\n"); - sngisdn_set_flag(sngisdn_info, FLAG_ACTIVATING); - sngisdn_snd_dl_req(ftdmchan); - ftdm_sched_timer(signal_data->sched, "timer_t3", signal_data->timer_t3*1000, sngisdn_t3_timeout, (void*) sngisdn_info, NULL); - } else { - sngisdn_snd_setup(ftdmchan); - } - } else { - sngisdn_snd_setup(ftdmchan); - } - } - break; - case FTDM_CHANNEL_STATE_PROCEED: - { - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - /*OUTBOUND...so we were told by the line of this so noifiy the user*/ - sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_PROCEED); - - if (sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY)) { - state_change++; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); - } - } else { - ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID}; - sngisdn_snd_proceed(ftdmchan, prog_ind); - } - } - break; - case FTDM_CHANNEL_STATE_RINGING: - { - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - /* OUTBOUND...so we were told by the line of this so notify the user */ - sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_RINGING); - - if (sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY)) { - state_change++; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); - } - } else { - ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN}; - sngisdn_snd_alert(ftdmchan, prog_ind); - } - } - break; - case FTDM_CHANNEL_STATE_PROGRESS: - { - /*check if the channel is inbound or outbound*/ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - /*OUTBOUND...so we were told by the line of this so noifiy the user*/ - - sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_PROGRESS); - } else { - /* Send a progress message, indicating: Call is not end-to-end ISDN, further call progress may be available */ - ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN}; - sngisdn_snd_progress(ftdmchan, prog_ind); - } - } - break; - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - { - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_PROGRESS_MEDIA); - } else { - /* Send a progress message, indicating: In-band information/pattern available */ - ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_IB_AVAIL}; - sngisdn_snd_progress(ftdmchan, prog_ind); - } - } - break; - case FTDM_CHANNEL_STATE_UP: /* call is answered */ - { - /* check if the channel is inbound or outbound */ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - /* OUTBOUND ... so we were told by the line that the other side answered */ - - sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_UP); - - if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP && - ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->signalling == SNGISDN_SIGNALING_NET) { - /* Assign the call to a specific equipment */ - sngisdn_snd_con_complete(ftdmchan); - } - } else { - /* INBOUND ... so FS told us it just answered ... tell the stack */ - sngisdn_snd_connect(ftdmchan); - } - } - break; - case FTDM_CHANNEL_STATE_CANCEL: - { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Hanging up call before informing user!\n"); - - /* Send a release complete */ - sngisdn_snd_release(ftdmchan, 0); - /*now go to the HANGUP complete state*/ - state_change++; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); - } - break; - case FTDM_CHANNEL_STATE_TERMINATING: /* call is hung up by the remote end */ - { - /* this state is set when the line is hanging up */ - sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_STOP); - } - break; - case FTDM_CHANNEL_STATE_HANGUP: /* call is hung up locally */ - { - if (sngisdn_test_flag(sngisdn_info, FLAG_REMOTE_ABORT)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Acknowledging remote abort\n"); - } else if (sngisdn_test_flag(sngisdn_info, FLAG_REMOTE_REL)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Acknowledging remote hangup\n"); - sngisdn_snd_release(ftdmchan, 0); - } else if (sngisdn_test_flag(sngisdn_info, FLAG_LOCAL_ABORT)) { - /* We aborted this call before sending anything to the stack, so nothing to do anymore */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Clearing local states from local abort\n"); - } else if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE)) { - /* We are hangup local call because there was a glare, we are waiting for a - RELEASE on this call, before we can process the saved call */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Waiting for RELEASE on hungup glared call\n"); - } else if (sngisdn_test_flag(sngisdn_info, FLAG_SEND_DISC)) { - /* Remote side sent a PROGRESS message, but cause indicates disconnect or T310 expired*/ - sngisdn_snd_disconnect(ftdmchan); - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Hanging up call upon local request!\n"); - - /* set the flag to indicate this hangup is started from the local side */ - sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_REL); - - switch(ftdmchan->last_state) { - case FTDM_CHANNEL_STATE_RING: - /* If we never sent PROCEED/ALERT/PROGRESS/CONNECT on an incoming call, we need to send release instead of disconnect */ - sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); - sngisdn_snd_release(ftdmchan, 0); - break; - case FTDM_CHANNEL_STATE_DIALING: - /* If we never received a PROCEED/ALERT/PROGRESS/CONNECT on an outgoing call, we need to send release instead of disconnect */ - sngisdn_snd_release(ftdmchan, 0); - break; - case FTDM_CHANNEL_STATE_PROCEED: - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - if (((sngisdn_span_data_t*)(ftdmchan->span->signal_data))->switchtype == SNGISDN_SWITCH_4ESS || - ((sngisdn_span_data_t*)(ftdmchan->span->signal_data))->switchtype == SNGISDN_SWITCH_5ESS) { - - /* When using 5ESS, if the user wants to clear an inbound call, the correct procedure is to send a PROGRESS with in-band info available, and play tones. Then send a DISCONNECT. If we reached this point, it means user did not try to play-tones, so send a RELEASE because remote side does not expect DISCONNECT in state 3 */ - sngisdn_snd_release(ftdmchan, 0); - break; - } - } - /* fall-through */ - default: - sngisdn_snd_disconnect(ftdmchan); - break; - } - } - /* now go to the HANGUP complete state */ - state_change++; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); - } - break; - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - { - if (sngisdn_test_flag(sngisdn_info, FLAG_REMOTE_ABORT) || - sngisdn_test_flag(sngisdn_info, FLAG_LOCAL_ABORT)) { - /* If the remote side aborted, we will not get anymore message for this call */ - state_change++; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } else { - /* waiting on remote confirmation before moving to down */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Waiting for release from stack\n"); - } - } - break; - case FTDM_CHANNEL_STATE_DOWN: /* the call is finished and removed */ - { - uint8_t glare = sngisdn_test_flag(sngisdn_info, FLAG_GLARE); - /* clear all of the call specific data store in the channel structure */ - clear_call_data(sngisdn_info); - - /* Close the channel even if we had a glare, we will re-open it when processing state COLLECT for the - "glared call" */ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { - ftdm_channel_t *close_chan = ftdmchan; - /* close the channel */ - ftdm_channel_close(&close_chan); - } - if (glare) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Glare detected, processing saved call\n"); - /* We are calling sngisdn_rcv_con_ind with ftdmchan->mutex being locked, - so no other threads will be able to touch this channel. The next time we will - process this channel is in this function, and it should be in state COLLECT (set inside - sngisdn_rcv_con_ind)*/ - sngisdn_rcv_con_ind(sngisdn_info->glare.suId, sngisdn_info->glare.suInstId, sngisdn_info->glare.spInstId, &sngisdn_info->glare.setup, sngisdn_info->glare.dChan, sngisdn_info->glare.ces); - } - } - break; - case FTDM_CHANNEL_STATE_TRANSFER: - { - /* sngisdn_transfer function will always result in a state change */ - sngisdn_transfer(ftdmchan); - state_change++; - } - break; - case FTDM_CHANNEL_STATE_RESTART: - { - /* IMPLEMENT ME */ - } - break; - case FTDM_CHANNEL_STATE_SUSPENDED: - { - /* IMPLEMENT ME */ - } - break; - case FTDM_CHANNEL_STATE_RESET: - { - sngisdn_snd_restart(ftdmchan); - } - break; - default: - { - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "unsupported sngisdn_rcvd state %s\n", ftdm_channel_state2str(ftdmchan->state)); - } - break; - } - - if (!state_change) { - /* Acknowledge the state change */ - ftdm_channel_complete_state(ftdmchan); - } - - /* If sngisdn_info->variables is not NULL, it means did not send any - * sigevent to the user, therefore we have to free that hashtable */ - if (sngisdn_info->variables) { - hashtable_destroy(sngisdn_info->variables); - sngisdn_info->variables = NULL; - } - - /* If sngisdn_info->raw_data is not NULL, it means did not send any - * sigevent to the user, therefore we have to free that raw data */ - if (sngisdn_info->raw_data) { - ftdm_safe_free(sngisdn_info->raw_data); - sngisdn_info->raw_data = NULL; - sngisdn_info->raw_data_len = 0; - } - - if (ftdmchan->state == initial_state) { - ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "state change flag is still set, but we did not change state\n"); - } -#ifdef FTDM_DEBUG_CHAN_MEMORY - if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) { - ftdm_assert(mprotect(ftdmchan, sizeof(*ftdmchan), PROT_READ|PROT_WRITE) == 0, "Failed to mprotect"); - } -#endif - return FTDM_SUCCESS; -} - -static FIO_CHANNEL_INDICATE_FUNCTION(ftdm_sangoma_isdn_indicate) -{ - ftdm_status_t status = FTDM_FAIL; - - switch (indication) { - case FTDM_CHANNEL_INDICATE_FACILITY: - sngisdn_snd_fac_req(ftdmchan); - status = FTDM_SUCCESS; - break; - default: - status = FTDM_NOTIMPL; - } - return status; -} - -static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_isdn_outgoing_call) -{ - sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; - ftdm_status_t status = FTDM_FAIL; - - if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) { - if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE)) { - /* A call came in after we called ftdm_channel_open_chan for this call, but before we got here */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Glare detected - aborting outgoing call\n"); - - sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); - - status = FTDM_BREAK; - } else { - status = FTDM_SUCCESS; - } - } else { - /* the channel is already used...this can't be, end the request */ - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Outgoing call requested channel in already in use (%s)\n", ftdm_channel_state2str(ftdmchan->state)); - status = FTDM_BREAK; - } - - return status; -} -static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_get_chan_sig_status) -{ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) { - *status = FTDM_SIG_STATE_UP; - } else { - *status = FTDM_SIG_STATE_DOWN; - } - - return FTDM_SUCCESS; -} - -static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_set_chan_sig_status) -{ - ftdm_log(FTDM_LOG_ERROR,"Cannot set channel status in this module\n"); - return FTDM_NOTIMPL; -} - -static FIO_SPAN_GET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_get_span_sig_status) -{ - if (ftdm_test_flag(span->channels[1], FTDM_CHANNEL_SIG_UP)) { - *status = FTDM_SIG_STATE_UP; - } else { - *status = FTDM_SIG_STATE_DOWN; - } - - return FTDM_SUCCESS; -} - -static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_set_span_sig_status) -{ - ftdm_log(FTDM_LOG_ERROR,"Cannot set span status in this module\n"); - return FTDM_NOTIMPL; -} - -static ftdm_status_t ftdm_sangoma_isdn_dtmf(ftdm_channel_t *ftdmchan, const char* dtmf) -{ - sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; - switch(sngisdn_info->transfer_data.type) { - case SNGISDN_TRANSFER_ATT_COURTESY_VRU: - case SNGISDN_TRANSFER_ATT_COURTESY_VRU_DATA: - return sngisdn_att_transfer_process_dtmf(ftdmchan, dtmf); - default: - /* We do not care about DTMF events, do nothing */ - break; - } - - return FTDM_SUCCESS; -} - -static ftdm_status_t ftdm_sangoma_isdn_perform_start(ftdm_span_t *span) -{ - sngisdn_span_data_t *signal_data = span->signal_data; - - ftdm_log(FTDM_LOG_DEBUG, "Actually starting span:%s\n", span->name); - /* clear the monitor thread stop flag */ - ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD); - ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD); - - if (signal_data->trace_q921 == SNGISDN_OPT_TRUE || - signal_data->raw_trace_q921 == SNGISDN_OPT_TRUE) { - - sngisdn_activate_trace(span, SNGISDN_TRACE_Q921); - } - - if (signal_data->trace_q931 == SNGISDN_OPT_TRUE || - signal_data->raw_trace_q931 == SNGISDN_OPT_TRUE) { - - sngisdn_activate_trace(span, SNGISDN_TRACE_Q931); - } - - /*start the span monitor thread*/ - if (ftdm_thread_create_detached(ftdm_sangoma_isdn_run, span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT,"Failed to start Sangoma ISDN Span Monitor Thread!\n"); - return FTDM_FAIL; - } - - /*start the dchan monitor thread*/ - if (ftdm_thread_create_detached(ftdm_sangoma_isdn_io_run, span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT,"Failed to start Sangoma ISDN d-channel Monitor Thread!\n"); - return FTDM_FAIL; - } - - if (signal_data->restart_timeout) { - ftdm_log(FTDM_LOG_DEBUG, "%s:Scheduling Restart timeout\n", signal_data->ftdm_span->name); - ftdm_sched_timer(signal_data->sched, "restart_timeout", signal_data->restart_timeout, - sngisdn_restart_timeout, (void*) signal_data, &signal_data->timers[SNGISDN_SPAN_TIMER_RESTART]); - } - - ftdm_log(FTDM_LOG_DEBUG,"Finished starting span %s\n", span->name); - return FTDM_SUCCESS; -} - - -static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span) -{ - sngisdn_span_data_t *signal_data = span->signal_data; - - ftdm_log(FTDM_LOG_INFO,"Starting span %s:%u.\n",span->name,span->span_id); - - if (signal_data->dchan) { - ftdm_channel_set_feature(signal_data->dchan, FTDM_CHANNEL_FEATURE_IO_STATS); - ftdm_channel_open_chan(signal_data->dchan); - ftdm_sangoma_isdn_dchan_set_queue_size(signal_data->dchan); - } - - if (signal_data->nfas.trunk) { - if (signal_data->nfas.trunk->num_spans == signal_data->nfas.trunk->num_spans_configured) { - int i; - ftdm_log(FTDM_LOG_DEBUG, "Starting span for all spans within trunkgroup:%s\n", signal_data->nfas.trunk->name); - - sngisdn_stack_start(signal_data->nfas.trunk->dchan->ftdm_span); - ftdm_sangoma_isdn_perform_start(signal_data->nfas.trunk->dchan->ftdm_span); - - if (signal_data->nfas.trunk->backup) { - sngisdn_stack_start(signal_data->nfas.trunk->backup->ftdm_span); - ftdm_sangoma_isdn_perform_start(signal_data->nfas.trunk->backup->ftdm_span); - } - - for (i = 0; i < signal_data->nfas.trunk->num_spans; i++) { - if (signal_data->nfas.trunk->spans[i] && - signal_data->nfas.trunk->spans[i]->nfas.sigchan == SNGISDN_NFAS_DCHAN_NONE) { - sngisdn_stack_start(signal_data->nfas.trunk->spans[i]->ftdm_span); - ftdm_sangoma_isdn_perform_start(signal_data->nfas.trunk->spans[i]->ftdm_span); - } - } - - return FTDM_SUCCESS; - } else { - ftdm_log(FTDM_LOG_DEBUG, "Delaying span start until all spans within trunkgroup are started: %s\n", signal_data->nfas.trunk->name); - return FTDM_SUCCESS; - } - } - - if (sngisdn_stack_start(span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Failed to start span %s\n", span->name); - return FTDM_FAIL; - } - - ftdm_sangoma_isdn_perform_start(span); - - return FTDM_SUCCESS; -} - -static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span) -{ - ftdm_iterator_t *chaniter = NULL; - ftdm_iterator_t *curr = NULL; - unsigned i; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; - ftdm_log(FTDM_LOG_INFO, "Stopping span %s\n", span->name); - - /* throw the STOP_THREAD flag to signal monitor thread stop */ - ftdm_set_flag(span, FTDM_SPAN_STOP_THREAD); - - /* wait for the thread to stop */ - while (ftdm_test_flag(span, FTDM_SPAN_IN_THREAD)) { - ftdm_log(FTDM_LOG_DEBUG, "Waiting for monitor thread to end for span %s\n", span->name); - ftdm_sleep(10); - } - - if (sngisdn_stack_stop(span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Failed to stop span %s\n", span->name); - } - - chaniter = ftdm_span_get_chan_iterator(span, NULL); - for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { - ftdm_safe_free(((ftdm_channel_t*)ftdm_iterator_current(curr))->call_data); - ((ftdm_channel_t*)ftdm_iterator_current(curr))->call_data = NULL; - } - ftdm_iterator_free(chaniter); - - ftdm_sched_destroy(&signal_data->sched); - ftdm_queue_destroy(&signal_data->event_queue); - for (i = 0 ; i < signal_data->num_local_numbers ; i++) { - if (signal_data->local_numbers[i] != NULL) { - ftdm_safe_free(signal_data->local_numbers[i]); - } - } - ftdm_safe_free(span->signal_data); - - ftdm_log(FTDM_LOG_DEBUG, "Finished stopping span %s\n", span->name); - - return FTDM_SUCCESS; -} - -static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config) -{ - ftdm_iterator_t *chaniter = NULL; - ftdm_iterator_t *curr = NULL; - - sngisdn_span_data_t *signal_data; - - ftdm_log(FTDM_LOG_INFO, "Configuring ftmod_sangoma_isdn span = %s\n", span->name); - - signal_data = ftdm_calloc(1, sizeof(sngisdn_span_data_t)); - signal_data->ftdm_span = span; - span->signal_data = signal_data; - - chaniter = ftdm_span_get_chan_iterator(span, NULL); - for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { - sngisdn_chan_data_t *chan_data = ftdm_calloc(1, sizeof(sngisdn_chan_data_t)); - chan_data->ftdmchan = ((ftdm_channel_t*)ftdm_iterator_current(curr)); - ((ftdm_channel_t*)ftdm_iterator_current(curr))->call_data = chan_data; - - } - ftdm_iterator_free(chaniter); - - if (ftmod_isdn_parse_cfg(ftdm_parameters, span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Failed to parse configuration\n"); - return FTDM_FAIL; - } - - if (signal_data->nfas.trunk) { - if (signal_data->nfas.trunk->num_spans == ++signal_data->nfas.trunk->num_spans_configured) { - int i; - ftdm_log(FTDM_LOG_DEBUG, "Starting stack configuration for all spans within trunkgroup:%s\n", signal_data->nfas.trunk->name); - - sngisdn_stack_cfg(signal_data->nfas.trunk->dchan->ftdm_span); - if (signal_data->nfas.trunk->backup) { - sngisdn_stack_cfg(signal_data->nfas.trunk->backup->ftdm_span); - } - - for (i = 0; i < signal_data->nfas.trunk->num_spans; i++) { - if (signal_data->nfas.trunk->spans[i] && - signal_data->nfas.trunk->spans[i]->nfas.sigchan == SNGISDN_NFAS_DCHAN_NONE) { - sngisdn_stack_cfg(signal_data->nfas.trunk->spans[i]->ftdm_span); - } - } - } else { - ftdm_log(FTDM_LOG_DEBUG, "Delaying span stack configuration until all spans within trunkgroup are started:%s\n", signal_data->nfas.trunk->name); - } - } else if (sngisdn_stack_cfg(span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Sangoma ISDN Stack configuration failed\n"); - return FTDM_FAIL; - } - - if (signal_data->cid_name_method == SNGISDN_CID_NAME_AUTO) { - switch (signal_data->switchtype) { - case SNGISDN_SWITCH_EUROISDN: - if (FTDM_SPAN_IS_BRI(span)) { - signal_data->cid_name_method = SNGISDN_CID_NAME_USR_USR_IE; - } else { - signal_data->cid_name_method = SNGISDN_CID_NAME_DISPLAY_IE; - } - break; - case SNGISDN_SWITCH_DMS100: - signal_data->cid_name_method = SNGISDN_CID_NAME_DISPLAY_IE; - break; - case SNGISDN_SWITCH_NI2: - case SNGISDN_SWITCH_5ESS: - case SNGISDN_SWITCH_4ESS: - signal_data->cid_name_method = SNGISDN_CID_NAME_FACILITY_IE; - break; - default: - break; - } - } - - if (signal_data->send_cid_name == SNGISDN_OPT_DEFAULT) { - switch (signal_data->switchtype) { - case SNGISDN_SWITCH_EUROISDN: -#ifdef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY - case SNGISDN_SWITCH_NI2: - case SNGISDN_SWITCH_5ESS: - case SNGISDN_SWITCH_4ESS: -#endif - if (signal_data->signalling == SNGISDN_SIGNALING_NET) { - signal_data->send_cid_name = SNGISDN_OPT_TRUE; - } else { - signal_data->send_cid_name = SNGISDN_OPT_FALSE; - } - break; - case SNGISDN_SWITCH_DMS100: - signal_data->send_cid_name = SNGISDN_OPT_TRUE; - break; -#ifndef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY - case SNGISDN_SWITCH_NI2: - case SNGISDN_SWITCH_5ESS: - case SNGISDN_SWITCH_4ESS: - signal_data->send_cid_name = SNGISDN_OPT_FALSE; - break; -#endif - default: - signal_data->send_cid_name = SNGISDN_OPT_FALSE; - break; - } - } else if (signal_data->send_cid_name == SNGISDN_OPT_TRUE) { - switch (signal_data->switchtype) { - case SNGISDN_SWITCH_NI2: - case SNGISDN_SWITCH_5ESS: - case SNGISDN_SWITCH_4ESS: -#ifndef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY - ftdm_log(FTDM_LOG_WARNING, "Sending Calling Name in Facility IE not supported, please update your libsng_isdn library\n"); - signal_data->send_cid_name = SNGISDN_OPT_FALSE; -#endif - break; - case SNGISDN_SWITCH_INSNET: /* Don't know how to transmit caller ID name on INSNET */ - case SNGISDN_SWITCH_QSIG: /* It seems like QSIG does not support Caller ID */ - signal_data->send_cid_name = SNGISDN_OPT_FALSE; - break; - case SNGISDN_SWITCH_EUROISDN: - break; - default: - signal_data->send_cid_name = SNGISDN_OPT_FALSE; - break; - } - } - - span->start = ftdm_sangoma_isdn_start; - span->stop = ftdm_sangoma_isdn_stop; - span->signal_type = FTDM_SIGTYPE_ISDN; - span->outgoing_call = ftdm_sangoma_isdn_outgoing_call; - span->indicate = ftdm_sangoma_isdn_indicate; - span->channel_request = NULL; - span->signal_cb = sig_cb; - span->sig_queue_dtmf = ftdm_sangoma_isdn_dtmf; - span->get_channel_sig_status = ftdm_sangoma_isdn_get_chan_sig_status; - span->set_channel_sig_status = ftdm_sangoma_isdn_set_chan_sig_status; - span->get_span_sig_status = ftdm_sangoma_isdn_get_span_sig_status; - span->set_span_sig_status = ftdm_sangoma_isdn_set_span_sig_status; - span->state_map = &sangoma_isdn_state_map; - span->state_processor = ftdm_sangoma_isdn_process_state_change; - ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE); - ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE); - ftdm_set_flag(span, FTDM_SPAN_USE_PROCEED_STATE); - ftdm_set_flag(span, FTDM_SPAN_USE_SKIP_STATES); - ftdm_set_flag(span, FTDM_SPAN_NON_STOPPABLE); - ftdm_set_flag(span, FTDM_SPAN_USE_TRANSFER); - - if (FTDM_SPAN_IS_BRI(span)) { - sngisdn_set_span_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING); - } - - /* Initialize scheduling context */ - ftdm_assert(ftdm_sched_create(&((sngisdn_span_data_t*)span->signal_data)->sched, "sngisdn_schedule") == FTDM_SUCCESS, "Failed to create a new schedule!!"); - - /* Initialize the event queue */ - ftdm_assert(ftdm_queue_create(&((sngisdn_span_data_t*)span->signal_data)->event_queue, SNGISDN_EVENT_QUEUE_SIZE) == FTDM_SUCCESS, "Failed to create a new queue!!"); - - ftdm_log(FTDM_LOG_INFO, "Finished configuring ftmod_sangoma_isdn span = %s\n", span->name); - return FTDM_SUCCESS; -} - -static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init) -{ - unsigned i; - ftdm_log(FTDM_LOG_INFO, "Loading ftmod_sangoma_isdn...\n"); - - memset(&g_sngisdn_data, 0, sizeof(g_sngisdn_data)); - memset(&g_sngisdn_event_interface, 0, sizeof(g_sngisdn_event_interface)); - /* set callbacks */ - g_sngisdn_event_interface.cc.sng_con_ind = sngisdn_rcv_con_ind; - g_sngisdn_event_interface.cc.sng_con_cfm = sngisdn_rcv_con_cfm; - g_sngisdn_event_interface.cc.sng_cnst_ind = sngisdn_rcv_cnst_ind; - g_sngisdn_event_interface.cc.sng_disc_ind = sngisdn_rcv_disc_ind; - g_sngisdn_event_interface.cc.sng_rel_ind = sngisdn_rcv_rel_ind; - g_sngisdn_event_interface.cc.sng_dat_ind = sngisdn_rcv_dat_ind; - g_sngisdn_event_interface.cc.sng_sshl_ind = sngisdn_rcv_sshl_ind; - g_sngisdn_event_interface.cc.sng_sshl_cfm = sngisdn_rcv_sshl_cfm; - g_sngisdn_event_interface.cc.sng_rmrt_ind = sngisdn_rcv_rmrt_ind; - g_sngisdn_event_interface.cc.sng_rmrt_cfm = sngisdn_rcv_rmrt_cfm; - g_sngisdn_event_interface.cc.sng_flc_ind = sngisdn_rcv_flc_ind; - g_sngisdn_event_interface.cc.sng_fac_ind = sngisdn_rcv_fac_ind; - g_sngisdn_event_interface.cc.sng_sta_cfm = sngisdn_rcv_sta_cfm; - g_sngisdn_event_interface.cc.sng_srv_ind = sngisdn_rcv_srv_ind; - g_sngisdn_event_interface.cc.sng_srv_cfm = sngisdn_rcv_srv_cfm; - g_sngisdn_event_interface.cc.sng_rst_ind = sngisdn_rcv_rst_ind; - g_sngisdn_event_interface.cc.sng_rst_cfm = sngisdn_rcv_rst_cfm; - - g_sngisdn_event_interface.lg.sng_log = sngisdn_rcv_sng_log; - g_sngisdn_event_interface.lg.sng_assert = sngisdn_rcv_sng_assert; - - g_sngisdn_event_interface.sta.sng_phy_sta_ind = sngisdn_rcv_phy_ind; - g_sngisdn_event_interface.sta.sng_q921_sta_ind = sngisdn_rcv_q921_ind; - g_sngisdn_event_interface.sta.sng_q921_trc_ind = sngisdn_rcv_q921_trace; - g_sngisdn_event_interface.sta.sng_q931_sta_ind = sngisdn_rcv_q931_ind; - g_sngisdn_event_interface.sta.sng_q931_trc_ind = sngisdn_rcv_q931_trace; - g_sngisdn_event_interface.sta.sng_cc_sta_ind = sngisdn_rcv_cc_ind; - - g_sngisdn_event_interface.io.sng_l1_data_req = sngisdn_rcv_l1_data_req; - g_sngisdn_event_interface.io.sng_l1_cmd_req = sngisdn_rcv_l1_cmd_req; - - for(i=1;i<=MAX_VARIANTS;i++) { - ftdm_mutex_create(&g_sngisdn_data.ccs[i].mutex); - } - - /* initalize sng_isdn library */ - ftdm_assert_return(!sng_isdn_init(&g_sngisdn_event_interface), FTDM_FAIL, "Failed to initialize stack\n"); - - /* Load Stack General Configuration */ - sngisdn_start_gen_cfg(); - - return FTDM_SUCCESS; -} - -static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_isdn_unload) -{ - unsigned i; - ftdm_log(FTDM_LOG_INFO, "Starting ftmod_sangoma_isdn unload...\n"); - - sng_isdn_free(); - - for(i=1;i<=MAX_VARIANTS;i++) { - ftdm_mutex_destroy(&g_sngisdn_data.ccs[i].mutex); - } - - ftdm_log(FTDM_LOG_INFO, "Finished ftmod_sangoma_isdn unload!\n"); - return FTDM_SUCCESS; -} - -#define SANGOMA_ISDN_API_USAGE_TRACE "ftdm sangoma_isdn trace \n" -#define SANGOMA_ISDN_API_USAGE_SHOW_L1_STATS "ftdm sangoma_isdn l1_stats \n" -#define SANGOMA_ISDN_API_USAGE_SHOW_SPANS "ftdm sangoma_isdn show_spans []\n" - -#define SANGOMA_ISDN_API_USAGE "\t"SANGOMA_ISDN_API_USAGE_TRACE \ - "\t"SANGOMA_ISDN_API_USAGE_SHOW_L1_STATS \ - "\t"SANGOMA_ISDN_API_USAGE_SHOW_SPANS - -static FIO_API_FUNCTION(ftdm_sangoma_isdn_api) -{ - ftdm_status_t status = FTDM_EINVAL; - char *mycmd = NULL, *argv[10] = { 0 }; - int argc = 0; - - if (data) { - mycmd = ftdm_strdup(data); - argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); - } - - /*ftdm_log(FTDM_LOG_DEBUG, "Sangoma argc:%d argv[0]:%s argv[1]:%s argv[2]:%s \n", argc, argv[0], argv[1], argv[2]);*/ - if (argc <= 0) { - ftdm_log(FTDM_LOG_ERROR, "No parameters provided\n"); - goto done; - } - - /* TODO: Move functions to table + function pointers */ - if (!strcasecmp(argv[0], "trace")) { - char *trace_opt; - - ftdm_span_t *span; - - if (argc < 3) { - ftdm_log(FTDM_LOG_ERROR, "Usage: %s\n", SANGOMA_ISDN_API_USAGE_TRACE); - status = FTDM_FAIL; - goto done; - } - trace_opt = argv[1]; - - status = ftdm_span_find_by_name(argv[2], &span); - if (FTDM_SUCCESS != status) { - stream->write_function(stream, "-ERR failed to find span by name %s\n", argv[2]); - - status = FTDM_FAIL; - goto done; - } - - if (!strcasecmp(trace_opt, "q921")) { - status = sngisdn_activate_trace(span, SNGISDN_TRACE_Q921); - } else if (!strcasecmp(trace_opt, "q931")) { - status = sngisdn_activate_trace(span, SNGISDN_TRACE_Q931); - } else if (!strcasecmp(trace_opt, "disable")) { - status = sngisdn_activate_trace(span, SNGISDN_TRACE_DISABLE); - } else { - stream->write_function(stream, "-ERR invalid trace option \n"); - status = FTDM_FAIL; - } - goto done; - } - - if (!strcasecmp(argv[0], "l1_stats")) { - ftdm_span_t *span; - if (argc < 2) { - stream->write_function(stream, "Usage: %s\n", SANGOMA_ISDN_API_USAGE_SHOW_L1_STATS); - status = FTDM_FAIL; - goto done; - } - status = ftdm_span_find_by_name(argv[1], &span); - if (FTDM_SUCCESS != status) { - stream->write_function(stream, "-ERR failed to find span with name %s\n", argv[1]); - - status = FTDM_FAIL; - goto done; - } - status = sngisdn_show_l1_stats(stream, span); - goto done; - } - - if (!strcasecmp(argv[0], "show_spans")) { - ftdm_span_t *span = NULL; - if (argc == 2) { - status = ftdm_span_find_by_name(argv[1], &span); - if (FTDM_SUCCESS != status) { - stream->write_function(stream, "-ERR failed to find span with name %s\n", argv[1]); - - stream->write_function(stream, "Usage: %s\n", SANGOMA_ISDN_API_USAGE_SHOW_SPANS); - status = FTDM_FAIL; - goto done; - } - status = sngisdn_show_span(stream, span); - goto done; - } - status = sngisdn_show_spans(stream); - goto done; - } - - if (!strcasecmp(argv[0], "check_ids")) { - status = sngisdn_check_free_ids(); - goto done; - } - if (!strcasecmp(argv[0], "check_mem")) { - sngisdn_get_memory_info(); - } -done: - switch (status) { - case FTDM_SUCCESS: - stream->write_function(stream, "Command executed OK\n"); - break; - case FTDM_EINVAL: - stream->write_function(stream, "Invalid arguments [%s]\n", mycmd); - stream->write_function(stream, "Usage:\n%s\n", SANGOMA_ISDN_API_USAGE); - break; - default: - /* FTDM_FAIL - Do nothing since we already printed the cause of the error */ - break; - } - - /* Return SUCCESS because we do not want to print the general FTDM usage list */ - status = FTDM_SUCCESS; - - ftdm_safe_free(mycmd); - return status; -} - - -static FIO_IO_LOAD_FUNCTION(ftdm_sangoma_isdn_io_init) -{ - memset(&g_sngisdn_io_interface, 0, sizeof(g_sngisdn_io_interface)); - - g_sngisdn_io_interface.name = "sangoma_isdn"; - g_sngisdn_io_interface.api = ftdm_sangoma_isdn_api; - - *fio = &g_sngisdn_io_interface; - - return FTDM_SUCCESS; -} - -EX_DECLARE_DATA ftdm_module_t ftdm_module = -{ - "sangoma_isdn", /* char name[256]; */ - ftdm_sangoma_isdn_io_init, /* fio_io_load_t */ - NULL, /* fio_io_unload_t */ - ftdm_sangoma_isdn_init, /* fio_sig_load_t */ - NULL, /* fio_sig_configure_t */ - ftdm_sangoma_isdn_unload, /* fio_sig_unload_t */ - ftdm_sangoma_isdn_span_config /* fio_configure_span_signaling_t */ -}; - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - -/******************************************************************************/ - - diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h deleted file mode 100644 index 64c1a20999..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ /dev/null @@ -1,613 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * David Yat Sin - * Moises Silva - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef __FTMOD_SNG_ISDN_H__ -#define __FTMOD_SNG_ISDN_H__ - -#include -#include -#include -#ifdef HAVE_STDINT_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#include - -#include "private/ftdm_core.h" -#include "ftmod_sangoma_isdn_user.h" - -#ifdef WIN32 -#include -#else -#include -#endif - -/* Theoretical limit for MAX_SPANS_PER_NFAS_LINK is 31, - but set to 8 for now to save some memory */ - -#define MAX_SPANS_PER_NFAS_LINK 16 -#define MAX_NFAS_GROUPS 16 -#define NUM_E1_CHANNELS_PER_SPAN 32 -#define NUM_T1_CHANNELS_PER_SPAN 24 -#define NUM_BRI_CHANNELS_PER_SPAN 2 -#define SNGISDN_EVENT_QUEUE_SIZE 100 -#define SNGISDN_EVENT_POLL_RATE 100 -#define SNGISDN_NUM_LOCAL_NUMBERS 8 -#define SNGISDN_DCHAN_QUEUE_LEN 200 -#define MAX_NFAS_GROUP_NAME 50 - -#define NSG - -#ifndef MI_NOTIFY -#define MI_NOTIFY 0x14 -#endif - -typedef enum { - FLAG_RESET_RX = (1 << 0), - FLAG_RESET_TX = (1 << 1), - FLAG_REMOTE_REL = (1 << 2), - FLAG_LOCAL_REL = (1 << 3), - FLAG_REMOTE_ABORT = (1 << 4), - FLAG_LOCAL_ABORT = (1 << 5), - FLAG_GLARE = (1 << 6), - FLAG_DELAYED_REL = (1 << 7), - FLAG_SENT_PROCEED = (1 << 8), - FLAG_SEND_DISC = (1 << 9), - /* Used for BRI only, flag is set after we request line CONNECTED */ - FLAG_ACTIVATING = (1 << 10), - /* Used when we receive an ALERT msg + inband tones ready */ - FLAG_MEDIA_READY = (1 << 11), - /* Set when we already sent a Channel ID IE */ - FLAG_SENT_CHAN_ID = (1 << 12), - /* Set when we already sent a Connect */ - FLAG_SENT_CONNECT = (1 << 13), -} sngisdn_flag_t; - - -typedef enum { - SNGISDN_SWITCH_INVALID = 0, /* invalid */ - SNGISDN_SWITCH_NI2 , /* national isdn-2 */ - SNGISDN_SWITCH_5ESS, /* att 5ess */ - SNGISDN_SWITCH_4ESS, /* att 4ess */ - SNGISDN_SWITCH_DMS100, /* nt dms100 */ - SNGISDN_SWITCH_EUROISDN,/* etsi */ - SNGISDN_SWITCH_QSIG, /* etsi qsig */ - SNGISDN_SWITCH_INSNET, /* int - net */ -} sngisdn_switchtype_t; - -typedef enum { - SNGISDN_SIGNALING_INVALID = 0, /* invalid */ - SNGISDN_SIGNALING_CPE , /* customer side emulation */ - SNGISDN_SIGNALING_NET, /* network side emulation */ -} sngisdn_signalingtype_t; - -typedef enum { - SNGISDN_TRACE_DISABLE = 0, - SNGISDN_TRACE_Q921 = 1, - SNGISDN_TRACE_Q931 = 2, -} sngisdn_tracetype_t; - -typedef enum { - SNGISDN_OPT_DEFAULT = 0, - SNGISDN_OPT_TRUE = 1, - SNGISDN_OPT_FALSE = 2, -} sngisdn_opt_t; - -typedef enum { - SNGISDN_EARLY_MEDIA_ON_PROCEED = (1 << 0), - SNGISDN_EARLY_MEDIA_ON_PROGRESS = (1 << 1), - SNGISDN_EARLY_MEDIA_ON_ALERT= (1 << 2), -} sngisdn_early_media_opt_t; - -typedef enum { - SNGISDN_AVAIL_DOWN = 1, - SNGISDN_AVAIL_PWR_SAVING = 5, - SNGISDN_AVAIL_UP = 10, -} sngisdn_avail_t; - -typedef enum { - SNGISDN_CID_NAME_AUTO, - SNGISDN_CID_NAME_DISPLAY_IE, - SNGISDN_CID_NAME_USR_USR_IE, - SNGISDN_CID_NAME_FACILITY_IE, -} sngisdn_cid_name_t; - -typedef enum { - SNGISDN_EVENT_CON_IND = 1, - SNGISDN_EVENT_CON_CFM, - SNGISDN_EVENT_CNST_IND, - SNGISDN_EVENT_DISC_IND, - SNGISDN_EVENT_REL_IND, - SNGISDN_EVENT_DAT_IND, - SNGISDN_EVENT_SSHL_IND, - SNGISDN_EVENT_SSHL_CFM, - SNGISDN_EVENT_RMRT_IND, - SNGISDN_EVENT_RMRT_CFM, - SNGISDN_EVENT_FLC_IND, - SNGISDN_EVENT_FAC_IND, - SNGISDN_EVENT_STA_CFM, - SNGISDN_EVENT_SRV_IND, - SNGISDN_EVENT_SRV_CFM, - SNGISDN_EVENT_RST_CFM, - SNGISDN_EVENT_RST_IND, -} ftdm_sngisdn_event_id_t; - -typedef struct ftdm_sngisdn_prog_ind { - ftdm_sngisdn_progind_loc_t loc; /* location */ - ftdm_sngisdn_progind_descr_t descr; /* description */ -} ftdm_sngisdn_progind_t; - -/* Only timers that can be cancelled are listed here */ -#define SNGISDN_NUM_CHAN_TIMERS 2 -/* Increase SNGISDN_NUM_CHAN_TIMERS as number of ftdm_sngisdn_chan_timer_t increases */ -typedef enum { - SNGISDN_CHAN_TIMER_FACILITY, - SNGISDN_CHAN_TIMER_ATT_TRANSFER, -} ftdm_sngisdn_chan_timer_t; - -#define SNGISDN_NUM_SPAN_TIMERS 1 -/* Increase SNGISDN_NUM_SPAN_TIMERS as number of ftdm_sngisdn_spanan_timer_t increases */ -typedef enum { - SNGISDN_SPAN_TIMER_RESTART, -} ftdm_sngisdn_span_timer_t; - -typedef struct sngisdn_glare_data { - int16_t suId; - uint32_t suInstId; - uint32_t spInstId; - int16_t dChan; - ConEvnt setup; - uint8_t ces; -} sngisdn_glare_data_t; - -typedef enum { - SNGISDN_TRANSFER_NONE = 0, /* Default value, no transfer being done */ - SNGISDN_TRANSFER_ATT_COURTESY_VRU, - SNGISDN_TRANSFER_ATT_COURTESY_VRU_DATA, - SNGISDN_TRANSFER_INVALID, -} sngisdn_transfer_type_t; -#define SNGISDN_TRANSFER_TYPE_STRINGS "NONE", "ATT_COURTESY_VRU", "ATT_COURTERY_VRU_DATA", "INVALID" -SNGISDN_STR2ENUM_P(ftdm_str2sngisdn_transfer_type, sngisdn_transfer_type2str, sngisdn_transfer_type_t) - -/* From section 4.2 of TR50075, max length of data is 100 when single UUI is sent */ -#define COURTESY_TRANSFER_MAX_DATA_SIZE 100 - -typedef struct _att_courtesy_vru -{ - char dtmf_digits [20]; - char data[COURTESY_TRANSFER_MAX_DATA_SIZE]; -} att_courtesy_vru_t; - -typedef struct _sngisdn_transfer_data -{ - sngisdn_transfer_type_t type; /* Specifies which type of transfer is being used */ - ftdm_transfer_response_t response; - union - { - att_courtesy_vru_t att_courtesy_vru; - } tdata; -} sngisdn_transfer_data_t; - -/* Channel specific data */ -typedef struct sngisdn_chan_data { - ftdm_channel_t *ftdmchan; - uint32_t flags; - uint8_t ces; /* used only for BRI, otherwise always 0 */ - uint8_t dchan_id; - uint16_t call_ref; /* Q.931 call reference, only valid for ETSI/INSNET/QSIG */ - uint32_t suInstId; /* instance ID generated locally */ - uint32_t spInstId; /* instance ID generated by stack */ - - uint8_t globalFlg; - sngisdn_glare_data_t glare; - ftdm_timer_id_t timers[SNGISDN_NUM_CHAN_TIMERS]; - sngisdn_transfer_data_t transfer_data; - - /* variables saved here will be sent to the user application - on next SIGEVENT_XXX */ - ftdm_hash_t* variables; - - /* raw_data saved here will be sent to the user application - on next SIGEVENT_XXX */ - void *raw_data; - ftdm_size_t raw_data_len; -} sngisdn_chan_data_t; - -struct sngisdn_nfas_data; -typedef struct sngisdn_nfas_data sngisdn_nfas_data_t; - -typedef enum { - SNGISDN_NFAS_DCHAN_NONE, - SNGISDN_NFAS_DCHAN_PRIMARY, - SNGISDN_NFAS_DCHAN_BACKUP, -} sngisdn_nfas_sigchan_t; - -/* Span specific data */ -typedef struct sngisdn_span_data { - ftdm_span_t *ftdm_span; - ftdm_channel_t *dchan; - uint8_t link_id; - uint8_t switchtype; - uint8_t signalling; /* SNGISDN_SIGNALING_CPE or SNGISDN_SIGNALING_NET */ - uint8_t cc_id; - ftdm_signaling_status_t sigstatus; - - uint8_t tei; - uint8_t min_digits; - uint8_t trace_flags; /* TODO change to bit map of sngisdn_tracetype_t */ - uint8_t early_media_flags; /* bit map of ftdm_sngisdn_early_media_opt_t */ - uint8_t overlap_dial; - uint8_t setup_arb; - uint8_t facility_ie_decode; - uint8_t facility; - int32_t facility_timeout; - uint8_t att_remove_dtmf; - int32_t transfer_timeout; - uint8_t num_local_numbers; - uint8_t ignore_cause_value; - uint8_t trace_q931; /* TODO: combine with trace_flags */ - uint8_t trace_q921; /* TODO: combine with trace_flags */ - uint8_t raw_trace_q931; /* TODO: combine with trace_flags */ - uint8_t raw_trace_q921; /* TODO: combine with trace_flags */ - uint8_t timer_t3; - uint8_t restart_opt; - uint8_t restart_timeout; - uint8_t force_sending_complete; - uint8_t cid_name_method; - uint8_t send_cid_name; - uint8_t send_connect_ack; - uint8_t dl_request_pending; /* Whether we have a DL request pending */ - - - int32_t timer_t301; - int32_t timer_t302; - int32_t timer_t303; - int32_t timer_t304; - int32_t timer_t305; - int32_t timer_t306; - int32_t timer_t307; - int32_t timer_t308; - int32_t timer_t310; - int32_t timer_t312; - int32_t timer_t313; - int32_t timer_t314; - int32_t timer_t316; - int32_t timer_t318; - int32_t timer_t319; - int32_t timer_t322; - char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS]; - ftdm_timer_id_t timers[SNGISDN_NUM_SPAN_TIMERS]; - ftdm_sched_t *sched; - ftdm_queue_t *event_queue; - - struct nfas_info { - sngisdn_nfas_data_t *trunk; - sngisdn_nfas_sigchan_t sigchan; - uint8_t interface_id; - } nfas; - - uint32_t num_chans; - sngisdn_chan_data_t *channels[NUM_E1_CHANNELS_PER_SPAN]; -} sngisdn_span_data_t; - -typedef struct sngisdn_event_data { - - int16_t suId; - int16_t dChan; - uint32_t suInstId; - uint32_t spInstId; - uint8_t ces; - uint8_t action; - uint8_t evntType; - - sngisdn_chan_data_t *sngisdn_info; - sngisdn_span_data_t *signal_data; - - ftdm_sngisdn_event_id_t event_id; - - union - { - ConEvnt conEvnt; - CnStEvnt cnStEvnt; - DiscEvnt discEvnt; - RelEvnt relEvnt; - InfoEvnt infoEvnt; - SsHlEvnt ssHlEvnt; - RmRtEvnt rmRtEvnt; - StaEvnt staEvnt; - FacEvnt facEvnt; - Srv srvEvnt; - Rst rstEvnt; - }event; - -} sngisdn_event_data_t; - -struct sngisdn_nfas_data { - char name[MAX_NFAS_GROUP_NAME]; - - char dchan_span_name[20]; - sngisdn_span_data_t *dchan; /* Span that contains primary d-channel */ - - char backup_span_name[20]; - sngisdn_span_data_t *backup; /* Span that contains backup d-channel */ - uint8_t num_spans; /* Number of spans within this NFAS */ - uint8_t num_spans_configured; - sngisdn_span_data_t *spans[MAX_SPANS_PER_NFAS_LINK+1]; //indexed by logical span id -}; - -typedef struct sngisdn_cc { - /* TODO: use flags instead of config_done and activation_done */ - uint8_t config_done; - uint8_t activation_done; - uint8_t switchtype; - ftdm_trunk_type_t trunktype; - uint32_t last_suInstId; - ftdm_mutex_t *mutex; - sngisdn_chan_data_t *active_spInstIds[MAX_INSTID+1]; - sngisdn_chan_data_t *active_suInstIds[MAX_INSTID+1]; -}sngisdn_cc_t; - -/* Global sngisdn data */ -typedef struct ftdm_sngisdn_data { - uint8_t gen_config_done; - uint8_t num_cc; /* 1 ent per switchtype */ - struct sngisdn_cc ccs[MAX_VARIANTS+1]; - uint8_t num_nfas; - sngisdn_nfas_data_t nfass[MAX_NFAS_GROUPS+1]; - sngisdn_span_data_t *spans[MAX_L1_LINKS+1]; /* spans are indexed by link_id */ - -#ifdef SANGOMA_ISDN_CHAN_ID_INVERT_BIT - /* Since this is a global configuration, place it here instead of sngisdn_span_data_t */ - uint8_t chan_id_invert_extend_bit; -#endif -}ftdm_sngisdn_data_t; - -typedef struct ftdm2trillium -{ - uint8_t ftdm_val; - uint8_t trillium_val; -}ftdm2trillium_t; - - -/* TODO implement these 2 functions */ -#define ISDN_FUNC_TRACE_ENTER(a) -#define ISDN_FUNC_TRACE_EXIT(a) - -/* Global Structs */ -extern ftdm_sngisdn_data_t g_sngisdn_data; - -/* Configuration functions */ -ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *span); - -/* Support functions */ -uint32_t get_unique_suInstId(int16_t cc_id); -void clear_call_data(sngisdn_chan_data_t *sngisdn_info); -void clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info); -ftdm_status_t get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data); -ftdm_status_t get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data); - -ftdm_status_t sngisdn_set_span_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail); -ftdm_status_t sngisdn_set_chan_avail_rate(ftdm_channel_t *chan, sngisdn_avail_t avail); -void sngisdn_set_span_sig_status(ftdm_span_t *ftdmspan, ftdm_signaling_status_t status); -void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status); - -ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt); - - -void stack_hdr_init(Header *hdr); -void stack_pst_init(Pst *pst); - -/* Outbound Call Control functions */ -void sngisdn_snd_setup(ftdm_channel_t *ftdmchan); -void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan); -void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind); -void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind); -void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind); -void sngisdn_snd_notify_req(ftdm_channel_t *ftdmchan); -void sngisdn_snd_connect(ftdm_channel_t *ftdmchan); -void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan); -void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare); -void sngisdn_snd_reset(ftdm_channel_t *ftdmchan); -void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan); -void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan); -void sngisdn_snd_dl_req(ftdm_channel_t *ftdmchan); -void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan); -void sngisdn_snd_restart(ftdm_channel_t *ftdmchan); -void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len); -void sngisdn_snd_event(sngisdn_span_data_t *signal_data, ftdm_oob_event_t event); - -/* Inbound Call Control functions */ -void sngisdn_rcv_con_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces); -void sngisdn_rcv_con_cfm(int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, int16_t dChan, uint8_t ces); -void sngisdn_rcv_cnst_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, int16_t dChan, uint8_t ces); -void sngisdn_rcv_disc_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt); -void sngisdn_rcv_rel_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt); -void sngisdn_rcv_dat_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, InfoEvnt *infoEvnt); -void sngisdn_rcv_sshl_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action); -void sngisdn_rcv_sshl_cfm(int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action); -void sngisdn_rcv_rmrt_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action); -void sngisdn_rcv_rmrt_cfm(int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action); -void sngisdn_rcv_flc_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt); -void sngisdn_rcv_fac_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, FacEvnt *facEvnt, uint8_t evntType, int16_t dChan, uint8_t ces); -void sngisdn_rcv_sta_cfm(int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt); -void sngisdn_rcv_srv_ind(int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces); -void sngisdn_rcv_srv_cfm(int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces); -void sngisdn_rcv_rst_cfm(int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType); -void sngisdn_rcv_rst_ind(int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType); -int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_l1_frame_t *l1_frame); -int16_t sngisdn_rcv_l1_cmd_req(uint16_t spId, sng_l1_cmd_t *l1_cmd); - - -void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event); -void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event); -void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event); -void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event); -void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event); -void sngisdn_process_dat_ind (sngisdn_event_data_t *sngisdn_event); -void sngisdn_process_sshl_ind (sngisdn_event_data_t *sngisdn_event); -void sngisdn_process_sshl_cfm (sngisdn_event_data_t *sngisdn_event); -void sngisdn_process_rmrt_ind (sngisdn_event_data_t *sngisdn_event); -void sngisdn_process_rmrt_cfm (sngisdn_event_data_t *sngisdn_event); -void sngisdn_process_flc_ind (sngisdn_event_data_t *sngisdn_event); -void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event); -void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event); - -void sngisdn_process_srv_ind (sngisdn_event_data_t *sngisdn_event); -void sngisdn_process_srv_cfm (sngisdn_event_data_t *sngisdn_event); -void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event); -void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event); - -void sngisdn_rcv_phy_ind(SuId suId, Reason reason); -void sngisdn_rcv_q921_ind(BdMngmt *status); - -void sngisdn_trace_interpreted_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len); -void sngisdn_trace_interpreted_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len); -void sngisdn_trace_raw_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len); -void sngisdn_trace_raw_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len); - -void sngisdn_get_memory_info(void); - -ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt); -ftdm_status_t sngisdn_check_free_ids(void); - -void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf); -void sngisdn_rcv_q931_ind(InMngmt *status); -void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf); -void sngisdn_rcv_cc_ind(CcMngmt *status); -void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...); -void sngisdn_rcv_sng_assert(char *message); - -#ifdef NETBORDER_CALL_REF -ftdm_status_t get_callref(ftdm_channel_t *ftdmchan, BCCallRef* callRef); -#endif -ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb); -ftdm_status_t get_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb); -ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb); -ftdm_status_t get_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb); -ftdm_status_t get_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt); -ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad); -ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd); -ftdm_status_t get_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr); -ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t data_len); -ftdm_status_t get_network_specific_fac(ftdm_channel_t *ftdmchan, NetFac *netFac); - -ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb); -ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb); -ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb); -ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb); -ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt); -ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad); -ftdm_status_t set_called_subaddr(ftdm_channel_t *ftdmchan, CdPtySad *cdPtySad); -ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind); -ftdm_status_t set_bear_cap_ie(ftdm_channel_t *ftdmchan, BearCap *bearCap); -ftdm_status_t set_network_specific_fac(ftdm_channel_t *ftdmchan, NetFac *netFac); -ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId); -ftdm_status_t set_restart_ind_ie(ftdm_channel_t *ftdmchan, RstInd *rstInd); -ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr); -ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t *data_len); -ftdm_status_t set_user_to_user_ie(ftdm_channel_t *ftdmchan, UsrUsr *usrUsr); -ftdm_status_t set_cause_ie(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn); -ftdm_status_t set_not_ind_ie(ftdm_channel_t *ftdmchan, NotInd *notInd); - -ftdm_status_t sngisdn_add_var(sngisdn_chan_data_t *sngisdn_info, const char* var, const char* val); -ftdm_status_t sngisdn_add_raw_data(sngisdn_chan_data_t *sngisdn_info, uint8_t* data, ftdm_size_t data_len); -ftdm_status_t sngisdn_clear_data(sngisdn_chan_data_t *sngisdn_info); -void sngisdn_send_signal(sngisdn_chan_data_t *sngisdn_info, ftdm_signal_event_t event_id); - -uint8_t sngisdn_get_infoTranCap_from_user(ftdm_bearer_cap_t bearer_capability); -uint8_t sngisdn_get_usrInfoLyr1Prot_from_user(ftdm_user_layer1_prot_t layer1_prot); -ftdm_bearer_cap_t sngisdn_get_infoTranCap_from_stack(uint8_t bearer_capability); -ftdm_user_layer1_prot_t sngisdn_get_usrInfoLyr1Prot_from_stack(uint8_t layer1_prot); - -ftdm_status_t sngisdn_transfer(ftdm_channel_t *ftdmchan); -ftdm_status_t sngisdn_att_transfer_process_dtmf(ftdm_channel_t *ftdmchan, const char* dtmf); - -static __inline__ uint32_t sngisdn_test_flag(sngisdn_chan_data_t *sngisdn_info, sngisdn_flag_t flag) -{ - return (uint32_t) sngisdn_info->flags & flag; -} -static __inline__ void sngisdn_clear_flag(sngisdn_chan_data_t *sngisdn_info, sngisdn_flag_t flag) -{ - sngisdn_info->flags &= ~flag; -} - -static __inline__ void sngisdn_set_flag(sngisdn_chan_data_t *sngisdn_info, sngisdn_flag_t flag) -{ - sngisdn_info->flags |= flag; -} - -#define sngisdn_set_trace_flag(obj, flag) ((obj)->trace_flags |= (flag)) -#define sngisdn_clear_trace_flag(obj, flag) ((obj)->trace_flags &= ~(flag)) -#define sngisdn_test_trace_flag(obj, flag) ((obj)->trace_flags & flag) - - -void handle_sng_log(uint8_t level, char *fmt,...); -void sngisdn_delayed_setup(void* p_sngisdn_info); -void sngisdn_delayed_release(void* p_sngisdn_info); -void sngisdn_delayed_release_nfas(void *p_sngisdn_info); -void sngisdn_delayed_connect(void* p_sngisdn_info); -void sngisdn_delayed_disconnect(void* p_sngisdn_info); -void sngisdn_facility_timeout(void* p_sngisdn_info); -void sngisdn_t3_timeout(void* p_sngisdn_info); -void sngisdn_restart_timeout(void* p_signal_data); -void sngisdn_delayed_dl_req(void* p_signal_data); - -/* Stack management functions */ -ftdm_status_t sngisdn_start_gen_cfg(void); -ftdm_status_t sngisdn_stack_cfg(ftdm_span_t *span); -ftdm_status_t sngisdn_stack_start(ftdm_span_t *span); -ftdm_status_t sngisdn_stack_stop(ftdm_span_t *span); -ftdm_status_t sngisdn_wake_up_phy(ftdm_span_t *span); -sngisdn_span_data_t *sngisdn_dchan(sngisdn_span_data_t *signal_data); - -ftdm_status_t sngisdn_show_l1_stats(ftdm_stream_handle_t *stream, ftdm_span_t *span); -ftdm_status_t sngisdn_show_spans(ftdm_stream_handle_t *stream); -ftdm_status_t sngisdn_show_span(ftdm_stream_handle_t *stream, ftdm_span_t *span); - -#endif /* __FTMOD_SNG_ISDN_H__ */ - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c deleted file mode 100644 index 31a1a5b69f..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c +++ /dev/null @@ -1,657 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * David Yat Sin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ******************************************************************************/ - -#include "ftmod_sangoma_isdn.h" - -static ftdm_status_t parse_timer(const char* val, int32_t *target); -static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span); -static ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span); -static ftdm_status_t parse_trunkgroup(const char *_trunkgroup); -static ftdm_status_t add_local_number(const char* val, ftdm_span_t *span); -static ftdm_status_t parse_yesno(const char* var, const char* val, uint8_t *target); -static ftdm_status_t set_switchtype_defaults(ftdm_span_t *span); - -extern ftdm_sngisdn_data_t g_sngisdn_data; - - -static ftdm_status_t parse_timer(const char* val, int32_t *target) -{ - *target = atoi(val); - if (*target < 0) { - *target = 0; - } - return FTDM_SUCCESS; -} - -static ftdm_status_t parse_yesno(const char* var, const char* val, uint8_t *target) -{ - if (ftdm_true(val)) { - *target = SNGISDN_OPT_TRUE; - } else { - *target = SNGISDN_OPT_FALSE; - } - return FTDM_SUCCESS; -} - -static ftdm_status_t add_local_number(const char* val, ftdm_span_t *span) -{ - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; - - if (signal_data->num_local_numbers >= SNGISDN_NUM_LOCAL_NUMBERS) { - ftdm_log(FTDM_LOG_ERROR, "%s: Maximum number of local-numbers exceeded (max:%d)\n", span->name, SNGISDN_NUM_LOCAL_NUMBERS); - return FTDM_FAIL; - } - - signal_data->local_numbers[signal_data->num_local_numbers++] = ftdm_strdup(val); - return FTDM_SUCCESS; -} - -static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span) -{ - unsigned i; - ftdm_iterator_t *chaniter = NULL; - ftdm_iterator_t *curr = NULL; - //sngisdn_dchan_data_t *dchan_data; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; - - switch(span->trunk_type) { - case FTDM_TRUNK_T1: - if (!strcasecmp(switch_name, "ni2") || - !strcasecmp(switch_name, "national")) { - signal_data->switchtype = SNGISDN_SWITCH_NI2; - } else if (!strcasecmp(switch_name, "5ess")) { - signal_data->switchtype = SNGISDN_SWITCH_5ESS; - } else if (!strcasecmp(switch_name, "4ess")) { - signal_data->switchtype = SNGISDN_SWITCH_4ESS; - } else if (!strcasecmp(switch_name, "dms100")) { - signal_data->switchtype = SNGISDN_SWITCH_DMS100; - } else if (!strcasecmp(switch_name, "qsig")) { - signal_data->switchtype = SNGISDN_SWITCH_QSIG; - } else { - ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported switchtype %s for trunktype:%s\n", span->name, switch_name, ftdm_trunk_type2str(span->trunk_type)); - return FTDM_FAIL; - } - break; - case FTDM_TRUNK_E1: - if (!strcasecmp(switch_name, "euroisdn") || - !strcasecmp(switch_name, "etsi")) { - signal_data->switchtype = SNGISDN_SWITCH_EUROISDN; - } else if (!strcasecmp(switch_name, "qsig")) { - signal_data->switchtype = SNGISDN_SWITCH_QSIG; - } else { - ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported switchtype %s for trunktype:%s\n", span->name, switch_name, ftdm_trunk_type2str(span->trunk_type)); - return FTDM_FAIL; - } - break; - case FTDM_TRUNK_BRI: - case FTDM_TRUNK_BRI_PTMP: - if (!strcasecmp(switch_name, "euroisdn") || - !strcasecmp(switch_name, "etsi")) { - signal_data->switchtype = SNGISDN_SWITCH_EUROISDN; - } else if (!strcasecmp(switch_name, "insnet") || - !strcasecmp(switch_name, "ntt")) { - signal_data->switchtype = SNGISDN_SWITCH_INSNET; - } else { - ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported switchtype %s for trunktype:%s\n", span->name, switch_name, ftdm_trunk_type2str(span->trunk_type)); - return FTDM_FAIL; - } - ftdm_set_flag(span, FTDM_SPAN_USE_AV_RATE); - ftdm_set_flag(span, FTDM_SPAN_PWR_SAVING); - /* can be > 1 for some BRI variants */ - break; - default: - ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported trunktype:%s\n", span->name, ftdm_trunk_type2str(span->trunk_type)); - return FTDM_FAIL; - } - - /* see if we have profile with this switch_type already */ - for (i = 1; i <= g_sngisdn_data.num_cc; i++) { - if (g_sngisdn_data.ccs[i].switchtype == signal_data->switchtype && - g_sngisdn_data.ccs[i].trunktype == span->trunk_type) { - break; - } - } - - /* need to create a new switch_type */ - if (i > g_sngisdn_data.num_cc) { - g_sngisdn_data.num_cc++; - g_sngisdn_data.ccs[i].switchtype = signal_data->switchtype; - g_sngisdn_data.ccs[i].trunktype = span->trunk_type; - ftdm_log(FTDM_LOG_DEBUG, "%s: New switchtype:%s cc_id:%u\n", span->name, switch_name, i); - } - - /* add this span to its ent_cc */ - signal_data->cc_id = i; - - g_sngisdn_data.spans[signal_data->link_id] = signal_data; - - ftdm_log(FTDM_LOG_DEBUG, "%s: cc_id:%d link_id:%d\n", span->name, signal_data->cc_id, signal_data->link_id); - - chaniter = ftdm_span_get_chan_iterator(span, NULL); - for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { - int32_t chan_id; - ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr); - if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) { - /* set the d-channel */ - signal_data->dchan = ftdmchan; - } else { - /* Add the channels to the span */ - chan_id = ftdmchan->physical_chan_id; - signal_data->channels[chan_id] = (sngisdn_chan_data_t*)ftdmchan->call_data; - signal_data->num_chans++; - } - } - ftdm_iterator_free(chaniter); - return FTDM_SUCCESS; -} - -static ftdm_status_t parse_signalling(const char *signalling, ftdm_span_t *span) -{ - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; - if (!strcasecmp(signalling, "net") || - !strcasecmp(signalling, "pri_net")|| - !strcasecmp(signalling, "bri_net")) { - - signal_data->signalling = SNGISDN_SIGNALING_NET; - } else if (!strcasecmp(signalling, "cpe") || - !strcasecmp(signalling, "pri_cpe")|| - !strcasecmp(signalling, "bri_cpe")) { - - signal_data->signalling = SNGISDN_SIGNALING_CPE; - } else { - ftdm_log(FTDM_LOG_ERROR, "Unsupported signalling/interface %s\n", signalling); - return FTDM_FAIL; - } - return FTDM_SUCCESS; -} - -static ftdm_status_t parse_spanmap(const char *_spanmap, ftdm_span_t *span) -{ - int i; - char *p, *name, *spanmap; - uint8_t logical_span_id = 0; - ftdm_status_t ret = FTDM_SUCCESS; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; - - spanmap = ftdm_strdup(_spanmap); - - p = name = NULL; - - i = 0; - for (p = strtok(spanmap, ","); p; p = strtok(NULL, ",")) { - while (*p == ' ') { - p++; - } - switch(i++) { - case 0: - name = ftdm_strdup(p); - break; - case 1: - logical_span_id = atoi(p); - break; - } - } - - if (!name) { - ftdm_log(FTDM_LOG_ERROR, "Invalid spanmap syntax %s\n", _spanmap); - ret = FTDM_FAIL; - goto done; - } - - for (i = 0; i < g_sngisdn_data.num_nfas; i++) { - if (!ftdm_strlen_zero(g_sngisdn_data.nfass[i].name) && - !strcasecmp(g_sngisdn_data.nfass[i].name, name)) { - - signal_data->nfas.trunk = &g_sngisdn_data.nfass[i]; - break; - } - } - - if (!signal_data->nfas.trunk) { - ftdm_log(FTDM_LOG_ERROR, "Could not find trunkgroup with name %s\n", name); - ret = FTDM_FAIL; - goto done; - } - - if (signal_data->nfas.trunk->spans[logical_span_id]) { - ftdm_log(FTDM_LOG_ERROR, "trunkgroup:%s already had a span with logical span id:%d\n", name, logical_span_id); - } else { - signal_data->nfas.trunk->spans[logical_span_id] = signal_data; - signal_data->nfas.interface_id = logical_span_id; - } - - if (!strcasecmp(signal_data->ftdm_span->name, signal_data->nfas.trunk->dchan_span_name)) { - - signal_data->nfas.sigchan = SNGISDN_NFAS_DCHAN_PRIMARY; - signal_data->nfas.trunk->dchan = signal_data; - } - - if (!strcasecmp(signal_data->ftdm_span->name, signal_data->nfas.trunk->backup_span_name)) { - - signal_data->nfas.sigchan = SNGISDN_NFAS_DCHAN_BACKUP; - signal_data->nfas.trunk->backup = signal_data; - } - -done: - ftdm_safe_free(spanmap); - ftdm_safe_free(name); - return ret; -} - -static ftdm_status_t parse_trunkgroup(const char *_trunkgroup) -{ - int i; - char *p, *name, *dchan_span, *backup_span, *trunkgroup; - uint8_t num_spans = 0; - ftdm_status_t ret = FTDM_SUCCESS; - - trunkgroup = ftdm_strdup(_trunkgroup); - - p = name = dchan_span = backup_span = NULL; - - /* format: name, num_chans, dchan_span, [backup_span] */ - - i = 0; - for (p = strtok(trunkgroup, ","); p; p = strtok(NULL, ",")) { - while (*p == ' ') { - p++; - } - switch(i++) { - case 0: - name = ftdm_strdup(p); - break; - case 1: - num_spans = atoi(p); - break; - case 2: - dchan_span = ftdm_strdup(p); - break; - case 3: - backup_span = ftdm_strdup(p); - } - } - - if (!name || !dchan_span || num_spans <= 0) { - ftdm_log(FTDM_LOG_ERROR, "Invalid parameters for trunkgroup:%s\n", _trunkgroup); - ret = FTDM_FAIL; - goto done; - } - - for (i = 0; i < g_sngisdn_data.num_nfas; i++) { - if (!ftdm_strlen_zero(g_sngisdn_data.nfass[i].name) && - !strcasecmp(g_sngisdn_data.nfass[i].name, name)) { - - /* We already configured this trunkgroup */ - goto done; - } - } - - /* Trunk group was not found, need to configure it */ - strncpy(g_sngisdn_data.nfass[i].name, name, sizeof(g_sngisdn_data.nfass[i].name)); - g_sngisdn_data.nfass[i].num_spans = num_spans; - strncpy(g_sngisdn_data.nfass[i].dchan_span_name, dchan_span, sizeof(g_sngisdn_data.nfass[i].dchan_span_name)); - - if (backup_span) { - strncpy(g_sngisdn_data.nfass[i].backup_span_name, backup_span, sizeof(g_sngisdn_data.nfass[i].backup_span_name)); - } - - - g_sngisdn_data.num_nfas++; -done: - ftdm_safe_free(trunkgroup); - ftdm_safe_free(name); - ftdm_safe_free(dchan_span); - ftdm_safe_free(backup_span); - return ret; -} - -static ftdm_status_t parse_early_media(const char* opt, ftdm_span_t *span) -{ - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; - if (!strcasecmp(opt, "on-proceed")) { - signal_data->early_media_flags |= SNGISDN_EARLY_MEDIA_ON_PROCEED; - } else if (!strcasecmp(opt, "on-progress")) { - signal_data->early_media_flags |= SNGISDN_EARLY_MEDIA_ON_PROGRESS; - } else if (!strcasecmp(opt, "on-alert")) { - signal_data->early_media_flags |= SNGISDN_EARLY_MEDIA_ON_ALERT; - } else { - ftdm_log(FTDM_LOG_ERROR, "Unsupported early-media option %s\n", opt); - return FTDM_FAIL; - } - ftdm_log(FTDM_LOG_DEBUG, "Early media opt:0x%x\n", signal_data->early_media_flags); - return FTDM_SUCCESS; -} - - -static ftdm_status_t set_switchtype_defaults(ftdm_span_t *span) -{ - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; - switch(signal_data->switchtype) { - case SNGISDN_SWITCH_NI2: - case SNGISDN_SWITCH_5ESS: - case SNGISDN_SWITCH_4ESS: - case SNGISDN_SWITCH_DMS100: - if (span->default_caller_data.dnis.plan >= FTDM_NPI_INVALID) { - ftdm_set_npi("isdn", &span->default_caller_data.dnis.plan); - } - if (span->default_caller_data.dnis.type >= FTDM_TON_INVALID) { - ftdm_set_ton("national", &span->default_caller_data.dnis.type); - } - if (span->default_caller_data.cid_num.plan >= FTDM_NPI_INVALID) { - ftdm_set_npi("isdn", &span->default_caller_data.cid_num.plan); - } - if (span->default_caller_data.cid_num.type >= FTDM_TON_INVALID) { - ftdm_set_ton("national", &span->default_caller_data.cid_num.type); - } - if (span->default_caller_data.rdnis.plan >= FTDM_NPI_INVALID) { - ftdm_set_npi("isdn", &span->default_caller_data.rdnis.plan); - } - if (span->default_caller_data.rdnis.type >= FTDM_TON_INVALID) { - ftdm_set_ton("national", &span->default_caller_data.rdnis.type); - } - break; - case SNGISDN_SWITCH_EUROISDN: - case SNGISDN_SWITCH_QSIG: - case SNGISDN_SWITCH_INSNET: - if (span->default_caller_data.dnis.plan >= FTDM_NPI_INVALID) { - ftdm_set_npi("unknown", &span->default_caller_data.dnis.plan); - } - if (span->default_caller_data.dnis.type >= FTDM_TON_INVALID) { - ftdm_set_ton("unknown", &span->default_caller_data.dnis.type); - } - if (span->default_caller_data.cid_num.plan >= FTDM_NPI_INVALID) { - ftdm_set_npi("unknown", &span->default_caller_data.cid_num.plan); - } - if (span->default_caller_data.cid_num.type >= FTDM_TON_INVALID) { - ftdm_set_ton("unknown", &span->default_caller_data.cid_num.type); - } - if (span->default_caller_data.rdnis.plan >= FTDM_NPI_INVALID) { - ftdm_set_npi("unknown", &span->default_caller_data.rdnis.plan); - } - if (span->default_caller_data.rdnis.type >= FTDM_TON_INVALID) { - ftdm_set_ton("unknown", &span->default_caller_data.rdnis.type); - } - break; - case SNGISDN_SWITCH_INVALID: - default: - ftdm_log(FTDM_LOG_ERROR, "Unsupported switchtype[%d]\n", signal_data->switchtype); - return FTDM_FAIL; - } - return FTDM_SUCCESS; -} - - -ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *span) -{ - unsigned paramindex; - const char *var, *val; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; - /* Set defaults here */ - signal_data->tei = 0; - signal_data->min_digits = 8; - signal_data->overlap_dial = SNGISDN_OPT_DEFAULT; - signal_data->setup_arb = SNGISDN_OPT_DEFAULT; - signal_data->facility_ie_decode = SNGISDN_OPT_DEFAULT; - signal_data->ignore_cause_value = SNGISDN_OPT_DEFAULT; - signal_data->timer_t3 = 8; - signal_data->restart_opt = SNGISDN_OPT_DEFAULT; - signal_data->link_id = span->span_id; - signal_data->transfer_timeout = 20000; - signal_data->att_remove_dtmf = SNGISDN_OPT_DEFAULT; - signal_data->force_sending_complete = SNGISDN_OPT_DEFAULT; - - signal_data->cid_name_method = SNGISDN_CID_NAME_AUTO; - signal_data->send_cid_name = SNGISDN_OPT_DEFAULT; - signal_data->send_connect_ack = SNGISDN_OPT_DEFAULT; - - span->default_caller_data.dnis.plan = FTDM_NPI_INVALID; - span->default_caller_data.dnis.type = FTDM_TON_INVALID; - span->default_caller_data.cid_num.plan = FTDM_NPI_INVALID; - span->default_caller_data.cid_num.type = FTDM_TON_INVALID; - span->default_caller_data.rdnis.plan = FTDM_NPI_INVALID; - span->default_caller_data.rdnis.type = FTDM_TON_INVALID; - - span->default_caller_data.bearer_capability = IN_ITC_SPEECH; - /* Cannot set default bearer_layer1 yet, as we do not know the switchtype */ - span->default_caller_data.bearer_layer1 = FTDM_INVALID_INT_PARM; - - /* Find out if NFAS is enabled first */ - for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) { - ftdm_log(FTDM_LOG_DEBUG, "Sangoma ISDN key=value, %s=%s\n", ftdm_parameters[paramindex].var, ftdm_parameters[paramindex].val); - var = ftdm_parameters[paramindex].var; - val = ftdm_parameters[paramindex].val; - - if (!strcasecmp(var, "trunkgroup")) { - if (parse_trunkgroup(val) != FTDM_SUCCESS) { - return FTDM_FAIL; - } - } - } - - for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) { - ftdm_log(FTDM_LOG_DEBUG, "Sangoma ISDN key=value, %s=%s\n", ftdm_parameters[paramindex].var, ftdm_parameters[paramindex].val); - var = ftdm_parameters[paramindex].var; - val = ftdm_parameters[paramindex].val; - - if (!strcasecmp(var, "switchtype")) { - if (parse_switchtype(val, span) != FTDM_SUCCESS) { - return FTDM_FAIL; - } - if (set_switchtype_defaults(span) != FTDM_SUCCESS) { - return FTDM_FAIL; - } - } else if (!strcasecmp(var, "signalling") || - !strcasecmp(var, "interface")) { - if (parse_signalling(val, span) != FTDM_SUCCESS) { - return FTDM_FAIL; - } - } else if (!strcasecmp(var, "spanmap")) { - if (parse_spanmap(val, span) != FTDM_SUCCESS) { - return FTDM_FAIL; - } - } else if (!strcasecmp(var, "tei")) { - uint8_t tei = atoi(val); - if (tei > 127) { - ftdm_log(FTDM_LOG_ERROR, "Invalid TEI %d, valid values are (0-127)", tei); - return FTDM_FAIL; - } - signal_data->tei = tei; - } else if (!strcasecmp(var, "overlap")) { - if (!strcasecmp(val, "yes")) { - signal_data->overlap_dial = SNGISDN_OPT_TRUE; - } else if (!strcasecmp(val, "no")) { - signal_data->overlap_dial = SNGISDN_OPT_FALSE; - } else { - ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val); - } - } else if (!strcasecmp(var, "setup-arbitration")) { - parse_yesno(var, val, &signal_data->setup_arb); - } else if (!strcasecmp(var, "facility")) { - parse_yesno(var, val, &signal_data->facility); - } else if (!strcasecmp(var, "min-digits") || - !strcasecmp(var, "min_digits")) { - signal_data->min_digits = atoi(val); - } else if (!strcasecmp(var, "outbound-called-ton")) { - ftdm_set_ton(val, &span->default_caller_data.dnis.type); - } else if (!strcasecmp(var, "outbound-called-npi")) { - ftdm_set_npi(val, &span->default_caller_data.dnis.plan); - } else if (!strcasecmp(var, "outbound-calling-ton")) { - ftdm_set_ton(val, &span->default_caller_data.cid_num.type); - } else if (!strcasecmp(var, "outbound-calling-npi")) { - ftdm_set_npi(val, &span->default_caller_data.cid_num.plan); - } else if (!strcasecmp(var, "outbound-rdnis-ton")) { - ftdm_set_ton(val, &span->default_caller_data.rdnis.type); - } else if (!strcasecmp(var, "outbound-rdnis-npi")) { - ftdm_set_npi(val, &span->default_caller_data.rdnis.plan); - } else if (!strcasecmp(var, "outbound-bc-transfer-cap") || - !strcasecmp(var, "outbound-bearer_cap")) { - ftdm_set_bearer_capability(val, (uint8_t*)&span->default_caller_data.bearer_capability); - } else if (!strcasecmp(var, "outbound-bc-user-layer1") || - !strcasecmp(var, "outbound-bearer_layer1")) { - ftdm_set_bearer_layer1(val, (uint8_t*)&span->default_caller_data.bearer_layer1); - } else if (!strcasecmp(var, "channel-restart-on-link-up")) { - parse_yesno(var, val, &signal_data->restart_opt); - } else if (!strcasecmp(var, "channel-restart-timeout")) { - signal_data->restart_timeout = atoi(val); - } else if (!strcasecmp(var, "local-number")) { - if (add_local_number(val, span) != FTDM_SUCCESS) { - return FTDM_FAIL; - } - } else if (!strcasecmp(var, "facility-timeout")) { - parse_timer(val, &signal_data->facility_timeout); - } else if (!strcasecmp(var, "transfer-timeout")) { - parse_timer(val, &signal_data->transfer_timeout); - } else if (!strcasecmp(var, "att-remove-dtmf")) { - parse_yesno(var, val, &signal_data->att_remove_dtmf); - } else if (!strcasecmp(var, "facility-ie-decode")) { - parse_yesno(var, val, &signal_data->facility_ie_decode); - } else if (!strcasecmp(var, "ignore-cause-value")) { - parse_yesno(var, val, &signal_data->ignore_cause_value); - } else if (!strcasecmp(var, "q931-trace")) { - parse_yesno(var, val, &signal_data->trace_q931); - } else if (!strcasecmp(var, "q921-trace")) { - parse_yesno(var, val, &signal_data->trace_q921); - } else if (!strcasecmp(var, "q931-raw-trace")) { - parse_yesno(var, val, &signal_data->raw_trace_q931); - } else if (!strcasecmp(var, "q921-raw-trace")) { - parse_yesno(var, val, &signal_data->raw_trace_q921); - } else if (!strcasecmp(var, "force-sending-complete")) { - parse_yesno(var, val, &signal_data->force_sending_complete); - } else if (!strcasecmp(var, "early-media-override")) { - if (parse_early_media(val, span) != FTDM_SUCCESS) { - return FTDM_FAIL; - } - } else if (!strcasecmp(var, "chan-id-invert-extend-bit")) { -#ifdef SANGOMA_ISDN_CHAN_ID_INVERT_BIT - parse_yesno(var, val, &g_sngisdn_data.chan_id_invert_extend_bit); -#else - ftdm_log(FTDM_LOG_WARNING, "chan-id-invert-extend-bit is not supported in your version of libsng_isdn\n"); -#endif - } else if (!strcasecmp(var, "cid-name-transmit-method")) { - if (!strcasecmp(val, "display-ie")) { - signal_data->cid_name_method = SNGISDN_CID_NAME_DISPLAY_IE; - } else if (!strcasecmp(val, "user-user-ie")) { - signal_data->cid_name_method = SNGISDN_CID_NAME_USR_USR_IE; - } else if (!strcasecmp(val, "facility-ie")) { - signal_data->cid_name_method = SNGISDN_CID_NAME_FACILITY_IE; - } else if (!strcasecmp(val, "auto") || !strcasecmp(val, "automatic") || !strcasecmp(val, "default")) { - signal_data->cid_name_method = SNGISDN_CID_NAME_AUTO; - } else { - ftdm_log(FTDM_LOG_WARNING, "Invalid option %s for parameter %s\n", val, var); - signal_data->cid_name_method = SNGISDN_CID_NAME_AUTO; - } - } else if (!strcasecmp(var, "send-cid-name")) { - if (!strcasecmp(val, "yes")) { - signal_data->send_cid_name = SNGISDN_OPT_TRUE; - } else if (!strcasecmp(val, "no")) { - signal_data->send_cid_name = SNGISDN_OPT_FALSE; - } else if (!strcasecmp(val, "auto") || !strcasecmp(val, "automatic") || !strcasecmp(val, "default")) { - signal_data->send_cid_name = SNGISDN_OPT_DEFAULT; - } else { - ftdm_log(FTDM_LOG_WARNING, "Invalid option %s for parameter %s\n", val, var); - signal_data->send_cid_name = SNGISDN_OPT_DEFAULT; - } - } else if (!strcasecmp(var, "timer-t301")) { - parse_timer(val, &signal_data->timer_t301); - } else if (!strcasecmp(var, "timer-t302")) { - parse_timer(val, &signal_data->timer_t302); - } else if (!strcasecmp(var, "timer-t303")) { - parse_timer(val, &signal_data->timer_t303); - } else if (!strcasecmp(var, "timer-t304")) { - parse_timer(val, &signal_data->timer_t304); - } else if (!strcasecmp(var, "timer-t305")) { - parse_timer(val, &signal_data->timer_t305); - } else if (!strcasecmp(var, "timer-t306")) { - parse_timer(val, &signal_data->timer_t306); - } else if (!strcasecmp(var, "timer-t307")) { - parse_timer(val, &signal_data->timer_t307); - } else if (!strcasecmp(var, "timer-t308")) { - parse_timer(val, &signal_data->timer_t308); - } else if (!strcasecmp(var, "timer-t310")) { - parse_timer(val, &signal_data->timer_t310); - } else if (!strcasecmp(var, "timer-t312")) { - parse_timer(val, &signal_data->timer_t312); - } else if (!strcasecmp(var, "timer-t313")) { - parse_timer(val, &signal_data->timer_t313); - } else if (!strcasecmp(var, "timer-t314")) { - parse_timer(val, &signal_data->timer_t314); - } else if (!strcasecmp(var, "timer-t316")) { - parse_timer(val, &signal_data->timer_t316); - } else if (!strcasecmp(var, "timer-t318")) { - parse_timer(val, &signal_data->timer_t318); - } else if (!strcasecmp(var, "timer-t319")) { - parse_timer(val, &signal_data->timer_t319); - } else if (!strcasecmp(var, "timer-t322")) { - parse_timer(val, &signal_data->timer_t322); - } else if (!strcasecmp(var, "trunkgroup")) { - /* Do nothing, we already parsed this parameter */ - } else if (!strcasecmp(var, "send-connect-ack")) { - parse_yesno(var, val, &signal_data->send_connect_ack); - } else { - ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var); - } - } /* for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) */ - - if (signal_data->switchtype == SNGISDN_SWITCH_INVALID) { - ftdm_log(FTDM_LOG_ERROR, "%s: switchtype not specified", span->name); - return FTDM_FAIL; - } - if (signal_data->signalling == SNGISDN_SIGNALING_INVALID) { - ftdm_log(FTDM_LOG_ERROR, "%s: signalling not specified", span->name); - return FTDM_FAIL; - } - - if (span->default_caller_data.bearer_layer1 == FTDM_INVALID_INT_PARM) { - if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN || - signal_data->switchtype == SNGISDN_SWITCH_QSIG) { - span->default_caller_data.bearer_layer1 = IN_UIL1_G711ALAW; - } else { - span->default_caller_data.bearer_layer1 = IN_UIL1_G711ULAW; - } - } - return FTDM_SUCCESS; -} - - -/******************************************************************************/ -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c deleted file mode 100644 index c0caf10ab7..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * David Yat Sin - - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ******************************************************************************/ - -#include "ftmod_sangoma_isdn.h" - -void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status); - -void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status) -{ - ftdm_sigmsg_t sig; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)ftdmchan->span->signal_data; - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Signalling link status changed to %s\n", ftdm_signaling_status2str(status)); - - memset(&sig, 0, sizeof(sig)); - sig.chan_id = ftdmchan->chan_id; - sig.span_id = ftdmchan->span_id; - sig.channel = ftdmchan; - sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sig.ev_data.sigstatus.status = status; - ftdm_span_send_signal(ftdmchan->span, &sig); - - if (FTDM_SPAN_IS_BRI(ftdmchan->span)) { - sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; - if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)) { - ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING); - - ftdm_sched_timer(signal_data->sched, "delayed_setup", 1000, sngisdn_delayed_setup, (void*) sngisdn_info, NULL); - } - } - return; -} - -void sngisdn_set_span_sig_status(ftdm_span_t *span, ftdm_signaling_status_t status) -{ - ftdm_iterator_t *chaniter = NULL; - ftdm_iterator_t *curr = NULL; - - ((sngisdn_span_data_t*)span->signal_data)->sigstatus = status; - - if (status == FTDM_SIG_STATE_UP) { - ((sngisdn_span_data_t*)span->signal_data)->dl_request_pending = 0; - } - - chaniter = ftdm_span_get_chan_iterator(span, NULL); - for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { - sngisdn_set_chan_sig_status(((ftdm_channel_t*)ftdm_iterator_current(curr)), status); - } - ftdm_iterator_free(chaniter); - return; -} - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - -/******************************************************************************/ - diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c deleted file mode 100644 index 92d401d5e0..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c +++ /dev/null @@ -1,1273 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * David Yat Sin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ftmod_sangoma_isdn.h" - -extern ftdm_sngisdn_data_t g_sngisdn_data; - -uint8_t sng_isdn_stack_switchtype(sngisdn_switchtype_t switchtype); - -ftdm_status_t sngisdn_cfg_phy(ftdm_span_t *span); -ftdm_status_t sngisdn_cfg_q921(ftdm_span_t *span); -ftdm_status_t sngisdn_cfg_q931(ftdm_span_t *span); -ftdm_status_t sngisdn_cfg_cc(ftdm_span_t *span); - -ftdm_status_t sngisdn_stack_cfg_phy_gen(void); -ftdm_status_t sngisdn_stack_cfg_q921_gen(void); -ftdm_status_t sngisdn_stack_cfg_q931_gen(void); -ftdm_status_t sngisdn_stack_cfg_cc_gen(void); - - -ftdm_status_t sngisdn_stack_cfg_phy_psap(ftdm_span_t *span); -ftdm_status_t sngisdn_stack_cfg_q921_msap(ftdm_span_t *span); -ftdm_status_t sngisdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t management); -ftdm_status_t sngisdn_stack_cfg_q931_tsap(ftdm_span_t *span); -ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span); -ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span); - -ftdm_status_t sngisdn_stack_cfg_cc_sap(ftdm_span_t *span); - -ftdm_status_t sngisdn_start_gen_cfg(void) -{ - if (!g_sngisdn_data.gen_config_done) { - g_sngisdn_data.gen_config_done = 1; - ftdm_log(FTDM_LOG_DEBUG, "Starting general stack configuration\n"); - if(sngisdn_stack_cfg_phy_gen()!= FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Failed general physical configuration\n"); - return FTDM_FAIL; - } - ftdm_log(FTDM_LOG_DEBUG, "General stack physical done\n"); - - if(sngisdn_stack_cfg_q921_gen()!= FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Failed general q921 configuration\n"); - return FTDM_FAIL; - } - ftdm_log(FTDM_LOG_DEBUG, "General stack q921 done\n"); - - if(sngisdn_stack_cfg_q931_gen()!= FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Failed general q921 configuration\n"); - return FTDM_FAIL; - } - ftdm_log(FTDM_LOG_DEBUG, "General stack q931 done\n"); - - if(sngisdn_stack_cfg_cc_gen()!= FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Failed general CC configuration\n"); - return FTDM_FAIL; - } - ftdm_log(FTDM_LOG_DEBUG, "General stack CC done\n"); - ftdm_log(FTDM_LOG_INFO, "General stack configuration done\n"); - } - return FTDM_SUCCESS; -} - - -ftdm_status_t sngisdn_stack_cfg(ftdm_span_t *span) -{ - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - - ftdm_log(FTDM_LOG_DEBUG, "Starting stack configuration for span:%s\n", span->name); - - if (signal_data->dchan) { - if (sngisdn_stack_cfg_phy_psap(span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "%s:phy_psap configuration failed\n", span->name); - return FTDM_FAIL; - } - ftdm_log(FTDM_LOG_DEBUG, "%s:phy_psap configuration done\n", span->name); - - if (sngisdn_stack_cfg_q921_msap(span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "%s:q921_msap configuration failed\n", span->name); - return FTDM_FAIL; - } - ftdm_log(FTDM_LOG_DEBUG, "%s:q921_msap configuration done\n", span->name); - - if (sngisdn_stack_cfg_q921_dlsap(span, 0) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "%s:q921_dlsap configuration failed\n", span->name); - return FTDM_FAIL; - } - ftdm_log(FTDM_LOG_DEBUG, "%s:q921_dlsap configuration done\n", span->name); - - if (span->trunk_type == FTDM_TRUNK_BRI_PTMP) { - if (sngisdn_stack_cfg_q921_dlsap(span, 1) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "%s:q921_dlsap management configuration failed\n", span->name); - return FTDM_FAIL; - } - ftdm_log(FTDM_LOG_DEBUG, "%s:q921_dlsap management configuration done\n", span->name); - } - } - - if (sngisdn_stack_cfg_q931_dlsap(span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "%s:q931_dlsap configuration failed\n", span->name); - return FTDM_FAIL; - } - ftdm_log(FTDM_LOG_DEBUG, "%s:q931_dlsap configuration done\n", span->name); - - if (signal_data->dchan) { - if (sngisdn_stack_cfg_q931_lce(span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "%s:q931_lce configuration failed\n", span->name); - return FTDM_FAIL; - } - ftdm_log(FTDM_LOG_DEBUG, "%s:q931_lce configuration done\n", span->name); - } - - if (!g_sngisdn_data.ccs[signal_data->cc_id].config_done) { - g_sngisdn_data.ccs[signal_data->cc_id].config_done = 1; - /* if BRI, need to configure dlsap_mgmt */ - if (sngisdn_stack_cfg_q931_tsap(span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "%s:q931_tsap configuration failed\n", span->name); - return FTDM_FAIL; - } - ftdm_log(FTDM_LOG_DEBUG, "%s:q931_tsap configuration done\n", span->name); - - if (sngisdn_stack_cfg_cc_sap(span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "%s:cc_sap configuration failed\n", span->name); - return FTDM_FAIL; - } - ftdm_log(FTDM_LOG_DEBUG, "%s:cc_sap configuration done\n", span->name); - } - - ftdm_log(FTDM_LOG_INFO, "%s:stack configuration done\n", span->name); - return FTDM_SUCCESS; -} - - - -ftdm_status_t sngisdn_stack_cfg_phy_gen(void) -{ - /*local variables*/ - L1Mngmt cfg; /*configuration structure*/ - Pst pst; /*post structure*/ - - /* initalize the post structure */ - stack_pst_init(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTL1; - - /*clear the configuration structure*/ - memset(&cfg, 0, sizeof(cfg)); - - /*fill in some general sections of the header*/ - stack_hdr_init(&cfg.hdr); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTL1; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STGEN; - - stack_pst_init(&cfg.t.cfg.s.l1Gen.sm ); - cfg.t.cfg.s.l1Gen.sm.srcEnt = ENTL1; - cfg.t.cfg.s.l1Gen.sm.dstEnt = ENTSM; - - cfg.t.cfg.s.l1Gen.nmbLnks = MAX_L1_LINKS; - cfg.t.cfg.s.l1Gen.poolTrUpper = POOL_UP_TR; /* upper pool threshold */ - cfg.t.cfg.s.l1Gen.poolTrLower = POOL_LW_TR; /* lower pool threshold */ - - if (sng_isdn_phy_config(&pst, &cfg)) { - return FTDM_FAIL; - } - return FTDM_SUCCESS; -} - -ftdm_status_t sngisdn_stack_cfg_phy_psap(ftdm_span_t *span) -{ - L1Mngmt cfg; - Pst pst; - - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - - /* initalize the post structure */ - stack_pst_init(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTL1; - - /*clear the configuration structure*/ - memset(&cfg, 0, sizeof(cfg)); - - /*fill in some general sections of the header*/ - stack_hdr_init(&cfg.hdr); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTL1; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STPSAP; - - cfg.hdr.elmId.elmntInst1 = signal_data->link_id; - - if (!signal_data->dchan) { - ftdm_log(FTDM_LOG_ERROR, "%s:No d-channels specified\n", span->name); - return FTDM_FAIL; - } - - cfg.t.cfg.s.l1PSAP.sockfd = (int32_t)signal_data->dchan->sockfd; - - switch(span->trunk_type) { - case FTDM_TRUNK_E1: - cfg.t.cfg.s.l1PSAP.type = SNG_L1_TYPE_PRI; - break; - case FTDM_TRUNK_T1: - case FTDM_TRUNK_J1: - cfg.t.cfg.s.l1PSAP.type = SNG_L1_TYPE_PRI; - break; - case FTDM_TRUNK_BRI: - case FTDM_TRUNK_BRI_PTMP: - cfg.t.cfg.s.l1PSAP.type = SNG_L1_TYPE_BRI; - break; - default: - ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported trunk type %d\n", span->name, span->trunk_type); - return FTDM_FAIL; - } - - cfg.t.cfg.s.l1PSAP.spId = signal_data->link_id; - - if (sng_isdn_phy_config(&pst, &cfg)) { - return FTDM_FAIL; - } - return FTDM_SUCCESS; -} - - -ftdm_status_t sngisdn_stack_cfg_q921_gen(void) -{ - BdMngmt cfg; - Pst pst; - - /* initalize the post structure */ - stack_pst_init(&pst); - /* insert the destination Entity */ - pst.dstEnt = ENTLD; - - /*clear the configuration structure*/ - memset(&cfg, 0, sizeof(cfg)); - /*fill in some general sections of the header*/ - stack_hdr_init(&cfg.hdr); - - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTLD; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STGEN; - /* fill in the Gen Conf structures internal pst struct */ - - stack_pst_init(&cfg.t.cfg.s.bdGen.sm); - - cfg.t.cfg.s.bdGen.sm.dstEnt = ENTSM; /* entity */ - - cfg.t.cfg.s.bdGen.nmbPLnks = MAX_L1_LINKS+1; - cfg.t.cfg.s.bdGen.nmbLDLnks = MAX_L1_LINKS+1; /* Not used in LAPD */ - cfg.t.cfg.s.bdGen.nmbDLCs = MAX_L1_LINKS+1; - cfg.t.cfg.s.bdGen.nmbDLCs = MAX_TEIS_PER_LINK*(MAX_L1_LINKS+1); - cfg.t.cfg.s.bdGen.nmbASPLnks = MAX_L1_LINKS+1; - -#ifdef LAPD_3_4 - cfg.t.cfg.s.bdGen.timeRes = 100; /* timer resolution = 1 sec */ -#endif - cfg.t.cfg.s.bdGen.poolTrUpper = 2; /* upper pool threshold */ - cfg.t.cfg.s.bdGen.poolTrLower = 1; /* lower pool threshold */ - - if (sng_isdn_q921_config(&pst, &cfg)) { - return FTDM_FAIL; - } - return FTDM_SUCCESS; -} - -ftdm_status_t sngisdn_stack_cfg_q921_msap(ftdm_span_t *span) -{ - BdMngmt cfg; - Pst pst; - - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - - /* initalize the post structure */ - stack_pst_init(&pst); - /* insert the destination Entity */ - pst.dstEnt = ENTLD; - - /*clear the configuration structure*/ - memset(&cfg, 0, sizeof(cfg)); - /*fill in some general sections of the header*/ - stack_hdr_init(&cfg.hdr); - - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTLD; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STMSAP; - - cfg.t.cfg.s.bdMSAP.lnkNmb = signal_data->link_id; - - cfg.t.cfg.s.bdMSAP.maxOutsFrms = 24; /* MAC window */ - cfg.t.cfg.s.bdMSAP.tQUpperTrs = 32; /* Tx Queue Upper Threshold */ - cfg.t.cfg.s.bdMSAP.tQLowerTrs = 24; /* Tx Queue Lower Threshold */ - cfg.t.cfg.s.bdMSAP.selector = 0; /* Selector 0 */ - /* TODO: check if bdMSAP parameters can be initialized by calling stack_pst_init */ - cfg.t.cfg.s.bdMSAP.mem.region = S_REG; /* Memory region */ - cfg.t.cfg.s.bdMSAP.mem.pool = S_POOL; /* Memory pool */ - cfg.t.cfg.s.bdMSAP.prior = PRIOR0; /* Priority */ - cfg.t.cfg.s.bdMSAP.route = RTESPEC; /* Route */ - cfg.t.cfg.s.bdMSAP.dstProcId = SFndProcId(); /* destination proc id */ - cfg.t.cfg.s.bdMSAP.dstEnt = ENTL1; /* entity */ - cfg.t.cfg.s.bdMSAP.dstInst = S_INST; /* instance */ - cfg.t.cfg.s.bdMSAP.t201Tmr = 1; /* T201 - should be equal to t200Tmr */ - cfg.t.cfg.s.bdMSAP.t202Tmr = 2; /* T202 */ - cfg.t.cfg.s.bdMSAP.bndRetryCnt = 2; /* bind retry counter */ - cfg.t.cfg.s.bdMSAP.tIntTmr = 200; /* bind retry timer */ - cfg.t.cfg.s.bdMSAP.n202 = 3; /* N202 */ - cfg.t.cfg.s.bdMSAP.lowTei = 64; /* Lowest dynamic TEI */ - - if (span->trunk_type == FTDM_TRUNK_BRI_PTMP && - signal_data->signalling == SNGISDN_SIGNALING_NET) { - cfg.t.cfg.s.bdMSAP.kpL1Up = FALSE; /* flag to keep l1 up or not */ - } else { - cfg.t.cfg.s.bdMSAP.kpL1Up = TRUE; /* flag to keep l1 up or not */ - } - - switch(signal_data->switchtype) { - case SNGISDN_SWITCH_NI2: - case SNGISDN_SWITCH_5ESS: - case SNGISDN_SWITCH_4ESS: - case SNGISDN_SWITCH_DMS100: - cfg.t.cfg.s.bdMSAP.type = SW_NI2; - break; - case SNGISDN_SWITCH_INSNET: - cfg.t.cfg.s.bdMSAP.type = SW_CCITT; - break; - case SNGISDN_SWITCH_EUROISDN: - case SNGISDN_SWITCH_QSIG: - cfg.t.cfg.s.bdMSAP.type = SW_ETSI; - break; - } - - if (span->trunk_type == FTDM_TRUNK_BRI_PTMP) { - cfg.t.cfg.s.bdMSAP.teiChkTmr = 20; /* Tei check timer */ - } else { - cfg.t.cfg.s.bdMSAP.teiChkTmr = 0; /* Tei check timer */ - } - - if (signal_data->signalling == SNGISDN_SIGNALING_NET) { - cfg.t.cfg.s.bdMSAP.logInt = 1; /* logical interface = 0 = user, 1= network */ - cfg.t.cfg.s.bdMSAP.setUpArb = PASSIVE; /* set up arbitration */ - } else { - cfg.t.cfg.s.bdMSAP.logInt = 0; /* logical interface = 0 = user, 1= network */ - cfg.t.cfg.s.bdMSAP.setUpArb = ACTIVE; /* set up arbitration */ - } - - /* Overwrite setUpArb value if user forced it */ - if (signal_data->setup_arb == SNGISDN_OPT_TRUE) { - cfg.t.cfg.s.bdMSAP.setUpArb = ACTIVE; - } else if (signal_data->setup_arb == SNGISDN_OPT_FALSE) { - cfg.t.cfg.s.bdMSAP.setUpArb = PASSIVE; - } - - if (sng_isdn_q921_config(&pst, &cfg)) { - return FTDM_FAIL; - } - return FTDM_SUCCESS; -} - -ftdm_status_t sngisdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t management) -{ - BdMngmt cfg; - Pst pst; - - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - /* initalize the post structure */ - stack_pst_init(&pst); - /* insert the destination Entity */ - pst.dstEnt = ENTLD; - - /*clear the configuration structure*/ - memset(&cfg, 0, sizeof(cfg)); - /*fill in some general sections of the header*/ - stack_hdr_init(&cfg.hdr); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTLD; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STDLSAP; - - cfg.t.cfg.s.bdDLSAP.lnkNmb = signal_data->link_id; - - cfg.t.cfg.s.bdDLSAP.n201 = 1028; /* n201 */ - if (span->trunk_type == FTDM_TRUNK_BRI_PTMP || - span->trunk_type == FTDM_TRUNK_BRI) { - - cfg.t.cfg.s.bdDLSAP.k = 1; /* Based on q.921 recommendations */ - } else { - cfg.t.cfg.s.bdDLSAP.k = 7; /* k */ - } - - cfg.t.cfg.s.bdDLSAP.n200 = 3; /* n200 */ - cfg.t.cfg.s.bdDLSAP.congTmr = 300; /* congestion timer */ - cfg.t.cfg.s.bdDLSAP.t200Tmr = 3; /* t1 changed from 25 */ - cfg.t.cfg.s.bdDLSAP.t203Tmr = 10; /* t3 changed from 50 */ - cfg.t.cfg.s.bdDLSAP.mod = 128; /* modulo */ - cfg.t.cfg.s.bdDLSAP.selector = 0; /* Selector 0 */ - cfg.t.cfg.s.bdDLSAP.mem.region = S_REG; /* Memory region */ - cfg.t.cfg.s.bdDLSAP.mem.pool = S_POOL; /* Memory pool */ - cfg.t.cfg.s.bdDLSAP.prior = PRIOR0; /* Priority */ - cfg.t.cfg.s.bdDLSAP.route = RTESPEC; /* Route */ - - if (management) { - cfg.t.cfg.s.bdDLSAP.sapi = MNGMT_SAPI; - cfg.t.cfg.s.bdDLSAP.teiAss = NON_AUTOMATIC; /* static tei assignment */ - cfg.t.cfg.s.bdDLSAP.noOfDlc = 1; - cfg.t.cfg.s.bdDLSAP.tei[0] = 0x7f; - } else { - cfg.t.cfg.s.bdDLSAP.sapi = Q930_SAPI; - if (span->trunk_type == FTDM_TRUNK_BRI_PTMP) { - if (signal_data->signalling == SNGISDN_SIGNALING_NET) { - cfg.t.cfg.s.bdDLSAP.teiAss = AUTOMATIC; - cfg.t.cfg.s.bdDLSAP.noOfDlc = 8; - - cfg.t.cfg.s.bdDLSAP.tei[0] = 64; - cfg.t.cfg.s.bdDLSAP.tei[1] = 65; - cfg.t.cfg.s.bdDLSAP.tei[2] = 66; - cfg.t.cfg.s.bdDLSAP.tei[3] = 67; - cfg.t.cfg.s.bdDLSAP.tei[4] = 68; - cfg.t.cfg.s.bdDLSAP.tei[5] = 69; - cfg.t.cfg.s.bdDLSAP.tei[6] = 70; - cfg.t.cfg.s.bdDLSAP.tei[7] = 71; - } else { - cfg.t.cfg.s.bdDLSAP.teiAss = AUTOMATIC; - cfg.t.cfg.s.bdDLSAP.noOfDlc = 1; - } - } else { - /* Point to point configs */ - cfg.t.cfg.s.bdDLSAP.teiAss = NON_AUTOMATIC; - cfg.t.cfg.s.bdDLSAP.noOfDlc = 1; - cfg.t.cfg.s.bdDLSAP.tei[0] = signal_data->tei; - } - } - - if (sng_isdn_q921_config(&pst, &cfg)) { - return FTDM_FAIL; - } - return FTDM_SUCCESS; -} - -ftdm_status_t sngisdn_stack_cfg_q931_gen(void) -{ - InMngmt cfg; - Pst pst; - - /* initalize the post structure */ - stack_pst_init(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTIN; - - /*clear the configuration structure*/ - memset(&cfg, 0, sizeof(cfg)); - - /*fill in some general sections of the header*/ - stack_hdr_init(&cfg.hdr); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTIN; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STGEN; - - /* fill in the Gen Conf structures internal pst struct */ - stack_pst_init(&cfg.t.cfg.s.inGen.sm); - - cfg.t.cfg.s.inGen.nmbSaps = MAX_VARIANTS+1; /* Total number of variants supported */ - - cfg.t.cfg.s.inGen.nmbLnks = MAX_L1_LINKS+1; /* number of Data Link SAPs */ - cfg.t.cfg.s.inGen.nmbSigLnks = MAX_L1_LINKS+1; - - /* number of CESs */ - cfg.t.cfg.s.inGen.nmbCes = (MAX_L1_LINKS+1)*MAX_NUM_CES_PER_LINK; - /* number of global Call References can have 2 per channel when using HOLD/RESUME */ - cfg.t.cfg.s.inGen.nmbCalRef = MAX_NUM_CALLS; - /* number of bearer channels */ - cfg.t.cfg.s.inGen.nmbBearer = NUM_E1_CHANNELS_PER_SPAN*(MAX_L1_LINKS+1); - /* maximum number of routing entries */ - cfg.t.cfg.s.inGen.nmbRouts = 0; - /* number of profiles */ - cfg.t.cfg.s.inGen.nmbProfiles = 0; - /* upper pool threshold */ - cfg.t.cfg.s.inGen.poolTrUpper = INGEN_POOL_UP_TR; - /* time resolution */ - cfg.t.cfg.s.inGen.timeRes = 100; /* timer resolution = 1 sec */ - - cfg.t.cfg.s.inGen.sm.dstEnt = ENTSM; - - if (sng_isdn_q931_config(&pst, &cfg)) { - return FTDM_FAIL; - } - return FTDM_SUCCESS; -} - -/* Link between CC and q931 */ -ftdm_status_t sngisdn_stack_cfg_q931_tsap(ftdm_span_t *span) -{ - InMngmt cfg; - Pst pst; - unsigned i; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - /* initalize the post structure */ - stack_pst_init(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTIN; - - /*clear the configuration structure*/ - memset(&cfg, 0, sizeof(cfg)); - - /*fill in some general sections of the header*/ - stack_hdr_init(&cfg.hdr); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTIN; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STTSAP; - - cfg.t.cfg.s.inTSAP.sapId = signal_data->cc_id; - - cfg.t.cfg.s.inTSAP.prior = PRIOR0; - cfg.t.cfg.s.inTSAP.route = RTESPEC; - - cfg.t.cfg.s.inTSAP.swtch = sng_isdn_stack_switchtype(signal_data->switchtype); - cfg.t.cfg.s.inTSAP.useSubAdr = 0; /* call routing on subaddress */ - cfg.t.cfg.s.inTSAP.adrPref = 0; /* use of prefix for int'l calls */ - cfg.t.cfg.s.inTSAP.nmbPrefDig = 0; /* number of digits used for prefix */ - - for (i = 0; i < IN_MAXPREFDIG; i++) - cfg.t.cfg.s.inTSAP.prefix[i] = 0; /* address prefix */ - - cfg.t.cfg.s.inTSAP.keyPad = 0; - cfg.t.cfg.s.inTSAP.wcRout = 0; - - for (i = 0; i < ADRLEN; i++) - cfg.t.cfg.s.inTSAP.wcMask[i] = 0; /* address prefix */ - - cfg.t.cfg.s.inTSAP.sidIns = FALSE; /* SID insertion Flag */ - cfg.t.cfg.s.inTSAP.sid.length = 0; /* SID */ - cfg.t.cfg.s.inTSAP.sidTon = 0; /* SID Type of Number */ - cfg.t.cfg.s.inTSAP.sidNPlan = 0; /* SID Numbering Plan */ - cfg.t.cfg.s.inTSAP.callId.len = 0; /* Default Call Identity */ - cfg.t.cfg.s.inTSAP.minAdrDig = 0; /* Minimum number of address digits */ - cfg.t.cfg.s.inTSAP.comptChck = FALSE; /* Validate compatibility */ - cfg.t.cfg.s.inTSAP.nmbApplProf = 0; /* Number of application profiles */ - cfg.t.cfg.s.inTSAP.profNmb[0] = 0; /* Application profiles */ - cfg.t.cfg.s.inTSAP.mem.region = S_REG; - cfg.t.cfg.s.inTSAP.mem.pool = S_POOL; - cfg.t.cfg.s.inTSAP.selector = 0; - - - if (sng_isdn_q931_config(&pst, &cfg)) { - return FTDM_FAIL; - } - return FTDM_SUCCESS; -} - -ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span) -{ - InMngmt cfg; - Pst pst; - - unsigned i; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - /* initalize the post structure */ - stack_pst_init(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTIN; - - /*clear the configuration structure*/ - memset(&cfg, 0, sizeof(cfg)); - - /*fill in some general sections of the header*/ - stack_hdr_init(&cfg.hdr); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTIN; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STDLSAP; - - cfg.hdr.response.selector=0; - - cfg.t.cfg.s.inDLSAP.sapId = signal_data->link_id; - cfg.t.cfg.s.inDLSAP.spId = signal_data->link_id; - - cfg.t.cfg.s.inDLSAP.swtch = sng_isdn_stack_switchtype(signal_data->switchtype); - - cfg.t.cfg.s.inDLSAP.n201 = 1024; - cfg.t.cfg.s.inDLSAP.nmbRst = 2; - cfg.t.cfg.s.inDLSAP.tCbCfg = TRUE; - - cfg.t.cfg.s.inDLSAP.tCbId = signal_data->cc_id; - - if (signal_data->facility == SNGISDN_OPT_TRUE) { - cfg.t.cfg.s.inDLSAP.facilityHandling = IN_FACILITY_STANDRD; - } else { - cfg.t.cfg.s.inDLSAP.facilityHandling = 0; - } - - if (!signal_data->nfas.trunk) { - cfg.t.cfg.s.inDLSAP.nfasInt = FALSE; - cfg.t.cfg.s.inDLSAP.intId = 0; - cfg.t.cfg.s.inDLSAP.sigInt = 0; - cfg.t.cfg.s.inDLSAP.bupInt = 0; - cfg.t.cfg.s.inDLSAP.nmbNfasInt = 0; - cfg.t.cfg.s.inDLSAP.buIntPr = FALSE; - - for (i = 0; i < IN_MAX_NMB_INTRFS; i++) - cfg.t.cfg.s.inDLSAP.ctldInt[i] = IN_INT_NOT_CFGD; - - } else { - cfg.t.cfg.s.inDLSAP.nfasInt = TRUE; - cfg.t.cfg.s.inDLSAP.intId = signal_data->nfas.interface_id; - - for (i = 0; i < IN_MAX_NMB_INTRFS; i++) - cfg.t.cfg.s.inDLSAP.ctldInt[i] = IN_INT_NOT_CFGD; - - switch (signal_data->nfas.sigchan) { - case SNGISDN_NFAS_DCHAN_PRIMARY: - cfg.t.cfg.s.inDLSAP.sigInt = signal_data->nfas.trunk->dchan->link_id; - cfg.t.cfg.s.inDLSAP.nmbNfasInt = signal_data->nfas.trunk->num_spans; - - if (signal_data->nfas.trunk->backup) { - cfg.t.cfg.s.inDLSAP.buIntPr = TRUE; - cfg.t.cfg.s.inDLSAP.bupInt = signal_data->nfas.trunk->backup->link_id; - } else { - cfg.t.cfg.s.inDLSAP.buIntPr = FALSE; - } - - for (i = 0; i < MAX_SPANS_PER_NFAS_LINK; i++) { - if (signal_data->nfas.trunk->spans[i]) { - cfg.t.cfg.s.inDLSAP.ctldInt[i] = signal_data->nfas.trunk->spans[i]->link_id; - } - } - - break; - case SNGISDN_NFAS_DCHAN_BACKUP: - cfg.t.cfg.s.inDLSAP.sigInt = signal_data->nfas.trunk->dchan->link_id; - cfg.t.cfg.s.inDLSAP.nmbNfasInt = signal_data->nfas.trunk->num_spans; - - if (signal_data->nfas.trunk->backup) { - cfg.t.cfg.s.inDLSAP.buIntPr = TRUE; - cfg.t.cfg.s.inDLSAP.bupInt = signal_data->nfas.trunk->backup->link_id; - } else { - cfg.t.cfg.s.inDLSAP.buIntPr = FALSE; - } - - for (i = 0; i < MAX_SPANS_PER_NFAS_LINK; i++) { - if (signal_data->nfas.trunk->spans[i]) { - cfg.t.cfg.s.inDLSAP.ctldInt[i] = signal_data->nfas.trunk->spans[i]->link_id; - } - } - - break; - case SNGISDN_NFAS_DCHAN_NONE: - cfg.t.cfg.s.inDLSAP.sigInt = signal_data->nfas.trunk->dchan->link_id; - cfg.t.cfg.s.inDLSAP.nmbNfasInt = 0; - - break; - } - } - - cfg.t.cfg.s.inDLSAP.numRstInd = 255; - cfg.t.cfg.s.inDLSAP.relOpt = TRUE; -#ifdef ISDN_SRV - cfg.t.cfg.s.inDLSAP.bcas = FALSE; - cfg.t.cfg.s.inDLSAP.maxBSrvCnt = 2; - cfg.t.cfg.s.inDLSAP.maxDSrvCnt = 2; -#endif /* ISDN_SRV */ - - if (signal_data->switchtype == SNGISDN_SWITCH_QSIG) { - cfg.t.cfg.s.inDLSAP.intType = SYM_USER; - cfg.t.cfg.s.inDLSAP.clrGlr = TRUE; /* in case of glare, clear local call */ - cfg.t.cfg.s.inDLSAP.statEnqOpt = FALSE; - cfg.t.cfg.s.inDLSAP.rstOpt = FALSE; - } else { - if (signal_data->signalling == SNGISDN_SIGNALING_NET) { - cfg.t.cfg.s.inDLSAP.intType = NETWORK; - cfg.t.cfg.s.inDLSAP.clrGlr = FALSE; /* in case of glare, do not clear local call */ - cfg.t.cfg.s.inDLSAP.statEnqOpt = TRUE; - - if (signal_data->ftdm_span->trunk_type == FTDM_TRUNK_BRI_PTMP) { - cfg.t.cfg.s.inDLSAP.rstOpt = FALSE; - } else { - cfg.t.cfg.s.inDLSAP.rstOpt = TRUE; - } - } else { - cfg.t.cfg.s.inDLSAP.intType = USER; - cfg.t.cfg.s.inDLSAP.clrGlr = TRUE; /* in case of glare, clear local call */ - cfg.t.cfg.s.inDLSAP.statEnqOpt = FALSE; - cfg.t.cfg.s.inDLSAP.rstOpt = FALSE; - } - } - - if (signal_data->switchtype == SNGISDN_SWITCH_QSIG || - signal_data->switchtype == SNGISDN_SWITCH_5ESS) { - - cfg.t.cfg.s.inDLSAP.ackOpt = TRUE; - } else if (signal_data->signalling == SNGISDN_SIGNALING_NET) { - cfg.t.cfg.s.inDLSAP.ackOpt = TRUE; - } else { - cfg.t.cfg.s.inDLSAP.ackOpt = FALSE; - } - - if (signal_data->send_connect_ack != SNGISDN_OPT_DEFAULT) { - if (signal_data->send_connect_ack == SNGISDN_OPT_TRUE) { - cfg.t.cfg.s.inDLSAP.ackOpt = TRUE; - } else { - cfg.t.cfg.s.inDLSAP.ackOpt = FALSE; - } - } - - /* Override the restart options if user selected that option */ - if (signal_data->restart_opt != SNGISDN_OPT_DEFAULT) { - if (signal_data->restart_opt == SNGISDN_OPT_TRUE) { - cfg.t.cfg.s.inDLSAP.rstOpt = TRUE; - } else { - cfg.t.cfg.s.inDLSAP.rstOpt = FALSE; - } - } - - for (i = 0; i < IN_MAXBCHNL; i++) - { - cfg.t.cfg.s.inDLSAP.bProf[i].profNmb = 0; - cfg.t.cfg.s.inDLSAP.bProf[i].valid = FALSE; - cfg.t.cfg.s.inDLSAP.bProf[i].state = IN_PROV_AVAIL; - } - - if (span->trunk_type == FTDM_TRUNK_BRI_PTMP && - signal_data->signalling == SNGISDN_SIGNALING_NET) { - cfg.t.cfg.s.inDLSAP.nmbCes = MAX_NUM_CES_PER_LINK; - } else { - cfg.t.cfg.s.inDLSAP.nmbCes=1; - } - - cfg.t.cfg.s.inDLSAP.useSubAdr = 0; /* call routing on subaddress */ -#ifdef SANGOMA_ISDN_CHAN_ID_INVERT_BIT - if (signal_data->switchtype == SNGISDN_SWITCH_DMS100 && - g_sngisdn_data.chan_id_invert_extend_bit == SNGISDN_OPT_TRUE) { - /* Since this feature is not standard, we modified Trillium to check - the useSubAdr field and remove the extended bit if this is set, this - is a global configuration and once set, applies to all spans configured - as DMS 100 */ - cfg.t.cfg.s.inDLSAP.useSubAdr = PRSNT_NODEF; - } -#endif - cfg.t.cfg.s.inDLSAP.adrPref = 0; /* use of prefix for international calls */ - cfg.t.cfg.s.inDLSAP.nmbPrefDig = 0; /* number of digits used for prefix */ - for (i = 0; i < IN_MAXPREFDIG; i++) - cfg.t.cfg.s.inDLSAP.prefix[i] = 0; /* address prefix */ - cfg.t.cfg.s.inDLSAP.keyPad = 0; - cfg.t.cfg.s.inDLSAP.wcRout = 0; - for (i = 0; i < ADRLEN; i++) - cfg.t.cfg.s.inDLSAP.wcMask[i] = 0; /* address prefix */ - - cfg.t.cfg.s.inDLSAP.sidIns = FALSE; /* SID insertion flag */ - cfg.t.cfg.s.inDLSAP.sid.length = 0; /* SID */ - cfg.t.cfg.s.inDLSAP.sidTon = 0; /* SID Type of Number */ - cfg.t.cfg.s.inDLSAP.sidNPlan = 0; /* SID Numbering Plan */ - cfg.t.cfg.s.inDLSAP.sidPresInd = FALSE; /* SID Presentation Indicator */ - cfg.t.cfg.s.inDLSAP.minAdrDig = 0; /* minimum number of address digits */ - cfg.t.cfg.s.inDLSAP.srvOpt = FALSE; - cfg.t.cfg.s.inDLSAP.callId.len = 0; /* default call id */ - cfg.t.cfg.s.inDLSAP.redirSubsc = FALSE; /* subscription to call redirection */ - cfg.t.cfg.s.inDLSAP.redirAdr.eh.pres = NOTPRSNT; /* redirAdr Numbering Plan */ - cfg.t.cfg.s.inDLSAP.forwSubsc = FALSE; /* programmed forwarding subscription */ - cfg.t.cfg.s.inDLSAP.cndSubsc = TRUE; /* calling adddress delivery service subscription */ - - cfg.t.cfg.s.inDLSAP.tmr.t301.enb = TRUE; - cfg.t.cfg.s.inDLSAP.tmr.t301.val = 180; - if (signal_data->timer_t301 > 0) { - cfg.t.cfg.s.inDLSAP.tmr.t301.val = signal_data->timer_t301; - } - - /* It looks like ETSI is the only variant that supports Overlap */ - if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) { - cfg.t.cfg.s.inDLSAP.tmr.t302.enb = TRUE; - cfg.t.cfg.s.inDLSAP.tmr.t302.val = 15; - } else { - cfg.t.cfg.s.inDLSAP.tmr.t302.enb = FALSE; - cfg.t.cfg.s.inDLSAP.tmr.t302.val = 0; - } - - if (signal_data->timer_t302 > 0) { - cfg.t.cfg.s.inDLSAP.tmr.t302.val = signal_data->timer_t302; - } - - cfg.t.cfg.s.inDLSAP.tmr.t303.enb = TRUE; - cfg.t.cfg.s.inDLSAP.tmr.t303.val = 4; - - if (signal_data->timer_t303 > 0) { - cfg.t.cfg.s.inDLSAP.tmr.t303.val = signal_data->timer_t303; - } - - cfg.t.cfg.s.inDLSAP.tmr.t304.enb = TRUE; - cfg.t.cfg.s.inDLSAP.tmr.t304.val = 30; - - if (signal_data->timer_t304 > 0) { - cfg.t.cfg.s.inDLSAP.tmr.t304.val = signal_data->timer_t304; - } - - cfg.t.cfg.s.inDLSAP.tmr.t305.enb = TRUE; - cfg.t.cfg.s.inDLSAP.tmr.t305.val = 30; - - if (signal_data->timer_t305 > 0) { - cfg.t.cfg.s.inDLSAP.tmr.t305.val = signal_data->timer_t305; - } - - cfg.t.cfg.s.inDLSAP.tmr.t306.enb = FALSE; - cfg.t.cfg.s.inDLSAP.tmr.t306.val = 35; - - if (signal_data->timer_t306 > 0) { - cfg.t.cfg.s.inDLSAP.tmr.t306.val = signal_data->timer_t306; - } - - cfg.t.cfg.s.inDLSAP.tmr.t307.enb = FALSE; - cfg.t.cfg.s.inDLSAP.tmr.t307.val = 35; - - if (signal_data->timer_t307 > 0) { - cfg.t.cfg.s.inDLSAP.tmr.t307.val = signal_data->timer_t307; - } - - cfg.t.cfg.s.inDLSAP.tmr.t308.enb = TRUE; - cfg.t.cfg.s.inDLSAP.tmr.t308.val = 4; - cfg.t.cfg.s.inDLSAP.tmr.t310.enb = TRUE; - cfg.t.cfg.s.inDLSAP.tmr.t310.val = 120; - - if (signal_data->timer_t308 > 0) { - cfg.t.cfg.s.inDLSAP.tmr.t308.val = signal_data->timer_t308; - } - - if (signal_data->signalling == SNGISDN_SIGNALING_NET) { - cfg.t.cfg.s.inDLSAP.tmr.t312.enb = TRUE; - cfg.t.cfg.s.inDLSAP.tmr.t312.val = cfg.t.cfg.s.inDLSAP.tmr.t303.val+2; - } else { - cfg.t.cfg.s.inDLSAP.tmr.t312.enb = FALSE; - } - - if (signal_data->timer_t310 > 0) { - cfg.t.cfg.s.inDLSAP.tmr.t310.val = signal_data->timer_t310; - } - - if (signal_data->timer_t312 > 0) { - cfg.t.cfg.s.inDLSAP.tmr.t312.val = signal_data->timer_t312; - } - - cfg.t.cfg.s.inDLSAP.tmr.t313.enb = TRUE; - cfg.t.cfg.s.inDLSAP.tmr.t313.val = 4; - - if (signal_data->timer_t313 > 0) { - cfg.t.cfg.s.inDLSAP.tmr.t313.val = signal_data->timer_t313; - } - - cfg.t.cfg.s.inDLSAP.tmr.t316.enb = TRUE; - cfg.t.cfg.s.inDLSAP.tmr.t316.val = 120; - - if (signal_data->timer_t316 > 0) { - cfg.t.cfg.s.inDLSAP.tmr.t316.val = signal_data->timer_t316; - } - - cfg.t.cfg.s.inDLSAP.tmr.t316c.enb = FALSE; - cfg.t.cfg.s.inDLSAP.tmr.t316c.val = 35; - - cfg.t.cfg.s.inDLSAP.tmr.t318.enb = TRUE; - cfg.t.cfg.s.inDLSAP.tmr.t318.val = 4; - - if (signal_data->timer_t318 > 0) { - cfg.t.cfg.s.inDLSAP.tmr.t318.val = signal_data->timer_t318; - } - - cfg.t.cfg.s.inDLSAP.tmr.t319.enb = TRUE; - cfg.t.cfg.s.inDLSAP.tmr.t319.val = 4; - - if (signal_data->timer_t319 > 0) { - cfg.t.cfg.s.inDLSAP.tmr.t319.val = signal_data->timer_t319; - } - - cfg.t.cfg.s.inDLSAP.tmr.t322.enb = TRUE; - cfg.t.cfg.s.inDLSAP.tmr.t322.val = 4; - - if (signal_data->timer_t322 > 0) { - cfg.t.cfg.s.inDLSAP.tmr.t322.val = signal_data->timer_t322; - } - - cfg.t.cfg.s.inDLSAP.tmr.t332.enb = FALSE; - cfg.t.cfg.s.inDLSAP.tmr.t332.val = 35; - - cfg.t.cfg.s.inDLSAP.tmr.tRst.enb = TRUE; - cfg.t.cfg.s.inDLSAP.tmr.tRst.val = 8; - - cfg.t.cfg.s.inDLSAP.tmr.tAns.enb = FALSE; /* non-standard timer */ - cfg.t.cfg.s.inDLSAP.tmr.t396.enb = FALSE; /* non-standard timer */ - cfg.t.cfg.s.inDLSAP.tmr.t397.enb = TRUE; /* non-standard timer */ - cfg.t.cfg.s.inDLSAP.tmr.tProg.enb= TRUE; - cfg.t.cfg.s.inDLSAP.tmr.tProg.val= 35; -#ifdef NI2 -#ifdef NI2_TREST - cfg.t.cfg.s.inDLSAP.tmr.tRest.enb= FALSE; - cfg.t.cfg.s.inDLSAP.tmr.tRest.val= 35; /* tRest timer for NI2 */ -#endif /* NI2_TREST */ -#endif /* NI2 */ - - cfg.t.cfg.s.inDLSAP.dstEnt = ENTLD; - cfg.t.cfg.s.inDLSAP.dstInst = S_INST; - cfg.t.cfg.s.inDLSAP.dstProcId = SFndProcId(); - cfg.t.cfg.s.inDLSAP.prior = PRIOR0; - cfg.t.cfg.s.inDLSAP.route = RTESPEC; - cfg.t.cfg.s.inDLSAP.selector = 0; - cfg.t.cfg.s.inDLSAP.mem.region = S_REG; - cfg.t.cfg.s.inDLSAP.mem.pool = S_POOL; - - switch (span->trunk_type) { - case FTDM_TRUNK_E1: - cfg.t.cfg.s.inDLSAP.dChannelNum = 16; - cfg.t.cfg.s.inDLSAP.nmbBearChan = NUM_E1_CHANNELS_PER_SPAN; - cfg.t.cfg.s.inDLSAP.firstBChanNum = 0; - cfg.t.cfg.s.inDLSAP.callRefLen = 2; - cfg.t.cfg.s.inDLSAP.teiAlloc = IN_STATIC; - cfg.t.cfg.s.inDLSAP.intCfg = IN_INTCFG_PTPT; - break; - case FTDM_TRUNK_T1: - case FTDM_TRUNK_J1: - /* if NFAS, could be 0 if no signalling */ - cfg.t.cfg.s.inDLSAP.callRefLen = 2; - cfg.t.cfg.s.inDLSAP.teiAlloc = IN_STATIC; - cfg.t.cfg.s.inDLSAP.intCfg = IN_INTCFG_PTPT; - cfg.t.cfg.s.inDLSAP.firstBChanNum = 1; - - if (signal_data->nfas.trunk) { - if (signal_data->nfas.sigchan == SNGISDN_NFAS_DCHAN_PRIMARY || - signal_data->nfas.sigchan == SNGISDN_NFAS_DCHAN_BACKUP) { - - cfg.t.cfg.s.inDLSAP.dChannelNum = 24; - cfg.t.cfg.s.inDLSAP.nmbBearChan = NUM_T1_CHANNELS_PER_SPAN - 1; - } else { - cfg.t.cfg.s.inDLSAP.dChannelNum = 0; - cfg.t.cfg.s.inDLSAP.nmbBearChan = NUM_T1_CHANNELS_PER_SPAN; - } - } else { - cfg.t.cfg.s.inDLSAP.dChannelNum = 24; - cfg.t.cfg.s.inDLSAP.nmbBearChan = NUM_T1_CHANNELS_PER_SPAN; - cfg.t.cfg.s.inDLSAP.firstBChanNum = 1; - } - break; - case FTDM_TRUNK_BRI: - cfg.t.cfg.s.inDLSAP.dChannelNum = 0; /* Unused for BRI */ - cfg.t.cfg.s.inDLSAP.nmbBearChan = NUM_BRI_CHANNELS_PER_SPAN; - cfg.t.cfg.s.inDLSAP.firstBChanNum = 1; - cfg.t.cfg.s.inDLSAP.callRefLen = 1; - cfg.t.cfg.s.inDLSAP.teiAlloc = IN_STATIC; - cfg.t.cfg.s.inDLSAP.intCfg = IN_INTCFG_PTPT; - break; - case FTDM_TRUNK_BRI_PTMP: - cfg.t.cfg.s.inDLSAP.dChannelNum = 0; /* Unused for BRI */ - cfg.t.cfg.s.inDLSAP.nmbBearChan = NUM_BRI_CHANNELS_PER_SPAN; - cfg.t.cfg.s.inDLSAP.firstBChanNum = 1; - cfg.t.cfg.s.inDLSAP.callRefLen = 1; - cfg.t.cfg.s.inDLSAP.teiAlloc = IN_DYNAMIC; - cfg.t.cfg.s.inDLSAP.intCfg = IN_INTCFG_MULTI; - break; - default: - ftdm_log(FTDM_LOG_ERROR, "%s: Unsupported trunk_type\n", span->name); - return FTDM_FAIL; - } - - if (sng_isdn_q931_config(&pst, &cfg)) { - return FTDM_FAIL; - } - return FTDM_SUCCESS; -} - -ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span) -{ - InMngmt cfg; - Pst pst; - uint8_t i; - uint8_t numCes=1; - - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - if (span->trunk_type == FTDM_TRUNK_BRI_PTMP && signal_data->signalling == SNGISDN_SIGNALING_NET) { - numCes = 8; - } - /* initalize the post structure */ - stack_pst_init(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTIN; - - /*clear the configuration structure*/ - memset(&cfg, 0, sizeof(cfg)); - - /*fill in some general sections of the header*/ - stack_hdr_init(&cfg.hdr); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTIN; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STDLC; - - cfg.hdr.response.selector=0; - - cfg.t.cfg.s.inLCe.sapId = signal_data->link_id; - - if (span->trunk_type == FTDM_TRUNK_BRI_PTMP) { - /* Stack will send Restart CFM's each time link is established (TEI negotiated), - and we do not want thi s event */ - cfg.t.cfg.s.inLCe.lnkUpDwnInd = FALSE; - } else { - cfg.t.cfg.s.inLCe.lnkUpDwnInd = TRUE; - } - - if (FTDM_SPAN_IS_BRI(span)) { - /* tCon Timer causes unwanted hangup on BRI links - where the Q.921 link goes into disconnected - state when idle. */ - - cfg.t.cfg.s.inLCe.tCon.enb = FALSE; - cfg.t.cfg.s.inLCe.tCon.val = 0; - } else { - cfg.t.cfg.s.inLCe.tCon.enb = TRUE; - cfg.t.cfg.s.inLCe.tCon.val = 35; - } - - cfg.t.cfg.s.inLCe.tDisc.enb = TRUE; - cfg.t.cfg.s.inLCe.tDisc.val = 35; - cfg.t.cfg.s.inLCe.t314.enb = FALSE; /* if segmentation enabled, set to TRUE */ - cfg.t.cfg.s.inLCe.t314.val = 35; - - if (signal_data->nfas.trunk) { - cfg.t.cfg.s.inLCe.t332i.enb = TRUE; - cfg.t.cfg.s.inLCe.t332i.val = 35; - } else { - cfg.t.cfg.s.inLCe.t332i.enb = FALSE; - cfg.t.cfg.s.inLCe.t332i.val = 35; - } - -#if (ISDN_NI1 || ISDN_NT || ISDN_ATT) - cfg.t.cfg.s.inLCe.tSpid.enb = TRUE; - cfg.t.cfg.s.inLCe.tSpid.val = 5; - - /* In case we want to support BRI - NORTH America, we will need to configure 8 spid's per CES */ - cfg.t.cfg.s.inLCe.spid.pres = NOTPRSNT; - cfg.t.cfg.s.inLCe.spid.len = 0; -#endif - cfg.t.cfg.s.inLCe.tRstAck.enb = TRUE; - cfg.t.cfg.s.inLCe.tRstAck.val = 10; - - cfg.t.cfg.s.inLCe.usid = 0; - cfg.t.cfg.s.inLCe.tid = 0; - - for(i=0;isignal_data; - - /* initalize the post structure */ - stack_pst_init(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTCC; - - /*clear the configuration structure*/ - memset(&cfg, 0, sizeof(cfg)); - - /*fill in some general sections of the header*/ - stack_hdr_init(&cfg.hdr); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTCC; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STTSAP; - - cfg.t.cfg.s.ccISAP.pst.srcProcId = SFndProcId(); - cfg.t.cfg.s.ccISAP.pst.srcEnt = ENTCC; - cfg.t.cfg.s.ccISAP.pst.srcInst = S_INST; - cfg.t.cfg.s.ccISAP.pst.dstEnt = ENTIN; - cfg.t.cfg.s.ccISAP.pst.dstInst = S_INST; - cfg.t.cfg.s.ccISAP.pst.dstProcId = SFndProcId(); - - cfg.t.cfg.s.ccISAP.pst.prior = PRIOR0; - cfg.t.cfg.s.ccISAP.pst.route = RTESPEC; - cfg.t.cfg.s.ccISAP.pst.region = S_REG; - cfg.t.cfg.s.ccISAP.pst.pool = S_POOL; - cfg.t.cfg.s.ccISAP.pst.selector = 0; - - cfg.t.cfg.s.ccISAP.suId = signal_data->cc_id; - cfg.t.cfg.s.ccISAP.spId = signal_data->cc_id; - - cfg.t.cfg.s.ccISAP.swtch = sng_isdn_stack_switchtype(signal_data->switchtype); - cfg.t.cfg.s.ccISAP.sapType = SNG_SAP_TYPE_ISDN; - - if (sng_isdn_cc_config(&pst, &cfg)) { - return FTDM_FAIL; - } - return FTDM_SUCCESS; -} - -/* TODO: see if we can move this to inside the library */ -void stack_pst_init(Pst *pst) -{ - memset(pst, 0, sizeof(Pst)); - /*fill in the post structure*/ - pst->dstProcId = SFndProcId(); - pst->dstInst = S_INST; - - pst->srcProcId = SFndProcId(); - pst->srcEnt = ENTSM; - pst->srcInst = S_INST; - - pst->prior = PRIOR0; - pst->route = RTESPEC; - pst->region = S_REG; - pst->pool = S_POOL; - pst->selector = 0; - return; -} - - - -void stack_hdr_init(Header *hdr) -{ - hdr->msgType = 0; - hdr->msgLen = 0; - hdr->entId.ent = 0; - hdr->entId.inst = 0; - hdr->elmId.elmnt = 0; - hdr->elmId.elmntInst1 = 0; - hdr->elmId.elmntInst2 = 0; - hdr->elmId.elmntInst3 = 0; - hdr->seqNmb = 0; - hdr->version = 0; - hdr->response.prior = PRIOR0; - hdr->response.route = RTESPEC; - hdr->response.mem.region = S_REG; - hdr->response.mem.pool = S_POOL; - hdr->transId = 0; - hdr->response.selector = 0; - return; -} - -uint8_t sng_isdn_stack_switchtype(sngisdn_switchtype_t switchtype) -{ - switch (switchtype) { - case SNGISDN_SWITCH_NI2: - return SW_NI2; - case SNGISDN_SWITCH_5ESS: - return SW_ATT5EP; - case SNGISDN_SWITCH_4ESS: - return SW_ATT4E; - case SNGISDN_SWITCH_DMS100: - return SW_NTDMS100P; - case SNGISDN_SWITCH_EUROISDN: - return SW_ETSI; - case SNGISDN_SWITCH_QSIG: - return SW_QSIG; - case SNGISDN_SWITCH_INSNET: - return SW_INSNET; - case SNGISDN_SWITCH_INVALID: - ftdm_log(FTDM_LOG_ERROR, "Invalid switchtype: %d\n", switchtype); - break; - } - return 0; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c deleted file mode 100644 index 6a944e28bb..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * David Yat Sin - * Moises Silva - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ftmod_sangoma_isdn.h" - -void stack_resp_hdr_init(Header *hdr); - -ftdm_status_t sngisdn_activate_phy(ftdm_span_t *span); -ftdm_status_t sngisdn_deactivate_phy(ftdm_span_t *span); - -ftdm_status_t sngisdn_activate_cc(ftdm_span_t *span); - -ftdm_status_t sngisdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction); -ftdm_status_t sngisdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction); - - -extern ftdm_sngisdn_data_t g_sngisdn_data; - -ftdm_status_t sngisdn_stack_stop(ftdm_span_t *span); - - -ftdm_status_t sngisdn_stack_start(ftdm_span_t *span) -{ - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - - if (signal_data->dchan) { - if (sngisdn_cntrl_q921(span, ABND_ENA, NOTUSED) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack q921\n", span->name); - return FTDM_FAIL; - } - ftdm_log(FTDM_LOG_DEBUG, "%s:Stack q921 activated\n", span->name); - } - - /* Try to find an alternative for this */ - /* LAPD will call LdUiDatBndCfm before it received a LdLiMacBndCfm from L1, - so we need to give some time before activating q931, as q931 will send a - LdUiDatConReq when activated, and this requires the Mac SAP to be already - bound first */ - ftdm_sleep(500); - - if (!g_sngisdn_data.ccs[signal_data->cc_id].activation_done) { - g_sngisdn_data.ccs[signal_data->cc_id].activation_done = 1; - if (sngisdn_activate_cc(span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack CC\n", span->name); - return FTDM_FAIL; - } - ftdm_log(FTDM_LOG_DEBUG, "%s:Stack CC activated\n", span->name); - } - - if (sngisdn_cntrl_q931(span, ABND_ENA, SAELMNT) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack q931\n", span->name); - return FTDM_FAIL; - } - ftdm_log(FTDM_LOG_DEBUG, "%s:Stack q931 activated\n", span->name); - - ftdm_log(FTDM_LOG_INFO, "%s:Stack activated\n",span->name); - return FTDM_SUCCESS; -} - -ftdm_status_t sngisdn_stack_stop(ftdm_span_t *span) -{ - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - /* Stop L1 first, so we do not receive any more frames */ - if (!signal_data->dchan) { - return FTDM_SUCCESS; - } - if (sngisdn_deactivate_phy(span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "%s:Failed to deactivate stack phy\n", span->name); - return FTDM_FAIL; - } - - if (sngisdn_cntrl_q931(span, AUBND_DIS, SAELMNT) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "%s:Failed to deactivate stack q931\n", span->name); - return FTDM_FAIL; - } - - if (sngisdn_cntrl_q921(span, AUBND_DIS, SAELMNT) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "%s:Failed to deactivate stack q921\n", span->name); - return FTDM_FAIL; - } - - ftdm_log(FTDM_LOG_INFO, "%s:Signalling stopped\n", span->name); - return FTDM_SUCCESS; -} - - -ftdm_status_t sngisdn_activate_phy(ftdm_span_t *span) -{ - - /* There is no need to start phy, as it will Q921 will send a activate request to phy when it starts */ - - return FTDM_SUCCESS; -} - -ftdm_status_t sngisdn_deactivate_phy(ftdm_span_t *span) -{ - L1Mngmt cntrl; - Pst pst; - - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - - /* initalize the post structure */ - stack_pst_init(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTL1; - - /* initalize the control structure */ - memset(&cntrl, 0, sizeof(cntrl)); - - /* initalize the control header */ - stack_hdr_init(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* configuration */ - cntrl.hdr.entId.ent = ENTL1; /* entity */ - cntrl.hdr.entId.inst = S_INST; /* instance */ - cntrl.hdr.elmId.elmnt = STTSAP; /* SAP Specific cntrl */ - - cntrl.t.cntrl.action = AUBND_DIS; - cntrl.t.cntrl.subAction = SAELMNT; - - cntrl.t.cntrl.sapId = signal_data->link_id; - - if (sng_isdn_phy_cntrl(&pst, &cntrl)) { - return FTDM_FAIL; - } - return FTDM_SUCCESS; -} - -ftdm_status_t sngisdn_wake_up_phy(ftdm_span_t *span) -{ - L1Mngmt cntrl; - Pst pst; - - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - - /* initalize the post structure */ - stack_pst_init(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTL1; - - /* initalize the control structure */ - memset(&cntrl, 0, sizeof(cntrl)); - - /* initalize the control header */ - stack_hdr_init(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* configuration */ - cntrl.hdr.entId.ent = ENTL1; /* entity */ - cntrl.hdr.entId.inst = S_INST; /* instance */ - cntrl.hdr.elmId.elmnt = STTSAP; /* SAP Specific cntrl */ - - cntrl.t.cntrl.action = AENA; - cntrl.t.cntrl.subAction = SAELMNT; - - cntrl.t.cntrl.sapId = signal_data->link_id; - - if (sng_isdn_phy_cntrl(&pst, &cntrl)) { - return FTDM_FAIL; - } - return FTDM_SUCCESS; -} - -ftdm_status_t sngisdn_activate_cc(ftdm_span_t *span) -{ - CcMngmt cntrl; - Pst pst; - - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - - /* initalize the post structure */ - stack_pst_init(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTCC; - - /* initalize the control structure */ - memset(&cntrl, 0, sizeof(cntrl)); - - /* initalize the control header */ - stack_hdr_init(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* configuration */ - cntrl.hdr.entId.ent = ENTCC; /* entity */ - cntrl.hdr.entId.inst = S_INST; /* instance */ - cntrl.hdr.elmId.elmnt = STTSAP; /* physical sap */ - - cntrl.t.cntrl.action = ABND_ENA; - cntrl.t.cntrl.subAction = SAELMNT; - - cntrl.t.cntrl.sapId = signal_data->cc_id; - if (sng_isdn_cc_cntrl(&pst, &cntrl)) { - return FTDM_FAIL; - } - return FTDM_SUCCESS; -} - -ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt) -{ - sngisdn_span_data_t *signal_data = sngisdn_dchan((sngisdn_span_data_t*)span->signal_data); - - if (!signal_data) { - ftdm_log(FTDM_LOG_ERROR, "%s:Span is not used by signalling module\n", span->name); - return FTDM_FAIL; - } - - switch (trace_opt) { - case SNGISDN_TRACE_DISABLE: - if (sngisdn_test_trace_flag(signal_data, SNGISDN_TRACE_Q921)) { - ftdm_log(FTDM_LOG_INFO, "%s:Disabling q921 trace\n", signal_data->ftdm_span->name); - sngisdn_clear_trace_flag(signal_data, SNGISDN_TRACE_Q921); - - if (sngisdn_cntrl_q921(signal_data->ftdm_span, ADISIMM, SATRC) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_INFO, "%s:Failed to disable q921 trace\n", signal_data->ftdm_span->name); - } - } - if (sngisdn_test_trace_flag(signal_data, SNGISDN_TRACE_Q931)) { - ftdm_log(FTDM_LOG_INFO, "%s:Disabling q921 trace\n", signal_data->ftdm_span->name); - sngisdn_clear_trace_flag(signal_data, SNGISDN_TRACE_Q931); - - if (sngisdn_cntrl_q931(signal_data->ftdm_span, ADISIMM, SATRC) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_INFO, "%s:Failed to disable q921 trace\n", signal_data->ftdm_span->name); - } - } - break; - case SNGISDN_TRACE_Q921: - if (!sngisdn_test_trace_flag(signal_data, SNGISDN_TRACE_Q921)) { - ftdm_log(FTDM_LOG_INFO, "%s:Enabling q921 trace\n", signal_data->ftdm_span->name); - sngisdn_set_trace_flag(signal_data, SNGISDN_TRACE_Q921); - - if (sngisdn_cntrl_q921(signal_data->ftdm_span, AENA, SATRC) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_INFO, "%s:Failed to enable q921 trace\n", signal_data->ftdm_span->name); - } - } - break; - case SNGISDN_TRACE_Q931: - if (!sngisdn_test_trace_flag(signal_data, SNGISDN_TRACE_Q931)) { - ftdm_log(FTDM_LOG_INFO, "s%d Enabling q931 trace\n", signal_data->link_id); - sngisdn_set_trace_flag(signal_data, SNGISDN_TRACE_Q931); - - if (sngisdn_cntrl_q931(signal_data->ftdm_span, AENA, SATRC) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_INFO, "%s:Failed to enable q931 trace\n", signal_data->ftdm_span->name); - } - } - break; - } - return FTDM_SUCCESS; -} - - -ftdm_status_t sngisdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction) -{ - InMngmt cntrl; - Pst pst; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - - /* initalize the post structure */ - stack_pst_init(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTIN; - - /* initalize the control structure */ - memset(&cntrl, 0, sizeof(cntrl)); - - /* initalize the control header */ - stack_hdr_init(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* configuration */ - cntrl.hdr.entId.ent = ENTIN; /* entity */ - cntrl.hdr.entId.inst = S_INST; /* instance */ - cntrl.hdr.elmId.elmnt = STDLSAP; /* physical sap */ - - cntrl.t.cntrl.action = action; - cntrl.t.cntrl.subAction = subaction; - - if (action == AENA && subaction == SATRC) { - cntrl.t.cntrl.trcLen = -1; /* Trace the entire message buffer */ - } - - cntrl.t.cntrl.sapId = signal_data->link_id; - cntrl.t.cntrl.ces = 0; - - if(sng_isdn_q931_cntrl(&pst, &cntrl)) { - return FTDM_FAIL; - } - return FTDM_SUCCESS; - -} - -ftdm_status_t sngisdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction) -{ - BdMngmt cntrl; - Pst pst; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - - /* initalize the post structure */ - stack_pst_init(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTLD; - - /* initalize the control structure */ - memset(&cntrl, 0, sizeof(cntrl)); - - /* initalize the control header */ - stack_hdr_init(&cntrl.hdr); - /* build control request */ - cntrl.hdr.msgType = TCNTRL; - cntrl.hdr.entId.ent = ENTLD; - cntrl.hdr.entId.inst = S_INST; - -#if (SMBD_LMINT3 || BD_LMINT3) - stack_resp_hdr_init(&cntrl.hdr); -#endif /* _LMINT3 */ - - cntrl.hdr.elmId.elmnt = STMSAP; - cntrl.t.cntrl.action = action; - cntrl.t.cntrl.subAction = subaction; - -#if (SMBD_LMINT3 || BD_LMINT3) - cntrl.t.cntrl.lnkNmb = signal_data->link_id; - cntrl.t.cntrl.sapi = NOTUSED; - cntrl.t.cntrl.tei = NOTUSED; -#else /* _LMINT3 */ - cntrl.hdr.elmId.elmntInst1 = signal_data->link_id; - cntrl.hdr.elmId.elmntInst2 = NOTUSED; - cntrl.hdr.elmId.elmntInst3 = NOTUSED; -#endif /* _LMINT3 */ - - cntrl.t.cntrl.logInt = NOTUSED; - cntrl.t.cntrl.trcLen = NOTUSED; - if (action == AENA && subaction == SATRC) { - cntrl.t.cntrl.trcLen = -1; /* Trace the entire message buffer */ - } - - SGetDateTime(&(cntrl.t.cntrl.dt)); - if(sng_isdn_q921_cntrl(&pst, &cntrl)) { - return FTDM_FAIL; - } - - return FTDM_SUCCESS; -} - - -void stack_resp_hdr_init(Header *hdr) -{ - hdr->response.selector = 0; - hdr->response.mem.region = RTESPEC; - hdr->response.mem.pool = S_POOL; - hdr->response.prior = PRIOR0; - hdr->response.route = RTESPEC; - - return; -} - - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c deleted file mode 100644 index 688c083adb..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ /dev/null @@ -1,1437 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * David Yat Sin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ftmod_sangoma_isdn.h" -static ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn); -static ftdm_status_t sngisdn_bring_down(ftdm_channel_t *ftdmchan); - -/* Remote side transmit a SETUP */ -void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) -{ - unsigned i; - int16_t suId = sngisdn_event->suId; - uint32_t suInstId = sngisdn_event->suInstId; - uint32_t spInstId = sngisdn_event->spInstId; - int16_t dChan = sngisdn_event->dChan; - uint8_t ces = sngisdn_event->ces; - sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - ConEvnt *conEvnt = &sngisdn_event->event.conEvnt; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n"); - - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - - switch (ftdmchan->state) { - case FTDM_CHANNEL_STATE_DOWN: /* Proper state to receive a SETUP */ - if (signal_data->nfas.trunk) { - ftdm_alarm_flag_t alarmflag = 0; - - ftdm_channel_get_alarms(ftdmchan, &alarmflag); - if (alarmflag) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received SETUP but channel has physical layer alarm - rejecting\n"); - - ftdmchan->caller_data.hangup_cause = 0x2C; /* Channel requested not available */ - ftdm_sched_timer(signal_data->sched, "delayed_release", 1, sngisdn_delayed_release, (void*) sngisdn_info, NULL); - break; - } - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE) || - ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { - - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received SETUP but channel is in USE, saving call for later processing\n"); - /* the flag the channel as having a collision */ - sngisdn_set_flag(sngisdn_info, FLAG_GLARE); - - /* save the SETUP for processing once the channel has gone to DOWN */ - memcpy(&sngisdn_info->glare.setup, conEvnt, sizeof(*conEvnt)); - sngisdn_info->glare.suId = suId; - sngisdn_info->glare.suInstId = suInstId; /* Do not generate a suInstId now, we will generate when glared call gets extracted */ - sngisdn_info->glare.spInstId = spInstId; - sngisdn_info->glare.dChan = dChan; - sngisdn_info->glare.ces = ces; - break; - } - - sngisdn_info->suInstId = get_unique_suInstId(suId); - sngisdn_info->spInstId = spInstId; - - if (conEvnt->cdPtyNmb.eh.pres && signal_data->num_local_numbers) { - uint8_t local_number_matched = 0; - for (i = 0 ; i < signal_data->num_local_numbers ; i++) { - if (!strcmp(signal_data->local_numbers[i], (char*)conEvnt->cdPtyNmb.nmbDigits.val)) { - local_number_matched++; - break; - } - } - if (!local_number_matched) { - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received SETUP, but local-number %s does not match - ignoring\n", conEvnt->cdPtyNmb.nmbDigits.val); - /* Special case to tell the stack to clear all internal resources about this call. We will no receive any event for this call after sending disconnect request */ - ftdmchan->caller_data.hangup_cause = IN_CCNORTTODEST; - ftdm_sched_timer(signal_data->sched, "delayed_disconnect", 1, sngisdn_delayed_disconnect, (void*) sngisdn_info, NULL); - return; - } - } - - /* If this is a glared call that was previously saved, we moved - all the info to the current call, so clear the glared saved data */ - if (sngisdn_info->glare.spInstId == spInstId) { - clear_call_glare_data(sngisdn_info); - } - - - if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) { - if (signal_data->signalling == SNGISDN_SIGNALING_NET) { - sngisdn_info->ces = ces; - } - } - - ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); - g_sngisdn_data.ccs[suId].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info; - ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); - - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND); - - /* try to open the channel */ - if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to open channel"); - sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_REL); - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); - break; - } - - /* Fill in call information */ -#ifdef NETBORDER_CALL_REF - get_callref(ftdmchan, &conEvnt->callRef); -#endif - get_calling_num(ftdmchan, &conEvnt->cgPtyNmb); - get_calling_num2(ftdmchan, &conEvnt->cgPtyNmb2); - get_called_num(ftdmchan, &conEvnt->cdPtyNmb); - get_redir_num(ftdmchan, &conEvnt->redirNmb); - get_calling_subaddr(ftdmchan, &conEvnt->cgPtySad); - get_prog_ind_ie(ftdmchan, &conEvnt->progInd); - get_facility_ie(ftdmchan, &conEvnt->facilityStr); - get_calling_name(ftdmchan, conEvnt); - get_network_specific_fac(ftdmchan, &conEvnt->netFac[0]); - - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Incoming call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits); - - if (conEvnt->bearCap[0].eh.pres) { - ftdmchan->caller_data.bearer_layer1 = sngisdn_get_usrInfoLyr1Prot_from_stack(conEvnt->bearCap[0].usrInfoLyr1Prot.val); - ftdmchan->caller_data.bearer_capability = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].infoTranCap.val); - } - - if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) { - if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) { - uint8_t encoding = (conEvnt->ni2OctStr.str.val[2] >> 5); - if (encoding == 0 || encoding == 1) { - /* BCD even or BCD odd */ - uint8_t value = (conEvnt->ni2OctStr.str.val[3] & 0x0F)*10 + ((conEvnt->ni2OctStr.str.val[3] >> 4) & 0x0F); - snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", value); - } else if (encoding == 2) { - /* IA 5 */ - snprintf(ftdmchan->caller_data.aniII, 5, "%c", conEvnt->ni2OctStr.str.val[3]); - } - } - } - -#if 1 - /* this section will not be needed once asn decoding function with key-value pairs is implemented */ - if (signal_data->facility == SNGISDN_OPT_TRUE && - signal_data->facility_ie_decode != SNGISDN_OPT_FALSE && - conEvnt->facilityStr.eh.pres) { - - /* Verify whether the Caller Name will come in a subsequent FACILITY message */ - uint16_t ret_val; - char retrieved_str[255]; - - ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str); - /* - return values for "sng_isdn_retrieve_facility_information_following": - If there will be no information following, or fails to decode IE, returns -1 - If there will be no information following, but current FACILITY IE contains a caller name, returns 0 - If there will be information following, returns 1 - */ - - if (ret_val == 1) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n"); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID); - /* Launch timer in case we never get a FACILITY msg */ - if (signal_data->facility_timeout) { - ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, - sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_CHAN_TIMER_FACILITY]); - } - break; - } else if (ret_val == 0) { - strcpy(ftdmchan->caller_data.cid_name, retrieved_str); - } - } -#endif - if (signal_data->overlap_dial == SNGISDN_OPT_TRUE) { - ftdm_size_t min_digits = ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->min_digits; - ftdm_size_t num_digits; - - num_digits = strlen(ftdmchan->caller_data.dnis.digits); - - if (conEvnt->sndCmplt.eh.pres || num_digits >= min_digits) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); - } else { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); - } - } else { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); - } - break; - case FTDM_CHANNEL_STATE_TERMINATING: - case FTDM_CHANNEL_STATE_HANGUP: - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Processing SETUP in %s state, saving SETUP info for later processing\n", ftdm_channel_state2str(ftdmchan->state)); - ftdm_assert(!sngisdn_test_flag(sngisdn_info, FLAG_GLARE), "Trying to save GLARE info, but we already had a glare\n"); - - sngisdn_set_flag(sngisdn_info, FLAG_GLARE); - - /* save the SETUP for processing once the channel has gone to DOWN */ - memcpy(&sngisdn_info->glare.setup, conEvnt, sizeof(*conEvnt)); - sngisdn_info->glare.suId = suId; - sngisdn_info->glare.suInstId = suInstId; /* Do not generate a suInstId now, we will generate when glared call gets extracted */ - sngisdn_info->glare.spInstId = spInstId; - sngisdn_info->glare.dChan = dChan; - sngisdn_info->glare.ces = ces; - - break; - case FTDM_CHANNEL_STATE_DIALING: /* glare */ - if (signal_data->signalling == SNGISDN_SIGNALING_NET) { - /* Save inbound call info so we can send a RELEASE when this channel goes to a different state */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Processing SETUP in DIALING state, rejecting inbound call\n"); - sngisdn_set_flag(sngisdn_info, FLAG_DELAYED_REL); - - sngisdn_info->glare.suId = suId; - sngisdn_info->glare.suInstId = get_unique_suInstId(suId); - sngisdn_info->glare.spInstId = spInstId; - - sngisdn_info->glare.dChan = dChan; - sngisdn_info->glare.ces = ces; - ftdmchan->caller_data.hangup_cause = 0x2C; /* Channel requested not available */ - ftdm_sched_timer(signal_data->sched, "delayed_release", 1, sngisdn_delayed_release, (void*) sngisdn_info, NULL); - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Processing SETUP in DIALING state, saving SETUP info for later processing\n"); - - /* the flag the channel as having a collision */ - ftdm_assert(!sngisdn_test_flag(sngisdn_info, FLAG_GLARE), "Trying to save GLARE info, but we already had a glare"); - sngisdn_set_flag(sngisdn_info, FLAG_GLARE); - - /* save the SETUP for processing once the channel has gone to DOWN */ - memcpy(&sngisdn_info->glare.setup, conEvnt, sizeof(*conEvnt)); - sngisdn_info->glare.suId = suId; - sngisdn_info->glare.suInstId = suInstId; /* Do not generate a suInstId now, we will generate when glared call gets extracted */ - sngisdn_info->glare.spInstId = spInstId; - sngisdn_info->glare.dChan = dChan; - sngisdn_info->glare.ces = ces; - - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - } - break; - case FTDM_CHANNEL_STATE_RESET: - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n"); - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing SETUP in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state)); - break; - } - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; -} - -/* Remote side transmit a CONNECT or CONNECT ACK */ -void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event) -{ - int16_t suId = sngisdn_event->suId; - uint32_t suInstId = sngisdn_event->suInstId; - uint32_t spInstId = sngisdn_event->spInstId; - uint8_t ces = sngisdn_event->ces; - sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n"); - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing CONNECT/CONNECT ACK (suId:%u suInstId:%u spInstId:%u ces:%d)\n", suId, suInstId, spInstId, ces); - - if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP && - ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->signalling == SNGISDN_SIGNALING_NET) { - - if(sngisdn_info->ces == CES_MNGMNT) { - /* We assign the call to the first TE */ - sngisdn_info->ces = ces; - } else { - /* We already assigned this call, do nothing */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call already assigned, ignoring connect\n"); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - switch(ftdmchan->state) { - case FTDM_CHANNEL_STATE_PROCEED: - case FTDM_CHANNEL_STATE_RINGING: - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - case FTDM_CHANNEL_STATE_DIALING: -#ifdef NETBORDER_CALL_REF - get_callref(ftdmchan, &cnStEvnt->callRef); -#endif - get_prog_ind_ie(ftdmchan, &cnStEvnt->progInd); - get_facility_ie(ftdmchan, &cnStEvnt->facilityStr); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); - break; - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - case FTDM_CHANNEL_STATE_HANGUP: - /* Race condition, we just hung up the call - ignore this message */ - break; - case FTDM_CHANNEL_STATE_RESET: - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n"); - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state)); - - /* Start the disconnect procedure */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - break; - } - } else { - switch(ftdmchan->state) { - case FTDM_CHANNEL_STATE_TRANSFER: - case FTDM_CHANNEL_STATE_UP: - /* These are the only valid states we should get a CONNECT ACK on */ - /* do nothing */ - break; - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - /* Race condition, We just hung up an incoming call right after we sent a CONNECT - ignore this message */ - break; - case FTDM_CHANNEL_STATE_RESET: - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n"); - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state)); - - /* Start the disconnect procedure */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - break; - } - } - - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; -} - -void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) -{ - int16_t suId = sngisdn_event->suId; - uint32_t suInstId = sngisdn_event->suInstId; - uint32_t spInstId = sngisdn_event->spInstId; - uint8_t ces = sngisdn_event->ces; - uint8_t evntType = sngisdn_event->evntType; - - sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n"); - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing %s (suId:%u suInstId:%u spInstId:%u ces:%d)\n", - (evntType == MI_ALERTING)?"ALERT": - (evntType == MI_CALLPROC)?"PROCEED": - (evntType == MI_PROGRESS)?"PROGRESS": - (evntType == MI_SETUPACK)?"SETUP ACK": - (evntType == MI_NOTIFY)?"NOTIFY": - (evntType == MI_INFO)?"INFO":"UNKNOWN", - suId, suInstId, spInstId, ces); - - switch(evntType) { - case MI_CALLPROC: - case MI_PROGRESS: - case MI_ALERTING: -#ifdef NETBORDER_CALL_REF - get_callref(ftdmchan, &cnStEvnt->callRef); -#endif - get_prog_ind_ie(ftdmchan, &cnStEvnt->progInd); - get_facility_ie(ftdmchan, &cnStEvnt->facilityStr); - - if (sngisdn_cause_val_requires_disconnect(ftdmchan, &cnStEvnt->causeDgn[0]) == FTDM_SUCCESS) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Cause requires disconnect (cause:%d)\n", cnStEvnt->causeDgn[0].causeVal.val); - ftdmchan->caller_data.hangup_cause = cnStEvnt->causeDgn[0].causeVal.val; - - sngisdn_set_flag(sngisdn_info, FLAG_SEND_DISC); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - goto sngisdn_process_cnst_ind_end; - } - - switch(ftdmchan->state) { - case FTDM_CHANNEL_STATE_DIALING: - case FTDM_CHANNEL_STATE_PROCEED: - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_RINGING: - if ((cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) || - (cnStEvnt->progInd1.eh.pres && cnStEvnt->progInd1.progDesc.val == IN_PD_IBAVAIL) || - (cnStEvnt->progInd2.eh.pres && cnStEvnt->progInd2.progDesc.val == IN_PD_IBAVAIL) || - (cnStEvnt->progInd3.eh.pres && cnStEvnt->progInd3.progDesc.val == IN_PD_IBAVAIL)) { - - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Early media available\n"); - sngisdn_set_flag(sngisdn_info, FLAG_MEDIA_READY); - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Early media not available\n"); - } - switch (evntType) { - case MI_CALLPROC: - if (!sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY) && - (signal_data->early_media_flags & SNGISDN_EARLY_MEDIA_ON_PROCEED)) { - - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Early media override on proceed\n"); - sngisdn_set_flag(sngisdn_info, FLAG_MEDIA_READY); - } - if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROCEED); - } - break; - case MI_ALERTING: - if (!sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY) && - (signal_data->early_media_flags & SNGISDN_EARLY_MEDIA_ON_ALERT)) { - - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Early media override on alert\n"); - sngisdn_set_flag(sngisdn_info, FLAG_MEDIA_READY); - } - if (ftdmchan->state == FTDM_CHANNEL_STATE_PROCEED) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RINGING); - } - break; - case MI_PROGRESS: - if (!sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY) && - (signal_data->early_media_flags & SNGISDN_EARLY_MEDIA_ON_PROGRESS)) { - - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Early media override on progress\n"); - sngisdn_set_flag(sngisdn_info, FLAG_MEDIA_READY); - } - if (sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY)) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); - } else if (ftdmchan->state != FTDM_CHANNEL_STATE_PROGRESS) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); - } - break; - default: - /* We should never reach this section !*/ - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle this event %d\n", evntType); - } - break; - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - /* We are already in progress media, we can't go to any higher state except up */ - /* Do nothing */ - break; - case FTDM_CHANNEL_STATE_RESET: - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring ALERT/PROCEED/PROGRESS because channel is in RESET state\n"); - break; - case FTDM_CHANNEL_STATE_HANGUP: - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - /* Ignore this message as we already started the hangup process */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring ALERT/PROCEED/PROGRESS because we are already hanging up\n"); - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing ALERT/PROCEED/PROGRESS in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state)); - - /* Start the disconnect procedure */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - break; - } - break; - case MI_SETUPACK: - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Processing SETUP_ACK, but overlap sending not implemented (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - break; - case MI_INFO: - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing INFO (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - - if (cnStEvnt->cdPtyNmb.eh.pres) { - switch(ftdmchan->state) { - case FTDM_CHANNEL_STATE_COLLECT: - { - ftdm_size_t min_digits = ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->min_digits; - ftdm_size_t num_digits; - - get_called_num(ftdmchan, &cnStEvnt->cdPtyNmb); - num_digits = strlen(ftdmchan->caller_data.dnis.digits); - - if (cnStEvnt->sndCmplt.eh.pres || num_digits >= min_digits) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); - } else { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "received %"FTDM_SIZE_FMT" of %"FTDM_SIZE_FMT" digits\n", num_digits, min_digits); - } - } - break; - case FTDM_CHANNEL_STATE_RING: - case FTDM_CHANNEL_STATE_RINGING: - case FTDM_CHANNEL_STATE_PROCEED: - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - case FTDM_CHANNEL_STATE_UP: - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Receiving more digits %s, but we already proceeded with call\n", cnStEvnt->cdPtyNmb.nmbDigits.val); - break; - case FTDM_CHANNEL_STATE_RESET: - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n"); - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unhandled INFO (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - break; - } - } - break; - case MI_NOTIFY: - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing NOTIFY (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - /* Do nothing */ - break; - default: - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Unhandled STATUS event\n"); - break; - } - -sngisdn_process_cnst_ind_end: - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; -} - -void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event) -{ - int16_t suId = sngisdn_event->suId; - uint32_t suInstId = sngisdn_event->suInstId; - uint32_t spInstId = sngisdn_event->spInstId; - sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - - DiscEvnt *discEvnt = &sngisdn_event->event.discEvnt; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing DISCONNECT (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - - ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n"); - switch (ftdmchan->state) { - case FTDM_CHANNEL_STATE_RING: - case FTDM_CHANNEL_STATE_RINGING: - case FTDM_CHANNEL_STATE_DIALING: - case FTDM_CHANNEL_STATE_PROCEED: - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - case FTDM_CHANNEL_STATE_UP: - get_facility_ie(ftdmchan, &discEvnt->facilityStr); - - if (discEvnt->causeDgn[0].eh.pres && discEvnt->causeDgn[0].causeVal.pres) { - ftdmchan->caller_data.hangup_cause = discEvnt->causeDgn[0].causeVal.val; - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "DISCONNECT did not have a cause code\n"); - ftdmchan->caller_data.hangup_cause = 0; - } - sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_REL); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - break; - case FTDM_CHANNEL_STATE_COLLECT: - case FTDM_CHANNEL_STATE_GET_CALLERID: - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); - break; - case FTDM_CHANNEL_STATE_DOWN: - /* somehow we are in down, nothing we can do locally */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Received DISCONNECT but we are in DOWN state\n"); - break; - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - /* This is a race condition. We just sent a DISCONNECT, on this channel */ - /* Do nothing */ - break; - case FTDM_CHANNEL_STATE_RESET: - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n"); - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received DISCONNECT in an invalid state (%s)\n", - ftdm_channel_state2str(ftdmchan->state)); - /* start reset procedure */ - - /* Start the release procedure */ - ftdm_set_flag(sngisdn_info, FLAG_REMOTE_REL); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - break; - } - - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; -} - -void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event) -{ - int16_t suId = sngisdn_event->suId; - uint32_t suInstId = sngisdn_event->suInstId; - uint32_t spInstId = sngisdn_event->spInstId; - sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - - RelEvnt *relEvnt = &sngisdn_event->event.relEvnt; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing RELEASE/RELEASE COMPLETE (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - - ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n"); - - if ((suInstId && (sngisdn_info->glare.suInstId == suInstId)) || - (spInstId && (sngisdn_info->glare.spInstId == spInstId))) { - - /* This hangup is for a glared saved call */ - ftdm_clear_flag(sngisdn_info, FLAG_DELAYED_REL); - clear_call_glare_data(sngisdn_info); - - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* check whether the ftdm channel is in a state to accept a call */ - switch (ftdmchan->state) { - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - /* go to DOWN */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - break; - case FTDM_CHANNEL_STATE_DOWN: - /* do nothing, just drop the message */ - break; - case FTDM_CHANNEL_STATE_DIALING: - /* Remote side rejected our SETUP message on outbound call */ - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) { - sngisdn_set_span_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN); - } - /* fall-through */ - case FTDM_CHANNEL_STATE_PROCEED: - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - case FTDM_CHANNEL_STATE_UP: - case FTDM_CHANNEL_STATE_RING: - case FTDM_CHANNEL_STATE_RINGING: - /* If we previously had a glare on this channel, - this RELEASE could be for the previous call. Confirm whether call_data has - not changed while we were waiting for ftdmchan->mutex by comparing suInstId's */ - if (((sngisdn_chan_data_t*)ftdmchan->call_data)->suInstId == suInstId || - ((sngisdn_chan_data_t*)ftdmchan->call_data)->spInstId == spInstId) { - - get_facility_ie(ftdmchan, &relEvnt->facilityStr); - - if (relEvnt->causeDgn[0].eh.pres && relEvnt->causeDgn[0].causeVal.pres) { - ftdmchan->caller_data.hangup_cause = relEvnt->causeDgn[0].causeVal.val; - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "cause:%d\n", ftdmchan->caller_data.hangup_cause); - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "RELEASE COMPLETE did not have a cause code\n"); - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_REQUESTED_CHAN_UNAVAIL; - } - - sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - - } else { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "RELEASE was for previous call (suInstId:%u spInstId:%u)\n", suInstId, spInstId); - } - break; - case FTDM_CHANNEL_STATE_COLLECT: - case FTDM_CHANNEL_STATE_GET_CALLERID: - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); - break; - case FTDM_CHANNEL_STATE_TERMINATING: - if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE) && - sngisdn_info->glare.suInstId != suInstId) { - /* This release if for the outbound call that we already started clearing */ - - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Received RELEASE for local glared call\n"); - sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT); - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Received release before we could clear local call\n"); - /* FS core took too long to respond to the SIG STOP event */ - sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT); - /* set abort flag so that we do not transmit another release complete on this channel once FS core is done */ - } - break; - case FTDM_CHANNEL_STATE_RESET: - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing RELEASE but channel in RESET state, ignoring\n"); - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RELEASE in an invalid state (%s)\n", - ftdm_channel_state2str(ftdmchan->state)); - break; - } - - - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; -} - -void sngisdn_process_dat_ind (sngisdn_event_data_t *sngisdn_event) -{ - int16_t suId = sngisdn_event->suId; - uint32_t suInstId = sngisdn_event->suInstId; - uint32_t spInstId = sngisdn_event->spInstId; - - sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - /* Function does not require any info from infoEvnt struct for now */ - /* InfoEvnt *infoEvnt = &sngisdn_event->event.infoEvnt; */ - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing DATA IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; -} - -void sngisdn_process_sshl_ind (sngisdn_event_data_t *sngisdn_event) -{ - int16_t suId = sngisdn_event->suId; - uint32_t suInstId = sngisdn_event->suInstId; - uint32_t spInstId = sngisdn_event->spInstId; - - sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - /* Function does not require any info from ssHlEvnt struct for now */ - /* SsHlEvnt *ssHlEvnt = &sngisdn_event->event.ssHlEvnt; */ - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing SSHL IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; -} - -void sngisdn_process_sshl_cfm (sngisdn_event_data_t *sngisdn_event) -{ - int16_t suId = sngisdn_event->suId; - uint32_t suInstId = sngisdn_event->suInstId; - uint32_t spInstId = sngisdn_event->spInstId; - - sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - /* Function does not require any info from ssHlEvnt struct for now */ - /* SsHlEvnt *ssHlEvnt = &sngisdn_event->event.ssHlEvnt; */ - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing SSHL CFM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; -} - -void sngisdn_process_rmrt_ind (sngisdn_event_data_t *sngisdn_event) -{ - int16_t suId = sngisdn_event->suId; - uint32_t suInstId = sngisdn_event->suInstId; - uint32_t spInstId = sngisdn_event->spInstId; - - sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - /* Function does not require any info from ssHlEvnt struct for now */ - /* RmRtEvnt *rmRtEvnt = &sngisdn_event->event.rmRtEvnt; */ - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing RESUME/RETRIEVE IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; -} - -void sngisdn_process_rmrt_cfm (sngisdn_event_data_t *sngisdn_event) -{ - int16_t suId = sngisdn_event->suId; - uint32_t suInstId = sngisdn_event->suInstId; - uint32_t spInstId = sngisdn_event->spInstId; - - sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - /* Function does not require any info from ssHlEvnt struct for now */ - /* RmRtEvnt *rmRtEvnt = &sngisdn_event->event.rmRtEvnt; */ - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing RESUME/RETRIEVE CFM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; -} - -void sngisdn_process_flc_ind (sngisdn_event_data_t *sngisdn_event) -{ - int16_t suId = sngisdn_event->suId; - uint32_t suInstId = sngisdn_event->suInstId; - uint32_t spInstId = sngisdn_event->spInstId; - - sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - /* Function does not require any info from ssHlEvnt struct for now */ - /* StaEvnt *staEvnt = &sngisdn_event->event.staEvnt; */ - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing FLOW CONTROL IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; -} - -void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event) -{ - int16_t suId = sngisdn_event->suId; - uint32_t suInstId = sngisdn_event->suInstId; - uint32_t spInstId = sngisdn_event->spInstId; - - sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - FacEvnt *facEvnt = &sngisdn_event->event.facEvnt; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing FACILITY IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - - if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - /* If Facility decoding is disabled, we do not care about current call state, just pass event up to user */ - if (facEvnt->facElmt.facStr.pres) { - get_facility_ie_str(ftdmchan, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len-2); - sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_FACILITY); - } - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - switch (ftdmchan->state) { - case FTDM_CHANNEL_STATE_GET_CALLERID: - /* Update the caller ID Name */ - - if (facEvnt->facElmt.facStr.pres) { - char retrieved_str[255]; - - /* return values for "sng_isdn_retrieve_facility_information_following": - If there will be no information following, or fails to decode IE, returns -1 - If there will be no information following, but current FACILITY IE contains a caller name, returns 0 - If there will be information following, returns 1 - */ - - if (sng_isdn_retrieve_facility_caller_name(&facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len, retrieved_str) == 0) { - strcpy(ftdmchan->caller_data.cid_name, retrieved_str); - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Failed to retrieve Caller Name from Facility IE\n"); - } - if (signal_data->facility_timeout) { - /* Cancel facility timeout */ - ftdm_sched_cancel_timer(signal_data->sched, sngisdn_info->timers[SNGISDN_CHAN_TIMER_FACILITY]); - } - } - - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); - break; - case FTDM_CHANNEL_STATE_RING: - /* We received the caller ID Name in FACILITY, but its too late, facility-timeout already occurred */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "FACILITY received, but we already proceeded with call\n"); - break; - case FTDM_CHANNEL_STATE_UP: - { - ftdm_sigmsg_t sigev; - if (facEvnt->facElmt.facStr.pres) { - get_facility_ie_str(ftdmchan, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len-2); - } - memset(&sigev, 0, sizeof(sigev)); - sigev.chan_id = ftdmchan->chan_id; - sigev.span_id = ftdmchan->span_id; - sigev.channel = ftdmchan; - - sigev.event_id = FTDM_SIGEVENT_FACILITY; - ftdm_span_send_signal(ftdmchan->span, &sigev); - } - break; - default: - /* We do not support other FACILITY types for now, so do nothing */ - break; - } - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; -} - -void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event) -{ - int16_t suId = sngisdn_event->suId; - uint32_t suInstId = sngisdn_event->suInstId; - uint32_t spInstId = sngisdn_event->spInstId; - sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - - StaEvnt *staEvnt = &sngisdn_event->event.staEvnt; - - uint8_t call_state = 0; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - if (!suInstId && !spInstId) { - /* We already cleared this call */ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Dropping STATUS CONFIRM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - return; - } - - if (staEvnt->callSte.eh.pres && staEvnt->callSte.callGlblSte.pres) { - call_state = staEvnt->callSte.callGlblSte.val; - } - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing STATUS CONFIRM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - - ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n"); - - if (staEvnt->causeDgn[0].eh.pres && staEvnt->causeDgn[0].causeVal.pres) { - if (staEvnt->callSte.eh.pres && staEvnt->callSte.callGlblSte.pres) { - call_state = staEvnt->callSte.callGlblSte.val; - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Received STATUS without call state\n"); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - switch (staEvnt->causeDgn[0].causeVal.val) { - case FTDM_CAUSE_RESPONSE_TO_STATUS_ENQUIRY: - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Status Check OK:%d", call_state); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - case FTDM_CAUSE_WRONG_CALL_STATE: - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Message incompatible with call state (call_state:%d channel-state:%s cause:%d) (suId:%u suInstId:%u spInstId:%u)\n", call_state, ftdm_channel_state2str(ftdmchan->state), staEvnt->causeDgn[0].causeVal.val, suId, suInstId, spInstId); - break; - case FTDM_CAUSE_RECOVERY_ON_TIMER_EXPIRE: - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Recovery on timer expire (call_state:%d channel-state:%s cause:%d) (suId:%u suInstId:%u spInstId:%u)\n", call_state, ftdm_channel_state2str(ftdmchan->state), staEvnt->causeDgn[0].causeVal.val, suId, suInstId, spInstId); - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "STATUS CONFIRM (call_state:%d channel-state:%s cause:%d) (suId:%u suInstId:%u spInstId:%u)\n", call_state, ftdm_channel_state2str(ftdmchan->state), staEvnt->causeDgn[0].causeVal.val, suId, suInstId, spInstId); - break; - } - - /* Section 4.3.30 from INT Interface - Service Definition */ - ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val; - - switch(call_state) { - /* Sere ITU-T Q931 for definition of call states */ - case 0: /* Remote switch thinks there are no calls on this channel */ - if (sngisdn_bring_down(ftdmchan) != FTDM_SUCCESS) { - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state)); - } - break; - case 1: - switch (ftdmchan->state) { - case FTDM_CHANNEL_STATE_UP: - /* Remote side is still waiting for our CONNECT message */ - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "delayed_connect", 1, sngisdn_delayed_connect, (void*) sngisdn_info, NULL); - break; - } - /* Fall-through */ - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state)); - break; - } - break; - case 2: /* overlap sending */ - switch (ftdmchan->state) { - case FTDM_CHANNEL_STATE_COLLECT: - /* T302 Timeout reached */ - /* Send the call to user, and see if they accept it */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "T302 Timer expired, proceeding with call\n"); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); - break; - case FTDM_CHANNEL_STATE_PROCEED: - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_RINGING: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Remote switch expecting OVERLAP receive, but we are already PROCEEDING\n"); - sngisdn_snd_disconnect(ftdmchan); - break; - case FTDM_CHANNEL_STATE_DOWN: - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - /* We hung up locally, but remote switch doesn't know send disconnect again*/ - sngisdn_snd_disconnect(ftdmchan); - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state)); - break; - } - break; - case 3: - switch (ftdmchan->state) { - case FTDM_CHANNEL_STATE_PROCEED: - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_RINGING: - /* T310 timer has expired */ - ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val; - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "T310 Timer expired, hanging up call\n"); - sngisdn_set_flag(sngisdn_info, FLAG_SEND_DISC); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - - break; - case FTDM_CHANNEL_STATE_UP: - /* Remote side is still waiting for our CONNECT message */ - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "delayed_connect", 1, sngisdn_delayed_connect, (void*) sngisdn_info, NULL); - break; - } - /* Fall-through */ - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state)); - break; - } - break; - case 8: /* Remote switch is in "Connect Request state" */ - switch (ftdmchan->state) { - case FTDM_CHANNEL_STATE_UP: - /* This is ok. We sent a Connect, and we are waiting for a connect ack */ - /* Do nothing */ - break; - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - /* We hung up locally, but remote switch doesn't know send disconnect again*/ - sngisdn_snd_disconnect(ftdmchan); - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state)); - break; - } - break; - case 9: /* Remote switch is in "Incoming call proceeding" state */ - switch (ftdmchan->state) { - case FTDM_CHANNEL_STATE_RINGING: - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - case FTDM_CHANNEL_STATE_GET_CALLERID: - /* Do nothing */ - break; - case FTDM_CHANNEL_STATE_UP: - /* Remote switch missed our CONNECT message, re-send */ - ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "delayed_connect", 1, sngisdn_delayed_connect, (void*) sngisdn_info, NULL); - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state)); - break; - } - break; - case 10: /* Remote switch is in active state */ - switch (ftdmchan->state) { - case FTDM_CHANNEL_STATE_UP: - /* This is ok, they are in active state and we are in active state */ - /* Do nothing */ - break; - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - /* We sent a disconnect message, but remote side missed it ? */ - ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "delayed_disconnect", 1, sngisdn_delayed_disconnect, (void*) sngisdn_info, NULL); - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state)); - break; - } - break; - case 12: /* We received a disconnect indication */ - switch (ftdmchan->state) { - case FTDM_CHANNEL_STATE_TERMINATING: - /* We are already waiting for user app to handle the disconnect, do nothing */ - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state)); - break; - } - break; - case 22: - switch (ftdmchan->state) { - case FTDM_CHANNEL_STATE_UP: - /* Stack is in the process of clearing the call*/ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - break; - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - /* Do nothing as we will get a RELEASE COMPLETE */ - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state)); - //ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - break; - } - break; - case 25: /* Overlap receiving */ - switch (ftdmchan->state) { - case FTDM_CHANNEL_STATE_COLLECT: - /* T302 Timeout reached */ - /* Send the call to user, and see if they accept it */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "T302 Timer expired, proceeding with call\n"); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state)); - //ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - break; - } - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state)); - //ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - break; - } - } - - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; -} - - -void sngisdn_process_srv_ind (sngisdn_event_data_t *sngisdn_event) -{ - int16_t suId = sngisdn_event->suId; - int16_t dChan = sngisdn_event->dChan; - uint8_t ces = sngisdn_event->ces; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - /* Function does not require any info from ssHlEvnt struct for now */ - /*Srv *srvEvnt = &sngisdn_event->event.srvEvnt;*/ - - ftdm_log(FTDM_LOG_DEBUG, "Processing SERVICE IND (suId:%u dChan:%d ces:%d)\n", suId, dChan, ces); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; -} - -void sngisdn_process_srv_cfm (sngisdn_event_data_t *sngisdn_event) -{ - int16_t suId = sngisdn_event->suId; - int16_t dChan = sngisdn_event->dChan; - uint8_t ces = sngisdn_event->ces; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - /* Function does not require any info from ssHlEvnt struct for now */ - /*Srv *srvEvnt = &sngisdn_event->event.srvEvnt;*/ - - ftdm_log(FTDM_LOG_DEBUG, "Processing SERVICE CFM (suId:%u dChan:%d ces:%d)\n", suId, dChan, ces); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; -} - -static ftdm_status_t sngisdn_bring_down(ftdm_channel_t *ftdmchan) -{ - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data; - ftdm_status_t status = FTDM_SUCCESS; - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Bringing channel to DOWN state (%s)\n", ftdm_channel_state2str(ftdmchan->state)); - switch (ftdmchan->state) { - case FTDM_CHANNEL_STATE_DOWN: - /* Do nothing */ - break; - case FTDM_CHANNEL_STATE_RESET: - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - break; - case FTDM_CHANNEL_STATE_COLLECT: - case FTDM_CHANNEL_STATE_DIALING: - case FTDM_CHANNEL_STATE_UP: - sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - break; - case FTDM_CHANNEL_STATE_TERMINATING: - /* We are already waiting for usr to respond to SIGEVENT stop. - FreeTDM already scheduled a timout in case the User does respond to - SIGEVENT_STOP, no need to do anything here */ - break; - case FTDM_CHANNEL_STATE_HANGUP: - /* This cannot happen, state_advance always sets - ftdmchan to STATE_HANGUP_COMPLETE when in STATE_HANGUP - and we called check_for_state_change earlier so something is very wrong here!!! */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "How can we we in FTDM_CHANNEL_STATE_HANGUP after checking for state change?\n"); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - break; - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - /* We were waiting for remote switch to send RELEASE COMPLETE - but this will not happen, so just clear local state */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - break; - default: - status = FTDM_FAIL; - - } - return status; -} - -void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event) -{ - ftdm_signaling_status_t sigstatus; - int16_t suId = sngisdn_event->suId; - int16_t dChan = sngisdn_event->dChan; - uint8_t ces = sngisdn_event->ces; - uint8_t evntType = sngisdn_event->evntType; - uint8_t chan_no = 0; - Rst *rstEvnt = &sngisdn_event->event.rstEvnt; - - sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[dChan]; - if (!signal_data) { - ftdm_log(FTDM_LOG_CRIT, "Received RESTART CFM on unconfigured span (suId:%d)\n", suId); - return; - } - - ftdm_log(FTDM_LOG_DEBUG, "%s: Processing RESTART CFM (suId:%u dChan:%d ces:%d %s(%d))\n", - signal_data->ftdm_span->name, - suId, dChan, ces, - (evntType == IN_LNK_DWN)?"LNK_DOWN": - (evntType == IN_LNK_UP)?"LNK_UP": - (evntType == IN_INDCHAN)?"b-channel": - (evntType == IN_LNK_DWN_DM_RLS)?"NFAS service procedures": - (evntType == IN_SWCHD_BU_DCHAN)?"NFAS switchover to backup":"Unknown", evntType); - - if (rstEvnt->rstInd.eh.pres == PRSNT_NODEF && rstEvnt->rstInd.rstClass.pres == PRSNT_NODEF) { - switch(rstEvnt->rstInd.rstClass.val) { - case IN_CL_INDCHAN: /* Indicated b-channel */ - if (rstEvnt->chanId.eh.pres) { - if (rstEvnt->chanId.intType.val == IN_IT_BASIC) { - if (rstEvnt->chanId.infoChanSel.pres == PRSNT_NODEF) { - chan_no = rstEvnt->chanId.infoChanSel.val; - } - } else if (rstEvnt->chanId.intType.val == IN_IT_OTHER) { - if (rstEvnt->chanId.chanNmbSlotMap.pres == PRSNT_NODEF) { - chan_no = rstEvnt->chanId.chanNmbSlotMap.val[0]; - } - } - - if (signal_data->nfas.trunk) { - if (!rstEvnt->chanId.intIdent.pres) { - ftdm_log(FTDM_LOG_CRIT, "Failed to determine interface from RESTART\n"); - return; - } else if (signal_data->nfas.interface_id != rstEvnt->chanId.intIdent.val) { - /* This RESTART is for another interface */ - return; - } - } - } - if (!chan_no) { - ftdm_log(FTDM_LOG_CRIT, "Failed to determine channel from RESTART\n"); - return; - } - break; - case IN_CL_SNGINT: /* Single interface */ - case IN_CL_ALLINT: /* All interfaces */ - /* In case restart class indicates all interfaces, we will duplicate - this event on each span associated to this d-channel in sngisdn_rcv_rst_cfm, - so treat it as a single interface anyway */ - chan_no = 0; - break; - default: - ftdm_log(FTDM_LOG_CRIT, "Invalid restart indicator class:%d\n", rstEvnt->rstInd.rstClass.val); - return; - } - } - - ftdm_span_get_sig_status(signal_data->ftdm_span, &sigstatus); - if (sigstatus == FTDM_SIG_STATE_DOWN) { - if (chan_no) { /* For a single channel */ - if (chan_no > ftdm_span_get_chan_count(signal_data->ftdm_span)) { - ftdm_log(FTDM_LOG_CRIT, "Received RESTART on invalid channel:%d\n", chan_no); - } else { - ftdm_channel_t *ftdmchan = ftdm_span_get_channel(signal_data->ftdm_span, chan_no); - sngisdn_bring_down(ftdmchan); - } - } else { /* for all channels */ - ftdm_iterator_t *chaniter = NULL; - ftdm_iterator_t *curr = NULL; - - chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL); - for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { - sngisdn_bring_down((ftdm_channel_t*)ftdm_iterator_current(curr)); - } - ftdm_iterator_free(chaniter); - } - } - - ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART CFM (suId:%u dChan:%d ces:%d type:%d)\n", suId, dChan, ces, evntType); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; -} - - -/* The remote side sent us a RESTART Msg. Trillium automatically acks with RESTART ACK, but - we need to clear our call states if there is a call on this channel */ -void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event) -{ - uint8_t chan_no = 0; - int16_t suId = sngisdn_event->suId; - int16_t dChan = sngisdn_event->dChan; - uint8_t ces = sngisdn_event->ces; - uint8_t evntType = sngisdn_event->evntType; - Rst *rstEvnt = NULL; - sngisdn_span_data_t *signal_data = NULL; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - rstEvnt = &sngisdn_event->event.rstEvnt; - - signal_data = g_sngisdn_data.spans[dChan]; - - if (!signal_data) { - ftdm_log(FTDM_LOG_CRIT, "Received RESTART IND on unconfigured span (suId:%d)\n", suId); - return; - } - - if (signal_data->restart_timeout) { - ftdm_sched_cancel_timer(signal_data->sched, signal_data->timers[SNGISDN_SPAN_TIMER_RESTART]); - } - - ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART IND (suId:%u dChan:%d ces:%d %s(%d))\n", suId, dChan, ces, - (evntType == IN_LNK_DWN)?"LNK_DOWN": - (evntType == IN_LNK_UP)?"LNK_UP": - (evntType == IN_INDCHAN)?"b-channel": - (evntType == IN_LNK_DWN_DM_RLS)?"NFAS service procedures": - (evntType == IN_SWCHD_BU_DCHAN)?"NFAS switchover to backup":"Unknown", evntType); - - if (rstEvnt->rstInd.eh.pres == PRSNT_NODEF && rstEvnt->rstInd.rstClass.pres == PRSNT_NODEF) { - switch(rstEvnt->rstInd.rstClass.val) { - case IN_CL_INDCHAN: /* Indicated b-channel */ - if (rstEvnt->chanId.eh.pres) { - if (rstEvnt->chanId.intType.val == IN_IT_BASIC) { - if (rstEvnt->chanId.infoChanSel.pres == PRSNT_NODEF) { - chan_no = rstEvnt->chanId.infoChanSel.val; - } - } else if (rstEvnt->chanId.intType.val == IN_IT_OTHER) { - if (rstEvnt->chanId.chanNmbSlotMap.pres == PRSNT_NODEF) { - chan_no = rstEvnt->chanId.chanNmbSlotMap.val[0]; - } - } - - if (signal_data->nfas.trunk) { - if (!rstEvnt->chanId.intIdent.pres) { - ftdm_log(FTDM_LOG_CRIT, "Failed to determine interface from RESTART\n"); - return; - } else if (signal_data->nfas.interface_id != rstEvnt->chanId.intIdent.val) { - /* This RESTART is for another interface */ - return; - } - } - } - if (!chan_no) { - ftdm_log(FTDM_LOG_CRIT, "Failed to determine channel from RESTART\n"); - return; - } - break; - case IN_CL_SNGINT: /* Single interface */ - case IN_CL_ALLINT: /* All interfaces */ - /* In case restart class indicates all interfaces, we will duplicated - this event on each span associated to this d-channel in sngisdn_rcv_rst_cfm, - so treat it as a single interface anyway */ - chan_no = 0; - break; - default: - ftdm_log(FTDM_LOG_CRIT, "Invalid restart indicator class:%d\n", rstEvnt->rstInd.rstClass.val); - return; - } - } - - if (chan_no) { /* For a single channel */ - ftdm_iterator_t *chaniter = NULL; - ftdm_iterator_t *curr = NULL; - - chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL); - for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { - ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr); - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; - if (sngisdn_info->ces == ces && ftdmchan->physical_chan_id == chan_no) { - sngisdn_bring_down(ftdmchan); - } - } - ftdm_iterator_free(chaniter); - } else { /* for all channels */ - ftdm_iterator_t *chaniter = NULL; - ftdm_iterator_t *curr = NULL; - - chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL); - for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { - ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr); - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; - if (sngisdn_info->ces == ces) { - sngisdn_bring_down(ftdmchan); - } - } - ftdm_iterator_free(chaniter); - } - - - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; -} - -static ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn) -{ - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - if (signal_data->ignore_cause_value == SNGISDN_OPT_TRUE) { - return FTDM_FAIL; - } - - /* By default, we only evaluate cause value on 5ESS switches */ - if (signal_data->ignore_cause_value == SNGISDN_OPT_DEFAULT && - signal_data->switchtype != SNGISDN_SWITCH_5ESS) { - - return FTDM_FAIL; - } - - /* ignore_cause_value = SNGISDN_OPT_FALSE or switchtype == 5ESS */ - switch(causeDgn->causeVal.val) { - case 17: /* User Busy */ - case 18: /* No User responding */ - case 19: /* User alerting, no answer */ - case 21: /* Call rejected, the called party does not with to accept this call */ - case 27: /* Destination out of order */ - case 31: /* Normal, unspecified */ - case 34: /* Circuit/Channel congestion */ - case 41: /* Temporary failure */ - case 42: /* Switching equipment is experiencing a period of high traffic */ - case 47: /* Resource unavailable */ - case 58: /* Bearer Capability not available */ - case 63: /* Service or option not available */ - case 65: /* Bearer Cap not implemented, not supported */ - case 79: /* Service or option not implemented, unspecified */ - return FTDM_SUCCESS; - } - return FTDM_FAIL; -} diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c deleted file mode 100644 index 9fc8ad1d82..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ /dev/null @@ -1,588 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * David Yat Sin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ftmod_sangoma_isdn.h" - -void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) -{ - ConEvnt conEvnt; - sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID}; - - ftdm_assert((!sngisdn_info->suInstId && !sngisdn_info->spInstId), "Trying to call out, but call data was not cleared\n"); - - sngisdn_info->suInstId = get_unique_suInstId(signal_data->cc_id); - sngisdn_info->spInstId = 0; - - ftdm_mutex_lock(g_sngisdn_data.ccs[signal_data->cc_id].mutex); - g_sngisdn_data.ccs[signal_data->cc_id].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info; - ftdm_mutex_unlock(g_sngisdn_data.ccs[signal_data->cc_id].mutex); - - memset(&conEvnt, 0, sizeof(conEvnt)); - if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN || signal_data->force_sending_complete == SNGISDN_OPT_TRUE) { - conEvnt.sndCmplt.eh.pres = PRSNT_NODEF; - } - - if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP && - signal_data->signalling == SNGISDN_SIGNALING_NET) { - sngisdn_info->ces = CES_MNGMNT; - } - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Outgoing call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits); - - set_chan_id_ie(ftdmchan, &conEvnt.chanId); - set_bear_cap_ie(ftdmchan, &conEvnt.bearCap[0]); - set_called_num(ftdmchan, &conEvnt.cdPtyNmb); - set_calling_num(ftdmchan, &conEvnt.cgPtyNmb); - set_calling_num2(ftdmchan, &conEvnt.cgPtyNmb2); - set_calling_subaddr(ftdmchan, &conEvnt.cgPtySad); - set_called_subaddr(ftdmchan, &conEvnt.cdPtySad); - set_redir_num(ftdmchan, &conEvnt.redirNmb); - set_calling_name(ftdmchan, &conEvnt); - set_network_specific_fac(ftdmchan, &conEvnt.netFac[0]); - - /* set_facility_ie will overwrite Calling Name for NI-2 if user specifies custom Facility IE */ - set_facility_ie(ftdmchan, &conEvnt.facilityStr); - set_prog_ind_ie(ftdmchan, &conEvnt.progInd, prog_ind); - - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces); - - if (sng_isdn_con_request(signal_data->cc_id, sngisdn_info->suInstId, &conEvnt, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused SETUP request\n"); - } - - return; -} - -/* Unsed only for overlap receive */ -void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan) -{ - CnStEvnt cnStEvnt; - - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending SETUP ACK , but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); - sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - return; - } - - memset(&cnStEvnt, 0, sizeof(cnStEvnt)); - - - - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP ACK (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces); - - if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, MI_SETUPACK, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused SETUP ACK request\n"); - } - return; -} - - -/* Used only for BRI PTMP - This function is used when the NT side makes a call out, - and one or multiple TE's reply, then NT assigns the call by sending a con_complete*/ -void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan) -{ - CnStEvnt cnStEvnt; - - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending CONNECT COMPL , but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); - sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - return; - } - - memset(&cnStEvnt, 0, sizeof(cnStEvnt)); - - /* Indicate channel ID only in first response */ - if (!ftdm_test_flag(sngisdn_info, FLAG_SENT_CHAN_ID)) { - set_chan_id_ie(ftdmchan, &cnStEvnt.chanId); - } - - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT COMPL (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces); - - if(sng_isdn_con_comp(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused CONNECT ACK request\n"); - } - return; -} - - -void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind) -{ - CnStEvnt cnStEvnt; - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - if (sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) { - return; - } - sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED); - - if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending PROGRESS, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); - sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - return; - } - - memset(&cnStEvnt, 0, sizeof(cnStEvnt)); - - /* Indicate channel ID only in first response */ - if (!ftdm_test_flag(sngisdn_info, FLAG_SENT_CHAN_ID)) { - set_chan_id_ie(ftdmchan, &cnStEvnt.chanId); - } - set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind); - set_facility_ie(ftdmchan, &cnStEvnt.facilityStr); - - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROCEED (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces); - - if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, MI_CALLPROC, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused PROCEED request\n"); - } - return; -} - -void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind) -{ - CnStEvnt cnStEvnt; - - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending PROGRESS, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); - sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - return; - } - - if (signal_data->switchtype == SNGISDN_SWITCH_INSNET) { - /* Trillium Q931 layer complains of invalid event when receiving PROGRESS in - INSNET variant, so PROGRESS event is probably invalid */ - return; - } - - memset(&cnStEvnt, 0, sizeof(cnStEvnt)); - set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind); - set_facility_ie(ftdmchan, &cnStEvnt.facilityStr); - - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROGRESS (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces); - if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_PROGRESS, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused PROGRESS request\n"); - } - return; -} - -void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind) -{ - CnStEvnt cnStEvnt; - - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending ALERT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); - sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - return; - } - - memset(&cnStEvnt, 0, sizeof(cnStEvnt)); - - set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind); - set_facility_ie(ftdmchan, &cnStEvnt.facilityStr); - - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending ALERT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces); - - if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_ALERTING, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused ALERT request\n"); - } - return; -} - -void sngisdn_snd_connect(ftdm_channel_t *ftdmchan) -{ - CnStEvnt cnStEvnt; - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN}; - - if (sngisdn_test_flag(sngisdn_info, FLAG_SENT_CONNECT)) { - return; - } - sngisdn_set_flag(sngisdn_info, FLAG_SENT_CONNECT); - - if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending CONNECT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); - sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - return; - } - - memset(&cnStEvnt, 0, sizeof(cnStEvnt)); - - /* Indicate channel ID only in first response */ - if (!ftdm_test_flag(sngisdn_info, FLAG_SENT_CHAN_ID)) { - set_chan_id_ie(ftdmchan, &cnStEvnt.chanId); - } - set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind); - set_facility_ie(ftdmchan, &cnStEvnt.facilityStr); - - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces); - if (sng_isdn_con_response(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused CONNECT request\n"); - } - return; -} - -void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan) -{ - FacEvnt facEvnt; - - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - if (!sngisdn_info->suInstId) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending FACILITY, but no call data, ignoring (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); - return; - } - - memset(&facEvnt, 0, sizeof(facEvnt)); - - if (set_facility_ie_str(ftdmchan, &facEvnt.facElmt.facStr.val[2], (uint8_t*)&facEvnt.facElmt.facStr.len) != FTDM_SUCCESS) { - /* No point in sending a FACILITY message if there is no Facility IE to transmit */ - return; - } - - facEvnt.facElmt.eh.pres = PRSNT_NODEF; - facEvnt.facElmt.facStr.pres = PRSNT_NODEF; - facEvnt.facElmt.facStr.val[0] = 0x1C; - facEvnt.facElmt.facStr.val[1] = (uint8_t)facEvnt.facElmt.facStr.len; - facEvnt.facElmt.facStr.len +=2; /* Need to include the size of identifier + len */ - - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending FACILITY (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces); - - if (sng_isdn_facility_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &facEvnt, MI_FACIL, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused FACILITY request\n"); - } - return; -} - -/* This is used to request Q.921 to initiate link establishment */ -void sngisdn_snd_dl_req(ftdm_channel_t *ftdmchan) -{ - CnStEvnt cnStEvnt; - - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - memset(&cnStEvnt, 0, sizeof(cnStEvnt)); - - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Requesting Link establishment (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces); - - if (sng_isdn_con_status(signal_data->cc_id, 0, 0, &cnStEvnt, MI_INFO, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused Link establishment\n"); - } - return; -} - -void sngisdn_snd_notify_req(ftdm_channel_t *ftdmchan) -{ - CnStEvnt cnStEvnt; - - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending NOTIFY, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); - sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - return; - } - - memset(&cnStEvnt, 0, sizeof(cnStEvnt)); - - set_not_ind_ie(ftdmchan, &cnStEvnt.notInd); - - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending NOTIFY (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces); - - if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_NOTIFY, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused NOTIFY request\n"); - } - return; -} - - -void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan) -{ - StaEvnt staEvnt; - - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - //ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending STATUS ENQ\n"); - - memset(&staEvnt, 0, sizeof(StaEvnt)); - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending Status ENQ on suId:%d suInstId:%u spInstId:%d dchan:%d ces:%d\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces); - if (sng_isdn_status_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &staEvnt, MI_STATENQ)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused Status ENQ request\n"); - } - return; -} - - -void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan) -{ - DiscEvnt discEvnt; - - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending DISCONNECT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); - - sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); - return; - } - - memset(&discEvnt, 0, sizeof(discEvnt)); - - set_cause_ie(ftdmchan, &discEvnt.causeDgn[0]); - set_facility_ie(ftdmchan, &discEvnt.facilityStr); - set_user_to_user_ie(ftdmchan, &discEvnt.usrUsr); - - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); - if (sng_isdn_disc_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &discEvnt)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused DISCONNECT request\n"); - } - return; -} - -void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare) -{ - RelEvnt relEvnt; - uint32_t suInstId, spInstId; - - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - if (!sngisdn_info->suInstId) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending RELEASE, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); - - sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); - return; - } - - memset(&relEvnt, 0, sizeof(relEvnt)); - - /* Fill relEvnt here */ - relEvnt.causeDgn[0].eh.pres = PRSNT_NODEF; - relEvnt.causeDgn[0].location.pres = PRSNT_NODEF; - relEvnt.causeDgn[0].location.val = IN_LOC_PRIVNETLU; - relEvnt.causeDgn[0].codeStand3.pres = PRSNT_NODEF; - relEvnt.causeDgn[0].codeStand3.val = IN_CSTD_CCITT; - - relEvnt.causeDgn[0].causeVal.pres = PRSNT_NODEF; - relEvnt.causeDgn[0].causeVal.val = ftdmchan->caller_data.hangup_cause; - relEvnt.causeDgn[0].recommend.pres = NOTPRSNT; - relEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT; - - if (glare) { - suInstId = sngisdn_info->glare.suInstId; - spInstId = sngisdn_info->glare.spInstId; - } else { - suInstId = sngisdn_info->suInstId; - spInstId = sngisdn_info->spInstId; - } - - set_facility_ie(ftdmchan, &relEvnt.facilityStr); - - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RELEASE/RELEASE COMPLETE (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, suInstId, spInstId); - - if (glare) { - if (sng_isdn_release_request(signal_data->cc_id, suInstId, spInstId, &relEvnt)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused RELEASE/RELEASE COMPLETE request\n"); - } - } else { - if (sng_isdn_release_request(signal_data->cc_id, suInstId, spInstId, &relEvnt)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused RELEASE/RELEASE COMPLETE request\n"); - } - } - return; -} - -void sngisdn_snd_restart(ftdm_channel_t *ftdmchan) -{ - Rst rstEvnt; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - memset(&rstEvnt, 0, sizeof(rstEvnt)); - - set_chan_id_ie(ftdmchan, &rstEvnt.chanId); - set_restart_ind_ie(ftdmchan, &rstEvnt.rstInd); - - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RESTART (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_dchan(signal_data)->link_id, CES_MNGMNT); - - if (sng_isdn_restart_request(signal_data->cc_id, &rstEvnt, sngisdn_dchan(signal_data)->link_id, CES_MNGMNT, IN_SND_RST)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused RESTART request\n"); - } - return; -} - - -/* We received an incoming frame on the d-channel, send data to the stack */ -void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len) -{ - sng_l1_frame_t l1_frame; - ftdm_alarm_flag_t alarmbits = 0; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) dchan->span->signal_data; - - ftdm_channel_get_alarms(dchan, &alarmbits); - - if (alarmbits) { - ftdm_log_chan_msg(dchan, FTDM_LOG_WARNING, "Dropping incoming data due to L1 alarm\n"); - return; - } - - if (len > sizeof(l1_frame.data)) { - ftdm_log_chan(dchan, FTDM_LOG_ERROR, "Received frame of %"FTDM_SIZE_FMT" bytes, exceeding max size of %"FTDM_SIZE_FMT" bytes\n", - len, sizeof(l1_frame.data)); - return; - } - if (len <= 2) { - return; - } - - memset(&l1_frame, 0, sizeof(l1_frame)); - l1_frame.len = len; - - memcpy(&l1_frame.data, data, len); - - if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC)) { - l1_frame.flags |= SNG_L1FRAME_ERROR_CRC; - } - - if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME)) { - l1_frame.flags |= SNG_L1FRAME_ERROR_FRAME; - } - - if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT)) { - l1_frame.flags |= SNG_L1FRAME_ERROR_ABORT; - } - - if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO)) { - l1_frame.flags |= SNG_L1FRAME_ERROR_FIFO; - } - - if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA)) { - l1_frame.flags |= SNG_L1FRAME_ERROR_DMA; - } - - if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)) { - /* Should we trigger congestion here? */ - l1_frame.flags |= SNG_L1FRAME_QUEUE_THRES; - } - - if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)) { - /* Should we trigger congestion here? */ - l1_frame.flags |= SNG_L1FRAME_QUEUE_FULL; - } -#if 0 - if (1) { - int i; - char string [2000]; - unsigned string_len = 0; - for (i = 0; i < l1_frame.len; i++) { - string_len += sprintf(&string[string_len], "0x%02x ", l1_frame.data[i]); - } - - ftdm_log_chan(dchan, FTDM_LOG_CRIT, "\nL1 RX [%s] flags:%x\n", string, l1_frame.flags); - } -#endif - sng_isdn_data_ind(signal_data->link_id, &l1_frame); -} - -void sngisdn_snd_event(sngisdn_span_data_t *signal_data, ftdm_oob_event_t event) -{ - sng_l1_event_t l1_event; - - if (!signal_data->dchan) { - return; - } - memset(&l1_event, 0, sizeof(l1_event)); - - switch(event) { - case FTDM_OOB_ALARM_CLEAR: - l1_event.type = SNG_L1EVENT_ALARM_OFF; - sng_isdn_event_ind(signal_data->link_id, &l1_event); - - if (!signal_data->dl_request_pending) { - signal_data->dl_request_pending = 1; - ftdm_sched_timer(signal_data->sched, "delayed_dl_req", 8000, sngisdn_delayed_dl_req, (void*) signal_data, NULL); - } - break; - case FTDM_OOB_ALARM_TRAP: - l1_event.type = SNG_L1EVENT_ALARM_ON; - sng_isdn_event_ind(signal_data->link_id, &l1_event); - break; - default: - /* We do not care about the other OOB events for now */ - return; - } - return; -} - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c deleted file mode 100644 index e5bebb1c8b..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c +++ /dev/null @@ -1,1134 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * David Yat Sin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ftmod_sangoma_isdn.h" -//static void sngisdn_rcv_q931_ind_span(sngisdn_span_data_t *signal_data, InMngmt *status); - -void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces) -{ - uint8_t bchan_no = 0; - int8_t interface_id = -1; /* Specifies which interface for NFAS */ - sngisdn_chan_data_t *sngisdn_info = NULL; - sngisdn_event_data_t *sngisdn_event = NULL; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Ind on unconfigured cc\n"); - ftdm_assert(g_sngisdn_data.spans[dChan], "Con Ind on unconfigured dchan\n"); - - if (conEvnt->chanId.eh.pres != PRSNT_NODEF) { - /* TODO: Implement me */ - ftdm_log(FTDM_LOG_ERROR, "Incoming call without Channel Id not supported yet\n"); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - if (conEvnt->chanId.chanNmbSlotMap.pres) { - bchan_no = conEvnt->chanId.chanNmbSlotMap.val[0]; - } else if (conEvnt->chanId.infoChanSel.pres) { - bchan_no = conEvnt->chanId.infoChanSel.val; - } - - if (conEvnt->chanId.intIdent.pres) { - interface_id = conEvnt->chanId.intIdent.val; - } - - if (!bchan_no) { - ftdm_log(FTDM_LOG_ERROR, "Failed to obtain b-channel number from SETUP message\n"); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - if (g_sngisdn_data.spans[dChan]->nfas.trunk) { - if (interface_id < 0) { - ftdm_log(FTDM_LOG_ERROR, "Interface ID not present on NFAS interface\n"); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } else if (!g_sngisdn_data.spans[dChan]->nfas.trunk->spans[interface_id]) { - ftdm_log(FTDM_LOG_ERROR, "NFAS group:%s does not have logical interface %d\n", g_sngisdn_data.spans[dChan]->nfas.trunk->name, interface_id); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } else { - sngisdn_info = g_sngisdn_data.spans[dChan]->nfas.trunk->spans[interface_id]->channels[bchan_no]; - } - } else { - if (g_sngisdn_data.spans[dChan]->channels[bchan_no] == NULL) { - ftdm_log(FTDM_LOG_ERROR, "Incoming call on unconfigured b-channel:%d\n", bchan_no); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - sngisdn_info = g_sngisdn_data.spans[dChan]->channels[bchan_no]; - } - - - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received SETUP (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - - sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); - memset(sngisdn_event, 0, sizeof(*sngisdn_event)); - - sngisdn_event->event_id = SNGISDN_EVENT_CON_IND; - sngisdn_event->sngisdn_info = sngisdn_info; - sngisdn_event->suId = suId; - sngisdn_event->spInstId = spInstId; - sngisdn_event->dChan = dChan; - sngisdn_event->ces = ces; - - ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); - g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info; - ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); - - memcpy(&sngisdn_event->event.conEvnt, conEvnt, sizeof(*conEvnt)); - - ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, int16_t dChan, uint8_t ces) -{ - sngisdn_chan_data_t *sngisdn_info = NULL; - sngisdn_event_data_t *sngisdn_event = NULL; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Cfm on unconfigured cc\n"); - ftdm_assert(g_sngisdn_data.spans[dChan] != 0, "Con Cfm on unconfigured dchan\n"); - - if (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - if (!sngisdn_info->spInstId) { - ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); - - sngisdn_info->spInstId = spInstId; - g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info; - ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); - } - - - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received CONNECT/CONNECT ACK (suId:%u suInstId:%u spInstId:%u ces:%d)\n", suId, suInstId, spInstId, ces); - - sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); - memset(sngisdn_event, 0, sizeof(*sngisdn_event)); - - sngisdn_event->event_id = SNGISDN_EVENT_CON_CFM; - sngisdn_event->sngisdn_info = sngisdn_info; - sngisdn_event->suId = suId; - sngisdn_event->suInstId = suInstId; - sngisdn_event->spInstId = spInstId; - sngisdn_event->dChan = dChan; - sngisdn_event->ces = ces; - memcpy(&sngisdn_event->event.cnStEvnt, cnStEvnt, sizeof(*cnStEvnt)); - - ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, int16_t dChan, uint8_t ces) -{ - sngisdn_chan_data_t *sngisdn_info = NULL; - sngisdn_event_data_t *sngisdn_event = NULL; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Cnst Ind on unconfigured cc\n"); - ftdm_assert(g_sngisdn_data.spans[dChan] != 0, "Cnst Ind on unconfigured dchan\n"); - - if (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - if (!sngisdn_info->spInstId) { - ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); - - sngisdn_info->spInstId = spInstId; - g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info; - ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); - } - - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received %s (suId:%u suInstId:%u spInstId:%u ces:%d)\n", - (evntType == MI_ALERTING)?"ALERT": - (evntType == MI_CALLPROC)?"PROCEED": - (evntType == MI_PROGRESS)?"PROGRESS": - (evntType == MI_SETUPACK)?"SETUP ACK": - (evntType == MI_NOTIFY)?"NOTIFY": - (evntType == MI_INFO)?"INFO":"UNKNOWN", - suId, suInstId, spInstId, ces); - - sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); - memset(sngisdn_event, 0, sizeof(*sngisdn_event)); - - sngisdn_event->event_id = SNGISDN_EVENT_CNST_IND; - sngisdn_event->sngisdn_info = sngisdn_info; - sngisdn_event->suId = suId; - sngisdn_event->suInstId = suInstId; - sngisdn_event->spInstId = spInstId; - sngisdn_event->dChan = dChan; - sngisdn_event->ces = ces; - sngisdn_event->evntType = evntType; - - memcpy(&sngisdn_event->event.cnStEvnt, cnStEvnt, sizeof(*cnStEvnt)); - - ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt) -{ - sngisdn_chan_data_t *sngisdn_info = NULL; - sngisdn_event_data_t *sngisdn_event = NULL; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - ftdm_assert(spInstId != 0, "Received DISCONNECT with invalid id"); - - if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && - !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { - - ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - ftdm_assert(0, "Inconsistent call states\n"); - return; - } - - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received DISCONNECT (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - - sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); - memset(sngisdn_event, 0, sizeof(*sngisdn_event)); - - sngisdn_event->event_id = SNGISDN_EVENT_DISC_IND; - sngisdn_event->sngisdn_info = sngisdn_info; - sngisdn_event->suId = suId; - sngisdn_event->suInstId = suInstId; - sngisdn_event->spInstId = spInstId; - - memcpy(&sngisdn_event->event.discEvnt, discEvnt, sizeof(*discEvnt)); - - ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); - - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -void sngisdn_rcv_rel_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt) -{ - sngisdn_chan_data_t *sngisdn_info = NULL; - sngisdn_event_data_t *sngisdn_event = NULL; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && - !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { - - ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - /* It seems that Trillium has a bug where they sometimes send release twice on a call, so do not crash on these for now */ - /* ftdm_assert(0, "Inconsistent call states\n"); */ - return; - } - - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received RELEASE/RELEASE COMPLETE (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - - sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); - memset(sngisdn_event, 0, sizeof(*sngisdn_event)); - - sngisdn_event->event_id = SNGISDN_EVENT_REL_IND; - sngisdn_event->sngisdn_info = sngisdn_info; - sngisdn_event->suId = suId; - sngisdn_event->suInstId = suInstId; - sngisdn_event->spInstId = spInstId; - - memcpy(&sngisdn_event->event.relEvnt, relEvnt, sizeof(*relEvnt)); - - ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -void sngisdn_rcv_dat_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, InfoEvnt *infoEvnt) -{ - sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event = NULL; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && - !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { - - ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - ftdm_assert(0, "Inconsistent call states\n"); - return; - } - - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received DATA IND suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - - sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); - memset(sngisdn_event, 0, sizeof(*sngisdn_event)); - - sngisdn_event->event_id = SNGISDN_EVENT_DAT_IND; - sngisdn_event->sngisdn_info = sngisdn_info; - sngisdn_event->suId = suId; - sngisdn_event->suInstId = suInstId; - sngisdn_event->spInstId = spInstId; - - memcpy(&sngisdn_event->event.infoEvnt, infoEvnt, sizeof(*infoEvnt)); - - ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -void sngisdn_rcv_sshl_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action) -{ - sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event = NULL; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && - !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { - - ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - ftdm_assert(0, "Inconsistent call states\n"); - return; - } - - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received SSHL IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - - sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); - memset(sngisdn_event, 0, sizeof(*sngisdn_event)); - - sngisdn_event->event_id = SNGISDN_EVENT_SSHL_IND; - sngisdn_event->sngisdn_info = sngisdn_info; - sngisdn_event->suId = suId; - sngisdn_event->suInstId = suInstId; - sngisdn_event->spInstId = spInstId; - sngisdn_event->action = action; - - memcpy(&sngisdn_event->event.ssHlEvnt, ssHlEvnt, sizeof(*ssHlEvnt)); - - ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -void sngisdn_rcv_sshl_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action) -{ - sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event = NULL; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && - !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { - - ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - ftdm_assert(0, "Inconsistent call states\n"); - return; - } - - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received SSHL CFM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - - sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); - memset(sngisdn_event, 0, sizeof(*sngisdn_event)); - - sngisdn_event->event_id = SNGISDN_EVENT_SSHL_CFM; - sngisdn_event->sngisdn_info = sngisdn_info; - sngisdn_event->suId = suId; - sngisdn_event->suInstId = suInstId; - sngisdn_event->spInstId = spInstId; - sngisdn_event->action = action; - - memcpy(&sngisdn_event->event.ssHlEvnt, ssHlEvnt, sizeof(*ssHlEvnt)); - - ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} -void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action) -{ - sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event = NULL; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && - !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { - - ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - ftdm_assert(0, "Inconsistent call states\n"); - return; - } - - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received RMRT IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - - sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); - memset(sngisdn_event, 0, sizeof(*sngisdn_event)); - - sngisdn_event->event_id = SNGISDN_EVENT_RMRT_IND; - sngisdn_event->sngisdn_info = sngisdn_info; - sngisdn_event->suId = suId; - sngisdn_event->suInstId = suInstId; - sngisdn_event->spInstId = spInstId; - sngisdn_event->action = action; - - memcpy(&sngisdn_event->event.rmRtEvnt, rmRtEvnt, sizeof(*rmRtEvnt)); - - ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action) -{ - sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event = NULL; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && - !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { - - ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - ftdm_assert(0, "Inconsistent call states\n"); - return; - } - - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received RESUME/RETRIEVE CFM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - - sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); - memset(sngisdn_event, 0, sizeof(*sngisdn_event)); - - sngisdn_event->event_id = SNGISDN_EVENT_RMRT_CFM; - sngisdn_event->sngisdn_info = sngisdn_info; - sngisdn_event->suId = suId; - sngisdn_event->suInstId = suInstId; - sngisdn_event->spInstId = spInstId; - sngisdn_event->action = action; - - memcpy(&sngisdn_event->event.rmRtEvnt, rmRtEvnt, sizeof(*rmRtEvnt)); - - ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt) -{ - sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event = NULL; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && - !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { - - ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - ftdm_assert(0, "Inconsistent call states\n"); - return; - } - - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received FLOW CONTROL IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - - sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); - memset(sngisdn_event, 0, sizeof(*sngisdn_event)); - - sngisdn_event->event_id = SNGISDN_EVENT_FLC_IND; - sngisdn_event->sngisdn_info = sngisdn_info; - sngisdn_event->suId = suId; - sngisdn_event->suInstId = suInstId; - sngisdn_event->spInstId = spInstId; - - memcpy(&sngisdn_event->event.staEvnt, staEvnt, sizeof(*staEvnt)); - - ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - - -void sngisdn_rcv_fac_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, FacEvnt *facEvnt, uint8_t evntType, int16_t dChan, uint8_t ces) -{ - sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event = NULL; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && - !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { - - ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - ftdm_assert(0, "Inconsistent call states\n"); - return; - } - - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received FACILITY IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); - memset(sngisdn_event, 0, sizeof(*sngisdn_event)); - - sngisdn_event->event_id = SNGISDN_EVENT_FAC_IND; - sngisdn_event->sngisdn_info = sngisdn_info; - sngisdn_event->suId = suId; - sngisdn_event->suInstId = suInstId; - sngisdn_event->spInstId = spInstId; - sngisdn_event->evntType = evntType; - - memcpy(&sngisdn_event->event.facEvnt, facEvnt, sizeof(*facEvnt)); - - ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - - -void sngisdn_rcv_sta_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt) -{ - sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event = NULL; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - if (!suInstId && !spInstId) { - /* This is a response to a sngisdn_snd_info_req - * that was sent to attempt to re-establish DL link */ - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* We sometimes receive a STA CFM after receiving a RELEASE/RELEASE COMPLETE, so we need to lock - here in case we are calling clear_call_data at the same time this function is called */ - - ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); - if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && - !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { - - ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); - return; - } - - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received STATUS CONFIRM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); - - sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); - memset(sngisdn_event, 0, sizeof(*sngisdn_event)); - - sngisdn_event->event_id = SNGISDN_EVENT_STA_CFM; - sngisdn_event->sngisdn_info = sngisdn_info; - sngisdn_event->suId = suId; - sngisdn_event->suInstId = suInstId; - sngisdn_event->spInstId = spInstId; - - memcpy(&sngisdn_event->event.staEvnt, staEvnt, sizeof(*staEvnt)); - - ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); - ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -void sngisdn_rcv_srv_ind (int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces) -{ - - sngisdn_span_data_t *signal_data; - sngisdn_event_data_t *sngisdn_event = NULL; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - ftdm_log(FTDM_LOG_INFO, "Received SERVICE IND (dChan:%d ces:%u)\n", dChan, ces); - - signal_data = g_sngisdn_data.spans[dChan]; - - if (signal_data->nfas.trunk) { - unsigned i; - for (i = 0; i < signal_data->nfas.trunk->num_spans; i++) { - sngisdn_span_data_t *my_signal_data = signal_data->nfas.trunk->spans[i]; - - sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); - memset(sngisdn_event, 0, sizeof(*sngisdn_event)); - sngisdn_event->event_id = SNGISDN_EVENT_SRV_IND; - sngisdn_event->suId = suId; - sngisdn_event->dChan = dChan; - sngisdn_event->ces = ces; - sngisdn_event->signal_data = my_signal_data; - memcpy(&sngisdn_event->event.srvEvnt, srvEvnt, sizeof(*srvEvnt)); - ftdm_queue_enqueue(my_signal_data->event_queue, sngisdn_event); - } - } else { - ftdm_queue_enqueue(signal_data->event_queue, sngisdn_event); - } - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - - -void sngisdn_rcv_srv_cfm (int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces) -{ - sngisdn_span_data_t *signal_data = NULL; - sngisdn_event_data_t *sngisdn_event = NULL; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - ftdm_log(FTDM_LOG_INFO, "Received SERVICE CFM (dChan:%d ces:%u)\n", dChan, ces); - - signal_data = g_sngisdn_data.spans[dChan]; - - if (signal_data->nfas.trunk) { - unsigned i; - for (i = 0; i < signal_data->nfas.trunk->num_spans; i++) { - sngisdn_span_data_t *my_signal_data = signal_data->nfas.trunk->spans[i]; - - sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); - memset(sngisdn_event, 0, sizeof(*sngisdn_event)); - sngisdn_event->event_id = SNGISDN_EVENT_SRV_CFM; - sngisdn_event->suId = suId; - sngisdn_event->dChan = dChan; - sngisdn_event->ces = ces; - sngisdn_event->signal_data = my_signal_data; - memcpy(&sngisdn_event->event.srvEvnt, srvEvnt, sizeof(*srvEvnt)); - ftdm_queue_enqueue(my_signal_data->event_queue, sngisdn_event); - } - } else { - ftdm_queue_enqueue(signal_data->event_queue, sngisdn_event); - } - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -void sngisdn_rcv_rst_ind (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType) -{ - sngisdn_span_data_t *signal_data = NULL; - sngisdn_event_data_t *sngisdn_event = NULL; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - ftdm_log(FTDM_LOG_INFO, "Received RESTART IND (dChan:%d ces:%u type:%u)\n", dChan, ces, evntType); - - signal_data = g_sngisdn_data.spans[dChan]; - - if (signal_data->nfas.trunk) { - unsigned i; - for (i = 0; i < signal_data->nfas.trunk->num_spans; i++) { - sngisdn_span_data_t *my_signal_data = signal_data->nfas.trunk->spans[i]; - - sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); - memset(sngisdn_event, 0, sizeof(*sngisdn_event)); - sngisdn_event->event_id = SNGISDN_EVENT_RST_IND; - sngisdn_event->suId = suId; - sngisdn_event->dChan = dChan; - sngisdn_event->ces = ces; - sngisdn_event->signal_data = my_signal_data; - memcpy(&sngisdn_event->event.rstEvnt, rstEvnt, sizeof(*rstEvnt)); - ftdm_queue_enqueue(my_signal_data->event_queue, sngisdn_event); - } - } else { - ftdm_queue_enqueue(signal_data->event_queue, sngisdn_event); - } - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -void sngisdn_rcv_rst_cfm (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType) -{ - sngisdn_span_data_t *signal_data; - sngisdn_event_data_t *sngisdn_event = NULL; - - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - - ftdm_log(FTDM_LOG_INFO, "Received RESTART CFM (dChan:%d ces:%u type:%u)\n", dChan, ces, evntType); - - signal_data = g_sngisdn_data.spans[dChan]; - - if (signal_data->nfas.trunk) { - unsigned i; - for (i = 0; i < signal_data->nfas.trunk->num_spans; i++) { - sngisdn_span_data_t *my_signal_data = signal_data->nfas.trunk->spans[i]; - - sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); - memset(sngisdn_event, 0, sizeof(*sngisdn_event)); - sngisdn_event->event_id = SNGISDN_EVENT_RST_CFM; - sngisdn_event->suId = suId; - sngisdn_event->dChan = dChan; - sngisdn_event->ces = ces; - sngisdn_event->signal_data = my_signal_data; - memcpy(&sngisdn_event->event.rstEvnt, rstEvnt, sizeof(*rstEvnt)); - ftdm_queue_enqueue(my_signal_data->event_queue, sngisdn_event); - } - } else { - ftdm_queue_enqueue(signal_data->event_queue, sngisdn_event); - } - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - - -void sngisdn_rcv_phy_ind(SuId suId, Reason reason) -{ - if (reason != LL1_REASON_CON_REQ_FAIL) { - ftdm_log(FTDM_LOG_DEBUG, "[SNGISDN PHY] D-chan %d : %s\n", suId, DECODE_LL1_REASON(reason)); - } - return; -} - -void sngisdn_rcv_q921_ind(BdMngmt *status) -{ - ftdm_span_t *ftdmspan; - - sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[status->t.usta.lnkNmb]; - - if (!signal_data) { - ftdm_log(FTDM_LOG_INFO, "Received q921 status on unconfigured span (lnkNmb:%d)\n", status->t.usta.lnkNmb); - return; - } - ftdmspan = signal_data->ftdm_span; - - if (!ftdmspan) { - ftdm_log(FTDM_LOG_INFO, "Received q921 status on unconfigured span (lnkNmb:%d)\n", status->t.usta.lnkNmb); - return; - } - - switch (status->t.usta.alarm.category) { - case (LCM_CATEGORY_PROTOCOL): - ftdm_log(FTDM_LOG_DEBUG, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n", - ftdmspan->name, - DECODE_LCM_CATEGORY(status->t.usta.alarm.category), - DECODE_LLD_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event, - DECODE_LLD_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause); - - if (FTDM_SPAN_IS_BRI(ftdmspan) && (status->t.usta.alarm.event == PROT_ST_DN)) { - /* Q.921 link is down - This is a line where the Q.921 stops transmitting - after the line goes idle. - - Do not drop current calls, but set sigstatus do down so that we - can try to re-initialize link before trying new outbound calls */ - - sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_DOWN); - sngisdn_set_span_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING); - } - break; - default: - ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n", - ftdmspan->name, - DECODE_LCM_CATEGORY(status->t.usta.alarm.category), - DECODE_LLD_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event, - DECODE_LLD_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause); - - switch (status->t.usta.alarm.event) { - case ENTR_CONG: /* Entering Congestion */ - ftdm_log(FTDM_LOG_WARNING, "s%d: Entering Congestion\n", ftdmspan->span_id); - ftdm_set_flag(ftdmspan, FTDM_SPAN_SUSPENDED); - break; - case EXIT_CONG: /* Exiting Congestion */ - ftdm_log(FTDM_LOG_WARNING, "s%d: Exiting Congestion\n", ftdmspan->span_id); - ftdm_clear_flag(ftdmspan, FTDM_SPAN_SUSPENDED); - break; - } - break; - } - return; -} - -#if 0 -static void sngisdn_rcv_q931_ind_span(sngisdn_span_data_t *signal_data, InMngmt *status) -{ - ftdm_span_t *ftdmspan = signal_data->ftdm_span; - uint32_t chan_no = status->t.usta.evntParm[2]; - - if (!signal_data) { - ftdm_log(FTDM_LOG_INFO, "Received q931 status on unconfigured span (lnkNmb:%d)\n", status->t.usta.suId); - return; - } - - ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n", - status->t.usta.suId, - DECODE_LCM_CATEGORY(status->t.usta.alarm.category), - DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event, - DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause); - - if (chan_no) { - ftdm_channel_t *ftdmchan = ftdm_span_get_channel(ftdmspan, chan_no); - if (ftdmchan) { - sngisdn_set_chan_sig_status(ftdmchan, (status->t.usta.alarm.event == LCM_EVENT_UP) ? FTDM_SIG_STATE_UP : FTDM_SIG_STATE_DOWN); - sngisdn_set_chan_avail_rate(ftdmchan, (status->t.usta.alarm.event == LCM_EVENT_UP) ? SNGISDN_AVAIL_UP: SNGISDN_AVAIL_PWR_SAVING); - } else { - ftdm_log(FTDM_LOG_CRIT, "stack alarm event on invalid channel :%d\n", chan_no); - } - } else { - sngisdn_set_span_sig_status(ftdmspan, (status->t.usta.alarm.event == LCM_EVENT_UP) ? FTDM_SIG_STATE_UP : FTDM_SIG_STATE_DOWN); - sngisdn_set_span_avail_rate(ftdmspan, (status->t.usta.alarm.event == LCM_EVENT_UP) ? SNGISDN_AVAIL_UP: SNGISDN_AVAIL_PWR_SAVING); - } -} -#endif - -void sngisdn_rcv_q931_ind(InMngmt *status) -{ - sngisdn_span_data_t *signal_data = NULL; - ftdm_span_t *ftdmspan = NULL; -#ifndef WIN32 - if (status->t.usta.alarm.cause == 287) { - sngisdn_get_memory_info(); - return; - } -#endif - - signal_data = g_sngisdn_data.spans[status->t.usta.suId]; - if (!signal_data) { - ftdm_log(FTDM_LOG_INFO, "Received q931 status on unconfigured span (lnkNmb:%d)\n", status->t.usta.suId); - return; - } - - ftdmspan = signal_data->ftdm_span; - - switch (status->t.usta.alarm.event) { - case LCM_EVENT_UP: - case LCM_EVENT_DOWN: - { - int i; - sngisdn_nfas_data_t *nfas_data = NULL; - ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n", - status->t.usta.suId, - DECODE_LCM_CATEGORY(status->t.usta.alarm.category), - DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event, - DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause); - - nfas_data = signal_data->nfas.trunk; - - if (nfas_data && status->t.usta.alarm.event == LCM_EVENT_UP) { - for (i = 0; i < ftdm_array_len(nfas_data->spans); i++) { - if (nfas_data->spans[i] && nfas_data->spans[i]->nfas.sigchan == SNGISDN_NFAS_DCHAN_NONE) { - - sngisdn_set_span_sig_status(nfas_data->spans[i]->ftdm_span, FTDM_SIG_STATE_UP); - sngisdn_set_span_avail_rate(nfas_data->spans[i]->ftdm_span, SNGISDN_AVAIL_UP); - } - } - } - - sngisdn_set_span_sig_status(ftdmspan, (status->t.usta.alarm.event == LCM_EVENT_UP) ? FTDM_SIG_STATE_UP : FTDM_SIG_STATE_DOWN); - sngisdn_set_span_avail_rate(ftdmspan, (status->t.usta.alarm.event == LCM_EVENT_UP) ? SNGISDN_AVAIL_UP: SNGISDN_AVAIL_PWR_SAVING); - - if (nfas_data && status->t.usta.alarm.event == LCM_EVENT_DOWN) { - if (nfas_data->dchan->sigstatus == FTDM_SIG_STATE_DOWN && - ((nfas_data->backup && nfas_data->backup->sigstatus == FTDM_SIG_STATE_DOWN) || !nfas_data->backup)) { - - for (i = 0; i < ftdm_array_len(nfas_data->spans); i++) { - if (nfas_data->spans[i] && nfas_data->spans[i]->nfas.sigchan == SNGISDN_NFAS_DCHAN_NONE) { - - sngisdn_set_span_sig_status(nfas_data->spans[i]->ftdm_span, FTDM_SIG_STATE_DOWN); - sngisdn_set_span_avail_rate(nfas_data->spans[i]->ftdm_span, SNGISDN_AVAIL_PWR_SAVING); - } - } - } - } - } - break; - default: - ftdm_log(FTDM_LOG_WARNING, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n", - status->t.usta.suId, - DECODE_LCM_CATEGORY(status->t.usta.alarm.category), - DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event, - DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause); - } - - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; -} - -void sngisdn_rcv_cc_ind(CcMngmt *status) -{ - ISDN_FUNC_TRACE_ENTER(__FTDM_FUNC__); - ftdm_log(FTDM_LOG_INFO, "RECEIVED %s\n", __FTDM_FUNC__); - ISDN_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; -} - -void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf) -{ - MsgLen mlen; - int16_t j; - Buffer *tmp; - Data *cptr; - uint8_t data; - ftdm_trace_dir_t dir; - uint8_t tdata[1000]; - - sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[trc->t.trc.suId]; - - ftdm_assert(mBuf != NULLP, "Received a Q931 trace with no buffer"); - mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len; - - if (trc->t.trc.evnt == TL3PKTTX) { - dir = FTDM_TRACE_DIR_OUTGOING; - } else { - dir = FTDM_TRACE_DIR_INCOMING; - } - - if (mlen) { - tmp = mBuf->b_cont; - cptr = tmp->b_rptr; - data = *cptr++; - - for(j=0;jb_wptr) { - tmp = tmp->b_cont; - if (tmp) cptr = tmp->b_rptr; - } - data = *cptr++; - } - if (signal_data->raw_trace_q931 == SNGISDN_OPT_TRUE) { - sngisdn_trace_raw_q931(signal_data, dir, tdata, mlen); - } else { - sngisdn_trace_interpreted_q931(signal_data, dir, tdata, mlen); - } - } - return; -} - - -void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf) -{ - MsgLen mlen; - Buffer *tmp; - MsgLen i; - int16_t j; - Data *cptr; - uint8_t data; - ftdm_trace_dir_t dir; - uint8_t tdata[1000]; - - sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[trc->t.trc.lnkNmb]; - - if (trc->t.trc.evnt == TL2TMR) { - return; - } - - if (trc->t.trc.evnt == TL2FRMTX) { - dir = FTDM_TRACE_DIR_OUTGOING; - } else { - dir = FTDM_TRACE_DIR_INCOMING; - } - - ftdm_assert(mBuf != NULLP, "Received a Q921 trace with no buffer"); - mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len; - if (mlen != 0) { - tmp = mBuf->b_cont; - cptr = tmp->b_rptr; - data = *cptr++; - i = 0; - while (i < mlen) { - j = 0; - for(j=0;j<16;j++) { - if (ib_wptr) { - tmp = tmp->b_cont; - if (tmp) cptr = tmp->b_rptr; - } - i++; - if (iraw_trace_q921 == SNGISDN_OPT_TRUE) { - sngisdn_trace_raw_q921(signal_data, dir, tdata, mlen); - } else { - sngisdn_trace_interpreted_q921(signal_data, dir, tdata, mlen); - } - } - return; -} - -/* The stacks is wants to transmit a frame */ -int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_l1_frame_t *l1_frame) -{ - ftdm_status_t status; - ftdm_wait_flag_t flags = FTDM_WRITE; - sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[spId]; - ftdm_size_t length = l1_frame->len; - - ftdm_assert(signal_data, "Received Data request on unconfigured span\n"); - - do { - flags = FTDM_WRITE; - status = signal_data->dchan->fio->wait(signal_data->dchan, &flags, 1000); - switch(status) { - case FTDM_SUCCESS: - break; - case FTDM_TIMEOUT: - continue; - case FTDM_FAIL: - default: - ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_WARNING, "failed to poll for channel\n"); - return -1; - } - - - /* status = FTDM_SUCCESS */ - if ((flags & FTDM_WRITE)) { -#if 0 - int i; - char string [2000]; - unsigned string_len = 0; - for (i = 0; i < length; i++) { - string_len += sprintf(&string[string_len], "0x%02x ", l1_frame->data[i]); - } - - ftdm_log_chan(signal_data->dchan, FTDM_LOG_CRIT, "\nL1 TX [%s]\n", string); -#endif - - status = signal_data->dchan->fio->write(signal_data->dchan, l1_frame->data, (ftdm_size_t*)&length); - if (status != FTDM_SUCCESS) { - ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_CRIT, "Failed to transmit frame\n"); - return -1; - } - break; - /* On WIN32, it is possible for poll to return without FTDM_WRITE flag set, so we try to retransmit */ -#ifndef WIN32 - } else { - ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_WARNING, "Failed to poll for d-channel\n"); - return -1; -#endif - } - } while(1); - return 0; -} - -int16_t sngisdn_rcv_l1_cmd_req(uint16_t spId, sng_l1_cmd_t *l1_cmd) -{ - sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[spId]; - ftdm_assert(signal_data, "Received Data request on unconfigured span\n"); - - switch(l1_cmd->type) { - case SNG_L1CMD_SET_LINK_STATUS: - { - ftdm_channel_hw_link_status_t status = FTDM_HW_LINK_CONNECTED; - ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_SET_LINK_STATUS, &status); - } - break; - case SNG_L1CMD_GET_LINK_STATUS: - { - ftdm_channel_hw_link_status_t status = 0; - ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_GET_LINK_STATUS, &status); - if (status == FTDM_HW_LINK_CONNECTED) { - l1_cmd->cmd.status = 1; - } else if (status == FTDM_HW_LINK_DISCONNECTED) { - l1_cmd->cmd.status = 0; - } else { - ftdm_log_chan(signal_data->dchan, FTDM_LOG_CRIT, "Invalid link status reported %d\n", status); - l1_cmd->cmd.status = 0; - } - } - break; - case SNG_L1CMD_FLUSH_STATS: - ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_FLUSH_IOSTATS, NULL); - break; - case SNG_L1CMD_FLUSH_BUFFERS: - ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_FLUSH_BUFFERS, NULL); - break; - default: - ftdm_log_chan(signal_data->dchan, FTDM_LOG_CRIT, "Unsupported channel command:%d\n", l1_cmd->type); - return -1; - } - return 0; -} - -void sngisdn_rcv_sng_assert(char *message) -{ - ftdm_assert(0, message); -} - -void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...) -{ - char *data; - int ret; - va_list ap; - - va_start(ap, fmt); - ret = ftdm_vasprintf(&data, fmt, ap); - if (ret == -1) { - return; - } - - switch (level) { - case SNG_LOGLEVEL_DEBUG: - ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s", data); - break; - case SNG_LOGLEVEL_WARN: - if ( strncmp(data, "Invalid Q.921/Q.931 frame", 25) ) { - ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data); - } - break; - case SNG_LOGLEVEL_INFO: - ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s\n", data); - break; - case SNG_LOGLEVEL_STATS: - ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s\n", data); - break; - case SNG_LOGLEVEL_ERROR: - ftdm_log(FTDM_LOG_ERROR, "sng_isdn->%s\n", data); - /*ftdm_assert(0, "Got an error from stack");*/ - break; - case SNG_LOGLEVEL_CRIT: - ftdm_log(FTDM_LOG_CRIT, "sng_isdn->%s\n", data); - /* ftdm_assert(0, "Got an error from stack"); */ - break; - default: - ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s\n", data); - break; - } - ftdm_safe_free(data); - return; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c deleted file mode 100644 index 83dd070387..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ /dev/null @@ -1,1643 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * David Yat Sin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ftmod_sangoma_isdn.h" -#define SNGISDN_Q931_FACILITY_IE_ID 0x1C - -/* ftmod_sangoma_isdn specific enum look-up functions */ - -SNGISDN_ENUM_NAMES(SNGISDN_PROGIND_DESCR_NAMES, SNGISDN_PROGIND_DESCR_STRINGS) -SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr2str, ftdm_sngisdn_progind_descr_t, SNGISDN_PROGIND_DESCR_NAMES, SNGISDN_PROGIND_DESCR_INVALID) - -SNGISDN_ENUM_NAMES(SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_STRINGS) -SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t, SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_INVALID) - -SNGISDN_ENUM_NAMES(SNGISDN_NETSPECFAC_TYPE_NAMES, SNGISDN_NETSPECFAC_TYPE_STRINGS) -SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_netspecfac_type, ftdm_sngisdn_netspecfac_type2str, ftdm_sngisdn_netspecfac_type_t, SNGISDN_NETSPECFAC_TYPE_NAMES, SNGISDN_NETSPECFAC_TYPE_INVALID) - -SNGISDN_ENUM_NAMES(SNGISDN_NETSPECFAC_PLAN_NAMES, SNGISDN_NETSPECFAC_PLAN_STRINGS) -SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_netspecfac_plan, ftdm_sngisdn_netspecfac_plan2str, ftdm_sngisdn_netspecfac_plan_t, SNGISDN_NETSPECFAC_PLAN_NAMES, SNGISDN_NETSPECFAC_PLAN_INVALID) - -SNGISDN_ENUM_NAMES(SNGISDN_NETSPECFAC_SPEC_NAMES, SNGISDN_NETSPECFAC_SPEC_STRINGS) -SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_netspecfac_spec, ftdm_sngisdn_netspecfac_spec2str, ftdm_sngisdn_netspecfac_spec_t, SNGISDN_NETSPECFAC_SPEC_NAMES, SNGISDN_NETSPECFAC_SPEC_INVALID) - -static uint8_t _get_trillium_val(ftdm2trillium_t *vals, unsigned int num_vals, uint8_t ftdm_val, uint8_t default_val); -static uint8_t _get_ftdm_val(ftdm2trillium_t *vals, unsigned int num_vals, uint8_t trillium_val, uint8_t default_val); - -#define get_trillium_val(vals, ftdm_val, default_val) _get_trillium_val(vals, ftdm_array_len(vals), ftdm_val, default_val) -#define get_ftdm_val(vals, trillium_val, default_val) _get_ftdm_val(vals, ftdm_array_len(vals), trillium_val, default_val) - -ftdm_status_t get_calling_name_from_usr_usr(ftdm_channel_t *ftdmchan, UsrUsr *usrUsr); -ftdm_status_t get_calling_name_from_display(ftdm_channel_t *ftdmchan, Display *display); -ftdm_status_t get_calling_name_from_ntDisplay(ftdm_channel_t *ftdmchan, NtDisplay *display); - -extern ftdm_sngisdn_data_t g_sngisdn_data; - -ftdm2trillium_t npi_codes[] = { - {FTDM_NPI_UNKNOWN, IN_NP_UNK}, - {FTDM_NPI_ISDN, IN_NP_ISDN}, - {FTDM_NPI_DATA, IN_NP_DATA}, - {FTDM_NPI_TELEX, IN_NP_TELEX}, - {FTDM_NPI_NATIONAL, IN_NP_NATIONAL}, - {FTDM_NPI_PRIVATE, IN_NP_PRIVATE}, - {FTDM_NPI_RESERVED, IN_NP_EXT}, -}; - -ftdm2trillium_t ton_codes[] = { - {FTDM_TON_UNKNOWN, IN_TON_UNK}, - {FTDM_TON_INTERNATIONAL, IN_TON_INT}, - {FTDM_TON_NATIONAL, IN_TON_NAT}, - {FTDM_TON_NETWORK_SPECIFIC, IN_TON_NETSPEC}, - {FTDM_TON_SUBSCRIBER_NUMBER, IN_TON_SUB}, - {FTDM_TON_ABBREVIATED_NUMBER, IN_TON_ABB}, - {FTDM_TON_RESERVED, IN_TON_EXT}, -}; - -ftdm2trillium_t nsf_spec_codes[] = { - {SNGISDN_NETSPECFAC_SPEC_ACCUNET, 0xe6}, - {SNGISDN_NETSPECFAC_SPEC_MEGACOM, 0xe3}, - {SNGISDN_NETSPECFAC_SPEC_MEGACOM_800, 0xe2}, - {SNGISDN_NETSPECFAC_SPEC_SDDN, 0xe1}, - {SNGISDN_NETSPECFAC_SPEC_INVALID, 0x00}, -}; - -ftdm2trillium_t nsf_type_codes[] = { - {SNGISDN_NETSPECFAC_TYPE_USER_SPEC, 0x00}, - {SNGISDN_NETSPECFAC_TYPE_NATIONAL_NETWORK_IDENT, 0x02}, - {SNGISDN_NETSPECFAC_TYPE_INTERNATIONAL_NETWORK_IDENT, 0x03}, - {SNGISDN_NETSPECFAC_TYPE_INVALID, 0x00}, -}; - -ftdm2trillium_t nsf_plan_codes[] = { - {SNGISDN_NETSPECFAC_PLAN_UNKNOWN, 0x00}, - {SNGISDN_NETSPECFAC_PLAN_CARRIER_IDENT, 0x01}, - {SNGISDN_NETSPECFAC_PLAN_DATA_NETWORK_IDENT, 0x03}, - {SNGISDN_NETSPECFAC_PLAN_INVALID, 0x00}, -}; - -static uint8_t _get_trillium_val(ftdm2trillium_t *vals, unsigned int num_vals, uint8_t ftdm_val, uint8_t default_val) -{ - int i; - for (i = 0; i < num_vals; i++) { - if (vals[i].ftdm_val == ftdm_val) { - return vals[i].trillium_val; - } - } - - return default_val; -} - -static uint8_t _get_ftdm_val(ftdm2trillium_t *vals, unsigned int num_vals, uint8_t trillium_val, uint8_t default_val) -{ - int i; - for (i = 0; i < num_vals; i++) { - if (vals[i].trillium_val == trillium_val) { - return vals[i].ftdm_val; - } - } - return default_val; -} - -void clear_call_data(sngisdn_chan_data_t *sngisdn_info) -{ - uint32_t cc_id = ((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->cc_id; - - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_DEBUG, "Clearing call data (suId:%u suInstId:%u spInstId:%u)\n", cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); - ftdm_mutex_lock(g_sngisdn_data.ccs[cc_id].mutex); - g_sngisdn_data.ccs[cc_id].active_spInstIds[sngisdn_info->spInstId]=NULL; - g_sngisdn_data.ccs[cc_id].active_suInstIds[sngisdn_info->suInstId]=NULL; - - sngisdn_info->suInstId = 0; - sngisdn_info->spInstId = 0; - sngisdn_info->globalFlg = 0; - sngisdn_info->flags = 0; - sngisdn_info->transfer_data.type = SNGISDN_TRANSFER_NONE; - - ftdm_mutex_unlock(g_sngisdn_data.ccs[cc_id].mutex); - return; -} - -void clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info) -{ - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_DEBUG, "Clearing glare data (suId:%d suInstId:%u spInstId:%u actv-suInstId:%u actv-spInstId:%u)\n", - sngisdn_info->glare.suId, - sngisdn_info->glare.suInstId, sngisdn_info->glare.spInstId, - sngisdn_info->suInstId, sngisdn_info->spInstId); - - ftdm_mutex_lock(g_sngisdn_data.ccs[sngisdn_info->glare.suId].mutex); - if (sngisdn_info->glare.spInstId != sngisdn_info->spInstId) { - g_sngisdn_data.ccs[sngisdn_info->glare.suId].active_spInstIds[sngisdn_info->glare.spInstId]=NULL; - } - g_sngisdn_data.ccs[sngisdn_info->glare.suId].active_suInstIds[sngisdn_info->glare.suInstId]=NULL; - ftdm_mutex_unlock(g_sngisdn_data.ccs[sngisdn_info->glare.suId].mutex); - - ftdm_clear_flag(sngisdn_info, FLAG_GLARE); - memset(&sngisdn_info->glare.setup, 0, sizeof(ConEvnt)); - sngisdn_info->glare.suId = 0; - sngisdn_info->glare.suInstId = 0; - sngisdn_info->glare.spInstId = 0; - sngisdn_info->glare.dChan = 0; - sngisdn_info->glare.ces = 0; - return; -} - - -uint32_t get_unique_suInstId(int16_t cc_id) -{ - uint32_t suInstId; - ftdm_assert_return((cc_id > 0 && cc_id <=MAX_VARIANTS), FTDM_FAIL, "Invalid cc_id\n"); - ftdm_mutex_lock(g_sngisdn_data.ccs[cc_id].mutex); - suInstId = g_sngisdn_data.ccs[cc_id].last_suInstId; - - while(1) { - if (++suInstId == MAX_INSTID) { - suInstId = 1; - } - if (g_sngisdn_data.ccs[cc_id].active_suInstIds[suInstId] == NULL) { - g_sngisdn_data.ccs[cc_id].last_suInstId = suInstId; - ftdm_mutex_unlock(g_sngisdn_data.ccs[cc_id].mutex); - return suInstId; - } - } - /* Should never reach here */ - ftdm_mutex_unlock(g_sngisdn_data.ccs[cc_id].mutex); - return 0; -} - -ftdm_status_t get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data) -{ - ftdm_assert_return((cc_id > 0 && cc_id <=MAX_VARIANTS), FTDM_FAIL, "Invalid cc_id\n"); - ftdm_assert_return(g_sngisdn_data.ccs[cc_id].activation_done, FTDM_FAIL, "Trying to find call on unconfigured CC\n"); - - if (g_sngisdn_data.ccs[cc_id].active_suInstIds[suInstId] == NULL) { - return FTDM_FAIL; - } - *sngisdn_data = g_sngisdn_data.ccs[cc_id].active_suInstIds[suInstId]; - return FTDM_SUCCESS; -} - -ftdm_status_t get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data) -{ - ftdm_assert_return((cc_id > 0 && cc_id <=MAX_VARIANTS), FTDM_FAIL, "Invalid cc_id\n"); - ftdm_assert_return(g_sngisdn_data.ccs[cc_id].activation_done, FTDM_FAIL, "Trying to find call on unconfigured CC\n"); - - if (g_sngisdn_data.ccs[cc_id].active_spInstIds[spInstId] == NULL) { - return FTDM_FAIL; - } - *sngisdn_data = g_sngisdn_data.ccs[cc_id].active_spInstIds[spInstId]; - return FTDM_SUCCESS; -} - -ftdm_status_t sngisdn_set_chan_avail_rate(ftdm_channel_t *chan, sngisdn_avail_t avail) -{ - if (FTDM_SPAN_IS_BRI(chan->span)) { - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Setting availability rate to:%d\n", avail); - chan->availability_rate = avail; - } - return FTDM_SUCCESS; -} - -ftdm_status_t sngisdn_set_span_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail) -{ - if (FTDM_SPAN_IS_BRI(span)) { - ftdm_iterator_t *chaniter = NULL; - ftdm_iterator_t *curr = NULL; - - chaniter = ftdm_span_get_chan_iterator(span, NULL); - for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { - ftdm_log_chan(((ftdm_channel_t*)ftdm_iterator_current(curr)), FTDM_LOG_DEBUG, "Setting availability rate to:%d\n", avail); - sngisdn_set_chan_avail_rate(((ftdm_channel_t*)ftdm_iterator_current(curr)), avail); - } - ftdm_iterator_free(chaniter); - } - return FTDM_SUCCESS; -} - -#ifdef NETBORDER_CALL_REF -ftdm_status_t get_callref(ftdm_channel_t *ftdmchan, BCCallRef* callRef) -{ - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; - - if (signal_data->raw_trace_q931) { - if (callRef->eh.pres != PRSNT_NODEF || callRef->reference.pres != PRSNT_NODEF) { - /* Netborder only supports BRI, so we only care for BRI for now */ - if (FTDM_SPAN_IS_BRI(ftdmchan->span) && !sngisdn_info->call_ref) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to obtain call reference\n"); - } - return FTDM_FAIL; - } - if (FTDM_SPAN_IS_BRI(ftdmchan->span)) { - sngisdn_info->call_ref = 0x7F & callRef->reference.val; - } else { - sngisdn_info->call_ref = 0x7FFF & callRef->reference.val; - } - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Call reference:%04x\n", sngisdn_info->call_ref); - } - return FTDM_SUCCESS; -} -#endif - -ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) -{ - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - if (cgPtyNmb->eh.pres != PRSNT_NODEF) { - return FTDM_FAIL; - } - - if (cgPtyNmb->screenInd.pres == PRSNT_NODEF) { - caller_data->screen = cgPtyNmb->screenInd.val; - } - - if (cgPtyNmb->presInd0.pres == PRSNT_NODEF) { - caller_data->pres = cgPtyNmb->presInd0.val; - } - - if (cgPtyNmb->nmbPlanId.pres == PRSNT_NODEF) { - caller_data->cid_num.plan = cgPtyNmb->nmbPlanId.val; - } - - if (cgPtyNmb->typeNmb1.pres == PRSNT_NODEF) { - caller_data->cid_num.type = cgPtyNmb->typeNmb1.val; - } - - if (cgPtyNmb->nmbDigits.pres == PRSNT_NODEF) { - ftdm_copy_string(caller_data->cid_num.digits, (const char*)cgPtyNmb->nmbDigits.val, cgPtyNmb->nmbDigits.len+1); - } - memcpy(&caller_data->ani, &caller_data->cid_num, sizeof(caller_data->ani)); - return FTDM_SUCCESS; -} - -ftdm_status_t get_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) -{ - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - if (cgPtyNmb->eh.pres != PRSNT_NODEF) { - return FTDM_FAIL; - } - - if (cgPtyNmb->screenInd.pres == PRSNT_NODEF) { - sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.cg_pty2.screen_ind", ftdm_screening2str(cgPtyNmb->screenInd.val)); - } - - if (cgPtyNmb->presInd0.pres == PRSNT_NODEF) { - sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.cg_pty2.presentation_ind", ftdm_presentation2str(cgPtyNmb->presInd0.val)); - } - - if (cgPtyNmb->nmbPlanId.pres == PRSNT_NODEF) { - sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.cg_pty2.npi", ftdm_npi2str(cgPtyNmb->nmbPlanId.val)); - } - - if (cgPtyNmb->typeNmb1.pres == PRSNT_NODEF) { - sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.cg_pty2.ton", ftdm_ton2str(cgPtyNmb->typeNmb1.val)); - } - - if (cgPtyNmb->nmbDigits.pres == PRSNT_NODEF) { - char digits_string [32]; - memcpy(digits_string, (const char*)cgPtyNmb->nmbDigits.val, cgPtyNmb->nmbDigits.len); - digits_string[cgPtyNmb->nmbDigits.len] = '\0'; - sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.cg_pty2.digits", digits_string); - } - memcpy(&caller_data->ani, &caller_data->cid_num, sizeof(caller_data->ani)); - return FTDM_SUCCESS; -} - -ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb) -{ - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - - if (cdPtyNmb->eh.pres != PRSNT_NODEF) { - return FTDM_FAIL; - } - - if (cdPtyNmb->nmbPlanId.pres == PRSNT_NODEF) { - caller_data->dnis.plan = get_ftdm_val(npi_codes, cdPtyNmb->nmbPlanId.val, IN_NP_UNK); - } - - if (cdPtyNmb->typeNmb0.pres == PRSNT_NODEF) { - caller_data->dnis.type = get_ftdm_val(ton_codes, cdPtyNmb->typeNmb0.val, IN_TON_UNK); - } - - if (cdPtyNmb->nmbDigits.pres == PRSNT_NODEF) { - /* In overlap receive mode, append the new digits to the existing dnis */ - unsigned i = strlen(caller_data->dnis.digits); - - ftdm_copy_string(&caller_data->dnis.digits[i], (const char*)cdPtyNmb->nmbDigits.val, cdPtyNmb->nmbDigits.len+1); - } - return FTDM_SUCCESS; -} - -ftdm_status_t get_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb) -{ - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - if (redirNmb->eh.pres != PRSNT_NODEF) { - return FTDM_FAIL; - } - - if (redirNmb->nmbPlanId.pres == PRSNT_NODEF) { - caller_data->rdnis.plan = get_ftdm_val(npi_codes, redirNmb->nmbPlanId.val, IN_NP_UNK); - } - - if (redirNmb->typeNmb.pres == PRSNT_NODEF) { - caller_data->rdnis.type = get_ftdm_val(ton_codes, redirNmb->typeNmb.val, IN_TON_UNK); - } - - if (redirNmb->nmbDigits.pres == PRSNT_NODEF) { - ftdm_copy_string(caller_data->rdnis.digits, (const char*)redirNmb->nmbDigits.val, redirNmb->nmbDigits.len+1); - } - return FTDM_SUCCESS; -} - -ftdm_status_t get_calling_name_from_display(ftdm_channel_t *ftdmchan, Display *display) -{ - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - if (display->eh.pres != PRSNT_NODEF) { - return FTDM_FAIL; - } - if (display->dispInfo.pres != PRSNT_NODEF) { - return FTDM_FAIL; - } - - ftdm_copy_string(caller_data->cid_name, (const char*)display->dispInfo.val, display->dispInfo.len+1); - return FTDM_SUCCESS; -} - -ftdm_status_t get_calling_name_from_ntDisplay(ftdm_channel_t *ftdmchan, NtDisplay *display) -{ - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - if (display->eh.pres != PRSNT_NODEF) { - return FTDM_FAIL; - } - if (display->dispInfo.pres != PRSNT_NODEF) { - return FTDM_FAIL; - } - - ftdm_copy_string(caller_data->cid_name, (const char*)display->dispInfo.val, display->dispInfo.len+1); - return FTDM_SUCCESS; -} - -ftdm_status_t get_calling_name_from_usr_usr(ftdm_channel_t *ftdmchan, UsrUsr *usrUsr) -{ - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - if (usrUsr->eh.pres != PRSNT_NODEF) { - return FTDM_FAIL; - } - - if (usrUsr->protocolDisc.val != PD_IA5) { - return FTDM_FAIL; - } - - if (usrUsr->usrInfo.pres != PRSNT_NODEF) { - return FTDM_FAIL; - } - - ftdm_copy_string(caller_data->cid_name, (const char*)usrUsr->usrInfo.val, usrUsr->usrInfo.len+1); - return FTDM_SUCCESS; -} - -ftdm_status_t get_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt) -{ - ftdm_status_t status = FTDM_FAIL; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - if (signal_data->switchtype == SNGISDN_SWITCH_DMS100) { - status = get_calling_name_from_ntDisplay(ftdmchan, &conEvnt->ntDisplay[0]); - } else { - status = get_calling_name_from_display(ftdmchan, &conEvnt->display); - - } - if (status != FTDM_SUCCESS) { - status = get_calling_name_from_usr_usr(ftdmchan, &conEvnt->usrUsr); - } - return status; -} - - -ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad) -{ - char subaddress[100]; - - if (cgPtySad->eh.pres != PRSNT_NODEF) { - return FTDM_FAIL; - } - memset(subaddress, 0, sizeof(subaddress)); - if(cgPtySad->sadInfo.len >= sizeof(subaddress)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Calling Party Subaddress exceeds local size limit (len:%d max:%"FTDM_SIZE_FMT")\n", cgPtySad->sadInfo.len, sizeof(subaddress)); - cgPtySad->sadInfo.len = sizeof(subaddress)-1; - } - - memcpy(subaddress, (char*)cgPtySad->sadInfo.val, cgPtySad->sadInfo.len); - subaddress[cgPtySad->sadInfo.len] = '\0'; - sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.calling_subaddr", subaddress); - return FTDM_SUCCESS; -} - -ftdm_status_t get_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr) -{ - if (!facilityStr->eh.pres) { - return FTDM_FAIL; - } - - return get_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, facilityStr->facilityStr.len); -} - -ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t data_len) -{ - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - /* Max size of Facility IE is 255 */ - uint8_t my_data [255]; - - /* Always include Facility IE identifier + len so this can be used as a sanity check by the user */ - my_data[0] = SNGISDN_Q931_FACILITY_IE_ID; - my_data[1] = data_len; - memcpy(&my_data[2], data, data_len); - - sngisdn_add_raw_data((sngisdn_chan_data_t*)ftdmchan->call_data, my_data, data_len+2); - - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Raw Facility IE copied available\n"); - } else { - /* Call libsng_isdn to process facility IE's here */ - } - return FTDM_SUCCESS; -} - -ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd) -{ - uint8_t val; - - if (!progInd->eh.pres) { - return FTDM_FAIL; - } - - if (progInd->progDesc.pres) { - /* TODO: use get_ftdm_val function and table here */ - switch (progInd->progDesc.val) { - case IN_PD_NOTETEISDN: - val = SNGISDN_PROGIND_DESCR_NETE_ISDN; - break; - case IN_PD_DSTNOTISDN: - val = SNGISDN_PROGIND_DESCR_DEST_NISDN; - break; - case IN_PD_ORGNOTISDN: - val = SNGISDN_PROGIND_DESCR_ORIG_NISDN; - break; - case IN_PD_CALLRET: - val = SNGISDN_PROGIND_DESCR_RET_ISDN; - break; - case IN_PD_DELRESP: - val = SNGISDN_PROGIND_DESCR_SERV_CHANGE; - break; - case IN_PD_IBAVAIL: - val = SNGISDN_PROGIND_DESCR_IB_AVAIL; - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unknown Progress Indicator Description (%d)\n", progInd->progDesc.val); - val = SNGISDN_PROGIND_DESCR_INVALID; - break; - } - sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.prog_ind.descr", ftdm_sngisdn_progind_descr2str(val)); - } - - if (progInd->location.pres) { - switch (progInd->location.val) { - case IN_LOC_USER: - val = SNGISDN_PROGIND_LOC_USER; - break; - case IN_LOC_PRIVNETLU: - val = SNGISDN_PROGIND_LOC_PRIV_NET_LOCAL_USR; - break; - case IN_LOC_PUBNETLU: - val = SNGISDN_PROGIND_LOC_PUB_NET_LOCAL_USR; - break; - case IN_LOC_TRANNET: - val = SNGISDN_PROGIND_LOC_TRANSIT_NET; - break; - case IN_LOC_PUBNETRU: - val = SNGISDN_PROGIND_LOC_PUB_NET_REMOTE_USR; - break; - case IN_LOC_PRIVNETRU: - val = SNGISDN_PROGIND_LOC_PRIV_NET_REMOTE_USR; - break; - case IN_LOC_NETINTER: - val = SNGISDN_PROGIND_LOC_NET_BEYOND_INTRW; - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unknown Progress Indicator Location (%d)", progInd->location.val); - val = SNGISDN_PROGIND_LOC_INVALID; - break; - } - sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.prog_ind.loc", ftdm_sngisdn_progind_loc2str(val)); - } - return FTDM_SUCCESS; -} - - -ftdm_status_t get_network_specific_fac(ftdm_channel_t *ftdmchan, NetFac *netFac) -{ - if (!netFac->eh.pres) { - return FTDM_FAIL; - } - - if (netFac->netFacSpec.pres == PRSNT_NODEF) { - char digits_string [32]; - memcpy(digits_string, (const char*)netFac->netFacSpec.val, netFac->netFacSpec.len); - digits_string[netFac->netFacSpec.len] = '\0'; - sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.netFac.spec", digits_string); - } - - if (netFac->typeNetId.pres == PRSNT_NODEF) { - sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.netFac.type", ftdm_sngisdn_netspecfac_type2str(get_ftdm_val(nsf_type_codes, netFac->typeNetId.val, 0x00))); - } - - if (netFac->netIdPlan.pres == PRSNT_NODEF) { - sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.netFac.plan", ftdm_sngisdn_netspecfac_type2str(get_ftdm_val(nsf_plan_codes, netFac->netIdPlan.val, 0x00))); - } - return FTDM_SUCCESS; -} - -ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) -{ - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - uint8_t len = strlen(caller_data->cid_num.digits); - if (!len) { - return FTDM_SUCCESS; - } - - if (!strncasecmp(caller_data->cid_num.digits, "0000000000", strlen("0000000000"))) { - return FTDM_SUCCESS; - } - - cgPtyNmb->eh.pres = PRSNT_NODEF; - - cgPtyNmb->screenInd.pres = PRSNT_NODEF; - cgPtyNmb->screenInd.val = caller_data->screen; - - cgPtyNmb->presInd0.pres = PRSNT_NODEF; - cgPtyNmb->presInd0.val = caller_data->pres; - - cgPtyNmb->nmbPlanId.pres = PRSNT_NODEF; - cgPtyNmb->nmbPlanId.val = get_trillium_val(npi_codes, caller_data->cid_num.plan, IN_NP_UNK); - - cgPtyNmb->typeNmb1.pres = PRSNT_NODEF; - - cgPtyNmb->typeNmb1.val = get_trillium_val(ton_codes, caller_data->cid_num.type, IN_TON_UNK); - - cgPtyNmb->nmbDigits.pres = PRSNT_NODEF; - cgPtyNmb->nmbDigits.len = len; - - memcpy(cgPtyNmb->nmbDigits.val, caller_data->cid_num.digits, len); - - return FTDM_SUCCESS; -} - -ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) -{ - const char* string = NULL; - uint8_t len,val; - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - - string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.digits"); - if (ftdm_strlen_zero(string)) { - return FTDM_FAIL; - } - - cgPtyNmb->eh.pres = PRSNT_NODEF; - - len = strlen(string); - cgPtyNmb->nmbDigits.len = len; - - cgPtyNmb->nmbDigits.pres = PRSNT_NODEF; - memcpy(cgPtyNmb->nmbDigits.val, string, len); - - /* Screening Indicator */ - cgPtyNmb->screenInd.pres = PRSNT_NODEF; - - val = FTDM_SCREENING_INVALID; - string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.screening_ind"); - if (!ftdm_strlen_zero(string)) { - val = ftdm_str2ftdm_screening(string); - } - - /* isdn.cg_pty2.screen_ind does not exist or we could not parse its value */ - if (val == FTDM_SCREENING_INVALID) { - /* default to caller data screening ind */ - cgPtyNmb->screenInd.val = caller_data->screen; - } else { - cgPtyNmb->screenInd.val = val; - } - - /* Presentation Indicator */ - cgPtyNmb->presInd0.pres = PRSNT_NODEF; - - val = FTDM_PRES_INVALID; - string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.presentation_ind"); - if (!ftdm_strlen_zero(string)) { - val = ftdm_str2ftdm_presentation(string); - } - - if (val == FTDM_PRES_INVALID) { - cgPtyNmb->presInd0.val = caller_data->pres; - } else { - cgPtyNmb->presInd0.val = val; - } - - /* Numbering Plan Indicator */ - cgPtyNmb->nmbPlanId.pres = PRSNT_NODEF; - - val = FTDM_NPI_INVALID; - string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.npi"); - if (!ftdm_strlen_zero(string)) { - val = ftdm_str2ftdm_npi(string); - } - - if (val == FTDM_NPI_INVALID) { - cgPtyNmb->nmbPlanId.val = caller_data->cid_num.plan; - } else { - cgPtyNmb->nmbPlanId.val = get_trillium_val(npi_codes, val, IN_NP_UNK); - } - - cgPtyNmb->typeNmb1.pres = PRSNT_NODEF; - - /* Type of Number */ - val = FTDM_TON_INVALID; - string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.ton"); - if (!ftdm_strlen_zero(string)) { - val = ftdm_str2ftdm_ton(string); - } - - if (val == FTDM_TON_INVALID) { - cgPtyNmb->typeNmb1.val = caller_data->cid_num.type; - } else { - cgPtyNmb->typeNmb1.val = get_trillium_val(ton_codes, val, IN_TON_UNK); - } - return FTDM_SUCCESS; -} - -ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb) -{ - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - uint8_t len = strlen(caller_data->dnis.digits); - - if (!len) { - return FTDM_SUCCESS; - } - - cdPtyNmb->eh.pres = PRSNT_NODEF; - - cdPtyNmb->nmbPlanId.pres = PRSNT_NODEF; - cdPtyNmb->nmbPlanId.val = get_trillium_val(npi_codes, caller_data->dnis.plan, IN_NP_UNK); - - cdPtyNmb->typeNmb0.pres = PRSNT_NODEF; - cdPtyNmb->typeNmb0.val = get_trillium_val(ton_codes, caller_data->dnis.type, IN_TON_UNK); - - cdPtyNmb->nmbDigits.pres = PRSNT_NODEF; - cdPtyNmb->nmbDigits.len = len; - - - memcpy(cdPtyNmb->nmbDigits.val, caller_data->dnis.digits, len); - return FTDM_SUCCESS; -} - -ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb) -{ - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - uint8_t len = strlen(caller_data->rdnis.digits); - if (!len) { - return FTDM_SUCCESS; - } - - redirNmb->eh.pres = PRSNT_NODEF; - - redirNmb->nmbPlanId.pres = PRSNT_NODEF; - redirNmb->nmbPlanId.val = get_trillium_val(npi_codes, caller_data->rdnis.plan, IN_NP_UNK); - - redirNmb->typeNmb.pres = PRSNT_NODEF; - redirNmb->typeNmb.val = get_trillium_val(ton_codes, caller_data->rdnis.type, IN_TON_UNK); - - redirNmb->nmbDigits.pres = PRSNT_NODEF; - redirNmb->nmbDigits.len = len; - - memcpy(redirNmb->nmbDigits.val, caller_data->rdnis.digits, len); - - return FTDM_SUCCESS; -} - - -ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt) -{ - uint8_t len; - const char *string = NULL; - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - ftdm_bool_t force_send_cid_name = FTDM_FALSE; - - len = strlen(caller_data->cid_name); - if (!len) { - return FTDM_SUCCESS; - } - - string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.send_cid_name"); - if (!ftdm_strlen_zero(string)) { - if (!strcasecmp(string, "no")) { - return FTDM_SUCCESS; - } else if (!strcasecmp(string, "yes")) { - force_send_cid_name = FTDM_TRUE; - } - } - - if (force_send_cid_name == FTDM_FALSE && signal_data->send_cid_name == SNGISDN_OPT_FALSE) { - return FTDM_SUCCESS; - } - - switch(signal_data->cid_name_method) { - case SNGISDN_CID_NAME_FACILITY_IE: -#ifdef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY - /* Note: The Facility IE will be overwritten if user chose to transmit a Raw Facility IE */ - sng_isdn_encode_facility_caller_name(caller_data->cid_name, conEvnt->facilityStr.facilityStr.val, &conEvnt->facilityStr.facilityStr.len); - conEvnt->facilityStr.eh.pres = PRSNT_NODEF; - conEvnt->facilityStr.facilityStr.pres = PRSNT_NODEF; -#endif - break; - case SNGISDN_CID_NAME_USR_USR_IE: - conEvnt->usrUsr.eh.pres = PRSNT_NODEF; - conEvnt->usrUsr.protocolDisc.pres = PRSNT_NODEF; - conEvnt->usrUsr.protocolDisc.val = PD_IA5; /* IA5 chars */ - conEvnt->usrUsr.usrInfo.pres = PRSNT_NODEF; - conEvnt->usrUsr.usrInfo.len = len; - /* in sangoma_brid we used to send usr-usr info as !, - change to previous style if current one does not work */ - memcpy(conEvnt->usrUsr.usrInfo.val, caller_data->cid_name, len); - break; - case SNGISDN_CID_NAME_DISPLAY_IE: - if (signal_data->switchtype == SNGISDN_SWITCH_DMS100) { - conEvnt->ntDisplay[0].eh.pres = PRSNT_NODEF; - conEvnt->ntDisplay[0].dispTypeNt.pres = PRSNT_NODEF; - conEvnt->ntDisplay[0].dispTypeNt.val = 0x01; /* Calling Party Name */ - conEvnt->ntDisplay[0].assocInfo.pres = PRSNT_NODEF; - conEvnt->ntDisplay[0].assocInfo.val = 0x03; /* Included */ - conEvnt->ntDisplay[0].eh.pres = PRSNT_NODEF; - conEvnt->ntDisplay[0].eh.pres = PRSNT_NODEF; - conEvnt->ntDisplay[0].dispInfo.pres = PRSNT_NODEF; - conEvnt->ntDisplay[0].dispInfo.len = len; - memcpy(conEvnt->ntDisplay[0].dispInfo.val, caller_data->cid_name, len); - } else { - conEvnt->display.eh.pres = PRSNT_NODEF; - conEvnt->display.dispInfo.pres = PRSNT_NODEF; - conEvnt->display.dispInfo.len = len; - memcpy(conEvnt->display.dispInfo.val, caller_data->cid_name, len); - } - break; - default: - break; - } - - return FTDM_SUCCESS; -} - -ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad) -{ - const char* clg_subaddr = NULL; - clg_subaddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.calling_subaddr"); - if (!ftdm_strlen_zero(clg_subaddr)) { - unsigned len = strlen (clg_subaddr); - cgPtySad->eh.pres = PRSNT_NODEF; - cgPtySad->typeSad.pres = 1; - cgPtySad->typeSad.val = 0; /* NSAP */ - cgPtySad->oddEvenInd.pres = 1; - cgPtySad->oddEvenInd.val = 0; - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending Calling Party Subaddress:%s\n", clg_subaddr); - cgPtySad->sadInfo.pres = 1; - cgPtySad->sadInfo.len = len; - memcpy(cgPtySad->sadInfo.val, clg_subaddr, len); - } - return FTDM_SUCCESS; -} - -ftdm_status_t set_called_subaddr(ftdm_channel_t *ftdmchan, CdPtySad *cdPtySad) -{ - const char* cld_subaddr = NULL; - cld_subaddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.called_subaddr"); - if (!ftdm_strlen_zero(cld_subaddr)) { - unsigned len = strlen (cld_subaddr); - cdPtySad->eh.pres = PRSNT_NODEF; - cdPtySad->typeSad.pres = 1; - cdPtySad->typeSad.val = 0; /* NSAP */ - cdPtySad->oddEvenInd.pres = 1; - cdPtySad->oddEvenInd.val = 0; - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending Called Party Subaddress:%s\n", cld_subaddr); - cdPtySad->sadInfo.pres = 1; - cdPtySad->sadInfo.len = len; - memcpy(cdPtySad->sadInfo.val, cld_subaddr, len); - } - return FTDM_SUCCESS; -} - -ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr) -{ - ftdm_status_t status; - status = set_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, (uint8_t*)&(facilityStr->facilityStr.len)); - if (status == FTDM_SUCCESS) { - facilityStr->eh.pres = PRSNT_NODEF; - facilityStr->facilityStr.pres = PRSNT_NODEF; - } - return status; -} - -ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t *data_len) -{ - ftdm_size_t len; - uint8_t *mydata; - void *vdata; - - if (ftdm_usrmsg_get_raw_data(ftdmchan->usrmsg, &vdata, &len) == FTDM_SUCCESS) { - mydata = vdata; - if (len > 2 && mydata[0] == SNGISDN_Q931_FACILITY_IE_ID) { - len = mydata[1]; - memcpy(data, &mydata[2], len); - *data_len = len; - return FTDM_SUCCESS; - } - } - return FTDM_FAIL; -} - -ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind) -{ - const char *str = NULL; - int descr = prog_ind.descr; - int loc = prog_ind.loc; - - str = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.prog_ind.descr"); - if (!ftdm_strlen_zero(str)) { - /* User wants to override progress indicator */ - descr = ftdm_str2ftdm_sngisdn_progind_descr(str); - } - - if (descr == SNGISDN_PROGIND_DESCR_INVALID) { - /* User does not want to send progress indicator */ - return FTDM_SUCCESS; - } - - str = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.prog_ind.loc"); - if (!ftdm_strlen_zero(str)) { - loc = ftdm_str2ftdm_sngisdn_progind_loc(str); - } - if (loc == SNGISDN_PROGIND_LOC_INVALID) { - loc = SNGISDN_PROGIND_LOC_USER; - } - - progInd->eh.pres = PRSNT_NODEF; - progInd->codeStand0.pres = PRSNT_NODEF; - progInd->codeStand0.val = IN_CSTD_CCITT; - - progInd->progDesc.pres = PRSNT_NODEF; - switch(descr) { - case SNGISDN_PROGIND_DESCR_NETE_ISDN: - progInd->progDesc.val = IN_PD_NOTETEISDN; - break; - case SNGISDN_PROGIND_DESCR_DEST_NISDN: - progInd->progDesc.val = IN_PD_DSTNOTISDN; - break; - case SNGISDN_PROGIND_DESCR_ORIG_NISDN: - progInd->progDesc.val = IN_PD_ORGNOTISDN; - break; - case SNGISDN_PROGIND_DESCR_RET_ISDN: - progInd->progDesc.val = IN_PD_CALLRET; - break; - case SNGISDN_PROGIND_DESCR_SERV_CHANGE: - /* Trillium defines do not match ITU-T Q931 Progress descriptions, - indicate a delayed response for now */ - progInd->progDesc.val = IN_PD_DELRESP; - break; - case SNGISDN_PROGIND_DESCR_IB_AVAIL: - progInd->progDesc.val = IN_PD_IBAVAIL; - break; - default: - ftdm_log(FTDM_LOG_WARNING, "Invalid prog_ind description:%d\n", descr); - progInd->progDesc.val = IN_PD_NOTETEISDN; - break; - } - - progInd->location.pres = PRSNT_NODEF; - switch (loc) { - case SNGISDN_PROGIND_LOC_USER: - progInd->location.val = IN_LOC_USER; - break; - case SNGISDN_PROGIND_LOC_PRIV_NET_LOCAL_USR: - progInd->location.val = IN_LOC_PRIVNETLU; - break; - case SNGISDN_PROGIND_LOC_PUB_NET_LOCAL_USR: - progInd->location.val = IN_LOC_PUBNETLU; - break; - case SNGISDN_PROGIND_LOC_TRANSIT_NET: - progInd->location.val = IN_LOC_TRANNET; - break; - case SNGISDN_PROGIND_LOC_PUB_NET_REMOTE_USR: - progInd->location.val = IN_LOC_PUBNETRU; - break; - case SNGISDN_PROGIND_LOC_PRIV_NET_REMOTE_USR: - progInd->location.val = IN_LOC_PRIVNETRU; - break; - case SNGISDN_PROGIND_LOC_NET_BEYOND_INTRW: - progInd->location.val = IN_LOC_NETINTER; - break; - default: - ftdm_log(FTDM_LOG_WARNING, "Invalid prog_ind location:%d\n", loc); - progInd->location.val = IN_LOC_USER; - } - return FTDM_SUCCESS; -} - -ftdm_status_t set_network_specific_fac(ftdm_channel_t *ftdmchan, NetFac *netFac) -{ - const char *str = NULL; - - str = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.netFac.spec"); - if (ftdm_strlen_zero(str)) { - /* Network-specific facility specification is mandatory, cannot send IE - without it */ - return FTDM_SUCCESS; - } else { - ftdm_sngisdn_netspecfac_spec_t spec = ftdm_str2ftdm_sngisdn_netspecfac_spec(str); - - netFac->eh.pres = PRSNT_NODEF; - netFac->netFacSpec.pres = PRSNT_NODEF; - - if (spec == SNGISDN_NETSPECFAC_SPEC_INVALID) { - int byte = 0; - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Non-standard NSF specified:%s\n", str); - - if (sscanf(str, "%x", &byte) == 1) { - netFac->netFacSpec.val[0] = byte & 0xFF; - } - - netFac->netFacSpec.len = 1; - } else { - /* User is using one of the pre-specified NSF's */ - netFac->netFacSpec.val[0] = get_trillium_val(nsf_spec_codes, spec, 0x00); - netFac->netFacSpec.len = 1; - } - } - - netFac->lenNetId.pres = PRSNT_NODEF; - netFac->lenNetId.val = 0; - - str = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.netFac.type"); - if (!ftdm_strlen_zero(str)) { - netFac->typeNetId.pres = PRSNT_NODEF; - netFac->typeNetId.val = ftdm_str2ftdm_sngisdn_netspecfac_type(str); - } - - str = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.netFac.plan"); - if (!ftdm_strlen_zero(str)) { - netFac->netIdPlan.pres = PRSNT_NODEF; - netFac->netIdPlan.val = ftdm_str2ftdm_sngisdn_netspecfac_plan(str); - } - - if (netFac->netIdPlan.pres == PRSNT_NODEF || netFac->typeNetId.pres == PRSNT_NODEF) { - netFac->lenNetId.val++; - } - - str = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.netFac.ident"); - if (!ftdm_strlen_zero(str)) { - netFac->lenNetId.val++; - - netFac->netId.pres = PRSNT_NODEF; - memcpy(netFac->netId.val, str, strlen(str)); - } - - return FTDM_SUCCESS; -} - -ftdm_status_t set_user_to_user_ie(ftdm_channel_t *ftdmchan, UsrUsr *usrUsr) -{ - sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; - - if (sngisdn_info->transfer_data.type == SNGISDN_TRANSFER_ATT_COURTESY_VRU_DATA) { - usrUsr->eh.pres = PRSNT_NODEF; - - usrUsr->protocolDisc.pres = PRSNT_NODEF; - usrUsr->protocolDisc.val = 0x08; - usrUsr->usrInfo.pres = PRSNT_NODEF; - usrUsr->usrInfo.len = strlen(sngisdn_info->transfer_data.tdata.att_courtesy_vru.data); - memcpy(usrUsr->usrInfo.val, sngisdn_info->transfer_data.tdata.att_courtesy_vru.data, usrUsr->usrInfo.len); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending AT&T Transfer data len:%d\n", usrUsr->usrInfo.len); - - return FTDM_SUCCESS; - } - - return FTDM_SUCCESS; -} - -ftdm_status_t set_cause_ie(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn) -{ - - causeDgn->eh.pres = PRSNT_NODEF; - causeDgn->location.pres = PRSNT_NODEF; - causeDgn->location.val = IN_LOC_PRIVNETLU; - causeDgn->codeStand3.pres = PRSNT_NODEF; - causeDgn->codeStand3.val = IN_CSTD_CCITT; - causeDgn->causeVal.pres = PRSNT_NODEF; - causeDgn->causeVal.val = ftdmchan->caller_data.hangup_cause; - causeDgn->recommend.pres = NOTPRSNT; - causeDgn->dgnVal.pres = NOTPRSNT; - return FTDM_SUCCESS; -} - -ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId) -{ - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data; - if (!ftdmchan) { - return FTDM_SUCCESS; - } - - ftdm_set_flag(sngisdn_info, FLAG_SENT_CHAN_ID); - - chanId->eh.pres = PRSNT_NODEF; - chanId->prefExc.pres = PRSNT_NODEF; - chanId->prefExc.val = IN_PE_EXCLSVE; - chanId->dChanInd.pres = PRSNT_NODEF; - chanId->dChanInd.val = IN_DSI_NOTDCHAN; - chanId->intIdentPres.pres = PRSNT_NODEF; - chanId->intIdentPres.val = IN_IIP_IMPLICIT; - - if (FTDM_SPAN_IS_BRI(ftdmchan->span)) { - - /* BRI only params */ - chanId->intType.pres = PRSNT_NODEF; - chanId->intType.val = IN_IT_BASIC; - chanId->infoChanSel.pres = PRSNT_NODEF; - chanId->infoChanSel.val = ftdmchan->physical_chan_id; - } else { - if (signal_data->nfas.trunk) { - chanId->intIdentPres.val = IN_IIP_EXPLICIT; - chanId->intIdent.pres = PRSNT_NODEF; - chanId->intIdent.val = signal_data->nfas.interface_id; - } - - chanId->intType.pres = PRSNT_NODEF; - chanId->intType.val = IN_IT_OTHER; - chanId->infoChanSel.pres = PRSNT_NODEF; - chanId->infoChanSel.val = IN_ICS_B1CHAN; - chanId->chanMapType.pres = PRSNT_NODEF; - chanId->chanMapType.val = IN_CMT_BCHAN; - chanId->nmbMap.pres = PRSNT_NODEF; - chanId->nmbMap.val = IN_NM_CHNNMB; - chanId->codeStand1.pres = PRSNT_NODEF; - chanId->codeStand1.val = IN_CSTD_CCITT; - chanId->chanNmbSlotMap.pres = PRSNT_NODEF; - chanId->chanNmbSlotMap.len = 1; - chanId->chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id; - } - - return FTDM_SUCCESS; -} - -ftdm_status_t set_bear_cap_ie(ftdm_channel_t *ftdmchan, BearCap *bearCap) -{ - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - bearCap->eh.pres = PRSNT_NODEF; - bearCap->infoTranCap.pres = PRSNT_NODEF; - bearCap->infoTranCap.val = sngisdn_get_infoTranCap_from_user(ftdmchan->caller_data.bearer_capability); - - bearCap->codeStand0.pres = PRSNT_NODEF; - bearCap->codeStand0.val = IN_CSTD_CCITT; - bearCap->infoTranRate0.pres = PRSNT_NODEF; - bearCap->infoTranRate0.val = IN_ITR_64KBIT; - bearCap->tranMode.pres = PRSNT_NODEF; - bearCap->tranMode.val = IN_TM_CIRCUIT; - - bearCap->usrInfoLyr1Prot.pres = PRSNT_NODEF; - bearCap->usrInfoLyr1Prot.val = sngisdn_get_usrInfoLyr1Prot_from_user(ftdmchan->caller_data.bearer_layer1); - - switch (signal_data->switchtype) { - case SNGISDN_SWITCH_NI2: - case SNGISDN_SWITCH_4ESS: - case SNGISDN_SWITCH_5ESS: - case SNGISDN_SWITCH_DMS100: - case SNGISDN_SWITCH_INSNET: - if (bearCap->usrInfoLyr1Prot.val == IN_UIL1_G711ALAW) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Overriding bearer cap to u-law\n"); - bearCap->usrInfoLyr1Prot.val = IN_UIL1_G711ULAW; - } - break; - case SNGISDN_SWITCH_EUROISDN: - case SNGISDN_SWITCH_QSIG: - if (bearCap->usrInfoLyr1Prot.val == IN_UIL1_G711ULAW) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Overriding bearer cap to a-law\n"); - bearCap->usrInfoLyr1Prot.val = IN_UIL1_G711ALAW; - } - break; - } - - bearCap->lyr1Ident.pres = PRSNT_NODEF; - bearCap->lyr1Ident.val = IN_L1_IDENT; - - return FTDM_SUCCESS; -} - -ftdm_status_t set_restart_ind_ie(ftdm_channel_t *ftdmchan, RstInd *rstInd) -{ - rstInd->eh.pres = PRSNT_NODEF; - rstInd->rstClass.pres = PRSNT_NODEF; - rstInd->rstClass.val = IN_CL_INDCHAN; - return FTDM_SUCCESS; -} - -ftdm_status_t set_not_ind_ie(ftdm_channel_t *ftdmchan, NotInd *notInd) -{ - notInd->eh.pres = PRSNT_NODEF; - notInd->notDesc.pres = PRSNT_NODEF; - notInd->notDesc.val = 0x71; /* Call information event */ - return FTDM_SUCCESS; -} - -void sngisdn_t3_timeout(void *p_sngisdn_info) -{ - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Timer T3 expired (suId:%d suInstId:%u spInstId:%u)\n", - signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId); - ftdm_mutex_lock(ftdmchan->mutex); - if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)){ - /* PHY layer timed-out, need to clear the call */ - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Failed to Wake-Up line (suId:%d suInstId:%u spInstId:%u)\n", - signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId); - - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NO_ROUTE_DESTINATION; - ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING); - ftdm_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - } - ftdm_mutex_unlock(ftdmchan->mutex); -} - - -void sngisdn_delayed_dl_req(void *p_signal_data) -{ - ftdm_signaling_status_t sigstatus = FTDM_SIG_STATE_DOWN; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t *)p_signal_data; - ftdm_span_t *span = signal_data->ftdm_span; - - if (!signal_data->dl_request_pending) { - return; - } - - ftdm_span_get_sig_status(span, &sigstatus); - if (sigstatus == FTDM_SIG_STATE_UP) { - signal_data->dl_request_pending = 0; - return; - } - - sngisdn_snd_dl_req(span->channels[1]); - ftdm_sched_timer(signal_data->sched, "delayed_dl_req", 4000, sngisdn_delayed_dl_req, (void*) signal_data, NULL); - - return; -} - -void sngisdn_restart_timeout(void *p_signal_data) -{ - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t *)p_signal_data; - ftdm_span_t *span = signal_data->ftdm_span; - ftdm_iterator_t *chaniter = NULL; - ftdm_iterator_t *curr = NULL; - - ftdm_log(FTDM_LOG_DEBUG, "s%s:Did not receive a RESTART from remote switch in %d ms - restarting\n", span->name, signal_data->restart_timeout); - - chaniter = ftdm_span_get_chan_iterator(span, NULL); - for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { - ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr); - if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) { - ftdm_mutex_lock(ftdmchan->mutex); - if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESET); - } - ftdm_mutex_unlock(ftdmchan->mutex); - } - } - return; -} - -void sngisdn_delayed_setup(void *p_sngisdn_info) -{ - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - - ftdm_mutex_lock(ftdmchan->mutex); - sngisdn_snd_setup(ftdmchan); - ftdm_mutex_unlock(ftdmchan->mutex); - return; -} - -void sngisdn_delayed_release_nfas(void *p_sngisdn_info) -{ - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - ftdm_mutex_lock(ftdmchan->mutex); - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending delayed RELEASE (suId:%d suInstId:%u spInstId:%u)\n", - signal_data->cc_id, sngisdn_info->spInstId, sngisdn_info->suInstId); - - sngisdn_snd_release(ftdmchan, 0); - - ftdm_mutex_unlock(ftdmchan->mutex); - return; -} - -void sngisdn_delayed_release(void *p_sngisdn_info) -{ - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - ftdm_mutex_lock(ftdmchan->mutex); - - if (ftdm_test_flag(sngisdn_info, FLAG_DELAYED_REL)) { - ftdm_clear_flag(sngisdn_info, FLAG_DELAYED_REL); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending delayed RELEASE (suId:%d suInstId:%u spInstId:%u)\n", - signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId); - - sngisdn_snd_release(ftdmchan, 1); - clear_call_glare_data(sngisdn_info); - } else { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Call was already released (suId:%d suInstId:%u spInstId:%u)\n", - signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId); - } - ftdm_mutex_unlock(ftdmchan->mutex); - return; -} - -void sngisdn_delayed_connect(void *p_sngisdn_info) -{ - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - ftdm_mutex_lock(ftdmchan->mutex); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending delayed CONNECT (suId:%d suInstId:%u spInstId:%u)\n", - signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId); - - sngisdn_snd_connect(ftdmchan); - ftdm_mutex_unlock(ftdmchan->mutex); - return; -} - -void sngisdn_delayed_disconnect(void *p_sngisdn_info) -{ - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - ftdm_mutex_lock(ftdmchan->mutex); - if (ftdmchan->caller_data.hangup_cause == IN_CCNORTTODEST || ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending delayed DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n", - signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId); - - sngisdn_snd_disconnect(ftdmchan); - if (ftdmchan->caller_data.hangup_cause == IN_CCNORTTODEST) { - ftdm_channel_t *close_chan = ftdmchan; - ftdm_channel_close(&close_chan); - } - } - - ftdm_mutex_unlock(ftdmchan->mutex); - return; -} - -void sngisdn_facility_timeout(void *p_sngisdn_info) -{ - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - ftdm_mutex_lock(ftdmchan->mutex); - if (ftdmchan->state == FTDM_CHANNEL_STATE_GET_CALLERID) { - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Facility timeout reached proceeding with call (suId:%d suInstId:%u spInstId:%u)\n", - signal_data->cc_id, sngisdn_info->spInstId, sngisdn_info->suInstId); - - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); - } - - ftdm_mutex_unlock(ftdmchan->mutex); - return; -} - -ftdm_status_t sngisdn_check_free_ids(void) -{ - unsigned i; - unsigned j; - ftdm_log(FTDM_LOG_INFO, "Checking suInstId's\n"); - for(j=1;j<=MAX_VARIANTS;j++) { - if (g_sngisdn_data.ccs[j].config_done) { - for(i=1;isignal_data; - - memset(&sts, 0, sizeof(sts)); - sng_isdn_phy_stats(sngisdn_dchan(signal_data)->link_id , &sts); - - stream->write_function(stream, "\n---------------------------------------------------------------------\n"); - stream->write_function(stream, " Span:%s", span->name); - stream->write_function(stream, "\n---------------------------------------------------------------------\n"); - stream->write_function(stream, " Performance Counters"); - stream->write_function(stream, "\n---------------------------------------------------------------------\n"); - stream->write_function(stream, "RX Packets:\t%u\tTX Packets:\t%u\tEvents:%u\n", sts.t.sts.rx_packets, sts.t.sts.tx_packets, sts.t.sts.rx_events); - stream->write_function(stream, "RX Bytes:\t%u\tTX Bytes:\t%u\n\n", sts.t.sts.rx_bytes, sts.t.sts.tx_bytes); - stream->write_function(stream, "TX Queue:\t%u/%u\tRX Queue:\t%u/%u\tEvents Queue:\t%u/%u\n", - sts.t.sts.num_frames_in_tx_queue,sts.t.sts.tx_queue_len, - sts.t.sts.num_frames_in_rx_queue, sts.t.sts.rx_queue_len, - sts.t.sts.rx_events_in_queue, sts.t.sts.event_queue_len); - - stream->write_function(stream, "\n---------------------------------------------------------------------\n"); - stream->write_function(stream, " Errors"); - stream->write_function(stream, "\n---------------------------------------------------------------------\n"); - stream->write_function(stream, "RX Errors:\t%u\tTX Errors:\t%u\n", sts.t.sts.rx_errors, sts.t.sts.tx_errors); - stream->write_function(stream, "RX Dropped:\t%u\tTX Dropped:\t%u\tEvents Dropped:\t%u\n", sts.t.sts.rx_dropped, sts.t.sts.tx_dropped,sts.t.sts.rx_events_dropped); - - - stream->write_function(stream, "\n---------------------------------------------------------------------\n"); - stream->write_function(stream, " RX Errors Details"); - stream->write_function(stream, "\n---------------------------------------------------------------------\n"); - stream->write_function(stream, "CRC:\t\t%u\tFrame:\t\t%u\tOverruns:\t%u\n", sts.t.sts.rx_crc_errors, sts.t.sts.rx_frame_errors, sts.t.sts.rx_over_errors); - stream->write_function(stream, "Fifo:\t\t%u\tAborts:\t\t%u\tMissed:\t\t%u\n", sts.t.sts.rx_fifo_errors, sts.t.sts.rx_hdlc_abort_counter, sts.t.sts.rx_missed_errors); - stream->write_function(stream, "Length:\t\t%u\n", sts.t.sts.rx_length_errors); - - stream->write_function(stream, "\n---------------------------------------------------------------------\n"); - stream->write_function(stream, " TX Errors Details"); - stream->write_function(stream, "\n---------------------------------------------------------------------\n"); - stream->write_function(stream, "Aborted:\t%u\tFifo:\t\t%u\tCarrier:\t%u\n", sts.t.sts.tx_aborted_errors, sts.t.sts.tx_fifo_errors, sts.t.sts.tx_carrier_errors); - return FTDM_SUCCESS; -} - - -ftdm_status_t sngisdn_show_span(ftdm_stream_handle_t *stream, ftdm_span_t *span) -{ - ftdm_signaling_status_t sigstatus; - ftdm_alarm_flag_t alarmbits; - ftdm_channel_t *fchan; - alarmbits = FTDM_ALARM_NONE; - fchan = ftdm_span_get_channel(span, 1); - if (fchan) { - ftdm_channel_get_alarms(fchan, &alarmbits); - } - - ftdm_span_get_sig_status(span, &sigstatus); - stream->write_function(stream, "span:%s physical:%s signalling:%s\n", - span->name, alarmbits ? "ALARMED" : "OK", - ftdm_signaling_status2str(sigstatus)); - return FTDM_SUCCESS; -} - -ftdm_status_t sngisdn_show_spans(ftdm_stream_handle_t *stream) -{ - int i; - for(i=1;i<=MAX_L1_LINKS;i++) { - if (g_sngisdn_data.spans[i]) { - sngisdn_show_span(stream, g_sngisdn_data.spans[i]->ftdm_span); - } - } - return FTDM_SUCCESS; -} - -ftdm_status_t sngisdn_add_var(sngisdn_chan_data_t *sngisdn_info, const char* var, const char* val) -{ - char *t_name = 0, *t_val = 0; - if (!var || !val) { - return FTDM_FAIL; - } - if (!sngisdn_info->variables) { - /* initialize on first use */ - sngisdn_info->variables = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); - ftdm_assert_return(sngisdn_info->variables, FTDM_FAIL, "Failed to create hash table\n"); - } - t_name = ftdm_strdup(var); - t_val = ftdm_strdup(val); - hashtable_insert(sngisdn_info->variables, t_name, t_val, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_FLAG_FREE_VALUE); - return FTDM_SUCCESS; -} - -ftdm_status_t sngisdn_add_raw_data(sngisdn_chan_data_t *sngisdn_info, uint8_t* data, ftdm_size_t data_len) -{ - ftdm_assert_return(!sngisdn_info->raw_data, FTDM_FAIL, "Overwriting existing raw data\n"); - - sngisdn_info->raw_data = ftdm_calloc(1, data_len); - ftdm_assert_return(sngisdn_info->raw_data, FTDM_FAIL, "Failed to allocate raw data\n"); - - memcpy(sngisdn_info->raw_data, data, data_len); - sngisdn_info->raw_data_len = data_len; - return FTDM_SUCCESS; -} - -void sngisdn_send_signal(sngisdn_chan_data_t *sngisdn_info, ftdm_signal_event_t event_id) -{ - ftdm_sigmsg_t sigev; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - - memset(&sigev, 0, sizeof(sigev)); - - sigev.chan_id = ftdmchan->chan_id; - sigev.span_id = ftdmchan->span_id; - sigev.channel = ftdmchan; - sigev.event_id = event_id; - - if (sngisdn_info->variables) { - /* - * variables now belongs to the ftdm core, and - * will be cleared after sigev is processed by user. Set - * local pointer to NULL so we do not attempt to - * destroy it */ - sigev.variables = sngisdn_info->variables; - sngisdn_info->variables = NULL; - } - - if (sngisdn_info->raw_data) { - /* - * raw_data now belongs to the ftdm core, and - * will be cleared after sigev is processed by user. Set - * local pointer to NULL so we do not attempt to - * destroy it */ - - sigev.raw.data = sngisdn_info->raw_data; - sigev.raw.len = sngisdn_info->raw_data_len; - - sngisdn_info->raw_data = NULL; - sngisdn_info->raw_data_len = 0; - } - if (event_id == FTDM_SIGEVENT_TRANSFER_COMPLETED) { - sigev.ev_data.transfer_completed.response = sngisdn_info->transfer_data.response; - } - ftdm_span_send_signal(ftdmchan->span, &sigev); -} - -sngisdn_span_data_t *sngisdn_dchan(sngisdn_span_data_t *signal_data) -{ - if (!signal_data) { - return NULL; - } - - if (!signal_data->nfas.trunk) { - return signal_data; - } - return signal_data->nfas.trunk->dchan; -} - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c deleted file mode 100644 index 56797fbf9c..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c +++ /dev/null @@ -1,996 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * David Yat Sin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ftmod_sangoma_isdn.h" -#include "ftmod_sangoma_isdn_trace.h" - -#define OCTET(x) (ieData[x-1] & 0xFF) -#define MAX_DECODE_STR_LEN 2000 - -typedef struct sngisdn_trace_info -{ - uint8_t call_ref_flag; - uint16_t call_ref; - uint8_t msgtype; - uint8_t bchan_no; - ftdm_trace_dir_t dir; -} sngisdn_frame_info_t; - -void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_start, uint32_t index_end); -uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset, uint8_t *data, uint16_t index_start); -static ftdm_status_t sngisdn_map_call(sngisdn_span_data_t *signal_data, sngisdn_frame_info_t frame_info, ftdm_channel_t **found); -static ftdm_status_t sngisdn_get_frame_info(uint8_t *data, uint32_t data_len, ftdm_trace_dir_t dir, sngisdn_frame_info_t *frame_info); - -uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi); -char* get_code_2_str(int code, struct code2str *pCodeTable); -void sngisdn_decode_q921(char* str, uint8_t* data, uint32_t data_len); -void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len); - - -char* get_code_2_str(int code, struct code2str *pCodeTable) -{ - struct code2str* pCode2txt; - pCode2txt = pCodeTable; - while(pCode2txt) { - if(pCode2txt->code >= 0) { - if (pCode2txt->code == code) { - return pCode2txt->text; - } - pCode2txt++; - } else { - /* This is the default value from the table */ - return pCode2txt->text; - } - } - return (char*)"unknown"; -} - - -uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi) -{ - if (!bitLo || !bitHi) { - return 0; - } - if (bitLo > bitHi) { - return 0; - } - - bitLo--; - bitHi--; - - switch(bitHi - bitLo) { - case 0: - return (octet >> bitLo) & 0x01; - case 1: - return (octet >> bitLo) & 0x03; - case 2: - return (octet >> bitLo) & 0x07; - case 3: - return (octet >> bitLo) & 0x0F; - case 4: - return (octet >> bitLo) & 0x1F; - case 5: - return (octet >> bitLo) & 0x3F; - case 6: - return (octet >> bitLo) & 0x7F; - case 7: - return (octet >> bitLo) & 0xFF; - } - return 0; -} - -void sngisdn_trace_interpreted_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len) -{ - char *data_str = ftdm_calloc(1,500); /* TODO Find a proper size */ - sngisdn_decode_q921(data_str, data, data_len); - ftdm_log(FTDM_LOG_DEBUG, "[SNGISDN Q921] %s FRAME %s:\n%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str); - ftdm_safe_free(data_str); -} - -void sngisdn_trace_raw_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len) -{ - uint8_t *raw_data; - ftdm_sigmsg_t sigev; - - memset(&sigev, 0, sizeof(sigev)); - - sigev.span_id = signal_data->ftdm_span->span_id; - sigev.chan_id = signal_data->dchan->chan_id; - sigev.channel = signal_data->dchan; - sigev.event_id = FTDM_SIGEVENT_TRACE_RAW; - - sigev.ev_data.trace.dir = dir; - sigev.ev_data.trace.type = FTDM_TRACE_TYPE_Q921; - - raw_data = ftdm_malloc(data_len); - ftdm_assert(raw_data, "Failed to malloc"); - - memcpy(raw_data, data, data_len); - sigev.raw.data = raw_data; - sigev.raw.len = data_len; - ftdm_span_send_signal(signal_data->ftdm_span, &sigev); -} - -void sngisdn_decode_q921(char* str, uint8_t* data, uint32_t data_len) -{ - uint32_t str_len; - uint32_t i; - uint8_t sapi, cr, ea, tei, ns, nr, pf, p, cmd; - uint8_t frame_format = 0; - - str_len = 0; - - if(data_len >= 2) { - switch ((int)data[2] & 0x03) { - case 0: case 2: - frame_format = I_FRAME; - break; - case 1: - frame_format = S_FRAME; - break; - case 3: - frame_format = U_FRAME; - break; - } - } - - str_len+= sprintf(&str[str_len], " format: %s\n", - get_code_2_str(frame_format, dcodQ921FrameFormatTable)); - - for(i=0; i < data_len; i++) { - switch(i) { - case 0: // Octet 2 - sapi = (uint8_t)((data[i]>>2) & 0x3F); - cr = (uint8_t)((data[i]>>1) & 0x1); - ea = (uint8_t)(data[i] & 0x1); - str_len+= sprintf(&str[str_len], " sapi: %03d c/r: %01d ea: %01d\n", sapi, cr, ea); - break; - case 1: - tei = (uint8_t)((data[i]>>1) & 0x7F); - ea = (uint8_t)(data[i] & 0x1); - str_len+= sprintf(&str[str_len], " tei: %03d ea: %01d\n", tei, ea); - break; - case 2: - switch(frame_format) { - case I_FRAME: - ns = (uint8_t)((data[i]>>1) & 0x7F); - nr = (uint8_t)((data[i+1]>>1) & 0x7F); - p = (uint8_t)(data[i+1] & 0x01); - str_len+= sprintf(&str[str_len], " n(s): %03d\n n(r): %03d p: %01d\n", ns, nr, p); - break; - case S_FRAME: - nr = (uint8_t)((data[i+1]>>1) & 0x7F); - pf = (uint8_t)(data[i+1] & 0x01); - str_len+= sprintf(&str[str_len], " n(r): %03d p/f: %01d\n", nr, pf); - - cmd = (uint8_t)((data[i]>>2) & 0x03); - str_len+= sprintf(&str[str_len], " cmd: %s\n", get_code_2_str(cmd, dcodQ921SupervisoryCmdTable)); - - break; - case U_FRAME: - pf = (uint8_t)((data[i]>>4) & 0x01); - str_len+= sprintf(&str[str_len], " p/f: %01d\n", pf); - - cmd = (uint8_t)((data[i]>>2) & 0x03); - cmd |= (uint8_t)((data[i]>>5) & 0x07); - - str_len+= sprintf(&str[str_len], " cmd: %s\n", get_code_2_str(cmd, dcodQ921UnnumberedCmdTable)); - break; - } - break; - } - } - - print_hex_dump(str, &str_len, (uint8_t*) data, 0, data_len); - return; -} - - -void sngisdn_trace_interpreted_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len) -{ - char *data_str = ftdm_calloc(1,MAX_DECODE_STR_LEN); /* TODO Find a proper size */ - sngisdn_decode_q931(data_str, data, data_len); - ftdm_log(FTDM_LOG_DEBUG, "[SNGISDN Q931] %s FRAME %s:\n%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str); - ftdm_safe_free(data_str); -} - -void sngisdn_trace_raw_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len) -{ - uint8_t *raw_data; - ftdm_sigmsg_t sigev; - ftdm_channel_t *ftdmchan = NULL; - sngisdn_frame_info_t frame_info; - - memset(&sigev, 0, sizeof(sigev)); - - /* Note: Mapped raw trace assume only exclusive b-channel selection is used. i.e the b-channel selected on outgoing SETUP is always used for the call */ - - if (sngisdn_get_frame_info(data, data_len, dir, &frame_info) == FTDM_SUCCESS) { - if (sngisdn_map_call(signal_data, frame_info, &ftdmchan) == FTDM_SUCCESS) { - sigev.call_id = ftdmchan->caller_data.call_id; - sigev.span_id = ftdmchan->physical_span_id; - sigev.chan_id = ftdmchan->physical_chan_id; - sigev.channel = ftdmchan; - } else { - /* We could not map the channel, but at least set the span */ - if (signal_data->ftdm_span->channels[1]) { - sigev.span_id = signal_data->ftdm_span->channels[1]->physical_span_id; - } - } - sigev.event_id = FTDM_SIGEVENT_TRACE_RAW; - - sigev.ev_data.trace.dir = dir; - sigev.ev_data.trace.type = FTDM_TRACE_TYPE_Q931; - - raw_data = ftdm_malloc(data_len); - ftdm_assert(raw_data, "Failed to malloc"); - - memcpy(raw_data, data, data_len); - sigev.raw.data = raw_data; - sigev.raw.len = data_len; - ftdm_span_send_signal(signal_data->ftdm_span, &sigev); - } -} - -void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len) -{ - uint32_t str_len; - uint8_t prot_disc, callRefFlag; - uint16_t lenCallRef, c, i; - uint8_t current_codeset = 0; - - str_len = 0; - - /* Decode Protocol Discrimator */ - prot_disc = (uint8_t)data[0]; - str_len += sprintf(&str[str_len], " Prot Disc:%s (0x%02x)\n", get_code_2_str(prot_disc, dcodQ931ProtDiscTable), prot_disc); - - /* Decode Call Reference */ - lenCallRef = (uint8_t) (data[1] & 0x0F); - - str_len += sprintf(&str[str_len], " Call Ref:"); - c=2; - callRefFlag = get_bits(data[c], 8,8); - for(i=0; i<(2*lenCallRef);i++) { - if(i==0) { - str_len += sprintf(&str[str_len], "%s%s", - get_code_2_str((uint8_t)(data[c] & 0x70), dcodQ931CallRefHiTable), - get_code_2_str((uint8_t)(data[c] & 0x0F), dcodQ931CallRefLoTable)); - } else { - str_len += sprintf(&str[str_len], "%s%s", - get_code_2_str((uint8_t)(data[c] & 0xF0), dcodQ931CallRefHiTable), - get_code_2_str((uint8_t)(data[c] & 0x0F), dcodQ931CallRefLoTable)); - } - - i=i+1; - c=c+1; - } - str_len += sprintf(&str[str_len], " (%s side)\n", callRefFlag?"Destination":"Originating"); - - /* Decode message type */ - str_len+= sprintf(&str[str_len], " Type:%s (0x%x)\n", get_code_2_str((int)(data[2+lenCallRef] & 0xFF), dcodQ931MsgTypeTable), (int)(data[2+lenCallRef] & 0xFF)); - - /* go through rest of data and look for important info */ - for(i=3+lenCallRef; i < data_len; i++) { - switch (data[i] & 0xF8) { - case Q931_LOCKING_SHIFT: - current_codeset = (data[i] & 0x7); - str_len+= sprintf(&str[str_len], "Codeset shift to %d (locking)\n", current_codeset); - continue; - case Q931_NON_LOCKING_SHIFT: - current_codeset = (data[i] & 0x7); - str_len+= sprintf(&str[str_len], "Codeset shift to %d (non-locking)\n", current_codeset); - continue; - } - i+= sngisdn_decode_ie(str, &str_len, current_codeset, data, i); - } - print_hex_dump(str, &str_len, (uint8_t*) data, 0, data_len); - return; -} - -uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset, uint8_t *data, uint16_t index_start) -{ - unsigned char* ieData; - uint8_t ieId; - uint32_t len = 0; - int index_end; - - ieData = (unsigned char*) &data[index_start]; - - ieId = OCTET(1); - len = OCTET(2); - index_end = index_start+len+1; - - *str_len += sprintf(&str[*str_len], " %s:", get_code_2_str(data[index_start], dcodQ931IEIDTable)); - switch(ieId) { - case PROT_Q931_IE_BEARER_CAP: - { - uint8_t codingStandard, infTransferCap, infTransferRate, usrL1Prot; - /*uint8_t transferMode;*/ - - codingStandard = get_bits(OCTET(3),6,7); - infTransferCap = get_bits(OCTET(3),1,5); - /*transferMode = get_bits(OCTET(4),6,7);*/ - infTransferRate = get_bits(OCTET(4),1,5); - usrL1Prot = get_bits(OCTET(5),1,5); - - *str_len+= sprintf(&str[*str_len], "Coding:%s(%d) TransferCap:%s(%d) TransferRate:%s(%d) L1Prot:%s(%d)\n", - get_code_2_str(codingStandard, dcodQ931BcCodingStandardTable), codingStandard, - get_code_2_str(infTransferCap, dcodQ931BcInfTransferCapTable), infTransferCap, - get_code_2_str(infTransferRate, dcodQ931BcInfTransferRateTable), infTransferRate, - get_code_2_str(usrL1Prot, dcodQ931BcusrL1ProtTable), usrL1Prot); - } - break; - case PROT_Q931_IE_CAUSE: - { - uint8_t codingStandard, location, cause,diagOct = 5; - codingStandard = get_bits(OCTET(3),6,7); - location = get_bits(OCTET(3),1,4); - - cause = get_bits(OCTET(4),1,7); - - *str_len+= sprintf(&str[*str_len], "coding:%s(%d) location:%s(%d) val:%s(%d)\n", - get_code_2_str(codingStandard, dcodQ931BcCodingStandardTable), codingStandard, - get_code_2_str(location,dcodQ931IelocationTable), location, - get_code_2_str(cause, dcodQ931CauseCodeTable), - cause); - switch(cause) { - case PROT_Q931_RELEASE_CAUSE_IE_NOT_EXIST: - while(diagOct++ < len) { - *str_len+= sprintf(&str[*str_len], " %d:IE %s(0x%02x)\n", - diagOct, - get_code_2_str(OCTET(diagOct), dcodQ931IEIDTable), - OCTET(diagOct)); - } - break; - case PROT_Q931_RELEASE_CAUSE_WRONG_CALL_STATE: - while(diagOct++ < len) { - *str_len+= sprintf(&str[*str_len], " %d:Message %s(0x%02x)\n", - diagOct, - get_code_2_str(OCTET(diagOct), dcodQ931MsgTypeTable), - OCTET(diagOct)); - } - break; - case PROT_Q931_RECOVERY_ON_TIMER_EXPIRE: - *str_len+= sprintf(&str[*str_len], " Timer T\n"); - while(diagOct++ < len) { - if(OCTET(diagOct) >= ' ' && OCTET(diagOct) < 0x7f) { - *str_len+= sprintf(&str[*str_len], "%c", OCTET(diagOct)); - } else { - *str_len+= sprintf(&str[*str_len], "."); - } - } - break; - default: - while(diagOct++ < len) { - *str_len+= sprintf(&str[*str_len], " %d: 0x%02x\n", - diagOct, - OCTET(diagOct)); - } - break; - } - } - break; - case PROT_Q931_IE_CHANNEL_ID: - { - uint8_t infoChannelSelection=0; - uint8_t prefExclusive=0; - uint8_t ifaceIdPresent=0; - /* uint8_t ifaceIdentifier = 0; */ /* octet_3_1 */ - uint8_t chanType=0, numberMap=0; - /* uint8_t codingStandard=0; */ - uint8_t channelNo = 0; - - infoChannelSelection = get_bits(OCTET(3),1,2); - prefExclusive = get_bits(OCTET(3),4,4); - ifaceIdPresent = get_bits(OCTET(3),7,7); - - if (ifaceIdPresent) { - /*ifaceIdentifier= get_bits(OCTET(4),1,7);*/ - chanType = get_bits(OCTET(5),1,4); - numberMap = get_bits(OCTET(5),5,5); - /*codingStandard = get_bits(OCTET(5),6,7);*/ - channelNo = get_bits(OCTET(6),1,7); - } else { - chanType = get_bits(OCTET(4),1,4); - numberMap = get_bits(OCTET(4),5,5); - /*codingStandard = get_bits(OCTET(4),6,7);*/ - channelNo = get_bits(OCTET(5),1,7); - } - - if (numberMap) { - *str_len+= sprintf(&str[*str_len], " MAP:%s ", get_code_2_str(infoChannelSelection, dcodQ931InfoChannelSelTable)); - } else { - *str_len+= sprintf(&str[*str_len], "No:%d ", channelNo); - } - - *str_len+= sprintf(&str[*str_len], "Type:%s(%d) %s ", get_code_2_str(chanType,dcodQ931ChanTypeTable), chanType, (numberMap)? "Map":""); - *str_len+= sprintf(&str[*str_len], "%s/%s \n", - (prefExclusive)? "Exclusive":"Preferred", - (ifaceIdPresent)? "Explicit":"Implicit"); - } - break; - case PROT_Q931_IE_CALLING_PARTY_NUMBER: - { - uint8_t plan, type, screening = 0, presentation = 0, callingNumOct, j; - uint8_t screeningEnabled = 0, presentationEnabled = 0; - char callingNumDigits[32]; - memset(callingNumDigits, 0, sizeof(callingNumDigits)); - - plan = get_bits(OCTET(3),1,4); - type = get_bits(OCTET(3),5,7); - - if(!get_bits(OCTET(3),8,8)) { - screening = get_bits(OCTET(4),1,2); - presentation = get_bits(OCTET(4),6,7); - screeningEnabled = 1; - presentationEnabled = 1; - callingNumOct = 4; - } else { - callingNumOct = 3; - } - if(len >= sizeof(callingNumDigits)) { - len = sizeof(callingNumDigits)-1; - } - j = 0; - while(callingNumOct++ <= len+1) { - callingNumDigits[j++]=ia5[get_bits(OCTET(callingNumOct),1,4)][get_bits(OCTET(callingNumOct),5,8)]; - } - callingNumDigits[j]='\0'; - *str_len+= sprintf(&str[*str_len], "%s(l:%d) plan:%s(%d) type:%s(%d)", - - callingNumDigits, j, - get_code_2_str(plan, dcodQ931NumberingPlanTable), plan, - get_code_2_str(type, dcodQ931TypeofNumberTable), type); - - if (presentationEnabled||screeningEnabled) { - *str_len+= sprintf(&str[*str_len], "scr:%s(%d) pres:%s(%d)\n", - get_code_2_str(screening, dcodQ931ScreeningTable), screening, - get_code_2_str(presentation, dcodQ931PresentationTable), presentation); - } else { - *str_len+= sprintf(&str[*str_len], "\n"); - } - } - break; - - case PROT_Q931_IE_CALLED_PARTY_NUMBER: - { - uint8_t plan, type, calledNumOct,j; - char calledNumDigits[32]; - memset(calledNumDigits, 0, sizeof(calledNumDigits)); - plan = get_bits(OCTET(3),1,4); - type = get_bits(OCTET(3),5,7); - - if(len >= sizeof(calledNumDigits)) { - len = sizeof(calledNumDigits)-1; - } - calledNumOct = 3; - j = 0; - while(calledNumOct++ <= len+1) { - calledNumDigits[j++]=ia5[get_bits(OCTET(calledNumOct),1,4)][get_bits(OCTET(calledNumOct),5,8)]; - } - calledNumDigits[j]='\0'; - *str_len+= sprintf(&str[*str_len], "%s(l:%d) plan:%s(%d) type:%s(%d)\n", - calledNumDigits, j, - get_code_2_str(plan, dcodQ931NumberingPlanTable), plan, - get_code_2_str(type, dcodQ931TypeofNumberTable), type); - } - break; - case PROT_Q931_IE_REDIRECTING_NUMBER: //rdnis - { - uint8_t plan, type, screening = 0, presentation = 0, reason = 0, rdnisOct,j; - uint8_t screeningEnabled = 0, presentationEnabled = 0, reasonEnabled = 0; - char rdnis_string[32]; - memset(rdnis_string, 0, sizeof(rdnis_string)); - rdnisOct = 5; - plan = get_bits(OCTET(3),1,4); - type = get_bits(OCTET(3),5,7); - - if(!get_bits(OCTET(3),8,8)) { //Oct 3a exists - rdnisOct++; - screening = get_bits(OCTET(4),1,2); - presentation = get_bits(OCTET(4),6,7); - screeningEnabled = 1; - presentationEnabled = 1; - if (!get_bits(OCTET(4),8,8)) { //Oct 3b exists - rdnisOct++; - reason = get_bits(OCTET(5),1,4); - reasonEnabled = 1; - } - } - - if(len >= sizeof(rdnis_string)) { - len = sizeof(rdnis_string)-1; - } - - j = 0; - while(rdnisOct++ <= len+1) { - rdnis_string[j++]=ia5[get_bits(OCTET(rdnisOct),1,4)][get_bits(OCTET(rdnisOct),5,8)]; - } - - rdnis_string[j]='\0'; - *str_len+= sprintf(&str[*str_len], "%s(l:%d) plan:%s(%d) type:%s(%d)", - rdnis_string, j, - get_code_2_str(plan, dcodQ931NumberingPlanTable), plan, - get_code_2_str(type, dcodQ931TypeofNumberTable), type); - - if(presentationEnabled || screeningEnabled) { - *str_len+= sprintf(&str[*str_len], "scr:%s(%d) pres:%s(%d)", - get_code_2_str(screening, dcodQ931ScreeningTable), screening, - get_code_2_str(presentation, dcodQ931PresentationTable), presentation); - } - - if(reasonEnabled) { - *str_len+= sprintf(&str[*str_len], "reason:%s(%d)", - get_code_2_str(reason, dcodQ931ReasonTable), reason); - } - *str_len+= sprintf(&str[*str_len], "\n"); - } - break; - case PROT_Q931_IE_USER_USER: - { - uint8_t protDiscr = 0x00, j, uui_stringOct; - char uui_string[32]; - memset(uui_string, 0, sizeof(uui_string)); - protDiscr = OCTET(3); - uui_stringOct = 3; - if (protDiscr != 0x04) { /* Non-IA5 */ - *str_len+= sprintf(&str[*str_len], "%s (0x%02x)\n", - get_code_2_str(protDiscr, dcodQ931UuiProtDiscrTable), protDiscr); - } else { - j = 0; - - if(len >= sizeof(uui_string)) { - len = sizeof(uui_string)-1; - } - while(uui_stringOct++ <= len+1) { - uui_string[j++]=ia5[get_bits(OCTET(uui_stringOct),1,4)][get_bits(OCTET(uui_stringOct),5,8)]; - } - uui_string[j]='\0'; - *str_len+= sprintf(&str[*str_len], " %s (0x%02x) <%s>\n", - get_code_2_str(protDiscr, dcodQ931UuiProtDiscrTable), protDiscr, - uui_string); - } - } - break; - case PROT_Q931_IE_DISPLAY: - { - uint8_t j; - char displayStr[82]; - uint8_t displayNtEnabled = 0; - uint8_t displayStrOct = 2; - uint8_t displayType = 0; - uint8_t assocInfo = 0; - - memset(displayStr, 0, sizeof(displayStr)); - - if(get_bits(OCTET(3),8,8)) { - displayType = get_bits(OCTET(3),1,4); - assocInfo = get_bits(OCTET(3),5,7); - - displayNtEnabled = 1; - displayStrOct++; - } - j = 0; - if(len >= sizeof(displayStr)) { - len = sizeof(displayStr)-1; - } - while(displayStrOct++ <= len+1) { - displayStr[j++]=ia5[get_bits(OCTET(displayStrOct),1,4)][get_bits(OCTET(displayStrOct),5,8)]; - } - displayStr[j]='\0'; - if (displayNtEnabled) { - *str_len+= sprintf(&str[*str_len], "%s(l:%d) type:%s(%d) info:%s(%d)\n", - displayStr, len, - get_code_2_str(displayType, dcodQ931DisplayTypeTable), displayType, - get_code_2_str(assocInfo, dcodQ931AssocInfoTable), assocInfo); - } else { - *str_len+= sprintf(&str[*str_len], "%s(l:%d)\n", - displayStr, len); - } - } - break; - case PROT_Q931_IE_RESTART_IND: - { - uint8_t indClass; - indClass = get_bits(OCTET(3),1,3); - *str_len+= sprintf(&str[*str_len], "class:%s(%d)\n", - get_code_2_str(indClass,dcodQ931RestartIndClassTable), indClass); - } - break; - case PROT_Q931_IE_PROGRESS_IND: - { - uint8_t codingStandard, location, progressDescr; - codingStandard = get_bits(OCTET(3),6,7); - location = get_bits(OCTET(3),1,4); - progressDescr = get_bits(OCTET(4),1,7); - *str_len+= sprintf(&str[*str_len], "coding:%s(%d) location:%s(%d) descr:%s(%d)\n", - get_code_2_str(codingStandard,dcodQ931BcCodingStandardTable), codingStandard, - get_code_2_str(location,dcodQ931IelocationTable), location, - get_code_2_str(progressDescr,dcodQ931IeprogressDescrTable), progressDescr); - } - break; - case PROT_Q931_IE_KEYPAD_FACILITY: - { - uint8_t keypadFacilityStrOct = 3, j; - char keypadFacilityStr[82]; - memset(keypadFacilityStr, 0, sizeof(keypadFacilityStr)); - - j = 0; - if(len >= sizeof(keypadFacilityStr)) { - len = sizeof(keypadFacilityStr)-1; - } - while(keypadFacilityStrOct++ < len+1) { - keypadFacilityStr[j++]=ia5[get_bits(OCTET(keypadFacilityStrOct),1,4)][get_bits(OCTET(keypadFacilityStrOct),5,8)]; - } - keypadFacilityStr[j]='\0'; - *str_len+= sprintf(&str[*str_len], " digits:%s(l:%d)\n", - keypadFacilityStr, len); - } - break; - case PROT_Q931_IE_FACILITY: - { - uint8_t protProfile; - protProfile = get_bits(OCTET(3),1,5); - *str_len+= sprintf(&str[*str_len], "Prot profile:%s(%d)\n", - get_code_2_str(protProfile,dcodQ931IeFacilityProtProfileTable), protProfile); - } - break; - case PROT_Q931_IE_GENERIC_DIGITS: - { - uint8_t encoding,type; - int value = 0; - - encoding = get_bits(OCTET(3),6,8); - type = get_bits(OCTET(3),1,5); - - *str_len+= sprintf(&str[*str_len], "encoding:%s(%d) type:%s(%d) ", - get_code_2_str(encoding,dcodQ931GenDigitsEncodingTable), encoding, - get_code_2_str(encoding,dcodQ931GenDigitsTypeTable), type); - - if (len > 1) { - uint32_t j=0; - - while(++j < len) { - switch(encoding) { - case 0: /* BCD even */ - case 1: /* BCD odd */ - { - uint8_t byte = OCTET(j+3); - value = (get_bits(byte,1,4)*10) + get_bits(byte,5,8) + (value*10); - } - break; - case 2: /* IA 5 */ - value = value*10 + OCTET(j+3)-'0'; - *str_len+= sprintf(&str[*str_len], "%c", OCTET(j+3)); - break; - case 3: - /* Don't know how to decode binary encoding yet */ - *str_len+= sprintf(&str[*str_len], "Binary encoded"); - break; - } - } - *str_len+= sprintf(&str[*str_len], " "); - switch(type) { - case 4: /* info digits */ - *str_len+= sprintf(&str[*str_len], "ani2:%s(%d)", get_code_2_str(value,dcodQ931LineInfoTable), value); - break; - case 5: /* Callid */ - *str_len+= sprintf(&str[*str_len], "Caller ID not implemented\n"); - break; - } - } - *str_len+= sprintf(&str[*str_len], "\n"); - print_hex_dump(str, str_len, (uint8_t*) data, index_start, index_end); - } - break; - case PROT_Q931_IE_SENDING_COMPLETE: - /* No need to decode sending complete IE, as no additional info is available except that sending is done */ - /* This is a single octet IE */ - *str_len+= sprintf(&str[*str_len], "\n"); - return 0; - break; - case PROT_Q931_IE_CALLED_PARTY_SUBADDRESS: - { - uint8_t type; - uint8_t currentOct, j=0; - char calling_subaddr_string[82]; - memset(calling_subaddr_string, 0, sizeof(calling_subaddr_string)); - type = get_bits(OCTET(3),5,7); - currentOct = 3; - while(currentOct++ <= len+1) { - calling_subaddr_string[j++]=ia5[get_bits(OCTET(currentOct),1,4)][get_bits(OCTET(currentOct),5,8)]; - } - calling_subaddr_string[j++]='\0'; - *str_len += sprintf(&str[*str_len], "%s (l:%d) type:%s(%d) \n", - calling_subaddr_string, (j-1), get_code_2_str(type, dcodQ931TypeOfSubaddressTable), type); - } - break; - case PROT_Q931_IE_NOTIFICATION_IND: - { - uint8_t desc; - - desc = get_bits(OCTET(3),1,7); - *str_len += sprintf(&str[*str_len], "%s (%d)\n", - get_code_2_str(desc, dcodQ931NotificationIndTable), desc); - } - break; - case PROT_Q931_IE_REDIRECTION_NUMBER: - case PROT_Q931_IE_DATE_TIME: - case PROT_Q931_IE_INFORMATION_REQUEST: - case PROT_Q931_IE_SIGNAL: - case PROT_Q931_IE_SWITCHOOK: - case PROT_Q931_IE_FEATURE_ACT: - case PROT_Q931_IE_FEATURE_IND: - case PROT_Q931_IE_INFORMATION_RATE: - case PROT_Q931_IE_END_TO_END_TRANSIT_DELAY: - case PROT_Q931_IE_TRANSIT_DELAY_SELECT_IND: - case PROT_Q931_IE_PACKET_LAYER_BINARY_PARAMS: - case PROT_Q931_IE_PACKET_LAYER_WINDOW_SIZE: - case PROT_Q931_IE_PACKET_LAYER_SIZE: - case PROT_Q931_IE_TRANSIT_NETWORK_SELECTION: - case PROT_Q931_IE_LOW_LAYER_COMPAT: - case PROT_Q931_IE_HIGH_LAYER_COMPAT: - case PROT_Q931_IE_ESCAPE_FOR_EXTENSION: - case PROT_Q931_IE_CALL_IDENTITY: - case PROT_Q931_IE_CALL_STATE: - case PROT_Q931_IE_SEGMENTED_MESSAGE: - case PROT_Q931_IE_NETWORK_SPF_FACILITY: - case PROT_Q931_IE_CALLING_PARTY_SUBADDRESS: - default: - { - *str_len += sprintf(&str[*str_len], "Undecoded"); - print_hex_dump((char*)str, str_len, data, index_start, index_end + 1); - } - break; - } - - return len+1; -} - -void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_start, uint32_t index_end) -{ - uint32_t k; - *str_len += sprintf(&str[*str_len], " [ "); - for(k=index_start; k < index_end; k++) { - if (k && !(k%32)) { - *str_len += sprintf(&str[*str_len], "\n "); - } - *str_len += sprintf(&str[*str_len], "%02x ", data[k]); - } - *str_len += sprintf(&str[*str_len], "]\n"); - return; -} - -static ftdm_status_t sngisdn_get_frame_info(uint8_t *data, uint32_t data_len, ftdm_trace_dir_t dir, sngisdn_frame_info_t *target) -{ - uint8_t pos = 0; - uint8_t flag; - uint16_t ref = 0; - uint8_t ref_len = 0; - uint8_t bchan_no = 0; - uint8_t msgtype; - - /* First octet is protocol discriminator */ - pos++; - /* Second octet contains length of call reference */ - ref_len = data[pos++] & 0x0F; - - /* third octet is call reference */ - flag = (data[pos] & 0x80) >> 7; - if (ref_len == 2) { - ref = (data[pos++] & 0x7F) << 8; - ref |= (data[pos++] & 0xFF) ; - } else { - ref = (data[pos++] & 0x7F); - } - - /* Next octet is the message type */ - msgtype = data[pos++] & 0x7F; - - /* - ftdm_log(FTDM_LOG_DEBUG, "Raw frame:call_ref:0x%04x flag:%d msgtype:%d\n", ref, flag, msgtype); - */ - if (!ref) { - /* This is not a call specific message (RESTART for example and we do not care about it) */ - return FTDM_FAIL; - } - - /* Look for the b-channel */ - if (msgtype == PROT_Q931_MSGTYPE_SETUP) { - /* Try to find the b-channel no*/ - - for(; pos < data_len; pos++) { - uint8_t ie_id = data[pos]; - uint8_t ie_len = data[pos+1]; - - switch(ie_id) { - case PROT_Q931_IE_SENDING_COMPLETE: - /* Single octet ie's do not have a length */ - ie_len = 0; - break; - case PROT_Q931_IE_CHANNEL_ID: - { - /* Try to obtain the b-channel */ - uint8_t ie_pos = pos+2; - //ifaceIdPresent = get_bits(OCTET(3),7,7); - if (data[ie_pos] & 0x20) { - /* Interface type is Primary Rate */ - ie_pos+=2; - bchan_no = data[ie_pos] & 0x7F; - } else { - /* Interface type is Basic Interface */ - /* Get the channel number from info channel selection */ - bchan_no = data[ie_pos] & 0x03; - } - ftdm_log(FTDM_LOG_DEBUG, "Found b-channel:%d\n", bchan_no); - goto parse_ies_done; - } - break; - default: - pos = pos+ie_len+1; - } - //ftdm_log(FTDM_LOG_DEBUG, "Decoded IE:%s\n", get_code_2_str(ie_id, dcodQ931IEIDTable)); - } - if (!bchan_no) { - uint32_t tmp_len = 0; - char tmp[1000]; - print_hex_dump(tmp, &tmp_len, data, 0, data_len); - ftdm_log(FTDM_LOG_DEBUG, "Failed to determine b-channel on SETUP message\n%s\n", tmp); - } - } - -parse_ies_done: - - target->call_ref = ref; - target->call_ref_flag = flag; - target->msgtype = msgtype; - target->bchan_no = bchan_no; - target->dir = dir; - - return FTDM_SUCCESS; -} - -static ftdm_status_t sngisdn_map_call(sngisdn_span_data_t *signal_data, sngisdn_frame_info_t frame_info, ftdm_channel_t **found) -{ - sngisdn_chan_data_t *sngisdn_info; - ftdm_channel_t *ftdmchan = NULL; - ftdm_iterator_t *chaniter = NULL; - ftdm_iterator_t *curr = NULL; - ftdm_status_t status = FTDM_FAIL; - uint8_t outbound_call = 0; - - if ((!frame_info.call_ref_flag && frame_info.dir == FTDM_TRACE_DIR_OUTGOING) || - (frame_info.call_ref_flag && frame_info.dir == FTDM_TRACE_DIR_INCOMING)) { - - /* If this is an outgoing frame and this frame was sent by the originating side - of the call (frame_info.call_ref_flag == 0), then this is an outbound call */ - outbound_call = 1; - } else { - outbound_call = 0; - } - - switch (frame_info.msgtype) { - case PROT_Q931_MSGTYPE_SETUP: - /* We initiated this outgoing call try to match the call reference with our internal call-id*/ - if (!frame_info.bchan_no) { - /* We were not able to determine the bchannel on this call, so we will not be able to match it anyway */ - status = FTDM_FAIL; - } - - chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL); - for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { - ftdmchan = (ftdm_channel_t*)(ftdm_iterator_current(curr)); - ftdm_channel_lock(ftdmchan); - - if (outbound_call) { - sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data; - if (sngisdn_info && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - if (ftdmchan->caller_data.call_id && ftdmchan->physical_chan_id == frame_info.bchan_no) { - - sngisdn_info->call_ref = frame_info.call_ref; - *found = ftdmchan; - status = FTDM_SUCCESS; - } - } - } else { - if (ftdmchan->physical_chan_id == frame_info.bchan_no) { - *found = ftdmchan; - status = FTDM_SUCCESS; - } - } - ftdm_channel_unlock(ftdmchan); - } - ftdm_iterator_free(chaniter); - break; - case PROT_Q931_MSGTYPE_ALERTING: - case PROT_Q931_MSGTYPE_PROCEEDING: - case PROT_Q931_MSGTYPE_PROGRESS: - case PROT_Q931_MSGTYPE_CONNECT: - case PROT_Q931_MSGTYPE_SETUP_ACK: - case PROT_Q931_MSGTYPE_CONNECT_ACK: - case PROT_Q931_MSGTYPE_USER_INFO: - case PROT_Q931_MSGTYPE_DISCONNECT: - case PROT_Q931_MSGTYPE_RELEASE: - case PROT_Q931_MSGTYPE_RESTART_ACK: - case PROT_Q931_MSGTYPE_RELEASE_COMPLETE: - case PROT_Q931_MSGTYPE_FACILITY: - case PROT_Q931_MSGTYPE_NOTIFY: - case PROT_Q931_MSGTYPE_STATUS_ENQUIRY: - case PROT_Q931_MSGTYPE_INFORMATION: - case PROT_Q931_MSGTYPE_STATUS: - /* Look for an outbound call on that span and and try to match the call-id */ - chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL); - for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { - ftdmchan = (ftdm_channel_t*)(ftdm_iterator_current(curr)); - ftdm_channel_lock(ftdmchan); - sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data; - if (outbound_call) { - if (sngisdn_info && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - if (sngisdn_info->call_ref == frame_info.call_ref) { - - *found = ftdmchan; - status = FTDM_SUCCESS; - } - } - } else { - if (sngisdn_info && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - if (sngisdn_info->call_ref && sngisdn_info->call_ref == frame_info.call_ref) { - - *found = ftdmchan; - status = FTDM_SUCCESS; - } - } - } - ftdm_channel_unlock(ftdmchan); - } - ftdm_iterator_free(chaniter); - break; - default: - /* This frame is not call specific, ignore */ - break; - } - if (status == FTDM_SUCCESS) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Mapped %s with Call Ref:%04x to call-id:%d\n", get_code_2_str(frame_info.msgtype, dcodQ931MsgTypeTable), frame_info.call_ref, (*found)->caller_data.call_id); - } else { - /* We could not map this frame to a call-id */ - ftdm_log(FTDM_LOG_DEBUG, "Failed to map %s with Call Ref:%04x to local call\n", - get_code_2_str(frame_info.msgtype, dcodQ931MsgTypeTable), frame_info.call_ref); - } - - return status; -} - - - diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h deleted file mode 100644 index b09bcbd33a..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h +++ /dev/null @@ -1,599 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * David Yat Sin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef __FTMOD_SANGOMA_ISDN_TRACE_H__ -#define __FTMOD_SANGOMA_ISDN_TRACE_H__ - -#define MX_CODE_TXT_LEN 70 -#define Q931_LOCKING_SHIFT 0x90 -#define Q931_NON_LOCKING_SHIFT 0x98 - -#define PROT_Q931_RELEASE_CAUSE_MISDIALED_TRUNK_PREFIX 5 -#define PROT_Q931_RELEASE_CAUSE_INVALID_NUMBER_FORMAT 28 -#define PROT_Q931_RELEASE_CAUSE_NO_CHAN_AVAIL 34 -#define PROT_Q931_RELEASE_CAUSE_DEST_OUT_OF_ORDER 27 -#define PROT_Q931_RELEASE_CAUSE_IE_NOT_EXIST 99 -#define PROT_Q931_RECOVERY_ON_TIMER_EXPIRE 102 -#define PROT_Q931_RELEASE_CAUSE_WRONG_CALL_STATE 101 - - -#define PROT_Q931_IE_SEGMENTED_MESSAGE 0x00 -#define PROT_Q931_IE_BEARER_CAP 0x04 -#define PROT_Q931_IE_CAUSE 0x08 -#define PROT_Q931_IE_CALL_IDENTITY 0x10 -#define PROT_Q931_IE_CALL_STATE 0x14 -#define PROT_Q931_IE_CHANNEL_ID 0x18 -#define PROT_Q931_IE_FACILITY 0x1c -#define PROT_Q931_IE_PROGRESS_IND 0x1e -#define PROT_Q931_IE_NETWORK_SPF_FACILITY 0x20 -#define PROT_Q931_IE_NOTIFICATION_IND 0x27 -#define PROT_Q931_IE_DISPLAY 0x28 -#define PROT_Q931_IE_DATE_TIME 0x29 -#define PROT_Q931_IE_KEYPAD_FACILITY 0x2c -#define PROT_Q931_IE_INFORMATION_REQUEST 0x32 -#define PROT_Q931_IE_SIGNAL 0x34 -#define PROT_Q931_IE_SWITCHOOK 0x36 -#define PROT_Q931_IE_GENERIC_DIGITS 0x37 -#define PROT_Q931_IE_FEATURE_ACT 0x38 -#define PROT_Q931_IE_FEATURE_IND 0x39 -#define PROT_Q931_IE_INFORMATION_RATE 0x40 -#define PROT_Q931_IE_END_TO_END_TRANSIT_DELAY 0x42 -#define PROT_Q931_IE_TRANSIT_DELAY_SELECT_IND 0x43 -#define PROT_Q931_IE_PACKET_LAYER_BINARY_PARAMS 0x44 -#define PROT_Q931_IE_PACKET_LAYER_WINDOW_SIZE 0x45 -#define PROT_Q931_IE_PACKET_LAYER_SIZE 0x46 -#define PROT_Q931_IE_CALLING_PARTY_NUMBER 0x6c -#define PROT_Q931_IE_CALLING_PARTY_SUBADDRESS 0x6d -#define PROT_Q931_IE_CALLED_PARTY_NUMBER 0x70 -#define PROT_Q931_IE_CALLED_PARTY_SUBADDRESS 0x71 -#define PROT_Q931_IE_REDIRECTING_NUMBER 0x74 -#define PROT_Q931_IE_REDIRECTION_NUMBER 0x76 -#define PROT_Q931_IE_TRANSIT_NETWORK_SELECTION 0x78 -#define PROT_Q931_IE_RESTART_IND 0x79 -#define PROT_Q931_IE_LOW_LAYER_COMPAT 0x7c -#define PROT_Q931_IE_HIGH_LAYER_COMPAT 0x7d -#define PROT_Q931_IE_USER_USER 0x7e -#define PROT_Q931_IE_SENDING_COMPLETE 0xa1 -#define PROT_Q931_IE_ESCAPE_FOR_EXTENSION 0x7f -#define PROT_Q931_IE_SENDING_COMPLETE 0xa1 - -#define NULL_CHAR 0 - - -struct code2str -{ - int code; - char text[MX_CODE_TXT_LEN]; -}; - -enum { - I_FRAME = 1, /* Information frame */ - S_FRAME, /* Supervisory frame */ - U_FRAME, /* Unnumbered frame */ -}; - -char ia5[16][8]={{NULL_CHAR,NULL_CHAR,' ','0','@','P','`','p'}, - {NULL_CHAR,NULL_CHAR,'!','1','A','Q','a','q'}, - {NULL_CHAR,NULL_CHAR,'"','2','B','R','b','r'}, - {NULL_CHAR,NULL_CHAR,'#','3','C','S','c','s'}, - {NULL_CHAR,NULL_CHAR,'$','4','D','T','d','t'}, - {NULL_CHAR,NULL_CHAR,'%','5','E','U','e','u'}, - {NULL_CHAR,NULL_CHAR,'&','6','F','V','f','v'}, - {NULL_CHAR,NULL_CHAR,'\'','7','G','W','g','w'}, - {NULL_CHAR,NULL_CHAR,'(','8','H','X','h','x'}, - {NULL_CHAR,NULL_CHAR,')','9','I','Y','i','y'}, - {NULL_CHAR,NULL_CHAR,'*',':','J','Z','j','z'}, - {NULL_CHAR,NULL_CHAR,'+',';','K','[','k','{'}, - {NULL_CHAR,NULL_CHAR,',','<','L','\\','l','|'}, - {NULL_CHAR,NULL_CHAR,'-','=','M',']','m','}'}, - {NULL_CHAR,NULL_CHAR,'.','>','N','^','n','~'}, - {NULL_CHAR,NULL_CHAR,'/','?','O','_','o',NULL_CHAR}}; - -/* Based on Table 4 - pg 15 of Q.921 Recommendation */ -struct code2str dcodQ921FrameFormatTable[] = { - {I_FRAME, "Information"}, - {S_FRAME, "Supervisory"}, - {U_FRAME, "Unnumbered"}, - {-1, "?"}, -}; - - -/* Based on Table 5 - pg 15 of Q.921 Recommendation */ -struct code2str dcodQ921SupervisoryCmdTable[] = { - {0, "RR - receive ready"}, - {1, "RNR - receive not ready"}, - {2, "REJ - reject"}, - {-1, "Unknown"}, -}; - -/* Based on Table 5 - pg 15 of Q.921 Recommendation */ -struct code2str dcodQ921UnnumberedCmdTable[] = { - {0x0F, "SABME - set async balanced mode extended"}, - {0x03, "DM - disconnected mode"}, - {0x00, "UI - unnumbered information"}, - {0x08, "DISC - disconnect"}, - {0x0C, "UA - unnumbered acknowledgement"}, - {0x11, "FRMR - frame reject"}, - {0x17, "XID - Exchange Identification)"}, - {-1, "Unknown"}, -}; - -struct code2str dcodQ931ProtDiscTable[] = { - {0x08, "Q.931/I.451"}, - {0x09, "Q.2931"}, - {-1, "Unknown"}, -}; - -struct code2str dcodQ931CallRefHiTable[] = { - {0, "0"}, - {16, "1"}, - {32, "2"}, - {48, "3"}, - {64, "4"}, - {80, "5"}, - {96, "6"}, - {112, "7"}, - {128, "8"}, - {144, "9"}, - {160, "A"}, - {176, "B"}, - {192, "C"}, - {208, "D"}, - {224, "E"}, - {240, "F"}, - {-1,"?"}, -}; - -struct code2str dcodQ931CallRefLoTable[] = { - {0, "0"}, - {1, "1"}, - {2, "2"}, - {3, "3"}, - {4, "4"}, - {5, "5"}, - {6, "6"}, - {7, "7"}, - {8, "8"}, - {9, "9"}, - {10, "A"}, - {11, "B"}, - {12, "C"}, - {13, "D"}, - {14, "E"}, - {15, "F"}, - {-1, "?"}, -}; - -#define PROT_Q931_MSGTYPE_ALERTING 1 -#define PROT_Q931_MSGTYPE_PROCEEDING 2 -#define PROT_Q931_MSGTYPE_PROGRESS 3 -#define PROT_Q931_MSGTYPE_SETUP 5 -#define PROT_Q931_MSGTYPE_CONNECT 7 -#define PROT_Q931_MSGTYPE_SETUP_ACK 13 -#define PROT_Q931_MSGTYPE_CONNECT_ACK 15 -#define PROT_Q931_MSGTYPE_USER_INFO 32 -#define PROT_Q931_MSGTYPE_SUSPEND_REJ 33 -#define PROT_Q931_MSGTYPE_RESUME_REJ 34 -#define PROT_Q931_MSGTYPE_SUSPEND 37 -#define PROT_Q931_MSGTYPE_RESUME 38 -#define PROT_Q931_MSGTYPE_SUSPEND_ACK 45 -#define PROT_Q931_MSGTYPE_RESUME_ACK 46 -#define PROT_Q931_MSGTYPE_DISCONNECT 69 -#define PROT_Q931_MSGTYPE_RESTART 70 -#define PROT_Q931_MSGTYPE_RELEASE 77 -#define PROT_Q931_MSGTYPE_RESTART_ACK 78 -#define PROT_Q931_MSGTYPE_RELEASE_COMPLETE 90 -#define PROT_Q931_MSGTYPE_SEGMENT 96 -#define PROT_Q931_MSGTYPE_FACILITY 98 -#define PROT_Q931_MSGTYPE_NOTIFY 110 -#define PROT_Q931_MSGTYPE_STATUS_ENQUIRY 117 -#define PROT_Q931_MSGTYPE_CONGESTION_CNTRL 121 -#define PROT_Q931_MSGTYPE_INFORMATION 123 -#define PROT_Q931_MSGTYPE_STATUS 125 - - -struct code2str dcodQ931MsgTypeTable[] = { - {PROT_Q931_MSGTYPE_ALERTING, "ALERT"}, - {PROT_Q931_MSGTYPE_PROCEEDING, "PROCEED"}, - {PROT_Q931_MSGTYPE_PROGRESS, "PROGRESS"}, - {PROT_Q931_MSGTYPE_SETUP, "SETUP"}, - {PROT_Q931_MSGTYPE_CONNECT, "CONNECT"}, - {PROT_Q931_MSGTYPE_SETUP_ACK, "SETUP ACK"}, - {PROT_Q931_MSGTYPE_CONNECT_ACK, "CONNECT ACK"}, - {PROT_Q931_MSGTYPE_USER_INFO, "USER INFO"}, - {PROT_Q931_MSGTYPE_SUSPEND_REJ, "SUSPEND REJ"}, - {PROT_Q931_MSGTYPE_RESUME_REJ, "RESUME REJ"}, - {PROT_Q931_MSGTYPE_SUSPEND, "SUSPEND"}, - {PROT_Q931_MSGTYPE_RESUME, "RESUME"}, - {PROT_Q931_MSGTYPE_SUSPEND_ACK, "SUSPEND ACK"}, - {PROT_Q931_MSGTYPE_RESUME_ACK, "RESUME ACK"}, - {PROT_Q931_MSGTYPE_DISCONNECT, "DISCONNECT"}, - {PROT_Q931_MSGTYPE_RESTART, "RESTART"}, - {PROT_Q931_MSGTYPE_RELEASE, "RELEASE"}, - {PROT_Q931_MSGTYPE_RESTART_ACK, "RESTART ACK"}, - {PROT_Q931_MSGTYPE_RELEASE_COMPLETE, "RELEASE COMPLETE"}, - {PROT_Q931_MSGTYPE_SEGMENT, "SEGMENT"}, - {PROT_Q931_MSGTYPE_FACILITY, "FACILITY"}, - {PROT_Q931_MSGTYPE_NOTIFY, "NOTIFY"}, - {PROT_Q931_MSGTYPE_STATUS_ENQUIRY, "STATUS ENQ"}, - {PROT_Q931_MSGTYPE_CONGESTION_CNTRL, "CONGESTION CTRL"}, - {PROT_Q931_MSGTYPE_INFORMATION, "INFO"}, - {PROT_Q931_MSGTYPE_STATUS, "STATUS"}, - {-1, "UNKNOWN"}, -}; - -struct code2str dcodQ931CauseCodeTable[] = { - {1, "Unallocated (unassigned) number"}, - {2, "No route to specified network"}, - {3, "No route to destination"}, - {4, "Send special information tone"}, - {5, "Misdialed trunk prefix"}, - {6, "Channel Unacceptable"}, - {7, "Call awarded and channel established"}, - {8, "Pre-emption"}, - {9, "Pre-emption-circuit reserved"}, - {16, "Normal call clearing"}, - {17, "User Busy"}, - {18, "No User Responding"}, - {19, "No Answer from User"}, - {20, "Subscriber Absent"}, - {21, "Call Rejected"}, - {22, "Number Changed"}, - {26, "Non-Selected User Clearing"}, - {27, "Destination Out-of-Order"}, - {28, "Invalid Number Format"}, - {29, "Facility Rejected"}, - {30, "Response to Status Enquiry"}, - {31, "Normal, Unspecified"}, - {34, "No Circuit/Channel Available"}, - {38, "Network Out-of-Order"}, - {39, "Permanent Frame Mode OOS"}, - {40, "Permanent Frame Mode Operational"}, - {41, "Temporary Failure"}, - {42, "Switching Equipment Congestion"}, - {43, "Access Information Discarded"}, - {44, "Requested Circuit/Channel not available"}, - {47, "Resource Unavailable, Unspecified"}, - {49, "Quality of Service not available"}, - {50, "Requested facility not subscribed"}, - {53, "Outgoing calls barred within CUG"}, - {55, "Incoming calls barred within CUG"}, - {57, "Bearer capability not authorized"}, - {58, "Bearer capability not presently available"}, - {62, "Inconsistency in access inf and subscriber"}, - {63, "Service or Option not available"}, - {65, "Bearer capability not implemented"}, - {66, "Channel type not implemented"}, - {69, "Requested facility not implemented"}, - {70, "Only restricted digital BC available"}, - {79, "Service or option not implemented"}, - {81, "Invalid call reference value"}, - {82, "Identified channel does not exist"}, - {83, "Suspended call exists"}, - {84, "Call identity in use"}, - {85, "No call suspended"}, - {86, "Call already cleared"}, - {87, "User not member of CUG"}, - {88, "Incompatible destination"}, - {90, "Non existent CUG"}, - {91, "Invalid transit network selection"}, - {95, "Invalid message, unspecified"}, - {96, "Mandatory IE missing"}, - {97, "Message type non-existent, not implemented"}, - {98, "Message not compatible with call state"}, - {99, "An IE or parameter does not exist"}, - {100, "Invalid IE contents"}, - {101, "Message not compatible with call state"}, - {102, "Recovery on timer expired"}, - {103, "Parameter non-existent, not impl"}, - {110, "Message with unrecognized parameter"}, - {111, "Protocol error, unspecified"}, - {127, "Interworking, unspecified"}, - {-1, "Unknown"}, -}; - -struct code2str dcodQ931IEIDTable[] = { - {PROT_Q931_IE_SEGMENTED_MESSAGE, "Segmented Message"}, - {PROT_Q931_IE_BEARER_CAP, "Bearer Capability"}, - {PROT_Q931_IE_CAUSE, "Cause"}, - {PROT_Q931_IE_CALL_IDENTITY, "Call Identity"}, - {PROT_Q931_IE_CALL_STATE, "Call State"}, - {PROT_Q931_IE_CHANNEL_ID, "Channel Id"}, - {PROT_Q931_IE_FACILITY, "Facility"}, - {PROT_Q931_IE_PROGRESS_IND, "Progress Indicator"}, - {PROT_Q931_IE_NETWORK_SPF_FACILITY, "Network Specific Facilities"}, - {PROT_Q931_IE_NOTIFICATION_IND, "Notification Indicator"}, - {PROT_Q931_IE_DISPLAY, "Display"}, - {PROT_Q931_IE_DATE_TIME, "Date/Time"}, - {PROT_Q931_IE_KEYPAD_FACILITY, "Keypad Facility"}, - {PROT_Q931_IE_INFORMATION_REQUEST, "Information Request"}, - {PROT_Q931_IE_SIGNAL, "Signal"}, - {PROT_Q931_IE_SWITCHOOK, "Switchhook"}, - {PROT_Q931_IE_GENERIC_DIGITS, "Generic Digits"}, - {PROT_Q931_IE_FEATURE_ACT, "Feature Activation"}, - {PROT_Q931_IE_FEATURE_IND, "Feature Indication"}, - {PROT_Q931_IE_INFORMATION_RATE, "Information Rate"}, - {PROT_Q931_IE_END_TO_END_TRANSIT_DELAY, "End-to-end Transit Delay"}, - {PROT_Q931_IE_TRANSIT_DELAY_SELECT_IND, "Transit Delay Selection and Indication"}, - {PROT_Q931_IE_PACKET_LAYER_BINARY_PARAMS, "Packet layer binary parameters"}, - {PROT_Q931_IE_PACKET_LAYER_WINDOW_SIZE, "Packet layer Window Size"}, - {PROT_Q931_IE_PACKET_LAYER_SIZE, "Packet layer Size"}, - {PROT_Q931_IE_CALLING_PARTY_NUMBER, "Calling Party Number"}, - {PROT_Q931_IE_CALLING_PARTY_SUBADDRESS, "Calling Party Subaddress"}, - {PROT_Q931_IE_CALLED_PARTY_NUMBER, "Called Party Number"}, - {PROT_Q931_IE_CALLED_PARTY_SUBADDRESS, "Called Party Subaddress"}, - {PROT_Q931_IE_REDIRECTING_NUMBER, "Redirecting Number"}, - {PROT_Q931_IE_REDIRECTION_NUMBER, "Redirection Number"}, - {PROT_Q931_IE_TRANSIT_NETWORK_SELECTION, "Transit Network Selection"}, - {PROT_Q931_IE_RESTART_IND, "Restart Indicator"}, - {PROT_Q931_IE_LOW_LAYER_COMPAT, "Low-Layer Compatibility"}, - {PROT_Q931_IE_HIGH_LAYER_COMPAT, "High-Layer Compatibility"}, - {PROT_Q931_IE_USER_USER, "User-User"}, - {PROT_Q931_IE_SENDING_COMPLETE, "Sending complete"}, - {PROT_Q931_IE_ESCAPE_FOR_EXTENSION, "Escape for extension"}, - {-1,"Unknown"}, -}; - -struct code2str dcodQ931NumberingPlanTable[] = { - {0, "unknown"}, - {1, "isdn"}, - {3, "data"}, - {4, "telex"}, - {8, "national"}, - {9, "private"}, - {15, "reserved"}, - {-1, "invalid"}, -}; - -struct code2str dcodQ931TypeofNumberTable[] = { - {0, "unknown"}, - {1, "international"}, - {2, "national"}, - {3, "network spf"}, - {4, "subscriber"}, - {6, "abbreviated"}, - {7, "reserved"}, - {-1, "invalid" }, -}; - -struct code2str dcodQ931PresentationTable[] = { - {0, "allowed"}, - {1, "restricted"}, - {2, "not available"}, - {-1, "invalid" }, -}; - -struct code2str dcodQ931ScreeningTable[] = { - {0, "user, not screened"}, - {1, "user, passed"}, - {2, "user, failed"}, - {3, "network, provided"}, - {-1, "invalid" }, -}; - -struct code2str dcodQ931InfoChannelSelTable[] = { - {0, "No Chan"}, - {1, "B1"}, - {2, "B2"}, - {3, "Any Chan"}, - {-1, "invalid" }, -}; - -struct code2str dcodQ931ReasonTable[] = { - {0x0, "Unknown"}, - {0x1, "Call forwarding busy"}, - {0x2, "Call forwarding no reply"}, - {0x4, "Call deflection"}, - {0x9, "Called DTE out of order"}, - {0xA, "Call forwarding by the called DTE"}, - {0xF, "Call forwarding unconditional"}, - {-1, "reserved" }, -}; - -struct code2str dcodQ931BcCodingStandardTable[] = { - {0x0, "ITU-T"}, - {0x1, "ISO/IEC"}, - {0x2, "National"}, - {0x3, "Defined standard"}, - {-1, "unknown"}, -}; - -struct code2str dcodQ931BcInfTransferCapTable[] = { - {0x00, "Speech"}, - {0x08, "Unrestricted digital"}, - {0x09, "Restricted digital"}, - {0x10, "3.1Khz audio"}, - {0x11, "Unrestricted digital w/ tones"}, - {0x18, "Video"}, - {-1, "reserved"}, -}; - -struct code2str dcodQ931BcInfTransferRateTable[] = { - {0x00, "n/a"}, /* for packet-mode calls */ - {0x10, "64 Kbit/s"}, - {0x11, "2x64 Kbit/s"}, - {0x13, "384 Kbit/s"}, - {0x15, "1536 Kbit/s"}, - {0x17, "1920 Kbit/s"}, - {0x18, "Multirate"}, - {-1, "reserved"}, -}; - - -struct code2str dcodQ931BcusrL1ProtTable[] = { - {0x01, "ITU-T rate/V.110/I.460/X.30"}, - {0x02, "G.711 u-Law"}, - {0x03, "G.711 A-Law"}, - {0x04, "G.721/I.460"}, - {0x05, "H.221/H.242"}, - {0x06, "H.223/H.245"}, - {0x07, "Non-ITU-T rate"}, - {0x08, "V.120"}, - {0x09, "X.31 HDLC"}, - {-1, "reserved"}, -}; - -struct code2str dcodQ931UuiProtDiscrTable[] = { - {0x00, "User-specific"}, - {0x01, "OSI high layer prot"}, - {0x02, "Recommendation X.244"}, - {0x03, "System management"}, - {0x04, "IA5 Chars"}, - {0x05, "X.208/X.209"}, - {0x07, "V.120"}, - {0x08, "Q.931/I.451"}, - {0x10, "X.25"}, - {-1,"reserved"}, -}; - -struct code2str dcodQ931ChanTypeTable[] = { - {0x3,"B-chans"}, - {0x6,"H0-chans"}, - {0x8,"H11-chans"}, - {0x9,"H12-chans"}, - {-1,"reserved"}, -}; - -struct code2str dcodQ931RestartIndClassTable[] = { - {0x0 ,"Indicated in channel IE"}, - {0x6 ,"Single interface"}, - {0x7 ,"All interfaces"}, - {-1, "reserved"}, -}; - -struct code2str dcodQ931IelocationTable[] = { - {0x0, "User"}, - {0x1, "Private network, local user"}, - {0x2, "Public network, local user"}, - {0x3, "Transit network"}, - {0x4, "Public network, remote user"}, - {0x5, "Private network, remote user"}, - {0xA, "Beyond interworking point"}, - {-1, "reserved"}, -}; - -struct code2str dcodQ931IeprogressDescrTable[] = { - {0x01, "Further info maybe available"}, - {0x02, "Destination is non-ISDN"}, - {0x03, "Origination address is non-ISDN"}, - {0x04, "Call returned to ISDN"}, - {0x08, "In-band data ready"}, - {-1, "reserved"}, -}; - -struct code2str dcodQ931IeFacilityProtProfileTable[] = { - {0x11, "Remote Operations Protocol"}, - {0x12, "CMIP Protocol"}, - {0x13, "ACSE Protocol"}, - {0x16, "GAT Protocol"}, - {0x1F, "Networking Extensions"}, - {-1, "reserved"}, -}; - -//from www.voip-info.org/wiki/ANI2 - NANPA -struct code2str dcodQ931LineInfoTable[] = { - {0, "Plain Old Telephone Service(POTS)" }, - {1, "Multiparty line"}, - {2, "ANI Failure"}, - {6, "Station Level Rating"}, - {7, "Special Operator Handling Required"}, - {20, "Automatic Identified Outward Dialing (AIOD)"}, - {23, "Coin or Non-coin"}, - {24, "Toll free service, POTS originated for non-pay station"}, - {25, "Toll free service, POTS originated for pay station"}, - {27, "Pay station with coin control"}, - {29, "Prison-Inmate service"}, - {30, "Intercept - blank"}, - {31, "Intercept - trouble"}, - {32, "Intercept - regular"}, - {34, "Telco operator handled call"}, - {52, "Outward Wide Area Telecommunications Service(OUTWATS)"}, - {60, "TRS call - from unrestricted line"}, - {61, "Cellular-Wireless PCS Type 1"}, - {62, "Cellular-Wireless PCS Type 2"}, - {63, "Cellular-Wireless PCS Type Roaming"}, - {66, "TRS call - from hotel/motel"}, - {67, "TRS call - from restricted line"}, - {70, "Line connected to pay station"}, - {93, "Private virtual network call"}, - {-1, "Unassigned"}, -}; - - -struct code2str dcodQ931GenDigitsEncodingTable[] = { - {0, "BCD even"}, - {1, "BCD odd"}, - {2, "IA5"}, - {3, "Binary"}, - {-1, "Invalid"}, -}; - - -struct code2str dcodQ931GenDigitsTypeTable[] = { - { 0, "Account Code"}, - { 1, "Auth Code"}, - { 2, "Customer ID" }, - { 3, "Universal Access"}, - { 4, "Info Digits"}, - { 5, "Callid"}, - { 6, "Opart"}, - { 7, "TCN"}, - { 9, "Adin"}, - {-1, "Invalid"}, -}; - -struct code2str dcodQ931TypeOfSubaddressTable[] = { - { 0x00, "NSAP"}, - { 0x02, "User-specified"}, - { -1, "Invalid"}, -}; - -struct code2str dcodQ931DisplayTypeTable[] = { - { 0x00, "Calling Party Name"}, - { 0x01, "Connected Party Name"}, - { 0x05, "Original Called Party Name"}, - { -1, "Invalid"}, -}; - -struct code2str dcodQ931AssocInfoTable[] = { - { 0x00, "Requested"}, - { 0x03, "Included"}, - { -1, "Invalid"}, -}; - - -struct code2str dcodQ931NotificationIndTable[] = { - { 0x71, "Call Information/event"}, - { -1, "Invalid"}, -}; -#endif /* __FTMOD_SANGOMA_ISDN_TRACE_H__ */ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_transfer.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_transfer.c deleted file mode 100644 index 5df54f48ea..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_transfer.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (c) 2011, Sangoma Technologies - * David Yat Sin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ftmod_sangoma_isdn.h" - -#define TRANSFER_FUNC(name) ftdm_status_t (name)(ftdm_channel_t *ftdmchan, sngisdn_transfer_type_t type, char* target) - -#define SNGISDN_ATT_TRANSFER_RESPONSE_CP_DROP_OFF "**1" -#define SNGISDN_ATT_TRANSFER_RESPONSE_LIMITS_EXCEEDED "**5" -#define SNGISDN_ATT_TRANSFER_RESPONSE_OK "**6" -#define SNGISDN_ATT_TRANSFER_RESPONSE_INVALID_NUM "**7" -#define SNGISDN_ATT_TRANSFER_RESPONSE_INVALID_COMMAND "**8" - - -void att_courtesy_transfer_complete(sngisdn_chan_data_t *sngisdn_info, ftdm_transfer_response_t response); -void att_courtesy_transfer_timeout(void* p_sngisdn_info); -static ftdm_status_t att_courtesy_vru(ftdm_channel_t *ftdmchan, sngisdn_transfer_type_t type, char* target); - -typedef struct transfer_interfaces { - const char *name; - sngisdn_transfer_type_t type; - TRANSFER_FUNC(*func); -}transfer_interface_t; - -static transfer_interface_t transfer_interfaces[] = { - /* AT&T TR-50075 Courtesy Transfer - VRU -- No Data (Section 4.3) */ - { "ATT_COURTESY_TRANSFER_V", SNGISDN_TRANSFER_ATT_COURTESY_VRU, att_courtesy_vru}, - /* AT&T TR-50075 Courtesy Transfer - VRU --Data (Section 4.4) */ - { "ATT_COURTESY_TRANSFER_V_DATA", SNGISDN_TRANSFER_ATT_COURTESY_VRU_DATA, att_courtesy_vru}, -}; - -void att_courtesy_transfer_complete(sngisdn_chan_data_t *sngisdn_info, ftdm_transfer_response_t response) -{ - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_DTMF_DETECT, NULL); - - sngisdn_info->transfer_data.type = SNGISDN_TRANSFER_NONE; - sngisdn_info->transfer_data.response = response; - - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Transfer Complete:%s\n", ftdm_transfer_response2str(sngisdn_info->transfer_data.response)); - sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_TRANSFER_COMPLETED); - - ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLUSH_RX_BUFFERS, NULL); - return; -} - -void att_courtesy_transfer_timeout(void* p_sngisdn_info) -{ - sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info; - ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - - ftdm_mutex_lock(ftdmchan->mutex); - if (sngisdn_info->transfer_data.type == SNGISDN_TRANSFER_NONE) { - /* Call was already cleared */ - ftdm_mutex_unlock(ftdmchan->mutex); - return; - } - - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "AT&T Courtesy Transfer timeout (%d)\n", signal_data->transfer_timeout); - att_courtesy_transfer_complete(sngisdn_info, FTDM_TRANSFER_RESPONSE_TIMEOUT); - ftdm_mutex_unlock(ftdmchan->mutex); - return; -} - -static ftdm_status_t att_courtesy_vru(ftdm_channel_t *ftdmchan, sngisdn_transfer_type_t type, char* args) -{ - char dtmf_digits[64]; - ftdm_status_t status = FTDM_FAIL; - sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - char *p = args; - uint8_t forced_answer = 0; - - switch (signal_data->switchtype) { - case SNGISDN_SWITCH_5ESS: - case SNGISDN_SWITCH_4ESS: - break; - default: - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "AT&T Courtesy Transfer not supported for switchtype\n"); - return FTDM_FAIL; - } - - while (!ftdm_strlen_zero(p)) { - if (!isdigit(*p) && *p != 'w' && *p != 'W') { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot transfer to non-numeric number:%s\n", args); - return FTDM_FAIL; - } - p++; - } - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Performing AT&T Courtesy Transfer-VRU%s to %s\n", (type == SNGISDN_TRANSFER_ATT_COURTESY_VRU_DATA) ?"--data" : "", args); - sprintf(dtmf_digits, "*8w%s", args); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending digits %s\n", dtmf_digits); - - switch (ftdmchan->last_state) { - case FTDM_CHANNEL_STATE_PROCEED: - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - /* Call has to be in answered state - so send a CONNECT message if we did not answer this call yet */ - forced_answer++; - sngisdn_snd_connect(ftdmchan); - /* fall-through */ - case FTDM_CHANNEL_STATE_UP: - memset(&sngisdn_info->transfer_data.tdata.att_courtesy_vru.dtmf_digits, 0, sizeof(sngisdn_info->transfer_data.tdata.att_courtesy_vru.dtmf_digits)); - sngisdn_info->transfer_data.type = type; - - /* We will be polling the channel for IO so that we can receive the DTMF events, - * Disable user RX otherwise it is a race between who calls channel_read */ - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED); - - ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_DTMF_DETECT, NULL); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_SEND_DTMF, dtmf_digits); - - if (type == SNGISDN_TRANSFER_ATT_COURTESY_VRU_DATA) { - /* We need to save transfer data, so we can send it in the disconnect msg */ - const char *val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "transfer_data"); - if (ftdm_strlen_zero(val)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Cannot perform data transfer because transfer_data variable is not set\n"); - goto done; - } - if (strlen(val) > COURTESY_TRANSFER_MAX_DATA_SIZE) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Data exceeds max size (len:%"FTDM_SIZE_FMT" max:%d), cannot perform transfer\n", strlen(val), COURTESY_TRANSFER_MAX_DATA_SIZE); - goto done; - } - memcpy(sngisdn_info->transfer_data.tdata.att_courtesy_vru.data, val, strlen(val)); - } - - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); - if (forced_answer) { - /* Notify the user that we answered the call */ - sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_UP); - } - if (signal_data->transfer_timeout) { - ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "courtesy_transfer_timeout", signal_data->transfer_timeout, att_courtesy_transfer_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_CHAN_TIMER_ATT_TRANSFER]); - } - - status = FTDM_SUCCESS; - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot perform transfer in state %s\n", ftdm_channel_state2str(ftdmchan->state)); - break; - - } -done: - return status; -} - - -ftdm_status_t sngisdn_transfer(ftdm_channel_t *ftdmchan) -{ - const char* args; - char *p; - char *type = NULL; - char *target = NULL; - ftdm_status_t status = FTDM_FAIL; - sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; - unsigned i; - - args = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "transfer_arg"); - if (ftdm_strlen_zero(args)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Cannot perform transfer because call_transfer_arg variable is not set\n"); - goto done; - } - - type = ftdm_strdup(args); - if ((p = strchr(type, '/'))) { - target = ftdm_strdup(p+1); - *p = '\0'; - } - - if (ftdm_strlen_zero(type) || ftdm_strlen_zero(target)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Invalid parameters for transfer %s, expected /\n", args); - goto done; - } - - if (sngisdn_info->transfer_data.type != SNGISDN_TRANSFER_NONE) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot perform transfer because an existing transfer transfer is pending (%s)\n", sngisdn_transfer_type2str(sngisdn_info->transfer_data.type)); - goto done; - } - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Transfer requested type:%s target:%s\n", type, target); - for (i = 0; i < ftdm_array_len(transfer_interfaces); i++ ) { - if (!strcasecmp(transfer_interfaces[i].name, type)) { - /* Depending on the transfer type, the transfer function may change the - * channel state to UP, or last_state, but the transfer function will always result in - * an immediate state change if FTDM_SUCCESS is returned */ - - status = transfer_interfaces[i].func(ftdmchan, transfer_interfaces[i].type, target); - goto done; - } - } - - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Invalid transfer type:%s\n", type); - -done: - if (status != FTDM_SUCCESS) { - ftdm_set_state(ftdmchan, ftdmchan->last_state); - } - - ftdm_safe_free(type); - ftdm_safe_free(target); - return status; -} - -ftdm_status_t sngisdn_att_transfer_process_dtmf(ftdm_channel_t *ftdmchan, const char* dtmf) -{ - ftdm_status_t status = FTDM_SUCCESS; - sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - char *dtmf_digits = sngisdn_info->transfer_data.tdata.att_courtesy_vru.dtmf_digits; - ftdm_size_t dtmf_digits_len = strlen(dtmf_digits); - - dtmf_digits_len += sprintf(&dtmf_digits[dtmf_digits_len], "%s", dtmf); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Transfer response digits:%s\n", dtmf_digits); - if (dtmf_digits_len == 3) { - if (!strcmp(dtmf_digits, SNGISDN_ATT_TRANSFER_RESPONSE_CP_DROP_OFF)) { - sngisdn_info->transfer_data.response = FTDM_TRANSFER_RESPONSE_CP_DROP_OFF; - } else if (!strcmp(dtmf_digits, SNGISDN_ATT_TRANSFER_RESPONSE_LIMITS_EXCEEDED)) { - sngisdn_info->transfer_data.response = FTDM_TRANSFER_RESPONSE_LIMITS_EXCEEDED; - } else if (!strcmp(dtmf_digits, SNGISDN_ATT_TRANSFER_RESPONSE_OK)) { - sngisdn_info->transfer_data.response = FTDM_TRANSFER_RESPONSE_OK; - } else if (!strcmp(dtmf_digits, SNGISDN_ATT_TRANSFER_RESPONSE_INVALID_NUM)) { - sngisdn_info->transfer_data.response = FTDM_TRANSFER_RESPONSE_INVALID_NUM; - } else if (!strcmp(dtmf_digits, SNGISDN_ATT_TRANSFER_RESPONSE_INVALID_COMMAND)) { - sngisdn_info->transfer_data.response = FTDM_TRANSFER_RESPONSE_INVALID_COMMAND; - } else { - sngisdn_info->transfer_data.response = FTDM_TRANSFER_RESPONSE_INVALID; - } - if (signal_data->transfer_timeout) { - ftdm_sched_cancel_timer(signal_data->sched, sngisdn_info->timers[SNGISDN_CHAN_TIMER_ATT_TRANSFER]); - } - - if (sngisdn_info->transfer_data.response == FTDM_TRANSFER_RESPONSE_OK && - sngisdn_info->transfer_data.type == SNGISDN_TRANSFER_ATT_COURTESY_VRU_DATA) { - sngisdn_set_flag(sngisdn_info, FLAG_SEND_DISC); - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING; - sngisdn_snd_disconnect(ftdmchan); - } - /* Network side will send disconnect in case of NO-DATA Transfer */ - att_courtesy_transfer_complete(sngisdn_info, sngisdn_info->transfer_data.response); - } - - if (signal_data->att_remove_dtmf != SNGISDN_OPT_FALSE) { - /* If we return FTDM_BREAK, dtmf event is not queue'ed to user */ - status = FTDM_BREAK; - } - return status; -} diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_user.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_user.h deleted file mode 100644 index 74abeef94c..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_user.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * David Yat Sin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef __FTMOD_SANGOMA_ISDN_USER_H__ -#define __FTMOD_SANGOMA_ISDN_USER_H__ - - -#define SNGISDN_ENUM_NAMES(_NAME, _STRINGS) static const char * _NAME [] = { _STRINGS , NULL }; -#define SNGISDN_STR2ENUM_P(_FUNC1, _FUNC2, _TYPE) _TYPE _FUNC1 (const char *name); const char * _FUNC2 (_TYPE type); -#define SNGISDN_STR2ENUM(_FUNC1, _FUNC2, _TYPE, _STRINGS, _MAX) \ - _TYPE _FUNC1 (const char *name) \ - { \ - int i; \ - _TYPE t = _MAX ; \ - \ - for (i = 0; i < _MAX ; i++) { \ - if (!strcasecmp(name, _STRINGS[i])) { \ - t = (_TYPE) i; \ - break; \ - } \ - } \ - return t; \ - } \ - const char * _FUNC2 (_TYPE type) \ - { \ - if (type > _MAX) { \ - type = _MAX; \ - } \ - return _STRINGS[(int)type]; \ - } \ - - -typedef enum { - /* Call is not end-to-end ISDN */ - SNGISDN_PROGIND_DESCR_NETE_ISDN, - /* Destination address is non-ISDN */ - SNGISDN_PROGIND_DESCR_DEST_NISDN, - /* Origination address is non-ISDN */ - SNGISDN_PROGIND_DESCR_ORIG_NISDN, - /* Call has returned to the ISDN */ - SNGISDN_PROGIND_DESCR_RET_ISDN, - /* Interworking as occured and has resulted in a telecommunication service change */ - SNGISDN_PROGIND_DESCR_SERV_CHANGE, - /* In-band information or an appropriate pattern is now available */ - SNGISDN_PROGIND_DESCR_IB_AVAIL, - /* Invalid */ - SNGISDN_PROGIND_DESCR_INVALID, -} ftdm_sngisdn_progind_descr_t; -#define SNGISDN_PROGIND_DESCR_STRINGS "not-end-to-end-isdn", "destination-is-non-isdn", "origination-is-non-isdn", "call-returned-to-isdn", "service-change", "inband-info-available", "invalid" -SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr2str, ftdm_sngisdn_progind_descr_t); - - -typedef enum { - /* User */ - SNGISDN_PROGIND_LOC_USER, - /* Private network serving the local user */ - SNGISDN_PROGIND_LOC_PRIV_NET_LOCAL_USR, - /* Public network serving the local user */ - SNGISDN_PROGIND_LOC_PUB_NET_LOCAL_USR, - /* Transit network */ - SNGISDN_PROGIND_LOC_TRANSIT_NET, - /* Public network serving remote user */ - SNGISDN_PROGIND_LOC_PUB_NET_REMOTE_USR, - /* Private network serving remote user */ - SNGISDN_PROGIND_LOC_PRIV_NET_REMOTE_USR, - /* Network beyond the interworking point */ - SNGISDN_PROGIND_LOC_NET_BEYOND_INTRW, - /* Invalid */ - SNGISDN_PROGIND_LOC_INVALID, -} ftdm_sngisdn_progind_loc_t; -#define SNGISDN_PROGIND_LOC_STRINGS "user", "private-net-local-user", "public-net-local-user", "transit-network", "public-net-remote-user", "private-net-remote-user", "beyond-interworking", "invalid" -SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t); - -typedef enum { - /* User Specified */ - SNGISDN_NETSPECFAC_TYPE_USER_SPEC, - /* National network identification */ - SNGISDN_NETSPECFAC_TYPE_NATIONAL_NETWORK_IDENT, - /* International network identification */ - SNGISDN_NETSPECFAC_TYPE_INTERNATIONAL_NETWORK_IDENT, - /* Invalid */ - SNGISDN_NETSPECFAC_TYPE_INVALID, -} ftdm_sngisdn_netspecfac_type_t; -#define SNGISDN_NETSPECFAC_TYPE_STRINGS "user-specified", "national-network-identification", "national-network-identification", "invalid" -SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_netspecfac_type, ftdm_sngisdn_netspecfac_type2str, ftdm_sngisdn_netspecfac_type_t); - -typedef enum { - /* Unknown */ - SNGISDN_NETSPECFAC_PLAN_UNKNOWN, - /* Carrier Identification Code */ - SNGISDN_NETSPECFAC_PLAN_CARRIER_IDENT, - /* Data network identification code */ - SNGISDN_NETSPECFAC_PLAN_DATA_NETWORK_IDENT, - /* Invalid */ - SNGISDN_NETSPECFAC_PLAN_INVALID, -} ftdm_sngisdn_netspecfac_plan_t; -#define SNGISDN_NETSPECFAC_PLAN_STRINGS "unknown", "carrier-identification", "data-network-identification", "invalid" -SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_netspecfac_plan, ftdm_sngisdn_netspecfac_plan2str, ftdm_sngisdn_netspecfac_plan_t); - -typedef enum { - /* Unknown */ - SNGISDN_NETSPECFAC_SPEC_ACCUNET, - SNGISDN_NETSPECFAC_SPEC_MEGACOM, - SNGISDN_NETSPECFAC_SPEC_MEGACOM_800, - SNGISDN_NETSPECFAC_SPEC_SDDN, - SNGISDN_NETSPECFAC_SPEC_INVALID, -} ftdm_sngisdn_netspecfac_spec_t; -#define SNGISDN_NETSPECFAC_SPEC_STRINGS "accunet", "megacom", "megacom-800", "sddn", "invalid" -SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_netspecfac_spec, ftdm_sngisdn_netspecfac_spec2str, ftdm_sngisdn_netspecfac_spec_t); - -#endif /* __FTMOD_SANGOMA_ISDN_USER_H__*/ - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c deleted file mode 100644 index 1210e39bb0..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c +++ /dev/null @@ -1,1745 +0,0 @@ -/* - * Copyright (c) 2009|Konrad Hammel - * All rights reserved. - * - * Redistribution and use in source and binary forms|with or without - * modification|are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice|this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice|this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT - * LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL, - * EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* INCLUDE ********************************************************************/ -#include "ftmod_sangoma_ss7_main.h" -/******************************************************************************/ - -/* DEFINES ********************************************************************/ -/******************************************************************************/ - -/* GLOBALS ********************************************************************/ -/******************************************************************************/ - -/* PROTOTYPES *****************************************************************/ -int ft_to_sngss7_cfg_all(void); - -int ftmod_ss7_relay_gen_config(void); -int ftmod_ss7_mtp1_gen_config(void); -int ftmod_ss7_mtp2_gen_config(void); -int ftmod_ss7_mtp3_gen_config(void); -int ftmod_ss7_isup_gen_config(void); -int ftmod_ss7_cc_gen_config(void); - -int ftmod_ss7_mtp1_psap_config(int id); - -int ftmod_ss7_mtp2_dlsap_config(int id); - -int ftmod_ss7_mtp3_dlsap_config(int id); -int ftmod_ss7_mtp3_nsap_config(int id); -int ftmod_ss7_mtp3_linkset_config(int id); -int ftmod_ss7_mtp3_route_config(int id); - -int ftmod_ss7_isup_nsap_config(int id); -int ftmod_ss7_isup_intf_config(int id); -int ftmod_ss7_isup_ckt_config(int id); -int ftmod_ss7_isup_isap_config(int id); - -int ftmod_ss7_cc_isap_config(int id); - -int ftmod_ss7_relay_chan_config(int id); -/******************************************************************************/ - -/* FUNCTIONS ******************************************************************/ -int ft_to_sngss7_cfg_all(void) -{ - int x = 0; - int ret = 0; - - /* check if we have done gen_config already */ - if (g_ftdm_sngss7_data.gen_config == SNG_GEN_CFG_STATUS_INIT) { - /* update the global gen_config so we don't do it again */ - g_ftdm_sngss7_data.gen_config = SNG_GEN_CFG_STATUS_PENDING; - - /* start of by checking if the license and sig file are valid */ - if (sng_validate_license(g_ftdm_sngss7_data.cfg.license, - g_ftdm_sngss7_data.cfg.signature)) { - - SS7_CRITICAL("License verification failed..ending!\n"); - return 1; - } - - /* if the procId is not 0 then we are using relay mode */ - if (g_ftdm_sngss7_data.cfg.procId != 0) { - /* set the desired procID value */ - sng_set_procId((uint16_t)g_ftdm_sngss7_data.cfg.procId); - } - - /* start up the stack manager */ - if (sng_isup_init_sm()) { - SS7_CRITICAL("Failed to start Stack Manager\n"); - return 1; - } else { - SS7_INFO("Started Stack Manager!\n"); - sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_SM_STARTED); - } - - /* check if the configuration had a Relay Channel */ - if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY_PRESENT)) { - /* start up the relay task */ - if (sng_isup_init_relay()) { - SS7_CRITICAL("Failed to start Relay\n"); - return 1; - } else { - SS7_INFO("Started Relay!\n"); - sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY_STARTED); - } - - /* run general configuration on the relay task */ - if (ftmod_ss7_relay_gen_config()) { - SS7_CRITICAL("Relay General configuration FAILED!\n"); - return 1; - } else { - SS7_INFO("Relay General configuration DONE\n"); - } - - } /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY)) */ - - if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC_PRESENT)) { - if (sng_isup_init_cc()) { - SS7_CRITICAL("Failed to start Call-Control\n"); - return 1; - } else { - SS7_INFO("Started Call-Control!\n"); - sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC_STARTED); - } - if (ftmod_ss7_cc_gen_config()) { - SS7_CRITICAL("CC General configuration FAILED!\n"); - return 1; - } else { - SS7_INFO("CC General configuration DONE\n"); - } - if (ftmod_ss7_cc_isap_config(1)) { - SS7_CRITICAL("CC ISAP configuration FAILED!\n"); - return 1; - } else { - SS7_INFO("CC ISAP configuration DONE!\n"); - } - } /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC)) */ - - if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP_PRESENT)) { - if (sng_isup_init_isup()) { - SS7_CRITICAL("Failed to start ISUP\n"); - return 1; - } else { - SS7_INFO("Started ISUP!\n"); - sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP_STARTED); - } - if (ftmod_ss7_isup_gen_config()) { - SS7_CRITICAL("ISUP General configuration FAILED!\n"); - return 1; - } else { - SS7_INFO("ISUP General configuration DONE\n"); - } - } /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP)) */ - - if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3_PRESENT)) { - if (sng_isup_init_mtp3()) { - SS7_CRITICAL("Failed to start MTP3\n"); - return 1; - } else { - SS7_INFO("Started MTP3!\n"); - sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3_STARTED); - } - - if (ftmod_ss7_mtp3_gen_config()) { - SS7_CRITICAL("MTP3 General configuration FAILED!\n"); - return 1; - } else { - SS7_INFO("MTP3 General configuration DONE\n"); - } - } /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3)) */ - - if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2_PRESENT)) { - if (sng_isup_init_mtp2()) { - SS7_CRITICAL("Failed to start MTP2\n"); - return 1; - } else { - SS7_INFO("Started MTP2!\n"); - sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2_STARTED); - } - if (sng_isup_init_mtp1()) { - SS7_CRITICAL("Failed to start MTP1\n"); - return 1; - } else { - SS7_INFO("Started MTP1!\n"); - sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP1_STARTED); - } - if (ftmod_ss7_mtp1_gen_config()) { - SS7_CRITICAL("MTP1 General configuration FAILED!\n"); - return 1; - } else { - SS7_INFO("MTP1 General configuration DONE\n"); - } - if (ftmod_ss7_mtp2_gen_config()) { - SS7_CRITICAL("MTP2 General configuration FAILED!\n"); - return 1; - } else { - SS7_INFO("MTP2 General configuration DONE\n"); - } - } /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2)) */ - - if(SNG_SS7_OPR_MODE_M2UA_SG == g_ftdm_operating_mode){ - if(FTDM_SUCCESS != ftmod_ss7_m2ua_init()){ - ftdm_log (FTDM_LOG_ERROR, "ftmod_ss7_m2ua_init FAILED \n"); - return FTDM_FAIL; - } - } - - g_ftdm_sngss7_data.gen_config = SNG_GEN_CFG_STATUS_DONE; - - } /* if (!(g_ftdm_sngss7_data.gen_config)) */ - - - if (g_ftdm_sngss7_data.gen_config != SNG_GEN_CFG_STATUS_DONE) { - SS7_CRITICAL("General configuration FAILED!\n"); - return 1; - } - - x = 1; - while (x < (MAX_MTP_LINKS)) { - /* check if this link has been configured already */ - if ((g_ftdm_sngss7_data.cfg.mtp1Link[x].id != 0) && - (!(g_ftdm_sngss7_data.cfg.mtp1Link[x].flags & SNGSS7_CONFIGURED))) { - - /* configure mtp1 */ - if (ftmod_ss7_mtp1_psap_config(x)) { - SS7_CRITICAL("MTP1 PSAP %d configuration FAILED!\n", x); - return 1;; - } else { - SS7_INFO("MTP1 PSAP %d configuration DONE!\n", x); - } - - /* set the SNGSS7_CONFIGURED flag */ - g_ftdm_sngss7_data.cfg.mtp1Link[x].flags |= SNGSS7_CONFIGURED; - } - x++; - } /* while (x < (MAX_MTP_LINKS+1)) */ - - x = 1; - while (x < (MAX_MTP_LINKS)) { - /* check if this link has been configured already */ - if ((g_ftdm_sngss7_data.cfg.mtp2Link[x].id != 0) && - (!(g_ftdm_sngss7_data.cfg.mtp2Link[x].flags & SNGSS7_CONFIGURED))) { - - /* configure mtp2 */ - if (ftmod_ss7_mtp2_dlsap_config(x)) { - SS7_CRITICAL("MTP2 DLSAP %d configuration FAILED!\n",x); - return 1;; - } else { - SS7_INFO("MTP2 DLSAP %d configuration DONE!\n", x); - } - - /* set the SNGSS7_CONFIGURED flag */ - g_ftdm_sngss7_data.cfg.mtp2Link[x].flags |= SNGSS7_CONFIGURED; - } - x++; - } /* while (x < (MAX_MTP_LINKS+1)) */ - - /* no configs above mtp2 for relay */ - if (g_ftdm_sngss7_data.cfg.procId == 1) { - x = 1; - while (x < (MAX_MTP_LINKS)) { - /* check if this link has been configured already */ - if ((g_ftdm_sngss7_data.cfg.mtp3Link[x].id != 0) && - (!(g_ftdm_sngss7_data.cfg.mtp3Link[x].flags & SNGSS7_CONFIGURED))) { - - /* configure mtp3 */ - if (ftmod_ss7_mtp3_dlsap_config(x)) { - SS7_CRITICAL("MTP3 DLSAP %d configuration FAILED!\n", x); - return 1;; - } else { - SS7_INFO("MTP3 DLSAP %d configuration DONE!\n", x); - } - - /* set the SNGSS7_CONFIGURED flag */ - g_ftdm_sngss7_data.cfg.mtp3Link[x].flags |= SNGSS7_CONFIGURED; - } - - x++; - } /* while (x < (MAX_MTP_LINKS+1)) */ - - /* in M2UA_SG mode there will not be any MTP3 layer */ - if(SNG_SS7_OPR_MODE_M2UA_SG != g_ftdm_operating_mode){ - x = 1; - while (x < (MAX_NSAPS)) { - /* check if this link has been configured already */ - if ((g_ftdm_sngss7_data.cfg.nsap[x].id != 0) && - (!(g_ftdm_sngss7_data.cfg.nsap[x].flags & SNGSS7_CONFIGURED))) { - - ret = ftmod_ss7_mtp3_nsap_config(x); - if (ret) { - SS7_CRITICAL("MTP3 NSAP %d configuration FAILED!(%s)\n", x, DECODE_LCM_REASON(ret)); - return 1; - } else { - SS7_INFO("MTP3 NSAP %d configuration DONE!\n", x); - } - - ret = ftmod_ss7_isup_nsap_config(x); - if (ret) { - SS7_CRITICAL("ISUP NSAP %d configuration FAILED!(%s)\n", x, DECODE_LCM_REASON(ret)); - return 1; - } else { - SS7_INFO("ISUP NSAP %d configuration DONE!\n", x); - } - - /* set the SNGSS7_CONFIGURED flag */ - g_ftdm_sngss7_data.cfg.nsap[x].flags |= SNGSS7_CONFIGURED; - } /* if !SNGSS7_CONFIGURED */ - - x++; - } /* while (x < (MAX_NSAPS)) */ - } - - /* in M2UA_SG mode there will not be any MTP3 layer */ - if(SNG_SS7_OPR_MODE_M2UA_SG != g_ftdm_operating_mode){ - x = 1; - while (x < (MAX_MTP_LINKSETS+1)) { - /* check if this link has been configured already */ - if ((g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) && - (!(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags & SNGSS7_CONFIGURED))) { - - if (ftmod_ss7_mtp3_linkset_config(x)) { - SS7_CRITICAL("MTP3 LINKSET %d configuration FAILED!\n", x); - return 1; - } else { - SS7_INFO("MTP3 LINKSET %d configuration DONE!\n", x); - } - - /* set the SNGSS7_CONFIGURED flag */ - g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags |= SNGSS7_CONFIGURED; - } /* if !SNGSS7_CONFIGURED */ - - x++; - } /* while (x < (MAX_MTP_LINKSETS+1)) */ - } - - /* in M2UA_SG mode there will not be any MTP3 layer */ - if(SNG_SS7_OPR_MODE_M2UA_SG != g_ftdm_operating_mode){ - x = 1; - while (x < (MAX_MTP_ROUTES+1)) { - /* check if this link has been configured already */ - if ((g_ftdm_sngss7_data.cfg.mtpRoute[x].id != 0) && - (!(g_ftdm_sngss7_data.cfg.mtpRoute[x].flags & SNGSS7_CONFIGURED))) { - - if (ftmod_ss7_mtp3_route_config(x)) { - SS7_CRITICAL("MTP3 ROUTE %d configuration FAILED!\n", x); - return 1; - } else { - SS7_INFO("MTP3 ROUTE %d configuration DONE!\n",x); - } - - /* set the SNGSS7_CONFIGURED flag */ - g_ftdm_sngss7_data.cfg.mtpRoute[x].flags |= SNGSS7_CONFIGURED; - } /* if !SNGSS7_CONFIGURED */ - - x++; - } /* while (x < (MAX_MTP_ROUTES+1)) */ - } - - x = 1; - while (x < (MAX_ISAPS)) { - /* check if this link has been configured already */ - if ((g_ftdm_sngss7_data.cfg.isap[x].id != 0) && - (!(g_ftdm_sngss7_data.cfg.isap[x].flags & SNGSS7_CONFIGURED))) { - - if (ftmod_ss7_isup_isap_config(x)) { - SS7_CRITICAL("ISUP ISAP %d configuration FAILED!\n", x); - return 1; - } else { - SS7_INFO("ISUP ISAP %d configuration DONE!\n", x); - } - - /* set the SNGSS7_CONFIGURED flag */ - g_ftdm_sngss7_data.cfg.isap[x].flags |= SNGSS7_CONFIGURED; - } /* if !SNGSS7_CONFIGURED */ - - x++; - } /* while (x < (MAX_ISAPS)) */ - - if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP_STARTED)) { - x = 1; - while (x < (MAX_ISUP_INFS)) { - /* check if this link has been configured already */ - if ((g_ftdm_sngss7_data.cfg.isupIntf[x].id != 0) && - (!(g_ftdm_sngss7_data.cfg.isupIntf[x].flags & SNGSS7_CONFIGURED))) { - - if (ftmod_ss7_isup_intf_config(x)) { - SS7_CRITICAL("ISUP INTF %d configuration FAILED!\n", x); - return 1; - } else { - SS7_INFO("ISUP INTF %d configuration DONE!\n", x); - /* set the interface to paused */ - sngss7_set_flag(&g_ftdm_sngss7_data.cfg.isupIntf[x], SNGSS7_PAUSED); - } - - /* set the SNGSS7_CONFIGURED flag */ - g_ftdm_sngss7_data.cfg.isupIntf[x].flags |= SNGSS7_CONFIGURED; - } /* if !SNGSS7_CONFIGURED */ - - x++; - } /* while (x < (MAX_ISUP_INFS)) */ - } /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP)) */ - - x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - - if (g_ftdm_sngss7_data.cfg.procId > 1) { - break; - } - - /* check if this link has been configured already */ - if ((g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) && - (!(g_ftdm_sngss7_data.cfg.isupCkt[x].flags & SNGSS7_CONFIGURED))) { - - if (ftmod_ss7_isup_ckt_config(x)) { - SS7_CRITICAL("ISUP CKT %d configuration FAILED!\n", x); - return 1; - } else { - SS7_INFO("ISUP CKT %d configuration DONE!\n", x); - } - - /* set the SNGSS7_CONFIGURED flag */ - g_ftdm_sngss7_data.cfg.isupCkt[x].flags |= SNGSS7_CONFIGURED; - } /* if !SNGSS7_CONFIGURED */ - - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */ - } - - /* go through all the relays channels and configure it */ - x = 1; - while (x < (MAX_RELAY_CHANNELS)) { - /* check if this relay channel has been configured already */ - if ((g_ftdm_sngss7_data.cfg.relay[x].id != 0) && - (!(g_ftdm_sngss7_data.cfg.relay[x].flags & SNGSS7_CONFIGURED))) { - - /* send the specific configuration */ - if (ftmod_ss7_relay_chan_config(x)) { - SS7_CRITICAL("Relay Channel %d configuration FAILED!\n", x); - return 1; - } else { - SS7_INFO("Relay Channel %d configuration DONE!\n", x); - } - - /* set the SNGSS7_CONFIGURED flag */ - g_ftdm_sngss7_data.cfg.relay[x].flags |= SNGSS7_CONFIGURED; - } /* if !SNGSS7_CONFIGURED */ - x++; - } /* while (x < (MAX_RELAY_CHANNELS)) */ - - - if(SNG_SS7_OPR_MODE_M2UA_SG == g_ftdm_operating_mode){ - return ftmod_ss7_m2ua_cfg(); - } - - return 0; -} - -/******************************************************************************/ -int ftmod_ss7_relay_gen_config(void) -{ - RyMngmt cfg; /*configuration structure*/ - Pst pst; /*post structure*/ - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTRY; - - /* clear the configuration structure */ - memset(&cfg, 0x0, sizeof(RyMngmt)); - - /* fill in some general sections of the header */ - smHdrInit(&cfg.hdr); - - /* fill in the post structure */ - smPstInit( &cfg.t.cfg.s.ryGenCfg.lmPst ); - - /*fill in the specific fields of the header */ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTRY; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STGEN; - - cfg.t.cfg.s.ryGenCfg.lmPst.srcEnt = ENTRY; - cfg.t.cfg.s.ryGenCfg.lmPst.dstEnt = ENTSM; - - cfg.t.cfg.s.ryGenCfg.nmbChan = 10; - cfg.t.cfg.s.ryGenCfg.tmrRes = RY_PERIOD; - cfg.t.cfg.s.ryGenCfg.usta = 1; - - - return(sng_cfg_relay(&pst, &cfg)); -} - -/******************************************************************************/ -int ftmod_ss7_mtp1_gen_config(void) -{ - L1Mngmt cfg; /*configuration structure*/ - Pst pst; /*post structure*/ - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTL1; - - /* clear the configuration structure */ - memset(&cfg, 0x0, sizeof(L1Mngmt)); - - /* fill in some general sections of the header */ - smHdrInit(&cfg.hdr); - - /* fill in the post structure */ - smPstInit( &cfg.t.cfg.s.l1Gen.sm ); - - /*fill in the specific fields of the header */ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTL1; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STGEN; - - cfg.t.cfg.s.l1Gen.sm.srcEnt = ENTL1; - cfg.t.cfg.s.l1Gen.sm.dstEnt = ENTSM; - - cfg.t.cfg.s.l1Gen.nmbLnks = MAX_L1_LINKS; - cfg.t.cfg.s.l1Gen.poolTrUpper = POOL_UP_TR; /* upper pool threshold */ - cfg.t.cfg.s.l1Gen.poolTrLower = POOL_LW_TR; /* lower pool threshold */ - - return(sng_cfg_mtp1(&pst, &cfg)); -} - -/******************************************************************************/ -int ftmod_ss7_mtp2_gen_config(void) -{ - SdMngmt cfg; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSD; - - /* clear the configuration structure */ - memset(&cfg, 0x0, sizeof(SdMngmt)); - - /* fill in some general sections of the header */ - smHdrInit(&cfg.hdr); - - /* fill in the post structure */ - smPstInit( &cfg.t.cfg.s.sdGen.sm ); - - /* fill in the specific fields of the header */ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTSD; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STGEN; - - cfg.t.cfg.s.sdGen.sm.srcEnt = ENTSD; - cfg.t.cfg.s.sdGen.sm.dstEnt = ENTSM; - - cfg.t.cfg.s.sdGen.nmbLnks = MAX_SD_LINKS; - cfg.t.cfg.s.sdGen.poolTrUpper = POOL_UP_TR; - cfg.t.cfg.s.sdGen.poolTrLower = POOL_LW_TR; - - return(sng_cfg_mtp2(&pst, &cfg)); -} - -/******************************************************************************/ -int ftmod_ss7_mtp3_gen_config(void) -{ - SnMngmt cfg; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /*clear the configuration structure*/ - memset(&cfg, 0x0, sizeof(SnMngmt)); - - /*fill in some general sections of the header*/ - smHdrInit(&cfg.hdr); - - /* fill in the post structure */ - smPstInit(&cfg.t.cfg.s.snGen.sm); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTSN; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STGEN; - - cfg.t.cfg.s.snGen.sm.srcEnt = ENTSN; - cfg.t.cfg.s.snGen.sm.dstEnt = ENTSM; - - - cfg.t.cfg.s.snGen.typeSP = LSN_TYPE_SP; /* type of signalling postatic int */ - cfg.t.cfg.s.snGen.spCode1 = 0; /* our DPC for CCITT version */ -#if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || SS7_CHINA || defined(TDS_ROLL_UPGRADE_SUPPORT)) - cfg.t.cfg.s.snGen.spCode2 = 0; /* our DPC for ANSI or CHINA version */ -#endif - cfg.t.cfg.s.snGen.ssfValid = TRUE; /* ssf validation required */ - cfg.t.cfg.s.snGen.nmbDLSap = MAX_SN_LINKS; /* number of MTP Data Link SAPs */ - cfg.t.cfg.s.snGen.nmbNSap = MAX_SN_ROUTES; /* number of Upper Layer Saps */ - cfg.t.cfg.s.snGen.nmbRouts = MAX_SN_ROUTES; /* maximum number of routing entries */ - cfg.t.cfg.s.snGen.nmbLnkSets = MAX_SN_LINKSETS; /* number of link sets */ - cfg.t.cfg.s.snGen.nmbRteInst = MAX_SN_ROUTES*16; /* number of simultaneous Rte instances */ - cfg.t.cfg.s.snGen.cbTimeRes = SN_CB_PERIOD; /* link time resolution */ - cfg.t.cfg.s.snGen.spTimeRes = SN_SP_PERIOD; /* general time resolution */ - cfg.t.cfg.s.snGen.rteTimeRes = SN_RTE_PERIOD; /* route time resolution */ - cfg.t.cfg.s.snGen.extCmbndLnkst = FALSE; /* enbale extended combined linkset feature */ - -#if (defined(LSNV3) || defined(SN_MULTIPLE_NETWORK_RESTART)) - -#else - cfg.t.cfg.s.snGen.rstReq = LSN_NO_RST; /* restarting procedure required */ - cfg.t.cfg.s.snGen.tfrReq = FALSE; /* TFR procedure required or not */ - cfg.t.cfg.s.snGen.tmr.t15.enb = TRUE; /* t15 - waiting to start route set congestion test */ - cfg.t.cfg.s.snGen.tmr.t15.val = 30; - cfg.t.cfg.s.snGen.tmr.t16.enb = TRUE; /* t16 - waiting for route set congestion status update */ - cfg.t.cfg.s.snGen.tmr.t16.val = 20; - cfg.t.cfg.s.snGen.tmr.t18.enb = TRUE; /* t18 - waiting for links to become available */ - cfg.t.cfg.s.snGen.tmr.t18.val = 200; - cfg.t.cfg.s.snGen.tmr.t19.enb = TRUE; /* t19 - waiting to receive all traffic restart allowed */ - cfg.t.cfg.s.snGen.tmr.t19.val = 690; - cfg.t.cfg.s.snGen.tmr.t21.enb = TRUE; /* t21 - waiting to restart traffic routed through adjacent SP */ - cfg.t.cfg.s.snGen.tmr.t21.val = 650; -# if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || defined(TDS_ROLL_UPGRADE_SUPPORT)) - cfg.t.cfg.s.snGen.tmr.t26.enb = TRUE; /* t26 - waiting to repeat traffic restart waiting message for ANSI */ - cfg.t.cfg.s.snGen.tmr.t26.val = 600; -# endif -#endif - -#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS96) - cfg.t.cfg.s.snGen.mopc = FALSE; -#endif - - return(sng_cfg_mtp3(&pst, &cfg)); -} - -/******************************************************************************/ -int ftmod_ss7_isup_gen_config(void) -{ - SiMngmt cfg; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSI; - - /* clear the configuration structure */ - memset(&cfg, 0x0, sizeof(SiMngmt)); - - /* fill in some general sections of the header */ - smHdrInit(&cfg.hdr); - - /* fill in the post structure */ - smPstInit( &cfg.t.cfg.s.siGen.sm ); - - /*fill in the specific fields of the header */ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTSI; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STGEN; - - cfg.t.cfg.s.siGen.sm.srcEnt = ENTSI; - cfg.t.cfg.s.siGen.sm.dstEnt = ENTSM; - - cfg.t.cfg.s.siGen.nmbSaps = MAX_CC_INTERFACE; /* Number of ISUP Saps */ - cfg.t.cfg.s.siGen.nmbNSaps = MAX_SN_INTERFACE; /* Number of Network Saps */ - cfg.t.cfg.s.siGen.nmbCir = MAX_SI_CIRCUITS; /* Number of circuits */ - cfg.t.cfg.s.siGen.nmbIntf = MAX_SI_INTERFACES; /* Number of interfaces */ - cfg.t.cfg.s.siGen.nmbCirGrp = MAX_SI_CIR_GRP; /* Max number of circuit groups */ - cfg.t.cfg.s.siGen.nmbCalRef = MAX_SI_CALL_REF; /* Number of Call References */ - cfg.t.cfg.s.siGen.timeRes = SI_PERIOD; /* time resolution */ - cfg.t.cfg.s.siGen.sccpSup = FALSE; /* SCCP support */ - cfg.t.cfg.s.siGen.handleTTBinCC = FALSE; /* Flag used for controlling TTB feature */ - cfg.t.cfg.s.siGen.mapCPCandFCI = TRUE; /* Flag used for controlling TTB feature */ -#if (LSIV3 || LSIV4 || LSIV5) - cfg.t.cfg.s.siGen.lnkSelOpt = SI_LINK_SELECTION; /* link selector option */ -#endif - cfg.t.cfg.s.siGen.poolTrUpper = POOL_UP_TR; /* upper pool threshold */ - cfg.t.cfg.s.siGen.poolTrLower = POOL_LW_TR; /* lower pool threshold */ - cfg.t.cfg.s.siGen.cirGrTmr.t18.enb = TRUE; /* t18 timer - group blocking sent */ - cfg.t.cfg.s.siGen.cirGrTmr.t18.val = 300; - cfg.t.cfg.s.siGen.cirGrTmr.t19.enb = TRUE; /* t19 timer - initial group blocking sent */ - cfg.t.cfg.s.siGen.cirGrTmr.t19.val = 3000; - cfg.t.cfg.s.siGen.cirGrTmr.t20.enb = TRUE; /* t20 timer - group unblocking sent */ - cfg.t.cfg.s.siGen.cirGrTmr.t20.val = 300; - cfg.t.cfg.s.siGen.cirGrTmr.t21.enb = TRUE; /* t21 timer - initial grp unblocking sent */ - cfg.t.cfg.s.siGen.cirGrTmr.t21.val = 3000; - cfg.t.cfg.s.siGen.cirGrTmr.t22.enb = TRUE; /* t22 timer - group reset sent */ - cfg.t.cfg.s.siGen.cirGrTmr.t22.val = 300; - cfg.t.cfg.s.siGen.cirGrTmr.t23.enb = TRUE; /* t23 timer - initial group reset sent */ - cfg.t.cfg.s.siGen.cirGrTmr.t23.val = 3000; -#ifndef SS7_UK - cfg.t.cfg.s.siGen.cirGrTmr.t28.enb = TRUE; /* t28 timer - circuit group query sent */ - cfg.t.cfg.s.siGen.cirGrTmr.t28.val = 100; -#endif -#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL) - cfg.t.cfg.s.siGen.cirGrTmr.tFGR.enb = TRUE; /* first group received timer */ - cfg.t.cfg.s.siGen.cirGrTmr.tFGR.val = 50; -#endif -#if CGPN_CHK - cfg.t.cfg.s.siGen.cgPtyNumGenCfg = TRUE; /* Calling party number general config flag */ -#endif -#ifdef SI_SUPPRESS_CFN - cfg.t.cfg.s.siGen.suppressCfn = TRUE; /* Flag used for 'suppress CFN' feature */ -#endif - - return(sng_cfg_isup(&pst, &cfg)); - -} - -/******************************************************************************/ -int ftmod_ss7_cc_gen_config(void) -{ - CcMngmt cfg; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTCC; - - /*clear the configuration structure*/ - memset(&cfg, 0x0, sizeof(CcMngmt)); - - /*fill in some general sections of the header*/ - smHdrInit(&cfg.hdr); - - /* fill in the post structure */ - smPstInit( &cfg.t.cfg.s.ccGen.sm ); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTCC; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STGEN; - - cfg.t.cfg.s.ccGen.sm.srcEnt = ENTCC; - cfg.t.cfg.s.ccGen.sm.dstEnt = ENTSM; - - cfg.t.cfg.s.ccGen.poolTrUpper = POOL_UP_TR; /* upper pool threshold */ - cfg.t.cfg.s.ccGen.poolTrLower = POOL_LW_TR; /* lower pool threshold */ - - return(sng_cfg_cc(&pst, &cfg)); -} - -/******************************************************************************/ -int ftmod_ss7_mtp1_psap_config(int id) -{ - L1Mngmt cfg; - Pst pst; - sng_mtp1_link_t *k = &g_ftdm_sngss7_data.cfg.mtp1Link[id]; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTL1; - - /*clear the configuration structure*/ - memset(&cfg, 0x0, sizeof(L1Mngmt)); - - /*fill in some general sections of the header*/ - smHdrInit(&cfg.hdr); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTL1; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STPSAP; - - cfg.hdr.elmId.elmntInst1 = k->id; - - cfg.t.cfg.s.l1PSAP.span = k->span; - cfg.t.cfg.s.l1PSAP.chan = k->chan; - cfg.t.cfg.s.l1PSAP.spId = k->id; - - return(sng_cfg_mtp1(&pst, &cfg)); -} - -/******************************************************************************/ -int ftmod_ss7_mtp2_dlsap_config(int id) -{ - SdMngmt cfg; - Pst pst; - sng_mtp2_link_t *k = &g_ftdm_sngss7_data.cfg.mtp2Link[id]; - - /* initalize the post structure */ - smPstInit( &pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSD; - - /*clear the configuration structure*/ - memset(&cfg, 0x0, sizeof(SdMngmt)); - - /*fill in some general sections of the header*/ - smHdrInit(&cfg.hdr); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTSD; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STDLSAP; - - cfg.hdr.elmId.elmntInst1 = k->id; - - cfg.t.cfg.s.sdDLSAP.mem.region = S_REG; /* memory region */ - cfg.t.cfg.s.sdDLSAP.mem.pool = S_POOL; /* memory pool */ - cfg.t.cfg.s.sdDLSAP.swtch = k->linkType; /* protocol type */ - cfg.t.cfg.s.sdDLSAP.priorDl = PRIOR0; /* priority for data link layer */ - cfg.t.cfg.s.sdDLSAP.routeDl = RTESPEC; /* route for data link layer */ - cfg.t.cfg.s.sdDLSAP.selectorDl = 0; /* upper interface selector */ - if (k->mtp1ProcId > 0) { - cfg.t.cfg.s.sdDLSAP.dstProcId = k->mtp1ProcId; /* the procid of MAC/L1/MTP1 */ - } else { - cfg.t.cfg.s.sdDLSAP.dstProcId = SFndProcId(); /* the procid of MAC/L1/MTP1 */ - } - cfg.t.cfg.s.sdDLSAP.dstProcId = SFndProcId(); /* the procid of MAC/L1/MTP1 */ - cfg.t.cfg.s.sdDLSAP.entMac = ENTL1; /* entity for MAC */ - cfg.t.cfg.s.sdDLSAP.instMac = S_INST; /* instance for MAC */ - cfg.t.cfg.s.sdDLSAP.priorMac = PRIOR0; /* priority for MAC layer */ - cfg.t.cfg.s.sdDLSAP.routeMac = RTESPEC; /* route for MAC layer */ - cfg.t.cfg.s.sdDLSAP.selectorMac = 0; /* lower interface selector */ - cfg.t.cfg.s.sdDLSAP.memMac.region = S_REG; /* memory region and pool id for MAC */ - cfg.t.cfg.s.sdDLSAP.memMac.pool = S_POOL; - cfg.t.cfg.s.sdDLSAP.maxOutsFrms = MAX_SD_OUTSTANDING; /* maximum outstanding frames */ - cfg.t.cfg.s.sdDLSAP.errType = k->errorType; - cfg.t.cfg.s.sdDLSAP.t1.enb = TRUE; /* timer 1 - Alignment Ready Timer */ - cfg.t.cfg.s.sdDLSAP.t1.val = k->t1; - cfg.t.cfg.s.sdDLSAP.t2.enb = TRUE; /* timer 2 - Not Aligned Timer */ - cfg.t.cfg.s.sdDLSAP.t2.val = k->t2; - cfg.t.cfg.s.sdDLSAP.t3.enb = TRUE; /* timer 3 - Aligned Timer */ - cfg.t.cfg.s.sdDLSAP.t3.val = k->t3; - cfg.t.cfg.s.sdDLSAP.t5.enb = TRUE; /* timer 5 - Sending SIB timer */ - cfg.t.cfg.s.sdDLSAP.t5.val = k->t5; - cfg.t.cfg.s.sdDLSAP.t6.enb = TRUE; /* timer 6 - Remote Congestion Timer */ - cfg.t.cfg.s.sdDLSAP.t6.val = k->t6; - cfg.t.cfg.s.sdDLSAP.t7.enb = TRUE; /* timer 7 - Excessive delay of acknowledgement timer */ - cfg.t.cfg.s.sdDLSAP.t7.val = k->t7; - cfg.t.cfg.s.sdDLSAP.provEmrgcy = k->t4e; /* emergency proving period */ - cfg.t.cfg.s.sdDLSAP.provNormal = k->t4n; /* normal proving period */ - cfg.t.cfg.s.sdDLSAP.lssuLen = k->lssuLength; /* one or two byte LSSU length */ - cfg.t.cfg.s.sdDLSAP.maxFrmLen = MAX_SD_FRAME_LEN; /* max frame length for MSU */ - cfg.t.cfg.s.sdDLSAP.congDisc = FALSE; /* congestion discard TRUE or FALSE */ - cfg.t.cfg.s.sdDLSAP.sdT = MAX_SD_SUERM; /* SUERM error rate threshold */ - cfg.t.cfg.s.sdDLSAP.sdTie = MAX_SD_AERM_EMERGENCY; /* AERM emergency error rate threshold */ - cfg.t.cfg.s.sdDLSAP.sdTin = MAX_SD_AERM_NORMAL; /* AERM normal error rate threshold */ - cfg.t.cfg.s.sdDLSAP.sdN1 = MAX_SD_MSU_RETRANS; /* maximum number of MSUs for retransmission */ - cfg.t.cfg.s.sdDLSAP.sdN2 = MAX_SD_OCTETS_RETRANS; /* maximum number of MSU octets for retrans */ - cfg.t.cfg.s.sdDLSAP.sdCp = MAX_SD_ALIGN_ATTEMPTS; /* maximum number of alignment attempts */ - cfg.t.cfg.s.sdDLSAP.spIdSE = k->mtp1Id; /* service provider id */ - cfg.t.cfg.s.sdDLSAP.sdtFlcStartTr = 256; /* SDT interface flow control start thresh */ - cfg.t.cfg.s.sdDLSAP.sdtFlcEndTr = 512; /* SDT interface flow control end thresh */ - -#ifdef SD_HSL - cfg.t.cfg.s.sdDLSAP.sapType =; /* Indcates whether link is HSL or LSL */ - cfg.t.cfg.s.sdDLSAP.sapFormat =; /* The extened sequence no to be used or not */ - cfg.t.cfg.s.sdDLSAP.t8.enb =; /* timer 8 configuration structure */ - cfg.t.cfg.s.sdDLSAP.sdTe =; /* EIM threshold */ - cfg.t.cfg.s.sdDLSAP.sdUe =; /* increment constant */ - cfg.t.cfg.s.sdDLSAP.sdDe =; /* decrement constant */ -#endif /* HIGH_SPEED_SIGNALING_SUPPORT */ - -#if (SS7_TTC || SS7_NTT) - cfg.t.cfg.s.sdDLSAP.numRtb =; /* outstanding number of messages in RTB */ - cfg.t.cfg.s.sdDLSAP.tf =; /* FISU transmission interval */ - cfg.t.cfg.s.sdDLSAP.tfv =; /* FISU transmission interval during verification */ - cfg.t.cfg.s.sdDLSAP.to =; /* SIO transmission interval */ - cfg.t.cfg.s.sdDLSAP.ta =; /* SIE transmission interval */ - cfg.t.cfg.s.sdDLSAP.ts =; /* SIOS transmission interval */ - cfg.t.cfg.s.sdDLSAP.tso =; /* SIOS transmission duration when out of service */ - cfg.t.cfg.s.sdDLSAP.te =; /* SU normalization time */ -#endif /* (SS7_TTC || SS7_NTT) */ - -#if (SS7_NTT) /* NTTT - Q.703 */ - cfg.t.cfg.s.sdDLSAP.repMsuNack =; /* Nack on receipt of repeated MSU */ - cfg.t.cfg.s.sdDLSAP.invFibIgnore =; /* invalid FIB ignore or bring the link down */ - cfg.t.cfg.s.sdDLSAP.invBsnIgnore =; /* invalid BSN ignore or bring the link down */ - cfg.t.cfg.s.sdDLSAP.congAbatOnNack =; /* congestion abatement on nack or only on acks */ -#endif /* (SS7_NTT) */ - -#ifdef TDS_ROLL_UPGRADE_SUPPORT - cfg.t.cfg.s.sdDLSAP.hlremIntfValid = FALSE; /* Upper Sap Version number valid ? */ - cfg.t.cfg.s.sdDLSAP.remIntfVer = SDTIFVER; /* remote version info */ -#endif /*RUG*/ - - return(sng_cfg_mtp2(&pst, &cfg)); -} - -/******************************************************************************/ -int ftmod_ss7_mtp3_dlsap_config(int id) -{ - Pst pst; - SnMngmt cfg; - sng_mtp3_link_t *k = &g_ftdm_sngss7_data.cfg.mtp3Link[id]; - - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /*clear the configuration structure*/ - memset(&cfg, 0x0, sizeof(SnMngmt)); - - /*fill in some general sections of the header*/ - smHdrInit(&cfg.hdr); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTSN; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STDLSAP; - - cfg.hdr.elmId.elmntInst1 = k->id; - - cfg.t.cfg.s.snDLSAP.lnkSetId = k->linkSetId; /* link set ID */ - cfg.t.cfg.s.snDLSAP.opc = k->spc; /* Originating Postatic int Code */ - cfg.t.cfg.s.snDLSAP.adjDpc = k->apc; /* Adlacent Destination Postatic int Code */ - cfg.t.cfg.s.snDLSAP.lnkPrior = 0; /* link priority within the link set */ - cfg.t.cfg.s.snDLSAP.msgSize = MAX_SN_MSG_SIZE; /* message length */ - cfg.t.cfg.s.snDLSAP.msgPrior = 0; /* management message priority */ - cfg.t.cfg.s.snDLSAP.lnkType = k->linkType; /* link type ANSI, ITU, BICI or CHINA */ - cfg.t.cfg.s.snDLSAP.upSwtch = k->switchType; /* user part switch type */ - cfg.t.cfg.s.snDLSAP.maxSLTtry = MAX_SLTM_RETRIES; /* maximun times to retry SLTM */ - cfg.t.cfg.s.snDLSAP.p0QLen = 32; /* size of the priority 0 Q */ - cfg.t.cfg.s.snDLSAP.p1QLen = 32; /* size of the priority 1 Q */ - cfg.t.cfg.s.snDLSAP.p2QLen = 32; /* size of the priority 2 Q */ - cfg.t.cfg.s.snDLSAP.p3QLen = 32; /* size of the priority 3 Q */ - cfg.t.cfg.s.snDLSAP.discPrior = 0; /* discard priority */ -#ifndef SDT2 - cfg.t.cfg.s.snDLSAP.maxCredit = MAX_SN_CREDIT; /* max credit */ -#endif /* SDT2 */ - cfg.t.cfg.s.snDLSAP.lnkId = 0; /* signalling link allocation procedure identity */ - cfg.t.cfg.s.snDLSAP.lnkTstSLC = k->slc; /* link selection code for link test */ - cfg.t.cfg.s.snDLSAP.tstLen = 7; /* link test pattern length */ - cfg.t.cfg.s.snDLSAP.tst[0] = 'S'; /* link test pattern */ - cfg.t.cfg.s.snDLSAP.tst[1] = 'A'; /* link test pattern */ - cfg.t.cfg.s.snDLSAP.tst[2] = 'N'; /* link test pattern */ - cfg.t.cfg.s.snDLSAP.tst[3] = 'G'; /* link test pattern */ - cfg.t.cfg.s.snDLSAP.tst[4] = 'O'; /* link test pattern */ - cfg.t.cfg.s.snDLSAP.tst[5] = 'M'; /* link test pattern */ - cfg.t.cfg.s.snDLSAP.tst[6] = 'A'; /* link test pattern */ - cfg.t.cfg.s.snDLSAP.ssf = k->ssf; /* sub service field */ - cfg.t.cfg.s.snDLSAP.dstProcId = k->mtp2ProcId; /* destination processor id */ - cfg.t.cfg.s.snDLSAP.dstEnt = ENTSD; /* entity */ - cfg.t.cfg.s.snDLSAP.dstInst = S_INST; /* instance */ - cfg.t.cfg.s.snDLSAP.prior = PRIOR0; /* priority */ - cfg.t.cfg.s.snDLSAP.route = RTESPEC; /* route */ - cfg.t.cfg.s.snDLSAP.selector = 0; /* lower layer selector */ - cfg.t.cfg.s.snDLSAP.mem.region = S_REG; /* memory region id */ - cfg.t.cfg.s.snDLSAP.mem.pool = S_POOL; /* memory pool id */ - cfg.t.cfg.s.snDLSAP.spId = k->mtp2Id; /* service provider id */ - - switch (k->linkType) { - /**************************************************************************/ - case (LSN_SW_ANS): - case (LSN_SW_ANS96): - case (LSN_SW_CHINA): - cfg.t.cfg.s.snDLSAP.dpcLen = DPC24; /* dpc length 24 bits */ - cfg.t.cfg.s.snDLSAP.l2Type = LSN_MTP2_56KBPS; /* layer 2 type - 56kbps MTP2 link, 1.536Mbps MTP2 link or QSAAL link */ - cfg.t.cfg.s.snDLSAP.isCLink = FALSE; /* identifies if the link is a C type link.Required to check if sls has to be rotated.*/ - break; - /**************************************************************************/ - case (LSN_SW_ITU): - cfg.t.cfg.s.snDLSAP.dpcLen = DPC14; /* dpc length 14 bits */ - break; - /**************************************************************************/ - default: - cfg.t.cfg.s.snDLSAP.dpcLen = DPC14; /* dpc length 14 bits */ - break; - /**************************************************************************/ - } /* switch (k->linkType) */ - - switch (k->linkType) { - /**************************************************************************/ - case (LSN_SW_ANS): - case (LSN_SW_ANS96): - cfg.t.cfg.s.snDLSAP.flushContFlag = TRUE; /* flush continue handling */ - break; - /**************************************************************************/ - case (LSN_SW_ITU): - case (LSN_SW_CHINA): - cfg.t.cfg.s.snDLSAP.flushContFlag = FALSE; /* flush continue handling */ - break; - /**************************************************************************/ - default: - cfg.t.cfg.s.snDLSAP.flushContFlag = FALSE; /* flush continue handling */ - break; - /**************************************************************************/ - } /* switch (k->linkType) */ - - cfg.t.cfg.s.snDLSAP.tmr.t1.enb = TRUE; /* t1 - delay to avoid missequencing on changeover */ - cfg.t.cfg.s.snDLSAP.tmr.t1.val = k->t1; - cfg.t.cfg.s.snDLSAP.tmr.t2.enb = TRUE; /* t2 - waiting for changeover ack */ - cfg.t.cfg.s.snDLSAP.tmr.t2.val = k->t2; - cfg.t.cfg.s.snDLSAP.tmr.t3.enb = TRUE; /* t3 - delay to avoid missequencing on changeback */ - cfg.t.cfg.s.snDLSAP.tmr.t3.val = k->t3; - cfg.t.cfg.s.snDLSAP.tmr.t4.enb = TRUE; /* t4 - waiting for first changeback ack */ - cfg.t.cfg.s.snDLSAP.tmr.t4.val = k->t4; - cfg.t.cfg.s.snDLSAP.tmr.t5.enb = TRUE; /* t5 - waiting for second changeback ack */ - cfg.t.cfg.s.snDLSAP.tmr.t5.val = k->t5; - cfg.t.cfg.s.snDLSAP.tmr.t7.enb = TRUE; /* t7 - waiting for link connection ack */ - cfg.t.cfg.s.snDLSAP.tmr.t7.val = k->t7; - cfg.t.cfg.s.snDLSAP.tmr.t12.enb = TRUE; /* t12 - waiting for uninhibit ack */ - cfg.t.cfg.s.snDLSAP.tmr.t12.val = k->t12; - cfg.t.cfg.s.snDLSAP.tmr.t13.enb = TRUE; /* t13 - waiting for forced uninhibit */ - cfg.t.cfg.s.snDLSAP.tmr.t13.val = k->t13; - cfg.t.cfg.s.snDLSAP.tmr.t14.enb = TRUE; /* t14 - waiting for inhibition ack */ - cfg.t.cfg.s.snDLSAP.tmr.t14.val = k->t14; - cfg.t.cfg.s.snDLSAP.tmr.t17.enb = TRUE; /* t17 - delay to avoid oscillation of initial alignment failure */ - cfg.t.cfg.s.snDLSAP.tmr.t17.val = k->t17; - cfg.t.cfg.s.snDLSAP.tmr.t22.enb = TRUE; /* t22 - local inhibit test timer */ - cfg.t.cfg.s.snDLSAP.tmr.t22.val = k->t22; - cfg.t.cfg.s.snDLSAP.tmr.t23.enb = TRUE; /* t23 - remote inhibit test timer */ - cfg.t.cfg.s.snDLSAP.tmr.t23.val = k->t23; - cfg.t.cfg.s.snDLSAP.tmr.t24.enb = TRUE; /* t24 - stabilizing timer */ - cfg.t.cfg.s.snDLSAP.tmr.t24.val = k->t24; - cfg.t.cfg.s.snDLSAP.tmr.t31.enb = TRUE; /* t31 - BSN requested timer */ - cfg.t.cfg.s.snDLSAP.tmr.t31.val = k->t31; - cfg.t.cfg.s.snDLSAP.tmr.t32.enb = TRUE; /* t32 - SLT timer */ - cfg.t.cfg.s.snDLSAP.tmr.t32.val = k->t32; - cfg.t.cfg.s.snDLSAP.tmr.t33.enb = TRUE; /* t33 - connecting timer */ - cfg.t.cfg.s.snDLSAP.tmr.t33.val = k->t33; - cfg.t.cfg.s.snDLSAP.tmr.t34.enb = TRUE; /* t34 - periodic signalling link test timer */ - cfg.t.cfg.s.snDLSAP.tmr.t34.val = k->t34; -#if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || defined(TDS_ROLL_UPGRADE_SUPPORT)) - cfg.t.cfg.s.snDLSAP.tmr.t35.enb = TRUE; /* t35 - false link congestion timer, same as t31 of ANSI'96*/ - cfg.t.cfg.s.snDLSAP.tmr.t35.val = k->t35; - cfg.t.cfg.s.snDLSAP.tmr.t36.enb = TRUE; /* t36 - false link congestion timer, same as t33 of ANSI'96*/ - cfg.t.cfg.s.snDLSAP.tmr.t36.val = k->t36; - cfg.t.cfg.s.snDLSAP.tmr.t37.enb = TRUE; /* t37 - false link congestion timer, same as t34 of ANSI'96*/ - cfg.t.cfg.s.snDLSAP.tmr.t37.val = k->t37; - cfg.t.cfg.s.snDLSAP.tmr.tCraft.enb = TRUE; /* link referral craft timer - T19 in ANSI */ - cfg.t.cfg.s.snDLSAP.tmr.tCraft.val = k->tcraft; -#endif -#ifdef SDT2 - cfg.t.cfg.s.snDLSAP.tmr.tFlc.enb = TRUE; /* flow control timer */ - cfg.t.cfg.s.snDLSAP.tmr.tFlc.val = 300; - cfg.t.cfg.s.snDLSAP.tmr.tBnd.enb = TRUE; /* bind request timer */ - cfg.t.cfg.s.snDLSAP.tmr.tBnd.val = 20; -#endif /* SDT2 */ -#ifdef TDS_ROLL_UPGRADE_SUPPORT - cfg.t.cfg.s.snDLSAP.remIntfValid = FALSE; /* remote interface version is valid */ - cfg.t.cfg.s.snDLSAP.remIntfVer = SNTIFVER; /* remote interface version */ -#endif - - return(sng_cfg_mtp3(&pst, &cfg)); -} - -/******************************************************************************/ -int ftmod_ss7_mtp3_nsap_config(int id) -{ - Pst pst; - SnMngmt cfg; - sng_nsap_t *k = &g_ftdm_sngss7_data.cfg.nsap[id]; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /*clear the configuration structure*/ - memset(&cfg, 0x0, sizeof(SnMngmt)); - - /*fill in some general sections of the header*/ - smHdrInit(&cfg.hdr); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTSN; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STNSAP; - - cfg.hdr.elmId.elmntInst1 = k->spId; - - cfg.t.cfg.s.snNSAP.ssf = k->ssf; /* sub service field */ - cfg.t.cfg.s.snNSAP.lnkType = k->linkType; /* link type -ANSI, ITU, CHINA or BICI */ - cfg.t.cfg.s.snNSAP.upSwtch = k->switchType; /* user part switch type */ - cfg.t.cfg.s.snNSAP.selector = 0; /* upper layer selector */ - cfg.t.cfg.s.snNSAP.mem.region = S_REG; /* memory region id */ - cfg.t.cfg.s.snNSAP.mem.pool = S_POOL; /* memory pool id */ - cfg.t.cfg.s.snNSAP.prior = PRIOR0; /* priority */ - cfg.t.cfg.s.snNSAP.route = RTESPEC; /* route */ -#if( SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || SS7_CHINA ) - cfg.t.cfg.s.snNSAP.dpcLen = DPC24; /* dpc length 14 or 24 bits */ -#else - cfg.t.cfg.s.snNSAP.dpcLen = DPC14; /* dpc length 14 or 24 bits */ -#endif -#if (defined(SN_SG) || defined(TDS_ROLL_UPGRADE_SUPPORT)) - cfg.t.cfg.s.snNSAP.usrParts = ; /* user parts configured on self postatic int code on IP side */ -#endif -#ifdef TDS_ROLL_UPGRADE_SUPPORT - cfg.t.cfg.s.snNSAP.remIntfValid = FALSE; /* remote interface version is valid */ - cfg.t.cfg.s.snNSAP.remIntfVer = SNTIFVER; /* remote interface version */ -#endif - - return(sng_cfg_mtp3(&pst, &cfg)); -} - -/******************************************************************************/ -int ftmod_ss7_mtp3_linkset_config(int id) -{ - Pst pst; - SnMngmt cfg; - int c; - sng_link_set_t *k = &g_ftdm_sngss7_data.cfg.mtpLinkSet[id]; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /*clear the configuration structure*/ - memset(&cfg, 0x0, sizeof(SnMngmt)); - - /*fill in some general sections of the header*/ - smHdrInit(&cfg.hdr); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTSN; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STLNKSET; /* link set */ - - cfg.hdr.elmId.elmntInst1 = k->id; - - cfg.t.cfg.s.snLnkSet.lnkSetId = k->id; /* link set ID */ - cfg.t.cfg.s.snLnkSet.lnkSetType = k->linkType; /* link type */ - cfg.t.cfg.s.snLnkSet.adjDpc = k->apc; /* adjacent DPC */ - cfg.t.cfg.s.snLnkSet.nmbActLnkReqd = k->minActive; /* minimum number of active links */ - cfg.t.cfg.s.snLnkSet.nmbCmbLnkSet = k->numLinks; /* number of combined link sets */ - for(c = 0; c < k->numLinks;c++) { - cfg.t.cfg.s.snLnkSet.cmbLnkSet[c].cmbLnkSetId = k->links[c]; - cfg.t.cfg.s.snLnkSet.cmbLnkSet[c].lnkSetPrior = 0; - } - - - return(sng_cfg_mtp3(&pst, &cfg)); -} - -/******************************************************************************/ -int ftmod_ss7_mtp3_route_config(int id) -{ - Pst pst; - SnMngmt cfg; - sng_route_t *k = &g_ftdm_sngss7_data.cfg.mtpRoute[id]; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /*clear the configuration structure*/ - memset(&cfg, 0x0, sizeof(SnMngmt)); - - /*fill in some general sections of the header*/ - smHdrInit(&cfg.hdr); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTSN; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STROUT; - - cfg.hdr.elmId.elmntInst1 = k->id; - - cfg.t.cfg.s.snRout.dpc = k->dpc; /* destination postatic int code */ - cfg.t.cfg.s.snRout.spType = LSN_TYPE_SP; /* signalling postatic int type */ - cfg.t.cfg.s.snRout.swtchType = k->linkType; /* switch type */ - cfg.t.cfg.s.snRout.upSwtch = k->switchType; /* user part switch type */ - cfg.t.cfg.s.snRout.cmbLnkSetId = k->cmbLinkSetId; /* combined link set ID */ - if (k->dir == SNG_RTE_UP) { - cfg.t.cfg.s.snRout.dir = LSN_RTE_UP; /* direction */ - } else { - cfg.t.cfg.s.snRout.dir = LSN_RTE_DN; /* direction */ - } - cfg.t.cfg.s.snRout.rteToAdjSp = 0; /* flag indicating this route to adjacent SP */ - cfg.t.cfg.s.snRout.ssf = k->ssf; /* sub service field */ - cfg.t.cfg.s.snRout.brdcastFlg = TRUE; /* flag indicating to have TFP broadcast */ - if (cfg.t.cfg.s.snRout.swtchType == LSN_SW_ITU) { - cfg.t.cfg.s.snRout.rstReq = LSN_ITU92_RST; /* Restart type supported by the node */ - } else if ((cfg.t.cfg.s.snRout.swtchType == LSN_SW_ANS) || - (cfg.t.cfg.s.snRout.swtchType == LSN_SW_ANS96)) { - cfg.t.cfg.s.snRout.rstReq = LSN_ANS_RST; /* Restart type supported by the node */ - } else { - cfg.t.cfg.s.snRout.rstReq = LSN_NO_RST; /* Restart type supported by the node */ - } - if ((cfg.t.cfg.s.snRout.swtchType == LSN_SW_ITU) || - (cfg.t.cfg.s.snRout.swtchType == LSN_SW_CHINA) || - (cfg.t.cfg.s.snRout.swtchType == LSN_SW_BICI)) { - cfg.t.cfg.s.snRout.slsRange = LSN_ITU_SLS_RANGE; /* max value of SLS for this DPC */ - } else { - cfg.t.cfg.s.snRout.slsRange = LSN_ANSI_5BIT_SLS_RANGE; /* max value of SLS for this DPC */ - } - cfg.t.cfg.s.snRout.lsetSel = 0x1; /* linkset selection bit in SLS for STP */ - cfg.t.cfg.s.snRout.multiMsgPrior = TRUE; /* TRUE if multiple cong priorities of messages */ - cfg.t.cfg.s.snRout.rctReq = TRUE; /* route set congestion test required or not */ - cfg.t.cfg.s.snRout.slsLnk = FALSE; -#ifdef LSNV2 -# if (SS7_NTT || defined(TDS_ROLL_UPGRADE_SUPPORT)) - cfg.t.cfg.s.snRout.destSpec =; /* destination specfication A or B*/ -# endif -#endif -#if (defined(LSNV3) || defined(SN_MULTIPLE_NETWORK_RESTART)) - cfg.t.cfg.s.snRout.tfrReq =; /* TFR procedure required or not */ -#endif - cfg.t.cfg.s.snRout.tmr.t6.enb = TRUE; - cfg.t.cfg.s.snRout.tmr.t6.val = k->t6; - cfg.t.cfg.s.snRout.tmr.t8.enb = TRUE; /* t8 - transfer prohibited inhibition timer */ - cfg.t.cfg.s.snRout.tmr.t8.val = k->t8; - cfg.t.cfg.s.snRout.tmr.t10.enb = TRUE; /* t10 - waiting to repeat route set test */ - cfg.t.cfg.s.snRout.tmr.t10.val = k->t10; - cfg.t.cfg.s.snRout.tmr.t11.enb = TRUE; /* t11 - transfer restrict timer */ - cfg.t.cfg.s.snRout.tmr.t11.val = k->t11; - cfg.t.cfg.s.snRout.tmr.t19.enb = TRUE; /* t19 - TRA sent timer */ - cfg.t.cfg.s.snRout.tmr.t19.val = k->t19; - cfg.t.cfg.s.snRout.tmr.t21.enb = TRUE; /* t21 - waiting to restart traffic routed through adjacent SP */ - cfg.t.cfg.s.snRout.tmr.t21.val = k->t21; - -#if (defined(LSNV3) || defined(SN_MULTIPLE_NETWORK_RESTART)) - cfg.t.cfg.s.snRout.tmr.t15.enb = TRUE; /* t15 - waiting to start route set congestion test */ - cfg.t.cfg.s.snRout.tmr.t15.val = k->t15; - cfg.t.cfg.s.snRout.tmr.t16.enb = TRUE; /* t16 - waiting for route set congestion status update */ - cfg.t.cfg.s.snRout.tmr.t16.val = k->t16; - cfg.t.cfg.s.snRout.tmr.t18.enb = TRUE; /* t18 - transfer prohibited inhibition timer */ - cfg.t.cfg.s.snRout.tmr.t18.val = k->t18; -# if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || defined(TDS_ROLL_UPGRADE_SUPPORT)) - cfg.t.cfg.s.snRout.tmr.t25.enb = TRUE; /* t25 - waiting to traffic resatrt allowed message for ANSI */ - cfg.t.cfg.s.snRout.tmr.t25.val = k->t25; - cfg.t.cfg.s.snRout.tmr.t26.enb = TRUE; /* t26 - waiting to repeat traffic restart waiting message for ANSI */ - cfg.t.cfg.s.snRout.tmr.t26.val = k->t26; -# endif -#endif -#if (SS7_TTC || SS7_NTT || defined(TDS_ROLL_UPGRADE_SUPPORT)) - cfg.t.cfg.s.snRout.tmr.tc.enb = TRUE; /* tc - Waiting for congestion abatement */ - cfg.t.cfg.s.snRout.tmr.tc.val = k->tc; -#endif -#if (defined(SN_SG) || defined(TDS_ROLL_UPGRADE_SUPPORT)) - cfg.t.cfg.s.snRout.tmr.tQry.enb = TRUE; /* Periodic query timer over the NIF */ - cfg.t.cfg.s.snRout.tmr.tQry.val = k->tqry; -#endif - - return(sng_cfg_mtp3(&pst, &cfg)); -} - -/******************************************************************************/ -int ftmod_ss7_isup_nsap_config(int id) -{ - SiMngmt cfg; - Pst pst; - sng_nsap_t *k = &g_ftdm_sngss7_data.cfg.nsap[id]; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSI; - - /*clear the configuration structure*/ - memset(&cfg, 0x0, sizeof(SiMngmt)); - - /*fill in some general sections of the header*/ - smHdrInit(&cfg.hdr); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTSI; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STNSAP; - - cfg.hdr.elmId.elmntInst1 = k->id; - -#if (SI_LMINT3 || SMSI_LMINT3) - cfg.t.cfg.s.siNSap.nsapId = k->id; /* Id of the NSAP being configured */ -#endif - cfg.t.cfg.s.siNSap.nwId = k->nwId; /* Network Id */ - cfg.t.cfg.s.siNSap.spId = k->spId; /* service providor id */ - cfg.t.cfg.s.siNSap.ssf = k->ssf; /* sub service field */ - cfg.t.cfg.s.siNSap.dstEnt = ENTSN; /* entity */ - cfg.t.cfg.s.siNSap.dstInst = S_INST; /* instance */ - cfg.t.cfg.s.siNSap.prior = PRIOR0; /* priority */ - cfg.t.cfg.s.siNSap.route = RTESPEC; /* route */ - cfg.t.cfg.s.siNSap.dstProcId = SFndProcId(); /* destination processor id */ - cfg.t.cfg.s.siNSap.sapType = SAP_MTP; /* sap type */ - cfg.t.cfg.s.siNSap.selector = 0; /* selector */ - cfg.t.cfg.s.siNSap.tINT.enb = TRUE; /* interface (Bind Confirm) timer */ - cfg.t.cfg.s.siNSap.tINT.val = 50; - cfg.t.cfg.s.siNSap.mem.region = S_REG; /* memory region & pool id */ - cfg.t.cfg.s.siNSap.mem.pool = S_POOL; - -#ifdef TDS_ROLL_UPGRADE_SUPPORT - cfg.t.cfg.s.siNSap.remIntfValid = FALSE; /* remote interface version is valid */ - cfg.t.cfg.s.siNSap.remIntfVer; /* remote interface version */ -#endif - - return(sng_cfg_isup(&pst, &cfg)); -} - -/******************************************************************************/ -int ftmod_ss7_isup_intf_config(int id) -{ - SiMngmt cfg; - Pst pst; - sng_isup_inf_t *k = &g_ftdm_sngss7_data.cfg.isupIntf[id]; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSI; - - /*clear the configuration structure*/ - memset(&cfg, 0x0, sizeof(SiMngmt)); - - /*fill in some general sections of the header*/ - smHdrInit(&cfg.hdr); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTSI; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = SI_STINTF; - - cfg.hdr.elmId.elmntInst1 = k->id; - - cfg.t.cfg.s.siIntfCb.intfId = k->id; /* Interface id */ - cfg.t.cfg.s.siIntfCb.nwId = k->nwId; /* Network Id */ - cfg.t.cfg.s.siIntfCb.sapId = k->isap; /* Id of the Upper ISUP SAP */ - cfg.t.cfg.s.siIntfCb.opc = k->spc; /* physical originating postatic int code */ - cfg.t.cfg.s.siIntfCb.phyDpc = k->dpc; /* physical destination postatic int code */ - cfg.t.cfg.s.siIntfCb.swtch = k->switchType; /* Protocol Switch */ - cfg.t.cfg.s.siIntfCb.ssf = k->ssf; /* subsystem service information */ - cfg.t.cfg.s.siIntfCb.pauseActn = SI_PAUSE_CLRTRAN; /* call clearing behavior upon rx. PAUSE */ - cfg.t.cfg.s.siIntfCb.dpcCbTmr.t4.enb = TRUE; /* t4 timer - user part test sent */ - cfg.t.cfg.s.siIntfCb.dpcCbTmr.t4.val = k->t4; - cfg.t.cfg.s.siIntfCb.dpcCbTmr.tPAUSE.enb = TRUE; /* waiting for PAUSE to be effective */ - cfg.t.cfg.s.siIntfCb.dpcCbTmr.tPAUSE.val = k->tpause; - cfg.t.cfg.s.siIntfCb.dpcCbTmr.tSTAENQ.enb = TRUE; /* status enquiry timer */ - cfg.t.cfg.s.siIntfCb.dpcCbTmr.tSTAENQ.val = k->tstaenq; -#if SS7_ANS95 - cfg.t.cfg.s.siIntfCb.availTest = FALSE; /* circuit validation test */ -#endif -#if (SS7_ITU97 || SS7_ETSIV3 || SS7_UK || SS7_NZL || SS7_ITU2000 || SS7_KZ) - cfg.t.cfg.s.siIntfCb.checkTable = LSI_CHKTBLE_MRATE; /* Validation flag for Table 3 p1/p2 Q.763 */ -#endif -#if (SS7_ANS95 || SS7_ITU97 || SS7_ETSIV3 || SS7_UK || SS7_NZL || SS7_ITU2000 || SS7_KZ) - switch (k->switchType) { - case LSI_SW_TST: - case LSI_SW_ITU: - case LSI_SW_ITU97: - case LSI_SW_ITU2000: - case LSI_SW_ETSI: - case LSI_SW_ETSIV3: - case LSI_SW_RUSSIA: - case LSI_SW_RUSS2000: - case LSI_SW_INDIA: - case LSI_SW_CHINA: - cfg.t.cfg.s.siIntfCb.trunkType = TRUE; /* truck type E1(TRUE)/T1(FALSE) at intf */ - break; - case LSI_SW_ANS88: - case LSI_SW_ANS92: - case LSI_SW_ANS95: - case LSI_SW_BELL: - cfg.t.cfg.s.siIntfCb.trunkType = FALSE; /* truck type E1(TRUE)/T1(FALSE) at intf */ - break; - } - -#endif -#if (LSIV4 || LSIV5) - cfg.t.cfg.s.siIntfCb.lnkSelOpt = LSI_LINSEK_CIC; /* link select option */ -# if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL) - cfg.t.cfg.s.siIntfCb.lnkSelBits = LSI_LNKSEL_8BITS; /* number of bits for link selection */ -# endif -#endif - - return(sng_cfg_isup(&pst, &cfg)); -} - -/******************************************************************************/ -int ftmod_ss7_isup_ckt_config(int id) -{ - SiMngmt cfg; - Pst pst; - U32 tmp_flag; - sng_isup_ckt_t *k = &g_ftdm_sngss7_data.cfg.isupCkt[id]; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSI; - - /* check the for the correct ProcId and make sure it goes to the right system */ - if (g_ftdm_sngss7_data.cfg.procId != 1) { - pst.dstProcId = 1; - } - - /*clear the configuration structure*/ - memset(&cfg, 0x0, sizeof(SiMngmt)); - - /*fill in some general sections of the header*/ - smHdrInit(&cfg.hdr); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTSI; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STICIR; - - cfg.hdr.elmId.elmntInst1 = k->id; - - cfg.t.cfg.s.siCir.cirId = k->id; /* circuit id code */ - cfg.t.cfg.s.siCir.cic = k->cic; /* cic */ - cfg.t.cfg.s.siCir.intfId = k->infId; /* interface id */ - cfg.t.cfg.s.siCir.typeCntrl = k->typeCntrl; /* type of control */ - cfg.t.cfg.s.siCir.contReq = FALSE; /* continuity check required */ -#if (SI_218_COMP || SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL) - cfg.t.cfg.s.siCir.firstCic = 1; /* First cic in the circuit group */ - cfg.t.cfg.s.siCir.numCir = 24; /* Number of circuits in the circuit group */ - cfg.t.cfg.s.siCir.nonSS7Con = TRUE; /* connecting to non SS7 network */ - cfg.t.cfg.s.siCir.outTrkGrpN.length = 0; /* outgoing trunk group number (For EXM) */ - cfg.t.cfg.s.siCir.cvrTrkClli.length = 0; /* Trunk Group number (For CVR validation) */ - cfg.t.cfg.s.siCir.clli.length = 0; /* common language location identifier */ -#endif - cfg.t.cfg.s.siCir.cirTmr.t3.enb = TRUE; /* t3 timer - overload received */ - cfg.t.cfg.s.siCir.cirTmr.t3.val = k->t3; - cfg.t.cfg.s.siCir.cirTmr.t12.enb = TRUE; /* t12 timer - blocking sent */ - cfg.t.cfg.s.siCir.cirTmr.t12.val = k->t12; - cfg.t.cfg.s.siCir.cirTmr.t13.enb = TRUE; /* t13 timer - initial blocking sent */ - cfg.t.cfg.s.siCir.cirTmr.t13.val = k->t13; - cfg.t.cfg.s.siCir.cirTmr.t14.enb = TRUE; /* t14 timer - unblocking sent */ - cfg.t.cfg.s.siCir.cirTmr.t14.val = k->t14; - cfg.t.cfg.s.siCir.cirTmr.t15.enb = TRUE; /* t15 timer - initial unblocking sent */ - cfg.t.cfg.s.siCir.cirTmr.t15.val = k->t15; - cfg.t.cfg.s.siCir.cirTmr.t16.enb = TRUE; /* t16 timer - reset sent */ - cfg.t.cfg.s.siCir.cirTmr.t16.val = k->t16; - cfg.t.cfg.s.siCir.cirTmr.t17.enb = TRUE; /* t17 timer - initial reset sent */ - cfg.t.cfg.s.siCir.cirTmr.t17.val = k->t17; -#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL) - cfg.t.cfg.s.siCir.cirTmr.tVal.enb = TRUE; /* circuit validation timer */ - cfg.t.cfg.s.siCir.cirTmr.tVal.val = k->tval; -#endif -#if (SS7_ANS95 || SS7_ITU97 || SS7_ETSIV3 || SS7_UK) - tmp_flag = 0x0; - /* bit 0 - 4 is the timeslot on the span for this circuit */ - tmp_flag = ( 1 ); - - /* bit 5 -> can this timeslot be used for contigous M-rate call */ - tmp_flag |= !(0x20); - - /* bit 6 -> does this timeslot support contigous M-rate call */ - tmp_flag |= !(0x40); - - cfg.t.cfg.s.siCir.slotId = tmp_flag ; /* physical slot id bit wise flag */ - cfg.t.cfg.s.siCir.ctrlMult = 0; /* Controller for multirate calls */ -#endif - - tmp_flag = 0x0; - /* bit 0 -> ANSI international support or national support */ - tmp_flag = k->ssf; - - /* bit 1 -> confusion message on */ - tmp_flag |= LSI_CIRFLG_CFN_ON; - - /*bit 2-3 -> circuit group carrier information */ - tmp_flag |= LSI_CFCI_ANALDIG; - - /*bit 4-5 -> alarm carrier */ - tmp_flag |= LSI_CFAC_UNKNOWN; - - /*bit 6-7 -> continuity check requirement*/ - tmp_flag |= LSI_CFCO_NONE; - - cfg.t.cfg.s.siCir.cirFlg = tmp_flag; /* Flag indicating diff cfg options for ckt */ - - return(sng_cfg_isup(&pst, &cfg)); -} - -/******************************************************************************/ -int ftmod_ss7_isup_isap_config(int id) -{ - SiMngmt cfg; - Pst pst; - sng_isap_t *k = &g_ftdm_sngss7_data.cfg.isap[id]; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSI; - - /*clear the configuration structure*/ - memset(&cfg, 0x0, sizeof(SiMngmt)); - - /*fill in some general sections of the header*/ - smHdrInit(&cfg.hdr); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTSI; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STISAP; - - cfg.hdr.elmId.elmntInst1 = k->id; - -#if (SI_LMINT3 || SMSI_LMINT3) - cfg.t.cfg.s.siSap.sapId = k->id; /* Id of the SAP being configured */ -#endif - cfg.t.cfg.s.siSap.swtch = k->switchType; /* Protocol Switch */ - cfg.t.cfg.s.siSap.ssf = k->ssf; /* Sub service field */ - cfg.t.cfg.s.siSap.sidIns = FALSE; /* SID insertion Flag */ - cfg.t.cfg.s.siSap.sidVer = FALSE; /* SID verification Flag */ - if ( cfg.t.cfg.s.siSap.sidIns == TRUE ) { /* SID */ - #if 0 - cfg.t.cfg.s.siSap.sid =; - cfg.t.cfg.s.siSap.natAddrInd =; /* SID Nature of Addres Indicator */ - cfg.t.cfg.s.siSap.sidNPlan =; /* SID Numbering Plan */ - cfg.t.cfg.s.siSap.sidPresInd =; /* default presentation indicator */ - cfg.t.cfg.s.siSap.incSidPresRes =; /* Presentation Restriction of incoming SID */ - cfg.t.cfg.s.siSap.sidPresRes =; /* Presentation Restriction */ - #endif - } else { - cfg.t.cfg.s.siSap.sid.length = 0; - /*cfg.t.cfg.s.siSap.sid.strg[0] =*/ - cfg.t.cfg.s.siSap.natAddrInd = ADDR_NOTPRSNT; /* SID Nature of Addres Indicator */ - cfg.t.cfg.s.siSap.sidNPlan = NP_ISDN; /* SID Numbering Plan */ - cfg.t.cfg.s.siSap.sidPresInd = FALSE; /* default presentation indicator */ - cfg.t.cfg.s.siSap.incSidPresRes = FALSE; /* Presentation Restriction of incoming SID */ - cfg.t.cfg.s.siSap.sidPresRes = 0; /* Presentation Restriction */ - } - cfg.t.cfg.s.siSap.reqOpt = FALSE; /* Request option */ - cfg.t.cfg.s.siSap.allCallMod = TRUE; /* call modification allowed flag */ - cfg.t.cfg.s.siSap.maxLenU2U = MAX_SI_USER_2_USER_LEN; /* Max length of user to user messages */ - cfg.t.cfg.s.siSap.passOnFlag = TRUE; /* flag for passing unknown par/msg */ - cfg.t.cfg.s.siSap.relLocation = ILOC_PRIVNETLU; /* release location indicator in cause val */ - cfg.t.cfg.s.siSap.prior = PRIOR0; /* priority */ - cfg.t.cfg.s.siSap.route = RTESPEC; /* route */ - cfg.t.cfg.s.siSap.selector = 0; /* selector */ - cfg.t.cfg.s.siSap.mem.region = S_REG; /* memory region & pool id */ - cfg.t.cfg.s.siSap.mem.pool = S_POOL; /* memory region & pool id */ - - cfg.t.cfg.s.siSap.tmr.t1.enb = TRUE; /* t1 timer - release sent */ - cfg.t.cfg.s.siSap.tmr.t1.val = k->t1; - cfg.t.cfg.s.siSap.tmr.t2.enb = TRUE; /* t2 timer - suspend received */ - cfg.t.cfg.s.siSap.tmr.t2.val = k->t2; - cfg.t.cfg.s.siSap.tmr.t5.enb = TRUE; /* t5 timer - initial release sent */ - cfg.t.cfg.s.siSap.tmr.t5.val = k->t5; - cfg.t.cfg.s.siSap.tmr.t6.enb = TRUE; /* t6 timer - suspend received */ - cfg.t.cfg.s.siSap.tmr.t6.val = k->t6; - cfg.t.cfg.s.siSap.tmr.t7.enb = TRUE; /* t7 timer - latest address sent */ - cfg.t.cfg.s.siSap.tmr.t7.val = k->t7; - cfg.t.cfg.s.siSap.tmr.t8.enb = TRUE; /* t8 timer - initial address received */ - cfg.t.cfg.s.siSap.tmr.t8.val = k->t8; - cfg.t.cfg.s.siSap.tmr.t9.enb = TRUE; /* t9 timer - latest address sent after ACM */ - cfg.t.cfg.s.siSap.tmr.t9.val = k->t9; - cfg.t.cfg.s.siSap.tmr.t27.enb = TRUE; /* t27 timer - wait. for continuity recheck */ - cfg.t.cfg.s.siSap.tmr.t27.val = k->t27; - cfg.t.cfg.s.siSap.tmr.t31.enb = TRUE; /* t31 timer - call reference frozen period */ - cfg.t.cfg.s.siSap.tmr.t31.val = k->t31; - cfg.t.cfg.s.siSap.tmr.t33.enb = TRUE; /* t33 timer - INR sent */ - cfg.t.cfg.s.siSap.tmr.t33.val = k->t33; - cfg.t.cfg.s.siSap.tmr.t34.enb = TRUE; /* t34 timer - wait. for continuity after recheck */ - cfg.t.cfg.s.siSap.tmr.t34.val = k->t34; - cfg.t.cfg.s.siSap.tmr.t36.enb = TRUE; /* waiting SGM */ - cfg.t.cfg.s.siSap.tmr.t36.val = k->t36; - cfg.t.cfg.s.siSap.tmr.tCCR.enb = TRUE; /* tCCR timer - continuity recheck timer */ - cfg.t.cfg.s.siSap.tmr.tCCR.val = k->tccr; - cfg.t.cfg.s.siSap.tmr.tRELRSP.enb = TRUE; /* waiting for release response */ - cfg.t.cfg.s.siSap.tmr.tRELRSP.val = k->trelrsp; - cfg.t.cfg.s.siSap.tmr.tFNLRELRSP.enb = TRUE; /* waiting for final release response */ - cfg.t.cfg.s.siSap.tmr.tFNLRELRSP.val = k->tfnlrelrsp; -#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL) - cfg.t.cfg.s.siSap.tmr.tEx.enb = TRUE; /* tEx timer - Exit to be sent */ - cfg.t.cfg.s.siSap.tmr.tEx.val = k->tex; - cfg.t.cfg.s.siSap.tmr.tCCRt.enb = TRUE; /* tCCR timer (o/g side) - continuity recheck timer */ - cfg.t.cfg.s.siSap.tmr.tCCRt.val = k->tccrt; -#endif -#if (SS7_ANS92 || SS7_ANS95 || SS7_BELL) - cfg.t.cfg.s.siSap.tmr.tCRM.enb = TRUE; /* circuit reservation message timer */ - cfg.t.cfg.s.siSap.tmr.tCRM.val = k->tcrm; - cfg.t.cfg.s.siSap.tmr.tCRA.enb = TRUE; /* circuit reservation ack. timer */ - cfg.t.cfg.s.siSap.tmr.tCRA.val = k->tcra; -#endif -#if (SS7_ETSI || SS7_ITU97 || SS7_ETSIV3 || SS7_UK || SS7_NZL || SS7_KZ) - cfg.t.cfg.s.siSap.tmr.tECT.enb = TRUE; /* Explicit Call Transfer - waiting for loop prvnt rsp */ - cfg.t.cfg.s.siSap.tmr.tECT.val = k->tect; -#endif - -#ifdef TDS_ROLL_UPGRADE_SUPPORT - cfg.t.cfg.s.siSap.remIntfValid = FALSE; /* remote interface version is valid */ - cfg.t.cfg.s.siSap.remIntfVer =; /* remote interface version */ -#endif - - return(sng_cfg_isup(&pst, &cfg)); -} - -/******************************************************************************/ -int ftmod_ss7_cc_isap_config(int dstProcId) -{ - CcMngmt cfg; - Pst pst; - - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTCC; - - /*clear the configuration structure*/ - memset(&cfg, 0x0, sizeof(CcMngmt)); - - /*fill in some general sections of the header*/ - smHdrInit(&cfg.hdr); - - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTCC; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STISAP; - - cfg.hdr.elmId.elmntInst1 = 1; - - cfg.t.cfg.s.ccISAP.suId = 1; - cfg.t.cfg.s.ccISAP.spId = 1; - cfg.t.cfg.s.ccISAP.pst.dstProcId = dstProcId; - cfg.t.cfg.s.ccISAP.pst.dstEnt = ENTSI; - cfg.t.cfg.s.ccISAP.pst.dstInst = S_INST; - cfg.t.cfg.s.ccISAP.pst.srcProcId = SFndProcId(); - cfg.t.cfg.s.ccISAP.pst.srcEnt = ENTCC; - cfg.t.cfg.s.ccISAP.pst.srcInst = S_INST; - cfg.t.cfg.s.ccISAP.pst.prior = PRIOR0; - cfg.t.cfg.s.ccISAP.pst.route = RTESPEC; - cfg.t.cfg.s.ccISAP.pst.region = S_REG; - cfg.t.cfg.s.ccISAP.pst.pool = S_POOL; - cfg.t.cfg.s.ccISAP.pst.selector = 0; - - return(sng_cfg_cc(&pst, &cfg)); -} - -/******************************************************************************/ -int ftmod_ss7_relay_chan_config(int id) -{ - RyMngmt cfg; /*configuration structure*/ - Pst pst; /*post structure*/ - sng_relay_t *k = &g_ftdm_sngss7_data.cfg.relay[id]; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTRY; - - /* clear the configuration structure */ - memset(&cfg, 0x0, sizeof(RyMngmt)); - - /* fill in some general sections of the header */ - smHdrInit(&cfg.hdr); - - /*fill in the specific fields of the header */ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTRY; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STCHCFG; - - cfg.hdr.elmId.elmntInst1 = k->id; - - cfg.t.cfg.s.ryChanCfg.id = k->id; /* channel id */ - cfg.t.cfg.s.ryChanCfg.type = k->type; /* channel type */ -/* cfg.t.cfg.s.ryChanCfg.msInd =;*/ /* master/slave indicator */ - if (k->type == LRY_CT_TCP_LISTEN) { - cfg.t.cfg.s.ryChanCfg.low = 0; /* low proc id for channel */ - cfg.t.cfg.s.ryChanCfg.high = 0; /* high proc id for channel */ - } else { - cfg.t.cfg.s.ryChanCfg.low = k->procId; /* low proc id for channel */ - cfg.t.cfg.s.ryChanCfg.high = k->procId; /* high proc id for channel */ - } - cfg.t.cfg.s.ryChanCfg.nmbScanQ = MAX_RELAY_NMBSCAN; /* number of times to scan the queue */ - cfg.t.cfg.s.ryChanCfg.flags = LRY_FLG_INTR; /* flags */ - cfg.t.cfg.s.ryChanCfg.congThrsh = MAX_RELAY_CONGTHRSH; /* congestion threshold */ - cfg.t.cfg.s.ryChanCfg.dropThrsh = 0; /* drop threshold */ - cfg.t.cfg.s.ryChanCfg.contThrsh = MAX_RELAY_CONGTHRSH + 1; /* continue threshold */ - cfg.t.cfg.s.ryChanCfg.kaTxTmr.enb = 1; /* keep alive transmit timer config */ - cfg.t.cfg.s.ryChanCfg.kaTxTmr.val = RY_TX_KP_ALIVE_TMR; - cfg.t.cfg.s.ryChanCfg.kaRxTmr.enb = 1; /* keep alive receive timer config */ - cfg.t.cfg.s.ryChanCfg.kaRxTmr.val = RY_RX_KP_ALIVE_TMR; - cfg.t.cfg.s.ryChanCfg.btTmr.enb = 1; /* boot timer */ - cfg.t.cfg.s.ryChanCfg.btTmr.val = RY_BT_TMR; - cfg.t.cfg.s.ryChanCfg.region = S_REG; /* Relay region */ - cfg.t.cfg.s.ryChanCfg.pool = S_POOL; /* Relay pool */ -#if (RY_ENBUDPSOCK || RY_ENBTCPSOCK) - cfg.t.cfg.s.ryChanCfg.listenPortNo = k->port; /* Listen Port of Rx Relay Channel*/ - strncpy(cfg.t.cfg.s.ryChanCfg.transmittoHostName, k->hostname, (size_t)RY_REMHOSTNAME_SIZE); - cfg.t.cfg.s.ryChanCfg.transmittoPortNo = k->port; /* TransmitTo PortId for Tx Relay Channel */ - cfg.t.cfg.s.ryChanCfg.targetProcId = k->procId; /* procId of the node present in the other end of this channel */ -# ifdef LRY1 - cfg.t.cfg.s.ryChanCfg.sockParam =; /* Socket Parameters */ -# endif /* LRY1 */ -# ifdef LRYV2 - cfg.t.cfg.s.ryChanCfg.selfHostName[RY_REMHOSTNAME_SIZE]; -# endif /* LRY2 */ -#endif /* RY_ENBUDPSOCK || RY_ENBTCPSOCK */ - - return(sng_cfg_relay(&pst, &cfg)); -} - -/******************************************************************************/ -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c deleted file mode 100644 index 98a2398630..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c +++ /dev/null @@ -1,4007 +0,0 @@ -/* - * Copyright (c) 2009|Konrad Hammel - * All rights reserved. - * - * Redistribution and use in source and binary forms|with or without - * modification|are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice|this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice|this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT - * LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL, - * EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Contributors: - * James Zhang - * - */ - -#if 0 -#define SMG_RELAY_DBG -#endif - -/* INCLUDE ********************************************************************/ -#include "ftmod_sangoma_ss7_main.h" -/******************************************************************************/ - -/* DEFINES ********************************************************************/ -/******************************************************************************/ - -/* GLOBALS ********************************************************************/ -/******************************************************************************/ - -/* PROTOTYPES *****************************************************************/ -ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const char *data); - -static ftdm_status_t handle_print_usage(ftdm_stream_handle_t *stream); - -static ftdm_status_t handle_show_procId(ftdm_stream_handle_t *stream); - -static ftdm_status_t handle_set_function_trace(ftdm_stream_handle_t *stream, int on, int level); -static ftdm_status_t handle_set_message_trace(ftdm_stream_handle_t *stream, int on, int level); -static ftdm_status_t handle_set_inhibit(ftdm_stream_handle_t *stream, char *name); -static ftdm_status_t handle_set_uninhibit(ftdm_stream_handle_t *stream, char *name); - -static ftdm_status_t handle_show_free(ftdm_stream_handle_t *stream, int span, int chan, int verbose); -static ftdm_status_t handle_show_inuse(ftdm_stream_handle_t *stream, int span, int chan, int verbose); -static ftdm_status_t handle_show_inreset(ftdm_stream_handle_t *stream, int span, int chan, int verbose); -static ftdm_status_t handle_show_flags(ftdm_stream_handle_t *stream, int span, int chan, int verbose); -static ftdm_status_t handle_show_blocks(ftdm_stream_handle_t *stream, int span, int chan, int verbose); -static ftdm_status_t handle_show_status(ftdm_stream_handle_t *stream, int span, int chan, int verbose); - -static ftdm_status_t handle_tx_rsc(ftdm_stream_handle_t *stream, int span, int chan, int verbose); -static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose); - -static ftdm_status_t handle_tx_blo(ftdm_stream_handle_t *stream, int span, int chan, int verbose); -static ftdm_status_t handle_tx_ubl(ftdm_stream_handle_t *stream, int span, int chan, int verbose); - -static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose); -static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose); - -static ftdm_status_t handle_bind_link(ftdm_stream_handle_t *stream, char *name); -static ftdm_status_t handle_unbind_link(ftdm_stream_handle_t *stream, char *name); -static ftdm_status_t handle_activate_link(ftdm_stream_handle_t *stream, char *name); -static ftdm_status_t handle_deactivate_link(ftdm_stream_handle_t *stream, char *name); - -static ftdm_status_t handle_activate_linkset(ftdm_stream_handle_t *stream, char *name); -static ftdm_status_t handle_deactivate_linkset(ftdm_stream_handle_t *stream, char *name); - -static ftdm_status_t handle_tx_lpo(ftdm_stream_handle_t *stream, char *name); -static ftdm_status_t handle_tx_lpr(ftdm_stream_handle_t *stream, char *name); - -static ftdm_status_t handle_status_mtp3link(ftdm_stream_handle_t *stream, char *name); -static ftdm_status_t handle_status_mtp2link(ftdm_stream_handle_t *stream, char *name); -static ftdm_status_t handle_status_linkset(ftdm_stream_handle_t *stream, char *name); -static ftdm_status_t handle_status_relay(ftdm_stream_handle_t *stream, char *name); -static ftdm_status_t handle_status_isup_ckt(ftdm_stream_handle_t *stream, char *id_name); - -static ftdm_status_t extract_span_chan(char *argv[10], int pos, int *span, int *chan); -static ftdm_status_t check_arg_count(int args, int min); - - - -static ftdm_status_t cli_ss7_show_general(ftdm_stream_handle_t *stream); - -static ftdm_status_t cli_ss7_show_mtp2link_by_id(ftdm_stream_handle_t *stream, int rcId); -static ftdm_status_t cli_ss7_show_mtp2link_by_name(ftdm_stream_handle_t *stream, char *name); -static ftdm_status_t cli_ss7_show_all_mtp2link(ftdm_stream_handle_t *stream); - -static ftdm_status_t cli_ss7_show_mtp3link_by_id(ftdm_stream_handle_t *stream, int rcId); -static ftdm_status_t cli_ss7_show_mtp3link_by_name(ftdm_stream_handle_t *stream, char *name); -static ftdm_status_t cli_ss7_show_all_mtp3link(ftdm_stream_handle_t *stream); - -static ftdm_status_t cli_ss7_show_relay_by_id(ftdm_stream_handle_t *stream, int rcId); -static ftdm_status_t cli_ss7_show_relay_by_name(ftdm_stream_handle_t *stream, char *name); -static ftdm_status_t cli_ss7_show_all_relay(ftdm_stream_handle_t *stream); - -static ftdm_status_t cli_ss7_show_channel_detail_of_span(ftdm_stream_handle_t *stream, char *span_id, char *chan_id); -static ftdm_status_t cli_ss7_show_all_channels_of_span(ftdm_stream_handle_t *stream, char *span_id); - -static ftdm_status_t cli_ss7_show_span_by_id(ftdm_stream_handle_t *stream, char *span_id); -static ftdm_status_t cli_ss7_show_all_spans_general(ftdm_stream_handle_t *stream); -static ftdm_status_t cli_ss7_show_all_spans_detail(ftdm_stream_handle_t *stream); -static ftdm_status_t handle_show_sctp_profiles(ftdm_stream_handle_t *stream); -static ftdm_status_t handle_show_sctp_profile(ftdm_stream_handle_t *stream, char* sctp_profile_name); -static ftdm_status_t handle_show_m2ua_profiles(ftdm_stream_handle_t *stream); -static ftdm_status_t handle_show_m2ua_profile(ftdm_stream_handle_t *stream, char* m2ua_profile_name); -static ftdm_status_t handle_show_m2ua_peer_status(ftdm_stream_handle_t *stream, char* m2ua_profile_name); -static ftdm_status_t handle_show_m2ua_cluster_status(ftdm_stream_handle_t *stream, char* m2ua_profile_name); -static ftdm_status_t handle_show_nif_profiles(ftdm_stream_handle_t *stream); -static ftdm_status_t handle_show_nif_profile(ftdm_stream_handle_t *stream, char* profile_name); -int get_assoc_resp_buf(char* buf,SbMgmt* cfm); - -/******************************************************************************/ -/* FUNCTIONS ******************************************************************/ -ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const char *data) -{ - char *mycmd = NULL; - char *argv[10] = { 0 }; - int argc = 0; - int span = 0; - int chan = 0; - int range = 0; - int trace = 0; - int trace_level = 7; - int verbose = 1; - int c = 0; - - if (data) { - mycmd = ftdm_strdup(data); - argc = ftdm_separate_string(mycmd, ' ', argv, ftdm_array_len(argv)); - } - - if (check_arg_count(argc, 1)) { - goto handle_cli_error_argc; - } - - if (!strcasecmp(argv[c], "show")) { - /**************************************************************************/ - if (check_arg_count(argc, 2)) { - cli_ss7_show_general(stream); - return FTDM_SUCCESS; - } - c++; - - if (!strcasecmp(argv[c], "relay")) { - /**********************************************************************/ - c++; - handle_status_relay(stream, argv[c]); - - } else if (!strcasecmp(argv[c], "span")) { - /**********************************************************************/ - switch (argc) { - case 2: - { - /* > ftdm ss7 show span */ - cli_ss7_show_all_spans_general(stream); - } - break; - - case 3: - { - if (!strcasecmp(argv[2], "all")) { - /* > ftdm ss7 show span all */ - cli_ss7_show_all_spans_detail(stream); - } else { - /* > ftdm ss7 show span 1 */ - cli_ss7_show_span_by_id(stream, argv[2]); - } - } - break; - - case 4: - { - /* > ftdm ss7 show span 1 chan */ - cli_ss7_show_all_channels_of_span(stream, argv[2]); - } - break; - - case 5: - default: - { - if (!strcasecmp(argv[3], "chan")) { - /* > ftdm ss7 show span 1 chan 2 */ - cli_ss7_show_channel_detail_of_span(stream, argv[2], argv[4]); - } else { - /* > ftdm ss7 show span 1 bla bla bla*/ - cli_ss7_show_all_channels_of_span(stream, argv[2]); - } - } - break; - } - } else if (!strcasecmp(argv[c], "status")) { - /**********************************************************************/ - if (check_arg_count(argc, 3)) { - cli_ss7_show_general(stream); - return FTDM_SUCCESS; - } - - c++; - - if (!strcasecmp(argv[c], "mtp3")) { - /******************************************************************/ - c++; - handle_status_mtp3link(stream, argv[c]); - /******************************************************************/ - } else if (!strcasecmp(argv[c], "mtp2")) { - /******************************************************************/ - c++; - handle_status_mtp2link(stream, argv[c]); - /******************************************************************/ - } else if (!strcasecmp(argv[c], "linkset")) { - /******************************************************************/ - c++; - handle_status_linkset(stream, argv[c]); - /******************************************************************/ - } else if (!strcasecmp(argv[c], "relay")) { - /******************************************************************/ - c++; - handle_status_relay(stream, argv[c]); - /******************************************************************/ - } else if (!strcasecmp(argv[c], "span")) { - /******************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - - handle_show_status(stream, span, chan, verbose); - /******************************************************************/ - } else if (!strcasecmp(argv[c], "isup")) { - /******************************************************************/ - if (check_arg_count(argc, 4)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "ckt")) { - /**************************************************************/ - if (check_arg_count(argc, 5)) goto handle_cli_error_argc; - c++; - - handle_status_isup_ckt(stream, argv[c]); - /**************************************************************/ - } else { - /**************************************************************/ - stream->write_function(stream, "Unknown \"status isup\" command\n"); - goto handle_cli_error; - /**************************************************************/ - } - /******************************************************************/ - } else { - /******************************************************************/ - stream->write_function(stream, "Unknown \"status\" command\n"); - goto handle_cli_error; - /******************************************************************/ - } - /**********************************************************************/ - } else if (!strcasecmp(argv[c], "inuse")) { - /**********************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "span")) { - /******************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - - handle_show_inuse(stream, span, chan, verbose); - /******************************************************************/ - } else { - /******************************************************************/ - stream->write_function(stream, "Unknown \"inuse\" command\n"); - goto handle_cli_error; - /******************************************************************/ - } - /**********************************************************************/ - } else if (!strcasecmp(argv[c], "inreset")) { - /**********************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "span")) { - /******************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - - handle_show_inreset(stream, span, chan, verbose); - /******************************************************************/ - } else { - /******************************************************************/ - stream->write_function(stream, "Unknown \"inreset\" command\n"); - goto handle_cli_error; - /******************************************************************/ - } - /**********************************************************************/ - } else if (!strcasecmp(argv[c], "free")) { - /**********************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "span")) { - /******************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - - handle_show_free(stream, span, chan, verbose); - /******************************************************************/ - } else { - /******************************************************************/ - stream->write_function(stream, "Unknown \"free\" command\n"); - goto handle_cli_error; - /******************************************************************/ - } - /**********************************************************************/ - } else if (!strcasecmp(argv[c], "blocks")) { - /**********************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "span")) { - /******************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - - handle_show_blocks(stream, span, chan, verbose); - /******************************************************************/ - } else { - /******************************************************************/ - stream->write_function(stream, "Unknown \"blocks\" command\n"); - goto handle_cli_error; - /******************************************************************/ - } - /**********************************************************************/ - } else if (!strcasecmp(argv[c], "flags")) { - /**********************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "span")) { - /******************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - - handle_show_flags(stream, span, chan, verbose); - /******************************************************************/ - } else { - /******************************************************************/ - stream->write_function(stream, "Unknown \"flags\" command\n"); - goto handle_cli_error; - /******************************************************************/ - } - /**********************************************************************/ - } else if (!strcasecmp(argv[c], "mem")) { - /**********************************************************************/ - sng_isup_reg_info_show(); - /**********************************************************************/ - } else if (!strcasecmp(argv[c], "stats")) { - /**********************************************************************/ -/* sng_mtp1_sts_t sts; - - memset(&sts, 0x0, sizeof(sng_mtp1_sts_t)); - - sng_mtp1_sts(1, &sts); - - stream->write_function(stream,"MTP1 tx stats:|tx_frm=%d|tx_err=%d|tx_fisu=%d|tx_lssu=%d|tx_msu=%d|\n", - sts.tx_frm, sts.tx_err, sts.tx_fisu, sts.tx_lssu, sts.tx_msu); - stream->write_function(stream,"MTP1 rx stats:|rx_frm=%d|rx_err=%d|rx_fisu=%d|rx_lssu=%d|rx_msu=%d|\n", - sts.rx_frm, sts.rx_err, sts.rx_fisu, sts.rx_lssu, sts.rx_msu); -*/ - /**********************************************************************/ - } else if (!strcasecmp(argv[c], "procid")) { - /**********************************************************************/ - handle_show_procId(stream); - - /**********************************************************************/ - } else{ - /**********************************************************************/ - stream->write_function(stream, "Unknown \"show\" command\n"); - goto handle_cli_error; - } - /**************************************************************************/ - } else if (!strcasecmp(argv[c], "xmlshow")) { - /**************************************************************************/ - - if (check_arg_count(argc, 2)) { - stream->write_function(stream, "Unknown \"xmlshow\" command\n"); - goto handle_cli_error; - } - c++; - /**************************************************************************/ - if (!strcasecmp(argv[c], "m2ua")) { - /**************************************************************************/ - switch(argc) - { - case 2: /* show m2ua */ - { - handle_show_m2ua_profiles(stream); - break; - } - case 3: /* show m2ua */ - { - c++; - handle_show_m2ua_profile(stream, argv[c]); - break; - } - case 4: - { - char* profile_name = argv[++c]; - c++; - /***************************************************************/ - if(!strcasecmp(argv[c],"peerstatus")){ - /***************************************************************/ - handle_show_m2ua_peer_status(stream, profile_name); - /***************************************************************/ - }else if(!strcasecmp(argv[c],"clusterstatus")){ - /***************************************************************/ - handle_show_m2ua_cluster_status(stream, profile_name); - /***************************************************************/ - } else{ - /***************************************************************/ - stream->write_function(stream, "Unknown \"show m2ua \" command..\n"); - goto handle_cli_error_argc; - } - break; - } - default: - goto handle_cli_error_argc; - } - - /**********************************************************************/ - } else if (!strcasecmp(argv[c], "nif")) { - /**********************************************************************/ - if (check_arg_count(argc, 3)){ - handle_show_nif_profiles(stream); - }else{ - c++; - handle_show_nif_profile(stream, argv[c]); - } - /**********************************************************************/ - } else if (!strcasecmp(argv[c], "sctp")) { - /**********************************************************************/ - if (check_arg_count(argc, 3)){ - handle_show_sctp_profiles(stream); - }else{ - c++; - handle_show_sctp_profile(stream, argv[c]); - } - /**********************************************************************/ - } else { - /**********************************************************************/ - stream->write_function(stream, "Unknown \"xmlshow\" command\n"); - goto handle_cli_error; - } - /**********************************************************************/ - } else if (!strcasecmp(argv[c], "set")) { - /**************************************************************************/ - if (check_arg_count(argc, 4)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "ftrace")) { - /**********************************************************************/ - c++; - trace = atoi(argv[c]); - c++; - trace_level = atoi(argv[c]); - c++; - handle_set_function_trace(stream, trace, trace_level); - /**********************************************************************/ - } else if (!strcasecmp(argv[c], "mtrace")) { - /**********************************************************************/ - c++; - trace = atoi(argv[c]); - c++; - trace_level = atoi(argv[c]); - c++; - handle_set_message_trace(stream, trace, trace_level); - /**********************************************************************/ - } else { - /**********************************************************************/ - stream->write_function(stream, "Unknown \"set\" command\n"); - goto handle_cli_error; - /**********************************************************************/ - } - /**************************************************************************/ - } else if (!strcasecmp(argv[c], "inhibit")) { - /**************************************************************************/ - if (check_arg_count(argc, 2)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "link")) { - /**********************************************************************/ - if (check_arg_count(argc, 3)) goto handle_cli_error_argc; - c++; - - handle_set_inhibit(stream, argv[c]); - /**********************************************************************/ - } else { - /**********************************************************************/ - stream->write_function(stream, "Unknown \"block\" command\n"); - goto handle_cli_error; - /**********************************************************************/ - } - /**************************************************************************/ - } else if (!strcasecmp(argv[c], "uninhibit")) { - /**************************************************************************/ - if (check_arg_count(argc, 2)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "link")) { - /**********************************************************************/ - if (check_arg_count(argc, 3)) goto handle_cli_error_argc; - c++; - - handle_set_uninhibit(stream, argv[c]); - /**********************************************************************/ - } else { - /**********************************************************************/ - stream->write_function(stream, "Unknown \"unblock\" command\n"); - goto handle_cli_error; - /**********************************************************************/ - } - /**************************************************************************/ - } else if (!strcasecmp(argv[c], "blo")) { - if (check_arg_count(argc, 2)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "span")) { - /**********************************************************************/ - if (check_arg_count(argc, 5)) goto handle_cli_error_argc; - - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - - handle_tx_blo(stream, span, chan, verbose); - /**********************************************************************/ - } else { - /**********************************************************************/ - stream->write_function(stream, "Unknown \"block\" command\n"); - goto handle_cli_error; - /**********************************************************************/ - } - /**************************************************************************/ - } else if (!strcasecmp(argv[c], "ubl")) { - /**************************************************************************/ - if (check_arg_count(argc, 2)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "span")) { - /**********************************************************************/ - if (check_arg_count(argc, 5)) goto handle_cli_error_argc; - - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - - handle_tx_ubl(stream, span, chan, verbose); - /**********************************************************************/ - } else { - /**********************************************************************/ - stream->write_function(stream, "Unknown \"ubl\" command\n"); - goto handle_cli_error; - /**********************************************************************/ - } - /**************************************************************************/ - } else if (!strcasecmp(argv[c], "cgb")) { - /**************************************************************************/ - if (check_arg_count(argc, 2)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "span")) { - /**********************************************************************/ - if (check_arg_count(argc, 5)) goto handle_cli_error_argc; - - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - c = c + 4; - - if (check_arg_count(argc, 7)) goto handle_cli_error_argc; - - if (!strcasecmp(argv[c], "range")) { - /******************************************************************/ - c++; - range = atoi(argv[c]); - /******************************************************************/ - } else { - /******************************************************************/ - stream->write_function(stream, "Unknown \"cgb range\" command\n"); - goto handle_cli_error; - /******************************************************************/ - } - - handle_tx_cgb(stream, span, chan, range, verbose); - /**********************************************************************/ - } else { - /**********************************************************************/ - stream->write_function(stream, "Unknown \"cgb\" command\n"); - goto handle_cli_error; - /**********************************************************************/ - } - /**************************************************************************/ - } else if (!strcasecmp(argv[c], "cgu")) { - /**************************************************************************/ - if (check_arg_count(argc, 2)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "span")) { - /**********************************************************************/ - if (check_arg_count(argc, 5)) goto handle_cli_error_argc; - - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - c = c + 4; - - if (check_arg_count(argc, 7)) goto handle_cli_error_argc; - - if (!strcasecmp(argv[c], "range")) { - /******************************************************************/ - c++; - range = atoi(argv[c]); - /******************************************************************/ - } else { - /******************************************************************/ - stream->write_function(stream, "Unknown \"cgu range\" command\n"); - goto handle_cli_error; - /******************************************************************/ - } - - handle_tx_cgu(stream, span, chan, range, verbose); - /**********************************************************************/ - } else { - /**********************************************************************/ - stream->write_function(stream, "Unknown \"cgu\" command\n"); - goto handle_cli_error; - /**********************************************************************/ - } - /**************************************************************************/ - } else if (!strcasecmp(argv[c], "rsc")) { - /**************************************************************************/ - if (check_arg_count(argc, 2)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "span")) { - /**********************************************************************/ - if (check_arg_count(argc, 5)) goto handle_cli_error_argc; - - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - - handle_tx_rsc(stream, span, chan, verbose); - /**********************************************************************/ - } else { - /**********************************************************************/ - stream->write_function(stream, "Unknown \"rsc\" command\n"); - goto handle_cli_error; - /**********************************************************************/ - } - /**************************************************************************/ - } else if (!strcasecmp(argv[c], "grs")) { - /**************************************************************************/ - if (check_arg_count(argc, 2)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "span")) { - /**********************************************************************/ - if (check_arg_count(argc, 5)) goto handle_cli_error_argc; - - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - c = c + 4; - - if (check_arg_count(argc, 7)) goto handle_cli_error_argc; - - if (!strcasecmp(argv[c], "range")) { - /******************************************************************/ - c++; - range = atoi(argv[c]); - /******************************************************************/ - } else { - /******************************************************************/ - stream->write_function(stream, "Unknown \"grs range\" command\n"); - goto handle_cli_error; - /******************************************************************/ - } - - handle_tx_grs(stream, span, chan, range, verbose); - /**********************************************************************/ - } else { - /**********************************************************************/ - stream->write_function(stream, "Unknown \"grs\" command\n"); - goto handle_cli_error; - /**********************************************************************/ - } - /**************************************************************************/ - } else if (!strcasecmp(argv[c], "lpo")) { - /**************************************************************************/ - if (check_arg_count(argc, 2)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "link")) { - /**********************************************************************/ - if (check_arg_count(argc, 3)) goto handle_cli_error_argc; - c++; - - handle_tx_lpo(stream, argv[c]); - /**********************************************************************/ - } else { - /**********************************************************************/ - stream->write_function(stream, "Unknown \"lpo\" command\n"); - goto handle_cli_error; - /**********************************************************************/ - } - /**************************************************************************/ - } else if (!strcasecmp(argv[c], "lpr")) { - /**************************************************************************/ - if (check_arg_count(argc, 2)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "link")) { - /**********************************************************************/ - if (check_arg_count(argc, 3)) goto handle_cli_error_argc; - c++; - - handle_tx_lpr(stream, argv[c]); - /**********************************************************************/ - } else { - /**********************************************************************/ - stream->write_function(stream, "Unknown \"lpr\" command\n"); - goto handle_cli_error; - /**********************************************************************/ - } - /**************************************************************************/ - } else if (!strcasecmp(argv[c], "bind")) { - /**************************************************************************/ - if (check_arg_count(argc, 2)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "link")) { - /**********************************************************************/ - if (check_arg_count(argc, 3)) goto handle_cli_error_argc; - c++; - - handle_bind_link(stream, argv[c]); - /**********************************************************************/ - } else { - /**********************************************************************/ - stream->write_function(stream, "Unknown \"bind\" command\n"); - goto handle_cli_error; - /**********************************************************************/ - } - /**************************************************************************/ - } else if (!strcasecmp(argv[c], "unbind")) { - /**************************************************************************/ - if (check_arg_count(argc, 2)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "link")) { - /**********************************************************************/ - if (check_arg_count(argc, 3)) goto handle_cli_error_argc; - c++; - - handle_unbind_link(stream, argv[c]); - /**********************************************************************/ - } else { - /**********************************************************************/ - stream->write_function(stream, "Unknown \"bind\" command\n"); - goto handle_cli_error; - /**********************************************************************/ - } - /**************************************************************************/ - } else if (!strcasecmp(argv[c], "activate")) { - /**************************************************************************/ - if (check_arg_count(argc, 2)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "link")) { - /**********************************************************************/ - if (check_arg_count(argc, 3)) goto handle_cli_error_argc; - c++; - - handle_activate_link(stream, argv[c]); - /**********************************************************************/ - }else if (!strcasecmp(argv[c], "linkset")) { - /**********************************************************************/ - if (check_arg_count(argc, 3)) goto handle_cli_error_argc; - c++; - - handle_activate_linkset(stream, argv[c]); - /**********************************************************************/ - } else { - /**********************************************************************/ - stream->write_function(stream, "Unknown \"activate\" command\n"); - goto handle_cli_error; - /**********************************************************************/ - } - /**************************************************************************/ - } else if (!strcasecmp(argv[c], "deactivate")) { - /**************************************************************************/ - if (check_arg_count(argc, 2)) goto handle_cli_error_argc; - c++; - - if (!strcasecmp(argv[c], "link")) { - /**********************************************************************/ - if (check_arg_count(argc, 3)) goto handle_cli_error_argc; - c++; - - handle_deactivate_link(stream, argv[c]); - /**********************************************************************/ - }else if (!strcasecmp(argv[c], "linkset")) { - /**********************************************************************/ - if (check_arg_count(argc, 3)) goto handle_cli_error_argc; - c++; - - handle_deactivate_linkset(stream, argv[c]); - /**********************************************************************/ - } else { - /**********************************************************************/ - stream->write_function(stream, "Unknown \"deactivate\" command\n"); - goto handle_cli_error; - /**********************************************************************/ - } - /**************************************************************************/ - } else if (!strcasecmp(argv[c], "m2ua")) { - /**************************************************************************/ - if (check_arg_count(argc, 3)) { - stream->write_function(stream, "Invalid \"m2ua option\", please use \"m2ua logging [enable|disable] \n"); - goto handle_cli_error_argc; - } - c++; - if(!strcasecmp(argv[c],"logging")){ - c++; - if(!strcasecmp(argv[c],"enable")){ - ftmod_ss7_enable_m2ua_sg_logging(); - }else if(!strcasecmp(argv[c],"disable")){ - ftmod_ss7_disable_m2ua_sg_logging(); - } else{ - stream->write_function(stream, "Unknown \"m2ua logging %s option\", supported values enable/disable\n",argv[c]); - goto handle_cli_error_argc; - } - }else{ - stream->write_function(stream, "Unknown \"m2ua %s option\", supported values \"logging\"\n",argv[c]); - goto handle_cli_error_argc; - } - /**************************************************************************/ - } else { - /**************************************************************************/ - goto handle_cli_error; - /**************************************************************************/ - } - - return FTDM_SUCCESS; - -handle_cli_error_argc: - stream->write_function(stream, "Invalid # of arguments in command\n"); - handle_print_usage(stream); - return FTDM_SUCCESS; - -handle_cli_error_span_chan: - stream->write_function(stream, "Unknown \"span\\chan\" command\n"); - handle_print_usage(stream); - return FTDM_SUCCESS; - -handle_cli_error: - stream->write_function(stream, "Unknown command requested\n"); - handle_print_usage(stream); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_print_usage(ftdm_stream_handle_t *stream) -{ - stream->write_function(stream, "Sangoma SS7 CLI usage:\n\n"); - - stream->write_function(stream, "ftmod_sangoma_ss7 general control:\n"); - stream->write_function(stream, "ftdm ss7 set ftrace X Y\n"); - stream->write_function(stream, "ftdm ss7 set mtrace X Y\n"); - stream->write_function(stream, "\n"); - - stream->write_function(stream, "ftmod_sangoma_ss7 signaling information:\n"); - stream->write_function(stream, "ftdm ss7 show \n"); - stream->write_function(stream, "ftdm ss7 show status mtp2 X\n"); - stream->write_function(stream, "ftdm ss7 show status mtp3 X\n"); - stream->write_function(stream, "ftdm ss7 show status linkset X\n"); - stream->write_function(stream, "\n"); - - stream->write_function(stream, "ftmod_sangoma_ss7 circuit information:\n"); - stream->write_function(stream, "ftdm ss7 show span all\n"); - stream->write_function(stream, "ftdm ss7 show span X\n"); - stream->write_function(stream, "ftdm ss7 show status span X chan Y\n"); - stream->write_function(stream, "ftdm ss7 show free span X chan Y\n"); - stream->write_function(stream, "ftdm ss7 show blocks span X chan Y\n"); - stream->write_function(stream, "ftdm ss7 show inuse span X chan Y\n"); - stream->write_function(stream, "ftdm ss7 show inreset span X chan Y\n"); - stream->write_function(stream, "\n"); - - stream->write_function(stream, "ftmod_sangoma_ss7 circuit control:\n"); - stream->write_function(stream, "ftdm ss7 blo span X chan Y\n"); - stream->write_function(stream, "ftdm ss7 ubl span X chan Y\n"); - stream->write_function(stream, "ftdm ss7 rsc span X chan Y\n"); - stream->write_function(stream, "ftdm ss7 grs span X chan Y range Z\n"); - stream->write_function(stream, "ftdm ss7 cgb span X chan Y range Z\n"); - stream->write_function(stream, "ftdm ss7 cgu span X chan Y range Z\n"); - stream->write_function(stream, "\n"); - - stream->write_function(stream, "ftmod_sangoma_ss7 link control:\n"); - /* - stream->write_function(stream, "ftdm ss7 inhibit link X\n"); - stream->write_function(stream, "ftdm ss7 uninhibit link X\n"); - */ - stream->write_function(stream, "ftdm ss7 activate link X\n"); - stream->write_function(stream, "ftdm ss7 deactivate link X\n"); - stream->write_function(stream, "ftdm ss7 activate linkset X\n"); - stream->write_function(stream, "ftdm ss7 deactivate linkset X\n"); - stream->write_function(stream, "ftdm ss7 lpo link X\n"); - stream->write_function(stream, "ftdm ss7 lpr link X\n"); - stream->write_function(stream, "\n"); - - - stream->write_function(stream, "ftmod_sangoma_ss7 Relay status:\n"); - stream->write_function(stream, "ftdm ss7 show status relay X\n"); - stream->write_function(stream, "ftdm ss7 show relay X\n"); - stream->write_function(stream, "ftdm ss7 show relay\n"); - stream->write_function(stream, "\n"); - - stream->write_function(stream, "ftmod_sangoma_ss7 M2UA :\n"); - stream->write_function(stream, "ftdm ss7 xmlshow sctp \n"); - stream->write_function(stream, "ftdm ss7 xmlshow sctp \n"); - stream->write_function(stream, "ftdm ss7 xmlshow m2ua \n"); - stream->write_function(stream, "ftdm ss7 xmlshow m2ua \n"); - stream->write_function(stream, "ftdm ss7 xmlshow m2ua peerstatus\n"); - stream->write_function(stream, "ftdm ss7 xmlshow m2ua clusterstatus\n"); - stream->write_function(stream, "ftdm ss7 xmlshow nif \n"); - stream->write_function(stream, "ftdm ss7 xmlshow nif \n"); - stream->write_function(stream, "\n"); - - - stream->write_function(stream, "ftmod_sangoma_ss7 M2UA logging:\n"); - stream->write_function(stream, "ftdm ss7 m2ua logging [enable|disable] \n"); - - stream->write_function(stream, "\n"); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_show_procId(ftdm_stream_handle_t *stream) -{ - int procId = sng_get_procId(); - - stream->write_function(stream, "Local ProcId = %d\n", procId); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_set_function_trace(ftdm_stream_handle_t *stream, int on, int level) -{ - stream->write_function(stream, "ftmod_sangoma_ss7 Function Trace was %s, level = %d\n", - (g_ftdm_sngss7_data.function_trace == 1) ? "ON" : "OFF", - g_ftdm_sngss7_data.function_trace_level); - - g_ftdm_sngss7_data.function_trace = on; - g_ftdm_sngss7_data.function_trace_level = level; - - stream->write_function(stream, "ftmod_sangoma_ss7 Function Trace now is %s, level = %d\n", - (g_ftdm_sngss7_data.function_trace == 1) ? "ON" : "OFF", - g_ftdm_sngss7_data.function_trace_level); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_set_message_trace(ftdm_stream_handle_t *stream, int on, int level) -{ - stream->write_function(stream, "ftmod_sangoma_ss7 Message Trace was %s, level = %d\n", - (g_ftdm_sngss7_data.message_trace == 1) ? "ON" : "OFF", - g_ftdm_sngss7_data.message_trace_level); - - g_ftdm_sngss7_data.message_trace = on; - g_ftdm_sngss7_data.message_trace_level = level; - - stream->write_function(stream, "ftmod_sangoma_ss7 Message Trace now is %s, level = %d\n", - (g_ftdm_sngss7_data.message_trace == 1) ? "ON" : "OFF", - g_ftdm_sngss7_data.message_trace_level); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_show_free(ftdm_stream_handle_t *stream, int span, int chan, int verbose) -{ - int x; - int free; - sngss7_chan_data_t *ss7_info; - ftdm_channel_t *ftdmchan; - int lspan; - int lchan; - - x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - free = 0; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - ftdmchan = ss7_info->ftdmchan; - - /* if span == 0 then all spans should be printed */ - if (span == 0) { - lspan = ftdmchan->physical_span_id; - } else { - lspan = span; - } - - /* if chan == 0 then all chans should be printed */ - if (chan == 0) { - lchan = ftdmchan->physical_chan_id; - } else { - lchan = chan; - } - - if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { - switch (ftdmchan->state) { - /******************************************************************/ - case (FTDM_CHANNEL_STATE_DOWN): - if (verbose) { - stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|state=%s\n", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id, - ss7_info->circuit->cic, - ftdm_channel_state2str(ftdmchan->state)); - } /* if (verbose) */ - - /*increment the count of circuits in reset */ - free++; - break; - /******************************************************************/ - default: - break; - /******************************************************************/ - } /* switch (ftdmchan->state) */ - } /* if ( span and chan) */ - } /* if ( cic != 0) */ - - /* go the next circuit */ - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ - - stream->write_function(stream, "\nTotal # of CICs free = %d\n",free); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_show_inuse(ftdm_stream_handle_t *stream, int span, int chan, int verbose) -{ - int x; - int in_use; - sngss7_chan_data_t *ss7_info; - ftdm_channel_t *ftdmchan; - int lspan; - int lchan; - - x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - in_use = 0; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - ftdmchan = ss7_info->ftdmchan; - - /* if span == 0 then all spans should be printed */ - if (span == 0) { - lspan = ftdmchan->physical_span_id; - } else { - lspan = span; - } - - /* if chan == 0 then all chans should be printed */ - if (chan == 0) { - lchan = ftdmchan->physical_chan_id; - } else { - lchan = chan; - } - - if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { - switch (ftdmchan->state) { - /******************************************************************/ - case (FTDM_CHANNEL_STATE_COLLECT): - case (FTDM_CHANNEL_STATE_RING): - case (FTDM_CHANNEL_STATE_DIALING): - case (FTDM_CHANNEL_STATE_PROGRESS): - case (FTDM_CHANNEL_STATE_PROGRESS_MEDIA): - case (FTDM_CHANNEL_STATE_UP): - case (FTDM_CHANNEL_STATE_TERMINATING): - case (FTDM_CHANNEL_STATE_HANGUP): - if (verbose) { - stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|state=%s\n", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id, - ss7_info->circuit->cic, - ftdm_channel_state2str(ftdmchan->state)); - } /* if (verbose) */ - - /*increment the count of circuits in reset */ - in_use++; - break; - /******************************************************************/ - default: - break; - /******************************************************************/ - } /* switch (ftdmchan->state) */ - } /* if ( span and chan) */ - } /* if ( cic != 0) */ - - /* go the next circuit */ - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ - - stream->write_function(stream, "\nTotal # of CICs in use = %d\n",in_use); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_show_inreset(ftdm_stream_handle_t *stream, int span, int chan, int verbose) -{ - int x; - int in_reset; - sngss7_chan_data_t *ss7_info; - ftdm_channel_t *ftdmchan; - int lspan; - int lchan; - - x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - in_reset = 0; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - ftdmchan = ss7_info->ftdmchan; - - /* if span == 0 then all spans should be printed */ - if (span == 0) { - lspan = ftdmchan->physical_span_id; - } else { - lspan = span; - } - - /* if chan == 0 then all chans should be printed */ - if (chan == 0) { - lchan = ftdmchan->physical_chan_id; - } else { - lchan = chan; - } - - if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { - if ((sngss7_test_ckt_flag(ss7_info, FLAG_RESET_RX)) || - (sngss7_test_ckt_flag(ss7_info, FLAG_RESET_TX)) || - (sngss7_test_ckt_flag(ss7_info, FLAG_GRP_RESET_RX)) || - (sngss7_test_ckt_flag(ss7_info, FLAG_GRP_RESET_TX))) { - - if (verbose) { - stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|in_reset=Y\n", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id, - ss7_info->circuit->cic); - } /* if (verbose) */ - - /*increment the count of circuits in reset */ - in_reset++; - } /* if ((sngss7_test_ckt_flag(ss7_info, FLAG_RESET_RX) ... */ - } /* if ( span and chan) */ - } /* if ( cic != 0) */ - - /* go the next circuit */ - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ - - stream->write_function(stream, "\nTotal # of CICs in reset = %d\n",in_reset); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_show_flags(ftdm_stream_handle_t *stream, int span, int chan, int verbose) -{ - sngss7_chan_data_t *ss7_info; - ftdm_channel_t *ftdmchan; - int x; - int bit; - int lspan; - int lchan; - const char *text; - int flag; - - x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - ftdmchan = ss7_info->ftdmchan; - - /* if span == 0 then all spans should be printed */ - if (span == 0) { - lspan = ftdmchan->physical_span_id; - } else { - lspan = span; - } - - /* if chan == 0 then all chans should be printed */ - if (chan == 0) { - lchan = ftdmchan->physical_chan_id; - } else { - lchan = chan; - } - - if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { - stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id, - ss7_info->circuit->cic); - - for (bit = 0; bit < 33; bit++) { - if (ss7_info->ckt_flags & ( 0x1 << bit)) { - stream->write_function(stream, "|"); - flag = bit; - text = ftmod_ss7_ckt_flag2str(flag); - stream->write_function(stream, "%s",text); - } - } - - for (bit = 0; bit < 33; bit++) { - if (ss7_info->blk_flags & ( 0x1 << bit)) { - stream->write_function(stream, "|"); - flag = bit; - text = ftmod_ss7_blk_flag2str(flag); - stream->write_function(stream, "%s",text); - } - } - - stream->write_function(stream, "\n"); - } /* if ( span and chan) */ - - } /* if ( cic != 0) */ - - /* go the next circuit */ - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_show_blocks(ftdm_stream_handle_t *stream, int span, int chan, int verbose) -{ - int x; - sngss7_chan_data_t *ss7_info; - ftdm_channel_t *ftdmchan; - int lspan; - int lchan; - - x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - ftdmchan = ss7_info->ftdmchan; - - /* if span == 0 then all spans should be printed */ - if (span == 0) { - lspan = ftdmchan->physical_span_id; - } else { - lspan = span; - } - - /* if chan == 0 then all chans should be printed */ - if (chan == 0) { - lchan = ftdmchan->physical_chan_id; - } else { - lchan = chan; - } - - if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { - stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id, - ss7_info->circuit->cic); - - if((sngss7_test_ckt_blk_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || (sngss7_test_ckt_blk_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) { - stream->write_function(stream, "l_mn=Y|"); - }else { - stream->write_function(stream, "l_mn=N|"); - } - - if((sngss7_test_ckt_blk_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || (sngss7_test_ckt_blk_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) { - stream->write_function(stream, "r_mn=Y|"); - }else { - stream->write_function(stream, "r_mn=N|"); - } - - if(sngss7_test_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) { - stream->write_function(stream, "l_hw=Y|"); - }else { - stream->write_function(stream, "l_hw=N|"); - } - - if(sngss7_test_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) { - stream->write_function(stream, "r_hw=Y|"); - }else { - stream->write_function(stream, "r_hw=N|"); - } - - if(sngss7_test_ckt_blk_flag(ss7_info, FLAG_CKT_LC_BLOCK_RX)) { - stream->write_function(stream, "l_mngmt=Y|"); - }else { - stream->write_function(stream, "l_mngmt=N|"); - } - - if(sngss7_test_ckt_blk_flag(ss7_info, FLAG_CKT_UCIC_BLOCK)) { - stream->write_function(stream, "l_ucic=Y|"); - }else { - stream->write_function(stream, "l_ucic=N|"); - } - -#ifdef SMG_RELAY_DBG - stream->write_function(stream," blk_flag=%x | ckt_flag=%x | chan_flag=%x", ss7_info->blk_flags, ss7_info->ckt_flags, ftdmchan->flags); -#endif - stream->write_function(stream, "\n"); - } /* if ( span and chan) */ - - } /* if ( cic != 0) */ - - /* go the next circuit */ - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_show_status(ftdm_stream_handle_t *stream, int span, int chan, int verbose) -{ - int x; - sngss7_chan_data_t *ss7_info; - ftdm_channel_t *ftdmchan; - int lspan; - int lchan; - ftdm_signaling_status_t sigstatus = FTDM_SIG_STATE_DOWN; - sng_isup_ckt_t *ckt; - - x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - /* extract the circuit to make it easier to work with */ - ckt = &g_ftdm_sngss7_data.cfg.isupCkt[x]; - - /* if span == 0 then all spans should be printed */ - if (span == 0) { - lspan = ckt->span; - } else { - lspan = span; - } - - /* if chan == 0 then all chans should be printed */ - if (chan == 0) { - lchan = ckt->chan; - } else { - lchan = chan; - } - - /* check if this circuit is one of the circuits we're interested in */ - if ((ckt->span == lspan) && (ckt->chan == lchan)) { - if (ckt->type == SNG_CKT_HOLE) { - stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|NOT USED\n", - ckt->span, - ckt->chan, - ckt->cic); - } else if (ckt->type == SNG_CKT_SIG) { - stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|SIGNALING LINK\n", - ckt->span, - ckt->chan, - ckt->cic); - } else { - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - ftdmchan = ss7_info->ftdmchan; - - if (ftdmchan == NULL) { - /* this should never happen!!! */ - stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|FTDMCHAN DOES NOT EXISTS", - ckt->span, - ckt->chan, - ckt->cic); - - } else { - /* grab the signaling_status */ - ftdm_channel_get_sig_status(ftdmchan, &sigstatus); - - stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|ckt=%4d|sig_status=%4s|state=%s|", - ckt->span, - ckt->chan, - ckt->cic, - ckt->id, - ftdm_signaling_status2str(sigstatus), - ftdm_channel_state2str(ftdmchan->state)); - - if ((sngss7_test_ckt_blk_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || - (sngss7_test_ckt_blk_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX)) || - (sngss7_test_ckt_blk_flag(ss7_info, FLAG_CKT_LC_BLOCK_RX))) { - stream->write_function(stream, "l_mn=Y|"); - }else { - stream->write_function(stream, "l_mn=N|"); - } - - if ((sngss7_test_ckt_blk_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || - (sngss7_test_ckt_blk_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) { - stream->write_function(stream, "r_mn=Y|"); - }else { - stream->write_function(stream, "r_mn=N|"); - } - - if (sngss7_test_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) { - stream->write_function(stream, "l_hw=Y|"); - }else { - stream->write_function(stream, "l_hw=N|"); - } - - if (sngss7_test_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) { - stream->write_function(stream, "r_hw=Y|"); - }else { - stream->write_function(stream, "r_hw=N|"); - } - - - if (g_ftdm_sngss7_data.cfg.procId != 1) { - /* if (sngss7_test_ckt_blk_flag(ss7_info, FLAG_RELAY_DOWN)) { */ - stream->write_function(stream, "relay=Y|"); - }else { - stream->write_function(stream, "relay=N"); - } - -#ifdef SMG_RELAY_DBG - stream->write_function(stream, "| flag=0x%llx", ftdmchan->flags); -#endif - } - -#ifdef SMG_RELAY_DBG - stream->write_function(stream," | blk_flag=%x | ckt_flag=%x", ss7_info->blk_flags, ss7_info->ckt_flags); -#endif - stream->write_function(stream, "\n"); - } /* if ( hole, sig, voice) */ - } /* if ( span and chan) */ - /* go the next circuit */ - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ - - /* Look spans that are being used by M2UA SG links */ - for (x = 1; x < ftdm_array_len(g_ftdm_sngss7_data.cfg.g_m2ua_cfg.nif); x++) { - if (g_ftdm_sngss7_data.cfg.g_m2ua_cfg.nif[x].id) { - if (g_ftdm_sngss7_data.cfg.mtp2Link[g_ftdm_sngss7_data.cfg.g_m2ua_cfg.nif[x].mtp2LnkNmb].id) { - uint32_t mtp1_id = g_ftdm_sngss7_data.cfg.mtp2Link[g_ftdm_sngss7_data.cfg.g_m2ua_cfg.nif[x].mtp2LnkNmb].id; - if (g_ftdm_sngss7_data.cfg.mtp1Link[mtp1_id].id) { - if (g_ftdm_sngss7_data.cfg.mtp1Link[mtp1_id].span == span) { - if (chan) { - if (chan == g_ftdm_sngss7_data.cfg.mtp1Link[mtp1_id].chan) { - stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|SIGNALING LINK\n", - g_ftdm_sngss7_data.cfg.mtp1Link[mtp1_id].span, - g_ftdm_sngss7_data.cfg.mtp1Link[mtp1_id].chan, - 0); - } - } else { - stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|SIGNALING LINK\n", - g_ftdm_sngss7_data.cfg.mtp1Link[mtp1_id].span, - g_ftdm_sngss7_data.cfg.mtp1Link[mtp1_id].chan, - 0); - } - } - } - - } - } - } - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_tx_blo(ftdm_stream_handle_t *stream, int span, int chan, int verbose) -{ - int x; - sngss7_chan_data_t *ss7_info; - ftdm_channel_t *ftdmchan; - int lspan; - int lchan; - - x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - ftdmchan = ss7_info->ftdmchan; - - /* if span == 0 then all spans should be printed */ - if (span == 0) { - lspan = ftdmchan->physical_span_id; - } else { - lspan = span; - } - - /* if chan == 0 then all chans should be printed */ - if (chan == 0) { - lchan = ftdmchan->physical_chan_id; - } else { - lchan = chan; - } - - if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change|give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", ss7_info->circuit->cic); - ftdm_assert(0, "State change not completed\n"); - ftdm_mutex_unlock(ftdmchan->mutex); - continue; - } else { - sngss7_set_ckt_blk_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - } - - ftdm_mutex_unlock(ftdmchan->mutex); - } - - } - - x++; - } - - handle_show_blocks(stream, span, chan, verbose); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_tx_ubl(ftdm_stream_handle_t *stream, int span, int chan, int verbose) -{ - int x; - sngss7_chan_data_t *ss7_info; - ftdm_channel_t *ftdmchan; - int lspan; - int lchan; - - x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - ftdmchan = ss7_info->ftdmchan; - - /* if span == 0 then all spans should be printed */ - if (span == 0) { - lspan = ftdmchan->physical_span_id; - } else { - lspan = span; - } - - /* if chan == 0 then all chans should be printed */ - if (chan == 0) { - lchan = ftdmchan->physical_chan_id; - } else { - lchan = chan; - } - - if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change|give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", ss7_info->circuit->cic); - ftdm_assert(0, "State change not completed\n"); - ftdm_mutex_unlock(ftdmchan->mutex); - continue; - } else { - sngss7_set_ckt_blk_flag(ss7_info, FLAG_CKT_MN_UNBLK_TX); - sngss7_clear_ckt_blk_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX); - sngss7_clear_ckt_blk_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX); - - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - } - - ftdm_mutex_unlock(ftdmchan->mutex); - - } - - } - - /* go the next circuit */ - x++; - } - - handle_show_blocks(stream, span, chan, verbose); - - return FTDM_SUCCESS; -} - - -/******************************************************************************/ -static ftdm_status_t handle_status_mtp3link(ftdm_stream_handle_t *stream, char *name) -{ - SS7_RELAY_DBG_FUN(handle_status_mtp3link); - - ftdm_assert_return(stream != NULL, FTDM_FAIL, "Invalid stream\n"); - - if (!name) { - return cli_ss7_show_all_mtp3link(stream); - } - - return cli_ss7_show_mtp3link_by_name(stream, name); -} - - -/******************************************************************************/ -static ftdm_status_t handle_status_mtp2link(ftdm_stream_handle_t *stream, char *name) -{ - SS7_RELAY_DBG_FUN(handle_status_mtp2link); - - ftdm_assert_return(stream != NULL, FTDM_FAIL, "Invalid stream\n"); - - if (!name) { - return cli_ss7_show_all_mtp2link(stream); - } - - return cli_ss7_show_mtp2link_by_name(stream, name); -} - -/******************************************************************************/ -static ftdm_status_t handle_status_linkset(ftdm_stream_handle_t *stream, char *name) -{ - int x = 0; - SnMngmt sta; - - /* find the linkset request by it's name */ - x = 1; - while(x < (MAX_MTP_LINKSETS+1)) { - if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name, name)) { - - /* send the status request */ - if (ftmod_ss7_mtplinkSet_sta(x, &sta)) { - stream->write_function(stream, "Failed to read linkset=%s status\n", name); - return FTDM_FAIL; - } - - /* print the results */ - stream->write_function(stream, "%s|state=%s|nmbActLnk=%d\n", - name, - DECODE_LSN_LINKSET_STATUS(sta.t.ssta.s.snLnkSet.state), - sta.t.ssta.s.snLnkSet.nmbActLnks); - - goto success; - } - - /* move to the next linkset */ - x++; - } /* while (id != 0) */ - - stream->write_function(stream, "Failed to find link=\"%s\"\n", name); - -success: - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_set_inhibit(ftdm_stream_handle_t *stream, char *name) -{ - int x = 0; - - /* find the link request by it's name */ - x = 1; - while(x < (MAX_MTP_LINKS+1)) { - if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) { - - /* send the inhibit request */ - if (ftmod_ss7_inhibit_mtp3link(x)) { - stream->write_function(stream, "Failed to inhibit link=%s\n", name); - return FTDM_FAIL; - } - - /* print the new status of the link */ - handle_status_mtp3link(stream, &name[0]); - - goto success; - } - - /* move to the next linkset */ - x++; - } /* while (x < (MAX_MTP_LINKS+1)) */ - - stream->write_function(stream, "Failed to find link=\"%s\"\n", name); - -success: - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_set_uninhibit(ftdm_stream_handle_t *stream, char *name) -{ - int x = 0; - - /* find the link request by it's name */ - x = 1; - while(x < (MAX_MTP_LINKS+1)) { - if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) { - - /* send the uninhibit request */ - if (ftmod_ss7_uninhibit_mtp3link(x)) { - stream->write_function(stream, "Failed to uninhibit link=%s\n", name); - return FTDM_FAIL; - } - - /* print the new status of the link */ - handle_status_mtp3link(stream, &name[0]); - - goto success; - } - - /* move to the next linkset */ - x++; - } /* while (x < (MAX_MTP_LINKS+1)) */ - - stream->write_function(stream, "Failed to find link=\"%s\"\n", name); - -success: - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_tx_rsc(ftdm_stream_handle_t *stream, int span, int chan, int verbose) -{ - int x; - sngss7_chan_data_t *sngss7_info; - ftdm_channel_t *ftdmchan; - int lspan; - int lchan; - - x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - ftdmchan = sngss7_info->ftdmchan; - - /* if span == 0 then all spans should be printed */ - if (span == 0) { - lspan = ftdmchan->physical_span_id; - } else { - lspan = span; - } - - /* if chan == 0 then all chans should be printed */ - if (chan == 0) { - lchan = ftdmchan->physical_chan_id; - } else { - lchan = chan; - } - - if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* throw the reset flag */ - sngss7_set_ckt_flag (sngss7_info, FLAG_LOCAL_REL); - sngss7_clear_ckt_flag (sngss7_info, FLAG_REMOTE_REL); - sngss7_tx_reset_restart(sngss7_info); - - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_RESTART: - /* go to idle so that we can redo the restart state*/ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE); - break; - /**************************************************************************/ - default: - /* set the state of the channel to restart...the rest is done by the chan monitor */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - break; - /**************************************************************************/ - } - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - } /* if ( span and chan) */ - - } /* if ( cic == voice) */ - - /* go the next circuit */ - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ - - /* print the status of channels */ - handle_show_status(stream, span, chan, verbose); - - - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose) -{ - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_span_data_t *sngss7_span = NULL; - int x = 0; - int basefound = 0; - - if (range > 31) { - stream->write_function(stream, "Range value %d is too big for a GRS", range); - return FTDM_SUCCESS; - } - - if (range < 2) { - stream->write_function(stream, "Range value %d is too small for a GRS", range); - return FTDM_SUCCESS; - } - - x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - - sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - ftdmchan = sngss7_info->ftdmchan; - sngss7_span = ftdmchan->span->signal_data; - - if ((ftdmchan->physical_span_id == span) && - ((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) { - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_channel_lock(ftdmchan); - - /* if another reset is still in progress, skip this channel */ - if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX)) { - ftdm_channel_unlock(ftdmchan); - continue; - } - - /* check if there is a pending state change|give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_channel_unlock(ftdmchan); - continue; - } - - /* throw the grp reset flag */ - sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX); - if (!basefound) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Setting channel as GRS base\n"); - sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_BASE); - sngss7_info->tx_grs.circuit = sngss7_info->circuit->id; - sngss7_info->tx_grs.range = range - 1; - basefound = 1; - } - - /* set the channel to restart state */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - - ftdm_channel_unlock(ftdmchan); - - } - - } - - /* go the next circuit */ - x++; - } - - x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - - sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - ftdmchan = sngss7_info->ftdmchan; - sngss7_span = ftdmchan->span->signal_data; - - if ((ftdmchan->physical_span_id == span) && - ((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) { - - handle_show_status(stream, span, chan, verbose); - } - } /* if ( cic == voice) */ - - /* go the next circuit */ - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose) -{ - int x; - sngss7_chan_data_t *sngss7_info; - ftdm_channel_t *ftdmchan; - ftdm_channel_t *main_chan = NULL; - sngss7_span_data_t *sngss7_span; - int byte = 0; - int bit = 0; - ftdm_sigmsg_t sigev; - - memset (&sigev, 0, sizeof (sigev)); - - - if (range <= 1 || range > 31) { - stream->write_function(stream, "Invalid range value %d. Range value must be greater than 1 and less than 31. \n", range); - return FTDM_SUCCESS; - } - - x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - - /* extract the channel and span info for this circuit */ - sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - ftdmchan = sngss7_info->ftdmchan; - sngss7_span = ftdmchan->span->signal_data; - - /* check if this circuit is part of the block */ - if ((ftdmchan->physical_span_id == span) && - ((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) { - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_channel_lock(ftdmchan); - - /* throw the grp maint. block flag */ - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX); - - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* bring the sig status down */ - sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN); - - /* if this is the first channel in the range */ - if (!main_chan) { - /* attach the cgb information */ - main_chan = ftdmchan; - sngss7_span->tx_cgb.circuit = sngss7_info->circuit->id; - sngss7_span->tx_cgb.range = 0; - sngss7_span->tx_cgb.type = 0; /* maintenace block */ - } else { - ((sngss7_span_data_t*)(main_chan->span->signal_data))->tx_cgb.range++; - } - - /* update the status field */ - sngss7_span->tx_cgb.status[byte] = (sngss7_span->tx_cgb.status[byte] | (1 << bit)); - - /* update the bit and byte counter*/ - bit ++; - if (bit == 8) { - byte++; - bit = 0; - } - - /* unlock the channel again before we exit */ - ftdm_channel_unlock(ftdmchan); - } - } - /* go the next circuit */ - x++; - } - - if (!main_chan) { - stream->write_function(stream, "Failed to find a voice cic in span %d chan %d range %d", span, chan, range); - return FTDM_SUCCESS; - } - - /* send the circuit group block */ - ft_to_sngss7_cgb(main_chan); - - x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - - sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - ftdmchan = sngss7_info->ftdmchan; - sngss7_span = ftdmchan->span->signal_data; - - if ((ftdmchan->physical_span_id == span) && - ((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) { - - handle_show_status(stream, ftdmchan->physical_span_id, ftdmchan->physical_chan_id, verbose); - } - } /* if ( cic == voice) */ - - /* go the next circuit */ - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ - - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose) -{ - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - ftdm_channel_t *main_chan = NULL; - sngss7_span_data_t *sngss7_span = NULL; - sngss7_chan_data_t *ubl_sng_info[MAX_CIC_MAP_LENGTH+1]; - int x = 0; - int byte = 0; - int bit = 0; - int ubl_sng_info_idx = 1; - ftdm_sigmsg_t sigev; - - memset(ubl_sng_info, 0, sizeof(ubl_sng_info)); - memset (&sigev, 0, sizeof (sigev)); - - if (range <= 1 || range > 31) { - stream->write_function(stream, "Invalid range value %d. Range value must be greater than 1 and less than 31.\n", range); - return FTDM_SUCCESS; - } - - /* verify that there is not hardware block in the range. - * if there is any channel within the group unblock range, do not execute the group unblock */ - x = (g_ftdm_sngss7_data.cfg.procId * MAX_CIC_MAP_LENGTH) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - ftdmchan = sngss7_info->ftdmchan; - sngss7_span = ftdmchan->span->signal_data; - - if ( (ftdmchan->physical_span_id == span) - && (ftdmchan->physical_chan_id >= chan) - && (ftdmchan->physical_chan_id < (chan+range)) - && sngss7_test_ckt_blk_flag(sngss7_info, (FLAG_GRP_HW_BLOCK_TX | FLAG_GRP_HW_BLOCK_TX_DN)) - ) { - stream->write_function(stream, "There is at least one channel with hardware block. Group unblock operation not allowed at this time.\n"); - return FTDM_SUCCESS; - } - } - x++; - } - - - x = (g_ftdm_sngss7_data.cfg.procId * MAX_CIC_MAP_LENGTH) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - - /* extract the channel and span info for this circuit */ - sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - ftdmchan = sngss7_info->ftdmchan; - sngss7_span = ftdmchan->span->signal_data; - - /* check if this circuit is part of the block */ - if ((ftdmchan->physical_span_id == span) && - ((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) { - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_channel_lock(ftdmchan); - - /* throw the grp maint. block flag */ - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX); - - if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX_DN)) { - ubl_sng_info[ubl_sng_info_idx] = sngss7_info; - ubl_sng_info_idx++; - } - - /* bring the sig status up */ - sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* if this is the first channel in the range */ - if (!main_chan) { - /* attach the cgb information */ - main_chan = ftdmchan; - sngss7_span->tx_cgu.circuit = sngss7_info->circuit->id; - sngss7_span->tx_cgu.range = 0; - sngss7_span->tx_cgu.type = 0; /* maintenace block */ - } else { - ((sngss7_span_data_t*)(main_chan->span->signal_data))->tx_cgu.range++; - } - - /* update the status field */ - sngss7_span->tx_cgu.status[byte] = (sngss7_span->tx_cgu.status[byte] | (1 << bit)); - - /* update the bit and byte counter*/ - bit ++; - if (bit == 8) { - byte++; - bit = 0; - } - - /* unlock the channel again before we exit */ - ftdm_channel_unlock(ftdmchan); - } - } - /* go the next circuit */ - x++; - } - - if (!main_chan) { - stream->write_function(stream, "Failed to find a voice cic in span %d chan %d range %d", span, chan, range); - return FTDM_SUCCESS; - } - - /* send the circuit group block */ - ft_to_sngss7_cgu(main_chan); - - /* clearing blocking flags */ - for (x = 1; ubl_sng_info[x]; x++) { - sngss7_info = ubl_sng_info[x]; - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX_DN); - } - - x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - - sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - ftdmchan = sngss7_info->ftdmchan; - sngss7_span = ftdmchan->span->signal_data; - - if ((ftdmchan->physical_span_id == span) && - ((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) { - - handle_show_status(stream, ftdmchan->physical_span_id, ftdmchan->physical_chan_id, verbose); - - } - } /* if ( cic == voice) */ - - /* go the next circuit */ - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ - - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_bind_link(ftdm_stream_handle_t *stream, char *name) -{ - int x = 0; - - /* find the link request by it's name */ - x = 1; - while(x < (MAX_MTP_LINKS+1)) { - if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) { - - /* send the uninhibit request */ - if (ftmod_ss7_bind_mtp3link(g_ftdm_sngss7_data.cfg.mtp3Link[x].mtp2Id)) { - stream->write_function(stream, "Failed to bind link=%s\n", name); - return FTDM_FAIL; - } - - /* print the new status of the link */ - handle_status_mtp3link(stream, &name[0]); - goto success; - } - - /* move to the next link */ - x++; - } /* while (x < (MAX_MTP_LINKS+1)) */ - - stream->write_function(stream, "Could not find link=%s\n", name); - -success: - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_unbind_link(ftdm_stream_handle_t *stream, char *name) -{ - int x = 0; - - /* find the link request by it's name */ - x = 1; - while(x < (MAX_MTP_LINKS+1)) { - if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) { - - /* send the uninhibit request */ - if (ftmod_ss7_unbind_mtp3link(g_ftdm_sngss7_data.cfg.mtp3Link[x].mtp2Id)) { - stream->write_function(stream, "Failed to bind link=%s\n", name); - return FTDM_FAIL; - } - - /* print the new status of the link */ - handle_status_mtp3link(stream, &name[0]); - goto success; - } - - /* move to the next link */ - x++; - } /* while (x < (MAX_MTP_LINKS+1)) */ - - stream->write_function(stream, "Could not find link=%s\n", name); - -success: - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_activate_link(ftdm_stream_handle_t *stream, char *name) -{ - int x = 0; - - /* find the link request by it's name */ - x = 1; - while(x < (MAX_MTP_LINKS+1)) { - if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) { - - /* send the uninhibit request */ - if (ftmod_ss7_activate_mtp3link(x)) { - stream->write_function(stream, "Failed to activate link=%s\n", name); - return FTDM_FAIL; - } - - /* print the new status of the link */ - handle_status_mtp3link(stream, &name[0]); - goto success; - } - - /* move to the next link */ - x++; - } /* while (x < (MAX_MTP_LINKS+1)) */ - - stream->write_function(stream, "Could not find link=%s\n", name); - -success: - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_deactivate_link(ftdm_stream_handle_t *stream, char *name) -{ - int x = 0; - - /* find the link request by it's name */ - x = 1; - while(x < (MAX_MTP_LINKS+1)) { - if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) { - - /* send the deactivate request */ - if (ftmod_ss7_deactivate2_mtp3link(x)) { - stream->write_function(stream, "Failed to deactivate link=%s\n", name); - return FTDM_FAIL; - } - - /* print the new status of the link */ - handle_status_mtp3link(stream, &name[0]); - goto success; - } - - /* move to the next link */ - x++; - } /* while (x < (MAX_MTP_LINKS+1)) */ - - stream->write_function(stream, "Could not find link=%s\n", name); - -success: - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_activate_linkset(ftdm_stream_handle_t *stream, char *name) -{ - int x = 0; - - /* find the linkset request by it's name */ - x = 1; - while(x < (MAX_MTP_LINKSETS+1)) { - if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name, name)) { - - /* send the activate request */ - if (ftmod_ss7_activate_mtplinkSet(x)) { - stream->write_function(stream, "Failed to activate linkset=%s\n", name); - return FTDM_FAIL; - } - - /* print the new status of the linkset */ - handle_status_linkset(stream, &name[0]); - goto success; - } - - /* move to the next linkset */ - x++; - } /* while (id != 0) */ - - stream->write_function(stream, "Could not find linkset=%s\n", name); - -success: - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_deactivate_linkset(ftdm_stream_handle_t *stream, char *name) -{ - int x = 0; - - /* find the linkset request by it's name */ - x = 1; - while(x < (MAX_MTP_LINKSETS+1)) { - if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name, name)) { - - /* send the deactivate request */ - if (ftmod_ss7_deactivate2_mtplinkSet(x)) { - stream->write_function(stream, "Failed to deactivate linkset=%s\n", name); - return FTDM_FAIL; - } - - /* print the new status of the linkset */ - handle_status_linkset(stream, &name[0]); - goto success; - } - - /* move to the next linkset */ - x++; - } /* while (id != 0) */ - - stream->write_function(stream, "Could not find linkset=%s\n", name); - -success: - return FTDM_SUCCESS; -} - -/******************************************************************************/ - -static ftdm_status_t handle_tx_lpo(ftdm_stream_handle_t *stream, char *name) -{ - int x = 0; - - /* find the link request by it's name */ - x = 1; - while(x < (MAX_MTP_LINKS+1)) { - if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) { - - /* send the uninhibit request */ - if (ftmod_ss7_lpo_mtp3link(x)) { - stream->write_function(stream, "Failed set LPO link=%s\n", name); - return FTDM_FAIL; - } - - /* print the new status of the link */ - handle_status_mtp3link(stream, &name[0]); - goto success; - } - - /* move to the next link */ - x++; - } /* while (x < (MAX_MTP_LINKS+1)) */ - - stream->write_function(stream, "Could not find link=%s\n", name); - -success: - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_tx_lpr(ftdm_stream_handle_t *stream, char *name) -{ - int x = 0; - - /* find the link request by it's name */ - x = 1; - while(x < (MAX_MTP_LINKS+1)) { - if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) { - - /* send the uninhibit request */ - if (ftmod_ss7_lpr_mtp3link(x)) { - stream->write_function(stream, "Failed set LPR link=%s\n", name); - return FTDM_FAIL; - } - - /* print the new status of the link */ - handle_status_mtp3link(stream, &name[0]); - goto success; - } - - /* move to the next link */ - x++; - } /* while (x < (MAX_MTP_LINKS+1)) */ - - stream->write_function(stream, "Could not find link=%s\n", name); - -success: - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_status_relay(ftdm_stream_handle_t *stream, char *name) -{ - SS7_RELAY_DBG_FUN(handle_status_relay); - if (!name) { - return cli_ss7_show_all_relay(stream); - } - return cli_ss7_show_relay_by_name(stream, name); -} - -/******************************************************************************/ -static ftdm_status_t handle_status_isup_ckt(ftdm_stream_handle_t *stream, char *id_name) -{ - sng_isup_ckt_t *ckt; - sngss7_chan_data_t *ss7_info; - ftdm_channel_t *ftdmchan; - uint32_t id; - uint8_t state = 0; - uint8_t bits_ab = 0; - uint8_t bits_cd = 0; - uint8_t bits_ef = 0; - - /* extract the integer version of the id (ckt) */ - id = atoi(id_name); - - /* extract the global config circuit structure */ - ckt = &g_ftdm_sngss7_data.cfg.isupCkt[id]; - - /* confirm the ckt exists */ - if (ckt->id == 0) { - stream->write_function(stream, "Requested ckt does not exist (%d)\n", id); - return FTDM_FAIL; - } - - /* confirm the ckt is a voice channel */ - if (ckt->type != SNG_CKT_VOICE) { - stream->write_function(stream, "Requested ckt is a sig link/hole and can not be queried (%d)\n", id); - return FTDM_FAIL; - } - - /* extract the global structure */ - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[id].obj; - ftdmchan = ss7_info->ftdmchan; - - /* query the isup stack for the state of the ckt */ - if (ftmod_ss7_isup_ckt_sta(ckt->id, &state)) { - stream->write_function(stream, "Failed to read isup ckt =%d status\n", id); - return FTDM_FAIL; - } - - - stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|ckt=%4d|state=0x%02X|", - ckt->span, - ckt->chan, - ckt->cic, - ckt->id, - state); - - /* extract the bit sections */ - bits_ab = (state & (SNG_BIT_A + SNG_BIT_B)) >> 0; - - bits_cd = (state & (SNG_BIT_C + SNG_BIT_D)) >> 2; - - bits_ef = (state & (SNG_BIT_E + SNG_BIT_F)) >> 4; - - /* check bits C and D */ - switch (bits_cd) { - /**************************************************************************/ - case (0): - /* ckt is either un-equipped or transient, check bits A and B */ - switch (bits_ab) { - /**********************************************************************/ - case (0): - /* bit a and bit are cleared, transient */ - stream->write_function(stream, "transient\n"); - goto success; - break; - /**********************************************************************/ - case (1): - case (2): - /* bit a or bit b are set, spare ... shouldn't happen */ - stream->write_function(stream, "spare\n"); - goto success; - break; - /**********************************************************************/ - case (3): - /* bit a and bit b are set, unequipped */ - stream->write_function(stream, "unequipped\n"); - goto success; - break; - /**********************************************************************/ - default: - stream->write_function(stream, "invalid values for bits A and B (%d)\n", - bits_ab); - goto success; - break; - /**********************************************************************/ - } /* switch (bits_ab) */ - - /* shouldn't get here but have a break for properness */ - break; - /**************************************************************************/ - case (1): - /* circuit incoming busy */ - stream->write_function(stream, "incoming busy"); - break; - /**************************************************************************/ - case (2): - /* circuit outgoing busy */ - stream->write_function(stream, "outgoing busy"); - break; - /**************************************************************************/ - case (3): - /* circuit idle */ - stream->write_function(stream, "idle"); - break; - /**************************************************************************/ - default: - /* invalid */ - stream->write_function(stream, "bits C and D are invalid (%d)!\n", - bits_cd); - goto success; - /**************************************************************************/ - } /* switch (bits_cd) */ - - /* check the maintenance block status in bits A and B */ - switch (bits_ab) { - /**************************************************************************/ - case (0): - /* no maintenace block...do nothing */ - break; - /**************************************************************************/ - case (1): - /* locally blocked */ - stream->write_function(stream, "|l_mn"); - break; - /**************************************************************************/ - case (2): - /* remotely blocked */ - stream->write_function(stream, "|r_mn"); - break; - /**************************************************************************/ - case (3): - /* both locally and remotely blocked */ - stream->write_function(stream, "|l_mn|r_mn"); - break; - /**************************************************************************/ - default: - stream->write_function(stream, "bits A and B are invlaid (%d)!\n", - bits_ab); - goto success; - /**************************************************************************/ - } /* switch (bits_ab) */ - - /* check the hardware block status in bits e and f */ - switch (bits_ef) { - /**************************************************************************/ - case (0): - /* no maintenace block...do nothing */ - break; - /**************************************************************************/ - case (1): - /* locally blocked */ - stream->write_function(stream, "|l_hw"); - break; - /**************************************************************************/ - case (2): - /* remotely blocked */ - stream->write_function(stream, "|r_hw"); - break; - /**************************************************************************/ - case (3): - /* both locally and remotely blocked */ - stream->write_function(stream, "|l_hw|r_hw"); - break; - /**************************************************************************/ - default: - stream->write_function(stream, "bits E and F are invlaid (%d)!\n", - bits_ef); - goto success; - /**************************************************************************/ - } /* switch (bits_ef) */ - -success: - stream->write_function(stream, "\n"); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t extract_span_chan(char *argv[10], int pos, int *span, int *chan) -{ - - if (!strcasecmp(argv[pos], "span")) { - /**************************************************************************/ - pos++; - *span = atoi(argv[pos]); - - pos++; - if (!strcasecmp(argv[pos], "chan")) { - /**********************************************************************/ - pos++; - *chan = atoi(argv[pos]); - /**********************************************************************/ - } else { - /**********************************************************************/ - return FTDM_FAIL; - /**********************************************************************/ - } - /**************************************************************************/ - } else { - /**************************************************************************/ - *span = atoi(argv[pos]); - - pos++; - if (!strcasecmp(argv[pos], "chan")) { - /**********************************************************************/ - pos++; - *chan = atoi(argv[pos]); - /**********************************************************************/ - } else { - /**********************************************************************/ - return FTDM_FAIL; - /**********************************************************************/ - } - /**************************************************************************/ - } - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t check_arg_count(int args, int min) -{ - if ( args < min ) { - return FTDM_FAIL; - } else { - return FTDM_SUCCESS; - } -} - - -/****************************************************************************** -* Fun: cli_ss7_show_mtp2link_by_id() -* Desc: display mtp3 link information with id -* Param: -* stream : output stream object -* rcId : mtp2 link's id -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: James Zhang -*******************************************************************************/ -static ftdm_status_t cli_ss7_show_mtp2link_by_id(ftdm_stream_handle_t *stream, int rcId) -{ - SdMngmt sta; - - SS7_RELAY_DBG_FUN(cli_ss7_show_mtp2link_by_id); - - ftdm_assert_return(stream != NULL, FTDM_FAIL, "Null stream\n"); - - if (ftmod_ss7_mtp2link_sta(rcId, &sta)) { - stream->write_function(stream, "Failed to read status of MTP2 link, id=%d \n", rcId); - return FTDM_FAIL; - } - - stream->write_function(stream, "name=%s|span=%d|chan=%d|sap=%d|state=%s|outsFrm=%d|drpdFrm=%d|lclStatus=%s|rmtStatus=%s|fsn=%d|bsn=%d\n", - g_ftdm_sngss7_data.cfg.mtp2Link[rcId].name, - g_ftdm_sngss7_data.cfg.mtp1Link[rcId].span, - g_ftdm_sngss7_data.cfg.mtp1Link[rcId].chan, - g_ftdm_sngss7_data.cfg.mtp2Link[rcId].id, - DECODE_LSD_LINK_STATUS(sta.t.ssta.s.sdDLSAP.hlSt), - sta.t.ssta.s.sdDLSAP.psOutsFrm, - sta.t.ssta.s.sdDLSAP.cntMaDrop, - (sta.t.ssta.s.sdDLSAP.lclBsy) ? "Y":"N", - (sta.t.ssta.s.sdDLSAP.remBsy) ? "Y":"N", - sta.t.ssta.s.sdDLSAP.fsn, - sta.t.ssta.s.sdDLSAP.bsn - ); - - return FTDM_SUCCESS; -} - -/****************************************************************************** -* Fun: cli_ss7_show_mtp2link_by_name() -* Desc: display all relay channels information -* Param: -* stream : output stream object -* rcName: mtp2 link's name -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: James Zhang -*******************************************************************************/ -static ftdm_status_t cli_ss7_show_mtp2link_by_name(ftdm_stream_handle_t *stream, char *name) -{ - int x = 0; - SS7_RELAY_DBG_FUN(cli_ss7_show_mtp2link_by_name); - - ftdm_assert_return(stream != NULL, FTDM_FAIL, "Null stream\n"); - ftdm_assert_return(!ftdm_strlen_zero(name), FTDM_FAIL, "Null MTP2 link name\n"); - - for (x = 0; x < (MAX_MTP_LINKS + 1); x++) { - if (0 == strcasecmp(g_ftdm_sngss7_data.cfg.mtp2Link[x].name, name)) { - return cli_ss7_show_mtp2link_by_id( stream, x ); - } - } - - stream->write_function (stream, "The MTP2 link with name \'%s\' is not found. \n", name); - return FTDM_FAIL; -} - -/****************************************************************************** -* Fun: cli_ss7_show_all_mtp2link() -* Desc: display all mtp2 links information -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: James Zhang -*******************************************************************************/ -static ftdm_status_t cli_ss7_show_all_mtp2link(ftdm_stream_handle_t *stream) -{ - int x = 0; - - SS7_RELAY_DBG_FUN(cli_ss7_show_all_mtp2link); - - ftdm_assert_return(stream != NULL, FTDM_FAIL, "Null stream\n"); - - for (x = 0; x < (MAX_MTP_LINKS + 1); x++) { - if (!ftdm_strlen_zero( g_ftdm_sngss7_data.cfg.mtp2Link[x].name)) { - cli_ss7_show_mtp2link_by_id(stream, x ); - } - } - - return FTDM_SUCCESS; -} - -/****************************************************************************** -* Fun: cli_ss7_show_mtp3link_by_id() -* Desc: display mtp3 link information with id -* Param: -* stream : output stream object -* rcId : mtp3 link's id -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: James Zhang -*******************************************************************************/ -static ftdm_status_t cli_ss7_show_mtp3link_by_id(ftdm_stream_handle_t *stream, int rcId) -{ - SnMngmt sta; - - SS7_RELAY_DBG_FUN(cli_ss7_show_mtp3link_by_id); - - ftdm_assert_return(stream != NULL, FTDM_FAIL, "Null stream\n"); - - memset(&sta, 0, sizeof(sta)); - if (ftmod_ss7_mtp3link_sta(rcId, &sta)) { - stream->write_function(stream, "Failed to read status of MTP3 link, id=%d \n", rcId); - return FTDM_FAIL; - } - - stream->write_function(stream, "name=%s|span=%d|chan=%d|sap=%d|state=%s|l_blk=%s|r_blk=%s|l_inhbt=%s|r_inhbt=%s\n", - g_ftdm_sngss7_data.cfg.mtp3Link[rcId].name, - g_ftdm_sngss7_data.cfg.mtp1Link[rcId].span, - g_ftdm_sngss7_data.cfg.mtp1Link[rcId].chan, - g_ftdm_sngss7_data.cfg.mtp3Link[rcId].id, - DECODE_LSN_LINK_STATUS(sta.t.ssta.s.snDLSAP.state), - (sta.t.ssta.s.snDLSAP.locBlkd) ? "Y":"N", - (sta.t.ssta.s.snDLSAP.remBlkd) ? "Y":"N", - (sta.t.ssta.s.snDLSAP.locInhbt) ? "Y":"N", - (sta.t.ssta.s.snDLSAP.rmtInhbt) ? "Y":"N" - ); - - return FTDM_SUCCESS; -} - -/****************************************************************************** -* Fun: cli_ss7_show_mtp3link_by_name() -* Desc: display all relay channels information -* Param: -* stream : output stream object -* rcName: mtp3 link's name -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: James Zhang -*******************************************************************************/ -static ftdm_status_t cli_ss7_show_mtp3link_by_name(ftdm_stream_handle_t *stream, char *name) -{ - int x=0; - SS7_RELAY_DBG_FUN(cli_ss7_show_mtp3link_by_name); - - ftdm_assert_return(stream != NULL, FTDM_FAIL, "Null stream\n"); - ftdm_assert_return(!ftdm_strlen_zero(name), FTDM_FAIL, "Null MTP3 link name\n"); - - for (x = 0; x < (MAX_MTP_LINKS + 1); x++) { - if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) { - return cli_ss7_show_mtp3link_by_id(stream, x ); - } - } - - stream->write_function(stream, "The MTP3 link with name \'%s\' is not found. \n", name); - return FTDM_FAIL; -} -/****************************************************************************** -* Fun: cli_ss7_show_all_mtp3link() -* Desc: display all mtp3 links information -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: James Zhang -*******************************************************************************/ -static ftdm_status_t cli_ss7_show_all_mtp3link(ftdm_stream_handle_t *stream) -{ - int x = 0; - - SS7_RELAY_DBG_FUN(cli_ss7_show_all_mtp3link); - ftdm_assert_return(stream != NULL, FTDM_FAIL, "Null stream\n"); - - for (x = 0; x < (MAX_MTP_LINKS + 1); x++) { - if (!ftdm_strlen_zero(g_ftdm_sngss7_data.cfg.mtp3Link[x].name)) { - cli_ss7_show_mtp3link_by_id(stream, x); - } - } - - return FTDM_SUCCESS; -} - - -/****************************************************************************** -* Fun: cli_ss7_show_all_linkset() -* Desc: display all mtp3 linksets information -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: James Zhang -*******************************************************************************/ -static ftdm_status_t cli_ss7_show_all_linkset(ftdm_stream_handle_t *stream) -{ - int x = 0; - SnMngmt sta; - - SS7_RELAY_DBG_FUN(cli_ss7_show_all_linkset); - ftdm_assert_return(stream != NULL, FTDM_FAIL, "Null stream\n"); - - x = 1; - while(x < (MAX_MTP_LINKSETS+1)) { - if (!ftdm_strlen_zero(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name)) { - if (ftmod_ss7_mtplinkSet_sta(x, &sta)) { - stream->write_function(stream, "Failed to read linkset=%s status\n", g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name); - } else { - stream->write_function(stream, "name=%s|state=%s|nmbActLnk=%d\n", - g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name, - DECODE_LSN_LINKSET_STATUS(sta.t.ssta.s.snLnkSet.state), sta.t.ssta.s.snLnkSet.nmbActLnks - ); - } - } - x++; - } - return FTDM_SUCCESS; -} - - -/****************************************************************************** -* Fun: cli_ss7_show_general() -* Desc: display all general information about ss7 -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: James Zhang -*******************************************************************************/ -static ftdm_status_t cli_ss7_show_general(ftdm_stream_handle_t *stream) -{ - SS7_RELAY_DBG_FUN(cli_ss7_show_general); - - ftdm_assert_return(stream != NULL, FTDM_FAIL, "Null stream\n"); - - stream->write_function(stream, "MTP2 status: \n"); - cli_ss7_show_all_mtp2link(stream); - - if(SNG_SS7_OPR_MODE_M2UA_SG != g_ftdm_operating_mode){ - stream->write_function(stream, "\nMTP3 status: \n"); - cli_ss7_show_all_mtp3link(stream); - - stream->write_function(stream, "\nMTP3 linkset status: \n"); - cli_ss7_show_all_linkset(stream); - -#if 0 - stream->write_function(stream, "\nMTP3 link route status: \n"); - - stream->write_function(stream, "\nISUP status: \n"); -#endif - - stream->write_function(stream, "\nRelay status: \n"); - cli_ss7_show_all_relay(stream); - } - - return FTDM_SUCCESS; -} - -/****************************************************************************** -* Fun: cli_ss7_show_relay_by_id() -* Desc: display all relay channels information -* Param: -* stream : output stream object -* rcId : channel's id -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: James Zhang -*******************************************************************************/ -static ftdm_status_t cli_ss7_show_relay_by_id(ftdm_stream_handle_t *stream, int rcId) -{ - RyMngmt sta; - - SS7_RELAY_DBG_FUN(cli_ss7_show_relay_by_id); - ftdm_assert_return(stream != NULL, FTDM_FAIL, "Null stream\n"); - - memset(&sta, 0x0, sizeof(sta)); - if (ftmod_ss7_relay_status(g_ftdm_sngss7_data.cfg.relay[rcId].id, &sta)) { - stream->write_function(stream, "Failed to read relay =%s status\n", g_ftdm_sngss7_data.cfg.relay[rcId].name); - return FTDM_FAIL; - } - - stream->write_function(stream, "name=%s|sap=%d|type=%d|port=%d|hostname=%s|procId=%d|status=%s\n", - g_ftdm_sngss7_data.cfg.relay[rcId].name, - g_ftdm_sngss7_data.cfg.relay[rcId].id, - g_ftdm_sngss7_data.cfg.relay[rcId].type, - g_ftdm_sngss7_data.cfg.relay[rcId].port, - g_ftdm_sngss7_data.cfg.relay[rcId].hostname, - g_ftdm_sngss7_data.cfg.relay[rcId].procId, - DECODE_LRY_CHAN_STATUS(sta.t.ssta.rySta.cStatus) - ); - - return FTDM_SUCCESS; -} -/****************************************************************************** -* Fun: cli_ss7_show_relay_by_name() -* Desc: display all relay channels information -* Param: -* stream : output stream object -* rcName: channel's name -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: James Zhang -*******************************************************************************/ -static ftdm_status_t cli_ss7_show_relay_by_name(ftdm_stream_handle_t *stream, char *name) -{ - int x = 0; - - SS7_RELAY_DBG_FUN(cli_ss7_show_relay_by_name); - - ftdm_assert_return(stream != NULL, FTDM_FAIL, "Null stream\n"); - ftdm_assert_return(!ftdm_strlen_zero(name), FTDM_FAIL, "Null relay link name\n"); - - for (x = 1; x < MAX_RELAY_CHANNELS; x++) { - if (!strcasecmp(g_ftdm_sngss7_data.cfg.relay[x].name, name)) { - return cli_ss7_show_relay_by_id(stream, x); - } - } - - stream->write_function( stream, "The relay channel with name \'%s\' is not found. \n", name); - return FTDM_FAIL; - -} -/****************************************************************************** -* Fun: cli_ss7_show_all_relay() -* Desc: display all relay channels information -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: James Zhang -*******************************************************************************/ -static ftdm_status_t cli_ss7_show_all_relay(ftdm_stream_handle_t *stream) -{ - int x = 0; - SS7_RELAY_DBG_FUN(cli_ss7_show_relay_by_name); - - ftdm_assert_return(stream != NULL, FTDM_FAIL, "Null stream\n"); - - for (x = 1; x < MAX_RELAY_CHANNELS; x++) { - if (!ftdm_strlen_zero(g_ftdm_sngss7_data.cfg.relay[x].name)) { - cli_ss7_show_relay_by_id (stream, x); - } - } - - return FTDM_SUCCESS; -} - - -/****************************************************************************** -* Fun: cli_ss7_show_channel_detail_of_span() -* Desc: display span information of a given id -* Param: -* stream : output stream object -* span_id : span id string received from cli -* chan_id : channel id string received from cli -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: James Zhang -*******************************************************************************/ -static ftdm_status_t cli_ss7_show_channel_detail_of_span(ftdm_stream_handle_t *stream, char *span_id, char *chan_id) -{ - int x, y; - - SS7_RELAY_DBG_FUN(cli_ss7_show_channel_detail_of_span); - - ftdm_assert_return(stream != NULL, FTDM_FAIL, "Null stream\n"); - ftdm_assert_return(span_id != 0, FTDM_FAIL, "Invalid span id\n"); - ftdm_assert_return(chan_id != 0, FTDM_FAIL, "Invalid chan id\n"); - - x = atoi(span_id); - y = atoi(chan_id); - if (!x) { - stream->write_function( stream, "Span \'%s\' does not exist. \n", span_id); - return FTDM_FAIL; - } - - return handle_show_status(stream, x, y, 1); -} - -/****************************************************************************** -* Fun: cli_ss7_show_all_channels_of_span() -* Desc: display span information of a given id -* Param: -* stream : output stream object -* span_id : span id string received from cli -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: James Zhang -*******************************************************************************/ -static ftdm_status_t cli_ss7_show_all_channels_of_span(ftdm_stream_handle_t *stream, char *span_id) -{ - int x=-1; - SS7_RELAY_DBG_FUN(cli_ss7_show_all_channels_of_span); - - ftdm_assert_return(stream != NULL, FTDM_FAIL, "Null stream\n"); - ftdm_assert_return(span_id != 0, FTDM_FAIL, "Invalid span id\n"); - - x = atoi(span_id); - if (!x) { - stream->write_function( stream, "Span \'%s\' does not exist. \n", span_id); - return FTDM_FAIL; - } - return handle_show_status(stream, x, 0, 1); -} - -/****************************************************************************** -* Fun: cli_ss7_show_span_by_id() -* Desc: display span information of a given id -* Param: -* stream : output stream object -* span_id : span id string received from cli -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: James Zhang -*******************************************************************************/ -static ftdm_status_t cli_ss7_show_span_by_id(ftdm_stream_handle_t *stream, char *span_id) -{ - int x = -1; - - SS7_RELAY_DBG_FUN(cli_ss7_show_span_by_id); - - ftdm_assert_return(stream != NULL, FTDM_FAIL, "Null stream\n"); - ftdm_assert_return(span_id != 0, FTDM_FAIL, "Invalid span id\n"); - - x = atoi(span_id); - if (!x) { - stream->write_function(stream, "Span \'%s\' does not exist. \n", span_id); - return FTDM_FAIL; - } - -#if 0 - stream->write_function( stream, "JZ: we should display span details here \n" ); -#endif - - cli_ss7_show_all_channels_of_span(stream, span_id); - - return FTDM_FAIL; -} - - -/****************************************************************************** -* Fun: cli_ss7_show_all_spans_detail() -* Desc: display all spans information in detail -* Param: -* stream : output stream object -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: James Zhang -*******************************************************************************/ -static ftdm_status_t cli_ss7_show_all_spans_detail(ftdm_stream_handle_t *stream) -{ - SS7_RELAY_DBG_FUN(cli_ss7_show_all_spans_detail); - ftdm_assert_return(stream != NULL, FTDM_FAIL, "Null stream\n"); - return handle_show_status(stream, 0, 0, 1); -} - -/****************************************************************************** -* Fun: cli_ss7_show_all_spans_general() -* Desc: display all spans information in general -* Param: -* stream : output stream object -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: James Zhang -*******************************************************************************/ -static ftdm_status_t cli_ss7_show_all_spans_general(ftdm_stream_handle_t *stream) -{ - SS7_RELAY_DBG_FUN(cli_ss7_show_all_spans_general); - ftdm_assert_return(stream != NULL, FTDM_FAIL, "Null stream\n"); - return FTDM_FAIL; -} - - -/****************************************************************************** -* Fun: handle_show_m2ua_profiles() -* Desc: display all m2ua profile information -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: Kapil Gupta -*******************************************************************************/ - -static ftdm_status_t handle_show_m2ua_profiles(ftdm_stream_handle_t *stream) -{ - MwMgmt cfm; - MwMgmt rsp; - char buf[2048]; - char* xmlhdr = (char*)""; - int x = 0x00; - int idx = 0x00; - int len = 0x00; - - memset((U8 *)&cfm, 0, sizeof(MwMgmt)); - memset((U8 *)&rsp, 0, sizeof(MwMgmt)); - memset(&buf[0], 0, sizeof(buf)); - - len = len + sprintf(buf + len, "%s\n", xmlhdr); - len = len + sprintf(buf + len, "\n"); - - if(ftmod_m2ua_ssta_req(STMWGEN, 0x00, &cfm)) { - stream->write_function(stream," Request to layer failed \n"); - return FTDM_FAIL; - } else { - len = len + sprintf(buf + len, "\n"); -#ifdef BIT_64 - len = len + sprintf(buf + len, " %d \n", cfm.t.ssta.s.genSta.memSize); - len = len + sprintf(buf + len, " %d \n", cfm.t.ssta.s.genSta.memAlloc); -#else - len = len + sprintf(buf + len, " %ld \n", cfm.t.ssta.s.genSta.memSize); - len = len + sprintf(buf + len, " %ld \n", cfm.t.ssta.s.genSta.memAlloc); -#endif - len = len + sprintf(buf + len, " %d \n", cfm.t.ssta.s.genSta.nmbClusters); - len = len + sprintf(buf + len, " %d \n", cfm.t.ssta.s.genSta.nmbPeers); - len = len + sprintf(buf + len, " %d \n", cfm.t.ssta.s.genSta.nmbIntf); - len = len + sprintf(buf + len, "\n"); - } - - /*iterate through all the m2ua links and prints all information */ - x = 1; - while(x\n"); - len = len + sprintf(buf + len, " %s \n", g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[x].name); - - if(ftmod_m2ua_ssta_req(STMWDLSAP,x,&cfm)) { - stream->write_function(stream," Request to M2UA layer failed \n"); - return FTDM_FAIL; - } else { - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len," %s \n", PRNT_M2UA_SAP_STATE(cfm.t.ssta.s.dlSapSta.state)); - len = len + sprintf(buf + len," %s \n", PRNT_M2UA_LINK_STATE(cfm.t.ssta.s.dlSapSta.lnkState)); - len = len + sprintf(buf + len," %d \n", cfm.t.ssta.s.dlSapSta.rpoEnable); - len = len + sprintf(buf + len," %d \n", cfm.t.ssta.s.dlSapSta.lpoEnable); - len = len + sprintf(buf + len," %d \n", cfm.t.ssta.s.dlSapSta.congLevel); - len = len + sprintf(buf + len, "\n"); - } - - memset((U8 *)&cfm, 0, sizeof(MwMgmt)); - if(ftmod_m2ua_ssta_req(STMWCLUSTER,g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[x].clusterId,&cfm)) { - stream->write_function(stream," Request to M2UA layer failed \n"); - return FTDM_FAIL; - } else { - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len," %s \n", PRNT_M2UA_CLUSTER_STATE(cfm.t.ssta.s.clusterSta.state)); - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.clusterSta.nmbPeer); - len = len + sprintf(buf + len, "\n"); - for(idx = 0; idx < cfm.t.ssta.s.clusterSta.nmbPeer; idx++) - { - len = len + sprintf(buf + len, " %d \n", cfm.t.ssta.s.clusterSta.peerSt[idx].peerId); - len = len + sprintf(buf + len, " %s \n", PRNT_M2UA_PEER_STATE(cfm.t.ssta.s.clusterSta.peerSt[idx].peerState)); - } - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.clusterSta.nmbActPeer); - - len = len + sprintf(buf + len, "\n"); - - memset((U8 *)&rsp, 0, sizeof(MwMgmt)); - memcpy(&rsp, &cfm, sizeof(MwMgmt)); - - - /* loop through configured peers */ - for(idx = 0; idx < rsp.t.ssta.s.clusterSta.nmbPeer; idx++) - { - int peer_id = rsp.t.ssta.s.clusterSta.peerSt[idx].peerId; - - memset(&cfm, 0, sizeof(MwMgmt)); - - if(LMW_PEER_DOWN != rsp.t.ssta.s.clusterSta.peerSt[idx].peerState){ - - if(ftmod_m2ua_ssta_req(STMWPEER, peer_id, &cfm)) { - stream->write_function(stream," Request to M2UA layer failed \n"); - return FTDM_FAIL; - } else { - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len, " %s \n",g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[peer_id].name); - len = len + sprintf(buf + len," %s \n", PRNT_M2UA_PEER_STATE(cfm.t.ssta.s.peerSta.state)); - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.peerSta.retryCount); - len = len + sprintf(buf + len, " %d \n", (int)cfm.t.ssta.s.peerSta.assocSta.spAssocId); - len = len + sprintf(buf + len, " %s \n",(cfm.t.ssta.s.peerSta.assocSta.connected)?"CONNECTED":"NOT CONNECTED"); - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.peerSta.assocSta.flcInProg); - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.peerSta.assocSta.flcLevel); - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.peerSta.assocSta.sctpHBeatEnb); - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.peerSta.assocSta.locOutStrms); - - len = len + sprintf(buf + len, "\n"); - } - } else { - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len, " %s \n",g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[peer_id].name); - len = len + sprintf(buf + len," %s \n", PRNT_M2UA_PEER_STATE(rsp.t.ssta.s.clusterSta.peerSt[idx].peerState)); - len = len + sprintf(buf + len, "\n"); - } - } - } - - memset((U8 *)&cfm, 0, sizeof(MwMgmt)); - if(ftmod_m2ua_ssta_req(STMWSCTSAP,x,&cfm)) { - stream->write_function(stream," Request to M2UA layer failed \n"); - return FTDM_FAIL; - } else { - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len," %s \n", PRNT_M2UA_SAP_STATE(cfm.t.ssta.s.sctSapSta.state)); - len = len + sprintf(buf + len," %s \n", (cfm.t.ssta.s.sctSapSta.endpOpen)?"END_POINT_OPENED_SUCCESSFULLY":"END_POINT_NOT_OPEN"); - len = len + sprintf(buf + len," %d \n", (int) cfm.t.ssta.s.sctSapSta.spEndpId); - len = len + sprintf(buf + len," %d \n", cfm.t.ssta.s.sctSapSta.nmbPrimRetry); - len = len + sprintf(buf + len, "\n"); - } - - len = len + sprintf(buf + len, "\n"); - } - x++; - } - - len = len + sprintf(buf + len, "\n"); - stream->write_function(stream,"\n%s\n",buf); - - return FTDM_SUCCESS; - -} - -/****************************************************************************** -* Fun: handle_show_m2ua_profile() -* Desc: display requested m2ua profile information -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: Kapil Gupta -*******************************************************************************/ - -static ftdm_status_t handle_show_m2ua_profile(ftdm_stream_handle_t *stream, char* m2ua_profile_name) -{ - char* xmlhdr = (char*)""; - char buf[4096]; - int x = 0x00; - int idx = 0x00; - int found = 0x00; - int len = 0x00; - MwMgmt cfm; - MwMgmt rsp; - - memset((U8 *)&cfm, 0, sizeof(MwMgmt)); - memset((U8 *)&rsp, 0, sizeof(MwMgmt)); - memset(&buf[0], 0, sizeof(buf)); - - len = len + sprintf(buf + len, "%s\n", xmlhdr); - - /*iterate through all the m2ua links and get required profile */ - x = 1; - while(xwrite_function(stream,"Requested M2UA profile[%s] not configured\n", m2ua_profile_name); - return FTDM_FAIL; - } - - - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len, " %s \n", m2ua_profile_name); - - if(ftmod_m2ua_ssta_req(STMWDLSAP,x,&cfm)) { - stream->write_function(stream," Request to M2UA layer failed \n"); - return FTDM_FAIL; - } else { - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len," %s \n", PRNT_M2UA_SAP_STATE(cfm.t.ssta.s.dlSapSta.state)); - len = len + sprintf(buf + len," %s \n", PRNT_M2UA_LINK_STATE(cfm.t.ssta.s.dlSapSta.lnkState)); - len = len + sprintf(buf + len," %d \n", cfm.t.ssta.s.dlSapSta.rpoEnable); - len = len + sprintf(buf + len," %d \n", cfm.t.ssta.s.dlSapSta.lpoEnable); - len = len + sprintf(buf + len," %d \n", cfm.t.ssta.s.dlSapSta.congLevel); - len = len + sprintf(buf + len, "\n"); - } - - if(ftmod_m2ua_ssta_req(STMWCLUSTER, g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[x].clusterId, &cfm)) { - stream->write_function(stream," Request to M2UA layer failed \n"); - return FTDM_FAIL; - } else { - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len," %s \n", PRNT_M2UA_CLUSTER_STATE(cfm.t.ssta.s.clusterSta.state)); - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.clusterSta.nmbPeer); - len = len + sprintf(buf + len, "\n"); - for(idx = 0; idx < cfm.t.ssta.s.clusterSta.nmbPeer; idx++) - { - len = len + sprintf(buf + len, " %d \n", cfm.t.ssta.s.clusterSta.peerSt[idx].peerId); - len = len + sprintf(buf + len, " %s \n", PRNT_M2UA_PEER_STATE(cfm.t.ssta.s.clusterSta.peerSt[idx].peerState)); - } - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.clusterSta.nmbActPeer); - - len = len + sprintf(buf + len, "\n"); - } - - memcpy((U8 *)&rsp, &cfm, sizeof(MwMgmt)); - - /* loop through configured peers */ - for(idx = 0; idx < rsp.t.ssta.s.clusterSta.nmbPeer; idx++) - { - memset((U8 *)&cfm, 0, sizeof(MwMgmt)); - - if(ftmod_m2ua_ssta_req(STMWPEER, rsp.t.ssta.s.clusterSta.peerSt[idx].peerId, &cfm)) { - stream->write_function(stream," Request to M2UA layer failed \n"); - return FTDM_FAIL; - } else { - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len, " %s \n",g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[rsp.t.ssta.s.clusterSta.peerSt[idx].peerId].name); - len = len + sprintf(buf + len," %s \n", PRNT_M2UA_PEER_STATE(cfm.t.ssta.s.peerSta.state)); - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.peerSta.retryCount); -#ifdef BIT_64 - len = len + sprintf(buf + len, " %d \n", cfm.t.ssta.s.peerSta.assocSta.spAssocId); -#else - len = len + sprintf(buf + len, " %ld \n", cfm.t.ssta.s.peerSta.assocSta.spAssocId); -#endif - len = len + sprintf(buf + len, " %s \n",(cfm.t.ssta.s.peerSta.assocSta.connected)?"CONNECTED":"NOT CONNECTED"); - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.peerSta.assocSta.flcInProg); - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.peerSta.assocSta.flcLevel); - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.peerSta.assocSta.sctpHBeatEnb); - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.peerSta.assocSta.locOutStrms); - - len = len + sprintf(buf + len, "\n"); - } - } - - if(ftmod_m2ua_ssta_req(STMWSCTSAP,x,&cfm)) { - stream->write_function(stream," Request to M2UA layer failed \n"); - return FTDM_FAIL; - } else { - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len," %s \n", PRNT_M2UA_SAP_STATE(cfm.t.ssta.s.sctSapSta.state)); - len = len + sprintf(buf + len," %s \n", (cfm.t.ssta.s.sctSapSta.endpOpen)?"END_POINT_OPENED_SUCCESSFULLY":"END_POINT_NOT_OPEN"); -#ifdef BIT_64 - len = len + sprintf(buf + len," %d \n", cfm.t.ssta.s.sctSapSta.spEndpId); -#else - len = len + sprintf(buf + len," %ld \n", cfm.t.ssta.s.sctSapSta.spEndpId); -#endif - len = len + sprintf(buf + len," %d \n", cfm.t.ssta.s.sctSapSta.nmbPrimRetry); - len = len + sprintf(buf + len, "\n"); - } - - len = len + sprintf(buf + len, "\n"); - - stream->write_function(stream,"\n%s\n",buf); - - return FTDM_SUCCESS; - -} - -/****************************************************************************** -* Fun: handle_show_sctp_profiles() -* Desc: display all sctp profile information -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: Kapil Gupta -*******************************************************************************/ -static ftdm_status_t handle_show_sctp_profiles(ftdm_stream_handle_t *stream) -{ - char* xmlhdr = (char*)""; - char buf[4096]; - int x = 0x00; - int len = 0x00; - SbMgmt cfm; - - memset((U8 *)&cfm, 0, sizeof(SbMgmt)); - memset(&buf[0], 0, sizeof(buf)); - - len = len + sprintf(buf + len, "%s\n", xmlhdr); - len = len + sprintf(buf + len, "\n"); - - if(ftmod_sctp_ssta_req(STSBGEN, 0x00, &cfm)) { - stream->write_function(stream," Request to SCTP layer failed \n"); - return FTDM_FAIL; - } else { - len = len + sprintf(buf + len, "\n"); -#ifdef BIT_64 - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.genSta.memSize); - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.genSta.memAlloc); -#else - len = len + sprintf(buf + len, " %ld \n",cfm.t.ssta.s.genSta.memSize); - len = len + sprintf(buf + len, " %ld \n",cfm.t.ssta.s.genSta.memAlloc); -#endif - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.genSta.nmbAssoc); - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.genSta.nmbEndp); - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.genSta.nmbLocalAddr); - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.genSta.nmbPeerAddr); - len = len + sprintf(buf + len, "\n"); - } - -#ifdef LSB12 - if(ftmod_sctp_ssta_req(STSBTMR, 0x00, &cfm)) { - stream->write_function(stream," Request to SCTP layer failed \n"); - return FTDM_FAIL; - } else { - len = len + sprintf(buf + len, "\n"); - - len = len + sprintf(buf + len, " %d \n", cfm.t.ssta.s.tmrSta.lifetimeTmr); - len = len + sprintf(buf + len, " %d \n", cfm.t.ssta.s.tmrSta.ackDelayTmr); - len = len + sprintf(buf + len, " %d \n", cfm.t.ssta.s.tmrSta.cookieTmr); - len = len + sprintf(buf + len, " %d \n", cfm.t.ssta.s.tmrSta.keyTmr); - len = len + sprintf(buf + len, " %d \n", cfm.t.ssta.s.tmrSta.freezeTmr); -#ifdef LSB4 - len = len + sprintf(buf + len, " %d \n", cfm.t.ssta.s.tmrSta.bundleTmr); -#endif - len = len + sprintf(buf + len, " %d \n", cfm.t.ssta.s.tmrSta.t1InitTmr); - len = len + sprintf(buf + len, " %d \n", cfm.t.ssta.s.tmrSta.t2ShutdownTmr); - len = len + sprintf(buf + len, " %d \n", cfm.t.ssta.s.tmrSta.hbeat); - len = len + sprintf(buf + len, " %d \n", cfm.t.ssta.s.tmrSta.t3rtx); - len = len + sprintf(buf + len, " %d \n", cfm.t.ssta.s.tmrSta.tIntTmr); - } - -#endif - - - /*iterate through all the sctp links and prints all information */ - x = 1; - while(x\n"); - - if(ftmod_sctp_ssta_req(STSBSCTSAP,x,&cfm)) { - stream->write_function(stream," Request to SCTP layer failed \n"); - return FTDM_FAIL; - } else { - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len," %s \n", PRNT_SCTP_SAP_STATE(cfm.t.ssta.s.sapSta.hlSt)); - len = len + sprintf(buf + len," %s \n", PRNT_SCTP_PROTO_SWITCH(cfm.t.ssta.s.sapSta.swtch)); - len = len + sprintf(buf + len, "\n"); - } - - if(ftmod_sctp_ssta_req(STSBTSAP,x,&cfm)) { - stream->write_function(stream," Request to SCTP layer failed \n"); - return FTDM_FAIL; - } else { - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len," %s \n", PRNT_SCTP_SAP_STATE(cfm.t.ssta.s.sapSta.hlSt)); - len = len + sprintf(buf + len," %s \n", PRNT_SCTP_PROTO_SWITCH(cfm.t.ssta.s.sapSta.swtch)); - len = len + sprintf(buf + len, "\n"); - } - - if(ftmod_sctp_ssta_req(STSBASSOC,x,&cfm)) { - if(LCM_REASON_INVALID_PAR_VAL == cfm.cfm.reason){ - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len, " SCT_ASSOC_STATE_CLOSED \n"); - len = len + sprintf(buf + len, "\n"); - }else{ - stream->write_function(stream," Request to SCTP layer failed \n"); - return FTDM_FAIL; - } - } else { - len = len + sprintf(buf + len, "\n"); - len = len + get_assoc_resp_buf(buf + len, &cfm); - len = len + sprintf(buf + len, "\n"); - } - - /* TODO - STSBDTA */ - - len = len + sprintf(buf + len, "\n"); - } - x++; - } - - len = len + sprintf(buf + len, "\n"); - stream->write_function(stream,"\n%s\n",buf); - - return FTDM_SUCCESS; -} - -int get_assoc_resp_buf(char* buf,SbMgmt* cfm) -{ - int len = 0x00; - int idx = 0x00; - char *asciiAddr; - CmInetIpAddr ip; - -#ifdef BIT_64 - len = len + sprintf(buf + len, " %d \n", cfm->t.ssta.s.assocSta.assocId); -#else - len = len + sprintf(buf + len, " %ld \n", cfm->t.ssta.s.assocSta.assocId); -#endif - len = len + sprintf(buf + len, " %s \n", PRNT_SCTP_ASSOC_STATE(cfm->t.ssta.s.assocSta.assocState)); - len = len + sprintf(buf + len, " %d \n", cfm->t.ssta.s.assocSta.dstPort); - len = len + sprintf(buf + len, " %d \n", cfm->t.ssta.s.assocSta.srcPort); - len = len + sprintf(buf + len, " %d \n", cfm->t.ssta.s.assocSta.dstNAddrLst.nmb); - for(idx =0; idx < cfm->t.ssta.s.assocSta.dstNAddrLst.nmb; idx++) - { - len = len + sprintf(buf + len, " \n"); - len = len + sprintf(buf + len, " %s \n", PRNT_CM_ADDR_TYPE(cfm->t.ssta.s.assocSta.dstNAddrLst.nAddr[idx].type)); - if(cfm->t.ssta.s.assocSta.dstNAddrLst.nAddr[idx].type == CM_IPV4ADDR_TYPE) - { - ip = ntohl(cfm->t.ssta.s.assocSta.dstNAddrLst.nAddr[idx].u.ipv4NetAddr); - cmInetNtoa(ip, &asciiAddr); - len = len + sprintf(buf + len, " %s \n",asciiAddr); - } - else - { - len = len + sprintf(buf + len, " %s \n", cfm->t.ssta.s.assocSta.dstNAddrLst.nAddr[idx].u.ipv6NetAddr); - } - len = len + sprintf(buf + len, " \n"); - } - - len = len + sprintf(buf + len, " %d \n", cfm->t.ssta.s.assocSta.srcNAddrLst.nmb); - for(idx =0; idx < cfm->t.ssta.s.assocSta.srcNAddrLst.nmb; idx++) - { - len = len + sprintf(buf + len, " \n"); - len = len + sprintf(buf + len, " %s \n", PRNT_CM_ADDR_TYPE(cfm->t.ssta.s.assocSta.srcNAddrLst.nAddr[idx].type)); - if(cfm->t.ssta.s.assocSta.srcNAddrLst.nAddr[idx].type == CM_IPV4ADDR_TYPE) - { - ip = ntohl(cfm->t.ssta.s.assocSta.srcNAddrLst.nAddr[idx].u.ipv4NetAddr); - cmInetNtoa(ip, &asciiAddr); - len = len + sprintf(buf + len, " %s \n", asciiAddr); - } - else - { - len = len + sprintf(buf + len, " %s \n", cfm->t.ssta.s.assocSta.srcNAddrLst.nAddr[idx].u.ipv6NetAddr); - } - len = len + sprintf(buf + len, " \n"); - } - - len = len + sprintf(buf + len, "\n %s \n", PRNT_CM_ADDR_TYPE(cfm->t.ssta.s.assocSta.priNAddr.type)); - - if(cfm->t.ssta.s.assocSta.priNAddr.type == CM_IPV4ADDR_TYPE) - { - ip = ntohl(cfm->t.ssta.s.assocSta.priNAddr.u.ipv4NetAddr); - cmInetNtoa(ip, &asciiAddr); - len = len + sprintf(buf + len, " %s \n",asciiAddr); - } - else - { - len = len + sprintf(buf + len, " %s \n", cfm->t.ssta.s.assocSta.priNAddr.u.ipv6NetAddr); - } - -#ifdef LSB11 - /* TODO - this flag is not enable as of now.. so later on will convert below prints to XML tags */ - len = len + sprintf(buf + len, " The number of unsent datagrams : %d\n", cfm->t.ssta.s.assocSta.nmbUnsentDgms); - len = len + sprintf(buf + len, " The number of unack datagrams : %d\n", cfm->t.ssta.s.assocSta.nmbUnackDgms); - len = len + sprintf(buf + len, " The number of undelivered datagrams : %d\n", cfm->t.ssta.s.assocSta.nmbUndelDgms); - len = len + sprintf(buf + len, " The number of retransmissions count : %d\n", cfm->t.ssta.s.assocSta.rtxCnt); - len = len + sprintf(buf + len, " The receive window size is: %d\n\n", cfm->t.ssta.s.assocSta.SctWinSize); - for(idx =0; idx < LSB_MAX_TMRS ; idx++) - { - len = len + sprintf(buf + len, " %d) Timer state is %d\n", idx, cfm->t.ssta.s.assocSta.tmr[idx].state); - len = len + sprintf(buf + len, " %d) Timer value is %d\n", idx, cfm->t.ssta.s.assocSta.tmr[idx].tmrVal); - len = len + sprintf(buf + len, " %d) No of paths is %d\n", idx, cfm->t.ssta.s.assocSta.tmr[idx].numPaths); - for(idx1 =0; idx1 < cfm->t.ssta.s.assocSta.tmr[idx].numPaths; idx1++) - { - if( cfm->t.ssta.s.assocSta.tmr[idx].path[idx1].localAddr.type == CM_IPV4ADDR_TYPE) - { - len = len + sprintf(buf + len, " %d) the local Addr is %d\n", idx1, - cfm->t.ssta.s.assocSta.tmr[idx].path[idx1].localAddr.u.ipv4NetAddr); - } - else - { - len = len + sprintf(buf + len, " %d) the local Addr is %s\n", idx1, - cfm->t.ssta.s.assocSta.tmr[idx].path[idx1].localAddr.u.ipv6NetAddr); - } - - if( cfm->t.ssta.s.assocSta.tmr[idx].path[idx1].peerAddr.type == CM_IPV4ADDR_TYPE) - { - len = len + sprintf(buf + len, " %d) the peer Addr is %d\n", idx1, - cfm->t.ssta.s.assocSta.tmr[idx].path[idx1].peerAddr.u.ipv4NetAddr); - } - else - { - len = len + sprintf(buf + len, " %d) the peer Addr is %s\n", idx1, - cfm->t.ssta.s.assocSta.tmr[idx].path[idx1].peerAddr.u.ipv6NetAddr); - } - } /* Loop for paths */ - } /* Loop for timers */ -#endif - - return len; -} - -/****************************************************************************** -* Fun: handle_show_sctp_profile() -* Desc: display requested sctp profile information -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: Kapil Gupta -*******************************************************************************/ -static ftdm_status_t handle_show_sctp_profile(ftdm_stream_handle_t *stream, char* sctp_profile_name) -{ - char* xmlhdr = (char*)""; - char buf[4096]; - int x = 0x00; - int len = 0x00; - SbMgmt cfm; - int found = 0x00; - - memset((U8 *)&cfm, 0, sizeof(SbMgmt)); - memset(&buf[0], 0, sizeof(buf)); - - len = len + sprintf(buf + len, "%s\n", xmlhdr); - - /*iterate through all the sctp links and prints all information */ - x = 1; - while(xwrite_function(stream,"Requested SCTP profile[%s] not configured\n", sctp_profile_name); - return FTDM_FAIL; - } - - len = len + sprintf(buf + len, "\n"); - - if(ftmod_sctp_ssta_req(STSBSCTSAP,x,&cfm)) { - stream->write_function(stream," Request to SCTP layer failed \n"); - return FTDM_FAIL; - } else { - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len," %s \n", PRNT_SCTP_SAP_STATE(cfm.t.ssta.s.sapSta.hlSt)); - len = len + sprintf(buf + len," %s \n", PRNT_SCTP_PROTO_SWITCH(cfm.t.ssta.s.sapSta.swtch)); - len = len + sprintf(buf + len, "\n"); - } - - if(ftmod_sctp_ssta_req(STSBTSAP,x,&cfm)) { - stream->write_function(stream," Request to SCTP layer failed \n"); - return FTDM_FAIL; - } else { - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len," %s \n", PRNT_SCTP_SAP_STATE(cfm.t.ssta.s.sapSta.hlSt)); - len = len + sprintf(buf + len," %s \n", PRNT_SCTP_PROTO_SWITCH(cfm.t.ssta.s.sapSta.swtch)); - len = len + sprintf(buf + len, "\n"); - } - - if(ftmod_sctp_ssta_req(STSBASSOC,x,&cfm)) { - /* it means assoc id not yet allocated */ - if(LCM_REASON_INVALID_PAR_VAL == cfm.cfm.reason){ - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len, " SCT_ASSOC_STATE_CLOSED \n"); - len = len + sprintf(buf + len, "\n"); - }else{ - stream->write_function(stream," Request to SCTP layer failed \n"); - return FTDM_FAIL; - } - } else { - len = len + sprintf(buf + len, "\n"); - len = len + get_assoc_resp_buf(buf + len, &cfm); - len = len + sprintf(buf + len, "\n"); - } - - /* TODO - STSBDTA */ - - len = len + sprintf(buf + len, "\n"); - - stream->write_function(stream,"\n%s\n",buf); - - return FTDM_SUCCESS; -} - -/****************************************************************************** -* Fun: handle_show_nif_profiles() -* Desc: display all nif profile information -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: Kapil Gupta -*******************************************************************************/ -static ftdm_status_t handle_show_nif_profiles(ftdm_stream_handle_t *stream) -{ - char* xmlhdr = (char*)""; - char buf[4096]; - int x = 0x00; - int len = 0x00; - NwMgmt cfm; - - memset((U8 *)&cfm, 0, sizeof(NwMgmt)); - memset(&buf[0], 0, sizeof(buf)); - - len = len + sprintf(buf + len, "%s\n", xmlhdr); - len = len + sprintf(buf + len, "\n"); - - if(ftmod_nif_ssta_req(STNWGEN, 0x00, &cfm)) { - stream->write_function(stream," Request to NIF layer failed \n"); - return FTDM_FAIL; - } else { - len = len + sprintf(buf + len, "\n"); -#ifdef BIT_64 - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.genSta.memSize); - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.genSta.memAlloc); -#else - len = len + sprintf(buf + len, " %ld \n",cfm.t.ssta.s.genSta.memSize); - len = len + sprintf(buf + len, " %ld \n",cfm.t.ssta.s.genSta.memAlloc); -#endif - len = len + sprintf(buf + len, "\n"); - } - - /*iterate through all the NIF links and prints all information */ - x = 1; - while(x\n"); - - if(ftmod_nif_ssta_req(STNWDLSAP,x,&cfm)) { - stream->write_function(stream," Request to NIF layer failed \n"); - return FTDM_FAIL; - } else { - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len," %s \n", PRNT_NIF_SAP_STATE(cfm.t.ssta.s.dlSapSta.m2uaState)); - len = len + sprintf(buf + len," %s \n", PRNT_NIF_SAP_STATE(cfm.t.ssta.s.dlSapSta.mtp2State)); -#ifdef BIT_64 - len = len + sprintf(buf + len," %d \n", cfm.t.ssta.s.dlSapSta.nmbRetry); -#else - len = len + sprintf(buf + len," %ld \n", cfm.t.ssta.s.dlSapSta.nmbRetry); -#endif - len = len + sprintf(buf + len, "\n"); - } - - len = len + sprintf(buf + len, "\n"); - } - x++; - } - - len = len + sprintf(buf + len, "\n"); - stream->write_function(stream,"\n%s\n",buf); - - return FTDM_SUCCESS; -} - -/****************************************************************************** -* Fun: handle_show_nif_profile() -* Desc: display requested nif profile information -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: Kapil Gupta -*******************************************************************************/ -static ftdm_status_t handle_show_nif_profile(ftdm_stream_handle_t *stream, char* nif_profile_name) -{ - char* xmlhdr = (char*)""; - char buf[4096]; - int x = 0x00; - int found = 0x00; - int len = 0x00; - NwMgmt cfm; - - memset((U8 *)&cfm, 0, sizeof(NwMgmt)); - memset(&buf[0], 0, sizeof(buf)); - - len = len + sprintf(buf + len, "%s\n", xmlhdr); - - /*iterate through all the m2ua links and get required profile */ - x = 1; - while(xwrite_function(stream,"Requested NIF profile[%s] not configured\n", nif_profile_name); - return FTDM_FAIL; - } - - - len = len + sprintf(buf + len, "\n"); - - if(ftmod_nif_ssta_req(STNWDLSAP,x,&cfm)) { - stream->write_function(stream," Request to NIF layer failed \n"); - return FTDM_FAIL; - } else { - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len," %s \n", PRNT_NIF_SAP_STATE(cfm.t.ssta.s.dlSapSta.m2uaState)); - len = len + sprintf(buf + len," %s \n", PRNT_NIF_SAP_STATE(cfm.t.ssta.s.dlSapSta.mtp2State)); -#ifdef BIT_64 - len = len + sprintf(buf + len," %d \n", cfm.t.ssta.s.dlSapSta.nmbRetry); -#else - len = len + sprintf(buf + len," %ld \n", cfm.t.ssta.s.dlSapSta.nmbRetry); -#endif - len = len + sprintf(buf + len, "\n"); - } - - len = len + sprintf(buf + len, "\n"); - - stream->write_function(stream,"\n%s\n",buf); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -/****************************************************************************** -* Fun: handle_show_m2ua_peer_status() -* Desc: display requested m2ua profile peer information -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: Kapil Gupta -*******************************************************************************/ - -static ftdm_status_t handle_show_m2ua_peer_status(ftdm_stream_handle_t *stream, char* m2ua_profile_name) -{ - char* xmlhdr = (char*)""; - char buf[4096]; - int x = 0x00; - int found = 0x00; - int len = 0x00; - MwMgmt cfm; - SbMgmt sctp_cfm; - sng_m2ua_cluster_cfg_t* clust = NULL; - sng_m2ua_cfg_t* m2ua = NULL; - sng_m2ua_peer_cfg_t* peer = NULL; - int peer_id = 0; - int sctp_id = 0; - - memset((U8 *)&cfm, 0, sizeof(MwMgmt)); - memset((U8 *)&sctp_cfm, 0, sizeof(SbMgmt)); - memset(&buf[0], 0, sizeof(buf)); - - len = len + sprintf(buf + len, "%s\n", xmlhdr); - - /*iterate through all the m2ua links and get required profile */ - x = 1; - while(xwrite_function(stream,"Requested M2UA profile[%s] not configured\n", m2ua_profile_name); - return FTDM_FAIL; - } - - m2ua = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[x]; - clust = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_clus[m2ua->clusterId]; - - for(x = 0; x < clust->numOfPeers;x++){ - peer_id = clust->peerIdLst[x]; - peer = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[peer_id]; - - if(ftmod_m2ua_ssta_req(STMWPEER, peer_id, &cfm)) { - stream->write_function(stream," Request to M2UA layer failed \n"); - return FTDM_FAIL; - } else { - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len, " %s \n",peer->name); - len = len + sprintf(buf + len," %s \n", PRNT_M2UA_PEER_STATE(cfm.t.ssta.s.peerSta.state)); - /*len = len + sprintf(buf + len, " %s \n",(cfm.t.ssta.s.peerSta.assocSta.connected)?"CONNECTED":"NOT CONNECTED");*/ - len = len + sprintf(buf + len, "\n"); - } - - sctp_id = peer->sctpId; - - if(ftmod_sctp_ssta_req(STSBASSOC, sctp_id, &sctp_cfm)) { - if(LMW_PEER_DOWN == cfm.t.ssta.s.peerSta.state){ - /* If there is no association established so far, it will return fail..*/ - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len, " SCT_ASSOC_STATE_CLOSED \n"); - len = len + sprintf(buf + len, "\n"); - }else{ - stream->write_function(stream," Request to SCTP layer failed \n"); - return FTDM_FAIL; - } - } else { - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len, " %s \n", PRNT_SCTP_ASSOC_STATE(sctp_cfm.t.ssta.s.assocSta.assocState)); - len = len + sprintf(buf + len, "\n"); - } - } - - stream->write_function(stream,"\n%s\n",buf); - - return FTDM_SUCCESS; -} - -/****************************************************************************** -* Fun: handle_show_m2ua_cluster_status() -* Desc: display requested m2ua profile cluster information -* Ret: FTDM_SUCCESS | FTDM_FAIL -* Note: -* author: Kapil Gupta -*******************************************************************************/ - -static ftdm_status_t handle_show_m2ua_cluster_status(ftdm_stream_handle_t *stream, char* m2ua_profile_name) -{ - char* xmlhdr = (char*)""; - char buf[4096]; - int x = 0x00; - int found = 0x00; - int len = 0x00; - int idx = 0x00; - MwMgmt cfm; - SbMgmt sctp_cfm; - sng_m2ua_cluster_cfg_t* clust = NULL; - sng_m2ua_cfg_t* m2ua = NULL; - - memset((U8 *)&cfm, 0, sizeof(MwMgmt)); - memset((U8 *)&sctp_cfm, 0, sizeof(SbMgmt)); - memset(&buf[0], 0, sizeof(buf)); - - len = len + sprintf(buf + len, "%s\n", xmlhdr); - - /*iterate through all the m2ua links and get required profile */ - x = 1; - while(xwrite_function(stream,"Requested M2UA profile[%s] not configured\n", m2ua_profile_name); - return FTDM_FAIL; - } - - m2ua = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[x]; - clust = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_clus[m2ua->clusterId]; - - if(ftmod_m2ua_ssta_req(STMWCLUSTER,g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[x].clusterId,&cfm)) { - stream->write_function(stream," Request to M2UA layer failed \n"); - return FTDM_FAIL; - } else { - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len, " %s \n",clust->name); - len = len + sprintf(buf + len," %s \n", PRNT_M2UA_CLUSTER_STATE(cfm.t.ssta.s.clusterSta.state)); - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.clusterSta.nmbPeer); - for(idx = 0; idx < cfm.t.ssta.s.clusterSta.nmbPeer; idx++) - { - len = len + sprintf(buf + len, "\n"); - len = len + sprintf(buf + len, " %s \n", g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[cfm.t.ssta.s.clusterSta.peerSt[idx].peerId].name); - len = len + sprintf(buf + len, " %d \n", cfm.t.ssta.s.clusterSta.peerSt[idx].peerId); - len = len + sprintf(buf + len, " %s \n", PRNT_M2UA_PEER_STATE(cfm.t.ssta.s.clusterSta.peerSt[idx].peerState)); - len = len + sprintf(buf + len, "\n"); - } - len = len + sprintf(buf + len, " %d \n",cfm.t.ssta.s.clusterSta.nmbActPeer); - - len = len + sprintf(buf + len, "\n"); - } - - stream->write_function(stream,"\n%s\n",buf); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c deleted file mode 100644 index 6b12605c6a..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c +++ /dev/null @@ -1,921 +0,0 @@ -/* - * Copyright (c) 2009, Konrad Hammel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* INCLUDE ********************************************************************/ -#include "ftmod_sangoma_ss7_main.h" -/******************************************************************************/ - -/* DEFINES ********************************************************************/ -/******************************************************************************/ - -/* GLOBALS ********************************************************************/ -/******************************************************************************/ - -/* PROTOTYPES *****************************************************************/ -int ft_to_sngss7_activate_all(void); - -static int ftmod_ss7_enable_isap(int suId); -static int ftmod_ss7_enable_nsap(int suId); -static int ftmod_ss7_enable_mtpLinkSet(int lnkSetId); - - -/******************************************************************************/ - -/* FUNCTIONS ******************************************************************/ -int ft_to_sngss7_activate_all(void) -{ - int x; - - x = 1; - while (x < (MAX_ISAPS)) { - /* check if this link has already been actived */ - if ((g_ftdm_sngss7_data.cfg.isap[x].id != 0) && - (!(g_ftdm_sngss7_data.cfg.isap[x].flags & SNGSS7_ACTIVE))) { - - if (ftmod_ss7_enable_isap(x)) { - SS7_CRITICAL("ISAP %d Enable: NOT OK\n", x); - return 1; - } else { - SS7_INFO("ISAP %d Enable: OK\n", x); - } - - /* set the SNGSS7_ACTIVE flag */ - g_ftdm_sngss7_data.cfg.isap[x].flags |= SNGSS7_ACTIVE; - } /* if !SNGSS7_ACTIVE */ - - x++; - } /* while (x < (MAX_ISAPS)) */ - - if(SNG_SS7_OPR_MODE_M2UA_SG != g_ftdm_operating_mode){ - x = 1; - while (x < (MAX_NSAPS)) { - /* check if this link has already been actived */ - if ((g_ftdm_sngss7_data.cfg.nsap[x].id != 0) && - (!(g_ftdm_sngss7_data.cfg.nsap[x].flags & SNGSS7_ACTIVE))) { - - if (ftmod_ss7_enable_nsap(x)) { - SS7_CRITICAL("NSAP %d Enable: NOT OK\n", x); - return 1; - } else { - SS7_INFO("NSAP %d Enable: OK\n", x); - } - - /* set the SNGSS7_ACTIVE flag */ - g_ftdm_sngss7_data.cfg.nsap[x].flags |= SNGSS7_ACTIVE; - } /* if !SNGSS7_ACTIVE */ - - x++; - } /* while (x < (MAX_NSAPS)) */ - - if (g_ftdm_sngss7_data.cfg.mtpRoute[1].id != 0) { - x = 1; - while (x < (MAX_MTP_LINKSETS+1)) { - /* check if this link has already been actived */ - if ((g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) && - (!(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags & SNGSS7_ACTIVE))) { - - if (ftmod_ss7_enable_mtpLinkSet(x)) { - SS7_CRITICAL("LinkSet \"%s\" Enable: NOT OK\n", g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name); - return 1; - } else { - SS7_INFO("LinkSet \"%s\" Enable: OK\n", g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name); - } - - /* set the SNGSS7_ACTIVE flag */ - g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags |= SNGSS7_ACTIVE; - } /* if !SNGSS7_ACTIVE */ - - x++; - } /* while (x < (MAX_MTP_LINKSETS+1)) */ - } - } - - if(SNG_SS7_OPR_MODE_M2UA_SG == g_ftdm_operating_mode){ - return ftmod_ss7_m2ua_start(); - } - - return 0; -} - -/******************************************************************************/ -static int ftmod_ss7_enable_isap(int suId) -{ - CcMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTCC; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(CcMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTCC; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STISAP; - - cntrl.hdr.elmId.elmntInst1 = suId; /* this is the SAP to bind */ - - cntrl.t.cntrl.action = ABND_ENA; /* bind and activate */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_cc(&pst, &cntrl)); -} - -/******************************************************************************/ -static int ftmod_ss7_enable_nsap(int suId) -{ - SiMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSI; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SiMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSI; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STNSAP; - - cntrl.t.cntrl.s.siElmnt.elmntId.sapId = suId; - cntrl.t.cntrl.s.siElmnt.elmntParam.nsap.nsapType = SAP_MTP; - - - cntrl.t.cntrl.action = ABND_ENA; /* bind and activate */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_isup(&pst, &cntrl)); -} - -/******************************************************************************/ -static int ftmod_ss7_enable_mtpLinkSet(int lnkSetId) -{ - SnMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SnMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSN; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STLNKSET; - cntrl.hdr.elmId.elmntInst1 = lnkSetId; /* this is the linkset to bind */ - - cntrl.t.cntrl.action = ABND_ENA; /* bind and activate */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_mtp3(&pst, &cntrl)); -} - -/******************************************************************************/ -int ftmod_ss7_inhibit_mtp3link(uint32_t id) -{ - SnMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SnMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSN; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STDLSAP; - cntrl.hdr.elmId.elmntInst1 = id; /* the DSLAP to inhibit */ - - cntrl.t.cntrl.action = AINH; /* Inhibit */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_mtp3(&pst, &cntrl)); -} - -/******************************************************************************/ -int ftmod_ss7_uninhibit_mtp3link(uint32_t id) -{ - SnMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SnMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSN; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STDLSAP; - cntrl.hdr.elmId.elmntInst1 = id; /* the DSLAP to inhibit */ - - cntrl.t.cntrl.action = AUNINH; /* Inhibit */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_mtp3(&pst, &cntrl)); -} - -/******************************************************************************/ -int ftmod_ss7_bind_mtp3link(uint32_t id) -{ - SnMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SnMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSN; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STDLSAP; - cntrl.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtp3Link[id].id; - - cntrl.t.cntrl.action = ABND; /* Activate */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_mtp3(&pst, &cntrl)); -} - -/******************************************************************************/ -int ftmod_ss7_unbind_mtp3link(uint32_t id) -{ - SnMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SnMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSN; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STDLSAP; - cntrl.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtp3Link[id].id; - - cntrl.t.cntrl.action = AUBND_DIS; /* unbind and disable */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_mtp3(&pst, &cntrl)); -} - -/******************************************************************************/ -int ftmod_ss7_activate_mtp3link(uint32_t id) -{ - SnMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SnMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSN; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STDLSAP; - cntrl.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtp3Link[id].id; - - cntrl.t.cntrl.action = AENA; /* Activate */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_mtp3(&pst, &cntrl)); -} - -/******************************************************************************/ -int ftmod_ss7_deactivate_mtp3link(uint32_t id) -{ - SnMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SnMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSN; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STDLSAP; - cntrl.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtp3Link[id].id; - - cntrl.t.cntrl.action = ADISIMM; /* Deactivate */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_mtp3(&pst, &cntrl)); -} - -/******************************************************************************/ -int ftmod_ss7_deactivate2_mtp3link(uint32_t id) -{ - SnMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SnMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSN; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STDLSAP; - cntrl.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtp3Link[id].id; - - cntrl.t.cntrl.action = ADISIMM_L2; /* Deactivate...layer 2 only */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_mtp3(&pst, &cntrl)); -} - -/******************************************************************************/ -int ftmod_ss7_activate_mtplinkSet(uint32_t id) -{ - SnMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SnMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSN; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STLNKSET; - cntrl.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLinkSet[id].id; - - cntrl.t.cntrl.action = AACTLNKSET; /* Activate */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_mtp3(&pst, &cntrl)); -} - -/******************************************************************************/ -int ftmod_ss7_deactivate_mtplinkSet(uint32_t id) -{ - SnMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SnMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSN; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STLNKSET; - cntrl.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLinkSet[id].id; - - cntrl.t.cntrl.action = ADEACTLNKSET; /* Activate */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_mtp3(&pst, &cntrl)); -} - -/******************************************************************************/ -int ftmod_ss7_deactivate2_mtplinkSet(uint32_t id) -{ - SnMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SnMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSN; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STLNKSET; - cntrl.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLinkSet[id].id; - - cntrl.t.cntrl.action = ADEACTLNKSET_L2; /* Activate */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_mtp3(&pst, &cntrl)); -} - -/******************************************************************************/ -int ftmod_ss7_lpo_mtp3link(uint32_t id) -{ - SnMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SnMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSN; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STDLSAP; - cntrl.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtp3Link[id].id; - - cntrl.t.cntrl.action = ACTION_LPO; /* Activate */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_mtp3(&pst, &cntrl)); -} - -/******************************************************************************/ -int ftmod_ss7_lpr_mtp3link(uint32_t id) -{ - SnMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SnMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSN; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STDLSAP; - cntrl.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtp3Link[id].id; - - cntrl.t.cntrl.action = ACTION_LPR; /* Activate */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_mtp3(&pst, &cntrl)); -} - -/******************************************************************************/ -int ftmod_ss7_shutdown_isup(void) -{ - SiMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSI; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SiMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSI; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STGEN; - - cntrl.t.cntrl.action = ASHUTDOWN; /* shutdown */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_isup(&pst, &cntrl)); -} - -/******************************************************************************/ -int ftmod_ss7_shutdown_mtp3(void) -{ - SnMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SnMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSN; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STGEN; - - cntrl.t.cntrl.action = ASHUTDOWN; /* Activate */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_mtp3(&pst, &cntrl)); -} - -/******************************************************************************/ -int ftmod_ss7_shutdown_mtp2(void) -{ - SdMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSD; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SdMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSD; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STGEN; - - cntrl.t.cntrl.action = ASHUTDOWN; /* Activate */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_mtp2(&pst, &cntrl)); -} - -/******************************************************************************/ -int ftmod_ss7_shutdown_relay(void) -{ - RyMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTRY; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(RyMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTRY; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STGEN; - - cntrl.t.cntrl.action = ASHUTDOWN; /* Activate */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_relay(&pst, &cntrl)); -} - -/******************************************************************************/ -int ftmod_ss7_disable_relay_channel(uint32_t chanId) -{ - RyMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTRY; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(RyMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTRY; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STGEN; - - - cntrl.hdr.elmId.elmntInst1 = chanId; - - cntrl.t.cntrl.action = ADISIMM; /* Deactivate */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_relay(&pst, &cntrl)); -} - -/******************************************************************************/ -int ftmod_ss7_disable_grp_mtp3Link(uint32_t procId) -{ - SnMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SnMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSN; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STGRDLSAP; /* group DLSAP */ - - cntrl.t.cntrl.ctlType.groupKey.dstProcId = procId; /* all SAPS to this ProcId */ - - cntrl.t.cntrl.action = AUBND_DIS; /* disable and unbind */ - cntrl.t.cntrl.subAction = SAGR_DSTPROCID; /* specificed element */ - - if (g_ftdm_sngss7_data.cfg.procId == procId) { - SS7_DEBUG("Executing MTP3 cntrl command local pid =%i\n",procId); - return (sng_cntrl_mtp3(&pst, &cntrl)); - } else { - SS7_WARN("Executing MTP3 cntrl command different local=%i target=%i\n", - g_ftdm_sngss7_data.cfg.procId,procId); - return (sng_cntrl_mtp3_nowait(&pst, &cntrl)); - } - -} - -/******************************************************************************/ -int ftmod_ss7_enable_grp_mtp3Link(uint32_t procId) -{ - SnMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SnMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSN; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STGRDLSAP; /* group DLSAP */ - - cntrl.t.cntrl.ctlType.groupKey.dstProcId = procId; /* all SAPS to this ProcId */ - - cntrl.t.cntrl.action = ABND_ENA; /* bind and enable */ - cntrl.t.cntrl.subAction = SAGR_DSTPROCID; /* specificed element */ - - if (g_ftdm_sngss7_data.cfg.procId == procId) { - SS7_DEBUG("Executing MTP3 cntrl command local pid =%i\n",procId); - return (sng_cntrl_mtp3(&pst, &cntrl)); - } else { - SS7_WARN("Executing MTP3 cntrl command different local=%i target=%i\n", - g_ftdm_sngss7_data.cfg.procId,procId); - return (sng_cntrl_mtp3_nowait(&pst, &cntrl)); - } - -} - -/******************************************************************************/ -int ftmod_ss7_disable_grp_mtp2Link(uint32_t procId) -{ - SdMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSD; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(cntrl)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSD; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STGRNSAP; /* group NSAP */ - - cntrl.t.cntrl.par.dstProcId = procId; /* all SAPS to this ProcId */ - - cntrl.t.cntrl.action = AUBND_DIS; /* disable and unbind */ - cntrl.t.cntrl.subAction = SAGR_DSTPROCID; /* specificed element */ - - return (sng_cntrl_mtp2(&pst, &cntrl)); - -} - -/******************************************************************************/ -int __ftmod_ss7_block_isup_ckt(uint32_t cktId, ftdm_bool_t wait) -{ - SiMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSI; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SiMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSI; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STICIR; - - cntrl.t.cntrl.s.siElmnt.elmntId.circuit = cktId; - cntrl.t.cntrl.s.siElmnt.elmntParam.cir.flag = LSI_CNTRL_CIR_FORCE; - - cntrl.t.cntrl.action = ADISIMM; /* block via BLO */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - if (wait == FTDM_TRUE) { - return (sng_cntrl_isup(&pst, &cntrl)); - } else { - return (sng_cntrl_isup_nowait(&pst, &cntrl)); - } -} - -/******************************************************************************/ -int ftmod_ss7_unblock_isup_ckt(uint32_t cktId) -{ - SiMngmt cntrl; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSI; - - /* initalize the control structure */ - memset(&cntrl, 0x0, sizeof(SiMngmt)); - - /* initalize the control header */ - smHdrInit(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* this is a control request */ - cntrl.hdr.entId.ent = ENTSI; - cntrl.hdr.entId.inst = S_INST; - cntrl.hdr.elmId.elmnt = STICIR; - - cntrl.t.cntrl.s.siElmnt.elmntId.circuit = cktId; - cntrl.t.cntrl.s.siElmnt.elmntParam.cir.flag = LSI_CNTRL_CIR_FORCE; - - cntrl.t.cntrl.action = AENA; /* unblock via UBL */ - cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ - - return (sng_cntrl_isup(&pst, &cntrl)); -} -/******************************************************************************/ -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ -/******************************************************************************/ - diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c deleted file mode 100644 index f120114667..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c +++ /dev/null @@ -1,2750 +0,0 @@ -/* - * Copyright (c) 2009 Konrad Hammel - * All rights reserved. - * - * Redistribution and use in source and binary forms|with or without - * modification|are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice|this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice|this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT - * LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL, - * EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Contributors: - * - * Ricardo Barroetaveña - * James Zhang - * - */ - -/* INCLUDE ********************************************************************/ -#include "ftmod_sangoma_ss7_main.h" - -/******************************************************************************/ - -/* DEFINES ********************************************************************/ -/******************************************************************************/ - -/* GLOBALS ********************************************************************/ - -/******************************************************************************/ - -/* PROTOTYPES *****************************************************************/ -ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); -ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCnStEvnt *siCnStEvnt, uint8_t evntType); -ftdm_status_t handle_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); -ftdm_status_t handle_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt); -ftdm_status_t handle_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt); -ftdm_status_t handle_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiInfoEvnt *siInfoEvnt); -ftdm_status_t handle_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt); -ftdm_status_t handle_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt); -ftdm_status_t handle_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit); -ftdm_status_t handle_susp_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiSuspEvnt *siSuspEvnt); -ftdm_status_t handle_resm_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiResmEvnt *siResmEvnt); -ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); - -ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_cot_start(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_cot_stop(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_local_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_blo_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_local_blk(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_local_ubl(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_cgb_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_olm_msg(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -/******************************************************************************/ - -/* FUNCTIONS ******************************************************************/ - -#define ftdm_running_return(var) if (!ftdm_running()) { SS7_ERROR("Error: ftdm_running is not set! Ignoring\n"); return var; } - -ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - char var[FTDM_DIGITS_LIMIT]; - - memset(var, '\0', sizeof(var)); - - ftdm_running_return(FTDM_FAIL); - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - if (sngss7_test_ckt_flag(sngss7_info, FLAG_GLARE)) { - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx IAM (glare)\n", sngss7_info->circuit->cic); - } - - /* check if the circuit has a remote block */ - if ((sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) || - (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) || - (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) { - - /* as per Q.764, 2.8.2.3 xiv ... remove the block from this channel */ - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX_DN); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX_DN); - - /* KONRAD FIX ME : check in case there is a ckt and grp block */ - } - - sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_TX); - sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_SENT); - sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_RX); - sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_RX_DN); - sngss7_clear_ckt_flag(sngss7_info, FLAG_INF_TX); - sngss7_clear_ckt_flag(sngss7_info, FLAG_INF_SENT); - sngss7_clear_ckt_flag(sngss7_info, FLAG_INF_RX); - sngss7_clear_ckt_flag(sngss7_info, FLAG_INF_RX_DN); - sngss7_clear_ckt_flag(sngss7_info, FLAG_FULL_NUMBER); - - /* check whether the ftdm channel is in a state to accept a call */ - switch (ftdmchan->state) { - /**************************************************************************/ - case (FTDM_CHANNEL_STATE_DOWN): /* only state it is valid to get IAM (except if there is glare */ - - /* check if there is any reason why we can't use this channel */ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) { - /* channel is already requested for use by the ftdm core */ - goto handle_glare; - } else if(ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { - /* channel is not inuse but we can't open it...fail the call */ - SS7_ERROR("Failed to open span: %d, chan: %d\n", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id); - - /* set the flag to indicate this hangup is started from the local side */ - sngss7_set_ckt_flag(sngss7_info, FLAG_LOCAL_REL); - - ftdmchan->caller_data.hangup_cause = 41; - - /* move the state to CANCEL */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); - - } else { - - /* fill in the channels SS7 Stack information */ - sngss7_info->suInstId = get_unique_id(); - sngss7_info->spInstId = spInstId; - - /* fill in calling party information */ - if (siConEvnt->cgPtyNum.eh.pres) { - if (siConEvnt->cgPtyNum.addrSig.pres) { - /* fill in cid_num */ - copy_tknStr_from_sngss7(siConEvnt->cgPtyNum.addrSig, - ftdmchan->caller_data.cid_num.digits, - siConEvnt->cgPtyNum.oddEven); - - /* fill in cid Name */ - ftdm_set_string(ftdmchan->caller_data.cid_name, ftdmchan->caller_data.cid_num.digits); - - /* fill in ANI */ - ftdm_set_string(ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.cid_num.digits); - } - else { - if (g_ftdm_sngss7_data.cfg.force_inr) { - sngss7_set_ckt_flag(sngss7_info, FLAG_INR_TX); - sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_SENT); - } - } - - if (siConEvnt->cgPtyNum.scrnInd.pres) { - /* fill in the screening indication value */ - ftdmchan->caller_data.screen = siConEvnt->cgPtyNum.scrnInd.val; - } - - if (siConEvnt->cgPtyNum.presRest.pres) { - /* fill in the presentation value */ - ftdmchan->caller_data.pres = siConEvnt->cgPtyNum.presRest.val; - } - } else { - if (g_ftdm_sngss7_data.cfg.force_inr) { - sngss7_set_ckt_flag(sngss7_info, FLAG_INR_TX); - sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_SENT); - } - - SS7_INFO_CHAN(ftdmchan,"No Calling party (ANI) information in IAM!%s\n", " "); - } - - /* fill in called party infomation */ - if (siConEvnt->cdPtyNum.eh.pres) { - if (siConEvnt->cdPtyNum.addrSig.pres) { - /* fill in the called number/dnis */ - copy_tknStr_from_sngss7(siConEvnt->cdPtyNum.addrSig, - ftdmchan->caller_data.dnis.digits, - siConEvnt->cdPtyNum.oddEven); - } - } else { - SS7_INFO_CHAN(ftdmchan,"No Called party (DNIS) information in IAM!%s\n", " "); - } - copy_NatureOfConnection_from_sngss7(ftdmchan, &siConEvnt->natConInd); - copy_fwdCallInd_hex_from_sngss7(ftdmchan, &siConEvnt->fwdCallInd); - copy_access_transport_from_sngss7(ftdmchan, &siConEvnt->accTrnspt); - copy_ocn_from_sngss7(ftdmchan, &siConEvnt->origCdNum); - copy_redirgNum_from_sngss7(ftdmchan, &siConEvnt->redirgNum); - copy_redirgInfo_from_sngss7(ftdmchan, &siConEvnt->redirInfo); - copy_genNmb_from_sngss7(ftdmchan, &siConEvnt->genNmb); - - copy_cgPtyCat_from_sngss7(ftdmchan, &siConEvnt->cgPtyCat); - copy_cdPtyNum_from_sngss7(ftdmchan, &siConEvnt->cdPtyNum); - - /* fill in the TMR/bearer capability */ - if (siConEvnt->txMedReq.eh.pres) { - if (siConEvnt->txMedReq.trMedReq.pres) { - /* fill in the bearer type */ - ftdmchan->caller_data.bearer_capability = siConEvnt->txMedReq.trMedReq.val; - } - } else { - SS7_DEBUG_CHAN(ftdmchan,"No TMR/Bearer Cap information in IAM!%s\n", " "); - } - - /* add any special variables for the dialplan */ - sprintf(var, "%d", siConEvnt->cgPtyNum.natAddrInd.val); - sngss7_add_var(sngss7_info, "ss7_clg_nadi", var); - - /* Retrieve the Location Number if present (see ITU Q.763, 3.30) */ - if (siConEvnt->cgPtyNum1.eh.pres) { - if (siConEvnt->cgPtyNum1.addrSig.pres) { - /* fill in the ss7 location address number */ - copy_tknStr_from_sngss7(siConEvnt->cgPtyNum1.addrSig, var, siConEvnt->cgPtyNum1.oddEven); - sngss7_add_var(sngss7_info, "ss7_loc_digits", var); - } - - if (siConEvnt->cgPtyNum1.scrnInd.pres) { - /* fill in the screening indication value */ - sprintf(var, "%d", siConEvnt->cgPtyNum1.scrnInd.val); - sngss7_add_var(sngss7_info, "ss7_loc_screen_ind", var); - } - - if (siConEvnt->cgPtyNum1.presRest.pres) { - /* fill in the presentation value */ - sprintf(var, "%d", siConEvnt->cgPtyNum1.presRest.val); - sngss7_add_var(sngss7_info, "ss7_loc_pres_ind", var); - } - - if (siConEvnt->cgPtyNum1.natAddrInd.pres) { - sprintf(var, "%d", siConEvnt->cgPtyNum1.natAddrInd.val); - sngss7_add_var(sngss7_info, "ss7_loc_nadi", var); - } - } else { - SS7_DEBUG_CHAN(ftdmchan, "No Location Number information in IAM%s\n", " "); - } - - sprintf(var, "%d", sngss7_info->circuit->cic); - sngss7_add_var(sngss7_info, "ss7_cic", var); - - - sprintf(var, "%d", g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].dpc ); - sngss7_add_var(sngss7_info, "ss7_opc", var); - - if (siConEvnt->callRef.callId.pres) { - ftdmchan->caller_data.call_reference = (unsigned int)siConEvnt->callRef.callId.val; - } else { - ftdmchan->caller_data.call_reference = 0; - } - - if (sngss7_info->circuit->transparent_iam) { - sngss7_save_iam(ftdmchan, siConEvnt); - } - - /* check if a COT test is requested */ - if ((siConEvnt->natConInd.eh.pres) && - (siConEvnt->natConInd.contChkInd.pres) && - (siConEvnt->natConInd.contChkInd.val)) { - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Found COT Request\n", sngss7_info->circuit->cic); - - /* tell the core to loop the channel */ - ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_LOOP, NULL); - - /* move to in loop state */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP); - } else { - /* set the state of the channel to collecting...the rest is done by the chan monitor */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); - } - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx IAM clg = \"%s\" (NADI=%d), cld = \"%s\" (NADI=%d)\n", - sngss7_info->circuit->cic, - ftdmchan->caller_data.cid_num.digits, - siConEvnt->cgPtyNum.natAddrInd.val, - ftdmchan->caller_data.dnis.digits, - siConEvnt->cdPtyNum.natAddrInd.val); - } /* if (channel is usable */ - - break; - /**************************************************************************/ - case (FTDM_CHANNEL_STATE_DIALING): - case (FTDM_CHANNEL_STATE_TERMINATING): - case (FTDM_CHANNEL_STATE_HANGUP): - case (FTDM_CHANNEL_STATE_HANGUP_COMPLETE): -handle_glare: - /* the core already has plans for this channel...glare */ - SS7_INFO_CHAN(ftdmchan, "Got IAM on channel that is already inuse (state=%s|inuse=%c)...glare!\n", - ftdm_channel_state2str (ftdmchan->state), - ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE) ? 'Y' : 'N'); - - /* save the info so that we can use it later on */ - sngss7_info->glare.spInstId = spInstId; - sngss7_info->glare.circuit = circuit; - memcpy(&sngss7_info->glare.iam, siConEvnt, sizeof(*siConEvnt)); - - if (!(sngss7_test_ckt_flag(sngss7_info, FLAG_GLARE))) { - /* glare, throw the flag */ - sngss7_set_ckt_flag(sngss7_info, FLAG_GLARE); - - /* setup the hangup cause */ - ftdmchan->caller_data.hangup_cause = 34; /* Circuit Congrestion */ - - /* move the state of the channel to Terminating to end the call - in TERMINATING state, the release cause is set to REMOTE_REL - in any means. So we don't have to set the release reason here. - */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - } - break; - /**************************************************************************/ - default: /* should not have gotten an IAM while in this state */ - SS7_ERROR_CHAN(ftdmchan, "Got IAM on channel in invalid state(%s)...reset!\n", ftdm_channel_state2str (ftdmchan->state)); - - /* throw the TX reset flag */ - if (!sngss7_tx_reset_status_pending(sngss7_info)) { - sngss7_tx_reset_restart(sngss7_info); - sngss7_set_ckt_flag (sngss7_info, FLAG_REMOTE_REL); - - /* go to RESTART */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - } - break; - /**************************************************************************/ - } /* switch (ftdmchan->state) */ - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCnStEvnt *siCnStEvnt, uint8_t evntType) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; - - ftdm_running_return(FTDM_FAIL); - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - switch (evntType) { - /**************************************************************************/ - case (ADDRCMPLT): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx ACM\n", sngss7_info->circuit->cic); - - switch (ftdmchan->state) { - /**********************************************************************/ - case FTDM_CHANNEL_STATE_DIALING: - /* KONRAD: should we confirm the instance ids ? */ - - /* need to grab the sp instance id */ - sngss7_info->spInstId = spInstId; - - if ((siCnStEvnt->optBckCalInd.eh.pres) && - (siCnStEvnt->optBckCalInd.inbndInfoInd.pres)) { - - if (siCnStEvnt->optBckCalInd.inbndInfoInd.val) { - /* go to PROGRESS_MEDIA */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); - } else { - /* go to PROGRESS */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); - } /* if (inband) */ - } else { - /* go to PROGRESS_MEDIA */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); - } - - break; - /**********************************************************************/ - default: /* incorrect state...reset the CIC */ - SS7_ERROR_CHAN(ftdmchan, "RX ACM in invalid state :%s...resetting CIC\n", - ftdm_channel_state2str (ftdmchan->state)); - - /* throw the TX reset flag */ - if (!sngss7_tx_reset_status_pending(sngss7_info)) { - sngss7_tx_reset_restart(sngss7_info); - sngss7_set_ckt_flag (sngss7_info, FLAG_REMOTE_REL); - - /* go to RESTART */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - } - break; - /**********************************************************************/ - } /* switch (ftdmchan->state) */ - - break; - /**************************************************************************/ - case (MODIFY): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx MODIFY\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (MODCMPLT): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx MODIFY-COMPLETE\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (MODREJ): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx MODIFY-REJECT\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (PROGRESS): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx CPG\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (FRWDTRSFR): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx FOT\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (INFORMATION): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx INF\n", sngss7_info->circuit->cic); - - SS7_DEBUG_CHAN (ftdmchan, "Cancelling T.39 timer %s\n", " "); - /* check if t39 is active */ - if (sngss7_info->t39.hb_timer_id) { - ftdm_sched_cancel_timer (sngss7_info->t39.sched, sngss7_info->t39.hb_timer_id); - SS7_DEBUG_CHAN (ftdmchan, "T.39 timer has been cancelled upon receiving INF message %s\n", " "); - } - - sngss7_set_ckt_flag(sngss7_info, FLAG_INF_RX_DN); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE); - - break; - /**************************************************************************/ - case (INFORMATREQ): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx INR\n", sngss7_info->circuit->cic); - - ft_to_sngss7_inf(ftdmchan, siCnStEvnt); - - sngss7_set_ckt_flag(sngss7_info, FLAG_INR_RX); - - break; - /**************************************************************************/ - case (SUBSADDR): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx SAM\n", sngss7_info->circuit->cic); - - /* check the channel state */ - switch (ftdmchan->state) { - /**********************************************************************/ - case (FTDM_CHANNEL_STATE_COLLECT): - - /* confirm that the event contains the subsquent number field */ - if (siCnStEvnt->subNum.eh.pres && siCnStEvnt->subNum.addrSig.pres) { - /* add the digits to the ftdm channel variable */ - append_tknStr_from_sngss7(siCnStEvnt->subNum.addrSig, - ftdmchan->caller_data.dnis.digits, - siCnStEvnt->subNum.oddEven); - SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Rx SAM (digits = %s)\n", sngss7_info->circuit->cic, - ftdmchan->caller_data.dnis.digits); - } else { - SS7_INFO_CHAN(ftdmchan,"No Called party (DNIS) information in SAM!%s\n", " "); - } - - /* go to idle so that collect state is processed again */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE); - - break; - /**********************************************************************/ - default: - SS7_ERROR_CHAN(ftdmchan, "RX SAM in invalid state :%s...ignoring\n", - ftdm_channel_state2str (ftdmchan->state)); - break; - /**********************************************************************/ - } /* switch (ftdmchan->state) */ - - break; - /**************************************************************************/ - case (EXIT): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx EXIT\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (NETRESMGT): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx NRM\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (IDENTREQ): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx IDR\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (IDENTRSP): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx IRS\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (MALCLLPRNT): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx MALICIOUS CALL\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (CHARGE): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx CRG\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (TRFFCHGE): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx CRG-TARIFF\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (CHARGEACK): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx CRG-ACK\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (CALLOFFMSG): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx CALL-OFFER\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (LOOPPRVNT): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx LOP\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (TECT_TIMEOUT): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx ECT-Timeout\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (RINGSEND): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx RINGING-SEND\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (CALLCLEAR): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx CALL-LINE Clear\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (PRERELEASE): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx PRI\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (APPTRANSPORT): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx APM\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (OPERATOR): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx OPERATOR\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (METPULSE): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx METERING-PULSE\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (CLGPTCLR): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx CALLING_PARTY_CLEAR\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (SUBDIRNUM): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx SUB-DIR\n", sngss7_info->circuit->cic); - break; -#ifdef SANGOMA_SPIROU - case (CHARGE_ACK): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx TXA\n", sngss7_info->circuit->cic); - break; - case (CHARGE_UNIT): - { - uint32_t charging_unit = 0; - uint32_t msg_num = 0; - char val[3]; - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx ITX\n", sngss7_info->circuit->cic); - - memset(val, '\0', sizeof(val)); - - if (siCnStEvnt->chargUnitNum.eh.pres == PRSNT_NODEF && - siCnStEvnt->chargUnitNum.chargUnitNum.pres == PRSNT_NODEF) { - - charging_unit = siCnStEvnt->chargUnitNum.chargUnitNum.val; - } - - if (siCnStEvnt->msgNum.eh.pres == PRSNT_NODEF && - siCnStEvnt->msgNum.msgNum.pres == PRSNT_NODEF) { - - msg_num = siCnStEvnt->msgNum.msgNum.val; - } - - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Charging Unit:%d Msg Num:%d\n", charging_unit, msg_num); - - sprintf(val, "%d", charging_unit); - sngss7_add_var(sngss7_info, "ss7_itx_charge_unit", val); - - sprintf(val, "%d", msg_num); - sngss7_add_var(sngss7_info, "ss7_itx_msg_num", val); - - if (sngss7_info->circuit->itx_auto_reply) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Auto-reply with TXA msg\n"); - ft_to_sngss7_txa (ftdmchan); - } - } - break; -#endif - /**************************************************************************/ - default: - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Unknown Msg\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - } - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; - - ftdm_running_return(FTDM_FAIL); - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check whether the ftdm channel is in a state to accept a call */ - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx ANM\n", sngss7_info->circuit->cic); - - /* go to UP */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); - - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_DIALING: - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx CON\n", sngss7_info->circuit->cic); - - /* go to UP */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); - - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - - /* already hangup complete, just ignore it */ - /* - * i.e. collision REL & ANM - * IAM -> - * <- ACM - * REL -> <- ANM (if REL gets processed first, ANM needs to be ignored) - * <- RLC - */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx ANM/CON Ignoring it because we already hung up\n", sngss7_info->circuit->cic); - - break; - /**************************************************************************/ - default: /* incorrect state...reset the CIC */ - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx ANM/CON\n", sngss7_info->circuit->cic); - - /* throw the TX reset flag */ - if (!sngss7_tx_reset_status_pending(sngss7_info)) { - sngss7_tx_reset_restart(sngss7_info); - sngss7_set_ckt_flag (sngss7_info, FLAG_REMOTE_REL); - - /* go to RESTART */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - } - - break; - /**************************************************************************/ - } - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; - - ftdm_running_return(FTDM_FAIL); - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx REL cause=%d\n", - sngss7_info->circuit->cic, - siRelEvnt->causeDgn.causeVal.val); - - /* check whether the ftdm channel is in a state to release a call */ - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_DIALING: - - /* pass the release code up to FTDM */ - if (siRelEvnt->causeDgn.causeVal.pres) { - ftdmchan->caller_data.hangup_cause = siRelEvnt->causeDgn.causeVal.val; - } else { - SS7_ERROR("REL does not have a cause code!\n"); - ftdmchan->caller_data.hangup_cause = 0; - } - - /* this is a remote hangup request */ - sngss7_set_ckt_flag(sngss7_info, FLAG_REMOTE_REL); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL); - /* move the state of the channel to CANCEL to end the call */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_RING: - case FTDM_CHANNEL_STATE_RINGING: - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - case FTDM_CHANNEL_STATE_UP: - - /* pass the release code up to FTDM */ - if (siRelEvnt->causeDgn.causeVal.pres) { - ftdmchan->caller_data.hangup_cause = siRelEvnt->causeDgn.causeVal.val; - } else { - SS7_ERROR("REL does not have a cause ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL);code!\n"); - ftdmchan->caller_data.hangup_cause = 0; - } - - /* this is a remote hangup request */ - sngss7_set_ckt_flag(sngss7_info, FLAG_REMOTE_REL); - - /* move the state of the channel to TERMINATING to end the call */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - /* ITU Q.764 2.3.1 e) - * Collision of release messages - * - * ITU Q.784 Test Number 3.8 - * Collision of REL messages - */ - SS7_DEBUG_CHAN(ftdmchan, "Collision of REL messages. Rx REL while waiting for RLC.%s\n", " "); - if (sngss7_test_ckt_flag(sngss7_info, FLAG_LOCAL_REL) && - !sngss7_test_ckt_flag (sngss7_info, FLAG_REMOTE_REL)) { - /* locally requested hangup completed, wait for remote RLC */ - /* need to perform remote release */ - - /* this is also a remote hangup request */ - sngss7_set_ckt_flag(sngss7_info, FLAG_REMOTE_REL); - - /* send out the release complete */ - ft_to_sngss7_rlc (ftdmchan); - } else { - SS7_DEBUG_CHAN(ftdmchan, "Collision of REL messages - resetting state.%s\n", " "); - ft_to_sngss7_rlc (ftdmchan); - goto rel_ind_reset; - } - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_IN_LOOP: - - /* inform the core to unloop the channel*/ - ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL); - - /* since we need to acknowledge the hang up set the flag for remote release */ - sngss7_set_ckt_flag(sngss7_info, FLAG_REMOTE_REL); - - /* go to hangup complete to send the RLC */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); - - /* save the call info for the RLC */ - sngss7_info->suInstId = get_unique_id(); - sngss7_info->spInstId = spInstId; - - break; - /**************************************************************************/ - default: - -rel_ind_reset: - /* throw the TX reset flag */ - if (!sngss7_tx_reset_status_pending(sngss7_info)) { - sngss7_set_ckt_flag (sngss7_info, FLAG_REMOTE_REL); - sngss7_tx_reset_restart(sngss7_info); - - /* go to RESTART */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - } - break; - /**************************************************************************/ - } /* switch (ftdmchan->state) */ - - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; - - ftdm_running_return(FTDM_FAIL); - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx RLC\n", sngss7_info->circuit->cic); - - /* check whether the ftdm channel is in a state to accept a call */ - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - - /* go to DOWN */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_DOWN: - /* do nothing, just drop the message */ - break; - /**************************************************************************/ - default: - /* KONRAD: should just stop the call...but a reset is easier for now (since it does hangup the call) */ - - /* go to RESTART */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - - break; - /**************************************************************************/ - } - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiInfoEvnt *siInfoEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; - - ftdm_running_return(FTDM_FAIL); - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx DATA IND\n", sngss7_info->circuit->cic); - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; - - ftdm_running_return(FTDM_FAIL); - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx FAC\n", sngss7_info->circuit->cic); - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; - - ftdm_running_return(FTDM_FAIL); - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx FAC-CON\n", sngss7_info->circuit->cic); - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; - - ftdm_running_return(FTDM_FAIL); - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx USER-USER msg\n", sngss7_info->circuit->cic); - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_susp_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiSuspEvnt *siSuspEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; - - ftdm_running_return(FTDM_FAIL); - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Call-Suspend msg\n", sngss7_info->circuit->cic); - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_resm_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiResmEvnt *siResmEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; - - ftdm_running_return(FTDM_FAIL); - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Call-Resume msg\n", sngss7_info->circuit->cic); - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - ftdm_running_return(FTDM_FAIL); - - /* confirm that the circuit is active on our side otherwise move to the next circuit */ - if (!sngss7_test_flag(&g_ftdm_sngss7_data.cfg.isupCkt[circuit], SNGSS7_ACTIVE)) { - SS7_ERROR("[CIC:%d]Rx %s but circuit is not active yet, skipping!\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - return FTDM_FAIL; - } - - switch (evntType) { - /**************************************************************************/ - case SIT_STA_REATTEMPT: /* reattempt indication */ - handle_reattempt(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_ERRORIND: /* error indication */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CONTCHK: /* continuity check */ - handle_cot_start(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CONTREP: /* continuity report */ - handle_cot(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_STPCONTIN: /* stop continuity */ - handle_cot_stop(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CGQRYRSP: /* circuit grp query response from far end forwarded to upper layer by ISUP */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CONFUSION: /* confusion */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_LOOPBACKACK: /* loop-back acknowledge */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CIRRSRVREQ: /* circuit reservation request */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CIRRSRVACK: /* circuit reservation acknowledgement */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CIRBLOREQ: /* circuit blocking request */ - handle_blo_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRBLORSP: /* circuit blocking response */ - handle_blo_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRUBLREQ: /* circuit unblocking request */ - handle_ubl_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRUBLRSP: /* circuit unblocking response */ - handle_ubl_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRRESREQ: /* circuit reset request - RSC */ - handle_rsc_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRLOCRES: /* reset initiated locally by the software */ - handle_local_rsc_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRRESRSP: /* circuit reset response */ - handle_rsc_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CGBREQ: /* CGB request */ - handle_cgb_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CGUREQ: /* CGU request */ - handle_cgu_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CGQRYREQ: /* circuit group query request */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CGBRSP: /* mntc. oriented CGB response */ - SS7_INFO(" Rx CGBA \n"); - break; - /**************************************************************************/ - case SIT_STA_CGURSP: /* mntc. oriented CGU response */ - /*SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));*/ - SS7_INFO(" Rx CGUA \n"); - break; - /**************************************************************************/ - case SIT_STA_GRSREQ: /* circuit group reset request */ - handle_grs_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRUNEQPD: /* circuit unequipped indication */ - handle_ucic(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_GRSRSP: /* circuit group reset response */ - handle_grs_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_PAUSEIND: /* pause indication */ - handle_pause(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_RESUMEIND: /* resume indication */ - handle_resume(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_USRPARTA: /* user part available */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_RMTUSRUNAV: /* remote user not available */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_MTPCONG0: /* congestion indication level 0 */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_MTPCONG1: /* congestion indication level 1 */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_MTPCONG2: /* congestion indication level 2 */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_MTPCONG3: /* congestion indication level 3 */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_MTPSTPCONG: /* stop congestion indication level 0 */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CIRLOCALBLOIND: /* Mngmt local blocking */ - handle_local_blk(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRLOCALUBLIND: /* Mngmt local unblocking */ - handle_local_ubl(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_OVERLOAD: /* Overload */ - handle_olm_msg(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_LMCGBREQ: /* when LM requests ckt grp blocking */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_LMCGUREQ: /* when LM requests ckt grp unblocking */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_LMGRSREQ: /* when LM requests ckt grp reset */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CGBINFOIND: /* circuit grp blking ind , no resp req */ -/* handle_cgb_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);*/ - break; - /**************************************************************************/ - case SIT_STA_LMCQMINFOREQ: /* when LM requests ckt grp query */ -// SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CIRLOCGRS: /* group reset initiated locally by the software */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - default: - SS7_INFO("[SNG-CC] Received Unknown indication %d\n", evntType); - break; - } /* switch (evntType) */ - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; - -} - -/******************************************************************************/ -ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - ftdm_running_return(FTDM_FAIL); - - /* confirm that the circuit is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } else { - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - if (sngss7_test_ckt_flag(sngss7_info, FLAG_GLARE)) { - /* the glare flag is already up so it was caught ... do nothing */ - SS7_DEBUG_CHAN(ftdmchan, "Glare flag is already up...nothing to do!%s\n", " "); - } else { - int bHangup = 0; - SS7_DEBUG_CHAN(ftdmchan, "Glare flag is not up yet...indicating glare from reattempt!%s\n", " "); - /* glare, throw the flag */ - sngss7_set_ckt_flag(sngss7_info, FLAG_GLARE); - - /* clear any existing glare data from the channel */ - memset(&sngss7_info->glare, 0x0, sizeof(sngss7_glare_data_t)); - - if (g_ftdm_sngss7_data.cfg.glareResolution == SNGSS7_GLARE_DOWN) { - /* If I'm in DOWN mode, I will always hangup my call. */ - bHangup = 1; - } - else if (g_ftdm_sngss7_data.cfg.glareResolution == SNGSS7_GLARE_PC) { - /* I'm in PointCode mode. - Case 1: My point code is higher than the other side. - If the CIC number is even, I'm trying to control. - If the CIC number is odd, I'll hangup my call and back off. - Case 2: My point code is lower than the other side. - If the CIC number is odd, I'm trying to control. - If the CIC number is even, I'll hangup my call and back off. - */ - if( g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].spc > g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].dpc ) - { - if ((sngss7_info->circuit->cic % 2) == 1 ) { - bHangup = 1; - } - } else { - if( (sngss7_info->circuit->cic % 2) == 0 ) { - bHangup = 1; - } - } - } - else { - /* If I'm in CONTROL mode, I will not hangup my call. */ - bHangup = 0; - } - - if (bHangup) { - /* setup the hangup cause */ - ftdmchan->caller_data.hangup_cause = 34; /* Circuit Congrestion */ - - /* move the state of the channel to Terminating to end the call - in TERMINATING state, the release cause is set to REMOTE_REL - in any means. So we don't have to set the release reason here. - */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - } - } - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - int infId; - int i; - - ftdm_running_return(FTDM_FAIL); - - /* extract the affected infId from the circuit structure */ - infId = g_ftdm_sngss7_data.cfg.isupCkt[circuit].infId; - - /* set the interface to paused */ - sngss7_set_flag(&g_ftdm_sngss7_data.cfg.isupIntf[infId], SNGSS7_PAUSED); - - /* go through all the circuits now and find any other circuits on this infId */ - i = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) { - - /* check that the infId matches and that this is not a siglink */ - if ((g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) && - (g_ftdm_sngss7_data.cfg.isupCkt[i].type == SNG_CKT_VOICE)) { - - /* confirm that the circuit is active on our side otherwise move to the next circuit */ - if (!sngss7_test_flag(&g_ftdm_sngss7_data.cfg.isupCkt[i], SNGSS7_ACTIVE)) { - SS7_ERROR("[CIC:%d]Circuit is not active yet, skipping!\n",g_ftdm_sngss7_data.cfg.isupCkt[i].cic); - i++; - continue; - } - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - i++; - continue; - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if the circuit is fully started */ - if (ftdm_test_flag(ftdmchan->span, FTDM_SPAN_IN_THREAD)) { - SS7_DEBUG_CHAN(ftdmchan, "Rx PAUSE%s\n", ""); - /* set the pause flag on the channel */ - sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_PAUSED); - - /* clear the resume flag on the channel */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_RESUME); - } - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - } /* if (g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) */ - - /* move to the next circuit */ - i++; - - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) */ - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - int infId; - int i; - - ftdm_running_return(FTDM_FAIL); - - /* extract the affect infId from the circuit structure */ - infId = g_ftdm_sngss7_data.cfg.isupCkt[circuit].infId; - - /* set the interface to resumed */ - sngss7_clear_flag(&g_ftdm_sngss7_data.cfg.isupIntf[infId], SNGSS7_PAUSED); - - /* go through all the circuits now and find any other circuits on this infId */ - i = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) { - - /* check that the infId matches and that this is not a siglink */ - if ((g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) && - (g_ftdm_sngss7_data.cfg.isupCkt[i].type == SNG_CKT_VOICE)) { - - /* confirm that the circuit is active on our side otherwise move to the next circuit */ - if (!sngss7_test_flag(&g_ftdm_sngss7_data.cfg.isupCkt[i], SNGSS7_ACTIVE)) { - ftdm_log(FTDM_LOG_DEBUG, "[CIC:%d]Circuit is not active yet, skipping!\n",g_ftdm_sngss7_data.cfg.isupCkt[i].cic); - i++; - continue; - } - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - i++; - continue; - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* only resume if we are paused */ - if (sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_PAUSED)) { - SS7_DEBUG_CHAN(ftdmchan, "Rx RESUME%s\n", ""); - - /* set the resume flag on the channel */ - sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_RESUME); - - /* clear the paused flag */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_PAUSED); - } - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - } /* if (g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) */ - - /* move to the next circuit */ - i++; - - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) */ - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_cot_start(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - ftdm_running_return(FTDM_FAIL); - - /* confirm that the circuit is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } else { - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* open the channel if it is not open */ - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { - if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { - SS7_ERROR("Failed to open CIC %d for CCR test!\n", sngss7_info->circuit->cic); - /* KONRAD FIX ME */ - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - } - - /* tell the core to loop the channel */ - ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_LOOP, NULL); - - /* switch to the IN_LOOP state */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_cot_stop(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - ftdm_running_return(FTDM_FAIL); - - /* confirm that the circuit is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } else { - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* tell the core to stop looping the channel */ - ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL); - - /* exit out of the LOOP state to the last state */ - ftdm_set_state(ftdmchan, ftdmchan->last_state); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - ftdm_running_return(FTDM_FAIL); - - /* confirm that the circuit is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } else { - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - switch (ftdmchan->state) { - /**************************************************************************/ - case (FTDM_CHANNEL_STATE_IN_LOOP): - /* tell the core to stop looping the channel */ - ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL); - - /* exit out of the LOOP state and go to collect */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); - - break; - /**************************************************************************/ - default: - /* exit out of the LOOP state to the last state */ - ftdm_set_state(ftdmchan, ftdmchan->last_state); - - break; - /**************************************************************************/ - } /* switch (ftdmchan->state) */ - - if ( (siStaEvnt->contInd.eh.pres > 0) && (siStaEvnt->contInd.contInd.pres > 0)) { - SS7_INFO("Continuity Test result for CIC = %d (span %d, chan %d) is: \"%s\"\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - g_ftdm_sngss7_data.cfg.isupCkt[circuit].span, - g_ftdm_sngss7_data.cfg.isupCkt[circuit].chan, - (siStaEvnt->contInd.contInd.val) ? "PASS" : "FAIL"); - } else { - SS7_ERROR("Recieved Continuity report containing no results!\n"); - } - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - ftdm_running_return(FTDM_FAIL); - - /* confirm that the circuit is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } else { - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if the circuit is already blocked or not */ - if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) { - SS7_WARN("Received BLO on circuit that is already blocked!\n"); - } - - /* throw the ckt block flag */ - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN); - - /* set the channel to suspended state */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_blo_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - ftdm_running_return(FTDM_FAIL); - - /* confirm that the circuit is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } else { - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* KONRAD FIX ME */ - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - ftdm_running_return(FTDM_FAIL); - - /* confirm that the circuit is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } else { - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if the channel is blocked */ - if (!(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) && !sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) { - SS7_WARN("Received UBL on circuit that is not blocked! span= %d, chan= %d , flag = %x \n", g_ftdm_sngss7_data.cfg.isupCkt[circuit].span, g_ftdm_sngss7_data.cfg.isupCkt[circuit].chan,sngss7_info->blk_flags ); - } - - /* throw the unblock flag */ - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_UNBLK_RX); - - /* clear the block flag */ - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX_DN); - - /* set the channel to suspended state */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - /* confirm that the circuit is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } else { - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - } - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - ftdm_running_return(FTDM_FAIL); - - /* confirm that the circuit is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } else { - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* throw the reset flag */ - sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_RX); - - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_RESTART: - - /* go to idle so that we can redo the restart state*/ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE); - - break; - /**************************************************************************/ - default: - - /* set the state of the channel to restart...the rest is done by the chan monitor */ - sngss7_set_ckt_flag(sngss7_info, FLAG_REMOTE_REL); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - break; - /**************************************************************************/ - } - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_local_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - ftdm_running_return(FTDM_FAIL); - - /* confirm that the circuit is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } else { - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - } - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* throw the reset flag */ - sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_RX); - - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_RESTART: - - /* go to idle so that we can redo the restart state*/ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE); - - break; - /**************************************************************************/ - default: - - /* set the state of the channel to restart...the rest is done by the chan monitor */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - break; - /**************************************************************************/ - } - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - ftdm_running_return(FTDM_FAIL); - - /* confirm that the circuit is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } else { - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - switch (ftdmchan->state) { - /**********************************************************************/ - case FTDM_CHANNEL_STATE_RESTART: - - if ( sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX) ) { - /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */ - sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP); - - /* go to DOWN */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } else { - SS7_ERROR("Received RSC-RLC but we're not waiting on a RSC-RLC on CIC #%d, dropping\n", sngss7_info->circuit->cic); - } - - break; - /**********************************************************************/ - case FTDM_CHANNEL_STATE_DOWN: - - /* do nothing, just drop the message */ - SS7_DEBUG("Receveived RSC-RLC in down state, dropping\n"); - - break; - /**********************************************************************/ - case FTDM_CHANNEL_STATE_TERMINATING: - case FTDM_CHANNEL_STATE_HANGUP: - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - - /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */ - sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP); - - /* go to DOWN */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - - break; - /**********************************************************************/ - default: - /* ITU Q764-2.9.5.1.c -> release the circuit */ - if ((siStaEvnt != NULL) && - (siStaEvnt->causeDgn.eh.pres ==PRSNT_NODEF) && - (siStaEvnt->causeDgn.causeVal.pres == PRSNT_NODEF)) { - ftdmchan->caller_data.hangup_cause = siStaEvnt->causeDgn.causeVal.val; - } else { - ftdmchan->caller_data.hangup_cause = 98; /* Message not compatiable with call state */ - } - - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - break; - /**********************************************************************/ - } - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} -/******************************************************************************/ -ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_span_data_t *sngss7_span = NULL; - int range = 0; - - ftdm_running_return(FTDM_FAIL); - - /* confirm that the circuit is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } else { - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - } - - /* extract the range value from the event structure */ - if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.range.pres == PRSNT_NODEF)) { - range = siStaEvnt->rangStat.range.val; - } else { - SS7_ERROR("Received GRS with no range value on CIC = %d\n", sngss7_info->circuit->cic); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - /* fill in the span structure for this circuit */ - sngss7_span = ftdmchan->span->signal_data; - if (sngss7_info->rx_grs.range) { - SS7_CRITICAL("Cannot handle another GRS on CIC = %d\n", sngss7_info->circuit->cic); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - sngss7_info->rx_grs.circuit = circuit; - sngss7_info->rx_grs.range = range; - - ftdm_set_flag(sngss7_span, SNGSS7_RX_GRS_PENDING); - /* the reset will be started in the main thread by "check_if_rx_grs_started" */ - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_span_data_t *sngss7_span = NULL; - int range = 0; - - ftdm_running_return(FTDM_FAIL); - - /* confirm that the circuit is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } else { - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - } - - /* extract the range value from the event structure */ - if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.range.pres == PRSNT_NODEF)) { - range = siStaEvnt->rangStat.range.val; - } else { - SS7_ERROR("Received GRA with no range value on CIC = %d\n", sngss7_info->circuit->cic); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - /* fill in the span structure for this circuit */ - sngss7_span = ftdmchan->span->signal_data; - if (sngss7_info->rx_gra.range) { - SS7_ERROR("Cannot handle another GRA on CIC = %d\n", sngss7_info->circuit->cic); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - sngss7_info->rx_gra.circuit = circuit; - sngss7_info->rx_gra.range = range; - - /* check if there is a cause value in the GRA */ - if ((siStaEvnt != NULL) && - (siStaEvnt->causeDgn.eh.pres == PRSNT_NODEF) && - (siStaEvnt->causeDgn.causeVal.pres == PRSNT_NODEF)) { - - sngss7_info->rx_gra.cause = siStaEvnt->causeDgn.causeVal.val; - } - - ftdm_set_flag(sngss7_span, SNGSS7_RX_GRA_PENDING); - - /* the reset will be started in the main thread by "check_if_rx_gra_started" */ - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_local_blk(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - ftdm_running_return(FTDM_FAIL); - - /* confirm that the circuit is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } else { - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if the circuit is already blocked or not */ - if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX)) { - SS7_WARN("Received local BLO on circuit that is already blocked!\n"); - } - - /* throw the ckt block flag */ - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX); - - /* set the channel to suspended state */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_local_ubl(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - ftdm_running_return(FTDM_FAIL); - - /* confirm that the circuit is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } else { - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if the circuit is blocked or not */ - if (!sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX)) { - SS7_WARN("Received local UBL on circuit that is not blocked!\n"); - } - - /* throw the ckt unblock flag */ - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX); - - /* set the channel to suspended state */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - ftdm_iterator_t *iter = NULL; - ftdm_iterator_t *curr = NULL; - sngss7_chan_data_t *sngss7_info = NULL; - sngss7_chan_data_t *cinfo = NULL; - sngss7_span_data_t *sngss7_span = NULL; - ftdm_channel_t *ftdmchan = NULL; - - ftdm_running_return(FTDM_FAIL); - - /* confirm that the circuit is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } else { - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - } - - /* find out if the cic belongs to one of our GRS requests, if so, - * all circuits in the request must be blocked */ - sngss7_span = ftdmchan->span->signal_data; - iter = ftdm_span_get_chan_iterator(ftdmchan->span, NULL); - curr = iter; - for (curr = iter; curr; curr = ftdm_iterator_next(curr)) { - ftdm_channel_t *fchan = ftdm_iterator_current(curr); - - ftdm_channel_lock(fchan); - - cinfo = fchan->call_data; - if (circuit == cinfo->tx_grs.circuit) { - cinfo->ucic.circuit = cinfo->tx_grs.circuit; - cinfo->ucic.range = cinfo->tx_grs.range; - ftdm_set_flag(sngss7_span, SNGSS7_UCIC_PENDING); - - SS7_WARN("Set span SNGSS7_UCIC_PENDING for ISUP circuit = %d!\n", circuit); - - ftdm_channel_unlock(fchan); - - goto done; - } - - ftdm_channel_unlock(fchan); - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* throw the ckt block flag */ - SS7_DEBUG("Set FLAG_CKT_UCIC_BLOCK for ISUP circuit = %d!\n", circuit); - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK); - - /* set the channel to suspended state */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); -done: - if (iter) { - ftdm_iterator_free(iter); - } - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_cgb_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - sngss7_span_data_t *sngss7_span = NULL; - ftdm_channel_t *ftdmchan = NULL; - int range; - uint8_t status[255]; - int blockType = 0; - int byte = 0; - int bit = 0; - int x; - int loop_range=0; - - ftdm_running_return(FTDM_FAIL); - - memset(&status[0], '\0', sizeof(status)); - - /* confirm that the circuit is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } else { - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - } - /* grab the span info */ - sngss7_span = ftdmchan->span->signal_data; - - /* figure out what type of block needs to be applied */ - if ((siStaEvnt->cgsmti.eh.pres == PRSNT_NODEF) && (siStaEvnt->cgsmti.typeInd.pres == PRSNT_NODEF)) { - blockType = siStaEvnt->cgsmti.typeInd.val; - } else { - SS7_ERROR("Received CGB with no circuit group supervision value on CIC = %d\n", sngss7_info->circuit->cic); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - /* pull out the range value */ - if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.range.pres == PRSNT_NODEF)) { - range = siStaEvnt->rangStat.range.val; - } else { - SS7_ERROR("Received CGB with no range value on CIC = %d\n", sngss7_info->circuit->cic); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - /* pull out the status field */ - if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.status.pres == PRSNT_NODEF)) { - for (x = 0; x < siStaEvnt->rangStat.status.len; x++) { - status[x] = siStaEvnt->rangStat.status.val[x]; - } - } else { - SS7_ERROR("Received CGB with no status value on CIC = %d\n", sngss7_info->circuit->cic); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - /* save the circuit, range and status */ - sngss7_span->rx_cgb.circuit = circuit; - sngss7_span->rx_cgb.range = range; - sngss7_span->rx_cgb.type = blockType; - for (x = 0; x < siStaEvnt->rangStat.status.len; x++) { - sngss7_span->rx_cgb.status[x] = status[x]; - } - - /* loop over the cics starting from circuit until range+1 */ - loop_range = circuit + range + 1; - x = circuit; - while( x < loop_range ) { - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type != SNG_CKT_VOICE) { - loop_range++; - } - else { - if (extract_chan_data(x, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", x); - } else { - ftdm_mutex_lock(ftdmchan->mutex); - if (status[byte] & (1 << bit)) { - switch (blockType) { - /**********************************************************************/ - case 0: /* maintenance oriented */ - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX); - break; - /**********************************************************************/ - case 1: /* hardware failure oriented */ - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX); - break; - /**********************************************************************/ - case 2: /* reserved for national use */ - break; - /**********************************************************************/ - default: - break; - /**********************************************************************/ - } - } - - /* bring the sig status down */ - sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN); - - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - /* update the bit and byte counter*/ - bit ++; - if (bit == 8) { - byte++; - bit = 0; - } - } - } - x++; - } - - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - ft_to_sngss7_cgba(ftdmchan); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - sngss7_span_data_t *sngss7_span = NULL; - ftdm_channel_t *ftdmchan = NULL; - int range; - uint8_t status[255]; - int blockType = 0; - int byte = 0; - int bit = 0; - int x; - int loop_range=0; - ftdm_sigmsg_t sigev; - - ftdm_running_return(FTDM_FAIL); - - memset(&sigev, 0, sizeof (sigev)); - memset(&status[0], '\0', sizeof(status)); - - /* confirm that the circuit is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } else { - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - } - - /* grab the span info */ - sngss7_span = ftdmchan->span->signal_data; - - /* figure out what type of block needs to be applied */ - if ((siStaEvnt->cgsmti.eh.pres == PRSNT_NODEF) && (siStaEvnt->cgsmti.typeInd.pres == PRSNT_NODEF)) { - blockType = siStaEvnt->cgsmti.typeInd.val; - } else { - SS7_ERROR("Received CGU with no circuit group supervision value on CIC = %d\n", sngss7_info->circuit->cic); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - /* pull out the range value */ - if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.range.pres == PRSNT_NODEF)) { - range = siStaEvnt->rangStat.range.val; - } else { - SS7_ERROR("Received CGU with no range value on CIC = %d\n", sngss7_info->circuit->cic); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - /* pull out the status field */ - if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.status.pres == PRSNT_NODEF)) { - for (x = 0; x < siStaEvnt->rangStat.status.len; x++) { - status[x] = siStaEvnt->rangStat.status.val[x]; - } - } else { - SS7_ERROR("Received CGU with no status value on CIC = %d\n", sngss7_info->circuit->cic); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - /* save the circuit, range and status */ - sngss7_span->rx_cgu.circuit = circuit; - sngss7_span->rx_cgu.range = range; - sngss7_span->rx_cgu.type = blockType; - for (x = 0; x < siStaEvnt->rangStat.status.len; x++) { - sngss7_span->rx_cgu.status[x] = status[x]; - } - - /* loop over the cics starting from circuit until range+1 */ - loop_range = circuit + range + 1; - x = circuit; - while( x < loop_range ) { - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type != SNG_CKT_VOICE) { - loop_range++; - } else { - if (extract_chan_data(x, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", x); - } - else { - ftdm_mutex_lock(ftdmchan->mutex); - - if (status[byte] & (1 << bit)) { - switch (blockType) { - /**********************************************************************/ - case 0: /* maintenance oriented */ - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN); - break; - /**********************************************************************/ - case 1: /* hardware failure oriented */ - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX); - break; - /**********************************************************************/ - case 2: /* reserved for national use */ - break; - /**********************************************************************/ - default: - break; - /**********************************************************************/ - } /* switch (blockType) */ - } /* if (status[byte] & (1 << bit)) */ - - sigev.chan_id = ftdmchan->chan_id; - sigev.span_id = ftdmchan->span_id; - sigev.channel = ftdmchan; - - /* bring the sig status down */ - if (sngss7_channel_status_clear(sngss7_info)) { - sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP); - } - - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - ftdm_mutex_unlock(ftdmchan->mutex); - - /* update the bit and byte counter*/ - bit ++; - if (bit == 8) { - byte++; - bit = 0; - } - } - } - x++; - } - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - ft_to_sngss7_cgua(ftdmchan); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_olm_msg(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - ftdm_running_return(FTDM_FAIL); - - /* confirm that the circuit is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } else { - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_FAIL; - } - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - } - - /* handle overload */ - SS7_ERROR_CHAN(ftdmchan,"[CIC:%d]Rx Overload\n", sngss7_info->circuit->cic); - - sng_isup_reg_info_show(); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c deleted file mode 100644 index 95ff402ae8..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c +++ /dev/null @@ -1,722 +0,0 @@ -/* - * Copyright (c) 2009, Konrad Hammel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* INCLUDE ********************************************************************/ -#include "ftmod_sangoma_ss7_main.h" -/******************************************************************************/ - -/* DEFINES ********************************************************************/ -/******************************************************************************/ - -/* GLOBALS ********************************************************************/ -/******************************************************************************/ - -/* PROTOTYPES *****************************************************************/ -void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -void sngss7_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); -void sngss7_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); -void sngss7_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCnStEvnt *siCnStEvnt, uint8_t evntType); -void sngss7_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt); -void sngss7_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt); -void sngss7_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiInfoEvnt *siInfoEvnt); -void sngss7_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt); -void sngss7_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt); -void sngss7_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit); -void sngss7_resm_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiResmEvnt *siResmEvnt); -void sngss7_susp_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiSuspEvnt *siSuspEvnt); -void sngss7_ssp_sta_cfm(uint32_t infId); -/******************************************************************************/ - -/* FUNCTIONS ******************************************************************/ -void sngss7_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_event_data_t *sngss7_event = NULL; - - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("Rx sig event on circuit that is not a voice CIC (%d)\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* initalize the sngss7_event */ - sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); - - if (sngss7_event == NULL) { - SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - - /* fill in the sngss7_event struct */ - sngss7_event->spInstId = spInstId; - sngss7_event->suInstId = suInstId; - sngss7_event->circuit = circuit; - sngss7_event->event_id = SNGSS7_CON_IND_EVENT; - memcpy(&sngss7_event->event.siConEvnt, siConEvnt, sizeof(*siConEvnt)); - - /* enqueue this event */ - ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -/******************************************************************************/ -void sngss7_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_event_data_t *sngss7_event = NULL; - - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("Rx sig event on circuit that is not a voice CIC (%d)\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* initalize the sngss7_event */ - sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); - if (sngss7_event == NULL) { - SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - - /* fill in the sngss7_event struct */ - sngss7_event->spInstId = spInstId; - sngss7_event->suInstId = suInstId; - sngss7_event->circuit = circuit; - sngss7_event->event_id = SNGSS7_CON_CFM_EVENT; - memcpy(&sngss7_event->event.siConEvnt, siConEvnt, sizeof(*siConEvnt)); - - /* enqueue this event */ - ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -/******************************************************************************/ -void sngss7_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCnStEvnt *siCnStEvnt, uint8_t evntType) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_event_data_t *sngss7_event = NULL; - - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("Rx sig event on circuit that is not a voice CIC (%d)\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* initalize the sngss7_event */ - sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); - if (sngss7_event == NULL) { - SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - - /* fill in the sngss7_event struct */ - sngss7_event->spInstId = spInstId; - sngss7_event->suInstId = suInstId; - sngss7_event->circuit = circuit; - sngss7_event->evntType = evntType; - sngss7_event->event_id = SNGSS7_CON_STA_EVENT; - memcpy(&sngss7_event->event.siCnStEvnt, siCnStEvnt, sizeof(*siCnStEvnt)); - - /* enqueue this event */ - ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -/******************************************************************************/ -void sngss7_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_event_data_t *sngss7_event = NULL; - - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("Rx sig event on circuit that is not a voice CIC (%d)\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* initalize the sngss7_event */ - sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); - if (sngss7_event == NULL) { - SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - - /* fill in the sngss7_event struct */ - sngss7_event->spInstId = spInstId; - sngss7_event->suInstId = suInstId; - sngss7_event->circuit = circuit; - sngss7_event->event_id = SNGSS7_REL_IND_EVENT; - memcpy(&sngss7_event->event.siRelEvnt, siRelEvnt, sizeof(*siRelEvnt)); - - /* enqueue this event */ - ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -/******************************************************************************/ -void sngss7_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_event_data_t *sngss7_event = NULL; - - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("Rx sig event on circuit that is not a voice CIC (%d)\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* initalize the sngss7_event */ - sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); - if (sngss7_event == NULL) { - SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - - /* fill in the sngss7_event struct */ - sngss7_event->spInstId = spInstId; - sngss7_event->suInstId = suInstId; - sngss7_event->circuit = circuit; - sngss7_event->event_id = SNGSS7_REL_CFM_EVENT; - memcpy(&sngss7_event->event.siRelEvnt, siRelEvnt, sizeof(*siRelEvnt)); - - /* enqueue this event */ - ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -/******************************************************************************/ -void sngss7_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiInfoEvnt *siInfoEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_event_data_t *sngss7_event = NULL; - - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("Rx sig event on circuit that is not a voice CIC (%d)\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* initalize the sngss7_event */ - sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); - if (sngss7_event == NULL) { - SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - - /* fill in the sngss7_event struct */ - sngss7_event->spInstId = spInstId; - sngss7_event->suInstId = suInstId; - sngss7_event->circuit = circuit; - sngss7_event->event_id = SNGSS7_DAT_IND_EVENT; - memcpy(&sngss7_event->event.siInfoEvnt, siInfoEvnt, sizeof(*siInfoEvnt)); - - /* enqueue this event */ - ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -/******************************************************************************/ -void sngss7_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_event_data_t *sngss7_event = NULL; - - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("Rx sig event on circuit that is not a voice CIC (%d)\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* initalize the sngss7_event */ - sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); - if (sngss7_event == NULL) { - SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - - /* fill in the sngss7_event struct */ - sngss7_event->spInstId = spInstId; - sngss7_event->suInstId = suInstId; - sngss7_event->circuit = circuit; - sngss7_event->evntType = evntType; - sngss7_event->event_id = SNGSS7_FAC_IND_EVENT; - memcpy(&sngss7_event->event.siFacEvnt, siFacEvnt, sizeof(*siFacEvnt)); - - /* enqueue this event */ - ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -/******************************************************************************/ -void sngss7_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_event_data_t *sngss7_event = NULL; - - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("Rx sig event on circuit that is not a voice CIC (%d)\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* initalize the sngss7_event */ - sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); - if (sngss7_event == NULL) { - SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - - /* fill in the sngss7_event struct */ - sngss7_event->spInstId = spInstId; - sngss7_event->suInstId = suInstId; - sngss7_event->circuit = circuit; - sngss7_event->evntType = evntType; - sngss7_event->event_id = SNGSS7_FAC_CFM_EVENT; - memcpy(&sngss7_event->event.siFacEvnt, siFacEvnt, sizeof(*siFacEvnt)); - - /* enqueue this event */ - ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -/******************************************************************************/ -void sngss7_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_event_data_t *sngss7_event = NULL; - - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("Rx sig event on circuit that is not a voice CIC (%d)\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* initalize the sngss7_event */ - sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); - if (sngss7_event == NULL) { - SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - - /* fill in the sngss7_event struct */ - sngss7_event->spInstId = spInstId; - sngss7_event->suInstId = suInstId; - sngss7_event->circuit = circuit; - sngss7_event->event_id = SNGSS7_UMSG_IND_EVENT; - - /* enqueue this event */ - ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - -} -/* GENERAL STATUS *************************************************************/ -void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_event_data_t *sngss7_event = NULL; - uint32_t intfId; - int x; - - - - /* check if the eventType is a pause/resume */ - switch (evntType) { - /**************************************************************************/ - case (SIT_STA_PAUSEIND): - case (SIT_STA_RESUMEIND): - /* the circuit may or may not be on the local system so we have to find - * circuit with the same intfId. The circuit specified might also be - * a non-voice cic so we also need to find the first voice cic on this - * system with the same intfId. - */ - intfId = g_ftdm_sngss7_data.cfg.isupCkt[circuit].infId; - - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_DEBUG("Rx %s on circuit that is not a voice CIC (%d) finding a new circuit\n", - DECODE_LCC_EVENT(evntType), - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic); - } - - x = (g_ftdm_sngss7_data.cfg.procId * MAX_CIC_MAP_LENGTH) + 1; - while ((g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) && - (g_ftdm_sngss7_data.cfg.isupCkt[x].id < ((g_ftdm_sngss7_data.cfg.procId + 1) * MAX_CIC_MAP_LENGTH))) { - /**********************************************************************/ - /* confirm this is a voice channel and not a gap/sig (no ftdmchan there) */ - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - /* compare the intfIds */ - if (g_ftdm_sngss7_data.cfg.isupCkt[x].infId == intfId) { - /* we have a match, setup the pointers to the correct values */ - circuit = x; - - /* confirm that the circuit is active on our side otherwise move to the next circuit */ - if (!sngss7_test_flag(&g_ftdm_sngss7_data.cfg.isupCkt[circuit], SNGSS7_ACTIVE)) { - SS7_DEBUG("[CIC:%d]Rx %s but circuit is not active yet, skipping!\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - DECODE_LCC_EVENT(evntType)); - x++; - continue; - } - - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* bounce out of the loop */ - break; - } - } - - x++; - /**********************************************************************/ - } - - /* check if we found any circuits that are on the intfId, drop the message - * if none are found */ - if (!ftdmchan) { - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - break; - /**************************************************************************/ - default: - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - ftdm_log(FTDM_LOG_DEBUG, "Rx %s on circuit that is not a voice CIC (%d) (circuit:%d)\n", - DECODE_LCC_EVENT(evntType), g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - break; - /**************************************************************************/ - } /* switch (evntType) */ - - /* initalize the sngss7_event */ - sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); - if (sngss7_event == NULL) { - SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - - /* fill in the sngss7_event struct */ - sngss7_event->spInstId = spInstId; - sngss7_event->suInstId = suInstId; - sngss7_event->circuit = circuit; - sngss7_event->globalFlg = globalFlg; - sngss7_event->evntType = evntType; - sngss7_event->event_id = SNGSS7_STA_IND_EVENT; - if (siStaEvnt != NULL) { - memcpy(&sngss7_event->event.siStaEvnt, siStaEvnt, sizeof(*siStaEvnt)); - } - - /* enqueue this event */ - ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event); -} - -/******************************************************************************/ -void sngss7_susp_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiSuspEvnt *siSuspEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_event_data_t *sngss7_event = NULL; - - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("Rx sig event on circuit that is not a voice CIC (%d)\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* initalize the sngss7_event */ - sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); - if (sngss7_event == NULL) { - SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - - /* fill in the sngss7_event struct */ - sngss7_event->spInstId = spInstId; - sngss7_event->suInstId = suInstId; - sngss7_event->circuit = circuit; - sngss7_event->event_id = SNGSS7_SUSP_IND_EVENT; - if (siSuspEvnt != NULL) { - memcpy(&sngss7_event->event.siSuspEvnt, siSuspEvnt, sizeof(*siSuspEvnt)); - } - - /* enqueue this event */ - ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - -} - -/******************************************************************************/ -void sngss7_resm_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiResmEvnt *siResmEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_event_data_t *sngss7_event = NULL; - - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { - SS7_ERROR("Rx sig event on circuit that is not a voice CIC (%d)\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* initalize the sngss7_event */ - sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); - if (sngss7_event == NULL) { - SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - - /* fill in the sngss7_event struct */ - sngss7_event->spInstId = spInstId; - sngss7_event->suInstId = suInstId; - sngss7_event->circuit = circuit; - sngss7_event->event_id = SNGSS7_RESM_IND_EVENT; - if (siResmEvnt != NULL) { - memcpy(&sngss7_event->event.siResmEvnt, siResmEvnt, sizeof(*siResmEvnt)); - } - - /* enqueue this event */ - ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - -} - -/******************************************************************************/ -void sngss7_ssp_sta_cfm(uint32_t infId) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); -#if 0 - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_event_data_t *sngss7_event = NULL; - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - - /* initalize the sngss7_event */ - sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); - if (sngss7_event == NULL) { - SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; - } - memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - - /* fill in the sngss7_event struct */ - sngss7_event->spInstId = spInstId; - sngss7_event->suInstId = suInstId; - sngss7_event->circuit = circuit; - sngss7_event->event_id = SNGSS7_RESM_IND_EVENT; - if (siSuspEvnt != NULL) { - memcpy(&sngss7_event->event.siResmEvnt, siResmEvnt, sizeof(*siResmEvnt)); - } - - /* enqueue this event */ - ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event); -#endif - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - -} -/******************************************************************************/ -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ -/******************************************************************************/ - diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c deleted file mode 100644 index a4c064a323..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c +++ /dev/null @@ -1,1155 +0,0 @@ -/* - * Copyright (c) 2009|Konrad Hammel - * All rights reserved. - * - * Redistribution and use in source and binary forms|with or without - * modification|are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice|this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice|this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT - * LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL, - * EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -/* INCLUDE ********************************************************************/ -#include "ftmod_sangoma_ss7_main.h" -/******************************************************************************/ - -/* DEFINES ********************************************************************/ -/******************************************************************************/ - -/* GLOBALS ********************************************************************/ -/******************************************************************************/ - -/* PROTOTYPES *****************************************************************/ -void handle_sng_log(uint8_t level, char *fmt,...); -void handle_sng_mtp1_alarm(Pst *pst, L1Mngmt *sta); -void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta); -void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta); -void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta); -void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta); -void handle_sng_relay_alarm(Pst *pst, RyMngmt *sta); - -/******************************************************************************/ - -/* FUNCTIONS ******************************************************************/ -void handle_sng_log(uint8_t level, char *fmt,...) -{ - char *data; - int ret; - va_list ap; - - va_start(ap, fmt); - ret = vasprintf(&data, fmt, ap); - if (ret == -1) { - return; - } - - switch (level) { - /**************************************************************************/ - case SNG_LOGLEVEL_DEBUG: - ftdm_log(FTDM_LOG_DEBUG, "sng_ss7->%s", data); - break; - /**************************************************************************/ - case SNG_LOGLEVEL_WARN: - ftdm_log(FTDM_LOG_WARNING, "sng_ss7->%s", data); - break; - /**************************************************************************/ - case SNG_LOGLEVEL_INFO: - ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data); - break; - /**************************************************************************/ - case SNG_LOGLEVEL_NOTICE: - ftdm_log(FTDM_LOG_NOTICE, "sng_ss7->%s", data); - break; - /**************************************************************************/ - case SNG_LOGLEVEL_ERROR: - ftdm_log(FTDM_LOG_ERROR, "sng_ss7->%s", data); - break; - /**************************************************************************/ - case SNG_LOGLEVEL_CRIT: - /*printf("%s",data);*/ - ftdm_log(FTDM_LOG_CRIT, "sng_ss7->%s", data); - break; - /**************************************************************************/ - default: - ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data); - break; - /**************************************************************************/ - } - - return; -} - -/******************************************************************************/ -void handle_sng_mtp1_alarm(Pst *pst, L1Mngmt *sta) -{ - - -} /* handle_mtp1_alarm */ - -/******************************************************************************/ -void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta) -{ - char buf[50]; - int x = 1; - int log_level = FTDM_LOG_LEVEL_DEBUG; - - memset(buf, '\0', sizeof(buf)); - - switch (sta->t.usta.alarm.category) { - /**************************************************************************/ - case (LCM_CATEGORY_PROTOCOL): - case (LCM_CATEGORY_INTERFACE): - - switch (sta->t.usta.alarm.event) { - /**********************************************************************/ - case (LSD_EVENT_ENTR_CONG): - case (LSD_EVENT_EXIT_CONG): - case (LSD_EVENT_PROT_ST_UP): - case (LSD_EVENT_PROT_ST_DN): - case (LSD_EVENT_LINK_ALIGNED): - case (LSD_EVENT_REMOTE_CONG_START): - case (LSD_EVENT_REMOTE_CONG_END): - case (LSD_EVENT_RX_REMOTE_SIPO): - - /* find the name for the sap in question */ - x = 1; - while (x < (MAX_MTP_LINKS+1)) { - if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == sta->t.usta.evntParm[0]) { - break; - } - x++; - } - - if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == 0) { - sprintf(buf, "[SAPID:%d]", sta->t.usta.evntParm[0]); - } else { - sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtp2Link[x].name); - } - - - switch (sta->t.usta.alarm.cause) { - case (LCM_CAUSE_MGMT_INITIATED): - ftdm_log(FTDM_LOG_DEBUG,"[MTP2]%s[MGMT] cause:%s event:%s\n", - buf, - DECODE_LCM_CAUSE(sta->t.usta.alarm.cause), - DECODE_LSD_EVENT(sta->t.usta.alarm.event)); - break; - case (LCM_CAUSE_UNKNOWN): - default: - { - if ((LSD_EVENT_ALIGN_LOST == sta->t.usta.alarm.event) || - (LSD_EVENT_PROT_ST_DN == sta->t.usta.alarm.event)) { - log_level = FTDM_LOG_LEVEL_WARNING; - } else if ((LSD_EVENT_LINK_ALIGNED == sta->t.usta.alarm.event) || - (LSD_EVENT_PROT_ST_UP == sta->t.usta.alarm.event)){ - log_level = FTDM_LOG_LEVEL_INFO; - } else { - log_level = FTDM_LOG_LEVEL_WARNING; - } - ftdm_log(FTDM_PRE, log_level,"[MTP2]%s cause:%s event:%s\n", - buf, - DECODE_LCM_CAUSE(sta->t.usta.alarm.cause), - DECODE_LSD_EVENT(sta->t.usta.alarm.event)); - break; - } - /******************************************************************/ - } /* switch (sta->t.usta.alarm.cause) */ - break; - /**********************************************************************/ - case (LSD_EVENT_PROT_ERR): - - /* find the name for the sap in question */ - x = 1; - while (x < (MAX_MTP_LINKS+1)) { - if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == sta->t.usta.evntParm[0]) { - break; - } - x++; - } - - if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == 0) { - sprintf(buf, "[SAPID:%d]", sta->t.usta.evntParm[0]); - } else { - sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtp2Link[x].name); - } - - ftdm_log(FTDM_LOG_WARNING,"[MTP2]%s %s : %s\n", - buf, - DECODE_LSD_EVENT(sta->t.usta.alarm.event), - DECODE_LSD_CAUSE(sta->t.usta.alarm.cause)); - break; - /**********************************************************************/ - case (LSD_EVENT_ALIGN_LOST): - - /* find the name for the sap in question */ - x = 1; - while (x < (MAX_MTP_LINKS+1)) { - if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == sta->t.usta.evntParm[0]) { - break; - } - x++; - } - - if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == 0) { - sprintf(buf, "[SAPID:%d]", sta->t.usta.evntParm[0]); - } else { - sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtp2Link[x].name); - } - - ftdm_log(FTDM_LOG_WARNING,"[MTP2]%s %s : %s\n", - buf, - DECODE_LSD_EVENT(sta->t.usta.alarm.event), - DECODE_DISC_REASON(sta->t.usta.evntParm[1])); - break; - /**********************************************************************/ - case (LSD_EVENT_RTB_FULL): - case (LSD_EVENT_RTB_FULL_OVER): - - /* find the name for the sap in question */ - x = 1; - while (x < (MAX_MTP_LINKS+1)) { - if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == sta->t.usta.evntParm[0]) { - break; - } - x++; - } - - if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == 0) { - sprintf(buf, "[SAPID:%d]", sta->t.usta.evntParm[0]); - } else { - sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtp2Link[x].name); - } - - ftdm_log(FTDM_LOG_WARNING,"[MTP2]%s %s : RTB Queue Len(%d)|Oldest BSN(%d)|Tx Queue Len(%d)|Outstanding Frames(%d)\n", - buf, - DECODE_LSD_EVENT(sta->t.usta.alarm.event), - sta->t.usta.evntParm[1], - sta->t.usta.evntParm[2], - sta->t.usta.evntParm[3], - sta->t.usta.evntParm[4]); - break; - /**********************************************************************/ - case (LSD_EVENT_NEG_ACK): - - /* find the name for the sap in question */ - x = 1; - while (x < (MAX_MTP_LINKS+1)) { - if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == sta->t.usta.evntParm[0]) { - break; - } - x++; - } - - if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == 0) { - sprintf(buf, "[SAPID:%d]", sta->t.usta.evntParm[0]); - } else { - sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtp2Link[x].name); - } - - ftdm_log(FTDM_LOG_WARNING,"[MTP2]%s %s : RTB Queue Len(%d)\n", - buf, - DECODE_LSD_EVENT(sta->t.usta.alarm.event), - sta->t.usta.evntParm[1]); - break; - /**********************************************************************/ - case (LSD_EVENT_DAT_CFM_SDT): - - /* find the name for the sap in question */ - x = 1; - while (x < (MAX_MTP_LINKS+1)) { - if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == sta->t.usta.evntParm[0]) { - break; - } - x++; - } - - if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == 0) { - sprintf(buf, "[SAPID:%d]", sta->t.usta.evntParm[0]); - } else { - sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtp2Link[x].name); - } - - ftdm_log(FTDM_LOG_WARNING,"[MTP2]%s %s : %s\n", - buf, - DECODE_LSD_EVENT(sta->t.usta.alarm.event), - DECODE_DISC_REASON(sta->t.usta.evntParm[1])); - break; - /**********************************************************************/ - case (LCM_EVENT_UI_INV_EVT): - case (LCM_EVENT_LI_INV_EVT): - ftdm_log(FTDM_LOG_WARNING,"[MTP2] %s(%d) : %s(%d) : Primitive (%d)\n", - DECODE_LSD_EVENT(sta->t.usta.alarm.event), - sta->t.usta.alarm.event, - DECODE_LCM_CAUSE(sta->t.usta.alarm.cause), - sta->t.usta.alarm.cause, - sta->t.usta.evntParm[0]); - break; - /**********************************************************************/ - case (LCM_EVENT_INV_EVT): - - switch (sta->t.usta.alarm.cause) { - /******************************************************************/ - case (LCM_CAUSE_UNKNOWN): - case (LCM_CAUSE_SWVER_NAVAIL): - ftdm_log(FTDM_LOG_WARNING,"[MTP2] %s : %s : Event (%d)\n", - DECODE_LSD_EVENT(sta->t.usta.alarm.event), - DECODE_LCM_CAUSE(sta->t.usta.alarm.cause), - sta->t.usta.evntParm[0]); - break; - /******************************************************************/ - case (LCM_CAUSE_DECODE_ERR): - ftdm_log(FTDM_LOG_WARNING,"[MTP2] %s : %s : Primitive (%d)|Version (%d)\n", - DECODE_LSD_EVENT(sta->t.usta.alarm.event), - DECODE_LCM_CAUSE(sta->t.usta.alarm.cause), - sta->t.usta.evntParm[0], - sta->t.usta.evntParm[1]); - break; - /******************************************************************/ - default: - ftdm_log(FTDM_LOG_WARNING,"[MTP2] %s(%d) : %s(%d)\n", - DECODE_LSD_EVENT(sta->t.usta.alarm.event), - sta->t.usta.alarm.event, - DECODE_LSD_CAUSE(sta->t.usta.alarm.cause), - sta->t.usta.alarm.cause); - break; - /******************************************************************/ - } /* switch (sta->t.usta.alarm.cause) */ - break; - /**********************************************************************/ - default: - ftdm_log(FTDM_LOG_WARNING,"[MTP2] %s(%d) : %s(%d)\n", - DECODE_LSD_EVENT(sta->t.usta.alarm.event), - sta->t.usta.alarm.event, - DECODE_LSD_CAUSE(sta->t.usta.alarm.cause), - sta->t.usta.alarm.cause); - break; - /**********************************************************************/ - } /* switch (sta->t.usta.alarm.event) */ - break; - /**************************************************************************/ - default: - ftdm_log(FTDM_LOG_ERROR,"[MTP2] Unknown alarm category %d\n", - sta->t.usta.alarm.category); - break; - /**************************************************************************/ - } /* switch(sta->t.usta.alarm.category) */ - - return; -} /* handle_mtp2_alarm */ - -/******************************************************************************/ -void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta) -{ - char buf[50]; - int x = 1; - - SS7_RELAY_DBG_FUN(handle_sng_mtp3_alarm); - - memset(buf, '\0', sizeof(buf)); - - switch (sta->hdr.elmId.elmnt) { - /**************************************************************************/ - case (STDLSAP): - - /* find the name for the sap in question */ - x = 1; - while (x < (MAX_MTP_LINKS+1)) { - if (g_ftdm_sngss7_data.cfg.mtp3Link[x].id == sta->hdr.elmId.elmntInst1) { - break; - } - x++; - } - - if (g_ftdm_sngss7_data.cfg.mtp3Link[x].id == 0) { - sprintf(buf, "[SAPID:%d]", sta->hdr.elmId.elmntInst1); - } else { - sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtp3Link[x].name); - } - - switch (sta->t.usta.alarm.event) { - /**********************************************************************/ - case (LSN_EVENT_INV_OPC_OTHER_END): - - ftdm_log(FTDM_LOG_WARNING,"[MTP3]%s %s : %s : OPC(0x%X%X%X%X)\n", - buf, - DECODE_LSN_EVENT(sta->t.usta.alarm.event), - DECODE_LSN_CAUSE(sta->t.usta.alarm.cause), - sta->t.usta.evntParm[3], - sta->t.usta.evntParm[2], - sta->t.usta.evntParm[1], - sta->t.usta.evntParm[0]); - break; - /**********************************************************************/ - case (LSN_EVENT_INV_SLC_OTHER_END): - ftdm_log(FTDM_LOG_WARNING,"[MTP3]%s %s : %s : SLC(%d)\n", - buf, - DECODE_LSN_EVENT(sta->t.usta.alarm.event), - DECODE_LSN_CAUSE(sta->t.usta.alarm.cause), - sta->t.usta.evntParm[0]); - break; - /**********************************************************************/ - default: - ftdm_log(FTDM_LOG_WARNING,"[MTP3]%s %s(%d) : %s(%d)\n", - buf, - DECODE_LSN_EVENT(sta->t.usta.alarm.event), - sta->t.usta.alarm.event, - DECODE_LSN_CAUSE(sta->t.usta.alarm.cause), - sta->t.usta.alarm.cause); - break; - /**********************************************************************/ - } /* sta->t.usta.alarm.event */ - break; - /**************************************************************************/ - case (STNSAP): - ftdm_log(FTDM_LOG_WARNING,"[MTP3][SAPID:%d] %s : %s\n", - sta->hdr.elmId.elmntInst1, - DECODE_LSN_EVENT(sta->t.usta.alarm.event), - DECODE_LSN_CAUSE(sta->t.usta.alarm.cause)); - break; - /**************************************************************************/ - case (STLNKSET): - ftdm_log(FTDM_LOG_DEBUG,"[MTP3][LNKSET:%d] %s : %s\n", - sta->hdr.elmId.elmntInst1, - DECODE_LSN_EVENT(sta->t.usta.alarm.event), - DECODE_LSN_CAUSE(sta->t.usta.alarm.cause)); - break; - /**************************************************************************/ - case (STROUT): - switch (sta->t.usta.alarm.event) { - /**********************************************************************/ - case (LSN_EVENT_RX_TRANSFER_MSG): - switch (sta->t.usta.evntParm[5]) { - /******************************************************************/ - case (0x23): - ftdm_log(FTDM_LOG_INFO,"[MTP3] Rx SNM TFC\n"); - break; - /******************************************************************/ - case (0x34): - ftdm_log(FTDM_LOG_INFO,"[MTP3] Rx SNM TFR\n"); - break; - /******************************************************************/ - case (0x54): - ftdm_log(FTDM_LOG_INFO,"[MTP3] Rx SNM TFA\n"); - break; - /******************************************************************/ - case (0x14): - ftdm_log(FTDM_LOG_INFO,"[MTP3] Rx SNM TFP\n"); - break; - /******************************************************************/ - case (0x24): - ftdm_log(FTDM_LOG_INFO,"[MTP3] Rx SNM TFP (cluster)\n"); - break; - /******************************************************************/ - case (0x64): - ftdm_log(FTDM_LOG_INFO,"[MTP3] Rx SNM TFA (cluster)\n"); - break; - /******************************************************************/ - case (0x44): - ftdm_log(FTDM_LOG_INFO,"[MTP3] Rx SNM TFR (cluster)\n"); - break; - /******************************************************************/ - } /* switch (sta->t.usta.evntParm[5]) */ - break; - /**********************************************************************/ - default: - ftdm_log(FTDM_LOG_WARNING,"[MTP3][DPC:0x%X%X%X%X] %s : %s\n", - sta->t.usta.evntParm[0], - sta->t.usta.evntParm[1], - sta->t.usta.evntParm[2], - sta->t.usta.evntParm[3], - DECODE_LSN_EVENT(sta->t.usta.alarm.event), - DECODE_LSN_CAUSE(sta->t.usta.alarm.cause)); - break; - /**********************************************************************/ - } /* switch (sta->t.usta.alarm.event) */ - break; - /**************************************************************************/ - default: - ftdm_log(FTDM_LOG_ERROR,"[MTP3] %s(%d) : %s(%d)\n", - DECODE_LSN_EVENT(sta->t.usta.alarm.event), - sta->t.usta.alarm.event, - DECODE_LSN_CAUSE(sta->t.usta.alarm.cause), - sta->t.usta.alarm.cause); - break; - /**************************************************************************/ - } /* switch (sta->hdr.elmId.elmnt) */ - - return; -} /* handle_mtp3_alarm */ - -/******************************************************************************/ -void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta) -{ - char msg[250]; - char tmp[25]; - char *p = NULL; - int x = 0; - - SS7_RELAY_DBG_FUN(handle_sng_isup_alarm); - - /* initalize the msg variable to NULLs */ - memset(&msg[0], '\0', sizeof(&msg)); - - /* if the event is REMOTE/LOCAL we don't need to print these */ - if ((sta->t.usta.alarm.event == LSI_EVENT_REMOTE) || - (sta->t.usta.alarm.event == LSI_EVENT_LOCAL)) { - return; - } - - /* point p to the first spot in msg */ - p = &msg[0]; - - p = strcat(p, "[ISUP]"); - - /* go through the dgnVals */ - for (x = 0; x < 5; x++) { - switch (sta->t.usta.dgn.dgnVal[x].type) { - /**********************************************************************/ - case (LSI_USTA_DGNVAL_NONE): - break; - /**********************************************************************/ - case (LSI_USTA_DGNVAL_EVENT): - /* init tmp with NULLs */ - memset(&tmp[0], '\0', sizeof(&tmp)); - - /* fill in the dgn val to tmp */ - sprintf(&tmp[0], "[EVENT:%d]",sta->t.usta.dgn.dgnVal[x].t.event); - - /* concat tmp to msg */ - p = strcat(p, &tmp[0]); - break; - /**********************************************************************/ - case (LSI_USTA_DGNVAL_SPID): - /* init tmp with NULLs */ - memset(&tmp[0], '\0', sizeof(&tmp)); - - /* fill in the dgn val to tmp */ - sprintf(&tmp[0], "[SPID:%d]",sta->t.usta.dgn.dgnVal[x].t.spId); - - /* concat tmp to msg */ - p = strcat(p, &tmp[0]); - break; - /**********************************************************************/ - case (LSI_USTA_DGNVAL_SUID): - /* init tmp with NULLs */ - memset(&tmp[0], '\0', sizeof(&tmp)); - - /* fill in the dgn val to tmp */ - sprintf(&tmp[0], "[SUID:%d]",sta->t.usta.dgn.dgnVal[x].t.suId); - - /* concat tmp to msg */ - p = strcat(p, &tmp[0]); - break; - /**********************************************************************/ - case (LSI_USTA_DGNVAL_SPINSTID): - /* init tmp with NULLs */ - memset(&tmp[0], '\0', sizeof(&tmp)); - - /* fill in the dgn val to tmp */ - sprintf(&tmp[0], "[SPINSTID:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.spInstId); - - /* concat tmp to msg */ - p = strcat(p, &tmp[0]); - break; - /**********************************************************************/ - case (LSI_USTA_DGNVAL_SUINSTID): - /* init tmp with NULLs */ - memset(&tmp[0], '\0', sizeof(&tmp)); - - /* fill in the dgn val to tmp */ - sprintf(&tmp[0], "[SUINSTID:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.suInstId); - - /* concat tmp to msg */ - p = strcat(p, &tmp[0]); - break; - /**********************************************************************/ - case (LSI_USTA_DGNVAL_CIRCUIT): - /* init tmp with NULLs */ - memset(&tmp[0], '\0', sizeof(&tmp)); - - /* fill in the dgn val to tmp */ - sprintf(&tmp[0], "[CKT:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.cirId); - - /* concat tmp to msg */ - p = strcat(p, &tmp[0]); - break; - /**********************************************************************/ - case (LSI_USTA_DGNVAL_CIC): - /* init tmp with NULLs */ - memset(&tmp[0], '\0', sizeof(&tmp)); - - /* fill in the dgn val to tmp */ - sprintf(&tmp[0], "[CIC:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.cic); - - /* concat tmp to msg */ - p = strcat(p, &tmp[0]); - break; - /**********************************************************************/ - case (LSI_USTA_DGNVAL_INTF): - /* init tmp with NULLs */ - memset(&tmp[0], '\0', sizeof(&tmp)); - - /* fill in the dgn val to tmp */ - sprintf(&tmp[0], "[INTF:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.intfId); - - /* concat tmp to msg */ - p = strcat(p, &tmp[0]); - break; - /**********************************************************************/ - case (LSI_USTA_DGNVAL_DPC): - /* init tmp with NULLs */ - memset(&tmp[0], '\0', sizeof(&tmp)); - - /* fill in the dgn val to tmp */ - sprintf(&tmp[0], "[DPC:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.dpc); - - /* concat tmp to msg */ - p = strcat(p, &tmp[0]); - break; - /**********************************************************************/ - case (LSI_USTA_DGNVAL_ADDRS): -#if 0 - /* - *typedef struct addrs - *{ - *U8 length; - *U8 strg[ADRLEN]; - *} Addrs; - */ - /* init tmp with NULLs */ - memset(&tmp[0], '\0', sizeof(&tmp)); - - /* fill in the dgn val to tmp */ - sprintf(&tmp[0], "[ADDRS:%d]",sta->t.usta.dgn.dgnVal[x].t.); - - /* concat tmp to msg */ - p = strcat(p, &tmp[0]); -#endif - break; - /**********************************************************************/ - case (LSI_USTA_DGNVAL_SWTCH): - /* init tmp with NULLs */ - memset(&tmp[0], '\0', sizeof(&tmp)); - - /* fill in the dgn val to tmp */ - sprintf(&tmp[0], "[SWTCH:%d]",sta->t.usta.dgn.dgnVal[x].t.swtch); - - /* concat tmp to msg */ - p = strcat(p, &tmp[0]); - break; - /**********************************************************************/ - case (LSI_USTA_DGNVAL_RANGE): - /* init tmp with NULLs */ - memset(&tmp[0], '\0', sizeof(&tmp)); - - /* fill in the dgn val to tmp */ - sprintf(&tmp[0], "[RANGE:0x%X]",sta->t.usta.dgn.dgnVal[x].t.range); - - /* concat tmp to msg */ - p = strcat(p, &tmp[0]); - break; - /**********************************************************************/ - case (LSI_USTA_DGNVAL_STATUS_OCTS): -#if 0 - /* - *typedef struct addrs - *{ - *U8 length; - *U8 strg[ADRLEN]; - *} Addrs; - */ - /* init tmp with NULLs */ - /* init tmp with NULLs */ - memset(&tmp[0], '\0', sizeof(&tmp)); - - /* fill in the dgn val to tmp */ - sprintf(&tmp[0], "[STATUS_OCT:0x%X]",sta->t.usta.dgn.dgnVal[x].t.); - - /* concat tmp to msg */ - p = strcat(p, &tmp[0]); -#endif - break; - /**********************************************************************/ - case (LSI_USTA_DGNVAL_VER): -#ifdef SI_RUG - /* init tmp with NULLs */ - memset(&tmp[0], '\0', sizeof(&tmp)); - - /* fill in the dgn val to tmp */ - sprintf(&tmp[0], "[VER:%d]",sta->t.usta.dgn.dgnVal[x].t.intfVer); - - /* concat tmp to msg */ - p = strcat(p, &tmp[0]); -#endif - break; - /**********************************************************************/ - case (LSI_USTA_DGNVAL_TIMER): - /* init tmp with NULLs */ - memset(&tmp[0], '\0', sizeof(&tmp)); - - /* fill in the dgn val to tmp */ - sprintf(&tmp[0], "[TIMER:0x%X]",sta->t.usta.dgn.dgnVal[x].t.tmrInfo); - - /* concat tmp to msg */ - p = strcat(p, &tmp[0]); - break; - /**********************************************************************/ - case (LSI_USTA_DGNVAL_MSGTYPE): - /* init tmp with NULLs */ - memset(&tmp[0], '\0', sizeof(&tmp)); - - /* fill in the dgn val to tmp */ - sprintf(&tmp[0], "[MSGTYPE:%d]",sta->t.usta.dgn.dgnVal[x].t.msgType); - - /* concat tmp to msg */ - p = strcat(p, &tmp[0]); - break; - /**********************************************************************/ - case (LSI_USTA_DGNVAL_STATE): - /* init tmp with NULLs */ - memset(&tmp[0], '\0', sizeof(&tmp)); - - /* fill in the dgn val to tmp */ - sprintf(&tmp[0], "[STATE:%d]",sta->t.usta.dgn.dgnVal[x].t.state); - - /* concat tmp to msg */ - p = strcat(p, &tmp[0]); - break; - /**********************************************************************/ - default: - break; - /**********************************************************************/ - } /* switch (sta->t.usta.dgn.dgnVal[x].t.type) */ - } /* for (x = 0; x < 5; x++) */ - - ftdm_log(FTDM_LOG_WARNING,"%s %s : %s\n", - msg, - DECODE_LSI_EVENT(sta->t.usta.alarm.event), - DECODE_LSI_CAUSE(sta->t.usta.alarm.cause)); - - return; - -} /* handle_isup_alarm */ - -/******************************************************************************/ -void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta) -{ - - SS7_RELAY_DBG_FUN(handle_sng_cc_alarm); - return; -} /* handle_cc_alarm */ - -/******************************************************************************/ -void handle_sng_relay_alarm(Pst *pst, RyMngmt *sta) -{ - - SS7_RELAY_DBG_FUN(handle_sng_relay_alarm); - - switch (sta->hdr.elmId.elmnt) { - /**************************************************************************/ - case (LRY_USTA_ERR): /* ERROR */ - ftdm_log(FTDM_LOG_WARNING,"[RELAY] Error: tx procId %d: err procId %d: channel %d: seq %s: reason %s\n", - sta->t.usta.s.ryErrUsta.sendPid, - sta->t.usta.s.ryErrUsta.errPid, - sta->t.usta.s.ryErrUsta.id, - DECODE_LRY_SEQ(sta->t.usta.s.ryErrUsta.sequence), - DECODE_LRY_REASON(sta->t.usta.s.ryErrUsta.reason)); - - /* process the event */ - switch (sta->t.usta.s.ryErrUsta.reason) { - /**********************************************************************/ - case (LRYRSNMGMTREQ): - /* do nothing since this is a shutdown */ - break; - /**********************************************************************/ - default: - /* handle the error */ - handle_relay_disconnect_on_error(sta); - break; - /**********************************************************************/ - } /* switch (sta->t.usta.s.ryErrUsta.reason) */ - - break; - /**************************************************************************/ - case (LRY_USTA_CNG): /* Congestion */ - ftdm_log(FTDM_LOG_WARNING,"[RELAY] Congestion: tx procId %d: rem procId %d: channel %d: %s\n", - sta->t.usta.s.ryCongUsta.sendPid, - sta->t.usta.s.ryCongUsta.remPid, - sta->t.usta.s.ryCongUsta.id, - DECODE_LRY_CONG_FLAGS(sta->t.usta.s.ryCongUsta.flags)); - break; - /**************************************************************************/ - case (LRY_USTA_UP): /* channel up */ - ftdm_log(FTDM_LOG_INFO,"[RELAY] Channel UP: tx procId %d: channel %d\n", - sta->t.usta.s.ryUpUsta.sendPid, - sta->t.usta.s.ryUpUsta.id); - - /* process the event */ - handle_relay_connect(sta); - - break; - /**************************************************************************/ - case (LRY_USTA_DN): /* channel down */ - ftdm_log(FTDM_LOG_WARNING,"[RELAY] Channel DOWN: tx procId %d: channel %d\n", - sta->t.usta.s.ryUpUsta.sendPid, - sta->t.usta.s.ryUpUsta.id); - - /* process the event */ - handle_relay_disconnect_on_down(sta); - - break; - /**************************************************************************/ - case (LRY_USTA_TCP_CONN_FAILED): - ftdm_log(FTDM_LOG_WARNING,"[RELAY] TCP connection failed \n" ); - - break; - /**************************************************************************/ - default: - ftdm_log(FTDM_LOG_ERROR,"Unknown Relay Alram\n"); - break; - /**************************************************************************/ - } /* switch (sta->hdr.elmId.elmnt) */ - - return; -} - -/******************************************************************************/ -void handle_sng_m2ua_alarm(Pst *pst, MwMgmt *sta) -{ - /* To print the general information */ - ftdm_log(FTDM_LOG_INFO, "Recieved a status indication from M2UA layer \n\n"); - ftdm_log(FTDM_LOG_INFO," Category = %d , event = %d , cause = %d\n", - sta->t.usta.alarm.category, sta->t.usta.alarm.event, sta->t.usta.alarm.cause); - - - /* To print the affected element value */ - switch(sta->hdr.elmId.elmnt) - { - case STMWDLSAP: - { - ftdm_log(FTDM_LOG_INFO," STMWDLSAP: with lnkNmb (%d) \n\n", - sta->t.usta.s.lnkNmb); - break; - } - case STMWSCTSAP: - { - ftdm_log(FTDM_LOG_INFO," STMWSCTSAP: suId (%d) \n\n", - sta->t.usta.s.suId); - break; - } - case STMWPEER: - { - ftdm_log(FTDM_LOG_INFO," STMWPEER: peerId (%d) \n\n", - sta->t.usta.s.peerId); - break; - } - case STMWCLUSTER: - { - ftdm_log(FTDM_LOG_INFO," STMWCLUSTER: clusterId (%d) \n\n", - sta->t.usta.s.peerId); - break; - } - default: - { - ftdm_log(FTDM_LOG_ERROR, "[MW_USTA]: Invalid element \n\n"); - break; - } - } - - /* To print the event specific information */ - switch(sta->t.usta.alarm.event) - { - case LMW_EVENT_TERM_OK: - { - ftdm_log(FTDM_LOG_INFO," M2UA : LMW_EVENT_TERM_OK: Association Terminated with PeerId[%d] \n",sta->t.usta.s.peerId); - break; - } - case LMW_EVENT_ENDPOPEN_OK: - { - ftdm_log(FTDM_LOG_INFO," M2UA : LMW_EVENT_ENDPOPEN_OK: \n"); - break; - } - case LMW_EVENT_ESTABLISH_OK: - { - ftdm_log(FTDM_LOG_INFO," M2UA : LMW_EVENT_ESTABLISH_OK Event raised on peerId[%d]\n",sta->t.usta.s.peerId); - break; - } - case LMW_EVENT_ESTABLISH_FAIL: - { - ftdm_log(FTDM_LOG_INFO," M2UA : LMW_EVENT_ESTABLISH_FAIL Event raised on peerId[%d]\n",sta->t.usta.s.peerId); - break; - } - case LMW_EVENT_ASPM: - { - ftdm_log(FTDM_LOG_INFO," M2UA : LMW_EVENT_ASPM Event raised with peerId (%d)," - " msgType (%d)\n\n",sta->t.usta.s.peerId, - sta->t.usta.t.aspm.msgType); - break; - } - case LMW_EVENT_CLUSTER: - { - ftdm_log(FTDM_LOG_INFO," M2UA : LMW_EVENT_CLUSTER Event raised on clusterId (%d), state (%d)\n\n", - sta->t.usta.s.clusterId, sta->t.usta.t.cluster.state); - - break; - } - case LMW_EVENT_NOTIFY: - { - ftdm_log(FTDM_LOG_INFO," M2UA : LMW_EVENT_NOTIFY: peerId (%d), aspId (%u), ntfy status type (%d)," - " ntfy status id (%d)\n\n", sta->t.usta.s.peerId, - (uint32_t) sta->t.usta.t.ntfy.aspId, sta->t.usta.t.ntfy.stType, - sta->t.usta.t.ntfy.stId); - - break; - } - - - case LMW_EVENT_M2UA_PROTO_ERROR: - { - ftdm_log(FTDM_LOG_ERROR, " M2UA : LMW_EVENT_M2UA_PROTO_ERROR with errorCode (%u)\n\n", - (uint32_t) sta->t.usta.t.error.errCode); - break; - } - default: - break; - } - -} /* handle_sng_m2ua_alarm */ - -/******************************************************************************/ -void handle_sng_nif_alarm(Pst *pst, NwMgmt *sta) -{ - /* To print the general information */ - ftdm_log(FTDM_LOG_INFO," Recieved a status indication from NIF layer\n"); - ftdm_log(FTDM_LOG_INFO," Category = %d , event = %d , cause = %d\n", sta->t.usta.alarm.category, - sta->t.usta.alarm.event, sta->t.usta.alarm.cause); - - switch(sta->hdr.elmId.elmnt) - { - case STNWDLSAP: - { - ftdm_log(FTDM_LOG_INFO," Recieved STNWDLSAP status indication for suId (%d) \n", sta->t.usta.suId); - switch(sta->t.usta.alarm.event) - { - case LCM_EVENT_LI_INV_EVT: - { - switch(sta->t.usta.alarm.cause) - { - case LCM_CAUSE_INV_SAP: - { - ftdm_log(FTDM_LOG_ERROR, " LCM_CAUSE_INV_SAP Alarm \n"); - break; - } - case LCM_CAUSE_INV_STATE: - { - ftdm_log(FTDM_LOG_ERROR, " LCM_CAUSE_INV_STATE Alarm \n"); - break; - } - default: - break; - } - break; - } - case LCM_EVENT_BND_OK: - { - ftdm_log(FTDM_LOG_INFO," NIF: LCM_EVENT_BND_OK Alarm \n"); - break; - } - case LCM_EVENT_BND_FAIL: - { - ftdm_log(FTDM_LOG_INFO," NIF: LCM_EVENT_BND_FAIL Alarm \n"); - break; - } - default: - break; - } - break; - } - default: - break; - } -} /* handle_sng_nif_alarm */ - -/******************************************************************************/ -void handle_sng_tucl_alarm(Pst *pst, HiMngmt *sta) -{ - /* To print the general information */ - ftdm_log(FTDM_LOG_INFO, "Recieved a status indication from TUCL layer \n\n"); - ftdm_log(FTDM_LOG_INFO, " Category = %d , event = %d , cause = %d\n", - sta->t.usta.alarm.category, - sta->t.usta.alarm.event, sta->t.usta.alarm.cause); - - switch(sta->t.usta.alarm.event) - { - case LCM_EVENT_INV_EVT: - { - ftdm_log(FTDM_LOG_INFO," [HI_USTA]: LCM_EVENT_INV_EVT with type (%d)\n\n", - sta->t.usta.info.type); - break; - } - case LHI_EVENT_BNDREQ: - { - ftdm_log(FTDM_LOG_INFO," [HI_USTA]: LHI_EVENT_BNDREQ with type (%d) spId (%d)\n\n", - sta->t.usta.info.type, sta->t.usta.info.spId); - break; - } - case LHI_EVENT_SERVOPENREQ: - case LHI_EVENT_DATREQ: - case LHI_EVENT_UDATREQ: - case LHI_EVENT_CONREQ: - case LHI_EVENT_DISCREQ: -#if(defined(HI_TLS) && defined(HI_TCP_TLS)) - case LHI_EVENT_TLS_ESTREQ: -#endif - { - ftdm_log(FTDM_LOG_INFO," [HI_USTA]: partype (%d) type(%d)\n\n", - sta->t.usta.info.inf.parType, sta->t.usta.info.type); - break; - } - case LCM_EVENT_DMEM_ALLOC_FAIL: - case LCM_EVENT_SMEM_ALLOC_FAIL: - { - ftdm_log(FTDM_LOG_ERROR," [HI_USTA]: MEM_ALLOC_FAIL with region(%d) pool (%d) type(%d)\n\n", - sta->t.usta.info.inf.mem.region, sta->t.usta.info.inf.mem.pool, - sta->t.usta.info.type); - break; - } - default: - break; - } - -} /* handle_sng_tucl_alarm */ - -/******************************************************************************/ -void handle_sng_sctp_alarm(Pst *pst, SbMgmt *sta) -{ - ftdm_log(FTDM_LOG_INFO, "Recieved a status indication from SCTP layer \n\n"); - ftdm_log(FTDM_LOG_INFO," Category = %d , event = %d , cause = %d " - " [SB_USTA]: sapId (%d) and swtch (%d)\n", - sta->t.usta.alarm.category, - sta->t.usta.alarm.event, sta->t.usta.alarm.cause, - sta->t.usta.sapId, sta->t.usta.swtch); - - switch(sta->t.usta.alarm.category) - { - case LCM_CATEGORY_INTERFACE: - { - switch(sta->t.usta.alarm.cause) - { - case LCM_CAUSE_INV_SPID: - { - ftdm_log(FTDM_LOG_ERROR, "SCTP : LCM_CAUSE_INV_SPID Alarm \n"); - break; - } - case LCM_CAUSE_SWVER_NAVAIL: - { - ftdm_log(FTDM_LOG_ERROR, "SCTP : LCM_CAUSE_SWVER_NAVAIL Alarm\n"); - break; - } - case LCM_CAUSE_INV_PAR_VAL: - { - ftdm_log(FTDM_LOG_ERROR, "SCTP : LCM_CAUSE_INV_PAR_VAL Alarm\n"); - break; - } - case LCM_CAUSE_INV_SUID: - { - ftdm_log(FTDM_LOG_ERROR, "SCTP : LCM_CAUSE_INV_SUID Alarm\n"); - break; - } - case LCM_CAUSE_INV_SAP: - { - ftdm_log(FTDM_LOG_ERROR, "SCTP : LCM_CAUSE_INV_SAP Alarm\n"); - break; - } - default: - break; - } - - break; - } - case LCM_CATEGORY_RESOURCE: - { - switch(sta->t.usta.alarm.cause) - { - case LCM_CAUSE_MEM_ALLOC_FAIL: - { - ftdm_log(FTDM_LOG_ERROR, "SCTP : LCM_CAUSE_MEM_ALLOC_FAIL Alarm \n"); - break; - } - case LSB_CAUSE_NUM_ADDR_EXCEED: - { - ftdm_log(FTDM_LOG_ERROR, "SCTP : LSB_CAUSE_NUM_ADDR_EXCEED Alarm\n"); - break; - } - default: - break; - } - break; - } - case LCM_CATEGORY_PROTOCOL: - { - switch(sta->t.usta.alarm.cause) - { - case LSB_CAUSE_PATH_FAILURE: - { - ftdm_log(FTDM_LOG_ERROR, "SCTP : LSB_CAUSE_PATH_FAILURE Alarm \n"); - break; - } - case LSB_CAUSE_PATH_ACTIVE: - { - ftdm_log(FTDM_LOG_ERROR, "SCTP : LSB_CAUSE_PATH_ACTIVE Alarm \n"); - break; - } - case LSB_CAUSE_UNRSLVD_ADDR: - { - ftdm_log(FTDM_LOG_ERROR, "SCTP : LSB_CAUSE_UNRSLVD_ADDR Alarm \n"); - break; - } - default: - break; - } - break; - } - default: - break; - } - -} /* handle_sng_sctp_alarm */ -/******************************************************************************/ - - -/******************************************************************************/ -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_m2ua.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_m2ua.c deleted file mode 100644 index 810c5a2902..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_m2ua.c +++ /dev/null @@ -1,1773 +0,0 @@ -/* - * Copyright (c) 2012, Kapil Gupta - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Contributors: - * - * - */ - -/* INCLUDE ********************************************************************/ -#include "ftmod_sangoma_ss7_main.h" -/******************************************************************************/ - -/* DEFINES ********************************************************************/ -/******************************************************************************/ -/* FUNCTION PROTOTYPES ********************************************************/ -static int ftmod_tucl_gen_config(void); -static int ftmod_tucl_sap_config(int id); -static int ftmod_sctp_gen_config(void); -static int ftmod_cfg_sctp(void); -static int ftmod_sctp_config(int id); -static ftdm_status_t ftmod_sctp_sap_config(int id); -static ftdm_status_t ftmod_sctp_tsap_config(int id); -static int ftmod_m2ua_gen_config(void); -static int ftmod_m2ua_sctsap_config(int sct_sap_id, int sctp_id); -static int ftmod_m2ua_peer_config(int id); -static int ftmod_m2ua_peer_config1(int m2ua_inf_id, int peer_id); -static int ftmod_m2ua_cluster_config(int idx); -static int ftmod_m2ua_dlsap_config(int idx); -static int ftmod_nif_gen_config(void); -static int ftmod_nif_dlsap_config(int idx); -static int ftmod_sctp_tucl_tsap_bind(int idx); -static int ftmod_m2ua_sctp_sctsap_bind(int idx); -static int ftmod_open_endpoint(int idx); -static int ftmod_init_sctp_assoc(int peer_id); -static int ftmod_nif_m2ua_dlsap_bind(int id); -static int ftmod_nif_mtp2_dlsap_bind(int id); -static int ftmod_m2ua_debug(int action); -static int ftmod_tucl_debug(int action); -static int ftmod_sctp_debug(int action); - -static int ftmod_ss7_sctp_shutdown(void); -static int ftmod_ss7_m2ua_shutdown(void); -static int ftmod_ss7_tucl_shutdown(void); - - -/******************************************************************************/ -ftdm_status_t ftmod_ss7_m2ua_init(void) -{ - /****************************************************************************************************/ - if (sng_isup_init_nif()) { - ftdm_log (FTDM_LOG_ERROR , "Failed to start NIF\n"); - return FTDM_FAIL; - } else { - ftdm_log (FTDM_LOG_INFO ,"Started NIF!\n"); - } - /****************************************************************************************************/ - - if (sng_isup_init_m2ua()) { - ftdm_log (FTDM_LOG_ERROR ,"Failed to start M2UA\n"); - return FTDM_FAIL; - } else { - ftdm_log (FTDM_LOG_INFO ,"Started M2UA!\n"); - } - /****************************************************************************************************/ - - if (sng_isup_init_sctp()) { - ftdm_log (FTDM_LOG_ERROR ,"Failed to start SCTP\n"); - return FTDM_FAIL; - } else { - ftdm_log (FTDM_LOG_INFO ,"Started SCTP!\n"); - } - /****************************************************************************************************/ - - if (sng_isup_init_tucl()) { - ftdm_log (FTDM_LOG_ERROR ,"Failed to start TUCL\n"); - return FTDM_FAIL; - } else { - ftdm_log (FTDM_LOG_INFO ,"Started TUCL!\n"); - sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_TUCL_PRESENT); - } - /****************************************************************************************************/ - - if(ftmod_tucl_gen_config()){ - ftdm_log (FTDM_LOG_ERROR ,"TUCL GEN configuration: NOT OK\n"); - return FTDM_FAIL; - } else { - ftdm_log (FTDM_LOG_INFO ,"TUCL GEN configuration: OK\n"); - } - /****************************************************************************************************/ - if(ftmod_sctp_gen_config()){ - ftdm_log (FTDM_LOG_ERROR ,"SCTP GEN configuration: NOT OK\n"); - return FTDM_FAIL; - } else { - ftdm_log (FTDM_LOG_INFO ,"SCTP GEN configuration: OK\n"); - } - /****************************************************************************************************/ - if(ftmod_m2ua_gen_config()) { - ftdm_log (FTDM_LOG_ERROR ,"M2UA General configuration: NOT OK\n"); - return FTDM_FAIL; - }else { - ftdm_log (FTDM_LOG_INFO ,"M2UA General configuration: OK\n"); - } - /****************************************************************************************************/ - if(ftmod_nif_gen_config()){ - ftdm_log (FTDM_LOG_ERROR ,"NIF General configuration: NOT OK\n"); - return FTDM_FAIL; - }else { - ftdm_log (FTDM_LOG_INFO ,"NIF General configuration: OK\n"); - } - /****************************************************************************************************/ - - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -void ftmod_ss7_m2ua_free() -{ - if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_M2UA_PRESENT)) { - ftmod_ss7_m2ua_shutdown(); - sng_isup_free_m2ua(); - } - if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_SCTP_PRESENT)) { - ftmod_ss7_sctp_shutdown(); - sng_isup_free_sctp(); - } - if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_TUCL_PRESENT)) { - ftmod_ss7_tucl_shutdown(); - sng_isup_free_tucl(); - } -} - -/******************************************************************************/ -static int ftmod_ss7_tucl_shutdown() -{ - Pst pst; - HiMngmt cntrl; - - memset((U8 *)&pst, 0, sizeof(Pst)); - memset((U8 *)&cntrl, 0, sizeof(HiMngmt)); - - smPstInit(&pst); - - pst.dstEnt = ENTHI; - - /* prepare header */ - cntrl.hdr.msgType = TCNTRL; /* message type */ - cntrl.hdr.entId.ent = ENTHI; /* entity */ - cntrl.hdr.entId.inst = 0; /* instance */ - cntrl.hdr.elmId.elmnt = STGEN; /* General */ - - cntrl.hdr.response.selector = 0; - cntrl.hdr.response.prior = PRIOR0; - cntrl.hdr.response.route = RTESPEC; - cntrl.hdr.response.mem.region = S_REG; - cntrl.hdr.response.mem.pool = S_POOL; - - cntrl.t.cntrl.action = ASHUTDOWN; - - return (sng_cntrl_tucl (&pst, &cntrl)); -} -/******************************************************************************/ -static int ftmod_ss7_m2ua_shutdown() -{ - Pst pst; - MwMgmt cntrl; - - memset((U8 *)&pst, 0, sizeof(Pst)); - memset((U8 *)&cntrl, 0, sizeof(MwMgmt)); - - smPstInit(&pst); - - pst.dstEnt = ENTMW; - - /* prepare header */ - cntrl.hdr.msgType = TCNTRL; /* message type */ - cntrl.hdr.entId.ent = ENTMW; /* entity */ - cntrl.hdr.entId.inst = 0; /* instance */ - cntrl.hdr.elmId.elmnt = STMWGEN; /* General */ - - cntrl.hdr.response.selector = 0; - cntrl.hdr.response.prior = PRIOR0; - cntrl.hdr.response.route = RTESPEC; - cntrl.hdr.response.mem.region = S_REG; - cntrl.hdr.response.mem.pool = S_POOL; - - cntrl.t.cntrl.action = ASHUTDOWN; - - return (sng_cntrl_m2ua (&pst, &cntrl)); -} -/***********************************************************************************************************************/ -static int ftmod_ss7_sctp_shutdown() -{ - Pst pst; - SbMgmt cntrl; - - memset((U8 *)&pst, 0, sizeof(Pst)); - memset((U8 *)&cntrl, 0, sizeof(SbMgmt)); - - smPstInit(&pst); - - pst.dstEnt = ENTSB; - - /* prepare header */ - cntrl.hdr.msgType = TCNTRL; /* message type */ - cntrl.hdr.entId.ent = ENTSB; /* entity */ - cntrl.hdr.entId.inst = 0; /* instance */ - cntrl.hdr.elmId.elmnt = STSBGEN; /* General */ - - cntrl.hdr.response.selector = 0; - cntrl.hdr.response.prior = PRIOR0; - cntrl.hdr.response.route = RTESPEC; - cntrl.hdr.response.mem.region = S_REG; - cntrl.hdr.response.mem.pool = S_POOL; - - cntrl.t.cntrl.action = ASHUTDOWN; - - return (sng_cntrl_sctp (&pst, &cntrl)); -} - -/******************************************************************************/ - - - -ftdm_status_t ftmod_ss7_m2ua_cfg(void) -{ - int x=0; - - /* SCTP configuration */ - if(ftmod_cfg_sctp()){ - ftdm_log (FTDM_LOG_ERROR ,"SCTP Configuration : NOT OK\n"); - return FTDM_FAIL; - } else { - ftdm_log (FTDM_LOG_INFO ,"SCTP Configuration : OK\n"); - } - - /****************************************************************************************************/ - /* M2UA SCTP SAP configurations */ - x = 1; - while(xspId = k->id ; /* each SCTP link there will be one tucl sap */ - pCfg->uiSel = 0x00; /*loosley coupled */ - pCfg->flcEnb = TRUE; - pCfg->txqCongStrtLim = HI_SAP_TXN_QUEUE_CONG_START_LIMIT; - pCfg->txqCongDropLim = HI_SAP_TXN_QUEUE_CONG_DROP_LIMIT; - pCfg->txqCongStopLim = HI_SAP_TXN_QUEUE_CONG_STOP_LIMIT; - pCfg->numBins = 10; - - pCfg->uiMemId.region = S_REG; - pCfg->uiMemId.pool = S_POOL; - pCfg->uiPrior = PRIOR0; - pCfg->uiRoute = RTESPEC; - - return(sng_cfg_tucl(&pst, &cfg)); -} - -/****************************************************************************************************/ - -static int ftmod_sctp_gen_config(void) -{ - SbMgmt cfg; - Pst pst; - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSB; - - /* clear the configuration structure */ - memset(&cfg, 0, sizeof(cfg)); - - /* fill in the post structure */ - smPstInit(&cfg.t.cfg.s.genCfg.smPst); - /*fill in the specific fields of the header */ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTSB; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STSBGEN; - -#ifdef SB_IPV6_SUPPORTED - /* U8 ipv6SrvcReqdFlg; */ /* IPV6 service required for sctp */ -#endif - - cfg.t.cfg.s.genCfg.serviceType = HI_SRVC_RAW_SCTP; /* Usr packetized TCP Data */ /* TUCL transport protocol (IP/UDP) */ - cfg.t.cfg.s.genCfg.maxNmbSctSaps = SB_MAX_SCT_SAPS; /* max no. SCT SAPS */ - cfg.t.cfg.s.genCfg.maxNmbTSaps = SB_MAX_T_SAPS; /* max no. Transport SAPS */ - cfg.t.cfg.s.genCfg.maxNmbEndp = SB_MAX_NUM_OF_ENDPOINTS; /* max no. endpoints */ - cfg.t.cfg.s.genCfg.maxNmbAssoc = SB_MAX_NUM_OF_ASSOC; /* max no. associations */ - cfg.t.cfg.s.genCfg.maxNmbDstAddr = SB_MAX_NUM_OF_DST_ADDR; /* max no. dest. addresses */ - cfg.t.cfg.s.genCfg.maxNmbSrcAddr = SB_MAX_NUM_OF_SRC_ADDR; /* max no. src. addresses */ - cfg.t.cfg.s.genCfg.maxNmbTxChunks = SB_MAX_NUM_OF_TX_CHUNKS; - cfg.t.cfg.s.genCfg.maxNmbRxChunks = SB_MAX_NUM_OF_RX_CHUNKS; - cfg.t.cfg.s.genCfg.maxNmbInStrms = SB_MAX_INC_STREAMS; - cfg.t.cfg.s.genCfg.maxNmbOutStrms = SB_MAX_OUT_STREAMS; - cfg.t.cfg.s.genCfg.initARwnd = SB_MAX_RWND_SIZE; - cfg.t.cfg.s.genCfg.mtuInitial = SB_MTU_INITIAL; - cfg.t.cfg.s.genCfg.mtuMinInitial = SB_MTU_MIN_INITIAL; - cfg.t.cfg.s.genCfg.mtuMaxInitial = SB_MTU_MAX_INITIAL; - cfg.t.cfg.s.genCfg.performMtu = FALSE; - cfg.t.cfg.s.genCfg.timeRes = 1; - sprintf((char*)cfg.t.cfg.s.genCfg.hostname, "www.sangoma.com"); /* DAVIDY - Fix this later, probably ignored */ - cfg.t.cfg.s.genCfg.useHstName = FALSE; /* Flag whether hostname is to be used in INIT and INITACK msg */ - cfg.t.cfg.s.genCfg.reConfig.maxInitReTx = 8; - cfg.t.cfg.s.genCfg.reConfig.maxAssocReTx = 10; - cfg.t.cfg.s.genCfg.reConfig.maxPathReTx = 10; - cfg.t.cfg.s.genCfg.reConfig.altAcceptFlg = TRUE; - cfg.t.cfg.s.genCfg.reConfig.keyTm = 600; /* initial value for MD5 Key expiry timer */ - cfg.t.cfg.s.genCfg.reConfig.alpha = 12; - cfg.t.cfg.s.genCfg.reConfig.beta = 25; -#ifdef SB_ECN - cfg.t.cfg.s.genCfg.reConfig.ecnFlg = TRUE; -#endif - - return(sng_cfg_sctp(&pst, &cfg)); -} - -/****************************************************************************************************/ -static int ftmod_cfg_sctp(void) -{ - int x=0; - - x = 1; - while(xid; - - c = &cfg.t.cfg.s.tSapCfg; - c->swtch = LSB_SW_RFC_REL0; - c->suId = k->id; - c->sel = 0; - c->ent = ENTHI; - c->inst = S_INST; - c->procId = g_ftdm_sngss7_data.cfg.procId; - c->memId.region = S_REG; - c->memId.pool = S_POOL; - c->prior = PRIOR1; - c->route = RTESPEC; - c->srcNAddrLst.nmb = k->numSrcAddr; - for (i=0; i <= (k->numSrcAddr-1); i++) { - c->srcNAddrLst.nAddr[i].type = CM_NETADDR_IPV4; - c->srcNAddrLst.nAddr[i].u.ipv4NetAddr = k->srcAddrList[i+1]; - } - - c->reConfig.spId = k->id; - c->reConfig.maxBndRetry = 3; - c->reConfig.tIntTmr = 200; - - ret = sng_cfg_sctp(&pst, &cfg); - if (0 == ret) { - SS7_INFO("SCTP TSAP [%d] configuration DONE!\n", id); - return FTDM_SUCCESS; - } else { - SS7_CRITICAL("SCTP TSAP [%d] configuration FAILED!\n", id); - return FTDM_FAIL; - } -} - -/****************************************************************************************************/ - -ftdm_status_t ftmod_sctp_sap_config(int id) -{ - Pst pst; - SbMgmt cfg; - SbSctSapCfg *c; - - int ret = -1; - sng_sctp_link_t *k = &g_ftdm_sngss7_data.cfg.sctpCfg.linkCfg[id]; - - smPstInit(&pst); - pst.dstEnt = ENTSB; - - memset(&cfg, 0x0, sizeof(cfg)); - smHdrInit(&cfg.hdr); - - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTSB; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STSBSCTSAP; - cfg.hdr.elmId.elmntInst1 = k->id; - - c = &cfg.t.cfg.s.sctSapCfg; - c->swtch = LSB_SW_RFC_REL0; - c->spId = k->id; /* Service Provider SAP Id */ - c->sel = 0; - c->memId.region = S_REG; - c->memId.pool = S_POOL; - c->prior = PRIOR1; - c->route = RTESPEC; - - /* Maximum time to wait before the SCTP layer must send a Selective Acknowledgement (SACK) message. Valid range is 1 -165535. */ - c->reConfig.maxAckDelayTm = 200; - /* Maximum number of messages to receive before the SCTP layer must send a SACK message. Valid range is 1 - 165535. */ - c->reConfig.maxAckDelayDg = 2; - /* Initial value of the retransmission timer (RTO). The SCTP layer retransmits data after waiting for feedback during this time period. Valid range is 1 - 65535. */ - c->reConfig.rtoInitial = 3000; - /* Minimum value used for the RTO. If the computed value of RTO is less than rtoMin, the computed value is rounded up to this value. */ - c->reConfig.rtoMin = 1000; - /* Maxiumum value used for RTO. If the computed value of RTO is greater than rtoMax, the computed value is rounded down to this value. */ - c->reConfig.rtoMax = 10000; - /* Default Freeze timer value */ - c->reConfig.freezeTm = 3000; - /* Base cookie lifetime for the cookie in the Initiation Acknowledgement (INIT ACK) message. */ - c->reConfig.cookieLife = 60000; - /* Default heartbeat interval timer. Valid range is 1 - 65535. */ - c->reConfig.intervalTm = 3000; - /* Maximum burst value. Valid range is 1 - 65535. */ - c->reConfig.maxBurst = 4; - /*Maximum number of heartbeats sent at each retransmission timeout (RTO). Valid range is 1 - 65535. */ - c->reConfig.maxHbBurst = 1; - /*Shutdown guard timer value for graceful shutdowns. */ - c->reConfig.t5SdownGrdTm = 15000; - /* Action to take when the receiver's number of incoming streams is less than the sender's number of outgoing streams. Valid values are: - TRUE = Accept incoming stream and continue association. - FALSE = Abort the association. - */ - c->reConfig.negAbrtFlg = FALSE; - /* Whether to enable or disable heartbeat by default. Valid values are: - TRUE = Enable heartbeat. - FALSE = Disable heartbeat. - */ - c->reConfig.hBeatEnable = TRUE; - /* Flow control start threshold. When the number of messages in SCTP’s message queue reaches this value, flow control starts. */ - c->reConfig.flcUpThr = 8; - /* Flow control stop threshold. When the number of messages in SCTP’s message queue reaches this value, flow control stops. */ - c->reConfig.flcLowThr = 6; - - c->reConfig.handleInitFlg = FALSE; - - ret = sng_cfg_sctp(&pst, &cfg); - if (0 == ret) { - SS7_INFO("SCTP SAP [%d] configuration DONE!\n", id); - return FTDM_SUCCESS; - } else { - SS7_CRITICAL("SCTP SAP [%d] configuration FAILED!\n", id); - return FTDM_FAIL; - } -} - -/**********************************************************************************************/ -/* M2UA - General configuration */ -static int ftmod_m2ua_gen_config(void) -{ - Pst pst; - MwMgmt cfg; - - memset((U8 *)&cfg, 0, sizeof(MwMgmt)); - memset((U8 *)&pst, 0, sizeof(Pst)); - - smPstInit(&pst); - - pst.dstEnt = ENTMW; - - /* prepare header */ - cfg.hdr.msgType = TCFG; /* message type */ - cfg.hdr.entId.ent = ENTMW; /* entity */ - cfg.hdr.entId.inst = 0; /* instance */ - cfg.hdr.elmId.elmnt = STMWGEN; /* General */ - cfg.hdr.transId = 0; /* transaction identifier */ - - cfg.hdr.response.selector = 0; - cfg.hdr.response.prior = PRIOR0; - cfg.hdr.response.route = RTESPEC; - cfg.hdr.response.mem.region = S_REG; - cfg.hdr.response.mem.pool = S_POOL; - - - - cfg.t.cfg.s.genCfg.nodeType = LMW_TYPE_SGP; /* NodeType == SGP or ASP */ - cfg.t.cfg.s.genCfg.maxNmbIntf = MW_MAX_NUM_OF_INTF; - cfg.t.cfg.s.genCfg.maxNmbCluster = MW_MAX_NUM_OF_CLUSTER; - cfg.t.cfg.s.genCfg.maxNmbPeer = MW_MAX_NUM_OF_PEER; - cfg.t.cfg.s.genCfg.maxNmbSctSap = MW_MAX_NUM_OF_SCT_SAPS; - cfg.t.cfg.s.genCfg.timeRes = 1; /* timer resolution */ - cfg.t.cfg.s.genCfg.maxClusterQSize = MW_MAX_CLUSTER_Q_SIZE; - cfg.t.cfg.s.genCfg.maxIntfQSize = MW_MAX_INTF_Q_SIZE; - -#ifdef LCMWMILMW - cfg.t.cfg.s.genCfg.reConfig.smPst.selector = 0; /* selector */ -#else /* LCSBMILSB */ - cfg.t.cfg.s.genCfg.reConfig.smPst.selector = 1; /* selector */ -#endif /* LCSBMILSB */ - - cfg.t.cfg.s.genCfg.reConfig.smPst.region = S_REG; /* region */ - cfg.t.cfg.s.genCfg.reConfig.smPst.pool = S_POOL; /* pool */ - cfg.t.cfg.s.genCfg.reConfig.smPst.prior = PRIOR0; /* priority */ - cfg.t.cfg.s.genCfg.reConfig.smPst.route = RTESPEC; /* route */ - - cfg.t.cfg.s.genCfg.reConfig.smPst.dstEnt = ENTSM; /* dst entity */ - cfg.t.cfg.s.genCfg.reConfig.smPst.dstInst = S_INST; /* dst inst */ - cfg.t.cfg.s.genCfg.reConfig.smPst.dstProcId = SFndProcId(); /* src proc id */ - - cfg.t.cfg.s.genCfg.reConfig.smPst.srcEnt = ENTMW; /* src entity */ - cfg.t.cfg.s.genCfg.reConfig.smPst.srcInst = S_INST; /* src inst */ - cfg.t.cfg.s.genCfg.reConfig.smPst.srcProcId = SFndProcId(); /* src proc id */ - - cfg.t.cfg.s.genCfg.reConfig.tmrFlcPoll.enb = TRUE; /* SCTP Flc Poll timer */ - cfg.t.cfg.s.genCfg.reConfig.tmrFlcPoll.val = 10; - -#ifdef MWASP - cfg.t.cfg.s.genCfg.reConfig.tmrAspm.enb = TRUE; /* ASPM timer */ - cfg.t.cfg.s.genCfg.reConfig.tmrAspm.val = 10; - cfg.t.cfg.s.genCfg.reConfig.tmrHeartBeat.enb = TRUE; /* Heartbeat timer */ - cfg.t.cfg.s.genCfg.reConfig.tmrHeartBeat.val = 10; -#endif - -#ifdef MWSG - cfg.t.cfg.s.genCfg.reConfig.tmrAsPend.enb = TRUE; /* AS-PENDING timer */ - cfg.t.cfg.s.genCfg.reConfig.tmrAsPend.val = 10; - cfg.t.cfg.s.genCfg.reConfig.tmrCongPoll.enb = TRUE; /* SS7 Congestion poll timer */ - cfg.t.cfg.s.genCfg.reConfig.tmrCongPoll.val = 10; - cfg.t.cfg.s.genCfg.reConfig.tmrHeartBeat.enb = FALSE; /* HBtimer only at ASP */ -#endif - cfg.t.cfg.s.genCfg.reConfig.aspmRetry = 5; - - return (sng_cfg_m2ua (&pst, &cfg)); -} - -/**********************************************************************************************/ -static int ftmod_m2ua_peer_config(int id) -{ - int x = 0; - int peer_id = 0; - sng_m2ua_cfg_t* m2ua = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[id]; - sng_m2ua_cluster_cfg_t* clust = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_clus[m2ua->clusterId]; - sng_m2ua_peer_cfg_t* peer = NULL; - - if((clust->flags & SNGSS7_CONFIGURED)){ - ftdm_log (FTDM_LOG_INFO, " ftmod_m2ua_peer_config: Cluster [%s] is already configured \n", clust->name); - return 0x00; - } - - /*NOTE : SCTSAP is based on per source address , so if we have same Cluster / peer shared across many then - * we dont have do configuration for each time */ - - /* loop through peer list from cluster to configure SCTSAP */ - - for(x = 0; x < clust->numOfPeers;x++){ - peer_id = clust->peerIdLst[x]; - peer = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[peer_id]; - if(ftmod_m2ua_sctsap_config(id, peer->sctpId)){ - ftdm_log (FTDM_LOG_ERROR, " ftmod_m2ua_sctsap_config: M2UA SCTSAP for M2UA Intf Id[%d] config FAILED \n", id); - return 0x01; - }else{ - ftdm_log (FTDM_LOG_INFO, " ftmod_m2ua_sctsap_config: M2UA SCTSAP for M2UA Intf Id[%d] config SUCCESS \n", id); - } - if(ftmod_m2ua_peer_config1(id, peer_id)){ - ftdm_log (FTDM_LOG_ERROR, " ftmod_m2ua_peer_config1: M2UA Peer[%d] configuration for M2UA Intf Id[%d] config FAILED \n", peer_id, id); - return 0x01; - }else{ - ftdm_log (FTDM_LOG_INFO, " ftmod_m2ua_peer_config1: M2UA Peer[%d] configuration for M2UA Intf Id[%d] config SUCCESS \n", peer_id, id); - } - - clust->sct_sap_id = id; - - /* set configured flag for cluster and peer */ - clust->flags |= SNGSS7_CONFIGURED; - peer->flags |= SNGSS7_CONFIGURED; - } - - return 0x0;; -} - - -static int ftmod_m2ua_sctsap_config(int sct_sap_id, int sctp_id) -{ - int i; - int ret; - Pst pst; - MwMgmt cfg; - MwMgmt cfm; - sng_sctp_link_t *sctp = &g_ftdm_sngss7_data.cfg.sctpCfg.linkCfg[sctp_id]; - - - - memset((U8 *)&cfg, 0, sizeof(MwMgmt)); - memset((U8 *)&cfm, 0, sizeof(MwMgmt)); - memset((U8 *)&pst, 0, sizeof(Pst)); - - /* check is sct_sap is already configured */ - if(!ftmod_m2ua_ssta_req(STMWSCTSAP, sct_sap_id, &cfm )){ - ftdm_log (FTDM_LOG_INFO, " ftmod_m2ua_sctsap_config: SCT SAP [%s] is already configured \n", sctp->name); - return 0x00; - } - - if(LCM_REASON_INVALID_SAP == cfm.cfm.reason){ - ftdm_log (FTDM_LOG_INFO, " ftmod_m2ua_sctsap_config: SCT SAP [%s] is not configured..configuring now \n", sctp->name); - } - - smPstInit(&pst); - - pst.dstEnt = ENTMW; - - /* prepare header */ - cfg.hdr.msgType = TCFG; /* message type */ - cfg.hdr.entId.ent = ENTMW; /* entity */ - cfg.hdr.entId.inst = 0; /* instance */ - cfg.hdr.elmId.elmnt = STMWSCTSAP; /* SCTSAP */ - cfg.hdr.transId = 0; /* transaction identifier */ - - cfg.hdr.response.selector = 0; - cfg.hdr.response.prior = PRIOR0; - cfg.hdr.response.route = RTESPEC; - cfg.hdr.response.mem.region = S_REG; - cfg.hdr.response.mem.pool = S_POOL; - - cfg.t.cfg.s.sctSapCfg.reConfig.selector = 0; - - /* service user SAP ID */ - cfg.t.cfg.s.sctSapCfg.suId = sct_sap_id; - /* service provider ID */ - cfg.t.cfg.s.sctSapCfg.spId = sctp_id; - /* source port number */ - cfg.t.cfg.s.sctSapCfg.srcPort = sctp->port; - /* interface address */ - /*For multiple IP address support */ -#ifdef SCT_ENDP_MULTI_IPADDR - cfg.t.cfg.s.sctSapCfg.srcAddrLst.nmb = sctp->numSrcAddr; - for (i=0; i <= (sctp->numSrcAddr-1); i++) { - cfg.t.cfg.s.sctSapCfg.srcAddrLst.nAddr[i].type = CM_NETADDR_IPV4; - cfg.t.cfg.s.sctSapCfg.srcAddrLst.nAddr[i].u.ipv4NetAddr = sctp->srcAddrList[i+1]; - } -#else - /* for single ip support ,src address will always be one */ - cfg.t.cfg.s.sctSapCfg.intfAddr.type = CM_NETADDR_IPV4; - cfg.t.cfg.s.sctSapCfg.intfAddr.u.ipv4NetAddr = sctp->srcAddrList[1]; -#endif - - /* lower SAP primitive timer */ - cfg.t.cfg.s.sctSapCfg.reConfig.tmrPrim.enb = TRUE; - cfg.t.cfg.s.sctSapCfg.reConfig.tmrPrim.val = 10; - /* Association primitive timer */ - cfg.t.cfg.s.sctSapCfg.reConfig.tmrAssoc.enb = TRUE; - cfg.t.cfg.s.sctSapCfg.reConfig.tmrAssoc.val = 10; - /* maxnumber of retries */ - cfg.t.cfg.s.sctSapCfg.reConfig.nmbMaxPrimRetry = 5; - /* Life Time of Packets */ - cfg.t.cfg.s.sctSapCfg.reConfig.lifeTime = 200; - /* priority */ - cfg.t.cfg.s.sctSapCfg.reConfig.prior = PRIOR0; - /* route */ - cfg.t.cfg.s.sctSapCfg.reConfig.route = RTESPEC; - cfg.t.cfg.s.sctSapCfg.reConfig.ent = ENTSB; - cfg.t.cfg.s.sctSapCfg.reConfig.inst = 0; - cfg.t.cfg.s.sctSapCfg.reConfig.procId = SFndProcId(); - /* memory region and pool ID */ - cfg.t.cfg.s.sctSapCfg.reConfig.mem.region = S_REG; - cfg.t.cfg.s.sctSapCfg.reConfig.mem.pool = S_POOL; - - if (0 == (ret = sng_cfg_m2ua (&pst, &cfg))){ - sctp->flags |= SNGSS7_CONFIGURED; - } - - return ret; -} - -/****************************************************************************************************/ - -/* M2UA - Peer configuration */ -static int ftmod_m2ua_peer_config1(int m2ua_inf_id, int peer_id) -{ - int i; - Pst pst; - MwMgmt cfg; - sng_m2ua_peer_cfg_t* peer = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[peer_id]; - sng_sctp_link_t *sctp = &g_ftdm_sngss7_data.cfg.sctpCfg.linkCfg[peer->sctpId]; - - memset((U8 *)&cfg, 0, sizeof(MwMgmt)); - memset((U8 *)&pst, 0, sizeof(Pst)); - - smPstInit(&pst); - - pst.dstEnt = ENTMW; - - /* prepare header */ - cfg.hdr.msgType = TCFG; /* message type */ - cfg.hdr.entId.ent = ENTMW; /* entity */ - cfg.hdr.entId.inst = 0; /* instance */ - cfg.hdr.elmId.elmnt = STMWPEER; /* Peer */ - cfg.hdr.transId = 0; /* transaction identifier */ - - cfg.hdr.response.selector = 0; - cfg.hdr.response.prior = PRIOR0; - cfg.hdr.response.route = RTESPEC; - cfg.hdr.response.mem.region = S_REG; - cfg.hdr.response.mem.pool = S_POOL; - - - - cfg.t.cfg.s.peerCfg.peerId = peer->id; /* peer id */ - cfg.t.cfg.s.peerCfg.aspIdFlag = peer->aspIdFlag; /* aspId flag */ -#ifdef MWASP - cfg.t.cfg.s.peerCfg.selfAspId = peer->selfAspId; /* aspId */ -#endif - cfg.t.cfg.s.peerCfg.assocCfg.suId = peer->sctpId; /* SCTSAP ID */ - cfg.t.cfg.s.peerCfg.assocCfg.dstAddrLst.nmb = peer->numDestAddr; - for (i=0; i <= (peer->numDestAddr); i++) { - cfg.t.cfg.s.peerCfg.assocCfg.dstAddrLst.nAddr[i].type = CM_NETADDR_IPV4; - cfg.t.cfg.s.peerCfg.assocCfg.dstAddrLst.nAddr[i].u.ipv4NetAddr = peer->destAddrList[i]; - } -#ifdef MW_CFG_DSTPORT - cfg.t.cfg.s.peerCfg.assocCfg.dstPort = peer->port; /* Port on which M2UA runs */ -#endif - cfg.t.cfg.s.peerCfg.assocCfg.srcAddrLst.nmb = sctp->numSrcAddr; /* source address list */ - for (i=0; i <= (sctp->numSrcAddr-1); i++) { - cfg.t.cfg.s.peerCfg.assocCfg.srcAddrLst.nAddr[i].type = CM_NETADDR_IPV4; - cfg.t.cfg.s.peerCfg.assocCfg.srcAddrLst.nAddr[i].u.ipv4NetAddr = sctp->srcAddrList[i+1]; - } - - cfg.t.cfg.s.peerCfg.assocCfg.priDstAddr.type = CM_NETADDR_IPV4; - cfg.t.cfg.s.peerCfg.assocCfg.priDstAddr.u.ipv4NetAddr = cfg.t.cfg.s.peerCfg.assocCfg.dstAddrLst.nAddr[0].u.ipv4NetAddr; - - cfg.t.cfg.s.peerCfg.assocCfg.locOutStrms = peer->locOutStrms; -#ifdef SCT3 - cfg.t.cfg.s.peerCfg.assocCfg.tos = 0; -#endif - - return (sng_cfg_m2ua (&pst, &cfg)); -} -/**********************************************************************************************/ -/* M2UA - Cluster configuration */ -static int ftmod_m2ua_cluster_config(int id) -{ - int i; - Pst pst; - MwMgmt cfg; - sng_m2ua_cfg_t* m2ua = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[id]; - sng_m2ua_cluster_cfg_t* clust = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_clus[m2ua->clusterId]; - - memset((U8 *)&cfg, 0, sizeof(MwMgmt)); - memset((U8 *)&pst, 0, sizeof(Pst)); - - smPstInit(&pst); - - pst.dstEnt = ENTMW; - - /* prepare header */ - cfg.hdr.msgType = TCFG; /* message type */ - cfg.hdr.entId.ent = ENTMW; /* entity */ - cfg.hdr.entId.inst = 0; /* instance */ - cfg.hdr.elmId.elmnt = STMWCLUSTER; /* Cluster */ - cfg.hdr.transId = 0; /* transaction identifier */ - - cfg.hdr.response.selector = 0; - cfg.hdr.response.prior = PRIOR0; - cfg.hdr.response.route = RTESPEC; - cfg.hdr.response.mem.region = S_REG; - cfg.hdr.response.mem.pool = S_POOL; - - - cfg.t.cfg.s.clusterCfg.clusterId = clust->id; - cfg.t.cfg.s.clusterCfg.trfMode = clust->trfMode; - cfg.t.cfg.s.clusterCfg.loadshareMode = clust->loadShareAlgo; - cfg.t.cfg.s.clusterCfg.reConfig.nmbPeer = clust->numOfPeers; - for(i=0; i<(clust->numOfPeers);i++) { - cfg.t.cfg.s.clusterCfg.reConfig.peer[i] = clust->peerIdLst[i]; - } - - return (sng_cfg_m2ua (&pst, &cfg)); -} - -/**********************************************************************************************/ - -/* M2UA - DLSAP configuration */ -static int ftmod_m2ua_dlsap_config(int id) -{ - Pst pst; - MwMgmt cfg; - sng_m2ua_cfg_t* m2ua = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[id]; - - memset((U8 *)&cfg, 0, sizeof(MwMgmt)); - memset((U8 *)&pst, 0, sizeof(Pst)); - - smPstInit(&pst); - - pst.dstEnt = ENTMW; - - /* prepare header */ - cfg.hdr.msgType = TCFG; /* message type */ - cfg.hdr.entId.ent = ENTMW; /* entity */ - cfg.hdr.entId.inst = 0; /* instance */ - cfg.hdr.elmId.elmnt = STMWDLSAP; /* DLSAP */ - cfg.hdr.transId = 0; /* transaction identifier */ - - cfg.hdr.response.selector = 0; - cfg.hdr.response.prior = PRIOR0; - cfg.hdr.response.route = RTESPEC; - cfg.hdr.response.mem.region = S_REG; - cfg.hdr.response.mem.pool = S_POOL; - - - cfg.t.cfg.s.dlSapCfg.lnkNmb = id; /* SapId */ - cfg.t.cfg.s.dlSapCfg.intfId.type = LMW_INTFID_INT; - cfg.t.cfg.s.dlSapCfg.intfId.id.intId = m2ua->iid; - - cfg.t.cfg.s.dlSapCfg.swtch = LMW_SAP_ITU; - - cfg.t.cfg.s.dlSapCfg.reConfig.clusterId = m2ua->clusterId; - cfg.t.cfg.s.dlSapCfg.reConfig.selector = 0; /* Loosely couple mode */ - /* memory region and pool id*/ - cfg.t.cfg.s.dlSapCfg.reConfig.mem.region = S_REG; - cfg.t.cfg.s.dlSapCfg.reConfig.mem.pool = S_POOL; - /* priority */ - cfg.t.cfg.s.dlSapCfg.reConfig.prior = PRIOR0; - /* route */ - cfg.t.cfg.s.dlSapCfg.reConfig.route = RTESPEC; - - return (sng_cfg_m2ua (&pst, &cfg)); - -} -/*****************************************************************************/ -/* NIF - General configuration */ -static int ftmod_nif_gen_config(void) -{ - Pst pst; - NwMgmt cfg; - - memset((U8 *)&cfg, 0, sizeof(NwMgmt)); - memset((U8 *)&pst, 0, sizeof(Pst)); - - smPstInit(&pst); - - pst.dstEnt = ENTNW; - - /* prepare header */ - cfg.hdr.msgType = TCFG; /* message type */ - cfg.hdr.entId.ent = ENTNW; /* entity */ - cfg.hdr.entId.inst = 0; /* instance */ - cfg.hdr.elmId.elmnt = STNWGEN; /* DLSAP */ - cfg.hdr.transId = 0; /* transaction identifier */ - - cfg.hdr.response.selector = 0; - cfg.hdr.response.prior = PRIOR0; - cfg.hdr.response.route = RTESPEC; - cfg.hdr.response.mem.region = S_REG; - cfg.hdr.response.mem.pool = S_POOL; - - cfg.t.cfg.s.genCfg.maxNmbDlSap = NW_MAX_NUM_OF_DLSAPS; - cfg.t.cfg.s.genCfg.timeRes = 1; /* timer resolution */ - - cfg.t.cfg.s.genCfg.reConfig.maxNmbRetry = NW_MAX_NUM_OF_RETRY; - cfg.t.cfg.s.genCfg.reConfig.tmrRetry.enb = TRUE; /* SS7 Congestion poll timer */ - cfg.t.cfg.s.genCfg.reConfig.tmrRetry.val = NW_RETRY_TMR_VALUE; - -#ifdef LCNWMILNW - cfg.t.cfg.s.genCfg.reConfig.smPst.selector = 0; /* selector */ -#else /* LCSBMILSB */ - cfg.t.cfg.s.genCfg.reConfig.smPst.selector = 1; /* selector */ -#endif /* LCSBMILSB */ - - cfg.t.cfg.s.genCfg.reConfig.smPst.region = S_REG; /* region */ - cfg.t.cfg.s.genCfg.reConfig.smPst.pool = S_POOL; /* pool */ - cfg.t.cfg.s.genCfg.reConfig.smPst.prior = PRIOR0; /* priority */ - cfg.t.cfg.s.genCfg.reConfig.smPst.route = RTESPEC; /* route */ - - cfg.t.cfg.s.genCfg.reConfig.smPst.dstEnt = ENTSM; /* dst entity */ - cfg.t.cfg.s.genCfg.reConfig.smPst.dstInst = 0; /* dst inst */ - cfg.t.cfg.s.genCfg.reConfig.smPst.dstProcId = SFndProcId(); /* src proc id */ - - cfg.t.cfg.s.genCfg.reConfig.smPst.srcEnt = ENTNW; /* src entity */ - cfg.t.cfg.s.genCfg.reConfig.smPst.srcInst = 0; /* src inst */ - cfg.t.cfg.s.genCfg.reConfig.smPst.srcProcId = SFndProcId(); /* src proc id */ - - return (sng_cfg_nif (&pst, &cfg)); - -} - -/*****************************************************************************/ - -/* NIF - DLSAP configuration */ -static int ftmod_nif_dlsap_config(int id) -{ - Pst pst; - NwMgmt cfg; - sng_nif_cfg_t* nif = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.nif[id]; - - memset((U8 *)&cfg, 0, sizeof(NwMgmt)); - memset((U8 *)&pst, 0, sizeof(Pst)); - - smPstInit(&pst); - - pst.dstEnt = ENTNW; - - /* prepare header */ - cfg.hdr.msgType = TCFG; /* message type */ - cfg.hdr.entId.ent = ENTNW; /* entity */ - cfg.hdr.entId.inst = 0; /* instance */ - cfg.hdr.elmId.elmnt = STNWDLSAP; /* DLSAP */ - cfg.hdr.transId = 0; /* transaction identifier */ - - cfg.hdr.response.selector = 0; - cfg.hdr.response.prior = PRIOR0; - cfg.hdr.response.route = RTESPEC; - cfg.hdr.response.mem.region = S_REG; - cfg.hdr.response.mem.pool = S_POOL; - cfg.t.cfg.s.dlSapCfg.suId = nif->id; - cfg.t.cfg.s.dlSapCfg.m2uaLnkNmb = nif->m2uaLnkNmb; - cfg.t.cfg.s.dlSapCfg.mtp2LnkNmb = nif->mtp2LnkNmb; - - cfg.t.cfg.s.dlSapCfg.reConfig.m2uaPst.selector = 0; - cfg.t.cfg.s.dlSapCfg.reConfig.m2uaPst.region = S_REG; - cfg.t.cfg.s.dlSapCfg.reConfig.m2uaPst.pool = S_POOL; - cfg.t.cfg.s.dlSapCfg.reConfig.m2uaPst.route = RTESPEC; - cfg.t.cfg.s.dlSapCfg.reConfig.m2uaPst.prior = PRIOR0; - cfg.t.cfg.s.dlSapCfg.reConfig.m2uaPst.srcEnt = ENTNW; - cfg.t.cfg.s.dlSapCfg.reConfig.m2uaPst.srcInst = 0; - cfg.t.cfg.s.dlSapCfg.reConfig.m2uaPst.srcProcId = SFndProcId(); - cfg.t.cfg.s.dlSapCfg.reConfig.m2uaPst.dstEnt = ENTMW; - cfg.t.cfg.s.dlSapCfg.reConfig.m2uaPst.dstInst = 0; - cfg.t.cfg.s.dlSapCfg.reConfig.m2uaPst.dstProcId = SFndProcId(); - - cfg.t.cfg.s.dlSapCfg.reConfig.mtp2Pst.selector = 0; - cfg.t.cfg.s.dlSapCfg.reConfig.mtp2Pst.region = S_REG; - cfg.t.cfg.s.dlSapCfg.reConfig.mtp2Pst.pool = S_POOL; - cfg.t.cfg.s.dlSapCfg.reConfig.mtp2Pst.route = RTESPEC; - cfg.t.cfg.s.dlSapCfg.reConfig.mtp2Pst.prior = PRIOR0; - cfg.t.cfg.s.dlSapCfg.reConfig.mtp2Pst.srcEnt = ENTNW; - cfg.t.cfg.s.dlSapCfg.reConfig.mtp2Pst.srcInst = 0; - cfg.t.cfg.s.dlSapCfg.reConfig.mtp2Pst.srcProcId = SFndProcId(); - cfg.t.cfg.s.dlSapCfg.reConfig.mtp2Pst.dstEnt = ENTSD; - cfg.t.cfg.s.dlSapCfg.reConfig.mtp2Pst.dstInst = 0; - cfg.t.cfg.s.dlSapCfg.reConfig.mtp2Pst.dstProcId = SFndProcId(); - - return (sng_cfg_nif (&pst, &cfg)); -} - -/*****************************************************************************/ -uint32_t iptoul(const char *ip) -{ - char i,*tmp; - int strl; - char strIp[16]; - unsigned long val=0, cvt; - if (!ip) - return 0; - - memset(strIp, 0, sizeof(char)*16); - strl = strlen(ip); - strncpy(strIp, ip, strl>=15?15:strl); - - - tmp=strtok(strIp, "."); - for (i=0;i<4;i++) - { - sscanf(tmp, "%lu", &cvt); - val <<= 8; - val |= (unsigned char)cvt; - tmp=strtok(NULL,"."); - } - return (uint32_t)val; -} -/***********************************************************************************************************************/ -void ftmod_ss7_enable_m2ua_sg_logging(void){ - - /* Enable DEBUGs*/ - ftmod_sctp_debug(AENA); - ftmod_m2ua_debug(AENA); - ftmod_tucl_debug(AENA); -} - -/***********************************************************************************************************************/ -void ftmod_ss7_disable_m2ua_sg_logging(void){ - - /* DISABLE DEBUGs*/ - ftmod_sctp_debug(ADISIMM); - ftmod_m2ua_debug(ADISIMM); - ftmod_tucl_debug(ADISIMM); -} - -/***********************************************************************************************************************/ -int ftmod_ss7_m2ua_start(void){ - int x=0; - -/***********************************************************************************************************************/ - x = 1; - while(xclusterId]; - - if(clust->flags & SNGSS7_M2UA_EP_OPENED) { - ftdm_log (FTDM_LOG_INFO ," END-POINT already opened\n"); - return ret; - } - - memset((U8 *)&pst, 0, sizeof(Pst)); - memset((U8 *)&cntrl, 0, sizeof(MwMgmt)); - - smPstInit(&pst); - - pst.dstEnt = ENTMW; - - /* prepare header */ - cntrl.hdr.msgType = TCNTRL; /* message type */ - cntrl.hdr.entId.ent = ENTMW; /* entity */ - cntrl.hdr.entId.inst = 0; /* instance */ - cntrl.hdr.elmId.elmnt = STMWSCTSAP; /* General */ - cntrl.hdr.transId = 1; /* transaction identifier */ - - cntrl.hdr.response.selector = 0; - cntrl.hdr.response.prior = PRIOR0; - cntrl.hdr.response.route = RTESPEC; - cntrl.hdr.response.mem.region = S_REG; - cntrl.hdr.response.mem.pool = S_POOL; - - - cntrl.t.cntrl.action = AMWENDPOPEN; - cntrl.t.cntrl.s.suId = m2ua->id; /* M2UA sct sap Id */ - - - if(0 == (ret = sng_cntrl_m2ua (&pst, &cntrl))){ - clust->flags |= SNGSS7_M2UA_EP_OPENED; - } - return ret; - -} - -/***********************************************************************************************************************/ -static int ftmod_init_sctp_assoc(int peer_id) -{ - - Pst pst; - MwMgmt cntrl; - - memset((U8 *)&pst, 0, sizeof(Pst)); - memset((U8 *)&cntrl, 0, sizeof(MwMgmt)); - - smPstInit(&pst); - - pst.dstEnt = ENTMW; - - /* prepare header */ - cntrl.hdr.msgType = TCNTRL; /* message type */ - cntrl.hdr.entId.ent = ENTMW; /* entity */ - cntrl.hdr.entId.inst = 0; /* instance */ - cntrl.hdr.elmId.elmnt = STMWPEER; /* General */ - cntrl.hdr.transId = 1; /* transaction identifier */ - - cntrl.hdr.response.selector = 0; - cntrl.hdr.response.prior = PRIOR0; - cntrl.hdr.response.route = RTESPEC; - cntrl.hdr.response.mem.region = S_REG; - cntrl.hdr.response.mem.pool = S_POOL; - - - cntrl.t.cntrl.action = AMWESTABLISH; - /*cntrl.t.cntrl.s.suId = 1;*/ - - cntrl.t.cntrl.s.peerId = (MwPeerId) peer_id; - - return (sng_cntrl_m2ua (&pst, &cntrl)); -} - -/***********************************************************************************************************************/ -static int ftmod_sctp_tucl_tsap_bind(int id) -{ - Pst pst; - SbMgmt cntrl; - sng_sctp_link_t *k = &g_ftdm_sngss7_data.cfg.sctpCfg.linkCfg[id]; - - memset((U8 *)&pst, 0, sizeof(Pst)); - memset((U8 *)&cntrl, 0, sizeof(SbMgmt)); - - smPstInit(&pst); - - pst.dstEnt = ENTSB; - - /* prepare header */ - cntrl.hdr.msgType = TCNTRL; /* message type */ - cntrl.hdr.entId.ent = ENTSB; /* entity */ - cntrl.hdr.entId.inst = 0; /* instance */ - cntrl.hdr.elmId.elmnt = STSBTSAP; /* General */ - cntrl.hdr.transId = 1; /* transaction identifier */ - - cntrl.hdr.response.selector = 0; - - cntrl.hdr.response.prior = PRIOR0; - cntrl.hdr.response.route = RTESPEC; - cntrl.hdr.response.mem.region = S_REG; - cntrl.hdr.response.mem.pool = S_POOL; - - cntrl.t.cntrl.action = ABND_ENA; - cntrl.t.cntrl.sapId = k->id; /* SCT sap id configured at SCTP layer */ - - return (sng_cntrl_sctp (&pst, &cntrl)); -} -/***********************************************************************************************************************/ - -static int ftmod_m2ua_sctp_sctsap_bind(int id) -{ - int ret = 0x00; - Pst pst; - MwMgmt cntrl; - sng_m2ua_cfg_t* m2ua = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[id]; - sng_m2ua_cluster_cfg_t* clust = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_clus[m2ua->clusterId]; - - if(clust->flags & SNGSS7_ACTIVE) { - ftdm_log (FTDM_LOG_INFO ," SCT-SAP is already enabled\n"); - return ret; - } - - - memset((U8 *)&pst, 0, sizeof(Pst)); - memset((U8 *)&cntrl, 0, sizeof(MwMgmt)); - - smPstInit(&pst); - - pst.dstEnt = ENTMW; - - /* prepare header */ - cntrl.hdr.msgType = TCNTRL; /* message type */ - cntrl.hdr.entId.ent = ENTMW; /* entity */ - cntrl.hdr.entId.inst = 0; /* instance */ - cntrl.hdr.elmId.elmnt = STMWSCTSAP; /* General */ - cntrl.hdr.transId = 1; /* transaction identifier */ - - cntrl.hdr.response.selector = 0; - cntrl.hdr.response.prior = PRIOR0; - cntrl.hdr.response.route = RTESPEC; - cntrl.hdr.response.mem.region = S_REG; - cntrl.hdr.response.mem.pool = S_POOL; - - cntrl.t.cntrl.action = ABND; - cntrl.t.cntrl.s.suId = m2ua->id; - - if(0 == (ret = sng_cntrl_m2ua (&pst, &cntrl))){ - clust->flags |= SNGSS7_ACTIVE; - } - return ret; -} -/***********************************************************************************************************************/ -static int ftmod_nif_m2ua_dlsap_bind(int id) -{ - Pst pst; - NwMgmt cntrl; - sng_nif_cfg_t* nif = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.nif[id]; - - memset((U8 *)&pst, 0, sizeof(Pst)); - memset((U8 *)&cntrl, 0, sizeof(NwMgmt)); - - smPstInit(&pst); - - pst.dstEnt = ENTNW; - - /* prepare header */ - cntrl.hdr.msgType = TCNTRL; /* message type */ - cntrl.hdr.entId.ent = ENTNW; /* entity */ - cntrl.hdr.entId.inst = 0; /* instance */ - cntrl.hdr.elmId.elmnt = STNWDLSAP; /* General */ - cntrl.hdr.transId = 1; /* transaction identifier */ - - cntrl.hdr.response.selector = 0; - cntrl.hdr.response.prior = PRIOR0; - cntrl.hdr.response.route = RTESPEC; - cntrl.hdr.response.mem.region = S_REG; - cntrl.hdr.response.mem.pool = S_POOL; - - cntrl.t.cntrl.action = ABND; - cntrl.t.cntrl.suId = nif->id; /* NIF DL sap Id */ - cntrl.t.cntrl.entity = ENTMW; /* M2UA */ - - return (sng_cntrl_nif (&pst, &cntrl)); - -} - -/***********************************************************************************************************************/ -static int ftmod_nif_mtp2_dlsap_bind(int id) -{ - Pst pst; - NwMgmt cntrl; - sng_nif_cfg_t* nif = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.nif[id]; - - memset((U8 *)&pst, 0, sizeof(Pst)); - memset((U8 *)&cntrl, 0, sizeof(NwMgmt)); - - smPstInit(&pst); - - pst.dstEnt = ENTNW; - - /* prepare header */ - cntrl.hdr.msgType = TCNTRL; /* message type */ - cntrl.hdr.entId.ent = ENTNW; /* entity */ - cntrl.hdr.entId.inst = 0; /* instance */ - cntrl.hdr.elmId.elmnt = STNWDLSAP; /* General */ - cntrl.hdr.transId = 1; /* transaction identifier */ - - cntrl.hdr.response.selector = 0; - cntrl.hdr.response.prior = PRIOR0; - cntrl.hdr.response.route = RTESPEC; - cntrl.hdr.response.mem.region = S_REG; - cntrl.hdr.response.mem.pool = S_POOL; - - cntrl.t.cntrl.action = ABND; - cntrl.t.cntrl.suId = nif->id; /* NIF DL sap Id */ - cntrl.t.cntrl.entity = ENTSD; /* MTP2 */ - - return (sng_cntrl_nif (&pst, &cntrl)); - -} - -/***********************************************************************************************************************/ -static int ftmod_sctp_debug(int action) -{ - Pst pst; - SbMgmt cntrl; - - memset((U8 *)&pst, 0, sizeof(Pst)); - memset((U8 *)&cntrl, 0, sizeof(SbMgmt)); - - smPstInit(&pst); - - pst.dstEnt = ENTSB; - - /* prepare header */ - cntrl.hdr.msgType = TCNTRL; /* message type */ - cntrl.hdr.entId.ent = ENTSB; /* entity */ - cntrl.hdr.entId.inst = 0; /* instance */ - cntrl.hdr.elmId.elmnt = STSBGEN; /* General */ - - cntrl.hdr.response.selector = 0; - cntrl.hdr.response.prior = PRIOR0; - cntrl.hdr.response.route = RTESPEC; - cntrl.hdr.response.mem.region = S_REG; - cntrl.hdr.response.mem.pool = S_POOL; - - cntrl.t.cntrl.action = action; - cntrl.t.cntrl.subAction = SADBG; - cntrl.t.cntrl.dbgMask = 0xFFFF; - - return (sng_cntrl_sctp (&pst, &cntrl)); -} -/***********************************************************************************************************************/ - -static int ftmod_m2ua_debug(int action) -{ - Pst pst; - MwMgmt cntrl; - - memset((U8 *)&pst, 0, sizeof(Pst)); - memset((U8 *)&cntrl, 0, sizeof(MwMgmt)); - - smPstInit(&pst); - - pst.dstEnt = ENTMW; - - /* prepare header */ - cntrl.hdr.msgType = TCNTRL; /* message type */ - cntrl.hdr.entId.ent = ENTMW; /* entity */ - cntrl.hdr.entId.inst = 0; /* instance */ - cntrl.hdr.elmId.elmnt = STMWGEN; /* General */ - - cntrl.hdr.response.selector = 0; - cntrl.hdr.response.prior = PRIOR0; - cntrl.hdr.response.route = RTESPEC; - cntrl.hdr.response.mem.region = S_REG; - cntrl.hdr.response.mem.pool = S_POOL; - - cntrl.t.cntrl.action = action; - cntrl.t.cntrl.subAction = SADBG; - cntrl.t.cntrl.s.dbgMask = 0xFFFF; - - return (sng_cntrl_m2ua (&pst, &cntrl)); -} -/***********************************************************************************************************************/ -static int ftmod_tucl_debug(int action) -{ - Pst pst; - HiMngmt cntrl; - - memset((U8 *)&pst, 0, sizeof(Pst)); - memset((U8 *)&cntrl, 0, sizeof(HiMngmt)); - - smPstInit(&pst); - - pst.dstEnt = ENTHI; - - /* prepare header */ - cntrl.hdr.msgType = TCNTRL; /* message type */ - cntrl.hdr.entId.ent = ENTHI; /* entity */ - cntrl.hdr.entId.inst = 0; /* instance */ - cntrl.hdr.elmId.elmnt = STGEN; /* General */ - - cntrl.hdr.response.selector = 0; - cntrl.hdr.response.prior = PRIOR0; - cntrl.hdr.response.route = RTESPEC; - cntrl.hdr.response.mem.region = S_REG; - cntrl.hdr.response.mem.pool = S_POOL; - - cntrl.t.cntrl.action = action; - cntrl.t.cntrl.subAction = SADBG; - cntrl.t.cntrl.ctlType.hiDbg.dbgMask = 0xFFFF; - - return (sng_cntrl_tucl (&pst, &cntrl)); -} -/***********************************************************************************************************************/ - -/***********************************************************************************************************************/ -int ftmod_sctp_ssta_req(int elemt, int id, SbMgmt* cfm) -{ - SbMgmt ssta; - Pst pst; - sng_sctp_link_t *k = &g_ftdm_sngss7_data.cfg.sctpCfg.linkCfg[id]; - - memset((U8 *)&pst, 0, sizeof(Pst)); - memset((U8 *)&ssta, 0, sizeof(SbMgmt)); - - smPstInit(&pst); - - pst.dstEnt = ENTSB; - - /* prepare header */ - ssta.hdr.msgType = TSSTA; /* message type */ - ssta.hdr.entId.ent = ENTSB; /* entity */ - ssta.hdr.entId.inst = 0; /* instance */ - ssta.hdr.elmId.elmnt = elemt; /* STSBGEN */ /* Others are STSBTSAP, STSBSCTSAP, STSBASSOC, STSBDTA, STSBTMR */ - ssta.hdr.transId = 1; /* transaction identifier */ - - ssta.hdr.response.selector = 0; - ssta.hdr.response.prior = PRIOR0; - ssta.hdr.response.route = RTESPEC; - ssta.hdr.response.mem.region = S_REG; - ssta.hdr.response.mem.pool = S_POOL; - - if((ssta.hdr.elmId.elmnt == STSBSCTSAP) || (ssta.hdr.elmId.elmnt == STSBTSAP)) - { - ssta.t.ssta.sapId = k->id; /* SapId */ - } - if(ssta.hdr.elmId.elmnt == STSBASSOC) - { - /*TODO - how to get assoc Id*/ - ssta.t.ssta.s.assocSta.assocId = 0; /* association id */ - } - return(sng_sta_sctp(&pst,&ssta,cfm)); -} - -int ftmod_m2ua_ssta_req(int elemt, int id, MwMgmt* cfm) -{ - MwMgmt ssta; - Pst pst; - sng_m2ua_cfg_t* m2ua = NULL; - sng_m2ua_cluster_cfg_t* clust = NULL; - - memset((U8 *)&pst, 0, sizeof(Pst)); - memset((U8 *)&ssta, 0, sizeof(MwMgmt)); - - smPstInit(&pst); - - pst.dstEnt = ENTMW; - - /* prepare header */ - ssta.hdr.msgType = TSSTA; /* message type */ - ssta.hdr.entId.ent = ENTMW; /* entity */ - ssta.hdr.entId.inst = 0; /* instance */ - ssta.hdr.elmId.elmnt = elemt; /*STMWGEN */ /* Others are STMWSCTSAP, STMWCLUSTER, STMWPEER,STMWSID, STMWDLSAP */ - ssta.hdr.transId = 1; /* transaction identifier */ - - ssta.hdr.response.selector = 0; - ssta.hdr.response.prior = PRIOR0; - ssta.hdr.response.route = RTESPEC; - ssta.hdr.response.mem.region = S_REG; - ssta.hdr.response.mem.pool = S_POOL; - - switch(ssta.hdr.elmId.elmnt) - { - case STMWSCTSAP: - { - m2ua = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[id]; - clust = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_clus[m2ua->clusterId]; - ssta.t.ssta.id.suId = clust->sct_sap_id ; /* lower sap Id */ - break; - } - case STMWDLSAP: - { - ssta.t.ssta.id.lnkNmb = id ; /* upper sap Id */ - break; - } - case STMWPEER: - { - ssta.t.ssta.id.peerId = id ; /* peer Id */ - break; - } - case STMWCLUSTER: - { - clust = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_clus[id]; - ssta.t.ssta.id.clusterId = clust->id ; /* cluster Id */ - break; - } - default: - break; - } - - return(sng_sta_m2ua(&pst,&ssta,cfm)); -} - -int ftmod_nif_ssta_req(int elemt, int id, NwMgmt* cfm) -{ - NwMgmt ssta; - Pst pst; - sng_nif_cfg_t* nif = &g_ftdm_sngss7_data.cfg.g_m2ua_cfg.nif[id]; - - memset((U8 *)&pst, 0, sizeof(Pst)); - memset((U8 *)&ssta, 0, sizeof(NwMgmt)); - - smPstInit(&pst); - - pst.dstEnt = ENTNW; - - /* prepare header */ - ssta.hdr.msgType = TSSTA; /* message type */ - ssta.hdr.entId.ent = ENTNW; /* entity */ - ssta.hdr.entId.inst = 0; /* instance */ - ssta.hdr.elmId.elmnt = elemt; - - ssta.hdr.response.selector = 0; - ssta.hdr.response.prior = PRIOR0; - ssta.hdr.response.route = RTESPEC; - ssta.hdr.response.mem.region = S_REG; - ssta.hdr.response.mem.pool = S_POOL; - ssta.t.ssta.suId = nif->id; /* Lower sapId */ - - return(sng_sta_nif(&pst,&ssta,cfm)); -} diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_m2ua.h b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_m2ua.h deleted file mode 100644 index 8bb564d284..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_m2ua.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2012, Kapil Gupta - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Contributors: - * - */ -/******************************************************************************/ -#ifndef __FTMOD_SNG_SS7_M2UA_H__ -#define __FTMOD_SNG_SS7_M2UA_H__ -/******************************************************************************/ -#include "private/ftdm_core.h" - -#define MAX_NAME_LEN 25 - -typedef struct sng_nif_cfg{ - char name[MAX_NAME_LEN]; - uint32_t flags; - uint32_t id; - uint32_t m2uaLnkNmb; - uint32_t mtp2LnkNmb; -}sng_nif_cfg_t; - -typedef enum{ - SNG_M2UA_NODE_TYPE_SGP = 1, /* type SG */ - SNG_M2UA_NODE_TYPE_ASP = 2, /* type ASP */ -}sng_m2ua_node_types_e; - -typedef struct sng_m2ua_cfg{ - char name[MAX_NAME_LEN]; - uint32_t flags; - uint32_t id; /* ID */ - uint32_t iid; /* ID */ - uint8_t nodeType; /*Node Type SG/ASP */ - uint8_t end_point_opened; /* flag to check is end-point already opened */ - uint16_t clusterId; /* idx to m2ua_cluster profile */ -}sng_m2ua_cfg_t; - -typedef struct sng_m2ua_peer_cfg{ - char name[MAX_NAME_LEN]; - uint32_t flags; - uint32_t id; /* ID */ - uint8_t aspIdFlag; /* Flag used to indicate whether include the ASP ID in the ASP UP message */ - uint16_t selfAspId; /* Self ASP ID. ASP identifier for this ASP node if the aspIdFlag is TRUE. */ - uint32_t numDestAddr; /* Number of destination address defined */ - uint16_t sctpId; /* idx to sctp profile */ - uint16_t port; - uint32_t destAddrList[SCT_MAX_NET_ADDRS+1]; /* Destination adddress list */ - uint16_t locOutStrms; /*Number of outgoing streams supported by this association*/ - int init_sctp_assoc; /* flag to tell if we need to initiate SCTP association */ -}sng_m2ua_peer_cfg_t; - -typedef enum{ - SNG_M2UA_LOAD_SHARE_ALGO_RR = 0x1, /* Round Robin Mode*/ - SNG_M2UA_LOAD_SHARE_ALGO_LS = 0x2, /* Link Specified */ - SNG_M2UA_LOAD_SHARE_ALGO_CS = 0x3, /* Customer Specified */ -}sng_m2ua_load_share_algo_types_e; - - -/* Possible values of Traffic mode */ -typedef enum{ - SNG_M2UA_TRF_MODE_OVERRIDE = 0x1, /* Override Mode */ - SNG_M2UA_TRF_MODE_LOADSHARE = 0x2, /* Loadshare Mode */ - SNG_M2UA_TRF_MODE_BROADCAST = 0x3, /* Broadcast Mode */ - SNG_M2UA_TRF_MODE_ANY = 0x0, /* ANY Mode */ -}sng_m2ua_traffic_mode_types_e; - -typedef struct sng_m2ua_cluster_cfg{ - char name[MAX_NAME_LEN]; - uint32_t flags; - uint32_t id; /* ID */ - uint32_t sct_sap_id; /* Internal - sct_sap_id */ - uint8_t trfMode; /* Traffic mode. This parameter defines the mode in which this m2ua cluster is supposed to work */ - uint8_t loadShareAlgo; /* This parameter defines the M2UA load share algorithm which is used to distribute the traffic */ - uint16_t numOfPeers; /* idx to m2ua_peer profile */ - uint16_t peerIdLst[MW_MAX_NUM_OF_PEER]; /* idx to m2ua_peer profile */ -}sng_m2ua_cluster_cfg_t; - -typedef struct sng_m2ua_gbl_cfg{ - sng_nif_cfg_t nif[MW_MAX_NUM_OF_INTF+1]; - sng_m2ua_cfg_t m2ua[MW_MAX_NUM_OF_INTF+1]; - sng_m2ua_peer_cfg_t m2ua_peer[MW_MAX_NUM_OF_PEER+1]; - sng_m2ua_cluster_cfg_t m2ua_clus[MW_MAX_NUM_OF_CLUSTER+1]; -}sng_m2ua_gbl_cfg_t; - -/* m2ua xml parsing APIs */ -int ftmod_ss7_parse_nif_interfaces(ftdm_conf_node_t *nif_interfaces); -int ftmod_ss7_parse_m2ua_interfaces(ftdm_conf_node_t *m2ua_interfaces); -int ftmod_ss7_parse_m2ua_peer_interfaces(ftdm_conf_node_t *m2ua_peer_interfaces); -int ftmod_ss7_parse_m2ua_clust_interfaces(ftdm_conf_node_t *m2ua_clust_interfaces); -int ftmod_ss7_parse_sctp_links(ftdm_conf_node_t *node); -uint32_t iptoul(const char *ip); - -int ftmod_ss7_m2ua_start(void); -void ftmod_ss7_m2ua_free(void); - -ftdm_status_t ftmod_ss7_m2ua_cfg(void); -ftdm_status_t ftmod_ss7_m2ua_init(void); - -int ftmod_sctp_ssta_req(int elemt, int id, SbMgmt* cfm); -int ftmod_m2ua_ssta_req(int elemt, int id, MwMgmt* cfm); -int ftmod_nif_ssta_req(int elemt, int id, NwMgmt* cfm); -void ftmod_ss7_enable_m2ua_sg_logging(void); -void ftmod_ss7_disable_m2ua_sg_logging(void); - - -#endif /*__FTMOD_SNG_SS7_M2UA_H__*/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_m2ua_xml.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_m2ua_xml.c deleted file mode 100644 index bb011c364e..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_m2ua_xml.c +++ /dev/null @@ -1,690 +0,0 @@ -/* - * Copyright (c) 2012, Kapil Gupta - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Contributors: - * - * - */ - -/* INCLUDE ********************************************************************/ -#include "ftmod_sangoma_ss7_main.h" -/******************************************************************************/ - -/* DEFINES ********************************************************************/ -/******************************************************************************/ - -static int ftmod_ss7_parse_nif_interface(ftdm_conf_node_t *nif_interface); -static int ftmod_ss7_parse_m2ua_interface(ftdm_conf_node_t *m2ua_interface); -static int ftmod_ss7_parse_m2ua_peer_interface(ftdm_conf_node_t *m2ua_peer_interface); -static int ftmod_ss7_parse_m2ua_clust_interface(ftdm_conf_node_t *m2ua_clust_interface); -static int ftmod_ss7_fill_in_nif_interface(sng_nif_cfg_t *nif_iface); -static int ftmod_ss7_fill_in_m2ua_interface(sng_m2ua_cfg_t *m2ua_iface); -static int ftmod_ss7_fill_in_m2ua_peer_interface(sng_m2ua_peer_cfg_t *m2ua_peer_face); -static int ftmod_ss7_fill_in_m2ua_clust_interface(sng_m2ua_cluster_cfg_t *m2ua_cluster_face); - -static int ftmod_ss7_parse_sctp_link(ftdm_conf_node_t *node); - -/******************************************************************************/ -int ftmod_ss7_parse_nif_interfaces(ftdm_conf_node_t *nif_interfaces) -{ - ftdm_conf_node_t *nif_interface = NULL; - - /* confirm that we are looking at sng_nif_interfaces */ - if (strcasecmp(nif_interfaces->name, "sng_nif_interfaces")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"sng_nif_interfaces\"!\n",nif_interfaces->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"nif_interfaces\"...\n"); - } - - /* extract the isup_interfaces */ - nif_interface = nif_interfaces->child; - - while (nif_interface != NULL) { - /* parse the found mtp_route */ - if (ftmod_ss7_parse_nif_interface(nif_interface)) { - SS7_ERROR("Failed to parse \"nif_interface\"\n"); - return FTDM_FAIL; - } - - /* go to the next nif_interface */ - nif_interface = nif_interface->next; - } - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_nif_interface(ftdm_conf_node_t *nif_interface) -{ - sng_nif_cfg_t sng_nif; - ftdm_conf_parameter_t *parm = nif_interface->parameters; - int num_parms = nif_interface->n_parameters; - int i; - - /* initalize the nif intf and isap structure */ - memset(&sng_nif, 0x0, sizeof(sng_nif)); - - if(!nif_interface){ - SS7_ERROR("ftmod_ss7_parse_nif_interface: Null XML Node pointer \n"); - return FTDM_FAIL; - } - - /* confirm that we are looking at an nif_interface */ - if (strcasecmp(nif_interface->name, "sng_nif_interface")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"nif_interface\"!\n",nif_interface->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"nif_interface\"...\n"); - } - - - for (i = 0; i < num_parms; i++) { - /**************************************************************************/ - - /* try to match the parameter to what we expect */ - if (!strcasecmp(parm->var, "name")) { - /**********************************************************************/ - strcpy((char *)sng_nif.name, parm->val); - SS7_DEBUG("Found an nif_interface named = %s\n", sng_nif.name); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "id")) { - /**********************************************************************/ - sng_nif.id = atoi(parm->val); - SS7_DEBUG("Found an nif id = %d\n", sng_nif.id); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "m2ua-interface-id")) { - /**********************************************************************/ - sng_nif.m2uaLnkNmb = atoi(parm->val); - SS7_DEBUG("Found an nif m2ua-interface-id = %d\n", sng_nif.m2uaLnkNmb); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "mtp2-interface-id")) { - /**********************************************************************/ - sng_nif.mtp2LnkNmb=atoi(parm->val); - - SS7_DEBUG("Found an nif mtp2-interface-id = %d\n", sng_nif.mtp2LnkNmb); - /**********************************************************************/ - } else { - /**********************************************************************/ - SS7_ERROR("Found an invalid parameter %s!\n", parm->var); - return FTDM_FAIL; - /**********************************************************************/ - } - - /* move to the next parameter */ - parm = parm + 1; - /**************************************************************************/ - } /* for (i = 0; i < num_parms; i++) */ - - /* fill in the nif interface */ - ftmod_ss7_fill_in_nif_interface(&sng_nif); - - return FTDM_SUCCESS; -} -/******************************************************************************/ -static int ftmod_ss7_fill_in_nif_interface(sng_nif_cfg_t *nif_iface) -{ - int i = nif_iface->id; - - strncpy((char *)g_ftdm_sngss7_data.cfg.g_m2ua_cfg.nif[i].name, (char *)nif_iface->name, MAX_NAME_LEN-1); - - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.nif[i].id = nif_iface->id; - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.nif[i].m2uaLnkNmb = nif_iface->m2uaLnkNmb; - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.nif[i].mtp2LnkNmb = nif_iface->mtp2LnkNmb; - - sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_NIF_PRESENT); - - return 0; -} - -/******************************************************************************/ -int ftmod_ss7_parse_m2ua_interfaces(ftdm_conf_node_t *m2ua_interfaces) -{ - ftdm_conf_node_t *m2ua_interface = NULL; - - /* confirm that we are looking at sng_m2ua_interfaces */ - if (strcasecmp(m2ua_interfaces->name, "sng_m2ua_interfaces")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"m2ua_nif_interfaces\"!\n",m2ua_interfaces->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"m2ua_interfaces\"...\n"); - } - - /* extract the isup_interfaces */ - m2ua_interface = m2ua_interfaces->child; - - while (m2ua_interface != NULL) { - /* parse the found mtp_route */ - if (ftmod_ss7_parse_m2ua_interface(m2ua_interface)) { - SS7_ERROR("Failed to parse \"m2ua_interface\"\n"); - return FTDM_FAIL; - } - - /* go to the next m2ua_interface */ - m2ua_interface = m2ua_interface->next; - } - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_m2ua_interface(ftdm_conf_node_t *m2ua_interface) -{ - sng_m2ua_cfg_t sng_m2ua; - ftdm_conf_parameter_t *parm = m2ua_interface->parameters; - int num_parms = m2ua_interface->n_parameters; - int i; - - /* initalize the m2ua intf */ - memset(&sng_m2ua, 0x0, sizeof(sng_m2ua)); - - if(!m2ua_interface){ - SS7_ERROR("ftmod_ss7_parse_m2ua_interface: Null XML Node pointer \n"); - return FTDM_FAIL; - } - - /* confirm that we are looking at an nif_interface */ - if (strcasecmp(m2ua_interface->name, "sng_m2ua_interface")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"m2ua_interface\"!\n",m2ua_interface->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"m2ua_interface\"...\n"); - } - - - for (i = 0; i < num_parms; i++) { - /**************************************************************************/ - - /* try to match the parameter to what we expect */ - if (!strcasecmp(parm->var, "name")) { - /**********************************************************************/ - strcpy((char *)sng_m2ua.name, parm->val); - SS7_DEBUG("Found an m2ua_interface named = %s\n", sng_m2ua.name); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "id")) { - /**********************************************************************/ - sng_m2ua.id = atoi(parm->val); - SS7_DEBUG("Found an m2ua id = %d\n", sng_m2ua.id); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "m2ua-cluster-interface-id")) { - /**********************************************************************/ - sng_m2ua.clusterId=atoi(parm->val); - - SS7_DEBUG("Found an m2ua cluster_id = %d\n", sng_m2ua.clusterId); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "interface-identifier")) { - /**********************************************************************/ - sng_m2ua.iid=atoi(parm->val); - - SS7_DEBUG("Found an m2ua interface-identifier = %d\n", sng_m2ua.iid); - /**********************************************************************/ - } else { - /**********************************************************************/ - SS7_ERROR("Found an invalid parameter %s!\n", parm->var); - return FTDM_FAIL; - /**********************************************************************/ - } - - /* move to the next parameter */ - parm = parm + 1; - /**************************************************************************/ - } /* for (i = 0; i < num_parms; i++) */ - - sng_m2ua.nodeType = SNG_M2UA_NODE_TYPE_SGP; - - /* fill in the nif interface */ - ftmod_ss7_fill_in_m2ua_interface(&sng_m2ua); - - return FTDM_SUCCESS; -} -/******************************************************************************/ -static int ftmod_ss7_fill_in_m2ua_interface(sng_m2ua_cfg_t *m2ua_iface) -{ - int i = m2ua_iface->id; - - strncpy((char *)g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[i].name, (char *)m2ua_iface->name, MAX_NAME_LEN-1); - - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[i].id = m2ua_iface->id; - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[i].nodeType = m2ua_iface->nodeType; - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[i].clusterId = m2ua_iface->clusterId; - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[i].iid = m2ua_iface->iid; - sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_M2UA_PRESENT); - - return 0; -} - -/******************************************************************************/ -int ftmod_ss7_parse_m2ua_peer_interfaces(ftdm_conf_node_t *m2ua_peer_interfaces) -{ - ftdm_conf_node_t *m2ua_peer_interface = NULL; - - /* confirm that we are looking at m2ua_peer_interfaces */ - if (strcasecmp(m2ua_peer_interfaces->name, "sng_m2ua_peer_interfaces")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"m2ua_peer_interfaces\"!\n",m2ua_peer_interfaces->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"m2ua_peer_interfaces\"...\n"); - } - - /* extract the m2ua_peer_interfaces */ - m2ua_peer_interface = m2ua_peer_interfaces->child; - - while (m2ua_peer_interface != NULL) { - /* parse the found mtp_route */ - if (ftmod_ss7_parse_m2ua_peer_interface(m2ua_peer_interface)) { - SS7_ERROR("Failed to parse \"m2ua_peer_interface\"\n"); - return FTDM_FAIL; - } - - /* go to the next m2ua_peer_interface */ - m2ua_peer_interface = m2ua_peer_interface->next; - } - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_m2ua_peer_interface(ftdm_conf_node_t *m2ua_peer_interface) -{ - sng_m2ua_peer_cfg_t sng_m2ua_peer; - ftdm_conf_parameter_t *parm = m2ua_peer_interface->parameters; - int num_parms = m2ua_peer_interface->n_parameters; - int i; - - /* initalize the m2ua intf */ - memset(&sng_m2ua_peer, 0x0, sizeof(sng_m2ua_peer)); - - if(!m2ua_peer_interface){ - SS7_ERROR("ftmod_ss7_parse_m2ua_peer_interface: Null XML Node pointer \n"); - return FTDM_FAIL; - } - - /* confirm that we are looking at an m2ua_peer_interface */ - if (strcasecmp(m2ua_peer_interface->name, "sng_m2ua_peer_interface")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"m2ua_peer_interface\"!\n",m2ua_peer_interface->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"m2ua_peer_interface\"...\n"); - } - - for (i = 0; i < num_parms; i++) { - /**************************************************************************/ - - /* try to match the parameter to what we expect */ - if (!strcasecmp(parm->var, "name")) { - /**********************************************************************/ - strcpy((char *)sng_m2ua_peer.name, parm->val); - SS7_DEBUG("Found an sng_m2ua_peer named = %s\n", sng_m2ua_peer.name); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "id")) { - /**********************************************************************/ - sng_m2ua_peer.id = atoi(parm->val); - SS7_DEBUG("Found an sng_m2ua_peer id = %d\n", sng_m2ua_peer.id); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "include-asp-identifier")) { - /**********************************************************************/ - if(!strcasecmp(parm->val, "TRUE")){ - sng_m2ua_peer.aspIdFlag = 0x01; - } else if(!strcasecmp(parm->val, "FALSE")){ - sng_m2ua_peer.aspIdFlag = 0x00; - } else { - SS7_ERROR("Found an invalid aspIdFlag Parameter Value[%s]\n", parm->val); - return FTDM_FAIL; - } - SS7_DEBUG("Found an sng_m2ua_peer aspIdFlag = %d\n", sng_m2ua_peer.aspIdFlag); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "asp-identifier")) { - /**********************************************************************/ - sng_m2ua_peer.selfAspId=atoi(parm->val); - - SS7_DEBUG("Found an sng_m2ua_peer self_asp_id = %d\n", sng_m2ua_peer.selfAspId); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "sctp-interface-id")) { - /**********************************************************************/ - sng_m2ua_peer.sctpId = atoi(parm->val); - - SS7_DEBUG("Found an sng_m2ua_peer sctp_id = %d\n", sng_m2ua_peer.sctpId); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "destination-port")) { - /**********************************************************************/ - sng_m2ua_peer.port = atoi(parm->val); - - SS7_DEBUG("Found an sng_m2ua_peer port = %d\n", sng_m2ua_peer.port); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "address")) { - /**********************************************************************/ - if (sng_m2ua_peer.numDestAddr < SCT_MAX_NET_ADDRS) { - sng_m2ua_peer.destAddrList[sng_m2ua_peer.numDestAddr] = iptoul (parm->val); - sng_m2ua_peer.numDestAddr++; - SS7_DEBUG("sng_m2ua_peer - Parsing with dest IP Address = %s \n", parm->val); - } else { - SS7_ERROR("sng_m2ua_peer - too many dest address configured. dropping %s \n", parm->val); - } - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "number-of-outgoing-streams")) { - /**********************************************************************/ - sng_m2ua_peer.locOutStrms=atoi(parm->val); - - SS7_DEBUG("Found an sng_m2ua_peer number-of-outgoing-streams = %d\n", sng_m2ua_peer.locOutStrms); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "init-sctp-association")) { - /**********************************************************************/ - if(!strcasecmp(parm->val, "TRUE")){ - sng_m2ua_peer.init_sctp_assoc = 0x01; - } else if(!strcasecmp(parm->val, "FALSE")){ - sng_m2ua_peer.init_sctp_assoc = 0x00; - } else { - SS7_ERROR("Found an invalid init_sctp_assoc Parameter Value[%s]\n", parm->val); - return FTDM_FAIL; - } - - SS7_DEBUG("Found an sng_m2ua_peer init_sctp_assoc = %d\n", sng_m2ua_peer.init_sctp_assoc); - /**********************************************************************/ - } else { - /**********************************************************************/ - SS7_ERROR("Found an invalid parameter %s!\n", parm->var); - return FTDM_FAIL; - /**********************************************************************/ - } - - /* move to the next parameter */ - parm = parm + 1; - /**************************************************************************/ - } /* for (i = 0; i < num_parms; i++) */ - - /* fill in the sng_m2ua_peer interface */ - ftmod_ss7_fill_in_m2ua_peer_interface(&sng_m2ua_peer); - - return FTDM_SUCCESS; -} -/******************************************************************************/ -static int ftmod_ss7_fill_in_m2ua_peer_interface(sng_m2ua_peer_cfg_t *m2ua_peer_iface) -{ - int k = 0x00; - int i = m2ua_peer_iface->id; - - strncpy((char *)g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[i].name, (char *)m2ua_peer_iface->name, MAX_NAME_LEN-1); - - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[i].id = m2ua_peer_iface->id; - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[i].aspIdFlag = m2ua_peer_iface->aspIdFlag; - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[i].selfAspId = m2ua_peer_iface->selfAspId; - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[i].locOutStrms = m2ua_peer_iface->locOutStrms; - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[i].numDestAddr = m2ua_peer_iface->numDestAddr; - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[i].sctpId = m2ua_peer_iface->sctpId; - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[i].port = m2ua_peer_iface->port; - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[i].init_sctp_assoc = m2ua_peer_iface->init_sctp_assoc; - for (k=0; knumDestAddr; k++) { - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[i].destAddrList[k] = m2ua_peer_iface->destAddrList[k]; - } - - - return 0; -} - -/******************************************************************************/ -int ftmod_ss7_parse_m2ua_clust_interfaces(ftdm_conf_node_t *m2ua_cluster_interfaces) -{ - ftdm_conf_node_t *m2ua_cluster_interface = NULL; - - /* confirm that we are looking at m2ua_cluster_interfaces */ - if (strcasecmp(m2ua_cluster_interfaces->name, "sng_m2ua_cluster_interfaces")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"m2ua_cluster_interfaces\"!\n",m2ua_cluster_interfaces->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"m2ua_cluster_interfaces\"...\n"); - } - - /* extract the m2ua_cluster_interfaces */ - m2ua_cluster_interface = m2ua_cluster_interfaces->child; - - while (m2ua_cluster_interface != NULL) { - /* parse the found m2ua_cluster_interface */ - if (ftmod_ss7_parse_m2ua_clust_interface(m2ua_cluster_interface)) { - SS7_ERROR("Failed to parse \"m2ua_cluster_interface\"\n"); - return FTDM_FAIL; - } - - /* go to the next m2ua_cluster_interface */ - m2ua_cluster_interface = m2ua_cluster_interface->next; - } - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_m2ua_clust_interface(ftdm_conf_node_t *m2ua_cluster_interface) -{ - sng_m2ua_cluster_cfg_t sng_m2ua_cluster; - ftdm_conf_parameter_t *parm = m2ua_cluster_interface->parameters; - int num_parms = m2ua_cluster_interface->n_parameters; - int i; - - /* initalize the m2ua_cluster_interface */ - memset(&sng_m2ua_cluster, 0x0, sizeof(sng_m2ua_cluster)); - - if (!m2ua_cluster_interface){ - SS7_ERROR("ftmod_ss7_parse_m2ua_clust_interface - NULL XML Node pointer \n"); - return FTDM_FAIL; - } - - /* confirm that we are looking at an m2ua_cluster_interface */ - if (strcasecmp(m2ua_cluster_interface->name, "sng_m2ua_cluster_interface")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"m2ua_cluster_interface\"!\n",m2ua_cluster_interface->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"m2ua_cluster_interface\"...\n"); - } - - - for (i = 0; i < num_parms; i++) { - /**************************************************************************/ - - /* try to match the parameter to what we expect */ - if (!strcasecmp(parm->var, "name")) { - /**********************************************************************/ - strcpy((char *)sng_m2ua_cluster.name, parm->val); - SS7_DEBUG("Found an sng_m2ua_cluster named = %s\n", sng_m2ua_cluster.name); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "id")) { - /**********************************************************************/ - sng_m2ua_cluster.id = atoi(parm->val); - SS7_DEBUG("Found an sng_m2ua_cluster id = %d\n", sng_m2ua_cluster.id); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "traffic-mode")) { - /**********************************************************************/ - if(!strcasecmp(parm->val, "loadshare")){ - sng_m2ua_cluster.trfMode = SNG_M2UA_TRF_MODE_LOADSHARE; - } else if(!strcasecmp(parm->val, "override")){ - sng_m2ua_cluster.trfMode = SNG_M2UA_TRF_MODE_OVERRIDE; - } else if(!strcasecmp(parm->val, "broadcast")){ - sng_m2ua_cluster.trfMode = SNG_M2UA_TRF_MODE_BROADCAST; - } else { - SS7_ERROR("Found an invalid trfMode Parameter Value[%s]..adding default one[ANY]\n", parm->val); - sng_m2ua_cluster.trfMode = SNG_M2UA_TRF_MODE_ANY; - } - SS7_DEBUG("Found an sng_m2ua_cluster.trfMode = %d\n", sng_m2ua_cluster.trfMode); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "load-share-algorithm")) { - /**********************************************************************/ - if(!strcasecmp(parm->val, "roundrobin")){ - sng_m2ua_cluster.loadShareAlgo = SNG_M2UA_LOAD_SHARE_ALGO_RR; - } else if(!strcasecmp(parm->val, "linkspecified")){ - sng_m2ua_cluster.loadShareAlgo = SNG_M2UA_LOAD_SHARE_ALGO_LS; - } else if(!strcasecmp(parm->val, "customerspecified")){ - sng_m2ua_cluster.loadShareAlgo = SNG_M2UA_LOAD_SHARE_ALGO_CS; - } else { - SS7_ERROR("Found an invalid loadShareAlgo Parameter Value[%s]\n", parm->val); - return FTDM_FAIL; - } - - SS7_DEBUG("Found an sng_m2ua_cluster.loadShareAlgo = %d\n", sng_m2ua_cluster.loadShareAlgo); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "m2ua-peer-interface-id")) { - /**********************************************************************/ - if(sng_m2ua_cluster.numOfPeers < MW_MAX_NUM_OF_PEER) { - sng_m2ua_cluster.peerIdLst[sng_m2ua_cluster.numOfPeers] = atoi(parm->val); - SS7_DEBUG("Found an sng_m2ua_cluster peerId[%d], Total numOfPeers[%d] \n", - sng_m2ua_cluster.peerIdLst[sng_m2ua_cluster.numOfPeers], - sng_m2ua_cluster.numOfPeers+1); - sng_m2ua_cluster.numOfPeers++; - }else{ - SS7_ERROR("Peer List excedding max[%d] limit \n", MW_MAX_NUM_OF_PEER); - return FTDM_FAIL; - } - /**********************************************************************/ - } else { - /**********************************************************************/ - SS7_ERROR("Found an invalid parameter %s!\n", parm->var); - return FTDM_FAIL; - /**********************************************************************/ - } - - /* move to the next parameter */ - parm = parm + 1; - /**************************************************************************/ - } /* for (i = 0; i < num_parms; i++) */ - - /* fill in the sng_m2ua_peer interface */ - ftmod_ss7_fill_in_m2ua_clust_interface(&sng_m2ua_cluster); - - return FTDM_SUCCESS; -} -/******************************************************************************/ -static int ftmod_ss7_fill_in_m2ua_clust_interface(sng_m2ua_cluster_cfg_t *m2ua_cluster_iface) -{ - int k = 0x00; - int i = m2ua_cluster_iface->id; - - strncpy((char *)g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_clus[i].name, (char *)m2ua_cluster_iface->name, MAX_NAME_LEN-1); - - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_clus[i].id = m2ua_cluster_iface->id; - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_clus[i].trfMode = m2ua_cluster_iface->trfMode; - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_clus[i].loadShareAlgo = m2ua_cluster_iface->loadShareAlgo; - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_clus[i].numOfPeers = m2ua_cluster_iface->numOfPeers; - for(k=0;knumOfPeers;k++){ - g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_clus[i].peerIdLst[k] = m2ua_cluster_iface->peerIdLst[k]; - } - - return 0; -} - -/******************************************************************************/ -int ftmod_ss7_parse_sctp_links(ftdm_conf_node_t *node) -{ - ftdm_conf_node_t *node_sctp_link = NULL; - - if (!node) - return FTDM_FAIL; - - if (strcasecmp(node->name, "sng_sctp_interfaces")) { - SS7_ERROR("SCTP - We're looking at <%s>...but we're supposed to be looking at !\n", node->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("SCTP - Parsing configurations\n"); - } - - for (node_sctp_link = node->child; node_sctp_link != NULL; node_sctp_link = node_sctp_link->next) { - if (ftmod_ss7_parse_sctp_link(node_sctp_link) != FTDM_SUCCESS) { - SS7_ERROR("SCTP - Failed to parse . \n"); - return FTDM_FAIL; - } - } - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_sctp_link(ftdm_conf_node_t *node) -{ - ftdm_conf_parameter_t *param = NULL; - int num_params = 0; - int i=0; - - if (!node){ - SS7_ERROR("SCTP - NULL XML Node pointer \n"); - return FTDM_FAIL; - } - - param = node->parameters; - num_params = node->n_parameters; - - sng_sctp_link_t t_link; - memset (&t_link, 0, sizeof(sng_sctp_link_t)); - - if (strcasecmp(node->name, "sng_sctp_interface")) { - SS7_ERROR("SCTP - We're looking at <%s>...but we're supposed to be looking at !\n", node->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("SCTP - Parsing configurations\n"); - } - - for (i=0; ivar, "name")) { - int n_strlen = strlen(param->val); - strncpy((char*)t_link.name, param->val, (n_strlen>MAX_NAME_LEN)?MAX_NAME_LEN:n_strlen); - SS7_DEBUG("SCTP - Parsing with name = %s\n", param->val); - } - else if (!strcasecmp(param->var, "id")) { - t_link.id = atoi(param->val); - SS7_DEBUG("SCTP - Parsing with id = %s\n", param->val); - } - else if (!strcasecmp(param->var, "address")) { - if (t_link.numSrcAddr < SCT_MAX_NET_ADDRS) { - t_link.srcAddrList[t_link.numSrcAddr+1] = iptoul (param->val); - t_link.numSrcAddr++; - SS7_DEBUG("SCTP - Parsing with source IP Address = %s\n", param->val); - } else { - SS7_ERROR("SCTP - too many source address configured. dropping %s \n", param->val); - } - } else if (!strcasecmp(param->var, "source-port")) { - t_link.port = atoi(param->val); - SS7_DEBUG("SCTP - Parsing with port = %s\n", param->val); - } - else { - SS7_ERROR("SCTP - Found an unknown parameter <%s>. Skipping it.\n", param->var); - } - } - - g_ftdm_sngss7_data.cfg.sctpCfg.linkCfg[t_link.id].id = t_link.id; - g_ftdm_sngss7_data.cfg.sctpCfg.linkCfg[t_link.id].port = t_link.port; - strncpy((char*)g_ftdm_sngss7_data.cfg.sctpCfg.linkCfg[t_link.id].name, t_link.name, strlen(t_link.name) ); - g_ftdm_sngss7_data.cfg.sctpCfg.linkCfg[t_link.id].numSrcAddr = t_link.numSrcAddr; - for (i=1; i<=t_link.numSrcAddr; i++) { - g_ftdm_sngss7_data.cfg.sctpCfg.linkCfg[t_link.id].srcAddrList[i] = t_link.srcAddrList[i]; - } - - sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_SCTP_PRESENT); - - return FTDM_SUCCESS; -} -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c deleted file mode 100644 index 47c88c29c5..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c +++ /dev/null @@ -1,2766 +0,0 @@ -/* - * Copyright (c) 2009, Sangoma Technologies - * Konrad Hammel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Contributors: - * - * Moises Silva - * David Yat Sin - * James Zhang - * - */ - -/* INCLUDE ********************************************************************/ -#include "ftmod_sangoma_ss7_main.h" -/******************************************************************************/ - -/* DEFINES ********************************************************************/ -/******************************************************************************/ - -/* GLOBALS ********************************************************************/ -static sng_isup_event_interface_t sng_event; -static ftdm_io_interface_t g_ftdm_sngss7_interface; -ftdm_sngss7_data_t g_ftdm_sngss7_data; -ftdm_sngss7_opr_mode g_ftdm_operating_mode; - -/******************************************************************************/ - -/* PROTOTYPES *****************************************************************/ -static void *ftdm_sangoma_ss7_run (ftdm_thread_t * me, void *obj); -static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_event); -static void ftdm_sangoma_ss7_process_peer_stack_event (ftdm_channel_t *ftdmchan, sngss7_event_data_t *sngss7_event); - -static ftdm_status_t ftdm_sangoma_ss7_stop (ftdm_span_t * span); -static ftdm_status_t ftdm_sangoma_ss7_start (ftdm_span_t * span); -/******************************************************************************/ - - -/* STATE MAP ******************************************************************/ -ftdm_state_map_t sangoma_ss7_state_map = { - { - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_DOWN, - FTDM_CHANNEL_STATE_IN_LOOP, FTDM_CHANNEL_STATE_COLLECT, - FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_PROGRESS, - FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, - FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_TERMINATING, - FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_TERMINATING, - FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, - FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_IDLE, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_IDLE, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_IN_LOOP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_DOWN, - FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_RING, - FTDM_CHANNEL_STATE_IDLE, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, - FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, - FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, - FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, - FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, - FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END} - }, - /**************************************************************************/ - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_DOWN, - FTDM_CHANNEL_STATE_IN_LOOP, FTDM_CHANNEL_STATE_DIALING, - FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, - FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_CANCEL, - FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, - FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_TERMINATING, - FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, - FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_IDLE, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_IDLE, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_IN_LOOP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_TERMINATING, - FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, - FTDM_CHANNEL_STATE_PROGRESS_MEDIA ,FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, - FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, - FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_END}, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_END} - }, - } -}; - -static void handle_hw_alarm(ftdm_event_t *e) -{ - sngss7_chan_data_t *ss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - int x = 0; - - ftdm_assert(e != NULL, "Null event!\n"); - - SS7_DEBUG("handle_hw_alarm event [%d/%d]\n",e->channel->physical_span_id,e->channel->physical_chan_id); - - for (x = (g_ftdm_sngss7_data.cfg.procId * MAX_CIC_MAP_LENGTH) + 1; g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0; x++) { - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - - /* NC. Its possible for alarms to come in the middle of configuration - especially on large systems */ - if (!ss7_info || !ss7_info->ftdmchan) { - SS7_DEBUG("handle_hw_alarm: span=%i chan=%i ckt=%i x=%i - ss7_info=%p ftdmchan=%p\n", - ftdmchan->physical_span_id,ftdmchan->physical_chan_id, - g_ftdm_sngss7_data.cfg.isupCkt[x].id,x, - ss7_info,ss7_info?ss7_info->ftdmchan:NULL); - continue; - } - - ftdmchan = ss7_info->ftdmchan; - - if (e->channel->physical_span_id == ftdmchan->physical_span_id && - e->channel->physical_chan_id == ftdmchan->physical_chan_id) { - SS7_DEBUG_CHAN(ftdmchan,"handle_hw_alarm: span=%i chan=%i ckt=%i x=%i\n", - ftdmchan->physical_span_id,ftdmchan->physical_chan_id,g_ftdm_sngss7_data.cfg.isupCkt[x].id,x); - if (e->enum_id == FTDM_OOB_ALARM_TRAP) { - SS7_DEBUG_CHAN(ftdmchan,"handle_hw_alarm: Set FLAG_GRP_HW_BLOCK_TX %s\n", " "); - sngss7_set_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX); - if (ftdmchan->state != FTDM_CHANNEL_STATE_SUSPENDED) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - } - } else if (e->enum_id == FTDM_OOB_ALARM_CLEAR) { - SS7_DEBUG_CHAN(ftdmchan,"handle_hw_alarm: Clear %s \n", " "); - sngss7_clear_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX); - sngss7_clear_ckt_blk_flag(ss7_info, FLAG_GRP_HW_UNBLK_TX); - if (sngss7_test_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX_DN)) { - sngss7_set_ckt_blk_flag(ss7_info, FLAG_GRP_HW_UNBLK_TX); - SS7_DEBUG_CHAN(ftdmchan,"handle_hw_alarm: Setting FLAG_GRP_HW_UNBLK_TX %s\n"," "); - if (ftdmchan->state != FTDM_CHANNEL_STATE_SUSPENDED) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - } - } - } - } - } - } -} - - -static void check_span_oob_events(ftdm_span_t *ftdmspan) -{ - ftdm_event_t *event = NULL; - /* Poll for events, e.g HW DTMF */ - switch (ftdm_span_poll_event(ftdmspan, 0, NULL)) { - /**********************************************************************/ - case FTDM_SUCCESS: - while (ftdm_span_next_event(ftdmspan, &event) == FTDM_SUCCESS) { - if (event->e_type == FTDM_EVENT_OOB) { - handle_hw_alarm(event); - } - } - break; - /**********************************************************************/ - case FTDM_TIMEOUT: - /* No events pending */ - break; - /**********************************************************************/ - default: - SS7_ERROR("%s:Failed to poll span event\n", ftdmspan->name); - /**********************************************************************/ - } -} - -/* MONITIOR THREADS ***********************************************************/ -static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj) -{ - ftdm_interrupt_t *ftdm_sangoma_ss7_int[2]; - ftdm_span_t *ftdmspan = (ftdm_span_t *) obj; - ftdm_channel_t *ftdmchan = NULL; - sngss7_event_data_t *sngss7_event = NULL; - sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data; - - int b_alarm_test = 1; - sngss7_chan_data_t *ss7_info=NULL; - - ftdm_log (FTDM_LOG_INFO, "ftmod_sangoma_ss7 monitor thread for span=%u started.\n", ftdmspan->span_id); - - /* set IN_THREAD flag so that we know this thread is running */ - ftdm_set_flag (ftdmspan, FTDM_SPAN_IN_THREAD); - - - - /* get an interrupt queue for this span for channel state changes */ - if (ftdm_queue_get_interrupt (ftdmspan->pendingchans, &ftdm_sangoma_ss7_int[0]) != FTDM_SUCCESS) { - SS7_CRITICAL ("Failed to get a ftdm_interrupt for span = %d for channel state changes!\n", ftdmspan->span_id); - goto ftdm_sangoma_ss7_run_exit; - } - - /* get an interrupt queue for this span for Trillium events */ - if (ftdm_queue_get_interrupt (sngss7_span->event_queue, &ftdm_sangoma_ss7_int[1]) != FTDM_SUCCESS) { - SS7_CRITICAL ("Failed to get a ftdm_interrupt for span = %d for Trillium event queue!\n", ftdmspan->span_id); - goto ftdm_sangoma_ss7_run_exit; - } - - if(SNG_SS7_OPR_MODE_M2UA_SG == g_ftdm_operating_mode){ - ftdm_log (FTDM_LOG_INFO, "FreeTDM running as M2UA_SG mode, freetdm dont have to do anything \n"); - - while (ftdm_running () && !(ftdm_test_flag (ftdmspan, FTDM_SPAN_STOP_THREAD))) { - - switch ((ftdm_interrupt_multiple_wait(ftdm_sangoma_ss7_int, ftdm_array_len(ftdm_sangoma_ss7_int), 100))) { - - case FTDM_SUCCESS: /* process all pending state changes */ - - SS7_DEVEL_DEBUG ("ftdm_interrupt_wait FTDM_SUCCESS on span = %d\n",ftdmspan->span_id); - - /**********************************************************************/ - case FTDM_TIMEOUT: - SS7_DEVEL_DEBUG ("ftdm_interrupt_wait timed-out on span = %d\n",ftdmspan->span_id); - - break; - /**********************************************************************/ - case FTDM_FAIL: - SS7_ERROR ("ftdm_interrupt_wait returned error!\non span = %d\n", ftdmspan->span_id); - - break; - /**********************************************************************/ - default: - SS7_ERROR("ftdm_interrupt_wait returned with unknown code on span = %d\n",ftdmspan->span_id); - - break; - /**********************************************************************/ - } - check_span_oob_events(ftdmspan); - - /* signal the core that sig events are queued for processing */ - ftdm_span_trigger_signals(ftdmspan); - } - goto ftdm_sangoma_ss7_stop; - } - - while (ftdm_running () && !(ftdm_test_flag (ftdmspan, FTDM_SPAN_STOP_THREAD))) { - int x = 0; - if (b_alarm_test) { - b_alarm_test = 0; - for (x = (g_ftdm_sngss7_data.cfg.procId * MAX_CIC_MAP_LENGTH) + 1; - g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0; x++) { - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - ftdmchan = ss7_info->ftdmchan; - if (!ftdmchan) { - continue; - } - - if (ftdmchan->alarm_flags != 0) { /* we'll send out block */ - sngss7_set_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX ); - } else { /* we'll send out reset */ - if (sngss7_test_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX )) { - sngss7_clear_ckt_blk_flag( ss7_info, FLAG_GRP_HW_BLOCK_TX ); - sngss7_clear_ckt_blk_flag( ss7_info, FLAG_GRP_HW_BLOCK_TX_DN ); - sngss7_set_ckt_blk_flag (ss7_info, FLAG_GRP_HW_UNBLK_TX); - SS7_DEBUG("b_alarm_test FLAG_GRP_HW_UNBLK_TX\n"); - } - } - } - usleep(50); - } - ftdmchan = NULL; - } - - /* check the channel state queue for an event*/ - switch ((ftdm_interrupt_multiple_wait(ftdm_sangoma_ss7_int, ftdm_array_len(ftdm_sangoma_ss7_int), 100))) { - /**********************************************************************/ - case FTDM_SUCCESS: /* process all pending state changes */ - - /* clean out all pending channel state changes */ - while ((ftdmchan = ftdm_queue_dequeue (ftdmspan->pendingchans))) { - sngss7_chan_data_t *chan_info = ftdmchan->call_data; - - /*first lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* process state changes for this channel until they are all done */ - ftdm_channel_advance_states(ftdmchan); - - if (chan_info->peer_data) { - /* clean out all pending stack events in the peer channel */ - while ((sngss7_event = ftdm_queue_dequeue(chan_info->event_queue))) { - ftdm_sangoma_ss7_process_peer_stack_event(ftdmchan, sngss7_event); - ftdm_safe_free(sngss7_event); - } - } - - /* unlock the channel */ - ftdm_mutex_unlock (ftdmchan->mutex); - } - - /* clean out all pending stack events */ - while ((sngss7_event = ftdm_queue_dequeue(sngss7_span->event_queue))) { - ftdm_sangoma_ss7_process_stack_event(sngss7_event); - ftdm_safe_free(sngss7_event); - } - - /* signal the core that sig events are queued for processing */ - ftdm_span_trigger_signals(ftdmspan); - - break; - /**********************************************************************/ - case FTDM_TIMEOUT: - SS7_DEVEL_DEBUG ("ftdm_interrupt_wait timed-out on span = %d\n",ftdmspan->span_id); - - break; - /**********************************************************************/ - case FTDM_FAIL: - SS7_ERROR ("ftdm_interrupt_wait returned error!\non span = %d\n", ftdmspan->span_id); - - break; - /**********************************************************************/ - default: - SS7_ERROR("ftdm_interrupt_wait returned with unknown code on span = %d\n",ftdmspan->span_id); - - break; - /**********************************************************************/ - } - - /* check if there is a GRA to proccess on the span */ - if (ftdm_test_flag(sngss7_span, SNGSS7_RX_GRA_PENDING)) { - check_if_rx_gra_started(ftdmspan); - } - - /* check if there is a GRS being processed on the span */ - if (ftdm_test_flag(sngss7_span, SNGSS7_RX_GRS_PENDING)) { - /* check if the rx_grs has started */ - check_if_rx_grs_started(ftdmspan); - - /* check if the rx_grs has cleared */ - check_if_rx_grs_processed(ftdmspan); - } - - /* check if there is a UCIC to be processed on the span */ - if (ftdm_test_flag(sngss7_span, SNGSS7_UCIC_PENDING)) { - /* process the span wide UCIC */ - process_span_ucic(ftdmspan); - } - - /* check each channel on the span to see if there is an un-procressed SUS/RES flag */ - check_for_res_sus_flag(ftdmspan); - - /* check each channel on the span to see if it needs to be reconfigured */ - check_for_reconfig_flag(ftdmspan); - - check_span_oob_events(ftdmspan); - } -ftdm_sangoma_ss7_stop: - - /* clear the IN_THREAD flag so that we know the thread is done */ - ftdm_clear_flag (ftdmspan, FTDM_SPAN_IN_THREAD); - - - ftdm_log (FTDM_LOG_INFO,"ftmod_sangoma_ss7 monitor thread for span=%u stopping.\n",ftdmspan->span_id); - - return NULL; - -ftdm_sangoma_ss7_run_exit: - - /* clear the IN_THREAD flag so that we know the thread is done */ - ftdm_clear_flag (ftdmspan, FTDM_SPAN_IN_THREAD); - - ftdm_log (FTDM_LOG_INFO,"ftmod_sangoma_ss7 monitor thread for span=%u stopping due to error.\n",ftdmspan->span_id); - - ftdm_sangoma_ss7_stop (ftdmspan); - - return NULL; -} - -/******************************************************************************/ -static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_event) -{ - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_event_data_t *event_clone = NULL; - int clone_event = 0; - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(sngss7_event->circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", sngss7_event->circuit); - return; - } - - /* now that we have the right channel ... put a lock on it so no-one else can use it */ - ftdm_channel_lock(ftdmchan); - - /* while there's a state change present on this channel process it */ - ftdm_channel_advance_states(ftdmchan); - - if (sngss7_event->event_id == SNGSS7_CON_IND_EVENT) { - clone_event++; - } - - /* If the call has already started (we only bridge events related to calls) - * and the event is not a release confirmation, then clone the event. - * We do not clone release cfm events because that is the only event (final event) that is not - * bridged to the other leg, the first Spirou customer we had explicitly requested to send - * release confirm as soon as the release is received and therefore not wait for the other leg - * to send release confirm (hence, not need to clone and enqueue in the other leg) */ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED) && sngss7_event->event_id != SNGSS7_REL_CFM_EVENT) { - clone_event++; - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) { - - if (sngss7_event->event_id == SNGSS7_SUSP_IND_EVENT) { - sngss7_set_ckt_flag(sngss7_info, FLAG_SUS_RECVD); - sngss7_clear_ckt_flag(sngss7_info, FLAG_T6_CANCELED); - } - - if (sngss7_test_ckt_flag(sngss7_info, FLAG_SUS_RECVD) && - !sngss7_test_ckt_flag(sngss7_info, FLAG_T6_CANCELED)) { - if (sng_cancel_isup_tmr(sngss7_info->suInstId, ISUP_T6i) == RFAILED ) { - SS7_ERROR_CHAN(ftdmchan,"[CIC:%d]could not stop timer T6 \n", sngss7_info->circuit->cic); - } else { - sngss7_set_ckt_flag(sngss7_info, FLAG_T6_CANCELED); - SS7_ERROR_CHAN(ftdmchan,"[CIC:%d] isup timer T6 has been cancelled. \n", sngss7_info->circuit->cic); - } - } - } - - /* clone the event and save it for later usage, we do not clone RLC messages */ - if (clone_event) { - event_clone = ftdm_calloc(1, sizeof(*sngss7_event)); - if (event_clone) { - memcpy(event_clone, sngss7_event, sizeof(*sngss7_event)); - /* if we have already a peer channel then enqueue the event in their queue */ - if (sngss7_info->peer_data) { - ftdm_span_t *peer_span = sngss7_info->peer_data->ftdmchan->span; - if (sngss7_info->peer_event_transfer_cnt) { - sngss7_event_data_t *peer_event = NULL; - int qi = 0; - /* looks like for the first time we found our peer, transfer any messages we enqueued */ - for (qi = 0; qi < sngss7_info->peer_event_transfer_cnt; qi++) { - peer_event = ftdm_queue_dequeue(sngss7_info->event_queue); - if (peer_event) { - ftdm_queue_enqueue(sngss7_info->peer_data->event_queue, peer_event); - } else { - /* This should never happen! */ - SS7_CRIT_CHAN(ftdmchan,"[CIC:%d]What!? someone stole my messages!\n", sngss7_info->circuit->cic); - } - } - SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Transferred %d messages into my peer's queue\n", - sngss7_info->circuit->cic, sngss7_info->peer_event_transfer_cnt); - sngss7_info->peer_event_transfer_cnt = 0; - } - /* we already have a peer attached, wake him up */ - ftdm_queue_enqueue(sngss7_info->peer_data->event_queue, event_clone); - ftdm_queue_enqueue(peer_span->pendingchans, sngss7_info->peer_data->ftdmchan); - } else { - /* we don't have a peer yet, save the event on our own queue for later - * only the first event in this queue is directly consumed by our peer (IAM), subsequent events - * must be transferred by us to their queue as soon as we find our peer */ - ftdm_queue_enqueue(sngss7_info->event_queue, event_clone); - if (sngss7_event->event_id != SNGSS7_CON_IND_EVENT) { - /* This could be an SAM, save it for transfer once we know who our peer is (if we ever find that) */ - sngss7_info->peer_event_transfer_cnt++; - } - } - } - } - - /* we could test for sngss7_info->peer_data too, bit this flag is set earlier, the earlier we know the better */ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) { - /* most messages are simply relayed in sig bridge mode, except for hangup which requires state changing */ - switch (sngss7_event->event_id) { - case SNGSS7_REL_IND_EVENT: - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - break; - case SNGSS7_REL_CFM_EVENT: - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - break; - default: - break; - } - goto done; - } - - /* figure out the type of event and send it to the right handler */ - switch (sngss7_event->event_id) { - /**************************************************************************/ - case (SNGSS7_CON_IND_EVENT): - handle_con_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siConEvnt); - break; - /**************************************************************************/ - case (SNGSS7_CON_CFM_EVENT): - handle_con_cfm(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siConEvnt); - break; - /**************************************************************************/ - case (SNGSS7_CON_STA_EVENT): - handle_con_sta(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siCnStEvnt, sngss7_event->evntType); - break; - /**************************************************************************/ - case (SNGSS7_REL_IND_EVENT): - handle_rel_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siRelEvnt); - break; - /**************************************************************************/ - case (SNGSS7_REL_CFM_EVENT): - handle_rel_cfm(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siRelEvnt); - break; - /**************************************************************************/ - case (SNGSS7_DAT_IND_EVENT): - handle_dat_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siInfoEvnt); - break; - /**************************************************************************/ - case (SNGSS7_FAC_IND_EVENT): - handle_fac_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, sngss7_event->evntType, &sngss7_event->event.siFacEvnt); - break; - /**************************************************************************/ - case (SNGSS7_FAC_CFM_EVENT): - handle_fac_cfm(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, sngss7_event->evntType, &sngss7_event->event.siFacEvnt); - break; - /**************************************************************************/ - case (SNGSS7_UMSG_IND_EVENT): - handle_umsg_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit); - break; - /**************************************************************************/ - case (SNGSS7_STA_IND_EVENT): - handle_sta_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, sngss7_event->globalFlg, sngss7_event->evntType, &sngss7_event->event.siStaEvnt); - break; - /**************************************************************************/ - case (SNGSS7_SUSP_IND_EVENT): - handle_susp_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siSuspEvnt); - break; - /**************************************************************************/ - case (SNGSS7_RESM_IND_EVENT): - handle_resm_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siResmEvnt); - break; - /**************************************************************************/ - case (SNGSS7_SSP_STA_CFM_EVENT): - SS7_ERROR("dazed and confused ... hu?!\n"); - break; - /**************************************************************************/ - default: - SS7_ERROR("Unknown Event Id!\n"); - break; - /**************************************************************************/ - } - -done: - /* while there's a state change present on this channel process it */ - ftdm_channel_advance_states(ftdmchan); - - /* unlock the channel */ - ftdm_channel_unlock(ftdmchan); - -} - -FTDM_ENUM_NAMES(SNG_EVENT_TYPE_NAMES, SNG_EVENT_TYPE_STRINGS) -FTDM_STR2ENUM(ftdm_str2sngss7_event, ftdm_sngss7_event2str, sng_event_type_t, SNG_EVENT_TYPE_NAMES, SNGSS7_INVALID_EVENT) -static void ftdm_sangoma_ss7_process_peer_stack_event (ftdm_channel_t *ftdmchan, sngss7_event_data_t *sngss7_event) -{ - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - if (ftdmchan->state < FTDM_CHANNEL_STATE_UP && ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); - ftdm_channel_advance_states(ftdmchan); - } - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Receiving message %s from bridged peer (our state = %s)\n", - sngss7_info->circuit->cic, ftdm_sngss7_event2str(sngss7_event->event_id), ftdm_channel_state2str(ftdmchan->state)); - - switch (sngss7_event->event_id) { - - case (SNGSS7_CON_IND_EVENT): - SS7_ERROR_CHAN(ftdmchan,"[CIC:%d]Rx IAM while bridged??\n", sngss7_info->circuit->cic); - break; - - case (SNGSS7_CON_CFM_EVENT): - /* send the ANM request to LibSngSS7 */ - sng_cc_con_response(1, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, - &sngss7_event->event.siConEvnt, - 5); - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Tx peer ANM\n", sngss7_info->circuit->cic); - break; - - case (SNGSS7_CON_STA_EVENT): - switch (sngss7_event->evntType) { - /**************************************************************************/ - case (ADDRCMPLT): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer ACM\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (MODIFY): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer MODIFY\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (MODCMPLT): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer MODIFY-COMPLETE\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (MODREJ): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer MODIFY-REJECT\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (PROGRESS): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CPG\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (FRWDTRSFR): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer FOT\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (INFORMATION): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer INF\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (INFORMATREQ): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer INR\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (SUBSADDR): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer SAM\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (EXIT): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer EXIT\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (NETRESMGT): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer NRM\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (IDENTREQ): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer IDR\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (IDENTRSP): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer IRS\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (MALCLLPRNT): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer MALICIOUS CALL\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (CHARGE): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CRG\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (TRFFCHGE): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CRG-TARIFF\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (CHARGEACK): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CRG-ACK\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (CALLOFFMSG): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CALL-OFFER\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (LOOPPRVNT): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer LOP\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (TECT_TIMEOUT): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer ECT-Timeout\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (RINGSEND): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer RINGING-SEND\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (CALLCLEAR): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CALL-LINE Clear\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (PRERELEASE): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer PRI\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (APPTRANSPORT): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer APM\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (OPERATOR): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer OPERATOR\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (METPULSE): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer METERING-PULSE\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (CLGPTCLR): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CALLING_PARTY_CLEAR\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (SUBDIRNUM): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer SUB-DIR\n", sngss7_info->circuit->cic); - break; -#ifdef SANGOMA_SPIROU - case (CHARGE_ACK): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer TXA\n", sngss7_info->circuit->cic); - break; - case (CHARGE_UNIT): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer ITX\n", sngss7_info->circuit->cic); - break; -#endif - /**************************************************************************/ - default: - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer Unknown Msg %d\n", sngss7_info->circuit->cic, sngss7_event->evntType); - break; - /**************************************************************************/ - } - sng_cc_con_status (1, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, - &sngss7_event->event.siCnStEvnt, - sngss7_event->evntType); - - break; - /**************************************************************************/ - case (SNGSS7_REL_IND_EVENT): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer REL cause=%d\n", sngss7_info->circuit->cic, sngss7_event->event.siRelEvnt.causeDgn.causeVal.val); - - //handle_rel_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siRelEvnt); - sng_cc_rel_request (1, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, - &sngss7_event->event.siRelEvnt); - break; - - /**************************************************************************/ - case (SNGSS7_REL_CFM_EVENT): - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer RLC\n", sngss7_info->circuit->cic); - sng_cc_rel_response (1, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, - &sngss7_event->event.siRelEvnt); - //handle_rel_cfm(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siRelEvnt); - break; - - /**************************************************************************/ - case (SNGSS7_DAT_IND_EVENT): - //handle_dat_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siInfoEvnt); - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer %s\n", sngss7_info->circuit->cic, ftdm_sngss7_event2str(sngss7_event->event_id)); - sng_cc_dat_request(1, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, - &sngss7_event->event.siInfoEvnt); - break; - /**************************************************************************/ - case (SNGSS7_FAC_IND_EVENT): - //handle_fac_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, sngss7_event->evntType, - //&sngss7_event->event.siFacEvnt); - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer %s -> %d\n", sngss7_info->circuit->cic, - ftdm_sngss7_event2str(sngss7_event->event_id), sngss7_event->evntType); - sng_cc_fac_request(1, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, - sngss7_event->evntType, - &sngss7_event->event.siFacEvnt); - - break; - /**************************************************************************/ - case (SNGSS7_FAC_CFM_EVENT): - //handle_fac_cfm(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, - //sngss7_event->evntType, &sngss7_event->event.siFacEvnt); - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer %s -> %d\n", sngss7_info->circuit->cic, - ftdm_sngss7_event2str(sngss7_event->event_id), sngss7_event->evntType); - sng_cc_fac_response(1, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, - sngss7_event->evntType, - &sngss7_event->event.siFacEvnt); - break; - /**************************************************************************/ - case (SNGSS7_UMSG_IND_EVENT): - //handle_umsg_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit); - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer %s\n", sngss7_info->circuit->cic, ftdm_sngss7_event2str(sngss7_event->event_id)); - sng_cc_umsg_request (1, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id); - break; - /**************************************************************************/ - case (SNGSS7_STA_IND_EVENT): - //handle_sta_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, sngss7_event->globalFlg, sngss7_event->evntType, &sngss7_event->event.siStaEvnt); - break; - /**************************************************************************/ - case (SNGSS7_SUSP_IND_EVENT): - //handle_susp_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siSuspEvnt); - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer %s\n", sngss7_info->circuit->cic, ftdm_sngss7_event2str(sngss7_event->event_id)); - sng_cc_susp_request (1, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, - &sngss7_event->event.siSuspEvnt); - break; - /**************************************************************************/ - case (SNGSS7_RESM_IND_EVENT): - //handle_resm_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siResmEvnt); - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer %s\n", sngss7_info->circuit->cic, ftdm_sngss7_event2str(sngss7_event->event_id)); - sng_cc_resm_request(1, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, - &sngss7_event->event.siResmEvnt); - break; - /**************************************************************************/ - case (SNGSS7_SSP_STA_CFM_EVENT): - SS7_CRITICAL("dazed and confused ... hu?!\n"); - break; - /**************************************************************************/ - default: - SS7_ERROR("Failed to relay unknown event id %d!\n", sngss7_event->event_id); - break; - /**************************************************************************/ - } - - if ((sngss7_event->event_id == SNGSS7_SUSP_IND_EVENT)) { - sngss7_set_ckt_flag(sngss7_info, FLAG_SUS_RECVD); - } - - if (sngss7_test_ckt_flag(sngss7_info, FLAG_SUS_RECVD) && - !sngss7_test_ckt_flag(sngss7_info, FLAG_T6_CANCELED)) { - if (sng_cancel_isup_tmr(sngss7_info->suInstId, ISUP_T6i) == RFAILED ) { - SS7_ERROR_CHAN(ftdmchan,"[CIC:%d]could not stop timer T6 \n", sngss7_info->circuit->cic); - } else { - sngss7_set_ckt_flag(sngss7_info, FLAG_T6_CANCELED); - SS7_ERROR_CHAN(ftdmchan,"[CIC:%d] isup timer T6 has been cancelled. \n", sngss7_info->circuit->cic); - } - } -} - -static ftdm_status_t ftdm_sangoma_ss7_native_bridge_state_change(ftdm_channel_t *ftdmchan); -static ftdm_status_t ftdm_sangoma_ss7_native_bridge_state_change(ftdm_channel_t *ftdmchan) -{ - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - ftdm_channel_complete_state(ftdmchan); - - switch (ftdmchan->state) { - - case FTDM_CHANNEL_STATE_DOWN: - { - ftdm_channel_t *close_chan = ftdmchan; - sngss7_clear_ckt_flag(sngss7_info, FLAG_SUS_RECVD); - sngss7_clear_ckt_flag(sngss7_info, FLAG_T6_CANCELED); - sngss7_clear_ckt_flag (sngss7_info, FLAG_SENT_ACM); - sngss7_clear_ckt_flag (sngss7_info, FLAG_SENT_CPG); - - sngss7_flush_queue(sngss7_info->event_queue); - sngss7_info->peer_data = NULL; - ftdm_channel_close (&close_chan); - } - break; - - case FTDM_CHANNEL_STATE_UP: - { - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_UP); - } - } - break; - - case FTDM_CHANNEL_STATE_TERMINATING: - { - /* Release confirm is sent immediately, since Spirou customer asked us not to wait for the second call leg - * to come back with a release confirm ... */ - /* when receiving REL we move to TERMINATING and notify the user that the bridge is ending */ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_USER_HANGUP)) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - } else { - /* Notify the user and wait for their ack before sending RLC */ - sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_STOP); - } - } - break; - - case FTDM_CHANNEL_STATE_HANGUP: - { - ft_to_sngss7_rlc(ftdmchan); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - break; - - default: - break; - } - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t *ftdmchan) -{ - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - sng_isup_inf_t *isup_intf = NULL; - int state_flag = 1; - int i = 0; - - SS7_DEBUG_CHAN(ftdmchan, "ftmod_sangoma_ss7 processing state %s: ckt=0x%X, blk=0x%X\n", - ftdm_channel_state2str (ftdmchan->state), - sngss7_info->ckt_flags, - sngss7_info->blk_flags); - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) { - /* DIALING is the only state we process normally when doing an outgoing call that is natively bridged, - * all other states are run by a different state machine (and the freetdm core does not do any checking) */ - if (ftdmchan->state != FTDM_CHANNEL_STATE_DIALING) { - return ftdm_sangoma_ss7_native_bridge_state_change(ftdmchan); - } - } - - /*check what state we are supposed to be in */ - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_COLLECT: /* IAM received but wating on digits */ - - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } - - while (ftdmchan->caller_data.dnis.digits[i] != '\0'){ - i++; - } - - /* kill t10 if active */ - if (sngss7_info->t10.hb_timer_id) { - ftdm_sched_cancel_timer (sngss7_info->t10.sched, sngss7_info->t10.hb_timer_id); - } - - /* check if the end of pulsing (ST) character has arrived or the right number of digits */ - if (ftdmchan->caller_data.dnis.digits[i-1] == 'F' - || sngss7_test_ckt_flag(sngss7_info, FLAG_FULL_NUMBER) ) - { - SS7_DEBUG_CHAN(ftdmchan, "Received the end of pulsing character %s\n", ""); - - if (!sngss7_test_ckt_flag(sngss7_info, FLAG_FULL_NUMBER)) { - /* remove the ST */ - ftdmchan->caller_data.dnis.digits[i-1] = '\0'; - sngss7_set_ckt_flag(sngss7_info, FLAG_FULL_NUMBER); - } - - if (sngss7_test_ckt_flag(sngss7_info, FLAG_INR_TX)) { - if (!sngss7_test_ckt_flag(sngss7_info, FLAG_INR_SENT) ) { - ft_to_sngss7_inr(ftdmchan); - sngss7_set_ckt_flag(sngss7_info, FLAG_INR_SENT); - - SS7_DEBUG_CHAN (ftdmchan, "Scheduling T.39 timer %s \n", " "); - - /* start ISUP t39 */ - if (ftdm_sched_timer (sngss7_info->t39.sched, - "t39", - sngss7_info->t39.beat, - sngss7_info->t39.callback, - &sngss7_info->t39, - &sngss7_info->t39.hb_timer_id)) - { - - SS7_ERROR ("Unable to schedule timer T39, hanging up call!\n"); - - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE; - sngss7_set_ckt_flag (sngss7_info, FLAG_LOCAL_REL); - - /* end the call */ - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); - } - }else { - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); - } - } else { - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); - } - } else if (i >= sngss7_info->circuit->min_digits) { - SS7_DEBUG_CHAN(ftdmchan, "Received %d digits (min digits = %d)\n", i, sngss7_info->circuit->min_digits); - - if (sngss7_test_ckt_flag(sngss7_info, FLAG_INR_TX)) { - if (!sngss7_test_ckt_flag(sngss7_info, FLAG_INR_SENT) ) { - ft_to_sngss7_inr(ftdmchan); - sngss7_set_ckt_flag(sngss7_info, FLAG_INR_SENT); - - SS7_DEBUG_CHAN (ftdmchan, "Scheduling T.39 timer %s\n", " " ); - - /* start ISUP t39 */ - if (ftdm_sched_timer (sngss7_info->t39.sched, - "t39", - sngss7_info->t39.beat, - sngss7_info->t39.callback, - &sngss7_info->t39, - &sngss7_info->t39.hb_timer_id)) - { - - SS7_ERROR ("Unable to schedule timer T39, hanging up call!\n"); - - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE; - sngss7_set_ckt_flag (sngss7_info, FLAG_LOCAL_REL); - - /* end the call */ - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); - } - - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE); - }else { - if (sngss7_test_ckt_flag(sngss7_info, FLAG_INF_RX_DN) ) { - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); - } - } - } else { - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); - } - } else { - /* if we are coming from idle state then we have already been here once before */ - if (ftdmchan->last_state != FTDM_CHANNEL_STATE_IDLE) { - SS7_INFO_CHAN(ftdmchan, "Received %d out of %d so far: %s...starting T35\n", - i, - sngss7_info->circuit->min_digits, - ftdmchan->caller_data.dnis.digits); - - /* start ISUP t35 */ - if (ftdm_sched_timer (sngss7_info->t35.sched, - "t35", - sngss7_info->t35.beat, - sngss7_info->t35.callback, - &sngss7_info->t35, - &sngss7_info->t35.hb_timer_id)) { - - SS7_ERROR ("Unable to schedule timer, hanging up call!\n"); - - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE; - - /* set the flag to indicate this hangup is started from the local side */ - sngss7_set_ckt_flag (sngss7_info, FLAG_LOCAL_REL); - - /* end the call */ - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); - } - } - - /* start ISUP t10 */ - if (ftdm_sched_timer (sngss7_info->t10.sched, - "t10", - sngss7_info->t10.beat, - sngss7_info->t10.callback, - &sngss7_info->t10, - &sngss7_info->t10.hb_timer_id)) { - - SS7_ERROR ("Unable to schedule timer, hanging up call!\n"); - - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE; - - /* set the flag to indicate this hangup is started from the local side */ - sngss7_set_ckt_flag (sngss7_info, FLAG_LOCAL_REL); - - /* end the call */ - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); - } - } - - break; - - /**************************************************************************/ - case FTDM_CHANNEL_STATE_RING: /*incoming call request */ - - sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_TX); - sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_SENT); - sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_RX); - sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_RX_DN); - sngss7_clear_ckt_flag(sngss7_info, FLAG_INF_TX); - sngss7_clear_ckt_flag(sngss7_info, FLAG_INF_SENT); - sngss7_clear_ckt_flag(sngss7_info, FLAG_INF_RX); - sngss7_clear_ckt_flag(sngss7_info, FLAG_INF_RX_DN); - - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } - - /* kill t35 if active */ - if (sngss7_info->t35.hb_timer_id) { - ftdm_sched_cancel_timer (sngss7_info->t35.sched, sngss7_info->t35.hb_timer_id); - } - - /* cancel t39 timer */ - if (sngss7_info->t39.hb_timer_id) { - ftdm_sched_cancel_timer (sngss7_info->t39.sched, sngss7_info->t39.hb_timer_id); - } - - SS7_DEBUG_CHAN(ftdmchan, "Sending incoming call from %s to %s to FTDM core\n", - ftdmchan->caller_data.ani.digits, - ftdmchan->caller_data.dnis.digits); - - - /* we have enough information to inform FTDM of the call */ - sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_START); - - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_DIALING: /*outgoing call request */ - - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } - - SS7_DEBUG_CHAN(ftdmchan, "Sending outgoing call from \"%s\" to \"%s\" to LibSngSS7\n", - ftdmchan->caller_data.ani.digits, - ftdmchan->caller_data.dnis.digits); - - /*call sangoma_ss7_dial to make outgoing call */ - ft_to_sngss7_iam(ftdmchan); - - break; - /**************************************************************************/ - /* We handle RING indication the same way we would indicate PROGRESS */ - case FTDM_CHANNEL_STATE_RINGING: - case FTDM_CHANNEL_STATE_PROGRESS: - - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } - - /*check if the channel is inbound or outbound */ - if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - /*OUTBOUND...so we were told by the line of this so noifiy the user */ - sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_PROGRESS); - - /* move to progress media */ - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); - } else { - /* inbound call so we need to send out ACM */ - if (!sngss7_test_ckt_flag(sngss7_info, FLAG_SENT_ACM)) { - sngss7_set_ckt_flag(sngss7_info, FLAG_SENT_ACM); - ft_to_sngss7_acm(ftdmchan); - } - if (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].cpg_on_progress == FTDM_TRUE) { - if (!sngss7_test_ckt_flag(sngss7_info, FLAG_SENT_CPG)) { - sngss7_set_ckt_flag(sngss7_info, FLAG_SENT_CPG); - ft_to_sngss7_cpg(ftdmchan); - } - } - } - - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } - - if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - /* inform the user there is media avai */ - sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_PROGRESS_MEDIA); - } else { - if (!sngss7_test_ckt_flag(sngss7_info, FLAG_SENT_ACM)) { - sngss7_set_ckt_flag(sngss7_info, FLAG_SENT_ACM); - ft_to_sngss7_acm(ftdmchan); - } - if (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].cpg_on_progress_media == FTDM_TRUE) { - if (!sngss7_test_ckt_flag(sngss7_info, FLAG_SENT_CPG)) { - sngss7_set_ckt_flag(sngss7_info, FLAG_SENT_CPG); - ft_to_sngss7_cpg(ftdmchan); - } - } - } - - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_UP: /*call is accpeted...both incoming and outgoing */ - - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } - - /*check if the channel is inbound or outbound */ - if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - /*OUTBOUND...so we were told by the line that the other side answered */ - sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_UP); - } else { - /*INBOUND...so FS told us it was going to answer...tell the stack */ - ft_to_sngss7_anm(ftdmchan); - } - - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_CANCEL: - - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } - - SS7_ERROR_CHAN(ftdmchan,"Hanging up call before informing user%s\n", " "); - - /*now go to the HANGUP complete state */ - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_TERMINATING: /*call is hung up remotely */ - - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } - - /* set the flag to indicate this hangup is started from the remote side */ - sngss7_set_ckt_flag (sngss7_info, FLAG_REMOTE_REL); - - /*this state is set when the line is hanging up */ - sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_STOP); - - /* If the RESET flag is set, do not say in TERMINATING state. - Go back to RESTART state and wait for RESET Confirmation */ - if (sngss7_tx_reset_status_pending(sngss7_info)) { - SS7_DEBUG_CHAN(ftdmchan,"Reset pending in Terminating state!%s\n", ""); - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - } - - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_HANGUP: /*call is hung up locally */ - - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } - - /* check for remote hangup flag */ - if (sngss7_test_ckt_flag (sngss7_info, FLAG_REMOTE_REL)) { - /* remote release ...do nothing here */ - SS7_DEBUG_CHAN(ftdmchan,"Hanging up remotely requested call!%s\n", ""); - } else if (sngss7_test_ckt_flag (sngss7_info, FLAG_GLARE)) { - /* release due to glare */ - SS7_DEBUG_CHAN(ftdmchan,"Hanging up requested call do to glare%s\n", ""); - } else { - /* set the flag to indicate this hangup is started from the local side */ - sngss7_set_ckt_flag (sngss7_info, FLAG_LOCAL_REL); - - /*this state is set when FS is hanging up...so tell the stack */ - ft_to_sngss7_rel (ftdmchan); - - SS7_DEBUG_CHAN(ftdmchan,"Hanging up locally requested call!%s\n", ""); - } - - /*now go to the HANGUP complete state */ - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); - - break; - - /**************************************************************************/ - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } - - if (sngss7_test_ckt_flag (sngss7_info, FLAG_REMOTE_REL)) { - - sngss7_clear_ckt_flag (sngss7_info, FLAG_LOCAL_REL); - - /* check if this hangup is from a tx RSC */ - if (sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_TX)) { - if (!sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_SENT)) { - ft_to_sngss7_rsc (ftdmchan); - sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_SENT); - - /* Wait for Reset in HANGUP Complete nothing to do until we - get reset response back */ - } else if (sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP)) { - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } else { - /* Stay in hangup complete until RSC is received */ - /* Channel is in use if we go to RESTART we will - restart will just come back to HANGUP_COMPLETE */ - } - } else { - /* if the hangup is from a rx RSC, rx GRS, or glare don't sent RLC */ - if (!(sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_RX)) && - !(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX)) && - !(sngss7_test_ckt_flag(sngss7_info, FLAG_GLARE))) { - - /* send out the release complete */ - ft_to_sngss7_rlc (ftdmchan); - } - - /*now go to the DOWN state */ - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - - SS7_DEBUG_CHAN(ftdmchan,"Completing remotely requested hangup!%s\n", ""); - } else if (sngss7_test_ckt_flag (sngss7_info, FLAG_LOCAL_REL)) { - - /* if this hang up is do to a rx RESET we need to sit here till the RSP arrives */ - if (sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_TX_RSP)) { - /* go to the down state as we have already received RSC-RLC */ - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - - /* if it's a local release the user sends us to down */ - SS7_DEBUG_CHAN(ftdmchan,"Completing locally requested hangup!%s\n", ""); - } else if (sngss7_test_ckt_flag (sngss7_info, FLAG_GLARE)) { - SS7_DEBUG_CHAN(ftdmchan,"Completing requested hangup due to glare!%s\n", ""); - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } else { - SS7_DEBUG_CHAN(ftdmchan,"Completing requested hangup for unknown reason!%s\n", ""); - if (sngss7_channel_status_clear(sngss7_info)) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - } - - break; - - /**************************************************************************/ - case FTDM_CHANNEL_STATE_DOWN: /*the call is finished and removed */ - - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OPEN)) { - SS7_DEBUG_CHAN(ftdmchan,"Down came from SUSPEND - break %s\n", ""); - break; - } - } - - /* check if there is a reset response that needs to be sent */ - if (sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_RX)) { - /* send a RSC-RLC */ - ft_to_sngss7_rsca (ftdmchan); - - /* clear the reset flag */ - clear_rx_rsc_flags(sngss7_info); - } - - /* check if there was a GRS that needs a GRA */ - if ((sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX)) && - (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) && - (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT))) { - - /* check if this is the base circuit and send out the GRA - * we insure that this is the last circuit to have the state change queued */ - if (sngss7_info->rx_grs.range) { - /* send out the GRA */ - ft_to_sngss7_gra(ftdmchan); - - /* clean out the spans GRS structure */ - clear_rx_grs_data(sngss7_info); - } - - /* clear the grp reset flag */ - clear_rx_grs_flags(sngss7_info); - } - - /* check if we got the reset response */ - if (sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP)) { - /* clear the reset flag */ - clear_tx_rsc_flags(sngss7_info); - } - - if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) { - /* clear the reset flag */ - clear_tx_grs_flags(sngss7_info); - if (sngss7_info->rx_gra.range) { - /* clean out the spans GRA structure */ - clear_rx_gra_data(sngss7_info); - } - } - - /* check if we came from reset (aka we just processed a reset) */ - if ((ftdmchan->last_state == FTDM_CHANNEL_STATE_RESTART) || - (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) || - (ftdmchan->last_state == FTDM_CHANNEL_STATE_HANGUP_COMPLETE)) { - - - /* check if reset flags are up indicating there is more processing to do yet */ - if (!(sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_TX)) && - !(sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_RX)) && - !(sngss7_test_ckt_flag (sngss7_info, FLAG_GRP_RESET_TX)) && - !(sngss7_test_ckt_flag (sngss7_info, FLAG_GRP_RESET_RX))) { - - SS7_DEBUG_CHAN(ftdmchan,"Current flags: ckt=0x%X, blk=0x%X\n", - sngss7_info->ckt_flags, - sngss7_info->blk_flags); - - if (sngss7_channel_status_clear(sngss7_info)) { - /* check if the sig status is down, and bring it up if it isn't */ - if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) { - SS7_DEBUG_CHAN(ftdmchan,"All reset flags cleared %s\n", ""); - /* all flags are down so we can bring up the sig status */ - sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP); - } - } else { - state_flag = 0; - SS7_DEBUG_CHAN(ftdmchan,"Down detected blocked flags go to SUSPEND %s\n", " "); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - break; - - } - } else { - SS7_DEBUG_CHAN(ftdmchan,"Reset flags present (0x%X)\n", sngss7_info->ckt_flags); - - /* there is still another reset pending so go back to reset*/ - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - } - } - - /* check if t35 is active */ - if (sngss7_info->t35.hb_timer_id) { - ftdm_sched_cancel_timer (sngss7_info->t35.sched, sngss7_info->t35.hb_timer_id); - } - - /* clear all of the call specific data store in the channel structure */ - sngss7_info->suInstId = 0; - sngss7_info->spInstId = 0; - sngss7_info->globalFlg = 0; - sngss7_info->spId = 0; - - /* clear any call related flags */ - sngss7_clear_ckt_flag (sngss7_info, FLAG_REMOTE_REL); - sngss7_clear_ckt_flag (sngss7_info, FLAG_LOCAL_REL); - sngss7_clear_ckt_flag (sngss7_info, FLAG_SENT_ACM); - sngss7_clear_ckt_flag (sngss7_info, FLAG_SENT_CPG); - - - if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OPEN)) { - ftdm_channel_t *close_chan = ftdmchan; - /* close the channel */ - SS7_DEBUG_CHAN(ftdmchan,"FTDM Channel Close %s\n", ""); - sngss7_flush_queue(sngss7_info->event_queue); - ftdm_channel_close (&close_chan); - } - - /* check if there is a glared call that needs to be processed */ - if (sngss7_test_ckt_flag(sngss7_info, FLAG_GLARE)) { - sngss7_clear_ckt_flag (sngss7_info, FLAG_GLARE); - - if (sngss7_info->glare.circuit != 0) { - int bHandle=0; - switch (g_ftdm_sngss7_data.cfg.glareResolution) { - case SNGSS7_GLARE_DOWN: - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Giving control to the other side, handling copied IAM from glare. \n", sngss7_info->circuit->cic); - bHandle = 1; - break; - - case SNGSS7_GLARE_PC: - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Trying to handle IAM copied from glare. \n", sngss7_info->circuit->cic); - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]My PC = %d, incoming PC = %d. \n", sngss7_info->circuit->cic, - g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].spc, - g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].dpc ); - - if( g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].spc > g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].dpc ) - { - if ((sngss7_info->circuit->cic % 2) == 1 ) { - bHandle = 1; - } - } else { - if( (sngss7_info->circuit->cic % 2) == 0 ) { - bHandle = 1; - } - } - - break; - default: /* if configured as SNGSS7_GLARE_CONTROL, always abandon incoming glared IAM. */ - bHandle = 0; - break; - } - - if (!bHandle) { - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Handling glare IAM. \n", sngss7_info->circuit->cic); - handle_con_ind (0, sngss7_info->glare.spInstId, sngss7_info->glare.circuit, &sngss7_info->glare.iam); - } - - /* clear the glare info */ - memset(&sngss7_info->glare, 0x0, sizeof(sngss7_glare_data_t)); - state_flag = 0; - } - } - - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_RESTART: /* CICs needs a Reset */ - - SS7_DEBUG_CHAN(ftdmchan,"RESTART: Current flags: ckt=0x%X, blk=0x%X\n", - sngss7_info->ckt_flags, - sngss7_info->blk_flags); - - if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK)) { - if ((sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_RX)) || - (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX))) { - - SS7_DEBUG_CHAN(ftdmchan,"Incoming Reset request on CIC in UCIC block, removing UCIC block%s\n", ""); - - /* set the unblk flag */ - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_UNBLK); - - /* clear the block flag */ - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK); - - /* process the flag */ - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* break out of the processing for now */ - break; - } - } - - - /* check if this is an outgoing RSC */ - if ((sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX)) && - !(sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_SENT))) { - - /* don't send out reset before finished hanging up if I'm in-use. */ - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) { - /* send a reset request */ - ft_to_sngss7_rsc (ftdmchan); - sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_SENT); - } - - } /* if (sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX)) */ - - /* check if this is the first channel of a GRS (this flag is thrown when requesting reset) */ - if ( (sngss7_test_ckt_flag (sngss7_info, FLAG_GRP_RESET_TX)) && - !(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_SENT)) && - (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_BASE))) { - - /* send out the grs */ - ft_to_sngss7_grs (ftdmchan); - - } - - /* if the sig_status is up...bring it down */ - if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) { - sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN); - } - - if (sngss7_test_ckt_flag (sngss7_info, FLAG_GRP_RESET_RX)) { - /* set the grp reset done flag so we know we have finished this reset */ - sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN); - } /* if (sngss7_test_ckt_flag (sngss7_info, FLAG_GRP_RESET_RX)) */ - - - if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_INUSE)) { - /* bring the call down first...then process the rest of the reset */ - switch (ftdmchan->last_state){ - /******************************************************************/ - case (FTDM_CHANNEL_STATE_TERMINATING): - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - break; - /******************************************************************/ - case (FTDM_CHANNEL_STATE_HANGUP): - case (FTDM_CHANNEL_STATE_HANGUP_COMPLETE): - /* go back to the last state after taking care of the rest of the restart state */ - state_flag = 0; - ftdm_set_state(ftdmchan, ftdmchan->last_state); - break; - /******************************************************************/ - case (FTDM_CHANNEL_STATE_IN_LOOP): - /* we screwed up in a COT/CCR, remove the loop */ - ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL); - - /* go to down */ - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - break; - /******************************************************************/ - default: - /* KONRAD: find out what the cause code should be */ - ftdmchan->caller_data.hangup_cause = 41; - - /* change the state to terminatting, it will throw us back here - * once the call is done - */ - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - break; - /******************************************************************/ - } /* switch (ftdmchan->last_state) */ - } else { - /* check if this an incoming RSC or we have a response already */ - if (sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_RX) || - sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_TX_RSP) || - sngss7_test_ckt_flag (sngss7_info, FLAG_GRP_RESET_TX_RSP) || - sngss7_test_ckt_flag (sngss7_info, FLAG_GRP_RESET_RX_CMPLT)) { - - SS7_DEBUG_CHAN(ftdmchan, "Reset processed moving to DOWN (0x%X)\n", sngss7_info->ckt_flags); - - /* go to a down state to clear the channel and send the response */ - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } else { - - SS7_DEBUG_CHAN(ftdmchan, "Waiting on Reset Rsp/Grp Reset to move to DOWN (0x%X)\n", sngss7_info->ckt_flags); - } - } - - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_SUSPENDED: /* circuit has been blocked */ - - SS7_DEBUG_CHAN(ftdmchan,"SUSPEND: Current flags: ckt=0x%X, blk=0x%X, circuit->flag=0x%X\n", - sngss7_info->ckt_flags, sngss7_info->blk_flags, - sngss7_info->circuit->flags ); - - if (!(sngss7_info->circuit->flags & SNGSS7_CONFIGURED)) { - /* Configure the circuit if RESUME and PAUSED are not set. - And also in a case when RESUME is set */ - if (!sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_PAUSED) || - sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_RESUME)) { - if (ftmod_ss7_isup_ckt_config(sngss7_info->circuit->id)) { - SS7_CRITICAL("ISUP CKT %d configuration FAILED!\n", sngss7_info->circuit->id); - sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_PAUSED); - sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_RESUME); - } else { - SS7_INFO("ISUP CKT %d configuration DONE!\n", sngss7_info->circuit->id); - sngss7_info->circuit->flags |= SNGSS7_CONFIGURED; - sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX); - } - } - } - - /**********************************************************************/ - if (sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_RESUME)) { - - SS7_DEBUG_CHAN(ftdmchan, "Processing RESUME%s\n", ""); - - /* clear the RESUME flag */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_RESUME); - - /* clear the PAUSE flag */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_PAUSED); - - /* We tried to hangup the call while in PAUSED state. - We must send a RESET to clear this circuit */ - if (sngss7_test_ckt_flag (sngss7_info, FLAG_LOCAL_REL)) { - SS7_DEBUG_CHAN(ftdmchan, "Channel local release on RESUME, restart Reset procedure%s\n", ""); - /* By setting RESET_TX flag the check below sngss7_tx_reset_status_pending() will - be true, and will restart the RESET TX procedure */ - sngss7_set_ckt_flag (sngss7_info, FLAG_REMOTE_REL); - sngss7_set_ckt_flag (sngss7_info, FLAG_RESET_TX); - } - - /* We have transmitted Reset/GRS but have not gotten a - * Response. In mean time we got a RESUME. We cannot be sure - * that our reset has been trasmitted, thus restart reset procedure. */ - if (sngss7_tx_reset_status_pending(sngss7_info)) { - SS7_DEBUG_CHAN(ftdmchan, "Channel transmitted RSC/GRS before RESUME, restart Reset procedure%s\n", ""); - clear_rx_grs_flags(sngss7_info); - clear_rx_grs_data(sngss7_info); - clear_tx_grs_flags(sngss7_info); - clear_tx_grs_data(sngss7_info); - clear_rx_rsc_flags(sngss7_info); - clear_tx_rsc_flags(sngss7_info); - - clear_tx_rsc_flags(sngss7_info); - sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX); - } - - /* if there are any resets present */ - if (!sngss7_channel_status_clear(sngss7_info)) { - /* don't bring up the sig status but also move to reset */ - if (!sngss7_reset_status_clear(sngss7_info)) { - goto suspend_goto_restart; - } else if (!sngss7_block_status_clear(sngss7_info)) { - /* Do nothing just go through and handle blocks below */ - } else { - /* This should not happen as above function tests - * for reset and blocks */ - SS7_ERROR_CHAN(ftdmchan, "Invalid code path: sngss7_channel_status_clear reset and block are both cleared%s\n", ""); - goto suspend_goto_restart; - } - } else { - /* bring the sig status back up */ - sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP); - } - } /* if (sngss7_test_flag(sngss7_info, FLAG_INFID_RESUME)) */ - - if (sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_PAUSED)) { - - SS7_DEBUG_CHAN(ftdmchan, "Processing PAUSE%s\n", ""); - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) { - /* bring the sig status down */ - sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN); - } - - /* Wait for RESUME */ - goto suspend_goto_last; - } /* if (sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_PAUSED)) { */ - - /**********************************************************************/ - if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_CKT_MN_BLOCK_RX) && - !sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN)) { - - SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_BLOCK_RX flag %s\n", ""); - - /* bring the sig status down */ - sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN); - - /* send a BLA */ - ft_to_sngss7_bla (ftdmchan); - - /* throw the done flag */ - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN); - - } - - if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX)){ - SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_UNBLK_RX flag %s\n", ""); - - /* clear the block flags */ - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN); - - /* clear the unblock flag */ - sngss7_clear_ckt_blk_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX); - - SS7_DEBUG_CHAN(ftdmchan,"Current flags: ckt=0x%X, blk=0x%X\n", - sngss7_info->ckt_flags, - sngss7_info->blk_flags); - /* not bring the cic up if there is a hardware block */ - if (sngss7_channel_status_clear(sngss7_info)) { - /* bring the sig status up */ - sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP); - - } - /* send a uba */ - ft_to_sngss7_uba (ftdmchan); - - } - - - /**********************************************************************/ - /* hardware block/unblock tx */ - if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_GRP_HW_BLOCK_TX ) && - !sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX_DN )) { - - SS7_DEBUG_CHAN(ftdmchan, "Processing FLAG_GRP_HW_BLOCK_TX flag %s\n", ""); - sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN); - - /* dont send block again if the channel is already blocked by maintenance */ - if( !sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX) && - !sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX_DN) - ) { - ft_to_sngss7_blo(ftdmchan); - } - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX_DN); - - } - - if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_UNBLK_TX)) { - int skip_unblock=0; - SS7_DEBUG_CHAN(ftdmchan, "Processing FLAG_GRP_HW_UNBLK_TX flag %s\n", ""); - - if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX) || - sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX_DN)) { - /* Real unblock */ - } else { - SS7_ERROR_CHAN(ftdmchan, "FLAG_GRP_HW_UNBLK_TX set while FLAG_GRP_HW_BLOCK_TX is not %s\n", ""); - skip_unblock=1; - } - - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX_DN); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_UNBLK_TX); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_UNBLK_TX_DN); - - if (sngss7_channel_status_clear(sngss7_info)) { - sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP); - } - - if (sngss7_tx_block_status_clear(sngss7_info) && !skip_unblock) { - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX_DN); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX); - ft_to_sngss7_ubl(ftdmchan); - } - - } - - /**********************************************************************/ -#if 0 - /* This logic is handled in the handle_cgu_req and handle_cgb_req */ - - if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_GRP_HW_BLOCK_RX ) && - !sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX_DN )) { - - SS7_DEBUG_CHAN(ftdmchan, "Processing FLAG_GRP_HW_BLOCK_RX flag %s\n", ""); - - sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN); - - /* FIXME: Transmit CRG Ack */ - - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX_DN); - - goto suspend_goto_last; - } - - if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_GRP_HW_UNBLK_RX )){ - SS7_DEBUG_CHAN(ftdmchan, "Processing FLAG_GRP_HW_UNBLK_RX flag %s\n", ""); - - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX_DN); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_UNBLK_RX); - - if (sngss7_channel_status_clear(sngs7_info)) { - sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP); - } - - /* Transmit CRU Ack */ - - goto suspend_goto_last; - } -#endif - - - /**********************************************************************/ - if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX) && - !sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX_DN)) { - - SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_BLOCK_TX flag %s\n", ""); - - /* bring the sig status down */ - sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN); - - /* send a blo */ - ft_to_sngss7_blo (ftdmchan); - - /* throw the done flag */ - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX_DN); - - } - - if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_CKT_MN_UNBLK_TX)) { - - SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_UNBLK_TX flag %s\n", ""); - - /* clear the block flags */ - sngss7_clear_ckt_blk_flag (sngss7_info, FLAG_CKT_MN_BLOCK_TX); - sngss7_clear_ckt_blk_flag (sngss7_info, FLAG_CKT_MN_BLOCK_TX_DN); - - /* clear the unblock flag */ - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_UNBLK_TX); - - if (sngss7_channel_status_clear(sngss7_info)) { - /* bring the sig status up */ - sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP); - } - - if (sngss7_tx_block_status_clear(sngss7_info)) { - /* send a ubl */ - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX_DN); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX); - ft_to_sngss7_ubl(ftdmchan); - } - - } - - /**********************************************************************/ - if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX) && - !sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX_DN)) { - - SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_LC_BLOCK_RX flag %s\n", ""); - - /* send a BLA */ - ft_to_sngss7_bla(ftdmchan); - - /* throw the done flag */ - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX_DN); - - if (sngss7_tx_block_status_clear(sngss7_info)) { - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX_DN); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX); - ft_to_sngss7_ubl(ftdmchan); - } else { - /* bring the sig status down */ - sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN); - } - - } - - if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_CKT_LC_UNBLK_RX)) { - - SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_LC_UNBLK_RX flag %s\n", ""); - - /* clear the block flags */ - sngss7_clear_ckt_blk_flag (sngss7_info, FLAG_CKT_LC_BLOCK_RX); - sngss7_clear_ckt_blk_flag (sngss7_info, FLAG_CKT_LC_BLOCK_RX_DN); - - /* clear the unblock flag */ - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX); - - /* send a uba */ - ft_to_sngss7_uba(ftdmchan); - - if (sngss7_channel_status_clear(sngss7_info)) { - sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP); - } - - - } - /**********************************************************************/ - if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_CKT_UCIC_BLOCK) && - !sngss7_test_ckt_blk_flag (sngss7_info, FLAG_CKT_UCIC_BLOCK_DN)) { - - SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_UCIC_BLOCK flag %s\n", ""); - - /* bring the channel signaling status to down */ - sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN); - - /* remove any reset flags */ - clear_rx_grs_flags(sngss7_info); - clear_rx_grs_data(sngss7_info); - clear_tx_grs_flags(sngss7_info); - clear_tx_grs_data(sngss7_info); - clear_rx_rsc_flags(sngss7_info); - clear_tx_rsc_flags(sngss7_info); - - /* throw the done flag */ - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK_DN); - - } - - if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_CKT_UCIC_UNBLK)) { - SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_UCIC_UNBLK flag %s\n", ""); - - /* remove the UCIC block flag */ - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK_DN); - - /* remove the UCIC unblock flag */ - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_UNBLK); - - /* throw the channel into reset to sync states */ - - clear_rx_grs_flags(sngss7_info); - clear_rx_grs_data(sngss7_info); - clear_tx_grs_flags(sngss7_info); - clear_tx_grs_data(sngss7_info); - clear_rx_rsc_flags(sngss7_info); - clear_tx_rsc_flags(sngss7_info); - - clear_tx_rsc_flags(sngss7_info); - sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX); - - /* bring the channel into restart again */ - goto suspend_goto_restart; - } - - SS7_DEBUG_CHAN(ftdmchan,"No block flag processed!%s\n", ""); - -suspend_goto_last: - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_UP) { - /* proceed to UP */ - } else if (!sngss7_reset_status_clear(sngss7_info) || - sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_PAUSED)) { - - /* At this point the circuit is in reset, if the call is - in use make sure that at least REMOTE REL flag is set - in order to drop the call on the sip side */ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) { - if (!sngss7_test_ckt_flag (sngss7_info, FLAG_LOCAL_REL) && - !sngss7_test_ckt_flag (sngss7_info, FLAG_REMOTE_REL)) { - sngss7_set_ckt_flag (sngss7_info, FLAG_REMOTE_REL); - } - } - SS7_DEBUG_CHAN(ftdmchan,"Channel opted to stay in RESTART due to reset!%s\n", ""); - SS7_DEBUG_CHAN(ftdmchan,"Current flags: ckt=0x%X, blk=0x%X, circuit->flag=0x%X\n", - sngss7_info->ckt_flags, sngss7_info->blk_flags, - sngss7_info->circuit->flags ); - - goto suspend_goto_restart; - - } else if (sngss7_channel_status_clear(sngss7_info)) { - - /* In this case all resets and blocks are clear sig state is up, thus go to DOWN */ - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_RESTART || - ftdmchan->last_state == FTDM_CHANNEL_STATE_TERMINATING) { - ftdmchan->last_state = FTDM_CHANNEL_STATE_DOWN; - } - - SS7_DEBUG_CHAN(ftdmchan,"Channel signallig is UP: proceed to State %s!\n", - ftdm_channel_state2str(ftdmchan->last_state)); - SS7_DEBUG_CHAN(ftdmchan,"Current flags: ckt=0x%X, blk=0x%X, circuit->flag=0x%X\n", - sngss7_info->ckt_flags, sngss7_info->blk_flags, - sngss7_info->circuit->flags ); - - } else { - - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_DOWN) { - ftdmchan->last_state = FTDM_CHANNEL_STATE_RESTART; - } - SS7_DEBUG_CHAN(ftdmchan,"Channel signaling is in block state: proceed to State=%s]\n", - ftdm_channel_state2str(ftdmchan->last_state)); - SS7_DEBUG_CHAN(ftdmchan,"Current flags: ckt=0x%X, blk=0x%X, circuit->flag=0x%X\n", - sngss7_info->ckt_flags, sngss7_info->blk_flags, - sngss7_info->circuit->flags); - } - - state_flag = 0; - ftdm_set_state(ftdmchan, ftdmchan->last_state); - break; - -suspend_goto_restart: - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - break; - - /**************************************************************************/ - case FTDM_CHANNEL_STATE_IN_LOOP: /* COT test */ - - isup_intf = &g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId]; - - if (sngss7_test_options(isup_intf, SNGSS7_LPA_FOR_COT)) { - /* send the lpa */ - ft_to_sngss7_lpa (ftdmchan); - } - - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_IDLE: - state_flag = 0; - ftdm_set_state(ftdmchan, ftdmchan->last_state); - break; - /**************************************************************************/ - default: - /* we don't handle any of the other states */ - SS7_ERROR_CHAN(ftdmchan, "ftmod_sangoma_ss7 does not support %s state\n", ftdm_channel_state2str (ftdmchan->state)); - - break; - /**************************************************************************/ - } - - if (state_flag) { - /* clear the state change flag...since we might be setting a new state */ - ftdm_channel_complete_state(ftdmchan); - } - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call) -{ - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - /* the core has this channel already locked so need to lock again */ - - /* check if the channel sig state is UP */ - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) { - SS7_ERROR_CHAN(ftdmchan, "Requested channel sig state is down, skipping channell!%s\n", " "); - /* Sig state will be down due to a block. - Right action is to hunt for another call */ - goto outgoing_break; - } - - /* check if there is a remote block */ - if ((sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) || - (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) || - (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) { - - /* the channel is blocked...can't send any calls here */ - SS7_ERROR_CHAN(ftdmchan, "Requested channel is remotely blocked, re-hunt channel!%s\n", " "); - goto outgoing_break; - } - - /* check if there is a local block */ - if ((sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) || - (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX)) || - (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX))) { - - /* KONRAD FIX ME : we should check if this is a TEST call and allow it */ - - /* the channel is blocked...can't send any calls here */ - SS7_ERROR_CHAN(ftdmchan, "Requested channel is locally blocked, re-hunt channel!%s\n", " "); - goto outgoing_break; - } - - - /* This is a gracefull stack resource check. - Removing this function will cause unpredictable - ungracefule errors. */ - if (sng_cc_resource_check()) { - goto outgoing_fail; - } - - /* check the state of the channel */ - switch (ftdmchan->state){ - /**************************************************************************/ - case FTDM_CHANNEL_STATE_DOWN: - /* inform the monitor thread that we want to make a call by returning FTDM_SUCCESS */ - - goto outgoing_successful; - break; - /**************************************************************************/ - default: - /* the channel is already used...this can't be, end the request */ - SS7_ERROR("Outgoing call requested channel in already in use...indicating glare on span=%d,chan=%d\n", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id); - - goto outgoing_break; - break; - /**************************************************************************/ - } /* switch (ftdmchan->state) (original call) */ - -outgoing_fail: - SS7_DEBUG_CHAN(ftdmchan, "Call Request failed%s\n", " "); - return FTDM_FAIL; - -outgoing_break: - SS7_DEBUG_CHAN(ftdmchan, "Call Request re-hunt%s\n", " "); - return FTDM_BREAK; - -outgoing_successful: - SS7_DEBUG_CHAN(ftdmchan, "Call Request successful%s\n", " "); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -#if 0 - static FIO_CHANNEL_REQUEST_FUNCTION (ftdm_sangoma_ss7_request_chan) - { - SS7_INFO ("KONRAD-> I got called %s\n", __FTDM_FUNC__); - return FTDM_SUCCESS; - } - -#endif - -/******************************************************************************/ - -/* FT-CORE SIG STATUS FUNCTIONS ********************************************** */ -static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_sangoma_ss7_get_sig_status) -{ - if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) { - *status = FTDM_SIG_STATE_UP; - } else { - *status = FTDM_SIG_STATE_DOWN; - } - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_ss7_set_sig_status) -{ - SS7_ERROR ("Cannot set channel status in this module\n"); - return FTDM_NOTIMPL; -} - -/* FT-CORE SIG FUNCTIONS ******************************************************/ -static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span) -{ - ftdm_channel_t *ftdmchan = NULL; - sngss7_chan_data_t *sngss7_info = NULL; - sngss7_span_data_t *sngss7_span = NULL; - sng_isup_inf_t *sngss7_intf = NULL; - int x; - int first_channel; - - first_channel=0; - - - SS7_INFO ("Starting span %s:%u.\n", span->name, span->span_id); - - /* clear the monitor thread stop flag */ - ftdm_clear_flag (span, FTDM_SPAN_STOP_THREAD); - ftdm_clear_flag (span, FTDM_SPAN_IN_THREAD); - - /* check the status of all isup interfaces */ - check_status_of_all_isup_intf(); - - /* throw the channels in pause */ - for (x = 1; x < (span->chan_count + 1); x++) { - /* extract the channel structure and sngss7 channel data */ - ftdmchan = span->channels[x]; - - /* if there is no sig mod data move along */ - if (ftdmchan->call_data == NULL) continue; - - sngss7_info = ftdmchan->call_data; - sngss7_span = ftdmchan->span->signal_data; - sngss7_intf = &g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId]; - - /* flag the circuit as active so we can receieve events on it */ - sngss7_set_flag(sngss7_info->circuit, SNGSS7_ACTIVE); - - /* if this is a non-voice channel, move along cause we're done with it */ - if (sngss7_info->circuit->type != SNG_CKT_VOICE) continue; - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if the interface is paused or resumed */ - if (sngss7_test_flag(sngss7_intf, SNGSS7_PAUSED)) { - SS7_DEBUG_CHAN(ftdmchan, "ISUP intf %d is PAUSED\n", sngss7_intf->id); - /* throw the pause flag */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_RESUME); - sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_PAUSED); - } else { - SS7_DEBUG_CHAN(ftdmchan, "ISUP intf %d is RESUMED\n", sngss7_intf->id); - /* throw the resume flag */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_PAUSED); - sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_RESUME); - } -#if 0 - /* throw the grp reset flag */ - sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX); - if (first_channel == 0) { - sngss7_chan_data_t *cinfo = ftdmchan->call_data; - sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_BASE); - cinfo->tx_grs.circuit = sngss7_info->circuit->id; - cinfo->tx_grs.range = span->chan_count -1; - first_channel=1; - } -#else - /* throw the channel into reset */ - sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX); -#endif - /* throw the channel to suspend */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - } - - /* activate all the configured ss7 links */ - if (ft_to_sngss7_activate_all()) { - SS7_CRITICAL ("Failed to activate LibSngSS7!\n"); - return FTDM_FAIL; - } - - /*start the span monitor thread */ - if (ftdm_thread_create_detached (ftdm_sangoma_ss7_run, span) != FTDM_SUCCESS) { - SS7_CRITICAL ("Failed to start Span Monitor Thread!\n"); - return FTDM_FAIL; - } - - SS7_DEBUG ("Finished starting span %s:%u.\n", span->name, span->span_id); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t ftdm_sangoma_ss7_stop(ftdm_span_t * span) -{ - /*this function is called by the FT-Core to stop this span */ - int timeout=0; - - ftdm_log (FTDM_LOG_INFO, "Stopping span %s:%u.\n", span->name,span->span_id); - - /* throw the STOP_THREAD flag to signal monitor thread stop */ - ftdm_set_flag (span, FTDM_SPAN_STOP_THREAD); - - /* wait for the thread to stop */ - while (ftdm_test_flag (span, FTDM_SPAN_IN_THREAD)) { - ftdm_set_flag (span, FTDM_SPAN_STOP_THREAD); - ftdm_log (FTDM_LOG_DEBUG,"Waiting for monitor thread to end for %s:%u. [flags=0x%08X]\n", - span->name, - span->span_id, - span->flags); - /* Wait 50ms */ - ftdm_sleep (50); - timeout++; - - /* timeout after 5 sec, better to crash than hang */ - ftdm_assert_return(timeout < 100, FTDM_FALSE, "SS7 Span stop timeout!\n"); - } - - /* KONRAD FIX ME - deconfigure any circuits, links, attached to this span */ - - ftdm_log (FTDM_LOG_DEBUG, "Finished stopping span %s:%u.\n", span->name, span->span_id); - - return FTDM_SUCCESS; -} - -/* SIG_FUNCTIONS ***************************************************************/ -static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_ss7_span_config) -{ - sngss7_span_data_t *ss7_span_info; - - ftdm_log (FTDM_LOG_INFO, "Configuring ftmod_sangoma_ss7 span = %s(%d)...\n", - span->name, - span->span_id); - - /* initalize the span's data structure */ - ss7_span_info = ftdm_calloc (1, sizeof (sngss7_span_data_t)); - - /* create a timer schedule */ - if (ftdm_sched_create(&ss7_span_info->sched, "SngSS7_Schedule")) { - SS7_CRITICAL("Unable to create timer schedule!\n"); - return FTDM_FAIL; - } - - /* start the free run thread for the schedule */ - if (ftdm_sched_free_run(ss7_span_info->sched)) { - SS7_CRITICAL("Unable to schedule free run!\n"); - return FTDM_FAIL; - } - - /* create an event queue for this span */ - if ((ftdm_queue_create(&(ss7_span_info)->event_queue, SNGSS7_EVENT_QUEUE_SIZE)) != FTDM_SUCCESS) { - SS7_CRITICAL("Unable to create event queue!\n"); - return FTDM_FAIL; - } - - /*setup the span structure with the info so far */ - g_ftdm_sngss7_data.sig_cb = sig_cb; - span->start = ftdm_sangoma_ss7_start; - span->stop = ftdm_sangoma_ss7_stop; - span->signal_type = FTDM_SIGTYPE_SS7; - span->signal_data = NULL; - span->outgoing_call = ftdm_sangoma_ss7_outgoing_call; - span->channel_request = NULL; - span->signal_cb = sig_cb; - span->get_channel_sig_status = ftdm_sangoma_ss7_get_sig_status; - span->set_channel_sig_status = ftdm_sangoma_ss7_set_sig_status; - span->state_map = &sangoma_ss7_state_map; - span->state_processor = ftdm_sangoma_ss7_process_state_change; - span->signal_data = ss7_span_info; - - /* set the flag to indicate that this span uses channel state change queues */ - ftdm_set_flag (span, FTDM_SPAN_USE_CHAN_QUEUE); - /* set the flag to indicate that this span uses sig event queues */ - ftdm_set_flag (span, FTDM_SPAN_USE_SIGNALS_QUEUE); - - - - /* parse the configuration and apply to the global config structure */ - if (ftmod_ss7_parse_xml(ftdm_parameters, span)) { - ftdm_log (FTDM_LOG_CRIT, "Failed to parse configuration!\n"); - ftdm_sleep (100); - return FTDM_FAIL; - } - - if(SNG_SS7_OPR_MODE_M2UA_SG == g_ftdm_operating_mode){ - ftdm_log (FTDM_LOG_INFO, "FreeTDM running as M2UA_SG mode, Setting Span type to FTDM_SIGTYPE_M2UA\n"); - span->signal_type = FTDM_SIGTYPE_M2UA; - } - - if (ft_to_sngss7_cfg_all()) { /* configure libsngss7 */ - ftdm_log (FTDM_LOG_CRIT, "Failed to configure LibSngSS7!\n"); - ftdm_sleep (100); - return FTDM_FAIL; - } - - ftdm_log (FTDM_LOG_INFO, "Finished configuring ftmod_sangoma_ss7 span = %s(%d)...\n", - span->name, - span->span_id); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_ss7_init) -{ - /*this function is called by the FT-core to load the signaling module */ - uint32_t major = 0; - uint32_t minor = 0; - uint32_t build = 0; - - ftdm_log (FTDM_LOG_INFO, "Loading ftmod_sangoma_ss7...\n"); - - /* default the global structure */ - memset (&g_ftdm_sngss7_data, 0x0, sizeof (ftdm_sngss7_data_t)); - - sngss7_id = 0; - - cmbLinkSetId = 0; - - /* initalize the global gen_config flag */ - g_ftdm_sngss7_data.gen_config = 0; - - /* function trace initizalation */ - g_ftdm_sngss7_data.function_trace = 1; - g_ftdm_sngss7_data.function_trace_level = 7; - - /* message (IAM, ACM, ANM, etc) trace initizalation */ - g_ftdm_sngss7_data.message_trace = 1; - g_ftdm_sngss7_data.message_trace_level = 6; - - /* setup the call backs needed by Sangoma_SS7 library */ - sng_event.cc.sng_con_ind = sngss7_con_ind; - sng_event.cc.sng_con_cfm = sngss7_con_cfm; - sng_event.cc.sng_con_sta = sngss7_con_sta; - sng_event.cc.sng_rel_ind = sngss7_rel_ind; - sng_event.cc.sng_rel_cfm = sngss7_rel_cfm; - sng_event.cc.sng_dat_ind = sngss7_dat_ind; - sng_event.cc.sng_fac_ind = sngss7_fac_ind; - sng_event.cc.sng_fac_cfm = sngss7_fac_cfm; - sng_event.cc.sng_sta_ind = sngss7_sta_ind; - sng_event.cc.sng_umsg_ind = sngss7_umsg_ind; - sng_event.cc.sng_susp_ind = sngss7_susp_ind; - sng_event.cc.sng_resm_ind = sngss7_resm_ind; - - sng_event.sm.sng_log = handle_sng_log; - sng_event.sm.sng_mtp1_alarm = handle_sng_mtp1_alarm; - sng_event.sm.sng_mtp2_alarm = handle_sng_mtp2_alarm; - sng_event.sm.sng_mtp3_alarm = handle_sng_mtp3_alarm; - sng_event.sm.sng_isup_alarm = handle_sng_isup_alarm; - sng_event.sm.sng_cc_alarm = handle_sng_cc_alarm; - sng_event.sm.sng_relay_alarm = handle_sng_relay_alarm; - sng_event.sm.sng_m2ua_alarm = handle_sng_m2ua_alarm; - sng_event.sm.sng_nif_alarm = handle_sng_nif_alarm; - sng_event.sm.sng_tucl_alarm = handle_sng_tucl_alarm; - sng_event.sm.sng_sctp_alarm = handle_sng_sctp_alarm; - - /* initalize sng_ss7 library */ - sng_isup_init_gen(&sng_event); - - /* print the version of the library being used */ - sng_isup_version(&major, &minor, &build); - SS7_INFO("Loaded LibSng-SS7 %d.%d.%d\n", major, minor, build); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_ss7_unload) -{ - /*this function is called by the FT-core to unload the signaling module */ - - int x; - - ftdm_log (FTDM_LOG_INFO, "Starting ftmod_sangoma_ss7 unload...\n"); - - - if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC_STARTED)) { - sng_isup_free_cc(); - sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC_STARTED); - } - - if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP_STARTED)) { - ftmod_ss7_shutdown_isup(); - sng_isup_free_isup(); - sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP_STARTED); - } - - if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3_STARTED)) { - ftmod_ss7_shutdown_mtp3(); - sng_isup_free_mtp3(); - sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3_STARTED); - } - - if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2_STARTED)) { - ftmod_ss7_shutdown_mtp2(); - sng_isup_free_mtp2(); - sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2_STARTED); - } - - if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP1_STARTED)) { - sng_isup_free_mtp1(); - sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP1_STARTED); - } - - if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY_STARTED)) { - /* go through all the relays channels and disable them */ - x = 1; - while (x < (MAX_RELAY_CHANNELS)) { - /* check if this relay channel has been configured already */ - if ((g_ftdm_sngss7_data.cfg.relay[x].flags & SNGSS7_CONFIGURED)) { - - /* send the specific configuration */ - if (ftmod_ss7_disable_relay_channel(x)) { - SS7_CRITICAL("Relay Channel %d disable failed!\n", x); - /* jz: dont leave like this - * return 1; - * */ - } else { - SS7_INFO("Relay Channel %d disable DONE!\n", x); - } - - /* set the SNGSS7_CONFIGURED flag */ - g_ftdm_sngss7_data.cfg.relay[x].flags &= ~(SNGSS7_CONFIGURED); - } /* if !SNGSS7_CONFIGURED */ - x++; - } /* while (x < (MAX_RELAY_CHANNELS)) */ - - ftmod_ss7_shutdown_relay(); - sng_isup_free_relay(); - sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY_STARTED); - } - - if(SNG_SS7_OPR_MODE_ISUP != g_ftdm_operating_mode){ - ftmod_ss7_m2ua_free(); - } - - - if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_SM_STARTED)) { - sng_isup_free_sm(); - sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_SM_STARTED); - } - - sng_isup_free_gen(); - - ftdm_log (FTDM_LOG_INFO, "Finished ftmod_sangoma_ss7 unload!\n"); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static FIO_API_FUNCTION(ftdm_sangoma_ss7_api) -{ - /* handle this in it's own file....so much to do */ - return (ftdm_sngss7_handle_cli_cmd (stream, data)); -} - -/******************************************************************************/ -static FIO_IO_LOAD_FUNCTION(ftdm_sangoma_ss7_io_init) -{ - assert (fio != NULL); - memset (&g_ftdm_sngss7_interface, 0, sizeof (g_ftdm_sngss7_interface)); - - g_ftdm_sngss7_interface.name = "ss7"; - g_ftdm_sngss7_interface.api = ftdm_sangoma_ss7_api; - - *fio = &g_ftdm_sngss7_interface; - - return FTDM_SUCCESS; -} - -/******************************************************************************/ - - -/* START **********************************************************************/ -ftdm_module_t ftdm_module = { - "sangoma_ss7", /*char name[256]; */ - ftdm_sangoma_ss7_io_init, /*fio_io_load_t */ - NULL, /*fio_io_unload_t */ - ftdm_sangoma_ss7_init, /*fio_sig_load_t */ - NULL, /*fio_sig_configure_t */ - ftdm_sangoma_ss7_unload, /*fio_sig_unload_t */ - ftdm_sangoma_ss7_span_config /*fio_configure_span_signaling_t */ -}; -/******************************************************************************/ - -/******************************************************************************/ -/* For Emacs: -* Local Variables: -* mode:c -* indent-tabs-mode:t -* tab-width:4 -* c-basic-offset:4 -* End: -* For VIM: -* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: -*/ -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h deleted file mode 100644 index 6dabf727cd..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h +++ /dev/null @@ -1,1246 +0,0 @@ -/* - * Copyright (c) 2009, Konrad Hammel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Contributors: - * - * James Zhang - * - */ -/******************************************************************************/ -#ifndef __FTMOD_SNG_SS7_H__ -#define __FTMOD_SNG_SS7_H__ -/******************************************************************************/ - -/* INCLUDE ********************************************************************/ -#include -#include -#include -#include -#include -#include - -#include "private/ftdm_core.h" - -#include "sng_ss7/sng_ss7.h" -#include "ftmod_sangoma_ss7_m2ua.h" - -/******************************************************************************/ - -/* DEFINES ********************************************************************/ -#define MAX_NAME_LEN 25 - -#define MAX_CIC_LENGTH 5 -#define MAX_CIC_MAP_LENGTH 1000 -#define MAX_SCTP_LINK 100 - -#define SNGSS7_EVENT_QUEUE_SIZE 100 -#define SNGSS7_PEER_CHANS_QUEUE_SIZE 100 -#define SNGSS7_CHAN_EVENT_QUEUE_SIZE 100 - -#define MAX_SIZEOF_SUBADDR_IE 24 /* as per Q931 4.5.9 */ - -#define SNGSS7_SWITCHTYPE_ANSI(switchtype) (switchtype == LSI_SW_ANS88) || \ - (switchtype == LSI_SW_ANS92) || \ - (switchtype == LSI_SW_ANS95) - -#define sngss7_flush_queue(queue) \ - do { \ - void *__queue_data = NULL; \ - while ((__queue_data = ftdm_queue_dequeue(queue))) { \ - ftdm_safe_free(__queue_data); \ - } \ - } while (0) - -typedef struct ftdm2trillium { - uint8_t ftdm_val; - uint8_t trillium_val; -} ftdm2trillium_t; - -typedef enum { - SNGSS7_CON_IND_EVENT = 0, - SNGSS7_CON_CFM_EVENT, - SNGSS7_CON_STA_EVENT, - SNGSS7_REL_IND_EVENT, - SNGSS7_REL_CFM_EVENT, - SNGSS7_DAT_IND_EVENT, - SNGSS7_FAC_IND_EVENT, - SNGSS7_FAC_CFM_EVENT, - SNGSS7_UMSG_IND_EVENT, - SNGSS7_STA_IND_EVENT, - SNGSS7_SUSP_IND_EVENT, - SNGSS7_RESM_IND_EVENT, - SNGSS7_SSP_STA_CFM_EVENT, - SNGSS7_INVALID_EVENT, -} sng_event_type_t; -#define SNG_EVENT_TYPE_STRINGS "CON_IND", "CON_CFM", "CON_STA", "REL_IND", "REL_CFM", "DAT_IND", "FAC_IND", \ - "FAC_CFM", "UMSG_IND", "STA_IND", "SUSP_IND", "RESM_IND", "SSP_STA_CFM", "INVALID" -FTDM_STR2ENUM_P(ftdm_str2sngss7_event, ftdm_sngss7_event2str, sng_event_type_t) - -typedef enum { - SNG_BIT_A = (1 << 0), - SNG_BIT_B = (1 << 1), - SNG_BIT_C = (1 << 2), - SNG_BIT_D = (1 << 3), - SNG_BIT_E = (1 << 4), - SNG_BIT_F = (1 << 5), - SNG_BIT_G = (1 << 6), - SNG_BIT_H = (1 << 7) -} sng_bit_enums_t; - -typedef enum { - SNG_CKT_VOICE = 0, - SNG_CKT_SIG, - SNG_CKT_HOLE -} sng_ckt_type_t; - -typedef enum { - SNG_RTE_UP = 0, - SNG_RTE_DN -} sng_route_direction_t; - -typedef enum { - SNGSS7_LPA_FOR_COT = (1 << 0), /* send LPA when COT arrives */ - SNGSS7_ACM_OBCI_BITA = (1 << 10) /* in-band indication */ -} sng_intf_options_t; - -typedef enum { - SNG_CALLED = 1, - SNG_CALLING = 2 -} sng_addr_type_t; - -typedef enum { - SNG_GEN_CFG_STATUS_INIT = 0, - SNG_GEN_CFG_STATUS_PENDING = 1, - SNG_GEN_CFG_STATUS_DONE = 2 -} nsg_gen_cfg_type_t; - -typedef struct sng_mtp2_error_type { - int init; - char sng_type[MAX_NAME_LEN]; - uint32_t tril_type; -} sng_mtp2_error_type_t; - -typedef struct sng_link_type { - int init; - char sng_type[MAX_NAME_LEN]; - uint32_t tril_mtp2_type; - uint32_t tril_mtp3_type; -} sng_link_type_t; - -typedef struct sng_switch_type { - int init; - char sng_type[MAX_NAME_LEN]; - uint32_t tril_mtp3_type; - uint32_t tril_isup_type; -} sng_switch_type_t; - -typedef struct sng_ssf_type { - int init; - char sng_type[MAX_NAME_LEN]; - uint32_t tril_type; -} sng_ssf_type_t; - -typedef struct sng_cic_cntrl_type { - int init; - char sng_type[MAX_NAME_LEN]; - uint32_t tril_type; -} sng_cic_cntrl_type_t; - -typedef struct sng_mtp1_link { - char name[MAX_NAME_LEN]; - uint32_t flags; - uint32_t id; - uint32_t span; - uint32_t chan; -} sng_mtp1_link_t; - -typedef struct sng_mtp2_link { - char name[MAX_NAME_LEN]; - uint32_t flags; - uint32_t id; - uint32_t lssuLength; - uint32_t errorType; - uint32_t linkType; - uint32_t mtp1Id; - uint32_t mtp1ProcId; - uint32_t t1; - uint32_t t2; - uint32_t t3; - uint32_t t4n; - uint32_t t4e; - uint32_t t5; - uint32_t t6; - uint32_t t7; -} sng_mtp2_link_t; - -/* defining glare handling methods: - SNGSS7_GLARE_PC: - higher PointCode controls even number CIC - lower PointCode controls odd number CIC - SNGSS7_GLARE_DOWN: - always give control to the other side - SNGSS7_GLARE_CONTROL: - always trying to control -*/ -typedef enum { - SNGSS7_GLARE_PC = 0, - SNGSS7_GLARE_DOWN, - SNGSS7_GLARE_CONTROL -} sng_glare_resolution; - -typedef struct sng_mtp3_link { - char name[MAX_NAME_LEN]; - uint32_t flags; - uint32_t id; - uint32_t priority; - uint32_t linkType; - uint32_t switchType; - uint32_t apc; - uint32_t spc; - uint32_t ssf; - uint32_t slc; - uint32_t linkSetId; - uint32_t mtp2Id; - uint32_t mtp2ProcId; - uint32_t t1; - uint32_t t2; - uint32_t t3; - uint32_t t4; - uint32_t t5; - uint32_t t6; - uint32_t t7; - uint32_t t8; - uint32_t t9; - uint32_t t10; - uint32_t t11; - uint32_t t12; - uint32_t t13; - uint32_t t14; - uint32_t t15; - uint32_t t16; - uint32_t t17; - uint32_t t18; - uint32_t t19; - uint32_t t20; - uint32_t t21; - uint32_t t22; - uint32_t t23; - uint32_t t24; - uint32_t t25; - uint32_t t27; - uint32_t t28; - uint32_t t29; - uint32_t t30; - uint32_t t31; - uint32_t t32; - uint32_t t33; - uint32_t t34; - uint32_t t35; - uint32_t t36; - uint32_t t37; - uint32_t tcraft; - uint32_t tflc; - uint32_t tbnd; -} sng_mtp3_link_t; - -typedef struct sng_link_set { - char name[MAX_NAME_LEN]; - uint32_t flags; - uint32_t id; - uint32_t apc; - uint32_t linkType; - uint32_t switchType; - uint32_t ssf; - uint32_t minActive; - uint32_t numLinks; - uint32_t links[16]; -} sng_link_set_t; - -typedef struct sng_link_set_list { - uint32_t lsId; - struct sng_link_set_list *next; -} sng_link_set_list_t; - -typedef struct sng_route { - char name[MAX_NAME_LEN]; - uint32_t flags; - uint32_t id; - uint32_t dpc; - uint32_t cmbLinkSetId; - struct sng_link_set_list lnkSets; - uint32_t linkType; - uint32_t switchType; - uint32_t ssf; - uint32_t nwId; - uint32_t isSTP; - uint32_t dir; - uint32_t t6; - uint32_t t8; - uint32_t t10; - uint32_t t11; - uint32_t t15; - uint32_t t16; - uint32_t t18; - uint32_t t19; - uint32_t t21; - uint32_t t25; - uint32_t t26; -} sng_route_t; - -typedef struct sng_isup_intf { - char name[MAX_NAME_LEN]; - uint32_t options; - uint32_t flags; - uint32_t id; - uint32_t spc; - uint32_t dpc; - uint32_t switchType; - uint32_t nwId; - uint32_t mtpRouteId; - uint32_t ssf; - uint32_t isap; - uint16_t t4; - uint32_t t11; - uint32_t t18; - uint32_t t19; - uint32_t t20; - uint32_t t21; - uint32_t t22; - uint32_t t23; - uint32_t t24; - uint32_t t25; - uint32_t t26; - uint32_t t28; - uint32_t t29; - uint32_t t30; - uint32_t t32; - uint32_t t37; - uint32_t t38; - uint32_t t39; - uint32_t tfgr; - uint32_t tpause; - uint32_t tstaenq; -} sng_isup_inf_t; - -typedef struct sng_isup_ckt { - uint32_t options; - uint32_t flags; - uint32_t procId; - uint32_t id; - uint32_t ccSpanId; - uint32_t span; - uint32_t chan; - uint32_t type; /* VOICE/SIG/HOLE */ - uint32_t cic; - uint32_t infId; - uint32_t typeCntrl; - uint32_t ssf; - uint32_t switchType; - - uint32_t clg_nadi; - uint32_t cld_nadi; - uint8_t rdnis_nadi; - uint32_t loc_nadi; - - /* Generic Number defaults */ - uint8_t gn_nmbqual; /* Number Qualifier */ - uint8_t gn_nadi; /* Nature of Address indicator */ - uint8_t gn_screen_ind; /* Screening Indicator */ - uint8_t gn_pres_ind; /* Presentation Indicator */ - uint8_t gn_npi; /* Numbering Plan Indicator */ - uint8_t gn_num_inc_ind; /* Number Incomplete Indicator */ - /* END - Generic Number defaults */ - - uint32_t min_digits; - uint32_t transparent_iam_max_size; - uint8_t transparent_iam; - uint8_t cpg_on_progress_media; - uint8_t cpg_on_progress; - uint8_t itx_auto_reply; - void *obj; - uint16_t t3; - uint32_t t10; - uint16_t t12; - uint16_t t13; - uint16_t t14; - uint16_t t15; - uint16_t t16; - uint16_t t17; - uint32_t t35; - uint32_t t39; - uint16_t tval; -} sng_isup_ckt_t; - -typedef struct sng_nsap { - uint32_t flags; - uint32_t id; - uint32_t suId; - uint32_t spId; - uint32_t nwId; - uint32_t linkType; - uint32_t switchType; - uint32_t ssf; -} sng_nsap_t; - -typedef struct sng_isap { - uint32_t id; - uint32_t suId; - uint32_t spId; - uint32_t switchType; - uint32_t ssf; - uint32_t flags; - uint32_t t1; - uint32_t t2; - uint32_t t5; - uint32_t t6; - uint32_t t7; - uint32_t t8; - uint32_t t9; - uint32_t t27; - uint32_t t31; - uint32_t t33; - uint32_t t34; - uint32_t t36; - uint32_t tccr; - uint32_t tccrt; - uint32_t tex; - uint32_t tcrm; - uint32_t tcra; - uint32_t tect; - uint32_t trelrsp; - uint32_t tfnlrelrsp; -} sng_isap_t; - -typedef struct sng_relay { - uint32_t id; - char name[MAX_NAME_LEN]; - uint32_t flags; - uint32_t type; - uint32_t port; - char hostname[RY_REMHOSTNAME_SIZE]; - uint32_t procId; -} sng_relay_t; - -/********************************************** -sctp structures and data definitions -**********************************************/ - -typedef struct sng_sctp_gen_cfg { -} sng_sctp_gen_cfg_t; - -typedef struct sng_sctp_link { - char name[MAX_NAME_LEN]; - uint32_t flags; - uint32_t id; - uint32_t port; - uint32_t numSrcAddr; - uint32_t srcAddrList[SCT_MAX_NET_ADDRS+1]; -} sng_sctp_link_t; - -typedef struct sng_sctp_cfg { - sng_sctp_gen_cfg_t genCfg; - sng_sctp_link_t linkCfg[MAX_SCTP_LINK+1]; -} sng_sctp_cfg_t; - - - -typedef struct sng_ss7_cfg { - uint32_t spc; - uint32_t procId; - char license[MAX_SNGSS7_PATH]; - char signature[MAX_SNGSS7_PATH]; - uint32_t transparent_iam_max_size; - uint32_t flags; - sng_relay_t relay[MAX_RELAY_CHANNELS+1]; - sng_mtp1_link_t mtp1Link[MAX_MTP_LINKS+1]; - sng_mtp2_link_t mtp2Link[MAX_MTP_LINKS+1]; - sng_mtp3_link_t mtp3Link[MAX_MTP_LINKS+1]; - sng_link_set_t mtpLinkSet[MAX_MTP_LINKSETS+1]; - sng_route_t mtpRoute[MAX_MTP_ROUTES+1]; - sng_isup_inf_t isupIntf[MAX_ISUP_INFS+1]; - sng_isup_ckt_t isupCkt[10000]; /* KONRAD - only need 2000 ( and 0-1000 aren't used) since other servers are registerd else where */ - sng_nsap_t nsap[MAX_NSAPS+1]; - sng_isap_t isap[MAX_ISAPS+1]; - sng_glare_resolution glareResolution; - uint32_t force_inr; - sng_m2ua_gbl_cfg_t g_m2ua_cfg; - sng_sctp_cfg_t sctpCfg; -} sng_ss7_cfg_t; - -typedef struct ftdm_sngss7_data { - sng_ss7_cfg_t cfg; - int gen_config; - int function_trace; - int function_trace_level; - int message_trace; - int message_trace_level; - fio_signal_cb_t sig_cb; -} ftdm_sngss7_data_t; - -typedef enum{ - SNG_SS7_OPR_MODE_NONE, - SNG_SS7_OPR_MODE_M2UA_SG, - SNG_SS7_OPR_MODE_ISUP, -}ftdm_sngss7_operating_modes_e; - -typedef ftdm_sngss7_operating_modes_e ftdm_sngss7_opr_mode; - -typedef struct sngss7_timer_data { - ftdm_timer_id_t hb_timer_id; - int beat; - int counter; - ftdm_sched_callback_t callback; - ftdm_sched_t *sched; - void *sngss7_info; -} sngss7_timer_data_t; - -typedef struct sngss7_glare_data { - uint32_t spInstId; - uint32_t circuit; - SiConEvnt iam; -} sngss7_glare_data_t; - -typedef struct sngss7_group_data { - uint32_t circuit; - uint32_t range; - uint8_t status[255]; - uint8_t type; - uint8_t cause; -} sngss7_group_data_t; - -typedef struct sngss7_chan_data { - ftdm_channel_t *ftdmchan; - sng_isup_ckt_t *circuit; - uint32_t base_chan; - uint32_t suInstId; - uint32_t spInstId; - uint32_t spId; - uint8_t globalFlg; - uint32_t ckt_flags; - uint32_t blk_flags; - ftdm_hash_t* variables; /* send on next sigevent */ - ftdm_size_t raw_data_len; - void *raw_data; /* send on next sigevent */ - sngss7_glare_data_t glare; - sngss7_timer_data_t t35; - sngss7_timer_data_t t10; - sngss7_timer_data_t t39; - sngss7_group_data_t rx_grs; - sngss7_group_data_t rx_gra; - sngss7_group_data_t tx_grs; - sngss7_group_data_t ucic; - ftdm_queue_t *event_queue; - struct sngss7_chan_data *peer_data; - uint8_t peer_event_transfer_cnt; -} sngss7_chan_data_t; - -#define SNGSS7_RX_GRS_PENDING (1 << 0) -#define SNGSS7_UCIC_PENDING (1 << 1) -#define SNGSS7_RX_GRA_PENDING (1 << 2) -typedef struct sngss7_span_data { - ftdm_sched_t *sched; - uint32_t flags; - sngss7_group_data_t rx_cgb; - sngss7_group_data_t tx_cgb; - sngss7_group_data_t rx_cgu; - sngss7_group_data_t tx_cgu; - ftdm_queue_t *event_queue; -} sngss7_span_data_t; - -typedef struct sngss7_event_data -{ - uint32_t event_id; - uint32_t spId; - uint32_t suId; - uint32_t spInstId; - uint32_t suInstId; - uint32_t circuit; - uint8_t globalFlg; - uint8_t evntType; - union - { - SiConEvnt siConEvnt; - SiCnStEvnt siCnStEvnt; - SiRelEvnt siRelEvnt; - SiInfoEvnt siInfoEvnt; - SiFacEvnt siFacEvnt; - SiStaEvnt siStaEvnt; - SiSuspEvnt siSuspEvnt; - SiResmEvnt siResmEvnt; - } event; -} sngss7_event_data_t; - - -typedef enum { - FLAG_RESET_RX = (1 << 0), - FLAG_RESET_TX = (1 << 1), - FLAG_RESET_SENT = (1 << 2), - FLAG_RESET_TX_RSP = (1 << 3), - FLAG_GRP_RESET_RX = (1 << 4), - FLAG_GRP_RESET_RX_DN = (1 << 5), - FLAG_GRP_RESET_RX_CMPLT = (1 << 6), - FLAG_GRP_RESET_BASE = (1 << 7), - FLAG_GRP_RESET_TX = (1 << 8), - FLAG_GRP_RESET_SENT = (1 << 9), - FLAG_GRP_RESET_TX_RSP = (1 << 10), - FLAG_REMOTE_REL = (1 << 11), - FLAG_LOCAL_REL = (1 << 12), - FLAG_GLARE = (1 << 13), - FLAG_INFID_RESUME = (1 << 14), - FLAG_INFID_PAUSED = (1 << 15), - FLAG_SENT_ACM = (1 << 16), - FLAG_SENT_CPG = (1 << 17), - FLAG_SUS_RECVD = (1 << 18), - FLAG_T6_CANCELED = (1 << 19), - FLAG_INR_TX = (1 << 20), - FLAG_INR_SENT = (1 << 21), - FLAG_INR_RX = (1 << 22), - FLAG_INR_RX_DN = (1 << 23), - FLAG_INF_TX = (1 << 24), - FLAG_INF_SENT = (1 << 25), - FLAG_INF_RX = (1 << 26), - FLAG_INF_RX_DN = (1 << 27), - FLAG_FULL_NUMBER = (1 << 28), - FLAG_RELAY_DOWN = (1 << 30), - FLAG_CKT_RECONFIG = (1 << 31) -} sng_ckt_flag_t; - -#define CKT_FLAGS_STRING \ - "RX_RSC", \ - "TX_RSC", \ - "TX_RSC_REQ_SENT", \ - "TX_RSC_RSP_RECEIVED", \ - "RX_GRS", \ - "RX_GRS_DONE", \ - "RX_GRS_CMPLT", \ - "GRS_BASE", \ - "TX_GRS", \ - "TX_GRS_REQ_SENT", \ - "TX_GRS_RSP_RECEIVED", \ - "REMOTE_REL", \ - "LOCAL_REL", \ - "GLARE", \ - "INF_RESUME", \ - "INF_PAUSED", \ - "TX_ACM_SENT" \ - "TX_INR" \ - "INR_SENT" \ - "RX_INR" \ - "RX_INR_DN" \ - "TX_INF" \ - "INF SENT" \ - "RX_INF" \ - "RX_INF_DN" \ - "RELAY_DOWN", \ - "CKT_RECONFIG" -FTDM_STR2ENUM_P(ftmod_ss7_ckt_state2flag, ftmod_ss7_ckt_flag2str, sng_ckt_flag_t) - -/* ckt blocking flags */ -typedef enum { - FLAG_CKT_UCIC_BLOCK = (1 << 0), - FLAG_CKT_UCIC_BLOCK_DN = (1 << 1), - FLAG_CKT_UCIC_UNBLK = (1 << 2), - FLAG_CKT_UCIC_UNBLK_DN = (1 << 3), - FLAG_CKT_LC_BLOCK_RX = (1 << 4), - FLAG_CKT_LC_BLOCK_RX_DN = (1 << 5), - FLAG_CKT_LC_UNBLK_RX = (1 << 6), - FLAG_CKT_LC_UNBLK_RX_DN = (1 << 7), - FLAG_CKT_MN_BLOCK_RX = (1 << 8), - FLAG_CKT_MN_BLOCK_RX_DN = (1 << 9), - FLAG_CKT_MN_UNBLK_RX = (1 << 10), - FLAG_CKT_MN_UNBLK_RX_DN = (1 << 11), - FLAG_CKT_MN_BLOCK_TX = (1 << 12), - FLAG_CKT_MN_BLOCK_TX_DN = (1 << 13), - FLAG_CKT_MN_UNBLK_TX = (1 << 14), - FLAG_CKT_MN_UNBLK_TX_DN = (1 << 15), - FLAG_GRP_HW_BLOCK_RX = (1 << 16), - FLAG_GRP_HW_BLOCK_RX_DN = (1 << 17), - FLAG_GRP_HW_BLOCK_TX = (1 << 18), - FLAG_GRP_HW_BLOCK_TX_DN = (1 << 19), - FLAG_GRP_MN_BLOCK_RX = (1 << 20), - FLAG_GRP_MN_BLOCK_RX_DN = (1 << 21), - FLAG_GRP_MN_BLOCK_TX = (1 << 22), - FLAG_GRP_MN_BLOCK_TX_DN = (1 << 23), - FLAG_GRP_HW_UNBLK_TX = (1 << 24), - FLAG_GRP_HW_UNBLK_TX_DN = (1 << 25), - FLAG_GRP_MN_UNBLK_TX = (1 << 26), - FLAG_GRP_MN_UNBLK_TX_DN = (1 << 27), -} sng_ckt_block_flag_t; - -#define BLK_FLAGS_STRING \ - "UCIC BLK", \ - "UCIC BLK DN", \ - "UCIC UNBLK", \ - "UCIC UNBLK DN", \ - "RX LC BLK", \ - "RX LC BLK DN", \ - "RX LC UNBLK", \ - "RX LC UNBLK DN", \ - "RX CKT BLK", \ - "RX CKT BLK DN", \ - "RX CKT UNBLK", \ - "RX CKT UNBLK DN", \ - "TX CKT BLK", \ - "TX CKT BLK DN", \ - "TX CKT UNBLK", \ - "TX CKT UNBLK DN", \ - "RX GRP HW BLK", \ - "RX GRP HW BLK DN", \ - "TX GRP HW BLK", \ - "TX GRP HW BLK DN", \ - "RX GRP MN BLK", \ - "RX GRP MN BLK DN", \ - "TX GRP MN BLK", \ - "TX GRP MN BLK DN", \ - "TX GRP HW UNBLK", \ - "TX GRP HW UNBLK DN", \ - "TX GRP MN UNBLK", \ - "TX GRP MN UNBLK DN", \ - "RX GRP HW UNBLK", \ - "RX GRP HW UNBLK DN" -FTDM_STR2ENUM_P(ftmod_ss7_blk_state2flag, ftmod_ss7_blk_flag2str, sng_ckt_block_flag_t) - -/* valid for every cfg array except circuits */ -typedef enum { - SNGSS7_CONFIGURED = (1 << 0), - SNGSS7_ACTIVE = (1 << 1), - SNGSS7_RELAY_INIT = (1 << 3), - SNGSS7_PAUSED = (1 << 7) /* for isup interfaces */ -} sng_cfg_flag_t; - -typedef enum { - SNGSS7_SM_STARTED = (1 << 0), - - SNGSS7_RY_PRESENT = (1 << 2), - SNGSS7_RY_STARTED = (1 << 3), - - SNGSS7_MTP1_PRESENT = (1 << 4), - SNGSS7_MTP1_STARTED = (1 << 5), - - SNGSS7_MTP2_PRESENT = (1 << 6), - SNGSS7_MTP2_STARTED = (1 << 7), - - SNGSS7_MTP3_PRESENT = (1 << 8), - SNGSS7_MTP3_STARTED = (1 << 9), - - SNGSS7_ISUP_PRESENT = (1 << 10), - SNGSS7_ISUP_STARTED = (1 << 11), - - SNGSS7_CC_PRESENT = (1 << 12), - SNGSS7_CC_STARTED = (1 << 13), - - SNGSS7_TUCL_PRESENT = (1 << 14), - SNGSS7_TUCL_STARTED = (1 << 15), - - SNGSS7_SCTP_PRESENT = (1 << 16), - SNGSS7_SCTP_STARTED = (1 << 17), - - SNGSS7_M2UA_PRESENT = (1 << 18), - SNGSS7_M2UA_STARTED = (1 << 19), - SNGSS7_M2UA_EP_OPENED = (1 << 20), - SNGSS7_M2UA_INIT_ASSOC_DONE = (1 << 21), - - SNGSS7_NIF_PRESENT = (1 << 22), - SNGSS7_NIF_STARTED = (1 << 23), - -} sng_task_flag_t; -/******************************************************************************/ - -/* GLOBALS ********************************************************************/ -extern ftdm_sngss7_data_t g_ftdm_sngss7_data; -extern ftdm_sngss7_opr_mode g_ftdm_operating_mode; -extern sng_ssf_type_t sng_ssf_type_map[]; -extern sng_switch_type_t sng_switch_type_map[]; -extern sng_link_type_t sng_link_type_map[]; -extern sng_mtp2_error_type_t sng_mtp2_error_type_map[]; -extern sng_cic_cntrl_type_t sng_cic_cntrl_type_map[]; -extern uint32_t sngss7_id; -extern ftdm_sched_t *sngss7_sched; -extern int cmbLinkSetId; -/******************************************************************************/ - -/* PROTOTYPES *****************************************************************/ -/* in ftmod_sangoma_ss7_main.c */ -ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t *ftdmchan); - -/* in ftmod_sangoma_ss7_logger.c */ -void handle_sng_log(uint8_t level, char *fmt,...); -void handle_sng_mtp1_alarm(Pst *pst, L1Mngmt *sta); -void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta); -void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta); -void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta); -void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta); -void handle_sng_relay_alarm(Pst *pst, RyMngmt *sta); -void handle_sng_m2ua_alarm(Pst *pst, MwMgmt *sta); -void handle_sng_nif_alarm(Pst *pst, NwMgmt *sta); -void handle_sng_tucl_alarm(Pst *pst, HiMngmt *sta); -void handle_sng_sctp_alarm(Pst *pst, SbMgmt *sta); - -/* in ftmod_sangoma_ss7_relay.c */ -ftdm_status_t handle_relay_connect(RyMngmt *sta); -ftdm_status_t handle_relay_disconnect_on_down(RyMngmt *sta); -ftdm_status_t handle_relay_disconnect_on_error(RyMngmt *sta); - -/* in ftmod_sangoma_ss7_cfg.c */ -int ft_to_sngss7_cfg_all(void); -int ftmod_ss7_mtp1_gen_config(void); -int ftmod_ss7_mtp2_gen_config(void); -int ftmod_ss7_mtp3_gen_config(void); -int ftmod_ss7_isup_gen_config(void); -int ftmod_ss7_cc_gen_config(void); -int ftmod_ss7_mtp1_psap_config(int id); -int ftmod_ss7_mtp2_dlsap_config(int id); -int ftmod_ss7_mtp3_dlsap_config(int id); -int ftmod_ss7_mtp3_nsap_config(int id); -int ftmod_ss7_mtp3_linkset_config(int id); -int ftmod_ss7_mtp3_route_config(int id); -int ftmod_ss7_isup_nsap_config(int id); -int ftmod_ss7_isup_intf_config(int id); -int ftmod_ss7_isup_ckt_config(int id); -int ftmod_ss7_isup_isap_config(int id); -int ftmod_ss7_cc_isap_config(int id); - -/* in ftmod_sangoma_ss7_cntrl.c */ -int ft_to_sngss7_activate_all(void); - -int ftmod_ss7_inhibit_mtp3link(uint32_t id); -int ftmod_ss7_uninhibit_mtp3link(uint32_t id); -int ftmod_ss7_bind_mtp3link(uint32_t id); -int ftmod_ss7_unbind_mtp3link(uint32_t id); -int ftmod_ss7_activate_mtp3link(uint32_t id); -int ftmod_ss7_deactivate_mtp3link(uint32_t id); -int ftmod_ss7_deactivate2_mtp3link(uint32_t id); -int ftmod_ss7_activate_mtplinkSet(uint32_t id); -int ftmod_ss7_deactivate_mtplinkSet(uint32_t id); -int ftmod_ss7_deactivate2_mtplinkSet(uint32_t id); -int ftmod_ss7_lpo_mtp3link(uint32_t id); -int ftmod_ss7_lpr_mtp3link(uint32_t id); - -int ftmod_ss7_shutdown_isup(void); -int ftmod_ss7_shutdown_mtp3(void); -int ftmod_ss7_shutdown_mtp2(void); -int ftmod_ss7_shutdown_relay(void); -int ftmod_ss7_disable_relay_channel(uint32_t chanId); - -int ftmod_ss7_disable_grp_mtp3Link(uint32_t procId); -int ftmod_ss7_enable_grp_mtp3Link(uint32_t procId); - -int ftmod_ss7_disable_grp_mtp2Link(uint32_t procId); - -#define ftmod_ss7_block_isup_ckt(x) __ftmod_ss7_block_isup_ckt(x,FTDM_TRUE) -#define ftmod_ss7_block_isup_ckt_nowait(x) __ftmod_ss7_block_isup_ckt(x,FTDM_FALSE) -int __ftmod_ss7_block_isup_ckt(uint32_t cktId, ftdm_bool_t wait); -int ftmod_ss7_unblock_isup_ckt(uint32_t cktId); - - -/* in ftmod_sangoma_ss7_sta.c */ -int ftmod_ss7_mtp1link_sta(uint32_t id, L1Mngmt *cfm); -int ftmod_ss7_mtp2link_sta(uint32_t id, SdMngmt *cfm); -int ftmod_ss7_mtp3link_sta(uint32_t id, SnMngmt *cfm); -int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm); -int ftmod_ss7_isup_intf_sta(uint32_t id, uint8_t *status); -int ftmod_ss7_relay_status(uint32_t id, RyMngmt *cfm); -int ftmod_ss7_isup_ckt_sta(uint32_t id, unsigned char *state); - - -/* in ftmod_sangoma_ss7_out.c */ -void ft_to_sngss7_iam(ftdm_channel_t *ftdmchan); -void ft_to_sngss7_acm(ftdm_channel_t *ftdmchan); -void ft_to_sngss7_cpg (ftdm_channel_t *ftdmchan); -void ft_to_sngss7_anm(ftdm_channel_t *ftdmchan); -void ft_to_sngss7_rel(ftdm_channel_t *ftdmchan); -void ft_to_sngss7_rlc(ftdm_channel_t *ftdmchan); -void ft_to_sngss7_rsc(ftdm_channel_t *ftdmchan); -void ft_to_sngss7_rsca(ftdm_channel_t *ftdmchan); -void ft_to_sngss7_blo(ftdm_channel_t *ftdmchan); -void ft_to_sngss7_bla(ftdm_channel_t *ftdmchan); -void ft_to_sngss7_ubl(ftdm_channel_t *ftdmchan); -void ft_to_sngss7_uba(ftdm_channel_t *ftdmchan); -void ft_to_sngss7_lpa(ftdm_channel_t *ftdmchan); -void ft_to_sngss7_gra(ftdm_channel_t *ftdmchan); -void ft_to_sngss7_grs(ftdm_channel_t *ftdmchan); -void ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan); -void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan); -void ft_to_sngss7_cgb(ftdm_channel_t * ftdmchan); -void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan); -void ft_to_sngss7_itx (ftdm_channel_t * ftdmchan); -void ft_to_sngss7_txa (ftdm_channel_t * ftdmchan); -void ft_to_sngss7_inr(ftdm_channel_t * ftdmchan); -void ft_to_sngss7_inf(ftdm_channel_t *ftdmchan, SiCnStEvnt *inr); - - - -/* in ftmod_sangoma_ss7_in.c */ -void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -void sngss7_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); -void sngss7_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); -void sngss7_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCnStEvnt *siCnStEvnt, uint8_t evntType); -void sngss7_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt); -void sngss7_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt); -void sngss7_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiInfoEvnt *siInfoEvnt); -void sngss7_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt); -void sngss7_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt); -void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -void sngss7_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit); -void sngss7_resm_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiResmEvnt *siResmEvnt); -void sngss7_susp_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiSuspEvnt *siSuspEvnt); -void sngss7_ssp_sta_cfm(uint32_t infId); - -ftdm_status_t sngss7_bufferzero_iam(SiConEvnt *siConEvnt); -ftdm_status_t sngss7_retrieve_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt); -ftdm_status_t sngss7_save_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt); - -/* in ftmod_sangoma_ss7_handle.c */ -ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); -ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCnStEvnt *siCnStEvnt, uint8_t evntType); -ftdm_status_t handle_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); -ftdm_status_t handle_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt); -ftdm_status_t handle_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt); -ftdm_status_t handle_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiInfoEvnt *siInfoEvnt); -ftdm_status_t handle_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt); -ftdm_status_t handle_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt); -ftdm_status_t handle_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit); -ftdm_status_t handle_susp_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiSuspEvnt *siSuspEvnt); -ftdm_status_t handle_resm_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiResmEvnt *siResmEvnt); -ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); - -ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_cot_start(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_cot_stop(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_local_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_blo_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_local_blk(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_local_ubl(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); - -/* in ftmod_sangoma_ss7_xml.c */ -int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *span); - -/* in ftmod_sangoma_ss7_cli.c */ -ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const char *data); - -/* in ftmod_sangoma_ss7_support.c */ -ftdm_status_t copy_cgPtyNum_from_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *cgPtyNum); -ftdm_status_t copy_cgPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *cgPtyNum); -ftdm_status_t copy_cdPtyNum_from_sngss7(ftdm_channel_t *ftdmchan, SiCdPtyNum *cdPtyNum); -ftdm_status_t copy_cdPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCdPtyNum *cdPtyNum); -ftdm_status_t copy_redirgNum_to_sngss7(ftdm_channel_t *ftdmchan, SiRedirNum *redirgNum); -ftdm_status_t copy_redirgNum_from_sngss7(ftdm_channel_t *ftdmchan, SiRedirNum *redirgNum); -ftdm_status_t copy_redirgInfo_from_sngss7(ftdm_channel_t *ftdmchan, SiRedirInfo *redirInfo); -ftdm_status_t copy_redirgInfo_to_sngss7(ftdm_channel_t *ftdmchan, SiRedirInfo *redirInfo); -ftdm_status_t copy_ocn_to_sngss7(ftdm_channel_t *ftdmchan, SiOrigCdNum *origCdNum); -ftdm_status_t copy_ocn_from_sngss7(ftdm_channel_t *ftdmchan, SiOrigCdNum *origCdNum); - -ftdm_status_t copy_access_transport_from_sngss7(ftdm_channel_t *ftdmchan, SiAccTrnspt *accTrnspt); -ftdm_status_t copy_access_transport_to_sngss7(ftdm_channel_t *ftdmchan, SiAccTrnspt *accTrnspt); -ftdm_status_t copy_locPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *locPtyNum); -ftdm_status_t copy_locPtyNum_from_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *locPtyNum); -ftdm_status_t copy_genNmb_to_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb); -ftdm_status_t copy_genNmb_from_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb); -ftdm_status_t copy_cgPtyCat_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyCat *cgPtyCat); -ftdm_status_t copy_cgPtyCat_from_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyCat *cgPtyCat); -ftdm_status_t copy_accTrnspt_to_sngss7(ftdm_channel_t *ftdmchan, SiAccTrnspt *accTrnspt); -ftdm_status_t copy_natConInd_to_sngss7(ftdm_channel_t *ftdmchan, SiNatConInd *natConInd); -ftdm_status_t copy_fwdCallInd_hex_from_sngss7(ftdm_channel_t *ftdmchan, SiFwdCallInd *fwdCallInd); -ftdm_status_t copy_fwdCallInd_to_sngss7(ftdm_channel_t *ftdmchan, SiFwdCallInd *fwdCallInd); -ftdm_status_t copy_txMedReq_to_sngss7(ftdm_channel_t *ftdmchan, SiTxMedReq *txMedReq); -ftdm_status_t copy_usrServInfoA_to_sngss7(ftdm_channel_t *ftdmchan, SiUsrServInfo *usrServInfoA); -ftdm_status_t copy_NatureOfConnection_from_sngss7(ftdm_channel_t *ftdmchan, SiNatConInd *natConInd ); -ftdm_status_t copy_NatureOfConnection_to_sngss7(ftdm_channel_t *ftdmchan, SiNatConInd *natConInd); - -ftdm_status_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven); -ftdm_status_t append_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven); -ftdm_status_t copy_tknStr_to_sngss7(char* str, TknStr *tknStr, TknU8 *oddEven); - -int check_for_state_change(ftdm_channel_t *ftdmchan); -int check_for_reset(sngss7_chan_data_t *sngss7_info); -ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan); -unsigned long get_unique_id(void); - -ftdm_status_t check_if_rx_grs_started(ftdm_span_t *ftdmspan); -ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan); -ftdm_status_t check_if_rx_gra_started(ftdm_span_t *ftdmspan); -ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan); - -ftdm_status_t process_span_ucic(ftdm_span_t *ftdmspan); - -ftdm_status_t clear_rx_grs_flags(sngss7_chan_data_t *sngss7_info); -ftdm_status_t clear_tx_grs_flags(sngss7_chan_data_t *sngss7_info); -ftdm_status_t clear_rx_rsc_flags(sngss7_chan_data_t *sngss7_info); -ftdm_status_t clear_tx_rsc_flags(sngss7_chan_data_t *sngss7_info); -ftdm_status_t clear_rx_grs_data(sngss7_chan_data_t *sngss7_info); -ftdm_status_t clear_rx_gra_data(sngss7_chan_data_t *sngss7_info); -ftdm_status_t clear_tx_grs_data(sngss7_chan_data_t *sngss7_info); - -ftdm_status_t encode_subAddrIE_nsap(const char *subAddr, char *subAddrIE, int type); -ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int type); - -int find_mtp2_error_type_in_map(const char *err_type); -int find_link_type_in_map(const char *linkType); -int find_switch_type_in_map(const char *switchType); -int find_ssf_type_in_map(const char *ssfType); -int find_cic_cntrl_in_map(const char *cntrlType); - -ftdm_status_t check_status_of_all_isup_intf(void); -ftdm_status_t check_for_reconfig_flag(ftdm_span_t *ftdmspan); - -void sngss7_send_signal(sngss7_chan_data_t *sngss7_info, ftdm_signal_event_t event_id); -void sngss7_set_sig_status(sngss7_chan_data_t *sngss7_info, ftdm_signaling_status_t status); -ftdm_status_t sngss7_add_var(sngss7_chan_data_t *ss7_info, const char* var, const char* val); -ftdm_status_t sngss7_add_raw_data(sngss7_chan_data_t *sngss7_info, uint8_t* data, ftdm_size_t data_len); - -/* in ftmod_sangoma_ss7_timers.c */ -void handle_isup_t35(void *userdata); -void handle_isup_t10(void *userdata); -void handle_isup_t39(void *userdata); - - -/******************************************************************************/ - -/* MACROS *********************************************************************/ -#define SS7_STATE_CHANGE(ftdmchan, new_state) \ -if (ftdmchan->state == new_state) { \ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE); \ -} else { \ - ftdm_set_state(ftdmchan, new_state); \ -} - -#define SS7_DEBUG(a,...) ftdm_log(FTDM_LOG_DEBUG,a , ##__VA_ARGS__ ); -#define SS7_INFO(a,...) ftdm_log(FTDM_LOG_INFO,a , ##__VA_ARGS__ ); -#define SS7_WARN(a,...) ftdm_log(FTDM_LOG_WARNING,a , ##__VA_ARGS__ ); -#define SS7_ERROR(a,...) ftdm_log(FTDM_LOG_ERROR,a , ##__VA_ARGS__ ); -#define SS7_CRITICAL(a,...) ftdm_log(FTDM_LOG_CRIT,a , ##__VA_ARGS__ ); - -#define SS7_DEBUG_CHAN(fchan, msg, args...) ftdm_log_chan(fchan, FTDM_LOG_DEBUG, msg , ##args) -#define SS7_INFO_CHAN(fchan, msg, args...) ftdm_log_chan(fchan, FTDM_LOG_INFO, msg , ##args) -#define SS7_WARN_CHAN(fchan, msg, args...) ftdm_log_chan(fchan, FTDM_LOG_WARNING, msg , ##args) -#define SS7_ERROR_CHAN(fchan, msg, args...) ftdm_log_chan(fchan, FTDM_LOG_ERROR, msg , ##args) -#define SS7_CRIT_CHAN(fchan, msg, args...) ftdm_log_chan(fchan, FTDM_LOG_CRIT, msg , ##args) - -#ifdef SS7_CODE_DEVEL -#define SS7_DEVEL_DEBUG(a,...) ftdm_log(FTDM_LOG_DEBUG,a,##__VA_ARGS__ ); -#else -#define SS7_DEVEL_DEBUG(a,...) -#endif - -#define SS7_FUNC_TRACE_ENTER(a) if (g_ftdm_sngss7_data.function_trace) { \ - switch (g_ftdm_sngss7_data.function_trace_level) { \ - case 0: \ - ftdm_log(FTDM_LOG_EMERG,"Entering %s\n", a); \ - break; \ - case 1: \ - ftdm_log(FTDM_LOG_ALERT,"Entering %s\n", a); \ - break; \ - case 2: \ - ftdm_log(FTDM_LOG_CRIT,"Entering %s\n", a); \ - break; \ - case 3: \ - ftdm_log(FTDM_LOG_ERROR,"Entering %s\n", a); \ - break; \ - case 4: \ - ftdm_log(FTDM_LOG_WARNING,"Entering %s\n", a); \ - break; \ - case 5: \ - ftdm_log(FTDM_LOG_NOTICE,"Entering %s\n", a); \ - break; \ - case 6: \ - ftdm_log(FTDM_LOG_INFO,"Entering %s\n", a); \ - break; \ - case 7: \ - ftdm_log(FTDM_LOG_DEBUG,"Entering %s\n", a); \ - break; \ - default: \ - ftdm_log(FTDM_LOG_INFO,"Entering %s\n", a); \ - break; \ - } /* switch (g_ftdm_sngss7_data.function_trace_level) */ \ - } /* if(g_ftdm_sngss7_data.function_trace) */ - -#define SS7_FUNC_TRACE_EXIT(a) if (g_ftdm_sngss7_data.function_trace) { \ - switch (g_ftdm_sngss7_data.function_trace_level) { \ - case 0: \ - ftdm_log(FTDM_LOG_EMERG,"Exiting %s\n", a); \ - break; \ - case 1: \ - ftdm_log(FTDM_LOG_ALERT,"Exiting %s\n", a); \ - break; \ - case 2: \ - ftdm_log(FTDM_LOG_CRIT,"Exiting %s\n", a); \ - break; \ - case 3: \ - ftdm_log(FTDM_LOG_ERROR,"Exiting %s\n", a); \ - break; \ - case 4: \ - ftdm_log(FTDM_LOG_WARNING,"Exiting %s\n", a); \ - break; \ - case 5: \ - ftdm_log(FTDM_LOG_NOTICE,"Exiting %s\n", a); \ - break; \ - case 6: \ - ftdm_log(FTDM_LOG_INFO,"Exiting %s\n", a); \ - break; \ - case 7: \ - ftdm_log(FTDM_LOG_DEBUG,"Exiting %s\n", a); \ - break; \ - default: \ - ftdm_log(FTDM_LOG_INFO,"Exiting %s\n", a); \ - break; \ - } /* switch (g_ftdm_sngss7_data.function_trace_level) */ \ - } /* if(g_ftdm_sngss7_data.function_trace) */ - -#define SS7_MSG_TRACE(fchan, sngss7info ,msg) if (g_ftdm_sngss7_data.message_trace) { \ - switch (g_ftdm_sngss7_data.message_trace_level) { \ - case 0: \ - ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ - sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ - break; \ - case 1: \ - ftdm_log_chan(fchan, FTDM_LOG_ALERT, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ - sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ - break; \ - case 2: \ - ftdm_log_chan(fchan, FTDM_LOG_CRIT, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ - sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ - break; \ - case 3: \ - ftdm_log_chan(fchan, FTDM_LOG_ERROR, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ - sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ - break; \ - case 4: \ - ftdm_log_chan(fchan, FTDM_LOG_WARNING, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ - sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ - break; \ - case 5: \ - ftdm_log_chan(fchan, FTDM_LOG_NOTICE, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ - sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ - break; \ - case 6: \ - ftdm_log_chan(fchan, FTDM_LOG_INFO, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ - sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ - break; \ - case 7: \ - ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ - sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ - break; \ - default: \ - ftdm_log_chan(fchan, FTDM_LOG_INFO, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ - sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ - break; \ - } /* switch (g_ftdm_sngss7_data.message_trace_level) */ \ - } /* if(g_ftdm_sngss7_data.message_trace) */ - -#define sngss7_test_flag(obj, flag) ((obj)->flags & flag) -#define sngss7_clear_flag(obj, flag) ((obj)->flags &= ~(flag)) -#define sngss7_set_flag(obj, flag) ((obj)->flags |= (flag)) - -#define sngss7_test_ckt_flag(obj, flag) ((obj)->ckt_flags & flag) -#define sngss7_clear_ckt_flag(obj, flag) ((obj)->ckt_flags &= ~(flag)) -#define sngss7_set_ckt_flag(obj, flag) ((obj)->ckt_flags |= (flag)) - -#define sngss7_test_ckt_blk_flag(obj, flag) ((obj)->blk_flags & flag) -#define sngss7_clear_ckt_blk_flag(obj, flag) ((obj)->blk_flags &= ~(flag)) -#define sngss7_set_ckt_blk_flag(obj, flag) ((obj)->blk_flags |= (flag)) - -#define sngss7_test_options(obj, option) ((obj)->options & option) -#define sngss7_clear_options(obj, option) ((obj)->options &= ~(option)) -#define sngss7_set_options(obj, option) ((obj)->options |= (option)) - -#define sngss7_tx_block_status_clear(obj) (!sngss7_test_ckt_blk_flag(obj, (FLAG_CKT_MN_BLOCK_TX | \ - FLAG_CKT_MN_BLOCK_TX_DN | \ - FLAG_GRP_MN_BLOCK_TX | \ - FLAG_GRP_MN_BLOCK_TX_DN | \ - FLAG_GRP_HW_BLOCK_TX | \ - FLAG_GRP_HW_BLOCK_TX_DN | \ - FLAG_GRP_HW_UNBLK_TX | \ - FLAG_CKT_MN_UNBLK_TX ))) - -#define sngss7_block_status_clear(obj) (obj->blk_flags == 0) - -#define sngss7_reset_status_clear(obj) (!sngss7_test_ckt_flag(obj, (FLAG_RESET_TX | \ - FLAG_RESET_RX | \ - FLAG_GRP_RESET_TX | \ - FLAG_GRP_RESET_RX ))) - -#define sngss7_tx_reset_sent(obj) ((sngss7_test_ckt_flag(obj, (FLAG_RESET_TX)) && \ - sngss7_test_ckt_flag(obj, (FLAG_RESET_SENT))) || \ - (sngss7_test_ckt_flag(obj, (FLAG_GRP_RESET_TX)) && \ - sngss7_test_ckt_flag(obj, (FLAG_GRP_RESET_SENT)))) - -#define sngss7_tx_reset_status_pending(obj) (sngss7_test_ckt_flag(obj, (FLAG_RESET_TX)) || sngss7_test_ckt_flag(obj, (FLAG_GRP_RESET_TX))) - -#define sngss7_channel_status_clear(obj) ((sngss7_block_status_clear(obj)) && \ - (sngss7_reset_status_clear(obj)) && \ - (!sngss7_test_ckt_flag((obj),FLAG_INFID_PAUSED))) - -#define sngss7_tx_reset_restart(obj) do { clear_tx_grs_flags((obj)); \ - clear_tx_grs_data((obj)); \ - clear_tx_rsc_flags((obj)); \ - sngss7_set_ckt_flag((obj), (FLAG_RESET_TX)); \ - } while (0); - - - -#ifdef SMG_RELAY_DBG -#define SS7_RELAY_DBG(a,...) printf(a"\n", ##__VA_ARGS__) -#define SS7_RELAY_DBG_FUN(a) printf(#a"\n") -#else -#define SS7_RELAY_DBG(a, ...) -#define SS7_RELAY_DBG_FUN(a) -#endif -/******************************************************************************/ - -/******************************************************************************/ -#endif /* __FTMOD_SNG_SS7_H__ */ -/******************************************************************************/ - -/******************************************************************************/ -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c deleted file mode 100644 index 7c567ab6ea..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c +++ /dev/null @@ -1,1052 +0,0 @@ -/* - * Copyright (c) 2009, Konrad Hammel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* INCLUDE ********************************************************************/ -#include "ftmod_sangoma_ss7_main.h" -/******************************************************************************/ - -/* DEFINES ********************************************************************/ -#define SNGSS7_EVNTINFO_IND_INBAND_AVAIL 0x03 -/******************************************************************************/ - -/* GLOBALS ********************************************************************/ - -/* FUNCTIONS ******************************************************************/ -void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) -{ - const char *var = NULL; - SiConEvnt iam; - ftdm_bool_t native_going_up = FTDM_FALSE; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;; - sngss7_event_data_t *event_clone = NULL; - - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - sngss7_info->suInstId = get_unique_id (); - sngss7_info->spInstId = 0; - sngss7_info->spId = 1; - - memset (&iam, 0x0, sizeof (iam)); - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) { - ftdm_span_t *peer_span = NULL; - ftdm_channel_t *peer_chan = NULL; - sngss7_chan_data_t *peer_info = NULL; - - var = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "sigbridge_peer"); - ftdm_get_channel_from_string(var, &peer_span, &peer_chan); - if (!peer_chan) { - SS7_ERROR_CHAN(ftdmchan, "Failed to find sigbridge peer from string '%s'\n", var); - } else { - if (peer_span->signal_type != FTDM_SIGTYPE_SS7) { - SS7_ERROR_CHAN(ftdmchan, "Peer channel '%s' has different signaling type %d'\n", - var, peer_span->signal_type); - } else { - peer_info = peer_chan->call_data; - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Starting native bridge with peer CIC %d\n", - sngss7_info->circuit->cic, peer_info->circuit->cic); - - /* retrieve only first message from the others guys queue (must be IAM) */ - event_clone = ftdm_queue_dequeue(peer_info->event_queue); - - /* make each one of us aware of the native bridge */ - peer_info->peer_data = sngss7_info; - sngss7_info->peer_data = peer_info; - - /* Go to up until release comes, note that state processing is done different and much simpler when there is a peer, - We can't go to UP state right away yet though, so do not set the state to UP here, wait until the end of this function - because moving from one state to another causes the ftdmchan->usrmsg structure to be wiped - and we still need those variables for further IAM processing */ - native_going_up = FTDM_TRUE; - } - } - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) { - if (!event_clone) { - SS7_ERROR_CHAN(ftdmchan, "No IAM event clone in peer queue!%s\n", ""); - } else if (event_clone->event_id != SNGSS7_CON_IND_EVENT) { - /* first message in the queue should ALWAYS be an IAM */ - SS7_ERROR_CHAN(ftdmchan, "Invalid initial peer message type '%d'\n", event_clone->event_id); - } else { - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged, dialing %s)\n", sngss7_info->circuit->cic, caller_data->dnis.digits); - - /* copy original incoming IAM */ - memcpy(&iam, &event_clone->event.siConEvnt, sizeof(iam)); - - /* Change DNIS to whatever was specified, do not change NADI or anything else! */ - copy_tknStr_to_sngss7(caller_data->dnis.digits, &iam.cdPtyNum.addrSig, &iam.cdPtyNum.oddEven); - - /* SPIROU certification hack - If the IAM already contain RDINF, just increment the count and set the RDNIS digits - otherwise, honor RDNIS and RDINF stuff coming from the user */ - if (iam.redirInfo.eh.pres == PRSNT_NODEF) { - const char *val = NULL; - if (iam.redirInfo.redirCnt.pres) { - iam.redirInfo.redirCnt.val++; - SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged), redirect count incremented = %d\n", sngss7_info->circuit->cic, iam.redirInfo.redirCnt.val); - } - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdnis_digits"); - if (!ftdm_strlen_zero(val)) { - SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged), found user supplied RDNIS digits = %s\n", sngss7_info->circuit->cic, val); - copy_tknStr_to_sngss7((char*)val, &iam.redirgNum.addrSig, &iam.redirgNum.oddEven); - } else { - SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged), not found user supplied RDNIS digits\n", sngss7_info->circuit->cic); - } - } else { - SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged), redirect info not present, attempting to copy user supplied values\n", sngss7_info->circuit->cic); - /* Redirecting Number */ - copy_redirgNum_to_sngss7(ftdmchan, &iam.redirgNum); - - /* Redirecting Information */ - copy_redirgInfo_to_sngss7(ftdmchan, &iam.redirInfo); - } - - if (iam.origCdNum.eh.pres != PRSNT_NODEF) { - /* Original Called Number */ - copy_ocn_to_sngss7(ftdmchan, &iam.origCdNum); - } - copy_access_transport_to_sngss7(ftdmchan, &iam.accTrnspt); - } - } else if (sngss7_info->circuit->transparent_iam && - sngss7_retrieve_iam(ftdmchan, &iam) == FTDM_SUCCESS) { - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Transparent)\n", sngss7_info->circuit->cic); - - /* Called Number information */ - copy_cdPtyNum_to_sngss7(ftdmchan, &iam.cdPtyNum); - - /* Redirecting Number */ - copy_redirgNum_to_sngss7(ftdmchan, &iam.redirgNum); - - /* Redirecting Information */ - copy_redirgInfo_to_sngss7(ftdmchan, &iam.redirInfo); - - /* Location Number information */ - copy_locPtyNum_to_sngss7(ftdmchan, &iam.cgPtyNum1); - - /* Forward Call Indicators */ - copy_fwdCallInd_to_sngss7(ftdmchan, &iam.fwdCallInd); - - /* Original Called Number */ - copy_ocn_to_sngss7(ftdmchan, &iam.origCdNum); - - copy_access_transport_to_sngss7(ftdmchan, &iam.accTrnspt); - - copy_NatureOfConnection_to_sngss7(ftdmchan, &iam.natConInd); - } else { - /* Nature of Connection Indicators */ - copy_natConInd_to_sngss7(ftdmchan, &iam.natConInd); - - /* Forward Call Indicators */ - copy_fwdCallInd_to_sngss7(ftdmchan, &iam.fwdCallInd); - - /* Transmission medium requirements */ - copy_txMedReq_to_sngss7(ftdmchan, &iam.txMedReq); - - if (SNGSS7_SWITCHTYPE_ANSI(g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType)) { - /* User Service Info A */ - copy_usrServInfoA_to_sngss7(ftdmchan, &iam.usrServInfoA); - } - - /* Called Number information */ - copy_cdPtyNum_to_sngss7(ftdmchan, &iam.cdPtyNum); - - /* Calling Number information */ - copy_cgPtyNum_to_sngss7(ftdmchan, &iam.cgPtyNum); - - /* Location Number information */ - copy_locPtyNum_to_sngss7(ftdmchan, &iam.cgPtyNum1); - - /* Generic Number information */ - copy_genNmb_to_sngss7(ftdmchan, &iam.genNmb); - - /* Calling Party's Category */ - copy_cgPtyCat_to_sngss7(ftdmchan, &iam.cgPtyCat); - - /* Redirecting Number */ - copy_redirgNum_to_sngss7(ftdmchan, &iam.redirgNum); - - /* Redirecting Information */ - copy_redirgInfo_to_sngss7(ftdmchan, &iam.redirInfo); - - /* Original Called Number */ - copy_ocn_to_sngss7(ftdmchan, &iam.origCdNum); - - /* Access Transport - old implementation, taking from channel variable of ss7_clg_subaddr */ - copy_accTrnspt_to_sngss7(ftdmchan, &iam.accTrnspt); - - /* Access Transport - taking from channel variable of ss7_access_transport_urlenc. - This will overwirte the IE value set be above old implementation. - */ - copy_access_transport_to_sngss7(ftdmchan, &iam.accTrnspt); - - copy_NatureOfConnection_to_sngss7(ftdmchan, &iam.natConInd); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM clg = \"%s\" (NADI=%d), cld = \"%s\" (NADI=%d), loc = %s (NADI=%d)\n", - sngss7_info->circuit->cic, - ftdmchan->caller_data.cid_num.digits, - iam.cgPtyNum.natAddrInd.val, - ftdmchan->caller_data.dnis.digits, - iam.cdPtyNum.natAddrInd.val, - ftdmchan->caller_data.loc.digits, - iam.cgPtyNum1.natAddrInd.val); - } - - sng_cc_con_request (sngss7_info->spId, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, - &iam, - 0); - - if (native_going_up) { - /* - Note that this function (ft_to_sngss7_iam) is run within the main SS7 processing loop in - response to the DIALING state handler, we can set the state to UP here and that will - implicitly complete the DIALING state, but we *MUST* also advance the state handler - right away for a native bridge, otherwise, the processing state function (ftdm_sangoma_ss7_process_state_change) - will complete the state without having executed the handler for FTDM_CHANNEL_STATE_UP, and we won't notify - the user sending FTDM_SIGEVENT_UP which can cause the application to misbehave (ie, no audio) */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); - ftdm_channel_advance_states(ftdmchan); - } - - ftdm_safe_free(event_clone); - - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); - return; -} - -void ft_to_sngss7_inf(ftdm_channel_t *ftdmchan, SiCnStEvnt *inr) -{ - SiCnStEvnt evnt; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - memset (&evnt, 0x0, sizeof (evnt)); - - evnt.infoInd.eh.pres = PRSNT_NODEF; - evnt.infoInd.cgPtyAddrRespInd.pres = PRSNT_NODEF; - evnt.infoInd.cgPtyCatRespInd.pres = PRSNT_NODEF; - - evnt.infoInd.chrgInfoRespInd.pres = PRSNT_NODEF; - evnt.infoInd.chrgInfoRespInd.val = 0; - evnt.infoInd.solInfoInd.pres = PRSNT_NODEF; - evnt.infoInd.solInfoInd.val = 0; - evnt.infoInd.holdProvInd.pres = PRSNT_NODEF; - evnt.infoInd.holdProvInd.val = 0; - evnt.infoInd.spare.pres = PRSNT_NODEF; - evnt.infoInd.spare.val = 0; - - if (inr->infoReqInd.eh.pres == PRSNT_NODEF) { - if ((inr->infoReqInd.holdingInd.pres == PRSNT_NODEF) && (inr->infoReqInd.holdingInd.val == HOLD_REQ)) { - SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Received INR requesting holding information. Holding is not supported in INF.\n", sngss7_info->circuit->cic); - } - if ((inr->infoReqInd.chrgInfoReqInd.pres == PRSNT_NODEF) && (inr->infoReqInd.chrgInfoReqInd.val == CHRGINFO_REQ)) { - SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Received INR requesting charging information. Charging is not supported in INF.\n", sngss7_info->circuit->cic); - } - if ((inr->infoReqInd.malCaIdReqInd.pres == PRSNT_NODEF) && (inr->infoReqInd.malCaIdReqInd.val == CHRGINFO_REQ)) { - SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Received INR requesting malicious call id. Malicious call id is not supported in INF.\n", sngss7_info->circuit->cic); - } - - if ((inr->infoReqInd.cgPtyAdReqInd.pres == PRSNT_NODEF) && (inr->infoReqInd.cgPtyAdReqInd.val == CGPRTYADDREQ_REQ)) { - evnt.infoInd.cgPtyAddrRespInd.val=CGPRTYADDRESP_INCL; - copy_cgPtyNum_to_sngss7 (ftdmchan, &evnt.cgPtyNum); - } else { - evnt.infoInd.cgPtyAddrRespInd.val=CGPRTYADDRESP_NOTINCL; - } - - if ((inr->infoReqInd.cgPtyCatReqInd.pres == PRSNT_NODEF) && (inr->infoReqInd.cgPtyCatReqInd.val == CGPRTYCATREQ_REQ)) { - evnt.infoInd.cgPtyCatRespInd.val = CGPRTYCATRESP_INCL; - copy_cgPtyCat_to_sngss7 (ftdmchan, &evnt.cgPtyCat); - } else { - evnt.infoInd.cgPtyCatRespInd.val = CGPRTYCATRESP_NOTINCL; - } - } - else { - SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Received INR with no information request. Sending back default INF.\n", sngss7_info->circuit->cic); - } - - sng_cc_inf(1, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, - &evnt, - INFORMATION); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx INF\n", sngss7_info->circuit->cic); - -} - -void ft_to_sngss7_inr(ftdm_channel_t *ftdmchan) -{ - SiCnStEvnt evnt; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - memset (&evnt, 0x0, sizeof (evnt)); - - evnt.infoReqInd.eh.pres = PRSNT_NODEF; - evnt.infoReqInd.cgPtyAdReqInd.pres = PRSNT_NODEF; - evnt.infoReqInd.cgPtyAdReqInd.val=CGPRTYADDREQ_REQ; - - evnt.infoReqInd.holdingInd.pres = PRSNT_NODEF; - evnt.infoReqInd.holdingInd.val = HOLD_REQ; - - evnt.infoReqInd.cgPtyCatReqInd.pres = PRSNT_NODEF; - evnt.infoReqInd.cgPtyCatReqInd.val = CGPRTYCATREQ_REQ; - - evnt.infoReqInd.chrgInfoReqInd.pres = PRSNT_NODEF; - evnt.infoReqInd.chrgInfoReqInd.val = CHRGINFO_REQ; - - evnt.infoReqInd.malCaIdReqInd.pres = PRSNT_NODEF; - evnt.infoReqInd.malCaIdReqInd.val = MLBG_INFOREQ; - - sng_cc_inr(1, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, - &evnt, - INFORMATREQ); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx INR\n", sngss7_info->circuit->cic); -} - -void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan) -{ - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - SiCnStEvnt acm; - const char *backwardInd = NULL; - - memset (&acm, 0x0, sizeof (acm)); - - /* fill in the needed information for the ACM */ - acm.bckCallInd.eh.pres = PRSNT_NODEF; - acm.bckCallInd.chrgInd.pres = PRSNT_NODEF; - acm.bckCallInd.chrgInd.val = CHRG_CHRG; - acm.bckCallInd.cadPtyStatInd.pres = PRSNT_NODEF; - acm.bckCallInd.cadPtyStatInd.val = 0x01; - acm.bckCallInd.cadPtyCatInd.pres = PRSNT_NODEF; - acm.bckCallInd.cadPtyCatInd.val = CADCAT_ORDSUBS; - acm.bckCallInd.end2EndMethInd.pres = PRSNT_NODEF; - acm.bckCallInd.end2EndMethInd.val = E2EMTH_NOMETH; - acm.bckCallInd.intInd.pres = PRSNT_NODEF; - acm.bckCallInd.intInd.val = INTIND_NOINTW; - acm.bckCallInd.end2EndInfoInd.pres = PRSNT_NODEF; - acm.bckCallInd.end2EndInfoInd.val = E2EINF_NOINFO; - - acm.bckCallInd.isdnUsrPrtInd.pres = PRSNT_NODEF; - acm.bckCallInd.isdnUsrPrtInd.val = ISUP_NOTUSED; - backwardInd = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "acm_bi_iup"); - if (!ftdm_strlen_zero(backwardInd)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied backward indicator ISDN user part indicator ACM, value \"%s\"\n", backwardInd); - if (atoi(backwardInd) != 0 ) { - acm.bckCallInd.isdnUsrPrtInd.val = ISUP_USED; - } - } - acm.bckCallInd.holdInd.pres = PRSNT_NODEF; - acm.bckCallInd.holdInd.val = HOLD_NOTREQD; - acm.bckCallInd.isdnAccInd.pres = PRSNT_NODEF; - acm.bckCallInd.isdnAccInd.val = ISDNACC_NONISDN; - acm.bckCallInd.echoCtrlDevInd.pres = PRSNT_NODEF; - switch (ftdmchan->caller_data.bearer_capability) { - /**********************************************************************/ - case (FTDM_BEARER_CAP_SPEECH): - acm.bckCallInd.echoCtrlDevInd.val = 0x1; - break; - /**********************************************************************/ - case (FTDM_BEARER_CAP_UNRESTRICTED): - acm.bckCallInd.echoCtrlDevInd.val = 0x0; - break; - /**********************************************************************/ - case (FTDM_BEARER_CAP_3_1KHZ_AUDIO): - acm.bckCallInd.echoCtrlDevInd.val = 0x1; - break; - /**********************************************************************/ - default: - SS7_ERROR_CHAN(ftdmchan, "Unknown Bearer capability falling back to speech%s\n", " "); - acm.bckCallInd.echoCtrlDevInd.val = 0x1; - break; - /**********************************************************************/ - } /* switch (ftdmchan->caller_data.bearer_capability) */ - acm.bckCallInd.sccpMethInd.pres = PRSNT_NODEF; - acm.bckCallInd.sccpMethInd.val = SCCPMTH_NOIND; - - /* fill in any optional parameters */ - if (sngss7_test_options(&g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id], SNGSS7_ACM_OBCI_BITA)) { - SS7_DEBUG_CHAN(ftdmchan, "Found ACM_OBCI_BITA flag:0x%X\n", g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].options); - acm.optBckCalInd.eh.pres = PRSNT_NODEF; - acm.optBckCalInd.inbndInfoInd.pres = PRSNT_NODEF; - acm.optBckCalInd.inbndInfoInd.val = 0x1; - acm.optBckCalInd.caFwdMayOcc.pres = PRSNT_DEF; - acm.optBckCalInd.simpleSegmInd.pres = PRSNT_DEF; - acm.optBckCalInd.mlppUserInd.pres = PRSNT_DEF; - acm.optBckCalInd.usrNetIneractInd.pres = PRSNT_DEF; - acm.optBckCalInd.netExcDelInd.pres = PRSNT_DEF; - } /* if (sngss7_test_options(isup_intf, SNGSS7_ACM_OBCI_BITA)) */ - - /* send the ACM request to LibSngSS7 */ - sng_cc_con_status (1, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, - &acm, - ADDRCMPLT); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ACM\n", sngss7_info->circuit->cic); - - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); - return; -} - -void ft_to_sngss7_cpg (ftdm_channel_t *ftdmchan) -{ - SiCnStEvnt cpg; - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - - memset (&cpg, 0, sizeof (cpg)); - - cpg.evntInfo.eh.pres = PRSNT_NODEF; - - cpg.evntInfo.evntInd.pres = PRSNT_NODEF; - cpg.evntInfo.evntInd.val = SNGSS7_EVNTINFO_IND_INBAND_AVAIL; /* Event Indicator = In-band info is now available */ - - cpg.evntInfo.evntPresResInd.pres = PRSNT_NODEF; - cpg.evntInfo.evntPresResInd.val = 0; /* Event presentation restricted indicator = no indication */ - - /* send the CPG request to LibSngSS7 */ - sng_cc_con_status (1, sngss7_info->suInstId, sngss7_info->spInstId, sngss7_info->circuit->id, &cpg, PROGRESS); - - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "[CIC:%d]Tx CPG\n", sngss7_info->circuit->cic); - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); - return; -} -void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan) -{ - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - SiConEvnt anm; - - memset (&anm, 0x0, sizeof (anm)); - - /* send the ANM request to LibSngSS7 */ - sng_cc_con_response(1, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, - &anm, - 5); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ANM\n", sngss7_info->circuit->cic); - - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); - return; -} - -/******************************************************************************/ -void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan) -{ - const char *loc_ind = NULL; - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - SiRelEvnt rel; - - memset (&rel, 0x0, sizeof (rel)); - - rel.causeDgn.eh.pres = PRSNT_NODEF; - rel.causeDgn.location.pres = PRSNT_NODEF; - - loc_ind = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rel_loc"); - if (!ftdm_strlen_zero(loc_ind)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied location indicator in REL, value \"%s\"\n", loc_ind); - rel.causeDgn.location.val = atoi(loc_ind); - } else { - rel.causeDgn.location.val = 0x01; - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied location indicator in REL, using 0x01\"%s\"\n", ""); - } - rel.causeDgn.cdeStand.pres = PRSNT_NODEF; - rel.causeDgn.cdeStand.val = 0x00; - rel.causeDgn.recommend.pres = NOTPRSNT; - rel.causeDgn.causeVal.pres = PRSNT_NODEF; - rel.causeDgn.causeVal.val = (uint8_t) ftdmchan->caller_data.hangup_cause; - rel.causeDgn.dgnVal.pres = NOTPRSNT; - - /* send the REL request to LibSngSS7 */ - sng_cc_rel_request (1, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, - &rel); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx REL cause=%d \n", - sngss7_info->circuit->cic, - ftdmchan->caller_data.hangup_cause ); - - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); - return; -} - -/******************************************************************************/ -void ft_to_sngss7_rlc (ftdm_channel_t * ftdmchan) -{ - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - SiRelEvnt rlc; - - memset (&rlc, 0x0, sizeof (rlc)); - - /* send the RLC request to LibSngSS7 */ - sng_cc_rel_response (1, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, - &rlc); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RLC\n", sngss7_info->circuit->cic); - - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); - return; -} - -/******************************************************************************/ -void ft_to_sngss7_rsc (ftdm_channel_t * ftdmchan) -{ - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - sng_cc_sta_request (1, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, - sngss7_info->globalFlg, - SIT_STA_CIRRESREQ, - NULL); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RSC\n", sngss7_info->circuit->cic); - - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); - return; -} - -/******************************************************************************/ -void ft_to_sngss7_rsca (ftdm_channel_t * ftdmchan) -{ - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - sng_cc_sta_request (1, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, - sngss7_info->globalFlg, - SIT_STA_CIRRESRSP, - NULL); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RSC-RLC\n", sngss7_info->circuit->cic); - - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); - return; -} - -/******************************************************************************/ -void ft_to_sngss7_blo (ftdm_channel_t * ftdmchan) -{ - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - sng_cc_sta_request (1, - 0, - 0, - sngss7_info->circuit->id, - sngss7_info->globalFlg, - SIT_STA_CIRBLOREQ, - NULL); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx BLO\n", sngss7_info->circuit->cic); - - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); - return; -} - -/******************************************************************************/ -void ft_to_sngss7_bla (ftdm_channel_t * ftdmchan) -{ - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - sng_cc_sta_request (1, - 0, - 0, - sngss7_info->circuit->id, - sngss7_info->globalFlg, - SIT_STA_CIRBLORSP, - NULL); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx BLA\n", sngss7_info->circuit->cic); - - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); - return; -} - -/******************************************************************************/ -void -ft_to_sngss7_ubl (ftdm_channel_t * ftdmchan) -{ - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - sng_cc_sta_request (1, - 0, - 0, - sngss7_info->circuit->id, - sngss7_info->globalFlg, - SIT_STA_CIRUBLREQ, - NULL); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx UBL\n", sngss7_info->circuit->cic); - - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); - return; -} - -/******************************************************************************/ -void ft_to_sngss7_uba (ftdm_channel_t * ftdmchan) -{ - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - sng_cc_sta_request (1, - 0, - 0, - sngss7_info->circuit->id, - sngss7_info->globalFlg, - SIT_STA_CIRUBLRSP, - NULL); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx UBA\n", sngss7_info->circuit->cic); - - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); - return; -} - -/******************************************************************************/ -void ft_to_sngss7_lpa (ftdm_channel_t * ftdmchan) -{ - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - sng_cc_sta_request (1, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, - sngss7_info->globalFlg, - SIT_STA_LOOPBACKACK, - NULL); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx LPA\n", sngss7_info->circuit->cic); - - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); -return; -} - -/******************************************************************************/ -void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan) -{ - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - SiStaEvnt gra; - - /* clean out the gra struct */ - memset (&gra, 0x0, sizeof (gra)); - - gra.rangStat.eh.pres = PRSNT_NODEF; - - /* fill in the range */ - gra.rangStat.range.pres = PRSNT_NODEF; - gra.rangStat.range.val = sngss7_info->rx_grs.range; - - /* fill in the status */ - gra.rangStat.status.pres = PRSNT_NODEF; - gra.rangStat.status.len = ((sngss7_info->rx_grs.range + 1) >> 3) + (((sngss7_info->rx_grs.range + 1) & 0x07) ? 1 : 0); - - /* the status field should be 1 if blocked for maintenace reasons - * and 0 is not blocked....since we memset the struct nothing to do - */ - - /* send the GRA to LibSng-SS7 */ - sng_cc_sta_request (1, - 0, - 0, - sngss7_info->rx_grs.circuit, - 0, - SIT_STA_GRSRSP, - &gra); - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Tx GRA (%d:%d)\n", - sngss7_info->circuit->cic, - sngss7_info->circuit->cic, - (sngss7_info->circuit->cic + sngss7_info->rx_grs.range)); - - - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); - return; -} - -/******************************************************************************/ -void ft_to_sngss7_grs (ftdm_channel_t *fchan) -{ - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - sngss7_chan_data_t *cinfo = fchan->call_data; - - SiStaEvnt grs; - - ftdm_assert(sngss7_test_ckt_flag(cinfo, FLAG_GRP_RESET_TX) && - !sngss7_test_ckt_flag(cinfo, FLAG_GRP_RESET_SENT), "Incorrect flags\n"); - - memset (&grs, 0x0, sizeof(grs)); - grs.rangStat.eh.pres = PRSNT_NODEF; - grs.rangStat.range.pres = PRSNT_NODEF; - grs.rangStat.range.val = cinfo->tx_grs.range; - - sng_cc_sta_request (1, - 0, - 0, - cinfo->tx_grs.circuit, - 0, - SIT_STA_GRSREQ, - &grs); - - SS7_INFO_CHAN(fchan, "[CIC:%d]Tx GRS (%d:%d)\n", - cinfo->circuit->cic, - cinfo->circuit->cic, - (cinfo->circuit->cic + cinfo->tx_grs.range)); - - sngss7_set_ckt_flag(cinfo, FLAG_GRP_RESET_SENT); - - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); -} - -/******************************************************************************/ -void ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan) -{ - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - int x = 0; - - SiStaEvnt cgba; - - memset (&cgba, 0x0, sizeof(cgba)); - - /* fill in the circuit group supervisory message */ - cgba.cgsmti.eh.pres = PRSNT_NODEF; - cgba.cgsmti.typeInd.pres = PRSNT_NODEF; - cgba.cgsmti.typeInd.val = sngss7_span->rx_cgb.type; - - cgba.rangStat.eh.pres = PRSNT_NODEF; - /* fill in the range */ - cgba.rangStat.range.pres = PRSNT_NODEF; - cgba.rangStat.range.val = sngss7_span->rx_cgb.range; - /* fill in the status */ - cgba.rangStat.status.pres = PRSNT_NODEF; - cgba.rangStat.status.len = ((sngss7_span->rx_cgb.range + 1) >> 3) + (((sngss7_span->rx_cgb.range + 1) & 0x07) ? 1 : 0); - for(x = 0; x < cgba.rangStat.status.len; x++){ - cgba.rangStat.status.val[x] = sngss7_span->rx_cgb.status[x]; - } - - sng_cc_sta_request (1, - 0, - 0, - sngss7_span->rx_cgb.circuit, - 0, - SIT_STA_CGBRSP, - &cgba); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx CGBA (%d:%d)\n", - sngss7_info->circuit->cic, - sngss7_info->circuit->cic, - (sngss7_info->circuit->cic + sngss7_span->rx_cgb.range)); - - /* clean out the saved data */ - memset(&sngss7_span->rx_cgb, 0x0, sizeof(sngss7_group_data_t)); - - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); - return; -} - -/******************************************************************************/ -void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan) -{ - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - int x = 0; - - SiStaEvnt cgua; - - memset (&cgua, 0x0, sizeof(cgua)); - - /* fill in the circuit group supervisory message */ - cgua.cgsmti.eh.pres = PRSNT_NODEF; - cgua.cgsmti.typeInd.pres = PRSNT_NODEF; - cgua.cgsmti.typeInd.val = sngss7_span->rx_cgu.type; - - cgua.rangStat.eh.pres = PRSNT_NODEF; - /* fill in the range */ - cgua.rangStat.range.pres = PRSNT_NODEF; - cgua.rangStat.range.val = sngss7_span->rx_cgu.range; - /* fill in the status */ - cgua.rangStat.status.pres = PRSNT_NODEF; - cgua.rangStat.status.len = ((sngss7_span->rx_cgu.range + 1) >> 3) + (((sngss7_span->rx_cgu.range + 1) & 0x07) ? 1 : 0); - for(x = 0; x < cgua.rangStat.status.len; x++){ - cgua.rangStat.status.val[x] = sngss7_span->rx_cgu.status[x]; - } - - sng_cc_sta_request (1, - 0, - 0, - sngss7_span->rx_cgu.circuit, - 0, - SIT_STA_CGURSP, - &cgua); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx CGUA (%d:%d)\n", - sngss7_info->circuit->cic, - sngss7_info->circuit->cic, - (sngss7_info->circuit->cic + sngss7_span->rx_cgu.range)); - - /* clean out the saved data */ - memset(&sngss7_span->rx_cgu, 0x0, sizeof(sngss7_group_data_t)); - - - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); - return; -} - -/******************************************************************************/ -void ft_to_sngss7_cgb(ftdm_channel_t * ftdmchan) -{ - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - SiStaEvnt cgb; - int x = 0; - - - memset (&cgb, 0x0, sizeof(cgb)); - - /* fill in the circuit group supervisory message */ - cgb.cgsmti.eh.pres = PRSNT_NODEF; - cgb.cgsmti.typeInd.pres = PRSNT_NODEF; - cgb.cgsmti.typeInd.val = sngss7_span->tx_cgb.type; - - /* fill in the range */ - cgb.rangStat.eh.pres = PRSNT_NODEF; - cgb.rangStat.range.pres = PRSNT_NODEF; - cgb.rangStat.range.val = sngss7_span->tx_cgb.range; - - /* fill in the status */ - cgb.rangStat.status.pres = PRSNT_NODEF; - cgb.rangStat.status.len = ((sngss7_span->tx_cgb.range + 1) >> 3) + (((sngss7_span->tx_cgb.range + 1) & 0x07) ? 1 : 0); - for(x = 0; x < cgb.rangStat.status.len; x++){ - cgb.rangStat.status.val[x] = sngss7_span->tx_cgb.status[x]; - } - - sng_cc_sta_request (1, - 0, - 0, - sngss7_span->tx_cgb.circuit, - 0, - SIT_STA_CGBREQ, - &cgb); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx CGB (%d:%d)\n", - sngss7_info->circuit->cic, - sngss7_info->circuit->cic, - (sngss7_info->circuit->cic + sngss7_span->tx_cgb.range)); - - /* clean out the saved data */ - memset(&sngss7_span->tx_cgb, 0x0, sizeof(sngss7_group_data_t)); - - - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); - return; -} - -/******************************************************************************/ -void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan) -{ - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - SiStaEvnt cgu; - int x = 0; - - - memset (&cgu, 0x0, sizeof(cgu)); - - /* fill in the circuit group supervisory message */ - cgu.cgsmti.eh.pres = PRSNT_NODEF; - cgu.cgsmti.typeInd.pres = PRSNT_NODEF; - cgu.cgsmti.typeInd.val = sngss7_span->tx_cgu.type; - - /* fill in the range */ - cgu.rangStat.eh.pres = PRSNT_NODEF; - cgu.rangStat.range.pres = PRSNT_NODEF; - cgu.rangStat.range.val = sngss7_span->tx_cgu.range; - - /* fill in the status */ - cgu.rangStat.status.pres = PRSNT_NODEF; - cgu.rangStat.status.len = ((sngss7_span->tx_cgu.range + 1) >> 3) + (((sngss7_span->tx_cgu.range + 1) & 0x07) ? 1 : 0); - for(x = 0; x < cgu.rangStat.status.len; x++){ - cgu.rangStat.status.val[x] = sngss7_span->tx_cgu.status[x]; - } - - sng_cc_sta_request (1, - 0, - 0, - sngss7_span->tx_cgu.circuit, - 0, - SIT_STA_CGUREQ, - &cgu); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx CGU (%d:%d)\n", - sngss7_info->circuit->cic, - sngss7_info->circuit->cic, - (sngss7_info->circuit->cic + sngss7_span->tx_cgu.range)); - - /* clean out the saved data */ - memset(&sngss7_span->tx_cgu, 0x0, sizeof(sngss7_group_data_t)); - - - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); - return; -} - -/* French SPIROU send Charge Unit */ -/* No one calls this function yet, but it has been implemented to complement TXA messages */ -void ft_to_sngss7_itx (ftdm_channel_t * ftdmchan) -{ -#ifndef SANGOMA_SPIROU - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "ITX message not supported!, please update your libsng_ss7\n"); -#else - const char* var = NULL; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - SiCnStEvnt itx; - - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - memset (&itx, 0x0, sizeof (itx)); - - itx.msgNum.eh.pres = PRSNT_NODEF; - itx.msgNum.msgNum.pres = PRSNT_NODEF; - var = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_itx_msg_num"); - if (!ftdm_strlen_zero(var)) { - itx.msgNum.msgNum.val = atoi(var); - } else { - itx.msgNum.msgNum.val = 0x1; - } - - itx.chargUnitNum.eh.pres = PRSNT_NODEF; - itx.chargUnitNum.chargUnitNum.pres = PRSNT_NODEF; - var = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_itx_charge_unit"); - if (!ftdm_strlen_zero(var)) { - itx.chargUnitNum.chargUnitNum.val = atoi(var); - } else { - itx.chargUnitNum.chargUnitNum.val = 0x1; - } - - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "ITX Charging Unit:%d Msg Num:%d\n", itx.chargUnitNum.chargUnitNum.val, itx.msgNum.msgNum.val); - sng_cc_con_status (1, sngss7_info->suInstId, sngss7_info->spInstId, sngss7_info->circuit->id, &itx, CHARGE_UNIT); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ITX\n", sngss7_info->circuit->cic); -#endif - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); - return; -} - -/* French SPIROU send Charging Acknowledgement */ -void ft_to_sngss7_txa (ftdm_channel_t * ftdmchan) -{ -#ifndef SANGOMA_SPIROU - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "TXA message not supported!, please update your libsng_ss7\n"); -#else - SiCnStEvnt txa; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__); - - memset (&txa, 0x0, sizeof(txa)); - - sng_cc_con_status(1, sngss7_info->suInstId, sngss7_info->spInstId, sngss7_info->circuit->id, &txa, CHARGE_ACK); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx TXA\n", sngss7_info->circuit->cic); -#endif - SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__); - return; -} - -/******************************************************************************/ -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_relay.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_relay.c deleted file mode 100644 index 8389e56950..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_relay.c +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright (c) 2009|Konrad Hammel - * All rights reserved. - * - * Redistribution and use in source and binary forms|with or without - * modification|are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice|this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice|this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT - * LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL, - * EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* INCLUDE ********************************************************************/ -#include "ftmod_sangoma_ss7_main.h" -/******************************************************************************/ - -/* DEFINES ********************************************************************/ -/******************************************************************************/ - -/* GLOBALS ********************************************************************/ -/******************************************************************************/ - -/* PROTOTYPES *****************************************************************/ - -/*static ftdm_status_t enable_all_ckts_for_relay(void);*/ -static ftdm_status_t reconfig_all_ckts_for_relay(void); -static ftdm_status_t disable_all_ckts_for_relay(void); -static ftdm_status_t block_all_ckts_for_relay(uint32_t procId); -/* static ftdm_status_t unblock_all_ckts_for_relay(uint32_t procId); */ -static ftdm_status_t disable_all_sigs_for_relay(uint32_t procId); -static ftdm_status_t disble_all_mtp2_sigs_for_relay(void); -/******************************************************************************/ - -/* FUNCTIONS ******************************************************************/ -ftdm_status_t handle_relay_connect(RyMngmt *sta) -{ - sng_relay_t *sng_relay = &g_ftdm_sngss7_data.cfg.relay[sta->t.usta.s.ryUpUsta.id]; - - if (!sngss7_test_flag(sng_relay, SNGSS7_RELAY_INIT)) { - /* SS7_INFO("Relay Channel %d initial connection UP\n", sng_relay->id); */ - sngss7_set_flag(sng_relay, SNGSS7_RELAY_INIT); - } - - SS7_INFO("Relay Channel %d connection UP\n", sng_relay->id); - if (sng_relay->type == LRY_CT_TCP_CLIENT) { - if (reconfig_all_ckts_for_relay()) { - SS7_ERROR("Failed to reconfigure ISUP Ckts!\n"); - /* we're done....this is very bad! */ - } - return FTDM_SUCCESS; - } else if (sng_relay->type == LRY_CT_TCP_SERVER) { - ftmod_ss7_enable_grp_mtp3Link(sta->t.usta.s.ryUpUsta.id); - /* unbloock the ckts on the client system */ - return FTDM_SUCCESS; - } - return FTDM_FAIL; -} - -/******************************************************************************/ -ftdm_status_t handle_relay_disconnect_on_error(RyMngmt *sta) -{ - SS7_DEBUG("SS7 relay disconnect on error\n"); - - /* check which procId is in error, if it is 1, disable the ckts */ - if (sta->t.usta.s.ryErrUsta.errPid == 1 ) { - /* we've lost the server, bring the sig status down on all ckts */ - disable_all_ckts_for_relay(); - - /* we've lost the server, bring down the mtp2 links */ - disble_all_mtp2_sigs_for_relay(); - } - - /* check if the channel is a server, means we just lost a MGW */ - if (g_ftdm_sngss7_data.cfg.relay[sta->t.usta.s.ryErrUsta.errPid].type == LRY_CT_TCP_SERVER) { - /* we've lost the client, bring down all the ckts for this procId */ - block_all_ckts_for_relay(sta->t.usta.s.ryErrUsta.errPid); - - /* we've lost the client, bring down all mtp3 links for this procId */ - disable_all_sigs_for_relay(sta->t.usta.s.ryErrUsta.errPid); - } - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t handle_relay_disconnect_on_down(RyMngmt *sta) -{ - - SS7_DEBUG("SS7 relay disconnect on down\n"); - - /* check if the channel is a server, means we just lost a MGW */ - if (g_ftdm_sngss7_data.cfg.relay[sta->t.usta.s.ryUpUsta.id].type == LRY_CT_TCP_SERVER) { - block_all_ckts_for_relay(sta->t.usta.s.ryUpUsta.id); - - disable_all_sigs_for_relay(sta->t.usta.s.ryUpUsta.id); - } - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t disable_all_ckts_for_relay(void) -{ - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - int x; - - SS7_INFO("Disabling all ckts becuase of Relay loss\n"); - - x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - /**********************************************************************/ - /* make sure this is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(g_ftdm_sngss7_data.cfg.isupCkt[x].id, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", g_ftdm_sngss7_data.cfg.isupCkt[x].id); - x++; - continue; - } - - /* throw the relay_down flag */ - sngss7_set_ckt_flag(sngss7_info, FLAG_RELAY_DOWN); - - /* throw the channel infId status flags to PAUSED ... they will be executed next process cycle */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_RESUME); - sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_PAUSED); - } /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) */ - - /* move along */ - x++; - /**********************************************************************/ - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */ - - return FTDM_SUCCESS; -} -#if 0 -/******************************************************************************/ -ftdm_status_t enable_all_ckts_for_relay(void) -{ - sngss7_chan_data_t *sngss7_info = NULL; - sng_isup_inf_t *sngIntf = NULL; - ftdm_channel_t *ftdmchan = NULL; - int x; - - SS7_INFO("Enabling all ckts becuase of Relay connection\n"); - - x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - /**********************************************************************/ - /* make sure this is voice channel */ - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(g_ftdm_sngss7_data.cfg.isupCkt[x].id, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", g_ftdm_sngss7_data.cfg.isupCkt[x].id); - x++; - continue; - } - - /* bring the relay_down flag down */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_RELAY_DOWN); - - sngIntf = &g_ftdm_sngss7_data.cfg.isupIntf[g_ftdm_sngss7_data.cfg.isupCkt[x].infId]; - - /* check if the interface is paused or resumed */ - if (sngss7_test_flag(sngIntf, SNGSS7_PAUSED)) { - /* don't bring the channel resume flag up...the interface is down */ - SS7_DEBUG_CHAN(ftdmchan, "ISUP interface (%d) set to paused, not resuming channel\n", sngIntf->id); - } else { - SS7_DEBUG_CHAN(ftdmchan, "ISUP interface (%d) set to resume, resuming channel\n", sngIntf->id); - /* throw the channel infId status flags to PAUSED ... they will be executed next process cycle */ - sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_RESUME); - sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_PAUSED); - } - } /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) */ - - /* move along */ - x++; - /**********************************************************************/ - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */ - - return FTDM_SUCCESS; -} -#endif -/******************************************************************************/ -ftdm_status_t reconfig_all_ckts_for_relay(void) -{ - int x; - sngss7_chan_data_t *sngss7_info = NULL; - - /* go through all the circuits on our ProcId */ - x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - /**************************************************************************/ - if ( g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - /* grab the private data structure */ - sngss7_info = g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - - /* mark the circuit for re-configuration */ - sngss7_set_ckt_flag(sngss7_info, FLAG_CKT_RECONFIG); - - /* clear the relay flag */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_RELAY_DOWN); - } - - /* move to the next circuit */ - x++; - /**************************************************************************/ - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */ - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t block_all_ckts_for_relay(uint32_t procId) -{ - int x; - int ret; - - /* we just lost connection to this procId, send out a block for all these circuits */ - x = (procId * 1000) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - /**************************************************************************/ - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - - /* send a block request via stack manager */ - ret = ftmod_ss7_block_isup_ckt_nowait(g_ftdm_sngss7_data.cfg.isupCkt[x].id); - if (ret) { - SS7_INFO("Successfully BLOcked CIC:%d(ckt:%d) due to Relay failure\n", - g_ftdm_sngss7_data.cfg.isupCkt[x].cic, - g_ftdm_sngss7_data.cfg.isupCkt[x].id); - } else { - SS7_ERROR("Failed to BLOck CIC:%d(ckt:%d) due to Relay failure\n", - g_ftdm_sngss7_data.cfg.isupCkt[x].cic, - g_ftdm_sngss7_data.cfg.isupCkt[x].id); - } - - } /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) */ - - /* move along */ - x++; - /**************************************************************************/ - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */ - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t disable_all_sigs_for_relay(uint32_t procId) -{ - SS7_INFO("Disalbing all sig links on ProcID = %d\n", procId); - - ftmod_ss7_disable_grp_mtp3Link(procId); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t disble_all_mtp2_sigs_for_relay(void) -{ - /* check if there is a local mtp2 link*/ - if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2_STARTED)) { - SS7_INFO("Disalbing all mtp2 sig links on local system\n"); - - ftmod_ss7_disable_grp_mtp2Link(1); - } - - return FTDM_SUCCESS; - -} - -#if 0 -/******************************************************************************/ -static ftdm_status_t unblock_all_ckts_for_relay(uint32_t procId) -{ - int x; - int ret; - - /* we just got connection to this procId, send out a unblock for all these circuits - * since we blocked them when we lost the connection - */ - x = (procId * 1000) + 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - /**************************************************************************/ - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) { - - /* send a block request via stack manager */ - ret = ftmod_ss7_unblock_isup_ckt(g_ftdm_sngss7_data.cfg.isupCkt[x].id); - if (ret) { - SS7_INFO("Successfully unblocked CIC:%d(ckt:%d) due to Relay connection\n", - g_ftdm_sngss7_data.cfg.isupCkt[x].cic, - g_ftdm_sngss7_data.cfg.isupCkt[x].id); - } else { - SS7_ERROR("Failed to unblock CIC:%d(ckt:%d) due to Relay connection\n", - g_ftdm_sngss7_data.cfg.isupCkt[x].cic, - g_ftdm_sngss7_data.cfg.isupCkt[x].id); - } - - } /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) */ - - /* move along */ - x++; - /**************************************************************************/ - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */ - - return FTDM_SUCCESS; -} -#endif - - -/******************************************************************************/ -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c deleted file mode 100644 index d9e1790da0..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (c) 2009 Konrad Hammel - * All rights reserved. - * - * Redistribution and use in source and binary forms|with or without - * modification|are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice|this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice|this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT - * LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL, - * EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* INCLUDE ********************************************************************/ -#include "ftmod_sangoma_ss7_main.h" -/******************************************************************************/ - -/* DEFINES ********************************************************************/ -/******************************************************************************/ - -/* GLOBALS ********************************************************************/ -/******************************************************************************/ - -/* PROTOTYPES *****************************************************************/ -int ftmod_ss7_mtp1link_sta(uint32_t id, L1Mngmt *cfm); -int ftmod_ss7_mtp2link_sta(uint32_t id, SdMngmt *cfm); -int ftmod_ss7_mtp3link_sta(uint32_t id, SnMngmt *cfm); -int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm); -int ftmod_ss7_isup_intf_sta(uint32_t id, uint8_t *status); -int ftmod_ss7_relay_status(uint32_t id, RyMngmt *cfm); -int ftmod_ss7_isup_ckt_sta(uint32_t id, unsigned char *state); -/******************************************************************************/ - -/* FUNCTIONS ******************************************************************/ -int ftmod_ss7_mtp1link_sta(uint32_t id, L1Mngmt *cfm) -{ - - return 1; -} - -/******************************************************************************/ -int ftmod_ss7_mtp2link_sta(uint32_t id, SdMngmt *cfm) -{ - SdMngmt sta; - Pst pst; - - memset(&sta, 0x0, sizeof(sta)); - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSD; - - sta.hdr.elmId.elmnt = STDLSAP; - sta.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtp2Link[id].id; - - return(sng_sta_mtp2(&pst, &sta, cfm)); -} - -/******************************************************************************/ -int ftmod_ss7_mtp3link_sta(uint32_t id, SnMngmt *cfm) -{ - SnMngmt sta; - Pst pst; - - memset(&sta, 0x0, sizeof(sta)); - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /* check the for the correct ProcId and make sure it goes to the right system */ - if (g_ftdm_sngss7_data.cfg.procId != 1) { - pst.dstProcId = 1; - } - - sta.hdr.elmId.elmnt = STDLSAP; - sta.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtp3Link[id].id; - - return(sng_sta_mtp3(&pst, &sta, cfm)); -} - -/******************************************************************************/ -int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm) -{ - SnMngmt sta; - Pst pst; - - memset(&sta, 0x0, sizeof(sta)); - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSN; - - /* check the for the correct ProcId and make sure it goes to the right system */ - if (g_ftdm_sngss7_data.cfg.procId != 1) { - pst.dstProcId = 1; - } - - sta.hdr.elmId.elmnt = STLNKSET; - sta.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLinkSet[id].id; - sta.hdr.elmId.elmntInst2 = g_ftdm_sngss7_data.cfg.mtpLinkSet[id].links[0]; - - return(sng_sta_mtp3(&pst, &sta, cfm)); -} - -/******************************************************************************/ -int ftmod_ss7_isup_intf_sta(uint32_t id, uint8_t *status) -{ - SiMngmt sta; - SiMngmt cfm; - Pst pst; - int ret; - - memset(&sta, 0x0, sizeof(sta)); - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSI; - - /* check the for the correct ProcId and make sure it goes to the right system */ - if (g_ftdm_sngss7_data.cfg.procId != 1) { - pst.dstProcId = 1; - } - - /* request the status of an inftId */ - sta.hdr.entId.ent = ENTSI; - sta.hdr.entId.inst = S_INST; - sta.hdr.msgType = TSSTA; - sta.hdr.elmId.elmnt = SI_STINTF; - - sta.t.ssta.elmntId.intfId = id; - - ret = sng_sta_isup(&pst, &sta, &cfm); - - *status = cfm.t.ssta.cfm.s.intf.state; - - return(ret); -} - -/******************************************************************************/ -int ftmod_ss7_relay_status(uint32_t id, RyMngmt *cfm) -{ - RyMngmt sta; - Pst pst; - - memset(&sta, 0x0, sizeof(sta)); - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTRY; - - sta.hdr.entId.ent = ENTRY; - sta.hdr.entId.inst = S_INST; - sta.hdr.msgType = TSSTA; - sta.hdr.elmId.elmnt = STCHSTA; - sta.hdr.elmId.elmntInst1 = id; - - - return(sng_sta_relay(&pst, &sta, cfm)); -} - -/******************************************************************************/ -int ftmod_ss7_isup_ckt_sta(uint32_t id, unsigned char *state) -{ - SiMngmt sta; - SiMngmt cfm; - Pst pst; - int ret; - - memset(&sta, 0x0, sizeof(sta)); - - /* initalize the post structure */ - smPstInit(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTSI; - - /* check the for the correct ProcId and make sure it goes to the right system */ - if (g_ftdm_sngss7_data.cfg.procId != 1) { - pst.dstProcId = 1; - } - - /* request the status of an inftId */ - sta.hdr.entId.ent = ENTSI; - sta.hdr.entId.inst = S_INST; - sta.hdr.msgType = TSSTA; - sta.hdr.elmId.elmnt = SI_STCIRGRP; - - sta.t.ssta.elmntId.circuit = id; - sta.t.ssta.param.cirgr.range = 1; - - ret = sng_sta_isup(&pst, &sta, &cfm); - - *state = cfm.t.ssta.cfm.s.cir.state[0]; - - return(ret); -} - -/******************************************************************************/ -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c deleted file mode 100644 index 257ccd943a..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2009 Konrad Hammel - * All rights reserved. - * - * Redistribution and use in source and binary forms|with or without - * modification|are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice|this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice|this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT - * LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL, - * EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* INCLUDE ********************************************************************/ -#include "ftmod_sangoma_ss7_main.h" -/******************************************************************************/ - -/* DEFINES ********************************************************************/ -/******************************************************************************/ - -/* GLOBALS ********************************************************************/ -/******************************************************************************/ - -/* PROTOTYPES *****************************************************************/ -/******************************************************************************/ - -/* FUNCTIONS ******************************************************************/ -/******************************************************************************/ - -/******************************************************************************/ -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c deleted file mode 100644 index 42f1ca82da..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c +++ /dev/null @@ -1,3415 +0,0 @@ -/* - * Copyright (c) 2009, Konrad Hammel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* INCLUDE ********************************************************************/ -#include "ftmod_sangoma_ss7_main.h" -#ifdef HAVE_ZLIB -#include -#endif -/******************************************************************************/ - -/* DEFINES ********************************************************************/ -/******************************************************************************/ - -/* GLOBALS ********************************************************************/ -uint32_t sngss7_id; -/******************************************************************************/ - -/* PROTOTYPES *****************************************************************/ -int check_for_state_change(ftdm_channel_t *ftdmchan); -int check_for_reset(sngss7_chan_data_t *sngss7_info); - -unsigned long get_unique_id(void); - -ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan); - -ftdm_status_t check_if_rx_grs_started(ftdm_span_t *ftdmspan); -ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan); -ftdm_status_t check_if_rx_gra_started(ftdm_span_t *ftdmspan); -ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan); - -ftdm_status_t process_span_ucic(ftdm_span_t *ftdmspan); - -ftdm_status_t encode_subAddrIE_nsap(const char *subAddr, char *subAddrIE, int type); -ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int type); - -int find_mtp2_error_type_in_map(const char *err_type); -int find_link_type_in_map(const char *linkType); -int find_switch_type_in_map(const char *switchType); -int find_ssf_type_in_map(const char *ssfType); -int find_cic_cntrl_in_map(const char *cntrlType); - -ftdm_status_t check_status_of_all_isup_intf(void); -ftdm_status_t check_for_reconfig_flag(ftdm_span_t *ftdmspan); - -void sngss7_send_signal(sngss7_chan_data_t *sngss7_info, ftdm_signal_event_t event_id); -void sngss7_set_sig_status(sngss7_chan_data_t *sngss7_info, ftdm_signaling_status_t status); -ftdm_status_t sngss7_add_var(sngss7_chan_data_t *ss7_info, const char* var, const char* val); -ftdm_status_t sngss7_add_raw_data(sngss7_chan_data_t *sngss7_info, uint8_t* data, ftdm_size_t data_len); -/******************************************************************************/ - -FTDM_ENUM_NAMES(CKT_FLAGS_NAMES, CKT_FLAGS_STRING) -FTDM_STR2ENUM(ftmod_ss7_ckt_state2flag, ftmod_ss7_ckt_flag2str, sng_ckt_flag_t, CKT_FLAGS_NAMES, 31) - -FTDM_ENUM_NAMES(BLK_FLAGS_NAMES, BLK_FLAGS_STRING) -FTDM_STR2ENUM(ftmod_ss7_blk_state2flag, ftmod_ss7_blk_flag2str, sng_ckt_block_flag_t, BLK_FLAGS_NAMES, 31) - -/* FUNCTIONS ******************************************************************/ -static uint8_t get_trillium_val(ftdm2trillium_t *vals, uint8_t ftdm_val, uint8_t default_val); -static uint8_t get_ftdm_val(ftdm2trillium_t *vals, uint8_t trillium_val, uint8_t default_val); -ftdm_status_t four_char_to_hex(const char* in, uint16_t* out) ; -ftdm_status_t hex_to_four_char(uint16_t in, char* out); - - -ftdm_status_t hex_to_char(uint16_t in, char* out, int len); -ftdm_status_t char_to_hex(const char* in, uint16_t* out, int len); - -/* Maps generic FreeTDM CPC codes to SS7 CPC codes */ -ftdm2trillium_t cpc_codes[] = { - {FTDM_CPC_UNKNOWN, CAT_UNKNOWN}, - {FTDM_CPC_OPERATOR_FRENCH, CAT_OPLANGFR}, - {FTDM_CPC_OPERATOR_ENGLISH, CAT_OPLANGENG}, - {FTDM_CPC_OPERATOR_GERMAN, CAT_OPLANGGER}, - {FTDM_CPC_OPERATOR_RUSSIAN, CAT_OPLANGRUS}, - {FTDM_CPC_OPERATOR_SPANISH, CAT_OPLANGSP}, - {FTDM_CPC_ORDINARY, CAT_ORD}, - {FTDM_CPC_PRIORITY, CAT_PRIOR}, - {FTDM_CPC_DATA, CAT_DATA}, - {FTDM_CPC_TEST, CAT_TEST}, - {FTDM_CPC_PAYPHONE, CAT_PAYPHONE}, -}; - -ftdm2trillium_t bc_cap_codes[] = { - {FTDM_BEARER_CAP_SPEECH, ITC_SPEECH}, /* speech as per ATIS-1000113.3.2005 */ - {FTDM_BEARER_CAP_UNRESTRICTED, ITC_UNRDIG}, /* unrestricted digital as per ATIS-1000113.3.2005 */ - {FTDM_BEARER_CAP_RESTRICTED, ITC_UNRDIG}, /* Restricted Digital */ - {FTDM_BEARER_CAP_3_1KHZ_AUDIO, ITC_A31KHZ}, /* 3.1kHz audio as per ATIS-1000113.3.2005 */ - {FTDM_BEARER_CAP_7KHZ_AUDIO, ITC_A7KHZ}, /* 7Khz audio */ - {FTDM_BEARER_CAP_15KHZ_AUDIO, ITC_A15KHZ}, /* 15Khz audio */ - {FTDM_BEARER_CAP_VIDEO, ITC_VIDEO}, /* Video */ -}; - -static uint8_t get_trillium_val(ftdm2trillium_t *vals, uint8_t ftdm_val, uint8_t default_val) -{ - ftdm2trillium_t *val = vals; - while(val++) { - if (val->ftdm_val == ftdm_val) { - return val->trillium_val; - } - } - return default_val; -} - -static uint8_t get_ftdm_val(ftdm2trillium_t *vals, uint8_t trillium_val, uint8_t default_val) -{ - ftdm2trillium_t *val = vals; - while(val++) { - if (val->trillium_val == trillium_val) { - return val->ftdm_val; - } - } - return default_val; -} - -ftdm_status_t copy_cgPtyNum_from_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *cgPtyNum) -{ - return FTDM_SUCCESS; -} - -ftdm_status_t copy_cgPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *cgPtyNum) -{ - const char *val = NULL; - const char *clg_nadi = NULL; - - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - - cgPtyNum->eh.pres = PRSNT_NODEF; - - cgPtyNum->natAddrInd.pres = PRSNT_NODEF; - cgPtyNum->natAddrInd.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].clg_nadi; - - - cgPtyNum->scrnInd.pres = PRSNT_NODEF; - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_screen_ind"); - if (!ftdm_strlen_zero(val)) { - cgPtyNum->scrnInd.val = atoi(val); - } else { - cgPtyNum->scrnInd.val = caller_data->screen; - } - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Calling Party Number Screening Ind %d\n", cgPtyNum->scrnInd.val); - - cgPtyNum->presRest.pres = PRSNT_NODEF; - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_pres_ind"); - if (!ftdm_strlen_zero(val)) { - cgPtyNum->presRest.val = atoi(val); - } else { - cgPtyNum->presRest.val = caller_data->pres; - } - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Calling Party Number Presentation Ind %d\n", cgPtyNum->presRest.val); - - cgPtyNum->numPlan.pres = PRSNT_NODEF; - cgPtyNum->numPlan.val = 0x01; - - cgPtyNum->niInd.pres = PRSNT_NODEF; - cgPtyNum->niInd.val = 0x00; - - /* check if the user would like a custom NADI value for the calling Pty Num */ - clg_nadi = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_clg_nadi"); - if (!ftdm_strlen_zero(clg_nadi)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Calling NADI value \"%s\"\n", clg_nadi); - cgPtyNum->natAddrInd.val = atoi(clg_nadi); - } - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Calling Party Number NADI value %d\n", cgPtyNum->natAddrInd.val); - - return copy_tknStr_to_sngss7(caller_data->cid_num.digits, &cgPtyNum->addrSig, &cgPtyNum->oddEven); -} - -ftdm_status_t copy_cdPtyNum_from_sngss7(ftdm_channel_t *ftdmchan, SiCdPtyNum *cdPtyNum) -{ - char var[FTDM_DIGITS_LIMIT]; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - if (cdPtyNum->eh.pres == PRSNT_NODEF && - cdPtyNum->natAddrInd.pres == PRSNT_NODEF) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Called Party Number NADI %d\n", cdPtyNum->natAddrInd.val); - sprintf(var, "%d", cdPtyNum->natAddrInd.val); - sngss7_add_var(sngss7_info, "ss7_cld_nadi", var); - } - - return FTDM_SUCCESS; -} - - -ftdm_status_t copy_cdPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCdPtyNum *cdPtyNum) -{ - const char *val = NULL; - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - cdPtyNum->eh.pres = PRSNT_NODEF; - - cdPtyNum->natAddrInd.pres = PRSNT_NODEF; - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_cld_nadi"); - if (!ftdm_strlen_zero(val)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Called NADI value \"%s\"\n", val); - cdPtyNum->natAddrInd.val = atoi(val); - } else { - cdPtyNum->natAddrInd.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].cld_nadi; - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied NADI value found for CLD, using \"%d\"\n", cdPtyNum->natAddrInd.val); - } - - cdPtyNum->numPlan.pres = PRSNT_NODEF; - cdPtyNum->numPlan.val = 0x01; - - cdPtyNum->innInd.pres = PRSNT_NODEF; - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_cld_inn"); - if (!ftdm_strlen_zero(val)) { - cdPtyNum->innInd.val = atoi(val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Called INN value \"%s\"\n", val); - } else { - cdPtyNum->innInd.val = 0x01; - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Called INN value, set to default value 0x01\n"); - } - - return copy_tknStr_to_sngss7(caller_data->dnis.digits, &cdPtyNum->addrSig, &cdPtyNum->oddEven); -} - -ftdm_status_t copy_locPtyNum_from_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *locPtyNum) -{ - return FTDM_SUCCESS; -} - -ftdm_status_t copy_locPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *locPtyNum) -{ - const char *val = NULL; - const char *loc_nadi = NULL; - int pres_val = PRSNT_NODEF; - - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - - if (!strcasecmp(caller_data->loc.digits, "NULL")) { - pres_val = NOTPRSNT; - return FTDM_SUCCESS; - } - - locPtyNum->eh.pres = pres_val; - locPtyNum->natAddrInd.pres = pres_val; - locPtyNum->natAddrInd.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].loc_nadi; - - locPtyNum->scrnInd.pres = pres_val; - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_loc_screen_ind"); - if (!ftdm_strlen_zero(val)) { - locPtyNum->scrnInd.val = atoi(val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Location Screening Ind %d\n", locPtyNum->scrnInd.val); - } else { - locPtyNum->scrnInd.val = caller_data->screen; - } - - locPtyNum->presRest.pres = pres_val; - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_loc_pres_ind"); - if (!ftdm_strlen_zero(val)) { - locPtyNum->presRest.val = atoi(val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Location Presentation Ind %d\n", locPtyNum->presRest.val); - } else { - locPtyNum->presRest.val = caller_data->pres; - } - - locPtyNum->numPlan.pres = pres_val; - locPtyNum->numPlan.val = 0x01; - - locPtyNum->niInd.pres = pres_val; - locPtyNum->niInd.val = 0x00; - - /* check if the user would like a custom NADI value for the Location Reference */ - loc_nadi = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_loc_nadi"); - if (!ftdm_strlen_zero(loc_nadi)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Location Reference NADI value \"%s\"\n", loc_nadi); - locPtyNum->natAddrInd.val = atoi(loc_nadi); - } else { - locPtyNum->natAddrInd.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].loc_nadi; - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied NADI value found for LOC, using \"%d\"\n", locPtyNum->natAddrInd.val); - } - - return copy_tknStr_to_sngss7(caller_data->loc.digits, &locPtyNum->addrSig, &locPtyNum->oddEven); -} - -ftdm_status_t copy_genNmb_to_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb) -{ - const char *val = NULL; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_gn_digits"); - if (!ftdm_strlen_zero(val)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Generic Number qualifier \"%s\"\n", val); - if (copy_tknStr_to_sngss7((char*)val, &genNmb->addrSig, &genNmb->oddEven) != FTDM_SUCCESS) { - return FTDM_FAIL; - } - } else { - return FTDM_SUCCESS; - } - - genNmb->eh.pres = PRSNT_NODEF; - genNmb->addrSig.pres = PRSNT_NODEF; - - genNmb->nmbQual.pres = PRSNT_NODEF; - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_gn_numqual"); - if (!ftdm_strlen_zero(val)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Generic Number \"%s\"\n", val); - genNmb->nmbQual.val = atoi(val); - } else { - genNmb->nmbQual.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].gn_nmbqual; - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Generic Number \n"); - } - genNmb->natAddrInd.pres = PRSNT_NODEF; - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_gn_nadi"); - if (!ftdm_strlen_zero(val)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Generic Number \"nature of address\" \"%s\"\n", val); - genNmb->natAddrInd.val = atoi(val); - } else { - genNmb->natAddrInd.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].gn_nadi; - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Generic Number \"nature of address\" \"%d\"\n", genNmb->natAddrInd.val); - } - genNmb->scrnInd.pres = PRSNT_NODEF; - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_gn_screen_ind"); - if (!ftdm_strlen_zero(val)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Generic Number \"screening indicator\" \"%s\"\n", val); - genNmb->scrnInd.val = atoi(val); - } else { - genNmb->natAddrInd.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].gn_screen_ind; - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Generic Number \"screening indicator\" \"%d\"\n", genNmb->natAddrInd.val); - } - genNmb->presRest.pres = PRSNT_NODEF; - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_gn_pres_ind"); - if (!ftdm_strlen_zero(val)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Generic Number \"presentation indicator\" \"%s\"\n", val); - genNmb->presRest.val = atoi(val); - } else { - genNmb->presRest.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].gn_pres_ind; - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Generic Number \"presentation indicator\" \"%d\"\n", genNmb->presRest.val); - } - genNmb->numPlan.pres = PRSNT_NODEF; - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_gn_npi"); - if (!ftdm_strlen_zero(val)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Generic Number \"numbering plan\" \"%s\"\n", val); - genNmb->numPlan.val = atoi(val); - } else { - genNmb->numPlan.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].gn_npi; - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Generic Number \"numbering plan\" \"%d\"\n", genNmb->numPlan.val); - } - genNmb->niInd.pres = PRSNT_NODEF; - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_gn_num_inc_ind"); - if (!ftdm_strlen_zero(val)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Generic Number \"number incomplete indicator\" \"%s\"\n", val); - genNmb->niInd.val = atoi(val); - } else { - genNmb->niInd.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].gn_num_inc_ind; - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Generic Number \"number incomplete indicator\" \"%d\"\n", genNmb->niInd.val); - } - return FTDM_SUCCESS; -} - -ftdm_status_t copy_genNmb_from_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb) -{ - char val[64]; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - memset(val, 0, sizeof(val)); - - if (genNmb->eh.pres != PRSNT_NODEF || genNmb->addrSig.pres != PRSNT_NODEF) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No Generic Number available\n"); - return FTDM_SUCCESS; - } - - copy_tknStr_from_sngss7(genNmb->addrSig, val, genNmb->oddEven); - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generic Number:%s\n", val); - sngss7_add_var(sngss7_info, "ss7_gn_digits", val); - - if (genNmb->nmbQual.pres == PRSNT_NODEF) { - snprintf(val, sizeof(val), "%d", genNmb->nmbQual.val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generic Number \"number qualifier\" \"%s\"\n", val); - sngss7_add_var(sngss7_info, "ss7_gn_numqual", val); - } - - if (genNmb->natAddrInd.pres == PRSNT_NODEF) { - snprintf(val, sizeof(val), "%d", genNmb->natAddrInd.val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generic Number \"nature of address\" \"%s\"\n", val); - sngss7_add_var(sngss7_info, "ss7_gn_nadi", val); - } - - if (genNmb->scrnInd.pres == PRSNT_NODEF) { - snprintf(val, sizeof(val), "%d", genNmb->scrnInd.val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generic Number \"screening indicator\" \"%s\"\n", val); - sngss7_add_var(sngss7_info, "ss7_gn_screen_ind", val); - } - - if (genNmb->presRest.pres == PRSNT_NODEF) { - snprintf(val, sizeof(val), "%d", genNmb->presRest.val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generic Number \"presentation indicator\" \"%s\"\n", val); - sngss7_add_var(sngss7_info, "ss7_gn_pres_ind", val); - } - - if (genNmb->numPlan.pres == PRSNT_NODEF) { - snprintf(val, sizeof(val), "%d", genNmb->numPlan.val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generic Number \"numbering plan\" \"%s\"\n", val); - sngss7_add_var(sngss7_info, "ss7_gn_npi", val); - } - - if (genNmb->niInd.pres == PRSNT_NODEF) { - snprintf(val, sizeof(val), "%d", genNmb->niInd.val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generic Number \"number incomplete indicator\" \"%s\"\n", val); - sngss7_add_var(sngss7_info, "ss7_gn_num_inc_ind", val); - } - - return FTDM_SUCCESS; -} - -ftdm_status_t copy_redirgNum_to_sngss7(ftdm_channel_t *ftdmchan, SiRedirNum *redirgNum) -{ - const char* val = NULL; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdnis_digits"); - if (!ftdm_strlen_zero(val)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Redirection Number\"%s\"\n", val); - if (copy_tknStr_to_sngss7((char*)val, &redirgNum->addrSig, &redirgNum->oddEven) != FTDM_SUCCESS) { - return FTDM_FAIL; - } - } else if (!ftdm_strlen_zero(caller_data->rdnis.digits)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Redirection Number\"%s\"\n", caller_data->rdnis.digits); - if (copy_tknStr_to_sngss7(caller_data->rdnis.digits, &redirgNum->addrSig, &redirgNum->oddEven) != FTDM_SUCCESS) { - return FTDM_FAIL; - } - } else { - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdnis_pres_ind"); - if (!ftdm_strlen_zero(val)) { - redirgNum->presRest.val = atoi(val); - } - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number Address Presentation Restricted Ind:%d\n", redirgNum->presRest.val); - - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Redirection Number\n"); - return FTDM_SUCCESS; - } - - redirgNum->eh.pres = PRSNT_NODEF; - - /* Nature of address indicator */ - redirgNum->natAddr.pres = PRSNT_NODEF; - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdnis_nadi"); - if (!ftdm_strlen_zero(val)) { - redirgNum->natAddr.val = atoi(val); - } else { - redirgNum->natAddr.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].rdnis_nadi; - } - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number NADI:%d\n", redirgNum->natAddr.val); - - /* Screening indicator */ - redirgNum->scrInd.pres = PRSNT_NODEF; - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdnis_screen_ind"); - if (!ftdm_strlen_zero(val)) { - redirgNum->scrInd.val = atoi(val); - } else { - redirgNum->scrInd.val = FTDM_SCREENING_VERIFIED_PASSED; - } - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number Screening Ind:%d\n", redirgNum->scrInd.val); - - /* Address presentation restricted ind */ - redirgNum->presRest.pres = PRSNT_NODEF; - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdnis_pres_ind"); - if (!ftdm_strlen_zero(val)) { - redirgNum->presRest.val = atoi(val); - } else { - redirgNum->presRest.val = FTDM_PRES_ALLOWED; - } - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number Address Presentation Restricted Ind:%d\n", redirgNum->presRest.val); - - /* Numbering plan */ - redirgNum->numPlan.pres = PRSNT_NODEF; - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdnis_plan"); - if (!ftdm_strlen_zero(val)) { - redirgNum->numPlan.val = atoi(val); - } else { - redirgNum->numPlan.val = caller_data->rdnis.plan; - } - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number Numbering plan:%d\n", redirgNum->numPlan.val); - - return copy_tknStr_to_sngss7(caller_data->rdnis.digits, &redirgNum->addrSig, &redirgNum->oddEven); -} - -ftdm_status_t copy_redirgNum_from_sngss7(ftdm_channel_t *ftdmchan, SiRedirNum *redirgNum) -{ - char val[20]; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - - if (redirgNum->eh.pres != PRSNT_NODEF || redirgNum->addrSig.pres != PRSNT_NODEF) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No Redirecting Number available\n"); - return FTDM_SUCCESS; - } - - copy_tknStr_from_sngss7(redirgNum->addrSig, ftdmchan->caller_data.rdnis.digits, redirgNum->oddEven); - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number:%s\n", ftdmchan->caller_data.rdnis.digits); - snprintf(val, sizeof(val), "%s", ftdmchan->caller_data.rdnis.digits); - sngss7_add_var(sngss7_info, "ss7_rdnis_digits", val); - - - if (redirgNum->natAddr.pres == PRSNT_NODEF) { - snprintf(val, sizeof(val), "%d", redirgNum->natAddr.val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number NADI:%s\n", val); - sngss7_add_var(sngss7_info, "ss7_rdnis_nadi", val); - caller_data->rdnis.type = redirgNum->natAddr.val; - } - - if (redirgNum->scrInd.pres == PRSNT_NODEF) { - snprintf(val, sizeof(val), "%d", redirgNum->scrInd.val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number Screening Ind:%s\n", val); - sngss7_add_var(sngss7_info, "ss7_rdnis_screen_ind", val); - } - - if (redirgNum->presRest.pres == PRSNT_NODEF) { - snprintf(val, sizeof(val), "%d", redirgNum->presRest.val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number Presentation Ind:%s\n", val); - sngss7_add_var(sngss7_info, "ss7_rdnis_pres_ind", val); - } - - if (redirgNum->numPlan.pres == PRSNT_NODEF) { - snprintf(val, sizeof(val), "%d", redirgNum->numPlan.val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number Numbering plan:%s\n", val); - sngss7_add_var(sngss7_info, "ss7_rdnis_plan", val); - caller_data->rdnis.plan = redirgNum->numPlan.val; - } - - return FTDM_SUCCESS; -} - -ftdm_status_t copy_redirgInfo_from_sngss7(ftdm_channel_t *ftdmchan, SiRedirInfo *redirInfo) -{ - char val[20]; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - if (redirInfo->eh.pres != PRSNT_NODEF ) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No Redirecting Information available\n"); - return FTDM_SUCCESS; - } - - - if (redirInfo->redirInd.pres == PRSNT_NODEF) { - snprintf(val, sizeof(val), "%d", redirInfo->redirInd.val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirection Information - redirection indicator:%s\n", val); - sngss7_add_var(sngss7_info, "ss7_rdinfo_indicator", val); - } - - if (redirInfo->origRedirReas.pres == PRSNT_NODEF) { - snprintf(val, sizeof(val), "%d", redirInfo->origRedirReas.val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirection Information - original redirection reason:%s\n", val); - sngss7_add_var(sngss7_info, "ss7_rdinfo_orig", val); - } - - if (redirInfo->redirCnt.pres == PRSNT_NODEF) { - snprintf(val, sizeof(val), "%d", redirInfo->redirCnt.val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirection Information - redirection count:%s\n", val); - sngss7_add_var(sngss7_info, "ss7_rdinfo_count", val); - } - - if (redirInfo->redirReas.pres == PRSNT_NODEF) { - snprintf(val, sizeof(val), "%d", redirInfo->redirReas.val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirection Information - redirection reason:%s\n", val); - sngss7_add_var(sngss7_info, "ss7_rdinfo_reason", val); - } - - return FTDM_SUCCESS; -} - -ftdm_status_t copy_redirgInfo_to_sngss7(ftdm_channel_t *ftdmchan, SiRedirInfo *redirInfo) -{ - const char* val = NULL; - int bProceed = 0; - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdinfo_indicator"); - if (!ftdm_strlen_zero(val)) { - redirInfo->redirInd.val = atoi(val); - redirInfo->redirInd.pres = 1; - bProceed = 1; - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Redirection Information on Redirection Indicator\n"); - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdinfo_orig"); - if (!ftdm_strlen_zero(val)) { - redirInfo->origRedirReas.val = atoi(val); - redirInfo->origRedirReas.pres = 1; - bProceed = 1; - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Redirection Information on Original Reasons\n"); - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdinfo_count"); - if (!ftdm_strlen_zero(val)) { - redirInfo->redirCnt.val = atoi(val); - redirInfo->redirCnt.pres= 1; - bProceed = 1; - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Redirection Information on Redirection Count\n"); - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdinfo_reason"); - if (!ftdm_strlen_zero(val)) { - redirInfo->redirReas.val = atoi(val); - redirInfo->redirReas.pres = 1; - bProceed = 1; - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Redirection Information on Redirection Reasons\n"); - } - - if( bProceed == 1 ) { - redirInfo->eh.pres = PRSNT_NODEF; - } else { - redirInfo->eh.pres = NOTPRSNT; - } - - return FTDM_SUCCESS; -} - -ftdm_status_t copy_access_transport_from_sngss7(ftdm_channel_t *ftdmchan, SiAccTrnspt *accTrnspt) -{ - char val[3*((MF_SIZE_TKNSTRE + 7) & 0xff8)]; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - if (accTrnspt->eh.pres != PRSNT_NODEF || accTrnspt->infoElmts.pres !=PRSNT_NODEF) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No Access Transport IE available\n"); - return FTDM_SUCCESS; - } - - ftdm_url_encode((const char*)accTrnspt->infoElmts.val, val, accTrnspt->infoElmts.len); - sngss7_add_var (sngss7_info, "ss7_access_transport_urlenc", val); - - return FTDM_SUCCESS; -} -ftdm_status_t copy_access_transport_to_sngss7(ftdm_channel_t *ftdmchan, SiAccTrnspt *accTrnspt) -{ - const char *val = NULL; - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_access_transport_urlenc"); - if (ftdm_strlen_zero(val)) { - accTrnspt->eh.pres = NOTPRSNT; - accTrnspt->infoElmts.pres = NOTPRSNT; - } - else { - char *val_dec = NULL; - int val_len = strlen (val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found Access Transport IE encoded : %s\n", val); - - accTrnspt->eh.pres = PRSNT_NODEF; - accTrnspt->infoElmts.pres = PRSNT_NODEF; - - val_dec = ftdm_strdup(val); - ftdm_url_decode(val_dec, (ftdm_size_t*)&val_len); - memcpy (accTrnspt->infoElmts.val, val_dec, val_len); - accTrnspt->infoElmts.len = val_len; - ftdm_safe_free(val_dec); - } - return FTDM_SUCCESS; -} - -ftdm_status_t copy_ocn_from_sngss7(ftdm_channel_t *ftdmchan, SiOrigCdNum *origCdNum) -{ - char val[20]; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - if (origCdNum->eh.pres != PRSNT_NODEF ) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No Original Called Number available\n"); - return FTDM_SUCCESS; - } - - if (origCdNum->addrSig.pres == PRSNT_NODEF) { - copy_tknStr_from_sngss7(origCdNum->addrSig, val, origCdNum->oddEven); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Original Called Number - Digits: %s\n", val); - sngss7_add_var(sngss7_info, "ss7_ocn", val); - } - - if (origCdNum->natAddr.pres == PRSNT_NODEF) { - snprintf(val, sizeof(val), "%d", origCdNum->natAddr.val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Original Called Number - NADI: %s\n", val); - sngss7_add_var(sngss7_info, "ss7_ocn_nadi", val); - } - - if (origCdNum->numPlan.pres == PRSNT_NODEF) { - snprintf(val, sizeof(val), "%d", origCdNum->numPlan.val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Original Called Number - Plan: %s\n", val); - sngss7_add_var(sngss7_info, "ss7_ocn_plan", val); - } - - if (origCdNum->presRest.pres == PRSNT_NODEF) { - snprintf(val, sizeof(val), "%d", origCdNum->presRest.val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Original Called Number - Presentation: %s\n", val); - sngss7_add_var(sngss7_info, "ss7_ocn_pres", val); - } - - return FTDM_SUCCESS; -} - -ftdm_status_t copy_ocn_to_sngss7(ftdm_channel_t *ftdmchan, SiOrigCdNum *origCdNum) -{ - const char *val = NULL; - int bProceed = 0; - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_ocn"); - if (!ftdm_strlen_zero(val)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Original Called Number - Digits: %s\n", val); - if (copy_tknStr_to_sngss7((char*)val, &origCdNum->addrSig, &origCdNum->oddEven) != FTDM_SUCCESS) { - return FTDM_FAIL; - } - origCdNum->addrSig.pres = 1; - } else { - return FTDM_SUCCESS; - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_ocn_nadi"); - if (!ftdm_strlen_zero(val)) { - origCdNum->natAddr.val = atoi(val); - origCdNum->natAddr.pres = 1; - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Original Called Number - NADI: %s\n", val); - bProceed = 1; - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Original Called Number NADI value\n"); - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_ocn_plan"); - if (!ftdm_strlen_zero(val)) { - origCdNum->numPlan.val = atoi(val); - origCdNum->numPlan.pres = 1; - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Original Called Number - Plan: %s\n", val); - bProceed = 1; - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Original Called Number Plan value\n"); - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_ocn_pres"); - if (!ftdm_strlen_zero(val)) { - origCdNum->presRest.val = atoi(val); - origCdNum->presRest.pres = 1; - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Original Called Number - Presentation: %s\n", val); - bProceed = 1; - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Original Called Number Presentation value\n"); - } - - if( bProceed == 1 ) { - origCdNum->eh.pres = PRSNT_NODEF; - } else { - origCdNum->eh.pres = NOTPRSNT; - } - - return FTDM_SUCCESS; -} - -ftdm_status_t copy_cgPtyCat_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyCat *cgPtyCat) -{ - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - - cgPtyCat->eh.pres = PRSNT_NODEF; - cgPtyCat->cgPtyCat.pres = PRSNT_NODEF; - - cgPtyCat->cgPtyCat.val = get_trillium_val(cpc_codes, caller_data->cpc, CAT_ORD); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Calling Party Category:0x%x\n",cgPtyCat->cgPtyCat.val); - return FTDM_SUCCESS; -} - -ftdm_status_t copy_cgPtyCat_from_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyCat *cgPtyCat) -{ - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - - if (cgPtyCat->eh.pres == PRSNT_NODEF && - cgPtyCat->cgPtyCat.pres == PRSNT_NODEF) { - - caller_data->cpc = get_ftdm_val(cpc_codes, cgPtyCat->cgPtyCat.val, FTDM_CPC_UNKNOWN); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Calling Party Category:0x%x\n", cgPtyCat->cgPtyCat.val); - } - return FTDM_SUCCESS; -} - - -ftdm_status_t copy_accTrnspt_to_sngss7(ftdm_channel_t *ftdmchan, SiAccTrnspt *accTrnspt) -{ - const char *clg_subAddr = NULL; - const char *cld_subAddr = NULL; - char subAddrIE[MAX_SIZEOF_SUBADDR_IE]; - - /* check if the user would like us to send a clg_sub-address */ - clg_subAddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_clg_subaddr"); - if (!ftdm_strlen_zero(clg_subAddr)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Calling Sub-Address value \"%s\"\n", clg_subAddr); - - /* clean out the subAddrIE */ - memset(subAddrIE, 0x0, sizeof(subAddrIE)); - - /* check the first character in the sub-address to see what type of encoding to use */ - switch (clg_subAddr[0]) { - case '0': /* NSAP */ - encode_subAddrIE_nsap(&clg_subAddr[1], subAddrIE, SNG_CALLING); - break; - case '1': /* national variant */ - encode_subAddrIE_nat(&clg_subAddr[1], subAddrIE, SNG_CALLING); - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Invalid Calling Sub-Address encoding requested: %c\n", clg_subAddr[0]); - break; - } /* switch (cld_subAddr[0]) */ - - - /* if subaddIE is still empty don't copy it in */ - if (subAddrIE[0] != '0') { - /* check if the clg_subAddr has already been added */ - if (accTrnspt->eh.pres == PRSNT_NODEF) { - /* append the subAddrIE */ - memcpy(&accTrnspt->infoElmts.val[accTrnspt->infoElmts.len], subAddrIE, (subAddrIE[1] + 2)); - accTrnspt->infoElmts.len = accTrnspt->infoElmts.len +subAddrIE[1] + 2; - } else { - /* fill in from the beginning */ - accTrnspt->eh.pres = PRSNT_NODEF; - accTrnspt->infoElmts.pres = PRSNT_NODEF; - memcpy(accTrnspt->infoElmts.val, subAddrIE, (subAddrIE[1] + 2)); - accTrnspt->infoElmts.len = subAddrIE[1] + 2; - } - } - } - - /* check if the user would like us to send a cld_sub-address */ - cld_subAddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_cld_subaddr"); - if ((cld_subAddr != NULL) && (*cld_subAddr)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Called Sub-Address value \"%s\"\n", cld_subAddr); - - /* clean out the subAddrIE */ - memset(subAddrIE, 0x0, sizeof(subAddrIE)); - - /* check the first character in the sub-address to see what type of encoding to use */ - switch (cld_subAddr[0]) { - case '0': /* NSAP */ - encode_subAddrIE_nsap(&cld_subAddr[1], subAddrIE, SNG_CALLED); - break; - case '1': /* national variant */ - encode_subAddrIE_nat(&cld_subAddr[1], subAddrIE, SNG_CALLED); - break; - default: - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Invalid Called Sub-Address encoding requested: %c\n", cld_subAddr[0]); - break; - } /* switch (cld_subAddr[0]) */ - - /* if subaddIE is still empty don't copy it in */ - if (subAddrIE[0] != '0') { - /* check if the cld_subAddr has already been added */ - if (accTrnspt->eh.pres == PRSNT_NODEF) { - /* append the subAddrIE */ - memcpy(&accTrnspt->infoElmts.val[accTrnspt->infoElmts.len], subAddrIE, (subAddrIE[1] + 2)); - accTrnspt->infoElmts.len = accTrnspt->infoElmts.len +subAddrIE[1] + 2; - } else { - /* fill in from the beginning */ - accTrnspt->eh.pres = PRSNT_NODEF; - accTrnspt->infoElmts.pres = PRSNT_NODEF; - memcpy(accTrnspt->infoElmts.val, subAddrIE, (subAddrIE[1] + 2)); - accTrnspt->infoElmts.len = subAddrIE[1] + 2; - } - } - } /* if ((cld_subAddr != NULL) && (*cld_subAddr)) */ - return FTDM_SUCCESS; -} - -ftdm_status_t copy_natConInd_to_sngss7(ftdm_channel_t *ftdmchan, SiNatConInd *natConInd) -{ - /* copy down the nature of connection indicators */ - natConInd->eh.pres = PRSNT_NODEF; - natConInd->satInd.pres = PRSNT_NODEF; - natConInd->satInd.val = 0; /* no satellite circuit */ - natConInd->contChkInd.pres = PRSNT_NODEF; - natConInd->contChkInd.val = CONTCHK_NOTREQ; - natConInd->echoCntrlDevInd.pres = PRSNT_NODEF; - natConInd->echoCntrlDevInd.val = ECHOCDEV_INCL; - return FTDM_SUCCESS; -} - -ftdm_status_t four_char_to_hex(const char* in, uint16_t* out) -{ - int i= 4; - char a, b, c, d; - if (!in || 4>strlen(in)) { - return FTDM_FAIL; - } - while(i) - { - switch((char)*(in+(4-i))) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (i==4) { - d = *(in+(4-i)) - 48; - } else if (i==3) { - c = *(in+(4-i)) - 48; - } else if (i==2) { - b = *(in+(4-i)) - 48; - } else { - a = *(in+(4-i)) - 48; - } - break; - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - if (i==4) { - d = *(in+(4-i)) - 55; - } else if (i==3) { - c = *(in+(4-i)) - 55; - } else if (i==2) { - b = *(in+(4-i)) - 55; - } else { - a = *(in+(4-i)) - 55; - } - break; - case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - if (i==4) { - d = *(in+(4-i)) - 87; - } else if (i==3) { - c = *(in+(4-i)) - 87; - } else if (i==2) { - b = *(in+(4-i)) - 87; - } else { - a = *(in+(4-i)) - 87; - } - break; - default: - SS7_ERROR("Invalid character found when decoding hex string, %c!\n", *(in+(4-i)) ); - break; - } - i--; - }; - - *out |= d; - *out = *out<<4; - *out |= c; - *out = *out<<4; - *out |= b; - *out = *out<<4; - *out |= a; - - return FTDM_SUCCESS; -} - -ftdm_status_t char_to_hex(const char* in, uint16_t* out, int len) -{ - int i= len; - char *val = ftdm_malloc(len*sizeof(char)); - - if (!val ||!in || len>strlen(in)) { - return FTDM_FAIL; - } - - while(i) - { - switch((char)*(in+(len-i))) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - *(val+(len-i)) = *(in+(len-i)) - 48; - break; - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - *(val+(len-i)) = *(in+(len-i)) - 55; - break; - case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - *(val+(len-i)) = *(in+(len-i)) - 87; - break; - default: - SS7_ERROR("Invalid character found when decoding hex string, %c!\n", *(in+(len-i)) ); - break; - } - i--; - }; - - for (i=0; i<=len-1; i++) { - *out = *out << 4; - *out |= *(val+i); - } - - return FTDM_SUCCESS; -} - - - -ftdm_status_t hex_to_char(uint16_t in, char* out, int len) -{ - char val=0; - int mask = 0xf; - int i=0; - if (!out) { - return FTDM_SUCCESS; - } - - for (i=len-1; i>=0; i--) { - val = (in & (mask<<(4*i))) >> (4*i); - sprintf (out+(len-1-i), "%x", val); - } - - return FTDM_SUCCESS; -} -ftdm_status_t hex_to_four_char(uint16_t in, char* out) -{ - char val=0; - int mask = 0xf; - int i=0; - if (!out) { - return FTDM_SUCCESS; - } - - for (i=3; i>=0; i--) { - val = (in & (mask<<(4*i))) >> (4*i); - sprintf (out+(3-i), "%x", val); - } - - return FTDM_SUCCESS; -} - -ftdm_status_t copy_NatureOfConnection_to_sngss7(ftdm_channel_t *ftdmchan, SiNatConInd *natConInd) -{ - const char *val = NULL; - - natConInd->eh.pres = PRSNT_NODEF; - natConInd->satInd.pres = PRSNT_NODEF; - natConInd->contChkInd.pres = PRSNT_NODEF;; - natConInd->echoCntrlDevInd.pres = PRSNT_NODEF; - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_nature_connection_hex"); - if (!ftdm_strlen_zero(val)) { - uint16_t val_hex = 0; - if (char_to_hex (val, &val_hex, 2) == FTDM_FAIL) { - SS7_ERROR ("Wrong value set in ss7_iam_nature_connection_hex variable. Please correct the error. Setting to default values.\n" ); - } else { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "hex = 0x%x\n", val_hex); - natConInd->satInd.val = (val_hex & 0x3); - natConInd->contChkInd.val = (val_hex & 0xc)>>2; - natConInd->echoCntrlDevInd.val = (val_hex & 0x10) >> 4; - - return FTDM_SUCCESS; - } - } - - natConInd->satInd.val = 0; - natConInd->contChkInd.val = 0; - natConInd->echoCntrlDevInd.val = 0; - - return FTDM_SUCCESS; -} - -ftdm_status_t copy_NatureOfConnection_from_sngss7(ftdm_channel_t *ftdmchan, SiNatConInd *natConInd ) -{ - char val[3]; - uint16_t val_hex = 0; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - memset (val, 0, 3*sizeof(char)); - if (natConInd->eh.pres != PRSNT_NODEF ) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No nature of connection indicator IE available\n"); - return FTDM_SUCCESS; - } - - val_hex |= natConInd->satInd.val; - val_hex |= natConInd->contChkInd.val << 2; - val_hex |= natConInd->echoCntrlDevInd.val <<4; - hex_to_char(val_hex, val, 2) ; - - sngss7_add_var(sngss7_info, "ss7_iam_nature_connection_hex", val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Nature of connection indicator Hex: 0x%s\n", val); - - return FTDM_SUCCESS; -} - -ftdm_status_t copy_fwdCallInd_hex_from_sngss7(ftdm_channel_t *ftdmchan, SiFwdCallInd *fwdCallInd) -{ - char val[5]; - uint16_t val_hex = 0; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - memset (val, 0, 5*sizeof(char)); - if (fwdCallInd->eh.pres != PRSNT_NODEF ) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No forward call indicator IE available\n"); - return FTDM_SUCCESS; - } - - val_hex |= fwdCallInd->natIntCallInd.val << 8; - val_hex |= (fwdCallInd->end2EndMethInd.val & 0x1) << 9; - val_hex |= ((fwdCallInd->end2EndMethInd.val & 0x2)>>1) << 10; - val_hex |= fwdCallInd->intInd.val << 11; - val_hex |= fwdCallInd->end2EndInfoInd.val << 12; - val_hex |= fwdCallInd->isdnUsrPrtInd.val << 13; - val_hex |= (fwdCallInd->isdnUsrPrtPrfInd.val & 0x1) << 14; - val_hex |= ((fwdCallInd->isdnUsrPrtPrfInd.val & 0x2)>>1) << 15; - - val_hex |= fwdCallInd->isdnAccInd.val; - hex_to_four_char(val_hex, val) ; - - sngss7_add_var(sngss7_info, "ss7_iam_fwd_ind_hex", val); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Forwad Call Indicator Hex: 0x%s\n", val); - - return FTDM_SUCCESS; -} - -ftdm_status_t copy_fwdCallInd_to_sngss7(ftdm_channel_t *ftdmchan, SiFwdCallInd *fwdCallInd) -{ - const char *val = NULL; - int acc_val = ISDNACC_ISDN; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - fwdCallInd->eh.pres = PRSNT_NODEF; - fwdCallInd->natIntCallInd.pres = PRSNT_NODEF; - fwdCallInd->end2EndMethInd.pres = PRSNT_NODEF; - fwdCallInd->intInd.pres = PRSNT_NODEF; - fwdCallInd->end2EndInfoInd.pres = PRSNT_NODEF; - fwdCallInd->isdnUsrPrtInd.pres = PRSNT_NODEF; - fwdCallInd->isdnUsrPrtPrfInd.pres = PRSNT_NODEF; - fwdCallInd->isdnAccInd.pres = PRSNT_NODEF; - fwdCallInd->sccpMethInd.pres = PRSNT_NODEF; - fwdCallInd->sccpMethInd.val = SCCPMTH_NOIND; - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_fwd_ind_hex"); - if (!ftdm_strlen_zero(val)) { - uint16_t val_hex = 0; - if (four_char_to_hex (val, &val_hex) == FTDM_FAIL) { - SS7_ERROR ("Wrong value set in iam_fwd_ind_HEX variable. Please correct the error. Setting to default values.\n" ); - } else { - fwdCallInd->natIntCallInd.val = (val_hex & 0x100)>>8; - fwdCallInd->end2EndMethInd.val = (val_hex & 0x600)>>9; - fwdCallInd->intInd.val = (val_hex & 0x800)>>11; - fwdCallInd->end2EndInfoInd.val = (val_hex & 0x1000)>>12; - fwdCallInd->isdnUsrPrtInd.val = (val_hex & 0x2000)>>13; - fwdCallInd->isdnUsrPrtPrfInd.val = (val_hex & 0xC000)>>14; - fwdCallInd->isdnUsrPrtPrfInd.val = (fwdCallInd->isdnUsrPrtPrfInd.val==0x03)?0x0:fwdCallInd->isdnUsrPrtPrfInd.val; - fwdCallInd->isdnAccInd.val = val_hex & 0x1; - - if ((g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS88) || - (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS92) || - (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS95)) { - - /* include only if we're running ANSI */ - fwdCallInd->transCallNInd.pres = PRSNT_NODEF; - fwdCallInd->transCallNInd.val = 0x0; - } - - return FTDM_SUCCESS; - } - } - - fwdCallInd->natIntCallInd.val = 0x00; - fwdCallInd->end2EndMethInd.val = E2EMTH_NOMETH; - fwdCallInd->intInd.val = INTIND_NOINTW; - fwdCallInd->end2EndInfoInd.val = E2EINF_NOINFO; - fwdCallInd->isdnUsrPrtInd.val = ISUP_USED; - fwdCallInd->isdnUsrPrtPrfInd.val = PREF_PREFAW; - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_fwd_ind_isdn_access_ind"); - if (ftdm_strlen_zero(val)) { - /* Kept for backward compatibility */ - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "iam_fwd_ind_isdn_access_ind"); - } - - if (!ftdm_strlen_zero(val)) { - acc_val = (int)atoi(val); - } - - fwdCallInd->isdnAccInd.val = acc_val; - - if ((g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS88) || - (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS92) || - (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS95)) { - - /* include only if we're running ANSI */ - fwdCallInd->transCallNInd.pres = PRSNT_NODEF; - fwdCallInd->transCallNInd.val = 0x0; - } - - return FTDM_SUCCESS; -} - -ftdm_status_t copy_txMedReq_to_sngss7(ftdm_channel_t *ftdmchan, SiTxMedReq *txMedReq) -{ - txMedReq->eh.pres = PRSNT_NODEF; - txMedReq->trMedReq.pres = PRSNT_NODEF; - txMedReq->trMedReq.val = ftdmchan->caller_data.bearer_capability; - - return FTDM_SUCCESS; -} - -ftdm_status_t copy_usrServInfoA_to_sngss7(ftdm_channel_t *ftdmchan, SiUsrServInfo *usrServInfoA) -{ - int bProceed = 0; - const char *val = NULL; - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_trans_cap"); - if (!ftdm_strlen_zero(val)) { - int itc_type = 0; - if (!strcasecmp(val, "SPEECH")) { - itc_type = ITC_SPEECH; - } else if (!strcasecmp(val, "UNRESTRICTED")) { - itc_type = ITC_UNRDIG; - } else if (!strcasecmp(val, "RESTRICTED")) { - itc_type = ITC_RESDIG; - } else if (!strcasecmp(val, "31KHZ")) { - itc_type = ITC_A31KHZ; - } else if (!strcasecmp(val, "7KHZ")) { - itc_type = ITC_A7KHZ; - } else if (!strcasecmp(val, "15KHZ")) { - itc_type = ITC_A15KHZ; - } else if (!strcasecmp(val, "VIDEO")) { - itc_type = ITC_VIDEO; - } else { - itc_type = ITC_SPEECH; - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI transmission capability parameter is wrong : %s. Setting to default SPEECH. \n", val ); - } - - usrServInfoA->infoTranCap.pres = PRSNT_NODEF; - usrServInfoA->infoTranCap.val = get_trillium_val(bc_cap_codes, ftdmchan->caller_data.bearer_capability, itc_type); - bProceed = 1; - } else { - usrServInfoA->infoTranCap.pres = NOTPRSNT; - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_code_standard"); - if (!ftdm_strlen_zero(val)) { - usrServInfoA->cdeStand.pres = PRSNT_NODEF; - usrServInfoA->cdeStand.val = (int)atoi(val); /* default is 0x0 */ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI coding standard = %d\n", usrServInfoA->cdeStand.val ); - bProceed = 1; - } else { - usrServInfoA->cdeStand.pres = NOTPRSNT; - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_trans_mode"); - if (!ftdm_strlen_zero(val)) { - usrServInfoA->tranMode.pres = PRSNT_NODEF; - usrServInfoA->tranMode.val = (int)atoi(val); /* transfer mode, default is 0x0*/ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI transfer mode = %d\n", usrServInfoA->tranMode.val ); - bProceed = 1; - } else { - usrServInfoA->tranMode.pres = NOTPRSNT; - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_trans_rate_0"); - if (!ftdm_strlen_zero(val)) { - usrServInfoA->infoTranRate0.pres = PRSNT_NODEF; - usrServInfoA->infoTranRate0.val = (int)atoi(val); /* default is 0x10, 64kbps origination to destination*/ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI trans rate 0 = %d\n", usrServInfoA->infoTranRate0.val ); - bProceed = 1; - } else { - usrServInfoA->infoTranRate0.pres = NOTPRSNT; - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_trans_rate_1"); - if (!ftdm_strlen_zero(val)) { - usrServInfoA->infoTranRate1.pres = PRSNT_NODEF; - usrServInfoA->infoTranRate1.val = (int)atoi(val); /* 64kbps destination to origination, default is 0x10 */ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI trans rate 1 = %d\n", usrServInfoA->infoTranRate1.val ); - bProceed = 1; - } else { - usrServInfoA->infoTranRate1.pres = NOTPRSNT; - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_layer1_ident"); - if (!ftdm_strlen_zero(val)) { - usrServInfoA->lyr1Ident.pres = PRSNT_NODEF; - usrServInfoA->lyr1Ident.val = (int)atoi(val); /*default value is 0x01 */ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI layer 1 indentification = %d\n", usrServInfoA->lyr1Ident.val ); - bProceed = 1; - } else { - usrServInfoA->lyr1Ident.pres = NOTPRSNT; - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_layer1_prot"); - if (!ftdm_strlen_zero(val)) { - usrServInfoA->usrInfLyr1Prot.pres = PRSNT_NODEF; - usrServInfoA->usrInfLyr1Prot.val = (int)atoi(val); /*default value is 0x02 */ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI layer 1 protocol = %d\n", usrServInfoA->usrInfLyr1Prot.val ); - bProceed = 1; - } else { - usrServInfoA->usrInfLyr1Prot.pres = NOTPRSNT; - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_layer2_ident"); - if (!ftdm_strlen_zero(val)) { - usrServInfoA->lyr2Ident.pres = PRSNT_NODEF; - usrServInfoA->lyr2Ident.val = (int)atoi(val); /*default value is 0x01 */ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI layer 2 indentification = %d\n", usrServInfoA->lyr2Ident.val ); - bProceed = 1; - } else { - usrServInfoA->lyr2Ident.pres = NOTPRSNT; - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_layer2_prot"); - if (!ftdm_strlen_zero(val)) { - usrServInfoA->usrInfLyr2Prot.pres = PRSNT_NODEF; - usrServInfoA->usrInfLyr2Prot.val = (int)atoi(val); /*default value is 0x02 */ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI layer 2 protocol = %d\n", usrServInfoA->usrInfLyr2Prot.val ); - bProceed = 1; - } else { - usrServInfoA->usrInfLyr2Prot.pres = NOTPRSNT; - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_layer3_ident"); - if (!ftdm_strlen_zero(val)) { - usrServInfoA->lyr3Ident.pres = PRSNT_NODEF; - usrServInfoA->lyr3Ident.val = (int)atoi(val); /*default value is 0x01 */ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI layer 3 indentification = %d\n", usrServInfoA->lyr3Ident.val ); - bProceed = 1; - } else { - usrServInfoA->lyr3Ident.pres = NOTPRSNT; - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_layer3_prot"); - if (!ftdm_strlen_zero(val)) { - usrServInfoA->usrInfLyr3Prot.pres = PRSNT_NODEF; - usrServInfoA->usrInfLyr3Prot.val = (int)atoi(val); /*default value is 0x02 */ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI layer 3 protocol = %d\n", usrServInfoA->usrInfLyr3Prot.val ); - bProceed = 1; - } else { - usrServInfoA->usrInfLyr3Prot.pres = NOTPRSNT; - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_chan_struct"); - if (!ftdm_strlen_zero(val)) { - usrServInfoA->chanStruct.pres = PRSNT_NODEF; - usrServInfoA->chanStruct.val = (int)atoi(val); /* default value is 0x1, 8kHz integrity */ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI channel structure = %d\n", usrServInfoA->chanStruct.val ); - bProceed = 1; - } else { - usrServInfoA->chanStruct.pres = NOTPRSNT; - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_config"); - if (!ftdm_strlen_zero(val)) { - usrServInfoA->config.pres = PRSNT_NODEF; - usrServInfoA->config.val = (int)atoi(val); /* default value is 0x0, point to point configuration */ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI configuration = %d\n", usrServInfoA->config.val ); - bProceed = 1; - } else { - usrServInfoA->config.pres = NOTPRSNT; - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_establish"); - if (!ftdm_strlen_zero(val)) { - usrServInfoA->establish.pres = PRSNT_NODEF; - usrServInfoA->establish.val = (int)atoi(val); /* default value is 0x0, on demand */ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI establishment = %d\n", usrServInfoA->establish.val ); - bProceed = 1; - } else { - usrServInfoA->establish.pres = NOTPRSNT; - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_symmetry"); - if (!ftdm_strlen_zero(val)) { - usrServInfoA->symmetry.pres = PRSNT_NODEF; - usrServInfoA->symmetry.val = (int)atoi(val); /* default value is 0x0, bi-directional symmetric */ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI symmetry = %d\n", usrServInfoA->symmetry.val ); - bProceed = 1; - } else { - usrServInfoA->symmetry.pres = NOTPRSNT; - } - - val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_rate_multiplier"); - if (!ftdm_strlen_zero(val)) { - usrServInfoA->rateMultiplier.pres = PRSNT_NODEF; - usrServInfoA->rateMultiplier.val = (int)atoi(val); /* default value is 0x1, 1x rate multipler */ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI rate multipier = %d\n", usrServInfoA->rateMultiplier.val ); - bProceed = 1; - } else { - usrServInfoA->rateMultiplier.pres = NOTPRSNT; - } - - if (bProceed) { - usrServInfoA->eh.pres = PRSNT_NODEF; - } else { - usrServInfoA->eh.pres = NOTPRSNT; - } - - return FTDM_SUCCESS; -} - - - -ftdm_status_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven) -{ - uint8_t i; - uint8_t j; - - /* check if the token string is present */ - if (str.pres == 1) { - j = 0; - - for (i = 0; i < str.len; i++) { - sprintf(&ftdm[j], "%X", (str.val[i] & 0x0F)); - j++; - sprintf(&ftdm[j], "%X", ((str.val[i] & 0xF0) >> 4)); - j++; - } - - /* if the odd flag is up the last digit is a fake "0" */ - if ((oddEven.pres == 1) && (oddEven.val == 1)) { - ftdm[j-1] = '\0'; - } else { - ftdm[j] = '\0'; - } - - - } else { - SS7_ERROR("Asked to copy tknStr that is not present!\n"); - return FTDM_FAIL; - } - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t append_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven) -{ - int i = 0; - int j = 0; - - /* check if the token string is present */ - if (str.pres == 1) { - /* find the length of the digits so far */ - j = strlen(ftdm); - - /* confirm that we found an acceptable length */ - if ( j > 25 ) { - SS7_ERROR("string length exceeds maxium value...aborting append!\n"); - return FTDM_FAIL; - } /* if ( j > 25 ) */ - - /* copy in digits */ - for (i = 0; i < str.len; i++) { - /* convert 4 bit integer to char and copy into lower nibblet*/ - sprintf(&ftdm[j], "%X", (str.val[i] & 0x0F)); - /* move along */ - j++; - /* convert 4 bit integer to char and copy into upper nibblet */ - sprintf(&ftdm[j], "%X", ((str.val[i] & 0xF0) >> 4)); - /* move along */ - j++; - } /* for (i = 0; i < str.len; i++) */ - - /* if the odd flag is up the last digit is a fake "0" */ - if ((oddEven.pres == 1) && (oddEven.val == 1)) { - ftdm[j-1] = '\0'; - } else { - ftdm[j] = '\0'; - } /* if ((oddEven.pres == 1) && (oddEven.val == 1)) */ - } else { - SS7_ERROR("Asked to copy tknStr that is not present!\n"); - return FTDM_FAIL; - } /* if (str.pres == 1) */ - - return FTDM_SUCCESS; -} - - -ftdm_status_t copy_tknStr_to_sngss7(char* val, TknStr *tknStr, TknU8 *oddEven) -{ - char tmp[2]; - int k = 0; - int j = 0; - uint8_t flag = 0; - uint8_t odd = 0; - - uint8_t lower = 0x0; - uint8_t upper = 0x0; - - tknStr->pres = PRSNT_NODEF; - - /* atoi will search through memory starting from the pointer it is given until - * it finds the \0...since tmp is on the stack it will start going through the - * possibly causing corruption. Hard code a \0 to prevent this - */ - tmp[1] = '\0'; - - while (1) { - /* grab a digit from the ftdm digits */ - tmp[0] = val[k]; - - /* check if the digit is a number and that is not null */ - while (!(isxdigit(tmp[0])) && (tmp[0] != '\0')) { - if (tmp[0] == '*') { - /* Could not find a spec that specifies this , but on customer system, * was transmitted as 0x0b */ - SS7_DEBUG("Replacing * with 0x0b"); - k++; - tmp[0] = 0x0b; - } else { - SS7_INFO("Dropping invalid digit: %c\n", tmp[0]); - /* move on to the next value */ - k++; - tmp[0] = val[k]; - } - } /* while(!(isdigit(tmp))) */ - - /* check if tmp is null or a digit */ - if (tmp[0] != '\0') { - /* push it into the lower nibble */ - lower = strtol(&tmp[0], (char **)NULL, 16); - /* move to the next digit */ - k++; - /* grab a digit from the ftdm digits */ - tmp[0] = val[k]; - - /* check if the digit is a number and that is not null */ - while (!(isxdigit(tmp[0])) && (tmp[0] != '\0')) { - SS7_INFO("Dropping invalid digit: %c\n", tmp[0]); - k++; - tmp[0] = val[k]; - } /* while(!(isdigit(tmp))) */ - - /* check if tmp is null or a digit */ - if (tmp[0] != '\0') { - /* push the digit into the upper nibble */ - upper = (strtol(&tmp[0], (char **)NULL, 16)) << 4; - } else { - /* there is no upper ... fill in 0 */ - upper = 0x0; - /* throw the odd flag */ - odd = 1; - /* throw the end flag */ - flag = 1; - } /* if (tmp != '\0') */ - } else { - /* keep the odd flag down */ - odd = 0; - /* break right away since we don't need to write the digits */ - break; - } - - /* push the digits into the trillium structure */ - tknStr->val[j] = upper | lower; - - /* increment the trillium pointer */ - j++; - - /* if the flag is up we're through all the digits */ - if (flag) break; - - /* move to the next digit */ - k++; - } /* while(1) */ - - tknStr->len = j; - oddEven->pres = PRSNT_NODEF; - oddEven->val = odd; - return FTDM_SUCCESS; -} - - - -/******************************************************************************/ -int check_for_state_change(ftdm_channel_t *ftdmchan) -{ - - /* check to see if there are any pending state changes on the channel and give them a sec to happen*/ - ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 500); - - /* check the flag to confirm it is clear now */ - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - /* the flag is still up...so we have a problem */ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "FTDM_CHANNEL_STATE_CHANGE flag set for over 500ms, channel state = %s\n", - ftdm_channel_state2str (ftdmchan->state)); - - return 1; - } - - return 0; -} - -/******************************************************************************/ -ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan) -{ - if (!g_ftdm_sngss7_data.cfg.isupCkt[circuit].obj) { - SS7_ERROR("No ss7 info for circuit #%d\n", circuit); - return FTDM_FAIL; - } - - *sngss7_info = g_ftdm_sngss7_data.cfg.isupCkt[circuit].obj; - - if (!(*sngss7_info)->ftdmchan) { - SS7_ERROR("No ftdmchan for circuit #%d\n", circuit); - return FTDM_FAIL; - } - - if (!(*sngss7_info)->ftdmchan->span) { - SS7_CRITICAL("ftdmchan->span = NULL for circuit #%d\n",circuit); - return FTDM_FAIL; - - } - if (!(*sngss7_info)->ftdmchan->span->signal_data) { - SS7_CRITICAL("ftdmchan->span->signal_data = NULL for circuit #%d\n",circuit); - return FTDM_FAIL; - - } - - *ftdmchan = (*sngss7_info)->ftdmchan; - return FTDM_SUCCESS; -} - -/******************************************************************************/ -int check_for_reset(sngss7_chan_data_t *sngss7_info) -{ - - if (sngss7_test_ckt_flag(sngss7_info,FLAG_RESET_RX)) { - return 1; - } - - if (sngss7_test_ckt_flag(sngss7_info,FLAG_RESET_TX)) { - return 1; - } - - if (sngss7_test_ckt_flag(sngss7_info,FLAG_GRP_RESET_RX)) { - return 1; - } - - if (sngss7_test_ckt_flag(sngss7_info,FLAG_GRP_RESET_TX)) { - return 1; - } - - return 0; - -} - -/******************************************************************************/ -unsigned long get_unique_id(void) -{ - int procId = sng_get_procId(); - - /* id values are between (procId * 1,000,000) and ((procId + 1) * 1,000,000) */ - if (sngss7_id < ((procId + 1) * 1000000) ) { - sngss7_id++; - } else { - sngss7_id = procId * 1000000; - } - - return(sngss7_id); -} - -/******************************************************************************/ -ftdm_status_t check_if_rx_grs_started(ftdm_span_t *ftdmspan) -{ - ftdm_iterator_t *iter = NULL; - ftdm_iterator_t *curr = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_chan_data_t *sngss7_info = NULL; - sngss7_chan_data_t *cinfo = NULL; - int i = 0; - - iter = ftdm_span_get_chan_iterator(ftdmspan, NULL); - for (curr = iter; curr; curr = ftdm_iterator_next(curr)) { - ftdm_channel_t *fchan = ftdm_iterator_current(curr); - - ftdm_channel_lock(fchan); - - cinfo = fchan->call_data; - - if (!cinfo->rx_grs.range) { - ftdm_channel_unlock(fchan); - continue; - } - - SS7_INFO("Rx GRS (%d:%d)\n", - g_ftdm_sngss7_data.cfg.isupCkt[cinfo->rx_grs.circuit].cic, - (g_ftdm_sngss7_data.cfg.isupCkt[cinfo->rx_grs.circuit].cic + cinfo->rx_grs.range)); - - for (i = cinfo->rx_grs.circuit; i < (cinfo->rx_grs.circuit + cinfo->rx_grs.range + 1); i++) { - - /* confirm this is a voice channel, otherwise we do nothing */ - if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) { - continue; - } - - /* extract the channel in question */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); - continue; - } - - /* check if the GRP_RESET_RX flag is already up */ - if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX)) { - /* we have already processed this channel...move along */ - continue; - } - - /* lock the channel */ - ftdm_channel_lock(ftdmchan); - - /* clear up any pending state changes */ - while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_sangoma_ss7_process_state_change (ftdmchan); - } - - /* flag the channel as having received a reset */ - sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX); - - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_RESTART: - - /* go to idle so that we can redo the restart state*/ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE); - - break; - /**************************************************************************/ - default: - - /* set the state of the channel to restart...the rest is done by the chan monitor */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - break; - /**************************************************************************/ - } - - /* unlock the channel again before we exit */ - ftdm_channel_unlock(ftdmchan); - - } - - ftdm_channel_unlock(fchan); - } - - ftdm_iterator_free(iter); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan) -{ - ftdm_iterator_t *iter = NULL; - ftdm_iterator_t *curr = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_chan_data_t *sngss7_info = NULL; - sngss7_chan_data_t *cinfo = NULL; - int i = 0, bn = 0; - int byte = 0, bit = 0; - int cic_start = 0, cic_end = 0, num_cics = 0; - ftdm_bitmap_t *lockmap = 0; - ftdm_size_t mapsize = 0; - - iter = ftdm_span_get_chan_iterator(ftdmspan, NULL); - for (curr = iter; curr; curr = ftdm_iterator_next(curr)) { - ftdm_channel_t *fchan = ftdm_iterator_current(curr); - - ftdm_channel_lock(fchan); - - cinfo = fchan->call_data; - - if (!cinfo->rx_grs.range) { - - ftdm_channel_unlock(fchan); - - continue; - } - - cic_start = cinfo->rx_grs.circuit; - cic_end = cinfo->rx_grs.circuit + cinfo->rx_grs.range; - num_cics = cinfo->rx_grs.range + 1; - mapsize = (num_cics / FTDM_BITMAP_NBITS) + 1; - - lockmap = ftdm_calloc(mapsize, sizeof(*lockmap)); - if (!lockmap) { - ftdm_channel_unlock(fchan); - return FTDM_ENOMEM; - } - - /* check all the circuits in the range to see if they are done resetting */ - for (i = cic_start, bn = 0; i <= cic_end; i++, bn++) { - - /* confirm this is a voice channel, otherwise we do nothing */ - if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) { - continue; - } - - /* extract the channel in question */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); - ftdm_assert(FTDM_FALSE, "Failed to extract channel data during GRS\n"); - continue; - } - - /* lock the channel */ - ftdm_channel_lock(ftdmchan); - ftdm_map_set_bit(lockmap, bn); - - /* check if there is a state change pending on the channel */ - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - /* check the state to the GRP_RESET_RX_DN flag */ - if (!sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) { - /* this channel is still resetting...do nothing */ - goto GRS_UNLOCK_ALL; - } /* if (!sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) */ - } else { - /* state change pending */ - goto GRS_UNLOCK_ALL; - } - - } - - SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n", cinfo->rx_grs.circuit, cinfo->rx_grs.range); - for (i = cic_start; i <= cic_end; i++) { - - /* confirm this is a voice channel, otherwise we do nothing */ - if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) { - continue; - } - - /* extract the channel in question */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n",i); - ftdm_assert(FTDM_FALSE, "Failed to extract channel data during GRS\n"); - continue; - } - - /* throw the GRP reset flag complete flag */ - sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT); - - /* move the channel to the down state */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - - /* update the status map if the ckt is in blocked state */ - if ((sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) || - (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) || - (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) || - (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) { - - cinfo->rx_grs.status[byte] = (cinfo->rx_grs.status[byte] | (1 << bit)); - } - - /* update the bit and byte counter*/ - bit ++; - if (bit == 8) { - byte++; - bit = 0; - } - - } -GRS_UNLOCK_ALL: - for (i = cic_start, bn = 0; i <= cic_end; i++, bn++) { - /* confirm this is a voice channel, otherwise we do nothing */ - if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) { - continue; - } - - /* extract the channel in question */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); - ftdm_assert(FTDM_FALSE, "Failed to extract channel data during GRS\n"); - continue; - } - if (ftdm_map_test_bit(lockmap, bn)) { - /* unlock the channel */ - ftdm_channel_unlock(ftdmchan); - ftdm_map_clear_bit(lockmap, bn); - } - } - - ftdm_safe_free(lockmap); - - ftdm_channel_unlock(fchan); - } - - ftdm_iterator_free(iter); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t check_if_rx_gra_started(ftdm_span_t *ftdmspan) -{ - ftdm_iterator_t *iter = NULL; - ftdm_iterator_t *curr = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_chan_data_t *sngss7_info = NULL; - sngss7_chan_data_t *cinfo = NULL; - int i = 0; - - iter = ftdm_span_get_chan_iterator(ftdmspan, NULL); - - for (curr = iter; curr; curr = ftdm_iterator_next(curr)) { - ftdm_channel_t *fchan = ftdm_iterator_current(curr); - ftdm_channel_lock(fchan); - - cinfo = fchan->call_data; - - if (!cinfo->rx_gra.range) { - - ftdm_channel_unlock(fchan); - - continue; - } - - SS7_INFO("Rx GRA (%d:%d)\n", - g_ftdm_sngss7_data.cfg.isupCkt[cinfo->rx_gra.circuit].cic, - (g_ftdm_sngss7_data.cfg.isupCkt[cinfo->rx_gra.circuit].cic + cinfo->rx_gra.range)); - - for (i = cinfo->rx_gra.circuit; i < (cinfo->rx_gra.circuit + cinfo->rx_gra.range + 1); i++) { - - /* confirm this is a voice channel, otherwise we do nothing */ - if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) { - continue; - } - - /* extract the channel in question */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); - continue; - } - - /* check if the channel is already processing the GRA */ - if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) { - /* move along */ - continue; - } - - /* lock the channel */ - ftdm_channel_lock(ftdmchan); - - /* clear up any pending state changes */ - while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_sangoma_ss7_process_state_change (ftdmchan); - } - - switch (ftdmchan->state) { - /**********************************************************************/ - case FTDM_CHANNEL_STATE_RESTART: - - /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */ - sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP); - - /* go to DOWN */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - - break; - /**********************************************************************/ - case FTDM_CHANNEL_STATE_DOWN: - - /* do nothing, just drop the message */ - SS7_DEBUG("Receveived GRA in down state, dropping\n"); - - break; - /**********************************************************************/ - case FTDM_CHANNEL_STATE_TERMINATING: - case FTDM_CHANNEL_STATE_HANGUP: - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - - /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */ - sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP); - - break; - /**********************************************************************/ - default: - /* ITU Q764-2.9.5.1.c -> release the circuit */ - if (cinfo->rx_gra.cause != 0) { - ftdmchan->caller_data.hangup_cause = cinfo->rx_gra.cause; - } else { - ftdmchan->caller_data.hangup_cause = 98; /* Message not compatiable with call state */ - } - - /* go to terminating to hang up the call */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - break; - /**********************************************************************/ - } - - ftdm_channel_unlock(ftdmchan); - } - - ftdm_channel_unlock(fchan); - } - - ftdm_iterator_free(iter); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan) -{ - ftdm_channel_t *ftdmchan = NULL; - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_sigmsg_t sigev; - int x; - - for (x = 1; x < (ftdmspan->chan_count + 1); x++) { - - /* extract the channel structure and sngss7 channel data */ - ftdmchan = ftdmspan->channels[x]; - - /* if the call data is NULL move on */ - if (ftdmchan->call_data == NULL) continue; - - sngss7_info = ftdmchan->call_data; - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - memset (&sigev, 0, sizeof (sigev)); - - sigev.chan_id = ftdmchan->chan_id; - sigev.span_id = ftdmchan->span_id; - sigev.channel = ftdmchan; - - /* if we have the PAUSED flag and the sig status is still UP */ - if ((sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_PAUSED)) && - (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP))) { - - /* clear up any pending state changes */ - while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_sangoma_ss7_process_state_change (ftdmchan); - } - - /* throw the channel into SUSPENDED to process the flag */ - /* after doing this once the sig status will be down */ - ftdm_set_state (ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - } - - /* if the RESUME flag is up go to SUSPENDED to process the flag */ - /* after doing this the flag will be cleared */ - if (sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_RESUME)) { - - /* clear up any pending state changes */ - while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_sangoma_ss7_process_state_change (ftdmchan); - } - - /* got SUSPENDED state to clear the flag */ - ftdm_set_state (ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - } - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - - } /* for (x = 1; x < (span->chan_count + 1); x++) */ - - /* signal the core that sig events are queued for processing */ - ftdm_span_trigger_signals(ftdmspan); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t process_span_ucic(ftdm_span_t *ftdmspan) -{ - ftdm_iterator_t *iter = NULL; - ftdm_iterator_t *curr = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_chan_data_t *sngss7_info = NULL; - sngss7_chan_data_t *cinfo = NULL; - sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data; - int i = 0; - - iter = ftdm_span_get_chan_iterator(ftdmspan, NULL); - curr = iter; - for (curr = iter; curr; curr = ftdm_iterator_next(curr)) { - ftdm_channel_t *fchan = ftdm_iterator_current(curr); - - ftdm_channel_lock(fchan); - - cinfo = fchan->call_data; - - if (!cinfo->ucic.range) { - - ftdm_channel_unlock(fchan); - - continue; - } - - for (i = cinfo->ucic.circuit; i < (cinfo->ucic.circuit + cinfo->ucic.range + 1); i++) { - - /* extract the channel in question */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); - continue; - } - - /* lock the channel */ - ftdm_channel_lock(ftdmchan); - - SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx Span UCIC\n", sngss7_info->circuit->cic); - - /* clear up any pending state changes */ - while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_sangoma_ss7_process_state_change (ftdmchan); - } - - /* throw the ckt block flag */ - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK); - - /* set the channel to suspended state */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* unlock the channel again before we exit */ - ftdm_channel_unlock(ftdmchan); - } - /* clear out the ucic data since we're done with it */ - memset(&cinfo->ucic, 0, sizeof(cinfo->ucic)); - - ftdm_channel_unlock(fchan); - } - - ftdm_clear_flag(sngss7_span, SNGSS7_UCIC_PENDING); - - ftdm_iterator_free(iter); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t clear_rx_grs_flags(sngss7_chan_data_t *sngss7_info) -{ - /* clear all the flags related to an incoming GRS */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX); - sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN); - sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t clear_rx_grs_data(sngss7_chan_data_t *sngss7_info) -{ - ftdm_iterator_t *iter = NULL; - ftdm_iterator_t *curr = NULL; - sngss7_chan_data_t *cinfo = NULL; - ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan; - sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmchan->span->signal_data; - - memset(&sngss7_info->rx_grs, 0, sizeof(sngss7_info->rx_grs)); - - iter = ftdm_span_get_chan_iterator(ftdmchan->span, NULL); - curr = iter; - for (curr = iter; curr; curr = ftdm_iterator_next(curr)) { - ftdm_channel_t *fchan = ftdm_iterator_current(curr); - - ftdm_channel_lock(fchan); - - cinfo = fchan->call_data; - if (cinfo->rx_grs.range) { - /* there is still another grs pending, do not clear the SNGSS7_RX_GRS_PENDING flag yet */ - ftdm_channel_unlock(fchan); - goto done; - } - - ftdm_channel_unlock(fchan); - } - - /* if we're here is because there is no other grs going on now in this span */ - ftdm_clear_flag(sngss7_span, SNGSS7_RX_GRS_PENDING); - -done: - ftdm_iterator_free(iter); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t clear_rx_gra_data(sngss7_chan_data_t *sngss7_info) -{ - ftdm_iterator_t *iter = NULL; - ftdm_iterator_t *curr = NULL; - sngss7_chan_data_t *cinfo = NULL; - ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan; - sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data; - - /* clear the rx_grs data fields */ - memset(&sngss7_info->rx_gra, 0, sizeof(sngss7_info->rx_gra)); - - iter = ftdm_span_get_chan_iterator(ftdmchan->span, NULL); - curr = iter; - for (curr = iter; curr; curr = ftdm_iterator_next(curr)) { - ftdm_channel_t *fchan = ftdm_iterator_current(curr); - - ftdm_channel_lock(fchan); - - cinfo = fchan->call_data; - if (cinfo->rx_gra.range) { - /* there is still another gra pending, do not clear the SNGSS7_RX_GRA_PENDING flag yet */ - ftdm_channel_unlock(fchan); - goto done; - } - - ftdm_channel_unlock(fchan); - } - - /* if we're here is because there is no other gra pending in this span */ - ftdm_clear_flag(sngss7_span, SNGSS7_RX_GRA_PENDING); - -done: - - ftdm_iterator_free(iter); - - return FTDM_SUCCESS; -} -/******************************************************************************/ -ftdm_status_t clear_tx_grs_flags(sngss7_chan_data_t *sngss7_info) -{ - /* clear all the flags related to an outgoing GRS */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_BASE); - sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX); - sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_SENT); - sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t clear_tx_grs_data(sngss7_chan_data_t *sngss7_info) -{ - /* clear everything up */ - memset(&sngss7_info->tx_grs, 0, sizeof(sngss7_info->tx_grs)); - return FTDM_SUCCESS; -} - -/******************************************************************************/ - -/******************************************************************************/ -ftdm_status_t clear_rx_rsc_flags(sngss7_chan_data_t *sngss7_info) -{ - /* clear all the flags related to an incoming RSC */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_RESET_RX); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t clear_tx_rsc_flags(sngss7_chan_data_t *sngss7_info) -{ - /* clear all the flags related to an outgoing RSC */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_RESET_TX); - sngss7_clear_ckt_flag(sngss7_info, FLAG_RESET_SENT); - sngss7_clear_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t encode_subAddrIE_nsap(const char *subAddr, char *subAddrIE, int type) -{ - /* Q931 4.5.9 - * 8 7 6 5 4 3 2 1 (octet) - * - * 0 1 1 1 0 0 0 1 (spare 8) ( IE id 1-7) - * X X X X X X X X (length of IE contents) - * 1 0 0 0 Z 0 0 0 (ext 8) (NSAP type 5-7) (odd/even 4) (spare 1-3) - * X X X X X X X X (sub address encoded in ia5) - */ - - int x = 0; - int p = 0; - int len = 0; - char tmp[2]; - - /* initalize the second element of tmp to \0 so that atoi doesn't go to far */ - tmp[1]='\0'; - - /* set octet 1 aka IE id */ - p = 0; - switch(type) { - /**************************************************************************/ - case SNG_CALLED: /* called party sub address */ - subAddrIE[p] = 0x71; - break; - /**************************************************************************/ - case SNG_CALLING: /* calling party sub address */ - subAddrIE[p] = 0x6d; - break; - /**************************************************************************/ - default: /* not good */ - SS7_ERROR("Sub-Address type is invalid: %d\n", type); - return FTDM_FAIL; - break; - /**************************************************************************/ - } /* switch(type) */ - - /* set octet 3 aka type and o/e */ - p = 2; - subAddrIE[p] = 0x80; - - /* set the subAddrIE pointer octet 4 */ - p = 3; - - /* loop through all digits in subAddr and insert them into subAddrIE */ - while (subAddr[x] != '\0') { - - /* grab a character */ - tmp[0] = subAddr[x]; - - /* confirm it is a digit */ - if (!isdigit(tmp[0])) { - SS7_INFO("Dropping invalid digit: %c\n", tmp[0]); - /* move to the next character in subAddr */ - x++; - - /* restart the loop */ - continue; - } - - /* convert the character to IA5 encoding and write into subAddrIE */ - subAddrIE[p] = atoi(&tmp[0]); /* lower nibble is the digit */ - subAddrIE[p] |= 0x3 << 4; /* upper nibble is 0x3 */ - - /* increment address length counter */ - len++; - - /* increment the subAddrIE pointer */ - p++; - - /* move to the next character in subAddr */ - x++; - - } /* while (subAddr[x] != '\0') */ - - /* set octet 2 aka length of subaddr */ - p = 1; - subAddrIE[p] = len + 1; - - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int type) -{ - /* Q931 4.5.9 - * 8 7 6 5 4 3 2 1 (octet) - * - * 0 1 1 1 0 0 0 1 (spare 8) ( IE id 1-7) - * X X X X X X X X (length of IE contents) - * 1 0 0 0 Z 0 0 0 (ext 8) (NSAP type 5-7) (odd/even 4) (spare 1-3) - * X X X X X X X X (sub address encoded in ia5) - */ - - int x = 0; - int p = 0; - int len = 0; - char tmp[2]; - int flag = 0; - int odd = 0; - uint8_t lower = 0x0; - uint8_t upper = 0x0; - - /* initalize the second element of tmp to \0 so that atoi doesn't go to far */ - tmp[1]='\0'; - - /* set octet 1 aka IE id */ - p = 0; - switch(type) { - /**************************************************************************/ - case SNG_CALLED: /* called party sub address */ - subAddrIE[p] = 0x71; - break; - /**************************************************************************/ - case SNG_CALLING: /* calling party sub address */ - subAddrIE[p] = 0x6d; - break; - /**************************************************************************/ - default: /* not good */ - SS7_ERROR("Sub-Address type is invalid: %d\n", type); - return FTDM_FAIL; - break; - /**************************************************************************/ - } /* switch(type) */ - - /* set the subAddrIE pointer octet 4 */ - p = 3; - - /* loop through all digits in subAddr and insert them into subAddrIE */ - while (1) { - - /* grab a character */ - tmp[0] = subAddr[x]; - - /* confirm it is a hex digit */ - while ((!isxdigit(tmp[0])) && (tmp[0] != '\0')) { - if (tmp[0] == '*') { - /* Could not find a spec that specifies this, but on customer system, * was transmitted as 0x0b */ - SS7_DEBUG("Replacing * with 0x0b"); - x++; - tmp[0] = 0x0b; - } else { - SS7_INFO("Dropping invalid digit: %c\n", tmp[0]); - /* move to the next character in subAddr */ - x++; - tmp[0] = subAddr[x]; - } - } - - /* check if tmp is null or a digit */ - if (tmp[0] != '\0') { - /* push it into the lower nibble using strtol to allow a-f chars */ - lower = strtol(&tmp[0], (char **)NULL, 16); - /* move to the next digit */ - x++; - /* grab a digit from the ftdm digits */ - tmp[0] = subAddr[x]; - - /* check if the digit is a hex digit and that is not null */ - while (!(isxdigit(tmp[0])) && (tmp[0] != '\0')) { - SS7_INFO("Dropping invalid digit: %c\n", tmp[0]); - x++; - tmp[0] = subAddr[x]; - } /* while(!(isdigit(tmp))) */ - - /* check if tmp is null or a digit */ - if (tmp[0] != '\0') { - /* push the digit into the upper nibble using strtol to allow a-f chars */ - upper = (strtol(&tmp[0], (char **)NULL, 16)) << 4; - } else { - /* there is no upper ... fill in spare */ - upper = 0x00; - /* throw the odd flag since we need to buffer */ - odd = 1; - /* throw the end flag */ - flag = 1; - } /* if (tmp != '\0') */ - } else { - /* keep the odd flag down */ - odd = 0; - - /* throw the flag */ - flag = 1; - - /* bounce out right away */ - break; - } - - /* fill in the octet */ - subAddrIE[p] = upper | lower; - - /* increment address length counter */ - len++; - - /* if the flag is we're through all the digits */ - if (flag) break; - - /* increment the subAddrIE pointer */ - p++; - - /* move to the next character in subAddr */ - x++; - - } /* while (subAddr[x] != '\0') */ - - /* set octet 2 aka length of subaddr */ - p = 1; - subAddrIE[p] = len + 1; - - /* set octet 3 aka type and o/e */ - p = 2; - subAddrIE[p] = 0xa0 | (odd << 3); - - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -int find_mtp2_error_type_in_map(const char *err_type) -{ - int i = 0; - - while (sng_mtp2_error_type_map[i].init == 1) { - /* check if string matches the sng_type name */ - if (!strcasecmp(err_type, sng_mtp2_error_type_map[i].sng_type)) { - /* we've found a match break from the loop */ - break; - } else { - /* move on to the next on */ - i++; - } - } /* while (sng_mtp2_error_type_map[i].init == 1) */ - - /* check how we exited the loop */ - if (sng_mtp2_error_type_map[i].init == 0) { - return -1; - } else { - return i; - } /* if (sng_mtp2_error_type_map[i].init == 0) */ -} - -/******************************************************************************/ -int find_link_type_in_map(const char *linkType) -{ - int i = 0; - - while (sng_link_type_map[i].init == 1) { - /* check if string matches the sng_type name */ - if (!strcasecmp(linkType, sng_link_type_map[i].sng_type)) { - /* we've found a match break from the loop */ - break; - } else { - /* move on to the next on */ - i++; - } - } /* while (sng_link_type_map[i].init == 1) */ - - /* check how we exited the loop */ - if (sng_link_type_map[i].init == 0) { - return -1; - } else { - return i; - } /* if (sng_link_type_map[i].init == 0) */ -} - -/******************************************************************************/ -int find_switch_type_in_map(const char *switchType) -{ - int i = 0; - - while (sng_switch_type_map[i].init == 1) { - /* check if string matches the sng_type name */ - if (!strcasecmp(switchType, sng_switch_type_map[i].sng_type)) { - /* we've found a match break from the loop */ - break; - } else { - /* move on to the next on */ - i++; - } - } /* while (sng_switch_type_map[i].init == 1) */ - - /* check how we exited the loop */ - if (sng_switch_type_map[i].init == 0) { - return -1; - } else { - return i; - } /* if (sng_switch_type_map[i].init == 0) */ -} - -/******************************************************************************/ -int find_ssf_type_in_map(const char *ssfType) -{ - int i = 0; - - while (sng_ssf_type_map[i].init == 1) { - /* check if string matches the sng_type name */ - if (!strcasecmp(ssfType, sng_ssf_type_map[i].sng_type)) { - /* we've found a match break from the loop */ - break; - } else { - /* move on to the next on */ - i++; - } - } /* while (sng_ssf_type_map[i].init == 1) */ - - /* check how we exited the loop */ - if (sng_ssf_type_map[i].init == 0) { - return -1; - } else { - return i; - } /* if (sng_ssf_type_map[i].init == 0) */ -} - -/******************************************************************************/ -int find_cic_cntrl_in_map(const char *cntrlType) -{ - int i = 0; - - while (sng_cic_cntrl_type_map[i].init == 1) { - /* check if string matches the sng_type name */ - if (!strcasecmp(cntrlType, sng_cic_cntrl_type_map[i].sng_type)) { - /* we've found a match break from the loop */ - break; - } else { - /* move on to the next on */ - i++; - } - } /* while (sng_cic_cntrl_type_map[i].init == 1) */ - - /* check how we exited the loop */ - if (sng_cic_cntrl_type_map[i].init == 0) { - return -1; - } else { - return i; - } /* if (sng_cic_cntrl_type_map[i].init == 0) */ -} - -/******************************************************************************/ -ftdm_status_t check_status_of_all_isup_intf(void) -{ - sng_isup_inf_t *sngss7_intf = NULL; - uint8_t status = 0xff; - int x; - - /* go through all the isupIntfs and ask the stack to give their current state */ - x = 1; - for (x = 1; x < (MAX_ISUP_INFS); x++) { - /**************************************************************************/ - - if (g_ftdm_sngss7_data.cfg.isupIntf[x].id == 0) continue; - - sngss7_intf = &g_ftdm_sngss7_data.cfg.isupIntf[x]; - - if (ftmod_ss7_isup_intf_sta(sngss7_intf->id, &status)) { - SS7_ERROR("Failed to get status of ISUP intf %d\n", sngss7_intf->id); - sngss7_set_flag(sngss7_intf, SNGSS7_PAUSED); - continue; - } - - switch (status){ - /**********************************************************************/ - case (SI_INTF_AVAIL): - SS7_DEBUG("State of ISUP intf %d = AVAIL\n", sngss7_intf->id); - - /* check the current state for interface that we know */ - if (sngss7_test_flag(sngss7_intf, SNGSS7_PAUSED)) { - /* we thing the intf is paused...put into resume */ - sngss7_clear_flag(sngss7_intf, SNGSS7_PAUSED); - } else { - /* nothing to since we already know that interface is active */ - } - break; - /**********************************************************************/ - case (SI_INTF_UNAVAIL): - SS7_DEBUG("State of ISUP intf %d = UNAVAIL\n", sngss7_intf->id); - /* check the current state for interface that we know */ - if (sngss7_test_flag(sngss7_intf, SNGSS7_PAUSED)) { - /* nothing to since we already know that interface is active */ - } else { - /* put the interface into pause */ - sngss7_set_flag(sngss7_intf, SNGSS7_PAUSED); - } - break; - /**********************************************************************/ - case (SI_INTF_CONG1): - SS7_DEBUG("State of ISUP intf %d = Congestion 1\n", sngss7_intf->id); - break; - /**********************************************************************/ - case (SI_INTF_CONG2): - SS7_DEBUG("State of ISUP intf %d = Congestion 2\n", sngss7_intf->id); - break; - /**********************************************************************/ - case (SI_INTF_CONG3): - SS7_DEBUG("State of ISUP intf %d = Congestion 3\n", sngss7_intf->id); - break; - /**********************************************************************/ - default: - /* should do something here to handle the possiblity of an unknown case */ - SS7_ERROR("Unknown ISUP intf Status code (%d) for Intf = %d\n", status, sngss7_intf->id); - break; - /**********************************************************************/ - } /* switch (status) */ - - /**************************************************************************/ - } /* for (x = 1; x < MAX_ISUP_INFS); i++) */ - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t sngss7_add_var(sngss7_chan_data_t *sngss7_info, const char* var, const char* val) -{ - char *t_name = 0; - char *t_val = 0; - - /* confirm the user has sent us a value */ - if (!var || !val) { - return FTDM_FAIL; - } - - if (!sngss7_info->variables) { - /* initialize on first use */ - sngss7_info->variables = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); - ftdm_assert_return(sngss7_info->variables, FTDM_FAIL, "Failed to create hash table\n"); - } - - t_name = ftdm_strdup(var); - t_val = ftdm_strdup(val); - - hashtable_insert(sngss7_info->variables, t_name, t_val, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_FLAG_FREE_VALUE); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -ftdm_status_t sngss7_add_raw_data(sngss7_chan_data_t *sngss7_info, uint8_t* data, ftdm_size_t data_len) -{ - ftdm_assert_return(!sngss7_info->raw_data, FTDM_FAIL, "Overwriting existing raw data\n"); - - sngss7_info->raw_data = ftdm_calloc(1, data_len); - ftdm_assert_return(sngss7_info->raw_data, FTDM_FAIL, "Failed to allocate raw data\n"); - - memcpy(sngss7_info->raw_data, data, data_len); - sngss7_info->raw_data_len = data_len; - return FTDM_SUCCESS; -} - -/******************************************************************************/ -void sngss7_send_signal(sngss7_chan_data_t *sngss7_info, ftdm_signal_event_t event_id) -{ - ftdm_sigmsg_t sigev; - ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan; - - memset(&sigev, 0, sizeof(sigev)); - - sigev.chan_id = ftdmchan->chan_id; - sigev.span_id = ftdmchan->span_id; - sigev.channel = ftdmchan; - sigev.event_id = event_id; - - if (sngss7_info->variables) { - /* - * variables now belongs to the ftdm core, and - * will be cleared after sigev is processed by user. Set - * local pointer to NULL so we do not attempt to - * destroy it */ - sigev.variables = sngss7_info->variables; - sngss7_info->variables = NULL; - } - - if (sngss7_info->raw_data) { - /* - * raw_data now belongs to the ftdm core, and - * will be cleared after sigev is processed by user. Set - * local pointer to NULL so we do not attempt to - * destroy it */ - - sigev.raw.data = sngss7_info->raw_data; - sigev.raw.len = sngss7_info->raw_data_len; - - sngss7_info->raw_data = NULL; - sngss7_info->raw_data_len = 0; - } - ftdm_span_send_signal(ftdmchan->span, &sigev); -} - -/******************************************************************************/ -void sngss7_set_sig_status(sngss7_chan_data_t *sngss7_info, ftdm_signaling_status_t status) -{ - ftdm_sigmsg_t sig; - ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan; - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Signalling link status changed to %s\n", - ftdm_signaling_status2str(status)); - - memset(&sig, 0, sizeof(sig)); - - sig.chan_id = ftdmchan->chan_id; - sig.span_id = ftdmchan->span_id; - sig.channel = ftdmchan; - sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sig.ev_data.sigstatus.status = status; - - if (ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to change channel status to %s\n", - ftdm_signaling_status2str(status)); - } - return; -} - -#if 0 -ftdm_status_t check_for_invalid_states(ftdm_channel_t *ftmchan) -{ - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - if (!sngss7_info) { - SS7_WARN_CHAN(ftdmchan, "Found ftdmchan with no sig module data!%s\n", " "); - return FTDM_FAIL; - } - - if (sngss7_test_flag(sngss7_intf, SNGSS7_PAUSED)) { - return FTDM_SUCCESS; - } - - switch (ftdmchan->state) { - case UP: - case DOWN: - return FTDM_SUCCESS; - - default: - if ((ftdm_current_time_in_ms() - ftdmchan->last_state_change_time) > 30000) { - SS7_WARN_CHAN(ftdmchan, "Circuite in state=%s too long - resetting!%s\n", - ftdm_channel_state2str(ftdmchan->state)); - - ftdm_channel_lock(ftdmchan); - - if (sngss7_channel_status_clear(sngss7_info)) { - sngss7_tx_reset_restart(sngss7_info); - - if (ftdmchan->state == FTDM_CHANNEL_STATE_RESTART) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - } else { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - } - } else { - - } - - - - ftdm_channel_unlock(ftdmchan); - } - } - - return FTDM_SUCCESS; -} -#endif - - -/******************************************************************************/ -ftdm_status_t check_for_reconfig_flag(ftdm_span_t *ftdmspan) -{ - ftdm_channel_t *ftdmchan = NULL; - sngss7_chan_data_t *sngss7_info = NULL; - sng_isup_inf_t *sngss7_intf = NULL; - uint8_t state; - uint8_t bits_ab = 0; - uint8_t bits_cd = 0; - uint8_t bits_ef = 0; - int x; - int ret; - ret=0; - - for (x = 1; x < (ftdmspan->chan_count + 1); x++) { - /**************************************************************************/ - /* extract the channel structure and sngss7 channel data */ - ftdmchan = ftdmspan->channels[x]; - - /* if the call data is NULL move on */ - if (ftdmchan->call_data == NULL) { - SS7_WARN_CHAN(ftdmchan, "Found ftdmchan with no sig module data!%s\n", " "); - continue; - } - - /* grab the private data */ - sngss7_info = ftdmchan->call_data; - - /* check the reconfig flag */ - if (sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_RECONFIG)) { - /* confirm the state of all isup interfaces*/ - check_status_of_all_isup_intf(); - - sngss7_intf = &g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId]; - - /* check if the interface is paused or resumed */ - if (sngss7_test_flag(sngss7_intf, SNGSS7_PAUSED)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Circuit set to PAUSED %s\n"," "); - /* throw the pause flag */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_RESUME); - sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_PAUSED); - } else { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Circuit set to RESUMED %s\n"," "); - /* throw the resume flag */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_PAUSED); - sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_RESUME); - } - - /* query for the status of the ckt */ - if (ftmod_ss7_isup_ckt_sta(sngss7_info->circuit->id, &state)) { - /* NC: Circuit statistic failed: does not exist. Must re-configure circuit - Reset the circuit CONFIGURED flag so that RESUME will reconfigure - this circuit. */ - sngss7_info->circuit->flags &= ~SNGSS7_CONFIGURED; - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR,"Failed to read isup ckt = %d status\n", sngss7_info->circuit->id); - continue; - } - - /* extract the bit sections */ - bits_ab = (state & (SNG_BIT_A + SNG_BIT_B)) >> 0; - bits_cd = (state & (SNG_BIT_C + SNG_BIT_D)) >> 2; - bits_ef = (state & (SNG_BIT_E + SNG_BIT_F)) >> 4; - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Circuit state=0x%X ab=0x%X cd=0x%X ef=0x%X\n",state,bits_ab,bits_cd,bits_ef); - - if (bits_cd == 0x0) { - /* check if circuit is UCIC or transient */ - if (bits_ab == 0x3) { - SS7_INFO("ISUP CKT %d re-configuration pending!\n", x); - sngss7_info->circuit->flags &= ~SNGSS7_CONFIGURED; - SS7_STATE_CHANGE(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* NC: The code below should be deleted. Its here for hitorical - reason. The RESUME code will reconfigure the channel since - the CONFIGURED flag has been reset */ -#if 0 - /* bit a and bit b are set, unequipped */ - ret = ftmod_ss7_isup_ckt_config(sngss7_info->circuit->id); - if (ret) { - SS7_CRITICAL("ISUP CKT %d re-configuration FAILED!\n",x); - } else { - SS7_INFO("ISUP CKT %d re-configuration DONE!\n", x); - } - - /* reset the circuit to sync states */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* flag the circuit as active */ - sngss7_set_flag(sngss7_info->circuit, SNGSS7_ACTIVE); - - /* throw the channel into reset */ - sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX); - - /* throw the channel to suspend */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); -#endif - - } else { /* if (bits_ab == 0x3) */ - /* The stack status is not blocked. However this is possible if - the circuit state was UP. So even though Master sent out the BLO - the status command is not showing it. - - As a kudge. We will try to send out an UBL even though the status - indicates that there is no BLO. */ - if (!sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) { - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_UNBLK_TX); - - /* set the channel to suspended state */ - SS7_STATE_CHANGE(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - } - } - } else { - /* check the maintenance block status in bits A and B */ - switch (bits_ab) { - /**************************************************************************/ - case (0): - /* no maintenace block...do nothing */ - break; - /**************************************************************************/ - case (1): - /* The stack status is Blocked. Check if the block was sent - by user via console. If the block was not sent by user then, it - was sent out by Master due to relay down. - Therefore send out the unblock to clear it */ - if (!sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) { - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_UNBLK_TX); - - /* set the channel to suspended state */ - SS7_STATE_CHANGE(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - } - - /* Only locally blocked, thus remove a remote block */ - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN); - - break; - /**************************************************************************/ - case (2): - /* remotely blocked */ - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN); - - /* set the channel to suspended state */ - SS7_STATE_CHANGE(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - break; - /**************************************************************************/ - case (3): - /* both locally and remotely blocked */ - if (!sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) { - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_UNBLK_TX); - } - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN); - - /* set the channel to suspended state */ - SS7_STATE_CHANGE(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - break; - /**************************************************************************/ - default: - break; - /**************************************************************************/ - } /* switch (bits_ab) */ - - /* check the hardware block status in bits e and f */ - switch (bits_ef) { - /**************************************************************************/ - case (0): - /* no maintenace block...do nothing */ - break; - /**************************************************************************/ - case (1): - /* locally blocked */ - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX); - - /* set the channel to suspended state */ - SS7_STATE_CHANGE(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - break; - /**************************************************************************/ - case (2): - /* remotely blocked */ - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX); - - /* set the channel to suspended state */ - SS7_STATE_CHANGE(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - break; - /**************************************************************************/ - case (3): - /* both locally and remotely blocked */ - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX); - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX); - - /* set the channel to suspended state */ - SS7_STATE_CHANGE(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - break; - /**************************************************************************/ - default: - break; - /**************************************************************************/ - } /* switch (bits_ef) */ - } - - /* clear the re-config flag ... no matter what */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_CKT_RECONFIG); - - } - } /* for (x = 1; x < (span->chan_count + 1); x++) */ - - return FTDM_SUCCESS; -} - -ftdm_status_t sngss7_bufferzero_iam(SiConEvnt *siConEvnt) -{ - if (siConEvnt->natConInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->natConInd, 0, sizeof(siConEvnt->natConInd)); - if (siConEvnt->fwdCallInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->fwdCallInd, 0, sizeof(siConEvnt->fwdCallInd)); - if (siConEvnt->cgPtyCat.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cgPtyCat, 0, sizeof(siConEvnt->cgPtyCat)); - if (siConEvnt->txMedReq.eh.pres != PRSNT_NODEF) memset(&siConEvnt->txMedReq, 0, sizeof(siConEvnt->txMedReq)); -#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL) - if (siConEvnt->usrServInfoA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usrServInfoA, 0, sizeof(siConEvnt->usrServInfoA)); -#endif - if (siConEvnt->cdPtyNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cdPtyNum, 0, sizeof(siConEvnt->cdPtyNum)); -#if TNS_ANSI -#if (SS7_ANS92 || SS7_ANS95 || SS7_BELL) - if (siConEvnt->tranNetSel1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->tranNetSel1, 0, sizeof(siConEvnt->tranNetSel1)); -#endif -#endif - if (siConEvnt->tranNetSel.eh.pres != PRSNT_NODEF) memset(&siConEvnt->tranNetSel, 0, sizeof(siConEvnt->tranNetSel)); -#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL || SS7_CHINA) - if (siConEvnt->callRefA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->callRefA, 0, sizeof(siConEvnt->callRefA)); -#endif - if (siConEvnt->callRef.eh.pres != PRSNT_NODEF) memset(&siConEvnt->callRef, 0, sizeof(siConEvnt->callRef)); - if (siConEvnt->cgPtyNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cgPtyNum, 0, sizeof(siConEvnt->cgPtyNum)); -#if SS7_BELL - if (siConEvnt->cgPtyNumB.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cgPtyNumB, 0, sizeof(siConEvnt->cgPtyNumB)); -#endif - if (siConEvnt->opFwdCalInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->opFwdCalInd, 0, sizeof(siConEvnt->opFwdCalInd)); -#if (SS7_Q767 || SS7_RUSSIA || SS7_NTT) - if (siConEvnt->opFwdCalIndQ.eh.pres != PRSNT_NODEF) memset(&siConEvnt->opFwdCalIndQ, 0, sizeof(siConEvnt->opFwdCalIndQ)); -#endif -#if SS7_Q767IT - if (siConEvnt->fwdVad.eh.pres != PRSNT_NODEF) memset(&siConEvnt->fwdVad, 0, sizeof(siConEvnt->fwdVad)); -#endif -#if SS7_ANS88 - if (siConEvnt->opFwdCalIndA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->opFwdCalIndA, 0, sizeof(siConEvnt->opFwdCalIndA)); -#endif - if (siConEvnt->redirgNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirgNum, 0, sizeof(siConEvnt->redirgNum)); - if (siConEvnt->redirInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirInfo, 0, sizeof(siConEvnt->redirInfo)); - if (siConEvnt->cugIntCode.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cugIntCode, 0, sizeof(siConEvnt->cugIntCode)); -#if SS7_ANS88 - if (siConEvnt->cugIntCodeA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cugIntCodeA, 0, sizeof(siConEvnt->cugIntCodeA)); -#endif -#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL || SS7_CHINA) - if (siConEvnt->connReqA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->connReqA, 0, sizeof(siConEvnt->connReqA)); -#endif -#if SS7_ANS88 - if (siConEvnt->usr2UsrInfoA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usr2UsrInfoA, 0, sizeof(siConEvnt->usr2UsrInfoA)); -#endif - if (siConEvnt->connReq.eh.pres != PRSNT_NODEF) memset(&siConEvnt->connReq, 0, sizeof(siConEvnt->connReq)); - if (siConEvnt->origCdNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->origCdNum, 0, sizeof(siConEvnt->origCdNum)); - if (siConEvnt->usr2UsrInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usr2UsrInfo, 0, sizeof(siConEvnt->usr2UsrInfo)); - if (siConEvnt->accTrnspt.eh.pres != PRSNT_NODEF) memset(&siConEvnt->accTrnspt, 0, sizeof(siConEvnt->accTrnspt)); - if (siConEvnt->echoControl.eh.pres != PRSNT_NODEF) memset(&siConEvnt->echoControl, 0, sizeof(siConEvnt->echoControl)); -#if SS7_ANS88 - if (siConEvnt->redirInfoA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirInfoA, 0, sizeof(siConEvnt->redirInfoA)); -#endif -#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL) - if (siConEvnt->chargeNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->chargeNum, 0, sizeof(siConEvnt->chargeNum)); - if (siConEvnt->origLineInf.eh.pres != PRSNT_NODEF) memset(&siConEvnt->origLineInf, 0, sizeof(siConEvnt->origLineInf)); -#endif - if (siConEvnt->usrServInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usrServInfo, 0, sizeof(siConEvnt->usrServInfo)); - if (siConEvnt->usr2UsrInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usr2UsrInd, 0, sizeof(siConEvnt->usr2UsrInd)); - if (siConEvnt->propDly.eh.pres != PRSNT_NODEF) memset(&siConEvnt->propDly, 0, sizeof(siConEvnt->propDly)); - if (siConEvnt->usrServInfo1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usrServInfo1, 0, sizeof(siConEvnt->usrServInfo1)); - if (siConEvnt->netFac.eh.pres != PRSNT_NODEF) memset(&siConEvnt->netFac, 0, sizeof(siConEvnt->netFac)); -#ifdef SS7_CHINA - if (siConEvnt->orgPteCdeA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->orgPteCdeA, 0, sizeof(siConEvnt->orgPteCdeA)); -#endif - if (siConEvnt->orgPteCde.eh.pres != PRSNT_NODEF) memset(&siConEvnt->orgPteCde, 0, sizeof(siConEvnt->orgPteCde)); - if (siConEvnt->genDigits.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genDigits, 0, sizeof(siConEvnt->genDigits)); - if (siConEvnt->genDigitsR.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genDigitsR, 0, sizeof(siConEvnt->genDigitsR)); - if (siConEvnt->usrTSrvInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usrTSrvInfo, 0, sizeof(siConEvnt->usrTSrvInfo)); - if (siConEvnt->remotOper.eh.pres != PRSNT_NODEF) memset(&siConEvnt->remotOper, 0, sizeof(siConEvnt->remotOper)); - if (siConEvnt->parmCom.eh.pres != PRSNT_NODEF) memset(&siConEvnt->parmCom, 0, sizeof(siConEvnt->parmCom)); -#if (SS7_ANS92 || SS7_ANS95) - if (siConEvnt->servCode.eh.pres != PRSNT_NODEF) memset(&siConEvnt->servCode, 0, sizeof(siConEvnt->servCode)); -#endif -#if SS7_ANS92 - if (siConEvnt->serviceAct1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->serviceAct1, 0, sizeof(siConEvnt->serviceAct1)); -#endif -#if SS7_CHINA - if (siConEvnt->serviceAct2.eh.pres != PRSNT_NODEF) memset(&siConEvnt->serviceAct2, 0, sizeof(siConEvnt->serviceAct2)); -#endif - if (siConEvnt->serviceAct2.eh.pres != PRSNT_NODEF) memset(&siConEvnt->serviceAct2, 0, sizeof(siConEvnt->serviceAct2)); - if (siConEvnt->serviceAct.eh.pres != PRSNT_NODEF) memset(&siConEvnt->serviceAct, 0, sizeof(siConEvnt->serviceAct)); - if (siConEvnt->mlppPrec.eh.pres != PRSNT_NODEF) memset(&siConEvnt->mlppPrec, 0, sizeof(siConEvnt->mlppPrec)); -#if (defined(SIT_PARAMETER) || defined(TDS_ROLL_UPGRADE_SUPPORT)) - if (siConEvnt->txMedUsPr.eh.pres != PRSNT_NODEF) memset(&siConEvnt->txMedUsPr, 0, sizeof(siConEvnt->txMedUsPr)); -#endif - if (siConEvnt->bckCallInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->bckCallInd, 0, sizeof(siConEvnt->bckCallInd)); - if (siConEvnt->cgPtyNum1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cgPtyNum1, 0, sizeof(siConEvnt->cgPtyNum1)); - if (siConEvnt->optBckCalInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->optBckCalInd, 0, sizeof(siConEvnt->optBckCalInd)); -#if (SS7_Q767 || SS7_RUSSIA || SS7_NTT) - if (siConEvnt->optBckCalIndQ.eh.pres != PRSNT_NODEF) memset(&siConEvnt->optBckCalIndQ, 0, sizeof(siConEvnt->optBckCalIndQ)); -#endif - if (siConEvnt->connNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->connNum, 0, sizeof(siConEvnt->connNum)); -#if (defined(SIT_PARAMETER) || defined(TDS_ROLL_UPGRADE_SUPPORT)) - if (siConEvnt->connNum2.eh.pres != PRSNT_NODEF) memset(&siConEvnt->connNum2, 0, sizeof(siConEvnt->connNum2)); -#endif - if (siConEvnt->accDelInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->accDelInfo, 0, sizeof(siConEvnt->accDelInfo)); - if (siConEvnt->notifInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->notifInd, 0, sizeof(siConEvnt->notifInd)); - if (siConEvnt->notifIndR2.eh.pres != PRSNT_NODEF) memset(&siConEvnt->notifIndR2, 0, sizeof(siConEvnt->notifIndR2)); - if (siConEvnt->cllHstry.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cllHstry, 0, sizeof(siConEvnt->cllHstry)); - if (siConEvnt->genNmb.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genNmb, 0, sizeof(siConEvnt->genNmb)); - if (siConEvnt->genNmbR.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genNmbR, 0, sizeof(siConEvnt->genNmbR)); - if (siConEvnt->redirNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirNum, 0, sizeof(siConEvnt->redirNum)); - if (siConEvnt->redirRstr.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirRstr, 0, sizeof(siConEvnt->redirRstr)); - -#if SS7_Q767IT - if (siConEvnt->backVad.eh.pres != PRSNT_NODEF) memset(&siConEvnt->backVad, 0, sizeof(siConEvnt->backVad)); -#endif -#if SS7_SINGTEL - if (siConEvnt->cgPtyNumS.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cgPtyNumS, 0, sizeof(siConEvnt->cgPtyNumS)); -#endif -#if (SS7_ANS92 || SS7_ANS95 || SS7_BELL) - if (siConEvnt->businessGrp.eh.pres != PRSNT_NODEF) memset(&siConEvnt->businessGrp, 0, sizeof(siConEvnt->businessGrp)); - if (siConEvnt->infoInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->infoInd, 0, sizeof(siConEvnt->infoInd)); - if (siConEvnt->carrierId.eh.pres != PRSNT_NODEF) memset(&siConEvnt->carrierId, 0, sizeof(siConEvnt->carrierId)); - if (siConEvnt->carSelInf.eh.pres != PRSNT_NODEF) memset(&siConEvnt->carSelInf, 0, sizeof(siConEvnt->carSelInf)); - if (siConEvnt->egress.eh.pres != PRSNT_NODEF) memset(&siConEvnt->egress, 0, sizeof(siConEvnt->egress)); - if (siConEvnt->genAddr.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genAddr, 0, sizeof(siConEvnt->genAddr)); - if (siConEvnt->genAddrR.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genAddrR, 0, sizeof(siConEvnt->genAddrR)); - if (siConEvnt->infoReqInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->infoReqInd, 0, sizeof(siConEvnt->infoReqInd)); - if (siConEvnt->jurisInf.eh.pres != PRSNT_NODEF) memset(&siConEvnt->jurisInf, 0, sizeof(siConEvnt->jurisInf)); - if (siConEvnt->netTransport.eh.pres != PRSNT_NODEF) memset(&siConEvnt->netTransport, 0, sizeof(siConEvnt->netTransport)); - if (siConEvnt->specProcReq.eh.pres != PRSNT_NODEF) memset(&siConEvnt->specProcReq, 0, sizeof(siConEvnt->specProcReq)); - if (siConEvnt->transReq.eh.pres != PRSNT_NODEF) memset(&siConEvnt->transReq, 0, sizeof(siConEvnt->transReq)); -#endif -#if (defined(SIT_PARAMETER) || defined(TDS_ROLL_UPGRADE_SUPPORT)) -#if (SS7_ANS92 || SS7_ANS95) - if (siConEvnt->notifInd1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->notifInd1, 0, sizeof(siConEvnt->notifInd1)); - if (siConEvnt->notifIndR1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->notifIndR1, 0, sizeof(siConEvnt->notifIndR1)); -#endif /* SS7_ANS92 */ -#endif /* SIT_PARAMETER || TDS_ROLL_UPGRADE_SUPPORT */ -#if (SS7_BELL || SS7_ANS95) - if (siConEvnt->genName.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genName, 0, sizeof(siConEvnt->genName)); -#endif -#if (SS7_ITU97 || SS7_RUSS2000 || SS7_ITU2000 || SS7_ETSIV3 || \ - SS7_BELL || SS7_ANS95 || SS7_INDIA || SS7_UK || SS7_NZL || SS7_KZ) - if (siConEvnt->hopCounter.eh.pres != PRSNT_NODEF) memset(&siConEvnt->hopCounter, 0, sizeof(siConEvnt->hopCounter)); -#endif -#if (SS7_BELL || SS7_ITU2000 || SS7_KZ) - if (siConEvnt->redirCap.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirCap, 0, sizeof(siConEvnt->redirCap)); - if (siConEvnt->redirCntr.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirCntr, 0, sizeof(siConEvnt->redirCntr)); -#endif -#if (SS7_ETSI || SS7_FTZ) - if (siConEvnt->ccbsParam.eh.pres != PRSNT_NODEF) memset(&siConEvnt->ccbsParam, 0, sizeof(siConEvnt->ccbsParam)); - if (siConEvnt->freePhParam.eh.pres != PRSNT_NODEF) memset(&siConEvnt->freePhParam, 0, sizeof(siConEvnt->freePhParam)); -#endif -#ifdef SS7_FTZ - if (siConEvnt->naPaFF.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaFF, 0, sizeof(siConEvnt->naPaFF)); - if (siConEvnt->naPaFE.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaFE, 0, sizeof(siConEvnt->naPaFE)); - if (siConEvnt->naPaSSP.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaSSP, 0, sizeof(siConEvnt->naPaSSP)); - if (siConEvnt->naPaCdPNO.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaCdPNO, 0, sizeof(siConEvnt->naPaCdPNO)); - if (siConEvnt->naPaSPV.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaSPV, 0, sizeof(siConEvnt->naPaSPV)); - if (siConEvnt->naPaUKK.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaUKK, 0, sizeof(siConEvnt->naPaUKK)); -#endif -#if SS7_NTT - if (siConEvnt->msgAreaInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->msgAreaInfo, 0, sizeof(siConEvnt->msgAreaInfo)); - if (siConEvnt->subsNumber.eh.pres != PRSNT_NODEF) memset(&siConEvnt->subsNumber, 0, sizeof(siConEvnt->subsNumber)); - if (siConEvnt->rpCllngNo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->rpCllngNo, 0, sizeof(siConEvnt->rpCllngNo)); - if (siConEvnt->supplUserType.eh.pres != PRSNT_NODEF) memset(&siConEvnt->supplUserType, 0, sizeof(siConEvnt->supplUserType)); - if (siConEvnt->carrierInfoTrans.eh.pres != PRSNT_NODEF) memset(&siConEvnt->carrierInfoTrans, 0, sizeof(siConEvnt->carrierInfoTrans)); - if (siConEvnt->nwFuncType.eh.pres != PRSNT_NODEF) memset(&siConEvnt->nwFuncType, 0, sizeof(siConEvnt->nwFuncType)); -#endif -#if SS7_ANS95 - if (siConEvnt->optrServicesInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->optrServicesInfo, 0, sizeof(siConEvnt->optrServicesInfo)); -#endif -#if (SS7_ANS95 || SS7_ITU97 || SS7_RUSS2000|| SS7_ITU2000 || SS7_NZL || SS7_KZ) - if (siConEvnt->cirAsgnMap.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cirAsgnMap, 0, sizeof(siConEvnt->cirAsgnMap)); -#endif -#if (SS7_ITU97 || SS7_RUSS2000 || SS7_ITU2000 || SS7_ETSIV3 || \ - SS7_INDIA || SS7_UK || SS7_NZL || SS7_KZ) - if (siConEvnt->displayInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->displayInfo, 0, sizeof(siConEvnt->displayInfo)); - if (siConEvnt->confTrtInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->confTrtInd, 0, sizeof(siConEvnt->confTrtInd)); - if (siConEvnt->netMgmtControls.eh.pres != PRSNT_NODEF) memset(&siConEvnt->netMgmtControls, 0, sizeof(siConEvnt->netMgmtControls)); - if (siConEvnt->correlationId.eh.pres != PRSNT_NODEF) memset(&siConEvnt->correlationId, 0, sizeof(siConEvnt->correlationId)); - if (siConEvnt->callDivTrtInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->callDivTrtInd, 0, sizeof(siConEvnt->callDivTrtInd)); - if (siConEvnt->callInNmb.eh.pres != PRSNT_NODEF) memset(&siConEvnt->callInNmb, 0, sizeof(siConEvnt->callInNmb)); - if (siConEvnt->callOfferTrtInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->callOfferTrtInd, 0, sizeof(siConEvnt->callOfferTrtInd)); - if (siConEvnt->scfId.eh.pres != PRSNT_NODEF) memset(&siConEvnt->scfId, 0, sizeof(siConEvnt->scfId)); - if (siConEvnt->uidCapInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->uidCapInd, 0, sizeof(siConEvnt->uidCapInd)); - if (siConEvnt->collCallReq.eh.pres != PRSNT_NODEF) memset(&siConEvnt->collCallReq, 0, sizeof(siConEvnt->collCallReq)); - if (siConEvnt->ccss.eh.pres != PRSNT_NODEF) memset(&siConEvnt->ccss, 0, sizeof(siConEvnt->ccss)); -#endif -#if (SS7_ITU97 || SS7_RUSS2000 || SS7_ITU2000 || SS7_UK || SS7_NZL || SS7_KZ) - if (siConEvnt->backGVNS.eh.pres != PRSNT_NODEF) memset(&siConEvnt->backGVNS, 0, sizeof(siConEvnt->backGVNS)); - if (siConEvnt->forwardGVNS.eh.pres != PRSNT_NODEF) memset(&siConEvnt->forwardGVNS, 0, sizeof(siConEvnt->forwardGVNS)); -#endif -#if (SS7_ETSIV3 || SS7_ITU97 || SS7_RUSS2000 || SS7_ITU2000 || \ - SS7_INDIA || SS7_UK || SS7_NZL || SS7_KZ) - if (siConEvnt->appTransParam.eh.pres != PRSNT_NODEF) memset(&siConEvnt->appTransParam, 0, sizeof(siConEvnt->appTransParam)); -#endif -#if (SS7_ITU2000 || SS7_UK || SS7_NZL || SS7_KZ) - if (siConEvnt->htrInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->htrInfo, 0, sizeof(siConEvnt->htrInfo)); - if (siConEvnt->pivotCap.eh.pres != PRSNT_NODEF) memset(&siConEvnt->pivotCap, 0, sizeof(siConEvnt->pivotCap)); - if (siConEvnt->cadDirNmb.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cadDirNmb, 0, sizeof(siConEvnt->cadDirNmb)); - if (siConEvnt->origCallInNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->origCallInNum, 0, sizeof(siConEvnt->origCallInNum)); - if (siConEvnt->calgGeoLoc.eh.pres != PRSNT_NODEF) memset(&siConEvnt->calgGeoLoc, 0, sizeof(siConEvnt->calgGeoLoc)); - if (siConEvnt->netRoutNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->netRoutNum, 0, sizeof(siConEvnt->netRoutNum)); - if (siConEvnt->qonRelCap.eh.pres != PRSNT_NODEF) memset(&siConEvnt->qonRelCap, 0, sizeof(siConEvnt->qonRelCap)); - if (siConEvnt->pivotCntr.eh.pres != PRSNT_NODEF) memset(&siConEvnt->pivotCntr, 0, sizeof(siConEvnt->pivotCntr)); - if (siConEvnt->pivotRtgFwInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->pivotRtgFwInfo, 0, sizeof(siConEvnt->pivotRtgFwInfo)); - if (siConEvnt->pivotRtgBkInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->pivotRtgBkInfo, 0, sizeof(siConEvnt->pivotRtgBkInfo)); - if (siConEvnt->numPortFwdInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->numPortFwdInfo, 0, sizeof(siConEvnt->numPortFwdInfo)); -#endif -#ifdef SS7_UK - if (siConEvnt->natFwdCalInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->natFwdCalInd, 0, sizeof(siConEvnt->natFwdCalInd)); - if (siConEvnt->presntNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->presntNum, 0, sizeof(siConEvnt->presntNum)); - if (siConEvnt->lstDvrtLineId.eh.pres != PRSNT_NODEF) memset(&siConEvnt->lstDvrtLineId, 0, sizeof(siConEvnt->lstDvrtLineId)); - if (siConEvnt->pcgLineId.eh.pres != PRSNT_NODEF) memset(&siConEvnt->pcgLineId, 0, sizeof(siConEvnt->pcgLineId)); - if (siConEvnt->natFwdCalIndLnk.eh.pres != PRSNT_NODEF) memset(&siConEvnt->natFwdCalIndLnk, 0, sizeof(siConEvnt->natFwdCalIndLnk)); - if (siConEvnt->cdBascSrvcMrk.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cdBascSrvcMrk, 0, sizeof(siConEvnt->cdBascSrvcMrk)); -#endif /* SS7_UK */ -#if (defined(CGPN_CHK)) - if (siConEvnt->causeDgnCgPnChk.eh.pres != PRSNT_NODEF) memset(&siConEvnt->causeDgnCgPnChk, 0, sizeof(siConEvnt->causeDgnCgPnChk)); -#endif - return FTDM_SUCCESS; -} - -ftdm_status_t sngss7_save_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt) -{ -#ifndef HAVE_ZLIB - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Cannot perform transparent IAM because zlib is missing\n"); - return FTDM_FAIL; -#else - unsigned ret_val = FTDM_FAIL; - char *compressed_iam = NULL; - char *url_encoded_iam = NULL; - uLongf len = sizeof(*siConEvnt); - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - - /* By default, Trillium does not memset their whole structure to zero for - * performance. But we want to memset all the IE's that are not present to - * optimize compressed size */ - sngss7_bufferzero_iam(siConEvnt); - - compressed_iam = ftdm_malloc(sizeof(*siConEvnt)); - if (!compressed_iam) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to allocate buffer for compressed_iam\n"); - goto done; - } - - /* Compress IAM structure to minimize buffer size */ - ret_val = compress((Bytef *)compressed_iam, &len, (const Bytef *)siConEvnt, (uLong)sizeof(*siConEvnt)); - if (ret_val != Z_OK) { - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Failed to compress IAM (error:%d)\n", ret_val); - ret_val = FTDM_FAIL; - goto done; - } - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Compressed IAM size:%lu\n", len); - - /* Worst case: size will triple after url encode */ - url_encoded_iam = ftdm_malloc(3*sizeof(*siConEvnt)); - if (!url_encoded_iam) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to allocated buffer for url_encoded_iam\n"); - ret_val = FTDM_FAIL; - goto done; - } - memset(url_encoded_iam, 0, 2*sizeof(*siConEvnt)); - - /* URL encode buffer to that its safe to store it in a string */ - ftdm_url_encode((const char*)compressed_iam, url_encoded_iam, len); - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "IAM variable length:%"FTDM_SIZE_FMT"\n", strlen(url_encoded_iam)); - - if (strlen(url_encoded_iam) > sngss7_info->circuit->transparent_iam_max_size) { - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "IAM variable length exceeds max size (len:%d max:%d) \n", - strlen(url_encoded_iam), sngss7_info->circuit->transparent_iam_max_size); - ret_val = FTDM_FAIL; - goto done; - } - - sngss7_add_var(sngss7_info, "ss7_iam", url_encoded_iam); -done: - ftdm_safe_free(compressed_iam); - ftdm_safe_free(url_encoded_iam); - return ret_val; -#endif -} - -ftdm_status_t sngss7_retrieve_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt) -{ -#ifndef HAVE_ZLIB - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Cannot perform transparent IAM because zlib is missing\n"); - return FTDM_FAIL; -#else - uLongf len = 3*sizeof(*siConEvnt); /* worst case: URL encoded buffer is 3x length of buffer */ - char *val = NULL; - unsigned ret_val = FTDM_FAIL; - void *uncompressed_buffer = NULL; - char *url_encoded_iam = NULL; - ftdm_size_t url_encoded_iam_len; - - val = (char*)ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam"); - if (ftdm_strlen_zero(val)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No Transparent IAM info available\n"); - return FTDM_FAIL; - } - - url_encoded_iam = ftdm_strdup(val); - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "IAM variable length:%"FTDM_SIZE_FMT"\n", strlen(val)); - ftdm_url_decode(url_encoded_iam, &url_encoded_iam_len); - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Compressed IAM size:%"FTDM_SIZE_FMT"\n", url_encoded_iam_len); - - uncompressed_buffer = ftdm_malloc(sizeof(*siConEvnt)); - ftdm_assert_return(uncompressed_buffer, FTDM_FAIL, "Failed to allocate buffer for uncompressed buffer\n"); - - ret_val = uncompress(uncompressed_buffer, &len, (const Bytef *)url_encoded_iam, (uLong)url_encoded_iam_len); - if (ret_val != Z_OK) { - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Failed to uncompress IAM (error:%d)\n", ret_val); - goto done; - } - - if (len != sizeof(*siConEvnt)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Incompatible IAM structure size (expected:%"FTDM_SIZE_FMT" size:%"FTDM_SIZE_FMT")\n", sizeof(*siConEvnt), strlen(uncompressed_buffer)); - goto done; - } - - memcpy(siConEvnt, uncompressed_buffer, sizeof(*siConEvnt)); - ret_val = FTDM_SUCCESS; - -done: - ftdm_safe_free(uncompressed_buffer); - ftdm_safe_free(url_encoded_iam); - return ret_val; -#endif -} - -/******************************************************************************/ -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c deleted file mode 100644 index 541f107704..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2009, Sangoma Technologies - * Konrad Hammel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Contributors: - * - * Moises Silva - * - */ - -/* INCLUDE ********************************************************************/ -#include "ftmod_sangoma_ss7_main.h" -/******************************************************************************/ - -/* DEFINES ********************************************************************/ -/******************************************************************************/ - -/* GLOBALS ********************************************************************/ - -/******************************************************************************/ - -/* PROTOTYPES *****************************************************************/ - -/******************************************************************************/ - -/* FUNCTIONS ******************************************************************/ -void handle_isup_t35(void *userdata) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_timer_data_t *timer = userdata; - sngss7_chan_data_t *sngss7_info = timer->sngss7_info; - ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan; - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_channel_lock(ftdmchan); - - /* Q.764 2.2.5 Address incomplete (T35 expiry action is hangup with cause 28 according to Table A.1/Q.764) */ - SS7_ERROR("[Call-Control] Timer 35 expired on CIC = %d\n", sngss7_info->circuit->cic); - - /* set the flag to indicate this hangup is started from the local side */ - sngss7_set_ckt_flag(sngss7_info, FLAG_LOCAL_REL); - - /* hang up on timer expiry */ - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_INVALID_NUMBER_FORMAT; - - /* end the call */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); - - /* kill t10 t39 if active */ - if (sngss7_info->t10.hb_timer_id) { - ftdm_sched_cancel_timer (sngss7_info->t10.sched, sngss7_info->t10.hb_timer_id); - } - if (sngss7_info->t39.hb_timer_id) { - ftdm_sched_cancel_timer (sngss7_info->t39.sched, sngss7_info->t39.hb_timer_id); - } - - /*unlock*/ - ftdm_channel_unlock(ftdmchan); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); - return; -} - - -void handle_isup_t10(void *userdata) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_timer_data_t *timer = userdata; - sngss7_chan_data_t *sngss7_info = timer->sngss7_info; - ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan; - - ftdm_channel_lock(ftdmchan); - - SS7_DEBUG("[Call-Control] Timer 10 expired on CIC = %d\n", sngss7_info->circuit->cic); - - /* send the call to the user */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); - - ftdm_channel_unlock(ftdmchan); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} - -void handle_isup_t39(void *userdata) -{ - SS7_FUNC_TRACE_ENTER(__FTDM_FUNC__); - - sngss7_timer_data_t *timer = userdata; - sngss7_chan_data_t *sngss7_info = timer->sngss7_info; - ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan; - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_channel_lock(ftdmchan); - - /* Q.764 2.2.5 Address incomplete (T35 expiry action is hangup with cause 28 according to Table A.1/Q.764) */ - SS7_ERROR("[Call-Control] Timer 39 expired on CIC = %d\n", sngss7_info->circuit->cic); - - /* set the flag to indicate this hangup is started from the local side */ - sngss7_set_ckt_flag(sngss7_info, FLAG_LOCAL_REL); - - /* hang up on timer expiry */ - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_INVALID_NUMBER_FORMAT; - - /* end the call */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); - - /* kill t10 t35 if active */ - if (sngss7_info->t10.hb_timer_id) { - ftdm_sched_cancel_timer (sngss7_info->t10.sched, sngss7_info->t10.hb_timer_id); - } - if (sngss7_info->t35.hb_timer_id) { - ftdm_sched_cancel_timer (sngss7_info->t35.sched, sngss7_info->t35.hb_timer_id); - } - - /*unlock*/ - ftdm_channel_unlock(ftdmchan); - - SS7_FUNC_TRACE_EXIT(__FTDM_FUNC__); -} -/******************************************************************************/ -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ -/******************************************************************************/ - diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c deleted file mode 100644 index ad504b14b0..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c +++ /dev/null @@ -1,3454 +0,0 @@ -/* - * Copyright (c) 2009, Konrad Hammel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Contributors: - * - * James Zhang - * - */ - -/* INCLUDE ********************************************************************/ -#include "ftmod_sangoma_ss7_main.h" -/******************************************************************************/ - -/* DEFINES ********************************************************************/ -/******************************************************************************/ - -/* GLOBALS ********************************************************************/ -sng_ssf_type_t sng_ssf_type_map[] = -{ - { 1, "nat" , SSF_NAT }, - { 1, "int" , SSF_INTL }, - { 1, "spare" , SSF_SPARE }, - { 1, "res" , SSF_RES }, - { 0, "", 0 }, -}; - -sng_switch_type_t sng_switch_type_map[] = -{ - { 1, "itu88" , LSI_SW_ITU , LSI_SW_ITU }, - { 1, "itu92" , LSI_SW_ITU , LSI_SW_ITU }, - { 1, "itu97" , LSI_SW_ITU97 , LSI_SW_ITU97 }, - { 1, "itu00" , LSI_SW_ITU2000 , LSI_SW_ITU2000 }, - { 1, "ansi88" , LSI_SW_ANS88 , LSI_SW_ANS88 }, - { 1, "ansi92" , LSI_SW_ANS92 , LSI_SW_ANS92 }, - { 1, "ansi95" , LSI_SW_ANS92 , LSI_SW_ANS92 }, - { 1, "etsiv2" , LSI_SW_ETSI , LSI_SW_ETSI }, - { 1, "etsiv3" , LSI_SW_ETSIV3 , LSI_SW_ETSIV3 }, - { 1, "india" , LSI_SW_INDIA , LSI_SW_INDIA }, - { 1, "uk" , LSI_SW_UK , LSI_SW_UK }, - { 1, "russia" , LSI_SW_RUSSIA , LSI_SW_RUSSIA }, - { 1, "china" , LSI_SW_CHINA , LSI_SW_CHINA }, - { 0, "", 0, 0 }, -}; - -sng_link_type_t sng_link_type_map[] = -{ - { 1, "itu88" , LSD_SW_ITU88 , LSN_SW_ITU }, - { 1, "itu92" , LSD_SW_ITU92 , LSN_SW_ITU }, - { 1, "etsi" , LSD_SW_ITU92 , LSN_SW_ITU }, - { 1, "ansi88" , LSD_SW_ANSI88, LSN_SW_ANS }, - { 1, "ansi92" , LSD_SW_ANSI92, LSN_SW_ANS }, - { 1, "ansi96" , LSD_SW_ANSI92, LSN_SW_ANS96 }, - { 0, "", 0, 0 }, -}; - -sng_mtp2_error_type_t sng_mtp2_error_type_map[] = -{ - { 1, "basic", SD_ERR_NRM }, - { 1, "pcr" , SD_ERR_CYC }, - { 0, "", 0 }, -}; - -sng_cic_cntrl_type_t sng_cic_cntrl_type_map[] = -{ - { 1, "bothway" , BOTHWAY }, - { 1, "incoming" , INCOMING }, - { 1, "outgoing" , OUTGOING }, - { 1, "controlling" , CONTROLLING }, - { 1, "controlled" , CONTROLLED }, - { 0, "", 0 }, -}; - -typedef struct sng_timeslot -{ - int channel; - int siglink; - int gap; - int hole; -}sng_timeslot_t; - -typedef struct sng_span -{ - char name[MAX_NAME_LEN]; - ftdm_span_t *span; - uint32_t ccSpanId; -} sng_span_t; - -typedef struct sng_ccSpan -{ - char name[MAX_NAME_LEN]; - uint32_t options; - uint32_t id; - uint32_t procId; - uint32_t isupInf; - uint32_t cicbase; - char ch_map[MAX_CIC_MAP_LENGTH]; - uint32_t typeCntrl; - uint32_t switchType; - uint32_t ssf; - uint32_t clg_nadi; - uint32_t cld_nadi; - uint32_t rdnis_nadi; - uint32_t loc_nadi; - uint32_t min_digits; - uint32_t transparent_iam_max_size; - uint8_t transparent_iam; - uint8_t cpg_on_progress_media; - uint8_t cpg_on_progress; - uint8_t itx_auto_reply; - uint32_t t3; - uint32_t t10; - uint32_t t12; - uint32_t t13; - uint32_t t14; - uint32_t t15; - uint32_t t16; - uint32_t t17; - uint32_t t35; - uint32_t t39; - uint32_t tval; -} sng_ccSpan_t; - -int cmbLinkSetId; -/******************************************************************************/ - -/* PROTOTYPES *****************************************************************/ -int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *span); - -static int ftmod_ss7_parse_sng_isup(ftdm_conf_node_t *sng_isup); - -static int ftmod_ss7_parse_sng_gen(ftdm_conf_node_t *sng_gen); - -static int ftmod_ss7_parse_sng_relay(ftdm_conf_node_t *sng_relay); -static int ftmod_ss7_parse_relay_channel(ftdm_conf_node_t *relay_chan); - -static int ftmod_ss7_parse_mtp1_links(ftdm_conf_node_t *mtp1_links); -static int ftmod_ss7_parse_mtp1_link(ftdm_conf_node_t *mtp1_link); - -static int ftmod_ss7_parse_mtp2_links(ftdm_conf_node_t *mtp2_links); -static int ftmod_ss7_parse_mtp2_link(ftdm_conf_node_t *mtp2_link); - -static int ftmod_ss7_parse_mtp3_links(ftdm_conf_node_t *mtp3_links); -static int ftmod_ss7_parse_mtp3_link(ftdm_conf_node_t *mtp3_link); - -static int ftmod_ss7_parse_mtp_linksets(ftdm_conf_node_t *mtp_linksets); -static int ftmod_ss7_parse_mtp_linkset(ftdm_conf_node_t *mtp_linkset); - -static int ftmod_ss7_parse_mtp_routes(ftdm_conf_node_t *mtp_routes); -static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route); - -static int ftmod_ss7_parse_isup_interfaces(ftdm_conf_node_t *isup_interfaces); -static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface); - -static int ftmod_ss7_parse_cc_spans(ftdm_conf_node_t *cc_spans); -static int ftmod_ss7_parse_cc_span(ftdm_conf_node_t *cc_span); - -static int ftmod_ss7_fill_in_relay_channel(sng_relay_t *relay_channel); -static int ftmod_ss7_fill_in_mtp1_link(sng_mtp1_link_t *mtp1Link); -static int ftmod_ss7_fill_in_mtp2_link(sng_mtp2_link_t *mtp1Link); -static int ftmod_ss7_fill_in_mtp3_link(sng_mtp3_link_t *mtp1Link); -static int ftmod_ss7_fill_in_mtpLinkSet(sng_link_set_t *mtpLinkSet); -static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route); -static int ftmod_ss7_fill_in_nsap(sng_route_t *mtp3_route); -static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup); -static int ftmod_ss7_fill_in_isap(sng_isap_t *sng_isap); -static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan); -static int ftmod_ss7_fill_in_self_route(int spc, int linkType, int switchType, int ssf); -static int ftmod_ss7_fill_in_circuits(sng_span_t *sngSpan); - -static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot); -static void ftmod_ss7_set_glare_resolution (const char *method); - -/******************************************************************************/ - -/* FUNCTIONS ******************************************************************/ - -int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *span) -{ - sng_route_t self_route; - sng_span_t sngSpan; - int i = 0; - const char *var = NULL; - const char *val = NULL; - ftdm_conf_node_t *ptr = NULL; - - /* clean out the isup ckt */ - memset(&sngSpan, 0x0, sizeof(sngSpan)); - - /* clean out the self route */ - memset(&self_route, 0x0, sizeof(self_route)); - - var = ftdm_parameters[i].var; - val = ftdm_parameters[i].val; - - g_ftdm_operating_mode = SNG_SS7_OPR_MODE_ISUP; - - /* confirm that the first parameter is the "operating-mode" */ - if(!strcasecmp(var, "operating-mode")){ - if(!strcasecmp(val, "ISUP")) { - g_ftdm_operating_mode = SNG_SS7_OPR_MODE_ISUP; - } - else if(!strcasecmp(val, "M2UA_SG")) { - g_ftdm_operating_mode = SNG_SS7_OPR_MODE_M2UA_SG; - } else { - SS7_DEBUG("Operating mode not specified, defaulting to ISUP\n"); - } - i++; - } - - - - var = ftdm_parameters[i].var; - val = ftdm_parameters[i].val; - ptr = (ftdm_conf_node_t *)ftdm_parameters[i].ptr; - - /* confirm that the 2nd parameter is the "confnode" */ - if (!strcasecmp(var, "confnode")) { - /* parse the confnode and fill in the global libsng_ss7 config structure */ - if (ftmod_ss7_parse_sng_isup(ptr)) { - SS7_ERROR("Failed to parse the \"confnode\"!\n"); - goto ftmod_ss7_parse_xml_error; - } - } else { - /* ERROR...exit */ - SS7_ERROR("The \"confnode\" configuration was not the first parameter!\n"); - SS7_ERROR("\tFound \"%s\" in the first slot\n", var); - goto ftmod_ss7_parse_xml_error; - } - - i++; - - while (ftdm_parameters[i].var != NULL) { - var = ftdm_parameters[i].var; - val = ftdm_parameters[i].val; - - if (!strcasecmp(var, "dialplan")) { - /* don't care for now */ - } else if (!strcasecmp(var, "context")) { - /* don't care for now */ - } else if (!strcasecmp(var, "span-id") || !strcasecmp(var, "ccSpanId")) { - sngSpan.ccSpanId = atoi(val); - SS7_DEBUG("Found an ccSpanId = %d\n",sngSpan.ccSpanId); - } else { - SS7_ERROR("Unknown parameter found =\"%s\"...ignoring it!\n", var); - } - - i++; - } /* while (ftdm_parameters[i].var != NULL) */ - - /* fill the pointer to span into isupCkt */ - sngSpan.span = span; - - if(SNG_SS7_OPR_MODE_ISUP == g_ftdm_operating_mode){ - /* setup the circuits structure */ - if(ftmod_ss7_fill_in_circuits(&sngSpan)) { - SS7_ERROR("Failed to fill in circuits structure!\n"); - goto ftmod_ss7_parse_xml_error; - } - } - - return FTDM_SUCCESS; - -ftmod_ss7_parse_xml_error: - return FTDM_FAIL; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_sng_isup(ftdm_conf_node_t *sng_isup) -{ - ftdm_conf_node_t *gen_config = NULL; - ftdm_conf_node_t *relay_channels = NULL; - ftdm_conf_node_t *mtp1_links = NULL; - ftdm_conf_node_t *mtp2_links = NULL; - ftdm_conf_node_t *mtp3_links = NULL; - ftdm_conf_node_t *mtp_linksets = NULL; - ftdm_conf_node_t *mtp_routes = NULL; - ftdm_conf_node_t *isup_interfaces = NULL; - ftdm_conf_node_t *cc_spans = NULL; - ftdm_conf_node_t *tmp_node = NULL; - ftdm_conf_node_t *nif_ifaces = NULL; - ftdm_conf_node_t *m2ua_ifaces = NULL; - ftdm_conf_node_t *m2ua_peer_ifaces = NULL; - ftdm_conf_node_t *m2ua_clust_ifaces = NULL; - ftdm_conf_node_t *sctp_ifaces = NULL; - - /* confirm that we are looking at sng_isup */ - if (strcasecmp(sng_isup->name, "sng_isup")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"sng_isup\"!\n",sng_isup->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"sng_isup\"...\n"); - } - - /* extract the main sections of the sng_isup block */ - tmp_node = sng_isup->child; - - while (tmp_node != NULL) { - /**************************************************************************/ - /* check the type of structure */ - if (!strcasecmp(tmp_node->name, "sng_gen")) { - /**********************************************************************/ - if (gen_config == NULL) { - gen_config = tmp_node; - SS7_DEBUG("Found a \"sng_gen\" section!\n"); - } else { - SS7_ERROR("Found a second \"sng_gen\" section\n!"); - return FTDM_FAIL; - } - /**********************************************************************/ - } else if (!strcasecmp(tmp_node->name, "sng_relay")) { - /**********************************************************************/ - if (relay_channels == NULL) { - relay_channels = tmp_node; - SS7_DEBUG("Found a \"sng_relay\" section!\n"); - } else { - SS7_ERROR("Found a second \"sng_relay\" section\n!"); - return FTDM_FAIL; - } - /**********************************************************************/ - }else if (!strcasecmp(tmp_node->name, "mtp1_links")) { - /**********************************************************************/ - if (mtp1_links == NULL) { - mtp1_links = tmp_node; - SS7_DEBUG("Found a \"mtp1_links\" section!\n"); - } else { - SS7_ERROR("Found a second \"mtp1_links\" section!\n"); - return FTDM_FAIL; - } - /**********************************************************************/ - } else if (!strcasecmp(tmp_node->name, "mtp2_links")) { - /**********************************************************************/ - if (mtp2_links == NULL) { - mtp2_links = tmp_node; - SS7_DEBUG("Found a \"mtp2_links\" section!\n"); - } else { - SS7_ERROR("Found a second \"mtp2_links\" section!\n"); - return FTDM_FAIL; - } - /**********************************************************************/ - } else if (!strcasecmp(tmp_node->name, "mtp3_links")) { - /**********************************************************************/ - if (mtp3_links == NULL) { - mtp3_links = tmp_node; - SS7_DEBUG("Found a \"mtp3_links\" section!\n"); - } else { - SS7_ERROR("Found a second \"mtp3_links\" section!\n"); - return FTDM_FAIL; - } - /**********************************************************************/ - } else if (!strcasecmp(tmp_node->name, "mtp_linksets")) { - /**********************************************************************/ - if (mtp_linksets == NULL) { - mtp_linksets = tmp_node; - SS7_DEBUG("Found a \"mtp_linksets\" section!\n"); - } else { - SS7_ERROR("Found a second \"mtp_linksets\" section!\n"); - return FTDM_FAIL; - } - /**********************************************************************/ - } else if (!strcasecmp(tmp_node->name, "mtp_routes")) { - /**********************************************************************/ - if (mtp_routes == NULL) { - mtp_routes = tmp_node; - SS7_DEBUG("Found a \"mtp_routes\" section!\n"); - } else { - SS7_ERROR("Found a second \"mtp_routes\" section!\n"); - return FTDM_FAIL; - } - /**********************************************************************/ - } else if (!strcasecmp(tmp_node->name, "isup_interfaces")) { - /**********************************************************************/ - if (isup_interfaces == NULL) { - isup_interfaces = tmp_node; - SS7_DEBUG("Found a \"isup_interfaces\" section!\n"); - } else { - SS7_ERROR("Found a second \"isup_interfaces\" section\n!"); - return FTDM_FAIL; - } - /**********************************************************************/ - } else if (!strcasecmp(tmp_node->name, "cc_spans")) { - /**********************************************************************/ - if (cc_spans == NULL) { - cc_spans = tmp_node; - SS7_DEBUG("Found a \"cc_spans\" section!\n"); - } else { - SS7_ERROR("Found a second \"cc_spans\" section\n!"); - return FTDM_FAIL; - } - /**********************************************************************/ - } else if (!strcasecmp(tmp_node->name, "sng_nif_interfaces")) { - /**********************************************************************/ - if (nif_ifaces == NULL) { - nif_ifaces = tmp_node; - SS7_DEBUG("Found a \"sng_nif_interfaces\" section!\n"); - } else { - SS7_ERROR("Found a second \"sng_nif_interfaces\" section\n!"); - return FTDM_FAIL; - } - /**********************************************************************/ - } else if (!strcasecmp(tmp_node->name, "sng_m2ua_interfaces")) { - /**********************************************************************/ - if (m2ua_ifaces == NULL) { - m2ua_ifaces = tmp_node; - SS7_DEBUG("Found a \"sng_m2ua_interfaces\" section!\n"); - } else { - SS7_ERROR("Found a second \"sng_m2ua_interfaces\" section\n!"); - return FTDM_FAIL; - } - /**********************************************************************/ - } else if (!strcasecmp(tmp_node->name, "sng_m2ua_peer_interfaces")) { - /**********************************************************************/ - if (m2ua_peer_ifaces == NULL) { - m2ua_peer_ifaces = tmp_node; - SS7_DEBUG("Found a \"sng_m2ua_peer_interfaces\" section!\n"); - } else { - SS7_ERROR("Found a second \"sng_m2ua_peer_interfaces\" section\n!"); - return FTDM_FAIL; - } - /**********************************************************************/ - } else if (!strcasecmp(tmp_node->name, "sng_m2ua_cluster_interfaces")) { - /**********************************************************************/ - if (m2ua_clust_ifaces == NULL) { - m2ua_clust_ifaces = tmp_node; - SS7_DEBUG("Found a \"sng_m2ua_cluster_interfaces\" section!\n"); - } else { - SS7_ERROR("Found a second \"sng_m2ua_peer_interfaces\" section\n!"); - return FTDM_FAIL; - } - /**********************************************************************/ - } else if (!strcasecmp(tmp_node->name, "sng_sctp_interfaces")) { - /**********************************************************************/ - if (sctp_ifaces == NULL) { - sctp_ifaces = tmp_node; - SS7_DEBUG("Found a section!\n"); - } else { - SS7_ERROR("Found a second section!\n"); - return FTDM_FAIL; - } - /**********************************************************************/ - } else { - /**********************************************************************/ - SS7_ERROR("\tFound an unknown section \"%s\"!\n", tmp_node->name); - return FTDM_FAIL; - /**********************************************************************/ - } - - /* go to the next sibling */ - tmp_node = tmp_node->next; - } /* while (tmp_node != NULL) */ - - /* now try to parse the sections */ - if (ftmod_ss7_parse_sng_gen(gen_config)) { - SS7_ERROR("Failed to parse \"gen_config\"!\n"); - return FTDM_FAIL; - } - - if (ftmod_ss7_parse_sng_relay(relay_channels)) { - SS7_ERROR("Failed to parse \"relay_channels\"!\n"); - return FTDM_FAIL; - } - - if (ftmod_ss7_parse_mtp1_links(mtp1_links)) { - SS7_ERROR("Failed to parse \"mtp1_links\"!\n"); - return FTDM_FAIL; - } - - if (ftmod_ss7_parse_mtp2_links(mtp2_links)) { - SS7_ERROR("Failed to parse \"mtp2_links\"!\n"); - return FTDM_FAIL; - } - - - switch(g_ftdm_operating_mode) - { - case SNG_SS7_OPR_MODE_ISUP: - { - if (mtp3_links && ftmod_ss7_parse_mtp3_links(mtp3_links)) { - SS7_ERROR("Failed to parse \"mtp3_links\"!\n"); - return FTDM_FAIL; - } - - if (ftmod_ss7_parse_mtp_linksets(mtp_linksets)) { - SS7_ERROR("Failed to parse \"mtp_linksets\"!\n"); - return FTDM_FAIL; - } - - if (ftmod_ss7_parse_mtp_routes(mtp_routes)) { - SS7_ERROR("Failed to parse \"mtp_routes\"!\n"); - return FTDM_FAIL; - } - - if (isup_interfaces && ftmod_ss7_parse_isup_interfaces(isup_interfaces)) { - SS7_ERROR("Failed to parse \"isup_interfaces\"!\n"); - return FTDM_FAIL; - } - - if (cc_spans && ftmod_ss7_parse_cc_spans(cc_spans)) { - SS7_ERROR("Failed to parse \"cc_spans\"!\n"); - return FTDM_FAIL; - } - break; - } - case SNG_SS7_OPR_MODE_M2UA_SG: - { - if (ftmod_ss7_parse_sctp_links(sctp_ifaces) != FTDM_SUCCESS) { - SS7_ERROR("Failed to parse !\n"); - return FTDM_FAIL; - } - - if (nif_ifaces && ftmod_ss7_parse_nif_interfaces(nif_ifaces)) { - SS7_ERROR("Failed to parse \"nif_ifaces\"!\n"); - return FTDM_FAIL; - } - - if (m2ua_ifaces && ftmod_ss7_parse_m2ua_interfaces(m2ua_ifaces)) { - SS7_ERROR("Failed to parse \"m2ua_ifaces\"!\n"); - return FTDM_FAIL; - } - if (m2ua_peer_ifaces && ftmod_ss7_parse_m2ua_peer_interfaces(m2ua_peer_ifaces)) { - SS7_ERROR("Failed to parse \"m2ua_peer_ifaces\"!\n"); - return FTDM_FAIL; - } - if (m2ua_clust_ifaces && ftmod_ss7_parse_m2ua_clust_interfaces(m2ua_clust_ifaces)) { - SS7_ERROR("Failed to parse \"m2ua_clust_ifaces\"!\n"); - return FTDM_FAIL; - } - break; - } - default: - SS7_ERROR("Invalid operating mode[%d]\n",g_ftdm_operating_mode); - break; - - } - - return FTDM_SUCCESS; -} - -static void ftmod_ss7_set_glare_resolution (const char *method) -{ - sng_glare_resolution iMethod=SNGSS7_GLARE_PC; - if (!method || (strlen (method) <=0) ) { - SS7_ERROR( "Wrong glare resolution parameter, using default. \n" ); - } else { - if (!strcasecmp( method, "PointCode")) { - iMethod = SNGSS7_GLARE_PC; - } else if (!strcasecmp( method, "Down")) { - iMethod = SNGSS7_GLARE_DOWN; - } else if (!strcasecmp( method, "Control")) { - iMethod = SNGSS7_GLARE_CONTROL; - } else { - SS7_ERROR( "Wrong glare resolution parameter, using default. \n" ); - iMethod = SNGSS7_GLARE_PC; - } - } - g_ftdm_sngss7_data.cfg.glareResolution = iMethod; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_sng_gen(ftdm_conf_node_t *sng_gen) -{ - ftdm_conf_parameter_t *parm = sng_gen->parameters; - int num_parms = sng_gen->n_parameters; - int i = 0; - - /* Set the transparent_iam_max_size to default value */ - g_ftdm_sngss7_data.cfg.transparent_iam_max_size=800; - g_ftdm_sngss7_data.cfg.force_inr = 0; - - /* extract all the information from the parameters */ - for (i = 0; i < num_parms; i++) { - if (!strcasecmp(parm->var, "procId")) { - g_ftdm_sngss7_data.cfg.procId = atoi(parm->val); - SS7_DEBUG("Found a procId = %d\n", g_ftdm_sngss7_data.cfg.procId); - } - else if (!strcasecmp(parm->var, "license")) { - ftdm_set_string(g_ftdm_sngss7_data.cfg.license, parm->val); - snprintf(g_ftdm_sngss7_data.cfg.signature, sizeof(g_ftdm_sngss7_data.cfg.signature), "%s.sig", parm->val); - SS7_DEBUG("Found license file = %s\n", g_ftdm_sngss7_data.cfg.license); - SS7_DEBUG("Found signature file = %s\n", g_ftdm_sngss7_data.cfg.signature); - } - else if (!strcasecmp(parm->var, "transparent_iam_max_size")) { - g_ftdm_sngss7_data.cfg.transparent_iam_max_size = atoi(parm->val); - SS7_DEBUG("Found a transparent_iam max size = %d\n", g_ftdm_sngss7_data.cfg.transparent_iam_max_size); - } - else if (!strcasecmp(parm->var, "glare-reso")) { - ftmod_ss7_set_glare_resolution (parm->val); - SS7_DEBUG("Found glare resolution configuration = %d %s\n", g_ftdm_sngss7_data.cfg.glareResolution, parm->val ); - } - else if (!strcasecmp(parm->var, "force-inr")) { - if (ftdm_true(parm->val)) { - g_ftdm_sngss7_data.cfg.force_inr = 1; - } else { - g_ftdm_sngss7_data.cfg.force_inr = 0; - } - SS7_DEBUG("Found INR force configuration = %s\n", parm->val ); - } - else { - SS7_ERROR("Found an invalid parameter \"%s\"!\n", parm->val); - return FTDM_FAIL; - } - - /* move to the next parmeter */ - parm = parm + 1; - } /* for (i = 0; i < num_parms; i++) */ - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_sng_relay(ftdm_conf_node_t *sng_relay) -{ - ftdm_conf_node_t *relay_chan = NULL; - - /* confirm that we are looking at sng_relay */ - if (strcasecmp(sng_relay->name, "sng_relay")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"sng_relay\"!\n",sng_relay->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"sng_relay\"...\n"); - } - - relay_chan = sng_relay->child; - - if (relay_chan != NULL) { - while (relay_chan != NULL) { - /* try to the parse relay_channel */ - if (ftmod_ss7_parse_relay_channel(relay_chan)) { - SS7_ERROR("Failed to parse \"relay_channels\"!\n"); - return FTDM_FAIL; - } - - /* move on to the next linkset */ - relay_chan = relay_chan->next; - } /* while (relay_chan != NULL) */ - } /* if (relay_chan != NULL) */ - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_relay_channel(ftdm_conf_node_t *relay_chan) -{ - sng_relay_t tmp_chan; - ftdm_conf_parameter_t *parm = relay_chan->parameters; - int num_parms = relay_chan->n_parameters; - int i = 0; - - /* confirm that we are looking at relay_channel */ - if (strcasecmp(relay_chan->name, "relay_channel")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"relay_channel\"!\n",relay_chan->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"relay_channel\"...\n"); - } - - /* initalize the tmp_chan structure */ - memset(&tmp_chan, 0x0, sizeof(tmp_chan)); - - /* extract all the information from the parameters */ - for (i = 0; i < num_parms; i++) { - /**************************************************************************/ - - if (!strcasecmp(parm->var, "name")) { - /**********************************************************************/ - strcpy((char *)tmp_chan.name, parm->val); - SS7_DEBUG("Found an relay_channel named = %s\n", tmp_chan.name); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "type")) { - /**********************************************************************/ - if (!strcasecmp(parm->val, "listen")) { - tmp_chan.type = LRY_CT_TCP_LISTEN; - SS7_DEBUG("Found a type = LISTEN\n"); - } else if (!strcasecmp(parm->val, "server")) { - tmp_chan.type = LRY_CT_TCP_SERVER; - SS7_DEBUG("Found a type = SERVER\n"); - } else if (!strcasecmp(parm->val, "client")) { - tmp_chan.type = LRY_CT_TCP_CLIENT; - SS7_DEBUG("Found a type = CLIENT\n"); - } else { - SS7_ERROR("Found an invalid \"type\" = %s\n", parm->var); - return FTDM_FAIL; - } - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "hostname")) { - /**********************************************************************/ - strcpy((char *)tmp_chan.hostname, parm->val); - SS7_DEBUG("Found a hostname = %s\n", tmp_chan.hostname); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "port")) { - /**********************************************************************/ - tmp_chan.port = atoi(parm->val); - SS7_DEBUG("Found a port = %d\n", tmp_chan.port); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "procId")) { - /**********************************************************************/ - tmp_chan.procId = atoi(parm->val); - SS7_DEBUG("Found a procId = %d\n", tmp_chan.procId); - /**********************************************************************/ - } else { - /**********************************************************************/ - SS7_ERROR("Found an invalid parameter \"%s\"!\n", parm->val); - return FTDM_FAIL; - /**********************************************************************/ - } - - /* move to the next parmeter */ - parm = parm + 1; - } /* for (i = 0; i < num_parms; i++) */ - - /* store the channel in the global structure */ - ftmod_ss7_fill_in_relay_channel(&tmp_chan); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_mtp1_links(ftdm_conf_node_t *mtp1_links) -{ - ftdm_conf_node_t *mtp1_link = NULL; - - /* confirm that we are looking at mtp1_links */ - if (strcasecmp(mtp1_links->name, "mtp1_links")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp1_links\"!\n",mtp1_links->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"mtp1_links\"...\n"); - } - - /* extract the mtp_links */ - mtp1_link = mtp1_links->child; - - /* run through all of the links found */ - while (mtp1_link != NULL) { - /* try to the parse mtp_link */ - if (ftmod_ss7_parse_mtp1_link(mtp1_link)) { - SS7_ERROR("Failed to parse \"mtp1_link\"!\n"); - return FTDM_FAIL; - } - - /* move on to the next link */ - mtp1_link = mtp1_link->next; - - } /* while (mtp_linkset != NULL) */ - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_mtp1_link(ftdm_conf_node_t *mtp1_link) -{ - sng_mtp1_link_t mtp1Link; - ftdm_conf_parameter_t *parm = mtp1_link->parameters; - int num_parms = mtp1_link->n_parameters; - int i; - - /* initalize the mtp1Link structure */ - memset(&mtp1Link, 0x0, sizeof(mtp1Link)); - - /* confirm that we are looking at an mtp_link */ - if (strcasecmp(mtp1_link->name, "mtp1_link")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp1_link\"!\n",mtp1_link->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"mtp1_link\"...\n"); - } - - for (i = 0; i < num_parms; i++) { - /**************************************************************************/ - - if (!strcasecmp(parm->var, "name")) { - /**********************************************************************/ - strcpy((char *)mtp1Link.name, parm->val); - SS7_DEBUG("Found an mtp1_link named = %s\n", mtp1Link.name); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "id")) { - /**********************************************************************/ - mtp1Link.id = atoi(parm->val); - SS7_DEBUG("Found an mtp1_link id = %d\n", mtp1Link.id); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "span")) { - /**********************************************************************/ - mtp1Link.span = atoi(parm->val); - SS7_DEBUG("Found an mtp1_link span = %d\n", mtp1Link.span); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "chan")) { - /**********************************************************************/ - mtp1Link.chan = atoi(parm->val); - SS7_DEBUG("Found an mtp1_link chan = %d\n", mtp1Link.chan); - /**********************************************************************/ - } else { - /**********************************************************************/ - SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val); - return FTDM_FAIL; - /**********************************************************************/ - } - - /* move to the next parmeter */ - parm = parm + 1; - - /**************************************************************************/ - } /* for (i = 0; i < num_parms; i++) */ - - /* store the link in global structure */ - ftmod_ss7_fill_in_mtp1_link(&mtp1Link); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_mtp2_links(ftdm_conf_node_t *mtp2_links) -{ - ftdm_conf_node_t *mtp2_link = NULL; - - /* confirm that we are looking at mtp2_links */ - if (strcasecmp(mtp2_links->name, "mtp2_links")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp2_links\"!\n",mtp2_links->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"mtp2_links\"...\n"); - } - - /* extract the mtp_links */ - mtp2_link = mtp2_links->child; - - /* run through all of the links found */ - while (mtp2_link != NULL) { - /* try to the parse mtp_linkset */ - if (ftmod_ss7_parse_mtp2_link(mtp2_link)) { - SS7_ERROR("Failed to parse \"mtp2_link\"!\n"); - return FTDM_FAIL; - } - - /* move on to the next link */ - mtp2_link = mtp2_link->next; - - } /* while (mtp_linkset != NULL) */ - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_mtp2_link(ftdm_conf_node_t *mtp2_link) -{ - sng_mtp2_link_t mtp2Link; - ftdm_conf_parameter_t *parm = mtp2_link->parameters; - int num_parms = mtp2_link->n_parameters; - int i; - int ret; - - /* initalize the mtp1Link structure */ - memset(&mtp2Link, 0x0, sizeof(mtp2Link)); - - /* confirm that we are looking at an mtp2_link */ - if (strcasecmp(mtp2_link->name, "mtp2_link")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp2_link\"!\n",mtp2_link->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"mtp2_link\"...\n"); - } - - for (i = 0; i < num_parms; i++) { - /**************************************************************************/ - - if (!strcasecmp(parm->var, "name")) { - /**********************************************************************/ - strcpy((char *)mtp2Link.name, parm->val); - SS7_DEBUG("Found an mtp2_link named = %s\n", mtp2Link.name); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "id")) { - /**********************************************************************/ - mtp2Link.id = atoi(parm->val); - SS7_DEBUG("Found an mtp2_link id = %d\n", mtp2Link.id); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "mtp1Id")) { - /**********************************************************************/ - mtp2Link.mtp1Id = atoi(parm->val); - SS7_DEBUG("Found an mtp2_link mtp1Id = %d\n", mtp2Link.mtp1Id); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "errorType")) { - /**********************************************************************/ - ret = find_mtp2_error_type_in_map(parm->val); - if (ret == -1) { - SS7_ERROR("Found an invalid mtp2_link errorType = %s\n", parm->var); - return FTDM_FAIL; - } else { - mtp2Link.errorType = sng_mtp2_error_type_map[ret].tril_type; - SS7_DEBUG("Found an mtp2_link errorType = %s\n", sng_mtp2_error_type_map[ret].sng_type); - } - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "lssuLength")) { - /**********************************************************************/ - mtp2Link.lssuLength = atoi(parm->val); - SS7_DEBUG("Found an mtp2_link lssuLength = %d\n", mtp2Link.lssuLength); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "linkType")) { - /**********************************************************************/ - ret = find_link_type_in_map(parm->val); - if (ret == -1) { - SS7_ERROR("Found an invalid mtp2_link linkType = %s\n", parm->var); - return FTDM_FAIL; - } else { - mtp2Link.linkType = sng_link_type_map[ret].tril_mtp2_type; - SS7_DEBUG("Found an mtp2_link linkType = %s\n", sng_link_type_map[ret].sng_type); - } - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t1")) { - /**********************************************************************/ - mtp2Link.t1 = atoi(parm->val); - SS7_DEBUG("Found an mtp2 t1 = \"%d\"\n",mtp2Link.t1); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t2")) { - /**********************************************************************/ - mtp2Link.t2 = atoi(parm->val); - SS7_DEBUG("Found an mtp2 t2 = \"%d\"\n",mtp2Link.t2); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t3")) { - /**********************************************************************/ - mtp2Link.t3 = atoi(parm->val); - SS7_DEBUG("Found an mtp2 t3 = \"%d\"\n",mtp2Link.t3); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t4n")) { - /**********************************************************************/ - mtp2Link.t4n = atoi(parm->val); - SS7_DEBUG("Found an mtp2 t4n = \"%d\"\n",mtp2Link.t4n); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t4e")) { - /**********************************************************************/ - mtp2Link.t4e = atoi(parm->val); - SS7_DEBUG("Found an mtp2 t4e = \"%d\"\n",mtp2Link.t4e); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t5")) { - /**********************************************************************/ - mtp2Link.t5 = atoi(parm->val); - SS7_DEBUG("Found an mtp2 t5 = \"%d\"\n",mtp2Link.t5); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t6")) { - /**********************************************************************/ - mtp2Link.t6 = atoi(parm->val); - SS7_DEBUG("Found an mtp2 t6 = \"%d\"\n",mtp2Link.t6); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t7")) { - /**********************************************************************/ - mtp2Link.t7 = atoi(parm->val); - SS7_DEBUG("Found an mtp2 t7 = \"%d\"\n",mtp2Link.t7); - /**********************************************************************/ - } else { - /**********************************************************************/ - SS7_ERROR("Found an invalid parameter \"%s\"!\n", parm->val); - return FTDM_FAIL; - /**********************************************************************/ - } - - /* move to the next parmeter */ - parm = parm + 1; - - /**************************************************************************/ - } /* for (i = 0; i < num_parms; i++) */ - - /* store the link in global structure */ - ftmod_ss7_fill_in_mtp2_link(&mtp2Link); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_mtp3_links(ftdm_conf_node_t *mtp3_links) -{ - ftdm_conf_node_t *mtp3_link = NULL; - - /* confirm that we are looking at mtp3_links */ - if (strcasecmp(mtp3_links->name, "mtp3_links")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp3_links\"!\n",mtp3_links->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"mtp3_links\"...\n"); - } - - /* extract the mtp_links */ - mtp3_link = mtp3_links->child; - - /* run through all of the links found */ - while (mtp3_link != NULL) { - /* try to the parse mtp_linkset */ - if (ftmod_ss7_parse_mtp3_link(mtp3_link)) { - SS7_ERROR("Failed to parse \"mtp3_link\"!\n"); - return FTDM_FAIL; - } - - /* move on to the next link */ - mtp3_link = mtp3_link->next; - - } /* while (mtp_linkset != NULL) */ - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_mtp3_link(ftdm_conf_node_t *mtp3_link) -{ - sng_mtp3_link_t mtp3Link; - ftdm_conf_parameter_t *parm = mtp3_link->parameters; - int num_parms = mtp3_link->n_parameters; - int i; - int ret; - - /* initalize the mtp3Link structure */ - memset(&mtp3Link, 0x0, sizeof(mtp3Link)); - - /* confirm that we are looking at an mtp_link */ - if (strcasecmp(mtp3_link->name, "mtp3_link")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp3_link\"!\n",mtp3_link->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"mtp3_link\"...\n"); - } - - for (i = 0; i < num_parms; i++) { - /**************************************************************************/ - if (!strcasecmp(parm->var, "name")) { - /**********************************************************************/ - strcpy((char *)mtp3Link.name, parm->val); - SS7_DEBUG("Found an mtp3_link named = %s\n", mtp3Link.name); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "id")) { - /**********************************************************************/ - mtp3Link.id = atoi(parm->val); - SS7_DEBUG("Found an mtp3_link id = %d\n", mtp3Link.id); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "mtp2Id")) { - /**********************************************************************/ - mtp3Link.mtp2Id = atoi(parm->val); - SS7_DEBUG("Found an mtp3_link mtp2Id = %d\n", mtp3Link.mtp2Id); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "mtp2ProcId")) { - /**********************************************************************/ - mtp3Link.mtp2ProcId = atoi(parm->val); - SS7_DEBUG("Found an mtp3_link mtp2ProcId = %d\n", mtp3Link.mtp2ProcId); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "priority")) { - /**********************************************************************/ - mtp3Link.priority = atoi(parm->val); - SS7_DEBUG("Found an mtp3 Link priority = %d\n",mtp3Link.priority); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "linkType")) { - /**********************************************************************/ - ret = find_link_type_in_map(parm->val); - if (ret == -1) { - SS7_ERROR("Found an invalid mtp3_link linkType = %s\n", parm->var); - return FTDM_FAIL; - } else { - mtp3Link.linkType = sng_link_type_map[ret].tril_mtp3_type; - SS7_DEBUG("Found an mtp3_link linkType = %s\n", sng_link_type_map[ret].sng_type); - } - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "switchType")) { - /**********************************************************************/ - ret = find_switch_type_in_map(parm->val); - if (ret == -1) { - SS7_ERROR("Found an invalid mtp3_link switchType = %s\n", parm->var); - return FTDM_FAIL; - } else { - mtp3Link.switchType = sng_switch_type_map[ret].tril_mtp3_type; - SS7_DEBUG("Found an mtp3_link switchType = %s\n", sng_switch_type_map[ret].sng_type); - } - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "ssf")) { - /**********************************************************************/ - ret = find_ssf_type_in_map(parm->val); - if (ret == -1) { - SS7_ERROR("Found an invalid mtp3_link ssf = %s\n", parm->var); - return FTDM_FAIL; - } else { - mtp3Link.ssf = sng_ssf_type_map[ret].tril_type; - SS7_DEBUG("Found an mtp3_link ssf = %s\n", sng_ssf_type_map[ret].sng_type); - } - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "slc")) { - /**********************************************************************/ - mtp3Link.slc = atoi(parm->val); - SS7_DEBUG("Found an mtp3 Link slc = %d\n",mtp3Link.slc); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "linkset")) { - /**********************************************************************/ - mtp3Link.linkSetId = atoi(parm->val); - SS7_DEBUG("Found an mtp3 Link linkset = %d\n",mtp3Link.linkSetId); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t1")) { - /**********************************************************************/ - mtp3Link.t1 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t1 = %d\n",mtp3Link.t1); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t2")) { - /**********************************************************************/ - mtp3Link.t2 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t2 = %d\n",mtp3Link.t2); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t3")) { - /**********************************************************************/ - mtp3Link.t3 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t3 = %d\n",mtp3Link.t3); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t4")) { - /**********************************************************************/ - mtp3Link.t4 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t4 = %d\n",mtp3Link.t4); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t5")) { - /**********************************************************************/ - mtp3Link.t5 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t5 = %d\n",mtp3Link.t5); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t7")) { - /**********************************************************************/ - mtp3Link.t7 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t7 = %d\n",mtp3Link.t7); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t12")) { - /**********************************************************************/ - mtp3Link.t12 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t12 = %d\n",mtp3Link.t12); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t13")) { - /**********************************************************************/ - mtp3Link.t13 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t13 = %d\n",mtp3Link.t13); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t14")) { - /**********************************************************************/ - mtp3Link.t14 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t14 = %d\n",mtp3Link.t14); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t17")) { - /**********************************************************************/ - mtp3Link.t17 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t17 = %d\n",mtp3Link.t17); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t22")) { - /**********************************************************************/ - mtp3Link.t22 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t22 = %d\n",mtp3Link.t22); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t23")) { - /**********************************************************************/ - mtp3Link.t23 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t23 = %d\n",mtp3Link.t23); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t24")) { - /**********************************************************************/ - mtp3Link.t24 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t24 = %d\n",mtp3Link.t24); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t31")) { - mtp3Link.t31 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t31 = %d\n",mtp3Link.t31); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t32")) { - /**********************************************************************/ - mtp3Link.t32 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t32 = %d\n",mtp3Link.t32); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t33")) { - /**********************************************************************/ - mtp3Link.t33 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t33 = %d\n",mtp3Link.t33); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t34")) { - /**********************************************************************/ - mtp3Link.t34 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t34 = %d\n",mtp3Link.t34); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t35")) { - /**********************************************************************/ - mtp3Link.t35 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t35 = %d\n",mtp3Link.t35); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t36")) { - /**********************************************************************/ - mtp3Link.t36 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t36 = %d\n",mtp3Link.t36); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "t37")) { - /**********************************************************************/ - mtp3Link.t37 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t37 = %d\n",mtp3Link.t37); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "tcraft")) { - /**********************************************************************/ - mtp3Link.tcraft = atoi(parm->val); - SS7_DEBUG("Found an mtp3 tcraft = %d\n",mtp3Link.tcraft); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "tflc")) { - /**********************************************************************/ - mtp3Link.tflc = atoi(parm->val); - SS7_DEBUG("Found an mtp3 tflc = %d\n",mtp3Link.tflc); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "tbnd")) { - /**********************************************************************/ - mtp3Link.tbnd = atoi(parm->val); - SS7_DEBUG("Found an mtp3 tbnd = %d\n",mtp3Link.tbnd); - /**********************************************************************/ - } else { - /**********************************************************************/ - SS7_ERROR("Found an invalid parameter %s!\n", parm->val); - return FTDM_FAIL; - /**********************************************************************/ - } - - /* move to the next parmeter */ - parm = parm + 1; - - /**************************************************************************/ - } /* for (i = 0; i < num_parms; i++) */ - - /* store the link in global structure */ - ftmod_ss7_fill_in_mtp3_link(&mtp3Link); - - /* move the linktype, switchtype and ssf to the linkset */ - if (g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].linkType == 0) { - g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].linkType = mtp3Link.linkType; - } else if (g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].linkType != mtp3Link.linkType) { - SS7_ERROR("Trying to add an MTP3 Link to a Linkset with a different linkType: mtp3.id=%d, mtp3.name=%s, mtp3.linktype=%d, linkset.id=%d, linkset.linktype=%d\n", - mtp3Link.id, mtp3Link.name, mtp3Link.linkType, - g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].id, g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].linkType); - return FTDM_FAIL; - } else { - /* should print that all is ok...*/ - } - - if (g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].switchType == 0) { - g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].switchType = mtp3Link.switchType; - } else if (g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].switchType != mtp3Link.switchType) { - SS7_ERROR("Trying to add an MTP3 Link to a Linkset with a different switchType: mtp3.id=%d, mtp3.name=%s, mtp3.switchtype=%d, linkset.id=%d, linkset.switchtype=%d\n", - mtp3Link.id, mtp3Link.name, mtp3Link.switchType, - g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].id, g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].switchType); - return FTDM_FAIL; - } else { - /* should print that all is ok...*/ - } - - if (g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].ssf == 0) { - g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].ssf = mtp3Link.ssf; - } else if (g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].ssf != mtp3Link.ssf) { - SS7_ERROR("Trying to add an MTP3 Link to a Linkset with a different ssf: mtp3.id=%d, mtp3.name=%s, mtp3.ssf=%d, linkset.id=%d, linkset.ssf=%d\n", - mtp3Link.id, mtp3Link.name, mtp3Link.ssf, - g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].id, g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].ssf); - return FTDM_FAIL; - } else { - /* should print that all is ok...*/ - } - - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_mtp_linksets(ftdm_conf_node_t *mtp_linksets) -{ - ftdm_conf_node_t *mtp_linkset = NULL; - - /* confirm that we are looking at mtp_linksets */ - if (strcasecmp(mtp_linksets->name, "mtp_linksets")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_linksets\"!\n",mtp_linksets->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"mtp_linksets\"...\n"); - } - - /* extract the mtp_links */ - mtp_linkset = mtp_linksets->child; - - /* run through all of the mtp_linksets found */ - while (mtp_linkset != NULL) { - /* try to the parse mtp_linkset */ - if (ftmod_ss7_parse_mtp_linkset(mtp_linkset)) { - SS7_ERROR("Failed to parse \"mtp_linkset\"!\n"); - return FTDM_FAIL; - } - - /* move on to the next linkset */ - mtp_linkset = mtp_linkset->next; - - } /* while (mtp_linkset != NULL) */ - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_mtp_linkset(ftdm_conf_node_t *mtp_linkset) -{ - sng_link_set_t mtpLinkSet; - ftdm_conf_parameter_t *parm = mtp_linkset->parameters; - int num_parms = mtp_linkset->n_parameters; - int i; - - /* initalize the mtpLinkSet structure */ - memset(&mtpLinkSet, 0x0, sizeof(mtpLinkSet)); - - /* confirm that we are looking at mtp_linkset */ - if (strcasecmp(mtp_linkset->name, "mtp_linkset")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_linkset\"!\n",mtp_linkset->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"mtp_linkset\"...\n"); - } - - /* extract all the information from the parameters */ - for (i = 0; i < num_parms; i++) { - /**************************************************************************/ - - if (!strcasecmp(parm->var, "name")) { - /**********************************************************************/ - strcpy((char *)mtpLinkSet.name, parm->val); - SS7_DEBUG("Found an mtpLinkSet named = %s\n", mtpLinkSet.name); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "id")) { - /**********************************************************************/ - mtpLinkSet.id = atoi(parm->val); - SS7_DEBUG("Found mtpLinkSet id = %d\n", mtpLinkSet.id); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "apc")) { - /**********************************************************************/ - mtpLinkSet.apc = atoi(parm->val); - SS7_DEBUG("Found mtpLinkSet apc = %d\n", mtpLinkSet.apc); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "minActive")) { - /**********************************************************************/ - mtpLinkSet.minActive = atoi(parm->val); - SS7_DEBUG("Found mtpLinkSet minActive = %d\n", mtpLinkSet.minActive); - /**********************************************************************/ - } else { - /**********************************************************************/ - SS7_ERROR("Found an invalid parameter \"%s\"!\n", parm->val); - return FTDM_FAIL; - /**********************************************************************/ - } - - /* move to the next parmeter */ - parm = parm + 1; - /**************************************************************************/ - } /* for (i = 0; i < num_parms; i++) */ - - ftmod_ss7_fill_in_mtpLinkSet(&mtpLinkSet); - - /* go through all the mtp3 links and fill in the apc */ - i = 1; - while (i < (MAX_MTP_LINKS)) { - if (g_ftdm_sngss7_data.cfg.mtp3Link[i].linkSetId == mtpLinkSet.id) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].apc = mtpLinkSet.apc; - } - - i++; - } - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_mtp_routes(ftdm_conf_node_t *mtp_routes) -{ - ftdm_conf_node_t *mtp_route = NULL; - - /* confirm that we are looking at an mtp_routes */ - if (strcasecmp(mtp_routes->name, "mtp_routes")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_routes\"!\n",mtp_routes->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"mtp_routes\"...\n"); - } - - /* extract the mtp_routes */ - mtp_route = mtp_routes->child; - - while (mtp_route != NULL) { - /* parse the found mtp_route */ - if (ftmod_ss7_parse_mtp_route(mtp_route)) { - SS7_ERROR("Failed to parse \"mtp_route\"\n"); - return FTDM_FAIL; - } - - /* go to the next mtp_route */ - mtp_route = mtp_route->next; - } - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route) -{ - sng_route_t mtpRoute; - ftdm_conf_parameter_t *parm = mtp_route->parameters; - int num_parms = mtp_route->n_parameters; - int i; - sng_link_set_list_t *lnkSet; - - ftdm_conf_node_t *linkset; - int numLinks; - - /* initalize the mtpRoute structure */ - memset(&mtpRoute, 0x0, sizeof(mtpRoute)); - - /* confirm that we are looking at an mtp_link */ - if (strcasecmp(mtp_route->name, "mtp_route")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_route\"!\n",mtp_route->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"mtp_route\"...\n"); - } - - for (i = 0; i < num_parms; i++) { - /**************************************************************************/ - - /* try to match the parameter to what we expect */ - if (!strcasecmp(parm->var, "name")) { - /**********************************************************************/ - strcpy((char *)mtpRoute.name, parm->val); - SS7_DEBUG("Found an mtpRoute named = %s\n", mtpRoute.name); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "id")) { - /**********************************************************************/ - mtpRoute.id = atoi(parm->val); - SS7_DEBUG("Found an mtpRoute id = %d\n", mtpRoute.id); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "dpc")) { - /**********************************************************************/ - mtpRoute.dpc = atoi(parm->val); - SS7_DEBUG("Found an mtpRoute dpc = %d\n", mtpRoute.dpc); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isSTP")) { - /**********************************************************************/ - if (!strcasecmp(parm->val, "no")) { - mtpRoute.isSTP = 0; - SS7_DEBUG("Found an mtpRoute isSTP = no\n"); - } else if (!strcasecmp(parm->val, "yes")) { - mtpRoute.isSTP = 1; - SS7_DEBUG("Found an mtpRoute isSTP = yes\n"); - } else { - SS7_ERROR("Found an invalid parameter for isSTP %s!\n", parm->val); - return FTDM_FAIL; - } - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "mtp3.t6")) { - /**********************************************************************/ - mtpRoute.t6 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t6 = %d\n",mtpRoute.t6); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "mtp3.t8")) { - /**********************************************************************/ - mtpRoute.t8 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t8 = %d\n",mtpRoute.t8); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "mtp3.t10")) { - /**********************************************************************/ - mtpRoute.t10 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t10 = %d\n",mtpRoute.t10); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "mtp3.t11")) { - /**********************************************************************/ - mtpRoute.t11 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t11 = %d\n",mtpRoute.t11); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "mtp3.t15")) { - /**********************************************************************/ - mtpRoute.t15 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t15 = %d\n",mtpRoute.t15); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "mtp3.t16")) { - /**********************************************************************/ - mtpRoute.t16 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t16 = %d\n",mtpRoute.t16); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "mtp3.t18")) { - /**********************************************************************/ - mtpRoute.t18 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t18 = %d\n",mtpRoute.t18); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "mtp3.t19")) { - /**********************************************************************/ - mtpRoute.t19 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t19 = %d\n",mtpRoute.t19); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "mtp3.t21")) { - /**********************************************************************/ - mtpRoute.t21 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t21 = %d\n",mtpRoute.t21); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "mtp3.t25")) { - /**********************************************************************/ - mtpRoute.t25 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t25 = %d\n",mtpRoute.t25); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "mtp3.t26")) { - /**********************************************************************/ - mtpRoute.t26 = atoi(parm->val); - SS7_DEBUG("Found an mtp3 t26 = %d\n",mtpRoute.t26); - /**********************************************************************/ - } else { - /**********************************************************************/ - SS7_ERROR("Found an invalid parameter \"%s\"!\n", parm->val); - return FTDM_FAIL; - /**********************************************************************/ - } - - /* move to the next parameter */ - parm = parm + 1; - } - - /* fill in the rest of the values in the mtpRoute struct */ - mtpRoute.nwId = 0; - mtpRoute.cmbLinkSetId = mtpRoute.id; - - /* parse in the list of linksets this route is reachable by */ - linkset = mtp_route->child->child; - - /* initalize the link-list of linkSet Ids */ - lnkSet = &mtpRoute.lnkSets; - - while (linkset != NULL) { - /**************************************************************************/ - /* extract the linkset Id */ - lnkSet->lsId = atoi(linkset->parameters->val); - - if (g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].id != 0) { - SS7_DEBUG("Found mtpRoute linkset id = %d that is valid\n",lnkSet->lsId); - } else { - SS7_ERROR("Found mtpRoute linkset id = %d that is invalid\n",lnkSet->lsId); - goto move_along; - } - - /* pull up the linktype, switchtype, and SSF from the linkset */ - mtpRoute.linkType = g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].linkType; - mtpRoute.switchType = g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].switchType; - mtpRoute.ssf = g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].ssf; - - /* extract the number of cmbLinkSetId aleady on this linkset */ - numLinks = g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].numLinks; - - /* add this routes cmbLinkSetId to the list */ - g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].links[numLinks] = mtpRoute.cmbLinkSetId; - - /* increment the number of cmbLinkSets on this linkset */ - g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].numLinks++; - - /* update the linked list */ - lnkSet->next = ftdm_malloc(sizeof(sng_link_set_list_t)); - lnkSet = lnkSet->next; - lnkSet->lsId = 0; - lnkSet->next = NULL; - -move_along: - /* move to the next linkset element */ - linkset = linkset->next; - /**************************************************************************/ - } /* while (linkset != null) */ - - - ftmod_ss7_fill_in_mtp3_route(&mtpRoute); - - ftmod_ss7_fill_in_nsap(&mtpRoute); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_isup_interfaces(ftdm_conf_node_t *isup_interfaces) -{ - ftdm_conf_node_t *isup_interface = NULL; - - /* confirm that we are looking at isup_interfaces */ - if (strcasecmp(isup_interfaces->name, "isup_interfaces")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"isup_interfaces\"!\n",isup_interfaces->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"isup_interfaces\"...\n"); - } - - /* extract the isup_interfaces */ - isup_interface = isup_interfaces->child; - - while (isup_interface != NULL) { - /* parse the found mtp_route */ - if (ftmod_ss7_parse_isup_interface(isup_interface)) { - SS7_ERROR("Failed to parse \"isup_interface\"\n"); - return FTDM_FAIL; - } - - /* go to the next mtp_route */ - isup_interface = isup_interface->next; - } - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface) -{ - sng_isup_inf_t sng_isup; - sng_isap_t sng_isap; - sng_link_set_list_t *lnkSet; - ftdm_conf_parameter_t *parm = isup_interface->parameters; - int num_parms = isup_interface->n_parameters; - int i; - int ret; - - /* initalize the isup intf and isap structure */ - memset(&sng_isup, 0x0, sizeof(sng_isup)); - memset(&sng_isap, 0x0, sizeof(sng_isap)); - - /* confirm that we are looking at an mtp_link */ - if (strcasecmp(isup_interface->name, "isup_interface")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"isup_interface\"!\n",isup_interface->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"isup_interface\"...\n"); - } - - - for (i = 0; i < num_parms; i++) { - /**************************************************************************/ - - /* try to match the parameter to what we expect */ - if (!strcasecmp(parm->var, "name")) { - /**********************************************************************/ - strcpy((char *)sng_isup.name, parm->val); - SS7_DEBUG("Found an isup_interface named = %s\n", sng_isup.name); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "id")) { - /**********************************************************************/ - sng_isup.id = atoi(parm->val); - SS7_DEBUG("Found an isup id = %d\n", sng_isup.id); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "spc")) { - /**********************************************************************/ - sng_isup.spc = atoi(parm->val); - SS7_DEBUG("Found an isup SPC = %d\n", sng_isup.spc); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "mtprouteId")) { - /**********************************************************************/ - sng_isup.mtpRouteId=atoi(parm->val); - - SS7_DEBUG("Found an isup mptRouteId = %d\n", sng_isup.mtpRouteId); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "ssf")) { - /**********************************************************************/ - ret = find_ssf_type_in_map(parm->val); - if (ret == -1) { - SS7_ERROR("Found an invalid isup ssf = %s\n", parm->var); - return FTDM_FAIL; - } else { - sng_isup.ssf = sng_ssf_type_map[ret].tril_type; - sng_isap.ssf = sng_ssf_type_map[ret].tril_type; - SS7_DEBUG("Found an isup ssf = %s\n", sng_ssf_type_map[ret].sng_type); - } - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t1")) { - /**********************************************************************/ - sng_isap.t1 = atoi(parm->val); - SS7_DEBUG("Found isup t1 = %d\n",sng_isap.t1); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t2")) { - /**********************************************************************/ - sng_isap.t2 = atoi(parm->val); - SS7_DEBUG("Found isup t2 = %d\n",sng_isap.t2); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t4")) { - /**********************************************************************/ - sng_isup.t4 = atoi(parm->val); - SS7_DEBUG("Found isup t4 = %d\n",sng_isup.t4); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t5")) { - /**********************************************************************/ - sng_isap.t5 = atoi(parm->val); - SS7_DEBUG("Found isup t5 = %d\n",sng_isap.t5); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t6")) { - /**********************************************************************/ - sng_isap.t6 = atoi(parm->val); - SS7_DEBUG("Found isup t6 = %d\n",sng_isap.t6); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t7")) { - /**********************************************************************/ - sng_isap.t7 = atoi(parm->val); - SS7_DEBUG("Found isup t7 = %d\n",sng_isap.t7); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t8")) { - /**********************************************************************/ - sng_isap.t8 = atoi(parm->val); - SS7_DEBUG("Found isup t8 = %d\n",sng_isap.t8); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t9")) { - /**********************************************************************/ - sng_isap.t9 = atoi(parm->val); - SS7_DEBUG("Found isup t9 = %d\n",sng_isap.t9); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t11")) { - /**********************************************************************/ - sng_isup.t11 = atoi(parm->val); - SS7_DEBUG("Found isup t11 = %d\n",sng_isup.t11); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t18")) { - /**********************************************************************/ - sng_isup.t18 = atoi(parm->val); - SS7_DEBUG("Found isup t18 = %d\n",sng_isup.t18); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t19")) { - /**********************************************************************/ - sng_isup.t19 = atoi(parm->val); - SS7_DEBUG("Found isup t19 = %d\n",sng_isup.t19); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t20")) { - /**********************************************************************/ - sng_isup.t20 = atoi(parm->val); - SS7_DEBUG("Found isup t20 = %d\n",sng_isup.t20); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t21")) { - /**********************************************************************/ - sng_isup.t21 = atoi(parm->val); - SS7_DEBUG("Found isup t21 = %d\n",sng_isup.t21); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t22")) { - /**********************************************************************/ - sng_isup.t22 = atoi(parm->val); - SS7_DEBUG("Found isup t22 = %d\n",sng_isup.t22); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t23")) { - /**********************************************************************/ - sng_isup.t23 = atoi(parm->val); - SS7_DEBUG("Found isup t23 = %d\n",sng_isup.t23); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t24")) { - /**********************************************************************/ - sng_isup.t24 = atoi(parm->val); - SS7_DEBUG("Found isup t24 = %d\n",sng_isup.t24); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t25")) { - /**********************************************************************/ - sng_isup.t25 = atoi(parm->val); - SS7_DEBUG("Found isup t25 = %d\n",sng_isup.t25); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t26")) { - /**********************************************************************/ - sng_isup.t26 = atoi(parm->val); - SS7_DEBUG("Found isup t26 = %d\n",sng_isup.t26); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t28")) { - /**********************************************************************/ - sng_isup.t28 = atoi(parm->val); - SS7_DEBUG("Found isup t28 = %d\n",sng_isup.t28); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t29")) { - /**********************************************************************/ - sng_isup.t29 = atoi(parm->val); - SS7_DEBUG("Found isup t29 = %d\n",sng_isup.t29); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t30")) { - /**********************************************************************/ - sng_isup.t30 = atoi(parm->val); - SS7_DEBUG("Found isup t30 = %d\n",sng_isup.t30); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t31")) { - /**********************************************************************/ - sng_isap.t31 = atoi(parm->val); - SS7_DEBUG("Found isup t31 = %d\n",sng_isap.t31); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t32")) { - /**********************************************************************/ - sng_isup.t32 = atoi(parm->val); - SS7_DEBUG("Found isup t32 = %d\n",sng_isup.t32); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t33")) { - /**********************************************************************/ - sng_isap.t33 = atoi(parm->val); - SS7_DEBUG("Found isup t33 = %d\n",sng_isap.t33); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t34")) { - /**********************************************************************/ - sng_isap.t34 = atoi(parm->val); - SS7_DEBUG("Found isup t34 = %d\n",sng_isap.t34); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t36")) { - /**********************************************************************/ - sng_isap.t36 = atoi(parm->val); - SS7_DEBUG("Found isup t36 = %d\n",sng_isap.t36); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t37")) { - /**********************************************************************/ - sng_isup.t37 = atoi(parm->val); - SS7_DEBUG("Found isup t37 = %d\n",sng_isup.t37); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t38")) { - /**********************************************************************/ - sng_isup.t38 = atoi(parm->val); - SS7_DEBUG("Found isup t38 = %d\n",sng_isup.t38); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t39")) { - /**********************************************************************/ - sng_isup.t39 = atoi(parm->val); - SS7_DEBUG("Found isup t39 = %d\n",sng_isup.t39); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.tccr")) { - /**********************************************************************/ - sng_isap.tccr = atoi(parm->val); - SS7_DEBUG("Found isup tccr = %d\n",sng_isap.tccr); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.tccrt")) { - /**********************************************************************/ - sng_isap.tccrt = atoi(parm->val); - SS7_DEBUG("Found isup tccrt = %d\n",sng_isap.tccrt); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.tex")) { - /**********************************************************************/ - sng_isap.tex = atoi(parm->val); - SS7_DEBUG("Found isup tex = %d\n",sng_isap.tex); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.tect")) { - /**********************************************************************/ - sng_isap.tect = atoi(parm->val); - SS7_DEBUG("Found isup tect = %d\n",sng_isap.tect); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.tcrm")) { - /**********************************************************************/ - sng_isap.tcrm = atoi(parm->val); - SS7_DEBUG("Found isup tcrm = %d\n",sng_isap.tcrm); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.tcra")) { - /**********************************************************************/ - sng_isap.tcra = atoi(parm->val); - SS7_DEBUG("Found isup tcra = %d\n",sng_isap.tcra); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.tfgr")) { - /**********************************************************************/ - sng_isup.tfgr = atoi(parm->val); - SS7_DEBUG("Found isup tfgr = %d\n",sng_isup.tfgr); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.trelrsp")) { - /**********************************************************************/ - sng_isap.trelrsp = atoi(parm->val); - SS7_DEBUG("Found isup trelrsp = %d\n",sng_isap.trelrsp); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.tfnlrelrsp")) { - /**********************************************************************/ - sng_isap.tfnlrelrsp = atoi(parm->val); - SS7_DEBUG("Found isup tfnlrelrsp = %d\n",sng_isap.tfnlrelrsp); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.tfnlrelrsp")) { - /**********************************************************************/ - sng_isap.tfnlrelrsp = atoi(parm->val); - SS7_DEBUG("Found isup tfnlrelrsp = %d\n",sng_isap.tfnlrelrsp); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.tpause")) { - /**********************************************************************/ - sng_isup.tpause = atoi(parm->val); - SS7_DEBUG("Found isup tpause = %d\n",sng_isup.tpause); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.tstaenq")) { - /**********************************************************************/ - sng_isup.tstaenq = atoi(parm->val); - SS7_DEBUG("Found isup tstaenq = %d\n",sng_isup.tstaenq); - /**********************************************************************/ - } else { - /**********************************************************************/ - SS7_ERROR("Found an invalid parameter %s!\n", parm->val); - return FTDM_FAIL; - /**********************************************************************/ - } - - /* move to the next parameter */ - parm = parm + 1; - /**************************************************************************/ - } /* for (i = 0; i < num_parms; i++) */ - - /* default the interface to paused state */ - sngss7_set_flag(&sng_isup, SNGSS7_PAUSED); - - - - /* trickle down the SPC to all sub entities */ - lnkSet = &g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].lnkSets; - while (lnkSet->next != NULL) { - /**************************************************************************/ - /* go through all the links and check if they belong to this linkset*/ - i = 1; - while (i < (MAX_MTP_LINKS)) { - /* check if this link is in the linkset */ - if (g_ftdm_sngss7_data.cfg.mtp3Link[i].linkSetId == lnkSet->lsId) { - /* fill in the spc */ - g_ftdm_sngss7_data.cfg.mtp3Link[i].spc = sng_isup.spc; - } - - i++; - } - - /* move to the next lnkSet */ - lnkSet = lnkSet->next; - /**************************************************************************/ - } /* while (lnkSet->next != NULL) */ - - /* pull values from the lower levels */ - sng_isap.switchType = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].switchType; - - /* fill in the isap */ - ftmod_ss7_fill_in_isap(&sng_isap); - - /* pull values from the lower levels */ - sng_isup.isap = sng_isap.id; - sng_isup.dpc = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].dpc; - sng_isup.switchType = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].switchType; - sng_isup.nwId = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].nwId; - - /* fill in the isup interface */ - ftmod_ss7_fill_in_isup_interface(&sng_isup); - - /* setup the self mtp3 route */ - i = sng_isup.mtpRouteId; - if(ftmod_ss7_fill_in_self_route(sng_isup.spc, - g_ftdm_sngss7_data.cfg.mtpRoute[i].linkType, - g_ftdm_sngss7_data.cfg.mtpRoute[i].switchType, - g_ftdm_sngss7_data.cfg.mtpRoute[i].ssf)) { - - SS7_ERROR("Failed to fill in self route structure!\n"); - return FTDM_FAIL; - - } - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_parse_cc_spans(ftdm_conf_node_t *cc_spans) -{ - ftdm_conf_node_t *cc_span = NULL; - - /* confirm that we are looking at cc_spans */ - if (strcasecmp(cc_spans->name, "cc_spans")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"cc_spans\"!\n",cc_spans->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"cc_spans\"...\n"); - } - - /* extract the cc_spans */ - cc_span = cc_spans->child; - - while (cc_span != NULL) { - /* parse the found cc_span */ - if (ftmod_ss7_parse_cc_span(cc_span)) { - SS7_ERROR("Failed to parse \"cc_span\"\n"); - return FTDM_FAIL; - } - - /* go to the next cc_span */ - cc_span = cc_span->next; - } - - return FTDM_SUCCESS; - -} - -/******************************************************************************/ -static int ftmod_ss7_parse_cc_span(ftdm_conf_node_t *cc_span) -{ - sng_ccSpan_t sng_ccSpan; - ftdm_conf_parameter_t *parm = cc_span->parameters; - int num_parms = cc_span->n_parameters; - int flag_clg_nadi = 0; - int flag_cld_nadi = 0; - int flag_rdnis_nadi = 0; - int flag_loc_nadi = 0; - int i; - int ret; - - /* initalize the ccSpan structure */ - memset(&sng_ccSpan, 0x0, sizeof(sng_ccSpan)); - - - /* confirm that we are looking at an mtp_link */ - if (strcasecmp(cc_span->name, "cc_span")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"cc_span\"!\n",cc_span->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"cc_span\"...\n"); - } - - /* Backward compatible. - * If cpg_on_progress_media is not in the config file - * default the cpg on progress_media to TRUE */ - sng_ccSpan.cpg_on_progress_media=FTDM_TRUE; - /* If transparent_iam_max_size is not set in cc spans - * use the global value */ - sng_ccSpan.transparent_iam_max_size=g_ftdm_sngss7_data.cfg.transparent_iam_max_size; - - - for (i = 0; i < num_parms; i++) { - /**************************************************************************/ - - /* try to match the parameter to what we expect */ - if (!strcasecmp(parm->var, "name")) { - /**********************************************************************/ - strcpy((char *)sng_ccSpan.name, parm->val); - SS7_DEBUG("Found an ccSpan named = %s\n", sng_ccSpan.name); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "id")) { - /**********************************************************************/ - sng_ccSpan.id = atoi(parm->val); - SS7_DEBUG("Found an ccSpan id = %d\n", sng_ccSpan.id); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "procid")) { - /**********************************************************************/ - sng_ccSpan.procId = atoi(parm->val); - SS7_DEBUG("Found an ccSpan procId = %d\n", sng_ccSpan.procId); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "ch_map")) { - /**********************************************************************/ - strcpy(sng_ccSpan.ch_map, parm->val); - SS7_DEBUG("Found channel map %s\n", sng_ccSpan.ch_map); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "typeCntrl")) { - /**********************************************************************/ - ret = find_cic_cntrl_in_map(parm->val); - if (ret == -1) { - SS7_ERROR("Found an invalid ccSpan typeCntrl = %s\n", parm->var); - return FTDM_FAIL; - } else { - sng_ccSpan.typeCntrl = sng_cic_cntrl_type_map[ret].tril_type; - SS7_DEBUG("Found an ccSpan typeCntrl = %s\n", sng_cic_cntrl_type_map[ret].sng_type); - } - } else if (!strcasecmp(parm->var, "itx_auto_reply")) { - sng_ccSpan.itx_auto_reply = ftdm_true(parm->val); - SS7_DEBUG("Found itx_auto_reply %d\n", sng_ccSpan.itx_auto_reply); - } else if (!strcasecmp(parm->var, "transparent_iam")) { -#ifndef HAVE_ZLIB - SS7_CRIT("Cannot enable transparent IAM becauze zlib not installed\n"); -#else - sng_ccSpan.transparent_iam = ftdm_true(parm->val); - SS7_DEBUG("Found transparent_iam %d\n", sng_ccSpan.transparent_iam); -#endif - } else if (!strcasecmp(parm->var, "transparent_iam_max_size")) { - sng_ccSpan.transparent_iam_max_size = atoi(parm->val); - SS7_DEBUG("Found transparent_iam_max_size %d\n", sng_ccSpan.transparent_iam_max_size); - } else if (!strcasecmp(parm->var, "cpg_on_progress_media")) { - sng_ccSpan.cpg_on_progress_media = ftdm_true(parm->val); - SS7_DEBUG("Found cpg_on_progress_media %d\n", sng_ccSpan.cpg_on_progress_media); - } else if (!strcasecmp(parm->var, "cpg_on_progress")) { - sng_ccSpan.cpg_on_progress = ftdm_true(parm->val); - SS7_DEBUG("Found cpg_on_progress %d\n", sng_ccSpan.cpg_on_progress); - } else if (!strcasecmp(parm->var, "cicbase")) { - /**********************************************************************/ - sng_ccSpan.cicbase = atoi(parm->val); - SS7_DEBUG("Found a cicbase = %d\n", sng_ccSpan.cicbase); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup_interface")) { - /**********************************************************************/ - sng_ccSpan.isupInf = atoi(parm->val); - SS7_DEBUG("Found an isup_interface = %d\n",sng_ccSpan.isupInf); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "min_digits")) { - /**********************************************************************/ - sng_ccSpan.min_digits = atoi(parm->val); - SS7_DEBUG("Found a min_digits = %d\n",sng_ccSpan.min_digits); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "clg_nadi")) { - /**********************************************************************/ - /* throw the flag so that we know we got this optional parameter */ - flag_clg_nadi = 1; - sng_ccSpan.clg_nadi = atoi(parm->val); - SS7_DEBUG("Found default CLG_NADI parm->value = %d\n", sng_ccSpan.clg_nadi); - } else if (!strcasecmp(parm->var, "cld_nadi")) { - /* throw the flag so that we know we got this optional parameter */ - flag_cld_nadi = 1; - sng_ccSpan.cld_nadi = atoi(parm->val); - SS7_DEBUG("Found default CLD_NADI parm->value = %d\n", sng_ccSpan.cld_nadi); - } else if (!strcasecmp(parm->var, "rdnis_nadi")) { - /* throw the flag so that we know we got this optional parameter */ - flag_rdnis_nadi = 1; - sng_ccSpan.rdnis_nadi = atoi(parm->val); - SS7_DEBUG("Found default RDNIS_NADI parm->value = %d\n", sng_ccSpan.rdnis_nadi); - } else if (!strcasecmp(parm->var, "obci_bita")) { - if (*parm->val == '1') { - sngss7_set_options(&sng_ccSpan, SNGSS7_ACM_OBCI_BITA); - SS7_DEBUG("Found Optional Backwards Indicator: Bit A (early media) enable option\n"); - } else if (*parm->val == '0') { - sngss7_clear_options(&sng_ccSpan, SNGSS7_ACM_OBCI_BITA); - SS7_DEBUG("Found Optional Backwards Indicator: Bit A (early media) disable option\n"); - } else { - SS7_DEBUG("Invalid parm->value for obci_bita option\n"); - } - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "loc_nadi")) { - /* add location reference number */ - flag_loc_nadi = 1; - sng_ccSpan.loc_nadi = atoi(parm->val); - SS7_DEBUG("Found default LOC_NADI parm->value = %d\n", sng_ccSpan.loc_nadi); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "lpa_on_cot")) { - /**********************************************************************/ - if (*parm->val == '1') { - sngss7_set_options(&sng_ccSpan, SNGSS7_LPA_FOR_COT); - SS7_DEBUG("Found Tx LPA on COT enable option\n"); - } else if (*parm->val == '0') { - sngss7_clear_options(&sng_ccSpan, SNGSS7_LPA_FOR_COT); - SS7_DEBUG("Found Tx LPA on COT disable option\n"); - } else { - SS7_DEBUG("Invalid parm->value for lpa_on_cot option\n"); - } - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t3")) { - /**********************************************************************/ - sng_ccSpan.t3 = atoi(parm->val); - SS7_DEBUG("Found isup t3 = %d\n", sng_ccSpan.t3); - } else if (!strcasecmp(parm->var, "isup.t10")) { - /**********************************************************************/ - sng_ccSpan.t10 = atoi(parm->val); - SS7_DEBUG("Found isup t10 = %d\n", sng_ccSpan.t10); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t12")) { - /**********************************************************************/ - sng_ccSpan.t12 = atoi(parm->val); - SS7_DEBUG("Found isup t12 = %d\n", sng_ccSpan.t12); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t13")) { - /**********************************************************************/ - sng_ccSpan.t13 = atoi(parm->val); - SS7_DEBUG("Found isup t13 = %d\n", sng_ccSpan.t13); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t14")) { - /**********************************************************************/ - sng_ccSpan.t14 = atoi(parm->val); - SS7_DEBUG("Found isup t14 = %d\n", sng_ccSpan.t14); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t15")) { - /**********************************************************************/ - sng_ccSpan.t15 = atoi(parm->val); - SS7_DEBUG("Found isup t15 = %d\n", sng_ccSpan.t15); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t16")) { - /**********************************************************************/ - sng_ccSpan.t16 = atoi(parm->val); - SS7_DEBUG("Found isup t16 = %d\n", sng_ccSpan.t16); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t17")) { - /**********************************************************************/ - sng_ccSpan.t17 = atoi(parm->val); - SS7_DEBUG("Found isup t17 = %d\n", sng_ccSpan.t17); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t35")) { - /**********************************************************************/ - sng_ccSpan.t35 = atoi(parm->val); - SS7_DEBUG("Found isup t35 = %d\n",sng_ccSpan.t35); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.t39")) { - /**********************************************************************/ - sng_ccSpan.t39 = atoi(parm->val); - SS7_DEBUG("Found isup t39 = %d\n",sng_ccSpan.t39); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isup.tval")) { - /**********************************************************************/ - sng_ccSpan.tval = atoi(parm->val); - SS7_DEBUG("Found isup tval = %d\n", sng_ccSpan.tval); - /**********************************************************************/ - } else { - /**********************************************************************/ - SS7_ERROR("Found an invalid parameter %s!\n", parm->var); - return FTDM_FAIL; - /**********************************************************************/ - } - - /* move to the next parameter */ - parm = parm + 1; - /**************************************************************************/ - } /* for (i = 0; i < num_parms; i++) */ - - /* check if the user filled in a nadi value by looking at flag */ - if (!flag_cld_nadi) { - /* default the nadi value to national */ - sng_ccSpan.cld_nadi = 0x03; - } - - if (!flag_clg_nadi) { - /* default the nadi value to national */ - sng_ccSpan.clg_nadi = 0x03; - } - - if (!flag_rdnis_nadi) { - /* default the nadi value to national */ - sng_ccSpan.rdnis_nadi = 0x03; - } - - if (!flag_loc_nadi) { - /* default the nadi value to national */ - sng_ccSpan.loc_nadi = 0x03; - } - - /* pull up the SSF and Switchtype from the isup interface */ - sng_ccSpan.ssf = g_ftdm_sngss7_data.cfg.isupIntf[sng_ccSpan.isupInf].ssf; - sng_ccSpan.switchType = g_ftdm_sngss7_data.cfg.isupIntf[sng_ccSpan.isupInf].switchType; - - /* add this span to our global listing */ - ftmod_ss7_fill_in_ccSpan(&sng_ccSpan); - - /* make sure the isup interface structure has something in it */ - if (g_ftdm_sngss7_data.cfg.isupIntf[sng_ccSpan.isupInf].id == 0) { - /* fill in the id, so that we know it exists */ - g_ftdm_sngss7_data.cfg.isupIntf[sng_ccSpan.isupInf].id = sng_ccSpan.isupInf; - - /* default the status to PAUSED */ - sngss7_set_flag(&g_ftdm_sngss7_data.cfg.isupIntf[sng_ccSpan.isupInf], SNGSS7_PAUSED); - } - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_fill_in_relay_channel(sng_relay_t *relay_channel) -{ - int i; - - /* go through all the existing channels and see if we find a match */ - i = 1; - while (g_ftdm_sngss7_data.cfg.relay[i].id != 0) { - if ((g_ftdm_sngss7_data.cfg.relay[i].type == relay_channel->type) && - (g_ftdm_sngss7_data.cfg.relay[i].port == relay_channel->port) && - (g_ftdm_sngss7_data.cfg.relay[i].procId == relay_channel->procId) && - (!strcasecmp(g_ftdm_sngss7_data.cfg.relay[i].hostname, relay_channel->hostname))) { - - /* we have a match so break out of this loop */ - break; - } - /* move on to the next one */ - i++; - } - - /* if the id value is 0 that means we didn't find the relay channel */ - if (g_ftdm_sngss7_data.cfg.relay[i].id == 0) { - relay_channel->id = i; - SS7_DEBUG("found new relay channel on type:%d, hostname:%s, port:%d, procId:%d, id = %d\n", - relay_channel->type, - relay_channel->hostname, - relay_channel->port, - relay_channel->procId, - relay_channel->id); - sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY_PRESENT); - } else { - relay_channel->id = i; - SS7_DEBUG("found existing relay channel on type:%d, hostname:%s, port:%d, procId:%d, id = %d\n", - relay_channel->type, - relay_channel->hostname, - relay_channel->port, - relay_channel->procId, - relay_channel->id); - } - - g_ftdm_sngss7_data.cfg.relay[i].id = relay_channel->id; - g_ftdm_sngss7_data.cfg.relay[i].type = relay_channel->type; - g_ftdm_sngss7_data.cfg.relay[i].port = relay_channel->port; - g_ftdm_sngss7_data.cfg.relay[i].procId = relay_channel->procId; - strcpy(g_ftdm_sngss7_data.cfg.relay[i].hostname, relay_channel->hostname); - strcpy(g_ftdm_sngss7_data.cfg.relay[i].name, relay_channel->name); - - /* if this is THE listen channel grab the procId and use it */ - if (relay_channel->type == LRY_CT_TCP_LISTEN) { - g_ftdm_sngss7_data.cfg.procId = relay_channel->procId; - } - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_fill_in_mtp1_link(sng_mtp1_link_t *mtp1Link) -{ - int i = mtp1Link->id; - - /* check if this id value has been used already */ - if (g_ftdm_sngss7_data.cfg.mtp1Link[i].id == 0) { - SS7_DEBUG("Found new MTP1 Link: id=%d, name=%s\n", mtp1Link->id, mtp1Link->name); - sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP1_PRESENT); - } else { - SS7_DEBUG("Found an existing MTP1 Link: id=%d, name=%s (old name=%s)\n", - mtp1Link->id, - mtp1Link->name, - g_ftdm_sngss7_data.cfg.mtp1Link[i].name); - } - - /* copy over the values */ - strcpy((char *)g_ftdm_sngss7_data.cfg.mtp1Link[i].name, (char *)mtp1Link->name); - - g_ftdm_sngss7_data.cfg.mtp1Link[i].id = mtp1Link->id; - g_ftdm_sngss7_data.cfg.mtp1Link[i].span = mtp1Link->span; - g_ftdm_sngss7_data.cfg.mtp1Link[i].chan = mtp1Link->chan; - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_fill_in_mtp2_link(sng_mtp2_link_t *mtp2Link) -{ - int i = mtp2Link->id; - - /* check if this id value has been used already */ - if (g_ftdm_sngss7_data.cfg.mtp2Link[i].id == 0) { - SS7_DEBUG("Found new MTP2 Link: id=%d, name=%s\n", mtp2Link->id, mtp2Link->name); - sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2_PRESENT); - } else { - SS7_DEBUG("Found an existing MTP2 Link: id=%d, name=%s (old name=%s)\n", - mtp2Link->id, - mtp2Link->name, - g_ftdm_sngss7_data.cfg.mtp2Link[i].name); - } - - /* copy over the values */ - strcpy((char *)g_ftdm_sngss7_data.cfg.mtp2Link[i].name, (char *)mtp2Link->name); - - g_ftdm_sngss7_data.cfg.mtp2Link[i].id = mtp2Link->id; - g_ftdm_sngss7_data.cfg.mtp2Link[i].lssuLength = mtp2Link->lssuLength; - g_ftdm_sngss7_data.cfg.mtp2Link[i].errorType = mtp2Link->errorType; - g_ftdm_sngss7_data.cfg.mtp2Link[i].linkType = mtp2Link->linkType; - g_ftdm_sngss7_data.cfg.mtp2Link[i].mtp1Id = mtp2Link->mtp1Id; - g_ftdm_sngss7_data.cfg.mtp2Link[i].mtp1ProcId = mtp2Link->mtp1ProcId; - - if ( mtp2Link->t1 != 0 ) { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t1 = mtp2Link->t1; - }else { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t1 = 500; - } - - if ( mtp2Link->t2 != 0 ) { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t2 = mtp2Link->t2; - }else { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t2 = 250; - } - - if ( mtp2Link->t3 != 0 ) { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t3 = mtp2Link->t3; - }else { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t3 = 20; - } - - if ( mtp2Link->t4n != 0 ) { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t4n = mtp2Link->t4n; - }else { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t4n = 80; - } - - if ( mtp2Link->t4e != 0 ) { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t4e = mtp2Link->t4e; - }else { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t4e = 5; - } - - if ( mtp2Link->t5 != 0 ) { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t5 = mtp2Link->t5; - }else { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t5 = 1; - } - - if ( mtp2Link->t6 != 0 ) { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t6 = mtp2Link->t6; - }else { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t6 = 60; - } - - if ( mtp2Link->t7 != 0 ) { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t7 = mtp2Link->t7; - }else { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t7 = 20; - } - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_fill_in_mtp3_link(sng_mtp3_link_t *mtp3Link) -{ - int i = mtp3Link->id; - - /* check if this id value has been used already */ - if (g_ftdm_sngss7_data.cfg.mtp3Link[i].id == 0) { - SS7_DEBUG("Found new MTP3 Link: id=%d, name=%s\n", mtp3Link->id, mtp3Link->name); - sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3_PRESENT); - } else { - SS7_DEBUG("Found an existing MTP3 Link: id=%d, name=%s (old name=%s)\n", - mtp3Link->id, - mtp3Link->name, - g_ftdm_sngss7_data.cfg.mtp3Link[i].name); - } - - /* copy over the values */ - strcpy((char *)g_ftdm_sngss7_data.cfg.mtp3Link[i].name, (char *)mtp3Link->name); - - g_ftdm_sngss7_data.cfg.mtp3Link[i].id = mtp3Link->id; - g_ftdm_sngss7_data.cfg.mtp3Link[i].priority = mtp3Link->priority; - g_ftdm_sngss7_data.cfg.mtp3Link[i].linkType = mtp3Link->linkType; - g_ftdm_sngss7_data.cfg.mtp3Link[i].switchType = mtp3Link->switchType; - g_ftdm_sngss7_data.cfg.mtp3Link[i].apc = mtp3Link->apc; - g_ftdm_sngss7_data.cfg.mtp3Link[i].spc = mtp3Link->spc; /* unknown at this time */ - g_ftdm_sngss7_data.cfg.mtp3Link[i].ssf = mtp3Link->ssf; - g_ftdm_sngss7_data.cfg.mtp3Link[i].slc = mtp3Link->slc; - g_ftdm_sngss7_data.cfg.mtp3Link[i].linkSetId = mtp3Link->linkSetId; - g_ftdm_sngss7_data.cfg.mtp3Link[i].mtp2Id = mtp3Link->mtp2Id; - g_ftdm_sngss7_data.cfg.mtp3Link[i].mtp2ProcId = mtp3Link->mtp2ProcId; - - if (mtp3Link->t1 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t1 = mtp3Link->t1; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t1 = 8; - } - if (mtp3Link->t2 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t2 = mtp3Link->t2; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t2 = 14; - } - if (mtp3Link->t3 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t3 = mtp3Link->t3; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t3 = 8; - } - if (mtp3Link->t4 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t4 = mtp3Link->t4; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t4 = 8; - } - if (mtp3Link->t5 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t5 = mtp3Link->t5; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t5 = 8; - } - if (mtp3Link->t7 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t7 = mtp3Link->t7; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t7 = 15; - } - if (mtp3Link->t12 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t12 = mtp3Link->t12; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t12 = 15; - } - if (mtp3Link->t13 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t13 = mtp3Link->t13; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t13 = 15; - } - if (mtp3Link->t14 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t14 = mtp3Link->t14; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t14 = 30; - } - if (mtp3Link->t17 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t17 = mtp3Link->t17; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t17 = 15; - } - if (mtp3Link->t22 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t22 = mtp3Link->t22; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t22 = 1800; - } - if (mtp3Link->t23 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t23 = mtp3Link->t23; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t23 = 1800; - } - if (mtp3Link->t24 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t24 = mtp3Link->t24; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t24 = 5; - } - if (mtp3Link->t31 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t31 = mtp3Link->t31; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t31 = 50; - } - if (mtp3Link->t32 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t32 = mtp3Link->t32; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t32 = 120; - } - if (mtp3Link->t33 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t33 = mtp3Link->t33; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t33 = 3000; - } - if (mtp3Link->t34 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t34 = mtp3Link->t34; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t34 = 600; - } - if (mtp3Link->tbnd != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].tbnd = mtp3Link->tbnd; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].tbnd = 30000; - } - if (mtp3Link->tflc != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].tflc = mtp3Link->tflc; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].tflc = 300; - } - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_fill_in_mtpLinkSet(sng_link_set_t *mtpLinkSet) -{ - int i = mtpLinkSet->id; - - strncpy((char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[i].name, (char *)mtpLinkSet->name, MAX_NAME_LEN-1); - - g_ftdm_sngss7_data.cfg.mtpLinkSet[i].id = mtpLinkSet->id; - g_ftdm_sngss7_data.cfg.mtpLinkSet[i].apc = mtpLinkSet->apc; - - /* these values are filled in as we find routes and start allocating cmbLinkSetIds */ - g_ftdm_sngss7_data.cfg.mtpLinkSet[i].minActive = mtpLinkSet->minActive; - g_ftdm_sngss7_data.cfg.mtpLinkSet[i].numLinks = 0; - return 0; -} - -/******************************************************************************/ -static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route) -{ - sng_link_set_list_t *lnkSet = NULL; - int i = mtp3_route->id; - int tmp = 0; - - - /* check if this id value has been used already */ - if (g_ftdm_sngss7_data.cfg.mtpRoute[i].id == 0) { - SS7_DEBUG("Found new MTP3 Link: id=%d, name=%s\n", mtp3_route->id, mtp3_route->name); - } else { - SS7_DEBUG("Found an existing MTP3 Link: id=%d, name=%s (old name=%s)\n", - mtp3_route->id, - mtp3_route->name, - g_ftdm_sngss7_data.cfg.mtpRoute[i].name); - } - - /* fill in the cmbLinkSet in the linkset structure */ - lnkSet = &mtp3_route->lnkSets; - - tmp = g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].numLinks; - g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].links[tmp] = mtp3_route->cmbLinkSetId; - g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].numLinks++; - - while (lnkSet->next != NULL) { - tmp = g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].numLinks; - g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].links[tmp] = mtp3_route->cmbLinkSetId; - g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].numLinks++; - - lnkSet = lnkSet->next; - } - - strcpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[i].name, (char *)mtp3_route->name); - - g_ftdm_sngss7_data.cfg.mtpRoute[i].id = mtp3_route->id; - g_ftdm_sngss7_data.cfg.mtpRoute[i].dpc = mtp3_route->dpc; - g_ftdm_sngss7_data.cfg.mtpRoute[i].linkType = mtp3_route->linkType; - g_ftdm_sngss7_data.cfg.mtpRoute[i].switchType = mtp3_route->switchType; - g_ftdm_sngss7_data.cfg.mtpRoute[i].cmbLinkSetId = mtp3_route->cmbLinkSetId; - g_ftdm_sngss7_data.cfg.mtpRoute[i].isSTP = mtp3_route->isSTP; - g_ftdm_sngss7_data.cfg.mtpRoute[i].nwId = mtp3_route->nwId; - g_ftdm_sngss7_data.cfg.mtpRoute[i].lnkSets = mtp3_route->lnkSets; - g_ftdm_sngss7_data.cfg.mtpRoute[i].ssf = mtp3_route->ssf; - g_ftdm_sngss7_data.cfg.mtpRoute[i].dir = SNG_RTE_DN; - if (mtp3_route->t6 != 0) { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t6 = mtp3_route->t6; - } else { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t6 = 8; - } - if (mtp3_route->t8 != 0) { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t8 = mtp3_route->t8; - } else { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t8 = 12; - } - if (mtp3_route->t10 != 0) { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t10 = mtp3_route->t10; - } else { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t10 = 300; - } - if (mtp3_route->t11 != 0) { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t11 = mtp3_route->t11; - } else { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t11 = 300; - } - if (mtp3_route->t15 != 0) { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t15 = mtp3_route->t15; - } else { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t15 = 30; - } - if (mtp3_route->t16 != 0) { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t16 = mtp3_route->t16; - } else { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t16 = 20; - } - if (mtp3_route->t18 != 0) { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t18 = mtp3_route->t18; - } else { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t18 = 200; - } - if (mtp3_route->t19 != 0) { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t19 = mtp3_route->t19; - } else { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t19 = 690; - } - if (mtp3_route->t21 != 0) { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t21 = mtp3_route->t21; - } else { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t21 = 650; - } - if (mtp3_route->t25 != 0) { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t25 = mtp3_route->t25; - } else { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t25 = 100; - } - if (mtp3_route->t26 != 0) { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t26 = mtp3_route->t26; - } else { - g_ftdm_sngss7_data.cfg.mtpRoute[i].t26 = 100; - } - - return 0; -} - -/******************************************************************************/ -static int ftmod_ss7_fill_in_self_route(int spc, int linkType, int switchType, int ssf) -{ - int i = 1; - - while (i < (MAX_MTP_ROUTES)) { - if (g_ftdm_sngss7_data.cfg.mtpRoute[i].dpc == spc) { - /* we have a match so break out of this loop */ - break; - } - /* move on to the next one */ - i++; - } - - if (g_ftdm_sngss7_data.cfg.mtpRoute[i].id == 0) { - /* this is a new route...find the first free spot */ - i = 1; - while (i < (MAX_MTP_ROUTES)) { - if (g_ftdm_sngss7_data.cfg.mtpRoute[i].id == 0) { - /* we have a match so break out of this loop */ - break; - } - /* move on to the next one */ - i++; - } - g_ftdm_sngss7_data.cfg.mtpRoute[i].id = i; - SS7_DEBUG("found new mtp3 self route\n"); - } else { - g_ftdm_sngss7_data.cfg.mtpRoute[i].id = i; - SS7_DEBUG("found existing mtp3 self route\n"); - } - - strncpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[i].name, "self-route", MAX_NAME_LEN-1); - - g_ftdm_sngss7_data.cfg.mtpRoute[i].id = i; - g_ftdm_sngss7_data.cfg.mtpRoute[i].dpc = spc; - g_ftdm_sngss7_data.cfg.mtpRoute[i].linkType = linkType; - g_ftdm_sngss7_data.cfg.mtpRoute[i].switchType = switchType; - g_ftdm_sngss7_data.cfg.mtpRoute[i].cmbLinkSetId = i; - g_ftdm_sngss7_data.cfg.mtpRoute[i].isSTP = 0; - g_ftdm_sngss7_data.cfg.mtpRoute[i].ssf = ssf; - g_ftdm_sngss7_data.cfg.mtpRoute[i].dir = SNG_RTE_UP; - g_ftdm_sngss7_data.cfg.mtpRoute[i].t6 = 8; - g_ftdm_sngss7_data.cfg.mtpRoute[i].t8 = 12; - g_ftdm_sngss7_data.cfg.mtpRoute[i].t10 = 300; - g_ftdm_sngss7_data.cfg.mtpRoute[i].t11 = 300; - g_ftdm_sngss7_data.cfg.mtpRoute[i].t15 = 30; - g_ftdm_sngss7_data.cfg.mtpRoute[i].t16 = 20; - g_ftdm_sngss7_data.cfg.mtpRoute[i].t18 = 200; - g_ftdm_sngss7_data.cfg.mtpRoute[i].t19 = 690; - g_ftdm_sngss7_data.cfg.mtpRoute[i].t21 = 650; - g_ftdm_sngss7_data.cfg.mtpRoute[i].t25 = 100; - - return 0; -} - -/******************************************************************************/ -static int ftmod_ss7_fill_in_nsap(sng_route_t *mtp3_route) -{ - int i; - - /* go through all the existing interfaces and see if we find a match */ - i = 1; - while (g_ftdm_sngss7_data.cfg.nsap[i].id != 0) { - if ((g_ftdm_sngss7_data.cfg.nsap[i].linkType == mtp3_route->linkType) && - (g_ftdm_sngss7_data.cfg.nsap[i].switchType == mtp3_route->switchType)) { - - /* we have a match so break out of this loop */ - break; - } - /* move on to the next one */ - i++; - } - - if (g_ftdm_sngss7_data.cfg.nsap[i].id == 0) { - g_ftdm_sngss7_data.cfg.nsap[i].id = i; - SS7_DEBUG("found new mtp3_isup interface, id is = %d\n", g_ftdm_sngss7_data.cfg.nsap[i].id); - } else { - g_ftdm_sngss7_data.cfg.nsap[i].id = i; - SS7_DEBUG("found existing mtp3_isup interface, id is = %d\n", g_ftdm_sngss7_data.cfg.nsap[i].id); - } - - g_ftdm_sngss7_data.cfg.nsap[i].spId = g_ftdm_sngss7_data.cfg.nsap[i].id; - g_ftdm_sngss7_data.cfg.nsap[i].suId = g_ftdm_sngss7_data.cfg.nsap[i].id; - g_ftdm_sngss7_data.cfg.nsap[i].nwId = mtp3_route->nwId; - g_ftdm_sngss7_data.cfg.nsap[i].linkType = mtp3_route->linkType; - g_ftdm_sngss7_data.cfg.nsap[i].switchType = mtp3_route->switchType; - g_ftdm_sngss7_data.cfg.nsap[i].ssf = mtp3_route->ssf; - - return 0; -} - -/******************************************************************************/ -static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup) -{ - int i = sng_isup->id; - - /* check if this id value has been used already */ - if (g_ftdm_sngss7_data.cfg.isupIntf[i].id == 0) { - SS7_DEBUG("Found new ISUP Interface: id=%d, name=%s\n", sng_isup->id, sng_isup->name); - sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP_PRESENT); - } else { - SS7_DEBUG("Found an existing ISUP Interface: id=%d, name=%s (old name=%s)\n", - sng_isup->id, - sng_isup->name, - g_ftdm_sngss7_data.cfg.isupIntf[i].name); - } - - strncpy((char *)g_ftdm_sngss7_data.cfg.isupIntf[i].name, (char *)sng_isup->name, MAX_NAME_LEN-1); - - g_ftdm_sngss7_data.cfg.isupIntf[i].id = sng_isup->id; - g_ftdm_sngss7_data.cfg.isupIntf[i].mtpRouteId = sng_isup->mtpRouteId; - g_ftdm_sngss7_data.cfg.isupIntf[i].nwId = sng_isup->nwId; - g_ftdm_sngss7_data.cfg.isupIntf[i].dpc = sng_isup->dpc; - g_ftdm_sngss7_data.cfg.isupIntf[i].spc = sng_isup->spc; - g_ftdm_sngss7_data.cfg.isupIntf[i].switchType = sng_isup->switchType; - g_ftdm_sngss7_data.cfg.isupIntf[i].ssf = sng_isup->ssf; - g_ftdm_sngss7_data.cfg.isupIntf[i].isap = sng_isup->isap; - g_ftdm_sngss7_data.cfg.isupIntf[i].options = sng_isup->options; - if (sng_isup->t4 != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].t4 = sng_isup->t4; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].t4 = 3000; - } - if (sng_isup->t11 != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].t11 = sng_isup->t11; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].t11 = 170; - } - if (sng_isup->t18 != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].t18 = sng_isup->t18; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].t18 = 300; - } - if (sng_isup->t19 != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].t19 = sng_isup->t19; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].t19 = 3000; - } - if (sng_isup->t20 != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].t20 = sng_isup->t20; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].t20 = 300; - } - if (sng_isup->t21 != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].t21 = sng_isup->t21; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].t21 = 3000; - } - if (sng_isup->t22 != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].t22 = sng_isup->t22; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].t22 = 300; - } - if (sng_isup->t23 != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].t23 = sng_isup->t23; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].t23 = 3000; - } - if (sng_isup->t24 != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].t24 = sng_isup->t24; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].t24 = 10; - } - if (sng_isup->t25 != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].t25 = sng_isup->t25; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].t25 = 20; - } - if (sng_isup->t26 != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].t26 = sng_isup->t26; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].t26 = 600; - } - if (sng_isup->t28 != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].t28 = sng_isup->t28; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].t28 = 100; - } - if (sng_isup->t29 != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].t29 = sng_isup->t29; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].t29 = 6; - } - if (sng_isup->t30 != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].t30 = sng_isup->t30; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].t30 = 50; - } - if (sng_isup->t32 != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].t32 = sng_isup->t32; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].t32 = 30; - } - if (sng_isup->t37 != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].t37 = sng_isup->t37; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].t37 = 20; - } - if (sng_isup->t38 != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].t38 = sng_isup->t38; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].t38 = 1200; - } - if (sng_isup->t39 != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].t39 = sng_isup->t39; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].t39 = 300; - } - if (sng_isup->tfgr != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].tfgr = sng_isup->tfgr; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].tfgr = 50; - } - if (sng_isup->tpause != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].tpause = sng_isup->tpause; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].tpause = 3000; - } - if (sng_isup->tstaenq != 0) { - g_ftdm_sngss7_data.cfg.isupIntf[i].tstaenq = sng_isup->tstaenq; - } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].tstaenq = 5000; - } - - return 0; -} - -/******************************************************************************/ -static int ftmod_ss7_fill_in_isap(sng_isap_t *sng_isap) -{ - int i; - - /* go through all the existing interfaces and see if we find a match */ - i = 1; - while (g_ftdm_sngss7_data.cfg.isap[i].id != 0) { - if (g_ftdm_sngss7_data.cfg.isap[i].switchType == sng_isap->switchType) { - - /* we have a match so break out of this loop */ - break; - } - /* move on to the next one */ - i++; - } - - if (g_ftdm_sngss7_data.cfg.isap[i].id == 0) { - sng_isap->id = i; - SS7_DEBUG("found new isup to cc interface, id is = %d\n", sng_isap->id); - } else { - sng_isap->id = i; - SS7_DEBUG("found existing isup to cc interface, id is = %d\n", sng_isap->id); - } - - g_ftdm_sngss7_data.cfg.isap[i].id = sng_isap->id; - g_ftdm_sngss7_data.cfg.isap[i].suId = sng_isap->id; - g_ftdm_sngss7_data.cfg.isap[i].spId = sng_isap->id; - g_ftdm_sngss7_data.cfg.isap[i].switchType = sng_isap->switchType; - g_ftdm_sngss7_data.cfg.isap[i].ssf = sng_isap->ssf; - - if (sng_isap->t1 != 0) { - g_ftdm_sngss7_data.cfg.isap[i].t1 = sng_isap->t1; - } else { - g_ftdm_sngss7_data.cfg.isap[i].t1 = 150; - } - if (sng_isap->t2 != 0) { - g_ftdm_sngss7_data.cfg.isap[i].t2 = sng_isap->t2; - } else { - g_ftdm_sngss7_data.cfg.isap[i].t2 = 1800; - } - if (sng_isap->t5 != 0) { - g_ftdm_sngss7_data.cfg.isap[i].t5 = sng_isap->t5; - } else { - g_ftdm_sngss7_data.cfg.isap[i].t5 = 3000; - } - if (sng_isap->t6 != 0) { - g_ftdm_sngss7_data.cfg.isap[i].t6 = sng_isap->t6; - } else { - g_ftdm_sngss7_data.cfg.isap[i].t6 = 600; - } - if (sng_isap->t7 != 0) { - g_ftdm_sngss7_data.cfg.isap[i].t7 = sng_isap->t7; - } else { - g_ftdm_sngss7_data.cfg.isap[i].t7 = 200; - } - if (sng_isap->t8 != 0) { - g_ftdm_sngss7_data.cfg.isap[i].t8 = sng_isap->t8; - } else { - g_ftdm_sngss7_data.cfg.isap[i].t8 = 100; - } - if (sng_isap->t9 != 0) { - g_ftdm_sngss7_data.cfg.isap[i].t9 = sng_isap->t9; - } else { - g_ftdm_sngss7_data.cfg.isap[i].t9 = 1800; - } - if (sng_isap->t27 != 0) { - g_ftdm_sngss7_data.cfg.isap[i].t27 = sng_isap->t27; - } else { - g_ftdm_sngss7_data.cfg.isap[i].t27 = 2400; - } - if (sng_isap->t31 != 0) { - g_ftdm_sngss7_data.cfg.isap[i].t31 = sng_isap->t31; - } else { - g_ftdm_sngss7_data.cfg.isap[i].t31 = 3650; - } - if (sng_isap->t33 != 0) { - g_ftdm_sngss7_data.cfg.isap[i].t33 = sng_isap->t33; - } else { - g_ftdm_sngss7_data.cfg.isap[i].t33 = 120; - } - if (sng_isap->t34 != 0) { - g_ftdm_sngss7_data.cfg.isap[i].t34 = sng_isap->t34; - } else { - g_ftdm_sngss7_data.cfg.isap[i].t34 = 40; - } - if (sng_isap->t36 != 0) { - g_ftdm_sngss7_data.cfg.isap[i].t36 = sng_isap->t36; - } else { - g_ftdm_sngss7_data.cfg.isap[i].t36 = 120; - } - if (sng_isap->tccr != 0) { - g_ftdm_sngss7_data.cfg.isap[i].tccr = sng_isap->tccr; - } else { - g_ftdm_sngss7_data.cfg.isap[i].tccr = 200; - } - if (sng_isap->tccrt != 0) { - g_ftdm_sngss7_data.cfg.isap[i].tccrt = sng_isap->tccrt; - } else { - g_ftdm_sngss7_data.cfg.isap[i].tccrt = 20; - } - if (sng_isap->tex != 0) { - g_ftdm_sngss7_data.cfg.isap[i].tex = sng_isap->tex; - } else { - g_ftdm_sngss7_data.cfg.isap[i].tex = 1000; - } - if (sng_isap->tcrm != 0) { - g_ftdm_sngss7_data.cfg.isap[i].tcrm = sng_isap->tcrm; - } else { - g_ftdm_sngss7_data.cfg.isap[i].tcrm = 30; - } - if (sng_isap->tcra != 0) { - g_ftdm_sngss7_data.cfg.isap[i].tcra = sng_isap->tcra; - } else { - g_ftdm_sngss7_data.cfg.isap[i].tcra = 100; - } - if (sng_isap->tect != 0) { - g_ftdm_sngss7_data.cfg.isap[i].tect = sng_isap->tect; - } else { - g_ftdm_sngss7_data.cfg.isap[i].tect = 10; - } - if (sng_isap->trelrsp != 0) { - g_ftdm_sngss7_data.cfg.isap[i].trelrsp = sng_isap->trelrsp; - } else { - g_ftdm_sngss7_data.cfg.isap[i].trelrsp = 10; - } - if (sng_isap->tfnlrelrsp != 0) { - g_ftdm_sngss7_data.cfg.isap[i].tfnlrelrsp = sng_isap->tfnlrelrsp; - } else { - g_ftdm_sngss7_data.cfg.isap[i].tfnlrelrsp = 10; - } - - return 0; -} - -/******************************************************************************/ -static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan) -{ - sng_timeslot_t timeslot; - sngss7_chan_data_t *ss7_info = NULL; - int x; - int count = 1; - int flag; - - while (ccSpan->ch_map[0] != '\0') { - /**************************************************************************/ - - /* pull out the next timeslot */ - if (ftmod_ss7_next_timeslot(ccSpan->ch_map, ×lot)) { - SS7_ERROR("Failed to parse the channel map!\n"); - return FTDM_FAIL; - } - - /* find a spot for this circuit in the global structure */ - x = (ccSpan->procId * 1000) + 1; - flag = 0; - while (flag == 0) { - /**********************************************************************/ - /* check the id value ( 0 = new, 0 > circuit can be existing) */ - if (g_ftdm_sngss7_data.cfg.isupCkt[x].id == 0) { - /* we're at the end of the list of circuitsl aka this is new */ - SS7_DEBUG("Found a new circuit %d, ccSpanId=%d, chan=%d\n", - x, - ccSpan->id, - count); - - /* throw the flag to end the loop */ - flag = 1; - } else { - /* check the ccspan.id and chan to see if the circuit already exists */ - if ((g_ftdm_sngss7_data.cfg.isupCkt[x].ccSpanId == ccSpan->id) && - (g_ftdm_sngss7_data.cfg.isupCkt[x].chan == count)) { - - /* we are processing a circuit that already exists */ - SS7_DEVEL_DEBUG("Found an existing circuit %d, ccSpanId=%d, chan%d\n", - x, - ccSpan->id, - count); - - /* throw the flag to end the loop */ - flag = 1; - - /* not supporting reconfig at this time */ - SS7_DEVEL_DEBUG("Not supporting ckt reconfig at this time!\n"); - goto move_along; - } else { - /* this is not the droid you are looking for */ - x++; - } - } - /**********************************************************************/ - } /* while (flag == 0) */ - - /* prepare the global info sturcture */ - ss7_info = ftdm_calloc(1, sizeof(sngss7_chan_data_t)); - ss7_info->ftdmchan = NULL; - if (ftdm_queue_create(&ss7_info->event_queue, SNGSS7_CHAN_EVENT_QUEUE_SIZE) != FTDM_SUCCESS) { - SS7_CRITICAL("Failed to create ss7 cic event queue\n"); - } - ss7_info->circuit = &g_ftdm_sngss7_data.cfg.isupCkt[x]; - - g_ftdm_sngss7_data.cfg.isupCkt[x].obj = ss7_info; - - /* fill in the rest of the global structure */ - g_ftdm_sngss7_data.cfg.isupCkt[x].procId = ccSpan->procId; - g_ftdm_sngss7_data.cfg.isupCkt[x].id = x; - g_ftdm_sngss7_data.cfg.isupCkt[x].ccSpanId = ccSpan->id; - g_ftdm_sngss7_data.cfg.isupCkt[x].span = 0; - g_ftdm_sngss7_data.cfg.isupCkt[x].chan = count; - - if (timeslot.siglink) { - g_ftdm_sngss7_data.cfg.isupCkt[x].type = SNG_CKT_SIG; - } else if (timeslot.gap) { - g_ftdm_sngss7_data.cfg.isupCkt[x].type = SNG_CKT_HOLE; - } else { - g_ftdm_sngss7_data.cfg.isupCkt[x].type = SNG_CKT_VOICE; - - /* throw the flag to indicate that we need to start call control */ - sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC_PRESENT); - } - - if (timeslot.channel) { - g_ftdm_sngss7_data.cfg.isupCkt[x].cic = ccSpan->cicbase; - ccSpan->cicbase++; - } else { - g_ftdm_sngss7_data.cfg.isupCkt[x].cic = 0; - } - - g_ftdm_sngss7_data.cfg.isupCkt[x].infId = ccSpan->isupInf; - g_ftdm_sngss7_data.cfg.isupCkt[x].typeCntrl = ccSpan->typeCntrl; - g_ftdm_sngss7_data.cfg.isupCkt[x].ssf = ccSpan->ssf; - g_ftdm_sngss7_data.cfg.isupCkt[x].cld_nadi = ccSpan->cld_nadi; - g_ftdm_sngss7_data.cfg.isupCkt[x].clg_nadi = ccSpan->clg_nadi; - g_ftdm_sngss7_data.cfg.isupCkt[x].rdnis_nadi = ccSpan->rdnis_nadi; - g_ftdm_sngss7_data.cfg.isupCkt[x].loc_nadi = ccSpan->loc_nadi; - g_ftdm_sngss7_data.cfg.isupCkt[x].options = ccSpan->options; - g_ftdm_sngss7_data.cfg.isupCkt[x].switchType = ccSpan->switchType; - g_ftdm_sngss7_data.cfg.isupCkt[x].min_digits = ccSpan->min_digits; - g_ftdm_sngss7_data.cfg.isupCkt[x].itx_auto_reply = ccSpan->itx_auto_reply; - g_ftdm_sngss7_data.cfg.isupCkt[x].transparent_iam = ccSpan->transparent_iam; - g_ftdm_sngss7_data.cfg.isupCkt[x].transparent_iam_max_size = ccSpan->transparent_iam_max_size; - g_ftdm_sngss7_data.cfg.isupCkt[x].cpg_on_progress_media = ccSpan->cpg_on_progress_media; - g_ftdm_sngss7_data.cfg.isupCkt[x].cpg_on_progress = ccSpan->cpg_on_progress; - - if (ccSpan->t3 == 0) { - g_ftdm_sngss7_data.cfg.isupCkt[x].t3 = 1200; - } else { - g_ftdm_sngss7_data.cfg.isupCkt[x].t3 = ccSpan->t3; - } - if (ccSpan->t10 == 0) { - g_ftdm_sngss7_data.cfg.isupCkt[x].t10 = 50; - } else { - g_ftdm_sngss7_data.cfg.isupCkt[x].t10 = ccSpan->t10; - } - if (ccSpan->t12 == 0) { - g_ftdm_sngss7_data.cfg.isupCkt[x].t12 = 300; - } else { - g_ftdm_sngss7_data.cfg.isupCkt[x].t12 = ccSpan->t12; - } - if (ccSpan->t13 == 0) { - g_ftdm_sngss7_data.cfg.isupCkt[x].t13 = 3000; - } else { - g_ftdm_sngss7_data.cfg.isupCkt[x].t13 = ccSpan->t13; - } - if (ccSpan->t14 == 0) { - g_ftdm_sngss7_data.cfg.isupCkt[x].t14 = 300; - } else { - g_ftdm_sngss7_data.cfg.isupCkt[x].t14 = ccSpan->t14; - } - if (ccSpan->t15 == 0) { - g_ftdm_sngss7_data.cfg.isupCkt[x].t15 = 3000; - } else { - g_ftdm_sngss7_data.cfg.isupCkt[x].t15 = ccSpan->t15; - } - if (ccSpan->t16 == 0) { - g_ftdm_sngss7_data.cfg.isupCkt[x].t16 = 300; - } else { - g_ftdm_sngss7_data.cfg.isupCkt[x].t16 = ccSpan->t16; - } - if (ccSpan->t17 == 0) { - g_ftdm_sngss7_data.cfg.isupCkt[x].t17 = 3000; - } else { - g_ftdm_sngss7_data.cfg.isupCkt[x].t17 = ccSpan->t17; - } - if (ccSpan->t35 == 0) { - /* Q.764 2.2.5 Address incomplete (T35 is 15-20 seconds according to Table A.1/Q.764) */ - g_ftdm_sngss7_data.cfg.isupCkt[x].t35 = 170; - } else { - g_ftdm_sngss7_data.cfg.isupCkt[x].t35 = ccSpan->t35; - } - if (ccSpan->t39 == 0) { - g_ftdm_sngss7_data.cfg.isupCkt[x].t39 = 120; - } else { - g_ftdm_sngss7_data.cfg.isupCkt[x].t39 = ccSpan->t39; - } - - if (ccSpan->tval == 0) { - g_ftdm_sngss7_data.cfg.isupCkt[x].tval = 10; - } else { - g_ftdm_sngss7_data.cfg.isupCkt[x].tval = ccSpan->tval; - } - - SS7_INFO("Added procId=%d, spanId = %d, chan = %d, cic = %d, ISUP cirId = %d\n", - g_ftdm_sngss7_data.cfg.isupCkt[x].procId, - g_ftdm_sngss7_data.cfg.isupCkt[x].ccSpanId, - g_ftdm_sngss7_data.cfg.isupCkt[x].chan, - g_ftdm_sngss7_data.cfg.isupCkt[x].cic, - g_ftdm_sngss7_data.cfg.isupCkt[x].id); - -move_along: - /* increment the span channel count */ - count++; - - /**************************************************************************/ - } /* while (ccSpan->ch_map[0] != '\0') */ - - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_fill_in_circuits(sng_span_t *sngSpan) -{ - ftdm_channel_t *ftdmchan = NULL; - ftdm_span_t *ftdmspan = sngSpan->span; - sng_isup_ckt_t *isupCkt = NULL; - sngss7_chan_data_t *ss7_info = NULL; - int flag; - int i; - int x; - - /* go through all the channels on ftdm span */ - for (i = 1; i < (ftdmspan->chan_count+1); i++) { - /**************************************************************************/ - - /* extract the ftdmchan pointer */ - ftdmchan = ftdmspan->channels[i]; - - /* find the equivalent channel in the global structure */ - x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; - flag = 0; - while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - /**********************************************************************/ - /* pull out the circuit to make it easier to work with */ - isupCkt = &g_ftdm_sngss7_data.cfg.isupCkt[x]; - - /* if the ccSpanId's match fill in the span value...this is for sigs - * because they will never have a channel that matches since they - * have a ftdmchan at this time */ - if (sngSpan->ccSpanId == isupCkt->ccSpanId) { - isupCkt->span = ftdmchan->physical_span_id; - } - - /* check if the ccSpanId matches and the physical channel # match */ - if ((sngSpan->ccSpanId == isupCkt->ccSpanId) && - (ftdmchan->physical_chan_id == isupCkt->chan)) { - - /* we've found the channel in the ckt structure...raise the flag */ - flag = 1; - - /* now get out of the loop */ - break; - } - - /* move to the next ckt */ - x++; - - /* check if we are outside of the range of possible indexes */ - if (x == ((g_ftdm_sngss7_data.cfg.procId + 1) * 1000)) { - break; - } - /**********************************************************************/ - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */ - - /* check we found the ckt or not */ - if (!flag) { - SS7_ERROR_CHAN(ftdmchan, "Failed to find this channel in the global ckts!%s\n",""); - return FTDM_FAIL; - } - - /* fill in the rest of the global sngss7_chan_data_t structure */ - ss7_info = (sngss7_chan_data_t *)isupCkt->obj; - ss7_info->ftdmchan = ftdmchan; - - /* attach the sngss7_chan_data_t to the freetdm channel structure */ - ftdmchan->call_data = ss7_info; - - /* prepare the timer structures */ - ss7_info->t35.sched = ((sngss7_span_data_t *)(ftdmspan->signal_data))->sched; - ss7_info->t35.counter = 1; - ss7_info->t35.beat = (isupCkt->t35) * 100; /* beat is in ms, t35 is in 100ms */ - ss7_info->t35.callback = handle_isup_t35; - ss7_info->t35.sngss7_info = ss7_info; - - ss7_info->t10.sched = ((sngss7_span_data_t *)(ftdmspan->signal_data))->sched; - ss7_info->t10.counter = 1; - ss7_info->t10.beat = (isupCkt->t10) * 100; /* beat is in ms, t10 is in 100ms */ - ss7_info->t10.callback = handle_isup_t10; - ss7_info->t10.sngss7_info = ss7_info; - - /* prepare the timer structures */ - ss7_info->t39.sched = ((sngss7_span_data_t *)(ftdmspan->signal_data))->sched; - ss7_info->t39.counter = 1; - ss7_info->t39.beat = (isupCkt->t39) * 100; /* beat is in ms, t39 is in 100ms */ - ss7_info->t39.callback = handle_isup_t39; - ss7_info->t39.sngss7_info = ss7_info; - - - /**************************************************************************/ - } /* for (i == 1; i < ftdmspan->chan_count; i++) */ - - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot) -{ - int i; - int x; - int lower; - int upper; - char tmp[5]; /*KONRAD FIX ME*/ - char new_ch_map[MAX_CIC_MAP_LENGTH]; - - memset(&tmp[0], '\0', sizeof(tmp)); - memset(&new_ch_map[0], '\0', sizeof(new_ch_map)); - memset(timeslot, 0x0, sizeof(sng_timeslot_t)); - - SS7_DEVEL_DEBUG("Old channel map = \"%s\"\n", ch_map); - - /* start at the beginning of the ch_map */ - x = 0; - - switch (ch_map[x]) { - /**************************************************************************/ - case 'S': - case 's': /* we have a sig link */ - timeslot->siglink = 1; - - /* check what comes next either a comma or a number */ - x++; - if (ch_map[x] == ',') { - timeslot->hole = 1; - SS7_DEVEL_DEBUG(" Found a siglink in the channel map with a hole in the cic map\n"); - } else if (isdigit(ch_map[x])) { - /* consume all digits until a comma as this is the channel */ - SS7_DEVEL_DEBUG(" Found a siglink in the channel map with out a hole in the cic map\n"); - } else { - SS7_ERROR("Found an illegal channel map character after signal link flag = \"%c\"!\n", ch_map[x]); - return FTDM_FAIL; - } - break; - /**************************************************************************/ - case 'G': - case 'g': /* we have a channel gap */ - timeslot->gap = 1; - - /* check what comes next either a comma or a number */ - x++; - if (ch_map[x] == ',') { - timeslot->hole = 1; - SS7_DEVEL_DEBUG(" Found a gap in the channel map with a hole in the cic map\n"); - } else if (isdigit(ch_map[x])) { - SS7_DEVEL_DEBUG(" Found a gap in the channel map with out a hole in the cic map\n"); - /* consume all digits until a comma as this is the channel */ - } else { - SS7_ERROR("Found an illegal channel map character after signal link flag = \"%c\"!\n", ch_map[x]); - return FTDM_FAIL; - } - break; - /**************************************************************************/ - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': /* we have a channel */ - /* consume all digits until a comma or a dash */ - SS7_DEVEL_DEBUG("Found a starting channel in the channel map\n"); - break; - /**************************************************************************/ - default: - SS7_ERROR("Found an illegal channel map character = \"%c\"!\n", ch_map[x]); - return FTDM_FAIL; - /**************************************************************************/ - } /* switch (ch_map[x]) */ - - /* grab the first number in the string */ - i = 0; - while ((ch_map[x] != '\0') && (ch_map[x] != '-') && (ch_map[x] != ',')) { - tmp[i] = ch_map[x]; - i++; - x++; - } - tmp[i] = '\0'; - timeslot->channel = atoi(tmp); - lower = timeslot->channel + 1; - - /* check the next value in the list */ - if (ch_map[x] == '-') { - /* consume the number after the dash */ - x++; - i = 0; - while ((ch_map[x] != '\0') && (ch_map[x] != '-') && (ch_map[x] != ',')) { - tmp[i] = ch_map[x]; - i++; - x++; - } - tmp[i] = '\0'; - upper = atoi(tmp); - - /* check if the upper end of the range is the same as the lower end of the range */ - if (upper == lower) { - /* the range is completed, eat the next comma or \0 and write it */ - sprintf(new_ch_map, "%d", lower); - } else if ( upper > lower) { - /* the list continues, add 1 from the channel map value and re-insert it to the list */ - sprintf(new_ch_map, "%d-%d", lower, upper); - } else { - SS7_ERROR("The upper is less then the lower end of the range...should not happen!\n"); - return FTDM_FAIL; - } - - /* the the rest of ch_map to new_ch_map */ - strncat(new_ch_map, &ch_map[x], strlen(&ch_map[x])); - - - /* set the new cic map to ch_map*/ - memset(ch_map, '\0', sizeof(ch_map)); - strcpy(ch_map, new_ch_map); - - } else if (ch_map[x] == ',') { - /* move past the comma */ - x++; - - /* copy the rest of the list to new_ch_map */ - memset(new_ch_map, '\0', sizeof(new_ch_map)); - strcpy(new_ch_map, &ch_map[x]); - - /* copy the new_ch_map over the old one */ - memset(ch_map, '\0', sizeof(ch_map)); - strcpy(ch_map, new_ch_map); - - } else if (ch_map[x] == '\0') { - - /* we're at the end of the string...copy the rest of the list to new_ch_map */ - memset(new_ch_map, '\0', sizeof(new_ch_map)); - strcpy(new_ch_map, &ch_map[x]); - - /* set the new cic map to ch_map*/ - memset(ch_map, '\0', sizeof(ch_map)); - strcpy(ch_map, new_ch_map); - } else { - /* nothing to do */ - } - - SS7_DEVEL_DEBUG("New channel map = \"%s\"\n", ch_map); - - return FTDM_SUCCESS; -} - -/******************************************************************************/ - -/******************************************************************************/ -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_skel/ftmod_skel.c b/libs/freetdm/src/ftmod/ftmod_skel/ftmod_skel.c deleted file mode 100644 index 7d8a9b7393..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_skel/ftmod_skel.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -#include "private/ftdm_core.h" -//#include "ftdm_skel.h" - -static FIO_CONFIGURE_FUNCTION(skel_configure) -{ - ftdm_unused_arg(category); - ftdm_unused_arg(var); - ftdm_unused_arg(val); - ftdm_unused_arg(lineno); - return FTDM_FAIL; -} - -static FIO_CONFIGURE_SPAN_FUNCTION(skel_configure_span) -{ - ftdm_unused_arg(span); - ftdm_unused_arg(str); - ftdm_unused_arg(type); - ftdm_unused_arg(name); - ftdm_unused_arg(number); - return FTDM_FAIL; -} - -static FIO_OPEN_FUNCTION(skel_open) -{ - ftdm_unused_arg(ftdmchan); - return FTDM_FAIL; -} - -static FIO_CLOSE_FUNCTION(skel_close) -{ - ftdm_unused_arg(ftdmchan); - return FTDM_FAIL; -} - -static FIO_WAIT_FUNCTION(skel_wait) -{ - ftdm_unused_arg(ftdmchan); - ftdm_unused_arg(flags); - ftdm_unused_arg(to); - return FTDM_FAIL; -} - -static FIO_READ_FUNCTION(skel_read) -{ - ftdm_unused_arg(ftdmchan); - ftdm_unused_arg(data); - ftdm_unused_arg(datalen); - return FTDM_FAIL; -} - -static FIO_WRITE_FUNCTION(skel_write) -{ - ftdm_unused_arg(ftdmchan); - ftdm_unused_arg(data); - ftdm_unused_arg(datalen); - return FTDM_FAIL; -} - -static FIO_COMMAND_FUNCTION(skel_command) -{ - ftdm_unused_arg(ftdmchan); - ftdm_unused_arg(command); - ftdm_unused_arg(obj); - return FTDM_FAIL; -} - -static FIO_SPAN_POLL_EVENT_FUNCTION(skel_poll_event) -{ - ftdm_unused_arg(span); - ftdm_unused_arg(ms); - ftdm_unused_arg(poll_events); - return FTDM_FAIL; -} - -static FIO_SPAN_NEXT_EVENT_FUNCTION(skel_next_event) -{ - ftdm_unused_arg(span); - ftdm_unused_arg(event); - return FTDM_FAIL; -} - -static FIO_CHANNEL_DESTROY_FUNCTION(skel_channel_destroy) -{ - ftdm_unused_arg(ftdmchan); - return FTDM_FAIL; -} - -static FIO_SPAN_DESTROY_FUNCTION(skel_span_destroy) -{ - ftdm_unused_arg(span); - return FTDM_FAIL; -} - -static FIO_GET_ALARMS_FUNCTION(skel_get_alarms) -{ - ftdm_unused_arg(ftdmchan); - return FTDM_FAIL; -} - -static ftdm_io_interface_t skel_interface; - -static FIO_IO_LOAD_FUNCTION(skel_init) -{ - assert(fio != NULL); - memset(&skel_interface, 0, sizeof(skel_interface)); - - skel_interface.name = "skel"; - skel_interface.configure = skel_configure; - skel_interface.configure_span = skel_configure_span; - skel_interface.open = skel_open; - skel_interface.close = skel_close; - skel_interface.wait = skel_wait; - skel_interface.read = skel_read; - skel_interface.write = skel_write; - skel_interface.command = skel_command; - skel_interface.poll_event = skel_poll_event; - skel_interface.next_event = skel_next_event; - skel_interface.channel_destroy = skel_channel_destroy; - skel_interface.span_destroy = skel_span_destroy; - skel_interface.get_alarms = skel_get_alarms; - *fio = &skel_interface; - - return FTDM_SUCCESS; -} - -static FIO_IO_UNLOAD_FUNCTION(skel_destroy) -{ - return FTDM_SUCCESS; -} - - -ftdm_module_t ftdm_module = { - "skel", - skel_init, - skel_destroy, -}; - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2008.vcproj deleted file mode 100644 index 7fdb0ff592..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2008.vcproj +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj.filters deleted file mode 100644 index 15a8bc3d35..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj.filters +++ /dev/null @@ -1,18 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Source Files - - - \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c deleted file mode 100755 index 58b5c9ca0e..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ /dev/null @@ -1,1807 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Contributors: - * - * Moises Silva - * David Yat Sin - * Nenad Corbic - * Arnaldo Pereira - * Gideon Sadan - * - */ -#ifdef WP_DEBUG_IO -#ifndef _DEFAULT_SOURCE -#define _DEFAULT_SOURCE -#endif -#define _BSD_SOURCE -#include -#endif - -#ifdef __sun -#include -#include -#endif -#include "private/ftdm_core.h" -#ifndef __WINDOWS__ -#include -#include -#endif -#include "libsangoma.h" - -#if defined(__WINDOWS__) -/*! Backward compatible defines - current code is all using the old names*/ -#define sangoma_open_tdmapi_span_chan sangoma_open_api_span_chan -#define sangoma_open_tdmapi_span sangoma_open_api_span -#define sangoma_open_tdmapi_ctrl sangoma_open_api_ctrl -#define sangoma_tdm_get_fe_status sangoma_get_fe_status -#define sangoma_socket_close sangoma_close -#define sangoma_tdm_get_hw_coding sangoma_get_hw_coding -#define sangoma_tdm_set_fe_status sangoma_set_fe_status -#define sangoma_tdm_get_link_status sangoma_get_link_status -#define sangoma_tdm_flush_bufs sangoma_flush_bufs -#define sangoma_tdm_cmd_exec sangoma_cmd_exec -#define sangoma_tdm_read_event sangoma_read_event -#define sangoma_readmsg_tdm sangoma_readmsg -#define sangoma_readmsg_socket sangoma_readmsg -#define sangoma_sendmsg_socket sangoma_writemsg -#define sangoma_writemsg_tdm sangoma_writemsg -#define sangoma_create_socket_intr sangoma_open_api_span_chan -#endif - -/*! Starting with libsangoma 3 we can use the new libsangoma waitable API, the poor souls of those using a release where LIBSANGOMA version - * is defined but the version is not higher or equal to 3.0.0 will be forced to upgrade - * */ -#ifdef LIBSANGOMA_VERSION -#if LIBSANGOMA_VERSION_CODE < LIBSANGOMA_VERSION(3,0,0) -#undef LIBSANGOMA_VERSION -#endif -#endif - -/** - * \brief Wanpipe flags - */ -typedef enum { - WP_RINGING = (1 << 0) -} wp_flag_t; - -/** - * \brief Wanpipe globals - */ -static struct { - uint32_t codec_ms; - uint32_t rxqueue_size; - uint32_t txqueue_size; - uint32_t wink_ms; - uint32_t flash_ms; - uint32_t ring_on_ms; - uint32_t ring_off_ms; -} wp_globals; - -typedef struct { - sangoma_wait_obj_t *waitobj; -#ifdef WP_DEBUG_IO - /* record the last reader threads */ - pid_t readers[10]; - int rindex; - ftdm_time_t last_read; -#endif -} wp_channel_t; -#define WP_GET_WAITABLE(fchan) ((wp_channel_t *)((fchan)->io_data))->waitobj - -/* a bunch of this stuff should go into the wanpipe_tdm_api_iface.h */ - -FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event); -FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event); -FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event); - -static void wp_swap16(char *data, int datalen) -{ - int i = 0; - uint16_t *samples = (uint16_t *)data; - for (i = 0; i < datalen/2; i++) { - uint16_t sample = ((samples[i] & 0x00FF) << 8) | ((samples[i] & 0xFF00) >> 8); - samples[i] = sample; - } -} - -/** - * \brief Poll for event on a wanpipe socket - * \param fd Wanpipe socket descriptor - * \param timeout Time to wait for event - * \param flags Sangoma event flags - * \return -1 on failure, wanpipe event flags on success - * - * a cross platform way to poll on an actual pollset (span and/or list of spans) will probably also be needed for analog - * so we can have one analong handler thread that will deal with all the idle analog channels for events - * the alternative would be for the driver to provide one socket for all of the oob events for all analog channels - */ -static __inline__ int tdmv_api_wait_socket(ftdm_channel_t *ftdmchan, int timeout, int *flags) -{ - -#ifdef LIBSANGOMA_VERSION - int err; - uint32_t inflags = *flags; - uint32_t outflags = 0; - sangoma_wait_obj_t *sangoma_wait_obj = WP_GET_WAITABLE(ftdmchan); - - if (timeout == -1) { - timeout = SANGOMA_WAIT_INFINITE; - } - - err = sangoma_waitfor(sangoma_wait_obj, inflags, &outflags, timeout); - *flags = 0; - if (err == SANG_STATUS_SUCCESS) { - *flags = outflags; - err = 1; /* ideally should be the number of file descriptors with something to read */ - } - if (err == SANG_STATUS_APIPOLL_TIMEOUT) { - err = 0; - } - return err; -#else - struct pollfd pfds[1]; - int res; - - memset(&pfds[0], 0, sizeof(pfds[0])); - pfds[0].fd = ftdmchan->sockfd; - pfds[0].events = *flags; - res = poll(pfds, 1, timeout); - *flags = 0; - - if (pfds[0].revents & POLLERR) { - res = -1; - } - - if (res > 0) { - *flags = pfds[0].revents; - } - - return res; -#endif - -} - -/** - * \brief Opens a sangoma channel socket (TDM API) - * \param span Span number - * \param chan Channel number - * \return 0 on success, wanpipe error code on failure - */ -static __inline__ sng_fd_t tdmv_api_open_span_chan(int span, int chan) -{ - return sangoma_open_tdmapi_span_chan(span, chan); -} - -#ifdef LIBSANGOMA_VERSION -static __inline__ sng_fd_t __tdmv_api_open_span_chan(int span, int chan) -{ - return __sangoma_open_tdmapi_span_chan(span, chan); -} -#endif - -static ftdm_io_interface_t wanpipe_interface; - -/** - * \brief Inverts bit string - * \param cas_bits CAS bit string - * \return Swapped bits - */ -static unsigned char wanpipe_swap_bits(unsigned char cas_bits) -{ - unsigned char swapped_bits = 0x0; - if (cas_bits & 0x8) { - swapped_bits |= 0x1; - } - if (cas_bits & 0x4) { - swapped_bits |= 0x2; - } - if (cas_bits & 0x2) { - swapped_bits |= 0x4; - } - if (cas_bits & 0x1) { - swapped_bits |= 0x8; - } - return swapped_bits; -} - -/** - * \brief Initialises a range of wanpipe channels - * \param span FreeTDM span - * \param spanno Wanpipe span number - * \param start Initial wanpipe channel number - * \param end Final wanpipe channel number - * \param type FreeTDM channel type - * \param name FreeTDM span name - * \param number FreeTDM span number - * \param cas_bits CAS bits - * \return number of spans configured - */ -static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start, unsigned end, ftdm_chan_type_t type, char *name, char *number, unsigned char cas_bits) -{ - unsigned configured = 0, x; -#ifdef LIBSANGOMA_VERSION - sangoma_status_t sangstatus; - sangoma_wait_obj_t *sangoma_wait_obj; -#endif - - if (type == FTDM_CHAN_TYPE_CAS) { - ftdm_log(FTDM_LOG_DEBUG, "Configuring Wanpipe CAS channels with abcd == 0x%X\n", cas_bits); - } - for(x = start; x < end; x++) { - ftdm_channel_t *chan; - ftdm_socket_t sockfd = FTDM_INVALID_SOCKET; - const char *dtmf = "none"; - const char *hwec_str = "none"; - const char *hwec_idle = "none"; - if (!strncasecmp(span->name, "smg_prid_nfas", 8) && span->trunk_type == FTDM_TRUNK_T1 && x == 24) { -#ifdef LIBSANGOMA_VERSION - sockfd = __tdmv_api_open_span_chan(spanno, x); -#else - ftdm_log(FTDM_LOG_ERROR, "span %d channel %d cannot be configured as smg_prid_nfas, you need to compile freetdm with newer libsangoma\n", spanno, x); -#endif - } else { -#ifdef LIBSANGOMA_VERSION - sockfd = __tdmv_api_open_span_chan(spanno, x); -#else - sockfd = tdmv_api_open_span_chan(spanno, x); -#endif - } - - if (sockfd == FTDM_INVALID_SOCKET) { - ftdm_log(FTDM_LOG_ERROR, "Failed to open wanpipe device span %d channel %d\n", spanno, x); - continue; - } - - if (ftdm_span_add_channel(span, sockfd, type, &chan) == FTDM_SUCCESS) { - wp_channel_t *wpchan = NULL; - wanpipe_tdm_api_t tdm_api; - memset(&tdm_api, 0, sizeof(tdm_api)); -#ifdef LIBSANGOMA_VERSION - wpchan = ftdm_calloc(1, sizeof(*wpchan)); - ftdm_assert(wpchan != NULL, "wpchan alloc failed\n"); - chan->io_data = wpchan; - /* we need SANGOMA_DEVICE_WAIT_OBJ_SIG and not SANGOMA_DEVICE_WAIT_OBJ alone because we need to call - * sangoma_wait_obj_sig to wake up any I/O waiters when closing the channel (typically on ftdm shutdown) - * this adds an extra pair of file descriptors to the waitable object - * */ - sangstatus = sangoma_wait_obj_create(&sangoma_wait_obj, sockfd, SANGOMA_DEVICE_WAIT_OBJ_SIG); - if (sangstatus != SANG_STATUS_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "failure create waitable object for s%dc%d\n", spanno, x); - continue; - } - WP_GET_WAITABLE(chan) = sangoma_wait_obj; -#endif - - chan->physical_span_id = spanno; - chan->physical_chan_id = x; - chan->rate = 8000; - - if (type == FTDM_CHAN_TYPE_FXS - || type == FTDM_CHAN_TYPE_FXO - || type == FTDM_CHAN_TYPE_CAS - || type == FTDM_CHAN_TYPE_B) { - int err; - - hwec_str = "unavailable"; - hwec_idle = "enabled"; - dtmf = "software"; - - err = sangoma_tdm_get_hw_coding(chan->sockfd, &tdm_api); - - - - if (tdm_api.wp_tdm_cmd.hw_tdm_coding) { - chan->native_codec = chan->effective_codec = FTDM_CODEC_ALAW; - } else { - chan->native_codec = chan->effective_codec = FTDM_CODEC_ULAW; - } - - - if ((span->trunk_type == FTDM_TRUNK_GSM) && (chan->type == FTDM_CHAN_TYPE_B)) { - chan->native_codec = FTDM_CODEC_SLIN; - chan->native_interval = 20; - chan->packet_len = 320; - } - - err = sangoma_tdm_get_hw_dtmf(chan->sockfd, &tdm_api); - if (err > 0) { - ftdm_channel_set_feature(chan, FTDM_CHANNEL_FEATURE_DTMF_DETECT); - dtmf = "hardware"; - } - - err = sangoma_tdm_get_hw_ec(chan->sockfd, &tdm_api); - if (err > 0) { - hwec_str = "available"; - ftdm_channel_set_feature(chan, FTDM_CHANNEL_FEATURE_HWEC); - } - -#ifdef WP_API_FEATURE_HWEC_PERSIST - err = sangoma_tdm_get_hwec_persist_status(chan->sockfd, &tdm_api); - if (err == 0) { - ftdm_channel_set_feature(chan, FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE); - hwec_idle = "disabled"; - } -#else - if (span->trunk_type == FTDM_TRUNK_BRI || span->trunk_type == FTDM_TRUNK_BRI_PTMP) { - ftdm_log(FTDM_LOG_WARNING, "WP_API_FEATURE_HWEC_PERSIST feature is not supported \ - with your version of libsangoma, you should update your Wanpipe drivers\n"); - - } -#endif - - } - -#ifdef LIBSANGOMA_VERSION - if (type == FTDM_CHAN_TYPE_FXS) { - if (sangoma_tdm_disable_ring_trip_detect_events(chan->sockfd, &tdm_api)) { - /* we had problems of on-hook/off-hook detection due to how ring trip events were handled - * if this fails, I believe we will still work ok as long as we dont handle them incorrectly */ - ftdm_log(FTDM_LOG_WARNING, "Failed to disable ring trip events in channel s%dc%d\n", spanno, x); - } - } -#endif -#if 0 - if (type == FTDM_CHAN_TYPE_FXS || type == FTDM_CHAN_TYPE_FXO) { - /* Enable FLASH/Wink Events */ - int err=sangoma_set_rm_rxflashtime(chan->sockfd, &tdm_api, wp_globals.flash_ms); - if (err == 0) { - ftdm_log(FTDM_LOG_ERROR, "flash enabled s%dc%d\n", spanno, x); - } else { - ftdm_log(FTDM_LOG_ERROR, "flash disabled s%dc%d\n", spanno, x); - } - } -#endif - - if (type == FTDM_CHAN_TYPE_CAS || type == FTDM_CHAN_TYPE_EM) { -#ifdef LIBSANGOMA_VERSION - sangoma_tdm_write_rbs(chan->sockfd,&tdm_api,chan->physical_chan_id, wanpipe_swap_bits(cas_bits)); - - /* this should probably be done for old libsangoma but I am not sure if the API is available and I'm lazy to check, - The poll rate is hard coded to 100 per second (done in the driver, is the max rate of polling allowed by wanpipe) - */ - if (sangoma_tdm_enable_rbs_events(chan->sockfd, &tdm_api, 100)) { - ftdm_log(FTDM_LOG_ERROR, "Failed to enable RBS/CAS events in device %d:%d fd:%d\n", chan->span_id, chan->chan_id, sockfd); - continue; - } - sangoma_flush_bufs(chan->sockfd, &tdm_api); - sangoma_flush_event_bufs(chan->sockfd, &tdm_api); -#else - /* - * With wanpipe 3.4.4.2 I get failure even though the events are enabled, /var/log/messages said: - * wanpipe4: WARNING: Event type 9 is already pending! - * wanpipe4: Failed to add new fe event 09 ch_map=FFFFFFFF! - * may be we should not send an error until that is fixed in the driver - */ - if (sangoma_tdm_enable_rbs_events(chan->sockfd, &tdm_api, 100)) { - ftdm_log(FTDM_LOG_ERROR, "Failed to enable RBS/CAS events in device %d:%d fd:%d\n", chan->span_id, chan->chan_id, sockfd); - } - /* probably done by the driver but lets write defensive code this time */ - sangoma_tdm_flush_bufs(chan->sockfd, &tdm_api); - sangoma_tdm_write_rbs(chan->sockfd,&tdm_api, wanpipe_swap_bits(cas_bits)); -#endif - } - - if (!ftdm_strlen_zero(name)) { - ftdm_copy_string(chan->chan_name, name, sizeof(chan->chan_name)); - } - - if (!ftdm_strlen_zero(number)) { - ftdm_copy_string(chan->chan_number, number, sizeof(chan->chan_number)); - } - configured++; - ftdm_log_chan(chan, FTDM_LOG_INFO, "Configured wanpipe device FD: %d, DTMF: %s, HWEC: %s, HWEC_IDLE: %s\n", - sockfd, dtmf, hwec_str, hwec_idle); - - } else { - ftdm_log(FTDM_LOG_ERROR, "ftdm_span_add_channel failed for wanpipe span %d channel %d\n", spanno, x); - } - } - - return configured; -} - -/** - * \brief Process configuration variable for a Wanpipe profile - * \param category Wanpipe profile name - * \param var Variable name - * \param val Variable value - * \param lineno Line number from configuration file - * \return Success - */ -static FIO_CONFIGURE_FUNCTION(wanpipe_configure) -{ - int num; - - if (!strcasecmp(category, "defaults")) { - if (!strcasecmp(var, "codec_ms")) { - num = atoi(val); - if (num < 10 || num > 60) { - ftdm_log(FTDM_LOG_WARNING, "invalid codec ms at line %d\n", lineno); - } else { - wp_globals.codec_ms = num; - } - } else if (!strcasecmp(var, "rxqueue_size")) { - num = atoi(val); - if (num < 1 || num > 1000) { - ftdm_log(FTDM_LOG_WARNING, "invalid rx queue size at line %d\n", lineno); - } else { - wp_globals.rxqueue_size = num; - } - } else if (!strcasecmp(var, "txqueue_size")) { - num = atoi(val); - if (num < 1 || num > 1000) { - ftdm_log(FTDM_LOG_WARNING, "invalid tx queue size at line %d\n", lineno); - } else { - wp_globals.txqueue_size = num; - } - } else if (!strcasecmp(var, "wink_ms")) { - num = atoi(val); - if (num < 50 || num > 3000) { - ftdm_log(FTDM_LOG_WARNING, "invalid wink ms at line %d\n", lineno); - } else { - wp_globals.wink_ms = num; - } - } else if (!strcasecmp(var, "flash_ms")) { - num = atoi(val); - if (num < 50 || num > 3000) { - ftdm_log(FTDM_LOG_WARNING, "invalid flash ms at line %d\n", lineno); - } else { - wp_globals.flash_ms = num; - } - } else if (!strcasecmp(var, "ring_on_ms")) { - num = atoi(val); - if (num < 500 || num > 5000) { - ftdm_log(FTDM_LOG_WARNING, "invalid ring_on_ms at line %d (valid range 500 to 5000)\n", lineno); - } else { - wp_globals.ring_on_ms = num; - } - } else if (!strcasecmp(var, "ring_off_ms")) { - num = atoi(val); - if (num < 500 || num > 5000) { - ftdm_log(FTDM_LOG_WARNING, "invalid ring_off_ms at line %d (valid range 500 to 5000)\n", lineno); - } else { - wp_globals.ring_off_ms = num; - } - } - - } - - return FTDM_SUCCESS; -} - -/** - * \brief Initialises an freetdm Wanpipe span from a configuration string - * \param span FreeTDM span - * \param str Configuration string - * \param type FreeTDM span type - * \param name FreeTDM span name - * \param number FreeTDM span number - * \return Success or failure - */ -static FIO_CONFIGURE_SPAN_FUNCTION(wanpipe_configure_span) -{ - int items, i; - char *mydata, *item_list[10]; - char *sp, *ch, *mx; - unsigned char cas_bits = 0; - int channo; - int spanno; - int top = 0; - unsigned configured = 0; - - assert(str != NULL); - - - mydata = ftdm_strdup(str); - assert(mydata != NULL); - - - items = ftdm_separate_string(mydata, ',', item_list, (sizeof(item_list) / sizeof(item_list[0]))); - - for(i = 0; i < items; i++) { - sp = item_list[i]; - if ((ch = strchr(sp, ':'))) { - *ch++ = '\0'; - } - - if (!(sp && ch)) { - ftdm_log(FTDM_LOG_ERROR, "No valid wanpipe span and channel was specified\n"); - continue; - } - - channo = atoi(ch); - spanno = atoi(sp); - - if (channo < 0) { - ftdm_log(FTDM_LOG_ERROR, "Invalid channel number %d\n", channo); - continue; - } - - if (spanno < 0) { - ftdm_log(FTDM_LOG_ERROR, "Invalid span number %d\n", channo); - continue; - } - - if ((mx = strchr(ch, '-'))) { - mx++; - top = atoi(mx) + 1; - } else { - top = channo + 1; - } - - - if (top < 0) { - ftdm_log(FTDM_LOG_ERROR, "Invalid range number %d\n", top); - continue; - } - if (FTDM_CHAN_TYPE_CAS == type && ftdm_config_get_cas_bits(ch, &cas_bits)) { - ftdm_log(FTDM_LOG_ERROR, "Failed to get CAS bits in CAS channel\n"); - continue; - } - configured += wp_open_range(span, spanno, channo, top, type, name, number, cas_bits); - - } - - ftdm_safe_free(mydata); - - return configured; -} - -/** - * \brief Opens Wanpipe channel - * \param ftdmchan Channel to open - * \return Success or failure - */ -static FIO_OPEN_FUNCTION(wanpipe_open) -{ - - wanpipe_tdm_api_t tdm_api; - - memset(&tdm_api,0,sizeof(tdm_api)); - - sangoma_tdm_flush_bufs(ftdmchan->sockfd, &tdm_api); - sangoma_flush_stats(ftdmchan->sockfd, &tdm_api); - memset(&ftdmchan->iostats, 0, sizeof(ftdmchan->iostats)); - - if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921 || ftdmchan->type == FTDM_CHAN_TYPE_DQ931) { - ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_NONE; - } else { - ftdmchan->effective_codec = ftdmchan->native_codec; - - sangoma_tdm_set_usr_period(ftdmchan->sockfd, &tdm_api, wp_globals.codec_ms); - - ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_INTERVAL); - ftdmchan->effective_interval = ftdmchan->native_interval = wp_globals.codec_ms; - - /* The packet len will depend on the codec and interval */ - ftdmchan->packet_len = ftdmchan->native_interval * ((ftdmchan->native_codec==FTDM_CODEC_SLIN) ? 16 : 8); - if (wp_globals.txqueue_size > 0) { - ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &wp_globals.txqueue_size); - } - if (wp_globals.rxqueue_size > 0) { - ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_RX_QUEUE_SIZE, &wp_globals.rxqueue_size); - } - } - - return FTDM_SUCCESS; -} - -/** - * \brief Closes Wanpipe channel - * \param ftdmchan Channel to close - * \return Success - */ -static FIO_CLOSE_FUNCTION(wanpipe_close) -{ -#ifdef LIBSANGOMA_VERSION - sangoma_wait_obj_t *waitobj = WP_GET_WAITABLE(ftdmchan); - /* kick any I/O waiters */ - sangoma_wait_obj_signal(waitobj); -#ifdef WP_DEBUG_IO - { - wp_channel_t *wchan = ftdmchan->io_data; - memset(wchan->readers, 0, sizeof(wchan->readers)); - wchan->rindex = 0; - } -#endif -#endif - return FTDM_SUCCESS; -} - -/** - * \brief Executes an FreeTDM command on a Wanpipe channel - * \param ftdmchan Channel to execute command on - * \param command FreeTDM command to execute - * \param obj Object (unused) - * \return Success or failure - */ -static FIO_COMMAND_FUNCTION(wanpipe_command) -{ - wanpipe_tdm_api_t tdm_api; - int err = 0; - - memset(&tdm_api, 0, sizeof(tdm_api)); - - switch(command) { - case FTDM_COMMAND_OFFHOOK: - { - err=sangoma_tdm_txsig_offhook(ftdmchan->sockfd,&tdm_api); - if (err) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "OFFHOOK Failed"); - return FTDM_FAIL; - } - ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK); - } - break; - case FTDM_COMMAND_ONHOOK: - { - err=sangoma_tdm_txsig_onhook(ftdmchan->sockfd,&tdm_api); - if (err) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "ONHOOK Failed"); - return FTDM_FAIL; - } - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK); - } - break; - case FTDM_COMMAND_GENERATE_RING_ON: - { - err=sangoma_tdm_txsig_start(ftdmchan->sockfd,&tdm_api); - if (err) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Ring Failed"); - return FTDM_FAIL; - } - ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_RINGING); - ftdm_set_pflag_locked(ftdmchan, WP_RINGING); - ftdmchan->ring_time = ftdm_current_time_in_ms() + wp_globals.ring_on_ms; - } - break; - case FTDM_COMMAND_GENERATE_RING_OFF: - { - err=sangoma_tdm_txsig_offhook(ftdmchan->sockfd,&tdm_api); - if (err) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Ring-off Failed"); - return FTDM_FAIL; - } - ftdm_clear_pflag_locked(ftdmchan, WP_RINGING); - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_RINGING); - } - break; - case FTDM_COMMAND_GET_INTERVAL: - { - err=sangoma_tdm_get_usr_period(ftdmchan->sockfd, &tdm_api); - if (err > 0 ) { - FTDM_COMMAND_OBJ_INT = err; - err=0; - } - } - break; - case FTDM_COMMAND_ENABLE_ECHOCANCEL: - { -#ifdef WP_API_FEATURE_EC_CHAN_STAT - err=sangoma_tdm_get_hwec_chan_status(ftdmchan->sockfd, &tdm_api); - if (err > 0) { - /* Hardware echo canceller already enabled */ - err = 0; - break; - } -#endif - err=sangoma_tdm_enable_hwec(ftdmchan->sockfd, &tdm_api); - if (err) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "HWEC Enable Failed"); - return FTDM_FAIL; - } - } - break; - case FTDM_COMMAND_DISABLE_ECHOCANCEL: - { -#ifdef WP_API_FEATURE_EC_CHAN_STAT - err=sangoma_tdm_get_hwec_chan_status(ftdmchan->sockfd, &tdm_api); - if (!err) { - /* Hardware echo canceller already disabled */ - break; - } -#endif - err=sangoma_tdm_disable_hwec(ftdmchan->sockfd, &tdm_api); - if (err) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "HWEC Disable Failed"); - return FTDM_FAIL; - } - } - break; - case FTDM_COMMAND_DISABLE_ECHOTRAIN: { err = 0; } - break; - case FTDM_COMMAND_ENABLE_DTMF_DETECT: - { -#ifdef WP_API_FEATURE_DTMF_EVENTS - err = sangoma_tdm_enable_dtmf_events(ftdmchan->sockfd, &tdm_api); - if (err) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Enabling of Sangoma HW DTMF failed\n"); - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "HW DTMF Enable Failed"); - return FTDM_FAIL; - } - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Enabled DTMF events\n"); -#else - return FTDM_NOTIMPL; -#endif - } - break; - case FTDM_COMMAND_DISABLE_DTMF_DETECT: - { -#ifdef WP_API_FEATURE_DTMF_EVENTS - err = sangoma_tdm_disable_dtmf_events(ftdmchan->sockfd, &tdm_api); - if (err) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Disabling of Sangoma HW DTMF failed\n"); - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "HW DTMF Disable Failed"); - return FTDM_FAIL; - } - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Disabled DTMF events\n"); -#else - return FTDM_NOTIMPL; -#endif - } - break; - case FTDM_COMMAND_ENABLE_DTMF_REMOVAL: - { -#ifdef WP_API_FEATURE_DTMF_REMOVAL - int return_code = 0; - err = sangoma_hwec_set_hwdtmf_removal(ftdmchan->sockfd, ftdmchan->physical_chan_id, &return_code, 1, 0); - if (return_code) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Wanpipe failed to Enable HW-DTMF removal\n"); - } -#endif - } - break; - case FTDM_COMMAND_DISABLE_DTMF_REMOVAL: - { -#ifdef WP_API_FEATURE_DTMF_REMOVAL - int return_code = 0; - err = sangoma_hwec_set_hwdtmf_removal(ftdmchan->sockfd, ftdmchan->physical_chan_id, &return_code, 0, 0); - if (return_code) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Wanpipe failed to Disable HW-DTMF removal\n"); - } -#endif - } - break; - case FTDM_COMMAND_ENABLE_LOOP: - { -#ifdef WP_API_FEATURE_LOOP - err=sangoma_tdm_enable_loop(ftdmchan->sockfd, &tdm_api); - if (err) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Loop Enable Failed"); - return FTDM_FAIL; - } -#endif - } - break; - case FTDM_COMMAND_DISABLE_LOOP: - { -#ifdef WP_API_FEATURE_LOOP - err=sangoma_tdm_disable_loop(ftdmchan->sockfd, &tdm_api); - if (err) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Loop Disable Failed"); - return FTDM_FAIL; - } -#endif - } - break; - case FTDM_COMMAND_SET_INTERVAL: - { - err=sangoma_tdm_set_usr_period(ftdmchan->sockfd, &tdm_api, FTDM_COMMAND_OBJ_INT); - - ftdmchan->packet_len = ftdmchan->native_interval * (ftdmchan->effective_codec == FTDM_CODEC_SLIN ? 16 : 8); - } - break; - case FTDM_COMMAND_SET_CAS_BITS: - { -#ifdef LIBSANGOMA_VERSION - err = sangoma_tdm_write_rbs(ftdmchan->sockfd,&tdm_api, ftdmchan->physical_chan_id, wanpipe_swap_bits(FTDM_COMMAND_OBJ_INT)); -#else - err = sangoma_tdm_write_rbs(ftdmchan->sockfd, &tdm_api, wanpipe_swap_bits(FTDM_COMMAND_OBJ_INT)); -#endif - } - break; - case FTDM_COMMAND_GET_CAS_BITS: - { -#ifdef LIBSANGOMA_VERSION - unsigned char rbsbits; - err = sangoma_tdm_read_rbs(ftdmchan->sockfd, &tdm_api, ftdmchan->physical_chan_id, &rbsbits); - if (!err) { - FTDM_COMMAND_OBJ_INT = wanpipe_swap_bits(rbsbits); - } -#else - /* is sangoma_tdm_read_rbs available here? */ - FTDM_COMMAND_OBJ_INT = ftdmchan->rx_cas_bits; -#endif - } - break; - case FTDM_COMMAND_SET_LINK_STATUS: - { - ftdm_channel_hw_link_status_t status = FTDM_COMMAND_OBJ_INT; - char sangoma_status = status == FTDM_HW_LINK_CONNECTED ? FE_CONNECTED : FE_DISCONNECTED; - err = sangoma_tdm_set_fe_status(ftdmchan->sockfd, &tdm_api, sangoma_status); - } - break; - case FTDM_COMMAND_GET_LINK_STATUS: - { - unsigned char sangoma_status = 0; - err = sangoma_tdm_get_fe_status(ftdmchan->sockfd, &tdm_api, &sangoma_status); - if (!err) { - FTDM_COMMAND_OBJ_INT = sangoma_status == FE_CONNECTED ? FTDM_HW_LINK_CONNECTED : FTDM_HW_LINK_DISCONNECTED; - } - } - break; - case FTDM_COMMAND_FLUSH_BUFFERS: - { - err = sangoma_flush_bufs(ftdmchan->sockfd, &tdm_api); - } - break; - case FTDM_COMMAND_FLUSH_RX_BUFFERS: - { - err = sangoma_flush_rx_bufs(ftdmchan->sockfd, &tdm_api); - } - break; - case FTDM_COMMAND_FLUSH_TX_BUFFERS: - { - err = sangoma_flush_tx_bufs(ftdmchan->sockfd, &tdm_api); - } - break; - case FTDM_COMMAND_FLUSH_IOSTATS: - { - err = sangoma_flush_stats(ftdmchan->sockfd, &tdm_api); - memset(&ftdmchan->iostats, 0, sizeof(ftdmchan->iostats)); - } - break; - case FTDM_COMMAND_SET_RX_QUEUE_SIZE: - { - uint32_t queue_size = FTDM_COMMAND_OBJ_INT; - err = sangoma_set_rx_queue_sz(ftdmchan->sockfd, &tdm_api, queue_size); - } - break; - case FTDM_COMMAND_SET_TX_QUEUE_SIZE: - { - uint32_t queue_size = FTDM_COMMAND_OBJ_INT; - err = sangoma_set_tx_queue_sz(ftdmchan->sockfd, &tdm_api, queue_size); - } - break; - case FTDM_COMMAND_SET_POLARITY: - { - ftdm_polarity_t polarity = FTDM_COMMAND_OBJ_INT; - err = sangoma_tdm_set_polarity(ftdmchan->sockfd, &tdm_api, polarity); - if (!err) { - ftdmchan->polarity = polarity; - } - } - break; - default: - err = FTDM_NOTIMPL; - break; - }; - - if (err) { - int myerrno = errno; - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Wanpipe failed to execute command %d: %s\n", command, strerror(myerrno)); - errno = myerrno; - return err; - } - - return FTDM_SUCCESS; -} - -static void wanpipe_write_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_tx_hdr_t *tx_stats) -{ - ftdmchan->iostats.tx.errors = tx_stats->wp_api_tx_hdr_errors; - ftdmchan->iostats.tx.queue_size = tx_stats->wp_api_tx_hdr_max_queue_length; - ftdmchan->iostats.tx.queue_len = tx_stats->wp_api_tx_hdr_number_of_frames_in_queue; - - /* we don't test for 80% full in tx since is typically full for voice channels, should we test tx 80% full for D-channels? */ - if (ftdmchan->iostats.tx.queue_len >= ftdmchan->iostats.tx.queue_size) { - ftdm_set_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL); - } else if (ftdm_test_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL)){ - ftdm_clear_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL); - } - - if (ftdmchan->iostats.tx.idle_packets < tx_stats->wp_api_tx_hdr_tx_idle_packets) { - ftdmchan->iostats.tx.idle_packets = tx_stats->wp_api_tx_hdr_tx_idle_packets; - } - - if (!ftdmchan->iostats.tx.packets) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "First packet write stats: Tx queue len: %d, Tx queue size: %d, Tx idle: %"FTDM_UINT64_FMT"\n", - ftdmchan->iostats.tx.queue_len, - ftdmchan->iostats.tx.queue_size, - ftdmchan->iostats.tx.idle_packets); - } - - ftdmchan->iostats.tx.packets++; -} - -static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx_stats) -{ - ftdmchan->iostats.rx.errors = rx_stats->wp_api_rx_hdr_errors; - ftdmchan->iostats.rx.queue_size = rx_stats->wp_api_rx_hdr_max_queue_length; - ftdmchan->iostats.rx.queue_len = rx_stats->wp_api_rx_hdr_number_of_frames_in_queue; - - if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_ABORT_ERROR_BIT))) { - ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT); - } else { - ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT); - } - - if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_DMA_ERROR_BIT))) { - ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA); - } else { - ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA); - } - - if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_FIFO_ERROR_BIT))) { - ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO); - } else { - ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO); - } - - if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_CRC_ERROR_BIT))) { - ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC); - } else { - ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC); - } - - if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_FRAME_ERROR_BIT))) { - ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME); - } else { - ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME); - } - - if (ftdmchan->iostats.rx.queue_len >= (0.8 * ftdmchan->iostats.rx.queue_size)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Rx Queue length exceeded 80%% threshold (%d/%d)\n", - ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); - ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); - } else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Rx Queue length reduced 80%% threshold (%d/%d)\n", - ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); - ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); - } - - if (ftdmchan->iostats.rx.queue_len >= ftdmchan->iostats.rx.queue_size) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Rx Queue Full (%d/%d)\n", - ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); - ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); - } else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)){ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Rx Queue no longer full (%d/%d)\n", - ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); - ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); - } - - if (!ftdmchan->iostats.rx.packets) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "First packet read stats: Rx queue len: %d, Rx queue size: %d\n", - ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); - } - - ftdmchan->iostats.rx.packets++; -} - -/** - * \brief Reads data from a Wanpipe channel - * \param ftdmchan Channel to read from - * \param data Data buffer - * \param datalen Size of data buffer - * \return Success, failure or timeout - */ - - -static FIO_READ_FUNCTION(wanpipe_read) -{ - int rx_len = 0; - int rq_len = (int)*datalen; - wp_tdm_api_rx_hdr_t hdrframe; - - -#ifdef WP_DEBUG_IO - wp_channel_t *wchan = ftdmchan->io_data; - ftdm_time_t time_diff = 0; - pid_t previous_thread = 1; - pid_t current_thread = 0; - int previous_thread_index = 0; - - previous_thread_index = wchan->rindex == 0 ? (ftdm_array_len(wchan->readers) - 1) : wchan->rindex - 1; - previous_thread = wchan->readers[previous_thread_index]; - current_thread = syscall(SYS_gettid); - if (current_thread && current_thread != wchan->readers[wchan->rindex]) { - if (!wchan->readers[wchan->rindex]) { - wchan->readers[wchan->rindex] = current_thread; - /* first read */ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Initial reader thread is %d\n", current_thread); - previous_thread = current_thread; - } else { - previous_thread = wchan->readers[wchan->rindex]; - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Changed reader thread from %d to %d (rindex = %d)\n", - previous_thread, current_thread, wchan->rindex); - if (wchan->rindex == (ftdm_array_len(wchan->readers) - 1)) { - wchan->rindex = 0; - } else { - wchan->rindex++; - } - wchan->readers[wchan->rindex] = current_thread; - } - } - ftdm_time_t curr = ftdm_current_time_in_ms(); - if (wchan->last_read) { - time_diff = curr - wchan->last_read; - } -#endif - - memset(&hdrframe, 0, sizeof(hdrframe)); - rx_len = sangoma_readmsg_tdm(ftdmchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (int)*datalen, 0); - *datalen = 0; - - if (rx_len == 0) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Read 0 bytes\n"); - return FTDM_TIMEOUT; - } - - if (rx_len < 0) { -#ifdef WP_DEBUG_IO - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read %d bytes from sangoma device: %s (%d) " - "(read time diff = %llums, prev thread = %d, curr thread = %d)\n", rq_len, strerror(errno), rx_len, - time_diff, previous_thread, current_thread); -#else - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read %d bytes from sangoma device: %s (%d)\n", rq_len, strerror(errno), rx_len); -#endif - return FTDM_FAIL; - } - *datalen = rx_len; - - if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS)) { - wanpipe_read_stats(ftdmchan, &hdrframe); - } - - if ((ftdmchan->type == FTDM_CHAN_TYPE_B) && (ftdmchan->span->trunk_type == FTDM_TRUNK_GSM)) { - wp_swap16(data, *datalen); - } - - return FTDM_SUCCESS; -} - -/** - * \brief Writes data to a Wanpipe channel - * \param ftdmchan Channel to write to - * \param data Data buffer - * \param datalen Size of data buffer - * \return Success or failure - */ -static FIO_WRITE_FUNCTION(wanpipe_write) -{ - int bsent = 0; - int err = 0; - wp_tdm_api_tx_hdr_t hdrframe; - - if ((ftdmchan->type == FTDM_CHAN_TYPE_B) && (ftdmchan->span->trunk_type == FTDM_TRUNK_GSM)) { - wp_swap16(data, *datalen); - } - - /* Do we even need the headerframe here? on windows, we don't even pass it to the driver */ - memset(&hdrframe, 0, sizeof(hdrframe)); - if (*datalen == 0) { - return FTDM_SUCCESS; - } - - if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS) && !ftdmchan->iostats.tx.packets) { - wanpipe_tdm_api_t tdm_api; - memset(&tdm_api, 0, sizeof(tdm_api)); - /* if this is the first write ever, flush the tx first to have clean stats */ - err = sangoma_flush_tx_bufs(ftdmchan->sockfd, &tdm_api); - if (err) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to flush on first write\n"); - } - } - - bsent = sangoma_writemsg_tdm(ftdmchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (unsigned short)(*datalen),0); - - /* should we be checking if bsent == *datalen here? */ - if (bsent > 0) { - *datalen = bsent; - if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS)) { - /* BRI cards do not support TX queues for now */ - if(!FTDM_SPAN_IS_BRI(ftdmchan->span)) { - wanpipe_write_stats(ftdmchan, &hdrframe); - } - } - return FTDM_SUCCESS; - } - - return FTDM_FAIL; -} - -/** - * \brief Waits for an event on a Wanpipe channel - * \param ftdmchan Channel to open - * \param flags Type of event to wait for - * \param to Time to wait (in ms) - * \return Success, failure or timeout - */ - -static FIO_WAIT_FUNCTION(wanpipe_wait) -{ - int32_t inflags = 0; - int result; - - if (*flags & FTDM_READ) { - inflags |= POLLIN; - } - - if (*flags & FTDM_WRITE) { - inflags |= POLLOUT; - } - - if (*flags & FTDM_EVENTS) { - inflags |= POLLPRI; - } - - result = tdmv_api_wait_socket(ftdmchan, to, &inflags); - - *flags = FTDM_NO_FLAGS; - - if (result < 0){ - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Poll failed"); - return FTDM_FAIL; - } - - if (result == 0) { - return FTDM_TIMEOUT; - } - - if (inflags & POLLIN) { - *flags |= FTDM_READ; - } - - if (inflags & POLLOUT) { - *flags |= FTDM_WRITE; - } - - if (inflags & POLLPRI) { - *flags |= FTDM_EVENTS; - } - - return FTDM_SUCCESS; -} - -/** - * \brief Checks for events on a Wanpipe span - * \param span Span to check for events - * \param ms Time to wait for event - * \return Success if event is waiting or failure if not - */ -FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event) -{ -#ifdef LIBSANGOMA_VERSION - sangoma_status_t sangstatus; - sangoma_wait_obj_t *pfds[FTDM_MAX_CHANNELS_SPAN] = { 0 }; - uint32_t inflags[FTDM_MAX_CHANNELS_SPAN]; - uint32_t outflags[FTDM_MAX_CHANNELS_SPAN]; -#else - struct pollfd pfds[FTDM_MAX_CHANNELS_SPAN]; -#endif - uint32_t i, j = 0, k = 0, l = 0; - int r; - - for(i = 1; i <= span->chan_count; i++) { - ftdm_channel_t *ftdmchan = span->channels[i]; - uint32_t chan_events = 0; - - /* translate events from ftdm to libsnagoma. if the user don't specify which events to poll the - * channel for, we just use SANG_WAIT_OBJ_HAS_EVENTS */ - if (poll_events) { - if (poll_events[j] & FTDM_READ) { - chan_events = SANG_WAIT_OBJ_HAS_INPUT; - } - if (poll_events[j] & FTDM_WRITE) { - chan_events |= SANG_WAIT_OBJ_HAS_OUTPUT; - } - if (poll_events[j] & FTDM_EVENTS) { - chan_events |= SANG_WAIT_OBJ_HAS_EVENTS; - } - } else { - chan_events = SANG_WAIT_OBJ_HAS_EVENTS; - } - -#ifdef LIBSANGOMA_VERSION - if (!ftdmchan->io_data) { - continue; /* should never happen but happens when shutting down */ - } - pfds[j] = WP_GET_WAITABLE(ftdmchan); - inflags[j] = chan_events; -#else - memset(&pfds[j], 0, sizeof(pfds[j])); - pfds[j].fd = span->channels[i]->sockfd; - pfds[j].events = chan_events; -#endif - - /* The driver probably should be able to do this wink/flash/ringing by itself this is sort of a hack to make it work! */ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_WINK) || ftdm_test_flag(ftdmchan, FTDM_CHANNEL_FLASH)) { - l = 5; - } - - j++; - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_RINGING)) { - l = 5; - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_RINGING) && ftdm_current_time_in_ms() >= ftdmchan->ring_time) { - wanpipe_tdm_api_t tdm_api; - int err; - memset(&tdm_api, 0, sizeof(tdm_api)); - if (ftdm_test_pflag(ftdmchan, WP_RINGING)) { - err = sangoma_tdm_txsig_offhook(ftdmchan->sockfd,&tdm_api); - if (err) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Ring-off Failed"); - ftdm_log(FTDM_LOG_ERROR, "sangoma_tdm_txsig_offhook failed\n"); - return FTDM_FAIL; - } - ftdm_clear_pflag_locked(ftdmchan, WP_RINGING); - ftdmchan->ring_time = ftdm_current_time_in_ms() + wp_globals.ring_off_ms; - } else { - err=sangoma_tdm_txsig_start(ftdmchan->sockfd,&tdm_api); - if (err) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Ring Failed"); - ftdm_log(FTDM_LOG_ERROR, "sangoma_tdm_txsig_start failed\n"); - return FTDM_FAIL; - } - ftdm_set_pflag_locked(ftdmchan, WP_RINGING); - ftdmchan->ring_time = ftdm_current_time_in_ms() + wp_globals.ring_on_ms; - } - } - } - - if (l) { - ms = l; - } -#ifdef LIBSANGOMA_VERSION - sangstatus = sangoma_waitfor_many(pfds, inflags, outflags, j, ms); - if (SANG_STATUS_APIPOLL_TIMEOUT == sangstatus) { - r = 0; - } else if (SANG_STATUS_SUCCESS == sangstatus) { - r = 1; /* hopefully we never need how many changed -_- */ - } else { - ftdm_log(FTDM_LOG_ERROR, "sangoma_waitfor_many failed: %d, %s\n", sangstatus, strerror(errno)); - r = -1; - } -#else - r = poll(pfds, j, ms); -#endif - - if (r == 0) { - return l ? FTDM_SUCCESS : FTDM_TIMEOUT; - } else if (r < 0) { - snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno)); - return FTDM_FAIL; - } - - for(i = 1; i <= span->chan_count; i++) { - ftdm_channel_t *ftdmchan = span->channels[i]; - -#ifdef LIBSANGOMA_VERSION - if (outflags[i-1] & POLLPRI) { -#else - if (pfds[i-1].revents & POLLPRI) { -#endif - ftdm_set_io_flag(ftdmchan, FTDM_CHANNEL_IO_EVENT); - ftdmchan->last_event_time = ftdm_current_time_in_ms(); - k++; - } -#ifdef LIBSANGOMA_VERSION - if (outflags[i-1] & POLLIN) { -#else - if (pfds[i-1].revents & POLLIN) { -#endif - ftdm_set_io_flag(ftdmchan, FTDM_CHANNEL_IO_READ); - } -#ifdef LIBSANGOMA_VERSION - if (outflags[i-1] & POLLOUT) { -#else - if (pfds[i-1].revents & POLLOUT) { -#endif - ftdm_set_io_flag(ftdmchan, FTDM_CHANNEL_IO_WRITE); - } - } - /* when k is 0 it might be that an async wanpipe device signal was delivered */ - return FTDM_SUCCESS; -} - -/** - * \brief Gets alarms from a Wanpipe Channel - * \param ftdmchan Channel to get alarms from - * \return Success or failure - */ -static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms) -{ - wanpipe_tdm_api_t tdm_api; - unsigned int alarms = 0; - int err; - - memset(&tdm_api, 0, sizeof(tdm_api)); - -#ifdef LIBSANGOMA_VERSION - if ((err = sangoma_tdm_get_fe_alarms(ftdmchan->sockfd, &tdm_api, &alarms))) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "ioctl failed (%s)", strerror(errno)); - snprintf(ftdmchan->span->last_error, sizeof(ftdmchan->span->last_error), "ioctl failed (%s)", strerror(errno)); - return FTDM_FAIL; - } -#else - if ((err = sangoma_tdm_get_fe_alarms(ftdmchan->sockfd, &tdm_api)) < 0){ - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "ioctl failed (%s)", strerror(errno)); - snprintf(ftdmchan->span->last_error, sizeof(ftdmchan->span->last_error), "ioctl failed (%s)", strerror(errno)); - return FTDM_FAIL; - } - alarms = tdm_api.wp_tdm_cmd.fe_alarms; -#endif -#ifdef WIN32 - /* Temporary fix: in the current trunk of libsangoma, for BRI, - WAN_TE_BIT_ALARM_RED bit is set if the card is in disconnected state, but this has - not been ported to Windows-libsangoma yet */ - if (FTDM_SPAN_IS_BRI(ftdmchan->span)) { - if (alarms) { - ftdmchan->alarm_flags |= FTDM_ALARM_RED; - alarms = 0; - } - } -#endif - - ftdmchan->alarm_flags = FTDM_ALARM_NONE; - - if (alarms & WAN_TE_BIT_ALARM_RED) { - ftdmchan->alarm_flags |= FTDM_ALARM_RED; - alarms &= ~WAN_TE_BIT_ALARM_RED; - } - - - if (alarms & WAN_TE_BIT_ALARM_AIS) { - ftdmchan->alarm_flags |= FTDM_ALARM_BLUE; - alarms &= ~WAN_TE_BIT_ALARM_AIS; - } - - if (alarms & WAN_TE_BIT_ALARM_RAI) { - ftdmchan->alarm_flags |= FTDM_ALARM_YELLOW; - alarms &= ~WAN_TE_BIT_ALARM_RAI; - } - - if (!ftdmchan->alarm_flags) { - /* there is a bug in wanpipe where alarms were not properly set when they should be - * on at application startup, until that is fixed we check the link status here too */ - ftdm_channel_hw_link_status_t sangoma_status = 0; - ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_LINK_STATUS, &sangoma_status); - ftdmchan->alarm_flags = sangoma_status == FTDM_HW_LINK_DISCONNECTED ? FTDM_ALARM_RED : FTDM_ALARM_NONE; - } - - if (alarms) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Unmapped wanpipe alarms: %d\n", alarms); - } - - return FTDM_SUCCESS; -} - -/** - * \brief Process an event in a channel and set it's OOB event id. The channel must be locked. - * \param fchan Channel in which event occured - * \param event_id Pointer where we save the OOB event id - * \param tdm_api Wanpipe tdm struct that contain the event - * \return FTDM_SUCCESS or FTDM_FAIL - */ -static __inline__ ftdm_status_t wanpipe_channel_process_event(ftdm_channel_t *fchan, ftdm_oob_event_t *event_id, wanpipe_tdm_api_t *tdm_api) -{ - ftdm_status_t status = FTDM_SUCCESS; - - switch(tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_type) { - case WP_API_EVENT_LINK_STATUS: - { - if (FTDM_IS_DIGITAL_CHANNEL(fchan)) { - switch(tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_link_status) { - case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED: - /* *event_id = FTDM_OOB_ALARM_CLEAR; */ - ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Ignoring wanpipe link connected event\n"); - break; - default: - /* *event_id = FTDM_OOB_ALARM_TRAP; */ - ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Ignoring wanpipe link disconnected event\n"); - break; - } - /* The WP_API_EVENT_ALARM event should be used to clear alarms */ - *event_id = FTDM_OOB_NOOP; - } else { - switch(tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_link_status) { - case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED: - /* *event_id = FTDM_OOB_ALARM_CLEAR; */ - ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Using analog link connected event as alarm clear\n"); - *event_id = FTDM_OOB_ALARM_CLEAR; - fchan->alarm_flags = FTDM_ALARM_NONE; - break; - default: - /* *event_id = FTDM_OOB_ALARM_TRAP; */ - ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Using analog link disconnected event as alarm trap\n"); - *event_id = FTDM_OOB_ALARM_TRAP; - fchan->alarm_flags = FTDM_ALARM_RED; - break; - } - } - } - break; - - case WP_API_EVENT_RXHOOK: - { - if (fchan->type == FTDM_CHAN_TYPE_FXS) { - *event_id = tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_hook_state - & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_OFFHOOK : FTDM_OOB_ONHOOK; - ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Got wanpipe %s\n", ftdm_oob_event2str(*event_id)); - if (*event_id == FTDM_OOB_OFFHOOK) { - if (ftdm_test_flag(fchan, FTDM_CHANNEL_FLASH)) { - ftdm_clear_flag(fchan, FTDM_CHANNEL_FLASH); - ftdm_clear_flag(fchan, FTDM_CHANNEL_WINK); - *event_id = FTDM_OOB_FLASH; - goto done; - } else { - ftdm_set_flag(fchan, FTDM_CHANNEL_WINK); - } - } else { - if (ftdm_test_flag(fchan, FTDM_CHANNEL_WINK)) { - ftdm_clear_flag(fchan, FTDM_CHANNEL_WINK); - ftdm_clear_flag(fchan, FTDM_CHANNEL_FLASH); - *event_id = FTDM_OOB_WINK; - ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Wink flag is set, delivering %s\n", - ftdm_oob_event2str(*event_id)); - goto done; - } else { - ftdm_set_flag(fchan, FTDM_CHANNEL_FLASH); - } - } - status = FTDM_BREAK; - } else { - ftdm_status_t status; - status = sangoma_tdm_txsig_onhook(fchan->sockfd, tdm_api); - if (status) { - snprintf(fchan->last_error, sizeof(fchan->last_error), "ONHOOK Failed"); - return FTDM_FAIL; - } - *event_id = tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_ONHOOK : FTDM_OOB_NOOP; - } - } - break; - case WP_API_EVENT_RING_DETECT: - { - *event_id = tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_RING_START : FTDM_OOB_RING_STOP; - } - break; - /* - disabled this ones when configuring, we don't need them, do we? - case WP_API_EVENT_RING_TRIP_DETECT: - { - *event_id = tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_ONHOOK : FTDM_OOB_OFFHOOK; - } - break; - */ - case WP_API_EVENT_RBS: - { - *event_id = FTDM_OOB_CAS_BITS_CHANGE; - fchan->rx_cas_bits = wanpipe_swap_bits(tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits); - } - break; - case WP_API_EVENT_DTMF: - { - char tmp_dtmf[2] = { tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_dtmf_digit, 0 }; - *event_id = FTDM_OOB_NOOP; - - if (tmp_dtmf[0] == 'f') { - ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Ignoring wanpipe DTMF: %c, fax tones will be passed through!\n", tmp_dtmf[0]); - break; - } - - if (tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_PRESENT) { - ftdm_set_flag(fchan, FTDM_CHANNEL_MUTE); - if (fchan->dtmfdetect.duration_ms) { - fchan->dtmfdetect.start_time = ftdm_current_time_in_ms(); - } else if (fchan->dtmfdetect.trigger_on_start) { - ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Queuing wanpipe DTMF: %c\n", tmp_dtmf[0]); - ftdm_channel_queue_dtmf(fchan, tmp_dtmf); - } - } - - if (tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_STOP) { - ftdm_clear_flag(fchan, FTDM_CHANNEL_MUTE); - if (ftdm_test_flag(fchan, FTDM_CHANNEL_INUSE)) { - if (fchan->dtmfdetect.duration_ms) { - ftdm_time_t diff = ftdm_current_time_in_ms() - fchan->dtmfdetect.start_time; - if (diff > fchan->dtmfdetect.duration_ms) { - ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Queuing wanpipe DTMF: %c (duration:%"FTDM_TIME_FMT" min:%d)\n", tmp_dtmf[0], diff, fchan->dtmfdetect.duration_ms); - ftdm_channel_queue_dtmf(fchan, tmp_dtmf); - } else { - ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Ignoring wanpipe DTMF: %c (duration:%"FTDM_TIME_FMT" min:%d)\n", tmp_dtmf[0], diff, fchan->dtmfdetect.duration_ms); - } - } else if (!fchan->dtmfdetect.trigger_on_start) { - ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Queuing wanpipe DTMF: %c\n", tmp_dtmf[0]); - ftdm_channel_queue_dtmf(fchan, tmp_dtmf); - } - } - } - } - break; - case WP_API_EVENT_ALARM: - { - if (tdm_api->wp_tdm_cmd.event.wp_api_event_alarm) { - ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Got Wanpipe alarms %d\n", tdm_api->wp_tdm_cmd.event.wp_api_event_alarm); - *event_id = FTDM_OOB_ALARM_TRAP; - } else { - ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Wanpipe alarms cleared\n"); - *event_id = FTDM_OOB_ALARM_CLEAR; - } - } - break; - case WP_API_EVENT_POLARITY_REVERSE: - { - ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Got polarity reverse\n"); - *event_id = FTDM_OOB_POLARITY_REVERSE; - } - break; - default: - { - ftdm_log_chan(fchan, FTDM_LOG_WARNING, "Unhandled wanpipe event %d\n", tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_type); - *event_id = FTDM_OOB_INVALID; - } - break; - } -done: - return status; -} - -/** - * \brief Retrieves an event from a wanpipe channel - * \param channel Channel to retrieve event from - * \param event FreeTDM event to return - * \return Success or failure - */ -FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event) -{ - ftdm_status_t status; - ftdm_oob_event_t event_id; - wanpipe_tdm_api_t tdm_api; - ftdm_span_t *span = ftdmchan->span; - - memset(&tdm_api, 0, sizeof(tdm_api)); - status = sangoma_tdm_read_event(ftdmchan->sockfd, &tdm_api); - if (status != FTDM_SUCCESS) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to read event from channel: %s\n", strerror(errno)); - return FTDM_FAIL; - } - - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "read wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type); - status = wanpipe_channel_process_event(ftdmchan, &event_id, &tdm_api); - if (status == FTDM_BREAK) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Ignoring event for now\n"); - } else if (status != FTDM_SUCCESS) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to process event from channel\n"); - return FTDM_FAIL; - } else { - ftdmchan->last_event_time = 0; - } - - span->event_header.e_type = FTDM_EVENT_OOB; - span->event_header.enum_id = event_id; - span->event_header.channel = ftdmchan; - *event = &span->event_header; - return FTDM_SUCCESS; -} - -/** - * \brief Retrieves an event from a wanpipe span - * \param span Span to retrieve event from - * \param event FreeTDM event to return - * \return Success or failure - */ -FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event) -{ - uint32_t i,err; - ftdm_oob_event_t event_id; - for(i = 1; i <= span->chan_count; i++) { - /* as a hack for wink/flash detection, wanpipe_poll_event overrides the timeout parameter - * to force the user to call this function each 5ms or so to detect the timeout of our wink/flash */ - if (span->channels[i]->last_event_time && !ftdm_test_io_flag(span->channels[i], FTDM_CHANNEL_IO_EVENT)) { - ftdm_time_t diff = ftdm_current_time_in_ms() - span->channels[i]->last_event_time; - /* XX printf("%u %u %u\n", diff, (unsigned)ftdm_current_time_in_ms(), (unsigned)span->channels[i]->last_event_time); */ - if (ftdm_test_flag(span->channels[i], FTDM_CHANNEL_WINK)) { - if (diff > wp_globals.wink_ms) { - ftdm_clear_flag_locked(span->channels[i], FTDM_CHANNEL_WINK); - ftdm_clear_flag_locked(span->channels[i], FTDM_CHANNEL_FLASH); - ftdm_set_flag_locked(span->channels[i], FTDM_CHANNEL_OFFHOOK); - event_id = FTDM_OOB_OFFHOOK; - ftdm_log_chan(span->channels[i], FTDM_LOG_DEBUG, "Diff since last event = %"FTDM_TIME_FMT" ms, delivering %s now\n", diff, ftdm_oob_event2str(event_id)); - goto event; - } - } - - if (ftdm_test_flag(span->channels[i], FTDM_CHANNEL_FLASH)) { - if (diff > wp_globals.flash_ms) { - ftdm_clear_flag_locked(span->channels[i], FTDM_CHANNEL_FLASH); - ftdm_clear_flag_locked(span->channels[i], FTDM_CHANNEL_WINK); - ftdm_clear_flag_locked(span->channels[i], FTDM_CHANNEL_OFFHOOK); - event_id = FTDM_OOB_ONHOOK; - - if (span->channels[i]->type == FTDM_CHAN_TYPE_FXO) { - ftdm_channel_t *ftdmchan = span->channels[i]; - wanpipe_tdm_api_t tdm_api; - memset(&tdm_api, 0, sizeof(tdm_api)); - - sangoma_tdm_txsig_onhook(ftdmchan->sockfd,&tdm_api); - } - ftdm_log_chan(span->channels[i], FTDM_LOG_DEBUG, "Diff since last event = %"FTDM_TIME_FMT" ms, delivering %s now\n", diff, ftdm_oob_event2str(event_id)); - goto event; - } - } - } - if (ftdm_test_io_flag(span->channels[i], FTDM_CHANNEL_IO_EVENT)) { - ftdm_status_t status; - wanpipe_tdm_api_t tdm_api; - ftdm_channel_t *ftdmchan = span->channels[i]; - memset(&tdm_api, 0, sizeof(tdm_api)); - ftdm_clear_io_flag(span->channels[i], FTDM_CHANNEL_IO_EVENT); - - err = sangoma_tdm_read_event(ftdmchan->sockfd, &tdm_api); - if (err != FTDM_SUCCESS) { - ftdm_log_chan(span->channels[i], FTDM_LOG_ERROR, "read wanpipe event got error: %s\n", strerror(errno)); - return FTDM_FAIL; - } - ftdm_log_chan(span->channels[i], FTDM_LOG_DEBUG, "read wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type); - - ftdm_channel_lock(ftdmchan); - status = wanpipe_channel_process_event(ftdmchan, &event_id, &tdm_api); - ftdm_channel_unlock(ftdmchan); - - if (status == FTDM_BREAK) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring event for now\n"); - continue; - } else if (status != FTDM_SUCCESS) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to process event from channel\n"); - return FTDM_FAIL; - } - - event: - - span->channels[i]->last_event_time = 0; - span->event_header.e_type = FTDM_EVENT_OOB; - span->event_header.enum_id = event_id; - span->event_header.channel = span->channels[i]; - *event = &span->event_header; - return FTDM_SUCCESS; - } - } - return FTDM_BREAK; -} - -/** - * \brief Destroys a Wanpipe Channel - * \param ftdmchan Channel to destroy - * \return Success - */ -static FIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy) -{ -#ifdef LIBSANGOMA_VERSION - if (ftdmchan->io_data) { - sangoma_wait_obj_t *sangoma_wait_obj = WP_GET_WAITABLE(ftdmchan); - sangoma_wait_obj_delete(&sangoma_wait_obj); - ftdm_safe_free(ftdmchan->io_data); - ftdmchan->io_data = NULL; - } -#endif - - if (ftdmchan->sockfd != FTDM_INVALID_SOCKET) { - /* enable HW DTMF. As odd as it seems. Why enable when the channel is being destroyed and won't be used anymore? - * because that way we can transfer the DTMF state back to the driver, if we're being restarted we will set again - * the FEATURE_DTMF flag and use HW DTMF, if we don't enable here, then on module restart we won't see - * HW DTMF available and will use software */ - if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) { - wanpipe_tdm_api_t tdm_api; - int err; - memset(&tdm_api, 0, sizeof(tdm_api)); - err = sangoma_tdm_enable_dtmf_events(ftdmchan->sockfd, &tdm_api); - if (err) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed enabling Sangoma HW DTMF failed on channel destroy\n"); - } - } - sangoma_close(&ftdmchan->sockfd); - } - - return FTDM_SUCCESS; -} - -/** - * \brief Loads wanpipe IO module - * \param fio FreeTDM IO interface - * \return Success - */ -static FIO_IO_LOAD_FUNCTION(wanpipe_init) -{ - ftdm_assert(fio != NULL, "fio should not be null\n"); - - memset(&wanpipe_interface, 0, sizeof(wanpipe_interface)); - - wp_globals.codec_ms = 20; - wp_globals.wink_ms = 150; - wp_globals.flash_ms = 750; - wp_globals.ring_on_ms = 2000; - wp_globals.ring_off_ms = 4000; - /* 0 for queue size will leave driver defaults */ - wp_globals.txqueue_size = 0; - wp_globals.rxqueue_size = 0; - wanpipe_interface.name = "wanpipe"; - wanpipe_interface.configure_span = wanpipe_configure_span; - wanpipe_interface.configure = wanpipe_configure; - wanpipe_interface.open = wanpipe_open; - wanpipe_interface.close = wanpipe_close; - wanpipe_interface.command = wanpipe_command; - wanpipe_interface.wait = wanpipe_wait; - wanpipe_interface.read = wanpipe_read; - wanpipe_interface.write = wanpipe_write; - wanpipe_interface.poll_event = wanpipe_poll_event; - wanpipe_interface.next_event = wanpipe_span_next_event; - wanpipe_interface.channel_next_event = wanpipe_channel_next_event; - wanpipe_interface.channel_destroy = wanpipe_channel_destroy; - wanpipe_interface.get_alarms = wanpipe_get_alarms; - *fio = &wanpipe_interface; - - return FTDM_SUCCESS; -} - -/** - * \brief Unloads wanpipe IO module - * \return Success - */ -static FIO_IO_UNLOAD_FUNCTION(wanpipe_destroy) -{ - memset(&wanpipe_interface, 0, sizeof(wanpipe_interface)); - return FTDM_SUCCESS; -} - -/** - * \brief FreeTDM wanpipe IO module definition - */ -EX_DECLARE_DATA ftdm_module_t ftdm_module = { - "wanpipe", - wanpipe_init, - wanpipe_destroy, -}; - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet - */ diff --git a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c deleted file mode 100644 index 369a05d1d0..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c +++ /dev/null @@ -1,1571 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Contributors: - * - * Moises Silva - * W McRoberts - * Puskás Zsolt - * - */ - -#include "private/ftdm_core.h" -#include "ftmod_zt.h" - -/* used by dahdi to indicate there is no data available, but events to read */ -#ifndef ELAST -#define ELAST 500 -#endif - -/** - * \brief Zaptel globals - */ -static struct { - uint32_t codec_ms; - uint32_t wink_ms; - uint32_t flash_ms; - uint32_t eclevel; - uint32_t etlevel; - float rxgain; - float txgain; -} zt_globals; - -#if defined(__FreeBSD__) -typedef unsigned long ioctlcmd; -#else -typedef int ioctlcmd; -#endif - -/** - * \brief General IOCTL codes - */ -struct ioctl_codes { - ioctlcmd GET_BLOCKSIZE; - ioctlcmd SET_BLOCKSIZE; - ioctlcmd FLUSH; - ioctlcmd SYNC; - ioctlcmd GET_PARAMS; - ioctlcmd SET_PARAMS; - ioctlcmd HOOK; - ioctlcmd GETEVENT; - ioctlcmd IOMUX; - ioctlcmd SPANSTAT; - ioctlcmd MAINT; - ioctlcmd GETCONF; - ioctlcmd SETCONF; - ioctlcmd CONFLINK; - ioctlcmd CONFDIAG; - ioctlcmd GETGAINS; - ioctlcmd SETGAINS; - ioctlcmd SPANCONFIG; - ioctlcmd CHANCONFIG; - ioctlcmd SET_BUFINFO; - ioctlcmd GET_BUFINFO; - ioctlcmd AUDIOMODE; - ioctlcmd ECHOCANCEL; - ioctlcmd HDLCRAWMODE; - ioctlcmd HDLCFCSMODE; - ioctlcmd SPECIFY; - ioctlcmd SETLAW; - ioctlcmd SETLINEAR; - ioctlcmd GETCONFMUTE; - ioctlcmd ECHOTRAIN; - ioctlcmd SETTXBITS; - ioctlcmd GETRXBITS; - ioctlcmd SETPOLARITY; - ioctlcmd TONEDETECT; -}; - -/** - * \brief Zaptel IOCTL codes - */ -static struct ioctl_codes zt_ioctl_codes = { - .GET_BLOCKSIZE = ZT_GET_BLOCKSIZE, - .SET_BLOCKSIZE = ZT_SET_BLOCKSIZE, - .FLUSH = ZT_FLUSH, - .SYNC = ZT_SYNC, - .GET_PARAMS = ZT_GET_PARAMS, - .SET_PARAMS = ZT_SET_PARAMS, - .HOOK = ZT_HOOK, - .GETEVENT = ZT_GETEVENT, - .IOMUX = ZT_IOMUX, - .SPANSTAT = ZT_SPANSTAT, - .MAINT = ZT_MAINT, - .GETCONF = ZT_GETCONF, - .SETCONF = ZT_SETCONF, - .CONFLINK = ZT_CONFLINK, - .CONFDIAG = ZT_CONFDIAG, - .GETGAINS = ZT_GETGAINS, - .SETGAINS = ZT_SETGAINS, - .SPANCONFIG = ZT_SPANCONFIG, - .CHANCONFIG = ZT_CHANCONFIG, - .SET_BUFINFO = ZT_SET_BUFINFO, - .GET_BUFINFO = ZT_GET_BUFINFO, - .AUDIOMODE = ZT_AUDIOMODE, - .ECHOCANCEL = ZT_ECHOCANCEL, - .HDLCRAWMODE = ZT_HDLCRAWMODE, - .HDLCFCSMODE = ZT_HDLCFCSMODE, - .SPECIFY = ZT_SPECIFY, - .SETLAW = ZT_SETLAW, - .SETLINEAR = ZT_SETLINEAR, - .GETCONFMUTE = ZT_GETCONFMUTE, - .ECHOTRAIN = ZT_ECHOTRAIN, - .SETTXBITS = ZT_SETTXBITS, - .GETRXBITS = ZT_GETRXBITS, - .TONEDETECT = ZT_TONEDETECT, -}; - -/** - * \brief Dahdi IOCTL codes - */ -static struct ioctl_codes dahdi_ioctl_codes = { - .GET_BLOCKSIZE = DAHDI_GET_BLOCKSIZE, - .SET_BLOCKSIZE = DAHDI_SET_BLOCKSIZE, - .FLUSH = DAHDI_FLUSH, - .SYNC = DAHDI_SYNC, - .GET_PARAMS = DAHDI_GET_PARAMS, - .SET_PARAMS = DAHDI_SET_PARAMS, - .HOOK = DAHDI_HOOK, - .GETEVENT = DAHDI_GETEVENT, - .IOMUX = DAHDI_IOMUX, - .SPANSTAT = DAHDI_SPANSTAT, - .MAINT = DAHDI_MAINT, - .GETCONF = DAHDI_GETCONF, - .SETCONF = DAHDI_SETCONF, - .CONFLINK = DAHDI_CONFLINK, - .CONFDIAG = DAHDI_CONFDIAG, - .GETGAINS = DAHDI_GETGAINS, - .SETGAINS = DAHDI_SETGAINS, - .SPANCONFIG = DAHDI_SPANCONFIG, - .CHANCONFIG = DAHDI_CHANCONFIG, - .SET_BUFINFO = DAHDI_SET_BUFINFO, - .GET_BUFINFO = DAHDI_GET_BUFINFO, - .AUDIOMODE = DAHDI_AUDIOMODE, - .ECHOCANCEL = DAHDI_ECHOCANCEL, - .HDLCRAWMODE = DAHDI_HDLCRAWMODE, - .HDLCFCSMODE = DAHDI_HDLCFCSMODE, - .SPECIFY = DAHDI_SPECIFY, - .SETLAW = DAHDI_SETLAW, - .SETLINEAR = DAHDI_SETLINEAR, - .GETCONFMUTE = DAHDI_GETCONFMUTE, - .ECHOTRAIN = DAHDI_ECHOTRAIN, - .SETTXBITS = DAHDI_SETTXBITS, - .GETRXBITS = DAHDI_GETRXBITS, - .SETPOLARITY = DAHDI_SETPOLARITY, - .TONEDETECT = DAHDI_TONEDETECT, -}; - -#define ZT_INVALID_SOCKET -1 -static struct ioctl_codes codes; -static const char *ctlpath = NULL; -static const char *chanpath = NULL; - -static const char dahdi_ctlpath[] = "/dev/dahdi/ctl"; -static const char dahdi_chanpath[] = "/dev/dahdi/channel"; - -static const char zt_ctlpath[] = "/dev/zap/ctl"; -static const char zt_chanpath[] = "/dev/zap/channel"; - -static ftdm_socket_t CONTROL_FD = ZT_INVALID_SOCKET; - -FIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event); -FIO_SPAN_POLL_EVENT_FUNCTION(zt_poll_event); -FIO_CHANNEL_NEXT_EVENT_FUNCTION(zt_channel_next_event); - -/** - * \brief Initialises codec, and rx/tx gains - * \param g Structure for gains to be initialised - * \param rxgain RX gain value - * \param txgain TX gain value - * \param codec Codec - */ -static void zt_build_gains(struct zt_gains *g, float rxgain, float txgain, int codec) -{ - int j; - int k; - float linear_rxgain = pow(10.0, rxgain / 20.0); - float linear_txgain = pow(10.0, txgain / 20.0); - - switch (codec) { - case FTDM_CODEC_ALAW: - for (j = 0; j < (sizeof(g->receive_gain) / sizeof(g->receive_gain[0])); j++) { - if (rxgain) { - k = (int) (((float) alaw_to_linear(j)) * linear_rxgain); - if (k > 32767) k = 32767; - if (k < -32767) k = -32767; - g->receive_gain[j] = linear_to_alaw(k); - } else { - g->receive_gain[j] = j; - } - if (txgain) { - k = (int) (((float) alaw_to_linear(j)) * linear_txgain); - if (k > 32767) k = 32767; - if (k < -32767) k = -32767; - g->transmit_gain[j] = linear_to_alaw(k); - } else { - g->transmit_gain[j] = j; - } - } - break; - case FTDM_CODEC_ULAW: - for (j = 0; j < (sizeof(g->receive_gain) / sizeof(g->receive_gain[0])); j++) { - if (rxgain) { - k = (int) (((float) ulaw_to_linear(j)) * linear_rxgain); - if (k > 32767) k = 32767; - if (k < -32767) k = -32767; - g->receive_gain[j] = linear_to_ulaw(k); - } else { - g->receive_gain[j] = j; - } - if (txgain) { - k = (int) (((float) ulaw_to_linear(j)) * linear_txgain); - if (k > 32767) k = 32767; - if (k < -32767) k = -32767; - g->transmit_gain[j] = linear_to_ulaw(k); - } else { - g->transmit_gain[j] = j; - } - } - break; - } -} - -/** - * \brief Initialises a range of Zaptel/DAHDI channels - * \param span FreeTDM span - * \param start Initial wanpipe channel number - * \param end Final wanpipe channel number - * \param type FreeTDM channel type - * \param name FreeTDM span name - * \param number FreeTDM span number - * \param cas_bits CAS bits - * \return number of spans configured - */ -static unsigned zt_open_range(ftdm_span_t *span, unsigned start, unsigned end, ftdm_chan_type_t type, char *name, char *number, unsigned char cas_bits) -{ - unsigned configured = 0, x; - zt_params_t ztp; - zt_tone_mode_t mode = 0; - - memset(&ztp, 0, sizeof(ztp)); - - if (type == FTDM_CHAN_TYPE_CAS) { - ftdm_log(FTDM_LOG_DEBUG, "Configuring CAS channels with abcd == 0x%X\n", cas_bits); - } - for(x = start; x < end; x++) { - ftdm_channel_t *ftdmchan; - ftdm_socket_t sockfd = ZT_INVALID_SOCKET; - int len; - - sockfd = open(chanpath, O_RDWR); - if (sockfd != ZT_INVALID_SOCKET && ftdm_span_add_channel(span, sockfd, type, &ftdmchan) == FTDM_SUCCESS) { - - if (ioctl(sockfd, codes.SPECIFY, &x)) { - ftdm_log(FTDM_LOG_ERROR, "failure configuring device %s chan %d fd %d (%s)\n", chanpath, x, sockfd, strerror(errno)); - close(sockfd); - continue; - } - - if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) { - struct zt_bufferinfo binfo; - memset(&binfo, 0, sizeof(binfo)); - binfo.txbufpolicy = 0; - binfo.rxbufpolicy = 0; - binfo.numbufs = 32; - binfo.bufsize = 1024; - if (ioctl(sockfd, codes.SET_BUFINFO, &binfo)) { - ftdm_log(FTDM_LOG_ERROR, "failure configuring device %s as FreeTDM device %d:%d fd:%d\n", chanpath, ftdmchan->span_id, ftdmchan->chan_id, sockfd); - close(sockfd); - continue; - } - } - - if (type == FTDM_CHAN_TYPE_FXS || type == FTDM_CHAN_TYPE_FXO) { - struct zt_chanconfig cc; - memset(&cc, 0, sizeof(cc)); - cc.chan = cc.master = x; - - switch(type) { - case FTDM_CHAN_TYPE_FXS: - { - switch(span->start_type) { - case FTDM_ANALOG_START_KEWL: - cc.sigtype = ZT_SIG_FXOKS; - break; - case FTDM_ANALOG_START_LOOP: - cc.sigtype = ZT_SIG_FXOLS; - break; - case FTDM_ANALOG_START_GROUND: - cc.sigtype = ZT_SIG_FXOGS; - break; - default: - break; - } - } - break; - case FTDM_CHAN_TYPE_FXO: - { - switch(span->start_type) { - case FTDM_ANALOG_START_KEWL: - cc.sigtype = ZT_SIG_FXSKS; - break; - case FTDM_ANALOG_START_LOOP: - cc.sigtype = ZT_SIG_FXSLS; - break; - case FTDM_ANALOG_START_GROUND: - cc.sigtype = ZT_SIG_FXSGS; - break; - default: - break; - } - } - break; - default: - break; - } - - if (ioctl(CONTROL_FD, codes.CHANCONFIG, &cc)) { - ftdm_log(FTDM_LOG_WARNING, "this ioctl fails in older zaptel but is harmless if you used ztcfg\n[device %s chan %d fd %d (%s)]\n", chanpath, x, CONTROL_FD, strerror(errno)); - } - } - - if (type == FTDM_CHAN_TYPE_CAS) { - struct zt_chanconfig cc; - memset(&cc, 0, sizeof(cc)); - cc.chan = cc.master = x; - cc.sigtype = ZT_SIG_CAS; - cc.idlebits = cas_bits; - if (ioctl(CONTROL_FD, codes.CHANCONFIG, &cc)) { - ftdm_log(FTDM_LOG_ERROR, "failure configuring device %s as FreeTDM device %d:%d fd:%d err:%s\n", chanpath, ftdmchan->span_id, ftdmchan->chan_id, sockfd, strerror(errno)); - close(sockfd); - continue; - } - } - - if (ftdmchan->type != FTDM_CHAN_TYPE_DQ921 && ftdmchan->type != FTDM_CHAN_TYPE_DQ931) { - len = zt_globals.codec_ms * 8; - if (ioctl(ftdmchan->sockfd, codes.SET_BLOCKSIZE, &len)) { - ftdm_log(FTDM_LOG_ERROR, "failure configuring device %s as FreeTDM device %d:%d fd:%d err:%s\n", - chanpath, ftdmchan->span_id, ftdmchan->chan_id, sockfd, strerror(errno)); - close(sockfd); - continue; - } - - ftdmchan->packet_len = len; - ftdmchan->effective_interval = ftdmchan->native_interval = ftdmchan->packet_len / 8; - - if (ftdmchan->effective_codec == FTDM_CODEC_SLIN) { - ftdmchan->packet_len *= 2; - } - } - - if (ioctl(sockfd, codes.GET_PARAMS, &ztp) < 0) { - ftdm_log(FTDM_LOG_ERROR, "failure configuring device %s as FreeTDM device %d:%d fd:%d\n", chanpath, ftdmchan->span_id, ftdmchan->chan_id, sockfd); - close(sockfd); - continue; - } - - if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) { - if ( - (ztp.sig_type != ZT_SIG_HDLCRAW) && - (ztp.sig_type != ZT_SIG_HDLCFCS) && - (ztp.sig_type != ZT_SIG_HARDHDLC) - ) { - ftdm_log(FTDM_LOG_ERROR, "Failure configuring device %s as FreeTDM device %d:%d fd:%d, hardware signaling is not HDLC, fix your Zap/DAHDI configuration!\n", chanpath, ftdmchan->span_id, ftdmchan->chan_id, sockfd); - close(sockfd); - continue; - } - } - - ftdm_log(FTDM_LOG_INFO, "configuring device %s channel %d as FreeTDM device %d:%d fd:%d\n", chanpath, x, ftdmchan->span_id, ftdmchan->chan_id, sockfd); - - ftdmchan->rate = 8000; - ftdmchan->physical_span_id = ztp.span_no; - ftdmchan->physical_chan_id = ztp.chan_no; - - if (type == FTDM_CHAN_TYPE_FXS || type == FTDM_CHAN_TYPE_FXO || type == FTDM_CHAN_TYPE_EM || type == FTDM_CHAN_TYPE_B) { - if (ztp.g711_type == ZT_G711_ALAW) { - ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_ALAW; - } else if (ztp.g711_type == ZT_G711_MULAW) { - ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_ULAW; - } else { - int type; - - if (ftdmchan->span->trunk_type == FTDM_TRUNK_E1) { - type = FTDM_CODEC_ALAW; - } else { - type = FTDM_CODEC_ULAW; - } - - ftdmchan->native_codec = ftdmchan->effective_codec = type; - - } - } - - ztp.wink_time = zt_globals.wink_ms; - ztp.flash_time = zt_globals.flash_ms; - - if (ioctl(sockfd, codes.SET_PARAMS, &ztp) < 0) { - ftdm_log(FTDM_LOG_ERROR, "failure configuring device %s as FreeTDM device %d:%d fd:%d\n", chanpath, ftdmchan->span_id, ftdmchan->chan_id, sockfd); - close(sockfd); - continue; - } - - mode = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE; - if (ioctl(sockfd, codes.TONEDETECT, &mode)) { - ftdm_log(FTDM_LOG_DEBUG, "HW DTMF not available on FreeTDM device %d:%d fd:%d\n", ftdmchan->span_id, ftdmchan->chan_id, sockfd); - } else { - ftdm_log(FTDM_LOG_DEBUG, "HW DTMF available on FreeTDM device %d:%d fd:%d\n", ftdmchan->span_id, ftdmchan->chan_id, sockfd); - ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT); - mode = 0; - ioctl(sockfd, codes.TONEDETECT, &mode); - } - - if (!ftdm_strlen_zero(name)) { - ftdm_copy_string(ftdmchan->chan_name, name, sizeof(ftdmchan->chan_name)); - } - if (!ftdm_strlen_zero(number)) { - ftdm_copy_string(ftdmchan->chan_number, number, sizeof(ftdmchan->chan_number)); - } - - configured++; - } else { - ftdm_log(FTDM_LOG_ERROR, "failure configuring device %s\n", chanpath); - } - } - - - - return configured; -} - -/** - * \brief Initialises a freetdm Zaptel/DAHDI span from a configuration string - * \param span FreeTDM span - * \param str Configuration string - * \param type FreeTDM span type - * \param name FreeTDM span name - * \param number FreeTDM span number - * \return Success or failure - */ -static FIO_CONFIGURE_SPAN_FUNCTION(zt_configure_span) -{ - - int items, i; - char *mydata, *item_list[10]; - char *ch, *mx; - unsigned char cas_bits = 0; - int channo; - int top = 0; - unsigned configured = 0; - - assert(str != NULL); - - - mydata = ftdm_strdup(str); - assert(mydata != NULL); - - - items = ftdm_separate_string(mydata, ',', item_list, (sizeof(item_list) / sizeof(item_list[0]))); - - for(i = 0; i < items; i++) { - ch = item_list[i]; - - if (!(ch)) { - ftdm_log(FTDM_LOG_ERROR, "Invalid input\n"); - continue; - } - - channo = atoi(ch); - - if (channo < 0) { - ftdm_log(FTDM_LOG_ERROR, "Invalid channel number %d\n", channo); - continue; - } - - if ((mx = strchr(ch, '-'))) { - mx++; - top = atoi(mx) + 1; - } else { - top = channo + 1; - } - - - if (top < 0) { - ftdm_log(FTDM_LOG_ERROR, "Invalid range number %d\n", top); - continue; - } - if (FTDM_CHAN_TYPE_CAS == type && ftdm_config_get_cas_bits(ch, &cas_bits)) { - ftdm_log(FTDM_LOG_ERROR, "Failed to get CAS bits in CAS channel\n"); - continue; - } - configured += zt_open_range(span, channo, top, type, name, number, cas_bits); - - } - - ftdm_safe_free(mydata); - - return configured; - -} - -/** - * \brief Process configuration variable for a Zaptel/DAHDI profile - * \param category Wanpipe profile name - * \param var Variable name - * \param val Variable value - * \param lineno Line number from configuration file - * \return Success - */ -static FIO_CONFIGURE_FUNCTION(zt_configure) -{ - - int num; - float fnum; - - if (!strcasecmp(category, "defaults")) { - if (!strcasecmp(var, "codec_ms")) { - num = atoi(val); - if (num < 10 || num > 60) { - ftdm_log(FTDM_LOG_WARNING, "invalid codec ms at line %d\n", lineno); - } else { - zt_globals.codec_ms = num; - } - } else if (!strcasecmp(var, "wink_ms")) { - num = atoi(val); - if (num < 50 || num > 3000) { - ftdm_log(FTDM_LOG_WARNING, "invalid wink ms at line %d\n", lineno); - } else { - zt_globals.wink_ms = num; - } - } else if (!strcasecmp(var, "flash_ms")) { - num = atoi(val); - if (num < 50 || num > 3000) { - ftdm_log(FTDM_LOG_WARNING, "invalid flash ms at line %d\n", lineno); - } else { - zt_globals.flash_ms = num; - } - } else if (!strcasecmp(var, "echo_cancel_level")) { - num = atoi(val); - if (num < 0 || num > 1024) { - ftdm_log(FTDM_LOG_WARNING, "invalid echo can val at line %d\n", lineno); - } else { - zt_globals.eclevel = num; - } - } else if (!strcasecmp(var, "echo_train_level")) { - if (zt_globals.eclevel < 1) { - ftdm_log(FTDM_LOG_WARNING, "can't set echo train level without setting echo cancel level first at line %d\n", lineno); - } else { - num = atoi(val); - if (num < 0 || num > 256) { - ftdm_log(FTDM_LOG_WARNING, "invalid echo train val at line %d\n", lineno); - } else { - zt_globals.etlevel = num; - } - } - } else if (!strcasecmp(var, "rxgain")) { - fnum = (float)atof(val); - if (fnum < -100.0 || fnum > 100.0) { - ftdm_log(FTDM_LOG_WARNING, "invalid rxgain val at line %d\n", lineno); - } else { - zt_globals.rxgain = fnum; - ftdm_log(FTDM_LOG_INFO, "Setting rxgain val to %f\n", fnum); - } - } else if (!strcasecmp(var, "txgain")) { - fnum = (float)atof(val); - if (fnum < -100.0 || fnum > 100.0) { - ftdm_log(FTDM_LOG_WARNING, "invalid txgain val at line %d\n", lineno); - } else { - zt_globals.txgain = fnum; - ftdm_log(FTDM_LOG_INFO, "Setting txgain val to %f\n", fnum); - } - } else { - ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown setting '%s'\n", var); - } - } - - return FTDM_SUCCESS; -} - -/** - * \brief Opens a Zaptel/DAHDI channel - * \param ftdmchan Channel to open - * \return Success or failure - */ -static FIO_OPEN_FUNCTION(zt_open) -{ - ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_INTERVAL); - - if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921 || ftdmchan->type == FTDM_CHAN_TYPE_DQ931) { - ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_NONE; - } else { - int blocksize = zt_globals.codec_ms * (ftdmchan->rate / 1000); - int err; - if ((err = ioctl(ftdmchan->sockfd, codes.SET_BLOCKSIZE, &blocksize))) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno)); - return FTDM_FAIL; - } else { - ftdmchan->effective_interval = ftdmchan->native_interval; - ftdmchan->packet_len = blocksize; - ftdmchan->native_codec = ftdmchan->effective_codec; - } - - if (ftdmchan->type == FTDM_CHAN_TYPE_B) { - int one = 1; - if (ioctl(ftdmchan->sockfd, codes.AUDIOMODE, &one)) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno)); - ftdm_log(FTDM_LOG_ERROR, "%s\n", ftdmchan->last_error); - return FTDM_FAIL; - } - } - if (zt_globals.rxgain || zt_globals.txgain) { - struct zt_gains gains; - memset(&gains, 0, sizeof(gains)); - - gains.chan_no = ftdmchan->physical_chan_id; - zt_build_gains(&gains, zt_globals.rxgain, zt_globals.txgain, ftdmchan->native_codec); - - if (zt_globals.rxgain) - ftdm_log(FTDM_LOG_INFO, "Setting rxgain to %f on channel %d\n", zt_globals.rxgain, gains.chan_no); - - if (zt_globals.txgain) - ftdm_log(FTDM_LOG_INFO, "Setting txgain to %f on channel %d\n", zt_globals.txgain, gains.chan_no); - - if (ioctl(ftdmchan->sockfd, codes.SETGAINS, &gains) < 0) { - ftdm_log(FTDM_LOG_ERROR, "failure configuring device %s as FreeTDM device %d:%d fd:%d\n", chanpath, ftdmchan->span_id, ftdmchan->chan_id, ftdmchan->sockfd); - } - } - - if (1) { - int len = zt_globals.eclevel; - if (len) { - ftdm_log(FTDM_LOG_INFO, "Setting echo cancel to %d taps for %d:%d\n", len, ftdmchan->span_id, ftdmchan->chan_id); - } else { - ftdm_log(FTDM_LOG_INFO, "Disable echo cancel for %d:%d\n", ftdmchan->span_id, ftdmchan->chan_id); - } - if (ioctl(ftdmchan->sockfd, codes.ECHOCANCEL, &len)) { - ftdm_log(FTDM_LOG_WARNING, "Echo cancel not available for %d:%d\n", ftdmchan->span_id, ftdmchan->chan_id); - } else if (zt_globals.etlevel > 0) { - len = zt_globals.etlevel; - if (ioctl(ftdmchan->sockfd, codes.ECHOTRAIN, &len)) { - ftdm_log(FTDM_LOG_WARNING, "Echo training not available for %d:%d\n", ftdmchan->span_id, ftdmchan->chan_id); - } - } - } - } - return FTDM_SUCCESS; -} - -/** - * \brief Closes Zaptel/DAHDI channel - * \param ftdmchan Channel to close - * \return Success - */ -static FIO_CLOSE_FUNCTION(zt_close) -{ - if (ftdmchan->type == FTDM_CHAN_TYPE_B) { - int value = 0; /* disable audio mode */ - if (ioctl(ftdmchan->sockfd, codes.AUDIOMODE, &value)) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno)); - ftdm_log(FTDM_LOG_ERROR, "%s\n", ftdmchan->last_error); - return FTDM_FAIL; - } - } - return FTDM_SUCCESS; -} - -/** - * \brief Executes a FreeTDM command on a Zaptel/DAHDI channel - * \param ftdmchan Channel to execute command on - * \param command FreeTDM command to execute - * \param obj Object (unused) - * \return Success or failure - */ -static FIO_COMMAND_FUNCTION(zt_command) -{ - zt_params_t ztp; - int err = 0; - - memset(&ztp, 0, sizeof(ztp)); - - switch(command) { - case FTDM_COMMAND_ENABLE_ECHOCANCEL: - { - int level = FTDM_COMMAND_OBJ_INT; - err = ioctl(ftdmchan->sockfd, codes.ECHOCANCEL, &level); - FTDM_COMMAND_OBJ_INT = level; - } - case FTDM_COMMAND_DISABLE_ECHOCANCEL: - { - int level = 0; - err = ioctl(ftdmchan->sockfd, codes.ECHOCANCEL, &level); - FTDM_COMMAND_OBJ_INT = level; - } - break; - case FTDM_COMMAND_ENABLE_ECHOTRAIN: - { - int level = FTDM_COMMAND_OBJ_INT; - err = ioctl(ftdmchan->sockfd, codes.ECHOTRAIN, &level); - FTDM_COMMAND_OBJ_INT = level; - } - case FTDM_COMMAND_DISABLE_ECHOTRAIN: - { - int level = 0; - err = ioctl(ftdmchan->sockfd, codes.ECHOTRAIN, &level); - FTDM_COMMAND_OBJ_INT = level; - } - break; - case FTDM_COMMAND_OFFHOOK: - { - int command = ZT_OFFHOOK; - if (ioctl(ftdmchan->sockfd, codes.HOOK, &command)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "OFFHOOK Failed"); - return FTDM_FAIL; - } - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Channel is now offhook\n"); - ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK); - } - break; - case FTDM_COMMAND_ONHOOK: - { - int command = ZT_ONHOOK; - if (ioctl(ftdmchan->sockfd, codes.HOOK, &command)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "ONHOOK Failed"); - return FTDM_FAIL; - } - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Channel is now onhook\n"); - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK); - } - break; - case FTDM_COMMAND_FLASH: - { - int command = ZT_FLASH; - if (ioctl(ftdmchan->sockfd, codes.HOOK, &command)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "FLASH Failed"); - return FTDM_FAIL; - } - } - break; - case FTDM_COMMAND_WINK: - { - int command = ZT_WINK; - if (ioctl(ftdmchan->sockfd, codes.HOOK, &command)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "WINK Failed"); - return FTDM_FAIL; - } - } - break; - case FTDM_COMMAND_GENERATE_RING_ON: - { - int command = ZT_RING; - if (ioctl(ftdmchan->sockfd, codes.HOOK, &command)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "RING Failed"); - return FTDM_FAIL; - } - ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_RINGING); - } - break; - case FTDM_COMMAND_GENERATE_RING_OFF: - { - int command = ZT_RINGOFF; - if (ioctl(ftdmchan->sockfd, codes.HOOK, &command)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Ring-off Failed"); - return FTDM_FAIL; - } - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_RINGING); - } - break; - case FTDM_COMMAND_GET_INTERVAL: - { - - if (!(err = ioctl(ftdmchan->sockfd, codes.GET_BLOCKSIZE, &ftdmchan->packet_len))) { - ftdmchan->native_interval = ftdmchan->packet_len / 8; - if (ftdmchan->effective_codec == FTDM_CODEC_SLIN) { - ftdmchan->packet_len *= 2; - } - FTDM_COMMAND_OBJ_INT = ftdmchan->native_interval; - } - } - break; - case FTDM_COMMAND_SET_INTERVAL: - { - int interval = FTDM_COMMAND_OBJ_INT; - int len = interval * 8; - - if (!(err = ioctl(ftdmchan->sockfd, codes.SET_BLOCKSIZE, &len))) { - ftdmchan->packet_len = len; - ftdmchan->effective_interval = ftdmchan->native_interval = ftdmchan->packet_len / 8; - - if (ftdmchan->effective_codec == FTDM_CODEC_SLIN) { - ftdmchan->packet_len *= 2; - } - } - } - break; - case FTDM_COMMAND_SET_CAS_BITS: - { - int bits = FTDM_COMMAND_OBJ_INT; - err = ioctl(ftdmchan->sockfd, codes.SETTXBITS, &bits); - } - break; - case FTDM_COMMAND_GET_CAS_BITS: - { - err = ioctl(ftdmchan->sockfd, codes.GETRXBITS, &ftdmchan->rx_cas_bits); - if (!err) { - FTDM_COMMAND_OBJ_INT = ftdmchan->rx_cas_bits; - } - } - break; - case FTDM_COMMAND_FLUSH_TX_BUFFERS: - { - int flushmode = ZT_FLUSH_WRITE; - err = ioctl(ftdmchan->sockfd, codes.FLUSH, &flushmode); - } - break; - case FTDM_COMMAND_SET_POLARITY: - { - ftdm_polarity_t polarity = FTDM_COMMAND_OBJ_INT; - err = ioctl(ftdmchan->sockfd, codes.SETPOLARITY, polarity); - if (!err) { - ftdmchan->polarity = polarity; - } - } - break; - case FTDM_COMMAND_FLUSH_RX_BUFFERS: - { - int flushmode = ZT_FLUSH_READ; - err = ioctl(ftdmchan->sockfd, codes.FLUSH, &flushmode); - } - break; - case FTDM_COMMAND_FLUSH_BUFFERS: - { - int flushmode = ZT_FLUSH_BOTH; - err = ioctl(ftdmchan->sockfd, codes.FLUSH, &flushmode); - } - break; - case FTDM_COMMAND_SET_RX_QUEUE_SIZE: - case FTDM_COMMAND_SET_TX_QUEUE_SIZE: - /* little white lie ... eventually we can implement this, in the meantime, not worth the effort - and this is only used by some sig modules such as ftmod_r2 to behave bettter under load */ - err = 0; - break; - case FTDM_COMMAND_ENABLE_DTMF_DETECT: - { - zt_tone_mode_t mode = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE; - err = ioctl(ftdmchan->sockfd, codes.TONEDETECT, &mode); - } - break; - case FTDM_COMMAND_DISABLE_DTMF_DETECT: - { - zt_tone_mode_t mode = 0; - err = ioctl(ftdmchan->sockfd, codes.TONEDETECT, &mode); - } - break; - default: - err = FTDM_NOTIMPL; - break; - }; - - if (err && err != FTDM_NOTIMPL) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno)); - return FTDM_FAIL; - } - - - return err == 0 ? FTDM_SUCCESS : err; -} - -/** - * \brief Gets alarms from a Zaptel/DAHDI channel - * \param ftdmchan Channel to get alarms from - * \return Success or failure - */ -static FIO_GET_ALARMS_FUNCTION(zt_get_alarms) -{ - struct zt_spaninfo info; - zt_params_t params; - - memset(&info, 0, sizeof(info)); - info.span_no = ftdmchan->physical_span_id; - - memset(¶ms, 0, sizeof(params)); - - if (ioctl(CONTROL_FD, codes.SPANSTAT, &info)) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "ioctl failed (%s)", strerror(errno)); - snprintf(ftdmchan->span->last_error, sizeof(ftdmchan->span->last_error), "ioctl failed (%s)", strerror(errno)); - return FTDM_FAIL; - } - - ftdmchan->alarm_flags = info.alarms; - - /* get channel alarms if span has no alarms */ - if (info.alarms == FTDM_ALARM_NONE) { - if (ioctl(ftdmchan->sockfd, codes.GET_PARAMS, ¶ms)) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "ioctl failed (%s)", strerror(errno)); - snprintf(ftdmchan->span->last_error, sizeof(ftdmchan->span->last_error), "ioctl failed (%s)", strerror(errno)); - return FTDM_FAIL; - } - - if (params.chan_alarms > 0) { - if (params.chan_alarms == DAHDI_ALARM_YELLOW) { - ftdmchan->alarm_flags = FTDM_ALARM_YELLOW; - } - else if (params.chan_alarms == DAHDI_ALARM_BLUE) { - ftdmchan->alarm_flags = FTDM_ALARM_BLUE; - } - else { - ftdmchan->alarm_flags = FTDM_ALARM_RED; - } - } - } - - return FTDM_SUCCESS; -} - -#define ftdm_zt_set_event_pending(fchan) \ - do { \ - ftdm_set_io_flag(fchan, FTDM_CHANNEL_IO_EVENT); \ - fchan->last_event_time = ftdm_current_time_in_ms(); \ - } while (0); - -#define ftdm_zt_store_chan_event(fchan, revent) \ - do { \ - if (fchan->io_data) { \ - ftdm_log_chan(fchan, FTDM_LOG_WARNING, "Dropping event %d, not retrieved on time\n", revent); \ - } \ - fchan->io_data = (void *)zt_event_id; \ - ftdm_zt_set_event_pending(fchan); \ - } while (0); - -/** - * \brief Waits for an event on a Zaptel/DAHDI channel - * \param ftdmchan Channel to open - * \param flags Type of event to wait for - * \param to Time to wait (in ms) - * \return Success, failure or timeout - */ -static FIO_WAIT_FUNCTION(zt_wait) -{ - int32_t inflags = 0; - int result; - struct pollfd pfds[1]; - - if (*flags & FTDM_READ) { - inflags |= POLLIN; - } - - if (*flags & FTDM_WRITE) { - inflags |= POLLOUT; - } - - if (*flags & FTDM_EVENTS) { - inflags |= POLLPRI; - } - -pollagain: - memset(&pfds[0], 0, sizeof(pfds[0])); - pfds[0].fd = ftdmchan->sockfd; - pfds[0].events = inflags; - result = poll(pfds, 1, to); - *flags = FTDM_NO_FLAGS; - - if (result < 0 && errno == EINTR) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "DAHDI wait got interrupted, trying again\n"); - goto pollagain; - } - - if (pfds[0].revents & POLLERR) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "DAHDI device got POLLERR\n"); - result = -1; - } - - if (result > 0) { - inflags = pfds[0].revents; - } - - if (result < 0){ - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Poll failed"); - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to poll DAHDI device: %s\n", strerror(errno)); - return FTDM_FAIL; - } - - if (result == 0) { - return FTDM_TIMEOUT; - } - - if (inflags & POLLIN) { - *flags |= FTDM_READ; - } - - if (inflags & POLLOUT) { - *flags |= FTDM_WRITE; - } - - if ((inflags & POLLPRI) || (ftdmchan->io_data && (*flags & FTDM_EVENTS))) { - *flags |= FTDM_EVENTS; - } - - return FTDM_SUCCESS; - -} - -/** - * \brief Checks for events on a Zaptel/DAHDI span - * \param span Span to check for events - * \param ms Time to wait for event - * \return Success if event is waiting or failure if not - */ -FIO_SPAN_POLL_EVENT_FUNCTION(zt_poll_event) -{ - struct pollfd pfds[FTDM_MAX_CHANNELS_SPAN]; - uint32_t i, j = 0, k = 0; - int r; - - ftdm_unused_arg(poll_events); - - for(i = 1; i <= span->chan_count; i++) { - memset(&pfds[j], 0, sizeof(pfds[j])); - pfds[j].fd = span->channels[i]->sockfd; - pfds[j].events = POLLPRI; - j++; - } - - r = poll(pfds, j, ms); - - if (r == 0) { - return FTDM_TIMEOUT; - } else if (r < 0) { - snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno)); - return FTDM_FAIL; - } - - for(i = 1; i <= span->chan_count; i++) { - - ftdm_channel_lock(span->channels[i]); - - if (pfds[i-1].revents & POLLERR) { - ftdm_log_chan(span->channels[i], FTDM_LOG_ERROR, "POLLERR, flags=%d\n", pfds[i-1].events); - - ftdm_channel_unlock(span->channels[i]); - - continue; - } - if ((pfds[i-1].revents & POLLPRI) || (span->channels[i]->io_data)) { - ftdm_zt_set_event_pending(span->channels[i]); - k++; - } - if (pfds[i-1].revents & POLLIN) { - ftdm_set_io_flag(span->channels[i], FTDM_CHANNEL_IO_READ); - } - if (pfds[i-1].revents & POLLOUT) { - ftdm_set_io_flag(span->channels[i], FTDM_CHANNEL_IO_WRITE); - } - - ftdm_channel_unlock(span->channels[i]); - - } - - if (!k) { - snprintf(span->last_error, sizeof(span->last_error), "no matching descriptor"); - } - - return k ? FTDM_SUCCESS : FTDM_FAIL; -} - -static __inline__ int handle_dtmf_event(ftdm_channel_t *fchan, zt_event_t zt_event_id) -{ - if ((zt_event_id & ZT_EVENT_DTMFUP)) { - int digit = (zt_event_id & (~ZT_EVENT_DTMFUP)); - char tmp_dtmf[2] = { digit, 0 }; - ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "DTMF UP [%d]\n", digit); - ftdm_channel_queue_dtmf(fchan, tmp_dtmf); - return 0; - } else if ((zt_event_id & ZT_EVENT_DTMFDOWN)) { - int digit = (zt_event_id & (~ZT_EVENT_DTMFDOWN)); - ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "DTMF DOWN [%d]\n", digit); - return 0; - } else { - return -1; - } -} - -/** - * \brief Process an event from a ftdmchan and set the proper OOB event_id. The channel must be locked. - * \param fchan Channel to retrieve event from - * \param event_id Pointer to OOB event id - * \param zt_event_id Zaptel event id - * \return FTDM_SUCCESS or FTDM_FAIL - */ -static __inline__ ftdm_status_t zt_channel_process_event(ftdm_channel_t *fchan, ftdm_oob_event_t *event_id, zt_event_t zt_event_id) -{ - ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Processing zap hardware event %d\n", zt_event_id); - switch(zt_event_id) { - case ZT_EVENT_RINGEROFF: - { - ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "ZT RINGER OFF\n"); - *event_id = FTDM_OOB_NOOP; - } - break; - case ZT_EVENT_RINGERON: - { - ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "ZT RINGER ON\n"); - *event_id = FTDM_OOB_NOOP; - } - break; - case ZT_EVENT_RINGBEGIN: - { - *event_id = FTDM_OOB_RING_START; - } - break; - case ZT_EVENT_ONHOOK: - { - *event_id = FTDM_OOB_ONHOOK; - } - break; - case ZT_EVENT_WINKFLASH: - { - if (fchan->state == FTDM_CHANNEL_STATE_DOWN || fchan->state == FTDM_CHANNEL_STATE_DIALING) { - *event_id = FTDM_OOB_WINK; - } else { - *event_id = FTDM_OOB_FLASH; - } - } - break; - case ZT_EVENT_RINGOFFHOOK: - { - *event_id = FTDM_OOB_NOOP; - if (fchan->type == FTDM_CHAN_TYPE_FXS || (fchan->type == FTDM_CHAN_TYPE_EM && fchan->state != FTDM_CHANNEL_STATE_UP)) { - if (fchan->type != FTDM_CHAN_TYPE_EM) { - /* In E&M we're supposed to set this flag only when the local side goes offhook, not the remote */ - ftdm_set_flag_locked(fchan, FTDM_CHANNEL_OFFHOOK); - } - - /* For E&M let's count the ring count (it seems sometimes we receive RINGOFFHOOK once before the other end - * answers, then another RINGOFFHOOK when the other end answers?? anyways, now we count rings before delivering the - * offhook event ... the E&M signaling code in ftmod_analog_em also polls the RBS bits looking for answer, just to - * be safe and not rely on this event, so even if this event does not arrive, when there is answer supervision - * the analog signaling code should detect the cas persistance pattern and answer */ - if (fchan->type == FTDM_CHAN_TYPE_EM && ftdm_test_flag(fchan, FTDM_CHANNEL_OUTBOUND)) { - fchan->ring_count++; - /* perhaps some day we'll make this configurable, but since I am not even sure what the hell is going on - * no point in making a configuration option for something that may not be technically correct */ - if (fchan->ring_count == 2) { - *event_id = FTDM_OOB_OFFHOOK; - } - } else { - *event_id = FTDM_OOB_OFFHOOK; - } - } else if (fchan->type == FTDM_CHAN_TYPE_FXO) { - *event_id = FTDM_OOB_RING_START; - } - } - break; - case ZT_EVENT_ALARM: - { - *event_id = FTDM_OOB_ALARM_TRAP; - } - break; - case ZT_EVENT_NOALARM: - { - *event_id = FTDM_OOB_ALARM_CLEAR; - } - break; - case ZT_EVENT_BITSCHANGED: - { - *event_id = FTDM_OOB_CAS_BITS_CHANGE; - int bits = 0; - int err = ioctl(fchan->sockfd, codes.GETRXBITS, &bits); - if (err) { - return FTDM_FAIL; - } - fchan->rx_cas_bits = bits; - } - break; - case ZT_EVENT_BADFCS: - { - ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Bad frame checksum (ZT_EVENT_BADFCS)\n"); - *event_id = FTDM_OOB_NOOP; /* What else could we do? */ - } - break; - case ZT_EVENT_OVERRUN: - { - ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "HDLC frame overrun (ZT_EVENT_OVERRUN)\n"); - *event_id = FTDM_OOB_NOOP; /* What else could we do? */ - } - break; - case ZT_EVENT_ABORT: - { - ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "HDLC abort frame received (ZT_EVENT_ABORT)\n"); - *event_id = FTDM_OOB_NOOP; /* What else could we do? */ - } - break; - case ZT_EVENT_POLARITY: - { - ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Got polarity reverse (ZT_EVENT_POLARITY)\n"); - *event_id = FTDM_OOB_POLARITY_REVERSE; - } - break; - case ZT_EVENT_NONE: - { - ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "No event\n"); - *event_id = FTDM_OOB_NOOP; - } - break; - default: - { - if (handle_dtmf_event(fchan, zt_event_id)) { - ftdm_log_chan(fchan, FTDM_LOG_WARNING, "Unhandled event %d\n", zt_event_id); - *event_id = FTDM_OOB_INVALID; - } else { - *event_id = FTDM_OOB_NOOP; - } - } - break; - } - return FTDM_SUCCESS; -} - -/** - * \brief Retrieves an event from a ftdm channel - * \param ftdmchan Channel to retrieve event from - * \param event FreeTDM event to return - * \return Success or failure - */ -FIO_CHANNEL_NEXT_EVENT_FUNCTION(zt_channel_next_event) -{ - uint32_t event_id = FTDM_OOB_INVALID; - zt_event_t zt_event_id = 0; - ftdm_span_t *span = ftdmchan->span; - - if (ftdm_test_io_flag(ftdmchan, FTDM_CHANNEL_IO_EVENT)) { - ftdm_clear_io_flag(ftdmchan, FTDM_CHANNEL_IO_EVENT); - } - - if (ftdmchan->io_data) { - zt_event_id = (zt_event_t)ftdmchan->io_data; - ftdmchan->io_data = NULL; - } else if (ioctl(ftdmchan->sockfd, codes.GETEVENT, &zt_event_id) == -1) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed retrieving event from channel: %s\n", - strerror(errno)); - return FTDM_FAIL; - } - - /* the core already locked the channel for us, so it's safe to call zt_channel_process_event() here */ - if ((zt_channel_process_event(ftdmchan, &event_id, zt_event_id)) != FTDM_SUCCESS) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to process DAHDI event %d from channel\n", zt_event_id); - return FTDM_FAIL; - } - - ftdmchan->last_event_time = 0; - span->event_header.e_type = FTDM_EVENT_OOB; - span->event_header.enum_id = event_id; - span->event_header.channel = ftdmchan; - *event = &span->event_header; - return FTDM_SUCCESS; -} - -/** - * \brief Retrieves an event from a Zaptel/DAHDI span - * \param span Span to retrieve event from - * \param event FreeTDM event to return - * \return Success or failure - */ -FIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event) -{ - uint32_t i, event_id = FTDM_OOB_INVALID; - zt_event_t zt_event_id = 0; - - for (i = 1; i <= span->chan_count; i++) { - ftdm_channel_t *fchan = span->channels[i]; - - ftdm_channel_lock(fchan); - - if (!ftdm_test_io_flag(fchan, FTDM_CHANNEL_IO_EVENT)) { - - ftdm_channel_unlock(fchan); - - continue; - } - - ftdm_clear_io_flag(fchan, FTDM_CHANNEL_IO_EVENT); - - if (fchan->io_data) { - zt_event_id = (zt_event_t)fchan->io_data; - fchan->io_data = NULL; - } else if (ioctl(fchan->sockfd, codes.GETEVENT, &zt_event_id) == -1) { - ftdm_log_chan(fchan, FTDM_LOG_ERROR, "Failed to retrieve DAHDI event from channel: %s\n", strerror(errno)); - - ftdm_channel_unlock(fchan); - - continue; - } - - if ((zt_channel_process_event(fchan, &event_id, zt_event_id)) != FTDM_SUCCESS) { - ftdm_log_chan(fchan, FTDM_LOG_ERROR, "Failed to process DAHDI event %d from channel\n", zt_event_id); - - ftdm_channel_unlock(fchan); - - return FTDM_FAIL; - } - - fchan->last_event_time = 0; - span->event_header.e_type = FTDM_EVENT_OOB; - span->event_header.enum_id = event_id; - span->event_header.channel = fchan; - *event = &span->event_header; - - ftdm_channel_unlock(fchan); - - return FTDM_SUCCESS; - } - - return FTDM_FAIL; -} - -/** - * \brief Reads data from a Zaptel/DAHDI channel - * \param ftdmchan Channel to read from - * \param data Data buffer - * \param datalen Size of data buffer - * \return Success, failure or timeout - */ -static FIO_READ_FUNCTION(zt_read) -{ - ftdm_ssize_t r = 0; - int read_errno = 0; - int errs = 0; - - while (errs++ < 30) { - r = read(ftdmchan->sockfd, data, *datalen); - if (r > 0) { - /* successful read, bail out now ... */ - break; - } - - /* Timeout ... retry after a bit */ - if (r == 0) { - ftdm_sleep(10); - if (errs) errs--; - continue; - } - - /* This gotta be an error, save errno in case we do printf(), ioctl() or other operations which may reset it */ - read_errno = errno; - if (read_errno == EAGAIN || read_errno == EINTR) { - /* Reasonable to retry under those errors */ - continue; - } - - /* When ELAST is returned, it means DAHDI has an out of band event ready and we won't be able to read anything until - * we retrieve the event using an ioctl(), so we try to retrieve it here ... */ - if (read_errno == ELAST) { - zt_event_t zt_event_id = 0; - if (ioctl(ftdmchan->sockfd, codes.GETEVENT, &zt_event_id) == -1) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed retrieving event after ELAST on read: %s\n", strerror(errno)); - r = -1; - break; - } - - if (handle_dtmf_event(ftdmchan, zt_event_id)) { - /* Enqueue this event for later */ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Deferring event %d to be able to read data\n", zt_event_id); - ftdm_zt_store_chan_event(ftdmchan, zt_event_id); - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Skipping one IO read cycle due to DTMF event processing\n"); - } - break; - } - - /* Read error, keep going unless to many errors force us to abort ...*/ - ftdm_log(FTDM_LOG_ERROR, "IO read failed: %s\n", strerror(read_errno)); - } - - if (r > 0) { - *datalen = r; - if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) { - *datalen -= 2; - } - return FTDM_SUCCESS; - } - else if (read_errno == ELAST) { - return FTDM_SUCCESS; - } - return r == 0 ? FTDM_TIMEOUT : FTDM_FAIL; -} - -/** - * \brief Writes data to a Zaptel/DAHDI channel - * \param ftdmchan Channel to write to - * \param data Data buffer - * \param datalen Size of data buffer - * \return Success or failure - */ -static FIO_WRITE_FUNCTION(zt_write) -{ - ftdm_ssize_t w = 0; - ftdm_size_t bytes = *datalen; - - if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) { - memset(data+bytes, 0, 2); - bytes += 2; - } - -tryagain: - w = write(ftdmchan->sockfd, data, bytes); - - if (w >= 0) { - *datalen = w; - return FTDM_SUCCESS; - } - - if (errno == ELAST) { - zt_event_t zt_event_id = 0; - if (ioctl(ftdmchan->sockfd, codes.GETEVENT, &zt_event_id) == -1) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed retrieving event after ELAST on write: %s\n", strerror(errno)); - return FTDM_FAIL; - } - - if (handle_dtmf_event(ftdmchan, zt_event_id)) { - /* Enqueue this event for later */ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Deferring event %d to be able to write data\n", zt_event_id); - ftdm_zt_store_chan_event(ftdmchan, zt_event_id); - } - - goto tryagain; - } - - return FTDM_FAIL; -} - -/** - * \brief Destroys a Zaptel/DAHDI Channel - * \param ftdmchan Channel to destroy - * \return Success - */ -static FIO_CHANNEL_DESTROY_FUNCTION(zt_channel_destroy) -{ - close(ftdmchan->sockfd); - ftdmchan->sockfd = ZT_INVALID_SOCKET; - return FTDM_SUCCESS; -} - -/** - * \brief Global FreeTDM IO interface for Zaptel/DAHDI - */ -static ftdm_io_interface_t zt_interface; - -/** - * \brief Loads Zaptel/DAHDI IO module - * \param fio FreeTDM IO interface - * \return Success or failure - */ -static FIO_IO_LOAD_FUNCTION(zt_init) -{ - assert(fio != NULL); - struct stat statbuf; - memset(&zt_interface, 0, sizeof(zt_interface)); - memset(&zt_globals, 0, sizeof(zt_globals)); - - if (!stat(zt_ctlpath, &statbuf)) { - ftdm_log(FTDM_LOG_NOTICE, "Using Zaptel control device\n"); - ctlpath = zt_ctlpath; - chanpath = zt_chanpath; - memcpy(&codes, &zt_ioctl_codes, sizeof(codes)); - } else if (!stat(dahdi_ctlpath, &statbuf)) { - ftdm_log(FTDM_LOG_NOTICE, "Using DAHDI control device\n"); - ctlpath = dahdi_ctlpath; - chanpath = dahdi_chanpath; - memcpy(&codes, &dahdi_ioctl_codes, sizeof(codes)); - } else { - ftdm_log(FTDM_LOG_ERROR, "No DAHDI or Zap control device found in /dev/\n"); - return FTDM_FAIL; - } - if ((CONTROL_FD = open(ctlpath, O_RDWR)) < 0) { - ftdm_log(FTDM_LOG_ERROR, "Cannot open control device %s: %s\n", ctlpath, strerror(errno)); - return FTDM_FAIL; - } - - zt_globals.codec_ms = 20; - zt_globals.wink_ms = 150; - zt_globals.flash_ms = 750; - zt_globals.eclevel = 0; - zt_globals.etlevel = 0; - - zt_interface.name = "zt"; - zt_interface.configure = zt_configure; - zt_interface.configure_span = zt_configure_span; - zt_interface.open = zt_open; - zt_interface.close = zt_close; - zt_interface.command = zt_command; - zt_interface.wait = zt_wait; - zt_interface.read = zt_read; - zt_interface.write = zt_write; - zt_interface.poll_event = zt_poll_event; - zt_interface.next_event = zt_next_event; - zt_interface.channel_next_event = zt_channel_next_event; - zt_interface.channel_destroy = zt_channel_destroy; - zt_interface.get_alarms = zt_get_alarms; - *fio = &zt_interface; - - return FTDM_SUCCESS; -} - -/** - * \brief Unloads Zaptel/DAHDI IO module - * \return Success - */ -static FIO_IO_UNLOAD_FUNCTION(zt_destroy) -{ - close(CONTROL_FD); - memset(&zt_interface, 0, sizeof(zt_interface)); - return FTDM_SUCCESS; -} - -/** - * \brief FreeTDM Zaptel/DAHDI IO module definition - */ -ftdm_module_t ftdm_module = { - "zt", - zt_init, - zt_destroy, -}; - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.h b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.h deleted file mode 100644 index 99c7ef451f..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.h +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Contributors: - * - * Moises Silva - * W McRoberts - * - */ - -#ifndef FTDM_ZT_H -#define FTDM_ZT_H -#include "freetdm.h" -#include -#include - -#ifdef __sun -#include -#include -#include -#endif - -/* Hardware interface structures and defines */ -/* Based on documentation of the structures required for the hardware interface */ -/* from http://wiki.freeswitch.org/wiki/Zapata_ftdmtel_interface */ - -/* Structures */ - -/* Used with ioctl: ZT_GET_PARAMS and ZT_SET_PARAMS */ -struct zt_params { - int chan_no; /* Channel Number */ - int span_no; /* Span Number */ - int chan_position; /* Channel Position */ - int sig_type; /* Signal Type (read-only) */ - int sig_cap; /* Signal Cap (read-only) */ - int receive_offhook; /* Receive is offhook (read-only) */ - int receive_bits; /* Number of bits in receive (read-only) */ - int transmit_bits; /* Number of bits in transmit (read-only) */ - int transmit_hook_sig; /* Transmit Hook Signal (read-only) */ - int receive_hook_sig; /* Receive Hook Signal (read-only) */ - int g711_type; /* Member of zt_g711_t (read-only) */ - int idlebits; /* bits for the idle state (read-only) */ - char chan_name[40]; /* Channel Name */ - int prewink_time; - int preflash_time; - int wink_time; - int flash_time; - int start_time; - int receive_wink_time; - int receive_flash_time; - int debounce_time; - int pulse_break_time; - int pulse_make_time; - int pulse_after_time; - /* latest version of this struct include chan_alarms field */ - uint32_t chan_alarms; -}; - -typedef struct zt_params zt_params_t; - -/* Used with ioctl: ZT_CONFLINK, ZT_GETCONF and ZT_SETCONF */ -struct zt_confinfo { - int chan_no; /* Channel Number, 0 for current */ - int conference_number; - int conference_mode; -}; - -/* Used with ioctl: ZT_GETGAINS and ZT_SETGAINS */ -struct zt_gains { - int chan_no; /* Channel Number, 0 for current */ - unsigned char receive_gain[256]; /* Receive gain table */ - unsigned char transmit_gain[256]; /* Transmit gain table */ -}; - -/* Used with ioctl: ZT_SPANSTAT */ -struct zt_spaninfo { - int span_no; /* span number (-1 to use name) */ - char name[20]; /* Name of span */ - char description[40]; /* Description of span */ - int alarms; /* alarms status */ - int transmit_level; /* Transmit level */ - int receive_level; /* Receive level */ - int bpv_count; /* Current BPV count */ - int crc4_count; /* Current CRC4 error count */ - int ebit_count; /* Current E-bit error count */ - int fas_count; /* Current FAS error count */ - int irq_misses; /* Current IRQ misses */ - int sync_src; /* Span # of sync source (0 = free run) */ - int configured_chan_count; /* Count of channels configured on the span */ - int channel_count; /* Total count of channels on the span */ - int span_count; /* Total count of ftdmtel spans on the system*/ - /* end v1 of the struct */ - /* as long as we don't use the fields below we should be ok regardless of the ftdmtel/dahdi version */ - int lbo; /* Line Build Out */ - int lineconfig; /* framing/coding */ - /* end of v2 of the struct */ - char lboname[40]; /* Line Build Out in text form */ - char location[40]; /* span's device location in system */ - char manufacturer[40]; /* manufacturer of span's device */ - char devicetype[40]; /* span's device type */ - int irq; /* span's device IRQ */ - int linecompat; /* signaling modes possible on this span */ - char spantype[6]; /* type of span in text form */ -}; - -struct zt_maintinfo { - int span_no; /* span number */ - int command; /* Maintenance mode to set (from zt_maintenance_mode_t) */ -}; - -struct zt_lineconfig { -/* Used in ZT_SPANCONFIG */ - int span; /* Which span number (0 to use name) */ - char name[20]; /* Name of span to use */ - int lbo; /* line build-outs */ - int lineconfig; /* line config parameters (framing, coding) */ - int sync; /* what level of sync source we are */ -}; - -struct zt_chanconfig { -/* Used in ZT_CHANCONFIG */ - int chan; /* Channel we're applying this to (0 to use name) */ - char name[40]; /* Name of channel to use */ - int sigtype; /* Signal type */ - int deflaw; /* Default law (ZT_LAW_DEFAULT, ZT_LAW_MULAW, or ZT_LAW_ALAW */ - int master; /* Master channel if sigtype is ZT_SLAVE */ - int idlebits; /* Idle bits (if this is a CAS channel) or channel to monitor (if this is DACS channel) */ - char netdev_name[16]; /* name for the hdlc network device */ -}; - -struct zt_bufferinfo { -/* used in ZT_SET_BUFINFO and ZT_GET_BUFINFO */ - int txbufpolicy; /* Policy for handling receive buffers */ - int rxbufpolicy; /* Policy for handling receive buffers */ - int numbufs; /* How many buffers to use */ - int bufsize; /* How big each buffer is */ - int readbufs; /* How many read buffers are full (read-only) */ - int writebufs; /* How many write buffers are full (read-only) */ -}; - -/* Enumerations */ - -/* Values in zt_params structure for member g711_type */ -typedef enum { - ZT_G711_DEFAULT = 0, /* Default mulaw/alaw from the span */ - ZT_G711_MULAW = 1, - ZT_G711_ALAW = 2 -} zt_g711_t; - -typedef enum { - ZT_EVENT_NONE = 0, - ZT_EVENT_ONHOOK = 1, - ZT_EVENT_RINGOFFHOOK = 2, - ZT_EVENT_WINKFLASH = 3, - ZT_EVENT_ALARM = 4, - ZT_EVENT_NOALARM = 5, - ZT_EVENT_ABORT = 6, - ZT_EVENT_OVERRUN = 7, - ZT_EVENT_BADFCS = 8, - ZT_EVENT_DIALCOMPLETE = 9, - ZT_EVENT_RINGERON = 10, - ZT_EVENT_RINGEROFF = 11, - ZT_EVENT_HOOKCOMPLETE = 12, - ZT_EVENT_BITSCHANGED = 13, - ZT_EVENT_PULSE_START = 14, - ZT_EVENT_TIMER_EXPIRED = 15, - ZT_EVENT_TIMER_PING = 16, - ZT_EVENT_POLARITY = 17, - ZT_EVENT_RINGBEGIN = 18, - ZT_EVENT_DTMFDOWN = (1 << 17), - ZT_EVENT_DTMFUP = (1 << 18), -} zt_event_t; - -typedef enum { - ZT_FLUSH_READ = 1, - ZT_FLUSH_WRITE = 2, - ZT_FLUSH_BOTH = (ZT_FLUSH_READ | ZT_FLUSH_WRITE), - ZT_FLUSH_EVENT = 4, - ZT_FLUSH_ALL = (ZT_FLUSH_READ | ZT_FLUSH_WRITE | ZT_FLUSH_EVENT) -} zt_flush_t; - -typedef enum { - ZT_IOMUX_READ = 1, - ZT_IOMUX_WRITE = 2, - ZT_IOMUX_WRITEEMPTY = 4, - ZT_IOMUX_SIGEVENT = 8, - ZT_IOMUX_NOWAIT = 256 -} zt_iomux_t; - -typedef enum { - ZT_ONHOOK = 0, - ZT_OFFHOOK = 1, - ZT_WINK = 2, - ZT_FLASH = 3, - ZT_START = 4, - ZT_RING = 5, - ZT_RINGOFF = 6 -} zt_hookstate_t; - -typedef enum { - ZT_MAINT_NONE = 0, /* Normal Mode */ - ZT_MAINT_LOCALLOOP = 1, /* Local Loopback */ - ZT_MAINT_REMOTELOOP = 2, /* Remote Loopback */ - ZT_MAINT_LOOPUP = 3, /* Send Loopup Code */ - ZT_MAINT_LOOPDOWN = 4, /* Send Loopdown Code */ - ZT_MAINT_LOOPSTOP = 5 /* Stop Sending Loop Codes */ -} zt_maintenance_mode_t; - -typedef enum { -/* Signalling type */ -ZT_SIG_NONE = 0, /* chan not configured. */ - -ZT_SIG_FXSLS = ((1 << 0) | (1 << 13)), /* FXS, Loopstart */ -ZT_SIG_FXSGS = ((1 << 1) | (1 << 13)), /* FXS, Groundstart */ -ZT_SIG_FXSKS = ((1 << 2) | (1 << 13)), /* FXS, Kewlstart */ -ZT_SIG_FXOLS = ((1 << 3) | (1 << 12)), /* FXO, Loopstart */ -ZT_SIG_FXOGS = ((1 << 4) | (1 << 12)), /* FXO, Groupstart */ -ZT_SIG_FXOKS = ((1 << 5) | (1 << 12)), /* FXO, Kewlstart */ -ZT_SIG_EM = (1 << 6), /* E&M */ -ZT_SIG_CLEAR = (1 << 7), -ZT_SIG_HDLCRAW = ((1 << 8) | ZT_SIG_CLEAR), -ZT_SIG_HDLCFCS = ((1 << 9) | ZT_SIG_HDLCRAW), -ZT_SIG_CAS = (1 << 15), -ZT_SIG_HARDHDLC = ((1 << 19) | ZT_SIG_CLEAR), -} zt_sigtype_t; - -typedef enum { -ZT_DBIT = 1, -ZT_CBIT = 2, -ZT_BBIT = 4, -ZT_ABIT = 8 -} zt_cas_bit_t; - -typedef enum { -/* Tone Detection */ -ZT_TONEDETECT_ON = (1 << 0), /* Detect tones */ -ZT_TONEDETECT_MUTE = (1 << 1) /* Mute audio in received channel */ -} zt_tone_mode_t; - -/* Defines */ - -#define ZT_MAX_BLOCKSIZE 8192 -#define ZT_DEFAULT_MTU_MRU 2048 - -/* ioctl defines */ - -#define ZT_CODE 'J' -#define DAHDI_CODE 0xDA - - -#define ZT_GET_BLOCKSIZE _IOR (ZT_CODE, 1, int) /* Get Transfer Block Size. */ -#define ZT_SET_BLOCKSIZE _IOW (ZT_CODE, 2, int) /* Set Transfer Block Size. */ -#define ZT_FLUSH _IOW (ZT_CODE, 3, int) /* Flush Buffer(s) and stop I/O */ -#define ZT_SYNC _IOW (ZT_CODE, 4, int) /* Wait for Write to Finish */ -#define ZT_GET_PARAMS _IOR (ZT_CODE, 5, struct zt_params) /* Get channel parameters */ -#define ZT_SET_PARAMS _IOW (ZT_CODE, 6, struct zt_params) /* Set channel parameters */ -#define ZT_HOOK _IOW (ZT_CODE, 7, int) /* Set Hookswitch Status */ -#define ZT_GETEVENT _IOR (ZT_CODE, 8, int) /* Get Signalling Event */ -#define ZT_IOMUX _IOWR (ZT_CODE, 9, int) /* Wait for something to happen (IO Mux) */ -#define ZT_SPANSTAT _IOWR (ZT_CODE, 10, struct zt_spaninfo) /* Get Span Status */ -#define ZT_MAINT _IOW (ZT_CODE, 11, struct zt_maintinfo)/* Set Maintenance Mode for a span */ -#define ZT_GETCONF _IOWR (ZT_CODE, 12, struct zt_confinfo) /* Get Conference Mode */ -#define ZT_SETCONF _IOWR (ZT_CODE, 13, struct zt_confinfo) /* Set Conference Mode */ -#define ZT_CONFLINK _IOW (ZT_CODE, 14, struct zt_confinfo) /* Setup or Remove Conference Link */ -#define ZT_CONFDIAG _IOR (ZT_CODE, 15, int) /* Display Conference Diagnostic Information on Console */ - -#define ZT_GETGAINS _IOWR (ZT_CODE, 16, struct zt_gains) /* Get Channel audio gains */ -#define ZT_SETGAINS _IOWR (ZT_CODE, 17, struct zt_gains) /* Set Channel audio gains */ -#define ZT_SPANCONFIG _IOW (ZT_CODE, 18, struct zt_lineconfig)/* Set Line (T1) Configurations and start system */ -#define ZT_CHANCONFIG _IOW (ZT_CODE, 19, struct zt_chanconfig)/* Set Channel Configuration */ -#define ZT_SET_BUFINFO _IOW (ZT_CODE, 27, struct zt_bufferinfo)/* Set buffer policy */ -#define ZT_GET_BUFINFO _IOR (ZT_CODE, 28, struct zt_bufferinfo)/* Get current buffer info */ -#define ZT_AUDIOMODE _IOW (ZT_CODE, 32, int) /* Set a clear channel into audio mode */ -#define ZT_ECHOCANCEL _IOW (ZT_CODE, 33, int) /* Control Echo Canceller */ -#define ZT_HDLCRAWMODE _IOW (ZT_CODE, 36, int) /* Set a clear channel into HDLC w/out FCS checking/calculation mode */ -#define ZT_HDLCFCSMODE _IOW (ZT_CODE, 37, int) /* Set a clear channel into HDLC w/ FCS mode */ - -/* Specify a channel on /dev/ftdm/chan -- must be done before any other ioctl's and is only valid on /dev/ftdm/chan */ -#define ZT_SPECIFY _IOW (ZT_CODE, 38, int) - -/* Temporarily set the law on a channel to ZT_LAW_DEFAULT, ZT_LAW_ALAW, or ZT_LAW_MULAW. Is reset on close. */ -#define ZT_SETLAW _IOW (ZT_CODE, 39, int) - -/* Temporarily set the channel to operate in linear mode when non-zero or default law if 0 */ -#define ZT_SETLINEAR _IOW (ZT_CODE, 40, int) - -#define ZT_GETCONFMUTE _IOR (ZT_CODE, 49, int) /* Get Conference to mute mode */ -#define ZT_ECHOTRAIN _IOW (ZT_CODE, 50, int) /* Control Echo Trainer */ - -/* Set/Get CAS bits */ -#define ZT_SETTXBITS _IOW (ZT_CODE, 43, int) -#define ZT_GETRXBITS _IOR (ZT_CODE, 45, int) - -/* - * Enable tone detection -- implemented by low level driver - */ -#define ZT_TONEDETECT _IOW(ZT_CODE, 91, int) - -#define DAHDI_GET_BLOCKSIZE _IOR (DAHDI_CODE, 1, int) /* Get Transfer Block Size. */ -#define DAHDI_SET_BLOCKSIZE _IOW (DAHDI_CODE, 1, int) /* Set Transfer Block Size. */ -#define DAHDI_FLUSH _IOW (DAHDI_CODE, 3, int) /* Flush Buffer(s) and stop I/O */ -#define DAHDI_SYNC _IO (DAHDI_CODE, 4) /* Wait for Write to Finish */ -#define DAHDI_GET_PARAMS _IOR (DAHDI_CODE, 5, struct zt_params) /* Get channel parameters */ -#define DAHDI_SET_PARAMS _IOW (DAHDI_CODE, 5, struct zt_params) /* Set channel parameters */ -#define DAHDI_HOOK _IOW (DAHDI_CODE, 7, int) /* Set Hookswitch Status */ -#define DAHDI_GETEVENT _IOR (DAHDI_CODE, 8, int) /* Get Signalling Event */ -#define DAHDI_IOMUX _IOWR (DAHDI_CODE, 9, int) /* Wait for something to happen (IO Mux) */ -#define DAHDI_SPANSTAT _IOWR (DAHDI_CODE, 10, struct zt_spaninfo) /* Get Span Status */ -#define DAHDI_MAINT _IOW (DAHDI_CODE, 11, struct zt_maintinfo) /* Set Maintenance Mode for a span */ -#define DAHDI_GETCONF _IOR (DAHDI_CODE, 12, struct zt_confinfo) /* Get Conference Mode */ -#define DAHDI_SETCONF _IOW (DAHDI_CODE, 12, struct zt_confinfo) /* Set Conference Mode */ -#define DAHDI_CONFLINK _IOW (DAHDI_CODE, 14, struct zt_confinfo) /* Setup or Remove Conference Link */ -#define DAHDI_CONFDIAG _IOR (DAHDI_CODE, 15, int) /* Display Conference Diagnostic Information on Console */ - -#define DAHDI_GETGAINS _IOR (DAHDI_CODE, 16, struct zt_gains) /* Get Channel audio gains */ -#define DAHDI_SETGAINS _IOW (DAHDI_CODE, 16, struct zt_gains) /* Set Channel audio gains */ -#define DAHDI_SPANCONFIG _IOW (DAHDI_CODE, 18, struct zt_lineconfig)/* Set Line (T1) Configurations and start system */ -#define DAHDI_CHANCONFIG _IOW (DAHDI_CODE, 19, struct zt_chanconfig)/* Set Channel Configuration */ -#define DAHDI_SET_BUFINFO _IOW (DAHDI_CODE, 27, struct zt_bufferinfo)/* Set buffer policy */ -#define DAHDI_GET_BUFINFO _IOR (DAHDI_CODE, 27, struct zt_bufferinfo)/* Get current buffer info */ -#define DAHDI_AUDIOMODE _IOW (DAHDI_CODE, 32, int) /* Set a clear channel into audio mode */ -#define DAHDI_ECHOCANCEL _IOW (DAHDI_CODE, 33, int) /* Control Echo Canceller */ -#define DAHDI_HDLCRAWMODE _IOW (DAHDI_CODE, 36, int) /* Set a clear channel into HDLC w/out FCS checking/calculation mode */ -#define DAHDI_HDLCFCSMODE _IOW (DAHDI_CODE, 37, int) /* Set a clear channel into HDLC w/ FCS mode */ - -/* Dahdi channel alarms */ -#define DAHDI_ALARM_YELLOW (1 << 2) /* Yellow Alarm */ -#define DAHDI_ALARM_BLUE (1 << 4) /* Blue Alarm */ - -/* Specify a channel on /dev/dahdi/chan -- must be done before any other ioctl's and is only valid on /dev/dahdi/chan */ -#define DAHDI_SPECIFY _IOW (DAHDI_CODE, 38, int) - -/* Temporarily set the law on a channel to DAHDI_LAW_DEFAULT, DAHDI_LAW_ALAW, or DAHDI_LAW_MULAW. Is reset on close. */ -#define DAHDI_SETLAW _IOW (DAHDI_CODE, 39, int) - -/* Temporarily set the channel to operate in linear mode when non-zero or default law if 0 */ -#define DAHDI_SETLINEAR _IOW (DAHDI_CODE, 40, int) - -#define DAHDI_GETCONFMUTE _IOR (DAHDI_CODE, 49, int) /* Get Conference to mute mode */ -#define DAHDI_ECHOTRAIN _IOW (DAHDI_CODE, 50, int) /* Control Echo Trainer */ - -/* Set/Get CAS bits */ -#define DAHDI_SETTXBITS _IOW (DAHDI_CODE, 43, int) -#define DAHDI_GETRXBITS _IOR (DAHDI_CODE, 43, int) - -#define DAHDI_SETPOLARITY _IOW (DAHDI_CODE, 92, int) /* Polarity setting for FXO lines */ - -/* - * Enable tone detection -- implemented by low level driver - */ -#define DAHDI_TONEDETECT _IOW(DAHDI_CODE, 91, int) - -#endif - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/g711.c b/libs/freetdm/src/g711.c deleted file mode 100644 index e113db5811..0000000000 --- a/libs/freetdm/src/g711.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * SpanDSP - a series of DSP components for telephony - * - * g711.c - A-law and u-law transcoding routines - * - * Written by Steve Underwood - * - * Copyright (C) 2006 Steve Underwood - * - * Despite my general liking of the GPL, I place this code in the - * public domain for the benefit of all mankind - even the slimy - * ones who might try to proprietize my work and use it to my - * detriment. - * - * $Id: g711.c,v 1.1 2006/06/07 15:46:39 steveu Exp $ - */ - -/*! \file */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#ifndef _MSC_VER -#include -#ifdef HAVE_TGMATH_H -#include -#endif -#endif - -#include "g711.h" - -/* Copied from the CCITT G.711 specification */ -static const uint8_t ulaw_to_alaw_table[256] = - { - 42, 43, 40, 41, 46, 47, 44, 45, 34, 35, 32, 33, 38, 39, 36, 37, - 58, 59, 56, 57, 62, 63, 60, 61, 50, 51, 48, 49, 54, 55, 52, 53, - 10, 11, 8, 9, 14, 15, 12, 13, 2, 3, 0, 1, 6, 7, 4, 26, - 27, 24, 25, 30, 31, 28, 29, 18, 19, 16, 17, 22, 23, 20, 21, 106, - 104, 105, 110, 111, 108, 109, 98, 99, 96, 97, 102, 103, 100, 101, 122, 120, - 126, 127, 124, 125, 114, 115, 112, 113, 118, 119, 116, 117, 75, 73, 79, 77, - 66, 67, 64, 65, 70, 71, 68, 69, 90, 91, 88, 89, 94, 95, 92, 93, - 82, 82, 83, 83, 80, 80, 81, 81, 86, 86, 87, 87, 84, 84, 85, 85, - 170, 171, 168, 169, 174, 175, 172, 173, 162, 163, 160, 161, 166, 167, 164, 165, - 186, 187, 184, 185, 190, 191, 188, 189, 178, 179, 176, 177, 182, 183, 180, 181, - 138, 139, 136, 137, 142, 143, 140, 141, 130, 131, 128, 129, 134, 135, 132, 154, - 155, 152, 153, 158, 159, 156, 157, 146, 147, 144, 145, 150, 151, 148, 149, 234, - 232, 233, 238, 239, 236, 237, 226, 227, 224, 225, 230, 231, 228, 229, 250, 248, - 254, 255, 252, 253, 242, 243, 240, 241, 246, 247, 244, 245, 203, 201, 207, 205, - 194, 195, 192, 193, 198, 199, 196, 197, 218, 219, 216, 217, 222, 223, 220, 221, - 210, 210, 211, 211, 208, 208, 209, 209, 214, 214, 215, 215, 212, 212, 213, 213 - }; - -/* These transcoding tables are copied from the CCITT G.711 specification. To achieve - optimal results, do not change them. */ - -static const uint8_t alaw_to_ulaw_table[256] = - { - 42, 43, 40, 41, 46, 47, 44, 45, 34, 35, 32, 33, 38, 39, 36, 37, - 57, 58, 55, 56, 61, 62, 59, 60, 49, 50, 47, 48, 53, 54, 51, 52, - 10, 11, 8, 9, 14, 15, 12, 13, 2, 3, 0, 1, 6, 7, 4, 5, - 26, 27, 24, 25, 30, 31, 28, 29, 18, 19, 16, 17, 22, 23, 20, 21, - 98, 99, 96, 97, 102, 103, 100, 101, 93, 93, 92, 92, 95, 95, 94, 94, - 116, 118, 112, 114, 124, 126, 120, 122, 106, 107, 104, 105, 110, 111, 108, 109, - 72, 73, 70, 71, 76, 77, 74, 75, 64, 65, 63, 63, 68, 69, 66, 67, - 86, 87, 84, 85, 90, 91, 88, 89, 79, 79, 78, 78, 82, 83, 80, 81, - 170, 171, 168, 169, 174, 175, 172, 173, 162, 163, 160, 161, 166, 167, 164, 165, - 185, 186, 183, 184, 189, 190, 187, 188, 177, 178, 175, 176, 181, 182, 179, 180, - 138, 139, 136, 137, 142, 143, 140, 141, 130, 131, 128, 129, 134, 135, 132, 133, - 154, 155, 152, 153, 158, 159, 156, 157, 146, 147, 144, 145, 150, 151, 148, 149, - 226, 227, 224, 225, 230, 231, 228, 229, 221, 221, 220, 220, 223, 223, 222, 222, - 244, 246, 240, 242, 252, 254, 248, 250, 234, 235, 232, 233, 238, 239, 236, 237, - 200, 201, 198, 199, 204, 205, 202, 203, 192, 193, 191, 191, 196, 197, 194, 195, - 214, 215, 212, 213, 218, 219, 216, 217, 207, 207, 206, 206, 210, 211, 208, 209 - }; - -uint8_t alaw_to_ulaw(uint8_t alaw) -{ - return alaw_to_ulaw_table[alaw]; -} -/*- End of function --------------------------------------------------------*/ - -uint8_t ulaw_to_alaw(uint8_t ulaw) -{ - return ulaw_to_alaw_table[ulaw]; -} -/*- End of function --------------------------------------------------------*/ -/*- End of file ------------------------------------------------------------*/ - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - diff --git a/libs/freetdm/src/hashtable.c b/libs/freetdm/src/hashtable.c deleted file mode 100644 index 4b39e8599a..0000000000 --- a/libs/freetdm/src/hashtable.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (c) 2002, Christopher Clark - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "private/ftdm_core.h" -#include "hashtable.h" -#include "hashtable_private.h" -#include -#include -#include -#include - -/* - Credit for primes table: Aaron Krowne - http://br.endernet.org/~akrowne/ - http://planetmath.org/encyclopedia/GoodHashTablePrimes.html -*/ -static const unsigned int primes[] = { - 53, 97, 193, 389, - 769, 1543, 3079, 6151, - 12289, 24593, 49157, 98317, - 196613, 393241, 786433, 1572869, - 3145739, 6291469, 12582917, 25165843, - 50331653, 100663319, 201326611, 402653189, - 805306457, 1610612741 -}; -const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]); -const float max_load_factor = 0.65f; - -/*****************************************************************************/ -FT_DECLARE(struct hashtable *) -create_hashtable(unsigned int minsize, - unsigned int (*hashf) (void*), - int (*eqf) (void*,void*)) -{ - struct hashtable *h; - unsigned int pindex, size = primes[0]; - /* Check requested hashtable isn't too large */ - if (minsize > (1u << 30)) return NULL; - /* Enforce size as prime */ - for (pindex=0; pindex < prime_table_length; pindex++) { - if (primes[pindex] > minsize) { size = primes[pindex]; break; } - } - h = (struct hashtable *)ftdm_malloc(sizeof(struct hashtable)); - if (NULL == h) return NULL; /*oom*/ - h->table = (struct entry **)ftdm_malloc(sizeof(struct entry*) * size); - if (NULL == h->table) { ftdm_safe_free(h); return NULL; } /*oom*/ - memset(h->table, 0, size * sizeof(struct entry *)); - h->tablelength = size; - h->primeindex = pindex; - h->entrycount = 0; - h->hashfn = hashf; - h->eqfn = eqf; - h->loadlimit = (unsigned int) ceil(size * max_load_factor); - return h; -} - -/*****************************************************************************/ -unsigned int -hash(struct hashtable *h, void *k) -{ - /* Aim to protect against poor hash functions by adding logic here - * - logic taken from java 1.4 hashtable source */ - unsigned int i = h->hashfn(k); - i += ~(i << 9); - i ^= ((i >> 14) | (i << 18)); /* >>> */ - i += (i << 4); - i ^= ((i >> 10) | (i << 22)); /* >>> */ - return i; -} - -/*****************************************************************************/ -static int -hashtable_expand(struct hashtable *h) -{ - /* Double the size of the table to accomodate more entries */ - struct entry **newtable; - struct entry *e; - struct entry **pE; - unsigned int newsize, i, index; - /* Check we're not hitting max capacity */ - if (h->primeindex == (prime_table_length - 1)) return 0; - newsize = primes[++(h->primeindex)]; - - newtable = (struct entry **)ftdm_malloc(sizeof(struct entry*) * newsize); - if (NULL != newtable) - { - memset(newtable, 0, newsize * sizeof(struct entry *)); - /* This algorithm is not 'stable'. ie. it reverses the list - * when it transfers entries between the tables */ - for (i = 0; i < h->tablelength; i++) { - while (NULL != (e = h->table[i])) { - h->table[i] = e->next; - index = indexFor(newsize,e->h); - e->next = newtable[index]; - newtable[index] = e; - } - } - ftdm_safe_free(h->table); - h->table = newtable; - } - /* Plan B: realloc instead */ - else - { - newtable = (struct entry **) - realloc(h->table, newsize * sizeof(struct entry *)); - if (NULL == newtable) { (h->primeindex)--; return 0; } - h->table = newtable; - memset(newtable[h->tablelength], 0, newsize - h->tablelength); - for (i = 0; i < h->tablelength; i++) { - for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) { - index = indexFor(newsize,e->h); - if (index == i) - { - pE = &(e->next); - } - else - { - *pE = e->next; - e->next = newtable[index]; - newtable[index] = e; - } - } - } - } - h->tablelength = newsize; - h->loadlimit = (unsigned int) ceil(newsize * max_load_factor); - return -1; -} - -/*****************************************************************************/ -FT_DECLARE(unsigned int) -hashtable_count(struct hashtable *h) -{ - return h->entrycount; -} - -/*****************************************************************************/ -FT_DECLARE(int) -hashtable_insert(struct hashtable *h, void *k, void *v, hashtable_flag_t flags) -{ - /* This method allows duplicate keys - but they shouldn't be used */ - unsigned int index; - struct entry *e; - if (++(h->entrycount) > h->loadlimit) - { - /* Ignore the return value. If expand fails, we should - * still try cramming just this value into the existing table - * -- we may not have memory for a larger table, but one more - * element may be ok. Next time we insert, we'll try expanding again.*/ - hashtable_expand(h); - } - e = (struct entry *)ftdm_malloc(sizeof(struct entry)); - if (NULL == e) { --(h->entrycount); return 0; } /*oom*/ - e->h = hash(h,k); - index = indexFor(h->tablelength,e->h); - e->k = k; - e->v = v; - e->flags = flags; - e->next = h->table[index]; - h->table[index] = e; - return -1; -} - -/*****************************************************************************/ -FT_DECLARE(void *) /* returns value associated with key */ -hashtable_search(struct hashtable *h, void *k) -{ - struct entry *e; - unsigned int hashvalue, index; - hashvalue = hash(h,k); - index = indexFor(h->tablelength,hashvalue); - e = h->table[index]; - while (NULL != e) - { - /* Check hash value to short circuit heavier comparison */ - if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v; - e = e->next; - } - return NULL; -} - -/*****************************************************************************/ -FT_DECLARE(void *) /* returns value associated with key */ -hashtable_remove(struct hashtable *h, void *k) -{ - /* TODO: consider compacting the table when the load factor drops enough, - * or provide a 'compact' method. */ - - struct entry *e; - struct entry **pE; - void *v; - unsigned int hashvalue, index; - - hashvalue = hash(h,k); - index = indexFor(h->tablelength,hash(h,k)); - pE = &(h->table[index]); - e = *pE; - while (NULL != e) - { - /* Check hash value to short circuit heavier comparison */ - if ((hashvalue == e->h) && (h->eqfn(k, e->k))) - { - *pE = e->next; - h->entrycount--; - v = e->v; - if (e->flags & HASHTABLE_FLAG_FREE_KEY) { - freekey(e->k); - } - ftdm_safe_free(e); - return v; - } - pE = &(e->next); - e = e->next; - } - return NULL; -} - -/*****************************************************************************/ -/* destroy */ -FT_DECLARE(void) -hashtable_destroy(struct hashtable *h) -{ - unsigned int i; - struct entry *e, *f; - struct entry **table = h->table; - - for (i = 0; i < h->tablelength; i++) - { - e = table[i]; - while (NULL != e) - { f = e; e = e->next; if (f->flags & HASHTABLE_FLAG_FREE_KEY) freekey(f->k); if (f->flags & HASHTABLE_FLAG_FREE_VALUE) ftdm_safe_free(f->v); ftdm_safe_free(f); } - } - - ftdm_safe_free(h->table); - ftdm_safe_free(h); -} - -FT_DECLARE(struct hashtable_iterator *) hashtable_next(struct hashtable_iterator *i) -{ - - if (i->e) { - if ((i->e = i->e->next) != 0) { - return i; - } else { - i->pos++; - } - } - - while(i->pos < i->h->tablelength && !i->h->table[i->pos]) { - i->pos++; - } - - if (i->pos >= i->h->tablelength) { - return NULL; - } - - if ((i->e = i->h->table[i->pos]) != 0) { - return i; - } - - return NULL; -} - -FT_DECLARE(struct hashtable_iterator *) hashtable_first(struct hashtable *h) -{ - h->iterator.pos = 0; - h->iterator.e = NULL; - h->iterator.h = h; - return hashtable_next(&h->iterator); -} - - - -FT_DECLARE(void) hashtable_this(struct hashtable_iterator *i, const void **key, int *klen, void **val) -{ - if (i->e) { - if (key) { - *key = i->e->k; - } - if (klen) { - *klen = (int)strlen(i->e->k); - } - if (val) { - *val = i->e->v; - } - } else { - if (key) { - *key = NULL; - } - if (klen) { - *klen = 0; - } - if (val) { - *val = NULL; - } - } -} - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - diff --git a/libs/freetdm/src/hashtable_itr.c b/libs/freetdm/src/hashtable_itr.c deleted file mode 100644 index 113d1ea503..0000000000 --- a/libs/freetdm/src/hashtable_itr.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2002, 2004, Christopher Clark - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "private/ftdm_core.h" -#include "hashtable.h" -#include "hashtable_private.h" -#include "hashtable_itr.h" -#include /* defines NULL */ - -/*****************************************************************************/ -/* hashtable_iterator - iterator constructor */ - -struct hashtable_itr * -hashtable_iterator(struct hashtable *h) -{ - unsigned int i, tablelength; - struct hashtable_itr *itr = ftdm_malloc(sizeof(struct hashtable_itr)); - if (NULL == itr) return NULL; - itr->h = h; - itr->e = NULL; - itr->parent = NULL; - tablelength = h->tablelength; - itr->index = tablelength; - if (0 == h->entrycount) return itr; - - for (i = 0; i < tablelength; i++) - { - if (NULL != h->table[i]) - { - itr->e = h->table[i]; - itr->index = i; - break; - } - } - return itr; -} - -/*****************************************************************************/ -/* advance - advance the iterator to the next element - * returns zero if advanced to end of table */ - -int -hashtable_iterator_advance(struct hashtable_itr *itr) -{ - unsigned int j,tablelength; - struct entry **table; - struct entry *next; - if (NULL == itr->e) return 0; /* stupidity check */ - - next = itr->e->next; - if (NULL != next) - { - itr->parent = itr->e; - itr->e = next; - return -1; - } - tablelength = itr->h->tablelength; - itr->parent = NULL; - if (tablelength <= (j = ++(itr->index))) - { - itr->e = NULL; - return 0; - } - table = itr->h->table; - while (NULL == (next = table[j])) - { - if (++j >= tablelength) - { - itr->index = tablelength; - itr->e = NULL; - return 0; - } - } - itr->index = j; - itr->e = next; - return -1; -} - -/*****************************************************************************/ -/* remove - remove the entry at the current iterator position - * and advance the iterator, if there is a successive - * element. - * If you want the value, read it before you remove: - * beware memory leaks if you don't. - * Returns zero if end of iteration. */ - -int -hashtable_iterator_remove(struct hashtable_itr *itr) -{ - struct entry *remember_e, *remember_parent; - int ret; - - /* Do the removal */ - if (NULL == (itr->parent)) - { - /* element is head of a chain */ - itr->h->table[itr->index] = itr->e->next; - } else { - /* element is mid-chain */ - itr->parent->next = itr->e->next; - } - /* itr->e is now outside the hashtable */ - remember_e = itr->e; - itr->h->entrycount--; - freekey(remember_e->k); - - /* Advance the iterator, correcting the parent */ - remember_parent = itr->parent; - ret = hashtable_iterator_advance(itr); - if (itr->parent == remember_e) { itr->parent = remember_parent; } - ftdm_safe_free(remember_e); - return ret; -} - -/*****************************************************************************/ -int /* returns zero if not found */ -hashtable_iterator_search(struct hashtable_itr *itr, - struct hashtable *h, void *k) -{ - struct entry *e, *parent; - unsigned int hashvalue, index; - - hashvalue = hash(h,k); - index = indexFor(h->tablelength,hashvalue); - - e = h->table[index]; - parent = NULL; - while (NULL != e) - { - /* Check hash value to short circuit heavier comparison */ - if ((hashvalue == e->h) && (h->eqfn(k, e->k))) - { - itr->index = index; - itr->e = e; - itr->parent = parent; - itr->h = h; - return -1; - } - parent = e; - e = e->next; - } - return 0; -} - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h deleted file mode 100755 index f90744df8d..0000000000 --- a/libs/freetdm/src/include/freetdm.h +++ /dev/null @@ -1,2023 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Contributors: - * - * Moises Silva - * David Yat Sin - * - */ - -#ifndef FREETDM_H -#define FREETDM_H - -#include "ftdm_declare.h" -#include "ftdm_call_utils.h" - -/*! \brief Max number of channels per physical span */ -#define FTDM_MAX_CHANNELS_PHYSICAL_SPAN 32 - -/*! \brief Max number of physical spans per logical span */ -#define FTDM_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN 128 - -/*! \brief Max number of channels a logical span can contain */ -#define FTDM_MAX_CHANNELS_SPAN FTDM_MAX_CHANNELS_PHYSICAL_SPAN * FTDM_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN - -/*! \brief Max number of logical spans */ -#define FTDM_MAX_SPANS_INTERFACE 128 - -/*! \brief Max number of channels per hunting group */ -#define FTDM_MAX_CHANNELS_GROUP 2048 - -/*! \brief Max number of groups */ -#define FTDM_MAX_GROUPS_INTERFACE FTDM_MAX_SPANS_INTERFACE - -/*! \brief Max number of key=value pairs to be sent as signaling stack parameters */ -#define FTDM_MAX_SIG_PARAMETERS 30 - -#define FTDM_INVALID_INT_PARM 0xFF - -/*! \brief Thread/Mutex OS abstraction API. */ -#include "ftdm_os.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/*! \brief Limit to span names */ -#define FTDM_MAX_NAME_STR_SZ 128 - -/*! \brief Limit to channel number strings */ -#define FTDM_MAX_NUMBER_STR_SZ 32 - -/*! \brief Hangup cause codes */ -typedef enum { - FTDM_CAUSE_NONE = 0, - FTDM_CAUSE_UNALLOCATED = 1, - FTDM_CAUSE_NO_ROUTE_TRANSIT_NET = 2, - FTDM_CAUSE_NO_ROUTE_DESTINATION = 3, - FTDM_CAUSE_SEND_SPECIAL_INFO_TONE = 4, - FTDM_CAUSE_MISDIALED_TRUNK_PREFIX = 5, - FTDM_CAUSE_CHANNEL_UNACCEPTABLE = 6, - FTDM_CAUSE_CALL_AWARDED_DELIVERED = 7, - FTDM_CAUSE_PREEMPTION = 8, - FTDM_CAUSE_PREEMPTION_CIRCUIT_RESERVED = 9, - FTDM_CAUSE_NORMAL_CLEARING = 16, - FTDM_CAUSE_USER_BUSY = 17, - FTDM_CAUSE_NO_USER_RESPONSE = 18, - FTDM_CAUSE_NO_ANSWER = 19, - FTDM_CAUSE_SUBSCRIBER_ABSENT = 20, - FTDM_CAUSE_CALL_REJECTED = 21, - FTDM_CAUSE_NUMBER_CHANGED = 22, - FTDM_CAUSE_REDIRECTION_TO_NEW_DESTINATION = 23, - FTDM_CAUSE_EXCHANGE_ROUTING_ERROR = 25, - FTDM_CAUSE_DESTINATION_OUT_OF_ORDER = 27, - FTDM_CAUSE_INVALID_NUMBER_FORMAT = 28, - FTDM_CAUSE_FACILITY_REJECTED = 29, - FTDM_CAUSE_RESPONSE_TO_STATUS_ENQUIRY = 30, - FTDM_CAUSE_NORMAL_UNSPECIFIED = 31, - FTDM_CAUSE_NORMAL_CIRCUIT_CONGESTION = 34, - FTDM_CAUSE_NETWORK_OUT_OF_ORDER = 38, - FTDM_CAUSE_PERMANENT_FRAME_MODE_CONNECTION_OOS = 39, - FTDM_CAUSE_PERMANENT_FRAME_MODE_OPERATIONAL = 40, - FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE = 41, - FTDM_CAUSE_SWITCH_CONGESTION = 42, - FTDM_CAUSE_ACCESS_INFO_DISCARDED = 43, - FTDM_CAUSE_REQUESTED_CHAN_UNAVAIL = 44, - FTDM_CAUSE_PRE_EMPTED = 45, - FTDM_CAUSE_PRECEDENCE_CALL_BLOCKED = 46, - FTDM_CAUSE_RESOURCE_UNAVAILABLE_UNSPECIFIED = 47, - FTDM_CAUSE_QOS_NOT_AVAILABLE = 49, - FTDM_CAUSE_FACILITY_NOT_SUBSCRIBED = 50, - FTDM_CAUSE_OUTGOING_CALL_BARRED = 53, - FTDM_CAUSE_INCOMING_CALL_BARRED = 55, - FTDM_CAUSE_BEARERCAPABILITY_NOTAUTH = 57, - FTDM_CAUSE_BEARERCAPABILITY_NOTAVAIL = 58, - FTDM_CAUSE_INCONSISTENCY_IN_INFO = 62, - FTDM_CAUSE_SERVICE_UNAVAILABLE = 63, - FTDM_CAUSE_BEARERCAPABILITY_NOTIMPL = 65, - FTDM_CAUSE_CHAN_NOT_IMPLEMENTED = 66, - FTDM_CAUSE_FACILITY_NOT_IMPLEMENTED = 69, - FTDM_CAUSE_ONLY_DIGITAL_INFO_BC_AVAIL = 70, - FTDM_CAUSE_SERVICE_NOT_IMPLEMENTED = 79, - FTDM_CAUSE_INVALID_CALL_REFERENCE = 81, - FTDM_CAUSE_IDENTIFIED_CHAN_NOT_EXIST = 82, - FTDM_CAUSE_SUSPENDED_CALL_EXISTS_BUT_CALL_ID_DOES_NOT = 83, - FTDM_CAUSE_CALL_ID_IN_USE = 84, - FTDM_CAUSE_NO_CALL_SUSPENDED = 85, - FTDM_CAUSE_CALL_WITH_CALL_ID_CLEARED = 86, - FTDM_CAUSE_USER_NOT_CUG = 87, - FTDM_CAUSE_INCOMPATIBLE_DESTINATION = 88, - FTDM_CAUSE_NON_EXISTENT_CUG = 90, - FTDM_CAUSE_INVALID_TRANSIT_NETWORK_SELECTION = 91, - FTDM_CAUSE_INVALID_MSG_UNSPECIFIED = 95, - FTDM_CAUSE_MANDATORY_IE_MISSING = 96, - FTDM_CAUSE_MESSAGE_TYPE_NONEXIST = 97, - FTDM_CAUSE_WRONG_MESSAGE = 98, - FTDM_CAUSE_IE_NONEXIST = 99, - FTDM_CAUSE_INVALID_IE_CONTENTS = 100, - FTDM_CAUSE_WRONG_CALL_STATE = 101, - FTDM_CAUSE_RECOVERY_ON_TIMER_EXPIRE = 102, - FTDM_CAUSE_MANDATORY_IE_LENGTH_ERROR = 103, - FTDM_CAUSE_MSG_WITH_UNRECOGNIZED_PARAM_DISCARDED = 110, - FTDM_CAUSE_PROTOCOL_ERROR = 111, - FTDM_CAUSE_INTERWORKING = 127, - FTDM_CAUSE_SUCCESS = 142, - FTDM_CAUSE_ORIGINATOR_CANCEL = 487, - FTDM_CAUSE_CRASH = 500, - FTDM_CAUSE_SYSTEM_SHUTDOWN = 501, - FTDM_CAUSE_LOSE_RACE = 502, - FTDM_CAUSE_MANAGER_REQUEST = 503, - FTDM_CAUSE_BLIND_TRANSFER = 600, - FTDM_CAUSE_ATTENDED_TRANSFER = 601, - FTDM_CAUSE_ALLOTTED_TIMEOUT = 602, - FTDM_CAUSE_USER_CHALLENGE = 603, - FTDM_CAUSE_MEDIA_TIMEOUT = 604 -} ftdm_call_cause_t; - -/*! \brief Hunting direction (when hunting for free channels) */ -typedef enum { - FTDM_HUNT_TOP_DOWN, - FTDM_HUNT_BOTTOM_UP, - FTDM_HUNT_RR_DOWN, - FTDM_HUNT_RR_UP, -} ftdm_hunt_direction_t; - -/*! \brief Legacy Hunting direction (Top down and Bottom up were reversed), keep for source backwards compatibility of freetdm user applications - * \deprecated - * \see ftdm_hunt_direction_t - */ -typedef enum { - FTDM_BOTTOM_UP, - FTDM_TOP_DOWN, - FTDM_RR_UP, - FTDM_RR_DOWN, -} ftdm_direction_t; - -/*! \brief I/O channel type */ -typedef enum { - FTDM_CHAN_TYPE_B, /*!< Bearer channel */ - FTDM_CHAN_TYPE_DQ921, /*!< DQ921 channel (D-channel) */ - FTDM_CHAN_TYPE_DQ931, /*!< DQ931 channel */ - FTDM_CHAN_TYPE_FXS, /*!< FXS analog channel */ - FTDM_CHAN_TYPE_FXO, /*!< FXO analog channel */ - FTDM_CHAN_TYPE_EM, /*!< E & M channel */ - FTDM_CHAN_TYPE_CAS, /*!< CAS channel */ - FTDM_CHAN_TYPE_COUNT /*!< Count of channel types */ -} ftdm_chan_type_t; -#define CHAN_TYPE_STRINGS "B", "DQ921", "DQ931", "FXS", "FXO", "EM", "CAS", "INVALID" -/*! \brief transform from channel type to string and from string to channel type - * ftdm_str2ftdm_chan_type transforms a channel string (ie: "FXO" to FTDM_CHAN_TYPE_FXO) - * ftdm_chan_type2str transforms a channel type to string (ie: FTDM_CHAN_TYPE_B to "B") - */ -FTDM_STR2ENUM_P(ftdm_str2ftdm_chan_type, ftdm_chan_type2str, ftdm_chan_type_t) - -/*! \brief Test if a channel is a voice channel */ -#define FTDM_IS_VOICE_CHANNEL(fchan) ((fchan)->type != FTDM_CHAN_TYPE_DQ921 && (fchan)->type != FTDM_CHAN_TYPE_DQ931) - -/*! \brief Test if a channel is a D-channel */ -#define FTDM_IS_DCHAN(fchan) ((fchan)->type == FTDM_CHAN_TYPE_DQ921 || (fchan)->type == FTDM_CHAN_TYPE_DQ931) - -/*! \brief Test if a channel is digital channel */ -#define FTDM_IS_DIGITAL_CHANNEL(fchan) ((fchan)->span->trunk_type == FTDM_TRUNK_E1 || \ - (fchan)->span->trunk_type == FTDM_TRUNK_T1 || \ - (fchan)->span->trunk_type == FTDM_TRUNK_J1 || \ - (fchan)->span->trunk_type == FTDM_TRUNK_BRI || \ - (fchan)->span->trunk_type == FTDM_TRUNK_BRI_PTMP) - -/*! \brief Test if a span is digital */ -#define FTDM_SPAN_IS_DIGITAL(span) \ - ((span)->trunk_type == FTDM_TRUNK_E1 || \ - (span)->trunk_type == FTDM_TRUNK_T1 || \ - (span)->trunk_type == FTDM_TRUNK_J1 || \ - (span)->trunk_type == FTDM_TRUNK_GSM || \ - (span)->trunk_type == FTDM_TRUNK_BRI || \ - (span)->trunk_type == FTDM_TRUNK_BRI_PTMP) - - -/*! \brief Logging function prototype to be used for all FreeTDM logs - * you should use ftdm_global_set_logger to set your own logger - */ -typedef void (*ftdm_logger_t)(const char *file, const char *func, int line, int level, const char *fmt, ...) __ftdm_check_printf(5, 6); - -/*! \brief Data queue operation functions - * you can use ftdm_global_set_queue_handler if you want to override the default implementation (not recommended) - */ -typedef ftdm_status_t (*ftdm_queue_create_func_t)(ftdm_queue_t **queue, ftdm_size_t capacity); -typedef ftdm_status_t (*ftdm_queue_enqueue_func_t)(ftdm_queue_t *queue, void *obj); -typedef void *(*ftdm_queue_dequeue_func_t)(ftdm_queue_t *queue); -typedef ftdm_status_t (*ftdm_queue_wait_func_t)(ftdm_queue_t *queue, int ms); -typedef ftdm_status_t (*ftdm_queue_get_interrupt_func_t)(ftdm_queue_t *queue, ftdm_interrupt_t **interrupt); -typedef ftdm_status_t (*ftdm_queue_destroy_func_t)(ftdm_queue_t **queue); - -typedef struct ftdm_queue_handler { - ftdm_queue_create_func_t create; - ftdm_queue_enqueue_func_t enqueue; - ftdm_queue_dequeue_func_t dequeue; - ftdm_queue_wait_func_t wait; - ftdm_queue_get_interrupt_func_t get_interrupt; - ftdm_queue_destroy_func_t destroy; -} ftdm_queue_handler_t; - -/*! \brief Type Of Number (TON) */ -typedef enum { - FTDM_TON_UNKNOWN = 0, - FTDM_TON_INTERNATIONAL, - FTDM_TON_NATIONAL, - FTDM_TON_NETWORK_SPECIFIC, - FTDM_TON_SUBSCRIBER_NUMBER, - FTDM_TON_ABBREVIATED_NUMBER, - FTDM_TON_RESERVED, - FTDM_TON_INVALID -} ftdm_ton_t; -#define TON_STRINGS "unknown", "international", "national", "network-specific", "subscriber-number", "abbreviated-number", "reserved", "invalid" -FTDM_STR2ENUM_P(ftdm_str2ftdm_ton, ftdm_ton2str, ftdm_ton_t) - -/*! Numbering Plan Identification (NPI) */ -typedef enum { - FTDM_NPI_UNKNOWN = 0, - FTDM_NPI_ISDN, - FTDM_NPI_DATA, - FTDM_NPI_TELEX, - FTDM_NPI_NATIONAL, - FTDM_NPI_PRIVATE, - FTDM_NPI_RESERVED, - FTDM_NPI_INVALID -} ftdm_npi_t; -#define NPI_STRINGS "unknown", "ISDN", "data", "telex", "national", "private", "reserved", "invalid" -FTDM_STR2ENUM_P(ftdm_str2ftdm_npi, ftdm_npi2str, ftdm_npi_t) - -/*! Presentation Ind */ -typedef enum { - FTDM_PRES_ALLOWED, - FTDM_PRES_RESTRICTED, - FTDM_PRES_NOT_AVAILABLE, - FTDM_PRES_RESERVED, - FTDM_PRES_INVALID -} ftdm_presentation_t; -#define PRESENTATION_STRINGS "presentation-allowed", "presentation-restricted", "number-not-available", "reserved", "Invalid" -FTDM_STR2ENUM_P(ftdm_str2ftdm_presentation, ftdm_presentation2str, ftdm_presentation_t) - -/*! Screening Ind */ -typedef enum { - FTDM_SCREENING_NOT_SCREENED, - FTDM_SCREENING_VERIFIED_PASSED, - FTDM_SCREENING_VERIFIED_FAILED, - FTDM_SCREENING_NETWORK_PROVIDED, - FTDM_SCREENING_INVALID -} ftdm_screening_t; -#define SCREENING_STRINGS "user-provided-not-screened", "user-provided-verified-and-passed", "user-provided-verified-and-failed", "network-provided", "invalid" -FTDM_STR2ENUM_P(ftdm_str2ftdm_screening, ftdm_screening2str, ftdm_screening_t) - -/*! \brief bearer capability */ -typedef enum { - FTDM_BEARER_CAP_SPEECH = 0x00, /* Speech */ - FTDM_BEARER_CAP_UNRESTRICTED, /* Unrestricted Digital */ - FTDM_BEARER_CAP_RESTRICTED, /* Restricted Digital */ - FTDM_BEARER_CAP_3_1KHZ_AUDIO, /* 3.1 Khz Audio */ - FTDM_BEARER_CAP_7KHZ_AUDIO, /* 7 Khz Audio or Unrestricted digital w tones */ - FTDM_BEARER_CAP_15KHZ_AUDIO, /* 15 Khz Audio */ - FTDM_BEARER_CAP_VIDEO, /* Video */ - FTDM_BEARER_CAP_INVALID -} ftdm_bearer_cap_t; -#define BEARER_CAP_STRINGS "speech", "unrestricted-digital-information", "restricted-digital-information", "3.1-Khz-audio", "7-Khz-audio", "15-Khz-audio", "video", "invalid" -FTDM_STR2ENUM_P(ftdm_str2ftdm_bearer_cap, ftdm_bearer_cap2str, ftdm_bearer_cap_t) - -/*! \brief user information layer 1 protocol */ -typedef enum { - FTDM_USER_LAYER1_PROT_V110 = 0x01, - FTDM_USER_LAYER1_PROT_ULAW = 0x02, - FTDM_USER_LAYER1_PROT_ALAW = 0x03, - FTDM_USER_LAYER1_PROT_INVALID -} ftdm_user_layer1_prot_t; -#define USER_LAYER1_PROT_STRINGS "V.110", "ulaw", "alaw", "Invalid" -FTDM_STR2ENUM_P(ftdm_str2ftdm_usr_layer1_prot, ftdm_user_layer1_prot2str, ftdm_user_layer1_prot_t) - -/*! Calling Party Category */ -typedef enum { - FTDM_CPC_UNKNOWN, - FTDM_CPC_OPERATOR, - FTDM_CPC_OPERATOR_FRENCH, - FTDM_CPC_OPERATOR_ENGLISH, - FTDM_CPC_OPERATOR_GERMAN, - FTDM_CPC_OPERATOR_RUSSIAN, - FTDM_CPC_OPERATOR_SPANISH, - FTDM_CPC_ORDINARY, - FTDM_CPC_PRIORITY, - FTDM_CPC_DATA, - FTDM_CPC_TEST, - FTDM_CPC_PAYPHONE, - FTDM_CPC_INVALID -} ftdm_calling_party_category_t; -#define CALLING_PARTY_CATEGORY_STRINGS "unknown", "operator", "operator-french", "operator-english", "operator-german", "operator-russian", "operator-spanish", "ordinary", "priority", "data-call", "test-call", "payphone", "invalid" -FTDM_STR2ENUM_P(ftdm_str2ftdm_calling_party_category, ftdm_calling_party_category2str, ftdm_calling_party_category_t) - -/*! Network responses to transfer requests */ -typedef enum { - FTDM_TRANSFER_RESPONSE_OK, /* Call is being transferred */ - FTDM_TRANSFER_RESPONSE_CP_DROP_OFF, /* Calling Party drop off */ - FTDM_TRANSFER_RESPONSE_LIMITS_EXCEEDED, /* Cannot redirect, limits exceeded */ - FTDM_TRANSFER_RESPONSE_INVALID_NUM, /* Network did not receive or recognize dialed number */ - FTDM_TRANSFER_RESPONSE_INVALID_COMMAND, /* Network received an invalid command */ - FTDM_TRANSFER_RESPONSE_TIMEOUT, /* We did not receive a response from Network */ - FTDM_TRANSFER_RESPONSE_INVALID, -} ftdm_transfer_response_t; -#define TRANSFER_RESPONSE_STRINGS "transfer-ok", "cp-drop-off", "limits-exceeded", "invalid-num", "invalid-command", "timeout", "invalid" -FTDM_STR2ENUM_P(ftdm_str2ftdm_transfer_response, ftdm_transfer_response2str, ftdm_transfer_response_t) - -/*! \brief Digit limit used in DNIS/ANI */ -#define FTDM_DIGITS_LIMIT 64 - -#define FTDM_SILENCE_VALUE(fchan) (fchan)->native_codec == FTDM_CODEC_ULAW ? 255 : (fchan)->native_codec == FTDM_CODEC_ALAW ? 0xD5 : 0x00 - -/*! \brief Number abstraction */ -typedef struct { - char digits[FTDM_DIGITS_LIMIT]; - uint8_t type; - uint8_t plan; -} ftdm_number_t; - -typedef struct { - char from[FTDM_MAX_NUMBER_STR_SZ]; - char body[FTDM_MAX_NAME_STR_SZ]; -} ftdm_sms_data_t; - -/*! \brief Caller information */ -typedef struct ftdm_caller_data { - char cid_date[8]; /*!< Caller ID date */ - char cid_name[80]; /*!< Caller ID name */ - ftdm_number_t cid_num; /*!< Caller ID number */ - ftdm_number_t ani; /*!< ANI (Automatic Number Identification) */ - ftdm_number_t dnis; /*!< DNIS (Dialed Number Identification Service) */ - ftdm_number_t rdnis; /*!< RDNIS (Redirected Dialed Number Identification Service) */ - ftdm_number_t loc; /*!< LOC (Location Reference Code) */ - char aniII[FTDM_DIGITS_LIMIT]; /*! ANI II */ - uint8_t screen; /*!< Screening */ - uint8_t pres; /*!< Presentation*/ - char collected[FTDM_DIGITS_LIMIT]; /*!< Collected digits so far */ - int hangup_cause; /*!< Hangup cause */ - /* these 2 are undocumented right now, only used by boost: */ - /* bearer capability */ - ftdm_bearer_cap_t bearer_capability; - /* user information layer 1 protocol */ - ftdm_user_layer1_prot_t bearer_layer1; - ftdm_calling_party_category_t cpc; /*!< Calling party category */ - uint32_t call_reference; - - ftdm_channel_t *fchan; /*!< FreeTDM channel associated (can be NULL) */ - - /* - * We need call_id inside caller_data for the user to be able to retrieve - * the call_id when ftdm_channel_call_place is called. This is the only time - * that the user can use caller_data.call_id to obtain the call_id. The user - * should use the call_id from sigmsg otherwise - */ - uint32_t call_id; /*!< Unique call ID for this call */ - - void *priv; /*!< Private data for the FreeTDM user */ -} ftdm_caller_data_t; - -/*! \brief Hunting mode */ -typedef enum { - FTDM_HUNT_SPAN, /*!< Hunt channels in a given span */ - FTDM_HUNT_GROUP, /*!< Hunt channels in a given group */ - FTDM_HUNT_CHAN, /*!< Hunt for a specific channel */ -} ftdm_hunt_mode_t; - -/*! \brief Structure used for FTDM_HUNT_SPAN mode */ -typedef struct { - uint32_t span_id; - ftdm_hunt_direction_t direction; -} ftdm_span_hunt_t; - -/*! \brief Structure used for FTDM_HUNT_GROUP mode */ -typedef struct { - uint32_t group_id; - ftdm_hunt_direction_t direction; -} ftdm_group_hunt_t; - -/*! \brief Structure used for FTDM_HUNT_CHAN mode */ -typedef struct { - uint32_t span_id; - uint32_t chan_id; -} ftdm_chan_hunt_t; - -/*! \brief Function called before placing the call in the hunted channel - * The user can have a last saying in whether to proceed or abort - * the call attempt. Be aware that this callback will be called with - * the channel lock and you must not do any blocking operations during - * its execution. - * \param fchan The channel that will be used to place the call - * \param caller_data The caller data provided to ftdm_call_place - * \return FTDM_SUCCESS to proceed or FTDM_BREAK to abort the hunting - */ -typedef ftdm_status_t (*ftdm_hunt_result_cb_t)(ftdm_channel_t *fchan, ftdm_caller_data_t *caller_data); - -/*! \brief Channel Hunting provided to ftdm_call_place() */ -typedef struct { - ftdm_hunt_mode_t mode; - union { - ftdm_span_hunt_t span; - ftdm_group_hunt_t group; - ftdm_chan_hunt_t chan; - } mode_data; - ftdm_hunt_result_cb_t result_cb; -} ftdm_hunting_scheme_t; - - -/*! \brief Tone type */ -typedef enum { - FTDM_TONE_DTMF = (1 << 0) -} ftdm_tone_type_t; - -/*! \brief Signaling messages sent by the stacks */ -typedef enum { - FTDM_SIGEVENT_START,/*!< Incoming call (ie: incoming SETUP msg or Ring) */ - FTDM_SIGEVENT_STOP, /*!< Hangup */ - FTDM_SIGEVENT_RELEASED, /*!< Channel is completely released and available */ - FTDM_SIGEVENT_UP, /*!< Outgoing call has been answered */ - FTDM_SIGEVENT_FLASH, /*!< Flash event (typically on-hook/off-hook for analog devices) */ - FTDM_SIGEVENT_PROCEED, /*!< Outgoing call got an initial positive response from the other end */ - FTDM_SIGEVENT_RINGING, /*!< Remote side is in ringing state */ - FTDM_SIGEVENT_PROGRESS, /*!< Outgoing call is making progress */ - FTDM_SIGEVENT_PROGRESS_MEDIA, /*!< Outgoing call is making progress and there is media available */ - FTDM_SIGEVENT_ALARM_TRAP, /*!< Hardware alarm ON */ - FTDM_SIGEVENT_ALARM_CLEAR, /*!< Hardware alarm OFF */ - FTDM_SIGEVENT_COLLECTED_DIGIT, /*!< Digit collected (in signalings where digits are collected one by one) */ - FTDM_SIGEVENT_ADD_CALL, /*!< New call should be added to the channel */ - FTDM_SIGEVENT_RESTART, /*!< Restart has been requested. Typically you hangup your call resources here */ - FTDM_SIGEVENT_SIGSTATUS_CHANGED, /*!< Signaling protocol status changed (ie: D-chan up), see new status in raw_data ftdm_sigmsg_t member */ - FTDM_SIGEVENT_FACILITY, /*!< In call facility event */ - FTDM_SIGEVENT_TRACE, /*!priv */ - ftdm_variable_container_t variables; - union { - ftdm_event_sigstatus_t sigstatus; /*!< valid if event_id is FTDM_SIGEVENT_SIGSTATUS_CHANGED */ - ftdm_event_trace_t trace; /*!< valid if event_id is FTDM_SIGEVENT_TRACE or FTDM_SIGEVENT_TRACE_RAW */ - ftdm_event_collected_t collected; /*!< valid if event_id is FTDM_SIGEVENT_COLLECTED_DIGIT */ - ftdm_event_indication_completed_t indication_completed; /*!< valid if the event_id is FTDM_SIGEVENT_INDICATION_COMPLETED */ - ftdm_event_transfer_completed_t transfer_completed; - } ev_data; - ftdm_raw_data_t raw; -}; - -/*! \brief Generic user message sent to the stack */ -struct ftdm_usrmsg { - ftdm_variable_container_t variables; - ftdm_raw_data_t raw; -}; - -/*! \brief Crash policy - * Useful for debugging only, default policy is never, if you wish to crash on asserts then use ftdm_global_set_crash_policy */ -typedef enum { - FTDM_CRASH_NEVER = 0, - FTDM_CRASH_ON_ASSERT -} ftdm_crash_policy_t; - -/*! \brief Signaling configuration parameter for the stacks (variable=value pair) */ -typedef struct ftdm_conf_parameter { - const char *var; - const char *val; - void *ptr; -} ftdm_conf_parameter_t; - -/*! \brief Opaque general purpose iterator */ -typedef struct ftdm_iterator ftdm_iterator_t; - -/*! \brief Channel commands that can be executed through ftdm_channel_command() */ -typedef enum { - FTDM_COMMAND_NOOP = 0, - FTDM_COMMAND_SET_INTERVAL = 1, - FTDM_COMMAND_GET_INTERVAL = 2, - FTDM_COMMAND_SET_CODEC = 3, - FTDM_COMMAND_GET_CODEC = 4, - FTDM_COMMAND_SET_NATIVE_CODEC = 5, - FTDM_COMMAND_GET_NATIVE_CODEC = 6, - FTDM_COMMAND_ENABLE_DTMF_DETECT = 7, - FTDM_COMMAND_DISABLE_DTMF_DETECT = 8, - FTDM_COMMAND_SEND_DTMF = 9, - FTDM_COMMAND_SET_DTMF_ON_PERIOD = 10, - FTDM_COMMAND_GET_DTMF_ON_PERIOD = 11, - FTDM_COMMAND_SET_DTMF_OFF_PERIOD = 12, - FTDM_COMMAND_GET_DTMF_OFF_PERIOD = 13, - FTDM_COMMAND_GENERATE_RING_ON = 14, - FTDM_COMMAND_GENERATE_RING_OFF = 15, - FTDM_COMMAND_OFFHOOK = 16, - FTDM_COMMAND_ONHOOK = 17, - FTDM_COMMAND_FLASH = 18, - FTDM_COMMAND_WINK = 19, - FTDM_COMMAND_ENABLE_PROGRESS_DETECT = 20, - FTDM_COMMAND_DISABLE_PROGRESS_DETECT = 21, - - /*!< Start tracing input and output from channel to the given file */ - FTDM_COMMAND_TRACE_INPUT = 22, - FTDM_COMMAND_TRACE_OUTPUT = 23, - - /*!< Stop both Input and Output trace, closing the files */ - FTDM_COMMAND_TRACE_END_ALL = 24, - - /*!< Enable DTMF debugging */ - FTDM_COMMAND_ENABLE_DEBUG_DTMF = 25, - - /*!< Disable DTMF debugging (if not disabled explicitly, it is disabled automatically when calls hangup) */ - FTDM_COMMAND_DISABLE_DEBUG_DTMF = 26, - - /*!< Start dumping all input to a circular buffer. The size of the circular buffer can be specified, default used otherwise */ - FTDM_COMMAND_ENABLE_INPUT_DUMP = 27, - - /*!< Stop dumping all input to a circular buffer. */ - FTDM_COMMAND_DISABLE_INPUT_DUMP = 28, - - /*!< Start dumping all output to a circular buffer. The size of the circular buffer can be specified, default used otherwise */ - FTDM_COMMAND_ENABLE_OUTPUT_DUMP = 29, - - /*!< Stop dumping all output to a circular buffer. */ - FTDM_COMMAND_DISABLE_OUTPUT_DUMP = 30, - - /*!< Dump the current input circular buffer to the specified FILE* structure */ - FTDM_COMMAND_DUMP_INPUT = 31, - - /*!< Dump the current output circular buffer to the specified FILE* structure */ - FTDM_COMMAND_DUMP_OUTPUT = 32, - - FTDM_COMMAND_ENABLE_CALLERID_DETECT = 33, - FTDM_COMMAND_DISABLE_CALLERID_DETECT = 34, - FTDM_COMMAND_ENABLE_ECHOCANCEL = 35, - FTDM_COMMAND_DISABLE_ECHOCANCEL = 36, - FTDM_COMMAND_ENABLE_ECHOTRAIN = 37, - FTDM_COMMAND_DISABLE_ECHOTRAIN = 38, - FTDM_COMMAND_SET_CAS_BITS = 39, - FTDM_COMMAND_GET_CAS_BITS = 40, - FTDM_COMMAND_SET_RX_GAIN = 41, - FTDM_COMMAND_GET_RX_GAIN = 42, - FTDM_COMMAND_SET_TX_GAIN = 43, - FTDM_COMMAND_GET_TX_GAIN = 44, - FTDM_COMMAND_FLUSH_TX_BUFFERS = 45, - FTDM_COMMAND_FLUSH_RX_BUFFERS = 46, - FTDM_COMMAND_FLUSH_BUFFERS = 47, - - /*!< Flush IO statistics */ - FTDM_COMMAND_FLUSH_IOSTATS = 48, - - FTDM_COMMAND_SET_PRE_BUFFER_SIZE = 49, - FTDM_COMMAND_SET_LINK_STATUS = 50, - FTDM_COMMAND_GET_LINK_STATUS = 51, - FTDM_COMMAND_ENABLE_LOOP = 52, - FTDM_COMMAND_DISABLE_LOOP = 53, - FTDM_COMMAND_SET_RX_QUEUE_SIZE = 54, - FTDM_COMMAND_SET_TX_QUEUE_SIZE = 55, - FTDM_COMMAND_SET_POLARITY = 56, - FTDM_COMMAND_START_MF_PLAYBACK = 57, - FTDM_COMMAND_STOP_MF_PLAYBACK = 58, - - /*!< Get a copy of the current IO stats */ - FTDM_COMMAND_GET_IOSTATS = 59, - /*!< Enable/disable IO stats in the channel */ - FTDM_COMMAND_SWITCH_IOSTATS = 60, - - /*!< Enable/disable DTMF removal */ - FTDM_COMMAND_ENABLE_DTMF_REMOVAL = 61, - FTDM_COMMAND_DISABLE_DTMF_REMOVAL = 62, - - FTDM_COMMAND_COUNT, -} ftdm_command_t; - -typedef enum { - FTDM_POLARITY_FORWARD = 0, - FTDM_POLARITY_REVERSE = 1 -} ftdm_polarity_t; - -/*! \brief Custom memory handler hooks. Not recommended to use unless you need memory allocation customizations */ -typedef void *(*ftdm_malloc_func_t)(void *pool, ftdm_size_t len); -typedef void *(*ftdm_calloc_func_t)(void *pool, ftdm_size_t elements, ftdm_size_t len); -typedef void *(*ftdm_realloc_func_t)(void *pool, void *buff, ftdm_size_t len); -typedef void (*ftdm_free_func_t)(void *pool, void *ptr); -struct ftdm_memory_handler { - void *pool; - ftdm_malloc_func_t malloc; - ftdm_calloc_func_t calloc; - ftdm_realloc_func_t realloc; - ftdm_free_func_t free; -}; - -/*! \brief FreeTDM I/O layer interface argument macros - * You don't need these unless your implementing an I/O interface module (most users don't) */ -#define FIO_CHANNEL_REQUEST_ARGS (ftdm_span_t *span, uint32_t chan_id, ftdm_hunt_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan) -#define FIO_CHANNEL_OUTGOING_CALL_ARGS (ftdm_channel_t *ftdmchan) -#define FIO_CHANNEL_INDICATE_ARGS (ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication) -#define FIO_CHANNEL_SET_SIG_STATUS_ARGS (ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status) -#define FIO_CHANNEL_GET_SIG_STATUS_ARGS (ftdm_channel_t *ftdmchan, ftdm_signaling_status_t *status) -#define FIO_SPAN_SET_SIG_STATUS_ARGS (ftdm_span_t *span, ftdm_signaling_status_t status) -#define FIO_SPAN_GET_SIG_STATUS_ARGS (ftdm_span_t *span, ftdm_signaling_status_t *status) -#define FIO_SPAN_POLL_EVENT_ARGS (ftdm_span_t *span, uint32_t ms, short *poll_events) -#define FIO_SPAN_NEXT_EVENT_ARGS (ftdm_span_t *span, ftdm_event_t **event) -#define FIO_CHANNEL_NEXT_EVENT_ARGS (ftdm_channel_t *ftdmchan, ftdm_event_t **event) -#define FIO_SIGNAL_CB_ARGS (ftdm_sigmsg_t *sigmsg) -#define FIO_EVENT_CB_ARGS (ftdm_channel_t *ftdmchan, ftdm_event_t *event) -#define FIO_CONFIGURE_SPAN_ARGS (ftdm_span_t *span, const char *str, ftdm_chan_type_t type, char *name, char *number) -#define FIO_CONFIGURE_ARGS (const char *category, const char *var, const char *val, int lineno) -#define FIO_OPEN_ARGS (ftdm_channel_t *ftdmchan) -#define FIO_CLOSE_ARGS (ftdm_channel_t *ftdmchan) -#define FIO_CHANNEL_DESTROY_ARGS (ftdm_channel_t *ftdmchan) -#define FIO_SPAN_DESTROY_ARGS (ftdm_span_t *span) -#define FIO_COMMAND_ARGS (ftdm_channel_t *ftdmchan, ftdm_command_t command, void *obj) -#define FIO_WAIT_ARGS (ftdm_channel_t *ftdmchan, ftdm_wait_flag_t *flags, int32_t to) -#define FIO_GET_ALARMS_ARGS (ftdm_channel_t *ftdmchan) -#define FIO_READ_ARGS (ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen) -#define FIO_WRITE_ARGS (ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen) -#define FIO_IO_LOAD_ARGS (ftdm_io_interface_t **fio) -#define FIO_IO_UNLOAD_ARGS (void) -#define FIO_SIG_LOAD_ARGS (void) -#define FIO_SIG_CONFIGURE_ARGS (ftdm_span_t *span, fio_signal_cb_t sig_cb, va_list ap) -#define FIO_CONFIGURE_SPAN_SIGNALING_ARGS (ftdm_span_t *span, fio_signal_cb_t sig_cb, ftdm_conf_parameter_t *ftdm_parameters) -#define FIO_SIG_UNLOAD_ARGS (void) -#define FIO_API_ARGS (ftdm_stream_handle_t *stream, const char *data) -#define FIO_SPAN_START_ARGS (ftdm_span_t *span) -#define FIO_SPAN_STOP_ARGS (ftdm_span_t *span) - -/*! \brief FreeTDM I/O layer interface function typedefs - * You don't need these unless your implementing an I/O interface module (most users don't) */ -typedef ftdm_status_t (*fio_channel_request_t) FIO_CHANNEL_REQUEST_ARGS ; -typedef ftdm_status_t (*fio_channel_outgoing_call_t) FIO_CHANNEL_OUTGOING_CALL_ARGS ; -typedef ftdm_status_t (*fio_channel_indicate_t) FIO_CHANNEL_INDICATE_ARGS; -typedef ftdm_status_t (*fio_channel_set_sig_status_t) FIO_CHANNEL_SET_SIG_STATUS_ARGS; -typedef ftdm_status_t (*fio_channel_get_sig_status_t) FIO_CHANNEL_GET_SIG_STATUS_ARGS; -typedef ftdm_status_t (*fio_span_set_sig_status_t) FIO_SPAN_SET_SIG_STATUS_ARGS; -typedef ftdm_status_t (*fio_span_get_sig_status_t) FIO_SPAN_GET_SIG_STATUS_ARGS; -typedef ftdm_status_t (*fio_span_poll_event_t) FIO_SPAN_POLL_EVENT_ARGS ; -typedef ftdm_status_t (*fio_span_next_event_t) FIO_SPAN_NEXT_EVENT_ARGS ; -typedef ftdm_status_t (*fio_channel_next_event_t) FIO_CHANNEL_NEXT_EVENT_ARGS ; - -/*! \brief Callback for signal delivery (FTDM_SIGEVENT_START and friends) - * \note This callback is provided by the user during ftdm_configure_span_signaling - * - * \note You must NOT do any blocking during this callback since this function is - * most likely called in an internal signaling thread that can potentially be - * shared for all the channels in a span and blocking will delay processing - * (sometimes even audio processing) for other channels - * - * \note Although some simple FreeTDM APIs can work (ie: ftdm_span_get_id etc), the - * use of any FreeTDM call API (ie ftdm_channel_call_answer) is discouraged - */ -typedef ftdm_status_t (*fio_signal_cb_t) FIO_SIGNAL_CB_ARGS ; - -typedef ftdm_status_t (*fio_event_cb_t) FIO_EVENT_CB_ARGS ; -typedef ftdm_status_t (*fio_configure_span_t) FIO_CONFIGURE_SPAN_ARGS ; -typedef ftdm_status_t (*fio_configure_t) FIO_CONFIGURE_ARGS ; -typedef ftdm_status_t (*fio_open_t) FIO_OPEN_ARGS ; -typedef ftdm_status_t (*fio_close_t) FIO_CLOSE_ARGS ; -typedef ftdm_status_t (*fio_channel_destroy_t) FIO_CHANNEL_DESTROY_ARGS ; -typedef ftdm_status_t (*fio_span_destroy_t) FIO_SPAN_DESTROY_ARGS ; -typedef ftdm_status_t (*fio_get_alarms_t) FIO_GET_ALARMS_ARGS ; -typedef ftdm_status_t (*fio_command_t) FIO_COMMAND_ARGS ; -typedef ftdm_status_t (*fio_wait_t) FIO_WAIT_ARGS ; -typedef ftdm_status_t (*fio_read_t) FIO_READ_ARGS ; -typedef ftdm_status_t (*fio_write_t) FIO_WRITE_ARGS ; -typedef ftdm_status_t (*fio_io_load_t) FIO_IO_LOAD_ARGS ; -typedef ftdm_status_t (*fio_sig_load_t) FIO_SIG_LOAD_ARGS ; -typedef ftdm_status_t (*fio_sig_configure_t) FIO_SIG_CONFIGURE_ARGS ; -typedef ftdm_status_t (*fio_configure_span_signaling_t) FIO_CONFIGURE_SPAN_SIGNALING_ARGS ; -typedef ftdm_status_t (*fio_io_unload_t) FIO_IO_UNLOAD_ARGS ; -typedef ftdm_status_t (*fio_sig_unload_t) FIO_SIG_UNLOAD_ARGS ; -typedef ftdm_status_t (*fio_api_t) FIO_API_ARGS ; -typedef ftdm_status_t (*fio_span_start_t) FIO_SPAN_START_ARGS ; -typedef ftdm_status_t (*fio_span_stop_t) FIO_SPAN_STOP_ARGS ; - - -/*! \brief FreeTDM I/O layer interface function prototype wrapper macros - * You don't need these unless your implementing an I/O interface module (most users don't) */ -#define FIO_CHANNEL_REQUEST_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_REQUEST_ARGS -#define FIO_CHANNEL_OUTGOING_CALL_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_OUTGOING_CALL_ARGS -#define FIO_CHANNEL_INDICATE_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_INDICATE_ARGS -#define FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_SET_SIG_STATUS_ARGS -#define FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_GET_SIG_STATUS_ARGS -#define FIO_SPAN_SET_SIG_STATUS_FUNCTION(name) ftdm_status_t name FIO_SPAN_SET_SIG_STATUS_ARGS -#define FIO_SPAN_GET_SIG_STATUS_FUNCTION(name) ftdm_status_t name FIO_SPAN_GET_SIG_STATUS_ARGS -#define FIO_SPAN_POLL_EVENT_FUNCTION(name) ftdm_status_t name FIO_SPAN_POLL_EVENT_ARGS -#define FIO_SPAN_NEXT_EVENT_FUNCTION(name) ftdm_status_t name FIO_SPAN_NEXT_EVENT_ARGS -#define FIO_CHANNEL_NEXT_EVENT_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_NEXT_EVENT_ARGS -#define FIO_SIGNAL_CB_FUNCTION(name) ftdm_status_t name FIO_SIGNAL_CB_ARGS -#define FIO_EVENT_CB_FUNCTION(name) ftdm_status_t name FIO_EVENT_CB_ARGS -#define FIO_CONFIGURE_SPAN_FUNCTION(name) ftdm_status_t name FIO_CONFIGURE_SPAN_ARGS -#define FIO_CONFIGURE_FUNCTION(name) ftdm_status_t name FIO_CONFIGURE_ARGS -#define FIO_OPEN_FUNCTION(name) ftdm_status_t name FIO_OPEN_ARGS -#define FIO_CLOSE_FUNCTION(name) ftdm_status_t name FIO_CLOSE_ARGS -#define FIO_CHANNEL_DESTROY_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_DESTROY_ARGS -#define FIO_SPAN_DESTROY_FUNCTION(name) ftdm_status_t name FIO_SPAN_DESTROY_ARGS -#define FIO_GET_ALARMS_FUNCTION(name) ftdm_status_t name FIO_GET_ALARMS_ARGS -#define FIO_COMMAND_FUNCTION(name) ftdm_status_t name FIO_COMMAND_ARGS -#define FIO_WAIT_FUNCTION(name) ftdm_status_t name FIO_WAIT_ARGS -#define FIO_READ_FUNCTION(name) ftdm_status_t name FIO_READ_ARGS -#define FIO_WRITE_FUNCTION(name) ftdm_status_t name FIO_WRITE_ARGS -#define FIO_IO_LOAD_FUNCTION(name) ftdm_status_t name FIO_IO_LOAD_ARGS -#define FIO_SIG_LOAD_FUNCTION(name) ftdm_status_t name FIO_SIG_LOAD_ARGS -#define FIO_SIG_CONFIGURE_FUNCTION(name) ftdm_status_t name FIO_SIG_CONFIGURE_ARGS -#define FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(name) ftdm_status_t name FIO_CONFIGURE_SPAN_SIGNALING_ARGS -#define FIO_IO_UNLOAD_FUNCTION(name) ftdm_status_t name FIO_IO_UNLOAD_ARGS -#define FIO_SIG_UNLOAD_FUNCTION(name) ftdm_status_t name FIO_SIG_UNLOAD_ARGS -#define FIO_API_FUNCTION(name) ftdm_status_t name FIO_API_ARGS -#define FIO_SPAN_START_FUNCTION(name) ftdm_status_t name FIO_SPAN_START_ARGS -#define FIO_SPAN_STOP_FUNCTION(name) ftdm_status_t name FIO_SPAN_STOP_ARGS - -/*! \brief FreeTDM I/O layer function prototype wrapper macros - * You don't need these unless your implementing an I/O interface module (most users don't) */ -struct ftdm_io_interface { - const char *name; /*!< I/O module name */ - fio_configure_span_t configure_span; /*!< Configure span I/O */ - fio_configure_t configure; /*!< Configure the module */ - fio_open_t open; /*!< Open I/O channel */ - fio_close_t close; /*!< Close I/O channel */ - fio_channel_destroy_t channel_destroy; /*!< Destroy I/O channel */ - fio_span_destroy_t span_destroy; /*!< Destroy span I/O */ - fio_get_alarms_t get_alarms; /*!< Get hardware alarms */ - fio_command_t command; /*!< Execute an I/O command on the channel */ - fio_wait_t wait; /*!< Wait for events on the channel */ - fio_read_t read; /*!< Read data from the channel */ - fio_write_t write; /*!< Write data to the channel */ - fio_span_poll_event_t poll_event; /*!< Poll for events on the whole span */ - fio_span_next_event_t next_event; /*!< Retrieve an event from the span */ - fio_channel_next_event_t channel_next_event; /*!< Retrieve an event from channel */ - fio_api_t api; /*!< Execute a text command */ - fio_span_start_t span_start; /*!< Start span I/O */ - fio_span_stop_t span_stop; /*!< Stop span I/O */ -}; - -/*! \brief FreeTDM supported I/O codecs */ -typedef enum { - FTDM_CODEC_ULAW = 0, - FTDM_CODEC_ALAW = 8, - FTDM_CODEC_SLIN = 10, - FTDM_CODEC_NONE = (1 << 30) -} ftdm_codec_t; - -/*! \brief FreeTDM supported hardware alarms. */ -typedef enum { - FTDM_ALARM_NONE = 0, - FTDM_ALARM_RED = (1 << 0), - FTDM_ALARM_YELLOW = (1 << 1), - FTDM_ALARM_RAI = (1 << 2), - FTDM_ALARM_BLUE = (1 << 3), - FTDM_ALARM_AIS = (1 << 4), - FTDM_ALARM_GENERAL = (1 << 30) -} ftdm_alarm_flag_t; - -/*! \brief MF generation direction flags - * \note Used in bitwise OR with channel ID as argument to MF_PLAYBACK I/O command, so value must be higher that 255 - * \see FTDM_COMMAND_START_MF_PLAYBACK - * */ - -typedef enum { - FTDM_MF_DIRECTION_FORWARD = (1 << 8), - FTDM_MF_DIRECTION_BACKWARD = (1 << 9) -} ftdm_mf_direction_flag_t; - -/*! \brief IO Error statistics */ -typedef enum { - FTDM_IOSTATS_ERROR_CRC = (1 << 0), - FTDM_IOSTATS_ERROR_FRAME = (1 << 1), - FTDM_IOSTATS_ERROR_ABORT = (1 << 2), - FTDM_IOSTATS_ERROR_FIFO = (1 << 3), - FTDM_IOSTATS_ERROR_DMA = (1 << 4), - FTDM_IOSTATS_ERROR_QUEUE_THRES = (1 << 5), /* Queue reached high threshold */ - FTDM_IOSTATS_ERROR_QUEUE_FULL = (1 << 6), /* Queue is full */ -} ftdm_iostats_error_type_t; - -/*! \brief IO statistics */ -typedef struct { - struct { - uint64_t packets; - uint32_t errors; - uint16_t flags; - uint8_t queue_size; /*!< max queue size configured */ - uint8_t queue_len; /*!< Current number of elements in queue */ - } rx; - - struct { - uint64_t idle_packets; - uint64_t packets; - uint32_t errors; - uint16_t flags; - uint8_t queue_size; /*!< max queue size configured */ - uint8_t queue_len; /*!< Current number of elements in queue */ - } tx; -} ftdm_channel_iostats_t; - -/*! \brief Override the default queue handler */ -FT_DECLARE(ftdm_status_t) ftdm_global_set_queue_handler(ftdm_queue_handler_t *handler); - -/*! \brief Return the availability rate for a channel - * \param ftdmchan Channel to get the availability from - * - * \retval > 0 if availability is supported - * \retval -1 if availability is not supported - */ -FT_DECLARE(int) ftdm_channel_get_availability(ftdm_channel_t *ftdmchan); - -/*! \brief Answer call. This can also be accomplished by ftdm_channel_call_indicate with FTDM_CHANNEL_INDICATE_ANSWER, in both - * cases you will get a FTDM_SIGEVENT_INDICATION_COMPLETED when the indication is sent (or an error occurs). - * Just as with ftdm_channel_call_indicate you won't receive FTDM_SIGEVENT_INDICATION_COMPLETED when this function - * returns anything else than FTDM_SUCCESS - * \note Although this API may result in FTDM_SIGEVENT_INDICATION_COMPLETED event being delivered, - * there is no guarantee of whether the event will arrive after or before your execution thread returns - * from ftdm_channel_call_answer - */ -#define ftdm_channel_call_answer(ftdmchan) _ftdm_channel_call_answer(__FILE__, __FTDM_FUNC__, __LINE__, (ftdmchan), NULL) -#define ftdm_channel_call_answer_ex(ftdmchan, usrmsg) _ftdm_channel_call_answer(__FILE__, __FTDM_FUNC__, __LINE__, (ftdmchan), (usrmsg)) - -/*! \brief Answer call recording the source code point where the it was called (see ftdm_channel_call_answer for an easy to use macro) */ -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg); - -/*! \brief Place an outgoing call in the given channel - * \deprecated This macro is deprecated since leaves the door open to glare issues, use ftdm_call_place instead - */ -#define ftdm_channel_call_place(ftdmchan) _ftdm_channel_call_place(__FILE__, __FTDM_FUNC__, __LINE__, (ftdmchan), NULL) -#define ftdm_channel_call_place_ex(ftdmchan, usrmsg) _ftdm_channel_call_place_ex(__FILE__, __FTDM_FUNC__, __LINE__, (ftdmchan), (usrmsg)) - -/*! \brief Place an outgoing call recording the source code point where it was called (see ftdm_channel_call_place for an easy to use macro) - * \deprecated This function is deprecated since leaves the door open to glare issues, use ftdm_call_place instead - */ -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg); - -/*! \brief Place an outgoing call with the given caller data in a channel according to the hunting scheme provided */ -#define ftdm_call_place(callerdata, hunting) _ftdm_call_place(__FILE__, __FTDM_FUNC__, __LINE__, (callerdata), (hunting), NULL) -#define ftdm_call_place_ex(callerdata, hunting, usrmsg) _ftdm_call_place(__FILE__, __FTDM_FUNC__, __LINE__, (callerdata), (hunting), (usrmsg)) - -/*! \brief Place an outgoing call with the given caller data in a channel according to the hunting scheme provided and records - * the place where it was called. See ftdm_call_place for an easy to use macro - * \return FTDM_SUCCESS if the call attempt was successful - * FTDM_FAIL if there was an unspecified error - * FTDM_EBUSY if the channel was busy - * FTDM_BREAK if glare was detected and you must try again - * \note Even when FTDM_SUCCESS is returned, the call may still fail later on due to glare, in such case FTDM_SIGEVENT_STOP - * will be sent with the hangup cause field set to FTDM_CAUSE_REQUESTED_CHAN_UNAVAIL - * - * \note When this function returns FTDM_SUCCESS, the member .fchan from caller_data will be set to the channel used to place the call - * and .call_id to the generated call id for that call - * - * \note When this function is successful you are guaranteed to receive FTDM_SIGEVENT_DIALING, this event could even be delivered - * before your execution thread returns from this function - */ -FT_DECLARE(ftdm_status_t) _ftdm_call_place(const char *file, const char *func, int line, ftdm_caller_data_t *caller_data, ftdm_hunting_scheme_t *hunting, ftdm_usrmsg_t *usrmsg); - -/*! \brief Indicate a new condition in an incoming call - * - * \note Every indication request will result in FTDM_SIGEVENT_INDICATION_COMPLETED event being delivered with - * the proper status that will inform you if the request was successful or not. The exception is if this - * function returns something different to FTDM_SUCCESS, in which case the request failed right away and no - * further FTDM_SIGEVENT_INDICATION_COMPLETED will be delivered - * Be aware there is no guarantee of whether the completion event will arrive after or before your execution - * thread returns from ftdm_channel_call_indicate. This means you could get FTDM_SIGEVENT_INDICATION_COMPLETED - * even before your execution thread returns from the ftdm_channel_call_indicate() API - * - * \note You cannot send more than one indication at the time. You must wait for the completed event before - * calling this function again (unless the return code was different than FTDM_SUCCESS) - */ -#define ftdm_channel_call_indicate(ftdmchan, indication) _ftdm_channel_call_indicate(__FILE__, __FTDM_FUNC__, __LINE__, (ftdmchan), (indication), NULL) -#define ftdm_channel_call_indicate_ex(ftdmchan, indication, usrmsg) _ftdm_channel_call_indicate(__FILE__, __FTDM_FUNC__, __LINE__, (ftdmchan), (indication), (usrmsg)) - -/*! \brief Indicate a new condition in an incoming call recording the source code point where it was called (see ftdm_channel_call_indicate for an easy to use macro) */ -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication, ftdm_usrmsg_t *usrmsg); - -/*! \brief Hangup the call without cause */ -#define ftdm_channel_call_hangup(ftdmchan) _ftdm_channel_call_hangup(__FILE__, __FTDM_FUNC__, __LINE__, (ftdmchan), NULL) -#define ftdm_channel_call_hangup_ex(ftdmchan, usrmsg) _ftdm_channel_call_hangup(__FILE__, __FTDM_FUNC__, __LINE__, (ftdmchan), (usrmsg)) - -/*! \brief Hangup the call without cause recording the source code point where it was called (see ftdm_channel_call_hangup for an easy to use macro)*/ -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg); - -/*! \brief Hangup the call with cause */ -#define ftdm_channel_call_hangup_with_cause(ftdmchan, cause) _ftdm_channel_call_hangup_with_cause(__FILE__, __FTDM_FUNC__, __LINE__, (ftdmchan), (cause), NULL) -#define ftdm_channel_call_hangup_with_cause_ex(ftdmchan, cause, usrmsg) _ftdm_channel_call_hangup_with_cause(__FILE__, __FTDM_FUNC__, __LINE__, (ftdmchan), (cause), (usrmsg)) - -/*! \brief Hangup the call with cause recording the source code point where it was called (see ftdm_channel_call_hangup_with_cause for an easy to use macro) */ -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup_with_cause(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_call_cause_t, ftdm_usrmsg_t *usrmsg); - -/*! \brief Transfer call. This can also be accomplished by ftdm_channel_call_indicate with FTDM_CHANNEL_INDICATE_TRANSFER, in both - * cases you will get a FTDM_SIGEVENT_INDICATION_COMPLETED when the indication is sent (or an error occurs). - * Just as with ftdm_channel_call_indicate you won't receive FTDM_SIGEVENT_INDICATION_COMPLETED when this function - * returns anything else than FTDM_SUCCESS - * \note Although this API may result in FTDM_SIGEVENT_INDICATION_COMPLETED event being delivered, - * there is no guarantee of whether the event will arrive after or before your execution thread returns - * from ftdm_channel_call_transfer - */ -#define ftdm_channel_call_transfer(ftdmchan, arg) _ftdm_channel_call_transfer(__FILE__, __FTDM_FUNC__, __LINE__, (ftdmchan), (arg), NULL) -#define ftdm_channel_call_transfer_ex(ftdmchan, arg, usrmsg) _ftdm_channel_call_transfer(__FILE__, __FTDM_FUNC__, __LINE__, (ftdmchan), (arg), (usrmsg)) - -/*! \brief Answer call recording the source code point where the it was called (see ftdm_channel_call_tranasfer for an easy to use macro) */ -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_transfer(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, const char* arg, ftdm_usrmsg_t *usrmsg); - -/*! \brief Reset the channel */ -#define ftdm_channel_reset(ftdmchan) _ftdm_channel_reset(__FILE__, __FTDM_FUNC__, __LINE__, (ftdmchan), NULL) -#define ftdm_channel_reset_ex(ftdmchan, usrmsg) _ftdm_channel_reset(__FILE__, __FTDM_FUNC__, __LINE__, (ftdmchan), usrmsg) - -/*! \brief Reset the channel (see _ftdm_channel_reset for an easy to use macro) - * \note if there was a call on this channel, call will be cleared without any notifications to the user - */ -FT_DECLARE(ftdm_status_t) _ftdm_channel_reset(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg); - -/*! \brief Put a call on hold (if supported by the signaling stack) */ -#define ftdm_channel_call_hold(ftdmchan) _ftdm_channel_call_hold(__FILE__, __FTDM_FUNC__, __LINE__, (ftdmchan), NULL) -#define ftdm_channel_call_hold_ex(ftdmchan, usrmsg) _ftdm_channel_call_hold(__FILE__, __FTDM_FUNC__, __LINE__, (ftdmchan), (usrmsg)) - -/*! \brief Put a call on hold recording the source code point where it was called (see ftdm_channel_call_hold for an easy to use macro) */ -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hold(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg); - -/*! \brief Unhold a call */ -#define ftdm_channel_call_unhold(ftdmchan) _ftdm_channel_call_unhold(__FILE__, __FTDM_FUNC__, __LINE__, (ftdmchan), NULL) -#define ftdm_channel_call_unhold_ex(ftdmchan, usrmsg) _ftdm_channel_call_unhold(__FILE__, __FTDM_FUNC__, __LINE__, (ftdmchan), (usrmsg)) - -/*! \brief Unhold a call recording the source code point where it was called (see ftdm_channel_call_unhold for an easy to use macro) */ -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_unhold(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg); - -/*! \brief Check if the call is answered already */ -FT_DECLARE(ftdm_bool_t) ftdm_channel_call_check_answered(const ftdm_channel_t *ftdmchan); - -/*! \brief Check if the call is busy */ -FT_DECLARE(ftdm_bool_t) ftdm_channel_call_check_busy(const ftdm_channel_t *ftdmchan); - -/*! \brief Check if the call is hangup */ -FT_DECLARE(ftdm_bool_t) ftdm_channel_call_check_hangup(const ftdm_channel_t *ftdmchan); - -/*! \brief Check if the call is done (final state for a call, just after hangup) */ -FT_DECLARE(ftdm_bool_t) ftdm_channel_call_check_done(const ftdm_channel_t *ftdmchan); - -/*! \brief Check if the call is in hold */ -FT_DECLARE(ftdm_bool_t) ftdm_channel_call_check_hold(const ftdm_channel_t *ftdmchan); - -/*! \brief Set channel signaling status (ie: put specific circuit down) only if supported by the signaling */ -FT_DECLARE(ftdm_status_t) ftdm_channel_set_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status); - -/*! \brief Get channel signaling status (ie: whether protocol layer is up or down) */ -FT_DECLARE(ftdm_status_t) ftdm_channel_get_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t *status); - -/*! \brief Set span signaling status (ie: put the whole span protocol layer down) only if supported by the signaling */ -FT_DECLARE(ftdm_status_t) ftdm_span_set_sig_status(ftdm_span_t *span, ftdm_signaling_status_t status); - -/*! \brief Get span signaling status (ie: whether protocol layer is up or down) */ -FT_DECLARE(ftdm_status_t) ftdm_span_get_sig_status(ftdm_span_t *span, ftdm_signaling_status_t *status); - - -/*! - * \brief Set user private data in the channel - * - * \param ftdmchan The channel where the private data will be stored - * \param pvt The private pointer to store - * - */ -FT_DECLARE(void) ftdm_channel_set_private(ftdm_channel_t *ftdmchan, void *pvt); - -/*! - * \brief Get user private data in the channel - * - * \param ftdmchan The channel to retrieve the private data - * \retval The private data (if any or NULL if no data has been stored) - * - */ -FT_DECLARE(void *) ftdm_channel_get_private(const ftdm_channel_t *ftdmchan); - -/*! - * \brief Remove the given token from the channel - * - * \param ftdmchan The channel where the token is - * \param token The token string. If NULL, all tokens in the channel are cleared - * - * \retval FTDM_SUCCESS success - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_channel_clear_token(ftdm_channel_t *ftdmchan, const char *token); - -/*! - * \brief Replace the given token with the new token - * - * \param ftdmchan The channel where the token is - * \param old_token The token to replace - * \param new_token The token to put in place - */ -FT_DECLARE(void) ftdm_channel_replace_token(ftdm_channel_t *ftdmchan, const char *old_token, const char *new_token); - -/*! - * \brief Add a new token to the channel - * - * \param ftdmchan The channel where the token will be added - * \param token The token string to add - * \param end if 0, the token will be added at the beginning of the token list, to the end otherwise - * - * \retval FTDM_SUCCESS success - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_channel_add_token(ftdm_channel_t *ftdmchan, char *token, int end); - -/*! - * \brief Get the requested token - * - * \param ftdmchan The channel where the token is - * \param tokenid The id of the token - * - * \retval The token character string - * \retval NULL token not found - */ -FT_DECLARE(const char *) ftdm_channel_get_token(const ftdm_channel_t *ftdmchan, uint32_t tokenid); - -/*! - * \brief Get the token count - * - * \param ftdmchan The channel to get the token count from - * - * \retval The token count - */ -FT_DECLARE(uint32_t) ftdm_channel_get_token_count(const ftdm_channel_t *ftdmchan); - -/*! - * \brief Get the I/O read/write interval - * - * \param ftdmchan The channel to get the interval from - * - * \retval The interval in milliseconds - */ -FT_DECLARE(uint32_t) ftdm_channel_get_io_interval(const ftdm_channel_t *ftdmchan); - -/*! - * \brief Get the I/O read/write packet length per interval - * - * \param ftdmchan The channel to get the packet length from - * - * \retval The packet length interval in bytes - */ -FT_DECLARE(uint32_t) ftdm_channel_get_io_packet_len(const ftdm_channel_t *ftdmchan); - -/*! - * \brief Get the I/O read/write codec - * - * \param ftdmchan The channel to get the codec from - * - * \retval The codec type - */ -FT_DECLARE(ftdm_codec_t) ftdm_channel_get_codec(const ftdm_channel_t *ftdmchan); - -/*! - * \brief Get the last error string for the channel - * - * \deprecated This API will disappear in the future and not every - * FreeTDM API set the last error value - * - * \param ftdmchan The channel to get the error from - * - * \retval The error string (not thread-safe, the string is per channel, not per thread) - */ -FT_DECLARE(const char *) ftdm_channel_get_last_error(const ftdm_channel_t *ftdmchan); - -/*! - * \brief Get the current alarm bitmask for the channel - * - * \param ftdmchan The channel to get the alarm bitmask from - * \param alarmbits The alarm bitmask pointer to store the current alarms (you are responsible for allocation/deallocation) - * - * \retval FTDM_SUCCESS success - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_channel_get_alarms(ftdm_channel_t *ftdmchan, ftdm_alarm_flag_t *alarmbits); - -/*! - * \brief Get the channel type - * - * \param ftdmchan The channel to get the type from - * - * \retval channel type (FXO, FXS, B-channel, D-channel, etc) - */ -FT_DECLARE(ftdm_chan_type_t) ftdm_channel_get_type(const ftdm_channel_t *ftdmchan); - -/*! - * \brief Dequeue DTMF from the given channel - * \note To transmit DTMF use ftdm_channel_command with command FTDM_COMMAND_SEND_DTMF - * - * \param ftdmchan The channel to dequeue DTMF from - * \param dtmf DTMF buffer to store the dtmf (you are responsible for its allocation and deallocation) - * \param len The size of the provided DTMF buffer - * - * \retval The size of the dequeued DTMF (it might be zero if there is no DTMF in the queue) - */ -FT_DECLARE(ftdm_size_t) ftdm_channel_dequeue_dtmf(ftdm_channel_t *ftdmchan, char *dtmf, ftdm_size_t len); - -/*! - * \brief Flush the DTMF queue - * - * \param ftdmchan The channel to flush the dtmf queue of - */ -FT_DECLARE(void) ftdm_channel_flush_dtmf(ftdm_channel_t *ftdmchan); - -/*! - * \brief Wait for an event in the span - * - * \param span The span to wait events for - * \param ms Milliseconds timeout - * \param poll_events Array of events to poll for, for each channel on the span - * - * \retval FTDM_SUCCESS success (at least one event available) - * \retval FTDM_TIMEOUT Timed out waiting for events - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_span_poll_event(ftdm_span_t *span, uint32_t ms, short *poll_events); - -/*! - * \brief Find a span by its id - * - * \param id The span id - * \param span Pointer to store the span if found - * - * \retval FTDM_SUCCESS success (span is valid) - * \retval FTDM_FAIL failure (span is not valid) - */ -FT_DECLARE(ftdm_status_t) ftdm_span_find(uint32_t id, ftdm_span_t **span); - -/*! - * \brief Get the last error string for the given span - * - * \deprecated This API will disappear in the future and not every - * FreeTDM API set the last error value - * - * \param span The span to get the last error from - * - * \retval character string for the last error - */ -FT_DECLARE(const char *) ftdm_span_get_last_error(const ftdm_span_t *span); - -/*! - * \brief Create a new span (not needed if you are using freetdm.conf) - * - * \param iotype The I/O interface type this span will use. - * This depends on the available I/O modules - * ftmod_wanpipe = "wanpipe" (Sangoma) - * ftmod_zt = "zt" (DAHDI or Zaptel) - * ftmod_pika "pika" (this one is most likely broken) - * \param name Name for the span - * \param span Pointer to store the create span - * - * \retval FTDM_SUCCESS success (the span was created) - * \retval FTDM_FAIL failure (span was not created) - */ -FT_DECLARE(ftdm_status_t) ftdm_span_create(const char *iotype, const char *name, ftdm_span_t **span); - -/*! - * \brief Add a new channel to a span - * - * \param span Where to add the new channel - * \param sockfd The socket device associated to the channel (ie: sangoma device, dahdi device etc) - * \param type Channel type - * \param chan Pointer to store the newly allocated channel - * - * \retval FTDM_SUCCESS success (the channel was created) - * \retval FTDM_FAIL failure (span was not created) - */ -FT_DECLARE(ftdm_status_t) ftdm_span_add_channel(ftdm_span_t *span, ftdm_socket_t sockfd, ftdm_chan_type_t type, ftdm_channel_t **chan); - -/*! \brief Add the channel to a hunt group */ -FT_DECLARE(ftdm_status_t) ftdm_channel_add_to_group(const char* name, ftdm_channel_t* ftdmchan); - -/*! \brief Remove the channel from a hunt group */ -FT_DECLARE(ftdm_status_t) ftdm_channel_remove_from_group(ftdm_group_t* group, ftdm_channel_t* ftdmchan); - -/*! - * \brief Retrieves an event from the span - * - * \note - * This function is non-reentrant and not thread-safe. - * The event returned may be modified if the function is called again - * from a different thread or even the same. It is recommended to - * handle events from the same span in a single thread. - * - * \param ftdmchan The channel to retrieve the event from - * \param event Pointer to store the pointer to the event - * - * \retval FTDM_SUCCESS success (at least one event available) - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_channel_read_event(ftdm_channel_t *ftdmchan, ftdm_event_t **event); - -/*! \brief Find a hunt group by id */ -FT_DECLARE(ftdm_status_t) ftdm_group_find(uint32_t id, ftdm_group_t **group); - -/*! \brief Find a hunt group by name */ -FT_DECLARE(ftdm_status_t) ftdm_group_find_by_name(const char *name, ftdm_group_t **group); - -/*! \brief Create a group with the given name */ -FT_DECLARE(ftdm_status_t) ftdm_group_create(ftdm_group_t **group, const char *name); - -/*! \brief Get the number of channels in use on a span */ -FT_DECLARE(ftdm_status_t) ftdm_span_channel_use_count(ftdm_span_t *span, uint32_t *count); - -/*! \brief Get the number of channels in use on a group */ -FT_DECLARE(ftdm_status_t) ftdm_group_channel_use_count(ftdm_group_t *group, uint32_t *count); - -/*! \brief Get the id of a group */ -FT_DECLARE(uint32_t) ftdm_group_get_id(const ftdm_group_t *group); - -/*! - * \brief Open a channel specifying the span id and chan id (required before placing a call on the channel) - * - * \warning Try using ftdm_call_place instead if you plan to place a call after opening the channel - * - * \note You must call ftdm_channel_close() or ftdm_channel_call_hangup() to release the channel afterwards - * Only use ftdm_channel_close if there is no call (incoming or outgoing) in the channel - * - * \param span_id The span id the channel belongs to - * \param chan_id Logical channel id of the channel you want to open - * \param ftdmchan Pointer to store the channel once is open - * - * \retval FTDM_SUCCESS success (the channel was found and is available) - * \retval FTDM_FAIL failure (channel was not found or not available) - */ -FT_DECLARE(ftdm_status_t) ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan); - -/*! - * \brief Open a channel specifying the span id and physical chan id (required before placing a call on the channel) - * - * \warning Try using ftdm_call_place instead if you plan to place a call after opening the channel - * - * \note You must call ftdm_channel_close() or ftdm_channel_call_hangup() to release the channel afterwards - * Only use ftdm_channel_close if there is no call (incoming or outgoing) in the channel - * - * \param span_id The span id the channel belongs to - * \param chan_id Physical channel id of the channel you want to open - * \param ftdmchan Pointer to store the channel once is open - * - * \retval FTDM_SUCCESS success (the channel was found and is available) - * \retval FTDM_FAIL failure (channel was not found or not available) - */ -FT_DECLARE(ftdm_status_t) ftdm_channel_open_ph(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan); - -/*! - * \brief Hunts and opens a channel specifying the span id only - * - * \warning Try using ftdm_call_place instead if you plan to place a call after opening the channel - * - * \note You must call ftdm_channel_close() or ftdm_channel_call_hangup() to release the channel afterwards - * Only use ftdm_channel_close if there is no call (incoming or outgoing) in the channel - * - * \param span_id The span id to hunt for a channel - * \param direction The hunting direction - * \param caller_data The calling party information - * \param ftdmchan The channel pointer to store the available channel - * - * \retval FTDM_SUCCESS success (a suitable channel was found available) - * \retval FTDM_FAIL failure (no suitable channel was found available) - */ -FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_hunt_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan); - -/*! - * \brief Hunts and opens a channel specifying group id - * - * \warning Try using ftdm_call_place instead if you plan to place a call after opening the channel - * - * \note You must call ftdm_channel_close() or ftdm_channel_call_hangup() to release the channel afterwards - * Only use ftdm_channel_close if there is no call (incoming or outgoing) in the channel - * - * \param group_id The group id to hunt for a channel - * \param direction The hunting direction - * \param caller_data The calling party information - * \param ftdmchan The channel pointer to store the available channel - * - * \retval FTDM_SUCCESS success (a suitable channel was found available) - * \retval FTDM_FAIL failure (no suitable channel was found available) - */ -FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_group(uint32_t group_id, ftdm_hunt_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan); - -/*! - * \brief Close a previously open channel - * - * \warning FreeTDM is more and more a signaling API rather than just a plane IO API, unless you are using - * FreeTDM as a pure IO API without its signaling modules, you should not use this function - * - * \note If you placed a call in this channel use ftdm_channel_call_hangup(), you MUST NOT call this function, - * the signaling stack will close the channel when the call is done. - * - * \param ftdmchan pointer to the channel to close - * - * \retval FTDM_SUCCESS success (a suitable channel was found available) - * \retval FTDM_FAIL failure (no suitable channel was found available) - */ -FT_DECLARE(ftdm_status_t) ftdm_channel_close(ftdm_channel_t **ftdmchan); - -/*! - * \brief Execute a command in a channel (same semantics as the ioctl() unix system call) - * - * \param ftdmchan The channel to execute the command - * \param command The command to execute - * \param arg The argument for the command - * - * \retval FTDM_SUCCESS success (a suitable channel was found available) - * \retval FTDM_FAIL failure (no suitable channel was found available) - */ -FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_command_t command, void *arg); - -/*! - * \brief Wait for I/O events in a channel - * - * \param ftdmchan The channel to wait I/O for - * \param flags The wait I/O flags - * \param timeout The timeout in milliseconds - * - * \retval FTDM_SUCCESS success (a suitable channel was found available) - * \retval FTDM_FAIL failure (no suitable channel was found available) - */ -FT_DECLARE(ftdm_status_t) ftdm_channel_wait(ftdm_channel_t *ftdmchan, ftdm_wait_flag_t *flags, int32_t timeout); - -/*! - * \brief Read data from a channel - * - * \param ftdmchan The channel to read data from - * \param data The pointer to the buffer to store the read data - * \param datalen The size in bytes of the provided buffer - * - * \retval FTDM_SUCCESS success (a suitable channel was found available) - * \retval FTDM_FAIL failure (no suitable channel was found available) - */ -FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen); - -/*! - * \brief Write data to a channel - * - * \note The difference between data and datasize is subtle but important. - * - * datalen is a pointer to the size of the actual data that you want to write. This pointer - * will be updated with the number of bytes actually written. - * - * datasize on the other hand is the size of the entire buffer provided in data, whether - * all of that buffer is in use or not is a different matter. The difference becomes - * important only if you are using FreeTDM doing transcoding, for example, providing - * a ulaw frame of 160 bytes but where the I/O device accepts input in signed linear, - * the data to write will be 320 bytes, therefore datasize is expected to be at least - * 320 where datalen would be just 160. - * - * \param ftdmchan The channel to write data to - * \param data The pointer to the buffer to write - * \param datasize The maximum number of bytes in data that can be used (in case transcoding is necessary) - * \param datalen The size of the actual data - * - * \retval FTDM_SUCCESS success (a suitable channel was found available) - * \retval FTDM_FAIL failure (no suitable channel was found available) - */ -FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t datasize, ftdm_size_t *datalen); - -/*! \brief Get a custom variable from the sigmsg - * \note The variable pointer returned is only valid while the before the event is processed and it'll be destroyed once the event is processed. */ -FT_DECLARE(const char *) ftdm_sigmsg_get_var(ftdm_sigmsg_t *sigmsg, const char *var_name); - -/*! \brief Get an iterator to iterate over the sigmsg variables - * \param sigmsg The message structure containing the variables - * \param iter Optional iterator. You can reuse an old iterator (not previously freed) to avoid the extra allocation of a new iterator. - * \note The iterator pointer returned is only valid while the channel is open and it'll be destroyed when the channel is closed. - * This iterator is completely non-thread safe, if you are adding variables or removing variables while iterating - * results are unpredictable - */ -FT_DECLARE(ftdm_iterator_t *) ftdm_sigmsg_get_var_iterator(const ftdm_sigmsg_t *sigmsg, ftdm_iterator_t *iter); - -/*! \brief Get raw data from sigmsg - * \param sigmsg The message structure containing the variables - * \param data data will point to available data pointer if available - * \param datalen datalen will be set to length of data available - * \retval FTDM_SUCCESS data is available - * \retval FTDM_FAIL no data available - * \note data is only valid within the duration of the callback, to receive a data pointer that does not get - * \note destroyed when callback returns, see ftdm_sigmsg_get_raw_data_detached - */ -FT_DECLARE(ftdm_status_t) ftdm_sigmsg_get_raw_data(ftdm_sigmsg_t *sigmsg, void **data, ftdm_size_t *datalen); - -/*! \brief Get raw data from event - * \param sigmsg The message structure containing the variables - * \param data data will point to available data pointer if available - * \param datalen datalen will be set to length of data available - * \retval FTDM_SUCCESS data is available - * \retval FTDM_FAIL no data available - * \note Once this function returns, User owns data, and is responsible to free data using ftdm_safe_free(); - */ -FT_DECLARE(ftdm_status_t) ftdm_sigmsg_get_raw_data_detached(ftdm_sigmsg_t *sigmsg, void **data, ftdm_size_t *datalen); - -/*! \brief Add a custom variable to the user message - * \note This variables may be used by signaling modules to override signaling parameters - * \todo Document which signaling variables are available - * */ -FT_DECLARE(ftdm_status_t) ftdm_usrmsg_add_var(ftdm_usrmsg_t *usrmsg, const char *var_name, const char *value); - -/*! \brief Attach raw data to usrmsg - * \param usrmsg The message structure containing the variables - * \param data pointer to data - * \param datalen datalen length of data - * \retval FTDM_SUCCESS success, data was successfully saved - * \retval FTDM_FAIL failed, event already had data attached to it. - * \note data must have been allocated using ftdm_calloc, FreeTDM will free data once the usrmsg is processed. - */ -FT_DECLARE(ftdm_status_t) ftdm_usrmsg_set_raw_data(ftdm_usrmsg_t *usrmsg, void *data, ftdm_size_t datalen); - -/*! \brief Get iterator current value (depends on the iterator type) - * \note Channel iterators return a pointer to ftdm_channel_t - * Span iterators return a pointer to ftdm_span_t - * Variable iterators return a pointer to the variable name (not the variable value) - */ -FT_DECLARE(void *) ftdm_iterator_current(ftdm_iterator_t *iter); - -/*! \brief Get variable name and value for the current iterator position */ -FT_DECLARE(ftdm_status_t) ftdm_get_current_var(ftdm_iterator_t *iter, const char **var_name, const char **var_val); - -/*! \brief Advance iterator */ -FT_DECLARE(ftdm_iterator_t *) ftdm_iterator_next(ftdm_iterator_t *iter); - -/*! \brief Free iterator - * \note You must free an iterator after using it unless you plan to reuse it - */ -FT_DECLARE(ftdm_status_t) ftdm_iterator_free(ftdm_iterator_t *iter); - -/*! \brief Get the span pointer associated to the channel */ -FT_DECLARE(ftdm_span_t *) ftdm_channel_get_span(const ftdm_channel_t *ftdmchan); - -/*! \brief Get the span pointer associated to the channel */ -FT_DECLARE(uint32_t) ftdm_channel_get_span_id(const ftdm_channel_t *ftdmchan); - -/*! \brief Get the physical span id associated to the channel */ -FT_DECLARE(uint32_t) ftdm_channel_get_ph_span_id(const ftdm_channel_t *ftdmchan); - -/*! \brief Get the span name associated to the channel */ -FT_DECLARE(const char *) ftdm_channel_get_span_name(const ftdm_channel_t *ftdmchan); - -/*! \brief Get the id associated to the channel */ -FT_DECLARE(uint32_t) ftdm_channel_get_id(const ftdm_channel_t *ftdmchan); - -/*! \brief Get the name associated to the channel */ -FT_DECLARE(const char *) ftdm_channel_get_name(const ftdm_channel_t *ftdmchan); - -/*! \brief Get the number associated to the channel */ -FT_DECLARE(const char *) ftdm_channel_get_number(const ftdm_channel_t *ftdmchan); - -/*! \brief Get the number physical id associated to the channel */ -FT_DECLARE(uint32_t) ftdm_channel_get_ph_id(const ftdm_channel_t *ftdmchan); - -/*! - * \brief Configure span with a signaling type - * - * \deprecated use ftdm_configure_span_signaling instead - * - * \note This function does the same as ftdm_configure_span_signaling - * - * \param span The span to configure - * \param type The signaling type ("boost", "isdn" and others, this depends on the available signaling modules) - * \param sig_cb The callback that the signaling stack will use to notify about events - * \param ... variable argument list with "var", value sequence, the variable and values are signaling type dependant - * the last argument must be FTDM_TAG_END - * - * \retval FTDM_SUCCESS success - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_configure_span(ftdm_span_t *span, const char *type, fio_signal_cb_t sig_cb, ...); -#define FTDM_TAG_END NULL - - -/*! - * \brief Configure span with a signaling type - * - * \param span The span to configure - * \param type The signaling type ("boost", "isdn" and others, this depends on the available signaling modules) - * \param sig_cb The callback that the signaling stack will use to notify about events - * \param parameters The array if signaling-specific parameters (the last member of the array MUST have its var member set to NULL, ie: .var = NULL) - * - * \retval FTDM_SUCCESS success - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_configure_span_signaling(ftdm_span_t *span, const char *type, fio_signal_cb_t sig_cb, ftdm_conf_parameter_t *parameters); - -/*! - * \brief Register callback to listen for incoming events - * \note This function should only be used when there is no signalling module - * \param span The span to register to - * \param sig_cb The callback that the signaling stack will use to notify about events - * - * \retval FTDM_SUCCESS success - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_span_register_signal_cb(ftdm_span_t *span, fio_signal_cb_t sig_cb); - -/*! - * \brief Start the span signaling (must call ftdm_configure_span_signaling first) - * - * \note Even before this function returns you may receive signaling events! - * Never block in the signaling callback since it might be called in a thread - * that handles more than 1 call and therefore you would be blocking all the - * calls handled by that thread! - * - * \param span The span to start - * - * \retval FTDM_SUCCESS success - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_span_start(ftdm_span_t *span); - -/*! - * \brief Stop the span signaling (must call ftdm_span_start first) - * \note certain signalings (boost signaling) does not support granular span start/stop - * so it is recommended to always configure all spans and then starting them all and finally - * stop them all (or call ftdm_global_destroy which takes care of stopping and destroying the spans at once). - * - * \param span The span to stop - * - * \retval FTDM_SUCCESS success - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_span_stop(ftdm_span_t *span); - -/*! - * \brief Register a custom I/O interface with the FreeTDM core - * - * \param io_interface the Interface to register - * - * \retval FTDM_SUCCESS success - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_global_add_io_interface(ftdm_io_interface_t *io_interface); - -/** - * Get I/O interface by name - * - * \param iotype Name of interface - * \param autoload Try to load missing plugins - * \retval I/O interface handle on success - * \retval NULL on failure - */ -FT_DECLARE(ftdm_io_interface_t *) ftdm_global_get_io_interface(const char *iotype, ftdm_bool_t autoload); - -/*! \brief Find a span by name */ -FT_DECLARE(ftdm_status_t) ftdm_span_find_by_name(const char *name, ftdm_span_t **span); - -/*! \brief Get the span id */ -FT_DECLARE(uint32_t) ftdm_span_get_id(const ftdm_span_t *span); - -/*! \brief Get the span name */ -FT_DECLARE(const char *) ftdm_span_get_name(const ftdm_span_t *span); - -/*! \brief Get iterator for the span channels - * \param span The span containing the channels - * \param iter Optional iterator. You can reuse an old iterator (not previously freed) to avoid the extra allocation of a new iterator. - */ -FT_DECLARE(ftdm_iterator_t *) ftdm_span_get_chan_iterator(const ftdm_span_t *span, ftdm_iterator_t *iter); - -/*! \brief Get iterator for spans - * \param iter Optional iterator. You can reuse an old iterator (not previously freed) to avoid the extra allocation of a new iterator. - */ -FT_DECLARE(ftdm_iterator_t *) ftdm_get_span_iterator(ftdm_iterator_t *iter); - -/*! - * \brief Execute a text command. The text command output will be returned and must be free'd - * - * \param cmd The command to execute - * - * \retval FTDM_SUCCESS success - * \retval FTDM_FAIL failure - */ -FT_DECLARE(char *) ftdm_api_execute(const char *cmd); - -/*! - * \brief Create a configuration node - * - * \param name The name of the configuration node - * \param node The node pointer to store the new node - * \param parent The parent node if any, or NULL if no parent - * - * \return FTDM_SUCCESS success - * \return FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_conf_node_create(const char *name, ftdm_conf_node_t **node, ftdm_conf_node_t *parent); - -/*! - * \brief Adds a new parameter to the specified configuration node - * - * \param node The configuration node to add the param-val pair to - * \param param The parameter name - * \param val The parameter value - * - * \return FTDM_SUCCESS success - * \return FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_conf_node_add_param(ftdm_conf_node_t *node, const char *param, const char *val); - -/*! - * \brief Destroy the memory allocated for a configuration node (and all of its descendance) - * - * \param node The node to destroy - * - * \return FTDM_SUCCESS success - * \return FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_conf_node_destroy(ftdm_conf_node_t *node); - -/*! - * \brief Create and configure channels in the given span - * - * \param span The span container - * \param str The channel range null terminated string. "1-10", "24" etc - * \param chan_config The basic channel configuration for each channel within the range - * \param configured Pointer where the number of channels configured will be stored - * - * \return FTDM_SUCCESS success - * \return FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_configure_span_channels(ftdm_span_t *span, const char *str, ftdm_channel_config_t *chan_config, unsigned *configured); - -/*! - * \brief Set the trunk type for a span - * This must be called before configuring any channels within the span - * - * \param span The span - * \param type The trunk type - * - */ -FT_DECLARE(void) ftdm_span_set_trunk_type(ftdm_span_t *span, ftdm_trunk_type_t type); - -/*! - * \brief Get the trunk type for a span - * - * \param span The span - * - * \return The span trunk type - */ -FT_DECLARE(ftdm_trunk_type_t) ftdm_span_get_trunk_type(const ftdm_span_t *span); - -/*! \brief For display debugging purposes you can display this string which describes the trunk type of a span */ -FT_DECLARE(const char *) ftdm_span_get_trunk_type_str(const ftdm_span_t *span); - -/*! - * Set the trunk mode for a span - * \note This must be called before configuring any channels within the span! - * \param[in] span The span - * \param[in] type The trunk mode - */ -FT_DECLARE(void) ftdm_span_set_trunk_mode(ftdm_span_t *span, ftdm_trunk_mode_t mode); - -/*! - * Get the trunk mode for a span - * \param[in] span The span - * \return Span trunk mode - */ -FT_DECLARE(ftdm_trunk_mode_t) ftdm_span_get_trunk_mode(const ftdm_span_t *span); - -/*! - * Get the trunk mode of a span in textual form - * \param[in] span The span - * \return Span mode name as a string - */ -FT_DECLARE(const char *) ftdm_span_get_trunk_mode_str(const ftdm_span_t *span); - -/*! - * \brief Return the channel identified by the provided logical id - * - * \param span The span where the channel belongs - * \param chanid The logical channel id within the span - * - * \return The channel pointer if found, NULL otherwise - */ -FT_DECLARE(ftdm_channel_t *) ftdm_span_get_channel(const ftdm_span_t *span, uint32_t chanid); - -/*! - * \brief Return the channel identified by the provided physical id - * - * \param span The span where the channel belongs - * \param chanid The physical channel id within the span - * - * \return The channel pointer if found, NULL otherwise - */ -FT_DECLARE(ftdm_channel_t *) ftdm_span_get_channel_ph(const ftdm_span_t *span, uint32_t chanid); - -/*! \brief Return the channel count number for the given span */ -FT_DECLARE(uint32_t) ftdm_span_get_chan_count(const ftdm_span_t *span); - -/*! \brief Set the caller data for a channel. Be sure to call this before ftdm_channel_call_place() */ -FT_DECLARE(ftdm_status_t) ftdm_channel_set_caller_data(ftdm_channel_t *ftdmchan, ftdm_caller_data_t *caller_data); - -/*! \brief Get the caller data for a channel, typically you need this when receiving FTDM_SIGEVENT_START */ -FT_DECLARE(ftdm_caller_data_t *) ftdm_channel_get_caller_data(ftdm_channel_t *channel); - -/*! \brief Get current state of a channel */ -FT_DECLARE(int) ftdm_channel_get_state(const ftdm_channel_t *ftdmchan); - -/*! \brief Get last state of a channel */ -FT_DECLARE(int) ftdm_channel_get_last_state(const ftdm_channel_t *ftdmchan); - -/*! \brief For display debugging purposes you can display this string which describes the current channel internal state */ -FT_DECLARE(const char *) ftdm_channel_get_state_str(const ftdm_channel_t *channel); - -/*! \brief For display debugging purposes you can display this string which describes the last channel internal state */ -FT_DECLARE(const char *) ftdm_channel_get_last_state_str(const ftdm_channel_t *channel); - -/*! \brief For display debugging purposes you can display this string which describes the history of the channel - * \param channel The channel to get the history from - * \return History string for the channel. You must free the string with ftdm_free - */ -FT_DECLARE(char *) ftdm_channel_get_history_str(const ftdm_channel_t *channel); - -/*! \brief Enable/disable blocking mode in the channels for this span */ -FT_DECLARE(ftdm_status_t) ftdm_span_set_blocking_mode(const ftdm_span_t *span, ftdm_bool_t enabled); - -/*! \brief Initialize the library */ -FT_DECLARE(ftdm_status_t) ftdm_global_init(void); - -/*! \brief Create spans and channels reading the freetdm.conf file */ -FT_DECLARE(ftdm_status_t) ftdm_global_configuration(void); - -/*! \brief Shutdown the library */ -FT_DECLARE(ftdm_status_t) ftdm_global_destroy(void); - -/*! \brief Set memory handler for the library */ -FT_DECLARE(ftdm_status_t) ftdm_global_set_memory_handler(ftdm_memory_handler_t *handler); - -/*! \brief Set the crash policy for the library */ -FT_DECLARE(void) ftdm_global_set_crash_policy(ftdm_crash_policy_t policy); - -/*! \brief Set the logger handler for the library */ -FT_DECLARE(void) ftdm_global_set_logger(ftdm_logger_t logger); - -/*! \brief Set the default logger level */ -FT_DECLARE(void) ftdm_global_set_default_logger(int level); - -/*! \brief Set the directory to look for modules */ -FT_DECLARE(void) ftdm_global_set_mod_directory(const char *path); - -/*! \brief Set the directory to look for configs */ -FT_DECLARE(void) ftdm_global_set_config_directory(const char *path); - -/*! \brief Check if the FTDM library is initialized and running */ -FT_DECLARE(ftdm_bool_t) ftdm_running(void); - -/** - * Generate a stack trace and invoke a callback function for each entry - * \param[in] callback Callback function, that is invoked for each stack symbol - * \param[in] priv (User-)Private data passed to the callback - * \retval - * FTDM_SUCCESS On success - * FTDM_NOTIMPL Backtraces are not available - * FTDM_EINVAL Invalid arguments (callback was NULL) - */ -FT_DECLARE(ftdm_status_t) ftdm_backtrace_walk(void (* callback)(const int tid, const void *addr, const char *symbol, void *priv), void *priv); - -/** - * Convenience function to print a backtrace for a span. - * \note The backtrace is generated with FTDM_LOG_DEBUG log level. - * \param[in] span Span object - * \retval - * FTDM_SUCCESS On success - * FTDM_NOTIMPL Backtraces are not available - * FTDM_EINVAL Invalid arguments (e.g. span was NULL) - */ -FT_DECLARE(ftdm_status_t) ftdm_backtrace_span(ftdm_span_t *span); - -/** - * Convenience function to print a backtrace for a channel. - * \note The backtrace is generated with FTDM_LOG_DEBUG log level. - * \param[in] chan Channel object - * \retval - * FTDM_SUCCESS On success - * FTDM_NOTIMPL Backtraces are not available - * FTDM_EINVAL Invalid arguments (e.g. chan was NULL) - */ -FT_DECLARE(ftdm_status_t) ftdm_backtrace_chan(ftdm_channel_t *chan); - - -FT_DECLARE_DATA extern ftdm_logger_t ftdm_log; - -/*! \brief Basic transcoding function prototype */ -#define FIO_CODEC_ARGS (void *data, ftdm_size_t max, ftdm_size_t *datalen) -#define FIO_CODEC_FUNCTION(name) FT_DECLARE_NONSTD(ftdm_status_t) name FIO_CODEC_ARGS -typedef ftdm_status_t (*fio_codec_t) FIO_CODEC_ARGS ; - -/*! \brief Basic transcoding functions */ -FIO_CODEC_FUNCTION(fio_slin2ulaw); -FIO_CODEC_FUNCTION(fio_ulaw2slin); -FIO_CODEC_FUNCTION(fio_slin2alaw); -FIO_CODEC_FUNCTION(fio_alaw2slin); -FIO_CODEC_FUNCTION(fio_ulaw2alaw); -FIO_CODEC_FUNCTION(fio_alaw2ulaw); - -#define FTDM_PRE __FILE__, __func__, __LINE__ -#define FTDM_LOG_LEVEL_DEBUG 7 -#define FTDM_LOG_LEVEL_INFO 6 -#define FTDM_LOG_LEVEL_NOTICE 5 -#define FTDM_LOG_LEVEL_WARNING 4 -#define FTDM_LOG_LEVEL_ERROR 3 -#define FTDM_LOG_LEVEL_CRIT 2 -#define FTDM_LOG_LEVEL_ALERT 1 -#define FTDM_LOG_LEVEL_EMERG 0 - -/*! \brief Log levels */ -#define FTDM_LOG_DEBUG FTDM_PRE, FTDM_LOG_LEVEL_DEBUG -#define FTDM_LOG_INFO FTDM_PRE, FTDM_LOG_LEVEL_INFO -#define FTDM_LOG_NOTICE FTDM_PRE, FTDM_LOG_LEVEL_NOTICE -#define FTDM_LOG_WARNING FTDM_PRE, FTDM_LOG_LEVEL_WARNING -#define FTDM_LOG_ERROR FTDM_PRE, FTDM_LOG_LEVEL_ERROR -#define FTDM_LOG_CRIT FTDM_PRE, FTDM_LOG_LEVEL_CRIT -#define FTDM_LOG_ALERT FTDM_PRE, FTDM_LOG_LEVEL_ALERT -#define FTDM_LOG_EMERG FTDM_PRE, FTDM_LOG_LEVEL_EMERG - -#ifdef __cplusplus -} /* extern C */ -#endif - -#endif - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/include/ftdm_call_utils.h b/libs/freetdm/src/include/ftdm_call_utils.h deleted file mode 100644 index 975e73e729..0000000000 --- a/libs/freetdm/src/include/ftdm_call_utils.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * David Yat Sin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Contributors: - * - * Moises Silva - * Ricardo Barroetaveña - * - */ - -#ifndef __FTDM_CALL_UTILS_H__ -#define __FTDM_CALL_UTILS_H__ - -/*! - * \brief Set the Numbering Plan Identification from a string - * - * \param npi_string string value - * \param target the target to set value to - * - * \retval FTDM_SUCCESS success - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_set_npi(const char *npi_string, uint8_t *target); - - -/*! - * \brief Set the Type of number from a string - * - * \param ton_string string value - * \param target the target to set value to - * - * \retval FTDM_SUCCESS success - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_set_ton(const char *ton_string, uint8_t *target); - -/*! - * \brief Set the Bearer Capability from a string - * - * \param bc_string string value - * \param target the target to set value to - * - * \retval FTDM_SUCCESS success - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_set_bearer_capability(const char *bc_string, uint8_t *target); - -/*! - * \brief Set the Bearer Capability - Layer 1 from a string - * - * \param bc_string string value - * \param target the target to set value to - * - * \retval FTDM_SUCCESS success - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_set_bearer_layer1(const char *bc_string, uint8_t *target); - -/*! - * \brief Set the Screening Ind from a string - * - * \param screen_string string value - * \param target the target to set value to - * - * \retval FTDM_SUCCESS success - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_set_screening_ind(const char *string, uint8_t *target); - - -/*! - * \brief Set the Presentation Ind from an enum - * - * \param screen_string string value - * \param target the target to set value to - * - * \retval FTDM_SUCCESS success - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_set_presentation_ind(const char *string, uint8_t *target); - - -/*! - * \brief Checks whether a string contains only numbers - * - * \param number string value - * - * \retval FTDM_SUCCESS success - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_is_number(const char *number); - -/*! - * \brief Set the Calling Party Category from an enum - * - * \param cpc_string string value - * \param target the target to set value to - * - * \retval FTDM_SUCCESS success - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_set_calling_party_category(const char *string, uint8_t *target); - -/*! - * \brief URL encode a buffer - * - * \param url buffer to convert - * \param buf target to save converted string to - * \param len size of buffer - * - * \retval pointer to converted string - */ -FT_DECLARE(char *) ftdm_url_encode(const char *url, char *buf, ftdm_size_t len); - -/*! - * \param s buffer to convert - * \param len size of buffer - * - * \retval pointer to converted string - */ -FT_DECLARE(char *) ftdm_url_decode(char *s, ftdm_size_t *len); - -#endif /* __FTDM_CALL_UTILS_H__ */ - diff --git a/libs/freetdm/src/include/ftdm_declare.h b/libs/freetdm/src/include/ftdm_declare.h deleted file mode 100644 index 410944e7d3..0000000000 --- a/libs/freetdm/src/include/ftdm_declare.h +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * Moises Silva - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __FTDM_DECLARE_H__ -#define __FTDM_DECLARE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(_XOPEN_SOURCE) && !defined(__FreeBSD__) -#define _XOPEN_SOURCE 600 -#endif - -#ifndef HAVE_STRINGS_H -#define HAVE_STRINGS_H 1 -#endif -#ifndef HAVE_SYS_SOCKET_H -#define HAVE_SYS_SOCKET_H 1 -#endif - -#ifndef __WINDOWS__ -#if defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32) || defined(_WIN64) -#define __WINDOWS__ -#endif -#endif - -#ifdef _MSC_VER -#define __FTDM_FUNC__ __FUNCTION__ -#if defined(FT_DECLARE_STATIC) -#define FT_DECLARE(type) type __stdcall -#define FT_DECLARE_NONSTD(type) type __cdecl -#define FT_DECLARE_DATA -#elif defined(FREETDM_EXPORTS) -#define FT_DECLARE(type) __declspec(dllexport) type __stdcall -#define FT_DECLARE_NONSTD(type) __declspec(dllexport) type __cdecl -#define FT_DECLARE_DATA __declspec(dllexport) -#else -#define FT_DECLARE(type) __declspec(dllimport) type __stdcall -#define FT_DECLARE_NONSTD(type) __declspec(dllimport) type __cdecl -#define FT_DECLARE_DATA __declspec(dllimport) -#endif -#define FT_DECLARE_INLINE(type) extern __inline__ type /* why extern? see http://support.microsoft.com/kb/123768 */ -#define EX_DECLARE_DATA __declspec(dllexport) -#else -#define __FTDM_FUNC__ (const char *)__func__ -#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(HAVE_VISIBILITY) -#define FT_DECLARE(type) __attribute__((visibility("default"))) type -#define FT_DECLARE_NONSTD(type) __attribute__((visibility("default"))) type -#define FT_DECLARE_DATA __attribute__((visibility("default"))) -#else -#define FT_DECLARE(type) type -#define FT_DECLARE_NONSTD(type) type -#define FT_DECLARE_DATA -#endif -#define FT_DECLARE_INLINE(type) __inline__ type -#define EX_DECLARE_DATA -#endif - -#ifdef _MSC_VER -#ifndef __inline__ -#define __inline__ __inline -#endif -#if (_MSC_VER >= 1400) /* VC8+ */ -#ifndef _CRT_SECURE_NO_DEPRECATE -#define _CRT_SECURE_NO_DEPRECATE -#endif -#ifndef _CRT_NONSTDC_NO_DEPRECATE -#define _CRT_NONSTDC_NO_DEPRECATE -#endif -#endif -#ifndef strcasecmp -#define strcasecmp(s1, s2) _stricmp(s1, s2) -#endif -#ifndef strncasecmp -#define strncasecmp(s1, s2, n) _strnicmp(s1, s2, n) -#endif -#if _MSC_VER < 1900 -#define snprintf _snprintf -#endif -#ifndef S_IRUSR -#define S_IRUSR _S_IREAD -#endif -#ifndef S_IWUSR -#define S_IWUSR _S_IWRITE -#endif -#undef HAVE_STRINGS_H -#undef HAVE_SYS_SOCKET_H -/* disable warning for zero length array in a struct */ -/* this will cause errors on c99 and ansi compliant compilers and will need to be fixed in the wanpipe header files */ -#pragma warning(disable:4706) -#pragma comment(lib, "Winmm") -#endif - -/* - * Compiler-specific format checking attributes - * use these on custom functions that use printf/scanf-style - * format strings (e.g. ftdm_log()) - */ -#if defined(__GNUC__) -/** - * Enable compiler-specific printf()-style format and argument checks on a function - * @param fmtp Position of printf()-style format string parameter - * @param argp Position of variable argument list ("...") parameter - * @code - * void log(const int level, const char *fmt, ...) __ftdm_check_printf(2, 3); - * @endcode - */ -#define __ftdm_check_printf(fmtp, argp) __attribute__((format (printf, fmtp, argp))) -/** - * Enable compiler-specific scanf()-style format and argument checks on a function - * @param fmtp Position of scanf()-style format string parameter - * @param argp Position of variable argument list ("...") parameter - * @code - * void parse(struct foo *ctx, const char *fmt, ...) __ftdm_check_scanf(2, 3); - * @endcode - */ -#define __ftdm_check_scanf(fmtp, argp) __attribute__((format (scanf, fmtp, argp))) -#else -#define __ftdm_check_printf(fmtp, argp) -#define __ftdm_check_scanf(fmtp, argp) -#endif - - -#define FTDM_STR2ENUM_P(_FUNC1, _FUNC2, _TYPE) FT_DECLARE(_TYPE) _FUNC1 (const char *name); FT_DECLARE(const char *) _FUNC2 (_TYPE type); -#define FTDM_STR2ENUM(_FUNC1, _FUNC2, _TYPE, _STRINGS, _MAX) \ - FT_DECLARE(_TYPE) _FUNC1 (const char *name) \ - { \ - int i; \ - _TYPE t = _MAX ; \ - \ - for (i = 0; i < _MAX ; i++) { \ - if (!strcasecmp(name, _STRINGS[i])) { \ - t = (_TYPE) i; \ - break; \ - } \ - } \ - \ - return t; \ - } \ - FT_DECLARE(const char *) _FUNC2 (_TYPE type) \ - { \ - if (type > _MAX) { \ - type = _MAX; \ - } \ - return _STRINGS[(int)type]; \ - } \ - -#ifdef __WINDOWS__ -#include -#include -#define FTDM_INVALID_SOCKET INVALID_HANDLE_VALUE -typedef HANDLE ftdm_socket_t; -typedef unsigned __int64 uint64_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int8 uint8_t; -typedef __int64 int64_t; -typedef __int32 int32_t; -typedef __int16 int16_t; -typedef __int8 int8_t; -#define FTDM_O_BINARY O_BINARY -#define FTDM_SIZE_FMT "Id" -#define FTDM_INT64_FMT "lld" -#define FTDM_UINT64_FMT "llu" -#define FTDM_XINT64_FMT "llx" -#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) -#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 -#else -#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL -#endif /* _MSC_VER */ -#else /* __WINDOWS__ */ -#define FTDM_O_BINARY 0 -#define FTDM_SIZE_FMT "zd" -#if (defined(__SIZEOF_LONG__) && (__SIZEOF_LONG__ == 8)) || defined(__LP64__) || defined(__LLP64__) -#define FTDM_INT64_FMT "ld" -#define FTDM_UINT64_FMT "lu" -#define FTDM_XINT64_FMT "lx" -#else -#define FTDM_INT64_FMT "lld" -#define FTDM_UINT64_FMT "llu" -#define FTDM_XINT64_FMT "llx" -#endif -#define FTDM_INVALID_SOCKET -1 -typedef int ftdm_socket_t; -#include -#include -#include -#endif - -/*! \brief FreeTDM APIs possible return codes */ -typedef enum { - FTDM_SUCCESS, /*!< Success */ - FTDM_FAIL, /*!< Failure, generic error return code when no more specific return code can be used */ - - FTDM_MEMERR, /*!< Allocation failure */ - FTDM_ENOMEM = FTDM_MEMERR, - - FTDM_TIMEOUT, /*!< Operation timed out (ie: polling on a device)*/ - FTDM_ETIMEDOUT = FTDM_TIMEOUT, - - FTDM_NOTIMPL, /*!< Operation not implemented */ - FTDM_ENOSYS = FTDM_NOTIMPL, /*!< The function is not implemented */ - - FTDM_BREAK, /*!< Request the caller to perform a break (context-dependant, ie: stop getting DNIS/ANI) */ - - /*!< Any new return codes should try to mimc unix style error codes, no need to reinvent */ - FTDM_EINVAL, /*!< Invalid argument */ - FTDM_ECANCELED, /*!< Operation cancelled */ - FTDM_EBUSY, /*!< Device busy */ -} ftdm_status_t; - -/*! \brief FreeTDM bool type. */ -typedef enum { - FTDM_FALSE, - FTDM_TRUE -} ftdm_bool_t; - -/*! \brief I/O waiting flags */ -typedef enum { - FTDM_NO_FLAGS = 0, - FTDM_READ = (1 << 0), - FTDM_WRITE = (1 << 1), - FTDM_EVENTS = (1 << 2) -} ftdm_wait_flag_t; - -/*! - * \brief FreeTDM channel. - * This is the basic data structure used to place calls and I/O operations - */ -typedef struct ftdm_channel ftdm_channel_t; - -/*! - * \brief FreeTDM span. - * Channel and signaling configuration container. - * This is a logical span structure, a span may ( or may note ) contain channels - * of other physical spans, depending on configuration (freetdm.conf) or if you - * are not using configuration depends on how you call ftdm_span_add_channel - */ -typedef struct ftdm_span ftdm_span_t; - -typedef struct ftdm_event ftdm_event_t; -typedef struct ftdm_conf_node ftdm_conf_node_t; -typedef struct ftdm_group ftdm_group_t; -typedef size_t ftdm_size_t; -typedef struct ftdm_sigmsg ftdm_sigmsg_t; -typedef struct ftdm_usrmsg ftdm_usrmsg_t; -typedef struct ftdm_io_interface ftdm_io_interface_t; -typedef struct ftdm_stream_handle ftdm_stream_handle_t; -typedef struct ftdm_queue ftdm_queue_t; -typedef struct ftdm_memory_handler ftdm_memory_handler_t; - -#ifdef __cplusplus -} /* extern C */ -#endif - -#endif - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/include/ftdm_dso.h b/libs/freetdm/src/include/ftdm_dso.h deleted file mode 100755 index b2d3c21999..0000000000 --- a/libs/freetdm/src/include/ftdm_dso.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Cross Platform dso/dll load abstraction - * Copyright(C) 2008 Michael Jerris - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so. - * - * This work is provided under this license on an "as is" basis, without warranty of any kind, - * either expressed or implied, including, without limitation, warranties that the covered code - * is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire - * risk as to the quality and performance of the covered code is with you. Should any covered - * code prove defective in any respect, you (not the initial developer or any other contributor) - * assume the cost of any necessary servicing, repair or correction. This disclaimer of warranty - * constitutes an essential part of this license. No use of any covered code is authorized hereunder - * except under this disclaimer. - * - */ - -#include "freetdm.h" - -#ifndef _FTDM_DSO_H -#define _FTDM_DSO_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void (*ftdm_func_ptr_t) (void); -typedef void * ftdm_dso_lib_t; - -FT_DECLARE(ftdm_status_t) ftdm_dso_destroy(ftdm_dso_lib_t *lib); -FT_DECLARE(ftdm_dso_lib_t) ftdm_dso_open(const char *path, char **err); -FT_DECLARE(void *) ftdm_dso_func_sym(ftdm_dso_lib_t lib, const char *sym, char **err); -FT_DECLARE(char *) ftdm_build_dso_path(const char *name, char *path, ftdm_size_t len); - - -#ifdef __cplusplus -} -#endif - -#endif - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - diff --git a/libs/freetdm/src/include/ftdm_os.h b/libs/freetdm/src/include/ftdm_os.h deleted file mode 100644 index 913debcd52..0000000000 --- a/libs/freetdm/src/include/ftdm_os.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * Moises Silva - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __FTDM_OS_H__ -#define __FTDM_OS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(__linux__) && !defined(__USE_BSD) -#define __USE_BSD -#endif - -#include "ftdm_declare.h" -#include "ftdm_threadmutex.h" -#include - -#ifndef __WINDOWS__ -#include -#endif - -/*! \brief time data type */ -typedef uint64_t ftdm_time_t; -/*! format string for ftdm_time_t */ -#define FTDM_TIME_FMT FTDM_UINT64_FMT - -/*! \brief sleep x amount of milliseconds */ -#ifdef __WINDOWS__ -#define ftdm_sleep(x) Sleep(x) -#else -#define ftdm_sleep(x) usleep(x * 1000) -#endif - -/*! \brief strncpy replacement */ -#define ftdm_copy_string(x,y,z) strncpy(x, y, z - 1) - -/*! \brief strncpy into a fixed-length buffer */ -#define ftdm_set_string(x,y) strncpy(x, y, sizeof(x)-1) - -/*! \brief check for null or zero length string buffer */ -#define ftdm_strlen_zero(s) (!s || *s == '\0') - -/*! \brief check for zero length string buffer */ -#define ftdm_strlen_zero_buf(s) (*s == '\0') - -/*! \brief array len helper */ -#define ftdm_array_len(array) sizeof(array)/sizeof(array[0]) - -/*! \brief Get smaller value */ -#define ftdm_min(x,y) ((x) < (y) ? (x) : (y)) - -/*! \brief Get larger value */ -#define ftdm_max(x,y) ((x) > (y) ? (x) : (y)) - -/*! \brief Get value that is in range [vmin,vmax] */ -#define ftdm_clamp(val,vmin,vmax) ftdm_max(vmin,ftdm_min(val,vmax)) - -/*!< \brief Safer version of ftdm_clamp(), that swaps vmin/vmax parameters if vmin > vmax */ -#define ftdm_clamp_safe(val,vmin,vmax) \ - ftdm_clamp(val, ftdm_min(vmin,vmax), ftdm_max(vmin,vmax)) - -/*! - * \brief Get offset of member in structure - * \param[in] type Type of struct - * \param[in] member Name of struct member - * \code - * struct a { - * int foo; - * int bar; - * }; - * - * int offset_a_bar = ftdm_offset_of(struct a, bar); // 4 byte offset - * \endcode - */ -#define ftdm_offset_of(type,member) (uintptr_t)&(((type *)0)->member) - -/*! - * \brief Get pointer to enclosing structrure from pointer to embedded member - * \param[in] ptr Pointer to embedded member - * \param[in] type Type of parent/container structure - * \param[in] member Name of embedded member in parent/container struct - * \code - * struct engine { - * int nr_cyl; - * }; - * - * struct car { - * char model[10]; - * struct engine eng; // struct engine embedded in car(!) - * }; - * - * int somefunc(struct engine *e) { - * struct car *c = ftdm_container_of(e, struct car, eng); - * - * ... do something with car ... - * } - * \endcode - */ -#define ftdm_container_of(ptr,type,member) (type *)((uintptr_t)(ptr) - ftdm_offset_of(type, member)) - -/*! - * \brief Silence "unused parameter" compiler warnings - * \note Tested with VS 2010, GCC 4.8, clang 3.1 and suncc - * \code - * int example(char *a) { - * ftdm_unused_arg(a); - * return 0; - * } - * \endcode - */ -#define ftdm_unused_arg(x) (void)(x) - - -/*! \brief The memory handler. - Do not use directly this variable, use the memory macros and ftdm_global_set_memory_handler to override */ -FT_DECLARE_DATA extern ftdm_memory_handler_t g_ftdm_mem_handler; - -/*! - \brief Allocate uninitialized memory - \param chunksize the chunk size -*/ -#define ftdm_malloc(chunksize) g_ftdm_mem_handler.malloc(g_ftdm_mem_handler.pool, chunksize) - -/*! - \brief Reallocates memory - \param buff the buffer - \param chunksize the chunk size -*/ -#define ftdm_realloc(buff, chunksize) g_ftdm_mem_handler.realloc(g_ftdm_mem_handler.pool, buff, chunksize) - -/*! - \brief Allocate initialized memory - \param chunksize the chunk size -*/ -#define ftdm_calloc(elements, chunksize) g_ftdm_mem_handler.calloc(g_ftdm_mem_handler.pool, elements, chunksize) - -/*! - \brief Free chunk of memory - \param chunksize the chunk size -*/ -#define ftdm_free(chunk) g_ftdm_mem_handler.free(g_ftdm_mem_handler.pool, chunk) - -/*! - \brief Free a pointer and set it to NULL unless it already is NULL - \param it the pointer -*/ -#define ftdm_safe_free(it) if (it) { ftdm_free(it); it = NULL; } - -/*! \brief Duplicate string */ -FT_DECLARE(char *) ftdm_strdup(const char *str); - -/*! \brief Duplicate string with limit */ -FT_DECLARE(char *) ftdm_strndup(const char *str, ftdm_size_t inlen); - -/*! \brief Get the current time in milliseconds */ -FT_DECLARE(ftdm_time_t) ftdm_current_time_in_ms(void); - -#ifdef __cplusplus -} /* extern C */ -#endif - -#endif - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/include/ftdm_threadmutex.h b/libs/freetdm/src/include/ftdm_threadmutex.h deleted file mode 100644 index 45eb87d441..0000000000 --- a/libs/freetdm/src/include/ftdm_threadmutex.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Cross Platform Thread/Mutex abstraction - * Copyright(C) 2007 Michael Jerris - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so. - * - * This work is provided under this license on an "as is" basis, without warranty of any kind, - * either expressed or implied, including, without limitation, warranties that the covered code - * is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire - * risk as to the quality and performance of the covered code is with you. Should any covered - * code prove defective in any respect, you (not the initial developer or any other contributor) - * assume the cost of any necessary servicing, repair or correction. This disclaimer of warranty - * constitutes an essential part of this license. No use of any covered code is authorized hereunder - * except under this disclaimer. - * - * Contributors: - * - * Moises Silva - * - */ - - -#ifndef _FTDM_THREADMUTEX_H -#define _FTDM_THREADMUTEX_H - -#include "freetdm.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct ftdm_mutex ftdm_mutex_t; -typedef struct ftdm_thread ftdm_thread_t; -typedef struct ftdm_interrupt ftdm_interrupt_t; -typedef void *(*ftdm_thread_function_t) (ftdm_thread_t *, void *); - -FT_DECLARE(ftdm_status_t) ftdm_thread_create_detached(ftdm_thread_function_t func, void *data); -FT_DECLARE(ftdm_status_t) ftdm_thread_create_detached_ex(ftdm_thread_function_t func, void *data, ftdm_size_t stack_size); -FT_DECLARE(void) ftdm_thread_override_default_stacksize(ftdm_size_t size); - -FT_DECLARE(ftdm_status_t) ftdm_mutex_create(ftdm_mutex_t **mutex); -FT_DECLARE(ftdm_status_t) ftdm_mutex_destroy(ftdm_mutex_t **mutex); - -#define ftdm_mutex_lock(_x) _ftdm_mutex_lock(__FILE__, __LINE__, __FTDM_FUNC__, _x) -FT_DECLARE(ftdm_status_t) _ftdm_mutex_lock(const char *file, int line, const char *func, ftdm_mutex_t *mutex); - -#define ftdm_mutex_trylock(_x) _ftdm_mutex_trylock(__FILE__, __LINE__, __FTDM_FUNC__, _x) -FT_DECLARE(ftdm_status_t) _ftdm_mutex_trylock(const char *file, int line, const char *func, ftdm_mutex_t *mutex); - -#define ftdm_mutex_unlock(_x) _ftdm_mutex_unlock(__FILE__, __LINE__, __FTDM_FUNC__, _x) -FT_DECLARE(ftdm_status_t) _ftdm_mutex_unlock(const char *file, int line, const char *func, ftdm_mutex_t *mutex); - -FT_DECLARE(ftdm_status_t) ftdm_interrupt_create(ftdm_interrupt_t **cond, ftdm_socket_t device, ftdm_wait_flag_t device_flags); -FT_DECLARE(ftdm_status_t) ftdm_interrupt_destroy(ftdm_interrupt_t **cond); -FT_DECLARE(ftdm_status_t) ftdm_interrupt_signal(ftdm_interrupt_t *cond); -FT_DECLARE(ftdm_status_t) ftdm_interrupt_wait(ftdm_interrupt_t *cond, int ms); -FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interrupts[], ftdm_size_t size, int ms); -FT_DECLARE(ftdm_wait_flag_t) ftdm_interrupt_device_ready(ftdm_interrupt_t *interrupt); - -#ifdef __cplusplus -} -#endif - -#endif - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - diff --git a/libs/freetdm/src/include/private/fsk.h b/libs/freetdm/src/include/private/fsk.h deleted file mode 100644 index 66da140df9..0000000000 --- a/libs/freetdm/src/include/private/fsk.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * bell202.h - * - * Copyright (c) 2005 Robert Krten. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This module contains the manifest constants and declarations for - * the Bell-202 1200 baud FSK modem. - * - * 2005 03 20 R. Krten created -*/ - -#ifndef __FSK_H__ -#define __FSK_H__ -#include "uart.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - int freq_space; /* Frequency of the 0 bit */ - int freq_mark; /* Frequency of the 1 bit */ - int baud_rate; /* baud rate for the modem */ -} fsk_modem_definition_t; - -/* Must be kept in sync with fsk_modem_definitions array in fsk.c */ -/* V.23 definitions: http://www.itu.int/rec/recommendation.asp?type=folders&lang=e&parent=T-REC-V.23 */ -typedef enum { - FSK_V23_FORWARD_MODE1 = 0, /* Maximum 600 bps for long haul */ - FSK_V23_FORWARD_MODE2, /* Standard 1200 bps V.23 */ - FSK_V23_BACKWARD, /* 75 bps return path for V.23 */ - FSK_BELL202 /* Bell 202 half-duplex 1200 bps */ -} fsk_modem_types_t; - -typedef enum { - FSK_STATE_CHANSEIZE = 0, - FSK_STATE_CARRIERSIG, - FSK_STATE_DATA -} fsk_state_t; - -typedef struct dsp_fsk_attr_s -{ - int sample_rate; /* sample rate in HZ */ - bithandler_func_t bithandler; /* bit handler */ - void *bithandler_arg; /* arbitrary ID passed to bithandler as first argument */ - bytehandler_func_t bytehandler; /* byte handler */ - void *bytehandler_arg; /* arbitrary ID passed to bytehandler as first argument */ -} dsp_fsk_attr_t; - -typedef struct -{ - fsk_state_t state; - dsp_fsk_attr_t attr; /* attributes structure */ - double *correlates[4]; /* one for each of sin/cos for mark/space */ - int corrsize; /* correlate size (also number of samples in ring buffer) */ - double *buffer; /* sample ring buffer */ - int ringstart; /* ring buffer start offset */ - double cellpos; /* bit cell position */ - double celladj; /* bit cell adjustment for each sample */ - int previous_bit; /* previous bit (for detecting a transition to sync-up cell position) */ - int current_bit; /* current bit */ - int last_bit; - int downsampling_count; /* number of samples to skip */ - int current_downsample; /* current skip count */ - int conscutive_state_bits; /* number of bits in a row that matches the pattern for the current state */ -} dsp_fsk_handle_t; - -/* - * Function prototypes - * - * General calling order is: - * a) create the attributes structure (dsp_fsk_attr_init) - * b) initialize fields in the attributes structure (dsp_fsk_attr_set_*) - * c) create a Bell-202 handle (dsp_fsk_create) - * d) feed samples through the handler (dsp_fsk_sample) -*/ - -void dsp_fsk_attr_init(dsp_fsk_attr_t *attributes); - -bithandler_func_t dsp_fsk_attr_get_bithandler(dsp_fsk_attr_t *attributes, void **bithandler_arg); -void dsp_fsk_attr_set_bithandler(dsp_fsk_attr_t *attributes, bithandler_func_t bithandler, void *bithandler_arg); -bytehandler_func_t dsp_fsk_attr_get_bytehandler(dsp_fsk_attr_t *attributes, void **bytehandler_arg); -void dsp_fsk_attr_set_bytehandler(dsp_fsk_attr_t *attributes, bytehandler_func_t bytehandler, void *bytehandler_arg); -int dsp_fsk_attr_get_samplerate(dsp_fsk_attr_t *attributes); -int dsp_fsk_attr_set_samplerate(dsp_fsk_attr_t *attributes, int samplerate); - -dsp_fsk_handle_t * dsp_fsk_create(dsp_fsk_attr_t *attributes); -void dsp_fsk_destroy(dsp_fsk_handle_t **handle); - -void dsp_fsk_sample(dsp_fsk_handle_t *handle, double normalized_sample); - -extern fsk_modem_definition_t fsk_modem_definitions[]; - -#ifdef __cplusplus -} /* extern C */ -#endif - -#endif - diff --git a/libs/freetdm/src/include/private/ftdm_buffer.h b/libs/freetdm/src/include/private/ftdm_buffer.h deleted file mode 100644 index fd5628c905..0000000000 --- a/libs/freetdm/src/include/private/ftdm_buffer.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef FTDM_BUFFER_H -#define FTDM_BUFFER_H - -#include "freetdm.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup ftdm_buffer Buffer Routines - * @ingroup buffer - * The purpose of this module is to make a plain buffering interface that can be used for read/write buffers - * throughout the application. - * @{ - */ -struct ftdm_buffer; -typedef struct ftdm_buffer ftdm_buffer_t; - -/*! \brief Allocate a new dynamic ftdm_buffer - * \param buffer returned pointer to the new buffer - * \param blocksize length to realloc by as data is added - * \param start_len ammount of memory to reserve initially - * \param max_len length the buffer is allowed to grow to - * \return status - */ -FT_DECLARE(ftdm_status_t) ftdm_buffer_create(ftdm_buffer_t **buffer, ftdm_size_t blocksize, ftdm_size_t start_len, ftdm_size_t max_len); - -/*! \brief Get the length of a ftdm_buffer_t - * \param buffer any buffer of type ftdm_buffer_t - * \return int size of the buffer. - */ -FT_DECLARE(ftdm_size_t) ftdm_buffer_len(ftdm_buffer_t *buffer); - -/*! \brief Get the freespace of a ftdm_buffer_t - * \param buffer any buffer of type ftdm_buffer_t - * \return int freespace in the buffer. - */ -FT_DECLARE(ftdm_size_t) ftdm_buffer_freespace(ftdm_buffer_t *buffer); - -/*! \brief Get the in use amount of a ftdm_buffer_t - * \param buffer any buffer of type ftdm_buffer_t - * \return int ammount of buffer curently in use - */ -FT_DECLARE(ftdm_size_t) ftdm_buffer_inuse(ftdm_buffer_t *buffer); - -/*! \brief Read data from a ftdm_buffer_t up to the ammount of datalen if it is available. Remove read data from buffer. - * \param buffer any buffer of type ftdm_buffer_t - * \param data pointer to the read data to be returned - * \param datalen amount of data to be returned - * \return int ammount of data actually read - */ -FT_DECLARE(ftdm_size_t) ftdm_buffer_read(ftdm_buffer_t *buffer, void *data, ftdm_size_t datalen); - -/*! \brief Read data endlessly from a ftdm_buffer_t - * \param buffer any buffer of type ftdm_buffer_t - * \param data pointer to the read data to be returned - * \param datalen amount of data to be returned - * \return int ammount of data actually read - * \note Once you have read all the data from the buffer it will loop around. - */ -FT_DECLARE(ftdm_size_t) ftdm_buffer_read_loop(ftdm_buffer_t *buffer, void *data, ftdm_size_t datalen); - -/*! \brief Assign a number of loops to read - * \param buffer any buffer of type ftdm_buffer_t - * \param loops the number of loops (-1 for infinite) - */ -FT_DECLARE(void) ftdm_buffer_set_loops(ftdm_buffer_t *buffer, int32_t loops); - -/*! \brief Write data into a ftdm_buffer_t up to the length of datalen - * \param buffer any buffer of type ftdm_buffer_t - * \param data pointer to the data to be written - * \param datalen amount of data to be written - * \return int amount of buffer used after the write, or 0 if no space available - */ -FT_DECLARE(ftdm_size_t) ftdm_buffer_write(ftdm_buffer_t *buffer, const void *data, ftdm_size_t datalen); - -/*! \brief Remove data from the buffer - * \param buffer any buffer of type ftdm_buffer_t - * \param datalen amount of data to be removed - * \return int size of buffer, or 0 if unable to toss that much data - */ -FT_DECLARE(ftdm_size_t) ftdm_buffer_toss(ftdm_buffer_t *buffer, ftdm_size_t datalen); - -/*! \brief Remove all data from the buffer - * \param buffer any buffer of type ftdm_buffer_t - */ -FT_DECLARE(void) ftdm_buffer_zero(ftdm_buffer_t *buffer); - -/*! \brief Destroy the buffer - * \param buffer buffer to destroy - * \note only neccessary on dynamic buffers (noop on pooled ones) - */ -FT_DECLARE(void) ftdm_buffer_destroy(ftdm_buffer_t **buffer); - -/*! \brief Seek to offset from the beginning of the buffer - * \param buffer buffer to seek - * \param datalen offset in bytes - * \return new position - */ -FT_DECLARE(ftdm_size_t) ftdm_buffer_seek(ftdm_buffer_t *buffer, ftdm_size_t datalen); - -/** @} */ - -FT_DECLARE(ftdm_size_t) ftdm_buffer_zwrite(ftdm_buffer_t *buffer, const void *data, ftdm_size_t datalen); - -#ifdef __cplusplus -} -#endif - -#endif -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/include/private/ftdm_config.h b/libs/freetdm/src/include/private/ftdm_config.h deleted file mode 100644 index f55261fcc9..0000000000 --- a/libs/freetdm/src/include/private/ftdm_config.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @defgroup config Config File Parser - * @ingroup config - * This module implements a basic interface and file format parser - * - *

- *
- * EXAMPLE 
- * 
- * [category1]
- * var1 => val1
- * var2 => val2
- * \# lines that begin with \# are comments
- * \#var3 => val3
- * 
- * @{ - */ - -#ifndef FTDM_CONFIG_H -#define FTDM_CONFIG_H - -#include "freetdm.h" -#define FTDM_URL_SEPARATOR "://" - - -#ifdef WIN32 -#define FTDM_PATH_SEPARATOR "\\" -#ifndef FTDM_CONFIG_DIR -#define FTDM_CONFIG_DIR "c:\\freetdm" -#endif -#define ftdm_is_file_path(file) (*(file +1) == ':' || *file == '/' || strstr(file, SWITCH_URL_SEPARATOR)) -#else -#define FTDM_PATH_SEPARATOR "/" -#ifndef FTDM_CONFIG_DIR -#define FTDM_CONFIG_DIR "/etc/freetdm" -#endif -#define ftdm_is_file_path(file) ((*file == '/') || strstr(file, SWITCH_URL_SEPARATOR)) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct ftdm_config ftdm_config_t; - -/*! \brief A simple file handle representing an open configuration file **/ -struct ftdm_config { - /*! FILE stream buffer to the opened file */ - FILE *file; - /*! path to the file */ - char path[512]; - /*! current category */ - char category[256]; - /*! current section */ - char section[256]; - /*! buffer of current line being read */ - char buf[1024]; - /*! current line number in file */ - int lineno; - /*! current category number in file */ - int catno; - /*! current section number in file */ - int sectno; - - int lockto; -}; - -/*! - \brief Open a configuration file - \param cfg (ftdm_config_t *) config handle to use - \param file_path path to the file - \return 1 (true) on success 0 (false) on failure -*/ -int ftdm_config_open_file(ftdm_config_t * cfg, const char *file_path); - -/*! - \brief Close a previously opened configuration file - \param cfg (ftdm_config_t *) config handle to use -*/ -void ftdm_config_close_file(ftdm_config_t * cfg); - -/*! - \brief Retrieve next name/value pair from configuration file - \param cfg (ftdm_config_t *) config handle to use - \param var pointer to aim at the new variable name - \param val pointer to aim at the new value -*/ -int ftdm_config_next_pair(ftdm_config_t * cfg, char **var, char **val); - -/*! - \brief Retrieve the CAS bits from a configuration string value - \param strvalue pointer to the configuration string value (expected to be in format whatever:xxxx) - \param outbits pointer to aim at the CAS bits -*/ -FT_DECLARE (int) ftdm_config_get_cas_bits(char *strvalue, unsigned char *outbits); - -#ifdef __cplusplus -} -#endif - -/** @} */ -#endif -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h deleted file mode 100644 index 935cd50078..0000000000 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ /dev/null @@ -1,803 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * Moises Silva - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "freetdm.h" - -#ifndef __PRIVATE_FTDM_CORE__ -#define __PRIVATE_FTDM_CORE__ - -#if !defined(_XOPEN_SOURCE) && !defined(__FreeBSD__) -#define _XOPEN_SOURCE 600 -#endif - -#ifndef HAVE_STRINGS_H -#define HAVE_STRINGS_H 1 -#endif -#ifndef HAVE_SYS_SOCKET_H -#define HAVE_SYS_SOCKET_H 1 -#endif - -#ifdef _MSC_VER -#ifndef __inline__ -#define __inline__ __inline -#endif -#if (_MSC_VER >= 1400) /* VC8+ */ -#ifndef _CRT_SECURE_NO_DEPRECATE -#define _CRT_SECURE_NO_DEPRECATE -#endif -#ifndef _CRT_NONSTDC_NO_DEPRECATE -#define _CRT_NONSTDC_NO_DEPRECATE -#endif -#endif -#ifndef strcasecmp -#define strcasecmp(s1, s2) _stricmp(s1, s2) -#endif -#ifndef strncasecmp -#define strncasecmp(s1, s2, n) _strnicmp(s1, s2, n) -#endif -#ifndef snprintf -#define snprintf _snprintf -#endif -#ifndef S_IRUSR -#define S_IRUSR _S_IREAD -#endif -#ifndef S_IWUSR -#define S_IWUSR _S_IWRITE -#endif -#undef HAVE_STRINGS_H -#undef HAVE_SYS_SOCKET_H -/* disable warning for zero length array in a struct */ -/* this will cause errors on c99 and ansi compliant compilers and will need to be fixed in the wanpipe header files */ -#pragma warning(disable:4706) -#pragma comment(lib, "Winmm") -#endif - -#define FTDM_THREAD_STACKSIZE 240 * 1024 -#define FTDM_ENUM_NAMES(_NAME, _STRINGS) static const char * _NAME [] = { _STRINGS , NULL }; - -#define ftdm_true(expr) \ - (expr && ( !strcasecmp(expr, "yes") || \ - !strcasecmp(expr, "on") || \ - !strcasecmp(expr, "true") || \ - !strcasecmp(expr, "enabled") || \ - !strcasecmp(expr, "active") || \ - atoi(expr))) ? FTDM_TRUE : FTDM_FALSE - -#ifdef WIN32_LEAN_AND_MEAN -#include -#include -#endif - -#include -#ifndef __WINDOWS__ -#include -#endif - -#include -#include -#include -#ifdef HAVE_STRINGS_H -#include -#endif -#include - -#include "ftdm_types.h" -#include "hashtable.h" -#include "ftdm_config.h" -#include "g711.h" -#include "libteletone.h" -#include "ftdm_buffer.h" -#include "ftdm_threadmutex.h" -#include "ftdm_sched.h" -#include "ftdm_call_utils.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define SPAN_PENDING_CHANS_QUEUE_SIZE 1000 -#define SPAN_PENDING_SIGNALS_QUEUE_SIZE 1000 - -#define GOTO_STATUS(label,st) status = st; goto label ; - -#define ftdm_copy_string(x,y,z) strncpy(x, y, z - 1) -#define ftdm_set_string(x,y) strncpy(x, y, sizeof(x)-1) -#define ftdm_strlen_zero(s) (!s || *s == '\0') -#define ftdm_strlen_zero_buf(s) (*s == '\0') - - -#define ftdm_channel_test_feature(obj, flag) ((obj)->features & flag) -#define ftdm_channel_set_feature(obj, flag) (obj)->features = (ftdm_channel_feature_t)((obj)->features | flag) -#define ftdm_channel_clear_feature(obj, flag) (obj)->features = (ftdm_channel_feature_t)((obj)->features & ( ~(flag) )) -#define ftdm_channel_set_member_locked(obj, _m, _v) ftdm_mutex_lock(obj->mutex); obj->_m = _v; ftdm_mutex_unlock(obj->mutex) - -/*! - \brief Test for the existance of a flag on an arbitary object - \command obj the object to test - \command flag the or'd list of flags to test - \return true value if the object has the flags defined -*/ -#define ftdm_test_flag(obj, flag) ((obj)->flags & flag) -/*!< Physical (IO) module specific flags */ -#define ftdm_test_pflag(obj, flag) ((obj)->pflags & flag) -/*!< signaling module specific flags */ -#define ftdm_test_sflag(obj, flag) ((obj)->sflags & flag) - -#define ftdm_set_alarm_flag(obj, flag) (obj)->alarm_flags |= (flag) -#define ftdm_clear_alarm_flag(obj, flag) (obj)->alarm_flags &= ~(flag) -#define ftdm_test_alarm_flag(obj, flag) ((obj)->alarm_flags & flag) - -#define ftdm_set_io_flag(obj, flag) (obj)->io_flags |= (flag) -#define ftdm_clear_io_flag(obj, flag) (obj)->io_flags &= ~(flag) -#define ftdm_test_io_flag(obj, flag) ((obj)->io_flags & flag) - -/*! - \brief Set a flag on an arbitrary object - \command obj the object to set the flags on - \command flag the or'd list of flags to set -*/ -#define ftdm_set_flag(obj, flag) (obj)->flags |= (flag) -#define ftdm_set_flag_locked(obj, flag) assert(obj->mutex != NULL); \ - ftdm_mutex_lock(obj->mutex); \ - (obj)->flags |= (flag); \ - ftdm_mutex_unlock(obj->mutex); - -#define ftdm_set_pflag(obj, flag) (obj)->pflags |= (flag) -#define ftdm_set_pflag_locked(obj, flag) assert(obj->mutex != NULL); \ - ftdm_mutex_lock(obj->mutex); \ - (obj)->pflags |= (flag); \ - ftdm_mutex_unlock(obj->mutex); - -#define ftdm_set_sflag(obj, flag) (obj)->sflags |= (flag) -#define ftdm_set_sflag_locked(obj, flag) assert(obj->mutex != NULL); \ - ftdm_mutex_lock(obj->mutex); \ - (obj)->sflags |= (flag); \ - ftdm_mutex_unlock(obj->mutex); - -/*! - \brief Clear a flag on an arbitrary object while locked - \command obj the object to test - \command flag the or'd list of flags to clear -*/ -#define ftdm_clear_flag(obj, flag) (obj)->flags &= ~(flag) - -#define ftdm_clear_flag_locked(obj, flag) assert(obj->mutex != NULL); ftdm_mutex_lock(obj->mutex); (obj)->flags &= ~(flag); ftdm_mutex_unlock(obj->mutex); - -#define ftdm_clear_pflag(obj, flag) (obj)->pflags &= ~(flag) - -#define ftdm_clear_pflag_locked(obj, flag) assert(obj->mutex != NULL); ftdm_mutex_lock(obj->mutex); (obj)->pflags &= ~(flag); ftdm_mutex_unlock(obj->mutex); - -#define ftdm_clear_sflag(obj, flag) (obj)->sflags &= ~(flag) - -#define ftdm_clear_sflag_locked(obj, flag) assert(obj->mutex != NULL); ftdm_mutex_lock(obj->mutex); (obj)->sflags &= ~(flag); ftdm_mutex_unlock(obj->mutex); - -#ifdef _MSC_VER -/* The while(0) below throws a conditional expression is constant warning */ -#pragma warning(disable:4127) -#endif - -/* this macro assumes obj is locked! */ -#define ftdm_wait_for_flag_cleared(obj, flag, time) \ - do { \ - int __safety = time; \ - while(__safety-- && ftdm_test_flag(obj, flag)) { \ - ftdm_mutex_unlock(obj->mutex); \ - ftdm_sleep(10); \ - ftdm_mutex_lock(obj->mutex); \ - } \ - if(!__safety) { \ - ftdm_log(FTDM_LOG_CRIT, "flag %"FTDM_UINT64_FMT" was never cleared\n", (uint64_t)flag); \ - } \ - } while(0); - -#define ftdm_is_dtmf(key) ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119) - -#ifdef __linux__ -#define ftdm_print_stack(level) \ - do { \ - void *__stacktrace[100] = { 0 }; \ - char **__symbols = NULL; \ - int __size = 0; \ - int __i = 0; \ - __size = backtrace(__stacktrace, ftdm_array_len(__stacktrace)); \ - __symbols = backtrace_symbols(__stacktrace, __size); \ - if (__symbols) { \ - for (__i = 0; __i < __size; __i++) { \ - ftdm_log(__level, "%s\n", __symbols[i]); \ - } \ - free(__symbols); \ - } \ - } while (0); -#else -#define ftdm_print_stack(level) ftdm_log(level, "FTDM_PRINT_STACK is not implemented in this operating system!\n"); -#endif - - -#define FTDM_SPAN_IS_BRI(x) ((x)->trunk_type == FTDM_TRUNK_BRI || (x)->trunk_type == FTDM_TRUNK_BRI_PTMP) -/*! - \brief Copy flags from one arbitrary object to another - \command dest the object to copy the flags to - \command src the object to copy the flags from - \command flags the flags to copy -*/ -#define ftdm_copy_flags(dest, src, flags) (dest)->flags &= ~(flags); (dest)->flags |= ((src)->flags & (flags)) - -struct ftdm_stream_handle { - ftdm_stream_handle_write_function_t write_function; - ftdm_stream_handle_raw_write_function_t raw_write_function; - void *data; - void *end; - ftdm_size_t data_size; - ftdm_size_t data_len; - ftdm_size_t alloc_len; - ftdm_size_t alloc_chunk; -}; - -FT_DECLARE_NONSTD(ftdm_status_t) ftdm_console_stream_raw_write(ftdm_stream_handle_t *handle, uint8_t *data, ftdm_size_t datalen); -FT_DECLARE_NONSTD(ftdm_status_t) ftdm_console_stream_write(ftdm_stream_handle_t *handle, const char *fmt, ...); - -#define FTDM_CMD_CHUNK_LEN 1024 -#define FTDM_STANDARD_STREAM(s) memset(&s, 0, sizeof(s)); s.data = ftdm_malloc(FTDM_CMD_CHUNK_LEN); \ - assert(s.data); \ - memset(s.data, 0, FTDM_CMD_CHUNK_LEN); \ - s.end = s.data; \ - s.data_size = FTDM_CMD_CHUNK_LEN; \ - s.write_function = ftdm_console_stream_write; \ - s.raw_write_function = ftdm_console_stream_raw_write; \ - s.alloc_len = FTDM_CMD_CHUNK_LEN; \ - s.alloc_chunk = FTDM_CMD_CHUNK_LEN - -/*! brief create a new queue */ -#define ftdm_queue_create(queue, capacity) g_ftdm_queue_handler.create(queue, capacity) - -/*! Enqueue an object */ -#define ftdm_queue_enqueue(queue, obj) g_ftdm_queue_handler.enqueue(queue, obj) - -/*! dequeue an object from the queue */ -#define ftdm_queue_dequeue(queue) g_ftdm_queue_handler.dequeue(queue) - -/*! wait ms milliseconds for a queue to have available objects, -1 to wait forever */ -#define ftdm_queue_wait(queue, ms) g_ftdm_queue_handler.wait(queue, ms) - -/*! get the internal interrupt object (to wait for elements to be added from the outside bypassing ftdm_queue_wait) */ -#define ftdm_queue_get_interrupt(queue, ms) g_ftdm_queue_handler.get_interrupt(queue, ms) - -/*! destroy the queue */ -#define ftdm_queue_destroy(queue) g_ftdm_queue_handler.destroy(queue) - -FT_DECLARE_DATA extern ftdm_queue_handler_t g_ftdm_queue_handler; - -#define FTDM_TOKEN_STRLEN 128 -#define FTDM_MAX_TOKENS 10 - -static __inline__ char *ftdm_clean_string(char *s) -{ - char *p; - - for (p = s; p && *p; p++) { - uint8_t x = (uint8_t) *p; - if (x < 32 || x > 127) { - *p = ' '; - } - } - - return s; -} - -struct ftdm_bitstream { - uint8_t *data; - uint32_t datalen; - uint32_t byte_index; - uint8_t bit_index; - int8_t endian; - uint8_t top; - uint8_t bot; - uint8_t ss; - uint8_t ssv; -}; - -struct ftdm_fsk_data_state { - dsp_fsk_handle_t *fsk1200_handle; - uint8_t init; - uint8_t *buf; - size_t bufsize; - ftdm_size_t blen; - ftdm_size_t bpos; - ftdm_size_t dlen; - ftdm_size_t ppos; - int checksum; -}; - -struct ftdm_fsk_modulator { - teletone_dds_state_t dds; - ftdm_bitstream_t bs; - uint32_t carrier_bits_start; - uint32_t carrier_bits_stop; - uint32_t chan_sieze_bits; - uint32_t bit_factor; - uint32_t bit_accum; - uint32_t sample_counter; - int32_t samples_per_bit; - int32_t est_bytes; - fsk_modem_types_t modem_type; - ftdm_fsk_data_state_t *fsk_data; - ftdm_fsk_write_sample_t write_sample_callback; - void *user_data; - int16_t sample_buffer[64]; -}; - - -typedef enum { - FTDM_TYPE_NONE, - FTDM_TYPE_SPAN = 0xFF, - FTDM_TYPE_CHANNEL -} ftdm_data_type_t; - -/* number of bytes for the IO dump circular buffer (5 seconds worth of audio by default) */ -#define FTDM_IO_DUMP_DEFAULT_BUFF_SIZE 8 * 5000 -typedef struct { - char *buffer; - ftdm_size_t size; - int windex; - int wrapped; -} ftdm_io_dump_t; - -/* number of interval cycles before timeout and close the debug dtmf file (5 seconds if interval is 20) */ -#define DTMF_DEBUG_TIMEOUT 250 -typedef struct { - uint8_t enabled; - uint8_t requested; - FILE *file; - int32_t closetimeout; - ftdm_mutex_t *mutex; -} ftdm_dtmf_debug_t; - -typedef struct { - uint32_t duration_ms; - ftdm_time_t start_time; - /* If set to 1, we will send DTMF event the the tone starts, instead of waiting for end */ - uint8_t trigger_on_start; -} ftdm_dtmf_detect_t; - -/* 2^8 table size, one for each byte (sample) value */ -#define FTDM_GAINS_TABLE_SIZE 256 -struct ftdm_channel { - ftdm_data_type_t data_type; - uint32_t span_id; - uint32_t chan_id; - uint32_t physical_span_id; - uint32_t physical_chan_id; - uint32_t rate; - uint32_t extra_id; - ftdm_chan_type_t type; - ftdm_socket_t sockfd; - uint64_t flags; - uint32_t pflags; - uint32_t sflags; - uint8_t io_flags; - ftdm_alarm_flag_t alarm_flags; - ftdm_channel_feature_t features; - ftdm_codec_t effective_codec; - ftdm_codec_t native_codec; - uint32_t effective_interval; - uint32_t native_interval; - uint32_t packet_len; - ftdm_channel_state_t state; - ftdm_state_status_t state_status; - ftdm_channel_state_t last_state; - ftdm_channel_state_t init_state; - ftdm_channel_indication_t indication; - ftdm_state_history_entry_t history[10]; - uint8_t hindex; - ftdm_mutex_t *mutex; - teletone_dtmf_detect_state_t dtmf_detect; - uint32_t buffer_delay; - ftdm_event_t event_header; - char last_error[256]; - fio_event_cb_t event_callback; - uint32_t skip_read_frames; - ftdm_buffer_t *dtmf_buffer; - ftdm_buffer_t *gen_dtmf_buffer; - ftdm_buffer_t *pre_buffer; - ftdm_buffer_t *digit_buffer; - ftdm_buffer_t *fsk_buffer; - ftdm_mutex_t *pre_buffer_mutex; - uint32_t dtmf_on; - uint32_t dtmf_off; - char *dtmf_hangup_buf; - teletone_generation_session_t tone_session; - ftdm_time_t last_event_time; - ftdm_time_t ring_time; - char tokens[FTDM_MAX_TOKENS+1][FTDM_TOKEN_STRLEN]; - uint8_t needed_tones[FTDM_TONEMAP_INVALID]; - uint8_t detected_tones[FTDM_TONEMAP_INVALID]; - ftdm_tonemap_t last_detected_tone; - uint32_t token_count; - char chan_name[128]; - char chan_number[32]; - ftdm_filehandle_t fds[2]; - ftdm_fsk_data_state_t fsk; - uint8_t fsk_buf[80]; - uint32_t ring_count; - ftdm_polarity_t polarity; - /* Private I/O data. Do not touch unless you are an I/O module */ - void *io_data; - /* Private signaling data. Do not touch unless you are a signaling module */ - void *call_data; - struct ftdm_caller_data caller_data; - struct ftdm_span *span; - struct ftdm_io_interface *fio; - unsigned char rx_cas_bits; - uint32_t pre_buffer_size; - uint8_t rxgain_table[FTDM_GAINS_TABLE_SIZE]; - uint8_t txgain_table[FTDM_GAINS_TABLE_SIZE]; - float rxgain; - float txgain; - int availability_rate; - void *user_private; - ftdm_timer_id_t hangup_timer; - ftdm_channel_iostats_t iostats; - ftdm_dtmf_debug_t dtmfdbg; - ftdm_dtmf_detect_t dtmfdetect; - ftdm_io_dump_t rxdump; - ftdm_io_dump_t txdump; - ftdm_interrupt_t *state_completed_interrupt; /*!< Notify when a state change is completed */ - int32_t txdrops; - int32_t rxdrops; - ftdm_usrmsg_t *usrmsg; - ftdm_time_t last_state_change_time; - ftdm_time_t last_release_time; -}; - -struct ftdm_span { - ftdm_data_type_t data_type; - char *name; - uint32_t span_id; - uint32_t chan_count; - ftdm_span_flag_t flags; - struct ftdm_io_interface *fio; - fio_event_cb_t event_callback; - ftdm_mutex_t *mutex; - ftdm_trunk_type_t trunk_type; - ftdm_trunk_mode_t trunk_mode; - ftdm_analog_start_type_t start_type; - ftdm_signal_type_t signal_type; - uint32_t last_used_index; - /* Private signaling data. Do not touch unless you are a signaling module */ - void *signal_data; - fio_signal_cb_t signal_cb; - ftdm_event_t event_header; - char last_error[256]; - char tone_map[FTDM_TONEMAP_INVALID+1][FTDM_TONEMAP_LEN]; - teletone_tone_map_t tone_detect_map[FTDM_TONEMAP_INVALID+1]; - teletone_multi_tone_t tone_finder[FTDM_TONEMAP_INVALID+1]; - ftdm_channel_t *channels[FTDM_MAX_CHANNELS_SPAN+1]; - fio_channel_outgoing_call_t outgoing_call; - fio_channel_indicate_t indicate; - fio_channel_set_sig_status_t set_channel_sig_status; - fio_channel_get_sig_status_t get_channel_sig_status; - fio_span_set_sig_status_t set_span_sig_status; - fio_span_get_sig_status_t get_span_sig_status; - fio_channel_request_t channel_request; - ftdm_span_start_t start; - ftdm_span_stop_t stop; - ftdm_span_destroy_t destroy; - ftdm_channel_sig_read_t sig_read; - ftdm_channel_sig_write_t sig_write; - ftdm_channel_sig_dtmf_t sig_queue_dtmf; - ftdm_channel_sig_dtmf_t sig_send_dtmf; - uint32_t sig_release_guard_time_ms; - ftdm_channel_state_processor_t state_processor; /*!< This guy is called whenever state processing is required */ - void *io_data; /*!< Private I/O data per span. Do not touch unless you are an I/O module */ - char *type; - char *dtmf_hangup; - size_t dtmf_hangup_len; - ftdm_state_map_t *state_map; - ftdm_caller_data_t default_caller_data; - ftdm_queue_t *pendingchans; /*!< Channels pending of state processing */ - ftdm_queue_t *pendingsignals; /*!< Signals pending from being delivered to the user */ - struct ftdm_span *next; -}; - -struct ftdm_group { - char *name; - uint32_t group_id; - uint32_t chan_count; - ftdm_channel_t *channels[FTDM_MAX_CHANNELS_GROUP]; - uint32_t last_used_index; - ftdm_mutex_t *mutex; - struct ftdm_group *next; -}; - -FT_DECLARE_DATA extern ftdm_crash_policy_t g_ftdm_crash_policy; - -FT_DECLARE(ftdm_size_t) ftdm_fsk_modulator_generate_bit(ftdm_fsk_modulator_t *fsk_trans, int8_t bit, int16_t *buf, ftdm_size_t buflen); -FT_DECLARE(int32_t) ftdm_fsk_modulator_generate_carrier_bits(ftdm_fsk_modulator_t *fsk_trans, uint32_t bits); -FT_DECLARE(void) ftdm_fsk_modulator_generate_chan_sieze(ftdm_fsk_modulator_t *fsk_trans); -FT_DECLARE(void) ftdm_fsk_modulator_send_data(ftdm_fsk_modulator_t *fsk_trans); -#define ftdm_fsk_modulator_send_all(_it) ftdm_fsk_modulator_generate_chan_sieze(_it); \ - ftdm_fsk_modulator_generate_carrier_bits(_it, _it->carrier_bits_start); \ - ftdm_fsk_modulator_send_data(_it); \ - ftdm_fsk_modulator_generate_carrier_bits(_it, _it->carrier_bits_stop) - -FT_DECLARE(ftdm_status_t) ftdm_fsk_modulator_init(ftdm_fsk_modulator_t *fsk_trans, - fsk_modem_types_t modem_type, - uint32_t sample_rate, - ftdm_fsk_data_state_t *fsk_data, - float db_level, - uint32_t carrier_bits_start, - uint32_t carrier_bits_stop, - uint32_t chan_sieze_bits, - ftdm_fsk_write_sample_t write_sample_callback, - void *user_data); -FT_DECLARE(int8_t) ftdm_bitstream_get_bit(ftdm_bitstream_t *bsp); -FT_DECLARE(void) ftdm_bitstream_init(ftdm_bitstream_t *bsp, uint8_t *data, uint32_t datalen, ftdm_endian_t endian, uint8_t ss); -FT_DECLARE(ftdm_status_t) ftdm_fsk_data_parse(ftdm_fsk_data_state_t *state, ftdm_size_t *type, char **data, ftdm_size_t *len); -FT_DECLARE(ftdm_status_t) ftdm_fsk_demod_feed(ftdm_fsk_data_state_t *state, int16_t *data, size_t samples); -FT_DECLARE(ftdm_status_t) ftdm_fsk_demod_destroy(ftdm_fsk_data_state_t *state); -FT_DECLARE(int) ftdm_fsk_demod_init(ftdm_fsk_data_state_t *state, int rate, uint8_t *buf, size_t bufsize); -FT_DECLARE(ftdm_status_t) ftdm_fsk_data_init(ftdm_fsk_data_state_t *state, uint8_t *data, uint32_t datalen); -FT_DECLARE(ftdm_status_t) ftdm_fsk_data_add_mdmf(ftdm_fsk_data_state_t *state, ftdm_mdmf_type_t type, const uint8_t *data, uint32_t datalen); -FT_DECLARE(ftdm_status_t) ftdm_fsk_data_add_checksum(ftdm_fsk_data_state_t *state); -FT_DECLARE(ftdm_status_t) ftdm_fsk_data_add_sdmf(ftdm_fsk_data_state_t *state, const char *date, char *number); -FT_DECLARE(ftdm_status_t) ftdm_channel_send_fsk_data(ftdm_channel_t *ftdmchan, ftdm_fsk_data_state_t *fsk_data, float db_level); - -FT_DECLARE(ftdm_status_t) ftdm_span_load_tones(ftdm_span_t *span, const char *mapname); - -FT_DECLARE(ftdm_status_t) ftdm_channel_use(ftdm_channel_t *ftdmchan); - -FT_DECLARE(void) ftdm_generate_sln_silence(int16_t *data, uint32_t samples, uint32_t divisor); - -FT_DECLARE(uint32_t) ftdm_separate_string(char *buf, char delim, char **array, int arraylen); -FT_DECLARE(void) print_bits(uint8_t *b, int bl, char *buf, int blen, int e, uint8_t ss); -FT_DECLARE(void) print_hex_bytes(uint8_t *data, ftdm_size_t dlen, char *buf, ftdm_size_t blen); - -FT_DECLARE_NONSTD(int) ftdm_hash_equalkeys(void *k1, void *k2); -FT_DECLARE_NONSTD(uint32_t) ftdm_hash_hashfromstring(void *ky); - -FT_DECLARE(int) ftdm_load_modules(void); - -FT_DECLARE(ftdm_status_t) ftdm_unload_modules(void); - -FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t *sigmsg); - -FT_DECLARE(void) ftdm_channel_clear_needed_tones(ftdm_channel_t *ftdmchan); -FT_DECLARE(void) ftdm_channel_rotate_tokens(ftdm_channel_t *ftdmchan); - -FT_DECLARE(int) ftdm_load_module(const char *name); -FT_DECLARE(int) ftdm_load_module_assume(const char *name); -FT_DECLARE(int) ftdm_vasprintf(char **ret, const char *fmt, va_list ap); - -FT_DECLARE(ftdm_status_t) ftdm_span_close_all(void); -FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan); -FT_DECLARE(void) ftdm_ack_indication(ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication, ftdm_status_t status); - - -FT_DECLARE(ftdm_iterator_t *) ftdm_get_iterator(ftdm_iterator_type_t type, ftdm_iterator_t *iter); - -FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen); - -FT_DECLARE(ftdm_status_t) ftdm_raw_read (ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen); -FT_DECLARE(ftdm_status_t) ftdm_raw_write (ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen); - -/*! - * \brief Retrieves an event from the span - * - * \note - * This function is non-reentrant and not thread-safe. - * The event returned may be modified if the function is called again - * from a different thread or even the same. It is recommended to - * handle events from the same span in a single thread. - * WARNING: this function used to be public ( in freetdm.h ) - * but since is really of no use to users better keep it here - * - * \param span The span to retrieve the event from - * \param event Pointer to store the pointer to the event - * - * \retval FTDM_SUCCESS success (at least one event available) - * \retval FTDM_TIMEOUT Timed out waiting for events - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_span_next_event(ftdm_span_t *span, ftdm_event_t **event); - -/*! - * \brief Enqueue a DTMF string into the channel - * - * \param ftdmchan The channel to enqueue the dtmf string to - * \param dtmf null-terminated DTMF string - * - * \retval FTDM_SUCCESS success - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, const char *dtmf); - -/* dequeue pending signals and notify the user via the span signal callback */ -FT_DECLARE(ftdm_status_t) ftdm_span_trigger_signals(const ftdm_span_t *span); - -/*! \brief clear the tone detector state */ -FT_DECLARE(void) ftdm_channel_clear_detected_tones(ftdm_channel_t *ftdmchan); - -/*! \brief adjust echocanceller for beginning of call */ -FT_DECLARE(void) ftdm_set_echocancel_call_begin(ftdm_channel_t *chan); - -/*! \brief adjust echocanceller for end of call */ -FT_DECLARE(void) ftdm_set_echocancel_call_end(ftdm_channel_t *chan); - -/*! \brief save data from user */ -FT_DECLARE(ftdm_status_t) ftdm_channel_save_usrmsg(ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg); - -/*! \brief free usrmsg and variables/raw data attached to it */ -FT_DECLARE(ftdm_status_t) ftdm_usrmsg_free(ftdm_usrmsg_t **usrmsg); - -/*! \brief Get a custom variable from the user message - * \note The variable pointer returned is only valid while the before the event is processed and it'll be destroyed once the event is processed. */ -FT_DECLARE(const char *) ftdm_usrmsg_get_var(ftdm_usrmsg_t *usrmsg, const char *var_name); - -/*! \brief Get raw data from user message - * \param usrmsg The message structure containing the variables - * \param data data will point to available data pointer if available - * \param datalen datalen will be set to length of data available - * \retval FTDM_SUCCESS data is available - * \retval FTDM_FAIL no data available - * \note data is only valid within the duration of the callback, to receive a data pointer that does not get - * \note destroyed when callback returns, see ftdm_sigmsg_get_raw_data_detached - */ -FT_DECLARE(ftdm_status_t) ftdm_usrmsg_get_raw_data(ftdm_usrmsg_t *usrmsg, void **data, ftdm_size_t *datalen); - -/*! \brief free sigmsg and variables/raw data attached to it */ -FT_DECLARE(ftdm_status_t) ftdm_sigmsg_free(ftdm_sigmsg_t **sigmsg); - -/*! \brief Add a custom variable to the event - * \note This variables may be used by signaling modules to override signaling parameters - * \todo Document which signaling variables are available - * */ -FT_DECLARE(ftdm_status_t) ftdm_sigmsg_add_var(ftdm_sigmsg_t *sigmsg, const char *var_name, const char *value); - -/*! \brief Remove a custom variable from the event - * \note The variable pointer returned is only valid while the before the event is processed and it'll be destroyed once the event is processed. */ -FT_DECLARE(ftdm_status_t) ftdm_sigmsg_remove_var(ftdm_sigmsg_t *sigmsg, const char *var_name); - -/*! \brief Attach raw data to sigmsg - * \param sigmsg The message structure containing the variables - * \param data pointer to data - * \param datalen datalen length of data - * \retval FTDM_SUCCESS success, data was successfully saved - * \retval FTDM_FAIL failed, event already had data attached to it. - * \note data must have been allocated using ftdm_calloc, FreeTDM will free data once the usrmsg is processed. - */ -FT_DECLARE(ftdm_status_t) ftdm_sigmsg_set_raw_data(ftdm_sigmsg_t *sigmsg, void *data, ftdm_size_t datalen); - -/*! \brief Retrieve a span and channel data structure from a string in the format 'span_id:chan_id'*/ -FT_DECLARE(ftdm_status_t) ftdm_get_channel_from_string(const char *string_id, ftdm_span_t **out_span, ftdm_channel_t **out_channel); - -/*! - \brief Assert condition -*/ -#define ftdm_assert(assertion, msg) \ - if (!(assertion)) { \ - ftdm_log(FTDM_LOG_CRIT, "%s", msg); \ - if (g_ftdm_crash_policy & FTDM_CRASH_ON_ASSERT) { \ - ftdm_abort(); \ - } \ - } - -/*! - \brief Assert condition and return -*/ -#define ftdm_assert_return(assertion, retval, msg) \ - if (!(assertion)) { \ - ftdm_log(FTDM_LOG_CRIT, "%s", msg); \ - if (g_ftdm_crash_policy & FTDM_CRASH_ON_ASSERT) { \ - ftdm_abort(); \ - } else { \ - return retval; \ - } \ - } - -/*! - \brief Socket the given socket - \command it the socket -*/ -#define ftdm_socket_close(it) if (it > -1) { close(it); it = -1;} - -#define ftdm_channel_lock(chan) ftdm_mutex_lock((chan)->mutex) -#define ftdm_channel_unlock(chan) ftdm_mutex_unlock((chan)->mutex) - -#define ftdm_log_throttle(level, ...) \ - time_current_throttle_log = ftdm_current_time_in_ms(); \ - if (time_current_throttle_log - time_last_throttle_log > FTDM_THROTTLE_LOG_INTERVAL) {\ - ftdm_log(level, __VA_ARGS__); \ - time_last_throttle_log = time_current_throttle_log; \ - } - -#define ftdm_log_chan_ex(fchan, file, func, line, level, format, ...) ftdm_log(file, func, line, level, "[s%dc%d][%d:%d] " format, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, __VA_ARGS__) - -#define ftdm_log_chan_ex_msg(fchan, file, func, line, level, msg) ftdm_log(file, func, line, level, "[s%dc%d][%d:%d] " msg, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id) - -#define ftdm_log_chan(fchan, level, format, ...) ftdm_log(level, "[s%dc%d][%d:%d] " format, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, __VA_ARGS__) - -#define ftdm_log_chan_msg(fchan, level, msg) ftdm_log(level, "[s%dc%d][%d:%d] " msg, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id) - -#define ftdm_log_chan_throttle(fchan, level, format, ...) ftdm_log_throttle(level, "[s%dc%d][%d:%d] " format, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, __VA_ARGS__) -#define ftdm_log_chan_msg_throttle(fchan, level, format, ...) ftdm_log_throttle(level, "[s%dc%d][%d:%d] " format, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, __VA_ARGS__) - -#define ftdm_span_lock(span) ftdm_mutex_lock(span->mutex) -#define ftdm_span_unlock(span) ftdm_mutex_unlock(span->mutex) - -#define ftdm_test_and_set_media(fchan) \ - do { \ - if (!ftdm_test_flag((fchan), FTDM_CHANNEL_MEDIA)) { \ - ftdm_set_flag((fchan), FTDM_CHANNEL_MEDIA); \ - ftdm_set_echocancel_call_begin((fchan)); \ - if ((fchan)->dtmfdbg.requested) { \ - ftdm_channel_command((fchan), FTDM_COMMAND_ENABLE_DEBUG_DTMF, NULL); \ - } \ - } \ - } while (0); - -FT_DECLARE_DATA extern const char *FTDM_LEVEL_NAMES[9]; - -static __inline__ void ftdm_abort(void) -{ -#ifdef __cplusplus - ::abort(); -#else - abort(); -#endif -} - -static __inline__ int16_t ftdm_saturated_add(int16_t sample1, int16_t sample2) -{ - int addres; - - addres = sample1 + sample2; - if (addres > 32767) - addres = 32767; - else if (addres < -32767) - addres = -32767; - return (int16_t)addres; -} - -/* Bitmap helper functions */ -typedef long ftdm_bitmap_t; -#define FTDM_BITMAP_NBITS (sizeof(ftdm_bitmap_t) * 8) -#define ftdm_map_set_bit(map, bit) (map[(bit/FTDM_BITMAP_NBITS)] |= ((ftdm_bitmap_t)1 << (bit % FTDM_BITMAP_NBITS))) -#define ftdm_map_clear_bit(map, bit) (map[(bit/FTDM_BITMAP_NBITS)] &= ~((ftdm_bitmap_t)1 << (bit % FTDM_BITMAP_NBITS))) -#define ftdm_map_test_bit(map, bit) (map[(bit/FTDM_BITMAP_NBITS)] & ((ftdm_bitmap_t)1 << (bit % FTDM_BITMAP_NBITS))) - -#ifdef __cplusplus -} -#endif - -#endif /* endif __PRIVATE_FTDM_CORE__ */ diff --git a/libs/freetdm/src/include/private/ftdm_cpu_monitor.h b/libs/freetdm/src/include/private/ftdm_cpu_monitor.h deleted file mode 100644 index 249a5233c7..0000000000 --- a/libs/freetdm/src/include/private/ftdm_cpu_monitor.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * Moises Silva - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Contributors: - * David Yat Sin - * - */ - -/*! \brief opaque cpu stats structure */ -struct ftdm_cpu_monitor_stats; - -/*! - * \brief create a new cpu monitor - * \return profile timer structure previously created with new_profile_timer, NULL on error - */ -FT_DECLARE(struct ftdm_cpu_monitor_stats*) ftdm_new_cpu_monitor(void); - -/*! - * \brief Deletes cpu_monitor - */ -FT_DECLARE(void) ftdm_delete_cpu_monitor(struct ftdm_cpu_monitor_stats *p); - -/*! - * \brief provides the percentage of idle system time - * \param p cpu_stats structure previously created with ftdm_new_cpu_monitor - * \param pointer to store the percentage of idle time - * \return -1 on error 0 for success - */ -FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time (struct ftdm_cpu_monitor_stats *p, double *idle_percentage); - - - - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/include/private/ftdm_sched.h b/libs/freetdm/src/include/private/ftdm_sched.h deleted file mode 100644 index 020da9fb3b..0000000000 --- a/libs/freetdm/src/include/private/ftdm_sched.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * Moises Silva - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __FTDM_SCHED_H__ -#define __FTDM_SCHED_H__ - -#include "freetdm.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define FTDM_MICROSECONDS_PER_SECOND 1000000 - -typedef struct ftdm_sched ftdm_sched_t; -typedef void (*ftdm_sched_callback_t)(void *data); -typedef uint64_t ftdm_timer_id_t; - -/*! \brief Create a new scheduling context */ -FT_DECLARE(ftdm_status_t) ftdm_sched_create(ftdm_sched_t **sched, const char *name); - -/*! \brief Run the schedule to find timers that are expired and run its callbacks */ -FT_DECLARE(ftdm_status_t) ftdm_sched_run(ftdm_sched_t *sched); - -/*! \brief Run the schedule in its own thread. Callbacks will be called in a core thread. You *must* not block there! */ -FT_DECLARE(ftdm_status_t) ftdm_sched_free_run(ftdm_sched_t *sched); - -/*! - * \brief Schedule a new timer - * \param sched The scheduling context (required) - * \param name Timer name, typically unique but is not required to be unique, any null terminated string is fine (required) - * \param callback The callback to call upon timer expiration (required) - * \param data Optional data to pass to the callback - * \param timer Timer id pointer to store the id of the newly created timer. It can be null - * if you do not need to know the id, but you need this if you want to be able - * to cancel the timer with ftdm_sched_cancel_timer - */ -FT_DECLARE(ftdm_status_t) ftdm_sched_timer(ftdm_sched_t *sched, const char *name, - int ms, ftdm_sched_callback_t callback, void *data, ftdm_timer_id_t *timer); - -/*! - * \brief Cancel the timer - * Note that there is a race between cancelling and triggering a timer. - * By the time you call this function the timer may be about to be triggered. - * This is specially true with timers in free run schedule. - * \param sched The scheduling context (required) - * \param timer The timer to cancel (required) - */ -FT_DECLARE(ftdm_status_t) ftdm_sched_cancel_timer(ftdm_sched_t *sched, ftdm_timer_id_t timer); - -/*! \brief Destroy the context and all of the scheduled timers in it */ -FT_DECLARE(ftdm_status_t) ftdm_sched_destroy(ftdm_sched_t **sched); - -/*! - * \brief Calculate the time to the next timer and return it - * \param sched The sched context - * \param timeto The pointer to store the next timer time in milliseconds - */ -FT_DECLARE(ftdm_status_t) ftdm_sched_get_time_to_next_timer(const ftdm_sched_t *sched, int32_t *timeto); - -/*! \brief Global initialization, called just once, this is called by FreeTDM core, other users MUST not call it */ -FT_DECLARE(ftdm_status_t) ftdm_sched_global_init(void); - -/*! \brief Global destroy, called just once, this is called by FreeTDM core, other users MUST not call it */ -FT_DECLARE(ftdm_status_t) ftdm_sched_global_destroy(void); - -/*! \brief Checks if the main scheduling thread is running */ -FT_DECLARE(ftdm_bool_t) ftdm_free_sched_running(void); - -/*! \brief Stop the main scheduling thread (if running) */ -FT_DECLARE(ftdm_bool_t) ftdm_free_sched_stop(void); - -#ifdef __cplusplus -} -#endif - -#endif - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/include/private/ftdm_state.h b/libs/freetdm/src/include/private/ftdm_state.h deleted file mode 100644 index 733a561dcc..0000000000 --- a/libs/freetdm/src/include/private/ftdm_state.h +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * Moises Silva - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __FTDM_STATE_H__ -#define __FTDM_STATE_H__ - -/*! \file - * \brief State handling definitions - * \note Most, if not all of the state handling functions assume you have a lock acquired. Touching the channel - * state is a sensitive matter that requires checks and careful thought and is typically a process that - * is not encapsulated within a single function, therefore the lock must be explicitly acquired by the - * caller (most of the time, signaling modules), process states, set a new state and process it, and - * finally unlock the channel. See docs/locking.txt fore more info - */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - FTDM_CHANNEL_STATE_ANY = -1, - FTDM_CHANNEL_STATE_END = -1, - FTDM_CHANNEL_STATE_DOWN, - FTDM_CHANNEL_STATE_HOLD, - FTDM_CHANNEL_STATE_SUSPENDED, - FTDM_CHANNEL_STATE_DIALTONE, - FTDM_CHANNEL_STATE_COLLECT, - FTDM_CHANNEL_STATE_RING, - FTDM_CHANNEL_STATE_RINGING, - FTDM_CHANNEL_STATE_BUSY, - FTDM_CHANNEL_STATE_ATTN, - FTDM_CHANNEL_STATE_GENRING, - FTDM_CHANNEL_STATE_DIALING, - FTDM_CHANNEL_STATE_GET_CALLERID, - FTDM_CHANNEL_STATE_CALLWAITING, - FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_PROCEED, - FTDM_CHANNEL_STATE_PROGRESS, - FTDM_CHANNEL_STATE_PROGRESS_MEDIA, - FTDM_CHANNEL_STATE_UP, - FTDM_CHANNEL_STATE_TRANSFER, - FTDM_CHANNEL_STATE_IDLE, - FTDM_CHANNEL_STATE_TERMINATING, - FTDM_CHANNEL_STATE_CANCEL, - FTDM_CHANNEL_STATE_HANGUP, - FTDM_CHANNEL_STATE_HANGUP_COMPLETE, - FTDM_CHANNEL_STATE_IN_LOOP, - FTDM_CHANNEL_STATE_RESET, - FTDM_CHANNEL_STATE_INVALID -} ftdm_channel_state_t; -/* Purposely not adding ANY (-1) and END (-1) since FTDM_STR2ENUM_P works only on enums starting at zero */ -#define CHANNEL_STATE_STRINGS "DOWN", "HOLD", "SUSPENDED", "DIALTONE", "COLLECT", \ - "RING", "RINGING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \ - "RESTART", "PROCEED", "PROGRESS", "PROGRESS_MEDIA", "UP", "TRANSFER", "IDLE", "TERMINATING", "CANCEL", \ - "HANGUP", "HANGUP_COMPLETE", "IN_LOOP", "RESET", "INVALID" -FTDM_STR2ENUM_P(ftdm_str2ftdm_channel_state, ftdm_channel_state2str, ftdm_channel_state_t) - -typedef struct { - const char *file; - const char *func; - int line; - ftdm_channel_state_t state; /*!< Current state (processed or not) */ - ftdm_channel_state_t last_state; /*!< Previous state */ - ftdm_time_t time; /*!< Time the state was set */ - ftdm_time_t end_time; /*!< Time the state processing was completed */ -} ftdm_state_history_entry_t; - -typedef ftdm_status_t (*ftdm_channel_state_processor_t)(ftdm_channel_t *fchan); - -/*! - * \brief Process channel states by invoking the channel state processing routine - * it will keep calling the processing routine while the state status - * is FTDM_STATE_STATUS_NEW, it will not do anything otherwise - */ -FT_DECLARE(ftdm_status_t) ftdm_channel_advance_states(ftdm_channel_t *fchan); - -FT_DECLARE(ftdm_status_t) _ftdm_channel_complete_state(const char *file, const char *function, int line, ftdm_channel_t *fchan); -#define ftdm_channel_complete_state(obj) _ftdm_channel_complete_state(__FILE__, __FTDM_FUNC__, __LINE__, obj) -FT_DECLARE(int) ftdm_check_state_all(ftdm_span_t *span, ftdm_channel_state_t state); - -/*! - * \brief Status of the current channel state - * \note A given state goes thru several status (yes, states for the state!) - * The order is always FTDM_STATE_STATUS_NEW -> FTDM_STATE_STATUS_PROCESSED -> FTDM_STATUS_COMPLETED - * However, is possible to go from NEW -> COMPLETED directly when the signaling module explicitly changes - * the state of the channel in the middle of processing the current state by calling the ftdm_set_state() API - * - * FTDM_STATE_STATUS_NEW - - * Someone just set the state of the channel, either the signaling module or the user (implicitly through a call API). - * This is accomplished by calling ftdm_channel_set_state() which changes the 'state' and 'last_state' memebers of - * the ftdm_channel_t structure. - * - * FTDM_STATE_STATUS_PROCESSED - - * The signaling module did something based on the new state. - * - * This is accomplished via ftdm_channel_advance_states() - * - * When ftdm_channel_advance_states(), at the very least, if the channel has its state in FTDM_STATE_STATUS_NEW, it - * will move to FTDM_STATE_STATUS_PROCESSED, depending on what the signaling module does during the processing - * the state may move to FTDM_STATE_STATUS_COMPLETED right after or wait for a signaling specific event to complete it. - * It is also possible that more state transitions occur during the execution of ftdm_channel_advance_states() if one - * state processing/completion leads to another state change, the function will not return until the chain of events - * lead to a state that is not in FTDM_STATE_STATUS_NEW - * - * FTDM_STATE_STATUS_COMPLETED - - * The signaling module completed the processing of the state and there is nothing further to be done for this state. - * - * This is accomplished either explicitly by the signaling module by calling ftdm_channel_complete_state() or by - * the signaling module implicitly by trying to set the state of the channel to a new state via ftdm_set_state() - * - * When working with blocking channels (FTDM_CHANNEL_NONBLOCK flag not set), the user thread is signaled and unblocked - * so it can continue. - * - * When a state moves to this status is also possible for a signal FTDM_SIGEVENT_INDICATION_COMPLETED to be delivered - * by the core if the state change was associated to an indication requested by the user, - */ -typedef enum { - FTDM_STATE_STATUS_NEW, - FTDM_STATE_STATUS_PROCESSED, - FTDM_STATE_STATUS_COMPLETED, - FTDM_STATE_STATUS_INVALID -} ftdm_state_status_t; -#define CHANNEL_STATE_STATUS_STRINGS "NEW", "PROCESSED", "COMPLETED", "INVALID" -FTDM_STR2ENUM_P(ftdm_str2ftdm_state_status, ftdm_state_status2str, ftdm_state_status_t) - -typedef enum { - ZSM_NONE, - ZSM_UNACCEPTABLE, - ZSM_ACCEPTABLE -} ftdm_state_map_type_t; - -typedef enum { - ZSD_INBOUND, - ZSD_OUTBOUND, -} ftdm_state_direction_t; - -#define FTDM_MAP_NODE_SIZE 512 -#define FTDM_MAP_MAX FTDM_CHANNEL_STATE_INVALID+2 - -struct ftdm_state_map_node { - ftdm_state_direction_t direction; - ftdm_state_map_type_t type; - ftdm_channel_state_t check_states[FTDM_MAP_MAX]; - ftdm_channel_state_t states[FTDM_MAP_MAX]; -}; -typedef struct ftdm_state_map_node ftdm_state_map_node_t; - -struct ftdm_state_map { - ftdm_state_map_node_t nodes[FTDM_MAP_NODE_SIZE]; -}; -typedef struct ftdm_state_map ftdm_state_map_t; - -/*!\brief Cancel the state processing for a channel (the channel must be locked when calling this function) - * \note Only the core should use this function - */ -FT_DECLARE(ftdm_status_t) ftdm_channel_cancel_state(const char *file, const char *func, int line, - ftdm_channel_t *ftdmchan); - -/*!\brief Set the state for a channel (the channel must be locked when calling this function) - * \note Signaling modules should use ftdm_set_state macro instead - * \note If this function is called with the wait parameter set to a non-zero value, the recursivity - * of the channel lock must be == 1 because the channel will be unlocked/locked when waiting */ -FT_DECLARE(ftdm_status_t) ftdm_channel_set_state(const char *file, const char *func, int line, - ftdm_channel_t *ftdmchan, ftdm_channel_state_t state, int wait, ftdm_usrmsg_t *usrmsg); - -/*!\brief Set the state of a channel immediately and implicitly complete the previous state if needed - * \note FTDM_SIGEVENT_INDICATION_COMPLETED will be sent if the state change - * is associated to some indication (ie FTDM_CHANNEL_INDICATE_PROCEED) - * \note The channel must be locked when calling this function - * */ -FT_DECLARE(ftdm_status_t) _ftdm_set_state(const char *file, const char *func, int line, - ftdm_channel_t *fchan, ftdm_channel_state_t state); -#define ftdm_set_state(obj, s) _ftdm_set_state(__FILE__, __FTDM_FUNC__, __LINE__, obj, s); \ - -/*!\brief This macro is deprecated, signaling modules should always lock the channel themselves anyways since they must - * process first the user pending state changes then set a new state before releasing the lock - * this macro is here for backwards compatibility, DO NOT USE IT in new code since it is *always* wrong to set - * a state in a signaling module without checking and processing the current state first (and for that you must lock the channel) - */ -#define ftdm_set_state_locked(obj, s) \ - do { \ - ftdm_channel_lock(obj); \ - ftdm_channel_set_state(__FILE__, __FTDM_FUNC__, __LINE__, obj, s, 0, NULL); \ - ftdm_channel_unlock(obj); \ - } while(0); - -#define ftdm_set_state_r(obj, s, r) r = ftdm_channel_set_state(__FILE__, __FTDM_FUNC__, __LINE__, obj, s, 0); - -#define ftdm_set_state_all(span, state) \ - do { \ - uint32_t _j; \ - ftdm_mutex_lock((span)->mutex); \ - for(_j = 1; _j <= (span)->chan_count; _j++) { \ - if (!FTDM_IS_DCHAN(span->channels[_j])) { \ - ftdm_set_state_locked((span->channels[_j]), state); \ - } \ - } \ - ftdm_mutex_unlock((span)->mutex); \ - } while (0); - -#ifdef __cplusplus -} -#endif - -#endif - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h deleted file mode 100755 index a498489af1..0000000000 --- a/libs/freetdm/src/include/private/ftdm_types.h +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Contributors: - * - * Moises Silva - * - */ - -#ifndef FTDM_TYPES_H -#define FTDM_TYPES_H - -#include "freetdm.h" - -#include "fsk.h" - -#ifdef WIN32 -typedef intptr_t ftdm_ssize_t; -typedef int ftdm_filehandle_t; -#else -#include -#include -#include -typedef ssize_t ftdm_ssize_t; -typedef int ftdm_filehandle_t; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#define FTDM_COMMAND_OBJ_SIZE *((ftdm_size_t *)obj) -#define FTDM_COMMAND_OBJ_INT *((int *)obj) -#define FTDM_COMMAND_OBJ_CHAR_P (char *)obj -#define FTDM_COMMAND_OBJ_FLOAT *(float *)obj -#define FTDM_FSK_MOD_FACTOR 0x10000 -#define FTDM_DEFAULT_DTMF_ON 250 -#define FTDM_DEFAULT_DTMF_OFF 50 - -typedef enum { - FTDM_ENDIAN_BIG = 1, - FTDM_ENDIAN_LITTLE = -1 -} ftdm_endian_t; - -typedef enum { - FTDM_CID_TYPE_SDMF = 0x04, - FTDM_CID_TYPE_MDMF = 0x80 -} ftdm_cid_type_t; - -typedef enum { - MDMF_DATETIME = 1, - MDMF_PHONE_NUM = 2, - MDMF_DDN = 3, - MDMF_NO_NUM = 4, - MDMF_PHONE_NAME = 7, - MDMF_NO_NAME = 8, - MDMF_ALT_ROUTE = 9, - MDMF_INVALID = 10 -} ftdm_mdmf_type_t; -#define MDMF_STRINGS "X", "DATETIME", "PHONE_NUM", "DDN", "NO_NUM", "X", "X", "PHONE_NAME", "NO_NAME", "ALT_ROUTE", "INVALID" -FTDM_STR2ENUM_P(ftdm_str2ftdm_mdmf_type, ftdm_mdmf_type2str, ftdm_mdmf_type_t) - -#define FTDM_TONEMAP_LEN 128 -typedef enum { - FTDM_TONEMAP_NONE, - FTDM_TONEMAP_DIAL, - FTDM_TONEMAP_RING, - FTDM_TONEMAP_BUSY, - FTDM_TONEMAP_FAIL1, - FTDM_TONEMAP_FAIL2, - FTDM_TONEMAP_FAIL3, - FTDM_TONEMAP_ATTN, - FTDM_TONEMAP_CALLWAITING_CAS, - FTDM_TONEMAP_CALLWAITING_SAS, - FTDM_TONEMAP_CALLWAITING_ACK, - FTDM_TONEMAP_INVALID -} ftdm_tonemap_t; -#define TONEMAP_STRINGS "NONE", "DIAL", "RING", "BUSY", "FAIL1", "FAIL2", "FAIL3", "ATTN", "CALLWAITING-CAS", "CALLWAITING-SAS", "CALLWAITING-ACK", "INVALID" -FTDM_STR2ENUM_P(ftdm_str2ftdm_tonemap, ftdm_tonemap2str, ftdm_tonemap_t) - -typedef enum { - FTDM_ANALOG_START_KEWL, - FTDM_ANALOG_START_LOOP, - FTDM_ANALOG_START_GROUND, - FTDM_ANALOG_START_WINK, - FTDM_ANALOG_START_NA -} ftdm_analog_start_type_t; -#define START_TYPE_STRINGS "KEWL", "LOOP", "GROUND", "WINK", "NA" -FTDM_STR2ENUM_P(ftdm_str2ftdm_analog_start_type, ftdm_analog_start_type2str, ftdm_analog_start_type_t) - -typedef enum { - FTDM_OOB_NOOP, - FTDM_OOB_ONHOOK, - FTDM_OOB_OFFHOOK, - FTDM_OOB_WINK, - FTDM_OOB_FLASH, - FTDM_OOB_RING_START, - FTDM_OOB_RING_STOP, - FTDM_OOB_ALARM_TRAP, - FTDM_OOB_ALARM_CLEAR, - FTDM_OOB_CAS_BITS_CHANGE, - FTDM_OOB_POLARITY_REVERSE, - FTDM_OOB_INVALID -} ftdm_oob_event_t; -#define OOB_STRINGS "NOOP", "ONHOOK", "OFFHOOK", "WINK", "FLASH", "RING_START", "RING_STOP", "ALARM_TRAP", "ALARM_CLEAR", "CAS_BITS_CHANGE", "POLARITY_REVERSE", "INVALID" -FTDM_STR2ENUM_P(ftdm_str2ftdm_oob_event, ftdm_oob_event2str, ftdm_oob_event_t) - -/*! \brief Event types */ -typedef enum { - FTDM_EVENT_NONE, - /* DTMF digit was just detected */ - FTDM_EVENT_DTMF, - /* Out of band event */ - FTDM_EVENT_OOB, - FTDM_EVENT_COUNT -} ftdm_event_type_t; - -/*! \brief Generic event data type */ -struct ftdm_event { - ftdm_event_type_t e_type; - uint32_t enum_id; - ftdm_channel_t *channel; - void *data; -}; - -typedef enum { - FTDM_SIGTYPE_NONE, - FTDM_SIGTYPE_ISDN, - FTDM_SIGTYPE_RBS, - FTDM_SIGTYPE_ANALOG, - FTDM_SIGTYPE_SANGOMABOOST, - FTDM_SIGTYPE_M3UA, - FTDM_SIGTYPE_M2UA, - FTDM_SIGTYPE_R2, - FTDM_SIGTYPE_SS7, - FTDM_SIGTYPE_GSM -} ftdm_signal_type_t; - -typedef enum { - FTDM_SPAN_CONFIGURED = (1 << 0), - FTDM_SPAN_STARTED = (1 << 1), - FTDM_SPAN_STATE_CHANGE = (1 << 2), - FTDM_SPAN_SUSPENDED = (1 << 3), - FTDM_SPAN_IN_THREAD = (1 << 4), - FTDM_SPAN_STOP_THREAD = (1 << 5), - /*! Signaling modules set this flag to use fchan->pendingchans queue instead - * of the FTDM_SPAN_STATE_CHANGE flag to detect when there is channels with - * a state change pending in the span. If you set this member you can't rely - * on FTDM_SPAN_STATE_CHANGE anymore and must use the queue only instead. This - * is the new way of detecting state changes, new modules should always set this - * flag, the old modules still relying on FTDM_SPAN_STATE_CHANGE should be updated */ - FTDM_SPAN_USE_CHAN_QUEUE = (1 << 6), - FTDM_SPAN_SUGGEST_CHAN_ID = (1 << 7), - FTDM_SPAN_USE_AV_RATE = (1 << 8), - FTDM_SPAN_PWR_SAVING = (1 << 9), - /* If you use this flag, you MUST call ftdm_span_trigger_signals to deliver the user signals - * after having called ftdm_send_span_signal(), which with this flag it will just enqueue the signal - * for later delivery */ - FTDM_SPAN_USE_SIGNALS_QUEUE = (1 << 10), - /* If this flag is set, channel will be moved to proceed state when calls goes to routing */ - FTDM_SPAN_USE_PROCEED_STATE = (1 << 11), - /* If this flag is set, the signalling module supports jumping directly to state up, without - going through PROGRESS/PROGRESS_MEDIA */ - FTDM_SPAN_USE_SKIP_STATES = (1 << 12), - /* If this flag is set, then this span cannot be stopped individually, it can only be stopped - on freetdm unload */ - FTDM_SPAN_NON_STOPPABLE = (1 << 13), - /* If this flag is set, then this span supports TRANSFER state */ - FTDM_SPAN_USE_TRANSFER = (1 << 14), - /* This is the last flag, no more flags bigger than this */ - FTDM_SPAN_MAX_FLAG = (1 << 15), -} ftdm_span_flag_t; - -/*! \brief Channel supported features */ -typedef enum { - FTDM_CHANNEL_FEATURE_DTMF_DETECT = (1 << 0), /*!< Channel can detect DTMF (read-only) */ - FTDM_CHANNEL_FEATURE_DTMF_GENERATE = (1 << 1), /*!< Channel can generate DTMF (read-only) */ - FTDM_CHANNEL_FEATURE_CODECS = (1 << 2), /*!< Channel can do transcoding (read-only) */ - FTDM_CHANNEL_FEATURE_INTERVAL = (1 << 3), /*!< Channel support i/o interval configuration (read-only) */ - FTDM_CHANNEL_FEATURE_CALLERID = (1 << 4), /*!< Channel can detect caller id (read-only) */ - FTDM_CHANNEL_FEATURE_PROGRESS = (1 << 5), /*!< Channel can detect inband progress (read-only) */ - FTDM_CHANNEL_FEATURE_CALLWAITING = (1 << 6), /*!< Channel will allow call waiting (ie: FXS devices) (read/write) */ - FTDM_CHANNEL_FEATURE_HWEC = (1<<7), /*!< Channel has a hardware echo canceller */ - FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE = (1<<8), /*!< hardware echo canceller is disabled when there are no calls on this channel */ - FTDM_CHANNEL_FEATURE_IO_STATS = (1<<9), /*!< Channel supports IO statistics (HDLC channels only) */ - FTDM_CHANNEL_FEATURE_MF_GENERATE = (1<<10), /*!< Channel can generate R2 MF tones (read-only) */ -} ftdm_channel_feature_t; - -/*! \brief Channel IO pending flags */ -typedef enum { - FTDM_CHANNEL_IO_EVENT = (1 << 0), - FTDM_CHANNEL_IO_READ = (1 << 1), - FTDM_CHANNEL_IO_WRITE = (1 << 2), -} ftdm_channel_io_flags_t; - -/*!< Channel flags. This used to be an enum but we reached the 32bit limit for enums, is safer this way */ -#define FTDM_CHANNEL_CONFIGURED (1ULL << 0) -#define FTDM_CHANNEL_READY (1ULL << 1) -#define FTDM_CHANNEL_OPEN (1ULL << 2) -#define FTDM_CHANNEL_DTMF_DETECT (1ULL << 3) -#define FTDM_CHANNEL_SUPRESS_DTMF (1ULL << 4) -#define FTDM_CHANNEL_TRANSCODE (1ULL << 5) -#define FTDM_CHANNEL_BUFFER (1ULL << 6) -#define FTDM_CHANNEL_INTHREAD (1ULL << 8) -#define FTDM_CHANNEL_WINK (1ULL << 9) -#define FTDM_CHANNEL_FLASH (1ULL << 10) -#define FTDM_CHANNEL_STATE_CHANGE (1ULL << 11) -#define FTDM_CHANNEL_HOLD (1ULL << 12) -#define FTDM_CHANNEL_INUSE (1ULL << 13) -#define FTDM_CHANNEL_OFFHOOK (1ULL << 14) -#define FTDM_CHANNEL_RINGING (1ULL << 15) -#define FTDM_CHANNEL_PROGRESS_DETECT (1ULL << 16) -#define FTDM_CHANNEL_CALLERID_DETECT (1ULL << 17) -#define FTDM_CHANNEL_OUTBOUND (1ULL << 18) -#define FTDM_CHANNEL_SUSPENDED (1ULL << 19) -#define FTDM_CHANNEL_3WAY (1ULL << 20) -#define FTDM_CHANNEL_PROGRESS (1ULL << 21) -/*!< There is media on the channel already */ -#define FTDM_CHANNEL_MEDIA (1ULL << 22) -/*!< The channel was answered */ -#define FTDM_CHANNEL_ANSWERED (1ULL << 23) -#define FTDM_CHANNEL_MUTE (1ULL << 24) -#define FTDM_CHANNEL_USE_RX_GAIN (1ULL << 25) -#define FTDM_CHANNEL_USE_TX_GAIN (1ULL << 26) -#define FTDM_CHANNEL_IN_ALARM (1ULL << 27) -#define FTDM_CHANNEL_SIG_UP (1ULL << 28) -#define FTDM_CHANNEL_USER_HANGUP (1ULL << 29) -#define FTDM_CHANNEL_RX_DISABLED (1ULL << 30) -#define FTDM_CHANNEL_TX_DISABLED (1ULL << 31) -/*!< The user knows about a call in this channel */ -#define FTDM_CHANNEL_CALL_STARTED (1ULL << 32) -/*!< The user wants non-blocking operations in the channel */ -#define FTDM_CHANNEL_NONBLOCK (1ULL << 33) -/*!< There is a pending acknowledge for an indication */ -#define FTDM_CHANNEL_IND_ACK_PENDING (1ULL << 34) -/*!< There is someone blocking in the channel waiting for state completion */ -#define FTDM_CHANNEL_BLOCKING (1ULL << 35) -/*!< Media is digital */ -#define FTDM_CHANNEL_DIGITAL_MEDIA (1ULL << 36) -/*!< Native signaling bridge is enabled */ -#define FTDM_CHANNEL_NATIVE_SIGBRIDGE (1ULL << 37) -/*!< Native signaling DTMF detection */ -#define FTDM_CHANNEL_SIG_DTMF_DETECTION (1ULL << 38) - -/*!< This no more flags after this flag */ -#define FTDM_CHANNEL_MAX_FLAG (1ULL << 39) -/*! - * - * Copyright (C) 2001 Steve Underwood - * - * Despite my general liking of the GPL, I place this code in the - * public domain for the benefit of all mankind - even the slimy - * ones who might try to proprietize my work and use it to my - * detriment. - * - * $Id: g711.h,v 1.1 2006/06/07 15:46:39 steveu Exp $ - */ - -/*! \file */ - -/*! \page g711_page A-law and mu-law handling - Lookup tables for A-law and u-law look attractive, until you consider the impact - on the CPU cache. If it causes a substantial area of your processor cache to get - hit too often, cache sloshing will severely slow things down. The main reason - these routines are slow in C, is the lack of direct access to the CPU's "find - the first 1" instruction. A little in-line assembler fixes that, and the - conversion routines can be faster than lookup tables, in most real world usage. - A "find the first 1" instruction is available on most modern CPUs, and is a - much underused feature. - - If an assembly language method of bit searching is not available, these routines - revert to a method that can be a little slow, so the cache thrashing might not - seem so bad :( - - Feel free to submit patches to add fast "find the first 1" support for your own - favourite processor. - - Look up tables are used for transcoding between A-law and u-law, since it is - difficult to achieve the precise transcoding procedure laid down in the G.711 - specification by other means. -*/ - -#if !defined(_G711_H_) -#define _G711_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _MSC_VER -#ifndef __inline__ -#define __inline__ __inline -#endif - typedef unsigned __int8 uint8_t; - typedef __int16 int16_t; - typedef __int32 int32_t; - typedef unsigned __int16 uint16_t; -#else -#include -#endif - -#if defined(__i386__) - /*! \brief Find the bit position of the highest set bit in a word - \param bits The word to be searched - \return The bit number of the highest set bit, or -1 if the word is zero. */ - static __inline__ int top_bit(unsigned int bits) - { - int res; - - __asm__ __volatile__(" movl $-1,%%edx;\n" - " bsrl %%eax,%%edx;\n" - : "=d" (res) - : "a" (bits)); - return res; - } - /*- End of function --------------------------------------------------------*/ - - /*! \brief Find the bit position of the lowest set bit in a word - \param bits The word to be searched - \return The bit number of the lowest set bit, or -1 if the word is zero. */ - static __inline__ int bottom_bit(unsigned int bits) - { - int res; - - __asm__ __volatile__(" movl $-1,%%edx;\n" - " bsfl %%eax,%%edx;\n" - : "=d" (res) - : "a" (bits)); - return res; - } - /*- End of function --------------------------------------------------------*/ -#elif defined(__x86_64__) - static __inline__ int top_bit(unsigned int bits) - { - int res; - - __asm__ __volatile__(" movq $-1,%%rdx;\n" - " bsrq %%rax,%%rdx;\n" - : "=d" (res) - : "a" (bits)); - return res; - } - /*- End of function --------------------------------------------------------*/ - - static __inline__ int bottom_bit(unsigned int bits) - { - int res; - - __asm__ __volatile__(" movq $-1,%%rdx;\n" - " bsfq %%rax,%%rdx;\n" - : "=d" (res) - : "a" (bits)); - return res; - } - /*- End of function --------------------------------------------------------*/ -#else - static __inline__ int top_bit(unsigned int bits) - { - int i; - - if (bits == 0) - return -1; - i = 0; - if (bits & 0xFFFF0000) - { - bits &= 0xFFFF0000; - i += 16; - } - if (bits & 0xFF00FF00) - { - bits &= 0xFF00FF00; - i += 8; - } - if (bits & 0xF0F0F0F0) - { - bits &= 0xF0F0F0F0; - i += 4; - } - if (bits & 0xCCCCCCCC) - { - bits &= 0xCCCCCCCC; - i += 2; - } - if (bits & 0xAAAAAAAA) - { - bits &= 0xAAAAAAAA; - i += 1; - } - return i; - } - /*- End of function --------------------------------------------------------*/ - - static __inline__ int bottom_bit(unsigned int bits) - { - int i; - - if (bits == 0) - return -1; - i = 32; - if (bits & 0x0000FFFF) - { - bits &= 0x0000FFFF; - i -= 16; - } - if (bits & 0x00FF00FF) - { - bits &= 0x00FF00FF; - i -= 8; - } - if (bits & 0x0F0F0F0F) - { - bits &= 0x0F0F0F0F; - i -= 4; - } - if (bits & 0x33333333) - { - bits &= 0x33333333; - i -= 2; - } - if (bits & 0x55555555) - { - bits &= 0x55555555; - i -= 1; - } - return i; - } - /*- End of function --------------------------------------------------------*/ -#endif - - /* N.B. It is tempting to use look-up tables for A-law and u-law conversion. - * However, you should consider the cache footprint. - * - * A 64K byte table for linear to x-law and a 512 byte table for x-law to - * linear sound like peanuts these days, and shouldn't an array lookup be - * real fast? No! When the cache sloshes as badly as this one will, a tight - * calculation may be better. The messiest part is normally finding the - * segment, but a little inline assembly can fix that on an i386, x86_64 and - * many other modern processors. - */ - - /* - * Mu-law is basically as follows: - * - * Biased Linear Input Code Compressed Code - * ------------------------ --------------- - * 00000001wxyza 000wxyz - * 0000001wxyzab 001wxyz - * 000001wxyzabc 010wxyz - * 00001wxyzabcd 011wxyz - * 0001wxyzabcde 100wxyz - * 001wxyzabcdef 101wxyz - * 01wxyzabcdefg 110wxyz - * 1wxyzabcdefgh 111wxyz - * - * Each biased linear code has a leading 1 which identifies the segment - * number. The value of the segment number is equal to 7 minus the number - * of leading 0's. The quantization interval is directly available as the - * four bits wxyz. * The trailing bits (a - h) are ignored. - * - * Ordinarily the complement of the resulting code word is used for - * transmission, and so the code word is complemented before it is returned. - * - * For further information see John C. Bellamy's Digital Telephony, 1982, - * John Wiley & Sons, pps 98-111 and 472-476. - */ - - /*#define ULAW_ZEROTRAP*/ /* turn on the trap as per the MIL-STD */ -#define ULAW_BIAS 0x84 /* Bias for linear code. */ - - /*! \brief Encode a linear sample to u-law - \param linear The sample to encode. - \return The u-law value. - */ - static __inline__ uint8_t linear_to_ulaw(int linear) - { - uint8_t u_val; - int mask; - int seg; - - /* Get the sign and the magnitude of the value. */ - if (linear < 0) - { - linear = ULAW_BIAS - linear; - mask = 0x7F; - } - else - { - linear = ULAW_BIAS + linear; - mask = 0xFF; - } - - seg = top_bit(linear | 0xFF) - 7; - - /* - * Combine the sign, segment, quantization bits, - * and complement the code word. - */ - if (seg >= 8) - u_val = (uint8_t) (0x7F ^ mask); - else - u_val = (uint8_t) (((seg << 4) | ((linear >> (seg + 3)) & 0xF)) ^ mask); -#ifdef ULAW_ZEROTRAP - /* Optional ITU trap */ - if (u_val == 0) - u_val = 0x02; -#endif - return u_val; - } - /*- End of function --------------------------------------------------------*/ - - /*! \brief Decode an u-law sample to a linear value. - \param ulaw The u-law sample to decode. - \return The linear value. - */ - static __inline__ int16_t ulaw_to_linear(uint8_t ulaw) - { - int t; - - /* Complement to obtain normal u-law value. */ - ulaw = ~ulaw; - /* - * Extract and bias the quantization bits. Then - * shift up by the segment number and subtract out the bias. - */ - t = (((ulaw & 0x0F) << 3) + ULAW_BIAS) << (((int) ulaw & 0x70) >> 4); - return (int16_t) ((ulaw & 0x80) ? (ULAW_BIAS - t) : (t - ULAW_BIAS)); - } - /*- End of function --------------------------------------------------------*/ - - /* - * A-law is basically as follows: - * - * Linear Input Code Compressed Code - * ----------------- --------------- - * 0000000wxyza 000wxyz - * 0000001wxyza 001wxyz - * 000001wxyzab 010wxyz - * 00001wxyzabc 011wxyz - * 0001wxyzabcd 100wxyz - * 001wxyzabcde 101wxyz - * 01wxyzabcdef 110wxyz - * 1wxyzabcdefg 111wxyz - * - * For further information see John C. Bellamy's Digital Telephony, 1982, - * John Wiley & Sons, pps 98-111 and 472-476. - */ - -#define ALAW_AMI_MASK 0x55 - - /*! \brief Encode a linear sample to A-law - \param linear The sample to encode. - \return The A-law value. - */ - static __inline__ uint8_t linear_to_alaw(int linear) - { - int mask; - int seg; - - if (linear >= 0) - { - /* Sign (bit 7) bit = 1 */ - mask = ALAW_AMI_MASK | 0x80; - } - else - { - /* Sign (bit 7) bit = 0 */ - mask = ALAW_AMI_MASK; - linear = -linear - 8; - } - - /* Convert the scaled magnitude to segment number. */ - seg = top_bit(linear | 0xFF) - 7; - if (seg >= 8) - { - if (linear >= 0) - { - /* Out of range. Return maximum value. */ - return (uint8_t) (0x7F ^ mask); - } - /* We must be just a tiny step below zero */ - return (uint8_t) (0x00 ^ mask); - } - /* Combine the sign, segment, and quantization bits. */ - return (uint8_t) (((seg << 4) | ((linear >> ((seg) ? (seg + 3) : 4)) & 0x0F)) ^ mask); - } - /*- End of function --------------------------------------------------------*/ - - /*! \brief Decode an A-law sample to a linear value. - \param alaw The A-law sample to decode. - \return The linear value. - */ - static __inline__ int16_t alaw_to_linear(uint8_t alaw) - { - int i; - int seg; - - alaw ^= ALAW_AMI_MASK; - i = ((alaw & 0x0F) << 4); - seg = (((int) alaw & 0x70) >> 4); - if (seg) - i = (i + 0x108) << (seg - 1); - else - i += 8; - return (int16_t) ((alaw & 0x80) ? i : -i); - } - /*- End of function --------------------------------------------------------*/ - - /*! \brief Transcode from A-law to u-law, using the procedure defined in G.711. - \param alaw The A-law sample to transcode. - \return The best matching u-law value. - */ - uint8_t alaw_to_ulaw(uint8_t alaw); - - /*! \brief Transcode from u-law to A-law, using the procedure defined in G.711. - \param alaw The u-law sample to transcode. - \return The best matching A-law value. - */ - uint8_t ulaw_to_alaw(uint8_t ulaw); - -#ifdef __cplusplus -} -#endif - -#endif -/*- End of file ------------------------------------------------------------*/ - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/include/private/hashtable.h b/libs/freetdm/src/include/private/hashtable.h deleted file mode 100644 index 5d029b5b85..0000000000 --- a/libs/freetdm/src/include/private/hashtable.h +++ /dev/null @@ -1,235 +0,0 @@ -/* Copyright (C) 2002 Christopher Clark */ - -#ifndef __HASHTABLE_CWC22_H__ -#define __HASHTABLE_CWC22_H__ -#ifdef _MSC_VER -#ifndef __inline__ -#define __inline__ __inline -#endif -#endif -#include "freetdm.h" - -#ifdef __cplusplus -extern "C" { -#endif -struct hashtable; -struct hashtable_iterator; - -/* Example of use: - * - * struct hashtable *h; - * struct some_key *k; - * struct some_value *v; - * - * static unsigned int hash_from_key_fn( void *k ); - * static int keys_equal_fn ( void *key1, void *key2 ); - * - * h = create_hashtable(16, hash_from_key_fn, keys_equal_fn); - * k = (struct some_key *) malloc(sizeof(struct some_key)); - * v = (struct some_value *) malloc(sizeof(struct some_value)); - * - * (initialise k and v to suitable values) - * - * if (! hashtable_insert(h,k,v) ) - * { exit(-1); } - * - * if (NULL == (found = hashtable_search(h,k) )) - * { printf("not found!"); } - * - * if (NULL == (found = hashtable_remove(h,k) )) - * { printf("Not found\n"); } - * - */ - -/* Macros may be used to define type-safe(r) hashtable access functions, with - * methods specialized to take known key and value types as parameters. - * - * Example: - * - * Insert this at the start of your file: - * - * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value); - * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value); - * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value); - * - * This defines the functions 'insert_some', 'search_some' and 'remove_some'. - * These operate just like hashtable_insert etc., with the same parameters, - * but their function signatures have 'struct some_key *' rather than - * 'void *', and hence can generate compile time errors if your program is - * supplying incorrect data as a key (and similarly for value). - * - * Note that the hash and key equality functions passed to create_hashtable - * still take 'void *' parameters instead of 'some key *'. This shouldn't be - * a difficult issue as they're only defined and passed once, and the other - * functions will ensure that only valid keys are supplied to them. - * - * The cost for this checking is increased code size and runtime overhead - * - if performance is important, it may be worth switching back to the - * unsafe methods once your program has been debugged with the safe methods. - * This just requires switching to some simple alternative defines - eg: - * #define insert_some hashtable_insert - * - */ - -/***************************************************************************** - * create_hashtable - - * @name create_hashtable - * @param minsize minimum initial size of hashtable - * @param hashfunction function for hashing keys - * @param key_eq_fn function for determining key equality - * @return newly created hashtable or NULL on failure - */ - -FT_DECLARE(struct hashtable *) -create_hashtable(unsigned int minsize, - unsigned int (*hashfunction) (void*), - int (*key_eq_fn) (void*,void*)); - -/***************************************************************************** - * hashtable_insert - - * @name hashtable_insert - * @param h the hashtable to insert into - * @param k the key - hashtable claims ownership and will free on removal - * @param v the value - does not claim ownership - * @return non-zero for successful insertion - * - * This function will cause the table to expand if the insertion would take - * the ratio of entries to table size over the maximum load factor. - * - * This function does not check for repeated insertions with a duplicate key. - * The value returned when using a duplicate key is undefined -- when - * the hashtable changes size, the order of retrieval of duplicate key - * entries is reversed. - * If in doubt, remove before insert. - */ - - -typedef enum { - HASHTABLE_FLAG_NONE = 0, - HASHTABLE_FLAG_FREE_KEY = (1 << 0), - HASHTABLE_FLAG_FREE_VALUE = (1 << 1) -} hashtable_flag_t; - -FT_DECLARE(int) -hashtable_insert(struct hashtable *h, void *k, void *v, hashtable_flag_t flags); - -#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \ - int fnname (struct hashtable *h, keytype *k, valuetype *v) \ - { \ - return hashtable_insert(h,k,v); \ - } - -/***************************************************************************** - * hashtable_search - - * @name hashtable_search - * @param h the hashtable to search - * @param k the key to search for - does not claim ownership - * @return the value associated with the key, or NULL if none found - */ - -FT_DECLARE(void *) -hashtable_search(struct hashtable *h, void *k); - -#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \ - valuetype * fnname (struct hashtable *h, keytype *k) \ - { \ - return (valuetype *) (hashtable_search(h,k)); \ - } - -/***************************************************************************** - * hashtable_remove - - * @name hashtable_remove - * @param h the hashtable to remove the item from - * @param k the key to search for - does not claim ownership - * @return the value associated with the key, or NULL if none found - */ - -FT_DECLARE(void *) /* returns value */ -hashtable_remove(struct hashtable *h, void *k); - -#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \ - valuetype * fnname (struct hashtable *h, keytype *k) \ - { \ - return (valuetype *) (hashtable_remove(h,k)); \ - } - - -/***************************************************************************** - * hashtable_count - - * @name hashtable_count - * @param h the hashtable - * @return the number of items stored in the hashtable - */ -FT_DECLARE(unsigned int) -hashtable_count(struct hashtable *h); - - -/***************************************************************************** - * hashtable_destroy - - * @name hashtable_destroy - * @param h the hashtable - * @param free_values whether to call 'free' on the remaining values - */ - -FT_DECLARE(void) -hashtable_destroy(struct hashtable *h); - -FT_DECLARE(struct hashtable_iterator*) hashtable_first(struct hashtable *h); -FT_DECLARE(struct hashtable_iterator*) hashtable_next(struct hashtable_iterator *i); -FT_DECLARE(void) hashtable_this(struct hashtable_iterator *i, const void **key, int *klen, void **val); - -#ifdef __cplusplus -} /* extern C */ -#endif - -#endif /* __HASHTABLE_CWC22_H__ */ - -/* - * Copyright (c) 2002, Christopher Clark - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/include/private/hashtable_itr.h b/libs/freetdm/src/include/private/hashtable_itr.h deleted file mode 100644 index bf0a6e19d0..0000000000 --- a/libs/freetdm/src/include/private/hashtable_itr.h +++ /dev/null @@ -1,134 +0,0 @@ -/* Copyright (C) 2002, 2004 Christopher Clark */ - -#ifndef __HASHTABLE_ITR_CWC22__ -#define __HASHTABLE_ITR_CWC22__ -#include "hashtable.h" -#include "hashtable_private.h" /* needed to enable inlining */ - -#ifdef __cplusplus -extern "C" { -#endif -/*****************************************************************************/ -/* This struct is only concrete here to allow the inlining of two of the - * accessor functions. */ -struct hashtable_itr -{ - struct hashtable *h; - struct entry *e; - struct entry *parent; - unsigned int index; -}; - - -/*****************************************************************************/ -/* hashtable_iterator - */ - -struct hashtable_itr * -hashtable_iterator(struct hashtable *h); - -/*****************************************************************************/ -/* hashtable_iterator_key - * - return the value of the (key,value) pair at the current position */ -extern __inline__ void * -hashtable_iterator_key(struct hashtable_itr *i); - -extern __inline__ void * -hashtable_iterator_key(struct hashtable_itr *i) -{ - return i->e->k; -} - -/*****************************************************************************/ -/* value - return the value of the (key,value) pair at the current position */ - -extern __inline__ void * -hashtable_iterator_value(struct hashtable_itr *i); - -extern __inline__ void * -hashtable_iterator_value(struct hashtable_itr *i) -{ - return i->e->v; -} - -/*****************************************************************************/ -/* advance - advance the iterator to the next element - * returns zero if advanced to end of table */ - -int -hashtable_iterator_advance(struct hashtable_itr *itr); - -/*****************************************************************************/ -/* remove - remove current element and advance the iterator to the next element - * NB: if you need the value to free it, read it before - * removing. ie: beware memory leaks! - * returns zero if advanced to end of table */ - -int -hashtable_iterator_remove(struct hashtable_itr *itr); - -/*****************************************************************************/ -/* search - overwrite the supplied iterator, to point to the entry - * matching the supplied key. - h points to the hashtable to be searched. - * returns zero if not found. */ -int -hashtable_iterator_search(struct hashtable_itr *itr, - struct hashtable *h, void *k); - -#define DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \ - int fnname (struct hashtable_itr *i, struct hashtable *h, keytype *k) \ - { \ - return (hashtable_iterator_search(i,h,k)); \ - } - -#ifdef __cplusplus -} -#endif - -#endif /* __HASHTABLE_ITR_CWC22__*/ - -/* - * Copyright (c) 2002, 2004, Christopher Clark - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - diff --git a/libs/freetdm/src/include/private/hashtable_private.h b/libs/freetdm/src/include/private/hashtable_private.h deleted file mode 100644 index 35f22091ef..0000000000 --- a/libs/freetdm/src/include/private/hashtable_private.h +++ /dev/null @@ -1,110 +0,0 @@ -/* Copyright (C) 2002, 2004 Christopher Clark */ - -#ifndef __HASHTABLE_PRIVATE_CWC22_H__ -#define __HASHTABLE_PRIVATE_CWC22_H__ - -#include "hashtable.h" - -#ifdef __cplusplus -extern "C" { -#endif -/*****************************************************************************/ - -struct entry -{ - void *k, *v; - unsigned int h; - hashtable_flag_t flags; - struct entry *next; -}; - -struct hashtable_iterator { - unsigned int pos; - struct entry *e; - struct hashtable *h; -}; - -struct hashtable { - unsigned int tablelength; - struct entry **table; - unsigned int entrycount; - unsigned int loadlimit; - unsigned int primeindex; - unsigned int (*hashfn) (void *k); - int (*eqfn) (void *k1, void *k2); - struct hashtable_iterator iterator; -}; - -/*****************************************************************************/ -unsigned int -hash(struct hashtable *h, void *k); - -/*****************************************************************************/ -/* indexFor */ -static __inline__ unsigned int -indexFor(unsigned int tablelength, unsigned int hashvalue) { - return (hashvalue % tablelength); -} - -/* Only works if tablelength == 2^N */ -/*static inline unsigned int - indexFor(unsigned int tablelength, unsigned int hashvalue) - { - return (hashvalue & (tablelength - 1u)); - } -*/ - -/*****************************************************************************/ -#define freekey(X) free(X) -/*define freekey(X) ; */ - -#ifdef __cplusplus -} -#endif - -/*****************************************************************************/ - -#endif /* __HASHTABLE_PRIVATE_CWC22_H__*/ - -/* - * Copyright (c) 2002, Christopher Clark - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/include/private/libteletone.h b/libs/freetdm/src/include/private/libteletone.h deleted file mode 100644 index 060a226032..0000000000 --- a/libs/freetdm/src/include/private/libteletone.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * libteletone - * Copyright (C) 2005-2014, Anthony Minessale II - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is libteletone - * - * The Initial Developer of the Original Code is - * Anthony Minessale II - * Portions created by the Initial Developer are Copyright (C) - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Anthony Minessale II - * - * - * libteletone.h -- Tone Generator/Detector - * - * - * - * Exception: - * The author hereby grants the use of this source code under the - * following license if and only if the source code is distributed - * as part of the OpenZAP or FreeTDM library. Any use or distribution of this - * source code outside the scope of the OpenZAP or FreeTDM library will nullify the - * following license and reinact the MPL 1.1 as stated above. - * - * Copyright (c) 2007, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef LIBTELETONE_H -#define LIBTELETONE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#define TELETONE_MAX_DTMF_DIGITS 128 -#define TELETONE_MAX_TONES 18 -#define TELETONE_TONE_RANGE 127 - -typedef double teletone_process_t; - -/*! \file libteletone.h - \brief Top level include file - - This file should be included by applications using the library -*/ - -/*! \brief An abstraction to store a tone mapping */ -typedef struct { - /*! An array of tone frequencies */ - teletone_process_t freqs[TELETONE_MAX_TONES]; -} teletone_tone_map_t; - -#if !defined(M_PI) -/* C99 systems may not define M_PI */ -#define M_PI 3.14159265358979323846264338327 -#endif - -#ifdef _MSC_VER -typedef __int16 int16_t; -#endif - -#if (_MSC_VER >= 1400) // VC8+ -#define teletone_assert(expr) assert(expr);__analysis_assume( expr ) -#else -#define teletone_assert(expr) assert(expr) -#endif - -#ifdef _MSC_VER -#if defined(TT_DECLARE_STATIC) -#define TELETONE_API(type) type __stdcall -#define TELETONE_API_NONSTD(type) type __cdecl -#define TELETONE_API_DATA -#elif defined(TELETONE_EXPORTS) -#define TELETONE_API(type) __declspec(dllexport) type __stdcall -#define TELETONE_API_NONSTD(type) __declspec(dllexport) type __cdecl -#define TELETONE_API_DATA __declspec(dllexport) -#else -#define TELETONE_API(type) __declspec(dllimport) type __stdcall -#define TELETONE_API_NONSTD(type) __declspec(dllimport) type __cdecl -#define TELETONE_API_DATA __declspec(dllimport) -#endif -#else -#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(HAVE_VISIBILITY) -#define TELETONE_API(type) __attribute__((visibility("default"))) type -#define TELETONE_API_NONSTD(type) __attribute__((visibility("default"))) type -#define TELETONE_API_DATA __attribute__((visibility("default"))) -#else -#define TELETONE_API(type) type -#define TELETONE_API_NONSTD(type) type -#define TELETONE_API_DATA -#endif -#endif - -#include "libteletone_generate.h" -#include "libteletone_detect.h" - -#ifdef HAVE_STRING_H -#include -#endif - -#ifdef __cplusplus -} -#endif - -#endif - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/include/private/libteletone_detect.h b/libs/freetdm/src/include/private/libteletone_detect.h deleted file mode 100644 index 646b03e1be..0000000000 --- a/libs/freetdm/src/include/private/libteletone_detect.h +++ /dev/null @@ -1,282 +0,0 @@ -/* - * libteletone - * Copyright (C) 2005-2014, Anthony Minessale II - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is tone_detect.c - General telephony tone detection, and specific detection of DTMF. - * - * - * The Initial Developer of the Original Code is - * Stephen Underwood - * Portions created by the Initial Developer are Copyright (C) - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * The the original interface designed by Steve Underwood was preserved to retain - *the optimizations when considering DTMF tones though the names were changed in the interest - * of namespace. - * - * Much less efficient expansion interface was added to allow for the detection of - * a single arbitrary tone combination which may also exceed 2 simultaneous tones. - * (controlled by compile time constant TELETONE_MAX_TONES) - * - * Copyright (C) 2006 Anthony Minessale II - * - * - * libteletone_detect.c Tone Detection Code - * - * - ********************************************************************************* - * - * Derived from tone_detect.h - General telephony tone detection, and specific - * detection of DTMF. - * - * Copyright (C) 2001 Steve Underwood - * - * Despite my general liking of the GPL, I place this code in the - * public domain for the benefit of all mankind - even the slimy - * ones who might try to proprietize my work and use it to my - * detriment. - * - * - * Exception: - * The author hereby grants the use of this source code under the - * following license if and only if the source code is distributed - * as part of the OpenZAP or FreeTDM library. Any use or distribution of this - * source code outside the scope of the OpenZAP or FreeTDM library will nullify the - * following license and reinact the MPL 1.1 as stated above. - * - * Copyright (c) 2007, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef LIBTELETONE_DETECT_H -#define LIBTELETONE_DETECT_H - -#ifdef __cplusplus -extern "C" { -#endif -#include "libteletone.h" - - /*! \file libteletone_detect.h - \brief Tone Detection Routines - - This module is responsible for tone detection specifics - */ - -#ifndef FALSE -#define FALSE 0 -#ifndef TRUE -#define TRUE (!FALSE) -#endif -#endif - - /* Basic DTMF specs: - * - * Minimum tone on = 40ms - * Minimum tone off = 50ms - * Maximum digit rate = 10 per second - * Normal twist <= 8dB accepted - * Reverse twist <= 4dB accepted - * S/N >= 15dB will detect OK - * Attenuation <= 26dB will detect OK - * Frequency tolerance +- 1.5% will detect, +-3.5% will reject - */ - -#define DTMF_THRESHOLD 8.0e7 -#define DTMF_NORMAL_TWIST 6.3 /* 8dB */ -#define DTMF_REVERSE_TWIST 2.5 /* 4dB */ -#define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */ -#define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */ -#define DTMF_2ND_HARMONIC_ROW 2.5 /* 4dB */ -#define DTMF_2ND_HARMONIC_COL 63.1 /* 18dB */ -#define GRID_FACTOR 4 -#define BLOCK_LEN 102 -#define M_TWO_PI 2.0*M_PI - - typedef enum { - TT_HIT_NONE = 0, - TT_HIT_BEGIN = 1, - TT_HIT_MIDDLE = 2, - TT_HIT_END = 3 - } teletone_hit_type_t; - - - /*! \brief A continer for the elements of a Goertzel Algorithm (The names are from his formula) */ - typedef struct { - float v2; - float v3; - double fac; - } teletone_goertzel_state_t; - - /*! \brief A container for a DTMF detection state.*/ - typedef struct { - int hit1; - int hit2; - int hit3; - int hit4; - int dur; - int zc; - - - teletone_goertzel_state_t row_out[GRID_FACTOR]; - teletone_goertzel_state_t col_out[GRID_FACTOR]; - teletone_goertzel_state_t row_out2nd[GRID_FACTOR]; - teletone_goertzel_state_t col_out2nd[GRID_FACTOR]; - float energy; - float lenergy; - - int current_sample; - char digit; - int current_digits; - int detected_digits; - int lost_digits; - int digit_hits[16]; - } teletone_dtmf_detect_state_t; - - /*! \brief An abstraction to store the coefficient of a tone frequency */ - typedef struct { - float fac; - } teletone_detection_descriptor_t; - - /*! \brief A container for a single multi-tone detection - TELETONE_MAX_TONES dictates the maximum simultaneous tones that can be present - in a multi-tone representation. - */ - typedef struct { - int sample_rate; - - teletone_detection_descriptor_t tdd[TELETONE_MAX_TONES]; - teletone_goertzel_state_t gs[TELETONE_MAX_TONES]; - teletone_goertzel_state_t gs2[TELETONE_MAX_TONES]; - int tone_count; - - float energy; - int current_sample; - - int min_samples; - int total_samples; - - int positives; - int negatives; - int hits; - - int positive_factor; - int negative_factor; - int hit_factor; - - } teletone_multi_tone_t; - - - /*! - \brief Initilize a multi-frequency tone detector - \param mt the multi-frequency tone descriptor - \param map a representation of the multi-frequency tone - */ -TELETONE_API(void) teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map); - - /*! - \brief Check a sample buffer for the presence of the mulit-frequency tone described by mt - \param mt the multi-frequency tone descriptor - \param sample_buffer an array aof 16 bit signed linear samples - \param samples the number of samples present in sample_buffer - \return true when the tone was detected or false when it is not - */ -TELETONE_API(int) teletone_multi_tone_detect (teletone_multi_tone_t *mt, - int16_t sample_buffer[], - int samples); - - /*! - \brief Initilize a DTMF detection state object - \param dtmf_detect_state the DTMF detection state to initilize - \param sample_rate the desired sample rate - */ -TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf_detect_state, int sample_rate); - - /*! - \brief Check a sample buffer for the presence of DTMF digits - \param dtmf_detect_state the detection state object to check - \param sample_buffer an array aof 16 bit signed linear samples - \param samples the number of samples present in sample_buffer - \return true when DTMF was detected or false when it is not - */ -TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state, - int16_t sample_buffer[], - int samples); - /*! - \brief retrieve any collected digits into a string buffer - \param dtmf_detect_state the detection state object to check - \param buf the string buffer to write to - \param max the maximum length of buf - \return the number of characters written to buf - */ -TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur); - - /*! - \brief Step through the Goertzel Algorithm for each sample in a buffer - \param goertzel_state the goertzel state to step the samples through - \param sample_buffer an array aof 16 bit signed linear samples - \param samples the number of samples present in sample_buffer - */ -TELETONE_API(void) teletone_goertzel_update(teletone_goertzel_state_t *goertzel_state, - int16_t sample_buffer[], - int samples); - - - -#ifdef __cplusplus -} -#endif - -#endif - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/include/private/libteletone_generate.h b/libs/freetdm/src/include/private/libteletone_generate.h deleted file mode 100644 index d5f0bf2e48..0000000000 --- a/libs/freetdm/src/include/private/libteletone_generate.h +++ /dev/null @@ -1,316 +0,0 @@ -/* - * libteletone - * Copyright (C) 2005-2014, Anthony Minessale II - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is libteletone - * - * The Initial Developer of the Original Code is - * Anthony Minessale II - * Portions created by the Initial Developer are Copyright (C) - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Anthony Minessale II - * - * - * libteletone.h -- Tone Generator - * - * - * - * Exception: - * The author hereby grants the use of this source code under the - * following license if and only if the source code is distributed - * as part of the OpenZAP or FreeTDM library. Any use or distribution of this - * source code outside the scope of the OpenZAP or FreeTDM library will nullify the - * following license and reinact the MPL 1.1 as stated above. - * - * Copyright (c) 2007, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef LIBTELETONE_GENERATE_H -#define LIBTELETONE_GENERATE_H -#ifdef __cplusplus -extern "C" { -#ifdef _doh -} -#endif -#endif - -#include -#include - -#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) -#ifndef __inline__ -#define __inline__ inline -#endif -#endif - -#ifdef _MSC_VER -#ifndef __inline__ -#define __inline__ __inline -#endif - -typedef unsigned __int64 uint64_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int8 uint8_t; -typedef __int64 int64_t; -typedef __int32 int32_t; -typedef __int16 int16_t; -typedef __int8 int8_t; -#else -#include -#endif -#include -#include -#include -#include -#if !defined(powf) && !defined(_WIN64) -extern float powf (float, float); -#endif -#include -#include -#ifndef _MSC_VER -#include -#endif -#include -#include -#include "libteletone.h" - -#define TELETONE_VOL_DB_MAX 0 -#define TELETONE_VOL_DB_MIN -63 -#define MAX_PHASE_TONES 4 - -struct teletone_dds_state { - uint32_t phase_rate[MAX_PHASE_TONES]; - uint32_t scale_factor; - uint32_t phase_accumulator; - teletone_process_t tx_level; -}; -typedef struct teletone_dds_state teletone_dds_state_t; - -#define SINE_TABLE_MAX 128 -#define SINE_TABLE_LEN (SINE_TABLE_MAX - 1) -#define MAX_PHASE_ACCUMULATOR 0x10000 * 0x10000 -/* 3.14 == the max power on ulaw (alaw is 3.17) */ -/* 3.02 represents twice the power */ -#define DBM0_MAX_POWER (3.14f + 3.02f) - -TELETONE_API_DATA extern int16_t TELETONE_SINES[SINE_TABLE_MAX]; - -static __inline__ int32_t teletone_dds_phase_rate(teletone_process_t tone, uint32_t rate) -{ - return (int32_t) ((tone * MAX_PHASE_ACCUMULATOR) / rate); -} - -static __inline__ int16_t teletone_dds_state_modulate_sample(teletone_dds_state_t *dds, uint32_t pindex) -{ - int32_t bitmask = dds->phase_accumulator, sine_index = (bitmask >>= 23) & SINE_TABLE_LEN; - int16_t sample; - - if (pindex >= MAX_PHASE_TONES) { - pindex = 0; - } - - if (bitmask & SINE_TABLE_MAX) { - sine_index = SINE_TABLE_LEN - sine_index; - } - - sample = TELETONE_SINES[sine_index]; - - if (bitmask & (SINE_TABLE_MAX * 2)) { - sample *= -1; - } - - dds->phase_accumulator += dds->phase_rate[pindex]; - return (int16_t) (sample * dds->scale_factor >> 15); -} - -static __inline__ void teletone_dds_state_set_tx_level(teletone_dds_state_t *dds, float tx_level) -{ - dds->scale_factor = (int) (powf(10.0f, (tx_level - DBM0_MAX_POWER) / 20.0f) * (32767.0f * 1.414214f)); - dds->tx_level = tx_level; -} - -static __inline__ void teletone_dds_state_reset_accum(teletone_dds_state_t *dds) -{ - dds->phase_accumulator = 0; -} - -static __inline__ int teletone_dds_state_set_tone(teletone_dds_state_t *dds, teletone_process_t tone, uint32_t rate, uint32_t pindex) -{ - if (pindex < MAX_PHASE_TONES) { - dds->phase_rate[pindex] = teletone_dds_phase_rate(tone, rate); - return 0; - } - - return -1; -} - - - -/*! \file libteletone_generate.h - \brief Tone Generation Routines - - This module is responsible for tone generation specifics -*/ - -typedef int16_t teletone_audio_t; -struct teletone_generation_session; -typedef int (*tone_handler)(struct teletone_generation_session *ts, teletone_tone_map_t *map); - -/*! \brief An abstraction to store a tone generation session */ -struct teletone_generation_session { - /*! An array of tone mappings to character mappings */ - teletone_tone_map_t TONES[TELETONE_TONE_RANGE]; - /*! The number of channels the output audio should be in */ - int channels; - /*! The Rate in hz of the output audio */ - int rate; - /*! The duration (in samples) of the output audio */ - int duration; - /*! The duration of silence to append after the initial audio is generated */ - int wait; - /*! The duration (in samples) of the output audio (takes prescedence over actual duration value) */ - int tmp_duration; - /*! The duration of silence to append after the initial audio is generated (takes prescedence over actual wait value)*/ - int tmp_wait; - /*! Number of loops to repeat a single instruction*/ - int loops; - /*! Number of loops to repeat the entire set of instructions*/ - int LOOPS; - /*! Number to mutiply total samples by to determine when to begin ascent or decent e.g. 0=beginning 4=(last 25%) */ - float decay_factor; - /*! Direction to perform volume increase/decrease 1/-1*/ - int decay_direction; - /*! Number of samples between increase/decrease of volume */ - int decay_step; - /*! Volume factor of the tone */ - float volume; - /*! Debug on/off */ - int debug; - /*! FILE stream to write debug data to */ - FILE *debug_stream; - /*! Extra user data to attach to the session*/ - void *user_data; - /*! Buffer for storing sample data (dynamic) */ - teletone_audio_t *buffer; - /*! Size of the buffer */ - int datalen; - /*! In-Use size of the buffer */ - int samples; - /*! Callback function called during generation */ - int dynamic; - tone_handler handler; -}; - -typedef struct teletone_generation_session teletone_generation_session_t; - - -/*! - \brief Assign a set of tones to a tone_session indexed by a paticular index/character - \param ts the tone generation session - \param index the index to map the tone to - \param ... up to TELETONE_MAX_TONES frequencies terminated by 0.0 - \return 0 -*/ -TELETONE_API(int) teletone_set_tone(teletone_generation_session_t *ts, int index, ...); - -/*! - \brief Assign a set of tones to a single tone map - \param map the map to assign the tones to - \param ... up to TELETONE_MAX_TONES frequencies terminated by 0.0 - \return 0 -*/ -TELETONE_API(int) teletone_set_map(teletone_tone_map_t *map, ...); - -/*! - \brief Initilize a tone generation session - \param ts the tone generation session to initilize - \param buflen the size of the buffer(in samples) to dynamically allocate - \param handler a callback function to execute when a tone generation instruction is complete - \param user_data optional user data to send - \return 0 -*/ -TELETONE_API(int) teletone_init_session(teletone_generation_session_t *ts, int buflen, tone_handler handler, void *user_data); - -/*! - \brief Free the buffer allocated by a tone generation session - \param ts the tone generation session to destroy - \return 0 -*/ -TELETONE_API(int) teletone_destroy_session(teletone_generation_session_t *ts); - -/*! - \brief Execute a single tone generation instruction - \param ts the tone generation session to consult for parameters - \param map the tone mapping to use for the frequencies - \return 0 -*/ -TELETONE_API(int) teletone_mux_tones(teletone_generation_session_t *ts, teletone_tone_map_t *map); - -/*! - \brief Execute a tone generation script and call callbacks after each instruction - \param ts the tone generation session to execute on - \param cmd the script to execute - \return 0 -*/ -TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cmd); - -#ifdef __cplusplus -} -#endif - -#endif - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/include/private/sangoma_tdm_api.h b/libs/freetdm/src/include/private/sangoma_tdm_api.h deleted file mode 100644 index 6880199110..0000000000 --- a/libs/freetdm/src/include/private/sangoma_tdm_api.h +++ /dev/null @@ -1,321 +0,0 @@ -/***************************************************************************** - * sangoma_tdm_api.h Sangoma TDM API Portability functions - * - * Author(s): Anthony Minessale II - * Nenad Corbic - * Michael Jerris - * David Rokhvarg - * - * Copyright: (c) 2006 Nenad Corbic - * Anthony Minessale II - * (c) 1984-2007 Sangoma Technologies Inc. - * - * ============================================================================ - */ - -#ifndef _SANGOMA_TDM_API_H -#define _SANGOMA_TDM_API_H - -/* This entire block of defines and includes from this line, through #define FNAME_LEN probably dont belong here */ -/* most of them probably belong in wanpipe_defines.h, then each header file listed included below properly included */ -/* in the header files that depend on them, leaving only the include for wanpipe_tdm_api.h left in this file or */ -/* possibly integrating the rest of this file diretly into wanpipe_tdm_api.h */ -#ifndef __WINDOWS__ -#if defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32) -#define __WINDOWS__ -#endif /* defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32) */ -#endif /* ndef __WINDOWS__ */ - -#if defined(__WINDOWS__) -#if defined(_MSC_VER) -/* disable some warnings caused by wanpipe headers that will need to be fixed in those headers */ -#pragma warning(disable:4201 4214) - -/* sang_api.h(74) : warning C4201: nonstandard extension used : nameless struct/union */ - -/* wanpipe_defines.h(219) : warning C4214: nonstandard extension used : bit field types other than int */ -/* wanpipe_defines.h(220) : warning C4214: nonstandard extension used : bit field types other than int */ -/* this will break for any compilers that are strict ansi or strict c99 */ - -/* The following definition for that struct should resolve this warning and work for 32 and 64 bit */ -#if 0 -struct iphdr { - -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned ihl:4, - version:4; -#elif defined (__BIG_ENDIAN_BITFIELD) - unsigned version:4, - ihl:4; -#else -# error "unknown byteorder!" -#endif - unsigned tos:8; - unsigned tot_len:16; - unsigned id:16; - unsigned frag_off:16; - __u8 ttl; - __u8 protocol; - __u16 check; - __u32 saddr; - __u32 daddr; - /*The options start here. */ -}; -#endif /* #if 0 */ - -#define __inline__ __inline -#endif /* defined(_MSC_VER) */ -#include -/* do we like the name WP_INVALID_SOCKET or should it be changed? */ -#define WP_INVALID_SOCKET INVALID_HANDLE_VALUE -#else /* defined(__WINDOWS__) */ -#define WP_INVALID_SOCKET -1 -#include -#include -#include -#endif - -#include -#include -#include -#include -#ifdef __WINDOWS__ -#include -#include -#endif -#include - -#define FNAME_LEN 50 - - -#if defined(__WINDOWS__) -/* This might be broken on windows, as POLL_EVENT_TELEPHONY seems to be commented out in sang_api.h.. it should be added to POLLPRI */ -#define POLLPRI (POLL_EVENT_LINK_STATE | POLL_EVENT_LINK_CONNECT | POLL_EVENT_LINK_DISCONNECT) -#endif - -/* return -1 for error, 0 for timeout or 1 for success. *flags is set to the poll evetns POLLIN | POLLOUT | POLLPRI based on the result of the poll */ -/* on windows we actually have POLLPRI defined with several events, so we could theoretically poll */ -/* for specific events. Is there any way to do this on *nix as well? */ - -/* a cross platform way to poll on an actual pollset (span and/or list of spans) will probably also be needed for analog */ -/* so we can have one analong handler thread that will deal with all the idle analog channels for events */ -/* the alternative would be for the driver to provide one socket for all of the oob events for all analog channels */ -static __inline__ int tdmv_api_wait_socket(sng_fd_t fd, int timeout, int *flags) -{ -#if defined(__WINDOWS__) - DWORD ln; - API_POLL_STRUCT api_poll; - - memset(&api_poll, 0x00, sizeof(API_POLL_STRUCT)); - - api_poll.user_flags_bitmap = *flags; - api_poll.timeout = timeout; - - if (!DeviceIoControl( - fd, - IoctlApiPoll, - (LPVOID)NULL, - 0L, - (LPVOID)&api_poll, - sizeof(API_POLL_STRUCT), - (LPDWORD)(&ln), - (LPOVERLAPPED)NULL)) { - return -1; - } - - *flags = 0; - - switch(api_poll.operation_status) - { - case SANG_STATUS_RX_DATA_AVAILABLE: - break; - - case SANG_STATUS_RX_DATA_TIMEOUT: - return 0; - - default: - return -1; - } - - if (api_poll.poll_events_bitmap == 0){ - return -1; - } - - if (api_poll.poll_events_bitmap & POLL_EVENT_TIMEOUT) { - return 0; - } - - *flags = api_poll.poll_events_bitmap; - - return 1; -#else - struct pollfd pfds[1]; - int res; - - memset(&pfds[0], 0, sizeof(pfds[0])); - pfds[0].fd = fd; - pfds[0].events = *flags; - res = poll(pfds, 1, timeout); - *flags = 0; - - if (pfds[0].revents & POLLERR) { - res = -1; - } - - if (res > 0) { - *flags = pfds[0].revents; - } - - return res; -#endif -} - -/* on windows right now, there is no way to specify if we want to read events here or not, we allways get them here */ -/* we need some what to select if we are reading regular tdm msgs or events */ -/* need to either have 2 functions, 1 for events, 1 for regural read, or a flag on this function to choose */ -/* 2 functions preferred. Need implementation for the event function for both nix and windows that is threadsafe */ -static __inline__ int tdmv_api_readmsg_tdm(sng_fd_t fd, void *hdrbuf, int hdrlen, void *databuf, int datalen) -{ - /* What do we need to do here to avoid having to do all */ - /* the memcpy's on windows and still maintain api compat with nix */ - int rx_len=0; -#if defined(__WINDOWS__) - static RX_DATA_STRUCT rx_data; - api_header_t *pri; - wp_tdm_api_rx_hdr_t *tdm_api_rx_hdr; - wp_tdm_api_rx_hdr_t *user_buf = (wp_tdm_api_rx_hdr_t*)hdrbuf; - DWORD ln; - - if (hdrlen != sizeof(wp_tdm_api_rx_hdr_t)){ - return -1; - } - - if (!DeviceIoControl( - fd, - IoctlReadCommand, - (LPVOID)NULL, - 0L, - (LPVOID)&rx_data, - sizeof(RX_DATA_STRUCT), - (LPDWORD)(&ln), - (LPOVERLAPPED)NULL - )){ - return -1; - } - - pri = &rx_data.api_header; - tdm_api_rx_hdr = (wp_tdm_api_rx_hdr_t*)rx_data.data; - - user_buf->wp_tdm_api_event_type = pri->operation_status; - - switch(pri->operation_status) - { - case SANG_STATUS_RX_DATA_AVAILABLE: - if (pri->data_length > datalen){ - break; - } - memcpy(databuf, rx_data.data, pri->data_length); - rx_len = pri->data_length; - break; - - default: - break; - } - -#else - struct msghdr msg; - struct iovec iov[2]; - - memset(&msg,0,sizeof(struct msghdr)); - - iov[0].iov_len=hdrlen; - iov[0].iov_base=hdrbuf; - - iov[1].iov_len=datalen; - iov[1].iov_base=databuf; - - msg.msg_iovlen=2; - msg.msg_iov=iov; - - rx_len = read(fd,&msg,datalen+hdrlen); - - if (rx_len <= sizeof(wp_tdm_api_rx_hdr_t)){ - return -EINVAL; - } - - rx_len-=sizeof(wp_tdm_api_rx_hdr_t); -#endif - return rx_len; -} - -static __inline__ int tdmv_api_writemsg_tdm(sng_fd_t fd, void *hdrbuf, int hdrlen, void *databuf, unsigned short datalen) -{ - /* What do we need to do here to avoid having to do all */ - /* the memcpy's on windows and still maintain api compat with nix */ - int bsent = 0; -#if defined(__WINDOWS__) - static TX_DATA_STRUCT local_tx_data; - api_header_t *pri; - DWORD ln; - - /* Are these really not needed or used??? What about for nix?? */ - (void)hdrbuf; - (void)hdrlen; - - pri = &local_tx_data.api_header; - - pri->data_length = datalen; - memcpy(local_tx_data.data, databuf, pri->data_length); - - if (!DeviceIoControl( - fd, - IoctlWriteCommand, - (LPVOID)&local_tx_data, - (ULONG)sizeof(TX_DATA_STRUCT), - (LPVOID)&local_tx_data, - sizeof(TX_DATA_STRUCT), - (LPDWORD)(&ln), - (LPOVERLAPPED)NULL - )){ - return -1; - } - - if (local_tx_data.api_header.operation_status == SANG_STATUS_SUCCESS) { - bsent = datalen; - } -#else - struct msghdr msg; - struct iovec iov[2]; - - memset(&msg,0,sizeof(struct msghdr)); - - iov[0].iov_len = hdrlen; - iov[0].iov_base = hdrbuf; - - iov[1].iov_len = datalen; - iov[1].iov_base = databuf; - - msg.msg_iovlen = 2; - msg.msg_iov = iov; - - bsent = write(fd, &msg, datalen + hdrlen); - if (bsent > 0){ - bsent -= sizeof(wp_tdm_api_tx_hdr_t); - } -#endif - return bsent; -} - -#endif /* _SANGOMA_TDM_API_H */ - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - diff --git a/libs/freetdm/src/include/private/uart.h b/libs/freetdm/src/include/private/uart.h deleted file mode 100644 index b1b04c09a4..0000000000 --- a/libs/freetdm/src/include/private/uart.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * uart.h - * - * Copyright (c) 2005 Robert Krten. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This module contains the manifest constants and declarations for - * the UART module. - * - * 2005 06 19 R. Krten created -*/ - -#ifndef __UART_H__ -#define __UART_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void (*bytehandler_func_t) (void *, int); -typedef void (*bithandler_func_t) (void *, int); - - -typedef struct dsp_uart_attr_s -{ - bytehandler_func_t bytehandler; /* byte handler */ - void *bytehandler_arg; /* arbitrary ID passed to bytehandler as first argument */ -} dsp_uart_attr_t; - -typedef struct -{ - dsp_uart_attr_t attr; - int have_start; /* wait for start bit to show up */ - int data; /* data buffer */ - int nbits; /* number of bits accumulated so far */ -} dsp_uart_handle_t; - -/* - * Function prototypes - * - * General calling order is: - * a) create the attributes structure (dsp_uart_attr_init) - * b) initialize fields in the attributes structure (dsp_uart_attr_set_*) - * c) create a Bell-202 handle (dsp_uart_create) - * d) feed bits through dsp_uart_bit_handler -*/ - -void dsp_uart_attr_init(dsp_uart_attr_t *attributes); - -bytehandler_func_t dsp_uart_attr_get_bytehandler(dsp_uart_attr_t *attributes, void **bytehandler_arg); -void dsp_uart_attr_set_bytehandler(dsp_uart_attr_t *attributes, bytehandler_func_t bytehandler, void *bytehandler_arg); - -dsp_uart_handle_t * dsp_uart_create(dsp_uart_attr_t *attributes); -void dsp_uart_destroy(dsp_uart_handle_t **handle); - -void dsp_uart_bit_handler(void *handle, int bit); - -#ifdef __cplusplus -} -#endif -#endif - diff --git a/libs/freetdm/src/isdn/5ESSStateNT.c b/libs/freetdm/src/isdn/5ESSStateNT.c deleted file mode 100644 index 6d38f4582e..0000000000 --- a/libs/freetdm/src/isdn/5ESSStateNT.c +++ /dev/null @@ -1,132 +0,0 @@ -/***************************************************************************** - - FileName: 5ESSStateNT.c - - Contents: AT&T 5ESS ISDN State Engine for NT (Network Mode). - - The controlling state engine for Q.931 is the state engine - on the NT side. The state engine on the TE side is a slave - of this. The TE side maintain it's own states as described in - ITU-T Q931, but will in raise conditions be overridden by - the NT side. - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Copyright (c) 2007, Michael Jerris. All rights reserved. - email:mike@jerris.com - - Copyright (c) 2007, Michael S. Collins, All rights reserved. - email:mcollins@fcnetwork.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -#include "5ESS.h" - -/***************************************************************************** - Function: ATT5ESSCreateNT - - Description: Will create the AT&T 5ESS ISDN NT as a Dialect in the stack. The first - bulk set up the message handlers, the second bulk the IE - encoders/coders, and the last bulk set up the state table. - - Parameters: i Dialect index -*****************************************************************************/ -void ATT5ESSCreateNT(L3UCHAR i) -{ - Q931SetMesProc(Q931mes_ALERTING, i, Q931ProcAlertingNT, Q931Umes_Alerting, Q931Pmes_Alerting); - Q931SetMesProc(Q931mes_CALL_PROCEEDING, i, Q931ProcCallProceedingNT, Q931Umes_CallProceeding, Q931Pmes_CallProceeding); - Q931SetMesProc(Q931mes_CONNECT, i, Q931ProcConnectNT, Q931Umes_Connect, Q931Pmes_Connect); - Q931SetMesProc(Q931mes_CONNECT_ACKNOWLEDGE, i, Q931ProcConnectAckNT, Q931Umes_ConnectAck, Q931Pmes_ConnectAck); - Q931SetMesProc(Q931mes_PROGRESS, i, Q931ProcProgressNT, Q931Umes_Progress, Q931Pmes_Progress); - Q931SetMesProc(Q931mes_SETUP, i, Q931ProcSetupNT, Q931Umes_Setup, Q931Pmes_Setup); - Q931SetMesProc(Q931mes_SETUP_ACKNOWLEDGE, i, Q931ProcSetupAckNT, Q931Umes_SetupAck, Q931Pmes_SetupAck); - Q931SetMesProc(Q931mes_RESUME, i, Q931ProcResumeNT, Q931Umes_Resume, Q931Pmes_Resume); - Q931SetMesProc(Q931mes_RESUME_ACKNOWLEDGE, i, Q931ProcResumeAckNT, Q931Umes_ResumeAck, Q931Pmes_ResumeAck); - Q931SetMesProc(Q931mes_RESUME_REJECT, i, Q931ProcResumeRejectNT, Q931Umes_ResumeReject, Q931Pmes_ResumeReject); - Q931SetMesProc(Q931mes_SUSPEND, i, Q931ProcSuspendNT, Q931Umes_Suspend, Q931Pmes_Suspend); - Q931SetMesProc(Q931mes_SUSPEND_ACKNOWLEDGE, i, Q931ProcSuspendAckNT, Q931Umes_SuspendAck, Q931Pmes_SuspendAck); - Q931SetMesProc(Q931mes_SUSPEND_REJECT, i, Q931ProcSuspendRejectNT, Q931Umes_SuspendReject, Q931Pmes_SuspendReject); - Q931SetMesProc(Q931mes_USER_INFORMATION, i, Q931ProcUserInformationNT, Q931Umes_UserInformation, Q931Pmes_UserInformation); - Q931SetMesProc(Q931mes_DISCONNECT, i, Q931ProcDisconnectNT, Q931Umes_Disconnect, Q931Pmes_Disconnect); - Q931SetMesProc(Q931mes_RELEASE, i, Q931ProcReleaseNT, Q931Umes_Release, Q931Pmes_Release); - Q931SetMesProc(Q931mes_RELEASE_COMPLETE, i, Q931ProcReleaseCompleteNT, Q931Umes_ReleaseComplete, Q931Pmes_ReleaseComplete); - Q931SetMesProc(Q931mes_RESTART, i, Q931ProcRestartNT, Q931Umes_Restart, Q931Pmes_Restart); - Q931SetMesProc(Q931mes_RESTART_ACKNOWLEDGE, i, Q931ProcRestartAckNT, Q931Umes_RestartAck, Q931Pmes_RestartAck); - Q931SetMesProc(Q931mes_CONGESTION_CONTROL, i, Q931ProcCongestionControlNT, Q931Umes_CongestionControl, Q931Pmes_CongestionControl); - Q931SetMesProc(Q931mes_INFORMATION, i, Q931ProcInformationNT, Q931Umes_Information, Q931Pmes_Information); - Q931SetMesProc(Q931mes_NOTIFY, i, Q931ProcNotifyNT, Q931Umes_Notify, Q931Pmes_Notify); - Q931SetMesProc(Q931mes_STATUS, i, Q931ProcStatusNT, Q931Umes_Status, Q931Pmes_Status); - Q931SetMesProc(Q931mes_STATUS_ENQUIRY, i, Q931ProcStatusEnquiryNT, Q931Umes_StatusEnquiry, Q931Pmes_StatusEnquiry); - Q931SetMesProc(Q931mes_SEGMENT, i, Q931ProcSegmentNT, Q931Umes_Segment, Q931Pmes_Segment); - - Q931SetMesProc(Q932mes_FACILITY, i, Q932ProcFacilityNT, Q932Umes_Facility, Q932Pmes_Facility); - Q931SetMesProc(Q932mes_HOLD, i, Q932ProcHoldNT, Q932Umes_Hold, Q932Pmes_Hold); - Q931SetMesProc(Q932mes_HOLD_ACKNOWLEDGE, i, Q932ProcHoldAckNT, Q932Umes_HoldAck, Q932Pmes_HoldAck); - Q931SetMesProc(Q932mes_HOLD_REJECT, i, Q932ProcHoldRejectNT, Q932Umes_HoldReject, Q932Pmes_HoldReject); - Q931SetMesProc(Q932mes_REGISTER, i, Q932ProcRegisterNT, Q932Umes_Register, Q932Pmes_Register); - Q931SetMesProc(Q932mes_RETRIEVE, i, Q932ProcRetrieveNT, Q932Umes_Retrieve, Q932Pmes_Retrieve); - Q931SetMesProc(Q932mes_RETRIEVE_ACKNOWLEDGE, i, Q932ProcRetrieveAckNT, Q932Umes_RetrieveAck, Q932Pmes_RetrieveAck); - Q931SetMesProc(Q932mes_RETRIEVE_REJECT, i, Q932ProcRetrieveRejectNT, Q932Umes_RetrieveReject, Q932Pmes_RetrieveReject); - - /* Set up the IE encoder/decoder handle table.*/ - Q931SetIEProc(Q931ie_SEGMENTED_MESSAGE, i, Q931Pie_Segment, Q931Uie_Segment); - Q931SetIEProc(Q931ie_BEARER_CAPABILITY, i, Q931Pie_BearerCap, Q931Uie_BearerCap); - Q931SetIEProc(Q931ie_CAUSE, i, Q931Pie_Cause, Q931Uie_Cause); - Q931SetIEProc(Q931ie_CALL_IDENTITY, i, Q931Pie_CallID, Q931Uie_CallID); - Q931SetIEProc(Q931ie_CALL_STATE, i, Q931Pie_CallState, Q931Uie_CallState); - Q931SetIEProc(Q931ie_CHANNEL_IDENTIFICATION, i, Q931Pie_ChanID, Q931Uie_ChanID); - Q931SetIEProc(Q931ie_PROGRESS_INDICATOR, i, Q931Pie_ProgInd, Q931Uie_ProgInd); - Q931SetIEProc(Q931ie_NETWORK_SPECIFIC_FACILITIES, i, Q931Pie_NetFac, Q931Uie_NetFac); - Q931SetIEProc(Q931ie_NOTIFICATION_INDICATOR, i, Q931Pie_NotifInd, Q931Uie_NotifInd); - Q931SetIEProc(Q931ie_DISPLAY, i, Q931Pie_Display, Q931Uie_Display); - Q931SetIEProc(Q931ie_DATETIME, i, Q931Pie_DateTime, Q931Uie_DateTime); - Q931SetIEProc(Q931ie_KEYPAD_FACILITY, i, Q931Pie_KeypadFac, Q931Uie_KeypadFac); - Q931SetIEProc(Q931ie_SIGNAL, i, Q931Pie_Signal, Q931Uie_Signal); - Q931SetIEProc(Q931ie_TRANSIT_DELAY_SELECTION_AND_IND, i, Q931Pie_TransNetSel, Q931Uie_TransNetSel); - Q931SetIEProc(Q931ie_CALLING_PARTY_NUMBER, i, Q931Pie_CallingNum, Q931Uie_CallingNum); - Q931SetIEProc(Q931ie_CALLING_PARTY_SUBADDRESS, i, Q931Pie_CallingSub, Q931Uie_CallingSub); - Q931SetIEProc(Q931ie_CALLED_PARTY_NUMBER, i, Q931Pie_CalledNum, Q931Uie_CalledNum); - Q931SetIEProc(Q931ie_CALLED_PARTY_SUBADDRESS, i, Q931Pie_CalledSub, Q931Uie_CalledSub); - Q931SetIEProc(Q931ie_TRANSIT_NETWORK_SELECTION, i, Q931Pie_TransNetSel, Q931Uie_TransNetSel); - Q931SetIEProc(Q931ie_RESTART_INDICATOR, i, Q931Pie_RestartInd, Q931Uie_RestartInd); - Q931SetIEProc(Q931ie_LOW_LAYER_COMPATIBILITY, i, Q931Pie_LLComp, Q931Uie_LLComp); - Q931SetIEProc(Q931ie_HIGH_LAYER_COMPATIBILITY, i, Q931Pie_HLComp, Q931Uie_HLComp); - Q931SetIEProc(Q931ie_USER_USER, i, Q931Pie_UserUser, Q931Uie_UserUser); - Q931SetIEProc(Q931ie_GENERIC_DIGITS, i, Q931Pie_GenericDigits, Q931Uie_GenericDigits); - - Q931SetIEProc(Q931ie_CONNECTED_NUMBER, i, Q931Pie_Generic, Q931Uie_Generic); - Q931SetIEProc(Q931ie_FACILITY, i, Q931Pie_Generic, Q931Uie_Generic); - - /* The following define a state machine. The point is that the Message */ - /* procs can when search this to find out if the message/state */ - /* combination is legale. If not, the proc for unexpected message apply.*/ - - /* TODO define state table here */ -} diff --git a/libs/freetdm/src/isdn/5ESSStateTE.c b/libs/freetdm/src/isdn/5ESSStateTE.c deleted file mode 100644 index 6c31df88c7..0000000000 --- a/libs/freetdm/src/isdn/5ESSStateTE.c +++ /dev/null @@ -1,291 +0,0 @@ -/***************************************************************************** - - FileName: 5ESSStateTE.c - - Contents: AT&T 5ESS ISDN State Engine for TE (User Mode). - - The controlling state engine for Q.931 is the state engine - on the NT side. The state engine on the TE side is a slave - of this. The TE side maintain it's own states as described in - ITU-T Q931, but will in raise conditions be overridden by - the NT side. - - This reference implementation uses a process per message, - meaning that each message must check call states. This - is easier for dialect maintenance as each message proc - can be replaced individually. A new TE variant only - need to copy the Q931CreateTE and replace those procs or - need to override. - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Copyright (c) 2007, Michael Jerris. All rights reserved. - email:mike@jerris.com - - Copyright (c) 2007, Michael S. Collins, All rights reserved. - email:mcollins@fcnetwork.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -#include "5ESS.h" -extern L3INT Q931L4HeaderSpace; - -/***************************************************************************** - Function: ATT5ESSCreateTE - - Description: Will create the AT&T 5ESS TE as a Dialect in the stack. The first - bulk set up the message handlers, the second bulk the IE - encoders/coders, and the last bulk set up the state table. - - Parameters: i Dialect index -*****************************************************************************/ -void ATT5ESSCreateTE(L3UCHAR i) -{ - Q931SetMesProc(Q931mes_ALERTING, i, Q931ProcAlertingTE, Q931Umes_Alerting, Q931Pmes_Alerting); - Q931SetMesProc(Q931mes_CALL_PROCEEDING, i, Q931ProcCallProceedingTE, Q931Umes_CallProceeding, Q931Pmes_CallProceeding); - Q931SetMesProc(Q931mes_CONNECT, i, ATT5ESSProc0x07TE, ATT5ESSUmes_0x07, ATT5ESSPmes_0x07); - Q931SetMesProc(Q931mes_CONNECT_ACKNOWLEDGE, i, ATT5ESSProc0x0fTE, ATT5ESSUmes_0x0f, ATT5ESSPmes_0x0f); - Q931SetMesProc(Q931mes_PROGRESS, i, Q931ProcProgressTE, Q931Umes_Progress, Q931Pmes_Progress); - Q931SetMesProc(Q931mes_SETUP, i, Q931ProcSetupTE, ATT5ESSUmes_Setup, ATT5ESSPmes_Setup); - Q931SetMesProc(Q931mes_SETUP_ACKNOWLEDGE, i, Q931ProcSetupAckTE, Q931Umes_SetupAck, Q931Pmes_SetupAck); - Q931SetMesProc(Q931mes_RESUME, i, Q931ProcResumeTE, Q931Umes_Resume, Q931Pmes_Resume); - Q931SetMesProc(Q931mes_RESUME_ACKNOWLEDGE, i, Q931ProcResumeAckTE, Q931Umes_ResumeAck, Q931Pmes_ResumeAck); - Q931SetMesProc(Q931mes_RESUME_REJECT, i, Q931ProcResumeRejectTE, Q931Umes_ResumeReject, Q931Pmes_ResumeReject); - Q931SetMesProc(Q931mes_SUSPEND, i, Q931ProcSuspendTE, Q931Umes_Suspend, Q931Pmes_Suspend); - Q931SetMesProc(Q931mes_SUSPEND_ACKNOWLEDGE, i, Q931ProcSuspendAckTE, Q931Umes_SuspendAck, Q931Pmes_SuspendAck); - Q931SetMesProc(Q931mes_SUSPEND_REJECT, i, Q931ProcSuspendRejectTE, Q931Umes_SuspendReject, Q931Pmes_SuspendReject); - Q931SetMesProc(Q931mes_USER_INFORMATION, i, Q931ProcUserInformationTE, Q931Umes_UserInformation, Q931Pmes_UserInformation); - Q931SetMesProc(Q931mes_DISCONNECT, i, Q931ProcDisconnectTE, Q931Umes_Disconnect, Q931Pmes_Disconnect); - Q931SetMesProc(Q931mes_RELEASE, i, Q931ProcReleaseTE, Q931Umes_Release, Q931Pmes_Release); - Q931SetMesProc(Q931mes_RELEASE_COMPLETE, i, Q931ProcReleaseCompleteTE, Q931Umes_ReleaseComplete, Q931Pmes_ReleaseComplete); - Q931SetMesProc(Q931mes_RESTART, i, Q931ProcRestartTE, Q931Umes_Restart, Q931Pmes_Restart); - Q931SetMesProc(Q931mes_RESTART_ACKNOWLEDGE, i, Q931ProcRestartAckTE, Q931Umes_RestartAck, Q931Pmes_RestartAck); - Q931SetMesProc(Q931mes_CONGESTION_CONTROL, i, Q931ProcCongestionControlTE, Q931Umes_CongestionControl, Q931Pmes_CongestionControl); - Q931SetMesProc(Q931mes_INFORMATION, i, Q931ProcInformationTE, Q931Umes_Information, Q931Pmes_Information); - Q931SetMesProc(Q931mes_NOTIFY, i, Q931ProcNotifyTE, Q931Umes_Notify, Q931Pmes_Notify); - Q931SetMesProc(Q931mes_STATUS, i, Q931ProcStatusTE, Q931Umes_Status, Q931Pmes_Status); - Q931SetMesProc(Q931mes_STATUS_ENQUIRY, i, Q931ProcStatusEnquiryTE, Q931Umes_StatusEnquiry, Q931Pmes_StatusEnquiry); - Q931SetMesProc(Q931mes_SEGMENT, i, Q931ProcSegmentTE, Q931Umes_Segment, Q931Pmes_Segment); - - Q931SetMesProc(Q932mes_FACILITY, i, Q932ProcFacilityTE, Q932Umes_Facility, Q932Pmes_Facility); - Q931SetMesProc(Q932mes_HOLD, i, Q932ProcHoldTE, Q932Umes_Hold, Q932Pmes_Hold); - Q931SetMesProc(Q932mes_HOLD_ACKNOWLEDGE, i, Q932ProcHoldAckTE, Q932Umes_HoldAck, Q932Pmes_HoldAck); - Q931SetMesProc(Q932mes_HOLD_REJECT, i, Q932ProcHoldRejectTE, Q932Umes_HoldReject, Q932Pmes_HoldReject); - Q931SetMesProc(Q932mes_REGISTER, i, Q932ProcRegisterTE, Q932Umes_Register, Q932Pmes_Register); - Q931SetMesProc(Q932mes_RETRIEVE, i, Q932ProcRetrieveTE, Q932Umes_Retrieve, Q932Pmes_Retrieve); - Q931SetMesProc(Q932mes_RETRIEVE_ACKNOWLEDGE, i, Q932ProcRetrieveAckTE, Q932Umes_RetrieveAck, Q932Pmes_RetrieveAck); - Q931SetMesProc(Q932mes_RETRIEVE_REJECT, i, Q932ProcRetrieveRejectTE, Q932Umes_RetrieveReject, Q932Pmes_RetrieveReject); - - /* Set up the IE encoder/decoder handle table.*/ - Q931SetIEProc(Q931ie_SEGMENTED_MESSAGE, i, Q931Pie_Segment, Q931Uie_Segment); - Q931SetIEProc(Q931ie_BEARER_CAPABILITY, i, Q931Pie_BearerCap, Q931Uie_BearerCap); - Q931SetIEProc(Q931ie_CAUSE, i, Q931Pie_Cause, Q931Uie_Cause); - Q931SetIEProc(Q931ie_CALL_IDENTITY, i, Q931Pie_CallID, Q931Uie_CallID); - Q931SetIEProc(Q931ie_CALL_STATE, i, Q931Pie_CallState, Q931Uie_CallState); - Q931SetIEProc(Q931ie_CHANGE_STATUS, i, Q931Pie_ChangeStatus, Q931Uie_ChangeStatus); - Q931SetIEProc(Q931ie_CHANNEL_IDENTIFICATION, i, Q931Pie_ChanID, Q931Uie_ChanID); - Q931SetIEProc(Q931ie_PROGRESS_INDICATOR, i, Q931Pie_ProgInd, Q931Uie_ProgInd); - Q931SetIEProc(Q931ie_NETWORK_SPECIFIC_FACILITIES, i, Q931Pie_NetFac, Q931Uie_NetFac); - Q931SetIEProc(Q931ie_NOTIFICATION_INDICATOR, i, Q931Pie_NotifInd, Q931Uie_NotifInd); - Q931SetIEProc(Q931ie_DISPLAY, i, Q931Pie_Display, Q931Uie_Display); - Q931SetIEProc(Q931ie_DATETIME, i, Q931Pie_DateTime, Q931Uie_DateTime); - Q931SetIEProc(Q931ie_KEYPAD_FACILITY, i, Q931Pie_KeypadFac, Q931Uie_KeypadFac); - Q931SetIEProc(Q931ie_SIGNAL, i, Q931Pie_Signal, Q931Uie_Signal); - Q931SetIEProc(Q931ie_TRANSIT_DELAY_SELECTION_AND_IND, i, Q931Pie_TransNetSel, Q931Uie_TransNetSel); - Q931SetIEProc(Q931ie_CALLING_PARTY_NUMBER, i, Q931Pie_CallingNum, Q931Uie_CallingNum); - Q931SetIEProc(Q931ie_CALLING_PARTY_SUBADDRESS, i, Q931Pie_CallingSub, Q931Uie_CallingSub); - Q931SetIEProc(Q931ie_CALLED_PARTY_NUMBER, i, Q931Pie_CalledNum, Q931Uie_CalledNum); - Q931SetIEProc(Q931ie_CALLED_PARTY_SUBADDRESS, i, Q931Pie_CalledSub, Q931Uie_CalledSub); - Q931SetIEProc(Q931ie_TRANSIT_NETWORK_SELECTION, i, Q931Pie_TransNetSel, Q931Uie_TransNetSel); - Q931SetIEProc(Q931ie_RESTART_INDICATOR, i, Q931Pie_RestartInd, Q931Uie_RestartInd); - Q931SetIEProc(Q931ie_LOW_LAYER_COMPATIBILITY, i, Q931Pie_LLComp, Q931Uie_LLComp); - Q931SetIEProc(Q931ie_HIGH_LAYER_COMPATIBILITY, i, Q931Pie_HLComp, Q931Uie_HLComp); - Q931SetIEProc(Q931ie_USER_USER, i, Q931Pie_UserUser, Q931Uie_UserUser); - Q931SetIEProc(Q931ie_GENERIC_DIGITS, i, Q931Pie_GenericDigits, Q931Uie_GenericDigits); - - Q931SetIEProc(Q931ie_CONNECTED_NUMBER, i, Q931Pie_Generic, Q931Uie_Generic); - Q931SetIEProc(Q931ie_FACILITY, i, Q931Pie_Generic, Q931Uie_Generic); - - /* The following define a state machine. The point is that the Message */ - /* procs can when search this to find out if the message/state */ - /* combination is legale. If not, the proc for unexpected message apply.*/ - - /* State 0 Idle */ - Q931AddStateEntry(i, Q931_U0, Q931mes_RESUME, 2); - Q931AddStateEntry(i, Q931_U0, Q931mes_SETUP, 4); - Q931AddStateEntry(i, Q931_U0, Q931mes_SETUP, 2); - Q931AddStateEntry(i, Q931_U0, Q931mes_STATUS, 4); - Q931AddStateEntry(i, Q931_U0, Q931mes_RELEASE, 4); - Q931AddStateEntry(i, Q931_U0, Q931mes_RELEASE_COMPLETE, 4); - - /* State 1 Call Initiating */ - Q931AddStateEntry(i, Q931_U1, Q931mes_DISCONNECT, 2); - Q931AddStateEntry(i, Q931_U1, Q931mes_SETUP_ACKNOWLEDGE, 4); - Q931AddStateEntry(i, Q931_U1, Q931mes_RELEASE_COMPLETE, 4); - Q931AddStateEntry(i, Q931_U1, Q931mes_CALL_PROCEEDING, 4); - Q931AddStateEntry(i, Q931_U1, Q931mes_ALERTING, 4); - Q931AddStateEntry(i, Q931_U1, Q931mes_CONNECT, 4); - - /* State 2 Overlap Sending */ - Q931AddStateEntry(i, Q931_U2, Q931mes_INFORMATION, 2); - Q931AddStateEntry(i, Q931_U2, Q931mes_CALL_PROCEEDING, 4); - Q931AddStateEntry(i, Q931_U2, Q931mes_ALERTING, 4); - Q931AddStateEntry(i, Q931_U2, Q931mes_PROGRESS, 4); - Q931AddStateEntry(i, Q931_U2, Q931mes_CONNECT, 4); - Q931AddStateEntry(i, Q931_U2, Q931mes_RELEASE, 2); - - /* State 3 Outgoing Call Proceeding */ - Q931AddStateEntry(i, Q931_U3, Q931mes_PROGRESS, 4); - Q931AddStateEntry(i, Q931_U3, Q931mes_ALERTING, 4); - Q931AddStateEntry(i, Q931_U3, Q931mes_CONNECT, 4); - Q931AddStateEntry(i, Q931_U3, Q931mes_RELEASE, 2); - - /* State 4 Call Delivered */ - Q931AddStateEntry(i, Q931_U4, Q931mes_CONNECT, 4); - - /* State 6 Call Precent */ - Q931AddStateEntry(i, Q931_U6, Q931mes_INFORMATION, 2); - Q931AddStateEntry(i, Q931_U6, Q931mes_ALERTING, 2); - Q931AddStateEntry(i, Q931_U6, Q931mes_CALL_PROCEEDING, 2); - Q931AddStateEntry(i, Q931_U6, Q931mes_CONNECT, 2); - Q931AddStateEntry(i, Q931_U6, Q931mes_RELEASE_COMPLETE, 2); - Q931AddStateEntry(i, Q931_U6, Q931mes_RELEASE, 4); - Q931AddStateEntry(i, Q931_U6, Q931mes_DISCONNECT, 4); - - /* State 7 Call Received */ - Q931AddStateEntry(i, Q931_U7, Q931mes_CONNECT, 2); - - /* State 8 Connect request */ - Q931AddStateEntry(i, Q931_U8, Q931mes_CONNECT_ACKNOWLEDGE, 4); - - /* State 9 Incoming Call Proceeding */ - Q931AddStateEntry(i, Q931_U9, Q931mes_CONNECT, 2); - Q931AddStateEntry(i, Q931_U9, Q931mes_ALERTING, 2); - Q931AddStateEntry(i, Q931_U9, Q931mes_PROGRESS, 2); - - /* State 10 Active */ - Q931AddStateEntry(i, Q931_U10, Q931mes_SUSPEND, 2); - Q931AddStateEntry(i, Q931_U10, Q931mes_NOTIFY, 4); - Q931AddStateEntry(i, Q931_U10, Q931mes_NOTIFY, 2); - - /* State 11 Disconnect Request */ - Q931AddStateEntry(i, Q931_U11, Q931mes_RELEASE, 4); - Q931AddStateEntry(i, Q931_U11, Q931mes_DISCONNECT, 4); - Q931AddStateEntry(i, Q931_U11, Q931mes_NOTIFY, 4); - - /* State 12 Disconnect Ind */ - Q931AddStateEntry(i, Q931_U12, Q931mes_RELEASE, 4); - Q931AddStateEntry(i, Q931_U12, Q931mes_RELEASE, 2); - - /* State 15 Suspend Request */ - Q931AddStateEntry(i, Q931_U15, Q931mes_SUSPEND_ACKNOWLEDGE, 4); - Q931AddStateEntry(i, Q931_U15, Q931mes_SUSPEND_REJECT, 4); - Q931AddStateEntry(i, Q931_U15, Q931mes_DISCONNECT, 4); - Q931AddStateEntry(i, Q931_U15, Q931mes_RELEASE, 4); - -/* TODO - Q931AddStateEntry(i, Q931_U17, - Q931AddStateEntry(i, Q931_U19, - Q931AddStateEntry(i, Q931_U25, -*/ -} - -/***************************************************************************** - - Function: ATT5ESSProc0x0fTE - -*****************************************************************************/ -L3INT ATT5ESSProc0x0fTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - if (pMes->ProtDisc == 8) { - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - } - if (iFrom == 4) { - /* TODO Add proc here*/ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom ==2) { - /* TODO Add proc here*/ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - - if (pMes->ProtDisc == 3 && pTrunk->autoServiceAck) { - printf("autoServiceAck is on, responding to Service Req from network...\n"); - Q931AckService(pTrunk, buf); - } - } - return ret; - -} - -/***************************************************************************** - - Function: ATT5ESSProc0x07TE - -*****************************************************************************/ -L3INT ATT5ESSProc0x07TE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - if (pMes->ProtDisc == 8) { - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - } - if (iFrom == 4) { - /* TODO Add proc here*/ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here*/ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; - -} diff --git a/libs/freetdm/src/isdn/5ESSmes.c b/libs/freetdm/src/isdn/5ESSmes.c deleted file mode 100644 index 9d7e3b9030..0000000000 --- a/libs/freetdm/src/isdn/5ESSmes.c +++ /dev/null @@ -1,361 +0,0 @@ -/***************************************************************************** - - FileName: 5ESSmes.c - - Contents: Pack/Unpack functions. These functions will unpack a 5ESS ISDN - message from the bit packed original format into structs - that contains variables sized by the user. It will also pack - the struct back into a Q.931 message as required. - - See 5ESS.h for description. - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Copyright (c) 2007, Michael Jerris. All rights reserved. - email:mike@jerris.com - - Copyright (c) 2007, Michael S. Collins, All rights reserved. - email:mcollins@fcnetwork.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -*****************************************************************************/ - -#include "5ESS.h" - -/***************************************************************************** - - Function: ATT5ESSUmes_Setup - -*****************************************************************************/ -L3INT ATT5ESSUmes_Setup(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT ir = 0; - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - L3UCHAR last_codeset = 0, codeset = 0; - L3UCHAR shift_nolock = 1; - - while (IOff < Size) { - - if (shift_nolock) { - codeset = last_codeset; - } - - if ((IBuf[IOff] & 0xF0) == Q931ie_SHIFT) { - shift_nolock = (IBuf[IOff] & 0x08); - if (shift_nolock) { - last_codeset = codeset; - } - codeset = ((IBuf[IOff] & 0x07)); - IOff++; - } - - if (codeset == 0) { - switch (IBuf[IOff]) - { - case Q931ie_SENDING_COMPLETE: - case Q931ie_BEARER_CAPABILITY: - case Q931ie_CHANNEL_IDENTIFICATION: - case Q931ie_PROGRESS_INDICATOR: - case Q931ie_NETWORK_SPECIFIC_FACILITIES: - case Q931ie_DISPLAY: - case Q931ie_DATETIME: - case Q931ie_KEYPAD_FACILITY: - case Q931ie_SIGNAL: - case Q931ie_CALLING_PARTY_NUMBER: - case Q931ie_CALLING_PARTY_SUBADDRESS: - case Q931ie_CALLED_PARTY_NUMBER: - case Q931ie_CALLED_PARTY_SUBADDRESS: - case Q931ie_TRANSIT_NETWORK_SELECTION: - case Q931ie_LOW_LAYER_COMPATIBILITY: - case Q931ie_HIGH_LAYER_COMPATIBILITY: - case Q931ie_FACILITY: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - case Q931ie_REPEAT_INDICATOR: - if (ir < 2) { - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - ir++; - } else { - return Q931E_ILLEGAL_IE; - } - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } else if (codeset == 6) { - switch (IBuf[IOff]) - { - case Q931ie_GENERIC_DIGITS: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } else if (codeset == 7) { - switch (IBuf[IOff]) - { - case Q931ie_DISPLAY: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } else { - return Q931E_ILLEGAL_IE; - } - } - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: ATT5ESSPmes_Setup - - Decription: Pack a Q931mes_Generic into a real Q.931 message. The user will - set up a SETUP message and issue this to the stack where it - is processed by Q931ProcSetup that processes and validates - it before it actually sends it out. This function is called - to compute the real Q.931 message. - - Parameters: IBuf[IN] Ptr to un-packed struct - ISize[IN] Size of input buffer (unpacked message). - OBuf[OUT] Ptr to packed 'octet' wise message. - OSize[OUT] Size of packed message. - - Called By: Q931ProcSetup - -*****************************************************************************/ -L3INT ATT5ESSPmes_Setup(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - L3INT rc = Q931E_NO_ERROR; - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Sending Complete */ - if (Q931IsIEPresent(pMes->SendComplete)) { - OBuf[Octet++] = (L3UCHAR)(pMes->SendComplete & 0x00ff); - } - - /* Repeat Indicator */ - if (Q931IsIEPresent(pMes->RepeatInd)) { - OBuf[Octet++] = (L3UCHAR)(pMes->RepeatInd & 0x00ff); - } - - /* Bearer capability */ - if (Q931IsIEPresent(pMes->BearerCap)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_BEARER_CAPABILITY](pTrunk, Q931GetIEPtr(pMes->BearerCap,pMes->buf), OBuf, &Octet))!=0) - return rc; - } else { - rc = Q931E_BEARERCAP; - } - - /* Channel Identification */ - if (Q931IsIEPresent(pMes->ChanID)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CHANNEL_IDENTIFICATION](pTrunk, Q931GetIEPtr(pMes->ChanID,pMes->buf), OBuf, &Octet))!=0) - return rc; - } - - /* Progress indicator */ - if (Q931IsIEPresent(pMes->ProgInd)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_PROGRESS_INDICATOR](pTrunk, Q931GetIEPtr(pMes->ProgInd,pMes->buf), OBuf, &Octet))!=0) - return rc; - } - - /* Network specific facilities */ - if (Q931IsIEPresent(pMes->NetFac)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_NETWORK_SPECIFIC_FACILITIES](pTrunk, Q931GetIEPtr(pMes->NetFac,pMes->buf), OBuf, &Octet))!=0) - return rc; - } - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet))!=0) - return rc; - } - - /* Date/Time */ - if (Q931IsIEPresent(pMes->DateTime)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DATETIME](pTrunk, Q931GetIEPtr(pMes->DateTime,pMes->buf), OBuf, &Octet))!=0) - return rc; - } - - /* Keypad Facility */ - if (Q931IsIEPresent(pMes->KeypadFac)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_KEYPAD_FACILITY](pTrunk, Q931GetIEPtr(pMes->KeypadFac,pMes->buf), OBuf, &Octet))!=0) - return rc; - } - - /* Signal */ - if (Q931IsIEPresent(pMes->Signal)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_SIGNAL](pTrunk, Q931GetIEPtr(pMes->Signal,pMes->buf), OBuf, &Octet))!=0) - return rc; - } - - /* Calling Party Number */ - if (Q931IsIEPresent(pMes->CallingNum)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLING_PARTY_NUMBER](pTrunk, Q931GetIEPtr(pMes->CallingNum,pMes->buf), OBuf, &Octet))!=0) - return rc; - } - - /* Calling Party Subaddress */ - if (Q931IsIEPresent(pMes->CallingSub)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLING_PARTY_SUBADDRESS](pTrunk, Q931GetIEPtr(pMes->CallingSub,pMes->buf), OBuf, &Octet))!=0) - return rc; - } - - /* Called Party number */ - if (Q931IsIEPresent(pMes->CalledNum)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLED_PARTY_NUMBER](pTrunk, Q931GetIEPtr(pMes->CalledNum,pMes->buf), OBuf, &Octet))!=0) - return rc; - } - - /* Called party subaddress */ - if (Q931IsIEPresent(pMes->CalledSub)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLED_PARTY_SUBADDRESS](pTrunk, Q931GetIEPtr(pMes->CalledSub,pMes->buf), OBuf, &Octet))!=0) - return rc; - } - - /* Transit network selection */ - if (Q931IsIEPresent(pMes->TransNetSel)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_TRANSIT_NETWORK_SELECTION](pTrunk, Q931GetIEPtr(pMes->TransNetSel,pMes->buf), OBuf, &Octet))!=0) - return rc; - } - - /* Repeat Indicator */ - if (Q931IsIEPresent(pMes->LLRepeatInd)) { - rc = Q931E_UNKNOWN_IE;/* TODO */ - } - - /* Low Layer Compatibility */ - if (Q931IsIEPresent(pMes->LLComp)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_LOW_LAYER_COMPATIBILITY](pTrunk, Q931GetIEPtr(pMes->LLComp,pMes->buf), OBuf, &Octet))!=0) - return rc; - } - - /* High Layer Compatibility */ - if (Q931IsIEPresent(pMes->HLComp)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_HIGH_LAYER_COMPATIBILITY](pTrunk, Q931GetIEPtr(pMes->HLComp,pMes->buf), OBuf, &Octet))!=0) - return rc; - } - - *OSize = Octet; - return rc; -} - - -/***************************************************************************** - - Function: ATT5ESSUmes_0x0f - -*****************************************************************************/ -L3INT ATT5ESSUmes_0x0f(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - if (mes->ProtDisc == 8) { - return Q931Umes_ConnectAck(pTrunk, IBuf, mes, IOff, Size); - } - - if (mes->ProtDisc == 3) { - return Q931Umes_Service(pTrunk, IBuf, mes, IOff, Size); - } - - return Q931E_UNKNOWN_MESSAGE; -} - -/***************************************************************************** - - Function: ATT5ESSPmes_0x0f - -*****************************************************************************/ -L3INT ATT5ESSPmes_0x0f(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *mes = (Q931mes_Generic *)IBuf; - - if (mes->ProtDisc == 8) { - return Q931Pmes_ConnectAck(pTrunk, IBuf, ISize, OBuf, OSize); - } - - if (mes->ProtDisc == 3) { - return Q931Pmes_Service(pTrunk, IBuf, ISize, OBuf, OSize); - } - - return Q931E_UNKNOWN_MESSAGE; -} - -/***************************************************************************** - - Function: ATT5ESSUmes_0x07 - -*****************************************************************************/ -L3INT ATT5ESSUmes_0x07(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - if (mes->ProtDisc == 8) { - return Q931Umes_Connect(pTrunk, IBuf, mes, IOff, Size); - } - - if (mes->ProtDisc == 3) { - return Q931Umes_ServiceAck(pTrunk, IBuf, mes, IOff, Size); - } - - return Q931E_UNKNOWN_MESSAGE; -} - -/***************************************************************************** - - Function: ATT5ESSPmes_0x07 - -*****************************************************************************/ -L3INT ATT5ESSPmes_0x07(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *mes = (Q931mes_Generic *)IBuf; - - if (mes->ProtDisc == 8) { - return Q931Pmes_Connect(pTrunk, IBuf, ISize, OBuf, OSize); - } - - if (mes->ProtDisc == 3) { - return Q931Pmes_ServiceAck(pTrunk, IBuf, ISize, OBuf, OSize); - } - - return Q931E_UNKNOWN_MESSAGE; -} diff --git a/libs/freetdm/src/isdn/DMSStateNT.c b/libs/freetdm/src/isdn/DMSStateNT.c deleted file mode 100644 index e8814ba8ef..0000000000 --- a/libs/freetdm/src/isdn/DMSStateNT.c +++ /dev/null @@ -1,126 +0,0 @@ -/***************************************************************************** - - FileName: DMSStateNT.c - - Contents: DMS-100 ISDN State Engine for NT (Network Mode). - - The controlling state engine for Q.931 is the state engine - on the NT side. The state engine on the TE side is a slave - of this. The TE side maintain it's own states as described in - ITU-T Q931, but will in raise conditions be overridden by - the NT side. - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Copyright (c) 2007, Michael Jerris. All rights reserved. - email:mike@jerris.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -#include "DMS.h" - -/***************************************************************************** - Function: DMSCreateNT - - Description: Will create the National ISDN NT as a Dialect in the stack. The first - bulk set up the message handlers, the second bulk the IE - encoders/coders, and the last bulk set up the state table. - - Parameters: i Dialect index -*****************************************************************************/ -void DMSCreateNT(L3UCHAR i) -{ - Q931SetMesProc(Q931mes_ALERTING, i, Q931ProcAlertingNT, Q931Umes_Alerting, Q931Pmes_Alerting); - Q931SetMesProc(Q931mes_CALL_PROCEEDING, i, Q931ProcCallProceedingNT, Q931Umes_CallProceeding, Q931Pmes_CallProceeding); - Q931SetMesProc(Q931mes_CONNECT, i, Q931ProcConnectNT, Q931Umes_Connect, Q931Pmes_Connect); - Q931SetMesProc(Q931mes_CONNECT_ACKNOWLEDGE, i, Q931ProcConnectAckNT, Q931Umes_ConnectAck, Q931Pmes_ConnectAck); - Q931SetMesProc(Q931mes_PROGRESS, i, Q931ProcProgressNT, Q931Umes_Progress, Q931Pmes_Progress); - Q931SetMesProc(Q931mes_SETUP, i, Q931ProcSetupNT, DMSUmes_Setup, DMSPmes_Setup); - Q931SetMesProc(Q931mes_SETUP_ACKNOWLEDGE, i, Q931ProcSetupAckNT, Q931Umes_SetupAck, Q931Pmes_SetupAck); - Q931SetMesProc(Q931mes_RESUME, i, Q931ProcResumeNT, Q931Umes_Resume, Q931Pmes_Resume); - Q931SetMesProc(Q931mes_RESUME_ACKNOWLEDGE, i, Q931ProcResumeAckNT, Q931Umes_ResumeAck, Q931Pmes_ResumeAck); - Q931SetMesProc(Q931mes_RESUME_REJECT, i, Q931ProcResumeRejectNT, Q931Umes_ResumeReject, Q931Pmes_ResumeReject); - Q931SetMesProc(Q931mes_SUSPEND, i, Q931ProcSuspendNT, Q931Umes_Suspend, Q931Pmes_Suspend); - Q931SetMesProc(Q931mes_SUSPEND_ACKNOWLEDGE, i, Q931ProcSuspendAckNT, Q931Umes_SuspendAck, Q931Pmes_SuspendAck); - Q931SetMesProc(Q931mes_SUSPEND_REJECT, i, Q931ProcSuspendRejectNT, Q931Umes_SuspendReject, Q931Pmes_SuspendReject); - Q931SetMesProc(Q931mes_USER_INFORMATION, i, Q931ProcUserInformationNT, Q931Umes_UserInformation, Q931Pmes_UserInformation); - Q931SetMesProc(Q931mes_DISCONNECT, i, Q931ProcDisconnectNT, Q931Umes_Disconnect, Q931Pmes_Disconnect); - Q931SetMesProc(Q931mes_RELEASE, i, Q931ProcReleaseNT, Q931Umes_Release, Q931Pmes_Release); - Q931SetMesProc(Q931mes_RELEASE_COMPLETE, i, Q931ProcReleaseCompleteNT, Q931Umes_ReleaseComplete, Q931Pmes_ReleaseComplete); - Q931SetMesProc(Q931mes_RESTART, i, Q931ProcRestartNT, Q931Umes_Restart, Q931Pmes_Restart); - Q931SetMesProc(Q931mes_RESTART_ACKNOWLEDGE, i, Q931ProcRestartAckNT, Q931Umes_RestartAck, Q931Pmes_RestartAck); - Q931SetMesProc(Q931mes_CONGESTION_CONTROL, i, Q931ProcCongestionControlNT, Q931Umes_CongestionControl, Q931Pmes_CongestionControl); - Q931SetMesProc(Q931mes_INFORMATION, i, Q931ProcInformationNT, Q931Umes_Information, Q931Pmes_Information); - Q931SetMesProc(Q931mes_NOTIFY, i, Q931ProcNotifyNT, Q931Umes_Notify, Q931Pmes_Notify); - Q931SetMesProc(Q931mes_STATUS, i, Q931ProcStatusNT, Q931Umes_Status, Q931Pmes_Status); - Q931SetMesProc(Q931mes_STATUS_ENQUIRY, i, Q931ProcStatusEnquiryNT, Q931Umes_StatusEnquiry, Q931Pmes_StatusEnquiry); - Q931SetMesProc(Q931mes_SEGMENT, i, Q931ProcSegmentNT, Q931Umes_Segment, Q931Pmes_Segment); - - Q931SetMesProc(Q932mes_FACILITY, i, Q932ProcFacilityNT, Q932Umes_Facility, Q932Pmes_Facility); - Q931SetMesProc(Q932mes_HOLD, i, Q932ProcHoldNT, Q932Umes_Hold, Q932Pmes_Hold); - Q931SetMesProc(Q932mes_HOLD_ACKNOWLEDGE, i, Q932ProcHoldAckNT, Q932Umes_HoldAck, Q932Pmes_HoldAck); - Q931SetMesProc(Q932mes_HOLD_REJECT, i, Q932ProcHoldRejectNT, Q932Umes_HoldReject, Q932Pmes_HoldReject); - Q931SetMesProc(Q932mes_REGISTER, i, Q932ProcRegisterNT, Q932Umes_Register, Q932Pmes_Register); - Q931SetMesProc(Q932mes_RETRIEVE, i, Q932ProcRetrieveNT, Q932Umes_Retrieve, Q932Pmes_Retrieve); - Q931SetMesProc(Q932mes_RETRIEVE_ACKNOWLEDGE, i, Q932ProcRetrieveAckNT, Q932Umes_RetrieveAck, Q932Pmes_RetrieveAck); - Q931SetMesProc(Q932mes_RETRIEVE_REJECT, i, Q932ProcRetrieveRejectNT, Q932Umes_RetrieveReject, Q932Pmes_RetrieveReject); - - /* Set up the IE encoder/decoder handle table.*/ - Q931SetIEProc(Q931ie_SEGMENTED_MESSAGE, i, Q931Pie_Segment, Q931Uie_Segment); - Q931SetIEProc(Q931ie_BEARER_CAPABILITY, i, Q931Pie_BearerCap, Q931Uie_BearerCap); - Q931SetIEProc(Q931ie_CAUSE, i, Q931Pie_Cause, Q931Uie_Cause); - Q931SetIEProc(Q931ie_CALL_IDENTITY, i, Q931Pie_CallID, Q931Uie_CallID); - Q931SetIEProc(Q931ie_CALL_STATE, i, Q931Pie_CallState, Q931Uie_CallState); - Q931SetIEProc(Q931ie_CHANNEL_IDENTIFICATION, i, Q931Pie_ChanID, Q931Uie_ChanID); - Q931SetIEProc(Q931ie_PROGRESS_INDICATOR, i, Q931Pie_ProgInd, Q931Uie_ProgInd); - Q931SetIEProc(Q931ie_NETWORK_SPECIFIC_FACILITIES, i, Q931Pie_NetFac, Q931Uie_NetFac); - Q931SetIEProc(Q931ie_NOTIFICATION_INDICATOR, i, Q931Pie_NotifInd, Q931Uie_NotifInd); - Q931SetIEProc(Q931ie_DISPLAY, i, Q931Pie_Display, Q931Uie_Display); - Q931SetIEProc(Q931ie_DATETIME, i, Q931Pie_DateTime, Q931Uie_DateTime); - Q931SetIEProc(Q931ie_KEYPAD_FACILITY, i, Q931Pie_KeypadFac, Q931Uie_KeypadFac); - Q931SetIEProc(Q931ie_SIGNAL, i, Q931Pie_Signal, Q931Uie_Signal); - Q931SetIEProc(Q931ie_TRANSIT_DELAY_SELECTION_AND_IND, i, Q931Pie_TransNetSel, Q931Uie_TransNetSel); - Q931SetIEProc(Q931ie_CALLING_PARTY_NUMBER, i, Q931Pie_CallingNum, Q931Uie_CallingNum); - Q931SetIEProc(Q931ie_CALLING_PARTY_SUBADDRESS, i, Q931Pie_CallingSub, Q931Uie_CallingSub); - Q931SetIEProc(Q931ie_CALLED_PARTY_NUMBER, i, Q931Pie_CalledNum, Q931Uie_CalledNum); - Q931SetIEProc(Q931ie_CALLED_PARTY_SUBADDRESS, i, Q931Pie_CalledSub, Q931Uie_CalledSub); - Q931SetIEProc(Q931ie_TRANSIT_NETWORK_SELECTION, i, Q931Pie_TransNetSel, Q931Uie_TransNetSel); - Q931SetIEProc(Q931ie_RESTART_INDICATOR, i, Q931Pie_RestartInd, Q931Uie_RestartInd); - Q931SetIEProc(Q931ie_LOW_LAYER_COMPATIBILITY, i, Q931Pie_LLComp, Q931Uie_LLComp); - Q931SetIEProc(Q931ie_HIGH_LAYER_COMPATIBILITY, i, Q931Pie_HLComp, Q931Uie_HLComp); - Q931SetIEProc(Q931ie_USER_USER, i, Q931Pie_UserUser, Q931Uie_UserUser); - Q931SetIEProc(Q931ie_GENERIC_DIGITS, i, Q931Pie_GenericDigits, Q931Uie_GenericDigits); - - /* The following define a state machine. The point is that the Message */ - /* procs can when search this to find out if the message/state */ - /* combination is legale. If not, the proc for unexpected message apply.*/ - - /* TODO define state table here */ -} diff --git a/libs/freetdm/src/isdn/DMSStateTE.c b/libs/freetdm/src/isdn/DMSStateTE.c deleted file mode 100644 index cb740d3c2f..0000000000 --- a/libs/freetdm/src/isdn/DMSStateTE.c +++ /dev/null @@ -1,284 +0,0 @@ -/***************************************************************************** - - FileName: DMSStateTE.c - - Contents: DMS-100 ISDN State Engine for TE (User Mode). - - The controlling state engine for Q.931 is the state engine - on the NT side. The state engine on the TE side is a slave - of this. The TE side maintain it's own states as described in - ITU-T Q931, but will in raise conditions be overridden by - the NT side. - - This reference implementation uses a process per message, - meaning that each message must check call states. This - is easier for dialect maintenance as each message proc - can be replaced individually. A new TE variant only - need to copy the Q931CreateTE and replace those procs or - need to override. - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Copyright (c) 2007, Michael Jerris. All rights reserved. - email:mike@jerris.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -#include "DMS.h" -extern L3INT Q931L4HeaderSpace; - -/***************************************************************************** - Function: DMSCreateTE - - Description: Will create the National TE as a Dialect in the stack. The first - bulk set up the message handlers, the second bulk the IE - encoders/coders, and the last bulk set up the state table. - - Parameters: i Dialect index -*****************************************************************************/ -void DMSCreateTE(L3UCHAR i) -{ - Q931SetMesProc(Q931mes_ALERTING, i, Q931ProcAlertingTE, Q931Umes_Alerting, Q931Pmes_Alerting); - Q931SetMesProc(Q931mes_CALL_PROCEEDING, i, Q931ProcCallProceedingTE, Q931Umes_CallProceeding, Q931Pmes_CallProceeding); - Q931SetMesProc(Q931mes_CONNECT, i, DMSProc0x07TE, DMSUmes_0x07, DMSPmes_0x07); - Q931SetMesProc(Q931mes_CONNECT_ACKNOWLEDGE, i, DMSProc0x0fTE, DMSUmes_0x0f, DMSPmes_0x0f); - Q931SetMesProc(Q931mes_PROGRESS, i, Q931ProcProgressTE, Q931Umes_Progress, Q931Pmes_Progress); - Q931SetMesProc(Q931mes_SETUP, i, Q931ProcSetupTE, DMSUmes_Setup, DMSPmes_Setup); - Q931SetMesProc(Q931mes_SETUP_ACKNOWLEDGE, i, Q931ProcSetupAckTE, Q931Umes_SetupAck, Q931Pmes_SetupAck); - Q931SetMesProc(Q931mes_RESUME, i, Q931ProcResumeTE, Q931Umes_Resume, Q931Pmes_Resume); - Q931SetMesProc(Q931mes_RESUME_ACKNOWLEDGE, i, Q931ProcResumeAckTE, Q931Umes_ResumeAck, Q931Pmes_ResumeAck); - Q931SetMesProc(Q931mes_RESUME_REJECT, i, Q931ProcResumeRejectTE, Q931Umes_ResumeReject, Q931Pmes_ResumeReject); - Q931SetMesProc(Q931mes_SUSPEND, i, Q931ProcSuspendTE, Q931Umes_Suspend, Q931Pmes_Suspend); - Q931SetMesProc(Q931mes_SUSPEND_ACKNOWLEDGE, i, Q931ProcSuspendAckTE, Q931Umes_SuspendAck, Q931Pmes_SuspendAck); - Q931SetMesProc(Q931mes_SUSPEND_REJECT, i, Q931ProcSuspendRejectTE, Q931Umes_SuspendReject, Q931Pmes_SuspendReject); - Q931SetMesProc(Q931mes_USER_INFORMATION, i, Q931ProcUserInformationTE, Q931Umes_UserInformation, Q931Pmes_UserInformation); - Q931SetMesProc(Q931mes_DISCONNECT, i, Q931ProcDisconnectTE, Q931Umes_Disconnect, Q931Pmes_Disconnect); - Q931SetMesProc(Q931mes_RELEASE, i, Q931ProcReleaseTE, Q931Umes_Release, Q931Pmes_Release); - Q931SetMesProc(Q931mes_RELEASE_COMPLETE, i, Q931ProcReleaseCompleteTE, Q931Umes_ReleaseComplete, Q931Pmes_ReleaseComplete); - Q931SetMesProc(Q931mes_RESTART, i, Q931ProcRestartTE, Q931Umes_Restart, Q931Pmes_Restart); - Q931SetMesProc(Q931mes_RESTART_ACKNOWLEDGE, i, Q931ProcRestartAckTE, Q931Umes_RestartAck, Q931Pmes_RestartAck); - Q931SetMesProc(Q931mes_CONGESTION_CONTROL, i, Q931ProcCongestionControlTE, Q931Umes_CongestionControl, Q931Pmes_CongestionControl); - Q931SetMesProc(Q931mes_INFORMATION, i, Q931ProcInformationTE, Q931Umes_Information, Q931Pmes_Information); - Q931SetMesProc(Q931mes_NOTIFY, i, Q931ProcNotifyTE, Q931Umes_Notify, Q931Pmes_Notify); - Q931SetMesProc(Q931mes_STATUS, i, Q931ProcStatusTE, Q931Umes_Status, Q931Pmes_Status); - Q931SetMesProc(Q931mes_STATUS_ENQUIRY, i, Q931ProcStatusEnquiryTE, Q931Umes_StatusEnquiry, Q931Pmes_StatusEnquiry); - Q931SetMesProc(Q931mes_SEGMENT, i, Q931ProcSegmentTE, Q931Umes_Segment, Q931Pmes_Segment); - - Q931SetMesProc(Q932mes_FACILITY, i, Q932ProcFacilityTE, Q932Umes_Facility, Q932Pmes_Facility); - Q931SetMesProc(Q932mes_HOLD, i, Q932ProcHoldTE, Q932Umes_Hold, Q932Pmes_Hold); - Q931SetMesProc(Q932mes_HOLD_ACKNOWLEDGE, i, Q932ProcHoldAckTE, Q932Umes_HoldAck, Q932Pmes_HoldAck); - Q931SetMesProc(Q932mes_HOLD_REJECT, i, Q932ProcHoldRejectTE, Q932Umes_HoldReject, Q932Pmes_HoldReject); - Q931SetMesProc(Q932mes_REGISTER, i, Q932ProcRegisterTE, Q932Umes_Register, Q932Pmes_Register); - Q931SetMesProc(Q932mes_RETRIEVE, i, Q932ProcRetrieveTE, Q932Umes_Retrieve, Q932Pmes_Retrieve); - Q931SetMesProc(Q932mes_RETRIEVE_ACKNOWLEDGE, i, Q932ProcRetrieveAckTE, Q932Umes_RetrieveAck, Q932Pmes_RetrieveAck); - Q931SetMesProc(Q932mes_RETRIEVE_REJECT, i, Q932ProcRetrieveRejectTE, Q932Umes_RetrieveReject, Q932Pmes_RetrieveReject); - - /* Set up the IE encoder/decoder handle table.*/ - Q931SetIEProc(Q931ie_SEGMENTED_MESSAGE, i, Q931Pie_Segment, Q931Uie_Segment); - Q931SetIEProc(Q931ie_BEARER_CAPABILITY, i, Q931Pie_BearerCap, Q931Uie_BearerCap); - Q931SetIEProc(Q931ie_CAUSE, i, Q931Pie_Cause, Q931Uie_Cause); - Q931SetIEProc(Q931ie_CALL_IDENTITY, i, Q931Pie_CallID, Q931Uie_CallID); - Q931SetIEProc(Q931ie_CALL_STATE, i, Q931Pie_CallState, Q931Uie_CallState); - Q931SetIEProc(Q931ie_CHANGE_STATUS, i, Q931Pie_ChangeStatus, Q931Uie_ChangeStatus); - Q931SetIEProc(Q931ie_CHANNEL_IDENTIFICATION, i, Q931Pie_ChanID, Q931Uie_ChanID); - Q931SetIEProc(Q931ie_PROGRESS_INDICATOR, i, Q931Pie_ProgInd, Q931Uie_ProgInd); - Q931SetIEProc(Q931ie_NETWORK_SPECIFIC_FACILITIES, i, Q931Pie_NetFac, Q931Uie_NetFac); - Q931SetIEProc(Q931ie_NOTIFICATION_INDICATOR, i, Q931Pie_NotifInd, Q931Uie_NotifInd); - Q931SetIEProc(Q931ie_DISPLAY, i, Q931Pie_Display, Q931Uie_Display); - Q931SetIEProc(Q931ie_DATETIME, i, Q931Pie_DateTime, Q931Uie_DateTime); - Q931SetIEProc(Q931ie_KEYPAD_FACILITY, i, Q931Pie_KeypadFac, Q931Uie_KeypadFac); - Q931SetIEProc(Q931ie_SIGNAL, i, Q931Pie_Signal, Q931Uie_Signal); - Q931SetIEProc(Q931ie_TRANSIT_DELAY_SELECTION_AND_IND, i, Q931Pie_TransNetSel, Q931Uie_TransNetSel); - Q931SetIEProc(Q931ie_CALLING_PARTY_NUMBER, i, Q931Pie_CallingNum, Q931Uie_CallingNum); - Q931SetIEProc(Q931ie_CALLING_PARTY_SUBADDRESS, i, Q931Pie_CallingSub, Q931Uie_CallingSub); - Q931SetIEProc(Q931ie_CALLED_PARTY_NUMBER, i, Q931Pie_CalledNum, Q931Uie_CalledNum); - Q931SetIEProc(Q931ie_CALLED_PARTY_SUBADDRESS, i, Q931Pie_CalledSub, Q931Uie_CalledSub); - Q931SetIEProc(Q931ie_TRANSIT_NETWORK_SELECTION, i, Q931Pie_TransNetSel, Q931Uie_TransNetSel); - Q931SetIEProc(Q931ie_RESTART_INDICATOR, i, Q931Pie_RestartInd, Q931Uie_RestartInd); - Q931SetIEProc(Q931ie_LOW_LAYER_COMPATIBILITY, i, Q931Pie_LLComp, Q931Uie_LLComp); - Q931SetIEProc(Q931ie_HIGH_LAYER_COMPATIBILITY, i, Q931Pie_HLComp, Q931Uie_HLComp); - Q931SetIEProc(Q931ie_USER_USER, i, Q931Pie_UserUser, Q931Uie_UserUser); - Q931SetIEProc(Q931ie_GENERIC_DIGITS, i, Q931Pie_GenericDigits, Q931Uie_GenericDigits); - - /* The following define a state machine. The point is that the Message */ - /* procs can when search this to find out if the message/state */ - /* combination is legale. If not, the proc for unexpected message apply.*/ - - /* State 0 Idle */ - Q931AddStateEntry(i, Q931_U0, Q931mes_RESUME, 2); - Q931AddStateEntry(i, Q931_U0, Q931mes_SETUP, 4); - Q931AddStateEntry(i, Q931_U0, Q931mes_SETUP, 2); - Q931AddStateEntry(i, Q931_U0, Q931mes_STATUS, 4); - Q931AddStateEntry(i, Q931_U0, Q931mes_RELEASE, 4); - Q931AddStateEntry(i, Q931_U0, Q931mes_RELEASE_COMPLETE, 4); - - /* State 1 Call Initiating */ - Q931AddStateEntry(i, Q931_U1, Q931mes_DISCONNECT, 2); - Q931AddStateEntry(i, Q931_U1, Q931mes_SETUP_ACKNOWLEDGE, 4); - Q931AddStateEntry(i, Q931_U1, Q931mes_RELEASE_COMPLETE, 4); - Q931AddStateEntry(i, Q931_U1, Q931mes_CALL_PROCEEDING, 4); - Q931AddStateEntry(i, Q931_U1, Q931mes_ALERTING, 4); - Q931AddStateEntry(i, Q931_U1, Q931mes_CONNECT, 4); - - /* State 2 Overlap Sending */ - Q931AddStateEntry(i, Q931_U2, Q931mes_INFORMATION, 2); - Q931AddStateEntry(i, Q931_U2, Q931mes_CALL_PROCEEDING, 4); - Q931AddStateEntry(i, Q931_U2, Q931mes_ALERTING, 4); - Q931AddStateEntry(i, Q931_U2, Q931mes_PROGRESS, 4); - Q931AddStateEntry(i, Q931_U2, Q931mes_CONNECT, 4); - Q931AddStateEntry(i, Q931_U2, Q931mes_RELEASE, 2); - - /* State 3 Outgoing Call Proceeding */ - Q931AddStateEntry(i, Q931_U3, Q931mes_PROGRESS, 4); - Q931AddStateEntry(i, Q931_U3, Q931mes_ALERTING, 4); - Q931AddStateEntry(i, Q931_U3, Q931mes_CONNECT, 4); - Q931AddStateEntry(i, Q931_U3, Q931mes_RELEASE, 2); - - /* State 4 Call Delivered */ - Q931AddStateEntry(i, Q931_U4, Q931mes_CONNECT, 4); - - /* State 6 Call Precent */ - Q931AddStateEntry(i, Q931_U6, Q931mes_INFORMATION, 2); - Q931AddStateEntry(i, Q931_U6, Q931mes_ALERTING, 2); - Q931AddStateEntry(i, Q931_U6, Q931mes_CALL_PROCEEDING, 2); - Q931AddStateEntry(i, Q931_U6, Q931mes_CONNECT, 2); - Q931AddStateEntry(i, Q931_U6, Q931mes_RELEASE_COMPLETE, 2); - Q931AddStateEntry(i, Q931_U6, Q931mes_RELEASE, 4); - Q931AddStateEntry(i, Q931_U6, Q931mes_DISCONNECT, 4); - - /* State 7 Call Received */ - Q931AddStateEntry(i, Q931_U7, Q931mes_CONNECT, 2); - - /* State 8 Connect request */ - Q931AddStateEntry(i, Q931_U8, Q931mes_CONNECT_ACKNOWLEDGE, 4); - - /* State 9 Incoming Call Proceeding */ - Q931AddStateEntry(i, Q931_U9, Q931mes_CONNECT, 2); - Q931AddStateEntry(i, Q931_U9, Q931mes_ALERTING, 2); - Q931AddStateEntry(i, Q931_U9, Q931mes_PROGRESS, 2); - - /* State 10 Active */ - Q931AddStateEntry(i, Q931_U10, Q931mes_SUSPEND, 2); - Q931AddStateEntry(i, Q931_U10, Q931mes_NOTIFY, 4); - Q931AddStateEntry(i, Q931_U10, Q931mes_NOTIFY, 2); - - /* State 11 Disconnect Request */ - Q931AddStateEntry(i, Q931_U11, Q931mes_RELEASE, 4); - Q931AddStateEntry(i, Q931_U11, Q931mes_DISCONNECT, 4); - Q931AddStateEntry(i, Q931_U11, Q931mes_NOTIFY, 4); - - /* State 12 Disconnect Ind */ - Q931AddStateEntry(i, Q931_U12, Q931mes_RELEASE, 4); - Q931AddStateEntry(i, Q931_U12, Q931mes_RELEASE, 2); - - /* State 15 Suspend Request */ - Q931AddStateEntry(i, Q931_U15, Q931mes_SUSPEND_ACKNOWLEDGE, 4); - Q931AddStateEntry(i, Q931_U15, Q931mes_SUSPEND_REJECT, 4); - Q931AddStateEntry(i, Q931_U15, Q931mes_DISCONNECT, 4); - Q931AddStateEntry(i, Q931_U15, Q931mes_RELEASE, 4); - -/* TODO - Q931AddStateEntry(i, Q931_U17, - Q931AddStateEntry(i, Q931_U19, - Q931AddStateEntry(i, Q931_U25, -*/ -} - -/***************************************************************************** - - Function: DMSProc0x0fTE - -*****************************************************************************/ -L3INT DMSProc0x0fTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - if (pMes->ProtDisc == 8) { - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - } - if (iFrom == 4) { - /* TODO Add proc here*/ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here*/ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - - if (pMes->ProtDisc == 3 && pTrunk->autoServiceAck) { - Q931AckService(pTrunk, buf); - } - } - return ret; - -} - -/***************************************************************************** - - Function: DMSProc0x07TE - -*****************************************************************************/ -L3INT DMSProc0x07TE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - if (pMes->ProtDisc == 8) { - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - } - if (iFrom == 4) { - /* TODO Add proc here*/ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here*/ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; - -} diff --git a/libs/freetdm/src/isdn/DMSmes.c b/libs/freetdm/src/isdn/DMSmes.c deleted file mode 100644 index 3ce82f2ded..0000000000 --- a/libs/freetdm/src/isdn/DMSmes.c +++ /dev/null @@ -1,344 +0,0 @@ -/***************************************************************************** - - FileName: DMSmes.c - - Contents: Pack/Unpack functions. These functions will unpack a DMS-100 ISDN - message from the bit packed original format into structs - that contains variables sized by the user. It will also pack - the struct back into a Q.931 message as required. - - See national.h for description. - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Copyright (c) 2007, Michael Jerris. All rights reserved. - email:mike@jerris.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -*****************************************************************************/ - -#include "DMS.h" - -/***************************************************************************** - - Function: DMSUmes_Setup - -*****************************************************************************/ -L3INT DMSUmes_Setup(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT ir = 0; - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - L3UCHAR last_codeset = 0, codeset = 0; - L3UCHAR shift_lock = 1; - - while (IOff < Size) { - if (!shift_lock) { - codeset = last_codeset; - } - - if ((IBuf[IOff] & 0xF0) == Q931ie_SHIFT ) { - shift_lock = (IBuf[IOff] & 0x08); - if (shift_lock) { - last_codeset = codeset; - } - codeset = ((IBuf[IOff] & 0x07)); - IOff++; - } - - if (codeset == 0) { - switch (IBuf[IOff]) { - case Q931ie_SENDING_COMPLETE: - case Q931ie_BEARER_CAPABILITY: - case Q931ie_CHANNEL_IDENTIFICATION: - case Q931ie_PROGRESS_INDICATOR: - case Q931ie_NETWORK_SPECIFIC_FACILITIES: - case Q931ie_DISPLAY: - case Q931ie_DATETIME: - case Q931ie_KEYPAD_FACILITY: - case Q931ie_SIGNAL: - case Q931ie_CALLING_PARTY_NUMBER: - case Q931ie_CALLING_PARTY_SUBADDRESS: - case Q931ie_CALLED_PARTY_NUMBER: - case Q931ie_CALLED_PARTY_SUBADDRESS: - case Q931ie_TRANSIT_NETWORK_SELECTION: - case Q931ie_LOW_LAYER_COMPATIBILITY: - case Q931ie_HIGH_LAYER_COMPATIBILITY: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - case Q931ie_REPEAT_INDICATOR: - if (ir < 2) { - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - ir++; - } else { - return Q931E_ILLEGAL_IE; - } - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } else if (codeset == 6) { - switch (IBuf[IOff]) { - case Q931ie_GENERIC_DIGITS: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - - } else { - return Q931E_ILLEGAL_IE; - } - } - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: DMSPmes_Setup - - Decription: Pack a Q931mes_Generic into a real Q.931 message. The user will - set up a SETUP message and issue this to the stack where it - is processed by Q931ProcSetup that processes and validates - it before it actually sends it out. This function is called - to compute the real Q.931 message. - - Parameters: IBuf[IN] Ptr to un-packed struct - ISize[IN] Size of input buffer (unpacked message). - OBuf[OUT] Ptr to packed 'octet' wise message. - OSize[OUT] Size of packed message. - - Called By: Q931ProcSetup - -*****************************************************************************/ -L3INT DMSPmes_Setup(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - L3INT rc = Q931E_NO_ERROR; - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Sending Complete */ - if (Q931IsIEPresent(pMes->SendComplete)) { - OBuf[Octet++] = (L3UCHAR)(pMes->SendComplete & 0x00ff); - } - - /* Repeat Indicator */ - if (Q931IsIEPresent(pMes->RepeatInd)) { - OBuf[Octet++] = (L3UCHAR)(pMes->RepeatInd & 0x00ff); - } - - /* Bearer capability */ - if (Q931IsIEPresent(pMes->BearerCap)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_BEARER_CAPABILITY](pTrunk, Q931GetIEPtr(pMes->BearerCap,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } else { - rc = Q931E_BEARERCAP; - } - - /* Channel Identification */ - if (Q931IsIEPresent(pMes->ChanID)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CHANNEL_IDENTIFICATION](pTrunk, Q931GetIEPtr(pMes->ChanID,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Progress indicator */ - if (Q931IsIEPresent(pMes->ProgInd)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_PROGRESS_INDICATOR](pTrunk, Q931GetIEPtr(pMes->ProgInd,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Network spesific facilities */ - if (Q931IsIEPresent(pMes->NetFac)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_NETWORK_SPECIFIC_FACILITIES](pTrunk, Q931GetIEPtr(pMes->NetFac,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Date/Time */ - if (Q931IsIEPresent(pMes->DateTime)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DATETIME](pTrunk, Q931GetIEPtr(pMes->DateTime,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Keypad Facility */ - if (Q931IsIEPresent(pMes->KeypadFac)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_KEYPAD_FACILITY](pTrunk, Q931GetIEPtr(pMes->KeypadFac,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Signal */ - if (Q931IsIEPresent(pMes->Signal)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_SIGNAL](pTrunk, Q931GetIEPtr(pMes->Signal,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Calling Party Number */ - if (Q931IsIEPresent(pMes->CallingNum)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLING_PARTY_NUMBER](pTrunk, Q931GetIEPtr(pMes->CallingNum,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Calling Party Subaddress */ - if (Q931IsIEPresent(pMes->CallingSub)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLING_PARTY_SUBADDRESS](pTrunk, Q931GetIEPtr(pMes->CallingSub,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Called Party number */ - if (Q931IsIEPresent(pMes->CalledNum)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLED_PARTY_NUMBER](pTrunk, Q931GetIEPtr(pMes->CalledNum,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - - /* Called party subaddress */ - if (Q931IsIEPresent(pMes->CalledSub)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLED_PARTY_SUBADDRESS](pTrunk, Q931GetIEPtr(pMes->CalledSub,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Transit network selection */ - if (Q931IsIEPresent(pMes->TransNetSel)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_TRANSIT_NETWORK_SELECTION](pTrunk, Q931GetIEPtr(pMes->TransNetSel,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Repeat Indicator */ - if (Q931IsIEPresent(pMes->LLRepeatInd)) { - rc = Q931E_UNKNOWN_IE;/* TODO */ - } - - /* Low Layer Compatibility */ - if (Q931IsIEPresent(pMes->LLComp)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_LOW_LAYER_COMPATIBILITY](pTrunk, Q931GetIEPtr(pMes->LLComp,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* High Layer Compatibility */ - if (Q931IsIEPresent(pMes->HLComp)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_HIGH_LAYER_COMPATIBILITY](pTrunk, Q931GetIEPtr(pMes->HLComp,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - - -/***************************************************************************** - - Function: DMSUmes_0x0f - -*****************************************************************************/ -L3INT DMSUmes_0x0f(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - if (mes->ProtDisc == 8) { - return Q931Umes_ConnectAck(pTrunk, IBuf, mes, IOff, Size); - } - - if (mes->ProtDisc == 3) { - return Q931Umes_Service(pTrunk, IBuf, mes, IOff, Size); - } - - return Q931E_UNKNOWN_MESSAGE; -} - -/***************************************************************************** - - Function: DMSPmes_0x0f - -*****************************************************************************/ -L3INT DMSPmes_0x0f(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *mes = (Q931mes_Generic *)IBuf; - - if (mes->ProtDisc == 8) { - return Q931Pmes_ConnectAck(pTrunk, IBuf, ISize, OBuf, OSize); - } - - if (mes->ProtDisc == 3) { - return Q931Pmes_Service(pTrunk, IBuf, ISize, OBuf, OSize); - } - - return Q931E_UNKNOWN_MESSAGE; -} - -/***************************************************************************** - - Function: DMSUmes_0x07 - -*****************************************************************************/ -L3INT DMSUmes_0x07(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - if (mes->ProtDisc == 8) { - return Q931Umes_Connect(pTrunk, IBuf, mes, IOff, Size); - } - - if (mes->ProtDisc == 3) { - return Q931Umes_ServiceAck(pTrunk, IBuf, mes, IOff, Size); - } - - return Q931E_UNKNOWN_MESSAGE; -} - -/***************************************************************************** - - Function: DMSPmes_0x07 - -*****************************************************************************/ -L3INT DMSPmes_0x07(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *mes = (Q931mes_Generic *)IBuf; - - if (mes->ProtDisc == 8) { - return Q931Pmes_Connect(pTrunk, IBuf, ISize, OBuf, OSize); - } - - if (mes->ProtDisc == 3) { - return Q931Pmes_ServiceAck(pTrunk, IBuf, ISize, OBuf, OSize); - } - - return Q931E_UNKNOWN_MESSAGE; -} diff --git a/libs/freetdm/src/isdn/EuroISDNStateNT.c b/libs/freetdm/src/isdn/EuroISDNStateNT.c deleted file mode 100644 index 6b26c91e04..0000000000 --- a/libs/freetdm/src/isdn/EuroISDNStateNT.c +++ /dev/null @@ -1,44 +0,0 @@ -/***************************************************************************** - - FileName: EuroISDNStateNT.c - - Contents: EuroISDN State Engine for NT (Network Mode). - - The controlling state engine for Q.931 is the state engine - on the NT side. The state engine on the TE side is a slave - of this. The TE side maintain it's own states as described in - ITU-T Q931, but will in raise conditions be overridden by - the NT side. - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -#include "Q931.h" diff --git a/libs/freetdm/src/isdn/EuroISDNStateTE.c b/libs/freetdm/src/isdn/EuroISDNStateTE.c deleted file mode 100644 index ef6b39e8e5..0000000000 --- a/libs/freetdm/src/isdn/EuroISDNStateTE.c +++ /dev/null @@ -1,58 +0,0 @@ -/***************************************************************************** - - FileName: EuroISDNStateTE.c - - Contents: EuroISDN State Engine for TE (User Mode). - - The controlling state engine for Q.931 is the state engine - on the NT side. The state engine on the TE side is a slave - of this. The TE side maintain it's own states as described in - ITU-T Q931, but will in raise conditions be overridden by - the NT side. - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -#include "Q931.h" - -/* - EuroISDN is a sub-set of Q.931. Q.931 is very generic as it embrase a lot, - while EuroISDN is more exact and make decitions on some of the - 'implementation options' in the original standard. EuroISDN will - however run smoothly under the generic space, so these functions are more - for show -*/ -#if 0 -static void EuroISDNCreateTE(L3UCHAR i) -{ - Q931CreateTE(i); -} -#endif diff --git a/libs/freetdm/src/isdn/Q921.c b/libs/freetdm/src/isdn/Q921.c deleted file mode 100644 index d1cbab6e6f..0000000000 --- a/libs/freetdm/src/isdn/Q921.c +++ /dev/null @@ -1,3518 +0,0 @@ -/***************************************************************************** - - FileName: q921.c - - Description: Contains the implementation of a Q.921 protocol - - Created: 27.dec.2000/JVB - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -*****************************************************************************/ - -/**************************************************************************** - * Changes: - * - * - June-August 2008: Stefan Knoblich : - * Add PTMP TEI management (NT + TE mode) - * Add timers - * Add retransmit counters - * Add logging - * Various cleanups - * Queues, retransmission of I frames - * PTMP NT mode - * - * - * TODO: - * - * - Cleanup queueing, test retransmission - * - * - Q921Start() /-Stop() TEI acquire + release - * (move everything related into these functions) - * - * - Q.921 '97 Appendix I (and maybe III, IV) - * - * - More complete Appendix II - * - * - Test PTP mode - * - * - PTMP NT mode (in progress) - * - * - NT mode TEI management: (ab)use T202 for TEI Check Request retransmission - * - * - General cleanup (move all non-public declarations into private header file) - * - * - Statistics, per-Frame type debug message filter - * - ****************************************************************************/ - -#include -#include -#include -#include - -#include "freetdm.h" -#include "Q921.h" -#include "Q921priv.h" -#include "mfifo.h" - -#ifdef WIN32 -#pragma warning(disable:4100 4244) -#endif - -/****************************************************************************************************** - * Actual code below this line - ******************************************************************************************************/ - - -/** - * Q921StateNames - * \brief Static array of state name / value mappings - */ -static struct Q921StateName { - Q921State_t value; - const char *name; -} Q921StateNames[10] = { - { Q921_STATE_STOPPED, "Stopped" }, - { Q921_STATE_TEI_UNASSIGNED, "TEI Unassigned" }, - { Q921_STATE_TEI_AWAITING, "TEI Awaiting Assignment" }, - { Q921_STATE_TEI_ESTABLISH, "TEI Awaiting Establishment" }, - { Q921_STATE_TEI_ASSIGNED, "TEI Assigned" }, - { Q921_STATE_AWAITING_ESTABLISHMENT, "Awaiting Establishment" }, - { Q921_STATE_AWAITING_RELEASE, "Awaiting Release" }, - { Q921_STATE_MULTIPLE_FRAME_ESTABLISHED, "Multiple Frame Mode Established" }, - { Q921_STATE_TIMER_RECOVERY, "Timer Recovery" }, - { 0, 0 } -}; - -/** - * Q921State2Name - * \brief Convert state value to name - * \param[in] state the state value - * \return the state name or "Unknown" - * - * \author Stefan Knoblich - */ -static const char *Q921State2Name(Q921State_t state) -{ - struct Q921StateName *p = Q921StateNames; - - while(p->name) { - if(p->value == state) - return p->name; - p++; - } - - return "Unknown"; -} - - -/** - * Q921SendEnquiry - */ -static int Q921SendEnquiry(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - /* send enquiry: begin */ - if(Q921_CHECK_FLAG(link, Q921_FLAG_RECV_BUSY)) { - - Q921SendRNR(trunk, trunk->sapi, Q921_COMMAND(trunk), tei, 1); - } - else { - Q921SendRR(trunk, trunk->sapi, Q921_COMMAND(trunk), tei, 1); - } - - /* clear acknowledge pending */ - Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING); - - /* "Start" T200 */ - Q921T200TimerReset(trunk, tei); - - /* send enquiry: end */ - return 1; -} - -/** - * Q921SendEnquiryResponse - */ -static int Q921SendEnquiryResponse(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - /* send enquiry: begin */ - if(Q921_CHECK_FLAG(link, Q921_FLAG_RECV_BUSY)) { - - Q921SendRNR(trunk, trunk->sapi, Q921_RESPONSE(trunk), tei, 1); - } - else { - Q921SendRR(trunk, trunk->sapi, Q921_RESPONSE(trunk), tei, 1); - - /* clear acknowledge pending */ - Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING); - } - /* send enquiry: end */ - return 1; -} - -/** - * Q921ResetExceptionConditions - * \brief Reset Q.921 Exception conditions procedure - * \param trunk Q.921 data structure - * \param tei TEI - * \todo Do something - */ -static void Q921ResetExceptionConditions(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - /* Clear peer receiver busy */ - Q921_CLEAR_FLAG(link, Q921_FLAG_PEER_RECV_BUSY); - - /* Clear reject exception */ - Q921_CLEAR_FLAG(link, Q921_FLAG_REJECT); - - /* Clear own receiver busy */ - Q921_CLEAR_FLAG(link, Q921_FLAG_RECV_BUSY); - - /* Clear acknowledge pending */ - Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING); - - return; -} - -/** - * Q921EstablishDataLink - * \brief Q.921 Establish data link procedure - * \param trunk Q.921 data structure - * \param tei TEI - * \return always 1 (success) - */ -static int Q921EstablishDataLink(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - /* reset exception conditions */ - Q921ResetExceptionConditions(trunk, tei); - - /* RC = 0 */ - link->N200 = 0; - - /* Send SABME */ - Q921SendSABME(trunk, trunk->sapi, Q921_COMMAND(trunk), tei, 1); - - /* Restart T200, stop T203 */ - Q921T200TimerReset(trunk, tei); - Q921T203TimerStop(trunk, tei); - - return 1; -} - -/** - * Q921NrErrorRecovery - * \brief NR(R) Error recovery procedure - * \param trunk Q.921 data structure - * \param tei TEI - * \return always 1 (success) - */ -static int Q921NrErrorRecovery(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - /* MDL Error indication (J) */ - - /* Establish datalink */ - Q921EstablishDataLink(trunk, tei); - - /* Clear L3 initiated */ - Q921_CLEAR_FLAG(link, Q921_FLAG_L3_INITIATED); - - return 1; -} - - -/** - * Q921InvokeRetransmission - * \brief I Frame retransmission procedure - * \param trunk Q.921 data structure - * \param tei TEI - * \param nr N(R) for retransmission - * \return always 1 (success) - */ -static int Q921InvokeRetransmission(L2TRUNK trunk, L2UCHAR tei, L2UCHAR nr) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - L2UCHAR *mes; - L2INT qpos, qnum, size = 0; - - qnum = MFIFOGetMesCount(link->IFrameResendQueue); - qpos = qnum - 1; - - /* - * slightly different than what is shown in the spec - * (Q.921 '97 Annex B, Figure B.9, page 104) - * - * what the above mentioned figure probably means is: - * "as long as V(S) != N(R), move the pointer marking - * the first frame to start resending at to the previous - * frame" - * - * if we actually implemented it as shown in the figure, we'd be - * resending frames in the wrong order (moving backwards in time) - * meaning we'd have to add an incoming queue to reorder the frames - * - */ - /* - * TODO: There's a "traditional" off-by-one error hidden in the original - * mfifo implementation + it's late, i'm tired and being lazy, - * so i'll probably have added another one :P - * - * wow, the first while loop sucks and can be removed - */ - while(link->vs != nr && qpos > 0) { /* ???? */ - /* V(S) = V(S) - 1 */ - Q921_DEC_COUNTER(link->vs); /* huh? backwards? */ - - /* next frame in queue (backtrack along I queue) ??? */ - qpos--; - } - - /* - * being lazy and trying to avoid mod 128 math this way... - */ - if(link->vs != nr && !qpos) { - /* fatal, we don't have enough history to resend all missing frames */ - /* TODO: how to handle this? */ - } - - /* - * resend frames in correct order (oldest missing frame first, - * contrary to what the spec figure shows) - */ - while(qpos < qnum) { - /* Grab frame's buffer ptr and size from queue */ - mes = MFIFOGetMesPtrOffset(link->IFrameResendQueue, &size, qpos); - if(mes) { - /* requeue frame (TODO: check queue full condition) */ - MFIFOWriteMes(link->IFrameQueue, mes, size); - - /* set I frame queued */ - } - - qpos++; - } - - return 1; -} - - -static int Q921AcknowledgePending(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - switch(link->state) { - case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED: - case Q921_STATE_TIMER_RECOVERY: - if(Q921_CHECK_FLAG(link, Q921_FLAG_ACK_PENDING)) { - /* clear acknowledge pending */ - Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING); - - /* send RR */ - Q921SendRR(trunk, trunk->sapi, Q921_COMMAND(trunk), tei, 0); - - return 1; - } - break; - - default: - break; - } - - return 0; -} - -/***************************************************************************** - - Function: Q921_InitTrunk - - Decription: Initialize a Q.921 trunk so it is ready for use. This - function MUST be called before you call any other functions. - -*****************************************************************************/ -int Q921_InitTrunk(L2TRUNK trunk, - L2UCHAR sapi, - L2UCHAR tei, - Q921NetUser_t NetUser, - Q921NetType_t NetType, - L2INT hsize, - Q921Tx21CB_t cb21, - Q921Tx23CB_t cb23, - void *priv21, - void *priv23) -{ - int numlinks = 0; - - trunk->sapi = sapi; - trunk->tei = tei; - trunk->NetUser = NetUser; - trunk->NetType = NetType; - trunk->Q921Tx21Proc = cb21; - trunk->Q921Tx23Proc = cb23; - trunk->PrivateData21 = priv21; - trunk->PrivateData23 = priv23; - trunk->Q921HeaderSpace = hsize; - - numlinks = Q921_IS_PTMP_NT(trunk) ? Q921_TEI_MAX : 1; - - if (trunk->initialized != INITIALIZED_MAGIC) { - MFIFOCreate(trunk->HDLCInQueue, Q921MAXHDLCSPACE, 10); - - /* - * Allocate space for per-link context(s) - */ - trunk->context = ftdm_malloc(numlinks * sizeof(struct Q921_Link)); - if(!trunk->context) - return -1; - - trunk->initialized = INITIALIZED_MAGIC; - } - - /* timeout default values */ - trunk->T200Timeout = 1000; /* 1 second */ - trunk->T203Timeout = 10000; /* 10 seconds */ - trunk->T202Timeout = 2000; /* 2 seconds */ - trunk->T201Timeout = 200000; /* 200 seconds */ - trunk->TM01Timeout = 10000; /* 10 seconds */ - - /* octet / retransmit counter default limits */ - trunk->N200Limit = 3; /* 3 retransmits */ - trunk->N201Limit = 260; /* 260 octets */ - trunk->N202Limit = 3; /* 3 retransmits */ - trunk->k = 7; /* 7 outstanding ACKs */ - - /* reset counters, timers, etc. */ - trunk->T202 = 0; - trunk->N202 = 0; - - /* Reset per-link contexts */ - memset(trunk->context, 0, numlinks * sizeof(struct Q921_Link)); - - /* clear tei map */ - memset(trunk->tei_map, 0, Q921_TEI_MAX + 1); - - if(Q921_IS_PTMP(trunk)) { - /* - * We're either the Network side (NT, TEI = 0) - * or user-side equipment (TE) which will get it's TEI via - * dynamic assignment - */ - trunk->tei = 0; - } - - return 0; -} - - -/** - * Q921Tx21Proc - * \brief Submit frame to layer 1 (for sending) - * \param[in] trunk Pointer to trunk struct - * \param[in] mes pointer to message buffer - * \param[in] size size of message - * \return > 0 on success; <= 0 on error - */ -static int Q921Tx21Proc(L2TRUNK trunk, L2UCHAR *Msg, L2INT size) -{ - Q921LogMesg(trunk, Q921_LOG_DEBUG, 0, Msg, size, "Sending frame"); - - return trunk->Q921Tx21Proc(trunk->PrivateData21, Msg, size); -} - - -/** - * Q921Tx23Proc - * \brief Submit frame to layer 3 - * \param[in] trunk Pointer to trunk struct - * \param[in] mes pointer to message buffer - * \param[in] size size of message - * \return > 0 on success; <= 0 on error - */ -static int Q921Tx23Proc(L2TRUNK trunk, Q921DLMsg_t ind, L2UCHAR tei, L2UCHAR *Msg, L2INT size) -{ - return trunk->Q921Tx23Proc(trunk->PrivateData23, ind, tei, Msg, size); -} - - -/** - * Q921LogProc - * \brief Used for logging, converts to string and submits to higher level log function via callback - * \param[in] trunk Pointer to trunk struct - * \param[in] level Q921 Loglevel - * \param[in] fmt format of logmessage - * \return >= 0 on success, < 0 on error - * - * \author Stefan Knoblich - */ -static int Q921Log(L2TRUNK trunk, Q921LogLevel_t level, const char *fmt, ...) -{ - char buf[Q921_LOGBUFSIZE]; - L2INT len; - va_list ap; - - if(!trunk->Q921LogProc) - return 0; - - if(trunk->loglevel < level) - return 0; - - va_start(ap, fmt); - - len = vsnprintf(buf, sizeof(buf)-1, fmt, ap); - if(len <= 0) { - /* TODO: error handling */ - return -1; - } - if(len >= sizeof(buf)) - len = sizeof(buf) - 1; - - buf[len] = '\0'; - - va_end(ap); - - return trunk->Q921LogProc(trunk->PrivateDataLog, level, buf, len); -} - - -static int print_hex(char *buf, int bsize, const unsigned char *in, const int len) -{ - static const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - int offset = 0; - int pos = 0; - int nr = 0; - - buf[pos++] = '['; - bsize -= 3; - - while((bsize - pos) > 0 && offset < len) { - buf[pos++] = hex[(in[offset] & 0xF0) >> 4]; - buf[pos++] = hex[(in[offset++] & 0x0F)]; - - if(++nr == 32 && offset < len && (bsize - pos) > 3) { - nr = 0; - buf[pos++] = ']'; - buf[pos++] = '\n'; - buf[pos++] = '['; - } - else if(offset < len) { - buf[pos++] = ' '; - } - } - - buf[pos++] = ']'; - buf[pos++] = '\n'; - buf[pos] = '\0'; - - return pos; -} - -#define APPEND_MSG(buf, off, lef, fmt, ...) \ - len = snprintf(buf + off, lef, fmt, ##__VA_ARGS__); \ - if(len > 0) { \ - off += len; \ - lef -= len; \ - } else { \ - goto out; \ - } - -/** - * Q921LogProcMesg - * \brief Used for logging, converts to string and submits to higher level log function via callback - * \param[in] trunk Pointer to trunk struct - * \param[in] level Q921 Loglevel - * \param[in] received direction of the message (received = 1, sending = 0) - * \param[in] mes pointer to message buffer - * \param[in] size size of message - * \param[in] fmt format of logmessage - * \return >= 0 on success, < 0 on error - * - * \author Stefan Knoblich - */ -static int Q921LogMesg(L2TRUNK trunk, Q921LogLevel_t level, L2UCHAR received, L2UCHAR *mes, L2INT size, const char *fmt, ...) -{ - char buf[Q921_LOGBUFSIZE]; - size_t len, left; - va_list ap; - - if(!trunk->Q921LogProc) - return 0; - - if(trunk->loglevel < level) - return 0; - - if(!mes) - return 0; - - memset(buf, 0, sizeof(buf)); - - left = sizeof(buf) - 1; - - va_start(ap, fmt); - - len = vsnprintf(buf, left, fmt, ap); - if(len > 0) - left -= len; - else { - /* TODO: error handling */ - return -1; - } - - va_end(ap); - - if(trunk->loglevel == Q921_LOG_DEBUG) { - char pbuf[1024]; - size_t pleft, poffset; - L2UCHAR sapi, tei, cr; - L2UCHAR *pmes = mes + trunk->Q921HeaderSpace; - struct Q921_Link *link; - - memset(pbuf, 0, sizeof(pbuf)); - - pleft = sizeof(pbuf); - poffset = 0; - - /* - * Decode packet - */ - sapi = (pmes[0] & 0xfc) >> 2; - cr = (pmes[0] & 0x02) >> 1; - tei = (pmes[1] & 0xfe) >> 1; - link = Q921_LINK_CONTEXT(trunk, tei); - - /* make cr actually useful */ - cr = (received) ? Q921_IS_COMMAND(trunk, cr) : Q921_IS_RESPONSE(trunk, cr); - - /* filter */ - if((pmes[2] & 0x01) == 0x00) { - ; - } - else if((pmes[2] & 0x03) == 0x01) { - ; //return 0; - } - else if((pmes[2] & 0x03) == 0x03) { - ; - } - - APPEND_MSG(pbuf, poffset, pleft, "\n----------------- Q.921 Packet [%s%s] ---------------\n", received ? "Incoming" : "Outgoing", - (tei == link->tei || tei == Q921_TEI_BCAST) ? "" : ", Ignored" ); - - /* common header */ - APPEND_MSG(pbuf, poffset, pleft, " SAPI: %u, TEI: %u, C/R: %s (%d)\n\n", sapi, tei, (cr) ? "Command" : "Response", (mes[0] & 0x02) >> 1 ); - - /* - * message specific - */ - if((pmes[2] & 0x01) == 0x00) { - /* - * I frame - */ - L2UCHAR pf = pmes[3] & 0x01; /* poll / final flag */ - L2UCHAR nr = pmes[3] >> 1; /* receive sequence number */ - L2UCHAR ns = pmes[2] >> 1; /* send sequence number */ - - APPEND_MSG(pbuf, poffset, pleft, " Type: I Frame\n P/F: %d, N(S): %d, N(R): %d [V(A): %d, V(R): %d, V(S): %d]\n", pf, ns, nr, - link->va, link->vr, link->vs); - - /* Dump content of I Frames for foreign TEIs */ - if(tei != link->tei) { - APPEND_MSG(pbuf, poffset, pleft, " CONTENT:\n"); - - len = print_hex(pbuf + poffset, (int)pleft, &pmes[4], size - (trunk->Q921HeaderSpace + 4)); - poffset += len; - pleft -= len; - } - } - else if((pmes[2] & 0x03) == 0x01) { - /* - * S frame - */ - L2UCHAR sv = (pmes[2] & 0x0c) >> 2; /* supervisory format id */ - L2UCHAR pf = pmes[3] & 0x01; /* poll / final flag */ - L2UCHAR nr = pmes[3] >> 1; /* receive sequence number */ - const char *type; - - switch(sv) { - case 0x00: /* RR : Receive Ready */ - type = "RR (Receive Ready)"; - break; - - case 0x02: /* RNR : Receive Not Ready */ - type = "RNR (Receiver Not Ready)"; - break; - - case 0x04: /* REJ : Reject */ - type = "REJ (Reject)"; - break; - - default: /* Invalid / Unknown */ - type = "Unknown"; - break; - } - - APPEND_MSG(pbuf, poffset, pleft, " Type: S Frame, SV: %s\n P/F: %d, N(R): %d [V(A): %d, V(R): %d, V(S): %d]\n", type, pf, nr, - link->va, link->vr, link->vs); - } - else if((pmes[2] & 0x03) == 0x03) { - /* - * U frame - */ - L2UCHAR m = (pmes[2] & 0xe0) >> 3 | (pmes[2] & 0x0c) >> 2; /* modifier function id */ - L2UCHAR pf = (pmes[2] & 0x10) >> 4; /* poll / final flag */ - const char *type; - - switch(m) { - case 0x00: - type = "UI (Unnumbered Information)"; - break; - - case 0x03: - type = "DM (Disconnected Mode)"; - break; - - case 0x08: - type = "DISC (Disconnect)"; - break; - - case 0x0c: - type = "UA (Unnumbered Acknowledgement)"; - break; - - case 0x0f: - type = "SABME"; - break; - - case 0x11: - type = "FRMR (Frame Reject)"; - break; - - case 0x17: - type = "XID (Exchange Identification)"; - break; - - default: - type = "Unknown"; - } - - - APPEND_MSG(pbuf, poffset, pleft, " Type: U Frame (%s)\n P/F: %d\n", type, pf); - - if(m == 0x00) { - switch(pmes[3]) { - case Q921_LAYER_ENT_ID_TEI: - type = "TEI Mgmt"; - break; - - case Q921_LAYER_ENT_ID_Q931: - type = "Q.931"; - break; - - default: - type = "Unknown"; - } - - if(pmes[3] == Q921_LAYER_ENT_ID_TEI) { - const char *command = ""; - - switch(pmes[6]) { - case Q921_TEI_ID_REQUEST: - command = "Request"; - break; - case Q921_TEI_ID_VERIFY: - command = "Verify"; - break; - case Q921_TEI_ID_CHECKREQ: - command = "Check req"; - break; - case Q921_TEI_ID_CHECKRESP: - command = "Check resp"; - break; - case Q921_TEI_ID_REMOVE: - command = "Remove"; - break; - case Q921_TEI_ID_ASSIGNED: - command = "Assign"; - break; - case Q921_TEI_ID_DENIED: - command = "Denied"; - break; - } - APPEND_MSG(pbuf, poffset, pleft, " ENT ID: %d (%s), COMMAND: %d (%s), RI: %#x, AI: %d\n", - pmes[3], type, pmes[6], command, (int)((pmes[4] << 8) | pmes[5]), pmes[7] >> 1); - } - else { - APPEND_MSG(pbuf, poffset, pleft, " ENT ID: %d (%s), MESSAGE CONTENT:\n", pmes[3], type); - - len = print_hex(pbuf + poffset, (int)pleft, &pmes[3], size - (trunk->Q921HeaderSpace + 3)); - poffset += len; - pleft -= len; - } - } - } - else { - /* - * Unknown - */ - strncat(pbuf + poffset, " -- unknown frame type --\n", pleft); - - len = (sizeof(pbuf) - poffset) - strlen(pbuf + poffset); - if(len > 0) { - poffset += len; - pleft -= len; - } else - goto out; - } - - APPEND_MSG(pbuf, poffset, pleft, "\n Q.921 state: \"%s\" (%d) [flags: %c%c%c%c]\n", Q921State2Name(link->state), link->state, - Q921_CHECK_FLAG(link, Q921_FLAG_ACK_PENDING) ? 'A' : '-', - Q921_CHECK_FLAG(link, Q921_FLAG_REJECT) ? 'R' : '-', - Q921_CHECK_FLAG(link, Q921_FLAG_PEER_RECV_BUSY) ? 'P' : '-', - Q921_CHECK_FLAG(link, Q921_FLAG_RECV_BUSY) ? 'B' : '-'); - - strncat(pbuf + poffset, "----------------------------------------------\n\n", pleft); - - len = (sizeof(pbuf) - poffset) - strlen(pbuf + poffset); - if(len > 0) { - poffset += len; - pleft -= len; - } else - goto out; - - - /* concat buffers together */ - len = strlen(pbuf); - if(len <= left) - strncat(buf, pbuf, left); - else - strncat(buf, "-- packet truncated --\n", left); - } - -out: - buf[sizeof(buf) - 1] = '\0'; - - return trunk->Q921LogProc(trunk->PrivateDataLog, level, buf, (int)strlen(buf)); -} - -/***************************************************************************** - - Function: Q921TimeTick - - Description: Called periodically from an external source to allow the - stack to process and maintain it's own timers. - - Return Value: none - -*****************************************************************************/ -static L2ULONG (*Q921GetTimeProc) (void) = NULL; /* callback for func reading time in ms */ -static L2ULONG tLast = {0}; - -static L2ULONG Q921GetTime(void) -{ - L2ULONG tNow = 0; - - if(Q921GetTimeProc) - { - tNow = Q921GetTimeProc(); - if(tNow < tLast) /* wrapped */ - { - /* TODO */ - } - tLast = tNow; - } - return tNow; -} - -/* - * T200 handling (per-TEI in PTMP NT mode, tei=0 otherwise) - */ -static void Q921T200TimerStart(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - if (!link->T200) { - link->T200 = Q921GetTime() + trunk->T200Timeout; - - Q921Log(trunk, Q921_LOG_DEBUG, "T200 (timeout: %d msecs) started for TEI %d\n", trunk->T200Timeout, tei); - } -} - -static void Q921T200TimerStop(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - link->T200 = 0; - - Q921Log(trunk, Q921_LOG_DEBUG, "T200 stopped for TEI %d\n", tei); -} - -static void Q921T200TimerReset(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - link->T200 = Q921GetTime() + trunk->T200Timeout; - - Q921Log(trunk, Q921_LOG_DEBUG, "T200 (timeout: %d msecs) restarted for TEI %d\n", trunk->T200Timeout, tei); -} - -/* - * T203 handling (per-TEI in PTMP NT mode, tei=0 otherwise) - */ -static void Q921T203TimerStart(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - if (!link->T203) { - link->T203 = Q921GetTime() + trunk->T203Timeout; - - Q921Log(trunk, Q921_LOG_DEBUG, "T203 (timeout: %d msecs) started for TEI %d\n", trunk->T203Timeout, tei); - } -} - -static void Q921T203TimerStop(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - link->T203 = 0; - - Q921Log(trunk, Q921_LOG_DEBUG, "T203 stopped for TEI %d\n", tei); -} - -static void Q921T203TimerReset(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - link->T203 = Q921GetTime() + trunk->T203Timeout; - - Q921Log(trunk, Q921_LOG_DEBUG, "T203 (timeout: %d msecs) restarted for TEI %d\n", trunk->T203Timeout, tei); -} - -/* - * T202 handling (TEI message timeout, TE mode only) - */ -static void Q921T202TimerStart(L2TRUNK trunk) -{ - if (!trunk->T202) { - trunk->T202 = Q921GetTime() + trunk->T202Timeout; - - Q921Log(trunk, Q921_LOG_DEBUG, "T202 (timeout: %d msecs) started\n", trunk->T202Timeout); - } -} - -static void Q921T202TimerStop(L2TRUNK trunk) -{ - trunk->T202 = 0; - - Q921Log(trunk, Q921_LOG_DEBUG, "T202 stopped\n"); -} - -static void Q921T202TimerReset(L2TRUNK trunk) -{ - trunk->T202 = Q921GetTime() + trunk->T202Timeout; - - Q921Log(trunk, Q921_LOG_DEBUG, "T202 (timeout: %d msecs) restarted\n", trunk->T202Timeout); -} - -/* - * T201 handling (TEI management (NT side), per-TEI) - */ -static void Q921T201TimerStart(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - if (!link->T201) { - link->T201 = Q921GetTime() + trunk->T201Timeout; - - Q921Log(trunk, Q921_LOG_DEBUG, "T201 (timeout: %d msecs) started for TEI %d\n", trunk->T201Timeout, tei); - } -} - -static void Q921T201TimerStop(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - link->T201 = 0; - - Q921Log(trunk, Q921_LOG_DEBUG, "T201 stopped for TEI %d\n", tei); -} - -#ifdef __UNUSED_FOR_NOW__ -static void Q921T201TimerReset(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - link->T201 = Q921GetTime() + trunk->T201Timeout; - - Q921Log(trunk, Q921_LOG_DEBUG, "T201 (timeout: %d msecs) restarted for TEI %d\n", trunk->T201Timeout, tei); -} -#endif - -/* - * TM01 handling (Datalink inactivity shutdown timer) - */ -static void Q921TM01TimerStart(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - if (!link->TM01) { - link->TM01 = Q921GetTime() + trunk->TM01Timeout; - - Q921Log(trunk, Q921_LOG_DEBUG, "TM01 (timeout: %d msecs) started for TEI %d\n", trunk->TM01Timeout, tei); - } -} - -#ifdef __UNUSED_FOR_NOW__ -static void Q921TM01TimerStop(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - link->TM01 = 0; - - Q921Log(trunk, Q921_LOG_DEBUG, "TM01 stopped for TEI %d\n", tei); -} -#endif - -static void Q921TM01TimerReset(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - link->TM01 = Q921GetTime() + trunk->TM01Timeout; - - Q921Log(trunk, Q921_LOG_DEBUG, "TM01 (timeout: %d msecs) restarted for TEI %d\n", trunk->TM01Timeout, tei); -} - -/* - * Expiry callbacks - */ -static void Q921T200TimerExpire(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - struct Q921_Link *trlink = Q921_TRUNK_CONTEXT(trunk); - - Q921Log(trunk, Q921_LOG_DEBUG, "T200 expired for TEI %d (trunk TEI %d)\n", tei, trlink->tei); - - /* Stop timer first */ - Q921T200TimerStop(trunk, tei); - - switch(link->state) { - case Q921_STATE_AWAITING_ESTABLISHMENT: - if(link->N200 >= trunk->N200Limit) { - /* Discard I queue */ - MFIFOClear(link->IFrameQueue); - - /* MDL-Error indication (G) */ - Q921Log(trunk, Q921_LOG_ERROR, "Failed to establish Q.921 link in %d retries\n", link->N200); - - /* DL-Release indication */ - Q921Tx23Proc(trunk, Q921_DL_RELEASE, tei, NULL, 0); - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_TEI_ASSIGNED, tei); - } else { - /* Increment retry counter */ - link->N200++; - - /* Send SABME */ - Q921SendSABME(trunk, - trunk->sapi, - Q921_COMMAND(trunk), - tei, - 1); - - /* Start T200 */ - Q921T200TimerStart(trunk, tei); - } - break; - - case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED: - link->N200 = 0; - - if(!Q921_CHECK_FLAG(link, Q921_FLAG_PEER_RECV_BUSY)) { - /* get last transmitted I frame */ - - /* V(S) = V(S) - 1 */ - Q921_DEC_COUNTER(link->vs); - - /* retransmit I frame */ - - /* V(S) = V(S) + 1 (done by Q921SendI() ) */ - //Q921_INC_COUNTER(link->vs); - - /* clear acknowledge pending */ - Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING); - - /* Start T200 */ - Q921T200TimerStart(trunk, tei); - } else { - /* transmit enquiry */ - Q921SendEnquiry(trunk, tei); - } - - /* increment counter */ - link->N200++; - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_TIMER_RECOVERY, tei); - break; - - case Q921_STATE_TIMER_RECOVERY: - if(link->N200 == trunk->N200Limit) { - /* MDL Error indication (I) */ - - /* Establish data link */ - Q921EstablishDataLink(trunk, tei); - - /* Clear L3 initiated */ - Q921_CLEAR_FLAG(link, Q921_FLAG_L3_INITIATED); - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei); - } else { - if(link->vs == link->va) { - /* transmit enquiry */ - Q921SendEnquiry(trunk, tei); - - } else if(!Q921_CHECK_FLAG(link, Q921_FLAG_PEER_RECV_BUSY)) { - /* get last transmitted frame */ - - /* V(S) = V(S) - 1 */ - Q921_DEC_COUNTER(link->vs); - - /* retrans frame */ - - /* V(S) = V(S) + 1 (done by Q921SendI() ) */ - //Q921_INC_COUNTER(link->vs); - - /* clear acknowledge pending */ - Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING); - - /* Start T200 */ - Q921T200TimerStart(trunk, tei); - } - - /* increment counter */ - link->N200++; - - /* no state change */ - } - break; - - default: - break; - } -} - -static void Q921T203TimerExpire(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - struct Q921_Link *trlink = Q921_TRUNK_CONTEXT(trunk); - - Q921Log(trunk, Q921_LOG_DEBUG, "T203 expired for TEI %d (trunk TEI %d)\n", tei, trlink->tei); - - /* Stop Timer first */ - Q921T203TimerStop(trunk, tei); - - switch(link->state) { - case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED: - /* Send Enquiry */ - Q921SendEnquiry(trunk, tei); - - /* RC = 0 */ - link->N200 = 0; - - /* no state change */ - break; - - default: - break; - } -} - -static void Q921T202TimerExpire(L2TRUNK trunk) -{ - struct Q921_Link *link = Q921_TRUNK_CONTEXT(trunk); - - Q921T202TimerReset(trunk); - - Q921Log(trunk, Q921_LOG_DEBUG, "T202 expired for Q.921 trunk with TEI %d\n", link->tei); - - /* todo: implement resend counter */ - - switch(link->state) { - case Q921_STATE_TEI_ASSIGNED: /* Tei identity verify timeout */ - Q921TeiSendVerifyRequest(trunk); - break; - - default: /* Tei assignment request timeout (TODO: refine) */ - - if(trunk->N202 >= trunk->N202Limit) { - /* Too many retransmits, reset counter, stop timer and handle case (TODO) */ - trunk->N202 = 0; - - Q921T202TimerStop(trunk); - - return; - } - Q921TeiSendAssignRequest(trunk); - - trunk->N202++; - } -} - -static void Q921T201TimerExpire(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - struct Q921_Link *trlink = Q921_TRUNK_CONTEXT(trunk); - - Q921Log(trunk, Q921_LOG_DEBUG, "T201 expired for TEI %d (trunk TEI: %d)\n", tei, trlink->tei); - - Q921T201TimerStop(trunk, tei); - - /* NOTE: abusing N202 for this */ - if(link->N202 < trunk->N202Limit) { - /* send check request */ - Q921TeiSendCheckRequest(trunk, tei); - - /* increment counter */ - link->N202++; - } else { - /* put context in STOPPED state */ - Q921ChangeState(trunk, Q921_STATE_STOPPED, tei); - - /* NOTE: should we clear the link too? */ - memset(link, 0, sizeof(struct Q921_Link)); - - /* mark TEI free */ - trunk->tei_map[tei] = 0; - } -} - -#ifdef __UNUSED_FOR_NOW__ -static void Q921TM01TimerExpire(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - struct Q921_Link *trlink = Q921_TRUNK_CONTEXT(trunk); - - Q921Log(trunk, Q921_LOG_DEBUG, "TM01 expired for TEI %d (trunk TEI: %d)\n", tei, trlink->tei); - - /* Restart TM01 */ - Q921TM01TimerReset(trunk, tei); - - switch(link->state) { - case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED: - case Q921_STATE_TIMER_RECOVERY: -/* - * NT-only, needs more support from L3 - */ -#if 0 - /* No activity, shutdown link */ - Q921SendDISC(trunk, trunk->sapi, Q921_COMMAND(trunk), tei, 1); - - /* clear I queue */ - MFIFOClear(link->IFrameQueue); - - /* change state */ - Q921ChangeState(trunk, Q921_STATE_AWAITING_RELEASE, tei); -#endif - break; - - default: - break; - } -} -#endif - -/* - * Timer Tick function - */ -void Q921TimerTick(L2TRUNK trunk) -{ - struct Q921_Link *link; - L2ULONG tNow = Q921GetTime(); - int numlinks = Q921_IS_PTMP_NT(trunk) ? Q921_TEI_MAX : 1; - int x; - - for(x = 0; x <= numlinks; x++) { - link = Q921_LINK_CONTEXT(trunk, x); - - /* TODO: check if TEI is assigned and skip check if not (speedup!) */ - if(link->state == Q921_STATE_STOPPED) - continue; - - if (link->T200 && tNow > link->T200) { - Q921T200TimerExpire(trunk, link->tei); - } - if (link->T203 && tNow > link->T203) { - Q921T203TimerExpire(trunk, link->tei); - } - - if(Q921_IS_PTMP_NT(trunk) && link->tei) { - if (link->T201 && tNow > link->T201) { - Q921T201TimerExpire(trunk, link->tei); - } - } - - if(!Q921_IS_PTMP_NT(trunk)) { - if (trunk->T202 && tNow > trunk->T202) { - Q921T202TimerExpire(trunk); - } - } - - /* Send enqueued I frame, if available */ - Q921SendQueuedIFrame(trunk, link->tei); - - /* Send ack if pending */ - Q921AcknowledgePending(trunk, link->tei); - } - -} - -void Q921SetGetTimeCB(L2ULONG (*callback)(void)) -{ - Q921GetTimeProc = callback; -} - -/***************************************************************************** - - Function: Q921QueueHDLCFrame - - Description: Called to receive and queue an incoming HDLC frame. Will - queue this in Q921HDLCInQueue. The called must either call - Q921Rx12 directly afterwards or signal Q921Rx12 to be called - later. Q921Rx12 will read from the same queue and process - the frame. - - This function assumes that the message contains header - space. This is removed for internal Q921 processing, but - must be keept for I frames. - - Parameters: trunk trunk # - b ptr to frame; - size size of frame in bytes - -*****************************************************************************/ -int Q921QueueHDLCFrame(L2TRUNK trunk, L2UCHAR *b, L2INT size) -{ - return MFIFOWriteMes(trunk->HDLCInQueue, b, size); -} - -/** - * Q921EnqueueI - * \brief Put I frame into transmit queue - * - */ -static int Q921EnqueueI(L2TRUNK trunk, L2UCHAR Sapi, char cr, L2UCHAR Tei, char pf, L2UCHAR *mes, L2INT size) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, Tei); - - /* I frame header */ - mes[trunk->Q921HeaderSpace+0] = ((Sapi << 2) & 0xfc) | ((cr << 1) & 0x02); - mes[trunk->Q921HeaderSpace+1] = (Tei << 1) | 0x01; - mes[trunk->Q921HeaderSpace+2] = 0x00; - mes[trunk->Q921HeaderSpace+3] = (pf & 0x01); - - Q921Log(trunk, Q921_LOG_DEBUG, "Enqueueing I frame for TEI %d [%d]\n", link->tei, Tei); - - /* transmit queue, (TODO: check for full condition!) */ - MFIFOWriteMes(link->IFrameQueue, mes, size); - - /* try to send queued frame */ - Q921SendQueuedIFrame(trunk, link->tei); - - return 1; -} - -/** - * Q921SendQueuedIFrame - * \brief Try to transmit queued I frame (if available) - */ -static int Q921SendQueuedIFrame(L2TRUNK trunk, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - L2INT size = 0; - L2UCHAR *mes; - - if(MFIFOGetMesCount(link->IFrameQueue) == 0) { - return 0; - } - - /* Link ready? */ - if(link->state != Q921_STATE_MULTIPLE_FRAME_ESTABLISHED) { - return 0; - } - - /* peer receiver busy? */ - if(Q921_CHECK_FLAG(link, Q921_FLAG_PEER_RECV_BUSY)) { - return 0; - } - - /* V(S) = V(A) + k? */ - if(link->vs == ((link->va + trunk->k) % 128)) { - Q921Log(trunk, Q921_LOG_WARNING, "Maximum number (%d) of outstanding I frames reached for TEI %d\n", trunk->k, tei); - return 0; - } - - mes = MFIFOGetMesPtr(link->IFrameQueue, &size); - if(mes) { - /* Fill in + update counter values */ - mes[trunk->Q921HeaderSpace+2] = link->vs << 1; - mes[trunk->Q921HeaderSpace+3] |= link->vr << 1; - - if(MFIFOGetMesCount(link->IFrameQueue) == 0) { - /* clear I frame queued */ - } - - /* Send I frame */ - Q921Tx21Proc(trunk, mes, size); - - /* V(S) = V(S) + 1 */ - Q921_INC_COUNTER(link->vs); - - /* clear acknowledge pending */ - Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING); - - /* T200 running? */ - if(!link->T200) { - /* Stop T203, Start T200 */ - Q921T200TimerStart(trunk, tei); - Q921T203TimerStop(trunk, tei); - } - - /* put frame into resend queue */ - MFIFOWriteMesOverwrite(link->IFrameResendQueue, mes, size); - - /* dequeue frame */ - MFIFOKillNext(link->IFrameQueue); - - /* Restart TM01 */ - if(Q921_IS_NT(trunk)) { - Q921TM01TimerReset(trunk, tei); - } - - /* no state change */ - return 1; - } - - return 0; -} - -/** - * Q921SendS - * \brief Prepare and send S frame - */ -static int Q921SendS(L2TRUNK trunk, L2UCHAR Sapi, char cr, L2UCHAR Tei, char pf, L2UCHAR sv, L2UCHAR *mes, L2INT size) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, Tei); - - if(!Q921_IS_READY(link)) { - /* don't even bother trying */ - Q921Log(trunk, Q921_LOG_DEBUG, "Link not ready, discarding S frame for TEI %d\n", Tei); - return 0; - } - - /* S frame header */ - mes[trunk->Q921HeaderSpace+0] = ((Sapi << 2) & 0xfc) | ((cr << 1) & 0x02); - mes[trunk->Q921HeaderSpace+1] = (Tei << 1) | 0x01; - mes[trunk->Q921HeaderSpace+2] = ((sv << 2) & 0x0c) | 0x01; - mes[trunk->Q921HeaderSpace+3] = (link->vr << 1) | (pf & 0x01); - - return Q921Tx21Proc(trunk, mes, size); -} - - -/** - * Q921SendU - * \brief Prepare and send U frame - */ -static int Q921SendU(L2TRUNK trunk, L2UCHAR Sapi, char cr, L2UCHAR Tei, char pf, L2UCHAR m, L2UCHAR *mes, L2INT size) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, Tei); - - /* U frame header */ - mes[trunk->Q921HeaderSpace+0] = ((Sapi << 2) & 0xfc) | ((cr << 1) & 0x02); - mes[trunk->Q921HeaderSpace+1] = (Tei << 1) | 0x01; - mes[trunk->Q921HeaderSpace+2] = ((m << 3) & 0xe0) | ((pf << 4) & 0x10) | ((m << 2) & 0x0c) | 0x03; - - /* link not ready? enqueue non-TEI-mgmt UI (DL-UNIT DATA) frames */ - if(m == 0x00 && Sapi != Q921_SAPI_TEI && link->state < Q921_STATE_TEI_ASSIGNED) { - - /* write frame to queue */ - MFIFOWriteMes(link->UIFrameQueue, mes, size); - - Q921Log(trunk, Q921_LOG_DEBUG, "Link not ready, UI Frame of size %d bytes queued for TEI %d\n", size, Tei); - return 1; - } - - return Q921Tx21Proc(trunk, mes, size); -} - -/** - * TODO: NT mode handling? Need a way to get Link context from Q.931 - */ -int Q921Rx32(L2TRUNK trunk, Q921DLMsg_t ind, L2UCHAR tei, L2UCHAR * Mes, L2INT Size) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); /* TODO: need real link tei for NT mode */ - L2INT res = 0; - - Q921Log(trunk, Q921_LOG_DEBUG, "Got frame from Q.931, type: %d, tei: %d, size: %d\n", ind, tei, Size); - - switch(ind) { - case Q921_DL_ESTABLISH: - /* - * Hmm... - */ - switch(link->state) { - case Q921_STATE_TEI_ASSIGNED: - if(!Q921_IS_NT(trunk)) { - /* establish data link */ - Q921EstablishDataLink(trunk, link->tei); - - /* Set layer 3 initiated */ - Q921_SET_FLAG(link, Q921_FLAG_L3_INITIATED); - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, link->tei); - } - break; - - case Q921_STATE_AWAITING_ESTABLISHMENT: - if(!Q921_IS_NT(trunk)) { - /* Discard I queue */ - MFIFOClear(link->IFrameQueue); - - /* Set layer 3 initiated */ - Q921_SET_FLAG(link, Q921_FLAG_L3_INITIATED); - } - break; - - case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED: - case Q921_STATE_TIMER_RECOVERY: - if(!Q921_IS_NT(trunk)) { - /* Discard I queue */ - MFIFOClear(link->IFrameQueue); - - /* establish data link */ - Q921EstablishDataLink(trunk, link->tei); - - /* Set layer 3 initiated */ - Q921_SET_FLAG(link, Q921_FLAG_L3_INITIATED); - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, link->tei); - } - break; - - default: - break; - } - break; - - case Q921_DL_RELEASE: - switch(link->state) { - case Q921_STATE_TEI_ASSIGNED: - /* send DL-RELEASE confirm */ - Q921Tx23Proc(trunk, Q921_DL_RELEASE, tei, NULL, 0); - break; - - case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED: - case Q921_STATE_TIMER_RECOVERY: - if(!Q921_IS_NT(trunk)) { - /* Discard I queue */ - MFIFOClear(link->IFrameQueue); - - /* RC = 0 */ - link->N200 = 0; - - /* send DISC command */ - Q921SendDISC(trunk, trunk->sapi, Q921_COMMAND(trunk), link->tei, 1); - - /* Stop T203, restart T200 */ - if(link->state == Q921_STATE_MULTIPLE_FRAME_ESTABLISHED) { - Q921T203TimerStop(trunk, link->tei); - } - Q921T200TimerReset(trunk, link->tei); - - /* change state */ - Q921ChangeState(trunk, Q921_STATE_AWAITING_RELEASE, link->tei); - } - break; - - default: - break; - } - break; - - case Q921_DL_DATA: /* DL-DATA request */ - res = Q921EnqueueI(trunk, - trunk->sapi, - Q921_COMMAND(trunk), - link->tei, - 0, - Mes, - Size); - - if(link->state < Q921_STATE_MULTIPLE_FRAME_ESTABLISHED) { - /* Treat as implicit DL-ESTABLISH request */ - - /* establish data link */ - Q921EstablishDataLink(trunk, link->tei); - - /* Set layer 3 initiated */ - Q921_SET_FLAG(link, Q921_FLAG_L3_INITIATED); - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, link->tei); - } - break; - - case Q921_DL_UNIT_DATA: /* DL-UNIT DATA request */ - res = Q921SendUN(trunk, - trunk->sapi, - Q921_COMMAND(trunk), - Q921_TEI_BCAST, - 0, - Mes, - Size); - /* NOTE: Let the other side initiate link establishment */ - break; - - default: - break; - } - - return res; -} -/***************************************************************************** - - Function: Q921SendRR - - Description: Compose and send Receive Ready. - - Parameters: trunk trunk # - Sapi Sapi - cr C/R field. - Tei Tei. - pf P/F fiels octet 5 - - Return Value: 0 if failed, 1 if Send. - -*****************************************************************************/ - -static int Q921SendRR(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf) -{ - L2UCHAR mes[25]; - - return Q921SendS(trunk, Sapi, cr, Tei, pf, 0x00, mes, trunk->Q921HeaderSpace+4); -} - -/***************************************************************************** - - Function: Q921SendRNR - - Description: Compose and send Receive Nor Ready - - Parameters: trunk trunk # - Sapi Sapi - cr C/R field. - Tei Tei. - pf P/F fiels octet 5 - - Return Value: 0 if failed, 1 if Send. - -*****************************************************************************/ -static int Q921SendRNR(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf) -{ - L2UCHAR mes[25]; - - return Q921SendS(trunk, Sapi, cr, Tei, pf, 0x01, mes, trunk->Q921HeaderSpace+4); -} - -/***************************************************************************** - - Function: Q921SendREJ - - Description: Compose and Send Reject. - - Parameters: trunk trunk # - Sapi Sapi - cr C/R field. - Tei Tei. - pf P/F fiels octet 5 - - Return Value: 0 if failed, 1 if Send. - -*****************************************************************************/ -static int Q921SendREJ(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf) -{ - L2UCHAR mes[25]; - - return Q921SendS(trunk, Sapi, cr, Tei, pf, 0x03, mes, trunk->Q921HeaderSpace+4); -} - -/***************************************************************************** - - Function: Q921SendSABME - - Description: Compose and send SABME - - Parameters: trunk trunk # - Sapi Sapi - cr C/R field. - Tei Tei. - pf P fiels octet 4 - - Return Value: 0 if failed, 1 if Send. - -*****************************************************************************/ -static int Q921SendSABME(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf) -{ - L2UCHAR mes[25]; - - return Q921SendU(trunk, Sapi, cr, Tei, pf, 0x0f, mes, trunk->Q921HeaderSpace+3); -} - - -/** - * Q921Start - * \brief Start trunk - * \param[in] trunk pointer to Q921 data struct - * \return > 0 on success; <= 0 on error - */ -int Q921Start(L2TRUNK trunk) -{ - int x, numlinks = Q921_IS_PTMP_NT(trunk) ? Q921_TEI_MAX : 1; - struct Q921_Link *link = Q921_TRUNK_CONTEXT(trunk); - - if(trunk->initialized != INITIALIZED_MAGIC) - return 0; - - memset(trunk->context, 0, numlinks * sizeof(struct Q921_Link)); - - /* Common init part */ - for(x = 0; x <= numlinks; x++) { - link = Q921_LINK_CONTEXT(trunk, x); - - link->state = Q921_STATE_TEI_UNASSIGNED; - link->tei = 0; - - /* Initialize per-TEI I + UI queues */ - MFIFOCreate(link->UIFrameQueue, Q921MAXHDLCSPACE, 10); - MFIFOCreate(link->IFrameQueue, Q921MAXHDLCSPACE, 10); - MFIFOCreate(link->IFrameResendQueue, Q921MAXHDLCSPACE, 10); - } - - if(Q921_IS_PTMP_TE(trunk)) { - link->state = Q921_STATE_TEI_UNASSIGNED; - link->tei = 0; - } - else if(Q921_IS_PTMP_NT(trunk)) { - link = Q921_TRUNK_CONTEXT(trunk); - - link->state = Q921_STATE_TEI_ASSIGNED; - link->tei = trunk->tei; - - /* clear tei map */ - memset(trunk->tei_map, 0, Q921_TEI_MAX + 1); - } - else { - link->state = Q921_STATE_TEI_ASSIGNED; - link->tei = trunk->tei; - } - - Q921Log(trunk, Q921_LOG_DEBUG, "Starting trunk %p (sapi: %d, tei: %d, mode: %s %s)\n", - trunk, - trunk->sapi, - link->tei, - Q921_IS_PTMP(trunk) ? "PTMP" : "PTP", - Q921_IS_TE(trunk) ? "TE" : "NT"); - - if(Q921_IS_PTP(trunk)) { - Q921Log(trunk, Q921_LOG_DEBUG, "Sending SABME\n"); - - return Q921SendSABME(trunk, - trunk->sapi, - Q921_COMMAND(trunk), - link->tei, - 1); - - } else if(Q921_IS_PTMP_NT(trunk)) { - - Q921Log(trunk, Q921_LOG_DEBUG, "Revoking all TEIs\n"); - - return Q921TeiSendRemoveRequest(trunk, Q921_TEI_BCAST); /* Revoke all TEIs in use */ - } else { - - Q921Log(trunk, Q921_LOG_DEBUG, "Requesting TEI\n"); - - return Q921TeiSendAssignRequest(trunk); - } -} - - -/** - * Q921Stop - * \brief Stop trunk - * \param[in] trunk pointer to Q921 data struct - * \return > 0 on success; <= 0 on error - * - * \author Stefan Knoblich - */ -int Q921Stop(L2TRUNK trunk) -{ - struct Q921_Link *link; - int x, numlinks; - - if(!trunk) - return -1; - - link = Q921_TRUNK_CONTEXT(trunk); - numlinks = Q921_IS_PTMP_NT(trunk) ? Q921_TEI_MAX : 1; - - if(Q921_IS_STOPPED(link)) - return 0; - - /* Release TEI */ - if(Q921_IS_PTMP_TE(trunk)) { - /* send verify request */ - Q921TeiSendVerifyRequest(trunk); - - /* drop TEI */ - link->tei = 0; - } - - /* Stop timers, stop link, flush queues */ - for(x = 0; x <= numlinks; x++) { - Q921T200TimerStop(trunk, x); - Q921T203TimerStop(trunk, x); - Q921T201TimerStop(trunk, x); - - /* Change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_STOPPED, x); - - /* Flush per-tei I/UI queues */ - MFIFOClear(link->UIFrameQueue); - MFIFOClear(link->IFrameQueue); - MFIFOClear(link->IFrameResendQueue); - } - Q921T202TimerStop(trunk); - - /* Flush HDLC queue */ - MFIFOClear(trunk->HDLCInQueue); - - return 0; -} - - -/***************************************************************************** - - Function: Q921SendDM - - Description: Compose and Send DM (Disconnected Mode) - - Parameters: trunk trunk # - Sapi Sapi - cr C/R field. - Tei Tei. - pf F fiels octet 4 - - Return Value: 0 if failed, 1 if Send. - -*****************************************************************************/ -static int Q921SendDM(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf) -{ - L2UCHAR mes[25]; - - return Q921SendU(trunk, Sapi, cr, Tei, pf, 0x03, mes, trunk->Q921HeaderSpace+3); -} - -/***************************************************************************** - - Function: Q921SendDISC - - Description: Compose and Send Disconnect - - Parameters: trunk trunk # - Sapi Sapi - cr C/R field. - Tei Tei. - pf P fiels octet 4 - - Return Value: 0 if failed, 1 if Send. - -*****************************************************************************/ -static int Q921SendDISC(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf) -{ - L2UCHAR mes[25]; - - return Q921SendU(trunk, Sapi, cr, Tei, pf, 0x08, mes, trunk->Q921HeaderSpace+3); -} - -/***************************************************************************** - - Function: Q921SendUA - - Description: Compose and Send UA - - Parameters: trunk trunk # - Sapi Sapi - cr C/R field. - Tei Tei. - pf F fiels octet 4 - - Return Value: 0 if failed, 1 if Send. - -*****************************************************************************/ -static int Q921SendUA(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf) -{ - L2UCHAR mes[25]; - - return Q921SendU(trunk, Sapi, cr, Tei, pf, 0x0c, mes, trunk->Q921HeaderSpace+3); -} - -static int Q921SendUN(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf, L2UCHAR *mes, L2INT size) -{ - return Q921SendU(trunk, Sapi, cr, Tei, pf, 0x00, mes, size+trunk->Q921HeaderSpace+3); -} - - -/** - * Q921ProcSABME - * \brief Handle incoming SABME - * \param[in] trunk pointer to Q921 data struct - * \param[in] mes pointer to message buffer - * \param[in] size size of message - * \return > 0 on success, <= 0 on error - */ -static int Q921ProcSABME(L2TRUNK trunk, L2UCHAR *mes, L2INT size) -{ - L2UCHAR pf = (mes[2] & 0x10) >> 4; /* poll / final flag */ - L2UCHAR tei = (mes[1] & 0xfe) >> 1; - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - switch(link->state) { - case Q921_STATE_TEI_ASSIGNED: - /* send UA */ - Q921SendUA(trunk, - trunk->sapi, - Q921_RESPONSE(trunk), /* or command? */ - tei, pf); - - /* clear counters */ - link->vr=0; - link->vs=0; - link->va=0; - - /* TODO: send DL-Establish indication to Q.931 */ - Q921Tx23Proc(trunk, Q921_DL_ESTABLISH, tei, NULL, 0); - - /* start T203 */ - Q921T203TimerStart(trunk, tei); - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_MULTIPLE_FRAME_ESTABLISHED, tei); - break; - - case Q921_STATE_AWAITING_ESTABLISHMENT: - /* send UA */ - Q921SendUA(trunk, - trunk->sapi, - Q921_RESPONSE(trunk), - tei, pf); - - /* no state change */ - break; - - case Q921_STATE_AWAITING_RELEASE: - /* send DM */ - Q921SendDM(trunk, - trunk->sapi, - Q921_RESPONSE(trunk), - tei, pf); - - /* no state change */ - break; - - case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED: - case Q921_STATE_TIMER_RECOVERY: - /* send UA */ - Q921SendUA(trunk, - trunk->sapi, - Q921_RESPONSE(trunk), - tei, pf); - - /* clear exception conditions */ - Q921ResetExceptionConditions(trunk, tei); - - /* send MDL-Error indication */ - - /* V(S) == V(A) ? */ - if(link->vs != link->va) { - /* clear I queue */ - MFIFOClear(link->IFrameQueue); - - /* DL-Establish indication */ - Q921Tx23Proc(trunk, Q921_DL_ESTABLISH, tei, NULL, 0); - } - - /* clear counters */ - link->vr=0; - link->vs=0; - link->va=0; - - /* Stop T200, start T203 */ - Q921T200TimerStop(trunk, tei); - Q921T203TimerStart(trunk, tei); - - /* state change only if in TIMER_RECOVERY state */ - if(link->state == Q921_STATE_TIMER_RECOVERY) - Q921ChangeState(trunk, Q921_STATE_MULTIPLE_FRAME_ESTABLISHED, tei); - break; - - default: - break; - } - - return 1; -} - - -/** - * Q921ProcDM - * \brief Handle incoming DM - * \param[in] trunk pointer to Q921 data struct - * \param[in] mes pointer to message buffer - * \param[in] size size of message - * \return > 0 on success, <= 0 on error - */ -static int Q921ProcDM(L2TRUNK trunk, L2UCHAR *mes, L2INT size) -{ - L2UCHAR pf = (mes[2] & 0x10) >> 4; /* poll / final flag */ - L2UCHAR tei = (mes[1] & 0xfe) >> 1; - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - switch(link->state) { - case Q921_STATE_TEI_ASSIGNED: - if(!pf) { - /* to next state (no action) */ - Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei); - } - break; - - case Q921_STATE_AWAITING_ESTABLISHMENT: - case Q921_STATE_AWAITING_RELEASE: - if(pf) { - if(link->state == Q921_STATE_AWAITING_ESTABLISHMENT) { - /* Discard I queue */ - MFIFOClear(link->IFrameQueue); - } - - /* Send DL-Release indication to Q.931 */ - Q921Tx23Proc(trunk, Q921_DL_RELEASE, tei, NULL, 0); - - /* Stop T200 */ - Q921T200TimerStop(trunk, tei); - - /* Change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_TEI_ASSIGNED, tei); - } - break; - - case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED: - if(pf) { - /* MDL-Error indication (B) */ - - /* no state change */ - } else { - /* MDL-Error indication (E) */ - - /* establish data link */ - Q921EstablishDataLink(trunk, tei); - - /* clear L3 initiated */ - Q921_CLEAR_FLAG(link, Q921_FLAG_L3_INITIATED); - - /* change state (no action?) */ - Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei); - } - break; - - case Q921_STATE_TIMER_RECOVERY: - if(pf) { - /* MDL Error indication (B) */ - } else { - /* MDL Error indication (E) */ - } - - /* establish data link */ - Q921EstablishDataLink(trunk, tei); - - /* clear layer 3 initiated */ - Q921_CLEAR_FLAG(link, Q921_FLAG_L3_INITIATED); - - /* change state */ - Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei); - break; - - default: - break; - } - - return 1; -} - -/** - * Q921ProcUA - * \brief Handle incoming UA - * \param[in] trunk pointer to Q921 data struct - * \param[in] mes pointer to message buffer - * \param[in] size size of message - * \return > 0 on success, <= 0 on error - */ -static int Q921ProcUA(L2TRUNK trunk, L2UCHAR *mes, L2INT size) -{ - L2UCHAR pf = (mes[2] & 0x10) >> 4; /* poll / final flag */ - L2UCHAR tei = (mes[1] & 0xfe) >> 1; - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - switch(link->state) { - case Q921_STATE_TEI_ASSIGNED: - case Q921_STATE_TIMER_RECOVERY: - /* MDL Error indication (C, D) */ - Q921Log(trunk, Q921_LOG_ERROR, "Received UA frame in invalid state\n"); - break; - - case Q921_STATE_AWAITING_ESTABLISHMENT: - if(pf) { - /* TODO: other fancy stuff (see docs) */ - if(Q921_CHECK_FLAG(link, Q921_FLAG_L3_INITIATED)) { /* layer3 initiated */ - link->vr = 0; - - /* DL-Establish confirm */ - Q921Tx23Proc(trunk, Q921_DL_ESTABLISH_CONFIRM, tei, NULL, 0); - - } else if(link->vs != link->va) { - - /* discard I queue */ - MFIFOClear(link->IFrameQueue); - - /* DL-Establish indication */ - Q921Tx23Proc(trunk, Q921_DL_ESTABLISH, tei, NULL, 0); - } - - /* Stop T200, start T203 */ - Q921T200TimerStop(trunk, tei); - Q921T203TimerStart(trunk, tei); - - link->vs = 0; - link->va = 0; - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_MULTIPLE_FRAME_ESTABLISHED, tei); - } else { - /* MDL Error indication (C, D) */ - Q921Log(trunk, Q921_LOG_ERROR, "Received UA frame is not a response to a request\n"); - - /* no state change */ - } - break; - - case Q921_STATE_AWAITING_RELEASE: - if(pf) { - /* DL Release confirm */ - Q921Tx23Proc(trunk, Q921_DL_RELEASE_CONFIRM, tei, NULL, 0); - - /* Stop T200 */ - Q921T200TimerStop(trunk, tei); - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_TEI_ASSIGNED, tei); - } else { - /* MDL Error indication (D) */ - Q921Log(trunk, Q921_LOG_ERROR, "Received UA frame is not a response to a request\n"); - - /* no state change */ - } - break; - - case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED: - /* MDL Error indication (C, D) */ - Q921Log(trunk, Q921_LOG_ERROR, "Received UA frame in invalid state\n"); - - /* no state change */ - break; - - default: - break; - } - - return 1; -} - - -/** - * Q921ProcDISC - * \brief Handle incoming DISC - * \param[in] trunk pointer to Q921 data struct - * \param[in] mes pointer to message buffer - * \param[in] size size of message - * \return > 0 on success, <= 0 on error - */ -static int Q921ProcDISC(L2TRUNK trunk, L2UCHAR *mes, L2INT size) -{ - L2UCHAR pf = (mes[2] & 0x10) >> 4; /* poll / final flag */ - L2UCHAR tei = (mes[1] & 0xfe) >> 1; - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - switch(link->state) { - case Q921_STATE_TEI_ASSIGNED: - case Q921_STATE_AWAITING_ESTABLISHMENT: - /* Send DM */ - Q921SendDM(trunk, - trunk->sapi, - Q921_RESPONSE(trunk), - tei, pf); - - /* no state change */ - break; - - case Q921_STATE_AWAITING_RELEASE: - Q921SendUA(trunk, - trunk->sapi, - Q921_RESPONSE(trunk), - tei, pf); - - /* no state change */ - break; - - case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED: - case Q921_STATE_TIMER_RECOVERY: - /* Discard I queue */ - MFIFOClear(link->IFrameQueue); - - /* send UA */ - Q921SendUA(trunk, - trunk->sapi, - Q921_RESPONSE(trunk), - tei, pf); - - /* DL Release indication */ - Q921Tx23Proc(trunk, Q921_DL_RELEASE, tei, NULL, 0); - - /* Stop T200 */ - Q921T200TimerStop(trunk, tei); - - if(link->state == Q921_STATE_MULTIPLE_FRAME_ESTABLISHED) { - /* Stop T203 */ - Q921T203TimerStop(trunk, tei); - } - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_TEI_ASSIGNED, tei); - break; - - default: - Q921Log(trunk, Q921_LOG_ERROR, "Invalid DISC received in state \"%s\" (%d)", Q921State2Name(link->state), link->state); - break; - } - - return 1; -} - - -/** - * Q921ProcRR - * \brief Handle incoming RR - * \param[in] trunk pointer to Q921 data struct - * \param[in] mes pointer to message buffer - * \param[in] size size of message - * \return > 0 on success, <= 0 on error - */ -static int Q921ProcRR(L2TRUNK trunk, L2UCHAR *mes, L2INT size) -{ - L2UCHAR cr = (mes[0] & 0x02) >> 1; - L2UCHAR pf = mes[3] & 0x01; /* poll / final flag */ - L2UCHAR nr = (mes[3] >> 1); -// L2UCHAR sapi = (mes[0] & 0xfc) >> 2; - L2UCHAR tei = (mes[1] & 0xfe) >> 1; - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - switch(link->state) { - case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED: - /* clear receiver peer busy */ - Q921_CLEAR_FLAG(link, Q921_FLAG_PEER_RECV_BUSY); - - if (Q921_IS_COMMAND(trunk, cr)) { /* if this is a command */ - if(pf) { - /* Enquiry response */ - Q921SendEnquiryResponse(trunk, tei); - } - } else { - if(pf) { - /* MDL Error indication */ - } - } - - /* */ - if(link->va <= nr && nr <= link->vs) { - - if(nr == link->vs) { - /* V(A) = N(R) */ - link->va = nr; - - /* Stop T200, restart T203 */ - Q921T200TimerStop(trunk, tei); - Q921T203TimerReset(trunk, tei); - - } else if(nr == link->va) { - - /* do nothing */ - - } else { - /* V(A) = N(R) */ - link->va = nr; - - /* Restart T200 */ - Q921T200TimerReset(trunk, tei); - } - /* no state change */ - - } else { - /* N(R) Error recovery */ - Q921NrErrorRecovery(trunk, tei); - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei); - } - break; - - case Q921_STATE_TIMER_RECOVERY: - /* clear receiver peer busy */ - Q921_CLEAR_FLAG(link, Q921_FLAG_PEER_RECV_BUSY); - - /* command + P? */ - if(Q921_IS_COMMAND(trunk, cr) && pf) { - /* Enquiry response */ - Q921SendEnquiryResponse(trunk, tei); - } - - /* */ - if(link->va <= nr && nr <= link->vs) { - /* V(A) = N(R) */ - link->va = nr; - - if(!Q921_IS_COMMAND(trunk, cr) && pf) { - /* Stop T200, start T203 */ - Q921T200TimerStop(trunk, tei); - Q921T203TimerStart(trunk, tei); - - /* Invoke retransmission */ - Q921InvokeRetransmission(trunk, tei, nr); - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_MULTIPLE_FRAME_ESTABLISHED, tei); - } - /* no state change otherwise */ - } else { - /* N(R) Error recovery */ - Q921NrErrorRecovery(trunk, tei); - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei); - } - break; - - default: - break; - } - return 1; -} - - -/** - * Q921ProcREJ - * \brief Handle incoming REJ - * \param[in] trunk pointer to Q921 data struct - * \param[in] mes pointer to message buffer - * \param[in] size size of message - * \return > 0 on success, <= 0 on error - */ -static int Q921ProcREJ(L2TRUNK trunk, L2UCHAR *mes, L2INT size) -{ - L2UCHAR cr = (mes[0] & 0x02) >> 1; - L2UCHAR pf = mes[3] & 0x01; /* poll / final flag */ - L2UCHAR nr = (mes[3] >> 1); -// L2UCHAR sapi = (mes[0] & 0xfc) >> 2; - L2UCHAR tei = (mes[1] & 0xfe) >> 1; - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - switch(link->state) { - case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED: - /* clear receiver peer busy */ - Q921_CLEAR_FLAG(link, Q921_FLAG_PEER_RECV_BUSY); - - /* command? */ - if(Q921_IS_COMMAND(trunk, cr)) { - if(pf) { - /* Enquiry response */ - Q921SendEnquiryResponse(trunk, tei); - } - } else { - if(pf) { - /* MDL Error indication (A) */ - } - } - - /* */ - if(link->va <= nr && nr <= link->vs) { - - /* V(A) = N(R) */ - link->va = nr; - - /* Stop T200, start T203 */ - Q921T200TimerStop(trunk, tei); - Q921T203TimerStart(trunk, tei); - - /* Invoke retransmission of frame >N(R) (?) */ - Q921InvokeRetransmission(trunk, tei, nr); - - /* no state change */ - } else { - /* N(R) Error recovery */ - Q921NrErrorRecovery(trunk, tei); - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei); - } - break; - - case Q921_STATE_TIMER_RECOVERY: - /* clear receiver peer busy */ - Q921_CLEAR_FLAG(link, Q921_FLAG_PEER_RECV_BUSY); - - /* command + P ? */ - if(Q921_IS_COMMAND(trunk, cr) && pf) { - /* Enquiry response */ - Q921SendEnquiryResponse(trunk, tei); - } - - /* */ - if(link->va <= nr && nr <= link->vs) { - - /* V(A) = N(R) */ - link->va = nr; - - if(!Q921_IS_COMMAND(trunk, cr) && pf) { - /* Stop T200, start T203 */ - Q921T200TimerStop(trunk, tei); - Q921T203TimerStart(trunk, tei); - - /* Invoke retransmission */ - Q921InvokeRetransmission(trunk, tei, nr); - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_MULTIPLE_FRAME_ESTABLISHED, tei); - } - /* no state change otherwise */ - } else { - /* N(R) Error recovery */ - Q921NrErrorRecovery(trunk, tei); - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei); - } - break; - - default: - break; - } - - return 1; -} - - -/** - * Q921ProcRNR - * \brief Handle incoming RNR - * \param[in] trunk pointer to Q921 data struct - * \param[in] mes pointer to message buffer - * \param[in] size size of message - * \return > 0 on success, <= 0 on error - */ -static int Q921ProcRNR(L2TRUNK trunk, L2UCHAR *mes, L2INT size) -{ - L2UCHAR cr = (mes[0] & 0x02) >> 1; - L2UCHAR pf = mes[3] & 0x01; /* poll / final flag */ - L2UCHAR nr = (mes[3] >> 1); -// L2UCHAR sapi = (mes[0] & 0xfc) >> 2; - L2UCHAR tei = (mes[1] & 0xfe) >> 1; - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - switch(link->state) { - case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED: - /* set peer receiver busy */ - Q921_SET_FLAG(link, Q921_FLAG_PEER_RECV_BUSY); - - /* command? */ - if(Q921_IS_COMMAND(trunk, cr)) { - if(pf) { - /* Enquiry response */ - Q921SendEnquiryResponse(trunk, tei); - } - } else { - if(pf) { - /* MDL Error indication (A) */ - } - } - - /* */ - if(link->va <= nr && nr <= link->vs) { - - /* V(A) = N(R) */ - link->va = nr; - - /* Stop T203, restart T200 */ - Q921T200TimerReset(trunk, tei); - Q921T203TimerStop(trunk, tei); - - /* no state change */ - } else { - /* N(R) Error recovery */ - Q921NrErrorRecovery(trunk, tei); - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei); - } - break; - - case Q921_STATE_TIMER_RECOVERY: - /* set peer receiver busy */ - Q921_SET_FLAG(link, Q921_FLAG_PEER_RECV_BUSY); - - /* command + P? */ - if(Q921_IS_COMMAND(trunk, cr) && pf) { - /* Enquiry response */ - Q921SendEnquiryResponse(trunk, tei); - } - - /* */ - if(link->va <= nr && nr <= link->vs) { - - /* V(A) = N(R) */ - link->va = nr; - - if(!Q921_IS_COMMAND(trunk, cr) && pf) { - /* Restart T200 */ - Q921T200TimerReset(trunk, tei); - - /* Invoke retransmission */ - Q921InvokeRetransmission(trunk, tei, nr); - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_MULTIPLE_FRAME_ESTABLISHED, tei); - } - /* no state change otherwise */ - } else { - /* N(R) Error recovery */ - Q921NrErrorRecovery(trunk, tei); - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei); - } - break; - - default: - break; - } - - return 1; -} - -#if 0 -static int Q921SetReceiverBusy(L2TRUNK trunk) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - switch(link->state) { - case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED: - if(!Q921_CHECK_FLAG(link, Q921_FLAG_RECV_BUSY)) { - /* set own receiver busy */ - Q921_SET_FLAG(link, Q921_FLAG_RECV_BUSY); - - /* send RR response */ - Q921SendRR(trunk, trunk->sapi, Q921_RESPONSE(trunk), link->tei, 0); - - /* clear ack pending */ - Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING); - } - break; - - case Q921_STATE_TIMER_RECOVERY: - if(!Q921_CHECK_FLAG(link, Q921_FLAG_RECV_BUSY)) { - /* set own receiver busy */ - Q921_SET_FLAG(link, Q921_FLAG_RECV_BUSY); - - /* send RNR response */ - Q921SendRNR(trunk, trunk->sapi, Q921_RESPONSE(trunk), link->tei, 0); - - /* clear ack pending */ - Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING); - } - break; - - default: - break; - } - - return 0; -} - -static int Q921ClearReceiverBusy(L2TRUNK trunk) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - switch(link->state) { - case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED: - case Q921_STATE_TIMER_RECOVERY: - if(Q921_CHECK_FLAG(link, Q921_FLAG_RECV_BUSY)) { - /* clear own receiver busy */ - Q921_CLEAR_FLAG(link, Q921_FLAG_RECV_BUSY); - - /* send RNR response */ - Q921SendRNR(trunk, trunk->sapi, Q921_RESPONSE(trunk), link->tei, 0); - - /* clear ack pending */ - Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING); - } - break; - - default: - break; - } - - return 0; -} -#endif - -static int Q921ProcIFrame(L2TRUNK trunk, L2UCHAR *mes, L2INT size) -{ - /* common fields: get sapi, tei and cr */ -// L2UCHAR sapi = (mes[0] & 0xfc) >> 2; -// L2UCHAR cr = (mes[0] & 0x02) >> 1; - L2UCHAR tei = (mes[1] & 0xfe) >> 1; - L2UCHAR pf = mes[3] & 0x01; /* poll / final flag */ - L2UCHAR nr = mes[3] >> 1; /* receive sequence number */ - L2UCHAR ns = mes[2] >> 1; /* send sequence number */ - L2UCHAR discard = 0; - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - /* Ignore I frames in earlier states */ - if(link->state < Q921_STATE_MULTIPLE_FRAME_ESTABLISHED) { - Q921Log(trunk, Q921_LOG_NOTICE, "I frame in invalid state ignored\n"); - return 0; - } - - /* Receiver busy? */ - if(Q921_CHECK_FLAG(link, Q921_FLAG_RECV_BUSY)) { - /* discard information */ - discard = 1; - - if(pf) { - /* send RNR Response */ - Q921SendRNR(trunk, trunk->sapi, Q921_RESPONSE(trunk), tei, 1); - - /* Clear ack pending */ - Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING); - } - } - else { - if(ns != link->vr) { - /* discard information */ - discard = 1; - - if(Q921_CHECK_FLAG(link, Q921_FLAG_REJECT) && pf) { - - /* Send RR response */ - Q921SendRR(trunk, trunk->sapi, Q921_RESPONSE(trunk), tei, 1); - - /* clear ack pending */ - Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING); - } - else if(!Q921_CHECK_FLAG(link, Q921_FLAG_REJECT)){ - - /* set reject exception */ - Q921_SET_FLAG(link, Q921_FLAG_REJECT); - - /* Send REJ response */ - Q921SendREJ(trunk, trunk->sapi, Q921_RESPONSE(trunk), tei, pf); - - /* clear ack pending */ - Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING); - } - } - else { - /* V(R) = V(R) + 1 */ - Q921_INC_COUNTER(link->vr); - - /* clear reject exception */ - Q921_CLEAR_FLAG(link, Q921_FLAG_REJECT); - - /* DL-Data indication */ - Q921Tx23Proc(trunk, Q921_DL_DATA, tei, mes, size); - - if(pf) { - /* Send RR response */ - Q921SendRR(trunk, trunk->sapi, Q921_RESPONSE(trunk), tei, 1); - - /* clear ack pending */ - Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING); - } - else if(!Q921_CHECK_FLAG(link, Q921_FLAG_ACK_PENDING)) { - /* ack pending */ - - /* Send RR response */ - Q921SendRR(trunk, trunk->sapi, Q921_RESPONSE(trunk), tei, 0); - - /* set ack pending*/ - Q921_SET_FLAG(link, Q921_FLAG_ACK_PENDING); - } - } - } - - - switch(link->state) { - case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED: - if(link->va <= nr && nr <= link->vs) { - if(Q921_CHECK_FLAG(link, Q921_FLAG_PEER_RECV_BUSY)) { - link->va = nr; - } - else if(nr == link->vs) { - /* V(A) = N(R) */ - link->va = nr; - - /* stop t200, restart t203 */ - Q921T200TimerStop(trunk, tei); - Q921T203TimerReset(trunk, tei); - } - else if(nr != link->va) { - /* V(A) = N(R) */ - link->va = nr; - - /* restart T200 */ - Q921T200TimerReset(trunk, tei); - } - - /* Restart TM01 */ - if(Q921_IS_NT(trunk)) { - Q921TM01TimerReset(trunk, tei); - } - } - else { - /* N(R) error recovery */ - Q921NrErrorRecovery(trunk, tei); - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei); - } - break; - - case Q921_STATE_TIMER_RECOVERY: - if(link->va <= nr && nr <= link->vs) { - /* V(A) = N(R) */ - link->va = nr; - - /* Restart TM01 */ - if(Q921_IS_NT(trunk)) { - Q921TM01TimerReset(trunk, tei); - } - } - else { - /* N(R) error recovery */ - Q921NrErrorRecovery(trunk, tei); - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei); - } - break; - - default: - break; - } - - return 0; -} - - -static int Q921ProcSFrame(L2TRUNK trunk, L2UCHAR *mes, L2INT size) -{ - L2UCHAR sv = (mes[2] & 0x0c) >> 2; /* supervisory format id */ - //L2UCHAR pf = mes[3] & 0x01; /* poll / final flag */ - //L2UCHAR nr = mes[3] >> 1; /* receive sequence number */ - L2INT res = -1; - - switch(sv) { - case 0x00: /* RR : Receive Ready */ - res = Q921ProcRR(trunk, mes, size); - break; - - case 0x02: /* RNR : Receive Not Ready */ - res = Q921ProcRNR(trunk, mes, size); - break; - - case 0x04: /* REJ : Reject */ - res = Q921ProcREJ(trunk, mes, size); - break; - - default: /* Invalid / Unknown */ - Q921Log(trunk, Q921_LOG_ERROR, "Invalid S frame type %d\n", sv); - break; - } - - return res; -} - - - -static int Q921ProcUFrame(L2TRUNK trunk, L2UCHAR *mes, L2INT size) -{ - L2UCHAR m = (mes[2] & 0xe0) >> 3 | (mes[2] & 0x0c) >> 2; /* modifier function id */ -// L2UCHAR pf = (mes[2] & 0x10) >> 4; /* poll / final flag */ - L2INT res = -1; - - switch(m) { - case 0x00: /* UN : Unnumbered Information */ - if(mes[3] == Q921_LAYER_ENT_ID_TEI) - { - if(!Q921_IS_PTMP(trunk)) { - /* wtf? nice try */ - return res; - } - - switch(mes[6]) { - case Q921_TEI_ID_REQUEST: /* (TE ->) NT */ - res = Q921TeiProcAssignRequest(trunk, mes, size); - break; - - case Q921_TEI_ID_ASSIGNED: /* (NT ->) TE */ - case Q921_TEI_ID_DENIED: - res = Q921TeiProcAssignResponse(trunk, mes, size); - break; - - case Q921_TEI_ID_CHECKREQ: /* (NT ->) TE */ - res = Q921TeiProcCheckRequest(trunk, mes, size); - break; - - case Q921_TEI_ID_CHECKRESP: /* (TE ->) NT */ - res = Q921TeiProcCheckResponse(trunk, mes, size); - break; - - case Q921_TEI_ID_REMOVE: /* (NT ->) TE */ - res = Q921TeiProcRemoveRequest(trunk, mes, size); - break; - - case Q921_TEI_ID_VERIFY: /* (TE ->) NT */ - res = Q921TeiProcVerifyRequest(trunk, mes, size); - break; - - default: /* Invalid / Unknown */ - Q921Log(trunk, Q921_LOG_ERROR, "Invalid UN message from TEI management/endpoint\n"); - break; - } - } - else if(mes[3] == Q921_LAYER_ENT_ID_Q931) { - - Q921Log(trunk, Q921_LOG_DEBUG, "UI Frame for Layer 3 received\n"); - - res = Q921Tx23Proc(trunk, Q921_DL_UNIT_DATA, 0, mes, size); - } - break; - - case 0x03: /* DM : Disconnect Mode */ - res = Q921ProcDM(trunk, mes, size); - break; - - case 0x08: /* DISC : Disconnect */ - res = Q921ProcDISC(trunk, mes, size); - break; - - case 0x0c: /* UA : Unnumbered Acknowledgement */ - res = Q921ProcUA(trunk, mes, size); - break; - - case 0x0f: /* SABME : Set Asynchronous Balanced Mode Extend */ - res = Q921ProcSABME(trunk, mes, size); - break; - - case 0x11: /* FRMR : Frame Reject */ - case 0x17: /* XID : Exchange Identification */ - res = 0; - break; - - default: /* Unknown / Invalid */ - Q921Log(trunk, Q921_LOG_ERROR, "Invalid U frame type: %d\n", m); - break; - } - - return res; -} - - -/***************************************************************************** - - Function: Q921Rx12 - - Description: Called to process a message frame from layer 1. Will - identify the message and call the proper 'processor' for - layer 2 messages and forward I frames to the layer 3 entity. - - Q921Rx12 will check the input fifo for a message, and if a - message exist process one message before it exits. The caller - must either call Q921Rx12 polling or keep track on # - messages in the queue. - - Parameters: trunk trunk #. - - Return Value: # messages processed (always 1 or 0). - -*****************************************************************************/ -int Q921Rx12(L2TRUNK trunk) -{ - L2INT size; /* receive size & Q921 frame size*/ - L2UCHAR *smes = MFIFOGetMesPtr(trunk->HDLCInQueue, &size); - - if(smes) - { - struct Q921_Link *link; - L2UCHAR sapi, tei; - L2UCHAR *mes; - L2INT rs; - - rs = size - trunk->Q921HeaderSpace; - mes = &smes[trunk->Q921HeaderSpace]; - - Q921LogMesg(trunk, Q921_LOG_DEBUG, 1, mes, rs, "New packet received (%d bytes)", rs); - - /* common fields: get sapi, tei and cr */ - sapi = (mes[0] & 0xfc) >> 2; - tei = (mes[1] & 0xfe) >> 1; - link = Q921_LINK_CONTEXT(trunk, tei); - - if(Q921_IS_PTMP_TE(trunk) && ( - (link->state >= Q921_STATE_TEI_ASSIGNED && tei != link->tei && tei != Q921_TEI_BCAST) || /* Assigned TEI: Only BCAST and directed */ - (link->state == Q921_STATE_TEI_UNASSIGNED && tei != Q921_TEI_BCAST))) /* No assigned TEI: Only BCAST */ - { - /* Ignore Messages with foreign TEIs */ - goto out; - } - - if((mes[2] & 0x01) == 0x00) { /* I frame */ - Q921ProcIFrame(trunk, mes, rs); - } - else if((mes[2] & 0x03) == 0x01) { /* S frame */ - Q921ProcSFrame(trunk, mes, rs); - } - else if((mes[2] & 0x03) == 0x03) { /* U frame */ - Q921ProcUFrame(trunk, mes, rs); - } - else { - Q921Log(trunk, Q921_LOG_ERROR, "Invalid frame type: %d\n", (int)(mes[2] & 0x03)); - /* TODO: send FRMR or REJ */ - } - -out: - MFIFOKillNext(trunk->HDLCInQueue); - - return 1; - } - - return 0; -} - -/* - * Misc - */ -/** - * Q921SetLogCB - * \brief Set logging callback - * \param[in] trunk pointer to Q921 data struct - * \param[in] func pointer to logging callback function - * \param[in] priv pointer to private data - * - * \author Stefan Knoblich - */ -void Q921SetLogCB(L2TRUNK trunk, Q921LogCB_t func, void *priv) -{ - if(!trunk) - return; - - trunk->Q921LogProc = func; - trunk->PrivateDataLog = priv; -} - -/** - * Q921SetLogLevel - * \brief Set loglevel of Q.921 logging functions - * \param[in] trunk pointer to Q921 data struct - * \param[in] level new loglevel - * - * \author Stefan Knoblich - */ -void Q921SetLogLevel(L2TRUNK trunk, Q921LogLevel_t level) -{ - if(!trunk) - return; - - if (level < Q921_LOG_NONE) { - level = Q921_LOG_NONE; - } else if (level > Q921_LOG_DEBUG) { - level = Q921_LOG_DEBUG; - } - - trunk->loglevel = level; -} - - -/** - * Q921ChangeState - * \brief Change state, invoke neccessary actions - * \param[in] trunk pointer to Q921 data struct - * \param[in] state state to change to - * \return > 0 on success; <= 0 on error - * - * \author Stefan Knoblich - */ -static int Q921ChangeState(L2TRUNK trunk, Q921State_t state, L2UCHAR tei) -{ - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - Q921State_t oldstate = link->state; - int res = 0; - - Q921Log(trunk, Q921_LOG_DEBUG, "Changing state from \"%s\" (%d) to \"%s\" (%d) for TEI %d\n", - Q921State2Name(oldstate), oldstate, - Q921State2Name(state), state, - tei); - - /* - * generic actions (depending on the target state only) - */ - switch(state) { - case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED: - /* Start TM01 */ - if(Q921_IS_NT(trunk)) { - Q921TM01TimerStart(trunk, tei); - } - break; - - default: - break; - } - - /* - * actions that depend on type of the old -> new state transition - */ - switch(oldstate) { - case Q921_STATE_STOPPED: - - switch(state) { - case Q921_STATE_TEI_UNASSIGNED: - if(Q921_IS_PTMP_TE(trunk)) { - res = Q921TeiSendAssignRequest(trunk); - } - break; - - case Q921_STATE_TEI_ASSIGNED: - if(Q921_IS_PTMP_NT(trunk)) { - res = Q921TeiSendRemoveRequest(trunk, Q921_TEI_BCAST); - } - break; - - default: - break; - } - break; - - default: - break; - } - - link->state = state; - - Q921Log(trunk, Q921_LOG_DEBUG, "Q921ChangeState() returns %d, new state is \"%s\" (%d) for TEI %d\n", res, Q921State2Name(state), state, tei); - - return res; -} - -/* - * TEI Management functions - * \note All TEI-mgmt UN frames are sent with cr = command! - */ -static int Q921TeiSend(L2TRUNK trunk, L2UCHAR type, L2USHORT ri, L2UCHAR ai) -{ - L2UCHAR mes[10]; - L2UCHAR offset = Q921_UFRAME_DATA_OFFSET(trunk); - - mes[offset++] = Q921_LAYER_ENT_ID_TEI; /* layer management entity identifier */ - mes[offset++] = (ri & 0xff00) >> 8; /* reference number upper part */ - mes[offset++] = ri & 0xff; /* reference number lower part */ - mes[offset++] = type; /* message type: Identity Request */ - mes[offset++] = ai << 1 | 0x01; /* action indicator: TEI */ - - return Q921SendU(trunk, Q921_SAPI_TEI, Q921_COMMAND(trunk), Q921_TEI_BCAST, 0, 0x00, mes, offset); -} - - -/** - * Q921TeiSendAssignRequest - * \brief Ask for new TEI (TE mode only) - * \param[in] trunk pointer to Q921 data struct - * \return > 0 on success, <= 0 on error - * - * \author Stefan Knoblich - */ -static int Q921TeiSendAssignRequest(L2TRUNK trunk) -{ - struct Q921_Link *link = Q921_TRUNK_CONTEXT(trunk); - L2INT res; - - if (!Q921_IS_PTMP_TE(trunk)) /* only ptmp te mode*/ - return 0; - -#ifndef WIN32 - link->ri = (L2USHORT)(random() % 0xffff); -#else - link->ri = (L2USHORT)(rand() % 0xffff); //todo -#endif - - /* send TEI assign request */ - res = Q921TeiSend(trunk, Q921_TEI_ID_REQUEST, link->ri, Q921_TEI_BCAST); - - /* start T202 */ - Q921T202TimerStart(trunk); - - return res; -} - - -/** - * Q921TeiProcessAssignResponse - * \brief Process assign response (TE mode only) - * \param[in] trunk pointer to Q921 data struct - * \param[in] mes pointer to message buffer - * \param[in] size size of message - * \return > 0 on success; <= 0 on error - * - * \author Stefan Knoblich - */ -static int Q921TeiProcAssignResponse(L2TRUNK trunk, L2UCHAR *mes, L2INT size) -{ - struct Q921_Link *link = Q921_TRUNK_CONTEXT(trunk); - L2UCHAR offset = Q921_UFRAME_DATA_OFFSET(trunk); - L2USHORT ri = 0; - - if (!Q921_IS_PTMP_TE(trunk)) /* PTMP TE only */ - return 0; - - ri = (mes[offset + 1] << 8) | mes[offset + 2]; - - if(ri != link->ri) { - /* hmmm ..., not our response i guess */ - return 0; - } - - switch(mes[offset + 3]) { - case Q921_TEI_ID_ASSIGNED: - /* Yay, use the new TEI and change state to assigned */ - link->tei = mes[offset + 4] >> 1; - - Q921Log(trunk, Q921_LOG_DEBUG, "Assigned TEI %d, setting state to TEI_ASSIGNED\n", link->tei); - - Q921ChangeState(trunk, Q921_STATE_TEI_ASSIGNED, link->tei); - break; - - case Q921_TEI_ID_DENIED: - /* oops, what to do now? */ - if ((mes[offset + 4] >> 1) == Q921_TEI_BCAST) { - /* No more free TEIs? this is bad */ - - //Q921TeiSendVerifyRequest(trunk, Q921_TEI_BCAST); /* TODO: does this work ?? */ - } else { - /* other reason, this is fatal, shutdown link */ - } - - Q921Log(trunk, Q921_LOG_DEBUG, "TEI assignment has been denied, reason: %s\n", - ((mes[offset +4] >> 1) == Q921_TEI_BCAST) ? "No free TEIs available" : "Unknown"); - - Q921ChangeState(trunk, Q921_STATE_TEI_UNASSIGNED, link->tei); - break; - - default: - return 0; - } - - /* stop T202 */ - Q921T202TimerStop(trunk); - - return 1; -} - - -/** - * Q921TeiSendVerifyRequest - * \brief Verify TEI (TE mode only) - * \param[in] trunk pointer to Q921 data struct - * \return > 0 on success; <= 0 on error - * - * \author Stefan Knoblich - */ -static int Q921TeiSendVerifyRequest(L2TRUNK trunk) -{ - struct Q921_Link *link = Q921_TRUNK_CONTEXT(trunk); - L2INT res; - - if (!Q921_IS_PTMP_TE(trunk)) /* only ptmp te mode*/ - return 0; - - /* Request running? */ - if (trunk->T202) - return 0; - - /* Send TEI verify request */ - res = Q921TeiSend(trunk, Q921_TEI_ID_VERIFY, link->ri, link->tei); - - /* start T202 */ - Q921T202TimerStart(trunk); - - return res; -} - - -/** - * Q921TeiProcCheckRequest - * \brief Process Check Request (TE mode only) - * \param[in] trunk pointer to Q921 data struct - * \param[in] mes pointer to message buffer - * \param[in] size size of message - * \return > 0 on success; <= 0 on error - * - * \author Stefan Knoblich - */ -static int Q921TeiProcCheckRequest(L2TRUNK trunk, L2UCHAR *mes, L2INT size) -{ - struct Q921_Link *link = Q921_TRUNK_CONTEXT(trunk); - L2UCHAR offset = Q921_UFRAME_DATA_OFFSET(trunk); - L2UCHAR tei = (mes[offset + 4] >> 1); /* action indicator => tei */ - L2INT res = 0; - - if (!Q921_IS_PTMP_TE(trunk)) /* ptmp te mode only */ - return 0; - - Q921Log(trunk, Q921_LOG_DEBUG, "Received TEI Check request for TEI %d\n", tei); - - if (tei == Q921_TEI_BCAST || tei == link->tei) { - /* - * Broadcast TEI check or for our assigned TEI - */ - - /* send TEI check reponse */ - res = Q921TeiSend(trunk, Q921_TEI_ID_CHECKRESP, link->ri, link->tei); - - Q921T202TimerStop(trunk); - } - - return res; -} - - -/** - * Q921TeiProcRemoveRequest - * \brief Process remove Request (TE mode only) - * \param[in] trunk pointer to Q921 data struct - * \param[in] mes pointer to message buffer - * \param[in] size size of message - * \return > 0 on success; <= 0 on error - * - * \author Stefan Knoblich - */ -static int Q921TeiProcRemoveRequest(L2TRUNK trunk, L2UCHAR *mes, L2INT size) -{ - struct Q921_Link *link = Q921_TRUNK_CONTEXT(trunk); - L2UCHAR offset = Q921_UFRAME_DATA_OFFSET(trunk); - L2UCHAR tei = (mes[offset + 4] >> 1); /* action indicator => tei */ - L2INT res = 0; - - if (!Q921_IS_PTMP_TE(trunk)) /* ptmp te mode only */ - return 0; - - Q921Log(trunk, Q921_LOG_DEBUG, "Received TEI Remove request for TEI %d\n", tei); - - if (tei == Q921_TEI_BCAST || tei == link->tei) { - /* - * Broadcast TEI remove or for our assigned TEI - */ - - /* reset tei */ - link->tei = 0; - - /* change state (no action) */ - Q921ChangeState(trunk, Q921_STATE_TEI_UNASSIGNED, link->tei); - - /* TODO: hmm, request new one ? */ - res = Q921TeiSendAssignRequest(trunk); - } - return res; -} - - -/** - * Q921TeiProcAssignRequest - * \brief Process assign request from peer (NT mode only) - * \param[in] trunk pointer to Q921 data struct - * \param[in] mes pointer to message buffer - * \param[in] size size of message - * \return > 0 on success; <= 0 on error - * - * \author Stefan Knoblich - */ -static int Q921TeiProcAssignRequest(L2TRUNK trunk, L2UCHAR *mes, L2INT size) -{ - L2UCHAR offset = Q921_UFRAME_DATA_OFFSET(trunk); - L2USHORT ri = 0; - L2UCHAR tei = 0; - - if (!Q921_IS_PTMP_NT(trunk)) /* PTMP NT only */ - return 0; - - ri = (mes[offset + 1] << 8) | mes[offset + 2]; - tei = mes[offset + 4] >> 1; - - if(tei == Q921_TEI_BCAST) { - int x; - - /* dynamically allocate TEI */ - for(x = Q921_TEI_DYN_MIN, tei = 0; x <= Q921_TEI_MAX; x++) { - if(!trunk->tei_map[x]) { - tei = x; - break; - } - } - } - else if(!(tei > 0 && tei < Q921_TEI_DYN_MIN)) { - /* reject TEIs that are not in the static area */ - Q921TeiSendDenyResponse(trunk, 0, ri); - - return 0; - } - - if(!tei) { - /* no free TEI found */ - Q921TeiSendDenyResponse(trunk, Q921_TEI_BCAST, ri); - } - else { - struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei); - - /* mark used */ - trunk->tei_map[tei] = 1; - - /* assign tei */ - link->tei = tei; - - /* put context in TEI ASSIGNED state */ - Q921ChangeState(trunk, Q921_STATE_TEI_ASSIGNED, tei); - - /* send assign response */ - Q921TeiSendAssignedResponse(trunk, tei, ri); - - /* Start T201 */ - Q921T201TimerStart(trunk, tei); - } - return 0; -} - -/** - * Q921TeiSendCheckRequest - * \brief Send check request (NT mode only) - * \param[in] trunk pointer to Q921 data struct - * \param[in] tei TEI to check - * \return > 0 on success; <= 0 on error - * - * \author Stefan Knoblich - */ -static int Q921TeiSendCheckRequest(L2TRUNK trunk, L2UCHAR tei) -{ - L2INT res = 0; - - if (!Q921_IS_PTMP_NT(trunk)) /* PTMP NT only */ - return 0; - - /* send TEI check request */ - res = Q921TeiSend(trunk, Q921_TEI_ID_CHECKREQ, 0, tei); - - /* (Re-)Start T201 timer */ - Q921T201TimerStart(trunk, tei); - - return res; -} - -/** - * Q921TeiProcCheckResponse - * \brief Process Check Response (NT mode only) - * \param[in] trunk pointer to Q921 data struct - * \param[in] mes pointer to message buffer - * \param[in] size size of message - * \return > 0 on success; <= 0 on error - * - * \author Stefan Knoblich - */ -static int Q921TeiProcCheckResponse(L2TRUNK trunk, L2UCHAR *mes, L2INT size) -{ - struct Q921_Link *link; - L2UCHAR offset = Q921_UFRAME_DATA_OFFSET(trunk); - L2USHORT ri = 0; - L2UCHAR tei = 0; - - if (!Q921_IS_PTMP_NT(trunk)) /* PTMP NT mode only */ - return 0; - - ri = (mes[offset + 1] << 8) | mes[offset + 2]; - tei = mes[offset + 4] >> 1; - - /* restart T201 */ - Q921T201TimerStop(trunk, tei); - - /* reset counter */ - link = Q921_LINK_CONTEXT(trunk, tei); - link->N202 = 0; - - if(!(tei > 0 && tei < Q921_TEI_MAX) || !trunk->tei_map[tei]) { - /* TODO: Should we send a DISC first? */ - - /* TEI not assigned? Invalid TEI? */ - Q921TeiSendRemoveRequest(trunk, tei); - - /* change state */ - Q921ChangeState(trunk, Q921_STATE_STOPPED, tei); - - /* clear */ - memset(link, 0, sizeof(struct Q921_Link)); - } else { - /* Start T201 */ - Q921T201TimerStart(trunk, tei); - } - - return 0; -} - - -/** - * Q921TeiProcVerifyRequest - * \brief Process Verify Request (NT mode only) - * \param[in] trunk pointer to Q921 data struct - * \param[in] mes pointer to message buffer - * \param[in] size size of message - * \return > 0 on success; <= 0 on error - * - * \author Stefan Knoblich - */ -static int Q921TeiProcVerifyRequest(L2TRUNK trunk, L2UCHAR *mes, L2INT size) -{ - L2UCHAR resp[25]; - L2UCHAR offset = Q921_UFRAME_DATA_OFFSET(trunk); - L2UCHAR tei = 0; - - if (!Q921_IS_PTMP_NT(trunk)) /* PTMP NT mode only */ - return 0; - - tei = mes[offset + 4] >> 1; - - /* todo: handle response... verify assigned TEI */ - resp[offset + 0] = 0; - - return 0; -} - -/** - * Q921TeiSendDenyResponse - * \brief Send Deny Response (NT mode only) - * \param[in] trunk pointer to Q921 data struct - * \return > 0 on success; <= 0 on error - * - * \author Stefan Knoblich - */ -static int Q921TeiSendDenyResponse(L2TRUNK trunk, L2UCHAR tei, L2USHORT ri) -{ - if (!Q921_IS_PTMP_NT(trunk)) /* PTMP NT only */ - return 0; - - return Q921TeiSend(trunk, Q921_TEI_ID_DENIED, ri, tei); -} - - -/** - * Q921TeiSendAssignedResponse - * \brief Send Assigned Response (NT mode only) - * \param[in] trunk pointer to Q921 data struct - * \param[in] tei TEI to assign - * \param[in] ri RI of request - * \return > 0 on success; <= 0 on error - * - * \author Stefan Knoblich - */ -static int Q921TeiSendAssignedResponse(L2TRUNK trunk, L2UCHAR tei, L2USHORT ri) -{ - if (!Q921_IS_PTMP_NT(trunk)) /* PTMP NT only */ - return 0; - - return Q921TeiSend(trunk, Q921_TEI_ID_ASSIGNED, ri, tei); -} - -/** - * Q921TeiSendRemoveRequest - * \brief Send Remove Request (NT mode only) - * \param[in] trunk pointer to Q921 data struct - * \param[in] tei TEI to remove - * \return > 0 on success; <= 0 on error - * - * \author Stefan Knoblich - */ -static int Q921TeiSendRemoveRequest(L2TRUNK trunk, L2UCHAR tei) -{ - if (!Q921_IS_PTMP_NT(trunk)) /* PTMP NT only */ - return 0; - - return Q921TeiSend(trunk, Q921_TEI_ID_REMOVE, 0, tei); -} diff --git a/libs/freetdm/src/isdn/Q931.c b/libs/freetdm/src/isdn/Q931.c deleted file mode 100644 index b245c144d8..0000000000 --- a/libs/freetdm/src/isdn/Q931.c +++ /dev/null @@ -1,888 +0,0 @@ -/***************************************************************************** - - FileName: Q931.c - - Contents: Implementation of Q.931 stack main interface functions. - See q931.h for description. - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -#include "Q921.h" -#include "Q931.h" -#include "national.h" -#include "DMS.h" -#include "5ESS.h" - - -/***************************************************************************** - - Dialect function pointers tables. - - The following function pointer arrays define pack/unpack functions and - processing furnctions for the different Q.931 based dialects. - - The arrays are initialized with pointers to dummy functions and later - overrided with pointers to actual functions as new dialects are added. - - The initial Q.931 will as an example define 2 dialects as it treats User - and Network mode as separate ISDN dialects. - - The API messages Q931AddProc, Q931AddMes, Q931AddIE are used to initialize - these table entries during system inititialization of a stack. - -*****************************************************************************/ -q931proc_func_t *Q931Proc[Q931MAXDLCT][Q931MAXMES]; - -q931umes_func_t *Q931Umes[Q931MAXDLCT][Q931MAXMES]; -q931pmes_func_t *Q931Pmes[Q931MAXDLCT][Q931MAXMES]; - -q931uie_func_t *Q931Uie[Q931MAXDLCT][Q931MAXIE]; -q931pie_func_t *Q931Pie[Q931MAXDLCT][Q931MAXIE]; - -q931timeout_func_t *Q931Timeout[Q931MAXDLCT][Q931MAXTIMER]; -q931timer_t Q931Timer[Q931MAXDLCT][Q931MAXTIMER]; - -void (*Q931CreateDialectCB[Q931MAXDLCT])(L3UCHAR iDialect) = { NULL, NULL }; - -Q931State Q931st[Q931MAXSTATE]; - -/***************************************************************************** - - Core system tables and variables. - -*****************************************************************************/ - -L3INT Q931L4HeaderSpace = {0}; /* header space to be ignoder/inserted */ - /* at head of each message. */ - -L3INT Q931L2HeaderSpace = {4}; /* Q921 header space, sapi, tei etc */ - -/***************************************************************************** - - Main interface callback functions. - -*****************************************************************************/ - -Q931ErrorCB_t Q931ErrorProc; /* callback for error messages. */ -L3ULONG (*Q931GetTimeProc) (void) = NULL; /* callback for func reading time in ms */ - -/***************************************************************************** - - Function: Q931SetL4HeaderSpace - - Description: Set the # of bytes to be inserted/ignored at the head of - each message. Q931 will issue a message with space for header - and the user will use this to fill in whatever header info - is required to support the architecture used. - -*****************************************************************************/ -void Q931SetL4HeaderSpace(L3INT space) -{ - Q931L4HeaderSpace = space; -} - -/***************************************************************************** - - Function: Q931SetL2HeaderSpace - - Description: Set the # of bytes to be inserted/ignored at the head of - each message. Q931 will issue a message with space for header - and the user will use this to fill in whatever header info - is required to support the architecture used. - -*****************************************************************************/ -void Q931SetL2HeaderSpace(L3INT space) -{ - Q931L2HeaderSpace = space; -} - -/***************************************************************************** - - Function: Q931ProcDummy - - Description: Dummy function for message processing. - -*****************************************************************************/ -L3INT Q931ProcDummy(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b,L3INT c) -{ - return Q931E_INTERNAL; -} - -/***************************************************************************** - - Function: Q931UmesDummy - - Description: Dummy function for message processing - -*****************************************************************************/ -L3INT Q931UmesDummy(Q931_TrunkInfo_t *pTrunk,L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT IOff, L3INT Size) -{ - return Q931E_UNKNOWN_MESSAGE; -} - -/***************************************************************************** - - Function: Q931UieDummy - - Description: Dummy function for message processing - -*****************************************************************************/ -L3INT Q931UieDummy(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - return Q931E_UNKNOWN_IE; -} - -/***************************************************************************** - - Function: Q931PmesDummy - - Description: Dummy function for message processing - -*****************************************************************************/ -L3INT Q931PmesDummy(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - return Q931E_UNKNOWN_MESSAGE; -} - -/***************************************************************************** - - Function: Q931PieDummy - - Description: Dummy function for message processing - -*****************************************************************************/ -L3INT Q931PieDummy(Q931_TrunkInfo_t *pTrunk,L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - return Q931E_UNKNOWN_IE; -} - -/***************************************************************************** - - Function: Q931TxDummy - - Description: Dummy function for message processing - -*****************************************************************************/ -L3INT Q931TxDummy(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT n) -{ - return Q931E_MISSING_CB; -} - -/***************************************************************************** - - Function: Q931ErrorDummy - - Description: Dummy function for error processing - -*****************************************************************************/ -L3INT Q931ErrorDummy(void *priv, L3INT a, L3INT b, L3INT c) -{ - return 0; -} - -/***************************************************************************** - - Function: Q931Initialize - - Description: This function Initialize the stack. - - Will set up the trunk array, channel - arrays and initialize Q931 function arrays before it finally - set up EuroISDN processing with User as dialect 0 and - Network as dialect 1. - - Note: Initialization of other stacks should be inserted after - the initialization of EuroISDN. - -*****************************************************************************/ -void Q931Initialize() -{ - L3INT x,y; - - /* Secure the callbacks to default procs */ - Q931ErrorProc = Q931ErrorDummy; - - /* The user will only add the message handlers and IE handlers he need, - * so we need to initialize every single entry to a default function - * that will throw an appropriate error if they are ever called. - */ - for (x = 0; x < Q931MAXDLCT; x++) { - for (y = 0; y < Q931MAXMES; y++) { - Q931Proc[x][y] = Q931ProcDummy; - Q931Umes[x][y] = Q931UmesDummy; - Q931Pmes[x][y] = Q931PmesDummy; - } - for (y = 0; y < Q931MAXIE; y++) { - Q931Pie[x][y] = Q931PieDummy; - Q931Uie[x][y] = Q931UieDummy; - } - for (y = 0; y < Q931MAXTIMER; y++) { - Q931Timeout[x][y] = Q931TimeoutDummy; - Q931Timer[x][y] = 0; - } - } - - if (Q931CreateDialectCB[Q931_Dialect_Q931 + Q931_TE] == NULL) - Q931AddDialect(Q931_Dialect_Q931 + Q931_TE, Q931CreateTE); - - if (Q931CreateDialectCB[Q931_Dialect_Q931 + Q931_NT] == NULL) - Q931AddDialect(Q931_Dialect_Q931 + Q931_NT, Q931CreateNT); - - if (Q931CreateDialectCB[Q931_Dialect_National + Q931_TE] == NULL) - Q931AddDialect(Q931_Dialect_National + Q931_TE, nationalCreateTE); - - if (Q931CreateDialectCB[Q931_Dialect_National + Q931_NT] == NULL) - Q931AddDialect(Q931_Dialect_National + Q931_NT, nationalCreateNT); - - if (Q931CreateDialectCB[Q931_Dialect_DMS + Q931_TE] == NULL) - Q931AddDialect(Q931_Dialect_DMS + Q931_TE, DMSCreateTE); - - if (Q931CreateDialectCB[Q931_Dialect_DMS + Q931_NT] == NULL) - Q931AddDialect(Q931_Dialect_DMS + Q931_NT, DMSCreateNT); - - if (Q931CreateDialectCB[Q931_Dialect_5ESS + Q931_TE] == NULL) - Q931AddDialect(Q931_Dialect_5ESS + Q931_TE, ATT5ESSCreateTE); - - if (Q931CreateDialectCB[Q931_Dialect_5ESS + Q931_NT] == NULL) - Q931AddDialect(Q931_Dialect_5ESS + Q931_NT, ATT5ESSCreateNT); - - /* The last step we do is to call the callbacks to create the dialects */ - for (x = 0; x < Q931MAXDLCT; x++) { - if (Q931CreateDialectCB[x] != NULL) { - Q931CreateDialectCB[x]((L3UCHAR)x); - } - } -} - -/** - * Q931TimerTick - * \brief Periodically called to update and check for expired timers - * \param pTrunk Q.931 trunk - */ -void Q931TimerTick(Q931_TrunkInfo_t *pTrunk) -{ - struct Q931_Call *call = NULL; - L3ULONG now = 0; - L3INT x; - - /* TODO: Loop through all active calls, check timers and call timout procs - * if timers are expired. - * Implement a function array so each dialect can deal with their own - * timeouts. - */ - now = Q931GetTime(); - - for (x = 0; x < Q931MAXCALLPERTRUNK; x++) { - call = &pTrunk->call[x]; - - if (!call->InUse || !call->Timer || !call->TimerID) - continue; - - if (call->Timer <= now) { - /* Stop Timer */ - Q931StopTimer(pTrunk, x, call->TimerID); - - /* Invoke dialect timeout callback */ - Q931Timeout[pTrunk->Dialect][call->TimerID](pTrunk, x); - } - } -} - -/***************************************************************************** - - Function: Q931Rx23 - - Description: Receive message from layer 2 (LAPD). Receiving a message - is always done in 2 steps. First the message must be - interpreted and translated to a static struct. Secondly - the message is processed and responded to. - - The Q.931 message contains a static header that is - interpreted in this function. The rest is interpreted - in a sub function according to mestype. - - Parameters: pTrunk [IN] Ptr to trunk info. - buf [IN] Ptr to buffer containing message. - Size [IN] Size of message. - - Return Value: Error Code. 0 = No Error, < 0 :error, > 0 : Warning - see q931errors.h for details. - -*****************************************************************************/ -L3INT Q931Rx23(Q931_TrunkInfo_t *pTrunk, L3INT ind, L3UCHAR tei, L3UCHAR * buf, L3INT Size) -{ - L3UCHAR *Mes = NULL; - L3INT RetCode = Q931E_NO_ERROR; - Q931mes_Generic *m = (Q931mes_Generic *) pTrunk->L3Buf; - L3INT ISize; - L3INT IOff = 0; - L3INT L2HSize = Q931L2HeaderSpace; - - switch (ind) { - case Q921_DL_UNIT_DATA: /* DL-UNITDATA indication (UI frame, 3 byte header) */ - L2HSize = 3; - - case Q921_DL_DATA: /* DL-DATA indication (I frame, 4 byte header) */ - /* Reset our decode buffer */ - memset(pTrunk->L3Buf, 0, sizeof(pTrunk->L3Buf)); - - /* L2 Header Offset */ - Mes = &buf[L2HSize]; - - /* Protocol Discriminator */ - m->ProtDisc = Mes[IOff++]; - - /* CRV */ - m->CRVFlag = (Mes[IOff + 1] >> 7) & 0x01; - m->CRV = Q931Uie_CRV(pTrunk, Mes, m->buf, &IOff, &ISize); - - /* Message Type */ - m->MesType = Mes[IOff++]; - - /* Store tei */ - m->Tei = tei; - - /* d'oh a little ugly but this saves us from: - * a) doing Q.921 work in the lower levels (extracting the TEI ourselves) - * b) adding a tei parameter to _all_ Proc functions - */ - if (tei) { - L3INT callIndex = 0; - - /* Find the call using CRV */ - RetCode = Q931FindCRV(pTrunk, m->CRV, &callIndex); - if (RetCode == Q931E_NO_ERROR && !pTrunk->call[callIndex].Tei) { - pTrunk->call[callIndex].Tei = tei; - } - } - - Q931Log(pTrunk, Q931_LOG_DEBUG, "Received message from Q.921 (ind %d, tei %d, size %d)\nMesType: %d, CRVFlag %d (%s), CRV %d (Dialect: %d)\n", ind, m->Tei, Size, - m->MesType, m->CRVFlag, m->CRVFlag ? "Terminator" : "Originator", m->CRV, pTrunk->Dialect); - - RetCode = Q931Umes[pTrunk->Dialect][m->MesType](pTrunk, Mes, (Q931mes_Generic *)pTrunk->L3Buf, IOff, Size - L2HSize); - if (RetCode >= Q931E_NO_ERROR) { - RetCode = Q931Proc[pTrunk->Dialect][m->MesType](pTrunk, pTrunk->L3Buf, 2); - } - break; - - default: - break; - } - - return RetCode; -} - -/***************************************************************************** - - Function: Q931Tx34 - - Description: Called from the stack to send a message to layer 4. - - Parameters: Mes[IN] Ptr to message buffer. - Size[IN] Message size in bytes. - - Return Value: Error Code. 0 = No Error, < 0 :error, > 0 : Warning - see q931errors.h for details. - -*****************************************************************************/ -L3INT Q931Tx34(Q931_TrunkInfo_t *pTrunk, L3UCHAR * Mes, L3INT Size) -{ - Q931Log(pTrunk, Q931_LOG_DEBUG, "Sending message to Layer4 (size: %d)\n", Size); - - if (pTrunk->Q931Tx34CBProc) { - return pTrunk->Q931Tx34CBProc(pTrunk->PrivateData34, Mes, Size); - } - return Q931E_MISSING_CB; -} - -/***************************************************************************** - - Function: Q931Rx43 - - Description: Receive message from Layer 4 (application). - - Parameters: pTrunk[IN] Trunk #. - buf[IN] Message Pointer. - Size[IN] Message size in bytes. - - Return Value: Error Code. 0 = No Error, < 0 :error, > 0 : Warning - see q931errors.h for details. - -*****************************************************************************/ -L3INT Q931Rx43(Q931_TrunkInfo_t *pTrunk,L3UCHAR * buf, L3INT Size) -{ - Q931mes_Header *ptr = (Q931mes_Header*)&buf[Q931L4HeaderSpace]; - L3INT RetCode = Q931E_NO_ERROR; - - Q931Log(pTrunk, Q931_LOG_DEBUG, "Receiving message from Layer4 (size: %d, type: %d)\n", Size, ptr->MesType); - - RetCode = Q931Proc[pTrunk->Dialect][ptr->MesType](pTrunk, buf, 4); - - Q931Log(pTrunk, Q931_LOG_DEBUG, "Q931Rx43 return code: %d\n", RetCode); - - return RetCode; -} - -/***************************************************************************** - - Function: Q931Tx32 - - Description: Called from the stack to send a message to L2. The input is - always a non-packed message so it will first make a proper - call to create a packed message before it transmits that - message to layer 2. - - Parameters: pTrunk[IN] Trunk # - buf[IN] Ptr to message buffer. - Size[IN] Message size in bytes. - - Return Value: Error Code. 0 = No Error, < 0 :error, > 0 : Warning - see q931errors.h for details. - -*****************************************************************************/ -L3INT Q931Tx32Data(Q931_TrunkInfo_t *pTrunk, L3UCHAR bcast, L3UCHAR * Mes, L3INT Size) -{ - Q931mes_Generic *ptr = (Q931mes_Generic*)Mes; - L3INT RetCode = Q931E_NO_ERROR; - L3INT iDialect = pTrunk->Dialect; - L3INT Offset = bcast ? (Q931L2HeaderSpace - 1) : Q931L2HeaderSpace; - L3INT OSize; - - Q931Log(pTrunk, Q931_LOG_DEBUG, "Sending message to Q.921 (size: %d)\n", Size); - - memset(pTrunk->L2Buf, 0, sizeof(pTrunk->L2Buf)); - - /* Call pack function through table. */ - RetCode = Q931Pmes[iDialect][ptr->MesType](pTrunk, (Q931mes_Generic *)Mes, Size, &pTrunk->L2Buf[Offset], &OSize); - if (RetCode >= Q931E_NO_ERROR) { - L3INT callIndex; - L3UCHAR tei = 0; - - if (ptr->CRV) { - /* Find the call using CRV */ - RetCode = Q931FindCRV(pTrunk, ptr->CRV, &callIndex); - if (RetCode != Q931E_NO_ERROR) - return RetCode; - - tei = pTrunk->call[callIndex].Tei; - } - - if (pTrunk->Q931Tx32CBProc) { - RetCode = pTrunk->Q931Tx32CBProc(pTrunk->PrivateData32, bcast ? Q921_DL_UNIT_DATA : Q921_DL_DATA, tei, pTrunk->L2Buf, OSize + Offset); - } else { - RetCode = Q931E_MISSING_CB; - } - } - - return RetCode; -} - - -/***************************************************************************** - - Function: Q931SetError - - Description: Called from the stack to indicate an error. - - Parameters: ErrID ID of ie or message causing error. - ErrPar1 Error parameter 1 - ErrPar2 Error parameter 2. - - -*****************************************************************************/ -void Q931SetError(Q931_TrunkInfo_t *pTrunk,L3INT ErrID, L3INT ErrPar1, L3INT ErrPar2) -{ - if (pTrunk->Q931ErrorCBProc) { - pTrunk->Q931ErrorCBProc(pTrunk->PrivateData34, ErrID, ErrPar1, ErrPar2); - } else { - Q931ErrorProc(pTrunk->PrivateData34, ErrID, ErrPar1, ErrPar2); - } -} - -void Q931SetDefaultErrorCB(Q931ErrorCB_t Q931ErrorPar) -{ - Q931ErrorProc = Q931ErrorPar; -} - -/***************************************************************************** - - Function: Q931CreateCRV - - Description: Create a CRV entry and return it's index. The function will - locate a free entry in the call tables allocate it and - allocate a unique CRV value attached to it. - - Parameters: pTrunk [IN] Trunk number - callindex [OUT] return call table index. - - Return Value: Error Code. 0 = No Error, < 0 :error, > 0 : Warning - see q931errors.h for details. -****************************************************************************/ -L3INT Q931CreateCRV(Q931_TrunkInfo_t *pTrunk, L3INT * callIndex) -{ - L3INT CRV = Q931GetUniqueCRV(pTrunk); - - return Q931AllocateCRV(pTrunk, CRV, callIndex); -} - - -L3INT Q931ReleaseCRV(Q931_TrunkInfo_t *pTrunk, L3INT CRV) -{ - int callIndex; - - if ((Q931FindCRV(pTrunk, CRV, &callIndex)) == Q931E_NO_ERROR) { - pTrunk->call[callIndex].InUse = 0; - return Q931E_NO_ERROR; - } - - return Q931E_INVALID_CRV; -} - -/***************************************************************************** - - Function: Q931AllocateCRV - - Description: Allocate a call table entry and assigns the given CRV value - to it. - - Parameters: pTrunk [IN] Trunk number - iCRV [IN] Call Reference Value. - callindex [OUT] return call table index. - - Return Value: Error Code. 0 = No Error, < 0 :error, > 0 : Warning - see q931errors.h for details. - -*****************************************************************************/ -L3INT Q931AllocateCRV(Q931_TrunkInfo_t *pTrunk, L3INT iCRV, L3INT * callIndex) -{ - L3INT x; - for (x = 0; x < Q931MAXCALLPERTRUNK; x++) { - if (!pTrunk->call[x].InUse) { - pTrunk->call[x].CRV = iCRV; - pTrunk->call[x].BChan = 255; - pTrunk->call[x].State = 0; /* null state - idle */ - pTrunk->call[x].TimerID = 0; /* no timer running */ - pTrunk->call[x].Timer = 0; - pTrunk->call[x].InUse = 1; /* mark as used */ - *callIndex = x; - return Q931E_NO_ERROR; - } - } - return Q931E_TOMANYCALLS; -} - -/***************************************************************************** - - Function: Q931GetCallState - - Description: Look up CRV and return current call state. A non existing - CRV is the same as state zero (0). - - Parameters: pTrunk [IN] Trunk number. - iCRV [IN] CRV - - Return Value: Call State. - -*****************************************************************************/ -L3INT Q931GetCallState(Q931_TrunkInfo_t *pTrunk, L3INT iCRV) -{ - L3INT x; - for (x = 0; x < Q931MAXCALLPERTRUNK; x++) { - if (pTrunk->call[x].InUse) { - if (pTrunk->call[x].CRV == iCRV) { - return pTrunk->call[x].State; - } - } - } - return 0; /* assume state zero for non existing CRV's */ -} - -/** - * Q931StartTimer - * \brief Start a timer - * \param pTrunk Q.931 trunk - * \param callindex Index of the call - * \param iTimerID ID of timer - * \return always 0 - */ -L3INT Q931StartTimer(Q931_TrunkInfo_t *pTrunk, L3INT callIndex, L3USHORT iTimerID) -{ -#if 0 - L3ULONG duration = Q931Timer[pTrunk->Dialect][iTimerID]; - - if (duration) { - pTrunk->call[callIndex].Timer = Q931GetTime() + duration; - pTrunk->call[callIndex].TimerID = iTimerID; - } -#endif - return 0; -} - -/** - * Q931StopTimer - * \brief Stop a timer - * \param pTrunk Q.931 trunk - * \param callindex Index of the call - * \param iTimerID ID of timer - * \return always 0 - */ -L3INT Q931StopTimer(Q931_TrunkInfo_t *pTrunk, L3INT callindex, L3USHORT iTimerID) -{ - if (pTrunk->call[callindex].TimerID == iTimerID) - pTrunk->call[callindex].TimerID = 0; - - return 0; -} - -L3INT Q931SetState(Q931_TrunkInfo_t *pTrunk, L3INT callIndex, L3INT iState) -{ - pTrunk->call[callIndex].State = iState; - - return 0; -} - -L3ULONG Q931GetTime() -{ - L3ULONG tNow = 0; - static L3ULONG tLast = 0; - - if (Q931GetTimeProc != NULL) { - tNow = Q931GetTimeProc(); - if (tNow < tLast) { /* wrapped */ - /* TODO */ - } - tLast = tNow; - } - return tNow; -} - -void Q931SetGetTimeCB(L3ULONG (*callback)(void)) -{ - Q931GetTimeProc = callback; -} - -L3INT Q931FindCRV(Q931_TrunkInfo_t *pTrunk, L3INT crv, L3INT *callindex) -{ - L3INT x; - for (x = 0; x < Q931MAXCALLPERTRUNK; x++) { - if (pTrunk->call[x].InUse) { - if (pTrunk->call[x].CRV == crv) { - *callindex = x; - return Q931E_NO_ERROR; - } - } - } - return Q931E_INVALID_CRV; -} - - -void Q931AddDialect(L3UCHAR i, void (*callback)(L3UCHAR iD )) -{ - if (i < Q931MAXDLCT) { - Q931CreateDialectCB[i] = callback; - } -} - -/***************************************************************************** - Function: Q931AddStateEntry - - Description: Find an empty entry in the dialects state table and add this - entry. -*****************************************************************************/ -void Q931AddStateEntry(L3UCHAR iD, L3INT iState, L3INT iMes, L3UCHAR cDir) -{ - int x; - for (x = 0; x < Q931MAXSTATE; x++) { - if (Q931st[x].Message == 0) { - Q931st[x].State = iState; - Q931st[x].Message = iMes; - Q931st[x].Direction = cDir; - /* TODO Sort table and use bsearch */ - return; - } - } -} - -/***************************************************************************** - Function: Q931IsEventLegal - - Description: Check state table for matching criteria to indicate if this - Message is legal in this state or not. - - Note: Someone write a bsearch or invent something smart here - please - sequential is ok for now. -*****************************************************************************/ -L3BOOL Q931IsEventLegal(L3UCHAR iD, L3INT iState, L3INT iMes, L3UCHAR cDir) -{ - int x; - /* TODO Sort table and use bsearch */ - for (x = 0; x < Q931MAXSTATE; x++) { - if (Q931st[x].State == iState && Q931st[x].Message == iMes && - Q931st[x].Direction == cDir) { - return L3TRUE; - } - } - return L3FALSE; -} - -/***************************************************************************** - Function: q931_error_to_name() - - Description: Check state table for matching criteria to indicate if this - Message is legal in this state or not. - - Note: Someone write a bsearch or invent something smart here - please - sequential is ok for now. -*****************************************************************************/ -static const char *q931_error_names[] = { - "Q931E_NO_ERROR", /* 0 */ - - "Q931E_UNKNOWN_MESSAGE", /* -3001 */ - "Q931E_ILLEGAL_IE", /* -3002 */ - "Q931E_UNKNOWN_IE", /* -3003 */ - "Q931E_BEARERCAP", /* -3004 */ - "Q931E_HLCOMP", /* -3005 */ - "Q931E_LLCOMP", /* -3006 */ - "Q931E_INTERNAL", /* -3007 */ - "Q931E_MISSING_CB", /* -3008 */ - "Q931E_UNEXPECTED_MESSAGE", /* -3009 */ - "Q931E_ILLEGAL_MESSAGE", /* -3010 */ - "Q931E_TOMANYCALLS", /* -3011 */ - "Q931E_INVALID_CRV", /* -3012 */ - "Q931E_CALLID", /* -3013 */ - "Q931E_CALLSTATE", /* -3014 */ - "Q931E_CALLEDSUB", /* -3015 */ - "Q931E_CALLEDNUM", /* -3016 */ - "Q931E_CALLINGNUM", /* -3017 */ - "Q931E_CALLINGSUB", /* -3018 */ - "Q931E_CAUSE", /* -3019 */ - "Q931E_CHANID", /* -3020 */ - "Q931E_DATETIME", /* -3021 */ - "Q931E_DISPLAY", /* -3022 */ - "Q931E_KEYPADFAC", /* -3023 */ - "Q931E_NETFAC", /* -3024 */ - "Q931E_NOTIFIND", /* -3025 */ - "Q931E_PROGIND", /* -3026 */ - "Q931E_RESTARTIND", /* -3027 */ - "Q931E_SEGMENT", /* -3028 */ - "Q931E_SIGNAL", /* -3029 */ - "Q931E_GENERIC_DIGITS" /* -3030 */ - -}; - -#define Q931_MAX_ERROR 30 - -const char *q931_error_to_name(q931_error_t error) -{ - int index = 0; - if ((int)error < 0) { - index = (((int)error * -1) -3000); - } - if (index < 0 || index > Q931_MAX_ERROR) { - return ""; - } - return q931_error_names[index]; -} -/* - * Logging - */ -#include - -L3INT Q931Log(Q931_TrunkInfo_t *trunk, Q931LogLevel_t level, const char *fmt, ...) -{ - char buf[Q931_LOGBUFSIZE]; - L3INT len; - va_list ap; - - if (!trunk->Q931LogCBProc) - return 0; - - if (trunk->loglevel < level) - return 0; - - va_start(ap, fmt); - - len = vsnprintf(buf, sizeof(buf)-1, fmt, ap); - if (len <= 0) { - /* TODO: error handling */ - return -1; - } - if (len >= sizeof(buf)) - len = sizeof(buf) - 1; - - buf[len] = '\0'; - - va_end(ap); - - return trunk->Q931LogCBProc(trunk->PrivateDataLog, level, buf, len); -} - -/** - * Q921SetLogCB - * \brief Set Logging callback function and private data - */ -void Q931SetLogCB(Q931_TrunkInfo_t *trunk, Q931LogCB_t func, void *priv) -{ - trunk->Q931LogCBProc = func; - trunk->PrivateDataLog = priv; -} - -/** - * Q921SetLogLevel - * \brief Set Loglevel - */ -void Q931SetLogLevel(Q931_TrunkInfo_t *trunk, Q931LogLevel_t level) -{ - if(!trunk) - return; - - if (level < Q931_LOG_NONE) { - level = Q931_LOG_NONE; - } else if (level > Q931_LOG_DEBUG) { - level = Q931_LOG_DEBUG; - } - - trunk->loglevel = level; -} - -/** - * Q931TimeoutDummy - * \brief Dummy handler for timeouts - * \param pTrunk Q.931 trunk - * \param callIndex Index of call - */ -L3INT Q931TimeoutDummy(Q931_TrunkInfo_t *pTrunk, L3INT callIndex) -{ - Q931Log(pTrunk, Q931_LOG_DEBUG, "Timer %d of call %d (CRV: %d) timed out\n", pTrunk->call[callIndex].TimerID, callIndex, pTrunk->call[callIndex].CRV); - - return 0; -} diff --git a/libs/freetdm/src/isdn/Q931StateNT.c b/libs/freetdm/src/isdn/Q931StateNT.c deleted file mode 100644 index 8d05fb6d03..0000000000 --- a/libs/freetdm/src/isdn/Q931StateNT.c +++ /dev/null @@ -1,1218 +0,0 @@ -/***************************************************************************** - - FileName: q931StateNT.c - - Contents: Q.931 State Engine for NT (Network Mode). - - The controlling state engine for Q.931 is the state engine - on the NT side. The state engine on the TE side is a slave - of this. The TE side maintain it's own states as described in - ITU-T Q931, but will in raise conditions be overridden by - the NT side. - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -#include "Q931.h" - -extern L3INT Q931L4HeaderSpace; - -/***************************************************************************** - Function: Q931CreateNT - - Description: Will create the Q931 NT as a Dialect in the stack. The first - bulk set up the message handlers, the second bulk the IE - encoders/coders, and the last bulk set up the state table. - - Parameters: i Dialect index -*****************************************************************************/ -void Q931CreateNT(L3UCHAR i) -{ - Q931SetMesProc(Q931mes_ALERTING, i, Q931ProcAlertingNT, Q931Umes_Alerting, Q931Pmes_Alerting); - Q931SetMesProc(Q931mes_CALL_PROCEEDING, i, Q931ProcCallProceedingNT, Q931Umes_CallProceeding, Q931Pmes_CallProceeding); - Q931SetMesProc(Q931mes_CONNECT, i, Q931ProcConnectNT, Q931Umes_Connect, Q931Pmes_Connect); - Q931SetMesProc(Q931mes_CONNECT_ACKNOWLEDGE, i, Q931ProcConnectAckNT, Q931Umes_ConnectAck, Q931Pmes_ConnectAck); - Q931SetMesProc(Q931mes_PROGRESS, i, Q931ProcProgressNT, Q931Umes_Progress, Q931Pmes_Progress); - Q931SetMesProc(Q931mes_SETUP, i, Q931ProcSetupNT, Q931Umes_Setup, Q931Pmes_Setup); - Q931SetMesProc(Q931mes_SETUP_ACKNOWLEDGE, i, Q931ProcSetupAckNT, Q931Umes_SetupAck, Q931Pmes_SetupAck); - Q931SetMesProc(Q931mes_RESUME, i, Q931ProcResumeNT, Q931Umes_Resume, Q931Pmes_Resume); - Q931SetMesProc(Q931mes_RESUME_ACKNOWLEDGE, i, Q931ProcResumeAckNT, Q931Umes_ResumeAck, Q931Pmes_ResumeAck); - Q931SetMesProc(Q931mes_RESUME_REJECT, i, Q931ProcResumeRejectNT, Q931Umes_ResumeReject, Q931Pmes_ResumeReject); - Q931SetMesProc(Q931mes_SUSPEND, i, Q931ProcSuspendNT, Q931Umes_Suspend, Q931Pmes_Suspend); - Q931SetMesProc(Q931mes_SUSPEND_ACKNOWLEDGE, i, Q931ProcSuspendAckNT, Q931Umes_SuspendAck, Q931Pmes_SuspendAck); - Q931SetMesProc(Q931mes_SUSPEND_REJECT, i, Q931ProcSuspendRejectNT, Q931Umes_SuspendReject, Q931Pmes_SuspendReject); - Q931SetMesProc(Q931mes_USER_INFORMATION, i, Q931ProcUserInformationNT, Q931Umes_UserInformation, Q931Pmes_UserInformation); - Q931SetMesProc(Q931mes_DISCONNECT, i, Q931ProcDisconnectNT, Q931Umes_Disconnect, Q931Pmes_Disconnect); - Q931SetMesProc(Q931mes_RELEASE, i, Q931ProcReleaseNT, Q931Umes_Release, Q931Pmes_Release); - Q931SetMesProc(Q931mes_RELEASE_COMPLETE, i, Q931ProcReleaseCompleteNT, Q931Umes_ReleaseComplete, Q931Pmes_ReleaseComplete); - Q931SetMesProc(Q931mes_RESTART, i, Q931ProcRestartNT, Q931Umes_Restart, Q931Pmes_Restart); - Q931SetMesProc(Q931mes_RESTART_ACKNOWLEDGE, i, Q931ProcRestartAckNT, Q931Umes_RestartAck, Q931Pmes_RestartAck); - Q931SetMesProc(Q931mes_CONGESTION_CONTROL, i, Q931ProcCongestionControlNT, Q931Umes_CongestionControl, Q931Pmes_CongestionControl); - Q931SetMesProc(Q931mes_INFORMATION, i, Q931ProcInformationNT, Q931Umes_Information, Q931Pmes_Information); - Q931SetMesProc(Q931mes_NOTIFY, i, Q931ProcNotifyNT, Q931Umes_Notify, Q931Pmes_Notify); - Q931SetMesProc(Q931mes_STATUS, i, Q931ProcStatusNT, Q931Umes_Status, Q931Pmes_Status); - Q931SetMesProc(Q931mes_STATUS_ENQUIRY, i, Q931ProcStatusEnquiryNT, Q931Umes_StatusEnquiry, Q931Pmes_StatusEnquiry); - Q931SetMesProc(Q931mes_SEGMENT, i, Q931ProcSegmentNT, Q931Umes_Segment, Q931Pmes_Segment); - - Q931SetMesProc(Q932mes_FACILITY, i, Q932ProcFacilityNT, Q932Umes_Facility, Q932Pmes_Facility); - Q931SetMesProc(Q932mes_HOLD, i, Q932ProcHoldNT, Q932Umes_Hold, Q932Pmes_Hold); - Q931SetMesProc(Q932mes_HOLD_ACKNOWLEDGE, i, Q932ProcHoldAckNT, Q932Umes_HoldAck, Q932Pmes_HoldAck); - Q931SetMesProc(Q932mes_HOLD_REJECT, i, Q932ProcHoldRejectNT, Q932Umes_HoldReject, Q932Pmes_HoldReject); - Q931SetMesProc(Q932mes_REGISTER, i, Q932ProcRegisterNT, Q932Umes_Register, Q932Pmes_Register); - Q931SetMesProc(Q932mes_RETRIEVE, i, Q932ProcRetrieveNT, Q932Umes_Retrieve, Q932Pmes_Retrieve); - Q931SetMesProc(Q932mes_RETRIEVE_ACKNOWLEDGE, i, Q932ProcRetrieveAckNT, Q932Umes_RetrieveAck, Q932Pmes_RetrieveAck); - Q931SetMesProc(Q932mes_RETRIEVE_REJECT, i, Q932ProcRetrieveRejectNT, Q932Umes_RetrieveReject, Q932Pmes_RetrieveReject); - - /* Set up the IE encoder/decoder handle table.*/ - Q931SetIEProc(Q931ie_SEGMENTED_MESSAGE, i, Q931Pie_Segment, Q931Uie_Segment); - Q931SetIEProc(Q931ie_BEARER_CAPABILITY, i, Q931Pie_BearerCap, Q931Uie_BearerCap); - Q931SetIEProc(Q931ie_CAUSE, i, Q931Pie_Cause, Q931Uie_Cause); - Q931SetIEProc(Q931ie_CALL_IDENTITY, i, Q931Pie_CallID, Q931Uie_CallID); - Q931SetIEProc(Q931ie_CALL_STATE, i, Q931Pie_CallState, Q931Uie_CallState); - Q931SetIEProc(Q931ie_CHANNEL_IDENTIFICATION, i, Q931Pie_ChanID, Q931Uie_ChanID); - Q931SetIEProc(Q931ie_PROGRESS_INDICATOR, i, Q931Pie_ProgInd, Q931Uie_ProgInd); - Q931SetIEProc(Q931ie_NETWORK_SPECIFIC_FACILITIES, i, Q931Pie_NetFac, Q931Uie_NetFac); - Q931SetIEProc(Q931ie_NOTIFICATION_INDICATOR, i, Q931Pie_NotifInd, Q931Uie_NotifInd); - Q931SetIEProc(Q931ie_DISPLAY, i, Q931Pie_Display, Q931Uie_Display); - Q931SetIEProc(Q931ie_DATETIME, i, Q931Pie_DateTime, Q931Uie_DateTime); - Q931SetIEProc(Q931ie_KEYPAD_FACILITY, i, Q931Pie_KeypadFac, Q931Uie_KeypadFac); - Q931SetIEProc(Q931ie_SIGNAL, i, Q931Pie_Signal, Q931Uie_Signal); - Q931SetIEProc(Q931ie_TRANSIT_DELAY_SELECTION_AND_IND, i, Q931Pie_TransNetSel, Q931Uie_TransNetSel); - Q931SetIEProc(Q931ie_CALLING_PARTY_NUMBER, i, Q931Pie_CallingNum, Q931Uie_CallingNum); - Q931SetIEProc(Q931ie_CALLING_PARTY_SUBADDRESS, i, Q931Pie_CallingSub, Q931Uie_CallingSub); - Q931SetIEProc(Q931ie_CALLED_PARTY_NUMBER, i, Q931Pie_CalledNum, Q931Uie_CalledNum); - Q931SetIEProc(Q931ie_CALLED_PARTY_SUBADDRESS, i, Q931Pie_CalledSub, Q931Uie_CalledSub); - Q931SetIEProc(Q931ie_TRANSIT_NETWORK_SELECTION, i, Q931Pie_TransNetSel, Q931Uie_TransNetSel); - Q931SetIEProc(Q931ie_RESTART_INDICATOR, i, Q931Pie_RestartInd, Q931Uie_RestartInd); - Q931SetIEProc(Q931ie_LOW_LAYER_COMPATIBILITY, i, Q931Pie_LLComp, Q931Uie_LLComp); - Q931SetIEProc(Q931ie_HIGH_LAYER_COMPATIBILITY, i, Q931Pie_HLComp, Q931Uie_HLComp); - Q931SetIEProc(Q931ie_USER_USER, i, Q931Pie_UserUser, Q931Uie_UserUser); - - Q931SetIEProc(Q931ie_CONNECTED_NUMBER, i, Q931Pie_Generic, Q931Uie_Generic); - Q931SetIEProc(Q931ie_FACILITY, i, Q931Pie_Generic, Q931Uie_Generic); - Q931SetIEProc(Q931ie_REDIRECTING_NUMBER, i, Q931Pie_Generic, Q931Uie_Generic); - - /* The following define a state machine. The point is that the Message - * procs can when search this to find out if the message/state - * combination is legale. If not, the proc for unexpected message apply. - */ - - /* TODO define state table here */ - - /* Timer default values */ - Q931SetTimerDefault(i, Q931_TIMER_T301, 180000); /* T301: 180s */ - Q931SetTimerDefault(i, Q931_TIMER_T302, 15000); /* T302: 15s */ - Q931SetTimerDefault(i, Q931_TIMER_T303, 4000); /* T303: 4s */ - Q931SetTimerDefault(i, Q931_TIMER_T304, 20000); /* T304: 20s */ - Q931SetTimerDefault(i, Q931_TIMER_T305, 30000); /* T305: 30s */ - Q931SetTimerDefault(i, Q931_TIMER_T306, 30000); /* T306: 30s */ - Q931SetTimerDefault(i, Q931_TIMER_T307, 180000); /* T307: 180s */ - Q931SetTimerDefault(i, Q931_TIMER_T308, 4000); /* T308: 4s */ - Q931SetTimerDefault(i, Q931_TIMER_T309, 60000); /* T309: 60s */ - Q931SetTimerDefault(i, Q931_TIMER_T310, 10000); /* T310: 10s */ - Q931SetTimerDefault(i, Q931_TIMER_T312, 12000); /* T312: 12s */ - Q931SetTimerDefault(i, Q931_TIMER_T314, 4000); /* T314: 4s */ - Q931SetTimerDefault(i, Q931_TIMER_T316, 120000); /* T316: 120s */ - Q931SetTimerDefault(i, Q931_TIMER_T317, 90000); /* T317: 90s */ - Q931SetTimerDefault(i, Q931_TIMER_T320, 30000); /* T320: 30s */ - Q931SetTimerDefault(i, Q931_TIMER_T321, 30000); /* T321: 30s */ - Q931SetTimerDefault(i, Q931_TIMER_T322, 4000); /* T322: 4s */ -} - -/***************************************************************************** - - Function: Q931ProcAlertingNT - -*****************************************************************************/ -L3INT Q931ProcAlertingNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* Reset 4 sec timer. */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcCallProceedingNT - -*****************************************************************************/ -L3INT Q931ProcCallProceedingNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcConnectNT - -*****************************************************************************/ -L3INT Q931ProcConnectNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcConnectAckNT - -*****************************************************************************/ -L3INT Q931ProcConnectAckNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcProgressNT - -*****************************************************************************/ -L3INT Q931ProcProgressNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcSetupNT - - Description: Process a SETUP message. - - *****************************************************************************/ -L3INT Q931ProcSetupNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)&buf[Q931L4HeaderSpace]; - L3INT rc = 0; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Reject SETUP on existing calls */ - if (Q931GetCallState(pTrunk, pMes->CRV) != Q931_U0) { - Q931Disconnect(pTrunk, iFrom, pMes->CRV, 81); - return Q931E_UNEXPECTED_MESSAGE; - } - - /* outgoing call */ - if (iFrom == 4) { - ret = Q931CreateCRV(pTrunk, &callIndex); - if (ret) - return ret; - - pMes->CRV = pTrunk->call[callIndex].CRV; - - /* - * Outgoing SETUP message will be broadcasted in PTMP mode - */ - ret = Q931Tx32Data(pTrunk, Q931_IS_PTP(pTrunk) ? 0 : 1, buf, pMes->Size); - if (ret) - return ret; - - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - Q931SetState(pTrunk, callIndex, Q931_U1); - } - /* incoming call */ - else { - /* Locate free CRV entry and store info */ - ret = Q931AllocateCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) { - /* Not possible to allocate CRV entry, so must reject call */ - Q931Disconnect(pTrunk, iFrom, pMes->CRV, 42); - return ret; - } - - /* store TEI in call */ - pTrunk->call[callIndex].Tei = pMes->Tei; - - /* Send setup indication to user */ - ret = Q931Tx34(pTrunk, (L3UCHAR*)pMes, pMes->Size); - if (ret != Q931E_NO_ERROR) { - return ret; - } else { - /* Must be full queue, meaning we can't process the call */ - /* so we must disconnect */ - Q931Disconnect(pTrunk, iFrom, pMes->CRV, 81); - return ret; - } -#if 0 - /* TODO: Unreachable code??? */ - /* Set state U6 */ - Q931SetState(pTrunk, callIndex, Q931_U6); - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); -#endif - } - - return rc; -} - -/***************************************************************************** - - Function: Q931ProcSetupAckNT - - Description: Used to acknowedge a SETUP. Usually the first initial - response recevide back used to buy some time. - - Note that ChanID (B Channel Assignment) might come here from - NT side. - -*****************************************************************************/ -L3INT Q931ProcSetupAckNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcResumeNT - -*****************************************************************************/ -L3INT Q931ProcResumeNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcResumeAckNT - -*****************************************************************************/ -L3INT Q931ProcResumeAckNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcResumeRejectNT - -*****************************************************************************/ -L3INT Q931ProcResumeRejectNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcSuspendNT - -*****************************************************************************/ -L3INT Q931ProcSuspendNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcSuspendAckNT - -*****************************************************************************/ -L3INT Q931ProcSuspendAckNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcSuspendRejectNT - -*****************************************************************************/ -L3INT Q931ProcSuspendRejectNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcInformationNT - -*****************************************************************************/ -L3INT Q931ProcUserInformationNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcDisconnectNT - -*****************************************************************************/ -L3INT Q931ProcDisconnectNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcReleaseNT - -*****************************************************************************/ -L3INT Q931ProcReleaseNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcReleaseCompleteNT - -*****************************************************************************/ -L3INT Q931ProcReleaseCompleteNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcRestartNT - -*****************************************************************************/ -L3INT Q931ProcRestartNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcRestartAckNT - -*****************************************************************************/ -L3INT Q931ProcRestartAckNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcCongestionControlNT - -*****************************************************************************/ -L3INT Q931ProcCongestionControlNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcInformationNT - -*****************************************************************************/ -L3INT Q931ProcInformationNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcNotifyNT - -*****************************************************************************/ -L3INT Q931ProcNotifyNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcStatusNT - -*****************************************************************************/ -L3INT Q931ProcStatusNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcStatusEnquiryNT - -*****************************************************************************/ -L3INT Q931ProcStatusEnquiryNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcSegmentNT - -*****************************************************************************/ -L3INT Q931ProcSegmentNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/****************************************************************************/ -/******************* Q.932 - Supplementary Services *************************/ -/****************************************************************************/ - -/***************************************************************************** - - Function: Q932ProcFacilityNT - -*****************************************************************************/ -L3INT Q932ProcFacilityNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q932ProcHoldNT - -*****************************************************************************/ -L3INT Q932ProcHoldNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q932ProcHoldAckNT - -*****************************************************************************/ -L3INT Q932ProcHoldAckNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q932ProcHoldRejectNT - -*****************************************************************************/ -L3INT Q932ProcHoldRejectNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q932ProcRegisterTE - -*****************************************************************************/ -L3INT Q932ProcRegisterNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q932ProcRetrieveNT - -*****************************************************************************/ -L3INT Q932ProcRetrieveNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcRetrieveAckNT - -*****************************************************************************/ -L3INT Q932ProcRetrieveAckNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcRetrieveRejectNT - -*****************************************************************************/ -L3INT Q932ProcRetrieveRejectNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here*/ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} diff --git a/libs/freetdm/src/isdn/Q931StateTE.c b/libs/freetdm/src/isdn/Q931StateTE.c deleted file mode 100644 index 562dd0b458..0000000000 --- a/libs/freetdm/src/isdn/Q931StateTE.c +++ /dev/null @@ -1,1310 +0,0 @@ -/***************************************************************************** - - FileName: q931StateTE.c - - Contents: Q.931 State Engine for TE (User Mode). - - The controlling state engine for Q.931 is the state engine - on the NT side. The state engine on the TE side is a slave - of this. The TE side maintain it's own states as described in - ITU-T Q931, but will in raise conditions be overridden by - the NT side. - - This reference implementation uses a process per message, - meaning that each message must check call states. This - is easier for dialect maintenance as each message proc - can be replaced individually. A new TE variant only - need to copy the Q931CreateTE and replace those procs or - need to override. - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -#include "Q931.h" - -extern L3INT Q931L4HeaderSpace; - -/***************************************************************************** - Function: Q931CreateTE - - Description: Will create the Q931 TE as a Dialect in the stack. The first - bulk set up the message handlers, the second bulk the IE - encoders/coders, and the last bulk set up the state table. - - Parameters: i Dialect index -*****************************************************************************/ -void Q931CreateTE(L3UCHAR i) -{ - Q931SetMesProc(Q931mes_ALERTING, i, Q931ProcAlertingTE, Q931Umes_Alerting, Q931Pmes_Alerting); - Q931SetMesProc(Q931mes_CALL_PROCEEDING, i, Q931ProcCallProceedingTE, Q931Umes_CallProceeding, Q931Pmes_CallProceeding); - Q931SetMesProc(Q931mes_CONNECT, i, Q931ProcConnectTE, Q931Umes_Connect, Q931Pmes_Connect); - Q931SetMesProc(Q931mes_CONNECT_ACKNOWLEDGE, i, Q931ProcConnectAckTE, Q931Umes_ConnectAck, Q931Pmes_ConnectAck); - Q931SetMesProc(Q931mes_PROGRESS, i, Q931ProcProgressTE, Q931Umes_Progress, Q931Pmes_Progress); - Q931SetMesProc(Q931mes_SETUP, i, Q931ProcSetupTE, Q931Umes_Setup, Q931Pmes_Setup); - Q931SetMesProc(Q931mes_SETUP_ACKNOWLEDGE, i, Q931ProcSetupAckTE, Q931Umes_SetupAck, Q931Pmes_SetupAck); - Q931SetMesProc(Q931mes_RESUME, i, Q931ProcResumeTE, Q931Umes_Resume, Q931Pmes_Resume); - Q931SetMesProc(Q931mes_RESUME_ACKNOWLEDGE, i, Q931ProcResumeAckTE, Q931Umes_ResumeAck, Q931Pmes_ResumeAck); - Q931SetMesProc(Q931mes_RESUME_REJECT, i, Q931ProcResumeRejectTE, Q931Umes_ResumeReject, Q931Pmes_ResumeReject); - Q931SetMesProc(Q931mes_SUSPEND, i, Q931ProcSuspendTE, Q931Umes_Suspend, Q931Pmes_Suspend); - Q931SetMesProc(Q931mes_SUSPEND_ACKNOWLEDGE, i, Q931ProcSuspendAckTE, Q931Umes_SuspendAck, Q931Pmes_SuspendAck); - Q931SetMesProc(Q931mes_SUSPEND_REJECT, i, Q931ProcSuspendRejectTE, Q931Umes_SuspendReject, Q931Pmes_SuspendReject); - Q931SetMesProc(Q931mes_USER_INFORMATION, i, Q931ProcUserInformationTE, Q931Umes_UserInformation, Q931Pmes_UserInformation); - Q931SetMesProc(Q931mes_DISCONNECT, i, Q931ProcDisconnectTE, Q931Umes_Disconnect, Q931Pmes_Disconnect); - Q931SetMesProc(Q931mes_RELEASE, i, Q931ProcReleaseTE, Q931Umes_Release, Q931Pmes_Release); - Q931SetMesProc(Q931mes_RELEASE_COMPLETE, i, Q931ProcReleaseCompleteTE, Q931Umes_ReleaseComplete, Q931Pmes_ReleaseComplete); - Q931SetMesProc(Q931mes_RESTART, i, Q931ProcRestartTE, Q931Umes_Restart, Q931Pmes_Restart); - Q931SetMesProc(Q931mes_RESTART_ACKNOWLEDGE, i, Q931ProcRestartAckTE, Q931Umes_RestartAck, Q931Pmes_RestartAck); - Q931SetMesProc(Q931mes_CONGESTION_CONTROL, i, Q931ProcCongestionControlTE, Q931Umes_CongestionControl, Q931Pmes_CongestionControl); - Q931SetMesProc(Q931mes_INFORMATION, i, Q931ProcInformationTE, Q931Umes_Information, Q931Pmes_Information); - Q931SetMesProc(Q931mes_NOTIFY, i, Q931ProcNotifyTE, Q931Umes_Notify, Q931Pmes_Notify); - Q931SetMesProc(Q931mes_STATUS, i, Q931ProcStatusTE, Q931Umes_Status, Q931Pmes_Status); - Q931SetMesProc(Q931mes_STATUS_ENQUIRY, i, Q931ProcStatusEnquiryTE, Q931Umes_StatusEnquiry, Q931Pmes_StatusEnquiry); - Q931SetMesProc(Q931mes_SEGMENT, i, Q931ProcSegmentTE, Q931Umes_Segment, Q931Pmes_Segment); - - Q931SetMesProc(Q932mes_FACILITY, i, Q932ProcFacilityTE, Q932Umes_Facility, Q932Pmes_Facility); - Q931SetMesProc(Q932mes_HOLD, i, Q932ProcHoldTE, Q932Umes_Hold, Q932Pmes_Hold); - Q931SetMesProc(Q932mes_HOLD_ACKNOWLEDGE, i, Q932ProcHoldAckTE, Q932Umes_HoldAck, Q932Pmes_HoldAck); - Q931SetMesProc(Q932mes_HOLD_REJECT, i, Q932ProcHoldRejectTE, Q932Umes_HoldReject, Q932Pmes_HoldReject); - Q931SetMesProc(Q932mes_REGISTER, i, Q932ProcRegisterTE, Q932Umes_Register, Q932Pmes_Register); - Q931SetMesProc(Q932mes_RETRIEVE, i, Q932ProcRetrieveTE, Q932Umes_Retrieve, Q932Pmes_Retrieve); - Q931SetMesProc(Q932mes_RETRIEVE_ACKNOWLEDGE, i, Q932ProcRetrieveAckTE, Q932Umes_RetrieveAck, Q932Pmes_RetrieveAck); - Q931SetMesProc(Q932mes_RETRIEVE_REJECT, i, Q932ProcRetrieveRejectTE, Q932Umes_RetrieveReject, Q932Pmes_RetrieveReject); - - /* Set up the IE encoder/decoder handle table.*/ - Q931SetIEProc(Q931ie_SEGMENTED_MESSAGE, i, Q931Pie_Segment, Q931Uie_Segment); - Q931SetIEProc(Q931ie_BEARER_CAPABILITY, i, Q931Pie_BearerCap, Q931Uie_BearerCap); - Q931SetIEProc(Q931ie_CAUSE, i, Q931Pie_Cause, Q931Uie_Cause); - Q931SetIEProc(Q931ie_CALL_IDENTITY, i, Q931Pie_CallID, Q931Uie_CallID); - Q931SetIEProc(Q931ie_CALL_STATE, i, Q931Pie_CallState, Q931Uie_CallState); - Q931SetIEProc(Q931ie_CHANNEL_IDENTIFICATION, i, Q931Pie_ChanID, Q931Uie_ChanID); - Q931SetIEProc(Q931ie_PROGRESS_INDICATOR, i, Q931Pie_ProgInd, Q931Uie_ProgInd); - Q931SetIEProc(Q931ie_NETWORK_SPECIFIC_FACILITIES, i, Q931Pie_NetFac, Q931Uie_NetFac); - Q931SetIEProc(Q931ie_NOTIFICATION_INDICATOR, i, Q931Pie_NotifInd, Q931Uie_NotifInd); - Q931SetIEProc(Q931ie_DISPLAY, i, Q931Pie_Display, Q931Uie_Display); - Q931SetIEProc(Q931ie_DATETIME, i, Q931Pie_DateTime, Q931Uie_DateTime); - Q931SetIEProc(Q931ie_KEYPAD_FACILITY, i, Q931Pie_KeypadFac, Q931Uie_KeypadFac); - Q931SetIEProc(Q931ie_SIGNAL, i, Q931Pie_Signal, Q931Uie_Signal); - Q931SetIEProc(Q931ie_TRANSIT_DELAY_SELECTION_AND_IND, i, Q931Pie_TransNetSel, Q931Uie_TransNetSel); - Q931SetIEProc(Q931ie_CALLING_PARTY_NUMBER, i, Q931Pie_CallingNum, Q931Uie_CallingNum); - Q931SetIEProc(Q931ie_CALLING_PARTY_SUBADDRESS, i, Q931Pie_CallingSub, Q931Uie_CallingSub); - Q931SetIEProc(Q931ie_CALLED_PARTY_NUMBER, i, Q931Pie_CalledNum, Q931Uie_CalledNum); - Q931SetIEProc(Q931ie_CALLED_PARTY_SUBADDRESS, i, Q931Pie_CalledSub, Q931Uie_CalledSub); - Q931SetIEProc(Q931ie_TRANSIT_NETWORK_SELECTION, i, Q931Pie_TransNetSel, Q931Uie_TransNetSel); - Q931SetIEProc(Q931ie_RESTART_INDICATOR, i, Q931Pie_RestartInd, Q931Uie_RestartInd); - Q931SetIEProc(Q931ie_LOW_LAYER_COMPATIBILITY, i, Q931Pie_LLComp, Q931Uie_LLComp); - Q931SetIEProc(Q931ie_HIGH_LAYER_COMPATIBILITY, i, Q931Pie_HLComp, Q931Uie_HLComp); - Q931SetIEProc(Q931ie_USER_USER, i, Q931Pie_UserUser, Q931Uie_UserUser); - - Q931SetIEProc(Q931ie_CONNECTED_NUMBER, i, Q931Pie_Generic, Q931Uie_Generic); - Q931SetIEProc(Q931ie_FACILITY, i, Q931Pie_Generic, Q931Uie_Generic); - Q931SetIEProc(Q931ie_REDIRECTING_NUMBER, i, Q931Pie_Generic, Q931Uie_Generic); - - /* The following define a state machine. The point is that the Message - * procs can when search this to find out if the message/state - * combination is legale. If not, the proc for unexpected message apply. - */ - - /* State 0 Idle */ - Q931AddStateEntry(i, Q931_U0, Q931mes_RESUME, 2); - Q931AddStateEntry(i, Q931_U0, Q931mes_SETUP, 4); - Q931AddStateEntry(i, Q931_U0, Q931mes_SETUP, 2); - Q931AddStateEntry(i, Q931_U0, Q931mes_STATUS, 4); - Q931AddStateEntry(i, Q931_U0, Q931mes_RELEASE, 4); - Q931AddStateEntry(i, Q931_U0, Q931mes_RELEASE_COMPLETE, 4); - - /* State 1 Call Initiating */ - Q931AddStateEntry(i, Q931_U1, Q931mes_DISCONNECT, 2); - Q931AddStateEntry(i, Q931_U1, Q931mes_SETUP_ACKNOWLEDGE, 4); - Q931AddStateEntry(i, Q931_U1, Q931mes_RELEASE_COMPLETE, 4); - Q931AddStateEntry(i, Q931_U1, Q931mes_CALL_PROCEEDING, 4); - Q931AddStateEntry(i, Q931_U1, Q931mes_ALERTING, 4); - Q931AddStateEntry(i, Q931_U1, Q931mes_CONNECT, 4); - - /* State 2 Overlap Sending */ - Q931AddStateEntry(i, Q931_U2, Q931mes_INFORMATION, 2); - Q931AddStateEntry(i, Q931_U2, Q931mes_CALL_PROCEEDING, 4); - Q931AddStateEntry(i, Q931_U2, Q931mes_ALERTING, 4); - Q931AddStateEntry(i, Q931_U2, Q931mes_PROGRESS, 4); - Q931AddStateEntry(i, Q931_U2, Q931mes_CONNECT, 4); - Q931AddStateEntry(i, Q931_U2, Q931mes_RELEASE, 2); - - /* State 3 Outgoing Call Proceeding */ - Q931AddStateEntry(i, Q931_U3, Q931mes_PROGRESS, 4); - Q931AddStateEntry(i, Q931_U3, Q931mes_ALERTING, 4); - Q931AddStateEntry(i, Q931_U3, Q931mes_CONNECT, 4); - Q931AddStateEntry(i, Q931_U3, Q931mes_RELEASE, 2); - - /* State 4 Call Delivered */ - Q931AddStateEntry(i, Q931_U4, Q931mes_CONNECT, 4); - - /* State 6 Call Precent */ - Q931AddStateEntry(i, Q931_U6, Q931mes_INFORMATION, 2); - Q931AddStateEntry(i, Q931_U6, Q931mes_ALERTING, 2); - Q931AddStateEntry(i, Q931_U6, Q931mes_CALL_PROCEEDING, 2); - Q931AddStateEntry(i, Q931_U6, Q931mes_CONNECT, 2); - Q931AddStateEntry(i, Q931_U6, Q931mes_RELEASE_COMPLETE, 2); - Q931AddStateEntry(i, Q931_U6, Q931mes_RELEASE, 4); - Q931AddStateEntry(i, Q931_U6, Q931mes_DISCONNECT, 4); - - /* State 7 Call Received */ - Q931AddStateEntry(i, Q931_U7, Q931mes_CONNECT, 2); - - /* State 8 Connect request */ - Q931AddStateEntry(i, Q931_U8, Q931mes_CONNECT_ACKNOWLEDGE, 4); - - /* State 9 Incoming Call Proceeding */ - Q931AddStateEntry(i, Q931_U9, Q931mes_CONNECT, 2); - Q931AddStateEntry(i, Q931_U9, Q931mes_ALERTING, 2); - Q931AddStateEntry(i, Q931_U9, Q931mes_PROGRESS, 2); - - /* State 10 Active */ - Q931AddStateEntry(i, Q931_U10, Q931mes_SUSPEND, 2); - Q931AddStateEntry(i, Q931_U10, Q931mes_NOTIFY, 4); - Q931AddStateEntry(i, Q931_U10, Q931mes_NOTIFY, 2); - - /* State 11 Disconnect Request */ - Q931AddStateEntry(i, Q931_U11, Q931mes_RELEASE, 4); - Q931AddStateEntry(i, Q931_U11, Q931mes_DISCONNECT, 4); - Q931AddStateEntry(i, Q931_U11, Q931mes_NOTIFY, 4); - - /* State 12 Disconnect Ind */ - Q931AddStateEntry(i, Q931_U12, Q931mes_RELEASE, 4); - Q931AddStateEntry(i, Q931_U12, Q931mes_RELEASE, 2); - - /* State 15 Suspend Request */ - Q931AddStateEntry(i, Q931_U15, Q931mes_SUSPEND_ACKNOWLEDGE, 4); - Q931AddStateEntry(i, Q931_U15, Q931mes_SUSPEND_REJECT, 4); - Q931AddStateEntry(i, Q931_U15, Q931mes_DISCONNECT, 4); - Q931AddStateEntry(i, Q931_U15, Q931mes_RELEASE, 4); - -/* TODO - Q931AddStateEntry(i, Q931_U17, - Q931AddStateEntry(i, Q931_U19, - Q931AddStateEntry(i, Q931_U25, -*/ - - /* Timer default values */ - Q931SetTimerDefault(i, Q931_TIMER_T301, 180000); /* T301: 180s */ - Q931SetTimerDefault(i, Q931_TIMER_T302, 15000); /* T302: 15s */ - Q931SetTimerDefault(i, Q931_TIMER_T303, 4000); /* T303: 4s */ - Q931SetTimerDefault(i, Q931_TIMER_T304, 30000); /* T304: 30s */ - Q931SetTimerDefault(i, Q931_TIMER_T305, 30000); /* T305: 30s */ - Q931SetTimerDefault(i, Q931_TIMER_T308, 4000); /* T308: 4s */ - Q931SetTimerDefault(i, Q931_TIMER_T309, 60000); /* T309: 60s */ - Q931SetTimerDefault(i, Q931_TIMER_T310, 60000); /* T310: 60s */ - Q931SetTimerDefault(i, Q931_TIMER_T313, 4000); /* T313: 4s */ - Q931SetTimerDefault(i, Q931_TIMER_T314, 4000); /* T314: 4s */ - Q931SetTimerDefault(i, Q931_TIMER_T316, 120000); /* T316: 120s */ - Q931SetTimerDefault(i, Q931_TIMER_T317, 90000); /* T317: 90s */ - Q931SetTimerDefault(i, Q931_TIMER_T318, 4000); /* T318: 4s */ - Q931SetTimerDefault(i, Q931_TIMER_T319, 4000); /* T319: 4s */ - Q931SetTimerDefault(i, Q931_TIMER_T321, 30000); /* T321: 30s */ - Q931SetTimerDefault(i, Q931_TIMER_T322, 4000); /* T322: 4s */ -} - -/***************************************************************************** - - Function: Q931ProcAlertingTE - -*****************************************************************************/ -L3INT Q931ProcAlertingTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* Reset 4 sec timer. */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcCallProceedingTE - -*****************************************************************************/ -L3INT Q931ProcCallProceedingTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcConnectTE - -*****************************************************************************/ -L3INT Q931ProcConnectTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - if (pTrunk->autoConnectAck) { - Q931AckConnect(pTrunk, buf); - } - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcConnectAckTE - -*****************************************************************************/ -L3INT Q931ProcConnectAckTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcProgressTE - -*****************************************************************************/ -L3INT Q931ProcProgressTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcSetupTE - -*****************************************************************************/ -L3INT Q931ProcSetupTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)&buf[Q931L4HeaderSpace]; - L3INT rc = 0; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Reject SETUP on existing calls */ - if (Q931GetCallState(pTrunk, pMes->CRV) != Q931_U0) { - Q931Disconnect(pTrunk, iFrom, pMes->CRV, 81); - return Q931E_UNEXPECTED_MESSAGE; - } - - /* outgoing call */ - if (iFrom == 4) { - ret = Q931CreateCRV(pTrunk, &callIndex); - if (ret) - return ret; - pMes->CRV = pTrunk->call[callIndex].CRV; - - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - if (ret) - return ret; - - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - - /* TODO: Add this back when we get the state stuff more filled out */ - /*Q931SetState(pTrunk, callIndex, Q931_U1);*/ - } - /* incoming call */ - else { - /* Locate free CRV entry and store info */ - ret = Q931AllocateCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) { - /* Not possible to allocate CRV entry, so must reject call */ - Q931Disconnect(pTrunk, iFrom, pMes->CRV, 42); - return ret; - } - - /* Send setup indication to user */ - ret = Q931Tx34(pTrunk, (L3UCHAR*)pMes, pMes->Size); - if (ret != Q931E_NO_ERROR) { - if (pTrunk->autoSetupAck) { - Q931AckSetup(pTrunk, buf); - } - return ret; - } else { - /* Must be full queue, meaning we can't process the call */ - /* so we must disconnect */ - Q931Disconnect(pTrunk, iFrom, pMes->CRV, 81); - return ret; - } -#if 0 - /* TODO: Unreachable code??? */ - /* Set state U6 */ - Q931SetState(pTrunk, callIndex, Q931_U6); - - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); -#endif - } - return rc; -} - -/***************************************************************************** - - Function: Q931ProcSetupAckTE - - Description: Used to acknowedge a SETUP. Usually the first initial - response recevide back used to buy some time. L4 sending this - should only be passed on. L2 sending this means that we set - a new timer (and pass it to L4). - - Note that ChanID (B Channel Assignment) might come here from - NT side. - -*****************************************************************************/ -L3INT Q931ProcSetupAckTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcResumeTE - -*****************************************************************************/ -L3INT Q931ProcResumeTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Generic * pMes = (Q931mes_Generic *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - if (Q931GetCallState(pTrunk, pMes->CRV) == Q931_U0 && iFrom ==4) { - /* Call reference selection */ - ret = Q931CreateCRV(pTrunk, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - pMes->CRV = pTrunk->call[callIndex].CRV; - - /* Send RESUME to network */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - if (ret != Q931E_NO_ERROR) - return ret; - - /* Start timer T318 */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T318); - - /* set state U17 */ - Q931SetState(pTrunk, callIndex, Q931_U17); - } else { - return Q931E_ILLEGAL_MESSAGE; - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcResumeAckTE - -*****************************************************************************/ -L3INT Q931ProcResumeAckTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcResumeRejectTE - -*****************************************************************************/ -L3INT Q931ProcResumeRejectTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcSuspendTE - -*****************************************************************************/ -L3INT Q931ProcSuspendTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcSuspendAckTE - -*****************************************************************************/ -L3INT Q931ProcSuspendAckTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcSuspendRejectTE - -*****************************************************************************/ -L3INT Q931ProcSuspendRejectTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcInformationTE - -*****************************************************************************/ -L3INT Q931ProcUserInformationTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcDisconnectTE - -*****************************************************************************/ -L3INT Q931ProcDisconnectTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - Q931Log(pTrunk, Q931_LOG_DEBUG, "Processing DISCONNECT message from %s for CRV: %d (%#hx)\n", - iFrom == 4 ? "Local" : "Remote", pMes->CRV, pMes->CRV); - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcReleaseTE - -*****************************************************************************/ -L3INT Q931ProcReleaseTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT state = Q931GetCallState(pTrunk, pMes->CRV); - L3INT ret = Q931E_NO_ERROR; - - if (iFrom == 4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (state == Q931_U0 && iFrom == 2) { - Q931Tx34(pTrunk, buf, pMes->Size); - ret = Q931ReleaseComplete(pTrunk, buf); - } else { - ret = Q931ProcUnexpectedMessage(pTrunk, buf, iFrom); - } - if (pMes->CRV && iFrom == 2) { - /* Find the call using CRV */ - if ((Q931FindCRV(pTrunk, pMes->CRV, &callIndex)) != Q931E_NO_ERROR) - return ret; - pTrunk->call[callIndex].InUse = 0; - } - - return ret; -} - -/***************************************************************************** - - Function: Q931ProcReleaseCompleteTE - -*****************************************************************************/ -L3INT Q931ProcReleaseCompleteTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } else { - if (pMes->CRV) { - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - pTrunk->call[callIndex].InUse = 0; - - /* TODO: experimental, send RELEASE_COMPLETE message */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcRestartTE - -*****************************************************************************/ -L3INT Q931ProcRestartTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - if (pMes->CRV) { - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - } - - /* TODO chack against state table for illegal or unexpected message here */ - - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - - if (pTrunk->autoRestartAck) { - Q931AckRestart(pTrunk, buf); - } - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcRestartAckTE - -*****************************************************************************/ -L3INT Q931ProcRestartAckTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - if (pMes->CRV) { - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - } - - /* TODO chack against state table for illegal or unexpected message here */ - - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcCongestionControlTE - -*****************************************************************************/ -L3INT Q931ProcCongestionControlTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcInformationTE - -*****************************************************************************/ -L3INT Q931ProcInformationTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcNotifyTE - -*****************************************************************************/ -L3INT Q931ProcNotifyTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcStatusTE - -*****************************************************************************/ -L3INT Q931ProcStatusTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcStatusEnquiryTE - -*****************************************************************************/ -L3INT Q931ProcStatusEnquiryTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcSegmentTE - -*****************************************************************************/ -L3INT Q931ProcSegmentTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/****************************************************************************/ -/******************* Q.932 - Supplementary Services *************************/ -/****************************************************************************/ - -/***************************************************************************** - - Function: Q932ProcRetrieveTE - -*****************************************************************************/ -L3INT Q932ProcFacilityTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q932ProcRetrieveTE - -*****************************************************************************/ -L3INT Q932ProcHoldTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q932ProcRetrieveTE - -*****************************************************************************/ -L3INT Q932ProcHoldAckTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q932ProcRetrieveTE - -*****************************************************************************/ -L3INT Q932ProcHoldRejectTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q932ProcRegisterTE - -*****************************************************************************/ -L3INT Q932ProcRegisterTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q932ProcRetrieveTE - -*****************************************************************************/ -L3INT Q932ProcRetrieveTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcRetrieveAckTE - -*****************************************************************************/ -L3INT Q932ProcRetrieveAckTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} - -/***************************************************************************** - - Function: Q931ProcRetrieveRejectTE - -*****************************************************************************/ -L3INT Q932ProcRetrieveRejectTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom) -{ - Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace]; - L3INT callIndex; - L3INT ret = Q931E_NO_ERROR; - - /* Find the call using CRV */ - ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex); - if (ret != Q931E_NO_ERROR) - return ret; - - /* TODO chack against state table for illegal or unexpected message here */ - - /* TODO - Set correct timer here */ - Q931StartTimer(pTrunk, callIndex, Q931_TIMER_T303); - if (iFrom ==4) { - /* TODO Add proc here */ - ret = Q931Tx32Data(pTrunk, 0, buf, pMes->Size); - } - else if (iFrom == 2) { - /* TODO Add proc here */ - ret = Q931Tx34(pTrunk, buf, pMes->Size); - } - return ret; -} diff --git a/libs/freetdm/src/isdn/Q931api.c b/libs/freetdm/src/isdn/Q931api.c deleted file mode 100644 index ed0d13836b..0000000000 --- a/libs/freetdm/src/isdn/Q931api.c +++ /dev/null @@ -1,598 +0,0 @@ -/***************************************************************************** - - FileName: Q931api.c - - Contents: api (Application Programming Interface) functions. - See q931.h for description. - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -#include "Q931.h" -#include "memory.h" - -extern L3INT Q931L4HeaderSpace; - -/* -L3INT Q931CreateMesIndex(L3INT mc) -{ - if(mc < 0 || mc > 127 ) - return Q931E_INTERNAL; - - if(Q931MesCount >127) - return Q931E_INTERNAL; - - Q931MesIndex[mc] = Q931MesCount ++; - - return Q931E_NO_ERROR; -} -*/ -/* -L3INT Q931CreateIEIndex(L3INT iec) -{ - if(iec < 0 || iec > 127 ) - return Q931E_INTERNAL; - - if(Q931IECount > 127) - return Q931E_INTERNAL; - - Q931IEIndex[iec] = Q931IECount ++; - - return Q931E_NO_ERROR; -} -*/ - -L3INT Q931Api_InitTrunk(Q931_TrunkInfo_t *pTrunk, - Q931Dialect_t Dialect, - Q931NetUser_t NetUser, - Q931_TrunkType_t TrunkType, - Q931Tx34CB_t Q931Tx34CBProc, - Q931Tx32CB_t Q931Tx32CBProc, - Q931ErrorCB_t Q931ErrorCBProc, - void *PrivateData32, - void *PrivateData34) -{ - int y, dchannel, maxchans, has_sync = 0; - - switch(TrunkType) - { - case Q931_TrType_E1: - dchannel = 16; - maxchans = 31; - has_sync = 1; - break; - - case Q931_TrType_T1: - case Q931_TrType_J1: - dchannel = 24; - maxchans = 24; - break; - - case Q931_TrType_BRI: - case Q931_TrType_BRI_PTMP: - dchannel = 3; - maxchans = 3; - break; - - default: - return 0; - } - - pTrunk->Q931Tx34CBProc = Q931Tx34CBProc; - pTrunk->Q931Tx32CBProc = Q931Tx32CBProc; - pTrunk->Q931ErrorCBProc = Q931ErrorCBProc; - pTrunk->PrivateData32 = PrivateData32; - pTrunk->PrivateData34 = PrivateData34; - - pTrunk->LastCRV = 0; - pTrunk->Dialect = Dialect + NetUser; - pTrunk->Enabled = 0; - pTrunk->TrunkType = TrunkType; - pTrunk->NetUser = NetUser; - pTrunk->TrunkState = 0; - pTrunk->autoRestartAck = 0; - for(y=0; y < Q931MAXCHPERTRUNK; y++) - { - pTrunk->ch[y].Available = 1; - - if(has_sync && y == 0) - { - pTrunk->ch[y].ChanType = Q931_ChType_Sync; - } - else if(y == dchannel) - { - pTrunk->ch[y].ChanType = Q931_ChType_D; - } - else if(y > maxchans) - { - pTrunk->ch[y].ChanType = Q931_ChType_NotUsed; - } - else - { - pTrunk->ch[y].ChanType = Q931_ChType_B; - } - } - - for(y=0; y < Q931MAXCALLPERTRUNK; y++) - { - pTrunk->call[y].InUse = 0; - - } - return 1; -} - -void Q931SetMesProc(L3UCHAR mes, L3UCHAR dialect, q931proc_func_t *Q931ProcFunc, q931umes_func_t *Q931UmesFunc, q931pmes_func_t *Q931PmesFunc) -{ - if(Q931ProcFunc != NULL) - Q931Proc[dialect][mes] = Q931ProcFunc; - if(Q931UmesFunc != NULL) - Q931Umes[dialect][mes] = Q931UmesFunc; - if(Q931PmesFunc != NULL) - Q931Pmes[dialect][mes] = Q931PmesFunc; -} - -void Q931SetIEProc(L3UCHAR iec, L3UCHAR dialect, q931pie_func_t *Q931PieProc, q931uie_func_t *Q931UieProc) -{ - if(Q931PieProc != NULL) - Q931Pie[dialect][iec] = Q931PieProc; - if(Q931UieProc != NULL) - Q931Uie[dialect][iec] = Q931UieProc; -} - -void Q931SetTimeoutProc(L3UCHAR dialect, L3UCHAR timer, q931timeout_func_t *Q931TimeoutProc) -{ - if(Q931Timeout != NULL) - Q931Timeout[dialect][timer] = Q931TimeoutProc; -} - -void Q931SetTimerDefault(L3UCHAR dialect, L3UCHAR timer, q931timer_t timeout) -{ - Q931Timer[dialect][timer] = timeout; -} - -L3INT Q931GetMesSize(Q931mes_Generic *pMes) -{ - - L3UCHAR *p = &pMes->buf[0]; - L3INT Size = (L3INT)(p - (L3UCHAR *)pMes); - return Size; -} - -/***************************************************************************** - - Function: q931AppendIE - - Description: Append IE to the message. - - Parameters: pm Ptr to message. - pi Ptr to information element - - Return Value ie setting - -*****************************************************************************/ - -ie Q931AppendIE( L3UCHAR *pm, L3UCHAR *pi) -{ - ie IE = 0; - Q931mes_Generic * pMes= (Q931mes_Generic *)pm; - Q931ie_BearerCap * pIE= (Q931ie_BearerCap *)pi; - L3INT iISize = pIE->Size; - - L3UCHAR *pBuf = &pMes->buf[0]; - L3INT Off = (L3INT)(pMes->Size - (pBuf - pm)); - IE = (ie)(Off | 0x8000); - - memcpy(&pm[pMes->Size], pi, iISize); - - pMes->Size += iISize; - - return IE; -} - -/***************************************************************************** -*****************************************************************************/ -static L3INT crv={1}; - -L3INT Q931GetUniqueCRV(Q931_TrunkInfo_t *pTrunk) -{ - L3INT max = (Q931_IS_BRI(pTrunk)) ? Q931_BRI_MAX_CRV : Q931_PRI_MAX_CRV; - - crv++; - crv = (crv <= max) ? crv : 1; - - return crv; -} - -L3INT Q931InitMesGeneric(Q931mes_Generic *pMes) -{ - memset(pMes, 0, sizeof(*pMes)); - pMes->ProtDisc = 0x08; - pMes->Size = Q931GetMesSize(pMes); - - return 0; -} - -L3INT Q931InitMesResume(Q931mes_Generic * pMes) -{ - pMes->ProtDisc = 0x08; - pMes->CRV = 0; /* CRV to be allocated, might be receive*/ - pMes->MesType = Q931mes_RESUME; - - pMes->Size = Q931GetMesSize(pMes); - pMes->CallID = 0; /* Channel Identification */ - return 0; -} - -L3INT Q931InitMesRestartAck(Q931mes_Generic * pMes) -{ - pMes->ProtDisc = 0x08; - pMes->CRV = 0; /* CRV to be allocated, might be receive*/ - pMes->MesType = Q931mes_RESTART_ACKNOWLEDGE; - - pMes->Size = Q931GetMesSize(pMes); - pMes->ChanID = 0; /* Channel Identification */ - pMes->Display = 0; - pMes->RestartInd = 0; - pMes->RestartWin = 0; - return 0; -} - -L3INT Q931InitIEBearerCap(Q931ie_BearerCap *pIE) -{ - pIE->IEId = Q931ie_BEARER_CAPABILITY; - pIE->Size = sizeof(Q931ie_BearerCap); - pIE->CodStand = 0; - pIE->ITC = 0; - pIE->TransMode = 0; - pIE->ITR = 0x10; - pIE->RateMul = 0; - - pIE->Layer1Ident = 0; - pIE->UIL1Prot = 0; /* User Information Layer 1 Protocol */ - pIE->SyncAsync = 0; /* Sync/Async */ - pIE->Negot = 0; - pIE->UserRate = 0; - pIE->InterRate = 0; /* Intermediate Rate */ - pIE->NIConTx = 0; - pIE->NIConRx = 0; - pIE->FlowCtlTx = 0; /* Flow control on Tx */ - pIE->FlowCtlRx = 0; /* Flow control on Rx */ - pIE->HDR = 0; - pIE->MultiFrame = 0; /* Multi frame support */ - pIE->Mode = 0; - pIE->LLInegot = 0; - pIE->Assignor = 0; /* Assignor/assignee */ - pIE->InBandNeg = 0; /* In-band/out-band negot. */ - pIE->NumStopBits = 0; /* Number of stop bits */ - pIE->NumDataBits = 0; /* Number of data bits. */ - pIE->Parity = 0; - pIE->DuplexMode = 0; - pIE->ModemType = 0; - pIE->Layer2Ident = 0; - pIE->UIL2Prot = 0; /* User Information Layer 2 Protocol */ - pIE->Layer3Ident = 0; - pIE->UIL3Prot = 0; /* User Information Layer 3 Protocol */ - pIE->AL3Info1 = 0; - pIE->AL3Info2 = 0; - - return 0; -} - -L3INT Q931InitIEChanID(Q931ie_ChanID *pIE) -{ - pIE->IEId = Q931ie_CHANNEL_IDENTIFICATION; - pIE->Size = sizeof(Q931ie_ChanID); - pIE->IntIDPresent = 0; /* Int. id. present */ - pIE->IntType = 0; /* Int. type */ - pIE->PrefExcl = 0; /* Pref./Excl. */ - pIE->DChanInd = 0; /* D-channel ind. */ - pIE->InfoChanSel = 0; /* Info. channel selection */ - pIE->InterfaceID = 0; /* Interface identifier */ - pIE->CodStand = 0; /* Code standard */ - pIE->NumMap = 0; /* Number/Map */ - pIE->ChanMapType = 0; /* Channel type/Map element type */ - pIE->ChanSlot = 0; /* Channel number/Slot map */ - - return 0; -} - -L3INT Q931InitIEProgInd(Q931ie_ProgInd * pIE) -{ - pIE->IEId = Q931ie_PROGRESS_INDICATOR; - pIE->Size = sizeof(Q931ie_ProgInd); - pIE->CodStand = 0; /* Coding standard */ - pIE->Location = 0; /* Location */ - pIE->ProgDesc = 0; /* Progress description */ - - return 0; -} - -L3INT Q931InitIENetFac(Q931ie_NetFac * pIE) -{ - pIE->IEId = Q931ie_NETWORK_SPECIFIC_FACILITIES; - pIE->Size = sizeof(Q931ie_NetFac); - pIE->LenNetID = 0; /* Length of network facilities id. */ - pIE->TypeNetID = 0; /* Type of network identification */ - pIE->NetIDPlan = 0; /* Network identification plan. */ - pIE->NetFac = 0; /* Network specific facility spec. */ - pIE->NetID[0] = 0; - return 0; -} - -L3INT Q931InitIEDisplay(Q931ie_Display * pIE) -{ - pIE->IEId = Q931ie_DISPLAY; - pIE->Size = sizeof(Q931ie_Display); - pIE->Display[0] = 0; - return 0; -} - -L3INT Q931InitIEDateTime(Q931ie_DateTime * pIE) -{ - pIE->IEId = Q931ie_DATETIME; - pIE->Size = sizeof(Q931ie_DateTime); - pIE->Year = 0; /* Year */ - pIE->Month = 0; /* Month */ - pIE->Day = 0; /* Day */ - pIE->Hour = 0; /* Hour */ - pIE->Minute = 0; /* Minute */ - pIE->Second = 0; /* Second */ - - return 0; -} - -L3INT Q931InitIEKeypadFac(Q931ie_KeypadFac * pIE) -{ - pIE->IEId = Q931ie_KEYPAD_FACILITY; - pIE->Size = sizeof(Q931ie_KeypadFac); - pIE->KeypadFac[0] = 0; - return 0; -} - -L3INT Q931InitIESignal(Q931ie_Signal * pIE) -{ - pIE->IEId = Q931ie_SIGNAL; - pIE->Size = sizeof(Q931ie_Signal); - pIE->Signal = 0; - return 0; -} - -L3INT Q931InitIECallingNum(Q931ie_CallingNum * pIE) -{ - pIE->IEId = Q931ie_CALLING_PARTY_NUMBER; - pIE->Size = sizeof(Q931ie_CallingNum); - pIE->TypNum = 0; /* Type of number */ - pIE->NumPlanID = 0; /* Numbering plan identification */ - pIE->PresInd = 0; /* Presentation indicator */ - pIE->ScreenInd = 0; /* Screening indicator */ - pIE->Digit[0] = 0; /* Number digits (IA5) */ - - return 0; -} - -L3INT Q931InitIECallingSub(Q931ie_CallingSub * pIE) -{ - pIE->IEId = Q931ie_CALLING_PARTY_SUBADDRESS; - pIE->Size = sizeof(Q931ie_CallingSub); - pIE->TypNum = 0; /* Type of subaddress */ - pIE->OddEvenInd = 0; /* Odd/Even indicator */ - pIE->Digit[0] = 0; /* Digits */ - - return 0; -} - -L3INT Q931InitIECalledNum(Q931ie_CalledNum * pIE) -{ - pIE->IEId = Q931ie_CALLED_PARTY_NUMBER; - pIE->Size = sizeof(Q931ie_CalledNum); - pIE->TypNum = 0; /* Type of Number */ - pIE->NumPlanID = 0; /* Numbering plan identification */ - pIE->Digit[0] = 0; /* Digit (IA5) */ - - return 0; -} - -L3INT Q931InitIECalledSub(Q931ie_CalledSub * pIE) -{ - pIE->IEId = Q931ie_CALLED_PARTY_SUBADDRESS; - pIE->Size = sizeof(Q931ie_CalledSub); - pIE->TypNum = 0; /* Type of subaddress */ - pIE->OddEvenInd = 0; /* Odd/Even indicator */ - pIE->Digit[0] = 0; /* Digits */ - - return 0; -} - -L3INT Q931InitIETransNetSel(Q931ie_TransNetSel * pIE) -{ - pIE->IEId = Q931ie_TRANSIT_NETWORK_SELECTION; - pIE->Size = sizeof(Q931ie_TransNetSel); - pIE->Type = 0; /* Type of network identifier */ - pIE->NetIDPlan = 0; /* Network idetification plan */ - pIE->NetID[0] = 0; /* Network identification(IA5) */ - - return 0; -} - -L3INT Q931InitIELLComp(Q931ie_LLComp * pIE) -{ - pIE->IEId = Q931ie_LOW_LAYER_COMPATIBILITY; - pIE->Size = sizeof(Q931ie_LLComp); - - pIE->CodStand = 0; /* Coding standard */ - pIE->ITransCap = 0; /* Information transfer capability */ - pIE->NegotInd = 0; /* Negot indic. */ - pIE->TransMode = 0; /* Transfer Mode */ - pIE->InfoRate = 0; /* Information transfer rate */ - pIE->RateMul = 0; /* Rate multiplier */ - pIE->Layer1Ident = 0; /* Layer 1 ident. */ - pIE->UIL1Prot = 0; /* User information layer 1 protocol */ - pIE->SyncAsync = 0; /* Synch/asynch */ - pIE->Negot = 0; /* Negot */ - pIE->UserRate = 0; /* User rate */ - pIE->InterRate = 0; /* Intermediate rate */ - pIE->NIConTx = 0; /* NIC on Tx */ - pIE->NIConRx = 0; /* NIC on Rx */ - pIE->FlowCtlTx = 0; /* Flow control on Tx */ - pIE->FlowCtlRx = 0; /* Flow control on Rx */ - pIE->HDR = 0; /* Hdr/no hdr */ - pIE->MultiFrame = 0; /* Multiframe */ - pIE->ModeL1 = 0; /* Mode L1 */ - pIE->NegotLLI = 0; /* Negot. LLI */ - pIE->Assignor = 0; /* Assignor/Assignor ee */ - pIE->InBandNeg = 0; /* In-band negot. */ - pIE->NumStopBits = 0; /* Number of stop bits */ - pIE->NumDataBits = 0; /* Number of data bits */ - pIE->Parity = 0; /* Parity */ - pIE->DuplexMode = 0; /* Duplex Mode */ - pIE->ModemType = 0; /* Modem type */ - pIE->Layer2Ident = 0; /* Layer 2 ident. */ - pIE->UIL2Prot = 0; /* User information layer 2 protocol */ - pIE->ModeL2 = 0; /* ModeL2 */ - pIE->Q933use = 0; /* Q.9333 use */ - pIE->UsrSpcL2Prot = 0; /* User specified layer 2 protocol info */ - pIE->WindowSize = 0; /* Window size (k) */ - pIE->Layer3Ident = 0; /* Layer 3 ident */ - pIE->OptL3Info = 0; /* Optional layer 3 protocol info. */ - pIE->ModeL3 = 0; /* Mode of operation */ -#if 0 - pIE->ModeX25op = 0; /* Mode of operation X.25 */ -#endif - pIE->DefPackSize = 0; /* Default packet size */ - pIE->PackWinSize = 0; /* Packet window size */ - pIE->AddL3Info = 0; /* Additional Layer 3 protocol info */ - - return 0; -} - -L3INT Q931InitIEHLComp(Q931ie_HLComp * pIE) -{ - pIE->IEId = Q931ie_HIGH_LAYER_COMPATIBILITY; - pIE->Size = sizeof(Q931ie_HLComp); - - return 0; -} - -L3INT Q931ProcUnknownMessage(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom) -{ - /* TODO: Unhandled paramaters */ - (void)pTrunk; - (void)b; - (void)iFrom; - - return 0; -} - -L3INT Q931ProcUnexpectedMessage(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom) -{ - /* TODO: Unhandled paramaters */ - (void)pTrunk; - (void)b; - (void)iFrom; - - return 0; -} - -L3INT Q931Disconnect(Q931_TrunkInfo_t *pTrunk, L3INT iTo, L3INT iCRV, L3INT iCause) -{ - /* TODO: Unhandled paramaters */ - (void)pTrunk; - (void)iTo; - (void)iCRV; - (void)iCause; - - return 0; -} - -L3INT Q931ReleaseComplete(Q931_TrunkInfo_t *pTrunk, L3UCHAR *buf) -{ - Q931mes_Header *ptr = (Q931mes_Header*)&buf[Q931L4HeaderSpace]; - ptr->MesType = Q931mes_RELEASE_COMPLETE; - ptr->CRVFlag = !(ptr->CRVFlag); - return Q931Tx32Data(pTrunk,0,buf,ptr->Size); -} - -L3INT Q931AckRestart(Q931_TrunkInfo_t *pTrunk, L3UCHAR *buf) -{ - L3INT RetCode; - - Q931mes_Header *ptr = (Q931mes_Header*)&buf[Q931L4HeaderSpace]; - ptr->MesType = Q931mes_RESTART_ACKNOWLEDGE; - //if (ptr->CRV) { - ptr->CRVFlag = !(ptr->CRVFlag); - //} - - RetCode = Q931Proc[pTrunk->Dialect][ptr->MesType](pTrunk, buf, 4); - - return RetCode; -} - -L3INT Q931AckSetup(Q931_TrunkInfo_t *pTrunk, L3UCHAR *buf) -{ - L3INT RetCode; - - Q931mes_Header *ptr = (Q931mes_Header*)&buf[Q931L4HeaderSpace]; - ptr->MesType = Q931mes_SETUP_ACKNOWLEDGE; - - RetCode = Q931Proc[pTrunk->Dialect][ptr->MesType](pTrunk, buf, 4); - - return RetCode; -} - -L3INT Q931AckConnect(Q931_TrunkInfo_t *pTrunk, L3UCHAR *buf) -{ - L3INT RetCode; - - Q931mes_Header *ptr = (Q931mes_Header*)&buf[Q931L4HeaderSpace]; - ptr->MesType = Q931mes_CONNECT_ACKNOWLEDGE; - - RetCode = Q931Proc[pTrunk->Dialect][ptr->MesType](pTrunk, buf, 4); - - return RetCode; -} - -L3INT Q931AckService(Q931_TrunkInfo_t *pTrunk, L3UCHAR *buf) -{ - L3INT RetCode; - - Q931mes_Header *ptr = (Q931mes_Header*)&buf[Q931L4HeaderSpace]; - ptr->MesType = Q931mes_SERVICE_ACKNOWLEDGE; - if (ptr->CRV) { - ptr->CRVFlag = !(ptr->CRVFlag); - } - - RetCode = Q931Proc[pTrunk->Dialect][ptr->MesType](pTrunk, buf, 4); - - return RetCode; -} - -Q931_ENUM_NAMES(DIALECT_TYPE_NAMES, DIALECT_STRINGS) -Q931_STR2ENUM(q931_str2Q931Dialect_type, q931_Q931Dialect_type2str, Q931Dialect_t, DIALECT_TYPE_NAMES, Q931_Dialect_Count) diff --git a/libs/freetdm/src/isdn/Q931ie.c b/libs/freetdm/src/isdn/Q931ie.c deleted file mode 100644 index 62312ee654..0000000000 --- a/libs/freetdm/src/isdn/Q931ie.c +++ /dev/null @@ -1,3074 +0,0 @@ -/***************************************************************************** - - FileName: Q931ie.c - - Contents: Information Element Pack/Unpack functions. - - These functions will pack out a Q931 message from the bit - packed original format into structs that are easier to process - and pack the same structs back into bit fields when sending - messages out. - - The messages contains a short for each possible IE. The MSB - bit flags the precense of an IE, while the remaining bits - are the offset into a buffer to find the actual IE. - - Each IE are supported by 3 functions: - - Q931Pie_XXX Pack struct into Q.931 IE - Q931Uie_XXX Unpack Q.931 IE into struct - Q931InitIEXXX Initialize IE (see Q931api.c). - - Dialect Note: This file will only contain standard DSS1 IE. Other IE as - used in QSIG, NI2, Q.932 etc are located in separate files. - - See q931.h for description. - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -#include "Q931.h" - -#ifdef _MSC_VER -#ifndef __inline__ -#define __inline__ __inline -#endif -#if (_MSC_VER >= 1400) /* VC8+ */ -#ifndef _CRT_SECURE_NO_DEPRECATE -#define _CRT_SECURE_NO_DEPRECATE -#endif -#ifndef _CRT_NONSTDC_NO_DEPRECATE -#define _CRT_NONSTDC_NO_DEPRECATE -#endif -#endif -#ifndef strcasecmp -#define strcasecmp(s1, s2) _stricmp(s1, s2) -#endif -#ifndef strncasecmp -#define strncasecmp(s1, s2, n) _strnicmp(s1, s2, n) -#endif -#ifndef snprintf -#define snprintf _snprintf -#endif -#endif - -/***************************************************************************** - - Macro: Q931MoreIE - - Description: Local helper macro detecting if there is more IE space left - based on the 3 standard parameters Octet, Off and IESpace. - This can be used to test if the IE is completed to avoid - that the header of the next IE is interpreted as a part of - the current IE. - -*****************************************************************************/ -#define Q931MoreIE() (Octet + Off - 2 < IESize) - -#define Q931IESizeTest(x) {\ - if (Octet + Off - 2 != IESize) {\ - Q931SetError(pTrunk, x, Octet, Off);\ - return x;\ - }\ -} - -/***************************************************************************** - - Function: Q931ReadExt - - Description: Many of the octets in the standard have an MSB 'ext.1'. This - means that the octet usually is the latest octet, but that a - futhure standard may extend the octet. A stack must be able - to handle such extensions by skipping the extension octets. - - This function will increase the offset counter with 1 for - each octet with an MSB of zero. This will allow the stack to - skip extensions wihout knowing anything about them. - - Parameters: IBuf ptr to octet array. - Off Starting offset counter - - Return Value: New offset value. - -*****************************************************************************/ - -L3INT Q931ReadExt(L3UCHAR * IBuf, L3INT Off) -{ - L3INT c = 0; - while ((IBuf[c] & 0x80) == 0) { - c++; - } - return Off + c; -} - -/***************************************************************************** - - Function: Q931Uie_BearerCap - - Description: Unpack a bearer capability ie. - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ - -L3INT Q931Uie_BearerCap(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_BearerCap *pie = (Q931ie_BearerCap*)OBuf; - ie *pIE = &pMsg->BearerCap; - L3INT Off = 0; - L3INT Octet = 0; - L3INT IESize; - *pIE = 0; - - /* Octet 1 */ - pie->IEId = IBuf[Octet++]; - - /* Octet 2 */ - IESize = IBuf[Octet++]; - - /* Octet 3 */ - pie->CodStand = ieGetOctet((IBuf[Octet] & 0x60) >> 5); - pie->ITC = ieGetOctet(IBuf[Octet] & 0x1f); - Off = Q931ReadExt(&IBuf[Octet], Off); - Octet++; - - /* Octet 4 */ - pie->TransMode = ieGetOctet((IBuf[Octet + Off] & 0x60) >> 5); - pie->ITR = ieGetOctet(IBuf[Octet + Off] & 0x1f); - Off = Q931ReadExt(&IBuf[Octet + Off], Off); - Octet++; - - /* Octet 4.1. Rate multiplier is only present if ITR = Multirate */ - if (pie->ITR == 0x18) { - pie->RateMul = ieGetOctet(IBuf[Octet + Off] & 0x7f); - Off = Q931ReadExt(&IBuf[Octet + Off], Off); - Off ++; - } - - /* Octet 5 */ - if ((IBuf[Octet + Off] & 0x60) == 0x20 && Q931MoreIE()) { - pie->Layer1Ident = ieGetOctet((IBuf[Octet + Off] & 0x60) >> 5); - pie->UIL1Prot = ieGetOctet(IBuf[Octet + Off] & 0x1f); - Octet++; - - /* Octet 5a. The octet may be present if ITC is unrestrictd digital info - * and UIL1Prot is either V.110, I.460 and X.30 or V.120. It may also - * be present if ITC = 3.1 kHz audio and UIL1Prot is G.711. - * Bit 8 of Octet 5 = 0 indicates that 5a is present. - */ - - if (IsQ931Ext(IBuf[Octet + Off - 1])) { - if (((pie->ITC == 0x08) && (pie->UIL1Prot == 0x01 || pie->UIL1Prot == 0x08)) - || ((pie->ITC == 0x10) && (pie->UIL1Prot == 0x02 || pie->UIL1Prot == 0x03))) { - pie->SyncAsync = ieGetOctet((IBuf[Octet + Off] & 0x40) >> 6); - pie->Negot = ieGetOctet((IBuf[Octet + Off] & 0x20) >> 5); - pie->UserRate = ieGetOctet(IBuf[Octet + Off] & 0x1f); - Off ++; - } - else { - /* We have detected bit 8 = 0, but no setting that require the */ - /* additional octets ??? */ - Q931SetError(pTrunk, Q931E_BEARERCAP, 5,Off); - return Q931E_BEARERCAP; - } - - /* Octet 5b. Two different structures used. */ - if (IsQ931Ext(IBuf[Octet + Off - 1])) { - if (pie->UIL1Prot == 0x01) { /* ITU V.110, I.460 and X.30 */ - pie->InterRate = ieGetOctet((IBuf[Octet + Off] & 0x60) >> 5); - pie->NIConTx = ieGetOctet((IBuf[Octet + Off] & 0x10) >> 4); - pie->NIConRx = ieGetOctet((IBuf[Octet + Off] & 0x08) >> 3); - pie->FlowCtlTx = ieGetOctet((IBuf[Octet + Off] & 0x04) >> 2); - pie->FlowCtlRx = ieGetOctet((IBuf[Octet + Off] & 0x20) >> 1); - Off++; - } - else if (pie->UIL1Prot == 0x08) { /* ITU V.120 */ - pie->HDR = ieGetOctet((IBuf[Octet + Off] & 0x40) >> 6); - pie->MultiFrame = ieGetOctet((IBuf[Octet + Off] & 0x20) >> 5); - pie->Mode = ieGetOctet((IBuf[Octet + Off] & 0x10) >> 4); - pie->LLInegot = ieGetOctet((IBuf[Octet + Off] & 0x08) >> 3); - pie->Assignor = ieGetOctet((IBuf[Octet + Off] & 0x04) >> 2); - pie->InBandNeg = ieGetOctet((IBuf[Octet + Off] & 0x02) >> 1); - Off++; - } - else { - Q931SetError(pTrunk,Q931E_BEARERCAP, 5,Off); - return Q931E_BEARERCAP; - } - - /* Octet 5c */ - if (IsQ931Ext(IBuf[Octet + Off - 1])) { - pie->NumStopBits = ieGetOctet((IBuf[Octet + Off] & 0x60) >> 5); - pie->NumDataBits = ieGetOctet((IBuf[Octet + Off] & 0x18) >> 3); - pie->Parity = ieGetOctet(IBuf[Octet + Off] & 0x07); - Off++; - - /* Octet 5d */ - if (IsQ931Ext(IBuf[Octet + Off - 1])) { - pie->DuplexMode = ieGetOctet((IBuf[Octet + Off] & 0x40) >> 6); - pie->ModemType = ieGetOctet(IBuf[Octet + Off] & 0x3f); - Off ++; - } - } - } - } - } - - /* Octet 6 */ - if ((IBuf[Octet + Off] & 0x60) == 0x40 && Q931MoreIE()) { - pie->Layer2Ident = ieGetOctet((IBuf[Octet + Off] & 0x60) >> 5); - pie->UIL2Prot = ieGetOctet(IBuf[Octet + Off] & 0x1f); - - Off = Q931ReadExt(&IBuf[Octet + Off], Off); - Octet ++; - } - - /* Octet 7 */ - if ((IBuf[Octet + Off] & 0x60) == 0x60 && Q931MoreIE()) { - pie->Layer3Ident = ieGetOctet((IBuf[Octet + Off] & 0x60) >> 5); - pie->UIL3Prot = ieGetOctet(IBuf[Octet + Off] & 0x1f); - Octet++; - - /* Octet 7a */ - if (IsQ931Ext(IBuf[Octet + Off - 1])) { - if (pie->UIL3Prot == 0x0c) { - pie->AL3Info1 = ieGetOctet(IBuf[Octet + Off] & 0x0f); - Off++; - - /* Octet 7b */ - if (IsQ931Ext(IBuf[Octet + Off])) { - pie->AL3Info2 = ieGetOctet(IBuf[Octet + Off] & 0x0f); - Off++; - } - } - else { - Q931SetError(pTrunk,Q931E_BEARERCAP, 7, Off); - return Q931E_BEARERCAP; - - } - } - } - - Q931IESizeTest(Q931E_BEARERCAP); - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_BearerCap); - pie->Size = sizeof(Q931ie_BearerCap); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_BearerCap - - Description: Packing a Q.931 Bearer Capability element from a generic - struct into a packed octet structure in accordance with the - standard. - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ - -L3INT Q931Pie_BearerCap(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_BearerCap *pIE = (Q931ie_BearerCap*)IBuf; - L3INT rc = 0; - L3INT Beg = *Octet; /* remember current offset */ - L3INT li; - - Q931Log(pTrunk, Q931_LOG_DEBUG, "Encoding Bearer Capability IE\n"); - - OBuf[(*Octet)++] = Q931ie_BEARER_CAPABILITY ; - li = (*Octet)++; /* remember length position */ - - /* Octet 3 - Coding standard / Information transfer capability */ - OBuf[(*Octet)++] = 0x80 | ((pIE->CodStand << 5) & 0x60) | (pIE->ITC & 0x1f); - - /* Octet 4 - Transfer mode / Information transfer rate */ - OBuf[(*Octet)++] = 0x80 | ((pIE->TransMode << 5) & 0x60) | (pIE->ITR & 0x1f); - - if (pIE->ITR == 0x18) { - /* Octet 4.1 - Rate Multiplier */ - OBuf[(*Octet)++] = 0x80 | (pIE->RateMul & 0x7f); - } - - /* Octet 5 - Layer 1 Ident / User information layer 1 protocol */ - if (pIE->Layer1Ident == 0x01) { - if (((pIE->ITC == 0x08) && (pIE->UIL1Prot == 0x01 || pIE->UIL1Prot == 0x08)) || - ((pIE->ITC == 0x10) && (pIE->UIL1Prot == 0x02 || pIE->UIL1Prot == 0x03))) { - OBuf[(*Octet)++] = 0x00 | ((pIE->Layer1Ident << 5) & 0x60) | (pIE->UIL1Prot & 0x15); - - /* Octet 5a - SyncAsync/Negot/UserRate */ - OBuf[(*Octet)++] = 0x00 | ((pIE->SyncAsync << 6) & 0x40) | ((pIE->Negot << 5) & 0x20) | (pIE->UserRate & 0x1f); - - /* Octet 5b - one of two types */ - if (pIE->UIL1Prot == 0x01) { /* ITU V.110, I.460 and X.30 */ - /* Octet 5b - Intermed rate/ Nic on Tx/Nix on Rx/FlowCtlTx/FlowCtlRx */ - OBuf[(*Octet)++] = 0x00 - | ((pIE->InterRate << 6) & 0x60) - | ((pIE->NIConTx << 4) & 0x10) - | ((pIE->NIConRx << 3) & 0x08) - | ((pIE->FlowCtlTx << 2) & 0x04) - | ((pIE->FlowCtlRx << 1) & 0x02); - } - else if (pIE->UIL1Prot == 0x08) { /* ITU V.120 */ - /* Octet 5b - HDR/Multiframe/Mode/LLINegot/Assignor/Inbandneg*/ - OBuf[(*Octet)++] = 0x00 - | ((pIE->InterRate << 6) & 0x60) - | ((pIE->MultiFrame << 5) & 0x20) - | ((pIE->Mode << 4) & 0x10) - | ((pIE->LLInegot << 3) & 0x08) - | ((pIE->Assignor << 2) & 0x04) - | ((pIE->InBandNeg << 1) & 0x02); - } - - /* Octet 5c - NumStopBits/NumStartBits/Parity */ - OBuf[(*Octet)++] = 0x00 - | ((pIE->NumStopBits << 5) & 0x60) - | ((pIE->NumDataBits << 3) & 0x18) - | (pIE->Parity & 0x07); - - /* Octet 5d - Duplex Mode/Modem Type */ - OBuf[(*Octet)++] = 0x80 | ((pIE->DuplexMode << 6) & 0x40) | (pIE->ModemType & 0x3f); - } - else { - OBuf[(*Octet)++] = 0x80 | ((pIE->Layer1Ident << 5) & 0x60) | (pIE->UIL1Prot & 0x1f); - } - } - - /* Octet 6 - Layer2Ident/User information layer 2 prtocol */ - if (pIE->Layer2Ident == 0x02) { - OBuf[(*Octet)++] = 0x80 | ((pIE->Layer2Ident << 5) & 0x60) | (pIE->UIL2Prot & 0x1f); - } - - /* Octet 7 - Layer 3 Ident/ User information layer 3 protocol */ - if (pIE->Layer3Ident == 0x03) { - if (pIE->UIL3Prot == 0x0c) { - OBuf[(*Octet)++] = 0x00 | ((pIE->Layer3Ident << 5) & 0x60) | (pIE->UIL3Prot & 0x1f); - - /* Octet 7a - Additional information layer 3 msb */ - OBuf[(*Octet)++] = 0x00 | (pIE->AL3Info1 & 0x0f); - - /* Octet 7b - Additional information layer 3 lsb */ - OBuf[(*Octet)++] = 0x80 | (pIE->AL3Info2 & 0x0f); - } - else { - OBuf[(*Octet)++] = 0x80 | ((pIE->Layer3Ident << 5) & 0x60) | (pIE->UIL3Prot & 0x1f); - } - } - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_CallID - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_CallID(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_CallID *pie = (Q931ie_CallID*)OBuf; - ie *pIE = &pMsg->CallID; - L3INT Off = 0; - L3INT Octet = 0; - L3INT x = 0; - L3INT IESize; - - *pIE = 0; - - /* Octet 1 */ - pie->IEId = IBuf[Octet++]; - - /* Octet 2 */ - IESize = IBuf[Octet++]; - - /* Octet 3 */ - do { - pie->CallId[x] = IBuf[Octet + Off] & 0x7f; - Off++; - x++; - } while (Q931MoreIE()); - - Q931IESizeTest(Q931E_CALLID); - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_CallID) + x - 1; - pie->Size = (L3UCHAR)(sizeof(Q931ie_CallID) + x - 1); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_CallID - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ - -L3INT Q931Pie_CallID(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_CallID *pIE = (Q931ie_CallID*)IBuf; - L3INT rc = 0; - L3INT Beg = *Octet;/* remember current offset */ - L3INT li; - L3INT sCI = pIE->Size - sizeof(Q931ie_CallID) + 1; - L3INT x; - - OBuf[(*Octet)++] = Q931ie_CALL_IDENTITY ; - li = (*Octet)++; /* remember length position */ - - for (x = 0; x < sCI; x++) { - OBuf[(*Octet)++] = pIE->CallId[x]; - } - - OBuf[(*Octet) - 1] |= 0x80; /* set complete flag at last octet*/ - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_CallState - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_CallState(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_CallState *pie = (Q931ie_CallState*)OBuf; - ie *pIE = &pMsg->CallState; - L3INT Off = 0; - L3INT Octet = 0; - L3INT IESize; - - *pIE = 0; - - /* Octet 1 */ - pie->IEId = IBuf[Octet++]; - - /* Octet 2 */ - IESize = IBuf[Octet++]; - - /* Octet 3 */ - pie->CodStand = (IBuf[Octet + Off] >> 6) & 0x03; - pie->CallState = IBuf[Octet + Off] & 0x3f; - Octet++; - - Q931IESizeTest(Q931E_CALLSTATE); - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_CallState); - pie->Size = sizeof(Q931ie_CallState); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_CallState - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_CallState(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_CallState *pIE = (Q931ie_CallState*)IBuf; - L3INT rc = 0; - L3INT Beg = *Octet; /* remember current offset */ - L3INT li; - - OBuf[(*Octet)++] = Q931ie_CALL_STATE; - li = (*Octet)++; /* remember length position */ - - OBuf[(*Octet)++] = (pIE->CodStand << 6) | (pIE->CallState & 0x3f); - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_CalledSub - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_CalledSub(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_CalledSub *pie = (Q931ie_CalledSub*)OBuf; - ie *pIE = &pMsg->CalledSub; - L3INT Off = 0; - L3INT Octet = 0; - L3INT x; - L3INT IESize; - - *pIE = 0; - - /* Octet 1 */ - pie->IEId = IBuf[Octet++]; - - /* Octet 2 */ - IESize = IBuf[Octet++]; - - /* Octet 3 */ - pie->TypNum = (IBuf[Octet + Off] >> 4) & 0x07; - pie->OddEvenInd = (IBuf[Octet + Off] >> 3) & 0x01; - Octet++; - - /* Octet 4 */ - x = 0; - do { - pie->Digit[x] = IBuf[Octet + Off] & 0x7f; - Off++; - x++; - } while (Q931MoreIE() && x < 20); - - Q931IESizeTest(Q931E_CALLEDSUB); - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_CalledSub) + x - 1; - pie->Size = (L3UCHAR)(sizeof(Q931ie_CalledSub) + x - 1); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_CalledSub - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_CalledSub(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_CalledSub *pIE = (Q931ie_CalledSub*)IBuf; - L3INT rc = 0; - L3INT Beg = *Octet; - L3INT li; - L3INT sN = pIE->Size - sizeof(Q931ie_CalledSub) + 1; - L3INT x; - - /* Octet 1 */ - OBuf[(*Octet)++] = Q931ie_CALLED_PARTY_SUBADDRESS; - li = (*Octet)++; - - /* Octet 3 */ - OBuf[(*Octet)++] = 0x80 | (pIE->TypNum << 4) | (pIE->OddEvenInd << 3); - - /* Octet 4 */ - for (x = 0; xDigit[x]; - } - - OBuf[(*Octet) - 1] |= 0x80; /* Terminate bit */ - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_CalledNum - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_CalledNum(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_CalledNum *pie = (Q931ie_CalledNum*)OBuf; - ie *pIE = &pMsg->CalledNum; - L3INT Off = 0; - L3INT Octet = 0; - L3INT x; - L3INT IESize; /* # digits in this case */ - - *pIE = 0; - - /* Octet 1 */ - pie->IEId = IBuf[Octet++]; - - /* Octet 2 */ - IESize = IBuf[Octet++]; - - /* Octet 3 */ - pie->TypNum = (IBuf[Octet + Off] >> 4) & 0x07; - pie->NumPlanID = IBuf[Octet + Off] & 0x0f; - Octet++; - - /* Octet 4*/ - x = 0; - do { - pie->Digit[x] = IBuf[Octet + Off] & 0x7f; - Off++; - x++; - } while ((IBuf[Octet + Off]&0x80) == 0 && Q931MoreIE()); - - pie->Digit[x] = '\0'; - - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_CalledNum) + x; - pie->Size = (L3UCHAR)(sizeof(Q931ie_CalledNum) + x); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_CalledNum - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_CalledNum(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_CalledNum *pIE = (Q931ie_CalledNum*)IBuf; - L3INT rc = 0; - L3INT Beg = *Octet; - L3INT li; - L3INT sN = pIE->Size - sizeof(Q931ie_CalledNum); - L3INT x; - - /* Octet 1 */ - OBuf[(*Octet)++] = Q931ie_CALLED_PARTY_NUMBER; - - /* Octet 2 */ - li = (*Octet)++; - - /* Octet 3 */ - OBuf[(*Octet)++] = 0x80 | (pIE->TypNum << 4) | (pIE->NumPlanID); - - /* Octet 4 */ - for (x = 0; xDigit[x]; - } - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_CallingNum - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_CallingNum(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_CallingNum *pie = (Q931ie_CallingNum*)OBuf; - ie *pIE = &pMsg->CallingNum; - L3INT Off = 0; - L3INT Octet = 0; - L3INT x; - L3INT IESize; - - *pIE = 0; - - /* Octet 1 */ - pie->IEId = IBuf[Octet++]; - - /* Octet 2 */ - IESize = IBuf[Octet++]; - - /* Octet 3 */ - pie->TypNum = (IBuf[Octet + Off] >> 4) & 0x07; - pie->NumPlanID = IBuf[Octet + Off] & 0x0f; - - /* Octet 3a */ - if ((IBuf[Octet + Off] & 0x80) == 0) { - Off++; - pie->PresInd = (IBuf[Octet + Off] >> 5) & 0x03; - pie->ScreenInd = IBuf[Octet + Off] & 0x03; - } - Octet++; - - /* Octet 4 */ - x = 0; - while (Q931MoreIE()) { - pie->Digit[x++] = IBuf[Octet + Off] & 0x7f; - - if ((IBuf[Octet + Off] & 0x80) != 0) { - break; - } - Off++; - } - pie->Digit[x] = '\0'; - - Q931IESizeTest(Q931E_CALLINGNUM); - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_CallingNum) + x; - pie->Size = (L3UCHAR)(sizeof(Q931ie_CallingNum) + x); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_CallingNum - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_CallingNum(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_CallingNum *pIE = (Q931ie_CallingNum*)IBuf; - L3INT rc = 0; - L3INT Beg = *Octet; - L3INT li; - L3INT sN = pIE->Size - sizeof(Q931ie_CallingNum); - L3INT x; - - /* Octet 1 */ - OBuf[(*Octet)++] = Q931ie_CALLING_PARTY_NUMBER; - - /* Octet 2 */ - li = (*Octet)++; - - /* Octet 3 */ - OBuf[(*Octet)++] = 0x00 | (pIE->TypNum << 4) | (pIE->NumPlanID); - - /* Octet 4 */ - OBuf[(*Octet)++] = 0x80; - - /* Octet 5 */ - for (x = 0; xDigit[x]; - } - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_CallingSub - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_CallingSub(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_CallingSub *pie = (Q931ie_CallingSub*)OBuf; - ie *pIE = &pMsg->CallingSub; - L3INT Off = 0; - L3INT Octet = 0; - L3INT x; - L3INT IESize; - - *pIE = 0; - - /* Octet 1 */ - pie->IEId = IBuf[Octet++]; - - /* Octet 2 */ - IESize = IBuf[Octet++]; - - /* Octet 3 */ - pie->TypNum = (IBuf[Octet + Off] >> 4) & 0x07; - pie->OddEvenInd = (IBuf[Octet + Off] >> 3) & 0x01; - Octet++; - - /* Octet 4*/ - x = 0; - do { - pie->Digit[x] = IBuf[Octet + Off] & 0x7f; - Off++; - x++; - } while (Q931MoreIE() && x < 20); - - Q931IESizeTest(Q931E_CALLINGSUB); - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_CallingSub) + x -1; - pie->Size = (L3UCHAR)(sizeof(Q931ie_CallingSub) + x -1); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_CallingSub - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_CallingSub(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_CallingSub *pIE = (Q931ie_CallingSub*)IBuf; - L3INT rc = 0; - L3INT Beg = *Octet; - L3INT li; - L3INT sN = pIE->Size - sizeof(Q931ie_CallingSub) + 1; - L3INT x; - - /* Octet 1 */ - OBuf[(*Octet)++] = Q931ie_CALLING_PARTY_SUBADDRESS; - li = (*Octet)++; - - /* Octet 3 */ - OBuf[(*Octet)++] = 0x80 | (pIE->TypNum << 4) | (pIE->OddEvenInd << 3); - - /* Octet 4 */ - for (x = 0; xDigit[x]; - } - - OBuf[(*Octet) - 1] |= 0x80; /* Terminate bit */ - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_Cause - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_Cause(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_Cause *pie = (Q931ie_Cause*)OBuf; - ie *pIE = &pMsg->Cause; - L3INT Off = 0; - L3INT Octet = 0; - L3INT IESize; - - *pIE = 0; - - pie->IEId = IBuf[Octet++]; - - /* Octet 2*/ - IESize = IBuf[Octet++]; - - /* Octet 3*/ - pie->CodStand = (IBuf[Octet + Off]>>5) & 0x03; - pie->Location = IBuf[Octet + Off] & 0x0f; - - /* Octet 3a */ - if ((IBuf[Octet + Off] & 0x80) == 0) { - Off++; - pie->Recom = IBuf[Octet + Off] & 0x7f; - } - Octet++; - - /* Octet 4 */ - pie->Value = IBuf[Octet + Off] & 0x7f; - Octet++; - - /* Consume optional Diagnostic bytes */ - while (Q931MoreIE()) { - Off++; - }; - - Q931IESizeTest(Q931E_CAUSE); - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_Cause); - pie->Size = sizeof(Q931ie_Cause); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_Cause - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_Cause(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_Cause *pIE = (Q931ie_Cause*)IBuf; - L3INT rc = 0; - L3INT Beg = *Octet; - L3INT li; - - OBuf[(*Octet)++] = Q931ie_CAUSE; - li = (*Octet)++; - - /* Octet 3 */ - OBuf[(*Octet)++] = 0x80 | (pIE->CodStand<<5) | pIE->Location; - - /* Octet 3a - currently not supported in send */ - - /* Octet 4 */ - OBuf[(*Octet)++] = 0x80 | pIE->Value; - - /* Octet 5 - diagnostics not supported in send */ - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_CongLevel - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_CongLevel(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_CongLevel *pie = (Q931ie_CongLevel*)OBuf; - ie *pIE = &pMsg->CongestionLevel; - L3INT Off = 0; - L3INT Octet = 0; - - *pIE = 0; - - pie->IEId = IBuf[Octet] & 0xf0; - pie->CongLevel = IBuf[Octet] & 0x0f; - Octet ++; - - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_CongLevel); - pie->Size = sizeof(Q931ie_CongLevel); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_CongLevel - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_CongLevel(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_CongLevel *pIE = (Q931ie_CongLevel*)IBuf; - L3INT rc = 0; - /* L3INT Beg = *Octet; */ - - OBuf[(*Octet)++] = Q931ie_CONGESTION_LEVEL | pIE->CongLevel; - - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_ChanID - - Parameters: IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Uie_ChanID(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR *OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_ChanID *pie = (Q931ie_ChanID*)OBuf; - ie *pIE = &pMsg->ChanID; - L3INT Off = 0; - L3INT Octet = 0; - L3INT IESize; -//18 04 e1 80 83 01 - *pIE = 0; - - Q931Log(pTrunk, Q931_LOG_DEBUG, "Decoding ChanID IE\n"); - - /* Octet 1 */ - pie->IEId = IBuf[Octet++]; - - /* Octet 2 */ - IESize = IBuf[Octet++]; - - /* Octet 3 */ - pie->IntIDPresent = (IBuf[Octet] >> 6) & 0x01; - pie->IntType = (IBuf[Octet] >> 5) & 0x01; - pie->PrefExcl = (IBuf[Octet] >> 3) & 0x01; - pie->DChanInd = (IBuf[Octet] >> 2) & 0x01; - pie->InfoChanSel = IBuf[Octet] & 0x03; - - Off = Q931ReadExt(&IBuf[Octet++], Off); - - /* Octet 3.1 */ - if (pie->IntIDPresent) { - pie->InterfaceID = IBuf[Octet + Off] & 0x7f; - - /* Temp fix. Interface id can be extended using the extension bit */ - /* this will read the octets, but do nothing with them. this is done */ - /* because the usage of this field is a little unclear */ - /* 30.jan.2001/JVB */ - Off = Q931ReadExt(&IBuf[Octet + Off], Off); - Off++; - } - - if ((Octet + Off - 2) != IESize) { - /* Octet 3.2 */ - if (pie->IntType == 1) { /* PRI etc */ - pie->CodStand = (IBuf[Octet + Off] >> 5) & 0x03; - pie->NumMap = (IBuf[Octet + Off] >> 4) & 0x01; - pie->ChanMapType = IBuf[Octet + Off] & 0x0f; - Off++; - - /* Octet 3.3 */ - /* Temp fix. Assume B channel. H channels not supported */ - pie->ChanSlot = IBuf[Octet + Off] & 0x7f; - - /* Some dialects don't follow the extension coding properly for this, but this should be safe for all */ - if ((Octet + Off - 1) != IESize) { - Off = Q931ReadExt(&IBuf[Octet + Off], Off); - } - Off++; - } - } - - Q931IESizeTest(Q931E_CHANID); - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_ChanID); - pie->Size = sizeof(Q931ie_ChanID); - - if (pTrunk->loglevel == Q931_LOG_DEBUG) { - const char *iface; - char tmp[100] = ""; - - if (!pie->IntType) { - switch (pie->InfoChanSel) { - case 0x0: - iface = "None"; - break; - case 0x1: - iface = "B1"; - break; - case 0x2: - iface = "B2"; - break; - default: - iface = "Any Channel"; - } - - snprintf(tmp, sizeof(tmp)-1, "InfoChanSel: %d (%s)", pie->InfoChanSel, iface); - } - - Q931Log(pTrunk, Q931_LOG_DEBUG, - "\n-------------------------- Q.931 Channel ID ------------------------\n" - " Pref/Excl: %s, Interface Type: %s\n" - " %s\n" - "--------------------------------------------------------------------\n\n", - ((pie->PrefExcl) ? "Preferred" : "Exclusive"), - ((pie->IntType) ? "PRI/Other" : "BRI"), - tmp); - } - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_ChanID - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_ChanID(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_ChanID *pIE = (Q931ie_ChanID*)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Beg = *Octet; /* remember current offset */ - L3INT li; - - OBuf[(*Octet)++] = Q931ie_CHANNEL_IDENTIFICATION; - li = (*Octet)++; /* remember length position */ - - /* Octet 3 flags & BRI chan # */ - OBuf[(*Octet)++] = 0x80 - | ((pIE->IntIDPresent << 6) & 0x40) - | ((pIE->IntType << 5) & 0x20) - | ((pIE->PrefExcl << 3) & 0x08) - | (pIE->InfoChanSel & 0x03); - - /* Octet 3.1 - Interface Identifier */ - if (pIE->IntIDPresent) { - OBuf[(*Octet)++] = 0x80 | (pIE->InterfaceID & 0x7f); - } - - /* Octet 3.2 & 3.3 - PRI */ - if (pIE->IntType) { - OBuf[(*Octet)++] = 0x80 - | ((pIE->CodStand << 5) & 0x60) - | ((pIE->NumMap << 4) & 0x10) - | (pIE->ChanMapType & 0x0f); /* TODO: support all possible channel map types */ - - /* Octet 3.3 Channel number */ - switch (pIE->ChanMapType) { - case 0x6: /* Slot map: H0 Channel Units */ /* unsupported, Octets 3.3.1 - 3.3.3 */ - return Q931E_CHANID; - - case 0x8: /* Slot map: H11 Channel Units */ - case 0x9: /* Slot map: H12 Channel Units */ - default: /* Channel number */ - OBuf[(*Octet)++] = 0x80 | (pIE->ChanSlot & 0x7f); - break; - } - } - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - - -/***************************************************************************** - - Function: Q931Uie_CRV - - Description: Reading CRV. - - The CRV is currently returned in the return value that - Q921Rx23 will assign to the CRV field in the unpacked - message. CRV is basically 2 bytes etc, but the spec allows - the use of longer CRV values. - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: CRV - -*****************************************************************************/ -L3USHORT Q931Uie_CRV(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *IOff, L3INT *OOff) -{ - L3USHORT CRV = 0; - L3INT Octet = *IOff; - L3INT l = IBuf[Octet++]; - - if (l == 1) { /* One octet CRV */ - CRV = IBuf[Octet++] & 0x7F; - } - else if (l == 2) { /* two octet CRV */ - CRV = (IBuf[Octet++] & 0x7f) << 8; - CRV |= IBuf[Octet++]; - } - else { - /* Long CRV is not used, so we skip this */ - /* TODO: is it right to set to 0 here? */ - CRV = 0; - Octet += l; - } - - *IOff = Octet; - return CRV; -} - -/***************************************************************************** - - Function: Q931Uie_DateTime - - Parameters: pTrunk [IN] Ptr to trunk information. - pIE [OUT] ptr to Information Element id. - IBuf [IN] ptr to a packed ie. - OBuf [OUT] ptr to buffer for Unpacked ie. - IOff [IN\OUT] Input buffer offset - OOff [IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_DateTime(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_DateTime * pie = (Q931ie_DateTime*)OBuf; - ie *pIE = &pMsg->DateTime; - L3INT Off = 0; - L3INT Octet = 0; - L3INT IESize = 0; - - *pIE = 0; - - pie->IEId = IBuf[Octet++]; - - /* Octet 2 */ - IESize = IBuf[Octet++]; - - /* Octet 3 - Year */ - pie->Year = IBuf[Octet++]; - - /* Octet 4 - Month */ - pie->Month = IBuf[Octet++]; - - /* Octet 5 - Day */ - pie->Day = IBuf[Octet++]; - - /******************************************************************* - The remaining part of the IE are optioinal, but only the length - can now tell us wherever these fields are present or not - (always remember: IESize does not include ID and Size octet) - ********************************************************************/ - pie->Format = 0; - - /* Octet 6 - Hour (optional)*/ - if (IESize >= 4) { - pie->Format = 1; - pie->Hour = IBuf[Octet++]; - - /* Octet 7 - Minute (optional)*/ - if (IESize >= 5) { - pie->Format = 2; - pie->Minute = IBuf[Octet++]; - - /* Octet 8 - Second (optional)*/ - if (IESize >= 6) { - pie->Format = 3; - pie->Second = IBuf[Octet++]; - } - } - } - - Q931IESizeTest(Q931E_DATETIME); - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_DateTime); - pie->Size = sizeof(Q931ie_DateTime); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_DateTime - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_DateTime(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_DateTime *pIE = (Q931ie_DateTime*)IBuf; - L3INT rc = 0; - L3INT Beg = *Octet; - L3INT li; - - OBuf[(*Octet)++] = Q931ie_DATETIME; - li = (*Octet)++; - - OBuf[(*Octet)++] = pIE->Year; - OBuf[(*Octet)++] = pIE->Month; - OBuf[(*Octet)++] = pIE->Day; - if (pIE->Format >= 1) { - OBuf[(*Octet)++] = pIE->Hour; - - if (pIE->Format >= 2) { - OBuf[(*Octet)++] = pIE->Minute; - - if (pIE->Format >= 3) { - OBuf[(*Octet)++] = pIE->Second; - } - } - } - - OBuf[li] = (L3UCHAR)((*Octet)-Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_Display - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_Display(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_Display *pie = (Q931ie_Display*)OBuf; - ie *pIE = &pMsg->Display; - L3INT Off = 0; - L3INT Octet = 0; - L3INT IESize; - L3INT x; - - *pIE = 0; - - pie->IEId = IBuf[Octet++]; - IESize = IBuf[Octet++]; - - for (x = 0; xDisplay[x] = IBuf[Octet + Off] & 0x7f; - Off++; - } - - Q931IESizeTest(Q931E_DISPLAY); - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_Display) + x - 1; - pie->Size = (L3UCHAR)(sizeof(Q931ie_Display) + x - 1); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_Display - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_Display(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_Display *pIE = (Q931ie_Display*)IBuf; - L3INT rc = 0; - L3INT Beg = *Octet; - L3INT li; - L3INT DSize; - L3INT x; - - OBuf[(*Octet)++] = Q931ie_DISPLAY; - li = (*Octet)++; - - DSize = pIE->Size - sizeof(Q931ie_Display); - - for (x = 0; x< DSize; x++) { - - OBuf[(*Octet)++] = pIE->Display[x]; - } - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_HLComp - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_HLComp(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_HLComp * pie = (Q931ie_HLComp*)OBuf; - ie *pIE = &pMsg->HLComp; - L3INT Off = 0; - L3INT Octet = 0; - L3INT IESize; - - *pIE = 0; - - pie->IEId = IBuf[Octet++]; - - /* Octet */ - IESize = IBuf[Octet++]; - - /* Octet 3*/ - pie->CodStand = (IBuf[Octet + Off] >>5) & 0x03; - pie->Interpret = (IBuf[Octet + Off] >>2) & 0x07; - pie->PresMeth = IBuf[Octet + Off] & 0x03; - Octet++; - - /* Octet 4 */ - pie->HLCharID = IBuf[Octet + Off] & 0x7f; - Octet++; - - /* Octet 4a*/ - if ((IBuf[Octet + Off - 1] & 0x80) == 0 && Q931MoreIE()) { - if (pie->HLCharID == 0x5e || pie->HLCharID == 0x5f) { - pie->EHLCharID = IBuf[Octet + Off] & 0x7f; - Off++; - } - else if ( pie->HLCharID >= 0xc3 && pie->HLCharID <= 0xcf) { - pie->EVideoTlfCharID = IBuf[Octet + Off] & 0x7f; - Off++; - } - else { - /* error Octet 4a indicated, but invalid value in Octet 4. */ - Q931SetError(pTrunk,Q931E_HLCOMP, 4, Off); - return Q931E_HLCOMP; - } - Off = Q931ReadExt(&IBuf[Octet + Off], Off); - } - - Q931IESizeTest(Q931E_HLCOMP); - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_HLComp); - pie->Size = sizeof(Q931ie_HLComp); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_HLComp - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_HLComp(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_HLComp *pIE = (Q931ie_HLComp*)IBuf; - L3INT rc = 0; - L3INT Beg = *Octet; - L3INT li; - - OBuf[(*Octet)++] = Q931ie_HIGH_LAYER_COMPATIBILITY; - li = (*Octet)++; - - /* Octet 3 */ - OBuf[(*Octet)++] = 0x80 | ((pIE->CodStand << 5) & 0x60) | ((pIE->Interpret << 2) & 0x1c) | (pIE->PresMeth & 0x03); - - /* Octet 4 */ - OBuf[(*Octet)++] = pIE->HLCharID; - - /* Octet 4a */ - if (pIE->HLCharID == 0x5e || pIE->HLCharID == 0x5f) { - OBuf[(*Octet)++] = 0x80 | (pIE->EHLCharID & 0x7f); - } - else if ( pIE->HLCharID >= 0xc3 && pIE->HLCharID <= 0xcf) { - OBuf[(*Octet)++] = 0x80 | (pIE->EVideoTlfCharID & 0x7f); - } - else { - OBuf[(*Octet) - 1] |= 0x80; - } - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_KeypadFac - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_KeypadFac(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_KeypadFac *pie = (Q931ie_KeypadFac*)OBuf; - ie *pIE = &pMsg->KeypadFac; - L3INT Off = 0; - L3INT Octet = 0; - L3INT IESize; - L3INT x; - - *pIE = 0; - - pie->IEId = IBuf[Octet++]; - IESize = IBuf[Octet++]; - - for (x = 0; xKeypadFac[x] = IBuf[Octet + Off] & 0x7f; - Off++; - } - - Q931IESizeTest(Q931E_KEYPADFAC); - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_KeypadFac) + x - 1; - pie->Size = (L3UCHAR)(sizeof(Q931ie_KeypadFac) + x - 1); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_KeypadFac - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_KeypadFac(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_KeypadFac *pIE = (Q931ie_KeypadFac*)IBuf; - L3INT rc = 0; - L3INT Beg = *Octet; - L3INT li; - L3INT DSize; - L3INT x; - - OBuf[(*Octet)++] = Q931ie_KEYPAD_FACILITY; - li = (*Octet)++; - - DSize = pIE->Size - sizeof(Q931ie_KeypadFac) + 1; - - for (x = 0; x< DSize; x++) { - OBuf[(*Octet)++] = pIE->KeypadFac[x]; - } - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_LLComp - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_LLComp(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_LLComp *pie = (Q931ie_LLComp*)OBuf; - ie *pIE = &pMsg->LLComp; - L3INT Off = 0; - L3INT Octet = 0; - L3INT IESize; - - *pIE = 0; - - pie->IEId = IBuf[Octet++]; - - /* Octet 2 */ - IESize = IBuf[Octet++]; - - /* Octet 3 */ - pie->CodStand = (IBuf[Octet + Off] >> 5) & 0x03; - pie->ITransCap = IBuf[Octet + Off] & 0x1f; - Octet++; - - /* Octet 3a*/ - if (IsQ931Ext(IBuf[Octet + Off - 1])) { - pie->NegotInd = (IBuf[Octet + Off] >> 6) & 0x01; - Off++; - } - - /* Octet 4 */ - pie->TransMode = (IBuf[Octet + Off] >> 5) & 0x03; - pie->InfoRate = IBuf[Octet + Off] & 0x1f; - - Octet++; - - /* Octet 4.1 */ - if (pie->InfoRate == 0x14) { /* Mutirate */ - pie->RateMul = IBuf[Octet + Off] & 0x7f; - Off++; - } - - /* Octet 5 - Layer 1 Ident */ - if ((IBuf[Octet + Off] & 0x60) == 0x20) { /* Layer 1 Ident ? */ - pie->Layer1Ident = (IBuf[Octet + Off] >> 5) & 0x03; - pie->UIL1Prot = IBuf[Octet + Off] & 0x1f; - Octet++; - - /* Octet 5a */ - if (IsQ931Ext(IBuf[Octet + Off - 1])) { - pie->SyncAsync = (IBuf[Octet + Off] >> 6) & 0x01; - pie->Negot = (IBuf[Octet + Off] >> 5) & 0x01; - pie->UserRate = IBuf[Octet + Off] & 0x1f; - Off++; - - /* Octet 5b - 2 options */ - if (IsQ931Ext(IBuf[Octet + Off - 1])) { - if (pie->UIL1Prot == 0x01) { /* V.110, I.460 and X.30*/ - pie->InterRate = (IBuf[Octet + Off] >> 5) & 0x03; - pie->NIConTx = (IBuf[Octet + Off] >> 4) & 0x01; - pie->NIConRx = (IBuf[Octet + Off] >> 3) & 0x01; - pie->FlowCtlTx = (IBuf[Octet + Off] >> 2) & 0x01; - pie->FlowCtlRx = (IBuf[Octet + Off] >> 1) & 0x01; - Off++; - } - else if (pie->UIL1Prot == 0x80) { /* V.120 */ - pie->HDR = (IBuf[Octet + Off] >> 6) & 0x01; - pie->MultiFrame = (IBuf[Octet + Off] >> 5) & 0x01; - pie->ModeL1 = (IBuf[Octet + Off] >> 4) & 0x01; - pie->NegotLLI = (IBuf[Octet + Off] >> 3) & 0x01; - pie->Assignor = (IBuf[Octet + Off] >> 2) & 0x01; - pie->InBandNeg = (IBuf[Octet + Off] >> 1) & 0x01; - Off++; - } - else if (pie->UIL1Prot == 0x07) { /* non standard */ - Off = Q931ReadExt(&IBuf[Octet + Off], Off); - Off++; - } - else { - Q931SetError(pTrunk,Q931E_LLCOMP, 5,2); - return Q931E_LLCOMP; - } - - /* Octet 5c */ - if (IsQ931Ext(IBuf[Octet + Off - 1])) { - pie->NumStopBits = (IBuf[Octet + Off] >> 5) & 0x03; - pie->NumDataBits = (IBuf[Octet + Off] >> 3) & 0x03; - pie->Parity = IBuf[Octet + Off] & 0x07; - Off++; - - /* Octet 5d */ - if (IsQ931Ext(IBuf[Octet + Off - 1])) { - pie->DuplexMode = (IBuf[Octet + Off] >> 6) & 0x01; - pie->ModemType = IBuf[Octet + Off] & 0x3f; - Off = Q931ReadExt(&IBuf[Octet + Off], Off); - Off++; - } - } - } - } - } - - /* Octet 6 - Layer 2 Ident */ - if ((IBuf[Octet + Off] & 0x60) == 0x40) { /* Layer 1 Ident ? */ - pie->Layer2Ident = (IBuf[Octet + Off] >>5) & 0x03; - pie->UIL2Prot = IBuf[Octet + Off] & 0x1f; - Octet++; - - /* Octet 6a */ - if (IsQ931Ext(IBuf[Octet + Off - 1])) { - if (pie->UIL2Prot == 0x10) { /* 2nd 6a */ - pie->UsrSpcL2Prot = IBuf[Octet + Off] & 0x7f; - Off++; - } - else { /* assume 1st 6a */ - pie->ModeL2 = (IBuf[Octet + Off] >> 5) & 0x03; - pie->Q933use = IBuf[Octet + Off] & 0x03; - Off++; - } - /* Octet 6b */ - if (IsQ931Ext(IBuf[Octet + Off - 1])) { - pie->WindowSize = IBuf[Octet + Off] & 0x7f; - Off++; - } - } - } - - /* Octet 7 - layer 3 Ident */ - if ((IBuf[Octet + Off] & 0x60) == 0x60) { /* Layer 3 Ident ? */ - pie->Layer3Ident = (IBuf[Octet + Off] >> 5) & 0x03; - pie->UIL3Prot = IBuf[Octet + Off] & 0x1f; - Octet++; - - /* Octet 7a */ - if (IsQ931Ext(IBuf[Octet + Off - 1])) { - if (pie->UIL3Prot == 0x0b) { - /* Octet 7a + 7b AddL3Info */ - pie->AddL3Info = ((IBuf[Octet + Off] << 4) & 0xf0) - | (IBuf[Octet + Off + 1] & 0x0f); - Off += 2; - } - else { - if (pie->UIL3Prot == 0x1f) { - pie->ModeL3 = (IBuf[Octet + Off] >> 5) & 0x03; - Off++; - } - else { - pie->OptL3Info = IBuf[Octet + Off] & 0x7f; - Off++; - } - - /* Octet 7b*/ - if (IsQ931Ext(IBuf[Octet + Off - 1])) { - pie->DefPackSize = IBuf[Octet + Off] & 0x0f; - Off++; - - /* Octet 7c */ - if (IsQ931Ext(IBuf[Octet + Off - 1])) { - pie->PackWinSize= IBuf[Octet + Off] & 0x7f; - } - } - } - } - } - - Q931IESizeTest(Q931E_LLCOMP); - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_LLComp); - pie->Size = sizeof(Q931ie_LLComp); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_LLComp - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_LLComp(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_LLComp *pIE = (Q931ie_LLComp*)IBuf; - L3INT rc = 0; - L3INT Beg = *Octet; - L3INT li; - - OBuf[(*Octet)++] = Q931ie_LOW_LAYER_COMPATIBILITY; - li = (*Octet)++; - - /* Octet 3 */ - OBuf[(*Octet)++] = (pIE->CodStand << 6) | pIE->ITransCap; - - /* Octet 3a */ - OBuf[(*Octet)++] = 0x80 | (pIE->NegotInd << 6); - - /* Octet 4 */ - OBuf[(*Octet)++] = 0x80 | (pIE->TransMode << 5) | pIE->InfoRate; - - /* Octet 4.1 */ - if (pIE->InfoRate == 0x18) { - OBuf[(*Octet)++] = 0x80 | pIE->RateMul; - } - - /* Octet 5 */ - if (pIE->Layer1Ident == 0x01) { - OBuf[(*Octet)++] = (pIE->Layer1Ident << 5) | pIE->UIL1Prot; - - /* Octet 5a */ - if ((pIE->ITransCap == 0x08 && (pIE->UIL1Prot == 0x01 || pIE->UIL1Prot == 0x08)) - || (pIE->ITransCap == 0x10 && (pIE->UIL1Prot == 0x02 || pIE->UIL1Prot == 0x03))) { - OBuf[(*Octet)++] = (pIE->SyncAsync<<6) | (pIE->Negot<<5) | pIE->UserRate; - - /* Octet 5b*/ - if (pIE->UIL1Prot == 0x01) { - OBuf[(*Octet)++] = (pIE->InterRate << 5) - | (pIE->NIConTx << 4) - | (pIE->NIConTx << 3) - | (pIE->FlowCtlTx << 2) - | (pIE->FlowCtlRx << 1); - } - else if (pIE->UIL1Prot == 0x08) { - OBuf[(*Octet)++] = (pIE->HDR << 6) - | (pIE->MultiFrame << 5) - | (pIE->ModeL1 << 4) - | (pIE->NegotLLI << 3) - | (pIE->Assignor << 2) - | (pIE->InBandNeg << 1); - } - else { - OBuf[(*Octet) - 1] |= 0x80; - } - - /* How to detect wherever 5c and 5d is to present is not clear - * but they have been inculded as 'standard' - * Octet 5c - */ - if (pIE->UIL1Prot == 0x01 || pIE->UIL1Prot == 0x08) { - OBuf[(*Octet)++] = (pIE->NumStopBits << 5) | (pIE->NumDataBits << 3) | pIE->Parity ; - - /* Octet 5d */ - OBuf[(*Octet)++] = 0x80 | (pIE->DuplexMode << 6) | pIE->ModemType; - } - } - else { - OBuf[(*Octet) - 1] |= 0x80; - } - } - - /* Octet 6 */ - if (pIE->Layer2Ident == 0x02) { - OBuf[(*Octet)++] = (pIE->Layer2Ident << 5) | pIE->UIL2Prot; - - /* Octet 6a*/ - if (pIE->UIL2Prot == 0x02 /* Q.921/I.441 */ - || pIE->UIL2Prot == 0x06 /* X.25 link layer */ - || pIE->UIL2Prot == 0x07 /* X.25 multilink */ - || pIE->UIL2Prot == 0x09 /* HDLC ARM */ - || pIE->UIL2Prot == 0x0a /* HDLC NRM */ - || pIE->UIL2Prot == 0x0b /* HDLC ABM */ - || pIE->UIL2Prot == 0x0d /* X.75 SLP */ - || pIE->UIL2Prot == 0x0e /* Q.922 */ - || pIE->UIL2Prot == 0x11) { /* ISO/ECE 7776 DTE-DCE */ - OBuf[(*Octet)++] = (pIE->ModeL2 << 5) | pIE->Q933use; - - /* Octet 6b */ - OBuf[(*Octet)++] = 0x80 | pIE->WindowSize; - } - else if (pIE->UIL2Prot == 0x10) { /* User Specific */ - OBuf[(*Octet)++] = 0x80 | pIE->UsrSpcL2Prot; - } - else { - OBuf[(*Octet) - 1] |= 0x80; - } - } - - /* Octet 7 */ - if (pIE->Layer3Ident == 0x03) { - OBuf[(*Octet)++] = (pIE->Layer3Ident << 5) | pIE->UIL3Prot; - - /* Octet 7a - 3 different ones */ - if (pIE->UIL3Prot == 0x10) { - OBuf[(*Octet++)] = 0x80 | pIE->OptL3Info; - } - else if (pIE->UIL3Prot == 0x06 - || pIE->UIL3Prot == 0x07 - || pIE->UIL3Prot == 0x08) { - OBuf[(*Octet)++] = pIE->ModeL3 << 5; - - /* Octet 7b note 7 */ - OBuf[(*Octet)++] = pIE->DefPackSize; - - /* Octet 7c note 7 */ - OBuf[(*Octet)++] = 0x80 | pIE->PackWinSize; - } - else if (pIE->UIL3Prot == 0x0b) { - OBuf[(*Octet)++] = (pIE->AddL3Info >> 4) & 0x0f; - OBuf[(*Octet)++] = 0x80 | (pIE->AddL3Info & 0x0f); - } - else { - OBuf[(*Octet) - 1] |= 0x80; - } - } - else { - Q931SetError(pTrunk,Q931E_LLCOMP, 7,0); - rc = Q931E_LLCOMP; - } - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_NetFac - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_NetFac(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_NetFac *pie = (Q931ie_NetFac*)OBuf; - ie *pIE = &pMsg->NetFac; - L3INT Off = 0; - L3INT Octet = 0; - L3INT x = 0; - L3INT IESize; - - *pIE = 0; - - pie->IEId = IBuf[Octet++]; - - /* Octet 2 */ - IESize = IBuf[Octet++]; - - pie->LenNetID = IBuf[Octet + Off]; /* full octet is used */ - Octet++; - - if (pie->LenNetID > 0) { - /* Octet 3.1 */ - pie->TypeNetID = (IBuf[Octet + Off] >> 4) & 0x0f; - pie->NetIDPlan = IBuf[Octet + Off] & 0x0f; - Off = Q931ReadExt(&IBuf[Octet], Off); - Off++; - - /* Octet 3.2*/ - for (x = 0; x < pie->LenNetID; x++) { - pie->NetID[x] = IBuf[Octet + Off] & 0x7f; - Off++; - } - } - - /* Octet 4*/ - pie->NetFac = IBuf[Octet + Off]; /* Full Octet is used */ - Octet++; - - Q931IESizeTest(Q931E_NETFAC); - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_NetFac) + x - 1; - pie->Size = (L3UCHAR)(sizeof(Q931ie_NetFac) + x - 1); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_NetFac - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_NetFac(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_NetFac *pIE = (Q931ie_NetFac*)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Beg = *Octet; - L3INT li; - L3INT x; - - OBuf[(*Octet)++] = Q931ie_NETWORK_SPECIFIC_FACILITIES; - li = (*Octet)++; - - /* Octet 3 */ - OBuf[(*Octet)++] = pIE->LenNetID; - - if (pIE->LenNetID > 0) { - /* Octet 3.1 */ - OBuf[(*Octet)++] = 0x80 | (pIE->TypeNetID << 4) | pIE->NetIDPlan; - - /* Octet 3.2 */ - for (x = 0; x LenNetID; x++) { - OBuf[(*Octet)++] = pIE->NetID[x]; - } - } - - /* Octet 4 */ - OBuf[(*Octet)++] = pIE->NetFac; - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_NotifInd - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_NotifInd(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_NotifInd *pie = (Q931ie_NotifInd*)OBuf; - ie *pIE = &pMsg->NotifInd; - L3INT Off = 0; - L3INT Octet = 0; - L3INT IESize; - - *pIE = 0; - - pie->IEId = IBuf[Octet++]; - - /* Octet 2*/ - IESize = IBuf[Octet++]; - - /* Octet 3 */ - pie->Notification = IBuf[Octet + Off] & 0x7f; - - Off = Q931ReadExt(&IBuf[Octet], Off); - Octet++; - - Q931IESizeTest(Q931E_NOTIFIND); - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_NotifInd); - pie->Size = sizeof(Q931ie_NotifInd); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_NotifInd - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_NotifInd(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_NotifInd *pIE = (Q931ie_NotifInd*)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Beg = *Octet; - L3INT li; - - OBuf[(*Octet)++] = Q931ie_NOTIFICATION_INDICATOR; - li = (*Octet)++; - - /* Octet 3 */ - OBuf[(*Octet)++] = pIE->Notification; - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_ProgInd - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_ProgInd(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_ProgInd *pie = (Q931ie_ProgInd*)OBuf; - ie *pIE = &pMsg->ProgInd; - L3INT Off = 0; - L3INT Octet = 0; - L3INT IESize; - - *pIE = 0; - - pie->IEId = IBuf[Octet++]; - - /* Octet 2 */ - IESize = IBuf[Octet++]; - - /* Octet 3 */ - pie->CodStand = (IBuf[Octet + Off] >> 5) & 0x03; - pie->Location = IBuf[Octet + Off] & 0x0f; - - Off = Q931ReadExt(&IBuf[Octet], Off); - Octet++; - - /* Octet 4 */ - pie->ProgDesc = IBuf[Octet + Off] & 0x7f; - Off = Q931ReadExt(&IBuf[Octet], Off); - Octet++; - - Q931IESizeTest(Q931E_PROGIND); - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_ProgInd); - pie->Size = sizeof(Q931ie_ProgInd); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_ProgInd - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset L3INTo OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_ProgInd(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_ProgInd *pIE = (Q931ie_ProgInd*)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Beg = *Octet; - L3INT li; - - OBuf[(*Octet)++] = Q931ie_PROGRESS_INDICATOR; - li = (*Octet)++; - - /* Octet 3 */ - OBuf[(*Octet)++] = 0x80 | (pIE->CodStand << 5) | pIE->Location; - - /* Octet 4 */ - OBuf[(*Octet)++] = 0x80 | pIE->ProgDesc; - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_RepeatInd - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_RepeatInd(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_RepeatInd *pie = (Q931ie_RepeatInd*)OBuf; - ie *pIE = &pMsg->RepeatInd; - L3INT Off = 0; - L3INT Octet = 0; - - *pIE = 0; - - pie->IEId = IBuf[Octet] & 0xf0; - pie->RepeatInd = IBuf[Octet] & 0x0f; - Octet ++; - - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_RepeatInd); - pie->Size = sizeof(Q931ie_RepeatInd); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_RepeatInd - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_RepeatInd(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_RepeatInd *pIE = (Q931ie_RepeatInd*)IBuf; - L3INT rc = 0; - /* L3INT Beg = *Octet; */ - - OBuf[(*Octet)++] = Q931ie_REPEAT_INDICATOR | pIE->RepeatInd; - - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_RevChargeInd - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_RevChargeInd(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - ie iE; - /* ie *pIE = &pMsg->RevChargeInd; */ - Q931SetIE(iE, *OOff); - - return iE; -} - -/***************************************************************************** - - Function: Q931Pie_RevChargeInd - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_RevChargeInd(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - L3BOOL RetCode = L3FALSE; - - NoWarning(OBuf); - NoWarning(IBuf); - - return RetCode; -} - -/***************************************************************************** - - Function: Q931Uie_RestartInd - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_RestartInd(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_RestartInd *pie = (Q931ie_RestartInd*)OBuf; - ie *pIE = &pMsg->RestartInd; - L3INT Off = 0; - L3INT Octet = 0; - L3INT IESize; - - *pIE = 0; - - pie->IEId = IBuf[Octet++]; - - /* Octet 2 */ - IESize = IBuf[Octet++]; - - /* Octet 3 */ - pie->Class = IBuf[Octet + Off] & 0x07; - pie->Spare = IBuf[Octet + Off] & 0x78; - - Off = Q931ReadExt(&IBuf[Octet], Off); - Octet++; - - Q931IESizeTest(Q931E_RESTARTIND); - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_RestartInd); - pie->Size = sizeof(Q931ie_RestartInd); - - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_RestartInd - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_RestartInd(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_RestartInd *pIE = (Q931ie_RestartInd*)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Beg = *Octet; - L3INT li; - - OBuf[(*Octet)++] = Q931ie_RESTART_INDICATOR; - li = (*Octet)++; - - /* Octet 3*/ - OBuf[(*Octet)++] = 0x80 | pIE->Class ; - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_Segment - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_Segment(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_Segment *pie = (Q931ie_Segment*)OBuf; - ie *pIE = &pMsg->Segment; - L3INT Off = 0; - L3INT Octet = 0; - L3INT IESize; - - *pIE = 0; - - pie->IEId = IBuf[Octet++]; - Octet++; - - /* Octet 2*/ - IESize = IBuf[Octet++]; - - /* Octet 3 */ - pie->FSI = (IBuf[Octet + Off] & 0x80) >> 7; - pie->NumSegRem = IBuf[Octet + Off] & 0x7f; - Octet++; - - /* Octet 4 */ - pie->SegType = IBuf[Octet + Off] & 0x7f; - Octet++; - - Q931IESizeTest(Q931E_SEGMENT); - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_Segment); - pie->Size = sizeof(Q931ie_Segment); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_Segment - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_Segment(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_Segment *pIE = (Q931ie_Segment*)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Beg = *Octet; - L3INT li; - - OBuf[(*Octet)++] = Q931ie_SEGMENTED_MESSAGE; - li = (*Octet)++; - - /* Octet 3 */ - OBuf[(*Octet)++] = (pIE->FSI << 7) | pIE->NumSegRem; - - /* Octet 4 */ - OBuf[(*Octet)++] = pIE->SegType; - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_SendComplete - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_SendComplete(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_SendComplete *pie = (Q931ie_SendComplete*)OBuf; - ie *pIE = &pMsg->SendComplete; - L3INT Off = 0; - L3INT Octet = 0; - - *pIE = 0; - Octet++; - - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_SendComplete); - pie->Size = sizeof(Q931ie_SendComplete); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_ProgInd - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_SendComplete(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - /* Q931ie_SendComplete * pIE = (Q931ie_SendComplete*)IBuf; */ - L3INT rc = Q931E_NO_ERROR; - /* L3INT Beg = *Octet; */ - - OBuf[(*Octet)++] = 0x80 | (L3UCHAR)Q931ie_SENDING_COMPLETE; - - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_Signal - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_Signal(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_Signal *pie = (Q931ie_Signal*)OBuf; - ie *pIE = &pMsg->Signal; - L3INT Off = 0; - L3INT Octet = 0; - L3INT IESize; - - *pIE = 0; - - pie->IEId = IBuf[Octet++]; - - /* Octet 2 */ - IESize = IBuf[Octet++]; - - /* Octet 3 */ - pie->Signal = IBuf[Octet + Off]; - Octet++; - - Q931IESizeTest(Q931E_SIGNAL); - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_Signal); - pie->Size = sizeof(Q931ie_Signal); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_Signal - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_Signal(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_Signal *pIE = (Q931ie_Signal*)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Beg = *Octet; - L3INT li; - - OBuf[(*Octet)++] = Q931ie_SIGNAL; - li = (*Octet)++; - - /* Octet 3 */ - OBuf[(*Octet)++] = pIE->Signal; - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_TransNetSel - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_TransNetSel(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_TransNetSel *pie = (Q931ie_TransNetSel*)OBuf; - ie *pIE = &pMsg->TransNetSel; - L3INT Off = 0; - L3INT Octet = 0; - L3INT x = 0; - L3INT l; - - *pIE = 0; - - pie->IEId = IBuf[Octet++]; - - /* Octet 2 */ - l = IBuf[Octet++] - 3; - - /* Octet 3 */ - pie->Type = (IBuf[Octet + Off] >> 4) & 0x07; - - Off = Q931ReadExt(&IBuf[Octet], Off); - Octet++; - - for (x = 0; x < l; x++) { - pie->NetID[x] = IBuf[Octet + Off] & 0x7f; - Off++; - } - - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_TransNetSel) + x - 1; - pie->Size = (L3UCHAR)(sizeof(Q931ie_TransNetSel) + x - 1); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_TransNetSel - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_TransNetSel(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_TransNetSel *pIE = (Q931ie_TransNetSel*)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Beg = *Octet; - L3INT li; - L3INT x; - L3INT l; - - OBuf[(*Octet)++] = Q931ie_TRANSIT_NETWORK_SELECTION; - li = (*Octet)++; - - /* Octet 3 */ - OBuf[(*Octet)++] = 0x80 | (pIE->Type << 4) | pIE->NetIDPlan; - - /* Octet 4 */ - l = pIE->Size - sizeof(Q931ie_TransNetSel) + 1; - for (x = 0; x < l; x++) { - OBuf[(*Octet)++] = pIE->NetID[x]; - } - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_UserUser - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_UserUser(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_UserUser *pie = (Q931ie_UserUser*)OBuf; - ie *pIE = &pMsg->UserUser; - L3INT Off = 0; - L3INT Octet = 0; - L3INT l; - - *pIE = 0; - - pie->IEId = IBuf[Octet++]; - - /* Octet 2 */ - l = IBuf[Octet++] - 1; - - /* Octet 3 */ - pie->ProtDisc = IBuf[Octet++]; - - for (Off = 0; Off < l; Off++) { - pie->User[Off] = IBuf[Octet + Off]; - } - - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_UserUser) + Off - 1; - pie->Size = (L3UCHAR)(sizeof(Q931ie_UserUser) + Off - 1); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_UserUser - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_UserUser(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_UserUser *pIE = (Q931ie_UserUser*)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Beg = *Octet; - L3INT li; - L3INT x; - L3INT l; - - OBuf[(*Octet)++] = Q931ie_USER_USER; - li = (*Octet)++; - - /* Octet 3 */ - OBuf[(*Octet)++] = pIE->ProtDisc; - - /* Octet 4 */ - l = pIE->Size - sizeof(Q931ie_UserUser) + 1; - for (x = 0; x < l; x++) { - OBuf[(*Octet)++] = pIE->User[x]; - } - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - -/***************************************************************************** - - Function: Q931Uie_GenericDigits - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_GenericDigits(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_GenericDigits *pie = (Q931ie_GenericDigits*)OBuf; - ie *pIE = &pMsg->GenericDigits; - L3INT Off = 0; - L3INT Octet = 0; - L3INT x; - L3INT IESize; - - *pIE = 0; - - /* Octet 1 */ - pie->IEId = IBuf[Octet++]; - - /* Octet 2 */ - IESize = IBuf[Octet++]; - - /* Octet 3 */ - pie->Type = (IBuf[Octet]) & 0x1F; - pie->Encoding = (IBuf[Octet] >> 5) & 0x07; - Octet++; - - /* Octet 4*/ - if (pie->Encoding == 0) { /* BCD Even */ - x = 0; - do { - pie->Digit[x++] = IBuf[Octet + Off] & 0x0f; - pie->Digit[x++] = (IBuf[Octet + Off] >> 4) & 0x0f; - Off++; - } while (Q931MoreIE()); - } else if (pie->Encoding == 1) { /* BCD Odd */ - x = 0; - do { - pie->Digit[x++] = IBuf[Octet + Off] & 0x0f; - if (Q931MoreIE()) { - pie->Digit[x] = (IBuf[Octet + Off] >> 4) & 0x0f; - } - x++; - Off++; - } while (Q931MoreIE()); - } else if (pie->Encoding == 2) { /* IA5 */ - x = 0; - do { - pie->Digit[x++] = IBuf[Octet + Off] & 0x7f; - Off++; - } while (Q931MoreIE()); - } else { - /* Binary encoding type unkown */ - Q931SetError(pTrunk, Q931E_GENERIC_DIGITS, Octet, Off); - return Q931E_GENERIC_DIGITS; - } - - Q931IESizeTest(Q931E_GENERIC_DIGITS); - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_CallingSub) + x - 1; - pie->Size = (L3UCHAR)(sizeof(Q931ie_CallingSub) + x - 1); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_GenericDigits - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ - -L3INT Q931Pie_GenericDigits(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - OBuf[(*Octet)++] = (Q931ie_GENERIC_DIGITS & 0xFF); - OBuf[(*Octet)++] = 0; - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Uie_ChangeStatus - - Parameters: pIE[OUT] ptr to Information Element id. - IBuf[IN] ptr to a packed ie. - OBuf[OUT] ptr to buffer for Unpacked ie. - IOff[IN\OUT] Input buffer offset - OOff[IN\OUT] Output buffer offset - - Ibuf and OBuf points directly to buffers. The IOff and OOff - must be updated, but are otherwise not used in the ie unpack. - - Return Value: Error Message - -*****************************************************************************/ -L3INT Q931Uie_ChangeStatus(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff) -{ - Q931ie_ChangeStatus *pie = (Q931ie_ChangeStatus*)OBuf; - ie *pIE = &pMsg->ChangeStatus; - L3INT Off = 0; - L3INT Octet = 0; - L3INT IESize; - - *pIE = 0; - - pie->IEId = IBuf[Octet++]; - - /* Octet 2 */ - IESize = IBuf[Octet++]; - - /* Octet 3 */ - pie->Preference = (IBuf[Octet + Off] >> 6) & 0x01; - pie->Spare = IBuf[Octet + Off] & 0x38; - pie->NewStatus = IBuf[Octet + Off] & 0x07; - Octet++; - - Q931SetIE(*pIE, *OOff); - - *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_ChangeStatus); - pie->Size = sizeof(Q931ie_ChangeStatus); - - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pie_ChangeStatus - - Parameters: IBuf[IN] Ptr to struct. - OBuf[OUT] Ptr tp packed output buffer. - Octet[IN/OUT] Offset into OBuf. - - Return Value: Error code, 0 = OK - -*****************************************************************************/ -L3INT Q931Pie_ChangeStatus(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - Q931ie_ChangeStatus *pIE = (Q931ie_ChangeStatus*)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Beg = *Octet; - L3INT li; - - OBuf[(*Octet)++] = Q931ie_CHANGE_STATUS; - li = (*Octet)++; - - /* Octet 3 */ - OBuf[(*Octet)++] = 0x80 | pIE->NewStatus | ((pIE->Preference & 0x01) << 6); - - OBuf[li] = (L3UCHAR)((*Octet) - Beg) - 2; - return rc; -} - - - -L3INT Q931Uie_Generic(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *IOff, L3INT *OOff) -{ - L3INT Octet = 0; - L3UCHAR id = 0; - - /* id */ - id = IBuf[Octet++]; - - /* Length */ - Octet += IBuf[Octet]; - Octet++; - - Q931Log(pTrunk, Q931_LOG_DEBUG, "Discarding IE %#hhx with length %d\n", id, Octet - 2); - - *IOff += Octet; - return Q931E_NO_ERROR; -} - -L3INT Q931Pie_Generic(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet) -{ - /* do nothing */ - return Q931E_NO_ERROR; -} diff --git a/libs/freetdm/src/isdn/Q931mes.c b/libs/freetdm/src/isdn/Q931mes.c deleted file mode 100644 index 8e34a170e1..0000000000 --- a/libs/freetdm/src/isdn/Q931mes.c +++ /dev/null @@ -1,1870 +0,0 @@ -/***************************************************************************** - - FileName: Q931mes.c - - Contents: Pack/Unpack functions. These functions will unpack a Q931 - message from the bit packed original format into structs - that contains variables sized by the user. It will also pack - the struct back into a Q.931 message as required. - - See q931.h for description. - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -*****************************************************************************/ - -#include "Q931.h" - -/** - * Q931MesgHeader - * \brief Create Q.931 Message header - */ -L3INT Q931MesgHeader(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *mes, L3UCHAR *OBuf, L3INT Size, L3INT *IOff) -{ - L3INT Octet = *IOff; - - Q931Log(pTrunk, Q931_LOG_DEBUG, "Creating Q.931 Message Header:\n ProtDisc %d (%#x), CRV %d (%#x), CRVflag: %d (%#x), MesType: %d (%#x)\n", - mes->ProtDisc, mes->ProtDisc, mes->CRV, mes->CRV, mes->CRVFlag, mes->CRVFlag, mes->MesType, mes->MesType); - - OBuf[Octet++] = mes->ProtDisc; /* Protocol discriminator */ - if (!Q931_IS_BRI(pTrunk)) { - OBuf[Octet++] = 2; /* length is 2 octets */ - OBuf[Octet++] = (L3UCHAR)((mes->CRV >> 8) & 0x7f) | ((mes->CRVFlag << 7) & 0x80); /* msb */ - OBuf[Octet++] = (L3UCHAR) (mes->CRV & 0xff); /* lsb */ - } else { - OBuf[Octet++] = 1; /* length is 1 octet */ - OBuf[Octet++] = (L3UCHAR) (mes->CRV & 0x7f) | ((mes->CRVFlag << 7) & 0x80); /* CRV & flag */ - } - OBuf[Octet++] = mes->MesType; /* message header */ - - *IOff = Octet; - return 0; -} - - -/***************************************************************************** - - Function: Q931Umes_Alerting - -*****************************************************************************/ - -L3INT Q931Umes_Alerting(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_BEARER_CAPABILITY: - case Q931ie_CHANNEL_IDENTIFICATION: - case Q931ie_PROGRESS_INDICATOR: - case Q931ie_DISPLAY: - case Q931ie_SIGNAL: - case Q931ie_HIGH_LAYER_COMPATIBILITY: - case Q931ie_USER_USER: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_Alerting - -*****************************************************************************/ -L3INT Q931Pmes_Alerting(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Bearer capability */ - if (Q931IsIEPresent(pMes->BearerCap)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_BEARER_CAPABILITY](pTrunk, Q931GetIEPtr(pMes->BearerCap,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Channel Identification */ - if (Q931IsIEPresent(pMes->ChanID)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CHANNEL_IDENTIFICATION](pTrunk, Q931GetIEPtr(pMes->ChanID,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Progress indicator */ - if (Q931IsIEPresent(pMes->ProgInd)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_PROGRESS_INDICATOR](pTrunk, Q931GetIEPtr(pMes->ProgInd,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Signal */ - if (Q931IsIEPresent(pMes->Signal)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_SIGNAL](pTrunk, Q931GetIEPtr(pMes->Signal,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* High Layer Compatibility */ - if (Q931IsIEPresent(pMes->HLComp)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_HIGH_LAYER_COMPATIBILITY](pTrunk, Q931GetIEPtr(pMes->HLComp,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_CallProceeding - -*****************************************************************************/ -L3INT Q931Umes_CallProceeding(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_BEARER_CAPABILITY: - case Q931ie_CHANNEL_IDENTIFICATION: - case Q931ie_PROGRESS_INDICATOR: - case Q931ie_DISPLAY: - case Q931ie_HIGH_LAYER_COMPATIBILITY: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_CallProceeding - -*****************************************************************************/ -L3INT Q931Pmes_CallProceeding(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Bearer capability */ - if (Q931IsIEPresent(pMes->BearerCap)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_BEARER_CAPABILITY](pTrunk, Q931GetIEPtr(pMes->BearerCap,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Channel Identification */ - if (Q931IsIEPresent(pMes->ChanID)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CHANNEL_IDENTIFICATION](pTrunk, Q931GetIEPtr(pMes->ChanID,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Progress indicator */ - if (Q931IsIEPresent(pMes->ProgInd)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_PROGRESS_INDICATOR](pTrunk, Q931GetIEPtr(pMes->ProgInd,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* High Layer Compatibility */ - if (Q931IsIEPresent(pMes->HLComp)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_HIGH_LAYER_COMPATIBILITY](pTrunk, Q931GetIEPtr(pMes->HLComp,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_CongestionControl - -*****************************************************************************/ -L3INT Q931Umes_CongestionControl(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3BOOL RetCode = L3FALSE; - - NoWarning(mes); - NoWarning(IBuf); - - return RetCode; -} - - -/***************************************************************************** - - Function: Q931Pmes_CongestionControl - -*****************************************************************************/ -L3INT Q931Pmes_CongestionControl(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - L3BOOL RetCode = L3FALSE; - - NoWarning(OBuf); - NoWarning(IBuf); - - *OSize = 0; - return RetCode; -} - -/***************************************************************************** - - Function: Q931Umes_Connect - -*****************************************************************************/ -L3INT Q931Umes_Connect(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_BEARER_CAPABILITY: - case Q931ie_CHANNEL_IDENTIFICATION: - case Q931ie_PROGRESS_INDICATOR: - case Q931ie_DISPLAY: - case Q931ie_DATETIME: - case Q931ie_SIGNAL: - case Q931ie_LOW_LAYER_COMPATIBILITY: - case Q931ie_HIGH_LAYER_COMPATIBILITY: - case Q931ie_CONNECTED_NUMBER: /* not actually used, seen while testing BRI PTMP TE */ - case Q931ie_USER_USER: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - - default: - Q931Log(pTrunk, Q931_LOG_ERROR, "Illegal IE %#hhx in Connect Message\n", IBuf[IOff]); - - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_Connect - -*****************************************************************************/ -L3INT Q931Pmes_Connect(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Bearer capability */ - if (Q931IsIEPresent(pMes->BearerCap)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_BEARER_CAPABILITY](pTrunk, Q931GetIEPtr(pMes->BearerCap,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Channel Identification */ - if (Q931IsIEPresent(pMes->ChanID)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CHANNEL_IDENTIFICATION](pTrunk, Q931GetIEPtr(pMes->ChanID,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Progress indicator */ - if (Q931IsIEPresent(pMes->ProgInd)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_PROGRESS_INDICATOR](pTrunk, Q931GetIEPtr(pMes->ProgInd,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Date/Time */ - if (Q931IsIEPresent(pMes->DateTime)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DATETIME](pTrunk, Q931GetIEPtr(pMes->DateTime,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Signal */ - if (Q931IsIEPresent(pMes->Signal)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_SIGNAL](pTrunk, Q931GetIEPtr(pMes->Signal,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Low Layer Compatibility */ - if (Q931IsIEPresent(pMes->LLComp)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_LOW_LAYER_COMPATIBILITY](pTrunk, Q931GetIEPtr(pMes->LLComp,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* High Layer Compatibility */ - if (Q931IsIEPresent(pMes->HLComp)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_HIGH_LAYER_COMPATIBILITY](pTrunk, Q931GetIEPtr(pMes->HLComp,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_ConnectAck - -*****************************************************************************/ -L3INT Q931Umes_ConnectAck(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_DISPLAY: - case Q931ie_SIGNAL: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - - -/***************************************************************************** - - Function: Q931Pmes_ConnectAck - -*****************************************************************************/ -L3INT Q931Pmes_ConnectAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Signal */ - if (Q931IsIEPresent(pMes->Signal)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_SIGNAL](pTrunk, Q931GetIEPtr(pMes->Signal,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_Disconnect - -*****************************************************************************/ -L3INT Q931Umes_Disconnect(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_CAUSE: - case Q931ie_PROGRESS_INDICATOR: - case Q931ie_DISPLAY: - case Q931ie_SIGNAL: - case Q931ie_FACILITY: - case Q931ie_USER_USER: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_Disconnect - -*****************************************************************************/ -L3INT Q931Pmes_Disconnect(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Cause */ - if (Q931IsIEPresent(pMes->Cause)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CAUSE](pTrunk, Q931GetIEPtr(pMes->Cause,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Progress indicator */ - if (Q931IsIEPresent(pMes->ProgInd)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_PROGRESS_INDICATOR](pTrunk, Q931GetIEPtr(pMes->ProgInd,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Signal */ - if (Q931IsIEPresent(pMes->Signal)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_SIGNAL](pTrunk, Q931GetIEPtr(pMes->Signal,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_Information - -*****************************************************************************/ -L3INT Q931Umes_Information(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_SENDING_COMPLETE: - case Q931ie_DISPLAY: - case Q931ie_KEYPAD_FACILITY: - case Q931ie_CALLED_PARTY_NUMBER: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_Information - -*****************************************************************************/ -L3INT Q931Pmes_Information(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Sending Complete */ - if (Q931IsIEPresent(pMes->SendComplete)) { - OBuf[Octet++] = (L3UCHAR)(pMes->SendComplete & 0x00ff); - } - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Keypad Facility */ - if (Q931IsIEPresent(pMes->KeypadFac)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_KEYPAD_FACILITY](pTrunk, Q931GetIEPtr(pMes->KeypadFac,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Signal */ - if (Q931IsIEPresent(pMes->Signal)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_SIGNAL](pTrunk, Q931GetIEPtr(pMes->Signal,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Called Party number */ - if (Q931IsIEPresent(pMes->CalledNum)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLED_PARTY_NUMBER](pTrunk, Q931GetIEPtr(pMes->CalledNum,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_Notify - -*****************************************************************************/ -L3INT Q931Umes_Notify(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_BEARER_CAPABILITY: - case Q931ie_NOTIFICATION_INDICATOR: - case Q931ie_DISPLAY: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_Notify - -*****************************************************************************/ -L3INT Q931Pmes_Notify(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Bearer capability */ - if (Q931IsIEPresent(pMes->BearerCap)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_BEARER_CAPABILITY](pTrunk, Q931GetIEPtr(pMes->BearerCap,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_Progress - -*****************************************************************************/ -L3INT Q931Umes_Progress(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_BEARER_CAPABILITY: - case Q931ie_CAUSE: - case Q931ie_PROGRESS_INDICATOR: - case Q931ie_DISPLAY: - case Q931ie_HIGH_LAYER_COMPATIBILITY: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_Progress - -*****************************************************************************/ -L3INT Q931Pmes_Progress(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Bearer capability */ - if (Q931IsIEPresent(pMes->BearerCap)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_BEARER_CAPABILITY](pTrunk, Q931GetIEPtr(pMes->BearerCap,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Cause */ - if (Q931IsIEPresent(pMes->Cause)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CAUSE](pTrunk, Q931GetIEPtr(pMes->Cause,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Progress indicator */ - if (Q931IsIEPresent(pMes->ProgInd)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_PROGRESS_INDICATOR](pTrunk, Q931GetIEPtr(pMes->ProgInd,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* High Layer Compatibility */ - if (Q931IsIEPresent(pMes->HLComp)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_HIGH_LAYER_COMPATIBILITY](pTrunk, Q931GetIEPtr(pMes->HLComp,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_Release - -*****************************************************************************/ -L3INT Q931Umes_Release(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_CAUSE: - case Q931ie_DISPLAY: - case Q931ie_SIGNAL: - case Q931ie_USER_USER: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_Release - -*****************************************************************************/ -L3INT Q931Pmes_Release(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Cause */ - if (Q931IsIEPresent(pMes->Cause)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CAUSE](pTrunk, Q931GetIEPtr(pMes->Cause,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Signal */ - if (Q931IsIEPresent(pMes->Signal)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_SIGNAL](pTrunk, Q931GetIEPtr(pMes->Signal,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_ReleaseComplete - -*****************************************************************************/ -L3INT Q931Umes_ReleaseComplete(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_CAUSE: - case Q931ie_DISPLAY: - case Q931ie_SIGNAL: - case Q931ie_USER_USER: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_ReleaseComplete - -*****************************************************************************/ -L3INT Q931Pmes_ReleaseComplete(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Cause */ - if (Q931IsIEPresent(pMes->Cause)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CAUSE](pTrunk, Q931GetIEPtr(pMes->Cause,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Signal */ - if (Q931IsIEPresent(pMes->Signal)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_SIGNAL](pTrunk, Q931GetIEPtr(pMes->Signal,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_Restart - -*****************************************************************************/ -L3INT Q931Umes_Restart(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_CHANNEL_IDENTIFICATION: - case Q931ie_DISPLAY: - case Q931ie_RESTART_INDICATOR: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_Restart - -*****************************************************************************/ -L3INT Q931Pmes_Restart(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* ChanID */ - if (Q931IsIEPresent(pMes->ChanID)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CHANNEL_IDENTIFICATION](pTrunk, Q931GetIEPtr(pMes->ChanID,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* RestartInd */ - if (Q931IsIEPresent(pMes->RestartInd)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_RESTART_INDICATOR](pTrunk, Q931GetIEPtr(pMes->RestartInd,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_RestartAck - -*****************************************************************************/ -L3INT Q931Umes_RestartAck(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT IOff, L3INT Size) -{ - Q931mes_Generic *mes = (Q931mes_Generic*)OBuf; - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_CHANNEL_IDENTIFICATION: - case Q931ie_DISPLAY: - case Q931ie_RESTART_INDICATOR: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_RestartAck - -*****************************************************************************/ -L3INT Q931Pmes_RestartAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* ChanID */ - if (Q931IsIEPresent(pMes->ChanID)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CHANNEL_IDENTIFICATION](pTrunk, Q931GetIEPtr(pMes->ChanID,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* RestartInd */ - if (Q931IsIEPresent(pMes->RestartInd)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_RESTART_INDICATOR](pTrunk, Q931GetIEPtr(pMes->RestartInd,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_Resume - -*****************************************************************************/ -L3INT Q931Umes_Resume(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_CALL_IDENTITY: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_Resume - -*****************************************************************************/ -L3INT Q931Pmes_Resume(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Call Identity */ - if (Q931IsIEPresent(pMes->CallID)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALL_IDENTITY](pTrunk, Q931GetIEPtr(pMes->CallID,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_ResumeAck - -*****************************************************************************/ -L3INT Q931Umes_ResumeAck(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_CHANNEL_IDENTIFICATION: - case Q931ie_DISPLAY: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - - -/***************************************************************************** - - Function: Q931Pmes_ResumeAck - -*****************************************************************************/ -L3INT Q931Pmes_ResumeAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Channel Identification */ - if (Q931IsIEPresent(pMes->ChanID)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CHANNEL_IDENTIFICATION](pTrunk, Q931GetIEPtr(pMes->ChanID,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_ResumeReject - -*****************************************************************************/ -L3INT Q931Umes_ResumeReject(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_CAUSE: - case Q931ie_DISPLAY: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - - -/***************************************************************************** - - Function: Q931Pmes_ResumeReject - -*****************************************************************************/ -L3INT Q931Pmes_ResumeReject(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Cause */ - if (Q931IsIEPresent(pMes->Cause)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CAUSE](pTrunk, Q931GetIEPtr(pMes->Cause,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -L3INT Q931Umes_Segment(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT OOff) -{ - L3INT i = IOff; - - return IOff - i; -} - -L3INT Q931Pmes_Segment(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - L3BOOL RetCode = L3FALSE; - - *OSize = 0; - return RetCode; -} - -/***************************************************************************** - - Function: Q931Umes_Setup - -*****************************************************************************/ -L3INT Q931Umes_Setup(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT ir = 0; - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_SENDING_COMPLETE: - IOff++; - break; - - case Q931ie_BEARER_CAPABILITY: - case Q931ie_CHANNEL_IDENTIFICATION: - case Q931ie_PROGRESS_INDICATOR: - case Q931ie_NETWORK_SPECIFIC_FACILITIES: - case Q931ie_DISPLAY: - case Q931ie_DATETIME: - case Q931ie_KEYPAD_FACILITY: - case Q931ie_SIGNAL: - case Q931ie_CALLING_PARTY_NUMBER: - case Q931ie_CALLING_PARTY_SUBADDRESS: - case Q931ie_CALLED_PARTY_NUMBER: - case Q931ie_CALLED_PARTY_SUBADDRESS: - case Q931ie_TRANSIT_NETWORK_SELECTION: - case Q931ie_LOW_LAYER_COMPATIBILITY: - case Q931ie_HIGH_LAYER_COMPATIBILITY: - case Q931ie_FACILITY: - case Q931ie_USER_USER: - case Q931ie_REDIRECTING_NUMBER: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - - case Q931ie_REPEAT_INDICATOR: - if (ir < 2) { - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - ir++; - } else { - return Q931E_ILLEGAL_IE; - } - break; - - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_Setup - - Decription: Pack a Q931mes_Generic into a real Q.931 message. The user will - set up a SETUP message and issue this to the stack where it - is processed by Q931ProcSetup that processes and validates - it before it actually sends it out. This function is called - to compute the real Q.931 message. - - Parameters: IBuf[IN] Ptr to un-packed struct - ISize[IN] Size of input buffer (unpacked message). - OBuf[OUT] Ptr to packed 'octet' wise message. - OSize[OUT] Size of packed message. - - Called By: Q931ProcSetup - -*****************************************************************************/ -L3INT Q931Pmes_Setup(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Sending Complete */ - if (Q931IsIEPresent(pMes->SendComplete)) { - OBuf[Octet++] = (L3UCHAR)Q931ie_SENDING_COMPLETE & 0xff; - } - - /* Repeat Indicator */ - if (Q931IsIEPresent(pMes->RepeatInd)) { - OBuf[Octet++] = (L3UCHAR)Q931ie_REPEAT_INDICATOR & 0xff; - } - - /* Bearer capability */ - if (Q931IsIEPresent(pMes->BearerCap)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_BEARER_CAPABILITY](pTrunk, Q931GetIEPtr(pMes->BearerCap,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } else { - rc = Q931E_BEARERCAP; - } - - /* Channel Identification */ - if (Q931IsIEPresent(pMes->ChanID)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CHANNEL_IDENTIFICATION](pTrunk, Q931GetIEPtr(pMes->ChanID,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Progress indicator */ - if (Q931IsIEPresent(pMes->ProgInd)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_PROGRESS_INDICATOR](pTrunk, Q931GetIEPtr(pMes->ProgInd,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Network spesific facilities */ - if (Q931IsIEPresent(pMes->NetFac)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_NETWORK_SPECIFIC_FACILITIES](pTrunk, Q931GetIEPtr(pMes->NetFac,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Date/Time */ - if (Q931IsIEPresent(pMes->DateTime)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DATETIME](pTrunk, Q931GetIEPtr(pMes->DateTime,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Keypad Facility */ - if (Q931IsIEPresent(pMes->KeypadFac)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_KEYPAD_FACILITY](pTrunk, Q931GetIEPtr(pMes->KeypadFac,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Signal */ - if (Q931IsIEPresent(pMes->Signal)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_SIGNAL](pTrunk, Q931GetIEPtr(pMes->Signal,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Calling Party Number */ - if (Q931IsIEPresent(pMes->CallingNum)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLING_PARTY_NUMBER](pTrunk, Q931GetIEPtr(pMes->CallingNum,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Calling Party Subaddress */ - if (Q931IsIEPresent(pMes->CallingSub)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLING_PARTY_SUBADDRESS](pTrunk, Q931GetIEPtr(pMes->CallingSub,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Called Party number */ - if (Q931IsIEPresent(pMes->CalledNum)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLED_PARTY_NUMBER](pTrunk, Q931GetIEPtr(pMes->CalledNum,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Called party subaddress */ - if (Q931IsIEPresent(pMes->CalledSub)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLED_PARTY_SUBADDRESS](pTrunk, Q931GetIEPtr(pMes->CalledSub,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Transit network selection */ - if (Q931IsIEPresent(pMes->TransNetSel)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_TRANSIT_NETWORK_SELECTION](pTrunk, Q931GetIEPtr(pMes->TransNetSel,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Repeat Indicator */ - if (Q931IsIEPresent(pMes->LLRepeatInd)) { - rc = Q931E_UNKNOWN_IE;/* TODO */ - } - - /* Low Layer Compatibility */ - if (Q931IsIEPresent(pMes->LLComp)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_LOW_LAYER_COMPATIBILITY](pTrunk, Q931GetIEPtr(pMes->LLComp,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* High Layer Compatibility */ - if (Q931IsIEPresent(pMes->HLComp)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_HIGH_LAYER_COMPATIBILITY](pTrunk, Q931GetIEPtr(pMes->HLComp,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_SetupAck - -*****************************************************************************/ -L3INT Q931Umes_SetupAck(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_CHANNEL_IDENTIFICATION: - case Q931ie_PROGRESS_INDICATOR: - case Q931ie_DISPLAY: - case Q931ie_SIGNAL: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_SetupAck - -*****************************************************************************/ -L3INT Q931Pmes_SetupAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Channel Identification */ - if (Q931IsIEPresent(pMes->ChanID)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CHANNEL_IDENTIFICATION](pTrunk, Q931GetIEPtr(pMes->ChanID,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Progress indicator */ - if (Q931IsIEPresent(pMes->ProgInd)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_PROGRESS_INDICATOR](pTrunk, Q931GetIEPtr(pMes->ProgInd,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Signal */ - if (Q931IsIEPresent(pMes->Signal)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_SIGNAL](pTrunk, Q931GetIEPtr(pMes->Signal,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_Status - -*****************************************************************************/ -L3INT Q931Umes_Status(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_CAUSE: - case Q931ie_CALL_STATE: - case Q931ie_DISPLAY: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - - -/***************************************************************************** - - Function: Q931Pmes_Status - -*****************************************************************************/ -L3INT Q931Pmes_Status(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Cause */ - if (Q931IsIEPresent(pMes->Cause)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CAUSE](pTrunk, Q931GetIEPtr(pMes->Cause,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Call State */ - if (Q931IsIEPresent(pMes->CallState)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALL_STATE](pTrunk, Q931GetIEPtr(pMes->CallState,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_StatusEnquiry - -*****************************************************************************/ -L3INT Q931Umes_StatusEnquiry(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_DISPLAY: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_StatusEnquiry - -*****************************************************************************/ -L3INT Q931Pmes_StatusEnquiry(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_Suspend - -*****************************************************************************/ -L3INT Q931Umes_Suspend(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_CALL_IDENTITY: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_Suspend - -*****************************************************************************/ -L3INT Q931Pmes_Suspend(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Call Identity */ - if (Q931IsIEPresent(pMes->CallID)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALL_IDENTITY](pTrunk, Q931GetIEPtr(pMes->CallID,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_SuspendAck - -*****************************************************************************/ -L3INT Q931Umes_SuspendAck(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_DISPLAY: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_SuspendAck - -*****************************************************************************/ -L3INT Q931Pmes_SuspendAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_SuspendReject - -*****************************************************************************/ -L3INT Q931Umes_SuspendReject(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_CAUSE: - case Q931ie_DISPLAY: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_SuspendReject - -*****************************************************************************/ -L3INT Q931Pmes_SuspendReject(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Cause */ - if (Q931IsIEPresent(pMes->Cause)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CAUSE](pTrunk, Q931GetIEPtr(pMes->Cause,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_UserInformation - -*****************************************************************************/ -L3INT Q931Umes_UserInformation(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT I, L3INT O) -{ - L3BOOL RetCode = L3FALSE; - - NoWarning(mes); - NoWarning(IBuf); - - return RetCode; -} - -/***************************************************************************** - - Function: Q931Pmes_UserInformation - -*****************************************************************************/ -L3INT Q931Pmes_UserInformation(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - L3BOOL RetCode = L3FALSE; - - NoWarning(OBuf); - NoWarning(IBuf); - - *OSize = 0; - - return RetCode; -} - -/***************************************************************************** - - Function: Q931Umes_Service - -*****************************************************************************/ -L3INT Q931Umes_Service(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_CHANNEL_IDENTIFICATION: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - case Q931ie_CHANGE_STATUS: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_Service - -*****************************************************************************/ -L3INT Q931Pmes_Service(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Display */ - if (Q931IsIEPresent(pMes->ChanID)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CHANNEL_IDENTIFICATION](pTrunk, Q931GetIEPtr(pMes->ChanID,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - if (Q931IsIEPresent(pMes->ChangeStatus)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CHANGE_STATUS](pTrunk, Q931GetIEPtr(pMes->ChangeStatus,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} - -/***************************************************************************** - - Function: Q931Umes_ServiceAck - -*****************************************************************************/ -L3INT Q931Umes_ServiceAck(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - - while (IOff < Size) { - switch (IBuf[IOff]) { - case Q931ie_CHANNEL_IDENTIFICATION: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - case Q931ie_CHANGE_STATUS: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_ServiceAck - -*****************************************************************************/ -L3INT Q931Pmes_ServiceAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT rc = Q931E_NO_ERROR; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - if (Q931IsIEPresent(pMes->ChangeStatus)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CHANGE_STATUS](pTrunk, Q931GetIEPtr(pMes->ChangeStatus,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - if (Q931IsIEPresent(pMes->ChanID)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CHANNEL_IDENTIFICATION](pTrunk, Q931GetIEPtr(pMes->ChanID,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} diff --git a/libs/freetdm/src/isdn/Q932mes.c b/libs/freetdm/src/isdn/Q932mes.c deleted file mode 100644 index 574499a241..0000000000 --- a/libs/freetdm/src/isdn/Q932mes.c +++ /dev/null @@ -1,286 +0,0 @@ -/***************************************************************************** - - FileName: Q932mes.c - - Contents: Q.932 Message Encoders/Decoders - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -#include "Q931.h" - -/***************************************************************************** - - Function: Q932Umes_Facility - -*****************************************************************************/ - -L3INT Q932Umes_Facility(Q931_TrunkInfo_t *pTrunk,L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - - /* TODO */ - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_Facility - -*****************************************************************************/ -L3INT Q932Pmes_Facility(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - L3BOOL RetCode = L3FALSE; - - NoWarning(OBuf); - NoWarning(IBuf); - - return RetCode; -} - -/***************************************************************************** - - Function: Q932Umes_Hold - -*****************************************************************************/ - -L3INT Q932Umes_Hold(Q931_TrunkInfo_t *pTrunk,L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - - /* TODO */ - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_Hold - -*****************************************************************************/ -L3INT Q932Pmes_Hold(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - L3BOOL RetCode = L3FALSE; - - NoWarning(OBuf); - NoWarning(IBuf); - - return RetCode; -} - -/***************************************************************************** - - Function: Q932Umes_HoldAck - -*****************************************************************************/ - -L3INT Q932Umes_HoldAck(Q931_TrunkInfo_t *pTrunk,L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - - /* TODO */ - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_HoldAck - -*****************************************************************************/ -L3INT Q932Pmes_HoldAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - L3BOOL RetCode = L3FALSE; - - NoWarning(OBuf); - NoWarning(IBuf); - - return RetCode; -} - -/***************************************************************************** - - Function: Q932Umes_HoldReject - -*****************************************************************************/ - -L3INT Q932Umes_HoldReject(Q931_TrunkInfo_t *pTrunk,L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - - /* TODO */ - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_HoldReject - -*****************************************************************************/ -L3INT Q932Pmes_HoldReject(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - L3BOOL RetCode = L3FALSE; - - NoWarning(OBuf); - NoWarning(IBuf); - - return RetCode; -} - -/***************************************************************************** - - Function: Q932Umes_Register - -*****************************************************************************/ - -L3INT Q932Umes_Register(Q931_TrunkInfo_t *pTrunk,L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - - /* TODO */ - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_Register - -*****************************************************************************/ -L3INT Q932Pmes_Register(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - L3BOOL RetCode = L3FALSE; - - NoWarning(OBuf); - NoWarning(IBuf); - - return RetCode; -} - -/***************************************************************************** - - Function: Q932Umes_Retrieve - -*****************************************************************************/ - -L3INT Q932Umes_Retrieve(Q931_TrunkInfo_t *pTrunk,L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - - /* TODO */ - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_Retrieve - -*****************************************************************************/ -L3INT Q932Pmes_Retrieve(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - L3BOOL RetCode = L3FALSE; - - NoWarning(OBuf); - NoWarning(IBuf); - - return RetCode; -} - -/***************************************************************************** - - Function: Q932Umes_RetrieveAck - -*****************************************************************************/ - -L3INT Q932Umes_RetrieveAck(Q931_TrunkInfo_t *pTrunk,L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - - /* TODO */ - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_RetrieveAck - -*****************************************************************************/ -L3INT Q932Pmes_RetrieveAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - L3BOOL RetCode = L3FALSE; - - NoWarning(OBuf); - NoWarning(IBuf); - - return RetCode; -} - -/***************************************************************************** - - Function: Q932Umes_RetrieveReject - -*****************************************************************************/ - -L3INT Q932Umes_RetrieveReject(Q931_TrunkInfo_t *pTrunk,L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT OOff = 0; - - /* TODO */ - - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: Q931Pmes_RetrieveReject - -*****************************************************************************/ -L3INT Q932Pmes_RetrieveReject(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - L3BOOL RetCode = L3FALSE; - - NoWarning(OBuf); - NoWarning(IBuf); - - return RetCode; -} diff --git a/libs/freetdm/src/isdn/include/5ESS.h b/libs/freetdm/src/isdn/include/5ESS.h deleted file mode 100644 index 882b257395..0000000000 --- a/libs/freetdm/src/isdn/include/5ESS.h +++ /dev/null @@ -1,103 +0,0 @@ -/****************************************************************************** - - FileName: 5ESS.h - - Contents: Header and definition for the AT&T 5ESS ISDN dialect. The - header contains the following parts: - - - Definition of codes - - Definition of information elements (5ESSie_). - - Definition of messages (5ESSmes_). - - Function prototypes. - - Description: The AT&T 5ESS ISDN dialect here covers ???? - - Related Files: 5ESS.h AT&T 5ESS ISDN Definitions - 5ESSie.c AT&T 5ESS ISDN IE encoders/coders (not extant yet) - See Q931ie.c for IE encoders/coders - 5ESSStateTE.c AT&T 5ESS ISDN TE State Engine - 5ESSStateNT.c AT&T 5ESS ISDN NT State Engine - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Copyright (c) 2007, Michael Jerris. All rights reserved. - email:mike@jerris.com - - Copyright (c) 2007, Michael S. Collins, All rights reserved. - email:mcollins@fcnetwork.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -******************************************************************************/ - -#ifndef _5ESS_NL -#define _5ESS_NL - -#include "Q931.h" - -/***************************************************************************** - - Q.931 Message codes - Only 5ESS specific message and ie types - here the rest are inherited from Q931.h - -*****************************************************************************/ - - -/***************************************************************************** - - Q.931 Message Pack/Unpack functions. Implemented in 5ESSmes.c - Note: Because C variables may not begin with numeric digit, all identifiers - are prefixed with "ATT5ESS" instead of a bare "5ESS" - -*****************************************************************************/ -L3INT ATT5ESSUmes_Setup(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT IOff, L3INT Size); -L3INT ATT5ESSPmes_Setup(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT ATT5ESSUmes_SetupAck(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT IOff, L3INT Size); -L3INT ATT5ESSPmes_SetupAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); - -L3INT ATT5ESSUmes_0x07(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size); -L3INT ATT5ESSPmes_0x07(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT ATT5ESSUmes_0x0f(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size); -L3INT ATT5ESSPmes_0x0f(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); - - - -/***************************************************************************** - - Q.931 Process Function Prototyping. Implemented in 5ESSStateTE.c - -*****************************************************************************/ -L3INT ATT5ESSProc0x0fTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom); -L3INT ATT5ESSProc0x07TE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom); - - -void ATT5ESSCreateTE(L3UCHAR i); -void ATT5ESSCreateNT(L3UCHAR i); - -#endif /* _5ESS_NL */ diff --git a/libs/freetdm/src/isdn/include/DMS.h b/libs/freetdm/src/isdn/include/DMS.h deleted file mode 100644 index 605a61aa6e..0000000000 --- a/libs/freetdm/src/isdn/include/DMS.h +++ /dev/null @@ -1,91 +0,0 @@ -/****************************************************************************** - - FileName: national.h - - Contents: Header and definition for the National ISDN dialect. The - header contents the following parts: - - Definition of codes - - Definition of information elements (nationalie_). - - Definition of messages (nationalmes_). - - Function prototypes. - - Description: The National ISDN dialect here covers ???? - - Related Files: national.h National ISDN Definitions - nationalie.c National ISDN IE encoders/coders - nationalStateTE.c National ISDN TE State Engine - nationalStateNT.c National ISDN NT State Engine - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Copyright (c) 2007, Michael Jerris. All rights reserved. - email:mike@jerris.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -******************************************************************************/ - -#ifndef _DMS_NL -#define _DMS_NL - -#include "Q931.h" - -/***************************************************************************** - - Q.931 Message codes - Only National specific message and ie types - here the rest are inherited from national.h - -*****************************************************************************/ - - -/***************************************************************************** - - Q.931 Message Pack/Unpack functions. Implemented in nationalmes.c - -*****************************************************************************/ -L3INT DMSUmes_Setup(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT IOff, L3INT Size); -L3INT DMSPmes_Setup(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT DMSUmes_0x07(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size); -L3INT DMSPmes_0x07(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT DMSUmes_0x0f(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size); -L3INT DMSPmes_0x0f(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); - -/***************************************************************************** - - Q.931 Process Function Prototyping. Implemented in nationalStateTE.c - -*****************************************************************************/ - -L3INT DMSProc0x0fTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom); -L3INT DMSProc0x07TE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom); - -void DMSCreateTE(L3UCHAR i); -void DMSCreateNT(L3UCHAR i); - -#endif /* _DMS_NL */ diff --git a/libs/freetdm/src/isdn/include/Q921.h b/libs/freetdm/src/isdn/include/Q921.h deleted file mode 100644 index cb21a157ea..0000000000 --- a/libs/freetdm/src/isdn/include/Q921.h +++ /dev/null @@ -1,227 +0,0 @@ -/***************************************************************************** - - FileName: q921.h - - Description: Contains headers of a Q.921 protocol. - - Note: This header file is the only include file that should be - acessed by users of the Q.921 stack. - - Interface: The Q.921 stack contains 2 layers. - - - One interface layer. - - One driver layer. - - The interface layer contains the interface functions required - for a layer 2 stack to be able to send and receive messages. - - The driver layer will simply feed bytes into the ship as - required and queue messages received out from the ship. - - Q921TimeTick The Q.921 like any other blackbox - modules contains no thread by it's own - and must therefore be called regularly - by an external 'thread' to do maintenance - etc. - - Q921Rx32 Receive message from layer 3. Called by - the layer 3 stack to send a message. - - - NOTE: The following are not yet implemented - - OnQ921Error Function called every if an error is - detected. - - OnQ921Log Function called if logging is active. - - - Maintenance/Configuration interface - Logging - DL_ message passing to layer 3 - Timers - Api commands to tell 921 to stop and start for a trunk - - Created: 27.dec.2000/JVB - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -*****************************************************************************/ - -/**************************************************************************** - * Changes: - * - * - June,July 2008: Stefan Knoblich : - * Add PTMP TEI management - * Add timers - * Add retransmit counters - * Add logging - * Various cleanups - * - ****************************************************************************/ - -#ifndef _Q921 -#define _Q921 - -#define Q921MAXHDLCSPACE 3000 -#define L2UCHAR unsigned char /* Min 8 bit */ -#define L2USHORT unsigned short /* 16 bit */ -#define L2INT int /* Min 16 bit signed */ -#define L2ULONG unsigned long /* Min 32 bit */ -#define L2TRUNK Q921Data_t * - -#define Q921_TEI_BCAST 127 -#define Q921_TEI_MAX Q921_TEI_BCAST - -#define Q921_TEI_DYN_MIN 64 -#define Q921_TEI_DYN_MAX 126 - - -typedef enum /* Network/User Mode */ -{ - Q921_TE=0, /* 0 : User Mode */ - Q921_NT=1 /* 1 : Network Mode */ -} Q921NetUser_t; - -typedef enum /* Type of connection */ -{ - Q921_PTP=0, /* 0 : Point-To-Point */ - Q921_PTMP=1 /* 1 : Point-To-Multipoint */ -} Q921NetType_t; - -typedef enum -{ - Q921_LOG_NONE = -1, - Q921_LOG_EMERG = 0, - Q921_LOG_ALERT, - Q921_LOG_CRIT, - Q921_LOG_ERROR, - Q921_LOG_WARNING, - Q921_LOG_NOTICE, - Q921_LOG_INFO, - Q921_LOG_DEBUG -} Q921LogLevel_t; - - -/* - * Messages for L2 <-> L3 communication - */ -typedef enum { - Q921_DL_ESTABLISH = 0, - Q921_DL_ESTABLISH_CONFIRM, - Q921_DL_RELEASE, - Q921_DL_RELEASE_CONFIRM, - Q921_DL_DATA, - Q921_DL_UNIT_DATA -} Q921DLMsg_t; - -typedef int (*Q921Tx21CB_t) (void *, L2UCHAR *, L2INT); -typedef int (*Q921Tx23CB_t) (void *, Q921DLMsg_t ind, L2UCHAR tei, L2UCHAR *, L2INT); -typedef int (*Q921LogCB_t) (void *, Q921LogLevel_t, char *, L2INT); - -struct Q921_Link; - -typedef struct Q921Data -{ - L2INT initialized; - - L2UCHAR sapi; /*!< User assigned SAPI */ - L2UCHAR tei; /*!< User assigned TEI value */ - - L2INT Q921HeaderSpace; - Q921NetUser_t NetUser; - Q921NetType_t NetType; - - struct Q921_Link *context; /*!< per-TEI / link context space */ - - /* timers */ - L2ULONG T202; /*!< PTMP TE mode TEI retransmit timer */ - L2ULONG T200Timeout; - L2ULONG T201Timeout; - L2ULONG T202Timeout; - L2ULONG T203Timeout; - - L2ULONG TM01Timeout; - - /* counters */ - L2ULONG N200Limit; /*!< max retransmit */ - - L2ULONG N202; /*!< PTMP TE mode retransmit counter */ - L2ULONG N202Limit; /*!< PTMP TE mode max retransmit */ - - L2ULONG N201Limit; /*!< max number of octets */ - L2ULONG k; /*!< max number of unacknowledged I frames */ - - /* callbacks and callback data pointers */ - Q921Tx21CB_t Q921Tx21Proc; - Q921Tx23CB_t Q921Tx23Proc; - void *PrivateData21; - void *PrivateData23; - - /* logging */ - Q921LogLevel_t loglevel; /*!< trunk loglevel */ - Q921LogCB_t Q921LogProc; /*!< log callback procedure */ - void *PrivateDataLog; /*!< private data pointer for log proc */ - - /* tei mgmt */ - L2UCHAR tei_map[Q921_TEI_MAX]; /*!< */ - - L2UCHAR HDLCInQueue[Q921MAXHDLCSPACE]; /*!< HDLC input queue */ -} Q921Data_t; - -/* - * Public functions - */ -int Q921_InitTrunk(L2TRUNK trunk, - L2UCHAR sapi, - L2UCHAR tei, - Q921NetUser_t NetUser, - Q921NetType_t NetType, - L2INT hsize, - Q921Tx21CB_t cb21, - Q921Tx23CB_t cb23, - void *priv21, - void *priv23); -int Q921Start(L2TRUNK trunk); -int Q921Stop(L2TRUNK trunk); - -void Q921SetLogCB(L2TRUNK trunk, Q921LogCB_t func, void *priv); -void Q921SetLogLevel(L2TRUNK trunk, Q921LogLevel_t level); - -int Q921Rx12(L2TRUNK trunk); -int Q921Rx32(L2TRUNK trunk, Q921DLMsg_t ind, L2UCHAR tei, L2UCHAR * Mes, L2INT Size); - -int Q921QueueHDLCFrame(L2TRUNK trunk, L2UCHAR *b, L2INT size); - -void Q921SetGetTimeCB(L2ULONG (*callback)(void)); -void Q921TimerTick(L2TRUNK trunk); - -#endif diff --git a/libs/freetdm/src/isdn/include/Q921priv.h b/libs/freetdm/src/isdn/include/Q921priv.h deleted file mode 100644 index d2d838c399..0000000000 --- a/libs/freetdm/src/isdn/include/Q921priv.h +++ /dev/null @@ -1,321 +0,0 @@ -/***************************************************************************** - - FileName: Q921priv.h - - Description: Private declarations - - Created: 08.Aug.2008/STKN - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Copyright (c) 2008, Stefan Knoblich, axsentis GmbH. All rights reserved. - email:s.knoblich@axsentis.de - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -*****************************************************************************/ -#ifndef _Q921_PRIV_H_ -#define _Q921_PRIV_H_ - -#ifdef _MSC_VER -#ifndef __inline__ -#define __inline__ __inline -#endif -#if (_MSC_VER >= 1400) /* VC8+ */ -#ifndef _CRT_SECURE_NO_DEPRECATE -#define _CRT_SECURE_NO_DEPRECATE -#endif -#ifndef _CRT_NONSTDC_NO_DEPRECATE -#define _CRT_NONSTDC_NO_DEPRECATE -#endif -#endif -#ifndef strcasecmp -#define strcasecmp(s1, s2) _stricmp(s1, s2) -#endif -#ifndef strncasecmp -#define strncasecmp(s1, s2, n) _strnicmp(s1, s2, n) -#endif -#ifndef snprintf -#define snprintf _snprintf -#endif -#endif - -typedef enum /* Q.921 States */ -{ - Q921_STATE_STOPPED = 0, /* Trunk stopped */ - Q921_STATE_TEI_UNASSIGNED = 1, /* TEI unassigned */ - Q921_STATE_TEI_AWAITING, /* Assign awaiting TEI */ - Q921_STATE_TEI_ESTABLISH, /* Establish awaiting TEI */ - Q921_STATE_TEI_ASSIGNED, /* TEI assigned */ - Q921_STATE_AWAITING_ESTABLISHMENT, /* Awaiting establishment */ - Q921_STATE_AWAITING_RELEASE, /* Awaiting release */ - Q921_STATE_MULTIPLE_FRAME_ESTABLISHED, /* Multiple frame established */ - Q921_STATE_TIMER_RECOVERY /* Timer recovery */ -} Q921State_t; - -/* - * Flags - */ -enum Q921_Flags { - Q921_FLAG_L3_INITIATED = (1 << 0), - - Q921_FLAG_UI_FRAME_QUEUED = (1 << 1), - Q921_FLAG_I_FRAME_QUEUED = (1 << 2), - - Q921_FLAG_ACK_PENDING = (1 << 3), - Q921_FLAG_REJECT = (1 << 4), - - Q921_FLAG_RECV_BUSY = (1 << 5), - Q921_FLAG_PEER_RECV_BUSY = (1 << 6) -}; - -#define Q921_SET_FLAG(x, f) ((x)->flags |= f) -#define Q921_CHECK_FLAG(x, f) ((x)->flags & f) -#define Q921_CLEAR_FLAG(x, f) ((x)->flags &= ~f) - - -/* - * dynamic TEI handling - */ -#define Q921_SAPI_TEI 63 /* SAPI for all TEI Messages */ -#define Q921_LAYER_ENT_ID_TEI 0x0f /* UN Layer Management Entity ID for TEI Mgmt */ -#define Q921_LAYER_ENT_ID_Q931 0x08 /* Q.931 Layer Management Entity ID */ - - -typedef enum { - Q921_TEI_ID_REQUEST = 1, - Q921_TEI_ID_ASSIGNED, - Q921_TEI_ID_DENIED, - Q921_TEI_ID_CHECKREQ, - Q921_TEI_ID_CHECKRESP, - Q921_TEI_ID_REMOVE, - Q921_TEI_ID_VERIFY -} Q921TeiMessageType_t; - - -/** - * Per-Datalink context - */ -struct Q921_Link { - L2UCHAR tei; /*!< This endpoint's TEI */ - - L2UCHAR va; - L2UCHAR vs; - L2UCHAR vr; - - L2INT flags; - Q921State_t state; - - L2ULONG N202; /*!< PTMP TE mode retransmit counter */ - L2ULONG N200; /*!< retransmit counter (per-TEI in PTMP NT mode) */ - - L2ULONG TM01; /*!< Datalink inactivity disconnect timer */ - - L2ULONG T200; - L2ULONG T201; /*!< PTMP NT mode timer */ - L2ULONG T203; - - L2USHORT ri; /*!< random id for TEI request mgmt */ - - /* I + UI Frame queue */ - L2UCHAR UIFrameQueue[Q921MAXHDLCSPACE]; - L2UCHAR IFrameQueue[Q921MAXHDLCSPACE]; - L2UCHAR IFrameResendQueue[Q921MAXHDLCSPACE]; -}; - - -#define Q921_LINK_CONTEXT(tr, tei) \ - (Q921_IS_PTMP_NT(tr) && tei != Q921_TEI_BCAST) ? ((struct Q921_Link *)&(tr)->context[tei]) : (tr)->context - -#define Q921_TRUNK_CONTEXT(tr) \ - (tr)->context - -#define Q921_LOGBUFSIZE 2000 -#define INITIALIZED_MAGIC 42 - -/* - * Helper macros - */ -#define Q921_INC_COUNTER(x) (x = (x + 1) % 128) -#define Q921_DEC_COUNTER(x) (x = (x) ? (x - 1) : 127) - -#define Q921_UFRAME_HEADER_SIZE 3 -#define Q921_UFRAME_DATA_OFFSET(tr) ((tr)->Q921HeaderSpace + Q921_UFRAME_HEADER_SIZE) - -#define Q921_SFRAME_HEADER_SIZE 4 -#define Q921_SFRAME_DATA_OFFSET(tr) ((tr)->Q921HeaderSpace + Q921_SFRAME_HEADER_SIZE) - -#define Q921_IFRAME_HEADER_SIZE 4 -#define Q921_IFRAME_DATA_OFFSET(tr) ((tr)->Q921HeaderSpace + Q921_IFRAME_HEADER_SIZE) - -#define Q921_IS_TE(x) ((x)->NetUser == Q921_TE) -#define Q921_IS_NT(x) ((x)->NetUser == Q921_NT) - -#define Q921_IS_STOPPED(tr) ((tr)->state == Q921_STATE_STOPPED) - -/* TODO: rework this one */ -#define Q921_IS_READY(tr) ((tr)->state >= Q921_STATE_TEI_ASSIGNED) - -#define Q921_IS_PTMP(x) ((x)->NetType == Q921_PTMP) -#define Q921_IS_PTMP_TE(x) ((x)->NetType == Q921_PTMP && (x)->NetUser == Q921_TE) -#define Q921_IS_PTMP_NT(x) ((x)->NetType == Q921_PTMP && (x)->NetUser == Q921_NT) - -#define Q921_IS_PTP(x) ((x)->NetType == Q921_PTP) -#define Q921_IS_PTP_TE(x) ((x)->NetType == Q921_PTP && (x)->NetUser == Q921_TE) -#define Q921_IS_PTP_NT(x) ((x)->NetType == Q921_PTP && (x)->NetUser == Q921_NT) - -/* Make life a little easier */ -#define Q921_COMMAND(x) ((x)->NetUser == Q921_TE ? 0 : 1) -#define Q921_RESPONSE(x) ((x)->NetUser == Q921_TE ? 1 : 0) - -#define Q921_IS_COMMAND(tr, x) ((x) == (Q921_IS_TE(tr) ? 1 : 0)) -#define Q921_IS_RESPONSE(tr, x) ((x) == (Q921_IS_TE(tr) ? 0 : 1)) - - -/******************************************************************************* - * Private functions - *******************************************************************************/ - -/* - * L1 / L2 Interface - */ -static int Q921Tx21Proc(L2TRUNK trunk, L2UCHAR *Msg, L2INT size); -static int Q921Tx23Proc(L2TRUNK trunk, Q921DLMsg_t ind, L2UCHAR tei, L2UCHAR *Msg, L2INT size); - - -/* - * Timers - */ -static L2ULONG Q921GetTime(void); - -static void Q921T200TimerStart(L2TRUNK trunk, L2UCHAR tei); -static void Q921T200TimerStop(L2TRUNK trunk, L2UCHAR tei); -static void Q921T200TimerReset(L2TRUNK trunk, L2UCHAR tei); -static void Q921T200TimerExpire(L2TRUNK trunk, L2UCHAR tei); - -static void Q921T201TimerStart(L2TRUNK trunk, L2UCHAR tei); -static void Q921T201TimerStop(L2TRUNK trunk, L2UCHAR tei); -/* static void Q921T201TimerReset(L2TRUNK trunk, L2UCHAR tei); - Unused for now */ -static void Q921T201TimerExpire(L2TRUNK trunk, L2UCHAR tei); - -static void Q921T202TimerStart(L2TRUNK trunk); -static void Q921T202TimerStop(L2TRUNK trunk); -static void Q921T202TimerReset(L2TRUNK trunk); -static void Q921T202TimerExpire(L2TRUNK trunk); - -static void Q921T203TimerStart(L2TRUNK trunk, L2UCHAR tei); -static void Q921T203TimerStop(L2TRUNK trunk, L2UCHAR tei); -static void Q921T203TimerReset(L2TRUNK trunk, L2UCHAR tei); -static void Q921T203TimerExpire(L2TRUNK trunk, L2UCHAR tei); - -static void Q921TM01TimerStart(L2TRUNK trunk, L2UCHAR tei); -/* static void Q921TM01TimerStop(L2TRUNK trunk, L2UCHAR tei); - Unused for now */ -static void Q921TM01TimerReset(L2TRUNK trunk, L2UCHAR tei); -/* static void Q921TM01TimerExpire(L2TRUNK trunk, L2UCHAR tei); - Unused for now */ - -/* - * Frame encoding - */ -static int Q921SendS(L2TRUNK trunk, L2UCHAR Sapi, char cr, L2UCHAR Tei, char pf, L2UCHAR sv, L2UCHAR *mes, L2INT size); -static int Q921SendU(L2TRUNK trunk, L2UCHAR Sapi, char cr, L2UCHAR Tei, char pf, L2UCHAR m, L2UCHAR *mes, L2INT size); - -static int Q921SendRNR(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf); -static int Q921SendREJ(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf); -static int Q921SendSABME(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf); -static int Q921SendDM(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf); -static int Q921SendDISC(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf); -static int Q921SendUA(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf); -static int Q921SendUN(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf, L2UCHAR *mes, L2INT size); -static int Q921SendRR(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf); - -/* - * Frame decoding - */ -static int Q921ProcIFrame(L2TRUNK trunk, L2UCHAR *mes, L2INT size); -static int Q921ProcSFrame(L2TRUNK trunk, L2UCHAR *mes, L2INT size); -static int Q921ProcUFrame(L2TRUNK trunk, L2UCHAR *mes, L2INT size); - -static int Q921ProcSABME(L2TRUNK trunk, L2UCHAR *mes, L2INT size); -static int Q921ProcDM(L2TRUNK trunk, L2UCHAR *mes, L2INT size); -static int Q921ProcUA(L2TRUNK trunk, L2UCHAR *mes, L2INT size); -static int Q921ProcDISC(L2TRUNK trunk, L2UCHAR *mes, L2INT size); -static int Q921ProcRR(L2TRUNK trunk, L2UCHAR *mes, L2INT size); -static int Q921ProcRNR(L2TRUNK trunk, L2UCHAR *mes, L2INT size); -static int Q921ProcREJ(L2TRUNK trunk, L2UCHAR *mes, L2INT size); - - -/* - * (Common) procedures defined in the Q.921 SDL - */ -static int Q921SendEnquiry(L2TRUNK trunk, L2UCHAR tei); -static int Q921SendEnquiryResponse(L2TRUNK trunk, L2UCHAR tei); -static void Q921ResetExceptionConditions(L2TRUNK trunk, L2UCHAR tei); -static int Q921EstablishDataLink(L2TRUNK trunk, L2UCHAR tei); -static int Q921NrErrorRecovery(L2TRUNK trunk, L2UCHAR tei); -static int Q921InvokeRetransmission(L2TRUNK trunk, L2UCHAR tei, L2UCHAR nr); -static int Q921AcknowledgePending(L2TRUNK trunk, L2UCHAR tei); -/* -static int Q921SetReceiverBusy(L2TRUNK trunk); -static int Q921ClearReceiverBusy(L2TRUNK trunk); -*/ - -/* - * Queueing - */ -static int Q921SendQueuedIFrame(L2TRUNK trunk, L2UCHAR tei); -static int Q921EnqueueI(L2TRUNK trunk, L2UCHAR Sapi, char cr, L2UCHAR Tei, char pf, L2UCHAR *mes, L2INT size); - -/* - * TEI management - */ -static int Q921TeiSendAssignRequest(L2TRUNK trunk); -static int Q921TeiProcAssignResponse(L2TRUNK trunk, L2UCHAR *mes, L2INT size); -static int Q921TeiSendVerifyRequest(L2TRUNK trunk); -static int Q921TeiProcCheckRequest(L2TRUNK trunk, L2UCHAR *mes, L2INT size); -static int Q921TeiProcRemoveRequest(L2TRUNK trunk, L2UCHAR *mes, L2INT size); -static int Q921TeiProcAssignRequest(L2TRUNK trunk, L2UCHAR *mes, L2INT size); -static int Q921TeiProcCheckResponse(L2TRUNK trunk, L2UCHAR *mes, L2INT size); -static int Q921TeiProcVerifyRequest(L2TRUNK trunk, L2UCHAR *mes, L2INT size); -static int Q921TeiSendRemoveRequest(L2TRUNK trunk, L2UCHAR tei); -static int Q921TeiSendDenyResponse(L2TRUNK trunk, L2UCHAR tei, L2USHORT ri); -static int Q921TeiSendAssignedResponse(L2TRUNK trunk, L2UCHAR tei, L2USHORT ri); -static int Q921TeiSendCheckRequest(L2TRUNK trunk, L2UCHAR tei); - -/* - * Logging - */ -static int Q921Log(L2TRUNK trunk, Q921LogLevel_t level, const char *fmt, ...); -static int Q921LogMesg(L2TRUNK trunk, Q921LogLevel_t level, L2UCHAR received, L2UCHAR *mes, L2INT size, const char *fmt, ...); - -/* - * State handling - */ -static int Q921ChangeState(L2TRUNK trunk, Q921State_t state, L2UCHAR tei); - -#endif diff --git a/libs/freetdm/src/isdn/include/Q931.h b/libs/freetdm/src/isdn/include/Q931.h deleted file mode 100644 index 0dbafd9f11..0000000000 --- a/libs/freetdm/src/isdn/include/Q931.h +++ /dev/null @@ -1,1175 +0,0 @@ -/****************************************************************************** - - FileName: Q931.h - - Contents: Header and definition for the ITU-T Q.931 stack. The - header contents the following parts: - - - Definition of codes - - Definition of information elements (Q931ie_). - - Definition of messages (Q931mes_). - - Definitian of variables (var_). - - Function prototypes. - - Description: The Q.931 stack provided here covers ITU-T Q.931 w/Q.932 - supplementary services for both PRI, BRI and variants. - The stack is generic and designed to deal with variants as - needed. - - The stack uses the following interface functions: - - - Q931Initialize Initialize the Q.931 stack. - - Q931Rx23 Receive a message from layer 2 - - Q931Tx32 Send a message to layer 2 - - Q931Rx43 Receive a message from layer 4 or above. - - Q931Tx34 Send a message to layer 4 or above. - - Q931TimeTick Periodical timer processing. - - Q931ErrorProc Callback for stack error message. - - The protocol is a module with no external dependencies and - can easely be ported to any operating system like Windows, - Linux, rtos and others. - - Related Files: Q931.h Q.931 Definitions - Q931.c Q.931 Interface Functions. - Q931api.c Low level L4 API functions. - - Q932.h Q.932 Suplementary Services - Q932mes.c Q.932 encoders/coders - - Q931mes.c Q.931 Message encoders/coders - Q931ie.c Q.931 IE encoders/coders - Q931StateTE.c Generic Q.931 TE State Engine - Q931StateNT.c Generic Q.931 NT State Engine - - Design Note 1: For each variant please add separate files starting with - the variant short-name as follows: - - .h Spesific headers needed. - mes.c Message encoders/decores. - ie.c IE encoders/decoders. - StateTE.c TE side state engine. - StateNT.c NT side state engine. - - Design Note 2: The stack is deliberatly made non-threading. Use 1 - thread per Trunk, but lock access from the timertick - and rx, tx functions. And make sure the callbacks only - dump messages to a queue, no time-consuming processing - inside stack processing. - - All stack processing is async 'fire and forget', meaning - that there are not, and should not be any time-consuming - processing within the stack-time. The best way to thread - a stack is to use one single thread that signal 5 queues. - - - Incoming L2 queue. - - Incoming L4 queue. - - Outgoing L2 queue. - - Outgoing L4 queue. - - Error/Trace queue. - - Design Note 3: DSP optimization. The L3 (Rx23) can be called directly - from a HDLC receiver without usage of queues for optimized - processing. But keep in mind that Q.931 calls Tx34 or Tx32 - as part of receiving a message from Layer 2. - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -******************************************************************************/ - -#ifndef _Q931_NL -#define _Q931_NL - -/* uncomment the #define below to add x.25 support to the Q.931 */ -/* #define Q931_X25_SUPPORT */ - -#include "stdio.h" - -#ifdef _MSC_VER -#pragma warning(disable:4100) -#ifndef strcasecmp -#define strcasecmp(s1, s2) _stricmp(s1, s2) -#endif -#endif -#include - - -/***************************************************************************** - - Enum helper macros - -*****************************************************************************/ -#define Q931_ENUM_NAMES(_NAME, _STRINGS) static const char * _NAME [] = { _STRINGS , NULL }; -#define Q931_STR2ENUM_P(_FUNC1, _FUNC2, _TYPE) _TYPE _FUNC1 (const char *name); const char * _FUNC2 (_TYPE type); -#define Q931_STR2ENUM(_FUNC1, _FUNC2, _TYPE, _STRINGS, _MAX) \ - _TYPE _FUNC1 (const char *name) \ - { \ - int i; \ - _TYPE t = _MAX ; \ - \ - for (i = 0; i < _MAX ; i++) { \ - if (!strcasecmp(name, _STRINGS[i])) { \ - t = (_TYPE) i; \ - break; \ - } \ - } \ - \ - return t; \ - } \ - const char * _FUNC2 (_TYPE type) \ - { \ - if (type > _MAX) { \ - type = _MAX; \ - } \ - return _STRINGS[(int)type]; \ - } \ - -/***************************************************************************** - - Error Codes - -*****************************************************************************/ -typedef enum { - Q931E_NO_ERROR = 0, - - Q931E_UNKNOWN_MESSAGE = -3001, - Q931E_ILLEGAL_IE = -3002, - Q931E_UNKNOWN_IE = -3003, - Q931E_BEARERCAP = -3004, - Q931E_HLCOMP = -3005, - Q931E_LLCOMP = -3006, - Q931E_INTERNAL = -3007, - Q931E_MISSING_CB = -3008, - Q931E_UNEXPECTED_MESSAGE = -3009, - Q931E_ILLEGAL_MESSAGE = -3010, - Q931E_TOMANYCALLS = -3011, - Q931E_INVALID_CRV = -3012, - Q931E_CALLID = -3013, - Q931E_CALLSTATE = -3014, - Q931E_CALLEDSUB = -3015, - Q931E_CALLEDNUM = -3016, - Q931E_CALLINGNUM = -3017, - Q931E_CALLINGSUB = -3018, - Q931E_CAUSE = -3019, - Q931E_CHANID = -3020, - Q931E_DATETIME = -3021, - Q931E_DISPLAY = -3022, - Q931E_KEYPADFAC = -3023, - Q931E_NETFAC = -3024, - Q931E_NOTIFIND = -3025, - Q931E_PROGIND = -3026, - Q931E_RESTARTIND = -3027, - Q931E_SEGMENT = -3028, - Q931E_SIGNAL = -3029, - Q931E_GENERIC_DIGITS = -3030 -} q931_error_t; - -/* The q931_error_t enum should be kept in sync with the q931_error_names array in Q931.c */ - -const char *q931_error_to_name(q931_error_t error); - -/***************************************************************************** - - Some speed optimization can be achieved by changing all variables to the - word size of your processor. A 32 bit processor has to do a lot of extra - work to read a packed 8 bit integer. Changing all fields to 32 bit integer - will result in usage of some extra space, but will speed up the stack. - - The stack has been designed to allow L3UCHAR etc. to be any size of 8 bit - or larger. - -*****************************************************************************/ - -#define L3UCHAR unsigned char /* Min 8 bit */ -#define L3USHORT unsigned short /* Min 16 bit unsigned */ -#define L3UINT unsigned int /* Min 16 bit unsigned */ -#define L3INT int /* Min 16 bit signed */ -#define L3ULONG unsigned long /* Min 32 bit */ -#define L3BOOL char /* Min 1 bit, valuse 0 & 1 only */ - -#define L3TRUE 1 -#define L3FALSE 0 - -/***************************************************************************** - - Global defines. - -*****************************************************************************/ - -typedef L3USHORT ie; /* Special data type to hold a dynamic */ - /* or optional information element as */ - /* part of a message struct. MSB = 1 */ - /* indicate that the ie is present, the */ - /* last 15 bits is an offset ( or the */ - /* value for single octet ) to the */ - /* struct holding the ie. Offset = 0 */ - /* is buf[1] etc. */ - /* ie == 0xffff indicates error */ - -/***************************************************************************** - - MAXTRUNKS sets how many physical trunks this system might have. This - number should be keept at a minimum since it will use global space. - - It is recommended that you leave MAXCHPERTRUNK as is - -*****************************************************************************/ - -#define Q931_LOGBUFSIZE 1024 /* size of logging buffer */ - -#define Q931L4BUF 1000 /* size of message buffer */ - -#define Q931L2BUF 300 /* size of message buffer */ - -#define Q931MAXTRUNKS 4 /* Total number of trunks that will be */ - /* processed by this instance of the */ - /* stack */ - -#define Q931MAXCHPERTRUNK 32 /* Number of channels per trunk. The */ - /* stack uses a static set of 32 */ - /* channels regardless if it is E1, T1 */ - /* or BRI that actually is used. */ - -#define Q931MAXCALLPERTRUNK (Q931MAXCHPERTRUNK * 2) - /* Number of max active CRV per trunk. */ - /* Q.931 can have more calls than there */ - /* are channels. */ - - -#define Q931_IS_BRI(x) ((x)->TrunkType == Q931_TrType_BRI || (x)->TrunkType == Q931_TrType_BRI_PTMP) -#define Q931_IS_PRI(x) (!Q931_IS_BRI(x)) - -#define Q931_IS_PTP(x) ((x)->TrunkType != Q931_TrType_BRI_PTMP) -#define Q931_IS_PTMP(X) ((x)->TrunkType == Q931_TrType_BRI_PTMP) - -#define Q931_BRI_MAX_CRV 127 -#define Q931_PRI_MAX_CRV 32767 - -/***************************************************************************** - - The following defines control the dialect switch tables and should only be - changed when a new dialect needs to be inserted into the stack. - - This stack uses an array of functions to know which function to call as - it receives a SETUP message etc. A new dialect can when choose to use - the proc etc. for standard Q.931 or insert a modified proc. - - This technique has also been used to distinguish between user and network - mode to make the code as easy to read and maintainable as possible. - - A message and IE index have been used to save space. These indexes allowes - the message or IE code to be used directly and will give back a new index - into the table. - -*****************************************************************************/ - -/* WARNING! Initialize Q931CreateDialectCB[] will NULL when increasing the */ -/* Q931MAXDLCT value to avoid Q931Initialize from crashing if one entry is */ -/* not used. */ -#define Q931MAXDLCT 8 /* Max dialects included in this */ - /* compile. User and Network count as */ - /* one dialect each. */ - -#define Q931MAXMES 128 /* Number of messages */ -#define Q931MAXIE 255 /* Number of IE */ -#define Q931MAXUSEDIE 50 /* Maximum number of ie types per Dialect */ -#define Q931MAXCODESETS 7 /* Maximum number of codests (by spec, 0-7) */ -#define Q931MAXSTATE 100 /* Size of state tables */ -#define Q931MAXTIMER 25 /* Maximum number of timers */ - -/***************************************************************************** - - Call States for ITU-T Q.931 TE (User Mode) - -*****************************************************************************/ - -#define Q931_U0 0 -#define Q931_U1 1 -#define Q931_U2 2 -#define Q931_U3 3 -#define Q931_U4 4 -#define Q931_U6 6 -#define Q931_U7 7 -#define Q931_U8 8 -#define Q931_U9 9 -#define Q931_U10 10 -#define Q931_U11 11 -#define Q931_U12 12 -#define Q931_U15 15 -#define Q931_U17 17 -#define Q931_U19 19 -#define Q931_U25 25 - -/***************************************************************************** - - Call States for ITU-T Q.931 NT (Network Mode) - -*****************************************************************************/ -#define Q931_N0 (0x0100 | 0) -#define Q931_N1 (0x0100 | 1) -#define Q931_N2 (0x0100 | 2) -#define Q931_N3 (0x0100 | 3) -#define Q931_N4 (0x0100 | 4) -#define Q931_N6 (0x0100 | 6) -#define Q931_N7 (0x0100 | 7) -#define Q931_N8 (0x0100 | 8) -#define Q931_N9 (0x0100 | 9) -#define Q931_N10 (0x0100 | 11) -#define Q931_N11 (0x0100 | 11) -#define Q931_N12 (0x0100 | 12) -#define Q931_N15 (0x0100 | 15) -#define Q931_N17 (0x0100 | 17) -#define Q931_N19 (0x0100 | 19) -#define Q931_N22 (0x0100 | 22) -#define Q931_N25 (0x0100 | 25) - -/***************************************************************************** - - Q.931 Message codes - -*****************************************************************************/ - -#define Q931mes_ALERTING 0x01 /* 0000 0001 */ -#define Q931mes_CALL_PROCEEDING 0x02 /* 0000 0010 */ -#define Q931mes_CONNECT 0x07 /* 0000 0111 */ -#define Q931mes_CONNECT_ACKNOWLEDGE 0x0f /* 0000 1111 */ -#define Q931mes_PROGRESS 0x03 /* 0000 0011 */ -#define Q931mes_SETUP 0x05 /* 0000 0101 */ -#define Q931mes_SETUP_ACKNOWLEDGE 0x0d /* 0000 1101 */ -#define Q931mes_RESUME 0x26 /* 0010 0110 */ -#define Q931mes_RESUME_ACKNOWLEDGE 0x2e /* 0010 1110 */ -#define Q931mes_RESUME_REJECT 0x22 /* 0010 0010 */ -#define Q931mes_SUSPEND 0x25 /* 0010 0101 */ -#define Q931mes_SUSPEND_ACKNOWLEDGE 0x2d /* 0010 1101 */ -#define Q931mes_SUSPEND_REJECT 0x21 /* 0010 0001 */ -#define Q931mes_USER_INFORMATION 0x20 /* 0010 0000 */ -#define Q931mes_DISCONNECT 0x45 /* 0100 0101 */ -#define Q931mes_RELEASE 0x4d /* 0100 1101 */ -#define Q931mes_RELEASE_COMPLETE 0x5a /* 0101 1010 */ -#define Q931mes_RESTART 0x46 /* 0100 0110 */ -#define Q931mes_RESTART_ACKNOWLEDGE 0x4e /* 0100 1110 */ -#define Q931mes_CONGESTION_CONTROL 0x79 /* 0111 1001 */ -#define Q931mes_INFORMATION 0x7b /* 0111 1011 */ -#define Q931mes_NOTIFY 0x6e /* 0110 1110 */ -#define Q931mes_STATUS 0x7d /* 0111 1101 */ -#define Q931mes_STATUS_ENQUIRY 0x75 /* 0111 0101 */ -#define Q931mes_SEGMENT 0x60 /* 0110 0000 */ - -#define Q931mes_SERVICE 0x0f /* 0000 1111 */ -#define Q931mes_SERVICE_ACKNOWLEDGE 0x07 /* 0000 0111 */ - - -/** - * Generic Q.931 Timers - */ -enum { - Q931_TIMER_T300 = 1, /* */ - Q931_TIMER_T301, - Q931_TIMER_T302, - Q931_TIMER_T303, - Q931_TIMER_T304, - Q931_TIMER_T305, - Q931_TIMER_T306, - Q931_TIMER_T307, - Q931_TIMER_T308, - Q931_TIMER_T309, - Q931_TIMER_T310, - Q931_TIMER_T311, - Q931_TIMER_T312, - Q931_TIMER_T313, - Q931_TIMER_T314, - Q931_TIMER_T315, - Q931_TIMER_T316, - Q931_TIMER_T317, - Q931_TIMER_T318, - Q931_TIMER_T319, - Q931_TIMER_T320, - Q931_TIMER_T321, - Q931_TIMER_T322, -}; - -/** - * Q.931 ToN - */ -enum { - Q931_TON_UNKNOWN = 0x00, - Q931_TON_INTERNATIONAL = 0x01, - Q931_TON_NATIONAL = 0x02, - Q931_TON_NETWORK_SPECIFIC = 0x03, - Q931_TON_SUBSCRIBER_NUMBER = 0x04, - Q931_TON_ABBREVIATED_NUMBER = 0x06, - Q931_TON_RESERVED = 0x07 -}; - -/** - * Q.931 Numbering Plan - */ -enum { - Q931_NUMPLAN_UNKNOWN = 0x00, - Q931_NUMPLAN_E164 = 0x01, - Q931_NUMPLAN_X121 = 0x03, - Q931_NUMPLAN_F69 = 0x04, - Q931_NUMPLAN_NATIONAL = 0x08, - Q931_NUMPLAN_PRIVATE = 0x09, - Q931_NUMPLAN_RESERVED = 0x0e -}; - -/** - * Q.931 Presentation Indicator - */ -enum { - Q931_PRES_ALLOWED = 0x00, - Q931_PRES_RESTRICTED = 0x01, - Q931_PRES_NOT_AVAILABLE = 0x02, - Q931_PRES_RESERVED = 0x03 -}; - -/** - * Q.931 Screening Indicator - */ -enum { - Q931_SCREEN_USER_NOT_SCREENED = 0x00, - Q931_SCREEN_USER_VERIFIED_PASSED = 0x01, - Q931_SCREEN_USER_VERIFIED_FAILED = 0x02, - Q931_SCREEN_NETWORK = 0x03 -}; - -/** - * Q.931 Coding Standard - */ -enum { - Q931_CODING_ITU = 0x00, - Q931_CODING_ISO = 0x01, - Q931_CODING_NATIONAL = 0x02, - Q931_CODING_NETWORK = 0x03 -}; - -/** - * Q.931 High layer characteristik id - */ -enum { - Q931_HLCHAR_TELEPHONY = 0x01, - Q931_HLCHAR_FAX_G23 = 0x04, - Q931_HLCHAR_FAX_G4 = 0x21, - Q931_HLCHAR_FAX_G4II = 0x24, - Q931_HLCHAR_T102 = 0x32, - Q931_HLCHAR_T101 = 0x33, - Q931_HLCHAR_F60 = 0x35, - Q931_HLCHAR_X400 = 0x38, - Q931_HLCHAR_X200 = 0x41 -}; - -/** - * Q.931 User information layer 1 protocol - */ -enum { - Q931_UIL1P_V110 = 0x01, - Q931_UIL1P_I460 = 0x01, - Q931_UIL1P_X30 = 0x01, - - Q931_UIL1P_G711U = 0x02, - Q931_UIL1P_G711A = 0x03, - Q931_UIL1P_G721 = 0x04, - - Q931_UIL1P_H221 = 0x05, - Q931_UIL1P_H242 = 0x05, - - Q931_UIL1P_H223 = 0x06, - Q931_UIL1P_H245 = 0x06, - - Q931_UIL1P_RATE_ADAP = 0x07, - - Q931_UIL1P_V120 = 0x08, - Q931_UIL1P_X31 = 0x09 -}; - -/** - * Q.931 Information Transfer Capability - */ -enum { - Q931_ITC_SPEECH = 0x00, - Q931_ITC_UNRESTRICTED = 0x08, - Q931_ITC_RESTRICTED = 0x09, - Q931_ITC_3K1_AUDIO = 0x10, - Q931_ITC_UNRESTRICTED_TONES = 0x11, - Q931_ITC_VIDEO = 0x18 -}; - -/** - * Q.931 Information transfer rate - */ -enum { - Q931_ITR_PACKET = 0x00, - Q931_ITR_64K = 0x10, - Q931_ITR_128K = 0x11, - Q931_ITR_384K = 0x13, - Q931_ITR_1536K = 0x15, - Q931_ITR_1920K = 0x17, - Q931_ITR_MULTI = 0x18 -}; - -/***************************************************************************** - - Struct: Q931mes_Header - - Description: Used to read the header & message code. - -*****************************************************************************/ -typedef struct { - L3UINT Size; /* Size of message in bytes */ - L3UCHAR ProtDisc; /* Protocol Discriminator */ - L3UCHAR MesType; /* Message type */ - L3UCHAR CRVFlag; /* Call reference value flag */ - L3INT CRV; /* Call reference value */ - -} Q931mes_Header; - -/***************************************************************************** - - Struct: Q931mes_Generic - - Description: Generic header containing all IE's. This is not used, but is - provided in case a proprietary variant needs it. - -*****************************************************************************/ -typedef struct { - L3UINT Size; /* Size of message in bytes */ - L3UCHAR ProtDisc; /* Protocol Discriminator */ - L3UCHAR MesType; /* Message type */ - L3UCHAR CRVFlag; /* Call reference value flag */ - L3INT CRV; /* Call reference value */ - - /* WARNING: don't touch anything above this line (TODO: use Q931mes_Header directly to make sure it's the same) */ - - L3UCHAR Tei; /* TEI */ - - ie Shift; - ie MoreData; - ie SendComplete; - ie CongestionLevel; - ie RepeatInd; - - ie Segment; /* Segmented message */ - ie BearerCap; /* Bearer Capability */ - ie Cause; /* Cause */ - ie CallState; /* Call State */ - ie CallID; /* Call Identity */ - ie ChanID; /* Channel Identification */ - ie ChangeStatus; /* Change Staus */ - ie ProgInd; /* Progress Indicator */ - ie NetFac; /* Network Spesific Facilities */ - ie NotifInd; /* Notification Indicator */ - ie Display; /* Display */ - ie DateTime; /* Date/Time */ - ie KeypadFac; /* Keypad Facility */ - ie Signal; /* Signal */ - ie InfoRate; /* Information rate */ - ie EndEndTxDelay; /* End to End Transmit Delay */ - ie TransDelSelInd; /* Transmit Delay Sel. and Ind. */ - ie PackParam; /* Packed Layer Binary parameters */ - ie PackWinSize; /* Packet Layer Window Size */ - ie PackSize; /* Packed Size */ - ie ClosedUserGrp; /* Closed User Group */ - ie RevChargeInd; /* Reverse Charging Indicator */ - ie CalledNum; /* Called Party Number */ - ie CalledSub; /* Called Party subaddress */ - ie CallingNum; /* Calling Party Number */ - ie CallingSub; /* Calling Party Subaddress */ - ie RedirNum; /* Redirection Number */ - ie TransNetSel; /* Transmit Network Selection */ - ie LLRepeatInd; /* Repeat Indicator 2 LLComp */ - ie RestartWin; /* Restart Window */ - ie RestartInd; /* Restart Indicator */ - ie LLComp; /* Low Layer Compatibility */ - ie HLComp; /* High Layer Compatibility */ - ie UserUser; /* User-user */ - ie Escape; /* Escape for extension */ - ie Switchhook; - ie FeatAct; - ie FeatInd; - ie GenericDigits; - - L3UCHAR buf[1]; /* Buffer for IE's */ - -} Q931mes_Generic; - - -/***************************************************************************** - - Struct: Q931_TrunkInfo - - Description: TrunkInfo is the struct entry used to store Q.931 related - information and state for E1/T1/J1 trunks and associated - channels in the system. - - The user should store this information outside this stack - and needs to feed the interface functions with a pointer to - the TrunkInfo entry. - -*****************************************************************************/ -typedef struct Q931_TrunkInfo Q931_TrunkInfo_t; - -typedef enum { - Q931_LOG_NONE = -1, - Q931_LOG_EMERG, - Q931_LOG_ALERT, - Q931_LOG_CRIT, - Q931_LOG_ERROR, - Q931_LOG_WARNING, - Q931_LOG_NOTICE, - Q931_LOG_INFO, - Q931_LOG_DEBUG -} Q931LogLevel_t; - -typedef L3INT (*Q931Tx34CB_t) (void *,L3UCHAR *, L3INT); -typedef L3INT (*Q931Tx32CB_t) (void *, L3INT, L3UCHAR, L3UCHAR *, L3INT); -typedef L3INT (*Q931ErrorCB_t) (void *,L3INT,L3INT,L3INT); -typedef L3INT (*Q931LogCB_t) (void *, Q931LogLevel_t, char *, L3INT); - -typedef enum { /* Network/User Mode. */ - Q931_TE=0, /* 0 : User Mode */ - Q931_NT=1 /* 1 : Network Mode */ -} Q931NetUser_t; - -typedef enum { /* Dialect enum */ - Q931_Dialect_Q931 = 0, - Q931_Dialect_National = 2, - Q931_Dialect_DMS = 4, - Q931_Dialect_5ESS = 6, /* Coming soon to a PRI stack near you! */ - - Q931_Dialect_Count -} Q931Dialect_t; -#define DIALECT_STRINGS "q931", "", "national", "", "dms", "", "5ess", "" -Q931_STR2ENUM_P(q931_str2Q931Dialect_type, q931_Q931Dialect_type2str, Q931Dialect_t) - -typedef enum { /* Trunk Line Type. */ - Q931_TrType_E1 = 0, /* 0 : E1 Trunk */ - Q931_TrType_T1 = 1, /* 1 : T1 Trunk */ - Q931_TrType_J1 = 2, /* 2 : J1 Trunk */ - Q931_TrType_BRI = 3, /* 3 : BRI Trunk */ - Q931_TrType_BRI_PTMP = 4 /* 4 : BRI PTMP Trunk */ -} Q931_TrunkType_t; - -typedef enum { /* Trunk State */ - Q931_TrState_NoAlignment=0, /* Trunk not aligned */ - Q931_TrState_Aligning=1, /* Aligning in progress */ - Q931_TrState_Aligned=2 /* Trunk Aligned */ -} Q931_TrunkState_t; - -typedef enum { - Q931_ChType_NotUsed=0, /* Unused Channel */ - Q931_ChType_B=1, /* B Channel (Voice) */ - Q931_ChType_D=2, /* D Channel (Signalling) */ - Q931_ChType_Sync=3 /* Sync Channel */ -} Q931_ChanType_t; - -struct Q931_Call -{ - L3UCHAR InUse; /* Indicate if entry is in use. */ - /* 0 = Not in Use */ - /* 1 = Active Call. */ - - L3UCHAR Tei; /* Associated TEI */ - - L3UCHAR BChan; /* Associated B Channel. */ - /* 0 - 31 valid B chan */ - /* 255 = Not allocated */ - - L3INT CRV; /* Associated CRV. */ - - L3UINT State; /* Call State. */ - /* 0 is Idle, but other values are */ - /* defined per dialect. */ - /* Default usage is 1-99 for TE and */ - /* 101 - 199 for NT. */ - - L3ULONG Timer; /* Timer in ms. The TimeTick will check */ - /* if this has exceeded the timeout, and */ - /* if so call the timers timeout proc. */ - - L3USHORT TimerID; /* Timer Identification/State */ - /* actual values defined by dialect */ - /* 0 : No timer running */ - /* ITU-T Q.931:301 - 322 Timer running */ -}; - -struct Q931_TrunkInfo -{ - Q931NetUser_t NetUser; /* Network/User Mode. */ - Q931_TrunkType_t TrunkType; /* Trunk Line Type. */ - Q931Dialect_t Dialect; /* Q.931 Based dialect index. */ - - Q931Tx34CB_t Q931Tx34CBProc; - Q931Tx32CB_t Q931Tx32CBProc; - Q931ErrorCB_t Q931ErrorCBProc; - Q931LogCB_t Q931LogCBProc; - void *PrivateData32; - void *PrivateData34; - void *PrivateDataLog; - - Q931LogLevel_t loglevel; - - L3UCHAR Enabled; /* Enabled/Disabled */ - /* 0 = Disabled */ - /* 1 = Enabled */ - - Q931_TrunkState_t TrunkState; - - L3INT LastCRV; /* Last used crv for the trunk. */ - - L3UCHAR L3Buf[Q931L4BUF]; /* message buffer for messages to be */ - /* send from Q.931 L4. */ - - L3UCHAR L2Buf[Q931L2BUF]; /* buffer for messages send to L2. */ - - /* The auto flags below switch on/off automatic Ack messages. SETUP ACK */ - /* as an example can be sent by the stack in response to SETUP to buy */ - /* time in processing on L4. Setting this to true will cause the stack */ - /* to automatically send this. */ - - L3BOOL autoSetupAck; /* Indicate if the stack should send */ - /* SETUP ACK or not. 0=No, 1 = Yes. */ - - L3BOOL autoConnectAck; /* Indicate if the stack should send */ - /* CONNECT ACT or not. 0=No, 1=Yes. */ - - L3BOOL autoRestartAck; /* Indicate if the stack should send */ - /* RESTART ACK or not. 0=No, 1=Yes. */ - - L3BOOL autoServiceAck; /* Indicate if the stack should send */ - /* SERVICE ACK or not. 0=No, 1=Yes. */ - - /* channel array holding info per channel. Usually defined to 32 */ - /* channels to fit an E1 since T1/J1 and BRI will fit inside a E1. */ - struct _charray - { - Q931_ChanType_t ChanType; /* Unused, B, D, Sync */ - - L3UCHAR Available; /* Channel Available Flag */ - /* 0 : Avaiabled */ - /* 1 : Used */ - - L3INT CRV; /* Associated CRV */ - - } ch[Q931MAXCHPERTRUNK]; - - /* Active Call information indentified by CRV. See Q931AllocateCRV for */ - /* initialization of call table. */ - struct Q931_Call call[Q931MAXCALLPERTRUNK]; -}; - -/***************************************************************************** - - Struct: Q931State - - Description: Define a Q931 State, legal events and next state for each - event. Used to simplify the state engine logic. Each state - engine defines its own state table and the logic need only - call a helper function to check if the message is legal - at this stage. - -*****************************************************************************/ -typedef struct -{ - L3INT State; - L3INT Message; - L3UCHAR Direction; -} Q931State; - -/***************************************************************************** - - Proc table external references. - - The proc tables are defined in Q931.c and initialized in Q931Initialize. - -*****************************************************************************/ -typedef L3INT (q931proc_func_t) (Q931_TrunkInfo_t *pTrunk, L3UCHAR *, L3INT); - -typedef L3INT (q931umes_func_t) (Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT IOff, L3INT Size); -typedef L3INT (q931pmes_func_t) (Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); - -typedef L3INT (q931uie_func_t) (Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff); -typedef L3INT (q931pie_func_t) (Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet); - -typedef L3INT (q931timeout_func_t) (Q931_TrunkInfo_t *pTrunk, L3INT callIndex); -typedef L3ULONG q931timer_t; - -extern q931proc_func_t *Q931Proc[Q931MAXDLCT][Q931MAXMES]; - -extern q931umes_func_t *Q931Umes[Q931MAXDLCT][Q931MAXMES]; -extern q931pmes_func_t *Q931Pmes[Q931MAXDLCT][Q931MAXMES]; - -extern q931uie_func_t *Q931Uie[Q931MAXDLCT][Q931MAXIE]; -extern q931pie_func_t *Q931Pie[Q931MAXDLCT][Q931MAXIE]; - -extern q931timeout_func_t *Q931Timeout[Q931MAXDLCT][Q931MAXTIMER]; -extern q931timer_t Q931Timer[Q931MAXDLCT][Q931MAXTIMER]; - - -/***************************************************************************** - - Macro: GetIETotoSize - - Syntax: L3INT GetIETotSize(InfoElem ie); - - Description: Compute the total size in bytes of an info element including - size of 'header'. - -*****************************************************************************/ -#define Q931GetIETotSize(ie) (((ie.InfoID & 0x80) != 0) ? 1 : ie.LenIE) + 2) - -/***************************************************************************** - - Macro: IsIEPresent - - Syntax: BOOL IsIEPresent(ie InfoElement); - - Description: Return TRUE if the Information Element is included. - -*****************************************************************************/ -#define Q931IsIEPresent(x) ((x & 0x8000) != 0) - -/***************************************************************************** - - Macro: GetIEOffset and GetIEValue - - Syntax: L3INT GetIEOffset(ie InfoElement) - L3INT GetIEValue(ie InfoElement) - - Description: Returns the offset (or the value )to the Information Element. - - Note: GetIEValue assumes that the 15 lsb bit is the value of a - single octet information element. This macro can not be used - on a variable information element. - -*****************************************************************************/ -#define Q931GetIEOffset(x) (x & 0x7fff) -#define Q931GetIEValue(x) (x & 0x7fff) - -/***************************************************************************** - - Macro: Q931GetIEPtr - - Syntax: void * Q931GetIEPtr(ie InfoElement, L3UCHAR * Buf); - - Description: Compute a Ptr to the information element. - -*****************************************************************************/ -#define Q931GetIEPtr(ie,buf) ((void *)&buf[Q931GetIEOffset(ie)]) - -/***************************************************************************** - - Macro: SetIE - - Syntax: void SetIE(ie InfoElement, L3INT Offset); - - Description: Set an information element. - -*****************************************************************************/ -#define Q931SetIE(x,o) { x = (ie)(o) | 0x8000; } - -/***************************************************************************** - - Macro: IsQ931Ext - - Syntax BOOL IsQ931Ext(L3UCHAR c) - - Description: Return true Check if the msb (bit 8) is 0. This indicate - that the octet is extended. - -*****************************************************************************/ -#define IsQ931Ext(x) ((x & 0x80) == 0) - -/***************************************************************************** - - Macro: ieGetOctet - - Syntax: unsigned L3UCHAR ieGetOctet(L3INT e) - - Description: Macro to fetch one byte from an integer. Mostly used to - avoid warnings. - -*****************************************************************************/ -#define ieGetOctet(x) ((L3UCHAR)(x)) - -/***************************************************************************** - - Macro: NoWarning - - Syntax: void NoWarning(x) - - Description: Macro to suppress unreferenced formal parameter warnings - - Used during creation of the stack since the stack is - developed for Warning Level 4 and this creates a lot of - warning for the initial empty functions. - -*****************************************************************************/ -#define NoWarning(x) (x = x) - -/***************************************************************************** - - External references. See Q931.c for details. - -*****************************************************************************/ - -#include "Q931ie.h" - -#include "Q932.h" - -/***************************************************************************** - - Q.931 Message Pack/Unpack functions. Implemented in Q931mes.c - -*****************************************************************************/ -L3INT Q931Pmes_Alerting(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_CallProceeding(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_Connect(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_ConnectAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_Progress(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_Setup(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_SetupAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_Resume(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_ResumeAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_ResumeReject(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_Suspend(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_SuspendAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_SuspendReject(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_UserInformation(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_Disconnect(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_Release(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_ReleaseComplete(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_Restart(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_RestartAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_CongestionControl(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_Information(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_Notify(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_Segment(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_Status(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_StatusEnquiry(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_Service(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931Pmes_ServiceAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); - - -L3INT Q931Umes_Alerting(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_CallProceeding(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_Connect(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_ConnectAck(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_Progress(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_Setup(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_SetupAck(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_Resume(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_ResumeAck(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_ResumeReject(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_Suspend(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_SuspendAck(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_SuspendReject(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_UserInformation(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_Disconnect(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_Release(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_ReleaseComplete(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_Restart(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_RestartAck(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_CongestionControl(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_Information(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_Notify(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_Segment(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_Status(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_StatusEnquiry(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT I, L3INT O); -L3INT Q931Umes_Service(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size); -L3INT Q931Umes_ServiceAck(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size); - - -/***************************************************************************** - - Q.931 Process Function Prototyping. Implemented in Q931StateTE.c - -*****************************************************************************/ -L3INT Q931ProcAlertingTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcCallProceedingTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcConnectTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcConnectAckTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcProgressTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcSetupTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcSetupAckTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcResumeTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcResumeAckTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcResumeRejectTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcSuspendTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcSuspendAckTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcSuspendRejectTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcUserInformationTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcDisconnectTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcReleaseTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcReleaseCompleteTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcRestartTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcRestartAckTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcCongestionControlTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcInformationTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcNotifyTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcStatusTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcStatusEnquiryTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcSegmentTE(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); - -L3INT Q931ProcAlertingNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcCallProceedingNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcConnectNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcConnectAckNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcProgressNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcSetupNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcSetupAckNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcResumeNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcResumeAckNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcResumeRejectNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcSuspendNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcSuspendAckNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcSuspendRejectNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcUserInformationNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcDisconnectNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcReleaseNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcReleaseCompleteNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcRestartNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcRestartAckNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcCongestionControlNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcInformationNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcNotifyNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcStatusNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcStatusEnquiryNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcSegmentNT(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); - -L3INT Q931ProcUnknownMessage(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); -L3INT Q931ProcUnexpectedMessage(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFrom); - -/***************************************************************************** - - Interface Function Prototypes. Implemented in Q931.c - -*****************************************************************************/ -void Q931TimerTick(Q931_TrunkInfo_t *pTrunk); -L3INT Q931Rx23(Q931_TrunkInfo_t *pTrunk, L3INT ind, L3UCHAR tei, L3UCHAR * Mes, L3INT Size); -L3INT Q931Tx32Data(Q931_TrunkInfo_t *pTrunk, L3UCHAR bcast, L3UCHAR * Mes, L3INT Size); -L3INT Q931Rx43(Q931_TrunkInfo_t *pTrunk, L3UCHAR * Mes, L3INT Size); -L3INT Q931Tx34(Q931_TrunkInfo_t *pTrunk, L3UCHAR * Mes, L3INT Size); -void Q931SetError(Q931_TrunkInfo_t *pTrunk,L3INT ErrID, L3INT ErrPar1, L3INT ErrPar2); - -void Q931SetDefaultErrorCB(Q931ErrorCB_t Q931ErrorPar); - -void Q931CreateTE(L3UCHAR i); -void Q931CreateNT(L3UCHAR i); -void Q931SetMesCreateCB(L3INT (*callback)(void)); -void Q931SetDialectCreateCB(L3INT (*callback)(L3INT)); -void Q931SetHeaderSpace(L3INT space); - -void Q931SetMesProc(L3UCHAR mes, L3UCHAR dialect, q931proc_func_t *Q931ProcFunc, q931umes_func_t *Q931UmesFunc, q931pmes_func_t *Q931PmesFunc); -void Q931SetIEProc(L3UCHAR iec, L3UCHAR dialect, q931pie_func_t *Q931PieProc, q931uie_func_t *Q931UieProc); -void Q931SetTimeoutProc(L3UCHAR dialect, L3UCHAR timer, q931timeout_func_t *Q931TimeoutProc); -void Q931SetTimerDefault(L3UCHAR dialect, L3UCHAR timer, q931timer_t timeout); - -void Q931Initialize(void); -void Q931AddDialect(L3UCHAR iDialect, void (*Q931CreateDialectCB)(L3UCHAR iDialect)); -L3INT Q931InitMesSetup(Q931mes_Generic *p); -L3INT Q931InitMesRestartAck(Q931mes_Generic * pMes); -L3INT Q931InitMesGeneric(Q931mes_Generic *pMes); - -L3INT Q931CreateCRV(Q931_TrunkInfo_t *pTrunk, L3INT * callIndex); -L3INT Q931ReleaseCRV(Q931_TrunkInfo_t *pTrunk, L3INT CRV); -L3INT Q931AllocateCRV(Q931_TrunkInfo_t *pTrunk, L3INT iCRV, L3INT * callIndex); -L3INT Q931FindCRV(Q931_TrunkInfo_t *pTrunk, L3INT crv, L3INT *callindex); -L3INT Q931GetCallState(Q931_TrunkInfo_t *pTrunk, L3INT iCRV); -L3INT Q931StartTimer(Q931_TrunkInfo_t *pTrunk, L3INT callIndex, L3USHORT iTimer); -L3INT Q931StopTimer(Q931_TrunkInfo_t *pTrunk, L3INT callindex, L3USHORT iTimer); -L3INT Q931SetState(Q931_TrunkInfo_t *pTrunk, L3INT callIndex, L3INT iState); -L3ULONG Q931GetTime(void); -void Q931SetGetTimeCB(L3ULONG (*callback)(void)); -void Q931AddStateEntry(L3UCHAR iD, L3INT iState, L3INT iMes, L3UCHAR cDir); -L3BOOL Q931IsEventLegal(L3UCHAR iD, L3INT iState, L3INT iMes, L3UCHAR cDir); - -/***************************************************************************** - - Q.931 Low Level API Function Prototyping. Implemented in Q931API.c - -*****************************************************************************/ -ie Q931AppendIE(L3UCHAR *pm, L3UCHAR *pi); -L3INT Q931GetUniqueCRV(Q931_TrunkInfo_t *pTrunk); - -L3INT Q931InitIEBearerCap(Q931ie_BearerCap *p); -L3INT Q931InitIEChanID(Q931ie_ChanID *p); -L3INT Q931InitIEProgInd(Q931ie_ProgInd *p); -L3INT Q931InitIENetFac(Q931ie_NetFac * pIE); -L3INT Q931InitIEDisplay(Q931ie_Display * pIE); -L3INT Q931InitIEDateTime(Q931ie_DateTime * pIE); -L3INT Q931InitIEKeypadFac(Q931ie_KeypadFac * pIE); -L3INT Q931InitIESignal(Q931ie_Signal * pIE); -L3INT Q931InitIECallingNum(Q931ie_CallingNum * pIE); -L3INT Q931InitIECallingSub(Q931ie_CallingSub * pIE); -L3INT Q931InitIECalledNum(Q931ie_CalledNum * pIE); -L3INT Q931InitIECalledSub(Q931ie_CalledSub * pIE); -L3INT Q931InitIETransNetSel(Q931ie_TransNetSel * pIE); -L3INT Q931InitIELLComp(Q931ie_LLComp * pIE); -L3INT Q931InitIEHLComp(Q931ie_HLComp * pIE); - -L3INT Q931Disconnect(Q931_TrunkInfo_t *pTrunk, L3INT iTo, L3INT iCRV, L3INT iCause); -L3INT Q931ReleaseComplete(Q931_TrunkInfo_t *pTrunk, L3UCHAR *buf); -L3INT Q931AckRestart(Q931_TrunkInfo_t *pTrunk, L3UCHAR *buf); -L3INT Q931AckConnect(Q931_TrunkInfo_t *pTrunk, L3UCHAR *buf); -L3INT Q931AckSetup(Q931_TrunkInfo_t *pTrunk, L3UCHAR *buf); -L3INT Q931AckService(Q931_TrunkInfo_t *pTrunk, L3UCHAR *buf); - -L3INT Q931Api_InitTrunk(Q931_TrunkInfo_t *pTrunk, - Q931Dialect_t Dialect, - Q931NetUser_t NetUser, - Q931_TrunkType_t TrunkType, - Q931Tx34CB_t Q931Tx34CBProc, - Q931Tx32CB_t Q931Tx32CBProc, - Q931ErrorCB_t Q931ErrorCBProc, - void *PrivateData32, - void *PrivateData34); - -L3INT Q931GetMesSize(Q931mes_Generic *pMes); -L3INT Q931InitMesResume(Q931mes_Generic * pMes); - -L3INT Q931Log(Q931_TrunkInfo_t *trunk, Q931LogLevel_t level, const char *fmt, ...); -void Q931SetLogCB(Q931_TrunkInfo_t *trunk, Q931LogCB_t func, void *priv); -void Q931SetLogLevel(Q931_TrunkInfo_t *trunk, Q931LogLevel_t level); - -void Q931SetL4HeaderSpace(L3INT space); -void Q931SetL2HeaderSpace(L3INT space); -L3INT Q931ProcDummy(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b,L3INT c); -L3INT Q931UmesDummy(Q931_TrunkInfo_t *pTrunk,L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT IOff, L3INT Size); -L3INT Q931UieDummy(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff); -L3INT Q931PmesDummy(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q931PieDummy(Q931_TrunkInfo_t *pTrunk,L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet); -L3INT Q931TxDummy(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT n); -L3INT Q931ErrorDummy(void *priv, L3INT a, L3INT b, L3INT c); -L3INT Q931TimeoutDummy(Q931_TrunkInfo_t *pTrunk, L3INT callIndex); - -L3INT Q931MesgHeader(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *mes, L3UCHAR *OBuf, L3INT Size, L3INT *IOff); - -#endif /* _Q931_NL */ diff --git a/libs/freetdm/src/isdn/include/Q931ie.h b/libs/freetdm/src/isdn/include/Q931ie.h deleted file mode 100644 index 65dba4e261..0000000000 --- a/libs/freetdm/src/isdn/include/Q931ie.h +++ /dev/null @@ -1,1205 +0,0 @@ -/****************************************************************************** - - FileName: Q931ie.h - - Contents: Header and definition for the ITU-T Q.931 ie - structures and functions - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -******************************************************************************/ - -#ifndef _Q931IE_NL -#define _Q931IE_NL - -/* Codesets */ - -typedef enum { - - Q931_CODESET_0 = ( 0 ), - Q931_CODESET_1 = ( 1 << 8 ), - Q931_CODESET_2 = ( 2 << 8 ), - Q931_CODESET_3 = ( 3 << 8 ), - Q931_CODESET_4 = ( 4 << 8 ), - Q931_CODESET_5 = ( 5 << 8 ), - Q931_CODESET_6 = ( 6 << 8 ), - Q931_CODESET_7 = ( 7 << 8 ) - -} q931_codeset_t; - -/* Single octet information elements */ -#define Q931ie_SHIFT 0x90 /* 1001 ---- */ -#define Q931ie_MORE_DATA 0xa0 /* 1010 ---- */ -#define Q931ie_SENDING_COMPLETE 0xa1 /* 1010 0001 */ -#define Q931ie_CONGESTION_LEVEL 0xb0 /* 1011 ---- */ -#define Q931ie_REPEAT_INDICATOR 0xd0 /* 1101 ---- */ - -/* Variable Length Information Elements */ -#define Q931ie_SEGMENTED_MESSAGE 0x00 /* 0000 0000 */ -#define Q931ie_CHANGE_STATUS 0x01 /* 0000 0001 */ -#define Q931ie_BEARER_CAPABILITY 0x04 /* 0000 0100 */ -#define Q931ie_CAUSE 0x08 /* 0000 1000 */ -#define Q931ie_CALL_IDENTITY 0x10 /* 0001 0000 */ -#define Q931ie_CALL_STATE 0x14 /* 0001 0100 */ -#define Q931ie_CHANNEL_IDENTIFICATION 0x18 /* 0001 1000 */ -#define Q931ie_PROGRESS_INDICATOR 0x1e /* 0001 1110 */ -#define Q931ie_NETWORK_SPECIFIC_FACILITIES 0x20 /* 0010 0000 */ -#define Q931ie_NOTIFICATION_INDICATOR 0x27 /* 0010 0111 */ -#define Q931ie_DISPLAY 0x28 /* 0010 1000 */ -#define Q931ie_DATETIME 0x29 /* 0010 1001 */ -#define Q931ie_KEYPAD_FACILITY 0x2c /* 0010 1100 */ -#define Q931ie_SIGNAL 0x34 /* 0011 0100 */ -#define Q931ie_SWITCHOOK 0x36 /* 0011 0110 */ -#define Q931ie_FEATURE_ACTIVATION 0x38 /* 0011 1000 */ -#define Q931ie_FEATURE_INDICATION 0x39 /* 0011 1001 */ -#define Q931ie_INFORMATION_RATE 0x40 /* 0100 0000 */ -#define Q931ie_END_TO_END_TRANSIT_DELAY 0x42 /* 0100 0010 */ -#define Q931ie_TRANSIT_DELAY_SELECTION_AND_IND 0x43 /* 0100 0011 */ -#define Q931ie_PACKED_LAYER_BIMARY_PARAMETERS 0x44 /* 0100 0100 */ -#define Q931ie_PACKED_LAYER_WINDOW_SIZE 0x45 /* 0100 0101 */ -#define Q931ie_PACKED_SIZE 0x46 /* 0100 0110 */ -#define Q931ie_CALLING_PARTY_NUMBER 0x6c /* 0110 1100 */ -#define Q931ie_CALLING_PARTY_SUBADDRESS 0x6d /* 0110 1101 */ -#define Q931ie_CALLED_PARTY_NUMBER 0x70 /* 0111 0000 */ -#define Q931ie_CALLED_PARTY_SUBADDRESS 0x71 /* 0111 0001 */ -#define Q931ie_REDIRECTING_NUMBER 0x74 /* 0111 0100 */ -#define Q931ie_TRANSIT_NETWORK_SELECTION 0x78 /* 0111 1000 */ -#define Q931ie_RESTART_INDICATOR 0x79 /* 0111 1001 */ -#define Q931ie_LOW_LAYER_COMPATIBILITY 0x7c /* 0111 1100 */ -#define Q931ie_HIGH_LAYER_COMPATIBILITY 0x7d /* 0111 1101 */ -#define Q931ie_USER_USER 0x7e /* 0111 1110 */ -#define Q931ie_ESCAPE_FOR_EX 0x7f /* 0111 1111 */ - -/* Variable Length Codeset 6 Information Elements */ -#define Q931ie_GENERIC_DIGITS 0x37 /* 0011 0111 */ - -/* Variable Length Information Element to shut up BRI testing */ -#define Q931ie_CONNECTED_NUMBER 0x4c /* 0100 1101 */ -#define Q931ie_FACILITY 0x1c /* 0001 1101 */ - - -/***************************************************************************** - - Struct: Q931ie_BearerCap - - Description: Bearer Capability Information Element. - -*****************************************************************************/ - -typedef struct { - - L3UCHAR IEId; /* 00000100 for Bearer Capability */ - L3UCHAR Size; /* Length of Information Element */ - - L3UCHAR CodStand; /* Coding Standard. */ - /* 00 - ITU-T */ - /* 01 - ISO/IEC */ - /* 10 - National standard */ - /* 11 - Network side spesific */ - - L3UCHAR ITC; /* Information Transfer Capability */ - /* 00000 - Speech */ - /* 01000 - Unrestricted digital info */ - /* 01001 - Restricted digital info */ - /* 10000 - 3.1 kHz audio */ - /* 10001 - Unrestricted with tones */ - /* 11000 - Video */ - - L3UCHAR TransMode; /* Transfer Mode. */ - /* 00 - Circuit mode */ - /* 10 - Packet mode */ - - L3UCHAR ITR; /* Information Transfer Rate. */ - /* 00000 - Packed mode */ - /* 10000 - 64 kbit/s */ - /* 10001 - 2 x 64 kbit/s */ - /* 10011 - 384 kbit/s */ - /* 10101 - 1536 kbit/s */ - /* 10111 - 1920 kbit/s */ - /* 11000 - Multirat (64 kbit/s base) */ - - L3UCHAR RateMul; /* Rate Multiplier */ - - L3UCHAR Layer1Ident; /* Layer 1 Ident. */ - - L3UCHAR UIL1Prot; /* User Information Layer 1 Protocol */ - /* 00001 : ITU-T V.110, I.460 and X.30 */ - /* 00010 : G.711 my-law */ - /* 00011 : G.711 A-law */ - /* 00100 : G.721 */ - /* 00101 : H.221 and H.242 */ - /* 00110 : H.223 and H.245 */ - /* 00111 : Non ITU-T Standard */ - /* 01000 : ITU-T V.120 */ - /* 01001 : ITU-T X.31 HDLC flag stuff. */ - - L3UCHAR SyncAsync; /* Sync/Async */ - /* 0 : Syncronous data */ - /* 1 : Asyncronous data */ - - L3UCHAR Negot; /* Negotiation */ - /* 0 : In-band negotiation not possib. */ - /* 1 : In-band negotiation possible */ - - L3UCHAR UserRate; /* User rate */ - /* 00000 : I.460, V.110, X,30 */ - /* 00001 : 0.6 kbit/s x.1 */ - /* 00010 : 1.2 kbit/s */ - /* 00011 : 2.4 kbit/s */ - /* 00100 : 3.6 kbit/s */ - /* 00101 : 4.8 kbit/s */ - /* 00110 : 7.2 kbit/s */ - /* 00111 : 8 kbit/s I.460 */ - /* 01000 : 9.6 kbit/s */ - /* 01001 : 14.4 kbit/s */ - /* 01010 : 16 kbit/s */ - /* 01011 : 19.2 kbit/s */ - /* 01100 : 32 kbit/s */ - /* 01101 : 38.4 kbit/s */ - /* 01110 : 48 kbit/s */ - /* 01111 : 56 kbit/s */ - /* 10000 : 57.6 kbit/s */ - /* 10010 : 28.8 kbit/s */ - /* 10100 : 24 kbit/s */ - /* 10101 : 0.1345 kbit/s */ - /* 10110 : 0.100 kbit/s */ - /* 10111 : 0.075/1.2 kbit/s */ - /* 11000 : 1.2/0.075/kbit/s */ - /* 11001 : 0.050 kbit/s */ - /* 11010 : 0.075 kbit/s */ - /* 11011 : 0.110 kbit/s */ - /* 11100 : 0.150 kbit/s */ - /* 11101 : 0.200 kbit/s */ - /* 11110 : 0.300 kbit/s */ - /* 11111 : 12 kbit/s */ - - L3UCHAR InterRate; /* Intermediate Rate */ - /* 00 : Not used */ - /* 01 : 8 kbit/s */ - /* 10 : 16 kbit/s */ - /* 11 : 32 kbit/s */ - - L3UCHAR NIConTx; /* Network Indepentend Clock on transmit*/ - /* 0 : Not required to send data clc */ - /* 1 : Send data w/NIC clc */ - - L3UCHAR NIConRx; /* NIC on Rx */ - /* 0 : Cannot accept indep. clc */ - /* 1 : data with indep. clc accepted */ - - L3UCHAR FlowCtlTx; /* Flow control on Tx */ - /* 0 : Send Flow ctrl not required */ - /* 1 : Send flow ctrl required */ - - L3UCHAR FlowCtlRx; /* Flow control on Rx */ - /* 0 : cannot use receive flow ctrl */ - /* 1 : Receive flow ctrl accepted */ - L3UCHAR HDR; /* HDR/No HDR */ - L3UCHAR MultiFrame; /* Multi frame support */ - /* 0 : multiframe not supported */ - /* 1 : multiframe supported */ - - L3UCHAR Mode; /* Mode of operation */ - /* 0 : bit transparent mode of operat. */ - /* 1 : protocol sesitive mode of op. */ - - L3UCHAR LLInegot; /* Logical link id negotiation (oct. 5b)*/ - /* 0 : default LLI=256 only */ - /* 1 : Full protocol negotiation */ - - L3UCHAR Assignor; /* Assignor/assignee */ - /* 0 : Default Asignee */ - /* 1 : Assignor only */ - - L3UCHAR InBandNeg; /* In-band/out-band negot. */ - /* 0 : negot done w/ USER INFO mes */ - /* 1 : negot done in-band w/link zero */ - - L3UCHAR NumStopBits; /* Number of stop bits */ - /* 00 : Not used */ - /* 01 : 1 bit */ - /* 10 : 1.5 bits */ - /* 11 : 2 bits */ - - L3UCHAR NumDataBits; /* Number of data bits. */ - /* 00 : not used */ - /* 01 : 5 bits */ - /* 10 : 7 bits */ - /* 11 : 8 bits */ - - L3UCHAR Parity; /* Parity Information */ - /* 000 : Odd */ - /* 010 : Even */ - /* 011 : None */ - /* 100 : Forced to 0 */ - /* 101 : Forced to 1 */ - - L3UCHAR DuplexMode; /* Mode duplex */ - /* 0 : Half duplex */ - /* 1 : Full duplex */ - - L3UCHAR ModemType; /* Modem type, see Q.931 p 64 */ - - L3UCHAR Layer2Ident; /* Layer 2 Ident */ - - L3UCHAR UIL2Prot; /* User Information Layer 2 Protocol */ - /* 00010 : Q.921/I.441 */ - /* 00110 : X.25 */ - /* 01100 : LAN logical link */ - - L3UCHAR Layer3Ident; /* Layer 3 ident. */ - - L3UCHAR UIL3Prot; /* User Information Layer 3 Protocol */ - /* 00010 : Q.931 */ - /* 00110 : X.25 */ - /* 01011 : ISO/IEC TR 9577 */ - - L3UCHAR AL3Info1; /* additional layer 3 info 1 */ - - L3UCHAR AL3Info2; /* additional layer 3 info 2 */ - -} Q931ie_BearerCap; - -/***************************************************************************** - - Struct: Q931ie_CallID - - -*****************************************************************************/ - -typedef struct { - - L3UCHAR IEId; /* 00010000 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR CallId[1]; /* Call identity */ - -} Q931ie_CallID; - -/***************************************************************************** - - Struct: Q931ie_CallState - - -*****************************************************************************/ - -typedef struct { - - L3UCHAR IEId; /* 00010100 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR CodStand; /* Coding Standard */ - L3UCHAR CallState; /* Call State Value */ - -} Q931ie_CallState; - -/***************************************************************************** - - Struct: Q931ie_Cause - - Description: Cause IE as described in Q.850 - -*****************************************************************************/ -typedef struct { - - L3UCHAR IEId; /* 00010100 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR CodStand; /* Coding Standard */ - L3UCHAR Location; /* Location */ - L3UCHAR Recom; /* Recommendation */ - L3UCHAR Value; /* Cause Value */ - L3UCHAR Diag[1]; /* Optional Diagnostics Field */ - -} Q931ie_Cause; - -/***************************************************************************** - - Struct: Q931ie_CalledNum - -*****************************************************************************/ -typedef struct { - - L3UCHAR IEId; /* 01110000 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR TypNum; /* Type of Number */ - L3UCHAR NumPlanID; /* Numbering plan identification */ - L3UCHAR Digit[1]; /* Digit (IA5) */ - -} Q931ie_CalledNum; - -/***************************************************************************** - - Struct: Q931ie_CalledSub - - Description: Called party subaddress - -*****************************************************************************/ - -typedef struct { - - L3UCHAR IEId; /* 01110001 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR TypNum; /* Type of subaddress */ - L3UCHAR OddEvenInd; /* Odd/Even indicator */ - L3UCHAR Digit[1]; /* digits */ - -} Q931ie_CalledSub; - -/***************************************************************************** - - Struct: Q931ie_CallingNum - - Description: Calling party number - -*****************************************************************************/ - -typedef struct { - - L3UCHAR IEId; /* 01101100 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR TypNum; /* Type of number */ - L3UCHAR NumPlanID; /* Numbering plan identification */ - L3UCHAR PresInd; /* Presentation indicator */ - L3UCHAR ScreenInd; /* Screening indicator */ - L3UCHAR Digit[1]; /* Number digits (IA5) */ - -} Q931ie_CallingNum; - -/***************************************************************************** - - Struct: Q931ie_CallingSub - - Description: Calling party subaddress - -*****************************************************************************/ - -typedef struct { - - L3UCHAR IEId; /* 01101101 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR TypNum; /* Type of subaddress */ - L3UCHAR OddEvenInd; /* Odd/Even indicator */ - L3UCHAR Digit[1]; /* digits */ - -} Q931ie_CallingSub; - -/***************************************************************************** - - Struct: Q931ie_ChanID - - Description: Channel identification - - Channel Identificationis one of the IE elements that differ - between BRI and PRI. IntType = 1 = BRI and ChanSlot is used - for channel number, while InfoChanSel is used for BRI. - - ChanID is one of the most important IE as it is passed - either though SETUP or CALL PROCEEDING to select the channel - to be used. - -*****************************************************************************/ - -typedef struct { - - L3UCHAR IEId; /* 00011000 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR IntIDPresent; /* Int. id. present */ - L3UCHAR IntType; /* Interface Type */ - /* 0 : Basic Interface (BRI) */ - /* 1 : Other interfaces, PRI etc. */ - - L3UCHAR PrefExcl; /* Pref./Excl. */ - /* 0 : Indicated channel is preffered */ - /* 1 : Exclusive, no other accepted */ - - L3UCHAR DChanInd; /* D-channel ind. */ - /* 0 : chan is NOT D chan. */ - /* 1 : chan is D chan */ - - L3UCHAR InfoChanSel; /* Info. channel selection */ - /* 00 : No channel */ - /* 01 : B1 channel */ - /* 10 : B2 channel */ - /* 11 : Any channel */ - - L3UCHAR InterfaceID; /* Interface identifier */ - - L3UCHAR CodStand; /* Code standard */ - /* 00 : ITU-T standardization coding */ - /* 01 : ISO/IEC Standard */ - /* 10 : National Standard */ - /* 11 : Standard def. by network. */ - - L3UCHAR NumMap; /* Number/Map */ - /* 0 : chan is in following octet */ - /* 1 : chan is indicated by slot map */ - - L3UCHAR ChanMapType; /* Channel type/Map element type */ - /* 0011 : B Channel units */ - /* 0110 : H0 channel units */ - /* 1000 : H11 channel units */ - /* 1001 : H12 channel units */ - - L3UCHAR ChanSlot; /* Channel number */ - -} Q931ie_ChanID; - -/***************************************************************************** - - Struct: Q931ie_DateTime - - Description: Date/time - -*****************************************************************************/ - -typedef struct { - - L3UCHAR IEId; /* 00101001 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR Year; /* Year */ - L3UCHAR Month; /* Month */ - L3UCHAR Day; /* Day */ - L3UCHAR Hour; /* Hour */ - L3UCHAR Minute; /* Minute */ - L3UCHAR Second; /* Second */ - L3UCHAR Format; /* Indicate presense of Hour, Min & sec */ - /* 0 : Only Date */ - /* 1 : Hour present */ - /* 2 : Hour and Minute present */ - /* 3 : Hour, Minute and Second present */ -} Q931ie_DateTime; - -/***************************************************************************** - - Struct: Q931ie_Display - - Description: Display - -*****************************************************************************/ - -typedef struct { - - L3UCHAR IEId; /* 00101000 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR Display[1]; /* Display information (IA5) */ - -} Q931ie_Display; - -/***************************************************************************** - - Struct: Q931ie_HLComp - - Description: High layer compatibility - -*****************************************************************************/ - -typedef struct { - - L3UCHAR IEId; /* 01111101 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR CodStand; /* Coding standard */ - L3UCHAR Interpret; /* Interpretation */ - L3UCHAR PresMeth; /* Presentation methor of prot. profile */ - L3UCHAR HLCharID; /* High layer characteristics id. */ - L3UCHAR EHLCharID; /* Extended high layer character. id. */ - L3UCHAR EVideoTlfCharID; /* Ext. videotelephony char. id. */ - -} Q931ie_HLComp; - -/***************************************************************************** - - Struct: Q931ie_KeypadFac - - Description: Keypad facility - -*****************************************************************************/ - -typedef struct { - L3UCHAR IEId; /* 00101100 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR KeypadFac[1]; /* dynamic buffer */ - -} Q931ie_KeypadFac; - -/***************************************************************************** - - Struct: Q931ie_LLComp - - Description: Low layer compatibility - -*****************************************************************************/ - -typedef struct { - - L3UCHAR IEId; /* 01111100 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR CodStand; /* Coding standard */ - /* 00 - ITU-T */ - /* 01 - ISO/IEC */ - /* 10 - National standard */ - /* 11 - Network side spesific */ - - L3UCHAR ITransCap; /* Information transfer capability */ - /* 00000 - Speech */ - /* 01000 - Unrestricted digital info */ - /* 01001 - Restricted digital info */ - /* 10000 - 3.1 kHz audio */ - /* 10001 - Unrestricted with tones */ - /* 11000 - Video */ - - L3UCHAR NegotInd; /* Negot indic. */ - /* 0 : Out-band neg. not possib. */ - /* 1 : Out-band neg. possible */ - - L3UCHAR TransMode; /* Transfer Mode */ - /* 00 : Circuit Mode */ - /* 10 : Packed Mode */ - - L3UCHAR InfoRate; /* Information transfer rate */ - /* 00000 - Packed mode */ - /* 10000 - 64 kbit/s */ - /* 10001 - 2 x 64 kbit/s */ - /* 10011 - 384 kbit/s */ - /* 10101 - 1536 kbit/s */ - /* 10111 - 1920 kbit/s */ - /* 11000 - Multirat (64 kbit/s base) */ - - L3UCHAR RateMul; /* Rate multiplier */ - L3UCHAR Layer1Ident; /* Layer 1 ident. */ - L3UCHAR UIL1Prot; /* User information layer 1 protocol */ - /* 00001 : ITU-T V.110, I.460 and X.30 */ - /* 00010 : G.711 my-law */ - /* 00011 : G.711 A-law */ - /* 00100 : G.721 */ - /* 00101 : H.221 and H.242 */ - /* 00110 : H.223 and H.245 */ - /* 00111 : Non ITU-T Standard */ - /* 01000 : ITU-T V.120 */ - /* 01001 : ITU-T X.31 HDLC flag stuff. */ - - L3UCHAR SyncAsync; /* Synch/asynch */ - /* 0 : Syncronous data */ - /* 1 : Asyncronous data */ - - L3UCHAR Negot; /* Negot */ - /* 0 : In-band negotiation not possib. */ - /* 1 : In-band negotiation possible */ - - L3UCHAR UserRate; /* User rate */ - /* 00000 : I.460, V.110, X,30 */ - /* 00001 : 0.6 kbit/s x.1 */ - /* 00010 : 1.2 kbit/s */ - /* 00011 : 2.4 kbit/s */ - /* 00100 : 3.6 kbit/s */ - /* 00101 : 4.8 kbit/s */ - /* 00110 : 7.2 kbit/s */ - /* 00111 : 8 kbit/s I.460 */ - /* 01000 : 9.6 kbit/s */ - /* 01001 : 14.4 kbit/s */ - /* 01010 : 16 kbit/s */ - /* 01011 : 19.2 kbit/s */ - /* 01100 : 32 kbit/s */ - /* 01101 : 38.4 kbit/s */ - /* 01110 : 48 kbit/s */ - /* 01111 : 56 kbit/s */ - /* 10000 : 57.6 kbit/s */ - /* 10010 : 28.8 kbit/s */ - /* 10100 : 24 kbit/s */ - /* 10101 : 0.1345 kbit/s */ - /* 10110 : 0.100 kbit/s */ - /* 10111 : 0.075/1.2 kbit/s */ - /* 11000 : 1.2/0.075/kbit/s */ - /* 11001 : 0.050 kbit/s */ - /* 11010 : 0.075 kbit/s */ - /* 11011 : 0.110 kbit/s */ - /* 11100 : 0.150 kbit/s */ - /* 11101 : 0.200 kbit/s */ - /* 11110 : 0.300 kbit/s */ - /* 11111 : 12 kbit/s */ - - L3UCHAR InterRate; /* Intermediate rate */ - /* 00 : Not used */ - /* 01 : 8 kbit/s */ - /* 10 : 16 kbit/s */ - /* 11 : 32 kbit/s */ - - L3UCHAR NIConTx; /* Network Indepentend Clock on transmit*/ - /* 0 : Not required to send data clc */ - /* 1 : Send data w/NIC clc */ - - L3UCHAR NIConRx; /* NIC on Rx */ - /* 0 : Cannot accept indep. clc */ - /* 1 : data with indep. clc accepted */ - - L3UCHAR FlowCtlTx; /* Flow control on Tx */ - /* 0 : Send Flow ctrl not required */ - /* 1 : Send flow ctrl required */ - - L3UCHAR FlowCtlRx; /* Flow control on Rx */ - /* 0 : cannot use receive flow ctrl */ - /* 1 : Receive flow ctrl accepted */ - L3UCHAR HDR; /* HDR/No HDR */ - L3UCHAR MultiFrame; /* Multi frame support */ - /* 0 : multiframe not supported */ - /* 1 : multiframe supported */ - - L3UCHAR ModeL1; /* Mode L1 */ - /* 0 : bit transparent mode of operat. */ - /* 1 : protocol sesitive mode of op. */ - - L3UCHAR NegotLLI; /* Negot. LLI */ - /* 0 : default LLI=256 only */ - /* 1 : Full protocol negotiation */ - - L3UCHAR Assignor; /* Assignor/Assignor ee */ - /* 0 : Default Asignee */ - /* 1 : Assignor only */ - - L3UCHAR InBandNeg; /* In-band negot. */ - /* 0 : negot done w/ USER INFO mes */ - /* 1 : negot done in-band w/link zero */ - - L3UCHAR NumStopBits; /* Number of stop bits */ - /* 00 : Not used */ - /* 01 : 1 bit */ - /* 10 : 1.5 bits */ - /* 11 : 2 bits */ - - L3UCHAR NumDataBits; /* Number of data bits. */ - /* 00 : not used */ - /* 01 : 5 bits */ - /* 10 : 7 bits */ - /* 11 : 8 bits */ - - L3UCHAR Parity; /* Parity Information */ - /* 000 : Odd */ - /* 010 : Even */ - /* 011 : None */ - /* 100 : Forced to 0 */ - /* 101 : Forced to 1 */ - - L3UCHAR DuplexMode; /* Mode duplex */ - /* 0 : Half duplex */ - /* 1 : Full duplex */ - - L3UCHAR ModemType; /* Modem type, see Q.931 p 89 */ - - L3UCHAR Layer2Ident; /* Layer 2 ident. */ - - L3UCHAR UIL2Prot; /* User information layer 2 protocol */ - /* 00001 : Basic mode ISO 1745 */ - /* 00010 : Q.921/I.441 */ - /* 00110 : X.25 single link */ - /* 00111 : X.25 multilink */ - /* 01000 : Extended LAPB T.71 */ - /* 01001 : HDLC ARM */ - /* 01010 : HDLC NRM */ - /* 01011 : HDLC ABM */ - /* 01100 : LAN logical link */ - /* 01101 : X.75 SLP */ - /* 01110 : Q.922 */ - /* 01111 : Q.922 core aspect */ - /* 10000 : User specified */ - /* 10001 : ISO/IEC 7776 DTE-DCE */ - - L3UCHAR ModeL2; /* Mode */ - /* 01 : Normal Mode of operation */ - /* 10 : Extended mode of operation */ - - L3UCHAR Q933use; /* Q.9333 use */ - - L3UCHAR UsrSpcL2Prot; /* User specified layer 2 protocol info */ - - L3UCHAR WindowSize; /* Window size (k) */ - - L3UCHAR Layer3Ident; /* Layer 3 ident */ - - L3UCHAR UIL3Prot; /* User Information Layer 3 protocol */ - /* 00010 : Q.931 */ - /* 00110 : X.25 */ - /* 00111 : 8208 */ - /* 01000 : X.233 ... */ - /* 01001 : 6473 */ - /* 01010 : T.70 */ - /* 01011 : ISO/IEC TR 9577 */ - /* 10000 : User specified */ - L3UCHAR OptL3Info; /* Optional Leyer 3 info */ - - L3UCHAR ModeL3; /* Mode of operation */ - /* 01 : Normal packed seq. numbering */ - /* 10 : Extended packed seq. numbering */ - - L3UCHAR DefPackSize; /* Default packet size */ - - L3UCHAR PackWinSize; /* Packet window size */ - - L3UCHAR AddL3Info; /* Additional Layer 3 protocol info */ - -} Q931ie_LLComp; - -/***************************************************************************** - - Struct: Q931ie_NetFac; - - Description: Network-specific facilities - -*****************************************************************************/ - -typedef struct { - - L3UCHAR IEId; /* 00100000 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR LenNetID; /* Length of network facilities id. */ - L3UCHAR TypeNetID; /* Type of network identification */ - L3UCHAR NetIDPlan; /* Network identification plan. */ - L3UCHAR NetFac; /* Network specific facility spec. */ - L3UCHAR NetID[1]; /* Network id. (IA5) */ - -} Q931ie_NetFac; - -/***************************************************************************** - - Struct: Q931ie_NotifInd; - - Description: Notification Indicator - -*****************************************************************************/ - -typedef struct { - - L3UCHAR IEId; /* 00100000 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR Notification; /* Notification descriptor */ - -} Q931ie_NotifInd; - -/***************************************************************************** - - Struct: Q931ie_ProgInd - - Description: Progress indicator - -*****************************************************************************/ - -typedef struct { - - L3UCHAR IEId; /* 00011110 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR CodStand; /* Coding standard */ - L3UCHAR Location; /* Location */ - L3UCHAR ProgDesc; /* Progress description */ - -} Q931ie_ProgInd; - -/***************************************************************************** - - Struct; Q931ie_Segment - - Description: Segmented message - -*****************************************************************************/ - -typedef struct { - - L3UCHAR IEId; /* 00000000 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR FSI; /* First segment indicator */ - L3UCHAR NumSegRem; /* Number of segments remaining */ - L3UCHAR SegType; /* Segment message type */ - -} Q931ie_Segment; - - -typedef struct { - - L3UCHAR IEId; /* 00000000 */ - L3UCHAR Size; /* Length of Information Element */ - -} Q931ie_SendComplete; - -/***************************************************************************** - - Struct: Q931ie_Signal - - Description: Signal - -*****************************************************************************/ - -typedef struct { - - L3UCHAR IEId; /* 00000000 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR Signal; /* Signal value */ - /* 00000000 Dial tone on */ - /* 00000001 Ring back tone on */ - /* 00000010 Intercept tone on */ - /* 00000011 Network congestion on */ - /* 00000100 Busy tone on */ - /* 00000101 Confirm tone on */ - /* 00000110 Answer tone on */ - /* 00000111 Call waiting tone */ - /* 00001000 Off-hook warning tone */ - /* 00001001 Pre-emption tone on */ - /* 00111111 Tones off */ - /* 01000000 Alerting on - pattern 0 */ - /* 01000001 Alerting on - pattern 1 */ - /* 01000010 Alerting on - pattern 2 */ - /* 01000011 Alerting on - pattern 3 */ - /* 01000100 Alerting on - pattern 4 */ - /* 01000101 Alerting on - pattern 5 */ - /* 01000110 Alerting on - pattern 6 */ - /* 01000111 Alerting on - pattern 7 */ - /* 01001111 Alerting off */ -} Q931ie_Signal; - -/***************************************************************************** - - Struct: Q931ie_TransDelSelInd - - description: Transit delay selection and indication - -*****************************************************************************/ -#ifdef Q931_X25_SUPPORT -typedef struct { - - L3UCHAR IEId; /* 00000000 */ - L3UCHAR Size; /* Length of Information Element */ - L3ULONG TxDSIValue; /* Trans. delay sel. & ind. value */ - -} Q931ie_TransDelSelInd; -#endif - -/***************************************************************************** - - Struct: Q931ie_TransNetSel - - Description: Transit network selection - -*****************************************************************************/ - -typedef struct { - - L3UCHAR IEId; /* 01111000 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR Type; /* Type of network identifier */ - L3UCHAR NetIDPlan; /* Network idetification plan */ - L3UCHAR NetID[1]; /* Network identification(IA5) */ - -} Q931ie_TransNetSel; - -/***************************************************************************** - - Struct: Q931ie_UserUser - - Description: User-user - -*****************************************************************************/ - -typedef struct { - - L3UCHAR IEId; /* 01111110 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR ProtDisc; /* Protocol discriminator */ - L3UCHAR User[1]; /* User information */ - -} Q931ie_UserUser; - -/***************************************************************************** - - Struct: Q931ie_ClosedUserGrp - - Description: Closed user group - -*****************************************************************************/ -#ifdef Q931_X25_SUPPORT -typedef struct { - - L3UCHAR IEId; /* 01000111 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR CUGInd; /* CUG indication */ - L3UCHAR CUG[1]; /* CUG index code (IA5) */ - -} Q931ie_ClosedUserGrp; -#endif - -/***************************************************************************** - - Struct: Q931ie_CongLevel - - Description: Congestion Level - -*****************************************************************************/ -typedef struct { - - L3UCHAR IEId; /* 01000111 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR CongLevel; /* Conguestion Level */ - -} Q931ie_CongLevel; - -/***************************************************************************** - - Struct: Q931ie_EndEndTxDelay - - Description: End to end transit delay - -*****************************************************************************/ -#ifdef Q931_X25_SUPPORT -typedef struct { - - L3UCHAR IEId; /* 01000010 */ - L3UCHAR Size; /* Length of Information Element */ - L3ULONG CumTxDelay; /* Cumulative transit delay value */ - L3ULONG ReqTxDelay; /* Requested end to end transit delay */ - L3ULONG MaxTxDelay; /* Maximum transit delay */ - -} Q931ie_EndEndTxDelay; -#endif - -/***************************************************************************** - - Struct: Q931ie_InfoRate - - Description: Information Rate - -*****************************************************************************/ -#ifdef Q931_X25_SUPPORT -typedef struct { - - L3UCHAR IEId; /* 01100000 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR InInfoRate; /* Incoming information rate */ - L3UCHAR OutInfoRate; /* Outgoing information rate */ - L3UCHAR MinInInfoRate; /* Minimum incoming information rate */ - L3UCHAR MinOutInfoRate; /* Minimum outgoing information rate */ - -} Q931ie_InfoRate; -#endif - -/***************************************************************************** - - Struct: Q931ie_PackParam - - Description: Packed layer binary parameters - -*****************************************************************************/ -#ifdef Q931_X25_SUPPORT -typedef struct { - - L3UCHAR IEId; /* 01000100 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR FastSel; /* Fast selected */ - L3UCHAR ExpData; /* Exp. data */ - L3UCHAR DelConf; /* Delivery conf */ - L3UCHAR Modulus; /* Modulus */ - -} Q931ie_PackParam; -#endif - -/***************************************************************************** - - Struct: Q931ie_PackWinSize - - Description: Packed window size - -*****************************************************************************/ -#ifdef Q931_X25_SUPPORT -typedef struct { - - L3UCHAR IEId; /* 01000101 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR ForwardValue; /* Forward value */ - L3UCHAR BackwardValue; /* Backward value */ - -} Q931ie_PackWinSize; -#endif - -/***************************************************************************** - - Struct: Q931ie_PackSize - - Description: Packet size - -*****************************************************************************/ -#ifdef Q931_X25_SUPPORT -typedef struct { - - L3UCHAR IEId; /* 01000110 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR ForwardValue; /* Forward value */ - L3UCHAR BackwardValue; /* Backward value */ - -} Q931ie_PackSize; -#endif - -/***************************************************************************** - - Struct: Q931ie_RedirNum - - Description: Redirecting number - -*****************************************************************************/ -#ifdef Q931_X25_SUPPORT -typedef struct { - - L3UCHAR IEId; /* 01110100 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR TypeNum; /* Type of number */ - L3UCHAR NumPlanID; /* Number plan identification */ - L3UCHAR PresInd; /* Presentation indicator */ - L3UCHAR ScreenInd; /* Screening indicator */ - L3UCHAR Reason; /* Reason for redirection */ - L3UCHAR Digit[1]; /* Number digits (IA5) */ - -} Q931ie_RedirNum; -#endif - -typedef struct { - - L3UCHAR IEId; /* 01110100 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR RepeatInd; /* 0010 Prioritized list for selecting */ - /* one possible. */ -} Q931ie_RepeatInd; - -typedef struct { - - L3UCHAR IEId; /* 01110100 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR Spare; /* Spare */ - L3UCHAR Class; /* Class */ - /* 000 Indicate channels */ - /* 110 Single interface */ - /* 111 All interfaces */ -} Q931ie_RestartInd; - -typedef struct { - - L3UCHAR IEId; /* 01110100 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR Preference; /* Preference 0 = reserved, 1 = channel */ - L3UCHAR Spare; /* Spare */ - L3UCHAR NewStatus; /* NewStatus */ - /* 000 In service */ - /* 001 Maintenance */ - /* 010 Out of service */ -} Q931ie_ChangeStatus; - -/***************************************************************************** - - Struct: Q931ie_GenericDigits - - -*****************************************************************************/ - -typedef struct { - - L3UCHAR IEId; /* 00110111 */ - L3UCHAR Size; /* Length of Information Element */ - L3UCHAR Type; /* Type of number */ - L3UCHAR Encoding; /* Encoding of number */ - L3UCHAR Digit[1]; /* Number digits (IA5) */ - -} Q931ie_GenericDigits; - - -/***************************************************************************** - - Q.931 Information Element Pack/Unpack functions. Implemented in Q931ie.c - -*****************************************************************************/ -q931pie_func_t Q931Pie_ChangeStatus; -q931pie_func_t Q931Pie_BearerCap; -q931pie_func_t Q931Pie_ChanID; -q931pie_func_t Q931Pie_ProgInd; -q931pie_func_t Q931Pie_Display; -q931pie_func_t Q931Pie_Signal; -q931pie_func_t Q931Pie_HLComp; -q931pie_func_t Q931Pie_Segment; -q931pie_func_t Q931Pie_DateTime; -q931pie_func_t Q931Pie_Cause; -q931pie_func_t Q931Pie_SendComplete; -q931pie_func_t Q931Pie_KeypadFac; -q931pie_func_t Q931Pie_NotifInd; -q931pie_func_t Q931Pie_CallID; -q931pie_func_t Q931Pie_RepeatInd; -q931pie_func_t Q931Pie_NetFac; -q931pie_func_t Q931Pie_CallingNum; -q931pie_func_t Q931Pie_CallingSub; -q931pie_func_t Q931Pie_CalledNum; -q931pie_func_t Q931Pie_CalledSub; -q931pie_func_t Q931Pie_CalledNum; -q931pie_func_t Q931Pie_TransNetSel; -q931pie_func_t Q931Pie_LLComp; -q931pie_func_t Q931Pie_CallState; -q931pie_func_t Q931Pie_RestartInd; -q931pie_func_t Q931Pie_UserUser; - -q931pie_func_t Q931Pie_GenericDigits; - -L3USHORT Q931Uie_CRV(Q931_TrunkInfo_t *pTrunk,L3UCHAR * IBuf, L3UCHAR *OBuf, L3INT *IOff, L3INT *OOff); - -q931uie_func_t Q931Uie_ChangeStatus; -q931uie_func_t Q931Uie_BearerCap; -q931uie_func_t Q931Uie_ChanID; -q931uie_func_t Q931Uie_ProgInd; -q931uie_func_t Q931Uie_Display; -q931uie_func_t Q931Uie_Signal; -q931uie_func_t Q931Uie_HLComp; -q931uie_func_t Q931Uie_Segment; -q931uie_func_t Q931Uie_DateTime; -q931uie_func_t Q931Uie_Cause; -q931uie_func_t Q931Uie_SendComplete; -q931uie_func_t Q931Uie_KeypadFac; -q931uie_func_t Q931Uie_NotifInd; -q931uie_func_t Q931Uie_CallID; -q931uie_func_t Q931Uie_RepeatInd; -q931uie_func_t Q931Uie_NetFac; -q931uie_func_t Q931Uie_CallingNum; -q931uie_func_t Q931Uie_CallingSub; -q931uie_func_t Q931Uie_CalledNum; -q931uie_func_t Q931Uie_CalledSub; -q931uie_func_t Q931Uie_TransNetSel; -q931uie_func_t Q931Uie_LLComp; -q931uie_func_t Q931Uie_CallState; -q931uie_func_t Q931Uie_RestartInd; -q931uie_func_t Q931Uie_UserUser; - -q931uie_func_t Q931Uie_GenericDigits; - - -L3INT Q931ReadExt(L3UCHAR * IBuf, L3INT Off); -L3INT Q931Uie_CongLevel(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff); -L3INT Q931Pie_CongLevel(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet); -L3INT Q931Uie_RevChargeInd(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff); -L3INT Q931Pie_RevChargeInd(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet); - -L3INT Q931Uie_Generic(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *IOff, L3INT *OOff); -L3INT Q931Pie_Generic(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet); - -#endif /* _Q931IE_NL */ diff --git a/libs/freetdm/src/isdn/include/Q932.h b/libs/freetdm/src/isdn/include/Q932.h deleted file mode 100644 index 9b69a34a02..0000000000 --- a/libs/freetdm/src/isdn/include/Q932.h +++ /dev/null @@ -1,95 +0,0 @@ -/***************************************************************************** - - FileName: Q932.h - - Contents: Header w/structs for Q932 Suplementary Services. - - NB: Do NOT include this header directly, include Q931.h - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** - Q.932 Additional Message codes -*****************************************************************************/ - -#define Q932mes_HOLD 0x24 /* 0010 0100 */ -#define Q932mes_HOLD_ACKNOWLEDGE 0x28 /* 0010 1000 */ -#define Q932mes_HOLD_REJECT 0x30 /* 0011 0000 */ -#define Q932mes_RETRIEVE 0x31 /* 0011 0001 */ -#define Q932mes_RETRIEVE_ACKNOWLEDGE 0x33 /* 0011 0011 */ -#define Q932mes_RETRIEVE_REJECT 0x37 /* 0011 0111 */ -#define Q932mes_FACILITY 0x62 /* 0110 0010 */ -#define Q932mes_REGISTER 0x64 /* 0110 0100 */ - -/***************************************************************************** - Q.932 Additional EI Codes -*****************************************************************************/ -#define Q932ie_FACILITY 0x1c /* 0001 1100 */ - -/***************************************************************************** - Function Prototypes. -*****************************************************************************/ -L3INT Q932ProcFacilityTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT iFrom); -L3INT Q932ProcHoldTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT iFrom); -L3INT Q932ProcHoldAckTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT iFrom); -L3INT Q932ProcHoldRejectTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT iFrom); -L3INT Q932ProcRegisterTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT iFrom); -L3INT Q932ProcRetrieveTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT iFrom); -L3INT Q932ProcRetrieveAckTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT iFrom); -L3INT Q932ProcRetrieveRejectTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT iFrom); - -L3INT Q932ProcFacilityNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT iFrom); -L3INT Q932ProcHoldNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT iFrom); -L3INT Q932ProcHoldAckNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT iFrom); -L3INT Q932ProcHoldRejectNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT iFrom); -L3INT Q932ProcRegisterNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT iFrom); -L3INT Q932ProcRetrieveNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT iFrom); -L3INT Q932ProcRetrieveAckNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT iFrom); -L3INT Q932ProcRetrieveRejectNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT iFrom); - -L3INT Q932Pmes_Facility(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q932Pmes_Hold(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q932Pmes_HoldAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q932Pmes_HoldReject(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q932Pmes_Register(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q932Pmes_Retrieve(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q932Pmes_RetrieveAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); -L3INT Q932Pmes_RetrieveReject(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); - -L3INT Q932Umes_Facility(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic * OBuf, L3INT I, L3INT O); -L3INT Q932Umes_Hold(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic * OBuf, L3INT I, L3INT O); -L3INT Q932Umes_HoldAck(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic * OBuf, L3INT I, L3INT O); -L3INT Q932Umes_HoldReject(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic * OBuf, L3INT I, L3INT O); -L3INT Q932Umes_Register(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic * OBuf, L3INT I, L3INT O); -L3INT Q932Umes_Retrieve(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic * OBuf, L3INT I, L3INT O); -L3INT Q932Umes_RetrieveAck(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic * OBuf, L3INT I, L3INT O); -L3INT Q932Umes_RetrieveReject(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic * OBuf, L3INT I, L3INT O); diff --git a/libs/freetdm/src/isdn/include/mfifo.h b/libs/freetdm/src/isdn/include/mfifo.h deleted file mode 100644 index 4c1d850d81..0000000000 --- a/libs/freetdm/src/isdn/include/mfifo.h +++ /dev/null @@ -1,85 +0,0 @@ -/***************************************************************************** - - Filename: mfifo.h - - Contents: header for MFIFO - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ -#ifndef _MFIFO -#define _MFIFO - -/***************************************************************************** - - Struct: MINDEX - - Description: Message Index used to index a dynamic size Message FIFO. - -*****************************************************************************/ -typedef struct _mindex { - int offset; /* offset to message in buf */ - int size; /* size of message in bytes */ -} MINDEX; - -/***************************************************************************** - - Struct: MFIFO - - Description: Message FIFO. Provides a dynamic sized message based FIFO - queue. - -*****************************************************************************/ -typedef struct { - int first; /* first out */ - int last; /* last in + 1 */ - int bsize; /* buffer size */ - unsigned char *buf; /* ptr to start of buffer */ - int ixsize; /* index size */ - MINDEX ix[1]; /* message index */ -} MFIFO; - -/***************************************************************************** - Function prototypes. -*****************************************************************************/ -int MFIFOCreate(unsigned char *buf, int size, int index); -void MFIFOClear(unsigned char * buf); -int MFIFOGetLBOffset(unsigned char *buf); -int MFIFOGetFBOffset(unsigned char *buf); -void MFIFOWriteIX(unsigned char *buf, unsigned char *mes, int size, int ix, int off); -int MFIFOWriteMes(unsigned char *buf, unsigned char *mes, int size); -unsigned char * MFIFOGetMesPtr(unsigned char *buf, int *size); -void MFIFOKillNext(unsigned char *buf); - -unsigned char * MFIFOGetMesPtrOffset(unsigned char *buf, int *size, const int pos); -int MFIFOGetMesCount(unsigned char *buf); -int MFIFOWriteMesOverwrite(unsigned char *buf, unsigned char *mes, int size); - -#endif diff --git a/libs/freetdm/src/isdn/include/national.h b/libs/freetdm/src/isdn/include/national.h deleted file mode 100644 index cff26aa4a4..0000000000 --- a/libs/freetdm/src/isdn/include/national.h +++ /dev/null @@ -1,86 +0,0 @@ -/****************************************************************************** - - FileName: national.h - - Contents: Header and definition for the National ISDN dialect. The - header contents the following parts: - - Definition of codes - - Definition of information elements (nationalie_). - - Definition of messages (nationalmes_). - - Function prototypes. - - Description: The National ISDN dialect here covers ???? - - Related Files: national.h National ISDN Definitions - nationalie.c National ISDN IE encoders/coders - nationalStateTE.c National ISDN TE State Engine - nationalStateNT.c National ISDN NT State Engine - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Copyright (c) 2007, Michael Jerris. All rights reserved. - email:mike@jerris.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -******************************************************************************/ - -#ifndef _national_NATIONAL_NL -#define _national_NATIONAL_NL - -#include "Q931.h" - -/***************************************************************************** - - Q.931 Message codes - Only National specific message and ie types - here the rest are inherited from national.h - -*****************************************************************************/ - - -/***************************************************************************** - - Q.931 Message Pack/Unpack functions. Implemented in nationalmes.c - -*****************************************************************************/ -L3INT nationalUmes_Setup(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT IOff, L3INT Size); -L3INT nationalPmes_Setup(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize); - -#include "DMS.h" - -/***************************************************************************** - - Q.931 Process Function Prototyping. Implemented in nationalStateTE.c - -*****************************************************************************/ - -void nationalCreateTE(L3UCHAR i); -void nationalCreateNT(L3UCHAR i); - -#endif /* _national_NATIONAL_NL */ diff --git a/libs/freetdm/src/isdn/mfifo.c b/libs/freetdm/src/isdn/mfifo.c deleted file mode 100644 index 28528f9b64..0000000000 --- a/libs/freetdm/src/isdn/mfifo.c +++ /dev/null @@ -1,399 +0,0 @@ -/***************************************************************************** - - Filename: mfifo.c - - Description: mfifo is a message orriented fifo system with support of - both message and byte per byte retriaval of messages. - - The fifo has been designed with two usages in mind: - - - Queueing of frames for hdlc and feeding out byte per byte - with the possibility of re-sending of frames etc. - - - fifo for messages of dynamic size. - - The fifo is allocated on top of any buffer and creates an - index of message in the queue. The user can write/read - messages or write messages and read the message one byte - at the time. - - Interface: - MFIFOCreate Create/reset/initialize fifo. - MFIFOClear Clear FIFO. - MFIFOWriteMes Write message into fifo - * MFIFOReadMes Read message from fifo. - MFIFOGetMesPtr Get ptr to next message. - MFIFOKillNext Kill next message. - - * currently not implemented. - - Note: The message will always be saved continuously. If there is not - sufficient space at the end of the buffer, the fifo will skip - the last bytes and save the message at the top of the buffer. - - This is required to allow direct ptr access to messages - stored in the queue. - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -#include "mfifo.h" -#include -#include - -/***************************************************************************** - - Function: MFIFOCreate - - Description: Creates a fifo on top of an existing buffer. - - Parameters: buf ptr to buffer. - size size of buffer in bytes. - index size of index entries (max no messages). - - Return value: 0 if failure, 1 if ok. - -*****************************************************************************/ -int MFIFOCreate(unsigned char *buf, int size, int index) -{ - MFIFO *mf = (MFIFO *)buf; - - mf->first = mf->last = 0; - mf->ixsize = index; - mf->buf = &buf[sizeof(MFIFO) + (sizeof(MINDEX) * index)]; - - if (mf->buf > &buf[size]) - return 0; - - mf->bsize = size - sizeof(MFIFO) - (sizeof(MINDEX) * index); - - return 1; -} - -/***************************************************************************** - - Function: MFIFOClear - - Description: Clear the FIFO - - Paremeters: buf ptr to fifo - - Return Value: none - -*****************************************************************************/ -void MFIFOClear(unsigned char * buf) -{ - MFIFO *mf = (MFIFO *)buf; - - mf->first = mf->last = 0; -} - -/***************************************************************************** - - Function: MFIFOGetLBOffset - - Description: Helper function caclulating offset to the 'first out' byte. - - Paremeters: buf ptr to fifo - - Return Value: offset. - -*****************************************************************************/ -int MFIFOGetLBOffset(unsigned char *buf) -{ - MFIFO *mf = (MFIFO *)buf; - - if (mf->last != mf->first) - return mf->ix[mf->last].offset; - - return 0; -} - -/***************************************************************************** - - Function: MFIFOGetFBOffset - - Description: Helper function calculating the offset to the 'first in' - byte in the buffer. This is the position the next byte - entering the fifo will occupy. - - Paremeters: buf ptr to fifo - - Return Value: offset - -*****************************************************************************/ -int MFIFOGetFBOffset(unsigned char *buf) -{ - MFIFO *mf = (MFIFO *)buf; - int x; - - if (mf->last == mf->first) - return 0; - - x = mf->first - 1; - - if (x < 0) - x = mf->ixsize - 1; - - return mf->ix[x].offset + mf->ix[x].size; -} - -/***************************************************************************** - - Function: MFIFOWriteIX - - Description: Helper function writing a calculated entry. The function - will perform a memcpy to move the message and set the index - values as well as increase the 'first in' index. - - Paremeters: buf ptr to fifo - mes ptr to message - size size of message in bytes. - ix index to index entry. - off offset to position to receive the message - - Return Value: none - -*****************************************************************************/ -void MFIFOWriteIX(unsigned char *buf, unsigned char *mes, int size, int ix, int off) -{ - MFIFO *mf = (MFIFO *)buf; - int x; - - memcpy(&mf->buf[off], mes, size); - mf->ix[ix].offset = off; - mf->ix[ix].size = size; - - x = mf->first + 1; - - if (x >= mf->ixsize) - x = 0; - - mf->first = x; -} - -/***************************************************************************** - - Function: MFIFOWriteMes - - Description: - - Paremeters: - - Return Value: - -*****************************************************************************/ -int MFIFOWriteMes(unsigned char *buf, unsigned char *mes, int size) -{ - MFIFO *mf = (MFIFO *)buf; - int of, ol, x; - - x = mf->first + 1; - - if (x >= mf->ixsize) - x = 0; - - if (x == mf->last) - return 0; /* full queue */ - - of = MFIFOGetFBOffset(buf); - ol = MFIFOGetLBOffset(buf); - if (mf->last == mf->first) { /* empty queue */ - mf->first = mf->last = 0; /* optimize */ - - MFIFOWriteIX(buf, mes, size, mf->first, 0); - return 1; - } - else if (of > ol) { - if (mf->bsize - of >= size) { - MFIFOWriteIX(buf, mes, size, mf->first, of); - return 1; - } - else if (ol > size) { - MFIFOWriteIX(buf, mes, size, mf->first, ol); - return 1; - } - } - else if (ol - of > size) { - MFIFOWriteIX(buf, mes, size, mf->first, of); - return 1; - } - - return 0; -} - -/***************************************************************************** - - Function: MFIFOGetMesPtr - - Description: - - Paremeters: - - Return Value: - -*****************************************************************************/ -unsigned char * MFIFOGetMesPtr(unsigned char *buf, int *size) -{ - MFIFO *mf = (MFIFO *)buf; - - if (mf->first == mf->last) { - return NULL; - } - - *size = mf->ix[mf->last].size; - return &mf->buf[mf->ix[mf->last].offset]; -} - -/***************************************************************************** - - Function: MFIFOKillNext - - Description: - - Paremeters: - - Return Value: - -*****************************************************************************/ -void MFIFOKillNext(unsigned char *buf) -{ - MFIFO *mf = (MFIFO *)buf; - int x; - - if (mf->first != mf->last) { - x = mf->last + 1; - if (x >= mf->ixsize) { - x = 0; - } - - mf->last = x; - } -} - - -/* - * Queue-style accessor functions - */ - -/** - * MFIFOGetMesPtrOffset - * \brief Get pointer to and size of message at position x - */ -unsigned char * MFIFOGetMesPtrOffset(unsigned char *buf, int *size, const int pos) -{ - MFIFO *mf = (MFIFO *)buf; - int x; - - if (mf->first == mf->last) { - return NULL; - } - - if (pos < 0 || pos >= mf->ixsize) { - return NULL; - } - - x = pos - mf->last; - if (x < 0) { - x += (mf->ixsize - 1); - } - - *size = mf->ix[x].size; - return &mf->buf[mf->ix[x].offset]; -} - - -/** - * MFIFOGetMesCount - * \brief How many messages are currently in the buffer? - */ -int MFIFOGetMesCount(unsigned char *buf) -{ - MFIFO *mf = (MFIFO *)buf; - - if (mf->first == mf->last) { - return 0; - } - else if (mf->first > mf->last) { - return mf->first - mf->last; - } - else { - return (mf->ixsize - mf->last) + mf->first; - } -} - -/** - * MFIFOWriteMesOverwrite - * \brief Same as MFIFOWriteMes but old frames will be overwritten if the fifo is full - */ -int MFIFOWriteMesOverwrite(unsigned char *buf, unsigned char *mes, int size) -{ - MFIFO *mf = (MFIFO *)buf; - int of, ol, x; - - x = mf->first + 1; - - if (x >= mf->ixsize) - x = 0; - - if (x == mf->last) { - /* advance last pointer */ - mf->last++; - - if (mf->last >= mf->ixsize) - mf->last = 0; - } - - of = MFIFOGetFBOffset(buf); - ol = MFIFOGetLBOffset(buf); - - if (mf->last == mf->first) { /* empty queue */ - mf->first = mf->last = 0; /* optimize */ - - MFIFOWriteIX(buf, mes, size, mf->first, 0); - return 1; - } - else if (of > ol) { - if (mf->bsize - of >= size) { - MFIFOWriteIX(buf, mes, size, mf->first, of); - return 1; - } - else if (ol > size) { - MFIFOWriteIX(buf, mes, size, mf->first, ol); - return 1; - } - } - else if (ol - of > size) { - MFIFOWriteIX(buf, mes, size, mf->first, of); - return 1; - } - return 0; -} diff --git a/libs/freetdm/src/isdn/nationalStateNT.c b/libs/freetdm/src/isdn/nationalStateNT.c deleted file mode 100644 index b150999650..0000000000 --- a/libs/freetdm/src/isdn/nationalStateNT.c +++ /dev/null @@ -1,130 +0,0 @@ -/***************************************************************************** - - FileName: nationalStateNT.c - - Contents: National ISDN State Engine for NT (Network Mode). - - The controlling state engine for Q.931 is the state engine - on the NT side. The state engine on the TE side is a slave - of this. The TE side maintain it's own states as described in - ITU-T Q931, but will in raise conditions be overridden by - the NT side. - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Copyright (c) 2007, Michael Jerris. All rights reserved. - email:mike@jerris.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -#include "national.h" - -/***************************************************************************** - Function: nationalCreateNT - - Description: Will create the National ISDN NT as a Dialect in the stack. The first - bulk set up the message handlers, the second bulk the IE - encoders/coders, and the last bulk set up the state table. - - Parameters: i Dialect index -*****************************************************************************/ -void nationalCreateNT(L3UCHAR i) -{ - Q931SetMesProc(Q931mes_ALERTING, i, Q931ProcAlertingNT, Q931Umes_Alerting, Q931Pmes_Alerting); - Q931SetMesProc(Q931mes_CALL_PROCEEDING, i, Q931ProcCallProceedingNT, Q931Umes_CallProceeding, Q931Pmes_CallProceeding); - Q931SetMesProc(Q931mes_CONNECT, i, Q931ProcConnectNT, Q931Umes_Connect, Q931Pmes_Connect); - Q931SetMesProc(Q931mes_CONNECT_ACKNOWLEDGE, i, Q931ProcConnectAckNT, Q931Umes_ConnectAck, Q931Pmes_ConnectAck); - Q931SetMesProc(Q931mes_PROGRESS, i, Q931ProcProgressNT, Q931Umes_Progress, Q931Pmes_Progress); - Q931SetMesProc(Q931mes_SETUP, i, Q931ProcSetupNT, nationalUmes_Setup, nationalPmes_Setup); - Q931SetMesProc(Q931mes_SETUP_ACKNOWLEDGE, i, Q931ProcSetupAckNT, Q931Umes_SetupAck, Q931Pmes_SetupAck); - Q931SetMesProc(Q931mes_RESUME, i, Q931ProcResumeNT, Q931Umes_Resume, Q931Pmes_Resume); - Q931SetMesProc(Q931mes_RESUME_ACKNOWLEDGE, i, Q931ProcResumeAckNT, Q931Umes_ResumeAck, Q931Pmes_ResumeAck); - Q931SetMesProc(Q931mes_RESUME_REJECT, i, Q931ProcResumeRejectNT, Q931Umes_ResumeReject, Q931Pmes_ResumeReject); - Q931SetMesProc(Q931mes_SUSPEND, i, Q931ProcSuspendNT, Q931Umes_Suspend, Q931Pmes_Suspend); - Q931SetMesProc(Q931mes_SUSPEND_ACKNOWLEDGE, i, Q931ProcSuspendAckNT, Q931Umes_SuspendAck, Q931Pmes_SuspendAck); - Q931SetMesProc(Q931mes_SUSPEND_REJECT, i, Q931ProcSuspendRejectNT, Q931Umes_SuspendReject, Q931Pmes_SuspendReject); - Q931SetMesProc(Q931mes_USER_INFORMATION, i, Q931ProcUserInformationNT, Q931Umes_UserInformation, Q931Pmes_UserInformation); - Q931SetMesProc(Q931mes_DISCONNECT, i, Q931ProcDisconnectNT, Q931Umes_Disconnect, Q931Pmes_Disconnect); - Q931SetMesProc(Q931mes_RELEASE, i, Q931ProcReleaseNT, Q931Umes_Release, Q931Pmes_Release); - Q931SetMesProc(Q931mes_RELEASE_COMPLETE, i, Q931ProcReleaseCompleteNT, Q931Umes_ReleaseComplete, Q931Pmes_ReleaseComplete); - Q931SetMesProc(Q931mes_RESTART, i, Q931ProcRestartNT, Q931Umes_Restart, Q931Pmes_Restart); - Q931SetMesProc(Q931mes_RESTART_ACKNOWLEDGE, i, Q931ProcRestartAckNT, Q931Umes_RestartAck, Q931Pmes_RestartAck); - Q931SetMesProc(Q931mes_CONGESTION_CONTROL, i, Q931ProcCongestionControlNT, Q931Umes_CongestionControl, Q931Pmes_CongestionControl); - Q931SetMesProc(Q931mes_INFORMATION, i, Q931ProcInformationNT, Q931Umes_Information, Q931Pmes_Information); - Q931SetMesProc(Q931mes_NOTIFY, i, Q931ProcNotifyNT, Q931Umes_Notify, Q931Pmes_Notify); - Q931SetMesProc(Q931mes_STATUS, i, Q931ProcStatusNT, Q931Umes_Status, Q931Pmes_Status); - Q931SetMesProc(Q931mes_STATUS_ENQUIRY, i, Q931ProcStatusEnquiryNT, Q931Umes_StatusEnquiry, Q931Pmes_StatusEnquiry); - Q931SetMesProc(Q931mes_SEGMENT, i, Q931ProcSegmentNT, Q931Umes_Segment, Q931Pmes_Segment); - - Q931SetMesProc(Q932mes_FACILITY, i, Q932ProcFacilityNT, Q932Umes_Facility, Q932Pmes_Facility); - Q931SetMesProc(Q932mes_HOLD, i, Q932ProcHoldNT, Q932Umes_Hold, Q932Pmes_Hold); - Q931SetMesProc(Q932mes_HOLD_ACKNOWLEDGE, i, Q932ProcHoldAckNT, Q932Umes_HoldAck, Q932Pmes_HoldAck); - Q931SetMesProc(Q932mes_HOLD_REJECT, i, Q932ProcHoldRejectNT, Q932Umes_HoldReject, Q932Pmes_HoldReject); - Q931SetMesProc(Q932mes_REGISTER, i, Q932ProcRegisterNT, Q932Umes_Register, Q932Pmes_Register); - Q931SetMesProc(Q932mes_RETRIEVE, i, Q932ProcRetrieveNT, Q932Umes_Retrieve, Q932Pmes_Retrieve); - Q931SetMesProc(Q932mes_RETRIEVE_ACKNOWLEDGE, i, Q932ProcRetrieveAckNT, Q932Umes_RetrieveAck, Q932Pmes_RetrieveAck); - Q931SetMesProc(Q932mes_RETRIEVE_REJECT, i, Q932ProcRetrieveRejectNT, Q932Umes_RetrieveReject, Q932Pmes_RetrieveReject); - - /* Set up the IE encoder/decoder handle table.*/ - Q931SetIEProc(Q931ie_SEGMENTED_MESSAGE, i, Q931Pie_Segment, Q931Uie_Segment); - Q931SetIEProc(Q931ie_BEARER_CAPABILITY, i, Q931Pie_BearerCap, Q931Uie_BearerCap); - Q931SetIEProc(Q931ie_CAUSE, i, Q931Pie_Cause, Q931Uie_Cause); - Q931SetIEProc(Q931ie_CALL_IDENTITY, i, Q931Pie_CallID, Q931Uie_CallID); - Q931SetIEProc(Q931ie_CALL_STATE, i, Q931Pie_CallState, Q931Uie_CallState); - Q931SetIEProc(Q931ie_CHANNEL_IDENTIFICATION, i, Q931Pie_ChanID, Q931Uie_ChanID); - Q931SetIEProc(Q931ie_PROGRESS_INDICATOR, i, Q931Pie_ProgInd, Q931Uie_ProgInd); - Q931SetIEProc(Q931ie_NETWORK_SPECIFIC_FACILITIES, i, Q931Pie_NetFac, Q931Uie_NetFac); - Q931SetIEProc(Q931ie_NOTIFICATION_INDICATOR, i, Q931Pie_NotifInd, Q931Uie_NotifInd); - Q931SetIEProc(Q931ie_DISPLAY, i, Q931Pie_Display, Q931Uie_Display); - Q931SetIEProc(Q931ie_DATETIME, i, Q931Pie_DateTime, Q931Uie_DateTime); - Q931SetIEProc(Q931ie_KEYPAD_FACILITY, i, Q931Pie_KeypadFac, Q931Uie_KeypadFac); - Q931SetIEProc(Q931ie_SIGNAL, i, Q931Pie_Signal, Q931Uie_Signal); - Q931SetIEProc(Q931ie_TRANSIT_DELAY_SELECTION_AND_IND, i, Q931Pie_TransNetSel, Q931Uie_TransNetSel); - Q931SetIEProc(Q931ie_CALLING_PARTY_NUMBER, i, Q931Pie_CallingNum, Q931Uie_CallingNum); - Q931SetIEProc(Q931ie_CALLING_PARTY_SUBADDRESS, i, Q931Pie_CallingSub, Q931Uie_CallingSub); - Q931SetIEProc(Q931ie_CALLED_PARTY_NUMBER, i, Q931Pie_CalledNum, Q931Uie_CalledNum); - Q931SetIEProc(Q931ie_CALLED_PARTY_SUBADDRESS, i, Q931Pie_CalledSub, Q931Uie_CalledSub); - Q931SetIEProc(Q931ie_TRANSIT_NETWORK_SELECTION, i, Q931Pie_TransNetSel, Q931Uie_TransNetSel); - Q931SetIEProc(Q931ie_RESTART_INDICATOR, i, Q931Pie_RestartInd, Q931Uie_RestartInd); - Q931SetIEProc(Q931ie_LOW_LAYER_COMPATIBILITY, i, Q931Pie_LLComp, Q931Uie_LLComp); - Q931SetIEProc(Q931ie_HIGH_LAYER_COMPATIBILITY, i, Q931Pie_HLComp, Q931Uie_HLComp); - Q931SetIEProc(Q931ie_USER_USER, i, Q931Pie_UserUser, Q931Uie_UserUser); - Q931SetIEProc(Q931ie_GENERIC_DIGITS, i, Q931Pie_GenericDigits, Q931Uie_GenericDigits); - - Q931SetIEProc(Q931ie_CONNECTED_NUMBER, i, Q931Pie_Generic, Q931Uie_Generic); - Q931SetIEProc(Q931ie_FACILITY, i, Q931Pie_Generic, Q931Uie_Generic); - Q931SetIEProc(Q931ie_REDIRECTING_NUMBER, i, Q931Pie_Generic, Q931Uie_Generic); - - /* The following define a state machine. The point is that the Message */ - /* procs can when search this to find out if the message/state */ - /* combination is legale. If not, the proc for unexpected message apply.*/ - - /* TODO define state table here */ -} diff --git a/libs/freetdm/src/isdn/nationalStateTE.c b/libs/freetdm/src/isdn/nationalStateTE.c deleted file mode 100644 index 46731d0910..0000000000 --- a/libs/freetdm/src/isdn/nationalStateTE.c +++ /dev/null @@ -1,217 +0,0 @@ -/***************************************************************************** - - FileName: nationalStateTE.c - - Contents: National ISDN State Engine for TE (User Mode). - - The controlling state engine for Q.931 is the state engine - on the NT side. The state engine on the TE side is a slave - of this. The TE side maintain it's own states as described in - ITU-T Q931, but will in raise conditions be overridden by - the NT side. - - This reference implementation uses a process per message, - meaning that each message must check call states. This - is easier for dialect maintenance as each message proc - can be replaced individually. A new TE variant only - need to copy the Q931CreateTE and replace those procs or - need to override. - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Copyright (c) 2007, Michael Jerris. All rights reserved. - email:mike@jerris.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -#include "national.h" -extern L3INT Q931L4HeaderSpace; - -/***************************************************************************** - Function: nationalCreateTE - - Description: Will create the National TE as a Dialect in the stack. The first - bulk set up the message handlers, the second bulk the IE - encoders/coders, and the last bulk set up the state table. - - Parameters: i Dialect index -*****************************************************************************/ -void nationalCreateTE(L3UCHAR i) -{ - Q931SetMesProc(Q931mes_ALERTING, i, Q931ProcAlertingTE, Q931Umes_Alerting, Q931Pmes_Alerting); - Q931SetMesProc(Q931mes_CALL_PROCEEDING, i, Q931ProcCallProceedingTE, Q931Umes_CallProceeding, Q931Pmes_CallProceeding); - Q931SetMesProc(Q931mes_CONNECT, i, DMSProc0x07TE, DMSUmes_0x07, DMSPmes_0x07); - Q931SetMesProc(Q931mes_CONNECT_ACKNOWLEDGE, i, DMSProc0x0fTE, DMSUmes_0x0f, DMSPmes_0x0f); - Q931SetMesProc(Q931mes_PROGRESS, i, Q931ProcProgressTE, Q931Umes_Progress, Q931Pmes_Progress); - Q931SetMesProc(Q931mes_SETUP, i, Q931ProcSetupTE, nationalUmes_Setup, nationalPmes_Setup); - Q931SetMesProc(Q931mes_SETUP_ACKNOWLEDGE, i, Q931ProcSetupAckTE, Q931Umes_SetupAck, Q931Pmes_SetupAck); - Q931SetMesProc(Q931mes_RESUME, i, Q931ProcResumeTE, Q931Umes_Resume, Q931Pmes_Resume); - Q931SetMesProc(Q931mes_RESUME_ACKNOWLEDGE, i, Q931ProcResumeAckTE, Q931Umes_ResumeAck, Q931Pmes_ResumeAck); - Q931SetMesProc(Q931mes_RESUME_REJECT, i, Q931ProcResumeRejectTE, Q931Umes_ResumeReject, Q931Pmes_ResumeReject); - Q931SetMesProc(Q931mes_SUSPEND, i, Q931ProcSuspendTE, Q931Umes_Suspend, Q931Pmes_Suspend); - Q931SetMesProc(Q931mes_SUSPEND_ACKNOWLEDGE, i, Q931ProcSuspendAckTE, Q931Umes_SuspendAck, Q931Pmes_SuspendAck); - Q931SetMesProc(Q931mes_SUSPEND_REJECT, i, Q931ProcSuspendRejectTE, Q931Umes_SuspendReject, Q931Pmes_SuspendReject); - Q931SetMesProc(Q931mes_USER_INFORMATION, i, Q931ProcUserInformationTE, Q931Umes_UserInformation, Q931Pmes_UserInformation); - Q931SetMesProc(Q931mes_DISCONNECT, i, Q931ProcDisconnectTE, Q931Umes_Disconnect, Q931Pmes_Disconnect); - Q931SetMesProc(Q931mes_RELEASE, i, Q931ProcReleaseTE, Q931Umes_Release, Q931Pmes_Release); - Q931SetMesProc(Q931mes_RELEASE_COMPLETE, i, Q931ProcReleaseCompleteTE, Q931Umes_ReleaseComplete, Q931Pmes_ReleaseComplete); - Q931SetMesProc(Q931mes_RESTART, i, Q931ProcRestartTE, Q931Umes_Restart, Q931Pmes_Restart); - Q931SetMesProc(Q931mes_RESTART_ACKNOWLEDGE, i, Q931ProcRestartAckTE, Q931Umes_RestartAck, Q931Pmes_RestartAck); - Q931SetMesProc(Q931mes_CONGESTION_CONTROL, i, Q931ProcCongestionControlTE, Q931Umes_CongestionControl, Q931Pmes_CongestionControl); - Q931SetMesProc(Q931mes_INFORMATION, i, Q931ProcInformationTE, Q931Umes_Information, Q931Pmes_Information); - Q931SetMesProc(Q931mes_NOTIFY, i, Q931ProcNotifyTE, Q931Umes_Notify, Q931Pmes_Notify); - Q931SetMesProc(Q931mes_STATUS, i, Q931ProcStatusTE, Q931Umes_Status, Q931Pmes_Status); - Q931SetMesProc(Q931mes_STATUS_ENQUIRY, i, Q931ProcStatusEnquiryTE, Q931Umes_StatusEnquiry, Q931Pmes_StatusEnquiry); - Q931SetMesProc(Q931mes_SEGMENT, i, Q931ProcSegmentTE, Q931Umes_Segment, Q931Pmes_Segment); - - Q931SetMesProc(Q932mes_FACILITY, i, Q932ProcFacilityTE, Q932Umes_Facility, Q932Pmes_Facility); - Q931SetMesProc(Q932mes_HOLD, i, Q932ProcHoldTE, Q932Umes_Hold, Q932Pmes_Hold); - Q931SetMesProc(Q932mes_HOLD_ACKNOWLEDGE, i, Q932ProcHoldAckTE, Q932Umes_HoldAck, Q932Pmes_HoldAck); - Q931SetMesProc(Q932mes_HOLD_REJECT, i, Q932ProcHoldRejectTE, Q932Umes_HoldReject, Q932Pmes_HoldReject); - Q931SetMesProc(Q932mes_REGISTER, i, Q932ProcRegisterTE, Q932Umes_Register, Q932Pmes_Register); - Q931SetMesProc(Q932mes_RETRIEVE, i, Q932ProcRetrieveTE, Q932Umes_Retrieve, Q932Pmes_Retrieve); - Q931SetMesProc(Q932mes_RETRIEVE_ACKNOWLEDGE, i, Q932ProcRetrieveAckTE, Q932Umes_RetrieveAck, Q932Pmes_RetrieveAck); - Q931SetMesProc(Q932mes_RETRIEVE_REJECT, i, Q932ProcRetrieveRejectTE, Q932Umes_RetrieveReject, Q932Pmes_RetrieveReject); - - /* Set up the IE encoder/decoder handle table.*/ - Q931SetIEProc(Q931ie_SEGMENTED_MESSAGE, i, Q931Pie_Segment, Q931Uie_Segment); - Q931SetIEProc(Q931ie_BEARER_CAPABILITY, i, Q931Pie_BearerCap, Q931Uie_BearerCap); - Q931SetIEProc(Q931ie_CAUSE, i, Q931Pie_Cause, Q931Uie_Cause); - Q931SetIEProc(Q931ie_CALL_IDENTITY, i, Q931Pie_CallID, Q931Uie_CallID); - Q931SetIEProc(Q931ie_CALL_STATE, i, Q931Pie_CallState, Q931Uie_CallState); - Q931SetIEProc(Q931ie_CHANGE_STATUS, i, Q931Pie_ChangeStatus, Q931Uie_ChangeStatus); - Q931SetIEProc(Q931ie_CHANNEL_IDENTIFICATION, i, Q931Pie_ChanID, Q931Uie_ChanID); - Q931SetIEProc(Q931ie_PROGRESS_INDICATOR, i, Q931Pie_ProgInd, Q931Uie_ProgInd); - Q931SetIEProc(Q931ie_NETWORK_SPECIFIC_FACILITIES, i, Q931Pie_NetFac, Q931Uie_NetFac); - Q931SetIEProc(Q931ie_NOTIFICATION_INDICATOR, i, Q931Pie_NotifInd, Q931Uie_NotifInd); - Q931SetIEProc(Q931ie_DISPLAY, i, Q931Pie_Display, Q931Uie_Display); - Q931SetIEProc(Q931ie_DATETIME, i, Q931Pie_DateTime, Q931Uie_DateTime); - Q931SetIEProc(Q931ie_KEYPAD_FACILITY, i, Q931Pie_KeypadFac, Q931Uie_KeypadFac); - Q931SetIEProc(Q931ie_SIGNAL, i, Q931Pie_Signal, Q931Uie_Signal); - Q931SetIEProc(Q931ie_TRANSIT_DELAY_SELECTION_AND_IND, i, Q931Pie_TransNetSel, Q931Uie_TransNetSel); - Q931SetIEProc(Q931ie_CALLING_PARTY_NUMBER, i, Q931Pie_CallingNum, Q931Uie_CallingNum); - Q931SetIEProc(Q931ie_CALLING_PARTY_SUBADDRESS, i, Q931Pie_CallingSub, Q931Uie_CallingSub); - Q931SetIEProc(Q931ie_CALLED_PARTY_NUMBER, i, Q931Pie_CalledNum, Q931Uie_CalledNum); - Q931SetIEProc(Q931ie_CALLED_PARTY_SUBADDRESS, i, Q931Pie_CalledSub, Q931Uie_CalledSub); - Q931SetIEProc(Q931ie_TRANSIT_NETWORK_SELECTION, i, Q931Pie_TransNetSel, Q931Uie_TransNetSel); - Q931SetIEProc(Q931ie_RESTART_INDICATOR, i, Q931Pie_RestartInd, Q931Uie_RestartInd); - Q931SetIEProc(Q931ie_LOW_LAYER_COMPATIBILITY, i, Q931Pie_LLComp, Q931Uie_LLComp); - Q931SetIEProc(Q931ie_HIGH_LAYER_COMPATIBILITY, i, Q931Pie_HLComp, Q931Uie_HLComp); - Q931SetIEProc(Q931ie_USER_USER, i, Q931Pie_UserUser, Q931Uie_UserUser); - Q931SetIEProc(Q931ie_GENERIC_DIGITS, i, Q931Pie_GenericDigits, Q931Uie_GenericDigits); - - Q931SetIEProc(Q931ie_CONNECTED_NUMBER, i, Q931Pie_Generic, Q931Uie_Generic); - Q931SetIEProc(Q931ie_FACILITY, i, Q931Pie_Generic, Q931Uie_Generic); - Q931SetIEProc(Q931ie_REDIRECTING_NUMBER, i, Q931Pie_Generic, Q931Uie_Generic); - - /* The following define a state machine. The point is that the Message - * procs can when search this to find out if the message/state - * combination is legale. If not, the proc for unexpected message apply. - */ - - /* State 0 Idle */ - Q931AddStateEntry(i, Q931_U0, Q931mes_RESUME, 2); - Q931AddStateEntry(i, Q931_U0, Q931mes_SETUP, 4); - Q931AddStateEntry(i, Q931_U0, Q931mes_SETUP, 2); - Q931AddStateEntry(i, Q931_U0, Q931mes_STATUS, 4); - Q931AddStateEntry(i, Q931_U0, Q931mes_RELEASE, 4); - Q931AddStateEntry(i, Q931_U0, Q931mes_RELEASE_COMPLETE, 4); - - /* State 1 Call Initiating */ - Q931AddStateEntry(i, Q931_U1, Q931mes_DISCONNECT, 2); - Q931AddStateEntry(i, Q931_U1, Q931mes_SETUP_ACKNOWLEDGE, 4); - Q931AddStateEntry(i, Q931_U1, Q931mes_RELEASE_COMPLETE, 4); - Q931AddStateEntry(i, Q931_U1, Q931mes_CALL_PROCEEDING, 4); - Q931AddStateEntry(i, Q931_U1, Q931mes_ALERTING, 4); - Q931AddStateEntry(i, Q931_U1, Q931mes_CONNECT, 4); - - /* State 2 Overlap Sending */ - Q931AddStateEntry(i, Q931_U2, Q931mes_INFORMATION, 2); - Q931AddStateEntry(i, Q931_U2, Q931mes_CALL_PROCEEDING, 4); - Q931AddStateEntry(i, Q931_U2, Q931mes_ALERTING, 4); - Q931AddStateEntry(i, Q931_U2, Q931mes_PROGRESS, 4); - Q931AddStateEntry(i, Q931_U2, Q931mes_CONNECT, 4); - Q931AddStateEntry(i, Q931_U2, Q931mes_RELEASE, 2); - - /* State 3 Outgoing Call Proceeding */ - Q931AddStateEntry(i, Q931_U3, Q931mes_PROGRESS, 4); - Q931AddStateEntry(i, Q931_U3, Q931mes_ALERTING, 4); - Q931AddStateEntry(i, Q931_U3, Q931mes_CONNECT, 4); - Q931AddStateEntry(i, Q931_U3, Q931mes_RELEASE, 2); - - /* State 4 Call Delivered */ - Q931AddStateEntry(i, Q931_U4, Q931mes_CONNECT, 4); - - /* State 6 Call Precent */ - Q931AddStateEntry(i, Q931_U6, Q931mes_INFORMATION, 2); - Q931AddStateEntry(i, Q931_U6, Q931mes_ALERTING, 2); - Q931AddStateEntry(i, Q931_U6, Q931mes_CALL_PROCEEDING, 2); - Q931AddStateEntry(i, Q931_U6, Q931mes_CONNECT, 2); - Q931AddStateEntry(i, Q931_U6, Q931mes_RELEASE_COMPLETE, 2); - Q931AddStateEntry(i, Q931_U6, Q931mes_RELEASE, 4); - Q931AddStateEntry(i, Q931_U6, Q931mes_DISCONNECT, 4); - - /* State 7 Call Received */ - Q931AddStateEntry(i, Q931_U7, Q931mes_CONNECT, 2); - - /* State 8 Connect request */ - Q931AddStateEntry(i, Q931_U8, Q931mes_CONNECT_ACKNOWLEDGE, 4); - - /* State 9 Incoming Call Proceeding */ - Q931AddStateEntry(i, Q931_U9, Q931mes_CONNECT, 2); - Q931AddStateEntry(i, Q931_U9, Q931mes_ALERTING, 2); - Q931AddStateEntry(i, Q931_U9, Q931mes_PROGRESS, 2); - - /* State 10 Active */ - Q931AddStateEntry(i, Q931_U10, Q931mes_SUSPEND, 2); - Q931AddStateEntry(i, Q931_U10, Q931mes_NOTIFY, 4); - Q931AddStateEntry(i, Q931_U10, Q931mes_NOTIFY, 2); - - /* State 11 Disconnect Request */ - Q931AddStateEntry(i, Q931_U11, Q931mes_RELEASE, 4); - Q931AddStateEntry(i, Q931_U11, Q931mes_DISCONNECT, 4); - Q931AddStateEntry(i, Q931_U11, Q931mes_NOTIFY, 4); - - /* State 12 Disconnect Ind */ - Q931AddStateEntry(i, Q931_U12, Q931mes_RELEASE, 4); - Q931AddStateEntry(i, Q931_U12, Q931mes_RELEASE, 2); - - /* State 15 Suspend Request */ - Q931AddStateEntry(i, Q931_U15, Q931mes_SUSPEND_ACKNOWLEDGE, 4); - Q931AddStateEntry(i, Q931_U15, Q931mes_SUSPEND_REJECT, 4); - Q931AddStateEntry(i, Q931_U15, Q931mes_DISCONNECT, 4); - Q931AddStateEntry(i, Q931_U15, Q931mes_RELEASE, 4); - -/* TODO - Q931AddStateEntry(i, Q931_U17, - Q931AddStateEntry(i, Q931_U19, - Q931AddStateEntry(i, Q931_U25, -*/ -} diff --git a/libs/freetdm/src/isdn/nationalmes.c b/libs/freetdm/src/isdn/nationalmes.c deleted file mode 100644 index 6d8350fbcd..0000000000 --- a/libs/freetdm/src/isdn/nationalmes.c +++ /dev/null @@ -1,269 +0,0 @@ -/***************************************************************************** - - FileName: nationalmes.c - - Contents: Pack/Unpack functions. These functions will unpack a National ISDN - message from the bit packed original format into structs - that contains variables sized by the user. It will also pack - the struct back into a Q.931 message as required. - - See national.h for description. - - License/Copyright: - - Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. - email:janvb@caselaboratories.com - - Copyright (c) 2007, Michael Jerris. All rights reserved. - email:mike@jerris.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Case Labs, Ltd nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -*****************************************************************************/ - -#include "national.h" - -/***************************************************************************** - - Function: nationalUmes_Setup - -*****************************************************************************/ -L3INT nationalUmes_Setup(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size) -{ - L3INT ir = 0; - L3INT OOff = 0; - L3INT rc = Q931E_NO_ERROR; - L3UCHAR last_codeset = 0, codeset = 0; - L3UCHAR shift_lock = 1; - - while (IOff < Size) { - if (!shift_lock) { - codeset = last_codeset; - } - - if ((IBuf[IOff] & 0xF0) == Q931ie_SHIFT ) { - shift_lock = (IBuf[IOff] & 0x08); - if (shift_lock) { - last_codeset = codeset; - } - codeset = ((IBuf[IOff] & 0x07)); - IOff++; - } - - if (codeset == 0) { - switch (IBuf[IOff]) { - case Q931ie_SENDING_COMPLETE: - case Q931ie_BEARER_CAPABILITY: - case Q931ie_CHANNEL_IDENTIFICATION: - case Q931ie_PROGRESS_INDICATOR: - case Q931ie_NETWORK_SPECIFIC_FACILITIES: - case Q931ie_DISPLAY: - case Q931ie_DATETIME: - case Q931ie_KEYPAD_FACILITY: - case Q931ie_SIGNAL: - case Q931ie_CALLING_PARTY_NUMBER: - case Q931ie_CALLING_PARTY_SUBADDRESS: - case Q931ie_CALLED_PARTY_NUMBER: - case Q931ie_CALLED_PARTY_SUBADDRESS: - case Q931ie_TRANSIT_NETWORK_SELECTION: - case Q931ie_LOW_LAYER_COMPATIBILITY: - case Q931ie_HIGH_LAYER_COMPATIBILITY: - case Q931ie_FACILITY: - case Q931ie_REDIRECTING_NUMBER: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - case Q931ie_REPEAT_INDICATOR: - if (ir < 2) { - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - ir++; - } else { - return Q931E_ILLEGAL_IE; - } - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - } else if (codeset == 6) { - switch (IBuf[IOff]) { - case Q931ie_GENERIC_DIGITS: - rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff); - if (rc != Q931E_NO_ERROR) - return rc; - break; - default: - return Q931E_ILLEGAL_IE; - break; - } - - } else { - return Q931E_ILLEGAL_IE; - } - } - mes->Size = sizeof(Q931mes_Generic) - 1 + OOff; - return Q931E_NO_ERROR; -} - -/***************************************************************************** - - Function: nationalPmes_Setup - - Decription: Pack a Q931mes_Generic into a real Q.931 message. The user will - set up a SETUP message and issue this to the stack where it - is processed by Q931ProcSetup that processes and validates - it before it actually sends it out. This function is called - to compute the real Q.931 message. - - Parameters: IBuf[IN] Ptr to un-packed struct - ISize[IN] Size of input buffer (unpacked message). - OBuf[OUT] Ptr to packed 'octet' wise message. - OSize[OUT] Size of packed message. - - Called By: Q931ProcSetup - -*****************************************************************************/ -L3INT nationalPmes_Setup(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize) -{ - L3INT rc = Q931E_NO_ERROR; - Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf; - L3INT Octet = 0; - - /* Q931 Message Header */ - Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet); - - /* Sending Complete */ - if (Q931IsIEPresent(pMes->SendComplete)) { - OBuf[Octet++] = (L3UCHAR)(pMes->SendComplete & 0x00ff); - } - - /* Repeat Indicator */ - if (Q931IsIEPresent(pMes->RepeatInd)) { - OBuf[Octet++] = (L3UCHAR)(pMes->RepeatInd & 0x00ff); - } - - /* Bearer capability */ - if (Q931IsIEPresent(pMes->BearerCap)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_BEARER_CAPABILITY](pTrunk, Q931GetIEPtr(pMes->BearerCap,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - else { - rc = Q931E_BEARERCAP; - } - - /* Channel Identification */ - if (Q931IsIEPresent(pMes->ChanID)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CHANNEL_IDENTIFICATION](pTrunk, Q931GetIEPtr(pMes->ChanID,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Progress indicator */ - if (Q931IsIEPresent(pMes->ProgInd)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_PROGRESS_INDICATOR](pTrunk, Q931GetIEPtr(pMes->ProgInd,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Network spesific facilities */ - if (Q931IsIEPresent(pMes->NetFac)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_NETWORK_SPECIFIC_FACILITIES](pTrunk, Q931GetIEPtr(pMes->NetFac,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Display */ - if (Q931IsIEPresent(pMes->Display)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Date/Time */ - if (Q931IsIEPresent(pMes->DateTime)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DATETIME](pTrunk, Q931GetIEPtr(pMes->DateTime,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Keypad Facility */ - if (Q931IsIEPresent(pMes->KeypadFac)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_KEYPAD_FACILITY](pTrunk, Q931GetIEPtr(pMes->KeypadFac,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Signal */ - if (Q931IsIEPresent(pMes->Signal)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_SIGNAL](pTrunk, Q931GetIEPtr(pMes->Signal,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Calling Party Number */ - if (Q931IsIEPresent(pMes->CallingNum)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLING_PARTY_NUMBER](pTrunk, Q931GetIEPtr(pMes->CallingNum,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Calling Party Subaddress */ - if (Q931IsIEPresent(pMes->CallingSub)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLING_PARTY_SUBADDRESS](pTrunk, Q931GetIEPtr(pMes->CallingSub,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Called Party number */ - if (Q931IsIEPresent(pMes->CalledNum)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLED_PARTY_NUMBER](pTrunk, Q931GetIEPtr(pMes->CalledNum,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Called party subaddress */ - if (Q931IsIEPresent(pMes->CalledSub)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLED_PARTY_SUBADDRESS](pTrunk, Q931GetIEPtr(pMes->CalledSub,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Transit network selection */ - if (Q931IsIEPresent(pMes->TransNetSel)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_TRANSIT_NETWORK_SELECTION](pTrunk, Q931GetIEPtr(pMes->TransNetSel,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* Repeat Indicator */ - if (Q931IsIEPresent(pMes->LLRepeatInd)) { - rc = Q931E_UNKNOWN_IE;/* TODO */ - } - - /* Low Layer Compatibility */ - if (Q931IsIEPresent(pMes->LLComp)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_LOW_LAYER_COMPATIBILITY](pTrunk, Q931GetIEPtr(pMes->LLComp,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - /* High Layer Compatibility */ - if (Q931IsIEPresent(pMes->HLComp)) { - if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_HIGH_LAYER_COMPATIBILITY](pTrunk, Q931GetIEPtr(pMes->HLComp,pMes->buf), OBuf, &Octet)) != 0) - return rc; - } - - *OSize = Octet; - return rc; -} diff --git a/libs/freetdm/src/libteletone_detect.c b/libs/freetdm/src/libteletone_detect.c deleted file mode 100644 index b89ea11645..0000000000 --- a/libs/freetdm/src/libteletone_detect.c +++ /dev/null @@ -1,485 +0,0 @@ -/* - * libteletone - * Copyright (C) 2005-2014, Anthony Minessale II - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is tone_detect.c - General telephony tone detection, and specific detection of DTMF. - * - * - * The Initial Developer of the Original Code is - * Stephen Underwood - * Portions created by the Initial Developer are Copyright (C) - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * The the original interface designed by Steve Underwood was preserved to retain - *the optimizations when considering DTMF tones though the names were changed in the interest - * of namespace. - * - * Much less efficient expansion interface was added to allow for the detection of - * a single arbitrary tone combination which may also exceed 2 simultaneous tones. - * (controlled by compile time constant TELETONE_MAX_TONES) - * - * Copyright (C) 2006 Anthony Minessale II - * - * - * libteletone_detect.c Tone Detection Code - * - * - ********************************************************************************* - * - * Derived from tone_detect.c - General telephony tone detection, and specific - * detection of DTMF. - * - * Copyright (C) 2001 Steve Underwood - * - * Despite my general liking of the GPL, I place this code in the - * public domain for the benefit of all mankind - even the slimy - * ones who might try to proprietize my work and use it to my - * detriment. - * - * - * Exception: - * The author hereby grants the use of this source code under the - * following license if and only if the source code is distributed - * as part of the OpenZAP or FreeTDM library. Any use or distribution of this - * source code outside the scope of the OpenZAP or FreeTDM library will nullify the - * following license and reinact the MPL 1.1 as stated above. - * - * Copyright (c) 2007, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#ifndef _MSC_VER -#include -#endif -#include -#include -#include -#include - -#define LOW_ENG 10000000 -#define ZC 2 -static teletone_detection_descriptor_t dtmf_detect_row[GRID_FACTOR]; -static teletone_detection_descriptor_t dtmf_detect_col[GRID_FACTOR]; -static teletone_detection_descriptor_t dtmf_detect_row_2nd[GRID_FACTOR]; -static teletone_detection_descriptor_t dtmf_detect_col_2nd[GRID_FACTOR]; - -static float dtmf_row[] = {697.0f, 770.0f, 852.0f, 941.0f}; -static float dtmf_col[] = {1209.0f, 1336.0f, 1477.0f, 1633.0f}; - -static char dtmf_positions[] = "123A" "456B" "789C" "*0#D"; - -static void goertzel_init(teletone_goertzel_state_t *goertzel_state, teletone_detection_descriptor_t *tdesc) { - goertzel_state->v2 = goertzel_state->v3 = 0.0; - goertzel_state->fac = tdesc->fac; -} - -TELETONE_API(void) teletone_goertzel_update(teletone_goertzel_state_t *goertzel_state, - int16_t sample_buffer[], - int samples) -{ - int i; - float v1; - - for (i = 0; i < samples; i++) { - v1 = goertzel_state->v2; - goertzel_state->v2 = goertzel_state->v3; - goertzel_state->v3 = (float)(goertzel_state->fac*goertzel_state->v2 - v1 + sample_buffer[i]); - } -} -#ifdef _MSC_VER -#pragma warning(disable:4244) -#endif - -#define teletone_goertzel_result(gs) (double)(((gs)->v3 * (gs)->v3 + (gs)->v2 * (gs)->v2 - (gs)->v2 * (gs)->v3 * (gs)->fac)) - -TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf_detect_state, int sample_rate) -{ - int i; - float theta; - - dtmf_detect_state->hit1 = dtmf_detect_state->hit2 = 0; - - for (i = 0; i < GRID_FACTOR; i++) { - theta = (float)(M_TWO_PI*(dtmf_row[i]/(float)sample_rate)); - dtmf_detect_row[i].fac = (float)(2.0*cos(theta)); - - theta = (float)(M_TWO_PI*(dtmf_col[i]/(float)sample_rate)); - dtmf_detect_col[i].fac = (float)(2.0*cos(theta)); - - theta = (float)(M_TWO_PI*(dtmf_row[i]*2.0/(float)sample_rate)); - dtmf_detect_row_2nd[i].fac = (float)(2.0*cos(theta)); - - theta = (float)(M_TWO_PI*(dtmf_col[i]*2.0/(float)sample_rate)); - dtmf_detect_col_2nd[i].fac = (float)(2.0*cos(theta)); - - goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]); - goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]); - goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]); - goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]); - - dtmf_detect_state->energy = 0.0; - } - dtmf_detect_state->current_sample = 0; - dtmf_detect_state->detected_digits = 0; - dtmf_detect_state->lost_digits = 0; - dtmf_detect_state->digit = 0; - dtmf_detect_state->dur = 0; -} - -TELETONE_API(void) teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map) -{ - float theta = 0; - int x = 0; - - if (!mt->sample_rate) { - mt->sample_rate = 8000; - } - - if (!mt->min_samples) { - mt->min_samples = 102; - } - - mt->min_samples *= (mt->sample_rate / 8000); - - if (!mt->positive_factor) { - mt->positive_factor = 2; - } - - if(!mt->negative_factor) { - mt->negative_factor = 10; - } - - if (!mt->hit_factor) { - mt->hit_factor = 2; - } - - for(x = 0; x < TELETONE_MAX_TONES; x++) { - if ((int) map->freqs[x] == 0) { - break; - } - mt->tone_count++; - theta = (float)(M_TWO_PI*(map->freqs[x]/(float)mt->sample_rate)); - mt->tdd[x].fac = (float)(2.0 * cos(theta)); - goertzel_init (&mt->gs[x], &mt->tdd[x]); - goertzel_init (&mt->gs2[x], &mt->tdd[x]); - } - -} - -TELETONE_API(int) teletone_multi_tone_detect (teletone_multi_tone_t *mt, - int16_t sample_buffer[], - int samples) -{ - int sample, limit = 0, j, x = 0; - float v1, famp; - float eng_sum = 0, eng_all[TELETONE_MAX_TONES] = {0.0}; - int gtest = 0, see_hit = 0; - - for (sample = 0; sample >= 0 && sample < samples; sample = limit) { - mt->total_samples++; - - if ((samples - sample) >= (mt->min_samples - mt->current_sample)) { - limit = sample + (mt->min_samples - mt->current_sample); - } else { - limit = samples; - } - if (limit < 0 || limit > samples) { - limit = samples; - } - - for (j = sample; j < limit; j++) { - famp = sample_buffer[j]; - - mt->energy += famp*famp; - - for(x = 0; x < TELETONE_MAX_TONES && x < mt->tone_count; x++) { - v1 = mt->gs[x].v2; - mt->gs[x].v2 = mt->gs[x].v3; - mt->gs[x].v3 = (float)(mt->gs[x].fac * mt->gs[x].v2 - v1 + famp); - - v1 = mt->gs2[x].v2; - mt->gs2[x].v2 = mt->gs2[x].v3; - mt->gs2[x].v3 = (float)(mt->gs2[x].fac*mt->gs2[x].v2 - v1 + famp); - } - } - - mt->current_sample += (limit - sample); - if (mt->current_sample < mt->min_samples) { - continue; - } - - eng_sum = 0; - for(x = 0; x < TELETONE_MAX_TONES && x < mt->tone_count; x++) { - eng_all[x] = (float)(teletone_goertzel_result (&mt->gs[x])); - eng_sum += eng_all[x]; - } - - gtest = 0; - for(x = 0; x < TELETONE_MAX_TONES && x < mt->tone_count; x++) { - gtest += teletone_goertzel_result (&mt->gs2[x]) < eng_all[x] ? 1 : 0; - } - - if ((gtest >= 2 || gtest == mt->tone_count) && eng_sum > 42.0 * mt->energy) { - if(mt->negatives) { - mt->negatives--; - } - mt->positives++; - - if(mt->positives >= mt->positive_factor) { - mt->hits++; - } - if (mt->hits >= mt->hit_factor) { - see_hit++; - mt->positives = mt->negatives = mt->hits = 0; - } - } else { - mt->negatives++; - if(mt->positives) { - mt->positives--; - } - if(mt->negatives > mt->negative_factor) { - mt->positives = mt->hits = 0; - } - } - - /* Reinitialise the detector for the next block */ - for(x = 0; x < TELETONE_MAX_TONES && x < mt->tone_count; x++) { - goertzel_init (&mt->gs[x], &mt->tdd[x]); - goertzel_init (&mt->gs2[x], &mt->tdd[x]); - } - - mt->energy = 0.0; - mt->current_sample = 0; - } - - return see_hit; -} - - -TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state, - int16_t sample_buffer[], - int samples) -{ - float row_energy[GRID_FACTOR]; - float col_energy[GRID_FACTOR]; - float famp; - float v1; - int i; - int j; - int sample; - int best_row; - int best_col; - char hit; - int limit; - teletone_hit_type_t r = 0; - - hit = 0; - for (sample = 0; sample < samples; sample = limit) { - /* BLOCK_LEN is optimised to meet the DTMF specs. */ - if ((samples - sample) >= (BLOCK_LEN - dtmf_detect_state->current_sample)) { - limit = sample + (BLOCK_LEN - dtmf_detect_state->current_sample); - } else { - limit = samples; - } - - for (j = sample; j < limit; j++) { - int x = 0; - famp = sample_buffer[j]; - - dtmf_detect_state->energy += famp*famp; - - for(x = 0; x < GRID_FACTOR; x++) { - v1 = dtmf_detect_state->row_out[x].v2; - dtmf_detect_state->row_out[x].v2 = dtmf_detect_state->row_out[x].v3; - dtmf_detect_state->row_out[x].v3 = (float)(dtmf_detect_state->row_out[x].fac*dtmf_detect_state->row_out[x].v2 - v1 + famp); - - v1 = dtmf_detect_state->col_out[x].v2; - dtmf_detect_state->col_out[x].v2 = dtmf_detect_state->col_out[x].v3; - dtmf_detect_state->col_out[x].v3 = (float)(dtmf_detect_state->col_out[x].fac*dtmf_detect_state->col_out[x].v2 - v1 + famp); - - v1 = dtmf_detect_state->col_out2nd[x].v2; - dtmf_detect_state->col_out2nd[x].v2 = dtmf_detect_state->col_out2nd[x].v3; - dtmf_detect_state->col_out2nd[x].v3 = (float)(dtmf_detect_state->col_out2nd[x].fac*dtmf_detect_state->col_out2nd[x].v2 - v1 + famp); - - v1 = dtmf_detect_state->row_out2nd[x].v2; - dtmf_detect_state->row_out2nd[x].v2 = dtmf_detect_state->row_out2nd[x].v3; - dtmf_detect_state->row_out2nd[x].v3 = (float)(dtmf_detect_state->row_out2nd[x].fac*dtmf_detect_state->row_out2nd[x].v2 - v1 + famp); - } - - } - - if (dtmf_detect_state->zc > 0) { - if (dtmf_detect_state->energy < LOW_ENG && dtmf_detect_state->lenergy < LOW_ENG) { - if (!--dtmf_detect_state->zc) { - /* Reinitialise the detector for the next block */ - dtmf_detect_state->hit1 = dtmf_detect_state->hit2 = 0; - for (i = 0; i < GRID_FACTOR; i++) { - goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]); - goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]); - goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]); - goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]); - } - dtmf_detect_state->dur -= samples; - return TT_HIT_END; - } - } - - dtmf_detect_state->dur += samples; - dtmf_detect_state->lenergy = dtmf_detect_state->energy; - dtmf_detect_state->energy = 0.0; - dtmf_detect_state->current_sample = 0; - return TT_HIT_MIDDLE; - } else if (dtmf_detect_state->digit) { - return TT_HIT_END; - } - - - dtmf_detect_state->current_sample += (limit - sample); - if (dtmf_detect_state->current_sample < BLOCK_LEN) { - continue; - } - /* We are at the end of a DTMF detection block */ - /* Find the peak row and the peak column */ - row_energy[0] = teletone_goertzel_result (&dtmf_detect_state->row_out[0]); - col_energy[0] = teletone_goertzel_result (&dtmf_detect_state->col_out[0]); - - for (best_row = best_col = 0, i = 1; i < GRID_FACTOR; i++) { - row_energy[i] = teletone_goertzel_result (&dtmf_detect_state->row_out[i]); - if (row_energy[i] > row_energy[best_row]) { - best_row = i; - } - col_energy[i] = teletone_goertzel_result (&dtmf_detect_state->col_out[i]); - if (col_energy[i] > col_energy[best_col]) { - best_col = i; - } - } - hit = 0; - /* Basic signal level test and the twist test */ - if (row_energy[best_row] >= DTMF_THRESHOLD && - col_energy[best_col] >= DTMF_THRESHOLD && - col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST && - col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) { - /* Relative peak test */ - for (i = 0; i < GRID_FACTOR; i++) { - if ((i != best_col && col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) || - (i != best_row && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) { - break; - } - } - /* ... and second harmonic test */ - if (i >= GRID_FACTOR && (row_energy[best_row] + col_energy[best_col]) > 42.0*dtmf_detect_state->energy && - teletone_goertzel_result (&dtmf_detect_state->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col] && - teletone_goertzel_result (&dtmf_detect_state->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) { - hit = dtmf_positions[(best_row << 2) + best_col]; - /* Look for two successive similar results */ - /* The logic in the next test is: - We need two successive identical clean detects, with - something different preceeding it. This can work with - back to back differing digits. More importantly, it - can work with nasty phones that give a very wobbly start - to a digit. */ - if (! r && hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) { - dtmf_detect_state->digit_hits[(best_row << 2) + best_col]++; - dtmf_detect_state->detected_digits++; - if (dtmf_detect_state->current_digits < TELETONE_MAX_DTMF_DIGITS) { - dtmf_detect_state->digit = hit; - } else { - dtmf_detect_state->lost_digits++; - } - - if (!dtmf_detect_state->zc) { - dtmf_detect_state->zc = ZC; - dtmf_detect_state->dur = 0; - r = TT_HIT_BEGIN; - break; - } - - } - } - } - - dtmf_detect_state->hit1 = dtmf_detect_state->hit2; - dtmf_detect_state->hit2 = dtmf_detect_state->hit3; - dtmf_detect_state->hit3 = hit; - - dtmf_detect_state->energy = 0.0; - dtmf_detect_state->current_sample = 0; - - } - - return r; -} - - -TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur) -{ - if (!dtmf_detect_state->digit) { - return 0; - } - - *buf = dtmf_detect_state->digit; - - *dur = dtmf_detect_state->dur; - - if (!dtmf_detect_state->zc) { - dtmf_detect_state->dur = 0; - dtmf_detect_state->digit = 0; - } - - return 1; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/libteletone_generate.c b/libs/freetdm/src/libteletone_generate.c deleted file mode 100644 index 3638d94989..0000000000 --- a/libs/freetdm/src/libteletone_generate.c +++ /dev/null @@ -1,505 +0,0 @@ -/* - * libteletone - * Copyright (C) 2005-2014, Anthony Minessale II - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is libteletone - * - * The Initial Developer of the Original Code is - * Anthony Minessale II - * Portions created by the Initial Developer are Copyright (C) - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Anthony Minessale II - * - * - * libteletone.c -- Tone Generator - * - * - * - * Exception: - * The author hereby grants the use of this source code under the - * following license if and only if the source code is distributed - * as part of the OpenZAP or FreeTDM library. Any use or distribution of this - * source code outside the scope of the OpenZAP or FreeTDM library will nullify the - * following license and reinact the MPL 1.1 as stated above. - * - * Copyright (c) 2007, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#define SMAX 32767 -#define SMIN -32768 -#define normalize_to_16bit(n) if (n > SMAX) n = SMAX; else if (n < SMIN) n = SMIN; - -#ifdef _MSC_VER -#pragma warning(disable:4706) -#endif - -TELETONE_API_DATA int16_t TELETONE_SINES[SINE_TABLE_MAX] = { - 0x00c9, 0x025b, 0x03ed, 0x057f, 0x0711, 0x08a2, 0x0a33, 0x0bc4, - 0x0d54, 0x0ee4, 0x1073, 0x1201, 0x138f, 0x151c, 0x16a8, 0x1833, - 0x19be, 0x1b47, 0x1cd0, 0x1e57, 0x1fdd, 0x2162, 0x22e5, 0x2467, - 0x25e8, 0x2768, 0x28e5, 0x2a62, 0x2bdc, 0x2d55, 0x2ecc, 0x3042, - 0x31b5, 0x3327, 0x3497, 0x3604, 0x3770, 0x38d9, 0x3a40, 0x3ba5, - 0x3d08, 0x3e68, 0x3fc6, 0x4121, 0x427a, 0x43d1, 0x4524, 0x4675, - 0x47c4, 0x490f, 0x4a58, 0x4b9e, 0x4ce1, 0x4e21, 0x4f5e, 0x5098, - 0x51cf, 0x5303, 0x5433, 0x5560, 0x568a, 0x57b1, 0x58d4, 0x59f4, - 0x5b10, 0x5c29, 0x5d3e, 0x5e50, 0x5f5e, 0x6068, 0x616f, 0x6272, - 0x6371, 0x646c, 0x6564, 0x6657, 0x6747, 0x6832, 0x691a, 0x69fd, - 0x6add, 0x6bb8, 0x6c8f, 0x6d62, 0x6e31, 0x6efb, 0x6fc2, 0x7083, - 0x7141, 0x71fa, 0x72af, 0x735f, 0x740b, 0x74b3, 0x7556, 0x75f4, - 0x768e, 0x7723, 0x77b4, 0x7840, 0x78c8, 0x794a, 0x79c9, 0x7a42, - 0x7ab7, 0x7b27, 0x7b92, 0x7bf9, 0x7c5a, 0x7cb7, 0x7d0f, 0x7d63, - 0x7db1, 0x7dfb, 0x7e3f, 0x7e7f, 0x7eba, 0x7ef0, 0x7f22, 0x7f4e, - 0x7f75, 0x7f98, 0x7fb5, 0x7fce, 0x7fe2, 0x7ff1, 0x7ffa, 0x7fff -}; - - -TELETONE_API(int) teletone_set_tone(teletone_generation_session_t *ts, int index, ...) -{ - va_list ap; - int i = 0; - teletone_process_t x = 0; - - va_start(ap, index); - while (i < TELETONE_MAX_TONES && (x = va_arg(ap, teletone_process_t))) { - ts->TONES[index].freqs[i++] = x; - } - va_end(ap); - - return (i > TELETONE_MAX_TONES) ? -1 : 0; - -} - -TELETONE_API(int) teletone_set_map(teletone_tone_map_t *map, ...) -{ - va_list ap; - int i = 0; - teletone_process_t x = 0; - - va_start(ap, map); - while (i < TELETONE_MAX_TONES && (x = va_arg(ap, teletone_process_t))) { - map->freqs[i++] = x; - } - va_end(ap); - - return (i > TELETONE_MAX_TONES) ? -1 : 0; - -} - -TELETONE_API(int) teletone_init_session(teletone_generation_session_t *ts, int buflen, tone_handler handler, void *user_data) -{ - memset(ts, 0, sizeof(*ts)); - ts->rate = 8000; - ts->channels = 1; - ts->duration = 2000; - ts->wait = 500; - ts->tmp_duration = -1; - ts->tmp_wait = -1; - ts->handler = handler; - ts->user_data = user_data; - ts->volume = -7; - ts->decay_step = 0; - ts->decay_factor = 1; - if (buflen) { - if ((ts->buffer = calloc(buflen, sizeof(teletone_audio_t))) == 0) { - return -1; - } - ts->datalen = buflen; - } else { - ts->dynamic = 1024; - } - /* Add Standard DTMF Tones */ - teletone_set_tone(ts, '1', 697.0, 1209.0, 0.0); - teletone_set_tone(ts, '2', 697.0, 1336.0, 0.0); - teletone_set_tone(ts, '3', 697.0, 1477.0, 0.0); - teletone_set_tone(ts, 'A', 697.0, 1633.0, 0.0); - teletone_set_tone(ts, '4', 770.0, 1209.0, 0.0); - teletone_set_tone(ts, '5', 770.0, 1336.0, 0.0); - teletone_set_tone(ts, '6', 770.0, 1477.0, 0.0); - teletone_set_tone(ts, 'B', 770.0, 1633.0, 0.0); - teletone_set_tone(ts, '7', 859.0, 1209.0, 0.0); - teletone_set_tone(ts, '8', 859.0, 1336.0, 0.0); - teletone_set_tone(ts, '9', 859.0, 1477.0, 0.0); - teletone_set_tone(ts, 'C', 859.0, 1633.0, 0.0); - teletone_set_tone(ts, '*', 941.0, 1209.0, 0.0); - teletone_set_tone(ts, '0', 941.0, 1336.0, 0.0); - teletone_set_tone(ts, '#', 941.0, 1477.0, 0.0); - teletone_set_tone(ts, 'D', 941.0, 1633.0, 0.0); - - return 0; -} - -TELETONE_API(int) teletone_destroy_session(teletone_generation_session_t *ts) -{ - if (ts->buffer) { - free(ts->buffer); - ts->buffer = NULL; - ts->samples = 0; - } - return 0; -} - -static int ensure_buffer(teletone_generation_session_t *ts, int need) -{ - need += ts->samples; - need *= sizeof(teletone_audio_t); - need *= ts->channels; - - if (need > ts->datalen) { - teletone_audio_t *tmp; - ts->datalen = need + ts->dynamic; - tmp = realloc(ts->buffer, ts->datalen); - if (!tmp) { - return -1; - } - ts->buffer = tmp; - } - - return 0; -} - -TELETONE_API(int) teletone_mux_tones(teletone_generation_session_t *ts, teletone_tone_map_t *map) -{ - /*teletone_process_t period = (1.0 / ts->rate) / ts->channels;*/ - int i, c; - int freqlen = 0; - teletone_dds_state_t tones[TELETONE_MAX_TONES+1]; - //int decay = 0; - int duration; - int wait = 0; - int32_t sample; - int32_t dc = 0; - float vol = ts->volume; - ts->samples = 0; - memset(tones, 0, sizeof(tones[0]) * TELETONE_MAX_TONES); - duration = (ts->tmp_duration > -1) ? ts->tmp_duration : ts->duration; - wait = (ts->tmp_wait > -1) ? ts->tmp_wait : ts->wait; - - if (map->freqs[0] > 0) { - for (freqlen = 0; freqlen < TELETONE_MAX_TONES && map->freqs[freqlen]; freqlen++) { - teletone_dds_state_set_tone(&tones[freqlen], map->freqs[freqlen], ts->rate, 0); - teletone_dds_state_set_tx_level(&tones[freqlen], vol); - } - - if (ts->channels > 1) { - duration *= ts->channels; - } - - if (ts->dynamic) { - if (ensure_buffer(ts, duration)) { - return -1; - } - } - - for (ts->samples = 0; ts->samples < ts->datalen && ts->samples < duration; ts->samples++) { - if (ts->decay_direction && ++dc >= ts->decay_step) { - float nvol = vol + ts->decay_direction * ts->decay_factor; - int j; - - if (nvol <= TELETONE_VOL_DB_MAX && nvol >= TELETONE_VOL_DB_MIN) { - vol = nvol; - for (j = 0; j < TELETONE_MAX_TONES && map->freqs[j]; j++) { - teletone_dds_state_set_tx_level(&tones[j], vol); - } - dc = 0; - } - } - - sample = 128; - - for (i = 0; i < freqlen; i++) { - int32_t s = teletone_dds_state_modulate_sample(&tones[i], 0); - sample += s; - } - sample /= freqlen; - ts->buffer[ts->samples] = (teletone_audio_t)sample; - - for (c = 1; c < ts->channels; c++) { - ts->buffer[ts->samples+1] = ts->buffer[ts->samples]; - ts->samples++; - } - - } - } - if (ts->dynamic) { - if (ensure_buffer(ts, wait)) { - return -1; - } - } - for (c = 0; c < ts->channels; c++) { - for (i = 0; i < wait && ts->samples < ts->datalen; i++) { - ts->buffer[ts->samples++] = 0; - } - } - - if (ts->debug && ts->debug_stream) { - if (map->freqs[0] <= 0) { - fprintf(ts->debug_stream, "wait %d (%dms)\n", wait, wait / (ts->rate / 1000)); - } else { - fprintf(ts->debug_stream, "Generate: ("); - - for (i = 0; i < TELETONE_MAX_TONES && map->freqs[i]; i++) { - fprintf(ts->debug_stream, "%s%0.2f", i == 0 ? "" : "+",map->freqs[i]); - } - - fprintf(ts->debug_stream, - ") [volume %0.2fdB; samples %d(%dms) x %d channel%s; wait %d(%dms); decay_factor %0.2fdB; decay_step %d(%dms); wrote %d bytes]\n", - ts->volume, - duration, - duration / (ts->rate / 1000), - ts->channels, - ts->channels == 1 ? "" : "s", - wait, - wait / (ts->rate / 1000), - ts->decay_factor, - ts->decay_step, - ts->decay_step / (ts->rate / 1000), - ts->samples * 2); - } - } - return ts->samples / ts->channels; -} - -/* don't ask */ -static char *my_strdup (const char *s) -{ - size_t len = strlen (s) + 1; - void *new = malloc (len); - - if (new == NULL) { - return NULL; - } - - return (char *) memcpy (new, s, len); -} - -TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cmd) -{ - char *data = NULL, *cur = NULL, *end = NULL; - int LOOPING = 0; - - if (!cmd) { - return -1; - } - - do { - if (!(data = my_strdup(cmd))) { - return -1; - } - - cur = data; - - while (*cur) { - if (*cur == ' ' || *cur == '\r' || *cur == '\n') { - cur++; - continue; - } - - if ((end = strchr(cur, ';')) != 0) { - *end++ = '\0'; - } - - if (*(cur + 1) == '=') { - switch(*cur) { - case 'c': - ts->channels = atoi(cur + 2); - break; - case 'r': - ts->rate = atoi(cur + 2); - break; - case 'd': - ts->duration = atoi(cur + 2) * (ts->rate / 1000); - break; - case 'v': - { - float vol = (float)atof(cur + 2); - if (vol <= TELETONE_VOL_DB_MAX && vol >= TELETONE_VOL_DB_MIN) { - ts->volume = vol; - } - } - break; - case '>': - ts->decay_step = atoi(cur + 2) * (ts->rate / 1000); - ts->decay_direction = -1; - break; - case '<': - ts->decay_step = atoi(cur + 2) * (ts->rate / 1000); - ts->decay_direction = 1; - break; - case '+': - ts->decay_factor = (float)atof(cur + 2); - break; - case 'w': - ts->wait = atoi(cur + 2) * (ts->rate / 1000); - break; - case 'l': - ts->loops = atoi(cur + 2); - break; - case 'L': - if (!LOOPING) { - int L; - if ((L = atoi(cur + 2)) > 0) { - ts->LOOPS = L; - LOOPING++; - } - } - break; - } - } else { - while (*cur) { - char *p = NULL, *e = NULL; - teletone_tone_map_t mymap, *mapp = NULL; - - if (*cur == ' ' || *cur == '\r' || *cur == '\n') { - cur++; - continue; - } - - ts->tmp_duration = -1; - ts->tmp_wait = -1; - - memset(&mymap, 0, sizeof(mymap)); - - if (*(cur + 1) == '(') { - p = cur + 2; - if (*cur) { - char *next; - int i = 0; - if ((e = strchr(p, ')')) != 0) { - *e++ = '\0'; - } - do { - if (!p) { - break; - } - if ((next = strchr(p, ',')) != 0) { - *next++ = '\0'; - } - if (i == 0) { - ts->tmp_duration = atoi(p) * (ts->rate / 1000); - i++; - } else if (i == 1) { - ts->tmp_wait = atoi(p) * (ts->rate / 1000); - i++; - } else { - mymap.freqs[i++ - 2] = atof(p); - } - p = next; - - } while (next && (i-2) < TELETONE_MAX_TONES); - if (i > 2 && *cur == '%') { - mapp = &mymap; - } else if ((i != 2 || *cur == '%')) { - if (ts->debug && ts->debug_stream) { - fprintf(ts->debug_stream, "Syntax Error!\n"); - } - goto bottom; - } - } - } - - if (*cur && !mapp) { - if (*cur > 0 && *cur < TELETONE_TONE_RANGE) { - mapp = &ts->TONES[(int)*cur]; - } else if (ts->debug && ts->debug_stream) { - fprintf(ts->debug_stream, "Map [%c] Out Of Range!\n", *cur); - } - } - - if (mapp) { - if (mapp->freqs[0]) { - if (ts->handler) { - do { - ts->handler(ts, mapp); - if (ts->loops > 0) { - ts->loops--; - } - } while (ts->loops); - } - } else if (ts->debug && ts->debug_stream) { - fprintf(ts->debug_stream, "Ignoring Empty Map [%c]!\n", *cur); - } - } - - if (e) { - cur = e; - } else { - cur++; - } - } - } - - if (end) { - cur = end; - } else if (*cur){ - cur++; - } - } - bottom: - free(data); - data = NULL; - - if (ts->LOOPS > 0) { - ts->LOOPS--; - } - - } while (ts->LOOPS); - - return 0; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/priserver.c b/libs/freetdm/src/priserver.c deleted file mode 100644 index bbc1f2236e..0000000000 --- a/libs/freetdm/src/priserver.c +++ /dev/null @@ -1,328 +0,0 @@ -/***************************************************************************** - * priserver.c Refactoring of pritest.c - * - * Author(s): Anthony Minessale II - * Nenad Corbic - * - * Copyright: (c) 2005-2014 Anthony Minessale II - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * ============================================================================ - */ - -#include "freetdm.h" -#include -#include -#include -#include -#include -#include - -typedef struct { - int pid; - q931_call call; - void *pri; - int ready; -}call_info_t; - - -#define SANGOMA_MAX_CHAN_PER_SPAN 32 - -static call_info_t pidmap[SANGOMA_MAX_CHAN_PER_SPAN]; - -FIO_EVENT_CB_FUNCTION(my_ftdm_event_handler) -{ - if (event->e_type = FTDM_EVENT_DTMF) { - char *dtmf = event->data; - printf("DTMF %s\n", dtmf); - } -} - -/* Stupid runtime process to play a file to a b channel*/ -#define BYTES 320 -#define MAX_BYTES 1000 - -static int ready = 1; - -static void handle_SIGINT(int sig) -{ - if (sig) { - ready = 0; - } - - return; -} - -static void launch_channel(struct sangoma_pri *spri, int channo) -{ - pid_t pid; - int fd = 0, file = 0, inlen = 0, outlen = 0; - unsigned char inframe[MAX_BYTES], outframe[MAX_BYTES]; - fd_set readfds; - int mtu_mru=BYTES / 2; - int err; - ftdm_channel_t *chan; - ftdm_codec_t codec = FTDM_CODEC_SLIN; - unsigned ms = 20; - unsigned int lead = 50; - int ifd = -1; - ftdm_tone_type_t tt = FTDM_TONE_DTMF; - char dtmf[] = "1234567890"; - int loops = 0; - - pid = fork(); - - if (pid) { - pidmap[channo-1].pid = pid; - printf("-- Launching process %d to handle channel %d\n", pid, channo); - return; - } - - signal(SIGINT, handle_SIGINT); - - //ifd = open("/nfs/sounds/ptest.raw", O_WRONLY|O_CREAT|O_TRUNC, 777); - - memset(inframe, 0, MAX_BYTES); - memset(outframe, 0, MAX_BYTES); - - if (ftdm_channel_open(spri->span, channo, &chan) != FTDM_SUCCESS) { - printf("DEBUG cant open fd!\n"); - } - - - -#if 1 - if (ftdm_channel_command(chan, FTDM_COMMAND_SET_CODEC, &codec) != FTDM_SUCCESS) { - printf("Critical Error: Failed to set driver codec!\n"); - ftdm_channel_close(&chan); - exit(-1); - } -#endif - -#if 1 - if (ftdm_channel_command(chan, FTDM_COMMAND_ENABLE_DTMF_DETECT, &tt) != FTDM_SUCCESS) { - printf("Critical Error: Failed to set dtmf detect!\n"); - ftdm_channel_close(&chan); - exit(-1); - } - ftdm_channel_set_event_callback(chan, my_ftdm_event_handler); -#endif - - - if (ftdm_channel_command(chan, FTDM_COMMAND_SET_INTERVAL, &ms) != FTDM_SUCCESS) { - printf("Critical Error: Failed to set codec interval!\n"); - ftdm_channel_close(&chan); - exit(-1); - } - - file = open("sound.raw", O_RDONLY); - if (file < 0){ - printf("Critical Error: Failed to open sound file!\n"); - ftdm_channel_close(&chan); - exit(-1); - } - - - while(ready) { - ftdm_wait_flag_t flags = FTDM_READ; - ftdm_size_t len; - loops++; - - if (lead) { - lead--; - } - - if (!lead && loops == 300) { -#if 1 - if (ftdm_channel_command(chan, FTDM_COMMAND_SEND_DTMF, dtmf) != FTDM_SUCCESS) { - printf("Critical Error: Failed to send dtmf\n"); - ftdm_channel_close(&chan); - exit(-1); - } -#endif - - } - - if (ftdm_channel_wait(chan, &flags, 2000) != FTDM_SUCCESS) { - printf("wait FAIL! [%s]\n", chan->last_error); - break; - } - - if (flags & FTDM_READ) { - len = MAX_BYTES; - if (ftdm_channel_read(chan, inframe, &len) == FTDM_SUCCESS) { - //printf("READ: %d\n", len); - //write(ifd, inframe, len); - if(!lead && (outlen = read(file, outframe, len)) <= 0) { - break; - } - - } else { - printf("READ FAIL! %d [%s]\n", len, chan->last_error); - break; - } - if (lead) { - continue; - } - ftdm_channel_write(chan, outframe, sizeof(outframe), &len); - } else { - printf("BREAK"); - break; - } - } - - printf("loop done\n"); - - //sangoma_get_full_cfg(fd, &tdm_api); - close(file); - //close(ifd); - - pri_hangup(spri->pri, channo, 16); - if (ftdm_channel_close(&chan) != FTDM_SUCCESS) { - printf("Critical Error: Failed to close channel [%s]\n", chan->last_error); - } - - printf("Call Handler: Process Finished\n"); - exit(0); -} - - -/* Event Handlers */ - -static int on_info(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) -{ - printf( "number is: %s\n", event->ring.callednum); - if(strlen(event->ring.callednum) > 3) { - printf( "final number is: %s\n", event->ring.callednum); - pri_answer(spri->pri, event->ring.call, 0, 1); - } - return 0; -} - -static int on_hangup(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) -{ - //pri_hangup(spri->pri, event->hangup.call, event->hangup.cause); - printf("-- Hanging up channel %d\n", event->hangup.channel); - if(pidmap[event->hangup.channel-1].pid) { - pri_hangup(spri->pri, event->hangup.call, 16); - pri_destroycall(spri->pri, event->hangup.call); - kill(pidmap[event->hangup.channel-1].pid, SIGINT); - pidmap[event->hangup.channel-1].pid = 0; - } - return 0; -} - -static int on_ring(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) -{ - printf("-- Ring on channel %d (from %s to %s), answering...\n", event->ring.channel, event->ring.callingnum, event->ring.callednum); - pri_answer(spri->pri, event->ring.call, event->ring.channel, 1); - memcpy(&pidmap[event->ring.channel-1].call, event->ring.call, sizeof(q931_call)); - pidmap[event->ring.channel-1].pri=spri->pri; - pidmap[event->ring.channel-1].call = *event->ring.call; - launch_channel(spri, event->ring.channel); - return 0; -} - -static int on_restart(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) -{ - printf("-- Restarting channel %d\n", event->restart.channel); - return 0; -} - -static int on_anything(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) -{ - printf("%s: Caught Event %d (%s)\n", __FTDM_FUNC__, event_type, sangoma_pri_event_str(event_type)); - return 0; -} - -/* Generic Reaper */ -static void chan_ended(int sig) -{ - int status; - int x; - struct rusage rusage; - pid_t pid; - pid = wait4(-1, &status, WNOHANG, &rusage); - - printf("-- PID %d ended\n", pid); - - for (x=0;x -1) { - fprintf(stderr, "--!! Unknown PID %d exited\n", pid); - signal(SIGCHLD, chan_ended); - return; - } -} - -/* Our Program */ -int main(int argc, char *argv[]) -{ - struct sangoma_pri spri; - int debug = 0; - if (argv[1]) { - debug = atoi(argv[1]); - } - - ftdm_global_set_default_logger(FTDM_LOG_LEVEL_DEBUG); - if (ftdm_global_init() != FTDM_SUCCESS) { - fprintf(stderr, "Error loading FreeTDM\n"); - exit(-1); - } - - printf("FreeTDM loaded\n"); - - - debug = PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE; - printf("WTF %d\n", debug); - - if (sangoma_init_pri(&spri, - 1, // span - 24, // dchan - SANGOMA_PRI_SWITCH_DMS100, - SANGOMA_PRI_CPE, - debug) < 0) { - return -1; - } - //spri.pri->debug = (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE); - - //pri_set_debug(&spri.pri, (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)); - - SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_ANY, on_anything); - SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_RING, on_ring); - SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_HANGUP, on_hangup); - SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_HANGUP_REQ, on_hangup); - SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_INFO_RECEIVED, on_info); - SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_RESTART, on_restart); - - signal(SIGCHLD, chan_ended); - sangoma_run_pri(&spri); - return 0; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/sangoma_pri.c b/libs/freetdm/src/sangoma_pri.c deleted file mode 100644 index a6e79c9682..0000000000 --- a/libs/freetdm/src/sangoma_pri.c +++ /dev/null @@ -1,251 +0,0 @@ -/***************************************************************************** - * sangoma_pri.c libpri Sangoma integration - * - * Author(s): Anthony Minessale II - * Nenad Corbic - * - * Copyright: (c) 2005-2014 Anthony Minessale II - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * ============================================================================ - */ - -#include "freetdm.h" -#include -#ifndef HAVE_GETTIMEOFDAY - -#ifdef WIN32 -#include - -static __inline int gettimeofday(struct timeval *tp, void *nothing) -{ -#ifdef WITHOUT_MM_LIB - SYSTEMTIME st; - time_t tt; - struct tm tmtm; - /* mktime converts local to UTC */ - GetLocalTime (&st); - tmtm.tm_sec = st.wSecond; - tmtm.tm_min = st.wMinute; - tmtm.tm_hour = st.wHour; - tmtm.tm_mday = st.wDay; - tmtm.tm_mon = st.wMonth - 1; - tmtm.tm_year = st.wYear - 1900; tmtm.tm_isdst = -1; - tt = mktime (&tmtm); - tp->tv_sec = tt; - tp->tv_usec = st.wMilliseconds * 1000; -#else - /** - ** The earlier time calculations using GetLocalTime - ** had a time resolution of 10ms.The timeGetTime, part - ** of multimedia apis offer a better time resolution - ** of 1ms.Need to link against winmm.lib for this - **/ - unsigned long Ticks = 0; - unsigned long Sec =0; - unsigned long Usec = 0; - Ticks = timeGetTime(); - - Sec = Ticks/1000; - Usec = (Ticks - (Sec*1000))*1000; - tp->tv_sec = Sec; - tp->tv_usec = Usec; -#endif /* WITHOUT_MM_LIB */ - (void)nothing; - return 0; -} -#endif /* WIN32 */ -#endif /* HAVE_GETTIMEOFDAY */ - -static struct sangoma_pri_event_list SANGOMA_PRI_EVENT_LIST[] = { - {0, SANGOMA_PRI_EVENT_ANY, "ANY"}, - {1, SANGOMA_PRI_EVENT_DCHAN_UP, "DCHAN_UP"}, - {2, SANGOMA_PRI_EVENT_DCHAN_DOWN, "DCHAN_DOWN"}, - {3, SANGOMA_PRI_EVENT_RESTART, "RESTART"}, - {4, SANGOMA_PRI_EVENT_CONFIG_ERR, "CONFIG_ERR"}, - {5, SANGOMA_PRI_EVENT_RING, "RING"}, - {6, SANGOMA_PRI_EVENT_HANGUP, "HANGUP"}, - {7, SANGOMA_PRI_EVENT_RINGING, "RINGING"}, - {8, SANGOMA_PRI_EVENT_ANSWER, "ANSWER"}, - {9, SANGOMA_PRI_EVENT_HANGUP_ACK, "HANGUP_ACK"}, - {10, SANGOMA_PRI_EVENT_RESTART_ACK, "RESTART_ACK"}, - {11, SANGOMA_PRI_EVENT_FACNAME, "FACNAME"}, - {12, SANGOMA_PRI_EVENT_INFO_RECEIVED, "INFO_RECEIVED"}, - {13, SANGOMA_PRI_EVENT_PROCEEDING, "PROCEEDING"}, - {14, SANGOMA_PRI_EVENT_SETUP_ACK, "SETUP_ACK"}, - {15, SANGOMA_PRI_EVENT_HANGUP_REQ, "HANGUP_REQ"}, - {16, SANGOMA_PRI_EVENT_NOTIFY, "NOTIFY"}, - {17, SANGOMA_PRI_EVENT_PROGRESS, "PROGRESS"}, - {18, SANGOMA_PRI_EVENT_KEYPAD_DIGIT, "KEYPAD_DIGIT"} -}; - -#define LINE "--------------------------------------------------------------------------------" - -char *sangoma_pri_event_str(sangoma_pri_event_t event_id) -{ - return SANGOMA_PRI_EVENT_LIST[event_id].name; -} - -static int __pri_sangoma_read(struct pri *pri, void *buf, int buflen) -{ - struct sangoma_pri *spri = (struct sangoma_pri *) pri->userdata; - ftdm_size_t len = buflen; - int res; - char bb[4096] = ""; - - - if (ftdm_channel_read(spri->zdchan, buf, &len) != FTDM_SUCCESS) { - printf("D-READ FAIL! [%s]\n", spri->zdchan->last_error); - return 0; - } - res = (int)len; - memset(&((unsigned char*)buf)[res],0,2); - res+=2; - - //print_bits(buf, res-2, bb, sizeof(bb), 1, 0); - //ftdm_log(FTDM_LOG_DEBUG, "READ %d\n%s\n%s\n\n", res-2, LINE, bb); - - return res; -} - -static int __pri_sangoma_write(struct pri *pri, void *buf, int buflen) -{ - struct sangoma_pri *spri = (struct sangoma_pri *) pri->userdata; - int res; - ftdm_size_t len = buflen -2; - char bb[4096] = ""; - - if (ftdm_channel_write(spri->zdchan, buf, buflen, &len) != FTDM_SUCCESS) { - printf("D-WRITE FAIL! [%s]\n", spri->zdchan->last_error); - return 0; - } - - //print_bits(buf, (int)buflen-2, bb, sizeof(bb), 1, 0); - //ftdm_log(FTDM_LOG_DEBUG, "WRITE %d\n%s\n%s\n\n", (int)buflen-2, LINE, bb); - - return (int) buflen; -} - -int sangoma_init_pri(struct sangoma_pri *spri, int span, int dchan, int swtype, int node, int debug) -{ - int ret = -1; - ftdm_socket_t dfd = 0; - - memset(spri, 0, sizeof(struct sangoma_pri)); - - if (ftdm_channel_open(span, dchan, &spri->zdchan) != FTDM_SUCCESS) { - fprintf(stderr, "Unable to open DCHAN %d for span %d (%s)\n", dchan, span, strerror(errno)); - } else { - if ((spri->pri = pri_new_cb(spri->zdchan->sockfd, node, swtype, __pri_sangoma_read, __pri_sangoma_write, spri))){ - spri->span = span; - pri_set_debug(spri->pri, debug); - ret = 0; - } else { - fprintf(stderr, "Unable to create PRI\n"); - } - } - return ret; -} - - -int sangoma_one_loop(struct sangoma_pri *spri) -{ - fd_set rfds, efds; - struct timeval now = {0,0}, *next; - pri_event *event; - int sel; - - if (spri->on_loop) { - spri->on_loop(spri); - } - - FD_ZERO(&rfds); - FD_ZERO(&efds); - -#ifdef _MSC_VER - //Windows macro for FD_SET includes a warning C4127: conditional expression is constant -#pragma warning(push) -#pragma warning(disable:4127) -#endif - - FD_SET(spri->pri->fd, &rfds); - FD_SET(spri->pri->fd, &efds); - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - - if ((next = pri_schedule_next(spri->pri))) { - gettimeofday(&now, NULL); - now.tv_sec = next->tv_sec - now.tv_sec; - now.tv_usec = next->tv_usec - now.tv_usec; - if (now.tv_usec < 0) { - now.tv_usec += 1000000; - now.tv_sec -= 1; - } - if (now.tv_sec < 0) { - now.tv_sec = 0; - now.tv_usec = 0; - } - } - - sel = select(spri->pri->fd + 1, &rfds, NULL, &efds, next ? &now : NULL); - event = NULL; - - if (!sel) { - event = pri_schedule_run(spri->pri); - } else if (sel > 0) { - event = pri_check_event(spri->pri); - } - - if (event) { - event_handler handler; - /* 0 is catchall event handler */ - if ((handler = spri->eventmap[event->e] ? spri->eventmap[event->e] : spri->eventmap[0] ? spri->eventmap[0] : NULL)) { - handler(spri, event->e, event); - } else { - fprintf(stderr,"No event handler found for event %d.\n", event->e); - } - } - - return sel; -} - -int sangoma_run_pri(struct sangoma_pri *spri) -{ - int ret = 0; - - for (;;){ - ret=sangoma_one_loop(spri); - if (ret < 0){ - -#ifndef WIN32 //This needs to be adressed fror WIN32 still - if (errno == EINTR){ - /* Igonore an interrupted system call */ - continue; - } -#endif - printf("Error = %i\n",ret); - perror("Sangoma Run Pri: "); - break; - } - } - - return ret; - -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - diff --git a/libs/freetdm/src/sangoma_pri.h b/libs/freetdm/src/sangoma_pri.h deleted file mode 100644 index 873aab8a27..0000000000 --- a/libs/freetdm/src/sangoma_pri.h +++ /dev/null @@ -1,100 +0,0 @@ -/***************************************************************************** - * libsangoma.c AFT T1/E1: HDLC API Code Library - * - * Author(s): Anthony Minessale II - * Nenad Corbic - * - * Copyright: (c) 2005-2014 Anthony Minessale II - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * ============================================================================ - */ - -#ifndef _SANGOMA_PRI_H -#define _SANGOMA_PRI_H -#include -#include - - -#define SANGOMA_MAX_CHAN_PER_SPAN 32 - -typedef enum { - SANGOMA_PRI_EVENT_ANY = 0, - SANGOMA_PRI_EVENT_DCHAN_UP = PRI_EVENT_DCHAN_UP, - SANGOMA_PRI_EVENT_DCHAN_DOWN = PRI_EVENT_DCHAN_DOWN, - SANGOMA_PRI_EVENT_RESTART = PRI_EVENT_RESTART, - SANGOMA_PRI_EVENT_CONFIG_ERR = PRI_EVENT_CONFIG_ERR, - SANGOMA_PRI_EVENT_RING = PRI_EVENT_RING, - SANGOMA_PRI_EVENT_HANGUP = PRI_EVENT_HANGUP, - SANGOMA_PRI_EVENT_RINGING = PRI_EVENT_RINGING, - SANGOMA_PRI_EVENT_ANSWER = PRI_EVENT_ANSWER, - SANGOMA_PRI_EVENT_HANGUP_ACK = PRI_EVENT_HANGUP_ACK, - SANGOMA_PRI_EVENT_RESTART_ACK = PRI_EVENT_RESTART_ACK, - SANGOMA_PRI_EVENT_FACNAME = PRI_EVENT_FACNAME, - SANGOMA_PRI_EVENT_INFO_RECEIVED = PRI_EVENT_INFO_RECEIVED, - SANGOMA_PRI_EVENT_PROCEEDING = PRI_EVENT_PROCEEDING, - SANGOMA_PRI_EVENT_SETUP_ACK = PRI_EVENT_SETUP_ACK, - SANGOMA_PRI_EVENT_HANGUP_REQ = PRI_EVENT_HANGUP_REQ, - SANGOMA_PRI_EVENT_NOTIFY = PRI_EVENT_NOTIFY, - SANGOMA_PRI_EVENT_PROGRESS = PRI_EVENT_PROGRESS, - SANGOMA_PRI_EVENT_KEYPAD_DIGIT = PRI_EVENT_KEYPAD_DIGIT -} sangoma_pri_event_t; - -typedef enum { - SANGOMA_PRI_NETWORK = PRI_NETWORK, - SANGOMA_PRI_CPE = PRI_CPE -} sangoma_pri_node_t; - -typedef enum { - SANGOMA_PRI_SWITCH_UNKNOWN = PRI_SWITCH_UNKNOWN, - SANGOMA_PRI_SWITCH_NI2 = PRI_SWITCH_NI2, - SANGOMA_PRI_SWITCH_DMS100 = PRI_SWITCH_DMS100, - SANGOMA_PRI_SWITCH_LUCENT5E = PRI_SWITCH_LUCENT5E, - SANGOMA_PRI_SWITCH_ATT4ESS = PRI_SWITCH_ATT4ESS, - SANGOMA_PRI_SWITCH_EUROISDN_E1 = PRI_SWITCH_EUROISDN_E1, - SANGOMA_PRI_SWITCH_EUROISDN_T1 = PRI_SWITCH_EUROISDN_T1, - SANGOMA_PRI_SWITCH_NI1 = PRI_SWITCH_NI1, - SANGOMA_PRI_SWITCH_GR303_EOC = PRI_SWITCH_GR303_EOC, - SANGOMA_PRI_SWITCH_GR303_TMC = PRI_SWITCH_GR303_TMC, - SANGOMA_PRI_SWITCH_QSIG = PRI_SWITCH_QSIG -} sangoma_pri_switch_t; - -typedef enum { - SANGOMA_PRI_READY = (1 << 0) -} sangoma_pri_flag_t; - -struct sangoma_pri; -typedef int (*event_handler)(struct sangoma_pri *, sangoma_pri_event_t, pri_event *); -typedef int (*loop_handler)(struct sangoma_pri *); -#define MAX_EVENT 18 - -struct sangoma_pri { - struct pri *pri; - int span; - int dchan; - unsigned int flags; - void *private_info; - event_handler eventmap[MAX_EVENT+1]; - loop_handler on_loop; - ftdm_channel_t *zdchan; -}; - -struct sangoma_pri_event_list { - int event_id; - int pri_event; - char *name; -}; - - - -#define SANGOMA_MAP_PRI_EVENT(spri, event, func) spri.eventmap[event] = func; - -char *sangoma_pri_event_str(sangoma_pri_event_t event_id); -int sangoma_one_loop(struct sangoma_pri *spri); -int sangoma_init_pri(struct sangoma_pri *spri, int span, int dchan, int swtype, int node, int debug); -int sangoma_run_pri(struct sangoma_pri *spri); - -#endif diff --git a/libs/freetdm/src/ss7/README b/libs/freetdm/src/ss7/README deleted file mode 100644 index 0efe94c94a..0000000000 --- a/libs/freetdm/src/ss7/README +++ /dev/null @@ -1,3 +0,0 @@ -SS7 Coming soon - --Shane Burrell- diff --git a/libs/freetdm/src/testanalog.c b/libs/freetdm/src/testanalog.c deleted file mode 100644 index 764c5d81d5..0000000000 --- a/libs/freetdm/src/testanalog.c +++ /dev/null @@ -1,138 +0,0 @@ -#include -#include -#include -#include "freetdm.h" - - -static void *test_call(ftdm_thread_t *me, void *obj) -{ - ftdm_channel_t *chan = (ftdm_channel_t *) obj; - uint8_t frame[1024]; - ftdm_size_t len; - char *number = ftdm_strdup("5551212"); - - ftdm_unused_arg(me); - - ftdm_sleep(10 * 1000); - - ftdm_log(FTDM_LOG_DEBUG, "answer call and start echo test\n"); - - ftdm_channel_call_answer(chan); - ftdm_channel_command(chan, FTDM_COMMAND_SEND_DTMF, number); - - while (ftdm_channel_call_check_answered(chan)) { - ftdm_wait_flag_t flags = FTDM_READ; - - if (ftdm_channel_wait(chan, &flags, -1) == FTDM_FAIL) { - break; - } - len = sizeof(frame); - if (flags & FTDM_READ) { - if (ftdm_channel_read(chan, frame, &len) == FTDM_SUCCESS) { - //ftdm_log(FTDM_LOG_DEBUG, "WRITE %d\n", len); - ftdm_channel_write(chan, frame, sizeof(frame), &len); - } else { - break; - } - } - } - - if (ftdm_channel_call_check_answered(chan)) { - ftdm_channel_call_indicate(chan, FTDM_CHANNEL_INDICATE_BUSY); - } - - ftdm_log(FTDM_LOG_DEBUG, "call over\n"); - ftdm_safe_free(number); - return NULL; -} - -static FIO_SIGNAL_CB_FUNCTION(on_signal) -{ - ftdm_log(FTDM_LOG_DEBUG, "got sig [%s]\n", ftdm_signal_event2str(sigmsg->event_id)); - - switch(sigmsg->event_id) { - case FTDM_SIGEVENT_START: - ftdm_channel_call_indicate(sigmsg->channel, FTDM_CHANNEL_INDICATE_RINGING); - ftdm_log(FTDM_LOG_DEBUG, "launching thread and indicating ring\n"); - ftdm_thread_create_detached(test_call, sigmsg->channel); - break; - default: - break; - } - - return FTDM_SUCCESS; -} - -static int R = 0; -#if 0 -static void handle_SIGINT(int sig) -{ - if (sig); - R = 0; - return; -} -#endif - -int main(int argc, char *argv[]) -{ - ftdm_span_t *span; - int span_id; - int digit_timeout = 2000; - int max_dialstr = 11; - - if (argc < 2) { - printf("usage %s \n", argv[0]); - exit(-1); - } - - span_id = atoi(argv[1]); - - ftdm_global_set_default_logger(FTDM_LOG_LEVEL_DEBUG); - - if (ftdm_global_init() != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error loading FreeTDM\n"); - exit(-1); - } - - ftdm_log(FTDM_LOG_DEBUG, "FreeTDM loaded\n"); - - if (ftdm_span_find(span_id, &span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span\n"); - goto done; - } - - - if (ftdm_configure_span(span, "analog", on_signal, - "tonemap", "us", - "digit_timeout", &digit_timeout, - "max_dialstr", &max_dialstr, - FTDM_TAG_END - ) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM span\n"); - goto done; - } - ftdm_span_start(span); - - R = 1; - - while(ftdm_running() && R) { - ftdm_sleep(1 * 1000); - } - -done: - - ftdm_global_destroy(); - return 0; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - diff --git a/libs/freetdm/src/testapp.c b/libs/freetdm/src/testapp.c deleted file mode 100644 index 1d7a2cb8cb..0000000000 --- a/libs/freetdm/src/testapp.c +++ /dev/null @@ -1,89 +0,0 @@ -#include "freetdm.h" -#include - -int main(int argc, char *argv[]) -{ - ftdm_global_set_default_logger(FTDM_LOG_LEVEL_DEBUG); - ftdm_channel_t *chan; - unsigned ms = 20; - ftdm_codec_t codec = FTDM_CODEC_SLIN; - unsigned runs = 1; - int spanid, chanid; - - ftdm_unused_arg(argc); - ftdm_unused_arg(argv); - - if (ftdm_global_init() != FTDM_SUCCESS) { - fprintf(stderr, "Error loading FreeTDM\n"); - exit(-1); - } - - printf("FreeTDM loaded\n"); - - top: - //if (ftdm_channel_open_any("wanpipe", 0, FTDM_HUNT_BOTTOM_UP, &chan) == FTDM_SUCCESS) { - if (ftdm_channel_open(1, 1, &chan) == FTDM_SUCCESS) { - int x = 0; - spanid = ftdm_channel_get_span_id(chan); - chanid = ftdm_channel_get_id(chan); - printf("opened channel %d:%d\n", spanid, chanid); - -#if 1 - if (ftdm_channel_command(chan, FTDM_COMMAND_SET_INTERVAL, &ms) == FTDM_SUCCESS) { - ms = 0; - ftdm_channel_command(chan, FTDM_COMMAND_GET_INTERVAL, &ms); - printf("interval set to %u\n", ms); - } else { - printf("set interval failed [%s]\n", ftdm_channel_get_last_error(chan)); - } -#endif - if (ftdm_channel_command(chan, FTDM_COMMAND_SET_CODEC, &codec) == FTDM_SUCCESS) { - codec = 1; - ftdm_channel_command(chan, FTDM_COMMAND_GET_CODEC, &codec); - printf("codec set to %u\n", codec); - } else { - printf("set codec failed [%s]\n", ftdm_channel_get_last_error(chan)); - } - - for(x = 0; x < 25; x++) { - unsigned char buf[2048]; - ftdm_size_t len = sizeof(buf); - ftdm_wait_flag_t flags = FTDM_READ; - - if (ftdm_channel_wait(chan, &flags, -1) == FTDM_FAIL) { - printf("wait FAIL! %u [%s]\n", (unsigned)len, ftdm_channel_get_last_error(chan)); - } - if (flags & FTDM_READ) { - if (ftdm_channel_read(chan, buf, &len) == FTDM_SUCCESS) { - printf("READ: %u\n", (unsigned)len); - } else { - printf("READ FAIL! %u [%s]\n", (unsigned)len, ftdm_channel_get_last_error(chan)); - break; - } - } else { - printf("wait fail [%s]\n", ftdm_channel_get_last_error(chan)); - } - } - ftdm_channel_close(&chan); - } else { - printf("open fail [%s]\n", ftdm_channel_get_last_error(chan)); - } - - if(--runs) { - goto top; - } - - ftdm_global_destroy(); - return 0; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/testcid.c b/libs/freetdm/src/testcid.c deleted file mode 100644 index e6a0116d4a..0000000000 --- a/libs/freetdm/src/testcid.c +++ /dev/null @@ -1,109 +0,0 @@ -#include "private/ftdm_core.h" - -ftdm_status_t my_write_sample(int16_t *buf, ftdm_size_t buflen, void *user_data); - -struct helper { - int fd; - int wrote; -}; - -ftdm_status_t my_write_sample(int16_t *buf, ftdm_size_t buflen, void *user_data) -{ - struct helper *foo = (struct helper *) user_data; - size_t len; - len = write(foo->fd, buf, buflen * 2); - if (!len) return FTDM_FAIL; - foo->wrote += buflen * 2; - return FTDM_SUCCESS; -} - -int main(int argc, char *argv[]) -{ - struct ftdm_fsk_modulator fsk_trans; - ftdm_fsk_data_state_t fsk_data = {0}; - int fd = -1; - int16_t buf[160] = {0}; - ssize_t len = 0; - size_t type, mlen; - char *sp; - char str[128] = ""; - char fbuf[256]; - uint8_t databuf[1024] = ""; - struct helper foo = {0}; - // int x, bytes, start_bits = 180, stop_bits = 5, sbits = 300; - char time_str[9]; - struct tm tm; - time_t now; - - if (argc < 2) { - int x; - const char *url = "sip:cool@rad.com"; - - if ((fd = open("tone.raw", O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR)) < 0) { - fprintf(stderr, "File Error! [%s]\n", strerror(errno)); - exit(-1); - } - - - time(&now); - localtime_r(&now, &tm); - strftime(time_str, sizeof(time_str), "%m%d%H%M", &tm); - - ftdm_fsk_data_init(&fsk_data, databuf, sizeof(databuf)); -#if 1 - - ftdm_fsk_data_add_mdmf(&fsk_data, MDMF_DATETIME, (uint8_t *)time_str, strlen(time_str)); - //ftdm_fsk_data_add_mdmf(&fsk_data, MDMF_DATETIME, "06091213", 8); - ftdm_fsk_data_add_mdmf(&fsk_data, MDMF_PHONE_NUM, (uint8_t *)"14149361212", 7); - ftdm_fsk_data_add_mdmf(&fsk_data, MDMF_PHONE_NAME, (uint8_t *)"Fred Smith", 10); - for(x = 0; x < 0; x++) - ftdm_fsk_data_add_mdmf(&fsk_data, MDMF_ALT_ROUTE, (uint8_t *)url, strlen(url)); -#else - ftdm_fsk_data_add_sdmf(&fsk_data, "06061234", "0"); - //ftdm_fsk_data_add_sdmf(&state, "06061234", "5551212"); -#endif - ftdm_fsk_data_add_checksum(&fsk_data); - - foo.fd = fd; - - - ftdm_fsk_modulator_init(&fsk_trans, FSK_BELL202, 8000, &fsk_data, -14, 180, 5, 300, my_write_sample, &foo); - ftdm_fsk_modulator_send_all((&fsk_trans)); - - printf("%u %d %d\n", (unsigned) fsk_data.dlen, foo.wrote, fsk_trans.est_bytes); - - if (fd > -1) { - close (fd); - } - - return 0; - } - - if (ftdm_fsk_demod_init(&fsk_data, 8000, (uint8_t *)fbuf, sizeof(fbuf))) { - printf("wtf\n"); - return 0; - } - - if ((fd = open(argv[1], O_RDONLY)) < 0) { - fprintf(stderr, "cant open file %s\n", argv[1]); - exit (-1); - } - - while((len = read(fd, buf, sizeof(buf))) > 0) { - if (ftdm_fsk_demod_feed(&fsk_data, buf, len / 2) != FTDM_SUCCESS) { - break; - } - } - - while(ftdm_fsk_data_parse(&fsk_data, &type, &sp, &mlen) == FTDM_SUCCESS) { - ftdm_copy_string(str, sp, mlen+1); - *(str+mlen) = '\0'; - ftdm_clean_string(str); - printf("TYPE %u (%s) LEN %u VAL [%s]\n", (unsigned)type, ftdm_mdmf_type2str(type), (unsigned)mlen, str); - } - - ftdm_fsk_demod_destroy(&fsk_data); - - close(fd); - return 0; -} diff --git a/libs/freetdm/src/testisdn.c b/libs/freetdm/src/testisdn.c deleted file mode 100644 index 13e14aedd2..0000000000 --- a/libs/freetdm/src/testisdn.c +++ /dev/null @@ -1,74 +0,0 @@ -#include "freetdm.h" -#include - - -static FIO_SIGNAL_CB_FUNCTION(on_signal) -{ - return FTDM_FAIL; -} - -static int R = 0; -static void handle_SIGINT(int sig) -{ - if (sig); - R = 0; - return; -} - -int main(int argc, char *argv[]) -{ - ftdm_span_t *span; - - ftdm_global_set_default_logger(FTDM_LOG_LEVEL_DEBUG); - - if (argc < 2) { - printf("umm no\n"); - exit(-1); - } - - if (ftdm_global_init() != FTDM_SUCCESS) { - fprintf(stderr, "Error loading FreeTDM\n"); - exit(-1); - } - - printf("FreeTDM loaded\n"); - - if (ftdm_span_find(atoi(argv[1]), &span) != FTDM_SUCCESS) { - fprintf(stderr, "Error finding FreeTDM span\n"); - goto done; - } - - if (ftdm_configure_span("isdn", span, on_signal, - "mode", "te", - "dialect", "national", - TAG_END) == FTDM_SUCCESS) { - ftdm_span_start(span); - } else { - fprintf(stderr, "Error starting ISDN D-Channel\n"); - goto done; - } - - signal(SIGINT, handle_SIGINT); - R = 1; - while(R) { - ftdm_sleep(1 * 1000); - } - - done: - - ftdm_global_destroy(); - - return 1; - -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/testpri.c b/libs/freetdm/src/testpri.c deleted file mode 100644 index fb7c0bdd38..0000000000 --- a/libs/freetdm/src/testpri.c +++ /dev/null @@ -1,174 +0,0 @@ -#include "freetdm.h" -#include -#include -#include -#include -#include -#include -#include - -static int THREADS[4][31] = { {0} }; -static int R = 0; -static int T = 0; -static ftdm_mutex_t *mutex = NULL; - - -static void *channel_run(ftdm_thread_t *me, void *obj) -{ - ftdm_channel_t *ftdmchan = obj; - int fd = -1; - short buf[160]; - int spanid = ftdm_channel_get_span_id(ftdmchan); - int chanid = ftdm_channel_get_id(ftdmchan); - - ftdm_unused_arg(me); - - ftdm_mutex_lock(mutex); - T++; - ftdm_mutex_unlock(mutex); - - ftdm_channel_call_answer(ftdmchan); - - if ((fd = open("test.raw", O_RDONLY, 0)) < 0) { - goto end; - } - - while(R == 1 && THREADS[spanid][chanid] == 1) { - ssize_t bytes = read(fd, buf, sizeof(buf)); - size_t bbytes; - - if (bytes <= 0) { - break; - } - - bbytes = (size_t) bytes; - - fio_slin2alaw(buf, sizeof(buf), &bbytes); - - if (ftdm_channel_write(ftdmchan, buf, sizeof(buf), &bbytes) != FTDM_SUCCESS) { - break; - } - } - - close(fd); - - end: - - ftdm_channel_call_hangup(ftdmchan); - - THREADS[spanid][chanid] = 0; - - ftdm_mutex_lock(mutex); - T = 0; - ftdm_mutex_unlock(mutex); - - return NULL; -} - -static FIO_SIGNAL_CB_FUNCTION(on_signal) -{ - int spanid = ftdm_channel_get_span_id(sigmsg->channel); - int chanid = ftdm_channel_get_id(sigmsg->channel); - ftdm_log(FTDM_LOG_DEBUG, "got sig %d:%d [%s]\n", spanid, chanid, ftdm_signal_event2str(sigmsg->event_id)); - - switch(sigmsg->event_id) { - - case FTDM_SIGEVENT_STOP: - THREADS[spanid][chanid] = -1; - break; - - case FTDM_SIGEVENT_START: - if (!THREADS[spanid][chanid]) { - THREADS[spanid][chanid] = 1; - ftdm_thread_create_detached(channel_run, sigmsg->channel); - } - - break; - default: - break; - } - - return FTDM_SUCCESS; -} - - -static void handle_SIGINT(int sig) -{ - ftdm_unused_arg(sig); - - ftdm_mutex_lock(mutex); - R = 0; - ftdm_mutex_unlock(mutex); - - return; -} - -int main(int argc, char *argv[]) -{ - ftdm_span_t *span; - ftdm_mutex_create(&mutex); - - ftdm_global_set_default_logger(FTDM_LOG_LEVEL_DEBUG); - - if (argc < 2) { - printf("umm no\n"); - exit(-1); - } - - if (ftdm_global_init() != FTDM_SUCCESS) { - fprintf(stderr, "Error loading FreeTDM\n"); - exit(-1); - } - - printf("FreeTDM loaded\n"); - - if (ftdm_span_find(atoi(argv[1]), &span) != FTDM_SUCCESS) { - fprintf(stderr, "Error finding FreeTDM span\n"); - goto done; - } - - - - if (ftdm_configure_span( - span, "libpri", on_signal, - "node", "cpe", - "switch", "euroisdn", - "dp", "unknown", - "l1", "alaw", - "debug", NULL, - "opts", 0, - FTDM_TAG_END) == FTDM_SUCCESS) { - - - ftdm_span_start(span); - } else { - fprintf(stderr, "Error starting ISDN D-Channel\n"); - goto done; - } - - signal(SIGINT, handle_SIGINT); - ftdm_mutex_lock(mutex); - R = 1; - ftdm_mutex_unlock(mutex); - while(R || T) { - ftdm_sleep(1 * 1000); - } - - done: - - ftdm_global_destroy(); - - return 1; - -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/testr2.c b/libs/freetdm/src/testr2.c deleted file mode 100644 index ef6897fc29..0000000000 --- a/libs/freetdm/src/testr2.c +++ /dev/null @@ -1,169 +0,0 @@ -#include "freetdm.h" -#include -#include - -static volatile int running = 0; -static ftdm_mutex_t *the_mutex = NULL; -static ftdm_channel_t *fchan = NULL; -static ftdm_channel_indication_t indication = FTDM_CHANNEL_INDICATE_NONE; - -static FIO_SIGNAL_CB_FUNCTION(on_r2_signal) -{ - int chanid = ftdm_channel_get_ph_id(sigmsg->channel); - ftdm_log(FTDM_LOG_DEBUG, "Got R2 channel sig [%s] in channel %d\n", ftdm_signal_event2str(sigmsg->event_id), chanid); - switch (sigmsg->event_id) { - case FTDM_SIGEVENT_START: - { - ftdm_mutex_lock(the_mutex); - if (!fchan) { - fchan = sigmsg->channel; - indication = FTDM_CHANNEL_INDICATE_PROCEED; - } - ftdm_mutex_unlock(the_mutex); - } - break; - case FTDM_SIGEVENT_INDICATION_COMPLETED: - { - ftdm_channel_indication_t ind = FTDM_CHANNEL_INDICATE_NONE; - if (sigmsg->ev_data.indication_completed.indication == FTDM_CHANNEL_INDICATE_PROCEED) { - ftdm_log(FTDM_LOG_DEBUG, "Proceed indication result = %d\n", sigmsg->ev_data.indication_completed.status); - ind = FTDM_CHANNEL_INDICATE_PROGRESS; - } else if (sigmsg->ev_data.indication_completed.indication == FTDM_CHANNEL_INDICATE_PROGRESS) { - ftdm_log(FTDM_LOG_DEBUG, "Progress indication result = %d\n", sigmsg->ev_data.indication_completed.status); - ind = FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA; - } else if (sigmsg->ev_data.indication_completed.indication == FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA) { - ftdm_log(FTDM_LOG_DEBUG, "Progress media indication result = %d\n", sigmsg->ev_data.indication_completed.status); - ind = FTDM_CHANNEL_INDICATE_ANSWER; - } else if (sigmsg->ev_data.indication_completed.indication == FTDM_CHANNEL_INDICATE_ANSWER) { - ftdm_log(FTDM_LOG_DEBUG, "Answer indication result = %d\n", sigmsg->ev_data.indication_completed.status); - } else { - ftdm_log(FTDM_LOG_DEBUG, "Unexpected indication, result = %d\n", sigmsg->ev_data.indication_completed.status); - exit(1); - } - ftdm_mutex_lock(the_mutex); - if (fchan) { - indication = ind; - } - ftdm_mutex_unlock(the_mutex); - } - break; - case FTDM_SIGEVENT_STOP: - { - ftdm_channel_call_hangup(sigmsg->channel); - } - break; - case FTDM_SIGEVENT_RELEASED: - { - ftdm_mutex_lock(the_mutex); - if (fchan && fchan == sigmsg->channel) { - fchan = NULL; - } - ftdm_mutex_unlock(the_mutex); - } - break; - default: - break; - } - return FTDM_SUCCESS; -} - -static void stop_test(int sig) -{ - ftdm_unused_arg(sig); - running = 0; -} - -int main(int argc, char *argv[]) -{ - ftdm_span_t *span; - ftdm_conf_parameter_t parameters[20]; - - ftdm_mutex_create(&the_mutex); - - if (argc < 2) { - printf("umm no\n"); - exit(1); - } - - ftdm_global_set_default_logger(FTDM_LOG_LEVEL_DEBUG); - - if (ftdm_global_init() != FTDM_SUCCESS) { - fprintf(stderr, "Error loading FreeTDM\n"); - exit(1); - } - - ftdm_global_configuration(); - - printf("FreeTDM loaded\n"); - - if (ftdm_span_find_by_name(argv[1], &span) != FTDM_SUCCESS) { - fprintf(stderr, "Error finding FreeTDM span %s\n", argv[1]); - goto done; - } - - /* testing non-blocking operation */ - //ftdm_span_set_blocking_mode(span, FTDM_FALSE); - - parameters[0].var = "variant"; - parameters[0].val = "br"; - - parameters[1].var = "max_ani"; - parameters[1].val = "4"; - - parameters[2].var = "max_dnis"; - parameters[2].val = "4"; - - parameters[3].var = "logging"; - parameters[3].val = "all"; - - parameters[4].var = NULL; - parameters[4].val = NULL; - - if (ftdm_configure_span_signaling(span, "r2", on_r2_signal, parameters) == FTDM_SUCCESS) { - ftdm_span_start(span); - } else { - fprintf(stderr, "Error starting R2 span\n"); - goto done; - } - - running = 1; - signal(SIGINT, stop_test); - while(running) { - ftdm_sleep(20); - if (fchan && indication != FTDM_CHANNEL_INDICATE_NONE) { - ftdm_channel_t *lchan = NULL; - ftdm_channel_indication_t ind = FTDM_CHANNEL_INDICATE_NONE; - ftdm_time_t start, stop, diff; - - ftdm_mutex_lock(the_mutex); - ind = indication; - indication = FTDM_CHANNEL_INDICATE_NONE; - lchan = fchan; - ftdm_mutex_unlock(the_mutex); - - start = ftdm_current_time_in_ms(); - ftdm_channel_call_indicate(lchan, ind); - stop = ftdm_current_time_in_ms(); - diff = stop - start; - ftdm_log(FTDM_LOG_DEBUG, "Setting indication %s took %"FTDM_TIME_FMT" ms\n", - ftdm_channel_indication2str(ind), diff); - } - } - -done: - - ftdm_global_destroy(); - - return 0; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/freetdm/src/testtones.c b/libs/freetdm/src/testtones.c deleted file mode 100644 index d5d5d548bf..0000000000 --- a/libs/freetdm/src/testtones.c +++ /dev/null @@ -1,76 +0,0 @@ -#include "private/ftdm_core.h" - -struct ttmp { - int fd; -}; - -static int teletone_handler(teletone_generation_session_t *ts, teletone_tone_map_t *map) -{ - struct ttmp *tmp = ts->user_data; - int wrote; - size_t len; - - wrote = teletone_mux_tones(ts, map); - len = write(tmp->fd, ts->buffer, wrote * 2); - - if (!len) return -1; - - return 0; -} - -#if 1 -int main(int argc, char *argv[]) -{ - teletone_generation_session_t ts; - struct ttmp tmp; - - if (argc < 3) { - fprintf(stderr, "Arg Error! \n"); - exit(-1); - } - - if ((tmp.fd = open(argv[1], O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR)) < 0) { - fprintf(stderr, "File Error! [%s]\n", strerror(errno)); - exit(-1); - } - - teletone_init_session(&ts, 0, teletone_handler, &tmp); - ts.rate = 8000; - ts.debug = 1; - ts.debug_stream = stdout; - teletone_run(&ts, argv[2]); - close(tmp.fd); - - return 0; -} -#else -int32_t main(int argc, char *argv[]) -{ - int32_t j, i, fd = -1; - int32_t rate = 8000; - /* SIT tones and durations */ - float tones[] = { 913.8, 1370.6, 1776.7, 0 }; - int32_t durations[] = {274, 274, 380, 0}; - teletone_dds_state_t dds = {0}; - int16_t sample; - size_t len = 1; - - if (argc < 2 || (fd = open(argv[1], O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR)) < 0) { - fprintf(stderr, "File Error!\n", strerror(errno)); - exit(-1); - } - - for (j = 0; tones[j] && durations[j]; j++) { - - teletone_dds_state_set_tone(&dds, tones[j], rate, -50); - - for(i = 0; (i < durations[j] * rate / 1000) && len != 0; i++) { - sample = teletone_dds_modulate_sample(&dds) * 20; - len = write(fd, &sample, sizeof(sample)); - } - - } - - close(fd); -} -#endif diff --git a/libs/freetdm/src/uart.c b/libs/freetdm/src/uart.c deleted file mode 100644 index 7211d9c643..0000000000 --- a/libs/freetdm/src/uart.c +++ /dev/null @@ -1,125 +0,0 @@ - -/* - * uart.c - * - * Copyright (c) 2005 Robert Krten. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This module contains a simple 8-bit UART, which performs a callback - * with the decoded byte value. - * - * 2005 06 11 R. Krten created -*/ - -#include -#include -#include -#include -#include - -#include "uart.h" - -/* - * dsp_uart_attr_init - * - * Initializes the attributes structure; this must be done before the - * attributes structure is used. -*/ - -void dsp_uart_attr_init (dsp_uart_attr_t *attr) -{ - memset (attr, 0, sizeof (*attr)); -} - -/* - * dsp_uart_attr_get_bytehandler - * dsp_uart_attr_set_bytehandler - * - * These functions get and set their respective elements from the - * attributes structure. If an error code is returned, it is just - * zero == ok, -1 == fail. -*/ - -bytehandler_func_t dsp_uart_attr_get_bytehandler(dsp_uart_attr_t *attr, void **bytehandler_arg) -{ - *bytehandler_arg = attr->bytehandler_arg; - return attr->bytehandler; -} - -void dsp_uart_attr_set_bytehandler(dsp_uart_attr_t *attr, bytehandler_func_t bytehandler, void *bytehandler_arg) -{ - attr->bytehandler = bytehandler; - attr->bytehandler_arg = bytehandler_arg; -} - -dsp_uart_handle_t *dsp_uart_create(dsp_uart_attr_t *attr) -{ - dsp_uart_handle_t *handle; - - handle = ftdm_malloc(sizeof (*handle)); - if (handle) { - memset(handle, 0, sizeof (*handle)); - - /* fill the attributes member */ - memcpy(&handle->attr, attr, sizeof (*attr)); - } - return handle; -} - -void dsp_uart_destroy(dsp_uart_handle_t **handle) -{ - if (*handle) { - ftdm_safe_free(*handle); - *handle = NULL; - } -} - - -void dsp_uart_bit_handler(void *x, int bit) -{ - dsp_uart_handle_t *handle = (dsp_uart_handle_t *) x; - - if (!handle->have_start) { - if (bit) { - return; /* waiting for start bit (0) */ - } - handle->have_start = 1; - handle->data = 0; - handle->nbits = 0; - return; - } - - handle->data >>= 1; - handle->data |= 0x80 * !!bit; - handle->nbits++; - - if (handle->nbits == 8) { - handle->attr.bytehandler(handle->attr.bytehandler_arg, handle->data); - handle->nbits = 0; - handle->data = 0; - handle->have_start = 0; - } -/* might consider handling errors in the future... */ -} - -- 2.47.2