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 HcmV?d00001 literal 399483 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 z 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�&~09jn}FRe}M_3 z60B;sY+6>YTAnaRk*lE9DA^AHQBPESa4peikdj9Y=kXG(OK1}Yk^=v zSGLqdO-;R_DGnw_(M6pSK&=fswcOl{3P#(QOB9u(p)D(Gn;lNv5(`I?%mj`{oAI2Q zvJ_55b-ZltgpI0Kr^)xI*&r{LSWY7;PbXJKAU?IxmuAT=z;7O{FcI(|;LqRXZ<=V% z9LSnM&w!pd!5*c5GM$Aps&LaK+2MYD7QUig#qxF3%KV{;!nu(lYKvYI zEoKY<>e3nWq*2-eb7*aA)6%8#zodHp!A_QE%6Sd#$|D~?J~pD>qlqT ztHSEjQDsZ>0aWvY36dvxUlQjF*f%J=k4xU$I+%xxUVi_Mm#^EA60ChQ`|QYT9N_ zWKSC(6*mV?=R{dF4^{sAOM@@2hX>^(H+;dYbpB_|NGVS+Wvloqp+@Ri(Ftz~Qa=1{ zk}Wz`!>ayORZDP3S?V63a(d?eKtC3(*Ra4V)Ob>t6a9<0L_xu!bYL3~ZR9Mm>P2?0l>Z;QVS;JJ>0v6PC5q#cU3*}xT0Sh&@i?C4Ks}r)+67mQ<<} zxrFXblFm_G4;1D#uGDBXXra`qi~M7#niz3tqMgwZF(QmrpWDG@;J34aQ}_WMLVH#x24aEbp{Vw zbQF!9_8^2d$lfIk1>(dYNpPH&5XFe)_g6p{jp^PRr;d+a@jL&Mrt-R|>W+@y50i}) zZn&fNOm=dtOnv&fV)qn4rv3E$jYAZrfQ*8$kh2gSws`iZdV;q&Y5je}2%338JT<3# zYlkzSy&%O2$}%xOe?s5j72O#>CqloMXi$sm_9o!U++)J3>L4bH*O($7nHKZ}?pA=i zxZtnY(2zyx$e@rm=037!XL&_Mg_8T0%VyfL~`OGKhs-B0Cp@yanUq44Y`Mr{p>8F4n*p>MsH8#_`-Ww#jLS65NNWv|{5U zd&X&0M<{f9;fX5yI3c9NP$4r?{!~`_XB^4ax@RoOJX7;0r)a2#tP(P_i4wYHK}9^t z^*o!mzb5VQ)eq#^mh%Gf7q0xVQg_*dev8 zZT|a-U^`g0v)aVH#&=2N?8_p3DDgggD2cJnmu-V=(eb>tGLezikY<{MKb4`_gFRoC zm^=DNKD{e^JH1nMaeTEF_=z}geGizsf+rG8iGUY;epVD|;jN6ZuJNF5_cGIS^hh9Y z?=tgod^e~OY~khMZ1=K|b9|4kSZ=r%cYKe*%-?XyDA;hhiL&;wBA6TfXGA=1Vw(~} zhPNsNn4ZI)$URK&hIAG#^c57 zsxDHObxZZMOs*)?BAmqT`O}c2`&nJAzJ(&bi;;gDsf`SY7|N6rKb^wFw3L{hogSB- zl%67dk6{KKJKz4$c;1LaQZ=SK&Y&hWBnn!2WIhgJ6gb+Lm{dS!RVrHP0)7x;k~$J1F9p|DOokyy@mp6o1iG@JTq70 zka5$NQfH-WK-ZRculL}#8LwWCVUK3MBb6iaMrE|U2)jCsoINtFuXa(j zcujc~hoVrHLWp_|t1P2I*+pDSGPP#*HFvvynh&Ct+U-dBdQubRg-UY`SKD31 z?&5BzF8L@{B|Hz>rG^m*tQK?Paurt_g@cmGXX#r*%sGEqpIc?o*BpJ!S9RZF?3S)s z>Kt9io?mc0xQ;+=UYVZ4zybyY)>JM+)L+>Xi&1Or1=n0N?FH0_%(=#ryufCruEp9i zcDTe%u2whG`_kjhW4EcIsirBZsj4Z?^c)NCvbKWPs$<3}?kN@ZM(W_?hh#Zw1C2X% z<;KgN>o2&gThZ|K7V3~{nSJZ7>u%_)uAj01^~g`TyX{*0_f-g8SjUArqF2{Zp?Bw4 zY#r!b4&+EqaWc=Rz96|^&(eAS!P{*`f{KP|BmYM)k1vU5JkOwMuv{bTYi#lS9a5S9E>=v=yx z7)N@vTa>V5`5Lpk?(KS8XcE(TQ3i~KOO4kMvg-Tt`oum(QR%SdVEzt>x^_zVZ;V*N zJaR*N%#-CPapt-ginZxM_2r|QjE-xSP=B=;Fx(5+7URIHtd)4QY*;~qNaUUxEUlqb zOcW(pM58(~nFCKdvf_V)m{tw)QUNpa*D)Go5RG(e3{bc}zOSNtNI8W4G{SJVwU0F9 zUvj+p+eE@j>oLnTzdg{Sib4oGt?2J)CS#Y}L8v1NK4c?LBL?QyoRlQHStu4#dlH0> z0^|=%8UuvRs8|G$DyVZQ&92mT+Uw|;y$oK54-|EiThO_SG9BTP51j|YJv+~VgpLGJywg1^Oh8YO3R4#}KCf_zD#|4h*18SEW* z$wqmB5yC{a*%6oCoT*@wC`&Xqcx`VJ<|l2ESYsIC)sE?QCSO;<#nN) z$-PRW^#qh%j7`)=v#Z9%li$XQ)y<~f>TPc{w9I(6B5xX?(CxtP&~SBZy%|F$iy!$n zSC!X#V;AGyS5o@dLwd=^;BUeqm;iFXWV#7UU26REq~EO6T%p%7NWQSH$#u-W_u+fp zh1yjEM2^N==hthCGnn!+_{HbLp|N`(=Bl|lqH-GMSr3O7{-K@SKiU?-)uAku_Ev{~ z9iB9{F|*ch>}jU%kgf@m*t^6AVUZb9t`A%x8P5>?DT2{)XhrQ24;s38NX#K^f|CxE zcMW1BF7S8Ghbg~H+VHbYf(8Nw!oG5fX#?+1eXu`=^N;D);e5X@MY~=9zVM~SEVDFT z`WtG+Rzk-Q>UB5#5!#|dzFqb7-*?l@1X;%#H9f6qv$zu;dBdFsv{z0d|{jr5u*e!})ci6sCF7%J% zMaZ+Z-4LE$vO{W-M0${Usl@!BETe&*ETJHb_S8Z}N|Q9>wu*A_CRYfu;&6P@?k#pS@F@>a?+`=!Rqj4 zeJJc1-r??=^lIzk&BA?PyF$9ExzfI(>?-Xh+OoYe0qShogorbxg57uFL9*Jw@MhbRX=WievUrt}q=+XiBSBvnWcdX{I&vu3>0@U7}) z(d7gnpXY!(gYbf6L#+GdfY#)GD($9>enYu}o&tGCy>1WQv!;IkUXLN%32T1_d{6@5 zbJ1QfTVa0p6K4Zq9vK4y`>&%8!L+Y+WcJza zFz1hR8Vz)a6yOM$7_h-9nh5}roBei!Dg}nk1%2QHiT#c4ON1Zv6(fs};#;Cu@~mIt zqF?eH&)?5-`NVA)3ZM}i$=m^*?3L=3)kTj5hJg?U`s*i2z-J9^Pq%~KpP+Gz4IK$O z4B7(R*8A+or3*p_nF^!oOWv!fi>V7%49e)s=?9`qLI<4+I|+OZehl&q6x7?*%a!}P z7I?@PhYT2-k6ac!(V$A&H(MG-wF0{I*QPH700bVCrx*U0FGVh9DX_U8$EopuIt#~L z1*8nZ4^RzyT=~mEsh33Hnts~}i4Fw=%HX@#`&*YN7IG8Da1Xf?jExxC&cs*7S9{kY zj|>?yULz1KUIo;`x2cz7mwwl77cv(`72Xnv1tcTzek{X}x>s2js}^S!m7eExezaiaim~zf2G)R^g+OZ zP<){Qe{kiB7>iI}Idp$I0fa-???~`p^g!5uDQ1SSEu|LnHsU+tN9wDr%kA4#Y&qz_ z_+|~<46@;S)eG0i4cQ3kmuND3qPEMfiv|DzAnCHM`#@dtfBm;L01yET0H|X(loznO zcR$eBBc})6(2p8|4T3`-P&J>3JA?-htfL)*ov>z?INsn7Jl~%!AW%G@5kFpFt==3z zc)uPXQr{Tg1U^<p}m6BFNVNCxwx%|IiO-f)sM&#SmX; zb>P0gqZ2{&XM?hvzgHK?E(k*A?+ZrX1Q{9}mXj}TDB3X=LP{h6fhjJ*#qPeKNoO}rh6mqzGhx~xCw^=5#IPmuuk|asE)`w$ zW%3NzH82++PA&E$rEgMiLGOJp%`RADSLlh1Z;S5^h=^~C+&3qe4?H&5HZX^uOIQY; z5bkcoD9mQx^qo^-vX1mHrp_XzBCW74FJ-G71Iv?JD1SSTh$|zkKYU_cw)zxE(vPGU9GQI0vFmp z9+vPg>}nwzcO0AXE3mZ*h|W7I{0a}auOjY@A~6`J^q}0vwadV*?2olOLI9#{#SS(* zJCF9zjRm32Y?}S!#Q+Uqc8T$Unw|cW?o(T;7maaF zL_!4w>55RMCbyu-&10ZjLKuCT zV$BEr>AumZq=vK}b4lLR!0fS}=>=WmQor>Q-W=**tG0G#>G{Eqhb+*FnZYY`PFNe# z5<6wjzHL5j;VDb^g5$_SU>lLBSw5s$nAx3{TJV`4`^!X(*?VOJ{F;TTgkZ^?5$0l@ z+fnuXQ0_Fb8c1(Gpf-W%$Z19pG`vG%Ze@(q0ebganS+=M*}WFDbs=nJ zjr-4++X0^C=-UeG1a$-%@#O`&0rdgl0g(o2Rfx0RMF!COivIf}CJJx(j@SyM`HKeF z2cjF~3-|#<2Q-D?{eMqissk>3c=)?;QCib_DGv5ODR={E?M|)+vs#c`wxu`SIPGSx z2G5qm7OIe*H>V9Syz zvh6wUB6|l^g4oUs)0iIw#G0YV!ZYQbpoex`szSmtv+6TWVAx#8M_>_d{IaCjg8^~Zx4I2VIUx^ z+r?NPd}pL`#>7-qKl6Gs1l0?XT~U$iS`_I@So$UR|5n5&gOyF@Gc==9H2no$DB6!$ zNd2d)N}S(ce#kCNLeoCQj^9qxR%~gzVrob(K~BW-Uz)JKYLU@J+e}*aKN^*rnfH~O zn3V&M=~wTWw6vS&Pd6W)6Rhw^^p;^e3v4tmO+qZ%U>RbbA3p~`7E-rEzl-!sHRKNS zT!>AO%o0u@Cqei5ph^~d>HYh~$5(qy$Wi-D?@i@B=f$SV3G4D}lvBM|){gv1%c5N= z2fYHR@%f+x&eYPJ<`(Uv)i99ZbvtjXGWeE571hf4(pc_-4D7_h4k{1*=ar_U5Qi2D z$0y;*wo8e}O4hZOOS{X~StDH*YH@{RNl(SO>)M%>xiiYy17+62kYju5mv$XfL3-5} zuVHz5buOjlu8Em<^0CR8ZkFnoE?Z8{(W@FQ-UOfy22bL?4vr`J*dT4!V0aVF`Mw@b zJ9*Ct<3G^M^^*9sko}2qWil5qvv>aj(jBV(snefwi!$?BZt}R7gYymjh4LMoX`!>= zt@RG;i3Go^@zQ(&zt73T7<2Qcy)z(S{P>eJD5jBjSY|dR>ZR<0_x_c4#oGQ0FB)&S zMz*)+Rs+WUI<`4Z=<;rD@>h-)jlkpG`cWs#-vlFb9;9P)o(Nn| zxSSC*fY8If#0x{We@#AoQcH~9^BZhUXAl>v^x7whe8T|N`2F5_dP*a0NQFV2t(hgf zBwUL0r}8S@u=t{7{CD?_amv^$fCF9pv*1f2X+SFrVpkK zpBAmK5ss4#Pv6hcMNZCAn!hcY6;|PzDD<` zOh#V<9PGmFnx1gA=mZjuy`XTk=mh-Moq({nDh+SpQLyC4uT1pGP}=40rPTym25ElK z?c=u%JIv(3`-7-!?tw0o{mNREY0;4xyDQC4DK_|%jv9;`z$Ub9o(0;T{>a2^{tcq$ z`L;{jbA2tpx7dgZ`a-bF0hHpMl(0wBjaSsy^R9a319!E<&SSJqZ`AOn;+C2wg3f`O zR`#d&%B!zuLbA>LofO9x{|av){DE|(%N5Q2Bf?BO?c@Y|+RKO+?=5wU;bC&*W_+9m zgS~{X_1IufAngI=3&miI<^sWr;bFSu$IfQXg7=im2S+zTb%YNRJlj|D&aD+!=nei& z_szb?3y(KYdwc+cy{s_Y_$WUHJK0|dqr==I`&oN-)3%QV>TkpH*OL_Qd*dDhAb8HN zBpw^YJ6U1epSou3WYiEvN4bsIiOB);KLWnQCV0(WNvXdJk8&D65|Vv54s+mMN&kKu z9{#61eN4eJQr5)FL>?iQmDSc>%d68U+aUsbQ0yy@v z?r-z9-CT>*@JsSn1j^zNpXSNrwb zv`qA-X8EhAr_MrspNIHb;Rg_u5as?0$cdq-1&f!{Jgh#qMc1Sw;v2(Sxpy(CdAXYzD z;!m%~y^;z>%qcp!nU{K86tic0-f@cEn_rU}#zVDoxHP+5^rjAN4W=dmXX&h_CVNqA z$PISra3dLX5Ds>~bZSO0pErx6yR|xo7I24@xk9e?0E;36Q3@^l^oez_1uu+0@i|}q zc3cS7k-T_3S63bdEjLly-K_5K*N@9xa~jXXf?eIL7HIpfov?V0R{}3|Jo}ykFOIci zHDfE6DApBg5byfDopA34P;i5ak^&&)lFw1_P&sAnt5CT6sh}&90Aad@cAaEaO1Fmi z{|nTwS5{WD58p?RK(c|A?89V+HQ2ID_qF}l&jE;LFiL6V#8PW@IH>&ZY-V*SS>t3 z<)k&kKMj4c;cs$TLBUmCPs7V_j;03KiMCRIL0BR|##oH>o9xeoSM}(39N_F3Q*xvF zsOg|vODyWjr^-me<%qpR4sHY3A#(&E-NZ)~`p*S7*({O(?22(E;hy@z2Lq9u*bX== zAqI-^GLsISy&3QSMn>ERc(g6J5lP#gSVnAIJTa4Z9aVDzAH}GGn8j5y1d%GG_Hk-? z!Xj+xllQVrhl*6AUHaaLX+oGK8~3(aK~(lBG$WE);ckW=O+y|fRc8j@Z7G#ssVnNh zTlSnc5#Wg10p6c@y}Ylm7Io7%x5czj!-9RP`_eNSHQzLwRX2Z!Jr|o|_INDmj=yX* zYE3S;bJ?F>Yq_6vRU;n_=t9BjR@eBwE<1C(kD>c;_ip@&NX5#KN-A35p?naqvA1!s z^GUqDTG>5wv8H;4*`Pt}vKBc@NqllA@fK{jom z%SiX$$9r^0BWHh9!qd=&A>>R}JI%+|BK-c(0KOh{-wf)wMc53m-i)v*_2>zM0QhX- z@B%5=>N=Hpc8^}?I4i7jR!!W#*Rfcp3Og-$E;qj4iWx3d=qx=E)ZBEe<6%4-TnRs0 z&RaY4Ap}z<@T-b12fi9oZKfu^$9w3? ztdN9sjdk@~+W-9R+G6g#2AU7O_u>t!JhV+Fzp8O`Cy`Yv4i!%pBEzr}=twZCWr`n` z^xRjIxX3iq{}*j<0ToBntqaG1;1Dc$fFQvkxF%?D2rz@Y+u$z29TMC%*bF|nJHa6^ zxCD0#u5%~v`+dj$``>fVx%aNM=jq)~Rqd{xuGLkwOInCeCqwA%;#Y5<1|fcNxV#Uj zqm(_~JD($zZZ-#Zk9sM2ReuHn1 z#ut>^{FY-Lk&o*a**V7&?z}Q>>TsD`rD?y2N91fL@EHFHNW(~;MiKii&iu7gA%~o< z=uirD$t~v0Nf-1ptNv_e;7k{UWlqnALHS8OSfaq!)58E~@r3hxY5uf=Yy0^pg_C8jbccNj~ z!KqWB-Q`o6hT>K}4eTyJcjY~r+hYe1?-2~H@<556TzG^|RK&9bm$?40=X>S*O4C@B z!0wZe7TkOhuIa4^-(I>y@>cPycx2m!SKsjlpM8FQt?uq-CFmODHiNX<(qz(5b@U=5 z484kZc)G09R)fe+P5Nr)fSzX4B!79Q{RweWG-vgMz?{V=p1}br{y7GEQbb6GO+tLM zW3`In-(;~i&tCbX!nN#J6B_a2FAv^;yCIS8>M?;i^UMRN;-x129mar&c=ed_=5a}e zX#b5Q3vTV1KLA|37$N4 ze&zVfh0Hzd`8J<@%pc%I8FlzYhC;E{!H?DQ7sK|4ahYTUC3)FT3wIhe*d7PLe;cGM zU^y*d)Q{LNxGcJcEnqn;P}vFgjG!%+4v!3eOBe1LX=>CY;WCK9axx`^;$uD)qv2oi&dJ~ZhanFcc#QYfH`C}1b zR>W?)`|p25dsxMhte`^$G0&?<t*aN-{{i}}38U>ftYUuD|q@0eST3BEC(*BEGHes-&P z^8JY!MrQi{k3CN5-E{_GvV!z{XNLs6n4d!`oMg1|-~)*lYmIa~gc;wngq0G#J}T=A zS70B-j=1@{@$tKYG$6MueH2_~>^h`Og3GJ7a)$fg=j{)_cL&C=@uFPOy1sb-Y7C{H zR@v!!QfK68GYt>J_c7s2K;G@}&0*)f_=)FOX0BhMHK>DBS5Qq*+bhKjd!}t5rLm7})l+z@kw@R_ z`z3=h;g0ss{cE!Qd58I$OP1T18MlBlyi>r8;?Jy7VM+bKOSLhPkrdi;-Zkf$(ebPj z-3aJ;c9}5BcGL2A;jz|j>+}oVo#jZK_SY=sx_LfDb+8n<+M(#i;glg=eSf!R*WgRp zL-jtLvSX6%<4)O`^2s)!mk(b;6IIH$CJsJU7d(MLj}q;g+KpeK`dkUZ-->L`7u9A@_ySh8 z&wZ9}h{pHllWX*`wvZ@ems-zc7_}t~FRHSCybO#PN~n`Fg)-PouPDz3prSF|KSyI~ zkupT5V<`P#==4a5mVV}j54c9b2jo=p`$-!j{Y|7G&fwC)1au5Gqbn*JtCY$b{#{%5 z^v$JWIIff^@?P${k8@aYBIRM|58~FYr zvieMJ9{Ao_Due>u29i%Axa?XU)gS58g~@y890;o4Ss{=9=m_2sHZt0>jrTz3v}5)3 zo6U4Emm;oL=v#Wbo@BaM9ksx;?kfMILDgh2Kt4Tknbg&MK9$q42!Tc$H>4lc`h{DcyJZc5y00oK~7rhlzia zoK_#{Mh3p?;&JZE6W1^YCYg@sqRv4fY5bsMmgDiZG>-S2TXe)wX5%E&VLf7~u~=UQ zwK1W|ppKf?@o2(((?JEqULu9eLkX>%rZYkE{Hle_Kfdx4S6jPFCGKiT_mi!shE_+uL~q zKHG;ak%J_0BQb1h>AEHqtgb7ZV5{5~x#I22spUQXijfhg>$c-5UefZVyng*zgMWdWKz5EJYnXe2l3z#c*(PvO~J>h1OYyKb*wJh zA!tywS@B>?#tbCqDQ}(_>K*DQRD-r;Fh-y-h1qSgw+QaQ{HbMI3VW;t-cgxf z$lVuwuH7#646jePmJP3P{+*CPz^btt2V>D(Qe;YprilZf2Hc@#W}Q~$H33LW8r7b( zkQvR3h*7XUhIWkZ-^(>z&&}Brx*$ zb&f6N!4Rs?e#bQ8-WioV?E3CHW3K!_5i8}C+sr$k*zd#QRrp;SszWx%9gE7MsL7>Z ze#0@|l`!5~Tdyp0^xET7hZXvxJGvg9K5&hMgZ^Cb9^RD?pjhG3qFNSnf_3Vr1rbuDyS#RGcdowHmI7JCwg-q~lx>M_7fgwN*c#qB-&^w&r)K zRhfyiK(TPFc|L{sGZ<`X3u*_%6sD#>*v9wz#5NowZZu&=(jzlrM#2L#fmiY$xt9*s zRhxZxq|M-9d6JkW-_Tg?r}zz9`fjuNvJdoqbad}%z`zB5cVeHjhdvhCXmRZPJ~64p znKqF};UvtLkws~iZArdh)1tj5Tvia`>+q#vu@=~rDm$ds6epVwUj9~dTXB?F?l+=m z86wLoKg)C&=1SyxoH!bzmga#VwQHIyQ)IVQcWoG#*bOUcXy$ciTY&=U|C6}8&+#s0 zd6i~$QyPG`{T3C@Th@qkiDq;n39o|0rQp!KrQmR{0#d|bP;b|WQTINr^(W@UQ5Vw0 zpHoCuA&Y;qT2cKct9tcPW!2W%j{m$Jb)Vz*W7RszX0*r>XOYCw!k?IUm+u7gbc2`f z5}^7}rADfG_2L6n*215?6>~+4IERcn%5z1fx26SVgVMfpq=##FKRNy*byIHn%)T{nHpK?qU zSZmrVqBaDP@+uVGCoS*O9(7b| z@Dez6oi^p$*Q_IHMAffNRl1J@uE|jnt1$hrB0uJBRoPem24z}PByVmZL9d7AXH|R; zCqDYv_^-!5+}4K*8Wp7{zBfgTgf7n_&7+U>VfNWi&W_v)kgrtlugIg&PurkIa>sU= zPa|A#S?-@2V2hwlBc*hBnaJ+$?6)j$XFe;Ix;{mFZ+{1-41Is=iFYU~Br$Z4_($x= z+9P*>vo=@@NTIE}7M-0iCJnA~CTjI4JpwPjq2z|=Z~0B#$Nry?ked}PXtsXK4>r9G zA~vvx5MRkwcuwOMvCy_RqMvDPo#plzce$CvpM+NKEg20Bn4itvg60j<)SQiMe&ZVy zVsqA0*+U&A(vDTtv3_|R&Yf2BzI5)hwQJJ8IjLLB&&rz8Tv8y zjG_Ql1Lx_Ty^u;*cED}Vw7snn*D(EK6h{=w291)MF%e2*;7T7a% zg7(ktdK4P|xDDIHe*;RptV%m=8_3;q(A!jhKfk6g?G^CGq3jBEFn3pS6h7)&x_)`2 z67FJs+$)L#q=VD)vD{S5`-!ur#NTV#+y35 zbN>W;HS`+SH!3@alJsFYd(HfspJ#RDl=2$MH~i07#G2tf8qz&U`)SmQ5so;+n%lMT zEp_mz7z=w`#ie*I7WrUthM7jNXrt`X7Av`=G zh-QZ>5974#O%?bjD^?uKRUo{%ph!{G-ZQ#`@tbl~N0inYA89{YhnKT4qeQ zy&Q92EL|{f&*k`0NoMJioZt{W86z*5zplq7zwb0t#qgRj&2QPPWOc`(Pd4G8&!^DI zi_BbMCgzi>ry_MKZ3BIyymgIfPM$ZK-?F27SRKZWJesDiH~U)9lUE&$=K~t6n7(zw zj#{PeC`x-=8kTEaZBgt_bRiz4zx6+=pUuwCGS1BW;#oW@tDsG>X7MbOWb

sek&& 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

A2FNH`4p_vD^GO&KA%+ymsts1imY{pEW? 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�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 B{{rj9Ut>5gipmP+t-szd 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 Xrh%{C5`8>-+wU4rH;tpclose 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... */ -} -