Changeset - 7e8720849725
[Not reviewed]
0 13 0
Jan Kaluza - 14 years ago 2011-09-07 14:03:27
hanzz.k@gmail.com
Fixed spectrum2 compilation with MSVC. Thanks to Vitaly Takmazov
13 files changed with 61 insertions and 36 deletions:
0 comments (0 inline, 0 general)
include/Swiften/TLS/OpenSSL/OpenSSLServerContext.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/Base/Platform.h"
 

	
 
#ifdef SWIFTEN_PLATFORM_WINDOWS
 
#include <windows.h>
 
#include <wincrypt.h>
 
#endif
 

	
 
#include <vector>
 
#include <openssl/err.h>
 
#include <openssl/pkcs12.h>
 

	
 

	
 
#include "Swiften/TLS/OpenSSL/OpenSSLServerContext.h"
 
#include "Swiften/TLS/OpenSSL/OpenSSLCertificate.h"
 
#include "Swiften/TLS/PKCS12Certificate.h"
 

	
 
#ifndef _MSC_VER
 
#pragma GCC diagnostic ignored "-Wold-style-cast"
 

	
 
#endif
 
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(SSLv23_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);
 
			ByteArray certData(createByteArray(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) {
include/transport/buddy.h
Show inline comments
 
@@ -42,97 +42,97 @@ class Buddy {
 
		/// Constructor.
 

	
 
		/// \param rosterManager RosterManager associated with this buddy.
 
		/// \param id ID which identifies the buddy in database or -1 if it's new buddy which is
 
		/// not in database yet.
 
		Buddy(RosterManager *rosterManager, long id = -1);
 

	
 
		/// Destructor
 
		virtual ~Buddy();
 
		
 
		/// Sets unique ID used to identify this buddy by StorageBackend.
 
		
 
		/// This is set
 
		/// by RosterStorage class once the buddy is stored into database or when the
 
		/// buddy is loaded from database.
 
		/// You should not need to set this ID manually.
 
		/// \param id ID
 
		void setID(long id);
 

	
 
		/// Returns unique ID used to identify this buddy by StorageBackend.
 

	
 
		/// \return ID which identifies the buddy in database or -1 if it's new buddy which is
 
		/// not in database yet.
 
		long getID();
 

	
 
		/// Returns full JID of this buddy.
 

	
 
		/// \param hostname hostname used as domain in returned JID
 
		/// \return full JID of this buddy
 
		const Swift::JID &getJID();
 

	
 
		/// Generates whole Presennce stanza with current status/show for this buddy.
 

	
 
		/// Presence stanza does not containt "to" attribute, it has to be added manually.
 
		/// \param features features used in returned stanza
 
		/// \param only_new if True, this function returns Presence stanza only if it's different
 
		/// than the previously generated one.
 
		/// \return Presence stanza or NULL.
 
		Swift::Presence::ref generatePresenceStanza(int features, bool only_new = false);
 

	
 
		void setBlocked(bool block) {
 
			if (block)
 
				m_flags = (BuddyFlag) (m_flags | BUDDY_BLOCKED);
 
			else
 
				m_flags = (BuddyFlag) (m_flags & ~BUDDY_BLOCKED);
 
		}
 

	
 
		bool isBlocked() {
 
			return m_flags & BUDDY_BLOCKED;
 
			return (m_flags & BUDDY_BLOCKED)  != 0;
 
		}
 

	
 
		/// Sets current subscription.
 

	
 
		/// \param subscription "to", "from", "both", "ask"
 
		void setSubscription(const std::string &subscription);
 

	
 
		/// Returns current subscription
 

	
 
		/// \return subscription "to", "from", "both", "ask"
 
		const std::string getSubscription();
 

	
 
		/// Sets this buddy's flags.
 

	
 
		/// \param flags flags
 
		void setFlags(BuddyFlag flags);
 

	
 
		/// Returns this buddy's flags.
 

	
 
		/// \param flags flags
 
		BuddyFlag getFlags();
 

	
 
		/// Returns RosterManager associated with this buddy.
 

	
 
		/// \return RosterManager associated with this buddy.
 
		RosterManager *getRosterManager() { return m_rosterManager; }
 

	
 
		/// Returns legacy network username which does not contain unsafe characters,
 
		/// so it can be used in JIDs.
 
		std::string getSafeName();
 

	
 
		/// This method should be called whenever some information returned by virtual functions changes.
 

	
 
		/// This method sends presence to XMPP user.
 
		void handleBuddyChanged();
 

	
 
		/// Handles VCard from legacy network and forwards it to XMPP user.
 

	
 
		/// \param id ID used in IQ-result.
 
		/// \param vcard VCard which will be sent.
 
		void handleVCardReceived(const std::string &id, Swift::VCard::ref vcard);
 

	
 
		/// Returns legacy network username of this buddy. (for example UIN for ICQ, JID for Jabber, ...).
 

	
 
		/// \return legacy network username
 
		virtual std::string getName() = 0;
 

	
 
		/// Returns alias (nickname) of this buddy.
include/transport/sqlite3backend.h
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
 
 */
 

	
 
#pragma once
 

	
 
#include <string>
 
#include <map>
 
#include "Swiften/Swiften.h"
 
#include "transport/storagebackend.h"
 
#include "transport/config.h"
 
#include <sqlite3.h>
 
#include "sqlite3.h"
 

	
 
namespace Transport {
 

	
 
/// Used to store transport data into SQLite3 database.
 
class SQLite3Backend : public StorageBackend
 
{
 
	public:
 
		/// Creates new SQLite3Backend instance.
 
		/// \param config cofiguration, this class uses following Config values:
 
		/// 	- database.database - path to SQLite3 database file, database file is created automatically
 
		/// 	- service.prefix - prefix for tables created by createDatabase method
 
		SQLite3Backend(Config *config);
 

	
 
		/// Destructor.
 
		~SQLite3Backend();
 

	
 
		/// Connects to the database and creates it if it's needed. This method call createDatabase() function
 
		/// automatically.
 
		/// \return true if database is opened successfully.
 
		bool connect();
 

	
 
		/// Creates database structure.
 
		/// \see connect()
 
		/// \return true if database structure has been created successfully. Note that it returns True also if database structure
 
		/// already exists.
 
		bool createDatabase();
 

	
 
		/// Stores user into database.
 
		/// \param user user struct containing all information about user which have to be stored
 
		void setUser(const UserInfo &user);
 

	
 
		/// Gets user data from database and stores them into user reference.
 
		/// \param barejid barejid of user
 
		/// \param user UserInfo object where user data will be stored
 
		/// \return true if user has been found in database
 
		bool getUser(const std::string &barejid, UserInfo &user);
 

	
 
		/// Changes users online state variable in database.
 
		/// \param id id of user - UserInfo.id
 
		/// \param online online state
 
		void setUserOnline(long id, bool online);
 

	
 
		/// Removes user and all connected data from database.
 
		/// \param id id of user - UserInfo.id
 
		/// \return true if user has been found in database and removed
 
		bool removeUser(long id);
 

	
 
		/// Returns JIDs of all buddies in user's roster.
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/mysqlbackend.h"
 
//#include "transport/mysqlbackend.h"
 
#include "transport/userregistration.h"
 
#include "transport/networkpluginserver.h"
 
#include "transport/admininterface.h"
 
#include "Swiften/EventLoop/SimpleEventLoop.h"
 
#ifndef WIN32
 
#include "sys/signal.h"
 
#else
 
#include <Windows.h>
 
#include <tchar.h>
 
#endif
 
#include "log4cxx/logger.h"
 
#include "log4cxx/patternlayout.h"
 
#include "log4cxx/propertyconfigurator.h"
 
#include "log4cxx/consoleappender.h"
 
 
using namespace log4cxx;
 
 
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;
 
 
#ifndef WIN32
 
	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;
 
	}
 
 
#endif
 
	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";
 
		return 1;
 
	}
 
 
	if (argc != 2) {
 
		std::cout << desc << "\n";
 
		return 1;
 
	}
 
 
 
	if (!config.load(argv[1])) {
 
		std::cerr << "Can't load configuration file.\n";
 
		return 1;
 
	}
 
 
	if (CONFIG_STRING(&config, "logging.config").empty()) {
 
		LoggerPtr root = log4cxx::Logger::getRootLogger();
 
#ifdef WIN32
 
		root->addAppender(new ConsoleAppender(new PatternLayout(L"%d %-5p %c: %m%n")));
 
#else
 
		root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n")));
 
#endif
 
	}
 
	else {
 
		log4cxx::PropertyConfigurator::configure(CONFIG_STRING(&config, "logging.config"));
 
	}
 
 
	Swift::SimpleEventLoop eventLoop;
 
 
	Swift::BoostNetworkFactories *factories = new Swift::BoostNetworkFactories(&eventLoop);
 
	UserRegistry userRegistry(&config, factories);
 
 
	Component transport(&eventLoop, factories, &config, NULL, &userRegistry);
 
// 	Logger logger(&transport);
 
 
	StorageBackend *storageBackend = NULL;
 
 
	if (CONFIG_STRING(&config, "database.type") == "sqlite3") {
 
		storageBackend = new SQLite3Backend(&config);
 
		if (!storageBackend->connect()) {
 
			std::cerr << "Can't connect to database.\n";
 
			return -1;
 
		}
 
	}
 
/*
 
	else if (CONFIG_STRING(&config, "database.type") == "mysql") {
 
		storageBackend = new MySQLBackend(&config);
 
		if (!storageBackend->connect()) {
 
			std::cerr << "Can't connect to database.\n";
 
			return -1;
 
		}
 
	}
 
 
*/
 
	UserManager userManager(&transport, &userRegistry, storageBackend);
 
	UserRegistration *userRegistration = NULL;
 
	if (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;
 
	delete factories;
 
}
src/logger.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/logger.h"
 
#include "transport/usermanager.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/storagebackend.h"
 
#include "transport/userregistration.h"
 
#include "transport/buddy.h"
 
#include "transport/rostermanager.h"
 
#include <boost/bind.hpp>
 

	
 
using namespace boost;
 

	
 
namespace Transport {
 

	
 
Logger::Logger(Component *component) {
 
	component->onConnected.connect(bind(&Logger::handleConnected, this));
 
	component->onConnectionError.connect(bind(&Logger::handleConnectionError, this, _1));
 
	component->onXMLIn.connect(bind(&Logger::handleXMLIn, this, _1));
 
	component->onXMLOut.connect(bind(&Logger::handleXMLOut, this, _1));
 
	component->onConnected.connect(boost::bind(&Logger::handleConnected, this));
 
	component->onConnectionError.connect(boost::bind(&Logger::handleConnectionError, this, _1));
 
	component->onXMLIn.connect(boost::bind(&Logger::handleXMLIn, this, _1));
 
	component->onXMLOut.connect(boost::bind(&Logger::handleXMLOut, this, _1));
 
}
 

	
 
Logger::~Logger(){
 
}
 

	
 
void Logger::setStorageBackend(StorageBackend *storage) {
 
	storage->onStorageError.connect(bind(&Logger::handleStorageError, this, _1, _2));
 
	storage->onStorageError.connect(boost::bind(&Logger::handleStorageError, this, _1, _2));
 
}
 

	
 
void Logger::setUserRegistration(UserRegistration *userRegistration) {
 
	userRegistration->onUserRegistered.connect(bind(&Logger::handleUserRegistered, this, _1));
 
	userRegistration->onUserUnregistered.connect(bind(&Logger::handleUserUnregistered, this, _1));
 
	userRegistration->onUserUpdated.connect(bind(&Logger::handleUserUpdated, this, _1));
 
	userRegistration->onUserRegistered.connect(boost::bind(&Logger::handleUserRegistered, this, _1));
 
	userRegistration->onUserUnregistered.connect(boost::bind(&Logger::handleUserUnregistered, this, _1));
 
	userRegistration->onUserUpdated.connect(boost::bind(&Logger::handleUserUpdated, this, _1));
 
}
 

	
 
void Logger::setUserManager(UserManager *userManager) {
 
	userManager->onUserCreated.connect(bind(&Logger::handleUserCreated, this, _1));
 
	userManager->onUserDestroyed.connect(bind(&Logger::handleUserDestroyed, this, _1));
 
	userManager->onUserCreated.connect(boost::bind(&Logger::handleUserCreated, this, _1));
 
	userManager->onUserDestroyed.connect(boost::bind(&Logger::handleUserDestroyed, this, _1));
 
}
 

	
 
void Logger::setRosterManager(RosterManager *rosterManager) {
 
	rosterManager->onBuddySet.connect(bind(&Logger::handleBuddySet, this, _1));
 
	rosterManager->onBuddyUnset.connect(bind(&Logger::handleBuddyUnset, this, _1));
 
	rosterManager->onBuddySet.connect(boost::bind(&Logger::handleBuddySet, this, _1));
 
	rosterManager->onBuddyUnset.connect(boost::bind(&Logger::handleBuddyUnset, this, _1));
 
}
 

	
 
void Logger::handleConnected() {
 
	std::cout << "[COMPONENT] Connected to Jabber Server!\n";
 
}
 

	
 
void Logger::handleConnectionError(const Swift::ComponentError &error) {
 
	std::cout << "[COMPONENT] Connection Error!\n";
 
	switch (error.getType()) {
 
		case Swift::ComponentError::UnknownError: std::cout << "[COMPONENT] Disconnect reason: UnknownError\n"; break;
 
		case Swift::ComponentError::ConnectionError: std::cout << "[COMPONENT] Disconnect reason: ConnectionError\n"; break;
 
		case Swift::ComponentError::ConnectionReadError: std::cout << "[COMPONENT] Disconnect reason: ConnectionReadError\n"; break;
 
		case Swift::ComponentError::ConnectionWriteError: std::cout << "[COMPONENT] Disconnect reason: ConnectionWriteError\n"; break;
 
		case Swift::ComponentError::XMLError: std::cout << "[COMPONENT] Disconnect reason: XMLError\n"; break;
 
		case Swift::ComponentError::AuthenticationFailedError: std::cout << "[COMPONENT] Disconnect reason: AuthenticationFailedError\n"; break;
 
		case Swift::ComponentError::UnexpectedElementError: std::cout << "[COMPONENT] Disconnect reason: UnexpectedElementError\n"; break; 
 
	};
 
}
 

	
 
void Logger::handleXMLIn(const std::string &data) {
 
	std::cout << "[XML IN] " << data << "\n";
 
}
 

	
 
void Logger::handleXMLOut(const std::string &data) {
 
	std::cout << "[XML OUT] " << data << "\n";
 
}
 

	
 
void Logger::handleStorageError(const std::string &statement, const std::string &error) {
 
	std::cout << "[SQL ERROR] \"" << error << "\" during statement \"" << statement << "\"\n";
 
}
 

	
 
void Logger::handleUserRegistered(const UserInfo &user) {
 
	std::cout << "[REGISTRATION] User \"" << user.jid << "\" registered as \"" << user.uin << "\"\n";
 
}
 

	
 
void Logger::handleUserUnregistered(const UserInfo &user) {
 
	std::cout << "[REGISTRATION] User \"" << user.jid << "\" unregistered \"" << user.uin << "\"\n";
 
}
 

	
 
void Logger::handleUserUpdated(const UserInfo &user) {
 
	std::cout << "[REGISTRATION] User \"" << user.jid << "\" updated \"" << user.uin << "\"\n";
 
}
 

	
 
void Logger::handleUserCreated(User *user) {
 
	std::cout << "[USERMANAGER] User \"" << user->getJID().toString() << "\" (UIN: \"" << user->getUserInfo().uin << "\") connected and User class has been created\n";
 
}
 

	
 
void Logger::handleUserDestroyed(User *user) {
src/memoryusage.cpp
Show inline comments
 
/**
 
 * XMPP - libpurple transport
 
 *
 
 * Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
 
 *
 
 * 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 "memoryusage.h"
 

	
 
#include <iostream>
 
#include <cstring>
 
#include <sstream>
 
#include <fstream>
 
#include <algorithm>
 
#ifndef WIN32
 
#include <sys/param.h>
 
#endif
 
#ifdef BSD
 
#include <sys/types.h>
 
#include <sys/sysctl.h>
 
#include <sys/param.h>
 
#include <sys/sysctl.h>
 
#include <sys/user.h>
 

	
 
#endif
 

	
 
namespace Transport {
 

	
 
#ifndef WIN32
 
#ifdef BSD
 
void process_mem_usage(double& vm_usage, double& resident_set) {
 
	int mib[4];
 
	size_t size;
 
	mib[0] = CTL_KERN;
 
	mib[1] = KERN_PROC;
 
	mib[2] = KERN_PROC_PID;
 
	mib[3] = getpid();
 
	struct kinfo_proc proc;
 

	
 
	size = sizeof(struct kinfo_proc);
 

	
 
	if (sysctl((int*)mib, 4, &proc, &size, NULL, 0) == -1) {
 
		vm_usage = 0;
 
		resident_set = 0;
 
		return;
 
	}
 

	
 
	// sysctl stores 0 in the size if we can't find the process information.
 
	// Set errno to ESRCH which will be translated in NoSuchProcess later on.
 
	if (size == 0) {
 
		vm_usage = 0;
 
		resident_set = 0;
 
		return;
 
	}
 

	
 
	int pagesize,cnt;
 

	
 
	size = sizeof(pagesize);
 
	sysctlbyname("hw.pagesize", &pagesize, &size, NULL, 0);
 

	
 
	resident_set = (double) (proc.ki_rssize * pagesize / 1024);
 
	vm_usage = (double) proc.ki_size;
 
}
 
#else /* BSD */
 
void process_mem_usage(double& shared, double& resident_set) {
src/networkplugin.cpp
Show inline comments
 
@@ -15,97 +15,99 @@
 
 *
 
 * 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/networkplugin.h"
 
#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 "pbnetwork.pb.h"
 
#include "log4cxx/logger.h"
 
#include "log4cxx/basicconfigurator.h"
 
#include "memoryusage.h"
 

	
 
using namespace log4cxx;
 

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

	
 
namespace Transport {
 

	
 
#define WRAP(MESSAGE, TYPE) 	pbnetwork::WrapperMessage wrap; \
 
	wrap.set_type(TYPE); \
 
	wrap.set_payload(MESSAGE); \
 
	wrap.SerializeToString(&MESSAGE);
 

	
 
NetworkPlugin::NetworkPlugin(Swift::EventLoop *loop, const std::string &host, int port) {
 
	m_factories = new Swift::BoostNetworkFactories(loop);
 
	m_host = host;
 
	m_port = port;
 
	m_pingReceived = false;
 
	m_loop = loop;
 
	m_conn = m_factories->getConnectionFactory()->createConnection();
 
	m_conn->onDataRead.connect(boost::bind(&NetworkPlugin::handleDataRead, this, _1));
 
	m_conn->onConnectFinished.connect(boost::bind(&NetworkPlugin::_handleConnected, this, _1));
 
	m_conn->onDisconnected.connect(boost::bind(&NetworkPlugin::handleDisconnected, this));
 

	
 
	m_pingTimer = m_factories->getTimerFactory()->createTimer(30000);
 
	m_pingTimer->onTick.connect(boost::bind(&NetworkPlugin::pingTimeout, this)); 
 
	connect();
 

	
 
	double shared;
 
#ifndef WIN32
 
	process_mem_usage(shared, m_init_res);
 
#endif
 
}
 

	
 
NetworkPlugin::~NetworkPlugin() {
 
	delete m_factories;
 
}
 

	
 
void NetworkPlugin::handleMessage(const std::string &user, const std::string &legacyName, const std::string &msg, const std::string &nickname, const std::string &xhtml) {
 
	pbnetwork::ConversationMessage m;
 
	m.set_username(user);
 
	m.set_buddyname(legacyName);
 
	m.set_message(msg);
 
	m.set_nickname(nickname);
 
	m.set_xhtml(xhtml);
 

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

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_CONV_MESSAGE);
 

	
 
	send(message);
 
}
 

	
 
void NetworkPlugin::handleAttention(const std::string &user, const std::string &buddyName, const std::string &msg) {
 
	pbnetwork::ConversationMessage m;
 
	m.set_username(user);
 
	m.set_buddyname(buddyName);
 
	m.set_message(msg);
 

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

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_ATTENTION);
 

	
 
	send(message);
 
}
 

	
 
void NetworkPlugin::handleVCard(const std::string &user, unsigned int id, const std::string &legacyName, const std::string &fullName, const std::string &nickname, const std::string &photo) {
 
	pbnetwork::VCard vcard;
 
	vcard.set_username(user);
 
	vcard.set_buddyname(legacyName);
 
	vcard.set_id(id);
 
	vcard.set_fullname(fullName);
 
	vcard.set_nickname(nickname);
 
	vcard.set_photo(photo);
 

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

	
 
@@ -464,70 +466,72 @@ void NetworkPlugin::handleDataRead(const Swift::SafeByteArray &data) {
 
			case pbnetwork::WrapperMessage_Type_TYPE_BUDDY_REMOVED:
 
				handleBuddyRemovedPayload(wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_STATUS_CHANGED:
 
				handleStatusChangedPayload(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_ATTENTION:
 
				handleAttentionPayload(wrapper.payload());
 
				break;
 
			default:
 
				return;
 
		}
 
	}
 
}
 

	
 
void NetworkPlugin::send(const std::string &data) {
 
	char header[4];
 
	*((int*)(header)) = htonl(data.size());
 
	m_conn->write(Swift::createSafeByteArray(std::string(header, 4) + data));
 
}
 

	
 
void NetworkPlugin::sendPong() {
 
	m_pingReceived = true;
 
	std::string message;
 
	pbnetwork::WrapperMessage wrap;
 
	wrap.set_type(pbnetwork::WrapperMessage_Type_TYPE_PONG);
 
	wrap.SerializeToString(&message);
 

	
 
	send(message);
 
	LOG4CXX_INFO(logger, "PONG");
 
	sendMemoryUsage();
 
}
 

	
 
void NetworkPlugin::sendMemoryUsage() {
 
	pbnetwork::Stats stats;
 

	
 
	stats.set_init_res(m_init_res);
 
	double res;
 
	double shared;
 
#ifndef WIN32
 
	process_mem_usage(shared, res);
 
#endif
 
	stats.set_res(res);
 
	stats.set_shared(shared);
 

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

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_STATS);
 

	
 
	send(message);
 
}
 

	
 
void NetworkPlugin::pingTimeout() {
 
	if (m_pingReceived == false) {
 
// 		LOG4CXX_ERROR(logger, "No PING received for long time. Exiting");
 
		handleExit();
 
	}
 
	m_pingReceived = false;
 
	m_pingTimer->start();
 
}
 

	
 
}
src/networkpluginserver.cpp
Show inline comments
 
@@ -79,98 +79,98 @@ class NetworkFactory : public Factory {
 
		// Creates new conversation (NetworkConversation in this case)
 
		Conversation *createConversation(ConversationManager *conversationManager, const std::string &legacyName) {
 
			NetworkConversation *nc = new NetworkConversation(conversationManager, legacyName);
 
			nc->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, m_nps, _1, _2));
 
			return nc;
 
		}
 

	
 
		// Creates new LocalBuddy
 
		Buddy *createBuddy(RosterManager *rosterManager, const BuddyInfo &buddyInfo) {
 
			LocalBuddy *buddy = new LocalBuddy(rosterManager, buddyInfo.id);
 
			buddy->setAlias(buddyInfo.alias);
 
			buddy->setName(buddyInfo.legacyName);
 
			buddy->setSubscription(buddyInfo.subscription);
 
			buddy->setGroups(buddyInfo.groups);
 
			buddy->setFlags((BuddyFlag) buddyInfo.flags);
 
			if (buddyInfo.settings.find("icon_hash") != buddyInfo.settings.end())
 
				buddy->setIconHash(buddyInfo.settings.find("icon_hash")->second.s);
 
			return buddy;
 
		}
 

	
 
	private:
 
		NetworkPluginServer *m_nps;
 
};
 

	
 
// Wraps google protobuf payload into WrapperMessage and serialize it to string
 
#define WRAP(MESSAGE, TYPE) 	pbnetwork::WrapperMessage wrap; \
 
	wrap.set_type(TYPE); \
 
	wrap.set_payload(MESSAGE); \
 
	wrap.SerializeToString(&MESSAGE);
 

	
 
// Executes new backend
 
static unsigned long exec_(std::string path, const char *host, const char *port, const char *config) {
 
	std::string original_path = path;
 
	// BACKEND_ID is replaced with unique ID. The ID is increasing for every backend.
 
	boost::replace_all(path, "BACKEND_ID", boost::lexical_cast<std::string>(backend_id++));
 

	
 
	// Add host and port.
 
	path += std::string(" --host ") + host + " --port " + port + " " + config;
 
	LOG4CXX_INFO(logger, "Starting new backend " << path);
 

	
 
#ifdef _WIN32
 
	STARTUPINFO         si;
 
	PROCESS_INFORMATION pi;
 

	
 
	ZeroMemory (&si, sizeof(si));
 
	si.cb=sizeof (si);
 

	
 
	if (! CreateProcess(
 
	original_path.c_str(),
 
	path.c_str(),         // command line
 
	NULL,
 
	(LPSTR)path.c_str(),         // command line
 
	0,                    // process attributes
 
	0,                    // thread attributes
 
	0,                    // inherit handles
 
	0,                    // creation flags
 
	0,                    // environment
 
	0,                    // cwd
 
	&si,
 
	&pi
 
	)
 
	)  {
 
		LOG4CXX_ERROR(logger, "Could not start process");
 
	}
 

	
 
	return 0;
 
#else
 
	// Create array of char * from string using -lpopt library
 
	char *p = (char *) malloc(path.size() + 1);
 
	strcpy(p, path.c_str());
 
	int argc;
 
	char **argv;
 
	poptParseArgvString(p, &argc, (const char ***) &argv);
 

	
 
	// fork and exec
 
	pid_t pid = fork();
 
	if ( pid == 0 ) {
 
		// child process
 
		exit(execv(argv[0], argv));
 
	} else if ( pid < 0 ) {
 
		// fork failed
 
	}
 
	free(p);
 

	
 
	return (unsigned long) pid;
 
#endif
 
}
 

	
 
#ifndef _WIN32
 
static void SigCatcher(int n) {
 
	pid_t result;
 
	int status;
 
	// Read exit code from all children to not have zombies arround
 
	// WARNING: Do not put LOG4CXX_ here, because it can lead to deadlock
 
	while ((result = waitpid(0, &status, WNOHANG)) > 0) {
 
		if (result != 0) {
 
			if (WIFEXITED(status)) {
 
				if (WEXITSTATUS(status) != 0) {
 
// 					LOG4CXX_ERROR(logger, "Backend can not be started, exit_code=" << WEXITSTATUS(status));
 
				}
 
@@ -1033,97 +1033,97 @@ void NetworkPluginServer::handleBuddyRemoved(Buddy *b) {
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_BUDDY_REMOVED);
 

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

	
 
void NetworkPluginServer::handleBuddyUpdated(Buddy *b, const Swift::RosterItemPayload &item) {
 
	User *user = b->getRosterManager()->getUser();
 

	
 
	dynamic_cast<LocalBuddy *>(b)->setAlias(item.getName());
 
	dynamic_cast<LocalBuddy *>(b)->setGroups(item.getGroups());
 
	user->getRosterManager()->storeBuddy(b);
 

	
 
	pbnetwork::Buddy buddy;
 
	buddy.set_username(user->getJID().toBare());
 
	buddy.set_buddyname(b->getName());
 
	buddy.set_alias(b->getAlias());
 
	buddy.set_groups(b->getGroups().size() == 0 ? "" : b->getGroups()[0]);
 
	buddy.set_status(Swift::StatusShow::None);
 

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

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_BUDDY_CHANGED);
 

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

	
 
void NetworkPluginServer::handleBuddyAdded(Buddy *buddy, const Swift::RosterItemPayload &item) {
 
	handleBuddyUpdated(buddy, item);
 
}
 

	
 
void NetworkPluginServer::handleBlockToggled(Buddy *b) {
 
	User *user = b->getRosterManager()->getUser();
 

	
 
	pbnetwork::Buddy buddy;
 
	buddy.set_username(user->getJID().toBare());
 
	buddy.set_buddyname(b->getName());
 
	buddy.set_alias(b->getAlias());
 
	buddy.set_groups(b->getGroups().size() == 0 ? "" : b->getGroups()[0]);
 
	buddy.set_status(Swift::StatusShow::None);
 
	buddy.set_blocked(not b->isBlocked());
 
	buddy.set_blocked(!b->isBlocked());
 

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

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_BUDDY_CHANGED);
 

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

	
 

	
 
void NetworkPluginServer::handleVCardUpdated(User *user, boost::shared_ptr<Swift::VCard> v) {
 
	pbnetwork::VCard vcard;
 
	vcard.set_username(user->getJID().toBare());
 
	vcard.set_buddyname("");
 
	vcard.set_id(0);
 
	vcard.set_photo(&v->getPhoto()[0], v->getPhoto().size());
 

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

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_VCARD);
 

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

	
 
void NetworkPluginServer::handleVCardRequired(User *user, const std::string &name, unsigned int id) {
 
	pbnetwork::VCard vcard;
 
	vcard.set_username(user->getJID().toBare());
 
	vcard.set_buddyname(name);
 
	vcard.set_id(id);
 

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

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_VCARD);
 

	
 
	Backend *c = (Backend *) user->getData();
 
	if (!c) {
 
		return;
 
	}
src/rostermanager.cpp
Show inline comments
 
/**
 
 * XMPP - libpurple transport
 
 *
 
 * Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
 
 *
 
 * 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/rostermanager.h"
 
#include "transport/rosterstorage.h"
 
#include "transport/storagebackend.h"
 
#include "transport/buddy.h"
 
#include "transport/usermanager.h"
 
#include "transport/buddy.h"
 
#include "transport/user.h"
 
#include "Swiften/Roster/SetRosterRequest.h"
 
#include "Swiften/Elements/RosterPayload.h"
 
#include "Swiften/Elements/RosterItemPayload.h"
 
#include "Swiften/Elements/RosterItemExchangePayload.h"
 
#include "log4cxx/logger.h"
 
#include <boost/foreach.hpp>
 

	
 
#include <map>
 
#include <iterator>
 

	
 
using namespace log4cxx;
 

	
 
namespace Transport {
 

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

	
 
RosterManager::RosterManager(User *user, Component *component){
 
	m_rosterStorage = NULL;
 
	m_user = user;
 
	m_component = component;
 
	m_setBuddyTimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(1000);
 
	m_RIETimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(5000);
 
	m_RIETimer->onTick.connect(boost::bind(&RosterManager::sendRIE, this));
 
}
 

	
 
RosterManager::~RosterManager() {
 
	m_setBuddyTimer->stop();
 
	m_RIETimer->stop();
 
	if (m_rosterStorage) {
 
		m_rosterStorage->storeBuddies();
 
	}
 

	
 
	sendUnavailablePresences(m_user->getJID().toBare());
 

	
 
	for (std::map<std::string, Buddy *>::const_iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
	for (std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
		Buddy *buddy = (*it).second;
 
		if (!buddy) {
 
			continue;
 
		}
 
		delete buddy;
 
	}
 

	
 
	if (m_requests.size() != 0) {
 
		LOG4CXX_INFO(logger, m_user->getJID().toString() <<  ": Removing " << m_requests.size() << " unresponded IQs");
 
		BOOST_FOREACH(Swift::SetRosterRequest::ref request, m_requests) {
 
			request->onResponse.disconnect_all_slots();
 
			m_component->getIQRouter()->removeHandler(request);
 
		}
 
		m_requests.clear();
 
	}
 

	
 
	boost::singleton_pool<boost::pool_allocator_tag, sizeof(unsigned int)>::release_memory();
 

	
 
	if (m_rosterStorage)
 
		delete m_rosterStorage;
 
}
 

	
 
void RosterManager::setBuddy(Buddy *buddy) {
 
// 	m_setBuddyTimer->onTick.connect(boost::bind(&RosterManager::setBuddyCallback, this, buddy));
 
// 	m_setBuddyTimer->start();
 
	setBuddyCallback(buddy);
 
}
 

	
 
void RosterManager::sendBuddyRosterPush(Buddy *buddy) {
 
	if (!m_user->isConnected())
 
		return;
 

	
 
	Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload());
 
	Swift::RosterItemPayload item;
 
	item.setJID(buddy->getJID().toBare());
 
	item.setName(buddy->getAlias());
 
	item.setGroups(buddy->getGroups());
 
	item.setSubscription(Swift::RosterItemPayload::Both);
 

	
 
	payload->addItem(item);
 

	
 
	Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, m_user->getJID().toBare(), m_component->getIQRouter());
 
	request->onResponse.connect(boost::bind(&RosterManager::handleBuddyRosterPushResponse, this, _1, request, buddy->getName()));
 
	request->send();
 
	m_requests.push_back(request);
 
}
 

	
 
void RosterManager::sendBuddySubscribePresence(Buddy *buddy) {
 
@@ -139,110 +142,110 @@ void RosterManager::setBuddyCallback(Buddy *buddy) {
 
			Swift::JID jidWithRIE = m_user->getJIDWithFeature("http://jabber.org/protocol/rosterx");
 
			if (jidWithRIE.isValid()) {
 
				m_RIETimer->start();
 
			}
 
			else {
 
				sendBuddySubscribePresence(buddy);
 
			}
 
		}
 
	}
 

	
 
	if (m_rosterStorage)
 
		m_rosterStorage->storeBuddy(buddy);
 
}
 

	
 
void RosterManager::unsetBuddy(Buddy *buddy) {
 
	m_buddies.erase(buddy->getName());
 
	if (m_rosterStorage)
 
		m_rosterStorage->removeBuddyFromQueue(buddy);
 
	onBuddyUnset(buddy);
 
}
 

	
 
void RosterManager::storeBuddy(Buddy *buddy) {
 
	if (m_rosterStorage) {
 
		m_rosterStorage->storeBuddy(buddy);
 
	}
 
}
 

	
 
void RosterManager::handleBuddyRosterPushResponse(Swift::ErrorPayload::ref error, Swift::SetRosterRequest::ref request, const std::string &key) {
 
	if (m_buddies[key] != NULL) {
 
		m_buddies[key]->handleBuddyChanged();
 
	}
 

	
 
	m_requests.remove(request);
 
	request->onResponse.disconnect_all_slots();
 
}
 

	
 
Buddy *RosterManager::getBuddy(const std::string &name) {
 
	return m_buddies[name];
 
}
 

	
 
void RosterManager::sendRIE() {
 
	m_RIETimer->stop();
 

	
 
	// Check the feature, because proper resource could logout during RIETimer.
 
	Swift::JID jidWithRIE = m_user->getJIDWithFeature("http://jabber.org/protocol/rosterx");
 

	
 
	// fallback to normal subscribe
 
	if (!jidWithRIE.isValid()) {
 
		for (std::map<std::string, Buddy *>::const_iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
		for (std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
			Buddy *buddy = (*it).second;
 
			if (!buddy) {
 
				continue;
 
			}
 
			sendBuddySubscribePresence(buddy);
 
		}
 
		return;
 
	}
 

	
 
	LOG4CXX_INFO(logger, "Sending RIE stanza to " << jidWithRIE.toString());
 

	
 
	Swift::RosterItemExchangePayload::ref payload = Swift::RosterItemExchangePayload::ref(new Swift::RosterItemExchangePayload());
 
	for (std::map<std::string, Buddy *>::const_iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
	for (std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
		Buddy *buddy = (*it).second;
 
		if (!buddy) {
 
			continue;
 
		}
 
		Swift::RosterItemExchangePayload::Item item;
 
		item.setJID(buddy->getJID().toBare());
 
		item.setName(buddy->getAlias());
 
		item.setAction(Swift::RosterItemExchangePayload::Item::Add);
 
// 		item.setGroups(buddy->getGroups());
 

	
 
		payload->addItem(item);
 
	}
 

	
 
	boost::shared_ptr<Swift::GenericRequest<Swift::RosterItemExchangePayload> > request(new Swift::GenericRequest<Swift::RosterItemExchangePayload>(Swift::IQ::Set, jidWithRIE, payload, m_component->getIQRouter()));
 
	request->send();
 
}
 

	
 
void RosterManager::handleSubscription(Swift::Presence::ref presence) {
 
	std::string legacyName = Buddy::JIDToLegacyName(presence->getTo());
 
	// For server mode the subscription changes are handler in rosterresponder.cpp
 
	// using roster pushes.
 
	if (m_component->inServerMode()) {
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setTo(presence->getFrom());
 
		response->setFrom(presence->getTo());
 
		Buddy *buddy = getBuddy(Buddy::JIDToLegacyName(presence->getTo()));
 
		if (buddy) {
 
			LOG4CXX_INFO(logger, m_user->getJID().toString() << ": Subscription received and buddy " << Buddy::JIDToLegacyName(presence->getTo()) << " is already there => answering");
 
			switch (presence->getType()) {
 
				case Swift::Presence::Subscribe:
 
					onBuddyAdded(buddy);
 
					response->setType(Swift::Presence::Subscribed);
 
					break;
 
				case Swift::Presence::Unsubscribe:
 
					onBuddyRemoved(buddy);
 
					response->setType(Swift::Presence::Unsubscribed);
 
					break;
 
				case Swift::Presence::Subscribed:
 
					onBuddyAdded(buddy);
 
					break;
 
				default:
 
					return;
 
			}
 
			m_component->getStanzaChannel()->sendPresence(response);
 
			
 
		}
 
		else {
 
			BuddyInfo buddyInfo;
 
@@ -330,111 +333,111 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) {
 
				// just send response
 
				case Swift::Presence::Unsubscribed:
 
					response->setType(Swift::Presence::Unsubscribe);
 
					break;
 
				// just send response
 
				default:
 
					return;
 
			}
 
		}
 

	
 
		m_component->getStanzaChannel()->sendPresence(response);
 

	
 
		// We have to act as buddy and send its subscribe/unsubscribe just to be sure...
 
		switch (response->getType()) {
 
			case Swift::Presence::Unsubscribed:
 
				response->setType(Swift::Presence::Unsubscribe);
 
				m_component->getStanzaChannel()->sendPresence(response);
 
				break;
 
			case Swift::Presence::Subscribed:
 
				response->setType(Swift::Presence::Subscribe);
 
				m_component->getStanzaChannel()->sendPresence(response);
 
				break;
 
			default:
 
				break;
 
		}
 
	}
 
}
 

	
 
void RosterManager::setStorageBackend(StorageBackend *storageBackend) {
 
	if (m_rosterStorage || !storageBackend) {
 
		return;
 
	}
 
	m_rosterStorage = new RosterStorage(m_user, storageBackend);
 

	
 
	std::list<BuddyInfo> roster;
 
	storageBackend->getBuddies(m_user->getUserInfo().id, roster);
 

	
 
	for (std::list<BuddyInfo>::const_iterator it = roster.begin(); it != roster.end(); it++) {
 
		Buddy *buddy = m_component->getFactory()->createBuddy(this, *it);
 
		LOG4CXX_INFO(logger, m_user->getJID().toString() << ": Adding cached buddy " << buddy->getName() << " fom database");
 
		m_buddies[buddy->getName()] = buddy;
 
		onBuddySet(buddy);
 
	}
 
}
 

	
 
Swift::RosterPayload::ref RosterManager::generateRosterPayload() {
 
	Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload());
 

	
 
	for (std::map<std::string, Buddy *>::const_iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
	for (std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
		Buddy *buddy = (*it).second;
 
		if (!buddy) {
 
			continue;
 
		}
 
		Swift::RosterItemPayload item;
 
		item.setJID(buddy->getJID().toBare());
 
		item.setName(buddy->getAlias());
 
		item.setGroups(buddy->getGroups());
 
		item.setSubscription(Swift::RosterItemPayload::Both);
 
		payload->addItem(item);
 
	}
 
	return payload;
 
}
 

	
 
void RosterManager::sendCurrentPresences(const Swift::JID &to) {
 
	for (std::map<std::string, Buddy *>::const_iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
	for (std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
		Buddy *buddy = (*it).second;
 
		if (!buddy) {
 
			continue;
 
		}
 
		Swift::Presence::ref presence = buddy->generatePresenceStanza(255);
 
		if (presence) {
 
			presence->setTo(to);
 
			m_component->getStanzaChannel()->sendPresence(presence);
 
		}
 
	}
 
}
 

	
 
void RosterManager::sendCurrentPresence(const Swift::JID &from, const Swift::JID &to) {
 
	Buddy *buddy = getBuddy(Buddy::JIDToLegacyName(from));
 
	if (buddy) {
 
		Swift::Presence::ref presence = buddy->generatePresenceStanza(255);
 
		if (presence) {
 
			presence->setTo(to);
 
			m_component->getStanzaChannel()->sendPresence(presence);
 
		}
 
	}
 
	else {
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setTo(to);
 
		response->setFrom(from);
 
		response->setType(Swift::Presence::Unavailable);
 
		m_component->getStanzaChannel()->sendPresence(response);
 
	}
 
}
 

	
 
void RosterManager::sendUnavailablePresences(const Swift::JID &to) {
 
	for (std::map<std::string, Buddy *>::const_iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
	for (std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
		Buddy *buddy = (*it).second;
 
		if (!buddy) {
 
			continue;
 
		}
 
		Swift::Presence::ref presence = buddy->generatePresenceStanza(255);
 
		if (presence) {
 
			presence->setTo(to);
 
			presence->setType(Swift::Presence::Unavailable);
 
			m_component->getStanzaChannel()->sendPresence(presence);
 
		}
 
	}
 
}
 

	
 
}
src/sqlite3backend.cpp
Show inline comments
 
@@ -180,97 +180,97 @@ bool SQLite3Backend::createDatabase() {
 
		exec("CREATE INDEX IF NOT EXISTS user_id03 ON " + m_prefix + "users_settings (user_id);");
 

	
 
		exec("CREATE TABLE IF NOT EXISTS " + m_prefix + "db_version ("
 
			"  ver INTEGER NOT NULL DEFAULT '3'"
 
			");");
 
		exec("REPLACE INTO " + m_prefix + "db_version (ver) values(3)");
 
	}
 
	return true;
 
}
 

	
 
bool SQLite3Backend::exec(const std::string &query) {
 
	char *errMsg = 0;
 
	int rc = sqlite3_exec(m_db, query.c_str(), NULL, 0, &errMsg);
 
	if (rc != SQLITE_OK) {
 
		LOG4CXX_ERROR(logger, errMsg << " during statement " << query);
 
		sqlite3_free(errMsg);
 
		return false;
 
	}
 
	return true;
 
}
 

	
 
void SQLite3Backend::setUser(const UserInfo &user) {
 
	sqlite3_reset(m_setUser);
 
	sqlite3_bind_text(m_setUser, 1, user.jid.c_str(), -1, SQLITE_STATIC);
 
	sqlite3_bind_text(m_setUser, 2, user.uin.c_str(), -1, SQLITE_STATIC);
 
	sqlite3_bind_text(m_setUser, 3, user.password.c_str(), -1, SQLITE_STATIC);
 
	sqlite3_bind_text(m_setUser, 4, user.language.c_str(), -1, SQLITE_STATIC);
 
	sqlite3_bind_text(m_setUser, 5, user.encoding.c_str(), -1, SQLITE_STATIC);
 
	sqlite3_bind_int (m_setUser, 6, user.vip);
 

	
 
	if(sqlite3_step(m_setUser) != SQLITE_DONE) {
 
		LOG4CXX_ERROR(logger, "setUser query"<< (sqlite3_errmsg(m_db) == NULL ? "" : sqlite3_errmsg(m_db)));
 
	}
 
}
 

	
 
bool SQLite3Backend::getUser(const std::string &barejid, UserInfo &user) {
 
// 	SELECT id, jid, uin, password, encoding, language, vip FROM " + m_prefix + "users WHERE jid=?
 
	sqlite3_reset(m_getUser);
 
	sqlite3_bind_text(m_getUser, 1, barejid.c_str(), -1, SQLITE_TRANSIENT);
 

	
 
	int ret;
 
	while((ret = sqlite3_step(m_getUser)) == SQLITE_ROW) {
 
		user.id = sqlite3_column_int(m_getUser, 0);
 
		user.jid = (const char *) sqlite3_column_text(m_getUser, 1);
 
		user.uin = (const char *) sqlite3_column_text(m_getUser, 2);
 
		user.password = (const char *) sqlite3_column_text(m_getUser, 3);
 
		user.encoding = (const char *) sqlite3_column_text(m_getUser, 4);
 
		user.language = (const char *) sqlite3_column_text(m_getUser, 5);
 
		user.vip = sqlite3_column_int(m_getUser, 6);
 
		user.vip = sqlite3_column_int(m_getUser, 6) != 0;
 
		return true;
 
	}
 

	
 
	if (ret != SQLITE_DONE) {
 
		LOG4CXX_ERROR(logger, "getUser query"<< (sqlite3_errmsg(m_db) == NULL ? "" : sqlite3_errmsg(m_db)));
 
	}
 

	
 
	return false;
 
}
 

	
 
void SQLite3Backend::setUserOnline(long id, bool online) {
 
	
 
}
 

	
 
long SQLite3Backend::addBuddy(long userId, const BuddyInfo &buddyInfo) {
 
// 	"INSERT INTO " + m_prefix + "buddies (user_id, uin, subscription, groups, nickname, flags) VALUES (?, ?, ?, ?, ?, ?)"
 
	BEGIN(m_addBuddy);
 
	BIND_INT(m_addBuddy, userId);
 
	BIND_STR(m_addBuddy, buddyInfo.legacyName);
 
	BIND_STR(m_addBuddy, buddyInfo.subscription);
 
	BIND_STR(m_addBuddy, buddyInfo.groups.size() == 0 ? "" : buddyInfo.groups[0]); // TODO: serialize groups
 
	BIND_STR(m_addBuddy, buddyInfo.alias);
 
	BIND_INT(m_addBuddy, buddyInfo.flags);
 

	
 
	if(sqlite3_step(m_addBuddy) != SQLITE_DONE) {
 
		LOG4CXX_ERROR(logger, "addBuddy query"<< (sqlite3_errmsg(m_db) == NULL ? "" : sqlite3_errmsg(m_db)));
 
		return -1;
 
	}
 

	
 
	long id = (long) sqlite3_last_insert_rowid(m_db);
 

	
 
// 	INSERT OR REPLACE INTO " + m_prefix + "buddies_settings (user_id, buddy_id, var, type, value) VALUES (?, ?, ?, ?, ?)
 
	BEGIN(m_updateBuddySetting);
 
	BIND_INT(m_updateBuddySetting, userId);
 
	BIND_INT(m_updateBuddySetting, id);
 
	BIND_STR(m_updateBuddySetting, buddyInfo.settings.find("icon_hash")->first);
 
	BIND_INT(m_updateBuddySetting, TYPE_STRING);
 
	BIND_STR(m_updateBuddySetting, buddyInfo.settings.find("icon_hash")->second.s);
 

	
 
	EXECUTE_STATEMENT(m_updateBuddySetting, "updateBuddySetting query");
 
	return id;
 
}
 

	
 
void SQLite3Backend::updateBuddy(long userId, const BuddyInfo &buddyInfo) {
 
// 	UPDATE " + m_prefix + "buddies SET groups=?, nickname=?, flags=?, subscription=? WHERE user_id=? AND uin=?
 
	BEGIN(m_updateBuddy);
 
	BIND_STR(m_updateBuddy, buddyInfo.groups.size() == 0 ? "" : buddyInfo.groups[0]); // TODO: serialize groups
 
	BIND_STR(m_updateBuddy, buddyInfo.alias);
src/transport.cpp
Show inline comments
 
@@ -50,107 +50,107 @@ namespace Transport {
 
	
 
static LoggerPtr logger = Logger::getLogger("Component");
 
static LoggerPtr logger_xml = Logger::getLogger("Component.XML");
 

	
 
Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories, Config *config, Factory *factory, Transport::UserRegistry *userRegistry) {
 
	m_component = NULL;
 
	m_userRegistry = NULL;
 
	m_server = NULL;
 
	m_reconnectCount = 0;
 
	m_config = config;
 
	m_factory = factory;
 
	m_loop = loop;
 
	m_userRegistry = userRegistry;
 

	
 
	m_jid = Swift::JID(CONFIG_STRING(m_config, "service.jid"));
 

	
 
	m_factories = factories;
 

	
 
	m_reconnectTimer = m_factories->getTimerFactory()->createTimer(3000);
 
	m_reconnectTimer->onTick.connect(bind(&Component::start, this)); 
 

	
 
	if (CONFIG_BOOL(m_config, "service.server_mode")) {
 
		LOG4CXX_INFO(logger, "Creating component in server mode on port " << CONFIG_INT(m_config, "service.port"));
 
		m_server = new Swift::Server(loop, m_factories, m_userRegistry, m_jid, CONFIG_INT(m_config, "service.port"));
 
		if (!CONFIG_STRING(m_config, "service.cert").empty()) {
 
			LOG4CXX_INFO(logger, "Using PKCS#12 certificate " << CONFIG_STRING(m_config, "service.cert"));
 
			LOG4CXX_INFO(logger, "SSLv23_server_method used.");
 
			TLSServerContextFactory *f = new OpenSSLServerContextFactory();
 
			m_server->addTLSEncryption(f, PKCS12Certificate(CONFIG_STRING(m_config, "service.cert"), createSafeByteArray(CONFIG_STRING(m_config, "service.cert_password"))));
 
		}
 
		else {
 
			LOG4CXX_WARN(logger, "No PKCS#12 certificate used. TLS is disabled.");
 
		}
 
// 		m_server->start();
 
		m_stanzaChannel = m_server->getStanzaChannel();
 
		m_iqRouter = m_server->getIQRouter();
 

	
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<StorageParser>("private", "jabber:iq:private"));
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::AttentionParser>("attention", "urn:xmpp:attention:0"));
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::XHTMLIMParser>("html", "http://jabber.org/protocol/xhtml-im"));
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::BlockParser>("block", "urn:xmpp:block:0"));
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
 

	
 
		m_server->addPayloadSerializer(new Swift::AttentionSerializer());
 
		m_server->addPayloadSerializer(new Swift::XHTMLIMSerializer());
 
		m_server->addPayloadSerializer(new Swift::BlockSerializer());
 
		m_server->addPayloadSerializer(new Swift::InvisibleSerializer());
 

	
 
		m_server->onDataRead.connect(bind(&Component::handleDataRead, this, _1));
 
		m_server->onDataWritten.connect(bind(&Component::handleDataWritten, this, _1));
 
		m_server->onDataRead.connect(boost::bind(&Component::handleDataRead, this, _1));
 
		m_server->onDataWritten.connect(boost::bind(&Component::handleDataWritten, this, _1));
 
	}
 
	else {
 
		LOG4CXX_INFO(logger, "Creating component in gateway mode");
 
		m_component = new Swift::Component(loop, m_factories, m_jid, CONFIG_STRING(m_config, "service.password"));
 
		m_component->setSoftwareVersion("", "");
 
		m_component->onConnected.connect(bind(&Component::handleConnected, this));
 
		m_component->onError.connect(bind(&Component::handleConnectionError, this, _1));
 
		m_component->onDataRead.connect(bind(&Component::handleDataRead, this, _1));
 
		m_component->onDataWritten.connect(bind(&Component::handleDataWritten, this, _1));
 
		m_component->onError.connect(boost::bind(&Component::handleConnectionError, this, _1));
 
		m_component->onDataRead.connect(boost::bind(&Component::handleDataRead, this, _1));
 
		m_component->onDataWritten.connect(boost::bind(&Component::handleDataWritten, this, _1));
 
		m_stanzaChannel = m_component->getStanzaChannel();
 
		m_iqRouter = m_component->getIQRouter();
 
	}
 

	
 
	m_capsMemoryStorage = new CapsMemoryStorage();
 
	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) {
 
		m_server->stop();
 
		delete m_server;
 
	}
 
}
 

	
 
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);
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>
 
#ifndef WIN32
 
#include <execinfo.h>
 
#endif
 
#include <stdio.h>
 
#include <stdlib.h>
 

	
 
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_ignoreDisconnect = 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");
 
	updateLastActivity();
 
}
 

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

	
 
	LOG4CXX_INFO(logger, m_jid.toString() << ": No JID with " << feature << " feature");
 
	return jid;
 
}
 

	
 
static void
 
print_trace (void)
 
{
 
#ifndef WIN32
 
void *array[80];
 
size_t size;
 
char **strings;
 
size_t i;
 

	
 
size = backtrace (array, 80);
 
strings = backtrace_symbols (array, size);
 

	
 
printf ("Obtained %zd stack frames.\n", size);
 

	
 
for (i = 0; i < size; i++)
 
	printf ("%s\n", strings[i]);
 

	
 
free (strings);
 
#endif
 
}
 

	
 
void User::handlePresence(Swift::Presence::ref presence) {
 
	std::cout << "PRESENCE " << presence->getFrom().toString() << "\n";
 
// 	print_trace();
 
	if (!m_connected) {
 
		// we are not connected to legacy network, so we should do it when disco#info arrive :)
 
		if (m_readyForConnect == false) {
 
			
 
			// Forward status message to legacy network, but only if it's sent from active resource
 
// 					if (m_activeResource == presence->getFrom().getResource().getUTF8String()) {
 
// 						forwardStatus(presenceShow, stanzaStatus);
 
// 					}
 
			boost::shared_ptr<Swift::CapsInfo> capsInfo = presence->getPayload<Swift::CapsInfo>();
 
			if (capsInfo && capsInfo->getHash() == "sha-1") {
 
				if (m_entityCapsManager->getCaps(presence->getFrom()) != Swift::DiscoInfo::ref()) {
 
					LOG4CXX_INFO(logger, m_jid.toString() << ": Ready to be connected to legacy network");
 
					m_readyForConnect = true;
 
					onReadyToConnect();
 
				}
 
			}
 
			else if (m_component->inServerMode()) {
 
				LOG4CXX_INFO(logger, m_jid.toString() << ": Ready to be connected to legacy network");
 
				m_readyForConnect = true;
 
				onReadyToConnect();
 
			}
 
			else {
 
				m_reconnectTimer->start();
 
			}
 
		}
 
	}
 
	bool isMUC = presence->getPayload<Swift::MUCPayload>() != NULL || *presence->getTo().getNode().c_str() == '#';
 
	if (isMUC) {
 
		if (presence->getType() == Swift::Presence::Unavailable) {
 
			LOG4CXX_INFO(logger, m_jid.toString() << ": Going to left room " << presence->getTo().getNode());
 
			onRoomLeft(presence->getTo().getNode());
 
		}
 
		else {
 
			// force connection to legacy network to let backend to handle auto-join on connect.
 
			if (!m_readyForConnect) {
 
				LOG4CXX_INFO(logger, m_jid.toString() << ": Ready to be connected to legacy network");
 
				m_readyForConnect = true;
 
				onReadyToConnect();
 
			}
 
			LOG4CXX_INFO(logger, m_jid.toString() << ": Going to join room " << presence->getTo().getNode() << " as " << presence->getTo().getResource());
 
			onRoomJoined(presence->getTo().getNode(), presence->getTo().getResource(), "");
 
		}
 
		return;
src/usermanager.cpp
Show inline comments
 
@@ -54,97 +54,99 @@ UserManager::UserManager(Component *component, UserRegistry *userRegistry, Stora
 

	
 
	component->onUserPresenceReceived.connect(bind(&UserManager::handlePresence, this, _1));
 
	m_component->getStanzaChannel()->onMessageReceived.connect(bind(&UserManager::handleMessageReceived, this, _1));
 
	m_component->getStanzaChannel()->onPresenceReceived.connect(bind(&UserManager::handleGeneralPresenceReceived, this, _1));
 

	
 
	m_userRegistry->onConnectUser.connect(bind(&UserManager::connectUser, this, _1));
 
	m_userRegistry->onDisconnectUser.connect(bind(&UserManager::disconnectUser, this, _1));
 
// 	component->onDiscoInfoResponse.connect(bind(&UserManager::handleDiscoInfoResponse, this, _1, _2, _3));
 

	
 
	m_removeTimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(1);
 
}
 

	
 
UserManager::~UserManager(){
 
	if (m_storageResponder) {
 
		m_storageResponder->stop();
 
		delete m_storageResponder;
 
	}
 
}
 

	
 
void UserManager::addUser(User *user) {
 
	m_users[user->getJID().toBare().toString()] = user;
 
	onUserCreated(user);
 
}
 

	
 
User *UserManager::getUser(const std::string &barejid){
 
	if (m_cachedUser && barejid == m_cachedUser->getJID().toBare().toString()) {
 
		return m_cachedUser;
 
	}
 

	
 
	if (m_users.find(barejid) != m_users.end()) {
 
		User *user = m_users[barejid];
 
		m_cachedUser = user;
 
		return user;
 
	}
 
	return NULL;
 
}
 

	
 
void UserManager::removeUser(User *user) {
 
	m_users.erase(user->getJID().toBare().toString());
 
	if (m_cachedUser == user)
 
		m_cachedUser = NULL;
 

	
 
	if (m_component->inServerMode()) {
 
		disconnectUser(user->getJID());
 
	}
 

	
 
	onUserDestroyed(user);
 
	delete user;
 
#ifndef WIN32
 
	malloc_trim(0);
 
#endif
 
// 	VALGRIND_DO_LEAK_CHECK;
 
}
 

	
 
int UserManager::getUserCount() {
 
	return m_users.size();
 
}
 

	
 
void UserManager::handlePresence(Swift::Presence::ref presence) {
 
	std::string barejid = presence->getTo().toBare().toString();
 
	std::string userkey = presence->getFrom().toBare().toString();
 

	
 
	User *user = getUser(userkey);
 
	// Create user class if it's not there
 
	if (!user) {
 
		// Admin user is not legacy network user, so do not create User class instance for him
 
		if (CONFIG_STRING(m_component->getConfig(), "service.admin_username") == presence->getFrom().getNode()) {
 
			return;
 
		}
 

	
 
		// No user and unavailable presence -> answer with unavailable
 
		if (presence->getType() == Swift::Presence::Unavailable) {
 
			Swift::Presence::ref response = Swift::Presence::create();
 
			response->setTo(presence->getFrom());
 
			response->setFrom(presence->getTo());
 
			response->setType(Swift::Presence::Unavailable);
 
			m_component->getStanzaChannel()->sendPresence(response);
 

	
 
			// Set user offline in database
 
			if (m_storageBackend) {
 
				UserInfo res;
 
				bool registered = m_storageBackend->getUser(userkey, res);
 
				if (registered) {
 
					m_storageBackend->setUserOnline(res.id, false);
 
				}
 
			}
 
			return;
 
		}
 

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

	
 
		// In server mode, there's no registration, but we store users into database
 
		// (if storagebackend is available) because of caching. Passwords are not stored
 
		// in server mode.
 
		if (m_component->inServerMode()) {
 
			if (!registered) {
 
				res.password = "";
 
				res.uin = presence->getFrom().getNode();
0 comments (0 inline, 0 general)