From 093d499945d779cfed92b45e413644834004b0d9 Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Tue, 17 Jan 2012 07:54:39 +0000
Subject: Allow specifying BOSH and BOSH proxy URLs with names (rather than
 IPs)


diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index 046120d..6f93dd3 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -505,6 +505,10 @@ void MainController::performLoginFromCachedCredentials() {
 	ClientOptions clientOptions;
 	clientOptions.forgetPassword = eagleMode_;
 	clientOptions.useTLS = eagleMode_ ? ClientOptions::RequireTLS : ClientOptions::UseTLSWhenAvailable;
+	/*if (clientJID.getDomain() == "doomsong.co.uk") {
+		clientOptions.boshURL = URL("https", "channels.doomsong.co.uk", 11443, "http-bind/");
+		clientOptions.boshHTTPConnectProxyURL = URL("http", "squidproxy.doomsong.co.uk", 8123, "");
+	}*/
 	client_->connect(clientOptions);
 }
 
diff --git a/Swiften/Client/ClientOptions.h b/Swiften/Client/ClientOptions.h
index 06bf947..fbec272 100644
--- a/Swiften/Client/ClientOptions.h
+++ b/Swiften/Client/ClientOptions.h
@@ -67,7 +67,6 @@ namespace Swift {
 
 		/**
 		 * If non-empty, use BOSH instead of direct TCP, with the given URL.
-		 * The host currently needs to be specified by IP, rather than hostname.
 		 * Default: empty (no BOSH)
 		 */
 		URL boshURL;
@@ -75,7 +74,6 @@ namespace Swift {
 		/**
 		 * If non-empty, BOSH connections will try to connect over this HTTP CONNECT
 		 * proxy instead of directly.
-		 * Must be specified by IP, rather than hostname.
 		 * Default: empty (no proxy)
 		 */
 		URL boshHTTPConnectProxyURL;
diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp
index 49fb9fa..de12fb7 100644
--- a/Swiften/Client/CoreClient.cpp
+++ b/Swiften/Client/CoreClient.cpp
@@ -67,7 +67,7 @@ void CoreClient::connect(const std::string& host) {
 		proxyConnectionFactories.push_back(new SOCKS5ProxiedConnectionFactory(networkFactories->getConnectionFactory(), networkFactories->getProxyProvider()->getSOCKS5Proxy()));
 	}
 	if(networkFactories->getProxyProvider()->getHTTPConnectProxy().isValid()) {
-		proxyConnectionFactories.push_back(new HTTPConnectProxiedConnectionFactory(networkFactories->getConnectionFactory(), networkFactories->getProxyProvider()->getHTTPConnectProxy()));
+		proxyConnectionFactories.push_back(new HTTPConnectProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), networkFactories->getEventLoop(), networkFactories->getProxyProvider()->getHTTPConnectProxy().getAddress().toString(), networkFactories->getProxyProvider()->getHTTPConnectProxy().getPort()));
 	}
 	std::vector<ConnectionFactory*> connectionFactories(proxyConnectionFactories);
 	if (options.boshURL.empty()) {
@@ -87,13 +87,14 @@ void CoreClient::connect(const std::string& host) {
 				getPayloadParserFactories(),
 				getPayloadSerializers(),
 				networkFactories->getConnectionFactory(),
-				networkFactories->getTLSContextFactory(), 
-				networkFactories->getTimerFactory(), 
+				networkFactories->getTLSContextFactory(),
+				networkFactories->getTimerFactory(),
 				networkFactories->getXMLParserFactory(),
-				networkFactories->getEventLoop(), 
-				host, 
-				options.boshHTTPConnectProxyURL, 
-				options.boshHTTPConnectProxyAuthID, 
+				networkFactories->getEventLoop(),
+				networkFactories->getDomainNameResolver(),
+				host,
+				options.boshHTTPConnectProxyURL,
+				options.boshHTTPConnectProxyAuthID,
 				options.boshHTTPConnectProxyAuthPassword));
 		sessionStream_->onDataRead.connect(boost::bind(&CoreClient::handleDataRead, this, _1));
 		sessionStream_->onDataWritten.connect(boost::bind(&CoreClient::handleDataWritten, this, _1));
diff --git a/Swiften/Network/BOSHConnection.cpp b/Swiften/Network/BOSHConnection.cpp
index ea84400..73f8ed6 100644
--- a/Swiften/Network/BOSHConnection.cpp
+++ b/Swiften/Network/BOSHConnection.cpp
@@ -17,32 +17,29 @@
 #include <boost/lexical_cast.hpp>
 #include <string>
 
-#include <Swiften/Network/ConnectionFactory.h>
 #include <Swiften/Base/Log.h>
 #include <Swiften/Base/String.h>
 #include <Swiften/Base/Concat.h>
 #include <Swiften/Base/ByteArray.h>
 #include <Swiften/Network/HostAddressPort.h>
-#include <Swiften/Network/TLSConnection.h>
 #include <Swiften/Parser/BOSHBodyExtractor.h>
 
 namespace Swift {
 
-BOSHConnection::BOSHConnection(const URL& boshURL, ConnectionFactory* connectionFactory, XMLParserFactory* parserFactory, TLSContextFactory* tlsFactory)
-	: boshURL_(boshURL), 
-	  connectionFactory_(connectionFactory), 
+BOSHConnection::BOSHConnection(const URL& boshURL, Connector::ref connector, XMLParserFactory* parserFactory)
+	: boshURL_(boshURL),
+	  connector_(connector),
 	  parserFactory_(parserFactory),
 	  sid_(),
 	  waitingForStartResponse_(false),
 	  pending_(false),
-	  tlsFactory_(tlsFactory),
 	  connectionReady_(false)
 {
 }
 
 BOSHConnection::~BOSHConnection() {
+	cancelConnector();
 	if (connection_) {
-		connection_->onConnectFinished.disconnect(boost::bind(&BOSHConnection::handleConnectionConnectFinished, shared_from_this(), _1));
 		connection_->onDataRead.disconnect(boost::bind(&BOSHConnection::handleDataRead, shared_from_this(), _1));
 		connection_->onDisconnected.disconnect(boost::bind(&BOSHConnection::handleDisconnected, shared_from_this(), _1));
 	}
@@ -50,15 +47,20 @@ BOSHConnection::~BOSHConnection() {
 }
 
 void BOSHConnection::connect() {
-	Connection::ref rawConnection = connectionFactory_->createConnection();
-	connection_ = (boshURL_.getScheme() == "https") ? boost::make_shared<TLSConnection>(rawConnection, tlsFactory_) : rawConnection;
-	connection_->onConnectFinished.connect(boost::bind(&BOSHConnection::handleConnectionConnectFinished, shared_from_this(), _1));
-	connection_->onDataRead.connect(boost::bind(&BOSHConnection::handleDataRead, shared_from_this(), _1));
-	connection_->onDisconnected.connect(boost::bind(&BOSHConnection::handleDisconnected, shared_from_this(), _1));
-	connection_->connect(HostAddressPort(HostAddress(boshURL_.getHost()), boshURL_.getPort()));
+	connector_->onConnectFinished.connect(boost::bind(&BOSHConnection::handleConnectFinished, shared_from_this(), _1));
+	connector_->start();
+}
+
+void BOSHConnection::cancelConnector() {
+	if (connector_) {
+		connector_->onConnectFinished.disconnect(boost::bind(&BOSHConnection::handleConnectFinished, shared_from_this(), _1));
+		connector_->stop();
+		connector_.reset();
+	}
 }
 
 void BOSHConnection::disconnect() {
+	cancelConnector();
 	if(connection_) {
 		connection_->disconnect();
 		sid_ = "";
@@ -78,7 +80,7 @@ void BOSHConnection::write(const SafeByteArray& data) {
 	write(data, false, false);
 }
 
-std::pair<SafeByteArray, size_t> BOSHConnection::createHTTPRequest(const SafeByteArray& data, bool streamRestart, bool terminate, long rid, const std::string& sid, const URL& boshURL) {
+std::pair<SafeByteArray, size_t> BOSHConnection::createHTTPRequest(const SafeByteArray& data, bool streamRestart, bool terminate, unsigned long long rid, const std::string& sid, const URL& boshURL) {
 	size_t size;
 	std::stringstream content;
 	SafeByteArray contentTail = createSafeByteArray("</body>");
@@ -124,13 +126,18 @@ void BOSHConnection::write(const SafeByteArray& data, bool streamRestart, bool t
 	SWIFT_LOG(debug) << "write data: " << safeByteArrayToString(safeHeader) << std::endl;
 }
 
-void BOSHConnection::handleConnectionConnectFinished(bool error) {
-	connection_->onConnectFinished.disconnect(boost::bind(&BOSHConnection::handleConnectionConnectFinished, shared_from_this(), _1));
-	connectionReady_ = !error;
-	onConnectFinished(error);
+void BOSHConnection::handleConnectFinished(Connection::ref connection) {
+	cancelConnector();
+	connectionReady_ = connection;
+	if (connectionReady_) {
+		connection_ = connection;
+		connection_->onDataRead.connect(boost::bind(&BOSHConnection::handleDataRead, shared_from_this(), _1));
+		connection_->onDisconnected.connect(boost::bind(&BOSHConnection::handleDisconnected, shared_from_this(), _1));
+	}
+	onConnectFinished(!connectionReady_);
 }
 
-void BOSHConnection::startStream(const std::string& to, unsigned long rid) {
+void BOSHConnection::startStream(const std::string& to, unsigned long long rid) {
 	assert(connectionReady_);
 	// Session Creation Request
 	std::stringstream content;
@@ -265,6 +272,7 @@ void BOSHConnection::setSID(const std::string& sid) {
 }
 
 void BOSHConnection::handleDisconnected(const boost::optional<Connection::Error>& error) {
+	cancelConnector();
 	onDisconnected(error);
 	sid_ = "";
 	connectionReady_ = false;
diff --git a/Swiften/Network/BOSHConnection.h b/Swiften/Network/BOSHConnection.h
index 4d53253..d9fa016 100644
--- a/Swiften/Network/BOSHConnection.h
+++ b/Swiften/Network/BOSHConnection.h
@@ -16,6 +16,7 @@
 #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/String.h>
 #include <Swiften/Base/URL.h>
@@ -32,7 +33,6 @@ namespace boost {
 class BOSHConnectionTest;
 
 namespace Swift {
-	class ConnectionFactory;
 	class XMLParserFactory;
 	class TLSContextFactory;
 
@@ -54,8 +54,8 @@ namespace Swift {
 	class BOSHConnection : public boost::enable_shared_from_this<BOSHConnection> {
 		public:
 			typedef boost::shared_ptr<BOSHConnection> ref;
-			static ref create(const URL& boshURL, ConnectionFactory* connectionFactory, XMLParserFactory* parserFactory, TLSContextFactory* tlsFactory) {
-				return ref(new BOSHConnection(boshURL, connectionFactory, parserFactory, tlsFactory));
+			static ref create(const URL& boshURL, Connector::ref connector, XMLParserFactory* parserFactory) {
+				return ref(new BOSHConnection(boshURL, connector, parserFactory));
 			}
 			virtual ~BOSHConnection();
 			virtual void connect();
@@ -65,7 +65,7 @@ namespace Swift {
 			const std::string& getSID();
 			void setRID(unsigned long long rid);
 			void setSID(const std::string& sid);
-			void startStream(const std::string& to, unsigned long rid);
+			void startStream(const std::string& to, unsigned long long rid);
 			void terminateStream();
 			bool isReadyToSend();
 			void restartStream();
@@ -83,17 +83,18 @@ namespace Swift {
 		private:
 			friend class ::BOSHConnectionTest;
 
-			BOSHConnection(const URL& boshURL, ConnectionFactory* connectionFactory, XMLParserFactory* parserFactory, TLSContextFactory* tlsFactory);
+			BOSHConnection(const URL& boshURL, Connector::ref connector, XMLParserFactory* parserFactory);
 
-			static std::pair<SafeByteArray, size_t> createHTTPRequest(const SafeByteArray& data, bool streamRestart, bool terminate, long rid, const std::string& sid, const URL& boshURL);
-			void handleConnectionConnectFinished(bool error);
+			static std::pair<SafeByteArray, size_t> createHTTPRequest(const SafeByteArray& data, bool streamRestart, bool terminate, unsigned long long rid, const std::string& sid, const URL& boshURL);
+			void handleConnectFinished(Connection::ref);
 			void handleDataRead(boost::shared_ptr<SafeByteArray> data);
 			void handleDisconnected(const boost::optional<Connection::Error>& error);
 			void write(const SafeByteArray& data, bool streamRestart, bool terminate); /* FIXME: refactor */
 			BOSHError::Type parseTerminationCondition(const std::string& text);
+			void cancelConnector();
 
 			URL boshURL_;
-			ConnectionFactory* connectionFactory_;
+			Connector::ref connector_;
 			XMLParserFactory* parserFactory_;
 			boost::shared_ptr<Connection> connection_;
 			std::string sid_;
@@ -101,7 +102,6 @@ namespace Swift {
 			unsigned long long rid_;
 			SafeByteArray buffer_;
 			bool pending_;
-			TLSContextFactory* tlsFactory_;
 			bool connectionReady_;
 	};
 }
diff --git a/Swiften/Network/BOSHConnectionPool.cpp b/Swiften/Network/BOSHConnectionPool.cpp
index a30bf7b..7d43f42 100644
--- a/Swiften/Network/BOSHConnectionPool.cpp
+++ b/Swiften/Network/BOSHConnectionPool.cpp
@@ -14,38 +14,43 @@
 #include <Swiften/Base/SafeString.h>
 #include <Swiften/Network/TLSConnectionFactory.h>
 #include <Swiften/Network/HTTPConnectProxiedConnectionFactory.h>
+#include <Swiften/Network/CachingNameOnlyDomainNameResolver.h>
 
 namespace Swift {
-BOSHConnectionPool::BOSHConnectionPool(const URL& boshURL, ConnectionFactory* connectionFactory, XMLParserFactory* parserFactory, TLSContextFactory* tlsFactory, const std::string& to, long initialRID, const URL& boshHTTPConnectProxyURL, const SafeString& boshHTTPConnectProxyAuthID, const SafeString& boshHTTPConnectProxyAuthPassword) :
+BOSHConnectionPool::BOSHConnectionPool(const URL& boshURL, DomainNameResolver* realResolver, ConnectionFactory* connectionFactoryParameter, XMLParserFactory* parserFactory, TLSContextFactory* tlsFactory, TimerFactory* timerFactory, EventLoop* eventLoop, const std::string& to, unsigned long long initialRID, const URL& boshHTTPConnectProxyURL, const SafeString& boshHTTPConnectProxyAuthID, const SafeString& boshHTTPConnectProxyAuthPassword) :
 		boshURL(boshURL),
-		connectionFactory(connectionFactory),
+		connectionFactory(connectionFactoryParameter),
 		xmlParserFactory(parserFactory),
 		tlsFactory(tlsFactory),
+		timerFactory(timerFactory),
 		rid(initialRID),
 		pendingTerminate(false),
 		to(to),
 		requestLimit(2),
 		restartCount(0),
 		pendingRestart(false) {
-	tlsConnectionFactory = NULL;
-	if (boshHTTPConnectProxyURL.empty()) {
-		connectProxyFactory = NULL;
-	}
-	else {
-		ConnectionFactory* rawFactory = connectionFactory;
+
+	if (!boshHTTPConnectProxyURL.empty()) {
 		if (boshHTTPConnectProxyURL.getScheme() == "https") {
-			tlsConnectionFactory = new TLSConnectionFactory(tlsFactory, rawFactory);
-			rawFactory = tlsConnectionFactory;
+			connectionFactory = new TLSConnectionFactory(tlsFactory, connectionFactory);
+			myConnectionFactories.push_back(connectionFactory);
 		}
-		connectProxyFactory = new HTTPConnectProxiedConnectionFactory(rawFactory, HostAddressPort(HostAddress(boshHTTPConnectProxyURL.getHost()), boshHTTPConnectProxyURL.getPort()), boshHTTPConnectProxyAuthID, boshHTTPConnectProxyAuthPassword);
+		connectionFactory = new HTTPConnectProxiedConnectionFactory(realResolver, connectionFactory, timerFactory, eventLoop, boshHTTPConnectProxyURL.getHost(), boshHTTPConnectProxyURL.getPort(), boshHTTPConnectProxyAuthID, boshHTTPConnectProxyAuthPassword);
 	}
+	if (boshURL.getScheme() == "https") {
+		connectionFactory = new TLSConnectionFactory(tlsFactory, connectionFactory);
+		myConnectionFactories.push_back(connectionFactory);
+	}
+	resolver = new CachingNameOnlyDomainNameResolver(realResolver, eventLoop);
 	createConnection();
 }
 
 BOSHConnectionPool::~BOSHConnectionPool() {
 	close();
-	delete connectProxyFactory;
-	delete tlsConnectionFactory;
+	foreach (ConnectionFactory* factory, myConnectionFactories) {
+		delete factory;
+	}
+	delete resolver;
 }
 
 void BOSHConnectionPool::write(const SafeByteArray& data) {
@@ -209,7 +214,8 @@ void BOSHConnectionPool::handleConnectionDisconnected(bool error, BOSHConnection
 }
 
 boost::shared_ptr<BOSHConnection> BOSHConnectionPool::createConnection() {
-	BOSHConnection::ref connection = BOSHConnection::create(boshURL, connectProxyFactory ? connectProxyFactory : connectionFactory, xmlParserFactory, tlsFactory);
+	Connector::ref connector = Connector::create(boshURL.getHost(), resolver, connectionFactory, timerFactory, boshURL.getPort());
+	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));
 	connection->onBOSHDataRead.connect(boost::bind(&BOSHConnectionPool::handleBOSHDataRead, this, _1));
diff --git a/Swiften/Network/BOSHConnectionPool.h b/Swiften/Network/BOSHConnectionPool.h
index cc354b8..8bc0a7c 100644
--- a/Swiften/Network/BOSHConnectionPool.h
+++ b/Swiften/Network/BOSHConnectionPool.h
@@ -15,10 +15,12 @@
 namespace Swift {
 	class HTTPConnectProxiedConnectionFactory;
 	class TLSConnectionFactory;
+	class CachingNameOnlyDomainNameResolver;
+	class EventLoop;
 
 	class BOSHConnectionPool : public boost::bsignals::trackable {
 		public:
-			BOSHConnectionPool(const URL& boshURL, ConnectionFactory* connectionFactory, XMLParserFactory* parserFactory, TLSContextFactory* tlsFactory, const std::string& to, long initialRID, const URL& boshHTTPConnectProxyURL, const SafeString& boshHTTPConnectProxyAuthID, const SafeString& boshHTTPConnectProxyAuthPassword);
+			BOSHConnectionPool(const URL& boshURL, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, XMLParserFactory* parserFactory, TLSContextFactory* tlsFactory, TimerFactory* timerFactory, EventLoop* eventLoop, const std::string& to, unsigned long long initialRID, const URL& boshHTTPConnectProxyURL, const SafeString& boshHTTPConnectProxyAuthID, const SafeString& boshHTTPConnectProxyAuthPassword);
 			~BOSHConnectionPool();
 			void write(const SafeByteArray& data);
 			void writeFooter();
@@ -52,16 +54,17 @@ namespace Swift {
 			ConnectionFactory* connectionFactory;
 			XMLParserFactory* xmlParserFactory;
 			TLSContextFactory* tlsFactory;
+			TimerFactory* timerFactory;
 			std::vector<BOSHConnection::ref> connections;
 			std::string sid;
-			unsigned long rid;
+			unsigned long long rid;
 			std::vector<SafeByteArray> dataQueue;
 			bool pendingTerminate;
 			std::string to;
 			size_t requestLimit;
 			int restartCount;
 			bool pendingRestart;
-			HTTPConnectProxiedConnectionFactory* connectProxyFactory;
-			TLSConnectionFactory* tlsConnectionFactory;
+			std::vector<ConnectionFactory*> myConnectionFactories;
+			CachingNameOnlyDomainNameResolver* resolver;
 	};
 }
diff --git a/Swiften/Network/CachingNameOnlyDomainNameResolver.cpp b/Swiften/Network/CachingNameOnlyDomainNameResolver.cpp
new file mode 100644
index 0000000..a83bebd
--- /dev/null
+++ b/Swiften/Network/CachingNameOnlyDomainNameResolver.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Network/CachingNameOnlyDomainNameResolver.h>
+
+#include <boost/smart_ptr/make_shared.hpp>
+
+namespace Swift {
+CachingNameOnlyDomainNameResolver::CachingNameOnlyDomainNameResolver(DomainNameResolver* realResolver, EventLoop* eventLoop) : realResolver(realResolver) {
+	staticResolver = boost::make_shared<StaticDomainNameResolver>(eventLoop);
+}
+
+CachingNameOnlyDomainNameResolver::~CachingNameOnlyDomainNameResolver() {
+
+}
+
+DomainNameServiceQuery::ref CachingNameOnlyDomainNameResolver::createServiceQuery(const std::string& name) {
+	return staticResolver->createServiceQuery(name);
+}
+
+DomainNameAddressQuery::ref CachingNameOnlyDomainNameResolver::createAddressQuery(const std::string& name) {
+	return realResolver->createAddressQuery(name);
+}
+
+void CachingNameOnlyDomainNameResolver::handleAddressQueryResult(const std::string hostname, const std::vector<HostAddress>& address, boost::optional<DomainNameResolveError> error) {
+	//FIXME: Cache
+}
+
+}
diff --git a/Swiften/Network/CachingNameOnlyDomainNameResolver.h b/Swiften/Network/CachingNameOnlyDomainNameResolver.h
new file mode 100644
index 0000000..d9e78e6
--- /dev/null
+++ b/Swiften/Network/CachingNameOnlyDomainNameResolver.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include <Swiften/Network/DomainNameResolver.h>
+#include <Swiften/Network/StaticDomainNameResolver.h>
+
+
+namespace Swift {
+	class EventLoop;
+	class CachingNameOnlyDomainNameResolver : public DomainNameResolver {
+		public:
+			CachingNameOnlyDomainNameResolver(DomainNameResolver* realResolver, EventLoop* eventLoop);
+			~CachingNameOnlyDomainNameResolver();
+
+			virtual DomainNameServiceQuery::ref createServiceQuery(const std::string& name);
+			virtual DomainNameAddressQuery::ref createAddressQuery(const std::string& name);
+
+		private:
+			void handleAddressQueryResult(const std::string hostname, const std::vector<HostAddress>& address, boost::optional<DomainNameResolveError> error);
+
+		private:
+			DomainNameResolver* realResolver;
+			boost::shared_ptr<StaticDomainNameResolver> staticResolver;
+	};
+}
diff --git a/Swiften/Network/Connector.cpp b/Swiften/Network/Connector.cpp
index 8f35aba..378875b 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) : hostname(hostname), resolver(resolver), connectionFactory(connectionFactory), timerFactory(timerFactory), timeoutMilliseconds(0), queriedAllServices(true) {
+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) {
 }
 
 void Connector::setTimeoutMilliseconds(int milliseconds) {
@@ -105,7 +105,7 @@ void Connector::tryNextAddress() {
 		HostAddress address = addressQueryResults.front();
 		addressQueryResults.pop_front();
 
-		int port = 5222;
+		int port = defaultPort;
 		if (!serviceQueryResults.empty()) {
 			port = serviceQueryResults.front().port;
 		}
diff --git a/Swiften/Network/Connector.h b/Swiften/Network/Connector.h
index 8336299..8f2c359 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) {
-				return ref(new Connector(hostname, resolver, connectionFactory, timerFactory));
+			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));
 			}
 
 			void setTimeoutMilliseconds(int milliseconds);
@@ -38,7 +38,7 @@ namespace Swift {
 			boost::signal<void (boost::shared_ptr<Connection>)> onConnectFinished;
 
 		private:
-			Connector(const std::string& hostname, DomainNameResolver*, ConnectionFactory*, TimerFactory*);
+			Connector(const std::string& hostname, DomainNameResolver*, ConnectionFactory*, TimerFactory*, int defaultPort);
 
 			void handleServiceQueryResult(const std::vector<DomainNameServiceQuery::Result>& result);
 			void handleAddressQueryResult(const std::vector<HostAddress>& address, boost::optional<DomainNameResolveError> error);
@@ -58,6 +58,7 @@ namespace Swift {
 			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 9ef63f0..512381f 100644
--- a/Swiften/Network/HTTPConnectProxiedConnection.cpp
+++ b/Swiften/Network/HTTPConnectProxiedConnection.cpp
@@ -5,7 +5,7 @@
  */
 
 /*
- * Copyright (c) 2011 Kevin Smith
+ * Copyright (c) 2011-2012 Kevin Smith
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -24,17 +24,20 @@
 #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(ConnectionFactory* connectionFactory, HostAddressPort proxy, const SafeString& authID, const SafeString& authPassword) : connectionFactory_(connectionFactory), proxy_(proxy), server_(HostAddressPort(HostAddress("0.0.0.0"), 0)), authID_(authID), authPassword_(authPassword) {
+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() {
+	cancelConnector();
+	delete resolver_;
 	if (connection_) {
-		connection_->onConnectFinished.disconnect(boost::bind(&HTTPConnectProxiedConnection::handleConnectionConnectFinished, shared_from_this(), _1));
 		connection_->onDataRead.disconnect(boost::bind(&HTTPConnectProxiedConnection::handleDataRead, shared_from_this(), _1));
 		connection_->onDisconnected.disconnect(boost::bind(&HTTPConnectProxiedConnection::handleDisconnected, shared_from_this(), _1));
 	}
@@ -44,13 +47,19 @@ HTTPConnectProxiedConnection::~HTTPConnectProxiedConnection() {
 	}
 }
 
+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;
-	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_);
+	connector_ = Connector::create(proxyHost_, resolver_, connectionFactory_, timerFactory_, proxyPort_);
+	connector_->onConnectFinished.connect(boost::bind(&HTTPConnectProxiedConnection::handleConnectFinished, shared_from_this(), _1));
+	connector_->start();
 }
 
 void HTTPConnectProxiedConnection::listen() {
@@ -71,9 +80,13 @@ void HTTPConnectProxiedConnection::write(const SafeByteArray& data) {
 	connection_->write(data);
 }
 
-void HTTPConnectProxiedConnection::handleConnectionConnectFinished(bool error) {
-	connection_->onConnectFinished.disconnect(boost::bind(&HTTPConnectProxiedConnection::handleConnectionConnectFinished, shared_from_this(), _1));
-	if (!error) {
+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());
diff --git a/Swiften/Network/HTTPConnectProxiedConnection.h b/Swiften/Network/HTTPConnectProxiedConnection.h
index 02d3edd..8318ecc 100644
--- a/Swiften/Network/HTTPConnectProxiedConnection.h
+++ b/Swiften/Network/HTTPConnectProxiedConnection.h
@@ -5,7 +5,7 @@
  */
 
 /*
- * Copyright (c) 2011 Kevin Smith
+ * Copyright (c) 2011-2012 Kevin Smith
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -16,6 +16,7 @@
 #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>
 
@@ -28,6 +29,7 @@ namespace boost {
 
 namespace Swift {
 	class ConnectionFactory;
+	class EventLoop;
 
 	class HTTPConnectProxiedConnection : public Connection, public boost::enable_shared_from_this<HTTPConnectProxiedConnection> {
 		public:
@@ -35,8 +37,8 @@ namespace Swift {
 
 			~HTTPConnectProxiedConnection();
 
-			static ref create(ConnectionFactory* connectionFactory, HostAddressPort proxy, const SafeString& authID, const SafeString& authPassword) {
-				return ref(new HTTPConnectProxiedConnection(connectionFactory, proxy, authID, authPassword));
+			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));
 			}
 
 			virtual void listen();
@@ -46,19 +48,24 @@ namespace Swift {
 
 			virtual HostAddressPort getLocalAddress() const;
 		private:
-			HTTPConnectProxiedConnection(ConnectionFactory* connectionFactory, HostAddressPort proxy, const SafeString& authID, const SafeString& authPassword);
+			HTTPConnectProxiedConnection(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, EventLoop* eventLoop, const std::string& proxyHost, int proxyPort, const SafeString& authID, const SafeString& authPassword);
 
-			void handleConnectionConnectFinished(bool error);
+			void handleConnectFinished(Connection::ref connection);
 			void handleDataRead(boost::shared_ptr<SafeByteArray> data);
 			void handleDisconnected(const boost::optional<Error>& error);
+			void cancelConnector();
 
 		private:
 			bool connected_;
+			DomainNameResolver* resolver_;
 			ConnectionFactory* connectionFactory_;	
-			HostAddressPort proxy_;
+			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 6ad0228..14d702c 100644
--- a/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp
+++ b/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp
@@ -1,4 +1,10 @@
 /*
+ * Copyright (c) 2012 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+/*
  * Copyright (c) 2010-2011 Thilo Cestonaro
  * Licensed under the simplified BSD license.
  * See Documentation/Licenses/BSD-simplified.txt for more information.
@@ -10,15 +16,15 @@
 
 namespace Swift {
 
-HTTPConnectProxiedConnectionFactory::HTTPConnectProxiedConnectionFactory(ConnectionFactory* connectionFactory, const HostAddressPort& proxy) : connectionFactory_(connectionFactory), proxy_(proxy), authID_(""), authPassword_("") {
+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(ConnectionFactory* connectionFactory, const HostAddressPort& proxy, const SafeString& authID, const SafeString& authPassword) : connectionFactory_(connectionFactory), proxy_(proxy), authID_(authID), authPassword_(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) {
 }
 
 boost::shared_ptr<Connection> HTTPConnectProxiedConnectionFactory::createConnection() {
-	return HTTPConnectProxiedConnection::create(connectionFactory_, proxy_, authID_, authPassword_);
+	return HTTPConnectProxiedConnection::create(resolver_, connectionFactory_, timerFactory_, eventLoop_, proxyHost_, proxyPort_, authID_, authPassword_);
 }
 
 }
diff --git a/Swiften/Network/HTTPConnectProxiedConnectionFactory.h b/Swiften/Network/HTTPConnectProxiedConnectionFactory.h
index ef3af66..7d003e8 100644
--- a/Swiften/Network/HTTPConnectProxiedConnectionFactory.h
+++ b/Swiften/Network/HTTPConnectProxiedConnectionFactory.h
@@ -1,4 +1,10 @@
 /*
+ * Copyright (c) 2012 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+/*
  * Copyright (c) 2010-2011 Thilo Cestonaro
  * Licensed under the simplified BSD license.
  * See Documentation/Licenses/BSD-simplified.txt for more information.
@@ -11,16 +17,23 @@
 #include <Swiften/Base/SafeString.h>
 
 namespace Swift {
+	class DomainNameResolver;
+	class TimerFactory;
+	class EventLoop;
 	class HTTPConnectProxiedConnectionFactory : public ConnectionFactory {
 		public:
-			HTTPConnectProxiedConnectionFactory(ConnectionFactory* connectionFactory, const HostAddressPort& proxy);
-			HTTPConnectProxiedConnectionFactory(ConnectionFactory* connectionFactory, const HostAddressPort& proxy, const SafeString& authID, const SafeString& authPassword);
+			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);
 
 			virtual boost::shared_ptr<Connection> createConnection();
 
 		private:
+			DomainNameResolver* resolver_;
 			ConnectionFactory* connectionFactory_;
-			HostAddressPort proxy_;
+			TimerFactory* timerFactory_;
+			EventLoop* eventLoop_;
+			std::string proxyHost_;
+			int proxyPort_;
 			SafeString authID_;
 			SafeString authPassword_;
 	};
diff --git a/Swiften/Network/SConscript b/Swiften/Network/SConscript
index 6975fe6..0d0abbd 100644
--- a/Swiften/Network/SConscript
+++ b/Swiften/Network/SConscript
@@ -17,6 +17,7 @@ sourceList = [
 			"BoostIOServiceThread.cpp",
 			"BOSHConnection.cpp",
 			"BOSHConnectionPool.cpp",
+                        "CachingNameOnlyDomainNameResolver.cpp",
 			"ConnectionFactory.cpp",
 			"ConnectionServer.cpp",
 			"ConnectionServerFactory.cpp",
diff --git a/Swiften/Network/StaticDomainNameResolver.cpp b/Swiften/Network/StaticDomainNameResolver.cpp
index 76ab411..ee18ee5 100644
--- a/Swiften/Network/StaticDomainNameResolver.cpp
+++ b/Swiften/Network/StaticDomainNameResolver.cpp
@@ -10,13 +10,14 @@
 #include <boost/lexical_cast.hpp>
 
 #include <Swiften/Network/DomainNameResolveError.h>
+#include <Swiften/EventLoop/EventOwner.h>
 #include <string>
 
 using namespace Swift;
 
 namespace {
 	struct ServiceQuery : public DomainNameServiceQuery, public boost::enable_shared_from_this<ServiceQuery> {
-		ServiceQuery(const std::string& service, Swift::StaticDomainNameResolver* resolver, EventLoop* eventLoop) : eventLoop(eventLoop), service(service), resolver(resolver) {}
+		ServiceQuery(const std::string& service, Swift::StaticDomainNameResolver* resolver, EventLoop* eventLoop, boost::shared_ptr<EventOwner> owner) : eventLoop(eventLoop), service(service), resolver(resolver), owner(owner) {}
 
 		virtual void run() {
 			if (!resolver->getIsResponsive()) {
@@ -28,7 +29,7 @@ namespace {
 					results.push_back(i->second);
 				}
 			}
-			eventLoop->postEvent(boost::bind(&ServiceQuery::emitOnResult, shared_from_this(), results));
+			eventLoop->postEvent(boost::bind(&ServiceQuery::emitOnResult, shared_from_this(), results), owner);
 		}
 
 		void emitOnResult(std::vector<DomainNameServiceQuery::Result> results) {
@@ -38,10 +39,11 @@ namespace {
 		EventLoop* eventLoop;
 		std::string service;
 		StaticDomainNameResolver* resolver;
+		boost::shared_ptr<EventOwner> owner;
 	};
 
 	struct AddressQuery : public DomainNameAddressQuery, public boost::enable_shared_from_this<AddressQuery> {
-		AddressQuery(const std::string& host, StaticDomainNameResolver* resolver, EventLoop* eventLoop) : eventLoop(eventLoop), host(host), resolver(resolver) {}
+		AddressQuery(const std::string& host, StaticDomainNameResolver* resolver, EventLoop* eventLoop, boost::shared_ptr<EventOwner> owner) : eventLoop(eventLoop), host(host), resolver(resolver), owner(owner) {}
 
 		virtual void run() {
 			if (!resolver->getIsResponsive()) {
@@ -53,7 +55,7 @@ namespace {
 						boost::bind(&AddressQuery::emitOnResult, shared_from_this(), i->second, boost::optional<DomainNameResolveError>()));
 			}
 			else {
-				eventLoop->postEvent(boost::bind(&AddressQuery::emitOnResult, shared_from_this(), std::vector<HostAddress>(), boost::optional<DomainNameResolveError>(DomainNameResolveError())));
+				eventLoop->postEvent(boost::bind(&AddressQuery::emitOnResult, shared_from_this(), std::vector<HostAddress>(), boost::optional<DomainNameResolveError>(DomainNameResolveError())), owner);
 			}
 		}
 
@@ -64,12 +66,25 @@ namespace {
 		EventLoop* eventLoop;
 		std::string host;
 		StaticDomainNameResolver* resolver;
+		boost::shared_ptr<EventOwner> owner;
 	};
 }
 
+class StaticDomainNameResolverEventOwner : public EventOwner {
+	public:
+		~StaticDomainNameResolverEventOwner() {
+
+		}
+};
+
+
 namespace Swift {
 
-StaticDomainNameResolver::StaticDomainNameResolver(EventLoop* eventLoop) : eventLoop(eventLoop), isResponsive(true) {
+StaticDomainNameResolver::StaticDomainNameResolver(EventLoop* eventLoop) : eventLoop(eventLoop), isResponsive(true), owner(new StaticDomainNameResolverEventOwner()) {
+}
+
+StaticDomainNameResolver::~StaticDomainNameResolver() {
+	eventLoop->removeEventsFromOwner(owner);
 }
 
 void StaticDomainNameResolver::addAddress(const std::string& domain, const HostAddress& address) {
@@ -94,11 +109,11 @@ void StaticDomainNameResolver::addXMPPClientService(const std::string& domain, c
 }
 
 boost::shared_ptr<DomainNameServiceQuery> StaticDomainNameResolver::createServiceQuery(const std::string& name) {
-	return boost::shared_ptr<DomainNameServiceQuery>(new ServiceQuery(name, this, eventLoop));
+	return boost::shared_ptr<DomainNameServiceQuery>(new ServiceQuery(name, this, eventLoop, owner));
 }
 
 boost::shared_ptr<DomainNameAddressQuery> StaticDomainNameResolver::createAddressQuery(const std::string& name) {
-	return boost::shared_ptr<DomainNameAddressQuery>(new AddressQuery(name, this, eventLoop));
+	return boost::shared_ptr<DomainNameAddressQuery>(new AddressQuery(name, this, eventLoop, owner));
 }
 
 }
diff --git a/Swiften/Network/StaticDomainNameResolver.h b/Swiften/Network/StaticDomainNameResolver.h
index a72db7c..29d1629 100644
--- a/Swiften/Network/StaticDomainNameResolver.h
+++ b/Swiften/Network/StaticDomainNameResolver.h
@@ -17,8 +17,6 @@
 #include <Swiften/EventLoop/EventLoop.h>
 
 namespace Swift {
-	
-
 	class StaticDomainNameResolver : public DomainNameResolver {
 		public:
 			typedef std::map<std::string, std::vector<HostAddress> > AddressesMap;
@@ -26,6 +24,7 @@ namespace Swift {
 
 		public:
 			StaticDomainNameResolver(EventLoop* eventLoop);
+			~StaticDomainNameResolver();
 
 			void addAddress(const std::string& domain, const HostAddress& address);
 			void addService(const std::string& service, const DomainNameServiceQuery::Result& result);
@@ -50,11 +49,11 @@ namespace Swift {
 
 			virtual boost::shared_ptr<DomainNameServiceQuery> createServiceQuery(const std::string& name);
 			virtual boost::shared_ptr<DomainNameAddressQuery> createAddressQuery(const std::string& name);
-			
 		private:
 			EventLoop* eventLoop;
 			bool isResponsive;
 			AddressesMap addresses;
 			ServicesCollection services;
+			boost::shared_ptr<EventOwner> owner;
 	};
 }
diff --git a/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp b/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp
index 1bfee10..82762c5 100644
--- a/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp
+++ b/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp
@@ -21,13 +21,18 @@
 #include <Swiften/Network/BOSHConnection.h>
 #include <Swiften/Network/BOSHConnectionPool.h>
 #include <Swiften/Network/HostAddressPort.h>
+#include <Swiften/Network/StaticDomainNameResolver.h>
+#include <Swiften/Network/DummyTimerFactory.h>
 #include <Swiften/EventLoop/DummyEventLoop.h>
 #include <Swiften/Parser/PlatformXMLParserFactory.h>
 
+
+
 using namespace Swift;
 
 typedef boost::shared_ptr<BOSHConnectionPool> PoolRef;
 
+
 class BOSHConnectionPoolTest : public CppUnit::TestFixture {
 	CPPUNIT_TEST_SUITE(BOSHConnectionPoolTest);
 	CPPUNIT_TEST(testConnectionCount_OneWrite);
@@ -64,11 +69,16 @@ class BOSHConnectionPoolTest : public CppUnit::TestFixture {
 			xmppDataRead.clear();
 			boshDataRead.clear();
 			boshDataWritten.clear();
+			resolver = new StaticDomainNameResolver(eventLoop);
+			resolver->addAddress(to, HostAddress("127.0.0.1"));
+			timerFactory = new DummyTimerFactory();
 		}
 
 		void tearDown() {
 			eventLoop->processEvents();
 			delete connectionFactory;
+			delete resolver;
+			delete timerFactory;
 			delete eventLoop;
 		}
 
@@ -91,10 +101,13 @@ class BOSHConnectionPoolTest : public CppUnit::TestFixture {
 			CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
 			eventLoop->processEvents();
 			readResponse(initial, connectionFactory->connections[0]);
+			eventLoop->processEvents();
 			testling->write(createSafeByteArray("<blah/>"));
+			eventLoop->processEvents();
 			CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
 			testling->write(createSafeByteArray("<bleh/>"));
 			eventLoop->processEvents();
+			eventLoop->processEvents();
 			CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size());
 		}
 
@@ -125,15 +138,20 @@ class BOSHConnectionPoolTest : public CppUnit::TestFixture {
 			CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* Connection finished, stream header sent */
 
 			readResponse(initial, connectionFactory->connections[0]);
+			eventLoop->processEvents();
 			CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
 			CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* Don't respond to initial data with a holding call */
 
 			testling->restartStream();
+			eventLoop->processEvents();
 			readResponse("<body/>", connectionFactory->connections[0]);
+			eventLoop->processEvents();
 			testling->restartStream();
+			eventLoop->processEvents();
 
 
 			testling->write(createSafeByteArray("<blah/>"));
+			eventLoop->processEvents();
 			CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size());
 			CPPUNIT_ASSERT_EQUAL(st(3), boshDataWritten.size()); /* New connection isn't up yet. */
 
@@ -142,6 +160,7 @@ class BOSHConnectionPoolTest : public CppUnit::TestFixture {
 			CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size()); /* New connection ready. */
 
 			testling->write(createSafeByteArray("<bleh/>"));
+			eventLoop->processEvents();
 			testling->write(createSafeByteArray("<bluh/>"));
 			CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size()); /* New data can't be sent, no free connections. */
 			eventLoop->processEvents();
@@ -167,6 +186,7 @@ class BOSHConnectionPoolTest : public CppUnit::TestFixture {
 
 			rid++;
 			testling->restartStream();
+			eventLoop->processEvents();
 			readResponse("<body/>", connectionFactory->connections[0]);
 
 			rid++;
@@ -199,6 +219,7 @@ class BOSHConnectionPoolTest : public CppUnit::TestFixture {
 
 			rid++;
 			testling->write(createSafeByteArray("<bleh/>"));
+			eventLoop->processEvents();
 			CPPUNIT_ASSERT(c0->pending);
 			CPPUNIT_ASSERT(c1->pending);
 			CPPUNIT_ASSERT_EQUAL(st(6), boshDataWritten.size()); /* data */
@@ -214,6 +235,7 @@ class BOSHConnectionPoolTest : public CppUnit::TestFixture {
 
 		void testSession() {
 			to = "prosody.doomsong.co.uk";
+			resolver->addAddress("prosody.doomsong.co.uk", HostAddress("127.0.0.1"));
 			path = "http-bind/";
 			boshURL = URL("http", to, 5280, path);
 
@@ -258,15 +280,18 @@ class BOSHConnectionPoolTest : public CppUnit::TestFixture {
 			boost::shared_ptr<MockConnection> c0;
 
 			PoolRef testling = createTestling();
-			c0 = connectionFactory->connections[0];
 			CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
-			eventLoop->processEvents();
+			c0 = connectionFactory->connections[0];
 
 			readResponse(initial, c0);
+			eventLoop->processEvents();
 			CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* Shouldn't have sent anything extra */
+			eventLoop->processEvents();
 			testling->restartStream();
+			eventLoop->processEvents();
 			CPPUNIT_ASSERT_EQUAL(st(2), boshDataWritten.size());
 			readResponse("<body></body>", c0);
+			eventLoop->processEvents();
 			CPPUNIT_ASSERT_EQUAL(st(3), boshDataWritten.size());
 			std::string fullBody = "<body rid='" + boost::lexical_cast<std::string>(initialRID + 2) + "' sid='" + sid + "' xmlns='http://jabber.org/protocol/httpbind'></body>";
 			std::string response = boshDataWritten[2];
@@ -279,12 +304,17 @@ class BOSHConnectionPoolTest : public CppUnit::TestFixture {
 	private:
 
 		PoolRef createTestling() {
-			PoolRef pool = boost::make_shared<BOSHConnectionPool>(boshURL, connectionFactory, &parserFactory, static_cast<TLSContextFactory*>(NULL), to, initialRID, URL(), "", "");
+			BOSHConnectionPool* a = new BOSHConnectionPool(boshURL, resolver, connectionFactory, &parserFactory, static_cast<TLSContextFactory*>(NULL), timerFactory, eventLoop, to, initialRID, URL(), SafeString(""), SafeString(""));
+			PoolRef pool(a);
+			//FIXME: Remko - why does the above work, but the below fail?
+			//PoolRef pool = boost::make_shared<BOSHConnectionPool>(boshURL, resolver, connectionFactory, &parserFactory, static_cast<TLSContextFactory*>(NULL), timerFactory, eventLoop, to, initialRID, URL(), SafeString(""), SafeString(""));
 			pool->onXMPPDataRead.connect(boost::bind(&BOSHConnectionPoolTest::handleXMPPDataRead, this, _1));
 			pool->onBOSHDataRead.connect(boost::bind(&BOSHConnectionPoolTest::handleBOSHDataRead, this, _1));
 			pool->onBOSHDataWritten.connect(boost::bind(&BOSHConnectionPoolTest::handleBOSHDataWritten, this, _1));
 			pool->onSessionStarted.connect(boost::bind(&BOSHConnectionPoolTest::handleSessionStarted, this));
 			pool->onSessionTerminated.connect(boost::bind(&BOSHConnectionPoolTest::handleSessionTerminated, this));
+			eventLoop->processEvents();
+			eventLoop->processEvents();
 			return pool;
 		}
 
@@ -406,6 +436,8 @@ class BOSHConnectionPoolTest : public CppUnit::TestFixture {
 		std::vector<std::string> boshDataRead;
 		std::vector<std::string> boshDataWritten;
 		PlatformXMLParserFactory parserFactory;
+		StaticDomainNameResolver* resolver;
+		TimerFactory* timerFactory;
 		std::string to;
 		std::string path;
 		std::string port;
diff --git a/Swiften/Network/UnitTest/BOSHConnectionTest.cpp b/Swiften/Network/UnitTest/BOSHConnectionTest.cpp
index 8062bea..e0dc0bf 100644
--- a/Swiften/Network/UnitTest/BOSHConnectionTest.cpp
+++ b/Swiften/Network/UnitTest/BOSHConnectionTest.cpp
@@ -20,6 +20,8 @@
 #include <Swiften/Network/ConnectionFactory.h>
 #include <Swiften/Network/BOSHConnection.h>
 #include <Swiften/Network/HostAddressPort.h>
+#include <Swiften/Network/StaticDomainNameResolver.h>
+#include <Swiften/Network/DummyTimerFactory.h>
 #include <Swiften/EventLoop/DummyEventLoop.h>
 #include <Swiften/Parser/PlatformXMLParserFactory.h>
 
@@ -43,6 +45,8 @@ class BOSHConnectionTest : public CppUnit::TestFixture {
 		void setUp() {
 			eventLoop = new DummyEventLoop();
 			connectionFactory = new MockConnectionFactory(eventLoop);
+			resolver = new StaticDomainNameResolver(eventLoop);
+			timerFactory = new DummyTimerFactory();
 			connectFinished = false;
 			disconnected = false;
 			disconnectedError = false;
@@ -52,7 +56,9 @@ class BOSHConnectionTest : public CppUnit::TestFixture {
 		void tearDown() {
 			eventLoop->processEvents();
 			delete connectionFactory;
-			delete eventLoop;	
+			delete resolver;
+			delete timerFactory;
+			delete eventLoop;
 		}
 
 		void testHeader() {
@@ -185,7 +191,9 @@ class BOSHConnectionTest : public CppUnit::TestFixture {
 	private:
 
 		BOSHConnection::ref createTestling() {
-			BOSHConnection::ref c = BOSHConnection::create(URL("http", "wonderland.lit", 5280, "http-bind"), connectionFactory, &parserFactory, static_cast<TLSContextFactory*>(NULL));
+			resolver->addAddress("wonderland.lit", HostAddress("127.0.0.1"));
+			Connector::ref connector = Connector::create("wonderland.lit", resolver, connectionFactory, timerFactory, 5280);
+			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));
 			c->onXMPPDataRead.connect(boost::bind(&BOSHConnectionTest::handleDataRead, this, _1));
@@ -284,6 +292,8 @@ class BOSHConnectionTest : public CppUnit::TestFixture {
 		bool disconnectedError;
 		ByteArray dataRead;
 		PlatformXMLParserFactory parserFactory;
+		StaticDomainNameResolver* resolver;
+		TimerFactory* timerFactory;
 		std::string sid;	
 
 };
diff --git a/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp b/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp
index c0252d4..347a145 100644
--- a/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp
+++ b/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp
@@ -18,6 +18,8 @@
 #include <Swiften/Network/ConnectionFactory.h>
 #include <Swiften/Network/HTTPConnectProxiedConnection.h>
 #include <Swiften/Network/HostAddressPort.h>
+#include <Swiften/Network/StaticDomainNameResolver.h>
+#include <Swiften/Network/DummyTimerFactory.h>
 #include <Swiften/EventLoop/DummyEventLoop.h>
 
 using namespace Swift;
@@ -37,44 +39,55 @@ class HTTPConnectProxiedConnectionTest : public CppUnit::TestFixture {
 
 	public:
 		void setUp() {
-			proxyHost = HostAddressPort(HostAddress("1.1.1.1"), 1234);
+			proxyHost = "doo.bah";
+			proxyPort = 1234;
+			proxyHostAddress = HostAddressPort(HostAddress("1.1.1.1"), proxyPort);
 			host = HostAddressPort(HostAddress("2.2.2.2"), 2345);
 			eventLoop = new DummyEventLoop();
+			resolver = new StaticDomainNameResolver(eventLoop);
+			resolver->addAddress(proxyHost, proxyHostAddress.getAddress());
+			timerFactory = new DummyTimerFactory();
 			connectionFactory = new MockConnectionFactory(eventLoop);
 			connectFinished = false;
 			disconnected = false;
 		}
 
 		void tearDown() {
+			delete timerFactory;
 			delete connectionFactory;
+			delete resolver;
 			delete eventLoop;
 		}
 
+		void connect(HTTPConnectProxiedConnection::ref connection, const HostAddressPort& to) {
+			connection->connect(to);
+			eventLoop->processEvents();
+			eventLoop->processEvents();
+			eventLoop->processEvents();
+		}
+
 		void testConnect_CreatesConnectionToProxy() {
 			HTTPConnectProxiedConnection::ref testling(createTestling());
 
-			testling->connect(host);
-			eventLoop->processEvents();
+			connect(testling, host);
 
 			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connectionFactory->connections.size()));
 			CPPUNIT_ASSERT(connectionFactory->connections[0]->hostAddressPort);
-			CPPUNIT_ASSERT(proxyHost == *connectionFactory->connections[0]->hostAddressPort);
+			CPPUNIT_ASSERT(proxyHostAddress == *connectionFactory->connections[0]->hostAddressPort);
 			CPPUNIT_ASSERT(!connectFinished);
 		}
 
 		void testConnect_SendsConnectRequest() {
 			HTTPConnectProxiedConnection::ref testling(createTestling());
 
-			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345));
-			eventLoop->processEvents();
+			connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
 
 			CPPUNIT_ASSERT_EQUAL(createByteArray("CONNECT 2.2.2.2:2345 HTTP/1.1\r\n\r\n"), connectionFactory->connections[0]->dataWritten);
 		}
 
 		void testConnect_ReceiveConnectResponse() {
 			HTTPConnectProxiedConnection::ref testling(createTestling());
-			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345));
-			eventLoop->processEvents();
+			connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
 
 			connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 200 Connection established\r\n\r\n"));
 			eventLoop->processEvents();
@@ -86,8 +99,7 @@ class HTTPConnectProxiedConnectionTest : public CppUnit::TestFixture {
 
 		void testConnect_ReceiveMalformedConnectResponse() {
 			HTTPConnectProxiedConnection::ref testling(createTestling());
-			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345));
-			eventLoop->processEvents();
+			connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
 
 			connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("FLOOP"));
 			eventLoop->processEvents();
@@ -99,8 +111,7 @@ class HTTPConnectProxiedConnectionTest : public CppUnit::TestFixture {
 
 		void testConnect_ReceiveErrorConnectResponse() {
 			HTTPConnectProxiedConnection::ref testling(createTestling());
-			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345));
-			eventLoop->processEvents();
+			connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
 
 			connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 401 Unauthorized\r\n\r\n"));
 			eventLoop->processEvents();
@@ -112,8 +123,7 @@ class HTTPConnectProxiedConnectionTest : public CppUnit::TestFixture {
 
 		void testConnect_ReceiveDataAfterConnect() {
 			HTTPConnectProxiedConnection::ref testling(createTestling());
-			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345));
-			eventLoop->processEvents();
+			connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
 			connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 200 Connection established\r\n\r\n"));
 			eventLoop->processEvents();
 
@@ -124,8 +134,7 @@ class HTTPConnectProxiedConnectionTest : public CppUnit::TestFixture {
 
 		void testWrite_AfterConnect() {
 			HTTPConnectProxiedConnection::ref testling(createTestling());
-			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345));
-			eventLoop->processEvents();
+			connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
 			connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 200 Connection established\r\n\r\n"));
 			eventLoop->processEvents();
 			connectionFactory->connections[0]->dataWritten.clear();
@@ -137,8 +146,7 @@ class HTTPConnectProxiedConnectionTest : public CppUnit::TestFixture {
 
 		void testDisconnect_AfterConnectRequest() {
 			HTTPConnectProxiedConnection::ref testling(createTestling());
-			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345));
-			eventLoop->processEvents();
+			connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
 
 			testling->disconnect();
 
@@ -149,8 +157,7 @@ class HTTPConnectProxiedConnectionTest : public CppUnit::TestFixture {
 
 		void testDisconnect_AfterConnect() {
 			HTTPConnectProxiedConnection::ref testling(createTestling());
-			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345));
-			eventLoop->processEvents();
+			connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
 			connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 200 Connection established\r\n\r\n"));
 			eventLoop->processEvents();
 
@@ -163,7 +170,7 @@ class HTTPConnectProxiedConnectionTest : public CppUnit::TestFixture {
 
 	private:
 		HTTPConnectProxiedConnection::ref createTestling() {
-			boost::shared_ptr<HTTPConnectProxiedConnection> c = HTTPConnectProxiedConnection::create(connectionFactory, proxyHost, "", "");
+			boost::shared_ptr<HTTPConnectProxiedConnection> c = HTTPConnectProxiedConnection::create(resolver, connectionFactory, timerFactory, eventLoop, 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));
@@ -231,10 +238,14 @@ class HTTPConnectProxiedConnectionTest : public CppUnit::TestFixture {
 		};
 
 	private:
-		HostAddressPort proxyHost;
+		std::string proxyHost;
+		HostAddressPort proxyHostAddress;
+		int proxyPort;
 		HostAddressPort host;
 		DummyEventLoop* eventLoop;
+		StaticDomainNameResolver* resolver;
 		MockConnectionFactory* connectionFactory;
+		TimerFactory* timerFactory;
 		std::vector< boost::shared_ptr<MockConnection> > connections;
 		bool connectFinished;
 		bool connectFinishedWithError;
diff --git a/Swiften/Session/BOSHSessionStream.cpp b/Swiften/Session/BOSHSessionStream.cpp
index f53b8e1..d706d43 100644
--- a/Swiften/Session/BOSHSessionStream.cpp
+++ b/Swiften/Session/BOSHSessionStream.cpp
@@ -35,6 +35,7 @@ BOSHSessionStream::BOSHSessionStream(
 		TimerFactory* timerFactory,
 		XMLParserFactory* xmlParserFactory,
 		EventLoop* eventLoop,
+		DomainNameResolver* resolver,
 		const std::string& to,
 		const URL& boshHTTPConnectProxyURL,
 		const SafeString& boshHTTPConnectProxyAuthID,
@@ -49,11 +50,11 @@ BOSHSessionStream::BOSHSessionStream(
 			firstHeader(true) {
 
 	boost::mt19937 random;
-	boost::uniform_int<long long> dist(0, (1LL<<53) - 1);
+	boost::uniform_int<unsigned long long> dist(0, (1LL<<53) - 1);
 	random.seed(time(NULL));
-	long long initialRID = boost::variate_generator<boost::mt19937&, boost::uniform_int<long long> >(random, dist)();
+	unsigned long long initialRID = boost::variate_generator<boost::mt19937&, boost::uniform_int<unsigned long long> >(random, dist)();
 
-	connectionPool = new BOSHConnectionPool(boshURL, connectionFactory, xmlParserFactory, tlsContextFactory, to, initialRID, boshHTTPConnectProxyURL, boshHTTPConnectProxyAuthID, boshHTTPConnectProxyAuthPassword);
+	connectionPool = new BOSHConnectionPool(boshURL, resolver, connectionFactory, xmlParserFactory, tlsContextFactory, timerFactory, eventLoop, to, initialRID, boshHTTPConnectProxyURL, boshHTTPConnectProxyAuthID, boshHTTPConnectProxyAuthPassword);
 	connectionPool->onSessionTerminated.connect(boost::bind(&BOSHSessionStream::handlePoolSessionTerminated, this, _1));
 	connectionPool->onSessionStarted.connect(boost::bind(&BOSHSessionStream::handlePoolSessionStarted, this));
 	connectionPool->onXMPPDataRead.connect(boost::bind(&BOSHSessionStream::handlePoolXMPPDataRead, this, _1));
diff --git a/Swiften/Session/BOSHSessionStream.h b/Swiften/Session/BOSHSessionStream.h
index c3f6220..497d391 100644
--- a/Swiften/Session/BOSHSessionStream.h
+++ b/Swiften/Session/BOSHSessionStream.h
@@ -38,6 +38,7 @@ namespace Swift {
 					TimerFactory* whitespacePingLayerFactory,
 					XMLParserFactory* xmlParserFactory,
 					EventLoop* eventLoop,
+					DomainNameResolver* resolver,
 					const std::string& to,
 					const URL& boshHTTPConnectProxyURL,
 					const SafeString& boshHTTPConnectProxyAuthID,
-- 
cgit v0.10.2-6-g49f6