From 498d681d3e8d740cb8fb0d35d1ba3959ff93da56 Mon Sep 17 00:00:00 2001
From: Simon Walton <simon@highfidelity.io>
Date: Fri, 7 Jun 2019 12:04:04 -0700
Subject: [PATCH 1/4] Force new IP port on local address change

---
 libraries/networking/src/LimitedNodeList.cpp | 8 ++++++--
 libraries/networking/src/udt/Socket.cpp      | 1 +
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp
index 0eda2ee2e0..97a12e4c71 100644
--- a/libraries/networking/src/LimitedNodeList.cpp
+++ b/libraries/networking/src/LimitedNodeList.cpp
@@ -1172,7 +1172,7 @@ void LimitedNodeList::stopInitialSTUNUpdate(bool success) {
 
     // We now setup a timer here to fire every so often to check that our IP address has not changed.
     // Or, if we failed - if will check if we can eventually get a public socket
-    const int STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS = 30 * 1000;
+    const int STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS = 10 * 1000;
 
     QTimer* stunOccasionalTimer = new QTimer { this };
     connect(stunOccasionalTimer, &QTimer::timeout, this, &LimitedNodeList::sendSTUNRequest);
@@ -1230,12 +1230,16 @@ void LimitedNodeList::errorTestingLocalSocket() {
 }
 
 void LimitedNodeList::setLocalSocket(const HifiSockAddr& sockAddr) {
-    if (sockAddr != _localSockAddr) {
+    if (sockAddr.getAddress() != _localSockAddr.getAddress()) {
 
         if (_localSockAddr.isNull()) {
             qCInfo(networking) << "Local socket is" << sockAddr;
         } else {
             qCInfo(networking) << "Local socket has changed from" << _localSockAddr << "to" << sockAddr;
+            if (_hasTCPCheckedLocalSocket) {  // Force a port change for NAT:
+                _nodeSocket.rebind(0);
+                _localSockAddr.setPort(_nodeSocket.localPort());
+            }
         }
 
         _localSockAddr = sockAddr;
diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp
index 98d6c0a6be..5a3111a7eb 100644
--- a/libraries/networking/src/udt/Socket.cpp
+++ b/libraries/networking/src/udt/Socket.cpp
@@ -73,6 +73,7 @@ void Socket::rebind() {
 
 void Socket::rebind(quint16 localPort) {
     _udpSocket.close();
+    _udpSocket.waitForDisconnected();
     bind(QHostAddress::AnyIPv4, localPort);
 }
 

From c088fab60602b9f5455f5d1e05208db2eff7c038 Mon Sep 17 00:00:00 2001
From: Simon Walton <simon@highfidelity.io>
Date: Fri, 7 Jun 2019 16:23:38 -0700
Subject: [PATCH 2/4] Fix annoying typo

---
 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 97a12e4c71..d8d43f4b02 100644
--- a/libraries/networking/src/LimitedNodeList.cpp
+++ b/libraries/networking/src/LimitedNodeList.cpp
@@ -983,7 +983,7 @@ void LimitedNodeList::sendSTUNRequest() {
         const int NUM_INITIAL_STUN_REQUESTS_BEFORE_FAIL = 10;
 
         if (!_hasCompletedInitialSTUN) {
-            qCDebug(networking) << "Sending intial stun request to" << STUN_SERVER_HOSTNAME;
+            qCDebug(networking) << "Sending initial stun request to" << STUN_SERVER_HOSTNAME;
 
             if (_numInitialSTUNRequests > NUM_INITIAL_STUN_REQUESTS_BEFORE_FAIL) {
                 // we're still trying to do our initial STUN we're over the fail threshold

From d780964cb4979abfdf501dc72f16abe1106f6130 Mon Sep 17 00:00:00 2001
From: Simon Walton <simon@highfidelity.io>
Date: Mon, 10 Jun 2019 17:28:49 -0700
Subject: [PATCH 3/4] Reset NodeList upon local nework change; abort current
 socket when rebinding

Also ensure QUdpSocket is owned by LimitedNodeList.
---
 libraries/networking/src/LimitedNodeList.cpp | 1 +
 libraries/networking/src/udt/Socket.cpp      | 5 +++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp
index 2f1a8c9d10..9b1f011680 100644
--- a/libraries/networking/src/LimitedNodeList.cpp
+++ b/libraries/networking/src/LimitedNodeList.cpp
@@ -1239,6 +1239,7 @@ void LimitedNodeList::setLocalSocket(const HifiSockAddr& sockAddr) {
         } else {
             qCInfo(networking) << "Local socket has changed from" << _localSockAddr << "to" << sockAddr;
             if (_hasTCPCheckedLocalSocket) {  // Force a port change for NAT:
+                reset();
                 _nodeSocket.rebind(0);
                 _localSockAddr.setPort(_nodeSocket.localPort());
             }
diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp
index 75d4c9ef45..bcc2293e1f 100644
--- a/libraries/networking/src/udt/Socket.cpp
+++ b/libraries/networking/src/udt/Socket.cpp
@@ -33,6 +33,7 @@ using namespace udt;
 
 Socket::Socket(QObject* parent, bool shouldChangeSocketOptions) :
     QObject(parent),
+    _udpSocket(parent),
     _readyReadBackupTimer(new QTimer(this)),
     _shouldChangeSocketOptions(shouldChangeSocketOptions)
 {
@@ -50,6 +51,7 @@ Socket::Socket(QObject* parent, bool shouldChangeSocketOptions) :
 }
 
 void Socket::bind(const QHostAddress& address, quint16 port) {
+
     _udpSocket.bind(address, port);
 
     if (_shouldChangeSocketOptions) {
@@ -72,8 +74,7 @@ void Socket::rebind() {
 }
 
 void Socket::rebind(quint16 localPort) {
-    _udpSocket.close();
-    _udpSocket.waitForDisconnected();
+    _udpSocket.abort();
     bind(QHostAddress::AnyIPv4, localPort);
 }
 

From cfcea359b2c5dc28630f952bf3794af687ee6faf Mon Sep 17 00:00:00 2001
From: Simon Walton <simon@highfidelity.io>
Date: Fri, 14 Jun 2019 16:51:59 -0700
Subject: [PATCH 4/4] Handle local address changes for servers

---
 domain-server/src/DomainServer.cpp           | 4 ++++
 libraries/networking/src/LimitedNodeList.cpp | 4 +++-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp
index 44887599d3..00ca858a1f 100644
--- a/domain-server/src/DomainServer.cpp
+++ b/domain-server/src/DomainServer.cpp
@@ -739,6 +739,10 @@ void DomainServer::setupNodeListAndAssignments() {
 
     connect(nodeList.data(), &LimitedNodeList::nodeAdded, this, &DomainServer::nodeAdded);
     connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &DomainServer::nodeKilled);
+    connect(nodeList.data(), &LimitedNodeList::localSockAddrChanged, this,
+        [this](const HifiSockAddr& localSockAddr) {
+        DependencyManager::get<LimitedNodeList>()->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this, localSockAddr.getPort());
+    });
 
     // register as the packet receiver for the types we want
     PacketReceiver& packetReceiver = nodeList->getPacketReceiver();
diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp
index 92a5692ca9..e47b4cc7bc 100644
--- a/libraries/networking/src/LimitedNodeList.cpp
+++ b/libraries/networking/src/LimitedNodeList.cpp
@@ -1237,16 +1237,18 @@ void LimitedNodeList::setLocalSocket(const HifiSockAddr& sockAddr) {
 
         if (_localSockAddr.isNull()) {
             qCInfo(networking) << "Local socket is" << sockAddr;
+            _localSockAddr = sockAddr;
         } else {
             qCInfo(networking) << "Local socket has changed from" << _localSockAddr << "to" << sockAddr;
+            _localSockAddr = sockAddr;
             if (_hasTCPCheckedLocalSocket) {  // Force a port change for NAT:
                 reset();
                 _nodeSocket.rebind(0);
                 _localSockAddr.setPort(_nodeSocket.localPort());
+                qCInfo(networking) << "Local port changed to" << _localSockAddr.getPort();
             }
         }
 
-        _localSockAddr = sockAddr;
         emit localSockAddrChanged(_localSockAddr);
     }
 }