From 2712cb4834f075f074e98650ee1d1a5a9988851d Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Mon, 27 Jul 2015 16:40:40 +0200 Subject: [PATCH] Clear pending tcp/tls address of record in case of network change. Very useful for legacy SIP server with no sip instance support and limited number of air. --- coreapi/bellesip_sal/sal_op_impl.c | 6 +++--- coreapi/bellesip_sal/sal_op_registration.c | 19 ++++++++++++++++++- coreapi/private.h | 1 + coreapi/proxy.c | 22 ++++++++++++++++++++-- include/sal/sal.h | 2 +- tester/register_tester.c | 2 +- 6 files changed, 44 insertions(+), 8 deletions(-) diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 3338356a1..d19091c96 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -286,7 +286,7 @@ void _sal_op_add_custom_headers(SalOp *op, belle_sip_message_t *msg){ } } -static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* request,bool_t add_contact) { +static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* request, bool_t add_contact) { belle_sip_client_transaction_t* client_transaction; belle_sip_provider_t* prov=op->base.root->prov; belle_sip_uri_t* outbound_proxy=NULL; @@ -294,10 +294,10 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req int result =-1; belle_sip_uri_t *next_hop_uri=NULL; - if (add_contact) { + if (add_contact && !belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_contact_t)) { contact = sal_op_create_contact(op); belle_sip_message_set_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(contact)); - } + } /*keep existing*/ _sal_op_add_custom_headers(op, (belle_sip_message_t*)request); diff --git a/coreapi/bellesip_sal/sal_op_registration.c b/coreapi/bellesip_sal/sal_op_registration.c index d56587db2..961ba4a34 100644 --- a/coreapi/bellesip_sal/sal_op_registration.c +++ b/coreapi/bellesip_sal/sal_op_registration.c @@ -40,6 +40,7 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher /*check service route rfc3608*/ belle_sip_header_service_route_t* service_route; belle_sip_header_address_t* service_route_address=NULL; + belle_sip_header_contact_t *contact = belle_sip_refresher_get_contact(refresher); if ((service_route=belle_sip_message_get_header_by_type(response,belle_sip_header_service_route_t))) { service_route_address=belle_sip_header_address_create(NULL,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(service_route))); } @@ -47,6 +48,9 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher if (service_route_address) belle_sip_object_unref(service_route_address); sal_remove_pending_auth(op->base.root,op); /*just in case*/ + if (contact) { + sal_op_set_contact_address(op,(SalAddress*)(BELLE_SIP_HEADER_ADDRESS(contact))); /*update contact with real value*/ + } op->base.root->callbacks.register_success(op,belle_sip_refresher_get_expires(op->refresher)>0); } else if (status_code>=400) { /* from rfc3608, 6.1. @@ -71,7 +75,7 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher } } -int sal_register(SalOp *op, const char *proxy, const char *from, int expires){ +int sal_register(SalOp *op, const char *proxy, const char *from, int expires,SalAddress* old_contact){ belle_sip_request_t *req; belle_sip_uri_t* req_uri; belle_sip_header_t* accept_header; @@ -96,6 +100,19 @@ int sal_register(SalOp *op, const char *proxy, const char *from, int expires){ accept_header = belle_sip_header_create("Accept", "application/sdp, text/plain, application/vnd.gsma.rcs-ft-http+xml"); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), accept_header); belle_sip_message_set_header(BELLE_SIP_MESSAGE(req),(belle_sip_header_t*)sal_op_create_contact(op)); + if (old_contact) { + belle_sip_header_contact_t *contact=belle_sip_header_contact_create((const belle_sip_header_address_t *)old_contact); + if (contact) { + char * tmp; + belle_sip_header_contact_set_expires(contact,0); /*remove old aor*/ + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), BELLE_SIP_HEADER(contact)); + tmp = belle_sip_object_to_string(contact); + ms_message("Clearing contact [%s] for op [%p]",tmp,op); + ms_free(tmp); + } else { + ms_error("Cannot add old contact header to op [%p]",op); + } + } return sal_op_send_and_create_refresher(op,req,expires,register_refresher_listener); } diff --git a/coreapi/private.h b/coreapi/private.h index c4470258a..aaf0f117a 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -531,6 +531,7 @@ struct _LinphoneProxyConfig LinphoneAddress *saved_proxy; LinphoneAddress *saved_identity; /*---*/ + LinphoneAddress *pending_contact; /*use to store previous contact in case of network failure*/ }; diff --git a/coreapi/proxy.c b/coreapi/proxy.c index d7e116c27..40b860511 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -173,6 +173,7 @@ void _linphone_proxy_config_destroy(LinphoneProxyConfig *cfg){ if (cfg->saved_proxy!=NULL) linphone_address_destroy(cfg->saved_proxy); if (cfg->saved_identity!=NULL) linphone_address_destroy(cfg->saved_identity); if (cfg->sent_headers!=NULL) sal_custom_header_free(cfg->sent_headers); + if (cfg->pending_contact) linphone_address_unref(cfg->pending_contact); _linphone_proxy_config_release_ops(cfg); } @@ -340,7 +341,19 @@ void linphone_proxy_config_apply(LinphoneProxyConfig *cfg,LinphoneCore *lc){ linphone_proxy_config_done(cfg); } -void linphone_proxy_config_stop_refreshing(LinphoneProxyConfig *cfg){ +void linphone_proxy_config_stop_refreshing(LinphoneProxyConfig * cfg){ + LinphoneAddress *contact_addr=NULL; + if ( cfg->op + && cfg->state == LinphoneRegistrationOk + && (contact_addr = (LinphoneAddress*)sal_op_get_contact_address(cfg->op)) + && linphone_address_get_transport(contact_addr) != LinphoneTransportUdp /*with udp, there is a risk of port reuse, so I prefer to not do anything for now*/) { + /*need to save current contact in order to reset is later*/ + linphone_address_ref(contact_addr); + if (cfg->pending_contact) + linphone_address_unref(cfg->pending_contact); + cfg->pending_contact=contact_addr; + + } if (cfg->publish_op){ sal_op_release(cfg->publish_op); cfg->publish_op=NULL; @@ -417,7 +430,12 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *cfg){ sal_op_set_user_pointer(cfg->op,cfg); - if (sal_register(cfg->op,proxy_string,from,cfg->expires)==0) { + + if (sal_register(cfg->op,proxy_string, cfg->reg_identity, cfg->expires, cfg->pending_contact)==0) { + if (cfg->pending_contact) { + linphone_address_unref(cfg->pending_contact); + cfg->pending_contact=NULL; + } linphone_proxy_config_set_state(cfg,LinphoneRegistrationProgress,"Registration in progress"); } else { linphone_proxy_config_set_state(cfg,LinphoneRegistrationFailed,"Registration failed"); diff --git a/include/sal/sal.h b/include/sal/sal.h index a404eb0b9..80f334835 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -704,7 +704,7 @@ LINPHONE_PUBLIC void sal_default_set_sdp_handling(Sal* h, SalOpSDPHandling handl LINPHONE_PUBLIC void sal_call_set_sdp_handling(SalOp *h, SalOpSDPHandling handling) ; /*Registration*/ -int sal_register(SalOp *op, const char *proxy, const char *from, int expires); +int sal_register(SalOp *op, const char *proxy, const char *from, int expires,SalAddress* old_contact); /*refresh a register, -1 mean use the last known value*/ int sal_register_refresh(SalOp *op, int expires); int sal_unregister(SalOp *h); diff --git a/tester/register_tester.c b/tester/register_tester.c index 6d0be9400..c2f883bd9 100644 --- a/tester/register_tester.c +++ b/tester/register_tester.c @@ -680,7 +680,7 @@ static void io_recv_error_retry_immediatly(){ BC_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationFailed,0,int,"%d"); sal_set_recv_error(lc->sal, 1); /*reset*/ - BC_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_LinphoneRegistrationOk,register_ok-number_of_udp_proxy+register_ok)); + BC_ASSERT_TRUE(wait_for_until(lc,lc,&counters->number_of_LinphoneRegistrationOk,register_ok-number_of_udp_proxy+register_ok,30000)); linphone_core_manager_destroy(lcm); }