Author: anthm Date: Wed Oct 4 19:11:11 2006 New Revision: 2969 Modified: freeswitch/trunk/src/include/switch_types.h freeswitch/trunk/src/mod/endpoints/mod_sofia/Makefile freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c freeswitch/trunk/src/switch_channel.c freeswitch/trunk/src/switch_ivr.c Log: sip work in progress changes Modified: freeswitch/trunk/src/include/switch_types.h ============================================================================== --- freeswitch/trunk/src/include/switch_types.h (original) +++ freeswitch/trunk/src/include/switch_types.h Wed Oct 4 19:11:11 2006 @@ -693,7 +693,9 @@ 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 { Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/Makefile ============================================================================== --- freeswitch/trunk/src/mod/endpoints/mod_sofia/Makefile (original) +++ freeswitch/trunk/src/mod/endpoints/mod_sofia/Makefile Wed Oct 4 19:11:11 2006 @@ -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) Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c ============================================================================== --- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c (original) +++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c Wed Oct 4 19:11:11 2006 @@ -247,6 +247,7 @@ 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 @@ 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 @@ 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 @@ private_object_t *tech_pvt = NULL; switch_channel_t *channel; char *host; + char username[512]; *new_session = NULL; @@ -1552,6 +1568,8 @@ 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 @@ ); 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 @@ 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,44 +2201,99 @@ 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; + 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); - *p = '\0'; - if ((br = switch_channel_get_variable(channel, "BRIDGETO"))) { - switch_core_session_t *bsession; + 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); + } + } - if ((bsession = switch_core_session_locate(br))) { - switch_ivr_session_transfer(bsession, exten, profile->dialplan, profile->context); - switch_core_session_rwunlock(bsession); + 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; + } + } 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); - 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); + 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))) { @@ -2230,7 +2306,7 @@ 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 @@ 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()); - - } } Modified: freeswitch/trunk/src/switch_channel.c ============================================================================== --- freeswitch/trunk/src/switch_channel.c (original) +++ freeswitch/trunk/src/switch_channel.c Wed Oct 4 19:11:11 2006 @@ -87,6 +87,8 @@ { "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 @@ 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 @@ } 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, Modified: freeswitch/trunk/src/switch_ivr.c ============================================================================== --- freeswitch/trunk/src/switch_ivr.c (original) +++ freeswitch/trunk/src/switch_ivr.c Wed Oct 4 19:11:11 2006 @@ -1998,7 +1998,7 @@ } done: - *cause = SWITCH_CAUSE_UNALLOCATED; + *cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; if (status == SWITCH_STATUS_SUCCESS) { if (caller_channel) {