From 32b5f64b10c6a22d3a30b27dcd2a654d7fff3b29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Poulin?= Date: Mon, 15 Feb 2021 14:21:40 -0500 Subject: [PATCH] [mod_sofia] add new uuid_refer_to_uri command and refer_to_uri to the dialplan --- src/include/switch_types.h | 1 + .../applications/mod_commands/mod_commands.c | 47 ++++++++++++ .../applications/mod_dptools/mod_dptools.c | 26 +++++++ src/mod/endpoints/mod_sofia/mod_sofia.c | 71 +++++++++++++++++++ 4 files changed, 145 insertions(+) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 133422764b..444226ddf6 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1132,6 +1132,7 @@ typedef enum { SWITCH_MESSAGE_INDICATE_BROADCAST, SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT, SWITCH_MESSAGE_INDICATE_DEFLECT, + SWITCH_MESSAGE_INDICATE_REFER_TO_URI_3PCC, SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ, SWITCH_MESSAGE_INDICATE_DISPLAY, SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY, diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index 37eda79929..c04abfa56d 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -3371,6 +3371,51 @@ SWITCH_STANDARD_API(uuid_deflect) return SWITCH_STATUS_SUCCESS; } +#define UUID_REFER_TO_URI_3PCC_SYNTAX " " +SWITCH_STANDARD_API(uuid_refer_to_uri_3pcc) +{ + char *argv[3] = { 0 }; + char *split_argv; + int argc = 0; + + if (zstr(cmd)) { + stream->write_function(stream, "-USAGE: %s\n", UUID_REFER_TO_URI_3PCC_SYNTAX); + return SWITCH_STATUS_SUCCESS; + } + + split_argv = strdup(cmd); + argc = switch_split(split_argv, ' ', argv); + + if (argc < 2 || zstr(argv[0]) || zstr(argv[1])) { + stream->write_function(stream, "-USAGE: %s\n", UUID_REFER_TO_URI_3PCC_SYNTAX); + } else { + char *uuid_to_send_refer = argv[0]; + char *refer_to_uri = argv[1]; + switch_core_session_t *session_to_send_refer = switch_core_session_locate(uuid_to_send_refer); + + if (session_to_send_refer) { + if (!zstr(refer_to_uri)) { + switch_core_session_message_t msg = {0}; + + /* Tell sofia to refer the channel */ + msg.from = __FILE__; + msg.string_arg = argv[1]; + msg.message_id = SWITCH_MESSAGE_INDICATE_REFER_TO_URI_3PCC; + switch_core_session_receive_message(session_to_send_refer, &msg); + stream->write_function(stream, "+OK:%s\n", msg.string_reply); + } else { + stream->write_function(stream, "-ERR Invalid URI!\n"); + } + switch_core_session_rwunlock(session_to_send_refer); + } else { + stream->write_function(stream, "-ERR No such channel %s!\n", uuid_to_send_refer); + } + } + + switch_safe_free(split_argv); + return SWITCH_STATUS_SUCCESS; +} + #define UUID_REDIRECT_SYNTAX " " SWITCH_STANDARD_API(uuid_redirect) { @@ -7563,6 +7608,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) SWITCH_ADD_API(commands_api_interface, "uuid_getvar", "Get a variable from a channel", uuid_getvar_function, GETVAR_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_hold", "Place call on 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_refer_to_uri_3pcc", "Send a REFER with a custom Refer-To URI to a channel", uuid_refer_to_uri_3pcc, UUID_REFER_TO_URI_3PCC_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_send_message", "Send MESSAGE to the endpoint", uuid_send_message_function, SEND_MESSAGE_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_set_media_stats", "Set media stats", uuid_set_media_stats, UUID_MEDIA_STATS_SYNTAX); @@ -7781,6 +7827,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) switch_console_set_complete("add uuid_recovery_refresh ::console::list_uuid"); switch_console_set_complete("add uuid_recv_dtmf ::console::list_uuid"); switch_console_set_complete("add uuid_redirect ::console::list_uuid"); + switch_console_set_complete("add uuid_refer_to_uri_3pcc ::console::list_uuid"); switch_console_set_complete("add uuid_send_dtmf ::console::list_uuid"); switch_console_set_complete("add uuid_session_heartbeat ::console::list_uuid"); switch_console_set_complete("add uuid_setvar_multi ::console::list_uuid"); diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index f891c6a513..a10872e00e 100644 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -1187,6 +1187,31 @@ SWITCH_STANDARD_APP(flush_dtmf_function) switch_channel_flush_dtmf(switch_core_session_get_channel(session)); } +#define refer_to_uri_3pcc_DESC "Send a REFER with Refer-To: set to ?;" +#define refer_to_uri_3pcc_SYNTAX "" +SWITCH_STANDARD_APP(refer_to_uri_3pcc_function) +{ + char *argv[1] = { 0 }; + int argc; + char *split_argv; + switch_core_session_t *session_to_send_refer = session; + switch_core_session_message_t msg = {0}; + + split_argv = switch_core_session_strdup(session, data); + argc = switch_split(split_argv, ' ', argv); + + if (argc < 1 || zstr(argv[0])) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "%s refer_to_uri_3pcc error USAGE: %s\n", + switch_core_session_get_name(session), refer_to_uri_3pcc_SYNTAX); + return; + } + + msg.from = __FILE__; + msg.string_arg = argv[0]; + msg.message_id = SWITCH_MESSAGE_INDICATE_REFER_TO_URI_3PCC; + switch_core_session_receive_message(session_to_send_refer, &msg); +} + SWITCH_STANDARD_APP(transfer_function) { int argc; @@ -6470,6 +6495,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SWITCH_ADD_APP(app_interface, "unhold", "Send a un-hold message", "Send a un-hold message", unhold_function, UNHOLD_SYNTAX, SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "mutex", "block on a call flow only allowing one at a time", "", mutex_function, MUTEX_SYNTAX, SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "page", "", "", page_function, PAGE_SYNTAX, SAF_NONE); + SWITCH_ADD_APP(app_interface, "refer_to_uri_3pcc", "Send a REFER with Refer-To/Call-Info/serviceurn to a channel", refer_to_uri_3pcc_DESC, refer_to_uri_3pcc_function, refer_to_uri_3pcc_SYNTAX, SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "transfer", "Transfer a channel", TRANSFER_LONG_DESC, transfer_function, " [ ]", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "check_acl", "Check an ip against an ACL list", "Check an ip against an ACL list", check_acl_function, diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 393bb43acc..331545a2f0 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -1313,6 +1313,71 @@ static switch_status_t sofia_send_dtmf(switch_core_session_t *session, const swi return SWITCH_STATUS_SUCCESS; } +static switch_bool_t sofia_refer_to_uri_3pcc(switch_core_session_t *session, switch_core_session_message_t *msg, const char *refer_to_uri) +{ + switch_channel_t *channel = switch_core_session_get_channel(session); + private_object_t *tech_pvt = switch_core_session_get_private(session); + const char *sip_refer_reply; + char *refer_to; + char *referred_by; + char *url_encoded; + char *sip_prefix = strcasecmp(refer_to_uri, "sip:") ? "" : "sip:"; + const char *from_host = switch_channel_get_variable(channel, "sip_from_host"); + const char *from_user = switch_channel_get_variable(channel, "sip_from_user"); + const char *refer_to_params_serviceurn = switch_channel_get_variable(channel, "sip_refer_to_params_serviceurn"); + const char *call_info_override = switch_channel_get_variable(tech_pvt->channel, "sip_h_Call-Info"); + + if (!zstr(from_host) && !zstr(from_user) && !zstr(refer_to_uri)) { + const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile); + + if (!zstr(call_info_override)) { + switch_size_t url_encoded_size = strlen(call_info_override)*3+1; + + switch_malloc(url_encoded, url_encoded_size); + switch_url_encode(call_info_override, url_encoded, url_encoded_size); + refer_to = switch_mprintf("<%s%s?Call-Info=%s>", sip_prefix, refer_to_uri, url_encoded); + switch_safe_free(url_encoded); + } else { + refer_to = switch_mprintf("<%s%s>", sip_prefix, refer_to_uri); + } + + if (!zstr(refer_to_params_serviceurn)) { + char *refer_to_with_params; + switch_size_t url_encoded_size = strlen(refer_to_params_serviceurn)*3+1; + + switch_malloc(url_encoded, url_encoded_size); + switch_url_encode(refer_to_params_serviceurn, url_encoded, url_encoded_size); + refer_to_with_params = switch_mprintf("%s;serviceurn=%s", refer_to, url_encoded); + switch_safe_free(url_encoded); + switch_safe_free(refer_to); + refer_to = refer_to_with_params; + } + + referred_by = switch_mprintf("", from_user, from_host); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "(%s) Referring %s: %s\n", + switch_channel_get_name(channel), refer_to_uri, refer_to); + nua_refer(tech_pvt->nh, SIPTAG_REFER_TO_STR(refer_to), SIPTAG_REFERRED_BY_STR(referred_by), + TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), + TAG_END()); + switch_safe_free(refer_to); + switch_safe_free(referred_by); + switch_mutex_unlock(tech_pvt->sofia_mutex); + sofia_wait_for_reply(tech_pvt, SOFIA_CUSTOM_NUA_EVENT_REFER, 10); + switch_mutex_lock(tech_pvt->sofia_mutex); + + if ((sip_refer_reply = switch_channel_get_variable(tech_pvt->channel, "sip_refer_reply"))) { + msg->string_reply = switch_core_session_strdup(session, sip_refer_reply); + } else { + msg->string_reply = "no reply"; + } + + return SWITCH_TRUE; + } else { + msg->string_reply = "from_host, from_user or refer_to_uri empty"; + return SWITCH_FALSE; + } +} + static switch_status_t sofia_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg) { switch_channel_t *channel = switch_core_session_get_channel(session); @@ -1515,6 +1580,12 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi switch (msg->message_id) { + case SWITCH_MESSAGE_INDICATE_REFER_TO_URI_3PCC: + if (sofia_refer_to_uri_3pcc(session, msg, msg->string_arg) == SWITCH_FALSE) { + goto end_lock; + } + break; + case SWITCH_MESSAGE_INDICATE_DEFLECT: { char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_HEADER_PREFIX);