提交 1dd780e6 authored 作者: Michael Jerris's avatar Michael Jerris

merge sip nat improvements from branches/brian

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@13594 d0543943-73ff-0310-b7d9-9358b9ac24b2
上级 b28bd6b9
......@@ -394,6 +394,7 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
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 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
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 {
......@@ -2694,6 +2694,8 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
}
}
sofia_glue_get_user_host(switch_core_session_strdup(nsession, tech_pvt->dest), NULL, &tech_pvt->remote_ip);
if (dest_to) {
if (strchr(dest_to, '@')) {
tech_pvt->dest_to = switch_core_session_sprintf(nsession, "sip:%s", dest_to);
......@@ -3217,6 +3219,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
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);
......
......@@ -192,6 +192,7 @@ typedef enum {
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 @@ struct mod_sofia_globals {
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 @@ struct sofia_profile {
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;
......@@ -430,8 +436,8 @@ struct sofia_profile {
sofia_cid_type_t cid_type;
sofia_dtmf_t dtmf_type;
int auto_restart;
int sip_port;
int tls_sip_port;
switch_port_t sip_port;
switch_port_t tls_sip_port;
int tls_version;
char *codec_string;
int running;
......@@ -489,6 +495,7 @@ struct sofia_profile {
uint32_t timer_t2;
uint32_t timer_t4;
char *contact_user;
char *local_network;
};
struct private_object {
......@@ -613,6 +620,7 @@ struct private_object {
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 {
......@@ -822,7 +830,9 @@ 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);
char *sofia_glue_create_via(switch_core_session_t *session, const char *ip, switch_port_t port, sofia_transport_t transport);
char *sofia_glue_create_external_via(switch_core_session_t *session, sofia_profile_t *profile, sofia_transport_t transport);
int sofia_glue_check_nat(sofia_profile_t *profile, const char *network_ip);
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);
switch_status_t sofia_glue_build_crypto(private_object_t *tech_pvt, int index, switch_rtp_crypto_key_type_t type, switch_rtp_crypto_direction_t direction);
......@@ -835,7 +845,7 @@ switch_status_t sofia_glue_tech_set_video_codec(private_object_t *tech_pvt, int
const char *sofia_glue_strip_proto(const char *uri);
switch_status_t reconfig_sofia(sofia_profile_t *profile);
void sofia_glue_del_gateway(sofia_gateway_t *gp);
void sofia_reg_send_reboot(sofia_profile_t *profile, const char *user, const char *host, const char *contact, const char *user_agent);
void sofia_reg_send_reboot(sofia_profile_t *profile, const char *user, const char *host, const char *contact, const char *user_agent, const char *network_ip);
void sofia_glue_restart_all_profiles(void);
void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly);
const char * sofia_state_string(int state);
......@@ -877,3 +887,4 @@ int sofia_get_loglevel(const char *name);
sofia_cid_type_t sofia_cid_name2type(const char *name);
void sofia_glue_tech_set_local_sdp(private_object_t *tech_pvt, const char *sdp_str, switch_bool_t dup);
void sofia_glue_set_rtp_stats(private_object_t *tech_pvt);
void sofia_glue_get_addr(msg_t *msg, char *buf, size_t buflen, int *port);
......@@ -375,11 +375,11 @@ 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,'%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);
}
......@@ -1401,13 +1401,14 @@ static int sofia_presence_mwi_callback2(void *pArg, int argc, char **argv, char
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 +1416,41 @@ static int sofia_presence_mwi_callback2(void *pArg, int argc, char **argv, char
}
}
id = switch_mprintf("sip:%s@%s", sub_to_user, sub_to_host);
contact = sofia_glue_get_url_from_contact(o_contact, 1);
if (sofia_test_pflag(profile, PFLAG_AUTO_NAT) && profile->local_network &&
!switch_check_network_list_ip(network_ip, profile->local_network)) {
char *ptr = NULL;
const char *transport_str = NULL;
id = switch_mprintf("sip:%s@%s", sub_to_user, profile->extsipip);
if ((ptr = sofia_glue_find_parameter(o_contact, "transport="))) {
sofia_transport_t transport = sofia_glue_str2transport(ptr);
transport_str = sofia_glue_transport2str(transport);
switch (transport) {
case SOFIA_TRANSPORT_TCP:
contact_str = profile->tcp_public_contact;
break;
case SOFIA_TRANSPORT_TCP_TLS:
contact_str = profile->tls_public_contact;
break;
default:
contact_str = profile->public_url;
break;
}
user_via = sofia_glue_create_external_via(NULL, profile, transport);
} else {
user_via = sofia_glue_create_external_via(NULL, profile, SOFIA_TRANSPORT_UDP);
contact_str = profile->public_url;
}
} else {
contact_str = profile->url;
id = switch_mprintf("sip:%s@%s", sub_to_user, sub_to_host);
}
if ((route = strstr(contact, ";fs_path=")) && (route = strdup(route + 9))) {
for (p = route; p && *p ; p++) {
......@@ -1455,17 +1488,24 @@ static int sofia_presence_mwi_callback2(void *pArg, int argc, char **argv, char
}
}
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(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);
}
......@@ -1501,13 +1541,13 @@ void sofia_presence_handle_sip_i_subscribe(int status,
switch_event_t *sevent;
int sub_state;
int sent_reply = 0;
su_addrinfo_t *my_addrinfo = msg_addrinfo(nua_current_request(nua));
int network_port = 0;
char network_ip[80];
const char *contact_host, *contact_user;
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)) {
......@@ -1515,8 +1555,12 @@ void sofia_presence_handle_sip_i_subscribe(int status,
return;
}
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);
sofia_glue_get_addr(nua_current_request(nua), network_ip, sizeof(network_ip), &network_port);
if (sofia_test_pflag(profile, PFLAG_AUTO_NAT) && profile->local_network &&
!switch_check_network_list_ip(network_ip, profile->local_network)) {
is_auto_nat = 1;
}
tl_gets(tags, NUTAG_SUBSTATE_REF(sub_state), TAG_END());
......@@ -1777,19 +1821,35 @@ void sofia_presence_handle_sip_i_subscribe(int status,
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());
......
......@@ -402,11 +402,13 @@ int sofia_sub_del_callback(void *pArg, int argc, char **argv, char **columnNames
return 0;
}
void sofia_reg_send_reboot(sofia_profile_t *profile, const char *user, const char *host, const char *contact, const char *user_agent)
void sofia_reg_send_reboot(sofia_profile_t *profile, const char *user, const char *host, const char *contact, const char *user_agent, const char *network_ip)
{
const char *event = "check-sync";
nua_handle_t *nh;
char *contact_url = NULL;
char *contact_str = NULL;
char *user_via = NULL;
char *id = NULL;
if (switch_stristr("snom", user_agent)) {
......@@ -417,22 +419,52 @@ void sofia_reg_send_reboot(sofia_profile_t *profile, const char *user, const cha
if ((contact_url = sofia_glue_get_url_from_contact((char *)contact, 1))) {
char *p;
id = switch_mprintf("sip:%s@%s", user, host);
id = switch_mprintf("sip:%s@%s", user, network_ip);
if ((p = strstr(contact_url, ";fs_"))) {
*p = '\0';
}
if (sofia_glue_check_nat(profile, network_ip)) {
char *ptr = NULL;
const char *transport_str = NULL;
if ((ptr = sofia_glue_find_parameter(contact_url, "transport="))) {
sofia_transport_t transport = sofia_glue_str2transport(ptr);
transport_str = sofia_glue_transport2str(transport);
switch (transport) {
case SOFIA_TRANSPORT_TCP:
contact_str = profile->tcp_public_contact;
break;
case SOFIA_TRANSPORT_TCP_TLS:
contact_str = profile->tls_public_contact;
break;
default:
contact_str = profile->public_url;
break;
}
user_via = sofia_glue_create_external_via(NULL, profile, transport);
} else {
user_via = sofia_glue_create_external_via(NULL, profile, SOFIA_TRANSPORT_UDP);
contact_str = profile->public_url;
}
} else {
contact_str = profile->url;
}
nh = nua_handle(profile->nua, NULL,
NUTAG_URL(contact_url),
SIPTAG_FROM_STR(id),
SIPTAG_TO_STR(id),
SIPTAG_CONTACT_STR(profile->url),
SIPTAG_CONTACT_STR(contact_str),
TAG_END());
nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
nua_notify(nh,
NUTAG_NEWSUB(1),
TAG_IF(user_via, SIPTAG_VIA_STR(user_via)),
SIPTAG_EVENT_STR(event),
SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"),
SIPTAG_PAYLOAD_STR(""),
......@@ -442,6 +474,7 @@ void sofia_reg_send_reboot(sofia_profile_t *profile, const char *user, const cha
free(contact_url);
}
switch_safe_free(user_via);
switch_safe_free(id);
}
......@@ -462,8 +495,8 @@ int sofia_reg_del_callback(void *pArg, int argc, char **argv, char **columnNames
switch_event_t *s_event;
sofia_profile_t *profile = (sofia_profile_t *) pArg;
if (argc > 11 && atoi(argv[11]) == 1) {
sofia_reg_send_reboot(profile, argv[1], argv[2], argv[3], argv[7]);
if (argc > 12 && atoi(argv[12]) == 1) {
sofia_reg_send_reboot(profile, argv[1], argv[2], argv[3], argv[7], argv[11]);
}
if (argc >= 3) {
......@@ -508,7 +541,8 @@ void sofia_reg_expire_call_id(sofia_profile_t *profile, const char *call_id, int
switch_snprintf(sqlextra, sizeof(sqlextra), " or (sip_user='%s' and sip_host='%s')", user, host);
}
switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid,expires,user_agent,server_user,server_host,profile_name"
switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid,expires"
",user_agent,server_user,server_host,profile_name,network_ip"
",%d from sip_registrations where call_id='%s' %s",
reboot, call_id, sqlextra);
......@@ -548,10 +582,12 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
switch_mutex_lock(profile->ireg_mutex);
if (now) {
switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid,expires,user_agent,server_user,server_host,profile_name"
switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid,expires"
",user_agent,server_user,server_host,profile_name,network_ip"
",%d from sip_registrations where expires > 0 and expires <= %ld", reboot, (long) now);
} else {
switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid,expires,user_agent,server_user,server_host,profile_name"
switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid,expires"
",user_agent,server_user,server_host,profile_name,network_ip"
",%d from sip_registrations where expires > 0", reboot);
}
......@@ -725,19 +761,17 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
char *force_user;
char received_data[128] = "";
char *path_val = NULL;
su_addrinfo_t *my_addrinfo = msg_addrinfo(nua_current_request(nua));
switch_event_t *auth_params = NULL;
int r = 0;
/* all callers must confirm that sip, sip->sip_request and sip->sip_contact are not NULL */
switch_assert(sip != NULL && sip->sip_contact != NULL && sip->sip_request != NULL);
get_addr(network_ip, sizeof(network_ip), my_addrinfo->ai_addr,my_addrinfo->ai_addrlen);
network_port = get_port(my_addrinfo->ai_addr);
sofia_glue_get_addr(nua_current_request(nua), network_ip, sizeof(network_ip), &network_port);
snprintf(network_port_c, sizeof(network_port_c), "%d", network_port);
snprintf(url_ip, sizeof(url_ip), my_addrinfo->ai_addr->sa_family == AF_INET6 ? "[%s]" : "%s", network_ip);
snprintf(url_ip, sizeof(url_ip), (msg_addrinfo(nua_current_request(nua)))->ai_addr->sa_family == AF_INET6 ? "[%s]" : "%s", network_ip);
expires = sip->sip_expires;
authorization = sip->sip_authorization;
......@@ -1249,15 +1283,11 @@ void sofia_reg_handle_sip_i_register(nua_t *nua, sofia_profile_t *profile, nua_h
char key[128] = "";
switch_event_t *v_event = NULL;
char network_ip[80];
su_addrinfo_t *my_addrinfo = msg_addrinfo(nua_current_request(nua));
sofia_regtype_t type = REG_REGISTER;
int network_port = 0;
char *is_nat = NULL;
get_addr(network_ip, sizeof(network_ip), my_addrinfo->ai_addr, my_addrinfo->ai_addrlen);
network_port = get_port(msg_addrinfo(nua_current_request(nua))->ai_addr);
sofia_glue_get_addr(nua_current_request(nua), network_ip, sizeof(network_ip), &network_port);
if (!(sip->sip_contact && sip->sip_contact->m_url)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NO CONTACT!\n");
......
......@@ -76,6 +76,10 @@ void sofia_sla_handle_register(nua_t *nua, sofia_profile_t *profile, sip_t const
struct sla_helper sh = { { 0 } };
char *contact_str = strip_uri(full_contact);
sofia_transport_t transport = sofia_glue_url2transport(sip->sip_contact->m_url);
char network_ip[80];
int network_port = 0;
sofia_glue_get_addr(nua_current_request(nua), network_ip, sizeof(network_ip), &network_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 +103,13 @@ void sofia_sla_handle_register(nua_t *nua, sofia_profile_t *profile, sip_t const
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_glue_check_nat(profile, network_ip)) {
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 +134,11 @@ void sofia_sla_handle_sip_i_subscribe(nua_t *nua, const char *contact_str, sofia
char *sql = NULL;
char *route_uri = NULL;
char *sla_contact = NULL;
char network_ip[80];
int network_port = 0;
sofia_transport_t transport = sofia_glue_url2transport(sip->sip_contact->m_url);
sofia_glue_get_addr(nua_current_request(nua), network_ip, sizeof(network_ip), &network_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
......@@ -141,8 +153,9 @@ void sofia_sla_handle_sip_i_subscribe(nua_t *nua, const char *contact_str, sofia
* so we do what openser's pua_bla does and...
*/
/* We always store the AOR as the sipip and not the request so SLA works with NAT inside out */
aor = switch_mprintf("sip:%s@%s;transport=%s", sip->sip_contact->m_url->url_user,
sip->sip_from->a_url->url_host, sofia_glue_transport2str(transport));
profile->sipip, sofia_glue_transport2str(transport));
/*
* ok, and now that we HAVE the AOR, we REALLY should go check in the XML config and see if this particular
......@@ -163,9 +176,9 @@ void sofia_sla_handle_sip_i_subscribe(nua_t *nua, const char *contact_str, sofia
}
if ((sql =
switch_mprintf("insert into sip_shared_appearance_subscriptions (subscriber, call_id, aor, profile_name, hostname, contact_str) "
"values ('%q','%q','%q','%q','%q','%q')",
subscriber, sip->sip_call_id->i_id, aor, profile->name, mod_sofia_globals.hostname, contact_str))) {
switch_mprintf("insert into sip_shared_appearance_subscriptions (subscriber, call_id, aor, profile_name, hostname, contact_str, network_ip) "
"values ('%q','%q','%q','%q','%q','%q','%q')",
subscriber, sip->sip_call_id->i_id, aor, profile->name, mod_sofia_globals.hostname, contact_str, network_ip))) {
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
}
......@@ -187,8 +200,11 @@ void sofia_sla_handle_sip_i_subscribe(nua_t *nua, const char *contact_str, sofia
*p++ = '\0';
}
}
sla_contact = switch_mprintf("<%s;transport=%s>", profile->sla_contact, sofia_glue_transport2str(transport));
if (sofia_glue_check_nat(profile, network_ip)) {
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->sipip, 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)),
......@@ -276,8 +292,9 @@ void sofia_sla_handle_sip_i_notify(nua_t *nua, sofia_profile_t *profile, nua_han
}
/* calculate the AOR we're trying to tell people about. should probably double-check before derferencing XXX MTK */
/* We always store the AOR as the sipip and not the request so SLA works with NAT inside out */
aor = switch_mprintf("sip:%s@%s;transport=%s", sip->sip_to->a_url->url_user,
sip->sip_to->a_url->url_host, sofia_glue_transport2str(transport));
profile->sipip, sofia_glue_transport2str(transport));
/* this isn't sufficient because on things like the polycom, the subscriber is the 'main' ext number, but the
* 'main' ext number isn't in ANY of the headers they send us in the notify. of course.
......@@ -290,10 +307,9 @@ void sofia_sla_handle_sip_i_notify(nua_t *nua, sofia_profile_t *profile, nua_han
sip->sip_contact->m_url->url_host, sofia_glue_transport2str(transport));
if (sip->sip_payload && sip->sip_payload->pl_data) {
sql = switch_mprintf("select subscriber,call_id,aor,profile_name,hostname,contact_str from sip_shared_appearance_subscriptions where "
"aor='%q' and subscriber<>'%q' and profile_name='%q' and hostname='%q'",
aor, contact, profile->name, mod_sofia_globals.hostname);
sql = switch_mprintf("select subscriber,call_id,aor,profile_name,hostname,contact_str,network_ip from sip_shared_appearance_subscriptions where "
"aor='%q' and profile_name='%q' and hostname='%q'",
aor, profile->name, mod_sofia_globals.hostname);
helper.profile = profile;
helper.payload = sip->sip_payload->pl_data; /* could just send the WHOLE payload. you'd get the type that way. */
......@@ -316,10 +332,11 @@ static int sofia_sla_sub_callback(void *pArg, int argc, char **argv, char **colu
/* char *profile_name = argv[3]; */
/* char *hostname = argv[4]; */
char *contact_str = argv[5];
char *network_ip = argv[6];
nua_handle_t *nh;
char *route_uri = NULL;
char *xml_fixup = NULL;
char *fixup = NULL;
nh = nua_handle_by_call_id(helper->profile->nua, call_id); /* that's all you need to find the subscription's nh */
if (nh) {
......@@ -343,13 +360,27 @@ static int sofia_sla_sub_callback(void *pArg, int argc, char **argv, char **colu
}
}
if (sofia_test_pflag(helper->profile, PFLAG_AUTO_NAT)) {
if (sofia_glue_check_nat(helper->profile, network_ip)) {
fixup = switch_string_replace(helper->payload, helper->profile->sipip, helper->profile->extsipip);
} else {
fixup = switch_string_replace(helper->payload, helper->profile->extsipip, helper->profile->sipip);
}
xml_fixup = fixup;
} else {
xml_fixup = helper->payload;
}
nua_notify(nh,
SIPTAG_SUBSCRIPTION_STATE_STR("active;expires=300"), /* XXX MTK FIXME - this is totally fake calculation */
TAG_IF(route_uri, NUTAG_PROXY(route_uri)),
SIPTAG_CONTENT_TYPE_STR("application/dialog-info+xml"), /* could've just kept the type from the payload */
SIPTAG_PAYLOAD_STR(helper->payload),
SIPTAG_PAYLOAD_STR(xml_fixup),
TAG_END());
switch_safe_free(route_uri);
if (fixup && fixup != helper->payload) {
free(fixup);
}
}
return 0;
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论