提交 093dc6b4 authored 作者: Michael Jerris's avatar Michael Jerris

refactor of sip_i_invite. Much more error handling of different missing data on…

refactor of sip_i_invite.  Much more error handling of different missing data on the inbound invite.  Some minor changes in behavior.  Chanvars are now not set for vars we don't have.  the channel name will now include :port (the full uri as we create it from the data available), display name is now unknown not service if there is not one available.  Added contact uri as a chan var like all the others, the channel name if there is no user portion of the from will not have a from part of service, it will have no user part or @.  The contact will now be used for the channel name if there is no from header in the invite.

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@4388 d0543943-73ff-0310-b7d9-9358b9ac24b2
上级 f2e482a7
...@@ -358,7 +358,7 @@ static void tech_set_codecs(private_object_t *tech_pvt); ...@@ -358,7 +358,7 @@ static void tech_set_codecs(private_object_t *tech_pvt);
static void attach_private(switch_core_session_t *session, static void attach_private(switch_core_session_t *session,
sofia_profile_t *profile, sofia_profile_t *profile,
private_object_t *tech_pvt, private_object_t *tech_pvt,
char *channame); const char *channame);
static void terminate_session(switch_core_session_t **session, switch_call_cause_t cause, int line); static void terminate_session(switch_core_session_t **session, switch_call_cause_t cause, int line);
...@@ -843,7 +843,7 @@ static void tech_set_codecs(private_object_t *tech_pvt) ...@@ -843,7 +843,7 @@ static void tech_set_codecs(private_object_t *tech_pvt)
static void attach_private(switch_core_session_t *session, static void attach_private(switch_core_session_t *session,
sofia_profile_t *profile, sofia_profile_t *profile,
private_object_t *tech_pvt, private_object_t *tech_pvt,
char *channame) const char *channame)
{ {
switch_channel_t *channel; switch_channel_t *channel;
char name[256]; char name[256];
...@@ -4231,6 +4231,88 @@ static void sip_i_info(nua_t *nua, ...@@ -4231,6 +4231,88 @@ static void sip_i_info(nua_t *nua,
return; return;
} }
#define url_set_chanvars(session, url, varprefix) _url_set_chanvars(session, url, #varprefix "_user", #varprefix "_host", #varprefix "_port", #varprefix "_uri")
static const char * _url_set_chanvars(switch_core_session_t *session, url_t *url, const char * user_var, const char * host_var, const char * port_var, const char * uri_var)
{
const char *user = NULL, *host = NULL, *port = NULL;
char *uri = NULL;
switch_channel_t *channel = switch_core_session_get_channel(session);
if (url) {
user = url->url_user;
host = url->url_host;
port = url->url_port;
}
if (user) {
switch_channel_set_variable(channel, user_var, user);
}
if (!port) {
port = "5060";
}
switch_channel_set_variable(channel, port_var, port);
if (host) {
if (user) {
uri = switch_core_session_sprintf(session, "%s@%s:%s", user, host, port);
} else {
uri = switch_core_session_sprintf(session, "%s:%s", host, port);
}
switch_channel_set_variable_nodup(channel, uri_var, uri);
switch_channel_set_variable(channel, host_var, host);
}
return uri;
}
static void process_rpid(sip_unknown_t *un, private_object_t *tech_pvt)
{
int argc, x, screen = 1;
char *mydata, *argv[10] = { 0 };
if (!switch_strlen_zero(un->un_value)) {
if ((mydata = strdup(un->un_value))) {
argc = switch_separate_string(mydata, ';', argv, (sizeof(argv) / sizeof(argv[0])));
// Do We really need this at this time
// clid_uri = argv[0];
for (x=1; x < argc && argv[x]; x++){
// we dont need to do anything with party yet we should only be seeing party=calling here anyway
// maybe thats a dangerous assumption bit oh well yell at me later
// if (!strncasecmp(argv[x], "party", 5)) {
// party = argv[x];
// } else
if (!strncasecmp(argv[x], "privacy=", 8)) {
char *arg = argv[x] + 9;
if (!strcasecmp(arg, "yes")) {
switch_set_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NAME | SWITCH_CPF_HIDE_NUMBER);
} else if (!strcasecmp(arg, "full")) {
switch_set_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NAME | SWITCH_CPF_HIDE_NUMBER);
} else if (!strcasecmp(arg, "name")) {
switch_set_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NAME);
} else if (!strcasecmp(arg, "number")) {
switch_set_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NUMBER);
} else {
switch_clear_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NAME);
switch_clear_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NUMBER);
}
} else if (!strncasecmp(argv[x], "screen=", 7) && screen > 0) {
char *arg = argv[x] + 8;
if (!strcasecmp(arg, "no")) {
screen = 0;
switch_clear_flag(tech_pvt->caller_profile, SWITCH_CPF_SCREEN);
}
}
}
free(mydata);
}
}
}
static void sip_i_invite(nua_t *nua, static void sip_i_invite(nua_t *nua,
sofia_profile_t *profile, sofia_profile_t *profile,
nua_handle_t *nh, nua_handle_t *nh,
...@@ -4243,21 +4325,20 @@ static void sip_i_invite(nua_t *nua, ...@@ -4243,21 +4325,20 @@ static void sip_i_invite(nua_t *nua,
sip_unknown_t *un; sip_unknown_t *un;
private_object_t *tech_pvt = NULL; private_object_t *tech_pvt = NULL;
switch_channel_t *channel = NULL; switch_channel_t *channel = NULL;
sip_from_t const *from = sip->sip_from; const char *channel_name = NULL;
sip_to_t const *to = sip->sip_to; const char *displayname = NULL;
char *displayname; const char *destination_number = NULL;
char *username, *req_username = NULL; const char *from_user = NULL, *from_host = NULL;
char *url_user = (char *) from->a_url->url_user; const char *context;
char *to_user, *to_host, *to_port;
char *req_user, *req_host, *req_port;
char *contact_user, *contact_host, *contact_port;
char *via_rport, *via_host, *via_port;
char *from_port;
char uri[1024];
char network_ip[80]; char network_ip[80];
if (!sip) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received an invite callback with no packet!\n");
nua_respond(nh, SIP_500_INTERNAL_SERVER_ERROR, TAG_END());
return;
}
if (!(sip && sip->sip_contact && sip->sip_contact->m_url)) { if (!(sip->sip_contact && sip->sip_contact->m_url)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NO CONTACT!\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NO CONTACT!\n");
nua_respond(nh, 400, "Missing Contact Header", TAG_END()); nua_respond(nh, 400, "Missing Contact Header", TAG_END());
return; return;
...@@ -4287,56 +4368,61 @@ static void sip_i_invite(nua_t *nua, ...@@ -4287,56 +4368,61 @@ static void sip_i_invite(nua_t *nua,
get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *)msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_addr); get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *)msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_addr);
channel = switch_core_session_get_channel(session);
if (sip->sip_from && sip->sip_from->a_url) {
from_user = sip->sip_from->a_url->url_user;
from_host = sip->sip_from->a_url->url_host;
channel_name = url_set_chanvars(session, sip->sip_from->a_url, "sip_from");
to_user = (char *) to->a_url->url_user; if (!switch_strlen_zero(from_user)) {
to_host = (char *) to->a_url->url_host; if (*from_user == '+') {
if (!(to_port = (char *) to->a_url->url_port)) { switch_channel_set_variable(channel, "sip_from_user_stripped", (const char *)(from_user+1));
to_port = "5060"; } else {
switch_channel_set_variable(channel, "sip_from_user_stripped", from_user);
}
} }
if (switch_strlen_zero(to_user)) { /* if sofia doesnt parse the To: right, we'll have to do it */ if (!switch_strlen_zero(sip->sip_from->a_display)) {
if ((to_user = sip_header_as_string(tech_pvt->home, (sip_header_t *) to))) { char *tmp;
tmp = switch_core_session_strdup(session, sip->sip_from->a_display);
if (*tmp == '"') {
char *p; char *p;
if (*to_user == '<') {
to_user++; tmp++;
} if ((p = strchr(tmp, '"'))) {
if ((p = strchr((to_user += 4), '@'))) {
*p++ = '\0';
to_host = p;
if ((p = strchr(to_host, '>'))) {
*p = '\0'; *p = '\0';
} }
} }
displayname = tmp;
} else {
displayname = switch_strlen_zero(from_user) ? "unkonwn" : from_user;
} }
} }
if (switch_strlen_zero(url_user)) { if (sip->sip_request && sip->sip_request->rq_url) {
url_user = "service"; const char * req_uri = url_set_chanvars(session, sip->sip_request->rq_url, "sip_req");
} if (profile->pflags & PFLAG_FULL_ID) {
destination_number = req_uri;
if (!switch_strlen_zero(from->a_display)) { } else {
displayname = switch_core_session_strdup(session, (char *) from->a_display); destination_number = sip->sip_request->rq_url->url_user;
if (*displayname == '"') {
char *p;
displayname++;
if ((p = strchr(displayname, '"'))) {
*p = '\0';
} }
} }
} else {
displayname = url_user; if (sip->sip_to && sip->sip_to->a_url) {
url_set_chanvars(session, sip->sip_to->a_url, "sip_to");
} }
if (!(username = switch_mprintf("%s@%s", url_user, (char *) from->a_url->url_host))) { if (sip->sip_contact && sip->sip_contact->m_url) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); const char *contact_uri = url_set_chanvars(session, sip->sip_contact->m_url, "sip_contact");
return; if (!channel_name) {
channel_name = contact_uri;
}
} }
attach_private(session, profile, tech_pvt, username); attach_private(session, profile, tech_pvt, channel_name);
tech_set_codecs(tech_pvt); tech_set_codecs(tech_pvt);
channel = switch_core_session_get_channel(session);
switch_channel_set_variable(channel, "endpoint_disposition", "INBOUND CALL"); switch_channel_set_variable(channel, "endpoint_disposition", "INBOUND CALL");
set_chat_hash(tech_pvt, sip); set_chat_hash(tech_pvt, sip);
...@@ -4345,162 +4431,58 @@ static void sip_i_invite(nua_t *nua, ...@@ -4345,162 +4431,58 @@ static void sip_i_invite(nua_t *nua,
switch_channel_set_flag(channel, CF_NOMEDIA); switch_channel_set_flag(channel, CF_NOMEDIA);
} }
if (!tech_pvt->call_id && sip->sip_call_id && sip->sip_call_id->i_id) {
switch_channel_set_variable(channel, "sip_from_user", from->a_url->url_user); tech_pvt->call_id = switch_core_session_strdup(session, sip->sip_call_id->i_id);
if (from->a_url->url_user && *from->a_url->url_user == '+') { switch_channel_set_variable(channel, "sip_call_id", tech_pvt->call_id);
switch_channel_set_variable(channel, "sip_from_user_stripped", (char *)(from->a_url->url_user+1));
} else {
switch_channel_set_variable(channel, "sip_from_user_stripped", from->a_url->url_user);
}
switch_channel_set_variable(channel, "sip_from_host", from->a_url->url_host);
if (!(from_port = (char *) from->a_url->url_port)) {
from_port = "5060";
}
switch_channel_set_variable(channel, "sip_from_port", from_port);
snprintf(uri, sizeof(uri), "%s@%s:%s", from->a_url->url_user, from->a_url->url_host, from_port);
switch_channel_set_variable(channel, "sip_from_uri", uri);
switch_channel_set_variable(channel, "sip_to_user", to_user);
switch_channel_set_variable(channel, "sip_to_host", to_host);
switch_channel_set_variable(channel, "sip_to_port", to_port);
snprintf(uri, sizeof(uri), "%s@%s:%s", to_user, to_host, to_port);
switch_channel_set_variable(channel, "sip_to_uri", uri);
req_user = (char *) sip->sip_request->rq_url->url_user;
req_host = (char *) sip->sip_request->rq_url->url_host;
if (!(req_port = (char *) sip->sip_request->rq_url->url_port)) {
req_port = "5060";
} }
switch_channel_set_variable(channel, "sip_req_user", req_user); if (sip->sip_via) {
switch_channel_set_variable(channel, "sip_req_host", req_host); if (sip->sip_via->v_host) {
switch_channel_set_variable(channel, "sip_req_port", req_port); switch_channel_set_variable(channel, "sip_via_host", sip->sip_via->v_host);
if (profile->pflags & PFLAG_FULL_ID) {
if (req_user) {
if (!(req_username = switch_mprintf("%s@%s:%s", req_user, req_host, req_port))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
switch_safe_free(username);
return;
} }
} else { if (sip->sip_via->v_port) {
if (!(req_username = switch_mprintf("%s:%s", req_host, req_port))) { switch_channel_set_variable(channel, "sip_via_port", sip->sip_via->v_port);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
switch_safe_free(username);
return;
} }
if (sip->sip_via->v_rport) {
switch_channel_set_variable(channel, "sip_via_rport", sip->sip_via->v_rport);
} }
} }
contact_user = (char *) sip->sip_contact->m_url->url_user; if (sip->sip_max_forwards) {
contact_host = (char *) sip->sip_contact->m_url->url_host; char max_forwards[32];
if (!(contact_port = (char *) sip->sip_contact->m_url->url_port)) { snprintf(max_forwards, sizeof(max_forwards), "%u", sip->sip_max_forwards->mf_count);
contact_port = "5060"; switch_channel_set_variable(channel, SWITCH_MAX_FORWARDS_VARIABLE, max_forwards);
}
switch_channel_set_variable(channel, "sip_contact_user", contact_user);
switch_channel_set_variable(channel, "sip_contact_host", contact_host);
switch_channel_set_variable(channel, "sip_contact_port", contact_port);
if (!tech_pvt->call_id && sip && sip->sip_call_id && sip->sip_call_id->i_id) {
tech_pvt->call_id = switch_core_session_strdup(session, sip->sip_call_id->i_id);
switch_channel_set_variable(channel, "sip_call_id", tech_pvt->call_id);
}
via_host = (char *) sip->sip_via->v_host;
if (!(via_port = (char *) sip->sip_via->v_port)) {
via_port = "5060";
}
if (!(via_rport = (char *) sip->sip_via->v_rport)) {
via_rport = "5060";
} }
switch_channel_set_variable(channel, "sip_via_host", via_host); if (profile->context && !strcasecmp(profile->context, "_domain_")) {
switch_channel_set_variable(channel, "sip_via_port", via_port); context = from_host;
switch_channel_set_variable(channel, "sip_via_rport", via_rport); } else {
context = profile->context;
snprintf(uri, sizeof(uri), "%s@%s:%s", req_user, req_host, req_port);
switch_channel_set_variable(channel, "sip_req_uri", uri);
if (sip->sip_max_forwards) {
snprintf(uri, sizeof(uri), "%u", sip->sip_max_forwards->mf_count);
switch_channel_set_variable(channel, SWITCH_MAX_FORWARDS_VARIABLE, uri);
} }
if ((tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session), tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
(char *) from->a_url->url_user, from_user,
profile->dialplan, profile->dialplan,
displayname, displayname,
(char *) from->a_url->url_user, from_user,
network_ip, network_ip,
NULL, NULL,
NULL, NULL,
NULL, NULL,
(char *)modname, modname,
(profile->context && !strcasecmp(profile->context, "_domain_")) ? context,
(char *) from->a_url->url_host : profile->context, destination_number);
req_username ? req_username : req_user ? (char *) req_user : ""
)) != 0) {
if (tech_pvt->caller_profile) {
/* Loop thru unknown Headers Here so we can do something with them */
for (un=sip->sip_unknown; un; un=un->un_next) { for (un=sip->sip_unknown; un; un=un->un_next) {
if (!strncasecmp(un->un_name, "Alert-Info", 10)) { if (!strncasecmp(un->un_name, "Alert-Info", 10)) {
if (!switch_strlen_zero(un->un_value)) { if (!switch_strlen_zero(un->un_value)) {
switch_channel_set_variable(channel, "alert_info", (char *)un->un_value); switch_channel_set_variable(channel, "alert_info", un->un_value);
} }
// Loop thru Known Headers Here so we can do something with them
} else if (!strncasecmp(un->un_name, "Remote-Party-ID", 15)) { } else if (!strncasecmp(un->un_name, "Remote-Party-ID", 15)) {
int argc, x, screen = 1; process_rpid(un, tech_pvt);
char *mydata, *argv[10] = { 0 };
if (!switch_strlen_zero(un->un_value)) {
if ((mydata = strdup(un->un_value))) {
argc = switch_separate_string(mydata, ';', argv, (sizeof(argv) / sizeof(argv[0])));
// Do We really need this at this time
// clid_uri = argv[0];
for (x=1; x < argc && argv[x]; x++){
// we dont need to do anything with party yet we should only be seeing party=calling here anyway
// maybe thats a dangerous assumption bit oh well yell at me later
// if (!strncasecmp(argv[x], "party", 5)) {
// party = argv[x];
// } else
if (!strncasecmp(argv[x], "privacy=", 8)) {
char *arg = argv[x] + 9;
if (!strcasecmp(arg, "yes")) {
switch_set_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NAME | SWITCH_CPF_HIDE_NUMBER);
} else if (!strcasecmp(arg, "full")) {
switch_set_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NAME | SWITCH_CPF_HIDE_NUMBER);
} else if (!strcasecmp(arg, "name")) {
switch_set_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NAME);
} else if (!strcasecmp(arg, "number")) {
switch_set_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NUMBER);
} else {
switch_clear_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NAME);
switch_clear_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NUMBER);
}
} else if (!strncasecmp(argv[x], "screen=", 7) && screen > 0) {
char *arg = argv[x] + 8;
if (!strcasecmp(arg, "no")) {
screen = 0;
switch_clear_flag(tech_pvt->caller_profile, SWITCH_CPF_SCREEN);
}
}
}
free(mydata);
}
}
} else if (!strncasecmp(un->un_name, "X-", 2)) { } else if (!strncasecmp(un->un_name, "X-", 2)) {
if (!switch_strlen_zero(un->un_value)) { if (!switch_strlen_zero(un->un_value)) {
char *new_name; char *new_name;
...@@ -4513,8 +4495,6 @@ static void sip_i_invite(nua_t *nua, ...@@ -4513,8 +4495,6 @@ static void sip_i_invite(nua_t *nua,
} }
switch_channel_set_caller_profile(channel, tech_pvt->caller_profile); switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
switch_safe_free(username);
switch_safe_free(req_username);
} }
if (!(tech_pvt->sofia_private = malloc(sizeof(*tech_pvt->sofia_private)))) { if (!(tech_pvt->sofia_private = malloc(sizeof(*tech_pvt->sofia_private)))) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论