summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swiften/Client/CoreClient.cpp57
-rw-r--r--Swiften/Client/CoreClient.h4
-rw-r--r--Swiften/QA/ClientTest/ClientTest.cpp34
3 files changed, 62 insertions, 33 deletions
diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp
index dbc6de2..22e3612 100644
--- a/Swiften/Client/CoreClient.cpp
+++ b/Swiften/Client/CoreClient.cpp
@@ -35,67 +35,60 @@ CoreClient::CoreClient(const JID& jid, const SafeByteArray& password, NetworkFac
stanzaChannel_->onStanzaAcked.connect(boost::bind(&CoreClient::handleStanzaAcked, this, _1));
stanzaChannel_->onAvailableChanged.connect(boost::bind(&CoreClient::handleStanzaChannelAvailableChanged, this, _1));
iqRouter_ = new IQRouter(stanzaChannel_);
iqRouter_->setJID(jid);
tlsFactories = new PlatformTLSFactories();
}
CoreClient::~CoreClient() {
- if ((session_ && !session_->isFinished()) || connection_) {
- std::cerr << "Warning: Client not disconnected properly" << std::endl;
- }
+ forceReset();
delete tlsFactories;
delete iqRouter_;
stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&CoreClient::handleStanzaChannelAvailableChanged, this, _1));
stanzaChannel_->onMessageReceived.disconnect(boost::bind(&CoreClient::handleMessageReceived, this, _1));
stanzaChannel_->onPresenceReceived.disconnect(boost::bind(&CoreClient::handlePresenceReceived, this, _1));
stanzaChannel_->onStanzaAcked.disconnect(boost::bind(&CoreClient::handleStanzaAcked, this, _1));
delete stanzaChannel_;
}
void CoreClient::connect(const ClientOptions& o) {
SWIFT_LOG(debug) << "Connecting" << std::endl;
options = o;
connect(jid_.getDomain());
}
void CoreClient::connect(const std::string& host) {
+ forceReset();
+
SWIFT_LOG(debug) << "Connecting to host " << host << std::endl;
disconnectRequested_ = false;
assert(!connector_);
-
assert(proxyConnectionFactories.empty());
PlatformProxyProvider proxyProvider;
if(proxyProvider.getSOCKS5Proxy().isValid()) {
proxyConnectionFactories.push_back(new SOCKS5ProxiedConnectionFactory(networkFactories->getConnectionFactory(), proxyProvider.getSOCKS5Proxy()));
}
if(proxyProvider.getHTTPConnectProxy().isValid()) {
proxyConnectionFactories.push_back(new HTTPConnectProxiedConnectionFactory(networkFactories->getConnectionFactory(), proxyProvider.getHTTPConnectProxy()));
}
std::vector<ConnectionFactory*> connectionFactories(proxyConnectionFactories);
connectionFactories.push_back(networkFactories->getConnectionFactory());
connector_ = boost::make_shared<ChainedConnector>(host, networkFactories->getDomainNameResolver(), connectionFactories, networkFactories->getTimerFactory());
connector_->onConnectFinished.connect(boost::bind(&CoreClient::handleConnectorFinished, this, _1));
connector_->setTimeoutMilliseconds(60*1000);
connector_->start();
}
void CoreClient::handleConnectorFinished(boost::shared_ptr<Connection> connection) {
- connector_->onConnectFinished.disconnect(boost::bind(&CoreClient::handleConnectorFinished, this, _1));
- connector_.reset();
- foreach(ConnectionFactory* f, proxyConnectionFactories) {
- delete f;
- }
- proxyConnectionFactories.clear();
-
+ resetConnector();
if (!connection) {
if (options.forgetPassword) {
purgePassword();
}
onDisconnected(disconnectRequested_ ? boost::optional<ClientError>() : boost::optional<ClientError>(ClientError::ConnectionError));
}
else {
assert(!connection_);
connection_ = connection;
@@ -145,27 +138,19 @@ void CoreClient::disconnect() {
void CoreClient::setCertificate(const std::string& certificate) {
certificate_ = certificate;
}
void CoreClient::handleSessionFinished(boost::shared_ptr<Error> error) {
if (options.forgetPassword) {
purgePassword();
}
- session_->onFinished.disconnect(boost::bind(&CoreClient::handleSessionFinished, this, _1));
- session_->onNeedCredentials.disconnect(boost::bind(&CoreClient::handleNeedCredentials, this));
-
- sessionStream_->onDataRead.disconnect(boost::bind(&CoreClient::handleDataRead, this, _1));
- sessionStream_->onDataWritten.disconnect(boost::bind(&CoreClient::handleDataWritten, this, _1));
- sessionStream_.reset();
-
- connection_->disconnect();
- connection_.reset();
+ resetSession();
boost::optional<ClientError> actualError;
if (error) {
ClientError clientError;
if (boost::shared_ptr<ClientSession::Error> actualError = boost::dynamic_pointer_cast<ClientSession::Error>(error)) {
switch(actualError->type) {
case ClientSession::Error::AuthenticationFailedError:
clientError = ClientError(ClientError::AuthenticationFailedError);
break;
@@ -335,10 +320,42 @@ const JID& CoreClient::getJID() const {
else {
return jid_;
}
}
void CoreClient::purgePassword() {
safeClear(password_);
}
+void CoreClient::resetConnector() {
+ connector_->onConnectFinished.disconnect(boost::bind(&CoreClient::handleConnectorFinished, this, _1));
+ connector_.reset();
+ foreach(ConnectionFactory* f, proxyConnectionFactories) {
+ delete f;
+ }
+ proxyConnectionFactories.clear();
+}
+
+void CoreClient::resetSession() {
+ session_->onFinished.disconnect(boost::bind(&CoreClient::handleSessionFinished, this, _1));
+ session_->onNeedCredentials.disconnect(boost::bind(&CoreClient::handleNeedCredentials, this));
+
+ sessionStream_->onDataRead.disconnect(boost::bind(&CoreClient::handleDataRead, this, _1));
+ sessionStream_->onDataWritten.disconnect(boost::bind(&CoreClient::handleDataWritten, this, _1));
+ sessionStream_.reset();
+
+ connection_->disconnect();
+ connection_.reset();
+}
+
+void CoreClient::forceReset() {
+ if (connector_) {
+ std::cerr << "Warning: Client not disconnected properly: Connector still active" << std::endl;
+ resetConnector();
+ }
+ if (sessionStream_ || connection_) {
+ std::cerr << "Warning: Client not disconnected properly: Session still active" << std::endl;
+ resetSession();
+ }
+}
+
}
diff --git a/Swiften/Client/CoreClient.h b/Swiften/Client/CoreClient.h
index 3472e76..ad31e72 100644
--- a/Swiften/Client/CoreClient.h
+++ b/Swiften/Client/CoreClient.h
@@ -203,18 +203,22 @@ namespace Swift {
void handleSessionFinished(boost::shared_ptr<Error>);
void handleNeedCredentials();
void handleDataRead(const SafeByteArray&);
void handleDataWritten(const SafeByteArray&);
void handlePresenceReceived(boost::shared_ptr<Presence>);
void handleMessageReceived(boost::shared_ptr<Message>);
void handleStanzaAcked(boost::shared_ptr<Stanza>);
void purgePassword();
+ void resetConnector();
+ void resetSession();
+ void forceReset();
+
private:
JID jid_;
SafeByteArray password_;
NetworkFactories* networkFactories;
ClientSessionStanzaChannel* stanzaChannel_;
IQRouter* iqRouter_;
ClientOptions options;
boost::shared_ptr<ChainedConnector> connector_;
std::vector<ConnectionFactory*> proxyConnectionFactories;
diff --git a/Swiften/QA/ClientTest/ClientTest.cpp b/Swiften/QA/ClientTest/ClientTest.cpp
index 584f644..4515893 100644
--- a/Swiften/QA/ClientTest/ClientTest.cpp
+++ b/Swiften/QA/ClientTest/ClientTest.cpp
@@ -16,39 +16,45 @@
#include <Swiften/Roster/GetRosterRequest.h>
#include <Swiften/Client/ClientXMLTracer.h>
using namespace Swift;
SimpleEventLoop eventLoop;
BoostNetworkFactories networkFactories(&eventLoop);
Client* client = 0;
-bool reconnected = false;
bool rosterReceived = false;
+enum TestStage {
+ FirstConnect,
+ Reconnect
+};
+TestStage stage;
-void handleDisconnected(boost::optional<ClientError>) {
- eventLoop.stop();
-}
-
-void handleRosterReceived(boost::shared_ptr<Payload>) {
- if (reconnected) {
- rosterReceived = true;
- client->onDisconnected.connect(boost::bind(&handleDisconnected, _1));
- client->disconnect();
+void handleDisconnected(boost::optional<ClientError> e) {
+ std::cout << "Disconnected: " << e << std::endl;
+ if (stage == FirstConnect) {
+ stage = Reconnect;
+ client->connect();
}
else {
- reconnected = true;
- client->disconnect();
- client->connect();
+ eventLoop.stop();
}
}
+void handleRosterReceived(boost::shared_ptr<Payload>) {
+ rosterReceived = true;
+ std::cout << "Disconnecting" << std::endl;
+ client->disconnect();
+}
+
void handleConnected() {
+ std::cout << "Connected" << std::endl;
+ rosterReceived = false;
GetRosterRequest::ref rosterRequest = GetRosterRequest::create(client->getIQRouter());
rosterRequest->onResponse.connect(boost::bind(&handleRosterReceived, _1));
rosterRequest->send();
}
int main(int, char**) {
char* jid = getenv("SWIFT_CLIENTTEST_JID");
if (!jid) {
std::cerr << "Please set the SWIFT_CLIENTTEST_JID environment variable" << std::endl;
@@ -57,19 +63,21 @@ int main(int, char**) {
char* pass = getenv("SWIFT_CLIENTTEST_PASS");
if (!pass) {
std::cerr << "Please set the SWIFT_CLIENTTEST_PASS environment variable" << std::endl;
return -1;
}
client = new Swift::Client(JID(jid), std::string(pass), &networkFactories);
ClientXMLTracer* tracer = new ClientXMLTracer(client);
client->onConnected.connect(&handleConnected);
+ client->onDisconnected.connect(boost::bind(&handleDisconnected, _1));
client->setAlwaysTrustCertificates();
+ stage = FirstConnect;
client->connect();
{
Timer::ref timer = networkFactories.getTimerFactory()->createTimer(60000);
timer->onTick.connect(boost::bind(&SimpleEventLoop::stop, &eventLoop));
timer->start();
eventLoop.run();
}