summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2009-07-14 17:27:32 (GMT)
committerRemko Tronçon <git@el-tramo.be>2009-07-14 17:27:32 (GMT)
commitee3a46975986865fe5064f9d87a27277fc6c235a (patch)
tree51bae2ed1669ca881f761ca7547fbaf22432ae12
parentc34f50d3371f47c88d2ee927a5d59af8e135304c (diff)
downloadswift-contrib-ee3a46975986865fe5064f9d87a27277fc6c235a.zip
swift-contrib-ee3a46975986865fe5064f9d87a27277fc6c235a.tar.bz2
Consolidating IncomingConnection & Connection.
BoostConnections no longer have their own thread, but are managed from a central Boost IO thread instead.
-rw-r--r--Limber/main.cpp91
-rw-r--r--Swift/Controllers/MainController.cpp1
-rw-r--r--Swiften/Client/Client.cpp7
-rw-r--r--Swiften/Client/Client.h30
-rw-r--r--Swiften/Client/ClientError.h1
-rw-r--r--Swiften/Client/Session.cpp7
-rw-r--r--Swiften/Client/Session.h1
-rw-r--r--Swiften/Client/UnitTest/SessionTest.cpp75
-rw-r--r--Swiften/Network/BoostConnection.cpp85
-rw-r--r--Swiften/Network/BoostConnection.h23
-rw-r--r--Swiften/Network/BoostConnectionFactory.cpp6
-rw-r--r--Swiften/Network/BoostConnectionFactory.h9
-rw-r--r--Swiften/Network/Connection.h16
-rw-r--r--Swiften/Network/ConnectionFactory.h3
-rw-r--r--Swiften/Network/ConnectionServer.h4
-rw-r--r--Swiften/Network/IncomingConnection.cpp8
-rw-r--r--Swiften/Network/IncomingConnection.h17
-rw-r--r--Swiften/Network/Makefile.inc1
-rw-r--r--Swiften/QA/ClientTest/Makefile.inc1
-rw-r--r--Swiften/QA/NetworkTest/BoostConnectionTest.cpp50
-rw-r--r--Swiften/QA/NetworkTest/Makefile.inc1
-rw-r--r--Swiften/Server/IncomingConnection.cpp8
-rw-r--r--Swiften/Server/IncomingConnection.h24
-rw-r--r--Swiften/Server/Makefile.inc1
-rw-r--r--Swiften/Server/ServerFromClientSession.cpp8
-rw-r--r--Swiften/Server/ServerFromClientSession.h10
-rw-r--r--Swiften/StreamStack/IncomingConnectionLayer.h22
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_;
- };
-}