diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 79d45c11b4..b35c73c567 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -871,6 +871,7 @@ typedef enum { SWITCH_MESSAGE_INDICATE_JITTER_BUFFER, SWITCH_MESSAGE_INDICATE_RECOVERY_REFRESH, SWITCH_MESSAGE_INDICATE_SIGNAL_DATA, + SWITCH_MESSAGE_INDICATE_INFO, SWITCH_MESSAGE_INVALID } switch_core_session_message_types_t; diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index 1f4984aa19..cffe756ad2 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -3022,6 +3022,44 @@ SWITCH_STANDARD_API(uuid_phone_event_function) return SWITCH_STATUS_SUCCESS; } +#define INFO_SYNTAX "" +SWITCH_STANDARD_API(uuid_send_info_function) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + char *mycmd = NULL, *argv[2] = { 0 }; + int argc = 0; + + if (!zstr(cmd) && (mycmd = strdup(cmd))) { + argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + } + + if (argc < 1) { + stream->write_function(stream, "-USAGE: %s\n", INFO_SYNTAX); + } else { + switch_core_session_message_t msg = { 0 }; + switch_core_session_t *lsession = NULL; + + msg.message_id = SWITCH_MESSAGE_INDICATE_INFO; + msg.string_array_arg[2] = argv[1]; + msg.from = __FILE__; + + if ((lsession = switch_core_session_locate(argv[0]))) { + status = switch_core_session_receive_message(lsession, &msg); + switch_core_session_rwunlock(lsession); + } + } + + if (status == SWITCH_STATUS_SUCCESS) { + stream->write_function(stream, "+OK Success\n"); + } else { + stream->write_function(stream, "-ERR Operation Failed\n"); + } + + switch_safe_free(mycmd); + + return SWITCH_STATUS_SUCCESS; +} + #define DEBUG_AUDIO_SYNTAX " " SWITCH_STANDARD_API(uuid_debug_audio_function) @@ -5344,6 +5382,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) SWITCH_ADD_API(commands_api_interface, "uuid_getvar", "uuid_getvar", uuid_getvar_function, GETVAR_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_hold", "hold", uuid_hold_function, HOLD_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_kill", "Kill Channel", kill_function, KILL_SYNTAX); + SWITCH_ADD_API(commands_api_interface, "uuid_send_info", "Send info to the endpoint", uuid_send_info_function, INFO_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_outgoing_answer", "Answer Outgoing Channel", outgoing_answer_function, OUTGOING_ANSWER_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_limit", "Increase limit resource", uuid_limit_function, LIMIT_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_limit_release", "Release limit resource", uuid_limit_release_function, LIMIT_RELEASE_SYNTAX); @@ -5470,6 +5509,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) switch_console_set_complete("add uuid_flush_dtmf ::console::list_uuid"); switch_console_set_complete("add uuid_getvar ::console::list_uuid"); switch_console_set_complete("add uuid_hold ::console::list_uuid"); + switch_console_set_complete("add uuid_send_info ::console::list_uuid"); switch_console_set_complete("add uuid_jitterbuffer ::console::list_uuid"); switch_console_set_complete("add uuid_kill ::console::list_uuid"); switch_console_set_complete("add uuid_outgoing_answer ::console::list_uuid"); diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 09299d8f2e..ebe51c3a28 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -1154,6 +1154,19 @@ SWITCH_STANDARD_APP(redirect_function) switch_core_session_receive_message(session, &msg); } +SWITCH_STANDARD_APP(send_info_function) +{ + switch_core_session_message_t msg = { 0 }; + + /* Tell the channel to send info */ + msg.from = __FILE__; + msg.string_arg = data; + msg.message_id = SWITCH_MESSAGE_INDICATE_INFO; + msg.string_array_arg[2] = data; + + switch_core_session_receive_message(session, &msg); +} + SWITCH_STANDARD_APP(jitterbuffer_function) { switch_core_session_message_t msg = { 0 }; @@ -4050,6 +4063,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SWITCH_ADD_APP(app_interface, "ivr", "Run an ivr menu", "Run an ivr menu.", ivr_application_function, "", SAF_NONE); SWITCH_ADD_APP(app_interface, "redirect", "Send session redirect", "Send a redirect message to a session.", redirect_function, "", SAF_SUPPORT_NOMEDIA); + SWITCH_ADD_APP(app_interface, "send_info", "Send info", "Send info", send_info_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "jitterbuffer", "Send session jitterbuffer", "Send a jitterbuffer message to a session.", jitterbuffer_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "send_display", "Send session a new display", "Send session a new display.", display_function, "", diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index f416c0fff0..2f9958a335 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -1906,7 +1906,6 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi case SWITCH_MESSAGE_INDICATE_PHONE_EVENT: { const char *event = "talk"; - switch_channel_set_flag(channel, CF_REQ_MEDIA); if (!zstr(msg->string_arg) && strcasecmp(msg->string_arg, event)) { if (!strcasecmp(msg->string_arg, "hold")) { @@ -1924,6 +1923,27 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi } } + case SWITCH_MESSAGE_INDICATE_INFO: + { + char *headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_INFO_HEADER_PREFIX); + char *ct = "freeswitch/data"; + const char *pl = NULL; + + if (!zstr(msg->string_array_arg[0]) && !zstr(msg->string_array_arg[1])) { + ct = switch_core_session_sprintf(session, "%s/%s", msg->string_array_arg[0], msg->string_array_arg[1]); + } + + if (!zstr(msg->string_array_arg[2])) { + pl = msg->string_array_arg[2]; + } + + nua_info(tech_pvt->nh, + SIPTAG_CONTENT_TYPE_STR(ct), + TAG_IF(!zstr(headers), SIPTAG_HEADER_STR(headers)), + TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), + TAG_IF(pl, SIPTAG_PAYLOAD_STR(pl)), + TAG_END()); + } break; case SWITCH_MESSAGE_INDICATE_SIMPLIFY: { diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 4a74ce3735..6b4d938c11 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -95,6 +95,8 @@ typedef struct private_object private_object_t; #define SOFIA_MULTIPART_PREFIX "sip_mp_" #define SOFIA_MULTIPART_PREFIX_T "~sip_mp_" #define SOFIA_SIP_HEADER_PREFIX "sip_h_" +#define SOFIA_SIP_INFO_HEADER_PREFIX "sip_info_h_" +#define SOFIA_SIP_INFO_HEADER_PREFIX_T "~sip_info_h_" #define SOFIA_SIP_RESPONSE_HEADER_PREFIX "sip_rh_" #define SOFIA_SIP_RESPONSE_HEADER_PREFIX_T "~sip_rh_" #define SOFIA_SIP_BYE_HEADER_PREFIX "sip_bye_h_" @@ -1108,7 +1110,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); 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_glue_set_extra_headers(switch_core_session_t *session, sip_t const *sip, const char *prefix); void sofia_info_send_sipfrag(switch_core_session_t *aleg, switch_core_session_t *bleg); void sofia_update_callee_id(switch_core_session_t *session, sofia_profile_t *profile, sip_t const *sip, switch_bool_t send); void sofia_send_callee_id(switch_core_session_t *session, const char *name, const char *number); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 3efd02cd8f..399ee3d19e 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -617,7 +617,7 @@ void sofia_handle_sip_i_bye(switch_core_session_t *session, int status, switch_channel_set_variable(channel, "sip_term_cause", st); extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_BYE_HEADER_PREFIX); - sofia_glue_set_extra_headers(channel, sip, SOFIA_SIP_BYE_HEADER_PREFIX); + sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_BYE_HEADER_PREFIX); if (!(vval = switch_channel_get_variable(channel, "sip_copy_custom_headers")) || switch_true(vval)) { switch_core_session_t *nsession = NULL; @@ -4714,9 +4714,9 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status const char *vval; if (status > 199) { - sofia_glue_set_extra_headers(channel, sip, SOFIA_SIP_RESPONSE_HEADER_PREFIX); + sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_RESPONSE_HEADER_PREFIX); } else { - sofia_glue_set_extra_headers(channel, sip, SOFIA_SIP_PROGRESS_HEADER_PREFIX); + sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_PROGRESS_HEADER_PREFIX); } @@ -6122,7 +6122,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, if (phrase) { switch_channel_set_variable_partner(channel, "sip_hangup_phrase", phrase); } - sofia_glue_set_extra_headers(channel, sip, SOFIA_SIP_BYE_HEADER_PREFIX); + sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_BYE_HEADER_PREFIX); } switch_snprintf(st, sizeof(st), "%d", cause); switch_channel_set_variable(channel, "sip_term_cause", st); @@ -6957,9 +6957,38 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t if (session) { /* Get the channel */ switch_channel_t *channel = switch_core_session_get_channel(session); + const char *vval; /* Barf if we didn't get our private */ assert(switch_core_session_get_private(session)); + + sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_INFO_HEADER_PREFIX); + + if (!(vval = switch_channel_get_variable(channel, "sip_copy_custom_headers")) || switch_true(vval)) { + switch_core_session_t *nsession = NULL; + + switch_core_session_get_partner(session, &nsession); + + if (nsession) { + switch_core_session_message_t *msg; + + switch_ivr_transfer_variable(session, nsession, SOFIA_SIP_INFO_HEADER_PREFIX_T); + msg = switch_core_session_alloc(nsession, sizeof(*msg)); + MESSAGE_STAMP_FFL(msg); + msg->message_id = SWITCH_MESSAGE_INDICATE_INFO; + + if (sip && sip->sip_content_type && sip->sip_content_type->c_type && sip->sip_content_type->c_subtype && + sip->sip_payload && sip->sip_payload->pl_data) { + msg->string_array_arg[0] = switch_core_session_strdup(nsession, sip->sip_content_type->c_type); + msg->string_array_arg[1] = switch_core_session_strdup(nsession, sip->sip_content_type->c_subtype); + msg->string_array_arg[0] = switch_core_session_strdup(nsession, sip->sip_payload->pl_data); + } + msg->from = __FILE__; + switch_core_session_queue_message(nsession, msg); + + switch_core_session_rwunlock(nsession); + } + } if (sip && sip->sip_content_type && sip->sip_content_type->c_subtype && sip->sip_content_type->c_type && !strncasecmp(sip->sip_content_type->c_type, "message", 7) && diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 41048a1d84..e4b8b567ba 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -1908,11 +1908,14 @@ char *sofia_glue_get_extra_headers(switch_channel_t *channel, const char *prefix return extra_headers; } -void sofia_glue_set_extra_headers(switch_channel_t *channel, sip_t const *sip, const char *prefix) +void sofia_glue_set_extra_headers(switch_core_session_t *session, sip_t const *sip, const char *prefix) { sip_unknown_t *un; char name[512] = ""; + switch_channel_t *channel = switch_core_session_get_channel(session); + char *pstr; + if (!sip || !channel) { return; } @@ -1925,6 +1928,13 @@ void sofia_glue_set_extra_headers(switch_channel_t *channel, sip_t const *sip, c } } } + + pstr = switch_core_session_sprintf(session, "execute_on_%sprefix", prefix); + switch_channel_execute_on(channel, pstr); + switch_channel_api_on(channel, pstr); + + switch_channel_execute_on(channel, "execute_on_sip_extra_headers"); + switch_channel_api_on(channel, "api_on_sip_extra_headers"); }