]> sjero.net Git - linphone/commitdiff
fix contact update after registration in case of TCP
authorJehan Monnier <jehan.monnier@linphone.org>
Wed, 15 Jun 2011 11:01:01 +0000 (13:01 +0200)
committerJehan Monnier <jehan.monnier@linphone.org>
Wed, 15 Jun 2011 11:01:01 +0000 (13:01 +0200)
coreapi/linphonecore.c
coreapi/proxy.c
coreapi/sal.c
coreapi/sal.h
coreapi/sal_eXosip2.c

index d179d81049d82040a37131ed309f24c2a3e4b136..aa88a263e1c308d22e9f6ef19d85b5b244a81004 100644 (file)
@@ -1375,13 +1375,13 @@ static int apply_transports(LinphoneCore *lc){
 
        sal_unlisten_ports (sal);
        if (tr->udp_port>0){
-               if (sal_listen_port (sal,anyaddr,tr->udp_port,SalTransportDatagram,FALSE)!=0){
+               if (sal_listen_port (sal,anyaddr,tr->udp_port,SalTransportUDP,FALSE)!=0){
                        transport_error(lc,"UDP",tr->udp_port);
                        return -1;
                }
        }
        if (tr->tcp_port>0){
-               if (sal_listen_port (sal,anyaddr,tr->tcp_port,SalTransportStream,FALSE)!=0){
+               if (sal_listen_port (sal,anyaddr,tr->tcp_port,SalTransportTCP,FALSE)!=0){
                        transport_error(lc,"TCP",tr->tcp_port);
                }
        }
index fbbf9ce18c0398bc4e1fe2c457dd546244a81c15..ff13f839e4545f99245f2642583ec0ec83564757 100644 (file)
@@ -259,7 +259,7 @@ static char *guess_contact_for_register(LinphoneProxyConfig *obj){
                
                linphone_core_get_sip_transports(obj->lc,&tr);
                if (tr.udp_port <= 0 && tr.tcp_port>0) {
-                       sal_address_add_param(contact,"transport","tcp");
+                       sal_address_set_param(contact,"transport","TCP");
                }
                ret=linphone_address_as_string(contact);
                linphone_address_destroy(contact);
index b25f3945130230a8fdc487d701bdb8e8cfe82c3c..1af6d000b6fae824ee9adca74a1bf6beb8b8b15a 100644 (file)
@@ -24,7 +24,26 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 **/
 
 #include "sal.h"
-
+const char* sal_transport_to_string(SalTransport transport) {
+    switch (transport) {
+        case SalTransportUDP:return "UDP";
+        case SalTransportTCP: return "TCP";
+        case SalTransportTLS:return "TLS";
+        case SalTransportDTLS:return "DTLS";
+        default: {
+            ms_fatal("Unexpected transport [%i]",transport);
+        }
+            
+    }
+}
+SalTransport sal_transport_parse(const char* param) {
+    if (strcasecmp("UDP",param)==0) return SalTransportUDP;
+    if (strcasecmp("TCP",param)==0) return SalTransportTCP;
+    if (strcasecmp("TLS",param)==0) return SalTransportTLS;
+    if (strcasecmp("DTLS",param)==0) return SalTransportDTLS;
+    ms_error("Unkown transport type[%s], returning UDP", param);
+    return SalTransportUDP;
+}
 SalMediaDescription *sal_media_description_new(){
        SalMediaDescription *md=ms_new0(SalMediaDescription,1);
        md->refcount=1;
index a89b862c05369740edde30ca3c2c72e685a6831e..af1ddc367e149d1aa5ac261aa0f79e78cdd5b7ef 100644 (file)
@@ -40,6 +40,15 @@ struct SalAddress;
 
 typedef struct SalAddress SalAddress;
 
+typedef enum {
+       SalTransportUDP, /*UDP*/
+       SalTransportTCP, /*TCP*/
+       SalTransportTLS, /*TLS*/
+       SalTransportDTLS /*DTLS*/
+}SalTransport;
+
+const char* sal_transport_to_string(SalTransport transport);
+SalTransport sal_transport_parse(const char*);
 /* Address manipulation API*/
 SalAddress * sal_address_new(const char *uri);
 SalAddress * sal_address_clone(const SalAddress *addr);
@@ -49,7 +58,8 @@ char *sal_address_get_display_name_unquoted(const SalAddress *addr);
 const char *sal_address_get_username(const SalAddress *addr);
 const char *sal_address_get_domain(const SalAddress *addr);
 const char * sal_address_get_port(const SalAddress *addr);
-int sal_address_get_port_int(const SalAddress *uri);
+int sal_address_get_port_int(const SalAddress *addr);
+SalTransport sal_address_get_transport(const SalAddress* addr);
 
 void sal_address_set_display_name(SalAddress *addr, const char *display_name);
 void sal_address_set_username(SalAddress *addr, const char *username);
@@ -60,8 +70,8 @@ void sal_address_clean(SalAddress *addr);
 char *sal_address_as_string(const SalAddress *u);
 char *sal_address_as_string_uri_only(const SalAddress *u);
 void sal_address_destroy(SalAddress *u);
-void sal_address_add_param(SalAddress *u,const char* name,const char* value);
-
+void sal_address_set_param(SalAddress *u,const char* name,const char* value);
+void sal_address_set_transport(SalAddress* addr,SalTransport transport);
 
 
 Sal * sal_init();
@@ -69,10 +79,6 @@ void sal_uninit(Sal* sal);
 void sal_set_user_pointer(Sal *sal, void *user_data);
 void *sal_get_user_pointer(const Sal *sal);
 
-typedef enum {
-       SalTransportDatagram,
-       SalTransportStream
-}SalTransport;
 
 typedef enum {
        SalAudio,
index 65c60afddcd53581efeaae80d6d481742ced8915..c62f828fb5986de99a405e959eec5d9a2a5ce32b 100644 (file)
@@ -32,6 +32,10 @@ static bool_t call_failure(Sal *sal, eXosip_event_t *ev);
 
 static void text_received(Sal *sal, eXosip_event_t *ev);
 
+static void masquerade_via(osip_message_t *msg, const char *ip, const char *port);
+static bool_t fix_message_contact(SalOp *op, osip_message_t *request,osip_message_t *last_answer);
+static void update_contact_from_response(SalOp *op, osip_message_t *response);
+
 void _osip_list_set_empty(osip_list_t *l, void (*freefunc)(void*)){
        void *data;
        while(!osip_list_eol(l,0)) {
@@ -351,11 +355,11 @@ int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int i
        int keepalive = ctx->keepalive_period;
        
        switch (tr) {
-       case SalTransportDatagram:
+       case SalTransportUDP:
                proto=IPPROTO_UDP;
                eXosip_set_option (EXOSIP_OPT_UDP_KEEP_ALIVE, &keepalive);      
                break;
-       case SalTransportStream:
+       case SalTransportTCP:
                proto= IPPROTO_TCP;
                        keepalive=-1;   
                eXosip_set_option (EXOSIP_OPT_UDP_KEEP_ALIVE,&keepalive);       
@@ -424,7 +428,8 @@ void sal_use_rport(Sal *ctx, bool_t use_rports){
 void sal_use_101(Sal *ctx, bool_t use_101){
        ctx->use_101=use_101;
 }
-static int extract_received_rport(osip_message_t *msg, const char **received, int *rportval){
+
+static int extract_received_rport(osip_message_t *msg, const char **received, int *rportval,SalTransport* transport){
        osip_via_t *via=NULL;
        osip_generic_param_t *param=NULL;
        const char *rport=NULL;
@@ -434,10 +439,7 @@ static int extract_received_rport(osip_message_t *msg, const char **received, in
        osip_message_get_via(msg,0,&via);
        if (!via) return -1;
 
-       /* it is useless to do that with tcp since client socket might have a different port
-               than the server socket.
-       */
-       if (strcasecmp(via->protocol,"tcp")==0) return -1;
+       *transport = sal_transport_parse(via->protocol);
        
        if (via->port && via->port[0]!='\0')
                *rportval=atoi(via->port);
@@ -800,9 +802,13 @@ int sal_call_terminate(SalOp *h){
 }
 
 void sal_op_authenticate(SalOp *h, const SalAuthInfo *info){
-       if (h->pending_auth){
+    if (h->pending_auth){
                push_auth_to_exosip(info);
                eXosip_lock();
+        /*FIXME exosip does not take into account this update register message*/
+        if (fix_message_contact(h, h->pending_auth->request,h->pending_auth->response)) {
+            update_contact_from_response(h,h->pending_auth->response);
+        };
                eXosip_default_action(h->pending_auth);
                eXosip_unlock();
                ms_message("eXosip_default_action() done");
@@ -826,7 +832,8 @@ static void set_network_origin(SalOp *op, osip_message_t *req){
        const char *received=NULL;
        int rport=5060;
        char origin[64];
-       if (extract_received_rport(req,&received,&rport)!=0){
+    SalTransport transport;
+       if (extract_received_rport(req,&received,&rport,&transport)!=0){
                osip_via_t *via=NULL;
                char *tmp;
                osip_message_get_via(req,0,&via);
@@ -834,7 +841,11 @@ static void set_network_origin(SalOp *op, osip_message_t *req){
                tmp=osip_via_get_port(via);
                if (tmp) rport=atoi(tmp);
        }
-       snprintf(origin,sizeof(origin)-1,"sip:%s:%i",received,rport);
+    if (transport != SalTransportUDP) {
+        snprintf(origin,sizeof(origin)-1,"sip:%s:%i",received,rport);
+    } else {
+       snprintf(origin,sizeof(origin)-1,"sip:%s:%i;transport=%s",received,rport,sal_transport_to_string(transport)); 
+    }
        __sal_op_set_network_origin(op,origin);
 }
 
@@ -992,7 +1003,8 @@ static void handle_ack(Sal *sal,  eXosip_event_t *ev){
 static void update_contact_from_response(SalOp *op, osip_message_t *response){
        const char *received;
        int rport;
-       if (extract_received_rport(response,&received,&rport)==0){
+    SalTransport transport;
+       if (extract_received_rport(response,&received,&rport,&transport)==0){
                const char *contact=sal_op_get_contact(op);
                if (!contact){
                        /*no contact given yet, use from instead*/
@@ -1003,8 +1015,9 @@ static void update_contact_from_response(SalOp *op, osip_message_t *response){
                        char *tmp;
                        sal_address_set_domain(addr,received);
                        sal_address_set_port_int(addr,rport);
+            sal_address_set_transport(addr,transport);
                        tmp=sal_address_as_string(addr);
-                       ms_message("Contact address updated to %s for this dialog",tmp);
+                       ms_message("Contact address updated to %s",tmp);
                        sal_op_set_contact(op,tmp);
                        sal_address_destroy(addr);
                        ms_free(tmp);
@@ -1601,39 +1614,22 @@ static void masquerade_via(osip_message_t *msg, const char *ip, const char *port
        }
 }
 
-static bool_t register_again_with_updated_contact(SalOp *op, osip_message_t *orig_request, osip_message_t *last_answer){
-       osip_message_t *msg;
-       const char *received;
-       int rport;
-       osip_contact_t *ctt=NULL;
-       char *tmp;
-       char port[20];
-       SalAddress *addr;
-       Sal *sal=op->base.root;
 
-       if (sal->double_reg==FALSE) return FALSE;
-       
-       if (extract_received_rport(last_answer,&received,&rport)==-1) return FALSE;
-       osip_message_get_contact(orig_request,0,&ctt);
-       if (strcmp(ctt->url->host,received)==0){
-               /*ip address matches, check ports*/
-               const char *contact_port=ctt->url->port;
-               if (contact_port==NULL || contact_port[0]=='\0')
-                       contact_port="5060";
-               if (atoi(contact_port)==rport){
-                       ms_message("Register has up to date contact, doing nothing.");
-                       return FALSE;
-               }else ms_message("ports do not match, need to update the register (%s <> %i)", contact_port,rport);
-       }
+static bool_t fix_message_contact(SalOp *op, osip_message_t *request,osip_message_t *last_answer) {
+       osip_contact_t *ctt=NULL;
+    const char *received;
+       int rport;
+    SalTransport transport;
+    char port[20];
+    
+    if (extract_received_rport(last_answer,&received,&rport,&transport)==-1) return FALSE;
        eXosip_lock();
-       msg=NULL;
-       eXosip_register_build_register(op->rid,op->expires,&msg);
-       if (msg==NULL){
-               eXosip_unlock();
-               ms_warning("Fail to create a contact updated register.");
-               return FALSE;
-       }
-       osip_message_get_contact(msg,0,&ctt);
+    osip_message_get_contact(request,0,&ctt);
+    if (ctt == NULL) {
+        /*nothing to update*/
+        eXosip_unlock();
+        return FALSE;
+    }
        if (ctt->url->host!=NULL){
                osip_free(ctt->url->host);
        }
@@ -1643,19 +1639,69 @@ static bool_t register_again_with_updated_contact(SalOp *op, osip_message_t *ori
        }
        snprintf(port,sizeof(port),"%i",rport);
        ctt->url->port=osip_strdup(port);
-       if (op->masquerade_via) masquerade_via(msg,received,port);
-       eXosip_register_send_register(op->rid,msg);
+       if (op->masquerade_via) masquerade_via(request,received,port);
+       
+    if (transport != SalTransportUDP) {
+       sal_address_set_param((SalAddress *)ctt, "transport", sal_transport_to_string(transport)); 
+        
+    }
        eXosip_unlock();
+    return TRUE;
+    
+}
+
+static bool_t register_again_with_updated_contact(SalOp *op, osip_message_t *orig_request, osip_message_t *last_answer){
+    osip_contact_t *ctt=NULL;
+    SalAddress* ori_contact_address=NULL;
+    const char *received;
+       int rport;
+    SalTransport transport;
+    char* tmp;
+    osip_message_t *msg=NULL;
+    Sal* sal=op->base.root;
+    
+    if (sal->double_reg==FALSE ) return FALSE; 
+    
+    if (extract_received_rport(last_answer,&received,&rport,&transport)==-1) return FALSE;
+    osip_message_get_contact(orig_request,0,&ctt);
        osip_contact_to_str(ctt,&tmp);
-       addr=sal_address_new(tmp);
-       osip_free(tmp);
-       sal_address_clean(addr);
-       tmp=sal_address_as_string(addr);
-       sal_op_set_contact(op,tmp);
-       sal_address_destroy(addr);
-       ms_message("Resending new register with updated contact %s",tmp);
-       ms_free(tmp);
-       return TRUE;
+    ori_contact_address = sal_address_new((const char*)tmp);
+    osip_free(tmp);
+    /*check if contact is up to date*/
+    if (strcmp(sal_address_get_domain(ori_contact_address),received) ==0 
+        && sal_address_get_port_int(ori_contact_address) == rport
+        && sal_address_get_transport(ori_contact_address) == transport) {
+        ms_message("Register has up to date contact, doing nothing.");        
+        return FALSE;
+    } else ms_message("contact do not match, need to update the register (%s with %s:%i;transport=%s)"
+                      ,tmp
+                      ,received
+                      ,rport
+                      ,sal_transport_to_string(transport));
+       
+    sal_address_destroy(ori_contact_address);
+    
+    if (transport == SalTransportUDP) {
+        eXosip_lock();
+        eXosip_register_build_register(op->rid,op->expires,&msg);
+        if (msg==NULL){
+            eXosip_unlock();
+            ms_warning("Fail to create a contact updated register.");
+            return FALSE;
+        }
+        if (fix_message_contact(op,msg,last_answer)) {
+            eXosip_register_send_register(op->rid,msg);   
+            ms_message("Resending new register with updated contact");
+            return TRUE;
+        } else {
+            ms_warning("Fail to send updated register.");
+            eXosip_unlock();
+            return FALSE;
+        }
+    }
+
+    update_contact_from_response(op,last_answer);
+    return FALSE;
 }
 
 static void registration_success(Sal *sal, eXosip_event_t *ev){
@@ -2081,8 +2127,16 @@ char *sal_address_as_string_uri_only(const SalAddress *u){
        osip_free(tmp);
        return ret;
 }
-void sal_address_add_param(SalAddress *u,const char* name,const char* value) {
-       osip_uri_uparam_add     (((osip_from_t*)u)->url,ms_strdup(name),ms_strdup(value));
+void sal_address_set_param(SalAddress *u,const char* name,const char* value) {
+       osip_uri_param_t *param=NULL;
+    osip_uri_uparam_get_byname(((osip_from_t*)u)->url,(char*)name,&param);
+    if (param == NULL){
+        osip_uri_uparam_add    (((osip_from_t*)u)->url,ms_strdup(name),ms_strdup(value));
+    } else {
+        osip_free(param->gvalue);
+        param->gvalue=osip_strdup(value);
+    }
+    
 }
 
 void sal_address_destroy(SalAddress *u){
@@ -2110,6 +2164,19 @@ int sal_address_get_port_int(const SalAddress *uri) {
                return 5060;
        }
 }
+SalTransport sal_address_get_transport(const SalAddress* addr) {
+    const osip_from_t *u=(const osip_from_t*)addr;
+    osip_uri_param_t *transport_param=NULL;
+    osip_uri_uparam_get_byname(u->url,"transport",&transport_param);
+    if (transport_param == NULL){
+        return SalTransportUDP;
+    }  else {
+        return sal_transport_parse(transport_param->gvalue);
+    }
+}
+void sal_address_set_transport(SalAddress* addr,SalTransport transport) {
+    sal_address_set_param(addr, "transport", sal_transport_to_string(transport));
+}
 
 /* sends a reinvite. Local media description may have changed by application since call establishment*/
 int sal_call_update(SalOp *h, const char *subject){