diff options
Diffstat (limited to 'Swiften/Network')
82 files changed, 1950 insertions, 232 deletions
| diff --git a/Swiften/Network/BoostConnection.cpp b/Swiften/Network/BoostConnection.cpp index f7ff8c4..ac3b444 100644 --- a/Swiften/Network/BoostConnection.cpp +++ b/Swiften/Network/BoostConnection.cpp @@ -4,18 +4,23 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/Network/BoostConnection.h" +#include <Swiften/Network/BoostConnection.h>  #include <iostream> +#include <string> +#include <algorithm>  #include <boost/bind.hpp>  #include <boost/thread.hpp> +#include <boost/asio/placeholders.hpp> +#include <boost/asio/write.hpp>  #include <Swiften/Base/Log.h> -#include "Swiften/EventLoop/EventLoop.h" -#include <string> -#include "Swiften/Base/ByteArray.h" -#include "Swiften/Network/HostAddressPort.h" -#include "Swiften/Base/sleep.h" +#include <Swiften/Base/Algorithm.h> +#include <Swiften/EventLoop/EventLoop.h> +#include <Swiften/Base/ByteArray.h> +#include <Swiften/Network/HostAddressPort.h> +#include <Swiften/Base/sleep.h> +#include <Swiften/Base/SafeAllocator.h>  namespace Swift { @@ -26,8 +31,8 @@ static const size_t BUFFER_SIZE = 4096;  // A reference-counted non-modifiable buffer class.  class SharedBuffer {  	public: -		SharedBuffer(const ByteArray& data) :  -				data_(new std::vector<char>(data.begin(), data.end())), +		SharedBuffer(const SafeByteArray& data) : +				data_(new std::vector<char, SafeAllocator<char> >(data.begin(), data.end())),  				buffer_(boost::asio::buffer(*data_)) {  		} @@ -38,7 +43,7 @@ class SharedBuffer {  		const boost::asio::const_buffer* end() const { return &buffer_ + 1; }  	private: -		boost::shared_ptr< std::vector<char> > data_; +		boost::shared_ptr< std::vector<char, SafeAllocator<char> > > data_;  		boost::asio::const_buffer buffer_;  }; @@ -75,18 +80,18 @@ void BoostConnection::disconnect() {  	socket_.close();  } -void BoostConnection::write(const ByteArray& data) { +void BoostConnection::write(const SafeByteArray& data) {  	boost::lock_guard<boost::mutex> lock(writeMutex_);  	if (!writing_) {  		writing_ = true;  		doWrite(data);  	}  	else { -		writeQueue_ += data; +		append(writeQueue_, data);  	}  } -void BoostConnection::doWrite(const ByteArray& data) { +void BoostConnection::doWrite(const SafeByteArray& data) {  	boost::asio::async_write(socket_, SharedBuffer(data),  			boost::bind(&BoostConnection::handleDataWritten, shared_from_this(), boost::asio::placeholders::error));  } @@ -111,7 +116,8 @@ void BoostConnection::doRead() {  void BoostConnection::handleSocketRead(const boost::system::error_code& error, size_t bytesTransferred) {  	SWIFT_LOG(debug) << "Socket read " << error << std::endl;  	if (!error) { -		eventLoop->postEvent(boost::bind(boost::ref(onDataRead), ByteArray(&readBuffer_[0], bytesTransferred)), shared_from_this()); +		eventLoop->postEvent(boost::bind(boost::ref(onDataRead), createSafeByteArray(&readBuffer_[0], bytesTransferred)), shared_from_this()); +		std::fill(readBuffer_.begin(), readBuffer_.end(), 0);  		doRead();  	}  	else if (/*error == boost::asio::error::eof ||*/ error == boost::asio::error::operation_aborted) { @@ -135,7 +141,7 @@ void BoostConnection::handleDataWritten(const boost::system::error_code& error)  	}  	{  		boost::lock_guard<boost::mutex> lock(writeMutex_); -		if (writeQueue_.isEmpty()) { +		if (writeQueue_.empty()) {  			writing_ = false;  		}  		else { diff --git a/Swiften/Network/BoostConnection.h b/Swiften/Network/BoostConnection.h index 506eedf..259fcec 100644 --- a/Swiften/Network/BoostConnection.h +++ b/Swiften/Network/BoostConnection.h @@ -6,12 +6,14 @@  #pragma once -#include <boost/asio.hpp> +#include <boost/asio/io_service.hpp> +#include <boost/asio/ip/tcp.hpp>  #include <boost/enable_shared_from_this.hpp>  #include <boost/thread/mutex.hpp> -#include "Swiften/Network/Connection.h" -#include "Swiften/EventLoop/EventOwner.h" +#include <Swiften/Network/Connection.h> +#include <Swiften/EventLoop/EventOwner.h> +#include <Swiften/Base/SafeByteArray.h>  namespace boost {  	class thread; @@ -36,7 +38,7 @@ namespace Swift {  			virtual void listen();  			virtual void connect(const HostAddressPort& address);  			virtual void disconnect(); -			virtual void write(const ByteArray& data); +			virtual void write(const SafeByteArray& data);  			boost::asio::ip::tcp::socket& getSocket() {  				return socket_; @@ -51,15 +53,15 @@ namespace Swift {  			void handleSocketRead(const boost::system::error_code& error, size_t bytesTransferred);  			void handleDataWritten(const boost::system::error_code& error);  			void doRead(); -			void doWrite(const ByteArray& data); +			void doWrite(const SafeByteArray& data);  		private:  			EventLoop* eventLoop;  			boost::shared_ptr<boost::asio::io_service> ioService;  			boost::asio::ip::tcp::socket socket_; -			std::vector<char> readBuffer_; +			SafeByteArray readBuffer_;  			boost::mutex writeMutex_;  			bool writing_; -			ByteArray writeQueue_; +			SafeByteArray writeQueue_;  	};  } diff --git a/Swiften/Network/BoostConnectionFactory.cpp b/Swiften/Network/BoostConnectionFactory.cpp index 743bb61..d5f9fad 100644 --- a/Swiften/Network/BoostConnectionFactory.cpp +++ b/Swiften/Network/BoostConnectionFactory.cpp @@ -4,8 +4,8 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/Network/BoostConnectionFactory.h" -#include "Swiften/Network/BoostConnection.h" +#include <Swiften/Network/BoostConnectionFactory.h> +#include <Swiften/Network/BoostConnection.h>  namespace Swift { diff --git a/Swiften/Network/BoostConnectionFactory.h b/Swiften/Network/BoostConnectionFactory.h index ea9d656..c0a105b 100644 --- a/Swiften/Network/BoostConnectionFactory.h +++ b/Swiften/Network/BoostConnectionFactory.h @@ -6,10 +6,10 @@  #pragma once -#include <boost/asio.hpp> +#include <boost/asio/io_service.hpp> -#include "Swiften/Network/ConnectionFactory.h" -#include "Swiften/Network/BoostConnection.h" +#include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Network/BoostConnection.h>  namespace Swift {  	class BoostConnection; diff --git a/Swiften/Network/BoostConnectionServer.cpp b/Swiften/Network/BoostConnectionServer.cpp index 27a1008..eccffc6 100644 --- a/Swiften/Network/BoostConnectionServer.cpp +++ b/Swiften/Network/BoostConnectionServer.cpp @@ -4,12 +4,13 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/Network/BoostConnectionServer.h" +#include <Swiften/Network/BoostConnectionServer.h>  #include <boost/bind.hpp>  #include <boost/system/system_error.hpp> +#include <boost/asio/placeholders.hpp> -#include "Swiften/EventLoop/EventLoop.h" +#include <Swiften/EventLoop/EventLoop.h>  namespace Swift { diff --git a/Swiften/Network/BoostConnectionServer.h b/Swiften/Network/BoostConnectionServer.h index aba9e3e..56dc8bd 100644 --- a/Swiften/Network/BoostConnectionServer.h +++ b/Swiften/Network/BoostConnectionServer.h @@ -7,13 +7,14 @@  #pragma once  #include <boost/shared_ptr.hpp> +#include <boost/asio/io_service.hpp> +#include <boost/asio/ip/tcp.hpp>  #include <boost/enable_shared_from_this.hpp> -#include <boost/asio.hpp> -#include "Swiften/Base/boost_bsignals.h" +#include <Swiften/Base/boost_bsignals.h> -#include "Swiften/Network/BoostConnection.h" -#include "Swiften/Network/ConnectionServer.h" -#include "Swiften/EventLoop/EventOwner.h" +#include <Swiften/Network/BoostConnection.h> +#include <Swiften/Network/ConnectionServer.h> +#include <Swiften/EventLoop/EventOwner.h>  namespace Swift {  	class BoostConnectionServer : public ConnectionServer, public EventOwner, public boost::enable_shared_from_this<BoostConnectionServer> { diff --git a/Swiften/Network/BoostIOServiceThread.cpp b/Swiften/Network/BoostIOServiceThread.cpp index 031e7b5..c98a653 100644 --- a/Swiften/Network/BoostIOServiceThread.cpp +++ b/Swiften/Network/BoostIOServiceThread.cpp @@ -4,7 +4,7 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/Network/BoostIOServiceThread.h" +#include <Swiften/Network/BoostIOServiceThread.h>  #include <boost/smart_ptr/make_shared.hpp> diff --git a/Swiften/Network/BoostIOServiceThread.h b/Swiften/Network/BoostIOServiceThread.h index 1f72049..00fb397 100644 --- a/Swiften/Network/BoostIOServiceThread.h +++ b/Swiften/Network/BoostIOServiceThread.h @@ -6,8 +6,8 @@  #pragma once -#include <boost/asio.hpp> -#include <boost/thread.hpp> +#include <boost/asio/io_service.hpp> +#include <boost/thread/thread.hpp>  #include <boost/shared_ptr.hpp>  namespace Swift { @@ -16,7 +16,7 @@ namespace Swift {  			BoostIOServiceThread();  			~BoostIOServiceThread(); -			boost::shared_ptr<boost::asio::io_service> getIOService() { +			boost::shared_ptr<boost::asio::io_service> getIOService() const {  				return ioService_;  			} diff --git a/Swiften/Network/BoostNetworkFactories.cpp b/Swiften/Network/BoostNetworkFactories.cpp index 1d9479a..cc80197 100644 --- a/Swiften/Network/BoostNetworkFactories.cpp +++ b/Swiften/Network/BoostNetworkFactories.cpp @@ -4,9 +4,9 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/Network/BoostNetworkFactories.h" -#include "Swiften/Network/BoostTimerFactory.h" -#include "Swiften/Network/BoostConnectionFactory.h" +#include <Swiften/Network/BoostNetworkFactories.h> +#include <Swiften/Network/BoostTimerFactory.h> +#include <Swiften/Network/BoostConnectionFactory.h>  #include <Swiften/Network/PlatformDomainNameResolver.h>  #include <Swiften/Network/BoostConnectionServerFactory.h> diff --git a/Swiften/Network/BoostNetworkFactories.h b/Swiften/Network/BoostNetworkFactories.h index e4d3128..96bcc6c 100644 --- a/Swiften/Network/BoostNetworkFactories.h +++ b/Swiften/Network/BoostNetworkFactories.h @@ -6,8 +6,8 @@  #pragma once -#include "Swiften/Network/NetworkFactories.h" -#include "Swiften/Network/BoostIOServiceThread.h" +#include <Swiften/Network/NetworkFactories.h> +#include <Swiften/Network/BoostIOServiceThread.h>  namespace Swift {  	class EventLoop; diff --git a/Swiften/Network/BoostTimer.cpp b/Swiften/Network/BoostTimer.cpp index 12d06c1..bf042d6 100644 --- a/Swiften/Network/BoostTimer.cpp +++ b/Swiften/Network/BoostTimer.cpp @@ -4,12 +4,13 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/Network/BoostTimer.h" +#include <Swiften/Network/BoostTimer.h>  #include <boost/date_time/posix_time/posix_time.hpp>  #include <boost/asio.hpp> +#include <boost/bind.hpp> -#include "Swiften/EventLoop/EventLoop.h" +#include <Swiften/EventLoop/EventLoop.h>  namespace Swift { diff --git a/Swiften/Network/BoostTimer.h b/Swiften/Network/BoostTimer.h index 1139dcf..bfe631b 100644 --- a/Swiften/Network/BoostTimer.h +++ b/Swiften/Network/BoostTimer.h @@ -6,12 +6,12 @@  #pragma once -#include <boost/asio.hpp> -#include <boost/thread.hpp> +#include <boost/asio/io_service.hpp> +#include <boost/asio/deadline_timer.hpp>  #include <boost/enable_shared_from_this.hpp> -#include "Swiften/EventLoop/EventOwner.h" -#include "Swiften/Network/Timer.h" +#include <Swiften/EventLoop/EventOwner.h> +#include <Swiften/Network/Timer.h>  namespace Swift {  	class EventLoop; diff --git a/Swiften/Network/BoostTimerFactory.cpp b/Swiften/Network/BoostTimerFactory.cpp index b8e628f..c0bdb56 100644 --- a/Swiften/Network/BoostTimerFactory.cpp +++ b/Swiften/Network/BoostTimerFactory.cpp @@ -4,8 +4,8 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/Network/BoostTimerFactory.h" -#include "Swiften/Network/BoostTimer.h" +#include <Swiften/Network/BoostTimerFactory.h> +#include <Swiften/Network/BoostTimer.h>  namespace Swift { diff --git a/Swiften/Network/BoostTimerFactory.h b/Swiften/Network/BoostTimerFactory.h index c0e9ef7..6093db0 100644 --- a/Swiften/Network/BoostTimerFactory.h +++ b/Swiften/Network/BoostTimerFactory.h @@ -6,10 +6,10 @@  #pragma once -#include <boost/asio.hpp> +#include <boost/asio/io_service.hpp> -#include "Swiften/Network/TimerFactory.h" -#include "Swiften/Network/BoostTimer.h" +#include <Swiften/Network/TimerFactory.h> +#include <Swiften/Network/BoostTimer.h>  namespace Swift {  	class BoostTimer; diff --git a/Swiften/Network/CAresDomainNameResolver.cpp b/Swiften/Network/CAresDomainNameResolver.cpp index dd49139..da0f49e 100644 --- a/Swiften/Network/CAresDomainNameResolver.cpp +++ b/Swiften/Network/CAresDomainNameResolver.cpp @@ -7,8 +7,8 @@  // TODO: Check the second param of postEvent. We sometimes omit it. Same   // goes for the PlatformDomainNameResolver. -#include "Swiften/Network/CAresDomainNameResolver.h" -#include "Swiften/Base/Platform.h" +#include <Swiften/Network/CAresDomainNameResolver.h> +#include <Swiften/Base/Platform.h>  #ifndef SWIFTEN_PLATFORM_WINDOWS  #include <netdb.h> @@ -16,11 +16,11 @@  #endif  #include <algorithm> -#include "Swiften/Network/DomainNameServiceQuery.h" -#include "Swiften/Network/DomainNameAddressQuery.h" -#include "Swiften/Base/ByteArray.h" -#include "Swiften/EventLoop/EventLoop.h" -#include "Swiften/Base/foreach.h" +#include <Swiften/Network/DomainNameServiceQuery.h> +#include <Swiften/Network/DomainNameAddressQuery.h> +#include <Swiften/Base/ByteArray.h> +#include <Swiften/EventLoop/EventLoop.h> +#include <Swiften/Base/foreach.h>  namespace Swift { diff --git a/Swiften/Network/CAresDomainNameResolver.h b/Swiften/Network/CAresDomainNameResolver.h index a630b61..d0ff82c 100644 --- a/Swiften/Network/CAresDomainNameResolver.h +++ b/Swiften/Network/CAresDomainNameResolver.h @@ -7,11 +7,11 @@  #pragma once  #include <ares.h> -#include <boost/thread.hpp> +#include <boost/thread/thread.hpp>  #include <boost/thread/mutex.hpp>  #include <list> -#include "Swiften/Network/DomainNameResolver.h" +#include <Swiften/Network/DomainNameResolver.h>  namespace Swift {  	class CAresQuery; diff --git a/Swiften/Network/ChainedConnector.cpp b/Swiften/Network/ChainedConnector.cpp new file mode 100644 index 0000000..1a38e53 --- /dev/null +++ b/Swiften/Network/ChainedConnector.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Network/ChainedConnector.h> + +#include <boost/bind.hpp> +#include <typeinfo> + +#include <Swiften/Base/Log.h> +#include <Swiften/Base/foreach.h> +#include <Swiften/Network/Connector.h> +#include <Swiften/Network/ConnectionFactory.h> + +using namespace Swift; + +ChainedConnector::ChainedConnector( +		const std::string& hostname,  +		DomainNameResolver* resolver,  +		const std::vector<ConnectionFactory*>& connectionFactories,  +		TimerFactory* timerFactory) :  +			hostname(hostname),  +			resolver(resolver),  +			connectionFactories(connectionFactories),  +			timerFactory(timerFactory),  +			timeoutMilliseconds(0) { +} + +void ChainedConnector::setTimeoutMilliseconds(int milliseconds) { +	timeoutMilliseconds = milliseconds; +} + +void ChainedConnector::start() { +	SWIFT_LOG(debug) << "Starting queued connector for " << hostname << std::endl; + +	connectionFactoryQueue = std::deque<ConnectionFactory*>(connectionFactories.begin(), connectionFactories.end()); +	tryNextConnectionFactory(); +} + +void ChainedConnector::stop() { +	if (currentConnector) { +		currentConnector->onConnectFinished.disconnect(boost::bind(&ChainedConnector::handleConnectorFinished, this, _1)); +		currentConnector->stop(); +		currentConnector.reset(); +	} +	finish(boost::shared_ptr<Connection>()); +} + +void ChainedConnector::tryNextConnectionFactory() { +	assert(!currentConnector); +	if (connectionFactoryQueue.empty()) { +		SWIFT_LOG(debug) << "No more connection factories" << std::endl; +		finish(boost::shared_ptr<Connection>()); +	} +	else { +		ConnectionFactory* connectionFactory = connectionFactoryQueue.front(); +		SWIFT_LOG(debug) << "Trying next connection factory: " << typeid(*connectionFactory).name() << std::endl; +		connectionFactoryQueue.pop_front(); +		currentConnector = Connector::create(hostname, resolver, connectionFactory, timerFactory); +		currentConnector->setTimeoutMilliseconds(timeoutMilliseconds); +		currentConnector->onConnectFinished.connect(boost::bind(&ChainedConnector::handleConnectorFinished, this, _1)); +		currentConnector->start(); +	} +} + +void ChainedConnector::handleConnectorFinished(boost::shared_ptr<Connection> connection) { +	SWIFT_LOG(debug) << "Connector finished" << std::endl; +	currentConnector->onConnectFinished.disconnect(boost::bind(&ChainedConnector::handleConnectorFinished, this, _1)); +	currentConnector.reset(); +	if (connection) { +		finish(connection); +	} +	else { +		tryNextConnectionFactory(); +	} +} + +void ChainedConnector::finish(boost::shared_ptr<Connection> connection) { +	onConnectFinished(connection); +} diff --git a/Swiften/Network/ChainedConnector.h b/Swiften/Network/ChainedConnector.h new file mode 100644 index 0000000..15b17f3 --- /dev/null +++ b/Swiften/Network/ChainedConnector.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <string> +#include <vector> +#include <deque> +#include <boost/shared_ptr.hpp> + +#include <Swiften/Base/boost_bsignals.h> + +namespace Swift { +	class Connection; +	class Connector; +	class ConnectionFactory; +	class TimerFactory; +	class DomainNameResolver; + +	class ChainedConnector { +		public: +			ChainedConnector(const std::string& hostname, DomainNameResolver*, const std::vector<ConnectionFactory*>&, TimerFactory*); + +			void setTimeoutMilliseconds(int milliseconds); +			void start(); +			void stop(); + +			boost::signal<void (boost::shared_ptr<Connection>)> onConnectFinished; + +		private: +			void finish(boost::shared_ptr<Connection> connection); +			void tryNextConnectionFactory(); +			void handleConnectorFinished(boost::shared_ptr<Connection>); + +		private: +			std::string hostname; +			DomainNameResolver* resolver; +			std::vector<ConnectionFactory*> connectionFactories; +			TimerFactory* timerFactory; +			int timeoutMilliseconds; +			std::deque<ConnectionFactory*> connectionFactoryQueue; +			boost::shared_ptr<Connector> currentConnector; +	}; +}; diff --git a/Swiften/Network/Connection.cpp b/Swiften/Network/Connection.cpp new file mode 100644 index 0000000..9bb29e1 --- /dev/null +++ b/Swiften/Network/Connection.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Network/Connection.h> + +using namespace Swift; + +Connection::Connection() { +} + +Connection::~Connection() { +} diff --git a/Swiften/Network/Connection.h b/Swiften/Network/Connection.h index 529dd82..1b9977f 100644 --- a/Swiften/Network/Connection.h +++ b/Swiften/Network/Connection.h @@ -7,13 +7,13 @@  #pragma once  #include <boost/shared_ptr.hpp> +#include <Swiften/Base/boost_bsignals.h> -#include "Swiften/Base/boost_bsignals.h" -#include "Swiften/Base/ByteArray.h" -#include <string> -#include "Swiften/Network/HostAddressPort.h" +#include <Swiften/Base/SafeByteArray.h>  namespace Swift { +	class HostAddressPort; +  	class Connection {  		public:  			typedef boost::shared_ptr<Connection> ref; @@ -23,20 +23,20 @@ namespace Swift {  				WriteError  			}; -			Connection() {} -			virtual ~Connection() {} +			Connection(); +			virtual ~Connection();  			virtual void listen() = 0;  			virtual void connect(const HostAddressPort& address) = 0;  			virtual void disconnect() = 0; -			virtual void write(const ByteArray& data) = 0; +			virtual void write(const SafeByteArray& data) = 0;  			virtual HostAddressPort getLocalAddress() const = 0;  		public:  			boost::signal<void (bool /* error */)> onConnectFinished;  			boost::signal<void (const boost::optional<Error>&)> onDisconnected; -			boost::signal<void (const ByteArray&)> onDataRead; +			boost::signal<void (const SafeByteArray&)> onDataRead;  			boost::signal<void ()> onDataWritten;  	};  } diff --git a/Swiften/Network/ConnectionFactory.cpp b/Swiften/Network/ConnectionFactory.cpp index dc322a4..2e38b21 100644 --- a/Swiften/Network/ConnectionFactory.cpp +++ b/Swiften/Network/ConnectionFactory.cpp @@ -4,7 +4,7 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/Network/ConnectionFactory.h" +#include <Swiften/Network/ConnectionFactory.h>  namespace Swift { diff --git a/Swiften/Network/ConnectionServer.cpp b/Swiften/Network/ConnectionServer.cpp index 9631efc..78312e7 100644 --- a/Swiften/Network/ConnectionServer.cpp +++ b/Swiften/Network/ConnectionServer.cpp @@ -4,7 +4,7 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/Network/ConnectionServer.h" +#include <Swiften/Network/ConnectionServer.h>  namespace Swift { diff --git a/Swiften/Network/ConnectionServer.h b/Swiften/Network/ConnectionServer.h index b90f73d..00703a4 100644 --- a/Swiften/Network/ConnectionServer.h +++ b/Swiften/Network/ConnectionServer.h @@ -7,10 +7,10 @@  #pragma once  #include <boost/shared_ptr.hpp> -#include "Swiften/Base/boost_bsignals.h" +#include <Swiften/Base/boost_bsignals.h> -#include "Swiften/Network/Connection.h" -#include "Swiften/Network/HostAddressPort.h" +#include <Swiften/Network/Connection.h> +#include <Swiften/Network/HostAddressPort.h>  namespace Swift {  	class ConnectionServer { diff --git a/Swiften/Network/Connector.cpp b/Swiften/Network/Connector.cpp index 868bd50..8f35aba 100644 --- a/Swiften/Network/Connector.cpp +++ b/Swiften/Network/Connector.cpp @@ -4,15 +4,15 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/Network/Connector.h" +#include <Swiften/Network/Connector.h>  #include <boost/bind.hpp>  #include <iostream> -#include "Swiften/Network/ConnectionFactory.h" -#include "Swiften/Network/DomainNameResolver.h" -#include "Swiften/Network/DomainNameAddressQuery.h" -#include "Swiften/Network/TimerFactory.h" +#include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Network/DomainNameResolver.h> +#include <Swiften/Network/DomainNameAddressQuery.h> +#include <Swiften/Network/TimerFactory.h>  #include <Swiften/Base/Log.h>  namespace Swift { diff --git a/Swiften/Network/Connector.h b/Swiften/Network/Connector.h index b3e7d83..8336299 100644 --- a/Swiften/Network/Connector.h +++ b/Swiften/Network/Connector.h @@ -7,15 +7,15 @@  #pragma once  #include <deque> -#include "Swiften/Base/boost_bsignals.h" +#include <Swiften/Base/boost_bsignals.h>  #include <boost/shared_ptr.hpp> -#include "Swiften/Network/DomainNameServiceQuery.h" -#include "Swiften/Network/Connection.h" -#include "Swiften/Network/Timer.h" -#include "Swiften/Network/HostAddressPort.h" +#include <Swiften/Network/DomainNameServiceQuery.h> +#include <Swiften/Network/Connection.h> +#include <Swiften/Network/Timer.h> +#include <Swiften/Network/HostAddressPort.h>  #include <string> -#include "Swiften/Network/DomainNameResolveError.h" +#include <Swiften/Network/DomainNameResolveError.h>  namespace Swift {  	class DomainNameAddressQuery; @@ -28,7 +28,7 @@ namespace Swift {  			typedef boost::shared_ptr<Connector> ref;  			static Connector::ref create(const std::string& hostname, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory) { -				return Connector::ref(new Connector(hostname, resolver, connectionFactory, timerFactory)); +				return ref(new Connector(hostname, resolver, connectionFactory, timerFactory));  			}  			void setTimeoutMilliseconds(int milliseconds); diff --git a/Swiften/Network/DomainNameAddressQuery.cpp b/Swiften/Network/DomainNameAddressQuery.cpp index fd36964..856f301 100644 --- a/Swiften/Network/DomainNameAddressQuery.cpp +++ b/Swiften/Network/DomainNameAddressQuery.cpp @@ -4,7 +4,7 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/Network/DomainNameAddressQuery.h" +#include <Swiften/Network/DomainNameAddressQuery.h>  namespace Swift { diff --git a/Swiften/Network/DomainNameAddressQuery.h b/Swiften/Network/DomainNameAddressQuery.h index 5bac350..c8ed981 100644 --- a/Swiften/Network/DomainNameAddressQuery.h +++ b/Swiften/Network/DomainNameAddressQuery.h @@ -6,12 +6,12 @@  #pragma once -#include "Swiften/Base/boost_bsignals.h" +#include <Swiften/Base/boost_bsignals.h>  #include <boost/optional.hpp>  #include <boost/shared_ptr.hpp> -#include "Swiften/Network/DomainNameResolveError.h" -#include "Swiften/Network/HostAddress.h" +#include <Swiften/Network/DomainNameResolveError.h> +#include <Swiften/Network/HostAddress.h>  namespace Swift {  	class DomainNameAddressQuery { diff --git a/Swiften/Network/DomainNameResolveError.h b/Swiften/Network/DomainNameResolveError.h index 632ba77..aa4441d 100644 --- a/Swiften/Network/DomainNameResolveError.h +++ b/Swiften/Network/DomainNameResolveError.h @@ -6,7 +6,7 @@  #pragma once -#include "Swiften/Base/Error.h" +#include <Swiften/Base/Error.h>  namespace Swift {  	class DomainNameResolveError : public Error { diff --git a/Swiften/Network/DomainNameResolver.cpp b/Swiften/Network/DomainNameResolver.cpp index 96c5165..56a9d72 100644 --- a/Swiften/Network/DomainNameResolver.cpp +++ b/Swiften/Network/DomainNameResolver.cpp @@ -4,7 +4,7 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/Network/DomainNameResolver.h" +#include <Swiften/Network/DomainNameResolver.h>  namespace Swift { diff --git a/Swiften/Network/DomainNameServiceQuery.cpp b/Swiften/Network/DomainNameServiceQuery.cpp index 423330c..5713b63 100644 --- a/Swiften/Network/DomainNameServiceQuery.cpp +++ b/Swiften/Network/DomainNameServiceQuery.cpp @@ -4,7 +4,7 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/Network/DomainNameServiceQuery.h" +#include <Swiften/Network/DomainNameServiceQuery.h>  namespace Swift { diff --git a/Swiften/Network/DomainNameServiceQuery.h b/Swiften/Network/DomainNameServiceQuery.h index 63d5841..0bd1569 100644 --- a/Swiften/Network/DomainNameServiceQuery.h +++ b/Swiften/Network/DomainNameServiceQuery.h @@ -6,13 +6,13 @@  #pragma once -#include "Swiften/Base/boost_bsignals.h" +#include <Swiften/Base/boost_bsignals.h>  #include <boost/optional.hpp>  #include <vector>  #include <boost/shared_ptr.hpp>  #include <string> -#include "Swiften/Network/DomainNameResolveError.h" +#include <Swiften/Network/DomainNameResolveError.h>  namespace Swift {  	class DomainNameServiceQuery { diff --git a/Swiften/Network/DummyConnection.cpp b/Swiften/Network/DummyConnection.cpp new file mode 100644 index 0000000..9a9d138 --- /dev/null +++ b/Swiften/Network/DummyConnection.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Network/DummyConnection.h> + +#include <boost/bind.hpp> +#include <cassert> + +namespace Swift { + +DummyConnection::DummyConnection(EventLoop* eventLoop) : eventLoop(eventLoop) { +} + +void DummyConnection::receive(const SafeByteArray& data) { +	eventLoop->postEvent(boost::bind(boost::ref(onDataRead), SafeByteArray(data)), shared_from_this()); +} + +void DummyConnection::listen() { +	assert(false); +} + +void DummyConnection::connect(const HostAddressPort&) { +	assert(false); +} + + +} diff --git a/Swiften/Network/DummyConnection.h b/Swiften/Network/DummyConnection.h index 6b426b1..5191e30 100644 --- a/Swiften/Network/DummyConnection.h +++ b/Swiften/Network/DummyConnection.h @@ -6,45 +6,37 @@  #pragma once -#include <cassert> -#include <boost/bind.hpp>  #include <boost/enable_shared_from_this.hpp> -#include "Swiften/Network/Connection.h" -#include "Swiften/EventLoop/EventLoop.h" -#include "Swiften/EventLoop/EventOwner.h" +#include <Swiften/Network/Connection.h> +#include <Swiften/Network/HostAddressPort.h> +#include <Swiften/EventLoop/EventLoop.h> +#include <Swiften/EventLoop/EventOwner.h>  namespace Swift {  	class DummyConnection : public Connection, public EventOwner,	public boost::enable_shared_from_this<DummyConnection> {  		public: -			DummyConnection(EventLoop* eventLoop) : eventLoop(eventLoop) {} +			DummyConnection(EventLoop* eventLoop); -			void listen() { -				assert(false); -			} - -			void connect(const HostAddressPort&) { -				assert(false); -			} +			void listen(); +			void connect(const HostAddressPort&);  			void disconnect() {  				//assert(false);  			} -			void write(const ByteArray& data) { +			void write(const SafeByteArray& data) {  				eventLoop->postEvent(boost::ref(onDataWritten), shared_from_this());  				onDataSent(data);  			} -			void receive(const ByteArray& data) { -				eventLoop->postEvent(boost::bind(boost::ref(onDataRead), ByteArray(data)), shared_from_this()); -			} +			void receive(const SafeByteArray& data);  			HostAddressPort getLocalAddress() const {  				return localAddress;  			} -			boost::signal<void (const ByteArray&)> onDataSent; +			boost::signal<void (const SafeByteArray&)> onDataSent;  			EventLoop* eventLoop;  			HostAddressPort localAddress; diff --git a/Swiften/Network/DummyTimerFactory.cpp b/Swiften/Network/DummyTimerFactory.cpp index 105b103..16428b7 100644 --- a/Swiften/Network/DummyTimerFactory.cpp +++ b/Swiften/Network/DummyTimerFactory.cpp @@ -4,12 +4,12 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/Network/DummyTimerFactory.h" +#include <Swiften/Network/DummyTimerFactory.h>  #include <algorithm> -#include "Swiften/Base/foreach.h" -#include "Swiften/Network/Timer.h" +#include <Swiften/Base/foreach.h> +#include <Swiften/Network/Timer.h>  namespace Swift { diff --git a/Swiften/Network/DummyTimerFactory.h b/Swiften/Network/DummyTimerFactory.h index 408b647..0c49f3d 100644 --- a/Swiften/Network/DummyTimerFactory.h +++ b/Swiften/Network/DummyTimerFactory.h @@ -8,7 +8,7 @@  #include <list> -#include "Swiften/Network/TimerFactory.h" +#include <Swiften/Network/TimerFactory.h>  namespace Swift {  	class DummyTimerFactory : public TimerFactory { diff --git a/Swiften/Network/EnvironmentProxyProvider.cpp b/Swiften/Network/EnvironmentProxyProvider.cpp new file mode 100644 index 0000000..7701da1 --- /dev/null +++ b/Swiften/Network/EnvironmentProxyProvider.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2010-2011 Thilo Cestonaro + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <iostream> + +#include <Swiften/Base/Log.h> +#include <Swiften/Network/EnvironmentProxyProvider.h> + +namespace Swift { + +EnvironmentProxyProvider::EnvironmentProxyProvider() { +	socksProxy = getFromEnv("all_proxy", "socks"); +	httpProxy = getFromEnv("http_proxy", "http"); +	SWIFT_LOG(debug) << "Environment: SOCKS5 => " << socksProxy.toString() << "; HTTP Connect => " << httpProxy.toString() << std::endl; +} + +HostAddressPort EnvironmentProxyProvider::getHTTPConnectProxy() const { +	return httpProxy; +} + +HostAddressPort EnvironmentProxyProvider::getSOCKS5Proxy() const { +	return socksProxy; +} + +HostAddressPort EnvironmentProxyProvider::getFromEnv(const char* envVarName, std::string proxyProtocol) { +	char* envVar = NULL; +	std::string address; +	int port = 0; + +	envVar = getenv(envVarName); + +	proxyProtocol += "://"; +	address = envVar != NULL ? envVar : "0.0.0.0"; +	if(envVar != NULL && address.compare(0, proxyProtocol.length(), proxyProtocol) == 0) { +		address = address.substr(proxyProtocol.length(), address.length()); +		port = atoi(address.substr(address.find(':') + 1, address.length()).c_str()); +		address = address.substr(0, address.find(':')); +	} + +	return HostAddressPort(HostAddress(address), port); +} + +} diff --git a/Swiften/Network/EnvironmentProxyProvider.h b/Swiften/Network/EnvironmentProxyProvider.h new file mode 100644 index 0000000..224d301 --- /dev/null +++ b/Swiften/Network/EnvironmentProxyProvider.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2010-2011 Thilo Cestonaro + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Network/ProxyProvider.h> + +namespace Swift { +	class EnvironmentProxyProvider : public ProxyProvider { +		public: +			EnvironmentProxyProvider(); +			virtual HostAddressPort getHTTPConnectProxy() const; +			virtual HostAddressPort getSOCKS5Proxy() const; +		private: +			HostAddressPort getFromEnv(const char* envVarName, std::string proxyProtocol); +			HostAddressPort socksProxy; +			HostAddressPort httpProxy; +	}; +} + + diff --git a/Swiften/Network/FakeConnection.cpp b/Swiften/Network/FakeConnection.cpp new file mode 100644 index 0000000..be5555c --- /dev/null +++ b/Swiften/Network/FakeConnection.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Network/FakeConnection.h> + +#include <boost/bind.hpp> + +namespace Swift { + +FakeConnection::FakeConnection(EventLoop* eventLoop) : eventLoop(eventLoop), state(Initial), delayConnect(false) { +} + +FakeConnection::~FakeConnection() { +} + +void FakeConnection::listen() { +	assert(false); +} + +void FakeConnection::setError(const Error& e) { +	error = boost::optional<Error>(e); +	state = DisconnectedWithError; +	if (connectedTo) { +		eventLoop->postEvent( +				boost::bind(boost::ref(onDisconnected), error), +				shared_from_this()); +	} +} + +void FakeConnection::connect(const HostAddressPort& address) { +	if (delayConnect) { +		state = Connecting; +	} +	else { +		if (!error) { +			connectedTo = address; +			state = Connected; +		} +		else { +			state = DisconnectedWithError; +		} +		eventLoop->postEvent( +				boost::bind(boost::ref(onConnectFinished), error), +				shared_from_this()); +	} +} + +void FakeConnection::disconnect() { +	if (!error) { +		state = Disconnected; +	} +	else { +		state = DisconnectedWithError; +	} +	connectedTo.reset(); +	eventLoop->postEvent( +			boost::bind(boost::ref(onDisconnected), error), +			shared_from_this()); +} + +} diff --git a/Swiften/Network/FakeConnection.h b/Swiften/Network/FakeConnection.h index 4e2e960..99cb584 100644 --- a/Swiften/Network/FakeConnection.h +++ b/Swiften/Network/FakeConnection.h @@ -7,14 +7,13 @@  #pragma once  #include <boost/optional.hpp> -#include <boost/bind.hpp>  #include <boost/enable_shared_from_this.hpp>  #include <vector> -#include "Swiften/Network/Connection.h" -#include "Swiften/Network/HostAddressPort.h" -#include "Swiften/EventLoop/EventOwner.h" -#include "Swiften/EventLoop/EventLoop.h" +#include <Swiften/Network/Connection.h> +#include <Swiften/Network/HostAddressPort.h> +#include <Swiften/EventLoop/EventOwner.h> +#include <Swiften/EventLoop/EventLoop.h>  namespace Swift {  	class FakeConnection :  @@ -30,58 +29,19 @@ namespace Swift {  				DisconnectedWithError  			}; -			FakeConnection(EventLoop* eventLoop) : eventLoop(eventLoop), state(Initial), delayConnect(false) {} - -			virtual void listen() { -				assert(false); -			} +			FakeConnection(EventLoop* eventLoop); +			~FakeConnection(); +			virtual void listen();  			virtual HostAddressPort getLocalAddress() const {  				return HostAddressPort();  			} -			void setError(const Error& e) { -				error = boost::optional<Error>(e); -				state = DisconnectedWithError; -				if (connectedTo) { -					eventLoop->postEvent( -							boost::bind(boost::ref(onDisconnected), error), -							shared_from_this()); -				} -			} - -			virtual void connect(const HostAddressPort& address) { -				if (delayConnect) { -					state = Connecting; -				} -				else { -					if (!error) { -						connectedTo = address; -						state = Connected; -					} -					else { -						state = DisconnectedWithError; -					} -					eventLoop->postEvent( -							boost::bind(boost::ref(onConnectFinished), error), -							shared_from_this()); -				} -			} - -			virtual void disconnect() { -				if (!error) { -					state = Disconnected; -				} -				else { -					state = DisconnectedWithError; -				} -				connectedTo.reset(); -				eventLoop->postEvent( -						boost::bind(boost::ref(onDisconnected), error), -						shared_from_this()); -			} +			void setError(const Error& e); +			virtual void connect(const HostAddressPort& address); +			virtual void disconnect(); -			virtual void write(const ByteArray& data) { +			virtual void write(const SafeByteArray& data) {  				dataWritten.push_back(data);  			} @@ -91,7 +51,7 @@ namespace Swift {  			EventLoop* eventLoop;  			boost::optional<HostAddressPort> connectedTo; -			std::vector<ByteArray> dataWritten; +			std::vector<SafeByteArray> dataWritten;  			boost::optional<Error> error;  			State state;  			bool delayConnect; diff --git a/Swiften/Network/GConfProxyProvider.cpp b/Swiften/Network/GConfProxyProvider.cpp new file mode 100644 index 0000000..26de4d8 --- /dev/null +++ b/Swiften/Network/GConfProxyProvider.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010-2011 Thilo Cestonaro + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <iostream> + +#include <gconf/gconf-client.h> + +#include <Swiften/Base/Log.h> +#include <Swiften/Network/GConfProxyProvider.h> + +namespace Swift { + +GConfProxyProvider::GConfProxyProvider() { +	socksProxy = getFromGConf("/system/proxy/socks_host", "/system/proxy/socks_port"); +	httpProxy = getFromGConf("/system/http_proxy/host", "/system/http_proxy/port"); +	SWIFT_LOG(debug) << "GConf: SOCKS5 => " << socksProxy.toString() << "; HTTP Connect => " << httpProxy.toString() << std::endl; +} + +HostAddressPort GConfProxyProvider::getHTTPConnectProxy() const { +	return httpProxy; +} + +HostAddressPort GConfProxyProvider::getSOCKS5Proxy() const { +	return socksProxy; +} + +HostAddressPort GConfProxyProvider::getFromGConf(const char* gcHost, const char* gcPort) { +	std::string address; +	int port = 0; +	gchar* str; + +	GConfClient* client = gconf_client_get_default(); + +	str = gconf_client_get_string(client, gcHost, NULL); +	port = static_cast<int> (gconf_client_get_int(client, gcPort, NULL)); + +	if(str) { +		address = static_cast<char*> (str); +		g_free(str); +	} + +	g_object_unref(client); +	return HostAddressPort(HostAddress(address), port); +} + +} diff --git a/Swiften/Network/GConfProxyProvider.h b/Swiften/Network/GConfProxyProvider.h new file mode 100644 index 0000000..31f38a9 --- /dev/null +++ b/Swiften/Network/GConfProxyProvider.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2010-2011 Thilo Cestonaro + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Network/ProxyProvider.h> + +namespace Swift { +	class GConfProxyProvider : public ProxyProvider { +		public: +			GConfProxyProvider(); +			virtual HostAddressPort getHTTPConnectProxy() const; +			virtual HostAddressPort getSOCKS5Proxy() const; +		private: +			HostAddressPort getFromGConf(const char* gcHost, const char* gcPort); +			HostAddressPort socksProxy; +			HostAddressPort httpProxy; +	}; +} + + diff --git a/Swiften/Network/HTTPConnectProxiedConnection.cpp b/Swiften/Network/HTTPConnectProxiedConnection.cpp new file mode 100644 index 0000000..20819ff --- /dev/null +++ b/Swiften/Network/HTTPConnectProxiedConnection.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2010-2011 Thilo Cestonaro + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Network/HTTPConnectProxiedConnection.h> + +#include <iostream> +#include <boost/bind.hpp> +#include <boost/thread.hpp> +#include <boost/lexical_cast.hpp> + +#include <Swiften/Base/Log.h> +#include <Swiften/Base/String.h> +#include <Swiften/Base/ByteArray.h> +#include <Swiften/Network/HostAddressPort.h> +#include <Swiften/Network/ConnectionFactory.h> + +using namespace Swift; + +HTTPConnectProxiedConnection::HTTPConnectProxiedConnection(ConnectionFactory* connectionFactory, HostAddressPort proxy) : connectionFactory_(connectionFactory), proxy_(proxy), server_(HostAddressPort(HostAddress("0.0.0.0"), 0)) { +	connected_ = false; +} + +HTTPConnectProxiedConnection::~HTTPConnectProxiedConnection() { +	if (connection_) { +		connection_->onDataRead.disconnect(boost::bind(&HTTPConnectProxiedConnection::handleDataRead, shared_from_this(), _1)); +		connection_->onDisconnected.disconnect(boost::bind(&HTTPConnectProxiedConnection::handleDisconnected, shared_from_this(), _1)); +	} + +	if (connected_) { +		std::cerr << "Warning: Connection was still established." << std::endl; +	} +} + +void HTTPConnectProxiedConnection::connect(const HostAddressPort& server) { +	server_ = server; +	connection_ = connectionFactory_->createConnection(); +	connection_->onConnectFinished.connect(boost::bind(&HTTPConnectProxiedConnection::handleConnectionConnectFinished, shared_from_this(), _1)); +	connection_->onDataRead.connect(boost::bind(&HTTPConnectProxiedConnection::handleDataRead, shared_from_this(), _1)); +	connection_->onDisconnected.connect(boost::bind(&HTTPConnectProxiedConnection::handleDisconnected, shared_from_this(), _1)); +	connection_->connect(proxy_); +} + +void HTTPConnectProxiedConnection::listen() { +	assert(false); +	connection_->listen(); +} + +void HTTPConnectProxiedConnection::disconnect() { +	connected_ = false; +	connection_->disconnect(); +} + +void HTTPConnectProxiedConnection::handleDisconnected(const boost::optional<Error>& error) { +	onDisconnected(error); +} + +void HTTPConnectProxiedConnection::write(const SafeByteArray& data) { +	connection_->write(data); +} + +void HTTPConnectProxiedConnection::handleConnectionConnectFinished(bool error) { +	connection_->onConnectFinished.disconnect(boost::bind(&HTTPConnectProxiedConnection::handleConnectionConnectFinished, shared_from_this(), _1)); +	if (!error) { +		std::stringstream connect; +		connect << "CONNECT " << server_.getAddress().toString() << ":" << server_.getPort() << " HTTP/1.1\r\n\r\n"; +		connection_->write(createSafeByteArray(connect.str())); +	} +	else { +		onConnectFinished(true); +	} +} + +void HTTPConnectProxiedConnection::handleDataRead(const SafeByteArray& data) { +	if (!connected_) { +		SWIFT_LOG(debug) << byteArrayToString(ByteArray(data.begin(), data.end())) << std::endl; +		std::vector<std::string> tmp = String::split(byteArrayToString(ByteArray(data.begin(), data.end())), ' '); +		if(tmp.size() > 1) { +			int status = boost::lexical_cast<int> (tmp[1].c_str());  +			SWIFT_LOG(debug) << "Proxy Status: " << status << std::endl; +			if (status / 100 == 2) { // all 2XX states are OK +				connected_ = true; +				onConnectFinished(false); +				return; +			} +			SWIFT_LOG(debug) << "HTTP Proxy returned an error: " << byteArrayToString(ByteArray(data.begin(), data.end())) << std::endl; +		} +		disconnect(); +		onConnectFinished(true); +	} +	else { +		onDataRead(data); +	} +} + +HostAddressPort HTTPConnectProxiedConnection::getLocalAddress() const { +	return connection_->getLocalAddress(); +} diff --git a/Swiften/Network/HTTPConnectProxiedConnection.h b/Swiften/Network/HTTPConnectProxiedConnection.h new file mode 100644 index 0000000..96c6be8 --- /dev/null +++ b/Swiften/Network/HTTPConnectProxiedConnection.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2010-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> + +namespace boost { +	class thread; +	namespace system { +		class error_code; +	} +} + +namespace Swift { +	class ConnectionFactory; + +	class HTTPConnectProxiedConnection : public Connection, public boost::enable_shared_from_this<HTTPConnectProxiedConnection> { +		public: +			typedef boost::shared_ptr<HTTPConnectProxiedConnection> ref; + +			~HTTPConnectProxiedConnection(); + +			static ref create(ConnectionFactory* connectionFactory, HostAddressPort proxy) { +				return ref(new HTTPConnectProxiedConnection(connectionFactory, proxy)); +			} + +			virtual void listen(); +			virtual void connect(const HostAddressPort& address); +			virtual void disconnect(); +			virtual void write(const SafeByteArray& data); + +			virtual HostAddressPort getLocalAddress() const; +		private: +			HTTPConnectProxiedConnection(ConnectionFactory* connectionFactory, HostAddressPort proxy); + +			void handleConnectionConnectFinished(bool error); +			void handleDataRead(const SafeByteArray& data); +			void handleDisconnected(const boost::optional<Error>& error); + +		private: +			bool connected_; +			ConnectionFactory* connectionFactory_;	 +			HostAddressPort proxy_; +			HostAddressPort server_; +			boost::shared_ptr<Connection> connection_; +	}; +} diff --git a/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp b/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp new file mode 100644 index 0000000..ab7f18e --- /dev/null +++ b/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2010-2011 Thilo Cestonaro + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Network/HTTPConnectProxiedConnectionFactory.h> + +#include <Swiften/Network/HTTPConnectProxiedConnection.h> + +namespace Swift { + +HTTPConnectProxiedConnectionFactory::HTTPConnectProxiedConnectionFactory(ConnectionFactory* connectionFactory, const HostAddressPort& proxy) : connectionFactory_(connectionFactory), proxy_(proxy) { +} + +boost::shared_ptr<Connection> HTTPConnectProxiedConnectionFactory::createConnection() { +	return HTTPConnectProxiedConnection::create(connectionFactory_, proxy_); +} + +} diff --git a/Swiften/Network/HTTPConnectProxiedConnectionFactory.h b/Swiften/Network/HTTPConnectProxiedConnectionFactory.h new file mode 100644 index 0000000..b475586 --- /dev/null +++ b/Swiften/Network/HTTPConnectProxiedConnectionFactory.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2010-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 HTTPConnectProxiedConnectionFactory : public ConnectionFactory { +		public: +			HTTPConnectProxiedConnectionFactory(ConnectionFactory* connectionFactory, const HostAddressPort& proxy); + +			virtual boost::shared_ptr<Connection> createConnection(); + +		private: +			ConnectionFactory* connectionFactory_; +			HostAddressPort proxy_; +	}; +} diff --git a/Swiften/Network/HostAddress.cpp b/Swiften/Network/HostAddress.cpp index 2ca1414..7ba2a7f 100644 --- a/Swiften/Network/HostAddress.cpp +++ b/Swiften/Network/HostAddress.cpp @@ -4,7 +4,7 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/Network/HostAddress.h" +#include <Swiften/Network/HostAddress.h>  #include <boost/numeric/conversion/cast.hpp>  #include <boost/lexical_cast.hpp> @@ -12,7 +12,7 @@  #include <stdexcept>  #include <boost/array.hpp> -#include "Swiften/Base/foreach.h" +#include <Swiften/Base/foreach.h>  #include <string>  namespace Swift { @@ -24,7 +24,7 @@ HostAddress::HostAddress(const std::string& address) {  	try {  		address_ = boost::asio::ip::address::from_string(address);  	} -	catch (const std::exception& t) { +	catch (const std::exception&) {  	}  } diff --git a/Swiften/Network/HostAddress.h b/Swiften/Network/HostAddress.h index 4b05c32..0b3bdda 100644 --- a/Swiften/Network/HostAddress.h +++ b/Swiften/Network/HostAddress.h @@ -3,16 +3,12 @@   * Licensed under the GNU General Public License v3.   * See Documentation/Licenses/GPLv3.txt for more information.   */ -  #pragma once  #include <string> -#include <vector> -#include <boost/asio.hpp> +#include <boost/asio/ip/address.hpp>  namespace Swift { -	 -  	class HostAddress {  		public:  			HostAddress(); diff --git a/Swiften/Network/HostAddressPort.cpp b/Swiften/Network/HostAddressPort.cpp new file mode 100644 index 0000000..e2e6012 --- /dev/null +++ b/Swiften/Network/HostAddressPort.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Network/HostAddressPort.h> + +#include <boost/lexical_cast.hpp> + +using namespace Swift; + +HostAddressPort::HostAddressPort(const HostAddress& address, int port) : address_(address), port_(port) { +} + +HostAddressPort::HostAddressPort(const boost::asio::ip::tcp::endpoint& endpoint) { +	address_ = HostAddress(endpoint.address()); +	port_ = endpoint.port(); +} + +std::string HostAddressPort::toString() const { +	return getAddress().toString() + ":" + boost::lexical_cast<std::string>(getPort()); +} diff --git a/Swiften/Network/HostAddressPort.h b/Swiften/Network/HostAddressPort.h index 6883380..e3c0413 100644 --- a/Swiften/Network/HostAddressPort.h +++ b/Swiften/Network/HostAddressPort.h @@ -6,21 +6,15 @@  #pragma once -#include <boost/asio.hpp> +#include <boost/asio/ip/tcp.hpp> -#include "Swiften/Network/HostAddress.h" +#include <Swiften/Network/HostAddress.h>  namespace Swift {  	class HostAddressPort {  		public: -			HostAddressPort(const HostAddress& address = HostAddress(), int port = -1) : address_(address), port_(port) { -			} - -			HostAddressPort(const boost::asio::ip::tcp::endpoint& endpoint) { -				address_ = HostAddress(endpoint.address()); -				port_ = endpoint.port(); -			} - +			HostAddressPort(const HostAddress& address = HostAddress(), int port = -1); +			HostAddressPort(const boost::asio::ip::tcp::endpoint& endpoint);  			const HostAddress& getAddress() const {  				return address_; @@ -37,6 +31,8 @@ namespace Swift {  			bool isValid() const {  				return address_.isValid() && port_ > 0;  			} +			 +			std::string toString() const;  		private:  			HostAddress address_; diff --git a/Swiften/Network/MacOSXProxyProvider.cpp b/Swiften/Network/MacOSXProxyProvider.cpp new file mode 100644 index 0000000..eaadd28 --- /dev/null +++ b/Swiften/Network/MacOSXProxyProvider.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2010-2011 Thilo Cestonaro + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Base/Platform.h> +#include <Swiften/Network/MacOSXProxyProvider.h> + +#include <stdio.h> +#include <stdlib.h> +#include <iostream> +#include <utility> + +#ifndef SWIFTEN_PLATFORM_IPHONE +#include <SystemConfiguration/SystemConfiguration.h> +#endif + +using namespace Swift; + +#ifndef SWIFTEN_PLATFORM_IPHONE +static HostAddressPort getFromDictionary(CFDictionaryRef dict, CFStringRef enabledKey, CFStringRef hostKey, CFStringRef portKey) { +	CFNumberRef numberValue = NULL; +	HostAddressPort ret = HostAddressPort(HostAddress(), 0); + +	if(CFDictionaryGetValueIfPresent(dict, reinterpret_cast<const void*> (enabledKey), reinterpret_cast<const void**> (&numberValue)) == true) { +		const int i = 0; +		CFNumberRef zero = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &i); +		CFComparisonResult result = CFNumberCompare(numberValue, zero, NULL); +		CFRelease(numberValue); + +		if(result != kCFCompareEqualTo) { +			int port = 0; +			std::string host = ""; + +			try { +				CFNumberRef numberValue = reinterpret_cast<CFNumberRef> (CFDictionaryGetValue(dict, portKey)); +				if(numberValue != NULL) { +					CFNumberGetValue(numberValue, kCFNumberIntType, &port); +					CFRelease(numberValue); +				} + +				CFStringRef stringValue = reinterpret_cast<CFStringRef> (CFDictionaryGetValue(dict, hostKey)); +				if(stringValue != NULL) { +					std::vector<char> buffer; + 					// length must be +1 for the ending zero; and the Docu of CFStringGetCString tells it like +					// if the string is toby the length must be at least 5. +					CFIndex length = CFStringGetLength(stringValue) + 1; +					buffer.resize(length); +					if(CFStringGetCString(stringValue, &buffer[0], length, kCFStringEncodingMacRoman)) { +						for(std::vector<char>::iterator iter = buffer.begin(); iter != buffer.end(); ++iter) { +							host += *iter; +						} +					} +					CFRelease(stringValue); +				} +			} +			catch(...) { +				std::cerr << "Exception caught ... " << std::endl; +			} +			 +			if(host != "" && port != 0) { +				ret = HostAddressPort(HostAddress(host), port); +			} +		} +	} +	return ret; +} +#endif +namespace Swift { + +MacOSXProxyProvider::MacOSXProxyProvider() { +} + +HostAddressPort MacOSXProxyProvider::getHTTPConnectProxy() const { +	HostAddressPort result; +#ifndef SWIFTEN_PLATFORM_IPHONE +	CFDictionaryRef proxies = SCDynamicStoreCopyProxies(NULL); +	if(proxies != NULL) { +		result = getFromDictionary(proxies, kSCPropNetProxiesHTTPEnable, kSCPropNetProxiesHTTPProxy, kSCPropNetProxiesHTTPPort); +	} +#endif +	return result; +} + +HostAddressPort MacOSXProxyProvider::getSOCKS5Proxy() const { +	HostAddressPort result; +#ifndef SWIFTEN_PLATFORM_IPHONE +	CFDictionaryRef proxies = SCDynamicStoreCopyProxies(NULL); +	if(proxies != NULL) { +		result = getFromDictionary(proxies, kSCPropNetProxiesSOCKSEnable, kSCPropNetProxiesSOCKSProxy, kSCPropNetProxiesSOCKSPort); +	} +#endif +	return result; +} + +} diff --git a/Swiften/Network/MacOSXProxyProvider.h b/Swiften/Network/MacOSXProxyProvider.h new file mode 100644 index 0000000..6666d30 --- /dev/null +++ b/Swiften/Network/MacOSXProxyProvider.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2010-2011 Thilo Cestonaro + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once +#include <Swiften/Network/ProxyProvider.h> +#include <CoreFoundation/CoreFoundation.h> + +namespace Swift { +	class MacOSXProxyProvider : public ProxyProvider { +		public: +			MacOSXProxyProvider(); +			virtual HostAddressPort getHTTPConnectProxy() const; +			virtual HostAddressPort getSOCKS5Proxy() const; +	}; +} diff --git a/Swiften/Network/NetworkFactories.cpp b/Swiften/Network/NetworkFactories.cpp index 361cb90..7046fd3 100644 --- a/Swiften/Network/NetworkFactories.cpp +++ b/Swiften/Network/NetworkFactories.cpp @@ -4,7 +4,7 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/Network/NetworkFactories.h" +#include <Swiften/Network/NetworkFactories.h>  namespace Swift { diff --git a/Swiften/Network/NullProxyProvider.cpp b/Swiften/Network/NullProxyProvider.cpp new file mode 100644 index 0000000..3b9d94d --- /dev/null +++ b/Swiften/Network/NullProxyProvider.cpp @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Network/NullProxyProvider.h> + +using namespace Swift; + +NullProxyProvider::NullProxyProvider() { +} + +HostAddressPort NullProxyProvider::getHTTPConnectProxy() const { +	return HostAddressPort(); +} + +HostAddressPort NullProxyProvider::getSOCKS5Proxy() const { +	return HostAddressPort(); +} diff --git a/Swiften/Network/NullProxyProvider.h b/Swiften/Network/NullProxyProvider.h new file mode 100644 index 0000000..544bea2 --- /dev/null +++ b/Swiften/Network/NullProxyProvider.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Network/ProxyProvider.h> + +namespace Swift { +	class NullProxyProvider : public ProxyProvider { +		public: +			NullProxyProvider(); + +			virtual HostAddressPort getHTTPConnectProxy() const; +			virtual HostAddressPort getSOCKS5Proxy() const; +	}; +} diff --git a/Swiften/Network/PlatformDomainNameAddressQuery.cpp b/Swiften/Network/PlatformDomainNameAddressQuery.cpp index 1832255..ec7e663 100644 --- a/Swiften/Network/PlatformDomainNameAddressQuery.cpp +++ b/Swiften/Network/PlatformDomainNameAddressQuery.cpp @@ -6,6 +6,8 @@  #include <Swiften/Network/PlatformDomainNameAddressQuery.h> +#include <boost/asio/ip/tcp.hpp> +  #include <Swiften/Network/PlatformDomainNameResolver.h>  #include <Swiften/EventLoop/EventLoop.h> diff --git a/Swiften/Network/PlatformDomainNameAddressQuery.h b/Swiften/Network/PlatformDomainNameAddressQuery.h index c2854ac..e1dc05f 100644 --- a/Swiften/Network/PlatformDomainNameAddressQuery.h +++ b/Swiften/Network/PlatformDomainNameAddressQuery.h @@ -6,7 +6,7 @@  #pragma once -#include <boost/asio.hpp> +#include <boost/asio/io_service.hpp>  #include <boost/enable_shared_from_this.hpp>  #include <Swiften/Network/DomainNameAddressQuery.h> diff --git a/Swiften/Network/PlatformDomainNameResolver.cpp b/Swiften/Network/PlatformDomainNameResolver.cpp index f2c1e36..63f7404 100644 --- a/Swiften/Network/PlatformDomainNameResolver.cpp +++ b/Swiften/Network/PlatformDomainNameResolver.cpp @@ -4,10 +4,10 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/Network/PlatformDomainNameResolver.h" +#include <Swiften/Network/PlatformDomainNameResolver.h>  // Putting this early on, because some system types conflict with thread -#include "Swiften/Network/PlatformDomainNameServiceQuery.h" +#include <Swiften/Network/PlatformDomainNameServiceQuery.h>  #include <string>  #include <vector> @@ -16,11 +16,11 @@  #include <algorithm>  #include <string> -#include "Swiften/IDN/IDNA.h" -#include "Swiften/Network/HostAddress.h" -#include "Swiften/EventLoop/EventLoop.h" -#include "Swiften/Network/HostAddressPort.h" -#include "Swiften/Network/DomainNameAddressQuery.h" +#include <Swiften/IDN/IDNA.h> +#include <Swiften/Network/HostAddress.h> +#include <Swiften/EventLoop/EventLoop.h> +#include <Swiften/Network/HostAddressPort.h> +#include <Swiften/Network/DomainNameAddressQuery.h>  #include <Swiften/Network/PlatformDomainNameAddressQuery.h>  using namespace Swift; diff --git a/Swiften/Network/PlatformDomainNameResolver.h b/Swiften/Network/PlatformDomainNameResolver.h index e681331..295ecc5 100644 --- a/Swiften/Network/PlatformDomainNameResolver.h +++ b/Swiften/Network/PlatformDomainNameResolver.h @@ -7,7 +7,7 @@  #pragma once  #include <deque> -#include <boost/thread.hpp> +#include <boost/thread/thread.hpp>  #include <boost/thread/mutex.hpp>  #include <boost/thread/condition_variable.hpp> diff --git a/Swiften/Network/PlatformDomainNameServiceQuery.cpp b/Swiften/Network/PlatformDomainNameServiceQuery.cpp index 7d8074d..5d076ac 100644 --- a/Swiften/Network/PlatformDomainNameServiceQuery.cpp +++ b/Swiften/Network/PlatformDomainNameServiceQuery.cpp @@ -6,11 +6,11 @@  #include <boost/asio.hpp> -#include "Swiften/Network/PlatformDomainNameServiceQuery.h" +#include <Swiften/Network/PlatformDomainNameServiceQuery.h>  #pragma GCC diagnostic ignored "-Wold-style-cast" -#include "Swiften/Base/Platform.h" +#include <Swiften/Base/Platform.h>  #include <stdlib.h>  #ifdef SWIFTEN_PLATFORM_WINDOWS  #undef UNICODE @@ -26,9 +26,9 @@  #endif  #include <boost/bind.hpp> -#include "Swiften/Base/ByteArray.h" -#include "Swiften/EventLoop/EventLoop.h" -#include "Swiften/Base/foreach.h" +#include <Swiften/Base/ByteArray.h> +#include <Swiften/EventLoop/EventLoop.h> +#include <Swiften/Base/foreach.h>  #include <Swiften/Base/Log.h>  #include <Swiften/Network/PlatformDomainNameResolver.h> @@ -81,7 +81,7 @@ void PlatformDomainNameServiceQuery::runBlocking() {  	ByteArray response;  	response.resize(NS_PACKETSZ); -	int responseLength = res_query(const_cast<char*>(service.c_str()), ns_c_in, ns_t_srv, reinterpret_cast<u_char*>(response.getData()), response.getSize()); +	int responseLength = res_query(const_cast<char*>(service.c_str()), ns_c_in, ns_t_srv, reinterpret_cast<u_char*>(vecptr(response)), response.size());  	if (responseLength == -1) {  		SWIFT_LOG(debug) << "Error" << std::endl;  		emitError(); @@ -89,8 +89,8 @@ void PlatformDomainNameServiceQuery::runBlocking() {  	}  	// Parse header -	HEADER* header = reinterpret_cast<HEADER*>(response.getData()); -	unsigned char* messageStart = reinterpret_cast<unsigned char*>(response.getData()); +	HEADER* header = reinterpret_cast<HEADER*>(vecptr(response)); +	unsigned char* messageStart = vecptr(response);  	unsigned char* messageEnd = messageStart + responseLength;  	unsigned char* currentEntry = messageStart + NS_HFIXEDSZ; @@ -146,12 +146,12 @@ void PlatformDomainNameServiceQuery::runBlocking() {  		}  		ByteArray entry;  		entry.resize(NS_MAXDNAME); -		entryLength = dn_expand(messageStart, messageEnd, currentEntry, reinterpret_cast<char*>(entry.getData()), entry.getSize()); +		entryLength = dn_expand(messageStart, messageEnd, currentEntry, reinterpret_cast<char*>(vecptr(entry)), entry.size());  		if (entryLength < 0) {  			emitError();  			return;  		} -		record.hostname = std::string(reinterpret_cast<const char*>(entry.getData())); +		record.hostname = std::string(reinterpret_cast<const char*>(vecptr(entry)));  		records.push_back(record);  		currentEntry += entryLength;  		answersCount--; diff --git a/Swiften/Network/PlatformDomainNameServiceQuery.h b/Swiften/Network/PlatformDomainNameServiceQuery.h index 52f8bc1..3372517 100644 --- a/Swiften/Network/PlatformDomainNameServiceQuery.h +++ b/Swiften/Network/PlatformDomainNameServiceQuery.h @@ -8,8 +8,8 @@  #include <boost/enable_shared_from_this.hpp> -#include "Swiften/Network/DomainNameServiceQuery.h" -#include "Swiften/EventLoop/EventOwner.h" +#include <Swiften/Network/DomainNameServiceQuery.h> +#include <Swiften/EventLoop/EventOwner.h>  #include <string>  #include <Swiften/Network/PlatformDomainNameQuery.h> diff --git a/Swiften/Network/PlatformProxyProvider.h b/Swiften/Network/PlatformProxyProvider.h new file mode 100644 index 0000000..1a0a1c6 --- /dev/null +++ b/Swiften/Network/PlatformProxyProvider.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2010-2011 Thilo Cestonaro + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Base/Platform.h> + +#if defined(SWIFTEN_PLATFORM_MACOSX) +#include <Swiften/Network/MacOSXProxyProvider.h> +namespace Swift { +	typedef MacOSXProxyProvider PlatformProxyProvider; +} +#elif defined(SWIFTEN_PLATFORM_WIN32) +#include <Swiften/Network/WindowsProxyProvider.h> +namespace Swift { +	typedef WindowsProxyProvider PlatformProxyProvider; +} +#else +#include <Swiften/Network/UnixProxyProvider.h> +namespace Swift { +	typedef UnixProxyProvider PlatformProxyProvider; +} +#endif diff --git a/Swiften/Network/ProxyProvider.cpp b/Swiften/Network/ProxyProvider.cpp new file mode 100644 index 0000000..fe235b1 --- /dev/null +++ b/Swiften/Network/ProxyProvider.cpp @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2010-2011 Thilo Cestonaro + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "ProxyProvider.h" + +namespace Swift { + +ProxyProvider::ProxyProvider() +{ +} + +ProxyProvider::~ProxyProvider() +{ +} + +} diff --git a/Swiften/Network/ProxyProvider.h b/Swiften/Network/ProxyProvider.h new file mode 100644 index 0000000..0b63d51 --- /dev/null +++ b/Swiften/Network/ProxyProvider.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2010-2011 Thilo Cestonaro + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once +#include <map> + +#include <Swiften/Base/Log.h> +#include <Swiften/Network/HostAddressPort.h> +#include <Swiften/Base/String.h> + +namespace Swift { +	class ProxyProvider { +		public: +			ProxyProvider(); +			virtual ~ProxyProvider(); +			virtual HostAddressPort getHTTPConnectProxy() const = 0; +			virtual HostAddressPort getSOCKS5Proxy() const = 0; +	}; +} + diff --git a/Swiften/Network/SConscript b/Swiften/Network/SConscript index d5cc185..965361b 100644 --- a/Swiften/Network/SConscript +++ b/Swiften/Network/SConscript @@ -6,6 +6,10 @@ if myenv.get("HAVE_CARES", False) :     myenv.MergeFlags(myenv.get("CARES_FLAGS", {}))  sourceList = [ +			"HTTPConnectProxiedConnection.cpp", +			"HTTPConnectProxiedConnectionFactory.cpp", +			"SOCKS5ProxiedConnection.cpp", +			"SOCKS5ProxiedConnectionFactory.cpp",  			"BoostConnection.cpp",  			"BoostConnectionFactory.cpp",  			"BoostConnectionServer.cpp", @@ -14,7 +18,11 @@ sourceList = [  			"ConnectionFactory.cpp",  			"ConnectionServer.cpp",  			"ConnectionServerFactory.cpp", +			"DummyConnection.cpp", +			"FakeConnection.cpp", + 			"ChainedConnector.cpp",   			"Connector.cpp", + 			"Connection.cpp",  			"TimerFactory.cpp",  			"DummyTimerFactory.cpp",  			"BoostTimerFactory.cpp", @@ -26,13 +34,30 @@ sourceList = [  			"PlatformDomainNameAddressQuery.cpp",  			"StaticDomainNameResolver.cpp",  			"HostAddress.cpp", +			"HostAddressPort.cpp",  			"NetworkFactories.cpp",  			"BoostNetworkFactories.cpp",  			"Timer.cpp", -			"BoostTimer.cpp"] +			"BoostTimer.cpp", +			"ProxyProvider.cpp", +			"NullProxyProvider.cpp" +	] +  if myenv.get("HAVE_CARES", False) :     sourceList.append("CAresDomainNameResolver.cpp") +if myenv["PLATFORM"] == "darwin" : +	myenv.Append(FRAMEWORKS = ["CoreServices", "SystemConfiguration"]) +	sourceList += [ "MacOSXProxyProvider.cpp" ] +elif myenv["PLATFORM"] == "win32" : +	sourceList += [ "WindowsProxyProvider.cpp" ] +else : +	sourceList += [ "UnixProxyProvider.cpp" ] +	sourceList += [ "EnvironmentProxyProvider.cpp" ] +	if myenv.get("HAVE_GCONF", 0) : +		myenv.Append(CPPDEFINES = "HAVE_GCONF") +		myenv.MergeFlags(myenv["GCONF_FLAGS"]) +		sourceList += [ "GConfProxyProvider.cpp" ]  objects = myenv.SwiftenObject(sourceList)  swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/Network/SOCKS5ProxiedConnection.cpp b/Swiften/Network/SOCKS5ProxiedConnection.cpp new file mode 100644 index 0000000..f8084ab --- /dev/null +++ b/Swiften/Network/SOCKS5ProxiedConnection.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2010-2011 Thilo Cestonaro + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Network/SOCKS5ProxiedConnection.h> + +#include <iostream> +#include <boost/bind.hpp> +#include <boost/thread.hpp> + +#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> + +using namespace Swift; + +SOCKS5ProxiedConnection::SOCKS5ProxiedConnection(ConnectionFactory* connectionFactory, const HostAddressPort& proxy) : connectionFactory_(connectionFactory), proxy_(proxy), server_(HostAddressPort(HostAddress("0.0.0.0"), 0)) { +	connected_ = false; +} + +SOCKS5ProxiedConnection::~SOCKS5ProxiedConnection() { +	if (connection_) { +		connection_->onDataRead.disconnect(boost::bind(&SOCKS5ProxiedConnection::handleDataRead, shared_from_this(), _1)); +		connection_->onDisconnected.disconnect(boost::bind(&SOCKS5ProxiedConnection::handleDisconnected, shared_from_this(), _1)); +	} + +	if (connected_) { +		std::cerr << "Warning: Connection was still established." << std::endl; +	} +} + +void SOCKS5ProxiedConnection::connect(const HostAddressPort& server) { +	server_ = server; +	connection_ = connectionFactory_->createConnection(); +	connection_->onConnectFinished.connect(boost::bind(&SOCKS5ProxiedConnection::handleConnectionConnectFinished, shared_from_this(), _1)); +	connection_->onDataRead.connect(boost::bind(&SOCKS5ProxiedConnection::handleDataRead, shared_from_this(), _1)); +	connection_->onDisconnected.connect(boost::bind(&SOCKS5ProxiedConnection::handleDisconnected, shared_from_this(), _1)); +	SWIFT_LOG(debug) << "Trying to connect via proxy " << proxy_.getAddress().toString() << ":" << proxy_.getPort() << std::endl; +	SWIFT_LOG(debug) << "to server " << server.getAddress().toString() << ":" << server.getPort() << std::endl; +	connection_->connect(proxy_); +} + +void SOCKS5ProxiedConnection::listen() { +	assert(false); +	connection_->listen(); +} + +void SOCKS5ProxiedConnection::disconnect() { +	connected_ = false; +	if (connection_) { +		connection_->disconnect(); +	} +} + +void SOCKS5ProxiedConnection::handleDisconnected(const boost::optional<Error>& error) { +	onDisconnected(error); +} + +void SOCKS5ProxiedConnection::write(const SafeByteArray& data) { +	if (connection_) { +		connection_->write(data); +	} +} + +void SOCKS5ProxiedConnection::handleConnectionConnectFinished(bool error) { +	connection_->onConnectFinished.disconnect(boost::bind(&SOCKS5ProxiedConnection::handleConnectionConnectFinished, shared_from_this(), _1)); +	if (!error) { +		SWIFT_LOG(debug) << "Connection to proxy established, now connect to the server via it." << std::endl; +		 +		proxyState_ = ProxyAuthenticating; +		SafeByteArray socksConnect; +		socksConnect.push_back(0x05); // VER = SOCKS5 = 0x05 +		socksConnect.push_back(0x01); // Number of authentication methods after this byte. +		socksConnect.push_back(0x00); // 0x00 == no authentication +		// buffer.push_back(0x01); // 0x01 == GSSAPI  +		// buffer.push_back(0x02); // 0x02 ==  Username/Password +		// rest see RFC 1928 (http://tools.ietf.org/html/rfc1928) +		connection_->write(socksConnect); +	} +	else { +		onConnectFinished(true); +	} +} + +void SOCKS5ProxiedConnection::handleDataRead(const SafeByteArray& data) { +	SafeByteArray socksConnect; +	boost::asio::ip::address rawAddress = server_.getAddress().getRawAddress(); +	assert(rawAddress.is_v4() || rawAddress.is_v6()); +	if (!connected_) { +		if (proxyState_ == ProxyAuthenticating) { +			SWIFT_LOG(debug) << "ProxyAuthenticating response received, reply with the connect BYTEs" << std::endl; +			unsigned char choosenMethod = static_cast<unsigned char> (data[1]); +			if (data[0] == 0x05 && choosenMethod != 0xFF) { +				switch(choosenMethod) { // use the correct Method +					case 0x00: +						try { +							proxyState_ = ProxyConnecting; +							socksConnect.push_back(0x05); // VER = SOCKS5 = 0x05 +							socksConnect.push_back(0x01); // Construct a TCP connection. (CMD) +							socksConnect.push_back(0x00); // reserved. +							socksConnect.push_back(rawAddress.is_v4() ? 0x01 : 0x04); // IPv4 == 0x01, Hostname == 0x02, IPv6 == 0x04. (ATYP) +							size_t size = rawAddress.is_v4() ? rawAddress.to_v4().to_bytes().size() : rawAddress.to_v6().to_bytes().size(); +							for (size_t s = 0; s < size; s++) { +								unsigned char uc; +								if(rawAddress.is_v4()) { +									uc = rawAddress.to_v4().to_bytes()[s]; // the address. +								} +								else { +									uc = rawAddress.to_v6().to_bytes()[s]; // the address. +								} +								socksConnect.push_back(static_cast<char>(uc)); +						 +							} +							socksConnect.push_back(static_cast<unsigned char> ((server_.getPort() >> 8) & 0xFF)); // highbyte of the port. +							socksConnect.push_back(static_cast<unsigned char> (server_.getPort() & 0xFF)); // lowbyte of the port. +							connection_->write(socksConnect); +							return; +						} +						catch(...) { +							std::cerr << "exception caught" << std::endl; +						} +						connection_->write(socksConnect); +						break; +					default: +						onConnectFinished(true); +						break; +				} +				return; +			} +		} +		else if (proxyState_ == ProxyConnecting) { +			SWIFT_LOG(debug) << "Connect response received, check if successfully." << std::endl; +			SWIFT_LOG(debug) << "Errorbyte: 0x" << std::hex << static_cast<int> (data[1]) << std::dec << std::endl; +			/* + +			data.at(1) can be one of the following: +			0x00 	succeeded +			0x01 	general SOCKS server failure +			0x02 	connection not allowed by ruleset +			0x03 	Network unreachable +			0x04 	Host unreachable +			0x05 	Connection refused +			0x06 	TTL expired +			0x07 	Command not supported (CMD) +			0x08 	Address type not supported (ATYP) +			0x09 bis 0xFF 	unassigned +			*/ +			if (data[0] == 0x05 && data[1] == 0x0) { +				SWIFT_LOG(debug) << "Successfully connected the server via the proxy." << std::endl; +				connected_ = true; +				onConnectFinished(false); +				return; +			} +			else { +				std::cerr << "SOCKS Proxy returned an error: " << std::hex << data[1] << std::endl; +			} +			return; +		} +	} +	else { +		onDataRead(data); +		return; +	} +	disconnect(); +	onConnectFinished(true); +} + +HostAddressPort SOCKS5ProxiedConnection::getLocalAddress() const { +	return connection_->getLocalAddress(); +} diff --git a/Swiften/Network/SOCKS5ProxiedConnection.h b/Swiften/Network/SOCKS5ProxiedConnection.h new file mode 100644 index 0000000..942b6ce --- /dev/null +++ b/Swiften/Network/SOCKS5ProxiedConnection.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2010-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> + +namespace boost { +	class thread; +	namespace system { +		class error_code; +	} +} + +namespace Swift { +	class ConnectionFactory; + +	class SOCKS5ProxiedConnection : public Connection, public boost::enable_shared_from_this<SOCKS5ProxiedConnection> { +		public: +			typedef boost::shared_ptr<SOCKS5ProxiedConnection> ref; + +			~SOCKS5ProxiedConnection(); + +			static ref create(ConnectionFactory* connectionFactory, const HostAddressPort& proxy) { +				return ref(new SOCKS5ProxiedConnection(connectionFactory, proxy)); +			} + +			virtual void listen(); +			virtual void connect(const HostAddressPort& address); +			virtual void disconnect(); +			virtual void write(const SafeByteArray& data); + +			virtual HostAddressPort getLocalAddress() const; + +		private: +			SOCKS5ProxiedConnection(ConnectionFactory* connectionFactory, const HostAddressPort& proxy); + +			void handleConnectionConnectFinished(bool error); +			void handleDataRead(const SafeByteArray& data); +			void handleDisconnected(const boost::optional<Error>& error); + +		private: +			enum { +				ProxyAuthenticating = 0, +				ProxyConnecting, +			} proxyState_; +			bool connected_; +			ConnectionFactory* connectionFactory_;	 +			HostAddressPort proxy_; +			HostAddressPort server_; +			boost::shared_ptr<Connection> connection_; +	}; +} diff --git a/Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp b/Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp new file mode 100644 index 0000000..272ade9 --- /dev/null +++ b/Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2010-2011 Thilo Cestonaro + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Network/SOCKS5ProxiedConnectionFactory.h> + +#include <Swiften/Network/SOCKS5ProxiedConnection.h> + +namespace Swift { + +SOCKS5ProxiedConnectionFactory::SOCKS5ProxiedConnectionFactory(ConnectionFactory* connectionFactory, const HostAddressPort& proxy) : connectionFactory_(connectionFactory), proxy_(proxy) { +} + +boost::shared_ptr<Connection> SOCKS5ProxiedConnectionFactory::createConnection() { +	return SOCKS5ProxiedConnection::create(connectionFactory_, proxy_); +} + +} diff --git a/Swiften/Network/SOCKS5ProxiedConnectionFactory.h b/Swiften/Network/SOCKS5ProxiedConnectionFactory.h new file mode 100644 index 0000000..f36d42a --- /dev/null +++ b/Swiften/Network/SOCKS5ProxiedConnectionFactory.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2010-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 SOCKS5ProxiedConnectionFactory : public ConnectionFactory { +		public: +			SOCKS5ProxiedConnectionFactory(ConnectionFactory* connectionFactory, const HostAddressPort& proxy); + +			virtual boost::shared_ptr<Connection> createConnection(); + +		private: +			ConnectionFactory* connectionFactory_; +			HostAddressPort proxy_; +	}; +} diff --git a/Swiften/Network/StaticDomainNameResolver.cpp b/Swiften/Network/StaticDomainNameResolver.cpp index a338272..76ab411 100644 --- a/Swiften/Network/StaticDomainNameResolver.cpp +++ b/Swiften/Network/StaticDomainNameResolver.cpp @@ -4,12 +4,12 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/Network/StaticDomainNameResolver.h" +#include <Swiften/Network/StaticDomainNameResolver.h>  #include <boost/bind.hpp>  #include <boost/lexical_cast.hpp> -#include "Swiften/Network/DomainNameResolveError.h" +#include <Swiften/Network/DomainNameResolveError.h>  #include <string>  using namespace Swift; diff --git a/Swiften/Network/StaticDomainNameResolver.h b/Swiften/Network/StaticDomainNameResolver.h index 2ef1295..a72db7c 100644 --- a/Swiften/Network/StaticDomainNameResolver.h +++ b/Swiften/Network/StaticDomainNameResolver.h @@ -9,12 +9,12 @@  #include <vector>  #include <map> -#include "Swiften/Network/HostAddress.h" -#include "Swiften/Network/HostAddressPort.h" -#include "Swiften/Network/DomainNameResolver.h" -#include "Swiften/Network/DomainNameServiceQuery.h" -#include "Swiften/Network/DomainNameAddressQuery.h" -#include "Swiften/EventLoop/EventLoop.h" +#include <Swiften/Network/HostAddress.h> +#include <Swiften/Network/HostAddressPort.h> +#include <Swiften/Network/DomainNameResolver.h> +#include <Swiften/Network/DomainNameServiceQuery.h> +#include <Swiften/Network/DomainNameAddressQuery.h> +#include <Swiften/EventLoop/EventLoop.h>  namespace Swift { diff --git a/Swiften/Network/Timer.cpp b/Swiften/Network/Timer.cpp index daa4490..3efbd3b 100644 --- a/Swiften/Network/Timer.cpp +++ b/Swiften/Network/Timer.cpp @@ -4,7 +4,7 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/Network/Timer.h" +#include <Swiften/Network/Timer.h>  namespace Swift { diff --git a/Swiften/Network/Timer.h b/Swiften/Network/Timer.h index d44a00d..b7578f2 100644 --- a/Swiften/Network/Timer.h +++ b/Swiften/Network/Timer.h @@ -6,7 +6,7 @@  #pragma once -#include "Swiften/Base/boost_bsignals.h" +#include <Swiften/Base/boost_bsignals.h>  namespace Swift {  	/** diff --git a/Swiften/Network/TimerFactory.cpp b/Swiften/Network/TimerFactory.cpp index 502f669..3fb807c 100644 --- a/Swiften/Network/TimerFactory.cpp +++ b/Swiften/Network/TimerFactory.cpp @@ -4,7 +4,7 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/Network/TimerFactory.h" +#include <Swiften/Network/TimerFactory.h>  namespace Swift { diff --git a/Swiften/Network/TimerFactory.h b/Swiften/Network/TimerFactory.h index 44c87b6..99903c3 100644 --- a/Swiften/Network/TimerFactory.h +++ b/Swiften/Network/TimerFactory.h @@ -8,7 +8,7 @@  #include <boost/shared_ptr.hpp> -#include "Swiften/Network/Timer.h" +#include <Swiften/Network/Timer.h>  namespace Swift {  	class TimerFactory { diff --git a/Swiften/Network/UnitTest/ChainedConnectorTest.cpp b/Swiften/Network/UnitTest/ChainedConnectorTest.cpp new file mode 100644 index 0000000..c7d23da --- /dev/null +++ b/Swiften/Network/UnitTest/ChainedConnectorTest.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <boost/bind.hpp> +#include <boost/smart_ptr/make_shared.hpp> + +#include <Swiften/Network/ChainedConnector.h> +#include <Swiften/Network/Connection.h> +#include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Network/HostAddressPort.h> +#include <Swiften/Network/StaticDomainNameResolver.h> +#include <Swiften/Network/DummyTimerFactory.h> +#include <Swiften/EventLoop/DummyEventLoop.h> + +using namespace Swift; + +class ChainedConnectorTest : public CppUnit::TestFixture { +		CPPUNIT_TEST_SUITE(ChainedConnectorTest); +		CPPUNIT_TEST(testConnect_FirstConnectorSucceeds); +		CPPUNIT_TEST(testConnect_SecondConnectorSucceeds); +		CPPUNIT_TEST(testConnect_NoConnectorSucceeds); +		CPPUNIT_TEST(testStop); +		CPPUNIT_TEST_SUITE_END(); + +	public: +		void setUp() { +			host = HostAddressPort(HostAddress("1.1.1.1"), 1234); +			eventLoop = new DummyEventLoop(); +			resolver = new StaticDomainNameResolver(eventLoop); +			resolver->addXMPPClientService("foo.com", host); +			connectionFactory1 = new MockConnectionFactory(eventLoop, 1); +			connectionFactory2 = new MockConnectionFactory(eventLoop, 2); +			timerFactory = new DummyTimerFactory(); +		} + +		void tearDown() { +			delete timerFactory; +			delete connectionFactory2; +			delete connectionFactory1; +			delete resolver; +			delete eventLoop; +		} + +		void testConnect_FirstConnectorSucceeds() { +			boost::shared_ptr<ChainedConnector> testling(createConnector()); +			connectionFactory1->connects = true; +			connectionFactory2->connects = false; + +			testling->start(); +			eventLoop->processEvents(); + +			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); +			CPPUNIT_ASSERT(connections[0]); +			CPPUNIT_ASSERT_EQUAL(1, boost::dynamic_pointer_cast<MockConnection>(connections[0])->id); +		} + +		void testConnect_SecondConnectorSucceeds() { +			boost::shared_ptr<ChainedConnector> testling(createConnector()); +			connectionFactory1->connects = false; +			connectionFactory2->connects = true; + +			testling->start(); +			eventLoop->processEvents(); + +			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); +			CPPUNIT_ASSERT(connections[0]); +			CPPUNIT_ASSERT_EQUAL(2, boost::dynamic_pointer_cast<MockConnection>(connections[0])->id); +		} + +		void testConnect_NoConnectorSucceeds() { +			boost::shared_ptr<ChainedConnector> testling(createConnector()); +			connectionFactory1->connects = false; +			connectionFactory2->connects = false; + +			testling->start(); +			eventLoop->processEvents(); + +			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); +			CPPUNIT_ASSERT(!connections[0]); +		} + +		void testStop() { +			boost::shared_ptr<ChainedConnector> testling(createConnector()); +			connectionFactory1->connects = true; +			connectionFactory2->connects = false; + +			testling->start(); +			testling->stop(); +			eventLoop->processEvents(); + +			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); +			CPPUNIT_ASSERT(!connections[0]); +		} + +	private: +		boost::shared_ptr<ChainedConnector> createConnector() { +			std::vector<ConnectionFactory*> factories; +			factories.push_back(connectionFactory1); +			factories.push_back(connectionFactory2); +			boost::shared_ptr<ChainedConnector> connector = boost::make_shared<ChainedConnector>("foo.com", resolver, factories, timerFactory); +			connector->onConnectFinished.connect(boost::bind(&ChainedConnectorTest::handleConnectorFinished, this, _1)); +			return connector; +		} + +		void handleConnectorFinished(boost::shared_ptr<Connection> connection) { +			boost::shared_ptr<MockConnection> c(boost::dynamic_pointer_cast<MockConnection>(connection)); +			if (connection) { +				assert(c); +			} +			connections.push_back(c); +		} + +		struct MockConnection : public Connection { +			public: +				MockConnection(bool connects, int id, EventLoop* eventLoop) : connects(connects), id(id), eventLoop(eventLoop) { +				} + +				void listen() { assert(false); } +				void connect(const HostAddressPort&) { +					eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), !connects)); +				} + +				HostAddressPort getLocalAddress() const { return HostAddressPort(); } +				void disconnect() { assert(false); } +				void write(const SafeByteArray&) { assert(false); } + +				bool connects; +				int id; +				EventLoop* eventLoop; +		}; + +		struct MockConnectionFactory : public ConnectionFactory { +			MockConnectionFactory(EventLoop* eventLoop, int id) : eventLoop(eventLoop), connects(true), id(id) { +			} + +			boost::shared_ptr<Connection> createConnection() { +				return boost::make_shared<MockConnection>(connects, id, eventLoop); +			} + +			EventLoop* eventLoop; +			bool connects; +			int id; +		}; + +	private: +		HostAddressPort host; +		DummyEventLoop* eventLoop; +		StaticDomainNameResolver* resolver; +		MockConnectionFactory* connectionFactory1; +		MockConnectionFactory* connectionFactory2; +		DummyTimerFactory* timerFactory; +		std::vector< boost::shared_ptr<MockConnection> > connections; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(ChainedConnectorTest); diff --git a/Swiften/Network/UnitTest/ConnectorTest.cpp b/Swiften/Network/UnitTest/ConnectorTest.cpp index c8aa9a9..6488e67 100644 --- a/Swiften/Network/UnitTest/ConnectorTest.cpp +++ b/Swiften/Network/UnitTest/ConnectorTest.cpp @@ -10,13 +10,13 @@  #include <boost/optional.hpp>  #include <boost/bind.hpp> -#include "Swiften/Network/Connector.h" -#include "Swiften/Network/Connection.h" -#include "Swiften/Network/ConnectionFactory.h" -#include "Swiften/Network/HostAddressPort.h" -#include "Swiften/Network/StaticDomainNameResolver.h" -#include "Swiften/Network/DummyTimerFactory.h" -#include "Swiften/EventLoop/DummyEventLoop.h" +#include <Swiften/Network/Connector.h> +#include <Swiften/Network/Connection.h> +#include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Network/HostAddressPort.h> +#include <Swiften/Network/StaticDomainNameResolver.h> +#include <Swiften/Network/DummyTimerFactory.h> +#include <Swiften/EventLoop/DummyEventLoop.h>  using namespace Swift; @@ -269,7 +269,7 @@ class ConnectorTest : public CppUnit::TestFixture {  				HostAddressPort getLocalAddress() const { return HostAddressPort(); }  				void disconnect() { assert(false); } -				void write(const ByteArray&) { assert(false); } +				void write(const SafeByteArray&) { assert(false); }  				EventLoop* eventLoop;  				boost::optional<HostAddressPort> hostAddressPort; diff --git a/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp b/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp new file mode 100644 index 0000000..48189ab --- /dev/null +++ b/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ +#include <QA/Checker/IO.h> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <boost/optional.hpp> +#include <boost/bind.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <boost/shared_ptr.hpp> + +#include <Swiften/Base/Algorithm.h> +#include <Swiften/Network/Connection.h> +#include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Network/HTTPConnectProxiedConnection.h> +#include <Swiften/Network/HostAddressPort.h> +#include <Swiften/EventLoop/DummyEventLoop.h> + +using namespace Swift; + +class HTTPConnectProxiedConnectionTest : public CppUnit::TestFixture { +		CPPUNIT_TEST_SUITE(HTTPConnectProxiedConnectionTest); +		CPPUNIT_TEST(testConnect_CreatesConnectionToProxy); +		CPPUNIT_TEST(testConnect_SendsConnectRequest); +		CPPUNIT_TEST(testConnect_ReceiveConnectResponse); +		CPPUNIT_TEST(testConnect_ReceiveMalformedConnectResponse); +		CPPUNIT_TEST(testConnect_ReceiveErrorConnectResponse); +		CPPUNIT_TEST(testConnect_ReceiveDataAfterConnect); +		CPPUNIT_TEST(testWrite_AfterConnect); +		CPPUNIT_TEST(testDisconnect_AfterConnectRequest); +		CPPUNIT_TEST(testDisconnect_AfterConnect); +		CPPUNIT_TEST_SUITE_END(); + +	public: +		void setUp() { +			proxyHost = HostAddressPort(HostAddress("1.1.1.1"), 1234); +			host = HostAddressPort(HostAddress("2.2.2.2"), 2345); +			eventLoop = new DummyEventLoop(); +			connectionFactory = new MockConnectionFactory(eventLoop); +			connectFinished = false; +			disconnected = false; +		} + +		void tearDown() { +			delete connectionFactory; +			delete eventLoop; +		} + +		void testConnect_CreatesConnectionToProxy() { +			HTTPConnectProxiedConnection::ref testling(createTestling()); + +			testling->connect(host); +			eventLoop->processEvents(); + +			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connectionFactory->connections.size())); +			CPPUNIT_ASSERT(connectionFactory->connections[0]->hostAddressPort); +			CPPUNIT_ASSERT(proxyHost == *connectionFactory->connections[0]->hostAddressPort); +			CPPUNIT_ASSERT(!connectFinished); +		} + +		void testConnect_SendsConnectRequest() { +			HTTPConnectProxiedConnection::ref testling(createTestling()); + +			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345)); +			eventLoop->processEvents(); + +			CPPUNIT_ASSERT_EQUAL(createByteArray("CONNECT 2.2.2.2:2345 HTTP/1.1\r\n\r\n"), connectionFactory->connections[0]->dataWritten); +		} + +		void testConnect_ReceiveConnectResponse() { +			HTTPConnectProxiedConnection::ref testling(createTestling()); +			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345)); +			eventLoop->processEvents(); + +			connectionFactory->connections[0]->onDataRead(createSafeByteArray("HTTP/1.0 200 Connection established\r\n\r\n")); +			eventLoop->processEvents(); + +			CPPUNIT_ASSERT(connectFinished); +			CPPUNIT_ASSERT(!connectFinishedWithError); +			CPPUNIT_ASSERT(dataRead.empty()); +		} + +		void testConnect_ReceiveMalformedConnectResponse() { +			HTTPConnectProxiedConnection::ref testling(createTestling()); +			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345)); +			eventLoop->processEvents(); + +			connectionFactory->connections[0]->onDataRead(createSafeByteArray("FLOOP")); +			eventLoop->processEvents(); + +			CPPUNIT_ASSERT(connectFinished); +			CPPUNIT_ASSERT(connectFinishedWithError); +			CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected); +		} + +		void testConnect_ReceiveErrorConnectResponse() { +			HTTPConnectProxiedConnection::ref testling(createTestling()); +			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345)); +			eventLoop->processEvents(); + +			connectionFactory->connections[0]->onDataRead(createSafeByteArray("HTTP/1.0 401 Unauthorized\r\n\r\n")); +			eventLoop->processEvents(); + +			CPPUNIT_ASSERT(connectFinished); +			CPPUNIT_ASSERT(connectFinishedWithError); +			CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected); +		} + +		void testConnect_ReceiveDataAfterConnect() { +			HTTPConnectProxiedConnection::ref testling(createTestling()); +			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345)); +			eventLoop->processEvents(); +			connectionFactory->connections[0]->onDataRead(createSafeByteArray("HTTP/1.0 200 Connection established\r\n\r\n")); +			eventLoop->processEvents(); + +			connectionFactory->connections[0]->onDataRead(createSafeByteArray("abcdef")); + +			CPPUNIT_ASSERT_EQUAL(createByteArray("abcdef"), dataRead); +		} + +		void testWrite_AfterConnect() { +			HTTPConnectProxiedConnection::ref testling(createTestling()); +			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345)); +			eventLoop->processEvents(); +			connectionFactory->connections[0]->onDataRead(createSafeByteArray("HTTP/1.0 200 Connection established\r\n\r\n")); +			eventLoop->processEvents(); +			connectionFactory->connections[0]->dataWritten.clear(); + +			testling->write(createSafeByteArray("abcdef")); + +			CPPUNIT_ASSERT_EQUAL(createByteArray("abcdef"), connectionFactory->connections[0]->dataWritten); +		} + +		void testDisconnect_AfterConnectRequest() { +			HTTPConnectProxiedConnection::ref testling(createTestling()); +			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345)); +			eventLoop->processEvents(); + +			testling->disconnect(); + +			CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected); +			CPPUNIT_ASSERT(disconnected); +			CPPUNIT_ASSERT(!disconnectedError); +		} + +		void testDisconnect_AfterConnect() { +			HTTPConnectProxiedConnection::ref testling(createTestling()); +			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345)); +			eventLoop->processEvents(); +			connectionFactory->connections[0]->onDataRead(createSafeByteArray("HTTP/1.0 200 Connection established\r\n\r\n")); +			eventLoop->processEvents(); + +			testling->disconnect(); + +			CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected); +			CPPUNIT_ASSERT(disconnected); +			CPPUNIT_ASSERT(!disconnectedError); +		} + +	private: +		HTTPConnectProxiedConnection::ref createTestling() { +			boost::shared_ptr<HTTPConnectProxiedConnection> c = HTTPConnectProxiedConnection::create(connectionFactory, proxyHost); +			c->onConnectFinished.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleConnectFinished, this, _1)); +			c->onDisconnected.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleDisconnected, this, _1)); +			c->onDataRead.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleDataRead, this, _1)); +			return c; +		} + +		void handleConnectFinished(bool error) { +			connectFinished = true; +			connectFinishedWithError = error; +		} + +		void handleDisconnected(const boost::optional<Connection::Error>& e) { +			disconnected = true; +			disconnectedError = e; +		} + +		void handleDataRead(const SafeByteArray& d) { +			append(dataRead, d); +		} + +		struct MockConnection : public Connection { +			public: +				MockConnection(const std::vector<HostAddressPort>& failingPorts, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), disconnected(false) { +				} + +				void listen() { assert(false); } + +				void connect(const HostAddressPort& address) { +					hostAddressPort = address; +					bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end(); +					eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail)); +				} + +				HostAddressPort getLocalAddress() const { return HostAddressPort(); } + +				void disconnect() {  +					disconnected = true; +					onDisconnected(boost::optional<Connection::Error>()); +				} +				 +				void write(const SafeByteArray& d) { +					append(dataWritten, d); +				} + +				EventLoop* eventLoop; +				boost::optional<HostAddressPort> hostAddressPort; +				std::vector<HostAddressPort> failingPorts; +				ByteArray dataWritten; +				bool disconnected; +		}; + +		struct MockConnectionFactory : public ConnectionFactory { +			MockConnectionFactory(EventLoop* eventLoop) : eventLoop(eventLoop) { +			} + +			boost::shared_ptr<Connection> createConnection() { +				boost::shared_ptr<MockConnection> connection = boost::make_shared<MockConnection>(failingPorts, eventLoop); +				connections.push_back(connection); +				return connection; +			} + +			EventLoop* eventLoop; +			std::vector< boost::shared_ptr<MockConnection> > connections; +			std::vector<HostAddressPort> failingPorts; +		}; + +	private: +		HostAddressPort proxyHost; +		HostAddressPort host; +		DummyEventLoop* eventLoop; +		MockConnectionFactory* connectionFactory; +		std::vector< boost::shared_ptr<MockConnection> > connections; +		bool connectFinished; +		bool connectFinishedWithError; +		bool disconnected; +		boost::optional<Connection::Error> disconnectedError; +		ByteArray dataRead; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(HTTPConnectProxiedConnectionTest); diff --git a/Swiften/Network/UnitTest/HostAddressTest.cpp b/Swiften/Network/UnitTest/HostAddressTest.cpp index 7fb33ca..b2511a8 100644 --- a/Swiften/Network/UnitTest/HostAddressTest.cpp +++ b/Swiften/Network/UnitTest/HostAddressTest.cpp @@ -7,7 +7,7 @@  #include <cppunit/extensions/HelperMacros.h>  #include <cppunit/extensions/TestFactoryRegistry.h> -#include "Swiften/Network/HostAddress.h" +#include <Swiften/Network/HostAddress.h>  #include <string>  using namespace Swift; diff --git a/Swiften/Network/UnixProxyProvider.cpp b/Swiften/Network/UnixProxyProvider.cpp new file mode 100644 index 0000000..4ca9311 --- /dev/null +++ b/Swiften/Network/UnixProxyProvider.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2010-2011 Thilo Cestonaro + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <iostream> + +#include <Swiften/Base/foreach.h> +#include <Swiften/Network/UnixProxyProvider.h> +#if defined(HAVE_GCONF) +#  include "Swiften/Network/GConfProxyProvider.h" +#endif + +namespace Swift { + +UnixProxyProvider::UnixProxyProvider() : +	gconfProxyProvider(0), +	environmentProxyProvider() +{ +#if defined(HAVE_GCONF) +	gconfProxyProvider = new GConfProxyProvider(); +#endif +} + +UnixProxyProvider::~UnixProxyProvider() { +#if defined(HAVE_GCONF) +	delete gconfProxyProvider; +#endif +} + +HostAddressPort UnixProxyProvider::getSOCKS5Proxy() const { +	HostAddressPort proxy; +#if defined(HAVE_GCONF) +	proxy = gconfProxyProvider->getSOCKS5Proxy(); +	if(proxy.isValid()) { +		return proxy; +	} +#endif +	proxy = environmentProxyProvider.getSOCKS5Proxy(); +	if(proxy.isValid()) { +		return proxy; +	} +	return HostAddressPort(HostAddress(), 0); +} + +HostAddressPort UnixProxyProvider::getHTTPConnectProxy() const { +	HostAddressPort proxy; +#if defined(HAVE_GCONF) +	proxy = gconfProxyProvider->getHTTPConnectProxy(); +	if(proxy.isValid()) { +		return proxy; +	} +#endif +	proxy = environmentProxyProvider.getHTTPConnectProxy(); +	if(proxy.isValid()) { +		return proxy; +	} +	return HostAddressPort(HostAddress(), 0); +} + + +} diff --git a/Swiften/Network/UnixProxyProvider.h b/Swiften/Network/UnixProxyProvider.h new file mode 100644 index 0000000..37a4d05 --- /dev/null +++ b/Swiften/Network/UnixProxyProvider.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2010-2011 Thilo Cestonaro + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Network/EnvironmentProxyProvider.h> + +namespace Swift { +	class GConfProxyProvider; + +	class UnixProxyProvider : public ProxyProvider { +		public: +			UnixProxyProvider(); +			~UnixProxyProvider(); + +			virtual HostAddressPort getHTTPConnectProxy() const; +			virtual HostAddressPort getSOCKS5Proxy() const; + +		private: +			GConfProxyProvider* gconfProxyProvider; +			EnvironmentProxyProvider environmentProxyProvider; +	}; +} diff --git a/Swiften/Network/WindowsProxyProvider.cpp b/Swiften/Network/WindowsProxyProvider.cpp new file mode 100644 index 0000000..3ae43e0 --- /dev/null +++ b/Swiften/Network/WindowsProxyProvider.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2010-2011 Thilo Cestonaro + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <iostream> +#include <boost/lexical_cast.hpp> + +#include <Swiften/Base/log.h> +#include <Swiften/Base/foreach.h> +#include <Swiften/Network/WindowsProxyProvider.h> +#include <Swiften/Base/ByteArray.h> + +#include <windows.h> + +namespace Swift { + +WindowsProxyProvider::WindowsProxyProvider() +: ProxyProvider() +{ +	HKEY hKey = (HKEY)INVALID_HANDLE_VALUE; +	long result; +		 +	result = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", 0, KEY_READ, &hKey); +	if (result == ERROR_SUCCESS && hKey != INVALID_HANDLE_VALUE && proxyEnabled(hKey)) { +		DWORD dataType = REG_SZ; +		DWORD dataSize = 0; +		ByteArray dataBuffer; + +		result = RegQueryValueEx(hKey, "ProxyServer", NULL, &dataType, NULL, &dataSize); +		if(result != ERROR_SUCCESS) { +			return; +		} +		dataBuffer.resize(dataSize); +		result = RegQueryValueEx(hKey, "ProxyServer", NULL, &dataType, reinterpret_cast<BYTE*>(vecptr(dataBuffer)), &dataSize); +		if(result == ERROR_SUCCESS) { +			std::vector<std::string> proxies = String::split(byteArrayToString(dataBuffer), ';'); +			std::pair<std::string, std::string> protocolAndProxy; +			foreach(std::string proxy, proxies) { +				if(proxy.find('=') != std::string::npos) { +					protocolAndProxy = String::getSplittedAtFirst(proxy, '='); +					SWIFT_LOG(debug) << "Found proxy: " << protocolAndProxy.first << " => " << protocolAndProxy.second << std::endl; +					if(protocolAndProxy.first.compare("socks") == 0) { +						socksProxy = getAsHostAddressPort(protocolAndProxy.second); +					} +					else if (protocolAndProxy.first.compare("http") == 0) { +						httpProxy = getAsHostAddressPort(protocolAndProxy.second); +					} +				} +			} +		} +	} +} + +HostAddressPort WindowsProxyProvider::getHTTPConnectProxy() const { +	return httpProxy; +} + +HostAddressPort WindowsProxyProvider::getSOCKS5Proxy() const { +	return socksProxy; +} + +HostAddressPort WindowsProxyProvider::getAsHostAddressPort(std::string proxy) { +	HostAddressPort ret(HostAddress(), 0); + +	try { +		std::pair<std::string, std::string> tmp; +		int port = 0; +		tmp = String::getSplittedAtFirst(proxy, ':'); +		// .c_str() is needed as tmp.second can include a \0 char which will end in an exception of the lexical cast. +		// with .c_str() the \0 will not be part of the string which is to be casted +		port = boost::lexical_cast<int> (tmp.second.c_str()); +		ret = HostAddressPort(HostAddress(tmp.first), port); +	} +	catch(...) { +			std::cerr << "Exception occured while parsing windows proxy \"getHostAddressPort\"." << std::endl; +	} + +	return ret; +} + + +bool WindowsProxyProvider::proxyEnabled(HKEY hKey) const { +	bool ret = false; +	long result; +	DWORD dataType = REG_DWORD; +	DWORD dataSize = 0; +	DWORD data = 0; +	ByteArray dataBuffer; + +	if(hKey == INVALID_HANDLE_VALUE) +		return ret; + +	result = RegQueryValueEx(hKey, "ProxyEnable", NULL, &dataType, NULL, &dataSize); +	if(result != ERROR_SUCCESS) +		return ret; + +	dataBuffer.resize(dataSize); +	result = RegQueryValueEx(hKey, "ProxyEnable", NULL, &dataType, reinterpret_cast<BYTE*>(vecptr(dataBuffer)), &dataSize); +	if(result != ERROR_SUCCESS) +		return ret; + +	for(size_t t = 0; t < dataBuffer.size(); t++) { +		data += static_cast<int> (dataBuffer[t]) * pow(256, static_cast<double>(t)); +	} +	return (data == 1); +} + +} diff --git a/Swiften/Network/WindowsProxyProvider.h b/Swiften/Network/WindowsProxyProvider.h new file mode 100644 index 0000000..c2d1f51 --- /dev/null +++ b/Swiften/Network/WindowsProxyProvider.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2010-2011 Thilo Cestonaro + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once +#include <Swiften/Network/ProxyProvider.h> + +namespace Swift { +	class WindowsProxyProvider : public ProxyProvider { +		public: +			WindowsProxyProvider(); +			virtual HostAddressPort getHTTPConnectProxy() const; +			virtual HostAddressPort getSOCKS5Proxy() const; +		private: +			HostAddressPort getAsHostAddressPort(std::string proxy); +			bool proxyEnabled(HKEY hKey) const; +			HostAddressPort socksProxy; +			HostAddressPort httpProxy; +	}; +} | 
 Swift
 Swift