Changeset - c6224941ceab
[Not reviewed]
0 7 0
HanzZ - 14 years ago 2011-07-17 03:56:19
hanzz.k@gmail.com
Fixed removing users
7 files changed with 22 insertions and 2 deletions:
0 comments (0 inline, 0 general)
include/Swiften/Server/Server.cpp
Show inline comments
 
/*
 
 * 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 <string>
 
#include <boost/bind.hpp>
 

	
 
#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 <string>
 
#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"
 
#include <iostream>
 

	
 

	
 
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() {
 
	if (serverFromClientConnectionServer) {
 
		return;
 
	}
 
	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<ServerFromClientSession> 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> connection) {
 

	
 
	boost::shared_ptr<ServerFromClientSession> serverFromClientSession = boost::shared_ptr<ServerFromClientSession>(
 
			new ServerFromClientSession(idGenerator.generateID(), connection, 
 
					getPayloadParserFactories(), getPayloadSerializers(), userRegistry_));
 
	//serverFromClientSession->setAllowSASLEXTERNAL();
 

	
 
	serverFromClientSession->onSessionStarted.connect(
 
			boost::bind(&Server::handleSessionStarted, this, serverFromClientSession));
 
	serverFromClientSession->onSessionFinished.connect(
 
			boost::bind(&Server::handleSessionFinished, this, 
 
			serverFromClientSession));
 
	serverFromClientSession->onPasswordInvalid.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));
 

	
 
	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<ServerFromClientSession> session) {
 
	dynamic_cast<ServerStanzaChannel *>(stanzaChannel_)->addSession(session);
 
}
 

	
 
void Server::handleSessionFinished(boost::shared_ptr<ServerFromClientSession> 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;
 
}
 

	
 
}
include/Swiften/Server/ServerFromClientSession.cpp
Show inline comments
 
/*
 
 * 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 <boost/bind.hpp>
 

	
 
#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>
 
#include <Swiften/StreamStack/StreamStack.h>
 
#include <Swiften/StreamStack/TLSServerLayer.h>
 
#include <Swiften/Elements/StartTLSRequest.h>
 
#include <Swiften/Elements/TLSProceed.h>
 
#include <iostream>
 

	
 
namespace Swift {
 

	
 
ServerFromClientSession::ServerFromClientSession(
 
		const std::string& id,
 
		boost::shared_ptr<Connection> 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;
 
	if (!isInitialized()) {
 
		getXMPPLayer()->writeElement(boost::shared_ptr<AuthSuccess>(new AuthSuccess()));
 
		authenticated_ = true;
 
		getXMPPLayer()->resetParser();
 
	}
 
}
 

	
 
void ServerFromClientSession::handlePasswordInvalid(const std::string &user) {
 
	if (user != JID(user_, getLocalJID().getDomain()).toString() || authenticated_)
 
		return;
 
	if (!isInitialized()) {
 
		user_ = "/././";
 
		getXMPPLayer()->writeElement(boost::shared_ptr<AuthFailure>(new AuthFailure));
 
		finishSession(AuthenticationFailedError);
 
		onPasswordInvalid();
 
	}
 
}
 

	
 
void ServerFromClientSession::handleElement(boost::shared_ptr<Element> element) {
 
	if (isInitialized()) {
 
		onElementReceived(element);
 
	}
 
	else {
 
		if (AuthRequest* authRequest = dynamic_cast<AuthRequest*>(element.get())) {
 
			if (authRequest->getMechanism() == "PLAIN" || (allowSASLEXTERNAL && authRequest->getMechanism() == "EXTERNAL")) {
 
				if (authRequest->getMechanism() == "EXTERNAL") {
 
						getXMPPLayer()->writeElement(boost::shared_ptr<AuthSuccess>(new AuthSuccess()));
 
						authenticated_ = true;
 
						getXMPPLayer()->resetParser();
 
				}
 
				else {
 
					PLAINMessage plainMessage(authRequest->getMessage() ? *authRequest->getMessage() : createSafeByteArray(""));
 
					user_ = plainMessage.getAuthenticationID();
 
					if (userRegistry_->isValidUserPassword(JID(plainMessage.getAuthenticationID(), getLocalJID().getDomain()), plainMessage.getPassword())) {
 
						// we're waiting for usermanager signal now
 
// 						authenticated_ = true;
 
// 						getXMPPLayer()->resetParser();
 
					}
 
					else {
 
						getXMPPLayer()->writeElement(boost::shared_ptr<AuthFailure>(new AuthFailure));
 
						finishSession(AuthenticationFailedError);
 
					}
 
				}
 
			}
 
			else {
 
				getXMPPLayer()->writeElement(boost::shared_ptr<AuthFailure>(new AuthFailure));
 
				finishSession(NoSupportedAuthMechanismsError);
 
			}
 
		}
 
		else if (dynamic_cast<StartTLSRequest*>(element.get()) != NULL) {
 
			getXMPPLayer()->writeElement(boost::shared_ptr<TLSProceed>(new TLSProceed));
 
			getStreamStack()->addLayer(tlsLayer);
 
			tlsLayer->connect();
 
			getXMPPLayer()->resetParser();
 
		}
 
		else if (IQ* iq = dynamic_cast<IQ*>(element.get())) {
 
			if (boost::shared_ptr<ResourceBind> resourceBind = iq->getPayload<ResourceBind>()) {
 
				std::string bucket = "abcdefghijklmnopqrstuvwxyz";
 
				std::string uuid;
 
				for (int i = 0; i < 10; i++) {
 
					uuid += bucket[rand() % bucket.size()];
 
				}
 
				setRemoteJID(JID(user_, getLocalJID().getDomain(), uuid));
include/Swiften/Server/ServerFromClientSession.h
Show inline comments
 
/*
 
 * 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 <boost/shared_ptr.hpp>
 
#include <Swiften/Base/boost_bsignals.h>
 
#include <boost/enable_shared_from_this.hpp>
 

	
 
#include <string>
 
#include <Swiften/Session/Session.h>
 
#include <Swiften/JID/JID.h>
 
#include <Swiften/Network/Connection.h>
 
#include <Swiften/Base/ByteArray.h>
 

	
 
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> connection, 
 
					PayloadParserFactoryCollection* payloadParserFactories, 
 
					PayloadSerializerCollection* payloadSerializers,
 
					UserRegistry* userRegistry);
 
			~ServerFromClientSession();
 

	
 
			boost::signal<void ()> onSessionStarted;
 
			boost::signal<void ()> onPasswordInvalid;
 
			void setAllowSASLEXTERNAL();
 
			const std::string &getUser() {
 
				return user_;
 
			}
 

	
 
			void addTLSEncryption(TLSServerContextFactory* tlsContextFactory, const PKCS12Certificate& cert);
 

	
 
		private:
 
			void handleElement(boost::shared_ptr<Element>);
 
			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;
 
	};
 
}
include/Swiften/Server/ServerStanzaChannel.cpp
Show inline comments
 
@@ -10,101 +10,99 @@
 
#include <boost/bind.hpp>
 

	
 
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<ServerFromClientSession> session) const {
 
			return session->getRemoteJID().equals(jid, JID::WithResource);
 
		}
 
		JID jid;
 
	};
 
}
 

	
 
void ServerStanzaChannel::addSession(boost::shared_ptr<ServerFromClientSession> session) {
 
	sessions[session->getRemoteJID().toBare().toString()].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<ServerFromClientSession> session) {
 
	session->onSessionFinished.disconnect(boost::bind(&ServerStanzaChannel::handleSessionFinished, this, _1, session));
 
	session->onElementReceived.disconnect(boost::bind(&ServerStanzaChannel::handleElement, this, _1, session));
 
	std::list<boost::shared_ptr<ServerFromClientSession> > &lst = sessions[session->getRemoteJID().toBare().toString()];
 
	lst.erase(std::remove(lst.begin(), lst.end(), session), lst.end());
 
}
 

	
 
void ServerStanzaChannel::sendIQ(boost::shared_ptr<IQ> iq) {
 
	send(iq);
 
}
 

	
 
void ServerStanzaChannel::sendMessage(boost::shared_ptr<Message> message) {
 
	send(message);
 
}
 

	
 
void ServerStanzaChannel::sendPresence(boost::shared_ptr<Presence> presence) {
 
	send(presence);
 
}
 

	
 
void ServerStanzaChannel::finishSession(const JID& to, boost::shared_ptr<Element> element) {
 
	std::vector<boost::shared_ptr<ServerFromClientSession> > candidateSessions;
 
	for (std::list<boost::shared_ptr<ServerFromClientSession> >::const_iterator i = sessions[to.toBare().toString()].begin(); i != sessions[to.toBare().toString()].end(); ++i) {
 
		if ((*i)->getRemoteJID().equals(to, JID::WithoutResource)) {
 
		(*i)->sendElement(element);
 
		candidateSessions.push_back(*i);
 
	}
 
	}
 

	
 
	for (std::vector<boost::shared_ptr<ServerFromClientSession> >::const_iterator i = candidateSessions.begin(); i != candidateSessions.end(); ++i) {
 
		(*i)->finishSession();
 
		sessions[to.toBare().toString()].remove(*i);
 
	}
 
}
 

	
 
std::string ServerStanzaChannel::getNewIQID() {
 
	return idGenerator.generateID();
 
}
 

	
 
void ServerStanzaChannel::send(boost::shared_ptr<Stanza> 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<boost::shared_ptr<ServerFromClientSession> >::const_iterator i = std::find_if(sessions[stanza->getTo().toBare().toString()].begin(), sessions[stanza->getTo().toBare().toString()].end(), HasJID(to));
 
		if (i != sessions[stanza->getTo().toBare().toString()].end()) {
 
			(*i)->sendElement(stanza);
 
			return;
 
		}
 
	}
 

	
 
	// Look for candidate sessions
 
	to = to.toBare();
 
	std::vector<boost::shared_ptr<ServerFromClientSession> > candidateSessions;
 
	for (std::list<boost::shared_ptr<ServerFromClientSession> >::const_iterator i = sessions[stanza->getTo().toBare().toString()].begin(); i != sessions[stanza->getTo().toBare().toString()].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<ServerSession*>::const_iterator i = std::max_element(sessions.begin(), sessions.end(), PriorityLessThan());
 
// 	(*i)->sendStanza(stanza);
 
	return;
 
}
 

	
 
void ServerStanzaChannel::handleSessionFinished(const boost::optional<Session::SessionError>&, const boost::shared_ptr<ServerFromClientSession>& session) {
 
	removeSession(session);
 

	
 
	Swift::Presence::ref presence = Swift::Presence::create();
 
	presence->setFrom(session->getRemoteJID());
src/networkpluginserver.cpp
Show inline comments
 
@@ -477,96 +477,97 @@ void NetworkPluginServer::handleDataRead(Backend *c, const Swift::SafeByteArray
 
			case pbnetwork::WrapperMessage_Type_TYPE_ROOM_NICKNAME_CHANGED:
 
				handleRoomChangedPayload(wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_VCARD:
 
				handleVCardPayload(wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_BUDDY_TYPING:
 
				handleChatStatePayload(wrapper.payload(), Swift::ChatState::Composing);
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_BUDDY_TYPED:
 
				handleChatStatePayload(wrapper.payload(), Swift::ChatState::Paused);
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_BUDDY_STOPPED_TYPING:
 
				handleChatStatePayload(wrapper.payload(), Swift::ChatState::Active);
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_AUTH_REQUEST:
 
				handleAuthorizationPayload(wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_ATTENTION:
 
				handleAttentionPayload(wrapper.payload());
 
				break;
 
			default:
 
				return;
 
		}
 
	}
 
}
 

	
 
void NetworkPluginServer::send(boost::shared_ptr<Swift::Connection> &c, const std::string &data) {
 
	char header[4];
 
	*((int*)(header)) = htonl(data.size());
 
	c->write(Swift::createSafeByteArray(std::string(header, 4) + data));
 
}
 

	
 
void NetworkPluginServer::pingTimeout() {
 
	// check ping responses
 
	for (std::list<Backend *>::const_iterator it = m_clients.begin(); it != m_clients.end(); it++) {
 
		if ((*it)->pongReceived) {
 
			sendPing((*it));
 
		}
 
		else {
 
			exec_(CONFIG_STRING(m_config, "service.backend").c_str(), CONFIG_STRING(m_config, "service.backend_host").c_str(), CONFIG_STRING(m_config, "service.backend_port").c_str(), m_config->getConfigFile().c_str());
 
		}
 
	}
 
	m_pingTimer->start();
 
}
 

	
 
void NetworkPluginServer::handleUserCreated(User *user) {
 
	Backend *c = getFreeClient();
 

	
 
	if (!c) {
 
		LOG4CXX_ERROR(logger, "There is no backend to handle user " << user->getJID().toString());
 
		user->handleDisconnected("Internal Server Error (no free backend to handle your session), please reconnect.");
 
		return;
 
	}
 
	user->setData(c);
 
	c->users.push_back(user);
 

	
 
// 	UserInfo userInfo = user->getUserInfo();
 
	user->onReadyToConnect.connect(boost::bind(&NetworkPluginServer::handleUserReadyToConnect, this, user));
 
	user->onPresenceChanged.connect(boost::bind(&NetworkPluginServer::handleUserPresenceChanged, this, user, _1));
 
	user->onRoomJoined.connect(boost::bind(&NetworkPluginServer::handleRoomJoined, this, user, _1, _2, _3));
 
	user->onRoomLeft.connect(boost::bind(&NetworkPluginServer::handleRoomLeft, this, user, _1));
 
}
 

	
 
void NetworkPluginServer::handleUserReadyToConnect(User *user) {
 
	UserInfo userInfo = user->getUserInfo();
 

	
 
	pbnetwork::Login login;
 
	login.set_user(user->getJID().toBare());
 
	login.set_legacyname(userInfo.uin);
 
	login.set_password(userInfo.password);
 

	
 
	std::string message;
 
	login.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_LOGIN);
 

	
 
	Backend *c = (Backend *) user->getData();
 
	send(c->connection, message);
 
}
 

	
 
void NetworkPluginServer::handleUserPresenceChanged(User *user, Swift::Presence::ref presence) {
 
	if (presence->getShow() == Swift::StatusShow::None)
 
		return;
 

	
 
	UserInfo userInfo = user->getUserInfo();
 

	
 
	pbnetwork::Status status;
 
	status.set_username(user->getJID().toBare());
 
	status.set_status((int) presence->getShow());
 
	status.set_statusmessage(presence->getStatus());
 

	
 
	std::string message;
 
	status.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_STATUS_CHANGED);
 

	
 
@@ -579,96 +580,97 @@ void NetworkPluginServer::handleRoomJoined(User *user, const std::string &r, con
 

	
 
	pbnetwork::Room room;
 
	room.set_username(user->getJID().toBare());
 
	room.set_nickname(nickname);
 
	room.set_room(r);
 
	room.set_password(password);
 

	
 
	std::string message;
 
	room.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_JOIN_ROOM);
 
 
 
	Backend *c = (Backend *) user->getData();
 
	send(c->connection, message);
 

	
 
	NetworkConversation *conv = new NetworkConversation(user->getConversationManager(), r, true);
 
	conv->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, this, _1, _2));
 
	conv->setNickname(nickname);
 
}
 

	
 
void NetworkPluginServer::handleRoomLeft(User *user, const std::string &r) {
 
	UserInfo userInfo = user->getUserInfo();
 

	
 
	pbnetwork::Room room;
 
	room.set_username(user->getJID().toBare());
 
	room.set_nickname("");
 
	room.set_room(r);
 
	room.set_password("");
 

	
 
	std::string message;
 
	room.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_LEAVE_ROOM);
 
 
 
	Backend *c = (Backend *) user->getData();
 
	send(c->connection, message);
 

	
 
	NetworkConversation *conv = (NetworkConversation *) user->getConversationManager()->getConversation(r);
 
	if (!conv) {
 
		return;
 
	}
 

	
 
	user->getConversationManager()->removeConversation(conv);
 

	
 
	delete conv;
 
}
 

	
 
void NetworkPluginServer::handleUserDestroyed(User *user) {
 
	std::cout << "HANDLE_DESTROYED\n";
 
	UserInfo userInfo = user->getUserInfo();
 

	
 
	pbnetwork::Logout logout;
 
	logout.set_user(user->getJID().toBare());
 
	logout.set_legacyname(userInfo.uin);
 

	
 
	std::string message;
 
	logout.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_LOGOUT);
 
 
 
	Backend *c = (Backend *) user->getData();
 
	if (!c) {
 
		return;
 
	}
 
	send(c->connection, message);
 
	c->users.remove(user);
 
	if (c->users.size() == 0) {
 
		LOG4CXX_INFO(logger, "Disconnecting backend " << c << ". There are no users.");
 
		c->connection->disconnect();
 
		c->connection.reset();
 
// 		m_clients.erase(user->connection);
 
	}
 
}
 

	
 
void NetworkPluginServer::handleMessageReceived(NetworkConversation *conv, boost::shared_ptr<Swift::Message> &msg) {
 

	
 
	boost::shared_ptr<Swift::ChatState> statePayload = msg->getPayload<Swift::ChatState>();
 
	if (statePayload) {
 
		pbnetwork::WrapperMessage_Type type = pbnetwork::WrapperMessage_Type_TYPE_BUDDY_CHANGED;
 
		switch (statePayload->getChatState()) {
 
			case Swift::ChatState::Active:
 
				type = pbnetwork::WrapperMessage_Type_TYPE_BUDDY_STOPPED_TYPING;
 
				break;
 
			case Swift::ChatState::Composing:
 
				type = pbnetwork::WrapperMessage_Type_TYPE_BUDDY_TYPING;
 
				break;
 
			case Swift::ChatState::Paused:
 
				type = pbnetwork::WrapperMessage_Type_TYPE_BUDDY_TYPED;
 
				break;
 
			default:
 
				break;
 
		}
 
		if (type != pbnetwork::WrapperMessage_Type_TYPE_BUDDY_CHANGED) {
 
			pbnetwork::Buddy buddy;
 
			buddy.set_username(conv->getConversationManager()->getUser()->getJID().toBare());
 
			buddy.set_buddyname(conv->getLegacyName());
 

	
src/user.cpp
Show inline comments
 
/**
 
 * libtransport -- C++ library for easy XMPP Transports development
 
 *
 
 * Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
 
 *
 
 * This program is free software; you can redistribute it and/or modify
 
 * it under the terms of the GNU General Public License as published by
 
 * the Free Software Foundation; either version 2 of the License, or
 
 * (at your option) any later version.
 
 *
 
 * This program is distributed in the hope that it will be useful,
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 * GNU General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU General Public License
 
 * along with this program; if not, write to the Free Software
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/storagebackend.h"
 
#include "transport/rostermanager.h"
 
#include "transport/usermanager.h"
 
#include "transport/conversationmanager.h"
 
#include "Swiften/Swiften.h"
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Elements/StreamError.h"
 
#include "Swiften/Elements/MUCPayload.h"
 
#include "log4cxx/logger.h"
 
#include <boost/foreach.hpp>
 

	
 
using namespace log4cxx;
 
using namespace boost;
 

	
 
#define foreach         BOOST_FOREACH
 

	
 
namespace Transport {
 

	
 
static LoggerPtr logger = Logger::getLogger("User");
 

	
 
User::User(const Swift::JID &jid, UserInfo &userInfo, Component *component, UserManager *userManager) {
 
	m_jid = jid;
 
	m_data = NULL;
 

	
 
	m_component = component;
 
	m_presenceOracle = component->m_presenceOracle;
 
	m_entityCapsManager = component->m_entityCapsManager;
 
	m_userManager = userManager;
 
	m_userInfo = userInfo;
 
	m_connected = false;
 
	m_readyForConnect = false;
 

	
 
	m_reconnectTimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(10000);
 
	m_reconnectTimer->onTick.connect(boost::bind(&User::onConnectingTimeout, this)); 
 

	
 
	m_rosterManager = new RosterManager(this, m_component);
 
	m_conversationManager = new ConversationManager(this, m_component);
 
	LOG4CXX_INFO(logger, m_jid.toString() << ": Created");
 
}
 

	
 
User::~User(){
 
	LOG4CXX_INFO(logger, m_jid.toString() << ": Destroying");
 
	m_reconnectTimer->stop();
 
	delete m_rosterManager;
 
	delete m_conversationManager;
 
}
 

	
 
const Swift::JID &User::getJID() {
 
	return m_jid;
 
}
 

	
 
Swift::JID User::getJIDWithFeature(const std::string &feature) {
 
	Swift::JID jid;
 
	std::vector<Swift::Presence::ref> presences = m_presenceOracle->getAllPresence(m_jid);
 

	
 
	foreach(Swift::Presence::ref presence, presences) {
 
		if (presence->getType() == Swift::Presence::Unavailable)
 
			continue;
 

	
 
		Swift::DiscoInfo::ref discoInfo = m_entityCapsManager->getCaps(presence->getFrom());
 
		if (!discoInfo)
 
			continue;
 

	
 
		if (discoInfo->hasFeature(feature)) {
 
			LOG4CXX_INFO(logger, m_jid.toString() << ": Found JID with " << feature << "feature: " << presence->getFrom().toString());
 
			return presence->getFrom();
 
		}
 
	}
 

	
 
	LOG4CXX_INFO(logger, m_jid.toString() << ": No JID with " << feature << "feature");
 
	return jid;
 
@@ -145,55 +146,56 @@ void User::handlePresence(Swift::Presence::ref presence) {
 
		response->setTo(presence->getFrom().toBare());
 
		response->setFrom(m_component->getJID());
 
		m_component->getStanzaChannel()->sendPresence(response);
 
		LOG4CXX_INFO(logger, m_jid.toString() << ": Changing legacy network presence to " << response->getType());
 
		onPresenceChanged(response);
 
	}
 
	else {
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setTo(m_jid.toBare());
 
		response->setFrom(m_component->getJID());
 
		response->setType(Swift::Presence::Unavailable);
 
		m_component->getStanzaChannel()->sendPresence(response);
 
		onPresenceChanged(response);
 
	}
 
}
 

	
 
void User::handleSubscription(Swift::Presence::ref presence) {
 
	m_rosterManager->handleSubscription(presence);
 
}
 

	
 
void User::onConnectingTimeout() {
 
	if (m_connected || m_readyForConnect)
 
		return;
 
	m_reconnectTimer->stop();
 
	m_readyForConnect = true;
 
	onReadyToConnect();
 
}
 

	
 
void User::handleDisconnected(const std::string &error) {
 
	if (error.empty()) {
 
		LOG4CXX_INFO(logger, m_jid.toString() << ": Disconnected from legacy network");
 
	}
 
	else {
 
		LOG4CXX_INFO(logger, m_jid.toString() << ": Disconnected from legacy network with error " << error);
 
	}
 
	onDisconnected();
 

	
 
	boost::shared_ptr<Swift::Message> msg(new Swift::Message());
 
	msg->setBody(error);
 
	msg->setTo(m_jid.toBare());
 
	msg->setFrom(m_component->getJID());
 
	m_component->getStanzaChannel()->sendMessage(msg);
 

	
 
	// In server mode, server finishes the session and pass unavailable session to userManager,
 
	// so we can't removeUser() in server mode, because it would be removed twice.
 
	// Once in finishSession and once in m_userManager->removeUser.
 
	if (m_component->inServerMode()) {
 
		dynamic_cast<Swift::ServerStanzaChannel *>(m_component->getStanzaChannel())->finishSession(m_jid, boost::shared_ptr<Swift::Element>(new Swift::StreamError()));
 
		m_userManager->removeUser(this);
 
	}
 
	else {
 
		m_userManager->removeUser(this);
 
	}
 
}
 

	
 
}
src/usermanager.cpp
Show inline comments
 
@@ -122,150 +122,160 @@ void UserManager::handlePresence(Swift::Presence::ref presence) {
 

	
 
		UserInfo res;
 
		bool registered = m_storageBackend ? m_storageBackend->getUser(userkey, res) : false;
 

	
 
		if (m_component->inServerMode()) {
 
			if (!registered) {
 
				res.password = "";
 
				res.uin = presence->getFrom().getNode();
 
				res.jid = userkey;
 
				if (res.uin.find_last_of("%") != std::string::npos) {
 
					res.uin.replace(res.uin.find_last_of("%"), 1, "@");
 
				}
 
				if (m_storageBackend) {
 
					m_storageBackend->setUser(res);
 
					registered = m_storageBackend->getUser(userkey, res);
 
				}
 
				else {
 
					registered = true;
 
				}
 
			}
 
			res.password = m_userRegistry->getUserPassword(userkey);
 
		}
 

	
 
		if (!registered) {
 
			LOG4CXX_WARN(logger, "Unregistered user " << userkey << " tried to login");
 
			// TODO: logging
 
			return;
 
		}
 

	
 
		// TODO: isVIP
 
// // 			bool isVip = res.vip;
 
// // 			std::list<std::string> const &x = CONFIG().allowedServers;
 
// // 			if (CONFIG().onlyForVIP && !isVip && std::find(x.begin(), x.end(), presence->getFrom().getDomain().getUTF8String()) == x.end()) {
 
// // 				Log(presence->getFrom().toString().getUTF8String(), "This user is not VIP, can't login...");
 
// // 				return;
 
// // 			}
 
// // 
 
// // 
 
				user = new User(presence->getFrom(), res, m_component, this);
 
				user->getRosterManager()->setStorageBackend(m_storageBackend);
 
				// TODO: handle features somehow
 
// // 			user->setFeatures(isVip ? CONFIG().VIPFeatures : CONFIG().transportFeatures);
 
// // // 				if (c != NULL)
 
// // // 					if (Transport::instance()->hasClientCapabilities(c->findAttribute("ver")))
 
// // // 						user->setResource(stanza.from().resource(), stanza.priority(), Transport::instance()->getCapabilities(c->findAttribute("ver")));
 
// // // 
 
			addUser(user);
 
	}
 

	
 
	// User can be handleDisconnected in addUser callbacks...
 
	user = getUser(userkey);
 
	if (!user) {
 
		m_userRegistry->onPasswordInvalid(presence->getFrom());
 
		return;
 
	}
 

	
 
	user->handlePresence(presence);
 

	
 
	bool isMUC = presence->getPayload<Swift::MUCPayload>() != NULL || *presence->getTo().getNode().c_str() == '#';
 
	if (isMUC)
 
		return;
 

	
 
	if (presence->getType() == Swift::Presence::Unavailable) {
 
		if (user) {
 
			Swift::Presence::ref highest = m_component->getPresenceOracle()->getHighestPriorityPresence(presence->getFrom().toBare());
 
			// There's no presence for this user, so disconnect
 
			if (!highest || (highest && highest->getType() == Swift::Presence::Unavailable)) {
 
				removeUser(user);
 
			}
 
		}
 
		// TODO: HANDLE MUC SOMEHOW
 
// 		else if (user && Transport::instance()->protocol()->tempAccountsAllowed() && !((User *) user)->hasOpenedMUC()) {
 
// 			Transport::instance()->userManager()->removeUser(user);
 
// 		}
 
	}
 
}
 

	
 
void UserManager::handleMessageReceived(Swift::Message::ref message) {
 
	User *user = getUser(message->getFrom().toBare().toString());
 
	if (!user ){
 
		return;
 
	}
 

	
 
	user->getConversationManager()->handleMessageReceived(message);
 
}
 

	
 
void UserManager::handleGeneralPresenceReceived(Swift::Presence::ref presence) {
 
	switch(presence->getType()) {
 
		case Swift::Presence::Subscribe:
 
		case Swift::Presence::Subscribed:
 
		case Swift::Presence::Unsubscribe:
 
		case Swift::Presence::Unsubscribed:
 
			handleSubscription(presence);
 
			break;
 
		case Swift::Presence::Available:
 
		case Swift::Presence::Unavailable:
 
			break;
 
		case Swift::Presence::Probe:
 
			handleProbePresence(presence);
 
			break;
 
		default:
 
			break;
 
	};
 
}
 

	
 
void UserManager::handleProbePresence(Swift::Presence::ref presence) {
 
	
 
}
 

	
 
void UserManager::handleSubscription(Swift::Presence::ref presence) {
 
	// answer to subscibe for transport itself
 
	if (presence->getType() == Swift::Presence::Subscribe && presence->getTo().getNode().empty()) {
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setFrom(presence->getTo());
 
		response->setTo(presence->getFrom());
 
		response->setType(Swift::Presence::Subscribed);
 
		m_component->getStanzaChannel()->sendPresence(response);
 

	
 
// 		response = Swift::Presence::create();
 
// 		response->setFrom(presence->getTo());
 
// 		response->setTo(presence->getFrom());
 
// 		response->setType(Swift::Presence::Subscribe);
 
// 		m_component->getStanzaChannel()->sendPresence(response);
 
		return;
 
	}
 

	
 
	User *user = getUser(presence->getFrom().toBare().toString());
 

	
 
 	if (user) {
 
 		user->handleSubscription(presence);
 
 	}
 
 	else if (presence->getType() == Swift::Presence::Unsubscribe) {
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setFrom(presence->getTo());
 
		response->setTo(presence->getFrom());
 
		response->setType(Swift::Presence::Unsubscribed);
 
		m_component->getStanzaChannel()->sendPresence(response);
 
	}
 
// 	else {
 
// // 		Log(presence->getFrom().toString().getUTF8String(), "Subscribe presence received, but this user is not logged in");
 
// 	}
 
}
 

	
 
void UserManager::connectUser(const Swift::JID &user) {
 
	if (m_users.find(user.toBare().toString()) != m_users.end()) {
 
		std::cout << "FOUND\n";
 
		m_userRegistry->onPasswordValid(user);
 
	}
 
	else {
 
		std::cout << "NOT FOUND - PRESENCe\n";
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setTo(m_component->getJID());
 
		response->setFrom(user);
 
		response->setType(Swift::Presence::Available);
 
		m_component->onUserPresenceReceived(response);
 
	}
 
}
 

	
 

	
 
}
0 comments (0 inline, 0 general)