diff options
Diffstat (limited to 'Swiften')
-rw-r--r-- | Swiften/Network/BoostConnectionServer.cpp | 48 | ||||
-rw-r--r-- | Swiften/Network/BoostConnectionServer.h | 13 | ||||
-rw-r--r-- | Swiften/QA/NetworkTest/BoostConnectionServerTest.cpp | 72 | ||||
-rw-r--r-- | Swiften/QA/NetworkTest/Makefile.inc | 1 |
4 files changed, 127 insertions, 7 deletions
diff --git a/Swiften/Network/BoostConnectionServer.cpp b/Swiften/Network/BoostConnectionServer.cpp index 18a3ca4..596761a 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) { + onStopped(Conflict); + } + else { + onStopped(UnknownError); + } + } +} + + +void BoostConnectionServer::stop() { + stop(boost::optional<Error>()); +} + +void BoostConnectionServer::stop(boost::optional<Error> e) { + if (acceptor_) { + acceptor_->close(); + acceptor_ = NULL; + } + onStopped(e); } 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/QA/NetworkTest/BoostConnectionServerTest.cpp b/Swiften/QA/NetworkTest/BoostConnectionServerTest.cpp new file mode 100644 index 0000000..a5c51aa --- /dev/null +++ b/Swiften/QA/NetworkTest/BoostConnectionServerTest.cpp @@ -0,0 +1,72 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> +#include <boost/shared_ptr.hpp> + +#include "Swiften/Base/String.h" +#include "Swiften/Network/BoostConnectionServer.h" +#include "Swiften/Network/BoostIOServiceThread.h" +#include "Swiften/EventLoop/DummyEventLoop.h" + +using namespace Swift; + +class BoostConnectionServerTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(BoostConnectionServerTest); + CPPUNIT_TEST(testConstructor_TwoServersOnSamePort); + CPPUNIT_TEST(testStart_Conflict); + CPPUNIT_TEST(testStop); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + boostIOServiceThread_ = new BoostIOServiceThread(); + eventLoop_ = new DummyEventLoop(); + stopped = false; + stoppedError.reset(); + } + + void tearDown() { + delete eventLoop_; + delete boostIOServiceThread_; + } + + void testConstructor_TwoServersOnSamePort() { + boost::shared_ptr<BoostConnectionServer> testling(new BoostConnectionServer(9999, &boostIOServiceThread_->getIOService())); + boost::shared_ptr<BoostConnectionServer> testling2(new BoostConnectionServer(9999, &boostIOServiceThread_->getIOService())); + } + + void testStart_Conflict() { + boost::shared_ptr<BoostConnectionServer> testling(new BoostConnectionServer(9999, &boostIOServiceThread_->getIOService())); + testling->start(); + + boost::shared_ptr<BoostConnectionServer> testling2(new BoostConnectionServer(9999, &boostIOServiceThread_->getIOService())); + testling2->onStopped.connect( + boost::bind(&BoostConnectionServerTest::handleStopped, this, _1)); + + testling->stop(); + } + + void testStop() { + boost::shared_ptr<BoostConnectionServer> testling(new BoostConnectionServer(9999, &boostIOServiceThread_->getIOService())); + testling->start(); + + testling->stop(); + + boost::shared_ptr<BoostConnectionServer> testling2(new BoostConnectionServer(9999, &boostIOServiceThread_->getIOService())); + testling2->start(); + + testling2->stop(); + } + + void handleStopped(boost::optional<BoostConnectionServer::Error> e) { + stopped = true; + stoppedError = e; + } + + private: + BoostIOServiceThread* boostIOServiceThread_; + DummyEventLoop* eventLoop_; + bool stopped; + boost::optional<BoostConnectionServer::Error> stoppedError; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(BoostConnectionServerTest); diff --git a/Swiften/QA/NetworkTest/Makefile.inc b/Swiften/QA/NetworkTest/Makefile.inc index b263cdb..57c97a1 100644 --- a/Swiften/QA/NetworkTest/Makefile.inc +++ b/Swiften/QA/NetworkTest/Makefile.inc @@ -2,6 +2,7 @@ NETWORKTEST_TARGET += Swiften/QA/NetworkTest/checker NETWORKTEST_SOURCES += \ Swiften/QA/NetworkTest/DomainNameResolverTest.cpp \ Swiften/QA/NetworkTest/BoostConnectionTest.cpp \ + Swiften/QA/NetworkTest/BoostConnectionServerTest.cpp \ QA/UnitTest/checker.cpp NETWORKTEST_OBJECTS = \ $(NETWORKTEST_SOURCES:.cpp=.o) |