summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2010-10-07 21:37:48 (GMT)
committerRemko Tronçon <git@el-tramo.be>2010-10-07 21:39:40 (GMT)
commit091f554f42dcdef534718fb759eb45b622adfd4f (patch)
treeb8753f62884ef5ef46d04782bb38d8ef2ed38d01 /Swiften/Network
parent88eab3d1d9b722590da3837e3c79839189ea58d2 (diff)
downloadswift-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.cpp13
-rw-r--r--Swiften/Network/Connector.h2
-rw-r--r--Swiften/Network/StaticDomainNameResolver.cpp17
-rw-r--r--Swiften/Network/UnitTest/ConnectorTest.cpp31
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() {