From 213ad11b3dad883134bc5ca23649224585d1d562 Mon Sep 17 00:00:00 2001 From: Sebastien Vincent Date: Sat, 12 Aug 2017 23:30:11 +0200 Subject: [PATCH] UPnP support (#144) * Adds initial implementation for UPnP. * Updates build instructions. * Returns string representation of UPnP errors and fixes compilation of FSCP samples. * Throws error if UPnP IGD is not supported. * Removes vim backup file. * Adds libminiupnpc dependency for Linux/macOS in Travis CI and in Dockerfile. * Adds Windows 'attendee' target to build miniupnpc. * Updates build documentation to add cmake requirement (to generate vcxproj for miniupnpc dependency). * Adds support for recent miniupnpc library (API change). * Changes Windows vcxproj to build FreeLAN with libminiupnpcplus. * Removes sample binary. * Fixes Dockerfile dependency for libminiupnpc. * Adds libminiupnpc dependency for valgrind provisioning. * Uses miniupnpcd.lib link for Windows debug build. * Adds UPnP option in configuration file. * Adds some logs. * Adds option in SConstruct to build FreeLAN with or without UPnP support. * Makes miniupnpcplus::upnp_device class noncopyable. * Be sure to have upnp flag for all SConstruct targets. * Adds some logs. * Uses std::unique_ptr rather than raw pointer and minor logic fixes. * Updates appveyor.yml to add miniupnpc dependency. --- .party | 32 +++ .travis.yml | 2 + BUILD.md | 7 +- SConscript | 6 + SConstruct | 27 ++- apps/freelan/SConscript | 6 + apps/freelan/config/freelan.cfg | 5 + apps/freelan/freelan.vcxproj | 26 +- apps/freelan/src/configuration_helper.cpp | 1 + appveyor.yml | 1 + freelan-all.sln | 14 +- .../freelan/include/freelan/configuration.hpp | 5 + libs/freelan/libfreelan.vcxproj | 18 +- libs/freelan/src/core.cpp | 9 + libs/fscp/include/fscp/server.hpp | 16 ++ libs/fscp/libfscp.vcxproj | 18 +- libs/fscp/src/server.cpp | 33 +++ libs/miniupnpcplus/SConscript | 17 ++ .../include/miniupnpcplus/error.hpp | 102 ++++++++ .../include/miniupnpcplus/miniupnpcplus.hpp | 49 ++++ .../include/miniupnpcplus/upnp_device.hpp | 162 +++++++++++++ libs/miniupnpcplus/libminiupnpcplus.vcxproj | 227 ++++++++++++++++++ .../libminiupnpcplus.vcxproj.filters | 39 +++ libs/miniupnpcplus/src/error.cpp | 67 ++++++ libs/miniupnpcplus/src/miniupnpcplus.cpp | 49 ++++ libs/miniupnpcplus/src/upnp_device.cpp | 142 +++++++++++ packaging/docker/freelan/Dockerfile | 4 +- .../roles/freelan-build/tasks/main.yml | 1 + samples/fscp/client/SConscript | 9 +- samples/fscp/schat/SConscript | 9 +- samples/miniupnpcplus/mapping/.gitignore | 2 + samples/miniupnpcplus/mapping/SConscript | 17 ++ samples/miniupnpcplus/mapping/mapping.cpp | 42 ++++ 33 files changed, 1115 insertions(+), 49 deletions(-) create mode 100644 libs/miniupnpcplus/SConscript create mode 100644 libs/miniupnpcplus/include/miniupnpcplus/error.hpp create mode 100644 libs/miniupnpcplus/include/miniupnpcplus/miniupnpcplus.hpp create mode 100644 libs/miniupnpcplus/include/miniupnpcplus/upnp_device.hpp create mode 100644 libs/miniupnpcplus/libminiupnpcplus.vcxproj create mode 100644 libs/miniupnpcplus/libminiupnpcplus.vcxproj.filters create mode 100644 libs/miniupnpcplus/src/error.cpp create mode 100644 libs/miniupnpcplus/src/miniupnpcplus.cpp create mode 100644 libs/miniupnpcplus/src/upnp_device.cpp create mode 100644 samples/miniupnpcplus/mapping/.gitignore create mode 100644 samples/miniupnpcplus/mapping/SConscript create mode 100644 samples/miniupnpcplus/mapping/mapping.cpp diff --git a/.party b/.party index b208635e..8abdf4ef 100644 --- a/.party +++ b/.party @@ -149,3 +149,35 @@ Attendee('curl').get_build('msvc-x64').commands = [ r'nmake /f Makefile.vc mode=static VC=15 WITH_DEVEL={{prefix}} DEBUG=yes GEN_PDB=yes MACHINE=x64', r'xcopy ..\builds\libcurl-vc15-x64-debug-static-ipv6-sspi-winssl {{prefix}}\Debug\ /S /Y', ] + +# miniupnpc +Attendee('miniupnpc', filter=('msvc')) +Attendee('miniupnpc').add_build('msvc-x86', environment='system', filter='msvc-x86', prefix='x86') +Attendee('miniupnpc').add_build('msvc-x64', environment='system', filter='msvc-x64', prefix='x64') +Attendee('miniupnpc').add_source('https://github.com/miniupnp/miniupnp/archive/miniupnpd_2_0.zip', filter='windows', mimetype='application/zip') +Attendee('miniupnpc').get_build('msvc-x86').commands = [ + r'"C:\Program Files\CMake\bin\cmake.exe" ./miniupnpc/', + r'msbuild .\upnpc-static.vcxproj /p:Platformtoolset=v141 /p:WindowsTargetPlatformVersion=10.0.15063.0 /p:Configuration=Release /p:Platform="Win32"', + r'msbuild .\upnpc-static.vcxproj /p:Platformtoolset=v141 /p:WindowsTargetPlatformVersion=10.0.15063.0 /p:Configuration=Debug /p:Platform="Win32"', + r'md {{prefix}}\Release\lib || echo', + r'md {{prefix}}\Release\include\miniupnpc || echo', + r'md {{prefix}}\Debug\lib || echo', + r'md {{prefix}}\Debug\include\miniupnpc || echo', + r'copy Release\miniupnpc.lib {{prefix}}\Release\lib\miniupnpc.lib', + r'copy Debug\miniupnpc.lib {{prefix}}\Debug\lib\miniupnpcd.lib', + r'xcopy miniupnpc\*.h {{prefix}}\Release\include\miniupnpc\ /S /Y', + r'xcopy miniupnpc\*.h {{prefix}}\Debug\include\miniupnpc\ /S /Y', +] +Attendee('miniupnpc').get_build('msvc-x64').commands = [ + r'"C:\Program Files\CMake\bin\cmake.exe" -DCMAKE_GENERATOR_PLATFORM=x64 ./miniupnpc/', + r'msbuild .\upnpc-static.vcxproj /p:Platformtoolset=v141 /p:WindowsTargetPlatformVersion=10.0.15063.0 /p:Configuration=Release /p:Platform="x64"', + r'msbuild .\upnpc-static.vcxproj /p:Platformtoolset=v141 /p:WindowsTargetPlatformVersion=10.0.15063.0 /p:Configuration=Debug /p:Platform="x64"', + r'md {{prefix}}\Release\lib || echo', + r'md {{prefix}}\Release\include || echo', + r'md {{prefix}}\Debug\lib || echo', + r'md {{prefix}}\Debug\include || echo', + r'copy Release\miniupnpc.lib {{prefix}}\Release\lib\miniupnpc.lib', + r'copy Debug\miniupnpc.lib {{prefix}}\Debug\lib\miniupnpcd.lib', + r'xcopy miniupnpc\*.h {{prefix}}\Release\include\miniupnpc\ /S /Y', + r'xcopy miniupnpc\*.h {{prefix}}\Debug\include\miniupnpc\ /S /Y', +] diff --git a/.travis.yml b/.travis.yml index e15daf58..64b6a0f2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,7 @@ addons: - libboost-all-dev - libssl-dev - libcurl4-openssl-dev + - libminiupnpc-dev - gcc - g++ before_install: @@ -23,6 +24,7 @@ before_install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew list scons &>/dev/null || brew install scons ; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew list boost &>/dev/null || brew install boost ; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew list openssl &>/dev/null || brew install openssl ; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew list miniupnpc &>/dev/null || brew install miniupnpc ; fi cache: apt: true script: scons install apps samples diff --git a/BUILD.md b/BUILD.md index 1a25d99c..4a922f6d 100644 --- a/BUILD.md +++ b/BUILD.md @@ -7,6 +7,7 @@ Third-party libraries FreeLAN depends on the following libraries: - libcurl4 +- libminiupnpc - boost - OpenSSL - iconv (Windows) @@ -17,7 +18,7 @@ to build these libraries explicitely. To build the third-party libraries, you can use [teapot](https://github.com/freelan-developers/teapot) (be sure to have `python -2.7` and `perl` installed). Check its +2.7`, `cmake` and `perl` installed). Check its [documentation](http://teapot-builder.readthedocs.org/en/latest/) for details, or just type the following command at the root of FreeLAN's repository: @@ -33,7 +34,7 @@ following command: > sudo apt-get install scons python libssl-dev libcurl4-openssl-dev > libboost-system-dev libboost-thread-dev libboost-program-options-dev -> libboost-filesystem-dev libboost-iostreams-dev build-essential +> libboost-filesystem-dev libboost-iostreams-dev libminiupnpc-dev build-essential ### Mac OSX @@ -44,7 +45,7 @@ To install the required dependencies on Mac OS, type the following commands: > brew update -> brew install scons boost openssl +> brew install scons boost openssl miniupnpc Building FreeLAN ---------------- diff --git a/SConscript b/SConscript index d3ea7f3c..a5c64b0a 100644 --- a/SConscript +++ b/SConscript @@ -42,6 +42,9 @@ for x in Glob('libs/*'): if env.mongoose == 'no' and name in 'mongooseplus': continue + if env.upnp == 'no' and name in 'miniupnpcplus': + continue + library, library_includes = SConscript(sconscript_path, exports='env dirs name') libraries.extend(library) includes.extend(library_includes) @@ -68,6 +71,9 @@ if env.mode != 'retail': if libname in 'netlinkplus': continue + if libname in 'miniupnpcplus': + continue + for y in x.glob('*'): sconscript_path = y.File('SConscript') diff --git a/SConstruct b/SConstruct index 295938f2..c8138086 100644 --- a/SConstruct +++ b/SConstruct @@ -31,14 +31,22 @@ AddOption( default='no', help='Build webserver with mongoose (warning: it will violate GPLv3 license to distribute binaries built with this switch turned on!)', ) - +AddOption( + '--upnp', + dest='upnp', + nargs=1, + action='store', + choices=('yes', 'no'), + default='yes', + help='Build FreeLAN with UPnP support.', +) class FreelanEnvironment(Environment): """ A freelan specific environment class. """ - def __init__(self, mode, prefix, bin_prefix=None, mongoose='no', **kwargs): + def __init__(self, mode, prefix, bin_prefix=None, **kwargs): """ Initialize the environment. @@ -79,6 +87,7 @@ class FreelanEnvironment(Environment): self.bin_prefix = bin_prefix if bin_prefix else prefix self.destdir = self['ENV'].get('DESTDIR', '') self.mongoose = mongoose + self.upnp = upnp if self.destdir: self.install_prefix = os.path.normpath( @@ -129,8 +138,11 @@ class FreelanEnvironment(Environment): else: self.Append(CXXFLAGS='-O3') - if self.mongoose == 'yes': - self.Append(CXXFLAGS=['-DUSE_MONGOOSE']) + if self.mongoose == 'yes': + self.Append(CXXFLAGS=['-DUSE_MONGOOSE']) + + if self.upnp == 'yes': + self.Append(CXXFLAGS=['-DUSE_UPNP']) self.Append(CPPDEFINES=r'FREELAN_INSTALL_PREFIX="\"%s\""' % self.prefix) @@ -177,6 +189,7 @@ class FreelanEnvironment(Environment): mode = GetOption('mode') mongoose = GetOption('mongoose') +upnp = GetOption('upnp') prefix = os.path.normpath(os.path.abspath(ARGUMENTS.get('prefix', './install'))) if 'bin_prefix' in ARGUMENTS: @@ -185,7 +198,7 @@ else: bin_prefix = None if mode in ('all', 'release'): - env = FreelanEnvironment(mode='release', prefix=prefix, bin_prefix=bin_prefix, mongoose=mongoose) + env = FreelanEnvironment(mode='release', prefix=prefix, bin_prefix=bin_prefix, mongoose=mongoose, upnp=upnp) libraries, includes, apps, samples, configurations = SConscript('SConscript', exports='env', variant_dir=os.path.join('build', env.mode)) install = env.Install(os.path.join(env.bin_install_prefix, 'bin'), apps) install.extend(env.Install(os.path.join(env.install_prefix, 'etc', 'freelan'), configurations)) @@ -196,7 +209,7 @@ if mode in ('all', 'release'): Alias('all', install + apps + samples) if mode in ('all', 'debug'): - env = FreelanEnvironment(mode='debug', prefix=prefix, mongoose=mongoose) + env = FreelanEnvironment(mode='debug', prefix=prefix, mongoose=mongoose, upnp=upnp) libraries, includes, apps, samples, configurations = SConscript('SConscript', exports='env', variant_dir=os.path.join('build', env.mode)) Alias('apps', apps) Alias('samples', samples) @@ -204,7 +217,7 @@ if mode in ('all', 'debug'): if sys.platform.startswith('darwin'): retail_prefix = '/usr/local' - env = FreelanEnvironment(mode='retail', prefix=retail_prefix, mongoose=mongoose) + env = FreelanEnvironment(mode='retail', prefix=retail_prefix, mongoose=mongoose, upnp=upnp) libraries, includes, apps, samples, configurations = SConscript('SConscript', exports='env', variant_dir=os.path.join('build', env.mode)) package = SConscript('packaging/osx/SConscript', exports='env apps configurations retail_prefix') install_package = env.Install('.', package) diff --git a/apps/freelan/SConscript b/apps/freelan/SConscript index d3ae84a7..5bb45d69 100644 --- a/apps/freelan/SConscript +++ b/apps/freelan/SConscript @@ -48,6 +48,12 @@ if env.mongoose == 'yes': 'mongooseplus', ]) +if env.upnp == 'yes': + libraries.extend([ + 'miniupnpcplus', + 'miniupnpc', + ]) + env = env.Clone() env.Prepend(LIBS=libraries) diff --git a/apps/freelan/config/freelan.cfg b/apps/freelan/config/freelan.cfg index e787300c..792ca174 100644 --- a/apps/freelan/config/freelan.cfg +++ b/apps/freelan/config/freelan.cfg @@ -328,6 +328,11 @@ public_endpoint=0.0.0.0 #elliptic_curve_capability=sect571k1 #elliptic_curve_capability=secp384r1 +# Enable UPnP to traverse NAT +# +# Default: yes +#upnp_enabled=yes + [tap_adapter] # The tap adapter type. diff --git a/apps/freelan/freelan.vcxproj b/apps/freelan/freelan.vcxproj index a0d0c59e..cbf37876 100644 --- a/apps/freelan/freelan.vcxproj +++ b/apps/freelan/freelan.vcxproj @@ -85,7 +85,7 @@ true - $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\include;$(IncludePath) + $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(SolutionDir)\libs\miniupnpcplus\include;$(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\include;$(IncludePath) $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\apps\$(ProjectName)\ $(SolutionDir)\install\$(PlatformShortName)\$(Configuration)\bin\ $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\lib;$(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\lib;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSDK_LibraryPath_x86);$(VC_LibraryPath_x86) @@ -94,7 +94,7 @@ true - $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\include;$(IncludePath) + $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(SolutionDir)\libs\miniupnpcplus\include;$(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\include;$(IncludePath) $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\apps\$(ProjectName)\ $(SolutionDir)\install\$(PlatformShortName)\$(Configuration)\bin\ $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\lib;$(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\lib;$(VCInstallDir)lib\amd64;$(VCInstallDir)atlmfc\lib\amd64;$(WindowsSDK_LibraryPath_x64);$(VC_LibraryPath_x64) @@ -103,7 +103,7 @@ false - $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\include;$(IncludePath) + $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(SolutionDir)\libs\miniupnpcplus\include;$(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\include;$(IncludePath) $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\apps\$(ProjectName)\ $(SolutionDir)\install\$(PlatformShortName)\$(Configuration)\bin\ $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\lib;$(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\lib;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSDK_LibraryPath_x86);$(VC_LibraryPath_x86) @@ -112,7 +112,7 @@ false - $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\include;$(IncludePath) + $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(SolutionDir)\libs\miniupnpcplus\include;$(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\include;$(IncludePath) $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\apps\$(ProjectName)\ $(SolutionDir)\install\$(PlatformShortName)\$(Configuration)\bin\ $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\lib;$(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\lib;$(VCInstallDir)lib\amd64;$(VCInstallDir)atlmfc\lib\amd64;$(WindowsSDK_LibraryPath_x64);$(VC_LibraryPath_x64) @@ -125,14 +125,14 @@ Level3 Disabled - USING_STATIC_LIBICONV;CURL_STATICLIB;BOOST_ALL_NO_LIB;DEBUG;_WIN32_WINNT=0x0501;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + USING_STATIC_LIBICONV;MINIUPNP_STATICLIB;CURL_STATICLIB;BOOST_ALL_NO_LIB;DEBUG;_WIN32_WINNT=0x0501;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true 4345;4996;4267 Console true - libiconvd.lib;libeay32.lib;ssleay32.lib;libcurl_a_debug.lib;libboost_date_time-vc141-mt-gd-1_64.lib;libboost_system-vc141-mt-gd-1_64.lib;libboost_thread-vc141-mt-gd-1_64.lib;libboost_program_options-vc141-mt-gd-1_64.lib;libboost_filesystem-vc141-mt-gd-1_64.lib;libiconvplus.lib;libkfather.lib;libexecuteplus.lib;libcryptoplus.lib;libasiotap.lib;libfscp.lib;libmongooseplus.lib;libfreelan.lib;Iphlpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + libiconvd.lib;libeay32.lib;ssleay32.lib;libcurl_a_debug.lib;libboost_date_time-vc141-mt-gd-1_64.lib;libboost_system-vc141-mt-gd-1_64.lib;libboost_thread-vc141-mt-gd-1_64.lib;libboost_program_options-vc141-mt-gd-1_64.lib;libboost_filesystem-vc141-mt-gd-1_64.lib;libiconvplus.lib;libkfather.lib;libexecuteplus.lib;libcryptoplus.lib;libasiotap.lib;libfscp.lib;libmongooseplus.lib;libfreelan.lib;miniupnpcd.lib;libminiupnpcplus.lib;Iphlpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) HighestAvailable @@ -163,14 +163,14 @@ xcopy /E /Y $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configurat Level3 Disabled - USING_STATIC_LIBICONV;CURL_STATICLIB;BOOST_ALL_NO_LIB;DEBUG;_WIN32_WINNT=0x0501;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + USING_STATIC_LIBICONV;MINIUPNP_STATICLIB;CURL_STATICLIB;BOOST_ALL_NO_LIB;DEBUG;_WIN32_WINNT=0x0501;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true 4345;4996;4267 Console true - libiconvd.lib;libeay32.lib;ssleay32.lib;libcurl_a_debug.lib;libboost_date_time-vc141-mt-gd-1_64.lib;libboost_system-vc141-mt-gd-1_64.lib;libboost_thread-vc141-mt-gd-1_64.lib;libboost_program_options-vc141-mt-gd-1_64.lib;libboost_filesystem-vc141-mt-gd-1_64.lib;libiconvplus.lib;libkfather.lib;libexecuteplus.lib;libcryptoplus.lib;libasiotap.lib;libfscp.lib;libmongooseplus.lib;libfreelan.lib;Iphlpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + libiconvd.lib;libeay32.lib;ssleay32.lib;libcurl_a_debug.lib;libboost_date_time-vc141-mt-gd-1_64.lib;libboost_system-vc141-mt-gd-1_64.lib;libboost_thread-vc141-mt-gd-1_64.lib;libboost_program_options-vc141-mt-gd-1_64.lib;libboost_filesystem-vc141-mt-gd-1_64.lib;libiconvplus.lib;libkfather.lib;libexecuteplus.lib;libcryptoplus.lib;libasiotap.lib;libfscp.lib;libmongooseplus.lib;libfreelan.lib;miniupnpcd.lib;libminiupnpcplus.lib;Iphlpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) HighestAvailable @@ -203,7 +203,7 @@ xcopy /E /Y $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configurat MaxSpeed true true - USING_STATIC_LIBICONV;CURL_STATICLIB;BOOST_ALL_NO_LIB;_WIN32_WINNT=0x0501;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + USING_STATIC_LIBICONV;MINIUPNP_STATICLIB;CURL_STATICLIB;BOOST_ALL_NO_LIB;_WIN32_WINNT=0x0501;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true 4345;4996;4267 @@ -212,7 +212,7 @@ xcopy /E /Y $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configurat true true true - libiconv.lib;libeay32.lib;ssleay32.lib;libcurl_a.lib;libboost_date_time-vc141-mt-1_64.lib;libboost_system-vc141-mt-1_64.lib;libboost_thread-vc141-mt-1_64.lib;libboost_program_options-vc141-mt-1_64.lib;libboost_filesystem-vc141-mt-1_64.lib;libiconvplus.lib;libkfather.lib;libexecuteplus.lib;libcryptoplus.lib;libasiotap.lib;libfscp.lib;libmongooseplus.lib;libfreelan.lib;Iphlpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + libiconv.lib;libeay32.lib;ssleay32.lib;libcurl_a.lib;libboost_date_time-vc141-mt-1_64.lib;libboost_system-vc141-mt-1_64.lib;libboost_thread-vc141-mt-1_64.lib;libboost_program_options-vc141-mt-1_64.lib;libboost_filesystem-vc141-mt-1_64.lib;libiconvplus.lib;libkfather.lib;libexecuteplus.lib;libcryptoplus.lib;libasiotap.lib;libfscp.lib;libmongooseplus.lib;libfreelan.lib;miniupnpc.lib;libminiupnpcplus.lib;Iphlpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) HighestAvailable @@ -245,7 +245,7 @@ xcopy /E /Y $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configurat MaxSpeed true true - USING_STATIC_LIBICONV;CURL_STATICLIB;BOOST_ALL_NO_LIB;_WIN32_WINNT=0x0501;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + USING_STATIC_LIBICONV;MINIUPNP_STATICLIB;CURL_STATICLIB;BOOST_ALL_NO_LIB;_WIN32_WINNT=0x0501;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true 4345;4996;4267 @@ -254,7 +254,7 @@ xcopy /E /Y $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configurat true true true - libiconv.lib;libeay32.lib;ssleay32.lib;libcurl_a.lib;libboost_date_time-vc141-mt-1_64.lib;libboost_system-vc141-mt-1_64.lib;libboost_thread-vc141-mt-1_64.lib;libboost_program_options-vc141-mt-1_64.lib;libboost_filesystem-vc141-mt-1_64.lib;libiconvplus.lib;libkfather.lib;libexecuteplus.lib;libcryptoplus.lib;libasiotap.lib;libfscp.lib;libmongooseplus.lib;libfreelan.lib;Iphlpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + libiconv.lib;libeay32.lib;ssleay32.lib;libcurl_a.lib;libboost_date_time-vc141-mt-1_64.lib;libboost_system-vc141-mt-1_64.lib;libboost_thread-vc141-mt-1_64.lib;libboost_program_options-vc141-mt-1_64.lib;libboost_filesystem-vc141-mt-1_64.lib;libiconvplus.lib;libkfather.lib;libexecuteplus.lib;libcryptoplus.lib;libasiotap.lib;libfscp.lib;libmongooseplus.lib;libfreelan.lib;miniupnpc.lib;libminiupnpcplus.lib;Iphlpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) HighestAvailable @@ -282,4 +282,4 @@ xcopy /E /Y $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configurat - \ No newline at end of file + diff --git a/apps/freelan/src/configuration_helper.cpp b/apps/freelan/src/configuration_helper.cpp index e32afd51..4394fcaa 100644 --- a/apps/freelan/src/configuration_helper.cpp +++ b/apps/freelan/src/configuration_helper.cpp @@ -291,6 +291,7 @@ po::options_description get_fscp_options() ("fscp.never_contact", po::value >()->multitoken()->zero_tokens()->default_value(std::vector(), ""), "A network address to avoid when dynamically contacting hosts.") ("fscp.cipher_suite_capability", po::value >()->multitoken()->zero_tokens()->default_value(fscp::get_default_cipher_suites(), ""), "A cipher suite to allow.") ("fscp.elliptic_curve_capability", po::value >()->multitoken()->zero_tokens()->default_value(fscp::get_default_elliptic_curves(), ""), "A elliptic curve to allow.") + ("fscp.upnp_enabled", po::value()->default_value(true, "yes"), "Enable UPnP.") ; return result; diff --git a/appveyor.yml b/appveyor.yml index aa9686b5..bbb44346 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -28,6 +28,7 @@ build_script: - '%PYTHON_ROOT%\scripts\teapot.exe build iconv' - '%PYTHON_ROOT%\scripts\teapot.exe build openssl' - '%PYTHON_ROOT%\scripts\teapot.exe build curl' + - '%PYTHON_ROOT%\scripts\teapot.exe build miniupnpc' - 'mkdir third-party\install\%PLATFORM%\%CONFIGURATION%\include\boost-1_64\boost' - 'xcopy /S %BOOST_ROOT%\boost\* third-party\install\%PLATFORM%\%CONFIGURATION%\include\boost-1_64\boost\' - 'xcopy /S %BOOST_ROOT%\lib%ARCH_BITS%-msvc-14.1\*vc141-mt-*.lib third-party\install\%PLATFORM%\%CONFIGURATION%\lib\' diff --git a/freelan-all.sln b/freelan-all.sln index ce991140..2e2946bc 100644 --- a/freelan-all.sln +++ b/freelan-all.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Express 2013 for Windows Desktop -VisualStudioVersion = 12.0.30501.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.16 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libiconvplus", "libs\iconvplus\libiconvplus.vcxproj", "{ACD7B910-1594-4192-9AE1-E805B2F5DB59}" EndProject @@ -47,6 +47,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmongooseplus", "libs\mon {BABD5FDD-D2DC-44FE-B2A4-A21D3DD1F6C2} = {BABD5FDD-D2DC-44FE-B2A4-A21D3DD1F6C2} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libminiupnpcplus", "libs\miniupnpcplus\libminiupnpcplus.vcxproj", "{AC73E1D7-49E7-4A12-8555-588CA931932B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -127,6 +129,14 @@ Global {70266482-33AC-449F-8356-0EC6FA0C1BBD}.Release|Win32.Build.0 = Release|Win32 {70266482-33AC-449F-8356-0EC6FA0C1BBD}.Release|x64.ActiveCfg = Release|x64 {70266482-33AC-449F-8356-0EC6FA0C1BBD}.Release|x64.Build.0 = Release|x64 + {AC73E1D7-49E7-4A12-8555-588CA931932B}.Debug|Win32.ActiveCfg = Debug|Win32 + {AC73E1D7-49E7-4A12-8555-588CA931932B}.Debug|Win32.Build.0 = Debug|Win32 + {AC73E1D7-49E7-4A12-8555-588CA931932B}.Debug|x64.ActiveCfg = Debug|x64 + {AC73E1D7-49E7-4A12-8555-588CA931932B}.Debug|x64.Build.0 = Debug|x64 + {AC73E1D7-49E7-4A12-8555-588CA931932B}.Release|Win32.ActiveCfg = Release|Win32 + {AC73E1D7-49E7-4A12-8555-588CA931932B}.Release|Win32.Build.0 = Release|Win32 + {AC73E1D7-49E7-4A12-8555-588CA931932B}.Release|x64.ActiveCfg = Release|x64 + {AC73E1D7-49E7-4A12-8555-588CA931932B}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/libs/freelan/include/freelan/configuration.hpp b/libs/freelan/include/freelan/configuration.hpp index 767eb9df..b8e1a9f3 100644 --- a/libs/freelan/include/freelan/configuration.hpp +++ b/libs/freelan/include/freelan/configuration.hpp @@ -316,6 +316,11 @@ namespace freelan * \brief The list of allowed elliptic curves. */ fscp::elliptic_curve_list_type elliptic_curve_capabilities; + + /** + * \brief State of UPnP. + */ + bool upnp_enabled; }; /** diff --git a/libs/freelan/libfreelan.vcxproj b/libs/freelan/libfreelan.vcxproj index a987f7c5..1e02fa3c 100644 --- a/libs/freelan/libfreelan.vcxproj +++ b/libs/freelan/libfreelan.vcxproj @@ -112,25 +112,25 @@ $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\lib\ $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\libs\$(ProjectName)\ - $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(IncludePath) + $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(SolutionDir)\libs\miniupnpcplus\include;$(IncludePath) ClCompile $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\lib\ $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\libs\$(ProjectName)\ - $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(IncludePath) + $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(SolutionDir)\libs\miniupnpcplus\include;$(IncludePath) ClCompile $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\lib\ $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\libs\$(ProjectName)\ - $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(IncludePath) + $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(SolutionDir)\libs\miniupnpcplus\include;$(IncludePath) ClCompile $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\lib\ $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\libs\$(ProjectName)\ - $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(IncludePath) + $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(SolutionDir)\libs\miniupnpcplus\include;$(IncludePath) ClCompile @@ -139,7 +139,7 @@ Level3 Disabled - USING_STATIC_LIBICONV;CURL_STATICLIB;BOOST_ALL_NO_LIB;DEBUG;_WIN32_WINNT=0x0501;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + USING_STATIC_LIBICONV;MINIUPNP_STATICLIB;CURL_STATICLIB;BOOST_ALL_NO_LIB;DEBUG;_WIN32_WINNT=0x0501;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true $(ProjectDir)\include\freelan 4345;4800;4996;4267 @@ -168,7 +168,7 @@ Level3 Disabled - USING_STATIC_LIBICONV;CURL_STATICLIB;BOOST_ALL_NO_LIB;DEBUG;_WIN32_WINNT=0x0501;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + USING_STATIC_LIBICONV;MINIUPNP_STATICLIB;CURL_STATICLIB;BOOST_ALL_NO_LIB;DEBUG;_WIN32_WINNT=0x0501;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true $(ProjectDir)\include\freelan 4345;4800;4996;4267 @@ -199,7 +199,7 @@ MaxSpeed true true - USING_STATIC_LIBICONV;CURL_STATICLIB;BOOST_ALL_NO_LIB;_WIN32_WINNT=0x0501;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + USING_STATIC_LIBICONV;MINIUPNP_STATICLIB;CURL_STATICLIB;BOOST_ALL_NO_LIB;_WIN32_WINNT=0x0501;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) true $(ProjectDir)\include\freelan 4345;4800;4996;4267 @@ -231,7 +231,7 @@ MaxSpeed true true - USING_STATIC_LIBICONV;CURL_STATICLIB;BOOST_ALL_NO_LIB;_WIN32_WINNT=0x0501;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + USING_STATIC_LIBICONV;MINIUPNP_STATICLIB;CURL_STATICLIB;BOOST_ALL_NO_LIB;_WIN32_WINNT=0x0501;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) true $(ProjectDir)\include\freelan 4345;4800;4996;4267 @@ -258,4 +258,4 @@ - \ No newline at end of file + diff --git a/libs/freelan/src/core.cpp b/libs/freelan/src/core.cpp index 0c4c8363..76463cdf 100644 --- a/libs/freelan/src/core.cpp +++ b/libs/freelan/src/core.cpp @@ -671,6 +671,15 @@ namespace freelan // Let's open the server. m_fscp_server->open(listen_endpoint); + if (m_configuration.fscp.upnp_enabled) + { +#ifdef USE_UPNP + m_fscp_server->upnp_punch_hole(listen_endpoint.port()); +#else + m_logger(fscp::log_level::error) << "UPnP support is not compiled in this version"; +#endif + } + #ifdef LINUX if (!m_configuration.fscp.listen_on_device.empty()) { diff --git a/libs/fscp/include/fscp/server.hpp b/libs/fscp/include/fscp/server.hpp index 067b15df..91f4b38c 100644 --- a/libs/fscp/include/fscp/server.hpp +++ b/libs/fscp/include/fscp/server.hpp @@ -53,6 +53,10 @@ #include "peer_session.hpp" #include "logger.hpp" +#ifdef USE_UPNP +#include "miniupnpcplus/upnp_device.hpp" +#endif + #include #include #include @@ -355,6 +359,14 @@ namespace fscp */ void close(); +#ifdef USE_UPNP + /** + * \brief Use UPnP to punch hole NAT. + * \param port local port. + */ + void upnp_punch_hole(uint16_t port); +#endif + /** * \brief Greet an host. * \param target The target to greet. @@ -1503,6 +1515,10 @@ namespace fscp private: // Misc +#ifdef USE_UPNP + boost::shared_ptr m_upnp; +#endif + friend std::ostream& operator<<(std::ostream& os, presentation_status_type status) { switch (status) diff --git a/libs/fscp/libfscp.vcxproj b/libs/fscp/libfscp.vcxproj index b9ffe9b7..8c6413f1 100644 --- a/libs/fscp/libfscp.vcxproj +++ b/libs/fscp/libfscp.vcxproj @@ -103,25 +103,25 @@ $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\lib\ $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\libs\$(ProjectName)\ - $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(IncludePath) + $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(SolutionDir)\libs\miniupnpcplus\include;$(IncludePath) ClCompile $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\lib\ $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\libs\$(ProjectName)\ - $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(IncludePath) + $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(SolutionDir)\libs\miniupnpcplus\include;$(IncludePath) ClCompile $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\lib\ $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\libs\$(ProjectName)\ - $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(IncludePath) + $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(SolutionDir)\libs\miniupnpcplus\include;$(IncludePath) ClCompile $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\lib\ $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\libs\$(ProjectName)\ - $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(IncludePath) + $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\executeplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(SolutionDir)\libs\miniupnpcplus\include;$(IncludePath) ClCompile @@ -130,7 +130,7 @@ Level3 Disabled - USING_STATIC_LIBICONV;CURL_STATICLIB;BOOST_ALL_NO_LIB;DEBUG;_WIN32_WINNT=0x0501;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + USING_STATIC_LIBICONV;MINIUPNP_STATICLIB;CURL_STATICLIB;BOOST_ALL_NO_LIB;DEBUG;_WIN32_WINNT=0x0501;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true $(ProjectDir)\include\fscp 4996;4267 @@ -158,7 +158,7 @@ Level3 Disabled - USING_STATIC_LIBICONV;CURL_STATICLIB;BOOST_ALL_NO_LIB;DEBUG;_WIN32_WINNT=0x0501;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + USING_STATIC_LIBICONV;MINIUPNP_STATICLIB;CURL_STATICLIB;BOOST_ALL_NO_LIB;DEBUG;_WIN32_WINNT=0x0501;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true $(ProjectDir)\include\fscp 4996;4267 @@ -188,7 +188,7 @@ MaxSpeed true true - USING_STATIC_LIBICONV;CURL_STATICLIB;BOOST_ALL_NO_LIB;_WIN32_WINNT=0x0501;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + USING_STATIC_LIBICONV;MINIUPNP_STATICLIB;CURL_STATICLIB;BOOST_ALL_NO_LIB;_WIN32_WINNT=0x0501;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) true $(ProjectDir)\include\fscp 4996;4267 @@ -220,7 +220,7 @@ MaxSpeed true true - USING_STATIC_LIBICONV;CURL_STATICLIB;BOOST_ALL_NO_LIB;_WIN32_WINNT=0x0501;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + USING_STATIC_LIBICONV;MINIUPNP_STATICLIB;CURL_STATICLIB;BOOST_ALL_NO_LIB;_WIN32_WINNT=0x0501;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) true $(ProjectDir)\include\fscp 4996;4267 @@ -247,4 +247,4 @@ - \ No newline at end of file + diff --git a/libs/fscp/src/server.cpp b/libs/fscp/src/server.cpp index 57f35967..4dd707bb 100644 --- a/libs/fscp/src/server.cpp +++ b/libs/fscp/src/server.cpp @@ -318,6 +318,39 @@ namespace fscp m_socket.close(); } +#ifdef USE_UPNP + void server::upnp_punch_hole(uint16_t port) + { + try + { + std::ostringstream oss; + oss << port; + + if(m_upnp.get() == nullptr) + { + m_logger(log_level::information) << "Discovering UPnP IGD gateways."; + m_upnp.reset(new miniupnpcplus::upnp_device(2000)); + + // same external port as local port + m_logger(log_level::trace) << "Try to register UPnP port mapping: " << + m_upnp->get_external_ip() << ":" << port << " -> " << m_upnp->get_lan_ip() << + ":" << port; + m_upnp->register_port_mapping(miniupnpcplus::UDP, oss.str(), oss.str(), + "FreeLAN peer"); + m_logger(log_level::information) << "UPnP port mapping registered: " << + m_upnp->get_external_ip() << ":" << port << " -> " << m_upnp->get_lan_ip() << + ":" << port; + + // TODO retry if port is already taken + } + } + catch (const boost::system::system_error& ex) + { + m_logger(log_level::error) << "UPnP discovery/port mapping failed: " << ex.what(); + } + } +#endif + void server::async_greet(const ep_type& target, duration_handler_type handler, const boost::posix_time::time_duration& timeout) { m_greet_strand.post(boost::bind(&server::do_greet, this, normalize(target), handler, timeout)); diff --git a/libs/miniupnpcplus/SConscript b/libs/miniupnpcplus/SConscript new file mode 100644 index 00000000..bc8e26e1 --- /dev/null +++ b/libs/miniupnpcplus/SConscript @@ -0,0 +1,17 @@ +import os +import sys + + +Import('env dirs name') + +env = env.Clone() + +local_include_dir = Dir(os.path.join('include', name)) +env.Prepend(CPPPATH=[local_include_dir]) + +sources = env.RGlob('src', '*.cpp') + +includes = env.RInstall(dirs['root'], local_include_dir, ['*.hpp']) +library = env.StaticLibrary(target=os.path.join(str(dirs['lib']), name), source=sources) + +Return('library includes') diff --git a/libs/miniupnpcplus/include/miniupnpcplus/error.hpp b/libs/miniupnpcplus/include/miniupnpcplus/error.hpp new file mode 100644 index 00000000..097fc7fa --- /dev/null +++ b/libs/miniupnpcplus/include/miniupnpcplus/error.hpp @@ -0,0 +1,102 @@ +/* + * libminiupnpcplus - C++ portable miniupnpc wrapper library. + * Copyright (C) 2010-2017 Julien Kauffmann + * + * This file is part of libminiupnpcplus. + * + * libfscp is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * libfscp is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + * + * If you intend to use libfscp in a commercial software, please + * contact me : we may arrange this for a small fee or no fee at all, + * depending on the nature of your project. + */ + +/** + * \file error.hpp + * \author Julien Kauffmann + * \brief The errors. + */ + +#pragma once + +#include +#include + +#include + +namespace miniupnpcplus +{ + /** + * @brief Get the default server error category. + * @return The default server error category instance. + * + * @warning The first call to this function is thread-safe only starting with C++11. + */ + const boost::system::error_category& miniupnpcplus_category(); + + /** + * @brief Create an error_code instance for the given error. + * @param error The error. + * @return The error_code instance. + */ + inline boost::system::error_code make_error_code(int error) + { + return boost::system::error_code(error, miniupnpcplus_category()); + } + + /** + * @brief Create an error_condition instance for the given error. + * @param error The error. + * @return The error_condition instance. + */ + inline boost::system::error_condition make_error_condition(int error) + { + return boost::system::error_condition(error, miniupnpcplus_category()); + } + + /** + * @brief A server error category. + */ + class miniupnpcplus_category_impl : public boost::system::error_category + { + public: + /** + * @brief Get the name of the category. + * @return The name of the category. + */ + virtual const char* name() const throw(); + + /** + * @brief Get the error message for a given error. + * @param ev The error numeric value. + * @return The message associated to the error. + */ + virtual std::string message(int ev) const; + }; +} + diff --git a/libs/miniupnpcplus/include/miniupnpcplus/miniupnpcplus.hpp b/libs/miniupnpcplus/include/miniupnpcplus/miniupnpcplus.hpp new file mode 100644 index 00000000..7ebdfda7 --- /dev/null +++ b/libs/miniupnpcplus/include/miniupnpcplus/miniupnpcplus.hpp @@ -0,0 +1,49 @@ +/* + * libminiupnpcplus - C++ portable miniupnpc wrapper library. + * Copyright (C) 2010-2017 Julien Kauffmann + * + * This file is part of libminiupnpcplus. + * + * libfscp is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * libfscp is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + * + * If you intend to use libfscp in a commercial software, please + * contact me : we may arrange this for a small fee or no fee at all, + * depending on the nature of your project. + */ + +/** + * \file miniupnpcplus.hpp + * \author Sebastien Vincent + * \brief UPnP functions. + */ + +#pragma once + +namespace miniupnpcplus +{ +} diff --git a/libs/miniupnpcplus/include/miniupnpcplus/upnp_device.hpp b/libs/miniupnpcplus/include/miniupnpcplus/upnp_device.hpp new file mode 100644 index 00000000..1db1dcf5 --- /dev/null +++ b/libs/miniupnpcplus/include/miniupnpcplus/upnp_device.hpp @@ -0,0 +1,162 @@ +/* + * libminiupnpcplus - C++ portable miniupnpc wrapper library. + * Copyright (C) 2010-2017 Julien Kauffmann + * + * This file is part of libminiupnpcplus. + * + * libfscp is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * libfscp is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + * + * If you intend to use libfscp in a commercial software, please + * contact me : we may arrange this for a small fee or no fee at all, + * depending on the nature of your project. + */ + +/** + * \file upnp_device.hpp + * \author Sebastien Vincent + * \brief A UPnP device class. + */ + +#ifndef MINIUPNPCPLUS_UPNP_DEVICE_HPP +#define MINIUPNPCPLUS_UPNP_DEVICE_HPP + +#include +#include +#include + +#include + +#include + +namespace miniupnpcplus +{ + /** + * \enum transport_protocol + * \brief Transport protocol. + */ + enum transport_protocol + { + UDP, + TCP + }; + + /** + * \brief UPnP mapping information. + */ + struct upnp_mapping + { + enum transport_protocol protocol; + std::string external_port; + std::string lan_port; + std::string description; + }; + + /** + * \class upnp_device + * \brief UPnP device. + */ + class upnp_device : public boost::noncopyable + { + public: + /** + * \brief Constructor. + * \param timeout UPnP discovery timeout in milliseconds. + */ + upnp_device(int timeout); + + /** + * \brief Destructor. + */ + ~upnp_device(); + + /** + * \brief Registers a port mapping to UPnP IGD. + * \param protocol protocol (TCP or UDP). + * \param external_port the external port wanted. + * \param lan_port the local port. + * \param description a description. + */ + void register_port_mapping(enum transport_protocol protocol, + const std::string& external_port, const std::string& lan_port, + const std::string& description); + + /** + * \brief Unregisters a port mapping from UPnP IGD. + * \param protocol protocol (TCP or UDP). + * \param external_port the external port wanted. + */ + void unregister_port_mapping(enum transport_protocol protocol, + const std::string& external_port); + + /** + * \brief Returns external (WAN) IP address. + * \return external (WAN) IP address. + */ + std::string get_external_ip() const; + + /** + * \brief Returns LAN IP address. + * \return LAN IP address. + */ + std::string get_lan_ip() const; + + private: + /** + * \brief Underlying miniupnpc library pointer. + */ + std::unique_ptr m_upnp; + + /** + * \brief UPnP data. + */ + struct IGDdatas m_upnp_data; + + /** + * \brief UPnP URLs. + */ + struct UPNPUrls m_upnp_urls; + + /** + * \brief LAN address. + */ + std::string m_lan_address; + + /** + * \brief External WAN address. + */ + std::string m_wan_address; + + /** + * \brief List of UPnP mappings. + */ + std::list m_mappings; + }; +} /* namespace miniupnpcplus */ + +#endif /* MINIUPNPCPLUS_UPNP_DEVICE_HPP */ + diff --git a/libs/miniupnpcplus/libminiupnpcplus.vcxproj b/libs/miniupnpcplus/libminiupnpcplus.vcxproj new file mode 100644 index 00000000..9221e9f5 --- /dev/null +++ b/libs/miniupnpcplus/libminiupnpcplus.vcxproj @@ -0,0 +1,227 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + + + {AC73E1D7-49E7-4A12-8555-588CA931932B} + Win32Proj + libminiupnpcplus + 10.0.15063.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\miniupnpcplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(IncludePath) + $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\lib\ + $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\libs\$(ProjectName)\ + ClCompile + + + $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\miniupnpcplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(IncludePath) + $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\lib\ + $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\libs\$(ProjectName)\ + ClCompile + + + $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\miniupnpcplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(IncludePath) + $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\lib\ + $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\libs\$(ProjectName)\ + ClCompile + + + $(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include;$(SolutionDir)\third-party\install\$(PlatformShortName)\$(Configuration)\include\boost-1_64;$(SolutionDir)\libs\asiotap\include;$(SolutionDir)\libs\cryptoplus\include;$(SolutionDir)\libs\miniupnpcplus\include;$(SolutionDir)\libs\freelan\include;$(SolutionDir)\libs\fscp\include;$(SolutionDir)\libs\iconvplus\include;$(SolutionDir)\libs\kfather\include;$(SolutionDir)\libs\mongooseplus\include;$(IncludePath) + $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\lib\ + $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\libs\$(ProjectName)\ + ClCompile + + + + + + Level3 + Disabled + USING_STATIC_LIBICONV;MINIUPNP_STATICLIB;CURL_STATICLIB;BOOST_ALL_NO_LIB;DEBUG;TAP_ID="tap0901";_WIN32_WINNT=0x0600;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + $(ProjectDir)\include\miniupnpcplus + 4996;4396 + + + Windows + true + + + + + + + + + C:\Python27\python.exe $(SolutionDir)\defines.py $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\include\defines.hpp + Generating the common defines header. + $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\include\defines.hpp + $(SolutionDir)\VERSION;$(SolutionDir)\defines.hpp.template + + + + + + + Level3 + Disabled + USING_STATIC_LIBICONV;MINIUPNP_STATICLIB;CURL_STATICLIB;BOOST_ALL_NO_LIB;DEBUG;TAP_ID="tap0901";_WIN32_WINNT=0x0600;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + $(ProjectDir)\include\miniupnpcplus + 4996;4396 + + + Windows + true + + + + + + + + + C:\Python27\python.exe $(SolutionDir)\defines.py $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\include\defines.hpp + Generating the common defines header. + $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\include\defines.hpp + $(SolutionDir)\VERSION;$(SolutionDir)\defines.hpp.template + + + + + Level3 + + + MaxSpeed + true + true + USING_STATIC_LIBICONV;MINIUPNP_STATICLIB;CURL_STATICLIB;BOOST_ALL_NO_LIB;TAP_ID="tap0901";_WIN32_WINNT=0x0600;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + $(ProjectDir)\include\miniupnpcplus + 4996;4396 + + + Windows + true + true + true + + + + + + + + + C:\Python27\python.exe $(SolutionDir)\defines.py $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\include\defines.hpp + Generating the common defines header. + $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\include\defines.hpp + $(SolutionDir)\VERSION;$(SolutionDir)\defines.hpp.template + + + + + Level3 + + + MaxSpeed + true + true + USING_STATIC_LIBICONV;MINIUPNP_STATICLIB;CURL_STATICLIB;BOOST_ALL_NO_LIB;TAP_ID="tap0901";_WIN32_WINNT=0x0600;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + $(ProjectDir)\include\miniupnpcplus + 4996;4396 + + + Windows + true + true + true + + + + + + + + + C:\Python27\python.exe $(SolutionDir)\defines.py $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\include\defines.hpp + Generating the common defines header. + $(SolutionDir)\build\$(PlatformShortName)\$(Configuration)\include\defines.hpp + $(SolutionDir)\VERSION;$(SolutionDir)\defines.hpp.template + + + + + + diff --git a/libs/miniupnpcplus/libminiupnpcplus.vcxproj.filters b/libs/miniupnpcplus/libminiupnpcplus.vcxproj.filters new file mode 100644 index 00000000..c9c3ea53 --- /dev/null +++ b/libs/miniupnpcplus/libminiupnpcplus.vcxproj.filters @@ -0,0 +1,39 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + diff --git a/libs/miniupnpcplus/src/error.cpp b/libs/miniupnpcplus/src/error.cpp new file mode 100644 index 00000000..56fdcaa6 --- /dev/null +++ b/libs/miniupnpcplus/src/error.cpp @@ -0,0 +1,67 @@ +/* + * libminiupnpcplus - A portable execution library. + * Copyright (C) 2010-2017 Julien KAUFFMANN + * + * This file is part of libminiupnpcplus. + * + * libminiupnpcplus is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * libminiupnpcplus is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + * + * If you intend to use libminiupnpcplus in a commercial software, please + * contact me : we may arrange this for a small fee or no fee at all, + * depending on the nature of your project. + */ + +/** + * \file error.cpp + * \author Sebastien Vincent + * \brief The errors. + */ + +#include + +#include "error.hpp" + +namespace miniupnpcplus +{ + const boost::system::error_category& miniupnpcplus_category() + { + static miniupnpcplus_category_impl instance; + + return instance; + } + + const char* miniupnpcplus_category_impl::name() const throw() + { + return "miniupnpcplus::error"; + } + + std::string miniupnpcplus_category_impl::message(int ev) const + { + return strupnperror(ev); + } +} diff --git a/libs/miniupnpcplus/src/miniupnpcplus.cpp b/libs/miniupnpcplus/src/miniupnpcplus.cpp new file mode 100644 index 00000000..a11e6d4f --- /dev/null +++ b/libs/miniupnpcplus/src/miniupnpcplus.cpp @@ -0,0 +1,49 @@ +/* + * libminiupnpcplus - C++ portable miniupnpc wrapper library. + * Copyright (C) 2010-2017 Julien Kauffmann + * + * This file is part of libminiupnpcplus. + * + * libfscp is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * libfscp is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + * + * If you intend to use libfscp in a commercial software, please + * contact me : we may arrange this for a small fee or no fee at all, + * depending on the nature of your project. + */ + +/** + * \file miniupnpcplus.cpp + * \author Julien KAUFFMANN + * \brief Execution functions. + */ + +#include "miniupnpcplus.hpp" + +namespace miniupnpcplus +{ +} diff --git a/libs/miniupnpcplus/src/upnp_device.cpp b/libs/miniupnpcplus/src/upnp_device.cpp new file mode 100644 index 00000000..22f331e6 --- /dev/null +++ b/libs/miniupnpcplus/src/upnp_device.cpp @@ -0,0 +1,142 @@ +/** + * \file upnp_device.cpp + * \author Sebastien Vincent + * \brief A UPnP device class. + */ + +#include + +#include + +#include "upnp_device.hpp" +#include "error.hpp" + +namespace miniupnpcplus +{ + upnp_device::upnp_device(int timeout) + : m_upnp(nullptr, freeUPNPDevlist) + { + int error = 0; + char lan[256]; + char wan[256]; + +#if MINIUPNPC_API_VERSION < 14 + m_upnp.reset(upnpDiscover(timeout, nullptr, nullptr, 0, 0, &error)); +#else + m_upnp.reset(upnpDiscover(timeout, nullptr, nullptr, 0, 0, 2, &error)); +#endif + if(!m_upnp) + { + boost::system::error_code ec = boost::system::error_code(error, + miniupnpcplus::miniupnpcplus_category()); + throw boost::system::system_error(ec); + } + + int status = UPNP_GetValidIGD(m_upnp.get(), &m_upnp_urls, &m_upnp_data, + lan, sizeof(lan)); + + if(status != 1) + { + // no IGD gateway on LAN + FreeUPNPUrls(&m_upnp_urls); + boost::system::error_code ec = boost::system::error_code(-1, + miniupnpcplus::miniupnpcplus_category()); + throw boost::system::system_error(ec); + } + + m_lan_address = std::string(lan); + + error = UPNP_GetExternalIPAddress(m_upnp_urls.controlURL, + m_upnp_data.first.servicetype, wan); + + if(error) + { + // problem retrieving WAN IP address + FreeUPNPUrls(&m_upnp_urls); + + boost::system::error_code ec = boost::system::error_code(error, + miniupnpcplus::miniupnpcplus_category()); + throw boost::system::system_error(ec); + } + + m_wan_address = std::string(wan); + } + + upnp_device::~upnp_device() + { + // unregister all mappings, do not use unregister_port_mapping here + // because it will modify the list + for(auto& mapping : m_mappings) + { + UPNP_DeletePortMapping(m_upnp_urls.controlURL, + m_upnp_data.first.servicetype, mapping.external_port.c_str(), + (mapping.protocol == TCP ? "TCP" : "UDP"), nullptr); + } + + m_mappings.clear(); + FreeUPNPUrls(&m_upnp_urls); + } + + void upnp_device::register_port_mapping(enum transport_protocol protocol, + const std::string& external_port, const std::string& lan_port, + const std::string& description) + { + // last parameters ("0" means the lease will be as long as possible + int error = UPNP_AddPortMapping(m_upnp_urls.controlURL, + m_upnp_data.first.servicetype, external_port.c_str(), lan_port.c_str(), + m_lan_address.c_str(), description.c_str(), + (protocol == TCP ? "TCP" : "UDP"), nullptr, "0"); + + if(error) + { + boost::system::error_code ec = boost::system::error_code(error, + miniupnpcplus::miniupnpcplus_category()); + throw boost::system::system_error(ec); + struct upnp_mapping mapping; + } + + struct upnp_mapping mapping; + mapping.description = description; + mapping.protocol = protocol; + mapping.external_port = external_port; + mapping.lan_port = lan_port; + m_mappings.push_back(mapping); + } + + void upnp_device::unregister_port_mapping(enum transport_protocol protocol, + const std::string& external_port) + { + int error = UPNP_DeletePortMapping(m_upnp_urls.controlURL, + m_upnp_data.first.servicetype, external_port.c_str(), + (protocol == TCP ? "TCP" : "UDP"), nullptr); + + if(error) + { + boost::system::error_code ec = boost::system::error_code(error, + miniupnpcplus::miniupnpcplus_category()); + throw boost::system::system_error(ec); + } + + for(std::list::iterator it = m_mappings.begin() ; + it != m_mappings.end() ; ++it) + { + if(it->external_port == external_port && + it->protocol == protocol) + { + m_mappings.erase(it); + break; + } + } + } + + std::string upnp_device::get_external_ip() const + { + return m_wan_address; + } + + std::string upnp_device::get_lan_ip() const + { + return m_lan_address; + } +} + diff --git a/packaging/docker/freelan/Dockerfile b/packaging/docker/freelan/Dockerfile index d9798aeb..d6640b9a 100644 --- a/packaging/docker/freelan/Dockerfile +++ b/packaging/docker/freelan/Dockerfile @@ -4,8 +4,8 @@ FROM debian:stretch RUN apt-get update # Install dependencies -ENV DEPENDENCIES libssl1.1 libboost-system1.62.0 libboost-thread1.62.0 libboost-filesystem1.62.0 libboost-date-time1.62.0 libboost-program-options1.62.0 libboost-iostreams1.62.0 libcurl4-openssl-dev -ENV BUILD_DEPENDENCIES g++ git scons libssl-dev libboost-system-dev libboost-thread-dev libboost-filesystem-dev libboost-date-time-dev libboost-program-options-dev libboost-iostreams-dev +ENV DEPENDENCIES libssl1.1 libboost-system1.62.0 libboost-thread1.62.0 libboost-filesystem1.62.0 libboost-date-time1.62.0 libboost-program-options1.62.0 libboost-iostreams1.62.0 libcurl4-openssl-dev libminiupnpc10 +ENV BUILD_DEPENDENCIES g++ git scons libssl-dev libboost-system-dev libboost-thread-dev libboost-filesystem-dev libboost-date-time-dev libboost-program-options-dev libboost-iostreams-dev libminiupnpc-dev RUN apt-get install -y $DEPENDENCIES $BUILD_DEPENDENCIES RUN apt-get clean diff --git a/provisioning/roles/freelan-build/tasks/main.yml b/provisioning/roles/freelan-build/tasks/main.yml index d53b8b6f..2627c9c9 100644 --- a/provisioning/roles/freelan-build/tasks/main.yml +++ b/provisioning/roles/freelan-build/tasks/main.yml @@ -8,6 +8,7 @@ - libboost-all-dev - libssl-dev - libcurl4-openssl-dev + - libminiupnpc-dev tags: - build sudo: True diff --git a/samples/fscp/client/SConscript b/samples/fscp/client/SConscript index b77fd312..cea50788 100644 --- a/samples/fscp/client/SConscript +++ b/samples/fscp/client/SConscript @@ -1,6 +1,7 @@ import os import sys +Import('env dirs name') libraries = [ 'fscp', @@ -9,6 +10,12 @@ libraries = [ 'crypto', ] +if env.upnp == 'yes': + libraries.extend([ + 'miniupnpcplus', + 'miniupnpc', + ]) + if sys.platform.startswith('darwin'): libraries.extend([ 'boost_thread-mt', @@ -23,8 +30,6 @@ if sys.platform.startswith('linux'): 'pthread', ]) -Import('env dirs name') - env = env.Clone() env.Append(LIBS=libraries) samples = env.Program(target=os.path.join(str(dirs['bin']), name), source=env.RGlob('.', ['*.cpp'])) diff --git a/samples/fscp/schat/SConscript b/samples/fscp/schat/SConscript index b77fd312..cea50788 100644 --- a/samples/fscp/schat/SConscript +++ b/samples/fscp/schat/SConscript @@ -1,6 +1,7 @@ import os import sys +Import('env dirs name') libraries = [ 'fscp', @@ -9,6 +10,12 @@ libraries = [ 'crypto', ] +if env.upnp == 'yes': + libraries.extend([ + 'miniupnpcplus', + 'miniupnpc', + ]) + if sys.platform.startswith('darwin'): libraries.extend([ 'boost_thread-mt', @@ -23,8 +30,6 @@ if sys.platform.startswith('linux'): 'pthread', ]) -Import('env dirs name') - env = env.Clone() env.Append(LIBS=libraries) samples = env.Program(target=os.path.join(str(dirs['bin']), name), source=env.RGlob('.', ['*.cpp'])) diff --git a/samples/miniupnpcplus/mapping/.gitignore b/samples/miniupnpcplus/mapping/.gitignore new file mode 100644 index 00000000..35b5d408 --- /dev/null +++ b/samples/miniupnpcplus/mapping/.gitignore @@ -0,0 +1,2 @@ +mapping +mappingd diff --git a/samples/miniupnpcplus/mapping/SConscript b/samples/miniupnpcplus/mapping/SConscript new file mode 100644 index 00000000..a3aa3d36 --- /dev/null +++ b/samples/miniupnpcplus/mapping/SConscript @@ -0,0 +1,17 @@ +import os +import sys + + +libraries = [ + 'miniupnpcplus', + 'miniupnpc', + 'boost_system', +] + +Import('env dirs name') + +env = env.Clone() +env.Append(LIBS=libraries) +samples = env.Program(target=os.path.join(str(dirs['bin']), name), source=env.RGlob('.', ['*.cpp'])) + +Return('samples') diff --git a/samples/miniupnpcplus/mapping/mapping.cpp b/samples/miniupnpcplus/mapping/mapping.cpp new file mode 100644 index 00000000..71bc52f3 --- /dev/null +++ b/samples/miniupnpcplus/mapping/mapping.cpp @@ -0,0 +1,42 @@ +/** + * \file mapping.cpp + * \author Sebastien Vincent + * \brief Test the UPnP functions. + */ + +#include + +#include + +int main(int argc, char** argv) +{ + static_cast(argc); + static_cast(argv); + + try + { + miniupnpcplus::upnp_device dev(2000); + std::string tmp; + + std::cout << "UPnP device created" << std::endl; + + dev.register_port_mapping(miniupnpcplus::TCP, "12000", "12000", + "Test miniupnpcplus"); + + std::cout << "UPnP port mapping registered" << std::endl; + + std::cout << "Press any key to continue..." << std::endl; + tmp = std::cin.get(); + + dev.unregister_port_mapping(miniupnpcplus::TCP, "12000"); + std::cout << "UPnP port mapping unregistered" << std::endl; + } + catch (std::exception& ex) + { + std::cerr << "Exception during UPnP: " << ex.what() << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} +