Changeset - 79673211dd9c
[Not reviewed]
Merge
0 12 0
Vitaly Takmazov - 13 years ago 2013-02-06 21:55:48
vitalyster@gmail.com
Merge branch 'master' of https://github.com/hanzz/libtransport
11 files changed with 90 insertions and 556 deletions:
0 comments (0 inline, 0 general)
CMakeLists.txt
Show inline comments
 
@@ -100,25 +100,25 @@ endif(WIN32)
 
message( STATUS "Found Boost: ${Boost_LIBRARIES}, ${Boost_INCLUDE_DIR}")
 

	
 
# FIND POPT
 
if (NOT WIN32)
 
	set(popt_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
	find_package(popt REQUIRED)
 
endif()
 

	
 
###### Database ######
 

	
 
# FIND SQLITE3
 
if (ENABLE_SQLITE3)
 
	if (NOT CMAKE_COMPILER_IS_GNUCXX)
 
	if (MSVC)
 
		ADD_SUBDIRECTORY(${CMAKE_SOURCE_DIR}/msvc-deps)
 
	else()
 
		if (WIN32)
 
			ADD_SUBDIRECTORY(${CMAKE_SOURCE_DIR}/msvc-deps/sqlite3)
 
		else()
 
			set(sqlite3_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
			find_package(sqlite3)
 
		endif()
 
	endif()
 
endif()
 

	
 
# FIND MYSQL
 
@@ -239,24 +239,34 @@ endif()
 
# FIND CPPUNIT
 
if(ENABLE_TESTS)
 
	set(cppunit_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
	find_package(cppunit)
 

	
 
	if(NOT CPPUNIT_FOUND AND CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARY)
 
		set(CCPUNIT_LIBRARIES ${CPPUNIT_LIBRARY})
 
		set(CPPUNIT_FOUND 1)
 
		message(STATUS "Using cppunit: ${CPPUNIT_INCLUDE_DIR} ${CPPUNIT_LIBRARIES}")
 
	endif()
 
endif()
 

	
 
if (APPLE)
 
        FIND_LIBRARY(IOKIT_FRAMEWORK IOKit)
 
        FIND_LIBRARY(SECURITY_FRAMEWORK Security)
 
        FIND_LIBRARY(APPKIT_FRAMEWORK AppKit)
 
        FIND_LIBRARY(SYSTEMCONFIGURATION_FRAMEWORK SystemConfiguration)
 
        FIND_LIBRARY(SECURITYINTERFACE_FRAMEWORK SecurityInterface)
 
        MARK_AS_ADVANCED(IOKIT_FRAMEWORK APPKIT_FRAMEWORK SYSTEMCONFIGURATION_FRAMEWORK SECURITY_FRAMEWORK SECURITYINTERFACE_FRAMEWORK)
 
        SET (APPLE_FRAMEWORKS ${IOKIT_FRAMEWORK} ${APPKIT_FRAMEWORK} ${SYSTEMCONFIGURATION_FRAMEWORK} ${SECURITY_FRAMEWORK} ${SECURITYINTERFACE_FRAMEWORK})
 
endif()
 

	
 
message("  Supported features")
 
message("-----------------------")
 

	
 
if (SPECTRUM_VERSION)
 
	ADD_DEFINITIONS(-DSPECTRUM_VERSION="${SPECTRUM_VERSION}")
 
else (SPECTRUM_VERSION)
 
	if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
 
		if (NOT GIT_EXECUTABLE)
 
		set (GIT_EXECUTABLE git)
 
		endif()
 
		execute_process(COMMAND ${GIT_EXECUTABLE} "--git-dir=${CMAKE_CURRENT_SOURCE_DIR}/.git" rev-parse --short HEAD
 
						OUTPUT_VARIABLE GIT_REVISION
backends/skype/main.cpp
Show inline comments
 
#include "glib.h"
 
#include <dbus-1.0/dbus/dbus-glib-lowlevel.h>
 
#include "sqlite3.h"
 
#include <iostream>
 

	
 
#include "transport/config.h"
 
#include "transport/logging.h"
 
#include "transport/transport.h"
 
#include "transport/usermanager.h"
 
#include "transport/memoryusage.h"
 
#include "transport/sqlite3backend.h"
 
#include "transport/userregistration.h"
 
#include "transport/user.h"
 
#include "transport/storagebackend.h"
 
#include "transport/rostermanager.h"
 
#include "transport/conversation.h"
 
#include "transport/networkplugin.h"
 
#include <boost/filesystem.hpp>
 
#include "sys/wait.h"
 
#include "sys/signal.h"
 
// #include "valgrind/memcheck.h"
 
#ifndef __FreeBSD__
 
#include "malloc.h"
 
#endif
 
#include <dbus-1.0/dbus/dbus-glib-lowlevel.h>
 

	
 
#include "sqlite3.h"
 
#include "skype.h"
 

	
 

	
 
DEFINE_LOGGER(logger, "backend");
 

	
 
using namespace Transport;
 

	
 
class SpectrumNetworkPlugin;
 
class SkypePlugin;
 

	
 
#define GET_RESPONSE_DATA(RESP, DATA) ((RESP.find(std::string(DATA) + " ") != std::string::npos) ? RESP.substr(RESP.find(DATA) + strlen(DATA) + 1) : "");
 
#define GET_PROPERTY(VAR, OBJ, WHICH, PROP) std::string VAR = sk->send_command(std::string("GET ") + OBJ + " " + WHICH + " " + PROP); \
 
					try {\
 
						VAR = GET_RESPONSE_DATA(VAR, PROP);\
 
					}\
 
					catch (std::out_of_range& oor) {\
 
						VAR="";\
 
					}
 
					
 

	
 
					
 
@@ -61,25 +62,25 @@ class SpectrumNetworkPlugin;
 
							(void)STATEMENT##_id_get;
 

	
 
#define BIND_INT(STATEMENT, VARIABLE) sqlite3_bind_int(STATEMENT, STATEMENT##_id++, VARIABLE)
 
#define BIND_STR(STATEMENT, VARIABLE) sqlite3_bind_text(STATEMENT, STATEMENT##_id++, VARIABLE.c_str(), -1, SQLITE_STATIC)
 
#define RESET_GET_COUNTER(STATEMENT)	STATEMENT##_id_get = 0;
 
#define GET_INT(STATEMENT)	sqlite3_column_int(STATEMENT, STATEMENT##_id_get++)
 
#define GET_STR(STATEMENT)	(const char *) sqlite3_column_text(STATEMENT, STATEMENT##_id_get++)
 
#define GET_BLOB(STATEMENT)	(const void *) sqlite3_column_blob(STATEMENT, STATEMENT##_id_get++)
 
#define EXECUTE_STATEMENT(STATEMENT, NAME) 	if(sqlite3_step(STATEMENT) != SQLITE_DONE) {\
 
		LOG4CXX_ERROR(logger, NAME<< (sqlite3_errmsg(db) == NULL ? "" : sqlite3_errmsg(db)));\
 
			}
 

	
 
SpectrumNetworkPlugin *np;
 
SkypePlugin *np;
 

	
 
int m_sock;
 
static int writeInput;
 

	
 
static std::string host;
 
static int port = 10000;
 

	
 
DBusHandlerResult skype_notify_handler(DBusConnection *connection, DBusMessage *message, gpointer user_data);
 

	
 
static pbnetwork::StatusType getStatus(const std::string &st) {
 
	pbnetwork::StatusType status = pbnetwork::STATUS_ONLINE;
 
	if (st == "SKYPEOUT" || st == "OFFLINE") {
 
@@ -88,81 +89,45 @@ static pbnetwork::StatusType getStatus(const std::string &st) {
 
	else if (st == "DND") {
 
		status = pbnetwork::STATUS_DND;
 
	}
 
	else if (st == "NA") {
 
		status = pbnetwork::STATUS_XA;
 
	}
 
	else if (st == "AWAY") {
 
		status = pbnetwork::STATUS_AWAY;
 
	}
 
	return status;
 
}
 

	
 
class Skype {
 
	public:
 
		Skype(const std::string &user, const std::string &username, const std::string &password);
 
		~Skype() { LOG4CXX_INFO(logger, "Skype instance desctuctor"); logout(); }
 
		void login();
 
		void logout();
 
		std::string send_command(const std::string &message);
 

	
 
		const std::string &getUser() {
 
			return m_user;
 
		}
 

	
 
		const std::string &getUsername() {
 
			return m_username;
 
		}
 

	
 
		bool createDBusProxy();
 
		bool loadSkypeBuddies();
 

	
 
		int getPid() {
 
			return (int) m_pid;
 
		}
 

	
 
	private:
 
		std::string m_username;
 
		std::string m_password;
 
		GPid m_pid;
 
		DBusGConnection *m_connection;
 
		DBusGProxy *m_proxy;
 
		std::string m_user;
 
		int m_timer;
 
		int m_counter;
 
		int fd_output;
 
		std::map<std::string, std::string> m_groups;
 
};
 

	
 
class SpectrumNetworkPlugin : public NetworkPlugin {
 
class SkypePlugin : public NetworkPlugin {
 
	public:
 
		SpectrumNetworkPlugin(Config *config, const std::string &host, int port) : NetworkPlugin() {
 
		SkypePlugin(Config *config, const std::string &host, int port) : NetworkPlugin() {
 
			this->config = config;
 
			LOG4CXX_INFO(logger, "Starting the backend.");
 
		}
 

	
 
		~SpectrumNetworkPlugin() {
 
		~SkypePlugin() {
 
			for (std::map<Skype *, std::string>::iterator it = m_accounts.begin(); it != m_accounts.end(); it++) {
 
				delete (*it).first;
 
			}
 
		}
 

	
 
		void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
 
			std::string name = legacyName;
 
			if (name.find("skype.") == 0 || name.find("prpl-skype.") == 0) {
 
				name = name.substr(name.find(".") + 1);
 
			}
 
			LOG4CXX_INFO(logger,  "Creating account with name '" << name << "'");
 

	
 
			Skype *skype = new Skype(user, name, password);
 
			Skype *skype = new Skype(this, user, name, password);
 
			m_sessions[user] = skype;
 
			m_accounts[skype] = user;
 

	
 
			skype->login();
 
		}
 

	
 
		void handleMemoryUsage(double &res, double &shared) {
 
			res = 0;
 
			shared = 0;
 
			for(std::map<std::string, Skype *>::const_iterator it = m_sessions.begin(); it != m_sessions.end(); it++) {
 
				Skype *skype = it->second;
 
				if (skype) {
 
@@ -382,513 +347,24 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 
		void handleAttentionRequest(const std::string &user, const std::string &buddyName, const std::string &message) {
 

	
 
		}
 

	
 
		std::map<std::string, Skype *> m_sessions;
 
		std::map<Skype *, std::string> m_accounts;
 
		std::map<std::string, unsigned int> m_vcards;
 
		Config *config;
 
		
 
};
 

	
 

	
 
Skype::Skype(const std::string &user, const std::string &username, const std::string &password) {
 
	m_username = username;
 
	m_user = user;
 
	m_password = password;
 
	m_pid = 0;
 
	m_connection = 0;
 
	m_proxy = 0;
 
	m_timer = -1;
 
	m_counter = 0;
 
}
 

	
 

	
 
static gboolean load_skype_buddies(gpointer data) {
 
	Skype *skype = (Skype *) data;
 
	return skype->loadSkypeBuddies();
 
}
 

	
 
bool Skype::createDBusProxy() {
 
	if (m_proxy == NULL) {
 
		LOG4CXX_INFO(logger, "Creating DBus proxy for com.Skype.Api.");
 
		m_counter++;
 

	
 
		GError *error = NULL;
 
		m_proxy = dbus_g_proxy_new_for_name_owner (m_connection, "com.Skype.API", "/com/Skype", "com.Skype.API", &error);
 
		if (m_proxy == NULL && error != NULL) {
 
			LOG4CXX_INFO(logger,  m_username << ":" << error->message);
 

	
 
			if (m_counter == 15) {
 
				LOG4CXX_ERROR(logger, "Logging out, proxy couldn't be created: " << error->message);
 
				np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, error->message);
 
				logout();
 
				g_error_free(error);
 
				return FALSE;
 
			}
 
			g_error_free(error);
 
		}
 

	
 
		if (m_proxy) {
 
			LOG4CXX_INFO(logger, "Proxy created.");
 
			DBusObjectPathVTable vtable;
 
			vtable.message_function = &skype_notify_handler;
 
			dbus_connection_register_object_path(dbus_g_connection_get_connection(m_connection), "/com/Skype/Client", &vtable, this);
 

	
 
			m_counter = 0;
 
			m_timer = g_timeout_add_seconds(1, load_skype_buddies, this);
 
			return FALSE;
 
		}
 
		return TRUE;
 
	}
 
	return FALSE;
 
}
 

	
 
static gboolean create_dbus_proxy(gpointer data) {
 
	Skype *skype = (Skype *) data;
 
	return skype->createDBusProxy();
 
}
 

	
 
void Skype::login() {
 
	if (m_username.find("..") == 0 || m_username.find("/") != std::string::npos) {
 
		np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Invalid username");
 
		return;
 
	}
 
	boost::filesystem::remove_all(std::string("/tmp/skype/") + m_username);
 

	
 
	boost::filesystem::path	path(std::string("/tmp/skype/") + m_username);
 
	if (!boost::filesystem::exists(path)) {
 
		boost::filesystem::create_directories(path);
 
		boost::filesystem::path	path2(std::string("/tmp/skype/") + m_username + "/" + m_username );
 
		boost::filesystem::create_directories(path2);
 
	}
 

	
 
	std::string shared_xml = "<?xml version=\"1.0\"?>\n"
 
							"<config version=\"1.0\" serial=\"28\" timestamp=\"" + boost::lexical_cast<std::string>(time(NULL)) + ".0\">\n"
 
							"<UI>\n"
 
								"<Installed>2</Installed>\n"
 
								"<Language>en</Language>\n"
 
							"</UI>\n"
 
							"</config>\n";
 
	g_file_set_contents(std::string(std::string("/tmp/skype/") + m_username + "/shared.xml").c_str(), shared_xml.c_str(), -1, NULL);
 

	
 
	std::string config_xml = "<?xml version=\"1.0\"?>\n"
 
							"<config version=\"1.0\" serial=\"7\" timestamp=\"" + boost::lexical_cast<std::string>(time(NULL)) + ".0\">\n"
 
								"<Lib>\n"
 
									"<Account>\n"
 
									"<IdleTimeForAway>30000000</IdleTimeForAway>\n"
 
									"<IdleTimeForNA>300000000</IdleTimeForNA>\n"
 
									"<LastUsed>" + boost::lexical_cast<std::string>(time(NULL)) + "</LastUsed>\n"
 
									"</Account>\n"
 
								"</Lib>\n"
 
								"<UI>\n"
 
									"<API>\n"
 
									"<Authorizations>Spectrum</Authorizations>\n"
 
									"<BlockedPrograms></BlockedPrograms>\n"
 
									"</API>\n"
 
								"</UI>\n"
 
							"</config>\n";
 
	g_file_set_contents(std::string(std::string("/tmp/skype/") + m_username + "/" + m_username +"/config.xml").c_str(), config_xml.c_str(), -1, NULL);
 

	
 
	sleep(1);
 
	std::string db_path = std::string("/tmp/skype/") + m_username;
 
	char *db = (char *) malloc(db_path.size() + 1);
 
	strcpy(db, db_path.c_str());
 
	LOG4CXX_INFO(logger,  m_username << ": Spawning new Skype instance dbpath=" << db);
 
	gchar* argv[6] = {"skype", "--disable-cleanlooks", "--pipelogin", "--dbpath", db, 0};
 

	
 
	int fd;
 
	GError *error = NULL;
 
	bool spawned = g_spawn_async_with_pipes(NULL,
 
		argv,
 
		NULL /*envp*/,
 
		G_SPAWN_SEARCH_PATH,
 
		NULL /*child_setup*/,
 
		NULL /*user_data*/,
 
		&m_pid /*child_pid*/,
 
		&fd,
 
		NULL,
 
		&fd_output,
 
		&error);
 

	
 
	if (!spawned) {
 
		LOG4CXX_ERROR(logger, "Error spawning the Skype instance: " << error->message)
 
		np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Error spawning the Skype instance.");
 
		return;
 
	}
 

	
 
	std::string login_data = std::string(m_username + " " + m_password + "\n");
 
	LOG4CXX_INFO(logger,  m_username << ": Login data=" << m_username);
 
	write(fd, login_data.c_str(), login_data.size());
 
	close(fd);
 

	
 
	fcntl (fd_output, F_SETFL, O_NONBLOCK);
 

	
 
	free(db);
 

	
 
	//Initialise threading
 
	dbus_threads_init_default();
 

	
 
	if (m_connection == NULL)
 
	{
 
		LOG4CXX_INFO(logger, "Creating DBUS connection.");
 
		GError *error = NULL;
 
		m_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
 
		if (m_connection == NULL && error != NULL)
 
		{
 
			LOG4CXX_INFO(logger,  m_username << ": Creating DBUS Connection error: " << error->message);
 
			g_error_free(error);
 
			return;
 
		}
 
	}
 

	
 
	sleep(1);
 
	m_timer = g_timeout_add_seconds(1, create_dbus_proxy, this);
 
}
 

	
 
bool Skype::loadSkypeBuddies() {
 
//	std::string re = "CONNSTATUS OFFLINE";
 
//	while (re == "CONNSTATUS OFFLINE" || re.empty()) {
 
//		sleep(1);
 

	
 
	gchar buffer[1024];
 
	int bytes_read = read(fd_output, buffer, 1023);
 
	if (bytes_read > 0) {
 
		buffer[bytes_read] = 0;
 
		std::string b(buffer);
 
		LOG4CXX_WARN(logger, "Skype wrote this on stdout '" << b << "'");
 
		if (b.find("Incorrect Password") != std::string::npos) {
 
			LOG4CXX_INFO(logger, "Incorrect password, logging out")
 
			np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_FAILED, "Incorrect password");
 
			close(fd_output);
 
			logout();
 
			return FALSE;
 
		}
 
	}
 

	
 
	std::string re = send_command("NAME Spectrum");
 
	if (m_counter++ > 15) {
 
		LOG4CXX_ERROR(logger, "Logging out, because we tried to connect the Skype over DBUS 15 times without success");
 
		np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Skype is not ready. This issue have been logged and admins will check it and try to fix it soon.");
 
		close(fd_output);
 
		logout();
 
		return FALSE;
 
	}
 

	
 
	if (re.empty() || re == "CONNSTATUS OFFLINE" || re == "ERROR 68") {
 
		return TRUE;
 
	}
 

	
 
	close(fd_output);
 

	
 
	if (send_command("PROTOCOL 7") != "PROTOCOL 7") {
 
		LOG4CXX_ERROR(logger, "PROTOCOL 7 failed, logging out");
 
		np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Skype is not ready. This issue have been logged and admins will check it and try to fix it soon.");
 
		logout();
 
		return FALSE;
 
	}
 

	
 
	np->handleConnected(m_user);
 

	
 
	std::map<std::string, std::string> group_map;
 
	std::string groups = send_command("SEARCH GROUPS CUSTOM");
 
	if (groups.find(' ') != std::string::npos) {
 
		groups = groups.substr(groups.find(' ') + 1);
 
		std::vector<std::string> grps;
 
		boost::split(grps, groups, boost::is_any_of(","));
 
		BOOST_FOREACH(std::string grp, grps) {
 
			std::vector<std::string> data;
 
			std::string name = send_command("GET GROUP " + grp + " DISPLAYNAME");
 

	
 
			if (name.find("ERROR") == 0) {
 
				continue;
 
			}
 

	
 
			boost::split(data, name, boost::is_any_of(" "));
 
			name = GET_RESPONSE_DATA(name, "DISPLAYNAME");
 

	
 
			std::string users = send_command("GET GROUP " + data[1] + " USERS");
 
			try {
 
				users = GET_RESPONSE_DATA(users, "USERS");
 
			}
 
			catch (std::out_of_range& oor) {
 
				continue;
 
			}
 
			boost::split(data, users, boost::is_any_of(","));
 
			BOOST_FOREACH(std::string u, data) {
 
				group_map[u] = grp;
 
			}
 
		}
 
	}
 

	
 
	std::string friends = send_command("GET AUTH_CONTACTS_PROFILES");
 

	
 
	char **full_friends_list = g_strsplit((strchr(friends.c_str(), ' ')+1), ";", 0);
 
	if (full_friends_list && full_friends_list[0])
 
	{
 
		//in the format of: username;full name;phone;office phone;mobile phone;
 
		//                  online status;friendly name;voicemail;mood
 
		// (comma-seperated lines, usernames can have comma's)
 

	
 
		for (int i=0; full_friends_list[i] && full_friends_list[i+1] && *full_friends_list[i] != '\0'; i+=8)
 
		{
 
			std::string buddy = full_friends_list[i];
 

	
 
			if (buddy[0] == ',') {
 
				buddy.erase(buddy.begin());
 
			}
 

	
 
			if (buddy.rfind(",") != std::string::npos) {
 
				buddy = buddy.substr(buddy.rfind(","));
 
			}
 

	
 
			if (buddy[0] == ',') {
 
				buddy.erase(buddy.begin());
 
			}
 

	
 
			LOG4CXX_INFO(logger, "Got buddy " << buddy);
 
			std::string st = full_friends_list[i + 5];
 

	
 
			pbnetwork::StatusType status = getStatus(st);
 

	
 
			std::string alias = full_friends_list[i + 6];
 

	
 
			std::string mood_text = "";
 
			if (full_friends_list[i + 8] && *full_friends_list[i + 8] != '\0' && *full_friends_list[i + 8] != ',') {
 
				mood_text = full_friends_list[i + 8];
 
			}
 

	
 
			std::vector<std::string> groups;
 
			if (group_map.find(buddy) != group_map.end()) {
 
				groups.push_back(group_map[buddy]);
 
			}
 
			np->handleBuddyChanged(m_user, buddy, alias, groups, status, mood_text);
 
		}
 
	}
 
	g_strfreev(full_friends_list);
 

	
 
	send_command("SET AUTOAWAY OFF");
 
	send_command("SET USERSTATUS ONLINE");
 
	return FALSE;
 
}
 

	
 
void Skype::logout() {
 
	if (m_pid != 0) {
 
		if (m_proxy) {
 
			send_command("SET USERSTATUS INVISIBLE");
 
			send_command("SET USERSTATUS OFFLINE");
 
			sleep(2);
 
			g_object_unref(m_proxy);
 
		}
 
		LOG4CXX_INFO(logger,  m_username << ": Terminating Skype instance (SIGTERM)");
 
		kill((int) m_pid, SIGTERM);
 
		// Give skype a chance
 
		sleep(2);
 
		LOG4CXX_INFO(logger,  m_username << ": Killing Skype instance (SIGKILL)");
 
		kill((int) m_pid, SIGKILL);
 
		m_pid = 0;
 
	}
 
}
 

	
 
std::string Skype::send_command(const std::string &message) {
 
	GError *error = NULL;
 
	gchar *str = NULL;
 
// 			int message_num;
 
// 			gchar error_return[30];
 

	
 
	LOG4CXX_INFO(logger, "Sending: '" << message << "'");
 
	if (!dbus_g_proxy_call (m_proxy, "Invoke", &error, G_TYPE_STRING, message.c_str(), G_TYPE_INVALID,
 
						G_TYPE_STRING, &str, G_TYPE_INVALID))
 
	{
 
			if (error && error->message)
 
			{
 
			LOG4CXX_INFO(logger,  m_username << ": DBUS Error: " << error->message);
 
			g_error_free(error);
 
			return "";
 
		} else {
 
			LOG4CXX_INFO(logger,  m_username << ": DBUS no response");
 
			return "";
 
		}
 

	
 
	}
 
	if (str != NULL)
 
	{
 
		LOG4CXX_INFO(logger,  m_username << ": DBUS:'" << str << "'");
 
	}
 
	return str ? std::string(str) : std::string();
 
}
 

	
 
static void handle_skype_message(std::string &message, Skype *sk) {
 
	std::vector<std::string> cmd;
 
	boost::split(cmd, message, boost::is_any_of(" "));
 

	
 
	if (cmd[0] == "USER") {
 
		if (cmd[1] == sk->getUsername()) {
 
			return;
 
		}
 

	
 
		if (cmd[2] == "ONLINESTATUS") {
 
			if (cmd[3] == "SKYPEOUT" || cmd[3] == "UNKNOWN") {
 
				return;
 
			}
 
			else {
 
				pbnetwork::StatusType status = getStatus(cmd[3]);
 
				GET_PROPERTY(mood_text, "USER", cmd[1], "MOOD_TEXT");
 
				GET_PROPERTY(alias, "USER", cmd[1], "FULLNAME");
 

	
 
				std::vector<std::string> groups;
 
				np->handleBuddyChanged(sk->getUser(), cmd[1], alias, groups, status, mood_text);
 
			}
 
		}
 
		else if (cmd[2] == "MOOD_TEXT") {
 
			GET_PROPERTY(st, "USER", cmd[1], "ONLINESTATUS");
 
			pbnetwork::StatusType status = getStatus(st);
 

	
 
			std::string mood_text = GET_RESPONSE_DATA(message, "MOOD_TEXT");
 

	
 
			std::vector<std::string> groups;
 
			np->handleBuddyChanged(sk->getUser(), cmd[1], "", groups, status, mood_text);
 
		}
 
		else if (cmd[2] == "BUDDYSTATUS" && cmd[3] == "3") {
 
			GET_PROPERTY(mood_text, "USER", cmd[1], "MOOD_TEXT");
 
			GET_PROPERTY(st, "USER", cmd[1], "ONLINESTATUS");
 
			pbnetwork::StatusType status = getStatus(st);
 

	
 
			std::vector<std::string> groups;
 
			np->handleBuddyChanged(sk->getUser(), cmd[1], "", groups, status, mood_text);
 
		}
 
		else if (cmd[2] == "FULLNAME") {
 
			GET_PROPERTY(alias, "USER", cmd[1], "FULLNAME");
 
			GET_PROPERTY(mood_text, "USER", cmd[1], "MOOD_TEXT");
 
			GET_PROPERTY(st, "USER", cmd[1], "ONLINESTATUS");
 
			pbnetwork::StatusType status = getStatus(st);
 

	
 
			std::vector<std::string> groups;
 
			np->handleBuddyChanged(sk->getUser(), cmd[1], alias, groups, status, mood_text);
 
		}
 
		else if(cmd[2] == "RECEIVEDAUTHREQUEST") {
 
			np->handleAuthorization(sk->getUser(), cmd[1]);
 
		}
 
	}
 
	else if (cmd[0] == "GROUP") {
 
// 		if (cmd[2] == "DISPLAYNAME") {
 
// 			//GROUP 810 DISPLAYNAME My Friends
 
// 			std::string grp = GET_RESPONSE_DATA(message, "DISPLAYNAME");
 
// 			std::string users = sk->send_command("GET GROUP " + cmd[1] + " USERS");
 
// 			try {
 
// 				users = GET_RESPONSE_DATA(users, "USERS");
 
// 			}
 
// 			catch (std::out_of_range& oor) {
 
// 				return;
 
// 			}
 
// 
 
// 			std::vector<std::string> data;
 
// 			boost::split(data, users, boost::is_any_of(","));
 
// 			BOOST_FOREACH(std::string u, data) {
 
// 				GET_PROPERTY(alias, "USER", u, "FULLNAME");
 
// 				GET_PROPERTY(mood_text, "USER", u, "MOOD_TEXT");
 
// 				GET_PROPERTY(st, "USER", u, "ONLINESTATUS");
 
// 				pbnetwork::StatusType status = getStatus(st);
 
// 
 
// 				std::vector<std::string> groups;
 
// 				groups.push_back(grp);
 
// 				np->handleBuddyChanged(sk->getUser(), u, alias, groups, status, mood_text);
 
// 			}
 
// 		}
 
		if (cmd[2] == "NROFUSERS" && cmd[3] != "0") {
 
			GET_PROPERTY(grp, "GROUP", cmd[1], "DISPLAYNAME");
 
			std::string users = sk->send_command("GET GROUP " + cmd[1] + " USERS");
 
			try {
 
				users = GET_RESPONSE_DATA(users, "USERS");
 
			}
 
			catch (std::out_of_range& oor) {
 
				return;
 
			}
 

	
 
			std::vector<std::string> data;
 
			boost::split(data, users, boost::is_any_of(","));
 
			BOOST_FOREACH(std::string u, data) {
 
				GET_PROPERTY(alias, "USER", u, "FULLNAME");
 
				GET_PROPERTY(mood_text, "USER", u, "MOOD_TEXT");
 
				GET_PROPERTY(st, "USER", u, "ONLINESTATUS");
 
				pbnetwork::StatusType status = getStatus(st);
 

	
 
				std::vector<std::string> groups;
 
				groups.push_back(grp);
 
				np->handleBuddyChanged(sk->getUser(), u, alias, groups, status, mood_text);
 
			}
 
		}
 
	}
 
	else if (cmd[0] == "CHATMESSAGE") {
 
		if (cmd[3] == "RECEIVED") {
 
			GET_PROPERTY(body, "CHATMESSAGE", cmd[1], "BODY");
 
			GET_PROPERTY(from_handle, "CHATMESSAGE", cmd[1], "FROM_HANDLE");
 

	
 
			if (from_handle == sk->getUsername())
 
				return;
 

	
 
			np->handleMessage(sk->getUser(), from_handle, body);
 

	
 
			sk->send_command("SET CHATMESSAGE " + cmd[1] + " SEEN");
 
		}
 
	}
 
	else if (cmd[0] == "CALL") {
 
		// CALL 884 STATUS RINGING
 
		if (cmd[2] == "STATUS") {
 
			if (cmd[3] == "RINGING" || cmd[3] == "MISSED") {
 
				// handle only incoming calls
 
				GET_PROPERTY(type, "CALL", cmd[1], "TYPE");
 
				if (type.find("INCOMING") != 0) {
 
					return;
 
				}
 

	
 
				GET_PROPERTY(from, "CALL", cmd[1], "PARTNER_HANDLE");
 
				GET_PROPERTY(dispname, "CALL", cmd[1], "PARTNER_DISPNAME");
 

	
 
				if (cmd[3] == "RINGING") {
 
					np->handleMessage(sk->getUser(), from, "User " + dispname + " is calling you.");
 
				}
 
				else {
 
					np->handleMessage(sk->getUser(), from, "You have missed call from user " + dispname + ".");
 
				}
 
			}
 
		}
 
	}
 
}
 

	
 
DBusHandlerResult skype_notify_handler(DBusConnection *connection, DBusMessage *message, gpointer user_data) {
 
	DBusMessageIter iterator;
 
	gchar *message_temp;
 
	DBusMessage *temp_message;
 
	
 
	temp_message = dbus_message_ref(message);
 
	dbus_message_iter_init(temp_message, &iterator);
 
	if (dbus_message_iter_get_arg_type(&iterator) != DBUS_TYPE_STRING)
 
	{
 
		dbus_message_unref(message);
 
		return (DBusHandlerResult) FALSE;
 
	}
 
	
 
	do {
 
		dbus_message_iter_get_basic(&iterator, &message_temp);
 
		std::string m(message_temp);
 
		LOG4CXX_INFO(logger,"DBUS message: " << m);
 
		handle_skype_message(m, (Skype *) user_data);
 
	} while(dbus_message_iter_has_next(&iterator) && dbus_message_iter_next(&iterator));
 
	
 
	dbus_message_unref(message);
 
	
 
	return DBUS_HANDLER_RESULT_HANDLED;
 
}
 

	
 
static void spectrum_sigchld_handler(int sig)
 
{
 
	int status;
 
	pid_t pid;
 

	
 
	do {
 
		pid = waitpid(-1, &status, WNOHANG);
 
	} while (pid != 0 && pid != (pid_t)-1);
 

	
 
	if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
 
		char errmsg[BUFSIZ];
 
		snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
 
@@ -960,31 +436,34 @@ int main(int argc, char **argv) {
 

	
 
	std::string error;
 
	Config *cfg = Config::createFromArgs(argc, argv, error, host, port);
 
	if (cfg == NULL) {
 
		std::cerr << error;
 
		return 1;
 
	}
 

	
 
	Logging::initBackendLogging(cfg);
 

	
 
	g_type_init();
 
	
 

	
 
	m_sock = create_socket(host.c_str(), port);
 

	
 
	g_set_printerr_handler(log_glib_error);
 

	
 
	GIOChannel *channel;
 
	GIOCondition cond = (GIOCondition) G_IO_IN;
 
	channel = g_io_channel_unix_new(m_sock);
 
	g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, transportDataReceived, NULL, io_destroy);
 

	
 
	np = new SpectrumNetworkPlugin(cfg, host, port);
 
	dbus_threads_init_default();
 

	
 
	np = new SkypePlugin(cfg, host, port);
 

	
 
	GMainLoop *m_loop;
 
	m_loop = g_main_loop_new(NULL, FALSE);
 

	
 
	if (m_loop) {
 
		g_main_loop_run(m_loop);
 
	}
 

	
 
}
backends/swiften/main.cpp
Show inline comments
 
@@ -8,27 +8,29 @@
 
// Swiften
 
#include "Swiften/Swiften.h"
 

	
 
#ifndef WIN32
 
// for signal handler
 
#include "unistd.h"
 
#include "signal.h"
 
#include "sys/wait.h"
 
#include "sys/signal.h"
 
#endif
 

	
 
#ifndef __FreeBSD__
 
#ifndef __MACH__
 
// malloc_trim
 
#include "malloc.h"
 
#endif
 
#endif
 

	
 
// Boost
 
#include <boost/algorithm/string.hpp>
 
using namespace boost::filesystem;
 
using namespace boost::program_options;
 
using namespace Transport;
 

	
 
DEFINE_LOGGER(logger, "Swiften");
 

	
 
// eventloop
 
Swift::SimpleEventLoop *loop_;
 

	
 
@@ -180,27 +182,29 @@ class SwiftenPlugin : public NetworkPlugin {
 

	
 
			boost::shared_ptr<Swift::Client> client = m_users[user];
 
			if (client) {
 
				client->onConnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftConnected, this, user));
 
				client->onDisconnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftDisconnected, this, user, _1));
 
				client->onMessageReceived.disconnect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1));
 
				m_users.erase(user);
 
				m_mucs.erase(user);
 
			}
 

	
 
#ifndef WIN32
 
#ifndef __FreeBSD__
 
#ifndef __MACH__
 
			// force returning of memory chunks allocated by libxml2 to kernel
 
			malloc_trim(0);
 
#endif
 
#endif
 
#endif
 
		}
 

	
 
		void handleSwiftConnected(const std::string &user) {
 
			LOG4CXX_INFO(logger, user << ": Connected to XMPP server.");
 
			handleConnected(user);
 
			m_users[user]->requestRoster();
 
			Swift::Presence::ref response = Swift::Presence::create();
 
			response->setFrom(m_users[user]->getJID());
 
			m_users[user]->sendPresence(response);
 
		}
 

	
 
@@ -211,24 +215,28 @@ class SwiftenPlugin : public NetworkPlugin {
 
				pbnetwork::StatusType status = lastPresence ? ((pbnetwork::StatusType) lastPresence->getShow()) : pbnetwork::STATUS_NONE;
 
				handleBuddyChanged(user, item.getJID().toBare().toString(),
 
								   item.getName(), item.getGroups(), status);
 
			}
 
		}
 

	
 
		void handleSwiftPresenceChanged(const std::string &user, Swift::Presence::ref presence) {
 
			boost::shared_ptr<Swift::Client> client = m_users[user];
 
			if (client->getMUCRegistry()->isMUC(presence->getFrom().toBare())) {
 
				return;
 
			}
 

	
 
			if (presence->getPayload<Swift::MUCUserPayload>() != NULL || presence->getPayload<Swift::MUCPayload>() != NULL) {
 
				return;
 
			}
 

	
 
			LOG4CXX_INFO(logger, user << ": " << presence->getFrom().toBare().toString() << " presence changed");
 

	
 
			std::string message = presence->getStatus();
 
			std::string photo = "";
 

	
 
			boost::shared_ptr<Swift::VCardUpdate> update = presence->getPayload<Swift::VCardUpdate>();
 
			if (update) {
 
				photo = update->getPhotoHash();
 
			}
 

	
 
			boost::optional<Swift::XMPPRosterItem> item = m_users[user]->getRoster()->getItem(presence->getFrom());
 
			if (item) {
 
@@ -290,40 +298,39 @@ class SwiftenPlugin : public NetworkPlugin {
 
		}
 

	
 
		void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
 
			boost::shared_ptr<Swift::Client> client = m_users[user];
 
			if (client) {
 
				client->onConnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftConnected, this, user));
 
// 				client->onDisconnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftDisconnected, this, user, _1));
 
				client->onMessageReceived.disconnect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1));
 
				client->getRoster()->onInitialRosterPopulated.disconnect(boost::bind(&SwiftenPlugin::handleSwiftRosterReceived, this, user));
 
				client->getPresenceOracle()->onPresenceChange.disconnect(boost::bind(&SwiftenPlugin::handleSwiftPresenceChanged, this, user, _1));
 
				client->disconnect();
 
				m_mucs.erase(user);
 
				m_users.erase(user);
 
			}
 
		}
 

	
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &msg, const std::string &xhtml = "", const std::string &id = "") {
 
			LOG4CXX_INFO(logger, "Sending message from " << user << " to " << legacyName << ".");
 
			boost::shared_ptr<Swift::Client> client = m_users[user];
 
			if (client) {
 
				boost::shared_ptr<Swift::Message> message(new Swift::Message());
 
				message->setTo(Swift::JID(legacyName));
 
				message->setFrom(client->getJID());
 
				message->setBody(msg);
 
				if (client->getMUCRegistry()->isMUC(legacyName)) {
 
					message->setType(Swift::Message::Groupchat);
 
					boost::shared_ptr<MUCController> muc = m_mucs[user][legacyName];
 
					handleMessage(user, legacyName, msg, muc->getNickname(), xhtml);
 
// 					handleMessage(user, legacyName, msg, muc->getNickname(), xhtml);
 
				}
 

	
 
				client->sendMessage(message);
 
			}
 
		}
 

	
 
		void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) {
 
			boost::shared_ptr<Swift::Client> client = m_users[user];
 
			if (client) {
 
				LOG4CXX_INFO(logger, user << ": fetching VCard of " << legacyName << " id=" << id);
 
				Swift::GetVCardRequest::ref request = Swift::GetVCardRequest::create(Swift::JID(legacyName), client->getIQRouter());
 
				request->onResponse.connect(boost::bind(&SwiftenPlugin::handleSwiftVCardReceived, this, user, id, _1, _2));
include/transport/memoryusage.h
Show inline comments
 
@@ -15,21 +15,19 @@
 
 *
 
 * 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 <vector>
 

	
 
#ifndef WIN32
 
#include "signal.h"
 
#else 
 
#define pid_t void*
 
#endif
 

	
 
namespace Transport {
 

	
 
#ifndef WIN32
 
	void process_mem_usage(double& shared, double& resident_set, pid_t pid = 0);
 
#endif
 

	
 
}
include/transport/protocol.proto
Show inline comments
 
@@ -86,24 +86,28 @@ message RoomList {
 
	repeated string room = 1;
 
	repeated string name = 2;
 
}
 

	
 
enum ParticipantFlag {
 
	PARTICIPANT_FLAG_NONE = 0;
 
	PARTICIPANT_FLAG_MODERATOR = 1;
 
	PARTICIPANT_FLAG_CONFLICT = 2;
 
	PARTICIPANT_FLAG_BANNED = 4;
 
	PARTICIPANT_FLAG_NOT_AUTHORIZED = 8;
 
	PARTICIPANT_FLAG_ME = 16;
 
	PARTICIPANT_FLAG_KICKED = 32;
 
	PARTICIPANT_FLAG_VISITOR = 64;
 
	PARTICIPANT_FLAG_MEMBER = 128;
 
	PARTICIPANT_FLAG_ADMIN = 256;
 
	PARTICIPANT_FLAG_OWNER = 512;
 
}
 

	
 
message Participant {
 
	required string userName = 1;
 
	required string room = 2;
 
	required string nickname = 3;
 
	required int32 flag = 4;
 
	required StatusType status = 5;
 
	optional string statusMessage = 6;
 
	optional string newname = 7;
 
}
 

	
spectrum/src/main.cpp
Show inline comments
 
@@ -19,26 +19,28 @@
 
#include "Swiften/EventLoop/SimpleEventLoop.h"
 
#include "Swiften/Network/BoostNetworkFactories.h"
 
#include <boost/filesystem.hpp>
 
#include <boost/algorithm/string.hpp>
 
#ifndef WIN32
 
#include "sys/signal.h"
 
#include "sys/stat.h"
 
#include <pwd.h>
 
#include <grp.h>
 
#include <sys/resource.h>
 
#include "libgen.h"
 
#ifndef __FreeBSD__
 
#ifndef __MACH__
 
#include <malloc.h>
 
#endif
 
#endif
 
#else
 
#include <process.h>
 
#define getpid _getpid
 
#include "win32/ServiceWrapper.h"
 
#endif
 
#include <sys/stat.h>
 

	
 
using namespace Transport;
 
using namespace Transport::Util;
 

	
 
DEFINE_LOGGER(logger, "Spectrum");
 

	
 
@@ -299,28 +301,30 @@ int main(int argc, char **argv)
 
	std::string config_file;
 
	std::string jid;
 
#ifdef WIN32
 
	std::string install_service_name, uninstall_service_name, run_service_name;
 
	// determine the name of the currently executing file
 
	char szFilePath[MAX_PATH];
 
	GetModuleFileNameA(NULL, szFilePath, sizeof(szFilePath));
 
	std::string exe_file(szFilePath);					
 
#endif	
 
	setlocale(LC_ALL, "");
 
#ifndef WIN32
 
#ifndef __FreeBSD__
 
#ifndef __MACH__
 
	mallopt(M_CHECK_ACTION, 2);
 
	mallopt(M_PERTURB, 0xb);
 
#endif
 
#endif
 
#endif
 

	
 
#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;
 
	}
 
#else
spectrum_manager/src/CMakeLists.txt
Show inline comments
 
cmake_minimum_required(VERSION 2.6)
 
FILE(GLOB SRC *.cpp *.c)
 
 
ADD_EXECUTABLE(spectrum2_manager ${SRC} ../../src/config.cpp ../../src/util.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../include/transport/protocol.pb.cc)
 

	
 
ADD_DEPENDENCIES(spectrum2_manager pb)
 
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/../../include/transport/protocol.pb.cc PROPERTIES GENERATED 1)
 

	
 
target_link_libraries(spectrum2_manager ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES})
 

	
 
if(APPLE)
 
target_link_libraries(spectrum2_manager ${APPLE_FRAMEWORKS})
 
endif()
 
INSTALL(TARGETS spectrum2_manager RUNTIME DESTINATION bin)
 
 
INSTALL(FILES
 
	spectrum_manager.cfg
 
	DESTINATION /etc/spectrum2
 
	)
src/CMakeLists.txt
Show inline comments
 
cmake_minimum_required(VERSION 2.6)
 
FILE(GLOB SRC *.cpp *.h)
 
FILE(GLOB_RECURSE SWIFTEN_SRC ../include/Swiften/*.cpp)
 

	
 
# Build without openssl on msvc
 
if (CMAKE_COMPILER_IS_GNUCXX)
 
if (NOT MSVC)
 
	string(REGEX REPLACE "[^;]+;?/Schannel/[^;]+;?" "" SWIFTEN_SRC "${SWIFTEN_SRC}") 
 
else()
 
	string(REGEX REPLACE "[^;]+;?/OpenSSL/[^;]+;?" "" SWIFTEN_SRC "${SWIFTEN_SRC}") 
 
endif()
 

	
 
FILE(GLOB HEADERS ../include/transport/*.h)
 

	
 
if (CPPUNIT_FOUND)
 
	FILE(GLOB SRC_TEST tests/*.cpp)
 

	
 
	ADD_EXECUTABLE(libtransport_test ${SRC_TEST})
 
	set_target_properties(libtransport_test PROPERTIES COMPILE_DEFINITIONS LIBTRANSPORT_TEST=1)
 
@@ -38,25 +38,28 @@ if (PROTOBUF_FOUND)
 
else(PROTOBUF_FOUND)
 
	ADD_LIBRARY(transport SHARED ${HEADERS} ${SRC} ${SWIFTEN_SRC})
 
endif(PROTOBUF_FOUND)
 

	
 
# if (CMAKE_COMPILER_IS_GNUCXX)
 
	if (NOT WIN32)
 
		ADD_DEFINITIONS(-fPIC)
 
	endif()
 
# endif()
 

	
 
if (WIN32)
 
	include_directories("${CMAKE_SOURCE_DIR}/msvc-deps/sqlite3")
 
	TARGET_LINK_LIBRARIES(transport transport-plugin sqlite3 ${PQXX_LIBRARY} ${PQ_LIBRARY} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES} ${PROTOBUF_LIBRARY})
 
	TARGET_LINK_LIBRARIES(transport transport-plugin sqlite3 ${PQXX_LIBRARY} ${PQ_LIBRARY} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES} ${PROTOBUF_LIBRARY} psapi.lib)
 
else()
 
	TARGET_LINK_LIBRARIES(transport transport-plugin ${PQXX_LIBRARY} ${PQ_LIBRARY} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES} ${POPT_LIBRARY} ${PROTOBUF_LIBRARY})
 
endif()
 

	
 
SET_TARGET_PROPERTIES(transport PROPERTIES
 
      VERSION ${TRANSPORT_VERSION} SOVERSION ${TRANSPORT_VERSION}
 
)
 
if (APPLE)
 
	TARGET_LINK_LIBRARIES(transport ${APPLE_FRAMEWORKS})
 
endif()
 

	
 
INSTALL(TARGETS transport LIBRARY DESTINATION ${LIB_INSTALL_DIR} ARCHIVE DESTINATION ${LIB_INSTALL_DIR} COMPONENT libraries)
 

	
 
#CONFIGURE_FILE(transport.pc.in "${CMAKE_CURRENT_BINARY_DIR}/transport.pc")
 
#INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/transport.pc" DESTINATION lib/pkgconfig)
src/admininterface.cpp
Show inline comments
 
@@ -127,55 +127,47 @@ void AdminInterface::handleQuery(Swift::Message::ref message) {
 
	else if (message->getBody().find("has_online_user") == 0) {
 
		User *user = m_userManager->getUser(getArg(message->getBody()));
 
		std::cout << getArg(message->getBody()) << "\n";
 
		message->setBody(boost::lexical_cast<std::string>(user != NULL));
 
	}
 
	else if (message->getBody() == "backends_count") {
 
		int backends = m_server->getBackendCount();
 
		message->setBody(boost::lexical_cast<std::string>(backends));
 
	}
 
	else if (message->getBody() == "res_memory") {
 
		double shared = 0;
 
		double rss = 0;
 
#ifndef WIN32
 
		process_mem_usage(shared, rss);
 
#endif
 

	
 
		const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
 
		BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
 
			rss += backend->res;
 
		}
 

	
 
		message->setBody(boost::lexical_cast<std::string>(rss));
 
	}
 
	else if (message->getBody() == "shr_memory") {
 
		double shared = 0;
 
		double rss = 0;
 
#ifndef WIN32
 
		process_mem_usage(shared, rss);
 
#endif
 

	
 
		const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
 
		BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
 
			shared += backend->shared;
 
		}
 

	
 
		message->setBody(boost::lexical_cast<std::string>(shared));
 
	}
 
	else if (message->getBody() == "used_memory") {
 
		double shared = 0;
 
		double rss = 0;
 
#ifndef WIN32
 
		process_mem_usage(shared, rss);
 
#endif
 
		rss -= shared;
 

	
 
		const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
 
		BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
 
			rss += backend->res - backend->shared;
 
		}
 

	
 
		message->setBody(boost::lexical_cast<std::string>(rss));
 
	}
 
	else if (message->getBody() == "average_memory_per_user") {
 
		if (m_userManager->getUserCount() == 0) {
 
			message->setBody(boost::lexical_cast<std::string>(0));
src/memoryusage.cpp
Show inline comments
 
@@ -19,38 +19,59 @@
 
 */
 

	
 
#include "transport/memoryusage.h"
 

	
 
#include <iostream>
 
#include <cstring>
 
#include <sstream>
 
#include <fstream>
 
#include <algorithm>
 
#include <boost/lexical_cast.hpp>
 
#ifndef WIN32
 
#include <sys/param.h>
 
#else 
 
#include <windows.h>
 
#include <psapi.h>
 
#endif
 
#ifdef BSD
 
#ifdef __MACH__
 
#include <mach/mach.h>
 
#elif 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
 
#ifdef __MACH__
 

	
 
void process_mem_usage(double& vm_usage, double& resident_set, pid_t pid) {
 

	
 
	struct task_basic_info t_info;
 
	mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
 

	
 
	if (KERN_SUCCESS != task_info(mach_task_self(),
 
                              TASK_BASIC_INFO, (task_info_t)&t_info, 
 
                              &t_info_count)) {
 
		vm_usage = 0;
 
		resident_set = 0;
 
    		return;
 
	}
 
	vm_usage = t_info.virtual_size;
 
	resident_set = t_info.resident_size;
 
}
 
#elif BSD
 
void process_mem_usage(double& vm_usage, double& resident_set, pid_t pid) {
 
	int mib[4];
 
	size_t size;
 
	mib[0] = CTL_KERN;
 
	mib[1] = KERN_PROC;
 
	mib[2] = KERN_PROC_PID;
 
	if (pid == 0) {
 
		mib[3] = getpid();
 
	}
 
	else {
 
		mib[3] = pid;
 
	}
 
@@ -111,15 +132,24 @@ void process_mem_usage(double& shared, double& resident_set, pid_t pid) {
 
	// the two fields we want
 
	//
 
	unsigned long shared_;
 
	long rss;
 

	
 
	stat_stream >> O >> rss >> shared_; // don't care about the rest
 

	
 
	long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
 
	shared     = shared_ * page_size_kb;
 
	resident_set = rss * page_size_kb;
 
}
 
#endif /* else BSD */
 
#else
 
#define PSAPI_VERSION 1
 
#define pid_t void*
 
	void process_mem_usage(double& shared, double& resident_set, pid_t pid) {
 
		PROCESS_MEMORY_COUNTERS_EX pmc;
 
		GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc));
 
		shared =  (double)pmc.PrivateUsage;
 
		resident_set = (double)pmc.WorkingSetSize;
 
	}
 
#endif /* WIN32 */
 

	
 
}
src/usermanager.cpp
Show inline comments
 
@@ -25,26 +25,28 @@
 
#include "transport/conversationmanager.h"
 
#include "transport/rostermanager.h"
 
#include "transport/userregistry.h"
 
#include "transport/logging.h"
 
#include "transport/discoitemsresponder.h"
 
#include "storageresponder.h"
 

	
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Elements/StreamError.h"
 
#include "Swiften/Elements/MUCPayload.h"
 
#include "Swiften/Elements/ChatState.h"
 
#ifndef __FreeBSD__ 
 
#ifndef __MACH__
 
#include "malloc.h"
 
#endif
 
#endif
 
// #include "valgrind/memcheck.h"
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "UserManager");
 

	
 
UserManager::UserManager(Component *component, UserRegistry *userRegistry, DiscoItemsResponder *discoItemsResponder, StorageBackend *storageBackend) {
 
	m_cachedUser = NULL;
 
	m_onlineBuddies = 0;
 
	m_sentToXMPP = 0;
 
	m_sentToBackend = 0;
 
	m_component = component;
 
@@ -121,27 +123,29 @@ void UserManager::removeUser(User *user, bool onUserBehalf) {
 
		// We have to clear all received presences for this user in PresenceOracle.
 
		m_component->getPresenceOracle()->clearPresences(user->getJID().toBare());
 
	}
 

	
 
	if (m_storageBackend && onUserBehalf) {
 
		m_storageBackend->setUserOnline(user->getUserInfo().id, false);
 
	}
 

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

	
 
void UserManager::removeAllUsers(bool onUserBehalf) {
 
	while(m_users.begin() != m_users.end()) {
 
		removeUser((*m_users.begin()).second, onUserBehalf);
 
	}
 
}
 

	
 
int UserManager::getUserCount() {
 
	return m_users.size();
 
}
 
@@ -239,26 +243,26 @@ void UserManager::handlePresence(Swift::Presence::ref presence) {
 
					registered = m_storageBackend->getUser(userkey, res);
 
				}
 
				else {
 
					registered = true;
 
				}
 
			}
 
			res.password = m_userRegistry->getUserPassword(userkey);
 
		}
 

	
 
		// We allow auto_register feature in gateway-mode. This allows IRC user to register
 
		// the transport just by joining the room.
 
		if (!m_component->inServerMode()) {
 
			if (!registered && (CONFIG_BOOL(m_component->getConfig(), "registration.auto_register") ||
 
				!CONFIG_BOOL_DEFAULTED(m_component->getConfig(), "registration.needRegistration", true))) {
 
			if (!registered && (CONFIG_BOOL(m_component->getConfig(), "registration.auto_register")
 
				/*!CONFIG_BOOL_DEFAULTED(m_component->getConfig(), "registration.needRegistration", true)*/)) {
 
				res.password = "";
 
				res.jid = userkey;
 

	
 
				bool isMUC = presence->getPayload<Swift::MUCPayload>() != NULL || *presence->getTo().getNode().c_str() == '#';
 
				if (isMUC) {
 
					res.uin = presence->getTo().getResource();
 
				}
 
				else {
 
					res.uin = presence->getFrom().toString();
 
				}
 
				LOG4CXX_INFO(logger, "Auto-registering user " << userkey << " with uin=" << res.uin);
 

	
0 comments (0 inline, 0 general)