]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
sip work in progress changes
authorAnthony Minessale <anthony.minessale@gmail.com>
Wed, 4 Oct 2006 23:11:11 +0000 (23:11 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Wed, 4 Oct 2006 23:11:11 +0000 (23:11 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2969 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/include/switch_types.h
src/mod/endpoints/mod_sofia/Makefile
src/mod/endpoints/mod_sofia/mod_sofia.c
src/switch_channel.c
src/switch_ivr.c

index 3a7adc79f5fc971a3b97c7b1fd1b9e8834c58a0c..9ccf83188688320200218f54aab767038ad0df11 100644 (file)
@@ -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 {
index f65904636348ee19cb310ec6f3bfae86c1c04d88..0066d022782f6957e0e6d44bbb3e4dcb2af3f80d 100644 (file)
@@ -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)
index a2f6d839776ea7e5478e72145e1fab6c6b9b19b3..16ad00d03a2acb375bee37af29841ee3517a45a2 100644 (file)
@@ -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;
-
-
-
-       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 == '"') {
+       int cnt = 0;
+
+       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,44 +2201,99 @@ 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 ((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;
 
-                       if ((p = strchr(exten, '@'))) {
-                               switch_channel_t *channel = switch_core_session_get_channel(session);
-                               char *br;
+                                               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 @@ 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());
-               
-               
        }
 }
 
index b608598dfb4ab630d487463aa3b452822cb5ad63..35cb669a1f43539731a0fba72e762af7d81fc350 100644 (file)
@@ -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,
index 8d1bb541d31c4b26575b4e9c8176ae2781e0f64e..3eb9f993b6fc9e4df98474635b58ae6cd74c7216 100644 (file)
@@ -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) {