From b202a6e9cf5b6668a77300e87a96b309ab9a5449 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Thu, 3 Sep 2009 15:53:04 +0200 Subject: [PATCH] arrange to set correct local interface in SDP and contact. Use proxy received/rport if possible in INVITEs. --- linphone/coreapi/linphonecore.c | 79 ++++++++++++++++++++------------- linphone/coreapi/misc.c | 55 +++++++++++++++++++++++ linphone/coreapi/private.h | 3 +- 3 files changed, 105 insertions(+), 32 deletions(-) diff --git a/linphone/coreapi/linphonecore.c b/linphone/coreapi/linphonecore.c index 4a1073db0..782d9afed 100644 --- a/linphone/coreapi/linphonecore.c +++ b/linphone/coreapi/linphonecore.c @@ -776,32 +776,14 @@ void linphone_core_get_local_ip(LinphoneCore *lc, const char *dest, char *result strncpy(result,linphone_core_get_nat_address(lc),LINPHONE_IPADDR_SIZE); return; } - if (linphone_core_get_firewall_policy(lc)==LINPHONE_POLICY_USE_STUN) { - if (lc->sip_conf.ipv6_enabled){ - ms_warning("stun support is not implemented for ipv6"); - }else{ - /* we no more use stun for sip socket*/ -#if 0 - int mport=0; - ms_message("doing stun lookup for local address..."); - if (stun_get_localip(lc,sock,linphone_core_get_sip_port(lc),result,&mport)){ - if (!lc->net_conf.nat_sdp_only) - eXosip_masquerade_contact(result,mport); - return; - } - ms_warning("stun lookup failed, falling back to a local interface..."); -#endif - } - - } + if (linphone_core_get_local_ip_for(dest,result)==0) + return; + /*else fallback to exosip routine that will attempt to find the most realistic interface */ if (eXosip_guess_localip(lc->sip_conf.ipv6_enabled ? AF_INET6 : AF_INET,result,LINPHONE_IPADDR_SIZE)<0){ /*default to something */ strncpy(result,lc->sip_conf.ipv6_enabled ? "::1" : "127.0.0.1",LINPHONE_IPADDR_SIZE); ms_error("Could not find default routable ip address !"); - } - /* - eXosip_masquerade_contact(NULL,0); - */ + } } const char *linphone_core_get_primary_contact(LinphoneCore *lc) @@ -1274,7 +1256,7 @@ void linphone_set_sdp(osip_message_t *sip, const char *sdpmesg){ osip_message_set_content_length(sip,clen); } -LinphoneProxyConfig * linphone_core_goes_through_known_proxy(LinphoneCore *lc, const char *uri){ +LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const char *uri){ const MSList *elem; LinphoneProxyConfig *found_cfg=NULL; osip_from_t *parsed_uri; @@ -1292,13 +1274,36 @@ LinphoneProxyConfig * linphone_core_goes_through_known_proxy(LinphoneCore *lc, c return found_cfg; } -static void fix_contact(osip_message_t *msg, const char *localip){ +static void fix_contact(osip_message_t *msg, const char *localip, LinphoneProxyConfig *dest_proxy){ osip_contact_t *ctt=NULL; + const char *ip=NULL; + int port=5060; osip_message_get_contact(msg,0,&ctt); if (ctt!=NULL){ - osip_free(ctt->url->host); - ctt->url->host=osip_strdup(localip); + if (dest_proxy!=NULL){ + /* if we know the request will go to a known proxy for which we are registered, + we can use the same contact address as in the register */ + linphone_proxy_config_get_contact(dest_proxy,&ip,&port); + }else{ + ip=localip; + port=linphone_core_get_sip_port(dest_proxy->lc); + } + if (ip!=NULL){ + osip_free(ctt->url->host); + ctt->url->host=osip_strdup(ip); + } + if (port!=0){ + char tmp[10]={0}; + char *str; + snprintf(tmp,sizeof(tmp)-1,"%i",port); + if (ctt->url->port!=NULL) + osip_free(ctt->url->port); + ctt->url->port=osip_strdup(tmp); + osip_contact_to_str(ctt,&str); + ms_message("Contact has been fixed to %s",str); + osip_free(str); + } } } @@ -1315,6 +1320,7 @@ int linphone_core_invite(LinphoneCore *lc, const char *url) osip_from_t *parsed_url2=NULL; osip_to_t *real_parsed_url=NULL; char *real_url=NULL; + LinphoneProxyConfig *dest_proxy=NULL; if (lc->call!=NULL){ lc->vtable.display_warning(lc,_("Sorry, having multiple simultaneous calls is not supported yet !")); @@ -1328,16 +1334,23 @@ int linphone_core_invite(LinphoneCore *lc, const char *url) gstate_new_state(lc, GSTATE_CALL_ERROR, NULL); return -1; } - if (proxy!=NULL) { - from=linphone_proxy_config_get_identity(proxy); - + dest_proxy=linphone_core_lookup_known_proxy(lc,real_url); + + 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)); } + + if (dest_proxy!=NULL) + from=linphone_proxy_config_get_identity(dest_proxy); + else if (proxy!=NULL) + from=linphone_proxy_config_get_identity(proxy); + /* if no proxy or no identity defined for this proxy, default to primary contact*/ if (from==NULL) from=linphone_core_get_primary_contact(lc); err=eXosip_call_build_initial_invite(&invite,real_url,from, route,"Phone call"); - if (err<0){ ms_warning("Could not build initial invite"); goto end; @@ -1352,7 +1365,7 @@ int linphone_core_invite(LinphoneCore *lc, const char *url) /*try to be best-effort in giving real local or routable contact address, except when the user choosed to override the ipaddress */ if (linphone_core_get_firewall_policy(lc)!=LINPHONE_POLICY_USE_NAT_ADDRESS) - fix_contact(invite,lc->call->localip); + fix_contact(invite,lc->call->localip,dest_proxy); barmsg=ortp_strdup_printf("%s %s", _("Contacting"), real_url); lc->vtable.display_status(lc,barmsg); @@ -1731,6 +1744,10 @@ int linphone_core_accept_call(LinphoneCore *lc, const char *url) ms_error("Fail to build answer for call: err=%i",err); return -1; } + /*try to be best-effort in giving real local or routable contact address, + except when the user choosed to override the ipaddress */ + if (linphone_core_get_firewall_policy(lc)!=LINPHONE_POLICY_USE_NAT_ADDRESS) + fix_contact(msg,call->localip,NULL); /*if a sdp answer is computed, send it, else send an offer */ sdpmesg=call->sdpctx->answerstr; if (sdpmesg==NULL){ diff --git a/linphone/coreapi/misc.c b/linphone/coreapi/misc.c index d58910d30..3b781185e 100644 --- a/linphone/coreapi/misc.c +++ b/linphone/coreapi/misc.c @@ -745,3 +745,58 @@ int linphone_core_wake_up_possible_already_running_instance( } return -1; } + +int linphone_core_get_local_ip_for(const char *dest, char *result){ + int err,tmp; + struct addrinfo hints; + struct addrinfo *res=NULL; + struct sockaddr_storage addr; + ortp_socket_t sock; +#ifdef __APPLE_CC__ + int s; +#else + socklen_t s; +#endif + memset(&hints,0,sizeof(hints)); + hints.ai_family=PF_UNSPEC; + hints.ai_socktype=SOCK_DGRAM; + /*hints.ai_flags=AI_NUMERICHOST|AI_CANONNAME;*/ + err=getaddrinfo(dest,"5060",&hints,&res); + if (err!=0){ + ms_error("getaddrinfo() error: %s",gai_strerror(err)); + return -1; + } + if (res==NULL){ + ms_error("bug: getaddrinfo returned nothing."); + return -1; + } + sock=socket(res->ai_family,SOCK_DGRAM,0); + tmp=1; + err=setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&tmp,sizeof(int)); + if (err<0){ + ms_warning("Error in setsockopt: %s",strerror(errno)); + } + err=connect(sock,res->ai_addr,res->ai_addrlen); + if (err<0) { + ms_error("Error in connect: %s",strerror(errno)); + freeaddrinfo(res); + close(sock); + return -1; + } + freeaddrinfo(res); + res=NULL; + s=sizeof(addr); + err=getsockname(sock,(struct sockaddr*)&addr,&s); + if (err!=0) { + ms_error("Error in getsockname: %s",strerror(errno)); + close(sock); + return -1; + } + err=getnameinfo((struct sockaddr *)&addr,s,result,LINPHONE_IPADDR_SIZE,NULL,0,NI_NUMERICHOST); + if (err!=0){ + ms_error("getnameinfo error: %s",strerror(errno)); + } + close(sock); + ms_message("Local interface to reach %s is %s.",dest,result); + return 0; +} diff --git a/linphone/coreapi/private.h b/linphone/coreapi/private.h index 88067899b..7e1b76c74 100644 --- a/linphone/coreapi/private.h +++ b/linphone/coreapi/private.h @@ -134,6 +134,7 @@ void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call); void linphone_core_write_friends_config(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 char *uri); +int linphone_core_get_local_ip_for(const char *dest, char *result); #endif /* _PRIVATE_H */