From 7d2db3b25effc93aa111664d0745a5365f4b7f05 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sat, 16 Apr 2011 11:56:17 +0200
Subject: Use fallback mechanism for proxies.


diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp
index 348f3b3..f4baca9 100644
--- a/Swiften/Client/CoreClient.cpp
+++ b/Swiften/Client/CoreClient.cpp
@@ -7,11 +7,12 @@
 #include "Swiften/Client/CoreClient.h"
 
 #include <boost/bind.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
 
 #include "Swiften/Client/ClientSession.h"
 #include "Swiften/TLS/PlatformTLSFactories.h"
 #include "Swiften/TLS/CertificateVerificationError.h"
-#include "Swiften/Network/Connector.h"
+#include <Swiften/Network/ChainedConnector.h>
 #include "Swiften/Network/NetworkFactories.h"
 #include "Swiften/TLS/PKCS12Certificate.h"
 #include "Swiften/Session/BasicSessionStream.h"
@@ -19,28 +20,21 @@
 #include "Swiften/Base/IDGenerator.h"
 #include "Swiften/Client/ClientSessionStanzaChannel.h"
 #include <Swiften/Base/Log.h>
+#include <Swiften/Base/foreach.h>
 #include "Swiften/Network/PlatformProxyProvider.h"
 #include "Swiften/Network/SOCKS5ProxiedConnectionFactory.h"
 #include "Swiften/Network/HTTPConnectProxiedConnectionFactory.h"
 
 namespace Swift {
 
-CoreClient::CoreClient(const JID& jid, const std::string& password, NetworkFactories* networkFactories) : jid_(jid), password_(password), networkFactories(networkFactories), useStreamCompression(true), useTLS(UseTLSWhenAvailable), proxyConnectionFactory_(NULL), disconnectRequested_(false), certificateTrustChecker(NULL) {
+CoreClient::CoreClient(const JID& jid, const std::string& password, NetworkFactories* networkFactories) : jid_(jid), password_(password), networkFactories(networkFactories), useStreamCompression(true), useTLS(UseTLSWhenAvailable), disconnectRequested_(false), certificateTrustChecker(NULL) {
 	stanzaChannel_ = new ClientSessionStanzaChannel();
 	stanzaChannel_->onMessageReceived.connect(boost::bind(&CoreClient::handleMessageReceived, this, _1));
 	stanzaChannel_->onPresenceReceived.connect(boost::bind(&CoreClient::handlePresenceReceived, this, _1));
 	stanzaChannel_->onStanzaAcked.connect(boost::bind(&CoreClient::handleStanzaAcked, this, _1));
 	stanzaChannel_->onAvailableChanged.connect(boost::bind(&CoreClient::handleStanzaChannelAvailableChanged, this, _1));
 
-	PlatformProxyProvider proxyProvider;
-
 	iqRouter_ = new IQRouter(stanzaChannel_);
-	if(proxyProvider.getSOCKS5Proxy().isValid()) {
-		proxyConnectionFactory_ = new SOCKS5ProxiedConnectionFactory(networkFactories->getConnectionFactory(), proxyProvider.getSOCKS5Proxy());
-	}
-	else if(proxyProvider.getHTTPConnectProxy().isValid()) {
-		proxyConnectionFactory_ = new HTTPConnectProxiedConnectionFactory(networkFactories->getConnectionFactory(), proxyProvider.getHTTPConnectProxy());
-	}
 	tlsFactories = new PlatformTLSFactories();
 }
 
@@ -49,7 +43,6 @@ CoreClient::~CoreClient() {
 		std::cerr << "Warning: Client not disconnected properly" << std::endl;
 	}
 	delete tlsFactories;
-	delete proxyConnectionFactory_;
 	delete iqRouter_;
 
 	stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&CoreClient::handleStanzaChannelAvailableChanged, this, _1));
@@ -68,7 +61,19 @@ void CoreClient::connect(const std::string& host) {
 	SWIFT_LOG(debug) << "Connecting to host " << host << std::endl;
 	disconnectRequested_ = false;
 	assert(!connector_);
-	connector_ = Connector::create(host, networkFactories->getDomainNameResolver(), proxyConnectionFactory_ != NULL ? proxyConnectionFactory_ : networkFactories->getConnectionFactory(), networkFactories->getTimerFactory());
+
+	assert(proxyConnectionFactories.empty());
+	PlatformProxyProvider proxyProvider;
+	if(proxyProvider.getSOCKS5Proxy().isValid()) {
+		proxyConnectionFactories.push_back(new SOCKS5ProxiedConnectionFactory(networkFactories->getConnectionFactory(), proxyProvider.getSOCKS5Proxy()));
+	}
+	if(proxyProvider.getHTTPConnectProxy().isValid()) {
+		proxyConnectionFactories.push_back(new HTTPConnectProxiedConnectionFactory(networkFactories->getConnectionFactory(), proxyProvider.getHTTPConnectProxy()));
+	}
+	std::vector<ConnectionFactory*> connectionFactories(proxyConnectionFactories);
+	connectionFactories.push_back(networkFactories->getConnectionFactory());
+
+	connector_ = boost::make_shared<ChainedConnector>(host, networkFactories->getDomainNameResolver(), connectionFactories, networkFactories->getTimerFactory());
 	connector_->onConnectFinished.connect(boost::bind(&CoreClient::handleConnectorFinished, this, _1));
 	connector_->setTimeoutMilliseconds(60*1000);
 	connector_->start();
@@ -77,6 +82,10 @@ void CoreClient::connect(const std::string& host) {
 void CoreClient::handleConnectorFinished(boost::shared_ptr<Connection> connection) {
 	connector_->onConnectFinished.disconnect(boost::bind(&CoreClient::handleConnectorFinished, this, _1));
 	connector_.reset();
+	foreach(ConnectionFactory* f, proxyConnectionFactories) {
+		delete f;
+	}
+
 	if (!connection) {
 		onDisconnected(disconnectRequested_ ? boost::optional<ClientError>() : boost::optional<ClientError>(ClientError::ConnectionError));
 	}
diff --git a/Swiften/Client/CoreClient.h b/Swiften/Client/CoreClient.h
index 2debb7f..d7c165f 100644
--- a/Swiften/Client/CoreClient.h
+++ b/Swiften/Client/CoreClient.h
@@ -15,7 +15,7 @@
 #include <Swiften/Client/ClientError.h>
 
 namespace Swift {
-	class Connector;
+	class ChainedConnector;
 	class Message;
 	class Presence;
 	class Error;
@@ -220,8 +220,8 @@ namespace Swift {
 			UseTLS useTLS;
 			ClientSessionStanzaChannel* stanzaChannel_;
 			IQRouter* iqRouter_;
-			boost::shared_ptr<Connector> connector_;
-			ConnectionFactory* proxyConnectionFactory_;
+			boost::shared_ptr<ChainedConnector> connector_;
+			std::vector<ConnectionFactory*> proxyConnectionFactories;
 			PlatformTLSFactories* tlsFactories;
 			boost::shared_ptr<Connection> connection_;
 			boost::shared_ptr<BasicSessionStream> sessionStream_;
diff --git a/Swiften/Network/ChainedConnector.cpp b/Swiften/Network/ChainedConnector.cpp
index e08ffc6..1a38e53 100644
--- a/Swiften/Network/ChainedConnector.cpp
+++ b/Swiften/Network/ChainedConnector.cpp
@@ -7,10 +7,12 @@
 #include <Swiften/Network/ChainedConnector.h>
 
 #include <boost/bind.hpp>
+#include <typeinfo>
 
 #include <Swiften/Base/Log.h>
 #include <Swiften/Base/foreach.h>
 #include <Swiften/Network/Connector.h>
+#include <Swiften/Network/ConnectionFactory.h>
 
 using namespace Swift;
 
@@ -47,7 +49,6 @@ void ChainedConnector::stop() {
 }
 
 void ChainedConnector::tryNextConnectionFactory() {
-	SWIFT_LOG(debug) << "Trying next connection factory" << std::endl;
 	assert(!currentConnector);
 	if (connectionFactoryQueue.empty()) {
 		SWIFT_LOG(debug) << "No more connection factories" << std::endl;
@@ -55,6 +56,7 @@ void ChainedConnector::tryNextConnectionFactory() {
 	}
 	else {
 		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->setTimeoutMilliseconds(timeoutMilliseconds);
-- 
cgit v0.10.2-6-g49f6