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; + }; +} |