diff --git a/coreapi/bellesip_sal/sal_op_registration.c b/coreapi/bellesip_sal/sal_op_registration.c index 8f708f6ad..e94407598 100644 --- a/coreapi/bellesip_sal/sal_op_registration.c +++ b/coreapi/bellesip_sal/sal_op_registration.c @@ -39,6 +39,9 @@ static void register_response_event(void *user_ctx, const belle_sip_response_eve belle_sip_request_t* original_request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); belle_sip_header_contact_t* original_contact=belle_sip_message_get_header_by_type(original_request,belle_sip_header_contact_t); const belle_sip_list_t* contact_header_list; + belle_sip_header_service_route_t* service_route; + belle_sip_header_address_t* service_route_address=NULL; + int response_code = belle_sip_response_get_status_code(response); int expires=-1; char* tmp_string; @@ -77,6 +80,12 @@ static void register_response_event(void *user_ctx, const belle_sip_response_eve ms_message("Neither Expires header nor corresponding Contact header found, using expires value [%i] from request",expires); } } + /*check service route rfc3608*/ + 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))); + } + sal_op_set_service_route(op,(const SalAddress*)service_route_address); + if (service_route_address) belle_sip_object_unref(service_route_address); op->base.root->callbacks.register_success(op,expires>0); /*always cancel pending refresh if any*/ @@ -92,6 +101,18 @@ static void register_response_event(void *user_ctx, const belle_sip_response_eve } default:{ + + /* from rfc3608, 6.1. + If the UA refreshes the registration, the stored value of the Service- + Route is updated according to the Service-Route header field of the + latest 200 class response. If there is no Service-Route header field + in the response, the UA clears any service route for that address- + of-record previously stored by the UA. If the re-registration + request is refused or if an existing registration expires and the UA + chooses not to re-register, the UA SHOULD discard any stored service + route for that address-of-record. */ + sal_op_set_service_route(op,NULL); + ms_error("Unexpected answer [%s] for registration request bound to [%s]",belle_sip_response_get_reason_phrase(response),op->base.from); op->base.root->callbacks.register_failure(op,SalErrorFailure,SalReasonUnknown,belle_sip_response_get_reason_phrase(response)); break; diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 26e0ba572..763f59058 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -2421,7 +2421,6 @@ LinphoneCall * linphone_core_invite_address(LinphoneCore *lc, const LinphoneAddr **/ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const LinphoneAddress *addr, const LinphoneCallParams *params) { - const char *route=NULL; const char *from=NULL; LinphoneProxyConfig *proxy=NULL,*dest_proxy=NULL; LinphoneAddress *parsed_url2=NULL; @@ -2437,7 +2436,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const return NULL; } linphone_core_get_default_proxy(lc,&proxy); - route=linphone_core_get_route(lc); + real_url=linphone_address_as_string(addr); dest_proxy=linphone_core_lookup_known_proxy(lc,addr); @@ -2459,7 +2458,15 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const call=linphone_call_new_outgoing(lc,parsed_url2,linphone_address_clone(addr),params); call->dest_proxy=dest_proxy; - sal_op_set_route(call->op,route); + + if (linphone_core_get_route(lc)) { + sal_op_set_route(call->op,linphone_core_get_route(lc)); + } else if (proxy && linphone_proxy_config_get_service_route(proxy)) { + /*set service route*/ + sal_op_set_route_address(call->op,linphone_proxy_config_get_service_route(proxy)); + } /*else, no route*/ + + if(linphone_core_add_call(lc,call)!= 0) { diff --git a/coreapi/private.h b/coreapi/private.h index bc2b65cfb..70a659679 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -187,6 +187,12 @@ int linphone_core_abort_call(LinphoneCore *lc, LinphoneCall *call, const char *e int linphone_proxy_config_send_publish(LinphoneProxyConfig *cfg, LinphoneOnlineStatus os); void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState rstate, const char *message); void linphone_proxy_config_write_all_to_config_file(LinphoneCore *lc); +/* + * returns service route as defined in as defined by rfc3608, might be a list instead of just one. + * Can be NULL + * */ +const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphoneProxyConfig* cfg); + int linphone_online_status_to_eXosip(LinphoneOnlineStatus os); void linphone_friend_close_subscriptions(LinphoneFriend *lf); diff --git a/coreapi/proxy.c b/coreapi/proxy.c index cd8a03f1b..fe5a724e8 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -1254,4 +1254,6 @@ void linphone_proxy_config_set_error(LinphoneProxyConfig *cfg,LinphoneReason err cfg->error = error; } - +const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphoneProxyConfig* cfg) { + return cfg->op?(const LinphoneAddress*) sal_op_get_service_route(cfg->op):NULL; +} diff --git a/coreapi/sal.c b/coreapi/sal.c index f995ee712..5809b2617 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -395,6 +395,9 @@ void __sal_op_free(SalOp *op){ sal_media_description_unref(b->remote_media); if (b->call_id) ms_free((void*)b->call_id); + if (b->service_route) { + sal_address_destroy(b->service_route); + } ms_free(op); } @@ -461,3 +464,12 @@ const char* sal_reason_to_string(const SalReason reason) { default: return "Unkown reason"; } } +const SalAddress* sal_op_get_service_route(const SalOp *op) { + return ((SalOpBase*)op)->service_route; +} +void sal_op_set_service_route(SalOp *op,const SalAddress* service_route) { + if (((SalOpBase*)op)->service_route) + sal_address_destroy(((SalOpBase*)op)->service_route); + + ((SalOpBase*)op)->service_route=service_route?sal_address_clone(service_route):NULL; +} diff --git a/coreapi/sal.h b/coreapi/sal.h index 016e6cbd3..281397143 100644 --- a/coreapi/sal.h +++ b/coreapi/sal.h @@ -229,6 +229,7 @@ typedef struct SalOpBase{ SalMediaDescription *remote_media; void *user_pointer; const char* call_id; + SalAddress* service_route; /*as defined by rfc3608, might be a list*/ } SalOpBase; @@ -416,6 +417,9 @@ const char *sal_op_get_remote_ua(const SalOp *op); void *sal_op_get_user_pointer(const SalOp *op); const char* sal_op_get_call_id(const SalOp *op); +const SalAddress* sal_op_get_service_route(const SalOp *op); +void sal_op_set_service_route(SalOp *op,const SalAddress* service_route); + /*Call API*/ int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc); int sal_call(SalOp *h, const char *from, const char *to);