diff options
author | Remko Tronçon <git@el-tramo.be> | 2010-10-07 21:37:48 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2010-10-07 21:39:40 (GMT) |
commit | 091f554f42dcdef534718fb759eb45b622adfd4f (patch) | |
tree | b8753f62884ef5ef46d04782bb38d8ef2ed38d01 /Swiften/Network | |
parent | 88eab3d1d9b722590da3837e3c79839189ea58d2 (diff) | |
download | swift-091f554f42dcdef534718fb759eb45b622adfd4f.zip swift-091f554f42dcdef534718fb759eb45b622adfd4f.tar.bz2 |
Fix crashes on disconnect during connect.
Resolves: #588
Diffstat (limited to 'Swiften/Network')
-rw-r--r-- | Swiften/Network/Connector.cpp | 13 | ||||
-rw-r--r-- | Swiften/Network/Connector.h | 2 | ||||
-rw-r--r-- | Swiften/Network/StaticDomainNameResolver.cpp | 17 | ||||
-rw-r--r-- | Swiften/Network/UnitTest/ConnectorTest.cpp | 31 |
4 files changed, 55 insertions, 8 deletions
diff --git a/Swiften/Network/Connector.cpp b/Swiften/Network/Connector.cpp index d9a4c5d..01875f7 100644 --- a/Swiften/Network/Connector.cpp +++ b/Swiften/Network/Connector.cpp @@ -39,6 +39,10 @@ void Connector::start() { serviceQuery->run(); } +void Connector::stop() { + finish(boost::shared_ptr<Connection>()); +} + void Connector::queryAddress(const String& hostname) { assert(!addressQuery); addressQuery = resolver->createAddressQuery(hostname); @@ -112,7 +116,7 @@ void Connector::tryConnect(const HostAddressPort& target) { assert(!currentConnection); //std::cout << "Connector::tryConnect() " << target.getAddress().toString() << " " << target.getPort() << std::endl; currentConnection = connectionFactory->createConnection(); - connectFinishedConnection = currentConnection->onConnectFinished.connect(boost::bind(&Connector::handleConnectionConnectFinished, shared_from_this(), _1)); + currentConnection->onConnectFinished.connect(boost::bind(&Connector::handleConnectionConnectFinished, shared_from_this(), _1)); currentConnection->connect(target); } @@ -138,15 +142,20 @@ void Connector::handleConnectionConnectFinished(bool error) { void Connector::finish(boost::shared_ptr<Connection> connection) { if (timer) { timer->stop(); + timer->onTick.disconnect(boost::bind(&Connector::handleTimeout, shared_from_this())); timer.reset(); } if (serviceQuery) { + serviceQuery->onResult.disconnect(boost::bind(&Connector::handleServiceQueryResult, shared_from_this(), _1)); serviceQuery.reset(); } if (addressQuery) { + addressQuery->onResult.disconnect(boost::bind(&Connector::handleAddressQueryResult, shared_from_this(), _1, _2)); addressQuery.reset(); } - connectFinishedConnection.disconnect(); + if (currentConnection) { + currentConnection->onConnectFinished.disconnect(boost::bind(&Connector::handleConnectionConnectFinished, shared_from_this(), _1)); + } onConnectFinished(connection); } diff --git a/Swiften/Network/Connector.h b/Swiften/Network/Connector.h index 36026de..52779c2 100644 --- a/Swiften/Network/Connector.h +++ b/Swiften/Network/Connector.h @@ -33,6 +33,7 @@ namespace Swift { void setTimeoutMilliseconds(int milliseconds); void start(); + void stop(); boost::signal<void (boost::shared_ptr<Connection>)> onConnectFinished; @@ -65,6 +66,5 @@ namespace Swift { std::deque<HostAddress> addressQueryResults; bool queriedAllServices; boost::shared_ptr<Connection> currentConnection; - boost::bsignals::connection connectFinishedConnection; }; }; diff --git a/Swiften/Network/StaticDomainNameResolver.cpp b/Swiften/Network/StaticDomainNameResolver.cpp index b94dd11..636f310 100644 --- a/Swiften/Network/StaticDomainNameResolver.cpp +++ b/Swiften/Network/StaticDomainNameResolver.cpp @@ -15,7 +15,7 @@ using namespace Swift; namespace { - struct ServiceQuery : public DomainNameServiceQuery, public EventOwner { + struct ServiceQuery : public DomainNameServiceQuery, public boost::enable_shared_from_this<ServiceQuery> { ServiceQuery(const String& service, Swift::StaticDomainNameResolver* resolver) : service(service), resolver(resolver) {} virtual void run() { @@ -28,14 +28,18 @@ namespace { results.push_back(i->second); } } - MainEventLoop::postEvent(boost::bind(boost::ref(onResult), results)); + MainEventLoop::postEvent(boost::bind(&ServiceQuery::emitOnResult, shared_from_this(), results)); + } + + void emitOnResult(std::vector<DomainNameServiceQuery::Result> results) { + onResult(results); } String service; StaticDomainNameResolver* resolver; }; - struct AddressQuery : public DomainNameAddressQuery, public EventOwner { + struct AddressQuery : public DomainNameAddressQuery, public boost::enable_shared_from_this<AddressQuery> { AddressQuery(const String& host, StaticDomainNameResolver* resolver) : host(host), resolver(resolver) {} virtual void run() { @@ -45,12 +49,15 @@ namespace { StaticDomainNameResolver::AddressesMap::const_iterator i = resolver->getAddresses().find(host); if (i != resolver->getAddresses().end()) { MainEventLoop::postEvent( - boost::bind(boost::ref(onResult), i->second, boost::optional<DomainNameResolveError>())); + boost::bind(&AddressQuery::emitOnResult, shared_from_this(), i->second, boost::optional<DomainNameResolveError>())); } else { - MainEventLoop::postEvent(boost::bind(boost::ref(onResult), std::vector<HostAddress>(), boost::optional<DomainNameResolveError>(DomainNameResolveError()))); + MainEventLoop::postEvent(boost::bind(&AddressQuery::emitOnResult, shared_from_this(), std::vector<HostAddress>(), boost::optional<DomainNameResolveError>(DomainNameResolveError()))); } + } + void emitOnResult(std::vector<HostAddress> results, boost::optional<DomainNameResolveError> error) { + onResult(results, error); } String host; diff --git a/Swiften/Network/UnitTest/ConnectorTest.cpp b/Swiften/Network/UnitTest/ConnectorTest.cpp index 32a7157..2e396b3 100644 --- a/Swiften/Network/UnitTest/ConnectorTest.cpp +++ b/Swiften/Network/UnitTest/ConnectorTest.cpp @@ -34,6 +34,8 @@ class ConnectorTest : public CppUnit::TestFixture { CPPUNIT_TEST(testConnect_TimeoutDuringResolve); CPPUNIT_TEST(testConnect_TimeoutDuringConnect); CPPUNIT_TEST(testConnect_NoTimeout); + CPPUNIT_TEST(testStop_DuringSRVQuery); + CPPUNIT_TEST(testStop_Timeout); CPPUNIT_TEST_SUITE_END(); public: @@ -208,6 +210,35 @@ class ConnectorTest : public CppUnit::TestFixture { CPPUNIT_ASSERT(connections[0]); } + void testStop_DuringSRVQuery() { + Connector::ref testling(createConnector()); + resolver->addXMPPClientService("foo.com", host1); + + testling->start(); + testling->stop(); + + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + } + + void testStop_Timeout() { + Connector::ref testling(createConnector()); + testling->setTimeoutMilliseconds(10); + resolver->addXMPPClientService("foo.com", host1); + + testling->start(); + testling->stop(); + + eventLoop->processEvents(); + timerFactory->setTime(10); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + } + private: Connector::ref createConnector() { |