Merge branch 'master' of https://github.com/hanzz/libtransport
This commit is contained in:
commit
bd4b3bcd1d
35 changed files with 854 additions and 794 deletions
|
@ -242,6 +242,7 @@ ADD_SUBDIRECTORY(spectrum)
|
|||
ADD_SUBDIRECTORY(backends)
|
||||
if (NOT WIN32)
|
||||
ADD_SUBDIRECTORY(spectrum_manager)
|
||||
# ADD_SUBDIRECTORY(spectrum2_send_message)
|
||||
endif()
|
||||
|
||||
if (CPPUNIT_FOUND)
|
||||
|
|
20
ChangeLog
20
ChangeLog
|
@ -1,3 +1,23 @@
|
|||
Version 2.0.0-beta2 (2012-XX-XX):
|
||||
General:
|
||||
* Fixed bug when Roster Item Exchange and subscribe stanzas were sent
|
||||
repeatedly.
|
||||
* Backends related logs now contain the backend PID.
|
||||
* Fixed username_mask setting.
|
||||
* Added new fields into statistics (backends_crashed, messages related
|
||||
stats).
|
||||
|
||||
libpurple:
|
||||
* Added support for MUC for prpl-jabber protocol.
|
||||
|
||||
Skype:
|
||||
* Memory usage statistic now includes the Skype client.
|
||||
* Fixed logging issue when the logs were not stored in the proper instance
|
||||
directory.
|
||||
* Skype backend includes also Skype client memory usage into the account.
|
||||
* Working buddies adding/removing.
|
||||
* Information about missed call is now forwarded to XMPP user.
|
||||
|
||||
Version 2.0.0-beta (2012-02-28):
|
||||
General:
|
||||
* Added PostreSQL support (thanks to Jadestorm).
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "transport/config.h"
|
||||
#include "transport/networkplugin.h"
|
||||
#include "transport/logging.h"
|
||||
#include "session.h"
|
||||
#include <QtCore>
|
||||
#include <QtNetwork>
|
||||
|
@ -83,30 +84,7 @@ int main (int argc, char* argv[]) {
|
|||
}
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
if (CONFIG_STRING(&config, "logging.backend_config").empty()) {
|
||||
LoggerPtr root = log4cxx::Logger::getRootLogger();
|
||||
#ifndef _MSC_VER
|
||||
root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n")));
|
||||
#else
|
||||
root->addAppender(new ConsoleAppender(new PatternLayout(L"%d %-5p %c: %m%n")));
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
log4cxx::helpers::Properties p;
|
||||
log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(&config, "logging.backend_config"));
|
||||
p.load(istream);
|
||||
LogString pid, jid;
|
||||
log4cxx::helpers::Transcoder::decode(boost::lexical_cast<std::string>(getpid()), pid);
|
||||
log4cxx::helpers::Transcoder::decode(CONFIG_STRING(&config, "service.jid"), jid);
|
||||
#ifdef _MSC_VER
|
||||
p.setProperty(L"pid", pid);
|
||||
p.setProperty(L"jid", jid);
|
||||
#else
|
||||
p.setProperty("pid", pid);
|
||||
p.setProperty("jid", jid);
|
||||
#endif
|
||||
log4cxx::PropertyConfigurator::configure(p);
|
||||
}
|
||||
Logging::initBackendLogging(&config);
|
||||
|
||||
Swift::QtEventLoop eventLoop;
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include "utils.h"
|
||||
|
||||
#include "glib.h"
|
||||
#include "purple.h"
|
||||
#include <algorithm>
|
||||
|
@ -12,25 +14,7 @@
|
|||
#include "log4cxx/helpers/properties.h"
|
||||
#include "log4cxx/helpers/fileinputstream.h"
|
||||
#include "log4cxx/helpers/transcoder.h"
|
||||
#ifndef WIN32
|
||||
#include "sys/wait.h"
|
||||
#include "sys/signal.h"
|
||||
#include <netinet/if_ether.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/ether.h>
|
||||
#include "sys/socket.h"
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#else
|
||||
#include <process.h>
|
||||
#define getpid _getpid
|
||||
#define ssize_t SSIZE_T
|
||||
#include "win32/win32dep.h"
|
||||
#endif
|
||||
|
||||
// #include "valgrind/memcheck.h"
|
||||
#include "malloc.h"
|
||||
#include <algorithm>
|
||||
|
@ -40,11 +24,18 @@
|
|||
#include <event.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include "win32/win32dep.h"
|
||||
#define ssize_t SSIZE_T
|
||||
#include <process.h>
|
||||
#define getpid _getpid
|
||||
#endif
|
||||
|
||||
using namespace log4cxx;
|
||||
|
||||
static LoggerPtr logger_libpurple = log4cxx::Logger::getLogger("libpurple");
|
||||
static LoggerPtr logger = log4cxx::Logger::getLogger("backend");
|
||||
int m_sock;
|
||||
int main_socket;
|
||||
static int writeInput;
|
||||
|
||||
using namespace Transport;
|
||||
|
@ -89,7 +80,7 @@ static std::string KEYFILE_STRING(const std::string &cat, const std::string &key
|
|||
return def;
|
||||
}
|
||||
std::string ret(str);
|
||||
free(str);
|
||||
g_free(str);
|
||||
|
||||
if (ret.find("#") != std::string::npos) {
|
||||
ret = ret.substr(0, ret.find("#"));
|
||||
|
@ -107,13 +98,8 @@ static std::string KEYFILE_STRING(const std::string &cat, const std::string &key
|
|||
|
||||
#define KEYFILE_BOOL(CAT, KEY) g_key_file_get_boolean(keyfile, CAT, KEY, 0)
|
||||
|
||||
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 list_purple_settings = FALSE;
|
||||
|
||||
struct FTData {
|
||||
unsigned long id;
|
||||
|
@ -122,121 +108,12 @@ struct FTData {
|
|||
};
|
||||
|
||||
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 }
|
||||
};
|
||||
|
||||
static void *notify_user_info(PurpleConnection *gc, const char *who, PurpleNotifyUserInfo *user_info);
|
||||
static GHashTable *ui_info = NULL;
|
||||
|
||||
static GHashTable *spectrum_ui_get_info(void)
|
||||
{
|
||||
if(NULL == ui_info) {
|
||||
ui_info = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
|
||||
g_hash_table_insert(ui_info, g_strdup("name"), g_strdup("Spectrum"));
|
||||
g_hash_table_insert(ui_info, g_strdup("version"), g_strdup("0.5"));
|
||||
g_hash_table_insert(ui_info, g_strdup("website"), g_strdup("http://spectrum.im"));
|
||||
g_hash_table_insert(ui_info, g_strdup("dev_website"), g_strdup("http://spectrum.im"));
|
||||
g_hash_table_insert(ui_info, g_strdup("client_type"), g_strdup("pc"));
|
||||
|
||||
/*
|
||||
* This is the client key for "Pidgin." It is owned by the AIM
|
||||
* account "markdoliner." Please don't use this key for other
|
||||
* applications. You can either not specify a client key, in
|
||||
* which case the default "libpurple" key will be used, or you
|
||||
* can register for your own client key at
|
||||
* http://developer.aim.com/manageKeys.jsp
|
||||
*/
|
||||
g_hash_table_insert(ui_info, g_strdup("prpl-aim-clientkey"), g_strdup("ma1cSASNCKFtrdv9"));
|
||||
g_hash_table_insert(ui_info, g_strdup("prpl-icq-clientkey"), g_strdup("ma1cSASNCKFtrdv9"));
|
||||
|
||||
/*
|
||||
* This is the distid for Pidgin, given to us by AOL. Please
|
||||
* don't use this for other applications. You can just not
|
||||
* specify a distid and libpurple will use a default.
|
||||
*/
|
||||
g_hash_table_insert(ui_info, g_strdup("prpl-aim-distid"), GINT_TO_POINTER(1550));
|
||||
g_hash_table_insert(ui_info, g_strdup("prpl-icq-distid"), GINT_TO_POINTER(1550));
|
||||
}
|
||||
|
||||
return ui_info;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
badchar(char c)
|
||||
{
|
||||
switch (c) {
|
||||
case ' ':
|
||||
case ',':
|
||||
case '\0':
|
||||
case '\n':
|
||||
case '\r':
|
||||
case '<':
|
||||
case '>':
|
||||
case '"':
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
badentity(const char *c)
|
||||
{
|
||||
if (!g_ascii_strncasecmp(c, "<", 4) ||
|
||||
!g_ascii_strncasecmp(c, ">", 4) ||
|
||||
!g_ascii_strncasecmp(c, """, 6)) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static const char *
|
||||
process_link(GString *ret,
|
||||
const char *start, const char *c,
|
||||
int matchlen,
|
||||
const char *urlprefix,
|
||||
int inside_paren)
|
||||
{
|
||||
char *url_buf;
|
||||
const char *t;
|
||||
|
||||
for (t = c;; t++) {
|
||||
if (!badchar(*t) && !badentity(t))
|
||||
continue;
|
||||
|
||||
if (t - c == matchlen)
|
||||
break;
|
||||
|
||||
if (*t == ',' && *(t + 1) != ' ') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (t > start && *(t - 1) == '.')
|
||||
t--;
|
||||
if (t > start && *(t - 1) == ')' && inside_paren > 0)
|
||||
t--;
|
||||
|
||||
url_buf = g_strndup(c, t - c);
|
||||
// tmpurlbuf = purple_unescape_html(url_buf);
|
||||
// std::cout << url_buf << "\n";
|
||||
g_string_append_printf(ret, "<A HREF=\"%s%s\">%s</A>",
|
||||
urlprefix,
|
||||
url_buf, url_buf);
|
||||
// g_free(tmpurlbuf);
|
||||
g_free(url_buf);
|
||||
return t;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static gboolean ft_ui_ready(void *data) {
|
||||
PurpleXfer *xfer = (PurpleXfer *) data;
|
||||
|
@ -246,184 +123,6 @@ static gboolean ft_ui_ready(void *data) {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static char *
|
||||
spectrum_markup_linkify(const char *text)
|
||||
{
|
||||
const char *c, *t, *q = NULL;
|
||||
char *tmpurlbuf, *url_buf;
|
||||
gunichar g;
|
||||
gboolean inside_html = FALSE;
|
||||
int inside_paren = 0;
|
||||
GString *ret;
|
||||
|
||||
if (text == NULL)
|
||||
return NULL;
|
||||
|
||||
ret = g_string_new("");
|
||||
|
||||
c = text;
|
||||
while (*c) {
|
||||
|
||||
if(*c == '(' && !inside_html) {
|
||||
inside_paren++;
|
||||
ret = g_string_append_c(ret, *c);
|
||||
c++;
|
||||
}
|
||||
|
||||
if(inside_html) {
|
||||
if(*c == '>') {
|
||||
inside_html = FALSE;
|
||||
} else if(!q && (*c == '\"' || *c == '\'')) {
|
||||
q = c;
|
||||
} else if(q) {
|
||||
if(*c == *q)
|
||||
q = NULL;
|
||||
}
|
||||
} else if(*c == '<') {
|
||||
inside_html = TRUE;
|
||||
if (!g_ascii_strncasecmp(c, "<A", 2)) {
|
||||
while (1) {
|
||||
if (!g_ascii_strncasecmp(c, "/A>", 3)) {
|
||||
inside_html = FALSE;
|
||||
break;
|
||||
}
|
||||
ret = g_string_append_c(ret, *c);
|
||||
c++;
|
||||
if (!(*c))
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (!g_ascii_strncasecmp(c, "http://", 7)) {
|
||||
c = process_link(ret, text, c, 7, "", inside_paren);
|
||||
} else if (!g_ascii_strncasecmp(c, "https://", 8)) {
|
||||
c = process_link(ret, text, c, 8, "", inside_paren);
|
||||
} else if (!g_ascii_strncasecmp(c, "ftp://", 6)) {
|
||||
c = process_link(ret, text, c, 6, "", inside_paren);
|
||||
} else if (!g_ascii_strncasecmp(c, "sftp://", 7)) {
|
||||
c = process_link(ret, text, c, 7, "", inside_paren);
|
||||
} else if (!g_ascii_strncasecmp(c, "file://", 7)) {
|
||||
c = process_link(ret, text, c, 7, "", inside_paren);
|
||||
} else if (!g_ascii_strncasecmp(c, "www.", 4) && c[4] != '.' && (c == text || badchar(c[-1]) || badentity(c-1))) {
|
||||
c = process_link(ret, text, c, 4, "http://", inside_paren);
|
||||
} else if (!g_ascii_strncasecmp(c, "ftp.", 4) && c[4] != '.' && (c == text || badchar(c[-1]) || badentity(c-1))) {
|
||||
c = process_link(ret, text, c, 4, "ftp://", inside_paren);
|
||||
} else if (!g_ascii_strncasecmp(c, "xmpp:", 5) && (c == text || badchar(c[-1]) || badentity(c-1))) {
|
||||
c = process_link(ret, text, c, 5, "", inside_paren);
|
||||
} else if (!g_ascii_strncasecmp(c, "mailto:", 7)) {
|
||||
t = c;
|
||||
while (1) {
|
||||
if (badchar(*t) || badentity(t)) {
|
||||
const char *d;
|
||||
if (t - c == 7) {
|
||||
break;
|
||||
}
|
||||
if (t > text && *(t - 1) == '.')
|
||||
t--;
|
||||
if ((d = strstr(c + 7, "?")) != NULL && d < t)
|
||||
url_buf = g_strndup(c + 7, d - c - 7);
|
||||
else
|
||||
url_buf = g_strndup(c + 7, t - c - 7);
|
||||
if (!purple_email_is_valid(url_buf)) {
|
||||
g_free(url_buf);
|
||||
break;
|
||||
}
|
||||
g_free(url_buf);
|
||||
url_buf = g_strndup(c, t - c);
|
||||
// tmpurlbuf = purple_unescape_html(url_buf);
|
||||
g_string_append_printf(ret, "<A HREF=\"%s\">%s</A>",
|
||||
url_buf, url_buf);
|
||||
g_free(url_buf);
|
||||
// g_free(tmpurlbuf);
|
||||
c = t;
|
||||
break;
|
||||
}
|
||||
t++;
|
||||
}
|
||||
} else if (c != text && (*c == '@')) {
|
||||
int flag;
|
||||
GString *gurl_buf = NULL;
|
||||
const char illegal_chars[] = "!@#$%^&*()[]{}/|\\<>\":;\r\n \0";
|
||||
|
||||
if (strchr(illegal_chars,*(c - 1)) || strchr(illegal_chars, *(c + 1)))
|
||||
flag = 0;
|
||||
else {
|
||||
flag = 1;
|
||||
gurl_buf = g_string_new("");
|
||||
}
|
||||
|
||||
t = c;
|
||||
while (flag) {
|
||||
/* iterate backwards grabbing the local part of an email address */
|
||||
g = g_utf8_get_char(t);
|
||||
if (badchar(*t) || (g >= 127) || (*t == '(') ||
|
||||
((*t == ';') && ((t > (text+2) && (!g_ascii_strncasecmp(t - 3, "<", 4) ||
|
||||
!g_ascii_strncasecmp(t - 3, ">", 4))) ||
|
||||
(t > (text+4) && (!g_ascii_strncasecmp(t - 5, """, 6)))))) {
|
||||
/* local part will already be part of ret, strip it out */
|
||||
ret = g_string_truncate(ret, ret->len - (c - t));
|
||||
ret = g_string_append_unichar(ret, g);
|
||||
break;
|
||||
} else {
|
||||
g_string_prepend_unichar(gurl_buf, g);
|
||||
t = g_utf8_find_prev_char(text, t);
|
||||
if (t < text) {
|
||||
ret = g_string_assign(ret, "");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
t = g_utf8_find_next_char(c, NULL);
|
||||
|
||||
while (flag) {
|
||||
/* iterate forwards grabbing the domain part of an email address */
|
||||
g = g_utf8_get_char(t);
|
||||
if (badchar(*t) || (g >= 127) || (*t == ')') || badentity(t)) {
|
||||
char *d;
|
||||
|
||||
url_buf = g_string_free(gurl_buf, FALSE);
|
||||
|
||||
/* strip off trailing periods */
|
||||
if (strlen(url_buf) > 0) {
|
||||
for (d = url_buf + strlen(url_buf) - 1; *d == '.'; d--, t--)
|
||||
*d = '\0';
|
||||
}
|
||||
|
||||
tmpurlbuf = purple_unescape_html(url_buf);
|
||||
if (purple_email_is_valid(tmpurlbuf)) {
|
||||
g_string_append_printf(ret, "<A HREF=\"mailto:%s\">%s</A>",
|
||||
url_buf, url_buf);
|
||||
} else {
|
||||
g_string_append(ret, url_buf);
|
||||
}
|
||||
g_free(url_buf);
|
||||
g_free(tmpurlbuf);
|
||||
c = t;
|
||||
|
||||
break;
|
||||
} else {
|
||||
g_string_append_unichar(gurl_buf, g);
|
||||
t = g_utf8_find_next_char(t, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(*c == ')' && !inside_html) {
|
||||
inside_paren--;
|
||||
ret = g_string_append_c(ret, *c);
|
||||
c++;
|
||||
}
|
||||
|
||||
if (*c == 0)
|
||||
break;
|
||||
|
||||
ret = g_string_append_c(ret, *c);
|
||||
c++;
|
||||
|
||||
}
|
||||
return g_string_free(ret, FALSE);
|
||||
}
|
||||
|
||||
struct authRequest {
|
||||
PurpleAccountRequestAuthorizationCb authorize_cb;
|
||||
PurpleAccountRequestAuthorizationCb deny_cb;
|
||||
|
@ -509,13 +208,13 @@ static std::string getAlias(PurpleBuddy *m_buddy) {
|
|||
|
||||
class SpectrumNetworkPlugin : public NetworkPlugin {
|
||||
public:
|
||||
SpectrumNetworkPlugin(const std::string &host, int port) : NetworkPlugin() {
|
||||
SpectrumNetworkPlugin() : NetworkPlugin() {
|
||||
|
||||
}
|
||||
|
||||
void handleExitRequest() {
|
||||
LOG4CXX_INFO(logger, "Exiting...");
|
||||
exit(1);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void getProtocolAndName(const std::string &legacyName, std::string &name, std::string &protocol) {
|
||||
|
@ -597,7 +296,7 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
|
|||
|
||||
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
|
||||
PurpleAccount *account = NULL;
|
||||
|
||||
|
||||
std::string name;
|
||||
std::string protocol;
|
||||
getProtocolAndName(legacyName, name, protocol);
|
||||
|
@ -614,7 +313,6 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
if (purple_accounts_find(name.c_str(), protocol.c_str()) != NULL) {
|
||||
LOG4CXX_INFO(logger, "Using previously created account with name '" << name.c_str() << "' and protocol '" << protocol << "'");
|
||||
account = purple_accounts_find(name.c_str(), protocol.c_str());
|
||||
|
@ -637,11 +335,13 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
|
|||
|
||||
setDefaultAccountOptions(account);
|
||||
|
||||
// Enable account + privacy lists
|
||||
purple_account_set_enabled(account, "spectrum", TRUE);
|
||||
if (KEYFILE_BOOL("service", "enable_privacy_lists")) {
|
||||
purple_account_set_privacy_type(account, PURPLE_PRIVACY_DENY_USERS);
|
||||
}
|
||||
|
||||
// Set the status
|
||||
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);
|
||||
|
@ -661,50 +361,6 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
|
|||
m_accounts.erase(account);
|
||||
|
||||
purple_accounts_delete(account);
|
||||
//
|
||||
// // 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);
|
||||
//
|
||||
// purple_notify_close_with_handle(account);
|
||||
// purple_request_close_with_handle(account);
|
||||
//
|
||||
// purple_accounts_remove(account);
|
||||
//
|
||||
// GSList *buddies = purple_find_buddies(account, NULL);
|
||||
// while(buddies) {
|
||||
// PurpleBuddy *b = (PurpleBuddy *) buddies->data;
|
||||
// purple_blist_remove_buddy(b);
|
||||
// buddies = g_slist_delete_link(buddies, buddies);
|
||||
// }
|
||||
//
|
||||
// /* Remove any open conversation for this account */
|
||||
// for (GList *it = purple_get_conversations(); it; ) {
|
||||
// PurpleConversation *conv = (PurpleConversation *) it->data;
|
||||
// it = it->next;
|
||||
// if (purple_conversation_get_account(conv) == account)
|
||||
// purple_conversation_destroy(conv);
|
||||
// }
|
||||
//
|
||||
// /* Remove this account's pounces */
|
||||
// // purple_pounce_destroy_all_by_account(account);
|
||||
//
|
||||
// /* This will cause the deletion of an old buddy icon. */
|
||||
// purple_buddy_icons_set_account_icon(account, NULL, 0);
|
||||
//
|
||||
// purple_account_destroy(account);
|
||||
// force returning of memory chunks allocated by libxml2 to kernel
|
||||
#ifndef WIN32
|
||||
malloc_trim(0);
|
||||
#endif
|
||||
|
@ -768,17 +424,30 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
|
|||
void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml) {
|
||||
PurpleAccount *account = m_sessions[user];
|
||||
if (account) {
|
||||
PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, legacyName.c_str(), account);
|
||||
PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, legacyName.c_str(), account);
|
||||
if (!conv) {
|
||||
conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, legacyName.c_str());
|
||||
conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, legacyName.c_str(), account);
|
||||
if (!conv) {
|
||||
conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, legacyName.c_str());
|
||||
}
|
||||
}
|
||||
if (xhtml.empty()) {
|
||||
gchar *_markup = purple_markup_escape_text(message.c_str(), -1);
|
||||
purple_conv_im_send(PURPLE_CONV_IM(conv), _markup);
|
||||
if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
|
||||
purple_conv_im_send(PURPLE_CONV_IM(conv), _markup);
|
||||
}
|
||||
else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
|
||||
purple_conv_chat_send(PURPLE_CONV_CHAT(conv), _markup);
|
||||
}
|
||||
g_free(_markup);
|
||||
}
|
||||
else {
|
||||
purple_conv_im_send(PURPLE_CONV_IM(conv), xhtml.c_str());
|
||||
if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
|
||||
purple_conv_im_send(PURPLE_CONV_IM(conv), xhtml.c_str());
|
||||
}
|
||||
else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
|
||||
purple_conv_chat_send(PURPLE_CONV_CHAT(conv), xhtml.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -989,9 +658,9 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
|
|||
}
|
||||
|
||||
void sendData(const std::string &string) {
|
||||
write(m_sock, string.c_str(), string.size());
|
||||
write(main_socket, string.c_str(), string.size());
|
||||
if (writeInput == 0)
|
||||
writeInput = purple_input_add(m_sock, PURPLE_INPUT_WRITE, &transportDataReceived, NULL);
|
||||
writeInput = purple_input_add(main_socket, PURPLE_INPUT_WRITE, &transportDataReceived, NULL);
|
||||
}
|
||||
|
||||
void readyForData() {
|
||||
|
@ -1213,8 +882,9 @@ static PurpleBlistUiOps blistUiOps =
|
|||
|
||||
static void conv_write_im(PurpleConversation *conv, const char *who, const char *msg, PurpleMessageFlags flags, time_t mtime) {
|
||||
// Don't forwards our own messages.
|
||||
if (flags & PURPLE_MESSAGE_SEND || flags & PURPLE_MESSAGE_SYSTEM)
|
||||
if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM && (flags & PURPLE_MESSAGE_SEND || flags & PURPLE_MESSAGE_SYSTEM)) {
|
||||
return;
|
||||
}
|
||||
PurpleAccount *account = purple_conversation_get_account(conv);
|
||||
|
||||
// char *striped = purple_markup_strip_html(message);
|
||||
|
@ -1253,19 +923,67 @@ static void conv_write_im(PurpleConversation *conv, const char *who, const char
|
|||
|
||||
// LOG4CXX_INFO(logger, "Received message body='" << message_ << "' xhtml='" << xhtml_ << "'");
|
||||
|
||||
np->handleMessage(np->m_accounts[account], w, message_, "", xhtml_);
|
||||
if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
|
||||
np->handleMessage(np->m_accounts[account], w, message_, "", xhtml_);
|
||||
}
|
||||
else {
|
||||
LOG4CXX_INFO(logger, "Received message body='" << message_ << "' name='" << purple_conversation_get_name(conv) << "' " << w);
|
||||
np->handleMessage(np->m_accounts[account], purple_conversation_get_name(conv), message_, w, xhtml_);
|
||||
}
|
||||
}
|
||||
|
||||
static void conv_chat_add_users(PurpleConversation *conv, GList *cbuddies, gboolean new_arrivals) {
|
||||
PurpleAccount *account = purple_conversation_get_account(conv);
|
||||
|
||||
GList *l = cbuddies;
|
||||
while (l != NULL) {
|
||||
PurpleConvChatBuddy *cb = (PurpleConvChatBuddy *)l->data;
|
||||
std::string name(cb->name);
|
||||
int flags = GPOINTER_TO_INT(cb->flags);
|
||||
if (flags & PURPLE_CBFLAGS_OP || flags & PURPLE_CBFLAGS_HALFOP) {
|
||||
// item->addAttribute("affiliation", "admin");
|
||||
// item->addAttribute("role", "moderator");
|
||||
flags = 1;
|
||||
}
|
||||
else if (flags & PURPLE_CBFLAGS_FOUNDER) {
|
||||
// item->addAttribute("affiliation", "owner");
|
||||
// item->addAttribute("role", "moderator");
|
||||
flags = 1;
|
||||
}
|
||||
else {
|
||||
flags = 0;
|
||||
// item->addAttribute("affiliation", "member");
|
||||
// item->addAttribute("role", "participant");
|
||||
}
|
||||
|
||||
np->handleParticipantChanged(np->m_accounts[account], name, purple_conversation_get_name(conv), (int) flags, pbnetwork::STATUS_ONLINE);
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void conv_chat_remove_users(PurpleConversation *conv, GList *users) {
|
||||
PurpleAccount *account = purple_conversation_get_account(conv);
|
||||
|
||||
GList *l = users;
|
||||
while (l != NULL) {
|
||||
std::string name((char *) l->data);
|
||||
np->handleParticipantChanged(np->m_accounts[account], name, purple_conversation_get_name(conv), 0, pbnetwork::STATUS_NONE);
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
|
||||
static PurpleConversationUiOps conversation_ui_ops =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,//conv_write_chat, /* write_chat */
|
||||
conv_write_im,//conv_write_chat, /* write_chat */
|
||||
conv_write_im, /* write_im */
|
||||
NULL,//conv_write_conv, /* write_conv */
|
||||
NULL,//conv_chat_add_users, /* chat_add_users */
|
||||
conv_chat_add_users, /* chat_add_users */
|
||||
NULL,//conv_chat_rename_user, /* chat_rename_user */
|
||||
NULL,//conv_chat_remove_users, /* chat_remove_users */
|
||||
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 */
|
||||
|
@ -1407,11 +1125,13 @@ static void *notify_user_info(PurpleConnection *gc, const char *who, PurpleNotif
|
|||
if (true) {
|
||||
gchar *data;
|
||||
gchar *path = purple_buddy_icon_get_full_path(icon);
|
||||
if (g_file_get_contents (path, &data, &len, NULL)) {
|
||||
photo = std::string(data, len);
|
||||
free(data);
|
||||
if (path) {
|
||||
if (g_file_get_contents(path, &data, &len, NULL)) {
|
||||
photo = std::string(data, len);
|
||||
g_free(data);
|
||||
}
|
||||
g_free(path);
|
||||
}
|
||||
free(path);
|
||||
}
|
||||
else {
|
||||
const gchar * data = (gchar*)purple_buddy_icon_get_data(icon, &len);
|
||||
|
@ -1800,9 +1520,8 @@ static bool initPurple() {
|
|||
remove("./accounts.xml");
|
||||
remove("./blist.xml");
|
||||
|
||||
// if (m_configuration.logAreas & LOG_AREA_PURPLE)
|
||||
purple_debug_set_ui_ops(&debugUiOps);
|
||||
purple_debug_set_verbose(true);
|
||||
purple_debug_set_ui_ops(&debugUiOps);
|
||||
purple_debug_set_verbose(true);
|
||||
|
||||
purple_core_set_ui_ops(&coreUiOps);
|
||||
if (KEYFILE_STRING("service", "eventloop") == "libev") {
|
||||
|
@ -1866,50 +1585,7 @@ static bool initPurple() {
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
#ifndef WIN32
|
||||
static void spectrum_sigchld_handler(int sig)
|
||||
{
|
||||
int status;
|
||||
pid_t pid;
|
||||
|
||||
do {
|
||||
pid = waitpid(-1, &status, WNOHANG);
|
||||
} while (pid != 0 && pid != (pid_t)-1);
|
||||
|
||||
if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
|
||||
char errmsg[BUFSIZ];
|
||||
snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
|
||||
perror(errmsg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int create_socket(char *host, int portno) {
|
||||
struct sockaddr_in serv_addr;
|
||||
|
||||
int m_sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
memset((char *) &serv_addr, 0, sizeof(serv_addr));
|
||||
serv_addr.sin_family = AF_INET;
|
||||
serv_addr.sin_port = htons(portno);
|
||||
|
||||
hostent *hos; // Resolve name
|
||||
if ((hos = gethostbyname(host)) == NULL) {
|
||||
// strerror() will not work for gethostbyname() and hstrerror()
|
||||
// is supposedly obsolete
|
||||
exit(1);
|
||||
}
|
||||
serv_addr.sin_addr.s_addr = *((unsigned long *) hos->h_addr_list[0]);
|
||||
|
||||
if (connect(m_sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
|
||||
close(m_sock);
|
||||
m_sock = 0;
|
||||
}
|
||||
|
||||
int flags = fcntl(m_sock, F_GETFL);
|
||||
flags |= O_NONBLOCK;
|
||||
fcntl(m_sock, F_SETFL, flags);
|
||||
return m_sock;
|
||||
}
|
||||
|
||||
static void transportDataReceived(gpointer data, gint source, PurpleInputCondition cond) {
|
||||
if (cond & PURPLE_INPUT_READ) {
|
||||
|
@ -1938,17 +1614,10 @@ int main(int argc, char **argv) {
|
|||
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";
|
||||
std::cerr << "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";
|
||||
|
@ -1972,27 +1641,6 @@ int main(int argc, char **argv) {
|
|||
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
|
||||
keyfile = g_key_file_new ();
|
||||
if (!g_key_file_load_from_file (keyfile, argv[1], (GKeyFileFlags) 0, 0)) {
|
||||
|
@ -2027,12 +1675,11 @@ int main(int argc, char **argv) {
|
|||
|
||||
initPurple();
|
||||
|
||||
m_sock = create_socket(host, port);
|
||||
|
||||
purple_input_add(m_sock, PURPLE_INPUT_READ, &transportDataReceived, NULL);
|
||||
main_socket = create_socket(host, port);
|
||||
purple_input_add(main_socket, PURPLE_INPUT_READ, &transportDataReceived, NULL);
|
||||
purple_timeout_add_seconds(30, pingTimeout, NULL);
|
||||
|
||||
np = new SpectrumNetworkPlugin(host, port);
|
||||
np = new SpectrumNetworkPlugin();
|
||||
bool libev = KEYFILE_STRING("service", "eventloop") == "libev";
|
||||
|
||||
GMainLoop *m_loop;
|
||||
|
|
129
backends/libpurple/utils.cpp
Normal file
129
backends/libpurple/utils.cpp
Normal file
|
@ -0,0 +1,129 @@
|
|||
/**
|
||||
* 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 "utils.h"
|
||||
|
||||
#include "glib.h"
|
||||
#include "purple.h"
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
#include "errno.h"
|
||||
|
||||
#ifndef WIN32
|
||||
#include "sys/wait.h"
|
||||
#include "sys/signal.h"
|
||||
#include <netinet/if_ether.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/ether.h>
|
||||
#include "sys/socket.h"
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#else
|
||||
#include <process.h>
|
||||
#define getpid _getpid
|
||||
#define ssize_t SSIZE_T
|
||||
#include "win32/win32dep.h"
|
||||
#endif
|
||||
|
||||
static GHashTable *ui_info = NULL;
|
||||
|
||||
GHashTable *spectrum_ui_get_info(void)
|
||||
{
|
||||
if(NULL == ui_info) {
|
||||
ui_info = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
|
||||
g_hash_table_insert(ui_info, g_strdup("name"), g_strdup("Spectrum"));
|
||||
g_hash_table_insert(ui_info, g_strdup("version"), g_strdup("0.5"));
|
||||
g_hash_table_insert(ui_info, g_strdup("website"), g_strdup("http://spectrum.im"));
|
||||
g_hash_table_insert(ui_info, g_strdup("dev_website"), g_strdup("http://spectrum.im"));
|
||||
g_hash_table_insert(ui_info, g_strdup("client_type"), g_strdup("pc"));
|
||||
|
||||
/*
|
||||
* This is the client key for "Pidgin." It is owned by the AIM
|
||||
* account "markdoliner." Please don't use this key for other
|
||||
* applications. You can either not specify a client key, in
|
||||
* which case the default "libpurple" key will be used, or you
|
||||
* can register for your own client key at
|
||||
* http://developer.aim.com/manageKeys.jsp
|
||||
*/
|
||||
g_hash_table_insert(ui_info, g_strdup("prpl-aim-clientkey"), g_strdup("ma1cSASNCKFtrdv9"));
|
||||
g_hash_table_insert(ui_info, g_strdup("prpl-icq-clientkey"), g_strdup("ma1cSASNCKFtrdv9"));
|
||||
|
||||
/*
|
||||
* This is the distid for Pidgin, given to us by AOL. Please
|
||||
* don't use this for other applications. You can just not
|
||||
* specify a distid and libpurple will use a default.
|
||||
*/
|
||||
g_hash_table_insert(ui_info, g_strdup("prpl-aim-distid"), GINT_TO_POINTER(1550));
|
||||
g_hash_table_insert(ui_info, g_strdup("prpl-icq-distid"), GINT_TO_POINTER(1550));
|
||||
}
|
||||
|
||||
return ui_info;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
void spectrum_sigchld_handler(int sig)
|
||||
{
|
||||
int status;
|
||||
pid_t pid;
|
||||
|
||||
do {
|
||||
pid = waitpid(-1, &status, WNOHANG);
|
||||
} while (pid != 0 && pid != (pid_t)-1);
|
||||
|
||||
if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
|
||||
char errmsg[BUFSIZ];
|
||||
snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
|
||||
perror(errmsg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int create_socket(char *host, int portno) {
|
||||
struct sockaddr_in serv_addr;
|
||||
|
||||
int main_socket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
memset((char *) &serv_addr, 0, sizeof(serv_addr));
|
||||
serv_addr.sin_family = AF_INET;
|
||||
serv_addr.sin_port = htons(portno);
|
||||
|
||||
hostent *hos; // Resolve name
|
||||
if ((hos = gethostbyname(host)) == NULL) {
|
||||
// strerror() will not work for gethostbyname() and hstrerror()
|
||||
// is supposedly obsolete
|
||||
exit(1);
|
||||
}
|
||||
serv_addr.sin_addr.s_addr = *((unsigned long *) hos->h_addr_list[0]);
|
||||
|
||||
if (connect(main_socket, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
|
||||
close(main_socket);
|
||||
main_socket = 0;
|
||||
}
|
||||
|
||||
int flags = fcntl(main_socket, F_GETFL);
|
||||
flags |= O_NONBLOCK;
|
||||
fcntl(main_socket, F_SETFL, flags);
|
||||
return main_socket;
|
||||
}
|
30
backends/libpurple/utils.h
Normal file
30
backends/libpurple/utils.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* 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 "purple.h"
|
||||
|
||||
#ifndef WIN32
|
||||
void spectrum_sigchld_handler(int sig);
|
||||
#endif
|
||||
|
||||
int create_socket(char *host, int portno);
|
||||
GHashTable *spectrum_ui_get_info(void);
|
|
@ -2,8 +2,10 @@
|
|||
#include <iostream>
|
||||
|
||||
#include "transport/config.h"
|
||||
#include "transport/logging.h"
|
||||
#include "transport/transport.h"
|
||||
#include "transport/usermanager.h"
|
||||
#include "transport/memoryusage.h"
|
||||
#include "transport/logger.h"
|
||||
#include "transport/sqlite3backend.h"
|
||||
#include "transport/userregistration.h"
|
||||
|
@ -34,6 +36,10 @@ using namespace Transport;
|
|||
|
||||
class SpectrumNetworkPlugin;
|
||||
|
||||
#define GET_RESPONSE_DATA(RESP, DATA) ((RESP.find(std::string(DATA) + " ") != std::string::npos) ? RESP.substr(RESP.find(DATA) + strlen(DATA) + 1) : "");
|
||||
#define GET_PROPERTY(VAR, OBJ, WHICH, PROP) std::string VAR = sk->send_command(std::string("GET ") + OBJ + " " + WHICH + " " + PROP); \
|
||||
VAR = GET_RESPONSE_DATA(VAR, PROP);
|
||||
|
||||
|
||||
SpectrumNetworkPlugin *np;
|
||||
|
||||
|
@ -81,7 +87,7 @@ static pbnetwork::StatusType getStatus(const std::string &st) {
|
|||
class Skype {
|
||||
public:
|
||||
Skype(const std::string &user, const std::string &username, const std::string &password);
|
||||
~Skype() { logout(); }
|
||||
~Skype() { LOG4CXX_INFO(logger, "Skype instance desctuctor"); logout(); }
|
||||
void login();
|
||||
void logout();
|
||||
std::string send_command(const std::string &message);
|
||||
|
@ -97,6 +103,10 @@ class Skype {
|
|||
bool createDBusProxy();
|
||||
bool loadSkypeBuddies();
|
||||
|
||||
int getPid() {
|
||||
return (int) m_pid;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_username;
|
||||
std::string m_password;
|
||||
|
@ -124,7 +134,9 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
|
|||
|
||||
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
|
||||
std::string name = legacyName;
|
||||
name = name.substr(name.find(".") + 1);
|
||||
if (name.find("skype.") == 0 || name.find("prpl-skype.") == 0) {
|
||||
name = name.substr(name.find(".") + 1);
|
||||
}
|
||||
LOG4CXX_INFO(logger, "Creating account with name '" << name << "'");
|
||||
|
||||
Skype *skype = new Skype(user, name, password);
|
||||
|
@ -134,9 +146,25 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
|
|||
skype->login();
|
||||
}
|
||||
|
||||
void handleMemoryUsage(double &res, double &shared) {
|
||||
res = 0;
|
||||
shared = 0;
|
||||
for(std::map<std::string, Skype *>::const_iterator it = m_sessions.begin(); it != m_sessions.end(); it++) {
|
||||
Skype *skype = it->second;
|
||||
if (skype) {
|
||||
double r;
|
||||
double s;
|
||||
process_mem_usage(s, r, skype->getPid());
|
||||
res += r;
|
||||
shared += s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
|
||||
Skype *skype = m_sessions[user];
|
||||
if (skype) {
|
||||
LOG4CXX_INFO(logger, "User wants to logout, logging out");
|
||||
skype->logout();
|
||||
exit(1);
|
||||
}
|
||||
|
@ -178,6 +206,21 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
|
||||
Skype *skype = m_sessions[user];
|
||||
if (skype) {
|
||||
skype->send_command("SET USER " + buddyName + " BUDDYSTATUS 2 Please authorize me");
|
||||
skype->send_command("SET USER " + buddyName + " ISAUTHORIZED TRUE");
|
||||
}
|
||||
}
|
||||
|
||||
void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
|
||||
Skype *skype = m_sessions[user];
|
||||
if (skype) {
|
||||
skype->send_command("SET USER " + buddyName + " BUDDYSTATUS 1");
|
||||
}
|
||||
}
|
||||
|
||||
void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml) {
|
||||
Skype *skype = m_sessions[user];
|
||||
if (skype) {
|
||||
|
@ -253,7 +296,7 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
|
|||
std::cout << skype->getUsername() << " " << name << "\n";
|
||||
if (skype->getUsername() == name) {
|
||||
alias = skype->send_command("GET PROFILE FULLNAME");
|
||||
alias = alias.substr(17);
|
||||
alias = GET_RESPONSE_DATA(alias, "FULLNAME")
|
||||
}
|
||||
handleVCard(user, id, legacyName, "", alias, photo);
|
||||
}
|
||||
|
@ -268,13 +311,6 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
|
|||
void handleVCardUpdatedRequest(const std::string &user, const std::string &p, const std::string &nickname) {
|
||||
}
|
||||
|
||||
void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
|
||||
}
|
||||
|
||||
void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
|
||||
|
||||
}
|
||||
|
||||
void handleBuddyBlockToggled(const std::string &user, const std::string &buddyName, bool blocked) {
|
||||
|
||||
}
|
||||
|
@ -331,7 +367,8 @@ bool Skype::createDBusProxy() {
|
|||
LOG4CXX_INFO(logger, m_username << ":" << error->message);
|
||||
|
||||
if (m_counter == 15) {
|
||||
np->handleDisconnected(m_user, 0, error->message);
|
||||
LOG4CXX_ERROR(logger, "Logging out, proxy couldn't be created");
|
||||
np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, error->message);
|
||||
logout();
|
||||
g_error_free(error);
|
||||
return FALSE;
|
||||
|
@ -360,6 +397,12 @@ static gboolean create_dbus_proxy(gpointer data) {
|
|||
}
|
||||
|
||||
void Skype::login() {
|
||||
if (m_username.find("..") == 0 || m_username.find("/") != std::string::npos) {
|
||||
np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Invalid username");
|
||||
return;
|
||||
}
|
||||
boost::filesystem::remove_all(std::string("/tmp/skype/") + m_username);
|
||||
|
||||
boost::filesystem::path path(std::string("/tmp/skype/") + m_username);
|
||||
if (!boost::filesystem::exists(path)) {
|
||||
boost::filesystem::create_directories(path);
|
||||
|
@ -394,6 +437,7 @@ void Skype::login() {
|
|||
"</config>\n";
|
||||
g_file_set_contents(std::string(std::string("/tmp/skype/") + m_username + "/" + m_username +"/config.xml").c_str(), config_xml.c_str(), -1, NULL);
|
||||
|
||||
sleep(1);
|
||||
std::string db_path = std::string("/tmp/skype/") + m_username;
|
||||
char *db = (char *) malloc(db_path.size() + 1);
|
||||
strcpy(db, db_path.c_str());
|
||||
|
@ -437,6 +481,7 @@ void Skype::login() {
|
|||
}
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
m_timer = g_timeout_add_seconds(1, create_dbus_proxy, this);
|
||||
}
|
||||
|
||||
|
@ -449,28 +494,35 @@ bool Skype::loadSkypeBuddies() {
|
|||
int bytes_read = read(fd_output, buffer, 1023);
|
||||
if (bytes_read > 0) {
|
||||
buffer[bytes_read] = 0;
|
||||
np->handleDisconnected(m_user, 0, buffer);
|
||||
close(fd_output);
|
||||
logout();
|
||||
return FALSE;
|
||||
std::string b(buffer);
|
||||
LOG4CXX_WARN(logger, "Skype wrote this on stdout '" << b << "'");
|
||||
if (b.find("Incorrect Password") != std::string::npos) {
|
||||
LOG4CXX_INFO(logger, "Incorrect password, logging out")
|
||||
np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_FAILED, "Incorrect password");
|
||||
close(fd_output);
|
||||
logout();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
std::string re = send_command("NAME Spectrum");
|
||||
if (m_counter++ > 15) {
|
||||
np->handleDisconnected(m_user, 0, "");
|
||||
LOG4CXX_ERROR(logger, "Logging out, because we tried to connect the Skype over DBUS 15 times without success");
|
||||
np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Skype is not ready. This issue have been logged and admins will check it and try to fix it soon.");
|
||||
close(fd_output);
|
||||
logout();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (re.empty() || re == "CONNSTATUS OFFLINE") {
|
||||
if (re.empty() || re == "CONNSTATUS OFFLINE" || re == "ERROR 68") {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
close(fd_output);
|
||||
|
||||
if (send_command("PROTOCOL 7") != "PROTOCOL 7") {
|
||||
np->handleDisconnected(m_user, 0, "Skype is not ready");
|
||||
LOG4CXX_ERROR(logger, "PROTOCOL 7 failed, logging out");
|
||||
np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Skype is not ready. This issue have been logged and admins will check it and try to fix it soon.");
|
||||
logout();
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -479,20 +531,27 @@ bool Skype::loadSkypeBuddies() {
|
|||
|
||||
std::map<std::string, std::string> group_map;
|
||||
std::string groups = send_command("SEARCH GROUPS CUSTOM");
|
||||
groups = groups.substr(groups.find(' ') + 1);
|
||||
std::vector<std::string> grps;
|
||||
boost::split(grps, groups, boost::is_any_of(","));
|
||||
BOOST_FOREACH(std::string grp, grps) {
|
||||
std::vector<std::string> data;
|
||||
std::string name = send_command("GET GROUP " + grp + " DISPLAYNAME");
|
||||
boost::split(data, name, boost::is_any_of(" "));
|
||||
name = name.substr(name.find("DISPLAYNAME") + 12);
|
||||
if (groups.find(' ') != std::string::npos) {
|
||||
groups = groups.substr(groups.find(' ') + 1);
|
||||
std::vector<std::string> grps;
|
||||
boost::split(grps, groups, boost::is_any_of(","));
|
||||
BOOST_FOREACH(std::string grp, grps) {
|
||||
std::vector<std::string> data;
|
||||
std::string name = send_command("GET GROUP " + grp + " DISPLAYNAME");
|
||||
|
||||
std::string users = send_command("GET GROUP " + data[1] + " USERS");
|
||||
users = name.substr(name.find("USERS") + 6);
|
||||
boost::split(data, users, boost::is_any_of(","));
|
||||
BOOST_FOREACH(std::string u, data) {
|
||||
group_map[u] = grp;
|
||||
if (name.find("ERROR") == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boost::split(data, name, boost::is_any_of(" "));
|
||||
name = GET_RESPONSE_DATA(name, "DISPLAYNAME");
|
||||
|
||||
std::string users = send_command("GET GROUP " + data[1] + " USERS");
|
||||
users = GET_RESPONSE_DATA(users, "USERS");
|
||||
boost::split(data, users, boost::is_any_of(","));
|
||||
BOOST_FOREACH(std::string u, data) {
|
||||
group_map[u] = grp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -565,6 +624,7 @@ std::string Skype::send_command(const std::string &message) {
|
|||
// int message_num;
|
||||
// gchar error_return[30];
|
||||
|
||||
LOG4CXX_INFO(logger, "Sending: '" << message << "'");
|
||||
if (!dbus_g_proxy_call (m_proxy, "Invoke", &error, G_TYPE_STRING, message.c_str(), G_TYPE_INVALID,
|
||||
G_TYPE_STRING, &str, G_TYPE_INVALID))
|
||||
{
|
||||
|
@ -572,14 +632,16 @@ std::string Skype::send_command(const std::string &message) {
|
|||
{
|
||||
LOG4CXX_INFO(logger, m_username << ": DBUS Error: " << error->message);
|
||||
g_error_free(error);
|
||||
return "";
|
||||
} else {
|
||||
LOG4CXX_INFO(logger, m_username << ": DBUS no response");
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
if (str != NULL)
|
||||
{
|
||||
LOG4CXX_INFO(logger, m_username << ": DBUS:" << str);
|
||||
LOG4CXX_INFO(logger, m_username << ": DBUS:'" << str << "'");
|
||||
}
|
||||
return str ? std::string(str) : std::string();
|
||||
}
|
||||
|
@ -599,70 +661,73 @@ static void handle_skype_message(std::string &message, Skype *sk) {
|
|||
}
|
||||
else {
|
||||
pbnetwork::StatusType status = getStatus(cmd[3]);
|
||||
std::string mood_text = sk->send_command("GET USER " + cmd[1] + " MOOD_TEXT");
|
||||
mood_text = mood_text.substr(mood_text.find("MOOD_TEXT") + 10);
|
||||
|
||||
std::string alias = sk->send_command("GET USER " + cmd[1] + " FULLNAME");
|
||||
alias = alias.substr(alias.find("FULLNAME") + 9);
|
||||
GET_PROPERTY(mood_text, "USER", cmd[1], "MOOD_TEXT");
|
||||
GET_PROPERTY(alias, "USER", cmd[1], "FULLNAME");
|
||||
|
||||
std::vector<std::string> groups;
|
||||
np->handleBuddyChanged(sk->getUser(), cmd[1], alias, groups, status, mood_text);
|
||||
}
|
||||
}
|
||||
else if (cmd[2] == "MOOD_TEXT") {
|
||||
std::string st = sk->send_command("GET USER " + cmd[1] + " ONLINESTATUS");
|
||||
st = st.substr(st.find("ONLINESTATUS") + 13);
|
||||
GET_PROPERTY(st, "USER", cmd[1], "ONLINESTATUS");
|
||||
pbnetwork::StatusType status = getStatus(st);
|
||||
|
||||
std::string mood_text = message.substr(message.find("MOOD_TEXT") + 10);
|
||||
std::string mood_text = GET_RESPONSE_DATA(message, "MOOD_TEXT");
|
||||
|
||||
std::vector<std::string> groups;
|
||||
np->handleBuddyChanged(sk->getUser(), cmd[1], "", groups, status, mood_text);
|
||||
}
|
||||
else if (cmd[2] == "BUDDYSTATUS" && cmd[3] == "3") {
|
||||
std::string st = sk->send_command("GET USER " + cmd[1] + " ONLINESTATUS");
|
||||
st = st.substr(st.find("ONLINESTATUS") + 13);
|
||||
GET_PROPERTY(mood_text, "USER", cmd[1], "MOOD_TEXT");
|
||||
GET_PROPERTY(st, "USER", cmd[1], "ONLINESTATUS");
|
||||
pbnetwork::StatusType status = getStatus(st);
|
||||
|
||||
std::string mood_text = message.substr(message.find("MOOD_TEXT") + 10);
|
||||
|
||||
std::vector<std::string> groups;
|
||||
np->handleBuddyChanged(sk->getUser(), cmd[1], "", groups, status, mood_text);
|
||||
}
|
||||
else if (cmd[2] == "FULLNAME") {
|
||||
std::string st = sk->send_command("GET USER " + cmd[1] + " ONLINESTATUS");
|
||||
st = st.substr(st.find("ONLINESTATUS") + 13);
|
||||
GET_PROPERTY(alias, "USER", cmd[1], "FULLNAME");
|
||||
GET_PROPERTY(mood_text, "USER", cmd[1], "MOOD_TEXT");
|
||||
GET_PROPERTY(st, "USER", cmd[1], "ONLINESTATUS");
|
||||
pbnetwork::StatusType status = getStatus(st);
|
||||
|
||||
std::string mood_text = sk->send_command("GET USER " + cmd[1] + " MOOD_TEXT");
|
||||
mood_text = mood_text.substr(mood_text.find("MOOD_TEXT") + 10);
|
||||
|
||||
std::string alias = message.substr(message.find("FULLNAME") + 9);
|
||||
|
||||
std::vector<std::string> groups;
|
||||
np->handleBuddyChanged(sk->getUser(), cmd[1], alias, groups, status, mood_text);
|
||||
}
|
||||
}
|
||||
else if (cmd[0] == "CHATMESSAGE") {
|
||||
if (cmd[3] == "RECEIVED") {
|
||||
std::string body = sk->send_command("GET CHATMESSAGE " + cmd[1] + " BODY");
|
||||
body = body.substr(body.find("BODY") + 5);
|
||||
GET_PROPERTY(body, "CHATMESSAGE", cmd[1], "BODY");
|
||||
GET_PROPERTY(from_handle, "CHATMESSAGE", cmd[1], "FROM_HANDLE");
|
||||
|
||||
std::string chatname = sk->send_command("GET CHATMESSAGE " + cmd[1] + " CHATNAME");
|
||||
size_t start = chatname.find("$") + 1;
|
||||
size_t len = chatname.find(";") - start;
|
||||
std::string from = chatname.substr(start, len);
|
||||
|
||||
std::string from_handle = sk->send_command("GET CHATMESSAGE " + cmd[1] + " FROM_HANDLE");
|
||||
from_handle = from_handle.substr(from_handle.find("FROM_HANDLE") + 12);
|
||||
|
||||
// if (from_handle != sk->getUsername()) {
|
||||
from = from_handle;
|
||||
// }
|
||||
if (from_handle == sk->getUsername())
|
||||
return;
|
||||
|
||||
np->handleMessage(sk->getUser(), from, body);
|
||||
np->handleMessage(sk->getUser(), from_handle, body);
|
||||
|
||||
sk->send_command("SET CHATMESSAGE " + cmd[1] + " SEEN");
|
||||
}
|
||||
}
|
||||
else if (cmd[0] == "CALL") {
|
||||
// CALL 884 STATUS RINGING
|
||||
if (cmd[2] == "STATUS") {
|
||||
if (cmd[3] == "RINGING" || cmd[3] == "MISSED") {
|
||||
// handle only incoming calls
|
||||
GET_PROPERTY(type, "CALL", cmd[1], "TYPE");
|
||||
if (type.find("INCOMING") != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
GET_PROPERTY(from, "CALL", cmd[1], "PARTNER_HANDLE");
|
||||
GET_PROPERTY(dispname, "CALL", cmd[1], "PARTNER_DISPNAME");
|
||||
|
||||
if (cmd[3] == "RINGING") {
|
||||
np->handleMessage(sk->getUser(), from, "User " + dispname + " is calling you.");
|
||||
}
|
||||
else {
|
||||
np->handleMessage(sk->getUser(), from, "You have missed call from user " + dispname + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -825,18 +890,7 @@ int main(int argc, char **argv) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (CONFIG_STRING(&config, "logging.backend_config").empty()) {
|
||||
LoggerPtr root = log4cxx::Logger::getRootLogger();
|
||||
root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n")));
|
||||
}
|
||||
else {
|
||||
log4cxx::helpers::Properties p;
|
||||
log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(&config, "logging.backend_config"));
|
||||
|
||||
p.load(istream);
|
||||
p.setProperty("pid", boost::lexical_cast<std::string>(getpid()));
|
||||
log4cxx::PropertyConfigurator::configure(p);
|
||||
}
|
||||
Logging::initBackendLogging(&config);
|
||||
|
||||
// initPurple(config);
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
*/
|
||||
|
||||
#include "transport/config.h"
|
||||
#include "transport/logging.h"
|
||||
#include "transport/networkplugin.h"
|
||||
#include "transport/sqlite3backend.h"
|
||||
#include "transport/mysqlbackend.h"
|
||||
|
@ -312,80 +313,19 @@ int main (int argc, char* argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (CONFIG_STRING(&config, "logging.backend_config").empty()) {
|
||||
LoggerPtr root = log4cxx::Logger::getRootLogger();
|
||||
#ifndef _MSC_VER
|
||||
root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n")));
|
||||
#else
|
||||
root->addAppender(new ConsoleAppender(new PatternLayout(L"%d %-5p %c: %m%n")));
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
log4cxx::helpers::Properties p;
|
||||
log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(&config, "logging.backend_config"));
|
||||
p.load(istream);
|
||||
LogString pid, jid;
|
||||
log4cxx::helpers::Transcoder::decode(boost::lexical_cast<std::string>(getpid()), pid);
|
||||
log4cxx::helpers::Transcoder::decode(CONFIG_STRING(&config, "service.jid"), jid);
|
||||
#ifdef _MSC_VER
|
||||
p.setProperty(L"pid", pid);
|
||||
p.setProperty(L"jid", jid);
|
||||
#else
|
||||
p.setProperty("pid", pid);
|
||||
p.setProperty("jid", jid);
|
||||
#endif
|
||||
log4cxx::PropertyConfigurator::configure(p);
|
||||
}
|
||||
Logging::initBackendLogging(&config);
|
||||
|
||||
#ifdef WITH_SQLITE
|
||||
if (CONFIG_STRING(&config, "database.type") == "sqlite3") {
|
||||
storageBackend = new SQLite3Backend(&config);
|
||||
if (!storageBackend->connect()) {
|
||||
std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
|
||||
return -1;
|
||||
std::string error;
|
||||
StorageBackend *storageBackend = StorageBackend::createBackend(&config, error);
|
||||
if (storageBackend == NULL) {
|
||||
if (!error.empty()) {
|
||||
std::cerr << error << "\n";
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (CONFIG_STRING(&config, "database.type") == "sqlite3") {
|
||||
std::cerr << "Spectrum2 is not compiled with mysql backend.\n";
|
||||
return -2;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_MYSQL
|
||||
if (CONFIG_STRING(&config, "database.type") == "mysql") {
|
||||
storageBackend = new MySQLBackend(&config);
|
||||
if (!storageBackend->connect()) {
|
||||
std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (CONFIG_STRING(&config, "database.type") == "mysql") {
|
||||
std::cerr << "Spectrum2 is not compiled with mysql backend.\n";
|
||||
return -2;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_PQXX
|
||||
if (CONFIG_STRING(&config, "database.type") == "pqxx") {
|
||||
storageBackend = new PQXXBackend(&config);
|
||||
if (!storageBackend->connect()) {
|
||||
std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (CONFIG_STRING(&config, "database.type") == "pqxx") {
|
||||
std::cerr << "Spectrum2 is not compiled with pqxx backend.\n";
|
||||
return -2;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (CONFIG_STRING(&config, "database.type") != "mysql" && CONFIG_STRING(&config, "database.type") != "sqlite3"
|
||||
&& CONFIG_STRING(&config, "database.type") != "pqxx" && CONFIG_STRING(&config, "database.type") != "none") {
|
||||
std::cerr << "Unknown storage backend " << CONFIG_STRING(&config, "database.type") << "\n";
|
||||
return -2;
|
||||
else if (!storageBackend->connect()) {
|
||||
std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
Swift::SimpleEventLoop eventLoop;
|
||||
|
|
|
@ -39,6 +39,9 @@ typedef enum { BUDDY_NO_FLAG = 0,
|
|||
/// Represents one legacy network Buddy.
|
||||
class Buddy {
|
||||
public:
|
||||
typedef enum { Ask,
|
||||
Both,
|
||||
} Subscription;
|
||||
/// Constructor.
|
||||
|
||||
/// \param rosterManager RosterManager associated with this buddy.
|
||||
|
@ -93,12 +96,12 @@ class Buddy {
|
|||
/// Sets current subscription.
|
||||
|
||||
/// \param subscription "to", "from", "both", "ask"
|
||||
void setSubscription(const std::string &subscription);
|
||||
void setSubscription(Subscription subscription);
|
||||
|
||||
/// Returns current subscription
|
||||
|
||||
/// \return subscription "to", "from", "both", "ask"
|
||||
const std::string getSubscription();
|
||||
Subscription getSubscription();
|
||||
|
||||
/// Sets this buddy's flags.
|
||||
|
||||
|
@ -172,6 +175,7 @@ class Buddy {
|
|||
Swift::JID m_jid;
|
||||
BuddyFlag m_flags;
|
||||
RosterManager *m_rosterManager;
|
||||
Subscription m_subscription;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
39
include/transport/logging.h
Normal file
39
include/transport/logging.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace Transport {
|
||||
|
||||
class Config;
|
||||
|
||||
namespace Logging {
|
||||
|
||||
void initBackendLogging(Config *config);
|
||||
void initMainLogging(Config *config);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -22,10 +22,14 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#ifndef WIN32
|
||||
#include "signal.h"
|
||||
#endif
|
||||
|
||||
namespace Transport {
|
||||
|
||||
#ifndef WIN32
|
||||
void process_mem_usage(double& shared, double& resident_set);
|
||||
void process_mem_usage(double& shared, double& resident_set, pid_t pid = 0);
|
||||
#endif
|
||||
|
||||
}
|
|
@ -211,6 +211,8 @@ class NetworkPlugin {
|
|||
virtual void handleFTPauseRequest(unsigned long ftID) {}
|
||||
virtual void handleFTContinueRequest(unsigned long ftID) {}
|
||||
|
||||
virtual void handleMemoryUsage(double &res, double &shared) {res = 0; shared = 0;}
|
||||
|
||||
virtual void handleExitRequest() { exit(1); }
|
||||
void handleDataRead(std::string &data);
|
||||
virtual void sendData(const std::string &string) {}
|
||||
|
|
|
@ -56,6 +56,7 @@ class NetworkPluginServer {
|
|||
bool acceptUsers;
|
||||
bool longRun;
|
||||
bool willDie;
|
||||
std::string id;
|
||||
};
|
||||
|
||||
NetworkPluginServer(Component *component, Config *config, UserManager *userManager, FileTransferManager *ftManager);
|
||||
|
@ -70,6 +71,10 @@ class NetworkPluginServer {
|
|||
return m_clients;
|
||||
}
|
||||
|
||||
const std::vector<std::string> &getCrashedBackends() {
|
||||
return m_crashedBackends;
|
||||
}
|
||||
|
||||
void collectBackend();
|
||||
|
||||
bool moveToLongRunBackend(User *user);
|
||||
|
@ -137,6 +142,7 @@ class NetworkPluginServer {
|
|||
bool m_isNextLongRun;
|
||||
std::map<unsigned long, FileTransferManager::Transfer> m_filetransfers;
|
||||
FileTransferManager *m_ftManager;
|
||||
std::vector<std::string> m_crashedBackends;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -106,6 +106,7 @@ message Stats {
|
|||
required int32 res = 1;
|
||||
required int32 init_res = 2;
|
||||
required int32 shared = 3;
|
||||
required string id = 4;
|
||||
}
|
||||
|
||||
message File {
|
||||
|
|
|
@ -80,6 +80,8 @@ struct BuddyInfo {
|
|||
int flags;
|
||||
};
|
||||
|
||||
class Config;
|
||||
|
||||
/// Abstract class defining storage backends.
|
||||
class StorageBackend
|
||||
{
|
||||
|
@ -87,6 +89,8 @@ class StorageBackend
|
|||
/// Virtual desctructor.
|
||||
virtual ~StorageBackend() {}
|
||||
|
||||
static StorageBackend *createBackend(Config *config, std::string &error);
|
||||
|
||||
/// connect
|
||||
virtual bool connect() = 0;
|
||||
|
||||
|
|
|
@ -116,6 +116,13 @@ class UserManager : public Swift::EntityCapsProvider {
|
|||
/// \param user JID of user.
|
||||
void disconnectUser(const Swift::JID &user);
|
||||
|
||||
void messageToXMPPSent() { m_sentToXMPP++; }
|
||||
void messageToBackendSent() { m_sentToBackend++; }
|
||||
|
||||
unsigned long getMessagesToXMPP() { return m_sentToXMPP; }
|
||||
unsigned long getMessagesToBackend() { return m_sentToBackend; }
|
||||
|
||||
|
||||
private:
|
||||
void handlePresence(Swift::Presence::ref presence);
|
||||
void handleMessageReceived(Swift::Message::ref message);
|
||||
|
@ -134,6 +141,8 @@ class UserManager : public Swift::EntityCapsProvider {
|
|||
StorageResponder *m_storageResponder;
|
||||
UserRegistry *m_userRegistry;
|
||||
Swift::Timer::ref m_removeTimer;
|
||||
unsigned long m_sentToXMPP;
|
||||
unsigned long m_sentToBackend;
|
||||
friend class RosterResponder;
|
||||
};
|
||||
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
ADD_SUBDIRECTORY(src)
|
||||
ADD_SUBDIRECTORY(cpp)
|
||||
ADD_SUBDIRECTORY(python)
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#else
|
||||
#include <winsock2.h>
|
||||
#include <stdint.h>
|
||||
#include <process.h>
|
||||
#define getpid _getpid
|
||||
#endif
|
||||
|
||||
using namespace log4cxx;
|
||||
|
@ -41,6 +43,12 @@ namespace Transport {
|
|||
wrap.set_payload(MESSAGE); \
|
||||
wrap.SerializeToString(&MESSAGE);
|
||||
|
||||
template <class T> std::string stringOf(T object) {
|
||||
std::ostringstream os;
|
||||
os << object;
|
||||
return (os.str());
|
||||
}
|
||||
|
||||
NetworkPlugin::NetworkPlugin() {
|
||||
m_pingReceived = false;
|
||||
|
||||
|
@ -587,13 +595,19 @@ void NetworkPlugin::sendMemoryUsage() {
|
|||
pbnetwork::Stats stats;
|
||||
|
||||
stats.set_init_res(m_init_res);
|
||||
double res;
|
||||
double shared;
|
||||
double res = 0;
|
||||
double shared = 0;
|
||||
#ifndef WIN32
|
||||
process_mem_usage(shared, res);
|
||||
#endif
|
||||
stats.set_res(res);
|
||||
stats.set_shared(shared);
|
||||
|
||||
double e_res;
|
||||
double e_shared;
|
||||
handleMemoryUsage(e_res, e_shared);
|
||||
|
||||
stats.set_res(res + e_res);
|
||||
stats.set_shared(shared + e_shared);
|
||||
stats.set_id(stringOf(getpid()));
|
||||
|
||||
std::string message;
|
||||
stats.SerializeToString(&message);
|
13
plugin/python/CMakeLists.txt
Normal file
13
plugin/python/CMakeLists.txt
Normal file
|
@ -0,0 +1,13 @@
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
if (PROTOBUF_FOUND)
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/protocol_pb2.py
|
||||
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --python_out ${CMAKE_CURRENT_BINARY_DIR} --proto_path ${CMAKE_CURRENT_BINARY_DIR}/../../include/transport/ ${CMAKE_CURRENT_BINARY_DIR}/../../include/transport/protocol.proto
|
||||
COMMENT "Running Python protocol buffer compiler on protocol.proto"
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../../include/transport/protocol.proto
|
||||
)
|
||||
ADD_CUSTOM_TARGET(pb-python DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/protocol_pb2.py)
|
||||
endif()
|
||||
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
#include "transport/usersreconnecter.h"
|
||||
#include "transport/util.h"
|
||||
#include "transport/gatewayresponder.h"
|
||||
#include "transport/logging.h"
|
||||
#include "Swiften/EventLoop/SimpleEventLoop.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
@ -235,71 +236,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (CONFIG_STRING(&config, "logging.config").empty()) {
|
||||
LoggerPtr root = log4cxx::Logger::getRootLogger();
|
||||
#ifdef WIN32
|
||||
root->addAppender(new ConsoleAppender(new PatternLayout(L"%d %-5p %c: %m%n")));
|
||||
#else
|
||||
root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n")));
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
log4cxx::helpers::Properties p;
|
||||
log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(&config, "logging.config"));
|
||||
|
||||
p.load(istream);
|
||||
LogString pid, jid;
|
||||
log4cxx::helpers::Transcoder::decode(boost::lexical_cast<std::string>(getpid()), pid);
|
||||
log4cxx::helpers::Transcoder::decode(CONFIG_STRING(&config, "service.jid"), jid);
|
||||
#ifdef WIN32
|
||||
p.setProperty(L"pid", pid);
|
||||
p.setProperty(L"jid", jid);
|
||||
#else
|
||||
p.setProperty("pid", pid);
|
||||
p.setProperty("jid", jid);
|
||||
#endif
|
||||
|
||||
std::string dir;
|
||||
BOOST_FOREACH(const log4cxx::LogString &prop, p.propertyNames()) {
|
||||
if (boost::ends_with(prop, ".File")) {
|
||||
log4cxx::helpers::Transcoder::encode(p.get(prop), dir);
|
||||
boost::replace_all(dir, "${jid}", jid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dir.empty()) {
|
||||
// create directories
|
||||
try {
|
||||
boost::filesystem::create_directories(
|
||||
boost::filesystem::path(dir).parent_path().string()
|
||||
);
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Can't create logging directory directory " << boost::filesystem::path(dir).parent_path().string() << ".\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
if (!CONFIG_STRING(&config, "service.group").empty() && !CONFIG_STRING(&config, "service.user").empty()) {
|
||||
struct group *gr;
|
||||
if ((gr = getgrnam(CONFIG_STRING(&config, "service.group").c_str())) == NULL) {
|
||||
std::cerr << "Invalid service.group name " << CONFIG_STRING(&config, "service.group") << "\n";
|
||||
return 1;
|
||||
}
|
||||
struct passwd *pw;
|
||||
if ((pw = getpwnam(CONFIG_STRING(&config, "service.user").c_str())) == NULL) {
|
||||
std::cerr << "Invalid service.user name " << CONFIG_STRING(&config, "service.user") << "\n";
|
||||
return 1;
|
||||
}
|
||||
chown(dir.c_str(), pw->pw_uid, gr->gr_gid);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
log4cxx::PropertyConfigurator::configure(p);
|
||||
}
|
||||
Logging::initMainLogging(&config);
|
||||
|
||||
#ifndef WIN32
|
||||
if (!CONFIG_STRING(&config, "service.group").empty() ||!CONFIG_STRING(&config, "service.user").empty() ) {
|
||||
|
@ -349,57 +286,17 @@ int main(int argc, char **argv)
|
|||
component_ = &transport;
|
||||
// Logger logger(&transport);
|
||||
|
||||
StorageBackend *storageBackend = NULL;
|
||||
|
||||
#ifdef WITH_SQLITE
|
||||
if (CONFIG_STRING(&config, "database.type") == "sqlite3") {
|
||||
storageBackend = new SQLite3Backend(&config);
|
||||
if (!storageBackend->connect()) {
|
||||
std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
|
||||
return -1;
|
||||
std::string error;
|
||||
StorageBackend *storageBackend = StorageBackend::createBackend(&config, error);
|
||||
if (storageBackend == NULL) {
|
||||
if (!error.empty()) {
|
||||
std::cerr << error << "\n";
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (CONFIG_STRING(&config, "database.type") == "sqlite3") {
|
||||
std::cerr << "Spectrum2 is not compiled with sqlite3 backend.\n";
|
||||
return -2;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_MYSQL
|
||||
if (CONFIG_STRING(&config, "database.type") == "mysql") {
|
||||
storageBackend = new MySQLBackend(&config);
|
||||
if (!storageBackend->connect()) {
|
||||
std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (CONFIG_STRING(&config, "database.type") == "mysql") {
|
||||
std::cerr << "Spectrum2 is not compiled with mysql backend.\n";
|
||||
return -2;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_PQXX
|
||||
if (CONFIG_STRING(&config, "database.type") == "pqxx") {
|
||||
storageBackend = new PQXXBackend(&config);
|
||||
if (!storageBackend->connect()) {
|
||||
std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (CONFIG_STRING(&config, "database.type") == "pqxx") {
|
||||
std::cerr << "Spectrum2 is not compiled with pqxx backend.\n";
|
||||
return -2;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (CONFIG_STRING(&config, "database.type") != "mysql" && CONFIG_STRING(&config, "database.type") != "sqlite3"
|
||||
&& CONFIG_STRING(&config, "database.type") != "pqxx" && CONFIG_STRING(&config, "database.type") != "none") {
|
||||
std::cerr << "Unknown storage backend " << CONFIG_STRING(&config, "database.type") << "\n";
|
||||
return -2;
|
||||
else if (!storageBackend->connect()) {
|
||||
std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
UserManager userManager(&transport, &userRegistry, storageBackend);
|
||||
|
@ -440,4 +337,5 @@ int main(int argc, char **argv)
|
|||
|
||||
delete storageBackend;
|
||||
delete factories;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -7,27 +7,22 @@ server_mode = 1
|
|||
backend_host=localhost
|
||||
pidfile=./test.pid
|
||||
# < this option doesn't work yet
|
||||
backend_port=10001
|
||||
admin_username=admin
|
||||
#backend_port=10001
|
||||
admin_jid=admin@localhost
|
||||
admin_password=test
|
||||
#cert=server.pfx #patch to PKCS#12 certificate
|
||||
#cert_password=test #password to that certificate if any
|
||||
users_per_backend=10
|
||||
backend=/home/hanzz/code/libtransport/backends/libpurple/spectrum2_libpurple_backend
|
||||
#backend=/home/hanzz/code/libtransport/backends/smstools3/spectrum2_smstools3_backend
|
||||
#backend=/usr/bin/mono /home/hanzz/code/networkplugin-csharp/msnp-sharp-backend/bin/Debug/msnp-sharp-backend.exe
|
||||
#backend=/home/hanzz/code/libtransport/backends/frotz/spectrum2_frotz_backend
|
||||
#backend=/home/hanzz/code/libtransport/backends/libircclient-qt/spectrum2_libircclient-qt_backend
|
||||
backend=../..//backends/libpurple/spectrum2_libpurple_backend
|
||||
protocol=prpl-xmpp
|
||||
#protocol=prpl-msn
|
||||
protocol=any
|
||||
#protocol=any
|
||||
#protocol=prpl-icq
|
||||
irc_server=irc.freenode.org
|
||||
working_dir=./
|
||||
|
||||
[backend]
|
||||
#default_avatar=catmelonhead.jpg
|
||||
#no_vcard_fetch=true
|
||||
incoming_dir=/var/spool/sms/incoming
|
||||
|
||||
[logging]
|
||||
#config=logging.cfg # log4cxx/log4j logging configuration file
|
||||
|
|
|
@ -112,7 +112,7 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
|
|||
const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
|
||||
for (std::list <NetworkPluginServer::Backend *>::const_iterator b = backends.begin(); b != backends.end(); b++) {
|
||||
NetworkPluginServer::Backend *backend = *b;
|
||||
lst += "Backend " + boost::lexical_cast<std::string>(id);
|
||||
lst += "Backend " + boost::lexical_cast<std::string>(id) + " (ID=" + backend->id + ")";
|
||||
lst += backend->acceptUsers ? "" : " - not-accepting";
|
||||
lst += backend->longRun ? " - long-running" : "";
|
||||
lst += ":\n";
|
||||
|
@ -204,7 +204,7 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
|
|||
int id = 1;
|
||||
const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
|
||||
BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
|
||||
lst += "Backend " + boost::lexical_cast<std::string>(id) + ": " + boost::lexical_cast<std::string>(backend->res) + "\n";
|
||||
lst += "Backend " + boost::lexical_cast<std::string>(id) + " (ID=" + backend->id + "): " + boost::lexical_cast<std::string>(backend->res) + "\n";
|
||||
id++;
|
||||
}
|
||||
|
||||
|
@ -215,7 +215,7 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
|
|||
int id = 1;
|
||||
const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
|
||||
BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
|
||||
lst += "Backend " + boost::lexical_cast<std::string>(id) + ": " + boost::lexical_cast<std::string>(backend->shared) + "\n";
|
||||
lst += "Backend " + boost::lexical_cast<std::string>(id) + " (ID=" + backend->id + "): " + boost::lexical_cast<std::string>(backend->shared) + "\n";
|
||||
id++;
|
||||
}
|
||||
|
||||
|
@ -226,7 +226,7 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
|
|||
int id = 1;
|
||||
const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
|
||||
BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
|
||||
lst += "Backend " + boost::lexical_cast<std::string>(id) + ": " + boost::lexical_cast<std::string>(backend->res - backend->shared) + "\n";
|
||||
lst += "Backend " + boost::lexical_cast<std::string>(id) + " (ID=" + backend->id + "): " + boost::lexical_cast<std::string>(backend->res - backend->shared) + "\n";
|
||||
id++;
|
||||
}
|
||||
|
||||
|
@ -238,10 +238,10 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
|
|||
const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
|
||||
BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
|
||||
if (backend->users.size() == 0) {
|
||||
lst += "Backend " + boost::lexical_cast<std::string>(id) + ": 0\n";
|
||||
lst += "Backend " + boost::lexical_cast<std::string>(id) + " (ID=" + backend->id + "): 0\n";
|
||||
}
|
||||
else {
|
||||
lst += "Backend " + boost::lexical_cast<std::string>(id) + ": " + boost::lexical_cast<std::string>((backend->res - backend->init_res) / backend->users.size()) + "\n";
|
||||
lst += "Backend " + boost::lexical_cast<std::string>(id) + " (ID=" + backend->id + "): " + boost::lexical_cast<std::string>((backend->res - backend->init_res) / backend->users.size()) + "\n";
|
||||
}
|
||||
id++;
|
||||
}
|
||||
|
@ -251,6 +251,14 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
|
|||
else if (message->getBody() == "collect_backend") {
|
||||
m_server->collectBackend();
|
||||
}
|
||||
else if (message->getBody() == "crashed_backends") {
|
||||
std::string lst;
|
||||
const std::vector<std::string> &backends = m_server->getCrashedBackends();
|
||||
BOOST_FOREACH(const std::string &backend, backends) {
|
||||
lst += backend + "\n";
|
||||
}
|
||||
message->setBody(lst);
|
||||
}
|
||||
else if (message->getBody().find("help") == 0) {
|
||||
std::string help;
|
||||
help += "General:\n";
|
||||
|
@ -263,6 +271,7 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
|
|||
help += " has_online_user <bare_JID> - returns 1 if user is online\n";
|
||||
help += "Backends:\n";
|
||||
help += " backends_count - number of active backends\n";
|
||||
help += " crashed_backends - returns IDs of crashed backends\n";
|
||||
help += "Memory:\n";
|
||||
help += " res_memory - Total RESident memory spectrum2 and its backends use in KB\n";
|
||||
help += " shr_memory - Total SHaRed memory spectrum2 backends share together in KB\n";
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
|
||||
namespace Transport {
|
||||
|
||||
Buddy::Buddy(RosterManager *rosterManager, long id) : m_id(id), m_flags(BUDDY_NO_FLAG), m_rosterManager(rosterManager){
|
||||
Buddy::Buddy(RosterManager *rosterManager, long id) : m_id(id), m_flags(BUDDY_NO_FLAG), m_rosterManager(rosterManager),
|
||||
m_subscription(Ask) {
|
||||
// m_rosterManager->setBuddy(this);
|
||||
}
|
||||
|
||||
|
@ -64,12 +65,12 @@ const Swift::JID &Buddy::getJID() {
|
|||
return m_jid;
|
||||
}
|
||||
|
||||
void Buddy::setSubscription(const std::string &subscription) {
|
||||
// m_subscription = subscription;
|
||||
void Buddy::setSubscription(Subscription subscription) {
|
||||
m_subscription = subscription;
|
||||
}
|
||||
|
||||
const std::string Buddy::getSubscription() {
|
||||
return "ask";
|
||||
Buddy::Subscription Buddy::getSubscription() {
|
||||
return m_subscription;
|
||||
}
|
||||
|
||||
Swift::Presence::ref Buddy::generatePresenceStanza(int features, bool only_new) {
|
||||
|
|
134
src/logging.cpp
Normal file
134
src/logging.cpp
Normal file
|
@ -0,0 +1,134 @@
|
|||
/**
|
||||
* 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/logging.h"
|
||||
#include "transport/config.h"
|
||||
#include <boost/foreach.hpp>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
|
||||
#include "log4cxx/logger.h"
|
||||
#include "log4cxx/consoleappender.h"
|
||||
#include "log4cxx/patternlayout.h"
|
||||
#include "log4cxx/propertyconfigurator.h"
|
||||
#include "log4cxx/helpers/properties.h"
|
||||
#include "log4cxx/helpers/fileinputstream.h"
|
||||
#include "log4cxx/helpers/transcoder.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#ifndef WIN32
|
||||
#include "sys/signal.h"
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <sys/resource.h>
|
||||
#include "libgen.h"
|
||||
#else
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#define getpid _getpid
|
||||
#endif
|
||||
|
||||
using namespace boost::filesystem;
|
||||
using namespace log4cxx;
|
||||
|
||||
namespace Transport {
|
||||
|
||||
namespace Logging {
|
||||
|
||||
static LoggerPtr root;
|
||||
|
||||
static void initLogging(Config *config, std::string key) {
|
||||
if (CONFIG_STRING(config, key).empty()) {
|
||||
root = log4cxx::Logger::getRootLogger();
|
||||
#ifdef WIN32
|
||||
root->addAppender(new ConsoleAppender(new PatternLayout(L"%d %-5p %c: %m%n")));
|
||||
#else
|
||||
root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n")));
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
log4cxx::helpers::Properties p;
|
||||
log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(config, key));
|
||||
|
||||
p.load(istream);
|
||||
LogString pid, jid;
|
||||
log4cxx::helpers::Transcoder::decode(boost::lexical_cast<std::string>(getpid()), pid);
|
||||
log4cxx::helpers::Transcoder::decode(CONFIG_STRING(config, "service.jid"), jid);
|
||||
#ifdef WIN32
|
||||
p.setProperty(L"pid", pid);
|
||||
p.setProperty(L"jid", jid);
|
||||
#else
|
||||
p.setProperty("pid", pid);
|
||||
p.setProperty("jid", jid);
|
||||
#endif
|
||||
|
||||
std::string dir;
|
||||
BOOST_FOREACH(const log4cxx::LogString &prop, p.propertyNames()) {
|
||||
if (boost::ends_with(prop, ".File")) {
|
||||
log4cxx::helpers::Transcoder::encode(p.get(prop), dir);
|
||||
boost::replace_all(dir, "${jid}", jid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dir.empty()) {
|
||||
// create directories
|
||||
try {
|
||||
boost::filesystem::create_directories(
|
||||
boost::filesystem::path(dir).parent_path().string()
|
||||
);
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Can't create logging directory directory " << boost::filesystem::path(dir).parent_path().string() << ".\n";
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
if (!CONFIG_STRING(config, "service.group").empty() && !CONFIG_STRING(config, "service.user").empty()) {
|
||||
struct group *gr;
|
||||
if ((gr = getgrnam(CONFIG_STRING(config, "service.group").c_str())) == NULL) {
|
||||
std::cerr << "Invalid service.group name " << CONFIG_STRING(config, "service.group") << "\n";
|
||||
}
|
||||
struct passwd *pw;
|
||||
if ((pw = getpwnam(CONFIG_STRING(config, "service.user").c_str())) == NULL) {
|
||||
std::cerr << "Invalid service.user name " << CONFIG_STRING(config, "service.user") << "\n";
|
||||
}
|
||||
chown(dir.c_str(), pw->pw_uid, gr->gr_gid);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
log4cxx::PropertyConfigurator::configure(p);
|
||||
}
|
||||
}
|
||||
|
||||
void initBackendLogging(Config *config) {
|
||||
initLogging(config, "logging.backend_config");
|
||||
}
|
||||
|
||||
void initMainLogging(Config *config) {
|
||||
initLogging(config, "logging.config");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -25,6 +25,7 @@
|
|||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#ifndef WIN32
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
@ -41,13 +42,18 @@ namespace Transport {
|
|||
|
||||
#ifndef WIN32
|
||||
#ifdef BSD
|
||||
void process_mem_usage(double& vm_usage, double& resident_set) {
|
||||
void process_mem_usage(double& vm_usage, double& resident_set, pid_t pid) {
|
||||
int mib[4];
|
||||
size_t size;
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROC;
|
||||
mib[2] = KERN_PROC_PID;
|
||||
mib[3] = getpid();
|
||||
if (pid == 0) {
|
||||
mib[3] = getpid();
|
||||
}
|
||||
else {
|
||||
mib[3] = pid;
|
||||
}
|
||||
struct kinfo_proc proc;
|
||||
|
||||
size = sizeof(struct kinfo_proc);
|
||||
|
@ -75,7 +81,7 @@ void process_mem_usage(double& vm_usage, double& resident_set) {
|
|||
vm_usage = (double) proc.ki_size;
|
||||
}
|
||||
#else /* BSD */
|
||||
void process_mem_usage(double& shared, double& resident_set) {
|
||||
void process_mem_usage(double& shared, double& resident_set, pid_t pid) {
|
||||
using std::ios_base;
|
||||
using std::ifstream;
|
||||
using std::string;
|
||||
|
@ -84,8 +90,11 @@ void process_mem_usage(double& shared, double& resident_set) {
|
|||
resident_set = 0.0;
|
||||
|
||||
// 'file' stat seems to give the most reliable results
|
||||
//
|
||||
ifstream stat_stream("/proc/self/statm",ios_base::in);
|
||||
std::string f = "/proc/self/statm";
|
||||
if (pid != 0) {
|
||||
f = "/proc/" + boost::lexical_cast<std::string>(pid) + "/statm";
|
||||
}
|
||||
ifstream stat_stream(f.c_str(), ios_base::in);
|
||||
if (!stat_stream.is_open()) {
|
||||
shared = 0;
|
||||
resident_set = 0;
|
||||
|
@ -94,7 +103,7 @@ void process_mem_usage(double& shared, double& resident_set) {
|
|||
|
||||
// dummy vars for leading entries in stat that we don't care about
|
||||
//
|
||||
string pid, comm, state, ppid, pgrp, session, tty_nr;
|
||||
string pid1, comm, state, ppid, pgrp, session, tty_nr;
|
||||
string tpgid, flags, minflt, cminflt, majflt, cmajflt;
|
||||
string utime, stime, cutime, cstime, priority, nice;
|
||||
string O, itrealvalue, starttime;
|
||||
|
|
|
@ -95,7 +95,12 @@ class NetworkFactory : public Factory {
|
|||
LocalBuddy *buddy = new LocalBuddy(rosterManager, buddyInfo.id);
|
||||
buddy->setAlias(buddyInfo.alias);
|
||||
buddy->setName(buddyInfo.legacyName);
|
||||
buddy->setSubscription(buddyInfo.subscription);
|
||||
if (buddyInfo.subscription == "both") {
|
||||
buddy->setSubscription(Buddy::Both);
|
||||
}
|
||||
else {
|
||||
buddy->setSubscription(Buddy::Ask);
|
||||
}
|
||||
buddy->setGroups(buddyInfo.groups);
|
||||
buddy->setFlags((BuddyFlag) (buddyInfo.flags));
|
||||
if (buddyInfo.settings.find("icon_hash") != buddyInfo.settings.end())
|
||||
|
@ -339,15 +344,19 @@ void NetworkPluginServer::handleNewClientConnection(boost::shared_ptr<Swift::Con
|
|||
}
|
||||
|
||||
void NetworkPluginServer::handleSessionFinished(Backend *c) {
|
||||
LOG4CXX_INFO(logger, "Backend " << c << " disconnected. Current backend count=" << (m_clients.size() - 1));
|
||||
LOG4CXX_INFO(logger, "Backend " << c << " (ID=" << c->id << ") disconnected. Current backend count=" << (m_clients.size() - 1));
|
||||
|
||||
// This backend will do, so we can't reconnect users to it in User::handleDisconnected call
|
||||
c->willDie = true;
|
||||
|
||||
// If there are users associated with this backend, it must have crashed, so print error output
|
||||
// and disconnect users
|
||||
if (!c->users.empty()) {
|
||||
m_crashedBackends.push_back(c->id);
|
||||
}
|
||||
|
||||
for (std::list<User *>::const_iterator it = c->users.begin(); it != c->users.end(); it++) {
|
||||
LOG4CXX_ERROR(logger, "Backend " << c << " disconnected (probably crashed) with active user " << (*it)->getJID().toString());
|
||||
LOG4CXX_ERROR(logger, "Backend " << c << " (ID=" << c->id << ") disconnected (probably crashed) with active user " << (*it)->getJID().toString());
|
||||
(*it)->setData(NULL);
|
||||
(*it)->handleDisconnected("Internal Server Error, please reconnect.");
|
||||
}
|
||||
|
@ -570,6 +579,7 @@ void NetworkPluginServer::handleConvMessagePayload(const std::string &data, bool
|
|||
|
||||
// Forward it
|
||||
conv->handleMessage(msg, payload.nickname());
|
||||
m_userManager->messageToXMPPSent();
|
||||
}
|
||||
|
||||
void NetworkPluginServer::handleAttentionPayload(const std::string &data) {
|
||||
|
@ -607,6 +617,7 @@ void NetworkPluginServer::handleStatsPayload(Backend *c, const std::string &data
|
|||
c->res = payload.res();
|
||||
c->init_res = payload.init_res();
|
||||
c->shared = payload.shared();
|
||||
c->id = payload.id();
|
||||
}
|
||||
|
||||
void NetworkPluginServer::handleFTStartPayload(const std::string &data) {
|
||||
|
@ -853,12 +864,12 @@ void NetworkPluginServer::pingTimeout() {
|
|||
sendPing((*it));
|
||||
}
|
||||
else {
|
||||
LOG4CXX_INFO(logger, "Disconnecting backend " << (*it) << ". PING response not received.");
|
||||
LOG4CXX_INFO(logger, "Disconnecting backend " << (*it) << " (ID=" << (*it)->id << "). PING response not received.");
|
||||
toRemove.push_back(*it);
|
||||
}
|
||||
|
||||
if ((*it)->users.size() == 0) {
|
||||
LOG4CXX_INFO(logger, "Disconnecting backend " << (*it) << ". There are no users.");
|
||||
LOG4CXX_INFO(logger, "Disconnecting backend " << (*it) << " (ID=" << (*it)->id << "). There are no users.");
|
||||
toRemove.push_back(*it);
|
||||
}
|
||||
}
|
||||
|
@ -887,7 +898,7 @@ void NetworkPluginServer::collectBackend() {
|
|||
if (m_collectTimer) {
|
||||
m_collectTimer->start();
|
||||
}
|
||||
LOG4CXX_INFO(logger, "Backend " << backend << "is set to die");
|
||||
LOG4CXX_INFO(logger, "Backend " << backend << " (ID=" << backend->id << ") is set to die");
|
||||
backend->acceptUsers = false;
|
||||
}
|
||||
}
|
||||
|
@ -1355,7 +1366,7 @@ void NetworkPluginServer::sendPing(Backend *c) {
|
|||
wrap.SerializeToString(&message);
|
||||
|
||||
if (c->connection) {
|
||||
LOG4CXX_INFO(logger, "PING to " << c);
|
||||
LOG4CXX_INFO(logger, "PING to " << c << " (ID=" << c->id << ")");
|
||||
send(c->connection, message);
|
||||
c->pongReceived = false;
|
||||
}
|
||||
|
|
|
@ -137,6 +137,11 @@ void RosterManager::sendBuddyRosterPush(Buddy *buddy) {
|
|||
request->send();
|
||||
m_requests.push_back(request);
|
||||
}
|
||||
|
||||
if (buddy->getSubscription() != Buddy::Both) {
|
||||
buddy->setSubscription(Buddy::Both);
|
||||
handleBuddyChanged(buddy);
|
||||
}
|
||||
}
|
||||
|
||||
void RosterManager::sendBuddySubscribePresence(Buddy *buddy) {
|
||||
|
@ -165,6 +170,11 @@ void RosterManager::setBuddyCallback(Buddy *buddy) {
|
|||
sendBuddyRosterPush(buddy);
|
||||
}
|
||||
else {
|
||||
if (buddy->getSubscription() == Buddy::Both) {
|
||||
LOG4CXX_INFO(logger, m_user->getJID().toString() << ": Not forwarding this buddy, because subscription=both");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_supportRemoteRoster) {
|
||||
sendBuddyRosterPush(buddy);
|
||||
}
|
||||
|
@ -331,8 +341,8 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) {
|
|||
response->setType(Swift::Presence::Subscribed);
|
||||
break;
|
||||
case Swift::Presence::Subscribed:
|
||||
onBuddyAdded(buddy);
|
||||
break;
|
||||
// onBuddyAdded(buddy);
|
||||
return;
|
||||
// buddy is already there, so nothing to do, just answer
|
||||
case Swift::Presence::Unsubscribe:
|
||||
response->setType(Swift::Presence::Unsubscribed);
|
||||
|
@ -361,6 +371,10 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) {
|
|||
currentPresence->setTo(presence->getFrom());
|
||||
m_component->getStanzaChannel()->sendPresence(currentPresence);
|
||||
}
|
||||
if (buddy->getSubscription() != Buddy::Both) {
|
||||
buddy->setSubscription(Buddy::Both);
|
||||
handleBuddyChanged(buddy);
|
||||
}
|
||||
break;
|
||||
// remove buddy
|
||||
case Swift::Presence::Unsubscribe:
|
||||
|
@ -370,7 +384,20 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) {
|
|||
// just send response
|
||||
case Swift::Presence::Unsubscribed:
|
||||
response->setType(Swift::Presence::Unsubscribe);
|
||||
// We set both here, because this Unsubscribed can be response to
|
||||
// subscribe presence and we don't want that unsubscribe presence
|
||||
// to be send later again
|
||||
if (buddy->getSubscription() != Buddy::Both) {
|
||||
buddy->setSubscription(Buddy::Both);
|
||||
handleBuddyChanged(buddy);
|
||||
}
|
||||
break;
|
||||
case Swift::Presence::Subscribed:
|
||||
if (buddy->getSubscription() != Buddy::Both) {
|
||||
buddy->setSubscription(Buddy::Both);
|
||||
handleBuddyChanged(buddy);
|
||||
}
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
@ -394,7 +421,7 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) {
|
|||
// buddy is already there, so nothing to do, just answer
|
||||
case Swift::Presence::Unsubscribe:
|
||||
response->setType(Swift::Presence::Unsubscribed);
|
||||
onBuddyRemoved(buddy);
|
||||
// onBuddyRemoved(buddy);
|
||||
break;
|
||||
// just send response
|
||||
case Swift::Presence::Unsubscribed:
|
||||
|
|
|
@ -103,7 +103,7 @@ bool RosterStorage::storeBuddies() {
|
|||
buddyInfo.alias = buddy->getAlias();
|
||||
buddyInfo.legacyName = buddy->getName();
|
||||
buddyInfo.groups = buddy->getGroups();
|
||||
buddyInfo.subscription = buddy->getSubscription();
|
||||
buddyInfo.subscription = buddy->getSubscription() == Buddy::Ask ? "ask" : "both";
|
||||
buddyInfo.id = buddy->getID();
|
||||
buddyInfo.flags = buddy->getFlags();
|
||||
buddyInfo.settings["icon_hash"].s = buddy->getIconHash();
|
||||
|
|
|
@ -81,7 +81,10 @@ bool StatsResponder::handleGetRequest(const Swift::JID& from, const Swift::JID&
|
|||
response->addItem(StatsPayload::Item("users/online"));
|
||||
response->addItem(StatsPayload::Item("contacts/online"));
|
||||
response->addItem(StatsPayload::Item("contacts/total"));
|
||||
response->addItem(StatsPayload::Item("backends"));
|
||||
response->addItem(StatsPayload::Item("messages/from-xmpp"));
|
||||
response->addItem(StatsPayload::Item("messages/to-xmpp"));
|
||||
response->addItem(StatsPayload::Item("backends/running"));
|
||||
response->addItem(StatsPayload::Item("backends/crashed"));
|
||||
response->addItem(StatsPayload::Item("memory-usage"));
|
||||
}
|
||||
else {
|
||||
|
@ -115,8 +118,11 @@ bool StatsResponder::handleGetRequest(const Swift::JID& from, const Swift::JID&
|
|||
else if (item.getName() == "users/online") {
|
||||
response->addItem(StatsPayload::Item("users/online", "users", boost::lexical_cast<std::string>(m_userManager->getUserCount())));
|
||||
}
|
||||
else if (item.getName() == "backends") {
|
||||
response->addItem(StatsPayload::Item("backends", "backends", boost::lexical_cast<std::string>(m_server->getBackendCount())));
|
||||
else if (item.getName() == "backends/running") {
|
||||
response->addItem(StatsPayload::Item("backends/running", "backends", boost::lexical_cast<std::string>(m_server->getBackendCount())));
|
||||
}
|
||||
else if (item.getName() == "backends/crashed") {
|
||||
response->addItem(StatsPayload::Item("backends/crashed", "backends", boost::lexical_cast<std::string>(m_server->getCrashedBackends().size())));
|
||||
}
|
||||
else if (item.getName() == "memory-usage") {
|
||||
response->addItem(StatsPayload::Item("memory-usage", "KB", boost::lexical_cast<std::string>(usedMemory())));
|
||||
|
@ -127,6 +133,12 @@ bool StatsResponder::handleGetRequest(const Swift::JID& from, const Swift::JID&
|
|||
else if (item.getName() == "contacts/total") {
|
||||
response->addItem(StatsPayload::Item("contacts/total", "contacts", boost::lexical_cast<std::string>(contactsTotal)));
|
||||
}
|
||||
else if (item.getName() == "messages/from-xmpp") {
|
||||
response->addItem(StatsPayload::Item("messages/from-xmpp", "messages", boost::lexical_cast<std::string>(m_userManager->getMessagesToBackend())));
|
||||
}
|
||||
else if (item.getName() == "messages/to-xmpp") {
|
||||
response->addItem(StatsPayload::Item("messages/to-xmpp", "messages", boost::lexical_cast<std::string>(m_userManager->getMessagesToXMPP())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
49
src/storagebackend.cpp
Normal file
49
src/storagebackend.cpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
#include "transport/storagebackend.h"
|
||||
#include "transport/config.h"
|
||||
|
||||
#include "transport/sqlite3backend.h"
|
||||
#include "transport/mysqlbackend.h"
|
||||
#include "transport/pqxxbackend.h"
|
||||
|
||||
namespace Transport {
|
||||
|
||||
StorageBackend *StorageBackend::createBackend(Config *config, std::string &error) {
|
||||
StorageBackend *storageBackend = NULL;
|
||||
#ifdef WITH_SQLITE
|
||||
if (CONFIG_STRING(config, "database.type") == "sqlite3") {
|
||||
storageBackend = new SQLite3Backend(config);
|
||||
}
|
||||
#else
|
||||
if (CONFIG_STRING(config, "database.type") == "sqlite3") {
|
||||
error = "Libtransport is not compiled with sqlite3 backend support.";
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_MYSQL
|
||||
if (CONFIG_STRING(config, "database.type") == "mysql") {
|
||||
storageBackend = new MySQLBackend(config);
|
||||
}
|
||||
#else
|
||||
if (CONFIG_STRING(config, "database.type") == "mysql") {
|
||||
error = "Spectrum2 is not compiled with mysql backend support.";
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_PQXX
|
||||
if (CONFIG_STRING(config, "database.type") == "pqxx") {
|
||||
storageBackend = new PQXXBackend(config);
|
||||
}
|
||||
#else
|
||||
if (CONFIG_STRING(config, "database.type") == "pqxx") {
|
||||
error = "Spectrum2 is not compiled with pqxx backend support.";
|
||||
}
|
||||
#endif
|
||||
|
||||
if (CONFIG_STRING(config, "database.type") != "mysql" && CONFIG_STRING(config, "database.type") != "sqlite3"
|
||||
&& CONFIG_STRING(config, "database.type") != "pqxx" && CONFIG_STRING(config, "database.type") != "none") {
|
||||
error = "Unknown storage backend " + CONFIG_STRING(config, "database.type");
|
||||
}
|
||||
return storageBackend;
|
||||
}
|
||||
|
||||
}
|
|
@ -72,7 +72,7 @@ class TestingFactory : public Factory {
|
|||
LocalBuddy *buddy = new LocalBuddy(rosterManager, buddyInfo.id);
|
||||
buddy->setAlias(buddyInfo.alias);
|
||||
buddy->setName(buddyInfo.legacyName);
|
||||
buddy->setSubscription(buddyInfo.subscription);
|
||||
buddy->setSubscription(Buddy::Ask);
|
||||
buddy->setGroups(buddyInfo.groups);
|
||||
buddy->setFlags((BuddyFlag) buddyInfo.flags);
|
||||
if (buddyInfo.settings.find("icon_hash") != buddyInfo.settings.end())
|
||||
|
|
|
@ -210,6 +210,7 @@ void User::handlePresence(Swift::Presence::ref presence) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isMUC = presence->getPayload<Swift::MUCPayload>() != NULL || *presence->getTo().getNode().c_str() == '#';
|
||||
if (isMUC) {
|
||||
if (presence->getType() == Swift::Presence::Unavailable) {
|
||||
|
@ -328,7 +329,7 @@ void User::handleDisconnected(const std::string &error, Swift::SpectrumErrorPayl
|
|||
if (e == Swift::SpectrumErrorPayload::CONNECTION_ERROR_OTHER_ERROR || e == Swift::SpectrumErrorPayload::CONNECTION_ERROR_NETWORK_ERROR) {
|
||||
if (m_reconnectCounter < 3) {
|
||||
m_reconnectCounter++;
|
||||
LOG4CXX_INFO(logger, m_jid.toString() << ": Disconnecting from legacy network for, trying to reconnect automatically.");
|
||||
LOG4CXX_INFO(logger, m_jid.toString() << ": Disconnecting from legacy network " << error << ", trying to reconnect automatically.");
|
||||
// Simulate destruction/resurrection :)
|
||||
// TODO: If this stops working, create onReconnect signal
|
||||
m_userManager->onUserDestroyed(this);
|
||||
|
|
|
@ -42,6 +42,8 @@ static LoggerPtr logger = Logger::getLogger("UserManager");
|
|||
UserManager::UserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend) {
|
||||
m_cachedUser = NULL;
|
||||
m_onlineBuddies = 0;
|
||||
m_sentToXMPP = 0;
|
||||
m_sentToBackend = 0;
|
||||
m_component = component;
|
||||
m_storageBackend = storageBackend;
|
||||
m_storageResponder = NULL;
|
||||
|
@ -150,6 +152,21 @@ void UserManager::handlePresence(Swift::Presence::ref presence) {
|
|||
if (!user) {
|
||||
// Admin user is not legacy network user, so do not create User class instance for him
|
||||
if (m_component->inServerMode() && CONFIG_STRING(m_component->getConfig(), "service.admin_jid") == presence->getFrom().toBare().toString()) {
|
||||
// Send admin contact to the user.
|
||||
Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload());
|
||||
Swift::RosterItemPayload item;
|
||||
item.setJID(m_component->getJID());
|
||||
item.setName("Admin");
|
||||
item.setSubscription(Swift::RosterItemPayload::Both);
|
||||
payload->addItem(item);
|
||||
|
||||
Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, presence->getFrom(), m_component->getIQRouter());
|
||||
request->send();
|
||||
|
||||
Swift::Presence::ref response = Swift::Presence::create();
|
||||
response->setTo(presence->getFrom());
|
||||
response->setFrom(m_component->getJID());
|
||||
m_component->getStanzaChannel()->sendPresence(response);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -266,6 +283,7 @@ void UserManager::handleMessageReceived(Swift::Message::ref message) {
|
|||
}
|
||||
|
||||
user->getConversationManager()->handleMessageReceived(message);
|
||||
messageToBackendSent();
|
||||
}
|
||||
|
||||
void UserManager::handleGeneralPresenceReceived(Swift::Presence::ref presence) {
|
||||
|
|
|
@ -453,7 +453,7 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID
|
|||
// #endif
|
||||
if (!registered) {
|
||||
res.jid = barejid;
|
||||
res.uin = username;
|
||||
res.uin = newUsername;
|
||||
res.password = *payload->getPassword();
|
||||
res.language = language;
|
||||
res.encoding = encoding;
|
||||
|
@ -462,7 +462,7 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID
|
|||
}
|
||||
else {
|
||||
res.jid = barejid;
|
||||
res.uin = username;
|
||||
res.uin = newUsername;
|
||||
res.password = *payload->getPassword();
|
||||
res.language = language;
|
||||
res.encoding = encoding;
|
||||
|
|
Loading…
Add table
Reference in a new issue