From f171bc207c2a7371ac6924ff467049dd0258aa00 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sat, 2 Jun 2012 18:40:22 +0200
Subject: Allow different connection methods for Client.


diff --git a/Sluift/sluift.cpp b/Sluift/sluift.cpp
index 85b35f9..8076f5a 100644
--- a/Sluift/sluift.cpp
+++ b/Sluift/sluift.cpp
@@ -73,7 +73,8 @@ class SluiftClient {
 
 		void connect(const std::string& host) {
 			rosterReceived = false;
-			client->connect(host);
+			options.manualHostname = host;
+			client->connect(options);
 		}
 
 		void waitConnected() {
diff --git a/Swiften/Client/ClientOptions.h b/Swiften/Client/ClientOptions.h
index fbec272..e5fcda9 100644
--- a/Swiften/Client/ClientOptions.h
+++ b/Swiften/Client/ClientOptions.h
@@ -17,7 +17,27 @@ namespace Swift {
 			RequireTLS
 		};
 
-		ClientOptions() : useStreamCompression(true), useTLS(UseTLSWhenAvailable), allowPLAINWithoutTLS(false), useStreamResumption(false), forgetPassword(false), useAcks(true), boshHTTPConnectProxyAuthID(""), boshHTTPConnectProxyAuthPassword("") {
+		enum ProxyType {
+			NoProxy,
+			SystemConfiguredProxy,
+			SOCKS5Proxy,
+			HTTPConnectProxy
+		};
+
+		ClientOptions() : 
+				useStreamCompression(true), 
+				useTLS(UseTLSWhenAvailable), 
+				allowPLAINWithoutTLS(false), 
+				useStreamResumption(false), 
+				forgetPassword(false), 
+				useAcks(true), 
+				manualHostname(""),
+				manualPort(-1),
+				proxyType(SystemConfiguredProxy),
+				manualProxyHostname(""),
+				manualProxyPort(-1),
+				boshHTTPConnectProxyAuthID(""), 
+				boshHTTPConnectProxyAuthPassword("") {
 		}
 
 		/**
@@ -66,6 +86,35 @@ namespace Swift {
 		bool useAcks;
 
 		/**
+		 * The hostname to connect to.
+		 * Leave this empty for standard XMPP connection, based on the JID domain.
+		 */
+		std::string manualHostname;
+
+		/**
+		 * The port to connect to.
+		 * Leave this to -1 to use the port discovered by SRV lookups, and 5222 as a
+		 * fallback.
+		 */
+		int manualPort;
+
+		/**
+		 * The type of proxy to use for connecting to the XMPP
+		 * server.
+		 */
+		ProxyType proxyType;
+
+		/**
+		 * Override the system-configured proxy hostname.
+		 */
+		std::string manualProxyHostname;
+
+		/**
+		 * Override the system-configured proxy port.
+		 */
+		int manualProxyPort;
+
+		/**
 		 * If non-empty, use BOSH instead of direct TCP, with the given URL.
 		 * Default: empty (no BOSH)
 		 */
diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp
index 36e27eb..64c0bab 100644
--- a/Swiften/Client/CoreClient.cpp
+++ b/Swiften/Client/CoreClient.cpp
@@ -54,27 +54,55 @@ CoreClient::~CoreClient() {
 
 void CoreClient::connect(const ClientOptions& o) {
 	SWIFT_LOG(debug) << "Connecting" << std::endl;
-	options = o;
-	connect(jid_.getDomain());
-}
 
-void CoreClient::connect(const std::string& host) {
 	forceReset();
-
-	SWIFT_LOG(debug) << "Connecting to host " << host << std::endl;
 	disconnectRequested_ = false;
-	assert(!connector_);
+
+	options = o;
+
+
+	// Determine connection types to use
 	assert(proxyConnectionFactories.empty());
-	if (networkFactories->getProxyProvider()->getSOCKS5Proxy().isValid()) {
-		proxyConnectionFactories.push_back(new SOCKS5ProxiedConnectionFactory(networkFactories->getConnectionFactory(), networkFactories->getProxyProvider()->getSOCKS5Proxy()));
-	}
-	if(networkFactories->getProxyProvider()->getHTTPConnectProxy().isValid()) {
-		proxyConnectionFactories.push_back(new HTTPConnectProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), networkFactories->getEventLoop(), networkFactories->getProxyProvider()->getHTTPConnectProxy().getAddress().toString(), networkFactories->getProxyProvider()->getHTTPConnectProxy().getPort()));
+	bool useDirectConnection = true;
+	HostAddressPort systemSOCKS5Proxy = networkFactories->getProxyProvider()->getSOCKS5Proxy();
+	HostAddressPort systemHTTPConnectProxy = networkFactories->getProxyProvider()->getHTTPConnectProxy();
+	switch (o.proxyType) {
+		case ClientOptions::NoProxy:
+			break;
+		case ClientOptions::SystemConfiguredProxy:
+			if (systemSOCKS5Proxy.isValid()) {
+				proxyConnectionFactories.push_back(new SOCKS5ProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), systemSOCKS5Proxy.getAddress().toString(), systemHTTPConnectProxy.getPort()));
+			}
+			if (systemHTTPConnectProxy.isValid()) {
+				proxyConnectionFactories.push_back(new HTTPConnectProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), systemHTTPConnectProxy.getAddress().toString(), systemHTTPConnectProxy.getPort()));
+			}
+			break;
+		case ClientOptions::SOCKS5Proxy: {
+			std::string proxyHostname = o.manualProxyHostname.empty() ? systemSOCKS5Proxy.getAddress().toString() : o.manualProxyHostname;
+			int proxyPort = o.manualProxyPort == -1 ? systemSOCKS5Proxy.getPort() : o.manualProxyPort;
+			proxyConnectionFactories.push_back(new SOCKS5ProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), proxyHostname, proxyPort));
+			useDirectConnection = false;
+			break;
+		}
+		case ClientOptions::HTTPConnectProxy: {
+			std::string proxyHostname = o.manualProxyHostname.empty() ? systemSOCKS5Proxy.getAddress().toString() : o.manualProxyHostname;
+			int proxyPort = o.manualProxyPort == -1 ? systemSOCKS5Proxy.getPort() : o.manualProxyPort;
+			proxyConnectionFactories.push_back(new HTTPConnectProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), proxyHostname, proxyPort));
+			useDirectConnection = false;
+			break;
+		}
 	}
 	std::vector<ConnectionFactory*> connectionFactories(proxyConnectionFactories);
-	if (options.boshURL.empty()) {
+	if (useDirectConnection) {
 		connectionFactories.push_back(networkFactories->getConnectionFactory());
-		connector_ = boost::make_shared<ChainedConnector>(host, networkFactories->getDomainNameResolver(), connectionFactories, networkFactories->getTimerFactory());
+	}
+
+	// Create connector
+	std::string host = o.manualHostname.empty() ?  jid_.getDomain() : o.manualHostname;
+	int port = o.manualPort;
+	assert(!connector_);
+	if (options.boshURL.empty()) {
+		connector_ = boost::make_shared<ChainedConnector>(host, port, o.manualHostname.empty(), networkFactories->getDomainNameResolver(), connectionFactories, networkFactories->getTimerFactory());
 		connector_->onConnectFinished.connect(boost::bind(&CoreClient::handleConnectorFinished, this, _1, _2));
 		connector_->setTimeoutMilliseconds(60*1000);
 		connector_->start();
diff --git a/Swiften/Client/CoreClient.h b/Swiften/Client/CoreClient.h
index 985bf7f..4bb04e2 100644
--- a/Swiften/Client/CoreClient.h
+++ b/Swiften/Client/CoreClient.h
@@ -74,8 +74,6 @@ namespace Swift {
 			 */
 			void disconnect();
 
-			void connect(const std::string& host);
-			
 			/**
 			 * Sends a message.
 			 */
diff --git a/Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp b/Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp
index c957481..636a52a 100644
--- a/Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp
+++ b/Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp
@@ -79,7 +79,9 @@ int main(int argc, char* argv[]) {
 	std::cout << "Connecting to JID " << jid << " with timeout " << timeout << "ms on host: "; ;
 	if (!connectHost.empty()) {
 		std::cout << connectHost << std::endl;
-		client->connect(connectHost);
+		ClientOptions options;
+		options.manualHostname = connectHost;
+		client->connect(options);
 	} else {
 		std::cout << " Default" << std::endl;
 		client->connect();
diff --git a/Swiften/Examples/SendMessage/SendMessage.cpp b/Swiften/Examples/SendMessage/SendMessage.cpp
index f4dbf53..07e289e 100644
--- a/Swiften/Examples/SendMessage/SendMessage.cpp
+++ b/Swiften/Examples/SendMessage/SendMessage.cpp
@@ -69,7 +69,9 @@ int main(int argc, char* argv[]) {
 	client->onConnected.connect(&handleConnected);
 	errorConnection = client->onDisconnected.connect(&handleDisconnected);
 	if (!connectHost.empty()) {
-		client->connect(connectHost);
+		ClientOptions options;
+		options.manualHostname = connectHost;
+		client->connect(options);
 	} else {
 		client->connect();
 	}
diff --git a/Swiften/Network/BOSHConnectionPool.cpp b/Swiften/Network/BOSHConnectionPool.cpp
index bb24aa5..0adeb45 100644
--- a/Swiften/Network/BOSHConnectionPool.cpp
+++ b/Swiften/Network/BOSHConnectionPool.cpp
@@ -35,7 +35,7 @@ BOSHConnectionPool::BOSHConnectionPool(const URL& boshURL, DomainNameResolver* r
 			connectionFactory = new TLSConnectionFactory(tlsFactory, connectionFactory);
 			myConnectionFactories.push_back(connectionFactory);
 		}
-		connectionFactory = new HTTPConnectProxiedConnectionFactory(realResolver, connectionFactory, timerFactory, eventLoop, boshHTTPConnectProxyURL.getHost(), boshHTTPConnectProxyURL.getPort(), boshHTTPConnectProxyAuthID, boshHTTPConnectProxyAuthPassword);
+		connectionFactory = new HTTPConnectProxiedConnectionFactory(realResolver, connectionFactory, timerFactory, boshHTTPConnectProxyURL.getHost(), boshHTTPConnectProxyURL.getPort(), boshHTTPConnectProxyAuthID, boshHTTPConnectProxyAuthPassword);
 	}
 	if (boshURL.getScheme() == "https") {
 		connectionFactory = new TLSConnectionFactory(tlsFactory, connectionFactory);
@@ -211,7 +211,7 @@ void BOSHConnectionPool::handleConnectionDisconnected(bool error, BOSHConnection
 }
 
 boost::shared_ptr<BOSHConnection> BOSHConnectionPool::createConnection() {
-	Connector::ref connector = Connector::create(boshURL.getHost(), resolver, connectionFactory, timerFactory, boshURL.getPort());
+	Connector::ref connector = Connector::create(boshURL.getHost(), boshURL.getPort(), false, resolver, connectionFactory, timerFactory);
 	BOSHConnection::ref connection = BOSHConnection::create(boshURL, connector, xmlParserFactory);
 	connection->onXMPPDataRead.connect(boost::bind(&BOSHConnectionPool::handleDataRead, this, _1));
 	connection->onSessionStarted.connect(boost::bind(&BOSHConnectionPool::handleSessionStarted, this, _1, _2));
diff --git a/Swiften/Network/ChainedConnector.cpp b/Swiften/Network/ChainedConnector.cpp
index 0a1283f..8c7c04b 100644
--- a/Swiften/Network/ChainedConnector.cpp
+++ b/Swiften/Network/ChainedConnector.cpp
@@ -18,10 +18,14 @@ using namespace Swift;
 
 ChainedConnector::ChainedConnector(
 		const std::string& hostname, 
+		int port,
+		bool doServiceLookups,
 		DomainNameResolver* resolver, 
 		const std::vector<ConnectionFactory*>& connectionFactories, 
 		TimerFactory* timerFactory) : 
 			hostname(hostname), 
+			port(port),
+			doServiceLookups(doServiceLookups),
 			resolver(resolver), 
 			connectionFactories(connectionFactories), 
 			timerFactory(timerFactory), 
@@ -58,7 +62,7 @@ void ChainedConnector::tryNextConnectionFactory() {
 		ConnectionFactory* connectionFactory = connectionFactoryQueue.front();
 		SWIFT_LOG(debug) << "Trying next connection factory: " << typeid(*connectionFactory).name() << std::endl;
 		connectionFactoryQueue.pop_front();
-		currentConnector = Connector::create(hostname, resolver, connectionFactory, timerFactory);
+		currentConnector = Connector::create(hostname, port, doServiceLookups, resolver, connectionFactory, timerFactory);
 		currentConnector->setTimeoutMilliseconds(timeoutMilliseconds);
 		currentConnector->onConnectFinished.connect(boost::bind(&ChainedConnector::handleConnectorFinished, this, _1, _2));
 		currentConnector->start();
diff --git a/Swiften/Network/ChainedConnector.h b/Swiften/Network/ChainedConnector.h
index 12ef023..60aea05 100644
--- a/Swiften/Network/ChainedConnector.h
+++ b/Swiften/Network/ChainedConnector.h
@@ -23,7 +23,7 @@ namespace Swift {
 
 	class ChainedConnector {
 		public:
-			ChainedConnector(const std::string& hostname, DomainNameResolver*, const std::vector<ConnectionFactory*>&, TimerFactory*);
+			ChainedConnector(const std::string& hostname, int port, bool doServiceLookups, DomainNameResolver*, const std::vector<ConnectionFactory*>&, TimerFactory*);
 
 			void setTimeoutMilliseconds(int milliseconds);
 			void start();
@@ -38,6 +38,8 @@ namespace Swift {
 
 		private:
 			std::string hostname;
+			int port;
+			bool doServiceLookups;
 			DomainNameResolver* resolver;
 			std::vector<ConnectionFactory*> connectionFactories;
 			TimerFactory* timerFactory;
diff --git a/Swiften/Network/Connector.cpp b/Swiften/Network/Connector.cpp
index 5e7f8d9..02ebb02 100644
--- a/Swiften/Network/Connector.cpp
+++ b/Swiften/Network/Connector.cpp
@@ -17,7 +17,7 @@
 
 namespace Swift {
 
-Connector::Connector(const std::string& hostname, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, int defaultPort) : hostname(hostname), resolver(resolver), connectionFactory(connectionFactory), timerFactory(timerFactory), defaultPort(defaultPort), timeoutMilliseconds(0), queriedAllServices(true), foundSomeDNS(false) {
+Connector::Connector(const std::string& hostname, int port, bool doServiceLookups, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory) : hostname(hostname), port(port), doServiceLookups(doServiceLookups), resolver(resolver), connectionFactory(connectionFactory), timerFactory(timerFactory), timeoutMilliseconds(0), queriedAllServices(true), foundSomeDNS(false) {
 }
 
 void Connector::setTimeoutMilliseconds(int milliseconds) {
@@ -31,14 +31,19 @@ void Connector::start() {
 	assert(!serviceQuery);
 	assert(!timer);
 	queriedAllServices = false;
-	serviceQuery = resolver->createServiceQuery("_xmpp-client._tcp." + hostname);
-	serviceQuery->onResult.connect(boost::bind(&Connector::handleServiceQueryResult, shared_from_this(), _1));
-	if (timeoutMilliseconds > 0) {
-		timer = timerFactory->createTimer(timeoutMilliseconds);
-		timer->onTick.connect(boost::bind(&Connector::handleTimeout, shared_from_this()));
-		timer->start();
-	}
-	serviceQuery->run();
+	if (doServiceLookups) {
+		serviceQuery = resolver->createServiceQuery("_xmpp-client._tcp." + hostname);
+		serviceQuery->onResult.connect(boost::bind(&Connector::handleServiceQueryResult, shared_from_this(), _1));
+		if (timeoutMilliseconds > 0) {
+			timer = timerFactory->createTimer(timeoutMilliseconds);
+			timer->onTick.connect(boost::bind(&Connector::handleTimeout, shared_from_this()));
+			timer->start();
+		}
+		serviceQuery->run();
+	}
+	else {
+		queryAddress(hostname);
+	}
 }
 
 void Connector::stop() {
@@ -109,12 +114,12 @@ void Connector::tryNextAddress() {
 		HostAddress address = addressQueryResults.front();
 		addressQueryResults.pop_front();
 
-		int port = defaultPort;
+		int connectPort = (port == -1 ? 5222 : port);
 		if (!serviceQueryResults.empty()) {
-			port = serviceQueryResults.front().port;
+			connectPort = serviceQueryResults.front().port;
 		}
 
-		tryConnect(HostAddressPort(address, port));
+		tryConnect(HostAddressPort(address, connectPort));
 	}
 }
 
diff --git a/Swiften/Network/Connector.h b/Swiften/Network/Connector.h
index bf0efaf..e3fd51f 100644
--- a/Swiften/Network/Connector.h
+++ b/Swiften/Network/Connector.h
@@ -27,8 +27,8 @@ namespace Swift {
 		public:
 			typedef boost::shared_ptr<Connector> ref;
 
-			static Connector::ref create(const std::string& hostname, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, int defaultPort = 5222) {
-				return ref(new Connector(hostname, resolver, connectionFactory, timerFactory, defaultPort));
+			static Connector::ref create(const std::string& hostname, int port, bool doServiceLookups, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory) {
+				return ref(new Connector(hostname, port, doServiceLookups, resolver, connectionFactory, timerFactory));
 			}
 
 			void setTimeoutMilliseconds(int milliseconds);
@@ -38,7 +38,7 @@ namespace Swift {
 			boost::signal<void (boost::shared_ptr<Connection>, boost::shared_ptr<Error>)> onConnectFinished;
 
 		private:
-			Connector(const std::string& hostname, DomainNameResolver*, ConnectionFactory*, TimerFactory*, int defaultPort);
+			Connector(const std::string& hostname, int port, bool doServiceLookups, DomainNameResolver*, ConnectionFactory*, TimerFactory*);
 
 			void handleServiceQueryResult(const std::vector<DomainNameServiceQuery::Result>& result);
 			void handleAddressQueryResult(const std::vector<HostAddress>& address, boost::optional<DomainNameResolveError> error);
@@ -55,10 +55,11 @@ namespace Swift {
 
 		private:
 			std::string hostname;
+			int port;
+			bool doServiceLookups;
 			DomainNameResolver* resolver;
 			ConnectionFactory* connectionFactory;
 			TimerFactory* timerFactory;
-			int defaultPort;
 			int timeoutMilliseconds;
 			boost::shared_ptr<Timer> timer;
 			boost::shared_ptr<DomainNameServiceQuery> serviceQuery;
diff --git a/Swiften/Network/HTTPConnectProxiedConnection.cpp b/Swiften/Network/HTTPConnectProxiedConnection.cpp
index 512381f..7bd7e41 100644
--- a/Swiften/Network/HTTPConnectProxiedConnection.cpp
+++ b/Swiften/Network/HTTPConnectProxiedConnection.cpp
@@ -15,7 +15,6 @@
 
 #include <iostream>
 #include <boost/bind.hpp>
-#include <boost/thread.hpp>
 #include <boost/lexical_cast.hpp>
 
 #include <Swiften/Base/Algorithm.h>
@@ -24,111 +23,52 @@
 #include <Swiften/Base/ByteArray.h>
 #include <Swiften/Network/HostAddressPort.h>
 #include <Swiften/Network/ConnectionFactory.h>
-#include <Swiften/Network/CachingNameOnlyDomainNameResolver.h>
 #include <Swiften/StringCodecs/Base64.h>
 
 using namespace Swift;
 
-HTTPConnectProxiedConnection::HTTPConnectProxiedConnection(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, EventLoop* eventLoop, const std::string& proxyHost, int proxyPort, const SafeString& authID, const SafeString& authPassword) : connectionFactory_(connectionFactory), timerFactory_(timerFactory), proxyHost_(proxyHost), proxyPort_(proxyPort), server_(HostAddressPort(HostAddress("0.0.0.0"), 0)), authID_(authID), authPassword_(authPassword) {
-	resolver_ = new CachingNameOnlyDomainNameResolver(resolver, eventLoop);
-	connected_ = false;
+HTTPConnectProxiedConnection::HTTPConnectProxiedConnection(
+		DomainNameResolver* resolver, 
+		ConnectionFactory* connectionFactory, 
+		TimerFactory* timerFactory, 
+		const std::string& proxyHost, 
+		int proxyPort, 
+		const SafeString& authID, 
+		const SafeString& authPassword) : 
+			ProxiedConnection(resolver, connectionFactory, timerFactory, proxyHost, proxyPort),
+			authID_(authID), 
+			authPassword_(authPassword) {
 }
 
-HTTPConnectProxiedConnection::~HTTPConnectProxiedConnection() {
-	cancelConnector();
-	delete resolver_;
-	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::cancelConnector() {
-	if (connector_) {
-		connector_->onConnectFinished.disconnect(boost::bind(&HTTPConnectProxiedConnection::handleConnectFinished, shared_from_this(), _1));
-		connector_->stop();
-		connector_.reset();
-	}
-}
-
-void HTTPConnectProxiedConnection::connect(const HostAddressPort& server) {
-	server_ = server;
-	connector_ = Connector::create(proxyHost_, resolver_, connectionFactory_, timerFactory_, proxyPort_);
-	connector_->onConnectFinished.connect(boost::bind(&HTTPConnectProxiedConnection::handleConnectFinished, shared_from_this(), _1));
-	connector_->start();
-}
 
-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 SafeByteArray& data) {
-	connection_->write(data);
-}
-
-void HTTPConnectProxiedConnection::handleConnectFinished(Connection::ref connection) {
-	cancelConnector();
-	if (connection) {
-		connection_ = connection;
-		connection_->onDataRead.connect(boost::bind(&HTTPConnectProxiedConnection::handleDataRead, shared_from_this(), _1));
-		connection_->onDisconnected.connect(boost::bind(&HTTPConnectProxiedConnection::handleDisconnected, shared_from_this(), _1));
-
-		std::stringstream connect;
-		connect << "CONNECT " << server_.getAddress().toString() << ":" << server_.getPort() << " HTTP/1.1\r\n";
-		SafeByteArray data = createSafeByteArray(connect.str());
-		if (!authID_.empty() && !authPassword_.empty()) {
-			append(data, createSafeByteArray("Proxy-Authorization: Basic "));
-			SafeByteArray credentials = authID_;
-			append(credentials, createSafeByteArray(":"));
-			append(credentials, authPassword_);
-			append(data, Base64::encode(credentials));
-			append(data, createSafeByteArray("\r\n"));
-		}
+void HTTPConnectProxiedConnection::initializeProxy() {
+	std::stringstream connect;
+	connect << "CONNECT " << getServer().getAddress().toString() << ":" << getServer().getPort() << " HTTP/1.1\r\n";
+	SafeByteArray data = createSafeByteArray(connect.str());
+	if (!authID_.empty() && !authPassword_.empty()) {
+		append(data, createSafeByteArray("Proxy-Authorization: Basic "));
+		SafeByteArray credentials = authID_;
+		append(credentials, createSafeByteArray(":"));
+		append(credentials, authPassword_);
+		append(data, Base64::encode(credentials));
 		append(data, createSafeByteArray("\r\n"));
-		SWIFT_LOG(debug) << "HTTP Proxy send headers: " << byteArrayToString(ByteArray(data.begin(), data.end())) << std::endl;
-		connection_->write(data);
-	}
-	else {
-		onConnectFinished(true);
 	}
+	append(data, createSafeByteArray("\r\n"));
+	SWIFT_LOG(debug) << "HTTP Proxy send headers: " << byteArrayToString(ByteArray(data.begin(), data.end())) << std::endl;
+	write(data);
 }
 
-void HTTPConnectProxiedConnection::handleDataRead(boost::shared_ptr<SafeByteArray> data) {
-	if (!connected_) {
-		SWIFT_LOG(debug) << byteArrayToString(ByteArray(data->begin(), data->end())) << std::endl;
-		std::vector<std::string> tmp = String::split(byteArrayToString(ByteArray(data->begin(), data->end())), ' ');
-		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;
-			}
-			SWIFT_LOG(debug) << "HTTP Proxy returned an error: " << byteArrayToString(ByteArray(data->begin(), data->end())) << std::endl;
+void HTTPConnectProxiedConnection::handleProxyInitializeData(boost::shared_ptr<SafeByteArray> data) {
+	SWIFT_LOG(debug) << byteArrayToString(ByteArray(data->begin(), data->end())) << std::endl;
+	std::vector<std::string> tmp = String::split(byteArrayToString(ByteArray(data->begin(), data->end())), ' ');
+	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
+			setProxyInitializeFinished(true);
+			return;
 		}
-		disconnect();
-		onConnectFinished(true);
-	}
-	else {
-		onDataRead(data);
+		SWIFT_LOG(debug) << "HTTP Proxy returned an error: " << byteArrayToString(ByteArray(data->begin(), data->end())) << std::endl;
 	}
-}
-
-HostAddressPort HTTPConnectProxiedConnection::getLocalAddress() const {
-	return connection_->getLocalAddress();
+	setProxyInitializeFinished(false);
 }
diff --git a/Swiften/Network/HTTPConnectProxiedConnection.h b/Swiften/Network/HTTPConnectProxiedConnection.h
index 8318ecc..e6c8629 100644
--- a/Swiften/Network/HTTPConnectProxiedConnection.h
+++ b/Swiften/Network/HTTPConnectProxiedConnection.h
@@ -13,59 +13,30 @@
 
 #pragma once
 
-#include <boost/enable_shared_from_this.hpp>
-
-#include <Swiften/Network/Connection.h>
-#include <Swiften/Network/Connector.h>
-#include <Swiften/Network/HostAddressPort.h>
-#include <Swiften/Base/SafeString.h>
-
-namespace boost {
-	class thread;
-	namespace system {
-		class error_code;
-	}
-}
+#include <Swiften/Network/ProxiedConnection.h>
 
 namespace Swift {
+	class DomainNameResolver;
 	class ConnectionFactory;
 	class EventLoop;
+	class TimerFactory;
 
-	class HTTPConnectProxiedConnection : public Connection, public boost::enable_shared_from_this<HTTPConnectProxiedConnection> {
+	class HTTPConnectProxiedConnection : public ProxiedConnection {
 		public:
 			typedef boost::shared_ptr<HTTPConnectProxiedConnection> ref;
 
-			~HTTPConnectProxiedConnection();
-
-			static ref create(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, EventLoop* eventLoop, const std::string& proxyHost, int proxyPort, const SafeString& authID, const SafeString& authPassword) {
-				return ref(new HTTPConnectProxiedConnection(resolver, connectionFactory, timerFactory, eventLoop, proxyHost, proxyPort, authID, authPassword));
+			static ref create(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort, const SafeString& authID, const SafeString& authPassword) {
+				return ref(new HTTPConnectProxiedConnection(resolver, connectionFactory, timerFactory, proxyHost, proxyPort, authID, authPassword));
 			}
 
-			virtual void listen();
-			virtual void connect(const HostAddressPort& address);
-			virtual void disconnect();
-			virtual void write(const SafeByteArray& data);
-
-			virtual HostAddressPort getLocalAddress() const;
 		private:
-			HTTPConnectProxiedConnection(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, EventLoop* eventLoop, const std::string& proxyHost, int proxyPort, const SafeString& authID, const SafeString& authPassword);
+			HTTPConnectProxiedConnection(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort, const SafeString& authID, const SafeString& authPassword);
 
-			void handleConnectFinished(Connection::ref connection);
-			void handleDataRead(boost::shared_ptr<SafeByteArray> data);
-			void handleDisconnected(const boost::optional<Error>& error);
-			void cancelConnector();
+			virtual void initializeProxy();
+			virtual void handleProxyInitializeData(boost::shared_ptr<SafeByteArray> data);
 
 		private:
-			bool connected_;
-			DomainNameResolver* resolver_;
-			ConnectionFactory* connectionFactory_;	
-			TimerFactory* timerFactory_;
-			std::string proxyHost_;
-			int proxyPort_;
-			HostAddressPort server_;
 			SafeByteArray authID_;
 			SafeByteArray authPassword_;
-			Connector::ref connector_;
-			boost::shared_ptr<Connection> connection_;
 	};
 }
diff --git a/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp b/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp
index 14d702c..cf4cef5 100644
--- a/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp
+++ b/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp
@@ -16,15 +16,15 @@
 
 namespace Swift {
 
-HTTPConnectProxiedConnectionFactory::HTTPConnectProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, EventLoop* eventLoop, const std::string& proxyHost, int proxyPort) : resolver_(resolver), connectionFactory_(connectionFactory), timerFactory_(timerFactory), eventLoop_(eventLoop), proxyHost_(proxyHost), proxyPort_(proxyPort),  authID_(""), authPassword_("") {
+HTTPConnectProxiedConnectionFactory::HTTPConnectProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort) : resolver_(resolver), connectionFactory_(connectionFactory), timerFactory_(timerFactory), proxyHost_(proxyHost), proxyPort_(proxyPort),  authID_(""), authPassword_("") {
 }
 
 
-HTTPConnectProxiedConnectionFactory::HTTPConnectProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, EventLoop* eventLoop, const std::string& proxyHost, int proxyPort, const SafeString& authID, const SafeString& authPassword) : resolver_(resolver), connectionFactory_(connectionFactory), timerFactory_(timerFactory), eventLoop_(eventLoop), proxyHost_(proxyHost), proxyPort_(proxyPort), authID_(authID), authPassword_(authPassword) {
+HTTPConnectProxiedConnectionFactory::HTTPConnectProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort, const SafeString& authID, const SafeString& authPassword) : resolver_(resolver), connectionFactory_(connectionFactory), timerFactory_(timerFactory), proxyHost_(proxyHost), proxyPort_(proxyPort), authID_(authID), authPassword_(authPassword) {
 }
 
 boost::shared_ptr<Connection> HTTPConnectProxiedConnectionFactory::createConnection() {
-	return HTTPConnectProxiedConnection::create(resolver_, connectionFactory_, timerFactory_, eventLoop_, proxyHost_, proxyPort_, authID_, authPassword_);
+	return HTTPConnectProxiedConnection::create(resolver_, connectionFactory_, timerFactory_, proxyHost_, proxyPort_, authID_, authPassword_);
 }
 
 }
diff --git a/Swiften/Network/HTTPConnectProxiedConnectionFactory.h b/Swiften/Network/HTTPConnectProxiedConnectionFactory.h
index 7d003e8..3efcecd 100644
--- a/Swiften/Network/HTTPConnectProxiedConnectionFactory.h
+++ b/Swiften/Network/HTTPConnectProxiedConnectionFactory.h
@@ -22,8 +22,8 @@ namespace Swift {
 	class EventLoop;
 	class HTTPConnectProxiedConnectionFactory : public ConnectionFactory {
 		public:
-			HTTPConnectProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, EventLoop* eventLoop, const std::string& proxyHost, int proxyPort);
-			HTTPConnectProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, EventLoop* eventLoop, const std::string& proxyHost, int proxyPort, const SafeString& authID, const SafeString& authPassword);
+			HTTPConnectProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort);
+			HTTPConnectProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort, const SafeString& authID, const SafeString& authPassword);
 
 			virtual boost::shared_ptr<Connection> createConnection();
 
@@ -31,7 +31,6 @@ namespace Swift {
 			DomainNameResolver* resolver_;
 			ConnectionFactory* connectionFactory_;
 			TimerFactory* timerFactory_;
-			EventLoop* eventLoop_;
 			std::string proxyHost_;
 			int proxyPort_;
 			SafeString authID_;
diff --git a/Swiften/Network/HostNameOrAddress.cpp b/Swiften/Network/HostNameOrAddress.cpp
new file mode 100644
index 0000000..bc2737d
--- /dev/null
+++ b/Swiften/Network/HostNameOrAddress.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Network/HostNameOrAddress.h>
+
+using namespace Swift;
+
+namespace {
+	struct ToStringVisitor : public boost::static_visitor<std::string> {
+			std::string operator()(const HostAddress& address) const {
+				return address.toString();
+			}
+			
+			std::string operator()(const std::string & str) const {
+				return str;
+			}
+	};
+}
+
+namespace Swift {
+
+std::string toString(const HostNameOrAddress& address) {
+	return boost::apply_visitor(ToStringVisitor(), address);
+}
+
+}
diff --git a/Swiften/Network/HostNameOrAddress.h b/Swiften/Network/HostNameOrAddress.h
new file mode 100644
index 0000000..f804d15
--- /dev/null
+++ b/Swiften/Network/HostNameOrAddress.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2012 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+#pragma once
+
+#include <string>
+#include <Swiften/Network/HostAddress.h>
+#include <boost/variant.hpp>
+
+namespace Swift {
+	typedef boost::variant<std::string, HostAddress> HostNameOrAddress;
+
+	std::string toString(const HostNameOrAddress& address);
+}
diff --git a/Swiften/Network/ProxiedConnection.cpp b/Swiften/Network/ProxiedConnection.cpp
new file mode 100644
index 0000000..8bf12d3
--- /dev/null
+++ b/Swiften/Network/ProxiedConnection.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2012 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+
+#include <Swiften/Network/ProxiedConnection.h>
+
+#include <iostream>
+#include <boost/bind.hpp>
+
+#include <Swiften/Base/ByteArray.h>
+#include <Swiften/Network/HostAddressPort.h>
+#include <Swiften/Network/ConnectionFactory.h>
+
+using namespace Swift;
+
+ProxiedConnection::ProxiedConnection(
+		DomainNameResolver* resolver, 
+		ConnectionFactory* connectionFactory, 
+		TimerFactory* timerFactory, 
+		const std::string& proxyHost, 
+		int proxyPort) : 
+			resolver_(resolver),
+			connectionFactory_(connectionFactory), 
+			timerFactory_(timerFactory), 
+			proxyHost_(proxyHost), 
+			proxyPort_(proxyPort), 
+			server_(HostAddressPort(HostAddress("0.0.0.0"), 0)) {
+	connected_ = false;
+}
+
+ProxiedConnection::~ProxiedConnection() {
+	cancelConnector();
+	if (connection_) {
+		connection_->onDataRead.disconnect(boost::bind(&ProxiedConnection::handleDataRead, shared_from_this(), _1));
+		connection_->onDisconnected.disconnect(boost::bind(&ProxiedConnection::handleDisconnected, shared_from_this(), _1));
+	}
+	if (connected_) {
+		std::cerr << "Warning: Connection was still established." << std::endl;
+	}
+}
+
+void ProxiedConnection::cancelConnector() {
+	if (connector_) {
+		connector_->onConnectFinished.disconnect(boost::bind(&ProxiedConnection::handleConnectFinished, shared_from_this(), _1));
+		connector_->stop();
+		connector_.reset();
+	}
+}
+
+void ProxiedConnection::connect(const HostAddressPort& server) {
+	server_ = server;
+
+	connector_ = Connector::create(proxyHost_, proxyPort_, false, resolver_, connectionFactory_, timerFactory_);
+	connector_->onConnectFinished.connect(boost::bind(&ProxiedConnection::handleConnectFinished, shared_from_this(), _1));
+	connector_->start();
+}
+
+void ProxiedConnection::listen() {
+	assert(false);
+	connection_->listen();
+}
+
+void ProxiedConnection::disconnect() {
+	connected_ = false;
+	connection_->disconnect();
+}
+
+void ProxiedConnection::handleDisconnected(const boost::optional<Error>& error) {
+	onDisconnected(error);
+}
+
+void ProxiedConnection::write(const SafeByteArray& data) {
+	connection_->write(data);
+}
+
+void ProxiedConnection::handleConnectFinished(Connection::ref connection) {
+	cancelConnector();
+	if (connection) {
+		connection_ = connection;
+		connection_->onDataRead.connect(boost::bind(&ProxiedConnection::handleDataRead, shared_from_this(), _1));
+		connection_->onDisconnected.connect(boost::bind(&ProxiedConnection::handleDisconnected, shared_from_this(), _1));
+		
+		initializeProxy();
+	}
+	else {
+		onConnectFinished(true);
+	}
+}
+
+void ProxiedConnection::handleDataRead(boost::shared_ptr<SafeByteArray> data) {
+	if (!connected_) {
+		handleProxyInitializeData(data);
+	}
+	else {
+		onDataRead(data);
+	}
+}
+
+HostAddressPort ProxiedConnection::getLocalAddress() const {
+	return connection_->getLocalAddress();
+}
+
+void ProxiedConnection::setProxyInitializeFinished(bool success) {
+	connected_ = success;
+	if (!success) {
+		disconnect();
+	}
+	onConnectFinished(!success);
+}
diff --git a/Swiften/Network/ProxiedConnection.h b/Swiften/Network/ProxiedConnection.h
new file mode 100644
index 0000000..aa8df38
--- /dev/null
+++ b/Swiften/Network/ProxiedConnection.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+
+#pragma once
+
+#include <boost/enable_shared_from_this.hpp>
+
+#include <Swiften/Network/Connection.h>
+#include <Swiften/Network/Connector.h>
+#include <Swiften/Network/HostAddressPort.h>
+#include <Swiften/Base/SafeString.h>
+
+namespace boost {
+	class thread;
+	namespace system {
+		class error_code;
+	}
+}
+
+namespace Swift {
+	class ConnectionFactory;
+
+	class ProxiedConnection : public Connection, public boost::enable_shared_from_this<ProxiedConnection> {
+		public:
+			ProxiedConnection(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort);
+			~ProxiedConnection();
+
+			virtual void listen();
+			virtual void connect(const HostAddressPort& address);
+			virtual void disconnect();
+			virtual void write(const SafeByteArray& data);
+
+			virtual HostAddressPort getLocalAddress() const;
+
+		private:
+			void handleConnectFinished(Connection::ref connection);
+			void handleDataRead(boost::shared_ptr<SafeByteArray> data);
+			void handleDisconnected(const boost::optional<Error>& error);
+			void cancelConnector();
+
+		protected:
+			void setProxyInitializeFinished(bool success);
+
+			virtual void initializeProxy() = 0;
+			virtual void handleProxyInitializeData(boost::shared_ptr<SafeByteArray> data) = 0;
+
+			const HostAddressPort& getServer() const {
+				return server_;
+			}
+
+		private:
+			bool connected_;
+			DomainNameResolver* resolver_;
+			ConnectionFactory* connectionFactory_;	
+			TimerFactory* timerFactory_;
+			std::string proxyHost_;
+			int proxyPort_;
+			HostAddressPort server_;
+			Connector::ref connector_;
+			boost::shared_ptr<Connection> connection_;
+	};
+}
+
diff --git a/Swiften/Network/SConscript b/Swiften/Network/SConscript
index 54565b4..ea45149 100644
--- a/Swiften/Network/SConscript
+++ b/Swiften/Network/SConscript
@@ -3,6 +3,7 @@ Import("swiften_env")
 myenv = swiften_env.Clone()
 
 sourceList = [
+			"ProxiedConnection.cpp",
 			"HTTPConnectProxiedConnection.cpp",
 			"HTTPConnectProxiedConnectionFactory.cpp",
 			"SOCKS5ProxiedConnection.cpp",
@@ -35,6 +36,7 @@ sourceList = [
 			"StaticDomainNameResolver.cpp",
 			"HostAddress.cpp",
 			"HostAddressPort.cpp",
+			"HostNameOrAddress.cpp",
 			"NetworkFactories.cpp",
 			"BoostNetworkFactories.cpp",
 			"NetworkEnvironment.cpp",
diff --git a/Swiften/Network/SOCKS5ProxiedConnection.cpp b/Swiften/Network/SOCKS5ProxiedConnection.cpp
index 163e23a..bf7a056 100644
--- a/Swiften/Network/SOCKS5ProxiedConnection.cpp
+++ b/Swiften/Network/SOCKS5ProxiedConnection.cpp
@@ -18,157 +18,98 @@
 
 using namespace Swift;
 
-SOCKS5ProxiedConnection::SOCKS5ProxiedConnection(ConnectionFactory* connectionFactory, const 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 SafeByteArray& data) {
-	if (connection_) {
-		connection_->write(data);
-	}
-}
+SOCKS5ProxiedConnection::SOCKS5ProxiedConnection(
+		DomainNameResolver* resolver, 
+		ConnectionFactory* connectionFactory, 
+		TimerFactory* timerFactory, 
+		const std::string& proxyHost, 
+		int proxyPort) :
+			ProxiedConnection(resolver, connectionFactory, timerFactory, proxyHost, proxyPort) {
+			}
 
-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;
-		SafeByteArray socksConnect;
-		socksConnect.push_back(0x05); // VER = SOCKS5 = 0x05
-		socksConnect.push_back(0x01); // Number of authentication methods after this byte.
-		socksConnect.push_back(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::initializeProxy() {
+	proxyState_ = ProxyAuthenticating;
+	SafeByteArray socksConnect;
+	socksConnect.push_back(0x05); // VER = SOCKS5 = 0x05
+	socksConnect.push_back(0x01); // Number of authentication methods after this byte.
+	socksConnect.push_back(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)
+	write(socksConnect);
 }
 
-void SOCKS5ProxiedConnection::handleDataRead(boost::shared_ptr<SafeByteArray> data) {
+void SOCKS5ProxiedConnection::handleProxyInitializeData(boost::shared_ptr<SafeByteArray> data) {
 	SafeByteArray socksConnect;
-	boost::asio::ip::address rawAddress = server_.getAddress().getRawAddress();
+	boost::asio::ip::address rawAddress = getServer().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.push_back(0x05); // VER = SOCKS5 = 0x05
-							socksConnect.push_back(0x01); // Construct a TCP connection. (CMD)
-							socksConnect.push_back(0x00); // reserved.
-							socksConnect.push_back(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.push_back(static_cast<char>(uc));
-						
+
+	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.push_back(0x05); // VER = SOCKS5 = 0x05
+						socksConnect.push_back(0x01); // Construct a TCP connection. (CMD)
+						socksConnect.push_back(0x00); // reserved.
+						socksConnect.push_back(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.
 							}
-							socksConnect.push_back(static_cast<unsigned char> ((server_.getPort() >> 8) & 0xFF)); // highbyte of the port.
-							socksConnect.push_back(static_cast<unsigned char> (server_.getPort() & 0xFF)); // lowbyte of the port.
-							connection_->write(socksConnect);
-							return;
-						}
-						catch(...) {
-							std::cerr << "exception caught" << std::endl;
+							else {
+								uc = rawAddress.to_v6().to_bytes()[s]; // the address.
+							}
+							socksConnect.push_back(static_cast<char>(uc));
+					
 						}
-						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;
+						socksConnect.push_back(static_cast<unsigned char> ((getServer().getPort() >> 8) & 0xFF)); // highbyte of the port.
+						socksConnect.push_back(static_cast<unsigned char> (getServer().getPort() & 0xFF)); // lowbyte of the port.
+						write(socksConnect);
+						return;
+					}
+					catch(...) {
+						std::cerr << "exception caught" << std::endl;
+					}
+					write(socksConnect);
+					break;
+				default:
+					setProxyInitializeFinished(true);
+					break;
 			}
 			return;
 		}
+		setProxyInitializeFinished(false);
 	}
-	else {
-		onDataRead(data);
-		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;
+			setProxyInitializeFinished(true);
+		}
+		else {
+			std::cerr << "SOCKS Proxy returned an error: " << std::hex << (*data)[1] << std::endl;
+			setProxyInitializeFinished(false);
+		}
 	}
-	disconnect();
-	onConnectFinished(true);
-}
-
-HostAddressPort SOCKS5ProxiedConnection::getLocalAddress() const {
-	return connection_->getLocalAddress();
 }
diff --git a/Swiften/Network/SOCKS5ProxiedConnection.h b/Swiften/Network/SOCKS5ProxiedConnection.h
index 592ce7d..61092e0 100644
--- a/Swiften/Network/SOCKS5ProxiedConnection.h
+++ b/Swiften/Network/SOCKS5ProxiedConnection.h
@@ -6,54 +6,31 @@
 
 #pragma once
 
-#include <boost/enable_shared_from_this.hpp>
-
-#include <Swiften/Network/Connection.h>
-#include <Swiften/Network/HostAddressPort.h>
-
-namespace boost {
-	class thread;
-	namespace system {
-		class error_code;
-	}
-}
+#include <Swiften/Network/ProxiedConnection.h>
 
 namespace Swift {
 	class ConnectionFactory;
+	class DomainNameResolver;
+	class TimerFactory;
 
-	class SOCKS5ProxiedConnection : public Connection, public boost::enable_shared_from_this<SOCKS5ProxiedConnection> {
+	class SOCKS5ProxiedConnection : public ProxiedConnection {
 		public:
 			typedef boost::shared_ptr<SOCKS5ProxiedConnection> ref;
 
-			~SOCKS5ProxiedConnection();
-
-			static ref create(ConnectionFactory* connectionFactory, const HostAddressPort& proxy) {
-				return ref(new SOCKS5ProxiedConnection(connectionFactory, proxy));
+			static ref create(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort) {
+				return ref(new SOCKS5ProxiedConnection(resolver, connectionFactory, timerFactory, proxyHost, proxyPort));
 			}
 
-			virtual void listen();
-			virtual void connect(const HostAddressPort& address);
-			virtual void disconnect();
-			virtual void write(const SafeByteArray& data);
-
-			virtual HostAddressPort getLocalAddress() const;
-
 		private:
-			SOCKS5ProxiedConnection(ConnectionFactory* connectionFactory, const HostAddressPort& proxy);
+			SOCKS5ProxiedConnection(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort);
 
-			void handleConnectionConnectFinished(bool error);
-			void handleDataRead(boost::shared_ptr<SafeByteArray> data);
-			void handleDisconnected(const boost::optional<Error>& error);
+			virtual void initializeProxy();
+			virtual void handleProxyInitializeData(boost::shared_ptr<SafeByteArray> data);
 
 		private:
 			enum {
 				ProxyAuthenticating = 0,
 				ProxyConnecting,
 			} proxyState_;
-			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
index 272ade9..af99034 100644
--- a/Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp
+++ b/Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp
@@ -10,11 +10,11 @@
 
 namespace Swift {
 
-SOCKS5ProxiedConnectionFactory::SOCKS5ProxiedConnectionFactory(ConnectionFactory* connectionFactory, const HostAddressPort& proxy) : connectionFactory_(connectionFactory), proxy_(proxy) {
+SOCKS5ProxiedConnectionFactory::SOCKS5ProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort) : resolver_(resolver), connectionFactory_(connectionFactory), timerFactory_(timerFactory), proxyHost_(proxyHost), proxyPort_(proxyPort) {
 }
 
 boost::shared_ptr<Connection> SOCKS5ProxiedConnectionFactory::createConnection() {
-	return SOCKS5ProxiedConnection::create(connectionFactory_, proxy_);
+	return SOCKS5ProxiedConnection::create(resolver_, connectionFactory_, timerFactory_, proxyHost_, proxyPort_);
 }
 
 }
diff --git a/Swiften/Network/SOCKS5ProxiedConnectionFactory.h b/Swiften/Network/SOCKS5ProxiedConnectionFactory.h
index f36d42a..4c5c585 100644
--- a/Swiften/Network/SOCKS5ProxiedConnectionFactory.h
+++ b/Swiften/Network/SOCKS5ProxiedConnectionFactory.h
@@ -8,16 +8,23 @@
 
 #include <Swiften/Network/ConnectionFactory.h>
 #include <Swiften/Network/HostAddressPort.h>
+#include <Swiften/Network/HostNameOrAddress.h>
 
 namespace Swift {
+	class DomainNameResolver;
+	class TimerFactory;
+
 	class SOCKS5ProxiedConnectionFactory : public ConnectionFactory {
 		public:
-			SOCKS5ProxiedConnectionFactory(ConnectionFactory* connectionFactory, const HostAddressPort& proxy);
+			SOCKS5ProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort);
 
 			virtual boost::shared_ptr<Connection> createConnection();
 
 		private:
+			DomainNameResolver* resolver_;
 			ConnectionFactory* connectionFactory_;
-			HostAddressPort proxy_;
+			TimerFactory* timerFactory_;
+			std::string proxyHost_;
+			int proxyPort_;
 	};
 }
diff --git a/Swiften/Network/UnitTest/BOSHConnectionTest.cpp b/Swiften/Network/UnitTest/BOSHConnectionTest.cpp
index e0dc0bf..31aed1b 100644
--- a/Swiften/Network/UnitTest/BOSHConnectionTest.cpp
+++ b/Swiften/Network/UnitTest/BOSHConnectionTest.cpp
@@ -192,7 +192,7 @@ class BOSHConnectionTest : public CppUnit::TestFixture {
 
 		BOSHConnection::ref createTestling() {
 			resolver->addAddress("wonderland.lit", HostAddress("127.0.0.1"));
-			Connector::ref connector = Connector::create("wonderland.lit", resolver, connectionFactory, timerFactory, 5280);
+			Connector::ref connector = Connector::create("wonderland.lit", 5280, false, resolver, connectionFactory, timerFactory);
 			BOSHConnection::ref c = BOSHConnection::create(URL("http", "wonderland.lit", 5280, "http-bind"), connector, &parserFactory);
 			c->onConnectFinished.connect(boost::bind(&BOSHConnectionTest::handleConnectFinished, this, _1));
 			c->onDisconnected.connect(boost::bind(&BOSHConnectionTest::handleDisconnected, this, _1));
diff --git a/Swiften/Network/UnitTest/ChainedConnectorTest.cpp b/Swiften/Network/UnitTest/ChainedConnectorTest.cpp
index a2fceb9..9abed57 100644
--- a/Swiften/Network/UnitTest/ChainedConnectorTest.cpp
+++ b/Swiften/Network/UnitTest/ChainedConnectorTest.cpp
@@ -126,7 +126,7 @@ class ChainedConnectorTest : public CppUnit::TestFixture {
 			std::vector<ConnectionFactory*> factories;
 			factories.push_back(connectionFactory1);
 			factories.push_back(connectionFactory2);
-			boost::shared_ptr<ChainedConnector> connector = boost::make_shared<ChainedConnector>("foo.com", resolver, factories, timerFactory);
+			boost::shared_ptr<ChainedConnector> connector = boost::make_shared<ChainedConnector>("foo.com", -1, true, resolver, factories, timerFactory);
 			connector->onConnectFinished.connect(boost::bind(&ChainedConnectorTest::handleConnectorFinished, this, _1, _2));
 			return connector;
 		}
diff --git a/Swiften/Network/UnitTest/ConnectorTest.cpp b/Swiften/Network/UnitTest/ConnectorTest.cpp
index 67270be..2d96bda 100644
--- a/Swiften/Network/UnitTest/ConnectorTest.cpp
+++ b/Swiften/Network/UnitTest/ConnectorTest.cpp
@@ -24,6 +24,8 @@ using namespace Swift;
 class ConnectorTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST_SUITE(ConnectorTest);
 		CPPUNIT_TEST(testConnect);
+		CPPUNIT_TEST(testConnect_NoServiceLookups);
+		CPPUNIT_TEST(testConnect_NoServiceLookups_DefaultPort);
 		CPPUNIT_TEST(testConnect_FirstAddressHostFails);
 		CPPUNIT_TEST(testConnect_NoSRVHost);
 		CPPUNIT_TEST(testConnect_NoHosts);
@@ -71,6 +73,38 @@ class ConnectorTest : public CppUnit::TestFixture {
 			CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
 		}
 
+		void testConnect_NoServiceLookups() {
+			Connector::ref testling(createConnector(4321, false));
+			resolver->addXMPPClientService("foo.com", host1);
+			resolver->addXMPPClientService("foo.com", host2);
+			resolver->addAddress("foo.com", host3.getAddress());
+
+			testling->start();
+			eventLoop->processEvents();
+
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+			CPPUNIT_ASSERT(connections[0]);
+			CPPUNIT_ASSERT(host3.getAddress() == (*(connections[0]->hostAddressPort)).getAddress());
+			CPPUNIT_ASSERT(4321 == (*(connections[0]->hostAddressPort)).getPort());
+			CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+		}
+
+		void testConnect_NoServiceLookups_DefaultPort() {
+			Connector::ref testling(createConnector(-1, false));
+			resolver->addXMPPClientService("foo.com", host1);
+			resolver->addXMPPClientService("foo.com", host2);
+			resolver->addAddress("foo.com", host3.getAddress());
+
+			testling->start();
+			eventLoop->processEvents();
+
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+			CPPUNIT_ASSERT(connections[0]);
+			CPPUNIT_ASSERT(host3.getAddress() == (*(connections[0]->hostAddressPort)).getAddress());
+			CPPUNIT_ASSERT_EQUAL(5222, (*(connections[0]->hostAddressPort)).getPort());
+			CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+		}
+
 		void testConnect_NoSRVHost() {
 			Connector::ref testling(createConnector());
 			resolver->addAddress("foo.com", host3.getAddress());
@@ -253,8 +287,8 @@ class ConnectorTest : public CppUnit::TestFixture {
 
 
 	private:
-		Connector::ref createConnector() {
-			Connector::ref connector = Connector::create("foo.com", resolver, connectionFactory, timerFactory);
+		Connector::ref createConnector(int port = -1, bool doServiceLookups = true) {
+			Connector::ref connector = Connector::create("foo.com", port, doServiceLookups, resolver, connectionFactory, timerFactory);
 			connector->onConnectFinished.connect(boost::bind(&ConnectorTest::handleConnectorFinished, this, _1, _2));
 			return connector;
 		}
diff --git a/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp b/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp
index 347a145..134748f 100644
--- a/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp
+++ b/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp
@@ -170,7 +170,7 @@ class HTTPConnectProxiedConnectionTest : public CppUnit::TestFixture {
 
 	private:
 		HTTPConnectProxiedConnection::ref createTestling() {
-			boost::shared_ptr<HTTPConnectProxiedConnection> c = HTTPConnectProxiedConnection::create(resolver, connectionFactory, timerFactory, eventLoop, proxyHost, proxyPort, "", "");
+			boost::shared_ptr<HTTPConnectProxiedConnection> c = HTTPConnectProxiedConnection::create(resolver, connectionFactory, timerFactory, proxyHost, proxyPort, "", "");
 			c->onConnectFinished.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleConnectFinished, this, _1));
 			c->onDisconnected.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleDisconnected, this, _1));
 			c->onDataRead.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleDataRead, this, _1));
-- 
cgit v0.10.2-6-g49f6