From 6e8cf5e4a3f54535ee951a748420aa5aac3f64cd Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Wed, 15 Jun 2011 13:01:01 +0200 Subject: [PATCH 1/2] fix contact update after registration in case of TCP --- coreapi/linphonecore.c | 4 +- coreapi/proxy.c | 2 +- coreapi/sal.c | 21 ++++- coreapi/sal.h | 20 +++-- coreapi/sal_eXosip2.c | 179 ++++++++++++++++++++++++++++------------- 5 files changed, 159 insertions(+), 67 deletions(-) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index d179d8104..aa88a263e 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -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); } } diff --git a/coreapi/proxy.c b/coreapi/proxy.c index fbbf9ce18..ff13f839e 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -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); diff --git a/coreapi/sal.c b/coreapi/sal.c index b25f39451..1af6d000b 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -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; diff --git a/coreapi/sal.h b/coreapi/sal.h index a89b862c0..af1ddc367 100644 --- a/coreapi/sal.h +++ b/coreapi/sal.h @@ -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, diff --git a/coreapi/sal_eXosip2.c b/coreapi/sal_eXosip2.c index 65c60afdd..c62f828fb 100644 --- a/coreapi/sal_eXosip2.c +++ b/coreapi/sal_eXosip2.c @@ -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,¶m); + 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){ From e545c638329025423c6bd7873f0af159be662750 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Wed, 15 Jun 2011 13:34:04 +0200 Subject: [PATCH 2/2] fix compilation issue --- coreapi/sal.c | 1 + 1 file changed, 1 insertion(+) diff --git a/coreapi/sal.c b/coreapi/sal.c index 1af6d000b..92b82d52c 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -32,6 +32,7 @@ const char* sal_transport_to_string(SalTransport transport) { case SalTransportDTLS:return "DTLS"; default: { ms_fatal("Unexpected transport [%i]",transport); + return NULL; } }