summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Smith <git@kismith.co.uk>2010-05-27 13:24:44 (GMT)
committerKevin Smith <git@kismith.co.uk>2010-05-27 17:34:56 (GMT)
commit109e50103d757d880e7ce390482951111dad1e22 (patch)
treecbb9cdb9f63eda164727a24653c8ef8bdf283a46
parent0bdb45be4aa66dcc478d5f061096b1adbaa3ab2c (diff)
downloadswift-109e50103d757d880e7ce390482951111dad1e22.zip
swift-109e50103d757d880e7ce390482951111dad1e22.tar.bz2
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
-rw-r--r--Swift/Controllers/MainController.cpp5
-rw-r--r--Swiften/Client/Client.cpp17
-rw-r--r--Swiften/Client/Client.h2
-rw-r--r--Swiften/Network/PlatformDomainNameServiceQuery.cpp1
-rw-r--r--Swiften/QA/ReconnectTest/ReconnectTest.cpp73
-rw-r--r--Swiften/QA/ReconnectTest/SConscript24
-rw-r--r--Swiften/QA/SConscript1
-rw-r--r--Swiften/TLS/OpenSSL/OpenSSLContext.cpp2
8 files changed, 118 insertions, 7 deletions
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> connection) {
+void Client::handleConnectorFinished(boost::shared_ptr<Connection> 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> 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<void (const String&)> onDataWritten;
private:
- void handleConnectorFinished(boost::shared_ptr<Connection>);
+ void handleConnectorFinished(boost::shared_ptr<Connection>, Connector::ref);
void send(boost::shared_ptr<Stanza>);
virtual String getNewIQID();
void handleElement(boost::shared_ptr<Element>);
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<char*>(service.getUTF8Data()), ns_c_in, ns_t_srv, reinterpret_cast<u_char*>(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 <boost/bind.hpp>
+#include <boost/thread.hpp>
+
+#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<BoostTimer> 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<BoostTimer> 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<BoostTimer>());
+ 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;
}
}