summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Markmann <tm@ayena.de>2017-03-13 09:01:54 (GMT)
committerKevin Smith <kevin.smith@isode.com>2017-03-15 11:44:46 (GMT)
commit87d5f54a90f2759aae587f01650e44aee8f2fe3f (patch)
treec84015f0343228aba73642fdd2adc6322631f937 /Swiften/Network/BOSHConnection.cpp
parent3368a6e5f220f00e03b3ebb41bdd8872ffdf81be (diff)
downloadswift-87d5f54a90f2759aae587f01650e44aee8f2fe3f.zip
swift-87d5f54a90f2759aae587f01650e44aee8f2fe3f.tar.bz2
Do no emit onXMPPDataRead when the session is terminated
On a bosh error BOSHSessionStream, posts an event to the event loop that closes the XMPP stream. If onXMPPDataRead is emitted, that data is handled before the close of the stream though, which can cause another BOSH request to be sent. Test-Information: Added a unit test verifying the behaviour. Wrote a custom python script replicating the original error and verified that Swift does not stay connected on a BOSH error with additional text data. Tested on macOS 10.12.3 with recent clang trunk. Change-Id: Ie90099afa0934707a6758b00706a65227ceb48b8
Diffstat (limited to 'Swiften/Network/BOSHConnection.cpp')
-rw-r--r--Swiften/Network/BOSHConnection.cpp3
1 files changed, 2 insertions, 1 deletions
diff --git a/Swiften/Network/BOSHConnection.cpp b/Swiften/Network/BOSHConnection.cpp
index 1c468f1..b4ffa7d 100644
--- a/Swiften/Network/BOSHConnection.cpp
+++ b/Swiften/Network/BOSHConnection.cpp
@@ -1,38 +1,38 @@
/*
* Copyright (c) 2011 Thilo Cestonaro
* Licensed under the simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
/*
- * Copyright (c) 2011-2016 Isode Limited.
+ * Copyright (c) 2011-2017 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
#include <Swiften/Network/BOSHConnection.h>
#include <string>
#include <thread>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <Swiften/Base/ByteArray.h>
#include <Swiften/Base/Concat.h>
#include <Swiften/Base/Log.h>
#include <Swiften/Base/String.h>
#include <Swiften/Network/HostAddressPort.h>
#include <Swiften/Parser/BOSHBodyExtractor.h>
#include <Swiften/StreamStack/DummyStreamLayer.h>
#include <Swiften/StreamStack/TLSLayer.h>
#include <Swiften/TLS/TLSContext.h>
#include <Swiften/TLS/TLSOptions.h>
namespace Swift {
BOSHConnection::BOSHConnection(const URL& boshURL, Connector::ref connector, XMLParserFactory* parserFactory, TLSContextFactory* tlsContextFactory, const TLSOptions& tlsOptions)
: boshURL_(boshURL),
connector_(connector),
parserFactory_(parserFactory),
sid_(),
@@ -269,60 +269,61 @@ void BOSHConnection::startStream(const std::string& to, unsigned long long rid)
<< "Content-Length: " << contentString.size() << "\r\n\r\n"
<< contentString;
waitingForStartResponse_ = true;
SafeByteArray safeHeader = createSafeByteArray(header.str());
onBOSHDataWritten(safeHeader);
writeData(safeHeader);
SWIFT_LOG(debug) << "write stream header: " << safeByteArrayToString(safeHeader) << std::endl;
}
void BOSHConnection::handleDataRead(std::shared_ptr<SafeByteArray> data) {
onBOSHDataRead(*data);
buffer_ = concat(buffer_, *data);
std::string response = safeByteArrayToString(buffer_);
if (response.find("\r\n\r\n") == std::string::npos) {
onBOSHDataRead(createSafeByteArray("[[Previous read incomplete, pending]]"));
return;
}
std::string httpCode = response.substr(response.find(" ") + 1, 3);
if (httpCode != "200") {
onHTTPError(httpCode);
return;
}
BOSHBodyExtractor parser(parserFactory_, createByteArray(response.substr(response.find("\r\n\r\n") + 4)));
if (parser.getBody()) {
if (parser.getBody()->attributes.getAttribute("type") == "terminate") {
BOSHError::Type errorType = parseTerminationCondition(parser.getBody()->attributes.getAttribute("condition"));
onSessionTerminated(errorType == BOSHError::NoError ? std::shared_ptr<BOSHError>() : std::make_shared<BOSHError>(errorType));
+ return;
}
buffer_.clear();
if (waitingForStartResponse_) {
waitingForStartResponse_ = false;
sid_ = parser.getBody()->attributes.getAttribute("sid");
std::string requestsString = parser.getBody()->attributes.getAttribute("requests");
size_t requests = 2;
if (!requestsString.empty()) {
try {
requests = boost::lexical_cast<size_t>(requestsString);
}
catch (const boost::bad_lexical_cast&) {
}
}
onSessionStarted(sid_, requests);
}
SafeByteArray payload = createSafeByteArray(parser.getBody()->content);
/* Say we're good to go again, so don't add anything after here in the method */
pending_ = false;
onXMPPDataRead(payload);
}
}
BOSHError::Type BOSHConnection::parseTerminationCondition(const std::string& text) {
BOSHError::Type condition = BOSHError::UndefinedCondition;
if (text == "bad-request") {
condition = BOSHError::BadRequest;
}
else if (text == "host-gone") {