diff options
| author | Thilo Cestonaro <thilo@cestona.ro> | 2011-09-28 22:03:14 (GMT) | 
|---|---|---|
| committer | Kevin Smith <git@kismith.co.uk> | 2011-12-13 08:17:58 (GMT) | 
| commit | fd17fe0d239f97cedebe4ceffa234155bd299b68 (patch) | |
| tree | 010ae5155e6e807b548861304657a25699487e1f | |
| parent | 7d19f0d81371d86d530d0e7083a04db914ce6745 (diff) | |
| download | swift-fd17fe0d239f97cedebe4ceffa234155bd299b68.zip swift-fd17fe0d239f97cedebe4ceffa234155bd299b68.tar.bz2 | |
BOSH implementation started
License: This patch is BSD-licensed, see http://www.opensource.org/licenses/bsd-license.php
| -rw-r--r-- | Swiften/Client/CoreClient.cpp | 4 | ||||
| -rw-r--r-- | Swiften/Network/BOSHConnection.cpp | 132 | ||||
| -rw-r--r-- | Swiften/Network/BOSHConnection.h | 52 | ||||
| -rw-r--r-- | Swiften/Network/BOSHConnectionFactory.cpp | 21 | ||||
| -rw-r--r-- | Swiften/Network/BOSHConnectionFactory.h | 22 | ||||
| -rw-r--r-- | Swiften/Network/SConscript | 2 | ||||
| -rw-r--r-- | Swiften/Parser/BOSHParser.cpp | 55 | ||||
| -rw-r--r-- | Swiften/Parser/BOSHParser.h | 47 | ||||
| -rw-r--r-- | Swiften/Parser/SConscript | 1 | 
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", | 
 Swift
 Swift