Connecting the legacy network
This commit is contained in:
parent
96e0e9f7a6
commit
5f017bd15d
8 changed files with 224 additions and 41 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ jid = icq.localhost
|
|||
password = secret
|
||||
server = 127.0.0.1
|
||||
port = 8888
|
||||
protocol=prpl-jabber
|
||||
|
||||
[database]
|
||||
database = test.sql
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
38
src/user.cpp
38
src/user.cpp
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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(){
|
||||
|
|
Loading…
Add table
Reference in a new issue