Commit 641ba753 authored by Simon Morlat's avatar Simon Morlat
Browse files

refine transport selection algorithm and set proper routes for all kind of...

refine transport selection algorithm and set proper routes for all kind of operations: INVITE, MESSAGE, SUBSCRIBE.
parent 0d154471
......@@ -83,14 +83,22 @@ int sal_address_get_port_int(const SalAddress *addr){
return -1;
}
SalTransport sal_address_get_transport(const SalAddress* addr){
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
if (uri && belle_sip_uri_get_transport_param(uri)) {
return sal_transport_parse(belle_sip_uri_get_transport_param(uri));
} else
const char *transport=sal_address_get_transport_name(addr);
if (transport)
return sal_transport_parse(transport);
else
return SalTransportUDP;
};
const char* sal_address_get_transport_name(const SalAddress* addr){
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
if (uri) {
return belle_sip_uri_get_transport_param(uri);
}
return NULL;
}
void sal_address_set_display_name(SalAddress *addr, const char *display_name){
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
belle_sip_header_address_set_displayname(header_addr,display_name);
......@@ -132,8 +140,11 @@ void sal_address_set_param(SalAddress *addr,const char* name,const char* value){
belle_sip_parameters_set_parameter(parameters,name,value);
return ;
}
void sal_address_set_transport(SalAddress* addr,SalTransport transport){
SAL_ADDRESS_SET(addr,transport_param,sal_transport_to_string(transport));
}
void sal_address_set_transport_name(SalAddress* addr,const char *transport){
SAL_ADDRESS_SET(addr,transport_param,transport);
}
......@@ -65,11 +65,11 @@ void linphone_chat_room_destroy(LinphoneChatRoom *cr){
static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage* msg){
const char *route=NULL;
const char *identity=linphone_core_find_best_identity(cr->lc,cr->peer_url,&route);
MSList *routes=NULL;
SalOp *op=NULL;
LinphoneCall *call;
char* content_type;
const char *identity=NULL;
time_t t=time(NULL);
if (lp_config_get_int(cr->lc->config,"sip","chat_use_call_dialogs",0)){
......@@ -82,14 +82,19 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM
ms_message("send SIP message through the existing call.");
op = call->op;
call->pending_message=msg;
identity=linphone_core_find_best_identity(cr->lc,linphone_call_get_remote_address(call));
}
}
}
msg->time=t;
if (op==NULL){
LinphoneProxyConfig *proxy=linphone_core_lookup_known_proxy(cr->lc,cr->peer_url,&routes);
if (proxy){
identity=linphone_proxy_config_get_identity(proxy);
}else identity=linphone_core_get_primary_contact(cr->lc);
/*sending out of calls*/
op = sal_op_new(cr->lc->sal);
sal_op_set_route(op,route);
linphone_transfer_routes_to_op(routes,op);
sal_op_set_user_pointer(op, msg); /*if out of call, directly store msg*/
if (msg->custom_headers){
sal_op_set_custom_header(op,msg->custom_headers);
......
......@@ -109,13 +109,14 @@ void __linphone_friend_do_subscribe(LinphoneFriend *fr){
const char *route=NULL;
const char *from=NULL;
LinphoneProxyConfig *cfg;
MSList *routes=NULL;
friend=linphone_address_as_string(fr->uri);
cfg=linphone_core_lookup_known_proxy(fr->lc,linphone_friend_get_address(fr));
cfg=linphone_core_lookup_known_proxy(fr->lc,linphone_friend_get_address(fr),&routes);
if (cfg!=NULL){
route=linphone_proxy_config_get_route(cfg);
from=linphone_proxy_config_get_identity(cfg);
}else from=linphone_core_get_primary_contact(fr->lc);
if (fr->outsub==NULL){
/* people for which we don't have yet an answer should appear as offline */
fr->status=LinphoneStatusOffline;
......@@ -133,6 +134,7 @@ void __linphone_friend_do_subscribe(LinphoneFriend *fr){
sal_op_set_contact(fr->outsub,sal_op_get_contact(cfg->op));
else
sal_op_set_contact(fr->outsub,NULL);
linphone_transfer_routes_to_op(routes,fr->outsub);
sal_subscribe_presence(fr->outsub,from,friend);
fr->subscribe_active=TRUE;
ms_free(friend);
......
......@@ -219,20 +219,25 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
PayloadType *pt;
SalMediaDescription *old_md=call->localdesc;
int i;
const char *me=linphone_core_get_identity(lc);
LinphoneAddress *addr=linphone_address_new(me);
const char *username=linphone_address_get_username (addr);
const char *me;
SalMediaDescription *md=sal_media_description_new();
LinphoneAddress *addr;
bool_t keep_srtp_keys=lp_config_get_int(lc->config,"sip","keep_srtp_keys",0);
linphone_core_adapt_to_network(lc,call->ping_time,&call->params);
if (call->dest_proxy)
me=linphone_proxy_config_get_identity(call->dest_proxy);
else
me=linphone_core_get_identity(lc);
addr=linphone_address_new(me);
md->session_id=(old_md ? old_md->session_id : (rand() & 0xfff));
md->session_ver=(old_md ? (old_md->session_ver+1) : (rand() & 0xfff));
md->n_total_streams=(old_md ? old_md->n_total_streams : 1);
md->n_active_streams=1;
strncpy(md->addr,call->localip,sizeof(md->addr));
strncpy(md->username,username,sizeof(md->username));
strncpy(md->username,linphone_address_get_username(addr),sizeof(md->username));
if (call->params.down_bw)
md->bandwidth=call->params.down_bw;
......@@ -523,7 +528,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
from_str=linphone_address_as_string_uri_only(from);
sal_op_set_route(call->ping_op,sal_op_get_network_origin(op));
sal_op_set_user_pointer(call->ping_op,call);
sal_ping(call->ping_op,linphone_core_find_best_identity(lc,from,NULL),from_str);
sal_ping(call->ping_op,linphone_core_find_best_identity(lc,from),from_str);
ms_free(from_str);
}
}
......
......@@ -66,6 +66,7 @@ static void linphone_core_free_hooks(LinphoneCore *lc);
#include "enum.h"
const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc);
static void toggle_video_preview(LinphoneCore *lc, bool_t val);
......@@ -2003,7 +2004,7 @@ static void linphone_core_grab_buddy_infos(LinphoneCore *lc, LinphoneProxyConfig
for(elem=linphone_core_get_friend_list(lc);elem!=NULL;elem=elem->next){
LinphoneFriend *lf=(LinphoneFriend*)elem->data;
if (lf->info==NULL){
if (linphone_core_lookup_known_proxy(lc,lf->uri)==cfg){
if (linphone_core_lookup_known_proxy(lc,lf->uri,NULL)==cfg){
if (linphone_address_get_username(lf->uri)!=NULL){
BuddyLookupRequest *req;
char *tmp=linphone_address_as_string_uri_only(lf->uri);
......@@ -2295,7 +2296,53 @@ void linphone_core_notify_refer_state(LinphoneCore *lc, LinphoneCall *referer, L
}
}
LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const LinphoneAddress *uri){
/* returns the ideal route set for making an operation through this proxy.
* The list must be freed as well as the SalAddress content*/
/*
* rfc3608
6.1. Procedures at the UA
/.../
For example, some devices will use locally-configured
explicit loose routing to reach a next-hop proxy, and others will use
a default outbound-proxy routing rule. However, for the result to
function, the combination MUST provide valid routing in the local
environment. In general, the service route set is appended to any
locally configured route needed to egress the access proxy chain.
Systems designers must match the service routing policy of their
nodes with the basic SIP routing policy in order to get a workable
system.
*/
static MSList *make_routes_for_proxy(LinphoneProxyConfig *proxy, const LinphoneAddress *addr){
MSList *ret=NULL;
const char *local_route=linphone_proxy_config_get_route(proxy);
const LinphoneAddress *srv_route=linphone_proxy_config_get_service_route(proxy);
if (local_route){
ret=ms_list_append(ret,sal_address_new(local_route));
}
if (srv_route){
ret=ms_list_append(ret,sal_address_clone((SalAddress*)srv_route));
}
if (ret==NULL){
/*still no route, so try to build a route from proxy transport + identity host,
*in order to force using the transport required for this proxy, if any.*/
SalAddress *proxy_addr=sal_address_new(linphone_proxy_config_get_addr(proxy));
const char *transport=sal_address_get_transport_name(proxy_addr);
sal_address_destroy(proxy_addr);
if (transport){
SalAddress *route=sal_address_new(NULL);
sal_address_set_domain(route,sal_address_get_domain((SalAddress*)addr));
sal_address_set_port_int(route,sal_address_get_port_int((SalAddress*)addr));
sal_address_set_transport_name(route,transport);
ret=ms_list_append(ret,route);
}
}
return ret;
}
LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const LinphoneAddress *uri, MSList **routes){
const MSList *elem;
LinphoneProxyConfig *found_cfg=NULL;
LinphoneProxyConfig *default_cfg=lc->default_proxy;
......@@ -2303,8 +2350,10 @@ LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const L
/*always prefer the default proxy if it is matching the destination uri*/
if (default_cfg){
const char *domain=linphone_proxy_config_get_domain(default_cfg);
if (strcmp(domain,linphone_address_get_domain(uri))==0)
return default_cfg;
if (strcmp(domain,linphone_address_get_domain(uri))==0){
found_cfg=default_cfg;
goto end;
}
}
/*otherwise iterate through the other proxy config and return the first matching*/
......@@ -2313,18 +2362,34 @@ LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const L
const char *domain=linphone_proxy_config_get_domain(cfg);
if (domain!=NULL && strcmp(domain,linphone_address_get_domain(uri))==0){
found_cfg=cfg;
break;
goto end;
}
}
end:
if (found_cfg!=NULL && found_cfg!=default_cfg){
ms_message("Overriding default proxy setting for this call/message/subscribe operation.");
};
/*if route argument is given, fill adequate route set for this proxy.*/
if (routes){
if (found_cfg){
*routes=make_routes_for_proxy(found_cfg,uri);
}else if (default_cfg){
/*if the default proxy config has a locally configured route, we should use it*/
const char *route=linphone_proxy_config_get_route(default_cfg);
if (route)
*routes=ms_list_append(*routes,sal_address_new(route));
}
}
return found_cfg;
}
const char *linphone_core_find_best_identity(LinphoneCore *lc, const LinphoneAddress *to, const char **route){
LinphoneProxyConfig *cfg=linphone_core_lookup_known_proxy(lc,to);
const char *linphone_core_find_best_identity(LinphoneCore *lc, const LinphoneAddress *to){
LinphoneProxyConfig *cfg=linphone_core_lookup_known_proxy(lc,to,NULL);
if (cfg==NULL)
linphone_core_get_default_proxy (lc,&cfg);
if (cfg!=NULL){
if (route) *route=linphone_proxy_config_get_route(cfg);
return linphone_proxy_config_get_identity (cfg);
}
return linphone_core_get_primary_contact (lc);
......@@ -2474,6 +2539,15 @@ LinphoneCall * linphone_core_invite_address(LinphoneCore *lc, const LinphoneAddr
return call;
}
void linphone_transfer_routes_to_op(MSList *routes, SalOp *op){
MSList *it;
for(it=routes;it!=NULL;it=it->next){
SalAddress *addr=(SalAddress*)it->data;
sal_op_add_route_address(op,addr);
sal_address_destroy(addr);
}
ms_list_free(routes);
}
/**
* Initiates an outgoing call given a destination LinphoneAddress
......@@ -2493,12 +2567,11 @@ 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 *from=NULL;
LinphoneProxyConfig *proxy=NULL,*dest_proxy=NULL;
LinphoneProxyConfig *proxy=NULL;
LinphoneAddress *parsed_url2=NULL;
SalAddress *route=NULL;
SalAddress *proxy_addr=NULL;
char *real_url=NULL;
LinphoneCall *call;
MSList *routes=NULL;
bool_t defer = FALSE;
linphone_core_preempt_sound_resources(lc);
......@@ -2510,18 +2583,10 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
}
linphone_core_get_default_proxy(lc,&proxy);
real_url=linphone_address_as_string(addr);
dest_proxy=linphone_core_lookup_known_proxy(lc,addr);
if (proxy!=dest_proxy && dest_proxy!=NULL) {
ms_message("Overriding default proxy setting for this call:");
ms_message("The used identity will be %s",linphone_proxy_config_get_identity(dest_proxy));
}
proxy=linphone_core_lookup_known_proxy(lc,addr,&routes);
if (dest_proxy!=NULL)
from=linphone_proxy_config_get_identity(dest_proxy);
else if (proxy!=NULL)
if (proxy!=NULL)
from=linphone_proxy_config_get_identity(proxy);
/* if no proxy or no identity defined for this proxy, default to primary contact*/
......@@ -2530,64 +2595,9 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
parsed_url2=linphone_address_new(from);
call=linphone_call_new_outgoing(lc,parsed_url2,linphone_address_clone(addr),params);
call->dest_proxy=dest_proxy;
if (linphone_core_get_route(lc)) {
sal_op_set_route(call->op,linphone_core_get_route(lc));
}
/*
* rfc3608
6.1. Procedures at the UA
/.../
For example, some devices will use locally-configured
explicit loose routing to reach a next-hop proxy, and others will use
a default outbound-proxy routing rule. However, for the result to
function, the combination MUST provide valid routing in the local
environment. In general, the service route set is appended to any
locally configured route needed to egress the access proxy chain.
Systems designers must match the service routing policy of their
nodes with the basic SIP routing policy in order to get a workable
system.
*/
if (proxy && linphone_proxy_config_get_service_route(proxy)) {
/*set service route*/
sal_op_add_route_address(call->op,linphone_proxy_config_get_service_route(proxy));
} /*else, no route*/
if (!sal_op_get_route(call->op)) {
/*still no route, so try to build a route from proxy transport + identity host*/
route=sal_address_new(NULL);
/*first, get domain and port from requerst uri*/
sal_address_set_domain(route,sal_address_get_domain((SalAddress*)addr));
sal_address_set_port_int(route,sal_address_get_port_int((SalAddress*)addr));
/*next get transport either from request uri or from proxy if any*/
if (sal_address_get_transport((SalAddress*)addr)) {
sal_address_set_transport(route,sal_address_get_transport((SalAddress*)addr));
} else {
LinphoneProxyConfig* chosen_proxy=NULL;
if (dest_proxy)
chosen_proxy=dest_proxy;
else if (proxy)
chosen_proxy=proxy;
else
chosen_proxy=NULL;
if (chosen_proxy)
proxy_addr=sal_address_new(linphone_proxy_config_get_addr(chosen_proxy));
if (proxy_addr && sal_address_get_transport(proxy_addr))
sal_address_set_transport(route,sal_address_get_transport(proxy_addr));
else if (proxy_addr && linphone_proxy_config_guess_transport(chosen_proxy) && !sal_address_get_transport((SalAddress*)route)) {
/*compatibility mode*/
sal_address_set_transport((SalAddress*)route,sal_transport_parse(linphone_proxy_config_guess_transport(chosen_proxy)));
}
}
sal_op_add_route_address(call->op,route);
}
call->dest_proxy=proxy;
linphone_transfer_routes_to_op(routes,call->op);
if(linphone_core_add_call(lc,call)!= 0)
{
ms_warning("we had a problem in adding the call into the invite ... weird");
......@@ -3119,7 +3129,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call,
linphone_core_get_default_proxy(lc,&cfg);
call->dest_proxy=cfg;
call->dest_proxy=linphone_core_lookup_known_proxy(lc,call->log->to);
call->dest_proxy=linphone_core_lookup_known_proxy(lc,call->log->to,NULL);
if (cfg!=call->dest_proxy && call->dest_proxy!=NULL) {
ms_message("Overriding default proxy setting for this call:");
......
......@@ -64,7 +64,7 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){
tmp=linphone_address_as_string(uri);
ms_message("Receiving new subscription from %s.",from);
cfg=linphone_core_lookup_known_proxy(lc,uri);
cfg=linphone_core_lookup_known_proxy(lc,uri,NULL);
if (cfg!=NULL){
if (cfg->op){
if (sal_op_get_contact(cfg->op)) {
......@@ -73,6 +73,7 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){
}
}
}
/* check if we answer to this subscription */
if (linphone_find_friend(lc->friends,uri,&lf)!=NULL){
lf->insub=op;
......
......@@ -240,10 +240,7 @@ void linphone_proxy_config_write_all_to_config_file(LinphoneCore *lc);
* Can be NULL
* */
const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphoneProxyConfig* cfg);
/*
*guess the transport if only one trasport is configured at core level (for backward compatibility)
* */
const char* linphone_proxy_config_guess_transport(const LinphoneProxyConfig *obj);
int linphone_online_status_to_eXosip(LinphoneOnlineStatus os);
void linphone_friend_close_subscriptions(LinphoneFriend *lf);
......@@ -318,8 +315,9 @@ LinphoneFriend * linphone_friend_new_from_config_file(struct _LinphoneCore *lc,
void linphone_proxy_config_update(LinphoneProxyConfig *cfg);
void linphone_proxy_config_get_contact(LinphoneProxyConfig *cfg, const char **ip, int *port);
LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const LinphoneAddress *uri);
const char *linphone_core_find_best_identity(LinphoneCore *lc, const LinphoneAddress *to, const char **route);
LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const LinphoneAddress *uri, MSList **routes);
void linphone_transfer_routes_to_op(MSList *routes, SalOp *op);
const char *linphone_core_find_best_identity(LinphoneCore *lc, const LinphoneAddress *to);
int linphone_core_get_local_ip_for(int type, const char *dest, char *result);
LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(struct _LpConfig *config, int index);
......
......@@ -346,35 +346,8 @@ LinphoneAddress *guess_contact_for_register(LinphoneProxyConfig *obj){
}
return ret;
}
/*use for compatibility with linphone supporting only 1 transport at a time*/
const char* linphone_proxy_config_guess_transport(const LinphoneProxyConfig *obj) {
LCSipTransports transports;
const char* transport_name;
unsigned char transports_count=0;
linphone_core_get_sip_transports(obj->lc,&transports);
if (transports.udp_port>0) {
transports_count++;
transport_name="udp";
}
if (transports.tcp_port>0) {
transports_count++;
transport_name="tcp";
}
if (transports.tls_port>0) {
transports_count++;
transport_name="tls";
}
if (transports.dtls_port>0) {
transports_count++;
transport_name="dtls";
}
if (transports_count==1) {
return transport_name;
} else {
/*cannot guess transport*/
return NULL;
}
}
static void linphone_proxy_config_register(LinphoneProxyConfig *obj){
if (obj->reg_sendregister){
LinphoneAddress* proxy=linphone_address_new(obj->reg_proxy);
......@@ -383,10 +356,6 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *obj){
char *contact;
#else
LinphoneAddress *contact;
if (linphone_proxy_config_guess_transport(obj) && !sal_address_get_transport((SalAddress*)proxy)) {
sal_address_set_transport((SalAddress*)proxy,sal_transport_parse(linphone_proxy_config_guess_transport(obj)));
}
#endif
proxy_string=linphone_address_as_string_uri_only(proxy);
linphone_address_destroy(proxy);
......
......@@ -84,6 +84,7 @@ 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 *addr);
SalTransport sal_address_get_transport(const SalAddress* addr);
const char* sal_address_get_transport_name(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);
......@@ -96,7 +97,7 @@ char *sal_address_as_string_uri_only(const SalAddress *u);
void sal_address_destroy(SalAddress *u);
void sal_address_set_param(SalAddress *u,const char* name,const char* value);
void sal_address_set_transport(SalAddress* addr,SalTransport transport);
void sal_address_set_transport_name(SalAddress* addr,const char* transport);
Sal * sal_init();
void sal_uninit(Sal* sal);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment