Changeset - 5f017bd15dc7
[Not reviewed]
0 8 0
HanzZ - 14 years ago 2011-03-18 09:44:23
hanzz.k@gmail.com
Connecting the legacy network
8 files changed with 224 insertions and 41 deletions:
0 comments (0 inline, 0 general)
include/transport/transport.h
Show inline comments
 
@@ -93,6 +93,8 @@ namespace Transport {
 
			/// \return Jabber ID of this transport
 
			Swift::JID &getJID() { return m_jid; }
 

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

	
 
			/// 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;
 
@@ -114,6 +116,8 @@ namespace Transport {
 
			/// \param presence presence data
 
			boost::signal<void (Swift::Presence::ref presence)> onUserPresenceReceived;
 

	
 
// 			boost::signal<void (boost::shared_ptr<Swift::DiscoInfo> info, Swift::ErrorPayload::ref error, const Swift::JID& jid)> onDiscoInfoResponse;
 

	
 
		private:
 
			void handleConnected();
 
			void handleConnectionError(const Swift::ComponentError &error);
 
@@ -125,8 +129,8 @@ namespace Transport {
 
			void handleDataRead(const std::string &data);
 
			void handleDataWritten(const std::string &data);
 

	
 
			void handleDiscoInfoResponse(boost::shared_ptr<Swift::DiscoInfo> info, Swift::ErrorPayload::ref error, const Swift::JID& jid);
 
// 			void handleCapsChanged(const Swift::JID& jid);
 
// 			void handleDiscoInfoResponse(boost::shared_ptr<Swift::DiscoInfo> info, Swift::ErrorPayload::ref error, const Swift::JID& jid);
 
			void handleCapsChanged(const Swift::JID& jid);
 

	
 
			Swift::BoostNetworkFactories *m_factories;
 
			Swift::Component *m_component;
include/transport/user.h
Show inline comments
 
@@ -52,6 +52,9 @@ class User {
 
		/// \return UserInfo struct
 
		UserInfo &getUserInfo() { return m_userInfo; }
 

	
 
		void setData(void *data) { m_data = data; }
 
		void *getData() { return m_data; }
 

	
 
		/// Handles presence from XMPP JID associated with this user.
 
		/// \param presence Swift::Presence.
 
		void handlePresence(Swift::Presence::ref presence);
 
@@ -60,12 +63,20 @@ class User {
 
		/// \return language
 
		const char *getLang() { return "en"; }
 

	
 
		boost::signal<void ()> onReadyToConnect;
 

	
 
	private:
 
		void onConnectingTimeout();
 

	
 
		Swift::JID m_jid;
 
		Component *m_component;		
 
		Swift::EntityCapsManager *m_entityCapsManager;
 
		Swift::PresenceOracle *m_presenceOracle;
 
		UserInfo m_userInfo;
 
		void *m_data;
 
		bool m_connected;
 
		bool m_readyForConnect;
 
		Swift::Timer::ref m_reconnectTimer;
 
};
 

	
 
}
include/transport/usermanager.h
Show inline comments
 
@@ -68,6 +68,7 @@ class UserManager {
 

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

	
 
		long m_onlineBuddies;
spectrum/src/main.cpp
Show inline comments
 
@@ -8,9 +8,12 @@
 
#include "transport/logger.h"
 
#include "transport/sqlite3backend.h"
 
#include "transport/userregistration.h"
 
#include "transport/user.h"
 
#include "transport/storagebackend.h"
 
#include "spectrumeventloop.h"
 
#include "geventloop.h"
 

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

	
 

	
 
using namespace Transport;
 
@@ -61,13 +64,39 @@ static PurpleCoreUiOps coreUiOps =
 
	NULL
 
};
 

	
 
static void printDebug(PurpleDebugLevel level, const char *category, const char *arg_s) {
 
	std::string c("[LIBPURPLE");
 

	
 
	if (category) {
 
		c.push_back('/');
 
		c.append(category);
 
	}
 

	
 
	c.push_back(']');
 

	
 
	std::cout << c << " " << arg_s;
 
}
 

	
 
/*
 
 * Ops....
 
 */
 
static PurpleDebugUiOps debugUiOps =
 
{
 
	printDebug,
 
	NULL,
 
	NULL,
 
	NULL,
 
	NULL,
 
	NULL
 
};
 

	
 
static bool initPurple(Config &cfg) {
 
	bool ret;
 

	
 
	purple_util_set_user_dir("./");
 

	
 
// 	if (m_configuration.logAreas & LOG_AREA_PURPLE)
 
// 		purple_debug_set_ui_ops(&debugUiOps);
 
		purple_debug_set_ui_ops(&debugUiOps);
 

	
 
	purple_core_set_ui_ops(&coreUiOps);
 
	purple_eventloop_set_ui_ops(getEventLoopUiOps());
 
@@ -119,6 +148,118 @@ static bool initPurple(Config &cfg) {
 
	return ret;
 
}
 

	
 
static void handleUserReadyToConnect(User *user) {
 
	PurpleAccount *account = (PurpleAccount *) user->getData();
 
	purple_account_set_enabled(account, "spectrum", TRUE);
 
	
 
	const PurpleStatusType *status_type = purple_account_get_status_type_with_primitive(account, PURPLE_STATUS_AVAILABLE);
 
	if (status_type != NULL) {
 
		purple_account_set_status(account, purple_status_type_get_id(status_type), TRUE, NULL);
 
	}
 
}
 

	
 
static void handleUserCreated(User *user, UserManager *userManager, Config *config) {
 
	UserInfo userInfo = user->getUserInfo();
 
	PurpleAccount *account = NULL;
 
	const char *protocol = CONFIG_STRING(config, "service.protocol").c_str();
 
	if (purple_accounts_find(userInfo.uin.c_str(), protocol) != NULL){
 
		Log(userInfo.jid, "this account already exists");
 
		account = purple_accounts_find(userInfo.uin.c_str(), protocol);
 
		User *u = (User *) account->ui_data;
 
		if (u && u != user) {
 
			Log(userInfo.jid, "This account is already connected by another jid " << user->getJID());
 
			return;
 
		}
 
	}
 
	else {
 
		Log(userInfo.jid, "creating new account");
 
		account = purple_account_new(userInfo.uin.c_str(), protocol);
 

	
 
		purple_accounts_add(account);
 
	}
 
// 	Transport::instance()->collector()->stopCollecting(m_account);
 

	
 
// 	PurplePlugin *plugin = purple_find_prpl(protocol);
 
// 	PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
 
// 	for (GList *l = prpl_info->protocol_options; l != NULL; l = l->next) {
 
// 		PurpleAccountOption *option = (PurpleAccountOption *) l->data;
 
// 		purple_account_remove_setting(account, purple_account_option_get_setting(option));
 
// 	}
 
// 
 
// 	std::map <std::string, PurpleAccountSettingValue> &settings = Transport::instance()->getConfiguration().purple_account_settings;
 
// 	for (std::map <std::string, PurpleAccountSettingValue>::iterator it = settings.begin(); it != settings.end(); it++) {
 
// 		PurpleAccountSettingValue v = (*it).second;
 
// 		std::string key((*it).first);
 
// 		switch (v.type) {
 
// 			case PURPLE_PREF_BOOLEAN:
 
// 				purple_account_set_bool(m_account, key.c_str(), v.b);
 
// 				break;
 
// 
 
// 			case PURPLE_PREF_INT:
 
// 				purple_account_set_int(m_account, key.c_str(), v.i);
 
// 				break;
 
// 
 
// 			case PURPLE_PREF_STRING:
 
// 				if (v.str)
 
// 					purple_account_set_string(m_account, key.c_str(), v.str);
 
// 				else
 
// 					purple_account_remove_setting(m_account, key.c_str());
 
// 				break;
 
// 
 
// 			case PURPLE_PREF_STRING_LIST:
 
// 				// TODO:
 
// 				break;
 
// 
 
// 			default:
 
// 				continue;
 
// 		}
 
// 	}
 

	
 
	purple_account_set_string(account, "encoding", userInfo.encoding.empty() ? CONFIG_STRING(config, "registration.encoding").c_str() : userInfo.encoding.c_str());
 
	purple_account_set_bool(account, "use_clientlogin", false);
 
// 	purple_account_set_bool(account, "require_tls",  Transport::instance()->getConfiguration().require_tls);
 
// 	purple_account_set_bool(account, "use_ssl",  Transport::instance()->getConfiguration().require_tls);
 
	purple_account_set_bool(account, "direct_connect", false);
 
// 	purple_account_set_bool(account, "check-mail", purple_value_get_boolean(getSetting("enable_notify_email")));
 

	
 
	account->ui_data = user;
 
	user->setData(account);
 

	
 
	user->onReadyToConnect.connect(boost::bind(&handleUserReadyToConnect, user));
 
	
 
// 	Transport::instance()->protocol()->onPurpleAccountCreated(m_account);
 

	
 
// 	m_loadingBuddiesFromDB = true;
 
// 	loadRoster();
 
// 	m_loadingBuddiesFromDB = false;
 

	
 
// 	m_connectionStart = time(NULL);
 
// 	m_readyForConnect = false;
 
	purple_account_set_password(account, userInfo.password.c_str());
 
// 	Log(m_jid, "UIN:" << m_username << " USER_ID:" << m_userID);
 
}
 

	
 
static void handleUserDestroyed(User *user, UserManager *userManager, Config *config) {
 
	PurpleAccount *account = (PurpleAccount *) user->getData();
 
	if (account) {
 
		purple_account_set_enabled(account, "spectrum", FALSE);
 

	
 
		// Remove conversations.
 
		// This has to be called before m_account->ui_data = NULL;, because it uses
 
		// ui_data to call SpectrumMessageHandler::purpleConversationDestroyed() callback.
 
		GList *iter;
 
		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);
 
	}
 
}
 

	
 
int main(int argc, char **argv) {
 
	GError *error = NULL;
 
	GOptionContext *context;
 
@@ -183,7 +324,7 @@ int main(int argc, char **argv) {
 
#endif
 
		Config config;
 
		if (!config.load(argv[1])) {
 
			std::cout << "Can't open sample.cfg configuration file.\n";
 
			std::cout << "Can't open " << argv[1] << " configuration file.\n";
 
			return 1;
 
		}
 

	
 
@@ -192,8 +333,22 @@ int main(int argc, char **argv) {
 
		SpectrumEventLoop eventLoop;
 
		Component transport(&eventLoop, &config);
 
		Logger logger(&transport);
 

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

	
 
		UserRegistration userRegistration(&transport, &userManager, &sql);
 
		logger.setUserRegistration(&userRegistration);
 
		logger.setUserManager(&userManager);
 

	
 
		transport.connect();
 
		
 
		eventLoop.run();
 
	}
 

	
spectrum/src/sample.cfg
Show inline comments
 
@@ -3,6 +3,7 @@ jid = icq.localhost
 
password = secret
 
server = 127.0.0.1
 
port = 8888
 
protocol=prpl-jabber
 

	
 
[database]
 
database = test.sql
src/transport.cpp
Show inline comments
 
@@ -52,7 +52,7 @@ Component::Component(Swift::EventLoop *loop, Config *config) {
 
	m_capsMemoryStorage = new CapsMemoryStorage();
 
	m_capsManager = new CapsManager(m_capsMemoryStorage, m_component->getStanzaChannel(), m_component->getIQRouter());
 
	m_entityCapsManager = new EntityCapsManager(m_capsManager, m_component->getStanzaChannel());
 
// 	m_entityCapsManager->onCapsChanged.connect(boost::bind(&Component::handleCapsChanged, this, _1));
 
 	m_entityCapsManager->onCapsChanged.connect(boost::bind(&Component::handleCapsChanged, this, _1));
 
	
 
	m_presenceOracle = new PresenceOracle(m_component->getStanzaChannel());
 
	m_presenceOracle->onPresenceChange.connect(bind(&Component::handlePresence, this, _1));
 
@@ -169,11 +169,11 @@ void Component::handlePresence(Swift::Presence::ref presence) {
 
			haveFeatures = m_entityCapsManager->getCaps(presence->getFrom()) != DiscoInfo::ref();
 
			std::cout << "has capsInfo " << haveFeatures << "\n";
 
		}
 
		else {
 
			GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(presence->getFrom(), m_component->getIQRouter());
 
			discoInfoRequest->onResponse.connect(boost::bind(&Component::handleDiscoInfoResponse, this, _1, _2, presence->getFrom()));
 
			discoInfoRequest->send();
 
		}
 
// 		else {
 
// 			GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(presence->getFrom(), m_component->getIQRouter());
 
// 			discoInfoRequest->onResponse.connect(boost::bind(&Component::handleDiscoInfoResponse, this, _1, _2, presence->getFrom()));
 
// 			discoInfoRequest->send();
 
// 		}
 
	}
 

	
 
	onUserPresenceReceived(presence);
 
@@ -223,35 +223,9 @@ void Component::handleSubscription(Swift::Presence::ref presence) {
 
// 	}
 
}
 

	
 
void Component::handleDiscoInfoResponse(boost::shared_ptr<DiscoInfo> discoInfo, Swift::ErrorPayload::ref error, const Swift::JID& jid) {
 
// 	AbstractUser *user = Transport::instance()->userManager()->getUserByJID(jid.toBare().toString().getUTF8String());
 
// 
 
// 	std::string resource = jid.getResource().getUTF8String();
 
// 	if (user && user->hasResource(resource)) {
 
// 		if (user->getResource(resource).caps == 0) {
 
// 			int capabilities = 0;
 
// 
 
// 			for (std::vector< String >::const_iterator it = discoInfo->getFeatures().begin(); it != discoInfo->getFeatures().end(); ++it) {
 
// 				if (*it == "http://jabber.org/protocol/rosterx") {
 
// 					capabilities |= CLIENT_FEATURE_ROSTERX;
 
// 				}
 
// 				else if (*it == "http://jabber.org/protocol/xhtml-im") {
 
// 					capabilities |= CLIENT_FEATURE_XHTML_IM;
 
// 				}
 
// 				else if (*it == "http://jabber.org/protocol/si/profile/file-transfer") {
 
// 					capabilities |= CLIENT_FEATURE_FILETRANSFER;
 
// 				}
 
// 				else if (*it == "http://jabber.org/protocol/chatstates") {
 
// 					capabilities |= CLIENT_FEATURE_CHATSTATES;
 
// 				}
 
// 			}
 
// 
 
// 			user->setResource(resource, -256, capabilities);
 
// 			if (user->readyForConnect()) {
 
// 				user->connect();
 
// 			}
 
// 		}
 
// 	}
 
void Component::handleCapsChanged(const Swift::JID& jid) {
 
	bool haveFeatures = m_entityCapsManager->getCaps(jid) != DiscoInfo::ref();
 
	std::cout << "has capsInfo " << haveFeatures << "\n";
 
}
 

	
 
}
src/user.cpp
Show inline comments
 
@@ -32,6 +32,11 @@ User::User(const Swift::JID &jid, UserInfo &userInfo, Component *component) {
 
	m_presenceOracle = component->m_presenceOracle;
 
	m_entityCapsManager = component->m_entityCapsManager;
 
	m_userInfo = userInfo;
 
	m_connected = false;
 
	m_readyForConnect = false;
 

	
 
	m_reconnectTimer = m_component->getFactories()->getTimerFactory()->createTimer(10000);
 
	m_reconnectTimer->onTick.connect(boost::bind(&User::onConnectingTimeout, this)); 
 
}
 

	
 
User::~User(){
 
@@ -44,8 +49,31 @@ const Swift::JID &User::getJID() {
 

	
 
void User::handlePresence(Swift::Presence::ref presence) {
 
	Swift::Presence::ref highest = m_presenceOracle->getHighestPriorityPresence(m_jid.toBare());
 

	
 
	if (!m_connected) {
 
		// we are not connected to legacy network, so we should do it when disco#info arrive :)
 
		if (m_readyForConnect == false) {
 
			
 
			// Forward status message to legacy network, but only if it's sent from active resource
 
// 					if (m_activeResource == presence->getFrom().getResource().getUTF8String()) {
 
// 						forwardStatus(presenceShow, stanzaStatus);
 
// 					}
 
			boost::shared_ptr<Swift::CapsInfo> capsInfo = presence->getPayload<Swift::CapsInfo>();
 
			if (capsInfo && capsInfo->getHash() == "sha-1") {
 
				if (m_entityCapsManager->getCaps(presence->getFrom()) != Swift::DiscoInfo::ref()) {
 
					m_readyForConnect = true;
 
					onReadyToConnect();
 
				}
 
			}
 
			else {
 
				m_reconnectTimer->start();
 
			}
 
		}
 
	}
 

	
 

	
 
	if (highest) {
 
		highest->setTo(presence->getFrom());
 
		highest->setTo(presence->getFrom().toBare());
 
		highest->setFrom(m_component->getJID());
 
		m_component->getComponent()->sendPresence(highest);
 
	}
 
@@ -58,4 +86,12 @@ void User::handlePresence(Swift::Presence::ref presence) {
 
	}
 
}
 

	
 
void User::onConnectingTimeout() {
 
	if (m_connected || m_readyForConnect)
 
		return;
 
	m_reconnectTimer->stop();
 
	m_readyForConnect = true;
 
	onReadyToConnect();
 
}
 

	
 
}
src/usermanager.cpp
Show inline comments
 
@@ -32,6 +32,7 @@ UserManager::UserManager(Component *component, StorageBackend *storageBackend) {
 
	m_storageBackend = storageBackend;
 

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

	
 
UserManager::~UserManager(){
0 comments (0 inline, 0 general)