From 71e34ffa7144441bc5a7fce15728f506daffc756 Mon Sep 17 00:00:00 2001
From: Tobias Markmann <tm@ayena.de>
Date: Sun, 11 Jan 2015 14:57:45 +0100
Subject: Remove port forwardings on stop or destruction of
 SOCKS5BytestreamServerManager.

Test-Information:

Verified with home router that supports UPnP that the forwards are removed
on stop.

Change-Id: Ie2a8fd56828cc01e456d40ff4e5500d3387c7afe

diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp b/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp
index 76c267c..cf4ae84 100644
--- a/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp
+++ b/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Isode Limited.
+ * Copyright (c) 2012-2015 Isode Limited.
  * All rights reserved.
  * See the COPYING file for more information.
  */
@@ -25,6 +25,7 @@
 #include <Swiften/Network/NATTraverser.h>
 #include <Swiften/Network/NATTraversalGetPublicIPRequest.h>
 #include <Swiften/Network/NATTraversalForwardPortRequest.h>
+#include <Swiften/Network/NATTraversalRemovePortForwardingRequest.h>
 
 using namespace Swift;
 
@@ -49,6 +50,11 @@ SOCKS5BytestreamServerManager::~SOCKS5BytestreamServerManager() {
 	SWIFT_LOG_ASSERT(!getPublicIPRequest, warning) << std::endl;
 	SWIFT_LOG_ASSERT(!forwardPortRequest, warning) << std::endl;
 	SWIFT_LOG_ASSERT(state == Start, warning) << std::endl;
+	if (portMapping && !unforwardPortRequest) {
+		SWIFT_LOG(warning) << "Port forwarding still alive. Trying to remove it now." << std::endl;
+		unforwardPortRequest = natTraverser->createRemovePortForwardingRequest(portMapping.get().getLocalPort(), portMapping.get().getPublicPort());
+		unforwardPortRequest->start();
+	}
 }
 
 
@@ -56,24 +62,6 @@ boost::shared_ptr<SOCKS5BytestreamServerInitializeRequest> SOCKS5BytestreamServe
 	return boost::make_shared<SOCKS5BytestreamServerInitializeRequest>(this);
 }
 
-void SOCKS5BytestreamServerManager::stop() {
-	if (getPublicIPRequest) {
-		getPublicIPRequest->stop();
-		getPublicIPRequest.reset();
-	}
-	if (forwardPortRequest) {
-		forwardPortRequest->stop();
-		forwardPortRequest.reset();
-	}
-	if (connectionServer) {
-		connectionServer->stop();
-		connectionServer.reset();
-	}
-	// TODO: Remove port forwards
-	
-	state = Start;
-}
-
 std::vector<HostAddressPort> SOCKS5BytestreamServerManager::getHostAddressPorts() const {
 	std::vector<HostAddressPort> result;
 	if (connectionServer) {
@@ -154,6 +142,30 @@ void SOCKS5BytestreamServerManager::initialize() {
 	}
 }
 
+void SOCKS5BytestreamServerManager::stop() {
+	if (getPublicIPRequest) {
+		getPublicIPRequest->stop();
+		getPublicIPRequest.reset();
+	}
+	if (forwardPortRequest) {
+		forwardPortRequest->stop();
+		forwardPortRequest.reset();
+	}
+	if (connectionServer) {
+		connectionServer->stop();
+		connectionServer.reset();
+	}
+
+	// remove port forwards
+	if (portMapping) {
+		unforwardPortRequest = natTraverser->createRemovePortForwardingRequest(portMapping.get().getLocalPort(), portMapping.get().getPublicPort());
+		unforwardPortRequest->onResult.connect(boost::bind(&SOCKS5BytestreamServerManager::handleUnforwardPortResult, this, _1));
+		unforwardPortRequest->start();
+	}
+
+	state = Start;
+}
+
 void SOCKS5BytestreamServerManager::handleGetPublicIPResult(boost::optional<HostAddress> address) {
 	if (address) {
 		SWIFT_LOG(debug) << "Public IP discovered as " << address.get().toString() << "." << std::endl;
@@ -186,6 +198,16 @@ void SOCKS5BytestreamServerManager::handleForwardPortResult(boost::optional<NATP
 	checkInitializeFinished();
 }
 
+void SOCKS5BytestreamServerManager::handleUnforwardPortResult(boost::optional<bool> result) {
+	if (result.is_initialized() && result.get()) {
+		portMapping.reset();
+	}
+	else {
+		SWIFT_LOG(warning) << "Failed to remove port forwarding." << std::endl;
+	}
+	unforwardPortRequest.reset();
+}
+
 void SOCKS5BytestreamServerManager::checkInitializeFinished() {
 	assert(state == Initializing);
 	if (!getPublicIPRequest && !forwardPortRequest) {
diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerManager.h b/Swiften/FileTransfer/SOCKS5BytestreamServerManager.h
index fd06e3a..abb28b0 100644
--- a/Swiften/FileTransfer/SOCKS5BytestreamServerManager.h
+++ b/Swiften/FileTransfer/SOCKS5BytestreamServerManager.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013 Isode Limited.
+ * Copyright (c) 2012-2015 Isode Limited.
  * All rights reserved.
  * See the COPYING file for more information.
  */
@@ -18,6 +18,7 @@ namespace Swift {
 	class NATTraverser;
 	class NATTraversalGetPublicIPRequest;
 	class NATTraversalForwardPortRequest;
+	class NATTraversalRemovePortForwardingRequest;
 	class SOCKS5BytestreamRegistry;
 	class ConnectionServerFactory;
 	class ConnectionServer;
@@ -50,6 +51,7 @@ namespace Swift {
 
 			void handleGetPublicIPResult(boost::optional<HostAddress> address);
 			void handleForwardPortResult(boost::optional<NATPortMapping> mapping);
+			void handleUnforwardPortResult(boost::optional<bool> result);
 
 			boost::signal<void (bool /* success */)> onInitialized;
 
@@ -66,6 +68,7 @@ namespace Swift {
 			int connectionServerPort;
 			boost::shared_ptr<NATTraversalGetPublicIPRequest> getPublicIPRequest;
 			boost::shared_ptr<NATTraversalForwardPortRequest> forwardPortRequest;
+			boost::shared_ptr<NATTraversalRemovePortForwardingRequest> unforwardPortRequest;
 			boost::optional<HostAddress> publicAddress;
 			boost::optional<NATPortMapping> portMapping;
 	};
-- 
cgit v0.10.2-6-g49f6