From 7af8a078c57d94ff63eb81f26de2f55eca6b5c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Remko=20Tron=C3=A7on?= Date: Sat, 18 Jun 2011 12:21:21 +0200 Subject: Moving unused server code out of Swiften into Limber. diff --git a/Limber/SConscript b/Limber/SConscript index e2fadac..bc05f7f 100644 --- a/Limber/SConscript +++ b/Limber/SConscript @@ -1,8 +1,26 @@ Import("env") -if env["SCONS_STAGE"] == "build" : +if env["SCONS_STAGE"] == "flags" : + env["LIMBER_FLAGS"] = { + "LIBPATH": [Dir(".")], + "LIBS": ["Limber"], + } + +elif env["SCONS_STAGE"] == "build" : + libenv = env.Clone() + libenv.MergeFlags(env["BOOST_FLAGS"]) + libenv.MergeFlags(env["SWIFTEN_FLAGS"]) + libenv.StaticLibrary("Limber", [ + "Server/ServerFromClientSession.cpp", + "Server/ServerSession.cpp", + "Server/ServerStanzaRouter.cpp", + "Server/SimpleUserRegistry.cpp", + "Server/UserRegistry.cpp", + ]) + myenv = env.Clone() myenv.BuildVersion("BuildVersion.h", project = "limber") + myenv.UseFlags(env["LIMBER_FLAGS"]) myenv.UseFlags(env["SWIFTEN_FLAGS"]) myenv.UseFlags(env["LIBIDN_FLAGS"]) myenv.UseFlags(env.get("LIBXML_FLAGS", "")) @@ -10,5 +28,8 @@ if env["SCONS_STAGE"] == "build" : myenv.UseFlags(env["OPENSSL_FLAGS"]) myenv.UseFlags(env["BOOST_FLAGS"]) myenv.UseFlags(myenv["PLATFORM_FLAGS"]) - myenv.Program("limber", ["main.cpp"]) + + env.Append(UNITTEST_SOURCES = [ + File("Server/UnitTest/ServerStanzaRouterTest.cpp"), + ]) diff --git a/Limber/Server/ServerFromClientSession.cpp b/Limber/Server/ServerFromClientSession.cpp new file mode 100644 index 0000000..b51a53f --- /dev/null +++ b/Limber/Server/ServerFromClientSession.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Limber/Server/ServerFromClientSession.h" + +#include + +#include "Swiften/Elements/ProtocolHeader.h" +#include "Limber/Server/UserRegistry.h" +#include "Swiften/Network/Connection.h" +#include "Swiften/StreamStack/XMPPLayer.h" +#include "Swiften/Elements/StreamFeatures.h" +#include "Swiften/Elements/ResourceBind.h" +#include "Swiften/Elements/StartSession.h" +#include "Swiften/Elements/IQ.h" +#include "Swiften/Elements/AuthSuccess.h" +#include "Swiften/Elements/AuthFailure.h" +#include "Swiften/Elements/AuthRequest.h" +#include "Swiften/SASL/PLAINMessage.h" + +namespace Swift { + +ServerFromClientSession::ServerFromClientSession( + const std::string& id, + boost::shared_ptr connection, + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers, + UserRegistry* userRegistry) : + Session(connection, payloadParserFactories, payloadSerializers), + id_(id), + userRegistry_(userRegistry), + authenticated_(false), + initialized(false), + allowSASLEXTERNAL(false) { +} + + +void ServerFromClientSession::handleElement(boost::shared_ptr element) { + if (isInitialized()) { + onElementReceived(element); + } + else { + if (AuthRequest* authRequest = dynamic_cast(element.get())) { + if (authRequest->getMechanism() == "PLAIN" || (allowSASLEXTERNAL && authRequest->getMechanism() == "EXTERNAL")) { + if (authRequest->getMechanism() == "EXTERNAL") { + getXMPPLayer()->writeElement(boost::shared_ptr(new AuthSuccess())); + authenticated_ = true; + getXMPPLayer()->resetParser(); + } + else { + PLAINMessage plainMessage(authRequest->getMessage() ? *authRequest->getMessage() : ""); + if (userRegistry_->isValidUserPassword(JID(plainMessage.getAuthenticationID(), getLocalJID().getDomain()), plainMessage.getPassword())) { + getXMPPLayer()->writeElement(boost::shared_ptr(new AuthSuccess())); + user_ = plainMessage.getAuthenticationID(); + authenticated_ = true; + getXMPPLayer()->resetParser(); + } + else { + getXMPPLayer()->writeElement(boost::shared_ptr(new AuthFailure)); + finishSession(AuthenticationFailedError); + } + } + } + else { + getXMPPLayer()->writeElement(boost::shared_ptr(new AuthFailure)); + finishSession(NoSupportedAuthMechanismsError); + } + } + else if (IQ* iq = dynamic_cast(element.get())) { + if (boost::shared_ptr resourceBind = iq->getPayload()) { + setRemoteJID(JID(user_, getLocalJID().getDomain(), resourceBind->getResource())); + boost::shared_ptr resultResourceBind(new ResourceBind()); + resultResourceBind->setJID(getRemoteJID()); + getXMPPLayer()->writeElement(IQ::createResult(JID(), iq->getID(), resultResourceBind)); + } + else if (iq->getPayload()) { + getXMPPLayer()->writeElement(IQ::createResult(getRemoteJID(), iq->getID())); + setInitialized(); + } + } + } +} + +void ServerFromClientSession::handleStreamStart(const ProtocolHeader& incomingHeader) { + setLocalJID(JID("", incomingHeader.getTo())); + ProtocolHeader header; + header.setFrom(incomingHeader.getTo()); + header.setID(id_); + getXMPPLayer()->writeHeader(header); + + boost::shared_ptr features(new StreamFeatures()); + if (!authenticated_) { + features->addAuthenticationMechanism("PLAIN"); + if (allowSASLEXTERNAL) { + features->addAuthenticationMechanism("EXTERNAL"); + } + } + else { + features->setHasResourceBind(); + features->setHasSession(); + } + getXMPPLayer()->writeElement(features); +} + +void ServerFromClientSession::setInitialized() { + initialized = true; + onSessionStarted(); +} + +void ServerFromClientSession::setAllowSASLEXTERNAL() { + allowSASLEXTERNAL = true; +} + +} diff --git a/Limber/Server/ServerFromClientSession.h b/Limber/Server/ServerFromClientSession.h new file mode 100644 index 0000000..80ef063 --- /dev/null +++ b/Limber/Server/ServerFromClientSession.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include +#include "Swiften/Base/boost_bsignals.h" +#include + +#include +#include "Swiften/Session/Session.h" +#include "Swiften/JID/JID.h" +#include "Swiften/Network/Connection.h" + +namespace Swift { + class ProtocolHeader; + class Element; + class Stanza; + class PayloadParserFactoryCollection; + class PayloadSerializerCollection; + class StreamStack; + class UserRegistry; + class XMPPLayer; + class ConnectionLayer; + class Connection; + class ByteArray; + + class ServerFromClientSession : public Session { + public: + ServerFromClientSession( + const std::string& id, + boost::shared_ptr connection, + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers, + UserRegistry* userRegistry); + + boost::signal onSessionStarted; + void setAllowSASLEXTERNAL(); + + private: + void handleElement(boost::shared_ptr); + void handleStreamStart(const ProtocolHeader& header); + + void setInitialized(); + bool isInitialized() const { + return initialized; + } + + private: + std::string id_; + UserRegistry* userRegistry_; + bool authenticated_; + bool initialized; + bool allowSASLEXTERNAL; + std::string user_; + }; +} diff --git a/Limber/Server/ServerSession.cpp b/Limber/Server/ServerSession.cpp new file mode 100644 index 0000000..5b6d66a --- /dev/null +++ b/Limber/Server/ServerSession.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Limber/Server/ServerSession.h" + +namespace Swift { + +ServerSession::~ServerSession() { +} + +} diff --git a/Limber/Server/ServerSession.h b/Limber/Server/ServerSession.h new file mode 100644 index 0000000..bd4ab6d --- /dev/null +++ b/Limber/Server/ServerSession.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include + +#include "Swiften/Elements/Stanza.h" + +namespace Swift { + class ServerSession { + public: + virtual ~ServerSession(); + + virtual const JID& getJID() const = 0; + virtual int getPriority() const = 0; + + virtual void sendStanza(boost::shared_ptr) = 0; + }; +} diff --git a/Limber/Server/ServerStanzaRouter.cpp b/Limber/Server/ServerStanzaRouter.cpp new file mode 100644 index 0000000..fec529f --- /dev/null +++ b/Limber/Server/ServerStanzaRouter.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Limber/Server/ServerStanzaRouter.h" +#include "Limber/Server/ServerSession.h" + +#include +#include + +namespace Swift { + +namespace { + struct PriorityLessThan { + bool operator()(const ServerSession* s1, const ServerSession* s2) const { + return s1->getPriority() < s2->getPriority(); + } + }; + + struct HasJID { + HasJID(const JID& jid) : jid(jid) {} + bool operator()(const ServerSession* session) const { + return session->getJID().equals(jid, JID::WithResource); + } + JID jid; + }; +} + +ServerStanzaRouter::ServerStanzaRouter() { +} + +bool ServerStanzaRouter::routeStanza(boost::shared_ptr stanza) { + JID to = stanza->getTo(); + assert(to.isValid()); + + // For a full JID, first try to route to a session with the full JID + if (!to.isBare()) { + std::vector::const_iterator i = std::find_if(clientSessions_.begin(), clientSessions_.end(), HasJID(to)); + if (i != clientSessions_.end()) { + (*i)->sendStanza(stanza); + return true; + } + } + + // Look for candidate sessions + to = to.toBare(); + std::vector candidateSessions; + for (std::vector::const_iterator i = clientSessions_.begin(); i != clientSessions_.end(); ++i) { + if ((*i)->getJID().equals(to, JID::WithoutResource) && (*i)->getPriority() >= 0) { + candidateSessions.push_back(*i); + } + } + if (candidateSessions.empty()) { + return false; + } + + // Find the session with the highest priority + std::vector::const_iterator i = std::max_element(clientSessions_.begin(), clientSessions_.end(), PriorityLessThan()); + (*i)->sendStanza(stanza); + return true; +} + +void ServerStanzaRouter::addClientSession(ServerSession* clientSession) { + clientSessions_.push_back(clientSession); +} + +void ServerStanzaRouter::removeClientSession(ServerSession* clientSession) { + clientSessions_.erase(std::remove(clientSessions_.begin(), clientSessions_.end(), clientSession), clientSessions_.end()); +} + +} diff --git a/Limber/Server/ServerStanzaRouter.h b/Limber/Server/ServerStanzaRouter.h new file mode 100644 index 0000000..2a1960c --- /dev/null +++ b/Limber/Server/ServerStanzaRouter.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include +#include + +#include "Swiften/JID/JID.h" +#include "Swiften/Elements/Stanza.h" + +namespace Swift { + class ServerSession; + + class ServerStanzaRouter { + public: + ServerStanzaRouter(); + + bool routeStanza(boost::shared_ptr); + + void addClientSession(ServerSession*); + void removeClientSession(ServerSession*); + + private: + std::vector clientSessions_; + }; +} diff --git a/Limber/Server/SimpleUserRegistry.cpp b/Limber/Server/SimpleUserRegistry.cpp new file mode 100644 index 0000000..5b7329a --- /dev/null +++ b/Limber/Server/SimpleUserRegistry.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Limber/Server/SimpleUserRegistry.h" + +namespace Swift { + +SimpleUserRegistry::SimpleUserRegistry() { +} + +bool SimpleUserRegistry::isValidUserPassword(const JID& user, const std::string& password) const { + std::map::const_iterator i = users.find(user); + return i != users.end() ? i->second == password : false; +} + +void SimpleUserRegistry::addUser(const JID& user, const std::string& password) { + users.insert(std::make_pair(user, password)); +} + +} diff --git a/Limber/Server/SimpleUserRegistry.h b/Limber/Server/SimpleUserRegistry.h new file mode 100644 index 0000000..677d006 --- /dev/null +++ b/Limber/Server/SimpleUserRegistry.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include + +#include "Swiften/JID/JID.h" +#include +#include "Limber/Server/UserRegistry.h" + +namespace Swift { + + + class SimpleUserRegistry : public UserRegistry { + public: + SimpleUserRegistry(); + + virtual bool isValidUserPassword(const JID& user, const std::string& password) const; + void addUser(const JID& user, const std::string& password); + + private: + std::map users; + }; +} diff --git a/Limber/Server/UnitTest/ServerStanzaRouterTest.cpp b/Limber/Server/UnitTest/ServerStanzaRouterTest.cpp new file mode 100644 index 0000000..87c713e --- /dev/null +++ b/Limber/Server/UnitTest/ServerStanzaRouterTest.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include +#include + +#include "Swiften/Elements/Message.h" +#include "Limber/Server/ServerStanzaRouter.h" +#include "Limber/Server/ServerSession.h" + +using namespace Swift; + +class ServerStanzaRouterTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(ServerStanzaRouterTest); + CPPUNIT_TEST(testRouteStanza_FullJID); + CPPUNIT_TEST(testRouteStanza_FullJIDWithNegativePriority); + CPPUNIT_TEST(testRouteStanza_FullJIDWithOnlyBareJIDMatchingSession); + CPPUNIT_TEST(testRouteStanza_BareJIDWithoutMatchingSession); + CPPUNIT_TEST(testRouteStanza_BareJIDWithMultipleSessions); + CPPUNIT_TEST(testRouteStanza_BareJIDWithOnlyNegativePriorities); + CPPUNIT_TEST(testRouteStanza_BareJIDWithChangingPresence); + CPPUNIT_TEST_SUITE_END(); + + public: + ServerStanzaRouterTest() {} + + void setUp() { + } + + void tearDown() { + } + + void testRouteStanza_FullJID() { + ServerStanzaRouter testling; + MockServerSession session1(JID("foo@bar.com/Bla"), 0); + testling.addClientSession(&session1); + MockServerSession session2(JID("foo@bar.com/Baz"), 0); + testling.addClientSession(&session2); + + bool result = testling.routeStanza(createMessageTo("foo@bar.com/Baz")); + + CPPUNIT_ASSERT(result); + CPPUNIT_ASSERT_EQUAL(0, static_cast(session1.sentStanzas.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast(session2.sentStanzas.size())); + } + + void testRouteStanza_FullJIDWithNegativePriority() { + ServerStanzaRouter testling; + MockServerSession session1(JID("foo@bar.com/Bla"), -1); + testling.addClientSession(&session1); + MockServerSession session2(JID("foo@bar.com/Baz"), 0); + testling.addClientSession(&session2); + + bool result = testling.routeStanza(createMessageTo("foo@bar.com/Bla")); + + CPPUNIT_ASSERT(result); + CPPUNIT_ASSERT_EQUAL(1, static_cast(session1.sentStanzas.size())); + CPPUNIT_ASSERT_EQUAL(0, static_cast(session2.sentStanzas.size())); + } + + void testRouteStanza_FullJIDWithOnlyBareJIDMatchingSession() { + ServerStanzaRouter testling; + MockServerSession session(JID("foo@bar.com/Bla"), 0); + testling.addClientSession(&session); + + bool result = testling.routeStanza(createMessageTo("foo@bar.com/Baz")); + + CPPUNIT_ASSERT(result); + CPPUNIT_ASSERT_EQUAL(1, static_cast(session.sentStanzas.size())); + } + + void testRouteStanza_BareJIDWithoutMatchingSession() { + ServerStanzaRouter testling; + + bool result = testling.routeStanza(createMessageTo("foo@bar.com")); + + CPPUNIT_ASSERT(!result); + } + + void testRouteStanza_BareJIDWithMultipleSessions() { + ServerStanzaRouter testling; + MockServerSession session1(JID("foo@bar.com/Bla"), 1); + testling.addClientSession(&session1); + MockServerSession session2(JID("foo@bar.com/Baz"), 8); + testling.addClientSession(&session2); + MockServerSession session3(JID("foo@bar.com/Bar"), 5); + testling.addClientSession(&session3); + + bool result = testling.routeStanza(createMessageTo("foo@bar.com")); + + CPPUNIT_ASSERT(result); + CPPUNIT_ASSERT_EQUAL(0, static_cast(session1.sentStanzas.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast(session2.sentStanzas.size())); + CPPUNIT_ASSERT_EQUAL(0, static_cast(session3.sentStanzas.size())); + } + + void testRouteStanza_BareJIDWithOnlyNegativePriorities() { + ServerStanzaRouter testling; + MockServerSession session(JID("foo@bar.com/Bla"), -1); + testling.addClientSession(&session); + + bool result = testling.routeStanza(createMessageTo("foo@bar.com")); + + CPPUNIT_ASSERT(!result); + } + + void testRouteStanza_BareJIDWithChangingPresence() { + ServerStanzaRouter testling; + MockServerSession session1(JID("foo@bar.com/Baz"), 8); + testling.addClientSession(&session1); + MockServerSession session2(JID("foo@bar.com/Bar"), 5); + testling.addClientSession(&session2); + + session1.priority = 3; + session2.priority = 4; + bool result = testling.routeStanza(createMessageTo("foo@bar.com")); + + CPPUNIT_ASSERT(result); + CPPUNIT_ASSERT_EQUAL(0, static_cast(session1.sentStanzas.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast(session2.sentStanzas.size())); + } + + private: + boost::shared_ptr createMessageTo(const std::string& recipient) { + boost::shared_ptr message(new Message()); + message->setTo(JID(recipient)); + return message; + } + + class MockServerSession : public ServerSession { + public: + MockServerSession(const JID& jid, int priority) : jid(jid), priority(priority) {} + + virtual const JID& getJID() const { return jid; } + virtual int getPriority() const { return priority; } + + virtual void sendStanza(boost::shared_ptr stanza) { + sentStanzas.push_back(stanza); + } + + JID jid; + int priority; + std::vector< boost::shared_ptr > sentStanzas; + }; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(ServerStanzaRouterTest); diff --git a/Limber/Server/UserRegistry.cpp b/Limber/Server/UserRegistry.cpp new file mode 100644 index 0000000..5ac462a --- /dev/null +++ b/Limber/Server/UserRegistry.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Limber/Server/UserRegistry.h" + +namespace Swift { + +UserRegistry::~UserRegistry() { +} + +} diff --git a/Limber/Server/UserRegistry.h b/Limber/Server/UserRegistry.h new file mode 100644 index 0000000..c021fc4 --- /dev/null +++ b/Limber/Server/UserRegistry.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include + +namespace Swift { + + class JID; + + class UserRegistry { + public: + virtual ~UserRegistry(); + + virtual bool isValidUserPassword(const JID& user, const std::string& password) const = 0; + }; +} diff --git a/Limber/main.cpp b/Limber/main.cpp index 6db623e..e6bc45d 100644 --- a/Limber/main.cpp +++ b/Limber/main.cpp @@ -11,7 +11,6 @@ #include "Swiften/Elements/IQ.h" #include "Swiften/Elements/RosterPayload.h" #include "Swiften/Elements/VCard.h" -#include "Swiften/Server/SimpleUserRegistry.h" #include "Swiften/Base/IDGenerator.h" #include "Swiften/EventLoop/EventLoop.h" #include "Swiften/EventLoop/SimpleEventLoop.h" @@ -21,7 +20,8 @@ #include "Swiften/Network/BoostConnection.h" #include "Swiften/Network/BoostIOServiceThread.h" #include "Swiften/Network/BoostConnectionServer.h" -#include "Swiften/Server/ServerFromClientSession.h" +#include "Limber/Server/SimpleUserRegistry.h" +#include "Limber/Server/ServerFromClientSession.h" #include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h" #include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h" diff --git a/QA/UnitTest/SConscript b/QA/UnitTest/SConscript index 25e9b05..76abbcb 100644 --- a/QA/UnitTest/SConscript +++ b/QA/UnitTest/SConscript @@ -12,6 +12,7 @@ if env["TEST"] : myenv.MergeFlags(env.get("SLIMBER_FLAGS","")) myenv.MergeFlags(env.get("SWIFT_CONTROLLERS_FLAGS","")) myenv.MergeFlags(env.get("SWIFTOOLS_FLAGS","")) + myenv.MergeFlags(env.get("LIMBER_FLAGS","")) myenv.MergeFlags(env.get("SWIFTEN_FLAGS","")) myenv.MergeFlags(env.get("CPPUNIT_FLAGS","")) myenv.MergeFlags(env.get("LIBIDN_FLAGS", "")) diff --git a/Slimber/CLI/SConscript b/Slimber/CLI/SConscript index fddd717..422b56c 100644 --- a/Slimber/CLI/SConscript +++ b/Slimber/CLI/SConscript @@ -1,6 +1,7 @@ Import("env") myenv = env.Clone() +myenv.UseFlags(env["LIMBER_FLAGS"]) myenv.MergeFlags(env["SLIMBER_FLAGS"]) myenv.MergeFlags(env["SWIFTOOLS_FLAGS"]) myenv.MergeFlags(env["SWIFTEN_FLAGS"]) diff --git a/Slimber/Cocoa/SConscript b/Slimber/Cocoa/SConscript index e2d8221..e122d87 100644 --- a/Slimber/Cocoa/SConscript +++ b/Slimber/Cocoa/SConscript @@ -1,6 +1,7 @@ Import("env") myenv = env.Clone() +myenv.UseFlags(env["LIMBER_FLAGS"]) myenv.MergeFlags(env["SLIMBER_FLAGS"]) myenv.MergeFlags(env["SWIFTOOLS_FLAGS"]) myenv.MergeFlags(env["SWIFTEN_FLAGS"]) diff --git a/Slimber/SConscript b/Slimber/SConscript index 9a84c17..11beee6 100644 --- a/Slimber/SConscript +++ b/Slimber/SConscript @@ -31,6 +31,7 @@ if "Slimber" in env["PROJECTS"] : if env["SCONS_STAGE"] == "build" : myenv = env.Clone() + myenv.UseFlags(env["LIMBER_FLAGS"]) myenv.MergeFlags(env["BOOST_FLAGS"]) myenv.MergeFlags(env["SWIFTEN_FLAGS"]) myenv.StaticLibrary("Slimber", [ diff --git a/Slimber/Server.cpp b/Slimber/Server.cpp index 380ce6a..d1d0e24 100644 --- a/Slimber/Server.cpp +++ b/Slimber/Server.cpp @@ -21,7 +21,7 @@ #include "Swiften/Session/SessionTracer.h" #include "Swiften/Elements/IQ.h" #include "Swiften/Elements/VCard.h" -#include "Swiften/Server/UserRegistry.h" +#include "Limber/Server/UserRegistry.h" #include #include "Swiften/LinkLocal/LinkLocalServiceInfo.h" #include "Swiften/LinkLocal/OutgoingLinkLocalSession.h" @@ -30,7 +30,7 @@ #include "Swiften/Network/ConnectionServer.h" #include "Slimber/VCardCollection.h" #include "Slimber/LinkLocalPresenceManager.h" -#include "Swiften/Server/ServerFromClientSession.h" +#include "Limber/Server/ServerFromClientSession.h" namespace Swift { diff --git a/Slimber/Server.h b/Slimber/Server.h index 98332fd..d1a2332 100644 --- a/Slimber/Server.h +++ b/Slimber/Server.h @@ -12,9 +12,9 @@ #include "Swiften/Network/BoostIOServiceThread.h" #include "Swiften/Network/BoostConnectionServer.h" -#include "Swiften/Server/UserRegistry.h" +#include "Limber/Server/UserRegistry.h" #include "Swiften/Base/IDGenerator.h" -#include "Swiften/Server/ServerFromClientSession.h" +#include "Limber/Server/ServerFromClientSession.h" #include "Swiften/JID/JID.h" #include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h" #include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h" diff --git a/Swiften/SConscript b/Swiften/SConscript index 110f202..30fd9b6 100644 --- a/Swiften/SConscript +++ b/Swiften/SConscript @@ -153,11 +153,6 @@ if env["SCONS_STAGE"] == "build" : "Serializer/XML/XMLElement.cpp", "Serializer/XML/XMLNode.cpp", "Serializer/XMPPSerializer.cpp", - "Server/ServerFromClientSession.cpp", - "Server/ServerSession.cpp", - "Server/ServerStanzaRouter.cpp", - "Server/SimpleUserRegistry.cpp", - "Server/UserRegistry.cpp", "Session/Session.cpp", "Session/SessionStream.cpp", "Session/BasicSessionStream.cpp", diff --git a/Swiften/Server/ServerFromClientSession.cpp b/Swiften/Server/ServerFromClientSession.cpp deleted file mode 100644 index 18da7e8..0000000 --- a/Swiften/Server/ServerFromClientSession.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include "Swiften/Server/ServerFromClientSession.h" - -#include - -#include "Swiften/Elements/ProtocolHeader.h" -#include "Swiften/Server/UserRegistry.h" -#include "Swiften/Network/Connection.h" -#include "Swiften/StreamStack/XMPPLayer.h" -#include "Swiften/Elements/StreamFeatures.h" -#include "Swiften/Elements/ResourceBind.h" -#include "Swiften/Elements/StartSession.h" -#include "Swiften/Elements/IQ.h" -#include "Swiften/Elements/AuthSuccess.h" -#include "Swiften/Elements/AuthFailure.h" -#include "Swiften/Elements/AuthRequest.h" -#include "Swiften/SASL/PLAINMessage.h" - -namespace Swift { - -ServerFromClientSession::ServerFromClientSession( - const std::string& id, - boost::shared_ptr connection, - PayloadParserFactoryCollection* payloadParserFactories, - PayloadSerializerCollection* payloadSerializers, - UserRegistry* userRegistry) : - Session(connection, payloadParserFactories, payloadSerializers), - id_(id), - userRegistry_(userRegistry), - authenticated_(false), - initialized(false), - allowSASLEXTERNAL(false) { -} - - -void ServerFromClientSession::handleElement(boost::shared_ptr element) { - if (isInitialized()) { - onElementReceived(element); - } - else { - if (AuthRequest* authRequest = dynamic_cast(element.get())) { - if (authRequest->getMechanism() == "PLAIN" || (allowSASLEXTERNAL && authRequest->getMechanism() == "EXTERNAL")) { - if (authRequest->getMechanism() == "EXTERNAL") { - getXMPPLayer()->writeElement(boost::shared_ptr(new AuthSuccess())); - authenticated_ = true; - getXMPPLayer()->resetParser(); - } - else { - PLAINMessage plainMessage(authRequest->getMessage() ? *authRequest->getMessage() : ""); - if (userRegistry_->isValidUserPassword(JID(plainMessage.getAuthenticationID(), getLocalJID().getDomain()), plainMessage.getPassword())) { - getXMPPLayer()->writeElement(boost::shared_ptr(new AuthSuccess())); - user_ = plainMessage.getAuthenticationID(); - authenticated_ = true; - getXMPPLayer()->resetParser(); - } - else { - getXMPPLayer()->writeElement(boost::shared_ptr(new AuthFailure)); - finishSession(AuthenticationFailedError); - } - } - } - else { - getXMPPLayer()->writeElement(boost::shared_ptr(new AuthFailure)); - finishSession(NoSupportedAuthMechanismsError); - } - } - else if (IQ* iq = dynamic_cast(element.get())) { - if (boost::shared_ptr resourceBind = iq->getPayload()) { - setRemoteJID(JID(user_, getLocalJID().getDomain(), resourceBind->getResource())); - boost::shared_ptr resultResourceBind(new ResourceBind()); - resultResourceBind->setJID(getRemoteJID()); - getXMPPLayer()->writeElement(IQ::createResult(JID(), iq->getID(), resultResourceBind)); - } - else if (iq->getPayload()) { - getXMPPLayer()->writeElement(IQ::createResult(getRemoteJID(), iq->getID())); - setInitialized(); - } - } - } -} - -void ServerFromClientSession::handleStreamStart(const ProtocolHeader& incomingHeader) { - setLocalJID(JID("", incomingHeader.getTo())); - ProtocolHeader header; - header.setFrom(incomingHeader.getTo()); - header.setID(id_); - getXMPPLayer()->writeHeader(header); - - boost::shared_ptr features(new StreamFeatures()); - if (!authenticated_) { - features->addAuthenticationMechanism("PLAIN"); - if (allowSASLEXTERNAL) { - features->addAuthenticationMechanism("EXTERNAL"); - } - } - else { - features->setHasResourceBind(); - features->setHasSession(); - } - getXMPPLayer()->writeElement(features); -} - -void ServerFromClientSession::setInitialized() { - initialized = true; - onSessionStarted(); -} - -void ServerFromClientSession::setAllowSASLEXTERNAL() { - allowSASLEXTERNAL = true; -} - -} diff --git a/Swiften/Server/ServerFromClientSession.h b/Swiften/Server/ServerFromClientSession.h deleted file mode 100644 index 80ef063..0000000 --- a/Swiften/Server/ServerFromClientSession.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#pragma once - -#include -#include "Swiften/Base/boost_bsignals.h" -#include - -#include -#include "Swiften/Session/Session.h" -#include "Swiften/JID/JID.h" -#include "Swiften/Network/Connection.h" - -namespace Swift { - class ProtocolHeader; - class Element; - class Stanza; - class PayloadParserFactoryCollection; - class PayloadSerializerCollection; - class StreamStack; - class UserRegistry; - class XMPPLayer; - class ConnectionLayer; - class Connection; - class ByteArray; - - class ServerFromClientSession : public Session { - public: - ServerFromClientSession( - const std::string& id, - boost::shared_ptr connection, - PayloadParserFactoryCollection* payloadParserFactories, - PayloadSerializerCollection* payloadSerializers, - UserRegistry* userRegistry); - - boost::signal onSessionStarted; - void setAllowSASLEXTERNAL(); - - private: - void handleElement(boost::shared_ptr); - void handleStreamStart(const ProtocolHeader& header); - - void setInitialized(); - bool isInitialized() const { - return initialized; - } - - private: - std::string id_; - UserRegistry* userRegistry_; - bool authenticated_; - bool initialized; - bool allowSASLEXTERNAL; - std::string user_; - }; -} diff --git a/Swiften/Server/ServerSession.cpp b/Swiften/Server/ServerSession.cpp deleted file mode 100644 index 10d642d..0000000 --- a/Swiften/Server/ServerSession.cpp +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include "Swiften/Server/ServerSession.h" - -namespace Swift { - -ServerSession::~ServerSession() { -} - -} diff --git a/Swiften/Server/ServerSession.h b/Swiften/Server/ServerSession.h deleted file mode 100644 index bd4ab6d..0000000 --- a/Swiften/Server/ServerSession.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#pragma once - -#include - -#include "Swiften/Elements/Stanza.h" - -namespace Swift { - class ServerSession { - public: - virtual ~ServerSession(); - - virtual const JID& getJID() const = 0; - virtual int getPriority() const = 0; - - virtual void sendStanza(boost::shared_ptr) = 0; - }; -} diff --git a/Swiften/Server/ServerStanzaRouter.cpp b/Swiften/Server/ServerStanzaRouter.cpp deleted file mode 100644 index b4d230a..0000000 --- a/Swiften/Server/ServerStanzaRouter.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include "Swiften/Server/ServerStanzaRouter.h" -#include "Swiften/Server/ServerSession.h" - -#include -#include - -namespace Swift { - -namespace { - struct PriorityLessThan { - bool operator()(const ServerSession* s1, const ServerSession* s2) const { - return s1->getPriority() < s2->getPriority(); - } - }; - - struct HasJID { - HasJID(const JID& jid) : jid(jid) {} - bool operator()(const ServerSession* session) const { - return session->getJID().equals(jid, JID::WithResource); - } - JID jid; - }; -} - -ServerStanzaRouter::ServerStanzaRouter() { -} - -bool ServerStanzaRouter::routeStanza(boost::shared_ptr stanza) { - JID to = stanza->getTo(); - assert(to.isValid()); - - // For a full JID, first try to route to a session with the full JID - if (!to.isBare()) { - std::vector::const_iterator i = std::find_if(clientSessions_.begin(), clientSessions_.end(), HasJID(to)); - if (i != clientSessions_.end()) { - (*i)->sendStanza(stanza); - return true; - } - } - - // Look for candidate sessions - to = to.toBare(); - std::vector candidateSessions; - for (std::vector::const_iterator i = clientSessions_.begin(); i != clientSessions_.end(); ++i) { - if ((*i)->getJID().equals(to, JID::WithoutResource) && (*i)->getPriority() >= 0) { - candidateSessions.push_back(*i); - } - } - if (candidateSessions.empty()) { - return false; - } - - // Find the session with the highest priority - std::vector::const_iterator i = std::max_element(clientSessions_.begin(), clientSessions_.end(), PriorityLessThan()); - (*i)->sendStanza(stanza); - return true; -} - -void ServerStanzaRouter::addClientSession(ServerSession* clientSession) { - clientSessions_.push_back(clientSession); -} - -void ServerStanzaRouter::removeClientSession(ServerSession* clientSession) { - clientSessions_.erase(std::remove(clientSessions_.begin(), clientSessions_.end(), clientSession), clientSessions_.end()); -} - -} diff --git a/Swiften/Server/ServerStanzaRouter.h b/Swiften/Server/ServerStanzaRouter.h deleted file mode 100644 index 2a1960c..0000000 --- a/Swiften/Server/ServerStanzaRouter.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#pragma once - -#include -#include - -#include "Swiften/JID/JID.h" -#include "Swiften/Elements/Stanza.h" - -namespace Swift { - class ServerSession; - - class ServerStanzaRouter { - public: - ServerStanzaRouter(); - - bool routeStanza(boost::shared_ptr); - - void addClientSession(ServerSession*); - void removeClientSession(ServerSession*); - - private: - std::vector clientSessions_; - }; -} diff --git a/Swiften/Server/SimpleUserRegistry.cpp b/Swiften/Server/SimpleUserRegistry.cpp deleted file mode 100644 index 2de28fe..0000000 --- a/Swiften/Server/SimpleUserRegistry.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include "Swiften/Server/SimpleUserRegistry.h" - -namespace Swift { - -SimpleUserRegistry::SimpleUserRegistry() { -} - -bool SimpleUserRegistry::isValidUserPassword(const JID& user, const std::string& password) const { - std::map::const_iterator i = users.find(user); - return i != users.end() ? i->second == password : false; -} - -void SimpleUserRegistry::addUser(const JID& user, const std::string& password) { - users.insert(std::make_pair(user, password)); -} - -} diff --git a/Swiften/Server/SimpleUserRegistry.h b/Swiften/Server/SimpleUserRegistry.h deleted file mode 100644 index 5de9f64..0000000 --- a/Swiften/Server/SimpleUserRegistry.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#pragma once - -#include - -#include "Swiften/JID/JID.h" -#include -#include "Swiften/Server/UserRegistry.h" - -namespace Swift { - - - class SimpleUserRegistry : public UserRegistry { - public: - SimpleUserRegistry(); - - virtual bool isValidUserPassword(const JID& user, const std::string& password) const; - void addUser(const JID& user, const std::string& password); - - private: - std::map users; - }; -} diff --git a/Swiften/Server/UnitTest/ServerStanzaRouterTest.cpp b/Swiften/Server/UnitTest/ServerStanzaRouterTest.cpp deleted file mode 100644 index 0a5c7c1..0000000 --- a/Swiften/Server/UnitTest/ServerStanzaRouterTest.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include -#include - -#include "Swiften/Elements/Message.h" -#include "Swiften/Server/ServerStanzaRouter.h" -#include "Swiften/Server/ServerSession.h" - -using namespace Swift; - -class ServerStanzaRouterTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ServerStanzaRouterTest); - CPPUNIT_TEST(testRouteStanza_FullJID); - CPPUNIT_TEST(testRouteStanza_FullJIDWithNegativePriority); - CPPUNIT_TEST(testRouteStanza_FullJIDWithOnlyBareJIDMatchingSession); - CPPUNIT_TEST(testRouteStanza_BareJIDWithoutMatchingSession); - CPPUNIT_TEST(testRouteStanza_BareJIDWithMultipleSessions); - CPPUNIT_TEST(testRouteStanza_BareJIDWithOnlyNegativePriorities); - CPPUNIT_TEST(testRouteStanza_BareJIDWithChangingPresence); - CPPUNIT_TEST_SUITE_END(); - - public: - ServerStanzaRouterTest() {} - - void setUp() { - } - - void tearDown() { - } - - void testRouteStanza_FullJID() { - ServerStanzaRouter testling; - MockServerSession session1(JID("foo@bar.com/Bla"), 0); - testling.addClientSession(&session1); - MockServerSession session2(JID("foo@bar.com/Baz"), 0); - testling.addClientSession(&session2); - - bool result = testling.routeStanza(createMessageTo("foo@bar.com/Baz")); - - CPPUNIT_ASSERT(result); - CPPUNIT_ASSERT_EQUAL(0, static_cast(session1.sentStanzas.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast(session2.sentStanzas.size())); - } - - void testRouteStanza_FullJIDWithNegativePriority() { - ServerStanzaRouter testling; - MockServerSession session1(JID("foo@bar.com/Bla"), -1); - testling.addClientSession(&session1); - MockServerSession session2(JID("foo@bar.com/Baz"), 0); - testling.addClientSession(&session2); - - bool result = testling.routeStanza(createMessageTo("foo@bar.com/Bla")); - - CPPUNIT_ASSERT(result); - CPPUNIT_ASSERT_EQUAL(1, static_cast(session1.sentStanzas.size())); - CPPUNIT_ASSERT_EQUAL(0, static_cast(session2.sentStanzas.size())); - } - - void testRouteStanza_FullJIDWithOnlyBareJIDMatchingSession() { - ServerStanzaRouter testling; - MockServerSession session(JID("foo@bar.com/Bla"), 0); - testling.addClientSession(&session); - - bool result = testling.routeStanza(createMessageTo("foo@bar.com/Baz")); - - CPPUNIT_ASSERT(result); - CPPUNIT_ASSERT_EQUAL(1, static_cast(session.sentStanzas.size())); - } - - void testRouteStanza_BareJIDWithoutMatchingSession() { - ServerStanzaRouter testling; - - bool result = testling.routeStanza(createMessageTo("foo@bar.com")); - - CPPUNIT_ASSERT(!result); - } - - void testRouteStanza_BareJIDWithMultipleSessions() { - ServerStanzaRouter testling; - MockServerSession session1(JID("foo@bar.com/Bla"), 1); - testling.addClientSession(&session1); - MockServerSession session2(JID("foo@bar.com/Baz"), 8); - testling.addClientSession(&session2); - MockServerSession session3(JID("foo@bar.com/Bar"), 5); - testling.addClientSession(&session3); - - bool result = testling.routeStanza(createMessageTo("foo@bar.com")); - - CPPUNIT_ASSERT(result); - CPPUNIT_ASSERT_EQUAL(0, static_cast(session1.sentStanzas.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast(session2.sentStanzas.size())); - CPPUNIT_ASSERT_EQUAL(0, static_cast(session3.sentStanzas.size())); - } - - void testRouteStanza_BareJIDWithOnlyNegativePriorities() { - ServerStanzaRouter testling; - MockServerSession session(JID("foo@bar.com/Bla"), -1); - testling.addClientSession(&session); - - bool result = testling.routeStanza(createMessageTo("foo@bar.com")); - - CPPUNIT_ASSERT(!result); - } - - void testRouteStanza_BareJIDWithChangingPresence() { - ServerStanzaRouter testling; - MockServerSession session1(JID("foo@bar.com/Baz"), 8); - testling.addClientSession(&session1); - MockServerSession session2(JID("foo@bar.com/Bar"), 5); - testling.addClientSession(&session2); - - session1.priority = 3; - session2.priority = 4; - bool result = testling.routeStanza(createMessageTo("foo@bar.com")); - - CPPUNIT_ASSERT(result); - CPPUNIT_ASSERT_EQUAL(0, static_cast(session1.sentStanzas.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast(session2.sentStanzas.size())); - } - - private: - boost::shared_ptr createMessageTo(const std::string& recipient) { - boost::shared_ptr message(new Message()); - message->setTo(JID(recipient)); - return message; - } - - class MockServerSession : public ServerSession { - public: - MockServerSession(const JID& jid, int priority) : jid(jid), priority(priority) {} - - virtual const JID& getJID() const { return jid; } - virtual int getPriority() const { return priority; } - - virtual void sendStanza(boost::shared_ptr stanza) { - sentStanzas.push_back(stanza); - } - - JID jid; - int priority; - std::vector< boost::shared_ptr > sentStanzas; - }; -}; - -CPPUNIT_TEST_SUITE_REGISTRATION(ServerStanzaRouterTest); diff --git a/Swiften/Server/UserRegistry.cpp b/Swiften/Server/UserRegistry.cpp deleted file mode 100644 index 0795f16..0000000 --- a/Swiften/Server/UserRegistry.cpp +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include "Swiften/Server/UserRegistry.h" - -namespace Swift { - -UserRegistry::~UserRegistry() { -} - -} diff --git a/Swiften/Server/UserRegistry.h b/Swiften/Server/UserRegistry.h deleted file mode 100644 index c021fc4..0000000 --- a/Swiften/Server/UserRegistry.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#pragma once - -#include - -namespace Swift { - - class JID; - - class UserRegistry { - public: - virtual ~UserRegistry(); - - virtual bool isValidUserPassword(const JID& user, const std::string& password) const = 0; - }; -} -- cgit v0.10.2-6-g49f6