Commit aaf00286 authored by Simon Morlat's avatar Simon Morlat
Browse files

Reimplement ip version selection for outgoing calls. This corresponds to...

Reimplement ip version selection for outgoing calls. This corresponds to commits 3fd706a7 and 08a66cdf of master branch.
parent 0adccd72
......@@ -1156,36 +1156,44 @@ void MediaSessionPrivate::getLocalIp (const Address &remoteAddr) {
* from the socket that connects to this proxy */
if (destProxy && destProxy->op) {
ip = destProxy->op->getLocalAddress(nullptr);
if (ip) {
lInfo() << "Found media local-ip from signaling.";
mediaLocalIp = ip;
return;
if (ip){
if (strchr(ip, ':') != nullptr && af == AF_INET){
/*case where we've decided to use IPv4 in select_outgoing_ip_version(), but the signaling local ip address is IPv6*/
/*we'll use the default media localip*/
}else{
lInfo() << "Found media local-ip from signaling.";
mediaLocalIp = ip;
return;
}
}
}
/* In last resort, attempt to find the local ip that routes to destination if given as an IP address,
or the default route (dest == nullptr) */
const char *dest = nullptr;
or the default route (dest is empty) */
string dest;
if (!destProxy) {
struct addrinfo hints;
struct addrinfo *res = nullptr;
string host(remoteAddr.getDomain());
int err;
/* FIXME the following doesn't work for IPv6 address because of brakets */
if (host[0] == '[') host = host.substr(1,host.size()-2);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_NUMERICHOST;
err = getaddrinfo(remoteAddr.getDomain().c_str(), nullptr, &hints, &res);
if (err == 0)
dest = remoteAddr.getDomain().c_str();
err = getaddrinfo(host.c_str(), nullptr, &hints, &res);
if (err == 0){
/*the remote address host part is real ip address. Use it.*/
dest = host;
}
if (res) freeaddrinfo(res);
}
if (dest || mediaLocalIp.empty() || needMediaLocalIpRefresh) {
if (!dest.empty() || mediaLocalIp.empty() || needMediaLocalIpRefresh) {
needMediaLocalIpRefresh = false;
char ip[LINPHONE_IPADDR_SIZE];
linphone_core_get_local_ip(q->getCore()->getCCore(), af, dest, ip);
mediaLocalIp = ip;
mediaLocalIp.reserve(LINPHONE_IPADDR_SIZE);
linphone_core_get_local_ip(q->getCore()->getCCore(), af, dest.c_str(), &mediaLocalIp[0]);
}
}
......@@ -1227,44 +1235,45 @@ void MediaSessionPrivate::selectIncomingIpVersion () {
* Choose IP version we are going to use for RTP streams IP address advertised in SDP.
* The algorithm is as follows:
* - if ipv6 is disabled at the core level, it is always AF_INET
* - Otherwise, if the destination address for the call is an IPv6 address, use IPv6.
* - Otherwise, if the call is done through a known proxy config, then use the information obtained during REGISTER
* - Otherwise if the destination address for the call is an IPv6 address, use IPv6.
* to know if IPv6 is supported by the server.
**/
void MediaSessionPrivate::selectOutgoingIpVersion () {
L_Q();
if (!linphone_core_ipv6_enabled(q->getCore()->getCCore())) {
af = AF_INET;
return;
}
const LinphoneAddress *to = linphone_call_log_get_to_address(log);
if (sal_address_is_ipv6(L_GET_PRIVATE_FROM_C_OBJECT(to)->getInternalAddress()))
af = AF_INET6;
else if (destProxy && destProxy->op)
af = destProxy->op->getAddressFamily();
else {
char ipv4[LINPHONE_IPADDR_SIZE];
char ipv6[LINPHONE_IPADDR_SIZE];
bool haveIpv6 = false;
bool haveIpv4 = false;
/* Check connectivity for IPv4 and IPv6 */
if (linphone_core_get_local_ip_for(AF_INET6, nullptr, ipv6) == 0)
haveIpv6 = true;
if (linphone_core_get_local_ip_for(AF_INET, nullptr, ipv4) == 0)
haveIpv4 = true;
if (haveIpv6) {
if (!haveIpv4)
af = AF_INET6;
else if (lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "rtp", "prefer_ipv6", 1)) /* This property tells whether ipv6 is prefered if two versions are available */
af = AF_INET6;
else
af = AF_INET;
} else
af = AF_INET;
/* Fill the media_localip default value since we have it here */
mediaLocalIp = (af == AF_INET6) ? ipv6 : ipv4;
}
char ipv4[LINPHONE_IPADDR_SIZE];
char ipv6[LINPHONE_IPADDR_SIZE];
bool_t have_ipv6 = FALSE;
bool_t have_ipv4 = FALSE;
af = AF_UNSPEC;
if (linphone_core_get_local_ip_for(AF_INET, nullptr, ipv4) == 0){
have_ipv4 = TRUE;
}
if (linphone_core_ipv6_enabled(q->getCore()->getCCore())){
const LinphoneAddress *to = linphone_call_log_get_to_address(log);
if (linphone_core_get_local_ip_for(AF_INET6, nullptr, ipv6) == 0){
have_ipv6 = TRUE;
}
if (destProxy && destProxy->op){
/*we can determine from the proxy connection whether IPv6 works - this is the most reliable*/
af = destProxy->op->getAddressFamily();
}else if (sal_address_is_ipv6(L_GET_PRIVATE_FROM_C_OBJECT(to)->getInternalAddress())){
af = AF_INET6;
}
if (lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "rtp", "prefer_ipv6", 1) == 0 && have_ipv4){
/* This is the case where ipv4 is to be prefered if both are available.*/
af = AF_INET; /*we'll use IPv4*/
lInfo()<<"prefer_ipv6 is set to false, as both IP versions are available we are going to use IPv4";
}
if (af == AF_UNSPEC){
af = have_ipv6 ? AF_INET6 : AF_INET;
}
}else af=AF_INET;
/*fill the media_localip default value since we have it here*/
mediaLocalIp = (af == AF_INET6) ? ipv6 : ipv4;
}
// -----------------------------------------------------------------------------
......
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