Merge branch 'master' of github.com:vitalyster/libtransport

This commit is contained in:
Vitaly Takmazov 2012-04-08 20:26:44 +04:00
commit aafea80a3c
22 changed files with 242 additions and 89 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*.pb.cc
*.pb.h

View file

@ -1,6 +1,10 @@
cmake_minimum_required(VERSION 2.6)
project(libtransport)
if(NOT LIB_INSTALL_DIR)
set(LIB_INSTALL_DIR "lib")
endif()
set(CMAKE_MODULE_PATH "cmake_modules")
set(cppunit_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")

View file

@ -1,4 +1,4 @@
Version 2.0.0-beta2 (2012-XX-XX):
Version 2.0.0-beta2 (2012-03-28):
General:
* Fixed bug when Roster Item Exchange and subscribe stanzas were sent
repeatedly.
@ -6,13 +6,19 @@ Version 2.0.0-beta2 (2012-XX-XX):
* Fixed username_mask setting.
* Added new fields into statistics (backends_crashed, messages related
stats).
* Chatstates are now not counted as incoming messages in stats.
* Log4cxx is now optional dependency. Without Log4cxx, Spectrum 2 logs
to standard output.
* Fixed crash when Log4cxx configuration file didn't exist.
* Admin can now see "Admin" contact in server-mode.
libpurple:
* Added support for MUC for prpl-jabber protocol.
* Added initial support for MUC for prpl-jabber protocol.
LibCommuni IRC backend:
* Fixed sending/receiving UTF8 messages.
* Using the [registration] auto_register=1 config option, users don't
have to register manually when connecting IRC network.
Skype:
* Memory usage statistic now includes the Skype client.
@ -21,6 +27,7 @@ Version 2.0.0-beta2 (2012-XX-XX):
* 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.
* Fixed bug when Skype client instance wasn't killed by backend.
Version 2.0.0-beta (2012-02-28):
General:

View file

@ -2,10 +2,13 @@
#include <IrcCommand>
#include <IrcMessage>
#define FROM_UTF8(WHAT) QString::fromUtf8((WHAT).c_str(), (WHAT).size())
#define TO_UTF8(WHAT) std::string((WHAT).toUtf8().data(), (WHAT).toUtf8().size())
IRCNetworkPlugin::IRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port) {
this->config = config;
m_socket = new QTcpSocket();
m_socket->connectToHost(QString::fromStdString(host), port);
m_socket->connectToHost(FROM_UTF8(host), port);
connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData()));
}
@ -28,8 +31,8 @@ void IRCNetworkPlugin::handleLoginRequest(const std::string &user, const std::st
if (CONFIG_BOOL(config, "service.server_mode")) {
MyIrcSession *session = new MyIrcSession(user, this);
std::string h = user.substr(0, user.find("@"));
session->setNickName(QString::fromStdString(h.substr(0, h.find("%"))));
session->setHost(QString::fromStdString(h.substr(h.find("%") + 1)));
session->setNickName(FROM_UTF8(h.substr(0, h.find("%"))));
session->setHost(FROM_UTF8(h.substr(h.find("%") + 1)));
session->setPort(6667);
session->open();
std::cout << "CONNECTING IRC NETWORK " << h.substr(h.find("%") + 1) << "\n";
@ -72,7 +75,7 @@ void IRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const s
}
}
std::cout << "MESSAGE " << u << " " << r << "\n";
m_sessions[u]->sendCommand(IrcCommand::createMessage(QString::fromStdString(r), QString::fromStdString(message)));
m_sessions[u]->sendCommand(IrcCommand::createMessage(FROM_UTF8(r), FROM_UTF8(message)));
std::cout << "SENT\n";
}
@ -89,8 +92,8 @@ void IRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std:
if (room.find("@") != std::string::npos) {
// suffix is %irc.freenode.net to let MyIrcSession return #room%irc.freenode.net
MyIrcSession *session = new MyIrcSession(user, this, room.substr(room.find("@")));
session->setNickName(QString::fromStdString(nickname));
session->setHost(QString::fromStdString(room.substr(room.find("@") + 1)));
session->setNickName(FROM_UTF8(nickname));
session->setHost(FROM_UTF8(room.substr(room.find("@") + 1)));
session->setPort(6667);
session->open();
std::cout << "CONNECTING IRC NETWORK " << room.substr(room.find("@") + 1) << "\n";
@ -103,10 +106,10 @@ void IRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std:
}
std::cout << "JOINING " << r << "\n";
m_sessions[u]->addAutoJoinChannel(r);
m_sessions[u]->sendCommand(IrcCommand::createJoin(QString::fromStdString(r), QString::fromStdString(password)));
m_sessions[u]->sendCommand(IrcCommand::createJoin(FROM_UTF8(r), FROM_UTF8(password)));
m_sessions[u]->rooms += 1;
// update nickname, because we have nickname per session, no nickname per room.
handleRoomNicknameChanged(user, r, m_sessions[u]->nickName().toStdString());
handleRoomNicknameChanged(user, r, TO_UTF8(m_sessions[u]->nickName()));
}
void IRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std::string &room) {
@ -120,7 +123,7 @@ void IRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std
if (m_sessions[u] == NULL)
return;
m_sessions[u]->sendCommand(IrcCommand::createPart(QString::fromStdString(r)));
m_sessions[u]->sendCommand(IrcCommand::createPart(FROM_UTF8(r)));
m_sessions[u]->removeAutoJoinChannel(r);
m_sessions[u]->rooms -= 1;

View file

@ -15,6 +15,9 @@
#include <IrcCommand>
#include <IrcMessage>
#define FROM_UTF8(WHAT) QString::fromUtf8((WHAT).c_str(), (WHAT).size())
#define TO_UTF8(WHAT) std::string((WHAT).toUtf8().data(), (WHAT).toUtf8().size())
#include "transport/logging.h"
DEFINE_LOGGER(logger, "IRCSession");
@ -38,13 +41,13 @@ void MyIrcSession::on_connected() {
}
for(std::list<std::string>::const_iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) {
sendCommand(IrcCommand::createJoin(QString::fromStdString(*it)));
sendCommand(IrcCommand::createJoin(FROM_UTF8(*it)));
}
if (getIdentify().find(" ") != std::string::npos) {
std::string to = getIdentify().substr(0, getIdentify().find(" "));
std::string what = getIdentify().substr(getIdentify().find(" ") + 1);
sendCommand(IrcCommand::createMessage(QString::fromStdString(to), QString::fromStdString(what)));
sendCommand(IrcCommand::createMessage(FROM_UTF8(to), FROM_UTF8(what)));
}
}
@ -67,30 +70,30 @@ bool MyIrcSession::correctNickname(std::string &nickname) {
void MyIrcSession::on_joined(IrcMessage *message) {
IrcJoinMessage *m = (IrcJoinMessage *) message;
bool flags = 0;
std::string nickname = m->sender().name().toStdString();
std::string nickname = TO_UTF8(m->sender().name());
flags = correctNickname(nickname);
np->handleParticipantChanged(user, nickname, m->channel().toStdString() + suffix, (int) flags, pbnetwork::STATUS_ONLINE);
LOG4CXX_INFO(logger, user << ": Joined " << m->parameters()[0].toStdString());
np->handleParticipantChanged(user, nickname, TO_UTF8(m->channel()), (int) flags, pbnetwork::STATUS_ONLINE);
LOG4CXX_INFO(logger, user << ": Joined " << TO_UTF8(m->parameters()[0]));
}
void MyIrcSession::on_parted(IrcMessage *message) {
IrcPartMessage *m = (IrcPartMessage *) message;
bool flags = 0;
std::string nickname = m->sender().name().toStdString();
std::string nickname = TO_UTF8(m->sender().name());
flags = correctNickname(nickname);
LOG4CXX_INFO(logger, user << ": " << nickname << " parted " << m->channel().toStdString() + suffix);
np->handleParticipantChanged(user, nickname, m->channel().toStdString() + suffix,(int) flags, pbnetwork::STATUS_NONE, m->reason().toStdString());
LOG4CXX_INFO(logger, user << ": " << nickname << " parted " << TO_UTF8(m->channel()) + suffix);
np->handleParticipantChanged(user, nickname, TO_UTF8(m->channel()) + suffix,(int) flags, pbnetwork::STATUS_NONE, TO_UTF8(m->reason()));
}
void MyIrcSession::on_quit(IrcMessage *message) {
IrcQuitMessage *m = (IrcQuitMessage *) message;
for(std::list<std::string>::const_iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) {
bool flags = 0;
std::string nickname = m->sender().name().toStdString();
std::string nickname = TO_UTF8(m->sender().name());
flags = correctNickname(nickname);
LOG4CXX_INFO(logger, user << ": " << nickname << " quit " << (*it) + suffix);
np->handleParticipantChanged(user, nickname, (*it) + suffix,(int) flags, pbnetwork::STATUS_NONE, m->reason().toStdString());
np->handleParticipantChanged(user, nickname, (*it) + suffix,(int) flags, pbnetwork::STATUS_NONE, TO_UTF8(m->reason()));
}
}
@ -98,10 +101,10 @@ void MyIrcSession::on_nickChanged(IrcMessage *message) {
IrcNickMessage *m = (IrcNickMessage *) message;
for(std::list<std::string>::const_iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) {
std::string nickname = m->sender().name().toStdString();
std::string nickname = TO_UTF8(m->sender().name());
bool flags = m_modes[(*it) + nickname];
LOG4CXX_INFO(logger, user << ": " << nickname << " changed nickname to " << m->nick().toStdString());
np->handleParticipantChanged(user, nickname, (*it) + suffix,(int) flags, pbnetwork::STATUS_ONLINE, "", m->nick().toStdString());
LOG4CXX_INFO(logger, user << ": " << nickname << " changed nickname to " << TO_UTF8(m->nick()));
np->handleParticipantChanged(user, nickname, (*it) + suffix,(int) flags, pbnetwork::STATUS_ONLINE, "", TO_UTF8(m->nick()));
}
}
@ -109,8 +112,8 @@ void MyIrcSession::on_modeChanged(IrcMessage *message) {
IrcModeMessage *m = (IrcModeMessage *) message;
// mode changed: "#testik" "HanzZ" "+o" "hanzz_k"
std::string nickname = m->argument().toStdString();
std::string mode = m->mode().toStdString();
std::string nickname = TO_UTF8(m->argument());
std::string mode = TO_UTF8(m->mode());
if (nickname.empty())
return;
LOG4CXX_INFO(logger, user << ": " << nickname << " changed mode to " << mode);
@ -130,29 +133,29 @@ void MyIrcSession::on_topicChanged(IrcMessage *message) {
IrcTopicMessage *m = (IrcTopicMessage *) message;
bool flags = 0;
std::string nickname = m->sender().name().toStdString();
std::string nickname = TO_UTF8(m->sender().name());
flags = correctNickname(nickname);
LOG4CXX_INFO(logger, user << ": " << nickname << " topic changed to " << m->topic().toStdString());
np->handleSubject(user, m->channel().toStdString() + suffix, m->topic().toStdString(), nickname);
LOG4CXX_INFO(logger, user << ": " << nickname << " topic changed to " << TO_UTF8(m->topic()));
np->handleSubject(user, TO_UTF8(m->channel()) + suffix, TO_UTF8(m->topic()), nickname);
}
void MyIrcSession::on_messageReceived(IrcMessage *message) {
IrcPrivateMessage *m = (IrcPrivateMessage *) message;
std::string target = m->target().toStdString();
std::string target = TO_UTF8(m->target());
LOG4CXX_INFO(logger, user << ": Message from " << target);
if (target.find("#") == 0) {
bool flags = 0;
std::string nickname = m->sender().name().toStdString();
std::string nickname = TO_UTF8(m->sender().name());
flags = correctNickname(nickname);
np->handleMessage(user, target + suffix, m->message().toStdString(), nickname);
np->handleMessage(user, target + suffix, TO_UTF8(m->message()), nickname);
}
else {
bool flags = 0;
std::string nickname = m->sender().name().toStdString();
std::string nickname = TO_UTF8(m->sender().name());
flags = correctNickname(nickname);
np->handleMessage(user, nickname, m->message().toStdString());
np->handleMessage(user, nickname, TO_UTF8(m->message()));
}
}
@ -163,10 +166,10 @@ void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
IrcNumericMessage *m = (IrcNumericMessage *) message;
switch (m->code()) {
case 332:
m_topicData = m->parameters().value(2).toStdString();
m_topicData = TO_UTF8(m->parameters().value(2));
break;
case 333:
np->handleSubject(user, m->parameters().value(1).toStdString() + suffix, m_topicData, m->parameters().value(2).toStdString());
np->handleSubject(user, TO_UTF8(m->parameters().value(1)) + suffix, m_topicData, TO_UTF8(m->parameters().value(2)));
break;
case 353:
channel = m->parameters().value(2);
@ -174,10 +177,10 @@ void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
for (int i = 0; i < members.size(); i++) {
bool flags = 0;
std::string nickname = members.at(i).toStdString();
std::string nickname = TO_UTF8(members.at(i));
flags = correctNickname(nickname);
m_modes[channel.toStdString() + nickname] = flags;
np->handleParticipantChanged(user, nickname, channel.toStdString() + suffix,(int) flags, pbnetwork::STATUS_ONLINE);
m_modes[TO_UTF8(channel) + nickname] = flags;
np->handleParticipantChanged(user, nickname, TO_UTF8(channel) + suffix,(int) flags, pbnetwork::STATUS_ONLINE);
}
break;
case 432:
@ -193,7 +196,7 @@ void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
}
void MyIrcSession::onMessageReceived(IrcMessage *message) {
LOG4CXX_INFO(logger, user << ": " << message->toString().toStdString());
LOG4CXX_INFO(logger, user << ": " << TO_UTF8(message->toString()));
switch (message->type()) {
case IrcMessage::Join:
on_joined(message);

View file

@ -3,13 +3,16 @@
#include <IrcCommand>
#include <IrcMessage>
#define FROM_UTF8(WHAT) QString::fromUtf8((WHAT).c_str(), (WHAT).size())
#define TO_UTF8(WHAT) std::string((WHAT).toUtf8().data(), (WHAT).toUtf8().size())
DEFINE_LOGGER(logger, "SingleIRCNetworkPlugin");
SingleIRCNetworkPlugin::SingleIRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port) {
this->config = config;
m_server = config->getUnregistered().find("service.irc_server")->second;
m_socket = new QTcpSocket();
m_socket->connectToHost(QString::fromStdString(host), port);
m_socket->connectToHost(FROM_UTF8(host), port);
connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData()));
if (config->getUnregistered().find("service.irc_identify") != config->getUnregistered().end()) {
@ -44,16 +47,18 @@ void SingleIRCNetworkPlugin::handleLoginRequest(const std::string &user, const s
LOG4CXX_INFO(logger, user << ": Connecting " << m_server << " as " << legacyName);
MyIrcSession *session = new MyIrcSession(user, this);
session->setUserName(QString::fromStdString(legacyName));
session->setNickName(QString::fromStdString(legacyName));
session->setRealName(QString::fromStdString(legacyName));
session->setHost(QString::fromStdString(m_server));
session->setUserName(FROM_UTF8(legacyName));
session->setNickName(FROM_UTF8(legacyName));
session->setRealName(FROM_UTF8(legacyName));
session->setHost(FROM_UTF8(m_server));
session->setPort(6667);
std::string identify = m_identify;
boost::replace_all(identify, "$password", password);
boost::replace_all(identify, "$name", legacyName);
session->setIdentify(identify);
if (!password.empty()) {
std::string identify = m_identify;
boost::replace_all(identify, "$password", password);
boost::replace_all(identify, "$name", legacyName);
session->setIdentify(identify);
}
session->open();
@ -88,10 +93,10 @@ void SingleIRCNetworkPlugin::handleMessageSendRequest(const std::string &user, c
}
LOG4CXX_INFO(logger, user << ": Forwarding message to " << r);
m_sessions[user]->sendCommand(IrcCommand::createMessage(QString::fromStdString(r), QString::fromStdString(message)));
m_sessions[user]->sendCommand(IrcCommand::createMessage(FROM_UTF8(r), FROM_UTF8(message)));
if (r.find("#") == 0) {
handleMessage(user, legacyName, message, m_sessions[user]->nickName().toStdString());
handleMessage(user, legacyName, message, TO_UTF8(m_sessions[user]->nickName()));
}
}
@ -103,11 +108,11 @@ void SingleIRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, cons
LOG4CXX_INFO(logger, user << ": Joining " << room);
m_sessions[user]->addAutoJoinChannel(room);
m_sessions[user]->sendCommand(IrcCommand::createJoin(QString::fromStdString(room), QString::fromStdString(password)));
m_sessions[user]->sendCommand(IrcCommand::createJoin(FROM_UTF8(room), FROM_UTF8(password)));
m_sessions[user]->rooms += 1;
// update nickname, because we have nickname per session, no nickname per room.
handleRoomNicknameChanged(user, room, m_sessions[user]->userName().toStdString());
handleRoomNicknameChanged(user, room, TO_UTF8(m_sessions[user]->userName()));
}
void SingleIRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std::string &room) {
@ -120,7 +125,7 @@ void SingleIRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, con
}
LOG4CXX_INFO(logger, user << ": Leaving " << room);
m_sessions[u]->sendCommand(IrcCommand::createPart(QString::fromStdString(r)));
m_sessions[u]->sendCommand(IrcCommand::createPart(FROM_UTF8(r)));
m_sessions[u]->removeAutoJoinChannel(r);
m_sessions[u]->rooms -= 1;
}

View file

@ -366,7 +366,7 @@ bool Skype::createDBusProxy() {
LOG4CXX_INFO(logger, m_username << ":" << error->message);
if (m_counter == 15) {
LOG4CXX_ERROR(logger, "Logging out, proxy couldn't be created");
LOG4CXX_ERROR(logger, "Logging out, proxy couldn't be created: " << error->message);
np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, error->message);
logout();
g_error_free(error);
@ -444,7 +444,8 @@ void Skype::login() {
gchar* argv[6] = {"skype", "--disable-cleanlooks", "--pipelogin", "--dbpath", db, 0};
int fd;
g_spawn_async_with_pipes(NULL,
GError *error = NULL;
bool spawned = g_spawn_async_with_pipes(NULL,
argv,
NULL /*envp*/,
G_SPAWN_SEARCH_PATH,
@ -454,9 +455,16 @@ void Skype::login() {
&fd,
NULL,
&fd_output,
NULL /*error*/);
&error);
if (!spawned) {
LOG4CXX_ERROR(logger, "Error spawning the Skype instance: " << error->message)
np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Error spawning the Skype instance.");
return;
}
std::string login_data = std::string(m_username + " " + m_password + "\n");
LOG4CXX_INFO(logger, m_username << ": Login data=" << login_data);
LOG4CXX_INFO(logger, m_username << ": Login data=" << m_username);
write(fd, login_data.c_str(), login_data.size());
close(fd);
@ -469,12 +477,12 @@ void Skype::login() {
if (m_connection == NULL)
{
LOG4CXX_INFO(logger, "Creating DBus connection.");
LOG4CXX_INFO(logger, "Creating DBUS connection.");
GError *error = NULL;
m_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
if (m_connection == NULL && error != NULL)
{
LOG4CXX_INFO(logger, m_username << ": DBUS Error: " << error->message);
LOG4CXX_INFO(logger, m_username << ": Creating DBUS Connection error: " << error->message);
g_error_free(error);
return;
}
@ -616,8 +624,12 @@ void Skype::logout() {
send_command("SET USERSTATUS OFFLINE");
sleep(2);
g_object_unref(m_proxy);
LOG4CXX_INFO(logger, m_username << ": Killing Skype instance");
LOG4CXX_INFO(logger, m_username << ": Terminating Skype instance (SIGTERM)");
kill((int) m_pid, SIGTERM);
// Give skype a chance
sleep(2);
LOG4CXX_INFO(logger, m_username << ": Killing Skype instance (SIGKILL)");
kill((int) m_pid, SIGKILL);
m_pid = 0;
}
}

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include <Swiften/Parser/PayloadParsers/MUCPayloadParser.h>
#include <boost/lexical_cast.hpp>
#include <Swiften/Parser/PayloadParserFactoryCollection.h>
#include <Swiften/Parser/PayloadParserFactory.h>
#include <Swiften/Base/foreach.h>
#include <Swiften/Elements/MUCOccupant.h>
#include <Swiften/Parser/Tree/TreeReparser.h>
namespace Swift {
void MUCPayloadParser::handleTree(ParserElement::ref root) {
foreach (ParserElement::ref child, root->getAllChildren()) {
if (child->getName() == "password" && child->getNamespace() == root->getNamespace()) {
getPayloadInternal()->setPassword(child->getText());
}
}
}
}

View file

@ -0,0 +1,22 @@
/*
* Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <boost/optional.hpp>
#include <Swiften/Elements/MUCPayload.h>
#include <Swiften/Parser/GenericPayloadTreeParser.h>
#include <Swiften/Parser/PayloadParsers/MUCItemParser.h>
namespace Swift {
class PayloadParserFactoryCollection;
class MUCPayloadParser : public GenericPayloadTreeParser<MUCPayload> {
public:
MUCPayloadParser(){}
virtual void handleTree(ParserElement::ref root);
};
}

View file

@ -3,12 +3,12 @@ if (PROTOBUF_FOUND)
set (PROTOBUF_PROTOC_EXECUTABLE protoc)
endif()
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/protocol.pb.cc ${CMAKE_CURRENT_BINARY_DIR}/protocol.pb.h
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --cpp_out ${CMAKE_CURRENT_BINARY_DIR} --proto_path ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/protocol.proto
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/protocol.pb.cc ${CMAKE_CURRENT_SOURCE_DIR}/protocol.pb.h
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --cpp_out ${CMAKE_CURRENT_SOURCE_DIR} --proto_path ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/protocol.proto
COMMENT "Running C++ protocol buffer compiler on protocol.proto"
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/protocol.proto
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/protocol.proto
)
ADD_CUSTOM_TARGET(pb DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/protocol.pb.cc)
ADD_CUSTOM_TARGET(pb DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/protocol.pb.cc)
endif()
FILE(GLOB HEADERS *.h protocol.h)

View file

@ -51,10 +51,20 @@ class LocalBuddy : public Buddy {
}
std::string getIconHash() { return m_iconHash; }
void setIconHash(const std::string &iconHash) { m_iconHash = iconHash; }
void setIconHash(const std::string &iconHash) {
bool changed = m_iconHash != iconHash;
m_iconHash = iconHash;
if (changed)
getRosterManager()->storeBuddy(this);
}
std::vector<std::string> getGroups() { return m_groups; }
void setGroups(const std::vector<std::string> &groups) { m_groups = groups; }
void setGroups(const std::vector<std::string> &groups) {
bool changed = m_groups.size() != groups.size();
m_groups = groups;
if (changed)
getRosterManager()->storeBuddy(this);
}
private:
std::string m_name;

View file

@ -2,10 +2,10 @@ cmake_minimum_required(VERSION 2.6)
FILE(GLOB SRC *.cpp *.h)
FILE(GLOB HEADERS ../include/transport/*.h)
set(EXTRA_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/../../src/memoryusage.cpp)
set(EXTRA_SOURCES ${EXTRA_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/../../src/logging.cpp)
set(EXTRA_SOURCES ${EXTRA_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/../../src/config.cpp)
set(EXTRA_SOURCES ${EXTRA_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/../../include/transport/protocol.pb.cc)
set(EXTRA_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../../src/memoryusage.cpp)
set(EXTRA_SOURCES ${EXTRA_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/../../src/logging.cpp)
set(EXTRA_SOURCES ${EXTRA_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/../../src/config.cpp)
set(EXTRA_SOURCES ${EXTRA_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/../../include/transport/protocol.pb.cc)
if (NOT WIN32)
ADD_LIBRARY(transport-plugin SHARED ${HEADERS} ${SRC} ${PROTOBUF_SRC} ${PROTOBUF_HDRS} ${EXTRA_SOURCES})
@ -15,7 +15,7 @@ else()
ADD_DEPENDENCIES(transport-plugin libprotobuf)
endif()
ADD_DEPENDENCIES(transport-plugin pb)
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/../../include/transport/protocol.pb.cc PROPERTIES GENERATED 1)
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/../../include/transport/protocol.pb.cc PROPERTIES GENERATED 1)
if (CMAKE_COMPILER_IS_GNUCXX)
ADD_DEFINITIONS(-fPIC)
@ -31,7 +31,7 @@ SET_TARGET_PROPERTIES(transport-plugin PROPERTIES
VERSION ${TRANSPORT_VERSION} SOVERSION ${TRANSPORT_VERSION}
)
INSTALL(TARGETS transport-plugin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib COMPONENT libraries)
INSTALL(TARGETS transport-plugin LIBRARY DESTINATION ${LIB_INSTALL_DIR} ARCHIVE DESTINATION ${LIB_INSTALL_DIR} COMPONENT libraries)
#CONFIGURE_FILE(transport.pc.in "${CMAKE_CURRENT_BINARY_DIR}/transport.pc")
#INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/transport.pc" DESTINATION lib/pkgconfig)
#CONFIGURE_FILE(transport.pc.in "${CMAKE_CURRENT_SOURCE_DIR}/transport.pc")
#INSTALL(FILES "${CMAKE_CURRENT_SOURCE_DIR}/transport.pc" DESTINATION lib/pkgconfig)

View file

@ -7,7 +7,9 @@ if (PROTOBUF_FOUND)
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)
ADD_CUSTOM_TARGET(pb-python ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/protocol_pb2.py)
endif()

View file

@ -13,7 +13,8 @@ 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=../..//backends/libpurple/spectrum2_libpurple_backend
#backend=../..//backends/libpurple/spectrum2_libpurple_backend
backend=../../backends/template/spectrum2_template_backend
protocol=prpl-xmpp
#protocol=prpl-msn
#protocol=any

BIN
spectrum/src/server.p12 Normal file

Binary file not shown.

View file

@ -46,8 +46,8 @@ endif()
if (NOT CMAKE_COMPILER_IS_GNUCXX)
include_directories("${CMAKE_SOURCE_DIR}/msvc-deps/protobuf/libprotobuf")
TARGET_LINK_LIBRARIES(transport transport-plugin ${PQXX_LIBRARY} ${PQ_LIBRARY} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES})
else ()
TARGET_LINK_LIBRARIES(transport transport-plugin sqlite3 libprotobuf ${PQXX_LIBRARY} ${PQ_LIBRARY} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
else (WIN32)
TARGET_LINK_LIBRARIES(transport transport-plugin ${PQXX_LIBRARY} ${PQ_LIBRARY} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES} ${POPT_LIBRARY})
endif()
@ -55,7 +55,7 @@ SET_TARGET_PROPERTIES(transport PROPERTIES
VERSION ${TRANSPORT_VERSION} SOVERSION ${TRANSPORT_VERSION}
)
INSTALL(TARGETS transport LIBRARY DESTINATION lib ARCHIVE DESTINATION lib COMPONENT libraries)
INSTALL(TARGETS transport LIBRARY DESTINATION ${LIB_INSTALL_DIR} ARCHIVE DESTINATION ${LIB_INSTALL_DIR} COMPONENT libraries)
#CONFIGURE_FILE(transport.pc.in "${CMAKE_CURRENT_BINARY_DIR}/transport.pc")
#INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/transport.pc" DESTINATION lib/pkgconfig)

View file

@ -148,7 +148,6 @@ void Buddy::handleBuddyChanged() {
if (presence) {
m_rosterManager->getUser()->getComponent()->getStanzaChannel()->sendPresence(presence);
}
m_rosterManager->handleBuddyChanged(this);
}
void Buddy::handleVCardReceived(const std::string &id, Swift::VCard::ref vcard) {

View file

@ -93,6 +93,7 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
("registration.instructions", value<std::string>()->default_value("Enter your legacy network username and password."), "Instructions showed to user in registration form")
("registration.username_label", value<std::string>()->default_value("Legacy network username:"), "Label for username field")
("registration.username_mask", value<std::string>()->default_value(""), "Username mask")
("registration.auto_register", value<bool>()->default_value(false), "Register new user automatically when the presence arrives.")
("registration.encoding", value<std::string>()->default_value("utf8"), "Default encoding in registration form")
("registration.require_local_account", value<bool>()->default_value(false), "True if users have to have a local account to register to this transport from remote servers.")
("registration.local_username_label", value<std::string>()->default_value("Local username:"), "Label for local usernme field")

View file

@ -163,9 +163,14 @@ static unsigned long exec_(std::string path, const char *host, const char *port,
if ( pid == 0 ) {
setsid();
// child process
exit(execv(argv[0], argv));
errno = 0;
int ret = execv(argv[0], argv);
if (ret == -1) {
exit(errno);
}
exit(0);
} else if ( pid < 0 ) {
// fork failed
LOG4CXX_ERROR(logger, "Fork failed");
}
free(p);
@ -258,12 +263,29 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U
LOG4CXX_INFO(logger, "Listening on host " << CONFIG_STRING(m_config, "service.backend_host") << " port " << CONFIG_STRING(m_config, "service.backend_port"));
unsigned long pid = exec_(CONFIG_STRING(m_config, "service.backend"), CONFIG_STRING(m_config, "service.backend_host").c_str(), CONFIG_STRING(m_config, "service.backend_port").c_str(), m_config->getConfigFile().c_str());
LOG4CXX_INFO(logger, "Backend should now connect to Spectrum2 instance. Spectrum2 won't accept any connection before backend connects");
#ifndef _WIN32
// wait if the backend process will still be alive after 1 second
sleep(1);
pid_t result;
int status;
result = waitpid(-1, &status, WNOHANG);
if (result != 0) {
if (WIFEXITED(status)) {
if (WEXITSTATUS(status) != 0) {
LOG4CXX_ERROR(logger, "Backend can not be started, exit_code=" << WEXITSTATUS(status) << ", possible error: " << strerror(WEXITSTATUS(status)));
}
}
else {
LOG4CXX_ERROR(logger, "Backend can not be started");
}
}
signal(SIGCHLD, SigCatcher);
#endif
exec_(CONFIG_STRING(m_config, "service.backend"), CONFIG_STRING(m_config, "service.backend_host").c_str(), CONFIG_STRING(m_config, "service.backend_port").c_str(), m_config->getConfigFile().c_str());
LOG4CXX_INFO(logger, "Backend should now connect to Spectrum2 instance. Spectrum2 won't accept any connection before backend connects");
}
NetworkPluginServer::~NetworkPluginServer() {

View file

@ -152,9 +152,6 @@ void RosterManager::sendBuddySubscribePresence(Buddy *buddy) {
}
void RosterManager::handleBuddyChanged(Buddy *buddy) {
if (m_rosterStorage) {
m_rosterStorage->storeBuddy(buddy);
}
}
void RosterManager::setBuddyCallback(Buddy *buddy) {

View file

@ -47,6 +47,7 @@
#include "Swiften/Parser/PayloadParsers/GatewayPayloadParser.h"
#include "Swiften/Serializer/PayloadSerializers/GatewayPayloadSerializer.h"
#include "Swiften/Serializer/PayloadSerializers/SpectrumErrorSerializer.h"
#include "Swiften/Parser/PayloadParsers/MUCPayloadParser.h"
#include "transport/BlockParser.h"
#include "transport/BlockSerializer.h"
#include "Swiften/Parser/PayloadParsers/InvisibleParser.h"
@ -107,6 +108,7 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories,
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::StatsParser>("query", "http://jabber.org/protocol/stats"));
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::GatewayPayloadParser>("query", "jabber:iq:gateway"));
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::MUCPayloadParser>("x", "http://jabber.org/protocol/muc"));
m_server->addPayloadSerializer(new Swift::AttentionSerializer());
m_server->addPayloadSerializer(new Swift::XHTMLIMSerializer());
@ -135,6 +137,7 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories,
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::StatsParser>("query", "http://jabber.org/protocol/stats"));
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::GatewayPayloadParser>("query", "jabber:iq:gateway"));
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::MUCPayloadParser>("x", "http://jabber.org/protocol/muc"));
m_component->addPayloadSerializer(new Swift::AttentionSerializer());
m_component->addPayloadSerializer(new Swift::XHTMLIMSerializer());

View file

@ -214,6 +214,34 @@ void UserManager::handlePresence(Swift::Presence::ref presence) {
res.password = m_userRegistry->getUserPassword(userkey);
}
// We allow auto_register feature in gateway-mode. This allows IRC user to register
// the transport just by joining the room.
if (!m_component->inServerMode()) {
if (!registered && CONFIG_BOOL(m_component->getConfig(), "registration.auto_register")) {
res.password = "";
res.jid = userkey;
bool isMUC = presence->getPayload<Swift::MUCPayload>() != NULL || *presence->getTo().getNode().c_str() == '#';
if (isMUC) {
res.uin = presence->getTo().getResource();
}
else {
res.uin = presence->getFrom().toString();
}
LOG4CXX_INFO(logger, "Auto-registering user " << userkey << " with uin=" << res.uin);
if (m_storageBackend) {
// store user and getUser again to get user ID.
m_storageBackend->setUser(res);
registered = m_storageBackend->getUser(userkey, res);
}
else {
registered = false;
}
}
}
// Unregistered users are not able to login
if (!registered) {
LOG4CXX_WARN(logger, "Unregistered user " << userkey << " tried to login");
@ -282,7 +310,12 @@ void UserManager::handleMessageReceived(Swift::Message::ref message) {
}
user->getConversationManager()->handleMessageReceived(message);
messageToBackendSent();
// Do not count chatstate notification...
boost::shared_ptr<Swift::ChatState> statePayload = message->getPayload<Swift::ChatState>();
if (!statePayload) {
messageToBackendSent();
}
}
void UserManager::handleGeneralPresenceReceived(Swift::Presence::ref presence) {