summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2009-07-17 19:15:54 (GMT)
committerRemko Tronçon <git@el-tramo.be>2009-07-17 19:15:54 (GMT)
commita328466bc492c50c443e406b9325542a75182327 (patch)
tree8388cb92845a20d5c495e5940f5f16a6b95363a3
parent436ae921afbc5c2b461ee9b2d8fa9b1c869ed274 (diff)
downloadswift-contrib-a328466bc492c50c443e406b9325542a75182327.zip
swift-contrib-a328466bc492c50c443e406b9325542a75182327.tar.bz2
Implemented clean session/connection shutdown.
-rw-r--r--Limber/main.cpp10
-rw-r--r--Nim/main.cpp12
-rw-r--r--Swiften/Client/Session.cpp32
-rw-r--r--Swiften/Client/Session.h2
-rw-r--r--Swiften/Client/UnitTest/SessionTest.cpp4
-rw-r--r--Swiften/LinkLocal/LinkLocalServiceInfo.cpp66
-rw-r--r--Swiften/LinkLocal/LinkLocalServiceInfo.h3
-rw-r--r--Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp16
-rw-r--r--Swiften/Network/BoostConnection.cpp19
-rw-r--r--Swiften/Network/Connection.h2
-rw-r--r--Swiften/Server/ServerFromClientSession.cpp20
-rw-r--r--Swiften/Server/ServerFromClientSession.h7
12 files changed, 151 insertions, 42 deletions
diff --git a/Limber/main.cpp b/Limber/main.cpp
index c478924..2a2197d 100644
--- a/Limber/main.cpp
+++ b/Limber/main.cpp
@@ -31,18 +31,18 @@ class Server {
private:
void handleNewConnection(boost::shared_ptr<Connection> c) {
- ServerFromClientSession* session = new ServerFromClientSession(idGenerator_.generateID(), c, &payloadParserFactories_, &payloadSerializers_, userRegistry_);
+ boost::shared_ptr<ServerFromClientSession> session(new ServerFromClientSession(idGenerator_.generateID(), c, &payloadParserFactories_, &payloadSerializers_, userRegistry_));
serverFromClientSessions_.push_back(session);
session->onStanzaReceived.connect(boost::bind(&Server::handleStanzaReceived, this, _1, session));
session->onSessionFinished.connect(boost::bind(&Server::handleSessionFinished, this, session));
+ session->start();
}
- void handleSessionFinished(ServerFromClientSession* session) {
+ void handleSessionFinished(boost::shared_ptr<ServerFromClientSession> session) {
serverFromClientSessions_.erase(std::remove(serverFromClientSessions_.begin(), serverFromClientSessions_.end(), session), serverFromClientSessions_.end());
- delete session;
}
- void handleStanzaReceived(boost::shared_ptr<Stanza> stanza, ServerFromClientSession* session) {
+ void handleStanzaReceived(boost::shared_ptr<Stanza> stanza, boost::shared_ptr<ServerFromClientSession> session) {
stanza->setFrom(session->getJID());
if (!stanza->getTo().isValid()) {
stanza->setTo(JID(session->getDomain()));
@@ -74,7 +74,7 @@ class Server {
UserRegistry* userRegistry_;
BoostIOServiceThread boostIOServiceThread_;
boost::shared_ptr<BoostConnectionServer> serverFromClientConnectionServer_;
- std::vector<ServerFromClientSession*> serverFromClientSessions_;
+ std::vector< boost::shared_ptr<ServerFromClientSession> > serverFromClientSessions_;
FullPayloadParserFactoryCollection payloadParserFactories_;
FullPayloadSerializerCollection payloadSerializers_;
};
diff --git a/Nim/main.cpp b/Nim/main.cpp
index 6747d4a..7c7105e 100644
--- a/Nim/main.cpp
+++ b/Nim/main.cpp
@@ -53,14 +53,15 @@ class Server {
private:
void handleNewConnection(boost::shared_ptr<Connection> c) {
- ServerFromClientSession* session = new ServerFromClientSession(idGenerator_.generateID(), c, &payloadParserFactories_, &payloadSerializers_, &userRegistry_);
+ boost::shared_ptr<ServerFromClientSession> session(new ServerFromClientSession(idGenerator_.generateID(), c, &payloadParserFactories_, &payloadSerializers_, &userRegistry_));
serverFromClientSessions_.push_back(session);
session->onStanzaReceived.connect(boost::bind(&Server::handleStanzaReceived, this, _1, session));
session->onSessionStarted.connect(boost::bind(&Server::handleSessionStarted, this, session));
session->onSessionFinished.connect(boost::bind(&Server::handleSessionFinished, this, session));
+ session->start();
}
- void handleSessionStarted(ServerFromClientSession* session) {
+ void handleSessionStarted(boost::shared_ptr<ServerFromClientSession> session) {
if (!dnsSDServiceRegistered_) {
dnsSDServiceRegistered_ = true;
dnsSDService_->onServiceRegistered.connect(boost::bind(&Server::handleServiceRegistered, this, _1));
@@ -81,16 +82,15 @@ class Server {
std::cout << "Service registered " << service.name << " " << service.type << " " << service.domain << std::endl;
}
- void handleSessionFinished(ServerFromClientSession* session) {
+ void handleSessionFinished(boost::shared_ptr<ServerFromClientSession> session) {
serverFromClientSessions_.erase(std::remove(serverFromClientSessions_.begin(), serverFromClientSessions_.end(), session), serverFromClientSessions_.end());
- delete session;
if (serverFromClientSessions_.empty()) {
dnsSDServiceRegistered_ = false;
dnsSDService_->unregisterService();
}
}
- void handleStanzaReceived(boost::shared_ptr<Stanza> stanza, ServerFromClientSession* session) {
+ void handleStanzaReceived(boost::shared_ptr<Stanza> stanza, boost::shared_ptr<ServerFromClientSession> session) {
stanza->setFrom(session->getJID());
if (!stanza->getTo().isValid()) {
stanza->setTo(JID(session->getDomain()));
@@ -124,7 +124,7 @@ class Server {
boost::shared_ptr<AppleDNSSDService> dnsSDService_;
boost::shared_ptr<LinkLocalRoster> linkLocalRoster_;
boost::shared_ptr<BoostConnectionServer> serverFromClientConnectionServer_;
- std::vector<ServerFromClientSession*> serverFromClientSessions_;
+ std::vector< boost::shared_ptr<ServerFromClientSession> > serverFromClientSessions_;
FullPayloadParserFactoryCollection payloadParserFactories_;
FullPayloadSerializerCollection payloadSerializers_;
bool dnsSDServiceRegistered_;
diff --git a/Swiften/Client/Session.cpp b/Swiften/Client/Session.cpp
index dbeddb7..2f0e076 100644
--- a/Swiften/Client/Session.cpp
+++ b/Swiften/Client/Session.cpp
@@ -44,7 +44,7 @@ void Session::start() {
state_ = Connecting;
connection_ = connectionFactory_->createConnection();
connection_->onConnected.connect(boost::bind(&Session::handleConnected, this));
- connection_->onError.connect(boost::bind(&Session::handleConnectionError, this, _1));
+ connection_->onDisconnected.connect(boost::bind(&Session::handleDisconnected, this, _1));
connection_->connect(jid_.getDomain());
}
@@ -75,20 +75,22 @@ void Session::initializeStreamStack() {
streamStack_ = new StreamStack(xmppLayer_, connectionLayer_);
}
-void Session::handleConnectionError(Connection::Error error) {
- switch (error) {
- case Connection::DomainNameResolveError:
- setError(DomainNameResolveError);
- break;
- case Connection::ReadError:
- setError(ConnectionReadError);
- break;
- case Connection::WriteError:
- setError(ConnectionWriteError);
- break;
- case Connection::ConnectionError:
- setError(ConnectionError);
- break;
+void Session::handleDisconnected(const boost::optional<Connection::Error>& error) {
+ if (error) {
+ switch (*error) {
+ case Connection::DomainNameResolveError:
+ setError(DomainNameResolveError);
+ break;
+ 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 1b4d1fe..17c10b9 100644
--- a/Swiften/Client/Session.h
+++ b/Swiften/Client/Session.h
@@ -87,7 +87,7 @@ namespace Swift {
void sendSessionStart();
void handleConnected();
- void handleConnectionError(Connection::Error);
+ void handleDisconnected(const boost::optional<Connection::Error>&);
void handleElement(boost::shared_ptr<Element>);
void handleStreamStart();
void handleTLSConnected();
diff --git a/Swiften/Client/UnitTest/SessionTest.cpp b/Swiften/Client/UnitTest/SessionTest.cpp
index 5d43736..45c0996 100644
--- a/Swiften/Client/UnitTest/SessionTest.cpp
+++ b/Swiften/Client/UnitTest/SessionTest.cpp
@@ -488,7 +488,7 @@ class SessionTest : public CppUnit::TestFixture {
void connect(const String& domain) {
if (fail_) {
- MainEventLoop::postEvent(boost::bind(boost::ref(onError), Connection::ConnectionError));
+ MainEventLoop::postEvent(boost::bind(boost::ref(onDisconnected), Connection::ConnectionError));
}
else {
domain_ = domain;
@@ -497,7 +497,7 @@ class SessionTest : public CppUnit::TestFixture {
}
void setError() {
- MainEventLoop::postEvent(boost::bind(boost::ref(onError), Connection::ConnectionError));
+ MainEventLoop::postEvent(boost::bind(boost::ref(onDisconnected), Connection::ConnectionError));
}
void write(const ByteArray& data) {
diff --git a/Swiften/LinkLocal/LinkLocalServiceInfo.cpp b/Swiften/LinkLocal/LinkLocalServiceInfo.cpp
index 99f83b8..8ee7ae0 100644
--- a/Swiften/LinkLocal/LinkLocalServiceInfo.cpp
+++ b/Swiften/LinkLocal/LinkLocalServiceInfo.cpp
@@ -45,4 +45,70 @@ ByteArray LinkLocalServiceInfo::getEncoded(const String& s) {
return sizeByte + ByteArray(s);
}
+LinkLocalServiceInfo LinkLocalServiceInfo::createFromTXTRecord(const ByteArray& record) {
+ LinkLocalServiceInfo info;
+ size_t i = 0;
+ while (i < record.getSize()) {
+ std::pair<String,String> entry = readEntry(record, &i);
+ if (entry.first.isEmpty()) {
+ break;
+ }
+ else if (entry.first == "1st") {
+ info.setFirstName(entry.second);
+ }
+ else if (entry.first == "last") {
+ info.setLastName(entry.second);
+ }
+ else if (entry.first == "email") {
+ info.setEMail(entry.second);
+ }
+ else if (entry.first == "jid") {
+ info.setJID(JID(entry.second));
+ }
+ else if (entry.first == "msg") {
+ info.setMessage(entry.second);
+ }
+ else if (entry.first == "nick") {
+ info.setNick(entry.second);
+ }
+ else if (entry.first == "port.p2pj") {
+ info.setPort(boost::lexical_cast<int>(entry.second));
+ }
+ else if (entry.first == "status") {
+ if (entry.second == "away") {
+ info.setStatus(Away);
+ }
+ else if (entry.second == "dnd") {
+ info.setStatus(DND);
+ }
+ }
+ }
+ return info;
+}
+
+std::pair<String,String> LinkLocalServiceInfo::readEntry(const ByteArray& record, size_t* index) {
+ size_t& i = *index;
+ String key;
+ String value;
+
+ size_t entryEnd = i + 1 + record[i];
+ ++i;
+ bool inKey = true;
+ while (i < entryEnd && i < record.getSize()) {
+ if (inKey) {
+ if (record[i] == '=') {
+ inKey = false;
+ }
+ else {
+ key += record[i];
+ }
+ }
+ else {
+ value += record[i];
+ }
+ ++i;
+ }
+ return std::make_pair(key, value);
+}
+
}
diff --git a/Swiften/LinkLocal/LinkLocalServiceInfo.h b/Swiften/LinkLocal/LinkLocalServiceInfo.h
index bd5286b..d78b70c 100644
--- a/Swiften/LinkLocal/LinkLocalServiceInfo.h
+++ b/Swiften/LinkLocal/LinkLocalServiceInfo.h
@@ -40,8 +40,11 @@ namespace Swift {
ByteArray toTXTRecord() const;
+ static LinkLocalServiceInfo createFromTXTRecord(const ByteArray& record);
+
private:
static ByteArray getEncoded(const String&);
+ static std::pair<String,String> readEntry(const ByteArray&, size_t*);
private:
String firstName;
diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp
index 8efe4ae..b850f14 100644
--- a/Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp
+++ b/Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp
@@ -8,6 +8,8 @@ using namespace Swift;
class LinkLocalServiceInfoTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(LinkLocalServiceInfoTest);
CPPUNIT_TEST(testGetTXTRecord);
+ CPPUNIT_TEST(testCreateFromTXTRecord);
+ CPPUNIT_TEST(testCreateFromTXTRecord_InvalidSize);
CPPUNIT_TEST_SUITE_END();
public:
@@ -21,6 +23,20 @@ class LinkLocalServiceInfoTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT_EQUAL(ByteArray("\x09txtvers=1\x09" + String("1st=Remko\x0dlast=Tron\xc3\xe7on\x0bstatus=away")), info.toTXTRecord());
}
+
+ void testCreateFromTXTRecord() {
+ LinkLocalServiceInfo info = LinkLocalServiceInfo::createFromTXTRecord(ByteArray("\x09txtvers=1\x09" + String("1st=Remko\x0dlast=Tron\xc3\xe7on\x0bstatus=away")));
+
+ CPPUNIT_ASSERT_EQUAL(String("Remko"), info.getFirstName());
+ CPPUNIT_ASSERT_EQUAL(String("Tron\xc3\xe7on"), info.getLastName());
+ CPPUNIT_ASSERT_EQUAL(LinkLocalServiceInfo::Away, info.getStatus());
+ }
+
+ void testCreateFromTXTRecord_InvalidSize() {
+ LinkLocalServiceInfo info = LinkLocalServiceInfo::createFromTXTRecord(ByteArray("\x10last=a"));
+
+ CPPUNIT_ASSERT_EQUAL(String("a"), info.getLastName());
+ }
};
CPPUNIT_TEST_SUITE_REGISTRATION(LinkLocalServiceInfoTest);
diff --git a/Swiften/Network/BoostConnection.cpp b/Swiften/Network/BoostConnection.cpp
index f837b50..d374221 100644
--- a/Swiften/Network/BoostConnection.cpp
+++ b/Swiften/Network/BoostConnection.cpp
@@ -59,7 +59,7 @@ void BoostConnection::connect(const String& domain) {
boost::bind(&BoostConnection::handleConnectFinished, shared_from_this(), boost::asio::placeholders::error));
}
catch (const DomainNameResolveException& e) {
- onError(DomainNameResolveError);
+ onDisconnected(DomainNameResolveError);
}
}
@@ -79,7 +79,7 @@ void BoostConnection::handleConnectFinished(const boost::system::error_code& err
doRead();
}
else if (error != boost::asio::error::operation_aborted) {
- MainEventLoop::postEvent(boost::bind(boost::ref(onError), ConnectionError), shared_from_this());
+ MainEventLoop::postEvent(boost::bind(boost::ref(onDisconnected), ConnectionError), shared_from_this());
}
}
@@ -94,14 +94,23 @@ void BoostConnection::handleSocketRead(const boost::system::error_code& error, s
MainEventLoop::postEvent(boost::bind(boost::ref(onDataRead), ByteArray(&readBuffer_[0], bytesTransferred)), shared_from_this());
doRead();
}
+ else if (error == boost::asio::error::eof) {
+ MainEventLoop::postEvent(boost::bind(boost::ref(onDisconnected), boost::optional<Error>()), shared_from_this());
+ }
else if (error != boost::asio::error::operation_aborted) {
- MainEventLoop::postEvent(boost::bind(boost::ref(onError), ReadError), shared_from_this());
+ MainEventLoop::postEvent(boost::bind(boost::ref(onDisconnected), ReadError), shared_from_this());
}
}
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), shared_from_this());
+ if (!error) {
+ return;
+ }
+ if (error == boost::asio::error::eof) {
+ MainEventLoop::postEvent(boost::bind(boost::ref(onDisconnected), boost::optional<Error>()), shared_from_this());
+ }
+ else if (error && error != boost::asio::error::operation_aborted) {
+ MainEventLoop::postEvent(boost::bind(boost::ref(onDisconnected), WriteError), shared_from_this());
}
}
diff --git a/Swiften/Network/Connection.h b/Swiften/Network/Connection.h
index 16d5d7b..c34c21d 100644
--- a/Swiften/Network/Connection.h
+++ b/Swiften/Network/Connection.h
@@ -26,7 +26,7 @@ namespace Swift {
public:
boost::signal<void ()> onConnected;
- boost::signal<void (Error)> onError;
+ boost::signal<void (const boost::optional<Error>&)> onDisconnected;
boost::signal<void (const ByteArray&)> onDataRead;
};
}
diff --git a/Swiften/Server/ServerFromClientSession.cpp b/Swiften/Server/ServerFromClientSession.cpp
index fe4388e..9a3cf83 100644
--- a/Swiften/Server/ServerFromClientSession.cpp
+++ b/Swiften/Server/ServerFromClientSession.cpp
@@ -32,6 +32,15 @@ ServerFromClientSession::ServerFromClientSession(
authenticated_(false),
initialized_(false) {
xmppLayer_ = boost::shared_ptr<XMPPLayer>(new XMPPLayer(payloadParserFactories_, payloadSerializers_));
+ connectionLayer_ = boost::shared_ptr<ConnectionLayer>(new ConnectionLayer(connection_));
+ streamStack_ = new StreamStack(xmppLayer_, connectionLayer_);
+}
+
+ServerFromClientSession::~ServerFromClientSession() {
+ delete streamStack_;
+}
+
+void ServerFromClientSession::start() {
xmppLayer_->onStreamStart.connect(
boost::bind(&ServerFromClientSession::handleStreamStart, this, _2));
xmppLayer_->onElement.connect(
@@ -42,12 +51,7 @@ ServerFromClientSession::ServerFromClientSession(
boost::bind(boost::ref(onDataRead), _1));
xmppLayer_->onWriteData.connect(
boost::bind(boost::ref(onDataWritten), _1));
- connectionLayer_ = boost::shared_ptr<ConnectionLayer>(new ConnectionLayer(connection_));
- streamStack_ = new StreamStack(xmppLayer_, connectionLayer_);
-}
-
-ServerFromClientSession::~ServerFromClientSession() {
- delete streamStack_;
+ connection_->onDisconnected.connect(boost::bind(&ServerFromClientSession::handleDisconnected, shared_from_this(), _1));
}
void ServerFromClientSession::handleElement(boost::shared_ptr<Element> element) {
@@ -114,5 +118,9 @@ void ServerFromClientSession::sendStanza(boost::shared_ptr<Stanza> stanza) {
xmppLayer_->writeElement(stanza);
}
+void ServerFromClientSession::handleDisconnected(const boost::optional<Connection::Error>&) {
+ onSessionFinished();
+}
+
}
diff --git a/Swiften/Server/ServerFromClientSession.h b/Swiften/Server/ServerFromClientSession.h
index 0110d5d..e7df99d 100644
--- a/Swiften/Server/ServerFromClientSession.h
+++ b/Swiften/Server/ServerFromClientSession.h
@@ -2,9 +2,11 @@
#include <boost/shared_ptr.hpp>
#include <boost/signal.hpp>
+#include <boost/enable_shared_from_this.hpp>
#include "Swiften/Base/String.h"
#include "Swiften/JID/JID.h"
+#include "Swiften/Network/Connection.h"
namespace Swift {
class Element;
@@ -18,7 +20,7 @@ namespace Swift {
class Connection;
class ByteArray;
- class ServerFromClientSession {
+ class ServerFromClientSession : public boost::enable_shared_from_this<ServerFromClientSession> {
public:
ServerFromClientSession(
const String& id,
@@ -28,6 +30,8 @@ namespace Swift {
UserRegistry* userRegistry);
~ServerFromClientSession();
+ void start();
+
void sendStanza(boost::shared_ptr<Stanza>);
const JID& getJID() const {
@@ -45,6 +49,7 @@ namespace Swift {
boost::signal<void (const ByteArray&)> onDataRead;
private:
+ void handleDisconnected(const boost::optional<Connection::Error>& error);
void handleElement(boost::shared_ptr<Element>);
void handleStreamStart(const String& domain);