diff options
-rw-r--r-- | Swiften/Client/CoreClient.cpp | 57 | ||||
-rw-r--r-- | Swiften/Client/CoreClient.h | 4 | ||||
-rw-r--r-- | Swiften/QA/ClientTest/ClientTest.cpp | 34 |
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(); } |