Files @ 5521c4094411
Branch filter:

Location: libtransport.git/src/admininterface.cpp - annotation

HanzZ
Fix regression when sending unavailable presences
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
091411eea4d9
091411eea4d9
7c93aee6f49a
981513b2a52c
9c294ea31925
cbcf2f145298
330ecc6dd45f
9c294ea31925
9c294ea31925
9c294ea31925
7c93aee6f49a
9c294ea31925
34207065ceb5
34207065ceb5
34207065ceb5
34207065ceb5
34207065ceb5
34207065ceb5
34207065ceb5
34207065ceb5
981513b2a52c
9c294ea31925
9c294ea31925
091411eea4d9
091411eea4d9
981513b2a52c
f75c6e8a701c
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
9c294ea31925
8b7923f3e3f4
351a6d97df2b
d3ccb9f195c8
d3ccb9f195c8
d3ccb9f195c8
a1d5543db0da
091411eea4d9
527e57d66c53
091411eea4d9
a1d5543db0da
f75c6e8a701c
f75c6e8a701c
f75c6e8a701c
9d23a3ba8ba4
34207065ceb5
34207065ceb5
34207065ceb5
34207065ceb5
34207065ceb5
34207065ceb5
34207065ceb5
34207065ceb5
34207065ceb5
34207065ceb5
34207065ceb5
9d23a3ba8ba4
9d23a3ba8ba4
9d23a3ba8ba4
9d23a3ba8ba4
4d106deddda6
4d106deddda6
4d106deddda6
4d106deddda6
4d106deddda6
4d106deddda6
4d106deddda6
4d106deddda6
4d106deddda6
9d23a3ba8ba4
9d23a3ba8ba4
9d23a3ba8ba4
9d23a3ba8ba4
9d23a3ba8ba4
9d23a3ba8ba4
9d23a3ba8ba4
c6c322f51f94
cbf6db2a6125
cbf6db2a6125
cbf6db2a6125
9d23a3ba8ba4
9d23a3ba8ba4
9d23a3ba8ba4
9d23a3ba8ba4
cbf6db2a6125
9d23a3ba8ba4
9d23a3ba8ba4
cbf6db2a6125
cbf6db2a6125
cbf6db2a6125
9d23a3ba8ba4
9d23a3ba8ba4
9d23a3ba8ba4
9d23a3ba8ba4
9d23a3ba8ba4
9d23a3ba8ba4
9d23a3ba8ba4
9d23a3ba8ba4
9d23a3ba8ba4
9d23a3ba8ba4
9d23a3ba8ba4
9d23a3ba8ba4
9d23a3ba8ba4
527e57d66c53
9d23a3ba8ba4
9d23a3ba8ba4
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
eeed514c75a7
eeed514c75a7
eeed514c75a7
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
c6c322f51f94
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
c6c322f51f94
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
c6c322f51f94
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
eeed514c75a7
c6c322f51f94
330ecc6dd45f
330ecc6dd45f
c6c322f51f94
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
ad49c6f5676f
ad49c6f5676f
ad49c6f5676f
c6c322f51f94
c6c322f51f94
c6c322f51f94
c6c322f51f94
c6c322f51f94
c6c322f51f94
c6c322f51f94
c6c322f51f94
f75c6e8a701c
f75c6e8a701c
f75c6e8a701c
e84ea9b1029b
e84ea9b1029b
e84ea9b1029b
e84ea9b1029b
e84ea9b1029b
e84ea9b1029b
e84ea9b1029b
e84ea9b1029b
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
81bcacf6953d
981513b2a52c
981513b2a52c
351a6d97df2b
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
34207065ceb5
34207065ceb5
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
f75c6e8a701c
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
981513b2a52c
981513b2a52c
981513b2a52c
981513b2a52c
e84ea9b1029b
e84ea9b1029b
e84ea9b1029b
330ecc6dd45f
330ecc6dd45f
c6c322f51f94
f75c6e8a701c
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
330ecc6dd45f
34207065ceb5
34207065ceb5
a1d5543db0da
34207065ceb5
a1d5543db0da
8b7923f3e3f4
8b7923f3e3f4
8b7923f3e3f4
8b7923f3e3f4
8b7923f3e3f4
8b7923f3e3f4
8b7923f3e3f4
8b7923f3e3f4
8b7923f3e3f4
8b7923f3e3f4
8b7923f3e3f4
8b7923f3e3f4
8b7923f3e3f4
8b7923f3e3f4
8b7923f3e3f4
8b7923f3e3f4
8b7923f3e3f4
8b7923f3e3f4
8b7923f3e3f4
d3ccb9f195c8
d3ccb9f195c8
9c294ea31925
9c294ea31925
9c294ea31925
/**
 * 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/admininterface.h"
#include "transport/user.h"
#include "transport/transport.h"
#include "transport/storagebackend.h"
#include "transport/conversationmanager.h"
#include "transport/rostermanager.h"
#include "transport/usermanager.h"
#include "transport/networkpluginserver.h"
#include "transport/logging.h"
#include "transport/userregistration.h"
#include "storageresponder.h"
#include "transport/memoryusage.h"
#include <boost/foreach.hpp>

namespace Transport {

DEFINE_LOGGER(logger, "AdminInterface");

static std::string getArg(const std::string &body) {
	std::string ret;
	if (body.find(" ") == std::string::npos)
		return ret;

	return body.substr(body.find(" ") + 1);
}

AdminInterface::AdminInterface(Component *component, UserManager *userManager, NetworkPluginServer *server, StorageBackend *storageBackend, UserRegistration *userRegistration) {
	m_component = component;
	m_storageBackend = storageBackend;
	m_userManager = userManager;
	m_server = server;
	m_userRegistration = userRegistration;
	m_start = time(NULL);

	m_component->getStanzaChannel()->onMessageReceived.connect(bind(&AdminInterface::handleMessageReceived, this, _1));
}

AdminInterface::~AdminInterface() {
}

void AdminInterface::handleQuery(Swift::Message::ref message) {
	LOG4CXX_INFO(logger, "Message from admin received: '" << message->getBody() << "'");
	message->setTo(message->getFrom());
	message->setFrom(m_component->getJID());

	if (message->getBody() == "status") {
		int users = m_userManager->getUserCount();
		int backends = m_server->getBackendCount();
		message->setBody("Running (" + boost::lexical_cast<std::string>(users) + " users connected using " + boost::lexical_cast<std::string>(backends) + " backends)");
	}
	else if (message->getBody() == "uptime") {
		message->setBody(boost::lexical_cast<std::string>(time(0) - m_start));
	}
	else if (message->getBody() == "online_users") {
		std::string lst;
		const std::map<std::string, User *> &users = m_userManager->getUsers();
		if (users.size() == 0)
			lst = "0";

		for (std::map<std::string, User *>::const_iterator it = users.begin(); it != users.end(); it ++) {
			lst += (*it).first + "\n";
		}

		message->setBody(lst);
	}
	else if (message->getBody() == "online_users_count") {
		int users = m_userManager->getUserCount();
		message->setBody(boost::lexical_cast<std::string>(users));
	}
	else if (message->getBody() == "reload") {
		bool done = m_component->getConfig()->reload();
		if (done) {
			message->setBody("Config reloaded");
		}
		else {
			message->setBody("Error during config reload");
		}
	}
	else if (message->getBody() == "online_users_per_backend") {
		std::string lst;
		int id = 1;

		const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
		for (std::list <NetworkPluginServer::Backend *>::const_iterator b = backends.begin(); b != backends.end(); b++) {
			NetworkPluginServer::Backend *backend = *b;
			lst += "Backend " + boost::lexical_cast<std::string>(id) + " (ID=" + backend->id + ")";
			lst += backend->acceptUsers ? "" : " - not-accepting";
			lst += backend->longRun ? " - long-running" : "";
			lst += ":\n";
			if (backend->users.size() == 0) {
				lst += "   waiting for users\n";
			}
			else {
				time_t now = time(NULL);
				for (std::list<User *>::const_iterator u = backend->users.begin(); u != backend->users.end(); u++) {
					User *user = *u;
					lst += "   " + user->getJID().toBare().toString();
					lst += " - non-active for " + boost::lexical_cast<std::string>(now - user->getLastActivity()) + " seconds";
					lst += "\n";
				}
			}
			id++;
		}

		message->setBody(lst);
	}
	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;
		process_mem_usage(shared, rss);
		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;
		process_mem_usage(shared, rss);
		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;
		process_mem_usage(shared, rss);
		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));
		}
		else {
			unsigned long per_user = 0;
			const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
			BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
				if (backend->res >= backend->init_res) {
					per_user += (backend->res - backend->init_res);
				}
			}

			message->setBody(boost::lexical_cast<std::string>(per_user / m_userManager->getUserCount()));
		}
	}
	else if (message->getBody() == "res_memory_per_backend") {
		std::string lst;
		int id = 1;
		const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
		BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
			lst += "Backend " + boost::lexical_cast<std::string>(id) + " (ID=" + backend->id + "): " + boost::lexical_cast<std::string>(backend->res) + "\n";
			id++;
		}

		message->setBody(lst);
	}
	else if (message->getBody() == "shr_memory_per_backend") {
		std::string lst;
		int id = 1;
		const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
		BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
			lst += "Backend " + boost::lexical_cast<std::string>(id)  + " (ID=" + backend->id + "): " + boost::lexical_cast<std::string>(backend->shared) + "\n";
			id++;
		}

		message->setBody(lst);
	}
	else if (message->getBody() == "used_memory_per_backend") {
		std::string lst;
		int id = 1;
		const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
		BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
			lst += "Backend " + boost::lexical_cast<std::string>(id)  + " (ID=" + backend->id + "): " + boost::lexical_cast<std::string>(backend->res - backend->shared) + "\n";
			id++;
		}

		message->setBody(lst);
	}
	else if (message->getBody() == "average_memory_per_user_per_backend") {
		std::string lst;
		int id = 1;
		const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
		BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
			if (backend->users.size() == 0 || backend->res < backend->init_res) {
				lst += "Backend " + boost::lexical_cast<std::string>(id)  + " (ID=" + backend->id + "): 0\n";
			}
			else {
				lst += "Backend " + boost::lexical_cast<std::string>(id) + " (ID=" + backend->id + "): " + boost::lexical_cast<std::string>((backend->res - backend->init_res) / backend->users.size()) + "\n";
			}
			id++;
		}

		message->setBody(lst);
	}
	else if (message->getBody() == "collect_backend") {
		m_server->collectBackend();
	}
	else if (message->getBody() == "crashed_backends") {
		std::string lst;
		const std::vector<std::string> &backends = m_server->getCrashedBackends();
		BOOST_FOREACH(const std::string &backend, backends) {
			lst += backend + "\n";
		}
		message->setBody(lst);
	}
	else if (message->getBody() == "crashed_backends_count") {
		message->setBody(boost::lexical_cast<std::string>(m_server->getCrashedBackends().size()));
	}
	else if (message->getBody() == "messages_from_xmpp") {
		int msgCount = m_userManager->getMessagesToBackend();
		message->setBody(boost::lexical_cast<std::string>(msgCount));
	}
	else if (message->getBody() == "messages_to_xmpp") {
		int msgCount = m_userManager->getMessagesToXMPP();
		message->setBody(boost::lexical_cast<std::string>(msgCount));
	}
	else if (message->getBody().find("register ") == 0 && m_userRegistration) {
		std::string body = message->getBody();
		std::vector<std::string> args;
		boost::split(args, body, boost::is_any_of(" "));
		if (args.size() == 4) {
			UserInfo res;
			res.jid = args[1];
			res.uin = args[2];
			res.password = args[3];
			res.language = "en";
			res.encoding = "utf-8";
			res.vip = 0;

			if (m_userRegistration->registerUser(res)) {
				message->setBody("User registered.");
			}
			else {
				message->setBody("Registration failed: User is already registered");
			}
		}
		else {
			message->setBody("Bad argument count. See 'help'.");
		}
	}
	else if (message->getBody().find("unregister ") == 0 && m_userRegistration) {
		std::string body = message->getBody();
		std::vector<std::string> args;
		boost::split(args, body, boost::is_any_of(" "));
		if (args.size() == 2) {
			if (m_userRegistration->unregisterUser(args[1])) {
				message->setBody("User '" + args[1] + "' unregistered.");
			}
			else {
				message->setBody("Unregistration failed: User '" + args[1] + "' is not registered");
			}
		}
		else {
			message->setBody("Bad argument count. See 'help'.");
		}
	}
	else if (message->getBody().find("help") == 0) {
		std::string help;
		help += "General:\n";
		help += "    status - shows instance status\n";
		help += "    reload - Reloads config file\n";
		help += "    uptime - returns ptime in seconds\n";
		help += "Users:\n";
		help += "    online_users - returns list of all online users\n";
		help += "    online_users_count - number of online users\n";
		help += "    online_users_per_backend - shows online users per backends\n";
		help += "    has_online_user <bare_JID> - returns 1 if user is online\n";
		if (m_userRegistration) {
			help += "    register <bare_JID> <legacyName> <password> - registers the new user\n";
			help += "    unregister <bare_JID> - unregisters existing user\n";
		}
		help += "Messages:\n";
		help += "    messages_from_xmpp - get number of messages received from XMPP users\n";
		help += "    messages_to_xmpp - get number of messages sent to XMPP users\n";
		help += "Backends:\n";
		help += "    backends_count - number of active backends\n";
		help += "    crashed_backends - returns IDs of crashed backends\n";
		help += "    crashed_backends_count - returns number of crashed backends\n";
		help += "Memory:\n";
		help += "    res_memory - Total RESident memory spectrum2 and its backends use in KB\n";
		help += "    shr_memory - Total SHaRed memory spectrum2 backends share together in KB\n";
		help += "    used_memory - (res_memory - shr_memory)\n";
		help += "    average_memory_per_user - (memory_used_without_any_user - res_memory)\n";
		help += "    res_memory_per_backend - RESident memory used by backends in KB\n";
		help += "    shr_memory_per_backend - SHaRed memory used by backends in KB\n";
		help += "    used_memory_per_backend - (res_memory - shr_memory) per backend\n";
		help += "    average_memory_per_user_per_backend - (memory_used_without_any_user - res_memory) per backend\n";
		
		
		message->setBody(help);
	}
	else {
		message->setBody("Unknown command. Try \"help\"");
	}
}

void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
	if (!message->getTo().getNode().empty())
		return;

	std::vector<std::string> const &x = CONFIG_VECTOR(m_component->getConfig(),"service.admin_jid");
	if (std::find(x.begin(), x.end(), message->getFrom().toBare().toString()) == x.end()) {
	    LOG4CXX_WARN(logger, "Message not from admin user, but from " << message->getFrom().toBare().toString());
	    return;
	
	}
	
	// Ignore empty messages
	if (message->getBody().empty()) {
		return;
	}

	handleQuery(message);

	m_component->getStanzaChannel()->sendMessage(message);
}

}