summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThilo Cestonaro <thilo@cestona.ro>2011-09-28 22:03:14 (GMT)
committerKevin Smith <git@kismith.co.uk>2011-12-13 08:17:58 (GMT)
commitfd17fe0d239f97cedebe4ceffa234155bd299b68 (patch)
tree010ae5155e6e807b548861304657a25699487e1f /Swiften
parent7d19f0d81371d86d530d0e7083a04db914ce6745 (diff)
downloadswift-fd17fe0d239f97cedebe4ceffa234155bd299b68.zip
swift-fd17fe0d239f97cedebe4ceffa234155bd299b68.tar.bz2
BOSH implementation started
License: This patch is BSD-licensed, see http://www.opensource.org/licenses/bsd-license.php
Diffstat (limited to 'Swiften')
-rw-r--r--Swiften/Client/CoreClient.cpp4
-rw-r--r--Swiften/Network/BOSHConnection.cpp132
-rw-r--r--Swiften/Network/BOSHConnection.h52
-rw-r--r--Swiften/Network/BOSHConnectionFactory.cpp21
-rw-r--r--Swiften/Network/BOSHConnectionFactory.h22
-rw-r--r--Swiften/Network/SConscript2
-rw-r--r--Swiften/Parser/BOSHParser.cpp55
-rw-r--r--Swiften/Parser/BOSHParser.h47
-rw-r--r--Swiften/Parser/SConscript1
9 files changed, 335 insertions, 1 deletions
diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp
index a8a5c8f..08f31a0 100644
--- a/Swiften/Client/CoreClient.cpp
+++ b/Swiften/Client/CoreClient.cpp
@@ -24,6 +24,7 @@
#include <Swiften/Client/ClientSessionStanzaChannel.h>
#include <Swiften/Network/SOCKS5ProxiedConnectionFactory.h>
#include <Swiften/Network/HTTPConnectProxiedConnectionFactory.h>
+#include <Swiften/Network/BOSHConnectionFactory.h>
namespace Swift {
@@ -69,7 +70,8 @@ void CoreClient::connect(const std::string& host) {
proxyConnectionFactories.push_back(new HTTPConnectProxiedConnectionFactory(networkFactories->getConnectionFactory(), networkFactories->getProxyProvider()->getHTTPConnectProxy()));
}
std::vector<ConnectionFactory*> connectionFactories(proxyConnectionFactories);
- connectionFactories.push_back(networkFactories->getConnectionFactory());
+ // connectionFactories.push_back(networkFactories->getConnectionFactory());
+ connectionFactories.push_back(new BOSHConnectionFactory(networkFactories->getConnectionFactory()));
connector_ = boost::make_shared<ChainedConnector>(host, networkFactories->getDomainNameResolver(), connectionFactories, networkFactories->getTimerFactory());
connector_->onConnectFinished.connect(boost::bind(&CoreClient::handleConnectorFinished, this, _1));
diff --git a/Swiften/Network/BOSHConnection.cpp b/Swiften/Network/BOSHConnection.cpp
new file mode 100644
index 0000000..549c652
--- /dev/null
+++ b/Swiften/Network/BOSHConnection.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "BOSHConnection.h"
+#include <boost/bind.hpp>
+#include <boost/thread.hpp>
+#include <string>
+
+#include <Swiften/Network/ConnectionFactory.h>
+#include <Swiften/Base/Log.h>
+#include <Swiften/Base/String.h>
+#include <Swiften/Base/ByteArray.h>
+#include <Swiften/Network/HostAddressPort.h>
+#include <Swiften/Parser/BOSHParser.h>
+
+namespace Swift {
+
+ BOSHConnection::BOSHConnection(ConnectionFactory* connectionFactory)
+ : connectionFactory_(connectionFactory), server_(HostAddressPort(HostAddress("0.0.0.0"), 0)), sid_()
+ {
+ reopenAfterAction = true;
+ }
+
+ BOSHConnection::~BOSHConnection() {
+ if (newConnection_) {
+ newConnection_->onDataRead.disconnect(boost::bind(&BOSHConnection::handleDataRead, shared_from_this(), _1));
+ newConnection_->onDisconnected.disconnect(boost::bind(&BOSHConnection::handleDisconnected, shared_from_this(), _1));
+ }
+ if (currentConnection_) {
+ currentConnection_->onDataRead.disconnect(boost::bind(&BOSHConnection::handleDataRead, shared_from_this(), _1));
+ currentConnection_->onDisconnected.disconnect(boost::bind(&BOSHConnection::handleDisconnected, shared_from_this(), _1));
+ }
+ }
+
+ void BOSHConnection::connect(const HostAddressPort& server) {
+ server_ = server;
+ newConnection_ = connectionFactory_->createConnection();
+ newConnection_->onConnectFinished.connect(boost::bind(&BOSHConnection::handleConnectionConnectFinished, shared_from_this(), _1));
+ newConnection_->onDataRead.connect(boost::bind(&BOSHConnection::handleDataRead, shared_from_this(), _1));
+ newConnection_->onDisconnected.connect(boost::bind(&BOSHConnection::handleDisconnected, shared_from_this(), _1));
+ SWIFT_LOG(debug) << "connect to server " << server.getAddress().toString() << ":" << server.getPort() << std::endl;
+ newConnection_->connect(HostAddressPort(HostAddress("85.10.192.88"), 5280));
+ }
+
+ void BOSHConnection::listen() {
+ assert(false);
+ }
+
+ void BOSHConnection::disconnect() {
+ if(newConnection_)
+ newConnection_->disconnect();
+
+ if(currentConnection_)
+ currentConnection_->disconnect();
+ }
+
+ void BOSHConnection::write(const SafeByteArray& data) {
+ SWIFT_LOG(debug) << "write data: " << safeByteArrayToString(data) << std::endl;
+ }
+
+ void BOSHConnection::handleConnectionConnectFinished(bool error) {
+ newConnection_->onConnectFinished.disconnect(boost::bind(&BOSHConnection::handleConnectionConnectFinished, shared_from_this(), _1));
+ if(error) {
+ onConnectFinished(true);
+ return;
+ }
+
+ if(sid_.size() == 0) {
+ // Session Creation Request
+ std::stringstream content;
+ std::stringstream header;
+
+ content << "<body content='text/xml; charset=utf-8'"
+ << " from='ephraim@0x10.de'"
+ << " hold='1'"
+ << " to='0x10.de'"
+ << " ver='1.6'"
+ << " wait='60'"
+ << " ack='1'"
+ << " xml:lang='en'"
+ << " xmlns='http://jabber.org/protocol/httpbind' />\r\n";
+
+ header << "POST /http-bind HTTP/1.1\r\n"
+ << "Host: 0x10.de:5280\r\n"
+ << "Accept-Encoding: deflate\r\n"
+ << "Content-Type: text/xml; charset=utf-8\r\n"
+ << "Content-Length: " << content.str().size() << "\r\n\r\n"
+ << content.str();
+
+ SWIFT_LOG(debug) << "request: ";
+ newConnection_->write(createSafeByteArray(header.str()));
+ }
+ }
+
+ void BOSHConnection::handleDataRead(const SafeByteArray& data) {
+ std::string response = safeByteArrayToString(data);
+ assert(response.find("\r\n\r\n") != std::string::npos);
+
+ SWIFT_LOG(debug) << "response: " << response.substr(response.find("\r\n\r\n") + 4) << std::endl;
+
+ BOSHParser parser;
+ if(parser.parse(response.substr(response.find("\r\n\r\n") + 4))) {
+ sid_ = parser.getAttribute("sid");
+ onConnectFinished(false);
+ int bodyStartElementLength = 0;
+ bool inQuote = false;
+ for(size_t i= 0; i < response.size(); i++) {
+ if(response.c_str()[i] == '\'' || response.c_str()[i] == '"') {
+ inQuote = !inQuote;
+ }
+ else if(!inQuote && response.c_str()[i] == '>') {
+ bodyStartElementLength = i + 1;
+ break;
+ }
+ }
+ SafeByteArray payload = createSafeByteArray(response.substr(bodyStartElementLength, response.size() - bodyStartElementLength - 7));
+ SWIFT_LOG(debug) << "payload: " << safeByteArrayToString(payload) << std::endl;
+ onDataRead(payload);
+ }
+ }
+
+ void BOSHConnection::handleDisconnected(const boost::optional<Error>& error) {
+ onDisconnected(error);
+ }
+
+ HostAddressPort BOSHConnection::getLocalAddress() const {
+ return newConnection_->getLocalAddress();
+ }
+}
diff --git a/Swiften/Network/BOSHConnection.h b/Swiften/Network/BOSHConnection.h
new file mode 100644
index 0000000..0da92ba
--- /dev/null
+++ b/Swiften/Network/BOSHConnection.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/enable_shared_from_this.hpp>
+
+#include <Swiften/Network/Connection.h>
+#include <Swiften/Network/HostAddressPort.h>
+#include <Swiften/Base/String.h>
+
+namespace boost {
+ class thread;
+ namespace system {
+ class error_code;
+ }
+}
+
+namespace Swift {
+ class ConnectionFactory;
+
+ class BOSHConnection : public Connection, public boost::enable_shared_from_this<BOSHConnection> {
+ public:
+ typedef boost::shared_ptr<BOSHConnection> ref;
+ static ref create(ConnectionFactory* connectionFactory) {
+ return ref(new BOSHConnection(connectionFactory));
+ }
+ virtual ~BOSHConnection();
+ virtual void listen();
+ virtual void connect(const HostAddressPort& address);
+ virtual void disconnect();
+ virtual void write(const SafeByteArray& data);
+ virtual HostAddressPort getLocalAddress() const;
+
+ private:
+ BOSHConnection(ConnectionFactory* connectionFactory);
+
+ void handleConnectionConnectFinished(bool error);
+ void handleDataRead(const SafeByteArray& data);
+ void handleDisconnected(const boost::optional<Error>& error);
+
+ bool reopenAfterAction;
+ ConnectionFactory* connectionFactory_;
+ HostAddressPort server_;
+ boost::shared_ptr<Connection> newConnection_;
+ boost::shared_ptr<Connection> currentConnection_;
+ std::string sid_;
+ };
+}
diff --git a/Swiften/Network/BOSHConnectionFactory.cpp b/Swiften/Network/BOSHConnectionFactory.cpp
new file mode 100644
index 0000000..4c49cae
--- /dev/null
+++ b/Swiften/Network/BOSHConnectionFactory.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "BOSHConnectionFactory.h"
+#include <Swiften/Network/BOSHConnection.h>
+
+namespace Swift {
+
+BOSHConnectionFactory::BOSHConnectionFactory(ConnectionFactory* connectionFactory) {
+ connectionFactory_ = connectionFactory;
+
+}
+
+boost::shared_ptr<Connection> BOSHConnectionFactory::createConnection() {
+ return BOSHConnection::create(connectionFactory_);
+}
+
+}
diff --git a/Swiften/Network/BOSHConnectionFactory.h b/Swiften/Network/BOSHConnectionFactory.h
new file mode 100644
index 0000000..7431cf4
--- /dev/null
+++ b/Swiften/Network/BOSHConnectionFactory.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Network/ConnectionFactory.h>
+#include <Swiften/Network/HostAddressPort.h>
+
+namespace Swift {
+ class BOSHConnectionFactory : public ConnectionFactory {
+ public:
+ BOSHConnectionFactory(ConnectionFactory* connectionFactory);
+
+ virtual boost::shared_ptr<Connection> createConnection();
+
+ private:
+ ConnectionFactory* connectionFactory_;
+ };
+}
diff --git a/Swiften/Network/SConscript b/Swiften/Network/SConscript
index 49df18f..399cec8 100644
--- a/Swiften/Network/SConscript
+++ b/Swiften/Network/SConscript
@@ -15,6 +15,8 @@ sourceList = [
"BoostConnectionServer.cpp",
"BoostConnectionServerFactory.cpp",
"BoostIOServiceThread.cpp",
+ "BOSHConnection.cpp",
+ "BOSHConnectionFactory.cpp"
"ConnectionFactory.cpp",
"ConnectionServer.cpp",
"ConnectionServerFactory.cpp",
diff --git a/Swiften/Parser/BOSHParser.cpp b/Swiften/Parser/BOSHParser.cpp
new file mode 100644
index 0000000..9fb218a
--- /dev/null
+++ b/Swiften/Parser/BOSHParser.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <cassert>
+
+#include <Swiften/Parser/BOSHParser.h>
+#include <Swiften/Parser/XMLParser.h>
+#include <Swiften/Parser/PlatformXMLParserFactory.h>
+
+namespace Swift {
+
+BOSHParser::BOSHParser() :
+ xmlParser_(0),
+ level_(-1),
+ parseErrorOccurred_(false)
+{
+ xmlParser_ = PlatformXMLParserFactory().createXMLParser(this);
+}
+
+BOSHParser::~BOSHParser() {
+ delete xmlParser_;
+}
+
+bool BOSHParser::parse(const std::string& data) {
+ bool xmlParseResult = xmlParser_->parse(data);
+ return xmlParseResult && !parseErrorOccurred_;
+}
+
+void BOSHParser::handleStartElement(const std::string& /*element*/, const std::string& /*ns*/, const AttributeMap& attributes) {
+ if (!parseErrorOccurred_) {
+ if (level_ == BoshTopLevel) {
+ boshBodyAttributes_ = attributes;
+ }
+ }
+ ++level_;
+}
+
+void BOSHParser::handleEndElement(const std::string& /*element*/, const std::string& /*ns*/) {
+ assert(level_ > BoshTopLevel);
+ --level_;
+ if (!parseErrorOccurred_) {
+
+ }
+}
+
+void BOSHParser::handleCharacterData(const std::string& /*data*/) {
+ if (!parseErrorOccurred_) {
+
+ }
+}
+
+}
diff --git a/Swiften/Parser/BOSHParser.h b/Swiften/Parser/BOSHParser.h
new file mode 100644
index 0000000..69b3d13
--- /dev/null
+++ b/Swiften/Parser/BOSHParser.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/noncopyable.hpp>
+
+#include <Swiften/Parser/XMLParserClient.h>
+#include <Swiften/Parser/AttributeMap.h>
+
+namespace Swift {
+ class XMLParser;
+
+ class BOSHParser : public XMLParserClient, boost::noncopyable {
+ public:
+ BOSHParser();
+ ~BOSHParser();
+
+ bool parse(const std::string&);
+
+ std::string getAttribute(const std::string& attribute, const std::string& ns = "") const {
+ return boshBodyAttributes_.getAttribute(attribute, ns);
+ }
+ private:
+ virtual void handleStartElement(
+ const std::string& element,
+ const std::string& ns,
+ const AttributeMap& attributes);
+ virtual void handleEndElement(const std::string& element, const std::string& ns);
+ virtual void handleCharacterData(const std::string& data);
+
+ private:
+ AttributeMap boshBodyAttributes_;
+ XMLParser* xmlParser_;
+ enum Level {
+ BoshTopLevel = -1,
+ TopLevel = 0,
+ StreamLevel = 1,
+ ElementLevel = 2
+ };
+ int level_;
+ bool parseErrorOccurred_;
+ };
+}
diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript
index e4c2778..dd19238 100644
--- a/Swiften/Parser/SConscript
+++ b/Swiften/Parser/SConscript
@@ -11,6 +11,7 @@ sources = [
"AuthChallengeParser.cpp",
"AuthSuccessParser.cpp",
"AuthResponseParser.cpp",
+ "BOSHParser.cpp",
"CompressParser.cpp",
"ElementParser.cpp",
"IQParser.cpp",