/* * Copyright (c) 2011-2019 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include #include #include #include #include #include using namespace Swift; ChainedConnector::ChainedConnector( const std::string& hostname, unsigned short 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) { } ChainedConnector::~ChainedConnector() { if (currentConnector) { currentConnector->onConnectFinished.disconnect(boost::bind(&ChainedConnector::handleConnectorFinished, this, _1, _2)); currentConnector->stop(); currentConnector.reset(); } } void ChainedConnector::setTimeoutMilliseconds(int milliseconds) { timeoutMilliseconds = milliseconds; } void ChainedConnector::start() { SWIFT_LOG(debug) << "Starting queued connector for " << hostname; 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(std::shared_ptr(), std::shared_ptr()); } void ChainedConnector::tryNextConnectionFactory() { assert(!currentConnector); if (connectionFactoryQueue.empty()) { SWIFT_LOG(debug) << "No more connection factories"; finish(std::shared_ptr(), lastError); } else { ConnectionFactory* connectionFactory = connectionFactoryQueue.front(); SWIFT_LOG(debug) << "Trying next connection factory: " << typeid(*connectionFactory).name(); 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(std::shared_ptr connection, std::shared_ptr error) { SWIFT_LOG(debug) << "Connector finished"; currentConnector->onConnectFinished.disconnect(boost::bind(&ChainedConnector::handleConnectorFinished, this, _1, _2)); lastError = error; currentConnector.reset(); if (connection) { finish(connection, error); } else { tryNextConnectionFactory(); } } void ChainedConnector::finish(std::shared_ptr connection, std::shared_ptr error) { onConnectFinished(connection, error); }