From 8fd309027f80b6d748cca8754b762cde4e93d408 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 26 Jun 2015 17:35:14 -0700 Subject: [PATCH] add a forced failover for hanging STUN dns lookup --- libraries/networking/src/HifiSockAddr.cpp | 22 ++++++++++---------- libraries/networking/src/LimitedNodeList.cpp | 17 +++++++++++++-- libraries/networking/src/LimitedNodeList.h | 1 + 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/libraries/networking/src/HifiSockAddr.cpp b/libraries/networking/src/HifiSockAddr.cpp index 8a967d7818..8951da58c9 100644 --- a/libraries/networking/src/HifiSockAddr.cpp +++ b/libraries/networking/src/HifiSockAddr.cpp @@ -22,14 +22,14 @@ HifiSockAddr::HifiSockAddr() : _address(), _port(0) { - + } HifiSockAddr::HifiSockAddr(const QHostAddress& address, quint16 port) : _address(address), _port(port) { - + } HifiSockAddr::HifiSockAddr(const HifiSockAddr& otherSockAddr) : @@ -37,7 +37,7 @@ HifiSockAddr::HifiSockAddr(const HifiSockAddr& otherSockAddr) : _address(otherSockAddr._address), _port(otherSockAddr._port) { - + } HifiSockAddr& HifiSockAddr::operator=(const HifiSockAddr& rhsSockAddr) { @@ -66,7 +66,7 @@ HifiSockAddr::HifiSockAddr(const QString& hostname, quint16 hostOrderPort, bool HifiSockAddr::HifiSockAddr(const sockaddr* sockaddr) { _address = QHostAddress(sockaddr); - + if (sockaddr->sa_family == AF_INET) { _port = ntohs(reinterpret_cast(sockaddr)->sin_port); } else { @@ -76,7 +76,7 @@ HifiSockAddr::HifiSockAddr(const sockaddr* sockaddr) { void HifiSockAddr::swap(HifiSockAddr& otherSockAddr) { using std::swap; - + swap(_address, otherSockAddr._address); swap(_port, otherSockAddr._port); } @@ -90,7 +90,7 @@ void HifiSockAddr::handleLookupResult(const QHostInfo& hostInfo) { qCDebug(networking) << "Lookup failed for" << hostInfo.lookupId() << ":" << hostInfo.errorString(); emit lookupFailed(); } - + foreach(const QHostAddress& address, hostInfo.addresses()) { // just take the first IPv4 address if (address.protocol() == QAbstractSocket::IPv4Protocol) { @@ -119,9 +119,9 @@ QDataStream& operator>>(QDataStream& dataStream, HifiSockAddr& sockAddr) { } QHostAddress getLocalAddress() { - + QHostAddress localAddress; - + foreach(const QNetworkInterface &networkInterface, QNetworkInterface::allInterfaces()) { if (networkInterface.flags() & QNetworkInterface::IsUp && networkInterface.flags() & QNetworkInterface::IsRunning @@ -131,19 +131,19 @@ QHostAddress getLocalAddress() { foreach(const QNetworkAddressEntry &entry, networkInterface.addressEntries()) { // make sure it's an IPv4 address that isn't the loopback if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol && !entry.ip().isLoopback()) { - + // set our localAddress and break out localAddress = entry.ip(); break; } } } - + if (!localAddress.isNull()) { break; } } - + // return the looked up local address return localAddress; } diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 123e140913..1d3a0a4397 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -743,6 +743,14 @@ void LimitedNodeList::startSTUNPublicSocketUpdate() { // if we don't know the STUN IP yet we need to have ourselves be called once it is known if (_stunSockAddr.getAddress().isNull()) { connect(&_stunSockAddr, &HifiSockAddr::lookupCompleted, this, &LimitedNodeList::startSTUNPublicSocketUpdate); + + // in case we just completely fail to lookup the stun socket - add a 10s timeout that will trigger the fail case + const quint64 STUN_DNS_LOOKUP_TIMEOUT_MSECS = 10 * 1000; + + QTimer* stunLookupFailTimer = new QTimer(this); + connect(stunLookupFailTimer, &QTimer::timeout, this, &LimitedNodeList::possiblyTimeoutSTUNAddressLookup); + stunLookupFailTimer->start(STUN_DNS_LOOKUP_TIMEOUT_MSECS); + } else { // setup our initial STUN timer here so we can quickly find out our public IP address _initialSTUNTimer = new QTimer(this); @@ -758,6 +766,13 @@ void LimitedNodeList::startSTUNPublicSocketUpdate() { } } +void LimitedNodeList::possiblyTimeoutSTUNAddressLookup() { + if (_stunSockAddr.getAddress().isNull()) { + // our stun address is still NULL, but we've been waiting for long enough - time to force a fail + stopInitialSTUNUpdate(false); + } +} + void LimitedNodeList::stopInitialSTUNUpdate(bool success) { _hasCompletedInitialSTUN = true; @@ -777,8 +792,6 @@ void LimitedNodeList::stopInitialSTUNUpdate(bool success) { flagTimeForConnectionStep(ConnectionStep::SetPublicSocketFromSTUN); } - assert(_initialSTUNTimer); - // stop our initial fast timer if (_initialSTUNTimer) { _initialSTUNTimer->stop(); diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 94063f49b1..46b631df52 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -317,6 +317,7 @@ protected: } private slots: void flagTimeForConnectionStep(ConnectionStep connectionStep, quint64 timestamp); + void possiblyTimeoutSTUNAddressLookup(); }; #endif // hifi_LimitedNodeList_h