Changeset - e31c07794705
[Not reviewed]
0 7 0
HanzZ - 14 years ago 2011-07-20 02:16:58
hanzz.k@gmail.com
Call finishSession in User destructor in server mode
7 files changed with 51 insertions and 4 deletions:
0 comments (0 inline, 0 general)
include/Swiften/Server/Server.cpp
Show inline comments
 
@@ -120,36 +120,37 @@ void Server::handleNewClientConnection(boost::shared_ptr<Connection> connection)
 

	
 
	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) {
 
	if (!session->getRemoteJID().isValid()) {
 
		Swift::Presence::ref presence = Swift::Presence::create();
 
		presence->setFrom(session->getBareJID());
 
		presence->setType(Swift::Presence::Unavailable);
 
		dynamic_cast<ServerStanzaChannel *>(stanzaChannel_)->onPresenceReceived(presence);
 
	}
 
	serverFromClientSessions.erase(std::remove(serverFromClientSessions.begin(), serverFromClientSessions.end(), session), serverFromClientSessions.end());
 
	std::cout << "FINISH SESSION2 " << serverFromClientSessions.size() << "\n";
 
	session->onSessionStarted.disconnect(
 
			boost::bind(&Server::handleSessionStarted, this, session));
 
	session->onSessionFinished.disconnect(
 
			boost::bind(&Server::handleSessionFinished, this, session));
 
}
 

	
 
void Server::addTLSEncryption(TLSServerContextFactory* tlsContextFactory, const PKCS12Certificate& cert) {
 
	tlsFactory = tlsContextFactory;
 
	this->cert = cert;
 
}
 

	
 
}
include/Swiften/Server/ServerFromClientSession.cpp
Show inline comments
 
@@ -27,48 +27,50 @@
 
#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() {
 
	std::cout << "DESTRUCTOR;\n";
 
	userRegistry_->onPasswordValid.disconnect(boost::bind(&ServerFromClientSession::handlePasswordValid, this, _1));
 
	userRegistry_->onPasswordInvalid.disconnect(boost::bind(&ServerFromClientSession::handlePasswordInvalid, this, _1));
 
	if (tlsLayer) {
 
		delete tlsLayer;
 
	}
 
}
 

	
 
void ServerFromClientSession::handlePasswordValid(const std::string &user) {
 
	if (user != JID(user_, getLocalJID().getDomain()).toString())
 
		return;
 
	if (!isInitialized()) {
 
		userRegistry_->onPasswordValid.disconnect(boost::bind(&ServerFromClientSession::handlePasswordValid, this, _1));
 
		userRegistry_->onPasswordInvalid.disconnect(boost::bind(&ServerFromClientSession::handlePasswordInvalid, this, _1));
 
		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()) {
 
		userRegistry_->onPasswordValid.disconnect(boost::bind(&ServerFromClientSession::handlePasswordValid, this, _1));
 
		userRegistry_->onPasswordInvalid.disconnect(boost::bind(&ServerFromClientSession::handlePasswordInvalid, this, _1));
 
		getXMPPLayer()->writeElement(boost::shared_ptr<AuthFailure>(new AuthFailure));
include/Swiften/Server/ServerStanzaChannel.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/ServerStanzaChannel.h"
 
#include "Swiften/Base/Error.h"
 
#include <iostream>
 

	
 
#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));
 
@@ -34,55 +35,59 @@ void ServerStanzaChannel::addSession(boost::shared_ptr<ServerFromClientSession>
 
}
 

	
 
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) {
 
		(*i)->sendElement(element);
 
		if (element) {
 
			(*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::cout << "FINISH SESSION " << sessions[to.toBare().toString()].size() << "\n";
 
	}
 
}
 

	
 
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) {
spectrum/src/main.cpp
Show inline comments
 
#include "transport/config.h"
 
#include "transport/transport.h"
 
#include "transport/usermanager.h"
 
#include "transport/logger.h"
 
#include "transport/sqlite3backend.h"
 
#include "transport/userregistration.h"
 
#include "transport/networkpluginserver.h"
 
#include "transport/admininterface.h"
 
#include "Swiften/EventLoop/SimpleEventLoop.h"
 
#include "sys/signal.h"
 
 
using namespace Transport;
 
 
Swift::SimpleEventLoop *eventLoop_ = NULL;
 
 
static void spectrum_sigint_handler(int sig) {
 
	eventLoop_->stop();
 
}
 
 
static void spectrum_sigterm_handler(int sig) {
 
	eventLoop_->stop();
 
}
 
 
int main(int argc, char **argv)
 
{
 
	Config config;
 
 
	if (signal(SIGINT, spectrum_sigint_handler) == SIG_ERR) {
 
		std::cout << "SIGINT handler can't be set\n";
 
		return -1;
 
	}
 
 
	if (signal(SIGTERM, spectrum_sigterm_handler) == SIG_ERR) {
 
		std::cout << "SIGTERM handler can't be set\n";
 
		return -1;
 
	}
 
 
	boost::program_options::options_description desc("Usage: spectrum [OPTIONS] <config_file.cfg>\nAllowed options");
 
	desc.add_options()
 
		("help,h", "help")
 
		("no-daemonize,n", "Do not run spectrum as daemon")
 
		;
 
	try
 
	{
 
		boost::program_options::variables_map vm;
 
		boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
 
		boost::program_options::notify(vm);
 
		if(vm.count("help"))
 
		{
 
			std::cout << desc << "\n";
 
			return 1;
 
		}
 
	}
 
	catch (std::runtime_error& e)
 
	{
 
		std::cout << desc << "\n";
 
		return 1;
 
	}
 
	catch (...)
 
	{
 
		std::cout << desc << "\n";
 
@@ -48,37 +69,45 @@ int main(int argc, char **argv)
 
 
 
	if (!config.load(argv[1])) {
 
		std::cerr << "Can't load configuration file.\n";
 
		return 1;
 
	}
 
 
	UserRegistry userRegistry(&config);
 
 
	Swift::SimpleEventLoop eventLoop;
 
	Component transport(&eventLoop, &config, NULL, &userRegistry);
 
// 	Logger logger(&transport);
 
 
	StorageBackend *storageBackend = NULL;
 
 
	if (CONFIG_STRING(&config, "database.type") == "sqlite3") {
 
		storageBackend = new SQLite3Backend(&config);
 
// 		logger.setStorageBackend(storageBackend);
 
		if (!storageBackend->connect()) {
 
			std::cerr << "Can't connect to database.\n";
 
		}
 
	}
 
 
	UserManager userManager(&transport, &userRegistry, storageBackend);
 
	UserRegistration *userRegistration = NULL;
 
	if (storageBackend) {
 
		UserRegistration *userRegistration = new UserRegistration(&transport, &userManager, storageBackend);
 
		userRegistration = new UserRegistration(&transport, &userManager, storageBackend);
 
		userRegistration->start();
 
// 		logger.setUserRegistration(&userRegistration);
 
	}
 
// 	logger.setUserManager(&userManager);
 
 
	NetworkPluginServer plugin(&transport, &config, &userManager);
 
 
	AdminInterface adminInterface(&transport, &userManager, &plugin, storageBackend);
 
 
	eventLoop_ = &eventLoop;
 
 
	eventLoop.run();
 
	if (userRegistration) {
 
		userRegistration->stop();
 
		delete userRegistration;
 
	}
 
	delete storageBackend;
 
}
src/networkpluginserver.cpp
Show inline comments
 
@@ -147,48 +147,51 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U
 
	m_vcardResponder = new VCardResponder(component->getIQRouter(), userManager);
 
	m_vcardResponder->onVCardRequired.connect(boost::bind(&NetworkPluginServer::handleVCardRequired, this, _1, _2, _3));
 
	m_vcardResponder->onVCardUpdated.connect(boost::bind(&NetworkPluginServer::handleVCardUpdated, this, _1, _2));
 
	m_vcardResponder->start();
 

	
 
	m_rosterResponder = new RosterResponder(component->getIQRouter(), userManager);
 
	m_rosterResponder->onBuddyAdded.connect(boost::bind(&NetworkPluginServer::handleBuddyAdded, this, _1, _2));
 
	m_rosterResponder->onBuddyRemoved.connect(boost::bind(&NetworkPluginServer::handleBuddyRemoved, this, _1));
 
	m_rosterResponder->onBuddyUpdated.connect(boost::bind(&NetworkPluginServer::handleBuddyUpdated, this, _1, _2));
 
	m_rosterResponder->start();
 

	
 
	m_server = Swift::BoostConnectionServer::create(Swift::HostAddress(CONFIG_STRING(m_config, "service.backend_host")), boost::lexical_cast<int>(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();
 

	
 
	LOG4CXX_INFO(logger, "Listening on host " << CONFIG_STRING(m_config, "service.backend_host") << " port " << CONFIG_STRING(m_config, "service.backend_port"));
 

	
 
	signal(SIGCHLD, SigCatcher);
 

	
 
	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());
 
}
 

	
 
NetworkPluginServer::~NetworkPluginServer() {
 
	m_pingTimer->stop();
 
	m_server->stop();
 
	m_server.reset();
 
	delete m_component->m_factory;
 
	delete m_vcardResponder;
 
	delete m_rosterResponder;
 
}
 

	
 
void NetworkPluginServer::handleNewClientConnection(boost::shared_ptr<Swift::Connection> c) {
 
	Backend *client = new Backend;
 
	client->pongReceived = true;
 
	client->connection = c;
 
	client->res = 0;
 
	client->init_res = 0;
 
	client->shared = 0;
 

	
 
	LOG4CXX_INFO(logger, "New backend " << client << " connected. Current backend count=" << (m_clients.size() + 1));
 

	
 
	if (m_clients.size() == 0) {
 
		// first backend connected, start the server, we're ready.
 
		m_component->start();
 
	}
 

	
 
	m_clients.push_back(client);
 

	
 
	c->onDisconnected.connect(boost::bind(&NetworkPluginServer::handleSessionFinished, this, client));
 
	c->onDataRead.connect(boost::bind(&NetworkPluginServer::handleDataRead, this, client, _1));
 
	sendPing(client);
src/transport.cpp
Show inline comments
 
@@ -113,52 +113,55 @@ Component::Component(Swift::EventLoop *loop, Config *config, Factory *factory, T
 
	m_capsManager = new CapsManager(m_capsMemoryStorage, m_stanzaChannel, m_iqRouter);
 
	m_entityCapsManager = new EntityCapsManager(m_capsManager, m_stanzaChannel);
 
 	m_entityCapsManager->onCapsChanged.connect(boost::bind(&Component::handleCapsChanged, this, _1));
 
	
 
	m_presenceOracle = new PresenceOracle(m_stanzaChannel);
 
	m_presenceOracle->onPresenceChange.connect(bind(&Component::handlePresence, this, _1));
 

	
 
	m_discoInfoResponder = new DiscoInfoResponder(m_iqRouter, m_config);
 
	m_discoInfoResponder->start();
 

	
 
	m_discoItemsResponder = new DiscoItemsResponder(m_iqRouter);
 
	m_discoItemsResponder->start();
 

	
 
// 
 
// 	m_registerHandler = new SpectrumRegisterHandler(m_component);
 
// 	m_registerHandler->start();
 
}
 

	
 
Component::~Component() {
 
	delete m_presenceOracle;
 
	delete m_entityCapsManager;
 
	delete m_capsManager;
 
	delete m_capsMemoryStorage;
 
	delete m_discoInfoResponder;
 
	delete m_discoItemsResponder;
 
	if (m_component)
 
		delete m_component;
 
	if (m_server)
 
	if (m_server) {
 
		m_server->stop();
 
		delete m_server;
 
	}
 
	delete m_factories;
 
}
 

	
 
Swift::StanzaChannel *Component::getStanzaChannel() {
 
	return m_stanzaChannel;
 
}
 

	
 
Swift::PresenceOracle *Component::getPresenceOracle() {
 
	return m_presenceOracle;
 
}
 

	
 
void Component::setTransportFeatures(std::list<std::string> &features) {
 
	m_discoInfoResponder->setTransportFeatures(features);
 
}
 

	
 
void Component::setBuddyFeatures(std::list<std::string> &features) {
 
	// TODO: handle caps change
 
	m_discoInfoResponder->setBuddyFeatures(features);
 
}
 

	
 
void Component::start() {
 
	if (m_component && !m_component->isAvailable()) {
 
		LOG4CXX_INFO(logger, "Connecting XMPP server " << CONFIG_STRING(m_config, "service.server") << " port " << CONFIG_INT(m_config, "service.port"));
 
		m_reconnectCount++;
src/user.cpp
Show inline comments
 
@@ -41,48 +41,52 @@ 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");
 
	if (m_component->inServerMode()) {
 
		dynamic_cast<Swift::ServerStanzaChannel *>(m_component->getStanzaChannel())->finishSession(m_jid, boost::shared_ptr<Swift::Element>());
 
	}
 

	
 
	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();
 
@@ -173,36 +177,36 @@ void User::onConnectingTimeout() {
 

	
 
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 if we're connected to legacy network,
 
	// 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()) {
 
		// Remove user later just to be sure there won't be double-free.
 
		// We can't be sure finishSession sends unavailable presence everytime, so check if user gets removed
 
		// in finishSession(...) call and if not, remove it here.
 
		std::string jid = m_jid.toBare().toString();
 
		std::string jid = m_jid.toBare().toString();		
 
		dynamic_cast<Swift::ServerStanzaChannel *>(m_component->getStanzaChannel())->finishSession(m_jid, boost::shared_ptr<Swift::Element>(new Swift::StreamError()));
 
		if (m_userManager->getUser(jid) != NULL) {
 
			m_userManager->removeUser(this);
 
		}
 
	}
 
	else {
 
		m_userManager->removeUser(this);
 
	}
 
}
 

	
 
}
0 comments (0 inline, 0 general)