From 6872ab5682ad170da8e214fb1c8091ea53b3413a Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 24 Oct 2013 14:29:29 -0500 Subject: [PATCH 01/31] FS-5910 --resolve --- src/include/switch_types.h | 2 ++ src/mod/endpoints/mod_sofia/sofia.c | 1 + 2 files changed, 3 insertions(+) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 758fe54c5b..3e2aeedfa6 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -27,6 +27,7 @@ * Bret McDanel * Joseph Sullivan * Raymond Chandler + * Emmanuel Schmidbauer * * switch_types.h -- Data Types * @@ -945,6 +946,7 @@ typedef enum { SWITCH_MESSAGE_INDICATE_BLIND_TRANSFER_RESPONSE, SWITCH_MESSAGE_INDICATE_STUN_ERROR, SWITCH_MESSAGE_INDICATE_MEDIA_RENEG, + SWITCH_MESSAGE_REFER_EVENT, SWITCH_MESSAGE_ANSWER_EVENT, SWITCH_MESSAGE_PROGRESS_EVENT, SWITCH_MESSAGE_RING_EVENT, diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 9230944a43..0dcc750327 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -6785,6 +6785,7 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t exten = (char *) refer_to->r_url->url_user; } + switch_core_session_queue_indication(session, SWITCH_MESSAGE_REFER_EVENT); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Process REFER to [%s@%s]\n", exten, (char *) refer_to->r_url->url_host); switch_channel_set_variable(tech_pvt->channel, "transfer_disposition", "recv_replace"); From c84e378ac4b41ac2a87d1c5dfa957d7b158b520d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Czu=C5=82ada?= Date: Mon, 28 Oct 2013 11:15:32 +0100 Subject: [PATCH 02/31] Trailing space removed --- src/mod/endpoints/mod_sofia/sofia.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 0dcc750327..181da7aea7 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -179,7 +179,7 @@ static void extract_header_vars(sofia_profile_t *profile, sip_t const *sip, if (sip->sip_route) { if ((full = sip_header_as_string(nh->nh_home, (void *) sip->sip_route))) { const char *v = switch_channel_get_variable(channel, "sip_full_route"); - if (!v) { + if (!v) { switch_channel_set_variable(channel, "sip_full_route", full); } su_free(nh->nh_home, full); From 3eb5c407a32243755575feb7f804927922d5b43c Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 28 Oct 2013 10:14:05 -0500 Subject: [PATCH 03/31] clear before calling callback --- src/switch_ivr_async.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index 3769965c98..cc811d6898 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -476,7 +476,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t * switch_bool_t is_timeout = switch_ivr_dmachine_check_timeout(dmachine); dm_match_t is_match = switch_ivr_dmachine_check_match(dmachine, is_timeout); switch_status_t r, s; - int clear = 0; if (is_match == DM_MATCH_NEVER) { is_timeout++; @@ -504,6 +503,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t * dmachine->is_match = 1; dmachine->match.type = DM_MATCH_POSITIVE; + switch_ivr_dmachine_clear(dmachine); if (dmachine->last_matching_binding->callback) { s = dmachine->last_matching_binding->callback(&dmachine->match); @@ -537,7 +537,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t * } - clear++; } else if (is_timeout) { r = SWITCH_STATUS_TIMEOUT; } else if (is_match == DM_MATCH_NONE && dmachine->cur_digit_len == dmachine->max_digit_len) { @@ -547,6 +546,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t * } if (r != SWITCH_STATUS_FOUND && r != SWITCH_STATUS_SUCCESS && r != SWITCH_STATUS_BREAK) { + switch_ivr_dmachine_clear(dmachine); switch_set_string(dmachine->last_failed_digits, dmachine->digits); dmachine->match.match_digits = dmachine->last_failed_digits; @@ -569,13 +569,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t * } - clear++; } - - if (clear) { - switch_ivr_dmachine_clear(dmachine); - } - + dmachine->last_return = r; switch_mutex_unlock(dmachine->mutex); From 95a1ef1e5df51f515363ab29bb8d7fad29145525 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 28 Oct 2013 10:20:42 -0500 Subject: [PATCH 04/31] revert --- src/switch_ivr_async.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index cc811d6898..3769965c98 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -476,6 +476,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t * switch_bool_t is_timeout = switch_ivr_dmachine_check_timeout(dmachine); dm_match_t is_match = switch_ivr_dmachine_check_match(dmachine, is_timeout); switch_status_t r, s; + int clear = 0; if (is_match == DM_MATCH_NEVER) { is_timeout++; @@ -503,7 +504,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t * dmachine->is_match = 1; dmachine->match.type = DM_MATCH_POSITIVE; - switch_ivr_dmachine_clear(dmachine); if (dmachine->last_matching_binding->callback) { s = dmachine->last_matching_binding->callback(&dmachine->match); @@ -537,6 +537,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t * } + clear++; } else if (is_timeout) { r = SWITCH_STATUS_TIMEOUT; } else if (is_match == DM_MATCH_NONE && dmachine->cur_digit_len == dmachine->max_digit_len) { @@ -546,7 +547,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t * } if (r != SWITCH_STATUS_FOUND && r != SWITCH_STATUS_SUCCESS && r != SWITCH_STATUS_BREAK) { - switch_ivr_dmachine_clear(dmachine); switch_set_string(dmachine->last_failed_digits, dmachine->digits); dmachine->match.match_digits = dmachine->last_failed_digits; @@ -569,8 +569,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t * } + clear++; } - + + if (clear) { + switch_ivr_dmachine_clear(dmachine); + } + dmachine->last_return = r; switch_mutex_unlock(dmachine->mutex); From 98634890107dee9b4f4751216f38135be6b83c13 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 29 Oct 2013 02:07:50 +0500 Subject: [PATCH 05/31] FS-5917 --resolve --- src/include/switch_version.h.template | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/include/switch_version.h.template b/src/include/switch_version.h.template index 2e253dc69f..06169d603f 100644 --- a/src/include/switch_version.h.template +++ b/src/include/switch_version.h.template @@ -37,11 +37,17 @@ extern "C" { #endif +#if UINTPTR_MAX == 0xffffffffffffffff +#define _fs__bits "64bit" +#else +#define _fs__bits "32bit" +#endif + #define SWITCH_VERSION_MAJOR "@SWITCH_VERSION_MAJOR@" #define SWITCH_VERSION_MINOR "@SWITCH_VERSION_MINOR@" #define SWITCH_VERSION_MICRO "@SWITCH_VERSION_MICRO@" -#define SWITCH_VERSION_REVISION "@SWITCH_VERSION_REVISION@" -#define SWITCH_VERSION_REVISION_HUMAN "@SWITCH_VERSION_REVISION_HUMAN@" +#define SWITCH_VERSION_REVISION "@SWITCH_VERSION_REVISION@" "~" _fs__bits +#define SWITCH_VERSION_REVISION_HUMAN "@SWITCH_VERSION_REVISION_HUMAN@" " " _fs__bits #define SWITCH_VERSION_FULL SWITCH_VERSION_MAJOR "." SWITCH_VERSION_MINOR "." SWITCH_VERSION_MICRO SWITCH_VERSION_REVISION #define SWITCH_VERSION_FULL_HUMAN SWITCH_VERSION_MAJOR "." SWITCH_VERSION_MINOR "." SWITCH_VERSION_MICRO " " SWITCH_VERSION_REVISION_HUMAN From ccc013e032756c0fcbb8fe32a6d347d26a6a281d Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 29 Oct 2013 03:48:55 +0500 Subject: [PATCH 06/31] opus drama stable edition --- src/mod/endpoints/mod_sofia/sofia_glue.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 9839688ca0..92e018acce 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -39,13 +39,13 @@ switch_cache_db_handle_t *_sofia_glue_get_db_handle(sofia_profile_t *profile, const char *file, const char *func, int line); #define sofia_glue_get_db_handle(_p) _sofia_glue_get_db_handle(_p, __FILE__, __SWITCH_FUNC__, __LINE__) -static int get_channels(const switch_codec_implementation_t *imp) +static int get_channels(const char *name, int dft) { - if (!strcasecmp(imp->iananame, "opus")) { + if (!strcasecmp(name, "opus")) { return 2; /* IKR???*/ } - return imp->number_of_channels; + return dft ? dft : 1; } void sofia_glue_set_udptl_image_sdp(private_object_t *tech_pvt, switch_t38_options_t *t38_options, int insist) @@ -317,7 +317,7 @@ static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen, } if (tech_pvt->ianacodes[i] > 95 || verbose_sdp) { - int channels = get_channels(imp); + int channels = get_channels(imp->iananame, imp->number_of_channels); if (channels > 1) { switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d %s/%d/%d\n", tech_pvt->ianacodes[i], imp->iananame, rate, channels); @@ -547,6 +547,10 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch rate = tech_pvt->adv_rm_rate; + if (!tech_pvt->adv_channels) { + tech_pvt->adv_channels = get_channels(tech_pvt->rm_encoding, 1); + } + if (tech_pvt->adv_channels > 1) { switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d/%d\n", tech_pvt->agreed_pt, tech_pvt->rm_encoding, rate, tech_pvt->adv_channels); @@ -776,7 +780,7 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch rate = imp->samples_per_second; } - channels = get_channels(imp); + channels = get_channels(imp->iananame, imp->number_of_channels); if (channels > 1) { switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d/%d\n", ianacode, imp->iananame, From 1f482302c6206dbc6364b5e00507b189bd350f4b Mon Sep 17 00:00:00 2001 From: William King Date: Mon, 28 Oct 2013 16:56:05 -0700 Subject: [PATCH 07/31] Minor code duplicatation removal. --- src/mod/endpoints/mod_sofia/rtp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/rtp.c b/src/mod/endpoints/mod_sofia/rtp.c index f943933248..cb34325f07 100644 --- a/src/mod/endpoints/mod_sofia/rtp.c +++ b/src/mod/endpoints/mod_sofia/rtp.c @@ -304,7 +304,7 @@ static switch_status_t channel_on_init(switch_core_session_t *session) static switch_status_t channel_on_destroy(switch_core_session_t *session) { - crtp_private_t *tech_pvt = switch_core_session_get_private(session); + crtp_private_t *tech_pvt = NULL; if ((tech_pvt = switch_core_session_get_private(session))) { From 5eddab90646c963b98c80387bccd6bd7c03df600 Mon Sep 17 00:00:00 2001 From: William King Date: Mon, 28 Oct 2013 17:01:13 -0700 Subject: [PATCH 08/31] Fixing printf arg mismatch --- src/mod/languages/mod_lua/mod_lua.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/languages/mod_lua/mod_lua.cpp b/src/mod/languages/mod_lua/mod_lua.cpp index 3d79dd8d0e..a21643bc97 100644 --- a/src/mod/languages/mod_lua/mod_lua.cpp +++ b/src/mod/languages/mod_lua/mod_lua.cpp @@ -350,7 +350,7 @@ static switch_status_t do_config(void) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set event handler: unsuccessful bind\n"); } } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set event handler: no script name\n", event); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set event handler: no script name for event type '%s'\n", event); } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set event handler: unknown event type '%s'\n", event); From 34b030d8311b10d67339dc478a1bf3f229d67af5 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 29 Oct 2013 11:36:31 -0500 Subject: [PATCH 09/31] fifo tweaks for tracking user count --- src/mod/applications/mod_fifo/mod_fifo.c | 64 +++++++++++++++++++++--- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index d3c7a87aa7..9f99b2df7b 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -1067,7 +1067,7 @@ static void do_unbridge(switch_core_session_t *consumer_session, switch_core_ses switch_channel_event_set_data(consumer_channel, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", MANUAL_QUEUE_NAME); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-consumer-stop"); - if (use_count) { + if (outbound_id) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Outbound-ID", outbound_id); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Use-Count", "%d", use_count); } @@ -2218,7 +2218,7 @@ SWITCH_STANDARD_API(fifo_add_outbound_function) } -static void dec_use_count(switch_core_session_t *session, switch_bool_t send_event) +static void dec_use_count(switch_core_session_t *session, const char *type) { char *sql; const char *outbound_id = NULL; @@ -2226,8 +2226,6 @@ static void dec_use_count(switch_core_session_t *session, switch_bool_t send_eve long now = (long) switch_epoch_time_now(NULL); switch_channel_t *channel = switch_core_session_get_channel(session); - do_unbridge(session, NULL); - if ((outbound_id = switch_channel_get_variable(channel, "fifo_outbound_uuid"))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s untracking call on uuid %s!\n", switch_channel_get_name(channel), outbound_id); @@ -2242,11 +2240,14 @@ static void dec_use_count(switch_core_session_t *session, switch_bool_t send_eve fifo_dec_use_count(outbound_id); } - if (send_event) { + do_unbridge(session, NULL); + + if (type) { if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(channel, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", MANUAL_QUEUE_NAME); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "channel-consumer-stop"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Type", type); if (outbound_id) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Outbound-ID", outbound_id); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Use-Count", "%d", fifo_get_use_count(outbound_id)); @@ -2262,7 +2263,7 @@ static switch_status_t hanguphook(switch_core_session_t *session) switch_channel_state_t state = switch_channel_get_state(channel); if (state >= CS_HANGUP && !switch_channel_test_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_DID_HOOK)) { - dec_use_count(session, SWITCH_TRUE); + dec_use_count(session, "manual"); switch_core_event_hook_remove_state_change(session, hanguphook); switch_channel_set_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_DID_HOOK); } @@ -2325,6 +2326,9 @@ SWITCH_STANDARD_APP(fifo_track_call_function) switch_channel_event_set_data(channel, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", MANUAL_QUEUE_NAME); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "channel-consumer-start"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Outbound-ID", data); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Use-Count", "%d", fifo_get_use_count(data)); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Type", "manual"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-CID-Name", cid_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-CID-Number", cid_number); switch_event_fire(&event); @@ -2729,16 +2733,33 @@ SWITCH_STANDARD_APP(fifo_function) const char *url = NULL; const char *caller_uuid = NULL; const char *outbound_id = switch_channel_get_variable(channel, "fifo_outbound_uuid"); + switch_event_t *event; + const char *cid_name = NULL, *cid_number = NULL; //const char *track_use_count = switch_channel_get_variable(channel, "fifo_track_use_count"); //int do_track = switch_true(track_use_count); if (switch_core_event_hook_remove_receive_message(session, messagehook) == SWITCH_STATUS_SUCCESS) { - dec_use_count(session, SWITCH_FALSE); + dec_use_count(session, NULL); switch_core_event_hook_remove_state_change(session, hanguphook); switch_channel_clear_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_TRACKING); } + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { + cid_name = switch_channel_get_variable(channel, "callee_id_name"); + cid_number = switch_channel_get_variable(channel, "callee_id_number"); + + if (!cid_name) { + cid_name = switch_channel_get_variable(channel, "destination_number"); + } + if (!cid_number) { + cid_number = cid_name; + } + } else { + cid_name = switch_channel_get_variable(channel, "caller_id_name"); + cid_number = switch_channel_get_variable(channel, "caller_id_number"); + } + if (!zstr(strat_str)) { if (!strcasecmp(strat_str, "more_ppl")) { strat = STRAT_MORE_PPL; @@ -3148,6 +3169,22 @@ SWITCH_STANDARD_APP(fifo_function) } + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(channel, event); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "channel-consumer-start"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Type", "onhook"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-CID-Name", cid_name); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-CID-Number", cid_number); + if (outbound_id) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Outbound-ID", outbound_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Use-Count", "%d", fifo_get_use_count(outbound_id)); + } + switch_event_fire(&event); + } + + + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(channel, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]); @@ -3221,6 +3258,19 @@ SWITCH_STANDARD_APP(fifo_function) } + + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(channel, event); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", arg_fifo_name); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "channel-consumer-stop"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Type", "onhook"); + if (outbound_id) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Outbound-ID", outbound_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Use-Count", "%d", fifo_get_use_count(outbound_id)); + } + switch_event_fire(&event); + } + del_bridge_call(switch_core_session_get_uuid(session)); del_bridge_call(switch_core_session_get_uuid(other_session)); From 293a9d691180d7daa8ce6b66b902d0c504d3be84 Mon Sep 17 00:00:00 2001 From: Brian West Date: Tue, 29 Oct 2013 12:58:28 -0500 Subject: [PATCH 10/31] Allow proxy media on pickup endpoint --- src/mod/applications/mod_dptools/mod_dptools.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 8d7b5c6f37..b5b7718231 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -3622,6 +3622,9 @@ static switch_call_cause_t pickup_outgoing_channel(switch_core_session_t *sessio switch_core_session_set_private(nsession, tech_pvt); nchannel = switch_core_session_get_channel(nsession); + switch_channel_set_cap(nchannel, CC_PROXY_MEDIA); + switch_channel_set_cap(nchannel, CC_BYPASS_MEDIA); + caller_profile = switch_caller_profile_clone(nsession, outbound_profile); switch_channel_set_caller_profile(nchannel, caller_profile); From 386807f19d6ad43e1cc8ad75f39ac4bbf62aadeb Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 30 Oct 2013 20:30:17 +0500 Subject: [PATCH 11/31] FS-5924 --resolve --- src/switch_core_io.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/switch_core_io.c b/src/switch_core_io.c index aa3e78c911..4b7a0a885e 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -283,6 +283,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi switch_thread_rwlock_rdlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { + ok = SWITCH_TRUE; + if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) { continue; } @@ -345,6 +347,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi if (session->bugs && switch_test_flag((*frame), SFF_CNG)) { switch_thread_rwlock_rdlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { + ok = SWITCH_TRUE; + if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) { continue; } @@ -639,6 +643,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi switch_thread_rwlock_rdlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { + ok = SWITCH_TRUE; + if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) { continue; } @@ -688,6 +694,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi switch_thread_rwlock_rdlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { + ok = SWITCH_TRUE; + if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) { continue; } @@ -854,6 +862,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi int prune = 0; switch_thread_rwlock_rdlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { + ok = SWITCH_TRUE; + if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) { continue; } @@ -924,6 +934,8 @@ static switch_status_t perform_write(switch_core_session_t *session, switch_fram switch_thread_rwlock_rdlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { + ok = SWITCH_TRUE; + if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) { continue; } @@ -1225,6 +1237,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess switch_thread_rwlock_rdlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { switch_bool_t ok = SWITCH_TRUE; + if (!bp->ready) { continue; } From 4783af2ee2e927051dc033a5984b461cf1764400 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 30 Oct 2013 14:08:27 -0500 Subject: [PATCH 12/31] add ring_wait callstate for devstate interface --- src/include/switch_core.h | 1 + src/include/switch_types.h | 1 + src/switch_channel.c | 41 ++++++++++++++++++++++++++++---------- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index db3e67c5a8..8e41a882a6 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -109,6 +109,7 @@ typedef struct switch_device_stats_s { uint32_t early; uint32_t early_in; uint32_t early_out; + uint32_t ring_wait; } switch_device_stats_t; diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 3e2aeedfa6..e43db7be08 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1116,6 +1116,7 @@ typedef enum { CCS_EARLY, CCS_ACTIVE, CCS_HELD, + CCS_RING_WAIT, CCS_HANGUP, CCS_UNHOLD } switch_channel_callstate_t; diff --git a/src/switch_channel.c b/src/switch_channel.c index 5f53b22a7a..75a4093d14 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -240,6 +240,7 @@ static struct switch_callstate_table CALLSTATE_CHART[] = { {"EARLY", CCS_EARLY}, {"ACTIVE", CCS_ACTIVE}, {"HELD", CCS_HELD}, + {"RING_WAIT", CCS_RING_WAIT}, {"HANGUP", CCS_HANGUP}, {"UNHOLD", CCS_UNHOLD}, {NULL, 0} @@ -1747,6 +1748,10 @@ SWITCH_DECLARE(void) switch_channel_set_flag_value(switch_channel_t *channel, sw channel->flags[flag] = value; switch_mutex_unlock(channel->flag_mutex); + if (flag == CF_ORIGINATOR && switch_channel_test_flag(channel, CF_ANSWERED) && switch_channel_up_nosig(channel)) { + switch_channel_set_callstate(channel, CCS_RING_WAIT); + } + if (HELD) { switch_hold_record_t *hr; const char *brto = switch_channel_get_partner_uuid(channel); @@ -1923,6 +1928,10 @@ SWITCH_DECLARE(void) switch_channel_clear_flag(switch_channel_t *channel, switch switch_mutex_unlock(channel->profile_mutex); } + if (flag == CF_ORIGINATOR && switch_channel_test_flag(channel, CF_ANSWERED) && switch_channel_up_nosig(channel)) { + switch_channel_set_callstate(channel, CCS_ACTIVE); + } + if (flag == CF_OUTBOUND) { switch_channel_set_variable(channel, "is_outbound", NULL); } @@ -4658,6 +4667,8 @@ static void fetch_device_stats(switch_device_record_t *drec) } else { drec->stats.ringing_out++; } + } else if (np->callstate == CCS_RING_WAIT) { + drec->stats.ring_wait++; } else if (np->callstate == CCS_HANGUP) { drec->stats.hup++; if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) { @@ -4821,7 +4832,7 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_ drec->state = SDS_HANGUP; } else { if (drec->stats.active == 0) { - if ((drec->stats.ringing_out + drec->stats.early_out) > 0) { + if ((drec->stats.ringing_out + drec->stats.early_out) > 0 || drec->stats.ring_wait > 0) { drec->state = SDS_RINGING; } else { if (drec->stats.held > 0) { @@ -4849,25 +4860,32 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_ switch(drec->state) { case SDS_RINGING: - drec->ring_start = switch_micro_time_now(); - drec->ring_stop = 0; + if (!drec->ring_start) { + drec->ring_start = switch_micro_time_now(); + drec->ring_stop = 0; + } break; case SDS_ACTIVE: case SDS_ACTIVE_MULTI: - if (drec->active_start && drec->last_state != SDS_HELD) { - drec->active_stop = switch_micro_time_now(); - } else if (!drec->active_start) { + if (!drec->active_start) { drec->active_start = switch_micro_time_now(); + drec->active_stop = 0; + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_CRIT, "SET START start:%ld stop:%ld\n", drec->active_start, drec->active_stop); } break; case SDS_HELD: - drec->hold_start = switch_micro_time_now(); - drec->hold_stop = 0; - default: - if (drec->active_start && drec->last_state != SDS_HELD) { - drec->active_stop = switch_micro_time_now(); + if (!drec->hold_start) { + drec->hold_start = switch_micro_time_now(); + drec->hold_stop = 0; } break; + default: + break; + } + + if (drec->active_start && drec->state != SDS_ACTIVE && drec->state != SDS_ACTIVE_MULTI) { + drec->active_stop = switch_micro_time_now(); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_CRIT, "SET STOP start:%ld stop:%ld\n", drec->active_start, drec->active_stop); } if (drec->ring_start && !drec->ring_stop && drec->state != SDS_RINGING) { @@ -4929,6 +4947,7 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_ if (drec->state == SDS_ACTIVE || drec->state == SDS_ACTIVE_MULTI) { drec->active_start = switch_micro_time_now(); } + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_CRIT, "SET START start:%ld stop:%ld\n", drec->active_start, drec->active_stop); } if (drec->hold_stop) { From 86f2047b1d640a90b2509f2b85cab2c66ace1816 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 30 Oct 2013 17:26:06 -0500 Subject: [PATCH 13/31] remove_debug --- src/switch_channel.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/switch_channel.c b/src/switch_channel.c index 75a4093d14..9791c948a0 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -4870,7 +4870,6 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_ if (!drec->active_start) { drec->active_start = switch_micro_time_now(); drec->active_stop = 0; - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_CRIT, "SET START start:%ld stop:%ld\n", drec->active_start, drec->active_stop); } break; case SDS_HELD: @@ -4885,7 +4884,6 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_ if (drec->active_start && drec->state != SDS_ACTIVE && drec->state != SDS_ACTIVE_MULTI) { drec->active_stop = switch_micro_time_now(); - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_CRIT, "SET STOP start:%ld stop:%ld\n", drec->active_start, drec->active_stop); } if (drec->ring_start && !drec->ring_stop && drec->state != SDS_RINGING) { @@ -4947,7 +4945,6 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_ if (drec->state == SDS_ACTIVE || drec->state == SDS_ACTIVE_MULTI) { drec->active_start = switch_micro_time_now(); } - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_CRIT, "SET START start:%ld stop:%ld\n", drec->active_start, drec->active_stop); } if (drec->hold_stop) { From bd20c517d6ce3d361c42c8fd281027bd3e478072 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 30 Oct 2013 20:31:38 -0500 Subject: [PATCH 14/31] FS-5844 --resolve --- src/mod/endpoints/mod_sofia/sofia.c | 36 ++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 181da7aea7..4b80d0938a 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -6331,7 +6331,41 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, } break; case nua_callstate_ready: - if (r_sdp && (!is_dup_sdp || sofia_test_flag(tech_pvt, TFLAG_NEW_SDP)) && switch_rtp_ready(tech_pvt->rtp_session) && !sofia_test_flag(tech_pvt, TFLAG_NOSDP_REINVITE)) { + + if (switch_channel_test_flag(channel, CF_PROXY_MODE) && r_sdp) { + char ibuf[35] = "", pbuf[35] = ""; + const char *ptr; + + if ((ptr = switch_stristr("c=IN IP4", r_sdp))) { + int i = 0; + + ptr += 8; + + while(*ptr == ' ') { + ptr++; + } + while(*ptr && *ptr != ' ' && *ptr != '\r' && *ptr != '\n') { + ibuf[i++] = *ptr++; + } + + switch_channel_set_variable(channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, ibuf); + } + + if ((ptr = switch_stristr("m=audio", r_sdp))) { + int i = 0; + + ptr += 7; + + while(*ptr == ' ') { + ptr++; + } + while(*ptr && *ptr != ' ' && *ptr != '\r' && *ptr != '\n') { + pbuf[i++] = *ptr++; + } + + switch_channel_set_variable(channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, pbuf); + } + } else if (r_sdp && (!is_dup_sdp || sofia_test_flag(tech_pvt, TFLAG_NEW_SDP)) && switch_rtp_ready(tech_pvt->rtp_session) && !sofia_test_flag(tech_pvt, TFLAG_NOSDP_REINVITE)) { /* sdp changed since 18X w sdp, we're supposed to ignore it but we, of course, were pressured into supporting it */ uint8_t match = 0; From ba3a84cc6ec29e508ce8c67f4beece5988b5124c Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 31 Oct 2013 09:28:31 -0500 Subject: [PATCH 15/31] FS-5925 --resolve Conflicts: src/mod/applications/mod_conference/mod_conference.c --- src/mod/applications/mod_conference/mod_conference.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 265effdb2e..bc04e21d65 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -32,6 +32,8 @@ * David Weekly * Joao Mesquita * Raymond Chandler + * Seven Du + * Emmanuel Schmidbauer * * mod_conference.c -- Software Conference Bridge * @@ -3605,6 +3607,7 @@ static void conference_loop_output(conference_member_t *member) const char *ann = switch_channel_get_variable(channel, "conference_auto_outcall_announce"); const char *prefix = switch_channel_get_variable(channel, "conference_auto_outcall_prefix"); const char *maxwait = switch_channel_get_variable(channel, "conference_auto_outcall_maxwait"); + const char *delimiter_val = switch_channel_get_variable(channel, "conference_auto_outcall_delimiter"); int to = 60; int wait_sec = 2; int loops = 0; @@ -3631,7 +3634,12 @@ static void conference_loop_output(conference_member_t *member) int x = 0; switch_assert(cpstr); - argc = switch_separate_string(cpstr, ',', argv, (sizeof(argv) / sizeof(argv[0]))); + if (!zstr(delimiter_val) && strlen(delimiter_val) == 1) { + char delimiter = *delimiter_val; + argc = switch_separate_string(cpstr, delimiter, argv, (sizeof(argv) / sizeof(argv[0]))); + } else { + argc = switch_separate_string(cpstr, ',', argv, (sizeof(argv) / sizeof(argv[0]))); + } for (x = 0; x < argc; x++) { char *dial_str = switch_mprintf("%s%s", switch_str_nil(prefix), argv[x]); switch_assert(dial_str); From 137b45da5520427a2e0d658873365f6c0718a81c Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 31 Oct 2013 10:36:06 -0500 Subject: [PATCH 16/31] FS-5844 --- src/mod/endpoints/mod_sofia/sofia.c | 73 ++++++++++++++--------------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 4b80d0938a..ee03d68876 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -5755,9 +5755,9 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, if (r_sdp) { sdp_parser_t *parser; sdp_session_t *sdp; - + tech_pvt->remote_sdp_str = NULL; switch_channel_set_variable(channel, SWITCH_R_SDP_VARIABLE, r_sdp); - + printf("WTF %d\n---\n%s\n---\n%s", (profile->ndlb & PFLAG_NDLB_ALLOW_NONDUP_SDP), tech_pvt->remote_sdp_str, r_sdp); if (!(profile->ndlb & PFLAG_NDLB_ALLOW_NONDUP_SDP) || (!zstr(tech_pvt->remote_sdp_str) && !strcmp(tech_pvt->remote_sdp_str, r_sdp))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Duplicate SDP\n%s\n", r_sdp); is_dup_sdp = 1; @@ -5855,6 +5855,39 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, if (r_sdp) { if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { + char ibuf[35] = "", pbuf[35] = ""; + const char *ptr; + + if ((ptr = switch_stristr("c=IN IP4", r_sdp))) { + int i = 0; + + ptr += 8; + + while(*ptr == ' ') { + ptr++; + } + while(*ptr && *ptr != ' ' && *ptr != '\r' && *ptr != '\n') { + ibuf[i++] = *ptr++; + } + + switch_channel_set_variable(channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, ibuf); + } + + if ((ptr = switch_stristr("m=audio", r_sdp))) { + int i = 0; + + ptr += 7; + + while(*ptr == ' ') { + ptr++; + } + while(*ptr && *ptr != ' ' && *ptr != '\r' && *ptr != '\n') { + pbuf[i++] = *ptr++; + } + + switch_channel_set_variable(channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, pbuf); + } + if (switch_channel_test_flag(channel, CF_PROXY_MEDIA) && switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) { switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "PROXY MEDIA"); } @@ -6331,41 +6364,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, } break; case nua_callstate_ready: - - if (switch_channel_test_flag(channel, CF_PROXY_MODE) && r_sdp) { - char ibuf[35] = "", pbuf[35] = ""; - const char *ptr; - - if ((ptr = switch_stristr("c=IN IP4", r_sdp))) { - int i = 0; - - ptr += 8; - - while(*ptr == ' ') { - ptr++; - } - while(*ptr && *ptr != ' ' && *ptr != '\r' && *ptr != '\n') { - ibuf[i++] = *ptr++; - } - - switch_channel_set_variable(channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, ibuf); - } - - if ((ptr = switch_stristr("m=audio", r_sdp))) { - int i = 0; - - ptr += 7; - - while(*ptr == ' ') { - ptr++; - } - while(*ptr && *ptr != ' ' && *ptr != '\r' && *ptr != '\n') { - pbuf[i++] = *ptr++; - } - - switch_channel_set_variable(channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, pbuf); - } - } else if (r_sdp && (!is_dup_sdp || sofia_test_flag(tech_pvt, TFLAG_NEW_SDP)) && switch_rtp_ready(tech_pvt->rtp_session) && !sofia_test_flag(tech_pvt, TFLAG_NOSDP_REINVITE)) { + if (r_sdp && (!is_dup_sdp || sofia_test_flag(tech_pvt, TFLAG_NEW_SDP)) && switch_rtp_ready(tech_pvt->rtp_session) && !sofia_test_flag(tech_pvt, TFLAG_NOSDP_REINVITE)) { /* sdp changed since 18X w sdp, we're supposed to ignore it but we, of course, were pressured into supporting it */ uint8_t match = 0; From 282808c26ac11be7a3ab8c8d6ab37c4c30702c97 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 31 Oct 2013 11:21:34 -0500 Subject: [PATCH 17/31] add channel to logline --- libs/freetdm/mod_freetdm/mod_freetdm.c | 36 +++++++++++++------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 865b52363f..3ac9bd0a36 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -719,14 +719,14 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch name = switch_channel_get_name(channel); if (!tech_pvt->ftdmchan) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "no ftdmchan set in channel %s!\n", name); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "no ftdmchan set in channel %s!\n", name); return SWITCH_STATUS_FALSE; } span_id = ftdm_channel_get_span_id(tech_pvt->ftdmchan); chan_id = ftdm_channel_get_id(tech_pvt->ftdmchan); if (switch_test_flag(tech_pvt, TFLAG_DEAD)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TFLAG_DEAD is set in channel %s device %d:%d!\n", name, span_id, chan_id); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "TFLAG_DEAD is set in channel %s device %d:%d!\n", name, span_id, chan_id); return SWITCH_STATUS_FALSE; } @@ -760,7 +760,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch } if (!switch_test_flag(tech_pvt, TFLAG_IO)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TFLAG_IO is not set in channel %s device %d:%d!\n", name, span_id, chan_id); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "TFLAG_IO is not set in channel %s device %d:%d!\n", name, span_id, chan_id); goto fail; } @@ -768,7 +768,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch status = ftdm_channel_wait(tech_pvt->ftdmchan, &wflags, chunk); if (status == FTDM_FAIL) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read from channel %s device %d:%d!\n", name, span_id, chan_id); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_ERROR, "Failed to read from channel %s device %d:%d!\n", name, span_id, chan_id); goto fail; } @@ -776,7 +776,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch if (!switch_test_flag(tech_pvt, TFLAG_HOLD)) { total_to -= chunk; if (total_to <= 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Too many timeouts while waiting I/O in channel %s device %d:%d!\n", name, span_id, chan_id); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "Too many timeouts while waiting I/O in channel %s device %d:%d!\n", name, span_id, chan_id); goto fail; } } @@ -789,9 +789,9 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch len = tech_pvt->read_frame.buflen; if (ftdm_channel_read(tech_pvt->ftdmchan, tech_pvt->read_frame.data, &len) != FTDM_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to read from channel %s device %d:%d!\n", name, span_id, chan_id); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "Failed to read from channel %s device %d:%d!\n", name, span_id, chan_id); if (++tech_pvt->read_error > FTDM_MAX_READ_WRITE_ERRORS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "too many I/O read errors on channel %s device %d:%d!\n", name, span_id, chan_id); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_ERROR, "too many I/O read errors on channel %s device %d:%d!\n", name, span_id, chan_id); goto fail; } } else { @@ -812,7 +812,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch for (p = dtmf; p && *p; p++) { if (is_dtmf(*p)) { _dtmf.digit = *p; - ftdm_log(FTDM_LOG_DEBUG, "Queuing DTMF [%c] in channel %s device %d:%d\n", *p, name, span_id, chan_id); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Queuing DTMF [%c] in channel %s device %d:%d\n", *p, name, span_id, chan_id); switch_channel_queue_dtmf(channel, &_dtmf); } } @@ -821,7 +821,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch return SWITCH_STATUS_SUCCESS; fail: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "clearing IO in channel %s device %d:%d!\n", name, span_id, chan_id); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_ERROR, "clearing IO in channel %s device %d:%d!\n", name, span_id, chan_id); switch_clear_flag_locked(tech_pvt, TFLAG_IO); return SWITCH_STATUS_GENERR; } @@ -844,7 +844,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc name = switch_channel_get_name(channel); if (!tech_pvt->ftdmchan) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "no ftdmchan set in channel %s!\n", name); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "no ftdmchan set in channel %s!\n", name); return SWITCH_STATUS_FALSE; } @@ -852,7 +852,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc chan_id = ftdm_channel_get_id(tech_pvt->ftdmchan); if (switch_test_flag(tech_pvt, TFLAG_DEAD)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TFLAG_DEAD is set in channel %s device %d:%d!\n", name, span_id, chan_id); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "TFLAG_DEAD is set in channel %s device %d:%d!\n", name, span_id, chan_id); return SWITCH_STATUS_FALSE; } @@ -861,7 +861,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc } if (!switch_test_flag(tech_pvt, TFLAG_IO)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TFLAG_IO is not set in channel %s device %d:%d!\n", name, span_id, chan_id); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "TFLAG_IO is not set in channel %s device %d:%d!\n", name, span_id, chan_id); goto fail; } @@ -879,15 +879,15 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc ftdm_channel_wait(tech_pvt->ftdmchan, &wflags, ftdm_channel_get_io_interval(tech_pvt->ftdmchan) * 10); if (!(wflags & FTDM_WRITE)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Dropping frame! (write not ready) in channel %s device %d:%d!\n", name, span_id, chan_id); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Dropping frame! (write not ready) in channel %s device %d:%d!\n", name, span_id, chan_id); return SWITCH_STATUS_SUCCESS; } len = frame->datalen; if (ftdm_channel_write(tech_pvt->ftdmchan, frame->data, frame->buflen, &len) != FTDM_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Failed to write to channel %s device %d:%d!\n", name, span_id, chan_id); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Failed to write to channel %s device %d:%d!\n", name, span_id, chan_id); if (++tech_pvt->write_error > FTDM_MAX_READ_WRITE_ERRORS) { - switch_log_printf(SWITCH_CHANNEL_LOG, + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_ERROR, "Too many I/O write errors on channel %s device %d:%d!\n", name, span_id, chan_id); goto fail; } @@ -898,7 +898,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc return SWITCH_STATUS_SUCCESS; fail: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error writing to channel %s device %d:%d!\n", name, span_id, chan_id); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Error writing to channel %s device %d:%d!\n", name, span_id, chan_id); switch_clear_flag_locked(tech_pvt, TFLAG_IO); return SWITCH_STATUS_GENERR; @@ -1239,7 +1239,7 @@ static ftdm_status_t on_channel_found(ftdm_channel_t *fchan, ftdm_caller_data_t tech_init(hdata->tech_pvt, hdata->new_session, fchan, caller_data); snprintf(name, sizeof(name), "FreeTDM/%u:%u/%s", span_id, chan_id, caller_data->dnis.digits); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connect outbound channel %s\n", name); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Connect outbound channel %s\n", name); switch_channel_set_name(channel, name); switch_channel_set_variable(channel, "freetdm_span_name", ftdm_channel_get_span_name(fchan)); switch_channel_set_variable_printf(channel, "freetdm_span_number", "%d", span_id); @@ -1267,7 +1267,7 @@ static ftdm_status_t on_channel_found(ftdm_channel_t *fchan, ftdm_caller_data_t return FTDM_BREAK; } } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Attached session %s to channel %d:%d\n", sess_uuid, span_id, chan_id); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Attached session %s to channel %d:%d\n", sess_uuid, span_id, chan_id); return FTDM_SUCCESS; } From c598a740b30c47f1d6e87fb85ec696e510438e5f Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 31 Oct 2013 14:08:43 -0500 Subject: [PATCH 18/31] FS-5930 --resolve this should suppress the message --- src/mod/formats/mod_local_stream/mod_local_stream.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/mod/formats/mod_local_stream/mod_local_stream.c b/src/mod/formats/mod_local_stream/mod_local_stream.c index 6d91f9b653..bae5408014 100644 --- a/src/mod/formats/mod_local_stream/mod_local_stream.c +++ b/src/mod/formats/mod_local_stream/mod_local_stream.c @@ -311,16 +311,17 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void if (!is_open || used >= source->prebuf || (source->total && used > source->samples * 2)) { used = switch_buffer_read(audio_buffer, dist_buf, source->samples * 2); if (source->total) { - + uint32_t used = 0; switch_mutex_lock(source->mutex); for (cp = source->context_list; cp && RUNNING; cp = cp->next) { if (switch_test_flag(cp->handle, SWITCH_FILE_CALLBACK)) { continue; } switch_mutex_lock(cp->audio_mutex); - if (switch_buffer_inuse(cp->audio_buffer) > source->samples * 768) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Leaking stream handle! [%s() %s:%d]\n", cp->func, cp->file, - cp->line); + used = switch_buffer_inuse(cp->audio_buffer); + if (used > source->samples * 768) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Flushing Stream Handle Buffer [%s() %s:%d] size: %u samples: %ld\n", + cp->func, cp->file, cp->line, used, (long)source->samples); switch_buffer_zero(cp->audio_buffer); } else { switch_buffer_write(cp->audio_buffer, dist_buf, used); From 0657ce7c52c0e7aef424e9e24ff051f4b18cdf2b Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 31 Oct 2013 15:28:24 -0500 Subject: [PATCH 19/31] add channel logical direction Conflicts: src/include/switch_channel.h src/switch_channel.c --- src/include/switch_caller.h | 1 + src/include/switch_channel.h | 2 ++ src/switch_channel.c | 42 ++++++++++++++++++++++++++++++++++-- src/switch_ivr_bridge.c | 4 ++++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/include/switch_caller.h b/src/include/switch_caller.h index f0dc1c76fe..1fd5ecbd29 100644 --- a/src/include/switch_caller.h +++ b/src/include/switch_caller.h @@ -127,6 +127,7 @@ typedef struct profile_node_s { switch_memory_pool_t *pool; struct switch_caller_profile *next; switch_call_direction_t direction; + switch_call_direction_t logical_direction; profile_node_t *soft; char *uuid_str; char *clone_of; diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index 2e53ef6107..dd3870f8ae 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -633,6 +633,8 @@ SWITCH_DECLARE(int) switch_channel_test_app_flag_key(const char *app, switch_cha SWITCH_DECLARE(void) switch_channel_set_bridge_time(switch_channel_t *channel); SWITCH_DECLARE(void) switch_channel_set_hangup_time(switch_channel_t *channel); SWITCH_DECLARE(switch_call_direction_t) switch_channel_direction(switch_channel_t *channel); +SWITCH_DECLARE(switch_call_direction_t) switch_channel_logical_direction(switch_channel_t *channel); +SWITCH_DECLARE(void) switch_channel_set_direction(switch_channel_t *channel, switch_call_direction_t direction); SWITCH_DECLARE(switch_core_session_t *) switch_channel_get_session(switch_channel_t *channel); SWITCH_DECLARE(char *) switch_channel_get_flag_string(switch_channel_t *channel); SWITCH_DECLARE(char *) switch_channel_get_cap_string(switch_channel_t *channel); diff --git a/src/switch_channel.c b/src/switch_channel.c index 9791c948a0..69442f3f60 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -139,6 +139,7 @@ typedef enum { struct switch_channel { char *name; switch_call_direction_t direction; + switch_call_direction_t logical_direction; switch_queue_t *dtmf_queue; switch_queue_t *dtmf_log_queue; switch_mutex_t*dtmf_mutex; @@ -390,11 +391,23 @@ SWITCH_DECLARE(switch_channel_timetable_t *) switch_channel_get_timetable(switch return times; } +SWITCH_DECLARE(void) switch_channel_set_direction(switch_channel_t *channel, switch_call_direction_t direction) +{ + if (!switch_core_session_in_thread(channel->session)) { + channel->direction = channel->logical_direction = direction; + } +} + SWITCH_DECLARE(switch_call_direction_t) switch_channel_direction(switch_channel_t *channel) { return channel->direction; } +SWITCH_DECLARE(switch_call_direction_t) switch_channel_logical_direction(switch_channel_t *channel) +{ + return channel->logical_direction; +} + SWITCH_DECLARE(switch_status_t) switch_channel_alloc(switch_channel_t **channel, switch_call_direction_t direction, switch_memory_pool_t *pool) { switch_assert(pool != NULL); @@ -416,7 +429,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_alloc(switch_channel_t **channel, switch_mutex_init(&(*channel)->profile_mutex, SWITCH_MUTEX_NESTED, pool); (*channel)->hangup_cause = SWITCH_CAUSE_NONE; (*channel)->name = ""; - (*channel)->direction = direction; + (*channel)->direction = (*channel)->logical_direction = direction; switch_channel_set_variable(*channel, "direction", switch_channel_direction(*channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound"); return SWITCH_STATUS_SUCCESS; @@ -1752,6 +1765,20 @@ SWITCH_DECLARE(void) switch_channel_set_flag_value(switch_channel_t *channel, sw switch_channel_set_callstate(channel, CCS_RING_WAIT); } + if (flag == CF_DIALPLAN) { + if (channel->direction == SWITCH_CALL_DIRECTION_INBOUND) { + channel->logical_direction = SWITCH_CALL_DIRECTION_OUTBOUND; + if (channel->device_node) { + channel->device_node->direction = SWITCH_CALL_DIRECTION_INBOUND; + } + } else { + channel->logical_direction = SWITCH_CALL_DIRECTION_INBOUND; + if (channel->device_node) { + channel->device_node->direction = SWITCH_CALL_DIRECTION_OUTBOUND; + } + } + } + if (HELD) { switch_hold_record_t *hr; const char *brto = switch_channel_get_partner_uuid(channel); @@ -1914,6 +1941,15 @@ SWITCH_DECLARE(void) switch_channel_clear_flag(switch_channel_t *channel, switch channel->flags[flag] = 0; switch_mutex_unlock(channel->flag_mutex); + if (flag == CF_DIALPLAN) { + if (channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND) { + channel->logical_direction = SWITCH_CALL_DIRECTION_OUTBOUND; + if (channel->device_node) { + channel->device_node->direction = SWITCH_CALL_DIRECTION_INBOUND; + } + } + } + if (ACTIVE) { switch_channel_set_callstate(channel, CCS_UNHOLD); switch_mutex_lock(channel->profile_mutex); @@ -2594,6 +2630,7 @@ SWITCH_DECLARE(void) switch_channel_set_caller_profile(switch_channel_t *channel switch_assert(caller_profile != NULL); caller_profile->direction = channel->direction; + caller_profile->logical_direction = channel->logical_direction; uuid = switch_core_session_get_uuid(channel->session); if (!caller_profile->uuid || strcasecmp(caller_profile->uuid, uuid)) { @@ -2676,6 +2713,7 @@ SWITCH_DECLARE(void) switch_channel_set_hunt_caller_profile(switch_channel_t *ch channel->caller_profile->hunt_caller_profile = NULL; if (channel->caller_profile && caller_profile) { caller_profile->direction = channel->direction; + caller_profile->logical_direction = channel->logical_direction; channel->caller_profile->hunt_caller_profile = caller_profile; } switch_mutex_unlock(channel->profile_mutex); @@ -4988,7 +5026,7 @@ static void add_uuid(switch_device_record_t *drec, switch_channel_t *channel) node->uuid = switch_core_strdup(drec->pool, switch_core_session_get_uuid(channel->session)); node->parent = drec; node->callstate = channel->callstate; - node->direction = channel->direction == SWITCH_CALL_DIRECTION_INBOUND ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND; + node->direction = channel->logical_direction == SWITCH_CALL_DIRECTION_INBOUND ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND; channel->device_node = node; diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index ef7067cec7..958b16fd67 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -1681,6 +1681,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_uuid_bridge(const char *originator_uu } } + if (switch_channel_direction(originatee_channel) == SWITCH_CALL_DIRECTION_OUTBOUND && switch_channel_test_flag(originatee_channel, CF_DIALPLAN)) { + switch_channel_clear_flag(originatee_channel, CF_DIALPLAN); + } + cleanup_proxy_mode_a(originator_session); cleanup_proxy_mode_a(originatee_session); From 456f69a62b2fa4df7ac8438b30ba68e74c2a04fc Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 1 Nov 2013 16:33:41 -0500 Subject: [PATCH 20/31] FS-5935 --resolve this was broken from the initial check in FS-5524 --- src/mod/languages/mod_lua/mod_lua.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/mod/languages/mod_lua/mod_lua.cpp b/src/mod/languages/mod_lua/mod_lua.cpp index a21643bc97..9715f0dc74 100644 --- a/src/mod/languages/mod_lua/mod_lua.cpp +++ b/src/mod/languages/mod_lua/mod_lua.cpp @@ -45,7 +45,6 @@ SWITCH_MODULE_DEFINITION_EX(mod_lua, mod_lua_load, mod_lua_shutdown, NULL, SMODF static struct { switch_memory_pool_t *pool; char *xml_handler; - switch_event_node_t *node; } globals; int luaopen_freeswitch(lua_State * L); @@ -339,12 +338,16 @@ static switch_status_t do_config(void) char *script = (char *) switch_xml_attr_soft(hook, "script"); switch_event_types_t evtype; + if (!zstr(script)) { + script = switch_core_strdup(globals.pool, script); + } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "hook params: '%s' | '%s' | '%s'\n", event, subclass, script); if (switch_name_event(event,&evtype) == SWITCH_STATUS_SUCCESS) { if (!zstr(script)) { - if (switch_event_bind_removable(modname, evtype, !zstr(subclass) ? subclass : SWITCH_EVENT_SUBCLASS_ANY, - lua_event_handler, script, &globals.node) == SWITCH_STATUS_SUCCESS) { + if (switch_event_bind(modname, evtype, !zstr(subclass) ? subclass : SWITCH_EVENT_SUBCLASS_ANY, + lua_event_handler, script) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "event handler for '%s' set to '%s'\n", switch_event_name(evtype), script); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set event handler: unsuccessful bind\n"); @@ -691,7 +694,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_lua_load) SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_lua_shutdown) { - switch_event_unbind(&globals.node); + switch_event_unbind_callback(lua_event_handler); return SWITCH_STATUS_SUCCESS; } From b5ac4fdb88e115a03b8bf9e7cdf6832f730f9437 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Sat, 2 Nov 2013 10:31:23 -0500 Subject: [PATCH 21/31] FS-5930 --resolve --- src/mod/formats/mod_local_stream/mod_local_stream.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/mod/formats/mod_local_stream/mod_local_stream.c b/src/mod/formats/mod_local_stream/mod_local_stream.c index bae5408014..a96d01c4c3 100644 --- a/src/mod/formats/mod_local_stream/mod_local_stream.c +++ b/src/mod/formats/mod_local_stream/mod_local_stream.c @@ -311,20 +311,20 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void if (!is_open || used >= source->prebuf || (source->total && used > source->samples * 2)) { used = switch_buffer_read(audio_buffer, dist_buf, source->samples * 2); if (source->total) { - uint32_t used = 0; + uint32_t bused = 0; switch_mutex_lock(source->mutex); for (cp = source->context_list; cp && RUNNING; cp = cp->next) { if (switch_test_flag(cp->handle, SWITCH_FILE_CALLBACK)) { continue; } switch_mutex_lock(cp->audio_mutex); - used = switch_buffer_inuse(cp->audio_buffer); - if (used > source->samples * 768) { + bused = switch_buffer_inuse(cp->audio_buffer); + if (bused > source->samples * 768) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Flushing Stream Handle Buffer [%s() %s:%d] size: %u samples: %ld\n", - cp->func, cp->file, cp->line, used, (long)source->samples); + cp->func, cp->file, cp->line, bused, (long)source->samples); switch_buffer_zero(cp->audio_buffer); } else { - switch_buffer_write(cp->audio_buffer, dist_buf, used); + switch_buffer_write(cp->audio_buffer, dist_buf, bused); } switch_mutex_unlock(cp->audio_mutex); } From 8610c831a1cb59e4a2e673f171ad2971097b2eee Mon Sep 17 00:00:00 2001 From: Ken Rice Date: Sat, 2 Nov 2013 17:34:16 -0500 Subject: [PATCH 22/31] FS-5930 --resolve --- src/mod/formats/mod_local_stream/mod_local_stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/formats/mod_local_stream/mod_local_stream.c b/src/mod/formats/mod_local_stream/mod_local_stream.c index a96d01c4c3..c94958ea87 100644 --- a/src/mod/formats/mod_local_stream/mod_local_stream.c +++ b/src/mod/formats/mod_local_stream/mod_local_stream.c @@ -324,7 +324,7 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void cp->func, cp->file, cp->line, bused, (long)source->samples); switch_buffer_zero(cp->audio_buffer); } else { - switch_buffer_write(cp->audio_buffer, dist_buf, bused); + switch_buffer_write(cp->audio_buffer, dist_buf, used); } switch_mutex_unlock(cp->audio_mutex); } From 7540023b9218c6d3dbf10dbabbdda3d64a1dd0f7 Mon Sep 17 00:00:00 2001 From: Chris Rienzo Date: Mon, 4 Nov 2013 14:28:07 -0500 Subject: [PATCH 23/31] FS-5921 --resolve mod_mongo: use jsonString() instead of toString(), tabs instead of spaces --- src/mod/applications/mod_mongo/mod_mongo.cpp | 100 ++++----- src/mod/applications/mod_mongo/mod_mongo.h | 20 +- src/mod/applications/mod_mongo/mongo_conn.cpp | 195 +++++++++--------- 3 files changed, 157 insertions(+), 158 deletions(-) diff --git a/src/mod/applications/mod_mongo/mod_mongo.cpp b/src/mod/applications/mod_mongo/mod_mongo.cpp index 83b31c7546..811361be21 100644 --- a/src/mod/applications/mod_mongo/mod_mongo.cpp +++ b/src/mod/applications/mod_mongo/mod_mongo.cpp @@ -1,6 +1,6 @@ -/* +/* * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005-2012, Anthony Minessale II + * Copyright (C) 2005-2013, Anthony Minessale II * * Version: MPL 1.1 * @@ -22,7 +22,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): - * + * * Tamas Cseke * * mod_mongo.cpp -- API for MongoDB @@ -53,7 +53,7 @@ SWITCH_STANDARD_API(mongo_mapreduce_function) switch_assert(ns != NULL); if ((json_query = strchr(ns, DELIMITER))) { - *json_query++ = '\0'; + *json_query++ = '\0'; } if (!zstr(ns) && !zstr(json_query)) { @@ -82,7 +82,7 @@ SWITCH_STANDARD_API(mongo_mapreduce_function) conn->runCommand(conn->nsGetDB(ns), cmd.done(), out); mongo_connection_pool_put(globals.conn_pool, conn, SWITCH_FALSE); - stream->write_function(stream, "-OK\n%s\n", out.toString().c_str()); + stream->write_function(stream, "-OK\n%s\n", out.jsonString().c_str()); } else { stream->write_function(stream, "-ERR\nNo connection\n"); } @@ -93,7 +93,7 @@ SWITCH_STANDARD_API(mongo_mapreduce_function) stream->write_function(stream, "-ERR\n%s\n", e.toString().c_str()); } } else { - stream->write_function(stream, "-ERR\n%s\n", MAPREDUCE_SYNTAX); + stream->write_function(stream, "-ERR\n%s\n", MAPREDUCE_SYNTAX); } switch_safe_free(ns); @@ -104,50 +104,50 @@ SWITCH_STANDARD_API(mongo_mapreduce_function) SWITCH_STANDARD_API(mongo_find_one_function) { - switch_status_t status = SWITCH_STATUS_SUCCESS; - char *ns = NULL, *json_query = NULL, *json_fields = NULL; + switch_status_t status = SWITCH_STATUS_SUCCESS; + char *ns = NULL, *json_query = NULL, *json_fields = NULL; - ns = strdup(cmd); - switch_assert(ns != NULL); + ns = strdup(cmd); + switch_assert(ns != NULL); - if ((json_query = strchr(ns, DELIMITER))) { - *json_query++ = '\0'; - if ((json_fields = strchr(json_query, DELIMITER))) { - *json_fields++ = '\0'; - } - } + if ((json_query = strchr(ns, DELIMITER))) { + *json_query++ = '\0'; + if ((json_fields = strchr(json_query, DELIMITER))) { + *json_fields++ = '\0'; + } + } - if (!zstr(ns) && !zstr(json_query) && !zstr(json_fields)) { + if (!zstr(ns) && !zstr(json_query) && !zstr(json_fields)) { - DBClientBase *conn = NULL; + DBClientBase *conn = NULL; - try { - BSONObj query = fromjson(json_query); - BSONObj fields = fromjson(json_fields); + try { + BSONObj query = fromjson(json_query); + BSONObj fields = fromjson(json_fields); - conn = mongo_connection_pool_get(globals.conn_pool); - if (conn) { - BSONObj res = conn->findOne(ns, Query(query), &fields); - mongo_connection_pool_put(globals.conn_pool, conn, SWITCH_FALSE); + conn = mongo_connection_pool_get(globals.conn_pool); + if (conn) { + BSONObj res = conn->findOne(ns, Query(query), &fields); + mongo_connection_pool_put(globals.conn_pool, conn, SWITCH_FALSE); - stream->write_function(stream, "-OK\n%s\n", res.toString().c_str()); - } else { - stream->write_function(stream, "-ERR\nNo connection\n"); - } - } catch (DBException &e) { - if (conn) { - mongo_connection_pool_put(globals.conn_pool, conn, SWITCH_TRUE); - } - stream->write_function(stream, "-ERR\n%s\n", e.toString().c_str()); - } + stream->write_function(stream, "-OK\n%s\n", res.jsonString().c_str()); + } else { + stream->write_function(stream, "-ERR\nNo connection\n"); + } + } catch (DBException &e) { + if (conn) { + mongo_connection_pool_put(globals.conn_pool, conn, SWITCH_TRUE); + } + stream->write_function(stream, "-ERR\n%s\n", e.toString().c_str()); + } - } else { + } else { stream->write_function(stream, "-ERR\n%s\n", FIND_ONE_SYNTAX); - } + } - switch_safe_free(ns); + switch_safe_free(ns); - return status; + return status; } static switch_status_t config(void) @@ -214,21 +214,21 @@ SWITCH_MODULE_DEFINITION(mod_mongo, mod_mongo_load, mod_mongo_shutdown, NULL); SWITCH_MODULE_LOAD_FUNCTION(mod_mongo_load) { - switch_api_interface_t *api_interface; - switch_application_interface_t *app_interface; + switch_api_interface_t *api_interface; + switch_application_interface_t *app_interface; - *module_interface = switch_loadable_module_create_module_interface(pool, modname); + *module_interface = switch_loadable_module_create_module_interface(pool, modname); - memset(&globals, 0, sizeof(globals)); + memset(&globals, 0, sizeof(globals)); - if (config() != SWITCH_STATUS_SUCCESS) { - return SWITCH_STATUS_TERM; - } - - SWITCH_ADD_API(api_interface, "mongo_find_one", "findOne", mongo_find_one_function, FIND_ONE_SYNTAX); - SWITCH_ADD_API(api_interface, "mongo_mapreduce", "Map/Reduce", mongo_mapreduce_function, MAPREDUCE_SYNTAX); + if (config() != SWITCH_STATUS_SUCCESS) { + return SWITCH_STATUS_TERM; + } - return SWITCH_STATUS_SUCCESS; + SWITCH_ADD_API(api_interface, "mongo_find_one", "findOne", mongo_find_one_function, FIND_ONE_SYNTAX); + SWITCH_ADD_API(api_interface, "mongo_mapreduce", "Map/Reduce", mongo_mapreduce_function, MAPREDUCE_SYNTAX); + + return SWITCH_STATUS_SUCCESS; } SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_mongo_shutdown) diff --git a/src/mod/applications/mod_mongo/mod_mongo.h b/src/mod/applications/mod_mongo/mod_mongo.h index 00e927f3a1..df09434352 100644 --- a/src/mod/applications/mod_mongo/mod_mongo.h +++ b/src/mod/applications/mod_mongo/mod_mongo.h @@ -1,6 +1,6 @@ -/* +/* * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005-2012, Anthony Minessale II + * Copyright (C) 2005-2013, Anthony Minessale II * * Version: MPL 1.1 * @@ -40,14 +40,14 @@ using namespace mongo; typedef struct { - char *conn_str; + char *conn_str; - switch_size_t min_connections; - switch_size_t max_connections; - switch_size_t size; - switch_queue_t *connections; - switch_mutex_t *mutex; - switch_memory_pool_t *pool; + switch_size_t min_connections; + switch_size_t max_connections; + switch_size_t size; + switch_queue_t *connections; + switch_mutex_t *mutex; + switch_memory_pool_t *pool; } mongo_connection_pool_t; @@ -56,7 +56,7 @@ switch_status_t mongo_connection_create(DBClientBase **connection, const char *c void mongo_connection_destroy(DBClientBase **conn); switch_status_t mongo_connection_pool_create(mongo_connection_pool_t **conn_pool, switch_size_t min_connections, switch_size_t max_connections, - const char *conn_str); + const char *conn_str); void mongo_connection_pool_destroy(mongo_connection_pool_t **conn_pool); diff --git a/src/mod/applications/mod_mongo/mongo_conn.cpp b/src/mod/applications/mod_mongo/mongo_conn.cpp index 8c7687b860..fd095fe54a 100644 --- a/src/mod/applications/mod_mongo/mongo_conn.cpp +++ b/src/mod/applications/mod_mongo/mongo_conn.cpp @@ -1,6 +1,6 @@ /* * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005-2012, Anthony Minessale II + * Copyright (C) 2005-2013, Anthony Minessale II * * Version: MPL 1.1 * @@ -42,162 +42,161 @@ switch_status_t mongo_connection_create(DBClientBase **connection, const char *conn_str) { - DBClientBase *conn = NULL; - string conn_string(conn_str), err_msg; - ConnectionString cs = ConnectionString::parse(conn_string, err_msg); - switch_status_t status = SWITCH_STATUS_FALSE; - - if (!cs.isValid()) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't parse url: %s\n", err_msg.c_str()); - return status; - } + DBClientBase *conn = NULL; + string conn_string(conn_str), err_msg; + ConnectionString cs = ConnectionString::parse(conn_string, err_msg); + switch_status_t status = SWITCH_STATUS_FALSE; - try { - conn = cs.connect(err_msg); - } catch (DBException &e) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't connect to mongo [%s]: %s\n", conn_str, err_msg.c_str()); - return status; - } + if (!cs.isValid()) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't parse url: %s\n", err_msg.c_str()); + return status; + } - if (conn) { - *connection = conn; - status = SWITCH_STATUS_SUCCESS; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected to mongo [%s]\n", conn_str); - } + try { + conn = cs.connect(err_msg); + } catch (DBException &e) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't connect to mongo [%s]: %s\n", conn_str, err_msg.c_str()); + return status; + } - return status; + if (conn) { + *connection = conn; + status = SWITCH_STATUS_SUCCESS; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected to mongo [%s]\n", conn_str); + } + + return status; } void mongo_connection_destroy(DBClientBase **conn) { - switch_assert(*conn != NULL); - delete *conn; + switch_assert(*conn != NULL); + delete *conn; - *conn = NULL; + *conn = NULL; } switch_status_t mongo_connection_pool_create(mongo_connection_pool_t **conn_pool, switch_size_t min_connections, switch_size_t max_connections, - const char *conn_str) + const char *conn_str) { - switch_memory_pool_t *pool = NULL; - switch_status_t status = SWITCH_STATUS_SUCCESS; - mongo_connection_pool_t *cpool = NULL; - DBClientBase *conn = NULL; + switch_memory_pool_t *pool = NULL; + switch_status_t status = SWITCH_STATUS_SUCCESS; + mongo_connection_pool_t *cpool = NULL; + DBClientBase *conn = NULL; - if ((status = switch_core_new_memory_pool(&pool)) != SWITCH_STATUS_SUCCESS) { - return status; - } + if ((status = switch_core_new_memory_pool(&pool)) != SWITCH_STATUS_SUCCESS) { + return status; + } - if (!(cpool = (mongo_connection_pool_t *)switch_core_alloc(pool, sizeof(mongo_connection_pool_t)))) { - switch_goto_status(SWITCH_STATUS_MEMERR, done); - } + if (!(cpool = (mongo_connection_pool_t *)switch_core_alloc(pool, sizeof(mongo_connection_pool_t)))) { + switch_goto_status(SWITCH_STATUS_MEMERR, done); + } - if ((status = switch_mutex_init(&cpool->mutex, SWITCH_MUTEX_NESTED, pool)) != SWITCH_STATUS_SUCCESS) { - goto done; - } + if ((status = switch_mutex_init(&cpool->mutex, SWITCH_MUTEX_NESTED, pool)) != SWITCH_STATUS_SUCCESS) { + goto done; + } - if ((status = switch_queue_create(&cpool->connections, max_connections, pool)) != SWITCH_STATUS_SUCCESS) { - goto done; - } + if ((status = switch_queue_create(&cpool->connections, max_connections, pool)) != SWITCH_STATUS_SUCCESS) { + goto done; + } - cpool->min_connections = min_connections; - cpool->max_connections = max_connections; - cpool->conn_str = switch_core_strdup(pool, conn_str); - - cpool->pool = pool; + cpool->min_connections = min_connections; + cpool->max_connections = max_connections; + cpool->conn_str = switch_core_strdup(pool, conn_str); + cpool->pool = pool; - for (cpool->size = 0; cpool->size < min_connections; cpool->size++) { + for (cpool->size = 0; cpool->size < min_connections; cpool->size++) { - if (mongo_connection_create(&conn, conn_str) == SWITCH_STATUS_SUCCESS) { - mongo_connection_pool_put(cpool, conn, SWITCH_FALSE); - } else { - break; - } - } + if (mongo_connection_create(&conn, conn_str) == SWITCH_STATUS_SUCCESS) { + mongo_connection_pool_put(cpool, conn, SWITCH_FALSE); + } else { + break; + } + } done: - if (status == SWITCH_STATUS_SUCCESS) { - *conn_pool = cpool; - } else { - switch_core_destroy_memory_pool(&pool); - } + if (status == SWITCH_STATUS_SUCCESS) { + *conn_pool = cpool; + } else { + switch_core_destroy_memory_pool(&pool); + } - return status; + return status; } void mongo_connection_pool_destroy(mongo_connection_pool_t **conn_pool) { - mongo_connection_pool_t *cpool = *conn_pool; - void *data = NULL; + mongo_connection_pool_t *cpool = *conn_pool; + void *data = NULL; - switch_assert(cpool != NULL); + switch_assert(cpool != NULL); - while (switch_queue_trypop(cpool->connections, &data) == SWITCH_STATUS_SUCCESS) { - mongo_connection_destroy((DBClientBase **)&data); - } + while (switch_queue_trypop(cpool->connections, &data) == SWITCH_STATUS_SUCCESS) { + mongo_connection_destroy((DBClientBase **)&data); + } - switch_mutex_destroy(cpool->mutex); - switch_core_destroy_memory_pool(&cpool->pool); + switch_mutex_destroy(cpool->mutex); + switch_core_destroy_memory_pool(&cpool->pool); - *conn_pool = NULL; + *conn_pool = NULL; } DBClientBase *mongo_connection_pool_get(mongo_connection_pool_t *conn_pool) { - DBClientBase *conn = NULL; - void *data = NULL; + DBClientBase *conn = NULL; + void *data = NULL; - switch_assert(conn_pool != NULL); + switch_assert(conn_pool != NULL); - switch_mutex_lock(conn_pool->mutex); + switch_mutex_lock(conn_pool->mutex); - if (switch_queue_trypop(conn_pool->connections, &data) == SWITCH_STATUS_SUCCESS) { - conn = (DBClientBase *) data; - } else if (mongo_connection_create(&conn, conn_pool->conn_str) == SWITCH_STATUS_SUCCESS) { - if (++conn_pool->size > conn_pool->max_connections) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Connection pool is empty. You may want to increase 'max-connections'\n"); - } - } + if (switch_queue_trypop(conn_pool->connections, &data) == SWITCH_STATUS_SUCCESS) { + conn = (DBClientBase *) data; + } else if (mongo_connection_create(&conn, conn_pool->conn_str) == SWITCH_STATUS_SUCCESS) { + if (++conn_pool->size > conn_pool->max_connections) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Connection pool is empty. You may want to increase 'max-connections'\n"); + } + } - switch_mutex_unlock(conn_pool->mutex); + switch_mutex_unlock(conn_pool->mutex); #ifdef MONGO_POOL_DEBUG - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL get: size %d conn: %p\n", (int) switch_queue_size(conn_pool->connections), conn); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL get: size %d conn: %p\n", (int) switch_queue_size(conn_pool->connections), conn); #endif - return conn; + return conn; } switch_status_t mongo_connection_pool_put(mongo_connection_pool_t *conn_pool, DBClientBase *conn, switch_bool_t destroy) { - switch_status_t status = SWITCH_STATUS_SUCCESS; + switch_status_t status = SWITCH_STATUS_SUCCESS; - switch_assert(conn_pool != NULL); - switch_assert(conn != NULL); + switch_assert(conn_pool != NULL); + switch_assert(conn != NULL); - switch_mutex_lock(conn_pool->mutex); - if (destroy || conn_pool->size > conn_pool->max_connections) { + switch_mutex_lock(conn_pool->mutex); + if (destroy || conn_pool->size > conn_pool->max_connections) { #ifdef MONGO_POOL_DEBUG - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: Destroy connection %p\n", conn); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: Destroy connection %p\n", conn); #endif - mongo_connection_destroy(&conn); - conn_pool->size--; - } else { + mongo_connection_destroy(&conn); + conn_pool->size--; + } else { #ifdef MONGO_POOL_DEBUG - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: push connection %p\n", conn); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: push connection %p\n", conn); #endif - status = switch_queue_push(conn_pool->connections, conn); - } + status = switch_queue_push(conn_pool->connections, conn); + } - switch_mutex_unlock(conn_pool->mutex); + switch_mutex_unlock(conn_pool->mutex); #ifdef MONGO_POOL_DEBUG - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: put size %d conn: %p\n", (int) switch_queue_size(conn_pool->connections), conn); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: put size %d conn: %p\n", (int) switch_queue_size(conn_pool->connections), conn); #endif - return status; + return status; } /* For Emacs: From d4916c3965a013df671c3facc96f5844a7869840 Mon Sep 17 00:00:00 2001 From: Chris Rienzo Date: Mon, 4 Nov 2013 14:29:48 -0500 Subject: [PATCH 24/31] FS-5931 --resolve mod_mongo: update driver to v2.4 --- src/mod/applications/mod_mongo/Makefile | 4 ++-- src/mod/applications/mod_mongo/fpic_hack.diff | 16 ++++++++-------- src/mod/applications/mod_mongo/mod_mongo.cpp | 4 ++-- src/mod/applications/mod_mongo/mod_mongo.h | 5 +---- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/mod/applications/mod_mongo/Makefile b/src/mod/applications/mod_mongo/Makefile index 9ce16b1171..7a6e1058ab 100644 --- a/src/mod/applications/mod_mongo/Makefile +++ b/src/mod/applications/mod_mongo/Makefile @@ -1,6 +1,6 @@ BASE=../../../.. -MONGO_CXX_DRIVER_VERSION=v1.8 +MONGO_CXX_DRIVER_VERSION=v2.4 MONGO_CXX_DRIVER_URL=http://downloads.mongodb.org/cxx-driver MONGO_CXX_DRIVER_TARBALL=mongodb-linux-x86_64-$(MONGO_CXX_DRIVER_VERSION)-latest.tgz MONGO_CXX_DRIVER_SRC=$(BASE)/libs/mongo-cxx-driver-$(MONGO_CXX_DRIVER_VERSION) @@ -9,7 +9,7 @@ LIBMONGOCLIENT_A =$(MONGO_CXX_DRIVER_SRC)/libmongoclient.a LOCAL_SOURCES=mongo_conn.cpp LOCAL_OBJS=mongo_conn.o -LOCAL_CFLAGS=-I$(MONGO_CXX_DRIVER_SRC)/mongo +LOCAL_CFLAGS=-I$(MONGO_CXX_DRIVER_SRC)/src LOCAL_LIBADD=$(LIBMONGOCLIENT_A) LOCAL_LDFLAGS=-lboost_thread -lboost_filesystem-mt -lboost_system-mt MODDIR=$(shell pwd) diff --git a/src/mod/applications/mod_mongo/fpic_hack.diff b/src/mod/applications/mod_mongo/fpic_hack.diff index 882f3c899a..1f85f85c97 100644 --- a/src/mod/applications/mod_mongo/fpic_hack.diff +++ b/src/mod/applications/mod_mongo/fpic_hack.diff @@ -1,11 +1,11 @@ ---- SConstruct.orig 2011-04-28 19:00:36.000000000 +0200 -+++ SConstruct 2011-04-28 19:01:19.000000000 +0200 -@@ -45,7 +45,7 @@ - linux = True +--- SConstruct 2013-10-30 17:18:51.160645496 -0400 ++++ new 2013-10-30 17:22:18.790072856 -0400 +@@ -78,7 +78,7 @@ + env['DIST_ARCHIVE_SUFFIX'] = '.tgz' if nix: -- env.Append( CPPFLAGS=" -O3" ) -+ env.Append( CPPFLAGS=" -I../pcre -fPIC -O3" ) - env.Append( LIBS=["pthread"] ) +- env.Append(CCFLAGS=["-O3", "-pthread"]) ++ env.Append(CCFLAGS=["-I../pcre", "-fPIC", "-O3", "-pthread"]) if linux: - env.Append( LINKFLAGS=" -Wl,--as-needed -Wl,-zdefs " ) + env.Append(LINKFLAGS=["-pthread"]) + diff --git a/src/mod/applications/mod_mongo/mod_mongo.cpp b/src/mod/applications/mod_mongo/mod_mongo.cpp index 811361be21..8c3536def2 100644 --- a/src/mod/applications/mod_mongo/mod_mongo.cpp +++ b/src/mod/applications/mod_mongo/mod_mongo.cpp @@ -62,7 +62,7 @@ SWITCH_STANDARD_API(mongo_mapreduce_function) BSONObj out; BSONObjBuilder cmd; - cmd.append("mapreduce", conn->nsGetCollection(ns)); + cmd.append("mapreduce", nsGetCollection(ns)); if (!zstr(globals.map)) { cmd.appendCode("map", globals.map); } @@ -79,7 +79,7 @@ SWITCH_STANDARD_API(mongo_mapreduce_function) conn = mongo_connection_pool_get(globals.conn_pool); if (conn) { - conn->runCommand(conn->nsGetDB(ns), cmd.done(), out); + conn->runCommand(nsGetDB(ns), cmd.done(), out); mongo_connection_pool_put(globals.conn_pool, conn, SWITCH_FALSE); stream->write_function(stream, "-OK\n%s\n", out.jsonString().c_str()); diff --git a/src/mod/applications/mod_mongo/mod_mongo.h b/src/mod/applications/mod_mongo/mod_mongo.h index df09434352..822dacaf63 100644 --- a/src/mod/applications/mod_mongo/mod_mongo.h +++ b/src/mod/applications/mod_mongo/mod_mongo.h @@ -32,10 +32,7 @@ #ifndef MOD_MONGO_H #define MOD_MONGO_H -#include -#include -#include -#include +#include using namespace mongo; From eab941d2270fd288a75be70fea861d777b928c7b Mon Sep 17 00:00:00 2001 From: Chris Rienzo Date: Tue, 5 Nov 2013 15:15:49 -0500 Subject: [PATCH 25/31] mod_rayo: default record format is now wav --- src/mod/event_handlers/mod_rayo/rayo_elements.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/event_handlers/mod_rayo/rayo_elements.c b/src/mod/event_handlers/mod_rayo/rayo_elements.c index 34577a9492..2bbf701794 100644 --- a/src/mod/event_handlers/mod_rayo/rayo_elements.c +++ b/src/mod/event_handlers/mod_rayo/rayo_elements.c @@ -80,7 +80,7 @@ ELEMENT_END * component validation */ ELEMENT(RAYO_RECORD) - ATTRIB(format, mp3, any) + ATTRIB(format, wav, any) ATTRIB(start-beep, false, bool) ATTRIB(stop-beep, false, bool) ATTRIB(start-paused, false, bool) From 93fa6f17b447d1591afd4a198322bb40f3f3ae2e Mon Sep 17 00:00:00 2001 From: Chris Rienzo Date: Wed, 6 Nov 2013 17:00:13 -0500 Subject: [PATCH 26/31] mod_rayo: component added. No support for HTTP(S) yet. --- conf/rayo/autoload_configs/rayo.conf.xml | 7 + src/mod/event_handlers/mod_rayo/Makefile | 2 + .../conf/autoload_configs/rayo.conf.xml | 7 + src/mod/event_handlers/mod_rayo/mod_rayo.c | 50 ++- src/mod/event_handlers/mod_rayo/mod_rayo.h | 3 + .../event_handlers/mod_rayo/rayo_components.c | 4 +- .../event_handlers/mod_rayo/rayo_components.h | 5 + .../event_handlers/mod_rayo/rayo_elements.c | 12 + .../event_handlers/mod_rayo/rayo_elements.h | 1 + .../mod_rayo/rayo_receivefax_component.c | 378 ++++++++++++++++++ 10 files changed, 464 insertions(+), 5 deletions(-) create mode 100644 src/mod/event_handlers/mod_rayo/rayo_receivefax_component.c diff --git a/conf/rayo/autoload_configs/rayo.conf.xml b/conf/rayo/autoload_configs/rayo.conf.xml index 35419319bc..c8171569af 100644 --- a/conf/rayo/autoload_configs/rayo.conf.xml +++ b/conf/rayo/autoload_configs/rayo.conf.xml @@ -16,6 +16,12 @@ + + + + + + @@ -65,6 +71,7 @@ ]]> ]]> ]]> + ]]> ]]> ]]> ]]> diff --git a/src/mod/event_handlers/mod_rayo/Makefile b/src/mod/event_handlers/mod_rayo/Makefile index 6fccfdf318..bfb38dbd6c 100644 --- a/src/mod/event_handlers/mod_rayo/Makefile +++ b/src/mod/event_handlers/mod_rayo/Makefile @@ -14,6 +14,7 @@ LOCAL_OBJS= $(IKS_LA) \ rayo_input_component.o \ rayo_output_component.o \ rayo_prompt_component.o \ + rayo_receivefax_component.o \ rayo_record_component.o \ sasl.o \ srgs.o \ @@ -27,6 +28,7 @@ LOCAL_SOURCES= \ rayo_output_component.c \ rayo_prompt_component.c \ rayo_record_component.c \ + rayo_receivefax_component.c \ sasl.c \ srgs.c \ xmpp_streams.c diff --git a/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml b/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml index 35419319bc..c8171569af 100644 --- a/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml +++ b/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml @@ -16,6 +16,12 @@ + + + + + + @@ -65,6 +71,7 @@ ]]> ]]> ]]> + ]]> ]]> ]]> ]]> diff --git a/src/mod/event_handlers/mod_rayo/mod_rayo.c b/src/mod/event_handlers/mod_rayo/mod_rayo.c index 6dd58d29c6..c5a57eeda5 100644 --- a/src/mod/event_handlers/mod_rayo/mod_rayo.c +++ b/src/mod/event_handlers/mod_rayo/mod_rayo.c @@ -126,6 +126,8 @@ struct rayo_call { switch_hash_t *pcps; /** current idle start time */ switch_time_t idle_start_time; + /** true if fax is in progress */ + int faxing; /** 1 if joined to call, 2 if joined to mixer */ int joined; /** pending join */ @@ -963,11 +965,35 @@ const char *rayo_call_get_dcp_jid(struct rayo_call *call) /** * @param call the Rayo call - * @return true if joined + * @return true if joined (or a join is in progress) */ -static int rayo_call_is_joined(struct rayo_call *call) +int rayo_call_is_joined(struct rayo_call *call) { - return call->joined; + return call->joined || call->pending_join_request; +} + +/** + * @param call to check if faxing + * @return true if faxing is in progress + */ +int rayo_call_is_faxing(struct rayo_call *call) +{ + return call->faxing; +} + +/** + * Set faxing flag if faxing is not in progress + * @param call the call to flag + * @param faxing true if faxing is in progress + * @return true if set, false if can't set because faxing is already in progress. Reset always succeeds. + */ +int rayo_call_set_faxing(struct rayo_call *call, int faxing) +{ + if (!faxing || (faxing && !call->faxing)) { + call->faxing = faxing; + return 1; + } + return 0; } #define RAYO_MIXER_LOCATE(mixer_name) rayo_mixer_locate(mixer_name, __FILE__, __LINE__) @@ -1942,6 +1968,12 @@ static iks *on_rayo_join(struct rayo_actor *call, struct rayo_message *msg, void goto done; } + if (rayo_call_is_faxing(RAYO_CALL(call))) { + /* can't join a call while it's faxing */ + response = iks_new_error_detailed(msg->payload, STANZA_ERROR_UNEXPECTED_REQUEST, "fax is in progress"); + goto done; + } + if (RAYO_CALL(call)->pending_join_request) { /* don't allow concurrent join requests */ response = iks_new_error_detailed(msg->payload, STANZA_ERROR_UNEXPECTED_REQUEST, "(un)join request is pending"); @@ -3074,12 +3106,22 @@ static switch_status_t rayo_call_on_read_frame(switch_core_session_t *session, s switch_time_t idle_start = call->idle_start_time; int idle_duration_ms = (now - idle_start) / 1000; /* detect idle session (rayo-client has stopped controlling call) and terminate call */ - if (rayo_call_is_joined(call)) { + if (rayo_call_is_joined(call) || rayo_call_is_faxing(call)) { call->idle_start_time = now; } else if (idle_duration_ms > globals.max_idle_ms) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Ending abandoned call. idle_duration_ms = %i ms\n", idle_duration_ms); switch_channel_hangup(channel, RAYO_CAUSE_HANGUP); } + + /* check for break request */ + { + const char *break_jid = switch_channel_get_variable(channel, "rayo_read_frame_interrupt"); + struct rayo_actor *actor; + if (break_jid && (actor = RAYO_LOCATE(break_jid))) { + RAYO_UNLOCK(actor); + return SWITCH_STATUS_FALSE; + } + } } return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/event_handlers/mod_rayo/mod_rayo.h b/src/mod/event_handlers/mod_rayo/mod_rayo.h index dd0adb3192..c65236b64a 100644 --- a/src/mod/event_handlers/mod_rayo/mod_rayo.h +++ b/src/mod/event_handlers/mod_rayo/mod_rayo.h @@ -153,6 +153,9 @@ extern void rayo_actor_destroy(struct rayo_actor *actor, const char *file, int l #define RAYO_DESTROY(x) rayo_actor_destroy(RAYO_ACTOR(x), __FILE__, __LINE__) #define RAYO_SEQ_NEXT(x) rayo_actor_seq_next(RAYO_ACTOR(x)) +extern int rayo_call_is_joined(struct rayo_call *call); +extern int rayo_call_is_faxing(struct rayo_call *call); +extern int rayo_call_set_faxing(struct rayo_call *call, int faxing); extern const char *rayo_call_get_dcp_jid(struct rayo_call *call); #define rayo_mixer_get_name(mixer) RAYO_ID(mixer) diff --git a/src/mod/event_handlers/mod_rayo/rayo_components.c b/src/mod/event_handlers/mod_rayo/rayo_components.c index b5137d9459..2448e166a8 100644 --- a/src/mod/event_handlers/mod_rayo/rayo_components.c +++ b/src/mod/event_handlers/mod_rayo/rayo_components.c @@ -226,7 +226,8 @@ switch_status_t rayo_components_load(switch_loadable_module_interface_t **module if (rayo_input_component_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS || rayo_output_component_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS || rayo_prompt_component_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS || - rayo_record_component_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS) { + rayo_record_component_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS || + rayo_receivefax_component_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS) { return SWITCH_STATUS_TERM; } return SWITCH_STATUS_SUCCESS; @@ -241,6 +242,7 @@ switch_status_t rayo_components_shutdown(void) rayo_output_component_shutdown(); rayo_prompt_component_shutdown(); rayo_record_component_shutdown(); + rayo_receivefax_component_shutdown(); return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/event_handlers/mod_rayo/rayo_components.h b/src/mod/event_handlers/mod_rayo/rayo_components.h index 6e93dfbc43..8d3909dd4d 100644 --- a/src/mod/event_handlers/mod_rayo/rayo_components.h +++ b/src/mod/event_handlers/mod_rayo/rayo_components.h @@ -49,6 +49,9 @@ #define RAYO_PROMPT_NS RAYO_BASE "prompt:" RAYO_VERSION #define RAYO_PROMPT_COMPLETE_NS RAYO_BASE "prompt:complete:" RAYO_VERSION +#define RAYO_FAX_NS RAYO_BASE "fax:" RAYO_VERSION +#define RAYO_FAX_COMPLETE_NS RAYO_BASE "fax:complete:" RAYO_VERSION + #define COMPONENT_COMPLETE_STOP "stop", RAYO_EXT_COMPLETE_NS #define COMPONENT_COMPLETE_ERROR "error", RAYO_EXT_COMPLETE_NS #define COMPONENT_COMPLETE_HANGUP "hangup", RAYO_EXT_COMPLETE_NS @@ -58,12 +61,14 @@ extern switch_status_t rayo_input_component_load(switch_loadable_module_interfac extern switch_status_t rayo_output_component_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool, const char *config_file); extern switch_status_t rayo_prompt_component_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool, const char *config_file); extern switch_status_t rayo_record_component_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool, const char *config_file); +extern switch_status_t rayo_receivefax_component_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool, const char *config_file); extern switch_status_t rayo_components_shutdown(void); extern switch_status_t rayo_input_component_shutdown(void); extern switch_status_t rayo_output_component_shutdown(void); extern switch_status_t rayo_prompt_component_shutdown(void); extern switch_status_t rayo_record_component_shutdown(void); +extern switch_status_t rayo_receivefax_component_shutdown(void); extern void rayo_component_send_start(struct rayo_component *component, iks *iq); extern void rayo_component_send_iq_error(struct rayo_component *component, iks *iq, const char *error_name, const char *error_type); diff --git a/src/mod/event_handlers/mod_rayo/rayo_elements.c b/src/mod/event_handlers/mod_rayo/rayo_elements.c index 2bbf701794..a6e4f09140 100644 --- a/src/mod/event_handlers/mod_rayo/rayo_elements.c +++ b/src/mod/event_handlers/mod_rayo/rayo_elements.c @@ -32,6 +32,7 @@ * component validation */ ELEMENT(RAYO_INPUT) + ATTRIB(xmlns,, any) STRING_ATTRIB(mode, any, "any,dtmf,voice") OPTIONAL_ATTRIB(terminator,, dtmf_digit) ATTRIB(recognizer,, any) @@ -52,6 +53,7 @@ ELEMENT_END * component validation */ ELEMENT(RAYO_OUTPUT) + ATTRIB(xmlns,, any) ATTRIB(start-offset, 0, not_negative) ATTRIB(start-paused, false, bool) ATTRIB(repeat-interval, 0, not_negative) @@ -65,6 +67,7 @@ ELEMENT_END * validation */ ELEMENT(RAYO_OUTPUT_SEEK) + ATTRIB(xmlns,, any) STRING_ATTRIB(direction,, "forward,back") ATTRIB(amount,-1, positive) ELEMENT_END @@ -73,6 +76,7 @@ ELEMENT_END * component validation */ ELEMENT(RAYO_PROMPT) + ATTRIB(xmlns,, any) ATTRIB(barge-in, true, bool) ELEMENT_END @@ -80,6 +84,7 @@ ELEMENT_END * component validation */ ELEMENT(RAYO_RECORD) + ATTRIB(xmlns,, any) ATTRIB(format, wav, any) ATTRIB(start-beep, false, bool) ATTRIB(stop-beep, false, bool) @@ -95,12 +100,19 @@ ELEMENT_END * command validation */ ELEMENT(RAYO_JOIN) + ATTRIB(xmlns,, any) STRING_ATTRIB(direction, duplex, "send,recv,duplex") STRING_ATTRIB(media, bridge, "bridge,direct") ATTRIB(call-uri,, any) ATTRIB(mixer-name,, any) ELEMENT_END +/** + * command validation + */ +ELEMENT(RAYO_RECEIVEFAX) + ATTRIB(xmlns,, any) +ELEMENT_END /* For Emacs: * Local Variables: diff --git a/src/mod/event_handlers/mod_rayo/rayo_elements.h b/src/mod/event_handlers/mod_rayo/rayo_elements.h index c780f160cf..4c061dc35e 100644 --- a/src/mod/event_handlers/mod_rayo/rayo_elements.h +++ b/src/mod/event_handlers/mod_rayo/rayo_elements.h @@ -37,6 +37,7 @@ ELEMENT_DECL(RAYO_OUTPUT_SEEK) ELEMENT_DECL(RAYO_PROMPT) ELEMENT_DECL(RAYO_RECORD) ELEMENT_DECL(RAYO_JOIN) +ELEMENT_DECL(RAYO_RECEIVEFAX) #endif diff --git a/src/mod/event_handlers/mod_rayo/rayo_receivefax_component.c b/src/mod/event_handlers/mod_rayo/rayo_receivefax_component.c new file mode 100644 index 0000000000..09cd7a2c19 --- /dev/null +++ b/src/mod/event_handlers/mod_rayo/rayo_receivefax_component.c @@ -0,0 +1,378 @@ +/* + * mod_rayo for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2013, Grasshopper + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mod_rayo for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is Grasshopper + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Rienzo + * + * rayo_receivefax_component.c -- Rayo receivefax component implementation + * + */ +#include "rayo_components.h" +#include "rayo_elements.h" + +/** + * settings + */ +static struct { + const char *file_prefix; +} globals; + +struct receivefax_component { + /** component base class */ + struct rayo_component base; + /** true if HTTP PUT needs to be done after fax is received */ + int http_put_after_receive; + /** fax stored on local filesystem */ + const char *local_filename; + /** fax final target (may be same as local filename) */ + const char *filename; + /** Flag to stop fax */ + int stop; +}; + +#define RECEIVEFAX_FINISH "finish", RAYO_FAX_COMPLETE_NS + +#define RECEIVEFAX_COMPONENT(x) ((struct receivefax_component *)x) + +/** + * Start execution of call receivefax component + * @param call the call to receive fax from + * @param msg the original request + * @param session_data the call's session + */ +static iks *start_receivefax_component(struct rayo_actor *call, struct rayo_message *msg, void *session_data) +{ + iks *iq = msg->payload; + switch_core_session_t *session = (switch_core_session_t *)session_data; + struct receivefax_component *receivefax_component = NULL; + iks *receivefax = iks_find(iq, "receivefax"); + iks *response = NULL; + switch_event_t *execute_event = NULL; + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_memory_pool_t *pool; + int file_no; + + /* validate attributes */ + if (!VALIDATE_RAYO_RECEIVEFAX(receivefax)) { + return iks_new_error(iq, STANZA_ERROR_BAD_REQUEST); + } + + /* fax is only allowed if the call is not currently joined */ + if (rayo_call_is_joined(RAYO_CALL(call))) { + return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "can't receive fax on a joined call"); + } + + if (!rayo_call_set_faxing(RAYO_CALL(call), 1)) { + return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "fax already in progress"); + } + + /* create receivefax component */ + switch_core_new_memory_pool(&pool); + receivefax_component = switch_core_alloc(pool, sizeof(*receivefax_component)); + rayo_component_init((struct rayo_component *)receivefax_component, pool, RAT_CALL_COMPONENT, "receivefax", NULL, call, iks_find_attrib(iq, "from")); + file_no = rayo_actor_seq_next(call); + receivefax_component->filename = switch_core_sprintf(pool, "%s%s%s-%d", + globals.file_prefix, SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(session), file_no); + if (!strncmp(receivefax_component->filename, "http://", 7) || strncmp(receivefax_component->filename, "https://", 8)) { + /* This is an HTTP URL, need to PUT after fax is received */ + receivefax_component->local_filename = switch_core_sprintf(pool, "%s%s%s-%d", + SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(session), file_no); + receivefax_component->http_put_after_receive = 1; + } else { + /* assume file.. */ + receivefax_component->local_filename = receivefax_component->filename; + } + + /* add channel variable so that fax component can be located from fax events */ + switch_channel_set_variable(channel, "rayo_fax_jid", RAYO_JID(receivefax_component)); + + /* clear fax result variables */ + switch_channel_set_variable(channel, "fax_success", NULL); + switch_channel_set_variable(channel, "fax_result_code", NULL); + switch_channel_set_variable(channel, "fax_result_text", NULL); + switch_channel_set_variable(channel, "fax_document_transferred_pages", NULL); + switch_channel_set_variable(channel, "fax_document_total_pages", NULL); + switch_channel_set_variable(channel, "fax_image_resolution", NULL); + switch_channel_set_variable(channel, "fax_image_size", NULL); + switch_channel_set_variable(channel, "fax_bad_rows", NULL); + switch_channel_set_variable(channel, "fax_transfer_rate", NULL); + switch_channel_set_variable(channel, "fax_ecm_used", NULL); + switch_channel_set_variable(channel, "fax_local_station_id", NULL); + switch_channel_set_variable(channel, "fax_remote_station_id", NULL); + + /* clear fax interrupt variable */ + switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_read_frame_interrupt", NULL); + + /* execute rxfax APP */ + if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", "rxfax"); + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", receivefax_component->local_filename); + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event-lock", "true"); + if (!switch_channel_test_flag(channel, CF_PROXY_MODE)) { + switch_channel_set_flag(channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA); + } + + if (switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { + response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to rxfax (queue event failed)"); + if (execute_event) { + switch_event_destroy(&execute_event); + } + RAYO_UNLOCK(receivefax_component); + } else { + /* component starting... */ + rayo_component_send_start(RAYO_COMPONENT(receivefax_component), iq); + } + } else { + response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to create rxfax event"); + RAYO_UNLOCK(receivefax_component); + } + + return response; +} + +/** + * Stop execution of receivefax component + */ +static iks *stop_receivefax_component(struct rayo_actor *component, struct rayo_message *msg, void *data) +{ + iks *iq = msg->payload; + switch_core_session_t *session = switch_core_session_locate(RAYO_COMPONENT(component)->parent->id); + if (session) { + /* fail on read frame until component is destroyed */ + switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_read_frame_interrupt", RAYO_JID(component)); + switch_core_session_rwunlock(session); + } + RECEIVEFAX_COMPONENT(component)->stop = 1; + return iks_new_iq_result(iq); +} + +/** + * Add fax metadata to result + * @param event source of metadata + * @param name of metadata + * @param result to add metadata to + */ +static void insert_fax_metadata(switch_event_t *event, const char *name, iks *result) +{ + char actual_name[256]; + const char *value; + snprintf(actual_name, sizeof(actual_name), "variable_%s", name); + actual_name[sizeof(actual_name) - 1] = '\0'; + value = switch_event_get_header(event, actual_name); + if (!zstr(value)) { + iks *metadata = iks_insert(result, "metadata"); + iks_insert_attrib(metadata, "xmlns", RAYO_FAX_COMPLETE_NS); + iks_insert_attrib(metadata, "name", name); + iks_insert_attrib(metadata, "value", value); + } +} + +/** + * Handle rxfax execute event + * @param event received from FreeSWITCH core. It will be destroyed by the core after this function returns. + */ +static void on_execute_event(switch_event_t *event) +{ + const char *application = switch_event_get_header(event, "Application"); + if (!zstr(application) && !strcmp(application, "rxfax")) { + /* TODO */ + } +} + +/** + * Handle rxfax completion event from FreeSWITCH core + * @param event received from FreeSWITCH core. It will be destroyed by the core after this function returns. + */ +static void on_execute_complete_event(switch_event_t *event) +{ + const char *application = switch_event_get_header(event, "Application"); + if (!zstr(application) && !strcmp(application, "rxfax")) { + const char *uuid = switch_event_get_header(event, "Unique-ID"); + const char *fax_jid = switch_event_get_header(event, "variable_rayo_fax_jid"); + struct rayo_actor *component; + if (!zstr(fax_jid) && (component = RAYO_LOCATE(fax_jid))) { + const char *url = RECEIVEFAX_COMPONENT(component)->filename; + iks *result; + iks *complete; + iks *fax; + switch_core_session_t *session; + switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "Got result for %s\n", fax_jid); + + /* clean up channel */ + session = switch_core_session_locate(uuid); + if (session) { + switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_read_frame_interrupt", NULL); + switch_core_session_rwunlock(session); + } + + /* flag faxing as done */ + rayo_call_set_faxing(RAYO_CALL(RAYO_COMPONENT(component)->parent), 0); + + /* successful fax? */ + if (switch_true(switch_event_get_header(event, "variable_fax_success"))) { + result = rayo_component_create_complete_event(RAYO_COMPONENT(component), RECEIVEFAX_FINISH); + } else if (RECEIVEFAX_COMPONENT(component)->stop) { + result = rayo_component_create_complete_event(RAYO_COMPONENT(component), COMPONENT_COMPLETE_STOP); + } else { + result = rayo_component_create_complete_event(RAYO_COMPONENT(component), COMPONENT_COMPLETE_ERROR); + } + complete = iks_find(result, "complete"); + + /* add fax document information */ + { + const char *pages = switch_event_get_header(event, "variable_fax_document_transferred_pages"); + if (!zstr(pages) && switch_is_number(pages) && atoi(pages) > 0) { + const char *resolution = switch_event_get_header(event, "variable_fax_file_image_resolution"); + const char *size = switch_event_get_header(event, "variable_fax_image_size"); + + fax = iks_insert(complete, "fax"); + iks_insert_attrib(fax, "xmlns", RAYO_FAX_COMPLETE_NS); + + if (strlen(url) > strlen(SWITCH_PATH_SEPARATOR) && !strncmp(url, SWITCH_PATH_SEPARATOR, strlen(SWITCH_PATH_SEPARATOR))) { + /* convert absolute path to file:// URI */ + iks_insert_attrib_printf(fax, "url", "file://%s", url); + } else { + /* is already a URI (hopefully) */ + iks_insert_attrib(fax, "url", url); + } + + if (!zstr(resolution)) { + iks_insert_attrib(fax, "resolution", resolution); + } + if (!zstr(size)) { + iks_insert_attrib(fax, "size", size); + } + iks_insert_attrib(fax, "pages", pages); + } + + /* TODO transfer HTTP document and delete local copy */ + } + + /* add metadata from event */ + insert_fax_metadata(event, "fax_success", complete); + insert_fax_metadata(event, "fax_result_code", complete); + insert_fax_metadata(event, "fax_result_text", complete); + insert_fax_metadata(event, "fax_document_transferred_pages", complete); + insert_fax_metadata(event, "fax_document_total_pages", complete); + insert_fax_metadata(event, "fax_image_resolution", complete); + insert_fax_metadata(event, "fax_image_size", complete); + insert_fax_metadata(event, "fax_bad_rows", complete); + insert_fax_metadata(event, "fax_transfer_rate", complete); + insert_fax_metadata(event, "fax_ecm_used", complete); + insert_fax_metadata(event, "fax_local_station_id", complete); + insert_fax_metadata(event, "fax_remote_station_id", complete); + + rayo_component_send_complete_event(RAYO_COMPONENT(component), result); + + RAYO_UNLOCK(component); + } + } +} + +/** + * Process module XML configuration + * @param pool memory pool to allocate from + * @param config_file to use + * @return SWITCH_STATUS_SUCCESS on successful configuration + */ +static switch_status_t do_config(switch_memory_pool_t *pool, const char *config_file) +{ + switch_xml_t cfg, xml; + + /* set defaults */ + globals.file_prefix = switch_core_sprintf(pool, "%s%s", SWITCH_GLOBAL_dirs.recordings_dir, SWITCH_PATH_SEPARATOR); + + if (!(xml = switch_xml_open_cfg(config_file, &cfg, NULL))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", config_file); + return SWITCH_STATUS_TERM; + } + + /* get params */ + { + switch_xml_t settings = switch_xml_child(cfg, "receivefax"); + if (settings) { + switch_xml_t param; + for (param = switch_xml_child(settings, "param"); param; param = param->next) { + const char *var = switch_xml_attr_soft(param, "name"); + const char *val = switch_xml_attr_soft(param, "value"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "param: %s = %s\n", var, val); + if (!strcasecmp(var, "file-prefix")) { + if (!zstr(val)) { + globals.file_prefix = switch_core_strdup(pool, val); + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unsupported param: %s\n", var); + } + } + } + } + + switch_xml_free(xml); + + return SWITCH_STATUS_SUCCESS; +} + +/** + * Initialize receivefax component + * @param module_interface + * @param pool memory pool to allocate from + * @param config_file to use + * @return SWITCH_STATUS_SUCCESS if successful + */ +switch_status_t rayo_receivefax_component_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool, const char *config_file) +{ + if (do_config(pool, config_file) != SWITCH_STATUS_SUCCESS) { + return SWITCH_STATUS_TERM; + } + + switch_event_bind("rayo_receivefax_component", SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE, NULL, on_execute_complete_event, NULL); + switch_event_bind("rayo_receivefax_component", SWITCH_EVENT_CHANNEL_EXECUTE, NULL, on_execute_event, NULL); + + rayo_actor_command_handler_add(RAT_CALL, "", "set:"RAYO_FAX_NS":receivefax", start_receivefax_component); + rayo_actor_command_handler_add(RAT_CALL_COMPONENT, "receivefax", "set:"RAYO_EXT_NS":stop", stop_receivefax_component); + + return SWITCH_STATUS_SUCCESS; +} + +/** + * Shutdown receivefax component + * @return SWITCH_STATUS_SUCCESS if successful + */ +switch_status_t rayo_receivefax_component_shutdown(void) +{ + switch_event_unbind_callback(on_execute_event); + switch_event_unbind_callback(on_execute_complete_event); + + return SWITCH_STATUS_SUCCESS; +} + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet + */ From f47e523d69bc26b1d85613d9298ef5398f07d33c Mon Sep 17 00:00:00 2001 From: Chris Rienzo Date: Wed, 6 Nov 2013 17:57:31 -0500 Subject: [PATCH 27/31] mod_rayo: now supports HTTP(S) --- .../mod_rayo/rayo_receivefax_component.c | 52 ++++++++++--------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/src/mod/event_handlers/mod_rayo/rayo_receivefax_component.c b/src/mod/event_handlers/mod_rayo/rayo_receivefax_component.c index 09cd7a2c19..75528f8b52 100644 --- a/src/mod/event_handlers/mod_rayo/rayo_receivefax_component.c +++ b/src/mod/event_handlers/mod_rayo/rayo_receivefax_component.c @@ -92,14 +92,16 @@ static iks *start_receivefax_component(struct rayo_actor *call, struct rayo_mess file_no = rayo_actor_seq_next(call); receivefax_component->filename = switch_core_sprintf(pool, "%s%s%s-%d", globals.file_prefix, SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(session), file_no); - if (!strncmp(receivefax_component->filename, "http://", 7) || strncmp(receivefax_component->filename, "https://", 8)) { + if (!strncmp(receivefax_component->filename, "http://", 7) || !strncmp(receivefax_component->filename, "https://", 8)) { /* This is an HTTP URL, need to PUT after fax is received */ receivefax_component->local_filename = switch_core_sprintf(pool, "%s%s%s-%d", SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(session), file_no); receivefax_component->http_put_after_receive = 1; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s save fax to HTTP URL\n", RAYO_JID(receivefax_component)); } else { /* assume file.. */ receivefax_component->local_filename = receivefax_component->filename; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s save fax to local file\n", RAYO_JID(receivefax_component)); } /* add channel variable so that fax component can be located from fax events */ @@ -187,18 +189,6 @@ static void insert_fax_metadata(switch_event_t *event, const char *name, iks *re } } -/** - * Handle rxfax execute event - * @param event received from FreeSWITCH core. It will be destroyed by the core after this function returns. - */ -static void on_execute_event(switch_event_t *event) -{ - const char *application = switch_event_get_header(event, "Application"); - if (!zstr(application) && !strcmp(application, "rxfax")) { - /* TODO */ - } -} - /** * Handle rxfax completion event from FreeSWITCH core * @param event received from FreeSWITCH core. It will be destroyed by the core after this function returns. @@ -215,6 +205,7 @@ static void on_execute_complete_event(switch_event_t *event) iks *result; iks *complete; iks *fax; + int have_fax_document = 1; switch_core_session_t *session; switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "Got result for %s\n", fax_jid); @@ -228,10 +219,26 @@ static void on_execute_complete_event(switch_event_t *event) /* flag faxing as done */ rayo_call_set_faxing(RAYO_CALL(RAYO_COMPONENT(component)->parent), 0); + /* transfer HTTP document and delete local copy */ + if (RECEIVEFAX_COMPONENT(component)->http_put_after_receive && switch_file_exists(RECEIVEFAX_COMPONENT(component)->local_filename, RAYO_POOL(component))) { + switch_stream_handle_t stream = { 0 }; + SWITCH_STANDARD_STREAM(stream); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s PUT fax to %s\n", RAYO_JID(component), RECEIVEFAX_COMPONENT(component)->filename); + switch_api_execute("http_put", RECEIVEFAX_COMPONENT(component)->filename, NULL, &stream); + /* check if successful */ + if (!zstr(stream.data) && strncmp(stream.data, "+OK", 3)) { + /* PUT failed */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s PUT fax to %s failed: %s\n", RAYO_JID(component), RECEIVEFAX_COMPONENT(component)->filename, (char *)stream.data); + have_fax_document = 0; + } + switch_safe_free(stream.data) + switch_file_remove(RECEIVEFAX_COMPONENT(component)->local_filename, RAYO_POOL(component)); + } + /* successful fax? */ - if (switch_true(switch_event_get_header(event, "variable_fax_success"))) { + if (have_fax_document && switch_true(switch_event_get_header(event, "variable_fax_success"))) { result = rayo_component_create_complete_event(RAYO_COMPONENT(component), RECEIVEFAX_FINISH); - } else if (RECEIVEFAX_COMPONENT(component)->stop) { + } else if (have_fax_document && RECEIVEFAX_COMPONENT(component)->stop) { result = rayo_component_create_complete_event(RAYO_COMPONENT(component), COMPONENT_COMPLETE_STOP); } else { result = rayo_component_create_complete_event(RAYO_COMPONENT(component), COMPONENT_COMPLETE_ERROR); @@ -239,7 +246,7 @@ static void on_execute_complete_event(switch_event_t *event) complete = iks_find(result, "complete"); /* add fax document information */ - { + if (have_fax_document) { const char *pages = switch_event_get_header(event, "variable_fax_document_transferred_pages"); if (!zstr(pages) && switch_is_number(pages) && atoi(pages) > 0) { const char *resolution = switch_event_get_header(event, "variable_fax_file_image_resolution"); @@ -248,12 +255,11 @@ static void on_execute_complete_event(switch_event_t *event) fax = iks_insert(complete, "fax"); iks_insert_attrib(fax, "xmlns", RAYO_FAX_COMPLETE_NS); - if (strlen(url) > strlen(SWITCH_PATH_SEPARATOR) && !strncmp(url, SWITCH_PATH_SEPARATOR, strlen(SWITCH_PATH_SEPARATOR))) { + if (RECEIVEFAX_COMPONENT(component)->http_put_after_receive) { + iks_insert_attrib(fax, "url", url); + } else { /* convert absolute path to file:// URI */ iks_insert_attrib_printf(fax, "url", "file://%s", url); - } else { - /* is already a URI (hopefully) */ - iks_insert_attrib(fax, "url", url); } if (!zstr(resolution)) { @@ -264,8 +270,6 @@ static void on_execute_complete_event(switch_event_t *event) } iks_insert_attrib(fax, "pages", pages); } - - /* TODO transfer HTTP document and delete local copy */ } /* add metadata from event */ @@ -327,6 +331,8 @@ static switch_status_t do_config(switch_memory_pool_t *pool, const char *config_ } } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "receivefax file-prefix = %s\n", globals.file_prefix); + switch_xml_free(xml); return SWITCH_STATUS_SUCCESS; @@ -346,7 +352,6 @@ switch_status_t rayo_receivefax_component_load(switch_loadable_module_interface_ } switch_event_bind("rayo_receivefax_component", SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE, NULL, on_execute_complete_event, NULL); - switch_event_bind("rayo_receivefax_component", SWITCH_EVENT_CHANNEL_EXECUTE, NULL, on_execute_event, NULL); rayo_actor_command_handler_add(RAT_CALL, "", "set:"RAYO_FAX_NS":receivefax", start_receivefax_component); rayo_actor_command_handler_add(RAT_CALL_COMPONENT, "receivefax", "set:"RAYO_EXT_NS":stop", stop_receivefax_component); @@ -360,7 +365,6 @@ switch_status_t rayo_receivefax_component_load(switch_loadable_module_interface_ */ switch_status_t rayo_receivefax_component_shutdown(void) { - switch_event_unbind_callback(on_execute_event); switch_event_unbind_callback(on_execute_complete_event); return SWITCH_STATUS_SUCCESS; From 9f629cd42c3d2b22d2e1178adab2cdc6af05cdf0 Mon Sep 17 00:00:00 2001 From: Chris Rienzo Date: Thu, 7 Nov 2013 16:14:03 -0500 Subject: [PATCH 28/31] mod_rayo: add fax to service discovery query --- src/mod/event_handlers/mod_rayo/mod_rayo.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/mod/event_handlers/mod_rayo/mod_rayo.c b/src/mod/event_handlers/mod_rayo/mod_rayo.c index c5a57eeda5..51d1614751 100644 --- a/src/mod/event_handlers/mod_rayo/mod_rayo.c +++ b/src/mod/event_handlers/mod_rayo/mod_rayo.c @@ -2371,11 +2371,14 @@ static iks *on_iq_get_xmpp_disco(struct rayo_actor *server, struct rayo_message iks *node = msg->payload; iks *response = NULL; iks *x; + iks *feature; response = iks_new_iq_result(node); x = iks_insert(response, "query"); iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_DISCO); - x = iks_insert(x, "feature"); - iks_insert_attrib(x, "var", RAYO_NS); + feature = iks_insert(x, "feature"); + iks_insert_attrib(feature, "var", RAYO_NS); + feature = iks_insert(x, "feature"); + iks_insert_attrib(feature, "var", RAYO_FAX_NS); /* TODO The response MUST also include features for the application formats and transport methods supported by * the responding entity, as described in the relevant specifications. From 02f1853d2f765d44a802791997e8b2189e713a03 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 8 Nov 2013 03:47:07 +0500 Subject: [PATCH 29/31] add 8k to opus --- src/mod/codecs/mod_opus/mod_opus.c | 289 +++++++++++++++++++++++++++-- 1 file changed, 274 insertions(+), 15 deletions(-) diff --git a/src/mod/codecs/mod_opus/mod_opus.c b/src/mod/codecs/mod_opus/mod_opus.c index b283cb2c01..f3d5585fdf 100644 --- a/src/mod/codecs/mod_opus/mod_opus.c +++ b/src/mod/codecs/mod_opus/mod_opus.c @@ -36,36 +36,231 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load); SWITCH_MODULE_DEFINITION(mod_opus, mod_opus_load, NULL, NULL); +/*! \brief Various codec settings */ +struct opus_codec_settings { + int useinbandfec; + int usedtx; + int maxaveragebitrate; + int stereo; + int cbr; + int sprop_maxcapturerate; + int sprop_stereo; + int maxptime; + int minptime; + int ptime; + int samplerate; +}; +typedef struct opus_codec_settings opus_codec_settings_t; + +static opus_codec_settings_t default_codec_settings = { + /*.useinbandfec */ 1, + /*.usedtx */ 1, + /*.maxaveragebitrate */ 30000, + /*.stereo*/ 0, + /*.cbr*/ 0, + /*.sprop_maxcapturerate*/ 0, + /*.sprop_stereo*/ 0, + /*.maxptime*/ 0, + /*.minptime*/ 0, + /*.ptime*/ 0, + /*.samplerate*/ 0 +}; + struct opus_context { OpusEncoder *encoder_object; OpusDecoder *decoder_object; int frame_size; }; +static switch_status_t switch_opus_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp) +{ + if (codec_fmtp) { + opus_codec_settings_t local_settings = { 0 }; + opus_codec_settings_t *codec_settings = &local_settings; + + if (codec_fmtp->private_info) { + codec_settings = codec_fmtp->private_info; + if (zstr(fmtp)) { + memcpy(codec_settings, &default_codec_settings, sizeof(*codec_settings)); + } + } + + if (fmtp) { + int x, argc; + char *argv[10]; + char *fmtp_dup = strdup(fmtp); + + switch_assert(fmtp_dup); + + argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0]))); + for (x = 0; x < argc; x++) { + char *data = argv[x]; + char *arg; + switch_assert(data); + while (*data == ' ') { + data++; + } + + + if ((arg = strchr(data, '='))) { + *arg++ = '\0'; + + if (codec_settings) { + if (!strcasecmp(data, "useinbandfec")) { + codec_settings->useinbandfec = switch_true(arg); + } + + if (!strcasecmp(data, "usedtx")) { + codec_settings->usedtx = switch_true(arg); + } + + if (!strcasecmp(data, "sprop-maxcapturerate")) { + codec_settings->sprop_maxcapturerate = atoi(arg); + } + + if (!strcasecmp(data, "maxptime")) { + codec_settings->maxptime = atoi(arg); + } + + if (!strcasecmp(data, "minptime")) { + codec_settings->minptime = atoi(arg); + } + + if (!strcasecmp(data, "ptime")) { + codec_settings->ptime = atoi(arg); + codec_fmtp->microseconds_per_packet = codec_settings->ptime * 1000; + } + + if (!strcasecmp(data, "samplerate")) { + codec_settings->samplerate = atoi(arg); + codec_fmtp->actual_samples_per_second = codec_settings->samplerate; + } + + if (!strcasecmp(data, "maxaveragebitrate")) { + codec_settings->maxaveragebitrate = atoi(arg); + switch(codec_fmtp->actual_samples_per_second) { + case 8000: + { + if(codec_settings->maxaveragebitrate < 6000 || codec_settings->maxaveragebitrate > 20000) { + codec_settings->maxaveragebitrate = 20000; + } + break; + } + case 12000: + { + if(codec_settings->maxaveragebitrate < 7000 || codec_settings->maxaveragebitrate > 25000) { + codec_settings->maxaveragebitrate = 25000; + } + break; + } + case 16000: + { + if(codec_settings->maxaveragebitrate < 8000 || codec_settings->maxaveragebitrate > 30000) { + codec_settings->maxaveragebitrate = 30000; + } + break; + } + case 24000: + { + if(codec_settings->maxaveragebitrate < 12000 || codec_settings->maxaveragebitrate > 40000) { + codec_settings->maxaveragebitrate = 40000; + } + break; + } + + default: + /* this should never happen but 20000 is common among all rates */ + codec_settings->maxaveragebitrate = 20000; + break; + } + + + codec_fmtp->bits_per_second = codec_settings->maxaveragebitrate; + } + + } + } + } + free(fmtp_dup); + } + //codec_fmtp->bits_per_second = bit_rate; + return SWITCH_STATUS_SUCCESS; + } + return SWITCH_STATUS_FALSE; +} + +static char *gen_fmtp(opus_codec_settings_t *settings, switch_memory_pool_t *pool) +{ + char buf[256] = ""; + + if (settings->useinbandfec) { + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "useinbandfec=1;"); + } + + if (settings->usedtx) { + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "usedtx=1;"); + } + + if (settings->maxaveragebitrate) { + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "maxaveragebitrate=%d;", settings->maxaveragebitrate); + + } + + if (settings->ptime) { + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "ptime=%d;", settings->ptime); + } + + if (settings->minptime) { + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "minptime=%d;", settings->minptime); + } + + if (settings->maxptime) { + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "maxptime=%d;", settings->maxptime); + } + + if (settings->samplerate) { + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "samplerate=%d;", settings->samplerate); + } + + if (end_of(buf) == ';') { + end_of(buf) = '\0'; + } + + return switch_core_strdup(pool, buf); + +} + static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings) { struct opus_context *context = NULL; int encoding = (flags & SWITCH_CODEC_FLAG_ENCODE); int decoding = (flags & SWITCH_CODEC_FLAG_DECODE); + switch_codec_fmtp_t codec_fmtp; + opus_codec_settings_t opus_codec_settings = { 0 }; if (!(encoding || decoding) || (!(context = switch_core_alloc(codec->memory_pool, sizeof(*context))))) { return SWITCH_STATUS_FALSE; } context->frame_size = codec->implementation->samples_per_packet; - + + memset(&codec_fmtp, '\0', sizeof(struct switch_codec_fmtp)); + codec_fmtp.private_info = &opus_codec_settings; + switch_opus_fmtp_parse(codec->fmtp_in, &codec_fmtp); + + codec->fmtp_out = gen_fmtp(&opus_codec_settings, codec->memory_pool); + if (encoding) { /* come up with a way to specify these */ - int bitrate_bps = codec->implementation->bits_per_second; + int bitrate_bps = OPUS_AUTO; int use_vbr = 1; int complexity = 10; - int use_inbandfec = 1; - int use_dtx = 1; - int bandwidth = OPUS_BANDWIDTH_FULLBAND; int err; + int samplerate = opus_codec_settings.samplerate ? opus_codec_settings.samplerate : codec->implementation->actual_samples_per_second; - context->encoder_object = opus_encoder_create(codec->implementation->actual_samples_per_second, - codec->implementation->number_of_channels, OPUS_APPLICATION_VOIP, &err); + context->encoder_object = opus_encoder_create(samplerate, + codec->implementation->number_of_channels, + OPUS_APPLICATION_VOIP, &err); if (err != OPUS_OK) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot create encoder: %s\n", opus_strerror(err)); @@ -73,12 +268,24 @@ static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag } opus_encoder_ctl(context->encoder_object, OPUS_SET_BITRATE(bitrate_bps)); - opus_encoder_ctl(context->encoder_object, OPUS_SET_BANDWIDTH(bandwidth)); + + if (codec->implementation->actual_samples_per_second == 8000) { + opus_encoder_ctl(context->encoder_object, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND)); + opus_encoder_ctl(context->encoder_object, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND)); + } else { + opus_encoder_ctl(context->encoder_object, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND)); + } + opus_encoder_ctl(context->encoder_object, OPUS_SET_VBR(use_vbr)); opus_encoder_ctl(context->encoder_object, OPUS_SET_COMPLEXITY(complexity)); - opus_encoder_ctl(context->encoder_object, OPUS_SET_INBAND_FEC(use_inbandfec)); - opus_encoder_ctl(context->encoder_object, OPUS_SET_DTX(use_dtx)); + if (opus_codec_settings.useinbandfec) { + opus_encoder_ctl(context->encoder_object, OPUS_SET_INBAND_FEC(opus_codec_settings.useinbandfec)); + } + + if (opus_codec_settings.usedtx) { + opus_encoder_ctl(context->encoder_object, OPUS_SET_DTX(opus_codec_settings.usedtx)); + } } if (decoding) { @@ -143,7 +350,7 @@ static switch_status_t switch_opus_encode(switch_codec_t *codec, if (len > 1275) len = 1275; bytes = opus_encode(context->encoder_object, (void *) decoded_data, decoded_data_len / 2, (unsigned char *) encoded_data, len); - + if (bytes > 0) { *encoded_data_len = (uint32_t) bytes; return SWITCH_STATUS_SUCCESS; @@ -186,26 +393,40 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load) int mss = 10000; int x = 0; int rate = 48000; - int bits = 32000; + int bits = 0; + char *dft_fmtp = NULL; + opus_codec_settings_t settings = { 0 }; /* connect my internal structure to the blank pointer passed to me */ *module_interface = switch_loadable_module_create_module_interface(pool, modname); SWITCH_ADD_CODEC(codec_interface, "OPUS (STANDARD)"); + codec_interface->parse_fmtp = switch_opus_fmtp_parse; + + settings = default_codec_settings; + + for (x = 0; x < 3; x++) { + + settings.ptime = mss / 1000; + settings.maxptime = settings.ptime; + settings.minptime = settings.ptime; + settings.samplerate = rate; + dft_fmtp = gen_fmtp(&settings, pool); + switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ 116, /* the IANA code number */ "opus",/* the IANA code name */ - NULL, /* default fmtp to send (can be overridden by the init function) */ - rate, /* samples transferred per second */ + dft_fmtp, /* default fmtp to send (can be overridden by the init function) */ + 48000, /* samples transferred per second */ rate, /* actual samples transferred per second */ bits, /* bits transferred per second */ mss, /* number of microseconds per frame */ samples, /* number of samples per frame */ bytes, /* number of bytes per frame decompressed */ 0, /* number of bytes per frame compressed */ - 1, /* number of channels represented */ + 1,/* number of channels represented */ 1, /* number of frames per network packet */ switch_opus_init, /* function to initialize a codec handle using this implementation */ switch_opus_encode, /* function to encode raw data into encoded data */ @@ -218,6 +439,44 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load) } + + samples = 80; + bytes = 160; + mss = 10000; + rate = 8000; + + for (x = 0; x < 3; x++) { + + settings.ptime = mss / 1000; + settings.maxptime = settings.ptime; + settings.minptime = settings.ptime; + settings.samplerate = rate; + dft_fmtp = gen_fmtp(&settings, pool); + + switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ + 116, /* the IANA code number */ + "opus",/* the IANA code name */ + dft_fmtp, /* default fmtp to send (can be overridden by the init function) */ + 48000, /* samples transferred per second */ + rate, /* actual samples transferred per second */ + bits, /* bits transferred per second */ + mss, /* number of microseconds per frame */ + samples, /* number of samples per frame */ + bytes, /* number of bytes per frame decompressed */ + 0, /* number of bytes per frame compressed */ + 1,/* number of channels represented */ + 1, /* number of frames per network packet */ + switch_opus_init, /* function to initialize a codec handle using this implementation */ + switch_opus_encode, /* function to encode raw data into encoded data */ + switch_opus_decode, /* function to decode encoded data into raw data */ + switch_opus_destroy); /* deinitalize a codec handle using this implementation */ + + bytes += 160; + samples += 80; + mss += 10000; + + } + /* indicate that the module should continue to be loaded */ return SWITCH_STATUS_SUCCESS; } From d22d045b14504e00316a59e99a8152fcc0e6b65e Mon Sep 17 00:00:00 2001 From: Chris Rienzo Date: Thu, 7 Nov 2013 20:31:58 -0500 Subject: [PATCH 30/31] mod_rayo: add component --- src/mod/event_handlers/mod_rayo/Makefile | 4 +- .../conf/autoload_configs/rayo.conf.xml | 8 +- src/mod/event_handlers/mod_rayo/mod_rayo.c | 14 +- .../event_handlers/mod_rayo/rayo_components.c | 4 +- .../event_handlers/mod_rayo/rayo_components.h | 4 +- .../event_handlers/mod_rayo/rayo_elements.c | 32 ++- .../event_handlers/mod_rayo/rayo_elements.h | 5 +- ...efax_component.c => rayo_fax_components.c} | 243 +++++++++++++++--- 8 files changed, 257 insertions(+), 57 deletions(-) rename src/mod/event_handlers/mod_rayo/{rayo_receivefax_component.c => rayo_fax_components.c} (60%) diff --git a/src/mod/event_handlers/mod_rayo/Makefile b/src/mod/event_handlers/mod_rayo/Makefile index bfb38dbd6c..a3bfc45d47 100644 --- a/src/mod/event_handlers/mod_rayo/Makefile +++ b/src/mod/event_handlers/mod_rayo/Makefile @@ -11,10 +11,10 @@ LOCAL_OBJS= $(IKS_LA) \ nlsml.o \ rayo_components.o \ rayo_elements.o \ + rayo_fax_components.o \ rayo_input_component.o \ rayo_output_component.o \ rayo_prompt_component.o \ - rayo_receivefax_component.o \ rayo_record_component.o \ sasl.o \ srgs.o \ @@ -24,11 +24,11 @@ LOCAL_SOURCES= \ nlsml.c \ rayo_components.c \ rayo_elements.c \ + rayo_fax_components.c \ rayo_input_component.c \ rayo_output_component.c \ rayo_prompt_component.c \ rayo_record_component.c \ - rayo_receivefax_component.c \ sasl.c \ srgs.c \ xmpp_streams.c diff --git a/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml b/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml index c8171569af..3fdc772daf 100644 --- a/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml +++ b/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml @@ -16,11 +16,11 @@ - - + + - - + + diff --git a/src/mod/event_handlers/mod_rayo/mod_rayo.c b/src/mod/event_handlers/mod_rayo/mod_rayo.c index 51d1614751..f852d2c5f8 100644 --- a/src/mod/event_handlers/mod_rayo/mod_rayo.c +++ b/src/mod/event_handlers/mod_rayo/mod_rayo.c @@ -952,6 +952,7 @@ static void rayo_call_cleanup(struct rayo_actor *actor) iks_delete(revent); switch_event_destroy(&event); + switch_core_hash_destroy(&call->pcps); } /** @@ -1130,13 +1131,23 @@ static struct rayo_call *_rayo_call_create(const char *uuid, const char *file, i return rayo_call_init(call, pool, uuid, file, line); } +/** + * Mixer destructor + */ +static void rayo_mixer_cleanup(struct rayo_actor *actor) +{ + struct rayo_mixer *mixer = RAYO_MIXER(actor); + switch_core_hash_destroy(&mixer->members); + switch_core_hash_destroy(&mixer->subscribers); +} + /** * Initialize mixer */ static struct rayo_mixer *rayo_mixer_init(struct rayo_mixer *mixer, switch_memory_pool_t *pool, const char *name, const char *file, int line) { char *mixer_jid = switch_mprintf("%s@%s", name, RAYO_JID(globals.server)); - rayo_actor_init(RAYO_ACTOR(mixer), pool, RAT_MIXER, "", name, mixer_jid, NULL, rayo_mixer_send, file, line); + rayo_actor_init(RAYO_ACTOR(mixer), pool, RAT_MIXER, "", name, mixer_jid, rayo_mixer_cleanup, rayo_mixer_send, file, line); switch_core_hash_init(&mixer->members, pool); switch_core_hash_init(&mixer->subscribers, pool); switch_safe_free(mixer_jid); @@ -1307,6 +1318,7 @@ static void rayo_peer_server_cleanup(struct rayo_actor *actor) RAYO_UNLOCK(client); RAYO_DESTROY(client); } + switch_core_hash_destroy(&rserver->clients); switch_mutex_unlock(globals.clients_mutex); } diff --git a/src/mod/event_handlers/mod_rayo/rayo_components.c b/src/mod/event_handlers/mod_rayo/rayo_components.c index 2448e166a8..7ad96d2a7d 100644 --- a/src/mod/event_handlers/mod_rayo/rayo_components.c +++ b/src/mod/event_handlers/mod_rayo/rayo_components.c @@ -227,7 +227,7 @@ switch_status_t rayo_components_load(switch_loadable_module_interface_t **module rayo_output_component_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS || rayo_prompt_component_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS || rayo_record_component_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS || - rayo_receivefax_component_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS) { + rayo_fax_components_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS) { return SWITCH_STATUS_TERM; } return SWITCH_STATUS_SUCCESS; @@ -242,7 +242,7 @@ switch_status_t rayo_components_shutdown(void) rayo_output_component_shutdown(); rayo_prompt_component_shutdown(); rayo_record_component_shutdown(); - rayo_receivefax_component_shutdown(); + rayo_fax_components_shutdown(); return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/event_handlers/mod_rayo/rayo_components.h b/src/mod/event_handlers/mod_rayo/rayo_components.h index 8d3909dd4d..5d1367d645 100644 --- a/src/mod/event_handlers/mod_rayo/rayo_components.h +++ b/src/mod/event_handlers/mod_rayo/rayo_components.h @@ -61,14 +61,14 @@ extern switch_status_t rayo_input_component_load(switch_loadable_module_interfac extern switch_status_t rayo_output_component_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool, const char *config_file); extern switch_status_t rayo_prompt_component_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool, const char *config_file); extern switch_status_t rayo_record_component_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool, const char *config_file); -extern switch_status_t rayo_receivefax_component_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool, const char *config_file); +extern switch_status_t rayo_fax_components_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool, const char *config_file); extern switch_status_t rayo_components_shutdown(void); extern switch_status_t rayo_input_component_shutdown(void); extern switch_status_t rayo_output_component_shutdown(void); extern switch_status_t rayo_prompt_component_shutdown(void); extern switch_status_t rayo_record_component_shutdown(void); -extern switch_status_t rayo_receivefax_component_shutdown(void); +extern switch_status_t rayo_fax_components_shutdown(void); extern void rayo_component_send_start(struct rayo_component *component, iks *iq); extern void rayo_component_send_iq_error(struct rayo_component *component, iks *iq, const char *error_name, const char *error_type); diff --git a/src/mod/event_handlers/mod_rayo/rayo_elements.c b/src/mod/event_handlers/mod_rayo/rayo_elements.c index a6e4f09140..78209c3bd6 100644 --- a/src/mod/event_handlers/mod_rayo/rayo_elements.c +++ b/src/mod/event_handlers/mod_rayo/rayo_elements.c @@ -49,6 +49,17 @@ ELEMENT(RAYO_INPUT) ATTRIB(start-timers, true, bool) ELEMENT_END +/** + * command validation + */ +ELEMENT(RAYO_JOIN) + ATTRIB(xmlns,, any) + STRING_ATTRIB(direction, duplex, "send,recv,duplex") + STRING_ATTRIB(media, bridge, "bridge,direct") + ATTRIB(call-uri,, any) + ATTRIB(mixer-name,, any) +ELEMENT_END + /** * component validation */ @@ -80,6 +91,13 @@ ELEMENT(RAYO_PROMPT) ATTRIB(barge-in, true, bool) ELEMENT_END +/** + * command validation + */ +ELEMENT(RAYO_RECEIVEFAX) + ATTRIB(xmlns,, any) +ELEMENT_END + /** * component validation */ @@ -97,22 +115,12 @@ ELEMENT(RAYO_RECORD) ELEMENT_END /** - * command validation + * command validation */ -ELEMENT(RAYO_JOIN) +ELEMENT(RAYO_SENDFAX) ATTRIB(xmlns,, any) - STRING_ATTRIB(direction, duplex, "send,recv,duplex") - STRING_ATTRIB(media, bridge, "bridge,direct") - ATTRIB(call-uri,, any) - ATTRIB(mixer-name,, any) ELEMENT_END -/** - * command validation - */ -ELEMENT(RAYO_RECEIVEFAX) - ATTRIB(xmlns,, any) -ELEMENT_END /* For Emacs: * Local Variables: diff --git a/src/mod/event_handlers/mod_rayo/rayo_elements.h b/src/mod/event_handlers/mod_rayo/rayo_elements.h index 4c061dc35e..e76809cc9e 100644 --- a/src/mod/event_handlers/mod_rayo/rayo_elements.h +++ b/src/mod/event_handlers/mod_rayo/rayo_elements.h @@ -32,12 +32,13 @@ #include "iks_helpers.h" ELEMENT_DECL(RAYO_INPUT) +ELEMENT_DECL(RAYO_JOIN) ELEMENT_DECL(RAYO_OUTPUT) ELEMENT_DECL(RAYO_OUTPUT_SEEK) ELEMENT_DECL(RAYO_PROMPT) -ELEMENT_DECL(RAYO_RECORD) -ELEMENT_DECL(RAYO_JOIN) ELEMENT_DECL(RAYO_RECEIVEFAX) +ELEMENT_DECL(RAYO_RECORD) +ELEMENT_DECL(RAYO_SENDFAX) #endif diff --git a/src/mod/event_handlers/mod_rayo/rayo_receivefax_component.c b/src/mod/event_handlers/mod_rayo/rayo_fax_components.c similarity index 60% rename from src/mod/event_handlers/mod_rayo/rayo_receivefax_component.c rename to src/mod/event_handlers/mod_rayo/rayo_fax_components.c index 75528f8b52..9cd48e2c2c 100644 --- a/src/mod/event_handlers/mod_rayo/rayo_receivefax_component.c +++ b/src/mod/event_handlers/mod_rayo/rayo_fax_components.c @@ -23,7 +23,7 @@ * Contributor(s): * Chris Rienzo * - * rayo_receivefax_component.c -- Rayo receivefax component implementation + * rayo_fax_components.c -- Rayo receivefax and sendfax components implementation * */ #include "rayo_components.h" @@ -36,23 +36,197 @@ static struct { const char *file_prefix; } globals; -struct receivefax_component { +struct fax_component { /** component base class */ struct rayo_component base; + /** Flag to stop fax */ + int stop; +}; + +#define FAX_COMPONENT(x) ((struct fax_component *)x) + +struct receivefax_component { + /** fax component base class */ + struct fax_component base; /** true if HTTP PUT needs to be done after fax is received */ int http_put_after_receive; /** fax stored on local filesystem */ const char *local_filename; /** fax final target (may be same as local filename) */ const char *filename; - /** Flag to stop fax */ - int stop; }; -#define RECEIVEFAX_FINISH "finish", RAYO_FAX_COMPLETE_NS - #define RECEIVEFAX_COMPONENT(x) ((struct receivefax_component *)x) +#define FAX_FINISH "finish", RAYO_FAX_COMPLETE_NS + +/** + * Start execution of call sendfax component + * @param call the call to send fax to + * @param msg the original request + * @param session_data the call's session + */ +static iks *start_sendfax_component(struct rayo_actor *call, struct rayo_message *msg, void *session_data) +{ + iks *iq = msg->payload; + switch_core_session_t *session = (switch_core_session_t *)session_data; + struct fax_component *sendfax_component = NULL; + iks *sendfax = iks_find(iq, "sendfax"); + iks *response = NULL; + switch_event_t *execute_event = NULL; + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_memory_pool_t *pool; + iks *document; + const char *fax_document; + const char *fax_header; + const char *fax_identity; + const char *pages; + + /* validate attributes */ + if (!VALIDATE_RAYO_SENDFAX(sendfax)) { + return iks_new_error(iq, STANZA_ERROR_BAD_REQUEST); + } + + /* fax is only allowed if the call is not currently joined */ + if (rayo_call_is_joined(RAYO_CALL(call))) { + return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "can't send fax on a joined call"); + } + + if (!rayo_call_set_faxing(RAYO_CALL(call), 1)) { + return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "fax already in progress"); + } + + /* get fax document */ + document = iks_find(sendfax, "document"); + if (!document) { + return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "missing document"); + } + fax_document = iks_find_attrib_soft(document, "url"); + if (zstr(fax_document)) { + return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "missing document url"); + } + + /* is valid URL type? */ + if (!strncasecmp(fax_document, "http://", 7) || strncasecmp(fax_document, "https://", 8)) { + switch_stream_handle_t stream = { 0 }; + SWITCH_STANDARD_STREAM(stream); + /* need to fetch document from server... */ + switch_api_execute("http_get", fax_document, session, &stream); + if (!zstr(stream.data) && !strncasecmp(fax_document, SWITCH_PATH_SEPARATOR, sizeof(SWITCH_PATH_SEPARATOR) - 1)) { + fax_document = switch_core_session_strdup(session, stream.data); + } else { + switch_safe_free(stream.data); + return iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to fetch document"); + } + switch_safe_free(stream.data); + } else if (!strncasecmp(fax_document, "file://", 7)) { + fax_document = fax_document + 7; + if (zstr(fax_document)) { + return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "invalid file:// url"); + } + } else if (strncasecmp(fax_document, SWITCH_PATH_SEPARATOR, sizeof(SWITCH_PATH_SEPARATOR) - 1)) { + return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "unsupported url type"); + } + + /* does document exist? */ + if (!switch_file_exists(fax_document, pool)) { + return iks_new_error_detailed_printf(iq, STANZA_ERROR_BAD_REQUEST, "file not found: %s", fax_document); + } + + /* get fax identity and header */ + fax_identity = iks_find_attrib_soft(document, "identity"); + if (!zstr(fax_identity)) { + switch_channel_set_variable(channel, "fax_ident", fax_identity); + } else { + switch_channel_set_variable(channel, "fax_ident", NULL); + } + fax_header = iks_find_attrib_soft(document, "header"); + if (!zstr(fax_header)) { + switch_channel_set_variable(channel, "fax_header", fax_header); + } else { + switch_channel_set_variable(channel, "fax_header", NULL); + } + + /* get pages to send */ + pages = iks_find_attrib_soft(document, "pages"); + if (!zstr(pages)) { + if (switch_regex_match(pages, "[1-9][0-9]*(-[1-9][0-9]*)?") == SWITCH_STATUS_FALSE) { + return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "invalid pages value"); + } else { + int start = 0; + int end = 0; + char *pages_dup = switch_core_session_strdup(session, pages); + char *sep = strchr(pages_dup, '-'); + if (sep) { + *sep = '\0'; + sep++; + end = atoi(sep); + } + start = atoi(pages_dup); + if (end && end < start) { + return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "invalid pages value"); + } + switch_channel_set_variable(channel, "fax_start_page", pages_dup); + switch_channel_set_variable(channel, "fax_end_page", sep); + } + } else { + switch_channel_set_variable(channel, "fax_start_page", NULL); + switch_channel_set_variable(channel, "fax_end_page", NULL); + } + + /* create sendfax component */ + switch_core_new_memory_pool(&pool); + sendfax_component = switch_core_alloc(pool, sizeof(*sendfax_component)); + rayo_component_init((struct rayo_component *)sendfax_component, pool, RAT_CALL_COMPONENT, "sendfax", NULL, call, iks_find_attrib(iq, "from")); + + /* add channel variable so that fax component can be located from fax events */ + switch_channel_set_variable(channel, "rayo_fax_jid", RAYO_JID(sendfax_component)); + + /* clear fax result variables */ + switch_channel_set_variable(channel, "fax_success", NULL); + switch_channel_set_variable(channel, "fax_result_code", NULL); + switch_channel_set_variable(channel, "fax_result_text", NULL); + switch_channel_set_variable(channel, "fax_document_transferred_pages", NULL); + switch_channel_set_variable(channel, "fax_document_total_pages", NULL); + switch_channel_set_variable(channel, "fax_image_resolution", NULL); + switch_channel_set_variable(channel, "fax_image_size", NULL); + switch_channel_set_variable(channel, "fax_bad_rows", NULL); + switch_channel_set_variable(channel, "fax_transfer_rate", NULL); + switch_channel_set_variable(channel, "fax_ecm_used", NULL); + switch_channel_set_variable(channel, "fax_local_station_id", NULL); + switch_channel_set_variable(channel, "fax_remote_station_id", NULL); + + /* clear fax interrupt variable */ + switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_read_frame_interrupt", NULL); + + /* execute txfax APP */ + if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", "txfax"); + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", fax_document); + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event-lock", "true"); + if (!switch_channel_test_flag(channel, CF_PROXY_MODE)) { + switch_channel_set_flag(channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA); + } + + if (switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { + response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to txfax (queue event failed)"); + if (execute_event) { + switch_event_destroy(&execute_event); + } + RAYO_UNLOCK(sendfax_component); + } else { + /* component starting... */ + rayo_component_send_start(RAYO_COMPONENT(sendfax_component), iq); + } + } else { + response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to create txfax event"); + RAYO_UNLOCK(sendfax_component); + } + + return response; +} + /** * Start execution of call receivefax component * @param call the call to receive fax from @@ -153,9 +327,9 @@ static iks *start_receivefax_component(struct rayo_actor *call, struct rayo_mess } /** - * Stop execution of receivefax component + * Stop execution of fax component */ -static iks *stop_receivefax_component(struct rayo_actor *component, struct rayo_message *msg, void *data) +static iks *stop_fax_component(struct rayo_actor *component, struct rayo_message *msg, void *data) { iks *iq = msg->payload; switch_core_session_t *session = switch_core_session_locate(RAYO_COMPONENT(component)->parent->id); @@ -164,7 +338,7 @@ static iks *stop_receivefax_component(struct rayo_actor *component, struct rayo_ switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_read_frame_interrupt", RAYO_JID(component)); switch_core_session_rwunlock(session); } - RECEIVEFAX_COMPONENT(component)->stop = 1; + FAX_COMPONENT(component)->stop = 1; return iks_new_iq_result(iq); } @@ -190,18 +364,19 @@ static void insert_fax_metadata(switch_event_t *event, const char *name, iks *re } /** - * Handle rxfax completion event from FreeSWITCH core + * Handle fax completion event from FreeSWITCH core * @param event received from FreeSWITCH core. It will be destroyed by the core after this function returns. */ static void on_execute_complete_event(switch_event_t *event) { const char *application = switch_event_get_header(event, "Application"); - if (!zstr(application) && !strcmp(application, "rxfax")) { + + if (!zstr(application) && (!strcmp(application, "rxfax") || !strcmp(application, "txfax"))) { + int is_rxfax = !strcmp(application, "rxfax"); const char *uuid = switch_event_get_header(event, "Unique-ID"); const char *fax_jid = switch_event_get_header(event, "variable_rayo_fax_jid"); struct rayo_actor *component; if (!zstr(fax_jid) && (component = RAYO_LOCATE(fax_jid))) { - const char *url = RECEIVEFAX_COMPONENT(component)->filename; iks *result; iks *complete; iks *fax; @@ -216,11 +391,8 @@ static void on_execute_complete_event(switch_event_t *event) switch_core_session_rwunlock(session); } - /* flag faxing as done */ - rayo_call_set_faxing(RAYO_CALL(RAYO_COMPONENT(component)->parent), 0); - - /* transfer HTTP document and delete local copy */ - if (RECEIVEFAX_COMPONENT(component)->http_put_after_receive && switch_file_exists(RECEIVEFAX_COMPONENT(component)->local_filename, RAYO_POOL(component))) { + /* RX only: transfer HTTP document and delete local copy */ + if (is_rxfax && RECEIVEFAX_COMPONENT(component)->http_put_after_receive && switch_file_exists(RECEIVEFAX_COMPONENT(component)->local_filename, RAYO_POOL(component))) { switch_stream_handle_t stream = { 0 }; SWITCH_STANDARD_STREAM(stream); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s PUT fax to %s\n", RAYO_JID(component), RECEIVEFAX_COMPONENT(component)->filename); @@ -237,16 +409,16 @@ static void on_execute_complete_event(switch_event_t *event) /* successful fax? */ if (have_fax_document && switch_true(switch_event_get_header(event, "variable_fax_success"))) { - result = rayo_component_create_complete_event(RAYO_COMPONENT(component), RECEIVEFAX_FINISH); - } else if (have_fax_document && RECEIVEFAX_COMPONENT(component)->stop) { + result = rayo_component_create_complete_event(RAYO_COMPONENT(component), FAX_FINISH); + } else if (have_fax_document && FAX_COMPONENT(component)->stop) { result = rayo_component_create_complete_event(RAYO_COMPONENT(component), COMPONENT_COMPLETE_STOP); } else { result = rayo_component_create_complete_event(RAYO_COMPONENT(component), COMPONENT_COMPLETE_ERROR); } complete = iks_find(result, "complete"); - /* add fax document information */ - if (have_fax_document) { + /* RX only: add fax document information */ + if (is_rxfax && have_fax_document) { const char *pages = switch_event_get_header(event, "variable_fax_document_transferred_pages"); if (!zstr(pages) && switch_is_number(pages) && atoi(pages) > 0) { const char *resolution = switch_event_get_header(event, "variable_fax_file_image_resolution"); @@ -256,10 +428,10 @@ static void on_execute_complete_event(switch_event_t *event) iks_insert_attrib(fax, "xmlns", RAYO_FAX_COMPLETE_NS); if (RECEIVEFAX_COMPONENT(component)->http_put_after_receive) { - iks_insert_attrib(fax, "url", url); + iks_insert_attrib(fax, "url", RECEIVEFAX_COMPONENT(component)->filename); } else { /* convert absolute path to file:// URI */ - iks_insert_attrib_printf(fax, "url", "file://%s", url); + iks_insert_attrib_printf(fax, "url", "file://%s", RECEIVEFAX_COMPONENT(component)->filename); } if (!zstr(resolution)) { @@ -286,6 +458,9 @@ static void on_execute_complete_event(switch_event_t *event) insert_fax_metadata(event, "fax_local_station_id", complete); insert_fax_metadata(event, "fax_remote_station_id", complete); + /* flag faxing as done */ + rayo_call_set_faxing(RAYO_CALL(RAYO_COMPONENT(component)->parent), 0); + rayo_component_send_complete_event(RAYO_COMPONENT(component), result); RAYO_UNLOCK(component); @@ -313,14 +488,14 @@ static switch_status_t do_config(switch_memory_pool_t *pool, const char *config_ /* get params */ { - switch_xml_t settings = switch_xml_child(cfg, "receivefax"); + switch_xml_t settings = switch_xml_child(cfg, "fax"); if (settings) { switch_xml_t param; for (param = switch_xml_child(settings, "param"); param; param = param->next) { const char *var = switch_xml_attr_soft(param, "name"); const char *val = switch_xml_attr_soft(param, "value"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "param: %s = %s\n", var, val); - if (!strcasecmp(var, "file-prefix")) { + if (!strcasecmp(var, "receivefax-file-prefix")) { if (!zstr(val)) { globals.file_prefix = switch_core_strdup(pool, val); } @@ -331,7 +506,7 @@ static switch_status_t do_config(switch_memory_pool_t *pool, const char *config_ } } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "receivefax file-prefix = %s\n", globals.file_prefix); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "receivefax-file-prefix = %s\n", globals.file_prefix); switch_xml_free(xml); @@ -339,31 +514,34 @@ static switch_status_t do_config(switch_memory_pool_t *pool, const char *config_ } /** - * Initialize receivefax component + * Initialize fax components * @param module_interface * @param pool memory pool to allocate from * @param config_file to use * @return SWITCH_STATUS_SUCCESS if successful */ -switch_status_t rayo_receivefax_component_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool, const char *config_file) +switch_status_t rayo_fax_components_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool, const char *config_file) { if (do_config(pool, config_file) != SWITCH_STATUS_SUCCESS) { return SWITCH_STATUS_TERM; } - switch_event_bind("rayo_receivefax_component", SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE, NULL, on_execute_complete_event, NULL); + switch_event_bind("rayo_fax_components", SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE, NULL, on_execute_complete_event, NULL); rayo_actor_command_handler_add(RAT_CALL, "", "set:"RAYO_FAX_NS":receivefax", start_receivefax_component); - rayo_actor_command_handler_add(RAT_CALL_COMPONENT, "receivefax", "set:"RAYO_EXT_NS":stop", stop_receivefax_component); + rayo_actor_command_handler_add(RAT_CALL_COMPONENT, "receivefax", "set:"RAYO_EXT_NS":stop", stop_fax_component); + + rayo_actor_command_handler_add(RAT_CALL, "", "set:"RAYO_FAX_NS":sendfax", start_sendfax_component); + rayo_actor_command_handler_add(RAT_CALL_COMPONENT, "sendfax", "set:"RAYO_EXT_NS":stop", stop_fax_component); return SWITCH_STATUS_SUCCESS; } /** - * Shutdown receivefax component + * Shutdown fax components * @return SWITCH_STATUS_SUCCESS if successful */ -switch_status_t rayo_receivefax_component_shutdown(void) +switch_status_t rayo_fax_components_shutdown(void) { switch_event_unbind_callback(on_execute_complete_event); @@ -380,3 +558,4 @@ switch_status_t rayo_receivefax_component_shutdown(void) * For VIM: * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet */ + From ed4d19b5147ce957fbf63522cd701154d1b403c7 Mon Sep 17 00:00:00 2001 From: Chris Rienzo Date: Thu, 7 Nov 2013 21:41:31 -0500 Subject: [PATCH 31/31] mod_rayo: bugfixes --- src/mod/event_handlers/mod_rayo/rayo_fax_components.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/mod/event_handlers/mod_rayo/rayo_fax_components.c b/src/mod/event_handlers/mod_rayo/rayo_fax_components.c index 9cd48e2c2c..420853104a 100644 --- a/src/mod/event_handlers/mod_rayo/rayo_fax_components.c +++ b/src/mod/event_handlers/mod_rayo/rayo_fax_components.c @@ -107,12 +107,12 @@ static iks *start_sendfax_component(struct rayo_actor *call, struct rayo_message } /* is valid URL type? */ - if (!strncasecmp(fax_document, "http://", 7) || strncasecmp(fax_document, "https://", 8)) { + if (!strncasecmp(fax_document, "http://", 7) || !strncasecmp(fax_document, "https://", 8)) { switch_stream_handle_t stream = { 0 }; SWITCH_STANDARD_STREAM(stream); /* need to fetch document from server... */ switch_api_execute("http_get", fax_document, session, &stream); - if (!zstr(stream.data) && !strncasecmp(fax_document, SWITCH_PATH_SEPARATOR, sizeof(SWITCH_PATH_SEPARATOR) - 1)) { + if (!zstr(stream.data) && !strncmp(fax_document, SWITCH_PATH_SEPARATOR, strlen(SWITCH_PATH_SEPARATOR))) { fax_document = switch_core_session_strdup(session, stream.data); } else { switch_safe_free(stream.data); @@ -124,12 +124,12 @@ static iks *start_sendfax_component(struct rayo_actor *call, struct rayo_message if (zstr(fax_document)) { return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "invalid file:// url"); } - } else if (strncasecmp(fax_document, SWITCH_PATH_SEPARATOR, sizeof(SWITCH_PATH_SEPARATOR) - 1)) { + } else if (strncasecmp(fax_document, SWITCH_PATH_SEPARATOR, strlen(SWITCH_PATH_SEPARATOR))) { return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "unsupported url type"); } /* does document exist? */ - if (!switch_file_exists(fax_document, pool)) { + if (switch_file_exists(fax_document, pool) != SWITCH_STATUS_SUCCESS) { return iks_new_error_detailed_printf(iq, STANZA_ERROR_BAD_REQUEST, "file not found: %s", fax_document); } @@ -392,7 +392,7 @@ static void on_execute_complete_event(switch_event_t *event) } /* RX only: transfer HTTP document and delete local copy */ - if (is_rxfax && RECEIVEFAX_COMPONENT(component)->http_put_after_receive && switch_file_exists(RECEIVEFAX_COMPONENT(component)->local_filename, RAYO_POOL(component))) { + if (is_rxfax && RECEIVEFAX_COMPONENT(component)->http_put_after_receive && switch_file_exists(RECEIVEFAX_COMPONENT(component)->local_filename, RAYO_POOL(component)) == SWITCH_STATUS_SUCCESS) { switch_stream_handle_t stream = { 0 }; SWITCH_STANDARD_STREAM(stream); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s PUT fax to %s\n", RAYO_JID(component), RECEIVEFAX_COMPONENT(component)->filename);