diff options
author | Remko Tronçon <git@el-tramo.be> | 2010-10-15 16:15:57 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2010-10-15 16:15:57 (GMT) |
commit | 062658db9f46ef749eeec09c162e5afaf1524ab6 (patch) | |
tree | 12ea883e39c7d938310ea715c71127bc1801319c /Swiften/Component/ComponentConnector.cpp | |
parent | f52aa93c3d6d5976b072d31f3d3336beb1596ece (diff) | |
download | swift-contrib-062658db9f46ef749eeec09c162e5afaf1524ab6.zip swift-contrib-062658db9f46ef749eeec09c162e5afaf1524ab6.tar.bz2 |
Added Component parser, serializer, element, and connector.
Diffstat (limited to 'Swiften/Component/ComponentConnector.cpp')
-rw-r--r-- | Swiften/Component/ComponentConnector.cpp | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/Swiften/Component/ComponentConnector.cpp b/Swiften/Component/ComponentConnector.cpp new file mode 100644 index 0000000..e764138 --- /dev/null +++ b/Swiften/Component/ComponentConnector.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Swiften/Component/ComponentConnector.h" + +#include <boost/bind.hpp> +#include <iostream> + +#include "Swiften/Network/ConnectionFactory.h" +#include "Swiften/Network/DomainNameResolver.h" +#include "Swiften/Network/DomainNameAddressQuery.h" +#include "Swiften/Network/TimerFactory.h" + +namespace Swift { + +ComponentConnector::ComponentConnector(const String& hostname, int port, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory) : hostname(hostname), port(port), resolver(resolver), connectionFactory(connectionFactory), timerFactory(timerFactory), timeoutMilliseconds(0) { +} + +void ComponentConnector::setTimeoutMilliseconds(int milliseconds) { + timeoutMilliseconds = milliseconds; +} + +void ComponentConnector::start() { + assert(!currentConnection); + assert(!timer); + assert(!addressQuery); + addressQuery = resolver->createAddressQuery(hostname); + addressQuery->onResult.connect(boost::bind(&ComponentConnector::handleAddressQueryResult, shared_from_this(), _1, _2)); + if (timeoutMilliseconds > 0) { + timer = timerFactory->createTimer(timeoutMilliseconds); + timer->onTick.connect(boost::bind(&ComponentConnector::handleTimeout, shared_from_this())); + timer->start(); + } + addressQuery->run(); +} + +void ComponentConnector::stop() { + finish(boost::shared_ptr<Connection>()); +} + + +void ComponentConnector::handleAddressQueryResult(const std::vector<HostAddress>& addresses, boost::optional<DomainNameResolveError> error) { + addressQuery.reset(); + if (error || addresses.empty()) { + finish(boost::shared_ptr<Connection>()); + } + else { + addressQueryResults = std::deque<HostAddress>(addresses.begin(), addresses.end()); + tryNextAddress(); + } +} + +void ComponentConnector::tryNextAddress() { + assert(!addressQueryResults.empty()); + HostAddress address = addressQueryResults.front(); + addressQueryResults.pop_front(); + tryConnect(HostAddressPort(address, port)); +} + +void ComponentConnector::tryConnect(const HostAddressPort& target) { + assert(!currentConnection); + currentConnection = connectionFactory->createConnection(); + currentConnection->onConnectFinished.connect(boost::bind(&ComponentConnector::handleConnectionConnectFinished, shared_from_this(), _1)); + currentConnection->connect(target); +} + +void ComponentConnector::handleConnectionConnectFinished(bool error) { + currentConnection->onConnectFinished.disconnect(boost::bind(&ComponentConnector::handleConnectionConnectFinished, shared_from_this(), _1)); + if (error) { + currentConnection.reset(); + if (!addressQueryResults.empty()) { + tryNextAddress(); + } + else { + finish(boost::shared_ptr<Connection>()); + } + } + else { + finish(currentConnection); + } +} + +void ComponentConnector::finish(boost::shared_ptr<Connection> connection) { + if (timer) { + timer->stop(); + timer->onTick.disconnect(boost::bind(&ComponentConnector::handleTimeout, shared_from_this())); + timer.reset(); + } + if (addressQuery) { + addressQuery->onResult.disconnect(boost::bind(&ComponentConnector::handleAddressQueryResult, shared_from_this(), _1, _2)); + addressQuery.reset(); + } + if (currentConnection) { + currentConnection->onConnectFinished.disconnect(boost::bind(&ComponentConnector::handleConnectionConnectFinished, shared_from_this(), _1)); + currentConnection.reset(); + } + onConnectFinished(connection); +} + +void ComponentConnector::handleTimeout() { + finish(boost::shared_ptr<Connection>()); +} + +}; |