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
This commit is contained in:
Michael Jerris 2007-02-25 16:53:17 +00:00
parent f2e482a7b4
commit 093dc6b4ef
1 changed files with 247 additions and 267 deletions

View File

@ -358,7 +358,7 @@ static void tech_set_codecs(private_object_t *tech_pvt);
static void attach_private(switch_core_session_t *session,
sofia_profile_t *profile,
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);
@ -843,7 +843,7 @@ static void tech_set_codecs(private_object_t *tech_pvt)
static void attach_private(switch_core_session_t *session,
sofia_profile_t *profile,
private_object_t *tech_pvt,
char *channame)
const char *channame)
{
switch_channel_t *channel;
char name[256];
@ -4231,234 +4231,44 @@ static void sip_i_info(nua_t *nua,
return;
}
static void sip_i_invite(nua_t *nua,
sofia_profile_t *profile,
nua_handle_t *nh,
sofia_private_t *sofia_private,
sip_t const *sip,
tagi_t tags[])
#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)
{
switch_core_session_t *session = NULL;
char key[128] = "";
sip_unknown_t *un;
private_object_t *tech_pvt = NULL;
switch_channel_t *channel = NULL;
sip_from_t const *from = sip->sip_from;
sip_to_t const *to = sip->sip_to;
char *displayname;
char *username, *req_username = NULL;
char *url_user = (char *) from->a_url->url_user;
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];
const char *user = NULL, *host = NULL, *port = NULL;
char *uri = NULL;
switch_channel_t *channel = switch_core_session_get_channel(session);
if (!(sip && sip->sip_contact && sip->sip_contact->m_url)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NO CONTACT!\n");
nua_respond(nh, 400, "Missing Contact Header", TAG_END());
return;
if (url) {
user = url->url_user;
host = url->url_host;
port = url->url_port;
}
if ((profile->pflags & PFLAG_AUTH_CALLS)) {
if (handle_register(nua, profile, nh, sip, REG_INVITE, key, sizeof(key))) {
return;
}
if (user) {
switch_channel_set_variable(channel, user_var, user);
}
if (!(session = switch_core_session_request(&sofia_endpoint_interface, NULL))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Session Alloc Failed!\n");
nua_respond(nh, SIP_503_SERVICE_UNAVAILABLE, TAG_END());
return;
if (!port) {
port = "5060";
}
if (!(tech_pvt = (private_object_t *) switch_core_session_alloc(session, sizeof(private_object_t)))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
terminate_session(&session, SWITCH_CAUSE_SWITCH_CONGESTION, __LINE__);
return;
}
if (!switch_strlen_zero(key)) {
tech_pvt->key = switch_core_session_strdup(session, key);
}
get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *)msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_addr);
to_user = (char *) to->a_url->url_user;
to_host = (char *) to->a_url->url_host;
if (!(to_port = (char *) to->a_url->url_port)) {
to_port = "5060";
}
if (switch_strlen_zero(to_user)) { /* if sofia doesnt parse the To: right, we'll have to do it */
if ((to_user = sip_header_as_string(tech_pvt->home, (sip_header_t *) to))) {
char *p;
if (*to_user == '<') {
to_user++;
}
if ((p = strchr((to_user += 4), '@'))) {
*p++ = '\0';
to_host = p;
if ((p = strchr(to_host, '>'))) {
*p = '\0';
}
}
}
}
if (switch_strlen_zero(url_user)) {
url_user = "service";
}
if (!switch_strlen_zero(from->a_display)) {
displayname = switch_core_session_strdup(session, (char *) from->a_display);
if (*displayname == '"') {
char *p;
displayname++;
if ((p = strchr(displayname, '"'))) {
*p = '\0';
}
}
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 {
displayname = url_user;
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);
}
if (!(username = switch_mprintf("%s@%s", url_user, (char *) from->a_url->url_host))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
return;
}
return uri;
}
attach_private(session, profile, tech_pvt, username);
tech_set_codecs(tech_pvt);
channel = switch_core_session_get_channel(session);
switch_channel_set_variable(channel, "endpoint_disposition", "INBOUND CALL");
set_chat_hash(tech_pvt, sip);
if (switch_test_flag(tech_pvt, TFLAG_INB_NOMEDIA)) {
switch_set_flag_locked(tech_pvt, TFLAG_NOMEDIA);
switch_channel_set_flag(channel, CF_NOMEDIA);
}
switch_channel_set_variable(channel, "sip_from_user", from->a_url->url_user);
if (from->a_url->url_user && *from->a_url->url_user == '+') {
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);
switch_channel_set_variable(channel, "sip_req_host", req_host);
switch_channel_set_variable(channel, "sip_req_port", req_port);
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 (!(req_username = switch_mprintf("%s:%s", req_host, req_port))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
switch_safe_free(username);
return;
}
}
}
contact_user = (char *) sip->sip_contact->m_url->url_user;
contact_host = (char *) sip->sip_contact->m_url->url_host;
if (!(contact_port = (char *) sip->sip_contact->m_url->url_port)) {
contact_port = "5060";
}
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);
switch_channel_set_variable(channel, "sip_via_port", via_port);
switch_channel_set_variable(channel, "sip_via_rport", via_rport);
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),
(char *) from->a_url->url_user,
profile->dialplan,
displayname,
(char *) from->a_url->url_user,
network_ip,
NULL,
NULL,
NULL,
(char *)modname,
(profile->context && !strcasecmp(profile->context, "_domain_")) ?
(char *) from->a_url->url_host : profile->context,
req_username ? req_username : req_user ? (char *) req_user : ""
)) != 0) {
for (un=sip->sip_unknown; un; un=un->un_next) {
if (!strncasecmp(un->un_name, "Alert-Info", 10)) {
if (!switch_strlen_zero(un->un_value)) {
switch_channel_set_variable(channel, "alert_info", (char *)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)) {
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)) {
@ -4501,6 +4311,178 @@ static void sip_i_invite(nua_t *nua,
free(mydata);
}
}
}
static void sip_i_invite(nua_t *nua,
sofia_profile_t *profile,
nua_handle_t *nh,
sofia_private_t *sofia_private,
sip_t const *sip,
tagi_t tags[])
{
switch_core_session_t *session = NULL;
char key[128] = "";
sip_unknown_t *un;
private_object_t *tech_pvt = NULL;
switch_channel_t *channel = NULL;
const char *channel_name = NULL;
const char *displayname = NULL;
const char *destination_number = NULL;
const char *from_user = NULL, *from_host = NULL;
const char *context;
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_contact && sip->sip_contact->m_url)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NO CONTACT!\n");
nua_respond(nh, 400, "Missing Contact Header", TAG_END());
return;
}
if ((profile->pflags & PFLAG_AUTH_CALLS)) {
if (handle_register(nua, profile, nh, sip, REG_INVITE, key, sizeof(key))) {
return;
}
}
if (!(session = switch_core_session_request(&sofia_endpoint_interface, NULL))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Session Alloc Failed!\n");
nua_respond(nh, SIP_503_SERVICE_UNAVAILABLE, TAG_END());
return;
}
if (!(tech_pvt = (private_object_t *) switch_core_session_alloc(session, sizeof(private_object_t)))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
terminate_session(&session, SWITCH_CAUSE_SWITCH_CONGESTION, __LINE__);
return;
}
if (!switch_strlen_zero(key)) {
tech_pvt->key = switch_core_session_strdup(session, key);
}
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");
if (!switch_strlen_zero(from_user)) {
if (*from_user == '+') {
switch_channel_set_variable(channel, "sip_from_user_stripped", (const char *)(from_user+1));
} else {
switch_channel_set_variable(channel, "sip_from_user_stripped", from_user);
}
}
if (!switch_strlen_zero(sip->sip_from->a_display)) {
char *tmp;
tmp = switch_core_session_strdup(session, sip->sip_from->a_display);
if (*tmp == '"') {
char *p;
tmp++;
if ((p = strchr(tmp, '"'))) {
*p = '\0';
}
}
displayname = tmp;
} else {
displayname = switch_strlen_zero(from_user) ? "unkonwn" : from_user;
}
}
if (sip->sip_request && sip->sip_request->rq_url) {
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;
} else {
destination_number = sip->sip_request->rq_url->url_user;
}
}
if (sip->sip_to && sip->sip_to->a_url) {
url_set_chanvars(session, sip->sip_to->a_url, "sip_to");
}
if (sip->sip_contact && sip->sip_contact->m_url) {
const char *contact_uri = url_set_chanvars(session, sip->sip_contact->m_url, "sip_contact");
if (!channel_name) {
channel_name = contact_uri;
}
}
attach_private(session, profile, tech_pvt, channel_name);
tech_set_codecs(tech_pvt);
switch_channel_set_variable(channel, "endpoint_disposition", "INBOUND CALL");
set_chat_hash(tech_pvt, sip);
if (switch_test_flag(tech_pvt, TFLAG_INB_NOMEDIA)) {
switch_set_flag_locked(tech_pvt, TFLAG_NOMEDIA);
switch_channel_set_flag(channel, CF_NOMEDIA);
}
if (!tech_pvt->call_id && 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);
}
if (sip->sip_via) {
if (sip->sip_via->v_host) {
switch_channel_set_variable(channel, "sip_via_host", sip->sip_via->v_host);
}
if (sip->sip_via->v_port) {
switch_channel_set_variable(channel, "sip_via_port", sip->sip_via->v_port);
}
if (sip->sip_via->v_rport) {
switch_channel_set_variable(channel, "sip_via_rport", sip->sip_via->v_rport);
}
}
if (sip->sip_max_forwards) {
char max_forwards[32];
snprintf(max_forwards, sizeof(max_forwards), "%u", sip->sip_max_forwards->mf_count);
switch_channel_set_variable(channel, SWITCH_MAX_FORWARDS_VARIABLE, max_forwards);
}
if (profile->context && !strcasecmp(profile->context, "_domain_")) {
context = from_host;
} else {
context = profile->context;
}
tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
from_user,
profile->dialplan,
displayname,
from_user,
network_ip,
NULL,
NULL,
NULL,
modname,
context,
destination_number);
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) {
if (!strncasecmp(un->un_name, "Alert-Info", 10)) {
if (!switch_strlen_zero(un->un_value)) {
switch_channel_set_variable(channel, "alert_info", un->un_value);
}
} else if (!strncasecmp(un->un_name, "Remote-Party-ID", 15)) {
process_rpid(un, tech_pvt);
} else if (!strncasecmp(un->un_name, "X-", 2)) {
if (!switch_strlen_zero(un->un_value)) {
char *new_name;
@ -4513,8 +4495,6 @@ static void sip_i_invite(nua_t *nua,
}
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)))) {