diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index b03db84e..9b9de826 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -656,16 +656,16 @@ static void *notify_user_info(PurpleConnection *gc, const char *who, PurpleNotif vcardEntry = (PurpleNotifyUserInfoEntry *)(vcardEntries->data); if (purple_notify_user_info_entry_get_label(vcardEntry) && purple_notify_user_info_entry_get_value(vcardEntry)){ label = purple_notify_user_info_entry_get_label(vcardEntry); - if (label == "Given Name"){ + if (label == "Given Name") { firstName = purple_notify_user_info_entry_get_value(vcardEntry); } - else if (label == "Family Name"){ + else if (label == "Family Name") { lastName = purple_notify_user_info_entry_get_value(vcardEntry); } - else if (label=="Nickname"){ + else if (label=="Nickname") { nickname = purple_notify_user_info_entry_get_value(vcardEntry); } - else if (label=="Full Name"){ + else if (label=="Full Name") { fullName = purple_notify_user_info_entry_get_value(vcardEntry); } else { diff --git a/include/Swiften/Server/Server.cpp b/include/Swiften/Server/Server.cpp new file mode 100644 index 00000000..09ba25a8 --- /dev/null +++ b/include/Swiften/Server/Server.cpp @@ -0,0 +1,144 @@ +/* + * 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/Server.h" + +#include +#include + +#include "Swiften/Base/String.h" +#include "Swiften/Base/foreach.h" +#include "Swiften/Network/Connection.h" +#include "Swiften/Network/ConnectionServer.h" +#include "Swiften/Network/ConnectionServerFactory.h" +#include "Swiften/Elements/Element.h" +#include "Swiften/Elements/Presence.h" +#include "Swiften/Elements/RosterPayload.h" +#include "Swiften/Network/NetworkFactories.h" +#include "Swiften/Session/SessionTracer.h" +#include "Swiften/Elements/IQ.h" +#include "Swiften/Elements/VCard.h" +#include "Swiften/Server/UserRegistry.h" +#include +#include "Swiften/Network/ConnectionServer.h" +#include "Swiften/Network/ConnectionFactory.h" +#include "Swiften/Server/ServerFromClientSession.h" +#include "Swiften/Server/ServerStanzaChannel.h" +#include "Swiften/Queries/IQRouter.h" + + +namespace Swift { + +Server::Server( + EventLoop* eventLoop, + NetworkFactories* networkFactories, + UserRegistry *userRegistry, + const JID& jid, + int port) : + userRegistry_(userRegistry), + port_(port), + eventLoop(eventLoop), + networkFactories_(networkFactories), + stopping(false), + selfJID(jid), + stanzaChannel_(){ + stanzaChannel_ = new ServerStanzaChannel(); + iqRouter_ = new IQRouter(stanzaChannel_); + tlsFactory = NULL; +} + +Server::~Server() { + stop(); + delete iqRouter_; + delete stanzaChannel_; +} + +void Server::start() { + assert(!serverFromClientConnectionServer); + serverFromClientConnectionServer = networkFactories_->getConnectionServerFactory()->createConnectionServer(port_); + serverFromClientConnectionServerSignalConnections.push_back( + serverFromClientConnectionServer->onNewConnection.connect( + boost::bind(&Server::handleNewClientConnection, this, _1))); +// serverFromClientConnectionServerSignalConnections.push_back( +// serverFromClientConnectionServer->onStopped.connect( +// boost::bind(&Server::handleClientConnectionServerStopped, this, _1))); + + serverFromClientConnectionServer->start(); +} + +void Server::stop() { + if (stopping) { + return; + } + + stopping = true; + + foreach(boost::shared_ptr session, serverFromClientSessions) { + session->finishSession(); + } + serverFromClientSessions.clear(); + + if (serverFromClientConnectionServer) { + serverFromClientConnectionServer->stop(); + foreach(boost::bsignals::connection& connection, serverFromClientConnectionServerSignalConnections) { + connection.disconnect(); + } + serverFromClientConnectionServerSignalConnections.clear(); + serverFromClientConnectionServer.reset(); + } + + stopping = false; +// onStopped(e); +} + +void Server::handleNewClientConnection(boost::shared_ptr connection) { + + boost::shared_ptr serverFromClientSession = boost::shared_ptr( + new ServerFromClientSession(idGenerator.generateID(), connection, + &payloadParserFactories, &payloadSerializers, userRegistry_)); + //serverFromClientSession->setAllowSASLEXTERNAL(); + + serverFromClientSession->onSessionStarted.connect( + boost::bind(&Server::handleSessionStarted, this, serverFromClientSession)); + serverFromClientSession->onSessionFinished.connect( + boost::bind(&Server::handleSessionFinished, this, + serverFromClientSession)); + serverFromClientSession->onDataRead.connect(boost::bind(&Server::handleDataRead, this, _1)); + serverFromClientSession->onDataWritten.connect(boost::bind(&Server::handleDataWritten, this, _1)); + + dynamic_cast(stanzaChannel_)->addSession(serverFromClientSession); + + if (tlsFactory) { + serverFromClientSession->addTLSEncryption(tlsFactory, cert); + } + + serverFromClientSession->startSession(); + + serverFromClientSessions.push_back(serverFromClientSession); +} + +void Server::handleDataRead(const SafeByteArray& data) { + onDataRead(data); +} + +void Server::handleDataWritten(const SafeByteArray& data) { + onDataWritten(data); +} + +void Server::handleSessionStarted(boost::shared_ptr) { +// onSelfConnected(true); +} + +void Server::handleSessionFinished(boost::shared_ptr session) { + serverFromClientSessions.erase(std::remove(serverFromClientSessions.begin(), serverFromClientSessions.end(), session), serverFromClientSessions.end()); +} + +void Server::addTLSEncryption(TLSServerContextFactory* tlsContextFactory, const PKCS12Certificate& cert) { + tlsFactory = tlsContextFactory; + this->cert = cert; +} + +} diff --git a/include/Swiften/Server/Server.h b/include/Swiften/Server/Server.h new file mode 100644 index 00000000..7d871241 --- /dev/null +++ b/include/Swiften/Server/Server.h @@ -0,0 +1,86 @@ +/* + * 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 + +#include "Swiften/Network/BoostIOServiceThread.h" +#include "Swiften/Network/ConnectionServer.h" +#include "Swiften/Server/UserRegistry.h" +#include "Swiften/Server/ServerSession.h" +#include "Swiften/Base/IDGenerator.h" +#include "Swiften/Server/ServerFromClientSession.h" +#include "Swiften/JID/JID.h" +#include "Swiften/Base/ByteArray.h" +#include "Swiften/Entity/Entity.h" +#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h" +#include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h" +#include "Swiften/TLS/PKCS12Certificate.h" + +namespace Swift { + class ConnectionServer; + class SessionTracer; + class EventLoop; + class NetworkFactories; + class StanzaChannel; + class IQRouter; + class TLSServerContextFactory; + + class Server : public Entity { + public: + Server(EventLoop* eventLoop, NetworkFactories* networkFactories, UserRegistry *userRegistry, const JID& jid, int port); + ~Server(); + + void start(); + void stop(); + + int getPort() const { + return port_; + } + + StanzaChannel* getStanzaChannel() const { + return stanzaChannel_; + } + + IQRouter* getIQRouter() const { + return iqRouter_; + } + + boost::signal onDataRead; + boost::signal onDataWritten; + + void addTLSEncryption(TLSServerContextFactory* tlsContextFactory, const PKCS12Certificate& cert); + + private: + void handleNewClientConnection(boost::shared_ptr c); + void handleSessionStarted(boost::shared_ptr); + void handleSessionFinished(boost::shared_ptr); + void handleElementReceived(boost::shared_ptr element, boost::shared_ptr session); + void handleDataRead(const SafeByteArray&); + void handleDataWritten(const SafeByteArray&); + + private: + IDGenerator idGenerator; + FullPayloadParserFactoryCollection payloadParserFactories; + FullPayloadSerializerCollection payloadSerializers; + UserRegistry *userRegistry_; + int port_; + EventLoop* eventLoop; + NetworkFactories* networkFactories_; + bool stopping; + boost::shared_ptr serverFromClientConnectionServer; + std::vector serverFromClientConnectionServerSignalConnections; + std::list > serverFromClientSessions; + JID selfJID; + StanzaChannel *stanzaChannel_; + IQRouter *iqRouter_; + TLSServerContextFactory *tlsFactory; + PKCS12Certificate cert; + }; +} diff --git a/include/Swiften/Server/ServerFromClientSession.cpp b/include/Swiften/Server/ServerFromClientSession.cpp new file mode 100644 index 00000000..1f1dee09 --- /dev/null +++ b/include/Swiften/Server/ServerFromClientSession.cpp @@ -0,0 +1,172 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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), + tlsLayer(0), + tlsConnected(false) { + userRegistry->onPasswordValid.connect(boost::bind(&ServerFromClientSession::handlePasswordValid, this, _1)); + userRegistry->onPasswordInvalid.connect(boost::bind(&ServerFromClientSession::handlePasswordInvalid, this, _1)); +} + +ServerFromClientSession::~ServerFromClientSession() { + if (tlsLayer) { + delete tlsLayer; + } +} + +void ServerFromClientSession::handlePasswordValid(const std::string &user) { + if (user != JID(user_, getLocalJID().getDomain()).toString()) + return; + getXMPPLayer()->writeElement(boost::shared_ptr(new AuthSuccess())); + authenticated_ = true; + getXMPPLayer()->resetParser(); +} + +void ServerFromClientSession::handlePasswordInvalid(const std::string &user) { + if (user != JID(user_, getLocalJID().getDomain()).toString() || authenticated_) + return; + getXMPPLayer()->writeElement(boost::shared_ptr(new AuthFailure)); + finishSession(AuthenticationFailedError); +} + +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() : createSafeByteArray("")); + if (userRegistry_->isValidUserPassword(JID(plainMessage.getAuthenticationID(), getLocalJID().getDomain()), plainMessage.getPassword())) { + user_ = plainMessage.getAuthenticationID(); + // we're waiting for usermanager signal now +// 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 (dynamic_cast(element.get()) != NULL) { + getXMPPLayer()->writeElement(boost::shared_ptr(new TLSProceed)); + getStreamStack()->addLayer(tlsLayer); + tlsLayer->connect(); + getXMPPLayer()->resetParser(); + } + 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_) { + if (tlsLayer && !tlsConnected) { + features->setHasStartTLS(); + } + 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; +} + +void ServerFromClientSession::addTLSEncryption(TLSServerContextFactory* tlsContextFactory, const PKCS12Certificate& cert) { + tlsLayer = new TLSServerLayer(tlsContextFactory); + if (!tlsLayer->setServerCertificate(cert)) { +// std::cout << "error\n"; + // TODO: +// onClosed(boost::shared_ptr(new Error(Error::InvalidTLSCertificateError))); + } + else { + tlsLayer->onError.connect(boost::bind(&ServerFromClientSession::handleTLSError, this)); + tlsLayer->onConnected.connect(boost::bind(&ServerFromClientSession::handleTLSConnected, this)); +// getStreamStack()->addLayer(tlsLayer); +// tlsLayer->onError.connect(boost::bind(&BasicSessionStream::handleTLSError, this)); +// tlsLayer->onConnected.connect(boost::bind(&BasicSessionStream::handleTLSConnected, this)); +// tlsLayer->connect(); + } +} + +} diff --git a/include/Swiften/Server/ServerFromClientSession.h b/include/Swiften/Server/ServerFromClientSession.h new file mode 100644 index 00000000..6483e3a0 --- /dev/null +++ b/include/Swiften/Server/ServerFromClientSession.h @@ -0,0 +1,76 @@ +/* + * 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 + +#include +#include +#include +#include +#include + +namespace Swift { + class ProtocolHeader; + class Element; + class Stanza; + class PayloadParserFactoryCollection; + class PayloadSerializerCollection; + class StreamStack; + class UserRegistry; + class XMPPLayer; + class ConnectionLayer; + class Connection; + class TLSServerLayer; + class TLSServerContextFactory; + class PKCS12Certificate; + + class ServerFromClientSession : public Session { + public: + ServerFromClientSession( + const std::string& id, + boost::shared_ptr connection, + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers, + UserRegistry* userRegistry); + ~ServerFromClientSession(); + + boost::signal onSessionStarted; + void setAllowSASLEXTERNAL(); + const std::string &getUser() { + return user_; + } + + void addTLSEncryption(TLSServerContextFactory* tlsContextFactory, const PKCS12Certificate& cert); + + private: + void handleElement(boost::shared_ptr); + void handleStreamStart(const ProtocolHeader& header); + void handlePasswordValid(const std::string &user); + void handlePasswordInvalid(const std::string &user); + + void setInitialized(); + bool isInitialized() const { + return initialized; + } + + void handleTLSError() { } + void handleTLSConnected() { tlsConnected = true; } + + private: + std::string id_; + UserRegistry* userRegistry_; + bool authenticated_; + bool initialized; + bool allowSASLEXTERNAL; + std::string user_; + TLSServerLayer* tlsLayer; + bool tlsConnected; + }; +} diff --git a/include/Swiften/Server/ServerSession.cpp b/include/Swiften/Server/ServerSession.cpp new file mode 100644 index 00000000..eb031f24 --- /dev/null +++ b/include/Swiften/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 + +namespace Swift { + +ServerSession::~ServerSession() { +} + +} diff --git a/include/Swiften/Server/ServerSession.h b/include/Swiften/Server/ServerSession.h new file mode 100644 index 00000000..486ebaa8 --- /dev/null +++ b/include/Swiften/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 + +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/include/Swiften/Server/ServerStanzaChannel.cpp b/include/Swiften/Server/ServerStanzaChannel.cpp new file mode 100644 index 00000000..690cc515 --- /dev/null +++ b/include/Swiften/Server/ServerStanzaChannel.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 "Swiften/Server/ServerStanzaChannel.h" +#include "Swiften/Base/Error.h" + +#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 boost::shared_ptr session) const { + return session->getRemoteJID().equals(jid, JID::WithResource); + } + JID jid; + }; +} + +void ServerStanzaChannel::addSession(boost::shared_ptr session) { + sessions.push_back(session); + session->onSessionFinished.connect(boost::bind(&ServerStanzaChannel::handleSessionFinished, this, _1, session)); + session->onElementReceived.connect(boost::bind(&ServerStanzaChannel::handleElement, this, _1, session)); +} + +void ServerStanzaChannel::removeSession(boost::shared_ptr session) { + session->onSessionFinished.disconnect(boost::bind(&ServerStanzaChannel::handleSessionFinished, this, _1, session)); + session->onElementReceived.disconnect(boost::bind(&ServerStanzaChannel::handleElement, this, _1, session)); + sessions.erase(std::remove(sessions.begin(), sessions.end(), session), sessions.end()); +} + +void ServerStanzaChannel::sendIQ(boost::shared_ptr iq) { + send(iq); +} + +void ServerStanzaChannel::sendMessage(boost::shared_ptr message) { + send(message); +} + +void ServerStanzaChannel::sendPresence(boost::shared_ptr presence) { + send(presence); +} + +void ServerStanzaChannel::finishSession(const JID& to, boost::shared_ptr element) { + std::vector > candidateSessions; + for (std::list >::const_iterator i = sessions.begin(); i != sessions.end(); ++i) { + if ((*i)->getRemoteJID().equals(to, JID::WithoutResource)) { + (*i)->sendElement(element); + candidateSessions.push_back(*i); + } + } + + for (std::vector >::const_iterator i = candidateSessions.begin(); i != candidateSessions.end(); ++i) { + (*i)->finishSession(); + } +} + +std::string ServerStanzaChannel::getNewIQID() { + return idGenerator.generateID(); +} + +void ServerStanzaChannel::send(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::list >::const_iterator i = std::find_if(sessions.begin(), sessions.end(), HasJID(to)); + if (i != sessions.end()) { + (*i)->sendElement(stanza); + return; + } + } + + // Look for candidate sessions + to = to.toBare(); + std::vector > candidateSessions; + for (std::list >::const_iterator i = sessions.begin(); i != sessions.end(); ++i) { + if ((*i)->getRemoteJID().equals(to, JID::WithoutResource)) { + candidateSessions.push_back(*i); + (*i)->sendElement(stanza); + } + } + if (candidateSessions.empty()) { + return; + } + + // Find the session with the highest priority +// std::vector::const_iterator i = std::max_element(sessions.begin(), sessions.end(), PriorityLessThan()); +// (*i)->sendStanza(stanza); + return; +} + +void ServerStanzaChannel::handleSessionFinished(const boost::optional&, const boost::shared_ptr& session) { + removeSession(session); + + Swift::Presence::ref presence = Swift::Presence::create(); + presence->setFrom(JID(session->getUser(), session->getLocalJID().getDomain()).toString()); + presence->setType(Swift::Presence::Unavailable); + onPresenceReceived(presence); +} + +void ServerStanzaChannel::handleElement(boost::shared_ptr element, const boost::shared_ptr& session) { + boost::shared_ptr stanza = boost::dynamic_pointer_cast(element); + if (!stanza) { + return; + } + + if (stanza->getFrom().toString().empty()) { + stanza->setFrom(session->getRemoteJID()); + } + + if (!stanza->getFrom().isValid()) + return; + + + boost::shared_ptr message = boost::dynamic_pointer_cast(stanza); + if (message) { + onMessageReceived(message); + return; + } + + boost::shared_ptr presence = boost::dynamic_pointer_cast(stanza); + if (presence) { + onPresenceReceived(presence); + return; + } + + boost::shared_ptr iq = boost::dynamic_pointer_cast(stanza); + if (iq) { + onIQReceived(iq); + return; + } +} + +void ServerStanzaChannel::handleSessionInitialized() { + onAvailableChanged(true); +} + +} diff --git a/include/Swiften/Server/ServerStanzaChannel.h b/include/Swiften/Server/ServerStanzaChannel.h new file mode 100644 index 00000000..1da89448 --- /dev/null +++ b/include/Swiften/Server/ServerStanzaChannel.h @@ -0,0 +1,51 @@ +/* + * 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/IDGenerator.h" +#include "Swiften/Server/ServerFromClientSession.h" +#include "Swiften/Client/StanzaChannel.h" +#include "Swiften/Elements/Message.h" +#include "Swiften/Elements/IQ.h" +#include "Swiften/Elements/Presence.h" + +namespace Swift { + class Error; + class ServerStanzaChannel : public StanzaChannel { + public: + void addSession(boost::shared_ptr session); + void removeSession(boost::shared_ptr session); + + void sendIQ(boost::shared_ptr iq); + void sendMessage(boost::shared_ptr message); + void sendPresence(boost::shared_ptr presence); + + void finishSession(const JID& to, boost::shared_ptr element); + + bool getStreamManagementEnabled() const { + return false; + } + + bool isAvailable() const { + return true; + } + + private: + std::string getNewIQID(); + void send(boost::shared_ptr stanza); + void handleSessionFinished(const boost::optional&, const boost::shared_ptr &session); + void handleElement(boost::shared_ptr element, const boost::shared_ptr &session); + void handleSessionInitialized(); + + private: + IDGenerator idGenerator; + std::list > sessions; + }; + +} diff --git a/include/Swiften/Server/ServerStanzaRouter.cpp b/include/Swiften/Server/ServerStanzaRouter.cpp new file mode 100644 index 00000000..17253597 --- /dev/null +++ b/include/Swiften/Server/ServerStanzaRouter.cpp @@ -0,0 +1,74 @@ +/* + * 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 + +#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) { + erase(clientSessions_, clientSession); +} + +} diff --git a/include/Swiften/Server/ServerStanzaRouter.h b/include/Swiften/Server/ServerStanzaRouter.h new file mode 100644 index 00000000..4a9493be --- /dev/null +++ b/include/Swiften/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 +#include + +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/include/Swiften/Server/SimpleUserRegistry.cpp b/include/Swiften/Server/SimpleUserRegistry.cpp new file mode 100644 index 00000000..a519ac22 --- /dev/null +++ b/include/Swiften/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 + +namespace Swift { + +SimpleUserRegistry::SimpleUserRegistry() { +} + +bool SimpleUserRegistry::isValidUserPassword(const JID& user, const SafeByteArray& 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, createSafeByteArray(password))); +} + +} diff --git a/include/Swiften/Server/SimpleUserRegistry.h b/include/Swiften/Server/SimpleUserRegistry.h new file mode 100644 index 00000000..324c0992 --- /dev/null +++ b/include/Swiften/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 +#include +#include + +namespace Swift { + + + class SimpleUserRegistry : public UserRegistry { + public: + SimpleUserRegistry(); + + virtual bool isValidUserPassword(const JID& user, const SafeByteArray& password) const; + void addUser(const JID& user, const std::string& password); + + private: + std::map users; + }; +} diff --git a/include/Swiften/Server/UserRegistry.cpp b/include/Swiften/Server/UserRegistry.cpp new file mode 100644 index 00000000..60bbb335 --- /dev/null +++ b/include/Swiften/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 + +namespace Swift { + +UserRegistry::~UserRegistry() { +} + +} diff --git a/include/Swiften/Server/UserRegistry.h b/include/Swiften/Server/UserRegistry.h new file mode 100644 index 00000000..cca4953b --- /dev/null +++ b/include/Swiften/Server/UserRegistry.h @@ -0,0 +1,26 @@ +/* + * 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 + +namespace Swift { + class JID; + + class UserRegistry { + public: + virtual ~UserRegistry(); + + virtual bool isValidUserPassword(const JID& user, const SafeByteArray& password) const = 0; + + boost::signal onPasswordValid; + boost::signal onPasswordInvalid; + + }; +} diff --git a/include/Swiften/StreamStack/TLSServerLayer.cpp b/include/Swiften/StreamStack/TLSServerLayer.cpp new file mode 100644 index 00000000..d2d9405e --- /dev/null +++ b/include/Swiften/StreamStack/TLSServerLayer.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Swiften/StreamStack/TLSServerLayer.h" + +#include + +#include "Swiften/TLS/TLSServerContextFactory.h" +#include "Swiften/TLS/TLSServerContext.h" + +namespace Swift { + +TLSServerLayer::TLSServerLayer(TLSServerContextFactory* factory) { + context = factory->createTLSServerContext(); + context->onDataForNetwork.connect(boost::bind(&TLSServerLayer::writeDataToChildLayer, this, _1)); + context->onDataForApplication.connect(boost::bind(&TLSServerLayer::writeDataToParentLayer, this, _1)); + context->onConnected.connect(onConnected); + context->onError.connect(onError); +} + +TLSServerLayer::~TLSServerLayer() { + delete context; +} + +void TLSServerLayer::connect() { + context->connect(); +} + +void TLSServerLayer::writeData(const SafeByteArray& data) { + context->handleDataFromApplication(data); +} + +void TLSServerLayer::handleDataRead(const SafeByteArray& data) { + context->handleDataFromNetwork(data); +} + +bool TLSServerLayer::setServerCertificate(const PKCS12Certificate& certificate) { + return context->setServerCertificate(certificate); +} + +Certificate::ref TLSServerLayer::getPeerCertificate() const { + return context->getPeerCertificate(); +} + +boost::shared_ptr TLSServerLayer::getPeerCertificateVerificationError() const { + return context->getPeerCertificateVerificationError(); +} + +} diff --git a/include/Swiften/StreamStack/TLSServerLayer.h b/include/Swiften/StreamStack/TLSServerLayer.h new file mode 100644 index 00000000..a3614f2d --- /dev/null +++ b/include/Swiften/StreamStack/TLSServerLayer.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Swiften/Base/boost_bsignals.h" + +#include "Swiften/Base/SafeByteArray.h" +#include "Swiften/StreamStack/StreamLayer.h" +#include "Swiften/TLS/Certificate.h" +#include "Swiften/TLS/CertificateVerificationError.h" + +namespace Swift { + class TLSServerContext; + class TLSServerContextFactory; + class PKCS12Certificate; + + class TLSServerLayer : public StreamLayer { + public: + TLSServerLayer(TLSServerContextFactory*); + ~TLSServerLayer(); + + void connect(); + bool setServerCertificate(const PKCS12Certificate&); + + Certificate::ref getPeerCertificate() const; + boost::shared_ptr getPeerCertificateVerificationError() const; + + void writeData(const SafeByteArray& data); + void handleDataRead(const SafeByteArray& data); + + TLSServerContext* getContext() const { + return context; + } + + public: + boost::signal onError; + boost::signal onConnected; + + private: + TLSServerContext* context; + }; +} diff --git a/include/Swiften/TLS/OpenSSL/OpenSSLServerContext.cpp b/include/Swiften/TLS/OpenSSL/OpenSSLServerContext.cpp new file mode 100644 index 00000000..da58b0b8 --- /dev/null +++ b/include/Swiften/TLS/OpenSSL/OpenSSLServerContext.cpp @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ +#include "Swiften/Base/Platform.h" + +#ifdef SWIFTEN_PLATFORM_WINDOWS +#include +#include +#endif + +#include +#include +#include + + +#include "Swiften/TLS/OpenSSL/OpenSSLServerContext.h" +#include "Swiften/TLS/OpenSSL/OpenSSLCertificate.h" +#include "Swiften/TLS/PKCS12Certificate.h" + +#pragma GCC diagnostic ignored "-Wold-style-cast" + +namespace Swift { + +static const int MAX_FINISHED_SIZE = 4096; +static const int SSL_READ_BUFFERSIZE = 8192; + +static void freeX509Stack(STACK_OF(X509)* stack) { + sk_X509_free(stack); +} + +static int _sx_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) { + return 1; +} + +OpenSSLServerContext::OpenSSLServerContext() : state_(Start), context_(0), handle_(0), readBIO_(0), writeBIO_(0) { + ensureLibraryInitialized(); + context_ = SSL_CTX_new(TLSv1_server_method()); + SSL_CTX_set_verify(context_, SSL_VERIFY_PEER, _sx_ssl_verify_callback); + + // Load system certs +#if defined(SWIFTEN_PLATFORM_WINDOWS) + X509_STORE* store = SSL_CTX_get_cert_store(context_); + HCERTSTORE systemStore = CertOpenSystemStore(0, "ROOT"); + if (systemStore) { + PCCERT_CONTEXT certContext = NULL; + while (true) { + certContext = CertFindCertificateInStore(systemStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, certContext); + if (!certContext) { + break; + } + ByteArray certData(certContext->pbCertEncoded, certContext->cbCertEncoded); + OpenSSLCertificate cert(certData); + if (store && cert.getInternalX509()) { + X509_STORE_add_cert(store, cert.getInternalX509().get()); + } + } + } +#elif !defined(SWIFTEN_PLATFORM_MACOSX) + SSL_CTX_load_verify_locations(context_, NULL, "/etc/ssl/certs"); +#endif +} + +OpenSSLServerContext::~OpenSSLServerContext() { + SSL_free(handle_); + SSL_CTX_free(context_); +} + +void OpenSSLServerContext::ensureLibraryInitialized() { + static bool isLibraryInitialized = false; + if (!isLibraryInitialized) { + SSL_load_error_strings(); + SSL_library_init(); + OpenSSL_add_all_algorithms(); + + // Disable compression + /* + STACK_OF(SSL_COMP)* compressionMethods = SSL_COMP_get_compression_methods(); + sk_SSL_COMP_zero(compressionMethods);*/ + + isLibraryInitialized = true; + } +} + +void OpenSSLServerContext::connect() { + handle_ = SSL_new(context_); + // Ownership of BIOs is ransferred + readBIO_ = BIO_new(BIO_s_mem()); + writeBIO_ = BIO_new(BIO_s_mem()); + SSL_set_bio(handle_, readBIO_, writeBIO_); + + state_ = Connecting; + doConnect(); +} + +void OpenSSLServerContext::doConnect() { + int connectResult = SSL_accept(handle_); + int error = SSL_get_error(handle_, connectResult); +// std::cout << "DO CONNECT\n"; + switch (error) { + case SSL_ERROR_NONE: { + if (SSL_is_init_finished(handle_)) { +// std::cout << "FINISHED\n"; + state_ = Connected; + //std::cout << x->name << std::endl; + //const char* comp = SSL_get_current_compression(handle_); + //std::cout << "Compression: " << SSL_COMP_get_name(comp) << std::endl; + onConnected(); + ERR_print_errors_fp(stdout); + sendPendingDataToNetwork(); + } + break; + } + case SSL_ERROR_WANT_READ: + sendPendingDataToNetwork(); + break; + default: + state_ = Error; +// std::cout << "AAAAAAAA 1 " << error << " " << connectResult << "\n"; + ERR_print_errors_fp(stdout); + onError(); + } +} + +void OpenSSLServerContext::sendPendingDataToNetwork() { + int size = BIO_pending(writeBIO_); + if (size > 0) { + SafeByteArray data; + data.resize(size); + BIO_read(writeBIO_, vecptr(data), size); + onDataForNetwork(data); + } +} + +void OpenSSLServerContext::handleDataFromNetwork(const SafeByteArray& data) { + BIO_write(readBIO_, vecptr(data), data.size()); +// std::cout << "handleDataFromNetwork\n"; + switch (state_) { + case Connecting: + doConnect(); + break; + case Connected: + sendPendingDataToApplication(); + break; + case Start: assert(false); break; + case Error: /*assert(false);*/ break; + } +} + +void OpenSSLServerContext::handleDataFromApplication(const SafeByteArray& data) { +// std::cout << "SSL_WRITE\n"; + if (SSL_write(handle_, vecptr(data), data.size()) >= 0) { + sendPendingDataToNetwork(); + } + else { + state_ = Error; +// std::cout << "AAAAAAAA 2\n"; + onError(); + } +} + +void OpenSSLServerContext::sendPendingDataToApplication() { + SafeByteArray data; + data.resize(SSL_READ_BUFFERSIZE); + int ret = SSL_read(handle_, vecptr(data), data.size()); + while (ret > 0) { + data.resize(ret); + onDataForApplication(data); + data.resize(SSL_READ_BUFFERSIZE); + ret = SSL_read(handle_, vecptr(data), data.size()); + } + if (ret < 0 && SSL_get_error(handle_, ret) != SSL_ERROR_WANT_READ) { + state_ = Error; +// std::cout << "AAAAAAAA 3\n"; + onError(); + } +} + +bool OpenSSLServerContext::setServerCertificate(const PKCS12Certificate& certificate) { + if (certificate.isNull()) { +// std::cout << "error 1\n"; + return false; + } + + // Create a PKCS12 structure + BIO* bio = BIO_new(BIO_s_mem()); + BIO_write(bio, vecptr(certificate.getData()), certificate.getData().size()); + boost::shared_ptr pkcs12(d2i_PKCS12_bio(bio, NULL), PKCS12_free); + BIO_free(bio); + if (!pkcs12) { +// std::cout << "error 2\n"; + return false; + } + + // Parse PKCS12 + X509 *certPtr = 0; + EVP_PKEY* privateKeyPtr = 0; + STACK_OF(X509)* caCertsPtr = 0; + int result = PKCS12_parse(pkcs12.get(), reinterpret_cast(vecptr(certificate.getPassword())), &privateKeyPtr, &certPtr, &caCertsPtr); + if (result != 1) { +// std::cout << "error 3\n"; + return false; + } + boost::shared_ptr cert(certPtr, X509_free); + boost::shared_ptr privateKey(privateKeyPtr, EVP_PKEY_free); + boost::shared_ptr caCerts(caCertsPtr, freeX509Stack); + + // Use the key & certificates + if (SSL_CTX_use_certificate(context_, cert.get()) != 1) { +// std::cout << "error 4\n"; + return false; + } + if (SSL_CTX_use_PrivateKey(context_, privateKey.get()) != 1) { +// std::cout << "error 5\n"; + return false; + } + return true; +} + +Certificate::ref OpenSSLServerContext::getPeerCertificate() const { + boost::shared_ptr x509Cert(SSL_get_peer_certificate(handle_), X509_free); + if (x509Cert) { + return Certificate::ref(new OpenSSLCertificate(x509Cert)); + } + else { + return Certificate::ref(); + } +} + +boost::shared_ptr OpenSSLServerContext::getPeerCertificateVerificationError() const { + int verifyResult = SSL_get_verify_result(handle_); + if (verifyResult != X509_V_OK) { + return boost::shared_ptr(new CertificateVerificationError(getVerificationErrorTypeForResult(verifyResult))); + } + else { + return boost::shared_ptr(); + } +} + +ByteArray OpenSSLServerContext::getFinishMessage() const { + ByteArray data; + data.resize(MAX_FINISHED_SIZE); + size_t size = SSL_get_finished(handle_, vecptr(data), data.size()); + data.resize(size); + return data; +} + +CertificateVerificationError::Type OpenSSLServerContext::getVerificationErrorTypeForResult(int result) { + assert(result != 0); + switch (result) { + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + return CertificateVerificationError::NotYetValid; + + case X509_V_ERR_CERT_HAS_EXPIRED: + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + return CertificateVerificationError::Expired; + + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: + return CertificateVerificationError::SelfSigned; + + case X509_V_ERR_CERT_UNTRUSTED: + return CertificateVerificationError::Untrusted; + + case X509_V_ERR_CERT_REJECTED: + return CertificateVerificationError::Rejected; + + case X509_V_ERR_INVALID_PURPOSE: + return CertificateVerificationError::InvalidPurpose; + + case X509_V_ERR_PATH_LENGTH_EXCEEDED: + return CertificateVerificationError::PathLengthExceeded; + + case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: + case X509_V_ERR_CERT_SIGNATURE_FAILURE: + case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: + return CertificateVerificationError::InvalidSignature; + + case X509_V_ERR_INVALID_CA: + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: + return CertificateVerificationError::InvalidCA; + + case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: + case X509_V_ERR_AKID_SKID_MISMATCH: + case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: + case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: + return CertificateVerificationError::UnknownError; + + // Unused / should not happen + case X509_V_ERR_CERT_REVOKED: + case X509_V_ERR_OUT_OF_MEM: + case X509_V_ERR_UNABLE_TO_GET_CRL: + case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: + case X509_V_ERR_CRL_SIGNATURE_FAILURE: + case X509_V_ERR_CRL_NOT_YET_VALID: + case X509_V_ERR_CRL_HAS_EXPIRED: + case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: + case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: + case X509_V_ERR_CERT_CHAIN_TOO_LONG: + case X509_V_ERR_APPLICATION_VERIFICATION: + default: + return CertificateVerificationError::UnknownError; + } +} + +} diff --git a/include/Swiften/TLS/OpenSSL/OpenSSLServerContext.h b/include/Swiften/TLS/OpenSSL/OpenSSLServerContext.h new file mode 100644 index 00000000..9d556e6f --- /dev/null +++ b/include/Swiften/TLS/OpenSSL/OpenSSLServerContext.h @@ -0,0 +1,53 @@ +/* + * 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 "Swiften/TLS/TLSServerContext.h" +#include "Swiften/Base/ByteArray.h" + +namespace Swift { + class PKCS12Certificate; + + class OpenSSLServerContext : public TLSServerContext, boost::noncopyable { + public: + OpenSSLServerContext(); + ~OpenSSLServerContext(); + + void connect(); + bool setServerCertificate(const PKCS12Certificate& cert); + + void handleDataFromNetwork(const SafeByteArray&); + void handleDataFromApplication(const SafeByteArray&); + + Certificate::ref getPeerCertificate() const; + boost::shared_ptr getPeerCertificateVerificationError() const; + + virtual ByteArray getFinishMessage() const; + + private: + static void ensureLibraryInitialized(); + + static CertificateVerificationError::Type getVerificationErrorTypeForResult(int); + + void doConnect(); + void sendPendingDataToNetwork(); + void sendPendingDataToApplication(); + + private: + enum State { Start, Connecting, Connected, Error }; + + State state_; + SSL_CTX* context_; + SSL* handle_; + BIO* readBIO_; + BIO* writeBIO_; + }; +} diff --git a/include/Swiften/TLS/OpenSSL/OpenSSLServerContextFactory.cpp b/include/Swiften/TLS/OpenSSL/OpenSSLServerContextFactory.cpp new file mode 100644 index 00000000..76791460 --- /dev/null +++ b/include/Swiften/TLS/OpenSSL/OpenSSLServerContextFactory.cpp @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Swiften/TLS/OpenSSL/OpenSSLServerContextFactory.h" +#include "Swiften/TLS/OpenSSL/OpenSSLServerContext.h" + +namespace Swift { + +bool OpenSSLServerContextFactory::canCreate() const { + return true; +} + +TLSServerContext* OpenSSLServerContextFactory::createTLSServerContext() { + return new OpenSSLServerContext(); +} + +} diff --git a/include/Swiften/TLS/OpenSSL/OpenSSLServerContextFactory.h b/include/Swiften/TLS/OpenSSL/OpenSSLServerContextFactory.h new file mode 100644 index 00000000..2ad839e8 --- /dev/null +++ b/include/Swiften/TLS/OpenSSL/OpenSSLServerContextFactory.h @@ -0,0 +1,17 @@ +/* + * 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 "Swiften/TLS/TLSServerContextFactory.h" + +namespace Swift { + class OpenSSLServerContextFactory : public TLSServerContextFactory { + public: + bool canCreate() const; + virtual TLSServerContext* createTLSServerContext(); + }; +} diff --git a/include/Swiften/TLS/TLSServerContext.cpp b/include/Swiften/TLS/TLSServerContext.cpp new file mode 100644 index 00000000..e62b6be5 --- /dev/null +++ b/include/Swiften/TLS/TLSServerContext.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 "Swiften/TLS/TLSServerContext.h" + +namespace Swift { + +TLSServerContext::~TLSServerContext() { +} + +} diff --git a/include/Swiften/TLS/TLSServerContext.h b/include/Swiften/TLS/TLSServerContext.h new file mode 100644 index 00000000..a6a04039 --- /dev/null +++ b/include/Swiften/TLS/TLSServerContext.h @@ -0,0 +1,41 @@ +/* + * 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 "Swiften/Base/boost_bsignals.h" +#include + +#include "Swiften/Base/SafeByteArray.h" +#include "Swiften/TLS/Certificate.h" +#include "Swiften/TLS/CertificateVerificationError.h" + +namespace Swift { + class PKCS12Certificate; + + class TLSServerContext { + public: + virtual ~TLSServerContext(); + + virtual void connect() = 0; + + virtual bool setServerCertificate(const PKCS12Certificate& cert) = 0; + + virtual void handleDataFromNetwork(const SafeByteArray&) = 0; + virtual void handleDataFromApplication(const SafeByteArray&) = 0; + + virtual Certificate::ref getPeerCertificate() const = 0; + virtual CertificateVerificationError::ref getPeerCertificateVerificationError() const = 0; + + virtual ByteArray getFinishMessage() const = 0; + + public: + boost::signal onDataForNetwork; + boost::signal onDataForApplication; + boost::signal onError; + boost::signal onConnected; + }; +} diff --git a/include/Swiften/TLS/TLSServerContextFactory.cpp b/include/Swiften/TLS/TLSServerContextFactory.cpp new file mode 100644 index 00000000..7a823346 --- /dev/null +++ b/include/Swiften/TLS/TLSServerContextFactory.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 "Swiften/TLS/TLSServerContextFactory.h" + +namespace Swift { + +TLSServerContextFactory::~TLSServerContextFactory() { +} + +} diff --git a/include/Swiften/TLS/TLSServerContextFactory.h b/include/Swiften/TLS/TLSServerContextFactory.h new file mode 100644 index 00000000..e6e9f31b --- /dev/null +++ b/include/Swiften/TLS/TLSServerContextFactory.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +namespace Swift { + class TLSServerContext; + + class TLSServerContextFactory { + public: + virtual ~TLSServerContextFactory(); + + virtual bool canCreate() const = 0; + + virtual TLSServerContext* createTLSServerContext() = 0; + }; +} diff --git a/include/transport/networkpluginserver.h b/include/transport/networkpluginserver.h index 777e061e..d7345e73 100644 --- a/include/transport/networkpluginserver.h +++ b/include/transport/networkpluginserver.h @@ -24,7 +24,7 @@ #include "Swiften/Swiften.h" #include "Swiften/Presence/PresenceOracle.h" #include "Swiften/Disco/EntityCapsManager.h" -#include "Swiften/Network/ConnectionServer.h" +#include "Swiften/Network/BoostConnectionServer.h" #include "Swiften/Network/Connection.h" #include "storagebackend.h" @@ -94,7 +94,7 @@ class NetworkPluginServer { VCardResponder *m_vcardResponder; RosterResponder *m_rosterResponder; Config *m_config; - boost::shared_ptr m_server; + boost::shared_ptr m_server; std::list m_clients; Swift::Timer::ref m_pingTimer; Component *m_component; diff --git a/include/transport/transport.h b/include/transport/transport.h index 60331759..b7bd92ef 100644 --- a/include/transport/transport.h +++ b/include/transport/transport.h @@ -178,7 +178,6 @@ namespace Transport { Swift::Component *m_component; Swift::Server *m_server; Swift::Timer::ref m_reconnectTimer; - Swift::BoostIOServiceThread m_boostIOServiceThread; Swift::EntityCapsManager *m_entityCapsManager; Swift::CapsManager *m_capsManager; Swift::CapsMemoryStorage *m_capsMemoryStorage; @@ -194,6 +193,7 @@ namespace Transport { std::string m_protocol; Swift::JID m_jid; Factory *m_factory; + Swift::EventLoop *m_loop; friend class User; friend class UserRegistration; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 21362895..d067e60c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 2.6) FILE(GLOB SRC *.cpp *.h) -FILE(GLOB HEADERS ../../include/transport/*.h) +FILE(GLOB_RECURSE SWIFTEN_SRC ../include/Swiften/*.cpp) +FILE(GLOB HEADERS ../include/transport/*.h) if (PROTOBUF_FOUND) PROTOBUF_GENERATE_CPP(PROTOBUF_SRC PROTOBUF_HDRS "pbnetwork.proto") @@ -8,7 +9,7 @@ endif() # SOURCE_GROUP(headers FILES ${HEADERS}) -ADD_LIBRARY(transport SHARED ${HEADERS} ${SRC} ${PROTOBUF_SRC} ${PROTOBUF_HDRS}) +ADD_LIBRARY(transport SHARED ${HEADERS} ${SRC} ${SWIFTEN_SRC} ${PROTOBUF_SRC} ${PROTOBUF_HDRS}) ADD_DEFINITIONS(-fPIC) TARGET_LINK_LIBRARIES(transport ${Boost_LIBRARIES} ${SQLITE3_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES}) diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index 5c5b012e..ebbe874d 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -33,6 +33,7 @@ #include "Swiften/Swiften.h" #include "Swiften/Server/ServerStanzaChannel.h" #include "Swiften/Elements/StreamError.h" +#include "Swiften/Network/BoostConnectionServer.h" #include "pbnetwork.pb.h" #include "sys/wait.h" #include "sys/signal.h" @@ -134,7 +135,7 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U m_rosterResponder->onBuddyUpdated.connect(boost::bind(&NetworkPluginServer::handleBuddyUpdated, this, _1, _2)); m_rosterResponder->start(); - m_server = component->getNetworkFactories()->getConnectionFactory()->createConnectionServer(boost::lexical_cast(CONFIG_STRING(m_config, "service.backend_port"))); + m_server = Swift::BoostConnectionServer::create(Swift::HostAddress(CONFIG_STRING(m_config, "service.backend_host")), boost::lexical_cast(CONFIG_STRING(m_config, "service.backend_port")), component->getNetworkFactories()->getIOServiceThread()->getIOService(), component->m_loop); m_server->onNewConnection.connect(boost::bind(&NetworkPluginServer::handleNewClientConnection, this, _1)); m_server->start(); diff --git a/src/rostermanager.cpp b/src/rostermanager.cpp index 3ff7037c..15742e27 100644 --- a/src/rostermanager.cpp +++ b/src/rostermanager.cpp @@ -143,7 +143,7 @@ void RosterManager::sendRIE() { item.setJID(buddy->getJID().toBare()); item.setName(buddy->getAlias()); item.setAction(Swift::RosterItemExchangePayload::Item::Add); - item.setGroups(buddy->getGroups()); +// item.setGroups(buddy->getGroups()); payload->addItem(item); } diff --git a/src/transport.cpp b/src/transport.cpp index 4695b9a2..3d79ae86 100644 --- a/src/transport.cpp +++ b/src/transport.cpp @@ -60,6 +60,7 @@ Component::Component(Swift::EventLoop *loop, Config *config, Factory *factory) { m_reconnectCount = 0; m_config = config; m_factory = factory; + m_loop = loop; m_jid = Swift::JID(CONFIG_STRING(m_config, "service.jid"));