From e8b61aa9b6fd6d9e890f8972dd7fbf3d972842f8 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Fri, 13 May 2011 10:54:03 +0200 Subject: [PATCH] pinging backends --- CMakeLists.txt | 1 + backends/libpurple/main.cpp | 2 +- cmake_modules/ProtobufConfig.cmake | 30 ++ examples/CMakeLists.txt | 4 + include/transport/config.h | 3 + include/transport/networkplugin.h | 1 + include/transport/networkpluginserver.h | 5 + spectrum/src/main.cpp | 622 ++---------------------- spectrum/src/sample.cfg | 3 +- src/CMakeLists.txt | 8 +- src/buddy.cpp | 2 +- src/config.cpp | 3 + src/networkplugin.cpp | 13 + src/networkpluginserver.cpp | 40 +- src/pbnetwork.proto | 4 +- src/rostermanager.cpp | 24 +- src/sqlite3backend.cpp | 9 + 17 files changed, 173 insertions(+), 601 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3eecd799..afe32f6a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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") diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index afd84e86..a8966e01 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -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) { diff --git a/cmake_modules/ProtobufConfig.cmake b/cmake_modules/ProtobufConfig.cmake index 1cd59e78..bfc1a2d0 100644 --- a/cmake_modules/ProtobufConfig.cmake +++ b/cmake_modules/ProtobufConfig.cmake @@ -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) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index d2430311..8d793b28 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,2 +1,6 @@ ADD_SUBDIRECTORY(server_connect) ADD_SUBDIRECTORY(usermanager) + +if (PROTOBUF_FOUND) + ADD_SUBDIRECTORY(external_network_plugin) +endif() diff --git a/include/transport/config.h b/include/transport/config.h index fe4ddfa4..dff687d8 100644 --- a/include/transport/config.h +++ b/include/transport/config.h @@ -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 onConfigReloaded; private: Variables m_variables; + std::string m_file; }; } diff --git a/include/transport/networkplugin.h b/include/transport/networkplugin.h index 8d894e03..646b500e 100644 --- a/include/transport/networkplugin.h +++ b/include/transport/networkplugin.h @@ -58,6 +58,7 @@ class NetworkPlugin { void handleDisconnected(); void send(const std::string &data); + void sendPong(); std::string m_data; std::string m_host; diff --git a/include/transport/networkpluginserver.h b/include/transport/networkpluginserver.h index d086d971..9649289c 100644 --- a/include/transport/networkpluginserver.h +++ b/include/transport/networkpluginserver.h @@ -58,12 +58,17 @@ class NetworkPluginServer { void send(boost::shared_ptr &, 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 m_server; boost::shared_ptr m_client; + bool m_pongReceived; + Swift::Timer::ref m_pingTimer; }; } diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index 6e54a927..6edd0e76 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -1,583 +1,39 @@ -#include "glib.h" -#include "purple.h" -#include - -#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 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(¬ifyUiOps); -// 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 &settings = Transport::instance()->getConfiguration().purple_account_settings; -// for (std::map ::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 \n"; -#else - -#if GLIB_CHECK_VERSION(2,14,0) - std::cout << g_option_context_get_help(context, FALSE, NULL); -#else - std::cout << "Usage: spectrum \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(); +} diff --git a/spectrum/src/sample.cfg b/spectrum/src/sample.cfg index 5daa303e..1c2a05a9 100644 --- a/spectrum/src/sample.cfg +++ b/spectrum/src/sample.cfg @@ -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 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4ab9c183..6153a1f3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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} diff --git a/src/buddy.cpp b/src/buddy.cpp index 5dac52b4..f72b7bf4 100644 --- a/src/buddy.cpp +++ b/src/buddy.cpp @@ -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() { diff --git a/src/config.cpp b/src/config.cpp index 0c6603c5..6e8499cf 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -35,6 +35,7 @@ bool Config::load(const std::string &configfile, boost::program_options::options ("service.server", value()->default_value(""), "Server to connect to") ("service.password", value()->default_value(""), "Password used to auth the server") ("service.port", value()->default_value(0), "Port the server is listening on") + ("service.backend", value()->default_value("libpurple_backend"), "Backend") ("service.protocol", value()->default_value(""), "Protocol") ("service.allowed_servers", value()->default_value(""), "Only users from these servers can connect") ("service.server_mode", value()->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; diff --git a/src/networkplugin.cpp b/src/networkplugin.cpp index ab2b6992..bfdaef20 100644 --- a/src/networkplugin.cpp +++ b/src/networkplugin.cpp @@ -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"; +} + } diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index a08cdcd6..69d462ff 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -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 c) { @@ -94,15 +98,21 @@ void NetworkPluginServer::handleNewClientConnection(boost::shared_ptrdisconnect(); } 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 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 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 &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"; +} + } diff --git a/src/pbnetwork.proto b/src/pbnetwork.proto index 1a282492..47321f61 100644 --- a/src/pbnetwork.proto +++ b/src/pbnetwork.proto @@ -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; } ; \ No newline at end of file diff --git a/src/rostermanager.cpp b/src/rostermanager.cpp index e3a546f9..665be1b6 100644 --- a/src/rostermanager.cpp +++ b/src/rostermanager.cpp @@ -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::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(); + } } } diff --git a/src/sqlite3backend.cpp b/src/sqlite3backend.cpp index 0d7c8e29..043fcef4 100644 --- a/src/sqlite3backend.cpp +++ b/src/sqlite3backend.cpp @@ -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); } }