From 33639a52730936a442070f6454920213f3350602 Mon Sep 17 00:00:00 2001
From: Tobias Markmann <tm@ayena.de>
Date: Fri, 19 Dec 2014 14:49:02 +0100
Subject: Limit NAT-PMP detection timeout to 10 seconds.

libnatpmp has a high (over 2 minutes) timeout for discovery of NAT-PMP
support. This leads to a bad user experience when there is no NAT-PMP
support in the network.

Test-Information:

Tested this in an university network where neither UPnP nor NAT-PMP is
available. File-transfers waited more than 2 minutes for an answer of
a NAT-PMP device before starting the file-transfer.

Change-Id: I3ceaac7f89c982ffa683ee367d5ea3c3d4a2c5ca

diff --git a/Swiften/Network/NATPMPInterface.cpp b/Swiften/Network/NATPMPInterface.cpp
index 5fe7fc2..064cfc8 100644
--- a/Swiften/Network/NATPMPInterface.cpp
+++ b/Swiften/Network/NATPMPInterface.cpp
@@ -55,9 +55,14 @@ boost::optional<HostAddress> NATPMPInterface::getPublicIP() {
 	  FD_ZERO(&fds);
 	  FD_SET(p->natpmp.s, &fds);
 	  getnatpmprequesttimeout(&p->natpmp, &timeout);
+
+	  // Limit NAT-PMP timeout to ten seconds.
+	  timeout.tv_sec = 10;
+	  timeout.tv_usec = 0;
+
 	  select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
 	  r = readnatpmpresponseorretry(&p->natpmp, &response);
-	} while (r == NATPMP_TRYAGAIN);
+	} while (false /*r == NATPMP_TRYAGAIN*/);
 
 	if (r == 0) {
 		return boost::optional<HostAddress>(HostAddress(reinterpret_cast<const unsigned char*>(&(response.pnu.publicaddress.addr)), 4));
@@ -88,9 +93,14 @@ boost::optional<NATPortMapping> NATPMPInterface::addPortForward(int localPort, i
 		FD_ZERO(&fds);
 		FD_SET(p->natpmp.s, &fds);
 		getnatpmprequesttimeout(&p->natpmp, &timeout);
+
+		// Limit NAT-PMP timeout to ten seconds.
+		timeout.tv_sec = 10;
+		timeout.tv_usec = 0;
+
 		select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
 		r = readnatpmpresponseorretry(&p->natpmp, &response);
-	} while(r == NATPMP_TRYAGAIN);
+	} while(false /*r == NATPMP_TRYAGAIN*/);
 
 	if (r == 0) {
 		NATPortMapping result(response.pnu.newportmapping.privateport, response.pnu.newportmapping.mappedpublicport, NATPortMapping::TCP, boost::numeric_cast<int>(response.pnu.newportmapping.lifetime));
diff --git a/Swiften/Network/PlatformNATTraversalWorker.cpp b/Swiften/Network/PlatformNATTraversalWorker.cpp
index 65ff577..5e2bc0c 100644
--- a/Swiften/Network/PlatformNATTraversalWorker.cpp
+++ b/Swiften/Network/PlatformNATTraversalWorker.cpp
@@ -141,6 +141,7 @@ NATTraversalInterface* PlatformNATTraversalWorker::getNATTraversalInterface() co
 		miniUPnPInterface = new MiniUPnPInterface();
 		miniUPnPSupported = miniUPnPInterface->isAvailable();
 	}
+	SWIFT_LOG(debug) << "UPnP NAT traversal supported: " << miniUPnPSupported << std::endl;
 	if (miniUPnPSupported) {
 		return miniUPnPInterface;
 	}
@@ -151,6 +152,7 @@ NATTraversalInterface* PlatformNATTraversalWorker::getNATTraversalInterface() co
 		natPMPInterface = new NATPMPInterface();
 		natPMPSupported = natPMPInterface->isAvailable();
 	}
+	SWIFT_LOG(debug) << "NAT-PMP NAT traversal supported: " << natPMPSupported << std::endl;
 	if (natPMPSupported) {
 		return natPMPInterface;
 	}
-- 
cgit v0.10.2-6-g49f6