summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/Network/BOSHConnection.cpp')
-rw-r--r--Swiften/Network/BOSHConnection.cpp104
1 files changed, 98 insertions, 6 deletions
diff --git a/Swiften/Network/BOSHConnection.cpp b/Swiften/Network/BOSHConnection.cpp
index 298b015..9a836cb 100644
--- a/Swiften/Network/BOSHConnection.cpp
+++ b/Swiften/Network/BOSHConnection.cpp
@@ -18,31 +18,41 @@
#include <boost/lexical_cast.hpp>
#include <boost/thread.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)
+BOSHConnection::BOSHConnection(const URL& boshURL, Connector::ref connector, XMLParserFactory* parserFactory, TLSContextFactory* tlsContextFactory, const TLSOptions& tlsOptions)
: boshURL_(boshURL),
connector_(connector),
parserFactory_(parserFactory),
sid_(),
waitingForStartResponse_(false),
rid_(~0ULL),
pending_(false),
connectionReady_(false)
{
+ if (boshURL_.getScheme() == "https") {
+ tlsLayer_ = boost::make_shared<TLSLayer>(tlsContextFactory, tlsOptions);
+ // The following dummyLayer_ is needed as the TLSLayer will pass the decrypted data to its parent layer.
+ // The dummyLayer_ will serve as the parent layer.
+ dummyLayer_ = boost::make_shared<DummyStreamLayer>(tlsLayer_.get());
+ }
}
BOSHConnection::~BOSHConnection() {
cancelConnector();
if (connection_) {
connection_->onDataRead.disconnect(boost::bind(&BOSHConnection::handleDataRead, shared_from_this(), _1));
connection_->onDisconnected.disconnect(boost::bind(&BOSHConnection::handleDisconnected, shared_from_this(), _1));
}
BOSHConnection::disconnect();
@@ -55,33 +65,100 @@ void BOSHConnection::connect() {
void BOSHConnection::cancelConnector() {
if (connector_) {
connector_->onConnectFinished.disconnect(boost::bind(&BOSHConnection::handleConnectFinished, shared_from_this(), _1));
connector_->stop();
connector_.reset();
}
}
+void BOSHConnection::handleTLSConnected() {
+ SWIFT_LOG(debug) << std::endl;
+ onConnectFinished(false);
+}
+
+void BOSHConnection::handleTLSApplicationDataRead(const SafeByteArray& data) {
+ SWIFT_LOG(debug) << std::endl;
+ handleDataRead(boost::make_shared<SafeByteArray>(data));
+}
+
+void BOSHConnection::handleTLSNetowrkDataWriteRequest(const SafeByteArray& data) {
+ SWIFT_LOG(debug) << std::endl;
+ connection_->write(data);
+}
+
+void BOSHConnection::handleRawDataRead(boost::shared_ptr<SafeByteArray> data) {
+ SWIFT_LOG(debug) << std::endl;
+ tlsLayer_->handleDataRead(*data.get());
+}
+
+void BOSHConnection::handleTLSError(boost::shared_ptr<TLSError> error) {
+
+}
+
+void BOSHConnection::writeData(const SafeByteArray& data) {
+ if (tlsLayer_) {
+ tlsLayer_->writeData(data);
+ }
+ else {
+ connection_->write(data);
+ }
+}
+
void BOSHConnection::disconnect() {
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);
}
+bool BOSHConnection::setClientCertificate(CertificateWithKey::ref cert) {
+ if (tlsLayer_) {
+ SWIFT_LOG(debug) << "set client certificate" << std::endl;
+ return tlsLayer_->setClientCertificate(cert);
+ }
+ else {
+ return false;
+ }
+}
+
+Certificate::ref BOSHConnection::getPeerCertificate() const {
+ Certificate::ref peerCertificate;
+ if (tlsLayer_) {
+ peerCertificate = tlsLayer_->getPeerCertificate();
+ }
+ return peerCertificate;
+}
+
+std::vector<Certificate::ref> BOSHConnection::getPeerCertificateChain() const {
+ std::vector<Certificate::ref> peerCertificateChain;
+ if (tlsLayer_) {
+ peerCertificateChain = tlsLayer_->getPeerCertificateChain();
+ }
+ return peerCertificateChain;
+}
+
+CertificateVerificationError::ref BOSHConnection::getPeerCertificateVerificationError() const {
+ CertificateVerificationError::ref verificationError;
+ if (tlsLayer_) {
+ verificationError = tlsLayer_->getPeerCertificateVerificationError();
+ }
+ return verificationError;
+}
+
void BOSHConnection::terminateStream() {
write(createSafeByteArray(""), false, true);
}
void BOSHConnection::write(const SafeByteArray& data) {
write(data, false, false);
}
@@ -123,33 +200,48 @@ std::pair<SafeByteArray, size_t> BOSHConnection::createHTTPRequest(const SafeByt
}
void BOSHConnection::write(const SafeByteArray& data, bool streamRestart, bool terminate) {
assert(connectionReady_);
assert(!sid_.empty());
SafeByteArray safeHeader = createHTTPRequest(data, streamRestart, terminate, rid_, sid_, boshURL_).first;
onBOSHDataWritten(safeHeader);
- connection_->write(safeHeader);
+ writeData(safeHeader);
pending_ = true;
SWIFT_LOG(debug) << "write data: " << safeByteArrayToString(safeHeader) << std::endl;
}
void BOSHConnection::handleConnectFinished(Connection::ref connection) {
cancelConnector();
connectionReady_ = !!connection;
if (connectionReady_) {
connection_ = connection;
- connection_->onDataRead.connect(boost::bind(&BOSHConnection::handleDataRead, shared_from_this(), _1));
- connection_->onDisconnected.connect(boost::bind(&BOSHConnection::handleDisconnected, shared_from_this(), _1));
+ if (tlsLayer_) {
+ connection_->onDataRead.connect(boost::bind(&BOSHConnection::handleRawDataRead, shared_from_this(), _1));
+ connection_->onDisconnected.connect(boost::bind(&BOSHConnection::handleDisconnected, shared_from_this(), _1));
+
+ tlsLayer_->getContext()->onDataForNetwork.connect(boost::bind(&BOSHConnection::handleTLSNetowrkDataWriteRequest, shared_from_this(), _1));
+ tlsLayer_->getContext()->onDataForApplication.connect(boost::bind(&BOSHConnection::handleTLSApplicationDataRead, shared_from_this(), _1));
+ tlsLayer_->onConnected.connect(boost::bind(&BOSHConnection::handleTLSConnected, shared_from_this()));
+ tlsLayer_->onError.connect(boost::bind(&BOSHConnection::handleTLSError, shared_from_this(), _1));
+ tlsLayer_->connect();
+ }
+ else {
+ connection_->onDataRead.connect(boost::bind(&BOSHConnection::handleDataRead, shared_from_this(), _1));
+ connection_->onDisconnected.connect(boost::bind(&BOSHConnection::handleDisconnected, shared_from_this(), _1));
+ }
+ }
+
+ if (!connectionReady_ || !tlsLayer_) {
+ onConnectFinished(!connectionReady_);
}
- onConnectFinished(!connectionReady_);
}
void BOSHConnection::startStream(const std::string& to, unsigned long long rid) {
assert(connectionReady_);
// Session Creation Request
std::stringstream content;
std::stringstream header;
content << "<body content='text/xml; charset=utf-8'"
@@ -174,19 +266,19 @@ void BOSHConnection::startStream(const std::string& to, unsigned long long rid)
header << "\r\n"
// << "Accept-Encoding: deflate\r\n"
<< "Content-Type: text/xml; charset=utf-8\r\n"
<< "Content-Length: " << contentString.size() << "\r\n\r\n"
<< contentString;
waitingForStartResponse_ = true;
SafeByteArray safeHeader = createSafeByteArray(header.str());
onBOSHDataWritten(safeHeader);
- connection_->write(safeHeader);
+ writeData(safeHeader);
SWIFT_LOG(debug) << "write stream header: " << safeByteArrayToString(safeHeader) << std::endl;
}
void BOSHConnection::handleDataRead(boost::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]]"));