From 109e50103d757d880e7ce390482951111dad1e22 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Thu, 27 May 2010 14:24:44 +0100 Subject: Cleaning up code paths for rapid disconnect/reconnect. This includes a fix in OpensSSLContext that stops assert failures when more data is received on a connection after a write has failed. It's worth investigating why this happens, stopping it doing so, and re-instate the assert. Resolves: #402 diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp index 596edd2..d6a5587 100644 --- a/Swift/Controllers/MainController.cpp +++ b/Swift/Controllers/MainController.cpp @@ -333,6 +333,9 @@ void MainController::performLoginFromCachedCredentials() { } client_->onError.connect(boost::bind(&MainController::handleError, this, _1)); client_->onConnected.connect(boost::bind(&MainController::handleConnected, this)); + } else { + /* In case we're in the middle of another login, make sure they don't overlap */ + client_->disconnect(); } client_->connect(); } @@ -387,7 +390,7 @@ void MainController::signOut() { } void MainController::logout() { - if (client_ && client_->isAvailable()) { + if (client_ /*&& client_->isAvailable()*/) { client_->disconnect(); } if (rosterController_) { diff --git a/Swiften/Client/Client.cpp b/Swiften/Client/Client.cpp index 63a93a3..763c83e 100644 --- a/Swiften/Client/Client.cpp +++ b/Swiften/Client/Client.cpp @@ -45,15 +45,23 @@ void Client::connect() { } void Client::connect(const String& host) { - assert(!connector_); + assert(!connector_); // Crash on reconnect is here. connector_ = Connector::create(host, &resolver_, connectionFactory_, timerFactory_); - connector_->onConnectFinished.connect(boost::bind(&Client::handleConnectorFinished, this, _1)); + connector_->onConnectFinished.connect(boost::bind(&Client::handleConnectorFinished, this, _1, connector_)); connector_->setTimeoutMilliseconds(60*1000); connector_->start(); } -void Client::handleConnectorFinished(boost::shared_ptr connection) { +void Client::handleConnectorFinished(boost::shared_ptr connection, Connector::ref connector) { + bool currentConnection = connector_ && (connector.get() == connector_.get()); // TODO: Add domain name resolver error + if (!currentConnection) { + /* disconnect() was called, this connection should be thrown away*/ + if (connection) { + connection->disconnect(); + } + return; + } connector_.reset(); if (!connection) { onError(ClientError::ConnectionError); @@ -81,6 +89,9 @@ void Client::handleConnectorFinished(boost::shared_ptr connection) { } void Client::disconnect() { + if (connector_) { + connector_.reset(); + } if (session_) { session_->finish(); } diff --git a/Swiften/Client/Client.h b/Swiften/Client/Client.h index 92e89f1..e0714bb 100644 --- a/Swiften/Client/Client.h +++ b/Swiften/Client/Client.h @@ -55,7 +55,7 @@ namespace Swift { boost::signal onDataWritten; private: - void handleConnectorFinished(boost::shared_ptr); + void handleConnectorFinished(boost::shared_ptr, Connector::ref); void send(boost::shared_ptr); virtual String getNewIQID(); void handleElement(boost::shared_ptr); diff --git a/Swiften/Network/PlatformDomainNameServiceQuery.cpp b/Swiften/Network/PlatformDomainNameServiceQuery.cpp index 10b9f63..3ee0b18 100644 --- a/Swiften/Network/PlatformDomainNameServiceQuery.cpp +++ b/Swiften/Network/PlatformDomainNameServiceQuery.cpp @@ -86,7 +86,6 @@ void PlatformDomainNameServiceQuery::doRun() { ByteArray response; response.resize(NS_PACKETSZ); int responseLength = res_query(const_cast(service.getUTF8Data()), ns_c_in, ns_t_srv, reinterpret_cast(response.getData()), response.getSize()); - //std::cout << "res_query done " << (responseLength != -1) << std::endl; if (responseLength == -1) { emitError(); return; diff --git a/Swiften/QA/ReconnectTest/ReconnectTest.cpp b/Swiften/QA/ReconnectTest/ReconnectTest.cpp new file mode 100644 index 0000000..f630dd8 --- /dev/null +++ b/Swiften/QA/ReconnectTest/ReconnectTest.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2010 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include +#include + +#include "Swiften/Client/Client.h" +#include "Swiften/Network/BoostTimer.h" +#include "Swiften/EventLoop/MainEventLoop.h" +#include "Swiften/EventLoop/SimpleEventLoop.h" +#include "Swiften/Queries/Requests/GetRosterRequest.h" +#include "Swiften/Client/ClientXMLTracer.h" +#include "Swiften/Network/BoostIOServiceThread.h" +#include "Swiften/Network/MainBoostIOServiceThread.h" + +using namespace Swift; + +using namespace Swift; + +bool connecting_ = false; +Client* client_; +SimpleEventLoop eventLoop_; +int count = 0; + +void handleTick(boost::shared_ptr timer) { + std::cout << "Count " << count++ << std::endl; + if (timer) { + timer->stop(); + } + if (connecting_) { + client_->disconnect(); + } else { + if (count > 60) { + eventLoop_.stop(); + return; + } + client_->connect(); + } + connecting_ = !connecting_; + + int delay = 500; +// int delay = 0; + boost::shared_ptr newTimer(new BoostTimer(delay, &MainBoostIOServiceThread::getInstance().getIOService())); + newTimer->onTick.connect(boost::bind(&handleTick, timer)); + newTimer->start(); +} + +int main(int, char**) { + char* jidChars = getenv("SWIFT_CLIENTTEST_JID"); + if (!jidChars) { + std::cerr << "Please set the SWIFT_CLIENTTEST_JID environment variable" << std::endl; + return -1; + } + char* passChars = getenv("SWIFT_CLIENTTEST_PASS"); + if (!passChars) { + std::cerr << "Please set the SWIFT_CLIENTTEST_PASS environment variable" << std::endl; + return -1; + } + + JID jid(jidChars); + String pass(passChars); + + client_ = new Swift::Client(jid, pass); + handleTick(boost::shared_ptr()); + eventLoop_.run(); + + delete client_; + return 0; + +} diff --git a/Swiften/QA/ReconnectTest/SConscript b/Swiften/QA/ReconnectTest/SConscript new file mode 100644 index 0000000..8e6a0fc --- /dev/null +++ b/Swiften/QA/ReconnectTest/SConscript @@ -0,0 +1,24 @@ +import os + +Import("env") + +if env["TEST"] : + myenv = env.Clone() + myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) + myenv.MergeFlags(myenv["CPPUNIT_FLAGS"]) + myenv.MergeFlags(myenv["LIBIDN_FLAGS"]) + myenv.MergeFlags(myenv["BOOST_FLAGS"]) + myenv.MergeFlags(myenv.get("SQLITE_FLAGS", "")) + myenv.MergeFlags(myenv["ZLIB_FLAGS"]) + myenv.MergeFlags(myenv["OPENSSL_FLAGS"]) + myenv.MergeFlags(myenv.get("LIBXML_FLAGS", "")) + myenv.MergeFlags(myenv.get("EXPAT_FLAGS", "")) +# myenv.Append(LIBPATH = ["/opt/local/lib"]) +# myenv.Append(LIBS = ["efence"]) + + for i in ["SWIFT_CLIENTTEST_JID", "SWIFT_CLIENTTEST_PASS"]: + if os.environ.get(i, "") : + myenv["ENV"][i] = os.environ[i] + + tester = myenv.Program("ReconnectTest", ["ReconnectTest.cpp"]) + myenv.Test(tester, "system") diff --git a/Swiften/QA/SConscript b/Swiften/QA/SConscript index ede7b39..dda6524 100644 --- a/Swiften/QA/SConscript +++ b/Swiften/QA/SConscript @@ -1,4 +1,5 @@ SConscript([ "NetworkTest/SConscript", + "ReconnectTest/SConscript", "ClientTest/SConscript", ]) diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp index ae5ccf5..80575ca 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp +++ b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp @@ -93,7 +93,7 @@ void OpenSSLContext::handleDataFromNetwork(const ByteArray& data) { sendPendingDataToApplication(); break; case Start: assert(false); break; - case Error: assert(false); break; + case Error: /*assert(false);*/ break; } } -- cgit v0.10.2-6-g49f6