summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2012-06-02 16:40:22 (GMT)
committerRemko Tronçon <git@el-tramo.be>2012-06-17 07:34:57 (GMT)
commitf171bc207c2a7371ac6924ff467049dd0258aa00 (patch)
treeeda5b5feb94dea264ea26b839b6f9ef5e32c915f
parent5a1bdf2f6a4842176be5938f8db5cb9d151aceb5 (diff)
downloadswift-contrib-f171bc207c2a7371ac6924ff467049dd0258aa00.zip
swift-contrib-f171bc207c2a7371ac6924ff467049dd0258aa00.tar.bz2
Allow different connection methods for Client.
-rw-r--r--Sluift/sluift.cpp3
-rw-r--r--Swiften/Client/ClientOptions.h51
-rw-r--r--Swiften/Client/CoreClient.cpp56
-rw-r--r--Swiften/Client/CoreClient.h2
-rw-r--r--Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp4
-rw-r--r--Swiften/Examples/SendMessage/SendMessage.cpp4
-rw-r--r--Swiften/Network/BOSHConnectionPool.cpp4
-rw-r--r--Swiften/Network/ChainedConnector.cpp6
-rw-r--r--Swiften/Network/ChainedConnector.h4
-rw-r--r--Swiften/Network/Connector.cpp29
-rw-r--r--Swiften/Network/Connector.h9
-rw-r--r--Swiften/Network/HTTPConnectProxiedConnection.cpp130
-rw-r--r--Swiften/Network/HTTPConnectProxiedConnection.h47
-rw-r--r--Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp6
-rw-r--r--Swiften/Network/HTTPConnectProxiedConnectionFactory.h5
-rw-r--r--Swiften/Network/HostNameOrAddress.cpp29
-rw-r--r--Swiften/Network/HostNameOrAddress.h16
-rw-r--r--Swiften/Network/ProxiedConnection.cpp112
-rw-r--r--Swiften/Network/ProxiedConnection.h67
-rw-r--r--Swiften/Network/SConscript2
-rw-r--r--Swiften/Network/SOCKS5ProxiedConnection.cpp223
-rw-r--r--Swiften/Network/SOCKS5ProxiedConnection.h41
-rw-r--r--Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp4
-rw-r--r--Swiften/Network/SOCKS5ProxiedConnectionFactory.h11
-rw-r--r--Swiften/Network/UnitTest/BOSHConnectionTest.cpp2
-rw-r--r--Swiften/Network/UnitTest/ChainedConnectorTest.cpp2
-rw-r--r--Swiften/Network/UnitTest/ConnectorTest.cpp38
-rw-r--r--Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp2
28 files changed, 548 insertions, 361 deletions
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));