diff options
| -rw-r--r-- | Swiften/Network/BOSHConnection.cpp | 7 | ||||
| -rw-r--r-- | Swiften/Network/BOSHConnectionPool.cpp | 33 |
2 files changed, 29 insertions, 11 deletions
diff --git a/Swiften/Network/BOSHConnection.cpp b/Swiften/Network/BOSHConnection.cpp index 539109a..377373d 100644 --- a/Swiften/Network/BOSHConnection.cpp +++ b/Swiften/Network/BOSHConnection.cpp @@ -51,29 +51,32 @@ void BOSHConnection::connect() { connector_->start(); } void BOSHConnection::cancelConnector() { if (connector_) { connector_->onConnectFinished.disconnect(boost::bind(&BOSHConnection::handleConnectFinished, shared_from_this(), _1)); connector_->stop(); connector_.reset(); } } void BOSHConnection::disconnect() { - cancelConnector(); - if(connection_) { + if (connection_) { connection_->disconnect(); sid_ = ""; } + else { + /* handleDisconnected takes care of the connector_ as well */ + handleDisconnected(boost::optional<Connection::Error>()); + } } void BOSHConnection::restartStream() { write(createSafeByteArray(""), true, false); } void BOSHConnection::terminateStream() { write(createSafeByteArray(""), false, true); } void BOSHConnection::write(const SafeByteArray& data) { diff --git a/Swiften/Network/BOSHConnectionPool.cpp b/Swiften/Network/BOSHConnectionPool.cpp index 83310fb..e535deb 100644 --- a/Swiften/Network/BOSHConnectionPool.cpp +++ b/Swiften/Network/BOSHConnectionPool.cpp @@ -36,25 +36,32 @@ BOSHConnectionPool::BOSHConnectionPool(const URL& boshURL, DomainNameResolver* r } connectionFactory = new HTTPConnectProxiedConnectionFactory(realResolver, connectionFactory, timerFactory, boshHTTPConnectProxyURL.getHost(), URL::getPortOrDefaultPort(boshHTTPConnectProxyURL), boshHTTPConnectProxyAuthID, boshHTTPConnectProxyAuthPassword); } if (boshURL.getScheme() == "https") { connectionFactory = new TLSConnectionFactory(tlsFactory, connectionFactory); myConnectionFactories.push_back(connectionFactory); } resolver = new CachingDomainNameResolver(realResolver, eventLoop); createConnection(); } BOSHConnectionPool::~BOSHConnectionPool() { - close(); + /* Don't do a normal close here. Instead kill things forcibly, as close() or writeFooter() will already have been called */ + std::vector<BOSHConnection::ref> connectionCopies = connections; + foreach (BOSHConnection::ref connection, connectionCopies) { + if (connection) { + destroyConnection(connection); + connection->disconnect(); + } + } foreach (ConnectionFactory* factory, myConnectionFactories) { delete factory; } delete resolver; } void BOSHConnectionPool::write(const SafeByteArray& data) { dataQueue.push_back(data); tryToSendQueuedData(); } void BOSHConnectionPool::handleDataRead(const SafeByteArray& data) { @@ -73,30 +80,34 @@ void BOSHConnectionPool::restartStream() { } else { pendingRestart = true; } } void BOSHConnectionPool::writeFooter() { pendingTerminate = true; tryToSendQueuedData(); } void BOSHConnectionPool::close() { - /* TODO: Send a terminate here. */ - std::vector<BOSHConnection::ref> connectionCopies = connections; - foreach (BOSHConnection::ref connection, connectionCopies) { - if (connection) { - connection->disconnect(); - destroyConnection(connection); + if (!sid.empty()) { + writeFooter(); + } + else { + pendingTerminate = true; + std::vector<BOSHConnection::ref> connectionCopies = connections; + foreach (BOSHConnection::ref connection, connectionCopies) { + if (connection) { + connection->disconnect(); + } } } } void BOSHConnectionPool::handleSessionStarted(const std::string& sessionID, size_t requests) { sid = sessionID; requestLimit = requests; onSessionStarted(); } void BOSHConnectionPool::handleConnectFinished(bool error, BOSHConnection::ref connection) { if (error) { @@ -149,25 +160,26 @@ void BOSHConnectionPool::tryToSendQueuedData() { suitableConnection->setRID(rid); SafeByteArray data; foreach (const SafeByteArray& datum, dataQueue) { data.insert(data.end(), datum.begin(), datum.end()); } suitableConnection->write(data); dataQueue.clear(); } else if (pendingTerminate) { rid++; suitableConnection->setRID(rid); suitableConnection->terminateStream(); - onSessionTerminated(boost::shared_ptr<BOSHError>()); + sid = ""; + close(); } } if (!pendingTerminate) { /* Ensure there's always a session waiting to read data for us */ bool pending = false; foreach (BOSHConnection::ref connection, connections) { if (connection && !connection->isReadyToSend()) { pending = true; } } if (!pending) { if (restartCount >= 1) { @@ -191,25 +203,28 @@ void BOSHConnectionPool::tryToSendQueuedData() { } } } } } void BOSHConnectionPool::handleHTTPError(const std::string& /*errorCode*/) { handleSessionTerminated(boost::make_shared<BOSHError>(BOSHError::UndefinedCondition)); } void BOSHConnectionPool::handleConnectionDisconnected(bool error, BOSHConnection::ref connection) { destroyConnection(connection); - if (false && error) { + if (pendingTerminate && sid.empty() && connections.empty()) { + handleSessionTerminated(BOSHError::ref()); + } + else if (false && error) { handleSessionTerminated(boost::make_shared<BOSHError>(BOSHError::UndefinedCondition)); } else { /* We might have just freed up a connection slot to send with */ tryToSendQueuedData(); } } boost::shared_ptr<BOSHConnection> BOSHConnectionPool::createConnection() { Connector::ref connector = Connector::create(boshURL.getHost(), URL::getPortOrDefaultPort(boshURL), false, resolver, connectionFactory, timerFactory); BOSHConnection::ref connection = BOSHConnection::create(boshURL, connector, xmlParserFactory); connection->onXMPPDataRead.connect(boost::bind(&BOSHConnectionPool::handleDataRead, this, _1)); |
Swift