void Connector::start() { SWIFT_LOG(debug) << "Starting connector for " << hostname << std::endl; assert(!currentConnection); assert(!serviceQuery); assert(!timer); queriedAllServices = false; auto hostAddress = HostAddress::fromString(hostname); if (timeoutMilliseconds > 0) { timer = timerFactory->createTimer(timeoutMilliseconds); timer->onTick.connect(boost::bind(&Connector::handleTimeout, shared_from_this())); } if (serviceLookupPrefix) { serviceQuery = resolver->createServiceQuery(*serviceLookupPrefix, hostname); serviceQuery->onResult.connect(boost::bind(&Connector::handleServiceQueryResult, shared_from_this(), _1)); serviceQuery->run(); } else if (hostAddress) { // hostname is already a valid address; skip name lookup. foundSomeDNS = true; addressQueryResults.push_back(hostAddress.get()); tryNextAddress(); } else { queryAddress(hostname); } }
void Link::retryTimeout(const boost::system::error_code &error) { // Ignore aborted timer operations if (error == boost::asio::error::operation_aborted) return; tryNextAddress(); }
void Connector::handleAddressQueryResult(const std::vector<HostAddress>& addresses, boost::optional<DomainNameResolveError> error) { SWIFT_LOG(debug) << addresses.size() << " addresses" << std::endl; addressQuery.reset(); if (error || addresses.empty()) { if (!serviceQueryResults.empty()) { serviceQueryResults.pop_front(); } tryNextServiceOrFallback(); } else { foundSomeDNS = true; addressQueryResults = std::deque<HostAddress>(addresses.begin(), addresses.end()); tryNextAddress(); } }
void Connector::handleConnectionConnectFinished(bool error) { SWIFT_LOG(debug) << "ConnectFinished: " << (error ? "error" : "success") << std::endl; currentConnection->onConnectFinished.disconnect(boost::bind(&Connector::handleConnectionConnectFinished, shared_from_this(), _1)); if (error) { currentConnection.reset(); if (!addressQueryResults.empty()) { tryNextAddress(); } else { if (!serviceQueryResults.empty()) { serviceQueryResults.pop_front(); } tryNextServiceOrFallback(); } } else { finish(currentConnection); } }
void Link::send(const Message &msg) { RecursiveUniqueLock lock(m_mutex); // When messages are queued to an invalid link, they are lost as the link // is going to be deleted in a moment if (m_state == Link::State::Invalid) return; if (m_state != Link::State::Connected) { // FIXME Make this limit configurable m_messages.push_back(msg); if (m_messages.size() > 512) m_messages.pop_front(); // Trigger a reconnect when one is not in progress if (m_state != Link::State::Connecting) tryNextAddress(); } else { m_dispatcher->send(msg); } }