diff options
Diffstat (limited to 'Swiften/Network')
-rw-r--r-- | Swiften/Network/BoostConnectionServer.cpp | 48 | ||||
-rw-r--r-- | Swiften/Network/BoostConnectionServer.h | 13 | ||||
-rw-r--r-- | Swiften/Network/FakeConnection.h | 88 | ||||
-rw-r--r-- | Swiften/Network/HostAddress.cpp | 12 | ||||
-rw-r--r-- | Swiften/Network/HostAddress.h | 8 | ||||
-rw-r--r-- | Swiften/Network/UnitTest/HostAddressTest.cpp | 11 |
6 files changed, 166 insertions, 14 deletions
diff --git a/Swiften/Network/BoostConnectionServer.cpp b/Swiften/Network/BoostConnectionServer.cpp index 18a3ca4..4e83ad5 100644 --- a/Swiften/Network/BoostConnectionServer.cpp +++ b/Swiften/Network/BoostConnectionServer.cpp @@ -1,28 +1,64 @@ #include "Swiften/Network/BoostConnectionServer.h" #include <boost/bind.hpp> +#include <boost/system/system_error.hpp> #include "Swiften/EventLoop/MainEventLoop.h" namespace Swift { -BoostConnectionServer::BoostConnectionServer(int port, boost::asio::io_service* ioService) : acceptor_(*ioService, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)) { +BoostConnectionServer::BoostConnectionServer(int port, boost::asio::io_service* ioService) : port_(port), ioService_(ioService), acceptor_(NULL) { } void BoostConnectionServer::start() { - acceptNextConnection(); + try { + assert(!acceptor_); + acceptor_ = new boost::asio::ip::tcp::acceptor( + *ioService_, + boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port_)); + acceptNextConnection(); + } + catch (const boost::system::system_error& e) { + if (e.code() == boost::asio::error::address_in_use) { + MainEventLoop::postEvent(boost::bind(boost::ref(onStopped), Conflict), shared_from_this()); + } + else { + MainEventLoop::postEvent(boost::bind(boost::ref(onStopped), UnknownError), shared_from_this()); + } + } +} + + +void BoostConnectionServer::stop() { + stop(boost::optional<Error>()); +} + +void BoostConnectionServer::stop(boost::optional<Error> e) { + if (acceptor_) { + acceptor_->close(); + acceptor_ = NULL; + } + MainEventLoop::postEvent(boost::bind(boost::ref(onStopped), e), shared_from_this()); } void BoostConnectionServer::acceptNextConnection() { - boost::shared_ptr<BoostConnection> newConnection(new BoostConnection(&acceptor_.io_service())); - acceptor_.async_accept(newConnection->getSocket(), + boost::shared_ptr<BoostConnection> newConnection(new BoostConnection(&acceptor_->io_service())); + acceptor_->async_accept(newConnection->getSocket(), boost::bind(&BoostConnectionServer::handleAccept, shared_from_this(), newConnection, boost::asio::placeholders::error)); } void BoostConnectionServer::handleAccept(boost::shared_ptr<BoostConnection> newConnection, const boost::system::error_code& error) { - if (!error) { - MainEventLoop::postEvent(boost::bind(boost::ref(onNewConnection), newConnection), shared_from_this()); + if (error) { + MainEventLoop::postEvent( + boost::bind( + &BoostConnectionServer::stop, shared_from_this(), UnknownError), + shared_from_this()); + } + else { + MainEventLoop::postEvent( + boost::bind(boost::ref(onNewConnection), newConnection), + shared_from_this()); newConnection->listen(); acceptNextConnection(); } diff --git a/Swiften/Network/BoostConnectionServer.h b/Swiften/Network/BoostConnectionServer.h index c92318e..d8e5eb4 100644 --- a/Swiften/Network/BoostConnectionServer.h +++ b/Swiften/Network/BoostConnectionServer.h @@ -3,6 +3,7 @@ #include <boost/shared_ptr.hpp> #include <boost/enable_shared_from_this.hpp> #include <boost/asio.hpp> +#include <boost/signal.hpp> #include "Swiften/Network/BoostConnection.h" #include "Swiften/Network/ConnectionServer.h" @@ -11,15 +12,25 @@ namespace Swift { class BoostConnectionServer : public ConnectionServer, public EventOwner, public boost::enable_shared_from_this<BoostConnectionServer> { public: + enum Error { + Conflict, + UnknownError + }; BoostConnectionServer(int port, boost::asio::io_service* ioService); void start(); + void stop(); + + boost::signal<void (boost::optional<Error>)> onStopped; private: + void stop(boost::optional<Error> e); void acceptNextConnection(); void handleAccept(boost::shared_ptr<BoostConnection> newConnection, const boost::system::error_code& error); private: - boost::asio::ip::tcp::acceptor acceptor_; + int port_; + boost::asio::io_service* ioService_; + boost::asio::ip::tcp::acceptor* acceptor_; }; } diff --git a/Swiften/Network/FakeConnection.h b/Swiften/Network/FakeConnection.h new file mode 100644 index 0000000..92a03c3 --- /dev/null +++ b/Swiften/Network/FakeConnection.h @@ -0,0 +1,88 @@ +#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/MainEventLoop.h" + +namespace Swift { + class FakeConnection : + public Connection, + public EventOwner, + public boost::enable_shared_from_this<FakeConnection> { + public: + enum State { + Initial, + Connecting, + Connected, + Disconnected, + DisconnectedWithError + }; + + FakeConnection() : state(Initial), delayConnect(false) {} + + virtual void listen() { + assert(false); + } + + void setError(const Error& e) { + error = boost::optional<Error>(e); + state = DisconnectedWithError; + if (connectedTo) { + MainEventLoop::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; + } + MainEventLoop::postEvent( + boost::bind(boost::ref(onConnectFinished), error), + shared_from_this()); + } + } + + virtual void disconnect() { + if (!error) { + state = Disconnected; + } + else { + state = DisconnectedWithError; + } + connectedTo.reset(); + MainEventLoop::postEvent( + boost::bind(boost::ref(onDisconnected), error), + shared_from_this()); + } + + virtual void write(const ByteArray& data) { + dataWritten.push_back(data); + } + + void setDelayConnect() { + delayConnect = true; + } + + boost::optional<HostAddressPort> connectedTo; + std::vector<ByteArray> dataWritten; + boost::optional<Error> error; + State state; + bool delayConnect; + }; +} diff --git a/Swiften/Network/HostAddress.cpp b/Swiften/Network/HostAddress.cpp index 84a0012..ea324cb 100644 --- a/Swiften/Network/HostAddress.cpp +++ b/Swiften/Network/HostAddress.cpp @@ -1,10 +1,14 @@ #include "Swiften/Network/HostAddress.h" #include <boost/numeric/conversion/cast.hpp> +#include <boost/lexical_cast.hpp> #include <cassert> #include <sstream> #include <iomanip> +#include "Swiften/Base/foreach.h" +#include "Swiften/Base/String.h" + namespace Swift { HostAddress::HostAddress() { @@ -13,6 +17,14 @@ HostAddress::HostAddress() { } } +HostAddress::HostAddress(const String& address) { + std::vector<String> components = address.split('.'); + assert(components.size() == 4); + foreach(const String& component, components) { + address_.push_back(boost::lexical_cast<int>(component.getUTF8String())); + } +} + HostAddress::HostAddress(const unsigned char* address, int length) { assert(length == 4 || length == 16); address_.reserve(length); diff --git a/Swiften/Network/HostAddress.h b/Swiften/Network/HostAddress.h index 2c9760d..fa34df4 100644 --- a/Swiften/Network/HostAddress.h +++ b/Swiften/Network/HostAddress.h @@ -1,13 +1,15 @@ -#ifndef SWIFTEN_HOSTADDRESS -#define SWIFTEN_HOSTADDRESS +#pragma once #include <string> #include <vector> namespace Swift { + class String; + class HostAddress { public: HostAddress(); + HostAddress(const String&); HostAddress(const unsigned char* address, int length); const std::vector<unsigned char>& getRawAddress() const { @@ -20,5 +22,3 @@ namespace Swift { std::vector<unsigned char> address_; }; } - -#endif diff --git a/Swiften/Network/UnitTest/HostAddressTest.cpp b/Swiften/Network/UnitTest/HostAddressTest.cpp index b805647..50e9198 100644 --- a/Swiften/Network/UnitTest/HostAddressTest.cpp +++ b/Swiften/Network/UnitTest/HostAddressTest.cpp @@ -2,18 +2,23 @@ #include <cppunit/extensions/TestFactoryRegistry.h> #include "Swiften/Network/HostAddress.h" +#include "Swiften/Base/String.h" using namespace Swift; -class HostAddressTest : public CppUnit::TestFixture -{ +class HostAddressTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(HostAddressTest); + CPPUNIT_TEST(testConstructor); CPPUNIT_TEST(testToString); CPPUNIT_TEST(testToString_IPv6); CPPUNIT_TEST_SUITE_END(); public: - HostAddressTest() {} + void testConstructor() { + HostAddress testling("192.168.1.254"); + + CPPUNIT_ASSERT_EQUAL(std::string("192.168.1.254"), testling.toString()); + } void testToString() { unsigned char address[4] = {10, 0, 1, 253}; |