diff options
author | Tobias Markmann <tm@ayena.de> | 2011-05-26 18:46:49 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2011-09-25 17:42:32 (GMT) |
commit | 4f62e5ec4b42929fe3c1a68667e63cb1b7a35509 (patch) | |
tree | 0d19fac3f578dec00ccf3e58930312951e38de89 /Swiften/Network | |
parent | de660b763459cdd707876ec244b6866abca07fa2 (diff) | |
download | swift-4f62e5ec4b42929fe3c1a68667e63cb1b7a35509.zip swift-4f62e5ec4b42929fe3c1a68667e63cb1b7a35509.tar.bz2 |
Google Summer of Code 2011 Project: Adding support for Jingle File Transfers (XEP-0234), Jingle SOCKS5 Bytestreams Transport Method (XEP-0260), Jingle In-Band Bytestreams Transport Method (XEP-0261) and SOCKS5 Bytestreams (XEP-0065).
License: This patch is BSD-licensed, see http://www.opensource.org/licenses/bsd-license.php
Diffstat (limited to 'Swiften/Network')
34 files changed, 1428 insertions, 1 deletions
diff --git a/Swiften/Network/BoostNetworkFactories.cpp b/Swiften/Network/BoostNetworkFactories.cpp index cc80197..c13270f 100644 --- a/Swiften/Network/BoostNetworkFactories.cpp +++ b/Swiften/Network/BoostNetworkFactories.cpp @@ -9,6 +9,7 @@ #include <Swiften/Network/BoostConnectionFactory.h> #include <Swiften/Network/PlatformDomainNameResolver.h> #include <Swiften/Network/BoostConnectionServerFactory.h> +#include <Swiften/Network/PlatformNATTraversalWorker.h> namespace Swift { @@ -17,9 +18,11 @@ BoostNetworkFactories::BoostNetworkFactories(EventLoop* eventLoop) { connectionFactory = new BoostConnectionFactory(ioServiceThread.getIOService(), eventLoop); domainNameResolver = new PlatformDomainNameResolver(eventLoop); connectionServerFactory = new BoostConnectionServerFactory(ioServiceThread.getIOService(), eventLoop); + platformNATTraversalWorker = new PlatformNATTraversalWorker(eventLoop); } BoostNetworkFactories::~BoostNetworkFactories() { + delete platformNATTraversalWorker; delete connectionServerFactory; delete domainNameResolver; delete connectionFactory; diff --git a/Swiften/Network/BoostNetworkFactories.h b/Swiften/Network/BoostNetworkFactories.h index 96bcc6c..a1cf9ae 100644 --- a/Swiften/Network/BoostNetworkFactories.h +++ b/Swiften/Network/BoostNetworkFactories.h @@ -37,11 +37,16 @@ namespace Swift { return connectionServerFactory; } + PlatformNATTraversalWorker* getPlatformNATTraversalWorker() const { + return platformNATTraversalWorker; + } + private: BoostIOServiceThread ioServiceThread; TimerFactory* timerFactory; ConnectionFactory* connectionFactory; DomainNameResolver* domainNameResolver; ConnectionServerFactory* connectionServerFactory; + PlatformNATTraversalWorker* platformNATTraversalWorker; }; } diff --git a/Swiften/Network/DummyConnectionFactory.h b/Swiften/Network/DummyConnectionFactory.h new file mode 100644 index 0000000..e8a294e --- /dev/null +++ b/Swiften/Network/DummyConnectionFactory.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <boost/smart_ptr/make_shared.hpp> + +#include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Network/DummyConnection.h> + +namespace Swift { + +class EventLoop; + +class DummyConnectionFactory : public ConnectionFactory { +public: + DummyConnectionFactory(EventLoop *eventLoop) : eventLoop(eventLoop) {} + virtual ~DummyConnectionFactory() {} + virtual boost::shared_ptr<Connection> createConnection() { + return boost::make_shared<DummyConnection>(eventLoop); + } +private: + EventLoop* eventLoop; +}; + +} diff --git a/Swiften/Network/NATPMPNATTraversalForwardPortRequest.cpp b/Swiften/Network/NATPMPNATTraversalForwardPortRequest.cpp new file mode 100644 index 0000000..69b325c --- /dev/null +++ b/Swiften/Network/NATPMPNATTraversalForwardPortRequest.cpp @@ -0,0 +1,62 @@ +/* + * 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> + +namespace Swift { + +NATPMPNATTraversalForwardPortRequest::NATPMPNATTraversalForwardPortRequest(PlatformNATTraversalForwardPortRequest::PortMapping mapping, PlatformNATTraversalWorker* worker) : PlatformNATTraversalForwardPortRequest(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 new file mode 100644 index 0000000..71d8621 --- /dev/null +++ b/Swiften/Network/NATPMPNATTraversalForwardPortRequest.h @@ -0,0 +1,24 @@ +/* + * 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/PlatformNATTraversalForwardPortRequest.h> + +namespace Swift { + +class NATPMPNATTraversalForwardPortRequest : public PlatformNATTraversalForwardPortRequest { +public: + NATPMPNATTraversalForwardPortRequest(PlatformNATTraversalForwardPortRequest::PortMapping, PlatformNATTraversalWorker*); + virtual ~NATPMPNATTraversalForwardPortRequest(); + + virtual void runBlocking(); + +private: + PlatformNATTraversalForwardPortRequest::PortMapping mapping; +}; + +} diff --git a/Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.cpp b/Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.cpp new file mode 100644 index 0000000..06a21a3 --- /dev/null +++ b/Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.cpp @@ -0,0 +1,64 @@ +/* + * 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> + +namespace Swift { + +NATPMPNATTraversalGetPublicIPRequest::NATPMPNATTraversalGetPublicIPRequest(PlatformNATTraversalWorker* worker) : PlatformNATTraversalGetPublicIPRequest(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 new file mode 100644 index 0000000..6112091 --- /dev/null +++ b/Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.h @@ -0,0 +1,22 @@ +/* + * 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/PlatformNATTraversalGetPublicIPRequest.h> + +namespace Swift { + +class NATPMPNATTraversalGetPublicIPRequest : public PlatformNATTraversalGetPublicIPRequest { +public: + NATPMPNATTraversalGetPublicIPRequest(PlatformNATTraversalWorker*); + virtual ~NATPMPNATTraversalGetPublicIPRequest(); + + //virtual void run(); + virtual void runBlocking(); +}; + +} diff --git a/Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.cpp b/Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.cpp new file mode 100644 index 0000000..c99ac92 --- /dev/null +++ b/Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.cpp @@ -0,0 +1,83 @@ +/* + * 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> + +namespace Swift { + +NATPMPNATTraversalRemovePortForwardingRequest::NATPMPNATTraversalRemovePortForwardingRequest(PlatformNATTraversalRemovePortForwardingRequest::PortMapping mapping, PlatformNATTraversalWorker* worker) : PlatformNATTraversalRemovePortForwardingRequest(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); +} + +HostAddress NATPMPNATTraversalRemovePortForwardingRequest::getLocalClient() { + PlatformNetworkEnvironment env; + + foreach (NetworkInterface::ref iface, env.getNetworkInterfaces()) { + if (!iface->isLoopback()) { + foreach (HostAddress address, iface->getAddresses()) { + if (address.getRawAddress().is_v4()) { + return address; + } + } + } + } + return HostAddress(); +} + +} diff --git a/Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.h b/Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.h new file mode 100644 index 0000000..c4ffcf3 --- /dev/null +++ b/Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.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/PlatformNATTraversalRemovePortForwardingRequest.h> + +namespace Swift { + +class NATPMPNATTraversalRemovePortForwardingRequest : public PlatformNATTraversalRemovePortForwardingRequest { +public: + NATPMPNATTraversalRemovePortForwardingRequest(PlatformNATTraversalRemovePortForwardingRequest::PortMapping, PlatformNATTraversalWorker*); + virtual ~NATPMPNATTraversalRemovePortForwardingRequest(); + + virtual void runBlocking(); + +private: + HostAddress getLocalClient(); + +private: + PlatformNATTraversalRemovePortForwardingRequest::PortMapping mapping; +}; + +} diff --git a/Swiften/Network/NetworkEnvironment.h b/Swiften/Network/NetworkEnvironment.h new file mode 100644 index 0000000..348bdb9 --- /dev/null +++ b/Swiften/Network/NetworkEnvironment.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <vector> + +#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/Network/NetworkInterface.h> + +namespace Swift { + +class NetworkEnvironment { +public: + virtual ~NetworkEnvironment() {}; + virtual std::vector<NetworkInterface::ref> getNetworkInterfaces() = 0; + + boost::signal <void (NetworkInterface::ref)> onNetworkInterfaceChange; +}; + +} diff --git a/Swiften/Network/NetworkFactories.h b/Swiften/Network/NetworkFactories.h index d0d2299..e7d2ff0 100644 --- a/Swiften/Network/NetworkFactories.h +++ b/Swiften/Network/NetworkFactories.h @@ -11,6 +11,7 @@ namespace Swift { class ConnectionFactory; class DomainNameResolver; class ConnectionServerFactory; + class PlatformNATTraversalWorker; /** * An interface collecting network factories. @@ -23,5 +24,6 @@ namespace Swift { virtual ConnectionFactory* getConnectionFactory() const = 0; virtual DomainNameResolver* getDomainNameResolver() const = 0; virtual ConnectionServerFactory* getConnectionServerFactory() const = 0; + virtual PlatformNATTraversalWorker* getPlatformNATTraversalWorker() const = 0; }; } diff --git a/Swiften/Network/NetworkInterface.h b/Swiften/Network/NetworkInterface.h new file mode 100644 index 0000000..062e1f9 --- /dev/null +++ b/Swiften/Network/NetworkInterface.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <vector> +#include <boost/shared_ptr.hpp> + +#include <Swiften/Network/HostAddress.h> + +namespace Swift { + +class NetworkInterface { +public: + typedef boost::shared_ptr<NetworkInterface> ref; + +public: + enum InterfaceType { + WLAN, + Ethernet, + Mobile, + VPN, + }; + +public: + virtual ~NetworkInterface() {}; + virtual std::vector<HostAddress> getAddresses() = 0; + virtual std::string getName() = 0; + virtual bool isLoopback() = 0; +}; + +} diff --git a/Swiften/Network/PlatformNATTraversalForwardPortRequest.cpp b/Swiften/Network/PlatformNATTraversalForwardPortRequest.cpp new file mode 100644 index 0000000..b28024a --- /dev/null +++ b/Swiften/Network/PlatformNATTraversalForwardPortRequest.cpp @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "PlatformNATTraversalForwardPortRequest.h" + +namespace Swift { + +PlatformNATTraversalForwardPortRequest::PlatformNATTraversalForwardPortRequest(PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker) { +} + +PlatformNATTraversalForwardPortRequest::~PlatformNATTraversalForwardPortRequest() { + +} + +} diff --git a/Swiften/Network/PlatformNATTraversalForwardPortRequest.h b/Swiften/Network/PlatformNATTraversalForwardPortRequest.h new file mode 100644 index 0000000..cb1750c --- /dev/null +++ b/Swiften/Network/PlatformNATTraversalForwardPortRequest.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/Network/HostAddress.h> +#include <Swiften/Network/PlatformNATTraversalRequest.h> + +namespace Swift { + +class PlatformNATTraversalWorker; + +class PlatformNATTraversalForwardPortRequest : public PlatformNATTraversalRequest { +public: + struct PortMapping { + enum Protocol { + TCP, + UDP, + }; + + unsigned int publicPort; + unsigned int localPort; + Protocol protocol; + unsigned long leaseInSeconds; + }; + +public: + PlatformNATTraversalForwardPortRequest(PlatformNATTraversalWorker* worker); + virtual ~PlatformNATTraversalForwardPortRequest(); + + boost::signal<void (boost::optional<PortMapping>)> onResult; +}; + +} diff --git a/Swiften/Network/PlatformNATTraversalGetPublicIPRequest.cpp b/Swiften/Network/PlatformNATTraversalGetPublicIPRequest.cpp new file mode 100644 index 0000000..7a57e30 --- /dev/null +++ b/Swiften/Network/PlatformNATTraversalGetPublicIPRequest.cpp @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "PlatformNATTraversalGetPublicIPRequest.h" + +namespace Swift { + +PlatformNATTraversalGetPublicIPRequest::PlatformNATTraversalGetPublicIPRequest(PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker) { +} + +PlatformNATTraversalGetPublicIPRequest::~PlatformNATTraversalGetPublicIPRequest() { + +} + +} diff --git a/Swiften/Network/PlatformNATTraversalGetPublicIPRequest.h b/Swiften/Network/PlatformNATTraversalGetPublicIPRequest.h new file mode 100644 index 0000000..1cb37fe --- /dev/null +++ b/Swiften/Network/PlatformNATTraversalGetPublicIPRequest.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/Network/HostAddress.h> +#include <Swiften/Network/PlatformNATTraversalRequest.h> + +namespace Swift { + +class PlatformNATTraversalWorker; + +class PlatformNATTraversalGetPublicIPRequest : public PlatformNATTraversalRequest { +public: + PlatformNATTraversalGetPublicIPRequest(PlatformNATTraversalWorker* worker); + virtual ~PlatformNATTraversalGetPublicIPRequest(); + + boost::signal<void (boost::optional<HostAddress>)> onResult; +}; + +} diff --git a/Swiften/Network/PlatformNATTraversalRemovePortForwardingRequest.cpp b/Swiften/Network/PlatformNATTraversalRemovePortForwardingRequest.cpp new file mode 100644 index 0000000..514988e --- /dev/null +++ b/Swiften/Network/PlatformNATTraversalRemovePortForwardingRequest.cpp @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "PlatformNATTraversalRemovePortForwardingRequest.h" + +namespace Swift { + +PlatformNATTraversalRemovePortForwardingRequest::PlatformNATTraversalRemovePortForwardingRequest(PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker) { +} + +PlatformNATTraversalRemovePortForwardingRequest::~PlatformNATTraversalRemovePortForwardingRequest() { + +} + +} diff --git a/Swiften/Network/PlatformNATTraversalRemovePortForwardingRequest.h b/Swiften/Network/PlatformNATTraversalRemovePortForwardingRequest.h new file mode 100644 index 0000000..03427ad --- /dev/null +++ b/Swiften/Network/PlatformNATTraversalRemovePortForwardingRequest.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/Network/HostAddress.h> +#include <Swiften/Network/PlatformNATTraversalRequest.h> + +namespace Swift { + +class PlatformNATTraversalWorker; + +class PlatformNATTraversalRemovePortForwardingRequest : public PlatformNATTraversalRequest { +public: + struct PortMapping { + enum Protocol { + TCP, + UDP, + }; + + unsigned int publicPort; + unsigned int localPort; + Protocol protocol; + unsigned long leaseInSeconds; + }; + +public: + PlatformNATTraversalRemovePortForwardingRequest(PlatformNATTraversalWorker* worker); + virtual ~PlatformNATTraversalRemovePortForwardingRequest(); + + boost::signal<void (boost::optional<bool> /* failure */)> onResult; +}; + +} diff --git a/Swiften/Network/PlatformNATTraversalRequest.cpp b/Swiften/Network/PlatformNATTraversalRequest.cpp new file mode 100644 index 0000000..25e8a32 --- /dev/null +++ b/Swiften/Network/PlatformNATTraversalRequest.cpp @@ -0,0 +1,25 @@ +/* + * 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::run() { + worker->addRequestToQueue(shared_from_this()); +} + +} diff --git a/Swiften/Network/PlatformNATTraversalRequest.h b/Swiften/Network/PlatformNATTraversalRequest.h new file mode 100644 index 0000000..4b760ad --- /dev/null +++ b/Swiften/Network/PlatformNATTraversalRequest.h @@ -0,0 +1,31 @@ +/* + * 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 run(); + virtual void runBlocking() = 0; + +private: + PlatformNATTraversalWorker* worker; +}; + +} diff --git a/Swiften/Network/PlatformNATTraversalWorker.cpp b/Swiften/Network/PlatformNATTraversalWorker.cpp new file mode 100644 index 0000000..a4efedd --- /dev/null +++ b/Swiften/Network/PlatformNATTraversalWorker.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "PlatformNATTraversalWorker.h" + +#include <boost/smart_ptr/make_shared.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/PlatformNATTraversalRemovePortForwardingRequest.h> + +namespace Swift { + +PlatformNATTraversalWorker::PlatformNATTraversalWorker(EventLoop* eventLoop) : backendType(NotYetDecided), eventLoop(eventLoop), stopRequested(false) { + checkAvailableNATTraversalProtocols(); + thread = new boost::thread(boost::bind(&PlatformNATTraversalWorker::run, this)); +} + +PlatformNATTraversalWorker::~PlatformNATTraversalWorker() { + stopRequested = true; + addRequestToQueue(boost::shared_ptr<PlatformNATTraversalRequest>()); + thread->join(); + delete thread; +} + +boost::shared_ptr<PlatformNATTraversalGetPublicIPRequest> 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; + } + return boost::shared_ptr<PlatformNATTraversalGetPublicIPRequest>(); +} + +boost::shared_ptr<PlatformNATTraversalForwardPortRequest> PlatformNATTraversalWorker::createForwardPortRequest(unsigned int localPort, unsigned int publicPort) { + PlatformNATTraversalForwardPortRequest::PortMapping mapping; + mapping.protocol = PlatformNATTraversalForwardPortRequest::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; + } + return boost::shared_ptr<PlatformNATTraversalForwardPortRequest>(); +} + +boost::shared_ptr<PlatformNATTraversalRemovePortForwardingRequest> PlatformNATTraversalWorker::createRemovePortForwardingRequest(unsigned int localPort, unsigned int publicPort) { + PlatformNATTraversalRemovePortForwardingRequest::PortMapping mapping; + mapping.protocol = PlatformNATTraversalRemovePortForwardingRequest::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<PlatformNATTraversalRemovePortForwardingRequest>(); +} + +void PlatformNATTraversalWorker::run() { + while (!stopRequested) { + PlatformNATTraversalRequest::ref request; + { + boost::unique_lock<boost::mutex> lock(queueMutex); + while (queue.empty()) { + queueNonEmpty.wait(lock); + } + request = queue.front(); + queue.pop_front(); + } + // Check whether we don't have a non-null request (used to stop the + // worker) + if (request) { + request->runBlocking(); + } + } +} + +void PlatformNATTraversalWorker::addRequestToQueue(PlatformNATTraversalRequest::ref request) { + { + boost::lock_guard<boost::mutex> lock(queueMutex); + queue.push_back(request); + } + 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 new file mode 100644 index 0000000..7c249cc --- /dev/null +++ b/Swiften/Network/PlatformNATTraversalWorker.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <deque> +#include <boost/optional.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/condition_variable.hpp> + +#include <Swiften/Network/HostAddressPort.h> +#include <Swiften/Network/PlatformNATTraversalRequest.h> + +namespace Swift { + +class EventLoop; +class PlatformNATTraversalGetPublicIPRequest; +class PlatformNATTraversalForwardPortRequest; +class PlatformNATTraversalRemovePortForwardingRequest; + +class PlatformNATTraversalWorker { +private: + enum BackendType { + NotYetDecided, + UPnP, + NATPMP, + None, + }; + +public: + PlatformNATTraversalWorker(EventLoop* eventLoop); + ~PlatformNATTraversalWorker(); + + boost::shared_ptr<PlatformNATTraversalGetPublicIPRequest> createGetPublicIPRequest(); + boost::shared_ptr<PlatformNATTraversalForwardPortRequest> createForwardPortRequest(unsigned int localPort, unsigned int publicPort); + boost::shared_ptr<PlatformNATTraversalRemovePortForwardingRequest> createRemovePortForwardingRequest(unsigned int localPort, unsigned int publicPort); + + 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/PlatformNetworkEnvironment.h b/Swiften/Network/PlatformNetworkEnvironment.h new file mode 100644 index 0000000..c6b945e --- /dev/null +++ b/Swiften/Network/PlatformNetworkEnvironment.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Base/Platform.h> + +#if defined(SWIFTEN_PLATFORM_MACOSX) +#include <Swiften/Network/UnixNetworkEnvironment.h> +namespace Swift { + typedef UnixNetworkEnvironment PlatformNetworkEnvironment; +} +#elif defined(SWIFTEN_PLATFORM_WIN32) +#include <Swiften/Network/WindowsNetworkEnvironment.h> +namespace Swift { + typedef WindowsNetworkEnvironment PlatformNetworkEnvironment; +} +#else +#include <Swiften/Network/UnixNetworkEnvironment.h> +namespace Swift { + typedef UnixNetworkEnvironment PlatformNetworkEnvironment; +} +#endif diff --git a/Swiften/Network/SConscript b/Swiften/Network/SConscript index 965361b..e9853dd 100644 --- a/Swiften/Network/SConscript +++ b/Swiften/Network/SConscript @@ -40,7 +40,18 @@ sourceList = [ "Timer.cpp", "BoostTimer.cpp", "ProxyProvider.cpp", - "NullProxyProvider.cpp" + "NullProxyProvider.cpp", + "PlatformNATTraversalWorker.cpp", + "PlatformNATTraversalGetPublicIPRequest.cpp", + "PlatformNATTraversalForwardPortRequest.cpp", + "PlatformNATTraversalRemovePortForwardingRequest.cpp", + "PlatformNATTraversalRequest.cpp", + "UPnPNATTraversalGetPublicIPRequest.cpp", + "UPnPNATTraversalForwardPortRequest.cpp", + "UPnPNATTraversalRemovePortForwardingRequest.cpp", + "NATPMPNATTraversalGetPublicIPRequest.cpp", + "NATPMPNATTraversalForwardPortRequest.cpp", + "NATPMPNATTraversalRemovePortForwardingRequest.cpp", ] if myenv.get("HAVE_CARES", False) : @@ -49,9 +60,12 @@ if myenv.get("HAVE_CARES", False) : if myenv["PLATFORM"] == "darwin" : myenv.Append(FRAMEWORKS = ["CoreServices", "SystemConfiguration"]) sourceList += [ "MacOSXProxyProvider.cpp" ] + sourceList += [ "UnixNetworkEnvironment.cpp" ] elif myenv["PLATFORM"] == "win32" : sourceList += [ "WindowsProxyProvider.cpp" ] + sourceList += [ "WindowsNetworkEnvironment.cpp" ] else : + sourceList += [ "UnixNetworkEnvironment.cpp" ] sourceList += [ "UnixProxyProvider.cpp" ] sourceList += [ "EnvironmentProxyProvider.cpp" ] if myenv.get("HAVE_GCONF", 0) : diff --git a/Swiften/Network/UPnPNATTraversalForwardPortRequest.cpp b/Swiften/Network/UPnPNATTraversalForwardPortRequest.cpp new file mode 100644 index 0000000..c95066e --- /dev/null +++ b/Swiften/Network/UPnPNATTraversalForwardPortRequest.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 "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(PlatformNATTraversalForwardPortRequest::PortMapping mapping, PlatformNATTraversalWorker* worker) : PlatformNATTraversalForwardPortRequest(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 = getLocalClient().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 == PlatformNATTraversalForwardPortRequest::PortMapping::TCP ? "TCP" : "UDP", 0, leaseSeconds.c_str()); + if (ret == UPNPCOMMAND_SUCCESS) { + result = boost::optional<PlatformNATTraversalForwardPortRequest::PortMapping>(mapping); + } + } while(false); + + freeUPNPDevlist(deviceList); deviceList = 0; + + onResult(result); +} + +HostAddress UPnPNATTraversalForwardPortRequest::getLocalClient() { + PlatformNetworkEnvironment env; + + foreach (NetworkInterface::ref iface, env.getNetworkInterfaces()) { + if (!iface->isLoopback()) { + foreach (HostAddress address, iface->getAddresses()) { + if (address.getRawAddress().is_v4()) { + return address; + } + } + } + } + return HostAddress(); +} + +} diff --git a/Swiften/Network/UPnPNATTraversalForwardPortRequest.h b/Swiften/Network/UPnPNATTraversalForwardPortRequest.h new file mode 100644 index 0000000..931efee --- /dev/null +++ b/Swiften/Network/UPnPNATTraversalForwardPortRequest.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/PlatformNATTraversalForwardPortRequest.h> + +namespace Swift { + +class UPnPNATTraversalForwardPortRequest : public PlatformNATTraversalForwardPortRequest { +public: + UPnPNATTraversalForwardPortRequest(PlatformNATTraversalForwardPortRequest::PortMapping, PlatformNATTraversalWorker*); + virtual ~UPnPNATTraversalForwardPortRequest(); + + virtual void runBlocking(); + +private: + HostAddress getLocalClient(); + +private: + PlatformNATTraversalForwardPortRequest::PortMapping mapping; +}; + +} diff --git a/Swiften/Network/UPnPNATTraversalGetPublicIPRequest.cpp b/Swiften/Network/UPnPNATTraversalGetPublicIPRequest.cpp new file mode 100644 index 0000000..4a7c247 --- /dev/null +++ b/Swiften/Network/UPnPNATTraversalGetPublicIPRequest.cpp @@ -0,0 +1,57 @@ +/* + * 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) : PlatformNATTraversalGetPublicIPRequest(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 new file mode 100644 index 0000000..9d50001 --- /dev/null +++ b/Swiften/Network/UPnPNATTraversalGetPublicIPRequest.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Network/PlatformNATTraversalGetPublicIPRequest.h> + +namespace Swift { + +class UPnPNATTraversalGetPublicIPRequest : public PlatformNATTraversalGetPublicIPRequest { +public: + UPnPNATTraversalGetPublicIPRequest(PlatformNATTraversalWorker*); + virtual ~UPnPNATTraversalGetPublicIPRequest(); + + virtual void runBlocking(); +}; + +} diff --git a/Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.cpp b/Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.cpp new file mode 100644 index 0000000..2026880 --- /dev/null +++ b/Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.cpp @@ -0,0 +1,92 @@ +/* + * 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(PlatformNATTraversalRemovePortForwardingRequest::PortMapping mapping, PlatformNATTraversalWorker* worker) : PlatformNATTraversalRemovePortForwardingRequest(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 = getLocalClient().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 == PlatformNATTraversalRemovePortForwardingRequest::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); +} + +HostAddress UPnPNATTraversalRemovePortForwardingRequest::getLocalClient() { + PlatformNetworkEnvironment env; + + foreach (NetworkInterface::ref iface, env.getNetworkInterfaces()) { + if (!iface->isLoopback()) { + foreach (HostAddress address, iface->getAddresses()) { + if (address.getRawAddress().is_v4()) { + return address; + } + } + } + } + return HostAddress(); +} + +} diff --git a/Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.h b/Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.h new file mode 100644 index 0000000..ad1e019 --- /dev/null +++ b/Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.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/PlatformNATTraversalRemovePortForwardingRequest.h> + +namespace Swift { + +class UPnPNATTraversalRemovePortForwardingRequest : public PlatformNATTraversalRemovePortForwardingRequest { +public: + UPnPNATTraversalRemovePortForwardingRequest(PlatformNATTraversalRemovePortForwardingRequest::PortMapping, PlatformNATTraversalWorker*); + virtual ~UPnPNATTraversalRemovePortForwardingRequest(); + + virtual void runBlocking(); + +private: + HostAddress getLocalClient(); + +private: + PlatformNATTraversalRemovePortForwardingRequest::PortMapping mapping; +}; + +} diff --git a/Swiften/Network/UnixNetworkEnvironment.cpp b/Swiften/Network/UnixNetworkEnvironment.cpp new file mode 100644 index 0000000..649855d --- /dev/null +++ b/Swiften/Network/UnixNetworkEnvironment.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "UnixNetworkEnvironment.h" + +#include <string> +#include <vector> +#include <map> + +#include <boost/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/Network/HostAddress.h> +#include <Swiften/Network/NetworkInterface.h> + +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <net/if.h> +#include <ifaddrs.h> + +namespace Swift { + +std::vector<NetworkInterface::ref> UnixNetworkEnvironment::getNetworkInterfaces() { + std::map<std::string, UnixNetworkInterface::ref> interfaces; + std::vector<NetworkInterface::ref> result; + + ifaddrs *addrs = 0; + int ret = getifaddrs(&addrs); + if (ret != 0) { + return result; + } + + for (ifaddrs *a = addrs; a != 0; a = a->ifa_next) { + std::string name(a->ifa_name); + std::string ip; + if (a->ifa_addr->sa_family == PF_INET) { + sockaddr_in* sa = reinterpret_cast<sockaddr_in*>(a->ifa_addr); + char str[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(sa->sin_addr), str, INET_ADDRSTRLEN); + ip.assign(str); + } + else if (a->ifa_addr->sa_family == PF_INET6) { + sockaddr_in6* sa = reinterpret_cast<sockaddr_in6*>(a->ifa_addr); + char str[INET6_ADDRSTRLEN]; + /*if (IN6_IS_ADDR_LINKLOCAL(sa)) { + continue; + }*/ + inet_ntop(AF_INET6, &(sa->sin6_addr), str, INET6_ADDRSTRLEN); + ip.assign(str); + } + if (!ip.empty()) { + if (interfaces.find(name) == interfaces.end()) { + interfaces[name] = boost::make_shared<UnixNetworkInterface>(name); + if (a->ifa_flags & IFF_LOOPBACK) { + interfaces[name]->setLoopback(true); + } + } + interfaces[name]->addHostAddress(HostAddress(ip)); + } + } + + freeifaddrs(addrs); + + for(std::map<std::string, UnixNetworkInterface::ref>::iterator i = interfaces.begin(); i != interfaces.end(); ++i) { + result.push_back(i->second); + } + return result; +} + +} diff --git a/Swiften/Network/UnixNetworkEnvironment.h b/Swiften/Network/UnixNetworkEnvironment.h new file mode 100644 index 0000000..e4b2f37 --- /dev/null +++ b/Swiften/Network/UnixNetworkEnvironment.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <vector> + +#include <Swiften/Base/boost_bsignals.h> + +#include <Swiften/Network/NetworkEnvironment.h> +#include <Swiften/Network/NetworkInterface.h> + +namespace Swift { + +class UnixNetworkEnvironment : public NetworkEnvironment { + class UnixNetworkInterface : public NetworkInterface { + public: + typedef boost::shared_ptr<UnixNetworkInterface> ref; + + public: + UnixNetworkInterface(std::string name) : name(name), loopback(false) { } + + std::vector<HostAddress> getAddresses() { + return addresses; + } + + std::string getName() { + return name; + } + + bool isLoopback() { + return loopback; + } + + private: + void addHostAddress(HostAddress address) { + addresses.push_back(address); + } + + void setLoopback(bool loopback) { + this->loopback = loopback; + } + + private: + friend class UnixNetworkEnvironment; + std::vector<HostAddress> addresses; + std::string name; + InterfaceType type; + bool loopback; + }; + +public: + std::vector<NetworkInterface::ref> getNetworkInterfaces(); +}; + +} diff --git a/Swiften/Network/WindowsNetworkEnvironment.cpp b/Swiften/Network/WindowsNetworkEnvironment.cpp new file mode 100644 index 0000000..5163f43 --- /dev/null +++ b/Swiften/Network/WindowsNetworkEnvironment.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "WindowsNetworkEnvironment.h" + +#include <string> +#include <vector> +#include <map> + +#include <boost/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/Network/HostAddress.h> +#include <Swiften/Network/NetworkInterface.h> + +#include <winsock2.h> +#include <iphlpapi.h> + +namespace Swift { + +std::string winSocketAddressToStdString(const SOCKET_ADDRESS& socketAddress) { + char text[46]; + ULONG bufferSize = sizeof(text); + std::string result; + + int ret = WSAAddressToString(socketAddress.lpSockaddr, socketAddress.iSockaddrLength, NULL, text, &bufferSize); + if (ret == 0) { + result.assign(text, sizeof(text)); + } + return result; +} + +std::vector<NetworkInterface::ref> WindowsNetworkEnvironment::getNetworkInterfaces() { + std::map<std::string, WindowsNetworkInterface::ref> interfaces; + std::vector<NetworkInterface::ref> result; + + IP_ADAPTER_ADDRESSES preBuffer[5]; + PIP_ADAPTER_ADDRESSES adapterStart = preBuffer; + + ULONG bufferSize = sizeof(preBuffer); + + ULONG flags = GAA_FLAG_INCLUDE_ALL_INTERFACES | GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER; + + ULONG ret = GetAdaptersAddresses( AF_UNSPEC, flags, NULL, adapterStart, &bufferSize); + if (ret == ERROR_BUFFER_OVERFLOW) { + adapterStart = new IP_ADAPTER_ADDRESSES[bufferSize / sizeof(IP_ADAPTER_ADDRESSES)]; + if (!adapterStart) { + return result; + } + ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterStart, &bufferSize); + } + if (ret != ERROR_SUCCESS) { + if (adapterStart != preBuffer) { + delete adapterStart; + } + return result; + } + + for (PIP_ADAPTER_ADDRESSES adapter = adapterStart; adapter; adapter = adapter->Next) { + std::string name(adapter->AdapterName); + + if (adapter->OperStatus != IfOperStatusUp) { + continue; + } + + // iterate over addresses + for (PIP_ADAPTER_UNICAST_ADDRESS address = adapter->FirstUnicastAddress; address; address = address->Next) { + std::string ip; + + if (address->Address.lpSockaddr->sa_family == PF_INET || + address->Address.lpSockaddr->sa_family == PF_INET6) { + ip = winSocketAddressToStdString(address->Address); + if (!ip.empty()) { + if (interfaces.find(name) == interfaces.end()) { + interfaces[name] = boost::make_shared<WindowsNetworkInterface>(); + interfaces[name]->setName(name); + } + interfaces[name]->addHostAddress(HostAddress(ip)); + } + } + } + } + + if (adapterStart != preBuffer) { + //delete adapterStart; + } + + for(std::map<std::string, WindowsNetworkInterface::ref>::iterator i = interfaces.begin(); i != interfaces.end(); ++i) { + result.push_back(i->second); + } + return result; +} + +} diff --git a/Swiften/Network/WindowsNetworkEnvironment.h b/Swiften/Network/WindowsNetworkEnvironment.h new file mode 100644 index 0000000..2b79504 --- /dev/null +++ b/Swiften/Network/WindowsNetworkEnvironment.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <vector> + +#include <Swiften/Base/boost_bsignals.h> + +#include <Swiften/Network/NetworkEnvironment.h> +#include <Swiften/Network/NetworkInterface.h> + +namespace Swift { + +class WindowsNetworkEnvironment : public NetworkEnvironment { + class WindowsNetworkInterface : public NetworkInterface { + public: + typedef boost::shared_ptr<WindowsNetworkInterface> ref; + + public: + virtual ~WindowsNetworkInterface() { } + virtual std::vector<HostAddress> getAddresses() { + return addresses; + } + + virtual std::string getName() { + return name; + } + + virtual bool isLoopback() { + return false; + } + + public: + void addHostAddress(HostAddress address) { + addresses.push_back(address); + } + + void setName(const std::string& name) { + this->name = name; + } + + private: + std::vector<HostAddress> addresses; + InterfaceType type; + std::string name; + }; + +public: + std::vector<NetworkInterface::ref> getNetworkInterfaces(); +}; + +} |