Commit aa5f676d authored by Ghislain MARY's avatar Ghislain MARY
Browse files

Improve fetching of the local IP to take into account the destination.

parent c68dd94a
......@@ -645,6 +645,61 @@ static void linphone_call_outgoing_select_ip_version(LinphoneCall *call, Linphon
}else call->af=AF_INET;
}
/**
* Fill the local ip that routes to the internet according to the destination, or guess it by other special means (upnp).
*/
static void linphone_call_get_local_ip(LinphoneCall *call, const LinphoneAddress *remote_addr){
const char *ip;
int af = call->af;
const char *dest = NULL;
if (call->dest_proxy == NULL) {
struct addrinfo hints;
struct addrinfo *res = NULL;
int err;
const char *domain = linphone_address_get_domain(remote_addr);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_NUMERICHOST;
err = getaddrinfo(domain, NULL, &hints, &res);
if (err == 0) {
dest = domain;
}
}
if (linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseNatAddress
&& (ip=linphone_core_get_nat_address_resolved(call->core))!=NULL){
strncpy(call->localip,ip,LINPHONE_IPADDR_SIZE);
return;
}
#ifdef BUILD_UPNP
else if (call->core->upnp != NULL && linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseUpnp &&
linphone_upnp_context_get_state(call->core->upnp) == LinphoneUpnpStateOk) {
ip = linphone_upnp_context_get_external_ipaddress(call->core->upnp);
strncpy(call->localip,ip,LINPHONE_IPADDR_SIZE);
return;
}
#endif //BUILD_UPNP
if (af==AF_UNSPEC){
if (linphone_core_ipv6_enabled(call->core)){
bool_t has_ipv6;
has_ipv6=linphone_core_get_local_ip_for(AF_INET6,dest,call->localip)==0;
if (strcmp(call->localip,"::1")!=0)
return; /*this machine has real ipv6 connectivity*/
if (linphone_core_get_local_ip_for(AF_INET,dest,call->localip)==0 && strcmp(call->localip,"127.0.0.1")!=0)
return; /*this machine has only ipv4 connectivity*/
if (has_ipv6){
/*this machine has only local loopback for both ipv4 and ipv6, so prefer ipv6*/
strncpy(call->localip,"::1",LINPHONE_IPADDR_SIZE);
return;
}
}
/*in all other cases use IPv4*/
af=AF_INET;
}
if (linphone_core_get_local_ip_for(af,dest,call->localip)==0)
return;
}
static void linphone_call_destroy(LinphoneCall *obj);
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCall);
......@@ -662,7 +717,7 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr
call->dir=LinphoneCallOutgoing;
call->core=lc;
linphone_call_outgoing_select_ip_version(call,to,cfg);
linphone_core_get_local_ip(lc,call->af,call->localip);
linphone_call_get_local_ip(call, to);
linphone_call_init_common(call,from,to);
_linphone_call_params_copy(&call->params,params);
......@@ -748,7 +803,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
}
linphone_address_clean(from);
linphone_core_get_local_ip(lc,call->af,call->localip);
linphone_call_get_local_ip(call, from);
linphone_call_init_common(call, from, to);
call->log->call_id=ms_strdup(sal_op_get_call_id(op)); /*must be known at that time*/
call->dest_proxy = linphone_core_lookup_known_proxy(call->core, to);
......
......@@ -1522,44 +1522,6 @@ int linphone_core_set_primary_contact(LinphoneCore *lc, const char *contact)
}
/*Returns the local ip that routes to the internet, or guessed by other special means (upnp)*/
/*result must be an array of chars at least LINPHONE_IPADDR_SIZE */
void linphone_core_get_local_ip(LinphoneCore *lc, int af, char *result){
const char *ip;
if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress
&& (ip=linphone_core_get_nat_address_resolved(lc))!=NULL){
strncpy(result,ip,LINPHONE_IPADDR_SIZE);
return;
}
#ifdef BUILD_UPNP
else if (lc->upnp != NULL && linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp &&
linphone_upnp_context_get_state(lc->upnp) == LinphoneUpnpStateOk) {
ip = linphone_upnp_context_get_external_ipaddress(lc->upnp);
strncpy(result,ip,LINPHONE_IPADDR_SIZE);
return;
}
#endif //BUILD_UPNP
if (af==AF_UNSPEC){
if (linphone_core_ipv6_enabled(lc)){
bool_t has_ipv6;
has_ipv6=linphone_core_get_local_ip_for(AF_INET6,NULL,result)==0;
if (strcmp(result,"::1")!=0)
return; /*this machine has real ipv6 connectivity*/
if (linphone_core_get_local_ip_for(AF_INET,NULL,result)==0 && strcmp(result,"127.0.0.1")!=0)
return; /*this machine has only ipv4 connectivity*/
if (has_ipv6){
/*this machine has only local loopback for both ipv4 and ipv6, so prefer ipv6*/
strncpy(result,"::1",LINPHONE_IPADDR_SIZE);
return;
}
}
/*in all other cases use IPv4*/
af=AF_INET;
}
if (linphone_core_get_local_ip_for(af,NULL,result)==0)
return;
}
static void update_primary_contact(LinphoneCore *lc){
char *guessed=NULL;
char tmp[LINPHONE_IPADDR_SIZE];
......@@ -1574,7 +1536,7 @@ static void update_primary_contact(LinphoneCore *lc){
ms_error("Could not parse identity contact !");
url=linphone_address_new("sip:unknown@unkwownhost");
}
linphone_core_get_local_ip(lc, AF_UNSPEC, tmp);
linphone_core_get_local_ip_for(AF_UNSPEC, NULL, tmp);
if (strcmp(tmp,"127.0.0.1")==0 || strcmp(tmp,"::1")==0 ){
ms_warning("Local loopback network only !");
lc->sip_conf.loopback_only=TRUE;
......@@ -2170,7 +2132,7 @@ static void monitor_network_state(LinphoneCore *lc, time_t curtime){
/* only do the network up checking every five seconds */
if (lc->network_last_check==0 || (curtime-lc->network_last_check)>=5){
linphone_core_get_local_ip(lc,AF_UNSPEC,newip);
linphone_core_get_local_ip_for(AF_UNSPEC,NULL,newip);
if (strcmp(newip,"::1")!=0 && strcmp(newip,"127.0.0.1")!=0){
new_status=TRUE;
}else new_status=FALSE; /*no network*/
......
......@@ -292,7 +292,6 @@ void linphone_core_update_friends_subscriptions(LinphoneCore *lc, LinphoneProxyC
int parse_hostname_to_addr(const char *server, struct sockaddr_storage *ss, socklen_t *socklen, int default_port);
void linphone_core_get_local_ip(LinphoneCore *lc, int af, char *result);
bool_t host_has_ipv6_network();
bool_t lp_spawn_command_line_sync(const char *command, char **result,int *command_ret);
......
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