summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThilo Cestonaro <thilo@cestona.ro>2011-04-14 08:25:33 (GMT)
committerRemko Tronçon <git@el-tramo.be>2011-04-18 19:11:45 (GMT)
commit427db871922a028bb299dd66c37f3cca4010fd47 (patch)
tree95c0c4bb407a5fd3ec49c138ec5fbff8cf3a7d7a /Swiften
parent0b0164a4cdae89afc254bd7aa6f14af81c6b9196 (diff)
downloadswift-contrib-427db871922a028bb299dd66c37f3cca4010fd47.zip
swift-contrib-427db871922a028bb299dd66c37f3cca4010fd47.tar.bz2
Support for SOCKS5 and HTTPConnect proxies.
automatic proxy settings detection; SOCKS5 proxied connection; HTTPConnect proxied connection; License: This patch is BSD-licensed, see http://www.opensource.org/licenses/bsd-license.php
Diffstat (limited to 'Swiften')
-rw-r--r--Swiften/Client/CoreClient.cpp16
-rw-r--r--Swiften/Client/CoreClient.h1
-rw-r--r--Swiften/Network/EnvironmentProxyProvider.cpp48
-rw-r--r--Swiften/Network/EnvironmentProxyProvider.h24
-rw-r--r--Swiften/Network/GConfProxyProvider.cpp51
-rw-r--r--Swiften/Network/GConfProxyProvider.h24
-rw-r--r--Swiften/Network/HTTPConnectProxiedConnection.cpp111
-rw-r--r--Swiften/Network/HTTPConnectProxiedConnection.h58
-rw-r--r--Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp22
-rw-r--r--Swiften/Network/HTTPConnectProxiedConnectionFactory.h26
-rw-r--r--Swiften/Network/HostAddress.cpp4
-rw-r--r--Swiften/Network/HostAddress.h2
-rw-r--r--Swiften/Network/HostAddressPort.h5
-rw-r--r--Swiften/Network/MacOSXProxyProvider.cpp83
-rw-r--r--Swiften/Network/MacOSXProxyProvider.h23
-rw-r--r--Swiften/Network/PlatformProxyProvider.h26
-rw-r--r--Swiften/Network/ProxyProvider.cpp19
-rw-r--r--Swiften/Network/ProxyProvider.h23
-rw-r--r--Swiften/Network/SConscript21
-rw-r--r--Swiften/Network/SOCKS5ProxiedConnection.cpp176
-rw-r--r--Swiften/Network/SOCKS5ProxiedConnection.h59
-rw-r--r--Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp22
-rw-r--r--Swiften/Network/SOCKS5ProxiedConnectionFactory.h28
-rw-r--r--Swiften/Network/UnixProxyProvider.cpp55
-rw-r--r--Swiften/Network/UnixProxyProvider.h25
-rw-r--r--Swiften/Network/WindowsProxyProvider.cpp113
-rw-r--r--Swiften/Network/WindowsProxyProvider.h22
-rw-r--r--Swiften/QA/ProxyProviderTest/.gitignore1
-rw-r--r--Swiften/QA/ProxyProviderTest/ProxyProviderTest.cpp35
-rw-r--r--Swiften/QA/ProxyProviderTest/SConscript11
-rw-r--r--Swiften/QA/SConscript1
-rw-r--r--Swiften/SConscript5
32 files changed, 1136 insertions, 4 deletions
diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp
index 8e51c8e..348f3b3 100644
--- a/Swiften/Client/CoreClient.cpp
+++ b/Swiften/Client/CoreClient.cpp
@@ -19,17 +19,28 @@
#include "Swiften/Base/IDGenerator.h"
#include "Swiften/Client/ClientSessionStanzaChannel.h"
#include <Swiften/Base/Log.h>
+#include "Swiften/Network/PlatformProxyProvider.h"
+#include "Swiften/Network/SOCKS5ProxiedConnectionFactory.h"
+#include "Swiften/Network/HTTPConnectProxiedConnectionFactory.h"
namespace Swift {
-CoreClient::CoreClient(const JID& jid, const std::string& password, NetworkFactories* networkFactories) : jid_(jid), password_(password), networkFactories(networkFactories), useStreamCompression(true), useTLS(UseTLSWhenAvailable), disconnectRequested_(false), certificateTrustChecker(NULL) {
+CoreClient::CoreClient(const JID& jid, const std::string& password, NetworkFactories* networkFactories) : jid_(jid), password_(password), networkFactories(networkFactories), useStreamCompression(true), useTLS(UseTLSWhenAvailable), proxyConnectionFactory_(NULL), disconnectRequested_(false), certificateTrustChecker(NULL) {
stanzaChannel_ = new ClientSessionStanzaChannel();
stanzaChannel_->onMessageReceived.connect(boost::bind(&CoreClient::handleMessageReceived, this, _1));
stanzaChannel_->onPresenceReceived.connect(boost::bind(&CoreClient::handlePresenceReceived, this, _1));
stanzaChannel_->onStanzaAcked.connect(boost::bind(&CoreClient::handleStanzaAcked, this, _1));
stanzaChannel_->onAvailableChanged.connect(boost::bind(&CoreClient::handleStanzaChannelAvailableChanged, this, _1));
+ PlatformProxyProvider proxyProvider;
+
iqRouter_ = new IQRouter(stanzaChannel_);
+ if(proxyProvider.getSOCKS5Proxy().isValid()) {
+ proxyConnectionFactory_ = new SOCKS5ProxiedConnectionFactory(networkFactories->getConnectionFactory(), proxyProvider.getSOCKS5Proxy());
+ }
+ else if(proxyProvider.getHTTPConnectProxy().isValid()) {
+ proxyConnectionFactory_ = new HTTPConnectProxiedConnectionFactory(networkFactories->getConnectionFactory(), proxyProvider.getHTTPConnectProxy());
+ }
tlsFactories = new PlatformTLSFactories();
}
@@ -38,6 +49,7 @@ CoreClient::~CoreClient() {
std::cerr << "Warning: Client not disconnected properly" << std::endl;
}
delete tlsFactories;
+ delete proxyConnectionFactory_;
delete iqRouter_;
stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&CoreClient::handleStanzaChannelAvailableChanged, this, _1));
@@ -56,7 +68,7 @@ void CoreClient::connect(const std::string& host) {
SWIFT_LOG(debug) << "Connecting to host " << host << std::endl;
disconnectRequested_ = false;
assert(!connector_);
- connector_ = Connector::create(host, networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory());
+ connector_ = Connector::create(host, networkFactories->getDomainNameResolver(), proxyConnectionFactory_ != NULL ? proxyConnectionFactory_ : networkFactories->getConnectionFactory(), networkFactories->getTimerFactory());
connector_->onConnectFinished.connect(boost::bind(&CoreClient::handleConnectorFinished, this, _1));
connector_->setTimeoutMilliseconds(60*1000);
connector_->start();
diff --git a/Swiften/Client/CoreClient.h b/Swiften/Client/CoreClient.h
index ceb0b0a..2debb7f 100644
--- a/Swiften/Client/CoreClient.h
+++ b/Swiften/Client/CoreClient.h
@@ -221,6 +221,7 @@ namespace Swift {
ClientSessionStanzaChannel* stanzaChannel_;
IQRouter* iqRouter_;
boost::shared_ptr<Connector> connector_;
+ ConnectionFactory* proxyConnectionFactory_;
PlatformTLSFactories* tlsFactories;
boost::shared_ptr<Connection> connection_;
boost::shared_ptr<BasicSessionStream> sessionStream_;
diff --git a/Swiften/Network/EnvironmentProxyProvider.cpp b/Swiften/Network/EnvironmentProxyProvider.cpp
new file mode 100644
index 0000000..b3bd0f6
--- /dev/null
+++ b/Swiften/Network/EnvironmentProxyProvider.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include "Swiften/Base/Log.h"
+#include "Swiften/Network/EnvironmentProxyProvider.h"
+
+namespace Swift {
+
+EnvironmentProxyProvider::EnvironmentProxyProvider() {
+ socksProxy = getFromEnv("all_proxy", "socks");
+ httpProxy = getFromEnv("http_proxy", "http");
+ SWIFT_LOG(debug) << "Environment: SOCKS5 => " << socksProxy.toString() << "; HTTP Connect => " << httpProxy.toString() << std::endl;
+}
+
+HostAddressPort EnvironmentProxyProvider::getHTTPConnectProxy() const {
+ return httpProxy;
+}
+
+HostAddressPort EnvironmentProxyProvider::getSOCKS5Proxy() const {
+ return socksProxy;
+}
+
+HostAddressPort EnvironmentProxyProvider::getFromEnv(const char* envVarName, std::string proxyProtocol) {
+ char* envVar = NULL;
+ std::string address;
+ int port = 0;
+
+ envVar = getenv(envVarName);
+
+ proxyProtocol += "://";
+ address = envVar != NULL ? envVar : "0.0.0.0";
+ if(envVar != NULL && address.compare(0, proxyProtocol.length(), proxyProtocol) == 0) {
+ address = address.substr(proxyProtocol.length(), address.length());
+ port = atoi(address.substr(address.find(':') + 1, address.length()).c_str());
+ address = address.substr(0, address.find(':'));
+ }
+
+ return HostAddressPort(HostAddress(address), port);
+}
+
+}
diff --git a/Swiften/Network/EnvironmentProxyProvider.h b/Swiften/Network/EnvironmentProxyProvider.h
new file mode 100644
index 0000000..1743269
--- /dev/null
+++ b/Swiften/Network/EnvironmentProxyProvider.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include "Swiften/Network/ProxyProvider.h"
+
+namespace Swift {
+ class EnvironmentProxyProvider : public ProxyProvider {
+ public:
+ EnvironmentProxyProvider();
+ virtual HostAddressPort getHTTPConnectProxy() const;
+ virtual HostAddressPort getSOCKS5Proxy() const;
+ private:
+ HostAddressPort getFromEnv(const char* envVarName, std::string proxyProtocol);
+ HostAddressPort socksProxy;
+ HostAddressPort httpProxy;
+ };
+}
+
+
diff --git a/Swiften/Network/GConfProxyProvider.cpp b/Swiften/Network/GConfProxyProvider.cpp
new file mode 100644
index 0000000..687bf77
--- /dev/null
+++ b/Swiften/Network/GConfProxyProvider.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include <gconf/gconf-client.h>
+
+#include "Swiften/Base/Log.h"
+#include "Swiften/Network/GConfProxyProvider.h"
+
+namespace Swift {
+
+GConfProxyProvider::GConfProxyProvider() {
+ socksProxy = getFromGConf("/system/proxy/socks_host", "/system/proxy/socks_port");
+ httpProxy = getFromGConf("/system/http_proxy/host", "/system/http_proxy/port");
+ SWIFT_LOG(debug) << "GConf: SOCKS5 => " << socksProxy.toString() << "; HTTP Connect => " << httpProxy.toString() << std::endl;
+}
+
+HostAddressPort GConfProxyProvider::getHTTPConnectProxy() const {
+ return httpProxy;
+}
+
+HostAddressPort GConfProxyProvider::getSOCKS5Proxy() const {
+ return socksProxy;
+}
+
+HostAddressPort GConfProxyProvider::getFromGConf(const char* gcHost, const char* gcPort) {
+ std::string address;
+ int port = 0;
+ gchar* str;
+
+ GConfClient* client = gconf_client_get_default();
+
+ str = gconf_client_get_string(client, gcHost, NULL);
+ port = static_cast<int> (gconf_client_get_int(client, gcPort, NULL));
+
+ if(str) {
+ address = static_cast<char*> (str);
+ g_free(str);
+ }
+
+ g_object_unref(client);
+ return HostAddressPort(HostAddress(address), port);
+}
+
+}
diff --git a/Swiften/Network/GConfProxyProvider.h b/Swiften/Network/GConfProxyProvider.h
new file mode 100644
index 0000000..15586ad
--- /dev/null
+++ b/Swiften/Network/GConfProxyProvider.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include "Swiften/Network/ProxyProvider.h"
+
+namespace Swift {
+ class GConfProxyProvider : public ProxyProvider {
+ public:
+ GConfProxyProvider();
+ virtual HostAddressPort getHTTPConnectProxy() const;
+ virtual HostAddressPort getSOCKS5Proxy() const;
+ private:
+ HostAddressPort getFromGConf(const char* gcHost, const char* gcPort);
+ HostAddressPort socksProxy;
+ HostAddressPort httpProxy;
+ };
+}
+
+
diff --git a/Swiften/Network/HTTPConnectProxiedConnection.cpp b/Swiften/Network/HTTPConnectProxiedConnection.cpp
new file mode 100644
index 0000000..4e05f29
--- /dev/null
+++ b/Swiften/Network/HTTPConnectProxiedConnection.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "Swiften/Network/HTTPConnectProxiedConnection.h"
+
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/thread.hpp>
+#include <boost/lexical_cast.hpp>
+#include <math.h>
+
+#include "Swiften/Base/Log.h"
+#include "Swiften/Base/String.h"
+#include "Swiften/Base/ByteArray.h"
+#include "Swiften/Network/HostAddressPort.h"
+
+namespace Swift {
+
+HTTPConnectProxiedConnection::HTTPConnectProxiedConnection(ConnectionFactory* connectionFactory, HostAddressPort proxy)
+: connectionFactory_(connectionFactory), proxy_(proxy), server_(HostAddressPort(HostAddress("0.0.0.0"), 0))
+{
+ connected_ = false;
+}
+
+HTTPConnectProxiedConnection::~HTTPConnectProxiedConnection() {
+ if(connection_) {
+ connection_->onDataRead.disconnect(boost::bind(&HTTPConnectProxiedConnection::handleDataRead, shared_from_this(), _1));
+ connection_->onDisconnected.disconnect(boost::bind(&HTTPConnectProxiedConnection::handleDisconnected, shared_from_this(), _1));
+ }
+
+ if(connected_) {
+ std::cerr << "Warning: Connection was still established." << std::endl;
+ }
+}
+
+void HTTPConnectProxiedConnection::connect(const HostAddressPort& server) {
+ server_ = server;
+ connection_ = connectionFactory_->createConnection();
+ connection_->onConnectFinished.connect(boost::bind(&HTTPConnectProxiedConnection::handleConnectionConnectFinished, shared_from_this(), _1));
+ connection_->onDataRead.connect(boost::bind(&HTTPConnectProxiedConnection::handleDataRead, shared_from_this(), _1));
+ connection_->onDisconnected.connect(boost::bind(&HTTPConnectProxiedConnection::handleDisconnected, shared_from_this(), _1));
+ connection_->connect(proxy_);
+}
+
+void HTTPConnectProxiedConnection::listen() {
+ assert(false);
+ connection_->listen();
+}
+
+void HTTPConnectProxiedConnection::disconnect() {
+ connected_ = false;
+ connection_->disconnect();
+}
+
+void HTTPConnectProxiedConnection::handleDisconnected(const boost::optional<Error>& error) {
+ onDisconnected(error);
+}
+
+void HTTPConnectProxiedConnection::write(const ByteArray& data) {
+ connection_->write(data);
+}
+
+void HTTPConnectProxiedConnection::handleConnectionConnectFinished(bool error) {
+ connection_->onConnectFinished.disconnect(boost::bind(&HTTPConnectProxiedConnection::handleConnectionConnectFinished, shared_from_this(), _1));
+ if(!error) {
+ proxyState_ = ProxyConnecting;
+ std::stringstream connect;
+ connect << "CONNECT " << server_.getAddress().toString() << ":" << server_.getPort() << " HTTP/1.1\r\n\r\n";
+ connection_->write(ByteArray(connect.str()));
+ }
+ else {
+ onConnectFinished(true);
+ }
+}
+
+void HTTPConnectProxiedConnection::handleDataRead(const ByteArray& data) {
+ if (!connected_) {
+ if (proxyState_ == ProxyConnecting) {
+ SWIFT_LOG(debug) << data.toString() << std::endl;
+ std::vector<std::string> tmp = String::split(data.toString(), ' ');
+ if(tmp.size() > 1) {
+ int status = boost::lexical_cast<int> (tmp[1].c_str());
+ SWIFT_LOG(debug) << "Proxy Status: " << status << std::endl;
+ if (status / 100 == 2) { // all 2XX states are OK
+ connected_ = true;
+ onConnectFinished(false);
+ return;
+ }
+ }
+
+ std::cerr << "HTTP Proxy returned an error: " << data.toString() << std::endl;
+ return;
+ }
+ }
+ else {
+ onDataRead(data);
+ return;
+ }
+ disconnect();
+ onConnectFinished(true);
+}
+
+HostAddressPort HTTPConnectProxiedConnection::getLocalAddress() const {
+ return connection_->getLocalAddress();
+}
+
+//namespace
+}
diff --git a/Swiften/Network/HTTPConnectProxiedConnection.h b/Swiften/Network/HTTPConnectProxiedConnection.h
new file mode 100644
index 0000000..88b4f66
--- /dev/null
+++ b/Swiften/Network/HTTPConnectProxiedConnection.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * 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 "Swiften/Network/ConnectionFactory.h"
+#include "Swiften/Network/Connection.h"
+#include "Swiften/Network/HostAddressPort.h"
+
+namespace boost {
+ class thread;
+ namespace system {
+ class error_code;
+ }
+}
+
+namespace Swift {
+ class HTTPConnectProxiedConnection : public Connection, public boost::enable_shared_from_this<HTTPConnectProxiedConnection> {
+ public:
+ typedef boost::shared_ptr<HTTPConnectProxiedConnection> ref;
+
+ ~HTTPConnectProxiedConnection();
+
+ static ref create(ConnectionFactory* connectionFactory, HostAddressPort proxy) {
+ return ref(new HTTPConnectProxiedConnection(connectionFactory, proxy));
+ }
+
+ virtual void listen();
+ virtual void connect(const HostAddressPort& address);
+ virtual void disconnect();
+ virtual void write(const ByteArray& data);
+
+ virtual HostAddressPort getLocalAddress() const;
+ private:
+ enum {
+ ProxyAuthenticating = 0,
+ ProxyConnecting,
+ } proxyState_;
+
+ HTTPConnectProxiedConnection(ConnectionFactory* connectionFactory, HostAddressPort proxy);
+
+ void handleConnectionConnectFinished(bool error);
+ void handleDataRead(const ByteArray& data);
+ void handleDisconnected(const boost::optional<Error>& error);
+
+ private:
+ bool connected_;
+ ConnectionFactory* connectionFactory_;
+ HostAddressPort proxy_;
+ HostAddressPort server_;
+ boost::shared_ptr<Connection> connection_;
+ };
+}
diff --git a/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp b/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp
new file mode 100644
index 0000000..0212945
--- /dev/null
+++ b/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "Swiften/Network/HTTPConnectProxiedConnectionFactory.h"
+#include "Swiften/Network/HTTPConnectProxiedConnection.h"
+
+namespace Swift {
+
+HTTPConnectProxiedConnectionFactory::HTTPConnectProxiedConnectionFactory(ConnectionFactory* connectionFactory, HostAddressPort proxy)
+: connectionFactory_(connectionFactory), proxy_(proxy)
+{
+
+}
+
+boost::shared_ptr<Connection> HTTPConnectProxiedConnectionFactory::createConnection() {
+ return HTTPConnectProxiedConnection::create(connectionFactory_, proxy_);
+}
+
+}
diff --git a/Swiften/Network/HTTPConnectProxiedConnectionFactory.h b/Swiften/Network/HTTPConnectProxiedConnectionFactory.h
new file mode 100644
index 0000000..7aeb337
--- /dev/null
+++ b/Swiften/Network/HTTPConnectProxiedConnectionFactory.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include "Swiften/Network/ConnectionFactory.h"
+#include "Swiften/Network/HTTPConnectProxiedConnection.h"
+#include "Swiften/Network/HostAddressPort.h"
+
+namespace Swift {
+ class HTTPConnectProxiedConnection;
+
+ class HTTPConnectProxiedConnectionFactory : public ConnectionFactory {
+ public:
+ HTTPConnectProxiedConnectionFactory(ConnectionFactory* connectionFactory, HostAddressPort proxy);
+
+ virtual boost::shared_ptr<Connection> createConnection();
+
+ private:
+ ConnectionFactory* connectionFactory_;
+ HostAddressPort proxy_;
+ };
+}
diff --git a/Swiften/Network/HostAddress.cpp b/Swiften/Network/HostAddress.cpp
index 331a233..f734329 100644
--- a/Swiften/Network/HostAddress.cpp
+++ b/Swiften/Network/HostAddress.cpp
@@ -57,4 +57,8 @@ bool HostAddress::isValid() const {
return !(address_.is_v4() && address_.to_v4().to_ulong() == 0);
}
+boost::asio::ip::address HostAddress::getRawAddress() const {
+ return address_;
+}
+
}
diff --git a/Swiften/Network/HostAddress.h b/Swiften/Network/HostAddress.h
index 3e9c8a6..0b3bdda 100644
--- a/Swiften/Network/HostAddress.h
+++ b/Swiften/Network/HostAddress.h
@@ -3,7 +3,6 @@
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-
#pragma once
#include <string>
@@ -18,6 +17,7 @@ namespace Swift {
HostAddress(const boost::asio::ip::address& address);
std::string toString() const;
+ boost::asio::ip::address getRawAddress() const;
bool operator==(const HostAddress& o) const {
return address_ == o.address_;
diff --git a/Swiften/Network/HostAddressPort.h b/Swiften/Network/HostAddressPort.h
index c99ca65..5655f4d 100644
--- a/Swiften/Network/HostAddressPort.h
+++ b/Swiften/Network/HostAddressPort.h
@@ -7,6 +7,7 @@
#pragma once
#include <boost/asio/ip/tcp.hpp>
+#include <boost/lexical_cast.hpp>
#include "Swiften/Network/HostAddress.h"
@@ -37,6 +38,10 @@ namespace Swift {
bool isValid() const {
return address_.isValid() && port_ > 0;
}
+
+ std::string toString() const {
+ return getAddress().toString() + ":" + boost::lexical_cast<std::string>(getPort());
+ }
private:
HostAddress address_;
diff --git a/Swiften/Network/MacOSXProxyProvider.cpp b/Swiften/Network/MacOSXProxyProvider.cpp
new file mode 100644
index 0000000..babcc7f
--- /dev/null
+++ b/Swiften/Network/MacOSXProxyProvider.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream>
+#include <utility>
+
+#include "Swiften/Network/MacOSXProxyProvider.h"
+#include <SystemConfiguration/SystemConfiguration.h>
+
+namespace Swift {
+
+MacOSXProxyProvider::MacOSXProxyProvider()
+: ProxyProvider()
+{
+ CFDictionaryRef proxies = SCDynamicStoreCopyProxies(NULL);
+ if(proxies != NULL) {
+ socksProxy = getFromDictionary(proxies, kSCPropNetProxiesSOCKSEnable, kSCPropNetProxiesSOCKSProxy, kSCPropNetProxiesSOCKSPort);
+ httpProxy = getFromDictionary(proxies, kSCPropNetProxiesHTTPEnable, kSCPropNetProxiesHTTPProxy, kSCPropNetProxiesHTTPPort);
+ }
+}
+
+HostAddressPort MacOSXProxyProvider::getHTTPConnectProxy() const {
+ return httpProxy;
+}
+
+HostAddressPort MacOSXProxyProvider::getSOCKS5Proxy() const {
+ return socksProxy;
+}
+
+HostAddressPort MacOSXProxyProvider::getFromDictionary(CFDictionaryRef dict, CFStringRef enabledKey, CFStringRef hostKey, CFStringRef portKey) {
+ CFNumberRef numberValue = NULL;
+ HostAddressPort ret = HostAddressPort(HostAddress(), 0);
+
+ if(CFDictionaryGetValueIfPresent(dict, reinterpret_cast<const void*> (enabledKey), reinterpret_cast<const void**> (&numberValue)) == true) {
+ const int i = 0;
+ CFNumberRef zero = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &i);
+ CFComparisonResult result = CFNumberCompare(numberValue, zero, NULL);
+ CFRelease(numberValue);
+
+ if(result != kCFCompareEqualTo) {
+ int port = 0;
+ std::string host = "";
+
+ try {
+ CFNumberRef numberValue = reinterpret_cast<CFNumberRef> (CFDictionaryGetValue(dict, portKey));
+ if(numberValue != NULL) {
+ CFNumberGetValue(numberValue, kCFNumberIntType, &port);
+ CFRelease(numberValue);
+ }
+
+ CFStringRef stringValue = reinterpret_cast<CFStringRef> (CFDictionaryGetValue(dict, hostKey));
+ if(stringValue != NULL) {
+ std::vector<char> buffer;
+ // length must be +1 for the ending zero; and the Docu of CFStringGetCString tells it like
+ // if the string is toby the length must be at least 5.
+ CFIndex length = CFStringGetLength(stringValue) + 1;
+ buffer.resize(length);
+ if(CFStringGetCString(stringValue, &buffer[0], length, kCFStringEncodingMacRoman)) {
+ for(std::vector<char>::iterator iter = buffer.begin(); iter != buffer.end(); iter++) {
+ host += *iter;
+ }
+ }
+ CFRelease(stringValue);
+ }
+ }
+ catch(...) {
+ std::cerr << "Exception caught ... " << std::endl;
+ }
+
+ if(host != "" && port != 0) {
+ ret = HostAddressPort(HostAddress(host), port);
+ }
+ }
+ }
+ return ret;
+}
+
+}
diff --git a/Swiften/Network/MacOSXProxyProvider.h b/Swiften/Network/MacOSXProxyProvider.h
new file mode 100644
index 0000000..1cb001f
--- /dev/null
+++ b/Swiften/Network/MacOSXProxyProvider.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+#include "Swiften/Network/ProxyProvider.h"
+#include <CoreFoundation/CoreFoundation.h>
+
+namespace Swift {
+ class MacOSXProxyProvider : public ProxyProvider {
+ public:
+ MacOSXProxyProvider();
+ virtual HostAddressPort getHTTPConnectProxy() const;
+ virtual HostAddressPort getSOCKS5Proxy() const;
+
+ private:
+ HostAddressPort getFromDictionary(CFDictionaryRef dict, CFStringRef enabledKey, CFStringRef hostKey, CFStringRef portKey);
+ HostAddressPort socksProxy;
+ HostAddressPort httpProxy;
+ };
+}
diff --git a/Swiften/Network/PlatformProxyProvider.h b/Swiften/Network/PlatformProxyProvider.h
new file mode 100644
index 0000000..13b15d2
--- /dev/null
+++ b/Swiften/Network/PlatformProxyProvider.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * 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/MacOSXProxyProvider.h"
+namespace Swift {
+ typedef MacOSXProxyProvider PlatformProxyProvider;
+}
+#elif defined(SWIFTEN_PLATFORM_WIN32)
+#include "Swiften/Network/WindowsProxyProvider.h"
+namespace Swift {
+ typedef WindowsProxyProvider PlatformProxyProvider;
+}
+#else
+#include "Swiften/Network/UnixProxyProvider.h"
+namespace Swift {
+ typedef UnixProxyProvider PlatformProxyProvider;
+}
+#endif
diff --git a/Swiften/Network/ProxyProvider.cpp b/Swiften/Network/ProxyProvider.cpp
new file mode 100644
index 0000000..fe235b1
--- /dev/null
+++ b/Swiften/Network/ProxyProvider.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "ProxyProvider.h"
+
+namespace Swift {
+
+ProxyProvider::ProxyProvider()
+{
+}
+
+ProxyProvider::~ProxyProvider()
+{
+}
+
+}
diff --git a/Swiften/Network/ProxyProvider.h b/Swiften/Network/ProxyProvider.h
new file mode 100644
index 0000000..05bb5a7
--- /dev/null
+++ b/Swiften/Network/ProxyProvider.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+#include <map>
+
+#include "Swiften/Base/Log.h"
+#include "Swiften/Network/HostAddressPort.h"
+#include "Swiften/Base/String.h"
+
+namespace Swift {
+ class ProxyProvider {
+ public:
+ ProxyProvider();
+ virtual ~ProxyProvider();
+ virtual HostAddressPort getHTTPConnectProxy() const = 0;
+ virtual HostAddressPort getSOCKS5Proxy() const = 0;
+ };
+}
+
diff --git a/Swiften/Network/SConscript b/Swiften/Network/SConscript
index 93732d1..426118b 100644
--- a/Swiften/Network/SConscript
+++ b/Swiften/Network/SConscript
@@ -6,6 +6,10 @@ if myenv.get("HAVE_CARES", False) :
myenv.MergeFlags(myenv.get("CARES_FLAGS", {}))
sourceList = [
+ "HTTPConnectProxiedConnection.cpp",
+ "HTTPConnectProxiedConnectionFactory.cpp",
+ "SOCKS5ProxiedConnection.cpp",
+ "SOCKS5ProxiedConnectionFactory.cpp",
"BoostConnection.cpp",
"BoostConnectionFactory.cpp",
"BoostConnectionServer.cpp",
@@ -30,10 +34,25 @@ sourceList = [
"NetworkFactories.cpp",
"BoostNetworkFactories.cpp",
"Timer.cpp",
- "BoostTimer.cpp"]
+ "BoostTimer.cpp",
+ "ProxyProvider.cpp"
+ ]
+
if myenv.get("HAVE_CARES", False) :
sourceList.append("CAresDomainNameResolver.cpp")
+if myenv["PLATFORM"] == "darwin" :
+ myenv.Append(FRAMEWORKS = ["CoreServices", "SystemConfiguration"])
+ sourceList += [ "MacOSXProxyProvider.cpp" ]
+elif myenv["PLATFORM"] == "win32" :
+ sourceList += [ "WindowsProxyProvider.cpp" ]
+else :
+ sourceList += [ "UnixProxyProvider.cpp" ]
+ sourceList += [ "EnvironmentProxyProvider.cpp" ]
+ if myenv.get("HAVE_GCONF", 0) :
+ myenv.Append(CPPDEFINES = "HAVE_GCONF")
+ myenv.MergeFlags(myenv["GCONF_FLAGS"])
+ sourceList += [ "GConfProxyProvider.cpp" ]
objects = myenv.SwiftenObject(sourceList)
swiften_env.Append(SWIFTEN_OBJECTS = [objects])
diff --git a/Swiften/Network/SOCKS5ProxiedConnection.cpp b/Swiften/Network/SOCKS5ProxiedConnection.cpp
new file mode 100644
index 0000000..d32a0f9
--- /dev/null
+++ b/Swiften/Network/SOCKS5ProxiedConnection.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "Swiften/Network/SOCKS5ProxiedConnection.h"
+
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/thread.hpp>
+#include <math.h>
+
+#include "Swiften/Base/Log.h"
+#include "Swiften/Base/String.h"
+#include "Swiften/Base/ByteArray.h"
+#include "Swiften/Network/HostAddressPort.h"
+
+namespace Swift {
+
+SOCKS5ProxiedConnection::SOCKS5ProxiedConnection(ConnectionFactory* connectionFactory, HostAddressPort proxy)
+: connectionFactory_(connectionFactory), proxy_(proxy), server_(HostAddressPort(HostAddress("0.0.0.0"), 0))
+{
+ connected_ = false;
+}
+
+SOCKS5ProxiedConnection::~SOCKS5ProxiedConnection() {
+ if(connection_) {
+ connection_->onDataRead.disconnect(boost::bind(&SOCKS5ProxiedConnection::handleDataRead, shared_from_this(), _1));
+ connection_->onDisconnected.disconnect(boost::bind(&SOCKS5ProxiedConnection::handleDisconnected, shared_from_this(), _1));
+ }
+
+ if(connected_) {
+ std::cerr << "Warning: Connection was still established." << std::endl;
+ }
+}
+
+void SOCKS5ProxiedConnection::connect(const HostAddressPort& server) {
+ server_ = server;
+ connection_ = connectionFactory_->createConnection();
+ connection_->onConnectFinished.connect(boost::bind(&SOCKS5ProxiedConnection::handleConnectionConnectFinished, shared_from_this(), _1));
+ connection_->onDataRead.connect(boost::bind(&SOCKS5ProxiedConnection::handleDataRead, shared_from_this(), _1));
+ connection_->onDisconnected.connect(boost::bind(&SOCKS5ProxiedConnection::handleDisconnected, shared_from_this(), _1));
+ SWIFT_LOG(debug) << "Trying to connect via proxy " << proxy_.getAddress().toString() << ":" << proxy_.getPort() << std::endl;
+ SWIFT_LOG(debug) << "to server " << server.getAddress().toString() << ":" << server.getPort() << std::endl;
+ connection_->connect(proxy_);
+}
+
+void SOCKS5ProxiedConnection::listen() {
+ assert(false);
+ connection_->listen();
+}
+
+void SOCKS5ProxiedConnection::disconnect() {
+ connected_ = false;
+ if(connection_)
+ connection_->disconnect();
+}
+
+void SOCKS5ProxiedConnection::handleDisconnected(const boost::optional<Error>& error) {
+ onDisconnected(error);
+}
+
+void SOCKS5ProxiedConnection::write(const ByteArray& data) {
+ if(connection_)
+ connection_->write(data);
+}
+
+void SOCKS5ProxiedConnection::handleConnectionConnectFinished(bool error) {
+ connection_->onConnectFinished.disconnect(boost::bind(&SOCKS5ProxiedConnection::handleConnectionConnectFinished, shared_from_this(), _1));
+ if(!error) {
+ SWIFT_LOG(debug) << "Connection to proxy established, now connect to the server via it." << std::endl;
+
+ proxyState_ = ProxyAuthenticating;
+ ByteArray socksConnect;
+ socksConnect += 0x05; // VER = SOCKS5 = 0x05
+ socksConnect += 0x01; // Number of authentication methods after this byte.
+ socksConnect += 0x00; // 0x00 == no authentication
+ // buffer.push_back(0x01); // 0x01 == GSSAPI
+ // buffer.push_back(0x02); // 0x02 == Username/Password
+ // rest see RFC 1928 (http://tools.ietf.org/html/rfc1928)
+ connection_->write(socksConnect);
+ }
+ else {
+ onConnectFinished(true);
+ }
+}
+
+void SOCKS5ProxiedConnection::handleDataRead(const ByteArray& data) {
+ ByteArray socksConnect;
+ boost::asio::ip::address rawAddress = server_.getAddress().getRawAddress();
+ assert(rawAddress.is_v4() || rawAddress.is_v6());
+ if (!connected_) {
+ if (proxyState_ == ProxyAuthenticating) {
+ SWIFT_LOG(debug) << "ProxyAuthenticating response received, reply with the connect BYTEs" << std::endl;
+ unsigned char choosenMethod = static_cast<unsigned char> (data[1]);
+ if (data[0] == 0x05 && choosenMethod != 0xFF) {
+ switch(choosenMethod) { // use the correct Method
+ case 0x00:
+ try {
+ proxyState_ = ProxyConnecting;
+ socksConnect += 0x05; // VER = SOCKS5 = 0x05
+ socksConnect += 0x01; // Construct a TCP connection. (CMD)
+ socksConnect += 0x00; // reserved.
+ socksConnect += rawAddress.is_v4() ? 0x01 : 0x04; // IPv4 == 0x01, Hostname == 0x02, IPv6 == 0x04. (ATYP)
+ size_t size = rawAddress.is_v4() ? rawAddress.to_v4().to_bytes().size() : rawAddress.to_v6().to_bytes().size();
+ for (size_t s = 0; s < size; s++) {
+ unsigned char uc;
+ if(rawAddress.is_v4()) {
+ uc = rawAddress.to_v4().to_bytes()[s]; // the address.
+ }
+ else
+ uc = rawAddress.to_v6().to_bytes()[s]; // the address.
+ socksConnect += static_cast<char> (uc);
+
+ }
+ socksConnect += static_cast<unsigned char> (server_.getPort() >> 8); // highbyte of the port.
+ socksConnect += static_cast<unsigned char> (server_.getPort()); // lowbyte of the port.
+ connection_->write(socksConnect);
+ return;
+ }
+ catch(...) {
+ std::cerr << "exception caught" << std::endl;
+ }
+ connection_->write(socksConnect);
+ break;
+ default:
+ onConnectFinished(true);
+ break;
+ }
+ return;
+ }
+ }
+ else if (proxyState_ == ProxyConnecting) {
+ SWIFT_LOG(debug) << "Connect response received, check if successfully." << std::endl;
+ SWIFT_LOG(debug) << "Errorbyte: 0x" << std::hex << static_cast<int> (data[1]) << std::dec << std::endl;
+ /*
+
+ data.at(1) can be one of the following:
+ 0x00 succeeded
+ 0x01 general SOCKS server failure
+ 0x02 connection not allowed by ruleset
+ 0x03 Network unreachable
+ 0x04 Host unreachable
+ 0x05 Connection refused
+ 0x06 TTL expired
+ 0x07 Command not supported (CMD)
+ 0x08 Address type not supported (ATYP)
+ 0x09 bis 0xFF unassigned
+ */
+ if (data[0] == 0x05 && data[1] == 0x0) {
+ SWIFT_LOG(debug) << "Successfully connected the server via the proxy." << std::endl;
+ connected_ = true;
+ onConnectFinished(false);
+ return;
+ }
+ else {
+ std::cerr << "SOCKS Proxy returned an error: " << std::hex << data[1] << std::endl;
+ }
+ return;
+ }
+ }
+ else {
+ onDataRead(data);
+ return;
+ }
+ disconnect();
+ onConnectFinished(true);
+}
+
+HostAddressPort SOCKS5ProxiedConnection::getLocalAddress() const {
+ return connection_->getLocalAddress();
+}
+
+//namespace
+}
diff --git a/Swiften/Network/SOCKS5ProxiedConnection.h b/Swiften/Network/SOCKS5ProxiedConnection.h
new file mode 100644
index 0000000..b222fd7
--- /dev/null
+++ b/Swiften/Network/SOCKS5ProxiedConnection.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/asio.hpp>
+#include <boost/enable_shared_from_this.hpp>
+
+#include "Swiften/Network/ConnectionFactory.h"
+#include "Swiften/Network/Connection.h"
+#include "Swiften/Network/HostAddressPort.h"
+
+namespace boost {
+ class thread;
+ namespace system {
+ class error_code;
+ }
+}
+
+namespace Swift {
+ class SOCKS5ProxiedConnection : public Connection, public boost::enable_shared_from_this<SOCKS5ProxiedConnection> {
+ public:
+ typedef boost::shared_ptr<SOCKS5ProxiedConnection> ref;
+
+ ~SOCKS5ProxiedConnection();
+
+ static ref create(ConnectionFactory* connectionFactory, HostAddressPort proxy) {
+ return ref(new SOCKS5ProxiedConnection(connectionFactory, proxy));
+ }
+
+ virtual void listen();
+ virtual void connect(const HostAddressPort& address);
+ virtual void disconnect();
+ virtual void write(const ByteArray& data);
+
+ virtual HostAddressPort getLocalAddress() const;
+ private:
+ enum {
+ ProxyAuthenticating = 0,
+ ProxyConnecting,
+ } proxyState_;
+
+ SOCKS5ProxiedConnection(ConnectionFactory* connectionFactory, HostAddressPort proxy);
+
+ void handleConnectionConnectFinished(bool error);
+ void handleDataRead(const ByteArray& data);
+ void handleDisconnected(const boost::optional<Error>& error);
+
+ private:
+ bool connected_;
+ ConnectionFactory* connectionFactory_;
+ HostAddressPort proxy_;
+ HostAddressPort server_;
+ boost::shared_ptr<Connection> connection_;
+ };
+}
diff --git a/Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp b/Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp
new file mode 100644
index 0000000..0be0931
--- /dev/null
+++ b/Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "Swiften/Network/SOCKS5ProxiedConnectionFactory.h"
+#include "Swiften/Network/SOCKS5ProxiedConnection.h"
+
+namespace Swift {
+
+SOCKS5ProxiedConnectionFactory::SOCKS5ProxiedConnectionFactory(ConnectionFactory* connectionFactory, HostAddressPort proxy)
+: connectionFactory_(connectionFactory), proxy_(proxy)
+{
+
+}
+
+boost::shared_ptr<Connection> SOCKS5ProxiedConnectionFactory::createConnection() {
+ return SOCKS5ProxiedConnection::create(connectionFactory_, proxy_);
+}
+
+}
diff --git a/Swiften/Network/SOCKS5ProxiedConnectionFactory.h b/Swiften/Network/SOCKS5ProxiedConnectionFactory.h
new file mode 100644
index 0000000..a78a9e8
--- /dev/null
+++ b/Swiften/Network/SOCKS5ProxiedConnectionFactory.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/asio.hpp>
+
+#include "Swiften/Network/ConnectionFactory.h"
+#include "Swiften/Network/SOCKS5ProxiedConnection.h"
+#include "Swiften/Network/HostAddressPort.h"
+
+namespace Swift {
+ class SOCKS5ProxiedConnection;
+
+ class SOCKS5ProxiedConnectionFactory : public ConnectionFactory {
+ public:
+ SOCKS5ProxiedConnectionFactory(ConnectionFactory* connectionFactory, HostAddressPort proxy);
+
+ virtual boost::shared_ptr<Connection> createConnection();
+
+ private:
+ ConnectionFactory* connectionFactory_;
+ HostAddressPort proxy_;
+ };
+}
diff --git a/Swiften/Network/UnixProxyProvider.cpp b/Swiften/Network/UnixProxyProvider.cpp
new file mode 100644
index 0000000..e21b310
--- /dev/null
+++ b/Swiften/Network/UnixProxyProvider.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include "Swiften/Base/foreach.h"
+#include "Swiften/Network/UnixProxyProvider.h"
+
+namespace Swift {
+
+UnixProxyProvider::UnixProxyProvider() :
+#if defined(HAVE_GCONF)
+ gconfProxyProvider(),
+#endif
+ environmentProxyProvider()
+{
+}
+
+HostAddressPort UnixProxyProvider::getSOCKS5Proxy() const {
+ HostAddressPort proxy;
+#if defined(HAVE_GCONF)
+ proxy = gconfProxyProvider.getSOCKS5Proxy();
+ if(proxy.isValid()) {
+ return proxy;
+ }
+#endif
+ proxy = environmentProxyProvider.getSOCKS5Proxy();
+ if(proxy.isValid()) {
+ return proxy;
+ }
+ return HostAddressPort(HostAddress(), 0);
+}
+
+HostAddressPort UnixProxyProvider::getHTTPConnectProxy() const {
+ HostAddressPort proxy;
+#if defined(HAVE_GCONF)
+ proxy = gconfProxyProvider.getHTTPConnectProxy();
+ if(proxy.isValid()) {
+ return proxy;
+ }
+#endif
+ proxy = environmentProxyProvider.getHTTPConnectProxy();
+ if(proxy.isValid()) {
+ return proxy;
+ }
+ return HostAddressPort(HostAddress(), 0);
+}
+
+
+}
diff --git a/Swiften/Network/UnixProxyProvider.h b/Swiften/Network/UnixProxyProvider.h
new file mode 100644
index 0000000..509cf4b
--- /dev/null
+++ b/Swiften/Network/UnixProxyProvider.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+#if defined(HAVE_GCONF)
+# include "Swiften/Network/GConfProxyProvider.h"
+#endif
+#include "Swiften/Network/EnvironmentProxyProvider.h"
+
+namespace Swift {
+ class UnixProxyProvider : public ProxyProvider {
+ public:
+ UnixProxyProvider();
+ virtual HostAddressPort getHTTPConnectProxy() const;
+ virtual HostAddressPort getSOCKS5Proxy() const;
+ private:
+#if defined(HAVE_GCONF)
+ GConfProxyProvider gconfProxyProvider;
+#endif
+ EnvironmentProxyProvider environmentProxyProvider;
+ };
+}
diff --git a/Swiften/Network/WindowsProxyProvider.cpp b/Swiften/Network/WindowsProxyProvider.cpp
new file mode 100644
index 0000000..5f6f5d2
--- /dev/null
+++ b/Swiften/Network/WindowsProxyProvider.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <iostream>
+#include <boost/lexical_cast.hpp>
+
+#include "Swiften/Base/log.h"
+#include "Swiften/Base/foreach.h"
+#include "Swiften/Network/WindowsProxyProvider.h"
+#include "Swiften/Base/ByteArray.h"
+
+#include <windows.h>
+
+namespace Swift {
+
+WindowsProxyProvider::WindowsProxyProvider()
+: ProxyProvider()
+{
+ HKEY hKey = (HKEY)INVALID_HANDLE_VALUE;
+ long result;
+
+ result = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", 0, KEY_READ, &hKey);
+ if (result == ERROR_SUCCESS && hKey != INVALID_HANDLE_VALUE && proxyEnabled(hKey)) {
+ DWORD dataType = REG_SZ;
+ DWORD dataSize = 0;
+ ByteArray dataBuffer;
+
+ result = RegQueryValueEx(hKey, "ProxyServer", NULL, &dataType, NULL, &dataSize);
+ if(result != ERROR_SUCCESS) {
+ return;
+ }
+ dataBuffer.resize(dataSize);
+ result = RegQueryValueEx(hKey, "ProxyServer", NULL, &dataType, reinterpret_cast<BYTE*>(dataBuffer.getData()), &dataSize);
+ if(result == ERROR_SUCCESS) {
+ std::vector<std::string> proxies = String::split(dataBuffer.toString(), ';');
+ std::pair<std::string, std::string> protocolAndProxy;
+ foreach(std::string proxy, proxies) {
+ if(proxy.find('=') != std::string::npos) {
+ protocolAndProxy = String::getSplittedAtFirst(proxy, '=');
+ SWIFT_LOG(debug) << "Found proxy: " << protocolAndProxy.first << " => " << protocolAndProxy.second << std::endl;
+ if(protocolAndProxy.first.compare("socks") == 0) {
+ socksProxy = getAsHostAddressPort(protocolAndProxy.second);
+ }
+ else if (protocolAndProxy.first.compare("http") == 0) {
+ httpProxy = getAsHostAddressPort(protocolAndProxy.second);
+ }
+ }
+ }
+ }
+ }
+}
+
+HostAddressPort WindowsProxyProvider::getHTTPConnectProxy() const {
+ return httpProxy;
+}
+
+HostAddressPort WindowsProxyProvider::getSOCKS5Proxy() const {
+ return socksProxy;
+}
+
+HostAddressPort WindowsProxyProvider::getAsHostAddressPort(std::string proxy) {
+ HostAddressPort ret(HostAddress(), 0);
+
+ try {
+ std::pair<std::string, std::string> tmp;
+ int port = 0;
+ tmp = String::getSplittedAtFirst(proxy, ':');
+ // .c_str() is needed as tmp.second can include a \0 char which will end in an exception of the lexical cast.
+ // with .c_str() the \0 will not be part of the string which is to be casted
+ port = boost::lexical_cast<int> (tmp.second.c_str());
+ ret = HostAddressPort(HostAddress(tmp.first), port);
+ }
+ catch(...) {
+ std::cerr << "Exception occured while parsing windows proxy \"getHostAddressPort\"." << std::endl;
+ }
+
+ return ret;
+}
+
+
+bool WindowsProxyProvider::proxyEnabled(HKEY hKey) const {
+ bool ret = false;
+ long result;
+ DWORD dataType = REG_DWORD;
+ DWORD dataSize = 0;
+ DWORD data = 0;
+ ByteArray dataBuffer;
+
+ if(hKey == INVALID_HANDLE_VALUE)
+ return ret;
+
+ result = RegQueryValueEx(hKey, "ProxyEnable", NULL, &dataType, NULL, &dataSize);
+ if(result != ERROR_SUCCESS)
+ return ret;
+
+ dataBuffer.resize(dataSize);
+ result = RegQueryValueEx(hKey, "ProxyEnable", NULL, &dataType, reinterpret_cast<BYTE*>(dataBuffer.getData()), &dataSize);
+ if(result != ERROR_SUCCESS)
+ return ret;
+
+ for(size_t t = 0; t < dataBuffer.getSize(); t++) {
+ data += static_cast<int> (dataBuffer[t]) * pow(256, static_cast<double>(t));
+ }
+ return (data == 1);
+}
+
+}
diff --git a/Swiften/Network/WindowsProxyProvider.h b/Swiften/Network/WindowsProxyProvider.h
new file mode 100644
index 0000000..d8d08f0
--- /dev/null
+++ b/Swiften/Network/WindowsProxyProvider.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+#include "Swiften/Network/ProxyProvider.h"
+
+namespace Swift {
+ class WindowsProxyProvider : public ProxyProvider {
+ public:
+ WindowsProxyProvider();
+ virtual HostAddressPort getHTTPConnectProxy() const;
+ virtual HostAddressPort getSOCKS5Proxy() const;
+ private:
+ HostAddressPort getAsHostAddressPort(std::string proxy);
+ bool proxyEnabled(HKEY hKey) const;
+ HostAddressPort socksProxy;
+ HostAddressPort httpProxy;
+ };
+}
diff --git a/Swiften/QA/ProxyProviderTest/.gitignore b/Swiften/QA/ProxyProviderTest/.gitignore
new file mode 100644
index 0000000..9d4b9b8
--- /dev/null
+++ b/Swiften/QA/ProxyProviderTest/.gitignore
@@ -0,0 +1 @@
+ProxyProviderTest
diff --git a/Swiften/QA/ProxyProviderTest/ProxyProviderTest.cpp b/Swiften/QA/ProxyProviderTest/ProxyProviderTest.cpp
new file mode 100644
index 0000000..ddaee01
--- /dev/null
+++ b/Swiften/QA/ProxyProviderTest/ProxyProviderTest.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2010 Thilo Cestonaro
+ * Licensed under the BSD License.
+ * See Documentation/Licenses/BSD.txt for more information.
+ */
+
+#include <iostream>
+
+#include <Swiften/Network/PlatformProxyProvider.h>
+#include <Swiften/Base/foreach.h>
+
+using namespace Swift;
+
+int main(void)
+{
+ int ret = 0;
+ HostAddressPort hap;
+
+ std::cout << "constructing PlatfromProxyProvider instance ..." << std::endl;
+ PlatformProxyProvider ppp;
+
+ hap = ppp.getSOCKS5Proxy();
+ std::cout << "SOCKS5 Proxy configured: " << hap.isValid() << std::endl;
+ if(hap.isValid()) {
+ std::cout << "SOCKS5 Proxy: " << hap.getAddress().toString() << ":" << hap.getPort() << std::endl;
+ }
+
+ hap = ppp.getHTTPConnectProxy();
+ std::cout << "HTTPConnect Proxy configured: " << hap.isValid() << std::endl;
+ if(hap.isValid()) {
+ std::cout << "HTTPConnect Proxy: " << hap.getAddress().toString() << ":" << hap.getPort() << std::endl;
+ }
+
+ return ret;
+}
diff --git a/Swiften/QA/ProxyProviderTest/SConscript b/Swiften/QA/ProxyProviderTest/SConscript
new file mode 100644
index 0000000..e9c5139
--- /dev/null
+++ b/Swiften/QA/ProxyProviderTest/SConscript
@@ -0,0 +1,11 @@
+import os
+
+Import("env")
+
+myenv = env.Clone()
+myenv.MergeFlags(myenv["SWIFTEN_FLAGS"])
+myenv.MergeFlags(myenv["BOOST_FLAGS"])
+
+myenv.Program("ProxyProviderTest", [
+ "ProxyProviderTest.cpp",
+ ])
diff --git a/Swiften/QA/SConscript b/Swiften/QA/SConscript
index 25ba814..41d7206 100644
--- a/Swiften/QA/SConscript
+++ b/Swiften/QA/SConscript
@@ -8,4 +8,5 @@ SConscript(dirs = [
"StorageTest",
"TLSTest",
"ScriptedTests",
+ "ProxyProviderTest",
])
diff --git a/Swiften/SConscript b/Swiften/SConscript
index 57c95fc..0a229e8 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -159,6 +159,9 @@ if env["SCONS_STAGE"] == "build" :
"StringCodecs/Hexify.cpp",
]
+ if myenv["PLATFORM"] != "darwin" and myenv["PLATFORM"] != "win32" and myenv.get("HAVE_GCONF", 0) :
+ env.MergeFlags(env["GCONF_FLAGS"])
+
SConscript(dirs = [
"Avatars",
"Base",
@@ -333,6 +336,8 @@ if env["SCONS_STAGE"] == "build" :
continue
if file.startswith("CAres") or file.startswith("LibXML") or file.startswith("Expat") or file.startswith("foreach") or file.startswith("Log.h") or file.startswith("format.h") :
continue
+ if file.find("ProxyProvider") != -1 :
+ continue
swiften_header += "#include <" + include + ">\n"
swiften_includes.append(include)
for file in ["EventLoop/SimpleEventLoop.h"] :