From ed9faf4189a0dbd34b756d875d6985acbbbbad53 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 7 Mar 2016 18:00:09 -0800 Subject: [PATCH 1/4] add a secondary check for local IP address --- assignment-client/src/octree/OctreeServer.cpp | 2 +- interface/src/FileLogger.cpp | 2 +- libraries/networking/src/HifiSockAddr.cpp | 2 +- libraries/networking/src/HifiSockAddr.h | 2 +- libraries/networking/src/LimitedNodeList.cpp | 69 ++++++++++++++++--- libraries/networking/src/LimitedNodeList.h | 11 ++- 6 files changed, 71 insertions(+), 17 deletions(-) diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index aedf451924..a7fa068868 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -981,7 +981,7 @@ void OctreeServer::readConfiguration() { _settings = settingsSectionObject; // keep this for later if (!readOptionString(QString("statusHost"), settingsSectionObject, _statusHost) || _statusHost.isEmpty()) { - _statusHost = getLocalAddress().toString(); + _statusHost = getGuessedLocalAddress().toString(); } qDebug("statusHost=%s", qPrintable(_statusHost)); diff --git a/interface/src/FileLogger.cpp b/interface/src/FileLogger.cpp index 10dce38fbc..247eb66c99 100644 --- a/interface/src/FileLogger.cpp +++ b/interface/src/FileLogger.cpp @@ -32,7 +32,7 @@ static const uint64_t MAX_LOG_AGE_USECS = USECS_PER_SECOND * 3600; QString getLogRollerFilename() { QString result = FileUtils::standardPath(LOGS_DIRECTORY); - QHostAddress clientAddress = getLocalAddress(); + QHostAddress clientAddress = getGuessedLocalAddress(); QDateTime now = QDateTime::currentDateTime(); result.append(QString(FILENAME_FORMAT).arg(clientAddress.toString(), now.toString(DATETIME_FORMAT))); return result; diff --git a/libraries/networking/src/HifiSockAddr.cpp b/libraries/networking/src/HifiSockAddr.cpp index 81a58df730..bc4c1a1599 100644 --- a/libraries/networking/src/HifiSockAddr.cpp +++ b/libraries/networking/src/HifiSockAddr.cpp @@ -124,7 +124,7 @@ QDataStream& operator>>(QDataStream& dataStream, HifiSockAddr& sockAddr) { return dataStream; } -QHostAddress getLocalAddress() { +QHostAddress getGuessedLocalAddress() { QHostAddress localAddress; diff --git a/libraries/networking/src/HifiSockAddr.h b/libraries/networking/src/HifiSockAddr.h index cb5d0acc12..063a41a202 100644 --- a/libraries/networking/src/HifiSockAddr.h +++ b/libraries/networking/src/HifiSockAddr.h @@ -92,7 +92,7 @@ namespace std { } -QHostAddress getLocalAddress(); +QHostAddress getGuessedLocalAddress(); Q_DECLARE_METATYPE(HifiSockAddr); diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index f236f9d596..4ee8a8bf49 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -77,7 +77,7 @@ LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short // check for local socket updates every so often const int LOCAL_SOCKET_UPDATE_INTERVAL_MSECS = 5 * 1000; QTimer* localSocketUpdate = new QTimer(this); - connect(localSocketUpdate, &QTimer::timeout, this, &LimitedNodeList::updateLocalSockAddr); + connect(localSocketUpdate, &QTimer::timeout, this, &LimitedNodeList::updateLocalSocket); localSocketUpdate->start(LOCAL_SOCKET_UPDATE_INTERVAL_MSECS); QTimer* silentNodeTimer = new QTimer(this); @@ -85,7 +85,7 @@ LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short silentNodeTimer->start(NODE_SILENCE_THRESHOLD_MSECS); // check the local socket right now - updateLocalSockAddr(); + updateLocalSocket(); // set &PacketReceiver::handleVerifiedPacket as the verified packet callback for the udt::Socket _nodeSocket.setPacketHandler( @@ -886,17 +886,66 @@ void LimitedNodeList::stopInitialSTUNUpdate(bool success) { stunOccasionalTimer->start(STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS); } -void LimitedNodeList::updateLocalSockAddr() { - HifiSockAddr newSockAddr(getLocalAddress(), _nodeSocket.localPort()); - if (newSockAddr != _localSockAddr) { +void LimitedNodeList::updateLocalSocket() { + // when update is called, if the local socket is empty then start with the guessed local socket + if (_localSockAddr.isNull()) { + setLocalSocket(HifiSockAddr { getGuessedLocalAddress(), _nodeSocket.localPort() }); + } - if (_localSockAddr.isNull()) { - qCDebug(networking) << "Local socket is" << newSockAddr; - } else { - qCDebug(networking) << "Local socket has changed from" << _localSockAddr << "to" << newSockAddr; + // attempt to use Google's DNS to confirm that local IP + static const QHostAddress RELIABLE_LOCAL_IP_CHECK_HOST = QHostAddress { "8.8.8.8" }; + static const int RELIABLE_LOCAL_IP_CHECK_PORT = 53; + + QTcpSocket* localIPTestSocket = new QTcpSocket; + + connect(localIPTestSocket, &QTcpSocket::connected, this, &LimitedNodeList::connectedForLocalSocketTest); + connect(localIPTestSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(errorTestingLocalSocket(QAbstractSocket::SocketError))); + + // attempt to connect to our reliable host + localIPTestSocket->connectToHost(RELIABLE_LOCAL_IP_CHECK_HOST, RELIABLE_LOCAL_IP_CHECK_PORT); +} + +void LimitedNodeList::connectedForLocalSocketTest() { + auto localIPTestSocket = qobject_cast(sender()); + + if (localIPTestSocket) { + auto localHostAddress = localIPTestSocket->localAddress(); + + if (localHostAddress.protocol() == QAbstractSocket::IPv4Protocol) { + _hasTCPCheckedLocalSocket = true; + setLocalSocket(HifiSockAddr { localHostAddress, _nodeSocket.localPort() }); } - _localSockAddr = newSockAddr; + localIPTestSocket->deleteLater(); + } +} + +void LimitedNodeList::errorTestingLocalSocket(QAbstractSocket::SocketError error) { + auto localIPTestSocket = qobject_cast(sender()); + qDebug() << sender() << error; + + if (localIPTestSocket) { + + // error connecting to the test socket - if we've never set our local socket using this test socket + // then use our possibly updated guessed local address as fallback + if (!_hasTCPCheckedLocalSocket) { + setLocalSocket(HifiSockAddr { getGuessedLocalAddress(), _nodeSocket.localPort() }); + } + + localIPTestSocket->deleteLater();; + } +} + +void LimitedNodeList::setLocalSocket(const HifiSockAddr& sockAddr) { + if (sockAddr != _localSockAddr) { + + if (_localSockAddr.isNull()) { + qCInfo(networking) << "Local socket is" << sockAddr; + } else { + qCInfo(networking) << "Local socket has changed from" << _localSockAddr << "to" << sockAddr; + } + + _localSockAddr = sockAddr; emit localSockAddrChanged(_localSockAddr); } diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index de110c7e7f..be621647e3 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -225,7 +225,7 @@ public slots: void removeSilentNodes(); - void updateLocalSockAddr(); + void updateLocalSocket(); void startSTUNPublicSocketUpdate(); virtual void sendSTUNRequest(); @@ -247,6 +247,10 @@ signals: void isAllowedEditorChanged(bool isAllowedEditor); void canRezChanged(bool canRez); +protected slots: + void connectedForLocalSocketTest(); + void errorTestingLocalSocket(QAbstractSocket::SocketError error); + protected: LimitedNodeList(unsigned short socketListenPort = 0, unsigned short dtlsListenPort = 0); LimitedNodeList(LimitedNodeList const&); // Don't implement, needed to avoid copies of singleton @@ -258,6 +262,8 @@ protected: const QUuid& connectionSecret = QUuid()); void collectPacketStats(const NLPacket& packet); void fillPacketHeader(const NLPacket& packet, const QUuid& connectionSecret = QUuid()); + + void setLocalSocket(const HifiSockAddr& sockAddr); bool isPacketVerified(const udt::Packet& packet); bool packetVersionMatch(const udt::Packet& packet); @@ -271,8 +277,6 @@ protected: void sendPacketToIceServer(PacketType packetType, const HifiSockAddr& iceServerSockAddr, const QUuid& clientID, const QUuid& peerRequestID = QUuid()); - - QUuid _sessionUUID; NodeHash _nodeHash; QReadWriteLock _nodeMutex; @@ -281,6 +285,7 @@ protected: HifiSockAddr _localSockAddr; HifiSockAddr _publicSockAddr; HifiSockAddr _stunSockAddr; + bool _hasTCPCheckedLocalSocket { false }; PacketReceiver* _packetReceiver; From 20ab108d51a3bad8469197a1cc2e57217df63a6a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 7 Mar 2016 18:01:57 -0800 Subject: [PATCH 2/4] remove some debug for local socket check error --- libraries/networking/src/LimitedNodeList.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 4ee8a8bf49..eadd2d740e 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -922,7 +922,6 @@ void LimitedNodeList::connectedForLocalSocketTest() { void LimitedNodeList::errorTestingLocalSocket(QAbstractSocket::SocketError error) { auto localIPTestSocket = qobject_cast(sender()); - qDebug() << sender() << error; if (localIPTestSocket) { From 73b7e787d3d77d95e379fcb5ff1f4e2326c76035 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 8 Mar 2016 09:09:28 -0800 Subject: [PATCH 3/4] change signature of errorTestingLocalSocket --- libraries/networking/src/LimitedNodeList.cpp | 2 +- libraries/networking/src/LimitedNodeList.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index eadd2d740e..ee83cffe53 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -920,7 +920,7 @@ void LimitedNodeList::connectedForLocalSocketTest() { } } -void LimitedNodeList::errorTestingLocalSocket(QAbstractSocket::SocketError error) { +void LimitedNodeList::errorTestingLocalSocket() { auto localIPTestSocket = qobject_cast(sender()); if (localIPTestSocket) { diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index be621647e3..43393ef69c 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -249,7 +249,7 @@ signals: protected slots: void connectedForLocalSocketTest(); - void errorTestingLocalSocket(QAbstractSocket::SocketError error); + void errorTestingLocalSocket(); protected: LimitedNodeList(unsigned short socketListenPort = 0, unsigned short dtlsListenPort = 0); From 909979bab9e31132461f2d92098fd5ca19b473c1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 8 Mar 2016 09:11:38 -0800 Subject: [PATCH 4/4] fix SLOT connection for local address check --- libraries/networking/src/LimitedNodeList.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index ee83cffe53..2c10d0627e 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -899,7 +899,7 @@ void LimitedNodeList::updateLocalSocket() { QTcpSocket* localIPTestSocket = new QTcpSocket; connect(localIPTestSocket, &QTcpSocket::connected, this, &LimitedNodeList::connectedForLocalSocketTest); - connect(localIPTestSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(errorTestingLocalSocket(QAbstractSocket::SocketError))); + connect(localIPTestSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(errorTestingLocalSocket())); // attempt to connect to our reliable host localIPTestSocket->connectToHost(RELIABLE_LOCAL_IP_CHECK_HOST, RELIABLE_LOCAL_IP_CHECK_PORT);