first part of networkpluginserver
This commit is contained in:
parent
ac1b0af209
commit
1105d3f1e3
22 changed files with 3575 additions and 19 deletions
3
backends/CMakeLists.txt
Normal file
3
backends/CMakeLists.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
if (PROTOBUF_FOUND)
|
||||
ADD_SUBDIRECTORY(libpurple)
|
||||
endif()
|
7
backends/libpurple/CMakeLists.txt
Normal file
7
backends/libpurple/CMakeLists.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
FILE(GLOB SRC *.cpp)
|
||||
|
||||
ADD_EXECUTABLE(libpurple_backend ${SRC})
|
||||
|
||||
target_link_libraries(libpurple_backend ${PURPLE_LIBRARY} ${GLIB2_LIBRARIES} ${EVENT_LIBRARIES} transport)
|
||||
|
249
backends/libpurple/geventloop.cpp
Normal file
249
backends/libpurple/geventloop.cpp
Normal file
|
@ -0,0 +1,249 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#include "geventloop.h"
|
||||
#ifdef _WIN32
|
||||
#include "win32/win32dep.h"
|
||||
#endif
|
||||
#ifdef WITH_LIBEVENT
|
||||
#include "event.h"
|
||||
#endif
|
||||
|
||||
typedef struct _PurpleIOClosure {
|
||||
PurpleInputFunction function;
|
||||
guint result;
|
||||
gpointer data;
|
||||
#ifdef WITH_LIBEVENT
|
||||
GSourceFunc function2;
|
||||
struct timeval timeout;
|
||||
struct event evfifo;
|
||||
#endif
|
||||
} PurpleIOClosure;
|
||||
|
||||
static gboolean io_invoke(GIOChannel *source,
|
||||
GIOCondition condition,
|
||||
gpointer data)
|
||||
{
|
||||
PurpleIOClosure *closure = (PurpleIOClosure* )data;
|
||||
PurpleInputCondition purple_cond = (PurpleInputCondition)0;
|
||||
|
||||
int tmp = 0;
|
||||
if (condition & READ_COND)
|
||||
{
|
||||
tmp |= PURPLE_INPUT_READ;
|
||||
purple_cond = (PurpleInputCondition)tmp;
|
||||
}
|
||||
if (condition & WRITE_COND)
|
||||
{
|
||||
tmp |= PURPLE_INPUT_WRITE;
|
||||
purple_cond = (PurpleInputCondition)tmp;
|
||||
}
|
||||
|
||||
closure->function(closure->data, g_io_channel_unix_get_fd(source), purple_cond);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void io_destroy(gpointer data)
|
||||
{
|
||||
g_free(data);
|
||||
}
|
||||
|
||||
static guint input_add(gint fd,
|
||||
PurpleInputCondition condition,
|
||||
PurpleInputFunction function,
|
||||
gpointer data)
|
||||
{
|
||||
PurpleIOClosure *closure = g_new0(PurpleIOClosure, 1);
|
||||
GIOChannel *channel;
|
||||
GIOCondition cond = (GIOCondition)0;
|
||||
closure->function = function;
|
||||
closure->data = data;
|
||||
|
||||
int tmp = 0;
|
||||
if (condition & PURPLE_INPUT_READ)
|
||||
{
|
||||
tmp |= READ_COND;
|
||||
cond = (GIOCondition)tmp;
|
||||
}
|
||||
if (condition & PURPLE_INPUT_WRITE)
|
||||
{
|
||||
tmp |= WRITE_COND;
|
||||
cond = (GIOCondition)tmp;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
channel = wpurple_g_io_channel_win32_new_socket(fd);
|
||||
#else
|
||||
channel = g_io_channel_unix_new(fd);
|
||||
#endif
|
||||
closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond,
|
||||
io_invoke, closure, io_destroy);
|
||||
|
||||
g_io_channel_unref(channel);
|
||||
return closure->result;
|
||||
}
|
||||
|
||||
static PurpleEventLoopUiOps eventLoopOps =
|
||||
{
|
||||
g_timeout_add,
|
||||
g_source_remove,
|
||||
input_add,
|
||||
g_source_remove,
|
||||
NULL,
|
||||
#if GLIB_CHECK_VERSION(2,14,0)
|
||||
g_timeout_add_seconds,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
#ifdef WITH_LIBEVENT
|
||||
|
||||
static GHashTable *events = NULL;
|
||||
static unsigned long id = 0;
|
||||
|
||||
static void event_io_destroy(gpointer data)
|
||||
{
|
||||
PurpleIOClosure *closure = (PurpleIOClosure* )data;
|
||||
event_del(&closure->evfifo);
|
||||
g_free(data);
|
||||
}
|
||||
|
||||
static void event_io_invoke(int fd, short event, void *data)
|
||||
{
|
||||
PurpleIOClosure *closure = (PurpleIOClosure* )data;
|
||||
PurpleInputCondition purple_cond = (PurpleInputCondition)0;
|
||||
int tmp = 0;
|
||||
if (event & EV_READ)
|
||||
{
|
||||
tmp |= PURPLE_INPUT_READ;
|
||||
purple_cond = (PurpleInputCondition)tmp;
|
||||
}
|
||||
if (event & EV_WRITE)
|
||||
{
|
||||
tmp |= PURPLE_INPUT_WRITE;
|
||||
purple_cond = (PurpleInputCondition)tmp;
|
||||
}
|
||||
if (event & EV_TIMEOUT)
|
||||
{
|
||||
// tmp |= PURPLE_INPUT_WRITE;
|
||||
// purple_cond = (PurpleInputCondition)tmp;
|
||||
if (closure->function2(closure->data))
|
||||
evtimer_add(&closure->evfifo, &closure->timeout);
|
||||
// else
|
||||
// event_io_destroy(data);
|
||||
return;
|
||||
}
|
||||
|
||||
closure->function(closure->data, fd, purple_cond);
|
||||
}
|
||||
|
||||
static gboolean event_input_remove(guint handle)
|
||||
{
|
||||
PurpleIOClosure *closure = (PurpleIOClosure *) g_hash_table_lookup(events, &handle);
|
||||
if (closure)
|
||||
event_io_destroy(closure);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint event_input_add(gint fd,
|
||||
PurpleInputCondition condition,
|
||||
PurpleInputFunction function,
|
||||
gpointer data)
|
||||
{
|
||||
PurpleIOClosure *closure = g_new0(PurpleIOClosure, 1);
|
||||
GIOChannel *channel;
|
||||
GIOCondition cond = (GIOCondition)0;
|
||||
closure->function = function;
|
||||
closure->data = data;
|
||||
|
||||
int tmp = EV_PERSIST;
|
||||
if (condition & PURPLE_INPUT_READ)
|
||||
{
|
||||
tmp |= EV_READ;
|
||||
}
|
||||
if (condition & PURPLE_INPUT_WRITE)
|
||||
{
|
||||
tmp |= EV_WRITE;
|
||||
}
|
||||
|
||||
event_set(&closure->evfifo, fd, tmp, event_io_invoke, closure);
|
||||
event_add(&closure->evfifo, NULL);
|
||||
|
||||
int *f = (int *) g_malloc(sizeof(int));
|
||||
*f = id;
|
||||
id++;
|
||||
g_hash_table_replace(events, f, closure);
|
||||
|
||||
return *f;
|
||||
}
|
||||
|
||||
static guint event_timeout_add (guint interval, GSourceFunc function, gpointer data) {
|
||||
struct timeval timeout;
|
||||
PurpleIOClosure *closure = g_new0(PurpleIOClosure, 1);
|
||||
closure->function2 = function;
|
||||
closure->data = data;
|
||||
|
||||
timeout.tv_sec = interval/1000;
|
||||
timeout.tv_usec = (interval%1000)*1000;
|
||||
evtimer_set(&closure->evfifo, event_io_invoke, closure);
|
||||
evtimer_add(&closure->evfifo, &timeout);
|
||||
closure->timeout = timeout;
|
||||
|
||||
guint *f = (guint *) g_malloc(sizeof(guint));
|
||||
*f = id;
|
||||
id++;
|
||||
g_hash_table_replace(events, f, closure);
|
||||
return *f;
|
||||
}
|
||||
|
||||
static PurpleEventLoopUiOps libEventLoopOps =
|
||||
{
|
||||
event_timeout_add,
|
||||
event_input_remove,
|
||||
event_input_add,
|
||||
event_input_remove,
|
||||
NULL,
|
||||
// #if GLIB_CHECK_VERSION(2,14,0)
|
||||
// g_timeout_add_seconds,
|
||||
// #else
|
||||
NULL,
|
||||
// #endif
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
#endif /* WITH_LIBEVENT*/
|
||||
|
||||
PurpleEventLoopUiOps * getEventLoopUiOps(void){
|
||||
return &eventLoopOps;
|
||||
#ifdef WITH_LIBEVENT
|
||||
std::cout << "EPOLL\n";
|
||||
events = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
|
||||
return &libEventLoopOps;
|
||||
#endif
|
||||
}
|
33
backends/libpurple/geventloop.h
Normal file
33
backends/libpurple/geventloop.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _HI_EVENTLOOP_H
|
||||
#define _HI_EVENTLOOP_H
|
||||
|
||||
#include <glib.h>
|
||||
#include "purple.h"
|
||||
#include "eventloop.h"
|
||||
|
||||
#define READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR)
|
||||
#define WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
|
||||
|
||||
PurpleEventLoopUiOps * getEventLoopUiOps(void);
|
||||
|
||||
#endif
|
566
backends/libpurple/main.cpp
Normal file
566
backends/libpurple/main.cpp
Normal file
|
@ -0,0 +1,566 @@
|
|||
#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 "transport/networkplugin.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;
|
||||
|
||||
class SpectrumNetworkPlugin;
|
||||
|
||||
Logger *_logger;
|
||||
SpectrumNetworkPlugin *np;
|
||||
|
||||
static gboolean nodaemon = FALSE;
|
||||
static gchar *logfile = NULL;
|
||||
static gchar *lock_file = NULL;
|
||||
static gchar *host = NULL;
|
||||
static int port = 10000;
|
||||
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 },
|
||||
{ "host", 'h', 0, G_OPTION_ARG_STRING, &host, "Host to connect to", NULL },
|
||||
{ "port", 'p', 0, G_OPTION_ARG_INT, &port, "Port to connect to", NULL },
|
||||
{ NULL, 0, 0, G_OPTION_ARG_NONE, NULL, "", NULL }
|
||||
};
|
||||
|
||||
class SpectrumNetworkPlugin : public NetworkPlugin {
|
||||
public:
|
||||
SpectrumNetworkPlugin(Config *config, SpectrumEventLoop *loop, const std::string &host, int port) : NetworkPlugin(loop, host, port) {
|
||||
this->config = config;
|
||||
}
|
||||
|
||||
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
|
||||
PurpleAccount *account = NULL;
|
||||
const char *protocol = CONFIG_STRING(config, "service.protocol").c_str();
|
||||
if (purple_accounts_find(legacyName.c_str(), protocol) != NULL){
|
||||
Log(user, "this account already exists");
|
||||
account = purple_accounts_find(legacyName.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(user, "creating new account");
|
||||
account = purple_account_new(legacyName.c_str(), protocol);
|
||||
|
||||
purple_accounts_add(account);
|
||||
}
|
||||
|
||||
purple_account_set_password(account, password.c_str());
|
||||
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);
|
||||
}
|
||||
m_accounts[account] = user;
|
||||
}
|
||||
|
||||
void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
|
||||
const char *protocol = CONFIG_STRING(config, "service.protocol").c_str();
|
||||
PurpleAccount *account = purple_accounts_find(legacyName.c_str(), protocol);
|
||||
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);
|
||||
}
|
||||
|
||||
g_free(account->ui_data);
|
||||
account->ui_data = NULL;
|
||||
m_accounts.erase(account);
|
||||
}
|
||||
}
|
||||
|
||||
std::map<PurpleAccount *, std::string> m_accounts;
|
||||
private:
|
||||
Config *config;
|
||||
};
|
||||
|
||||
static std::string getAlias(PurpleBuddy *m_buddy) {
|
||||
std::string alias;
|
||||
if (purple_buddy_get_server_alias(m_buddy))
|
||||
alias = (std::string) purple_buddy_get_server_alias(m_buddy);
|
||||
else
|
||||
alias = (std::string) purple_buddy_get_alias(m_buddy);
|
||||
return alias;
|
||||
}
|
||||
|
||||
static std::string getName(PurpleBuddy *m_buddy) {
|
||||
std::string name(purple_buddy_get_name(m_buddy));
|
||||
if (name.empty()) {
|
||||
Log("getName", "Name is EMPTY!");
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
static bool getStatus(PurpleBuddy *m_buddy, Swift::StatusShow &status, std::string &statusMessage) {
|
||||
PurplePresence *pres = purple_buddy_get_presence(m_buddy);
|
||||
if (pres == NULL)
|
||||
return false;
|
||||
PurpleStatus *stat = purple_presence_get_active_status(pres);
|
||||
if (stat == NULL)
|
||||
return false;
|
||||
int st = purple_status_type_get_primitive(purple_status_get_type(stat));
|
||||
|
||||
switch(st) {
|
||||
case PURPLE_STATUS_AVAILABLE: {
|
||||
break;
|
||||
}
|
||||
case PURPLE_STATUS_AWAY: {
|
||||
status = Swift::StatusShow::Away;
|
||||
break;
|
||||
}
|
||||
case PURPLE_STATUS_UNAVAILABLE: {
|
||||
status = Swift::StatusShow::DND;
|
||||
break;
|
||||
}
|
||||
case PURPLE_STATUS_EXTENDED_AWAY: {
|
||||
status = Swift::StatusShow::XA;
|
||||
break;
|
||||
}
|
||||
case PURPLE_STATUS_OFFLINE: {
|
||||
status = Swift::StatusShow::None;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const char *message = purple_status_get_attr_string(stat, "message");
|
||||
|
||||
if (message != NULL) {
|
||||
char *stripped = purple_markup_strip_html(message);
|
||||
statusMessage = std::string(stripped);
|
||||
g_free(stripped);
|
||||
}
|
||||
else
|
||||
statusMessage = "";
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::string getIconHash(PurpleBuddy *m_buddy) {
|
||||
char *avatarHash = NULL;
|
||||
PurpleBuddyIcon *icon = purple_buddy_icons_find(purple_buddy_get_account(m_buddy), purple_buddy_get_name(m_buddy));
|
||||
if (icon) {
|
||||
avatarHash = purple_buddy_icon_get_full_path(icon);
|
||||
}
|
||||
|
||||
if (avatarHash) {
|
||||
// Check if it's patched libpurple which saves icons to directories
|
||||
char *hash = strrchr(avatarHash,'/');
|
||||
std::string h;
|
||||
if (hash) {
|
||||
char *dot;
|
||||
hash++;
|
||||
dot = strchr(hash, '.');
|
||||
if (dot)
|
||||
*dot = '\0';
|
||||
|
||||
std::string ret(hash);
|
||||
g_free(avatarHash);
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
std::string ret(avatarHash);
|
||||
g_free(avatarHash);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
static std::vector<std::string> getGroups(PurpleBuddy *m_buddy) {
|
||||
std::vector<std::string> groups;
|
||||
groups.push_back(purple_group_get_name(purple_buddy_get_group(m_buddy)) ? std::string(purple_group_get_name(purple_buddy_get_group(m_buddy))) : std::string("Buddies"));
|
||||
return groups;
|
||||
}
|
||||
|
||||
static void buddyListNewNode(PurpleBlistNode *node) {
|
||||
if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
|
||||
return;
|
||||
PurpleBuddy *buddy = (PurpleBuddy *) node;
|
||||
PurpleAccount *account = purple_buddy_get_account(buddy);
|
||||
|
||||
Swift::StatusShow status;
|
||||
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));
|
||||
}
|
||||
|
||||
static void buddyStatusChanged(PurpleBuddy *buddy, PurpleStatus *status_, PurpleStatus *old_status) {
|
||||
PurpleAccount *account = purple_buddy_get_account(buddy);
|
||||
|
||||
Swift::StatusShow status;
|
||||
std::string message;
|
||||
getStatus(buddy, status, message);
|
||||
|
||||
np->handleBuddyChanged(np->m_accounts[account], purple_buddy_get_name(buddy), getAlias(buddy), getGroups(buddy)[0], (int) status.getType(), message, getIconHash(buddy));
|
||||
}
|
||||
|
||||
static void buddySignedOn(PurpleBuddy *buddy) {
|
||||
PurpleAccount *account = purple_buddy_get_account(buddy);
|
||||
|
||||
Swift::StatusShow status;
|
||||
std::string message;
|
||||
getStatus(buddy, status, message);
|
||||
|
||||
np->handleBuddyChanged(np->m_accounts[account], purple_buddy_get_name(buddy), getAlias(buddy), getGroups(buddy)[0], (int) status.getType(), message, getIconHash(buddy));
|
||||
}
|
||||
|
||||
static void buddySignedOff(PurpleBuddy *buddy) {
|
||||
PurpleAccount *account = purple_buddy_get_account(buddy);
|
||||
|
||||
Swift::StatusShow status;
|
||||
std::string message;
|
||||
getStatus(buddy, status, message);
|
||||
|
||||
np->handleBuddyChanged(np->m_accounts[account], purple_buddy_get_name(buddy), getAlias(buddy), getGroups(buddy)[0], (int) status.getType(), message, getIconHash(buddy));
|
||||
}
|
||||
|
||||
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);
|
||||
np->handleDisconnected(np->m_accounts[account], purple_account_get_username(account), (int) reason, text ? 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;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
np = new SpectrumNetworkPlugin(&config, &eventLoop, host, port);
|
||||
eventLoop.run();
|
||||
}
|
||||
|
||||
g_option_context_free(context);
|
||||
}
|
11
backends/libpurple/sample_client.cfg
Normal file
11
backends/libpurple/sample_client.cfg
Normal file
|
@ -0,0 +1,11 @@
|
|||
[service]
|
||||
jid = icq.localhost
|
||||
password = secret
|
||||
server = 127.0.0.1
|
||||
port = 5347
|
||||
protocol=prpl-jabber
|
||||
#server_mode=1
|
||||
|
||||
[database]
|
||||
database = test.sql
|
||||
prefix=icq
|
15
backends/libpurple/spectrum.cpp
Normal file
15
backends/libpurple/spectrum.cpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
#include "spectrum.h"
|
||||
#include "transport/config.h"
|
||||
#include "transport/transport.h"
|
||||
#include "transport/usermanager.h"
|
||||
#include "transport/logger.h"
|
||||
#include "transport/sqlite3backend.h"
|
||||
#include "transport/userregistration.h"
|
||||
|
||||
Spectrum::Spectrum(const std::string &config) {
|
||||
|
||||
}
|
||||
|
||||
Spectrum::~Spectrum() {
|
||||
|
||||
}
|
33
backends/libpurple/spectrum.h
Normal file
33
backends/libpurple/spectrum.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2011, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "transport/transport.h"
|
||||
|
||||
using namespace Transport;
|
||||
|
||||
class Spectrum {
|
||||
public:
|
||||
Spectrum(const std::string &config);
|
||||
~Spectrum();
|
||||
|
||||
private:
|
||||
Component *m_component;
|
||||
};
|
138
backends/libpurple/spectrumbuddy.cpp
Normal file
138
backends/libpurple/spectrumbuddy.cpp
Normal file
|
@ -0,0 +1,138 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#include "spectrumbuddy.h"
|
||||
#include "transport/user.h"
|
||||
|
||||
#define Log(X, STRING) std::cout << "[SPECTRUM] " << X << " " << STRING << "\n";
|
||||
|
||||
SpectrumBuddy::SpectrumBuddy(RosterManager *rosterManager, long id, PurpleBuddy *buddy) : Buddy(rosterManager, id), m_buddy(buddy) {
|
||||
}
|
||||
|
||||
SpectrumBuddy::~SpectrumBuddy() {
|
||||
}
|
||||
|
||||
|
||||
std::string SpectrumBuddy::getAlias() {
|
||||
std::string alias;
|
||||
if (purple_buddy_get_server_alias(m_buddy))
|
||||
alias = (std::string) purple_buddy_get_server_alias(m_buddy);
|
||||
else
|
||||
alias = (std::string) purple_buddy_get_alias(m_buddy);
|
||||
return alias;
|
||||
}
|
||||
|
||||
std::string SpectrumBuddy::getName() {
|
||||
std::string name(purple_buddy_get_name(m_buddy));
|
||||
if (name.empty()) {
|
||||
Log("SpectrumBuddy::getName", "Name is EMPTY!");
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
bool SpectrumBuddy::getStatus(Swift::StatusShow &status, std::string &statusMessage) {
|
||||
PurplePresence *pres = purple_buddy_get_presence(m_buddy);
|
||||
if (pres == NULL)
|
||||
return false;
|
||||
PurpleStatus *stat = purple_presence_get_active_status(pres);
|
||||
if (stat == NULL)
|
||||
return false;
|
||||
int st = purple_status_type_get_primitive(purple_status_get_type(stat));
|
||||
|
||||
switch(st) {
|
||||
case PURPLE_STATUS_AVAILABLE: {
|
||||
break;
|
||||
}
|
||||
case PURPLE_STATUS_AWAY: {
|
||||
status = Swift::StatusShow::Away;
|
||||
break;
|
||||
}
|
||||
case PURPLE_STATUS_UNAVAILABLE: {
|
||||
status = Swift::StatusShow::DND;
|
||||
break;
|
||||
}
|
||||
case PURPLE_STATUS_EXTENDED_AWAY: {
|
||||
status = Swift::StatusShow::XA;
|
||||
break;
|
||||
}
|
||||
case PURPLE_STATUS_OFFLINE: {
|
||||
status = Swift::StatusShow::None;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const char *message = purple_status_get_attr_string(stat, "message");
|
||||
|
||||
if (message != NULL) {
|
||||
char *stripped = purple_markup_strip_html(message);
|
||||
statusMessage = std::string(stripped);
|
||||
g_free(stripped);
|
||||
}
|
||||
else
|
||||
statusMessage = "";
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string SpectrumBuddy::getIconHash() {
|
||||
char *avatarHash = NULL;
|
||||
PurpleBuddyIcon *icon = purple_buddy_icons_find(purple_buddy_get_account(m_buddy), purple_buddy_get_name(m_buddy));
|
||||
if (icon) {
|
||||
avatarHash = purple_buddy_icon_get_full_path(icon);
|
||||
Log(getName(), "avatarHash");
|
||||
}
|
||||
|
||||
if (avatarHash) {
|
||||
Log(getName(), "Got avatar hash");
|
||||
// Check if it's patched libpurple which saves icons to directories
|
||||
char *hash = strrchr(avatarHash,'/');
|
||||
std::string h;
|
||||
if (hash) {
|
||||
char *dot;
|
||||
hash++;
|
||||
dot = strchr(hash, '.');
|
||||
if (dot)
|
||||
*dot = '\0';
|
||||
|
||||
std::string ret(hash);
|
||||
g_free(avatarHash);
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
std::string ret(avatarHash);
|
||||
g_free(avatarHash);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
std::vector<std::string> SpectrumBuddy::getGroups() {
|
||||
std::vector<std::string> groups;
|
||||
groups.push_back(purple_group_get_name(purple_buddy_get_group(m_buddy)) ? std::string(purple_group_get_name(purple_buddy_get_group(m_buddy))) : std::string("Buddies"));
|
||||
return groups;
|
||||
}
|
||||
|
||||
void SpectrumBuddy::getVCard(const std::string &id, const Swift::JID &to) {
|
||||
|
||||
}
|
||||
|
58
backends/libpurple/spectrumbuddy.h
Normal file
58
backends/libpurple/spectrumbuddy.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SPECTRUM_BUDDY_H
|
||||
#define SPECTRUM_BUDDY_H
|
||||
|
||||
#include <string>
|
||||
#include "purple.h"
|
||||
#include "account.h"
|
||||
#include "glib.h"
|
||||
#include <algorithm>
|
||||
#include "transport/buddy.h"
|
||||
#include "transport/rostermanager.h"
|
||||
|
||||
using namespace Transport;
|
||||
|
||||
// Wrapper for PurpleBuddy
|
||||
class SpectrumBuddy : public Buddy {
|
||||
public:
|
||||
SpectrumBuddy(RosterManager *rosterManager, long id, PurpleBuddy *buddy);
|
||||
virtual ~SpectrumBuddy();
|
||||
|
||||
std::string getAlias();
|
||||
std::string getName();
|
||||
bool getStatus(Swift::StatusShow &status, std::string &statusMessage);
|
||||
std::string getIconHash();
|
||||
std::vector<std::string> getGroups();
|
||||
|
||||
void addBuddy(PurpleBuddy *buddy) { m_buddies.push_back(buddy); }
|
||||
void removeBuddy(PurpleBuddy *buddy) { m_buddies.remove(buddy); }
|
||||
int getBuddiesCount() { return m_buddies.size(); }
|
||||
void getVCard(const std::string &id, const Swift::JID &to);
|
||||
|
||||
PurpleBuddy *getBuddy() { return m_buddy; }
|
||||
|
||||
private:
|
||||
PurpleBuddy *m_buddy;
|
||||
std::list<PurpleBuddy *> m_buddies;
|
||||
};
|
||||
|
||||
#endif
|
41
backends/libpurple/spectrumconversation.cpp
Normal file
41
backends/libpurple/spectrumconversation.cpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#include "spectrumconversation.h"
|
||||
#include "transport/user.h"
|
||||
|
||||
#define Log(X, STRING) std::cout << "[SPECTRUM] " << X << " " << STRING << "\n";
|
||||
|
||||
SpectrumConversation::SpectrumConversation(ConversationManager *conversationManager, const std::string &legacyName, PurpleConversation *conv) : Conversation(conversationManager, legacyName), m_conv(conv) {
|
||||
}
|
||||
|
||||
SpectrumConversation::~SpectrumConversation() {
|
||||
}
|
||||
|
||||
void SpectrumConversation::sendMessage(boost::shared_ptr<Swift::Message> &message) {
|
||||
// escape and send
|
||||
gchar *_markup = purple_markup_escape_text(message->getBody().c_str(), -1);
|
||||
if (purple_conversation_get_type(m_conv) == PURPLE_CONV_TYPE_IM) {
|
||||
purple_conv_im_send(PURPLE_CONV_IM(m_conv), _markup);
|
||||
}
|
||||
g_free(_markup);
|
||||
}
|
||||
|
||||
|
47
backends/libpurple/spectrumconversation.h
Normal file
47
backends/libpurple/spectrumconversation.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "purple.h"
|
||||
#include "account.h"
|
||||
#include "glib.h"
|
||||
#include <algorithm>
|
||||
#include "transport/conversation.h"
|
||||
#include "transport/conversationmanager.h"
|
||||
#include "transport/user.h"
|
||||
|
||||
using namespace Transport;
|
||||
|
||||
// Wrapper for PurpleBuddy
|
||||
class SpectrumConversation : public Conversation {
|
||||
public:
|
||||
SpectrumConversation(ConversationManager *conversationManager, const std::string &legacyName, PurpleConversation *conv);
|
||||
virtual ~SpectrumConversation();
|
||||
|
||||
PurpleConversation *getConversation() { return m_conv; }
|
||||
|
||||
void sendMessage(boost::shared_ptr<Swift::Message> &message);
|
||||
|
||||
private:
|
||||
PurpleConversation *m_conv;
|
||||
};
|
||||
|
89
backends/libpurple/spectrumeventloop.cpp
Normal file
89
backends/libpurple/spectrumeventloop.cpp
Normal file
|
@ -0,0 +1,89 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#include "spectrumeventloop.h"
|
||||
#include "purple.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#ifdef WITH_LIBEVENT
|
||||
#include <event.h>
|
||||
#endif
|
||||
|
||||
|
||||
using namespace Swift;
|
||||
|
||||
// Fires the event's callback and frees the event
|
||||
static gboolean processEvent(void *data) {
|
||||
Event *ev = (Event *) data;
|
||||
ev->callback();
|
||||
delete ev;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SpectrumEventLoop::SpectrumEventLoop() : m_isRunning(false) {
|
||||
m_loop = NULL;
|
||||
if (true) {
|
||||
m_loop = g_main_loop_new(NULL, FALSE);
|
||||
}
|
||||
#ifdef WITH_LIBEVENT
|
||||
else {
|
||||
/*struct event_base *base = (struct event_base *)*/
|
||||
event_init();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SpectrumEventLoop::~SpectrumEventLoop() {
|
||||
stop();
|
||||
}
|
||||
|
||||
void SpectrumEventLoop::run() {
|
||||
m_isRunning = true;
|
||||
if (m_loop) {
|
||||
g_main_loop_run(m_loop);
|
||||
}
|
||||
#ifdef WITH_LIBEVENT
|
||||
else {
|
||||
event_loop(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SpectrumEventLoop::stop() {
|
||||
if (!m_isRunning)
|
||||
return;
|
||||
if (m_loop) {
|
||||
g_main_loop_quit(m_loop);
|
||||
g_main_loop_unref(m_loop);
|
||||
m_loop = NULL;
|
||||
}
|
||||
#ifdef WITH_LIBEVENT
|
||||
else {
|
||||
event_loopexit(NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SpectrumEventLoop::post(const Event& event) {
|
||||
// pass copy of event to main thread
|
||||
Event *ev = new Event(event.owner, event.callback);
|
||||
purple_timeout_add(0, processEvent, ev);
|
||||
}
|
49
backends/libpurple/spectrumeventloop.h
Normal file
49
backends/libpurple/spectrumeventloop.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SPECTRUM_EVENT_LOOP_H
|
||||
#define SPECTRUM_EVENT_LOOP_H
|
||||
|
||||
#include <vector>
|
||||
#include "Swiften/EventLoop/EventLoop.h"
|
||||
#include "glib.h"
|
||||
|
||||
// Event loop implementation for Spectrum
|
||||
class SpectrumEventLoop : public Swift::EventLoop {
|
||||
public:
|
||||
// Creates event loop according to CONFIG().eventloop settings.
|
||||
SpectrumEventLoop();
|
||||
~SpectrumEventLoop();
|
||||
|
||||
// Executes the eventloop.
|
||||
void run();
|
||||
|
||||
// Stops tht eventloop.
|
||||
void stop();
|
||||
|
||||
// Posts new Swift::Event to main thread.
|
||||
virtual void post(const Swift::Event& event);
|
||||
|
||||
private:
|
||||
bool m_isRunning;
|
||||
GMainLoop *m_loop;
|
||||
};
|
||||
|
||||
#endif
|
1510
docs/Doxyfile
Normal file
1510
docs/Doxyfile
Normal file
File diff suppressed because it is too large
Load diff
75
include/transport/localbuddy.h
Normal file
75
include/transport/localbuddy.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SPECTRUM_BUDDY_H
|
||||
#define SPECTRUM_BUDDY_H
|
||||
|
||||
#include <string>
|
||||
#include "purple.h"
|
||||
#include "account.h"
|
||||
#include "glib.h"
|
||||
#include <algorithm>
|
||||
#include "transport/buddy.h"
|
||||
#include "transport/rostermanager.h"
|
||||
|
||||
namespace Transport {
|
||||
|
||||
class LocalBuddy : public Buddy {
|
||||
public:
|
||||
LocalBuddy(RosterManager *rosterManager, long id);
|
||||
virtual ~LocalBuddy();
|
||||
|
||||
std::string getAlias() { return m_alias; }
|
||||
void setAlias(const std::string &alias) { m_alias = alias; }
|
||||
|
||||
std::string getName() { return m_name; }
|
||||
void setName(const std::string &name) { m_name = name; }
|
||||
|
||||
bool getStatus(Swift::StatusShow &status, std::string &statusMessage) {
|
||||
status = m_status;
|
||||
m_statusMessage = statusMessage;
|
||||
return true;
|
||||
}
|
||||
|
||||
void setStatus(const Swift::StatusShow &status, const std::string &statusMessage) {
|
||||
m_status = status;
|
||||
m_statusMessage = statusMessage;
|
||||
}
|
||||
|
||||
std::string getIconHash() { return m_iconHash; }
|
||||
void setIconHash(const std::string &iconHash) { m_iconHash = iconHash; }
|
||||
|
||||
std::vector<std::string> getGroups() { return m_groups; }
|
||||
void setGroups(const std::vector<std::string> &groups) { m_groups = groups; }
|
||||
|
||||
void getVCard(const std::string &id, const Swift::JID &to) {}
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
std::string m_alias;
|
||||
std::vector<std::string> m_groups;
|
||||
std::string m_statusMessage;
|
||||
std::string m_iconHash;
|
||||
Swift::StatusShow m_status;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
72
include/transport/networkplugin.h
Normal file
72
include/transport/networkplugin.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* libtransport -- C++ library for easy XMPP Transports development
|
||||
*
|
||||
* Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <time.h>
|
||||
#include "Swiften/Swiften.h"
|
||||
#include "Swiften/Presence/PresenceOracle.h"
|
||||
#include "Swiften/Disco/EntityCapsManager.h"
|
||||
#include "Swiften/Network/ConnectionServer.h"
|
||||
#include "Swiften/Network/Connection.h"
|
||||
#include "Swiften/Network/BoostTimerFactory.h"
|
||||
#include "Swiften/Network/BoostNetworkFactories.h"
|
||||
#include "Swiften/Network/BoostIOServiceThread.h"
|
||||
#include "Swiften/Network/Connection.h"
|
||||
#include "storagebackend.h"
|
||||
|
||||
namespace Transport {
|
||||
|
||||
class NetworkPlugin {
|
||||
public:
|
||||
NetworkPlugin(Swift::EventLoop *loop, const std::string &host, int port);
|
||||
|
||||
virtual ~NetworkPlugin();
|
||||
|
||||
void handleBuddyChanged(const std::string &user, const std::string &buddyName, const std::string &alias,
|
||||
const std::string &groups, int status, const std::string &statusMessage = "", const std::string &iconHash = ""
|
||||
);
|
||||
|
||||
void handleDisconnected(const std::string &user, const std::string &legacyName, int error, const std::string &message);
|
||||
|
||||
virtual void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) = 0;
|
||||
virtual void handleLogoutRequest(const std::string &user, const std::string &legacyName) = 0;
|
||||
|
||||
private:
|
||||
void connect();
|
||||
void handleLoginPayload(const std::string &payload);
|
||||
void handleLogoutPayload(const std::string &payload);
|
||||
void handleDataRead(const Swift::ByteArray&);
|
||||
void handleConnected(bool error);
|
||||
void handleDisconnected();
|
||||
|
||||
void send(const std::string &data);
|
||||
|
||||
std::string m_data;
|
||||
std::string m_host;
|
||||
int m_port;
|
||||
Swift::BoostNetworkFactories *m_factories;
|
||||
Swift::BoostIOServiceThread m_boostIOServiceThread;
|
||||
boost::shared_ptr<Swift::Connection> m_conn;
|
||||
Swift::Timer::ref m_reconnectTimer;
|
||||
|
||||
};
|
||||
|
||||
}
|
69
include/transport/networkpluginserver.h
Normal file
69
include/transport/networkpluginserver.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* libtransport -- C++ library for easy XMPP Transports development
|
||||
*
|
||||
* Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <time.h>
|
||||
#include "Swiften/Swiften.h"
|
||||
#include "Swiften/Presence/PresenceOracle.h"
|
||||
#include "Swiften/Disco/EntityCapsManager.h"
|
||||
#include "Swiften/Network/ConnectionServer.h"
|
||||
#include "Swiften/Network/Connection.h"
|
||||
#include "storagebackend.h"
|
||||
|
||||
namespace Transport {
|
||||
|
||||
class UserManager;
|
||||
class User;
|
||||
class Component;
|
||||
class Buddy;
|
||||
class LocalBuddy;
|
||||
class Config;
|
||||
|
||||
class NetworkPluginServer {
|
||||
public:
|
||||
NetworkPluginServer(Component *component, Config *config, UserManager *userManager);
|
||||
|
||||
virtual ~NetworkPluginServer();
|
||||
|
||||
private:
|
||||
void handleNewClientConnection(boost::shared_ptr<Swift::Connection> c);
|
||||
void handleSessionFinished(boost::shared_ptr<Swift::Connection>);
|
||||
void handleDataRead(boost::shared_ptr<Swift::Connection>, const Swift::ByteArray&);
|
||||
|
||||
void handleConnectedPayload(const std::string &payload);
|
||||
void handleDisconnectedPayload(const std::string &payload);
|
||||
void handleBuddyChangedPayload(const std::string &payload);
|
||||
|
||||
void handleUserCreated(User *user);
|
||||
void handleUserReadyToConnect(User *user);
|
||||
void handleUserDestroyed(User *user);
|
||||
|
||||
void send(boost::shared_ptr<Swift::Connection> &, const std::string &data);
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
32
src/localbuddy.cpp
Normal file
32
src/localbuddy.cpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#include "transport/localbuddy.h"
|
||||
#include "transport/user.h"
|
||||
|
||||
namespace Transport {
|
||||
|
||||
LocalBuddy::LocalBuddy(RosterManager *rosterManager, long id) : Buddy(rosterManager, id) {
|
||||
}
|
||||
|
||||
LocalBuddy::~LocalBuddy() {
|
||||
}
|
||||
|
||||
}
|
181
src/networkplugin.cpp
Normal file
181
src/networkplugin.cpp
Normal file
|
@ -0,0 +1,181 @@
|
|||
/**
|
||||
* libtransport -- C++ library for easy XMPP Transports development
|
||||
*
|
||||
* Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#include "transport/networkplugin.h"
|
||||
#include "transport/user.h"
|
||||
#include "transport/transport.h"
|
||||
#include "transport/storagebackend.h"
|
||||
#include "transport/rostermanager.h"
|
||||
#include "transport/usermanager.h"
|
||||
#include "transport/conversationmanager.h"
|
||||
#include "Swiften/Swiften.h"
|
||||
#include "Swiften/Server/ServerStanzaChannel.h"
|
||||
#include "Swiften/Elements/StreamError.h"
|
||||
#include "pbnetwork.pb.h"
|
||||
|
||||
namespace Transport {
|
||||
|
||||
#define WRAP(MESSAGE, TYPE) pbnetwork::WrapperMessage wrap; \
|
||||
wrap.set_type(TYPE); \
|
||||
wrap.set_payload(MESSAGE); \
|
||||
wrap.SerializeToString(&MESSAGE);
|
||||
|
||||
NetworkPlugin::NetworkPlugin(Swift::EventLoop *loop, const std::string &host, int port) {
|
||||
m_factories = new Swift::BoostNetworkFactories(loop);
|
||||
m_host = host;
|
||||
m_port = port;
|
||||
m_conn = m_factories->getConnectionFactory()->createConnection();
|
||||
m_conn->onDataRead.connect(boost::bind(&NetworkPlugin::handleDataRead, this, _1));
|
||||
m_conn->onConnectFinished.connect(boost::bind(&NetworkPlugin::handleConnected, this, _1));
|
||||
m_conn->onDisconnected.connect(boost::bind(&NetworkPlugin::handleDisconnected, this));
|
||||
|
||||
m_reconnectTimer = m_factories->getTimerFactory()->createTimer(1000);
|
||||
m_reconnectTimer->onTick.connect(boost::bind(&NetworkPlugin::connect, this));
|
||||
connect();
|
||||
}
|
||||
|
||||
NetworkPlugin::~NetworkPlugin() {
|
||||
delete m_factories;
|
||||
}
|
||||
|
||||
void NetworkPlugin::handleBuddyChanged(const std::string &user, const std::string &buddyName, const std::string &alias,
|
||||
const std::string &groups, int status, const std::string &statusMessage, const std::string &iconHash) {
|
||||
pbnetwork::Buddy buddy;
|
||||
buddy.set_username(user);
|
||||
buddy.set_buddyname(buddyName);
|
||||
buddy.set_alias(alias);
|
||||
buddy.set_groups(groups);
|
||||
buddy.set_status(status);
|
||||
buddy.set_statusmessage(statusMessage);
|
||||
buddy.set_iconhash(iconHash);
|
||||
|
||||
std::string message;
|
||||
buddy.SerializeToString(&message);
|
||||
|
||||
WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_BUDDY_CHANGED);
|
||||
|
||||
send(message);
|
||||
}
|
||||
|
||||
void NetworkPlugin::handleDisconnected(const std::string &user, const std::string &legacyName, int error, const std::string &msg) {
|
||||
pbnetwork::Disconnected d;
|
||||
d.set_user(user);
|
||||
d.set_name(legacyName);
|
||||
d.set_error(error);
|
||||
d.set_message(msg);
|
||||
|
||||
std::string message;
|
||||
d.SerializeToString(&message);
|
||||
|
||||
WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_DISCONNECTED);
|
||||
|
||||
send(message);
|
||||
}
|
||||
|
||||
void NetworkPlugin::handleConnected(bool error) {
|
||||
if (error) {
|
||||
std::cout << "Connecting error\n";
|
||||
connect();
|
||||
}
|
||||
else {
|
||||
std::cout << "Connected\n";
|
||||
m_reconnectTimer->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkPlugin::handleDisconnected() {
|
||||
std::cout << "Disconnected\n";
|
||||
m_reconnectTimer->start();
|
||||
}
|
||||
|
||||
void NetworkPlugin::connect() {
|
||||
std::cout << "Trying to connect the server\n";
|
||||
m_conn->connect(Swift::HostAddressPort(Swift::HostAddress(m_host), m_port));
|
||||
m_reconnectTimer->stop();
|
||||
}
|
||||
|
||||
void NetworkPlugin::handleLoginPayload(const std::string &data) {
|
||||
pbnetwork::Login payload;
|
||||
if (payload.ParseFromString(data) == false) {
|
||||
// TODO: ERROR
|
||||
return;
|
||||
}
|
||||
handleLoginRequest(payload.user(), payload.legacyname(), payload.password());
|
||||
}
|
||||
|
||||
void NetworkPlugin::handleLogoutPayload(const std::string &data) {
|
||||
pbnetwork::Logout payload;
|
||||
if (payload.ParseFromString(data) == false) {
|
||||
// TODO: ERROR
|
||||
return;
|
||||
}
|
||||
handleLogoutRequest(payload.user(), payload.legacyname());
|
||||
}
|
||||
|
||||
void NetworkPlugin::handleDataRead(const Swift::ByteArray &data) {
|
||||
long expected_size = 0;
|
||||
m_data += data.toString();
|
||||
std::cout << "received data; size = " << m_data.size() << "\n";
|
||||
while (m_data.size() != 0) {
|
||||
if (m_data.size() >= 4) {
|
||||
expected_size = (((((m_data[0] << 8) | m_data[1]) << 8) | m_data[2]) << 8) | m_data[3];
|
||||
std::cout << "expected_size=" << expected_size << "\n";
|
||||
if (m_data.size() - 4 < expected_size)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string msg = m_data.substr(4, expected_size);
|
||||
m_data.erase(0, 4 + expected_size);
|
||||
|
||||
pbnetwork::WrapperMessage wrapper;
|
||||
if (wrapper.ParseFromString(msg) == false) {
|
||||
// TODO: ERROR
|
||||
return;
|
||||
}
|
||||
|
||||
switch(wrapper.type()) {
|
||||
case pbnetwork::WrapperMessage_Type_TYPE_LOGIN:
|
||||
handleLoginPayload(wrapper.payload());
|
||||
break;
|
||||
case pbnetwork::WrapperMessage_Type_TYPE_LOGOUT:
|
||||
handleLogoutPayload(wrapper.payload());
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkPlugin::send(const std::string &data) {
|
||||
std::string header(" ");
|
||||
std::cout << data.size() << "\n";
|
||||
boost::int32_t size = data.size();
|
||||
for (int i = 0; i != 4; ++i) {
|
||||
header.at(i) = static_cast<char>(size >> (8 * (3 - i)));
|
||||
std::cout << std::hex << (int) header.at(i) << "\n";
|
||||
}
|
||||
|
||||
m_conn->write(Swift::ByteArray(header + data));
|
||||
}
|
||||
|
||||
}
|
240
src/networkpluginserver.cpp
Normal file
240
src/networkpluginserver.cpp
Normal file
|
@ -0,0 +1,240 @@
|
|||
/**
|
||||
* libtransport -- C++ library for easy XMPP Transports development
|
||||
*
|
||||
* Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#include "transport/networkpluginserver.h"
|
||||
#include "transport/user.h"
|
||||
#include "transport/transport.h"
|
||||
#include "transport/storagebackend.h"
|
||||
#include "transport/rostermanager.h"
|
||||
#include "transport/usermanager.h"
|
||||
#include "transport/conversationmanager.h"
|
||||
#include "transport/localbuddy.h"
|
||||
#include "transport/config.h"
|
||||
#include "Swiften/Swiften.h"
|
||||
#include "Swiften/Server/ServerStanzaChannel.h"
|
||||
#include "Swiften/Elements/StreamError.h"
|
||||
#include "pbnetwork.pb.h"
|
||||
#include "sys/wait.h"
|
||||
#include "sys/signal.h"
|
||||
|
||||
namespace Transport {
|
||||
|
||||
#define WRAP(MESSAGE, TYPE) pbnetwork::WrapperMessage wrap; \
|
||||
wrap.set_type(TYPE); \
|
||||
wrap.set_payload(MESSAGE); \
|
||||
wrap.SerializeToString(&MESSAGE);
|
||||
|
||||
static int exec_(const char *path, const char *host, const char *port, const char *config) {
|
||||
// char *argv[] = {(char*)script_name, '\0'};
|
||||
int status = 0;
|
||||
pid_t pid = fork();
|
||||
if ( pid == 0 ) {
|
||||
// child process
|
||||
execlp(path, path, "--host", host, "--port", port, config, NULL);
|
||||
exit(1);
|
||||
} else if ( pid < 0 ) {
|
||||
// fork failed
|
||||
status = -1;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static void SigCatcher(int n) {
|
||||
wait3(NULL,WNOHANG,NULL);
|
||||
}
|
||||
|
||||
static void handleBuddyPayload(LocalBuddy *buddy, const pbnetwork::Buddy &payload) {
|
||||
buddy->setName(payload.buddyname());
|
||||
buddy->setAlias(payload.alias());
|
||||
std::vector<std::string> groups;
|
||||
groups.push_back(payload.groups());
|
||||
buddy->setGroups(groups);
|
||||
buddy->setStatus(Swift::StatusShow((Swift::StatusShow::Type) payload.status()), payload.statusmessage());
|
||||
buddy->setIconHash(payload.iconhash());
|
||||
}
|
||||
|
||||
NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, UserManager *userManager) {
|
||||
m_userManager = userManager;
|
||||
m_config = config;
|
||||
m_userManager->onUserCreated.connect(boost::bind(&NetworkPluginServer::handleUserCreated, this, _1));
|
||||
m_userManager->onUserDestroyed.connect(boost::bind(&NetworkPluginServer::handleUserDestroyed, this, _1));
|
||||
|
||||
m_server = component->getFactories()->getConnectionFactory()->createConnectionServer(10000);
|
||||
m_server->onNewConnection.connect(boost::bind(&NetworkPluginServer::handleNewClientConnection, this, _1));
|
||||
m_server->start();
|
||||
|
||||
signal(SIGCHLD, SigCatcher);
|
||||
|
||||
exec_(CONFIG_STRING(m_config, "service.backend").c_str(), "localhost", "10000", m_config->getConfigFile().c_str());
|
||||
}
|
||||
|
||||
NetworkPluginServer::~NetworkPluginServer() {
|
||||
|
||||
}
|
||||
|
||||
void NetworkPluginServer::handleNewClientConnection(boost::shared_ptr<Swift::Connection> c) {
|
||||
if (m_client) {
|
||||
c->disconnect();
|
||||
}
|
||||
m_client = c;
|
||||
|
||||
c->onDisconnected.connect(boost::bind(&NetworkPluginServer::handleSessionFinished, this, c));
|
||||
c->onDataRead.connect(boost::bind(&NetworkPluginServer::handleDataRead, this, c, _1));
|
||||
}
|
||||
|
||||
void NetworkPluginServer::handleSessionFinished(boost::shared_ptr<Swift::Connection> c) {
|
||||
if (c == m_client) {
|
||||
m_client.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkPluginServer::handleConnectedPayload(const std::string &data) {
|
||||
pbnetwork::Connected payload;
|
||||
if (payload.ParseFromString(data) == false) {
|
||||
// TODO: ERROR
|
||||
return;
|
||||
}
|
||||
std::cout << payload.name() << "\n";
|
||||
}
|
||||
|
||||
void NetworkPluginServer::handleDisconnectedPayload(const std::string &data) {
|
||||
pbnetwork::Disconnected payload;
|
||||
if (payload.ParseFromString(data) == false) {
|
||||
// TODO: ERROR
|
||||
return;
|
||||
}
|
||||
|
||||
User *user = m_userManager->getUser(payload.user());
|
||||
if (!user)
|
||||
return;
|
||||
|
||||
user->handleDisconnected(payload.message());
|
||||
}
|
||||
|
||||
void NetworkPluginServer::handleBuddyChangedPayload(const std::string &data) {
|
||||
pbnetwork::Buddy payload;
|
||||
if (payload.ParseFromString(data) == false) {
|
||||
// TODO: ERROR
|
||||
return;
|
||||
}
|
||||
|
||||
User *user = m_userManager->getUser(payload.username());
|
||||
if (!user)
|
||||
return;
|
||||
|
||||
LocalBuddy *buddy = (LocalBuddy *) user->getRosterManager()->getBuddy(payload.buddyname());
|
||||
if (buddy) {
|
||||
handleBuddyPayload(buddy, payload);
|
||||
buddy->buddyChanged();
|
||||
}
|
||||
else {
|
||||
buddy = new LocalBuddy(user->getRosterManager(), -1);
|
||||
handleBuddyPayload(buddy, payload);
|
||||
user->getRosterManager()->setBuddy(buddy);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkPluginServer::handleDataRead(boost::shared_ptr<Swift::Connection> c, const Swift::ByteArray &data) {
|
||||
long expected_size = 0;
|
||||
m_data += data.toString();
|
||||
std::cout << "received data; size = " << m_data.size() << "\n";
|
||||
while (m_data.size() != 0) {
|
||||
if (m_data.size() >= 4) {
|
||||
unsigned char * head = (unsigned char*) m_data.c_str();
|
||||
expected_size = (((((*head << 8) | *(head + 1)) << 8) | *(head + 2)) << 8) | *(head + 3);
|
||||
//expected_size = m_data[0];
|
||||
std::cout << "expected_size=" << expected_size << "\n";
|
||||
if (m_data.size() - 4 < expected_size)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string msg = m_data.substr(4, expected_size);
|
||||
m_data.erase(0, 4 + expected_size);
|
||||
|
||||
pbnetwork::WrapperMessage wrapper;
|
||||
if (wrapper.ParseFromString(msg) == false) {
|
||||
// TODO: ERROR
|
||||
return;
|
||||
}
|
||||
|
||||
switch(wrapper.type()) {
|
||||
case pbnetwork::WrapperMessage_Type_TYPE_CONNECTED:
|
||||
handleConnectedPayload(wrapper.payload());
|
||||
break;
|
||||
case pbnetwork::WrapperMessage_Type_TYPE_DISCONNECTED:
|
||||
handleDisconnectedPayload(wrapper.payload());
|
||||
break;
|
||||
case pbnetwork::WrapperMessage_Type_TYPE_BUDDY_CHANGED:
|
||||
handleBuddyChangedPayload(wrapper.payload());
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkPluginServer::send(boost::shared_ptr<Swift::Connection> &c, const std::string &data) {
|
||||
std::string header(" ");
|
||||
for (int i = 0; i != 4; ++i)
|
||||
header.at(i) = static_cast<char>(data.size() >> (8 * (3 - i)));
|
||||
|
||||
c->write(Swift::ByteArray(header + data));
|
||||
}
|
||||
|
||||
void NetworkPluginServer::handleUserCreated(User *user) {
|
||||
// UserInfo userInfo = user->getUserInfo();
|
||||
user->onReadyToConnect.connect(boost::bind(&NetworkPluginServer::handleUserReadyToConnect, this, user));
|
||||
}
|
||||
|
||||
void NetworkPluginServer::handleUserReadyToConnect(User *user) {
|
||||
UserInfo userInfo = user->getUserInfo();
|
||||
|
||||
pbnetwork::Login login;
|
||||
login.set_user(user->getJID().toBare());
|
||||
login.set_legacyname(userInfo.uin);
|
||||
login.set_password(userInfo.password);
|
||||
|
||||
std::string message;
|
||||
login.SerializeToString(&message);
|
||||
|
||||
WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_LOGIN);
|
||||
|
||||
send(m_client, message);
|
||||
}
|
||||
|
||||
void NetworkPluginServer::handleUserDestroyed(User *user) {
|
||||
UserInfo userInfo = user->getUserInfo();
|
||||
|
||||
pbnetwork::Logout logout;
|
||||
logout.set_user(user->getJID().toBare());
|
||||
logout.set_legacyname(userInfo.uin);
|
||||
|
||||
std::string message;
|
||||
logout.SerializeToString(&message);
|
||||
|
||||
WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_LOGOUT);
|
||||
|
||||
send(m_client, message);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,24 +1,62 @@
|
|||
package pbnetwork;
|
||||
|
||||
message Person {
|
||||
required string name = 1;
|
||||
required int32 id = 2;
|
||||
optional string email = 3;
|
||||
|
||||
enum PhoneType {
|
||||
MOBILE = 0;
|
||||
HOME = 1;
|
||||
WORK = 2;
|
||||
}
|
||||
|
||||
message PhoneNumber {
|
||||
required string number = 1;
|
||||
optional PhoneType type = 2 [default = HOME];
|
||||
}
|
||||
|
||||
repeated PhoneNumber phone = 4;
|
||||
message Connected {
|
||||
required string user = 1;
|
||||
required string name = 2;
|
||||
}
|
||||
|
||||
message AddressBook {
|
||||
repeated Person person = 1;
|
||||
message Disconnected {
|
||||
required string user = 1;
|
||||
required string name = 2;
|
||||
required int32 error = 3;
|
||||
optional string message = 4;
|
||||
}
|
||||
|
||||
message Login {
|
||||
required string user = 1;
|
||||
required string legacyName = 2;
|
||||
required string password = 3;
|
||||
}
|
||||
|
||||
message Logout {
|
||||
required string user = 1;
|
||||
required string legacyName = 2;
|
||||
}
|
||||
|
||||
message Buddy {
|
||||
required string userName = 1;
|
||||
required string buddyName = 2;
|
||||
required string alias = 3;
|
||||
required string groups = 4;
|
||||
required int32 status = 5;
|
||||
optional string statusMessage = 6;
|
||||
optional string iconHash = 7;
|
||||
}
|
||||
|
||||
message Conversation {
|
||||
required string userName = 1;
|
||||
required string buddyName = 2;
|
||||
}
|
||||
|
||||
message ConversationMessage {
|
||||
required string userName = 1;
|
||||
required string buddyName = 2;
|
||||
required string message = 3;
|
||||
}
|
||||
|
||||
message WrapperMessage {
|
||||
enum Type {
|
||||
TYPE_CONNECTED = 1;
|
||||
TYPE_DISCONNECTED = 2;
|
||||
TYPE_LOGIN = 3;
|
||||
TYPE_LOGOUT = 4;
|
||||
TYPE_BUDDY_CHANGED = 6;
|
||||
TYPE_BUDDY_REMOVED = 7;
|
||||
TYPE_CONV_CREATED = 8;
|
||||
TYPE_CONV_WRITE = 9;
|
||||
TYPE_CONV_REMOVED = 10;
|
||||
}
|
||||
required Type type = 1;
|
||||
required bytes payload = 2;
|
||||
}
|
||||
;
|
Loading…
Add table
Reference in a new issue