From 57613192ccbf2a735d4afacfd63956aba5735457 Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Mon, 17 Jan 2011 15:24:55 -0800 Subject: [PATCH 01/43] Bump sounds file version to 1.0.14 --- build/sounds_version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/sounds_version.txt b/build/sounds_version.txt index cb0c481b13..20cb29cbd7 100644 --- a/build/sounds_version.txt +++ b/build/sounds_version.txt @@ -1,3 +1,3 @@ -en-us-callie 1.0.13 +en-us-callie 1.0.14 ru-RU-elena 1.0.12 From 017842c87fb8f7c93e486e00076ffdfd684d41fb Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 15 Feb 2011 09:45:14 -0600 Subject: [PATCH 02/43] FS-3056 --- src/mod/applications/mod_commands/mod_commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index 030cb8e867..517134d2e1 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -780,7 +780,7 @@ SWITCH_STANDARD_API(user_data_function) if ((domain = strchr(user, '@'))) { *domain++ = '\0'; } else { - if ((dup_domain = switch_core_get_variable("domain"))) { + if ((dup_domain = switch_core_get_variable_dup("domain"))) { domain = dup_domain; } else { domain = "cluecon.com"; From a411cea7b21c2b1094848c11ff9213b9b7d2b3b6 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 15 Feb 2011 16:34:09 -0500 Subject: [PATCH 03/43] freetdm: ftmod_r2 - check fclose return value when dumping IO --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 4265c9b8fa..540d7cb6e9 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -714,6 +714,7 @@ 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) { @@ -727,7 +728,10 @@ static void dump_mf(openr2_chan_t *r2chan) 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); - fclose(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)); } @@ -738,7 +742,10 @@ static void dump_mf(openr2_chan_t *r2chan) 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); - fclose(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)); } From c565501f555a507fa2c56eccedccdbba7a366d6d Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 15 Feb 2011 16:09:48 -0600 Subject: [PATCH 04/43] tell rtp stack about what remote payload type to expect when the receiving end follows the stupid SHOULD as WONT and sends a different dynamic payload number than the one in the offer --- src/include/switch_rtp.h | 2 + src/mod/endpoints/mod_sofia/mod_sofia.h | 2 + src/mod/endpoints/mod_sofia/sofia_glue.c | 71 ++++++++++++++++++++++-- src/switch_rtp.c | 12 ++-- 4 files changed, 78 insertions(+), 9 deletions(-) diff --git a/src/include/switch_rtp.h b/src/include/switch_rtp.h index 27dacc7c18..2870bba3af 100644 --- a/src/include/switch_rtp.h +++ b/src/include/switch_rtp.h @@ -437,6 +437,8 @@ SWITCH_DECLARE(void) switch_rtp_set_private(switch_rtp_t *rtp_session, void *pri */ SWITCH_DECLARE(void) switch_rtp_set_telephony_event(switch_rtp_t *rtp_session, switch_payload_t te); SWITCH_DECLARE(void) switch_rtp_set_telephony_recv_event(switch_rtp_t *rtp_session, switch_payload_t te); +SWITCH_DECLARE(void) switch_rtp_set_recv_pt(switch_rtp_t *rtp_session, switch_payload_t pt); + /*! \brief Set the payload type for comfort noise \param rtp_session the RTP session to modify diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 12148c0f1b..da92746319 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -587,6 +587,8 @@ struct private_object { sofia_private_t *sofia_private; uint8_t flags[TFLAG_MAX]; switch_payload_t agreed_pt; + switch_payload_t audio_recv_pt; + switch_payload_t video_recv_pt; switch_core_session_t *session; switch_channel_t *channel; switch_frame_t read_frame; diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index a0b7fca2ff..b2185a2f15 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -3234,6 +3234,11 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f switch_rtp_set_telephony_recv_event(tech_pvt->rtp_session, tech_pvt->recv_te); } + if (tech_pvt->audio_recv_pt != tech_pvt->agreed_pt) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_CRIT, "Set audio receive payload to %u\n", tech_pvt->audio_recv_pt); + switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->audio_recv_pt); + } + if (sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) || ((val = switch_channel_get_variable(tech_pvt->channel, "supress_cng")) && switch_true(val)) || ((val = switch_channel_get_variable(tech_pvt->channel, "suppress_cng")) && switch_true(val))) { @@ -3307,7 +3312,7 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f if ((rport = switch_channel_get_variable(tech_pvt->channel, "sip_remote_video_rtcp_port"))) { remote_rtcp_port = (switch_port_t)atoi(rport); } - + if (switch_rtp_set_remote_address (tech_pvt->video_rtp_session, tech_pvt->remote_sdp_video_ip, tech_pvt->remote_sdp_video_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) { @@ -3412,6 +3417,13 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f switch_rtp_set_ssrc(tech_pvt->video_rtp_session, ssrc_ul); } + + if (tech_pvt->video_recv_pt != tech_pvt->video_agreed_pt) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, + "Set video receive payload to %u\n", tech_pvt->video_recv_pt); + switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->video_recv_pt); + } + switch_channel_set_variable_printf(tech_pvt->channel, "sip_use_video_pt", "%d", tech_pvt->video_agreed_pt); tech_pvt->video_ssrc = switch_rtp_get_ssrc(tech_pvt->rtp_session); switch_channel_set_variable_printf(tech_pvt->channel, "rtp_use_video_ssrc", "%u", tech_pvt->ssrc); @@ -4038,6 +4050,24 @@ switch_t38_options_t *sofia_glue_extract_t38_options(switch_core_session_t *sess } +switch_status_t sofia_glue_get_offered_pt(private_object_t *tech_pvt, const switch_codec_implementation_t *mimp, switch_payload_t *pt) +{ + int i = 0; + + for (i = 0; i < tech_pvt->num_codecs; i++) { + const switch_codec_implementation_t *imp = tech_pvt->codecs[i]; + + if (!strcasecmp(imp->iananame, mimp->iananame)) { + *pt = tech_pvt->ianacodes[i]; + + return SWITCH_STATUS_SUCCESS; + } + } + + return SWITCH_STATUS_FALSE; +} + + uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_sdp) { uint8_t match = 0; @@ -4554,9 +4584,17 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_audio_port); switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip); switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp); - + tech_pvt->audio_recv_pt = map->rm_pt; + + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { + sofia_glue_get_offered_pt(tech_pvt, mimp, &tech_pvt->audio_recv_pt); + } + + switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->audio_recv_pt); + switch_channel_set_variable(tech_pvt->channel, "sip_audio_recv_pt", tmp); + } - + if (match) { if (sofia_glue_tech_set_codec(tech_pvt, 1) == SWITCH_STATUS_SUCCESS) { got_audio = 1; @@ -4583,7 +4621,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s } } - + if (!match && greedy && mine < tech_pvt->num_codecs) { mine++; skip = 0; @@ -4665,6 +4703,16 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->video_agreed_pt); switch_channel_set_variable(tech_pvt->channel, "sip_video_pt", tmp); sofia_glue_check_video_codecs(tech_pvt); + + tech_pvt->video_recv_pt = map->rm_pt; + + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { + sofia_glue_get_offered_pt(tech_pvt, mimp, &tech_pvt->video_recv_pt); + } + + switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->video_recv_pt); + switch_channel_set_variable(tech_pvt->channel, "sip_video_recv_pt", tmp); + break; } else { vmatch = 0; @@ -5164,7 +5212,7 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName if ((tmp = switch_channel_get_variable(channel, "sip_use_pt"))) { tech_pvt->pt = tech_pvt->agreed_pt = (switch_payload_t)atoi(tmp); } - + sofia_glue_tech_set_codec(tech_pvt, 1); tech_pvt->adv_sdp_audio_ip = tech_pvt->extrtpip = (char *) ip; @@ -5219,6 +5267,19 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName switch_xml_free(xml); return 0; } + + if (switch_rtp_ready(tech_pvt->rtp_session)) { + if ((tmp = switch_channel_get_variable(channel, "sip_audio_recv_pt"))) { + switch_rtp_set_recv_pt(tech_pvt->rtp_session, atoi(tmp)); + } + } + + if (switch_rtp_ready(tech_pvt->video_rtp_session)) { + if ((tmp = switch_channel_get_variable(channel, "sip_video_recv_pt"))) { + switch_rtp_set_recv_pt(tech_pvt->rtp_session, atoi(tmp)); + } + } + } if (switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE)) { diff --git a/src/switch_rtp.c b/src/switch_rtp.c index faa79e35a2..ffc41a73c6 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -1578,7 +1578,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session rtp_session->recv_msg.header.cc = 0; rtp_session->payload = payload; - + rtp_session->rpayload = payload; rtp_session->rtcp_send_msg.header.version = 2; rtp_session->rtcp_send_msg.header.p = 0; @@ -1773,6 +1773,12 @@ SWITCH_DECLARE(void) switch_rtp_set_telephony_recv_event(switch_rtp_t *rtp_sessi } } +SWITCH_DECLARE(void) switch_rtp_set_recv_pt(switch_rtp_t *rtp_session, switch_payload_t pt) +{ + rtp_session->rpayload = pt; +} + + SWITCH_DECLARE(void) switch_rtp_set_cng_pt(switch_rtp_t *rtp_session, switch_payload_t pt) { rtp_session->cng_pt = pt; @@ -2813,7 +2819,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ rtp_session->recv_msg.header.pt != 13 && rtp_session->recv_msg.header.pt != rtp_session->recv_te && (!rtp_session->cng_pt || rtp_session->recv_msg.header.pt != rtp_session->cng_pt) && - rtp_session->recv_msg.header.pt != rtp_session->payload) { + rtp_session->recv_msg.header.pt != rtp_session->rpayload) { /* drop frames of incorrect payload number and return CNG frame instead */ return_cng_frame(); } @@ -3131,8 +3137,6 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ rtp_session->recv_msg.header.pt = 97; } - rtp_session->rpayload = (switch_payload_t) rtp_session->recv_msg.header.pt; - break; do_continue: From b7fd81de33a28c95cb935cc57429081b6c5a5f41 Mon Sep 17 00:00:00 2001 From: Brian West Date: Tue, 15 Feb 2011 16:30:57 -0600 Subject: [PATCH 05/43] rip off the fs_ args on message like we do in SEND_MESSAGE --- src/mod/endpoints/mod_sofia/sofia_presence.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 2313cb7a1a..3755894cb8 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -80,6 +80,7 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co char *ffrom = NULL; nua_handle_t *msg_nh; char *contact = NULL; + char *p; char *dup = NULL; switch_status_t status = SWITCH_STATUS_FALSE; const char *ct = "text/html"; @@ -239,8 +240,12 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co status = SWITCH_STATUS_SUCCESS; - /* if this cries, add contact here too, change the 1 to 0 and omit the safe_free */ + if ((p = strstr(contact, ";fs_"))) { + *p = '\0'; + } + /* if this cries, add contact here too, change the 1 to 0 and omit the safe_free */ + msg_nh = nua_handle(profile->nua, NULL, TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), From 4f93ea25ece53df029e6dc6c913ad7c190df22d5 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 15 Feb 2011 17:43:13 -0600 Subject: [PATCH 06/43] allow uuid bridge on unaswered channels as long as there is media available on at least one --- src/switch_ivr_bridge.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index 6f84de3893..f130625a75 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -1398,8 +1398,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_uuid_bridge(const char *originator_uu return SWITCH_STATUS_FALSE; } - if (!switch_channel_test_flag(originator_channel, CF_ANSWERED)) { - if (switch_channel_test_flag(originatee_channel, CF_ANSWERED)) { + //if (!switch_channel_test_flag(originator_channel, CF_ANSWERED)) { + if (!switch_channel_media_ready(originator_channel)) { + if (switch_channel_media_ready(originatee_channel)) { + //if (switch_channel_test_flag(originatee_channel, CF_ANSWERED)) { swap_session = originator_session; originator_session = originatee_session; originatee_session = swap_session; From 713b82d52f0432044d210ef6050418e285abf213 Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Tue, 15 Feb 2011 16:20:50 -0800 Subject: [PATCH 07/43] Update ChangeLog through Feb 1 --- docs/ChangeLog | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/docs/ChangeLog b/docs/ChangeLog index 41f94d78ab..356cbdc852 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -35,6 +35,7 @@ freeswitch (1.0.7) config: Disallow global-intercept and group-intercept can intercept an outbound call in default dialplan (r:890871ba/FS-2777) config: fix single domain assumption in default config to be more portable *cough* bkw *cough* (r:f987903e) config: Bump Doxygen.conf version to 1.0.6... belatedly (r:cfeae1ba) + config: docs for acl (r:57b410eb) core: Add RTCP support (FSRTP-14) core: handle some errors on missing db handle conditions core: add ... and shutdown as a fail-safe when no modules are loaded @@ -164,6 +165,24 @@ freeswitch (1.0.7) core: drop rtp frame that was already replaced with a cng frame (r:34a0ca50) core: fix partial match counting as exact match in dmachine (r:5eb951aa) core: try to adjust the timer to be ok with the horrible 10000 microsecond kernel resolution on amazon ec3 but that doesn't mean it's not horribly wrong to run the kernel that slow (r:903b2901) + core: make exact matches return sooner in dmachine (r:e897646e) + core: don't let inherit_codec work when we have ep_codec_string set and the B-leg codec is not in that list since it will lead to failure (r:f79f9766) + core: set maximum query run time to 30 seconds at least on drivers that support SQL_ATTR_QUERY_TIMEOUT (r:5bb525e1) + core: dd switch_cache_db_affected_rows() to switch_core_sqldb (and switch_odbc) and expose it through Lua dbh:affected_rows() (r:d79cf484/FS-2962) + core: add bind meta on A-D and refactor (r:27869d7a) + core: add temp_hold_music var that is only valid until you transfer the call and finishing touches on bind meta to A-D (r:b262f44c) + core: add function to help set session read codec to slinear (r:1a08df9b) + core: add rtp_bug IGNORE_DTMF_DURATION to speed up dtmf detection of RFC2833 on strange carriers (r:b3fc001e) + core: Fix crash when re-connecting to non-working database server (r:29daaa07/FS-2960) + core: treat EINTR returns as a BREAK (now mapped to SWITCH_STATUS_INTR), we appriciate the interrupted syscalls but we would like to continue working properly (r:316963c5) + core: eat rtp frames with the wrong payload type number (r:fe1711fd) + core: up assert vaule on header loop detection to 1 meeeeelyonne for hmmhesegs (r:d9c56345) + core: Fix race condition in originate where USER_BUSY is reported as a no answer (r:cc06fdb5/FS-2992) + core: Allow check ip change to be optional (r:1cf79386/FS-2917) + core: handle 2833 in do_flush instead of dropping valid dtmf (r:3fa3e11c/FS-3002) + core: add record_restart_time_limit_on_dtmf var (r:7a1dcb69) + core: fix unreachable condition with a null args to make any key stop playback/record etc without dequing and remove hard-coded flush digits in play_and_get_digits be sure to flush it yourself before using (r:976859bb) + core: Fix a lock on reloadxml when stderr write is blocked. Also remove an error parsing print since reason generated were wrong and duplicate. (r:2d6161e8) embedded languages: Provide core level support for conditional Set Global Variable (r:c017c24b/FSCORE-612) embedded languages: add insertFile front end to switch_ivr_insert_file and reswig (r:c4e350ab) lang: Improve French phrase files (FSCONFIG-23) @@ -188,11 +207,14 @@ freeswitch (1.0.7) libesl: Make last_event pointer last longer (r:a15f51d5/ESL-37) libesl: use a packet buffer for ESL (r:2081bf97) libesl: Noevent/Noevents disparity (r:d29d83d7/ESL-53) + libesl: FS-2957 esl lib on windows fails to build (r:5254df04/FS-2957) + libesl: Small fix on ESL that cause event_id to be set wrong on headers that had value failure. (r:eb88304a) libfreetdm: implemented freetdm config nodes and ss7 initial configuration libfreetdm: fix codec for CAS signaling (r:b76e7f18) libfreetdm: freetdm: ss7- added support for incoming group blocks, started adding support for ansi (r:c219a73c) libg7221: A bunch of tweaks to the G.722.1 codec (r:5d548570) libgnutls: link to libgcrypt as well, please report any platforms this breaks, but it should be portable (r:c569fb0f/FS-1248) + libjs: non-portable comment syntax in .s files libopenzap: Add CLI tracing libs: Merged OpenZAP and FreeTDM into the FreeSWITCH tree. libs: Add support for TLS on Windows using openssl (r:1abe3b93/MODSOFIA-92) @@ -207,6 +229,7 @@ freeswitch (1.0.7) libspandsp: Fix Windows build after libspandsp update (r:d70cc852/FSBUILD-293) libspandsp: Fix for T.30 processing of operator interrupts, to improve compatibility with some machines, which seem to send them when no operator is around. (r:84ee0ae6) libspandsp: spandsp t38 fax receiving error in win XP - regression from f029f7ef (r:761cec8f/FS-2766) + libspandsp: Added missing error codes when an ECM FAX is abandoned with the T30_ERR message (r:ec57dc7a) mod_avmd: Initial check in - Advanced Voicemail Detect (r:10c6a30a) (by Eric Des Courtis) mod_avmd: Add to windows build (r:df4bd935) mod_avmd: Fix mem leak (r:cd951384/FS-2839) @@ -229,8 +252,12 @@ freeswitch (1.0.7) mod_callcenter: Fix bad return type so it compile on archlinux, thx bougyman (r:3a475986) mod_callcenter: Make callcenter_config agent get return the value of the item requested. Also added queue param max-wait-time-with-no-agent-time-reached: If the max-wai-time-with-no-agent is already reached for the queue, then new caller can wait for x amount of second before it kicked out of the queue rather than get rejected automatically. (r:81a03869) mod_callcenter: Add new event socket agent-offering. Plus some documentation and better handling of bad agent type -- FS-2869 (r:80174cf3/FS-2869) + mod_callcenter: Add error response for queue load and queue reload (FS-2988) (r:49a5effc/FS-2988) mod_cdr_sqlite: initial commit (r:f625fe3b) mod_cdr_sqlite: config file for mod_cdr_sqlite (r:25bc8fe3) + mod_cdr_sqlite: Drop transaction BEGIN/END around INSERT. We're only executing one command, and autocommit will automatically rollback if the INSERT fails. Sync state_handlers with mod_cdr_csv. Minor libpq fixups. (r:0f95b870) + mod_celt: Bump celt to 0.10.0 (r:231fbe5e) + mod_celt: update code in mod_celt to match API of 0.10.0 (r:6e4c30ea) mod_cidlookup: null xml is bad (r:095815f8) mod_cid_lookup: honor skipcitystate when using whitepages (r:a66654de/FSMOD-53) mod_commands: make break uuid_break and add cascade flag @@ -252,6 +279,7 @@ freeswitch (1.0.7) mod_commands: Dramatic jitterbuffer changes (r:d5470961) mod_commands: add uuid_buglist to fetch the current media-bugs attached to a given session uuid (r:f6eab64c) mod_commands: add recovery_refresh app and api and use it in mod_conference to send a message to the channel telling it to sync its recovery snapshot (r:650393fb) + mod_commands: add moh by default to uuid_broadcast when only broadcasting to A leg use aleg arg to disable this (r:d164a797) mod_conference: Fix reporting of volume up/down (MODAPP-419) mod_conference: add last talking time per member to conference xml list mod_conference: add terminate-on-silence conference param @@ -265,6 +293,10 @@ freeswitch (1.0.7) mod_conference: Add a chan var conference_enter_sound to override conference enter-sound param on the profile (r:651acc62) mod_conference: Add an unique id to the conference obj so that we can track conferences. (r:479f3de2) mod_conference: Fix corrupted audio when playing "you are now (un)muted..." (r:10257c7d/FS-2768) + mod_conference: clear last_transferred conference when you exit the conference app (r:fb017a52) + mod_conference: Add energy level to conference_add_event_member_data (r:8d6d52e0) + mod_conference: if more digits than the length of the correct pin the remaining digits are accounted for next retry (r:b88cd345/FS-3000) + mod_conference: Fix unexpected behavior with endconf and auto-outcalls and pre_answer (r:6f58e6aa/FS-2771) mod_curl: use method=post when post requested (r:c6a4ddd0/FSMOD-69) mod_db: fix stack corruption (MODAPP-407) mod_dialplan_xml: Add in the INFO log the caller id number when processing a request (Currenly only show the caller name) (r:e1df5e13) @@ -282,12 +314,16 @@ freeswitch (1.0.7) mod_dptools: refactor export code and add new bridge_export app which is like export but exports across when one channel bridges another (r:4aa9a838) mod_dptools: add bind_digit_action application (r:9537197b) mod_dptools: emit event when user presses DTMFs (r:37298f56) + mod_dptools: Log error when there's no IVR menus configured when you call 'ivr' DP app (r:30034891) + mod_easyroute: Fix possible segfaults and memory leak during unload, and add new setting odbc-retries (r:7fbc47f8/FS-2973) mod_erlang_event: Make XML fetch reply ACKs distinguishable, update freeswitch.erl (r:9d44ed04) mod_erlang_event: Add 3 new commands; session_event, session_noevents, session_nixevent (r:698fa045) mod_erlang_event: generate long node names the same as erlang does (r:9ad509c2) mod_erlang_event: Improve some logging to include UUIDs (r:c0d51b83) mod_erlang_event: Support for reading erlang cookie from a file (r:094ffe37) mod_erlang_event: Rewrite XML fetch conditional wait to be more sane (Reported by James Aimonetti) (r:6941c6eb/FS-2775) + mod_erlang_event: Don't urlencode events (and destroy an event after use) (r:4eccdfef) + mod_erlang_event Add proper locking for the list of XML bindings (r:9fe440b2) mod_event_socket: fix up other users of switch_event_xmlize() to use SWITCH_EVENT_NONE (r:d6eb7562) mod_event_socket: Fix small mem leaks (r:e4f90584/MODEVENT-68) mod_event_socket: Add "-ERR" to api cmd response when failure occurs (r:58759052/FS-2827) @@ -301,6 +337,8 @@ freeswitch (1.0.7) mod_fifo: add outbound_ring_timeout param to mod_fifo (r:3885eea7) mod_fifo: add default_lag to fifo (r:dd4fb5be) mod_fifo: Fix crash when using fifo_destroy_after_use (r:ee562c82/FS-2879) + mod_fifo: don't seg in edge case error conditions (r:9ee13b72) + mod_fifo: set tracking data before enabling hooks (r:34267869) mod_freetdm: Fix for TON and NPI not passed through to channel variables on incoming calls mod_freetdm: add pvt data to freetdm channels fix fxs features (r:9d456900) mod_freetdm: export and import boost custom data (r:edb2d582) @@ -334,6 +372,7 @@ freeswitch (1.0.7) mod_freetdm: created cmake files for freetdm (r:fc55997b) mod_freetdm: ss7 - added support to control mtp2, mtp3, and isup timers via freetdm.conf.xml (r:4455d581) mod_freetdm: made ftmod_r2 use FTDM_SPAN_USE_SIGNALS_QUEUE and properly send FTDM_SIGEVENT_SIGSTATUS_CHANGED (r:af5f0a4a) + mod_fsk: add mod_fsk (r:fcc912a9) mod_gsmopen: copy from branch mod_gsmopen: fix FS-2793, compilation stops (r:355c0dbb/FS-2793) mod_gsmopen: retry serial initialization if failed, zeroing audio buffers, slower retry on soundcard busy (EAGAIN) (r:c7aefe93) @@ -351,6 +390,7 @@ freeswitch (1.0.7) mod_hash: use 5 seconds connection timeouts for remote connections (r:7431fbe9) mod_hash: use esl_recv_timed with a 5000ms timeout when doing api commands (r:27d8378f) mod_hash: limit_remote_thread sending invalid handle to esl_connect_timeout causing core (r:6cdd3e2a/MODAPP-446) + mod_hash: avoid scheduler caling a function on null hash during shutdown (r:8458adeb) mod_h323: initial t.38 support. remake logical channel opening. add missing param name in example config. (r:8c58074c) mod_h323: some t.38 and lockinng improvements. replace ptrace with switch_log_printf. (r:5efe5c88) mod_h323: add missing conf prameter (r:0b353d7a) @@ -379,6 +419,8 @@ freeswitch (1.0.7) mod_lua: Made 2nd arg to freeswitch.Dbh:query (cb func) optional (r:87db11af) mod_lua: Added SAF_ROUTING_EXEC flag to lua app, so it can be run inline (r:7d5ca1c0) mod_lua: spelling error in -ERR return code encounterd -> encountered (r:86e7cdc5/FS-2949) + mod_lua: Make dbh:connected accessible from Lua - thanks Grmt (r:09e6fd3f) + mod_lua: Added optional core: prefix to first arg passed to freeswitch.Dbh for giving direct access to sqlite db (r:a0181479) mod_managed: Added wrapper for switch_event_bind for .net (r:a5f07a80/MODLANG-165) mod_managed: add additional support (r:5be58aac) mod_managed: add mono 2.8 patch file see FS-2774 (r:6a948bd9/FS-2774) @@ -442,6 +484,7 @@ freeswitch (1.0.7) mod_snapshot: fix bad codepaths in mod_snapshot (r:844ac220) mod_sndfile: Add support for .alaw and .ulaw to mod_sndfile (r:facf09b8/MODFORM-41) mod_sndfile: return break in mod_sndfile when seek returns failure (r:564dc7e4) + mod_snmp: initial checkin of mod_snmp (r:6e2b1bd3) mod_sofia: Send SIP MESSAGE to unregistered users by prefixing sip: to user@domain mod_sofia: fix callee being updated with callee information mod_sofia: set appearance-index in update statement for SLA @@ -548,6 +591,20 @@ freeswitch (1.0.7) mod_sofia: improve fail2ban logging (r:f4d52d4c/FS-2943) mod_sofia: refactor sofia_contact to try the profile_name first then the domain to resolve the profile then fall back to querying every profile to reduce confusion with multi-homers (d'oh) also special profile name * will force a search-all situation (r:81608da0) mod_sofia: support allowing pidf-ful presence clients to share the same account and 'appear offline' without influencing each other =/ also refactor the contact generation string based on nat into a helper function (r:97a68c50) + mod_sofia: gateway not identified when extension-in-contact is set (r:7b289941/FS-502) + mod_sofia: Fix erroneous error log on SQL statement (r:2c595a6c/FS-2961) + mod_sofia: Fix routing behavior of inbound calls from gateways that only match gateway based on the gw request uri param (r:0132cd3f) + mod_sofia: don't say we are not for polycom phones (safe rport) when its not really nat (r:9462f53c) + mod_sofia: Set route header as a var on channel like Diversion header (r:d41e6498) + mod_sofia: fix seg related to ptime mismatch + CNG + PLC (if you ever get purple ptime mismatch warnings you want this patch) (r:54de293b) + mod_sofia: be more iOS friendly when using TCP or TLS because the phone never sleeps thus drains the battery (r:159ae989) + mod_sofia: add send-presence-on-register (true|false|first-only) param to sofia and api command sofia global debug [presence|sla|none] + mod_sofia: disable media timeout when encountering a recvonly stream (r:029d68ce) + mod_sofia: fix sofia flush_inbound_reg to work when @domain is given (r:68bf642c) + mod_sofia: fix session timer failure when freeswitch is generating the sdp and there are enough dynamic codecs enabled to conflict with the 2833 pt (4 by default) (r:018a3800) + mod_sofia: Places ;fs_path= within the contact string <...> when using NDLB-connectile-dysfunction-2.0, instead of just appending to the end of the contact string. (r:afc02747/FS-2989) + mod_sofia: Fix handling SUBSCRIBE to "park+" fifo, the NOTIFY data was not being generated from mod_fifo data. (r:3dd9d5c0/FS-3007) + mod_sofia: fsctl pause improvements (r:008e527c/FS-3012) mod_spandsp: initial checkin of mod_fax/mod_voipcodecs merge into mod_spandsp (r:fa9a59a8) mod_spandsp: rework of new mod_spandsp to have functions broken up into different c files (r:65400642) mod_spandsp: improve duplicate digit detection and add 'min_dup_digit_spacing_ms' channel variable for use with the dtmf detector (r:eab4f246/FSMOD-45) @@ -559,6 +616,7 @@ freeswitch (1.0.7) mod_spandsp: deadlock in mod_spandsp (mod_spandsp_fax.c) (r:b02c69bb/FS-1690) mod_spandsp: T.38 reINVITE glare condition causes FAX processing to stop. (r:04aa7ef9/FS-1682) mod_spandsp: improve nat handling when using stun or host as ext-rtp-ip (r:03e74c51/FS-526) + mod_spandsp: Fire event when fax is finished; indicates result of fax attempt (r:314a2a1e/FS-3004) mod_spidermonkey: allow vars to be set containing vars from languages (r:5cd072a3) mod_spidermonkey: fix seg in js hangup (r:7d554c11) mod_spidermonkey: Fix mod_spidermonkey build on FreeBSD, (Undefined symbol PR_LocalTimeParameters). (r:3edb8419) @@ -579,10 +637,14 @@ freeswitch (1.0.7) mod_voicemail: add quotes to vm_cc command generated internally to escape spaces in the caller id name (r:5f012813) mod_voicemail: Play caller id of callee prior to playing a vmail (r:e7b97907/FS-2719) mod_voicemail: FS-1776 Add support for per user operator exten override param vm-operator-extension (r:df5b3498/FS-1776) + mod_voicemail: Set email address from within directory (r:83ce26b2/FS-2972) + mod_voicemail: add events for record/change greeting and record name (r:54421f59) + mod_voicemail: let vmain-key and operator-key be set empty (r:de49305a) mod_xml_cdr: add force_process_cdr var to process b leg cdr on a case by case basis when b leg cdr is disabled (XML-17) mod_xml_cdr: add leg param to query string (XML-24) mod_xml_cdr: fix locked sessions (XML-26) mod_xml_cdr: fix minor memory leaks and config bug (r:19253d83/MODEVENT-62) + mod_xml_cdr: Fix prefix-a-leg not respected for url submission (r:ea9021a2/FS-2998) mod_xml_rpc: Fix crash if unauthorized XML RPC is attempted (r:9835395c/FS-184) scripts: added honeypot.pl and blacklist.pl which add extra SIP security options (r:b6a81ba7) scripts: do simple verification to make sure we are getting IP addresses from VoIP abuse blacklist (r:b0049160) From 722b2ce16807e77228f7698275a177af9901ad61 Mon Sep 17 00:00:00 2001 From: Brian West Date: Tue, 15 Feb 2011 19:01:31 -0600 Subject: [PATCH 08/43] FS-3041 --- conf/autoload_configs/modules.conf.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/conf/autoload_configs/modules.conf.xml b/conf/autoload_configs/modules.conf.xml index 8b4a4e7ea4..0e485b24e3 100644 --- a/conf/autoload_configs/modules.conf.xml +++ b/conf/autoload_configs/modules.conf.xml @@ -52,6 +52,7 @@ + From 5f2857b8b8e2d426f9b442e5afb9a26997635330 Mon Sep 17 00:00:00 2001 From: Brian West Date: Wed, 16 Feb 2011 08:36:40 -0600 Subject: [PATCH 09/43] use the correct URI on endpoints behind nat --- src/mod/endpoints/mod_sofia/sofia_presence.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 3755894cb8..df472f2f56 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -190,16 +190,8 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co dup_dest = strdup(dst->contact); - if (switch_stristr("fs_path", dst->contact)) { - const char *s; - - if ((s = switch_stristr("fs_path=", dst->contact))) { - s += 8; - } - if (s) { - remote_host = strdup(s); - switch_url_decode(remote_host); - } + if (dst->route_uri) { + remote_host = strdup(dst->route_uri); if (!zstr(remote_host)) { switch_split_user_domain(remote_host, NULL, &remote_ip); } From de707ab7f158a56e09ebab1ef835ad7fe6686c3b Mon Sep 17 00:00:00 2001 From: Brian West Date: Wed, 16 Feb 2011 08:45:17 -0600 Subject: [PATCH 10/43] comment out --- src/mod/endpoints/mod_sofia/sofia_presence.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index df472f2f56..a8d3b84b0a 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -232,9 +232,11 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co status = SWITCH_STATUS_SUCCESS; + /* if ((p = strstr(contact, ";fs_"))) { *p = '\0'; } + */ /* if this cries, add contact here too, change the 1 to 0 and omit the safe_free */ From 0d8e945bd1588650051dca407e6e3e3ff90698e9 Mon Sep 17 00:00:00 2001 From: Brian West Date: Wed, 16 Feb 2011 08:57:43 -0600 Subject: [PATCH 11/43] doh --- src/mod/endpoints/mod_sofia/sofia_presence.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index a8d3b84b0a..89eb1ae948 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -80,7 +80,6 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co char *ffrom = NULL; nua_handle_t *msg_nh; char *contact = NULL; - char *p; char *dup = NULL; switch_status_t status = SWITCH_STATUS_FALSE; const char *ct = "text/html"; From d4068d9755fb65d4a2f21b983cc882fbc7c8b0b1 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Wed, 16 Feb 2011 11:06:26 -0500 Subject: [PATCH 12/43] freetdm: Removed ftmod_sangoma_boost --- libs/freetdm/Makefile.am | 21 - libs/freetdm/configure.ac | 3 +- .../ftmod_sangoma_boost/BOOST.limitations | 20 - .../ftmod/ftmod_sangoma_boost/boost-tasks.txt | 146 - .../ftmod_sangoma_boost/ftdm_sangoma_boost.h | 75 - .../ftmod_sangoma_boost.2008.vcproj | 373 --- .../ftmod_sangoma_boost.2010.vcxproj | 206 -- .../ftmod_sangoma_boost.2010.vcxproj.filters | 35 - .../ftmod_sangoma_boost/ftmod_sangoma_boost.c | 2730 ----------------- .../sangoma_boost_client.c | 589 ---- .../sangoma_boost_client.h | 164 - .../sangoma_boost_interface.h | 254 -- .../src/ftmod/ftmod_sangoma_boost/sigboost.h | 221 -- 13 files changed, 1 insertion(+), 4836 deletions(-) delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_boost/BOOST.limitations delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_boost/boost-tasks.txt delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftdm_sangoma_boost.h delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2008.vcproj delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj.filters delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_boost/sangoma_boost_client.c delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_boost/sangoma_boost_client.h delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_boost/sangoma_boost_interface.h delete mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_boost/sigboost.h diff --git a/libs/freetdm/Makefile.am b/libs/freetdm/Makefile.am index b3353f32de..a26035b2ef 100644 --- a/libs/freetdm/Makefile.am +++ b/libs/freetdm/Makefile.am @@ -39,7 +39,6 @@ libdir = @libdir@ library_includedir = $(prefix)/include INCS = -I$(FT_SRCDIR)/$(SRC)/include -I$(FT_SRCDIR)/$(SRC)/include/private -INCS += -I$(FT_SRCDIR)/$(SRC)/ftmod/ftmod_sangoma_boost if HAVE_SNG_SS7 INCS += -I/usr/include/sng_ss7 @@ -109,7 +108,6 @@ core-install: install-libLTLIBRARIES # tools & test programs # noinst_PROGRAMS = testtones detect_tones detect_dtmf testpri testr2 testanalog testapp testcid -noinst_PROGRAMS += testsangomaboost testapp_SOURCES = $(SRC)/testapp.c testapp_LDADD = libfreetdm.la @@ -143,17 +141,6 @@ testr2_SOURCES = $(SRC)/testr2.c testr2_LDADD = libfreetdm.la testr2_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) -if HAVE_SCTP -noinst_PROGRAMS += testboost -testboost_SOURCES = $(SRC)/testboost.c -testboost_LDADD = libfreetdm.la -testboost_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) -endif - -testsangomaboost_SOURCES = $(SRC)/testsangomaboost.c -testsangomaboost_LDADD = libfreetdm.la -testsangomaboost_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) - testanalog_SOURCES = $(SRC)/testanalog.c testanalog_LDADD = libfreetdm.la testanalog_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) @@ -201,14 +188,6 @@ ftmod_isdn_la_LDFLAGS = -shared -module -avoid-version $(LIBISDN_LDFLAGS) $(PCA ftmod_isdn_la_LIBADD = libfreetdm.la $(LIBISDN_LIBS) $(PCAP_LIBS) endif -if HAVE_SCTP -mod_LTLIBRARIES += ftmod_sangoma_boost.la -ftmod_sangoma_boost_la_SOURCES = $(SRC)/ftmod/ftmod_sangoma_boost/sangoma_boost_client.c $(SRC)/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c -ftmod_sangoma_boost_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) -ftmod_sangoma_boost_la_LDFLAGS = -shared -module -avoid-version -ftmod_sangoma_boost_la_LIBADD = libfreetdm.la -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 diff --git a/libs/freetdm/configure.ac b/libs/freetdm/configure.ac index 1f4fc9c6ac..38f849b9e6 100644 --- a/libs/freetdm/configure.ac +++ b/libs/freetdm/configure.ac @@ -121,8 +121,7 @@ AC_CHECK_LIB([dl], [dlopen]) AC_CHECK_LIB([pthread], [pthread_create]) AC_CHECK_LIB([m], [cos]) -AC_CHECK_HEADERS([netinet/sctp.h netdb.h sys/select.h]) -AM_CONDITIONAL([HAVE_SCTP],[test "${ac_cv_header_netinet_sctp_h}" = "yes"]) +AC_CHECK_HEADERS([netdb.h sys/select.h]) AC_CHECK_FUNC([gethostbyname_r], [], [AC_CHECK_LIB([nsl], [gethostbyname_r])] diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/BOOST.limitations b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/BOOST.limitations deleted file mode 100644 index 663b7d376a..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/BOOST.limitations +++ /dev/null @@ -1,20 +0,0 @@ -== Boost sigmod current limitations == -- we don't support having openzap spans with physical channels - belonging to other physical spans. this is due to netborder sangoma abstraction, therefore - any openzap span using sigboost must have only channels belonging to the corresponding - physical span. - - This is the reason we added group functionality in openzap core, furthermore, previous groups in openzap - were only possible through adding of b-channels to a single span, but this forces the user to create groups - of channels only whithin the same type of trunk among other things. - -- all spans must be configured and then started, cannot configure, start, configure start etc - this is due to netborder telesoft abstraction. that requires configuring everything and - then starting everything at once. - -- sangoma_prid and sangoma_brid on Windows had to be compiled hacking make/Makefile.platform to comment all VC runtime checks, - otherwise when running in debug mode exceptions are thrown due to loss of data ie short to char conversions. - -== TODO == -- proper upper layer management of HW alarms (this must be done in mod_openzap.c) - diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/boost-tasks.txt b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/boost-tasks.txt deleted file mode 100644 index f0eab3a277..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/boost-tasks.txt +++ /dev/null @@ -1,146 +0,0 @@ -== General Design == - -NBE will do its current loading of spans and configuration process through Sangoma Board Manager (SBM). -After doing SangomaBoardManager::getInstance().configure -> start. It will proceed to initalize -the openzap stack (just as the TelesoftStack is loaded after starting SMB. The procedure will be: - -- create a static or malloced zap_io_interface_t -- call zap_global_set_logger with the logging hooks. -- call zap_global_set_memhandler() with the memory hooks. -- call zap_global_init() to initialize the stack -- call zap_add_io_iface() to add the I/O iface. -- iterate over all SBM spans configured for BRI or any boost-managed signaling and: - * call zap_span_create(NBE I/O mod, in_ptrSpan, SMB span name) - * Fill in some members like: - span->trunk_type = E1/T1/J1/FXO/FXS etc ... - * iterate over all channels in SMB span and: - * zap_span_add_channel(zap_span, sock, type:CAS|BCHAN|DCHAN|ETC) - * call zap_configure_span("sangoma_boost", span, sigmsg_callback, "param1", value1, "param2", value1 ...) - * zap_span_start(span); - - -At this point, NBE would receive signaling msgs via sigmsg_callback registered when configuring -and NBE would request hangup or making calls throug openzap API, like zap_set_state_* and zap_channel_outgoing_call() to place calls. - -When NBE wants to check for link status. - - zap_get_siglink_state() which would return - ZAP_SIG_STATE_UP (D-chan UP, R2 bits in IDLE, ss7?) - ZAP_SIG_STATE_SUSPENDED (D-chan in power saving mode?) - ZAP_SIG_STATE_DOWN (D-chan down, R2 bits in blocked, ss7?) - - Whenever a state in sig link changes, the sigmsg_callback will be used to notify NBE or any other user. - -NOTE: right now hardware alarms notification in openzap is seriously broken, -see ozmod_libpri.c process_event ... reads an event from hardware (zap_event_t *), -then checks the event type, if its ZAP_OOB_ALARM_TRAP prepares a zap_sigmsg_t -(signaling event) setting its event_id to ZAP_OOB_ALARM_TRAP, which is *WRONG* -because event_id is of type zap_signal_event_t and not zap_oob_event_t! -this means on alarm the user will get ZAP_SIGEVENT_PROGRESS_MEDIA!! which is -value 7 that is in conflict with ZAP_OOB_ALARM_TRAP, I think a separate -callback should be used if the outside user wants to be notified about -hardware events like HW DTMF or so. Currently there is alreadya generic DTMF -listener. - -== Tasks Stage 1 / OpenZAP and Boost changes (To be tested with FreeSWITCH) == - -- Change malloc and other mem functions in openzap - to use internal hooks provided via zap_global_set_memhandler() - which would be called before zap_global_init(), this is - already done for the logger via zap_global_set_logger() - - question: should the mem routines allow for memory pool ptr? - this could be useful to provide a memory pool to - the whole module. - - question: should we allow hooks for threads and locking? - I think we can skip this one unless needed. They already - use their own threading abstraction which is working for - Linux and Windows. If we ever need to profile threading - we can add profiling hooks. - - question: I had to add openzap calls to the hash table and libteletone implementations, is that acceptable? - -- Modify zap_global_init() API - - This API must just initialize vars, mutexes etc. - and NOT DO ANY CONFIGURATION LOADING, PARSING, SPAN CREATION and I/O - configuration, which is what is currently doing. - We don't want zap_global_init() to create the spans based on that configuration - since NBE will have its own configuration and will take care of creating - the needed data structures on its own. - -- Add new zap_std_io_config() API - - This API will parse the standard openzap.conf module and create the spans. - This will be used by FS but not by NBE, which will create the openzap spans by itself. - The NBE flow to initialize openzap will be: - -- Add new API zap_global_add_io_iface(), - - This API will add a new I/O interface structure to the internal openzap hash of I/O structs. - This is needed because NBE I/O structure will NOT be loaded from an openzap module (.so/.dll) - but rather just registered on runtime (probably from a static structure in NBE code). - This openzap hash is used by zap_api_execute() for example, to find the module that can - handle a given API, ie (oz libpri status). This is an example of how an openzap I/O interface - can decide to implement just the ->api() member to handle commands and NOTHING else, - so I/O interfaces not necessary are hardware-related. - -- Add new zap_channel_get_siglink_state(zap_channel, zap_siglink_status_t &status) - -- Modify mod_openzap.c to read proto= setting in boost spans, this will determine wich boost sig - module will handle the configuration and those channels. - - - - Then as first config arg to zap_config_span() the boost proto module name would be included as "sigmod" which will be used - by ozmod_sangoma_boost to decide which sig module must handle that span configuration - -- Create minimal boost mod interface. - - ozmod_boost_ss7 should load sig boost mods and get interface via dlsym(boost_get_interface) boost_get_interface(boost_iface); - The boost interface will have - * const char *name // boost sigmod name (brid,ss7d) - * set_write_boost_msg_cb(callback) // tell the stack how to send us boost messages - * set_sig_status_cb(callback); // tell the stack how to notify us about link status changes - * write_boost_msg(struct boost_msg) // send a boost msg to the stack - * configure_span(zap_span_t span, "configuration", value, "configuration", value) // configure a given span - * get_sig_status(openzap_sigstatus_t status) - * start(span) // to start a given openzap span - * stop(span) // to stop the stack on a given openzap span - -- Migrate current sangoma_brid sig module to openzap - * Make sangoma_brid a library - * Move from using malloc, threading, locking, logging and I/O to openzap functions. Export the boost sigmod interface and its supporting code. - -== State 2 Tasks == - -- Create the I/O NBE interface and supporting functions. It must be possible to poll over the span - given that ozmod_sangoma_boost BRI module and others may need to *wait* for data. The poll() - function in I/O NBE interface would wait on a pthread condition or Windows event, which would - be triggered by some external NBE component registered with Sangoma Board Manager (SMB) for d-chan - data, whenever d-chan data arrives, saves the data in a buffer and triggers the condition to wakeup - any waiter, then the waiter (sangoma_brid or any other boost client) calls zap_channel_read which calls - our own I/O NBE interface read method and retrieves the data from the buffer. - - Dropped alternative design: - Another option is to add a new API zap_span_push_incoming_data(span/chan, data); However this changes - the model openzap has followed and I don't think fits that well, since now we have 2 different models - to support in openzap. - -== TODO == - -- how about logging specific modules, like, just ozmod_boost, or just the BRI stack? - more work to be done so the BRI module uses zap_log instead of current syslog - then work to be done to be able to filter logs from specific openzap code? is it worth it? - -- remove FORCE_SEGFAULT from sprid - - -=== Shortcomings == - -- we had to drop smg support in the branch where we work on sangoma prid. - After all, most people using sangoma_prid is using freeswitch/openzap and not Sangoma Media Gateway - The problem is in freeswitch/openzap mode, sangoma_boost ozmod takes care of span events (POLLPRI) - where in SMG and Netborder POLLPRI is done typically by sangoma board manager. - diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftdm_sangoma_boost.h b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftdm_sangoma_boost.h deleted file mode 100644 index 6fbf272d07..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftdm_sangoma_boost.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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 FTDM_SANGOMA_BOOST_H -#define FTDM_SANGOMA_BOOST_H -#include "sangoma_boost_client.h" -#include "freetdm.h" - -#define MAX_CHANS_PER_TRUNKGROUP 1024 - -typedef enum { - FTDM_SANGOMA_BOOST_RUNNING = (1 << 0), - FTDM_SANGOMA_BOOST_RESTARTING = (1 << 1), - FTDM_SANGOMA_BOOST_EVENTS_RUNNING = (1 << 2), -} ftdm_sangoma_boost_flag_t; - -typedef struct ftdm_sangoma_boost_data { - sangomabc_connection_t mcon; - sangomabc_connection_t pcon; - int iteration; - uint32_t flags; - boost_sigmod_interface_t *sigmod; - ftdm_queue_t *boost_queue; -} ftdm_sangoma_boost_data_t; - -typedef struct ftdm_sangoma_boost_trunkgroup { - ftdm_mutex_t *mutex; - ftdm_size_t size; /* Number of b-channels in group */ - unsigned int last_used_index; /* index of last b-channel used */ - ftdm_channel_t* ftdmchans[MAX_CHANS_PER_TRUNKGROUP]; - //TODO need to merge congestion timeouts to this struct -} ftdm_sangoma_boost_trunkgroup_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: - */ - diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2008.vcproj deleted file mode 100644 index 73e421818f..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2008.vcproj +++ /dev/null @@ -1,373 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj deleted file mode 100644 index 684e4326cb..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj +++ /dev/null @@ -1,206 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - ftmod_sangoma_boost - {D021EF2A-460D-4827-A0F7-41FDECF46F1B} - ftmod_sangoma_boost - Win32Proj - - - - DynamicLibrary - Unicode - true - - - DynamicLibrary - Unicode - - - DynamicLibrary - Unicode - true - - - DynamicLibrary - Unicode - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - true - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - false - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - true - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_SANGOMA_BOOST_EXPORTS;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - - - Level4 - true - EditAndContinue - 4100;%(DisableSpecificWarnings) - - - %(AdditionalDependencies) - $(OutDir);%(AdditionalLibraryDirectories) - true - Windows - MachineX86 - - - - - MaxSpeed - true - ..\..\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_SANGOMA_BOOST_EXPORTS;%(PreprocessorDefinitions) - MultiThreadedDLL - true - - - Level4 - true - ProgramDatabase - 4100;%(DisableSpecificWarnings) - - - true - Windows - true - true - MachineX86 - - - - - X64 - - - Disabled - ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_SANGOMA_BOOST_EXPORTS;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - - - Level4 - true - ProgramDatabase - 4100;%(DisableSpecificWarnings) - - - %(AdditionalDependencies) - $(OutDir);%(AdditionalLibraryDirectories) - true - Windows - MachineX64 - - - - - X64 - - - MaxSpeed - true - ..\..\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_SANGOMA_BOOST_EXPORTS;%(PreprocessorDefinitions) - MultiThreadedDLL - true - - - Level4 - false - ProgramDatabase - 4100;%(DisableSpecificWarnings) - - - true - Windows - true - true - MachineX64 - - - - - - - - - - - - - - - {93b8812c-3ec4-4f78-8970-ffbfc99e167d} - false - - - - - - \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj.filters deleted file mode 100644 index 2aeed155cd..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj.filters +++ /dev/null @@ -1,35 +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 - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c deleted file mode 100644 index d0bc14c8d8..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c +++ /dev/null @@ -1,2730 +0,0 @@ -/* - * 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. - * - * Contributors: - * - * Moises Silva - * David Yat Sin - * Nenad Corbic - * - */ - -/* NOTE: -On __WINDOWS__ platform this code works with sigmod ONLY, don't try to make sense of any socket code for win -I basically ifdef out everything that the compiler complained about -*/ - -#include "private/ftdm_core.h" -#include "sangoma_boost_client.h" -#include "ftdm_sangoma_boost.h" -#ifdef HAVE_SYS_SELECT_H -#include -#endif - -/* Boost signaling modules global hash and its mutex */ -ftdm_mutex_t *g_boost_modules_mutex = NULL; -ftdm_hash_t *g_boost_modules_hash = NULL; - -#define MAX_TRUNK_GROUPS 64 -//TODO need to merge congestion_timeouts with ftdm_sangoma_boost_trunkgroups -static time_t congestion_timeouts[MAX_TRUNK_GROUPS]; - -static ftdm_sangoma_boost_trunkgroup_t *g_trunkgroups[MAX_TRUNK_GROUPS]; - -static ftdm_io_interface_t ftdm_sangoma_boost_interface; -static ftdm_status_t ftdm_sangoma_boost_list_sigmods(ftdm_stream_handle_t *stream); - -#define BOOST_QUEUE_SIZE 500 - -/* get freetdm span and chan depending on the span mode */ -#define BOOST_SPAN(ftdmchan) ((ftdm_sangoma_boost_data_t*)(ftdmchan)->span->signal_data)->sigmod ? ftdmchan->physical_span_id : ftdmchan->physical_span_id-1 -#define BOOST_CHAN(ftdmchan) ((ftdm_sangoma_boost_data_t*)(ftdmchan)->span->signal_data)->sigmod ? ftdmchan->physical_chan_id : ftdmchan->physical_chan_id-1 - -/** - * \brief SANGOMA boost notification flag - */ -typedef enum { - SFLAG_SENT_FINAL_MSG = (1 << 0), - SFLAG_SENT_ACK = (1 << 1), - SFLAG_RECVD_ACK = (1 << 2), - SFLAG_HANGUP = (1 << 3), - SFLAG_TERMINATING = (1 << 4) -} sflag_t; - -typedef uint16_t sangoma_boost_request_id_t; - -/** - * \brief SANGOMA boost request status - */ -typedef enum { - BST_FREE, - BST_WAITING, - BST_READY, - BST_FAIL -} sangoma_boost_request_status_t; - -/** - * \brief SANGOMA boost request structure - */ -typedef struct { - sangoma_boost_request_status_t status; - sangomabc_short_event_t event; - ftdm_span_t *span; - ftdm_channel_t *ftdmchan; - int hangup_cause; - int flags; -} sangoma_boost_request_t; - -typedef struct { - int call_setup_id; - int last_event_id; -} sangoma_boost_call_t; - -#define CALL_DATA(ftdmchan) ((sangoma_boost_call_t*)((ftdmchan)->call_data)) - -//#define MAX_REQ_ID FTDM_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN * FTDM_MAX_CHANNELS_PHYSICAL_SPAN -#define MAX_REQ_ID 6000 - -static uint16_t SETUP_GRID[FTDM_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN+1][FTDM_MAX_CHANNELS_PHYSICAL_SPAN+1] = {{ 0 }}; - -static sangoma_boost_request_t OUTBOUND_REQUESTS[MAX_REQ_ID+1] = {{ 0 }}; - -static ftdm_mutex_t *request_mutex = NULL; - -static uint8_t req_map[MAX_REQ_ID+1] = { 0 }; -static uint8_t nack_map[MAX_REQ_ID+1] = { 0 }; - -/** - * \brief Releases span and channel from setup grid - * - * \note This is ALWAYS based on freetdm span/chan numbers! not boost event numbers - * is totally brain damaged to use event->span or event->chan to release the request - * use BOOST_SPAN_EVENT and BOOST_SPAN_CHAN to get the right index!! - * - * \param span Span number - * \param chan Channel number - * \param func Calling function - * \param line Line number on request - * \return NULL if not found, channel otherwise - */ -static void __release_request_id_span_chan(int span, int chan, const char *func, int line) -{ - int id; - - ftdm_mutex_lock(request_mutex); - if ((id = SETUP_GRID[span][chan])) { - ftdm_assert(id <= MAX_REQ_ID, "Invalid request id\n"); - req_map[id] = 0; - SETUP_GRID[span][chan] = 0; - } - ftdm_mutex_unlock(request_mutex); -} -#define release_request_id_span_chan(s, c) __release_request_id_span_chan(s, c, __FUNCTION__, __LINE__) - -/** - * \brief Releases request ID - * \param func Calling function - * \param line Line number on request - * \return NULL if not found, channel otherwise - */ -static void __release_request_id(sangoma_boost_request_id_t r, const char *func, int line) -{ - ftdm_assert(r <= MAX_REQ_ID, "Invalid request id\n"); - ftdm_mutex_lock(request_mutex); - req_map[r] = 0; - ftdm_mutex_unlock(request_mutex); -} -#define release_request_id(r) __release_request_id(r, __FUNCTION__, __LINE__) - -static sangoma_boost_request_id_t last_req = 0; - -/** - * \brief Gets the first available tank request ID - * \param func Calling function - * \param line Line number on request - * \return 0 on failure, request ID on success - */ -static sangoma_boost_request_id_t __next_request_id(const char *func, int line) -{ - sangoma_boost_request_id_t r = 0, i = 0; - int found=0; - - ftdm_mutex_lock(request_mutex); - //r = ++last_req; - //while(!r || req_map[r]) { - - for (i=1; i<= MAX_REQ_ID; i++){ - r = ++last_req; - - if (r >= MAX_REQ_ID) { - r = last_req = 1; - } - - if (req_map[r]) { - /* Busy find another */ - continue; - - } - - req_map[r] = 1; - found=1; - break; - - } - - ftdm_mutex_unlock(request_mutex); - - if (!found) { - return 0; - } - - return r; -} -#define next_request_id() __next_request_id(__FUNCTION__, __LINE__) - - -static void print_request_ids(void) -{ - sangoma_boost_request_id_t i = 0; - int cnt=0; - - ftdm_mutex_lock(request_mutex); - - for (i=1; i<= MAX_REQ_ID; i++){ - if (req_map[i]) { - ftdm_log(FTDM_LOG_CRIT, "Used Request ID=%i\n",i); - cnt++; - } - } - - ftdm_mutex_unlock(request_mutex); - ftdm_log(FTDM_LOG_CRIT, "Total Request IDs=%i\n",cnt); - - return; -} - - -/** - * \brief Finds the channel that triggered an event - * \param span Span where to search the channel - * \param event SANGOMA event - * \param force Do not wait for the channel to be available if in use - * \return NULL if not found, channel otherwise - */ -static ftdm_channel_t *find_ftdmchan(ftdm_span_t *span, sangomabc_short_event_t *event, int force) -{ - uint32_t i; - ftdm_channel_t *ftdmchan = NULL; - - ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data; - uint32_t targetspan = BOOST_EVENT_SPAN(sangoma_boost_data->sigmod, event); - uint32_t targetchan = BOOST_EVENT_CHAN(sangoma_boost_data->sigmod, event); - - /* NC: Sanity check in case the call setup id does not relate - to span. This can happen if RESTART is received on a - full load. Where stray ACK messages can arrive after - a RESTART has taken place. - */ - if (!span) { - ftdm_log(FTDM_LOG_CRIT, "No Span for Event=%s s%dc%d cid=%d\n", - BOOST_DECODE_EVENT_ID(event->event_id), - targetspan, - targetchan, - event->call_setup_id); - return NULL; - } - - - for(i = 1; i <= span->chan_count; i++) { - if (span->channels[i]->physical_span_id == targetspan && span->channels[i]->physical_chan_id == targetchan) { - ftdmchan = span->channels[i]; - if (force || (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE))) { - break; - } else { - ftdmchan = NULL; - ftdm_log(FTDM_LOG_DEBUG, "Channel %d:%d ~ %d:%d is already in use in state %s\n", - span->channels[i]->span_id, - span->channels[i]->chan_id, - span->channels[i]->physical_span_id, - span->channels[i]->physical_chan_id, - ftdm_channel_state2str(span->channels[i]->state)); - break; - } - } - } - - return ftdmchan; -} - -static int check_congestion(int trunk_group) -{ - if (congestion_timeouts[trunk_group]) { - time_t now = time(NULL); - - if (now >= congestion_timeouts[trunk_group]) { - congestion_timeouts[trunk_group] = 0; - } else { - return 1; - } - } - - return 0; -} - - -/** - * \brief Requests an sangoma boost channel on a span (outgoing call) - * \param span Span where to get a channel - * \param chan_id Specific channel to get (0 for any) - * \param direction Call direction - * \param caller_data Caller information - * \param ftdmchan Channel to initialise - * \return Success or failure - */ -static FIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request) -{ - ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data; - ftdm_status_t status = FTDM_FAIL; - sangoma_boost_request_id_t r; - sangomabc_event_t event = {0}; - /* sanity has to be more than 8 seconds. - * In PRI specs, timeout is 4 seconds for remote switch to respond to a SETUP, - * and PRI stack will retransmit a second SETUP after the first timeout, so - * we should allow for at least 8 seconds. - */ - - int boost_request_timeout = 10000; - sangoma_boost_request_status_t st; - char dnis[128] = ""; - char *gr = NULL; - uint32_t count = 0; - int tg=0; - - /* NC: On large number of calls 10 seconds is not enough. - Resetting to 30 seconds. Especially on ss7 when - links are reset during large call volume */ - if (!sangoma_boost_data->sigmod) { - boost_request_timeout = 30000; - } - - if (sangoma_boost_data->sigmod) { - ftdm_log(FTDM_LOG_CRIT, "This function should not be called when sigmod was configured in boost\n"); - *ftdmchan = NULL; - return FTDM_FAIL; - } - - if (ftdm_test_flag(span, FTDM_SPAN_SUSPENDED)) { - ftdm_log(FTDM_LOG_CRIT, "SPAN is Suspended.\n"); - *ftdmchan = NULL; - return FTDM_FAIL; - } - - if (check_congestion(tg)) { - ftdm_log(FTDM_LOG_CRIT, "All circuits are busy. Trunk Group=%i (CONGESTION)\n",tg+1); - *ftdmchan = NULL; - return FTDM_FAIL; - } - - if (count >= span->chan_count) { - ftdm_log(FTDM_LOG_CRIT, "All circuits are busy.\n"); - *ftdmchan = NULL; - return FTDM_FAIL; - } - - r = next_request_id(); - if (r == 0) { - ftdm_log(FTDM_LOG_CRIT, "All tanks ids are busy.\n"); - *ftdmchan = NULL; - return FTDM_FAIL; - } - - /* After this point we must release request id before we leave the function - in case of an error. */ - - ftdm_set_string(dnis, caller_data->dnis.digits); - - if ((gr = strchr(dnis, '@'))) { - *gr++ = '\0'; - } - - if (gr && *(gr+1)) { - tg = atoi(gr+1); - if (tg > 0) { - tg--; - } - } - - sangomabc_call_init(&event, caller_data->cid_num.digits, dnis, r); - - event.trunk_group = tg; - - - ftdm_span_channel_use_count(span, &count); - - if (gr && *(gr+1)) { - switch(*gr) { - case 'g': - event.hunt_group = SIGBOOST_HUNTGRP_SEQ_ASC; - break; - case 'G': - event.hunt_group = SIGBOOST_HUNTGRP_SEQ_DESC; - break; - case 'r': - event.hunt_group = SIGBOOST_HUNTGRP_RR_ASC; - break; - case 'R': - event.hunt_group = SIGBOOST_HUNTGRP_RR_DESC; - break; - default: - ftdm_log(FTDM_LOG_WARNING, "Failed to determine huntgroup (%s)\n", gr); - event.hunt_group = SIGBOOST_HUNTGRP_SEQ_ASC; - } - } - - ftdm_set_string(event.calling_name, caller_data->cid_name); - ftdm_set_string(event.rdnis.digits, caller_data->rdnis.digits); - if (strlen(caller_data->rdnis.digits)) { - event.rdnis.digits_count = (uint8_t)strlen(caller_data->rdnis.digits)+1; - event.rdnis.ton = caller_data->rdnis.type; - event.rdnis.npi = caller_data->rdnis.plan; - } - - event.calling.screening_ind = caller_data->screen; - event.calling.presentation_ind = caller_data->pres; - - event.calling.ton = caller_data->cid_num.type; - event.calling.npi = caller_data->cid_num.plan; - - event.called.ton = caller_data->dnis.type; - event.called.npi = caller_data->dnis.plan; - - /* we're making a contract now that FreeTDM values for capability, layer 1 and such will be the same as for boost */ - event.bearer.capability = caller_data->bearer_capability; - event.bearer.uil1p = caller_data->bearer_layer1; - - if (caller_data->raw_data_len) { - ftdm_set_string(event.custom_data, caller_data->raw_data); - event.custom_data_size = (uint16_t)caller_data->raw_data_len; - } - - OUTBOUND_REQUESTS[r].status = BST_WAITING; - OUTBOUND_REQUESTS[r].span = span; - - if (sangomabc_connection_write(&sangoma_boost_data->mcon, &event) <= 0) { - ftdm_log(FTDM_LOG_CRIT, "Failed to tx boost event [%s]\n", strerror(errno)); - status = OUTBOUND_REQUESTS[r].status = FTDM_FAIL; - if (!sangoma_boost_data->sigmod) { - *ftdmchan = NULL; - } - goto done; - } - - while(ftdm_running() && OUTBOUND_REQUESTS[r].status == BST_WAITING) { - ftdm_sleep(1); - if (--boost_request_timeout <= 0) { - status = FTDM_FAIL; - if (!sangoma_boost_data->sigmod) { - *ftdmchan = NULL; - } - ftdm_log(FTDM_LOG_CRIT, "Csid:%d Timed out waiting for boost channel request response, current status: BST_WAITING\n", r); - goto done; - } - } - - if (OUTBOUND_REQUESTS[r].status == BST_READY && OUTBOUND_REQUESTS[r].ftdmchan) { - *ftdmchan = OUTBOUND_REQUESTS[r].ftdmchan; - status = FTDM_SUCCESS; - } else { - status = FTDM_FAIL; - if (!sangoma_boost_data->sigmod) { - *ftdmchan = NULL; - } - } - - done: - - st = OUTBOUND_REQUESTS[r].status; - OUTBOUND_REQUESTS[r].status = BST_FREE; - - if (status == FTDM_FAIL) { - if (st == BST_FAIL) { - caller_data->hangup_cause = OUTBOUND_REQUESTS[r].hangup_cause; - } else { - caller_data->hangup_cause = FTDM_CAUSE_RECOVERY_ON_TIMER_EXPIRE; - } - } - - if (st == BST_FAIL) { - release_request_id(r); - } else if (st != BST_READY) { - ftdm_assert_return(r <= MAX_REQ_ID, FTDM_FAIL, "Invalid index\n"); - nack_map[r] = 1; - if (sangoma_boost_data->sigmod) { - sangomabc_exec_command(&sangoma_boost_data->mcon, - BOOST_SPAN((*ftdmchan)), - BOOST_CHAN((*ftdmchan)), - r, - SIGBOOST_EVENT_CALL_START_NACK, - 0, 0); - } else { - sangomabc_exec_command(&sangoma_boost_data->mcon, - 0, - 0, - r, - SIGBOOST_EVENT_CALL_START_NACK, - 0, 0); - } - } - - return status; -} - -/** - * \brief Starts an sangoma boost channel (outgoing call) - * \param ftdmchan Channel to initiate call on - * \return Success - */ -static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(sangoma_boost_outgoing_call) -{ - ftdm_sangoma_boost_data_t *sangoma_boost_data = ftdmchan->span->signal_data; - - if (!sangoma_boost_data->sigmod) { - return FTDM_SUCCESS; - } - - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND); - - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DIALING); - - return FTDM_SUCCESS; -} - -/** - * \brief Handler for call start ack no media event - * \param mcon sangoma boost connection - * \param event Event to handle - */ -static void handle_call_progress(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event) -{ - ftdm_channel_t *ftdmchan; - - - if ((ftdmchan = find_ftdmchan(span, event, 1))) { - ftdm_sangoma_boost_data_t *sangoma_boost_data = ftdmchan->span->signal_data; - ftdm_mutex_lock(ftdmchan->mutex); - if (!sangoma_boost_data->sigmod && ftdmchan->state == FTDM_CHANNEL_STATE_HOLD) { - if ((event->flags & SIGBOOST_PROGRESS_MEDIA)) { - ftdmchan->init_state = FTDM_CHANNEL_STATE_PROGRESS_MEDIA; - ftdm_log(FTDM_LOG_DEBUG, "Channel init state updated to PROGRESS_MEDIA [Csid:%d]\n", event->call_setup_id); - } else if ((event->flags & SIGBOOST_PROGRESS_RING)) { - ftdmchan->init_state = FTDM_CHANNEL_STATE_PROGRESS; - ftdm_log(FTDM_LOG_DEBUG, "Channel init state updated to PROGRESS [Csid:%d]\n", event->call_setup_id); - } else { - ftdmchan->init_state = FTDM_CHANNEL_STATE_IDLE; - ftdm_log(FTDM_LOG_DEBUG, "Channel init state updated to IDLE [Csid:%d]\n", event->call_setup_id); - } - } else { - if ((event->flags & SIGBOOST_PROGRESS_MEDIA)) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); - } else if ((event->flags & SIGBOOST_PROGRESS_RING)) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); - } else { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); - } - } - ftdm_mutex_unlock(ftdmchan->mutex); - } -} - -/** - * \brief Handler for call start ack event - * \param mcon sangoma boost connection - * \param event Event to handle - */ -static void handle_call_start_ack(sangomabc_connection_t *mcon, sangomabc_short_event_t *event) -{ - - ftdm_channel_t *ftdmchan = NULL; - uint32_t event_span = BOOST_EVENT_SPAN(mcon->sigmod, event); - uint32_t event_chan = BOOST_EVENT_CHAN(mcon->sigmod, event); - - - if (nack_map[event->call_setup_id]) { - /* In this scenario outgoing call was alrady stopped - via NACK and now we are expecting an NACK_ACK. - If we receive an ACK its a race condition thus - ignor it */ - return; - } - - if (mcon->sigmod) { - ftdmchan = OUTBOUND_REQUESTS[event->call_setup_id].ftdmchan; - } else { - ftdmchan = find_ftdmchan(OUTBOUND_REQUESTS[event->call_setup_id].span, event, 0); - } - - - if (ftdmchan) { - ftdm_sangoma_boost_data_t *sangoma_boost_data = ftdmchan->span->signal_data; - if (!mcon->sigmod && ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Failed to open FTDM channel [%s]\n", ftdmchan->last_error); - } else { - - /* Only bind the setup id to GRID when we are sure that channel is ready - otherwise we could overwite the original call */ - OUTBOUND_REQUESTS[event->call_setup_id].event = *event; - SETUP_GRID[event_span][event_chan] = event->call_setup_id; - - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND); - ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_INUSE); - ftdmchan->sflags = SFLAG_RECVD_ACK; - - if ((event->flags & SIGBOOST_PROGRESS_MEDIA)) { - if (sangoma_boost_data->sigmod) { - ftdm_log(FTDM_LOG_DEBUG, "Channel state changing to PROGRESS_MEDIA [Csid:%d]\n", event->call_setup_id); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); - } else { - ftdmchan->init_state = FTDM_CHANNEL_STATE_PROGRESS_MEDIA; - ftdm_log(FTDM_LOG_DEBUG, "Channel init state changed to PROGRESS_MEDIA [Csid:%d]\n", event->call_setup_id); - } - } else if ((event->flags & SIGBOOST_PROGRESS_RING)) { - if (sangoma_boost_data->sigmod) { - ftdm_log(FTDM_LOG_DEBUG, "Channel state changing to PROGRESS [Csid:%d]\n", event->call_setup_id); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); - } else { - ftdmchan->init_state = FTDM_CHANNEL_STATE_PROGRESS; - ftdm_log(FTDM_LOG_DEBUG, "Channel init state changed to PROGRESS [Csid:%d]\n", event->call_setup_id); - } - } else { - if (sangoma_boost_data->sigmod) { - /* should we set a state here? */ - } else { - ftdmchan->init_state = FTDM_CHANNEL_STATE_IDLE; - ftdm_log(FTDM_LOG_DEBUG, "Channel init state changed to IDLE [Csid:%d]\n", event->call_setup_id); - } - } - if (!sangoma_boost_data->sigmod) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HOLD); - ftdm_log(FTDM_LOG_DEBUG, "Assigned chan %d:%d (%d:%d) to CSid=%d\n", - ftdmchan->span_id, ftdmchan->chan_id, event_span, event_chan, event->call_setup_id); - OUTBOUND_REQUESTS[event->call_setup_id].ftdmchan = ftdmchan; - } - OUTBOUND_REQUESTS[event->call_setup_id].flags = event->flags; - OUTBOUND_REQUESTS[event->call_setup_id].status = BST_READY; - return; - } - - } else { - - ftdm_assert(!mcon->sigmod, "CALL STOP ACK: Invalid Sigmod Path"); - - if ((ftdmchan = find_ftdmchan(OUTBOUND_REQUESTS[event->call_setup_id].span, (sangomabc_short_event_t*)event, 1))) { - int r; - /* NC: If we get CALL START ACK and channel is in active state - then we are completely out of sync with the other end. - Treat CALL START ACK as CALL STOP and hangup the current call. - */ - - if (ftdmchan->state == FTDM_CHANNEL_STATE_UP || - ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA || - ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS) { - ftdm_log(FTDM_LOG_CRIT, "FTDMCHAN CALL ACK STATE UP -> Changed to TERMINATING %d:%d\n", event_span, event_chan); - ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, r); - } else if (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP || ftdm_test_sflag(ftdmchan, SFLAG_HANGUP)) { - ftdm_log(FTDM_LOG_CRIT, "FTDMCHAN CALL ACK STATE HANGUP -> Changed to HANGUP COMPLETE %d:%d\n", event_span, event_chan); - ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, r); - } else { - ftdm_log(FTDM_LOG_CRIT, "FTDMCHAN STATE INVALID State %s on IN CALL ACK %d:%d\n", - ftdm_channel_state2str(ftdmchan->state), event_span, event_chan); - } - ftdm_set_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG); - ftdmchan=NULL; - } - } - - - if (!ftdmchan) { - ftdm_log(FTDM_LOG_CRIT, "START ACK CANT FIND A CHAN %d:%d\n", event_span, event_chan); - } else { - /* only reason to be here is failed to open channel when we we're in sigmod */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - ftdm_set_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG); - } - - sangomabc_exec_command(mcon, - event->span, - event->chan, - event->call_setup_id, - SIGBOOST_EVENT_CALL_STOPPED, - FTDM_CAUSE_DESTINATION_OUT_OF_ORDER, 0); - OUTBOUND_REQUESTS[event->call_setup_id].status = BST_FAIL; - OUTBOUND_REQUESTS[event->call_setup_id].hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER; -} - -/** - * \brief Handler for call done event - * \param span Span where event was fired - * \param mcon sangoma boost connection - * \param event Event to handle - */ -static void handle_call_done(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event) -{ - ftdm_channel_t *ftdmchan; - int r = 0; - - if ((ftdmchan = find_ftdmchan(span, event, 1))) { - ftdm_sangoma_boost_data_t *sangoma_boost_data = ftdmchan->span->signal_data; - ftdm_mutex_lock(ftdmchan->mutex); - - if (sangoma_boost_data->sigmod) { - /* not really completely done, but if we ever get an incoming call before moving to HANGUP_COMPLETE - * handle_incoming_call() will take care of moving the state machine to release the channel */ - sangomabc_exec_command(&sangoma_boost_data->mcon, - BOOST_SPAN(ftdmchan), - BOOST_CHAN(ftdmchan), - 0, - SIGBOOST_EVENT_CALL_RELEASED, - 0, 0); - } - - if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN || ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP_COMPLETE || ftdm_test_sflag(ftdmchan, SFLAG_TERMINATING)) { - goto done; - } - - ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, r); - if (r) { - ftdm_mutex_unlock(ftdmchan->mutex); - return; - } - } - - done: - - if (ftdmchan) { - ftdm_mutex_unlock(ftdmchan->mutex); - } - - if (event->call_setup_id) { - release_request_id(event->call_setup_id); - } else { - release_request_id_span_chan(BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event)); - } -} - - -/** - * \brief Handler for call start nack event - * \param span Span where event was fired - * \param mcon sangoma boost connection - * \param event Event to handle - */ -static void handle_call_start_nack(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event) -{ - ftdm_channel_t *ftdmchan; - ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data; - - if (event->release_cause == SIGBOOST_CALL_SETUP_NACK_ALL_CKTS_BUSY) { - uint32_t count = 0; - int delay = 0; - int tg=event->trunk_group; - - ftdm_span_channel_use_count(span, &count); - - delay = (int) (count / 100) * 2; - - if (delay > 10) { - delay = 10; - } else if (delay < 1) { - delay = 1; - } - - if (tg < 0 || tg >= MAX_TRUNK_GROUPS) { - ftdm_log(FTDM_LOG_CRIT, "Invalid All Ckt Busy trunk group number %i\n", tg); - tg=0; - } - - congestion_timeouts[tg] = time(NULL) + delay; - event->release_cause = 17; - - } else if (event->release_cause == SIGBOOST_CALL_SETUP_CSUPID_DBL_USE) { - event->release_cause = 17; - } - - if (event->call_setup_id) { - if (sangoma_boost_data->sigmod) { - ftdmchan = OUTBOUND_REQUESTS[event->call_setup_id].ftdmchan; - CALL_DATA(ftdmchan)->last_event_id = event->event_id; - CALL_DATA(ftdmchan)->call_setup_id = event->call_setup_id; - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - ftdm_clear_sflag_locked(ftdmchan, SFLAG_SENT_FINAL_MSG); - } else { - sangomabc_exec_command(mcon, - 0, - 0, - event->call_setup_id, - SIGBOOST_EVENT_CALL_START_NACK_ACK, - 0, 0); - OUTBOUND_REQUESTS[event->call_setup_id].event = *event; - OUTBOUND_REQUESTS[event->call_setup_id].status = BST_FAIL; - OUTBOUND_REQUESTS[event->call_setup_id].hangup_cause = event->release_cause; - ftdm_log(FTDM_LOG_DEBUG, "setting outbound request status %d to BST_FAIL\n", event->call_setup_id); - } - return; - } else { - if ((ftdmchan = find_ftdmchan(span, event, 1))) { - int r = 0; - - /* if there is no call setup id this should not be an outbound channel for sure */ - ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND), "Yay, outbound flag should not be set here!\n"); - - CALL_DATA(ftdmchan)->last_event_id = event->event_id; - ftdm_mutex_lock(ftdmchan->mutex); - ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, r); - if (r == FTDM_SUCCESS) { - ftdmchan->caller_data.hangup_cause = event->release_cause; - } - ftdm_mutex_unlock(ftdmchan->mutex); - if (r) { - return; - } - } - } - - if (ftdmchan) { - ftdm_set_sflag_locked(ftdmchan, SFLAG_SENT_FINAL_MSG); - } - - /* nobody else will do it so we have to do it ourselves */ - sangomabc_exec_command(mcon, - event->span, - event->chan, - event->call_setup_id, - SIGBOOST_EVENT_CALL_START_NACK_ACK, - 0, 0); -} - -static void handle_call_released(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event) -{ - ftdm_channel_t *ftdmchan; - - if ((ftdmchan = find_ftdmchan(span, event, 1))) { - ftdm_log(FTDM_LOG_DEBUG, "Releasing completely chan s%dc%d\n", BOOST_EVENT_SPAN(mcon->sigmod, event), - BOOST_EVENT_CHAN(mcon->sigmod, event)); - ftdm_channel_close(&ftdmchan); - } else { - ftdm_log(FTDM_LOG_CRIT, "Odd, We could not find chan: s%dc%d to release the call completely!!\n", - BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event)); - } -} - -/** - * \brief Handler for call stop event - * \param span Span where event was fired - * \param mcon sangoma boost connection - * \param event Event to handle - */ -static void handle_call_stop(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event) -{ - ftdm_channel_t *ftdmchan; - - if ((ftdmchan = find_ftdmchan(span, event, 1))) { - int r = 0; - - ftdm_mutex_lock(ftdmchan->mutex); - - if (ftdm_test_sflag(ftdmchan, SFLAG_HANGUP) || - ftdmchan->state == FTDM_CHANNEL_STATE_DOWN || - ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) { - - /* NC: Checking for state DOWN because ss7box can - send CALL_STOP twice in a row. If we do not check for - STATE_DOWN we will set the state back to termnating - and block the channel forever - */ - - /* racing condition where both sides initiated a hangup - * Do not change current state as channel is already clearing - * itself through local initiated hangup */ - - sangomabc_exec_command(mcon, - BOOST_SPAN(ftdmchan), - BOOST_CHAN(ftdmchan), - 0, - SIGBOOST_EVENT_CALL_STOPPED_ACK, - 0, 0); - ftdm_mutex_unlock(ftdmchan->mutex); - return; - } else if (ftdmchan->state == FTDM_CHANNEL_STATE_HOLD) { - ftdmchan->init_state = FTDM_CHANNEL_STATE_TERMINATING; - ftdm_log(FTDM_LOG_DEBUG, "Channel init state updated to TERMINATING [Csid:%d]\n", event->call_setup_id); - OUTBOUND_REQUESTS[event->call_setup_id].hangup_cause = event->release_cause; - ftdmchan->caller_data.hangup_cause = event->release_cause; - ftdm_mutex_unlock(ftdmchan->mutex); - return; - } else { - ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, r); - } - - if (r == FTDM_SUCCESS) { - ftdmchan->caller_data.hangup_cause = event->release_cause; - } - - ftdm_mutex_unlock(ftdmchan->mutex); - - if (r) { - return; - } - } else { /* we have to do it ourselves.... */ - ftdm_log(FTDM_LOG_CRIT, "Odd, We could not find chan: s%dc%d\n", - BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event)); - release_request_id_span_chan(BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event)); - } -} - -/** - * \brief Handler for call answer event - * \param span Span where event was fired - * \param mcon sangoma boost connection - * \param event Event to handle - */ -static void handle_call_answer(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event) -{ - ftdm_channel_t *ftdmchan; - - if ((ftdmchan = find_ftdmchan(span, event, 1))) { - ftdm_mutex_lock(ftdmchan->mutex); - - if (ftdm_test_sflag(ftdmchan, SFLAG_HANGUP) || - ftdmchan->state == FTDM_CHANNEL_STATE_DOWN || - ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) { - - /* NC: Do nothing here because we are in process - of stopping the call. So ignore the ANSWER. */ - ftdm_log(FTDM_LOG_DEBUG, "Got answer but call is already hangup %d:%d\n", BOOST_EVENT_SPAN(mcon->sigmod, event), - BOOST_EVENT_CHAN(mcon->sigmod, event)); - - } else if (ftdmchan->state == FTDM_CHANNEL_STATE_HOLD) { - ftdmchan->init_state = FTDM_CHANNEL_STATE_UP; - - } else { - int r = 0; - ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_UP, r); - } - ftdm_mutex_unlock(ftdmchan->mutex); - } else { - ftdm_log(FTDM_LOG_CRIT, "Could not find channel %d:%d on answer message!\n", BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event)); - sangomabc_exec_command(mcon, - event->span, - event->chan, - event->call_setup_id, - SIGBOOST_EVENT_CALL_STOPPED, - FTDM_CAUSE_DESTINATION_OUT_OF_ORDER, 0); - } -} - -static __inline__ void stop_loop(ftdm_channel_t *ftdmchan); - -/** - * \brief Handler for call start event - * \param span Span where event was fired - * \param mcon sangoma boost connection - * \param event Event to handle - */ -static void handle_call_start(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_event_t *event) -{ - ftdm_channel_t *ftdmchan = NULL; - int hangup_cause = FTDM_CAUSE_CALL_REJECTED; - int retry = 1; - -tryagain: - - if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 0))) { - if ((ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 1))) { - int r; - - /* NC: If we get CALL START and channel is in active state - then we are completely out of sync with the other end. - Treat CALL START as CALL STOP and hangup the current call. - The incoming call will also be NACKed. - */ - - if (ftdmchan->state == FTDM_CHANNEL_STATE_UP || - ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA || - ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS) { - ftdm_log(FTDM_LOG_CRIT, "s%dc%d: FTDMCHAN STATE UP -> Changed to TERMINATING\n", - BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event)); - ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, r); - } else if (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP || ftdm_test_sflag(ftdmchan, SFLAG_HANGUP)) { - ftdm_log(FTDM_LOG_CRIT, "s%dc%d: FTDMCHAN STATE HANGUP -> Changed to HANGUP COMPLETE\n", - BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event)); - ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, r); - } else if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) { - ftdm_log(FTDM_LOG_WARNING, "s%dc%d: Collision, hanging up incoming call\n", - BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event)); - /* dont hangup the outgoing call, the other side will send a call start nack too - * and there we will move to terminating. If we move to terminating here. We used to move - * to terminating here, but that introduces a problem in handle_call_start_nack where - * when receiving call start nack we move the channel from DOWN to TERMINATING ( cuz we already - * hangup here ) and the channel gets stuck in terminating forever. So at this point we're trusting - * the other side to send the call start nack ( or proceed with the call ) - * ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, r); - */ - } else if (ftdmchan->state == FTDM_CHANNEL_STATE_IN_LOOP && retry) { - retry = 0; - stop_loop(ftdmchan); - ftdm_channel_advance_states(ftdmchan); - goto tryagain; - } else { - ftdm_log(FTDM_LOG_ERROR, "s%dc%d: rejecting incoming call in channel state %s\n", - BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event), - ftdm_channel_state2str(ftdmchan->state)); - } - ftdm_set_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG); - ftdmchan = NULL; - } else { - ftdm_log(FTDM_LOG_CRIT, "s%dc%d: incoming call in invalid channel (channel not found)!\n", - BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event)); - } - goto error; - } - - if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "s%dc%d: failed to open channel on incoming call, rejecting!\n", - BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event)); - goto error; - } - - ftdm_log(FTDM_LOG_DEBUG, "Got call start from s%dc%d mapped to freetdm logical s%dc%d, physical s%dc%d\n", - event->span, event->chan, - ftdmchan->span_id, ftdmchan->chan_id, - ftdmchan->physical_span_id, ftdmchan->physical_chan_id); - - ftdmchan->sflags = 0; - ftdm_set_string(ftdmchan->caller_data.cid_num.digits, (char *)event->calling.digits); - ftdm_set_string(ftdmchan->caller_data.cid_name, (char *)event->calling.digits); - ftdm_set_string(ftdmchan->caller_data.ani.digits, (char *)event->calling.digits); - ftdm_set_string(ftdmchan->caller_data.dnis.digits, (char *)event->called.digits); - ftdm_set_string(ftdmchan->caller_data.rdnis.digits, (char *)event->rdnis.digits); - if (event->custom_data_size) { - ftdm_set_string(ftdmchan->caller_data.raw_data, event->custom_data); - ftdmchan->caller_data.raw_data_len = event->custom_data_size; - } - - if (strlen(event->calling_name)) { - ftdm_set_string(ftdmchan->caller_data.cid_name, (char *)event->calling_name); - } - - ftdmchan->caller_data.cid_num.plan = event->calling.npi; - ftdmchan->caller_data.cid_num.type = event->calling.ton; - - ftdmchan->caller_data.ani.plan = event->calling.npi; - ftdmchan->caller_data.ani.type = event->calling.ton; - - ftdmchan->caller_data.dnis.plan = event->called.npi; - ftdmchan->caller_data.dnis.type = event->called.ton; - - ftdmchan->caller_data.rdnis.plan = event->rdnis.npi; - ftdmchan->caller_data.rdnis.type = event->rdnis.ton; - - ftdmchan->caller_data.screen = event->calling.screening_ind; - ftdmchan->caller_data.pres = event->calling.presentation_ind; - - ftdmchan->caller_data.bearer_capability = event->bearer.capability; - ftdmchan->caller_data.bearer_layer1 = event->bearer.uil1p; - - /* more info about custom data: http://www.ss7box.com/smg_manual.html#ISUP-IN-RDNIS-NEW */ - if (event->custom_data_size) { - char* p = NULL; - - p = strstr((char*)event->custom_data,"PRI001-ANI2-"); - if (p!=NULL) { - int ani2 = 0; - sscanf(p, "PRI001-ANI2-%d", &ani2); - snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", ani2); - } - } - - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); - return; - - error: - hangup_cause = ftdmchan ? ftdmchan->caller_data.hangup_cause : FTDM_CAUSE_REQUESTED_CHAN_UNAVAIL; - sangomabc_exec_command(mcon, - event->span, - event->chan, - event->call_setup_id, - SIGBOOST_EVENT_CALL_START_NACK, - hangup_cause, 0); - -} - -static void handle_call_loop_start(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event) -{ - ftdm_status_t res = FTDM_FAIL; - ftdm_channel_t *ftdmchan; - - if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 0))) { - ftdm_log(FTDM_LOG_CRIT, "CANNOT START LOOP, CHAN NOT AVAILABLE %d:%d\n", BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event)); - return; - } - - if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "CANNOT START LOOP, CANT OPEN CHAN %d:%d\n", BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event)); - return; - } - - ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP, res); - if (res != FTDM_SUCCESS) { - ftdm_channel_t *toclose = ftdmchan; - ftdm_log(FTDM_LOG_CRIT, "yay, could not set the state of the channel to IN_LOOP, loop will fail\n"); - ftdm_channel_close(&toclose); - return; - } - ftdm_log(FTDM_LOG_DEBUG, "%d:%d starting loop\n", ftdmchan->span_id, ftdmchan->chan_id); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_LOOP, NULL); -} - -static __inline__ void stop_loop(ftdm_channel_t *ftdmchan) -{ - ftdm_status_t res = FTDM_FAIL; - ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL); - /* even when we did not sent a msg we set this flag to avoid sending call stop in the DOWN state handler */ - ftdm_set_flag(ftdmchan, SFLAG_SENT_FINAL_MSG); - ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_DOWN, res); - if (res != FTDM_SUCCESS) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "yay, could not set the state of the channel from IN_LOOP to DOWN\n"); - } -} - -static void handle_call_loop_stop(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event) -{ - ftdm_channel_t *ftdmchan; - if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 1))) { - ftdm_log(FTDM_LOG_CRIT, "CANNOT STOP LOOP, INVALID CHAN REQUESTED %d:%d\n", BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event)); - return; - } - if (ftdmchan->state != FTDM_CHANNEL_STATE_IN_LOOP) { - ftdm_log(FTDM_LOG_WARNING, "Got stop loop request in a channel that is not in loop, ignoring ...\n"); - return; - } - stop_loop(ftdmchan); -} - -/** - * \brief Handler for heartbeat event - * \param mcon sangoma boost connection - * \param event Event to handle - */ -static void handle_heartbeat(sangomabc_connection_t *mcon, sangomabc_short_event_t *event) -{ - int err; - - err = sangomabc_connection_writep(mcon, (sangomabc_event_t*)event); - - if (err <= 0) { - ftdm_log(FTDM_LOG_CRIT, "Failed to tx on boost connection [%s]: %s\n", strerror(errno)); - } - return; -} - -/** - * \brief Handler for restart ack event - * \param mcon sangoma boost connection - * \param span Span where event was fired - * \param event Event to handle - */ -static void handle_restart_ack(sangomabc_connection_t *mcon, ftdm_span_t *span, sangomabc_short_event_t *event) -{ - ftdm_log(FTDM_LOG_DEBUG, "RECV RESTART ACK\n"); -} - -/** - * \brief Handler for restart event - * \param mcon sangoma boost connection - * \param span Span where event was fired - * \param event Event to handle - */ -static void handle_restart(sangomabc_connection_t *mcon, ftdm_span_t *span, sangomabc_short_event_t *event) -{ - ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data; - - mcon->rxseq_reset = 0; - ftdm_set_flag((&sangoma_boost_data->mcon), MSU_FLAG_DOWN); - ftdm_set_flag_locked(span, FTDM_SPAN_SUSPENDED); - ftdm_set_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RESTARTING); - -} - -/** - * \brief Handler for incoming digit event - * \param mcon sangoma boost connection - * \param span Span where event was fired - * \param event Event to handle - */ -static void handle_incoming_digit(sangomabc_connection_t *mcon, ftdm_span_t *span, sangomabc_event_t *event) -{ - ftdm_channel_t *ftdmchan = NULL; - char digits[MAX_DIALED_DIGITS + 2] = ""; - - if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t *)event, 1))) { - ftdm_log(FTDM_LOG_ERROR, "Invalid channel\n"); - return; - } - - if (event->called_number_digits_count == 0) { - ftdm_log(FTDM_LOG_WARNING, "Error Incoming digit with len %s %d [w%dg%d]\n", - event->called_number_digits, - event->called_number_digits_count, - BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event)); - return; - } - - ftdm_log(FTDM_LOG_WARNING, "Incoming digit with len %s %d [w%dg%d]\n", - event->called_number_digits, - event->called_number_digits_count, - BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event)); - - memcpy(digits, event->called_number_digits, event->called_number_digits_count); - ftdm_channel_queue_dtmf(ftdmchan, digits); - - return; -} - - -/** - * \brief Checks if span has state changes pending and processes - * \param span Span where event was fired - * \param event Event to handle - * \return The locked FTDM channel associated to the event if any, NULL otherwise - */ -static ftdm_channel_t* event_process_states(ftdm_span_t *span, sangomabc_short_event_t *event) -{ - ftdm_channel_t *ftdmchan = NULL; - ftdm_sangoma_boost_data_t *signal_data = span->signal_data; - - switch (event->event_id) { - case SIGBOOST_EVENT_CALL_START_NACK: - case SIGBOOST_EVENT_CALL_START_NACK_ACK: - if (event->call_setup_id && !signal_data->sigmod) { - return NULL; - } - //if event->span and event->chan is valid, fall-through - case SIGBOOST_EVENT_CALL_START: - case SIGBOOST_EVENT_CALL_START_ACK: - case SIGBOOST_EVENT_CALL_STOPPED: - case SIGBOOST_EVENT_CALL_PROGRESS: - case SIGBOOST_EVENT_CALL_ANSWERED: - case SIGBOOST_EVENT_CALL_STOPPED_ACK: - case SIGBOOST_EVENT_DIGIT_IN: - case SIGBOOST_EVENT_INSERT_CHECK_LOOP: - case SIGBOOST_EVENT_REMOVE_CHECK_LOOP: - case SIGBOOST_EVENT_CALL_RELEASED: - if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 1))) { - ftdm_log(FTDM_LOG_CRIT, "could not find channel %d:%d to process pending state changes!\n", - BOOST_EVENT_SPAN(signal_data->sigmod, event), - BOOST_EVENT_CHAN(signal_data->sigmod, event)); - return NULL; - } - break; - case SIGBOOST_EVENT_HEARTBEAT: - case SIGBOOST_EVENT_SYSTEM_RESTART_ACK: - case SIGBOOST_EVENT_SYSTEM_RESTART: - case SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE: - return NULL; - default: - ftdm_log(FTDM_LOG_CRIT, "Unhandled event id: %d\n", event->event_id); - return NULL; - } - - ftdm_mutex_lock(ftdmchan->mutex); - ftdm_channel_advance_states(ftdmchan); - return ftdmchan; -} - -/** - * \brief Handler for sangoma boost event - * \param span Span where event was fired - * \param mcon sangoma boost connection - * \param event Event to handle - */ -static int parse_sangoma_event(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event) -{ - ftdm_channel_t* ftdmchan = NULL; - - if (!ftdm_running()) { - ftdm_log(FTDM_LOG_WARNING, "System is shutting down.\n"); - return -1; - } - - ftdm_assert_return(event->call_setup_id <= MAX_REQ_ID, -1, "Unexpected call setup id\n"); - - /* process all pending state changes for that channel before - * processing the new boost event */ - ftdmchan = event_process_states(span, event); - - switch(event->event_id) { - case SIGBOOST_EVENT_CALL_START: - handle_call_start(span, mcon, (sangomabc_event_t*)event); - break; - case SIGBOOST_EVENT_CALL_STOPPED: - handle_call_stop(span, mcon, event); - break; - case SIGBOOST_EVENT_CALL_RELEASED: - handle_call_released(span, mcon, event); - break; - case SIGBOOST_EVENT_CALL_START_ACK: - handle_call_start_ack(mcon, event); - break; - case SIGBOOST_EVENT_CALL_PROGRESS: - handle_call_progress(span, mcon, event); - break; - case SIGBOOST_EVENT_CALL_START_NACK: - handle_call_start_nack(span, mcon, event); - break; - case SIGBOOST_EVENT_CALL_ANSWERED: - handle_call_answer(span, mcon, event); - break; - case SIGBOOST_EVENT_HEARTBEAT: - handle_heartbeat(mcon, event); - break; - case SIGBOOST_EVENT_CALL_STOPPED_ACK: - handle_call_done(span, mcon, event); - break; - case SIGBOOST_EVENT_CALL_START_NACK_ACK: - /* On NACK ack span chan are always invalid - All there is to do is to clear the id */ - if (event->call_setup_id) { - nack_map[event->call_setup_id] = 0; - release_request_id(event->call_setup_id); - } else { - handle_call_done(span, mcon, event); - } - break; - case SIGBOOST_EVENT_INSERT_CHECK_LOOP: - handle_call_loop_start(span, mcon, event); - break; - case SIGBOOST_EVENT_REMOVE_CHECK_LOOP: - handle_call_loop_stop(span, mcon, event); - break; - case SIGBOOST_EVENT_SYSTEM_RESTART_ACK: - handle_restart_ack(mcon, span, event); - break; - case SIGBOOST_EVENT_SYSTEM_RESTART: - handle_restart(mcon, span, event); - break; - case SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE: - //handle_gap_abate(event); - break; - case SIGBOOST_EVENT_DIGIT_IN: - handle_incoming_digit(mcon, span, (sangomabc_event_t*)event); - break; - default: - ftdm_log(FTDM_LOG_WARNING, "No handler implemented for [%s]\n", sangomabc_event_id_name(event->event_id)); - break; - } - - if(ftdmchan != NULL) { - ftdm_channel_advance_states(ftdmchan); - ftdm_mutex_unlock(ftdmchan->mutex); - } - - return 0; - -} - -/** - * \brief Handler for channel state change - * \param ftdmchan Channel to handle - */ -static ftdm_status_t state_advance(ftdm_channel_t *ftdmchan) -{ - ftdm_sangoma_boost_data_t *sangoma_boost_data = ftdmchan->span->signal_data; - sangomabc_connection_t *mcon = &sangoma_boost_data->mcon; - ftdm_sigmsg_t sig; - ftdm_status_t status; - - - ftdm_assert_return(ftdmchan->last_state != ftdmchan->state, FTDM_FAIL, "Channel state already processed\n"); - - ftdm_log(FTDM_LOG_DEBUG, "%d:%d PROCESSING STATE [%s]\n", ftdmchan->span_id, ftdmchan->chan_id, 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: - { - int call_stopped_ack_sent = 0; - ftdm_sangoma_boost_data_t *sangoma_boost_data = ftdmchan->span->signal_data; - - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_IN_LOOP) { - ftdm_log(FTDM_LOG_DEBUG, "%d:%d terminating loop\n", ftdmchan->span_id, ftdmchan->chan_id); - } else { - release_request_id_span_chan(ftdmchan->physical_span_id, ftdmchan->physical_chan_id); - - if (!ftdm_test_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG)) { - ftdm_set_sflag_locked(ftdmchan, SFLAG_SENT_FINAL_MSG); - - if (ftdmchan->call_data && CALL_DATA(ftdmchan)->last_event_id == SIGBOOST_EVENT_CALL_START_NACK) { - sangomabc_exec_command(mcon, - BOOST_SPAN(ftdmchan), - BOOST_CHAN(ftdmchan), - CALL_DATA(ftdmchan)->call_setup_id, - SIGBOOST_EVENT_CALL_START_NACK_ACK, - 0, 0); - - } else { - /* we got a call stop msg, time to reply with call stopped ack */ - sangomabc_exec_command(mcon, - BOOST_SPAN(ftdmchan), - BOOST_CHAN(ftdmchan), - 0, - SIGBOOST_EVENT_CALL_STOPPED_ACK, - 0, 0); - call_stopped_ack_sent = 1; - } - } - } - - ftdmchan->sflags = 0; - memset(ftdmchan->call_data, 0, sizeof(sangoma_boost_call_t)); - if (sangoma_boost_data->sigmod && call_stopped_ack_sent) { - /* we dont want to call ftdm_channel_close just yet until call released is received */ - ftdm_log(FTDM_LOG_DEBUG, "Waiting for call release confirmation before declaring chan %d:%d as available \n", - ftdmchan->span_id, ftdmchan->chan_id); - } else { - ftdm_channel_t *toclose = ftdmchan; - ftdm_channel_close(&toclose); - } - } - 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(ftdmchan->span, &sig) != FTDM_SUCCESS)) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - } - } else { - if (!ftdm_test_sflag(ftdmchan, SFLAG_SENT_ACK)) { - ftdm_set_sflag(ftdmchan, SFLAG_SENT_ACK); - sangomabc_exec_command(mcon, - BOOST_SPAN(ftdmchan), - BOOST_CHAN(ftdmchan), - 0, - SIGBOOST_EVENT_CALL_START_ACK, - 0, 0); - } - sangomabc_exec_command(mcon, - BOOST_SPAN(ftdmchan), - BOOST_CHAN(ftdmchan), - 0, - SIGBOOST_EVENT_CALL_PROGRESS, - 0, SIGBOOST_PROGRESS_MEDIA); - } - } - 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(ftdmchan->span, &sig) != FTDM_SUCCESS)) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - } - } else { - if (!ftdm_test_sflag(ftdmchan, SFLAG_SENT_ACK)) { - ftdm_set_sflag(ftdmchan, SFLAG_SENT_ACK); - sangomabc_exec_command(mcon, - BOOST_SPAN(ftdmchan), - BOOST_CHAN(ftdmchan), - 0, - SIGBOOST_EVENT_CALL_START_ACK, - 0, SIGBOOST_PROGRESS_RING); - } - } - } - break; - case FTDM_CHANNEL_STATE_IDLE: - case FTDM_CHANNEL_STATE_HOLD: - { - /* twiddle */ - } - 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(ftdmchan->span, &sig) != FTDM_SUCCESS)) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - } - } - } - break; - case FTDM_CHANNEL_STATE_RESTART: - { - sig.event_id = FTDM_SIGEVENT_RESTART; - status = ftdm_span_send_signal(ftdmchan->span, &sig); - ftdm_set_sflag_locked(ftdmchan, SFLAG_SENT_FINAL_MSG); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - 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(ftdmchan->span, &sig) != FTDM_SUCCESS)) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - } - } else { - if (!(ftdm_test_flag(ftdmchan, FTDM_CHANNEL_PROGRESS) || ftdm_test_flag(ftdmchan, FTDM_CHANNEL_MEDIA))) { - sangomabc_exec_command(mcon, - BOOST_SPAN(ftdmchan), - BOOST_CHAN(ftdmchan), - 0, - SIGBOOST_EVENT_CALL_START_ACK, - 0, 0); - } - - sangomabc_exec_command(mcon, - BOOST_SPAN(ftdmchan), - BOOST_CHAN(ftdmchan), - 0, - SIGBOOST_EVENT_CALL_ANSWERED, - 0, 0); - } - } - break; - case FTDM_CHANNEL_STATE_DIALING: - { - char dnis[128] = ""; - sangoma_boost_request_id_t r; - sangomabc_event_t event = {0}; - - ftdm_assert(sangoma_boost_data->sigmod != NULL, "We should be in sigmod here!\n"); - - ftdm_set_string(dnis, ftdmchan->caller_data.dnis.digits); - - r = next_request_id(); - if (r == 0) { - ftdm_log(FTDM_LOG_CRIT, "All boost request ids are busy.\n"); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - break; - } - - sangomabc_call_init(&event, ftdmchan->caller_data.cid_num.digits, dnis, r); - - event.span = (uint8_t)ftdmchan->physical_span_id; - event.chan = (uint8_t)ftdmchan->physical_chan_id; - /* because we already have a span/chan here we bind to the SETUP_GRID now and not on call start ack */ - SETUP_GRID[event.span][event.chan] = event.call_setup_id; - - ftdm_set_string(event.calling_name, ftdmchan->caller_data.cid_name); - ftdm_set_string(event.rdnis.digits, ftdmchan->caller_data.rdnis.digits); - if (strlen(ftdmchan->caller_data.rdnis.digits)) { - event.rdnis.digits_count = (uint8_t)strlen(ftdmchan->caller_data.rdnis.digits)+1; - event.rdnis.ton = ftdmchan->caller_data.rdnis.type; - event.rdnis.npi = ftdmchan->caller_data.rdnis.plan; - } - - event.calling.screening_ind = ftdmchan->caller_data.screen; - event.calling.presentation_ind = ftdmchan->caller_data.pres; - - event.calling.ton = ftdmchan->caller_data.cid_num.type; - event.calling.npi = ftdmchan->caller_data.cid_num.plan; - - event.called.ton = ftdmchan->caller_data.dnis.type; - event.called.npi = ftdmchan->caller_data.dnis.plan; - - if (ftdmchan->caller_data.raw_data_len) { - ftdm_set_string(event.custom_data, ftdmchan->caller_data.raw_data); - event.custom_data_size = (uint16_t)ftdmchan->caller_data.raw_data_len; - } - - OUTBOUND_REQUESTS[r].status = BST_WAITING; - OUTBOUND_REQUESTS[r].span = ftdmchan->span; - OUTBOUND_REQUESTS[r].ftdmchan = ftdmchan; - - ftdm_log(FTDM_LOG_DEBUG, "Dialing number %s over boost channel with request id %d\n", event.called_number_digits, r); - if (sangomabc_connection_write(&sangoma_boost_data->mcon, &event) <= 0) { - release_request_id(r); - ftdm_log(FTDM_LOG_CRIT, "Failed to tx boost event [%s]\n", strerror(errno)); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - } - - } - break; - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } - break; - case FTDM_CHANNEL_STATE_HANGUP: - { - ftdm_set_sflag_locked(ftdmchan, SFLAG_HANGUP); - - if (ftdm_test_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG) || ftdm_test_sflag(ftdmchan, SFLAG_TERMINATING)) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); - } else { - ftdm_set_sflag_locked(ftdmchan, SFLAG_SENT_FINAL_MSG); - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_ANSWERED) || - ftdm_test_flag(ftdmchan, FTDM_CHANNEL_PROGRESS) || - ftdm_test_flag(ftdmchan, FTDM_CHANNEL_MEDIA) || - ftdm_test_sflag(ftdmchan, SFLAG_RECVD_ACK)) { - sangomabc_exec_command(mcon, - BOOST_SPAN(ftdmchan), - BOOST_CHAN(ftdmchan), - 0, - SIGBOOST_EVENT_CALL_STOPPED, - ftdmchan->caller_data.hangup_cause, 0); - } else { - sangomabc_exec_command(mcon, - BOOST_SPAN(ftdmchan), - BOOST_CHAN(ftdmchan), - 0, - SIGBOOST_EVENT_CALL_START_NACK, - ftdmchan->caller_data.hangup_cause, 0); - } - } - } - break; - case FTDM_CHANNEL_STATE_TERMINATING: - { - ftdm_set_sflag_locked(ftdmchan, SFLAG_TERMINATING); - sig.event_id = FTDM_SIGEVENT_STOP; - status = ftdm_span_send_signal(ftdmchan->span, &sig); - } - break; - case FTDM_CHANNEL_STATE_IN_LOOP: - { - /* nothing to do, we sent the FTDM_COMMAND_ENABLE_LOOP command in handle_call_loop_start() right away */ - } - break; - default: - break; - } - return FTDM_SUCCESS; -} - -/** - * \brief Initialises outgoing requests array - */ -static __inline__ void init_outgoing_array(void) -{ - memset(&OUTBOUND_REQUESTS, 0, sizeof(OUTBOUND_REQUESTS)); -} - -/** - * \brief Checks current state on a span - * \param span Span to check status on - */ -static __inline__ void check_state(ftdm_span_t *span) -{ - ftdm_channel_t *ftdmchan = NULL; - ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data; - int susp = ftdm_test_flag(span, FTDM_SPAN_SUSPENDED); - - if (susp && ftdm_check_state_all(span, FTDM_CHANNEL_STATE_DOWN)) { - susp = 0; - } - - if (ftdm_test_flag(span, FTDM_SPAN_STATE_CHANGE) || susp) { - uint32_t j; - ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE); - if (susp) { - for(j = 1; j <= span->chan_count; j++) { - if (ftdm_test_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE) || susp) { - ftdm_mutex_lock(span->channels[j]->mutex); - ftdm_clear_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE); - if (susp && span->channels[j]->state != FTDM_CHANNEL_STATE_DOWN) { - ftdm_set_state(span->channels[j], FTDM_CHANNEL_STATE_RESTART); - } - ftdm_channel_advance_states(span->channels[j]); - ftdm_mutex_unlock(span->channels[j]->mutex); - } - } - } else { - while ((ftdmchan = ftdm_queue_dequeue(span->pendingchans))) { - /* it can happen that someone else processed the chan states - * but without taking the chan out of the queue, so check th - * flag before advancing the state */ - ftdm_mutex_lock(ftdmchan->mutex); - ftdm_channel_advance_states(ftdmchan); - ftdm_mutex_unlock(ftdmchan->mutex); - } - } - } - - if (ftdm_test_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RESTARTING)) { - if (ftdm_check_state_all(span, FTDM_CHANNEL_STATE_DOWN)) { - sangomabc_exec_command(&sangoma_boost_data->mcon, - 0, - 0, - -1, - SIGBOOST_EVENT_SYSTEM_RESTART_ACK, - 0, 0); - ftdm_clear_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RESTARTING); - ftdm_clear_flag_locked(span, FTDM_SPAN_SUSPENDED); - ftdm_clear_flag((&sangoma_boost_data->mcon), MSU_FLAG_DOWN); - init_outgoing_array(); - } - } -} - - -/** - * \brief Checks for events on a span - * \param span Span to check for events - */ -static __inline__ ftdm_status_t check_events(ftdm_span_t *span, int ms_timeout) -{ - ftdm_status_t status; - ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data; - - status = ftdm_span_poll_event(span, ms_timeout, NULL); - - switch(status) { - case FTDM_SUCCESS: - { - ftdm_event_t *event; - while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) { - switch (event->enum_id) { - case FTDM_OOB_ALARM_TRAP: - if (sangoma_boost_data->sigmod) { - sangoma_boost_data->sigmod->on_hw_link_status_change(event->channel, FTDM_HW_LINK_DISCONNECTED); - } - break; - case FTDM_OOB_ALARM_CLEAR: - if (sangoma_boost_data->sigmod) { - sangoma_boost_data->sigmod->on_hw_link_status_change(event->channel, FTDM_HW_LINK_CONNECTED); - } - break; - } - } - } - break; - case FTDM_FAIL: - { - if (!ftdm_running()) { - break; - } - ftdm_log(FTDM_LOG_ERROR, "Boost Check Event Failure Failure: %s\n", span->last_error); - return FTDM_FAIL; - } - break; - default: - break; - } - - return FTDM_SUCCESS; -} - -/** - * \brief Main thread function for sangoma boost span (monitor) - * \param me Current thread - * \param obj Span to run in this thread - */ -static void *ftdm_sangoma_events_run(ftdm_thread_t *me, void *obj) -{ - ftdm_span_t *span = (ftdm_span_t *) obj; - ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data; - unsigned errs = 0; - - while (ftdm_test_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_EVENTS_RUNNING) && ftdm_running()) { - if (check_events(span, 100) != FTDM_SUCCESS) { - if (errs++ > 50) { - ftdm_log(FTDM_LOG_ERROR, "Too many event errors, quitting sangoma events thread\n"); - return NULL; - } - } - } - - ftdm_log(FTDM_LOG_DEBUG, "Sangoma Boost Events thread ended.\n"); - - ftdm_clear_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_EVENTS_RUNNING); - - return NULL; -} - -static ftdm_status_t ftdm_boost_connection_open(ftdm_span_t *span) -{ - ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data; - if (sangoma_boost_data->sigmod) { - if (sangoma_boost_data->sigmod->start_span(span) != FTDM_SUCCESS) { - return FTDM_FAIL; - } - ftdm_clear_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RESTARTING); - ftdm_clear_flag_locked(span, FTDM_SPAN_SUSPENDED); - ftdm_clear_flag((&sangoma_boost_data->mcon), MSU_FLAG_DOWN); - } - - sangoma_boost_data->pcon = sangoma_boost_data->mcon; - - /* when sigmod is present, all arguments: local_ip etc, are ignored by sangomabc_connection_open */ - if (sangomabc_connection_open(&sangoma_boost_data->mcon, - sangoma_boost_data->mcon.cfg.local_ip, - sangoma_boost_data->mcon.cfg.local_port, - sangoma_boost_data->mcon.cfg.remote_ip, - sangoma_boost_data->mcon.cfg.remote_port) < 0) { - ftdm_log(FTDM_LOG_ERROR, "Error: Opening MCON Socket [%d] %s\n", sangoma_boost_data->mcon.socket, strerror(errno)); - return FTDM_FAIL; - } - - if (sangomabc_connection_open(&sangoma_boost_data->pcon, - sangoma_boost_data->pcon.cfg.local_ip, - ++sangoma_boost_data->pcon.cfg.local_port, - sangoma_boost_data->pcon.cfg.remote_ip, - ++sangoma_boost_data->pcon.cfg.remote_port) < 0) { - ftdm_log(FTDM_LOG_ERROR, "Error: Opening PCON Socket [%d] %s\n", sangoma_boost_data->pcon.socket, strerror(errno)); - return FTDM_FAIL; - } - - /* try to create the boost sockets interrupt objects */ - if (ftdm_interrupt_create(&sangoma_boost_data->pcon.sock_interrupt, sangoma_boost_data->pcon.socket) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Span %s could not create its boost msock interrupt!\n", span->name); - return FTDM_FAIL; - } - - if (ftdm_interrupt_create(&sangoma_boost_data->mcon.sock_interrupt, sangoma_boost_data->mcon.socket) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Span %s could not create its boost psock interrupt!\n", span->name); - return FTDM_FAIL; - } - - return FTDM_SUCCESS; -} - -/*! - \brief wait for a boost event - \return -1 on error, 0 on timeout, 1 when there are events - */ -static int ftdm_boost_wait_event(ftdm_span_t *span) -{ - ftdm_status_t res; - ftdm_interrupt_t *ints[3]; - int numints; - ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data; - - ftdm_queue_get_interrupt(span->pendingchans, &ints[0]); - numints = 1; - /* if in queue mode wait for both the pendingchans queue and the boost msg queue */ - if (sangoma_boost_data->sigmod) { - ftdm_queue_get_interrupt(sangoma_boost_data->boost_queue, &ints[1]); - numints = 2; - } -#ifndef __WINDOWS__ - else { - /* socket mode ... */ - ints[1] = sangoma_boost_data->mcon.sock_interrupt; - ints[2] = sangoma_boost_data->pcon.sock_interrupt; - numints = 3; - sangoma_boost_data->iteration = 0; - } -#endif - res = ftdm_interrupt_multiple_wait(ints, numints, 100); - if (FTDM_SUCCESS != res && FTDM_TIMEOUT != res) { - ftdm_log(FTDM_LOG_CRIT, "Unexpected return value from interrupt waiting: %d\n", res); - return -1; - } - return 0; -} - - -static sangomabc_event_t *ftdm_boost_read_event(ftdm_span_t *span) -{ - sangomabc_event_t *event = NULL; - sangomabc_connection_t *mcon, *pcon; - ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data; - - mcon = &sangoma_boost_data->mcon; - pcon = &sangoma_boost_data->pcon; - - event = sangomabc_connection_readp(pcon, sangoma_boost_data->iteration); - - /* if there is no event and this is not a sigmod-driven span it's time to try the other connection for events */ - if (!event && !sangoma_boost_data->sigmod) { - event = sangomabc_connection_read(mcon, sangoma_boost_data->iteration); - } - - return event; -} - -/** - * \brief Main thread function for sangoma boost span (monitor) - * \param me Current thread - * \param obj Span to run in this thread - */ -static void *ftdm_sangoma_boost_run(ftdm_thread_t *me, void *obj) -{ - ftdm_span_t *span = (ftdm_span_t *) obj; - sangomabc_connection_t *mcon, *pcon; - ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data; - - mcon = &sangoma_boost_data->mcon; - pcon = &sangoma_boost_data->pcon; - - /* sigmod overrides socket functionality if not null */ - if (sangoma_boost_data->sigmod) { - mcon->span = span; - pcon->span = span; - /* everything could be retrieved through span, but let's use shortcuts */ - mcon->sigmod = sangoma_boost_data->sigmod; - pcon->sigmod = sangoma_boost_data->sigmod; - mcon->boost_queue = sangoma_boost_data->boost_queue; - pcon->boost_queue = sangoma_boost_data->boost_queue; - } - - if (ftdm_boost_connection_open(span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "ftdm_boost_connection_open failed\n"); - goto end; - } - - init_outgoing_array(); - if (!sangoma_boost_data->sigmod) { - sangomabc_exec_commandp(pcon, - 0, - 0, - -1, - SIGBOOST_EVENT_SYSTEM_RESTART, - 0); - ftdm_set_flag(mcon, MSU_FLAG_DOWN); - } - - while (ftdm_test_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RUNNING)) { - sangomabc_event_t *event = NULL; - - if (!ftdm_running()) { - if (!sangoma_boost_data->sigmod) { - sangomabc_exec_commandp(pcon, - 0, - 0, - -1, - SIGBOOST_EVENT_SYSTEM_RESTART, - 0); - ftdm_set_flag(mcon, MSU_FLAG_DOWN); - } - ftdm_log(FTDM_LOG_DEBUG, "ftdm is no longer running\n"); - break; - } - - if (ftdm_boost_wait_event(span) < 0) { - ftdm_log(FTDM_LOG_ERROR, "ftdm_boost_wait_event failed\n"); - } - - while ((event = ftdm_boost_read_event(span))) { - parse_sangoma_event(span, pcon, (sangomabc_short_event_t*)event); - sangoma_boost_data->iteration++; - } - - check_state(span); - } - -end: - if (!sangoma_boost_data->sigmod) { - sangomabc_connection_close(&sangoma_boost_data->mcon); - sangomabc_connection_close(&sangoma_boost_data->pcon); - } - - ftdm_clear_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RUNNING); - - ftdm_log(FTDM_LOG_DEBUG, "Sangoma Boost thread ended.\n"); - return NULL; -} - -#if 0 -static int sigmod_ss7box_isup_exec_cmd(ftdm_stream_handle_t *stream, char *cmd) -{ - FILE *fp; - int status=0; - char path[1024]; - - fp = popen(cmd, "r"); - if (fp == NULL) { - stream->write_function(stream, "%s: -ERR failed to execute cmd: %s\n", - __FILE__,cmd); - return -1; - } - - while (fgets(path, sizeof(path)-1, fp) != NULL) { - path[sizeof(path)-1]='\0'; - stream->write_function(stream,"%s", path); - } - - - status = pclose(fp); - if (status == -1) { - /* Error reported by pclose() */ - } else { - /* Use macros described under wait() to inspect `status' in order - to determine success/failure of command executed by popen() */ - } - - return status; -} -#endif - -static void ftdm_cli_span_state_cmd(ftdm_span_t *span, char *state) -{ - unsigned int j; - int cnt=0; - ftdm_channel_state_t state_e = ftdm_str2ftdm_channel_state(state); - if (state_e == FTDM_CHANNEL_STATE_INVALID) { - ftdm_log(FTDM_LOG_CRIT, "Checking for channels not in the INVALID state is probably not what you want\n"); - } - for(j = 1; j <= span->chan_count; j++) { - if (span->channels[j]->state != state_e) { - ftdm_channel_t *ftdmchan = span->channels[j]; - ftdm_log(FTDM_LOG_CRIT, "Channel %i s%dc%d State=%s\n", - j, ftdmchan->physical_span_id-1, ftdmchan->physical_chan_id-1, ftdm_channel_state2str(ftdmchan->state)); - cnt++; - } - } - ftdm_log(FTDM_LOG_CRIT, "Total Channel Cnt %i\n",cnt); -} - -#define FTDM_BOOST_SYNTAX "list sigmods | | tracelevel " -/** - * \brief API function to kill or debug a sangoma_boost span - * \param stream API stream handler - * \param data String containing argurments - * \return Flags - */ -static FIO_API_FUNCTION(ftdm_sangoma_boost_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], "list")) { - if (!strcasecmp(argv[1], "sigmods")) { - if (ftdm_sangoma_boost_list_sigmods(stream) != FTDM_SUCCESS) { - stream->write_function(stream, "-ERR failed to list sigmods\n"); - goto done; - } - goto done; - } - - if (!strcasecmp(argv[1], "ids")) { - print_request_ids(); - goto done; - } - } else if (!strcasecmp(argv[0], "tracelevel")) { - ftdm_status_t status; - const char *levelname = NULL; - int dbglevel; - ftdm_sangoma_boost_data_t *sangoma_boost_data; - ftdm_span_t *span; - - if (argc <= 2) { - stream->write_function(stream, "-ERR usage: tracelevel \n"); - goto done; - } - - status = ftdm_span_find_by_name(argv[1], &span); - if (FTDM_SUCCESS != status) { - stream->write_function(stream, "-ERR failed to find span by name %s\n", argv[1]); - goto done; - } - - if (span->signal_type != FTDM_SIGTYPE_SANGOMABOOST) { - stream->write_function(stream, "-ERR span %s is not of boost type\n", argv[1]); - goto done; - } - - for (dbglevel = 0; (levelname = FTDM_LEVEL_NAMES[dbglevel]); dbglevel++) { - if (!strcasecmp(levelname, argv[2])) { - break; - } - } - - if (!levelname) { - stream->write_function(stream, "-ERR invalid log level %s\n", argv[2]); - goto done; - } - - sangoma_boost_data = span->signal_data; - sangoma_boost_data->pcon.debuglevel = dbglevel; - sangoma_boost_data->mcon.debuglevel = dbglevel; - stream->write_function(stream, "+OK span %s has now trace level %s\n", argv[1], FTDM_LEVEL_NAMES[dbglevel]); - goto done; -#ifndef __WINDOWS__ -#if 0 -/* NC: This code crashes the kernel due to fork on heavy fs load */ - } else if (!strcasecmp(argv[0], "ss7box_isupd_ckt")) { - - if (!strcasecmp(argv[1], "used")) { - stream->write_function(stream, "ss7box_isupd: in use\n", FTDM_BOOST_SYNTAX); - sigmod_ss7box_isup_exec_cmd(stream, (char*) "ckt_report.sh inuse"); - } else if (!strcasecmp(argv[1], "reset")) { - stream->write_function(stream, "ss7box_isupd: in reset\n", FTDM_BOOST_SYNTAX); - sigmod_ss7box_isup_exec_cmd(stream, (char*) "ckt_report.sh reset"); - } else if (!strcasecmp(argv[1], "ready")) { - stream->write_function(stream, "ss7box_isupd: ready \n", FTDM_BOOST_SYNTAX); - sigmod_ss7box_isup_exec_cmd(stream, (char*) "ckt_report.sh free"); - } else { - stream->write_function(stream, "ss7box_isupd: list\n", FTDM_BOOST_SYNTAX); - sigmod_ss7box_isup_exec_cmd(stream, (char*) "ckt_report.sh"); - } - - goto done; -#endif -#endif - - } else if (!strcasecmp(argv[0], "span")) { - int err; - sangomabc_connection_t *pcon; - ftdm_sangoma_boost_data_t *sangoma_boost_data; - ftdm_span_t *span; - - if (argc <= 2) { - stream->write_function(stream, "-ERR invalid span usage: span \n"); - goto done; - } - - err = ftdm_span_find_by_name(argv[1], &span); - if (FTDM_SUCCESS != err) { - stream->write_function(stream, "-ERR failed to find span by name %s\n",argv[1]); - goto done; - } - - if (!strcasecmp(argv[2], "restart")) { - sangoma_boost_data = span->signal_data; - pcon = &sangoma_boost_data->pcon; - - /* No need to set any span flags because - our RESTART will generate a RESTART from the sig daemon */ - sangomabc_exec_commandp(pcon, - 0, - 0, - -1, - SIGBOOST_EVENT_SYSTEM_RESTART, - 0); - } else if (!strcasecmp(argv[2], "state")) { - if (argc <= 3) { - stream->write_function(stream, "-ERR invalid span state: span state \n"); - goto done; - } - ftdm_cli_span_state_cmd(span,argv[3]); - } - - goto done; - - } else { - boost_sigmod_interface_t *sigmod_iface = NULL; - sigmod_iface = hashtable_search(g_boost_modules_hash, argv[0]); - if (sigmod_iface) { - char *p = strchr(data, ' '); - if (++p) { - char* mydup = strdup(p); - if(sigmod_iface->exec_api == NULL) { - stream->write_function(stream, "%s does not support api functions\n", sigmod_iface->name); - goto done; - } - //stream->write_function(stream, "sigmod:%s command:%s\n", sigmod_iface->name, mydup); - if (sigmod_iface->exec_api(stream, mydup) != FTDM_SUCCESS) { - stream->write_function(stream, "-ERR:failed to execute command:%s\n", mydup); - } - free(mydup); - } - - goto done; - } else { - stream->write_function(stream, "-ERR: Could not find sigmod %s\n", argv[0]); - } - } - } - stream->write_function(stream, "-ERR: Usage: %s\n", FTDM_BOOST_SYNTAX); -done: - ftdm_safe_free(mycmd); - return FTDM_SUCCESS; -} - -/** - * \brief Loads sangoma_boost IO module - * \param fio FreeTDM IO interface - * \return Success - */ -static FIO_IO_LOAD_FUNCTION(ftdm_sangoma_boost_io_init) -{ - ftdm_assert(fio != NULL, "fio is NULL"); - memset(&ftdm_sangoma_boost_interface, 0, sizeof(ftdm_sangoma_boost_interface)); - - ftdm_sangoma_boost_interface.name = "boost"; - ftdm_sangoma_boost_interface.api = ftdm_sangoma_boost_api; - - *fio = &ftdm_sangoma_boost_interface; - - return FTDM_SUCCESS; -} - -/** - * \brief Loads sangoma boost signaling module - * \param fio FreeTDM IO interface - * \return Success - */ -static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_boost_init) -{ - g_boost_modules_hash = create_hashtable(10, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); - if (!g_boost_modules_hash) { - return FTDM_FAIL; - } - ftdm_mutex_create(&request_mutex); - ftdm_mutex_create(&g_boost_modules_mutex); - memset(&g_trunkgroups[0], 0, sizeof(g_trunkgroups)); - return FTDM_SUCCESS; -} - -static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_boost_destroy) -{ - ftdm_hash_iterator_t *i = NULL; - boost_sigmod_interface_t *sigmod = NULL; - const void *key = NULL; - void *val = NULL; - ftdm_dso_lib_t lib; - ftdm_log(FTDM_LOG_DEBUG, "Destroying sangoma boost module\n"); - for (i = hashtable_first(g_boost_modules_hash); i; i = hashtable_next(i)) { - hashtable_this(i, &key, NULL, &val); - if (key && val) { - sigmod = val; - lib = sigmod->pvt; - ftdm_log(FTDM_LOG_DEBUG, "destroying sigmod %s\n", sigmod->name); - sigmod->on_unload(); - ftdm_dso_destroy(&lib); - } - } - - hashtable_destroy(g_boost_modules_hash); - ftdm_mutex_destroy(&request_mutex); - ftdm_mutex_destroy(&g_boost_modules_mutex); - return FTDM_SUCCESS; -} - -static ftdm_status_t ftdm_sangoma_boost_start(ftdm_span_t *span) -{ - int err; - - ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data; - - ftdm_set_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RUNNING); - err = ftdm_thread_create_detached(ftdm_sangoma_boost_run, span); - if (err) { - ftdm_clear_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RUNNING); - return err; - } - - // launch the events thread to handle HW DTMF and possibly - // other events in the future - ftdm_set_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_EVENTS_RUNNING); - err = ftdm_thread_create_detached(ftdm_sangoma_events_run, span); - if (err) { - ftdm_clear_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_EVENTS_RUNNING); - ftdm_clear_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RUNNING); - } - - return err; -} - -static ftdm_status_t ftdm_sangoma_boost_stop(ftdm_span_t *span) -{ - int cnt = 50; - ftdm_status_t status = FTDM_SUCCESS; - ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data; - - if (sangoma_boost_data->sigmod) { - /* I think stopping the span before destroying the queue makes sense - otherwise may be boost events would still arrive when the queue is already destroyed! */ - status = sangoma_boost_data->sigmod->stop_span(span); - if (status != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Failed to stop span %s boost signaling\n", span->name); - return FTDM_FAIL; - } - ftdm_queue_enqueue(sangoma_boost_data->boost_queue, NULL); - } - - while (ftdm_test_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RUNNING) && cnt-- > 0) { - ftdm_log(FTDM_LOG_DEBUG, "Waiting for boost thread\n"); - ftdm_sleep(100); - } - - if (!cnt) { - ftdm_log(FTDM_LOG_CRIT, "it seems boost thread in span %s may be stuck, we may segfault :-(\n", span->name); - return FTDM_FAIL; - } - - cnt = 50; - while (ftdm_test_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_EVENTS_RUNNING) && cnt-- > 0) { - ftdm_log(FTDM_LOG_DEBUG, "Waiting for boost events thread\n"); - ftdm_sleep(100); - } - - if (!cnt) { - ftdm_log(FTDM_LOG_CRIT, "it seems boost events thread in span %s may be stuck, we may segfault :-(\n", span->name); - return FTDM_FAIL; - } - - if (sangoma_boost_data->sigmod) { - ftdm_queue_destroy(&sangoma_boost_data->boost_queue); - } - - return status; -} - -static ftdm_state_map_t boost_state_map = { - { - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_ANY_STATE}, - {FTDM_CHANNEL_STATE_RESTART, FTDM_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RESTART, FTDM_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DOWN, FTDM_END}, - {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_IDLE, FTDM_CHANNEL_STATE_HOLD, FTDM_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HOLD, FTDM_END}, - {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_PROGRESS, - FTDM_CHANNEL_STATE_IDLE, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_HANGUP, FTDM_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_IDLE, FTDM_CHANNEL_STATE_DIALING, FTDM_END}, - {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_PROGRESS, FTDM_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_IDLE, FTDM_CHANNEL_STATE_DIALING, FTDM_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_HANGUP, FTDM_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_END}, - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_UP, FTDM_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END} - }, - - /****************************************/ - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_ANY_STATE}, - {FTDM_CHANNEL_STATE_RESTART, FTDM_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RESTART, FTDM_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DOWN}, - {FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_IN_LOOP}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DOWN, FTDM_END}, - {FTDM_CHANNEL_STATE_RING, FTDM_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RING, FTDM_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA,FTDM_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_HANGUP, FTDM_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_UP, FTDM_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}, - }, - - - } -}; - -static BOOST_WRITE_MSG_FUNCTION(ftdm_boost_write_msg) -{ - sangomabc_short_event_t *shortmsg = NULL; - ftdm_sangoma_boost_data_t *sangoma_boost_data = NULL; - sangomabc_queue_element_t *element = NULL; - - ftdm_assert_return(msg != NULL, FTDM_FAIL, "Boost message to write was null"); - - if (!span) { - shortmsg = msg; - ftdm_log(FTDM_LOG_ERROR, "Unexpected boost message %d\n", shortmsg->event_id); - return FTDM_FAIL; - } - /* duplicate the event and enqueue it */ - element = ftdm_calloc(1, sizeof(*element)); - if (!element) { - return FTDM_FAIL; - } - memcpy(element->boostmsg, msg, msglen); - element->size = msglen; - - sangoma_boost_data = span->signal_data; - return ftdm_queue_enqueue(sangoma_boost_data->boost_queue, element); -} - -static BOOST_SIG_STATUS_CB_FUNCTION(ftdm_boost_sig_status_change) -{ - ftdm_sigmsg_t sig; - ftdm_log(FTDM_LOG_NOTICE, "%d:%d Signaling link status changed to %s\n", ftdmchan->span_id, ftdmchan->chan_id, 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); - return; -} - -static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(sangoma_boost_set_channel_sig_status) -{ - ftdm_sangoma_boost_data_t *sangoma_boost_data = ftdmchan->span->signal_data; - if (!sangoma_boost_data->sigmod) { - ftdm_log(FTDM_LOG_ERROR, "Cannot set signaling status in boost channel with no signaling module configured\n"); - return FTDM_FAIL; - } - if (!sangoma_boost_data->sigmod->set_channel_sig_status) { - ftdm_log(FTDM_LOG_ERROR, "Cannot set signaling status in boost channel: method not implemented\n"); - return FTDM_NOTIMPL; - } - return sangoma_boost_data->sigmod->set_channel_sig_status(ftdmchan, status); -} - -static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(sangoma_boost_get_channel_sig_status) -{ - ftdm_sangoma_boost_data_t *sangoma_boost_data = ftdmchan->span->signal_data; - if (!sangoma_boost_data->sigmod) { - return FTDM_FAIL; - } - if (!sangoma_boost_data->sigmod->get_channel_sig_status) { - return FTDM_NOTIMPL; - } - return sangoma_boost_data->sigmod->get_channel_sig_status(ftdmchan, status); -} - -static FIO_SPAN_SET_SIG_STATUS_FUNCTION(sangoma_boost_set_span_sig_status) -{ - ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data; - if (!sangoma_boost_data->sigmod) { - ftdm_log(FTDM_LOG_ERROR, "Cannot set signaling status in boost span with no signaling module configured\n"); - return FTDM_FAIL; - } - if (!sangoma_boost_data->sigmod->set_span_sig_status) { - ftdm_log(FTDM_LOG_ERROR, "Cannot set signaling status in boost span: method not implemented\n"); - return FTDM_NOTIMPL; - } - return sangoma_boost_data->sigmod->set_span_sig_status(span, status); -} - -static FIO_SPAN_GET_SIG_STATUS_FUNCTION(sangoma_boost_get_span_sig_status) -{ - ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data; - if (!sangoma_boost_data->sigmod) { - return FTDM_FAIL; - } - if (!sangoma_boost_data->sigmod->get_span_sig_status) { - ftdm_log(FTDM_LOG_ERROR, "Cannot get signaling status in boost span: method not implemented\n"); - return FTDM_NOTIMPL; - } - return sangoma_boost_data->sigmod->get_span_sig_status(span, status); -} - -/** - * \brief Initialises an sangoma boost 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_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_boost_configure_span) -{ -#define FAIL_CONFIG_RETURN(retstatus) \ - if (sangoma_boost_data) \ - ftdm_safe_free(sangoma_boost_data); \ - if (err) \ - ftdm_safe_free(err) \ - if (hash_locked) \ - ftdm_mutex_unlock(g_boost_modules_mutex); \ - if (lib) \ - ftdm_dso_destroy(&lib); \ - return retstatus; - - boost_sigmod_interface_t *sigmod_iface = NULL; - ftdm_sangoma_boost_data_t *sangoma_boost_data = NULL; - const char *local_ip = "127.0.0.65", *remote_ip = "127.0.0.66"; - const char *sigmod = NULL; - int local_port = 53000, remote_port = 53000; - const char *var = NULL, *val = NULL; - int hash_locked = 0; - ftdm_dso_lib_t lib = NULL; - char path[255] = ""; - char *err = NULL; - unsigned int j = 0; - unsigned paramindex = 0; - ftdm_status_t rc = FTDM_SUCCESS; - - for (; ftdm_parameters[paramindex].var; paramindex++) { - var = ftdm_parameters[paramindex].var; - val = ftdm_parameters[paramindex].val; - if (!strcasecmp(var, "sigmod")) { - sigmod = val; - } else if (!strcasecmp(var, "local_ip")) { - local_ip = val; - } else if (!strcasecmp(var, "remote_ip")) { - remote_ip = val; - } else if (!strcasecmp(var, "local_port")) { - local_port = atoi(val); - } else if (!strcasecmp(var, "remote_port")) { - remote_port = 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 (!sigmod) { - snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var); - FAIL_CONFIG_RETURN(FTDM_FAIL); - } - } - - if (!sigmod) { -#ifndef HAVE_NETINET_SCTP_H - ftdm_log(FTDM_LOG_CRIT, "No sigmod attribute in span %s, you must either specify a sigmod or re-compile with SCTP available to use socket mode boost!\n", span->name); - ftdm_set_string(span->last_error, "No sigmod configuration was set and there is no SCTP available!"); - FAIL_CONFIG_RETURN(FTDM_FAIL); -#else - if (!local_ip && local_port && remote_ip && remote_port && sig_cb) { - ftdm_set_string(span->last_error, "missing Sangoma boost IP parameters"); - FAIL_CONFIG_RETURN(FTDM_FAIL); - } -#endif - } - - sangoma_boost_data = ftdm_calloc(1, sizeof(*sangoma_boost_data)); - if (!sangoma_boost_data) { - FAIL_CONFIG_RETURN(FTDM_FAIL); - } - - /* WARNING: be sure to release this mutex on errors inside this if() */ - ftdm_mutex_lock(g_boost_modules_mutex); - hash_locked = 1; - if (sigmod && !(sigmod_iface = hashtable_search(g_boost_modules_hash, (void *)sigmod))) { - ftdm_build_dso_path(sigmod, path, sizeof(path)); - lib = ftdm_dso_open(path, &err); - if (!lib) { - ftdm_log(FTDM_LOG_ERROR, "Error loading Sangoma boost signaling module '%s': %s\n", path, err); - snprintf(span->last_error, sizeof(span->last_error), "Failed to load sangoma boost signaling module %s", path); - - FAIL_CONFIG_RETURN(FTDM_FAIL); - } - if (!(sigmod_iface = (boost_sigmod_interface_t *)ftdm_dso_func_sym(lib, BOOST_INTERFACE_NAME_STR, &err))) { - ftdm_log(FTDM_LOG_ERROR, "Failed to read Sangoma boost signaling module interface '%s': %s\n", path, err); - snprintf(span->last_error, sizeof(span->last_error), "Failed to read Sangoma boost signaling module interface '%s': %s", path, err); - - FAIL_CONFIG_RETURN(FTDM_FAIL); - } - rc = sigmod_iface->on_load(); - if (rc != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Failed to load Sangoma boost signaling module interface '%s': on_load method failed (%d)\n", path, rc); - FAIL_CONFIG_RETURN(FTDM_FAIL); - } - sigmod_iface->pvt = lib; - sigmod_iface->set_write_msg_cb(ftdm_boost_write_msg); - sigmod_iface->set_sig_status_cb(ftdm_boost_sig_status_change); - hashtable_insert(g_boost_modules_hash, (void *)sigmod_iface->name, sigmod_iface, HASHTABLE_FLAG_NONE); - lib = NULL; /* destroying the lib will be done when going down and NOT on FAIL_CONFIG_RETURN */ - } - ftdm_mutex_unlock(g_boost_modules_mutex); - hash_locked = 0; - - if (sigmod_iface) { - /* try to create the boost queue */ - if (ftdm_queue_create(&sangoma_boost_data->boost_queue, BOOST_QUEUE_SIZE) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Span %s could not create its boost queue!\n", span->name); - FAIL_CONFIG_RETURN(FTDM_FAIL); - } - ftdm_log(FTDM_LOG_NOTICE, "Span %s will use Sangoma Boost Signaling Module %s\n", span->name, sigmod_iface->name); - sangoma_boost_data->sigmod = sigmod_iface; - sigmod_iface->configure_span(span, ftdm_parameters); - } else { - ftdm_log(FTDM_LOG_NOTICE, "Span %s will use boost socket mode\n", span->name); - ftdm_set_string(sangoma_boost_data->mcon.cfg.local_ip, local_ip); - sangoma_boost_data->mcon.cfg.local_port = local_port; - ftdm_set_string(sangoma_boost_data->mcon.cfg.remote_ip, remote_ip); - sangoma_boost_data->mcon.cfg.remote_port = remote_port; - } - - for (j = 1; j <= span->chan_count; j++) { - span->channels[j]->call_data = ftdm_calloc(1, sizeof(sangoma_boost_call_t)); - if (!span->channels[j]->call_data) { - FAIL_CONFIG_RETURN(FTDM_FAIL); - } - } - - span->signal_cb = sig_cb; - span->start = ftdm_sangoma_boost_start; - span->stop = ftdm_sangoma_boost_stop; - span->signal_data = sangoma_boost_data; - span->signal_type = FTDM_SIGTYPE_SANGOMABOOST; - span->outgoing_call = sangoma_boost_outgoing_call; - span->channel_request = sangoma_boost_channel_request; - span->get_channel_sig_status = sangoma_boost_get_channel_sig_status; - span->set_channel_sig_status = sangoma_boost_set_channel_sig_status; - span->get_span_sig_status = sangoma_boost_get_span_sig_status; - span->set_span_sig_status = sangoma_boost_set_span_sig_status; - span->state_map = &boost_state_map; - span->state_processor = state_advance; - sangoma_boost_data->mcon.debuglevel = FTDM_LOG_LEVEL_DEBUG; - sangoma_boost_data->pcon.debuglevel = FTDM_LOG_LEVEL_DEBUG; - ftdm_clear_flag(span, FTDM_SPAN_SUGGEST_CHAN_ID); - ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE); - if (sigmod_iface) { - /* the core will do the hunting */ - span->channel_request = NULL; - } - ftdm_set_flag_locked(span, FTDM_SPAN_SUSPENDED); - return FTDM_SUCCESS; -} - -static ftdm_status_t ftdm_sangoma_boost_list_sigmods(ftdm_stream_handle_t *stream) -{ - ftdm_hash_iterator_t *i = NULL; - boost_sigmod_interface_t *sigmod_iface = NULL; - const void *key = NULL; - void *val = NULL; - - stream->write_function(stream, "List of loaded sigmod modules:\n"); - for (i = hashtable_first(g_boost_modules_hash); i; i = hashtable_next(i)) { - hashtable_this(i, &key, NULL, &val); - if (key && val) { - sigmod_iface = val; - stream->write_function(stream, " %s\n", sigmod_iface->name); - } - } - stream->write_function(stream, "\n"); - return FTDM_SUCCESS; -} - -/** - * \brief FreeTDM sangoma boost signaling module definition - */ -EX_DECLARE_DATA ftdm_module_t ftdm_module = { - /*.name =*/ "sangoma_boost", - /*.io_load =*/ ftdm_sangoma_boost_io_init, - /*.io_unload =*/ NULL, - /*.sig_load = */ ftdm_sangoma_boost_init, - /*.sig_configure =*/ NULL, - /*.sig_unload = */ftdm_sangoma_boost_destroy, - /*.configure_span_signaling = */ ftdm_sangoma_boost_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: - */ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sangoma_boost_client.c b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sangoma_boost_client.c deleted file mode 100644 index 6ddb74d253..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sangoma_boost_client.c +++ /dev/null @@ -1,589 +0,0 @@ -/* - * Copyright (c) 2007, Anthony Minessale II, Nenad Corbic - * 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 _GNU_SOURCE - -#if HAVE_NETDB_H -#include -#endif - -#include "freetdm.h" -#include "sangoma_boost_client.h" - -#ifndef HAVE_GETHOSTBYNAME_R -extern int gethostbyname_r (const char *__name, - struct hostent *__result_buf, - char *__buf, size_t __buflen, - struct hostent **__result, - int *__h_errnop); -#endif - -struct sangomabc_map { - uint32_t event_id; - const char *name; -}; - -static struct sangomabc_map sangomabc_table[] = { - {SIGBOOST_EVENT_CALL_START, "CALL_START"}, - {SIGBOOST_EVENT_CALL_START_ACK, "CALL_START_ACK"}, - {SIGBOOST_EVENT_CALL_START_NACK, "CALL_START_NACK"}, - {SIGBOOST_EVENT_CALL_PROGRESS, "CALL PROGRESS"}, - {SIGBOOST_EVENT_CALL_START_NACK_ACK, "CALL_START_NACK_ACK"}, - {SIGBOOST_EVENT_CALL_ANSWERED, "CALL_ANSWERED"}, - {SIGBOOST_EVENT_CALL_STOPPED, "CALL_STOPPED"}, - {SIGBOOST_EVENT_CALL_STOPPED_ACK, "CALL_STOPPED_ACK"}, - {SIGBOOST_EVENT_CALL_RELEASED, "CALL_RELEASED"}, - {SIGBOOST_EVENT_SYSTEM_RESTART, "SYSTEM_RESTART"}, - {SIGBOOST_EVENT_SYSTEM_RESTART_ACK, "SYSTEM_RESTART_ACK"}, - {SIGBOOST_EVENT_HEARTBEAT, "HEARTBEAT"}, - {SIGBOOST_EVENT_INSERT_CHECK_LOOP, "LOOP START"}, - {SIGBOOST_EVENT_REMOVE_CHECK_LOOP, "LOOP STOP"}, - {SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE, "AUTO_CALL_GAP_ABATE"}, - {SIGBOOST_EVENT_DIGIT_IN, "DIGIT_IN"} -}; - - - -static void sangomabc_print_event_call(sangomabc_connection_t *mcon, sangomabc_event_t *event, int priority, int dir, const char *file, const char *func, int line) -{ - if (event->event_id == SIGBOOST_EVENT_HEARTBEAT) - return; - - ftdm_log(file, func, line, mcon->debuglevel, "%s EVENT (%s): %s:(%X) [w%dg%d] CSid=%i Seq=%i Cn=[%s] Cd=[%s] Ci=[%s] Rdnis=[%s]\n", - dir ? "TX":"RX", - priority ? "P":"N", - sangomabc_event_id_name(event->event_id), - event->event_id, - BOOST_EVENT_SPAN(mcon->sigmod, event), - BOOST_EVENT_CHAN(mcon->sigmod, event), - event->call_setup_id, - event->fseqno, - strlen(event->calling_name)?event->calling_name:"N/A", - (event->called_number_digits_count ? (char *) event->called_number_digits : "N/A"), - (event->calling_number_digits_count ? (char *) event->calling_number_digits : "N/A"), - event->isup_in_rdnis); - -} -static void sangomabc_print_event_short(sangomabc_connection_t *mcon, sangomabc_short_event_t *event, int priority, int dir, const char *file, const char *func, int line) -{ - if (event->event_id == SIGBOOST_EVENT_HEARTBEAT) - return; - ftdm_log(file, func, line, mcon->debuglevel, "%s EVENT (%s): %s:(%X) [s%dc%d] Rc=%i CSid=%i Seq=%i \n", - dir ? "TX":"RX", - priority ? "P":"N", - sangomabc_event_id_name(event->event_id), - event->event_id, - BOOST_EVENT_SPAN(mcon->sigmod, event), - BOOST_EVENT_CHAN(mcon->sigmod, event), - event->release_cause, - event->call_setup_id, - event->fseqno); -} - - -static int create_conn_socket(sangomabc_connection_t *mcon, char *local_ip, int local_port, char *ip, int port) -{ -#ifndef WIN32 - int rc; - struct hostent *result, *local_result; - char buf[512], local_buf[512]; - int err = 0, local_err = 0; - - if (mcon->sigmod) { - ftdm_log(FTDM_LOG_WARNING, "I should not be called on a sigmod-managed connection!\n"); - return 0; - } - - memset(&mcon->remote_hp, 0, sizeof(mcon->remote_hp)); - memset(&mcon->local_hp, 0, sizeof(mcon->local_hp)); -#ifdef HAVE_NETINET_SCTP_H - ftdm_log(FTDM_LOG_DEBUG, "Creating SCTP socket L=%s:%d R=%s:%d\n", - local_ip, local_port, ip, port); - mcon->socket = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); -#else - ftdm_log(FTDM_LOG_DEBUG, "Creating UDP socket L=%s:%d R=%s:%d\n", - local_ip, local_port, ip, port); - mcon->socket = socket(AF_INET, SOCK_DGRAM, 0); -#endif - - if (mcon->socket >= 0) { - int flag; - - flag = 1; -#ifdef HAVE_GETHOSTBYNAME_R_FIVE - gethostbyname_r(ip, &mcon->remote_hp, buf, sizeof(buf), &err); - gethostbyname_r(local_ip, &mcon->local_hp, local_buf, sizeof(local_buf), &local_err); - if (!err && !local_err) { -#else - gethostbyname_r(ip, &mcon->remote_hp, buf, sizeof(buf), &result, &err); - gethostbyname_r(local_ip, &mcon->local_hp, local_buf, sizeof(local_buf), &local_result, &local_err); - if (result && local_result) { -#endif - mcon->remote_addr.sin_family = mcon->remote_hp.h_addrtype; - memcpy((char *) &mcon->remote_addr.sin_addr.s_addr, mcon->remote_hp.h_addr_list[0], mcon->remote_hp.h_length); - mcon->remote_addr.sin_port = htons(port); - - mcon->local_addr.sin_family = mcon->local_hp.h_addrtype; - memcpy((char *) &mcon->local_addr.sin_addr.s_addr, mcon->local_hp.h_addr_list[0], mcon->local_hp.h_length); - mcon->local_addr.sin_port = htons(local_port); - -#ifdef HAVE_NETINET_SCTP_H - setsockopt(mcon->socket, IPPROTO_SCTP, SCTP_NODELAY, - (char *)&flag, sizeof(int)); -#endif - - if ((rc = bind(mcon->socket, - (struct sockaddr *) &mcon->local_addr, - sizeof(mcon->local_addr))) < 0) { - close(mcon->socket); - mcon->socket = -1; - } else { -#ifdef HAVE_NETINET_SCTP_H - rc=listen(mcon->socket, 100); - if (rc) { - close(mcon->socket); - mcon->socket = -1; - } -#endif - } - } - } - - return mcon->socket; -#else - return 0; -#endif // ifndef WIN32 -} - -int sangomabc_connection_close(sangomabc_connection_t *mcon) -{ -#ifndef WIN32 - if (mcon->sigmod) { - ftdm_log(FTDM_LOG_WARNING, "I should not be called on a sigmod-managed connection!\n"); - return 0; - } - if (mcon->socket > -1) { - close(mcon->socket); - } - - if (mcon->mutex) { - ftdm_mutex_lock(mcon->mutex); - ftdm_mutex_unlock(mcon->mutex); - ftdm_mutex_destroy(&mcon->mutex); - } - memset(mcon, 0, sizeof(*mcon)); - mcon->socket = -1; -#endif - return 0; -} - -int sangomabc_connection_open(sangomabc_connection_t *mcon, char *local_ip, int local_port, char *ip, int port) -{ - ftdm_mutex_create(&mcon->mutex); - if (mcon->sigmod) { - /*value of mcon->socket will be ignored in sigmod mode */ - return 0; - } -#ifndef WIN32 - create_conn_socket(mcon, local_ip, local_port, ip, port); - return mcon->socket; -#else - return 0; -#endif -} - - -int sangomabc_exec_command(sangomabc_connection_t *mcon, int span, int chan, int id, int cmd, int cause, int flags) -{ - sangomabc_event_t *oevent; - sangomabc_short_event_t sevent; - sangomabc_event_t fevent; - int retry = 5; - - if (boost_full_event(cmd)) { - sangomabc_event_init((void *)&fevent, cmd, chan, span); - oevent = &fevent; - } else { - sangomabc_event_init(&sevent, cmd, chan, span); - sevent.release_cause = (uint8_t)cause; - oevent = (sangomabc_event_t *)&sevent; - } - oevent->flags = flags; - - if (cmd == SIGBOOST_EVENT_SYSTEM_RESTART || cmd == SIGBOOST_EVENT_SYSTEM_RESTART_ACK) { - mcon->rxseq_reset = 1; - mcon->txseq = 0; - mcon->rxseq = 0; - mcon->txwindow = 0; - } - - if (id >= 0) { - oevent->call_setup_id = (uint16_t)id; - } - - while (sangomabc_connection_write(mcon, (sangomabc_event_t*)oevent) <= 0) { - if (--retry <= 0) { - ftdm_log(FTDM_LOG_CRIT, "Failed to tx on boost socket: %s\n", strerror(errno)); - return -1; - } else { - ftdm_log(FTDM_LOG_WARNING, "Failed to tx on boost socket: %s :retry %i\n", strerror(errno), retry); - ftdm_sleep(1); - } - } - - return 0; -} - - -int sangomabc_exec_commandp(sangomabc_connection_t *pcon, int span, int chan, int id, int cmd, int cause) -{ - sangomabc_short_event_t oevent; - int retry = 5; - - sangomabc_event_init(&oevent, cmd, chan, span); - oevent.release_cause = (uint8_t)cause; - - if (id >= 0) { - oevent.call_setup_id = (uint16_t)id; - } - - while (sangomabc_connection_writep(pcon, (sangomabc_event_t*)&oevent) <= 0) { - if (--retry <= 0) { - ftdm_log(FTDM_LOG_CRIT, "Failed to tx on boost socket: %s\n", strerror(errno)); - return -1; - } else { - ftdm_log(FTDM_LOG_WARNING, "Failed to tx on boost socket: %s :retry %i\n", strerror(errno), retry); - ftdm_sleep(1); - } - } - - return 0; -} - -sangomabc_event_t *__sangomabc_connection_read(sangomabc_connection_t *mcon, int iteration, const char *file, const char *func, int line) -{ -#ifndef WIN32 - unsigned int fromlen = sizeof(struct sockaddr_in); -#endif - int bytes = 0; - int msg_ok = 0; - sangomabc_queue_element_t *e = NULL; - - if (mcon->sigmod) { - e = ftdm_queue_dequeue(mcon->boost_queue); - if (e) { - bytes = (int)e->size; - memcpy(&mcon->event, e->boostmsg, bytes); - ftdm_safe_free(e); - } - } -#ifndef WIN32 - else { - bytes = recvfrom(mcon->socket, &mcon->event, sizeof(mcon->event), MSG_DONTWAIT, - (struct sockaddr *) &mcon->local_addr, &fromlen); - } -#endif - if (bytes <= 0) { - return NULL; - } - - if (mcon->event.version != SIGBOOST_VERSION) { - ftdm_log(FTDM_LOG_CRIT, "Invalid Boost Version %i Expecting %i\n",mcon->event.version, SIGBOOST_VERSION); - } - - if ((bytes >= MIN_SIZE_CALLSTART_MSG) && boost_full_event(mcon->event.event_id)) { - msg_ok=1; - - } else if (bytes == sizeof(sangomabc_short_event_t)) { - msg_ok=1; - - } else { - msg_ok=0; - } - - if (msg_ok) { - if (sangomabc_test_flag(mcon, MSU_FLAG_DOWN)) { - if (mcon->event.event_id != SIGBOOST_EVENT_SYSTEM_RESTART && - mcon->event.event_id != SIGBOOST_EVENT_SYSTEM_RESTART_ACK && - mcon->event.event_id != SIGBOOST_EVENT_HEARTBEAT) { - ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "Not reading packets when connection is down. [%s]\n", - sangomabc_event_id_name(mcon->event.event_id)); - return NULL; - } - } - - if (boost_full_event(mcon->event.event_id)) { - sangomabc_print_event_call(mcon, &mcon->event, 0, 0, file, func, line); - } else { - sangomabc_print_event_short(mcon, (sangomabc_short_event_t*)&mcon->event, 0, 0, file, func, line); - } - -#if 0 -/* NC: NOT USED ANY MORE */ - if (mcon->rxseq_reset) { - //if (mcon->event.event_id == SIGBOOST_EVENT_SYSTEM_RESTART_ACK) { - ftdm_log(FTDM_LOG_DEBUG, "Rx sync ok\n"); - mcon->rxseq = mcon->event.fseqno; - return &mcon->event; - //} - errno=EAGAIN; - ftdm_log(FTDM_LOG_DEBUG, "Waiting for rx sync...\n"); - return NULL; - } -#endif - - mcon->txwindow = mcon->txseq - mcon->event.bseqno; - mcon->rxseq++; - -#if 0 - if (mcon->rxseq != mcon->event.fseqno) { - ftdm_log(FTDM_LOG_CRIT, "Invalid Sequence Number Expect=%i Rx=%i\n", mcon->rxseq, mcon->event.fseqno); - return NULL; - } -#endif - - return &mcon->event; - } else { - if (iteration == 0) { - ftdm_log(FTDM_LOG_CRIT, "NC - Invalid Event length from boost rxlen=%i evsz=%i\n", bytes, sizeof(mcon->event)); - return NULL; - } - } - - return NULL; -} - -sangomabc_event_t *__sangomabc_connection_readp(sangomabc_connection_t *mcon, int iteration, const char *file, const char *func, int line) -{ -#ifndef WIN32 - unsigned int fromlen = sizeof(struct sockaddr_in); -#endif - int bytes = 0; - - if (mcon->sigmod) { - /* priority stuff is handled just the same when there is a sigmod */ - return sangomabc_connection_read(mcon, iteration); - } -#ifndef WIN32 - else { - bytes = recvfrom(mcon->socket, &mcon->event, sizeof(mcon->event), MSG_DONTWAIT, (struct sockaddr *) &mcon->local_addr, &fromlen); - } -#endif - if (bytes <= 0) { - return NULL; - } - - if (mcon->event.version != SIGBOOST_VERSION) { - ftdm_log(FTDM_LOG_CRIT, "Invalid Boost Version %i Expecting %i\n",mcon->event.version, SIGBOOST_VERSION); - } - - if (bytes == sizeof(sangomabc_short_event_t)) { - - if (boost_full_event(mcon->event.event_id)) { - sangomabc_print_event_call(mcon, &mcon->event, 1, 0, file, func, line); - } else { - sangomabc_print_event_short(mcon, (sangomabc_short_event_t*)&mcon->event, 1, 0, file, func, line); - } - - return &mcon->event; - } else { - if (iteration == 0) { - ftdm_log(FTDM_LOG_CRIT, "Critical Error: PQ Invalid Event lenght from boost rxlen=%i evsz=%i\n", bytes, sizeof(mcon->event)); - return NULL; - } - } - - return NULL; -} - - -int __sangomabc_connection_write(sangomabc_connection_t *mcon, sangomabc_event_t *event, const char *file, const char *func, int line) -{ - int err = 0; - int event_size=MIN_SIZE_CALLSTART_MSG+event->isup_in_rdnis_size; - - ftdm_assert_return(event != NULL, -1, "No event!"); - ftdm_assert_return(mcon->socket >= 0, -1, "No mcon->socket!"); - ftdm_assert_return(mcon->mutex != NULL, -1, "No mcon->mutex!"); - - ftdm_assert_return(event->span <= FTDM_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN, -1, "Invalid span when writing boost event\n"); - ftdm_assert_return(event->chan <= FTDM_MAX_CHANNELS_PHYSICAL_SPAN, -1, "Invalid chan when writing boost event\n"); - - if (!boost_full_event(event->event_id)) { - event_size=sizeof(sangomabc_short_event_t); - } - - if (sangomabc_test_flag(mcon, MSU_FLAG_DOWN)) { - if (event->event_id != SIGBOOST_EVENT_SYSTEM_RESTART && - event->event_id != SIGBOOST_EVENT_SYSTEM_RESTART_ACK && - event->event_id != SIGBOOST_EVENT_HEARTBEAT) { - ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "Not writing packets when connection is down. [%s]\n", - sangomabc_event_id_name(event->event_id)); - return 0; - } - } - - ftdm_mutex_lock(mcon->mutex); - if (event->event_id == SIGBOOST_EVENT_SYSTEM_RESTART_ACK) { - mcon->txseq=0; - mcon->rxseq=0; - event->fseqno=0; - } else { - event->fseqno = mcon->txseq++; - } - event->bseqno = mcon->rxseq; - event->version = SIGBOOST_VERSION; - - if (boost_full_event(event->event_id)) { - sangomabc_print_event_call(mcon, event, 0, 1, file, func, line); - } else { - sangomabc_print_event_short(mcon, (sangomabc_short_event_t*)event, 0, 1, file, func, line); - } - - if (mcon->sigmod) { - mcon->sigmod->write_msg(mcon->span, event, event_size); - err = event_size; - } -#ifndef WIN32 - else { - err = sendto(mcon->socket, event, event_size, 0, (struct sockaddr *) &mcon->remote_addr, sizeof(mcon->remote_addr)); - } -#endif - - ftdm_mutex_unlock(mcon->mutex); - - ftdm_assert_return(err == event_size, -1, "Failed to send the boost message completely!"); - - return err; -} - - -int __sangomabc_connection_writep(sangomabc_connection_t *mcon, sangomabc_event_t *event, const char *file, const char *func, int line) -{ - int err = 0; - int event_size=sizeof(sangomabc_event_t); - - if (!mcon->sigmod) { - ftdm_assert_return(event != NULL, -1, "No event!"); - ftdm_assert_return(mcon->socket >= 0, -1, "No mcon->socket!"); - ftdm_assert_return(mcon->mutex != NULL, -1, "No mcon->mutex!"); - } - - if (!boost_full_event(event->event_id)) { - event_size=sizeof(sangomabc_short_event_t); - } - - ftdm_mutex_lock(mcon->mutex); - event->version = SIGBOOST_VERSION; - if (mcon->sigmod) { - mcon->sigmod->write_msg(mcon->span, event, event_size); - err = event_size; - - } -#ifndef WIN32 - else { - err = sendto(mcon->socket, event, event_size, 0, (struct sockaddr *) &mcon->remote_addr, sizeof(mcon->remote_addr)); - } -#endif - ftdm_mutex_unlock(mcon->mutex); - - ftdm_assert_return(err == event_size, -1, "Failed to send boost message completely!"); - - if (boost_full_event(event->event_id)) { - sangomabc_print_event_call(mcon, event, 1, 1, file, func, line); - } else { - sangomabc_print_event_short(mcon, (sangomabc_short_event_t*)event, 1, 1, file, func, line); - } - - return err; -} - - -void sangomabc_call_init(sangomabc_event_t *event, const char *calling, const char *called, int setup_id) -{ - memset(event, 0, sizeof(sangomabc_event_t)); - event->event_id = SIGBOOST_EVENT_CALL_START; - - if (calling) { - strncpy((char*)event->calling_number_digits, calling, sizeof(event->calling_number_digits)-1); - event->calling_number_digits_count = (uint8_t)strlen(calling); - } - - if (called) { - strncpy((char*)event->called_number_digits, called, sizeof(event->called_number_digits)-1); - event->called_number_digits_count = (uint8_t)strlen(called); - } - - event->call_setup_id = (uint16_t)setup_id; - -} - -void sangomabc_event_init(sangomabc_short_event_t *event, sangomabc_event_id_t event_id, int chan, int span) -{ - if (boost_full_event(event_id)) { - memset(event, 0, sizeof(sangomabc_event_t)); - } else { - memset(event, 0, sizeof(sangomabc_short_event_t)); - } - event->event_id = event_id; - event->chan = (uint8_t)chan; - event->span = (uint8_t)span; -} - -const char *sangomabc_event_id_name(uint32_t event_id) -{ - unsigned int x; - const char *ret = NULL; - - for (x = 0 ; x < sizeof(sangomabc_table)/sizeof(struct sangomabc_map); x++) { - if (sangomabc_table[x].event_id == event_id) { - ret = sangomabc_table[x].name; - 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: - */ - diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sangoma_boost_client.h b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sangoma_boost_client.h deleted file mode 100644 index e333c4aba3..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sangoma_boost_client.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2007, Anthony Minessale II, Nenad Corbic - * 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 _SANGOMABC_H -#define _SANGOMABC_H - -#include "sangoma_boost_interface.h" - -#include -#include -#ifndef WIN32 -#include -#include -#include -#ifdef HAVE_NETINET_SCTP_H -#include -#endif -#include -#include -#include -#endif -#include -#include -#include -#include -#include -#include -#include "sigboost.h" - -#define sangomabc_test_flag(p,flag) ((p)->flags & (flag)) - -#define sangomabc_set_flag(p,flag) do { \ - ((p)->flags |= (flag)); \ - } while (0) - -#define sangomabc_clear_flag(p,flag) do { \ - ((p)->flags &= ~(flag)); \ - } while (0) - -#define sangomabc_copy_flags(dest,src,flagz) do { \ - (dest)->flags &= ~(flagz); \ - (dest)->flags |= ((src)->flags & (flagz)); \ - } while (0) - -typedef t_sigboost_callstart sangomabc_event_t; -typedef t_sigboost_short sangomabc_short_event_t; -typedef uint32_t sangomabc_event_id_t; - -typedef struct sangomabc_ip_cfg -{ - char local_ip[25]; - int local_port; - char remote_ip[25]; - int remote_port; -}sangomabc_ip_cfg_t; - -typedef enum { - MSU_FLAG_EVENT = (1 << 0), - MSU_FLAG_DOWN = (1 << 1) -} sangomabc_flag_t; - - -struct sangomabc_connection { - ftdm_socket_t socket; - struct sockaddr_in local_addr; - struct sockaddr_in remote_addr; - sangomabc_event_t event; - struct hostent remote_hp; - struct hostent local_hp; - unsigned int flags; - ftdm_mutex_t *mutex; - FILE *log; - unsigned int txseq; - unsigned int rxseq; - unsigned int txwindow; - unsigned int rxseq_reset; - sangomabc_ip_cfg_t cfg; - /* boost signaling mod interface pointer (if not working in TCP mode) */ - boost_sigmod_interface_t *sigmod; - ftdm_queue_t *boost_queue; - ftdm_interrupt_t *sock_interrupt; - ftdm_span_t *span; - int debuglevel; -}; - -typedef struct sangomabc_connection sangomabc_connection_t; - -typedef struct sangomabc_queue_element { - unsigned char boostmsg[sizeof(sangomabc_event_t)]; - ftdm_size_t size; -} sangomabc_queue_element_t; - -/* disable nagle's algorythm */ -static __inline__ void sctp_no_nagle(int socket) -{ -#ifdef HAVE_NETINET_SCTP_H - int flag = 1; - setsockopt(socket, IPPROTO_SCTP, SCTP_NODELAY, (char *) &flag, sizeof(int)); -#endif -} - -int sangomabc_connection_close(sangomabc_connection_t *mcon); -int sangomabc_connection_open(sangomabc_connection_t *mcon, char *local_ip, int local_port, char *ip, int port); -sangomabc_event_t *__sangomabc_connection_read(sangomabc_connection_t *mcon, int iteration, const char *file, const char *func, int line); -sangomabc_event_t *__sangomabc_connection_readp(sangomabc_connection_t *mcon, int iteration, const char *file, const char *func, int line); -int __sangomabc_connection_write(sangomabc_connection_t *mcon, sangomabc_event_t *event, const char *file, const char *func, int line); -int __sangomabc_connection_writep(sangomabc_connection_t *mcon, sangomabc_event_t *event, const char *file, const char *func, int line); -#define sangomabc_connection_write(_m,_e) __sangomabc_connection_write(_m, _e, __FILE__, __FUNCTION__, __LINE__) -#define sangomabc_connection_writep(_m,_e) __sangomabc_connection_writep(_m, _e, __FILE__, __FUNCTION__, __LINE__) -#define sangomabc_connection_read(_m,_e) __sangomabc_connection_read(_m, _e, __FILE__, __FUNCTION__, __LINE__) -#define sangomabc_connection_readp(_m,_e) __sangomabc_connection_readp(_m, _e, __FILE__, __FUNCTION__, __LINE__) -void sangomabc_event_init(sangomabc_short_event_t *event, sangomabc_event_id_t event_id, int chan, int span); -void sangomabc_call_init(sangomabc_event_t *event, const char *calling, const char *called, int setup_id); -const char *sangomabc_event_id_name(uint32_t event_id); -int sangomabc_exec_command(sangomabc_connection_t *mcon, int span, int chan, int id, int cmd, int cause, int flags); -int sangomabc_exec_commandp(sangomabc_connection_t *pcon, int span, int chan, int id, int cmd, int cause); - -#define BOOST_EVENT_SPAN(sigmod, event) ((sigmod) ? event->span : event->span + 1) -#define BOOST_EVENT_CHAN(sigmod, event) ((sigmod) ? event->chan : event->chan + 1) - - -#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: - */ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sangoma_boost_interface.h b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sangoma_boost_interface.h deleted file mode 100644 index f6130db444..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sangoma_boost_interface.h +++ /dev/null @@ -1,254 +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. - */ - -#ifndef SANGOMA_BOOST_INTERFACE_H -#define SANGOMA_BOOST_INTERFACE_H - -#include "private/ftdm_core.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/*! - \brief Callback used to notify signaling status changes on a channel - \param ftdmchan The freetdm channel where the signaling status just changed - \param status The new signaling status - */ -#define BOOST_SIG_STATUS_CB_ARGS (ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status) -typedef void (*boost_sig_status_cb_func_t) BOOST_SIG_STATUS_CB_ARGS; -#define BOOST_SIG_STATUS_CB_FUNCTION(name) void name BOOST_SIG_STATUS_CB_ARGS - -/*! - \brief Write a boost msg to a boost endpoint - \param span The freetdm span where this msg was generated - \param msg The generic message pointer, owned by the caller - \param msglen The length of the provided structure pointed by msg - \return FTDM_SUCCESS or FTDM_FAIL - - The msg buffer is owned by the caller and it should - be either t_sigboost_callstart or t_sigboost_short - the endpoint receiving the msg will first cast to - t_sigboost_short, check the event type, and if needed. - */ -#define BOOST_WRITE_MSG_ARGS (ftdm_span_t *span, void *msg, ftdm_size_t msglen) -typedef ftdm_status_t (*boost_write_msg_func_t) BOOST_WRITE_MSG_ARGS; -#define BOOST_WRITE_MSG_FUNCTION(name) ftdm_status_t name BOOST_WRITE_MSG_ARGS - -/*! - \brief Set the callback to be used by a signaling module to write boost messages - \param callback The callback to be used by the signaling module - - The provided callback will be used for the signaling boost module to notify the - user with boost messages. - */ -#define BOOST_SET_WRITE_MSG_CB_ARGS (boost_write_msg_func_t callback) -typedef void (*boost_set_write_msg_cb_func_t) BOOST_SET_WRITE_MSG_CB_ARGS; -#define BOOST_SET_WRITE_MSG_CB_FUNCTION(name) void name BOOST_SET_WRITE_MSG_CB_ARGS - -/*! - \brief Notify hardware status change - \param ftdmchan The freetdm channel - \param status The hw status - \return FTDM_SUCCESS or FTDM_FAIL - */ -#define BOOST_ON_HW_LINK_STATUS_CHANGE_ARGS (ftdm_channel_t *ftdmchan, ftdm_channel_hw_link_status_t status) -typedef void (*boost_on_hw_link_status_change_func_t) BOOST_ON_HW_LINK_STATUS_CHANGE_ARGS; -#define BOOST_ON_HW_LINK_STATUS_CHANGE_FUNCTION(name) void name BOOST_ON_HW_LINK_STATUS_CHANGE_ARGS - -/*! - \brief Set signaling status callback used by the signaling module to report signaling status changes - \param callback The callback to be used by the signaling module - - The provided callback will be used for the signaling boost module to notify the - user with signaling link status changes. - */ -#define BOOST_SET_SIG_STATUS_CB_ARGS (boost_sig_status_cb_func_t callback) -typedef void (*boost_set_sig_status_cb_func_t) BOOST_SET_SIG_STATUS_CB_ARGS; -#define BOOST_SET_SIG_STATUS_CB_FUNCTION(name) void name BOOST_SET_SIG_STATUS_CB_ARGS - -/*! - \brief Get the signaling status on the given channel. - \param ftdmchan The freetdm channel - \param status The status pointer where the current signaling status will be set - */ -#define BOOST_GET_CHANNEL_SIG_STATUS_ARGS (ftdm_channel_t *ftdmchan, ftdm_signaling_status_t *status) -typedef ftdm_status_t (*boost_get_channel_sig_status_func_t) BOOST_GET_CHANNEL_SIG_STATUS_ARGS; -#define BOOST_GET_CHANNEL_SIG_STATUS_FUNCTION(name) ftdm_status_t name BOOST_GET_CHANNEL_SIG_STATUS_ARGS - -/*! - \brief Set the signaling status on the given channel. - \param ftdmchan The freetdm channel - \param status The new status for the channel - \return FTDM_SUCCESS or FTDM_FAIL - */ -#define BOOST_SET_CHANNEL_SIG_STATUS_ARGS (ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status) -typedef ftdm_status_t (*boost_set_channel_sig_status_func_t) BOOST_SET_CHANNEL_SIG_STATUS_ARGS; -#define BOOST_SET_CHANNEL_SIG_STATUS_FUNCTION(name) ftdm_status_t name BOOST_SET_CHANNEL_SIG_STATUS_ARGS - -/*! - \brief Get the signaling status on the given span. - \param span The freetdm span - \param status The status pointer where the current signaling status will be set - */ -#define BOOST_GET_SPAN_SIG_STATUS_ARGS (ftdm_span_t *span, ftdm_signaling_status_t *status) -typedef ftdm_status_t (*boost_get_span_sig_status_func_t) BOOST_GET_SPAN_SIG_STATUS_ARGS; -#define BOOST_GET_SPAN_SIG_STATUS_FUNCTION(name) ftdm_status_t name BOOST_GET_SPAN_SIG_STATUS_ARGS - -/*! - \brief Set the signaling status on the given span. - \param ftdmchan The freetdm span - \param status The new status for the span - \return FTDM_SUCCESS or FTDM_FAIL - */ -#define BOOST_SET_SPAN_SIG_STATUS_ARGS (ftdm_span_t *span, ftdm_signaling_status_t status) -typedef ftdm_status_t (*boost_set_span_sig_status_func_t) BOOST_SET_SPAN_SIG_STATUS_ARGS; -#define BOOST_SET_SPAN_SIG_STATUS_FUNCTION(name) ftdm_status_t name BOOST_SET_SPAN_SIG_STATUS_ARGS - -/*! - \brief Configure the given span signaling - \param span The freetdm span - \param parameters The array of configuration key,value pairs (must be null terminated) - \return FTDM_SUCCESS or FTDM_FAIL - */ -#define BOOST_CONFIGURE_SPAN_ARGS (ftdm_span_t *span, ftdm_conf_parameter_t *parameters) -typedef ftdm_status_t (*boost_configure_span_func_t) BOOST_CONFIGURE_SPAN_ARGS; -#define BOOST_CONFIGURE_SPAN_FUNCTION(name) ftdm_status_t name BOOST_CONFIGURE_SPAN_ARGS - -/*! - \brief Start the given span - \param span The freetdm span - \return FTDM_SUCCESS or FTDM_FAIL - */ -#define BOOST_START_SPAN_ARGS (ftdm_span_t *span) -typedef ftdm_status_t (*boost_start_span_func_t) BOOST_START_SPAN_ARGS; -#define BOOST_START_SPAN_FUNCTION(name) ftdm_status_t name BOOST_START_SPAN_ARGS - -/*! - \brief Stop the given span - \param span The freetdm span - \return FTDM_SUCCESS or FTDM_FAIL - */ -#define BOOST_STOP_SPAN_ARGS (ftdm_span_t *span) -typedef ftdm_status_t (*boost_stop_span_func_t) BOOST_START_SPAN_ARGS; -#define BOOST_STOP_SPAN_FUNCTION(name) ftdm_status_t name BOOST_STOP_SPAN_ARGS - -/*! - \brief Called when the module is being loaded BEFORE calling anything else - \return FTDM_SUCCESS or FTDM_FAIL - */ -#define BOOST_ON_LOAD_ARGS (void) -typedef ftdm_status_t (*boost_on_load_func_t) BOOST_ON_LOAD_ARGS; -#define BOOST_ON_LOAD_FUNCTION(name) ftdm_status_t name BOOST_ON_LOAD_ARGS - -/*! - \brief Called when the module is being unloaded, last chance to stop everything! - */ -#define BOOST_ON_UNLOAD_ARGS (void) -typedef ftdm_status_t (*boost_on_unload_func_t) BOOST_ON_UNLOAD_ARGS; -#define BOOST_ON_UNLOAD_FUNCTION(name) ftdm_status_t name BOOST_ON_UNLOAD_ARGS - -/*! - \brief Called when user wants to execute sigmod api function - \return FTDM_SUCCESS or FTDM_FAIL - */ -#define BOOST_API_ARGS (ftdm_stream_handle_t *stream, char *cmd) -typedef ftdm_status_t (*boost_api_func_t) BOOST_API_ARGS; -#define BOOST_API_FUNCTION(name) ftdm_status_t name BOOST_API_ARGS - - -/*! - \brief The boost signaling module interface - */ -typedef struct boost_sigmod_interface_s { - /*! \brief Module name */ - const char *name; - /*! \brief write boost message function */ - boost_write_msg_func_t write_msg; - /*! \brief set the user write boost message function */ - boost_set_write_msg_cb_func_t set_write_msg_cb; - /*! \brief set the user signaling status function */ - boost_set_sig_status_cb_func_t set_sig_status_cb; - /*! \brief get channel signaling status */ - boost_get_channel_sig_status_func_t get_channel_sig_status; - /*! \brief set channel signaling status */ - boost_set_channel_sig_status_func_t set_channel_sig_status; - /*! \brief get span signaling status */ - boost_get_span_sig_status_func_t get_span_sig_status; - /*! \brief set span signaling status */ - boost_set_span_sig_status_func_t set_span_sig_status; - /*! \brief set notify hardware link status change */ - boost_on_hw_link_status_change_func_t on_hw_link_status_change; - /*! \brief configure span signaling */ - boost_configure_span_func_t configure_span; - /*! \brief start freetdm span */ - boost_start_span_func_t start_span; - /*! \brief stop freetdm span */ - boost_stop_span_func_t stop_span; - /*! \brief the module was just loaded */ - boost_on_load_func_t on_load; - /*! \brief the module is about to be unloaded */ - boost_on_unload_func_t on_unload; - /*! \brief module api function */ - boost_api_func_t exec_api; - /*! \brief private pointer for the interface user */ - void *pvt; -} boost_sigmod_interface_t; - -#ifdef __cplusplus -} // extern C -#endif - -#define BOOST_INTERFACE_NAME boost_sigmod_interface -#define BOOST_INTERFACE_NAME_STR "boost_sigmod_interface" -/* use this in your sig boost module to declare your interface */ -#ifndef WIN32 -#define BOOST_INTERFACE boost_sigmod_interface_t BOOST_INTERFACE_NAME -#else -#define BOOST_INTERFACE __declspec(dllexport) boost_sigmod_interface_t BOOST_INTERFACE_NAME -#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: - */ - diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sigboost.h b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sigboost.h deleted file mode 100644 index 7975dc5b93..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sigboost.h +++ /dev/null @@ -1,221 +0,0 @@ -/**************************************************************************** - * sigboost.h $Revision: 1.13 $ - * - * Definitions for the sigboost interface. - * - * WARNING WARNING WARNING - * - * This file is used by sangoma_mgd and perhaps other programs. Any changes - * to this file must be coordinated with other user programs, - * - * Copyright (C) 2005 Xygnada Technology, Inc. - * -****************************************************************************/ -#ifndef _SIGBOOST_H_ -#define _SIGBOOST_H_ - -#define SIGBOOST_VERSION 103 - -// handy to define integer types that actually work on both Lin and Win -#include - -enum e_sigboost_event_id_values -{ - SIGBOOST_EVENT_CALL_START = 0x80, /*128*/ - SIGBOOST_EVENT_CALL_START_ACK = 0x81, /*129*/ - SIGBOOST_EVENT_CALL_START_NACK = 0x82, /*130*/ - SIGBOOST_EVENT_CALL_START_NACK_ACK = 0x83, /*131*/ - SIGBOOST_EVENT_CALL_ANSWERED = 0x84, /*132*/ - SIGBOOST_EVENT_CALL_STOPPED = 0x85, /*133*/ - SIGBOOST_EVENT_CALL_STOPPED_ACK = 0x86, /*134*/ - SIGBOOST_EVENT_SYSTEM_RESTART = 0x87, /*135*/ - SIGBOOST_EVENT_SYSTEM_RESTART_ACK = 0x88, /*136*/ - /* CALL_RELEASED is aimed to fix a race condition that became obvious - * when the boost socket was replaced by direct function calls - * and the channel hunting was moved to freetdm, the problem is - * we can get CALL_STOPPED msg and reply with CALL_STOPPED_ACK - * but the signaling module will still (in PRI) send RELEASE and - * wait for RELEASE_COMPLETE from the isdn network before - * marking the channel as available, therefore freetdm should - * also not mark the channel as available until CALL_RELEASED - * is received, for socket mode we can continue working as usual - * with CALL_STOPPED being the last step because the hunting is - * done in the signaling module. - * */ - SIGBOOST_EVENT_CALL_RELEASED = 0x51, /* 81 */ - SIGBOOST_EVENT_CALL_PROGRESS = 0x50, /*decimal 80*/ - /* Following IDs are ss7boost to sangoma_mgd only. */ - SIGBOOST_EVENT_HEARTBEAT = 0x89, /*137*/ - SIGBOOST_EVENT_INSERT_CHECK_LOOP = 0x8a, /*138*/ - SIGBOOST_EVENT_REMOVE_CHECK_LOOP = 0x8b, /*139*/ - SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE = 0x8c, /*140*/ - SIGBOOST_EVENT_DIGIT_IN = 0x8d, /*141*/ -}; - -#define BOOST_DECODE_EVENT_ID(id) \ - (id==SIGBOOST_EVENT_CALL_START)?"SIGBOOST_EVENT_CALL_START": \ - (id==SIGBOOST_EVENT_CALL_START_ACK)?"SIGBOOST_EVENT_CALL_START_ACK": \ - (id==SIGBOOST_EVENT_CALL_START_NACK)?"SIGBOOST_EVENT_CALL_START_NACK": \ - (id==SIGBOOST_EVENT_CALL_ANSWERED)?"SIGBOOST_EVENT_CALL_ANSWERED": \ - (id==SIGBOOST_EVENT_CALL_STOPPED)?"SIGBOOST_EVENT_CALL_STOPPED": \ - (id==SIGBOOST_EVENT_CALL_STOPPED_ACK)?"SIGBOOST_EVENT_CALL_STOPPED_ACK": \ - (id==SIGBOOST_EVENT_SYSTEM_RESTART)?"SIGBOOST_EVENT_SYSTEM_RESTART": \ - (id==SIGBOOST_EVENT_SYSTEM_RESTART_ACK)?"SIGBOOST_EVENT_SYSTEM_RESTART_ACK": \ - (id==SIGBOOST_EVENT_CALL_RELEASED)?"SIGBOOST_EVENT_CALL_RELEASED": \ - (id==SIGBOOST_EVENT_CALL_PROGRESS)?"SIGBOOST_EVENT_CALL_PROGRESS": \ - (id==SIGBOOST_EVENT_HEARTBEAT)?"SIGBOOST_EVENT_HEARTBEAT": \ - (id==SIGBOOST_EVENT_INSERT_CHECK_LOOP)?"SIGBOOST_EVENT_INSERT_CHECK_LOOP": \ - (id==SIGBOOST_EVENT_REMOVE_CHECK_LOOP)?"SIGBOOST_EVENT_REMOVE_CHECK_LOOP": \ - (id==SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE)?"SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE": \ - (id==SIGBOOST_EVENT_DIGIT_IN)?"SIGBOOST_EVENT_DIGIT_IN": "Unknown" - -enum e_sigboost_release_cause_values -{ - SIGBOOST_RELEASE_CAUSE_UNDEFINED = 0, - SIGBOOST_RELEASE_CAUSE_NORMAL = 16, - /* probable elimination */ - //SIGBOOST_RELEASE_CAUSE_BUSY = 0x91, /* 145 */ - //SIGBOOST_RELEASE_CAUSE_CALLED_NOT_EXIST = 0x92, /* 146 */ - //SIGBOOST_RELEASE_CAUSE_CIRCUIT_RESET = 0x93, /* 147 */ - //SIGBOOST_RELEASE_CAUSE_NOANSWER = 0x94, /* 148 */ -}; - -enum e_sigboost_call_setup_ack_nack_cause_values -{ - //SIGBOOST_CALL_SETUP_NACK_ALL_CKTS_BUSY = 34, /* Q.850 value - don't use */ - SIGBOOST_CALL_SETUP_NACK_ALL_CKTS_BUSY = 117, /* non Q.850 value indicates local all ckt busy - causing sangoma_mgd to perform automatic call - gapping*/ - SIGBOOST_CALL_SETUP_NACK_TEST_CKT_BUSY = 17, /* Q.850 value */ - SIGBOOST_CALL_SETUP_NACK_INVALID_NUMBER = 28, /* Q.850 value */ - SIGBOOST_CALL_SETUP_CSUPID_DBL_USE = 200, /* unused Q.850 value */ -}; - - -enum e_sigboost_huntgroup_values -{ - SIGBOOST_HUNTGRP_SEQ_ASC = 0x00, /* sequential with lowest available first */ - SIGBOOST_HUNTGRP_SEQ_DESC = 0x01, /* sequential with highest available first */ - SIGBOOST_HUNTGRP_RR_ASC = 0x02, /* round-robin with lowest available first */ - SIGBOOST_HUNTGRP_RR_DESC = 0x03, /* round-robin with highest available first */ -}; - -enum e_sigboost_event_info_par_values -{ - SIGBOOST_EVI_SPARE = 0x00, - SIGBOOST_EVI_ALERTING = 0x01, - SIGBOOST_EVI_PROGRESS = 0x02, -}; - -enum e_sigboost_progress_flags -{ - SIGBOOST_PROGRESS_RING = (1 << 0), - SIGBOOST_PROGRESS_MEDIA = (1 << 1) -}; - -#define MAX_DIALED_DIGITS 31 - -/* Next two defines are used to create the range of values for call_setup_id - * in the t_sigboost structure. - * 0..((CORE_MAX_SPANS * CORE_MAX_CHAN_PER_SPAN) - 1) */ -#define CORE_MAX_SPANS 200 -#define CORE_MAX_CHAN_PER_SPAN 32 -#define MAX_PENDING_CALLS CORE_MAX_SPANS * CORE_MAX_CHAN_PER_SPAN -/* 0..(MAX_PENDING_CALLS-1) is range of call_setup_id below */ - -/* Should only be used by server */ -#define MAX_CALL_SETUP_ID 0xFFFF - -#define SIZE_CUSTOM 900 -#define SIZE_RDNIS SIZE_CUSTOM - - -#pragma pack(1) - -typedef struct -{ - uint8_t capability; - uint8_t uil1p; -} t_sigboost_bearer; - -typedef struct -{ - uint8_t digits_count; - char digits [MAX_DIALED_DIGITS + 1]; /* it's a null terminated string */ - uint8_t npi; - uint8_t ton; - uint8_t screening_ind; - uint8_t presentation_ind; -}t_sigboost_digits; - -typedef struct -{ - uint16_t version; - uint32_t event_id; - /* delete sequence numbers - SCTP does not need them */ - uint32_t fseqno; - uint32_t bseqno; - uint16_t call_setup_id; - uint32_t trunk_group; - uint8_t span; - uint8_t chan; - uint32_t flags; - /* struct timeval tv; */ - t_sigboost_digits called; - t_sigboost_digits calling; - t_sigboost_digits rdnis; - /* ref. Q.931 Table 4-11 and Q.951 Section 3 */ - char calling_name[MAX_DIALED_DIGITS + 1]; - t_sigboost_bearer bearer; - uint8_t hunt_group; - uint16_t custom_data_size; - char custom_data[SIZE_CUSTOM]; /* it's a null terminated string */ - -} t_sigboost_callstart; - -#define called_number_digits_count called.digits_count -#define called_number_digits called.digits -#define calling_number_digits_count calling.digits_count -#define calling_number_digits calling.digits -#define calling_number_screening_ind calling.screening_ind -#define calling_number_presentation calling.presentation_ind - -#define isup_in_rdnis_size custom_data_size -#define isup_in_rdnis custom_data - - -#define MIN_SIZE_CALLSTART_MSG sizeof(t_sigboost_callstart) - SIZE_CUSTOM - -typedef struct -{ - uint16_t version; - uint32_t event_id; - /* delete sequence numbers - SCTP does not need them */ - uint32_t fseqno; - uint32_t bseqno; - uint16_t call_setup_id; - uint32_t trunk_group; - uint8_t span; - uint8_t chan; - uint32_t flags; - /* struct timeval tv; */ - uint8_t release_cause; -} t_sigboost_short; -#pragma pack() - - -static __inline__ int boost_full_event(int event_id) -{ - switch (event_id) { - case SIGBOOST_EVENT_CALL_START: - case SIGBOOST_EVENT_DIGIT_IN: - case SIGBOOST_EVENT_CALL_PROGRESS: - return 1; - default: - break; - } - - return 0; -} - -#endif From b83a30caf68e290239f2d62c01bdc5ba7f8a5e15 Mon Sep 17 00:00:00 2001 From: Michal Bielicki - cypromis Date: Wed, 16 Feb 2011 20:35:11 +0100 Subject: [PATCH 13/43] added python eslmod installation to esl Makefiles --- libs/esl/Makefile | 3 +++ libs/esl/python/Makefile | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/libs/esl/Makefile b/libs/esl/Makefile index ab50bac4d9..fbc870ac24 100644 --- a/libs/esl/Makefile +++ b/libs/esl/Makefile @@ -95,4 +95,7 @@ managedmod: $(MYLIB) phpmod-install: phpmod $(MAKE) -C php install +pymod-install: pymod + $(MAKE) -C python install + everymod: perlmod phpmod luamod pymod rubymod javamod managedmod diff --git a/libs/esl/python/Makefile b/libs/esl/python/Makefile index 758aeaf500..6b7147bede 100644 --- a/libs/esl/python/Makefile +++ b/libs/esl/python/Makefile @@ -1,5 +1,6 @@ LOCAL_CFLAGS=`python ./python-config --includes` LOCAL_LDFLAGS=`python ./python-config --ldflags` +SITE_DIR=`python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"` all: _ESL.so @@ -12,6 +13,9 @@ esl_wrap.o: esl_wrap.cpp _ESL.so: esl_wrap.o $(CXX) $(SOLINK) esl_wrap.o $(MYLIB) $(LOCAL_LDFLAGS) -o _ESL.so -L. $(LIBS) +install: _ESL.so + install -o root -g root -m 644 _ESL.so $(SITE_DIR) + clean: rm -f *.o *.so *~ From 837c6ff6e828d1f81c8df2ac71d0733eb97f9fd1 Mon Sep 17 00:00:00 2001 From: Michal Bielicki - cypromis Date: Wed, 16 Feb 2011 20:35:56 +0100 Subject: [PATCH 14/43] adding centos standard java include parts to javamod esl module --- libs/esl/java/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/esl/java/Makefile b/libs/esl/java/Makefile index 9474a83276..3606edf331 100644 --- a/libs/esl/java/Makefile +++ b/libs/esl/java/Makefile @@ -1,4 +1,4 @@ -LOCAL_CFLAGS=-I../src/include -I/usr/java/jdk1.6.0_14/include -I/usr/java/jdk1.6.0_14/include/linux -I/usr/lib/jvm/java-6-openjdk/include/ +LOCAL_CFLAGS=-I../src/include -I/usr/java/jdk1.6.0_14/include -I/usr/java/jdk1.6.0_14/include/linux -I/usr/lib/jvm/java-6-openjdk/include/ -I/usr/lib/jvm/java/include -I/usr/lib/jvm/java/include/linux GCC_WARNING_JUNK=-w CLASSES=org/freeswitch/esl/* From e8335f588002217240ab49bc12504b42e89114d4 Mon Sep 17 00:00:00 2001 From: Michal Bielicki - cypromis Date: Wed, 16 Feb 2011 20:54:57 +0100 Subject: [PATCH 15/43] added DESTDIR to esl makefiles so that it can be used during rpm building --- libs/esl/php/Makefile | 6 +++--- libs/esl/python/Makefile | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/esl/php/Makefile b/libs/esl/php/Makefile index 44fdd22dae..e970ff7d82 100644 --- a/libs/esl/php/Makefile +++ b/libs/esl/php/Makefile @@ -25,6 +25,6 @@ swigclean: reswig: swigclean esl_wrap.cpp install: ESL.so - cp ESL.so $(shell php-config --extension-dir) - cp ESL.php $(shell php -r 'echo ini_get("include_path");' | cut -d: -f2) - echo 'extension=ESL.so' >> $(shell php-config --configure-options | tr " " "\n" | grep -- --with-config-file-scan-dir | cut -f2 -d=)/esl.ini + cp ESL.so $(DESTDIR)/$(shell php-config --extension-dir) + cp ESL.php /$(DESTDIR)/$(shell php -r 'echo ini_get("include_path");' | cut -d: -f2) + echo 'extension=ESL.so' >> $(DESTDIR)/$(shell php-config --configure-options | tr " " "\n" | grep -- --with-config-file-scan-dir | cut -f2 -d=)/esl.ini diff --git a/libs/esl/python/Makefile b/libs/esl/python/Makefile index 6b7147bede..0d9ca84cbd 100644 --- a/libs/esl/python/Makefile +++ b/libs/esl/python/Makefile @@ -1,6 +1,6 @@ LOCAL_CFLAGS=`python ./python-config --includes` LOCAL_LDFLAGS=`python ./python-config --ldflags` -SITE_DIR=`python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"` +SITE_DIR=$(DESTDIR)/`python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"` all: _ESL.so From 3ce98c4ebddec0e459c564942f6beb583350188a Mon Sep 17 00:00:00 2001 From: Michal Bielicki - cypromis Date: Thu, 17 Feb 2011 00:02:37 +0100 Subject: [PATCH 16/43] major cleanups, mod_skinny and skypopen and sangoma ftdm modules added to rpm spec file --- freeswitch.spec | 162 +++++++++++++++++++++++++++++++++++---- libs/esl/python/Makefile | 2 +- 2 files changed, 150 insertions(+), 14 deletions(-) diff --git a/freeswitch.spec b/freeswitch.spec index 7fb9f80d8e..9b6e60f123 100644 --- a/freeswitch.spec +++ b/freeswitch.spec @@ -27,6 +27,14 @@ # Maintainer(s): Michal Bielicki 910 @@ -282,14 +295,72 @@ German language phrases module and directory structure for say module and voicem Summary: Provides a unified interface to hardware TDM cards and ss7 stacks for FreeSWITCH Group: System/Libraries Requires: %{name} = %{version}-%{release} -%{?with_sang_isdn: Requires: wanpipe } -%{?with_sang_isdn: Requires: libsng_isdn } -%{?with_sang_isdn: BuildRequires: wanpipe } -%{?with_sang_isdn: BuildRequires: libang_isdn } %description freetdm FreeTDM +%if %{build_sng_isdn} + +%package freetdm-sng-isdn +Summary: Sangoma ISDN Module for FreeTDM +Group: System/Libraries +Requires: %{name} = %{version}-%{release} +Requires: %{name}-freetdm = %{version}-%{release} +Requires: wanpipe +Requires: libsng_isdn +BuildRequires: wanpipe +BuildRequires: libsng_isdn + +%description freetdm-sng-isdn +Sangoma ISDN Module for freetdm + +%endif + +%if %{build_sng_ss7} + +%package freetdm-sng-ss7 +Summary: Provides a unified interface to hardware TDM cards and ss7 stacks for FreeSWITCH, Sangoma SS7 Module +Group: System/Libraries +Requires: %{name} = %{version}-%{release} +Requires: %{name}-freetdm = %{version}-%{release} +Requires: wanpipe +Requires: libsng_ss7 +BuildRequires: wanpipe +BuildRequires: libsng_ss7 + +%description freetdm-sng-ss7 +Sangoma SMG-SS7 drivers for FreeTDM + +%endif + + +%if %{build_sng_tc} + +%package sangoma-codec +Summary: Sangoma D100 and D500 Codec Card Support +Group: System/Libraries +Requires: %{name} = %{version}-%{release} +Requires: sng-tc-linux +BuildRequires: sng-tc-linux + +%description sangoma-codec +Sangoma D100 and D500 Codec Card Support + +%endif + +%package skypopen +Summary: Skype Endpoint +Group: System/Libraries +Requires: %{name} = %{version}-%{release} +Requires: libX11 +BuildRequires: libX11-devel + +%description skypopen +This software (Skypopen) uses the Skype API but is not endorsed, certified or otherwise approved in any way by Skype. +Skypopen is an endpoint (channel driver) that uses the Skype client as an interface to the Skype network, and allows +incoming and outgoing Skype calls to/from FreeSWITCH (that can be bridged, originated, answered, etc. as in all other +endpoints, e.g. Sofia-SIP). + ###################################################################################################################### # # Unpack and prepare Source archives, copy stuff around etc .. @@ -309,6 +380,8 @@ cp %{SOURCE8} libs/ cp %{SOURCE9} libs/ cp %{SOURCE10} libs/ cp %{SOURCE11} libs/ +cp %{SOURCE12} libs/ +cp %{SOURCE13} libs/ ###################################################################################################################### # @@ -358,7 +431,11 @@ ASR_TTS_MODULES="asr_tts/mod_pocketsphinx asr_tts/mod_flite asr_tts/mod_unimrcp" # ###################################################################################################################### CODECS_MODULES="codecs/mod_bv codecs/mod_h26x codecs/mod_speex codecs/mod_celt codecs/mod_codec2 codecs/mod_ilbc codecs/mod_mp4v \ - codecs/mod_silk codecs/mod_siren codecs/mod_theora" + codecs/mod_opus codecs/mod_silk codecs/mod_siren codecs/mod_theora " +# +%if %{build_sng_tc} +CODECS_MODULES+="codecs/mod_sangoma_codec" +%endif ###################################################################################################################### # # Dialplan Modules @@ -377,7 +454,7 @@ DIRECTORIES_MODULES="" # ###################################################################################################################### ENDPOINTS_MODULES="endpoints/mod_dingaling endpoints/mod_loopback ../../libs/freetdm/mod_freetdm endpoints/mod_portaudio \ - endpoints/mod_sofia" + endpoints/mod_sofia endpoints/mod_skinny endpoints/mod_skypopen" ###################################################################################################################### # @@ -483,11 +560,13 @@ fi %{?configure_options} #Create the version header file here -cat src/include/switch_version.h.in | sed "s/@SVN_VERSION@/%{version}/g" > src/include/switch_version.h -touch .noversion +#cat src/include/switch_version.h.in | sed "s/@SVN_VERSION@/%{version}/g" > src/include/switch_version.h +#touch .noversion %{__make} +cd libs/esl +%{__make} pymod ###################################################################################################################### # @@ -503,6 +582,11 @@ touch .noversion %{__mkdir} -p %{buildroot}%{logfiledir} %{__mkdir} -p %{buildroot}%{runtimedir} +#install the esl stuff +cd libs/esl +%{__make} DESTDIR=%{buildroot} pymod-install +cd ../.. + %ifos linux # Install init files # On SuSE: @@ -522,6 +606,23 @@ touch .noversion # Add monit file %{__install} -D -m 644 build/freeswitch.monitrc %{buildroot}/etc/monit.d/freeswitch.monitrc %endif +###################################################################################################################### +# +# Remove files that are not wanted if they exist +# +###################################################################################################################### + +%if %{build_sng_ss7} +#do not delete a thing +%else +rm %{prefix}/mod/ftdm_sangoma_ss7* +%endif +%if %{build_sng_isdn} +#do not delete a thing +%else +rm %{prefix}/mod/ftdm_sangoma_isdn* +%endif + ###################################################################################################################### @@ -545,8 +646,6 @@ fi chkconfig --add freeswitch - - %postun ###################################################################################################################### # @@ -790,6 +889,7 @@ fi %{prefix}/mod/mod_mp4v.so* %{prefix}/mod/mod_native_file.so* %{prefix}/mod/mod_nibblebill.so* +%{prefix}/mod/mod_opus.so* %{prefix}/mod/mod_pocketsphinx.so* %{prefix}/mod/mod_portaudio.so* %{prefix}/mod/mod_portaudio_stream.so* @@ -798,6 +898,7 @@ fi %{prefix}/mod/mod_shout.so* %{prefix}/mod/mod_silk.so* %{prefix}/mod/mod_siren.so* +%{prefix}/mod/mod_skinny.so* %{prefix}/mod/mod_sndfile.so* %{prefix}/mod/mod_snom.so* %{prefix}/mod/mod_sofia.so* @@ -831,7 +932,7 @@ fi %{prefix}/include/*.h ###################################################################################################################### # -# OpenZAP Module for TDM Interaction +# FreeTDM Module for TDM Interaction # ###################################################################################################################### %files freetdm @@ -844,7 +945,26 @@ fi %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/zt.conf %{prefix}/lib/libfreetdm.so* %{prefix}/mod/mod_freetdm.so* -%{prefix}/mod/ftm*.so* +%{prefix}/mod/ftmod_skel*.so* +%{prefix}/mod/ftmod_[a-r,t-z]*.so* + +%if %{build_sng_tc} +%files sangoma-codec +%defattr(-, freeswitch, daemon) +%{prefix}/mod/mod_sangoma_codec.so* +%endif + +%if %{build_sng_ss7} +%files freetdm-sng-ss7 +%defattr(-, freeswitch, daemon) +%{prefix}/mod/ftmod_sangoma_ss7.so* +%endif + +%if %{build_sng_isdn} +%files freetdm-sng-isdn +%defattr(-, freeswitch, daemon) +%{prefix}/mod/ftmod_sangoma_isdn.so* +%endif ###################################################################################################################### # @@ -899,9 +1019,13 @@ fi %defattr(-,freeswitch,daemon) %{prefix}/mod/mod_python*.so* %attr(0644, root, bin) /usr/lib/python*/site-packages/freeswitch.py* +%attr(0644, root, bin) /usr/lib/python*/site-packages/_ESL.so* %dir %attr(0750, freeswitch, daemon) %{prefix}/conf/autoload_configs %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/python.conf.xml +%files skypopen +%defattr(-,freeswitch,daemon) +%{prefix}/mod/mod_skypopen.so* ###################################################################################################################### # # Language Modules @@ -956,6 +1080,17 @@ fi # ###################################################################################################################### %changelog +* Wed Feb 16 2011 - michal.bielicki@seventhsignal.de +- added mod_skinny +- added sangoma libraries +- added sangoma codec module for D100 and D150 and D500 +- added skypopen module +- fixes for ss7 freetdm modules +- added mod_opus +- added selector for sangoma modules +- addded python esl module to rpm +- some minor cleanups +- cut sangoma modules into separate rpms as addons for freetdm * Tue Jan 18 2011 - michal.bielicki@seventhsignal.de - Fedora adjustments * Fri Oct 15 2010 - michal.bielicki@seventhsignal.de @@ -1090,3 +1225,4 @@ fi - Added devel package * Thu Mar 15 2007 - peter+rpmspam@suntel.com.tr - Initial RPM release + diff --git a/libs/esl/python/Makefile b/libs/esl/python/Makefile index 0d9ca84cbd..784426ee1b 100644 --- a/libs/esl/python/Makefile +++ b/libs/esl/python/Makefile @@ -14,7 +14,7 @@ _ESL.so: esl_wrap.o $(CXX) $(SOLINK) esl_wrap.o $(MYLIB) $(LOCAL_LDFLAGS) -o _ESL.so -L. $(LIBS) install: _ESL.so - install -o root -g root -m 644 _ESL.so $(SITE_DIR) + install -m 755 _ESL.so $(SITE_DIR) clean: rm -f *.o *.so *~ From 2a3aea4cc8aa7a6f9f255fd548e29c30c32864fe Mon Sep 17 00:00:00 2001 From: Michal Bielicki - cypromis Date: Thu, 17 Feb 2011 02:01:46 +0100 Subject: [PATCH 17/43] its getting late and I am looking at this file the whole day already --- freeswitch.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/freeswitch.spec b/freeswitch.spec index 9b6e60f123..6b7530d471 100644 --- a/freeswitch.spec +++ b/freeswitch.spec @@ -615,12 +615,12 @@ cd ../.. %if %{build_sng_ss7} #do not delete a thing %else -rm %{prefix}/mod/ftdm_sangoma_ss7* +rm -f %{prefix}/mod/ftmod_sangoma_ss7* %endif %if %{build_sng_isdn} #do not delete a thing %else -rm %{prefix}/mod/ftdm_sangoma_isdn* +rm -f %{prefix}/mod/ftmod_sangoma_isdn* %endif From 65d5932c9ffc17be3df98deb0fe0e3552565eb76 Mon Sep 17 00:00:00 2001 From: Michal Bielicki - cypromis Date: Thu, 17 Feb 2011 10:09:26 +0100 Subject: [PATCH 18/43] fixes for the python esl (we need ESL.py as well) deleting the sangoma modules if they are not defined to be build but are build anyway --- freeswitch.spec | 7 ++++--- libs/esl/python/Makefile | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/freeswitch.spec b/freeswitch.spec index 6b7530d471..1000a89239 100644 --- a/freeswitch.spec +++ b/freeswitch.spec @@ -615,12 +615,12 @@ cd ../.. %if %{build_sng_ss7} #do not delete a thing %else -rm -f %{prefix}/mod/ftmod_sangoma_ss7* +%{__rm} -f %{buildroot}/%{prefix}/mod/ftmod_sangoma_ss7* %endif %if %{build_sng_isdn} #do not delete a thing %else -rm -f %{prefix}/mod/ftmod_sangoma_isdn* +%{__rm} -f %{buildroot}/%{prefix}/mod/ftmod_sangoma_isdn* %endif @@ -1019,7 +1019,8 @@ fi %defattr(-,freeswitch,daemon) %{prefix}/mod/mod_python*.so* %attr(0644, root, bin) /usr/lib/python*/site-packages/freeswitch.py* -%attr(0644, root, bin) /usr/lib/python*/site-packages/_ESL.so* +%attr(0755, root, bin) /usr/lib/python*/site-packages/_ESL.so* +%attr(0755, root, bin) /usr/lib/python*/site-packages/ESL.py* %dir %attr(0750, freeswitch, daemon) %{prefix}/conf/autoload_configs %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/python.conf.xml diff --git a/libs/esl/python/Makefile b/libs/esl/python/Makefile index 784426ee1b..7504665561 100644 --- a/libs/esl/python/Makefile +++ b/libs/esl/python/Makefile @@ -15,6 +15,7 @@ _ESL.so: esl_wrap.o install: _ESL.so install -m 755 _ESL.so $(SITE_DIR) + install -m 755 ESL.py $(SITE_DIR) clean: rm -f *.o *.so *~ From bb797286d012f67e9806ed061c0c14316dd12506 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Thu, 17 Feb 2011 09:17:41 -0500 Subject: [PATCH 19/43] freetdm: increase size of static buffer for DSO path --- libs/freetdm/src/ftdm_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 260892ada0..8b1925f84f 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -4866,7 +4866,7 @@ FT_DECLARE(int) ftdm_load_module(const char *name) { ftdm_dso_lib_t lib; int count = 0, x = 0; - char path[128] = ""; + char path[512] = ""; char *err; ftdm_module_t *mod; From 60395cea462ecfa0f34c546892918a5427979f51 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Thu, 17 Feb 2011 11:44:57 -0500 Subject: [PATCH 20/43] chlog: freetdm: Channel indicator IE only included in first response --- .../src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h | 2 ++ .../ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c | 8 ++++++++ 2 files changed, 10 insertions(+) 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 index 80dc73f0fa..b369deae1f 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -80,6 +80,8 @@ typedef enum { 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), } sngisdn_flag_t; 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 index 23fe08b983..08e5984a4f 100644 --- 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 @@ -821,9 +821,17 @@ ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_s ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId) { + sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data; if (!ftdmchan) { return FTDM_SUCCESS; } + + if (ftdm_test_flag(sngisdn_info, FLAG_SENT_CHAN_ID)) { + /* Indicate channel ID only in first response */ + 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; From 4b62ff799e00a30fb898ddea2633d928d0d24eeb Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 17 Feb 2011 11:32:00 -0600 Subject: [PATCH 21/43] put transport in the request uri on outbound registers if register_transport is set and proxy does not already contain a transport param --- src/mod/endpoints/mod_sofia/sofia.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 825d1bf46e..e9d2cada2e 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -2148,8 +2148,13 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) if (!zstr(from_domain)) { gateway->from_domain = switch_core_strdup(gateway->pool, from_domain); } + + if (!zstr(register_transport) && !switch_stristr("transport=", proxy)) { + gateway->register_url = switch_core_sprintf(gateway->pool, "sip:%s;transport=%s", proxy, register_transport); + } else { + gateway->register_url = switch_core_sprintf(gateway->pool, "sip:%s", proxy); + } - gateway->register_url = switch_core_sprintf(gateway->pool, "sip:%s", proxy); gateway->register_from = switch_core_sprintf(gateway->pool, "", from_user, !zstr(from_domain) ? from_domain : proxy, register_transport); From b36a7c0ba6381699cc9dbbc096aef90bea1ad4d3 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 17 Feb 2011 12:12:43 -0600 Subject: [PATCH 22/43] add multiple-registrations flag to the core similar to mod_sofia --- src/include/private/switch_core_pvt.h | 1 + src/switch_core.c | 2 ++ src/switch_core_sqldb.c | 9 ++++++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index f8c6a794b9..ab0777ed3b 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -248,6 +248,7 @@ struct switch_runtime { int max_sql_buffer_len; switch_dbtype_t odbc_dbtype; char hostname[256]; + int multiple_registrations; }; extern struct switch_runtime runtime; diff --git a/src/switch_core.c b/src/switch_core.c index 66731b61c8..5479229100 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1549,6 +1549,8 @@ static void switch_load_core_config(const char *file) if (tmp > -1 && tmp < 11) { switch_core_session_ctl(SCSC_DEBUG_LEVEL, &tmp); } + } else if (!strcasecmp(var, "multiple-registrations")) { + runtime.multiple_registrations = switch_true(val); } else if (!strcasecmp(var, "sql-buffer-len")) { int tmp = atoi(val); diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index f135e9586d..1274213893 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -1653,7 +1653,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_add_registration(const char *user, c return SWITCH_STATUS_FALSE; } - sql = switch_mprintf("delete from registrations where hostname='%q' and (url='%q' or token='%q')", switch_core_get_hostname(), url, switch_str_nil(token)); + if (runtime.multiple_registrations) { + sql = switch_mprintf("delete from registrations where hostname='%q' and (url='%q' or token='%q')", + switch_core_get_hostname(), url, switch_str_nil(token)); + } else { + sql = switch_mprintf("delete from registrations where reg_user='%q' and realm='%q' and hostname='%q'", + user, realm, switch_core_get_hostname()); + } + switch_cache_db_execute_sql(dbh, sql, NULL); free(sql); From 28242f871ac338876ffafa79dd677485d2ce0f5e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 17 Feb 2011 12:14:48 -0600 Subject: [PATCH 23/43] add multiple-registrations flag to the core similar to mod_sofia --- conf/autoload_configs/switch.conf.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/conf/autoload_configs/switch.conf.xml b/conf/autoload_configs/switch.conf.xml index 95c43331e4..4f72c6a65d 100644 --- a/conf/autoload_configs/switch.conf.xml +++ b/conf/autoload_configs/switch.conf.xml @@ -98,7 +98,9 @@ - + + + From 0f8fb4b1fdb7f9256f21f55ab8c28afa280e7884 Mon Sep 17 00:00:00 2001 From: Raymond Chandler Date: Thu, 17 Feb 2011 14:12:42 -0500 Subject: [PATCH 24/43] add ability to jump to a specific message --- .../applications/mod_voicemail/mod_voicemail.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index 894e49a511..ef843f683c 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -1725,8 +1725,7 @@ static void update_mwi(vm_profile_t *profile, const char *id, const char *domain #define FREE_DOMAIN_ROOT() if (x_user) switch_xml_free(x_user); x_user = NULL - -static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *profile, const char *domain_name, const char *id, int auth) +static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *profile, const char *domain_name, const char *id, int auth, const char *uuid_in) { vm_check_state_t vm_check_state = VM_CHECK_START; switch_channel_t *channel = switch_core_session_get_channel(session); @@ -1900,6 +1899,9 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p cbt.type = play_msg_type; cbt.move = VM_MOVE_NEXT; vm_execute_sql_callback(profile, profile->mutex, sql, listen_callback, &cbt); + if (strcmp(cbt.uuid, uuid_in)) { + continue; + } status = listen_file(session, profile, &cbt); if (cbt.move == VM_MOVE_PREV) { if (cur_message <= 0) { @@ -3154,12 +3156,12 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, vm_p if (*buf != '\0') { greet_key_press: if (switch_stristr(buf, profile->login_keys)) { - voicemail_check_main(session, profile, domain_name, id, 0); + voicemail_check_main(session, profile, domain_name, id, 0, NULL); } else if ((!zstr(profile->operator_ext) || !zstr(operator_ext)) && !zstr(profile->operator_key) && !strcasecmp(buf, profile->operator_key) ) { int argc; char *argv[4]; char *mycmd; - + if ((!zstr(operator_ext) && (mycmd = switch_core_session_strdup(session, operator_ext))) || (!zstr(profile->operator_ext) && (mycmd = switch_core_session_strdup(session, profile->operator_ext)))) { argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); @@ -3292,7 +3294,7 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, vm_p #define VM_DESC "voicemail" -#define VM_USAGE "[check] [auth] []" +#define VM_USAGE "[check] [auth] [] [uuid]" SWITCH_STANDARD_APP(voicemail_function) { @@ -3304,6 +3306,7 @@ SWITCH_STANDARD_APP(voicemail_function) const char *domain_name = NULL; const char *id = NULL; const char *auth_var = NULL; + const char *uuid = NULL; int x = 0, check = 0, auth = 0; switch_channel_t *channel = switch_core_session_get_channel(session); @@ -3363,7 +3366,10 @@ SWITCH_STANDARD_APP(voicemail_function) } if (check) { - voicemail_check_main(session, profile, domain_name, id, auth); + if (argv[x]) { + uuid = argv[x++]; + } + voicemail_check_main(session, profile, domain_name, id, auth, uuid); } else { voicemail_leave_main(session, profile, domain_name, id); } From 2f9357b2a7cd262863459fbce042e17f47563ef8 Mon Sep 17 00:00:00 2001 From: Geovani Ricardo Wiedenhoft Date: Thu, 17 Feb 2011 17:41:56 -0200 Subject: [PATCH 25/43] - fxo-busy-disconnection timer for desconnection on FXO - khomp set changes configuration - KR2GotCategory variable - Disconnection forced R2 signaling (collect call) - restricted, omits the number of origin - Option to enable/disable dial with '#' on FXS - Added KR2StrCategory - Added "khomp dump config" command - KISDNOrigTypeOfNumber, KISDNDestTypeOfNumber, KISDNOrigNumberingPlan, KISDNDestNumberingPlan, KISDNOrigPresentation - New version of commons - Updated documentation --- .../mod_khomp/Install/files/khomp.conf.xml | 24 ++ .../mod_khomp/commons/base/config_commons.hpp | 2 +- .../mod_khomp/commons/base/config_options.hpp | 28 +- .../commons/base/configurator/configfile.cpp | 5 +- .../mod_khomp/commons/base/k3lapi.cpp | 9 + .../mod_khomp/commons/base/k3lapi.hpp | 2 + .../mod_khomp/commons/base/logger.hpp | 67 +---- .../mod_khomp/commons/base/simple_lock.hpp | 4 +- .../base/system/freeswitch/simple_lock.hpp | 2 +- .../mod_khomp/commons/base/verbose.cpp | 4 +- src/mod/endpoints/mod_khomp/docs/Manual.html | 12 +- src/mod/endpoints/mod_khomp/docs/Manual.pdf | Bin 470343 -> 470577 bytes src/mod/endpoints/mod_khomp/docs/README.html | 2 +- src/mod/endpoints/mod_khomp/docs/README.pdf | Bin 399119 -> 399111 bytes .../endpoints/mod_khomp/docs/README_en.html | 3 +- .../endpoints/mod_khomp/docs/README_en.pdf | Bin 314413 -> 314423 bytes .../endpoints/mod_khomp/docs/User_Guide.html | 11 +- .../endpoints/mod_khomp/docs/User_Guide.pdf | Bin 509260 -> 464991 bytes src/mod/endpoints/mod_khomp/include/cli.h | 38 +++ src/mod/endpoints/mod_khomp/include/k3l.h | 13 + .../endpoints/mod_khomp/include/khomp_pvt.h | 29 +- .../mod_khomp/include/khomp_pvt_fxo.h | 26 +- .../mod_khomp/include/khomp_pvt_kxe1.h | 150 +++++++--- src/mod/endpoints/mod_khomp/include/opt.h | 5 +- .../endpoints/mod_khomp/include/revision.h | 2 +- src/mod/endpoints/mod_khomp/src/cli.cpp | 99 ++++++- src/mod/endpoints/mod_khomp/src/khomp_pvt.cpp | 48 ++-- .../endpoints/mod_khomp/src/khomp_pvt_fxo.cpp | 32 ++- .../endpoints/mod_khomp/src/khomp_pvt_gsm.cpp | 3 + .../mod_khomp/src/khomp_pvt_kxe1.cpp | 272 ++++++++++++------ src/mod/endpoints/mod_khomp/src/opt.cpp | 5 +- src/mod/endpoints/mod_khomp/src/spec.cpp | 2 - src/mod/endpoints/mod_khomp/src/utils.cpp | 27 +- 33 files changed, 654 insertions(+), 272 deletions(-) diff --git a/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml b/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml index 79c00516b9..069792935c 100644 --- a/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml +++ b/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml @@ -272,6 +272,15 @@ a FXS branch. --> + + + + ce6+xNn#ae@d3!6TkUfL=E`)^e zF6fO|SkDuFvkltKHcQjb=_awCuj}avsYn0Mv~=`qGfuVg{byQc`a)QIJIw#rBLn}v z&%o60drq=`XSM(N{SWT+MGeL8iwT_HQ!U{u3V5B0ObXt*7(oghRY=SFnunm)vslX1 z-|C2|_QXVwUcWA$?5dwrSp&B9#e)9g68JCi?=c6q6hZi(u)DMYpGb3=Q*==S1_qzl z@BvU>LWm*zoS3Jv41j3kXR$s&=+sM7p#IO6PqNgTJLV9^pi_{cP;=yQSr+F4$oYlL z8cbTw2^MfH}>ZI@|(wP&|#TDB{`Lyv;sydTPXBXL?IFp$)M4ae{mO+y0#qKf&TkdLjC z;0Q+hoW+3o`iC6=s5!}~k^ST{Z4-1zNo0d176WE=0VpTJs6Q3QQpWrjn1Sxf;wHxA zHE@piOfPj$wX%U5cAtuhpY3_rQP*<;P-UBV_4$VFN;}f1#1pseLJMUgWS^+iRa|g_ z=Tx2FEx&DOE_NCBI@ZuYc1{1dx=2G{LwM#vE02{~G{geLNrsRV|`IhZ1_ ziUh`_q-MP3d9Wx+?no*^+eqy=QQ$VRH9y~F91T)tQ68vJP(E3A++GNN!KaprU)eHM zeYq(|NPW^M>j1LiB%-KO@5D6h!&B5b5u)$ji1`~JRTTdMWwpzZK3+9l(g*SOaB#E( zg|uTWjW7nF`gf+V+M6x3=tcaNhn;8fz@jWGViwoRB$j{8AOKKKxa`TM#d6$BM=Y^* zeBkBv#sSRJZWsbM+KX{D?4goVc(3-z+q=l{DTj^r;J_ao`CVL?AIDNJR+o+R>+p?v zl?c%fC~;Ni-G0!462mnwwzQ>ocn7nF2lYjS{!0PSHpN(B*ooKCG4KwN={w)y&Hkku zFI;-yXan@1?VR=*lPTarV~NA^ky9UWn8I0$m`Zx$FH*Zp1 zLj1ete3%0U$I&-{z2G%PoYy=j{b${E7dzbvMVpLMPBZF$-^!U7S$&##@s;Q?GgTc? zbNe8m;-%dWTC2)ew%m``;z#GE!vnH9EW)=r!ed0o3kk{y_42P(o((v5Q8Qw^t=l&_otx-9(pPmyG>l|>fI9@gl*KjrjDRe zf_a}H$Gv-3p<+v&pJ{=j998-kUiM_&no+RCzGdZ1s(8~3+$kut%we@|qy`Y}YMS#+ z0sm(K_HjO6B*(H-XL|3iL1Sc&UG=h#Y}%<4_UlollU0U^%r!NaOK7VV0Jv^NN3yjV z01483kO=OLuT$NZfw}W3yDxX8dms}Y;d9NZS0Ezb7U*fzyt{t2@9#hkfwDv3HxLN}6Si@Cgd^i@QV0A#KtGdV|0 z1S)l^*X^ebtb~G7BgMSPzWU$08||^qQ{DUa82p~k$Md{-4&t-B132CubDvKySHuq= zj*^C)1l}%v_5j}MUO@4K!)-MB=kuBtbj=8`eetRjw_aWS*oTX>fYs~cp4n!r&V@yT zR)RpWYrtjWDvI|~J>PnvD{C8#OLC=+#H^l4x~x=Dd5mbeiy8g$S9@Aj$-$f56J?t5 zwLy1kFzK&cNleR=F+YLR2xcl{YPL%gDac6%&cYBB-MBm*R6ub=g$gR_L}3K!uH*4; zOg2$=+Ppt(+IT)F;B0;9;FI(OF3zBJQXa$CGK2Y zj!Ju}aE6XJStksQ3KnO=&U)eRoHN19U$7q?2)+)Fyl8=wWY^IyA+lp|0(^*ws#+De z@|=igvQya3+TWG04prtZk^w)0-v!b+>?R9M6JM!-eyw~F5!Za1?-i0O=hxNOg@<@v zB8(IxT5J8b&PDj!Zv{NmIr<^(Q6LO4X$Nl>4|1b3bHw`fIsU$qw{<|*+La_8I@PC5 zn>Y3vUi4?aexkiSebu?8W-{N`Uep3Xq{;|Dl>!F4mjRs$?X;p*u)F%%0)u~zW}82< zuvkXm`ep;t3`b^cW=Fw*mUJ|=30)>mQnW_nX)3(e92|h^MuP5GY_JBY%Z2)YS||dU ztZ9#eV~UtALgh0WmfyMVe@Wj$K^&I@VI&F@P$q{Tisie#C5RiSk=`e8<@})61gX^XR@NSu_6QW@sPaJM?X>C8aH(f>#BO1EU!QAlC$z@=()K*}CZyq&9# zn@<;U>X6@irrg3B;jBr07N5M?%&_^$N|XMnpa{@imRuwxC4ov3$Ddp*bApu#Y8^}` zq*g>lRf(VtwlBz}$(909ROwXu{q&wFzZ_i|(vHxG8uhehA!tKGGdA}8UobZJyg*7= z<#FNk5xrpju=DfdbaTf|=^HVvWgdw|r!BcxGoVQ@=@oF2Uy5b?kk*9PYUHi2l%d(B z*zW*C1TtzNlDJ;zsf<+}t)H$DpTWTP(yX*Q)9lgmq6|2{Con?}eg+C6g#4O=Hevax zsUq3$gI$1@BQU`%{2b-WO13UjUlI2}vCx}3T4F3v&U*NK4!WZ6hHvSQ#jeV4Y1cH( z(+~}vpUFb31+~ED?rMn?FjidrJJmfG(EbHDyoyfF=hVU7SB@<&gdYWx~%Ib9wIJDX@^Z$XA>kS5^1Y@Re_QUceaIpGPD9-$L3 zQa0~d6HR^FpFcwclo-Hih1N)J%;;zl<~k%25r5`=$a=52ArFc|4c=cf-tiSzDP)y{qv2Ty{3jA)FR2%@|_ zWA!*Ox`wSq$<`2Pv#j}Y1))w36soIbNof-EOTmn+;2Hz-xEQsPwEs;LtXOifko2Wm zIHH$itfh)js~%LxM!4UEo{c!(4oVD08nZlV#jrQBXs{ds$a@Ebt%y4SBTf#Gi8m6^ z(ftzHVIO_8AFR;he(AMAo;Eqg)OhM&Xu$M0H7&N(hodj?P@UeDfb$%0cT*~ z{33Bpi?24ba^{(X!Nck>^`roJ{}C%xxOcL!uPG6@^)O}J)(2D7M=--fg~P73@!s$C32_~_Y_%k zhRBk+a{Ik#a<3z^$+J>S9~kqyes2NjneF#0{6k`5Uk!7v;$XvOC0qvU%H(Q8sM|Tz z-#ucC?krou*1(GVHAINB>kMz-yMoYNX%>s`|540Q=-#N~buB#$1ByTJJ4 zdnceJ26W|(tNMd=iBAyF+oZ2Ee+ie$M$yZP0i$&HE`9xXuUmcn0pjdbl$d`oTOgH%IS9R*nv?BGQb-u=!)Ghz<6T zom8s0A`41-7LNCu#lz{&m{_gGnvXOAx{@+A%QzhL+>4SH+HAC>)9T(al_{*$p&K&` zvnM-;^z<#Gl!tc9&+=`d{gO6hYUFv*gxN7Vs!5KP&IJU7-C0Vz9@tzR{Vc@_z>yXy zr`h|7yS)k{WtA0yI|Oj@`H10H+Iz&D$dfP6g}axJK~CjcH_B}(@1%(=i*dKTayTOQ zuz;o6DtKGsSS^-!2MRjo5NmgFuq1{<@vV&Udsy$BV+39FQ+X4~U@wkC=5a+~s;lFyMgZvar`CI3_sK&}y_u6ba;+-2H0U0ki2xdq+)rba~^f*?9YMN_lW zi)vow4;eH8joV3&;LPF8d#wGw-arS&(_o@}uA?~+MSNIs%)tln%1niZm=-OWtV|MY zX|fqo^l5vKkD=0Lu)p#TYGPMqpL&L_FJr!yFx{u5-8_(fHm ztF$G}badLA(_O)bN_R{WFo~LknAI8B;{F}$rfE*BWwE>#bkn;Lnc2wj8G3c$@94?X zm_(DQ|CLuED^x}(nU2OiL}j4Rk`i~zG0h*Ky>FJ|#NLHR4V49sUTbZk+r^F7W7EE% z$UO-bc4L4RQ>`f%rTo_YSgc67XkyjFuC<_XAd^qwU<5BU^!51zV3SKL)+AVPGbpK1 zS(J_HjZ>Y$60HMRGONb9s3crMN4P~HT1S3VO(5Y=bmhb$Ai?qcAm@VqY7Ni6(LAtP z&#*S8WjR6E#5^>uDR_}d;tpV-bIKuHUHKu;{W-xz`JOlM+$3g3rfBZqdKh0k5NbqG zEecT*;L4_7ZK7rdI1?vt#pB*g(xNOk4wHoOHAm+~1Pb|#ni~QigNmefdo=Rk^9!nW zgu}*C**RE(4Ve2mS4`r4skG3E^E~xxbU3atMXLUoZKlaMM>QT@7je#iy~R#4S;?~D zcm~w|8|`yl?#r?F0r%yqxV;tZQ5X1*QDNn7t-hG^4K<`2uy01rFEa-*qlHS8m+6Fe zi;!HW&bV^Rs7;7<9I3=b4fo6;|5c_@b?QUQf)(m8lug``NwvH zdRjX9fO0P%h$M=}6^&v$i~nr}q`!}zp3y=%3B06dt6r2Z5QNNZGkroMQGzreH0se^}r7h1V{xyeC+4=|y)_%O0L z%LoAJ!G=Z#i=EVVKTOU#yFRCdR4$!#O;9%Yjz0w>03r8W(=?X74=U}Jd+9*e?ItVh zm^tM{kv_i&DGF2rlQcyhT$g|!R!<5mN9sDvg5Ofcylzt*^e$7aH&yj}G6k@@aRm-_ z7Q@0#dyG0}LPKe1{;*9;x^~T!qV1Gyg1;keLT9U*L}Ng{sriWO6g2gxzkD85Dt3*= zi7Tr$fN=t_uU2B3tX%Fr&Y^OLZQUdkE~ZRbQ|%qI|mum`ZHXWUrr?`5T2j&O4aVMgaqwg!_e(u7J?$3>xqpM5T&T@4@1FrK6^0viF&L=MhREr z66?@2`L~unmi%BMHfK|ms?{7l=+722&K|-V3;hwfW3$Ecuiv|JV1AuHUVZrkOESqP z01Aj|X6=hv4l#cR4k2H=H1;Ni==$lak_Hh|3ma2!X1CkZolDh*?mOrcHLBydYGC)- zFHM=|?8gFsn;cZ>U?(}wq$iG)=EEvnMvF}5@hlk8`ysYUpIscPy(sNO=reP=Iaa@I z17GUJ8yxuG!c!6kyvE+BIX6Qz7qSk%0S4`L$CnL5CAz1WxVQXP9vSp%G6(Z86c2f_yx0~xnIqmt?I##-&k<(`b?>4q8PEJEs#0T+rRCL^o z3X;85C-8`US!opfPxH9HP*ekvG4x0yX)B_kOT?=}!d3N=&-=*c!5K!HTO<#lJ7+T; zeJp?j6}UyKnAl8>l8f)GKRF=<+A>Q%S@;9c?QnFNoHd#p`hJ3N zg%$|5=j#zlPz4SZ`}m|N(MO*#TAsT7B~nK98vlXDCn(V77$HeL*FSV{*#K)M=jczV4MEaL_-B*#D}I`cMk;BJf0CT}K@0HM4ziSjrE z=3%G0hKGaIZ&(;22~xS8LJ$y>Wq%|R$vnK*HnSFA`!WN`pWMH8sId4VKT@-mGt{w$?rp3WkA2>pnVqiq5K42P=!72lnVZiunO8Sku4LXALN5oou^yQ<;bM-Jm-(OJgZq)_0 ztLB`#{)6(mvmw9s3e-xs1+)Sc{iTS0g4pNndZCiPpBb4Nk;$sB!H`k)4Lq|x#jI)` zG}ToRsu8BO0z1%=qQPpx4;Ydq*R8&i3Z3rz=a4qDku=!w0A>U{z0(+9V-J0*KeXPu zst1}!l}`YPR_(u0n~lEtOFcqkZWtbKe-)N1Fh(lVA=_eb#W;R1jo@=S_MeIjI4&h9 zvIuKiuQqQrPOq}?8rnB67V|W0E>;LM%~lj%^(G^1*5xm`?Z8p#ecJ}L@|1#r4*ztw zB?Z4CT!zqmL8!$HFyo#Ngu4#-PK|hiPrys_^0M1Hc%DdLcj|R5gob(OHC&>Qxj( zd)s$$G)bTR${Q9VJp}`bLGT1hSn9_cbmrjZ$Y!vuFjFa5)qm#9$H!Bf`6vek5}@W3 zn5LR@M&fY?*E3OF`GLkLZ69;C75&KH#?*UY7;6#|I18O6ypU+(#mspWFC;<;cBJAi zR+xnf#f}uoz~869j++`HUY>H&>PdIucl(53wQ0Xgh0gqEQ{&G3-v~1O$I6xo!3oOr zUC(=a_HF6kc3$H|@;k0w8Iu`JfUZ-LfMtgLc=<|qVbynb?f8q3XxLUmQDP?PJk?MWT*=A#L?G3N?SH3YtB;5 zRJc_~8A6WxGA&*B2R}Q(*U~X_toPJv>ES+8?ePTVN{yrLWza7SH5f>c&)7OUYAFr7 zpr$SxTu5BDqOK-c%AML2nm{g`=$ zxD_OX(L?EHqOLw5>Jze&a}8%&hrsUcZ&R4D6mghpNuml!$0TAq3@@o~Z&9i}l|fuu zyNV0Hyu3jb|Bg(f-&W1S@ za&$ThE`>}^*zhQ(*02=Qk_yokE7gscY+b|pB=NWahNRt^^R}m@Ygfnp6S$Zjlrtn@ zez$BL+<^gg5po^BN5v2pUZPvkE-Y52dP<1|15XoKy^X-NkE1r`HUfZ(v2F*nL$?am zXKm{R$zb$)T8pH;3e75r>;1LIj)&$DwtvA{a2ClD<|N3A`4Zr5%l8yc*bJMv1W&jH zVK!U66!T`^B)+DHpkMepem0viK|`sPif~J0Dt2ap5?s8p0{UvE{mr}0uX?RGb!%B?N=?RI2{9dgHdDF}TFx?T-ipDjL^2{+sqK7DTUhmxXzj% z3a)39nnBLk8^eL~D~rc%=?fEs=~D?I5UOSQPOy^_8T)CXG*+sIk`bt`3Tn6*NF;F( z-^@VP`;c?Uh4S(LqV22WqTIShr3R$CmF^w}hLCQM?rsq228mHh>1IT_ySqz55fJGT zkPsxKJMQ2)?|aUX_kK6Nd*>g1zr}u5ueH~+pS{3}erpWbee2 zl7{c1{E&eO8$OTZ(%hmi}4W{%uPZc^0go<%G3b`u%&+ zkk-GCF$KfN!o^ZEg(U^#in1!yV^6=dZ}u*{tfYp1p&w_jG0;;Dzwxp5if3(6e1U+9 z7E%jsf*obD67e)}+8YU0#|nXyOc}N&ZaFD5IF_zQj@l9B+~47{$0TgW`i|-#U=1-v z_S|#0RIV`L^fZAt4QL2dZ^rFggG25vJY5$Y3@D1L;uM$LFj_QD8*(sxalU(D=J7R{ zZ48K9vyNQ_S|jZMs^28_T7`CK!dq8b@k`p$Yd@*)s`lr5DB?k0X;5%9>C=<_MPRU6 zLo%YhW2e32c(*Y^f6?$wvZ-TB&n_ghRphO5r+Z0b*)n20=E`HEW)-WC=*CQKG~mFd z4v}@FdgXrM(x#v^X3@hp;WC(|=p9(puT#l%c0b}<0f!S}0QKFaTeK{LL%p!0puDfo zlg?S#w8YKux$JpnFiVIZGLjMIJJZvyn$hVpucA7%bxrurBGa3r%XP;|WTQf^x>g-p z*54sKW@t3;`oe1YrMwJWG}KY5;l8CMi>m7(?6RmbXroy=sbVspq)OO}l^|+ALr(>KIv#-6VABOLvMqE-){>TD zrjuaH!{1FfkKY~NRW)J`A@F{s*o5%0yzX}3OF$0`veB`rZcJg8z!JkciP8IQIHY~i z>L^`KnS9z{`i?h7DN-4&t5SMJ7U}!4v~?R@)U6HTjmhYSUK{rK9zG%4`25N^&*XPD zoz;1R9lg7HK2)9RA%Dh%EGs2ANNtyN3Z-7DpL;2_sY#@BKv;rRFKz|AZB}K|Z?Kxe z5wJ+Km1>25M7^1;q;qzxE7bBf!#LJUzJhag%_+)llvwaGxMVRKhFg2drYW%$#I2$H zwV%J=ICDJxRloFYgo;iY?-3;SiA9n|MIHt_IrjPolY%OvA&sgJkOW@z%Q427k1Fqu zQ&y`U^YL>^GJXg4TVq5)p2#i`R6Qjg&o*YJl5kUZaQe17Erm0P1&Peokl2TR;r?- zx#nGDYFDEeJeI~%u<)U>2zXV@ZX`7JBi+M_-#x7~xRju)dB5@rLH_^kqW54v>}U@k ztmEvx+>)mWJNV6q-+HP21W~8c@O>EVTv)1*ea(=A%Bo7|f;v0s*rF;?HaPd&*`lYc zuJf!A8$7}dwusf&*5vO6y3$NWB!=H>S!F$H7?^7;9%Za=(H4N@il$5BfUHIf6(q(*E!*a_f4{`PeU7!y=1e_1Eex2y;G$DOhukH6<+* zTd$;yXj#bL-m;Y9wj{}EECRkaWiQ0~_8iG+x2euDxc!vlcZtAKwAvHo-U!PbeV3;# z-J(!EukTUX_T|!RmcoZ#J^l@Pp|w8QoHKz}ZtXx4BZP2+ffYeip|m9E@p~?V9i&S5 z$l2O5{vg{7DZ$E?hhWi;DR}nB)BIK6qu1909)Ir;@o&ru6DrJt)gvC(M$~w5^Y!Ck z=|hSfa$WB)=Bo6%O#xAvM~wz~M>Pg3KUg-y^-asneBj#~vmA0CMAjBO%F&2geKcoH zm;AyuT@%uKlGbQ0nAIB?6ZwUFD-tOhh@3dQ*z7ze$aPC1kR`LkZGiVUdsb&b5N`K9 z8h+5L2#iO9pi(&%Hlu+Y^)7F9aQvzJPRULAkQjm;amT2I8q@Y|-TQ1EdP}WTd*U>i zIe>40ZNY8_6IIY)Q5#_y&GND=S)`G^KdFvFFCS#V1TN^toIX^PhIEhAWdkFWvOk42 zt=0b_ng&X^5P&mq^`WC3{PO{?7O>WNJ`K|g5z6XulJ62v#3z-&obYXAotQ%9IFxG6 zBnc{^ye2Z$u*>bcD7Knu&3oVoUQ18=Jy>G;G#r>xIq{IN*G;-XhLl`;RGQJ6^eHy} zWK=DLMRUq73ya3!rqc;!L%?F&Bzu-!1G^ce;)s~$Oh^f9sz#$O&NO%YxritlI_r|6 zE9!@N{n5x_y^Q`9P-Z*F9FuAt2?xokQjVKH30lNOq%_8Zs^TxFCH!Xy2HSsgLBxpbtu>Ph+99ce&LjB?9lh7@-(?^t@Nw?q;iAZ|m91#}ucN3v`yCXe;HkJK~&L3s}Pc|H8HNiSF_Lsvh$w4T9HEYl=QI6cnmHq|_B|qxr zuzgNvuNeE0-A3yAB7G*DR$VQA96pR%lrr8Yc`%vV`s|oCpYW!4T)A)orlf;Jfb)2r za=b%=3d?iVpV@dAXKUw*1rpjwegfWpo&n(LmK$Z|&8s0KI=1E%6Q7EyzVwzV!&lZe zE7b#vv2ya^=MaNc^TQvzBk_meM`7j-ImzfwiwlkWM#*tu4?`KUfcuqo!5T_y5z$UE zim3Lt{yBN%*Uqk<=VXT8SERCBd^%fnxs1^lgbX2At#%%Gwt6eEi|PV+-t62G=9W%Q z>|+N_HW;K|CN3TkG||ora)8kHeQ26fnD7i}XqG7+zJn;3zt{L?5vg87kTI8SHSZCX z6kO-erB9L=#+usKuFnztxTfEj#YSFp)jButGELd}tk0k|d?P%zR%0zfO?Cf=aVp+^ zr{LFZnZUQ*6Q^<&$|E%9i{N;p@nza^Gxaqr-B{sWz`DZl$cOgCm8AeGrO1y&1h`p6 zh4NQn8>f&b`u2GQ?U552iPR-XeT6o|&OT}ZgVPdUXfIW2Z9o6w$twj zHI3x2bookW*e(?xl=epk#-eAP#MYjss3nLt$YYUqg)WwwF?vOC!L~ujmhrD-I+T4g zLDNHtj4wg=zYyX8`!Jv4_vq`AhJS8-CnB5cDc%d|Caq@@(f8r#xW%zhrFzuT*)p6= z8bd#nxa9wO!XT7aN0iolV{oHRf#JCuJFJv~E^kYNO=Pz~Z}`oV#;`rEL?0NXrvyZ^ z1xoGNR_kaw5T0_JeI;o}dmF8nCU#DB0>;0rjt3P19XQrW+!aXS)->^G2l!R$6^v|KRgl zqIegNBF;)M^x|6BkXFgy(Ih&Tcyp|=Zw-V!lf>iUNsXVKeG21lAaCGP0x`Is2>}FN zB00KeFSJNB9~n~4=vIMFPDDi#wDb@*RJ^d_iad)nbzSh>#|O9HgPI23quS4uuu!b5 zOzS<5g*UNEodWVms%%p_(@`)_5j#k0Qw;ogiqg8t^%G*J&)=d*u=iU;T#ys(IBOuC3$&#G7v4}5Lsa@$b|w# zOD+zTPrFXh@_95RBrY*M*}CgKqAZ9JAvSxuB`OnX?sc4t?gnd1p@KDEsZ005@Y5R^ zq6Wck70=cmAT8VnJ%@(2^DI_@qeEp745aa{7pW(8)^o90o{lmN9MR~}ty!9r+i)ia zeG>UXOI-j5R;w@*{W7tQ64r;TA%!lXVtmCk$oZj9g>o_AwOR5esdL{f2 zZr3f>`*Y^c2P3*#j&gRdcjV?P8y{u&&$$x{7$NR&L=NNg(MNpnc;hzV6eM0rc=1!* zhq;S%6E1w1^fPHYZIkGX)x!bD?XSdaeP*vh&t#K!t)DUK?~c`9(!7;jci$fHm7ozM z-7h!}R$O1_?mG=w6HcwvIX(m$S@Ub|Yp?lh3*~>^C;q=ar1X2A;a`(sY%T24 zv8{3d5yW2kkQe{@tFiNxvRF2i++3}t4}BHf2zDSw-57n@rHNU?e$q6Z2jJ;Q^kSO_ zdKQwsIQ;Va)3sFBk)a;SU_^-8TT9O2tU_cgPUV#%!J&L-fLy9*``h=fFT7lMk~^D1 zTDm+-;DozcI6B_3r5dnPDwx!DZFvj#39{^d?S#}&3#=IE6%mw}(7d%LGmX-MU@EaQ z#N^+6VN5aqND!@+2U1C}vz9_Ic$dv1O>FX-O4PA437#E)(WYpd3zTi9++3tPZq?dgzqNDTGkL6fyMlG@Jszz~ z@e1-XfQf$5=GnSL=?l7U_oA%@F3z=`bZmMmlEVW_<~h z#L;P*1+Mb0$a3au#tFh)f;xUb8*|**0bh)sE#ru1S{Uk9G^7znvprNeZ{VW+35TS? zbtC32;V7BxL0pwKZad73v-wn#Eoy$1t>zFO_=(BWZ0{6mc=T=da0ZryEG2yjMeOAF z$R!&hpDf+8SQ_;|vIWbUBt*5zPLARl7a_8iO?RD^7E^*=C#YQc458$SmqgBIFY!H* z*YB1>)gC;YGkWJPiM*9#-l<=PQyw-*F_I+0#~V}BHjjUO(2$X8Rhi2gjbs0Xjqnyy z%Ied7C8>}}^GYh_?0pC7Vr4hZe9rQiuvDtqsf4#W6d20w ze&KZ`(ZwxZX2<2YY2ug)FB+&d25E|Wk?D@`z*D0w96y;pK{Fy5#-hWi2YA&q2Gl>? zoD6ixHxoXk`T*Bw!@zu0O!Vo}3y~!hqO?3&g!x!u^enTmprbRPxr}dqMU}x?LkfJp z*%~hVuGbYP9b}ib#=YkhGQYbVjv_d}NFB8a?cR-4Jf%O!&6kPYH!oEpq^qQN!gW!B zT@BoTTm`ZGB3@EjdUfWG`6@|Ht7w!R71SA6{spAexAJ)k&@u?=V*RK!M<0d zWx@8N7WOk69{SCMEnPqnAE>7vyhj}z$~tPsBY(dGGhY7P=A6Q-&e zb*iM+uTo~uRXa`}eJ`Dnrj0H240#Rf!)NI!n(#*$woR6$Gc z0@Wkcv%76sTM}8>q)lJrUp<2pUsM^5TsJx_5M?13ZWzGV)!o7+E<_;2OqyLIiJS<{Z~T=4ryBoi0q|d^ zz<(|P{^z~pu*3(3*3|;&iSeb>9LBms*C;vFC^-Y4X!z;GDmd%AXhRQc0aOraPKC^8 z44yH;HwGP%>;8zZC`7B@TtB_$^CReYqFWkT^%m|j-rGH^nCm=xfoY23omUwL>Q?YB zibjkfa!|;lC3}%{%bRS}f0FA1$AA5~=VP0-ADf5J{EnpZ+7I*>aJHy%2ah}6=_9o3 ztIcpLy`VqCNq0=|`9!*>CZetiS(?Q>WZ{7T}6o+5fo-8Z}n*%z2|ArM?Sg3>;< zEIB zdEeHmVq~rvf!!cmg~-tV1QY)f)6TYw>FZ{vE^9TbV*GnCG;{WtQo_{FT`pqZkvO=X z`3Co@#grp5IMrrt9$SB*=oE(}Zoa*qwzx$$LzxL*NgjI>i9omcf&2UO^Q#>Nm2#G7 z2jj(npE*-w6t7ben^zZ*ogK!7TDf1A1yWz}NuE1ryn)+ShZ3)AG-tfm?-j^x`oWk~ zlka4*WiUaH&%@>qt^aaiSfKyB;=RRCJzM>9&pc*u3?Mwp9Pgl0cupLiIrBh%Wx3L_iFO!ZViVWxOW%#w|h-@B^AXR`#J29|KL7A(#cX3(#fJ{5y|ReeYmYi4t%?JagI zQ;iI^)?MXTFMPE!fWK_3+O5boyMxr4$jE8D`!?3^tJAmwLIQ0b8ItKza4b;}^AThE zr7j`aIVt;i31_m6T^Y%<Z&X+fv$|6^qY zYv)J{oo)iSLmu~pz6|dwv3SYwtmUE@%K0Qkj5EaI)w(K3B88S4>?^DGy|5TH3AY#V zbz6f>ByPpSmHvPdJ$#>$IOV|Q8RCG>*_LJevNT$2T-gyI1FnXW>FC~gqZ<Ljw|$ zszhI|_c$0unvu%@RUrbQ2m|q~P&j!h?nA&-1?#Ma4ix7vv=dmScYaHNcC zKOj$rnzMn)1u0IX^2QP=9Mg9&jCZxjHZ!OA%QjyLrPiuYvN;gX3M zz-LNo>m`evc)&$MMiX^3A$BpKo*9S}j3YXZ%BtL?>lf z^Wu!>H?eOqyo5w=>w*+d;aFHyS-KM)xY_Zg=pcAVSo~`XIv+EkmNJ*^bjA;rVn4nU zm&(m087`XBWRSME<=}rH`+92WOS(mP;h1ZVBJcS0{=ZSnO#UVDOYF6Lc>it2X|1~JYnDIXimjac7u3!XLH@Hd7|l$S}QObrr}DCRpRo#4$mPQhuZ@O-qt_7$>d zJ@rKLD$ta;d_F>AK^Q@p9F#h*KQtqj&&AEew0t%L` z@V_&0a`gbfi2SgdZGZLugBr90OdwA}C@@;Lt}A~mKbrSB)3!HlOcf>XVJ^@c(+x<` znis+CVkX;;EJky#x|k+o@81awM4Csl?%F{Fop!BKy6Xy>ybCOPWLS&yc)~ zquufOdmDY)x4}#}y8B%M$-|jV3#R+vK(8Q+y;u1rd$>s_ZEU&UD>{N;dv75}RA7Q< z2s2TeWnPaMM^2@lMl#E92Mge?>c8oR(2kLRG*=?UxNaf4 zsj7FdDW>!JK|w~m+()vbvy+Q-VmBAXQ@>s}?E45biTXYFEBs-#4Xrq{7B!xW@|LHd zdVw$jWKD@-@ax3j&rP zyhM!U9Xu9!y22G(mK$Z0v?5u@cOj2wt8z}o54Dp+Yo1jBR<|FLOeU2=mR(pLkxuEE zz_l5+-x2@=qr9B$w<^aO9w#ND1i9PgPtWU)@|f4FQ&`BhEk~IEen)${$F{mu-T*#kaeYujc}xodc^y?w zno0&!9d7{o`deG%$Vr5!kk|(ky2j*30uIGuC<;vY4Gd~K(?(~lc8FBVXkDNik6E{A zu3#MBv4!`Sxi|1zEbkW|NP-_3s^R7kn|S7HrDmd~RehO6-Sk2&nOlonuQySY_7O!F zoHy(Aj2Bksph{P+LQ-0aUVpf!mOirQklR7Bf-GP$rR^)Q-OSFL4MAPzJ*}};i2Y!o zrho1lQl$4FKXHbSo+oZLQ$be$n|J&r3*9k=J=Pa^x|HgWlO@&+>{)KQxsSQ}hYn}7 ziPZa?`-R?31G;78?wt!8-w!|dhWL6u^;mxL4%{)u9xjaopBmL4IN>v?a)=xoi9k=?v z<2H$9gzu5eAeDTxME0dTNuC^E#?ot5*X|oLuRtfb4t>=w<+@dW@xa|K6TPy&KMj96M%kV;L!$?N zMSADJKdzShPg_9$&lU>oKESpJ!7e?%i+TbGtVfpbRE5rl9N?*Zt}ttX;;VIuy5(F& zGlHGKm)|7Qb8QC%*Q07vZ!U%(%LV60X4@bjR7pHOweqyKIvu0Te&|o#{Klp^la|6a z+Y*2Hdd%x_ALt=NZDVS%f^GBwzU_@~_J;(H zAq@1jO43__F0^6P>Y|UTD-)$~T&OmA7D*TVc&OP-2f770fsOGRk7;+F zCMD;5@%fnd`D`bB0%sPa5=Uti#C`L;00Nu|zm4!GuCPIX_mj1Tf$7>Y|*lNO#XK1uVQi&Z+XKMe39k%r*10`hMItfR@ncV#ZW_E^=fu6JoRO)6_gju-N&+bz*C+YjW2K%9*`^+Y{EU2ke6ag z$LhBtP?a% zoVI!cczzYw?cm_rP)!ff$r$CQljgS9m3%t;ZtD}A^%7CcLKh{-WPgsn|K|_JTe;`x ztFXqIC4in`B*$nh>E7Q%krx$!>e8cY_1Vpa`6W zMSu3Zxzy`L=2o7~l`Ws07|upWLToKQ8{2qdiQ{Y(5&iX5;iIo!S&>R}a*0Y-Ed@LI zjTPMEP(uNg)|dJ7v0d1peA&8VNkzGSYeh_8^?fZh2~sE-GnsGp7Nj7$s_TB!?e%7A|gn}~mB z-WrQAtoKZEsPsV8hAlW}LnhmdUbtG>q{72pTlc~oi-#AE*P9|k!a+>5qENc8kbJ3o;+?d4Ro7X6`Fn}< z#C{JG#r2d=J*6|yb|Xo5&sM8OPa{S2w*|V|^1-!?x|l{i-q-mw)es{L0p^vPNHGP- z1sYs4122ts*OXL^NIKu>UY<5*QUVeCwQbSK=kv8KmY_M=#5u$fZ%UP~L@F%GZ%M6N z^p&8_Ui`+NeTBO~w>7YJh*rG4|w1b2VSix&$z zsN0s`$0ZU*s7^6Q#!PbkHb0CFPPnQk;KA;>c)JnSSF9UAU3*_DbZh8W{v{v&Z*08( zG7MXr$oT+phZ}1k`3NXPKwh-J6l>XXg$@h>C=hd+8L^>pUw+Z)`SRbd=v2mFHY`*rNSeUfz|Gf7^OxHVxp1hK|9Om~;5B+b*?_xO^%DJ578XT0E-P zW?d%L>0O~>Q9KB^H1BD@8h5bq*iDL(tF6h4K~8;?FZfNdmnZ_IP*mY{`OhCJ@P=Q{ zai#}je}b3QI-L39*Sa|Ty>fKV{Xj;bi(}(*G1~jpW&Z=MnDozrx_nU3DF7~a#;_Xx z_Q}ChLdX{*Q5&@CQdCt`OQ{?E3qRb>1f;J&9X<^BmiX_BuRBdY>Le}y5zlFYc!Qew zuroSxqpAFx?UdR$4}?UAPKc%4#i6e0r3Qn&yhEPW^#IzzjH+ZMRNjOF^?gbyTm5K* zvC&*h61Sli@ud!mSK`SwSxH1awd=#I`gu%wdl^WB9|t<((2kZz-?I>(h;nYjmz>fm zMxm^^>Gh2Whs8r!MMePnap@l}W}75R8w=Avs~n2uQJ| z%jat&3Q?nc`W{>tug8LYwcP1|-f`5g-8vQ>`sO5;n!lfB3moQDHrT$!3uxxCMylAF zd&~tn_BQ-v9;{@p31T#)Uf-rkn5>BRt{z zAh!5Xa;p8VXN#$^m&ukI$UZO#4oABz= z@v>jJPl8x>^dR4qSY@EcYvo79(*w zACoV~mJNHGh{w!^ez8dpf0o7^-thE|FK1oMsE6SYV?4RbbusGDq3X-m``E$epTqYM zogpJPr35D;sDX@`;(oW?S8;`aH*i;uDi-+IqPOKiRQP-km!-0dW$cQwZ0Dk%5g-N4 zV1`FA=M5ui%j#CQyi90#G+!f7BI?a?c@`~8*Y3h zo>zo}bCt#))4oY@FChC|NP+rl4vSC~)*u3R@=?IjUa%|~vD#$8&>>1S9xilB8a7vlBTxItrH}}+ zveO^oRv&JB?n5lkTAT9x*d`_j|CA&LUMZq`~(hL&r2kALM4QC+}DR*^#;THm_LMjcL~C0BB}`5 z0(cJU0iL@_0W7V%XDh2zX})P!Xg4PCSlrN#`CsW`Z~m{I$^U%w{9EGiTYx2}|UHKS5+I8>txlQok0 z=|%6Mr3>BEC_6bPA`F_e^{#|VMOjZu)ykT%^+8)%#omewoCy=|BRi(LEsFT++!7la z(8V;!Fl>@zMUm8wf z*s?x%Hnq0WX1;yvwYa$)N-PqKp}m_ky~$Sraf$K;mUj+iMc=Zb1{3xo>?;pm<3muM zP0`ai;#gs$jH)kg=;VYT>q?8*Cw+UG$E102?kVvg1qP8L|zZ4 zyf~EfyyKgA;>Vvjc{Q3tarMQQDB1B#PfjBdiZaM7TRxAV6x0VpmVF!bQ0p{>D6M92 ze6mWPB}Bgo&ick-kZ4W+++(BUsG<*Yy*8B9S01 zaXq?q2l$j^bd^S_#Wm9{oQYICD|Kl)VwaC{X2q2wgX}0&oq|3E@45Fk{UANQzYrBFWeZj#h>pN zIDF-2S}$|Kq$6i84|mGgUaZ8X3G(-#`Rw(zKE3PbmWN$P>`>8B4^Eyk zW=~gY^aQo{FZdq!2vI&k##YK(^HpWFS-z2gy&~l9csRMt)#RoH_%MA6mxQ3JcD5Ef zp|3*RjfY8WCH!jo$V}y9Cf|K^f7&pP@#O=+G(Y^rEi2iAsa&EFYM>Cg)%jC1A6Q6) z8@$qH88U#h=pj7_M^}J@*gB}%%VSh3mg<~b)RQ%AfK4z!#o_gcFhOlI<5epohfuFT zsoV}Po`KA9*TRoFYlUtsNBd`n>MNR(VXn?~@b3wsZ8OYi>xW3JNp@j##$4?@NLMWq zv)350#Z!^YW;gMHn-84i>OMO8pl1*+6QtBInR{QNvag)H z*%n)OjZ}2$TF*G%a5xf4b;N{1%a(tohp)^3(`v%@8vu;J&ku$+EC9qH8dahNEzwFH zN4%8SOVG}@;%`N@Fu$6JOIMvk`)E+R7++eDM$+#rFR+F!iFJ>3b(FxRXYMS^>@4ka zy<{q_f0h=ZAFt`~0Isxpj(FR;2^!F~WrsO91CQ@x+h}&)Fi|1)KmwPzWNsDhY@cIe zpXBIbGtLoL$7@SN7QQW_3M>;kR-1e>{(B0m-=MhEDJ(AO_L(uSz1R@%)X z2XQYWU5YZOIq=+Tijv!T5ow^Y>^*6{iNuB;?OK=`^6iJ@hweMf>|C#()&Eekt9b9u z-vlj=W1iT4P6-Xe+p`?`@S)P*J;EZd3E#?NN--F21l`d;fCJ>YrcUUQsVt8MS1g*0p5%GH3g_orq<<0K}h-odspZLMvf!;3hSHw1T8ZIOq zKEHuqhrh`zs49C;-~dehl!1vvqLutJqfaZz=Sh#)5t`pA1RxYC$fc$V;q>(-(N^J# zH6Qhgu(6wPO0&qcw@FivYIf*d&`j1&CtEusj}`2?-BOn;B@b~Zo9i+)vhW_oqpGTV z9@CiZoV|m;wW)wN_rO7<0TWB|=VOMKJFiE^oWy0+HF!wkRfD3(=bAn(+i(p2pwKa= z>xl*wShBpY6b!`dhikVx)F+KGk=@|r+>y`m0wqhHeYKB%S`+^^0wsC2W65Z}G{hq< ziIt!*MQ-|ZV(I%5q^gr%4@$lIE7sLl|EIBzvIg5(&CLtCzq8ssZb+?^6Fd0yNw4m( zVJ9t#Nx)!<_F#4GM_dZZ7>^JZT5jyx^&Q1;BjWhQI!EWja${-c-Cb9MRRq%s&t9*h ze5j$;l8Sv;8Ie_b@D$+em-fA}vQhbFGE}?ubc=hpvfZLkMa0{)2?LU(C-XAPK|A{s zPP)w4+zCn9L{My$D>&{({Z^S+Z8*C>M@sVNK-=s-$(+ zEaz7ai(}a+K!+z{$23fS-K*mp{?A0E2b+Lw$3iwBhEHQyqZ7d9I@b!*QVEHUH3dRH zqK`~R9xjXeNl$)cK){gCprS`vRqbo(pN4mcF!z^L%C?NIy8H)fKP^c9pb9gVs6+-* zIr=emdFw1mhm|tR?_rF%bo5P>O*GETEjxwCh#(sbrR6WliHy1pUhN*sa}KMqtMvu4 z9#F>vPr=l(zyz-@?%|SC+~I4Xx0w-rq95I?z)0)HY4Z$@h1&3yPoX25ca}=}@!vjd zSpNgS2Nhidc*6BGG_C=55dh>TJ%u9Z(9%uV%k4VoVGdMo@0VA+*!%0#-haJ<38v)c z`{O(RKMTqK{OzA(ANC1@i<|$~c}Eh+X~lFgmfC|@TpPb;n+M=3yd2ptl*|Walzg!= z;rp@u^RXUBKLvecRC%Kzq+XXVRmSTf8nK-s>1A|9n^)SSd?O(Y5LSy5^~j&D zf^>#*$iWhvOHm!M6@^<{7Lz*M>H;{=ld`M{W8!-vxP~OvZHJF0XliScE@MPqi=a-u ztGS{tHxFe;{b2DRE#PChZ~L>cdTO25DQ~n`cGvt`_2MDI1#Aj@Z@{Ltc_xCVYCh)* z*q;@&%av~~Q6L?{)uPfMABdFL-bZ9UEV0Un>p^48boc|(!{UP#6}g-!>vby7o5-KOBBWo*Aw@^DpW=cWK;g|cKQnLgVUL@Vf2(RaY(29 zQx4>h2e}k-J%}#a)H*4U>iTECWpN5Y&(Bhr+g8pt;Nl&Ud7O$eXRntA2ZxZ1RS>NtI?9vh%=N=&1 zZ0LL8qBQi4-|NXke#&Lq?>2S>$ZaNAi0|!)WhOSv6&9ExtnoofCN`28SxEFADnetQ zT#3HCdBny4EHWLHy?QuaIy5~jf3?#?QQ39OpB*M7d2m)6taxvBTbss~UpT5*UTJXh?B3JL56Gg)&wFh({D?u_9cTGT8&pKz`sE-H8H=yr~O zj<58=6a__g8^;84hWnf(!_Fn*g^qt(bfao#+pzmL4NK2Qjq~r9J({xDPU7bFjT#y{ zST4v)!oTwFNh%S!AqO6lgM;00M{>Ned%K=|>*vz?U{%veKpf5f{YtaeD0tLrr6W6S z6eBYSG}P0L?BGF^!F~fb`zGo9_nswC=_3FotXGNk(SKuVLI3-OoKVJN04F>rC)8#i zwu7sHPItIW>K!#BDyZ@T4kXoI$}~z<)VMq4DJPW5i1CG&a|xkIFg0yKcfsf3`!fZT zFUf5ZqN@d$#<8XRvqjCTnj|pkw=eFpK^r3 zyB5z%y;o7am9VyuKrf)AEfRAO<38?W8WV-glAb)Rdn!t^rNnvNez7byMM5iwMU*>O zDavAKN{q84LB_)CH%!hR+e?7A7r=AbWvl0QAPwn%b>tI;q zDg^PtadAo-b;@~&%GqYTp^_ym#Kk28#y%3?C(H@%d~S(`VIzp<0;j?CM10m_SZ~h* zBJw>#(yr`KMUg<{tyq?Cv7lLqbn6;@X-->Nl@^w(S0HVN$F5r3X@mS02q0~-9c zrmlDfP9piTq=O6tLuMwFly~H)zRWbx0kR@`;j}vaOnXjcj}JK>_i)NE5Z~~%YbhGv zZlj4(!3W%W#Qd9-@o{Y77n`g-qO^WWt4JTir>H4rOdgCFDeRlR`II3AKU$e6K9JMC zP10LQIwd+8Jt2tAhS-dptSA)mnbEygNh^B6B)QLl>l_la@#p~_Vi0yOuLDAz z>E$RX%C`9CCFuzEu!pNrozgY^TOOtbu4d1g!fon$A5x<97iKb?xZ334RFoTA-o|IB z;zb%fHcYO(UHg5LUYaxyP@3Fxl=HTE6!v+3TFa7)K+B?*-3ji7jnD@`)(UgB{#qO^0!C{UQwr1)=2f#D}P^aFv}RVk(w&|{xAJ}|ItIgR@@?L}=tyPOEv4za?tsFvMUz)|*W;Ob1K{Dv3=qzW5$=7TX zihHkW+|py?Po$`jdBC&!lTu1?U-ZoddE1THb8{}u5`Buu`D?1;(Ay@ynIxRh zhNkSA)Q&%P)~b(S$w}s9hdkcWPAJR2ScA97yiu@C{`vuv-=d!Jwa2U$>TI!A^I^TV zx!!^-?nn9ENKMARG7F=yTyAlDf-i~miLP+P4X;;`rakQFC^W`#<=NM|hb zWyKXZm&94{w(^5e_Lm8Gol9Lm_W$;F{aCUwB51 z3#QbD)bP&eF)idAw8}Y=&CyaWDB1+EWZ5Fl`?VAqcTiA9L!BlKUgC!^5RoFTlJ#`q zEImP4Ahrr_$)3U()2r7;aQcY=SvsSxo@4YAc7JxV#pU>JT3A*A*|yPbSHz@j)}WJ= z-cdA@5>bb6_tK2R`aMJpy;Fii#s!7Jk7cBqLMPJ??2^zwV{AxynKN@eIXfmg`TE-m z|K{ziEw-o1CgVF*@9+;0*9(2;o*|UWy^87Yh{t-HOAH0PY^#C#&oS_@he7=o(ISPH z2-=!@x%*#J1H?QEgtoB`zBdn4qm2go(C*}62%v<1_R)%9S*e1kwo*;KZ6~OGwVB+T zh5~G3nDiOrs-RpZOg~&rPlZ0}n&=YeT6p%}yrOdp8)5wiCEr)sb_!Y@{jnA7C3?Qq z-0Hx^D%E`Z>hx*WNpAzTN)zq1X9LR8pI3`!sL0HshSgBk_>3a_ChUb*YMjewFSRVTd1(EkkHgK014(F z(fHKV)r}I!!v!rm2T;QSq3dS=5F9U*>>NM>2Z9P*`~vEn1DK$=7XVVEUk^c(F90lb zcOARbI3yh19o#6{xH+V4T<$P&|GI9K;}5jle9*mf02LepFyQ#1#FsFn zJW#_6023aV^A{E!T|L-eULZdury-Q<0zeFny9D6D2K8P5nBl>k(ESS-KfKWOO8^H9 zDtHNCBm3jc>5nIQz%a6g94aoB9xxWb(6FmteCJ;RXrLxn0CLzfepdi8YS0}ySi`X= zPdHReU0~S>Hu@iOa6zN50fcZ|P=PA|BTOB`*8mbE7*~{P(5E*rwh(UskD(1$fOoL} z6~iNwLCtRfc=Z3o0s5CN{@kfDWCx24JB5Vn&Ta$> zVE@Csg_#xfOQCm2DS;r~L|WuKtLoeW9>XsGzBAY#3ghO3sqYVkLHDl#c!`zBxFr7+ z>^!AOAz*xj=U#eur`K-5bXPybGwi z-@ov2^Kf$B=>qZ_5P0XR|AcV?`Cxr?{{iFU=emot-(cMLVEmjQ*nzEoi~|8V`8Z)Z z{_|PLFNtA5e*WJi0Re%W+%W(7bKsxjfG`E#gK_^2;lIX#?hN_cvpm0R1_Xov!NB_i z@0kPygl!$W#~?Qs&u`j-jpOFL4}*b!X9mQ_e@FLD|NpWH2nYu8{4OyF$a_zPuz_5^ z*%Jf;@&SKm5Cr50{^naC5H~0AZ!~_{9|q(C{$@`Y40um7AZ~8p@9GC}!%+Sv9f+HU z8y1rPP(O&9m-}}ufVd&xyZd*38_37~yGcOY{IF{hej5kkyi1(_d=|uYmyLdd0YQJ0 z`0jrom~^0D0>kA0xB6kwdrkv_S>!%pUjBPp0DDu4gNhX z!(e>(Lza(^_dX5&fB6FBZ))Y|`G;zLNz8xW)9;e{@0#J~#>ch0PoP3|RQl|LYV&iQvK0DNDqeD}kXALd>62=l|@<9BBG@B0kQn!iOD1eRww ze=iR1VD}Od4<{Gb@BRUU@%&4Ye+k0F3B2dPFxb5m41@83DSypBf5kQrCv5)wO%fRF zUWVg=`QUGoz?cT{{B9Ch66O3oNx@*Ce+vTnqvX2Fws(c_-S6KK!NbXWZx(~WV0Xs- zJ`Q{@ws|!+)O{F3$VRz)Ht^%y4ntG4o6R ze@P5W%lFjEb$`;~;rjKq^iOTU!u_5gT-^7H7g&7p{^jU@)_**(Qudx&x$aNLuyOb5 zL>^cb_Iv(-!G14BL3fkqJqBSnoZgF1ShWoE%-?Jb1cC247YOF9zmJ2}YxkZ7f&X4| z-66iKDt_U+)Bj)U=lu^}4Vz`}A>;#t?l~(T|GnCPmlJ%?KX|!d)c<1om;FJ!K(2c! zlNa_X@Vmsk+~E7;xcTqHU{mVyVJZX_pN+YjalNChNIE?^q&rWk>e91sm zz85dmuwJUYq2Pp+bMOVMe;PRX#>DvqhUPs6rJJyvkPeKVcmp8Vki~+F{X;_2lC6NU zF!PyB2=iujD4f`|!Srh+3*myD* zWWi3*M>aq7gh2(e#5DtCd2+%({sZLTv)m`h98>TCkjPmfLjiB@jhqjlCv(|;Xt(1> zKU8RfK5u_|bbrJ3({5MVz!(B8!iUez?g~#XUvFP-G<2QoTj#s?C_Q{5c<1}K;4}!r gMqK}|@w#4DU;B30e-HhpiZyzlUaHmV?(x3*1sc6?6951J diff --git a/src/mod/endpoints/mod_khomp/include/cli.h b/src/mod/endpoints/mod_khomp/include/cli.h index bb251bb16b..5df472bb66 100644 --- a/src/mod/endpoints/mod_khomp/include/cli.h +++ b/src/mod/endpoints/mod_khomp/include/cli.h @@ -733,17 +733,21 @@ struct Cli options.push_back("fxs-global-orig"); options.push_back("fxs-co-dialtone"); options.push_back("fxs-bina"); + options.push_back("fxs-sharp-dial"); options.push_back("disconnect-delay"); options.push_back("delay-ringback-co"); options.push_back("delay-ringback-pbx"); options.push_back("ignore-letter-dtmfs"); options.push_back("fxo-send-pre-audio"); + options.push_back("fxo-busy-disconnection"); options.push_back("fxs-digit-timeout"); options.push_back("drop-collect-call"); options.push_back("kommuter-activation"); options.push_back("kommuter-timeout"); options.push_back("user-transfer-digits"); options.push_back("flash-to-digits"); + options.push_back("accountcode"); + options.push_back("audio-packet-length"); brief = "Get configuration options in the Khomp channel."; @@ -821,17 +825,21 @@ struct Cli options.push_back("fxs-global-orig"); options.push_back("fxs-co-dialtone"); options.push_back("fxs-bina"); + options.push_back("fxs-sharp-dial"); options.push_back("disconnect-delay"); options.push_back("delay-ringback-co"); options.push_back("delay-ringback-pbx"); options.push_back("ignore-letter-dtmfs"); options.push_back("fxo-send-pre-audio"); + options.push_back("fxo-busy-disconnection"); options.push_back("fxs-digit-timeout"); options.push_back("drop-collect-call"); options.push_back("kommuter-activation"); options.push_back("kommuter-timeout"); options.push_back("user-transfer-digits"); options.push_back("flash-to-digits"); + options.push_back("accountcode"); + options.push_back("audio-packet-length"); brief = "Ajust configuration options in the Khomp channel."; @@ -933,6 +941,36 @@ struct Cli bool execute(int argc, char *argv[]); } KhompRevision; + /* khomp dump config */ + static struct _KhompDumpConfig : public Command + { + _KhompDumpConfig() + { + complete_name = "dump config"; + brief = "Dump configuration values on screen."; + + usage = \ +"\nUsage: khomp dump config\n\n" \ +"Dump configuration values loaded on memory.\n "; + + _commands.push_back(this); + } + + /* just to hide unavaible options */ + bool removeUnavaible(const std::string &s) + { + if(s == "atxfer" || s == "blindxfer" || s == "callgroup" || + s == "mohclass" || s == "native-bridge" || s == "recording" || + s == "record-prefix" || s == "transferdigittimeout" || + s == "pickupgroup" || s == "has-ctbus" || + s == "user-transfer-digits") + return true; + return false; + } + + bool execute(int argc, char *argv[]); + } KhompDumpConfig; + /* khomp send command */ static struct _KhompSendCommand : public Command { diff --git a/src/mod/endpoints/mod_khomp/include/k3l.h b/src/mod/endpoints/mod_khomp/include/k3l.h index 046bd666b1..51686d0296 100644 --- a/src/mod/endpoints/mod_khomp/include/k3l.h +++ b/src/mod/endpoints/mod_khomp/include/k3l.h @@ -231,6 +231,8 @@ struct KVoIPSeize #define CM_USER_INFORMATION 0x0F +#define CM_USER_INFORMATION_EX 0x2B + #define CM_VOIP_SEIZE 0x23 @@ -369,6 +371,8 @@ struct KVoIPSeize #define EV_USER_INFORMATION 0x0F +#define EV_USER_INFORMATION_EX 0x1D + #define EV_DIALED_DIGIT 0x10 #define EV_SIP_REGISTER_INFO 0x11 @@ -713,6 +717,8 @@ enum KH100CtbusFreq #define CM_START_CADENCE 0xA1 #define CM_STOP_CADENCE 0xA2 + +#define CM_SET_INPUT_MODE 0xA3 #if !defined KR2D_H #define KR2D_H @@ -925,6 +931,7 @@ enum KSignGroupII #ifndef _KISDN_H_ #define _KISDN_H_ #define KMAX_USER_USER_LEN 32 +#define KMAX_USER_USER_EX_LEN 254 #define KMAX_SUBADRESS_INFORMATION_LEN 20 enum KQ931Cause @@ -1845,6 +1852,12 @@ struct KUserInformation int32 UserInfoLength; byte UserInfo[ KMAX_USER_USER_LEN ]; }; +struct KUserInformationEx +{ + int32 ProtocolDescriptor; + int32 UserInfoLength; + byte UserInfo[ KMAX_USER_USER_EX_LEN ]; +}; struct KISDNSubaddressInformation { KQ931TypeOfSubaddress TypeOfSubaddress; diff --git a/src/mod/endpoints/mod_khomp/include/khomp_pvt.h b/src/mod/endpoints/mod_khomp/include/khomp_pvt.h index d09be88567..b17d163cc6 100644 --- a/src/mod/endpoints/mod_khomp/include/khomp_pvt.h +++ b/src/mod/endpoints/mod_khomp/include/khomp_pvt.h @@ -305,8 +305,6 @@ struct KhompPvt { try { - //std::string type((name == "input_volume")?"input":"output"); - int i = Strings::tolong(value); if (i < -10 || i > 10) @@ -614,6 +612,7 @@ public: virtual bool indicateRinging(); virtual bool sendDtmf(std::string digit); + virtual void cleanupIndications(bool force); /* Methods */ @@ -849,7 +848,31 @@ public: if(!name) return NULL; - return switch_core_get_variable(name); +#if SWITCH_LESS_THAN(1,0,6) + const char * tmp = switch_core_get_variable(name); + + if(!tmp) return NULL; + + const char * val = strdup(tmp); + + return val; +#else + return switch_core_get_variable_dup(name); +#endif + } + + void freeFSGlobalVar(const char ** val) + { + if(!val || !*val) return; + +#if SWITCH_LESS_THAN(1,0,6) + free((void *)*val); + *val = NULL; +#else + char * v = (char *)*val; + switch_safe_free(v); + *val=NULL; +#endif } bool mixer(const char *file, const char *func, int line, diff --git a/src/mod/endpoints/mod_khomp/include/khomp_pvt_fxo.h b/src/mod/endpoints/mod_khomp/include/khomp_pvt_fxo.h index d91705b626..6e51af35bd 100644 --- a/src/mod/endpoints/mod_khomp/include/khomp_pvt_fxo.h +++ b/src/mod/endpoints/mod_khomp/include/khomp_pvt_fxo.h @@ -138,7 +138,7 @@ struct KhompPvtFXO: public KhompPvt TriState _var_fax_adjust; - //ChanTimer::Index _idx_disconnect; + ChanTimer::Index _busy_disconnect; }; /******************************************************************************/ KhompPvtFXO(K3LAPIBase::GenericTarget & target) : KhompPvt(target) @@ -240,6 +240,7 @@ struct KhompPvtFXO: public KhompPvt bool autoGainControl(bool enable); void setAnswerInfo(int answer_info); bool indicateBusyUnlocked(int cause, bool sent_signaling = false); + static void busyDisconnect(Board::KhompPvt * pvt); void reportFailToReceive(int fail_code); bool validContexts(MatchExtension::ContextListType & contexts, std::string extra_context = ""); @@ -266,13 +267,20 @@ struct KhompPvtFXO: public KhompPvt virtual bool cleanup(CleanupType type = CLN_HARD) { - //Board::board(_target.device)->_timers.del(callFXO()->_idx_disconnect); - //callFXO()->_idx_disconnect.reset(); - + try + { + Board::board(_target.device)->_timers.del(callFXO()->_busy_disconnect); + } + catch (K3LAPITraits::invalid_device & err) + { + LOG(ERROR, PVT_FMT(target(), "Unable to get device: %d!") % err.device); + } + call()->_flags.clear(Kflags::CALL_WAIT_SEIZE); call()->_flags.clear(Kflags::EARLY_RINGBACK); _transfer->clear(); + callFXO()->_busy_disconnect.reset(); switch (type) { @@ -312,6 +320,16 @@ struct KhompPvtFXO: public KhompPvt // static void delayedDisconnect(Board::KhompPvt * pvt); + void cleanupIndications(bool force) + { + if (call()->_indication == INDICA_BUSY && !force) + { + DBG(FUNC, PVT_FMT(_target, "skipping busy indication cleanup on FXO channel.")); + return; + } + + KhompPvt::cleanupIndications(force); + } }; /******************************************************************************/ /******************************************************************************/ diff --git a/src/mod/endpoints/mod_khomp/include/khomp_pvt_kxe1.h b/src/mod/endpoints/mod_khomp/include/khomp_pvt_kxe1.h index 0267f33f24..c32071b981 100644 --- a/src/mod/endpoints/mod_khomp/include/khomp_pvt_kxe1.h +++ b/src/mod/endpoints/mod_khomp/include/khomp_pvt_kxe1.h @@ -272,24 +272,39 @@ struct KhompPvtISDN: public KhompPvtE1 bool process(std::string name, std::string value = "") { - if (name == "uui") + if ((name == "uui" ) || (name == "uui_ex")) { - Strings::vector_type values; - Strings::tokenize(value, values, "#", 2); - - try + if(value.find("#") != std::string::npos) { - std::string uui_proto_s = values[0]; - std::string uui_data_s = values[1]; + Strings::vector_type values; + Strings::tokenize(value, values, "#", 2); - _uui_descriptor = Strings::toulong(uui_proto_s); - _uui_information.append(uui_data_s); + try + { + std::string uui_proto_s = values[0]; + _uui_extended = (name == "uui_ex"); + _uui_descriptor = Strings::toulong(uui_proto_s); + _uui_information.clear(); - DBG(FUNC, FMT("uui adjusted (%s, '%s')!") % uui_proto_s.c_str() % uui_data_s.c_str()); - } - catch (...) + for (unsigned int i = 0; i < values[1].size(); ++i) + _uui_information += STG(FMT("%02hhx") % ((unsigned char)values[1][i])); + + DBG(FUNC, FMT("uui adjusted (ex=%s, proto=%s, data='%s')!") + % (_uui_extended ? "true" : "false") + % uui_proto_s.c_str() + % _uui_information.c_str()); + } + catch (...) + { + LOG(ERROR, FMT("invalid %s protocol descriptor: '%s' is not a number.") + % (_uui_extended ? "uui_ex" : "uui") + % value.c_str()); + } + } + else { - LOG(ERROR, FMT("invalid uui protocol descriptor: '%s' is not a number.") % value.c_str()); + LOG(ERROR, FMT("invalid %s protocol descriptor, need a '#'.") + % (_uui_extended ? "uui_ex" : "uui")) } } else if (name == "usr_xfer") @@ -306,6 +321,7 @@ struct KhompPvtISDN: public KhompPvtE1 bool clear() { + _uui_extended = false; _uui_descriptor = -1; _uui_information.clear(); _isdn_cause = -1; @@ -322,6 +338,7 @@ struct KhompPvtISDN: public KhompPvtE1 long int _uui_descriptor; std::string _uui_information; long int _isdn_cause; + bool _uui_extended; /* what should we dial to trigger an user-signaled transfer? */ /* used for xfer on user signaling */ @@ -329,6 +346,13 @@ struct KhompPvtISDN: public KhompPvtE1 std::string _user_xfer_buffer; std::string _digits_buffer; std::string _qsig_number; + + /* isdn information */ + std::string _isdn_orig_type_of_number; + std::string _isdn_orig_numbering_plan; + std::string _isdn_dest_type_of_number; + std::string _isdn_dest_numbering_plan; + std::string _isdn_orig_presentation; }; /******************************************************************************/ @@ -429,12 +453,29 @@ struct KhompPvtISDN: public KhompPvtE1 std::string descriptor = STG(FMT("%d") % callISDN()->_uui_descriptor); + setFSChannelVar("KUserInfoExtended", (callISDN()->_uui_extended ? "true" : "false")); setFSChannelVar("KUserInfoDescriptor", descriptor.c_str()); setFSChannelVar("KUserInfoData", callISDN()->_uui_information.c_str()); + callISDN()->_uui_extended = false; callISDN()->_uui_descriptor = -1; callISDN()->_uui_information.clear(); } + + if (!callISDN()->_isdn_orig_type_of_number.empty()) + setFSChannelVar("KISDNOrigTypeOfNumber", callISDN()->_isdn_orig_type_of_number.c_str()); + + if (!callISDN()->_isdn_dest_type_of_number.empty()) + setFSChannelVar("KISDNDestTypeOfNumber", callISDN()->_isdn_dest_type_of_number.c_str()); + + if (!callISDN()->_isdn_orig_numbering_plan.empty()) + setFSChannelVar("KISDNOrigNumberingPlan", callISDN()->_isdn_orig_numbering_plan.c_str()); + + if (!callISDN()->_isdn_dest_numbering_plan.empty()) + setFSChannelVar("KISDNDestNumberingPlan", callISDN()->_isdn_dest_numbering_plan.c_str()); + + if (!callISDN()->_isdn_orig_presentation.empty()) + setFSChannelVar("KISDNOrigPresentation", callISDN()->_isdn_orig_presentation.c_str()); } catch(Board::KhompPvt::InvalidSwitchChannel & err) { @@ -444,8 +485,33 @@ struct KhompPvtISDN: public KhompPvtE1 KhompPvtE1::setSpecialVariables(); } - Transfer * _transfer; + virtual void getSpecialVariables() + { + try + { + const char * isdn_orig_type = getFSChannelVar("KISDNOrigTypeOfNumber"); + const char * isdn_dest_type = getFSChannelVar("KISDNDestTypeOfNumber"); + const char * isdn_orig_numbering = getFSChannelVar("KISDNOrigNumberingPlan"); + const char * isdn_dest_numbering = getFSChannelVar("KISDNDestNumberingPlan"); + const char * isdn_orig_presentation = getFSChannelVar("KISDNOrigPresentation"); + LOG(ERROR, PVT_FMT(_target,"ISDNORIG: %s") % (isdn_orig_type ? isdn_orig_type : "")); + + callISDN()->_isdn_orig_type_of_number = (isdn_orig_type ? isdn_orig_type : ""); + callISDN()->_isdn_dest_type_of_number = (isdn_dest_type ? isdn_dest_type : ""); + callISDN()->_isdn_orig_numbering_plan = (isdn_orig_numbering ? isdn_orig_numbering : ""); + callISDN()->_isdn_dest_numbering_plan = (isdn_dest_numbering ? isdn_dest_numbering : ""); + callISDN()->_isdn_orig_presentation = (isdn_orig_presentation ? isdn_orig_presentation : ""); + } + catch(Board::KhompPvt::InvalidSwitchChannel & err) + { + LOG(ERROR, PVT_FMT(_target, "(ISDN) %s") % err._msg.c_str()); + } + + KhompPvt::getSpecialVariables(); + } + + Transfer * _transfer; }; /******************************************************************************/ /********************************* R2 Channel *********************************/ @@ -472,7 +538,6 @@ struct KhompPvtR2: public KhompPvtE1 { LOG(ERROR, FMT("invalid r2 category: '%s' is not a number.") % value.c_str()); } - } else { @@ -554,7 +619,23 @@ struct KhompPvtR2: public KhompPvtE1 { return (CallR2 *)call(); } - + + bool forceDisconnect(void) + { + char cmd[] = { 0x07, (char)(_target.object + 1) }; + + try + { + Globals::k3lapi.raw_command(_target.device, 0, cmd, sizeof(cmd)); + } + catch(K3LAPI::failed_raw_command &e) + { + return false; + } + + return true; + }; + int makeCall(std::string params = ""); bool doChannelAnswer(CommandRequest &); bool doChannelHangup(CommandRequest &); @@ -609,9 +690,9 @@ struct KhompPvtR2: public KhompPvtE1 /* r2 caller category */ if (callR2()->_r2_category != -1) { - setFSChannelVar("KR2GotCategory",Verbose::signGroupII((KSignGroupII)callR2()->_r2_category).c_str()); + setFSChannelVar("KR2GotCategory",STG(FMT("%d") % callR2()->_r2_category).c_str()); + setFSChannelVar("KR2StrCategory",Verbose::signGroupII((KSignGroupII)callR2()->_r2_category).c_str()); } - } catch(Board::KhompPvt::InvalidSwitchChannel & err) { @@ -834,9 +915,9 @@ struct KhompPvtFXS: public KhompPvt _ring_off_ext = -1; _incoming_exten.clear(); - _flash_transfer.clear(); + //_flash_transfer.clear(); - _uuid_other_session.clear(); + //_uuid_other_session.clear(); return Call::clear(); } @@ -850,10 +931,10 @@ struct KhompPvtFXS: public KhompPvt std::string _incoming_exten; - ChanTimer::Index _idx_transfer; + //ChanTimer::Index _idx_transfer; - std::string _flash_transfer; - std::string _uuid_other_session; + //std::string _flash_transfer; + //std::string _uuid_other_session; }; @@ -936,9 +1017,9 @@ struct KhompPvtFXS: public KhompPvt std::string extra_context = ""); bool isOK(void); - bool startTransfer(); - bool stopTransfer(); - bool transfer(std::string & context, bool blind = false); + //bool startTransfer(); + //bool stopTransfer(); + //bool transfer(std::string & context, bool blind = false); bool hasNumberDial() { return false; } @@ -996,7 +1077,7 @@ struct KhompPvtFXS: public KhompPvt static OrigToNseqMapType generateNseqMap(); static void dialTimer(KhompPvt * pvt); - static void transferTimer(KhompPvt * pvt); + //static void transferTimer(KhompPvt * pvt); static std::string padOrig(std::string orig_base, unsigned int padding) { @@ -1015,21 +1096,16 @@ struct KhompPvtFXS: public KhompPvt return STG(FMT(STG(FMT("%%0%dd") % orig_size)) % (orig_numb + padding)); } - /* - virtual void getSpecialVariables() + void cleanupIndications(bool force) { - try + if (call()->_indication == INDICA_BUSY && !force) { - } - catch(Board::KhompPvt::InvalidSwitchChannel & err) - { - LOG(ERROR, PVT_FMT(_target, "(FXS) %s") % err._msg.c_str()); + DBG(FUNC, PVT_FMT(_target, "skipping busy indication cleanup on FXS channel.")); + return; } - KhompPvt::getSpecialVariables(); + KhompPvt::cleanupIndications(force); } - */ - }; /******************************************************************************/ /******************************************************************************/ diff --git a/src/mod/endpoints/mod_khomp/include/opt.h b/src/mod/endpoints/mod_khomp/include/opt.h index 270adc7068..4bc65361a6 100644 --- a/src/mod/endpoints/mod_khomp/include/opt.h +++ b/src/mod/endpoints/mod_khomp/include/opt.h @@ -108,10 +108,13 @@ struct Options Config::Value< bool > _recording; Config::Value< bool > _has_ctbus; Config::Value< bool > _fxs_bina; - Config::Value< bool > _fxo_send_pre_audio; + Config::Value< bool > _fxs_sharp_dial; Config::Value< bool > _drop_collect_call; Config::Value< bool > _ignore_letter_dtmfs; Config::Value< bool > _optimize_audio_path; + + Config::Value< bool > _fxo_send_pre_audio; + Config::Value< unsigned int > _fxo_busy_disconnection; Config::Value< bool > _auto_fax_adjustment; Config::Value< unsigned int > _fax_adjustment_timeout; diff --git a/src/mod/endpoints/mod_khomp/include/revision.h b/src/mod/endpoints/mod_khomp/include/revision.h index b0ace1ad42..717124dda9 100644 --- a/src/mod/endpoints/mod_khomp/include/revision.h +++ b/src/mod/endpoints/mod_khomp/include/revision.h @@ -1 +1 @@ -#define MOD_KHOMP_VERSION "1.0 - (rev: 5891)" +#define MOD_KHOMP_VERSION "1.0 - (rev: 6034)" diff --git a/src/mod/endpoints/mod_khomp/src/cli.cpp b/src/mod/endpoints/mod_khomp/src/cli.cpp index 621afe6a20..b5bcbdd924 100644 --- a/src/mod/endpoints/mod_khomp/src/cli.cpp +++ b/src/mod/endpoints/mod_khomp/src/cli.cpp @@ -75,6 +75,7 @@ void Cli::registerCommands(APIFunc func,switch_loadable_module_interface_t **mod " khomp channels unblock {all | all | }\n" \ " khomp clear links [ []]\n" \ " khomp clear statistics [ []]\n" \ +" khomp dump config\n" \ " khomp get