summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Markmann <tm@ayena.de>2011-05-26 18:46:49 (GMT)
committerRemko Tronçon <git@el-tramo.be>2011-09-25 17:42:32 (GMT)
commit4f62e5ec4b42929fe3c1a68667e63cb1b7a35509 (patch)
tree0d19fac3f578dec00ccf3e58930312951e38de89 /Swiften/Network
parentde660b763459cdd707876ec244b6866abca07fa2 (diff)
downloadswift-contrib-4f62e5ec4b42929fe3c1a68667e63cb1b7a35509.zip
swift-contrib-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')
-rw-r--r--Swiften/Network/BoostNetworkFactories.cpp3
-rw-r--r--Swiften/Network/BoostNetworkFactories.h5
-rw-r--r--Swiften/Network/DummyConnectionFactory.h29
-rw-r--r--Swiften/Network/NATPMPNATTraversalForwardPortRequest.cpp62
-rw-r--r--Swiften/Network/NATPMPNATTraversalForwardPortRequest.h24
-rw-r--r--Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.cpp64
-rw-r--r--Swiften/Network/NATPMPNATTraversalGetPublicIPRequest.h22
-rw-r--r--Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.cpp83
-rw-r--r--Swiften/Network/NATPMPNATTraversalRemovePortForwardingRequest.h27
-rw-r--r--Swiften/Network/NetworkEnvironment.h24
-rw-r--r--Swiften/Network/NetworkFactories.h2
-rw-r--r--Swiften/Network/NetworkInterface.h35
-rw-r--r--Swiften/Network/PlatformNATTraversalForwardPortRequest.cpp18
-rw-r--r--Swiften/Network/PlatformNATTraversalForwardPortRequest.h38
-rw-r--r--Swiften/Network/PlatformNATTraversalGetPublicIPRequest.cpp18
-rw-r--r--Swiften/Network/PlatformNATTraversalGetPublicIPRequest.h25
-rw-r--r--Swiften/Network/PlatformNATTraversalRemovePortForwardingRequest.cpp18
-rw-r--r--Swiften/Network/PlatformNATTraversalRemovePortForwardingRequest.h38
-rw-r--r--Swiften/Network/PlatformNATTraversalRequest.cpp25
-rw-r--r--Swiften/Network/PlatformNATTraversalRequest.h31
-rw-r--r--Swiften/Network/PlatformNATTraversalWorker.cpp140
-rw-r--r--Swiften/Network/PlatformNATTraversalWorker.h60
-rw-r--r--Swiften/Network/PlatformNetworkEnvironment.h26
-rw-r--r--Swiften/Network/SConscript16
-rw-r--r--Swiften/Network/UPnPNATTraversalForwardPortRequest.cpp86
-rw-r--r--Swiften/Network/UPnPNATTraversalForwardPortRequest.h27
-rw-r--r--Swiften/Network/UPnPNATTraversalGetPublicIPRequest.cpp57
-rw-r--r--Swiften/Network/UPnPNATTraversalGetPublicIPRequest.h21
-rw-r--r--Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.cpp92
-rw-r--r--Swiften/Network/UPnPNATTraversalRemovePortForwardingRequest.h27
-rw-r--r--Swiften/Network/UnixNetworkEnvironment.cpp74
-rw-r--r--Swiften/Network/UnixNetworkEnvironment.h59
-rw-r--r--Swiften/Network/WindowsNetworkEnvironment.cpp97
-rw-r--r--Swiften/Network/WindowsNetworkEnvironment.h56
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();
+};
+
+}