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 /Swiften | |
parent | 6cea7fdfea93e54543c6757909a8fae7348754fc (diff) | |
download | swift-dfccb5703c4d85ab1a54429016b103101bdc54ae.zip swift-dfccb5703c4d85ab1a54429016b103101bdc54ae.tar.bz2 |
File Transfer refactoring.
NAT traversal classes refactoring.
Added beginnings of a NetworkTool.
Diffstat (limited to 'Swiften')
35 files changed, 630 insertions, 783 deletions
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; -}; - -} |