From dfccb5703c4d85ab1a54429016b103101bdc54ae Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Wed, 28 Sep 2011 22:01:57 +0200
Subject: File Transfer refactoring.

NAT traversal classes refactoring.
Added beginnings of a NetworkTool.

diff --git a/.cproject b/.cproject
index 7971420..dc35a7d 100644
--- a/.cproject
+++ b/.cproject
@@ -3199,6 +3199,297 @@
 				</scannerConfigBuildInfo>
 			</storageModule>
 		</cconfiguration>
+		<cconfiguration id="0.980756260.1834106966.226646757.1415775202.1627288159">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="0.980756260.1834106966.226646757.1415775202.1627288159" moduleId="org.eclipse.cdt.core.settings" name="NetworkTool">
+				<externalSettings/>
+				<extensions>
+					<extension id="org.eclipse.cdt.core.MachO64" point="org.eclipse.cdt.core.BinaryParser"/>
+					<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+					<extension id="org.eclipse.cdt.core.PE" point="org.eclipse.cdt.core.BinaryParser"/>
+					<extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+					<extension id="org.eclipse.cdt.core.VCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="be.el_tramo.ecppunit.CPPUnitErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactName="${ProjName}" buildProperties="" description="" errorParsers="org.eclipse.cdt.core.VCErrorParser;org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;be.el_tramo.ecppunit.CPPUnitErrorParser" id="0.980756260.1834106966.226646757.1415775202.1627288159" name="NetworkTool" parent="org.eclipse.cdt.build.core.prefbase.cfg">
+					<folderInfo id="0.980756260.1834106966.226646757.1415775202.1627288159." name="/" resourcePath="">
+						<toolChain errorParsers="" id="org.eclipse.cdt.build.core.prefbase.toolchain.1096610170" name="No ToolChain" resourceTypeBasedDiscovery="false" superClass="org.eclipse.cdt.build.core.prefbase.toolchain">
+							<targetPlatform binaryParser="org.eclipse.cdt.core.MachO64;org.eclipse.cdt.core.ELF;org.eclipse.cdt.core.PE;org.eclipse.cdt.core.GNU_ELF" id="org.eclipse.cdt.build.core.prefbase.toolchain.1096610170.316602503" name=""/>
+							<builder arguments="${ProjDirPath}/3rdParty/SCons/scons.py" autoBuildTarget="Swiften/Examples/NetworkTool" buildPath="" cleanBuildTarget="-c" command="python" enableAutoBuild="true" errorParsers="org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.CWDLocator" id="org.eclipse.cdt.build.core.settings.default.builder.2054666555" incrementalBuildTarget="Swiften/Examples/NetworkTool" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
+							<tool errorParsers="org.eclipse.cdt.core.VCErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser" id="org.eclipse.cdt.build.core.settings.holder.libs.1235898736" name="holder for library settings" superClass="org.eclipse.cdt.build.core.settings.holder.libs"/>
+							<tool errorParsers="org.eclipse.cdt.core.VCErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser" id="org.eclipse.cdt.build.core.settings.holder.435535367" name="Assembly" superClass="org.eclipse.cdt.build.core.settings.holder">
+								<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.1960300889" languageId="org.eclipse.cdt.core.assembly" languageName="Assembly" sourceContentType="org.eclipse.cdt.core.asmSource" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
+							</tool>
+							<tool errorParsers="org.eclipse.cdt.core.VCErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser" id="org.eclipse.cdt.build.core.settings.holder.569051524" name="GNU C++" superClass="org.eclipse.cdt.build.core.settings.holder">
+								<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.1305417300" languageId="org.eclipse.cdt.core.g++" languageName="GNU C++" sourceContentType="org.eclipse.cdt.core.cxxSource,org.eclipse.cdt.core.cxxHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
+							</tool>
+							<tool errorParsers="org.eclipse.cdt.core.VCErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser" id="org.eclipse.cdt.build.core.settings.holder.1784984314" name="GNU C" superClass="org.eclipse.cdt.build.core.settings.holder">
+								<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.479612703" languageId="org.eclipse.cdt.core.gcc" languageName="GNU C" sourceContentType="org.eclipse.cdt.core.cSource,org.eclipse.cdt.core.cHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
+							</tool>
+						</toolChain>
+					</folderInfo>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+			<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+			<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+			<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
+			<storageModule moduleId="scannerConfiguration">
+				<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+				<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+					<buildOutputProvider>
+						<openAction enabled="true" filePath=""/>
+						<parser enabled="true"/>
+					</buildOutputProvider>
+					<scannerInfoProvider id="specsFile">
+						<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+						<parser enabled="true"/>
+					</scannerInfoProvider>
+				</profile>
+				<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+					<buildOutputProvider>
+						<openAction enabled="true" filePath=""/>
+						<parser enabled="true"/>
+					</buildOutputProvider>
+					<scannerInfoProvider id="makefileGenerator">
+						<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
+						<parser enabled="true"/>
+					</scannerInfoProvider>
+				</profile>
+				<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+					<buildOutputProvider>
+						<openAction enabled="true" filePath=""/>
+						<parser enabled="true"/>
+					</buildOutputProvider>
+					<scannerInfoProvider id="specsFile">
+						<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+						<parser enabled="true"/>
+					</scannerInfoProvider>
+				</profile>
+				<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+					<buildOutputProvider>
+						<openAction enabled="true" filePath=""/>
+						<parser enabled="true"/>
+					</buildOutputProvider>
+					<scannerInfoProvider id="specsFile">
+						<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+						<parser enabled="true"/>
+					</scannerInfoProvider>
+				</profile>
+				<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+					<buildOutputProvider>
+						<openAction enabled="true" filePath=""/>
+						<parser enabled="true"/>
+					</buildOutputProvider>
+					<scannerInfoProvider id="specsFile">
+						<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+						<parser enabled="true"/>
+					</scannerInfoProvider>
+				</profile>
+				<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+					<buildOutputProvider>
+						<openAction enabled="true" filePath=""/>
+						<parser enabled="true"/>
+					</buildOutputProvider>
+					<scannerInfoProvider id="specsFile">
+						<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
+						<parser enabled="true"/>
+					</scannerInfoProvider>
+				</profile>
+				<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+					<buildOutputProvider>
+						<openAction enabled="true" filePath=""/>
+						<parser enabled="true"/>
+					</buildOutputProvider>
+					<scannerInfoProvider id="specsFile">
+						<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
+						<parser enabled="true"/>
+					</scannerInfoProvider>
+				</profile>
+				<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+					<buildOutputProvider>
+						<openAction enabled="true" filePath=""/>
+						<parser enabled="true"/>
+					</buildOutputProvider>
+					<scannerInfoProvider id="specsFile">
+						<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
+						<parser enabled="true"/>
+					</scannerInfoProvider>
+				</profile>
+				<scannerConfigBuildInfo instanceId="0.980756260.1834106966.1269306596">
+					<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+					<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="makefileGenerator">
+							<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+				</scannerConfigBuildInfo>
+				<scannerConfigBuildInfo instanceId="0.980756260">
+					<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+					<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="makefileGenerator">
+							<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+				</scannerConfigBuildInfo>
+			</storageModule>
+		</cconfiguration>
 	</storageModule>
 	<storageModule moduleId="cdtBuildSystem" version="4.0.0">
 		<project id="swift.null.189117846" name="swift"/>
diff --git a/.project b/.project
index fcdfcdc..60b9ebf 100644
--- a/.project
+++ b/.project
@@ -18,7 +18,7 @@
 				</dictionary>
 				<dictionary>
 					<key>org.eclipse.cdt.make.core.autoBuildTarget</key>
-					<value></value>
+					<value>Swift</value>
 				</dictionary>
 				<dictionary>
 					<key>org.eclipse.cdt.make.core.buildArguments</key>
@@ -29,6 +29,10 @@
 					<value>python</value>
 				</dictionary>
 				<dictionary>
+					<key>org.eclipse.cdt.make.core.buildLocation</key>
+					<value></value>
+				</dictionary>
+				<dictionary>
 					<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
 					<value>-c</value>
 				</dictionary>
@@ -50,7 +54,7 @@
 				</dictionary>
 				<dictionary>
 					<key>org.eclipse.cdt.make.core.fullBuildTarget</key>
-					<value></value>
+					<value>Swift</value>
 				</dictionary>
 				<dictionary>
 					<key>org.eclipse.cdt.make.core.stopOnError</key>
diff --git a/3rdParty/Boost/src/boost/logic/tribool.hpp b/3rdParty/Boost/src/boost/logic/tribool.hpp
new file mode 100644
index 0000000..229feb4
--- /dev/null
+++ b/3rdParty/Boost/src/boost/logic/tribool.hpp
@@ -0,0 +1,460 @@
+// Three-state boolean logic library
+
+// Copyright Douglas Gregor 2002-2004. Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+// For more information, see http://www.boost.org
+#ifndef BOOST_LOGIC_TRIBOOL_HPP
+#define BOOST_LOGIC_TRIBOOL_HPP
+
+#include <boost/logic/tribool_fwd.hpp>
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+
+#if BOOST_WORKAROUND(_MSC_VER, >= 1200)
+#  pragma once
+#endif
+
+namespace boost { namespace logic {
+
+/// INTERNAL ONLY
+namespace detail {
+/**
+ * INTERNAL ONLY
+ *
+ * \brief A type used only to uniquely identify the 'indeterminate'
+ * function/keyword.
+ */
+struct indeterminate_t
+{
+#if BOOST_WORKAROUND(__BORLANDC__, < 0x0600)
+  char dummy_; // BCB would use 8 bytes by default
+#endif
+};
+
+} // end namespace detail
+
+/**
+ * INTERNAL ONLY
+ * The type of the 'indeterminate' keyword. This has the same type as the
+ * function 'indeterminate' so that we can recognize when the keyword is
+ * used.
+ */
+typedef bool (*indeterminate_keyword_t)(tribool, detail::indeterminate_t);
+
+/**
+ * \brief Keyword and test function for the indeterminate tribool value
+ *
+ * The \c indeterminate function has a dual role. It's first role is
+ * as a unary function that tells whether the tribool value is in the
+ * "indeterminate" state. It's second role is as a keyword
+ * representing the indeterminate (just like "true" and "false"
+ * represent the true and false states). If you do not like the name
+ * "indeterminate", and would prefer to use a different name, see the
+ * macro \c BOOST_TRIBOOL_THIRD_STATE.
+ *
+ * \returns <tt>x.value == tribool::indeterminate_value</tt>
+ * \throws nothrow
+ */
+inline bool
+indeterminate(tribool x,
+              detail::indeterminate_t dummy = detail::indeterminate_t());
+
+/**
+ * \brief A 3-state boolean type.
+ *
+ * 3-state boolean values are either true, false, or
+ * indeterminate.
+ */
+class tribool
+{
+private:
+  /// INTERNAL ONLY
+  struct dummy {
+    void nonnull() {};
+  };
+
+  typedef void (dummy::*safe_bool)();
+
+public:
+  /**
+   * Construct a new 3-state boolean value with the value 'false'.
+   *
+   * \throws nothrow
+   */
+  tribool() : value(false_value) {}
+
+  /**
+   * Construct a new 3-state boolean value with the given boolean
+   * value, which may be \c true or \c false.
+   *
+   * \throws nothrow
+   */
+  tribool(bool value) : value(value? true_value : false_value) {}
+
+  /**
+   * Construct a new 3-state boolean value with an indeterminate value.
+   *
+   * \throws nothrow
+   */
+  tribool(indeterminate_keyword_t) : value(indeterminate_value) {}
+
+  /**
+   * Use a 3-state boolean in a boolean context. Will evaluate true in a
+   * boolean context only when the 3-state boolean is definitely true.
+   *
+   * \returns true if the 3-state boolean is true, false otherwise
+   * \throws nothrow
+   */
+  operator safe_bool() const
+  {
+    return value == true_value? &dummy::nonnull : 0;
+  }
+
+  /**
+   * The actual stored value in this 3-state boolean, which may be false, true,
+   * or indeterminate.
+   */
+  enum value_t { false_value, true_value, indeterminate_value } value;
+};
+
+// Check if the given tribool has an indeterminate value. Also doubles as a
+// keyword for the 'indeterminate' value
+inline bool indeterminate(tribool x, detail::indeterminate_t)
+{
+  return x.value == tribool::indeterminate_value;
+}
+
+/** @defgroup logical Logical operations
+ */
+//@{
+/**
+ * \brief Computes the logical negation of a tribool
+ *
+ * \returns the logical negation of the tribool, according to the
+ * table:
+ *  <table border=1>
+ *    <tr>
+ *      <th><center><code>!</code></center></th>
+ *      <th/>
+ *    </tr>
+ *    <tr>
+ *      <th><center>false</center></th>
+ *      <td><center>true</center></td>
+ *    </tr>
+ *    <tr>
+ *      <th><center>true</center></th>
+ *      <td><center>false</center></td>
+ *    </tr>
+ *    <tr>
+ *      <th><center>indeterminate</center></th>
+ *      <td><center>indeterminate</center></td>
+ *    </tr>
+ *  </table>
+ * \throws nothrow
+ */
+inline tribool operator!(tribool x)
+{
+  return x.value == tribool::false_value? tribool(true)
+        :x.value == tribool::true_value? tribool(false)
+        :tribool(indeterminate);
+}
+
+/**
+ * \brief Computes the logical conjuction of two tribools
+ *
+ * \returns the result of logically ANDing the two tribool values,
+ * according to the following table:
+ *       <table border=1>
+ *           <tr>
+ *             <th><center><code>&amp;&amp;</code></center></th>
+ *             <th><center>false</center></th>
+ *             <th><center>true</center></th>
+ *             <th><center>indeterminate</center></th>
+ *           </tr>
+ *           <tr>
+ *             <th><center>false</center></th>
+ *             <td><center>false</center></td>
+ *             <td><center>false</center></td>
+ *             <td><center>false</center></td>
+ *           </tr>
+ *           <tr>
+ *             <th><center>true</center></th>
+ *             <td><center>false</center></td>
+ *             <td><center>true</center></td>
+ *             <td><center>indeterminate</center></td>
+ *           </tr>
+ *           <tr>
+ *             <th><center>indeterminate</center></th>
+ *             <td><center>false</center></td>
+ *             <td><center>indeterminate</center></td>
+ *             <td><center>indeterminate</center></td>
+ *           </tr>
+ *       </table>
+ * \throws nothrow
+ */
+inline tribool operator&&(tribool x, tribool y)
+{
+  if (static_cast<bool>(!x) || static_cast<bool>(!y))
+    return false;
+  else if (static_cast<bool>(x) && static_cast<bool>(y))
+    return true;
+  else
+    return indeterminate;
+}
+
+/**
+ * \overload
+ */
+inline tribool operator&&(tribool x, bool y)
+{ return y? x : tribool(false); }
+
+/**
+ * \overload
+ */
+inline tribool operator&&(bool x, tribool y)
+{ return x? y : tribool(false); }
+
+/**
+ * \overload
+ */
+inline tribool operator&&(indeterminate_keyword_t, tribool x)
+{ return !x? tribool(false) : tribool(indeterminate); }
+
+/**
+ * \overload
+ */
+inline tribool operator&&(tribool x, indeterminate_keyword_t)
+{ return !x? tribool(false) : tribool(indeterminate); }
+
+/**
+ * \brief Computes the logical disjunction of two tribools
+ *
+ * \returns the result of logically ORing the two tribool values,
+ * according to the following table:
+ *       <table border=1>
+ *           <tr>
+ *             <th><center><code>||</code></center></th>
+ *             <th><center>false</center></th>
+ *             <th><center>true</center></th>
+ *             <th><center>indeterminate</center></th>
+ *           </tr>
+ *           <tr>
+ *             <th><center>false</center></th>
+ *             <td><center>false</center></td>
+ *             <td><center>true</center></td>
+ *             <td><center>indeterminate</center></td>
+ *           </tr>
+ *           <tr>
+ *             <th><center>true</center></th>
+ *             <td><center>true</center></td>
+ *             <td><center>true</center></td>
+ *             <td><center>true</center></td>
+ *           </tr>
+ *           <tr>
+ *             <th><center>indeterminate</center></th>
+ *             <td><center>indeterminate</center></td>
+ *             <td><center>true</center></td>
+ *             <td><center>indeterminate</center></td>
+ *           </tr>
+ *       </table>
+ *  \throws nothrow
+ */
+inline tribool operator||(tribool x, tribool y)
+{
+  if (static_cast<bool>(!x) && static_cast<bool>(!y))
+    return false;
+  else if (static_cast<bool>(x) || static_cast<bool>(y))
+    return true;
+  else
+    return indeterminate;
+}
+
+/**
+ * \overload
+ */
+inline tribool operator||(tribool x, bool y)
+{ return y? tribool(true) : x; }
+
+/**
+ * \overload
+ */
+inline tribool operator||(bool x, tribool y)
+{ return x? tribool(true) : y; }
+
+/**
+ * \overload
+ */
+inline tribool operator||(indeterminate_keyword_t, tribool x)
+{ return x? tribool(true) : tribool(indeterminate); }
+
+/**
+ * \overload
+ */
+inline tribool operator||(tribool x, indeterminate_keyword_t)
+{ return x? tribool(true) : tribool(indeterminate); }
+//@}
+
+/**
+ * \brief Compare tribools for equality
+ *
+ * \returns the result of comparing two tribool values, according to
+ * the following table:
+ *       <table border=1>
+ *          <tr>
+ *            <th><center><code>==</code></center></th>
+ *            <th><center>false</center></th>
+ *            <th><center>true</center></th>
+ *            <th><center>indeterminate</center></th>
+ *          </tr>
+ *          <tr>
+ *            <th><center>false</center></th>
+ *            <td><center>true</center></td>
+ *            <td><center>false</center></td>
+ *            <td><center>indeterminate</center></td>
+ *          </tr>
+ *          <tr>
+ *            <th><center>true</center></th>
+ *            <td><center>false</center></td>
+ *            <td><center>true</center></td>
+ *            <td><center>indeterminate</center></td>
+ *          </tr>
+ *          <tr>
+ *            <th><center>indeterminate</center></th>
+ *            <td><center>indeterminate</center></td>
+ *            <td><center>indeterminate</center></td>
+ *            <td><center>indeterminate</center></td>
+ *          </tr>
+ *      </table>
+ * \throws nothrow
+ */
+inline tribool operator==(tribool x, tribool y)
+{
+  if (indeterminate(x) || indeterminate(y))
+    return indeterminate;
+  else
+    return (x && y) || (!x && !y);
+}
+
+/**
+ * \overload
+ */
+inline tribool operator==(tribool x, bool y) { return x == tribool(y); }
+
+/**
+ * \overload
+ */
+inline tribool operator==(bool x, tribool y) { return tribool(x) == y; }
+
+/**
+ * \overload
+ */
+inline tribool operator==(indeterminate_keyword_t, tribool x)
+{ return tribool(indeterminate) == x; }
+
+/**
+ * \overload
+ */
+inline tribool operator==(tribool x, indeterminate_keyword_t)
+{ return tribool(indeterminate) == x; }
+
+/**
+ * \brief Compare tribools for inequality
+ *
+ * \returns the result of comparing two tribool values for inequality,
+ * according to the following table:
+ *       <table border=1>
+ *           <tr>
+ *             <th><center><code>!=</code></center></th>
+ *             <th><center>false</center></th>
+ *             <th><center>true</center></th>
+ *             <th><center>indeterminate</center></th>
+ *           </tr>
+ *           <tr>
+ *             <th><center>false</center></th>
+ *             <td><center>false</center></td>
+ *             <td><center>true</center></td>
+ *             <td><center>indeterminate</center></td>
+ *           </tr>
+ *           <tr>
+ *             <th><center>true</center></th>
+ *             <td><center>true</center></td>
+ *             <td><center>false</center></td>
+ *             <td><center>indeterminate</center></td>
+ *           </tr>
+ *           <tr>
+ *             <th><center>indeterminate</center></th>
+ *             <td><center>indeterminate</center></td>
+ *             <td><center>indeterminate</center></td>
+ *             <td><center>indeterminate</center></td>
+ *           </tr>
+ *       </table>
+ * \throws nothrow
+ */
+inline tribool operator!=(tribool x, tribool y)
+{
+  if (indeterminate(x) || indeterminate(y))
+    return indeterminate;
+  else
+    return !((x && y) || (!x && !y));
+}
+
+/**
+ * \overload
+ */
+inline tribool operator!=(tribool x, bool y) { return x != tribool(y); }
+
+/**
+ * \overload
+ */
+inline tribool operator!=(bool x, tribool y) { return tribool(x) != y; }
+
+/**
+ * \overload
+ */
+inline tribool operator!=(indeterminate_keyword_t, tribool x)
+{ return tribool(indeterminate) != x; }
+
+/**
+ * \overload
+ */
+inline tribool operator!=(tribool x, indeterminate_keyword_t)
+{ return x != tribool(indeterminate); }
+
+} } // end namespace boost::logic
+
+// Pull tribool and indeterminate into namespace "boost"
+namespace boost {
+  using logic::tribool;
+  using logic::indeterminate;
+}
+
+/**
+ * \brief Declare a new name for the third state of a tribool
+ *
+ * Use this macro to declare a new name for the third state of a
+ * tribool. This state can have any number of new names (in addition
+ * to \c indeterminate), all of which will be equivalent. The new name will be
+ * placed in the namespace in which the macro is expanded.
+ *
+ * Example:
+ *   BOOST_TRIBOOL_THIRD_STATE(true_or_false)
+ *
+ *   tribool x(true_or_false);
+ *   // potentially set x
+ *   if (true_or_false(x)) {
+ *     // don't know what x is
+ *   }
+ */
+#define BOOST_TRIBOOL_THIRD_STATE(Name)                                 \
+inline bool                                                             \
+Name(boost::logic::tribool x,                                           \
+     boost::logic::detail::indeterminate_t dummy =                      \
+       boost::logic::detail::indeterminate_t())                         \
+{ return x.value == boost::logic::tribool::indeterminate_value; }
+
+#endif // BOOST_LOGIC_TRIBOOL_HPP
+
diff --git a/3rdParty/Boost/src/boost/logic/tribool_fwd.hpp b/3rdParty/Boost/src/boost/logic/tribool_fwd.hpp
new file mode 100644
index 0000000..2cdd91b
--- /dev/null
+++ b/3rdParty/Boost/src/boost/logic/tribool_fwd.hpp
@@ -0,0 +1,15 @@
+// Three-state boolean logic library
+
+// Copyright Douglas Gregor 2002-2004. Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+// For more information, see http://www.boost.org
+#ifndef BOOST_LOGIC_TRIBOOL_FWD_HPP
+#define BOOST_LOGIC_TRIBOOL_FWD_HPP
+
+namespace boost { namespace logic { class tribool; } }
+
+#endif // BOOST_LOGIC_TRIBOOL_FWD_HPP
diff --git a/3rdParty/Boost/update.sh b/3rdParty/Boost/update.sh
index c272d1a..a7c0638 100755
--- a/3rdParty/Boost/update.sh
+++ b/3rdParty/Boost/update.sh
@@ -32,9 +32,10 @@ fi
 	uuid/uuid_generators.hpp \
 	variant.hpp \
 	regex.hpp \
-	boost/unordered_map.hpp \
-	boost/algorithm/string.hpp \
-	boost/format.hpp \
+	unordered_map.hpp \
+	algorithm/string.hpp \
+	format.hpp \
+	logic/tribool.hpp \
 	assign/list_of.hpp \
 	$TARGET_DIR
 
diff --git a/Swiften/Examples/NetworkTool/.gitignore b/Swiften/Examples/NetworkTool/.gitignore
new file mode 100644
index 0000000..ab9c4e7
--- /dev/null
+++ b/Swiften/Examples/NetworkTool/.gitignore
@@ -0,0 +1 @@
+NetworkTool
diff --git a/Swiften/Examples/NetworkTool/SConscript b/Swiften/Examples/NetworkTool/SConscript
new file mode 100644
index 0000000..0b27f0d
--- /dev/null
+++ b/Swiften/Examples/NetworkTool/SConscript
@@ -0,0 +1,9 @@
+Import("env")
+
+myenv = env.Clone()
+myenv.MergeFlags(myenv["SWIFTEN_FLAGS"])
+myenv.MergeFlags(myenv["SWIFTEN_DEP_FLAGS"])
+
+linkLocalTool = myenv.Program("NetworkTool", [
+		"main.cpp"
+	])
diff --git a/Swiften/Examples/NetworkTool/main.cpp b/Swiften/Examples/NetworkTool/main.cpp
new file mode 100644
index 0000000..fa19e14
--- /dev/null
+++ b/Swiften/Examples/NetworkTool/main.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <iostream>
+#include <boost/lexical_cast.hpp>
+
+#include <Swiften/EventLoop/SimpleEventLoop.h>
+#include <Swiften/Network/PlatformNATTraversalWorker.h>
+#include <Swiften/Network/NATTraversalGetPublicIPRequest.h>
+#include <Swiften/Network/NATTraversalForwardPortRequest.h>
+#include <Swiften/Network/NATTraversalRemovePortForwardingRequest.h>
+
+using namespace Swift;
+
+SimpleEventLoop eventLoop;
+
+void handleGetPublicIPRequestResponse(const boost::optional<HostAddress>& result) {
+	if (result) {
+		std::cerr << "Result: " << result->toString() << std::endl;;
+	}
+	else {
+		std::cerr << "No result" << std::endl;
+	}
+	eventLoop.stop();
+}
+
+void handleGetForwardPortRequestResponse(const boost::optional<NATPortMapping>& result) {
+	if (result) {
+		std::cerr << "Result: " << result->publicPort << " -> " << result->localPort << std::endl;;
+	}
+	else {
+		std::cerr << "No result" << std::endl;
+	}
+	eventLoop.stop();
+}
+
+void handleRemovePortForwardingRequestResponse(bool result) {
+	if (result) {
+		std::cerr << "Result: OK" << std::endl;
+	}
+	else {
+		std::cerr << "Result: ERROR" << std::endl;
+	}
+	eventLoop.stop();
+}
+
+int main(int argc, char* argv[]) {
+	if (argc < 2) {
+		std::cerr << "Invalid parameters" << std::endl;
+		return -1;
+	}
+
+	PlatformNATTraversalWorker natTraverser(&eventLoop);
+	if (std::string(argv[1]) == "get-public-ip") {
+		boost::shared_ptr<NATTraversalGetPublicIPRequest> query = natTraverser.createGetPublicIPRequest();
+		query->onResult.connect(boost::bind(&handleGetPublicIPRequestResponse, _1));
+		query->run();
+		eventLoop.run();
+	}
+	else if (std::string(argv[1]) == "add-port-forward") {
+		if (argc < 4) {
+			std::cerr << "Invalid parameters" << std::endl;
+		}
+		boost::shared_ptr<NATTraversalForwardPortRequest> query = natTraverser.createForwardPortRequest(boost::lexical_cast<int>(argv[2]), boost::lexical_cast<int>(argv[3]));
+		query->onResult.connect(boost::bind(&handleGetForwardPortRequestResponse, _1));
+		query->run();
+		eventLoop.run();
+	}
+	else if (std::string(argv[1]) == "remove-port-forward") {
+		if (argc < 4) {
+			std::cerr << "Invalid parameters" << std::endl;
+		}
+		boost::shared_ptr<NATTraversalRemovePortForwardingRequest> query = natTraverser.createRemovePortForwardingRequest(boost::lexical_cast<int>(argv[2]), boost::lexical_cast<int>(argv[3]));
+		query->onResult.connect(boost::bind(&handleRemovePortForwardingRequestResponse, _1));
+		query->run();
+		eventLoop.run();
+	}
+}
diff --git a/Swiften/Examples/SConscript b/Swiften/Examples/SConscript
index 9b9a35a..fb568fc 100644
--- a/Swiften/Examples/SConscript
+++ b/Swiften/Examples/SConscript
@@ -7,6 +7,7 @@ SConscript(dirs = [
 	"SendFile",
 	"ConnectivityTest",
 	"LinkLocalTool",
+	"NetworkTool",
 	"ParserTester",
 	"BenchTool",
 ])
diff --git a/Swiften/FileTransfer/ConnectivityManager.cpp b/Swiften/FileTransfer/ConnectivityManager.cpp
index 1002b45..7d25991 100644
--- a/Swiften/FileTransfer/ConnectivityManager.cpp
+++ b/Swiften/FileTransfer/ConnectivityManager.cpp
@@ -92,7 +92,7 @@ void ConnectivityManager::natTraversalGetPublicIPResult(boost::optional<HostAddr
 	}
 }
 
-void ConnectivityManager::natTraversalForwardPortResult(boost::optional<NATTraversalForwardPortRequest::PortMapping> mapping) {
+void ConnectivityManager::natTraversalForwardPortResult(boost::optional<NATPortMapping> 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 41e0ab6..c094c02 100644
--- a/Swiften/FileTransfer/ConnectivityManager.h
+++ b/Swiften/FileTransfer/ConnectivityManager.h
@@ -14,6 +14,7 @@
 #include <Swiften/Network/HostAddressPort.h>
 #include <Swiften/Network/NATTraverser.h>
 #include <Swiften/Network/NATTraversalForwardPortRequest.h>
+#include <Swiften/Network/NATPortMapping.h>
 
 namespace Swift {
 
@@ -32,7 +33,7 @@ public:
 
 private:
 	void natTraversalGetPublicIPResult(boost::optional<HostAddress> address);
-	void natTraversalForwardPortResult(boost::optional<NATTraversalForwardPortRequest::PortMapping> mapping);
+	void natTraversalForwardPortResult(boost::optional<NATPortMapping> mapping);
 
 private:
 	NATTraverser* natTraversalWorker;
diff --git a/Swiften/Network/MiniUPnPInterface.cpp b/Swiften/Network/MiniUPnPInterface.cpp
new file mode 100644
index 0000000..f6e3b5d
--- /dev/null
+++ b/Swiften/Network/MiniUPnPInterface.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <Swiften/Network/MiniUPnPInterface.h>
+
+#include <upnpcommands.h>
+#include <upnperrors.h>
+#include <boost/lexical_cast.hpp>
+
+#include <Swiften/Base/Log.h>
+
+namespace Swift {
+
+MiniUPnPInterface::MiniUPnPInterface() : isValid(false) {
+	int error = 0;
+	deviceList = upnpDiscover(1500 /* timeout in ms */, 0, 0, 0, 0 /* do IPv6? */, &error);
+	if (!deviceList) {
+		return;
+	}
+
+	char lanAddress[64];
+	if (!UPNP_GetValidIGD(deviceList, &urls, &data, lanAddress, sizeof(lanAddress))) {
+		return;
+	}
+	localAddress = std::string(lanAddress);
+	isValid = true;
+}
+
+MiniUPnPInterface::~MiniUPnPInterface() {
+	if (isValid) {
+		FreeUPNPUrls(&urls);
+	}
+	freeUPNPDevlist(deviceList);
+}
+
+boost::optional<HostAddress> MiniUPnPInterface::getPublicIP() {
+	if (!isValid) {
+		return boost::optional<HostAddress>();
+	}
+	char externalIPAddress[40];
+	int ret = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
+	if (ret != UPNPCOMMAND_SUCCESS) {
+		return boost::optional<HostAddress>();
+	}
+	else {
+		return HostAddress(std::string(externalIPAddress));
+	}
+}
+
+boost::optional<NATPortMapping> MiniUPnPInterface::addPortForward(int actualLocalPort, int actualPublicPort) {
+	if (!isValid) {
+		return boost::optional<NATPortMapping>();
+	}
+
+	NATPortMapping mapping(actualLocalPort, actualPublicPort, NATPortMapping::TCP);
+
+	std::string publicPort = boost::lexical_cast<std::string>(mapping.publicPort);
+	std::string localPort = boost::lexical_cast<std::string>(mapping.localPort);
+	std::string leaseSeconds = boost::lexical_cast<std::string>(mapping.leaseInSeconds);
+
+	int ret = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, publicPort.c_str(), localPort.c_str(), localAddress.c_str(), 0, mapping.protocol == NATPortMapping::TCP ? "TCP" : "UDP", 0, leaseSeconds.c_str());
+	if (ret == UPNPCOMMAND_SUCCESS) {
+		return mapping;
+	}
+	else {
+		return boost::optional<NATPortMapping>();
+	}
+}
+
+bool MiniUPnPInterface::removePortForward(const NATPortMapping& mapping) {
+	if (!isValid) {
+		return false;
+	}
+
+	std::string publicPort = boost::lexical_cast<std::string>(mapping.publicPort);
+	std::string localPort = boost::lexical_cast<std::string>(mapping.localPort);
+	std::string leaseSeconds = boost::lexical_cast<std::string>(mapping.leaseInSeconds);
+
+	int ret = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, publicPort.c_str(), mapping.protocol == NATPortMapping::TCP ? "TCP" : "UDP", 0);
+	return ret == UPNPCOMMAND_SUCCESS;
+}
+
+}
diff --git a/Swiften/Network/MiniUPnPInterface.h b/Swiften/Network/MiniUPnPInterface.h
new file mode 100644
index 0000000..ae9be66
--- /dev/null
+++ b/Swiften/Network/MiniUPnPInterface.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/optional.hpp>
+#include <miniupnpc.h>
+
+#include <Swiften/Network/NATPortMapping.h>
+#include <Swiften/Network/NATTraversalInterface.h>
+
+namespace Swift {
+	class MiniUPnPInterface : public NATTraversalInterface {
+		public:
+			MiniUPnPInterface();
+			~MiniUPnPInterface();
+
+			virtual bool isAvailable() {
+				return isValid;
+			}
+
+			boost::optional<HostAddress> getPublicIP();
+			boost::optional<NATPortMapping> addPortForward(int localPort, int publicPort);
+			bool removePortForward(const NATPortMapping&);
+
+		private:
+			bool isValid;
+			std::string localAddress;
+			UPNPDev* deviceList;
+			UPNPUrls urls;
+			IGDdatas data;
+	};
+}
diff --git a/Swiften/Network/NATPMPInterface.cpp b/Swiften/Network/NATPMPInterface.cpp
new file mode 100644
index 0000000..74f582c
--- /dev/null
+++ b/Swiften/Network/NATPMPInterface.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <Swiften/Network/NATPMPInterface.h>
+
+#include <Swiften/Base/Log.h>
+
+
+namespace Swift {
+
+NATPMPInterface::NATPMPInterface() {
+	initnatpmp(&natpmp, 0, 0);
+}
+
+NATPMPInterface::~NATPMPInterface() {
+	closenatpmp(&natpmp);
+}
+
+bool NATPMPInterface::isAvailable() {
+	return getPublicIP();
+}
+
+boost::optional<HostAddress> NATPMPInterface::getPublicIP() {
+	if (sendpublicaddressrequest(&natpmp) < 0) {
+		SWIFT_LOG(debug) << "Failed to send NAT-PMP public address request!" << std::endl;
+		return boost::optional<HostAddress>();
+	}
+
+	int r = 0;
+	natpmpresp_t response;
+	do {
+	  fd_set fds;
+	  struct timeval timeout;
+	  FD_ZERO(&fds);
+	  FD_SET(natpmp.s, &fds);
+	  getnatpmprequesttimeout(&natpmp, &timeout);
+	  select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
+	  r = readnatpmpresponseorretry(&natpmp, &response);
+	} while (r == NATPMP_TRYAGAIN);
+
+	if (r == 0) {
+		return boost::optional<HostAddress>(HostAddress(reinterpret_cast<const unsigned char*>(&(response.pnu.publicaddress.addr)), 4));
+	}
+	else {
+		SWIFT_LOG(debug) << "Inavlid NAT-PMP response." << std::endl;
+		return boost::optional<HostAddress>();
+	}
+}
+
+boost::optional<NATPortMapping> NATPMPInterface::addPortForward(int localPort, int publicPort) {
+	NATPortMapping mapping(localPort, publicPort, NATPortMapping::TCP);
+	if (sendnewportmappingrequest(&natpmp, mapping.protocol == NATPortMapping::TCP ? NATPMP_PROTOCOL_TCP : NATPMP_PROTOCOL_UDP, mapping.leaseInSeconds, mapping.publicPort, mapping.localPort) < 0) {
+			SWIFT_LOG(debug) << "Failed to send NAT-PMP port forwarding request!" << std::endl;
+			return boost::optional<NATPortMapping>();
+	}
+
+	int r = 0;
+	natpmpresp_t response;
+	do {
+		fd_set fds;
+		struct timeval timeout;
+		FD_ZERO(&fds);
+		FD_SET(natpmp.s, &fds);
+		getnatpmprequesttimeout(&natpmp, &timeout);
+		select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
+		r = readnatpmpresponseorretry(&natpmp, &response);
+	} while(r == NATPMP_TRYAGAIN);
+
+	if (r == 0) {
+		mapping.localPort = response.pnu.newportmapping.privateport;
+		mapping.publicPort = response.pnu.newportmapping.mappedpublicport;
+		mapping.leaseInSeconds = response.pnu.newportmapping.lifetime;
+		return mapping;
+	}
+	else {
+		SWIFT_LOG(debug) << "Invalid NAT-PMP response." << std::endl;
+		return boost::optional<NATPortMapping>();
+	}
+}
+
+bool NATPMPInterface::removePortForward(const NATPortMapping& mapping) {
+	if (sendnewportmappingrequest(&natpmp, mapping.protocol == NATPortMapping::TCP ? NATPMP_PROTOCOL_TCP : NATPMP_PROTOCOL_UDP, 0, 0, mapping.localPort) < 0) {
+		SWIFT_LOG(debug) << "Failed to send NAT-PMP remove forwarding request!" << std::endl;
+		return false;
+	}
+
+	int r = 0;
+	natpmpresp_t response;
+	do {
+	  fd_set fds;
+	  struct timeval timeout;
+	  FD_ZERO(&fds);
+	  FD_SET(natpmp.s, &fds);
+	  getnatpmprequesttimeout(&natpmp, &timeout);
+	  select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
+	  r = readnatpmpresponseorretry(&natpmp, &response);
+	} while(r == NATPMP_TRYAGAIN);
+
+	if (r == 0) {
+		return true;
+	}
+	else {
+		SWIFT_LOG(debug) << "Invalid NAT-PMP response." << std::endl;
+		return false;
+	}
+}
+
+
+}
diff --git a/Swiften/Network/NATPMPInterface.h b/Swiften/Network/NATPMPInterface.h
new file mode 100644
index 0000000..55f5b87
--- /dev/null
+++ b/Swiften/Network/NATPMPInterface.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/optional.hpp>
+#include <natpmp.h>
+
+#include <Swiften/Network/NATPortMapping.h>
+#include <Swiften/Network/NATTraversalInterface.h>
+
+namespace Swift {
+	class NATPMPInterface : public NATTraversalInterface {
+		public:
+			NATPMPInterface();
+			~NATPMPInterface();
+
+			virtual bool isAvailable();
+
+			virtual boost::optional<HostAddress> getPublicIP();
+			virtual boost::optional<NATPortMapping> addPortForward(int localPort, int publicPort);
+			virtual bool removePortForward(const NATPortMapping&);
+
+		private:
+			natpmp_t natpmp;
+	};
+}
diff --git a/Swiften/Network/NATPMPNATTraversalForwardPortRequest.cpp b/Swiften/Network/NATPMPNATTraversalForwardPortRequest.cpp
deleted file mode 100644
index d7ef88a..0000000
--- a/Swiften/Network/NATPMPNATTraversalForwardPortRequest.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2011 Tobias Markmann
- * Licensed under the simplified BSD license.
- * See Documentation/Licenses/BSD-simplified.txt for more information.
- */
-
-#include "NATPMPNATTraversalForwardPortRequest.h"
-
-#include <natpmp.h>
-
-#include <Swiften/Base/Log.h>
-
-#pragma GCC diagnostic ignored "-Wold-style-cast"
-
-namespace Swift {
-
-NATPMPNATTraversalForwardPortRequest::NATPMPNATTraversalForwardPortRequest(NATTraversalForwardPortRequest::PortMapping mapping, PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker), mapping(mapping) {
-
-}
-
-NATPMPNATTraversalForwardPortRequest::~NATPMPNATTraversalForwardPortRequest() {
-
-}
-
-void NATPMPNATTraversalForwardPortRequest::runBlocking() {
-	boost::optional<PortMapping> result;
-
-	natpmp_t natpmp;
-	natpmpresp_t response;
-	initnatpmp(&natpmp, 0, 0);
-
-	do {
-		if (sendnewportmappingrequest(&natpmp, mapping.protocol == PortMapping::TCP ? NATPMP_PROTOCOL_TCP : NATPMP_PROTOCOL_UDP, mapping.leaseInSeconds, mapping.publicPort, mapping.localPort) != 2) {
-			SWIFT_LOG(debug) << "Failed to send NAT-PMP port forwarding request!" << std::endl;
-			break;
-		}
-		int r = 0;
-
-		do {
-		  fd_set fds;
-		  struct timeval timeout;
-		  FD_ZERO(&fds);
-		  FD_SET(natpmp.s, &fds);
-		  getnatpmprequesttimeout(&natpmp, &timeout);
-		  select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
-		  r = readnatpmpresponseorretry(&natpmp, &response);
-		} while(r == NATPMP_TRYAGAIN);
-
-		if (r == 0) {
-			if (response.pnu.newportmapping.privateport == mapping.localPort &&
-				response.pnu.newportmapping.mappedpublicport == mapping.publicPort) {
-				mapping.leaseInSeconds = response.pnu.newportmapping.lifetime;
-				result = boost::optional<PortMapping>(mapping);
-			}
-		} else {
-			SWIFT_LOG(debug) << "Inavlid NAT-PMP response." << std::endl;
-		}
-	} while(false);
-	closenatpmp(&natpmp);
-
-	onResult(result);
-}
-
-}
diff --git a/Swiften/Network/NATPMPNATTraversalForwardPortRequest.h b/Swiften/Network/NATPMPNATTraversalForwardPortRequest.h
deleted file mode 100644
index 99a5d04..0000000
--- a/Swiften/Network/NATPMPNATTraversalForwardPortRequest.h
+++ /dev/null
@@ -1,29 +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/Network/NATTraversalForwardPortRequest.h>
-#include <Swiften/Network/PlatformNATTraversalRequest.h>
-
-namespace Swift {
-
-class NATPMPNATTraversalForwardPortRequest : public NATTraversalForwardPortRequest, public PlatformNATTraversalRequest {
-public:
-	NATPMPNATTraversalForwardPortRequest(NATTraversalForwardPortRequest::PortMapping, PlatformNATTraversalWorker*);
-	virtual ~NATPMPNATTraversalForwardPortRequest();
-
-	virtual void runBlocking();
-
-	virtual void run() {
-		doRun();
-	}
-
-private:
-	NATTraversalForwardPortRequest::PortMapping mapping;
-};
-
-}
diff --git a/Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.cpp b/Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.cpp
deleted file mode 100644
index 0f6067d..0000000
--- a/Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2011 Tobias Markmann
- * Licensed under the simplified BSD license.
- * See Documentation/Licenses/BSD-simplified.txt for more information.
- */
-
-#include "NATPMPNATTraversalGetPublicIPRequest.h"
-
-#include <natpmp.h>
-
-#include <Swiften/Base/Log.h>
-
-#pragma GCC diagnostic ignored "-Wold-style-cast"
-
-namespace Swift {
-
-NATPMPNATTraversalGetPublicIPRequest::NATPMPNATTraversalGetPublicIPRequest(PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker) {
-
-}
-
-NATPMPNATTraversalGetPublicIPRequest::~NATPMPNATTraversalGetPublicIPRequest() {
-
-}
-
-/*
-TODO: a non-blocking solution should be possible too here
-void NATPMPNATTraversalGetPublicIPRequest::run() {
-	// we can run directly since libnatpmp's API is asynchronous
-	runBlocking();
-}*/
-
-void NATPMPNATTraversalGetPublicIPRequest::runBlocking() {
-	boost::optional<HostAddress> result;
-
-	natpmp_t natpmp;
-	natpmpresp_t response;
-	initnatpmp(&natpmp, 0, 0);
-
-	do {
-		if (sendpublicaddressrequest(&natpmp) != 2) {
-			SWIFT_LOG(debug) << "Failed to send NAT-PMP public address request!" << std::endl;
-			break;
-		}
-		int r = 0;
-
-		do {
-		  fd_set fds;
-		  struct timeval timeout;
-		  FD_ZERO(&fds);
-		  FD_SET(natpmp.s, &fds);
-		  getnatpmprequesttimeout(&natpmp, &timeout);
-		  select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
-		  r = readnatpmpresponseorretry(&natpmp, &response);
-		} while(r == NATPMP_TRYAGAIN);
-
-		if (r == 0) {
-			result = boost::optional<HostAddress>(HostAddress(reinterpret_cast<const unsigned char*>(&(response.pnu.publicaddress.addr)), 4));
-		} else {
-			SWIFT_LOG(debug) << "Inavlid NAT-PMP response." << std::endl;
-		}
-	} while(false);
-	closenatpmp(&natpmp);
-	onResult(result);
-}
-
-}
diff --git a/Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.h b/Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.h
deleted file mode 100644
index dba447c..0000000
--- a/Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.h
+++ /dev/null
@@ -1,26 +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/Network/PlatformNATTraversalRequest.h>
-#include <Swiften/Network/NATTraversalGetPublicIPRequest.h>
-
-namespace Swift {
-
-class NATPMPNATTraversalGetPublicIPRequest : public NATTraversalGetPublicIPRequest, public PlatformNATTraversalRequest {
-public:
-	NATPMPNATTraversalGetPublicIPRequest(PlatformNATTraversalWorker*);
-	virtual ~NATPMPNATTraversalGetPublicIPRequest();
-
-	virtual void runBlocking();
-
-	virtual void run() {
-		doRun();
-	}
-};
-
-}
diff --git a/Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.cpp b/Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.cpp
deleted file mode 100644
index 8ba20a6..0000000
--- a/Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2011 Tobias Markmann
- * Licensed under the simplified BSD license.
- * See Documentation/Licenses/BSD-simplified.txt for more information.
- */
-
-#include "NATPMPNATTraversalRemovePortForwardingRequest.h"
-
-#include <boost/format.hpp>
-
-#include <natpmp.h>
-
-#include <Swiften/Base/foreach.h>
-#include <Swiften/Base/Log.h>
-#include <Swiften/Network/NetworkInterface.h>
-#include <Swiften/Network/PlatformNetworkEnvironment.h>
-
-#pragma GCC diagnostic ignored "-Wold-style-cast"
-
-namespace Swift {
-
-NATPMPNATTraversalRemovePortForwardingRequest::NATPMPNATTraversalRemovePortForwardingRequest(PortMapping mapping, PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker), mapping(mapping) {
-
-}
-
-NATPMPNATTraversalRemovePortForwardingRequest::~NATPMPNATTraversalRemovePortForwardingRequest() {
-
-}
-
-void NATPMPNATTraversalRemovePortForwardingRequest::runBlocking() {
-	boost::optional<bool> result;
-
-	natpmp_t natpmp;
-	natpmpresp_t response;
-	initnatpmp(&natpmp, 0, 0);
-
-	do {
-		if (sendnewportmappingrequest(&natpmp, mapping.protocol == PortMapping::TCP ? NATPMP_PROTOCOL_TCP : NATPMP_PROTOCOL_UDP, 0, 0, mapping.localPort) != 2) {
-			SWIFT_LOG(debug) << "Failed to send NAT-PMP remove forwarding request!" << std::endl;
-			break;
-		}
-		int r = 0;
-
-		do {
-		  fd_set fds;
-		  struct timeval timeout;
-		  FD_ZERO(&fds);
-		  FD_SET(natpmp.s, &fds);
-		  getnatpmprequesttimeout(&natpmp, &timeout);
-		  select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
-		  r = readnatpmpresponseorretry(&natpmp, &response);
-		} while(r == NATPMP_TRYAGAIN);
-
-		if (r == 0) {
-			if (response.pnu.newportmapping.privateport == mapping.localPort &&
-				response.pnu.newportmapping.mappedpublicport == mapping.publicPort) {
-				mapping.leaseInSeconds = response.pnu.newportmapping.lifetime;
-				result = boost::optional<bool>(true);
-			}
-		} else {
-			result = boost::optional<bool>(false);
-			SWIFT_LOG(debug) << "Inavlid NAT-PMP response." << std::endl;
-		}
-	} while(false);
-	closenatpmp(&natpmp);
-
-	onResult(result);
-}
-
-}
diff --git a/Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.h b/Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.h
deleted file mode 100644
index aefbdc0..0000000
--- a/Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.h
+++ /dev/null
@@ -1,29 +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/Network/NATTraversalRemovePortForwardingRequest.h>
-#include <Swiften/Network/PlatformNATTraversalRequest.h>
-
-namespace Swift {
-
-class NATPMPNATTraversalRemovePortForwardingRequest : public NATTraversalRemovePortForwardingRequest, public PlatformNATTraversalRequest {
-public:
-	NATPMPNATTraversalRemovePortForwardingRequest(PortMapping, PlatformNATTraversalWorker*);
-	virtual ~NATPMPNATTraversalRemovePortForwardingRequest();
-
-	virtual void runBlocking();
-
-	virtual void run() {
-		doRun();
-	}
-
-private:
-	PortMapping mapping;
-};
-
-}
diff --git a/Swiften/Network/NATPortMapping.h b/Swiften/Network/NATPortMapping.h
new file mode 100644
index 0000000..82f62bb
--- /dev/null
+++ b/Swiften/Network/NATPortMapping.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Network/HostAddress.h>
+
+namespace Swift {
+	struct NATPortMapping {
+		enum Protocol {
+			TCP,
+			UDP,
+		};
+
+		NATPortMapping(int localPort, int publicPort, Protocol protocol = TCP, int leaseInSeconds = 60 * 60 * 24) : publicPort(publicPort), localPort(localPort), protocol(protocol), leaseInSeconds(leaseInSeconds) {
+
+		}
+
+		int publicPort;
+		int localPort;
+		Protocol protocol;
+		int leaseInSeconds;
+	};
+}
diff --git a/Swiften/Network/NATTraversalForwardPortRequest.h b/Swiften/Network/NATTraversalForwardPortRequest.h
index 8cdbd3d..1bbc9ca 100644
--- a/Swiften/Network/NATTraversalForwardPortRequest.h
+++ b/Swiften/Network/NATTraversalForwardPortRequest.h
@@ -7,28 +7,16 @@
 #pragma once
 
 #include <Swiften/Base/boost_bsignals.h>
-#include <Swiften/Network/HostAddress.h>
+
+#include <Swiften/Network/NATPortMapping.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;
+			boost::signal<void (boost::optional<NATPortMapping>)> onResult;
 	};
 }
diff --git a/Swiften/Network/NATTraversalInterface.cpp b/Swiften/Network/NATTraversalInterface.cpp
new file mode 100644
index 0000000..f8a0cc2
--- /dev/null
+++ b/Swiften/Network/NATTraversalInterface.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <Swiften/Network/NATTraversalInterface.h>
+
+#include <Swiften/Base/Log.h>
+
+
+namespace Swift {
+
+NATTraversalInterface::~NATTraversalInterface() {
+}
+
+}
diff --git a/Swiften/Network/NATTraversalInterface.h b/Swiften/Network/NATTraversalInterface.h
new file mode 100644
index 0000000..428db10
--- /dev/null
+++ b/Swiften/Network/NATTraversalInterface.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/optional.hpp>
+#include <natpmp.h>
+
+#include <Swiften/Network/NATPortMapping.h>
+
+namespace Swift {
+	class NATTraversalInterface {
+		public:
+			virtual ~NATTraversalInterface();
+
+			virtual bool isAvailable() = 0;
+
+			virtual boost::optional<HostAddress> getPublicIP() = 0;
+			virtual boost::optional<NATPortMapping> addPortForward(int localPort, int publicPort) = 0;
+			virtual bool removePortForward(const NATPortMapping&) = 0;
+	};
+}
diff --git a/Swiften/Network/NATTraverser.h b/Swiften/Network/NATTraverser.h
index 4afd624..e48ce26 100644
--- a/Swiften/Network/NATTraverser.h
+++ b/Swiften/Network/NATTraverser.h
@@ -18,7 +18,7 @@ namespace Swift {
 			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;
+			virtual boost::shared_ptr<NATTraversalForwardPortRequest> createForwardPortRequest(int localPort, int publicPort) = 0;
+			virtual boost::shared_ptr<NATTraversalRemovePortForwardingRequest> createRemovePortForwardingRequest(int localPort, int publicPort) = 0;
 	};
 }
diff --git a/Swiften/Network/NullNATTraversalInterface.h b/Swiften/Network/NullNATTraversalInterface.h
new file mode 100644
index 0000000..c76634f
--- /dev/null
+++ b/Swiften/Network/NullNATTraversalInterface.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/optional.hpp>
+#include <natpmp.h>
+
+#include <Swiften/Network/NATTraversalInterface.h>
+
+namespace Swift {
+	class NullNATTraversalInterface : public NATTraversalInterface {
+		public:
+			virtual bool isAvailable() {
+				return true;
+			}
+
+			virtual boost::optional<HostAddress> getPublicIP() {
+				return boost::optional<HostAddress>();
+			}
+
+			virtual boost::optional<NATPortMapping> addPortForward(int, int) {
+				return boost::optional<NATPortMapping>();
+			}
+
+			virtual bool removePortForward(const NATPortMapping&) {
+				return false;
+			}
+	};
+}
diff --git a/Swiften/Network/NullNATTraverser.cpp b/Swiften/Network/NullNATTraverser.cpp
index 018ef91..8cb35cd 100644
--- a/Swiften/Network/NullNATTraverser.cpp
+++ b/Swiften/Network/NullNATTraverser.cpp
@@ -35,7 +35,7 @@ class NullNATTraversalForwardPortRequest : public NATTraversalForwardPortRequest
 		}
 
 		virtual void run() {
-			eventLoop->postEvent(boost::bind(boost::ref(onResult), boost::optional<PortMapping>()));
+			eventLoop->postEvent(boost::bind(boost::ref(onResult), boost::optional<NATPortMapping>()));
 		}
 
 	private:
@@ -62,11 +62,11 @@ boost::shared_ptr<NATTraversalGetPublicIPRequest> NullNATTraverser::createGetPub
 	return boost::make_shared<NullNATTraversalGetPublicIPRequest>(eventLoop);
 }
 
-boost::shared_ptr<NATTraversalForwardPortRequest> NullNATTraverser::createForwardPortRequest(unsigned int, unsigned int) {
+boost::shared_ptr<NATTraversalForwardPortRequest> NullNATTraverser::createForwardPortRequest(int, int) {
 	return boost::make_shared<NullNATTraversalForwardPortRequest>(eventLoop);
 }
 
-boost::shared_ptr<NATTraversalRemovePortForwardingRequest> NullNATTraverser::createRemovePortForwardingRequest(unsigned int, unsigned int) {
+boost::shared_ptr<NATTraversalRemovePortForwardingRequest> NullNATTraverser::createRemovePortForwardingRequest(int, int) {
 	return boost::make_shared<NullNATTraversalRemovePortForwardingRequest>(eventLoop);
 }
 
diff --git a/Swiften/Network/NullNATTraverser.h b/Swiften/Network/NullNATTraverser.h
index 1b66a7d..5775a9b 100644
--- a/Swiften/Network/NullNATTraverser.h
+++ b/Swiften/Network/NullNATTraverser.h
@@ -16,8 +16,8 @@ namespace Swift {
 			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);
+			boost::shared_ptr<NATTraversalForwardPortRequest> createForwardPortRequest(int localPort, int publicPort);
+			boost::shared_ptr<NATTraversalRemovePortForwardingRequest> createRemovePortForwardingRequest(int localPort, int publicPort);
 
 		private:
 			EventLoop* eventLoop;
diff --git a/Swiften/Network/PlatformNATTraversalRequest.cpp b/Swiften/Network/PlatformNATTraversalRequest.cpp
deleted file mode 100644
index f875630..0000000
--- a/Swiften/Network/PlatformNATTraversalRequest.cpp
+++ /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.
- */
-
-#include "PlatformNATTraversalRequest.h"
-
-#include <Swiften/Network/PlatformNATTraversalWorker.h>
-
-namespace Swift {
-
-PlatformNATTraversalRequest::PlatformNATTraversalRequest(PlatformNATTraversalWorker* worker) : worker(worker) {
-
-}
-
-PlatformNATTraversalRequest::~PlatformNATTraversalRequest() {
-
-}
-
-void PlatformNATTraversalRequest::doRun() {
-	worker->addRequestToQueue(shared_from_this());
-}
-
-}
diff --git a/Swiften/Network/PlatformNATTraversalRequest.h b/Swiften/Network/PlatformNATTraversalRequest.h
deleted file mode 100644
index a891bab..0000000
--- a/Swiften/Network/PlatformNATTraversalRequest.h
+++ /dev/null
@@ -1,31 +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 <boost/enable_shared_from_this.hpp>
-#include <boost/shared_ptr.hpp>
-
-namespace Swift {
-
-class PlatformNATTraversalWorker;
-
-class PlatformNATTraversalRequest : public boost::enable_shared_from_this<PlatformNATTraversalRequest> {
-public:
-	typedef boost::shared_ptr<PlatformNATTraversalRequest> ref;
-
-public:
-	PlatformNATTraversalRequest(PlatformNATTraversalWorker* worker);
-	virtual ~PlatformNATTraversalRequest();
-
-	virtual void doRun();
-	virtual void runBlocking() = 0;
-
-private:
-	PlatformNATTraversalWorker* worker;
-};
-
-}
diff --git a/Swiften/Network/PlatformNATTraversalWorker.cpp b/Swiften/Network/PlatformNATTraversalWorker.cpp
index e0dcab5..c962b3b 100644
--- a/Swiften/Network/PlatformNATTraversalWorker.cpp
+++ b/Swiften/Network/PlatformNATTraversalWorker.cpp
@@ -7,18 +7,94 @@
 #include "PlatformNATTraversalWorker.h"
 
 #include <boost/smart_ptr/make_shared.hpp>
+#include <boost/enable_shared_from_this.hpp>
+
 #include <Swiften/Base/Log.h>
-#include <Swiften/Network/UPnPNATTraversalGetPublicIPRequest.h>
-#include <Swiften/Network/UPnPNATTraversalForwardPortRequest.h>
-#include <Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.h>
-#include <Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.h>
-#include <Swiften/Network/NATPMPNATTraversalForwardPortRequest.h>
-#include <Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.h>
+#include <Swiften/Network/NATTraversalGetPublicIPRequest.h>
+#include <Swiften/Network/NATTraversalForwardPortRequest.h>
+#include <Swiften/Network/NATTraversalRemovePortForwardingRequest.h>
+#include <Swiften/Network/NATPMPInterface.h>
+#include <Swiften/Network/MiniUPnPInterface.h>
 
 namespace Swift {
 
-PlatformNATTraversalWorker::PlatformNATTraversalWorker(EventLoop* eventLoop) : backendType(NotYetDecided), eventLoop(eventLoop), stopRequested(false) {
-	checkAvailableNATTraversalProtocols();
+class PlatformNATTraversalRequest : public boost::enable_shared_from_this<PlatformNATTraversalRequest> {
+	public:
+		typedef boost::shared_ptr<PlatformNATTraversalRequest> ref;
+
+	public:
+		PlatformNATTraversalRequest(PlatformNATTraversalWorker* worker) : worker(worker) {
+		}
+
+		virtual ~PlatformNATTraversalRequest() {
+		}
+
+		virtual void doRun() {
+			worker->addRequestToQueue(shared_from_this());
+		}
+
+		NATTraversalInterface* getNATTraversalInterface() const {
+			return worker->getNATTraversalInterface();
+		}
+
+
+		virtual void runBlocking() = 0;
+
+	private:
+		PlatformNATTraversalWorker* worker;
+};
+
+class PlatformNATTraversalGetPublicIPRequest : public NATTraversalGetPublicIPRequest, public PlatformNATTraversalRequest {
+	public:
+		PlatformNATTraversalGetPublicIPRequest(PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker) {
+		}
+
+		virtual void run() {
+			doRun();
+		}
+
+		virtual void runBlocking() {
+			onResult(getNATTraversalInterface()->getPublicIP());
+		}
+};
+
+class PlatformNATTraversalForwardPortRequest : public NATTraversalForwardPortRequest, public PlatformNATTraversalRequest {
+	public:
+		PlatformNATTraversalForwardPortRequest(PlatformNATTraversalWorker* worker, unsigned int localIP, unsigned int publicIP) : PlatformNATTraversalRequest(worker), localIP(localIP), publicIP(publicIP) {
+		}
+
+		virtual void run() {
+			doRun();
+		}
+
+		virtual void runBlocking() {
+			onResult(getNATTraversalInterface()->addPortForward(localIP, publicIP));
+		}
+
+	private:
+		unsigned int localIP;
+		unsigned int publicIP;
+};
+
+class PlatformNATTraversalRemovePortForwardingRequest : public NATTraversalRemovePortForwardingRequest, public PlatformNATTraversalRequest {
+	public:
+		PlatformNATTraversalRemovePortForwardingRequest(PlatformNATTraversalWorker* worker, const NATPortMapping& mapping) : PlatformNATTraversalRequest(worker), mapping(mapping) {
+		}
+
+		virtual void run() {
+			doRun();
+		}
+
+		virtual void runBlocking() {
+			onResult(getNATTraversalInterface()->removePortForward(mapping));
+		}
+
+	private:
+		NATPortMapping mapping;
+};
+
+PlatformNATTraversalWorker::PlatformNATTraversalWorker(EventLoop* eventLoop) : eventLoop(eventLoop), stopRequested(false), natPMPSupported(boost::logic::indeterminate), natPMPInterface(NULL), miniUPnPSupported(boost::logic::indeterminate), miniUPnPInterface(NULL) {
+	nullNATTraversalInterface = new NullNATTraversalInterface();
 	thread = new boost::thread(boost::bind(&PlatformNATTraversalWorker::run, this));
 }
 
@@ -27,57 +103,43 @@ PlatformNATTraversalWorker::~PlatformNATTraversalWorker() {
 	addRequestToQueue(boost::shared_ptr<PlatformNATTraversalRequest>());
 	thread->join();
 	delete thread;
+	delete natPMPInterface;
+	delete miniUPnPInterface;
+	delete nullNATTraversalInterface;
 }
 
-boost::shared_ptr<NATTraversalGetPublicIPRequest> PlatformNATTraversalWorker::createGetPublicIPRequest() {
-	switch(backendType) {
-		case UPnP:
-			return boost::make_shared<UPnPNATTraversalGetPublicIPRequest>(this);
-		case NATPMP:
-			return boost::make_shared<NATPMPNATTraversalGetPublicIPRequest>(this);
-		case NotYetDecided:
-		case None:
-			break;
+NATTraversalInterface* PlatformNATTraversalWorker::getNATTraversalInterface() const {
+	if (boost::logic::indeterminate(miniUPnPSupported)) {
+		miniUPnPInterface = new MiniUPnPInterface();
+		miniUPnPSupported = miniUPnPInterface->isAvailable();
+	}
+	if (miniUPnPSupported) {
+		return miniUPnPInterface;
 	}
-	return boost::shared_ptr<NATTraversalGetPublicIPRequest>();
-}
 
-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;
-
-	switch(backendType) {
-		case UPnP:
-			return boost::make_shared<UPnPNATTraversalForwardPortRequest>(mapping, this);
-		case NATPMP:
-			return boost::make_shared<NATPMPNATTraversalForwardPortRequest>(mapping, this);
-		case NotYetDecided:
-		case None:
-			break;
+
+	if (boost::logic::indeterminate(natPMPSupported)) {
+		natPMPInterface = new NATPMPInterface();
+		natPMPSupported = natPMPInterface->isAvailable();
+	}
+	if (natPMPSupported) {
+		return natPMPInterface;
 	}
-	return boost::shared_ptr<NATTraversalForwardPortRequest>();
+
+	return nullNATTraversalInterface;
 }
 
-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;
-
-	switch(backendType) {
-		case UPnP:
-			return boost::make_shared<UPnPNATTraversalRemovePortForwardingRequest>(mapping, this);
-		case NATPMP:
-			return boost::make_shared<NATPMPNATTraversalRemovePortForwardingRequest>(mapping, this);
-		case NotYetDecided:
-		case None:
-			break;
-	}
-	return boost::shared_ptr<NATTraversalRemovePortForwardingRequest>();
+boost::shared_ptr<NATTraversalGetPublicIPRequest> PlatformNATTraversalWorker::createGetPublicIPRequest() {
+	return boost::make_shared<PlatformNATTraversalGetPublicIPRequest>(this);
+}
+
+boost::shared_ptr<NATTraversalForwardPortRequest> PlatformNATTraversalWorker::createForwardPortRequest(int localPort, int publicPort) {
+	return boost::make_shared<PlatformNATTraversalForwardPortRequest>(this, localPort, publicPort);
+}
+
+boost::shared_ptr<NATTraversalRemovePortForwardingRequest> PlatformNATTraversalWorker::createRemovePortForwardingRequest(int localPort, int publicPort) {
+	NATPortMapping mapping(localPort, publicPort, NATPortMapping::TCP); // FIXME
+	return boost::make_shared<PlatformNATTraversalRemovePortForwardingRequest>(this, mapping);
 }
 
 void PlatformNATTraversalWorker::run() {
@@ -107,33 +169,4 @@ void PlatformNATTraversalWorker::addRequestToQueue(PlatformNATTraversalRequest::
 	queueNonEmpty.notify_one();
 }
 
-void PlatformNATTraversalWorker::checkAvailableNATTraversalProtocols() {
-	boost::shared_ptr<UPnPNATTraversalGetPublicIPRequest> upnpRequest = boost::make_shared<UPnPNATTraversalGetPublicIPRequest>(this);
-	upnpRequest->onResult.connect(boost::bind(&PlatformNATTraversalWorker::handleUPnPGetPublicIPResult, this, _1));
-
-	boost::shared_ptr<NATPMPNATTraversalGetPublicIPRequest> natpmpRequest = boost::make_shared<NATPMPNATTraversalGetPublicIPRequest>(this);
-	natpmpRequest->onResult.connect(boost::bind(&PlatformNATTraversalWorker::handleNATPMPGetPublicIPResult, this, _1));
-
-	upnpRequest->run();
-	natpmpRequest->run();
-}
-
-void PlatformNATTraversalWorker::handleUPnPGetPublicIPResult(boost::optional<HostAddress> address) {
-	if (backendType == NotYetDecided || backendType == None) {
-		if (address) {
-			SWIFT_LOG(debug) << "Found UPnP IGD in the local network." << std::endl;
-			backendType = UPnP;
-		}
-	}
-}
-
-void PlatformNATTraversalWorker::handleNATPMPGetPublicIPResult(boost::optional<HostAddress> address) {
-	if (backendType == NotYetDecided || backendType == None) {
-		if (address) {
-			SWIFT_LOG(debug) << "Found NAT-PMP device in the local network." << std::endl;
-			backendType = NATPMP;
-		}
-	}
-}
-
 }
diff --git a/Swiften/Network/PlatformNATTraversalWorker.h b/Swiften/Network/PlatformNATTraversalWorker.h
index 9de1258..94d3339 100644
--- a/Swiften/Network/PlatformNATTraversalWorker.h
+++ b/Swiften/Network/PlatformNATTraversalWorker.h
@@ -11,51 +11,51 @@
 #include <boost/thread/thread.hpp>
 #include <boost/thread/mutex.hpp>
 #include <boost/thread/condition_variable.hpp>
+#include <boost/logic/tribool.hpp>
 
 #include <Swiften/Network/NATTraverser.h>
 #include <Swiften/Network/HostAddressPort.h>
-#include <Swiften/Network/PlatformNATTraversalRequest.h>
+#include <Swiften/Network/NullNATTraversalInterface.h>
 
 namespace Swift {
-
-class EventLoop;
-class NATTraversalGetPublicIPRequest;
-class NATTraversalForwardPortRequest;
-class NATTraversalRemovePortForwardingRequest;
-
-class PlatformNATTraversalWorker : public NATTraverser {
-private:
-	enum BackendType {
-		NotYetDecided,
-		UPnP,
-		NATPMP,
-		None,
+	class EventLoop;
+	class NATTraversalGetPublicIPRequest;
+	class NATTraversalForwardPortRequest;
+	class NATTraversalRemovePortForwardingRequest;
+	class PlatformNATTraversalRequest;
+	class NATPMPInterface;
+	class MiniUPnPInterface;
+	class NATTraversalInterface;
+	class NATPortMapping;
+
+	class PlatformNATTraversalWorker : public NATTraverser {
+			friend class PlatformNATTraversalRequest;
+
+		public:
+			PlatformNATTraversalWorker(EventLoop* eventLoop);
+			~PlatformNATTraversalWorker();
+
+			boost::shared_ptr<NATTraversalGetPublicIPRequest> createGetPublicIPRequest();
+			boost::shared_ptr<NATTraversalForwardPortRequest> createForwardPortRequest(int localPort, int publicPort);
+			boost::shared_ptr<NATTraversalRemovePortForwardingRequest> createRemovePortForwardingRequest(int localPort, int publicPort);
+
+		private:
+			NATTraversalInterface* getNATTraversalInterface() const;
+			void addRequestToQueue(boost::shared_ptr<PlatformNATTraversalRequest>);
+			void run();
+
+		private:
+			EventLoop* eventLoop;
+			bool stopRequested;
+			boost::thread* thread;
+			std::deque<boost::shared_ptr<PlatformNATTraversalRequest> > queue;
+			boost::mutex queueMutex;
+			boost::condition_variable queueNonEmpty;
+
+			NullNATTraversalInterface* nullNATTraversalInterface;
+			mutable boost::logic::tribool natPMPSupported;
+			mutable NATPMPInterface* natPMPInterface;
+			mutable boost::logic::tribool miniUPnPSupported;
+			mutable MiniUPnPInterface* miniUPnPInterface;
 	};
-
-public:
-	PlatformNATTraversalWorker(EventLoop* eventLoop);
-	~PlatformNATTraversalWorker();
-
-	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);
-
-private:
-	void checkAvailableNATTraversalProtocols();
-	void handleUPnPGetPublicIPResult(boost::optional<HostAddress> address);
-	void handleNATPMPGetPublicIPResult(boost::optional<HostAddress> address);
-
-private:
-	BackendType backendType;
-	EventLoop* eventLoop;
-	bool stopRequested;
-	boost::thread* thread;
-	std::deque<PlatformNATTraversalRequest::ref> queue;
-	boost::mutex queueMutex;
-	boost::condition_variable queueNonEmpty;
-};
-
 }
diff --git a/Swiften/Network/SConscript b/Swiften/Network/SConscript
index e44f868..49df18f 100644
--- a/Swiften/Network/SConscript
+++ b/Swiften/Network/SConscript
@@ -47,6 +47,7 @@ sourceList = [
 			"NATTraversalGetPublicIPRequest.cpp",
 			"NATTraversalForwardPortRequest.cpp",
 			"NATTraversalRemovePortForwardingRequest.cpp",
+			"NATTraversalInterface.cpp",
 	]
 
 if myenv.get("HAVE_CARES", False) :
@@ -75,22 +76,17 @@ if myenv["experimental"] :
 	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"
+				"NATPMPInterface.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",
+				"MiniUPnPInterface.cpp",
 			])
 	objects += myenv.SwiftenObject([
 				"PlatformNATTraversalWorker.cpp",
-				"PlatformNATTraversalRequest.cpp",
-				])
+			])
 
 swiften_env.Append(SWIFTEN_OBJECTS = [objects])
diff --git a/Swiften/Network/UPnPNATTraversalForwardPortRequest.cpp b/Swiften/Network/UPnPNATTraversalForwardPortRequest.cpp
deleted file mode 100644
index 6fcc01a..0000000
--- a/Swiften/Network/UPnPNATTraversalForwardPortRequest.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2011 Tobias Markmann
- * Licensed under the simplified BSD license.
- * See Documentation/Licenses/BSD-simplified.txt for more information.
- */
-
-#include "UPnPNATTraversalForwardPortRequest.h"
-
-#include <boost/format.hpp>
-
-#include <miniupnpc.h>
-#include <upnpcommands.h>
-#include <upnperrors.h>
-
-#include <Swiften/Base/foreach.h>
-#include <Swiften/Network/NetworkInterface.h>
-#include <Swiften/Network/PlatformNetworkEnvironment.h>
-
-namespace Swift {
-
-UPnPNATTraversalForwardPortRequest::UPnPNATTraversalForwardPortRequest(NATTraversalForwardPortRequest::PortMapping mapping, PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker), mapping(mapping) {
-
-}
-
-UPnPNATTraversalForwardPortRequest::~UPnPNATTraversalForwardPortRequest() {
-
-}
-
-void UPnPNATTraversalForwardPortRequest::runBlocking() {
-	boost::optional<PortMapping> result;
-
-	UPNPDev* deviceList = 0;
-	int error = 0;
-	char lanAddrress[64];
-
-	std::string publicPort = str(boost::format("%d") % mapping.publicPort);
-	std::string localPort = str(boost::format("%d") % mapping.localPort);
-	std::string internalClient = PlatformNetworkEnvironment().getLocalAddress().toString();
-	std::string leaseSeconds = str(boost::format("%d") % mapping.leaseInSeconds);
-	UPNPUrls urls;
-	IGDdatas data;
-
-	do {
-		// find valid IGD
-		deviceList = upnpDiscover(1500 /* timeout in ms */, 0, 0, 0, 0 /* do IPv6? */, &error);
-		if (!deviceList) {
-			break;
-		}
-
-		if (!UPNP_GetValidIGD(deviceList, &urls, &data, lanAddrress, sizeof(lanAddrress))) {
-			break;
-		}
-
-		/*
-		int ret = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
-		if (ret != UPNPCOMMAND_SUCCESS) {
-			break;
-		}*/
-
-		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<NATTraversalForwardPortRequest::PortMapping>(mapping);
-		}
-	} while(false);
-
-	freeUPNPDevlist(deviceList); deviceList = 0;
-
-	onResult(result);
-}
-
-}
diff --git a/Swiften/Network/UPnPNATTraversalForwardPortRequest.h b/Swiften/Network/UPnPNATTraversalForwardPortRequest.h
deleted file mode 100644
index 777ab26..0000000
--- a/Swiften/Network/UPnPNATTraversalForwardPortRequest.h
+++ /dev/null
@@ -1,29 +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/Network/NATTraversalForwardPortRequest.h>
-#include <Swiften/Network/PlatformNATTraversalRequest.h>
-
-namespace Swift {
-
-class UPnPNATTraversalForwardPortRequest : public NATTraversalForwardPortRequest, public PlatformNATTraversalRequest {
-public:
-	UPnPNATTraversalForwardPortRequest(NATTraversalForwardPortRequest::PortMapping, PlatformNATTraversalWorker*);
-	virtual ~UPnPNATTraversalForwardPortRequest();
-
-	virtual void runBlocking();
-
-	virtual void run() {
-		doRun();
-	}
-
-private:
-	NATTraversalForwardPortRequest::PortMapping mapping;
-};
-
-}
diff --git a/Swiften/Network/UPnPNATTraversalGetPublicIPRequest.cpp b/Swiften/Network/UPnPNATTraversalGetPublicIPRequest.cpp
deleted file mode 100644
index 4ed2f5f..0000000
--- a/Swiften/Network/UPnPNATTraversalGetPublicIPRequest.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2011 Tobias Markmann
- * Licensed under the simplified BSD license.
- * See Documentation/Licenses/BSD-simplified.txt for more information.
- */
-
-#include "UPnPNATTraversalGetPublicIPRequest.h"
-
-#include <miniupnpc.h>
-#include <upnpcommands.h>
-#include <upnperrors.h>
-
-namespace Swift {
-
-UPnPNATTraversalGetPublicIPRequest::UPnPNATTraversalGetPublicIPRequest(PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker) {
-
-}
-
-UPnPNATTraversalGetPublicIPRequest::~UPnPNATTraversalGetPublicIPRequest() {
-
-}
-
-void UPnPNATTraversalGetPublicIPRequest::runBlocking() {
-	boost::optional<HostAddress> result;
-
-	UPNPDev* deviceList = 0;
-	int error = 0;
-	char lanAddrress[64];
-	char externalIPAddress[40];
-	UPNPUrls urls;
-	IGDdatas data;
-
-	do {
-		// find valid IGD
-		deviceList = upnpDiscover(1500 /* timeout in ms */, 0, 0, 0, 0 /* do IPv6? */, &error);
-		if (!deviceList) {
-			break;
-		}
-
-		if (!UPNP_GetValidIGD(deviceList, &urls, &data, lanAddrress, sizeof(lanAddrress))) {
-			break;
-		}
-
-		int ret = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
-		if (ret != UPNPCOMMAND_SUCCESS) {
-			break;
-		} else {
-			result = HostAddress(std::string(externalIPAddress));
-		}
-	} while(false);
-
-	freeUPNPDevlist(deviceList); deviceList = 0;
-
-	onResult(result);
-}
-
-}
diff --git a/Swiften/Network/UPnPNATTraversalGetPublicIPRequest.h b/Swiften/Network/UPnPNATTraversalGetPublicIPRequest.h
deleted file mode 100644
index 884f1de..0000000
--- a/Swiften/Network/UPnPNATTraversalGetPublicIPRequest.h
+++ /dev/null
@@ -1,26 +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/Network/NATTraversalGetPublicIPRequest.h>
-#include <Swiften/Network/PlatformNATTraversalRequest.h>
-
-namespace Swift {
-
-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
deleted file mode 100644
index 9b83173..0000000
--- a/Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2011 Tobias Markmann
- * Licensed under the simplified BSD license.
- * See Documentation/Licenses/BSD-simplified.txt for more information.
- */
-
-#include "UPnPNATTraversalRemovePortForwardingRequest.h"
-
-#include <boost/format.hpp>
-
-#include <miniupnpc.h>
-#include <upnpcommands.h>
-#include <upnperrors.h>
-
-#include <Swiften/Base/foreach.h>
-#include <Swiften/Base/Log.h>
-#include <Swiften/Network/NetworkInterface.h>
-#include <Swiften/Network/PlatformNetworkEnvironment.h>
-
-namespace Swift {
-
-UPnPNATTraversalRemovePortForwardingRequest::UPnPNATTraversalRemovePortForwardingRequest(NATTraversalRemovePortForwardingRequest::PortMapping mapping, PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker), mapping(mapping) {
-
-}
-
-UPnPNATTraversalRemovePortForwardingRequest::~UPnPNATTraversalRemovePortForwardingRequest() {
-
-}
-
-void UPnPNATTraversalRemovePortForwardingRequest::runBlocking() {
-	boost::optional<bool> result;
-
-	UPNPDev* deviceList = 0;
-	int error = 0;
-	char lanAddrress[64];
-
-	std::string publicPort = str(boost::format("%d") % mapping.publicPort);
-	std::string localPort = str(boost::format("%d") % mapping.localPort);
-	std::string internalClient = PlatformNetworkEnvironment().getLocalAddress().toString();
-	std::string leaseSeconds = str(boost::format("%d") % mapping.leaseInSeconds);
-	UPNPUrls urls;
-	IGDdatas data;
-
-	do {
-		// find valid IGD
-		deviceList = upnpDiscover(1500 /* timeout in ms */, 0, 0, 0, 0 /* do IPv6? */, &error);
-		if (!deviceList) {
-			break;
-		}
-
-		if (!UPNP_GetValidIGD(deviceList, &urls, &data, lanAddrress, sizeof(lanAddrress))) {
-			break;
-		}
-
-		/*
-		int ret = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
-		if (ret != UPNPCOMMAND_SUCCESS) {
-			break;
-		}*/
-		SWIFT_LOG(debug) << "Start removing port forwarding..." << std::endl;
-		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;
-			result = true;
-		} else {
-			SWIFT_LOG(debug) << "Removing port " << publicPort << " failed." << std::endl;
-			result = false;
-		}
-	} while(false);
-
-	freeUPNPDevlist(deviceList); deviceList = 0;
-
-	onResult(result);
-}
-
-}
diff --git a/Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.h b/Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.h
deleted file mode 100644
index 644eae7..0000000
--- a/Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.h
+++ /dev/null
@@ -1,29 +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/Network/PlatformNATTraversalRequest.h>
-#include <Swiften/Network/NATTraversalRemovePortForwardingRequest.h>
-
-namespace Swift {
-
-class UPnPNATTraversalRemovePortForwardingRequest : public NATTraversalRemovePortForwardingRequest, public PlatformNATTraversalRequest {
-public:
-	UPnPNATTraversalRemovePortForwardingRequest(NATTraversalRemovePortForwardingRequest::PortMapping, PlatformNATTraversalWorker*);
-	virtual ~UPnPNATTraversalRemovePortForwardingRequest();
-
-	virtual void runBlocking();
-
-	virtual void run() {
-		doRun();
-	}
-
-private:
-	NATTraversalRemovePortForwardingRequest::PortMapping mapping;
-};
-
-}
-- 
cgit v0.10.2-6-g49f6