pinging backends

This commit is contained in:
HanzZ 2011-05-13 10:54:03 +02:00
parent 7ac55eba24
commit e8b61aa9b6
17 changed files with 173 additions and 601 deletions

View file

@ -82,6 +82,7 @@ ADD_SUBDIRECTORY(src)
ADD_SUBDIRECTORY(include)
ADD_SUBDIRECTORY(examples)
ADD_SUBDIRECTORY(spectrum)
ADD_SUBDIRECTORY(backends)
if(DOXYGEN_FOUND)
message("Docs : yes")

View file

@ -222,7 +222,7 @@ static void buddyListNewNode(PurpleBlistNode *node) {
std::string message;
getStatus(buddy, status, message);
np->handleBuddyCreated(np->m_accounts[account], purple_buddy_get_name(buddy), getAlias(buddy), getGroups(buddy)[0], (int) status.getType(), message, getIconHash(buddy));
np->handleBuddyChanged(np->m_accounts[account], purple_buddy_get_name(buddy), getAlias(buddy), getGroups(buddy)[0], (int) status.getType(), message, getIconHash(buddy));
}
static void buddyStatusChanged(PurpleBuddy *buddy, PurpleStatus *status_, PurpleStatus *old_status) {

View file

@ -81,6 +81,36 @@ function(PROTOBUF_GENERATE_CPP SRCS HDRS)
set(${HDRS} ${${HDRS}} PARENT_SCOPE)
endfunction()
function(PROTOBUF_GENERATE_PY SRCS HDRS)
if(NOT ARGN)
message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files")
return()
endif(NOT ARGN)
set(${SRCS})
set(${HDRS})
foreach(FIL ${ARGN})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(FIL_WE ${FIL} NAME_WE)
list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc")
list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h")
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc"
"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h"
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
ARGS --python_out ${CMAKE_CURRENT_BINARY_DIR} --proto_path ${CMAKE_CURRENT_SOURCE_DIR} ${ABS_FIL}
DEPENDS ${ABS_FIL}
COMMENT "Running Py protocol buffer compiler on ${FIL}"
VERBATIM )
endforeach()
set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
set(${SRCS} ${${SRCS}} PARENT_SCOPE)
set(${HDRS} ${${HDRS}} PARENT_SCOPE)
endfunction()
find_path(PROTOBUF_INCLUDE_DIR google/protobuf/service.h)

View file

@ -1,2 +1,6 @@
ADD_SUBDIRECTORY(server_connect)
ADD_SUBDIRECTORY(usermanager)
if (PROTOBUF_FOUND)
ADD_SUBDIRECTORY(external_network_plugin)
endif()

View file

@ -70,11 +70,14 @@ class Config {
return m_variables[key];
}
const std::string &getConfigFile() { return m_file; }
/// This signal is emitted when config is loaded/reloaded.
boost::signal<void ()> onConfigReloaded;
private:
Variables m_variables;
std::string m_file;
};
}

View file

@ -58,6 +58,7 @@ class NetworkPlugin {
void handleDisconnected();
void send(const std::string &data);
void sendPong();
std::string m_data;
std::string m_host;

View file

@ -58,12 +58,17 @@ class NetworkPluginServer {
void send(boost::shared_ptr<Swift::Connection> &, const std::string &data);
void pingTimeout();
void sendPing();
std::string m_command;
std::string m_data;
UserManager *m_userManager;
Config *m_config;
boost::shared_ptr<Swift::ConnectionServer> m_server;
boost::shared_ptr<Swift::Connection> m_client;
bool m_pongReceived;
Swift::Timer::ref m_pingTimer;
};
}

View file

@ -1,583 +1,39 @@
#include "glib.h"
#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/conversation.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;
static gboolean nodaemon = FALSE;
static gchar *logfile = NULL;
static gchar *lock_file = NULL;
static gboolean ver = FALSE;
static gboolean upgrade_db = FALSE;
static gboolean check_db_version = FALSE;
static gboolean list_purple_settings = FALSE;
static GOptionEntry options_entries[] = {
{ "nodaemon", 'n', 0, G_OPTION_ARG_NONE, &nodaemon, "Disable background daemon mode", NULL },
{ "logfile", 'l', 0, G_OPTION_ARG_STRING, &logfile, "Set file to log", NULL },
{ "pidfile", 'p', 0, G_OPTION_ARG_STRING, &lock_file, "File where to write transport PID", NULL },
{ "version", 'v', 0, G_OPTION_ARG_NONE, &ver, "Shows Spectrum version", NULL },
{ "list-purple-settings", 's', 0, G_OPTION_ARG_NONE, &list_purple_settings, "Lists purple settings which can be used in config file", NULL },
{ "upgrade-db", 'u', 0, G_OPTION_ARG_NONE, &upgrade_db, "Upgrades Spectrum database", NULL },
{ "check-db-GlooxMessageHandler::version", 'c', 0, G_OPTION_ARG_NONE, &check_db_version, "Checks Spectrum database version", NULL },
{ NULL, 0, 0, G_OPTION_ARG_NONE, NULL, "", NULL }
};
static void buddyListNewNode(PurpleBlistNode *node) {
if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
return;
PurpleBuddy *buddy = (PurpleBuddy *) node;
PurpleAccount *account = purple_buddy_get_account(buddy);
User *user = (User *) account->ui_data;
if (!user)
return;
SpectrumBuddy *s_buddy = NULL;
GSList *list = purple_find_buddies(account, purple_buddy_get_name(buddy));
while (list) {
PurpleBuddy *b = (PurpleBuddy *) list->data;
if (b->node.ui_data)
s_buddy = (SpectrumBuddy *) b->node.ui_data;
list = g_slist_delete_link(list, list);
}
if (s_buddy) {
buddy->node.ui_data = s_buddy;
s_buddy->addBuddy(buddy);
}
else {
buddy->node.ui_data = (void *) new SpectrumBuddy(user->getRosterManager(), -1, buddy);
SpectrumBuddy *s_buddy = (SpectrumBuddy *) buddy->node.ui_data;
s_buddy->setFlags(BUDDY_JID_ESCAPING);
}
}
static void buddyStatusChanged(PurpleBuddy *buddy, PurpleStatus *status, PurpleStatus *old_status) {
SpectrumBuddy *s_buddy = (SpectrumBuddy *) buddy->node.ui_data;
PurpleAccount *account = purple_buddy_get_account(buddy);
User *user = (User *) account->ui_data;
if (!user || !s_buddy)
return;
s_buddy->buddyChanged();
}
static void buddySignedOn(PurpleBuddy *buddy) {
SpectrumBuddy *s_buddy = (SpectrumBuddy *) buddy->node.ui_data;
PurpleAccount *account = purple_buddy_get_account(buddy);
User *user = (User *) account->ui_data;
if (!user || !s_buddy)
return;
s_buddy->buddyChanged();
}
static void buddySignedOff(PurpleBuddy *buddy) {
SpectrumBuddy *s_buddy = (SpectrumBuddy *) buddy->node.ui_data;
PurpleAccount *account = purple_buddy_get_account(buddy);
User *user = (User *) account->ui_data;
if (!user || !s_buddy)
return;
s_buddy->buddyChanged();
}
static void NodeRemoved(PurpleBlistNode *node, void *data) {
if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
return;
PurpleBuddy *buddy = (PurpleBuddy *) node;
// PurpleAccount *account = purple_buddy_get_account(buddy);
// User *user = (User *) account->ui_data;
if (buddy->node.ui_data) {
SpectrumBuddy *s_buddy = (SpectrumBuddy *) buddy->node.ui_data;
s_buddy->removeBuddy(buddy);
buddy->node.ui_data = NULL;
if (s_buddy->getBuddiesCount() == 0) {
delete s_buddy;
}
}
}
static PurpleBlistUiOps blistUiOps =
{
NULL,
buddyListNewNode,
NULL,
NULL, // buddyListUpdate,
NULL, //NodeRemoved,
NULL,
NULL,
NULL, // buddyListAddBuddy,
NULL,
NULL,
NULL, //buddyListSaveNode,
NULL, //buddyListRemoveNode,
NULL, //buddyListSaveAccount,
NULL
};
static void conv_new(PurpleConversation *conv) {
PurpleAccount *account = purple_conversation_get_account(conv);
User *user = (User *) account->ui_data;
if (!user)
return;
std::string name = purple_conversation_get_name(conv);
size_t pos = name.find("/");
if (pos != std::string::npos)
name.erase((int) pos, name.length() - (int) pos);
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());
char *striped = purple_markup_strip_html(message);
msg->setBody(message);
g_free(striped);
s_conv->handleMessage(msg);
}
static PurpleConversationUiOps conversation_ui_ops =
{
conv_new,
conv_destroy,
NULL,//conv_write_chat, /* write_chat */
conv_write_im, /* write_im */
NULL,//conv_write_conv, /* write_conv */
NULL,//conv_chat_add_users, /* chat_add_users */
NULL,//conv_chat_rename_user, /* chat_rename_user */
NULL,//conv_chat_remove_users, /* chat_remove_users */
NULL,//pidgin_conv_chat_update_user, /* chat_update_user */
NULL,//pidgin_conv_present_conversation, /* present */
NULL,//pidgin_conv_has_focus, /* has_focus */
NULL,//pidgin_conv_custom_smiley_add, /* custom_smiley_add */
NULL,//pidgin_conv_custom_smiley_write, /* custom_smiley_write */
NULL,//pidgin_conv_custom_smiley_close, /* custom_smiley_close */
NULL,//pidgin_conv_send_confirm, /* send_confirm */
NULL,
NULL,
NULL,
NULL
};
static void connection_report_disconnect(PurpleConnection *gc, PurpleConnectionError reason, const char *text){
PurpleAccount *account = purple_connection_get_account(gc);
User *user = (User *) account->ui_data;
if (!user)
return;
user->handleDisconnected(text);
}
static PurpleConnectionUiOps conn_ui_ops =
{
NULL,
NULL,
NULL,//connection_disconnected,
NULL,
NULL,
NULL,
NULL,
connection_report_disconnect,
NULL,
NULL,
NULL
};
static void transport_core_ui_init(void)
{
purple_blist_set_ui_ops(&blistUiOps);
// purple_accounts_set_ui_ops(&accountUiOps);
// purple_notify_set_ui_ops(&notifyUiOps);
// purple_request_set_ui_ops(&requestUiOps);
// purple_xfers_set_ui_ops(getXferUiOps());
purple_connections_set_ui_ops(&conn_ui_ops);
purple_conversations_set_ui_ops(&conversation_ui_ops);
// #ifndef WIN32
// purple_dnsquery_set_ui_ops(getDNSUiOps());
// #endif
}
static PurpleCoreUiOps coreUiOps =
{
NULL,
// debug_init,
NULL,
transport_core_ui_init,
NULL,
NULL,
NULL,
NULL,
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("./");
remove("./accounts.xml");
remove("./blist.xml");
// if (m_configuration.logAreas & LOG_AREA_PURPLE)
purple_debug_set_ui_ops(&debugUiOps);
purple_core_set_ui_ops(&coreUiOps);
purple_eventloop_set_ui_ops(getEventLoopUiOps());
ret = purple_core_init("spectrum");
if (ret) {
static int conversation_handle;
static int conn_handle;
static int blist_handle;
purple_set_blist(purple_blist_new());
purple_blist_load();
purple_prefs_load();
/* Good default preferences */
/* The combination of these two settings mean that libpurple will never
* (of its own accord) set all the user accounts idle.
*/
purple_prefs_set_bool("/purple/away/away_when_idle", false);
/*
* This must be set to something not "none" for idle reporting to work
* for, e.g., the OSCAR prpl. We don't implement the UI ops, so this is
* okay for now.
*/
purple_prefs_set_string("/purple/away/idle_reporting", "system");
/* Disable all logging */
purple_prefs_set_bool("/purple/logging/log_ims", false);
purple_prefs_set_bool("/purple/logging/log_chats", false);
purple_prefs_set_bool("/purple/logging/log_system", false);
// purple_signal_connect(purple_conversations_get_handle(), "received-im-msg", &conversation_handle, PURPLE_CALLBACK(newMessageReceived), NULL);
// purple_signal_connect(purple_conversations_get_handle(), "buddy-typing", &conversation_handle, PURPLE_CALLBACK(buddyTyping), NULL);
// purple_signal_connect(purple_conversations_get_handle(), "buddy-typed", &conversation_handle, PURPLE_CALLBACK(buddyTyped), NULL);
// purple_signal_connect(purple_conversations_get_handle(), "buddy-typing-stopped", &conversation_handle, PURPLE_CALLBACK(buddyTypingStopped), NULL);
// purple_signal_connect(purple_connections_get_handle(), "signed-on", &conn_handle,PURPLE_CALLBACK(signed_on), NULL);
// purple_signal_connect(purple_blist_get_handle(), "buddy-removed", &blist_handle,PURPLE_CALLBACK(buddyRemoved), NULL);
purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", &blist_handle,PURPLE_CALLBACK(buddySignedOn), NULL);
purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", &blist_handle,PURPLE_CALLBACK(buddySignedOff), NULL);
purple_signal_connect(purple_blist_get_handle(), "buddy-status-changed", &blist_handle,PURPLE_CALLBACK(buddyStatusChanged), NULL);
purple_signal_connect(purple_blist_get_handle(), "blist-node-removed", &blist_handle,PURPLE_CALLBACK(NodeRemoved), NULL);
// purple_signal_connect(purple_conversations_get_handle(), "chat-topic-changed", &conversation_handle, PURPLE_CALLBACK(conv_chat_topic_changed), NULL);
//
// purple_commands_init();
}
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));
_logger->setRosterManager(user->getRosterManager());
// 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);
}
}
class SpectrumFactory : public Factory {
public:
Conversation *createConversation(ConversationManager *conversationManager, const std::string &legacyName) {
PurpleConversation *conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, (PurpleAccount *) conversationManager->getUser()->getData() , legacyName.c_str());
return (Conversation *) conv->ui_data;
}
Buddy *createBuddy(RosterManager *rosterManager, const BuddyInfo &buddyInfo) {
PurpleAccount *account = (PurpleAccount *) rosterManager->getUser()->getData();
std::string group = buddyInfo.groups[0];
PurpleGroup *g = purple_find_group(group.c_str());
if (!g) {
g = purple_group_new(group.c_str());
purple_blist_add_group(g, NULL);
}
PurpleBuddy *buddy = purple_find_buddy_in_group(account, buddyInfo.legacyName.c_str(), g);
if (!buddy) {
// create contact
PurpleContact *contact = purple_contact_new();
purple_blist_add_contact(contact, g, NULL);
// create buddy
buddy = purple_buddy_new(account, buddyInfo.legacyName.c_str(), buddyInfo.alias.c_str());
purple_blist_add_buddy(buddy, contact, g, NULL);
purple_blist_server_alias_buddy(buddy, buddyInfo.alias.c_str());
}
return (Buddy *) buddy->node.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";
std::cout << "verze\n";
g_option_context_free(context);
return 0;
}
if (argc != 2) {
#ifdef WIN32
std::cout << "Usage: spectrum.exe <configuration_file.cfg>\n";
#else
#if GLIB_CHECK_VERSION(2,14,0)
std::cout << g_option_context_get_help(context, FALSE, NULL);
#else
std::cout << "Usage: spectrum <configuration_file.cfg>\n";
std::cout << "See \"man spectrum\" for more info.\n";
#endif
#endif
}
else {
#ifndef WIN32
// signal(SIGPIPE, SIG_IGN);
//
// if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
// std::cout << "SIGCHLD handler can't be set\n";
// g_option_context_free(context);
// return -1;
// }
//
// if (signal(SIGINT, spectrum_sigint_handler) == SIG_ERR) {
// std::cout << "SIGINT handler can't be set\n";
// g_option_context_free(context);
// return -1;
// }
//
// if (signal(SIGTERM, spectrum_sigterm_handler) == SIG_ERR) {
// std::cout << "SIGTERM handler can't be set\n";
// g_option_context_free(context);
// return -1;
// }
//
// struct sigaction sa;
// memset(&sa, 0, sizeof(sa));
// sa.sa_handler = spectrum_sighup_handler;
// if (sigaction(SIGHUP, &sa, NULL)) {
// std::cout << "SIGHUP handler can't be set\n";
// g_option_context_free(context);
// 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;
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));
UserRegistration userRegistration(&transport, &userManager, &sql);
logger.setUserRegistration(&userRegistration);
logger.setUserManager(&userManager);
transport.connect();
eventLoop.run();
}
g_option_context_free(context);
}
#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/networkpluginserver.h"
#include "Swiften/EventLoop/SimpleEventLoop.h"
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, 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);
NetworkPluginServer plugin(&transport, &config, &userManager);
transport.connect();
eventLoop.run();
}

View file

@ -3,8 +3,9 @@ jid = icq.localhost
password = secret
server = 127.0.0.1
port = 5222
server_mode = 1
backend=../../backends/libpurple/libpurple_backend
protocol=prpl-jabber
server_mode=1
[database]
database = test.sql

View file

@ -2,12 +2,16 @@ cmake_minimum_required(VERSION 2.6)
FILE(GLOB SRC *.cpp *.h)
FILE(GLOB HEADERS ../../include/transport/*.h)
if (PROTOBUF_FOUND)
PROTOBUF_GENERATE_CPP(PROTOBUF_SRC PROTOBUF_HDRS "pbnetwork.proto")
endif()
# SOURCE_GROUP(headers FILES ${HEADERS})
ADD_LIBRARY(transport SHARED ${HEADERS} ${SRC})
ADD_LIBRARY(transport SHARED ${HEADERS} ${SRC} ${PROTOBUF_SRC} ${PROTOBUF_HDRS})
ADD_DEFINITIONS(-fPIC)
TARGET_LINK_LIBRARIES(transport -lresolv -lidn -lz -lpthread -lexpat -lidn -lz -lssl -lcrypto -lexpat -lresolv -lc -lxml2 ${Boost_LIBRARIES} ${SQLITE3_LIBRARIES} ${SWIFTEN_LIBRARY})
TARGET_LINK_LIBRARIES(transport -lresolv -lidn -lz -lpthread -lexpat -lidn -lz -lssl -lcrypto -lexpat -lresolv -lc -lxml2 ${Boost_LIBRARIES} ${SQLITE3_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES})
SET_TARGET_PROPERTIES(transport PROPERTIES
VERSION ${TRANSPORT_VERSION} SOVERSION ${TRANSPORT_VERSION}

View file

@ -26,7 +26,7 @@
namespace Transport {
Buddy::Buddy(RosterManager *rosterManager, long id) : m_id(id), m_online(false), m_subscription("ask"), m_flags(BUDDY_NO_FLAG), m_rosterManager(rosterManager){
m_rosterManager->setBuddy(this);
// m_rosterManager->setBuddy(this);
}
Buddy::~Buddy() {

View file

@ -35,6 +35,7 @@ bool Config::load(const std::string &configfile, boost::program_options::options
("service.server", value<std::string>()->default_value(""), "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.backend", value<std::string>()->default_value("libpurple_backend"), "Backend")
("service.protocol", value<std::string>()->default_value(""), "Protocol")
("service.allowed_servers", value<std::string>()->default_value(""), "Only users from these servers can connect")
("service.server_mode", value<bool>()->default_value(false), "True if Spectrum should behave as server")
@ -51,6 +52,8 @@ bool Config::load(const std::string &configfile, boost::program_options::options
store(parse_config_file(ifs, opts), m_variables);
notify(m_variables);
m_file = configfile;
onConfigReloaded();
return true;

View file

@ -160,6 +160,9 @@ void NetworkPlugin::handleDataRead(const Swift::ByteArray &data) {
case pbnetwork::WrapperMessage_Type_TYPE_LOGOUT:
handleLogoutPayload(wrapper.payload());
break;
case pbnetwork::WrapperMessage_Type_TYPE_PING:
sendPong();
break;
default:
return;
}
@ -178,4 +181,14 @@ void NetworkPlugin::send(const std::string &data) {
m_conn->write(Swift::ByteArray(header + data));
}
void NetworkPlugin::sendPong() {
std::string message;
pbnetwork::WrapperMessage wrap;
wrap.set_type(pbnetwork::WrapperMessage_Type_TYPE_PONG);
wrap.SerializeToString(&message);
send(message);
std::cout << "SENDING PONG\n";
}
}

View file

@ -73,9 +73,13 @@ static void handleBuddyPayload(LocalBuddy *buddy, const pbnetwork::Buddy &payloa
NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, UserManager *userManager) {
m_userManager = userManager;
m_config = config;
m_pongReceived = false;
m_userManager->onUserCreated.connect(boost::bind(&NetworkPluginServer::handleUserCreated, this, _1));
m_userManager->onUserDestroyed.connect(boost::bind(&NetworkPluginServer::handleUserDestroyed, this, _1));
m_pingTimer = component->getFactories()->getTimerFactory()->createTimer(10000);
m_pingTimer->onTick.connect(boost::bind(&NetworkPluginServer::pingTimeout, this));
m_server = component->getFactories()->getConnectionFactory()->createConnectionServer(10000);
m_server->onNewConnection.connect(boost::bind(&NetworkPluginServer::handleNewClientConnection, this, _1));
m_server->start();
@ -86,7 +90,7 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U
}
NetworkPluginServer::~NetworkPluginServer() {
m_pingTimer->stop();
}
void NetworkPluginServer::handleNewClientConnection(boost::shared_ptr<Swift::Connection> c) {
@ -94,15 +98,21 @@ void NetworkPluginServer::handleNewClientConnection(boost::shared_ptr<Swift::Con
c->disconnect();
}
m_client = c;
m_pongReceived = false;
c->onDisconnected.connect(boost::bind(&NetworkPluginServer::handleSessionFinished, this, c));
c->onDataRead.connect(boost::bind(&NetworkPluginServer::handleDataRead, this, c, _1));
sendPing();
m_pingTimer->start();
}
void NetworkPluginServer::handleSessionFinished(boost::shared_ptr<Swift::Connection> c) {
if (c == m_client) {
m_client.reset();
}
m_pingTimer->stop();
exec_(CONFIG_STRING(m_config, "service.backend").c_str(), "localhost", "10000", m_config->getConfigFile().c_str());
}
void NetworkPluginServer::handleConnectedPayload(const std::string &data) {
@ -187,6 +197,9 @@ void NetworkPluginServer::handleDataRead(boost::shared_ptr<Swift::Connection> c,
case pbnetwork::WrapperMessage_Type_TYPE_BUDDY_CHANGED:
handleBuddyChangedPayload(wrapper.payload());
break;
case pbnetwork::WrapperMessage_Type_TYPE_PONG:
m_pongReceived = true;
break;
default:
return;
}
@ -201,6 +214,17 @@ void NetworkPluginServer::send(boost::shared_ptr<Swift::Connection> &c, const st
c->write(Swift::ByteArray(header + data));
}
void NetworkPluginServer::pingTimeout() {
std::cout << "pingtimeout\n";
if (m_pongReceived) {
sendPing();
m_pingTimer->start();
}
else {
exec_(CONFIG_STRING(m_config, "service.backend").c_str(), "localhost", "10000", m_config->getConfigFile().c_str());
}
}
void NetworkPluginServer::handleUserCreated(User *user) {
// UserInfo userInfo = user->getUserInfo();
user->onReadyToConnect.connect(boost::bind(&NetworkPluginServer::handleUserReadyToConnect, this, user));
@ -233,8 +257,20 @@ void NetworkPluginServer::handleUserDestroyed(User *user) {
logout.SerializeToString(&message);
WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_LOGOUT);
send(m_client, message);
}
void NetworkPluginServer::sendPing() {
std::string message;
pbnetwork::WrapperMessage wrap;
wrap.set_type(pbnetwork::WrapperMessage_Type_TYPE_PING);
wrap.SerializeToString(&message);
send(m_client, message);
m_pongReceived = false;
std::cout << "SENDING PING\n";
}
}

View file

@ -55,8 +55,10 @@ message WrapperMessage {
TYPE_CONV_CREATED = 8;
TYPE_CONV_WRITE = 9;
TYPE_CONV_REMOVED = 10;
TYPE_PING = 11;
TYPE_PONG = 12;
}
required Type type = 1;
required bytes payload = 2;
optional bytes payload = 2;
}
;

View file

@ -37,20 +37,25 @@ RosterManager::RosterManager(User *user, Component *component){
m_user = user;
m_component = component;
m_setBuddyTimer = m_component->getFactories()->getTimerFactory()->createTimer(1000);
m_RIETimer = m_component->getFactories()->getTimerFactory()->createTimer(3000);
m_RIETimer = m_component->getFactories()->getTimerFactory()->createTimer(5000);
m_RIETimer->onTick.connect(boost::bind(&RosterManager::sendRIE, this));
}
RosterManager::~RosterManager() {
m_setBuddyTimer->stop();
m_RIETimer->stop();
for (std::map<std::string, Buddy *>::const_iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
Buddy *buddy = (*it).second;
delete buddy;
}
if (m_rosterStorage)
delete m_rosterStorage;
}
void RosterManager::setBuddy(Buddy *buddy) {
m_setBuddyTimer->onTick.connect(boost::bind(&RosterManager::setBuddyCallback, this, buddy));
m_setBuddyTimer->start();
// m_setBuddyTimer->onTick.connect(boost::bind(&RosterManager::setBuddyCallback, this, buddy));
// m_setBuddyTimer->start();
setBuddyCallback(buddy);
}
void RosterManager::sendBuddyRosterPush(Buddy *buddy) {
@ -70,6 +75,7 @@ void RosterManager::sendBuddyRosterPush(Buddy *buddy) {
void RosterManager::setBuddyCallback(Buddy *buddy) {
m_setBuddyTimer->onTick.disconnect(boost::bind(&RosterManager::setBuddyCallback, this, buddy));
std::cout << "ADDING " << buddy->getName() << "\n";
m_buddies[buddy->getName()] = buddy;
onBuddySet(buddy);
@ -79,13 +85,11 @@ void RosterManager::setBuddyCallback(Buddy *buddy) {
sendBuddyRosterPush(buddy);
}
else {
}
if (m_setBuddyTimer->onTick.empty()) {
m_setBuddyTimer->stop();
if (true /*&& rie_is_supported*/) {
m_RIETimer->start();
if (m_setBuddyTimer->onTick.empty()) {
m_setBuddyTimer->stop();
if (true /*&& rie_is_supported*/) {
m_RIETimer->start();
}
}
}

View file

@ -76,6 +76,15 @@ SQLite3Backend::~SQLite3Backend(){
// But requires SQLite3 >= 3.6.0 beta
FINALIZE_STMT(m_setUser);
FINALIZE_STMT(m_getUser);
FINALIZE_STMT(m_removeUser);
FINALIZE_STMT(m_removeUserBuddies);
FINALIZE_STMT(m_removeUserSettings);
FINALIZE_STMT(m_removeUserBuddiesSettings);
FINALIZE_STMT(m_addBuddy);
FINALIZE_STMT(m_updateBuddy);
FINALIZE_STMT(m_getBuddies);
FINALIZE_STMT(m_getBuddiesSettings);
sqlite3_close(m_db);
}
}