Changeset - 6b45e0e418ee
backends/frotz/main.cpp
Show inline comments
 
@@ -63,193 +63,193 @@ static const char *howtoplay = "To move around, just type the direction you want
 
"\n"
 
"You can use multiple objects with certain verbs if you separate them by\n"
 
"the word \"AND\" or by a comma.  Here are some examples:\n"
 
"\n"
 
"> TAKE THE BOOK AND THE FROG\n"
 
"> DROP THE JAR OF PEANUT BUTTER, THE SPOON, AND THE LEMMING FOOD\n"
 
"> PUT THE EGG AND THE PENCIL IN THE CABINET\n"
 
"\n"
 
"You can include several inputs on one line if you separate them by the\n"
 
"word \"THEN\" or by a period.  Each input will be handled in order, as\n"
 
"though you had typed them individually at seperate prompts.  For example,\n"
 
"you could type all of the following at once, before pressing the ENTER (or\n"
 
"RETURN) key:\n"
 
"\n"
 
"> TURN ON THE LIGHT. TAKE THE BOOK THEN READ ABOUT THE JESTER IN THE BOOK\n"
 
"\n"
 
"If the story doesn't understand one of the sentences on your input line,\n"
 
"or if an unusual event occurs, it will ignore the rest of your input line.\n"
 
"\n"
 
"The words \"IT\" and \"ALL\" can be very useful.  For example:\n"
 
"\n"
 
"> EXAMINE THE APPLE.  TAKE IT.  EAT IT\n"
 
"> CLOSE THE HEAVY METAL DOOR.  LOCK IT\n"
 
"> PICK UP THE GREEN BOOT.  SMELL IT.  PUT IT ON.\n"
 
"> TAKE ALL\n"
 
"> TAKE ALL THE TOOLS\n"
 
"> DROP ALL THE TOOLS EXCEPT THE WRENCH AND MINIATURE HAMMER\n"
 
"> TAKE ALL FROM THE CARTON\n"
 
"> GIVE ALL BUT THE RUBY SLIPPERS TO THE WICKED WITCH\n"
 
"\n"
 
"The word \"ALL\" refers to every visible object except those inside\n"
 
"something else.  If there were an apple on the ground and an orange inside\n"
 
"a cabinet, \"TAKE ALL\" would take the apple but not the orange.\n"
 
"\n"
 
"There are three kinds of questions you can ask:  \"WHERE IS (something)\",\n"
 
"\"WHAT IS (something)\", and \"WHO IS (someone)\".  For example:\n"
 
"\n"
 
"> WHO IS LORD DIMWIT?\n"
 
"> WHAT IS A GRUE?\n"
 
"> WHERE IS EVERYBODY?\n"
 
"\n"
 
"When you meet intelligent creatures, you can talk to them by typing their\n"
 
"name, then a comma, then whatever you want to say to them.  Here are some\n"
 
"examples:\n"
 
"\n"
 
"> JESTER, HELLO\n"
 
"> GUSTAR WOOMAX, TELL ME ABOUT THE COCONUT\n"
 
"> UNCLE OTTO, GIVE ME YOUR WALLET\n"
 
"> HORSE, WHERE IS YOUR SADDLE?\n"
 
"> BOY, RUN HOME THEN CALL THE POLICE\n"
 
"> MIGHTY WIZARD, TAKE THIS POISONED APPLE.  EAT IT\n"
 
"\n"
 
"Notice that in the last two examples, you are giving the characters more\n"
 
"than one command on the same input line.  Keep in mind, however, that many\n"
 
"creatures don't care for idle chatter; your actions will speak louder than\n"
 
"your words.  \n";
 

	
 

	
 
static void start_dfrotz(dfrotz &p, const std::string &game) {
 
// 	p.writepipe[0] = -1;
 

	
 
	if (pipe(p.readpipe) < 0 || pipe(p.writepipe) < 0) {
 
	}
 

	
 
	std::cout << "dfrotz -p " << game << "\n";
 

	
 
	if ((p.pid = fork()) < 0) {
 
		/* FATAL: cannot fork child */
 
	}
 
	else if (p.pid == 0) {
 
		close(PARENT_WRITE);
 
		close(PARENT_READ);
 

	
 
		dup2(CHILD_READ,  0);  close(CHILD_READ);
 
		dup2(CHILD_WRITE, 1);  close(CHILD_WRITE);
 

	
 
		execlp("dfrotz", "-p", game.c_str(), NULL);
 

	
 
	}
 
	else {
 
		close(CHILD_READ);
 
		close(CHILD_WRITE);
 
	}
 
}
 

	
 
class FrotzNetworkPlugin : public NetworkPlugin {
 
	public:
 
		Swift::BoostNetworkFactories *m_factories;
 
		Swift::BoostIOServiceThread m_boostIOServiceThread;
 
		SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Connection> m_conn;
 

	
 
		FrotzNetworkPlugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() {
 
			this->config = config;
 
			m_factories = new Swift::BoostNetworkFactories(loop);
 
			m_conn = m_factories->getConnectionFactory()->createConnection();
 
			m_conn->onDataRead.connect(boost::bind(&FrotzNetworkPlugin::_handleDataRead, this, _1));
 
			m_conn->connect(Swift::HostAddressPort(Swift::HostAddress(host), port));
 
			m_conn->connect(Swift::HostAddressPort(SWIFT_HOSTADDRESS(host), port));
 
// 			m_conn->onConnectFinished.connect(boost::bind(&FrotzNetworkPlugin::_handleConnected, this, _1));
 
// 			m_conn->onDisconnected.connect(boost::bind(&FrotzNetworkPlugin::handleDisconnected, this));
 
		}
 

	
 
		void sendData(const std::string &string) {
 
			m_conn->write(Swift::createSafeByteArray(string));
 
		}
 

	
 
		void _handleDataRead(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::SafeByteArray> data) {
 
			std::string d(data->begin(), data->end());
 
			handleDataRead(d);
 
		}
 

	
 
		void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
 
			np->handleConnected(user);
 
			std::vector<std::string> groups;
 
			groups.push_back("ZCode");
 
			np->handleBuddyChanged(user, "zcode", "ZCode", groups, pbnetwork::STATUS_ONLINE);
 
// 			sleep(1);
 
// 			np->handleMessage(np->m_user, "zork", first_msg);
 
		}
 

	
 
		void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
 
			if (games.find(user) != games.end()) {
 
				kill(games[user].pid, SIGTERM);
 
				games.erase(user);
 
			}
 
// 			exit(0);
 
		}
 

	
 
		void readMessage(const std::string &user) {
 
			static char buf[15000];
 
			buf[0] = 0;
 
			int repeated = 0;
 
			while (strlen(buf) == 0) {
 
				ssize_t len = read(games[user].readpipe[0], buf, 15000);
 
				if (len > 0) {
 
					buf[len] = 0;
 
				}
 
				usleep(1000);
 
				repeated++;
 
				if (repeated > 30)
 
					return;
 
			}
 
			np->handleMessage(user, "zcode", buf);
 

	
 
			std::string msg = "save\n";
 
			write(games[user].writepipe[1], msg.c_str(), msg.size());
 

	
 
			msg = user + "_" + games[user].game + ".save\n";
 
			write(games[user].writepipe[1], msg.c_str(), msg.size());
 
			ignoreMessage(user);
 
		}
 

	
 
		void ignoreMessage(const std::string &user) {
 
			usleep(1000000);
 
			static char buf[15000];
 
			buf[0] = 0;
 
			int repeated = 0;
 
			while (strlen(buf) == 0) {
 
				ssize_t len = read(games[user].readpipe[0], buf, 15000);
 
				if (len > 0) {
 
					buf[len] = 0;
 
				}
 
				usleep(1000);
 
				repeated++;
 
				if (repeated > 30)
 
					return;
 
			}
 

	
 
			std::cout << "ignoring: " << buf << "\n";
 
		}
 

	
 
		std::vector<std::string> getGames() {
 
			std::vector<std::string> games;
 
			path p(".");
 
			directory_iterator end_itr;
 
			for (directory_iterator itr(p); itr != end_itr; ++itr) {
 
				if (extension(itr->path()) == ".z5") {
 
#if BOOST_FILESYSTEM_VERSION == 3
 
					games.push_back(itr->path().filename().string());
 
#else
 
					games.push_back(itr->path().leaf());
 
#endif
 
				}
 
			}
 
			return games;
 
		}
 

	
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "", const std::string &id = "") {
 
			std::cout << "aaa\n";
 
			if (message.find("start") == 0) {
 
				std::string game = message.substr(6);
 
				std::vector<std::string> lst = getGames();
 
				if (std::find(lst.begin(), lst.end(), game) == lst.end()) {
 
					np->handleMessage(user, "zcode", "Unknown game");
backends/smstools3/main.cpp
Show inline comments
 
/*
 
 * Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com
 
 *
 
 * This example is free, and not covered by LGPL license. There is no
 
 * restriction applied to their modification, redistribution, using and so on.
 
 * You can study them, modify them, use them in your own program - either
 
 * completely or partially. By using it you may give me some credits in your
 
 * program, but you don't have to.
 
 */
 

	
 
#include "transport/Config.h"
 
#include "transport/Logging.h"
 
#include "transport/NetworkPlugin.h"
 
#include "transport/SQLite3Backend.h"
 
#include "transport/MySQLBackend.h"
 
#include "transport/PQXXBackend.h"
 
#include "transport/StorageBackend.h"
 
#include "Swiften/Swiften.h"
 
#include "Swiften/SwiftenCompat.h"
 
#include <boost/filesystem.hpp>
 
#include "unistd.h"
 
#include "signal.h"
 
#include "sys/wait.h"
 
#include "sys/signal.h"
 
#include <fstream>
 
#include <streambuf>
 

	
 
Swift::SimpleEventLoop *loop_;
 

	
 
#include <boost/filesystem.hpp>
 
#include <boost/algorithm/string.hpp>
 

	
 
using namespace boost::filesystem;
 

	
 
using namespace boost::program_options;
 
using namespace Transport;
 

	
 
DEFINE_LOGGER(logger, "SMSNetworkPlugin");
 

	
 
#define INTERNAL_USER "/sms@backend@internal@user"
 

	
 
class SMSNetworkPlugin;
 
SMSNetworkPlugin * np = NULL;
 

	
 
class SMSNetworkPlugin : public NetworkPlugin {
 
	public:
 
		Swift::BoostNetworkFactories *m_factories;
 
		Swift::BoostIOServiceThread m_boostIOServiceThread;
 
		SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Connection> m_conn;
 
		Swift::Timer::ref m_timer;
 
		int m_internalUser;
 
		StorageBackend *storageBackend;
 

	
 
		SMSNetworkPlugin(Config *config, Swift::SimpleEventLoop *loop, StorageBackend *storagebackend, const std::string &host, int port) : NetworkPlugin() {
 
			this->config = config;
 
			this->storageBackend = storagebackend;
 
			m_factories = new Swift::BoostNetworkFactories(loop);
 
			m_conn = m_factories->getConnectionFactory()->createConnection();
 
			m_conn->onDataRead.connect(boost::bind(&SMSNetworkPlugin::_handleDataRead, this, _1));
 
			m_conn->connect(Swift::HostAddressPort(Swift::HostAddress(host), port));
 
			m_conn->connect(Swift::HostAddressPort(SWIFT_HOSTADDRESS(host), port));
 
// 			m_conn->onConnectFinished.connect(boost::bind(&FrotzNetworkPlugin::_handleConnected, this, _1));
 
// 			m_conn->onDisconnected.connect(boost::bind(&FrotzNetworkPlugin::handleDisconnected, this));
 

	
 
			LOG4CXX_INFO(logger, "Starting the plugin.");
 

	
 
			m_timer = m_factories->getTimerFactory()->createTimer(5000);
 
			m_timer->onTick.connect(boost::bind(&SMSNetworkPlugin::handleSMSDir, this));
 
			m_timer->start();
 

	
 
			// We're reusing our database model here. Buddies of user with JID INTERNAL_USER are there
 
			// to match received GSM messages from number N with the XMPP users who sent message to number N.
 
			// BuddyName = GSM number
 
			// Alias = XMPP user JID to which the messages from this number is sent to.
 
			// TODO: This should be per Modem!!!
 
			UserInfo info;
 
			info.jid = INTERNAL_USER;
 
			info.password = "";
 
			storageBackend->setUser(info);
 
			storageBackend->getUser(INTERNAL_USER, info);
 
			m_internalUser = info.id;
 
		}
 

	
 

	
 
		void handleSMS(const std::string &sms) {
 
			LOG4CXX_INFO(logger, "Handling SMS " << sms << ".")
 
			std::ifstream t(sms.c_str());
 
			std::string str;
 

	
 
			t.seekg(0, std::ios::end);
 
			str.reserve(t.tellg());
 
			t.seekg(0, std::ios::beg);
 

	
 
			str.assign((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
 

	
 
			std::string from = "";
 
			std::string msg = "";
 
			while(str.find("\n") != std::string::npos) {
 
				std::string line = str.substr(0, str.find("\n"));
 
				if (line.find("From: ") == 0) {
 
					from = line.substr(strlen("From: "));
 
				}
 
				else if (line.empty()) {
 
					msg = str.substr(1);
 
					break;
 
				}
 
				str = str.substr(str.find("\n") + 1);
 
			}
 

	
 
			std::list<BuddyInfo> roster;
 
			storageBackend->getBuddies(m_internalUser, roster);
 

	
 
			std::string to;
 
			BOOST_FOREACH(BuddyInfo &b, roster) {
 
				if (b.legacyName == from) {
 
					to = b.alias;
 
				}
 
			}
 

	
 
			if (to.empty()) {
 
				LOG4CXX_WARN(logger, "Received SMS from " << from << ", but this number is not associated with any XMPP user.");
 
			}
 

	
 
			LOG4CXX_INFO(logger, "Forwarding SMS from " << from << " to " << to << ".");
 
			handleMessage(to, from, msg);
 
		}
 

	
 
		void handleSMSDir() {
 
			std::string dir = "/var/spool/sms/incoming/";
 
			if (CONFIG_HAS_KEY(config, "backend.incoming_dir")) {
 
				dir = CONFIG_STRING(config, "backend.incoming_dir");
 
			}
 
			LOG4CXX_INFO(logger, "Checking directory " << dir << " for incoming SMS.");
 

	
 
			path p(dir);
 
			directory_iterator end_itr;
 
			for (directory_iterator itr(p); itr != end_itr; ++itr) {
 

	
 
				try {
 
					if (is_regular(itr->path())) {
 
						handleSMS(itr->path().string());
 
						remove(itr->path());
 
					}
 
				}
 
				catch (const filesystem_error& ex) {
 
					LOG4CXX_ERROR(logger, "Error when removing the SMS: " << ex.what() << ".");
 
				}
 
			}
 
			m_timer->start();
 
		}
 

	
 
		void sendSMS(const std::string &to, const std::string &msg) {
 
			// TODO: Probably 
 
			std::string data = "To: " + to + "\n";
 
			data += "\n";
 
			data += msg;
 

	
backends/swiften/main.cpp
Show inline comments
 
// Transport includes
 
#include "transport/Config.h"
 
#include "transport/NetworkPlugin.h"
 
#include "transport/Logging.h"
 

	
 
#include "boost/date_time/posix_time/posix_time.hpp"
 

	
 
// Swiften
 
#include "Swiften/Swiften.h"
 
#include "Swiften/SwiftenCompat.h"
 
#include <Swiften/Version.h>
 
#define HAVE_SWIFTEN_3  (SWIFTEN_VERSION >= 0x030000)
 

	
 
#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");
 
DEFINE_LOGGER(logger_xml, "backend.xml");
 

	
 
// eventloop
 
Swift::SimpleEventLoop *loop_;
 

	
 
// Plugins
 
class SwiftenPlugin;
 
NetworkPlugin *np = NULL;
 
Swift::XMPPSerializer *serializer;
 

	
 
class ForwardIQHandler : public Swift::IQHandler {
 
	public:
 
		std::map <std::string, std::string> m_id2resource;
 

	
 
		ForwardIQHandler(NetworkPlugin *np, const std::string &user) {
 
			m_np = np;
 
			m_user = user;
 
		}
 

	
 
		bool handleIQ(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::IQ> iq) {
 
			if (iq->getPayload<Swift::RosterPayload>() != NULL) {
 
				return false;
 
			}
 
			if (iq->getType() == Swift::IQ::Get) {
 
				m_id2resource[iq->getID()] = iq->getFrom().getResource();
 
			}
 

	
 
			iq->setTo(m_user);
 
			std::string xml = safeByteArrayToString(serializer->serializeElement(iq));
 
			m_np->sendRawXML(xml);
 
			return true;
 
		}
 

	
 
	private:
 
		NetworkPlugin *m_np;
 
		std::string m_user;
 
		
 
};
 

	
 
class SwiftenPlugin : public NetworkPlugin, Swift::XMPPParserClient {
 
	public:
 
		Swift::BoostNetworkFactories *m_factories;
 
		Swift::BoostIOServiceThread m_boostIOServiceThread;
 
		SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Connection> m_conn;
 
		bool m_firstPing;
 
		
 
		Swift::FullPayloadSerializerCollection collection;
 
		Swift::XMPPParser *m_xmppParser;
 
		Swift::FullPayloadParserFactoryCollection m_collection2;
 

	
 
		SwiftenPlugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() {
 
			this->config = config;
 
			m_firstPing = true;
 
			m_factories = new Swift::BoostNetworkFactories(loop);
 
			m_conn = m_factories->getConnectionFactory()->createConnection();
 
			m_conn->onDataRead.connect(boost::bind(&SwiftenPlugin::_handleDataRead, this, _1));
 
			m_conn->connect(Swift::HostAddressPort(Swift::HostAddress(host), port));
 
			m_conn->connect(Swift::HostAddressPort(SWIFT_HOSTADDRESS(host), port));
 
#if HAVE_SWIFTEN_3
 
			serializer = new Swift::XMPPSerializer(&collection, Swift::ClientStreamType, false);
 
#else
 
			serializer = new Swift::XMPPSerializer(&collection, Swift::ClientStreamType);
 
#endif
 
			m_xmppParser = new Swift::XMPPParser(this, &m_collection2, m_factories->getXMLParserFactory());
 
			m_xmppParser->parse("<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='localhost' version='1.0'>");
 

	
 
			LOG4CXX_INFO(logger, "Starting the plugin.");
 
		}
 

	
 
		// NetworkPlugin uses this method to send the data to networkplugin server
 
		void sendData(const std::string &string) {
 
			m_conn->write(Swift::createSafeByteArray(string));
 
		}
 

	
 
		// This method has to call handleDataRead with all received data from network plugin server
 
		void _handleDataRead(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::SafeByteArray> data) {
 
			if (m_firstPing) {
 
				m_firstPing = false;
 
				NetworkPlugin::PluginConfig cfg;
 
				cfg.setRawXML(true);
 
				cfg.setNeedRegistration(false);
 
				sendConfig(cfg);
 
			}
 
			std::string d(data->begin(), data->end());
 
			handleDataRead(d);
 
		}
 

	
 
		void handleStreamStart(const Swift::ProtocolHeader&) {}
 
#if HAVE_SWIFTEN_3
 
		void handleElement(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::ToplevelElement> element) {
 
#else
 
		void handleElement(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Element> element) {
 
#endif
 
			SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Stanza> stanza = SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast<Swift::Stanza>(element);
 
			if (!stanza) {
 
				return;
 
			}
 

	
 
			std::string user = stanza->getFrom().toBare();
 

	
 
			SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Client> client = m_users[user];
 
			if (!client)
 
				return;
 

	
 
			stanza->setFrom(client->getJID());
 

	
 
			SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> message = SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast<Swift::Message>(stanza);
 
			if (message) {
 
				client->sendMessage(message);
 
				return;
 
			}
 

	
 
			SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Presence> presence = SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast<Swift::Presence>(stanza);
 
			if (presence) {
 
				client->sendPresence(presence);
 
				return;
 
			}
 

	
 
			SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::IQ> iq = SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast<Swift::IQ>(stanza);
 
			if (iq) {
 
				if (m_handlers[user]->m_id2resource.find(stanza->getID()) != m_handlers[user]->m_id2resource.end()) {
 
					std::string resource = m_handlers[user]->m_id2resource[stanza->getID()];
 
					if (resource.empty()) {
 
						iq->setTo(Swift::JID(iq->getTo().getNode(), iq->getTo().getDomain()));					
 
					} else {
 
						iq->setTo(Swift::JID(iq->getTo().getNode(), iq->getTo().getDomain(), resource));					
 
					}
 
					
 
					m_handlers[user]->m_id2resource.erase(stanza->getID());
 
				}
 
				client->getIQRouter()->sendIQ(iq);
 
				return;
 
			}
 
		}
 

	
 
		void handleStreamEnd() {}
 

	
 
		void handleRawXML(const std::string &xml) {
 
			m_xmppParser->parse(xml);
 
		}
 

	
 
		void handleSwiftDisconnected(const std::string &user, const boost::optional<Swift::ClientError> &error) {
 
			std::string message = "";
 
			bool reconnect = false;
 
			if (error) {
 
				switch(error->getType()) {
 
					case Swift::ClientError::UnknownError: message = ("Unknown Error"); reconnect = true; break;
 
					case Swift::ClientError::DomainNameResolveError: message = ("Unable to find server"); break;
 
					case Swift::ClientError::ConnectionError: message = ("Error connecting to server"); break;
 
					case Swift::ClientError::ConnectionReadError: message = ("Error while receiving server data"); reconnect = true; break;
 
					case Swift::ClientError::ConnectionWriteError: message = ("Error while sending data to the server"); reconnect = true; break;
 
					case Swift::ClientError::XMLError: message = ("Error parsing server data"); reconnect = true; break;
 
					case Swift::ClientError::AuthenticationFailedError: message = ("Login/password invalid"); break;
 
					case Swift::ClientError::CompressionFailedError: message = ("Error while compressing stream"); break;
backends/template/plugin.cpp
Show inline comments
 
#include "plugin.h"
 
// Transport includes
 
#include "transport/Config.h"
 
#include "transport/NetworkPlugin.h"
 
#include "transport/Logging.h"
 

	
 
// Swiften
 
#include "Swiften/Swiften.h"
 

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

	
 
DEFINE_LOGGER(logger, "Backend Template");
 

	
 
Plugin::Plugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() {
 
	this->config = config;
 
	m_factories = new Swift::BoostNetworkFactories(loop);
 
	m_conn = m_factories->getConnectionFactory()->createConnection();
 
	m_conn->onDataRead.connect(boost::bind(&Plugin::_handleDataRead, this, _1));
 
	m_conn->connect(Swift::HostAddressPort(Swift::HostAddress(host), port));
 
	m_conn->connect(Swift::HostAddressPort(SWIFT_HOSTADDRESS(host), port));
 

	
 
	LOG4CXX_INFO(logger, "Starting the plugin.");
 
}
 

	
 
// NetworkPlugin uses this method to send the data to networkplugin server
 
void Plugin::sendData(const std::string &string) {
 
	m_conn->write(Swift::createSafeByteArray(string));
 
}
 

	
 
// This method has to call handleDataRead with all received data from network plugin server
 
void Plugin::_handleDataRead(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::SafeByteArray> data) {
 
	std::string d(data->begin(), data->end());
 
	handleDataRead(d);
 
}
 

	
 
void Plugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
 
	handleConnected(user);
 
	LOG4CXX_INFO(logger, user << ": Added buddy - Echo.");
 
	handleBuddyChanged(user, "echo", "Echo", std::vector<std::string>(), pbnetwork::STATUS_ONLINE);
 
}
 

	
 
void Plugin::handleLogoutRequest(const std::string &user, const std::string &legacyName) {
 
}
 

	
 
void Plugin::handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml, const std::string &id) {
 
	LOG4CXX_INFO(logger, "Sending message from " << user << " to " << legacyName << ".");
 
	if (legacyName == "echo") {
 
		handleMessage(user, legacyName, message);
 
	}
 
}
 

	
 
void Plugin::handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
 
	LOG4CXX_INFO(logger, user << ": Added buddy " << buddyName << ".");
 
	handleBuddyChanged(user, buddyName, alias, groups, pbnetwork::STATUS_ONLINE);
 
}
 

	
 
void Plugin::handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
 

	
 
}
backends/twitter/TwitterPlugin.cpp
Show inline comments
 
#include "TwitterPlugin.h"
 
#include "Requests/StatusUpdateRequest.h"
 
#include "Requests/DirectMessageRequest.h"
 
#include "Requests/TimelineRequest.h"
 
#include "Requests/FetchFriends.h"
 
#include "Requests/HelpMessageRequest.h"
 
#include "Requests/PINExchangeProcess.h"
 
#include "Requests/OAuthFlow.h"
 
#include "Requests/CreateFriendRequest.h"
 
#include "Requests/DestroyFriendRequest.h"
 
#include "Requests/RetweetRequest.h"
 
#include "Requests/ProfileImageRequest.h"
 
#include "Swiften/StringCodecs/Hexify.h"
 

	
 
DEFINE_LOGGER(logger, "Twitter Backend");
 

	
 
TwitterPlugin *np = NULL;
 
Swift::SimpleEventLoop *loop_; // Event Loop
 

	
 
const std::string OLD_APP_KEY = "PCWAdQpyyR12ezp2fVwEhw";
 
const std::string OLD_APP_SECRET = "EveLmCXJIg2R7BTCpm6OWV8YyX49nI0pxnYXh7JMvDg";
 

	
 
#define abs(x) ((x)<0?-(x):(x))
 
#define SHA(x) (Swift::Hexify::hexify(Swift::SHA1::getHash(Swift::createByteArray((x)))))
 

	
 
//Compares two +ve intergers 'a' and 'b' represented as strings 
 
static int cmp(std::string a, std::string b)
 
{
 
	int diff = abs((int)a.size() - (int)b.size());
 
	if(a.size() < b.size()) a = std::string(diff,'0') + a;
 
	else b = std::string(diff,'0') + b;
 
	
 
	if(a == b) return 0;
 
	if(a < b) return -1;
 
	return 1;
 
}
 

	
 

	
 
TwitterPlugin::TwitterPlugin(Config *config, Swift::SimpleEventLoop *loop, StorageBackend *storagebackend, const std::string &host, int port) : NetworkPlugin() 
 
{
 
	this->config = config;
 
	this->storagebackend = storagebackend;
 
	this->m_firstPing = true;
 

	
 
	if (CONFIG_HAS_KEY(config, "twitter.consumer_key") == false) {
 
		consumerKey = "5mFePMiJi0KpeURONkelg";
 
	}
 
	else {
 
		consumerKey = CONFIG_STRING(config, "twitter.consumer_key");
 
	}
 
	if (CONFIG_HAS_KEY(config, "twitter.consumer_secret") == false) {
 
		consumerSecret = "YFZCDJwRhbkccXEnaYr1waCQejTJcOY8F7l5Wim3FA";
 
	}
 
	else {
 
		consumerSecret = CONFIG_STRING(config, "twitter.consumer_secret");
 
	}
 

	
 
	if (consumerSecret.empty() || consumerKey.empty()) {
 
		LOG4CXX_ERROR(logger, "Consumer key and Consumer secret can't be empty.");
 
		exit(1);
 
	}
 

	
 
	adminLegacyName = "twitter.com"; 
 
	adminChatRoom = "#twitter"; 
 
	adminNickName = "twitter"; 
 
	adminAlias = "twitter";
 

	
 
	OAUTH_KEY = "twitter_oauth_token";
 
	OAUTH_SECRET = "twitter_oauth_secret";
 
	MODE = "mode";
 

	
 
	m_factories = new Swift::BoostNetworkFactories(loop);
 
	m_conn = m_factories->getConnectionFactory()->createConnection();
 
	m_conn->onDataRead.connect(boost::bind(&TwitterPlugin::_handleDataRead, this, _1));
 
	m_conn->connect(Swift::HostAddressPort(Swift::HostAddress(host), port));
 
	m_conn->connect(Swift::HostAddressPort(SWIFT_HOSTADDRESS(host), port));
 

	
 
	tp = new ThreadPool(loop_, 10);
 

	
 
	LOG4CXX_INFO(logger, "Fetch timeout is set to " << CONFIG_INT_DEFAULTED(config, "twitter.fetch_timeout", 90000));
 
	tweet_timer = m_factories->getTimerFactory()->createTimer(CONFIG_INT_DEFAULTED(config, "twitter.fetch_timeout", 90000));
 
	message_timer = m_factories->getTimerFactory()->createTimer(CONFIG_INT_DEFAULTED(config, "twitter.fetch_timeout", 90000));
 

	
 
	tweet_timer->onTick.connect(boost::bind(&TwitterPlugin::pollForTweets, this));
 
	message_timer->onTick.connect(boost::bind(&TwitterPlugin::pollForDirectMessages, this));
 

	
 
	tweet_timer->start();
 
	message_timer->start();
 

	
 
#if HAVE_SWIFTEN_3
 
		cryptoProvider = SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::CryptoProvider>(Swift::PlatformCryptoProvider::create());
 
#endif
 
	
 
	
 
	LOG4CXX_INFO(logger, "Starting the plugin.");
 
}
 

	
 
TwitterPlugin::~TwitterPlugin() 
 
{
 
	delete storagebackend;
 
	std::set<std::string>::iterator it;
 
	for(it = onlineUsers.begin() ; it != onlineUsers.end() ; it++) delete userdb[*it].sessions;
 
	delete tp;
 
}
 

	
 
// Send data to NetworkPlugin server
 
void TwitterPlugin::sendData(const std::string &string) 
 
{
 
	m_conn->write(Swift::createSafeByteArray(string));
 
}
 

	
 
// Receive date from the NetworkPlugin server and invoke the appropirate payload handler (implement in the NetworkPlugin class)
 
void TwitterPlugin::_handleDataRead(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::SafeByteArray> data)
 
{
 
	if (m_firstPing) {
 
		m_firstPing = false;
 
		// Users can join the network without registering if we allow
 
		// one user to connect multiple IRC networks.
 
		NetworkPlugin::PluginConfig cfg;
 
		cfg.setNeedPassword(false);
 
		sendConfig(cfg);
 
	}
 

	
 
	std::string d(data->begin(), data->end());
 
	handleDataRead(d);
 
}
 

	
 
// User trying to login into his twitter account
 
void TwitterPlugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) 
 
{
 
	if(userdb.count(user) && (userdb[user].connectionState == NEW || 
 
										userdb[user].connectionState == CONNECTED || 
 
										userdb[user].connectionState == WAITING_FOR_PIN)) {
 
		LOG4CXX_INFO(logger, std::string("A session corresponding to ") + user + std::string(" is already active"))
 
		return;
 
	}
 
	
 
	LOG4CXX_INFO(logger, std::string("Received login request for ") + user)	
 
	initUserSession(user, legacyName, password);
 
	handleConnected(user);
 
	
 
	LOG4CXX_INFO(logger, "SPECTRUM 1 USER? - " << (userdb[user].spectrum1User? "true" : "false")) 
 
	
 
	LOG4CXX_INFO(logger, user << ": Adding Buddy " << adminLegacyName << " " << adminAlias)
 
	handleBuddyChanged(user, adminLegacyName, adminAlias, std::vector<std::string>(), pbnetwork::STATUS_ONLINE);
 
	userdb[user].nickName = "";
 
	
 
	LOG4CXX_INFO(logger, "Querying database for usersettings of " << user)
 
	std::string key, secret;
 
	getUserOAuthKeyAndSecret(user, key, secret);
 

	
 
	if(key == "" || secret == "") {			
 
		LOG4CXX_INFO(logger, "Intiating OAuth Flow for user " << user)
 
		setTwitterMode(user, 0);
 
		tp->runAsThread(new OAuthFlow(np, userdb[user].sessions, user, userdb[user].sessions->getTwitterUsername()));
 
	} else {
 
		LOG4CXX_INFO(logger, user << " is already registerd. Using the stored oauth key and secret")
 
		LOG4CXX_INFO(logger, key << " " << secret)	
 
		pinExchangeComplete(user, key, secret);
 
	}
 
}
 

	
 
// User logging out
 
void TwitterPlugin::handleLogoutRequest(const std::string &user, const std::string &legacyName) 
 
{
 
	if (userdb.count(user)) {
 
		delete userdb[user].sessions;
 
		userdb[user].sessions = NULL;
 
		userdb[user].connectionState = DISCONNECTED;
 
	}
 

	
 
	if(onlineUsers.count(user)) {
include/Swiften/FileTransfer/CombinedOutgoingFileTransferManager.cpp
Show inline comments
 
/*
 
 * Copyright (c) 2011 Tobias Markmann
 
 * Licensed under the simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#include "CombinedOutgoingFileTransferManager.h"
 

	
 
#include <boost/foreach.hpp>
 
#include <boost/smart_ptr/make_shared.hpp>
 

	
 
#include <Swiften/JID/JID.h>
 
#include "Swiften/Disco/EntityCapsProvider.h"
 
#include <Swiften/Jingle/JingleSessionManager.h>
 
#include <Swiften/Jingle/JingleSessionImpl.h>
 
#include <Swiften/Jingle/JingleContentID.h>
 
#include <Swiften/FileTransfer/OutgoingJingleFileTransfer.h>
 
#include <Swiften/FileTransfer/MyOutgoingSIFileTransfer.h>
 
#include <Swiften/FileTransfer/SOCKS5BytestreamServer.h>
 
#include <Swiften/Base/IDGenerator.h>
 
#include <Swiften/Elements/Presence.h>
 
#include <Swiften/Base/foreach.h>
 

	
 

	
 
namespace Swift {
 

	
 
CombinedOutgoingFileTransferManager::CombinedOutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, Transport::PresenceOracle *presOracle, SOCKS5BytestreamServer *bytestreamServer) : jsManager(jingleSessionManager), iqRouter(router), capsProvider(capsProvider), remoteFactory(remoteFactory), localFactory(localFactory), bytestreamRegistry(bytestreamRegistry), bytestreamProxy(bytestreamProxy), presenceOracle(presOracle), bytestreamServer(bytestreamServer) {
 
	idGenerator = new IDGenerator();
 
}
 

	
 
CombinedOutgoingFileTransferManager::~CombinedOutgoingFileTransferManager() {
 
	delete idGenerator;
 
}
 

	
 
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<OutgoingFileTransfer> CombinedOutgoingFileTransferManager::createOutgoingFileTransfer(const JID& from, const JID& receipient, SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ReadBytestream> readBytestream, const StreamInitiationFileInfo& fileInfo) {
 
	// check if receipient support Jingle FT
 
	boost::optional<JID> fullJID = highestPriorityJIDSupportingJingle(receipient);
 
	if (!fullJID.is_initialized()) {
 
		fullJID = highestPriorityJIDSupportingSI(receipient);
 
	}
 
	else {
 
		JingleSessionImpl::ref jingleSession = SWIFTEN_SHRPTR_NAMESPACE::make_shared<JingleSessionImpl>(from, receipient, idGenerator->generateID(), iqRouter);
 

	
 
		//jsManager->getSession(receipient, idGenerator->generateID());
 
		assert(jingleSession);
 
		jsManager->registerOutgoingSession(from, jingleSession);
 
#if !HAVE_SWIFTEN_3
 
		SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<OutgoingJingleFileTransfer> jingleFT =  SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<OutgoingJingleFileTransfer>(new OutgoingJingleFileTransfer(jingleSession, remoteFactory, localFactory, iqRouter, idGenerator, from, receipient, readBytestream, fileInfo, bytestreamRegistry, bytestreamProxy));
 
		return jingleFT;
 
#endif
 
	}
 

	
 
	if (!fullJID.is_initialized()) {
 
		return SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<OutgoingFileTransfer>();
 
	}
 
	
 
	// otherwise try SI
 
	SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<MyOutgoingSIFileTransfer> jingleFT =  SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<MyOutgoingSIFileTransfer>(new MyOutgoingSIFileTransfer(idGenerator->generateID(), from, fullJID.get(), fileInfo.getName(), fileInfo.getSize(), fileInfo.getDescription(), readBytestream, iqRouter, bytestreamServer, bytestreamRegistry));
 
	// else fail
 
	
 
	return jingleFT;
 
}
 

	
 
boost::optional<JID> CombinedOutgoingFileTransferManager::highestPriorityJIDSupportingJingle(const JID& bareJID) {
 
	JID fullReceipientJID;
 
	int priority = INT_MIN;
 
	
 
	//getAllPresence(bareJID) gives you all presences for the bare JID (i.e. all resources) Remko Tronçon @ 11:11
 
	std::vector<Presence::ref> presences = presenceOracle->getAllPresence(bareJID);
 

	
 
	//iterate over them
 
	foreach(Presence::ref pres, presences) {
 
	BOOST_FOREACH(Presence::ref pres, presences) {
 
		if (pres->getPriority() > priority) {
 
			// look up caps from the jid
 
			DiscoInfo::ref info = capsProvider->getCaps(pres->getFrom());
 
			if (info && info->hasFeature(DiscoInfo::JingleFeature) && info->hasFeature(DiscoInfo::JingleFTFeature) &&
 
				info->hasFeature(DiscoInfo::JingleTransportsIBBFeature)) {
 
			
 
				priority = pres->getPriority();
 
				fullReceipientJID = pres->getFrom();
 
			}
 
		}
 
	}
 
	
 
	return fullReceipientJID.isValid() ? boost::optional<JID>(fullReceipientJID) : boost::optional<JID>();
 
}
 

	
 
boost::optional<JID> CombinedOutgoingFileTransferManager::highestPriorityJIDSupportingSI(const JID& bareJID) {
 
	JID fullReceipientJID;
 
	int priority = INT_MIN;
 
	
 
	//getAllPresence(bareJID) gives you all presences for the bare JID (i.e. all resources) Remko Tronçon @ 11:11
 
	std::vector<Presence::ref> presences = presenceOracle->getAllPresence(bareJID);
 

	
 
	//iterate over them
 
	foreach(Presence::ref pres, presences) {
 
	BOOST_FOREACH(Presence::ref pres, presences) {
 
		if (pres->getPriority() > priority) {
 
			// look up caps from the jid
 
			DiscoInfo::ref info = capsProvider->getCaps(pres->getFrom());
 
			if (info && info->hasFeature("http://jabber.org/protocol/si/profile/file-transfer")) {
 
			
 
				priority = pres->getPriority();
 
				fullReceipientJID = pres->getFrom();
 
			}
 
		}
 
	}
 
	
 
	return fullReceipientJID.isValid() ? boost::optional<JID>(fullReceipientJID) : boost::optional<JID>();
 
}
 

	
 
}
include/Swiften/Parser/PayloadParsers/GatewayPayloadParser.cpp
Show inline comments
 
/*
 
 * Copyright (c) 2012 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#include <Swiften/Parser/PayloadParsers/GatewayPayloadParser.h>
 

	
 
#include <boost/foreach.hpp>
 
#include <boost/lexical_cast.hpp>
 

	
 
#include <Swiften/Parser/PayloadParserFactoryCollection.h>
 
#include <Swiften/Parser/PayloadParserFactory.h>
 
#include <Swiften/Base/foreach.h>
 
#include <Swiften/Elements/MUCOccupant.h>
 
#include <Swiften/Parser/Tree/TreeReparser.h>
 

	
 
namespace Swift {
 

	
 
void GatewayPayloadParser::handleTree(ParserElement::ref root) {
 
	foreach (ParserElement::ref child, root->getAllChildren()) {
 
	BOOST_FOREACH (ParserElement::ref child, root->getAllChildren()) {
 
		if (child->getName() == "desc") {
 
			getPayloadInternal()->setDesc(child->getText());
 
		}
 
		else if (child->getName() == "prompt") {
 
			getPayloadInternal()->setPrompt(child->getText());
 
		}
 
		else if (child->getName() == "jid") {
 
			getPayloadInternal()->setJID(child->getText());
 
		}
 
	}
 
}
 

	
 
}
include/Swiften/Parser/PayloadParsers/MUCPayloadParser.cpp
Show inline comments
 
/*
 
 * Copyright (c) 2010 Kevin Smith
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#include <Swiften/Parser/PayloadParsers/MUCPayloadParser.h>
 

	
 
#include <boost/foreach.hpp>
 
#include <boost/lexical_cast.hpp>
 

	
 
#include <Swiften/Parser/PayloadParserFactoryCollection.h>
 
#include <Swiften/Parser/PayloadParserFactory.h>
 
#include <Swiften/Base/foreach.h>
 
#include <Swiften/Elements/MUCOccupant.h>
 
#include <Swiften/Parser/Tree/TreeReparser.h>
 

	
 
namespace Swift {
 

	
 
void MUCPayloadParser::handleTree(ParserElement::ref root) {
 
	foreach (ParserElement::ref child, root->getAllChildren()) {
 
	BOOST_FOREACH (ParserElement::ref child, root->getAllChildren()) {
 
		if (child->getName() == "password" && child->getNamespace() == root->getNamespace()) {
 
			getPayloadInternal()->setPassword(child->getText());
 
		}
 
	}
 
}
 

	
 
}
include/Swiften/Parser/StringTreeParser.cpp
Show inline comments
 
/*
 
 * Copyright (c) 2011 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#include <Swiften/Parser/StringTreeParser.h>
 
#include <Swiften/Parser/PlatformXMLParserFactory.h>
 
#include <Swiften/Parser/Tree/ParserElement.h>
 
#include <Swiften/Parser/XMLParser.h>
 
#include <Swiften/Version.h>
 

	
 
namespace Swift {
 

	
 
class DefaultStringTreeParser : public StringTreeParser {
 
	public:
 
		void handleTree(ParserElement::ref root) {
 
			root_ = root;
 
		}
 

	
 
		ParserElement::ref getRoot() {
 
			return root_;
 
		}
 

	
 
	private:
 
		ParserElement::ref root_;
 
};
 
	
 
ParserElement::ref StringTreeParser::parse(const std::string &xml) {
 
	PlatformXMLParserFactory factory;
 
	DefaultStringTreeParser client;
 
#if (SWIFTEN_VERSION >= 0x040000)
 
	std::unique_ptr<XMLParser> parser = factory.createXMLParser(&client);
 
#else
 
	XMLParser *parser = factory.createXMLParser(&client);
 
#endif
 
	
 
	parser->parse(xml);
 
	ParserElement::ref root = client.getRoot();
 
#if (SWIFTEN_VERSION < 0x040000)
 
	delete parser;
 
#endif
 
	return root;
 
}
 

	
 
}
include/Swiften/Serializer/PayloadSerializers/GatewayPayloadSerializer.cpp
Show inline comments
 
/*
 
 * Copyright (c) 2011 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#include <Swiften/Serializer/PayloadSerializers/GatewayPayloadSerializer.h>
 
#include <Swiften/Base/foreach.h>
 
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
 
#include <Swiften/Serializer/XML/XMLTextNode.h>
 
#include <Swiften/Serializer/XML/XMLElement.h>
 
#include <Swiften/Serializer/PayloadSerializerCollection.h>
 

	
 
#include "Swiften/SwiftenCompat.h"
 

	
 
namespace Swift {
 

	
 
GatewayPayloadSerializer::GatewayPayloadSerializer()
 
	: GenericPayloadSerializer<GatewayPayload>() {
 
}
 

	
 
std::string GatewayPayloadSerializer::serializePayload(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<GatewayPayload> payload)  const {
 
	XMLElement query("query", "jabber:iq:gateway");
 

	
 
	if (payload->getJID().isValid()) {
 
		SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<XMLElement> jid(new XMLElement("jid", "", payload->getJID().toBare().toString()));
 
		query.addNode(jid);
 
	}
 

	
 
	if (!payload->getDesc().empty()) {
 
		SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<XMLElement> desc(new XMLElement("desc", "", payload->getDesc()));
 
		query.addNode(desc);
 
	}
 

	
 
	if (!payload->getPrompt().empty()) {
 
		SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<XMLElement> prompt(new XMLElement("prompt", "", payload->getPrompt()));
 
		query.addNode(prompt);
 
	}
 

	
 
	return query.serialize();
 
}
 

	
 
}
include/Swiften/Serializer/PayloadSerializers/SpectrumErrorSerializer.cpp
Show inline comments
 
/*
 
 * Copyright (c) 2011 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#include <Swiften/Serializer/PayloadSerializers/SpectrumErrorSerializer.h>
 

	
 
#include <boost/shared_ptr.hpp>
 

	
 
#include <Swiften/Base/foreach.h>
 
#include <Swiften/Serializer/XML/XMLTextNode.h>
 
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
 
#include <Swiften/Serializer/XML/XMLElement.h>
 
#include "Swiften/SwiftenCompat.h"
 
#include <boost/lexical_cast.hpp>
 

	
 
namespace Swift {
 

	
 
SpectrumErrorSerializer::SpectrumErrorSerializer() : GenericPayloadSerializer<SpectrumErrorPayload>() {
 
}
 

	
 
std::string SpectrumErrorSerializer::serializePayload(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<SpectrumErrorPayload> error)  const {
 
	std::string data;
 
	switch (error->getError()) {
 
		case SpectrumErrorPayload::CONNECTION_ERROR_NETWORK_ERROR: data = "CONNECTION_ERROR_NETWORK_ERROR"; break;
 
		case SpectrumErrorPayload::CONNECTION_ERROR_INVALID_USERNAME: data = "CONNECTION_ERROR_INVALID_USERNAME"; break;
 
		case SpectrumErrorPayload::CONNECTION_ERROR_AUTHENTICATION_FAILED: data = "CONNECTION_ERROR_AUTHENTICATION_FAILED"; break;
 
		case SpectrumErrorPayload::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE: data = "CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE"; break;
 
		case SpectrumErrorPayload::CONNECTION_ERROR_NO_SSL_SUPPORT: data = "CONNECTION_ERROR_NO_SSL_SUPPORT"; break;
 
		case SpectrumErrorPayload::CONNECTION_ERROR_ENCRYPTION_ERROR: data = "CONNECTION_ERROR_ENCRYPTION_ERROR"; break;
 
		case SpectrumErrorPayload::CONNECTION_ERROR_NAME_IN_USE: data = "CONNECTION_ERROR_NAME_IN_USE"; break;
 
		case SpectrumErrorPayload::CONNECTION_ERROR_INVALID_SETTINGS: data = "CONNECTION_ERROR_INVALID_SETTINGS"; break;
 
		case SpectrumErrorPayload::CONNECTION_ERROR_CERT_NOT_PROVIDED: data = "CONNECTION_ERROR_CERT_NOT_PROVIDED"; break;
 
		case SpectrumErrorPayload::CONNECTION_ERROR_CERT_UNTRUSTED: data = "CONNECTION_ERROR_CERT_UNTRUSTED"; break;
 
		case SpectrumErrorPayload::CONNECTION_ERROR_CERT_EXPIRED: data = "CONNECTION_ERROR_NETWORK_ERROR"; break;
 
		case SpectrumErrorPayload::CONNECTION_ERROR_CERT_NOT_ACTIVATED: data = "CONNECTION_ERROR_NETWORK_ERROR"; break;
 
		case SpectrumErrorPayload::CONNECTION_ERROR_CERT_HOSTNAME_MISMATCH: data = "CONNECTION_ERROR_NETWORK_ERROR"; break;
 
		case SpectrumErrorPayload::CONNECTION_ERROR_CERT_FINGERPRINT_MISMATCH: data = "CONNECTION_ERROR_NETWORK_ERROR"; break;
 
		case SpectrumErrorPayload::CONNECTION_ERROR_CERT_SELF_SIGNED: data = "CONNECTION_ERROR_NETWORK_ERROR"; break;
 
		case SpectrumErrorPayload::CONNECTION_ERROR_CERT_OTHER_ERROR: data = "CONNECTION_ERROR_NETWORK_ERROR"; break;
 
		case SpectrumErrorPayload::CONNECTION_ERROR_OTHER_ERROR: data = "CONNECTION_ERROR_NETWORK_ERROR"; break;
 
	}
 

	
 
	XMLElement el("spectrumerror", "http://spectrum.im/error", data);
 

	
 
	el.setAttribute("error", boost::lexical_cast<std::string>(error->getError()));
 

	
 
	return el.serialize();
 
}
 

	
 
}
include/Swiften/Serializer/PayloadSerializers/StatsSerializer.cpp
Show inline comments
 
/*
 
 * Copyright (c) 2011 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#include <Swiften/Serializer/PayloadSerializers/StatsSerializer.h>
 
#include <boost/foreach.hpp>
 

	
 
#include <boost/shared_ptr.hpp>
 
#include <Swiften/Serializer/PayloadSerializers/StatsSerializer.h>
 

	
 
#include <Swiften/Base/foreach.h>
 
#include <Swiften/Serializer/XML/XMLTextNode.h>
 
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
 
#include <Swiften/Serializer/XML/XMLElement.h>
 

	
 
#include "Swiften/SwiftenCompat.h"
 

	
 
namespace Swift {
 

	
 
StatsSerializer::StatsSerializer() : GenericPayloadSerializer<StatsPayload>() {
 
}
 

	
 
std::string StatsSerializer::serializePayload(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<StatsPayload> stats)  const {
 
	XMLElement queryElement("query", "http://jabber.org/protocol/stats");
 
	foreach(const StatsPayload::Item& item, stats->getItems()) {
 
	BOOST_FOREACH(const StatsPayload::Item& item, stats->getItems()) {
 
		SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<XMLElement> statElement(new XMLElement("stat"));
 
		statElement->setAttribute("name", item.getName());
 
		if (!item.getUnits().empty()) {
 
			statElement->setAttribute("units", item.getUnits());
 
		}
 
		if (!item.getValue().empty()) {
 
			statElement->setAttribute("value", item.getValue());
 
		}
 

	
 
		queryElement.addNode(statElement);
 
	}
 

	
 
	return queryElement.serialize();
 
}
 

	
 
}
include/Swiften/Serializer/PayloadSerializers/XHTMLIMSerializer.cpp
Show inline comments
 
/*
 
 * Copyright (c) 2011 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#include <Swiften/Serializer/PayloadSerializers/XHTMLIMSerializer.h>
 
#include <Swiften/Base/foreach.h>
 
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
 
#include <Swiften/Serializer/XML/XMLTextNode.h>
 
#include <Swiften/Serializer/XML/XMLElement.h>
 

	
 
#include "Swiften/SwiftenCompat.h"
 

	
 
namespace Swift {
 

	
 
XHTMLIMSerializer::XHTMLIMSerializer() : GenericPayloadSerializer<XHTMLIMPayload>() {
 
}
 

	
 
std::string XHTMLIMSerializer::serializePayload(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<XHTMLIMPayload> payload)  const {
 
	XMLElement html("html", "http://jabber.org/protocol/xhtml-im");
 

	
 
	SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<XMLElement> body(new XMLElement("body", "http://www.w3.org/1999/xhtml"));
 
	body->addNode(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<XMLRawTextNode>(new XMLRawTextNode(payload->getBody())));
 
	html.addNode(body);
 

	
 
	return html.serialize();
 
}
 

	
 
}
include/Swiften/Server/Server.cpp
Show inline comments
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#include "Swiften/Server/Server.h"
 

	
 
#include <string>
 
#include <boost/bind.hpp>
 
#include <boost/foreach.hpp>
 
#include <boost/signal.hpp>
 

	
 
#include "Swiften/Base/String.h"
 
#include "Swiften/Base/foreach.h"
 
#include "Swiften/Network/Connection.h"
 
#include "Swiften/Network/ConnectionServer.h"
 
#include "Swiften/Network/ConnectionServerFactory.h"
 
#include "Swiften/Elements/Element.h"
 
#include "Swiften/Elements/Presence.h"
 
#include "Swiften/Elements/RosterPayload.h"
 
#include "Swiften/Network/NetworkFactories.h"
 
#include "Swiften/Session/SessionTracer.h"
 
#include "Swiften/Elements/IQ.h"
 
#include "Swiften/Elements/VCard.h"
 
#include "Swiften/Server/UserRegistry.h"
 
#include <string>
 
#include "Swiften/Network/ConnectionServer.h"
 
#include "Swiften/Network/ConnectionFactory.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Queries/IQRouter.h"
 
#include <iostream>
 

	
 

	
 
namespace Swift {
 

	
 
Server::Server(
 
		EventLoop* eventLoop,
 
		NetworkFactories* networkFactories,
 
		UserRegistry *userRegistry,
 
		const JID& jid,
 
		const std::string &address,
 
		int port) :
 
			userRegistry_(userRegistry),
 
			port_(port),
 
			eventLoop(eventLoop),
 
			networkFactories_(networkFactories),
 
			stopping(false),
 
			selfJID(jid),
 
			stanzaChannel_(),
 
			address_(address){
 
	stanzaChannel_ = new ServerStanzaChannel(selfJID);
 
	iqRouter_ = new IQRouter(stanzaChannel_);
 
	tlsFactory = NULL;
 
	parserFactory_ = new PlatformXMLParserFactory();
 
}
 

	
 
Server::~Server() {
 
	stop();
 
	delete iqRouter_;
 
	delete stanzaChannel_;
 
	delete parserFactory_;
 
}
 

	
 
void Server::start() {
 
	if (serverFromClientConnectionServer) {
 
		return;
 
	}
 
	if (address_ == "0.0.0.0") {
 
		serverFromClientConnectionServer = networkFactories_->getConnectionServerFactory()->createConnectionServer(port_);
 
	}
 
	else {
 
		serverFromClientConnectionServer = networkFactories_->getConnectionServerFactory()->createConnectionServer(Swift::HostAddress(address_), port_);
 
		serverFromClientConnectionServer = networkFactories_->getConnectionServerFactory()->createConnectionServer(SWIFT_HOSTADDRESS(address_), port_);
 
	}
 
	serverFromClientConnectionServerSignalConnections.push_back(
 
		serverFromClientConnectionServer->onNewConnection.connect(
 
				boost::bind(&Server::handleNewClientConnection, this, _1)));
 
// 	serverFromClientConnectionServerSignalConnections.push_back(
 
// 		serverFromClientConnectionServer->onStopped.connect(
 
// 				boost::bind(&Server::handleClientConnectionServerStopped, this, _1)));
 

	
 
	serverFromClientConnectionServer->start();
 
}
 

	
 
void Server::stop() {
 
	if (stopping) {
 
		return;
 
	}
 

	
 
	stopping = true;
 

	
 
// 	foreach(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ServerFromClientSession> session, serverFromClientSessions) {
 
// 		session->finishSession();
 
// 	}
 
	serverFromClientSessions.clear();
 

	
 
	if (serverFromClientConnectionServer) {
 
		serverFromClientConnectionServer->stop();
 
		foreach(SWIFTEN_SIGNAL_NAMESPACE::connection& connection, serverFromClientConnectionServerSignalConnections) {
 
		BOOST_FOREACH(SWIFTEN_SIGNAL_NAMESPACE::connection& connection, serverFromClientConnectionServerSignalConnections) {
 
			connection.disconnect();
 
		}
 
		serverFromClientConnectionServerSignalConnections.clear();
 
		serverFromClientConnectionServer.reset();
 
	}
 

	
 
	stopping = false;
 
// 	onStopped(e);
 
}
 

	
 
void Server::handleNewClientConnection(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Connection> connection) {
 

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

	
 
	serverFromClientSession->onSessionStarted.connect(
 
			boost::bind(&Server::handleSessionStarted, this, serverFromClientSession));
 
	serverFromClientSession->onSessionFinished.connect(
 
			boost::bind(&Server::handleSessionFinished, this, 
 
			serverFromClientSession));
 
	serverFromClientSession->onDataRead.connect(boost::bind(&Server::handleDataRead, this, _1));
 
	serverFromClientSession->onDataWritten.connect(boost::bind(&Server::handleDataWritten, this, _1));
 

	
 
	if (tlsFactory) {
 
		serverFromClientSession->addTLSEncryption(tlsFactory, cert);
 
	}
 

	
 
	serverFromClientSession->startSession();
 

	
 
	serverFromClientSessions.push_back(serverFromClientSession);
 
}
 

	
 
void Server::handleDataRead(const SafeByteArray& data) {
 
	onDataRead(data);
 
}
 

	
 
void Server::handleDataWritten(const SafeByteArray& data) {
 
	onDataWritten(data);
 
}
 

	
 
void Server::handleSessionStarted(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ServerFromClientSession> session) {
 
	dynamic_cast<ServerStanzaChannel *>(stanzaChannel_)->addSession(session);
 
}
 

	
 
void Server::handleSessionFinished(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ServerFromClientSession> session) {
 
// 	if (!session->getRemoteJID().isValid()) {
 
// 		Swift::Presence::ref presence = Swift::Presence::create();
 
// 		presence->setFrom(session->getBareJID());
 
// 		presence->setType(Swift::Presence::Unavailable);
 
// 		dynamic_cast<ServerStanzaChannel *>(stanzaChannel_)->onPresenceReceived(presence);
 
// 	}
 
	serverFromClientSessions.erase(std::remove(serverFromClientSessions.begin(), serverFromClientSessions.end(), session), serverFromClientSessions.end());
 
	session->onSessionStarted.disconnect(
 
			boost::bind(&Server::handleSessionStarted, this, session));
 
	session->onSessionFinished.disconnect(
 
			boost::bind(&Server::handleSessionFinished, this, session));
 
}
 

	
 
void Server::addTLSEncryption(TLSServerContextFactory* tlsContextFactory, CertificateWithKey::ref cert) {
 
	tlsFactory = tlsContextFactory;
 
	this->cert = cert;
 
}
 

	
 
}
include/Swiften/SwiftenCompat.h
Show inline comments
 
/*
 
 * Swift compatibility
 
 * 
 
 * Copyright (c) 2016, Vladimir Matena <vlada.matena@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  02110-1301, USA.
 
 */
 

	
 
#include <Swiften/Version.h>
 

	
 
/*
 
 * Define macros for Swiften compatible shared pointer and signal namespaces.
 
 *
 
 * Using these it is possible to declare shared pointers and signals like this:
 
 *
 
 * SWIFTEN_SIGNAL_NAMESPACE::signal signal;
 
 * SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Type> ptr;
 
 *
 
 * These are guaranteed to be the same implementation as Swift uses internally,
 
 * thus can be used when passign/retrieveing data from/to swiften.
 
 *
 
 * This is due to Swift 4 moved from boost::shared_ptr to SWIFTEN_SHRPTR_NAMESPACE::shared_ptr
 
 * and from boost::signals to boost::signals2 .
 
 */
 

	
 
#if (SWIFTEN_VERSION >= 0x040000)
 
#define SWIFTEN_SHRPTR_NAMESPACE std
 
#define SWIFTEN_SIGNAL_NAMESPACE boost::signals2
 
#define SWIFT_HOSTADDRESS(x) *(Swift::HostAddress::fromString(x))
 
#else
 
#define SWIFTEN_SHRPTR_NAMESPACE boost
 
#define SWIFTEN_SIGNAL_NAMESPACE boost::signals
 
#define SWIFT_HOSTADDRESS(x) Swift::HostAddress(x)
 
#endif
libtransport/Config.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/Config.h"
 
#include <fstream>
 

	
 
#ifdef _WIN32
 
#include <direct.h>
 
#define getcwd _getcwd
 
#include <windows.h>
 
#ifdef _MSC_VER
 
#define PATH_MAX MAX_PATH
 
#endif
 
#endif
 

	
 
#include "iostream"
 
#include "boost/version.hpp"
 
#include "boost/algorithm/string.hpp"
 

	
 
#define BOOST_MAJOR_VERSION BOOST_VERSION / 100000
 
#define BOOST_MINOR_VERSION BOOST_VERSION / 100 % 1000
 

	
 
using namespace boost::program_options;
 

	
 
namespace Transport {
 
static int getRandomPort(const std::string &s) {
 
	unsigned long r = 0;
 
	BOOST_FOREACH(char c, s) {
 
		r += (int) c;
 
	}
 
	srand(time(NULL) + r);
 
	return 30000 + rand() % 10000;
 
}
 

	
 
bool Config::load(const std::string &configfile, boost::program_options::options_description &opts, const std::string &jid) {
 
	std::ifstream ifs(configfile.c_str());
 
	if (!ifs.is_open())
 
		return false;
 

	
 
	m_file = configfile;
 
	m_jid = jid;
 
	bool ret = load(ifs, opts, jid);
 
	ifs.close();
 
#ifndef WIN32
 
	char path[PATH_MAX] = "";
 
	if (m_file.find_first_of("/") != 0) {
 
		getcwd(path, PATH_MAX);
 
		m_file = std::string(path) + "/" + m_file;
 
	}
 
#endif
 

	
 
	return ret;
 
}
 

	
 
bool Config::load(std::istream &ifs, boost::program_options::options_description &opts, const std::string &_jid) {
 
	m_unregistered.clear();
 
	opts.add_options()
 
		("service.jid", value<std::string>()->default_value(""), "Transport Jabber ID")
 
		("service.server", value<std::string>()->default_value(""), "Server to connect to")
 
		("service.server", value<std::string>()->default_value("127.0.0.1"), "Server to connect to")
 
		("service.password", value<std::string>()->default_value(""), "Password used to auth the server")
 
		("service.port", value<int>()->default_value(0), "Port the server is listening on")
 
		("service.user", value<std::string>()->default_value(""), "The name of user Spectrum runs as.")
 
		("service.group", value<std::string>()->default_value(""), "The name of group Spectrum runs as.")
 
		("service.backend", value<std::string>()->default_value("libpurple_backend"), "Backend")
 
		("service.protocol", value<std::string>()->default_value(""), "Protocol")
 
		("service.pidfile", value<std::string>()->default_value("/var/run/spectrum2/$jid.pid"), "Full path to pid file")
 
		("service.portfile", value<std::string>()->default_value("/var/run/spectrum2/$jid.port"), "File to store backend_port to. It's used by spectrum2_manager.")
 
		("service.working_dir", value<std::string>()->default_value("/var/lib/spectrum2/$jid"), "Working dir")
 
		("service.allowed_servers", value<std::vector<std::string> >()->multitoken(), "Only users from these servers can connect")
 
		("service.server_mode", value<bool>()->default_value(false), "True if Spectrum should behave as server")
 
		("service.users_per_backend", value<int>()->default_value(100), "Number of users per one legacy network backend")
 
		("service.backend_host", value<std::string>()->default_value("localhost"), "Host to bind backend server to")
 
		("service.backend_host", value<std::string>()->default_value("127.0.0.1"), "Host to bind backend server to")
 
		("service.backend_port", value<std::string>()->default_value("0"), "Port to bind backend server to")
 
		("service.cert", value<std::string>()->default_value(""), "PKCS#12 Certificate.")
 
		("service.cert_password", value<std::string>()->default_value(""), "PKCS#12 Certificate password.")
 
		("service.admin_jid", value<std::vector<std::string> >()->multitoken(), "Administrator jid.")
 
		("service.admin_password", value<std::string>()->default_value(""), "Administrator password.")
 
		("service.reuse_old_backends", value<bool>()->default_value(true), "True if Spectrum should use old backends which were full in the past.")
 
		("service.idle_reconnect_time", value<int>()->default_value(0), "Time in seconds after which idle users are reconnected to let their backend die.")
 
		("service.memory_collector_time", value<int>()->default_value(0), "Time in seconds after which backend with most memory is set to die.")
 
		("service.more_resources", value<bool>()->default_value(false), "Allow more resources to be connected in server mode at the same time.")
 
		("service.enable_privacy_lists", value<bool>()->default_value(true), "")
 
		("service.enable_xhtml", value<bool>()->default_value(true), "")
 
		("service.max_room_list_size", value<int>()->default_value(100), "")
 
		("service.login_delay", value<int>()->default_value(0), "")
 
		("service.jid_escaping", value<bool>()->default_value(true), "")
 
		("service.vip_only", value<bool>()->default_value(false), "")
 
		("service.vip_message", value<std::string>()->default_value(""), "")
 
		("service.reconnect_all_users", value<bool>()->default_value(false), "")
 
		("service.frontend", value<std::string>()->default_value("xmpp"), "")
 
		("service.web_directory", value<std::string>()->default_value(""), "Full path to directory used to save files to which the links are sent to users.")
 
		("service.web_url", value<std::string>()->default_value(""), "URL on which files in web_directory are accessible.")
 
		("vhosts.vhost", value<std::vector<std::string> >()->multitoken(), "")
 
		("identity.name", value<std::string>()->default_value("Spectrum 2 Transport"), "Name showed in service discovery.")
 
		("identity.category", value<std::string>()->default_value("gateway"), "Disco#info identity category. 'gateway' by default.")
 
		("identity.type", value<std::string>()->default_value(""), "Type of transport ('icq','msn','gg','irc', ...)")
 
		("registration.enable_public_registration", value<bool>()->default_value(true), "True if users should be able to register.")
 
		("registration.language", value<std::string>()->default_value("en"), "Default language for registration form")
 
		("registration.instructions", value<std::string>()->default_value("Enter your legacy network username and password."), "Instructions showed to user in registration form")
 
		("registration.username_label", value<std::string>()->default_value("3rd-party network username"), "Label for username field")
 
		("registration.password_label", value<std::string>()->default_value("3rd-party network password"), "Label for password field")
 
		("registration.username_mask", value<std::string>()->default_value(""), "Username mask")
 
		("registration.allowed_usernames", value<std::string>()->default_value(""), "Allowed usernames")
 
		("registration.auto_register", value<bool>()->default_value(false), "Register new user automatically when the presence arrives.")
 
		("registration.encoding", value<std::string>()->default_value("utf8"), "Default encoding in registration form")
 
		("registration.require_local_account", value<bool>()->default_value(false), "True if users have to have a local account to register to this transport from remote servers.")
 
		("registration.notify_jid", value<std::vector<std::string> >()->multitoken(), "Send message to this JID if user registers/unregisters")
 
		("registration.local_username_label", value<std::string>()->default_value("Local username:"), "Label for local usernme field")
 
		("registration.local_account_server", value<std::string>()->default_value("localhost"), "The server on which the local accounts will be checked for validity")
 
		("registration.local_account_server_timeout", value<int>()->default_value(10000), "Timeout when checking local user on local_account_server (msecs)")
 
		("gateway_responder.prompt", value<std::string>()->default_value("Contact ID"), "Value of <prompt> </promt> field")
 
		("gateway_responder.label", value<std::string>()->default_value("Enter legacy network contact ID."), "Label for add contact ID field")
 
		("database.type", value<std::string>()->default_value("none"), "Database type.")
 
		("database.database", value<std::string>()->default_value("/var/lib/spectrum2/$jid/database.sql"), "Database used to store data")
 
		("database.server", value<std::string>()->default_value("localhost"), "Database server.")
 
		("database.user", value<std::string>()->default_value(""), "Database user.")
 
		("database.password", value<std::string>()->default_value(""), "Database Password.")
 
		("database.port", value<int>()->default_value(0), "Database port.")
 
		("database.prefix", value<std::string>()->default_value(""), "Prefix of tables in database")
 
		("database.encryption_key", value<std::string>()->default_value(""), "Encryption key.")
 
		("database.vip_statement", value<std::string>()->default_value(""), "Encryption key.")
 
		("logging.config", value<std::string>()->default_value(""), "Path to log4cxx config file which is used for Spectrum 2 instance")
 
		("logging.backend_config", value<std::string>()->default_value(""), "Path to log4cxx config file which is used for backends")
 
		("backend.default_avatar", value<std::string>()->default_value(""), "Full path to default avatar")
 
		("backend.avatars_directory", value<std::string>()->default_value(""), "Path to directory with avatars")
 
		("backend.no_vcard_fetch", value<bool>()->default_value(false), "True if VCards for buddies should not be fetched. Only avatars will be forwarded.")
 
		("proxy.server", value<std::string>()->default_value("localhost"), "Proxy IP.")
 
		("proxy.user", value<std::string>()->default_value(""), "Proxy user.")
 
		("proxy.password", value<std::string>()->default_value(""), "Proxy Password.")
 
		("proxy.port", value<int>()->default_value(0), "Proxy port.")
 
		("twitter.fetch_timeout", value<int>()->default_value(90000), "Proxy port.")
 

	
 
	;
 

	
 
	parsed_options parsed = parse_config_file(ifs, opts, true);
 

	
 
	bool found_working = false;
 
	bool found_pidfile = false;
 
	bool found_portfile = false;
 
	bool found_backend_port = false;
 
	bool found_database = false;
 
	std::string jid = "";
 
	BOOST_FOREACH(option &opt, parsed.options) {
 
		if (opt.string_key == "service.jid") {
 
			if (_jid.empty()) {
 
				jid = opt.value[0];
 
			}
 
			else {
 
				opt.value[0] = _jid;
 
				jid = _jid;
 
			}
 
		}
 
		else if (opt.string_key == "service.backend_port") {
 
			found_backend_port = true;
 
			if (opt.value[0] == "0") {
 
				opt.value[0] = boost::lexical_cast<std::string>(getRandomPort(_jid.empty() ? jid : _jid));
 
			}
 
		}
 
		else if (opt.string_key == "service.working_dir") {
 
			found_working = true;
 
		}
 
		else if (opt.string_key == "service.pidfile") {
 
			found_pidfile = true;
 
		}
 
		else if (opt.string_key == "service.portfile") {
 
			found_portfile = true;
 
		}
 
		else if (opt.string_key == "database.database") {
libtransport/NetworkPluginServer.cpp
Show inline comments
 
@@ -213,193 +213,193 @@ static unsigned long exec_(const std::string& exePath, const char *host, const c
 
}
 

	
 
#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(-1, &status, WNOHANG)) > 0) {
 
		if (result != 0) {
 
			_server->handlePIDTerminated((unsigned long)result);
 
			if (WIFEXITED(status)) {
 
				if (WEXITSTATUS(status) != 0) {
 
// 					LOG4CXX_ERROR(logger, "Backend can not be started, exit_code=" << WEXITSTATUS(status));
 
				}
 
			}
 
			else {
 
// 				LOG4CXX_ERROR(logger, "Backend can not be started");
 
			}
 
		}
 
	}
 
}
 
#endif
 

	
 
static void handleBuddyPayload(LocalBuddy *buddy, const pbnetwork::Buddy &payload) {
 
	// Set alias only if it's not empty. Backends are allowed to send empty alias if it has
 
	// not changed.
 
	if (!payload.alias().empty()) {
 
		buddy->setAlias(payload.alias());
 
	}
 

	
 
	// Change groups if it's not empty. The same as above...
 
	std::vector<std::string> groups;
 
	for (int i = 0; i < payload.group_size(); i++) {
 
		std::string group;
 
		utf8::replace_invalid(payload.group(i).begin(), payload.group(i).end(), std::back_inserter(group), '_');
 
		groups.push_back(group);
 
	}
 
	if (!groups.empty()) {
 
		buddy->setGroups(groups);
 
	}
 

	
 
	buddy->setStatus(Swift::StatusShow((Swift::StatusShow::Type) payload.status()), payload.statusmessage());
 
	buddy->setIconHash(payload.iconhash());
 
	buddy->setBlocked(payload.blocked());
 
}
 

	
 
NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, UserManager *userManager, FileTransferManager *ftManager) {
 
	_server = this;
 
	m_ftManager = ftManager;
 
	m_userManager = userManager;
 
	m_config = config;
 
	m_component = component;
 
	m_isNextLongRun = false;
 
	m_adminInterface = NULL;
 
	m_startingBackend = false;
 
	m_lastLogin = 0;
 
	m_firstPong = true;
 
	m_xmppParser = new Swift::XMPPParser(this, &m_collection, component->getNetworkFactories()->getXMLParserFactory());
 
	m_xmppParser->parse("<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='localhost' version='1.0'>");
 
#if HAVE_SWIFTEN_3
 
	m_serializer = new Swift::XMPPSerializer(&m_collection2, Swift::ClientStreamType, false);
 
#else
 
	m_serializer = new Swift::XMPPSerializer(&m_collection2, Swift::ClientStreamType);
 
#endif
 
	m_component->m_factory = new NetworkFactory(this);
 
	m_userManager->onUserCreated.connect(boost::bind(&NetworkPluginServer::handleUserCreated, this, _1));
 
	m_userManager->onUserDestroyed.connect(boost::bind(&NetworkPluginServer::handleUserDestroyed, this, _1));
 

	
 
	m_component->onRawIQReceived.connect(boost::bind(&NetworkPluginServer::handleRawIQReceived, this, _1));
 

	
 
	m_pingTimer = component->getNetworkFactories()->getTimerFactory()->createTimer(20000);
 
	m_pingTimer->onTick.connect(boost::bind(&NetworkPluginServer::pingTimeout, this));
 
	m_pingTimer->start();
 

	
 
	m_loginTimer = component->getNetworkFactories()->getTimerFactory()->createTimer(CONFIG_INT(config, "service.login_delay") * 1000);
 
	m_loginTimer->onTick.connect(boost::bind(&NetworkPluginServer::loginDelayFinished, this));
 
	m_loginTimer->start();
 

	
 
	if (CONFIG_INT(m_config, "service.memory_collector_time") != 0) {
 
		m_collectTimer = component->getNetworkFactories()->getTimerFactory()->createTimer(CONFIG_INT(m_config, "service.memory_collector_time"));
 
		m_collectTimer->onTick.connect(boost::bind(&NetworkPluginServer::collectBackend, this));
 
		m_collectTimer->start();
 
	}
 

	
 
	m_component->getFrontend()->onVCardRequired.connect(boost::bind(&NetworkPluginServer::handleVCardRequired, this, _1, _2, _3));
 
	m_component->getFrontend()->onVCardUpdated.connect(boost::bind(&NetworkPluginServer::handleVCardUpdated, this, _1, _2));
 

	
 
	m_component->getFrontend()->onBuddyAdded.connect(boost::bind(&NetworkPluginServer::handleBuddyAdded, this, _1, _2));
 
	m_component->getFrontend()->onBuddyRemoved.connect(boost::bind(&NetworkPluginServer::handleBuddyRemoved, this, _1));
 
	m_component->getFrontend()->onBuddyUpdated.connect(boost::bind(&NetworkPluginServer::handleBuddyUpdated, this, _1, _2));
 

	
 
// // 	m_blockResponder = new BlockResponder(component->getIQRouter(), userManager);
 
// // 	m_blockResponder->onBlockToggled.connect(boost::bind(&NetworkPluginServer::handleBlockToggled, this, _1));
 
// // 	m_blockResponder->start();
 

	
 
	m_server = component->getNetworkFactories()->getConnectionServerFactory()->createConnectionServer(Swift::HostAddress(CONFIG_STRING(m_config, "service.backend_host")), boost::lexical_cast<int>(CONFIG_STRING(m_config, "service.backend_port")));
 
	m_server = component->getNetworkFactories()->getConnectionServerFactory()->createConnectionServer(SWIFT_HOSTADDRESS(CONFIG_STRING_DEFAULTED(m_config, "service.backend_host", "127.0.0.1")), boost::lexical_cast<int>(CONFIG_STRING(m_config, "service.backend_port")));
 
	m_server->onNewConnection.connect(boost::bind(&NetworkPluginServer::handleNewClientConnection, this, _1));
 
}
 

	
 
NetworkPluginServer::~NetworkPluginServer() {
 
#ifndef _WIN32
 
	signal(SIGCHLD, SIG_IGN);
 
#endif
 

	
 
	for (std::list<Backend *>::const_iterator it = m_clients.begin(); it != m_clients.end(); it++) {
 
		LOG4CXX_INFO(logger, "Stopping backend " << *it);
 
		std::string message;
 
		pbnetwork::WrapperMessage wrap;
 
		wrap.set_type(pbnetwork::WrapperMessage_Type_TYPE_EXIT);
 
		wrap.SerializeToString(&message);
 

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

	
 
	m_pingTimer->stop();
 
	m_server->stop();
 
	m_server.reset();
 
	delete m_component->m_factory;
 
	delete m_xmppParser;
 
// 	delete m_vcardResponder;
 
// 	delete m_rosterResponder;
 
// 	delete m_blockResponder;
 
}
 

	
 
void NetworkPluginServer::start() {
 
	m_server->start();
 

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

	
 
	while (true) {
 
		unsigned long pid = exec_(CONFIG_STRING(m_config, "service.backend"), CONFIG_STRING(m_config, "service.backend_host").c_str(), CONFIG_STRING(m_config, "service.backend_port").c_str(), "1", m_config->getCommandLineArgs().c_str());
 
		LOG4CXX_INFO(logger, "Tried to spawn first backend with pid " << pid);
 
		LOG4CXX_INFO(logger, "Backend should now connect to Spectrum2 instance. Spectrum2 won't accept any connection before backend connects");
 

	
 
#ifndef _WIN32
 
		// wait if the backend process will still be alive after 1 second
 
		sleep(1);
 
		pid_t result;
 
		int status;
 
		result = waitpid(-1, &status, WNOHANG);
 
		if (result != 0) {
 
			if (WIFEXITED(status)) {
 
				if (WEXITSTATUS(status) != 0) {
 
					if (status == 254) {
 
						LOG4CXX_ERROR(logger, "Backend can not be started, because it needs database to store data, but the database backend is not configured.");
 
					}
 
					else {
 
						LOG4CXX_ERROR(logger, "Backend can not be started, exit_code=" << WEXITSTATUS(status) << ", possible error: " << strerror(WEXITSTATUS(status)));
 
						if (WEXITSTATUS(status) == ENOENT) {
 
							LOG4CXX_ERROR(logger, "This usually means the path to backend executable defined in config file as '[service] backend=\"...\"' is wrong or the executable does not exists.");
 
						}
 
						
 
					}
 
					LOG4CXX_ERROR(logger, "Check backend log for more details");
 
					continue;
 
				}
 
			}
 
			else {
 
				LOG4CXX_ERROR(logger, "Backend can not be started");
 
				continue;
 
			}
 
		}
 

	
 
		m_pids.push_back(pid);
 

	
 
		signal(SIGCHLD, SigCatcher);
 
#endif
 
		// quit the while loop
 
		break;
 
	}
 
}
 

	
 
void NetworkPluginServer::loginDelayFinished() {
 
	m_loginTimer->stop();
 
	connectWaitingUsers();
 
}
 

	
 
void NetworkPluginServer::handleNewClientConnection(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Connection> c) {
 
	// Create new Backend instance
 
	Backend *client = new Backend;
 
	client->pongReceived = -1;
 
	client->connection = c;
 
	client->res = 0;
 
	client->init_res = 0;
 
	client->shared = 0;
 
	// Until we receive first PONG from backend, backend is in willDie state.
 
	client->willDie = true;
 
	// Backend does not accept new clients automatically if it's long-running
 
	client->acceptUsers = !m_isNextLongRun;
 
	client->longRun = m_isNextLongRun;
 

	
spectrum_manager/src/methods.cpp
Show inline comments
 
@@ -498,151 +498,151 @@ static void handleConnected(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Connecti
 
		m_conn->onDataRead.disconnect(boost::bind(&handleDataRead, m_conn, _1));
 

	
 
// 		exit(50);
 
	}
 
	else {
 
		pbnetwork::BackendConfig m;
 
		m.set_config(msg);
 

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

	
 
		WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_QUERY);
 

	
 
		uint32_t size = htonl(message.size());
 
		char *header = (char *) &size;
 

	
 
		
 
		// send header together with wrapper message
 
		m_conn->write(Swift::createSafeByteArray(std::string(header, 4) + message));
 
	}
 
}
 

	
 
std::string get_config(ManagerConfig *config, const std::string &jid, const std::string &key) {
 
	path p(CONFIG_STRING(config, "service.config_directory"));
 

	
 
	try {
 
		if (!exists(p)) {
 
			std::cerr << "Config directory " << CONFIG_STRING(config, "service.config_directory") << " does not exist\n";
 
			return "";
 
		}
 

	
 
		if (!is_directory(p)) {
 
			std::cerr << "Config directory " << CONFIG_STRING(config, "service.config_directory") << " does not exist\n";
 
			return "";
 
		}
 

	
 
		directory_iterator end_itr;
 
		for (directory_iterator itr(p); itr != end_itr; ++itr) {
 
			if (is_regular(itr->path()) && extension(itr->path()) == ".cfg") {
 
				Config cfg;
 
				if (cfg.load(itr->path().string()) == false) {
 
					std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n";
 
					continue;
 
				}
 

	
 
				if (CONFIG_STRING(&cfg, "service.jid") != jid) {
 
					continue;
 
				}
 

	
 
				return CONFIG_STRING(&cfg, key);
 
			}
 
		}
 

	
 
	}
 
	catch (const filesystem_error& ex) {
 
		return "";
 
	}
 

	
 
	return "";
 
}
 

	
 
void ask_local_server(ManagerConfig *config, Swift::BoostNetworkFactories &networkFactories, const std::string &jid, const std::string &message) {
 
	response = "";
 
	path p(CONFIG_STRING(config, "service.config_directory"));
 

	
 
	try {
 
		if (!exists(p)) {
 
			response = "Error: Config directory " + CONFIG_STRING(config, "service.config_directory") + " does not exist\n";
 
			return;
 
		}
 

	
 
		if (!is_directory(p)) {
 
			response = "Error: Config directory " + CONFIG_STRING(config, "service.config_directory") + " does not exist\n";
 
			return;
 
		}
 

	
 
		bool found = false;
 
		directory_iterator end_itr;
 
		for (directory_iterator itr(p); itr != end_itr; ++itr) {
 
			if (is_regular(itr->path()) && extension(itr->path()) == ".cfg") {
 
				Config cfg;
 
				if (cfg.load(itr->path().string()) == false) {
 
					std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n";
 
					continue;
 
				}
 

	
 
				if (CONFIG_STRING(&cfg, "service.jid") != jid) {
 
					continue;
 
				}
 

	
 
				found = true;
 

	
 
				SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Connection> m_conn;
 
				m_conn = networkFactories.getConnectionFactory()->createConnection();
 
				m_conn->onDataRead.connect(boost::bind(&handleDataRead, m_conn, _1));
 
				m_conn->onConnectFinished.connect(boost::bind(&handleConnected, m_conn, message, _1));
 
				m_conn->connect(Swift::HostAddressPort(Swift::HostAddress(CONFIG_STRING(&cfg, "service.backend_host")), getPort(CONFIG_STRING(&cfg, "service.portfile"))));
 
				m_conn->connect(Swift::HostAddressPort(SWIFT_HOSTADDRESS(CONFIG_STRING_DEFAULTED(&cfg, "service.backend_host", "127.0.0.1")), getPort(CONFIG_STRING(&cfg, "service.portfile"))));
 
			}
 
		}
 

	
 
		if (!found) {
 
			response = "Error: Config file for Spectrum instance with this JID was not found\n";
 
		}
 
	}
 
	catch (const filesystem_error& ex) {
 
		response = "Error: Filesystem error: " + std::string(ex.what()) + "\n";
 
	}
 
}
 

	
 
std::vector<std::string> show_list(ManagerConfig *config, bool show) {
 
	path p(CONFIG_STRING(config, "service.config_directory"));
 
	std::vector<std::string> list;
 

	
 
	try {
 
		if (!exists(p)) {
 
			std::cerr << "Config directory " << CONFIG_STRING(config, "service.config_directory") << " does not exist\n";
 
			return list;
 
		}
 

	
 
		if (!is_directory(p)) {
 
			std::cerr << "Config directory " << CONFIG_STRING(config, "service.config_directory") << " does not exist\n";
 
			return list;
 
		}
 

	
 
		bool found = false;
 
		directory_iterator end_itr;
 
		for (directory_iterator itr(p); itr != end_itr; ++itr) {
 
			if (is_regular(itr->path()) && extension(itr->path()) == ".cfg") {
 
				Config cfg;
 
				if (cfg.load(itr->path().string()) == false) {
 
					std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n";
 
					continue;
 
				}
 

	
 
				if (show) {
 
					std::cout << CONFIG_STRING(&cfg, "service.jid") << "\n";
 
				}
 
				list.push_back(CONFIG_STRING(&cfg, "service.jid"));
 
			}
 
		}
 
	}
 
	catch (const filesystem_error& ex) {
 
		std::cerr << "Filesystem error: " << ex.what() << "\n";
 
	}
 
	return list;
 
}
 

	
 

	
 

	
 

	
 

	
0 comments (0 inline, 0 general)