Changeset - c8006a0ebab6
[Not reviewed]
0 11 1
HanzZ - 15 years ago 2011-04-02 21:51:51
hanzz.k@gmail.com
Working message forwarding in both sides :)
12 files changed with 102 insertions and 6 deletions:
0 comments (0 inline, 0 general)
examples/usermanager/main.cpp
Show inline comments
 
@@ -8,25 +8,25 @@
 
 
using namespace Transport;
 
 
int main(void)
 
{
 
	Config config;
 
	if (!config.load("sample.cfg")) {
 
		std::cout << "Can't open sample.cfg configuration file.\n";
 
		return 1;
 
	}
 
 
	Swift::SimpleEventLoop eventLoop;
 
	Component transport(&eventLoop, &config);
 
	Component transport(&eventLoop, &config, NULL);
 
	Logger logger(&transport);
 
 
	SQLite3Backend sql(&config);
 
	logger.setStorageBackend(&sql);
 
	if (!sql.connect()) {
 
		std::cout << "Can't connect to database.\n";
 
	}
 
 
	UserManager userManager(&transport, &sql);
 
	UserRegistration userRegistration(&transport, &userManager, &sql);
 
	logger.setUserRegistration(&userRegistration);
 
	logger.setUserManager(&userManager);
include/transport/conversationmanager.h
Show inline comments
 
@@ -43,19 +43,22 @@ class ConversationManager {
 

	
 
		/// Returns user associated with this manager.
 
		/// \return User
 
		User *getUser() { return m_user; }
 

	
 
		Component *getComponent() { return m_component; }
 

	
 
		void setConversation(AbstractConversation *conv);
 

	
 
		void unsetConversation(AbstractConversation *conv);
 

	
 
	private:
 
		void handleMessageReceived(Swift::Message::ref message);
 

	
 
		Component *m_component;
 
		User *m_user;
 

	
 
		std::map<std::string, AbstractConversation *> m_convs;
 
		friend class UserManager;
 
};
 

	
 
}
include/transport/factory.h
Show inline comments
 
new file 100644
 
/**
 
 * XMPP - libpurple transport
 
 *
 
 * Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
 
 *
 
 * This program is free software; you can redistribute it and/or modify
 
 * it under the terms of the GNU General Public License as published by
 
 * the Free Software Foundation; either version 2 of the License, or
 
 * (at your option) any later version.
 
 *
 
 * This program is distributed in the hope that it will be useful,
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 * GNU General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU General Public License
 
 * along with this program; if not, write to the Free Software
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#pragma once
 

	
 
#include <string>
 
#include <algorithm>
 
#include "transport/transport.h"
 

	
 
#include "Swiften/Swiften.h"
 
#include "Swiften/Elements/Message.h"
 
#include "transport/abstractconversation.h"
 

	
 
namespace Transport {
 

	
 
class AbstractConversation;
 
class ConversationManager;
 

	
 
class Factory {
 
	public:
 
		
 
		virtual AbstractConversation *createConversation(ConversationManager *conversationManager, const std::string &legacyName) = 0;
 
};
 

	
 
}
include/transport/transport.h
Show inline comments
 
@@ -24,55 +24,57 @@
 
#include "Swiften/Swiften.h"
 
#include "Swiften/Server/Server.h"
 
#include "Swiften/Disco/GetDiscoInfoRequest.h"
 
#include "Swiften/Disco/EntityCapsManager.h"
 
#include "Swiften/Disco/CapsManager.h"
 
#include "Swiften/Disco/CapsMemoryStorage.h"
 
#include "Swiften/Presence/PresenceOracle.h"
 
#include "Swiften/Network/BoostTimerFactory.h"
 
#include "Swiften/Network/BoostIOServiceThread.h"
 
#include "Swiften/Server/UserRegistry.h"
 
#include <boost/bind.hpp>
 
#include "transport/config.h"
 
#include "transport/factory.h"
 

	
 
#define tr(lang,STRING)    (STRING)
 
#define _(STRING)    (STRING)
 

	
 
namespace Transport {
 
	// typedef enum { 	CLIENT_FEATURE_ROSTERX = 2,
 
	// 				CLIENT_FEATURE_XHTML_IM = 4,
 
	// 				CLIENT_FEATURE_FILETRANSFER = 8,
 
	// 				CLIENT_FEATURE_CHATSTATES = 16
 
	// 				} SpectrumImportantFeatures;
 
	// 
 
	class StorageBackend;
 
	class DiscoInfoResponder;
 
	class DiscoItemsResponder;
 
	class RosterResponder;
 
	class Factory;
 

	
 
	/// Represents one transport instance.
 

	
 
	/// It's used to connect
 
	/// the Jabber server and provides transaction layer between Jabber server
 
	/// and other classes.
 
	class Component {
 
		public:
 
			/// Creates new Component instance.
 
			/// \param loop main event loop 
 
			/// \param config cofiguration, this class uses following Config values:
 
			/// 	- service.jid
 
			/// 	- service.password
 
			/// 	- service.server
 
			/// 	- service.port
 
			Component(Swift::EventLoop *loop, Config *config);
 
			Component(Swift::EventLoop *loop, Config *config, Factory *factory);
 

	
 
			/// Component destructor.
 
			~Component();
 

	
 
			/// Returns Swift::Component associated with this Transport::Component.
 
			/// You can use it to send presences and other stanzas.
 
			/// \return Swift::Component associated with this Transport::Component
 
			Swift::StanzaChannel *getStanzaChannel();
 

	
 
			Swift::IQRouter *getIQRouter() { return m_iqRouter; }
 

	
 
			/// Returns Swift::PresenceOracle associated with this Transport::Component.
 
@@ -94,24 +96,26 @@ namespace Transport {
 

	
 
			/// Sets disco#info features which are sent as answer to
 
			/// disco#info IQ-get. This sets features of legacy network buddies (For example "me\40gmail.com@j2j.domain.tld").
 
			/// \param features list of features as sent in disco#info response
 
			void setBuddyFeatures(std::list<std::string> &features);
 

	
 
			/// Returns Jabber ID of this transport.
 
			/// \return Jabber ID of this transport
 
			Swift::JID &getJID() { return m_jid; }
 

	
 
			Swift::BoostNetworkFactories *getFactories() { return m_factories; }
 

	
 
			Factory *getFactory() { return m_factory; }
 

	
 
			/// This signal is emitted when server disconnects the transport because of some error.
 
			/// \param error disconnection error
 
			boost::signal<void (const Swift::ComponentError &error)> onConnectionError;
 

	
 
			/// This signal is emitted when transport successfully connects the server.
 
			boost::signal<void ()> onConnected;
 

	
 
			/// This signal is emitted when XML stanza is sent to server.
 
			/// \param xml xml stanza
 
			boost::signal<void (const std::string &xml)> onXMLOut;
 

	
 
			/// This signal is emitted when XML stanza is received from server.
 
@@ -151,17 +155,18 @@ namespace Transport {
 
			Swift::PresenceOracle *m_presenceOracle;
 
			Swift::StanzaChannel *m_stanzaChannel;
 
			Swift::IQRouter *m_iqRouter;
 
			Swift::UserRegistry *m_userRegistry;
 
			StorageBackend *m_storageBackend;
 
 			DiscoInfoResponder *m_discoInfoResponder;
 
			DiscoItemsResponder *m_discoItemsResponder;
 
			RosterResponder *m_rosterResponder;
 
			int m_reconnectCount;
 
			Config* m_config;
 
			std::string m_protocol;
 
			Swift::JID m_jid;
 
			Factory *m_factory;
 

	
 
		friend class User;
 
		friend class UserRegistration;
 
	};
 
}
include/transport/usermanager.h
Show inline comments
 
@@ -59,23 +59,24 @@ class UserManager {
 
		void removeUser(User *user);
 

	
 
		/// Called when new User class is created.
 
		/// \param user newly created User class
 
		boost::signal<void (User *user)> onUserCreated;
 

	
 
		/// Called when User class is going to be removed
 
		/// \param user removed User class
 
		boost::signal<void (User *user)> onUserDestroyed;
 

	
 
	private:
 
		void handlePresence(Swift::Presence::ref presence);
 
		void handleMessageReceived(Swift::Message::ref message);
 
// 		void handleDiscoInfoResponse(boost::shared_ptr<Swift::DiscoInfo> info, Swift::ErrorPayload::ref error, const Swift::JID& jid);
 
		void addUser(User *user);
 

	
 
		long m_onlineBuddies;
 
		User *m_cachedUser;
 
		std::map<std::string, User *> m_users;
 
		Component *m_component;
 
		StorageBackend *m_storageBackend;
 
};
 

	
 
}
spectrum/src/main.cpp
Show inline comments
 
@@ -2,24 +2,25 @@
 
#include "purple.h"
 
#include <iostream>
 

	
 
#include "transport/config.h"
 
#include "transport/transport.h"
 
#include "transport/usermanager.h"
 
#include "transport/logger.h"
 
#include "transport/sqlite3backend.h"
 
#include "transport/userregistration.h"
 
#include "transport/user.h"
 
#include "transport/storagebackend.h"
 
#include "transport/rostermanager.h"
 
#include "transport/abstractconversation.h"
 
#include "spectrumeventloop.h"
 
#include "spectrumbuddy.h"
 
#include "spectrumconversation.h"
 
#include "geventloop.h"
 

	
 
#define Log(X, STRING) std::cout << "[SPECTRUM] " << X << " " << STRING << "\n";
 

	
 

	
 
using namespace Transport;
 

	
 
Logger *_logger;
 

	
 
@@ -155,24 +156,27 @@ static void conv_new(PurpleConversation *conv) {
 
	SpectrumConversation *s_conv = new SpectrumConversation(user->getConversationManager(), name, conv);
 
	conv->ui_data = s_conv;
 
}
 

	
 
static void conv_destroy(PurpleConversation *conv) {
 
	SpectrumConversation *s_conv = (SpectrumConversation *) conv->ui_data;
 
	if (s_conv) {
 
		delete s_conv;
 
	}
 
}
 

	
 
static void conv_write_im(PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime) {
 
	// Don't forwards our own messages.
 
	if (flags & PURPLE_MESSAGE_SEND || flags & PURPLE_MESSAGE_SYSTEM)
 
		return;
 
	SpectrumConversation *s_conv = (SpectrumConversation *) conv->ui_data;
 
	if (!s_conv)
 
		return;
 

	
 
	boost::shared_ptr<Swift::Message> msg(new Swift::Message());
 
	msg->setBody(message);
 

	
 
	s_conv->handleMessage(msg);
 
}
 

	
 
static PurpleConversationUiOps conversation_ui_ops =
 
{
 
@@ -414,24 +418,32 @@ static void handleUserDestroyed(User *user, UserManager *userManager, Config *co
 
		for (iter = purple_get_conversations(); iter; ) {
 
			PurpleConversation *conv = (PurpleConversation*) iter->data;
 
			iter = iter->next;
 
			if (purple_conversation_get_account(conv) == account)
 
				purple_conversation_destroy(conv);
 
		}
 

	
 
		account->ui_data = NULL;
 
// 		Transport::instance()->collector()->collect(m_account);
 
	}
 
}
 

	
 
class SpectrumFactory : public Factory {
 
	public:
 
		AbstractConversation *createConversation(ConversationManager *conversationManager, const std::string &legacyName) {
 
			PurpleConversation *conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, (PurpleAccount *) conversationManager->getUser()->getData() , legacyName.c_str());
 
			return (AbstractConversation *) conv->ui_data;
 
		}
 
};
 

	
 
int main(int argc, char **argv) {
 
	GError *error = NULL;
 
	GOptionContext *context;
 
	context = g_option_context_new("config_file_name or profile name");
 
	g_option_context_add_main_entries(context, options_entries, "");
 
	if (!g_option_context_parse (context, &argc, &argv, &error)) {
 
		std::cout << "option parsing failed: " << error->message << "\n";
 
		return -1;
 
	}
 

	
 
	if (ver) {
 
// 		std::cout << VERSION << "\n";
 
@@ -485,25 +497,26 @@ int main(int argc, char **argv) {
 
// 			return -1;
 
//		}
 
#endif
 
		Config config;
 
		if (!config.load(argv[1])) {
 
			std::cout << "Can't open " << argv[1] << " configuration file.\n";
 
			return 1;
 
		}
 

	
 
		initPurple(config);
 

	
 
		SpectrumEventLoop eventLoop;
 
		Component transport(&eventLoop, &config);
 
		SpectrumFactory factory;
 
		Component transport(&eventLoop, &config, &factory);
 
		Logger logger(&transport);
 
		_logger = &logger;
 

	
 
		SQLite3Backend sql(&config);
 
		logger.setStorageBackend(&sql);
 
		if (!sql.connect()) {
 
			std::cout << "Can't connect to database.\n";
 
		}
 

	
 
		UserManager userManager(&transport, &sql);
 
		userManager.onUserCreated.connect(boost::bind(&handleUserCreated, _1, &userManager, &config));
 
		userManager.onUserDestroyed.connect(boost::bind(&handleUserDestroyed, _1, &userManager, &config));
spectrum/src/spectrumconversation.cpp
Show inline comments
 
@@ -21,16 +21,21 @@
 
#include "spectrumconversation.h"
 
#include "transport/user.h"
 

	
 
#define Log(X, STRING) std::cout << "[SPECTRUM] " << X << " " << STRING << "\n";
 

	
 
SpectrumConversation::SpectrumConversation(ConversationManager *conversationManager, const std::string &legacyName, PurpleConversation *conv) : AbstractConversation(conversationManager, legacyName), m_conv(conv) {
 
}
 

	
 
SpectrumConversation::~SpectrumConversation() {
 
}
 

	
 
void SpectrumConversation::sendMessage(boost::shared_ptr<Swift::Message> &message) {
 
	
 
	// escape and send
 
	gchar *_markup = purple_markup_escape_text(message->getBody().c_str(), -1);
 
	if (purple_conversation_get_type(m_conv) == PURPLE_CONV_TYPE_IM) {
 
		purple_conv_im_send(PURPLE_CONV_IM(m_conv), _markup);
 
	}
 
	g_free(_markup);
 
}
 

	
 

	
spectrum/src/spectrumconversation.h
Show inline comments
 
@@ -18,24 +18,25 @@
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#pragma once
 

	
 
#include <string>
 
#include "purple.h"
 
#include "account.h"
 
#include "glib.h"
 
#include <algorithm>
 
#include "transport/abstractconversation.h"
 
#include "transport/conversationmanager.h"
 
#include "transport/user.h"
 

	
 
using namespace Transport;
 

	
 
// Wrapper for PurpleBuddy
 
class SpectrumConversation : public AbstractConversation {
 
	public:
 
		SpectrumConversation(ConversationManager *conversationManager, const std::string &legacyName, PurpleConversation *conv);
 
		virtual ~SpectrumConversation();
 
		
 
		PurpleConversation *getConversation() { return m_conv; }
 

	
 
		void sendMessage(boost::shared_ptr<Swift::Message> &message);
src/abstractconversation.cpp
Show inline comments
 
@@ -20,26 +20,26 @@
 

	
 
#include <iostream>
 
#include "transport/abstractconversation.h"
 
#include "transport/conversationmanager.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/abstractbuddy.h"
 
#include "transport/rostermanager.h"
 

	
 
namespace Transport {
 

	
 
AbstractConversation::AbstractConversation(ConversationManager *conversationManager, const std::string &legacyName) : m_conversationManager(conversationManager) {
 
	m_conversationManager->setConversation(this);
 
	m_legacyName = legacyName;
 
	m_conversationManager->setConversation(this);
 
}
 

	
 
AbstractConversation::~AbstractConversation() {
 
	m_conversationManager->unsetConversation(this);
 
}
 

	
 
void AbstractConversation::handleMessage(boost::shared_ptr<Swift::Message> &message) {
 
	message->setTo(m_conversationManager->getUser()->getJID().toBare());
 
	AbstractBuddy *buddy = m_conversationManager->getUser()->getRosterManager()->getBuddy(m_legacyName);
 
	if (buddy) {
 
		std::cout << m_legacyName << " 222222\n";
 
		message->setFrom(buddy->getJID());
src/conversationmanager.cpp
Show inline comments
 
@@ -13,36 +13,49 @@
 
 * 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/conversationmanager.h"
 
#include "transport/abstractconversation.h"
 
#include "transport/usermanager.h"
 
#include "transport/abstractbuddy.h"
 
#include "transport/factory.h"
 
#include "transport/user.h"
 
#include "Swiften/Roster/SetRosterRequest.h"
 
#include "Swiften/Elements/RosterPayload.h"
 
#include "Swiften/Elements/RosterItemPayload.h"
 

	
 
namespace Transport {
 

	
 
ConversationManager::ConversationManager(User *user, Component *component){
 
	m_user = user;
 
	m_component = component;
 
}
 

	
 
ConversationManager::~ConversationManager() {
 
}
 

	
 
void ConversationManager::setConversation(AbstractConversation *conv) {
 
	m_convs[conv->getLegacyName()] = conv;
 
}
 

	
 
void ConversationManager::unsetConversation(AbstractConversation *conv) {
 
	m_convs.erase(conv->getLegacyName());
 
}
 

	
 
void ConversationManager::handleMessageReceived(Swift::Message::ref message) {
 
	std::string name = message->getTo().getUnescapedNode();
 
	if (name.find_last_of("%") != std::string::npos) {
 
		name.replace(name.find_last_of("%"), 1, "@");
 
	}
 

	
 
	if (!m_convs[name]) {
 
		m_convs[name] = m_component->getFactory()->createConversation(this, name);
 
	}
 
	m_convs[name]->sendMessage(message);
 
}
 

	
 
}
 
\ No newline at end of file
src/transport.cpp
Show inline comments
 
@@ -12,51 +12,53 @@
 
 * 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/transport.h"
 
#include <boost/bind.hpp>
 
#include "transport/storagebackend.h"
 
#include "transport/factory.h"
 
#include "discoinforesponder.h"
 
#include "discoitemsresponder.h"
 
#include "rosterresponder.h"
 

	
 
using namespace Swift;
 
using namespace boost;
 

	
 
namespace Transport {
 

	
 

	
 
class MyUserRegistry : public Swift::UserRegistry {
 
	public:
 
		MyUserRegistry() {}
 
		~MyUserRegistry() {}
 
		bool isValidUserPassword(const JID& user, const std::string& password) const {
 
			users[user.toBare().toString()] = password;
 
			return true;
 
		}
 
		mutable std::map<std::string, std::string> users;
 
};
 

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

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

	
 
	m_factories = new BoostNetworkFactories(loop);
 

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

	
 
	if (CONFIG_BOOL(m_config, "service.server_mode")) {
 
		m_userRegistry = new MyUserRegistry();
 
		m_server = new Swift::Server(loop, m_factories, m_userRegistry, m_jid, CONFIG_INT(m_config, "service.port"));
 
		m_server->start();
src/usermanager.cpp
Show inline comments
 
@@ -13,34 +13,36 @@
 
 * 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/usermanager.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/storagebackend.h"
 
#include "transport/conversationmanager.h"
 

	
 
namespace Transport {
 

	
 
UserManager::UserManager(Component *component, StorageBackend *storageBackend) {
 
	m_cachedUser = NULL;
 
	m_onlineBuddies = 0;
 
	m_component = component;
 
	m_storageBackend = storageBackend;
 

	
 
	component->onUserPresenceReceived.connect(bind(&UserManager::handlePresence, this, _1));
 
	m_component->getStanzaChannel()->onMessageReceived.connect(bind(&UserManager::handleMessageReceived, this, _1));
 
// 	component->onDiscoInfoResponse.connect(bind(&UserManager::handleDiscoInfoResponse, this, _1, _2, _3));
 
}
 

	
 
UserManager::~UserManager(){
 
}
 

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

	
 
User *UserManager::getUser(const std::string &barejid){
 
@@ -135,13 +137,22 @@ void UserManager::handlePresence(Swift::Presence::ref presence) {
 
			// There's no presence for this user, so disconnect
 
			if (!highest || (highest && highest->getType() == Swift::Presence::Unavailable)) {
 
				removeUser(user);
 
			}
 
		}
 
		// TODO: HANDLE MUC SOMEHOW
 
// 		else if (user && Transport::instance()->protocol()->tempAccountsAllowed() && !((User *) user)->hasOpenedMUC()) {
 
// 			Transport::instance()->userManager()->removeUser(user);
 
// 		}
 
	}
 
}
 

	
 
void UserManager::handleMessageReceived(Swift::Message::ref message) {
 
	User *user = getUser(message->getFrom().toBare().toString());
 
	if (!user ){
 
		return;
 
	}
 

	
 
	user->getConversationManager()->handleMessageReceived(message);
 
}
 

	
 
}
0 comments (0 inline, 0 general)