diff options
author | Remko Tronçon <git@el-tramo.be> | 2009-07-14 17:27:32 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2009-07-14 17:27:32 (GMT) |
commit | ee3a46975986865fe5064f9d87a27277fc6c235a (patch) | |
tree | 51bae2ed1669ca881f761ca7547fbaf22432ae12 | |
parent | c34f50d3371f47c88d2ee927a5d59af8e135304c (diff) | |
download | swift-ee3a46975986865fe5064f9d87a27277fc6c235a.zip swift-ee3a46975986865fe5064f9d87a27277fc6c235a.tar.bz2 |
Consolidating IncomingConnection & Connection.
BoostConnections no longer have their own thread, but are managed from
a central Boost IO thread instead.
27 files changed, 189 insertions, 321 deletions
diff --git a/Limber/main.cpp b/Limber/main.cpp index be7387e..200f2e4 100644 --- a/Limber/main.cpp +++ b/Limber/main.cpp @@ -1,12 +1,8 @@ - #include <iostream> #include <string> #include <boost/asio.hpp> -#include <boost/signal.hpp> #include <boost/bind.hpp> #include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> -#include <boost/thread.hpp> #include "Swiften/Elements/IQ.h" #include "Swiften/Elements/RosterPayload.h" @@ -18,6 +14,7 @@ #include "Swiften/EventLoop/SimpleEventLoop.h" #include "Swiften/Elements/Stanza.h" #include "Swiften/Network/ConnectionServer.h" +#include "Swiften/Network/BoostConnection.h" #include "Swiften/Network/BoostIOServiceThread.h" #include "Swiften/Server/ServerFromClientSession.h" #include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h" @@ -25,82 +22,6 @@ using namespace Swift; -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())), - buffer_(boost::asio::buffer(*data_)) { - } - - // ConstBufferSequence requirements. - typedef boost::asio::const_buffer value_type; - typedef const boost::asio::const_buffer* const_iterator; - const boost::asio::const_buffer* begin() const { return &buffer_; } - const boost::asio::const_buffer* end() const { return &buffer_ + 1; } - - private: - boost::shared_ptr< std::vector<char> > data_; - boost::asio::const_buffer buffer_; -}; - -class IncomingBoostConnection : public IncomingConnection, public boost::enable_shared_from_this<IncomingBoostConnection> { - public: - typedef boost::shared_ptr<IncomingBoostConnection> pointer; - - static pointer create(boost::asio::io_service& ioService) { - return pointer(new IncomingBoostConnection(ioService)); - } - - boost::asio::ip::tcp::socket& getSocket() { - return socket_; - } - - void write(const ByteArray& data) { - boost::asio::async_write(socket_, SharedBuffer(data), - boost::bind( - &IncomingBoostConnection::handleDataWritten, - shared_from_this(), - boost::asio::placeholders::error)); - } - - void start() { - read(); - } - - private: - IncomingBoostConnection(boost::asio::io_service& ioService) : socket_(ioService), readBuffer_(BUFFER_SIZE) { - } - - void read() { - socket_.async_read_some( - boost::asio::buffer(readBuffer_), - boost::bind(&IncomingBoostConnection::handleDataRead, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); - } - - void handleDataRead(const boost::system::error_code& error, size_t bytesTransferred) { - if (!error) { - MainEventLoop::postEvent(boost::bind(boost::ref(onDataRead), ByteArray(&readBuffer_[0], bytesTransferred)), this); - read(); - } - else if (error != boost::asio::error::operation_aborted) { - //MainEventLoop::postEvent(boost::bind(boost::ref(onError), ReadError), this); - } - } - - void handleDataWritten(const boost::system::error_code& error) { - if (error && error != boost::asio::error::operation_aborted) { - //std::cerr << "ERROR: Unable to write data to socket" << std::endl; - //MainEventLoop::postEvent(boost::bind(boost::ref(onError), ReadError), this); - } - } - - boost::asio::ip::tcp::socket socket_; - std::vector<char> readBuffer_; -}; - class BoostConnectionServer : public ConnectionServer { public: BoostConnectionServer(int port, boost::asio::io_service& ioService) : acceptor_(ioService, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)) { @@ -109,15 +30,15 @@ class BoostConnectionServer : public ConnectionServer { private: void acceptNextConnection() { - IncomingBoostConnection::pointer newConnection = IncomingBoostConnection::create(acceptor_.io_service()); + boost::shared_ptr<BoostConnection> newConnection(new BoostConnection(&acceptor_.io_service())); acceptor_.async_accept(newConnection->getSocket(), boost::bind(&BoostConnectionServer::handleAccept, this, newConnection, boost::asio::placeholders::error)); } - void handleAccept(IncomingBoostConnection::pointer newConnection, const boost::system::error_code& error) { + void handleAccept(boost::shared_ptr<BoostConnection> newConnection, const boost::system::error_code& error) { if (!error) { MainEventLoop::postEvent(boost::bind(boost::ref(onNewConnection), newConnection), this); - newConnection->start(); + newConnection->listen(); acceptNextConnection(); } } @@ -137,7 +58,7 @@ class Server { } private: - void handleNewConnection(boost::shared_ptr<IncomingConnection> c) { + void handleNewConnection(boost::shared_ptr<Connection> c) { ServerFromClientSession* session = new ServerFromClientSession(idGenerator_.generateID(), c, &payloadParserFactories_, &payloadSerializers_, userRegistry_); serverFromClientSessions_.push_back(session); session->onStanzaReceived.connect(boost::bind(&Server::handleStanzaReceived, this, _1, session)); @@ -192,5 +113,5 @@ int main() { userRegistry.addUser(JID("remko@limber"), "pass"); Server server(&userRegistry); eventLoop.run(); - return 0; + return 0; } diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp index 1af689c..77e531e 100644 --- a/Swift/Controllers/MainController.cpp +++ b/Swift/Controllers/MainController.cpp @@ -209,6 +209,7 @@ void MainController::handleError(const ClientError& error) { case ClientError::DomainNameResolveError: message = "Unable to find server"; break; case ClientError::ConnectionError: message = "Error connecting to server"; break; case ClientError::ConnectionReadError: message = "Error while receiving server data"; break; + case ClientError::ConnectionWriteError: message = "Error while sending data to the server"; break; case ClientError::XMLError: message = "Error parsing server data"; break; case ClientError::AuthenticationFailedError: message = "Login/password invalid"; break; case ClientError::NoSupportedAuthMechanismsError: message = "Authentication mechanisms not supported"; break; diff --git a/Swiften/Client/Client.cpp b/Swiften/Client/Client.cpp index e5bbf9d..d87673b 100644 --- a/Swiften/Client/Client.cpp +++ b/Swiften/Client/Client.cpp @@ -11,14 +11,14 @@ namespace Swift { Client::Client(const JID& jid, const String& password) : IQRouter(this), jid_(jid), password_(password), session_(0) { - connectionFactory_ = new BoostConnectionFactory(); + connectionFactory_ = new BoostConnectionFactory(&boostIOServiceThread_.getIOService()); tlsLayerFactory_ = new PlatformTLSLayerFactory(); } Client::~Client() { delete session_; delete tlsLayerFactory_; - delete connectionFactory_; + delete connectionFactory_; } void Client::connect() { @@ -101,6 +101,9 @@ void Client::handleSessionError(Session::SessionError error) { case Session::ConnectionReadError: clientError = ClientError(ClientError::ConnectionReadError); break; + case Session::ConnectionWriteError: + clientError = ClientError(ClientError::ConnectionWriteError); + break; case Session::XMLError: clientError = ClientError(ClientError::XMLError); break; diff --git a/Swiften/Client/Client.h b/Swiften/Client/Client.h index 946bdbd..d876302 100644 --- a/Swiften/Client/Client.h +++ b/Swiften/Client/Client.h @@ -15,44 +15,46 @@ #include "Swiften/Queries/IQRouter.h" #include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h" #include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h" +#include "Swiften/Network/BoostIOServiceThread.h" namespace Swift { class TLSLayerFactory; class ConnectionFactory; class Session; - class Client : public StanzaChannel, public IQRouter { - public: - Client(const JID& jid, const String& password); - ~Client(); + class Client : public StanzaChannel, public IQRouter { + public: + Client(const JID& jid, const String& password); + ~Client(); void setCertificate(const String& certificate); - void connect(); + void connect(); void disconnect(); - virtual void sendIQ(boost::shared_ptr<IQ>); + virtual void sendIQ(boost::shared_ptr<IQ>); virtual void sendMessage(boost::shared_ptr<Message>); virtual void sendPresence(boost::shared_ptr<Presence>); - public: - boost::signal<void (ClientError)> onError; - boost::signal<void ()> onConnected; + public: + boost::signal<void (ClientError)> onError; + boost::signal<void ()> onConnected; boost::signal<void (const String&)> onDataRead; boost::signal<void (const String&)> onDataWritten; private: - void send(boost::shared_ptr<Stanza>); - virtual String getNewIQID(); + void send(boost::shared_ptr<Stanza>); + virtual String getNewIQID(); void handleElement(boost::shared_ptr<Element>); void handleSessionError(Session::SessionError error); void handleNeedCredentials(); void handleDataRead(const ByteArray&); void handleDataWritten(const ByteArray&); - private: + private: + BoostIOServiceThread boostIOServiceThread_; JID jid_; - String password_; + String password_; IDGenerator idGenerator_; ConnectionFactory* connectionFactory_; TLSLayerFactory* tlsLayerFactory_; @@ -60,7 +62,7 @@ namespace Swift { FullPayloadSerializerCollection payloadSerializers_; Session* session_; String certificate_; - }; + }; } #endif diff --git a/Swiften/Client/ClientError.h b/Swiften/Client/ClientError.h index 38f20c0..d81cc0e 100644 --- a/Swiften/Client/ClientError.h +++ b/Swiften/Client/ClientError.h @@ -9,6 +9,7 @@ namespace Swift { DomainNameResolveError, ConnectionError, ConnectionReadError, + ConnectionWriteError, XMLError, AuthenticationFailedError, NoSupportedAuthMechanismsError, diff --git a/Swiften/Client/Session.cpp b/Swiften/Client/Session.cpp index c4adfa0..1ae97d6 100644 --- a/Swiften/Client/Session.cpp +++ b/Swiften/Client/Session.cpp @@ -52,10 +52,10 @@ Session::~Session() { void Session::start() { assert(state_ == Initial); state_ = Connecting; - connection_ = connectionFactory_->createConnection(jid_.getDomain()); + connection_ = connectionFactory_->createConnection(); connection_->onConnected.connect(boost::bind(&Session::handleConnected, this)); connection_->onError.connect(boost::bind(&Session::handleConnectionError, this, _1)); - connection_->connect(); + connection_->connect(jid_.getDomain()); } void Session::stop() { @@ -93,6 +93,9 @@ void Session::handleConnectionError(Connection::Error error) { case Connection::ReadError: setError(ConnectionReadError); break; + case Connection::WriteError: + setError(ConnectionWriteError); + break; case Connection::ConnectionError: setError(ConnectionError); break; diff --git a/Swiften/Client/Session.h b/Swiften/Client/Session.h index c49d877..516cb5a 100644 --- a/Swiften/Client/Session.h +++ b/Swiften/Client/Session.h @@ -43,6 +43,7 @@ namespace Swift { DomainNameResolveError, ConnectionError, ConnectionReadError, + ConnectionWriteError, XMLError, AuthenticationFailedError, NoSupportedAuthMechanismsError, diff --git a/Swiften/Client/UnitTest/SessionTest.cpp b/Swiften/Client/UnitTest/SessionTest.cpp index c2b99db..da05a06 100644 --- a/Swiften/Client/UnitTest/SessionTest.cpp +++ b/Swiften/Client/UnitTest/SessionTest.cpp @@ -57,9 +57,9 @@ class SessionTest : public CppUnit::TestFixture { CPPUNIT_TEST(testSessionStart); CPPUNIT_TEST(testSessionStart_Error); CPPUNIT_TEST(testSessionStart_AfterResourceBind); - CPPUNIT_TEST(testWhitespacePing); + CPPUNIT_TEST(testWhitespacePing); CPPUNIT_TEST(testReceiveElementAfterSessionStarted); - CPPUNIT_TEST(testSendElement); + CPPUNIT_TEST(testSendElement); CPPUNIT_TEST_SUITE_END(); public: @@ -74,8 +74,8 @@ class SessionTest : public CppUnit::TestFixture { } void tearDown() { - delete tlsLayerFactory_; - delete connectionFactory_; + delete tlsLayerFactory_; + delete connectionFactory_; delete eventLoop_; } @@ -250,7 +250,7 @@ class SessionTest : public CppUnit::TestFixture { CPPUNIT_ASSERT_EQUAL(Session::Negotiating, session->getState()); } - void testAuthenticate_Unauthorized() { + void testAuthenticate_Unauthorized() { std::auto_ptr<MockSession> session(createSession("me@foo.com/Bar")); session->start(); getMockServer()->expectStreamStart(); @@ -265,9 +265,9 @@ class SessionTest : public CppUnit::TestFixture { CPPUNIT_ASSERT_EQUAL(Session::Error, session->getState()); CPPUNIT_ASSERT_EQUAL(Session::AuthenticationFailedError, session->getError()); - } + } - void testAuthenticate_NoValidAuthMechanisms() { + void testAuthenticate_NoValidAuthMechanisms() { std::auto_ptr<MockSession> session(createSession("me@foo.com/Bar")); session->start(); getMockServer()->expectStreamStart(); @@ -277,7 +277,7 @@ class SessionTest : public CppUnit::TestFixture { CPPUNIT_ASSERT_EQUAL(Session::Error, session->getState()); CPPUNIT_ASSERT_EQUAL(Session::NoSupportedAuthMechanismsError, session->getError()); - } + } void testResourceBind() { std::auto_ptr<MockSession> session(createSession("me@foo.com/Bar")); @@ -389,7 +389,7 @@ class SessionTest : public CppUnit::TestFixture { CPPUNIT_ASSERT(sessionStarted_); } - void testWhitespacePing() { + void testWhitespacePing() { std::auto_ptr<MockSession> session(createSession("me@foo.com/Bar")); session->start(); getMockServer()->expectStreamStart(); @@ -397,7 +397,7 @@ class SessionTest : public CppUnit::TestFixture { getMockServer()->sendStreamFeatures(); processEvents(); CPPUNIT_ASSERT(session->getWhitespacePingLayer()); - } + } void testReceiveElementAfterSessionStarted() { std::auto_ptr<MockSession> session(createSession("me@foo.com/Bar")); @@ -407,11 +407,11 @@ class SessionTest : public CppUnit::TestFixture { getMockServer()->sendStreamFeatures(); processEvents(); - getMockServer()->expectMessage(); - session->sendElement(boost::shared_ptr<Message>(new Message())); + getMockServer()->expectMessage(); + session->sendElement(boost::shared_ptr<Message>(new Message())); } - void testSendElement() { + void testSendElement() { std::auto_ptr<MockSession> session(createSession("me@foo.com/Bar")); session->onElementReceived.connect(boost::bind(&SessionTest::addReceivedElement, this, _1)); session->start(); @@ -421,9 +421,9 @@ class SessionTest : public CppUnit::TestFixture { getMockServer()->sendMessage(); processEvents(); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(receivedElements_.size())); - CPPUNIT_ASSERT(boost::dynamic_pointer_cast<Message>(receivedElements_[0])); - } + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(receivedElements_.size())); + CPPUNIT_ASSERT(boost::dynamic_pointer_cast<Message>(receivedElements_[0])); + } private: struct MockConnection; @@ -446,9 +446,9 @@ class SessionTest : public CppUnit::TestFixture { needCredentials_ = true; } - void addReceivedElement(boost::shared_ptr<Element> element) { - receivedElements_.push_back(element); - } + void addReceivedElement(boost::shared_ptr<Element> element) { + receivedElements_.push_back(element); + } private: struct MockConnection : public Connection, public XMPPParserClient { @@ -463,12 +463,11 @@ class SessionTest : public CppUnit::TestFixture { direction(direction), type(type), element(element) {} Direction direction; - Type type; + Type type; boost::shared_ptr<Element> element; }; - MockConnection(const String& domain, bool fail) : - Connection(domain), + MockConnection(bool fail) : fail_(fail), resetParser_(false), parser_(0), @@ -476,18 +475,23 @@ class SessionTest : public CppUnit::TestFixture { parser_ = new XMPPParser(this, &payloadParserFactories_); } - ~MockConnection() { - delete parser_; - } + ~MockConnection() { + delete parser_; + } void disconnect() { } - void connect() { + void listen() { + assert(false); + } + + void connect(const String& domain) { if (fail_) { MainEventLoop::postEvent(boost::bind(boost::ref(onError), Connection::ConnectionError)); } else { + domain_ = domain; MainEventLoop::postEvent(boost::bind(boost::ref(onConnected))); } } @@ -510,7 +514,7 @@ class SessionTest : public CppUnit::TestFixture { } void handleStreamStart(const String&, const String& to, const String&) { - CPPUNIT_ASSERT_EQUAL(getDomain(), to); + CPPUNIT_ASSERT_EQUAL(domain_, to); handleEvent(Event::StreamStartEvent); } @@ -544,7 +548,7 @@ class SessionTest : public CppUnit::TestFixture { String serializeEvent(const Event& event) { switch (event.type) { case Event::StreamStartEvent: - return serializer_.serializeHeader("", getDomain(), ""); + return serializer_.serializeHeader("", domain_, ""); case Event::ElementEvent: return serializer_.serializeElement(event.element); case Event::StreamEndEvent: @@ -571,7 +575,7 @@ class SessionTest : public CppUnit::TestFixture { } void expectAuth(const String& user, const String& password) { - String s = String("") + '\0' + user + '\0' + password; + String s = String("") + '\0' + user + '\0' + password; events_.push_back(Event(Event::In, Event::ElementEvent, boost::shared_ptr<AuthRequest>(new AuthRequest("PLAIN", ByteArray(s.getUTF8Data(), s.getUTF8Size()))))); } @@ -584,10 +588,10 @@ class SessionTest : public CppUnit::TestFixture { void expectSessionStart(const String& id) { events_.push_back(Event(Event::In, Event::ElementEvent, IQ::createRequest(IQ::Set, JID(), id, boost::shared_ptr<StartSession>(new StartSession())))); } - - void expectMessage() { + + void expectMessage() { events_.push_back(Event(Event::In, Event::ElementEvent, boost::shared_ptr<Message>(new Message()))); - } + } void sendInvalidXML() { sendData("<invalid xml/>"); @@ -675,6 +679,7 @@ class SessionTest : public CppUnit::TestFixture { bool fail_; bool resetParser_; + String domain_; FullPayloadParserFactoryCollection payloadParserFactories_; FullPayloadSerializerCollection payloadSerializers_; XMPPParser* parser_; @@ -684,8 +689,8 @@ class SessionTest : public CppUnit::TestFixture { struct MockConnectionFactory : public ConnectionFactory { MockConnectionFactory() : fail_(false) {} - MockConnection* createConnection(const String& domain) { - MockConnection* result = new MockConnection(domain, fail_); + MockConnection* createConnection() { + MockConnection* result = new MockConnection(fail_); connections_.push_back(result); return result; } @@ -746,7 +751,7 @@ class SessionTest : public CppUnit::TestFixture { FullPayloadSerializerCollection payloadSerializers_; bool sessionStarted_; bool needCredentials_; - std::vector< boost::shared_ptr<Element> > receivedElements_; + std::vector< boost::shared_ptr<Element> > receivedElements_; typedef std::vector< boost::function<void ()> > EventQueue; EventQueue events_; }; diff --git a/Swiften/Network/BoostConnection.cpp b/Swiften/Network/BoostConnection.cpp index f055f6a..ec15c96 100644 --- a/Swiften/Network/BoostConnection.cpp +++ b/Swiften/Network/BoostConnection.cpp @@ -14,53 +14,67 @@ namespace Swift { static const size_t BUFFER_SIZE = 4096; -BoostConnection::BoostConnection(const String& domain) : - Connection(domain), ioService_(0), thread_(0), socket_(0), readBuffer_(BUFFER_SIZE) { - ioService_ = new boost::asio::io_service(); +// ----------------------------------------------------------------------------- + +// A reference-counted non-modifiable buffer class. +class SharedBuffer { + public: + SharedBuffer(const ByteArray& data) : + data_(new std::vector<char>(data.begin(), data.end())), + buffer_(boost::asio::buffer(*data_)) { + } + + // ConstBufferSequence requirements. + typedef boost::asio::const_buffer value_type; + typedef const boost::asio::const_buffer* const_iterator; + const boost::asio::const_buffer* begin() const { return &buffer_; } + const boost::asio::const_buffer* end() const { return &buffer_ + 1; } + + private: + boost::shared_ptr< std::vector<char> > data_; + boost::asio::const_buffer buffer_; +}; + +// ----------------------------------------------------------------------------- + +BoostConnection::BoostConnection(boost::asio::io_service* ioService) : + socket_(*ioService), readBuffer_(BUFFER_SIZE) { } BoostConnection::~BoostConnection() { MainEventLoop::removeEventsFromOwner(this); - ioService_->stop(); - thread_->join(); - delete socket_; - delete thread_; - delete ioService_; } -void BoostConnection::connect() { - thread_ = new boost::thread(boost::bind(&BoostConnection::doConnect, this)); +void BoostConnection::listen() { + doRead(); } -void BoostConnection::disconnect() { - if (ioService_) { - ioService_->post(boost::bind(&BoostConnection::doDisconnect, this)); - } -} - -void BoostConnection::write(const ByteArray& data) { - if (ioService_) { - ioService_->post(boost::bind(&BoostConnection::doWrite, this, data)); - } -} - -void BoostConnection::doConnect() { +void BoostConnection::connect(const String& domain) { DomainNameResolver resolver; try { - HostAddressPort addressPort = resolver.resolve(getDomain().getUTF8String()); - socket_ = new boost::asio::ip::tcp::socket(*ioService_); + HostAddressPort addressPort = resolver.resolve(domain.getUTF8String()); boost::asio::ip::tcp::endpoint endpoint( boost::asio::ip::address::from_string(addressPort.getAddress().toString()), addressPort.getPort()); - socket_->async_connect( + // Use shared_from_this + socket_.async_connect( endpoint, boost::bind(&BoostConnection::handleConnectFinished, this, boost::asio::placeholders::error)); - ioService_->run(); } catch (const DomainNameResolveException& e) { - MainEventLoop::postEvent(boost::bind(boost::ref(onError), DomainNameResolveError), this); + onError(DomainNameResolveError); } } +void BoostConnection::disconnect() { + socket_.close(); +} + +void BoostConnection::write(const ByteArray& data) { + // Use shared_from_this + boost::asio::async_write(socket_, SharedBuffer(data), + boost::bind(&BoostConnection::handleDataWritten, this, boost::asio::placeholders::error)); +} + void BoostConnection::handleConnectFinished(const boost::system::error_code& error) { if (!error) { MainEventLoop::postEvent(boost::bind(boost::ref(onConnected)), this); @@ -72,15 +86,12 @@ void BoostConnection::handleConnectFinished(const boost::system::error_code& err } void BoostConnection::doRead() { - socket_->async_read_some( - boost::asio::buffer(readBuffer_), + // Use shared_from_this + socket_.async_read_some( + boost::asio::buffer(readBuffer_), boost::bind(&BoostConnection::handleSocketRead, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } -void BoostConnection::doWrite(const ByteArray& data) { - boost::asio::write(*socket_, boost::asio::buffer(static_cast<const char*>(data.getData()), data.getSize())); -} - void BoostConnection::handleSocketRead(const boost::system::error_code& error, size_t bytesTransferred) { if (!error) { MainEventLoop::postEvent(boost::bind(boost::ref(onDataRead), ByteArray(&readBuffer_[0], bytesTransferred)), this); @@ -91,9 +102,9 @@ void BoostConnection::handleSocketRead(const boost::system::error_code& error, s } } -void BoostConnection::doDisconnect() { - if (socket_) { - socket_->close(); +void BoostConnection::handleDataWritten(const boost::system::error_code& error) { + if (error && error != boost::asio::error::operation_aborted) { + MainEventLoop::postEvent(boost::bind(boost::ref(onError), WriteError), this); } } diff --git a/Swiften/Network/BoostConnection.h b/Swiften/Network/BoostConnection.h index f8fa514..85de926 100644 --- a/Swiften/Network/BoostConnection.h +++ b/Swiften/Network/BoostConnection.h @@ -1,5 +1,4 @@ -#ifndef SWIFTEN_BoostConnection_H -#define SWIFTEN_BoostConnection_H +#pragma once #include <boost/asio.hpp> @@ -15,29 +14,27 @@ namespace boost { namespace Swift { class BoostConnection : public Connection { public: - BoostConnection(const String& domain); + BoostConnection(boost::asio::io_service* ioService); ~BoostConnection(); - virtual void connect(); + virtual void listen(); + virtual void connect(const String& domain); virtual void disconnect(); virtual void write(const ByteArray& data); - private: - void doConnect(); - void doDisconnect(); + boost::asio::ip::tcp::socket& getSocket() { + return socket_; + } + private: void handleConnectFinished(const boost::system::error_code& error); 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&); private: - boost::asio::io_service* ioService_; - boost::thread* thread_; - boost::asio::ip::tcp::socket* socket_; + boost::asio::ip::tcp::socket socket_; std::vector<char> readBuffer_; bool disconnecting_; }; } - -#endif diff --git a/Swiften/Network/BoostConnectionFactory.cpp b/Swiften/Network/BoostConnectionFactory.cpp index 9c542ac..a1bef15 100644 --- a/Swiften/Network/BoostConnectionFactory.cpp +++ b/Swiften/Network/BoostConnectionFactory.cpp @@ -2,11 +2,11 @@ namespace Swift { -BoostConnectionFactory::BoostConnectionFactory() { +BoostConnectionFactory::BoostConnectionFactory(boost::asio::io_service* ioService) : ioService(ioService) { } -BoostConnection* BoostConnectionFactory::createConnection(const String& domain) { - return new BoostConnection(domain); +BoostConnection* BoostConnectionFactory::createConnection() { + return new BoostConnection(ioService); } } diff --git a/Swiften/Network/BoostConnectionFactory.h b/Swiften/Network/BoostConnectionFactory.h index b6a27b2..d15770d 100644 --- a/Swiften/Network/BoostConnectionFactory.h +++ b/Swiften/Network/BoostConnectionFactory.h @@ -1,6 +1,8 @@ #ifndef SWIFTEN_BoostConnectionFactory_H #define SWIFTEN_BoostConnectionFactory_H +#include <boost/asio.hpp> + #include "Swiften/Network/ConnectionFactory.h" #include "Swiften/Network/BoostConnection.h" @@ -9,9 +11,12 @@ namespace Swift { class BoostConnectionFactory : public ConnectionFactory { public: - BoostConnectionFactory(); + BoostConnectionFactory(boost::asio::io_service*); + + virtual BoostConnection* createConnection(); - virtual BoostConnection* createConnection(const String& domain); + private: + boost::asio::io_service* ioService; }; } diff --git a/Swiften/Network/Connection.h b/Swiften/Network/Connection.h index 6d05eee..16d5d7b 100644 --- a/Swiften/Network/Connection.h +++ b/Swiften/Network/Connection.h @@ -12,13 +12,15 @@ namespace Swift { enum Error { DomainNameResolveError, ConnectionError, - ReadError + ReadError, + WriteError }; - Connection(const String& domain) : domain_(domain) {} + Connection() {} virtual ~Connection() {} - virtual void connect() = 0; + virtual void listen() = 0; + virtual void connect(const String& domain) = 0; virtual void disconnect() = 0; virtual void write(const ByteArray& data) = 0; @@ -26,14 +28,6 @@ namespace Swift { boost::signal<void ()> onConnected; boost::signal<void (Error)> onError; boost::signal<void (const ByteArray&)> onDataRead; - - protected: - const String& getDomain() const { - return domain_; - } - - private: - String domain_; }; } diff --git a/Swiften/Network/ConnectionFactory.h b/Swiften/Network/ConnectionFactory.h index 2af9ebf..ef4eec9 100644 --- a/Swiften/Network/ConnectionFactory.h +++ b/Swiften/Network/ConnectionFactory.h @@ -2,14 +2,13 @@ #define SWIFTEN_ConnectionFactory_H namespace Swift { - class String; class Connection; class ConnectionFactory { public: virtual ~ConnectionFactory(); - virtual Connection* createConnection(const String& domain) = 0; + virtual Connection* createConnection() = 0; }; } diff --git a/Swiften/Network/ConnectionServer.h b/Swiften/Network/ConnectionServer.h index d376308..539367d 100644 --- a/Swiften/Network/ConnectionServer.h +++ b/Swiften/Network/ConnectionServer.h @@ -3,13 +3,13 @@ #include <boost/shared_ptr.hpp> #include <boost/signal.hpp> -#include "Swiften/Network/IncomingConnection.h" +#include "Swiften/Network/Connection.h" namespace Swift { class ConnectionServer { public: virtual ~ConnectionServer(); - boost::signal<void (boost::shared_ptr<IncomingConnection>)> onNewConnection; + boost::signal<void (boost::shared_ptr<Connection>)> onNewConnection; }; } diff --git a/Swiften/Network/IncomingConnection.cpp b/Swiften/Network/IncomingConnection.cpp deleted file mode 100644 index 669f68e..0000000 --- a/Swiften/Network/IncomingConnection.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "Swiften/Network/IncomingConnection.h" - -namespace Swift { - -IncomingConnection::~IncomingConnection() { -} - -} diff --git a/Swiften/Network/IncomingConnection.h b/Swiften/Network/IncomingConnection.h deleted file mode 100644 index eaa2ad6..0000000 --- a/Swiften/Network/IncomingConnection.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include <boost/signal.hpp> - -#include "Swiften/Base/ByteArray.h" - -namespace Swift { - class IncomingConnection { - public: - virtual ~IncomingConnection(); - - virtual void write(const ByteArray& data) = 0; - - //boost::signal<void (Error)> onError; - boost::signal<void (const ByteArray&)> onDataRead; - }; -} diff --git a/Swiften/Network/Makefile.inc b/Swiften/Network/Makefile.inc index 3e4ece6..d8c1ee9 100644 --- a/Swiften/Network/Makefile.inc +++ b/Swiften/Network/Makefile.inc @@ -5,7 +5,6 @@ SWIFTEN_SOURCES += \ Swiften/Network/BoostConnection.cpp \ Swiften/Network/BoostConnectionFactory.cpp \ Swiften/Network/ConnectionServer.cpp \ - Swiften/Network/IncomingConnection.cpp \ Swiften/Network/BoostIOServiceThread.cpp \ Swiften/Network/Timer.cpp diff --git a/Swiften/QA/ClientTest/Makefile.inc b/Swiften/QA/ClientTest/Makefile.inc index 08a9b5b..16a87cf 100644 --- a/Swiften/QA/ClientTest/Makefile.inc +++ b/Swiften/QA/ClientTest/Makefile.inc @@ -7,6 +7,7 @@ CLIENTTEST_OBJECTS = \ TEST_TARGETS += ClientTest CLEANFILES += $(CLIENTTEST_OBJECTS) $(CLIENTTEST_TARGET) +DEPS += $(CLIENTTEST_SOURCES:.cpp=.dep) $(CLIENTTEST_TARGET): $(SWIFTEN_TARGET) $(CLIENTTEST_OBJECTS) $(BUNDLED_LIBS) $(QUIET_LINK)$(CXX) -o $(CLIENTTEST_TARGET) $(CLIENTTEST_OBJECTS) $(LDFLAGS) $(CPPCLIENT_LDFLAGS) $(SWIFTEN_TARGET) $(BUNDLED_LIBS) $(LIBS) diff --git a/Swiften/QA/NetworkTest/BoostConnectionTest.cpp b/Swiften/QA/NetworkTest/BoostConnectionTest.cpp index 639097a..6090a97 100644 --- a/Swiften/QA/NetworkTest/BoostConnectionTest.cpp +++ b/Swiften/QA/NetworkTest/BoostConnectionTest.cpp @@ -4,6 +4,7 @@ #include "Swiften/Base/String.h" #include "Swiften/Base/sleep.h" #include "Swiften/Network/BoostConnection.h" +#include "Swiften/Network/BoostIOServiceThread.h" #include "Swiften/EventLoop/DummyEventLoop.h" using namespace Swift; @@ -11,41 +12,44 @@ using namespace Swift; class BoostConnectionTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(BoostConnectionTest); CPPUNIT_TEST(testDestructor); - CPPUNIT_TEST(testDestructor_PendingEvents); + CPPUNIT_TEST(testDestructor_PendingEvents); CPPUNIT_TEST_SUITE_END(); public: BoostConnectionTest() {} - void setUp() { - eventLoop_ = new DummyEventLoop(); - } + void setUp() { + eventLoop_ = new DummyEventLoop(); + boostIOServiceThread_ = new BoostIOServiceThread(); + } - void tearDown() { - delete eventLoop_; - } + void tearDown() { + delete boostIOServiceThread_; + delete eventLoop_; + } void testDestructor() { - { - std::string domain("el-tramo.be"); - std::auto_ptr<BoostConnection> testling(new BoostConnection(domain)); - testling->connect(); - } - } + { + std::string domain("el-tramo.be"); + std::auto_ptr<BoostConnection> testling(new BoostConnection(&boostIOServiceThread_->getIOService())); + testling->connect(domain); + } + } void testDestructor_PendingEvents() { - { - std::auto_ptr<BoostConnection> testling(new BoostConnection("el-tramo.be")); - testling->connect(); - while (!eventLoop_->hasEvents()) { - Swift::sleep(10); - } - } - eventLoop_->processEvents(); + { + std::auto_ptr<BoostConnection> testling(new BoostConnection(&boostIOServiceThread_->getIOService())); + testling->connect("el-tramo.be"); + while (!eventLoop_->hasEvents()) { + Swift::sleep(10); + } + } + eventLoop_->processEvents(); } - private: - DummyEventLoop* eventLoop_; + private: + BoostIOServiceThread* boostIOServiceThread_; + DummyEventLoop* eventLoop_; }; CPPUNIT_TEST_SUITE_REGISTRATION(BoostConnectionTest); diff --git a/Swiften/QA/NetworkTest/Makefile.inc b/Swiften/QA/NetworkTest/Makefile.inc index 055937b..5ac14c0 100644 --- a/Swiften/QA/NetworkTest/Makefile.inc +++ b/Swiften/QA/NetworkTest/Makefile.inc @@ -9,6 +9,7 @@ NETWORKTEST_OBJECTS = \ TEST_TARGETS += NetworkTest CLEANFILES += $(NETWORKTEST_OBJECTS) $(NETWORKTEST_TARGET) +DEPS += $(NETWORKTEST_SOURCES:.cpp=.dep) $(NETWORKTEST_TARGET): $(SWIFTEN_TARGET) $(CPPUNIT_TARGET) $(NETWORKTEST_OBJECTS) $(BUNDLED_LIBS) $(QUIET_LINK)$(CXX) -o $(NETWORKTEST_TARGET) $(NETWORKTEST_OBJECTS) $(LDFLAGS) $(CPPNETWORK_LDFLAGS) $(SWIFTEN_TARGET) $(CPPUNIT_TARGET) $(BUNDLED_LIBS) $(LIBS) diff --git a/Swiften/Server/IncomingConnection.cpp b/Swiften/Server/IncomingConnection.cpp deleted file mode 100644 index e2317c8..0000000 --- a/Swiften/Server/IncomingConnection.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "Swiften/Server/IncomingConnection.h" - -namespace Swift { - -IncomingConnection::~IncomingConnection() { -} - -} diff --git a/Swiften/Server/IncomingConnection.h b/Swiften/Server/IncomingConnection.h deleted file mode 100644 index 6ef64e8..0000000 --- a/Swiften/Server/IncomingConnection.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include <boost/signals.hpp> - -#include "Swiften/Base/ByteArray.h" -#include "Swiften/Base/String.h" - -namespace Swift { - class IncomingConnection { - public: - enum Error { - ConnectionError, - ReadError - }; - - virtual ~IncomingConnection(); - - virtual void write(const ByteArray& data) = 0; - - public: - boost::signal<void (Error)> onError; - boost::signal<void (const ByteArray&)> onDataRead; - }; -} diff --git a/Swiften/Server/Makefile.inc b/Swiften/Server/Makefile.inc index ae10bd2..ae38335 100644 --- a/Swiften/Server/Makefile.inc +++ b/Swiften/Server/Makefile.inc @@ -2,7 +2,6 @@ SWIFTEN_SOURCES += \ Swiften/Server/ServerSession.cpp \ Swiften/Server/ServerFromClientSession.cpp \ Swiften/Server/ServerStanzaRouter.cpp \ - Swiften/Server/IncomingConnection.cpp \ Swiften/Server/UserRegistry.cpp \ Swiften/Server/SimpleUserRegistry.cpp diff --git a/Swiften/Server/ServerFromClientSession.cpp b/Swiften/Server/ServerFromClientSession.cpp index e6ba28a..612e667 100644 --- a/Swiften/Server/ServerFromClientSession.cpp +++ b/Swiften/Server/ServerFromClientSession.cpp @@ -3,9 +3,9 @@ #include <boost/bind.hpp> #include "Swiften/Server/UserRegistry.h" -#include "Swiften/Network/IncomingConnection.h" +#include "Swiften/Network/Connection.h" #include "Swiften/StreamStack/StreamStack.h" -#include "Swiften/StreamStack/IncomingConnectionLayer.h" +#include "Swiften/StreamStack/ConnectionLayer.h" #include "Swiften/StreamStack/XMPPLayer.h" #include "Swiften/Elements/StreamFeatures.h" #include "Swiften/Elements/ResourceBind.h" @@ -20,7 +20,7 @@ namespace Swift { ServerFromClientSession::ServerFromClientSession( const String& id, - boost::shared_ptr<IncomingConnection> connection, + boost::shared_ptr<Connection> connection, PayloadParserFactoryCollection* payloadParserFactories, PayloadSerializerCollection* payloadSerializers, UserRegistry* userRegistry) : @@ -42,7 +42,7 @@ ServerFromClientSession::ServerFromClientSession( boost::bind(boost::ref(onDataRead), _1)); xmppLayer_->onWriteData.connect( boost::bind(boost::ref(onDataWritten), _1)); - connectionLayer_ = new IncomingConnectionLayer(connection_.get()); + connectionLayer_ = new ConnectionLayer(connection_.get()); streamStack_ = new StreamStack(xmppLayer_, connectionLayer_); } diff --git a/Swiften/Server/ServerFromClientSession.h b/Swiften/Server/ServerFromClientSession.h index 6c74093..9c37b3d 100644 --- a/Swiften/Server/ServerFromClientSession.h +++ b/Swiften/Server/ServerFromClientSession.h @@ -14,15 +14,15 @@ namespace Swift { class StreamStack; class UserRegistry; class XMPPLayer; - class IncomingConnectionLayer; - class IncomingConnection; + class ConnectionLayer; + class Connection; class ByteArray; class ServerFromClientSession { public: ServerFromClientSession( const String& id, - boost::shared_ptr<IncomingConnection> connection, + boost::shared_ptr<Connection> connection, PayloadParserFactoryCollection* payloadParserFactories, PayloadSerializerCollection* payloadSerializers, UserRegistry* userRegistry); @@ -49,13 +49,13 @@ namespace Swift { private: String id_; - boost::shared_ptr<IncomingConnection> connection_; + boost::shared_ptr<Connection> connection_; PayloadParserFactoryCollection* payloadParserFactories_; PayloadSerializerCollection* payloadSerializers_; UserRegistry* userRegistry_; bool authenticated_; bool initialized_; - IncomingConnectionLayer* connectionLayer_; + ConnectionLayer* connectionLayer_; StreamStack* streamStack_; XMPPLayer* xmppLayer_; JID domain_; diff --git a/Swiften/StreamStack/IncomingConnectionLayer.h b/Swiften/StreamStack/IncomingConnectionLayer.h deleted file mode 100644 index c1a9eab..0000000 --- a/Swiften/StreamStack/IncomingConnectionLayer.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include <boost/signal.hpp> - -#include "Swiften/StreamStack/LowLayer.h" -#include "Swiften/Network/IncomingConnection.h" - -namespace Swift { - class IncomingConnectionLayer : public LowLayer { - public: - IncomingConnectionLayer(IncomingConnection* connection) : connection_(connection) { - connection_->onDataRead.connect(onDataRead); - } - - void writeData(const ByteArray& data) { - connection_->write(data); - } - - private: - IncomingConnection* connection_; - }; -} |