summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Smith <git@kismith.co.uk>2012-12-04 15:56:42 (GMT)
committerKevin Smith <git@kismith.co.uk>2012-12-04 17:33:59 (GMT)
commitd96f856fea35e8a8f6e426318a87f044223de8d8 (patch)
tree7050a69456b523c1810e95964784fed760deecaf /Swiften/Network/BOSHConnectionPool.cpp
parenta6f8c4e4579b93b3e004229dcdeb098bd5b356a4 (diff)
downloadswift-d96f856fea35e8a8f6e426318a87f044223de8d8.zip
swift-d96f856fea35e8a8f6e426318a87f044223de8d8.tar.bz2
Make sure we say the session's ended after calling close() with BOSH.
Change-Id: I35b290cb75657e2d9778cc81d83c8a52693f1103 Resolves: #1184
Diffstat (limited to 'Swiften/Network/BOSHConnectionPool.cpp')
-rw-r--r--Swiften/Network/BOSHConnectionPool.cpp33
1 files changed, 24 insertions, 9 deletions
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));