From 2eae19e63f04459187179d1529a5e367ff921b29 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 4 Aug 2011 09:38:45 -0500 Subject: [PATCH 01/15] FS-3484 --resolve --- src/switch_core_session.c | 1 - src/switch_ivr_originate.c | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 23aa8bed52..fc03ab6f10 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -530,7 +530,6 @@ SWITCH_DECLARE(switch_call_cause_t) switch_core_session_outgoing_channel(switch_ switch_channel_set_variable(peer_channel, SWITCH_ORIGINATOR_VARIABLE, switch_core_session_get_uuid(session)); switch_channel_set_variable(peer_channel, SWITCH_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(session)); - switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(*new_session)); if ((val = switch_channel_get_variable(channel, SWITCH_PROCESS_CDR_VARIABLE))) { switch_channel_set_variable(peer_channel, SWITCH_PROCESS_CDR_VARIABLE, val); diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index 6df4f40782..48b75090d7 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -3413,6 +3413,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess switch_channel_set_originatee_caller_profile(caller_channel, cloned_profile); } } + + switch_channel_set_variable(caller_channel, SWITCH_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(*bleg)); } From dee0f540269e07d00a4b6589fce94cf38eea4643 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 4 Aug 2011 09:50:23 -0500 Subject: [PATCH 02/15] FS-3483 --resolve --- src/switch_ivr_originate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index 48b75090d7..938be90db2 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -2346,7 +2346,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess } new_profile->callee_id_name = switch_core_strdup(new_profile->pool, "Outbound Call"); - new_profile->callee_id_number = switch_core_strdup(new_profile->pool, new_profile->destination_number); + new_profile->callee_id_number = switch_sanitize_number(switch_core_strdup(new_profile->pool, new_profile->destination_number)); originate_status[i].caller_profile = NULL; originate_status[i].peer_channel = NULL; From b952b2b2d9111ae963067f20a667c472c4d77aea Mon Sep 17 00:00:00 2001 From: Daniel Swarbrick Date: Thu, 4 Aug 2011 19:53:18 +0200 Subject: [PATCH 03/15] remove pointless update_mwi() in vm_list api command --- src/mod/applications/mod_voicemail/mod_voicemail.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index d896527d7d..1ce5ecccd1 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -4390,7 +4390,6 @@ SWITCH_STANDARD_API(voicemail_list_api_function) vm_execute_sql_callback(profile, profile->mutex, sql, api_list_callback, stream); switch_safe_free(sql); - update_mwi(profile, id, domain, "inbox"); if (!strcasecmp(format, "xml")) { stream->write_function(stream, "\n"); From 77c5000dad6154231fa2b9eb59d77f3187670800 Mon Sep 17 00:00:00 2001 From: Daniel Swarbrick Date: Thu, 4 Aug 2011 20:17:15 +0200 Subject: [PATCH 04/15] add message_len to output of vm_list api command --- src/mod/applications/mod_voicemail/mod_voicemail.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index 1ce5ecccd1..2eb89ebc43 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -4318,7 +4318,7 @@ static int api_list_callback(void *pArg, int argc, char **argv, char **columnNam { switch_stream_handle_t *stream = (switch_stream_handle_t *) pArg; - if (!strcasecmp(argv[9], "xml")) { + if (!strcasecmp(argv[10], "xml")) { stream->write_function(stream, " \n"); stream->write_function(stream, " %s\n", argv[0]); stream->write_function(stream, " %s\n", argv[1]); @@ -4329,9 +4329,10 @@ static int api_list_callback(void *pArg, int argc, char **argv, char **columnNam stream->write_function(stream, " %s\n", argv[6]); stream->write_function(stream, " %s\n", argv[7]); stream->write_function(stream, " %s\n", argv[8]); + stream->write_function(stream, " %s\n", argv[9]); stream->write_function(stream, " \n"); } else { - stream->write_function(stream, "%s:%s:%s:%s:%s:%s:%s:%s:%s\n", argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]); + stream->write_function(stream, "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n", argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]); } return 0; @@ -4375,11 +4376,11 @@ SWITCH_STANDARD_API(voicemail_list_api_function) if (id && domain && profile_name && (profile = get_profile(profile_name))) { if (uuid) { - sql = switch_mprintf("select created_epoch, read_epoch, username, domain, in_folder, file_path, uuid, cid_name, cid_number, " + sql = switch_mprintf("select created_epoch, read_epoch, username, domain, in_folder, file_path, uuid, cid_name, cid_number, message_len, " "'%q' from voicemail_msgs where username='%q' and domain='%q' and uuid='%q'", format, id, domain, uuid); } else { - sql = switch_mprintf("select created_epoch, read_epoch, username, domain, in_folder, file_path, uuid, cid_name, cid_number, " + sql = switch_mprintf("select created_epoch, read_epoch, username, domain, in_folder, file_path, uuid, cid_name, cid_number, message_len, " "'%q' from voicemail_msgs where username='%q' and domain='%q'", format, id, domain); } From 3e2c662a882aae0d447f489df7b4a6d9dbe4f71e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 4 Aug 2011 17:20:02 -0500 Subject: [PATCH 05/15] clean up originator/ee profile so the right one is prevelant in events --- src/switch_channel.c | 32 +++++++++++++++++--------------- src/switch_ivr_bridge.c | 4 ++++ 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/switch_channel.c b/src/switch_channel.c index bd2f84b779..72aa68ea7f 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -110,6 +110,12 @@ typedef enum { OCF_HANGUP = (1 << 0) } opaque_channel_flag_t; +typedef enum { + LP_NEITHER, + LP_ORIGINATOR, + LP_ORIGINATEE +} switch_originator_type_t; + struct switch_channel { char *name; switch_call_direction_t direction; @@ -139,6 +145,7 @@ struct switch_channel { int event_count; int profile_index; opaque_channel_flag_t opaque_flags; + switch_originator_type_t last_profile_type; }; @@ -2156,23 +2163,16 @@ SWITCH_DECLARE(void) switch_channel_event_set_basic_data(switch_channel_t *chann switch_caller_profile_event_set_data(caller_profile, "Caller", event); } - if (originator_caller_profile && originatee_caller_profile) { - /* Index Originator's Profile */ - switch_caller_profile_event_set_data(originator_caller_profile, "Originator", event); - - /* Index Originatee's Profile */ - switch_caller_profile_event_set_data(originatee_caller_profile, "Originatee", event); - } else { - /* Index Originator's Profile */ - if (originator_caller_profile) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Other-Type", "originator"); - switch_caller_profile_event_set_data(originator_caller_profile, "Other-Leg", event); - } else if (originatee_caller_profile) { /* Index Originatee's Profile */ - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Other-Type", "originatee"); - switch_caller_profile_event_set_data(originatee_caller_profile, "Other-Leg", event); - } + /* Index Originator/ee's Profile */ + if (originator_caller_profile && channel->last_profile_type == LP_ORIGINATOR) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Other-Type", "originator"); + switch_caller_profile_event_set_data(originator_caller_profile, "Other-Leg", event); + } else if (originatee_caller_profile && channel->last_profile_type == LP_ORIGINATEE) { /* Index Originatee's Profile */ + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Other-Type", "originatee"); + switch_caller_profile_event_set_data(originatee_caller_profile, "Other-Leg", event); } + switch_mutex_unlock(channel->profile_mutex); } @@ -2342,6 +2342,7 @@ SWITCH_DECLARE(void) switch_channel_set_originator_caller_profile(switch_channel if (channel->caller_profile) { caller_profile->next = channel->caller_profile->originator_caller_profile; channel->caller_profile->originator_caller_profile = caller_profile; + channel->last_profile_type = LP_ORIGINATOR; } switch_assert(channel->caller_profile->originator_caller_profile->next != channel->caller_profile->originator_caller_profile); switch_mutex_unlock(channel->profile_mutex); @@ -2402,6 +2403,7 @@ SWITCH_DECLARE(void) switch_channel_set_originatee_caller_profile(switch_channel if (channel->caller_profile) { caller_profile->next = channel->caller_profile->originatee_caller_profile; channel->caller_profile->originatee_caller_profile = caller_profile; + channel->last_profile_type = LP_ORIGINATEE; } switch_assert(channel->caller_profile->originatee_caller_profile->next != channel->caller_profile->originatee_caller_profile); switch_mutex_unlock(channel->profile_mutex); diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index 9dbd4aecab..b1726e9119 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -997,6 +997,8 @@ static switch_status_t signal_bridge_on_hangup(switch_core_session_t *session) if (switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) { switch_channel_clear_flag_recursive(channel, CF_BRIDGE_ORIGINATOR); if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_UNBRIDGE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridge-A-Unique-ID", switch_core_session_get_uuid(session)); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridge-B-Unique-ID", uuid); switch_channel_event_set_data(channel, event); switch_event_fire(&event); } @@ -1310,6 +1312,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses switch_channel_set_variable(peer_channel, "call_uuid", switch_core_session_get_uuid(peer_session)); if (br && switch_event_create(&event, SWITCH_EVENT_CHANNEL_UNBRIDGE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridge-A-Unique-ID", switch_core_session_get_uuid(session)); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridge-B-Unique-ID", switch_core_session_get_uuid(peer_session)); switch_channel_event_set_data(caller_channel, event); switch_event_fire(&event); } From 308f44af2e59623f9b9fd1bb6329953781307a42 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 4 Aug 2011 16:12:17 -0500 Subject: [PATCH 06/15] make valet parking reserve a space for 10 seconds to allow time for an attended transfer switcharoo --- .../mod_valet_parking/mod_valet_parking.c | 102 +++++++++++++++--- 1 file changed, 86 insertions(+), 16 deletions(-) diff --git a/src/mod/applications/mod_valet_parking/mod_valet_parking.c b/src/mod/applications/mod_valet_parking/mod_valet_parking.c index 14412bc318..3e8337d857 100644 --- a/src/mod/applications/mod_valet_parking/mod_valet_parking.c +++ b/src/mod/applications/mod_valet_parking/mod_valet_parking.c @@ -38,6 +38,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_valet_parking_load); */ SWITCH_MODULE_DEFINITION(mod_valet_parking, mod_valet_parking_load, NULL, NULL); +typedef struct { + char uuid[SWITCH_UUID_FORMATTED_LENGTH + 1]; + time_t timeout; +} valet_token_t; + typedef struct { switch_hash_t *hash; switch_mutex_t *mutex; @@ -80,22 +85,65 @@ static switch_status_t valet_on_dtmf(switch_core_session_t *session, void *input return SWITCH_STATUS_SUCCESS; } +static void check_timeouts(void) +{ + switch_hash_index_t *hi; + const void *var; + void *val; + time_t now; + valet_lot_t *lot; + now = switch_epoch_time_now(NULL); + + switch_mutex_lock(globals.mutex); + + + for (hi = switch_hash_first(NULL, globals.hash); hi; hi = switch_hash_next(hi)) { + switch_hash_index_t *i_hi; + const void *i_var; + void *i_val; + char *i_ext; + valet_token_t *token; + + switch_hash_this(hi, &var, NULL, &val); + lot = (valet_lot_t *) val; + + switch_mutex_lock(lot->mutex); + + top: + + for (i_hi = switch_hash_first(NULL, lot->hash); i_hi; i_hi = switch_hash_next(i_hi)) { + switch_hash_this(i_hi, &i_var, NULL, &i_val); + i_ext = (char *) i_var; + token = (valet_token_t *) i_val; + if (token->timeout > 0 && token->timeout < now) { + switch_core_hash_delete(lot->hash, i_ext); + switch_safe_free(token); + goto top; + } + } + + switch_mutex_unlock(lot->mutex); + } + switch_mutex_unlock(globals.mutex); +} static int next_id(valet_lot_t *lot, int min, int max, int in) { - int i, r = 0, m; + int i, r = 0; char buf[128] = ""; + valet_token_t *token; - if (!min) + if (!min) { min = 1; + } switch_mutex_lock(globals.mutex); for (i = min; (i < max || max == 0); i++) { switch_snprintf(buf, sizeof(buf), "%d", i); - m = !!switch_core_hash_find(lot->hash, buf); - - if ((in && !m) || (!in && m)) { + token = (valet_token_t *) switch_core_hash_find(lot->hash, buf); + + if ((in && !token) || (!in && token && !token->timeout)) { r = i; break; } @@ -116,12 +164,14 @@ SWITCH_STANDARD_APP(valet_parking_function) char dtmf_buf[128] = ""; int is_auto = 0, play_announce = 1; const char *var; - + valet_token_t *token; if ((var = switch_channel_get_variable(channel, "valet_announce_slot"))) { play_announce = switch_true(var); } + check_timeouts(); + if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data)) && (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) >= 2) { char *lot_name = argv[0]; @@ -220,9 +270,23 @@ SWITCH_STANDARD_APP(valet_parking_function) } switch_mutex_lock(lot->mutex); - if ((uuid = switch_core_hash_find(lot->hash, ext))) { + if ((token = (valet_token_t *) switch_core_hash_find(lot->hash, ext))) { switch_core_session_t *b_session; - if ((b_session = switch_core_session_locate(uuid))) { + + if (token->timeout) { + const char *var = switch_channel_get_variable(channel, "valet_ticket"); + + if (!strcmp(var, token->uuid)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Valet ticket %s accepted.\n", var); + switch_channel_set_variable(channel, "valet_ticket", NULL); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid token %s\n", token->uuid); + switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + return; + } + } + + if (token && (b_session = switch_core_session_locate(token->uuid))) { if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, VALET_EVENT) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Valet-Lot-Name", lot_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Valet-Extension", ext); @@ -231,14 +295,17 @@ SWITCH_STANDARD_APP(valet_parking_function) switch_channel_event_set_data(switch_core_session_get_channel(b_session), event); switch_event_fire(&event); switch_core_session_rwunlock(b_session); - - switch_ivr_uuid_bridge(switch_core_session_get_uuid(session), uuid); + token->timeout = 0; + switch_ivr_uuid_bridge(switch_core_session_get_uuid(session), token->uuid); switch_mutex_unlock(lot->mutex); return; } } } + + token = NULL; + if (!(tmp = switch_channel_get_variable(channel, "valet_hold_music"))) { tmp = switch_channel_get_hold_music(channel); } @@ -249,7 +316,13 @@ SWITCH_STANDARD_APP(valet_parking_function) music = "silence_stream://-1"; } - dest = switch_core_session_sprintf(session, "set:valet_hold_music=%s,sleep:1000,valet_park:%s %s", music, lot_name, ext); + switch_zmalloc(token, sizeof(*token)); + token->timeout = switch_epoch_time_now(NULL) + 10; + switch_set_string(token->uuid, switch_core_session_get_uuid(session)); + switch_core_hash_insert(lot->hash, ext, token); + + dest = switch_core_session_sprintf(session, "set:valet_ticket=%s,set:valet_hold_music=%s,sleep:1000,valet_park:%s %s", + token->uuid, music, lot_name, ext); switch_channel_set_variable(channel, "inline_destination", dest); if (is_auto) { @@ -263,6 +336,7 @@ SWITCH_STANDARD_APP(valet_parking_function) if (play_announce) { switch_ivr_phrase_macro(session, "valet_announce_ext", tmp, NULL, NULL); } + switch_ivr_session_transfer(b_session, dest, "inline", NULL); switch_mutex_unlock(lot->mutex); switch_core_session_rwunlock(b_session); @@ -286,7 +360,7 @@ SWITCH_STANDARD_APP(valet_parking_function) } - switch_core_hash_insert(lot->hash, ext, switch_core_session_get_uuid(session)); + args.input_callback = valet_on_dtmf; args.buf = dbuf; @@ -302,10 +376,6 @@ SWITCH_STANDARD_APP(valet_parking_function) } } - switch_mutex_lock(lot->mutex); - switch_core_hash_delete(lot->hash, ext); - switch_mutex_unlock(lot->mutex); - if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, VALET_EVENT) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Valet-Lot-Name", lot_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Valet-Extension", ext); From 714195b8f26ed325ac0100dfd02befb6cdbdcbb8 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 4 Aug 2011 16:34:01 -0500 Subject: [PATCH 07/15] FS-3487 gonna guess, try this... --- src/mod/endpoints/mod_sofia/sofia.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 316c23d369..7a5fe8fc74 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -952,9 +952,8 @@ static void our_sofia_event_callback(nua_event_t event, } } case nua_r_ack: - if (channel) { + if (channel) switch_channel_set_flag(channel, CF_MEDIA_ACK); - } break; case nua_r_shutdown: if (status >= 200) { @@ -4969,12 +4968,6 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status sofia_clear_flag(tech_pvt, TFLAG_RECOVERING); } - if ((status == 180 || status == 183) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { - const char *val; - if ((val = switch_channel_get_variable(channel, "sip_auto_answer")) && switch_true(val)) { - nua_notify(nh, NUTAG_NEWSUB(1), NUTAG_SUBSTATE(nua_substate_active), SIPTAG_EVENT_STR("talk"), TAG_END()); - } - } } end: @@ -5165,6 +5158,14 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, status = 183; } + if (channel && (status == 180 || status == 183) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { + const char *val; + if ((val = switch_channel_get_variable(channel, "sip_auto_answer")) && switch_true(val)) { + nua_notify(nh, NUTAG_NEWSUB(1), NUTAG_SUBSTATE(nua_substate_active), SIPTAG_EVENT_STR("talk"), TAG_END()); + } + } + + state_process: From ef1accf70738d12749688a61b54064a0422c2982 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 4 Aug 2011 20:26:23 -0500 Subject: [PATCH 08/15] FS-3487 --resolve --- src/mod/endpoints/mod_sofia/sofia.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 7a5fe8fc74..7932eeed8b 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -85,7 +85,7 @@ void sofia_handle_sip_r_notify(switch_core_session_t *session, int status, sofia_dispatch_event_t *de, tagi_t tags[]) { - if (status >= 300 && sip && sip->sip_call_id) { + if (status >= 300 && sip && sip->sip_call_id && (!sofia_private || !sofia_private->is_call)) { char *sql; sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", sip->sip_call_id->i_id); switch_assert(sql != NULL); @@ -5161,7 +5161,8 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, if (channel && (status == 180 || status == 183) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { const char *val; if ((val = switch_channel_get_variable(channel, "sip_auto_answer")) && switch_true(val)) { - nua_notify(nh, NUTAG_NEWSUB(1), NUTAG_SUBSTATE(nua_substate_active), SIPTAG_EVENT_STR("talk"), TAG_END()); + nua_notify(nh, NUTAG_NEWSUB(1), NUTAG_WITH_THIS_MSG(de->data->e_msg), + NUTAG_SUBSTATE(nua_substate_terminated), SIPTAG_EVENT_STR("talk"), TAG_END()); } } From b3208f5cdc1c74a5975f33e7c81d91476379c8c6 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 4 Aug 2011 20:27:54 -0500 Subject: [PATCH 09/15] FS-3444 --resolve with previous commit this can come back --- src/mod/endpoints/mod_sofia/sofia.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 7932eeed8b..318ca29b7b 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -5842,6 +5842,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, switch_snprintf(st, sizeof(st), "%d", cause); switch_channel_set_variable(channel, "sip_term_cause", st); switch_channel_hangup(channel, cause); + ss_state = nua_callstate_terminated; } From 885203a461fe831247de6bd8bc5dfee04c9d5b3d Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 4 Aug 2011 22:32:06 -0500 Subject: [PATCH 10/15] add event header --- src/switch_channel.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/switch_channel.c b/src/switch_channel.c index 72aa68ea7f..7dd43672a9 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -1847,6 +1847,10 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_running_state( switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Presence-Call-Direction", channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-HIT-Dialplan", + switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND || + switch_channel_test_flag(channel, CF_DIALPLAN) ? "true" : "false"); + if (switch_channel_down(channel)) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "hangup"); } else if (switch_channel_test_flag(channel, CF_ANSWERED)) { @@ -2113,6 +2117,11 @@ SWITCH_DECLARE(void) switch_channel_event_set_basic_data(switch_channel_t *chann switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Presence-Call-Direction", channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-HIT-Dialplan", + switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND || + switch_channel_test_flag(channel, CF_DIALPLAN) ? "true" : "false"); + + if ((v = switch_channel_get_variable(channel, "presence_id"))) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Presence-ID", v); } From 88a681d47c5b2d46c2f11bb3ef276d1d70916e6e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 4 Aug 2011 23:21:38 -0500 Subject: [PATCH 11/15] fix typo in sql stmt --- src/switch_core_sqldb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 897cbe9ebd..a55d3ee905 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -1364,8 +1364,8 @@ static void core_event_handler(switch_event_t *event) switch_event_get_header_nil(event, "unique-id")); free(extra_cols); } else { - new_sql() = switch_mprintf("update channels set state='%s',cid_name='%q',cid_num='%q',callee_name='%q'," - "sent_callee_name='%q',sent_callee_num='%q', callee_num='%q'," + new_sql() = switch_mprintf("update channels set state='%s',cid_name='%q',cid_num='%q',callee_name='%q',callee_num='%q'," + "sent_callee_name='%q',sent_callee_num='%q'," "ip_addr='%s',dest='%q',dialplan='%q',context='%q',presence_id='%q',presence_data='%q' " "where uuid='%s'", switch_event_get_header_nil(event, "channel-state"), @@ -1511,6 +1511,7 @@ static void core_event_handler(switch_event_t *event) if (sql_idx) { int i = 0; + for (i = 0; i < sql_idx; i++) { if (switch_stristr("update channels", sql[i]) || switch_stristr("delete from channels", sql[i])) { From 0f459d4b4545398f0def0bd70a1cf0c37c0705ac Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 5 Aug 2011 09:31:21 -0500 Subject: [PATCH 12/15] check for answer flag in bridge to do display update properly --- src/switch_core.c | 2 +- src/switch_ivr_bridge.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/switch_core.c b/src/switch_core.c index e7cd60d58f..37784193b0 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1449,7 +1449,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc if (flags & SCF_MINIMAL) return SWITCH_STATUS_SUCCESS; runtime.tipping_point = 0; - runtime.timer_affinity = -1; + runtime.timer_affinity = 0; runtime.microseconds_per_tick = 20000; switch_load_core_config("switch.conf"); diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index b1726e9119..fb8b89096d 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -457,6 +457,8 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) } } + if (originator && !ans_b) ans_b = switch_channel_test_flag(chan_b, CF_ANSWERED); + if (originator && !sent_update && ans_a && ans_b && switch_channel_media_ack(chan_a) && switch_channel_media_ack(chan_b)) { switch_ivr_bridge_display(session_a, session_b); sent_update = 1; From 54feb3e245f0c8fa00afeef42507f338178c48ee Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 5 Aug 2011 09:32:23 -0500 Subject: [PATCH 13/15] revert, didn't mean to commit that one --- src/switch_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_core.c b/src/switch_core.c index 37784193b0..e7cd60d58f 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1449,7 +1449,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc if (flags & SCF_MINIMAL) return SWITCH_STATUS_SUCCESS; runtime.tipping_point = 0; - runtime.timer_affinity = 0; + runtime.timer_affinity = -1; runtime.microseconds_per_tick = 20000; switch_load_core_config("switch.conf"); From 53b0ecce6009db3247fcfa3369e11887d2fe64b7 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 5 Aug 2011 11:09:45 -0500 Subject: [PATCH 14/15] use the call_id of the original register in the unsolicited notify for MWI --- src/mod/endpoints/mod_sofia/mod_sofia.h | 2 +- src/mod/endpoints/mod_sofia/sofia_glue.c | 3 ++- src/mod/endpoints/mod_sofia/sofia_presence.c | 7 ++++--- src/mod/endpoints/mod_sofia/sofia_reg.c | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 07c917cbca..a7bd1e6843 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -1096,7 +1096,7 @@ void sofia_glue_get_addr(msg_t *msg, char *buf, size_t buflen, int *port); sofia_destination_t *sofia_glue_get_destination(char *data); void sofia_glue_free_destination(sofia_destination_t *dst); switch_status_t sofia_glue_send_notify(sofia_profile_t *profile, const char *user, const char *host, const char *event, const char *contenttype, - const char *body, const char *o_contact, const char *network_ip); + const char *body, const char *o_contact, const char *network_ip, const char *call_id); char *sofia_glue_get_extra_headers(switch_channel_t *channel, const char *prefix); void sofia_glue_set_extra_headers(switch_channel_t *channel, sip_t const *sip, const char *prefix); void sofia_info_send_sipfrag(switch_core_session_t *aleg, switch_core_session_t *bleg); diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 54c946ad58..006f002334 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -6319,7 +6319,7 @@ void sofia_glue_free_destination(sofia_destination_t *dst) } switch_status_t sofia_glue_send_notify(sofia_profile_t *profile, const char *user, const char *host, const char *event, const char *contenttype, - const char *body, const char *o_contact, const char *network_ip) + const char *body, const char *o_contact, const char *network_ip, const char *call_id) { char *id = NULL; nua_handle_t *nh; @@ -6376,6 +6376,7 @@ switch_status_t sofia_glue_send_notify(sofia_profile_t *profile, const char *use TAG_IF(dst->route_uri, NUTAG_PROXY(route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), TAG_IF(user_via, SIPTAG_VIA_STR(user_via)), TAG_IF(event, SIPTAG_EVENT_STR(event)), + TAG_IF(call_id, SIPTAG_CALL_ID_STR(call_id)), TAG_IF(contenttype, SIPTAG_CONTENT_TYPE_STR(contenttype)), TAG_IF(body, SIPTAG_PAYLOAD_STR(body)), TAG_END()); switch_safe_free(contact); diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index a85138b8f6..f7b7a0aa84 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -484,10 +484,10 @@ static void actual_sofia_presence_mwi_event_handler(switch_event_t *event) } if (for_everyone) { - sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,network_ip,'%q' " + sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,network_ip,'%q',call_id " "from sip_registrations where mwi_user='%q' and mwi_host='%q'", stream.data, user, host); } else if (call_id) { - sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,network_ip,'%q' " + sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,network_ip,'%q',call_id " "from sip_registrations where mwi_user='%q' and mwi_host='%q' and call_id='%q'", stream.data, user, host, call_id); } @@ -1860,6 +1860,7 @@ static int sofia_presence_mwi_callback2(void *pArg, int argc, char **argv, char const char *body = argv[5]; const char *o_contact = argv[2]; const char *network_ip = argv[4]; + const char *call_id = argv[6]; char *profile_name = argv[3]; struct mwi_helper *h = (struct mwi_helper *) pArg; @@ -1871,7 +1872,7 @@ static int sofia_presence_mwi_callback2(void *pArg, int argc, char **argv, char } } - sofia_glue_send_notify(profile, user, host, event, contenttype, body, o_contact, network_ip); + sofia_glue_send_notify(profile, user, host, event, contenttype, body, o_contact, network_ip, call_id); if (ext_profile) { sofia_glue_release_profile(ext_profile); diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 4b5422fab6..1d014aff80 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -519,7 +519,7 @@ void sofia_reg_send_reboot(sofia_profile_t *profile, const char *user, const cha event = "reboot"; } - sofia_glue_send_notify(profile, user, host, event, contenttype, body, contact, network_ip); + sofia_glue_send_notify(profile, user, host, event, contenttype, body, contact, network_ip, NULL); } int sofia_sla_dialog_del_callback(void *pArg, int argc, char **argv, char **columnNames) From 2ecf2d6e62ac37fea8facd0a824e3ddf59910916 Mon Sep 17 00:00:00 2001 From: Marc Olivier Chouinard Date: Fri, 5 Aug 2011 22:50:58 -0400 Subject: [PATCH 15/15] freetdm/libpri: Add support to change status of an individual channel or multiple channel. This allow to put bchannel out of service on an active T1 without affecting active call. Allow graceful out of service of T1 trunk. NOTE: There is bugs in libpri, even latest 1.4.12 as of this writing if you use NI2. So rightnow it only work in DMS100/ATT mode. Email me to get the NI2 patch (really stupid error). NOTE2: The way libpri is build doesn't allow to do advance feature with the SERVICE feature, so if you put an channel out of service, and the far end send an restart, it will be bring back in service. Lot of changes in libpri is required to allow this. I need to figure out what would be the best steps to take since I don't have commit access to libpri release. NOTE3: You need to enable this feature by setting service_message_support to true on the span --- .../src/ftmod/ftmod_libpri/ftmod_libpri.c | 108 ++++++++++++++++++ .../src/ftmod/ftmod_libpri/ftmod_libpri.h | 6 + 2 files changed, 114 insertions(+) diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index 7a8e74fd7c..a379aeda9c 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -204,6 +204,32 @@ static int parse_debug(const char *in, uint32_t *flags) return res; } +/** + * \brief Parses a change status string to flags + * \param in change status string to parse for + * \return Flags + */ +static int parse_change_status(const char *in) +{ + int flags = 0; + if (!in) { + return 0; + } + + if (strstr(in, "in_service") || strstr(in, "in")) { + flags = SERVICE_CHANGE_STATUS_INSERVICE; + } + if (strstr(in, "maintenance") || strstr(in, "maint")) { + flags = SERVICE_CHANGE_STATUS_MAINTENANCE; + } + if (strstr(in, "out_of_service") || strstr(in, "out")) { + flags = SERVICE_CHANGE_STATUS_OUTOFSERVICE; + } + + + return flags; +} + static int print_debug(uint32_t flags, char *tmp, const int size) { int offset = 0; @@ -240,6 +266,9 @@ static ftdm_io_interface_t ftdm_libpri_interface; static const char *ftdm_libpri_usage = "Usage:\n" "libpri kill \n" + "libpri reset \n" + "libpri restart \n" + "libpri maintenance \n" "libpri debug [all|none|flag,...flagN]\n" "\n" "Possible debug flags:\n" @@ -339,8 +368,78 @@ static FIO_API_FUNCTION(ftdm_libpri_api) goto done; } } + if (!strcasecmp(argv[0], "reset")) { + ftdm_span_t *span = NULL; + if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) { + ftdm_libpri_data_t *isdn_data = span->signal_data; + if (span->start != ftdm_libpri_start) { + stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); + goto done; + } + + pri_restart(isdn_data->spri.pri); + stream->write_function(stream, "%s: +OK reset.\n", __FILE__); + goto done; + } else { + stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); + goto done; + } + } + if (!strcasecmp(argv[0], "restart") && argc == 3) { + ftdm_span_t *span = NULL; + if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) { + ftdm_libpri_data_t *isdn_data = span->signal_data; + if (span->start != ftdm_libpri_start) { + stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); + goto done; + } + if (!strcasecmp(argv[2], "all")) { + int j; + for(j = 1; j <= span->chan_count; j++) { + pri_reset(isdn_data->spri.pri, j); + ftdm_sleep(50); + } + } else { + pri_reset(isdn_data->spri.pri, atoi(argv[2])); + } + stream->write_function(stream, "%s: +OK restart set.\n", __FILE__); + goto done; + } else { + stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); + goto done; + } + } + if (!strcasecmp(argv[0], "maintenance") && argc > 3) { + ftdm_span_t *span = NULL; + if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) { + ftdm_libpri_data_t *isdn_data = span->signal_data; + if (span->start != ftdm_libpri_start) { + stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); + goto done; + } + if (!isdn_data->service_message_support) { + stream->write_function(stream, "%s: -ERR service message support is disabled\n", __FILE__); + goto done; + } + if (!strcasecmp(argv[2], "all")) { + int j; + for(j = 1; j <= span->chan_count; j++) { + pri_maintenance_service(isdn_data->spri.pri, atoi(argv[1]), j, parse_change_status(argv[3])); + ftdm_sleep(50); + } + } else { + pri_maintenance_service(isdn_data->spri.pri, atoi(argv[1]), atoi(argv[2]), parse_change_status(argv[3])); + } + stream->write_function(stream, "%s: +OK change status set.\n", __FILE__); + goto done; + } else { + stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); + goto done; + } + } } + stream->write_function(stream, "%s: -ERR invalid command.\n", __FILE__); done: @@ -1780,6 +1879,10 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj) pri_facility_enable(isdn_data->spri.pri); } #endif + /* Support the different switch of service status */ + if (isdn_data->service_message_support) { + pri_set_service_message_support(isdn_data->spri.pri, 1 /* True */); + } if (res == 0) { LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_ANY, on_anything); @@ -2159,6 +2262,11 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span) isdn_data->debug_mask = 0; } } + else if (!strcasecmp(var, "service_message_support")) { + if (ftdm_true(val)) { + isdn_data->service_message_support = 1; + } + } else { ftdm_log(FTDM_LOG_ERROR, "Unknown parameter '%s', aborting configuration\n", var); snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var); diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h index 4ec15c7b69..27b1763fec 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h @@ -31,6 +31,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +typedef enum { + SERVICE_CHANGE_STATUS_INSERVICE = 0, + SERVICE_CHANGE_STATUS_MAINTENANCE = 1, + SERVICE_CHANGE_STATUS_OUTOFSERVICE = 2 +} service_change_status_t; #ifndef FTMOD_LIBPRI_H #define FTMOD_LIBPRI_H @@ -69,6 +74,7 @@ struct ftdm_libpri_data { int overlap; /*!< Overlap dial flags */ unsigned int layer1; unsigned int ton; + unsigned int service_message_support; lpwrap_pri_t spri; };