/* * Copyright (c) 2011 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include #include #include #include #include #include #include using namespace Swift; ChainedConnector::ChainedConnector( const std::string& hostname, int port, const boost::optional& serviceLookupPrefix, DomainNameResolver* resolver, const std::vector& connectionFactories, TimerFactory* timerFactory) : hostname(hostname), port(port), serviceLookupPrefix(serviceLookupPrefix), resolver(resolver), connectionFactories(connectionFactories), timerFactory(timerFactory), timeoutMilliseconds(0) { } void ChainedConnector::setTimeoutMilliseconds(int milliseconds) { timeoutMilliseconds = milliseconds; } void ChainedConnector::start() { SWIFT_LOG(debug) << "Starting queued connector for " << hostname << std::endl; connectionFactoryQueue = std::deque(connectionFactories.begin(), connectionFactories.end()); tryNextConnectionFactory(); } void ChainedConnector::stop() { if (currentConnector) { currentConnector->onConnectFinished.disconnect(boost::bind(&ChainedConnector::handleConnectorFinished, this, _1, _2)); currentConnector->stop(); currentConnector.reset(); } finish(boost::shared_ptr(), boost::shared_ptr()); } void ChainedConnector::tryNextConnectionFactory() { assert(!currentConnector); if (connectionFactoryQueue.empty()) { SWIFT_LOG(debug) << "No more connection factories" << std::endl; finish(boost::shared_ptr(), lastError); } else { ConnectionFactory* connectionFactory = connectionFactoryQueue.front(); SWIFT_LOG(debug) << "Trying next connection factory: " << typeid(*connectionFactory).name() << std::endl; connectionFactoryQueue.pop_front(); currentConnector = Connector::create(hostname, port, serviceLookupPrefix, resolver, connectionFactory, timerFactory); currentConnector->setTimeoutMilliseconds(timeoutMilliseconds); currentConnector->onConnectFinished.connect(boost::bind(&ChainedConnector::handleConnectorFinished, this, _1, _2)); currentConnector->start(); } } void ChainedConnector::handleConnectorFinished(boost::shared_ptr connection, boost::shared_ptr error) { SWIFT_LOG(debug) << "Connector finished" << std::endl; currentConnector->onConnectFinished.disconnect(boost::bind(&ChainedConnector::handleConnectorFinished, this, _1, _2)); lastError = error; currentConnector.reset(); if (connection) { finish(connection, error); } else { tryNextConnectionFactory(); } } void ChainedConnector::finish(boost::shared_ptr connection, boost::shared_ptr error) { onConnectFinished(connection, error); }