From 94f87ffc9769f2782b2267db813854b0fe752678 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sat, 24 Sep 2011 20:18:28 +0200
Subject: File transfer changes.

- Introduce 'experimental' flag to conditionally compile FT.
- Use LibMiniUPNPC and NATPMP CPPDEFINES only locally in the classes that need them.
- Extract abstract interface from NAT traversal classes
- Avoid unit test warnings

diff --git a/3rdParty/LibMiniUPnPc/SConscript b/3rdParty/LibMiniUPnPc/SConscript
index be9910c..c482109 100644
--- a/3rdParty/LibMiniUPnPc/SConscript
+++ b/3rdParty/LibMiniUPnPc/SConscript
@@ -11,6 +11,7 @@ if env.get("LIBMINIUPNPC_BUNDLED", False) :
 				"CPPPATH": [Dir("src/miniupnpc")],
 				"LIBPATH": [Dir(".")],
 				"LIBS": ["Swiften_MiniUPnPc"],
+				"INTERNAL_CPPDEFINES": ["STATICLIB"],
 			}
 		#if env["PLATFORM"] == "win32" :
 		#	env["LIBIDN_FLAGS"]["CPPPATH"] += [Dir("stubs/win32")]
diff --git a/3rdParty/LibNATPMP/SConscript b/3rdParty/LibNATPMP/SConscript
index 60e59a0..2cf745a 100644
--- a/3rdParty/LibNATPMP/SConscript
+++ b/3rdParty/LibNATPMP/SConscript
@@ -11,6 +11,7 @@ if env.get("LIBNATPMP_BUNDLED", False) :
 				"CPPPATH": [Dir("src/libnatpmp")],
 				"LIBPATH": [Dir(".")],
 				"LIBS": ["Swiften_NATPMP"],
+				"INTERNAL_CPPDEFINES": ["STATICLIB"],
 			}
 		#if env["PLATFORM"] == "win32" :
 		#	env["LIBIDN_FLAGS"]["CPPPATH"] += [Dir("stubs/win32")]
diff --git a/BuildTools/SCons/SConscript.boot b/BuildTools/SCons/SConscript.boot
index 77b1cf1..366981c 100644
--- a/BuildTools/SCons/SConscript.boot
+++ b/BuildTools/SCons/SConscript.boot
@@ -52,6 +52,7 @@ vars.Add(PathVariable("docbook_xml", "DocBook XML", None, PathVariable.PathAccep
 vars.Add(PathVariable("docbook_xsl", "DocBook XSL", None, PathVariable.PathAccept))
 vars.Add(BoolVariable("build_examples", "Build example programs", "yes"))
 vars.Add(BoolVariable("enable_variants", "Build in a separate dir under build/, depending on compile flags", "no"))
+vars.Add(BoolVariable("experimental", "Build experimental features", "no"))
 
 ################################################################################
 # Set up default build & configure environment
@@ -162,6 +163,9 @@ if env.get("mac105", 0) :
 if not env["assertions"] :
 	env.Append(CPPDEFINES = ["NDEBUG"])
 
+if env["experimental"] :
+	env.Append(CPPDEFINES = ["SWIFT_EXPERIMENTAL_FT"])
+
 # If we build shared libs on AMD64, we need -fPIC.
 # This should have no performance impact om AMD64
 if env["PLATFORM"] == "posix" and platform.machine() == "x86_64" :
diff --git a/BuildTools/SCons/SConstruct b/BuildTools/SCons/SConstruct
index ba2f4b7..448bdbd 100644
--- a/BuildTools/SCons/SConstruct
+++ b/BuildTools/SCons/SConstruct
@@ -312,25 +312,28 @@ else :
 conf.Finish()
 
 # LibMiniUPnPc
-libminiupnpc_conf_env = conf_env.Clone()
-
-conf = Configure(libminiupnpc_conf_env)
-if conf.CheckCHeader("miniupnpc.h") and conf.CheckLib(env["libminiupnpc_libname"]) :
-	print "NOT IMPLEMENTED YET"
+if env["experimental"] :
+	libminiupnpc_conf_env = conf_env.Clone()
+	conf = Configure(libminiupnpc_conf_env)
+	if conf.CheckCHeader("miniupnpc.h") and conf.CheckLib(env["libminiupnpc_libname"]) :
+		print "NOT IMPLEMENTED YET"
+	else :
+		env["LIBMINIUPNPC_BUNDLED"] = 1
+	conf.Finish()
 else :
-	env["LIBMINIUPNPC_BUNDLED"] = 1
-conf.Finish()
+	env["LIBMINIUPNPC_FLAGS"] = {}
 
 # LibNATPMP
-libnatpmp_conf_env = conf_env.Clone()
-
-conf = Configure(libnatpmp_conf_env)
-if conf.CheckCHeader("natpmp.h") and conf.CheckLib(env["libnatpmp_libname"]) :
-	print "NOT IMPLEMENTED YET"
+if env["experimental"] :
+	libnatpmp_conf_env = conf_env.Clone()
+	conf = Configure(libnatpmp_conf_env)
+	if conf.CheckCHeader("natpmp.h") and conf.CheckLib(env["libnatpmp_libname"]) :
+		print "NOT IMPLEMENTED YET"
+	else :
+		env["LIBNATPMP_BUNDLED"] = 1
+	conf.Finish()
 else :
-	env["LIBNATPMP_BUNDLED"] = 1
-conf.Finish()
-
+	env["LIBNATPMP_FLAGS"] = {}
 
 # SQLite
 #sqlite_conf_env = conf_env.Clone()
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index b84e7d6..2f5356e 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -309,10 +309,12 @@ void MainController::handleConnected() {
 		discoInfo.addFeature(DiscoInfo::ChatStatesFeature);
 		discoInfo.addFeature(DiscoInfo::SecurityLabelsFeature);
 		discoInfo.addFeature(DiscoInfo::MessageCorrectionFeature);
+#ifdef SWIFT_EXPERIMENTAL_FT
 		discoInfo.addFeature(DiscoInfo::JingleFeature);
 		discoInfo.addFeature(DiscoInfo::JingleFTFeature);
 		discoInfo.addFeature(DiscoInfo::JingleTransportsIBBFeature);
 		discoInfo.addFeature(DiscoInfo::JingleTransportsS5BFeature);
+#endif
 		client_->getDiscoManager()->setCapsNode(CLIENT_NODE);
 		client_->getDiscoManager()->setDiscoInfo(discoInfo);
 
diff --git a/Swift/Controllers/Roster/ContactRosterItem.cpp b/Swift/Controllers/Roster/ContactRosterItem.cpp
index 6d707bb..8c388bf 100644
--- a/Swift/Controllers/Roster/ContactRosterItem.cpp
+++ b/Swift/Controllers/Roster/ContactRosterItem.cpp
@@ -117,8 +117,8 @@ void ContactRosterItem::setSupportedFeatures(const std::set<Feature>& features)
 	features_ = features;
 }
 
-bool ContactRosterItem::supportsFeature(const Feature feat) const {
-	return features_.find(feat) != features_.end();
+bool ContactRosterItem::supportsFeature(const Feature feature) const {
+	return features_.find(feature) != features_.end();
 }
 
 }
diff --git a/Swift/Controllers/Roster/ContactRosterItem.h b/Swift/Controllers/Roster/ContactRosterItem.h
index 67ffaa9..9932dc4 100644
--- a/Swift/Controllers/Roster/ContactRosterItem.h
+++ b/Swift/Controllers/Roster/ContactRosterItem.h
@@ -48,7 +48,7 @@ class ContactRosterItem : public RosterItem {
 		void removeGroup(const std::string& group);
 		
 		void setSupportedFeatures(const std::set<Feature>& features);
-		bool supportsFeature(Feature feat) const;
+		bool supportsFeature(Feature feature) const;
 	private:
 		JID jid_;
 		JID displayJID_;
diff --git a/Swift/Controllers/Roster/Roster.cpp b/Swift/Controllers/Roster/Roster.cpp
index f3d058e..83837b1 100644
--- a/Swift/Controllers/Roster/Roster.cpp
+++ b/Swift/Controllers/Roster/Roster.cpp
@@ -62,8 +62,11 @@ GroupRosterItem* Roster::getGroup(const std::string& groupName) {
 }
 
 void Roster::setAvailableFeatures(const JID& jid, const std::set<ContactRosterItem::Feature>& features) {
-	if (itemMap_[fullJIDMapping_ ? jid : jid.toBare()].empty()) return;
-	foreach(ContactRosterItem* item, itemMap_[fullJIDMapping_ ? jid : jid.toBare()]) {
+	JID actualJID = fullJIDMapping_ ? jid : jid.toBare();
+	if (itemMap_[actualJID].empty()) {
+		return;
+	}
+	foreach(ContactRosterItem* item, itemMap_[actualJID]) {
 		item->setSupportedFeatures(features);
 	}
 }
diff --git a/Swift/QtUI/QtChatView.cpp b/Swift/QtUI/QtChatView.cpp
index d51f74c..cb7f901 100644
--- a/Swift/QtUI/QtChatView.cpp
+++ b/Swift/QtUI/QtChatView.cpp
@@ -49,11 +49,16 @@ QtChatView::QtChatView(QtChatTheme* theme, QWidget* parent) : QWidget(parent), f
 #else
 	mainLayout->addWidget(webView_);
 #endif
+
+#ifdef SWIFT_EXPERIMENTAL_FT
 	setAcceptDrops(true);
+#endif
 
 	webPage_ = new QWebPage(this);
 	webPage_->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
+#ifdef SWIFT_EXPERIMENTAL_FT
 	webPage_->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
+#endif
 	webView_->setPage(webPage_);
 	connect(webPage_, SIGNAL(selectionChanged()), SLOT(copySelectionToClipboard()));
 
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index 238100a..fa039de 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -55,7 +55,9 @@ QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventSt
 	updateTitleWithUnreadCount();
 	QtSettingsProvider settings;
 
+#ifdef SWIFT_EXPERIMENTAL_FT
 	setAcceptDrops(true);
+#endif
 
 	alertStyleSheet_ = "background: rgb(255, 255, 153); color: black";
 
diff --git a/Swift/QtUI/QtLoginWindow.cpp b/Swift/QtUI/QtLoginWindow.cpp
index 543af65..0db6071 100644
--- a/Swift/QtUI/QtLoginWindow.cpp
+++ b/Swift/QtUI/QtLoginWindow.cpp
@@ -168,9 +168,11 @@ QtLoginWindow::QtLoginWindow(UIEventStream* uiEventStream) : QMainWindow(), forg
 	connect(xmlConsoleAction_, SIGNAL(triggered()), SLOT(handleShowXMLConsole()));
 	generalMenu_->addAction(xmlConsoleAction_);
 
+#ifdef SWIFT_EXPERIMENTAL_FT
 	fileTransferOverviewAction_ = new QAction(tr("Show &File Transfer Overview"), this);
 	connect(fileTransferOverviewAction_, SIGNAL(triggered()), SLOT(handleShowFileTransferOverview()));
 	generalMenu_->addAction(fileTransferOverviewAction_);
+#endif
 
 	toggleSoundsAction_ = new QAction(tr("&Play Sounds"), this);
 	toggleSoundsAction_->setCheckable(true);
diff --git a/Swift/QtUI/Roster/QtRosterWidget.cpp b/Swift/QtUI/Roster/QtRosterWidget.cpp
index f3b0441..3d9b273 100644
--- a/Swift/QtUI/Roster/QtRosterWidget.cpp
+++ b/Swift/QtUI/Roster/QtRosterWidget.cpp
@@ -56,10 +56,12 @@ void QtRosterWidget::contextMenuEvent(QContextMenuEvent* event) {
 	if (ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item)) {
 		QAction* editContact = contextMenu.addAction(tr("Edit"));
 		QAction* removeContact = contextMenu.addAction(tr("Remove"));
+#ifdef SWIFT_EXPERIMENTAL_FT
 		QAction* sendFile = NULL;
 		if (contact->supportsFeature(ContactRosterItem::FileTransferFeature)) {
 			sendFile = contextMenu.addAction(tr("Send File"));
 		}
+#endif
 		QAction* result = contextMenu.exec(event->globalPos());
 		if (result == editContact) {
 			eventStream_->send(boost::make_shared<RequestContactEditorUIEvent>(contact->getJID()));
@@ -69,12 +71,14 @@ void QtRosterWidget::contextMenuEvent(QContextMenuEvent* event) {
 				eventStream_->send(boost::make_shared<RemoveRosterItemUIEvent>(contact->getJID()));
 			}
 		}
-		else if (result == sendFile) {
+#ifdef SWIFT_EXPERIMENTAL_FT
+		else if (sendFile && result == sendFile) {
 			QString fileName = QFileDialog::getOpenFileName(this, tr("Send File"), "", tr("All Files (*);;"));
 			if (!fileName.isEmpty()) {
 				eventStream_->send(boost::make_shared<SendFileUIEvent>(contact->getJID(), fileName.toStdString()));
 			}
 		}
+#endif
 	}
 	else if (GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(item)) {
 		QAction* renameGroupAction = contextMenu.addAction(tr("Rename"));
diff --git a/Swift/QtUI/Roster/QtTreeWidget.cpp b/Swift/QtUI/Roster/QtTreeWidget.cpp
index 79dd6a2..2e37ba2 100644
--- a/Swift/QtUI/Roster/QtTreeWidget.cpp
+++ b/Swift/QtUI/Roster/QtTreeWidget.cpp
@@ -34,7 +34,9 @@ QtTreeWidget::QtTreeWidget(UIEventStream* eventStream, QWidget* parent) : QTreeV
 	expandAll();
 	setAnimated(true);
 	setIndentation(0);
+#ifdef SWIFT_EXPERIMENTAL_FT
 	setAcceptDrops(true);
+#endif
 	setRootIsDecorated(true);
 	connect(this, SIGNAL(activated(const QModelIndex&)), this, SLOT(handleItemActivated(const QModelIndex&)));
 	connect(model_, SIGNAL(itemExpanded(const QModelIndex&, bool)), this, SLOT(handleModelItemExpanded(const QModelIndex&, bool)));
diff --git a/Swiften/Client/Client.cpp b/Swiften/Client/Client.cpp
index e95e704..48eddc2 100644
--- a/Swiften/Client/Client.cpp
+++ b/Swiften/Client/Client.cpp
@@ -29,6 +29,9 @@
 #include <Swiften/Jingle/JingleSessionManager.h>
 #include <Swiften/Network/NetworkFactories.h>
 #include <Swiften/FileTransfer/FileTransferManagerImpl.h>
+#ifndef SWIFT_EXPERIMENTAL_FT
+#include <Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h>
+#endif
 
 namespace Swift {
 
@@ -108,7 +111,11 @@ void Client::setSoftwareVersion(const std::string& name, const std::string& vers
 }
 
 void Client::handleConnected() {
-	fileTransferManager = new FileTransferManagerImpl(getJID(), jingleSessionManager, getIQRouter(), getEntityCapsProvider(), presenceOracle, getNetworkFactories()->getConnectionFactory(), getNetworkFactories()->getConnectionServerFactory(), getNetworkFactories()->getTimerFactory(), getNetworkFactories()->getPlatformNATTraversalWorker());
+#ifdef SWIFT_EXPERIMENTAL_FT
+	fileTransferManager = new FileTransferManagerImpl(getJID(), jingleSessionManager, getIQRouter(), getEntityCapsProvider(), presenceOracle, getNetworkFactories()->getConnectionFactory(), getNetworkFactories()->getConnectionServerFactory(), getNetworkFactories()->getTimerFactory(), getNetworkFactories()->getNATTraverser());
+#else
+	fileTransferManager = new DummyFileTransferManager();
+#endif
 }
 
 void Client::requestRoster() {
diff --git a/Swiften/Client/Client.h b/Swiften/Client/Client.h
index 7269f10..940a526 100644
--- a/Swiften/Client/Client.h
+++ b/Swiften/Client/Client.h
@@ -35,7 +35,7 @@ namespace Swift {
 	class NickManager;
 	class FileTransferManager;
 	class JingleSessionManager;
-	class FileTransferManagerImpl;
+	class FileTransferManager;
 
 	/**
 	 * Provides the core functionality for writing XMPP client software.
@@ -136,7 +136,10 @@ namespace Swift {
 			}
 			
 			/**
-			 * Returns a FileTransferManager for the client. This is only available after the onConnected signal has been fired.
+			 * Returns a FileTransferManager for the client. This is only available after the onConnected 
+			 * signal has been fired.
+			 *
+			 * WARNING: File transfer will only work if Swiften is built in 'experimental' mode.
 			 */
 			FileTransferManager* getFileTransferManager() const;
 
@@ -180,7 +183,7 @@ namespace Swift {
 			MUCManager* mucManager;
 			ClientDiscoManager* discoManager;
 			JingleSessionManager* jingleSessionManager;
-			FileTransferManagerImpl* fileTransferManager;
+			FileTransferManager* fileTransferManager;
 			BlindCertificateTrustChecker* blindCertificateTrustChecker;
 	};
 }
diff --git a/Swiften/FileTransfer/ConnectivityManager.cpp b/Swiften/FileTransfer/ConnectivityManager.cpp
index 174d6ab..cfb0729 100644
--- a/Swiften/FileTransfer/ConnectivityManager.cpp
+++ b/Swiften/FileTransfer/ConnectivityManager.cpp
@@ -6,17 +6,19 @@
 
 #include "ConnectivityManager.h"
 
+#include <boost/bind.hpp>
+
 #include <Swiften/Base/foreach.h>
 #include <Swiften/Base/Log.h>
 #include <Swiften/Network/NetworkInterface.h>
-#include <Swiften/Network/PlatformNATTraversalGetPublicIPRequest.h>
-#include <Swiften/Network/PlatformNATTraversalRemovePortForwardingRequest.h>
-#include <Swiften/Network/PlatformNATTraversalWorker.h>
+#include <Swiften/Network/NATTraversalGetPublicIPRequest.h>
+#include <Swiften/Network/NATTraversalRemovePortForwardingRequest.h>
+#include <Swiften/Network/NATTraverser.h>
 #include <Swiften/Network/PlatformNetworkEnvironment.h>
 
 namespace Swift {
 
-ConnectivityManager::ConnectivityManager(PlatformNATTraversalWorker* worker) : natTraversalWorker(worker) {
+ConnectivityManager::ConnectivityManager(NATTraverser* worker) : natTraversalWorker(worker) {
 
 }
 
@@ -29,13 +31,13 @@ ConnectivityManager::~ConnectivityManager() {
 
 void ConnectivityManager::addListeningPort(int port) {
 	ports.insert(port);
-	boost::shared_ptr<PlatformNATTraversalGetPublicIPRequest> getIPRequest = natTraversalWorker->createGetPublicIPRequest();
+	boost::shared_ptr<NATTraversalGetPublicIPRequest> getIPRequest = natTraversalWorker->createGetPublicIPRequest();
 	if (getIPRequest) {
 		getIPRequest->onResult.connect(boost::bind(&ConnectivityManager::natTraversalGetPublicIPResult, this, _1));
 		getIPRequest->run();
 	}
 
-	boost::shared_ptr<PlatformNATTraversalForwardPortRequest> forwardPortRequest = natTraversalWorker->createForwardPortRequest(port, port);
+	boost::shared_ptr<NATTraversalForwardPortRequest> forwardPortRequest = natTraversalWorker->createForwardPortRequest(port, port);
 	if (forwardPortRequest) {
 		forwardPortRequest->onResult.connect(boost::bind(&ConnectivityManager::natTraversalForwardPortResult, this, _1));
 		forwardPortRequest->run();
@@ -45,7 +47,7 @@ void ConnectivityManager::addListeningPort(int port) {
 void ConnectivityManager::removeListeningPort(int port) {
 	SWIFT_LOG(debug) << "remove listening port " << port << std::endl;
 	ports.erase(port);
-	boost::shared_ptr<PlatformNATTraversalRemovePortForwardingRequest> removePortForwardingRequest = natTraversalWorker->createRemovePortForwardingRequest(port, port);
+	boost::shared_ptr<NATTraversalRemovePortForwardingRequest> removePortForwardingRequest = natTraversalWorker->createRemovePortForwardingRequest(port, port);
 	if (removePortForwardingRequest) {
 		removePortForwardingRequest->run();
 	}
@@ -89,7 +91,7 @@ void ConnectivityManager::natTraversalGetPublicIPResult(boost::optional<HostAddr
 	}
 }
 
-void ConnectivityManager::natTraversalForwardPortResult(boost::optional<PlatformNATTraversalForwardPortRequest::PortMapping> mapping) {
+void ConnectivityManager::natTraversalForwardPortResult(boost::optional<NATTraversalForwardPortRequest::PortMapping> mapping) {
 	if (mapping) {
 		SWIFT_LOG(debug) << "Mapping port was successful." << std::endl;
 	} else {
diff --git a/Swiften/FileTransfer/ConnectivityManager.h b/Swiften/FileTransfer/ConnectivityManager.h
index 87041b2..41e0ab6 100644
--- a/Swiften/FileTransfer/ConnectivityManager.h
+++ b/Swiften/FileTransfer/ConnectivityManager.h
@@ -12,15 +12,16 @@
 #include <boost/optional.hpp>
 
 #include <Swiften/Network/HostAddressPort.h>
-#include <Swiften/Network/PlatformNATTraversalForwardPortRequest.h>
+#include <Swiften/Network/NATTraverser.h>
+#include <Swiften/Network/NATTraversalForwardPortRequest.h>
 
 namespace Swift {
 
-class PlatformNATTraversalWorker;
+class NATTraverser;
 
 class ConnectivityManager {
 public:
-	ConnectivityManager(PlatformNATTraversalWorker*);
+	ConnectivityManager(NATTraverser*);
 	~ConnectivityManager();
 public:
 	void addListeningPort(int port);
@@ -31,10 +32,10 @@ public:
 
 private:
 	void natTraversalGetPublicIPResult(boost::optional<HostAddress> address);
-	void natTraversalForwardPortResult(boost::optional<PlatformNATTraversalForwardPortRequest::PortMapping> mapping);
+	void natTraversalForwardPortResult(boost::optional<NATTraversalForwardPortRequest::PortMapping> mapping);
 
 private:
-	PlatformNATTraversalWorker* natTraversalWorker;
+	NATTraverser* natTraversalWorker;
 
 	std::set<int> ports;
 	boost::optional<HostAddress> publicAddress;
diff --git a/Swiften/FileTransfer/FileTransferManagerImpl.cpp b/Swiften/FileTransfer/FileTransferManagerImpl.cpp
index f89a3e9..a30aeed 100644
--- a/Swiften/FileTransfer/FileTransferManagerImpl.cpp
+++ b/Swiften/FileTransfer/FileTransferManagerImpl.cpp
@@ -25,14 +25,14 @@
 #include <Swiften/Network/ConnectionFactory.h>
 #include <Swiften/Network/ConnectionServerFactory.h>
 #include <Swiften/Network/HostAddress.h>
-#include <Swiften/Network/PlatformNATTraversalWorker.h>
+#include <Swiften/Network/NATTraverser.h>
 
 namespace Swift {
 
-FileTransferManagerImpl::FileTransferManagerImpl(const JID& ownFullJID, JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, PresenceOracle* presOracle, ConnectionFactory* connectionFactory, ConnectionServerFactory* connectionServerFactory, TimerFactory* timerFactory, PlatformNATTraversalWorker* natTraversalWorker) : ownJID(ownFullJID), jingleSM(jingleSessionManager), iqRouter(router), capsProvider(capsProvider), presenceOracle(presOracle), timerFactory(timerFactory), connectionFactory(connectionFactory), connectionServerFactory(connectionServerFactory), natTraversalWorker(natTraversalWorker), bytestreamServer(NULL) {
+FileTransferManagerImpl::FileTransferManagerImpl(const JID& ownFullJID, JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, PresenceOracle* presOracle, ConnectionFactory* connectionFactory, ConnectionServerFactory* connectionServerFactory, TimerFactory* timerFactory, NATTraverser* natTraverser) : ownJID(ownFullJID), jingleSM(jingleSessionManager), iqRouter(router), capsProvider(capsProvider), presenceOracle(presOracle), timerFactory(timerFactory), connectionFactory(connectionFactory), connectionServerFactory(connectionServerFactory), natTraverser(natTraverser), bytestreamServer(NULL) {
 	assert(!ownFullJID.isBare());
 
-	connectivityManager = new ConnectivityManager(natTraversalWorker);
+	connectivityManager = new ConnectivityManager(natTraverser);
 	bytestreamRegistry = new SOCKS5BytestreamRegistry();
 	bytestreamProxy = new SOCKS5BytestreamProxy(connectionFactory, timerFactory);
 
diff --git a/Swiften/FileTransfer/FileTransferManagerImpl.h b/Swiften/FileTransfer/FileTransferManagerImpl.h
index b38eaea..d1c3786 100644
--- a/Swiften/FileTransfer/FileTransferManagerImpl.h
+++ b/Swiften/FileTransfer/FileTransferManagerImpl.h
@@ -32,7 +32,7 @@ class IncomingFileTransferManager;
 class JingleSessionManager;
 class LocalJingleTransportCandidateGeneratorFactory;
 class OutgoingFileTransferManager;
-class PlatformNATTraversalWorker;
+class NATTraverser;
 class PresenceOracle;
 class ReadBytestream;
 class RemoteJingleTransportCandidateSelectorFactory;
@@ -43,7 +43,7 @@ class TimerFactory;
 
 class FileTransferManagerImpl : public FileTransferManager {
 public:
-	FileTransferManagerImpl(const JID& ownFullJID, JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, PresenceOracle* presOracle, ConnectionFactory* connectionFactory, ConnectionServerFactory* connectionServerFactory, TimerFactory* timerFactory, PlatformNATTraversalWorker* natTraversalWorker);
+	FileTransferManagerImpl(const JID& ownFullJID, JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, PresenceOracle* presOracle, ConnectionFactory* connectionFactory, ConnectionServerFactory* connectionServerFactory, TimerFactory* timerFactory, NATTraverser* natTraverser);
 	~FileTransferManagerImpl();
 	
 	void startListeningOnPort(int port);
@@ -70,7 +70,7 @@ private:
 	TimerFactory* timerFactory;
 	ConnectionFactory* connectionFactory;
 	ConnectionServerFactory* connectionServerFactory;
-	PlatformNATTraversalWorker* natTraversalWorker;
+	NATTraverser* natTraverser;
 	SOCKS5BytestreamRegistry* bytestreamRegistry;
 	SOCKS5BytestreamServer* bytestreamServer;
 	SOCKS5BytestreamProxy* bytestreamProxy;
diff --git a/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp b/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp
index 7407f44..4c6ae72 100644
--- a/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp
+++ b/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp
@@ -156,7 +156,7 @@ public:
 		void test_AcceptOnyIBBSendsSessionAccept() {
 			//1. create your test incoming file transfer
 			shared_ptr<JingleFileTransferDescription> desc = make_shared<JingleFileTransferDescription>();
-			desc->addOffer(StreamInitiationFileInfo());
+			desc->addOffer(StreamInitiationFileInfo("foo.txt", "", 10));
 			jingleContentPayload->addDescription(desc);
 			JingleIBBTransportPayload::ref tpRef = make_shared<JingleIBBTransportPayload>();
 			tpRef->setSessionID("mysession");
@@ -175,7 +175,7 @@ public:
 		void test_OnlyIBBTransferReceiveWorks() {
 			//1. create your test incoming file transfer
 			shared_ptr<JingleFileTransferDescription> desc = make_shared<JingleFileTransferDescription>();
-			desc->addOffer(StreamInitiationFileInfo());
+			desc->addOffer(StreamInitiationFileInfo("file.txt", "", 10));
 			jingleContentPayload->addDescription(desc);
 			JingleIBBTransportPayload::ref tpRef = make_shared<JingleIBBTransportPayload>();
 			tpRef->setSessionID("mysession");
@@ -235,7 +235,7 @@ public:
 private:
 	void addFileTransferDescription() {
 		shared_ptr<JingleFileTransferDescription> desc = make_shared<JingleFileTransferDescription>();
-		desc->addOffer(StreamInitiationFileInfo());
+		desc->addOffer(StreamInitiationFileInfo("file.txt", "", 10));
 		jingleContentPayload->addDescription(desc);
 	}
 
diff --git a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp
index 35580bf..75b9faf 100644
--- a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp
+++ b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp
@@ -189,7 +189,7 @@ public:
 		CPPUNIT_ASSERT_EQUAL(false, helper.sessionReadyError);
 
 		helper.unprocessedInput.clear();
-		ByteArray transferData = generateRandomByteArray(1024 * 1024);
+		ByteArray transferData = generateRandomByteArray(1024);
 		boost::shared_ptr<ByteArrayReadBytestream> input = boost::make_shared<ByteArrayReadBytestream>(transferData);
 		clientSession->startSending(input);
 		eventLoop->processEvents();
diff --git a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp
index cd480f0..4fe72c0 100644
--- a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp
+++ b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp
@@ -96,6 +96,7 @@ class SOCKS5BytestreamServerSessionTest : public CppUnit::TestFixture {
 			eventLoop->processEvents();
 			testling->startTransfer();
 			skipHeader("abcdef");
+			eventLoop->processEvents();
 
 			CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData);
 			CPPUNIT_ASSERT_EQUAL(2, receivedDataChunks);
diff --git a/Swiften/Network/BoostNetworkFactories.cpp b/Swiften/Network/BoostNetworkFactories.cpp
index c13270f..315290c 100644
--- a/Swiften/Network/BoostNetworkFactories.cpp
+++ b/Swiften/Network/BoostNetworkFactories.cpp
@@ -10,6 +10,7 @@
 #include <Swiften/Network/PlatformDomainNameResolver.h>
 #include <Swiften/Network/BoostConnectionServerFactory.h>
 #include <Swiften/Network/PlatformNATTraversalWorker.h>
+#include <Swiften/Network/NullNATTraverser.h>
 
 namespace Swift {
 
@@ -18,11 +19,15 @@ BoostNetworkFactories::BoostNetworkFactories(EventLoop* eventLoop) {
 	connectionFactory = new BoostConnectionFactory(ioServiceThread.getIOService(), eventLoop);
 	domainNameResolver = new PlatformDomainNameResolver(eventLoop);
 	connectionServerFactory = new BoostConnectionServerFactory(ioServiceThread.getIOService(), eventLoop);
-	platformNATTraversalWorker = new PlatformNATTraversalWorker(eventLoop);
+#ifdef SWIFT_EXPERIMENTAL_FT
+	natTraverser = new PlatformNATTraversalWorker(eventLoop);
+#else
+	natTraverser = new NullNATTraverser(eventLoop);
+#endif
 }
 
 BoostNetworkFactories::~BoostNetworkFactories() {
-	delete platformNATTraversalWorker;
+	delete natTraverser;
 	delete connectionServerFactory;
 	delete domainNameResolver;
 	delete connectionFactory;
diff --git a/Swiften/Network/BoostNetworkFactories.h b/Swiften/Network/BoostNetworkFactories.h
index a1cf9ae..bc7a963 100644
--- a/Swiften/Network/BoostNetworkFactories.h
+++ b/Swiften/Network/BoostNetworkFactories.h
@@ -11,6 +11,7 @@
 
 namespace Swift {
 	class EventLoop;
+	class NATTraverser;
 
 	class BoostNetworkFactories : public NetworkFactories {
 		public:
@@ -37,8 +38,8 @@ namespace Swift {
 				return connectionServerFactory;
 			}
 
-			PlatformNATTraversalWorker* getPlatformNATTraversalWorker() const {
-				return platformNATTraversalWorker;
+			NATTraverser* getNATTraverser() const {
+				return natTraverser;
 			}
 
 		private:
@@ -47,6 +48,6 @@ namespace Swift {
 			ConnectionFactory* connectionFactory;
 			DomainNameResolver* domainNameResolver;
 			ConnectionServerFactory* connectionServerFactory;
-			PlatformNATTraversalWorker* platformNATTraversalWorker;
+			NATTraverser* natTraverser;
 	};
 }
diff --git a/Swiften/Network/NATPMPNATTraversalForwardPortRequest.cpp b/Swiften/Network/NATPMPNATTraversalForwardPortRequest.cpp
index 69b325c..d7ef88a 100644
--- a/Swiften/Network/NATPMPNATTraversalForwardPortRequest.cpp
+++ b/Swiften/Network/NATPMPNATTraversalForwardPortRequest.cpp
@@ -10,9 +10,11 @@
 
 #include <Swiften/Base/Log.h>
 
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+
 namespace Swift {
 
-NATPMPNATTraversalForwardPortRequest::NATPMPNATTraversalForwardPortRequest(PlatformNATTraversalForwardPortRequest::PortMapping mapping, PlatformNATTraversalWorker* worker) : PlatformNATTraversalForwardPortRequest(worker), mapping(mapping) {
+NATPMPNATTraversalForwardPortRequest::NATPMPNATTraversalForwardPortRequest(NATTraversalForwardPortRequest::PortMapping mapping, PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker), mapping(mapping) {
 
 }
 
diff --git a/Swiften/Network/NATPMPNATTraversalForwardPortRequest.h b/Swiften/Network/NATPMPNATTraversalForwardPortRequest.h
index 71d8621..99a5d04 100644
--- a/Swiften/Network/NATPMPNATTraversalForwardPortRequest.h
+++ b/Swiften/Network/NATPMPNATTraversalForwardPortRequest.h
@@ -6,19 +6,24 @@
 
 #pragma once
 
-#include <Swiften/Network/PlatformNATTraversalForwardPortRequest.h>
+#include <Swiften/Network/NATTraversalForwardPortRequest.h>
+#include <Swiften/Network/PlatformNATTraversalRequest.h>
 
 namespace Swift {
 
-class NATPMPNATTraversalForwardPortRequest : public PlatformNATTraversalForwardPortRequest {
+class NATPMPNATTraversalForwardPortRequest : public NATTraversalForwardPortRequest, public PlatformNATTraversalRequest {
 public:
-	NATPMPNATTraversalForwardPortRequest(PlatformNATTraversalForwardPortRequest::PortMapping, PlatformNATTraversalWorker*);
+	NATPMPNATTraversalForwardPortRequest(NATTraversalForwardPortRequest::PortMapping, PlatformNATTraversalWorker*);
 	virtual ~NATPMPNATTraversalForwardPortRequest();
 
 	virtual void runBlocking();
 
+	virtual void run() {
+		doRun();
+	}
+
 private:
-	PlatformNATTraversalForwardPortRequest::PortMapping mapping;
+	NATTraversalForwardPortRequest::PortMapping mapping;
 };
 
 }
diff --git a/Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.cpp b/Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.cpp
index 06a21a3..0f6067d 100644
--- a/Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.cpp
+++ b/Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.cpp
@@ -10,9 +10,11 @@
 
 #include <Swiften/Base/Log.h>
 
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+
 namespace Swift {
 
-NATPMPNATTraversalGetPublicIPRequest::NATPMPNATTraversalGetPublicIPRequest(PlatformNATTraversalWorker* worker) : PlatformNATTraversalGetPublicIPRequest(worker) {
+NATPMPNATTraversalGetPublicIPRequest::NATPMPNATTraversalGetPublicIPRequest(PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker) {
 
 }
 
diff --git a/Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.h b/Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.h
index 6112091..dba447c 100644
--- a/Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.h
+++ b/Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.h
@@ -6,17 +6,21 @@
 
 #pragma once
 
-#include <Swiften/Network/PlatformNATTraversalGetPublicIPRequest.h>
+#include <Swiften/Network/PlatformNATTraversalRequest.h>
+#include <Swiften/Network/NATTraversalGetPublicIPRequest.h>
 
 namespace Swift {
 
-class NATPMPNATTraversalGetPublicIPRequest : public PlatformNATTraversalGetPublicIPRequest {
+class NATPMPNATTraversalGetPublicIPRequest : public NATTraversalGetPublicIPRequest, public PlatformNATTraversalRequest {
 public:
 	NATPMPNATTraversalGetPublicIPRequest(PlatformNATTraversalWorker*);
 	virtual ~NATPMPNATTraversalGetPublicIPRequest();
 
-	//virtual void run();
 	virtual void runBlocking();
+
+	virtual void run() {
+		doRun();
+	}
 };
 
 }
diff --git a/Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.cpp b/Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.cpp
index c99ac92..a21383c 100644
--- a/Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.cpp
+++ b/Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.cpp
@@ -15,9 +15,11 @@
 #include <Swiften/Network/NetworkInterface.h>
 #include <Swiften/Network/PlatformNetworkEnvironment.h>
 
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+
 namespace Swift {
 
-NATPMPNATTraversalRemovePortForwardingRequest::NATPMPNATTraversalRemovePortForwardingRequest(PlatformNATTraversalRemovePortForwardingRequest::PortMapping mapping, PlatformNATTraversalWorker* worker) : PlatformNATTraversalRemovePortForwardingRequest(worker), mapping(mapping) {
+NATPMPNATTraversalRemovePortForwardingRequest::NATPMPNATTraversalRemovePortForwardingRequest(PortMapping mapping, PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker), mapping(mapping) {
 
 }
 
diff --git a/Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.h b/Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.h
index c4ffcf3..3eb2b15 100644
--- a/Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.h
+++ b/Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.h
@@ -6,22 +6,27 @@
 
 #pragma once
 
-#include <Swiften/Network/PlatformNATTraversalRemovePortForwardingRequest.h>
+#include <Swiften/Network/NATTraversalRemovePortForwardingRequest.h>
+#include <Swiften/Network/PlatformNATTraversalRequest.h>
 
 namespace Swift {
 
-class NATPMPNATTraversalRemovePortForwardingRequest : public PlatformNATTraversalRemovePortForwardingRequest {
+class NATPMPNATTraversalRemovePortForwardingRequest : public NATTraversalRemovePortForwardingRequest, public PlatformNATTraversalRequest {
 public:
-	NATPMPNATTraversalRemovePortForwardingRequest(PlatformNATTraversalRemovePortForwardingRequest::PortMapping, PlatformNATTraversalWorker*);
+	NATPMPNATTraversalRemovePortForwardingRequest(PortMapping, PlatformNATTraversalWorker*);
 	virtual ~NATPMPNATTraversalRemovePortForwardingRequest();
 
 	virtual void runBlocking();
 
+	virtual void run() {
+		doRun();
+	}
+
 private:
 	HostAddress getLocalClient();
 
 private:
-	PlatformNATTraversalRemovePortForwardingRequest::PortMapping mapping;
+	PortMapping mapping;
 };
 
 }
diff --git a/Swiften/Network/NATTraversalForwardPortRequest.cpp b/Swiften/Network/NATTraversalForwardPortRequest.cpp
new file mode 100644
index 0000000..c364b8f
--- /dev/null
+++ b/Swiften/Network/NATTraversalForwardPortRequest.cpp
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <Swiften/Network/NATTraversalForwardPortRequest.h>
+
+namespace Swift {
+
+NATTraversalForwardPortRequest::~NATTraversalForwardPortRequest() {
+}
+
+}
diff --git a/Swiften/Network/NATTraversalForwardPortRequest.h b/Swiften/Network/NATTraversalForwardPortRequest.h
new file mode 100644
index 0000000..8cdbd3d
--- /dev/null
+++ b/Swiften/Network/NATTraversalForwardPortRequest.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/boost_bsignals.h>
+#include <Swiften/Network/HostAddress.h>
+
+namespace Swift {
+	class NATTraversalForwardPortRequest {
+		public:
+			struct PortMapping {
+				enum Protocol {
+					TCP,
+					UDP,
+				};
+
+				unsigned int publicPort;
+				unsigned int localPort;
+				Protocol protocol;
+				unsigned long leaseInSeconds;
+			};
+
+		public:
+			virtual ~NATTraversalForwardPortRequest();
+
+			virtual void run() = 0;
+
+			boost::signal<void (boost::optional<PortMapping>)> onResult;
+	};
+}
diff --git a/Swiften/Network/NATTraversalGetPublicIPRequest.cpp b/Swiften/Network/NATTraversalGetPublicIPRequest.cpp
new file mode 100644
index 0000000..d8219d5
--- /dev/null
+++ b/Swiften/Network/NATTraversalGetPublicIPRequest.cpp
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <Swiften/Network/NATTraversalGetPublicIPRequest.h>
+
+namespace Swift {
+
+NATTraversalGetPublicIPRequest::~NATTraversalGetPublicIPRequest() {
+}
+
+}
diff --git a/Swiften/Network/NATTraversalGetPublicIPRequest.h b/Swiften/Network/NATTraversalGetPublicIPRequest.h
new file mode 100644
index 0000000..db1f005
--- /dev/null
+++ b/Swiften/Network/NATTraversalGetPublicIPRequest.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/boost_bsignals.h>
+#include <Swiften/Network/HostAddress.h>
+
+namespace Swift {
+	class NATTraversalGetPublicIPRequest {
+		public:
+			virtual ~NATTraversalGetPublicIPRequest();
+
+			virtual void run() = 0;
+
+			boost::signal<void (boost::optional<HostAddress>)> onResult;
+	};
+}
diff --git a/Swiften/Network/NATTraversalRemovePortForwardingRequest.cpp b/Swiften/Network/NATTraversalRemovePortForwardingRequest.cpp
new file mode 100644
index 0000000..04ec715
--- /dev/null
+++ b/Swiften/Network/NATTraversalRemovePortForwardingRequest.cpp
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <Swiften/Network/NATTraversalRemovePortForwardingRequest.h>
+
+namespace Swift {
+
+NATTraversalRemovePortForwardingRequest::~NATTraversalRemovePortForwardingRequest() {
+}
+
+}
diff --git a/Swiften/Network/NATTraversalRemovePortForwardingRequest.h b/Swiften/Network/NATTraversalRemovePortForwardingRequest.h
new file mode 100644
index 0000000..cf349b1
--- /dev/null
+++ b/Swiften/Network/NATTraversalRemovePortForwardingRequest.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/boost_bsignals.h>
+#include <Swiften/Network/HostAddress.h>
+
+namespace Swift {
+	class NATTraversalRemovePortForwardingRequest {
+		public:
+			struct PortMapping {
+				enum Protocol {
+					TCP,
+					UDP,
+				};
+
+				unsigned int publicPort;
+				unsigned int localPort;
+				Protocol protocol;
+				unsigned long leaseInSeconds;
+			};
+
+		public:
+			virtual ~NATTraversalRemovePortForwardingRequest();
+
+			virtual void run() = 0;
+
+			boost::signal<void (boost::optional<bool> /* failure */)> onResult;
+	};
+}
diff --git a/Swiften/Network/NATTraverser.cpp b/Swiften/Network/NATTraverser.cpp
new file mode 100644
index 0000000..8c628ee
--- /dev/null
+++ b/Swiften/Network/NATTraverser.cpp
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Network/NATTraverser.h>
+
+namespace Swift {
+
+NATTraverser::~NATTraverser() {
+}
+
+}
diff --git a/Swiften/Network/NATTraverser.h b/Swiften/Network/NATTraverser.h
new file mode 100644
index 0000000..4afd624
--- /dev/null
+++ b/Swiften/Network/NATTraverser.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+namespace Swift {
+	class NATTraversalGetPublicIPRequest;
+	class NATTraversalForwardPortRequest;
+	class NATTraversalRemovePortForwardingRequest;
+
+	class NATTraverser {
+		public:
+			virtual ~NATTraverser();
+
+			virtual boost::shared_ptr<NATTraversalGetPublicIPRequest> createGetPublicIPRequest() = 0;
+			virtual boost::shared_ptr<NATTraversalForwardPortRequest> createForwardPortRequest(unsigned int localPort, unsigned int publicPort) = 0;
+			virtual boost::shared_ptr<NATTraversalRemovePortForwardingRequest> createRemovePortForwardingRequest(unsigned int localPort, unsigned int publicPort) = 0;
+	};
+}
diff --git a/Swiften/Network/NetworkFactories.h b/Swiften/Network/NetworkFactories.h
index e7d2ff0..05ddfe3 100644
--- a/Swiften/Network/NetworkFactories.h
+++ b/Swiften/Network/NetworkFactories.h
@@ -11,7 +11,7 @@ namespace Swift {
 	class ConnectionFactory;
 	class DomainNameResolver;
 	class ConnectionServerFactory;
-	class PlatformNATTraversalWorker;
+	class NATTraverser;
 
 	/**
 	 * An interface collecting network factories.
@@ -24,6 +24,6 @@ namespace Swift {
 			virtual ConnectionFactory* getConnectionFactory() const = 0;
 			virtual DomainNameResolver* getDomainNameResolver() const = 0;
 			virtual ConnectionServerFactory* getConnectionServerFactory() const = 0;
-			virtual PlatformNATTraversalWorker* getPlatformNATTraversalWorker() const = 0;
+			virtual NATTraverser* getNATTraverser() const = 0;
 	};
 }
diff --git a/Swiften/Network/NullNATTraverser.cpp b/Swiften/Network/NullNATTraverser.cpp
new file mode 100644
index 0000000..018ef91
--- /dev/null
+++ b/Swiften/Network/NullNATTraverser.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Network/NullNATTraverser.h>
+
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/bind.hpp>
+
+#include <Swiften/Network/NATTraversalGetPublicIPRequest.h>
+#include <Swiften/Network/NATTraversalForwardPortRequest.h>
+#include <Swiften/Network/NATTraversalRemovePortForwardingRequest.h>
+#include <Swiften/EventLoop/EventLoop.h>
+
+namespace Swift {
+
+class NullNATTraversalGetPublicIPRequest : public NATTraversalGetPublicIPRequest {
+	public:
+		NullNATTraversalGetPublicIPRequest(EventLoop* eventLoop) : eventLoop(eventLoop) {
+		}
+
+		virtual void run() {
+			eventLoop->postEvent(boost::bind(boost::ref(onResult), boost::optional<HostAddress>()));
+		}
+
+	private:
+		EventLoop* eventLoop;
+};
+
+class NullNATTraversalForwardPortRequest : public NATTraversalForwardPortRequest {
+	public:
+		NullNATTraversalForwardPortRequest(EventLoop* eventLoop) : eventLoop(eventLoop) {
+		}
+
+		virtual void run() {
+			eventLoop->postEvent(boost::bind(boost::ref(onResult), boost::optional<PortMapping>()));
+		}
+
+	private:
+		EventLoop* eventLoop;
+};
+
+class NullNATTraversalRemovePortForwardingRequest : public NATTraversalRemovePortForwardingRequest {
+	public:
+		NullNATTraversalRemovePortForwardingRequest(EventLoop* eventLoop) : eventLoop(eventLoop) {
+		}
+
+		virtual void run() {
+			eventLoop->postEvent(boost::bind(boost::ref(onResult), boost::optional<bool>(true)));
+		}
+
+	private:
+		EventLoop* eventLoop;
+};
+
+NullNATTraverser::NullNATTraverser(EventLoop* eventLoop) : eventLoop(eventLoop) {
+}
+
+boost::shared_ptr<NATTraversalGetPublicIPRequest> NullNATTraverser::createGetPublicIPRequest() {
+	return boost::make_shared<NullNATTraversalGetPublicIPRequest>(eventLoop);
+}
+
+boost::shared_ptr<NATTraversalForwardPortRequest> NullNATTraverser::createForwardPortRequest(unsigned int, unsigned int) {
+	return boost::make_shared<NullNATTraversalForwardPortRequest>(eventLoop);
+}
+
+boost::shared_ptr<NATTraversalRemovePortForwardingRequest> NullNATTraverser::createRemovePortForwardingRequest(unsigned int, unsigned int) {
+	return boost::make_shared<NullNATTraversalRemovePortForwardingRequest>(eventLoop);
+}
+
+}
diff --git a/Swiften/Network/NullNATTraverser.h b/Swiften/Network/NullNATTraverser.h
new file mode 100644
index 0000000..1b66a7d
--- /dev/null
+++ b/Swiften/Network/NullNATTraverser.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Network/NATTraverser.h>
+
+namespace Swift {
+	class EventLoop;
+
+	class NullNATTraverser : public NATTraverser {
+		public:
+			NullNATTraverser(EventLoop* eventLoop);
+
+			boost::shared_ptr<NATTraversalGetPublicIPRequest> createGetPublicIPRequest();
+			boost::shared_ptr<NATTraversalForwardPortRequest> createForwardPortRequest(unsigned int localPort, unsigned int publicPort);
+			boost::shared_ptr<NATTraversalRemovePortForwardingRequest> createRemovePortForwardingRequest(unsigned int localPort, unsigned int publicPort);
+
+		private:
+			EventLoop* eventLoop;
+	};
+}
diff --git a/Swiften/Network/PlatformNATTraversalForwardPortRequest.cpp b/Swiften/Network/PlatformNATTraversalForwardPortRequest.cpp
deleted file mode 100644
index b28024a..0000000
--- a/Swiften/Network/PlatformNATTraversalForwardPortRequest.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (c) 2011 Tobias Markmann
- * Licensed under the simplified BSD license.
- * See Documentation/Licenses/BSD-simplified.txt for more information.
- */
-
-#include "PlatformNATTraversalForwardPortRequest.h"
-
-namespace Swift {
-
-PlatformNATTraversalForwardPortRequest::PlatformNATTraversalForwardPortRequest(PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker) {
-}
-
-PlatformNATTraversalForwardPortRequest::~PlatformNATTraversalForwardPortRequest() {
-
-}
-
-}
diff --git a/Swiften/Network/PlatformNATTraversalForwardPortRequest.h b/Swiften/Network/PlatformNATTraversalForwardPortRequest.h
deleted file mode 100644
index cb1750c..0000000
--- a/Swiften/Network/PlatformNATTraversalForwardPortRequest.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2011 Tobias Markmann
- * Licensed under the simplified BSD license.
- * See Documentation/Licenses/BSD-simplified.txt for more information.
- */
-
-#pragma once
-
-#include <Swiften/Base/boost_bsignals.h>
-#include <Swiften/Network/HostAddress.h>
-#include <Swiften/Network/PlatformNATTraversalRequest.h>
-
-namespace Swift {
-
-class PlatformNATTraversalWorker;
-
-class PlatformNATTraversalForwardPortRequest : public PlatformNATTraversalRequest {
-public:
-	struct PortMapping {
-		enum Protocol {
-			TCP,
-			UDP,
-		};
-
-		unsigned int publicPort;
-		unsigned int localPort;
-		Protocol protocol;
-		unsigned long leaseInSeconds;
-	};
-
-public:
-	PlatformNATTraversalForwardPortRequest(PlatformNATTraversalWorker* worker);
-	virtual ~PlatformNATTraversalForwardPortRequest();
-
-	boost::signal<void (boost::optional<PortMapping>)> onResult;
-};
-
-}
diff --git a/Swiften/Network/PlatformNATTraversalGetPublicIPRequest.cpp b/Swiften/Network/PlatformNATTraversalGetPublicIPRequest.cpp
deleted file mode 100644
index 7a57e30..0000000
--- a/Swiften/Network/PlatformNATTraversalGetPublicIPRequest.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (c) 2011 Tobias Markmann
- * Licensed under the simplified BSD license.
- * See Documentation/Licenses/BSD-simplified.txt for more information.
- */
-
-#include "PlatformNATTraversalGetPublicIPRequest.h"
-
-namespace Swift {
-
-PlatformNATTraversalGetPublicIPRequest::PlatformNATTraversalGetPublicIPRequest(PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker) {
-}
-
-PlatformNATTraversalGetPublicIPRequest::~PlatformNATTraversalGetPublicIPRequest() {
-
-}
-
-}
diff --git a/Swiften/Network/PlatformNATTraversalGetPublicIPRequest.h b/Swiften/Network/PlatformNATTraversalGetPublicIPRequest.h
deleted file mode 100644
index 1cb37fe..0000000
--- a/Swiften/Network/PlatformNATTraversalGetPublicIPRequest.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2011 Tobias Markmann
- * Licensed under the simplified BSD license.
- * See Documentation/Licenses/BSD-simplified.txt for more information.
- */
-
-#pragma once
-
-#include <Swiften/Base/boost_bsignals.h>
-#include <Swiften/Network/HostAddress.h>
-#include <Swiften/Network/PlatformNATTraversalRequest.h>
-
-namespace Swift {
-
-class PlatformNATTraversalWorker;
-
-class PlatformNATTraversalGetPublicIPRequest : public PlatformNATTraversalRequest {
-public:
-	PlatformNATTraversalGetPublicIPRequest(PlatformNATTraversalWorker* worker);
-	virtual ~PlatformNATTraversalGetPublicIPRequest();
-
-	boost::signal<void (boost::optional<HostAddress>)> onResult;
-};
-
-}
diff --git a/Swiften/Network/PlatformNATTraversalRemovePortForwardingRequest.cpp b/Swiften/Network/PlatformNATTraversalRemovePortForwardingRequest.cpp
deleted file mode 100644
index 514988e..0000000
--- a/Swiften/Network/PlatformNATTraversalRemovePortForwardingRequest.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (c) 2011 Tobias Markmann
- * Licensed under the simplified BSD license.
- * See Documentation/Licenses/BSD-simplified.txt for more information.
- */
-
-#include "PlatformNATTraversalRemovePortForwardingRequest.h"
-
-namespace Swift {
-
-PlatformNATTraversalRemovePortForwardingRequest::PlatformNATTraversalRemovePortForwardingRequest(PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker) {
-}
-
-PlatformNATTraversalRemovePortForwardingRequest::~PlatformNATTraversalRemovePortForwardingRequest() {
-
-}
-
-}
diff --git a/Swiften/Network/PlatformNATTraversalRemovePortForwardingRequest.h b/Swiften/Network/PlatformNATTraversalRemovePortForwardingRequest.h
deleted file mode 100644
index 03427ad..0000000
--- a/Swiften/Network/PlatformNATTraversalRemovePortForwardingRequest.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2011 Tobias Markmann
- * Licensed under the simplified BSD license.
- * See Documentation/Licenses/BSD-simplified.txt for more information.
- */
-
-#pragma once
-
-#include <Swiften/Base/boost_bsignals.h>
-#include <Swiften/Network/HostAddress.h>
-#include <Swiften/Network/PlatformNATTraversalRequest.h>
-
-namespace Swift {
-
-class PlatformNATTraversalWorker;
-
-class PlatformNATTraversalRemovePortForwardingRequest : public PlatformNATTraversalRequest {
-public:
-	struct PortMapping {
-		enum Protocol {
-			TCP,
-			UDP,
-		};
-
-		unsigned int publicPort;
-		unsigned int localPort;
-		Protocol protocol;
-		unsigned long leaseInSeconds;
-	};
-
-public:
-	PlatformNATTraversalRemovePortForwardingRequest(PlatformNATTraversalWorker* worker);
-	virtual ~PlatformNATTraversalRemovePortForwardingRequest();
-
-	boost::signal<void (boost::optional<bool> /* failure */)> onResult;
-};
-
-}
diff --git a/Swiften/Network/PlatformNATTraversalRequest.cpp b/Swiften/Network/PlatformNATTraversalRequest.cpp
index 25e8a32..f875630 100644
--- a/Swiften/Network/PlatformNATTraversalRequest.cpp
+++ b/Swiften/Network/PlatformNATTraversalRequest.cpp
@@ -18,7 +18,7 @@ PlatformNATTraversalRequest::~PlatformNATTraversalRequest() {
 
 }
 
-void PlatformNATTraversalRequest::run() {
+void PlatformNATTraversalRequest::doRun() {
 	worker->addRequestToQueue(shared_from_this());
 }
 
diff --git a/Swiften/Network/PlatformNATTraversalRequest.h b/Swiften/Network/PlatformNATTraversalRequest.h
index 4b760ad..a891bab 100644
--- a/Swiften/Network/PlatformNATTraversalRequest.h
+++ b/Swiften/Network/PlatformNATTraversalRequest.h
@@ -21,7 +21,7 @@ public:
 	PlatformNATTraversalRequest(PlatformNATTraversalWorker* worker);
 	virtual ~PlatformNATTraversalRequest();
 
-	virtual void run();
+	virtual void doRun();
 	virtual void runBlocking() = 0;
 
 private:
diff --git a/Swiften/Network/PlatformNATTraversalWorker.cpp b/Swiften/Network/PlatformNATTraversalWorker.cpp
index a4efedd..e0dcab5 100644
--- a/Swiften/Network/PlatformNATTraversalWorker.cpp
+++ b/Swiften/Network/PlatformNATTraversalWorker.cpp
@@ -14,7 +14,6 @@
 #include <Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.h>
 #include <Swiften/Network/NATPMPNATTraversalForwardPortRequest.h>
 #include <Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.h>
-#include <Swiften/Network/PlatformNATTraversalRemovePortForwardingRequest.h>
 
 namespace Swift {
 
@@ -30,7 +29,7 @@ PlatformNATTraversalWorker::~PlatformNATTraversalWorker() {
 	delete thread;
 }
 
-boost::shared_ptr<PlatformNATTraversalGetPublicIPRequest> PlatformNATTraversalWorker::createGetPublicIPRequest() {
+boost::shared_ptr<NATTraversalGetPublicIPRequest> PlatformNATTraversalWorker::createGetPublicIPRequest() {
 	switch(backendType) {
 		case UPnP:
 			return boost::make_shared<UPnPNATTraversalGetPublicIPRequest>(this);
@@ -40,12 +39,12 @@ boost::shared_ptr<PlatformNATTraversalGetPublicIPRequest> PlatformNATTraversalWo
 		case None:
 			break;
 	}
-	return boost::shared_ptr<PlatformNATTraversalGetPublicIPRequest>();
+	return boost::shared_ptr<NATTraversalGetPublicIPRequest>();
 }
 
-boost::shared_ptr<PlatformNATTraversalForwardPortRequest> PlatformNATTraversalWorker::createForwardPortRequest(unsigned int localPort, unsigned int publicPort) {
-	PlatformNATTraversalForwardPortRequest::PortMapping mapping;
-	mapping.protocol = PlatformNATTraversalForwardPortRequest::PortMapping::TCP;
+boost::shared_ptr<NATTraversalForwardPortRequest> PlatformNATTraversalWorker::createForwardPortRequest(unsigned int localPort, unsigned int publicPort) {
+	NATTraversalForwardPortRequest::PortMapping mapping;
+	mapping.protocol = NATTraversalForwardPortRequest::PortMapping::TCP;
 	mapping.leaseInSeconds = 60 * 60 * 24;
 	mapping.localPort = localPort;
 	mapping.publicPort = publicPort;
@@ -59,12 +58,12 @@ boost::shared_ptr<PlatformNATTraversalForwardPortRequest> PlatformNATTraversalWo
 		case None:
 			break;
 	}
-	return boost::shared_ptr<PlatformNATTraversalForwardPortRequest>();
+	return boost::shared_ptr<NATTraversalForwardPortRequest>();
 }
 
-boost::shared_ptr<PlatformNATTraversalRemovePortForwardingRequest> PlatformNATTraversalWorker::createRemovePortForwardingRequest(unsigned int localPort, unsigned int publicPort) {
-	PlatformNATTraversalRemovePortForwardingRequest::PortMapping mapping;
-	mapping.protocol = PlatformNATTraversalRemovePortForwardingRequest::PortMapping::TCP;
+boost::shared_ptr<NATTraversalRemovePortForwardingRequest> PlatformNATTraversalWorker::createRemovePortForwardingRequest(unsigned int localPort, unsigned int publicPort) {
+	NATTraversalRemovePortForwardingRequest::PortMapping mapping;
+	mapping.protocol = NATTraversalRemovePortForwardingRequest::PortMapping::TCP;
 	mapping.leaseInSeconds = 60 * 60 * 24;
 	mapping.localPort = localPort;
 	mapping.publicPort = publicPort;
@@ -78,7 +77,7 @@ boost::shared_ptr<PlatformNATTraversalRemovePortForwardingRequest> PlatformNATTr
 		case None:
 			break;
 	}
-	return boost::shared_ptr<PlatformNATTraversalRemovePortForwardingRequest>();
+	return boost::shared_ptr<NATTraversalRemovePortForwardingRequest>();
 }
 
 void PlatformNATTraversalWorker::run() {
diff --git a/Swiften/Network/PlatformNATTraversalWorker.h b/Swiften/Network/PlatformNATTraversalWorker.h
index 7c249cc..9de1258 100644
--- a/Swiften/Network/PlatformNATTraversalWorker.h
+++ b/Swiften/Network/PlatformNATTraversalWorker.h
@@ -12,17 +12,18 @@
 #include <boost/thread/mutex.hpp>
 #include <boost/thread/condition_variable.hpp>
 
+#include <Swiften/Network/NATTraverser.h>
 #include <Swiften/Network/HostAddressPort.h>
 #include <Swiften/Network/PlatformNATTraversalRequest.h>
 
 namespace Swift {
 
 class EventLoop;
-class PlatformNATTraversalGetPublicIPRequest;
-class PlatformNATTraversalForwardPortRequest;
-class PlatformNATTraversalRemovePortForwardingRequest;
+class NATTraversalGetPublicIPRequest;
+class NATTraversalForwardPortRequest;
+class NATTraversalRemovePortForwardingRequest;
 
-class PlatformNATTraversalWorker {
+class PlatformNATTraversalWorker : public NATTraverser {
 private:
 	enum BackendType {
 		NotYetDecided,
@@ -35,9 +36,9 @@ public:
 	PlatformNATTraversalWorker(EventLoop* eventLoop);
 	~PlatformNATTraversalWorker();
 
-	boost::shared_ptr<PlatformNATTraversalGetPublicIPRequest> createGetPublicIPRequest();
-	boost::shared_ptr<PlatformNATTraversalForwardPortRequest> createForwardPortRequest(unsigned int localPort, unsigned int publicPort);
-	boost::shared_ptr<PlatformNATTraversalRemovePortForwardingRequest> createRemovePortForwardingRequest(unsigned int localPort, unsigned int publicPort);
+	boost::shared_ptr<NATTraversalGetPublicIPRequest> createGetPublicIPRequest();
+	boost::shared_ptr<NATTraversalForwardPortRequest> createForwardPortRequest(unsigned int localPort, unsigned int publicPort);
+	boost::shared_ptr<NATTraversalRemovePortForwardingRequest> createRemovePortForwardingRequest(unsigned int localPort, unsigned int publicPort);
 
 	void run();
 	void addRequestToQueue(PlatformNATTraversalRequest::ref);
diff --git a/Swiften/Network/SConscript b/Swiften/Network/SConscript
index e9853dd..f168219 100644
--- a/Swiften/Network/SConscript
+++ b/Swiften/Network/SConscript
@@ -41,17 +41,13 @@ sourceList = [
 			"BoostTimer.cpp",
 			"ProxyProvider.cpp",
 			"NullProxyProvider.cpp",
+			"NATTraverser.cpp",
+			"NullNATTraverser.cpp",
+			"NATTraversalGetPublicIPRequest.cpp",
+			"NATTraversalForwardPortRequest.cpp",
+			"NATTraversalRemovePortForwardingRequest.cpp",
 			"PlatformNATTraversalWorker.cpp",
-			"PlatformNATTraversalGetPublicIPRequest.cpp",
-			"PlatformNATTraversalForwardPortRequest.cpp",
-			"PlatformNATTraversalRemovePortForwardingRequest.cpp",
 			"PlatformNATTraversalRequest.cpp",
-			"UPnPNATTraversalGetPublicIPRequest.cpp",
-			"UPnPNATTraversalForwardPortRequest.cpp",
-			"UPnPNATTraversalRemovePortForwardingRequest.cpp",
-			"NATPMPNATTraversalGetPublicIPRequest.cpp",
-			"NATPMPNATTraversalForwardPortRequest.cpp",
-			"NATPMPNATTraversalRemovePortForwardingRequest.cpp",
 	]
 
 if myenv.get("HAVE_CARES", False) :
@@ -74,4 +70,24 @@ else :
 		sourceList += [ "GConfProxyProvider.cpp" ]
 
 objects = myenv.SwiftenObject(sourceList)
+
+if myenv["experimental"] :
+	# LibNATPMP classes
+	natpmp_env = myenv.Clone()
+	natpmp_env.Append(CPPDEFINES = natpmp_env["LIBNATPMP_FLAGS"].get("INTERNAL_CPPDEFINES", []))
+	objects += natpmp_env.SwiftenObject([
+				"NATPMPNATTraversalGetPublicIPRequest.cpp",
+				"NATPMPNATTraversalForwardPortRequest.cpp",
+				"NATPMPNATTraversalRemovePortForwardingRequest.cpp"
+			])
+
+	# LibMINIUPnP classes
+	upnp_env = myenv.Clone()
+	upnp_env.Append(CPPDEFINES = upnp_env["LIBMINIUPNPC_FLAGS"].get("INTERNAL_CPPDEFINES", []))
+	objects += upnp_env.SwiftenObject([
+				"UPnPNATTraversalGetPublicIPRequest.cpp",
+				"UPnPNATTraversalForwardPortRequest.cpp",
+				"UPnPNATTraversalRemovePortForwardingRequest.cpp",
+			])
+
 swiften_env.Append(SWIFTEN_OBJECTS = [objects])
diff --git a/Swiften/Network/UPnPNATTraversalForwardPortRequest.cpp b/Swiften/Network/UPnPNATTraversalForwardPortRequest.cpp
index c95066e..065efbc 100644
--- a/Swiften/Network/UPnPNATTraversalForwardPortRequest.cpp
+++ b/Swiften/Network/UPnPNATTraversalForwardPortRequest.cpp
@@ -18,7 +18,7 @@
 
 namespace Swift {
 
-UPnPNATTraversalForwardPortRequest::UPnPNATTraversalForwardPortRequest(PlatformNATTraversalForwardPortRequest::PortMapping mapping, PlatformNATTraversalWorker* worker) : PlatformNATTraversalForwardPortRequest(worker), mapping(mapping) {
+UPnPNATTraversalForwardPortRequest::UPnPNATTraversalForwardPortRequest(NATTraversalForwardPortRequest::PortMapping mapping, PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker), mapping(mapping) {
 
 }
 
@@ -57,9 +57,9 @@ void UPnPNATTraversalForwardPortRequest::runBlocking() {
 			break;
 		}*/
 
-		int ret = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, publicPort.c_str(), localPort.c_str(), internalClient.c_str(), 0, mapping.protocol == PlatformNATTraversalForwardPortRequest::PortMapping::TCP ? "TCP" : "UDP", 0, leaseSeconds.c_str());
+		int ret = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, publicPort.c_str(), localPort.c_str(), internalClient.c_str(), 0, mapping.protocol == NATTraversalForwardPortRequest::PortMapping::TCP ? "TCP" : "UDP", 0, leaseSeconds.c_str());
 		if (ret == UPNPCOMMAND_SUCCESS) {
-			result = boost::optional<PlatformNATTraversalForwardPortRequest::PortMapping>(mapping);
+			result = boost::optional<NATTraversalForwardPortRequest::PortMapping>(mapping);
 		}
 	} while(false);
 
diff --git a/Swiften/Network/UPnPNATTraversalForwardPortRequest.h b/Swiften/Network/UPnPNATTraversalForwardPortRequest.h
index 931efee..ae63a80 100644
--- a/Swiften/Network/UPnPNATTraversalForwardPortRequest.h
+++ b/Swiften/Network/UPnPNATTraversalForwardPortRequest.h
@@ -6,22 +6,27 @@
 
 #pragma once
 
-#include <Swiften/Network/PlatformNATTraversalForwardPortRequest.h>
+#include <Swiften/Network/NATTraversalForwardPortRequest.h>
+#include <Swiften/Network/PlatformNATTraversalRequest.h>
 
 namespace Swift {
 
-class UPnPNATTraversalForwardPortRequest : public PlatformNATTraversalForwardPortRequest {
+class UPnPNATTraversalForwardPortRequest : public NATTraversalForwardPortRequest, public PlatformNATTraversalRequest {
 public:
-	UPnPNATTraversalForwardPortRequest(PlatformNATTraversalForwardPortRequest::PortMapping, PlatformNATTraversalWorker*);
+	UPnPNATTraversalForwardPortRequest(NATTraversalForwardPortRequest::PortMapping, PlatformNATTraversalWorker*);
 	virtual ~UPnPNATTraversalForwardPortRequest();
 
 	virtual void runBlocking();
 
+	virtual void run() {
+		doRun();
+	}
+
 private:
 	HostAddress getLocalClient();
 
 private:
-	PlatformNATTraversalForwardPortRequest::PortMapping mapping;
+	NATTraversalForwardPortRequest::PortMapping mapping;
 };
 
 }
diff --git a/Swiften/Network/UPnPNATTraversalGetPublicIPRequest.cpp b/Swiften/Network/UPnPNATTraversalGetPublicIPRequest.cpp
index 4a7c247..4ed2f5f 100644
--- a/Swiften/Network/UPnPNATTraversalGetPublicIPRequest.cpp
+++ b/Swiften/Network/UPnPNATTraversalGetPublicIPRequest.cpp
@@ -12,7 +12,7 @@
 
 namespace Swift {
 
-UPnPNATTraversalGetPublicIPRequest::UPnPNATTraversalGetPublicIPRequest(PlatformNATTraversalWorker* worker) : PlatformNATTraversalGetPublicIPRequest(worker) {
+UPnPNATTraversalGetPublicIPRequest::UPnPNATTraversalGetPublicIPRequest(PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker) {
 
 }
 
diff --git a/Swiften/Network/UPnPNATTraversalGetPublicIPRequest.h b/Swiften/Network/UPnPNATTraversalGetPublicIPRequest.h
index 9d50001..884f1de 100644
--- a/Swiften/Network/UPnPNATTraversalGetPublicIPRequest.h
+++ b/Swiften/Network/UPnPNATTraversalGetPublicIPRequest.h
@@ -6,16 +6,21 @@
 
 #pragma once
 
-#include <Swiften/Network/PlatformNATTraversalGetPublicIPRequest.h>
+#include <Swiften/Network/NATTraversalGetPublicIPRequest.h>
+#include <Swiften/Network/PlatformNATTraversalRequest.h>
 
 namespace Swift {
 
-class UPnPNATTraversalGetPublicIPRequest : public PlatformNATTraversalGetPublicIPRequest {
+class UPnPNATTraversalGetPublicIPRequest : public NATTraversalGetPublicIPRequest, public PlatformNATTraversalRequest {
 public:
 	UPnPNATTraversalGetPublicIPRequest(PlatformNATTraversalWorker*);
 	virtual ~UPnPNATTraversalGetPublicIPRequest();
 
 	virtual void runBlocking();
+
+	virtual void run() {
+		doRun();
+	}
 };
 
 }
diff --git a/Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.cpp b/Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.cpp
index 2026880..6e4d0eb 100644
--- a/Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.cpp
+++ b/Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.cpp
@@ -19,7 +19,7 @@
 
 namespace Swift {
 
-UPnPNATTraversalRemovePortForwardingRequest::UPnPNATTraversalRemovePortForwardingRequest(PlatformNATTraversalRemovePortForwardingRequest::PortMapping mapping, PlatformNATTraversalWorker* worker) : PlatformNATTraversalRemovePortForwardingRequest(worker), mapping(mapping) {
+UPnPNATTraversalRemovePortForwardingRequest::UPnPNATTraversalRemovePortForwardingRequest(NATTraversalRemovePortForwardingRequest::PortMapping mapping, PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker), mapping(mapping) {
 
 }
 
@@ -58,7 +58,7 @@ void UPnPNATTraversalRemovePortForwardingRequest::runBlocking() {
 			break;
 		}*/
 		SWIFT_LOG(debug) << "Start removing port forwarding..." << std::endl;
-		int ret = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, publicPort.c_str(), mapping.protocol == PlatformNATTraversalRemovePortForwardingRequest::PortMapping::TCP ? "TCP" : "UDP", 0);
+		int ret = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, publicPort.c_str(), mapping.protocol == NATTraversalRemovePortForwardingRequest::PortMapping::TCP ? "TCP" : "UDP", 0);
 
 		if (ret == UPNPCOMMAND_SUCCESS) {
 			SWIFT_LOG(debug) << "Removing port " << publicPort << " successfull." << std::endl;
diff --git a/Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.h b/Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.h
index ad1e019..af6d3b0 100644
--- a/Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.h
+++ b/Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.h
@@ -6,22 +6,27 @@
 
 #pragma once
 
-#include <Swiften/Network/PlatformNATTraversalRemovePortForwardingRequest.h>
+#include <Swiften/Network/PlatformNATTraversalRequest.h>
+#include <Swiften/Network/NATTraversalRemovePortForwardingRequest.h>
 
 namespace Swift {
 
-class UPnPNATTraversalRemovePortForwardingRequest : public PlatformNATTraversalRemovePortForwardingRequest {
+class UPnPNATTraversalRemovePortForwardingRequest : public NATTraversalRemovePortForwardingRequest, public PlatformNATTraversalRequest {
 public:
-	UPnPNATTraversalRemovePortForwardingRequest(PlatformNATTraversalRemovePortForwardingRequest::PortMapping, PlatformNATTraversalWorker*);
+	UPnPNATTraversalRemovePortForwardingRequest(NATTraversalRemovePortForwardingRequest::PortMapping, PlatformNATTraversalWorker*);
 	virtual ~UPnPNATTraversalRemovePortForwardingRequest();
 
 	virtual void runBlocking();
 
+	virtual void run() {
+		doRun();
+	}
+
 private:
 	HostAddress getLocalClient();
 
 private:
-	PlatformNATTraversalRemovePortForwardingRequest::PortMapping mapping;
+	NATTraversalRemovePortForwardingRequest::PortMapping mapping;
 };
 
 }
diff --git a/Swiften/SConscript b/Swiften/SConscript
index ca8dee5..e496fbe 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -22,9 +22,6 @@ if env["SCONS_STAGE"] == "flags" :
 	env["SWIFTEN_LIBRARY_FILE"] = "Swiften"
 	env["SWIFTEN_LIBRARY_ALIASES"] = []
 	
-	if env["PLATFORM"] == "win32" :
-		env.Append(CCFLAGS = ["-DSTATICLIB"])
-	
 	if ARGUMENTS.get("swiften_dll", False) :
 		if env["PLATFORM"] == "win32" :
 			pass
-- 
cgit v0.10.2-6-g49f6