From 7de068b9ac4cf82b364d89c470cdc9199efab7a0 Mon Sep 17 00:00:00 2001 From: Anthony Minessale <anthony.minessale@gmail.com> Date: Wed, 4 Oct 2006 23:11:11 +0000 Subject: [PATCH] sip work in progress changes git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2969 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/include/switch_types.h | 4 +- src/mod/endpoints/mod_sofia/Makefile | 2 +- src/mod/endpoints/mod_sofia/mod_sofia.c | 200 ++++++++++++++++-------- src/switch_channel.c | 39 +++-- src/switch_ivr.c | 2 +- 5 files changed, 171 insertions(+), 76 deletions(-) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 3a7adc79f5..9ccf831886 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -693,7 +693,9 @@ typedef enum { SWITCH_CAUSE_CRASH = 500, SWITCH_CAUSE_SYSTEM_SHUTDOWN = 501, SWITCH_CAUSE_LOSE_RACE = 502, - SWITCH_CAUSE_MANAGER_REQUEST = 503 + SWITCH_CAUSE_MANAGER_REQUEST = 503, + SWITCH_CAUSE_BLIND_TRANSFER = 600, + SWITCH_CAUSE_ATTENDED_TRANSFER = 601 } switch_call_cause_t; typedef enum { diff --git a/src/mod/endpoints/mod_sofia/Makefile b/src/mod/endpoints/mod_sofia/Makefile index f659046363..0066d02278 100644 --- a/src/mod/endpoints/mod_sofia/Makefile +++ b/src/mod/endpoints/mod_sofia/Makefile @@ -1,6 +1,6 @@ OS_ARCH := $(subst /,_,$(shell uname -s | sed /\ /s//_/)) VERSION = sofia-sip-1.12 -TARBALL = sofia-sip-1.12.2.tar.gz +TARBALL = sofia-sip-1.12.3.tar.gz CFLAGS += -I. -I$(PREFIX)/include/$(VERSION) LDFLAGS += -lsofia-sip-ua LINKER=$(CC) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index a2f6d83977..16ad00d03a 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -247,6 +247,7 @@ struct private_object { char *remote_sdp_str; char *local_sdp_str; char *dest; + char *source; char *key; unsigned long rm_rate; switch_payload_t pt; @@ -372,42 +373,54 @@ static auth_res_t parse_auth(sofia_profile_t *profile, sip_authorization_t const auth_res_t ret = AUTH_OK; char *npassword = NULL; nonce = uri = qop = cnonce = nc = response = NULL; + int cnt = 0; - - - for(index = 0; (cur=(char*)authorization->au_params[index]); index++) { - char *var, *val, *p, *work; - var = val = work = NULL; - if ((work = strdup(cur))) { - var = work; - if ((val = strchr(var, '='))) { - *val++ = '\0'; - while(*val == '"') { + if (authorization->au_params) { + for(index = 0; (cur=(char*)authorization->au_params[index]); index++) { + char *var, *val, *p, *work; + var = val = work = NULL; + if ((work = strdup(cur))) { + var = work; + if ((val = strchr(var, '='))) { *val++ = '\0'; - } - if ((p = strchr(val, '"'))) { - *p = '\0'; - } + while(*val == '"') { + *val++ = '\0'; + } + if ((p = strchr(val, '"'))) { + *p = '\0'; + } - if (!strcasecmp(var, "nonce")) { - nonce = strdup(val); - } else if (!strcasecmp(var, "uri")) { - uri = strdup(val); - } else if (!strcasecmp(var, "qop")) { - qop = strdup(val); - } else if (!strcasecmp(var, "cnonce")) { - cnonce = strdup(val); - } else if (!strcasecmp(var, "response")) { - response = strdup(val); - } else if (!strcasecmp(var, "nc")) { - nc = strdup(val); + if (!strcasecmp(var, "nonce")) { + nonce = strdup(val); + cnt++; + } else if (!strcasecmp(var, "uri")) { + uri = strdup(val); + cnt++; + } else if (!strcasecmp(var, "qop")) { + qop = strdup(val); + cnt++; + } else if (!strcasecmp(var, "cnonce")) { + cnonce = strdup(val); + cnt++; + } else if (!strcasecmp(var, "response")) { + response = strdup(val); + cnt++; + } else if (!strcasecmp(var, "nc")) { + nc = strdup(val); + cnt++; + } } - } - free(work); + free(work); + } } } + if (cnt != 6) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Authorization header!\n"); + goto end; + } + if (switch_strlen_zero(np)) { if (!get_auth_data(profile->dbname, nonce, np, nplen, profile->ireg_mutex)) { ret = AUTH_STALE; @@ -779,6 +792,8 @@ static void do_invite(switch_core_session_t *session) tech_pvt->sofia_private.session = session; nua_handle_bind(tech_pvt->nh, &tech_pvt->sofia_private); nua_invite(tech_pvt->nh, + SIPTAG_FROM_STR(tech_pvt->source), + SIPTAG_CONTACT_STR(tech_pvt->profile->url), SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str), SOATAG_RTP_SORT(SOA_RTP_SORT_REMOTE), SOATAG_RTP_SELECT(SOA_RTP_SELECT_ALL), @@ -1506,6 +1521,7 @@ static switch_status_t sofia_outgoing_channel(switch_core_session_t *session, sw private_object_t *tech_pvt = NULL; switch_channel_t *channel; char *host; + char username[512]; *new_session = NULL; @@ -1552,6 +1568,8 @@ static switch_status_t sofia_outgoing_channel(switch_core_session_t *session, sw snprintf(tech_pvt->dest, strlen(dest) + 5, "sip:%s", dest); } + snprintf(username, sizeof(username), "sip:%s@%s:%d", (char *) outbound_profile->caller_id_number, profile->sipip, profile->sip_port); + tech_pvt->source = switch_core_session_strdup(nsession, username); channel = switch_core_session_get_channel(nsession); attach_private(nsession, profile, tech_pvt, dest); caller_profile = switch_caller_profile_clone(nsession, outbound_profile); @@ -2143,7 +2161,9 @@ static uint8_t handle_register(nua_t *nua, ); if (regtype == REG_REGISTER) { - nua_respond(nh, SIP_200_OK, SIPTAG_CONTACT(contact), TAG_END()); + nua_respond(nh, SIP_200_OK, SIPTAG_CONTACT(contact), + NUTAG_WITH_THIS(nua), + TAG_END()); return 1; } @@ -2164,11 +2184,12 @@ static void sip_i_refer(nua_t *nua, sip_from_t const *from; sip_to_t const *to; sip_refer_to_t const *refer_to; - char *refer_to_str; switch_core_session_t *session = sofia_private ? sofia_private->session : NULL; if (session) { private_object_t *tech_pvt = NULL; + char *exten; + const char *tmp = NULL; #ifdef this_was_done char *dest; private_object_t *ntech_pvt; @@ -2180,45 +2201,100 @@ static void sip_i_refer(nua_t *nua, tech_pvt = switch_core_session_get_private(session); from = sip->sip_from; to = sip->sip_to; - refer_to = sip->sip_refer_to; + tl_gets(tags, + SIPTAG_REFER_TO_STR_REF(tmp), + TAG_END()); - if ((refer_to_str = sip_header_as_string(tech_pvt->home, (sip_header_t*)refer_to))) { - char *exten = switch_core_session_strdup(session, refer_to_str); - char *p; + if ((refer_to = sip->sip_refer_to)) { + exten = (char *) refer_to->r_url->url_user; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Process REFER to [%s@%s]\n", + exten, (char *) refer_to->r_url->url_host); - if ((p = strchr(exten, ':'))) { - *p++ = '\0'; - exten = p; - } + if (refer_to->r_url->url_headers) { + sip_replaces_t *replaces; + nua_handle_t *bnh; + char *rep; - if ((p = strchr(exten, '@'))) { - switch_channel_t *channel = switch_core_session_get_channel(session); - char *br; - - *p = '\0'; - if ((br = switch_channel_get_variable(channel, "BRIDGETO"))) { - switch_core_session_t *bsession; - - if ((bsession = switch_core_session_locate(br))) { - switch_ivr_session_transfer(bsession, exten, profile->dialplan, profile->context); - switch_core_session_rwunlock(bsession); + if ((rep = strchr(refer_to->r_url->url_headers, '='))) { + char *buf; + rep++; + + if ((buf = switch_core_session_alloc(session, strlen(rep) + 1))) { + rep = url_unescape(buf, (const char *) rep); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Replaces: [%s]\n", rep); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n"); + return; } + if ((replaces = sip_replaces_make(tech_pvt->home, rep)) && (bnh = nua_handle_by_replaces(nua, replaces))) { + sofia_private_t *b_private; + switch_channel_t *channel_a = NULL, *channel_b = NULL; + + channel_a = switch_core_session_get_channel(session); + + if ((b_private = nua_handle_fetch(bnh))) { + char *br_a, *br_b; + + channel_b = switch_core_session_get_channel(b_private->session); + + br_a = switch_channel_get_variable(channel_a, "BRIDGETO"); + //br_a = switch_core_session_get_uuid(session); + br_b = switch_channel_get_variable(channel_b, "BRIDGETO"); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Attended Transfer [%s][%s]\n", br_a, br_b); + + if (br_a && br_b) { + switch_ivr_uuid_bridge(br_a, br_b); + switch_channel_set_variable(channel_b, "endpoint_disposition", "ATTENDED_TRANSFER"); + switch_channel_hangup(channel_b, SWITCH_CAUSE_ATTENDED_TRANSFER); + switch_channel_set_variable(channel_a, "endpoint_disposition", "ATTENDED_TRANSFER"); + switch_channel_hangup(channel_a, SWITCH_CAUSE_ATTENDED_TRANSFER); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Transfer! [%s][%s]\n", br_a, br_b); + switch_channel_set_variable(channel_b, "endpoint_disposition", "ATTENDED_TRANSFER_ERROR"); + switch_channel_hangup(channel_b, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + switch_channel_set_variable(channel_a, "endpoint_disposition", "ATTENDED_TRANSFER_ERROR"); + switch_channel_hangup(channel_a, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + } + } + + nua_handle_unref(bnh); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find handle from Replaces!\n"); + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot parse Replaces!\n"); } - - + return; } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "refer to " URL_PRINT_FORMAT " from %s%s" URL_PRINT_FORMAT " to %s\n", - URL_PRINT_ARGS(from->a_url), - from->a_display ? from->a_display : "", from->a_display ? " " : "", - URL_PRINT_ARGS(from->a_url), - refer_to_str - ); - - su_free(tech_pvt->home, refer_to_str); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Refer-To\n"); + return; } + if (exten) { + switch_channel_t *channel = switch_core_session_get_channel(session); + char *br; + + switch_channel_set_variable(channel, "endpoint_disposition", "BLIND_TRANSFER"); + switch_channel_hangup(channel, SWITCH_CAUSE_BLIND_TRANSFER); + + if ((br = switch_channel_get_variable(channel, "BRIDGETO"))) { + switch_core_session_t *bsession; + + if ((bsession = switch_core_session_locate(br))) { + channel = switch_core_session_get_channel(bsession); + switch_channel_set_variable(channel, "TRANSFER_FALLBACK", (char *) from->a_user); + switch_ivr_session_transfer(bsession, exten, profile->dialplan, profile->context); + switch_core_session_rwunlock(bsession); + } + } + + } + + #ifdef this_was_done if (!(nsession = switch_core_session_request(&sofia_endpoint_interface, NULL))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error Creating Session\n"); @@ -2230,7 +2306,7 @@ static void sip_i_refer(nua_t *nua, terminate_session(&nsession, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER, __LINE__); goto done; } - ntech_pvt->dest = switch_core_session_strdup(nsession, refer_to_str); + ntech_pvt->dest = switch_core_session_strdup(nsession, exten); dest = ntech_pvt->dest + 4; channel = switch_core_session_get_channel(session); outbound_profile = switch_channel_get_caller_profile(channel); @@ -2427,12 +2503,10 @@ static void sip_r_register(int status, tl_gets(tags, NUTAG_CALLSTATE_REF(ss_state), - SIPTAG_WWW_AUTHENTICATE_REF(authenticate), + SIPTAG_WWW_AUTHENTICATE_REF(authenticate), TAG_END()); nua_authenticate(nh, NUTAG_AUTH(authentication), TAG_END()); - - } } diff --git a/src/switch_channel.c b/src/switch_channel.c index b608598dfb..35cb669a1f 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -87,6 +87,8 @@ static struct switch_cause_table CAUSE_CHART[] = { { "SYSTEM_SHUTDOWN", SWITCH_CAUSE_SYSTEM_SHUTDOWN }, { "LOSE_RACE", SWITCH_CAUSE_LOSE_RACE }, { "MANAGER_REQUEST", SWITCH_CAUSE_MANAGER_REQUEST }, + { "BLIND_TRANSFER", SWITCH_CAUSE_BLIND_TRANSFER }, + { "ATTENDED_TRANSFER", SWITCH_CAUSE_ATTENDED_TRANSFER }, { NULL, 0 } }; @@ -804,43 +806,59 @@ SWITCH_DECLARE(int) switch_channel_add_state_handler(switch_channel_t *channel, int x, index; assert(channel != NULL); + switch_mutex_lock(channel->flag_mutex); for (x = 0; x < SWITCH_MAX_STATE_HANDLERS; x++) { if (channel->state_handlers[x] == state_handler) { - return x; + index = x; + goto end; } } index = channel->state_handler_index++; if (channel->state_handler_index >= SWITCH_MAX_STATE_HANDLERS) { - return -1; + index = -1; + goto end; } - + channel->state_handlers[index] = state_handler; + + end: + switch_mutex_unlock(channel->flag_mutex); return index; } SWITCH_DECLARE(const switch_state_handler_table_t *) switch_channel_get_state_handler(switch_channel_t *channel, int index) { + const switch_state_handler_table_t *h = NULL; + assert(channel != NULL); if (index > SWITCH_MAX_STATE_HANDLERS || index > channel->state_handler_index) { return NULL; } - return channel->state_handlers[index]; + switch_mutex_lock(channel->flag_mutex); + h = channel->state_handlers[index]; + switch_mutex_unlock(channel->flag_mutex); + + return h; } SWITCH_DECLARE(void) switch_channel_clear_state_handler(switch_channel_t *channel, const switch_state_handler_table_t *state_handler) { - int index, i = 0; + int index, i = channel->state_handler_index; const switch_state_handler_table_t *new_handlers[SWITCH_MAX_STATE_HANDLERS] = {0}; + + switch_mutex_lock(channel->flag_mutex); + assert(channel != NULL); + channel->state_handler_index = 0; if (state_handler) { - for (index = 0; index < channel->state_handler_index; index++) { + for (index = 0; index < i; index++) { if (channel->state_handlers[index] != state_handler) { - new_handlers[i++] = channel->state_handlers[index]; + new_handlers[channel->state_handler_index++] = channel->state_handlers[index]; } } } @@ -849,12 +867,13 @@ SWITCH_DECLARE(void) switch_channel_clear_state_handler(switch_channel_t *channe } if (state_handler) { - for (index = 0; index < i; index++) { - channel->state_handlers[index] = new_handlers[i]; + for (index = 0; index < channel->state_handler_index; index++) { + channel->state_handlers[index] = new_handlers[index]; } } - channel->state_handler_index = i; + switch_mutex_unlock(channel->flag_mutex); + } SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel_t *channel, diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 8d1bb541d3..3eb9f993b6 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -1998,7 +1998,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess } done: - *cause = SWITCH_CAUSE_UNALLOCATED; + *cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; if (status == SWITCH_STATUS_SUCCESS) { if (caller_channel) {