diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 930428fb43..5fe46c80fe 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -1628,7 +1628,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session nchannel = switch_core_session_get_channel(nsession); if (!strncasecmp(profile_name, "gateway", 7)) { - char *gw; + char *gw, *params; sofia_gateway_t *gateway_ptr = NULL; if (!(gw = strchr(profile_name, '/'))) { @@ -1653,19 +1653,55 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session goto error; } + tech_pvt->transport = gateway_ptr->register_transport; + + /* + * Handle params, strip them off the destination and add them to the + * invite contact. + * + * TODO: + * - Add parameters back to destination url? + */ + if ((params = strchr(dest, ';'))) { + char *tp_param; + + *params++ = '\0'; + + if ((tp_param = (char *)switch_stristr("port=", params))) { + tp_param += 5; + tech_pvt->transport = sofia_glue_str2transport(tp_param); + if (tech_pvt->transport == SOFIA_TRANSPORT_UNKNOWN) { + cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; + goto error; + } + } + } + + if (tech_pvt->transport != gateway_ptr->register_transport) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "You are trying to use a different transport type for this gateway (overriding the register-transport), this is unsupported!\n"); + cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; + goto error; + } + profile = gateway_ptr->profile; tech_pvt->gateway_name = switch_core_session_strdup(nsession, gateway_ptr->name); switch_channel_set_variable(nchannel, "sip_gateway_name", gateway_ptr->name); - + if (!switch_test_flag(gateway_ptr, REG_FLAG_CALLERID)) { tech_pvt->gateway_from_str = switch_core_session_strdup(nsession, gateway_ptr->register_from); } + if (!strchr(dest, '@')) { tech_pvt->dest = switch_core_session_sprintf(nsession, "sip:%s@%s", dest, gateway_ptr->register_proxy + 4); } else { tech_pvt->dest = switch_core_session_sprintf(nsession, "sip:%s", dest); } - tech_pvt->invite_contact = switch_core_session_strdup(nsession, gateway_ptr->register_contact); + + if (params) { + tech_pvt->invite_contact = switch_core_session_sprintf(nsession, "%s;%s", gateway_ptr->register_contact, params); + } else { + tech_pvt->invite_contact = switch_core_session_strdup(nsession, gateway_ptr->register_contact); + } } else { if (!(dest = strchr(profile_name, '/'))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid URL\n"); @@ -1729,7 +1765,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session } } switch_channel_set_variable(nchannel, "sip_destination_url", tech_pvt->dest); - + caller_profile = switch_caller_profile_clone(nsession, outbound_profile); caller_profile->destination_number = switch_core_strdup(caller_profile->pool, dest); switch_channel_set_caller_profile(nchannel, caller_profile); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index fcfe7d163c..91caac1df1 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -196,6 +196,14 @@ typedef enum { REG_STATE_LAST } reg_state_t; +typedef enum { + SOFIA_TRANSPORT_UNKNOWN = 0, + SOFIA_TRANSPORT_UDP, + SOFIA_TRANSPORT_TCP, + SOFIA_TRANSPORT_TCP_TLS, + SOFIA_TRANSPORT_SCTP +} sofia_transport_t; + struct sofia_gateway { sofia_private_t *sofia_private; nua_handle_t *nh; @@ -212,6 +220,7 @@ struct sofia_gateway { char *register_context; char *expires_str; char *register_url; + sofia_transport_t register_transport; uint32_t freq; time_t expires; time_t retry; @@ -358,6 +367,7 @@ struct private_object { switch_payload_t bte; switch_payload_t cng_pt; switch_payload_t bcng_pt; + sofia_transport_t transport; nua_handle_t *nh; nua_handle_t *nh2; sip_contact_t *contact; @@ -401,14 +411,6 @@ typedef enum { AUTH_STALE, } auth_res_t; -typedef enum { - SOFIA_TRANSPORT_UNKNOWN = 0, - SOFIA_TRANSPORT_UDP, - SOFIA_TRANSPORT_TCP, - SOFIA_TRANSPORT_TCP_TLS, - SOFIA_TRANSPORT_SCTP, -} sofia_transport_t; - #define sofia_test_pflag(obj, flag) ((obj)->pflags & flag) #define sofia_set_pflag(obj, flag) (obj)->pflags |= (flag) #define sofia_set_pflag_locked(obj, flag) assert(obj->flag_mutex != NULL);\ @@ -568,8 +570,10 @@ void sofia_reg_release_gateway__(const char *file, const char *func, int line, s */ sofia_transport_t sofia_glue_via2transport(const sip_via_t *via); sofia_transport_t sofia_glue_url2transport(const url_t *url); +sofia_transport_t sofia_glue_str2transport(const char *str); const char *sofia_glue_transport2str(const sofia_transport_t tp); +char * sofia_glue_find_parameter(const char *str, const char *param); int sofia_glue_transport_has_tls(const sofia_transport_t tp); const char *sofia_glue_get_unknown_header(sip_t const *sip, const char *name); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 494e946425..d573568543 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -664,8 +664,9 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) *register_proxy = NULL, *contact_params = NULL, *params = NULL, - *register_transport = "udp"; + *register_transport = NULL; + gateway->register_transport = SOFIA_TRANSPORT_UDP; gateway->pool = profile->pool; gateway->profile = profile; gateway->name = switch_core_strdup(gateway->pool, name); @@ -707,12 +708,14 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) } else if (!strcmp(var, "contact-params")) { contact_params = val; } else if (!strcmp(var, "register-transport")) { - if (!strcasecmp(val, "udp") || !strcasecmp(val, "tcp")) { - register_transport = val; - } else { + sofia_transport_t transport = sofia_glue_str2transport(val); + + if (transport == SOFIA_TRANSPORT_UNKNOWN || (!sofia_test_pflag(profile, PFLAG_TLS) && sofia_glue_transport_has_tls(transport))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: unsupported transport\n"); goto skip; } + + gateway->register_transport = transport; } } @@ -767,6 +770,7 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) if (switch_true(caller_id_in_from)) { switch_set_flag(gateway, REG_FLAG_CALLERID); } + register_transport = (char *)sofia_glue_transport2str(gateway->register_transport); if (contact_params) { if (*contact_params == ';') { params = switch_core_sprintf(gateway->pool, "%s&transport=%s", contact_params, register_transport); @@ -777,10 +781,11 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) params = switch_core_sprintf(gateway->pool, ";transport=%s", register_transport); } - gateway->register_url = switch_core_sprintf(gateway->pool, "sip:%s;transport=%s", register_proxy,register_transport); + gateway->register_url = switch_core_sprintf(gateway->pool, "sip:%s;transport=%s", register_proxy, register_transport); gateway->register_from = switch_core_sprintf(gateway->pool, "", from_user, from_domain, register_transport); gateway->register_contact = switch_core_sprintf(gateway->pool, "", extension, - profile->extsipip ? profile->extsipip : profile->sipip, profile->sip_port, params); + profile->extsipip ? profile->extsipip : profile->sipip, + sofia_glue_transport_has_tls(gateway->register_transport) ? profile->tls_sip_port : profile->sip_port, params); if (!strncasecmp(proxy, "sip:", 4)) { gateway->register_proxy = switch_core_strdup(gateway->pool, proxy); diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 7e455df2f3..3fd4f72f36 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -509,24 +509,40 @@ switch_status_t sofia_glue_tech_choose_video_port(private_object_t *tech_pvt) return SWITCH_STATUS_SUCCESS; } -static sofia_transport_t sofia_glue_str2transport(const char *str) +sofia_transport_t sofia_glue_str2transport(const char *str) { - if (!strcasecmp(str, "udp")) { + if (!strncasecmp(str, "udp", 3)) { return SOFIA_TRANSPORT_UDP; } - else if (!strcasecmp(str, "tcp")) { + else if (!strncasecmp(str, "tcp", 3)) { return SOFIA_TRANSPORT_TCP; } - else if (!strcasecmp(str, "sctp")) { + else if (!strncasecmp(str, "sctp", 4)) { return SOFIA_TRANSPORT_SCTP; } - else if (!strcasecmp(str, "tls")) { + else if (!strncasecmp(str, "tls", 3)) { return SOFIA_TRANSPORT_TCP_TLS; } return SOFIA_TRANSPORT_UNKNOWN; } +char * sofia_glue_find_parameter(const char *str, const char *param) +{ + char *ptr = NULL; + + ptr = (char *)str; + while(ptr) { + if (!strncasecmp(ptr, param, strlen(param))) + return ptr; + + if ((ptr = strchr(ptr, ';'))) + ptr++; + } + + return NULL; +} + sofia_transport_t sofia_glue_url2transport(const url_t *url) { char *ptr = NULL; @@ -539,29 +555,8 @@ sofia_transport_t sofia_glue_url2transport(const url_t *url) tls++; } - ptr = (char *)url->url_params; - while(ptr) { - - if (!strncasecmp(ptr, "transport=", 10)) { - ptr += 10; - - if (!strncasecmp(ptr, "udp", 3)) { - return SOFIA_TRANSPORT_UDP; - } - else if (!strncasecmp(ptr, "tcp", 3)) { - return SOFIA_TRANSPORT_TCP; - } - else if (!strncasecmp(ptr, "tls", 3)) { - return SOFIA_TRANSPORT_TCP_TLS; - } - else if (!strncasecmp(ptr, "sctp", 4)) { - return SOFIA_TRANSPORT_SCTP; - } - break; - } - - if ((ptr = strchr(ptr, ';'))) - ptr++; + if ((ptr = sofia_glue_find_parameter(url->url_params, "transport="))) { + return sofia_glue_str2transport(ptr + 10); } return (tls) ? SOFIA_TRANSPORT_TCP_TLS : SOFIA_TRANSPORT_UDP; @@ -713,7 +708,6 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) if (!tech_pvt->nh) { char *d_url = NULL, *url = NULL; sofia_private_t *sofia_private; - sofia_transport_t transport = SOFIA_TRANSPORT_UDP; char *invite_contact = NULL, *to_str, *use_from_str, *from_str, *url_str; const char *t_var; char *rpid_domain = "cluecon.com", *p; @@ -752,28 +746,35 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) rpid_domain = "cluecon.com"; } - if ((p = (char *)switch_stristr("port=", url))) { - p += 5; - transport = sofia_glue_str2transport( p ); - } else { - if ((t_var = switch_channel_get_variable(channel, "sip_transport"))) { - transport = sofia_glue_str2transport(t_var); + /* + * Ignore transport chanvar and uri parameter for gateway connections + * since all of them have been already taken care of in mod_sofia.c:sofia_outgoing_channel() + */ + if (switch_strlen_zero(tech_pvt->gateway_name)) { + if ((p = (char *)switch_stristr("port=", url))) { + p += 5; + tech_pvt->transport = sofia_glue_str2transport( p ); + } else { + if ((t_var = switch_channel_get_variable(channel, "sip_transport"))) { + tech_pvt->transport = sofia_glue_str2transport(t_var); + } + } + + if (tech_pvt->transport == SOFIA_TRANSPORT_UNKNOWN) { + tech_pvt->transport = SOFIA_TRANSPORT_UDP; } } - if (transport == SOFIA_TRANSPORT_UNKNOWN) { - transport = SOFIA_TRANSPORT_UDP; - } - - if (switch_strlen_zero(tech_pvt->invite_contact)) { - if (sofia_glue_transport_has_tls(transport)) + if (switch_strlen_zero(tech_pvt->invite_contact)) + { + if (sofia_glue_transport_has_tls(tech_pvt->transport)) tech_pvt->invite_contact = tech_pvt->profile->tls_url; else tech_pvt->invite_contact = tech_pvt->profile->url; } - url_str = sofia_overcome_sip_uri_weakness(session, url, transport, SWITCH_TRUE); - invite_contact = sofia_overcome_sip_uri_weakness(session, tech_pvt->invite_contact, transport, SWITCH_FALSE); + url_str = sofia_overcome_sip_uri_weakness(session, url, tech_pvt->transport, SWITCH_TRUE); + invite_contact = sofia_overcome_sip_uri_weakness(session, tech_pvt->invite_contact, tech_pvt->transport, SWITCH_FALSE); from_str = sofia_overcome_sip_uri_weakness(session, use_from_str, 0, SWITCH_FALSE); to_str = sofia_overcome_sip_uri_weakness(session, tech_pvt->dest_to, 0, SWITCH_FALSE); diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 11213f6dbc..767a203310 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -343,7 +343,7 @@ uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t *profile, nua_han char network_ip[80]; char *register_gateway = NULL; int network_port; - int cd = 0; + const char *reg_desc = "Registered"; const char *call_id = NULL; char *force_user; @@ -431,34 +431,19 @@ uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t *profile, nua_han } if ((v_contact_str = switch_event_get_header(*v_event, "sip-force-contact"))) { - if (!strcasecmp(v_contact_str, "nat-connectile-dysfunction") || !strcasecmp(v_contact_str, "NDLB-connectile-dysfunction")) { + if (!strcasecmp(v_contact_str, "nat-connectile-dysfunction") || + !strcasecmp(v_contact_str, "NDLB-connectile-dysfunction") || !strcasecmp(v_contact_str, "NDLB-tls-connectile-dysfunction")) { if (contact->m_url->url_params) { switch_snprintf(contact_str, sizeof(contact_str), "%s ", display, contact->m_url->url_user, network_ip, network_port, contact->m_url->url_params); } else { switch_snprintf(contact_str, sizeof(contact_str), "%s ", display, contact->m_url->url_user, network_ip, network_port); } - cd = 1; - exptime = 20; - } else if (!strcasecmp(v_contact_str, "NDLB-tls-connectile-dysfunction")) { - const char *pt = contact->m_url->url_port; - int port; - - if (!pt) { - pt = "5060"; - } - - port = atoi(pt); - - if (port > 0) { - port++; - if (contact->m_url->url_params) { - switch_snprintf(contact_str, sizeof(contact_str), "%s ", - display, contact->m_url->url_user, contact->m_url->url_host, port, contact->m_url->url_params); - } else { - switch_snprintf(contact_str, sizeof(contact_str), "%s ", - display, contact->m_url->url_user, contact->m_url->url_host, port); - } + if (strstr(v_contact_str, "tls")) { + reg_desc = "Registered(TLSHACK)"; + } else { + reg_desc = "Registered(NATHACK)"; + exptime = 20; } } else { char *p; @@ -524,7 +509,7 @@ uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t *profile, nua_han switch_safe_free(sql); sql = switch_mprintf("insert into sip_registrations values ('%q', '%q','%q','%q','%q', '%q', %ld, '%q')", call_id, - to_user, to_host, contact_str, cd ? "Registered(NATHACK)" : "Registered", + to_user, to_host, contact_str, reg_desc, rpid, (long) switch_timestamp(NULL) + (long) exptime * 2, agent);