[Freeswitch-svn] [commit] r13553 - freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia
Author: brian Date: Tue Jun 2 16:02:47 2009 New Revision: 13553 Log: adding NAT patch to my branch so others can help Modified: freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/sofia.c freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/sofia_sla.c Modified: freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c ============================================================================== --- freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c (original) +++ freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c Tue Jun 2 16:02:47 2009 @@ -394,6 +394,7 @@ if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) { nua_bye(tech_pvt->nh, SIPTAG_REASON_STR(reason), + TAG_IF(!switch_strlen_zero(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), TAG_IF(!switch_strlen_zero(bye_headers), SIPTAG_HEADER_STR(bye_headers)), TAG_END()); } @@ -407,7 +408,6 @@ nua_cancel(tech_pvt->nh, SIPTAG_REASON_STR(reason), TAG_IF(!switch_strlen_zero(bye_headers), SIPTAG_HEADER_STR(bye_headers)), - TAG_IF(!switch_strlen_zero(bye_headers), SIPTAG_HEADER_STR(bye_headers)), TAG_END()); } } else { @@ -2644,6 +2644,9 @@ } } else { + char *dup_dest = NULL, *dest_host, *dest_user; + + if (!(dest = strchr(profile_name, '/'))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid URL\n"); cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT; @@ -2661,10 +2664,17 @@ profile_name = profile->domain_name; } + dup_dest = strdup(dest); + switch_assert(dup_dest != NULL); + sofia_glue_get_user_host(dup_dest, &dest_user, &dest_host); + tech_pvt->remote_ip = switch_core_session_sprintf(nsession, "%s", dest_host); + switch_safe_free(dup_dest); + if (!strncasecmp(dest, "sip:", 4) || !strncasecmp(dest, "sips:", 5)) { tech_pvt->dest = switch_core_session_strdup(nsession, dest); } else if ((host = strchr(dest, '%'))) { char buf[128]; + *host = '@'; tech_pvt->e_dest = switch_core_session_strdup(nsession, dest); *host++ = '\0'; @@ -2678,6 +2688,7 @@ } } else if (!(host = strchr(dest, '@'))) { char buf[128]; + tech_pvt->e_dest = switch_core_session_strdup(nsession, dest); if (sofia_reg_find_reg_url(profile, dest, profile_name, buf, sizeof(buf))) { tech_pvt->dest = switch_core_session_strdup(nsession, buf); @@ -3217,6 +3228,8 @@ mod_sofia_globals.running = 1; switch_mutex_unlock(mod_sofia_globals.mutex); + mod_sofia_globals.auto_nat = (switch_core_get_variable("nat_type") ? 1 : 0); + switch_queue_create(&mod_sofia_globals.presence_queue, SOFIA_QUEUE_SIZE, mod_sofia_globals.pool); switch_queue_create(&mod_sofia_globals.mwi_queue, SOFIA_QUEUE_SIZE, mod_sofia_globals.pool); Modified: freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h ============================================================================== --- freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h (original) +++ freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h Tue Jun 2 16:02:47 2009 @@ -192,6 +192,7 @@ PFLAG_MESSAGE_QUERY_ON_REGISTER, PFLAG_RTP_AUTOFLUSH_DURING_BRIDGE, PFLAG_PROXY_FOLLOW_REDIRECT, + PFLAG_AUTO_NAT, /* No new flags below this line */ PFLAG_MAX } PFLAGS; @@ -272,6 +273,7 @@ char guess_mask_str[16]; int debug_presence; int auto_restart; + int auto_nat; }; extern struct mod_sofia_globals mod_sofia_globals; @@ -408,9 +410,13 @@ char *extsipip; char *username; char *url; + char *public_url; char *bindurl; char *tls_url; + char *tls_public_url; char *tls_bindurl; + char *tcp_public_contact; + char *tls_public_contact; char *tcp_contact; char *tls_contact; char *sla_contact; @@ -489,6 +495,7 @@ uint32_t timer_t2; uint32_t timer_t4; char *contact_user; + char *local_network; }; struct private_object { @@ -613,6 +620,7 @@ switch_rtp_bug_flag_t rtp_bugs; switch_codec_implementation_t read_impl; switch_codec_implementation_t write_impl; + char *user_via; }; struct callback_t { Modified: freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/sofia.c ============================================================================== --- freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/sofia.c (original) +++ freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/sofia.c Tue Jun 2 16:02:47 2009 @@ -766,6 +766,7 @@ sofia_event_callback, /* Callback for processing events */ profile, /* Additional data to pass to callback */ NUTAG_URL(profile->bindurl), + NTATAG_USER_VIA(1), TAG_IF(!strchr(profile->sipip, ':'), SOATAG_AF(SOA_AF_IP4_ONLY)), TAG_IF(strchr(profile->sipip, ':'), SOATAG_AF(SOA_AF_IP6_ONLY)), TAG_IF(sofia_test_pflag(profile, PFLAG_TLS), NUTAG_SIPS_URL(profile->tls_bindurl)), @@ -1759,6 +1760,8 @@ } } else if(!strcasecmp(var, "context")) { profile->context = switch_core_strdup(profile->pool, val); + } else if (!strcasecmp(var, "local-network-acl")) { + profile->local_network = switch_core_strdup(profile->pool, val); } else if (!strcasecmp(var, "force-register-domain")) { profile->reg_domain = switch_core_strdup(profile->pool, val); } else if (!strcasecmp(var, "force-register-db-domain")) { @@ -2163,8 +2166,11 @@ if (!strcmp(val, "0.0.0.0")) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid IP 0.0.0.0 replaced with %s\n", mod_sofia_globals.guess_ip); + } else if (!strcasecmp(val, "auto-nat")) { + ip = mod_sofia_globals.auto_nat ? switch_core_get_variable("nat_public_addr") : mod_sofia_globals.guess_ip; + sofia_set_pflag(profile, PFLAG_AUTO_NAT); } else { - ip = strcasecmp(val, "auto") ? val : mod_sofia_globals.guess_ip; + ip = strcasecmp(val, "auto") ? val : mod_sofia_globals.guess_ip; } profile->extrtpip = switch_core_strdup(profile->pool, ip); } else { @@ -2198,6 +2204,9 @@ if (!strcasecmp(val, "0.0.0.0")) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid IP 0.0.0.0 replaced with %s\n", mod_sofia_globals.guess_ip); + } else if (!strcasecmp(val, "auto-nat")) { + ip = mod_sofia_globals.auto_nat ? switch_core_get_variable("nat_public_addr") : mod_sofia_globals.guess_ip; + sofia_set_pflag(profile, PFLAG_AUTO_NAT); } else if (strcasecmp(val, "auto")) { switch_port_t port = 0; if (sofia_glue_ext_address_lookup(profile, NULL, &myip, &port, val, profile->pool) == SWITCH_STATUS_SUCCESS) { @@ -2210,6 +2219,8 @@ } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid ext-sip-ip\n"); } + } else if (!strcasecmp(var, "local-network-acl")) { + profile->local_network = switch_core_strdup(profile->pool, val); } else if (!strcasecmp(var, "force-register-domain")) { profile->reg_domain = switch_core_strdup(profile->pool, val); } else if (!strcasecmp(var, "force-register-db-domain")) { @@ -2264,7 +2275,7 @@ } else if (!strcasecmp(var, "manage-shared-appearance")) { if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE); - profile->sla_contact = switch_core_sprintf(profile->pool, "sip:sla-agent@%s", profile->sipip); + profile->sla_contact = switch_core_sprintf(profile->pool, "sla-agent"); } } else if (!strcasecmp(var, "disable-srv")) { if (switch_true(val)) { @@ -2548,7 +2559,18 @@ if (!profile->sipdomain) { profile->sipdomain = switch_core_strdup(profile->pool, profile->sipip); } - if (profile->extsipip) { + if (profile->extsipip && sofia_test_pflag(profile, PFLAG_AUTO_NAT)) { + char *ipv6 = strchr(profile->extsipip, ':'); + profile->public_url = switch_core_sprintf(profile->pool, + "sip:%s@%s%s%s:%d", + profile->contact_user, + ipv6 ? "[" : "", + profile->extsipip, + ipv6 ? "]" : "", + profile->sip_port); + } + + if (profile->extsipip && !sofia_test_pflag(profile, PFLAG_AUTO_NAT)) { char *ipv6 = strchr(profile->extsipip, ':'); profile->url = switch_core_sprintf(profile->pool, "sip:%s@%s%s%s:%d", @@ -2571,7 +2593,11 @@ } profile->tcp_contact = switch_core_sprintf(profile->pool, "%s;transport=tcp", profile->url); - + + if(sofia_test_pflag(profile, PFLAG_AUTO_NAT)) { + profile->tcp_public_contact = switch_core_sprintf(profile->pool, "%s;transport=tcp", profile->public_url); + } + if (profile->bind_params) { char *bindurl = profile->bindurl; profile->bindurl = switch_core_sprintf(profile->pool, "%s;%s", bindurl, profile->bind_params); @@ -2585,7 +2611,18 @@ profile->tls_sip_port = atoi(SOFIA_DEFAULT_TLS_PORT); } - if (profile->extsipip) { + if (profile->extsipip && sofia_test_pflag(profile, PFLAG_AUTO_NAT)) { + char *ipv6 = strchr(profile->extsipip, ':'); + profile->tls_public_url = switch_core_sprintf(profile->pool, + "sip:%s@%s%s%s:%d", + profile->contact_user, + ipv6 ? "[" : "", + profile->extsipip, + ipv6 ? "]" : "", + profile->tls_sip_port); + } + + if (profile->extsipip && !sofia_test_pflag(profile, PFLAG_AUTO_NAT)) { char *ipv6 = strchr(profile->extsipip, ':'); profile->tls_url = switch_core_sprintf(profile->pool, @@ -2632,6 +2669,9 @@ profile->tls_cert_dir = switch_core_sprintf(profile->pool, "%s/ssl", SWITCH_GLOBAL_dirs.conf_dir); } profile->tls_contact = switch_core_sprintf(profile->pool, "%s;transport=tls", profile->tls_url); + if (sofia_test_pflag(profile, PFLAG_AUTO_NAT)) { + profile->tls_public_contact = switch_core_sprintf(profile->pool, "%s;transport=tls", profile->tls_public_url); + } } } if (profile) { @@ -4309,6 +4349,7 @@ get_addr(network_ip, sizeof(network_ip), my_addrinfo->ai_addr, my_addrinfo->ai_addrlen); network_port = ntohs(((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_port); + if (sofia_test_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION)) { if (sip && sip->sip_via) { const char *port = sip->sip_via->v_port; @@ -4428,6 +4469,12 @@ tech_pvt->remote_ip = switch_core_session_strdup(session, network_ip); tech_pvt->remote_port = network_port; + + if (sofia_test_pflag(profile, PFLAG_AUTO_NAT) && !switch_check_network_list_ip(tech_pvt->remote_ip, profile->local_network)) { + sofia_transport_t transport = sofia_glue_url2transport(sip->sip_contact->m_url); + tech_pvt->user_via = switch_core_session_sprintf(session, "SIP/2.0/%s %s;rport", sofia_glue_transport2str(transport), + profile->extsipip); + } channel = tech_pvt->channel = switch_core_session_get_channel(session); @@ -4626,7 +4673,8 @@ const char *url; - if ((url = (sofia_glue_transport_has_tls(transport)) ? profile->tls_url : profile->url)) { + if ((url = (sofia_glue_transport_has_tls(transport)) ? profile->tls_url : + (switch_check_network_list_ip(tech_pvt->remote_ip, profile->local_network)) ? profile->url : profile->public_url)) { if (strchr(url, '>')) { tech_pvt->reply_contact = switch_core_session_sprintf(session, "%s;transport=%s", url, sofia_glue_transport2str(transport)); } else { Modified: freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c ============================================================================== --- freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c (original) +++ freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c Tue Jun 2 16:02:47 2009 @@ -642,15 +642,16 @@ switch_rtp_release_port(tech_pvt->profile->rtpip, tech_pvt->local_sdp_audio_port); } - tech_pvt->local_sdp_audio_ip = ip; + if (!(tech_pvt->local_sdp_audio_port = switch_rtp_request_port(tech_pvt->profile->rtpip))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No RTP ports available!\n"); return SWITCH_STATUS_FALSE; } + sdp_port = tech_pvt->local_sdp_audio_port; - if (!(use_ip = switch_channel_get_variable(tech_pvt->channel, "rtp_adv_audio_ip"))) { + if (!(use_ip = switch_channel_get_variable(tech_pvt->channel, "rtp_adv_audio_ip")) && !sofia_test_pflag(tech_pvt->profile, PFLAG_AUTO_NAT)) { if (tech_pvt->profile->extrtpip) { use_ip = tech_pvt->profile->extrtpip; } @@ -663,9 +664,24 @@ return SWITCH_STATUS_FALSE; } } - - tech_pvt->adv_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, ip); + if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { + if (tech_pvt->remote_ip && sofia_test_pflag(tech_pvt->profile, PFLAG_AUTO_NAT) && + !switch_check_network_list_ip(tech_pvt->remote_ip, tech_pvt->profile->local_network)) { + tech_pvt->adv_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, tech_pvt->profile->extrtpip); + } else { + tech_pvt->adv_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, ip); + } + } else { + + if (tech_pvt->remote_ip && sofia_test_pflag(tech_pvt->profile, PFLAG_AUTO_NAT) && + !switch_check_network_list_ip(tech_pvt->remote_ip, tech_pvt->profile->local_network)) { + tech_pvt->adv_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, tech_pvt->profile->extrtpip); + } else { + tech_pvt->adv_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, ip); + } + } + tech_pvt->adv_sdp_audio_port = sdp_port; switch_snprintf(tmp, sizeof(tmp), "%d", sdp_port); @@ -1257,10 +1273,19 @@ check_decode(cid_num, session); if (!tech_pvt->from_str) { - const char* sipip = tech_pvt->profile->extsipip ? tech_pvt->profile->extsipip : tech_pvt->profile->sipip; - const char* format = strchr(sipip, ':') ? "\"%s\" <sip:%s%s[%s]>" : "\"%s\" <sip:%s%s%s>"; + const char* sipip; + const char* format; const char *alt = NULL; + if (sofia_test_pflag(tech_pvt->profile, PFLAG_AUTO_NAT)) { + sipip = (switch_check_network_list_ip(tech_pvt->remote_ip, tech_pvt->profile->local_network)) + ? tech_pvt->profile->sipip : tech_pvt->profile->extsipip; + } else { + sipip = tech_pvt->profile->extsipip ? tech_pvt->profile->extsipip : tech_pvt->profile->sipip; + } + + format = strchr(sipip, ':') ? "\"%s\" <sip:%s%s[%s]>" : "\"%s\" <sip:%s%s%s>"; + if ((alt = switch_channel_get_variable(channel, "sip_invite_domain"))) { sipip = alt; } @@ -1303,7 +1328,7 @@ const char *invite_from_params = switch_channel_get_variable(tech_pvt->channel, "sip_invite_from_params"); const char *from_var = switch_channel_get_variable(tech_pvt->channel, "sip_from_uri"); const char *from_display = switch_channel_get_variable(tech_pvt->channel, "sip_from_display"); - + if (switch_strlen_zero(tech_pvt->dest)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "URL Error!\n"); return SWITCH_STATUS_FALSE; @@ -1365,6 +1390,13 @@ tech_pvt->transport = SOFIA_TRANSPORT_UDP; } } + + if (sofia_test_pflag(tech_pvt->profile, PFLAG_AUTO_NAT) && !switch_check_network_list_ip(tech_pvt->remote_ip, tech_pvt->profile->local_network)) { + const char *transport = sofia_glue_transport2str(tech_pvt->transport); + tech_pvt->user_via = switch_core_session_sprintf(session, "SIP/2.0/%s %s;rport", + transport, tech_pvt->profile->extsipip); + } + if (!sofia_test_pflag(tech_pvt->profile, PFLAG_TLS) && sofia_glue_transport_has_tls(tech_pvt->transport)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "TLS not supported by profile\n"); @@ -1374,8 +1406,18 @@ if (switch_strlen_zero(tech_pvt->invite_contact)) { const char * contact; if ((contact = switch_channel_get_variable(channel, "sip_contact_user"))) { - char *ip_addr = (tech_pvt->profile->extsipip) ? tech_pvt->profile->extsipip : tech_pvt->profile->sipip; - char *ipv6 = strchr(ip_addr, ':'); + char *ip_addr; + char *ipv6; + + if (sofia_test_pflag(tech_pvt->profile, PFLAG_AUTO_NAT)) { + ip_addr = (switch_check_network_list_ip(tech_pvt->remote_ip, tech_pvt->profile->local_network)) + ? tech_pvt->profile->sipip : tech_pvt->profile->extsipip; + } else { + ip_addr = tech_pvt->profile->extsipip ? tech_pvt->profile->extsipip : tech_pvt->profile->sipip; + } + + ipv6 = strchr(ip_addr, ':'); + if (sofia_glue_transport_has_tls(tech_pvt->transport)) { tech_pvt->invite_contact = switch_core_session_sprintf(session, "sip:%s@%s%s%s:%d", contact, ipv6 ? "[" : "", ip_addr, ipv6 ? "]" : "", @@ -1388,7 +1430,12 @@ 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; + if (sofia_test_pflag(tech_pvt->profile, PFLAG_AUTO_NAT) && + !switch_check_network_list_ip(tech_pvt->remote_ip, tech_pvt->profile->local_network)) { + tech_pvt->invite_contact = tech_pvt->profile->public_url; + } else { + tech_pvt->invite_contact = tech_pvt->profile->url; + } } } } @@ -1603,6 +1650,7 @@ nua_invite(tech_pvt->nh, NUTAG_AUTOANSWER(0), NUTAG_SESSION_TIMER(session_timeout), + TAG_IF(!switch_strlen_zero(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), TAG_IF(!switch_strlen_zero(tech_pvt->rpid), SIPTAG_REMOTE_PARTY_ID_STR(tech_pvt->rpid)), TAG_IF(!switch_strlen_zero(tech_pvt->preferred_id), SIPTAG_P_PREFERRED_IDENTITY_STR(tech_pvt->preferred_id)), TAG_IF(!switch_strlen_zero(tech_pvt->asserted_id), SIPTAG_P_ASSERTED_IDENTITY_STR(tech_pvt->asserted_id)), @@ -1630,14 +1678,23 @@ private_object_t *tech_pvt = switch_core_session_get_private(session); switch_channel_t *channel = switch_core_session_get_channel(session); switch_caller_profile_t *caller_profile; - const char *sipip, *format; + const char *sipip, *format, *contact_url; switch_assert(tech_pvt != NULL); switch_mutex_lock(tech_pvt->sofia_mutex); caller_profile = switch_channel_get_caller_profile(channel); - sipip = tech_pvt->profile->extsipip ? tech_pvt->profile->extsipip : tech_pvt->profile->sipip; + if (sofia_test_pflag(tech_pvt->profile, PFLAG_AUTO_NAT)) { + sipip = (switch_check_network_list_ip(tech_pvt->remote_ip, tech_pvt->profile->local_network)) + ? tech_pvt->profile->sipip : tech_pvt->profile->extsipip; + contact_url = tech_pvt->profile->public_url; + } else { + sipip = tech_pvt->profile->extsipip ? tech_pvt->profile->extsipip : tech_pvt->profile->sipip; + contact_url = tech_pvt->profile->url; + } + format = strchr(sipip, ':') ? "\"%s\" <sip:%s@[%s]>" : "\"%s\" <sip:%s@%s>"; + if ((tech_pvt->from_str = switch_core_session_sprintf(session, format, caller_profile->caller_id_name, caller_profile->caller_id_number, sipip))) { @@ -1646,12 +1703,15 @@ tech_pvt->nh2 = nua_handle(tech_pvt->profile->nua, NULL, SIPTAG_TO_STR(tech_pvt->dest), - SIPTAG_FROM_STR(tech_pvt->from_str), SIPTAG_CONTACT_STR(tech_pvt->profile->url), TAG_END()); + SIPTAG_FROM_STR(tech_pvt->from_str), + SIPTAG_CONTACT_STR(contact_url), + TAG_END()); nua_handle_bind(tech_pvt->nh2, tech_pvt->sofia_private); nua_invite(tech_pvt->nh2, - SIPTAG_CONTACT_STR(tech_pvt->profile->url), + SIPTAG_CONTACT_STR(contact_url), + TAG_IF(!switch_strlen_zero(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), SOATAG_ADDRESS(tech_pvt->adv_sdp_audio_ip), SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str), SOATAG_REUSE_REJECTED(1), Modified: freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c ============================================================================== --- freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c (original) +++ freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c Tue Jun 2 16:02:47 2009 @@ -306,12 +306,10 @@ for_everyone = 1; } - dup_account = strdup(account); switch_assert(dup_account != NULL); sofia_glue_get_user_host(dup_account, &user, &host); - if ((pname = switch_event_get_header(event, "sofia-profile"))) { if (!(profile = sofia_glue_find_profile(pname))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No profile %s\n", pname); @@ -375,11 +373,11 @@ } if (for_everyone) { - sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,'%q' " + sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,network_ip,'%q' " "from sip_registrations where sip_user='%q' and sip_host='%q'", stream.data, user, host); } else if (call_id) { - sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,'%q' " + sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,network_ip,'%q' " "from sip_registrations where sip_user='%q' and sip_host='%q' and call_id='%q'", stream.data, user, host, call_id); } @@ -1363,7 +1361,7 @@ profile = ext_profile; } } - + if (!(nh = nua_handle_by_call_id(h->profile->nua, call_id))) { if (profile->debug) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Cannot find handle for %s\n", call_id); @@ -1379,7 +1377,10 @@ nua_handle_bind(nh, &mod_sofia_globals.keep_private); nua_notify(nh, SIPTAG_SUBSCRIPTION_STATE_STR("active"), - SIPTAG_EVENT_STR(event), SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"), SIPTAG_PAYLOAD_STR(body), TAG_END()); + SIPTAG_EVENT_STR(event), + SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"), + SIPTAG_PAYLOAD_STR(body), + TAG_END()); switch_safe_free(id); @@ -1401,13 +1402,14 @@ char *event = "message-summary"; char *contact, *o_contact = argv[2]; char *profile_name = argv[3]; - char *body = argv[4]; + char *network_ip = argv[4]; + char *body = argv[5]; char *id = NULL; nua_handle_t *nh; struct mwi_helper *h = (struct mwi_helper *) pArg; sofia_profile_t *ext_profile = NULL, *profile = h->profile; - char *route = NULL, *route_uri = NULL; - char *p; + char *route = NULL, *route_uri = NULL, *user_via = NULL; + char *p, *contact_str; if (profile_name && strcasecmp(profile_name, h->profile->name)) { if ((ext_profile = sofia_glue_find_profile(profile_name))) { @@ -1415,9 +1417,24 @@ } } - id = switch_mprintf("sip:%s@%s", sub_to_user, sub_to_host); + id = switch_mprintf("sip:%s@%s", sub_to_user, switch_check_network_list_ip(network_ip, profile->local_network) ? sub_to_host : profile->extsipip); contact = sofia_glue_get_url_from_contact(o_contact, 1); + + if (sofia_test_pflag(profile, PFLAG_AUTO_NAT) && !switch_check_network_list_ip(network_ip, profile->local_network)) { + char *ptr = NULL; + if ((ptr = sofia_glue_find_parameter(o_contact, "transport="))) { + sofia_transport_t transport = sofia_glue_str2transport(ptr); + user_via = switch_mprintf("SIP/2.0/%s %s;rport", sofia_glue_transport2str(transport), profile->extsipip); + printf("user_via -> %s\n", user_via); + } else { + user_via = switch_mprintf("SIP/2.0/UDP %s;rport", profile->extsipip); + } + + contact_str = profile->public_url; + } else { + contact_str = profile->url; + } if ((route = strstr(contact, ";fs_path=")) && (route = strdup(route + 9))) { for (p = route; p && *p ; p++) { @@ -1455,17 +1472,23 @@ } } - nh = nua_handle(profile->nua, NULL, NUTAG_URL(contact), SIPTAG_FROM_STR(id), SIPTAG_TO_STR(id), SIPTAG_CONTACT_STR(h->profile->url), TAG_END()); + nh = nua_handle(profile->nua, NULL, NUTAG_URL(contact), + SIPTAG_FROM_STR(id), SIPTAG_TO_STR(id), + SIPTAG_CONTACT_STR(contact_str), TAG_END()); nua_handle_bind(nh, &mod_sofia_globals.destroy_private); nua_notify(nh, NUTAG_NEWSUB(1), TAG_IF(route_uri, NUTAG_PROXY(route_uri)), - SIPTAG_EVENT_STR(event), SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"), SIPTAG_PAYLOAD_STR(body), TAG_END()); + TAG_IF(!switch_strlen_zero(user_via), SIPTAG_VIA_STR(user_via)), + SIPTAG_EVENT_STR(event), + SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"), + SIPTAG_PAYLOAD_STR(body), TAG_END()); switch_safe_free(contact); switch_safe_free(id); switch_safe_free(route); + switch_safe_free(user_via); if (ext_profile) { sofia_glue_release_profile(ext_profile); } @@ -1508,6 +1531,7 @@ char *port; char new_port[25] = ""; char *is_nat = NULL; + int is_auto_nat = 0; const char *ipv6; if (!(contact && sip->sip_contact->m_url)) { @@ -1518,6 +1542,10 @@ get_addr(network_ip, sizeof(network_ip), my_addrinfo->ai_addr, my_addrinfo->ai_addrlen); network_port = ntohs(((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_port); + if (sofia_test_pflag(profile, PFLAG_AUTO_NAT) && !switch_check_network_list_ip(network_ip, profile->local_network)) { + is_auto_nat = 1; + } + tl_gets(tags, NUTAG_SUBSTATE_REF(sub_state), TAG_END()); event = sip_header_as_string(profile->home, (void *) sip->sip_event); @@ -1777,25 +1805,41 @@ network_port, params); } + + + if (is_auto_nat) { + contactstr = profile->public_url; + } else { + contactstr = profile->url; + } + if (switch_stristr("port=tcp", contact->m_url->url_params)) { - contactstr = profile->tcp_contact; + if (is_auto_nat) { + contactstr = profile->tcp_public_contact; + } else { + contactstr = profile->tcp_contact; + } } else if (switch_stristr("port=tls", contact->m_url->url_params)) { - contactstr = profile->tls_contact; + if (is_auto_nat) { + contactstr = profile->tls_contact; + } else { + contactstr = profile->tls_public_contact; + } } - if (nh && nh->nh_ds && nh->nh_ds->ds_usage) { nua_dialog_usage_set_refresh_range(nh->nh_ds->ds_usage, exp_delta + SUB_OVERLAP, exp_delta + SUB_OVERLAP); } - nua_respond(nh, SIP_202_ACCEPTED, SIPTAG_CONTACT_STR(contactstr), NUTAG_WITH_THIS(nua), + nua_respond(nh, SIP_202_ACCEPTED, + SIPTAG_CONTACT_STR(contactstr), + NUTAG_WITH_THIS(nua), SIPTAG_SUBSCRIPTION_STATE_STR(sstr), SIPTAG_EXPIRES_STR(exp_delta_str), TAG_IF(sticky, NUTAG_PROXY(sticky)), TAG_END()); switch_safe_free(sticky); - } sent_reply++; Modified: freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/sofia_sla.c ============================================================================== --- freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/sofia_sla.c (original) +++ freeswitch/branches/brian/trunk/src/mod/endpoints/mod_sofia/sofia_sla.c Tue Jun 2 16:02:47 2009 @@ -76,6 +76,12 @@ struct sla_helper sh = { { 0 } }; char *contact_str = strip_uri(full_contact); sofia_transport_t transport = sofia_glue_url2transport(sip->sip_contact->m_url); + su_addrinfo_t *my_addrinfo = msg_addrinfo(nua_current_request(nua)); + char network_ip[80]; + int network_port = 0; + + get_addr(network_ip, sizeof(network_ip), my_addrinfo->ai_addr, my_addrinfo->ai_addrlen); + network_port = ntohs(((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_port); sql = switch_mprintf("select call_id from sip_shared_appearance_dialogs where hostname='%q' and profile_name='%q' and contact_str='%q'", mod_sofia_globals.hostname, profile->name, contact_str); @@ -99,8 +105,13 @@ nua_handle_bind(nh, &mod_sofia_globals.keep_private); switch_snprintf(exp_str, sizeof(exp_str), "%ld", exptime + 30); - switch_snprintf(my_contact, sizeof(my_contact), "<%s;transport=%s>;expires=%s", profile->sla_contact, sofia_glue_transport2str(transport), exp_str); - + if (sofia_test_pflag(profile, PFLAG_AUTO_NAT) && !switch_check_network_list_ip(network_ip, profile->local_network)) { + switch_snprintf(my_contact, sizeof(my_contact), "<sip:%s@%s;transport=%s>;expires=%s", profile->sla_contact, + profile->extsipip, sofia_glue_transport2str(transport), exp_str); + } else { + switch_snprintf(my_contact, sizeof(my_contact), "<sip:%s@%s;transport=%s>;expires=%s", profile->sla_contact, + profile->sipip, sofia_glue_transport2str(transport), exp_str); + } nua_subscribe(nh, SIPTAG_TO(sip->sip_to), SIPTAG_FROM(sip->sip_to), @@ -125,8 +136,14 @@ char *sql = NULL; char *route_uri = NULL; char *sla_contact = NULL; + su_addrinfo_t *my_addrinfo = msg_addrinfo(nua_current_request(nua)); + char network_ip[80]; + int network_port = 0; sofia_transport_t transport = sofia_glue_url2transport(sip->sip_contact->m_url); + + get_addr(network_ip, sizeof(network_ip), my_addrinfo->ai_addr, my_addrinfo->ai_addrlen); + network_port = ntohs(((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_port); /* * XXX MTK FIXME - we don't look at the tag to see if NUTAG_SUBSTATE(nua_substate_terminated) or * a Subscription-State header with state "terminated" and/or expiration of 0. So we never forget @@ -187,8 +204,12 @@ *p++ = '\0'; } } - - sla_contact = switch_mprintf("<%s;transport=%s>", profile->sla_contact, sofia_glue_transport2str(transport)); + + if (sofia_test_pflag(profile, PFLAG_AUTO_NAT) && !switch_check_network_list_ip(network_ip, profile->local_network)) { + sla_contact = switch_mprintf("<sip:%s@%s;transport=%s>", profile->sla_contact, profile->extsipip, sofia_glue_transport2str(transport)); + } else { + sla_contact = switch_mprintf("<sip:%s@%s;transport=%s>", profile->sla_contact, profile->extsipip, sofia_glue_transport2str(transport)); + } nua_respond(nh, SIP_202_ACCEPTED, SIPTAG_CONTACT_STR(sla_contact), NUTAG_WITH_THIS(nua), TAG_IF(route_uri, NUTAG_PROXY(route_uri)),
participants (1)
-
FreeSWITCH SVN