diff --git a/src/libtomahawk/network/ConnectionManager.cpp b/src/libtomahawk/network/ConnectionManager.cpp index 7a0d9aade..f430b45a1 100644 --- a/src/libtomahawk/network/ConnectionManager.cpp +++ b/src/libtomahawk/network/ConnectionManager.cpp @@ -164,7 +164,69 @@ ConnectionManager::connectToPeer( const Tomahawk::peerinfo_ptr &peerInfo, bool l // If we are not connected, try to connect d_func()->currentPeerInfo = peerInfo; peerInfoDebug( peerInfo ) << "No existing connection found, trying to connect."; - d_func()->sipCandidates.append( peerInfo->sipInfos() ); + // Sort SipInfos + QList< SipInfo > anyOther; + QList< SipInfo > publicIPv4; + QList< SipInfo > publicIPv6; + QList< SipInfo > privateIPv4; + QList< SipInfo > privateIPv6; + foreach ( SipInfo sipInfo, peerInfo->sipInfos() ) + { + if ( !sipInfo.isVisible() ) + { + continue; + } + + QHostAddress ha; + if ( ha.setAddress( sipInfo.host() ) ) + { + if ( Servent::isValidExternalIP( ha ) ) + { + if ( ha.protocol() == QAbstractSocket::IPv6Protocol ) + { + publicIPv6.append( sipInfo ); + } + else + { + publicIPv4.append( sipInfo ); + } + } + else + { + if ( ha.protocol() == QAbstractSocket::IPv6Protocol ) + { + privateIPv6.append( sipInfo ); + } + else + { + privateIPv4.append( sipInfo ); + } + } + } + else + { + anyOther.append( sipInfo ); + } + + } + if ( Servent::instance()->ipv6ConnectivityLikely() && !publicIPv6.isEmpty() ) + { + // Prefer IPv6 over IPv4 + d_func()->sipCandidates.append( anyOther ); + d_func()->sipCandidates.append( publicIPv6 ); + d_func()->sipCandidates.append( publicIPv4 ); + d_func()->sipCandidates.append( privateIPv6 ); + d_func()->sipCandidates.append( privateIPv4 ); + } + else + { + // First try all IPv4 before trying IPv6 + d_func()->sipCandidates.append( anyOther ); + d_func()->sipCandidates.append( publicIPv4 ); + d_func()->sipCandidates.append( privateIPv4 ); + d_func()->sipCandidates.append( publicIPv6 ); + d_func()->sipCandidates.append( privateIPv6 ); + } QVariantMap m; m["conntype"] = "accept-offer"; diff --git a/src/libtomahawk/network/Servent.cpp b/src/libtomahawk/network/Servent.cpp index bdb77ee92..260211279 100644 --- a/src/libtomahawk/network/Servent.cpp +++ b/src/libtomahawk/network/Servent.cpp @@ -953,6 +953,20 @@ Servent::visibleExternally() const return (!d_func()->externalHostname.isNull()) || (d_func()->externalAddresses.length() > 0); } +bool +Servent::ipv6ConnectivityLikely() const +{ + foreach ( QHostAddress ha, d_func()->externalAddresses ) + { + if ( ha.protocol() == QAbstractSocket::IPv6Protocol && Servent::isValidExternalIP( ha ) ) + { + return true; + } + } + + return false; +} + int Servent::port() const { diff --git a/src/libtomahawk/network/Servent.h b/src/libtomahawk/network/Servent.h index 63f259ce3..76ccbc422 100644 --- a/src/libtomahawk/network/Servent.h +++ b/src/libtomahawk/network/Servent.h @@ -99,6 +99,13 @@ public: bool visibleExternally() const; + /** + * Is the probality that this host supports IPv6 high? + * + * Though we cannot fully test for IPv6 connectivity, some guesses based on non-localhost addresses are done. + */ + bool ipv6ConnectivityLikely() const; + /** * The port this Peer listens directly (per default) */