diff options
author | Remko Tronçon <git@el-tramo.be> | 2011-09-28 20:01:57 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2011-09-29 18:07:17 (GMT) |
commit | dfccb5703c4d85ab1a54429016b103101bdc54ae (patch) | |
tree | 05ac257e6dc7609a5b02e94e59b52f44b74f123d | |
parent | 6cea7fdfea93e54543c6757909a8fae7348754fc (diff) | |
download | swift-contrib-dfccb5703c4d85ab1a54429016b103101bdc54ae.zip swift-contrib-dfccb5703c4d85ab1a54429016b103101bdc54ae.tar.bz2 |
File Transfer refactoring.
NAT traversal classes refactoring.
Added beginnings of a NetworkTool.
40 files changed, 1406 insertions, 788 deletions
@@ -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 "${plugin_state_location}/${specs_file}"'" 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 "${plugin_state_location}/specs.cpp"'" 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 "${plugin_state_location}/specs.c"'" 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 "${plugin_state_location}/${specs_file}"'" 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 "${plugin_state_location}/specs.cpp"'" 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 "${plugin_state_location}/specs.c"'" 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 "${plugin_state_location}/${specs_file}"'" 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 "${plugin_state_location}/specs.cpp"'" 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 "${plugin_state_location}/specs.c"'" 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"/> @@ -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>&&</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; -}; - -} |