Merge remote-tracking branch 'hanzz/origin/master'
This commit is contained in:
commit
eaa28f6599
76 changed files with 1658 additions and 943 deletions
|
@ -44,8 +44,8 @@ message( STATUS "Found Boost: ${Boost_LIBRARIES}, ${Boost_INCLUDE_DIR}")
|
||||||
set(Protobuf_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
set(Protobuf_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||||
find_package(Protobuf REQUIRED)
|
find_package(Protobuf REQUIRED)
|
||||||
|
|
||||||
set(IRCClientQt_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
set(Communi_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||||
find_package(IRCClientQt)
|
find_package(Communi)
|
||||||
|
|
||||||
set(log4cxx_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
set(log4cxx_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||||
find_package(log4cxx)
|
find_package(log4cxx)
|
||||||
|
@ -64,6 +64,25 @@ ADD_DEFINITIONS(-DBOOST_FILESYSTEM_VERSION=2)
|
||||||
|
|
||||||
message(" Supported features")
|
message(" Supported features")
|
||||||
message("-----------------------")
|
message("-----------------------")
|
||||||
|
|
||||||
|
if (SPECTRUM_VERSION)
|
||||||
|
ADD_DEFINITIONS(-DSPECTRUM_VERSION="${SPECTRUM_VERSION}")
|
||||||
|
else (SPECTRUM_VERSION)
|
||||||
|
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
|
||||||
|
execute_process(COMMAND git "--git-dir=${CMAKE_CURRENT_SOURCE_DIR}/.git" rev-parse --short HEAD
|
||||||
|
OUTPUT_VARIABLE GIT_REVISION
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
set(SPECTRUM_VERSION 2.0.0-beta-git-${GIT_REVISION})
|
||||||
|
ADD_DEFINITIONS(-DSPECTRUM_VERSION="${SPECTRUM_VERSION}")
|
||||||
|
else (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
|
||||||
|
set(SPECTRUM_VERSION 2.0.0-alpha)
|
||||||
|
ADD_DEFINITIONS(-DSPECTRUM_VERSION="${SPECTRUM_VERSION}")
|
||||||
|
endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
|
||||||
|
endif (SPECTRUM_VERSION)
|
||||||
|
|
||||||
|
message("Version : " ${SPECTRUM_VERSION})
|
||||||
|
|
||||||
if (SQLITE3_FOUND)
|
if (SQLITE3_FOUND)
|
||||||
ADD_DEFINITIONS(-DWITH_SQLITE)
|
ADD_DEFINITIONS(-DWITH_SQLITE)
|
||||||
include_directories(${SQLITE3_INCLUDE_DIR})
|
include_directories(${SQLITE3_INCLUDE_DIR})
|
||||||
|
@ -104,13 +123,13 @@ if (PROTOBUF_FOUND)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(IRC_FOUND)
|
if(IRC_FOUND)
|
||||||
ADD_DEFINITIONS(-DIRC_SHARED)
|
ADD_DEFINITIONS(-DCOMMUNI_SHARED)
|
||||||
message("IRC plugin : yes")
|
message("IRC plugin : yes")
|
||||||
include_directories(${QT_QTNETWORK_INCLUDE_DIR})
|
include_directories(${QT_QTNETWORK_INCLUDE_DIR})
|
||||||
include_directories(${IRC_INCLUDE_DIR})
|
include_directories(${IRC_INCLUDE_DIR})
|
||||||
include(${QT_USE_FILE})
|
include(${QT_USE_FILE})
|
||||||
else()
|
else()
|
||||||
message("IRC plugin : no (install libircclient-qt and libprotobuf-dev)")
|
message("IRC plugin : no (install libCommuni and libprotobuf-dev)")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
message("Frotz plugin : yes")
|
message("Frotz plugin : yes")
|
||||||
|
@ -170,10 +189,8 @@ include_directories(${OPENSSL_INCLUDE_DIR})
|
||||||
ADD_SUBDIRECTORY(src)
|
ADD_SUBDIRECTORY(src)
|
||||||
ADD_SUBDIRECTORY(plugin)
|
ADD_SUBDIRECTORY(plugin)
|
||||||
ADD_SUBDIRECTORY(include)
|
ADD_SUBDIRECTORY(include)
|
||||||
#ADD_SUBDIRECTORY(examples)
|
|
||||||
ADD_SUBDIRECTORY(spectrum)
|
ADD_SUBDIRECTORY(spectrum)
|
||||||
ADD_SUBDIRECTORY(backends)
|
ADD_SUBDIRECTORY(backends)
|
||||||
#ADD_SUBDIRECTORY(tests)
|
|
||||||
if (NOT WIN32)
|
if (NOT WIN32)
|
||||||
ADD_SUBDIRECTORY(spectrum_manager)
|
ADD_SUBDIRECTORY(spectrum_manager)
|
||||||
endif()
|
endif()
|
||||||
|
|
6
README
6
README
|
@ -0,0 +1,6 @@
|
||||||
|
Spectrum is an XMPP transport/gateway. It allows XMPP users to communicate with
|
||||||
|
their friends who are using one of the supported networks. It supports a wide
|
||||||
|
range of different networks such as ICQ, XMPP (Jabber, GTalk), AIM, MSN,
|
||||||
|
Facebook, Twitter, Gadu-Gadu, IRC and SIMPLE. Spectrum is written in C++
|
||||||
|
and uses the Swiften XMPP library and libpurple for “legacy networks”.
|
||||||
|
Spectrum is open source and released under the GNU GPL.
|
|
@ -4,7 +4,7 @@ if (PROTOBUF_FOUND)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (IRC_FOUND)
|
if (IRC_FOUND)
|
||||||
ADD_SUBDIRECTORY(libircclient-qt)
|
ADD_SUBDIRECTORY(libcommuni)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT WIN32)
|
if (NOT WIN32)
|
||||||
|
|
10
backends/libcommuni/CMakeLists.txt
Normal file
10
backends/libcommuni/CMakeLists.txt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
cmake_minimum_required(VERSION 2.6)
|
||||||
|
FILE(GLOB SRC *.cpp)
|
||||||
|
FILE(GLOB HEADERS *.h)
|
||||||
|
QT4_WRAP_CPP(SRC ${HEADERS})
|
||||||
|
ADD_EXECUTABLE(spectrum2_libcommuni_backend ${SRC})
|
||||||
|
|
||||||
|
target_link_libraries(spectrum2_libcommuni_backend ${IRC_LIBRARY} ${QT_LIBRARIES} transport-plugin transport pthread)
|
||||||
|
|
||||||
|
INSTALL(TARGETS spectrum2_libcommuni_backend RUNTIME DESTINATION bin)
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
#include "ircnetworkplugin.h"
|
#include "ircnetworkplugin.h"
|
||||||
|
#include <IrcCommand>
|
||||||
|
#include <IrcMessage>
|
||||||
|
|
||||||
IRCNetworkPlugin::IRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port) {
|
IRCNetworkPlugin::IRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port) {
|
||||||
this->config = config;
|
this->config = config;
|
||||||
|
@ -26,8 +28,10 @@ void IRCNetworkPlugin::handleLoginRequest(const std::string &user, const std::st
|
||||||
if (CONFIG_BOOL(config, "service.server_mode")) {
|
if (CONFIG_BOOL(config, "service.server_mode")) {
|
||||||
MyIrcSession *session = new MyIrcSession(user, this);
|
MyIrcSession *session = new MyIrcSession(user, this);
|
||||||
std::string h = user.substr(0, user.find("@"));
|
std::string h = user.substr(0, user.find("@"));
|
||||||
session->setNick(QString::fromStdString(h.substr(0, h.find("%"))));
|
session->setNickName(QString::fromStdString(h.substr(0, h.find("%"))));
|
||||||
session->connectToServer(QString::fromStdString(h.substr(h.find("%") + 1)), 6667);
|
session->setHost(QString::fromStdString(h.substr(h.find("%") + 1)));
|
||||||
|
session->setPort(6667);
|
||||||
|
session->open();
|
||||||
std::cout << "CONNECTING IRC NETWORK " << h.substr(h.find("%") + 1) << "\n";
|
std::cout << "CONNECTING IRC NETWORK " << h.substr(h.find("%") + 1) << "\n";
|
||||||
m_sessions[user] = session;
|
m_sessions[user] = session;
|
||||||
}
|
}
|
||||||
|
@ -39,7 +43,7 @@ void IRCNetworkPlugin::handleLoginRequest(const std::string &user, const std::st
|
||||||
void IRCNetworkPlugin::handleLogoutRequest(const std::string &user, const std::string &legacyName) {
|
void IRCNetworkPlugin::handleLogoutRequest(const std::string &user, const std::string &legacyName) {
|
||||||
if (m_sessions[user] == NULL)
|
if (m_sessions[user] == NULL)
|
||||||
return;
|
return;
|
||||||
m_sessions[user]->disconnectFromServer();
|
m_sessions[user]->close();
|
||||||
m_sessions[user]->deleteLater();
|
m_sessions[user]->deleteLater();
|
||||||
m_sessions.erase(user);
|
m_sessions.erase(user);
|
||||||
}
|
}
|
||||||
|
@ -68,7 +72,7 @@ void IRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout << "MESSAGE " << u << " " << r << "\n";
|
std::cout << "MESSAGE " << u << " " << r << "\n";
|
||||||
m_sessions[u]->message(QString::fromStdString(r), QString::fromStdString(message));
|
m_sessions[u]->sendCommand(IrcCommand::createMessage(QString::fromStdString(r), QString::fromStdString(message)));
|
||||||
std::cout << "SENT\n";
|
std::cout << "SENT\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,8 +89,10 @@ void IRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std:
|
||||||
if (room.find("@") != std::string::npos) {
|
if (room.find("@") != std::string::npos) {
|
||||||
// suffix is %irc.freenode.net to let MyIrcSession return #room%irc.freenode.net
|
// suffix is %irc.freenode.net to let MyIrcSession return #room%irc.freenode.net
|
||||||
MyIrcSession *session = new MyIrcSession(user, this, room.substr(room.find("@")));
|
MyIrcSession *session = new MyIrcSession(user, this, room.substr(room.find("@")));
|
||||||
session->setNick(QString::fromStdString(nickname));
|
session->setNickName(QString::fromStdString(nickname));
|
||||||
session->connectToServer(QString::fromStdString(room.substr(room.find("@") + 1)), 6667);
|
session->setHost(QString::fromStdString(room.substr(room.find("@") + 1)));
|
||||||
|
session->setPort(6667);
|
||||||
|
session->open();
|
||||||
std::cout << "CONNECTING IRC NETWORK " << room.substr(room.find("@") + 1) << "\n";
|
std::cout << "CONNECTING IRC NETWORK " << room.substr(room.find("@") + 1) << "\n";
|
||||||
std::cout << "SUFFIX " << room.substr(room.find("@")) << "\n";
|
std::cout << "SUFFIX " << room.substr(room.find("@")) << "\n";
|
||||||
m_sessions[u] = session;
|
m_sessions[u] = session;
|
||||||
|
@ -96,11 +102,11 @@ void IRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout << "JOINING " << r << "\n";
|
std::cout << "JOINING " << r << "\n";
|
||||||
m_sessions[u]->addAutoJoinChannel(QString::fromStdString(r));
|
m_sessions[u]->addAutoJoinChannel(r);
|
||||||
m_sessions[u]->join(QString::fromStdString(r), QString::fromStdString(password));
|
m_sessions[u]->sendCommand(IrcCommand::createJoin(QString::fromStdString(r), QString::fromStdString(password)));
|
||||||
m_sessions[u]->rooms += 1;
|
m_sessions[u]->rooms += 1;
|
||||||
// update nickname, because we have nickname per session, no nickname per room.
|
// update nickname, because we have nickname per session, no nickname per room.
|
||||||
handleRoomNicknameChanged(user, r, m_sessions[u]->nick().toStdString());
|
handleRoomNicknameChanged(user, r, m_sessions[u]->nickName().toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std::string &room) {
|
void IRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std::string &room) {
|
||||||
|
@ -114,12 +120,12 @@ void IRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std
|
||||||
if (m_sessions[u] == NULL)
|
if (m_sessions[u] == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_sessions[u]->part(QString::fromStdString(r));
|
m_sessions[u]->sendCommand(IrcCommand::createPart(QString::fromStdString(r)));
|
||||||
m_sessions[u]->removeAutoJoinChannel(QString::fromStdString(r));
|
m_sessions[u]->removeAutoJoinChannel(r);
|
||||||
m_sessions[u]->rooms -= 1;
|
m_sessions[u]->rooms -= 1;
|
||||||
|
|
||||||
if (m_sessions[u]->rooms <= 0) {
|
if (m_sessions[u]->rooms <= 0) {
|
||||||
m_sessions[u]->disconnectFromServer();
|
m_sessions[u]->close();
|
||||||
m_sessions[u]->deleteLater();
|
m_sessions[u]->deleteLater();
|
||||||
m_sessions.erase(u);
|
m_sessions.erase(u);
|
||||||
}
|
}
|
|
@ -15,11 +15,22 @@
|
||||||
#include <QtNetwork>
|
#include <QtNetwork>
|
||||||
#include "Swiften/EventLoop/Qt/QtEventLoop.h"
|
#include "Swiften/EventLoop/Qt/QtEventLoop.h"
|
||||||
#include "ircnetworkplugin.h"
|
#include "ircnetworkplugin.h"
|
||||||
|
#include "singleircnetworkplugin.h"
|
||||||
|
|
||||||
|
#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"
|
||||||
|
|
||||||
using namespace boost::program_options;
|
using namespace boost::program_options;
|
||||||
using namespace Transport;
|
using namespace Transport;
|
||||||
|
|
||||||
IRCNetworkPlugin * np = NULL;
|
using namespace log4cxx;
|
||||||
|
|
||||||
|
NetworkPlugin * np = NULL;
|
||||||
|
|
||||||
int main (int argc, char* argv[]) {
|
int main (int argc, char* argv[]) {
|
||||||
std::string host;
|
std::string host;
|
||||||
|
@ -72,8 +83,39 @@ int main (int argc, char* argv[]) {
|
||||||
}
|
}
|
||||||
QCoreApplication app(argc, 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);
|
||||||
|
}
|
||||||
|
|
||||||
Swift::QtEventLoop eventLoop;
|
Swift::QtEventLoop eventLoop;
|
||||||
np = new IRCNetworkPlugin(&config, &eventLoop, host, port);
|
|
||||||
|
if (config.getUnregistered().find("service.irc_server") == config.getUnregistered().end()) {
|
||||||
|
np = new IRCNetworkPlugin(&config, &eventLoop, host, port);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
np = new SingleIRCNetworkPlugin(&config, &eventLoop, host, port);
|
||||||
|
}
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
212
backends/libcommuni/session.cpp
Normal file
212
backends/libcommuni/session.cpp
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com
|
||||||
|
*
|
||||||
|
* This example is free, and not covered by LGPL license. There is no
|
||||||
|
* restriction applied to their modification, redistribution, using and so on.
|
||||||
|
* You can study them, modify them, use them in your own program - either
|
||||||
|
* completely or partially. By using it you may give me some credits in your
|
||||||
|
* program, but you don't have to.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "session.h"
|
||||||
|
#include <QtCore>
|
||||||
|
#include <iostream>
|
||||||
|
#include "Swiften/Elements/StatusShow.h"
|
||||||
|
#include <IrcCommand>
|
||||||
|
#include <IrcMessage>
|
||||||
|
|
||||||
|
#include "log4cxx/logger.h"
|
||||||
|
|
||||||
|
using namespace log4cxx;
|
||||||
|
|
||||||
|
static LoggerPtr logger = log4cxx::Logger::getLogger("IRCSession");
|
||||||
|
|
||||||
|
MyIrcSession::MyIrcSession(const std::string &user, NetworkPlugin *np, const std::string &suffix, QObject* parent) : IrcSession(parent)
|
||||||
|
{
|
||||||
|
this->np = np;
|
||||||
|
this->user = user;
|
||||||
|
this->suffix = suffix;
|
||||||
|
rooms = 0;
|
||||||
|
connect(this, SIGNAL(disconnected()), SLOT(on_disconnected()));
|
||||||
|
connect(this, SIGNAL(connected()), SLOT(on_connected()));
|
||||||
|
connect(this, SIGNAL(messageReceived(IrcMessage*)), this, SLOT(onMessageReceived(IrcMessage*)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyIrcSession::on_connected() {
|
||||||
|
if (suffix.empty()) {
|
||||||
|
np->handleConnected(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(std::list<std::string>::const_iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) {
|
||||||
|
sendCommand(IrcCommand::createJoin(QString::fromStdString(*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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyIrcSession::on_disconnected() {
|
||||||
|
if (suffix.empty())
|
||||||
|
np->handleDisconnected(user, 0, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MyIrcSession::correctNickname(std::string &nickname) {
|
||||||
|
bool flags = 0;
|
||||||
|
switch(nickname.at(0)) {
|
||||||
|
case '@': nickname = nickname.substr(1); flags = 1; break;
|
||||||
|
case '+': nickname = nickname.substr(1); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyIrcSession::on_joined(IrcMessage *message) {
|
||||||
|
IrcJoinMessage *m = (IrcJoinMessage *) message;
|
||||||
|
bool flags = 0;
|
||||||
|
std::string nickname = m->sender().name().toStdString();
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MyIrcSession::on_parted(IrcMessage *message) {
|
||||||
|
IrcPartMessage *m = (IrcPartMessage *) message;
|
||||||
|
bool flags = 0;
|
||||||
|
std::string nickname = m->sender().name().toStdString();
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
if (nickname.empty())
|
||||||
|
return;
|
||||||
|
LOG4CXX_INFO(logger, user << ": " << nickname << " changed mode to " << mode);
|
||||||
|
for(std::list<std::string>::const_iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) {
|
||||||
|
if (mode == "+o") {
|
||||||
|
m_modes[(*it) + nickname] = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_modes[(*it) + nickname] = 0;
|
||||||
|
}
|
||||||
|
bool flags = m_modes[(*it) + nickname];
|
||||||
|
np->handleParticipantChanged(user, nickname, (*it) + suffix,(int) flags, pbnetwork::STATUS_ONLINE, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyIrcSession::on_topicChanged(IrcMessage *message) {
|
||||||
|
IrcTopicMessage *m = (IrcTopicMessage *) message;
|
||||||
|
|
||||||
|
bool flags = 0;
|
||||||
|
std::string nickname = m->sender().name().toStdString();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyIrcSession::on_messageReceived(IrcMessage *message) {
|
||||||
|
IrcPrivateMessage *m = (IrcPrivateMessage *) message;
|
||||||
|
|
||||||
|
std::string target = m->target().toStdString();
|
||||||
|
LOG4CXX_INFO(logger, user << ": Message from " << target);
|
||||||
|
if (target.find("#") == 0) {
|
||||||
|
bool flags = 0;
|
||||||
|
std::string nickname = m->sender().name().toStdString();
|
||||||
|
flags = correctNickname(nickname);
|
||||||
|
np->handleMessage(user, target + suffix, m->message().toStdString(), nickname);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bool flags = 0;
|
||||||
|
std::string nickname = m->sender().name().toStdString();
|
||||||
|
flags = correctNickname(nickname);
|
||||||
|
np->handleMessage(user, nickname, m->message().toStdString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
|
||||||
|
IrcNumericMessage *m = (IrcNumericMessage *) message;
|
||||||
|
switch (m->code()) {
|
||||||
|
case 332:
|
||||||
|
m_topicData = m->parameters().value(2).toStdString();
|
||||||
|
break;
|
||||||
|
case 333:
|
||||||
|
np->handleSubject(user, m->parameters().value(1).toStdString() + suffix, m_topicData, m->parameters().value(2).toStdString());
|
||||||
|
break;
|
||||||
|
case 353:
|
||||||
|
QString channel = m->parameters().value(2);
|
||||||
|
QStringList members = m->parameters().value(3).split(" ");
|
||||||
|
|
||||||
|
for (int i = 0; i < members.size(); i++) {
|
||||||
|
bool flags = 0;
|
||||||
|
std::string nickname = members.at(i).toStdString();
|
||||||
|
flags = correctNickname(nickname);
|
||||||
|
m_modes[channel.toStdString() + nickname] = flags;
|
||||||
|
np->handleParticipantChanged(user, nickname, channel.toStdString() + suffix,(int) flags, pbnetwork::STATUS_ONLINE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//qDebug() << "numeric message received:" << receiver() << origin << code << params;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyIrcSession::onMessageReceived(IrcMessage *message) {
|
||||||
|
LOG4CXX_INFO(logger, user << ": " << message->toString().toStdString());
|
||||||
|
switch (message->type()) {
|
||||||
|
case IrcMessage::Join:
|
||||||
|
on_joined(message);
|
||||||
|
break;
|
||||||
|
case IrcMessage::Part:
|
||||||
|
on_parted(message);
|
||||||
|
break;
|
||||||
|
case IrcMessage::Quit:
|
||||||
|
on_quit(message);
|
||||||
|
break;
|
||||||
|
case IrcMessage::Nick:
|
||||||
|
on_nickChanged(message);
|
||||||
|
break;
|
||||||
|
case IrcMessage::Mode:
|
||||||
|
on_modeChanged(message);
|
||||||
|
break;
|
||||||
|
case IrcMessage::Topic:
|
||||||
|
on_topicChanged(message);
|
||||||
|
break;
|
||||||
|
case IrcMessage::Private:
|
||||||
|
on_messageReceived(message);
|
||||||
|
break;
|
||||||
|
case IrcMessage::Numeric:
|
||||||
|
on_numericMessageReceived(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
103
backends/libcommuni/session.h
Normal file
103
backends/libcommuni/session.h
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com
|
||||||
|
*
|
||||||
|
* This example is free, and not covered by LGPL license. There is no
|
||||||
|
* restriction applied to their modification, redistribution, using and so on.
|
||||||
|
* You can study them, modify them, use them in your own program - either
|
||||||
|
* completely or partially. By using it you may give me some credits in your
|
||||||
|
* program, but you don't have to.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SESSION_H
|
||||||
|
#define SESSION_H
|
||||||
|
|
||||||
|
#include <IrcSession>
|
||||||
|
#include <transport/networkplugin.h>
|
||||||
|
|
||||||
|
using namespace Transport;
|
||||||
|
|
||||||
|
class MyIrcSession : public IrcSession
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MyIrcSession(const std::string &user, NetworkPlugin *np, const std::string &suffix = "", QObject* parent = 0);
|
||||||
|
std::map<std::string, bool> m_modes;
|
||||||
|
std::string suffix;
|
||||||
|
int rooms;
|
||||||
|
|
||||||
|
void addAutoJoinChannel(const std::string &channel) {
|
||||||
|
m_autoJoin.push_back(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeAutoJoinChannel(const std::string &channel) {
|
||||||
|
m_autoJoin.remove(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setIdentify(const std::string &identify) {
|
||||||
|
m_identify = identify;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string &getIdentify() {
|
||||||
|
return m_identify;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool correctNickname(std::string &nickname);
|
||||||
|
|
||||||
|
void on_joined(IrcMessage *message);
|
||||||
|
void on_parted(IrcMessage *message);
|
||||||
|
void on_quit(IrcMessage *message);
|
||||||
|
void on_nickChanged(IrcMessage *message);
|
||||||
|
void on_modeChanged(IrcMessage *message);
|
||||||
|
void on_topicChanged(IrcMessage *message);
|
||||||
|
void on_messageReceived(IrcMessage *message);
|
||||||
|
void on_numericMessageReceived(IrcMessage *message);
|
||||||
|
|
||||||
|
protected Q_SLOTS:
|
||||||
|
void on_connected();
|
||||||
|
void on_disconnected();
|
||||||
|
|
||||||
|
void onMessageReceived(IrcMessage* message);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
NetworkPlugin *np;
|
||||||
|
std::string user;
|
||||||
|
std::string m_identify;
|
||||||
|
std::list<std::string> m_autoJoin;
|
||||||
|
std::string m_topicData;
|
||||||
|
};
|
||||||
|
|
||||||
|
//class MyIrcBuffer : public Irc::Buffer
|
||||||
|
//{
|
||||||
|
// Q_OBJECT
|
||||||
|
|
||||||
|
//public:
|
||||||
|
// MyIrcBuffer(const QString& receiver, const std::string &user, NetworkPlugin *np, const std::string &suffix, Irc::Session* parent);
|
||||||
|
// NetworkPlugin *np;
|
||||||
|
// std::string user;
|
||||||
|
// MyIrcSession *p;
|
||||||
|
// std::string m_topicData;
|
||||||
|
// std::string suffix;
|
||||||
|
|
||||||
|
//protected Q_SLOTS:
|
||||||
|
// void on_receiverChanged(const QString& receiver);
|
||||||
|
// void on_joined(const QString& origin);
|
||||||
|
// void on_parted(const QString& origin, const QString& message);
|
||||||
|
// void on_quit(const QString& origin, const QString& message);
|
||||||
|
// void on_nickChanged(const QString& origin, const QString& nick);
|
||||||
|
// void on_modeChanged(const QString& origin, const QString& mode, const QString& args);
|
||||||
|
// void on_topicChanged(const QString& origin, const QString& topic);
|
||||||
|
// void on_invited(const QString& origin, const QString& receiver, const QString& channel);
|
||||||
|
// void on_kicked(const QString& origin, const QString& nick, const QString& message);
|
||||||
|
// void on_messageReceived(const QString& origin, const QString& message, Irc::Buffer::MessageFlags flags);
|
||||||
|
// void on_noticeReceived(const QString& origin, const QString& notice, Irc::Buffer::MessageFlags flags);
|
||||||
|
// void on_ctcpRequestReceived(const QString& origin, const QString& request, Irc::Buffer::MessageFlags flags);
|
||||||
|
// void on_ctcpReplyReceived(const QString& origin, const QString& reply, Irc::Buffer::MessageFlags flags);
|
||||||
|
// void on_ctcpActionReceived(const QString& origin, const QString& action, Irc::Buffer::MessageFlags flags);
|
||||||
|
// void on_numericMessageReceived(const QString& origin, uint code, const QStringList& params);
|
||||||
|
// void on_unknownMessageReceived(const QString& origin, const QStringList& params);
|
||||||
|
|
||||||
|
// bool correctNickname(std::string &nickname);
|
||||||
|
//};
|
||||||
|
|
||||||
|
#endif // SESSION_H
|
128
backends/libcommuni/singleircnetworkplugin.cpp
Normal file
128
backends/libcommuni/singleircnetworkplugin.cpp
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
#include "singleircnetworkplugin.h"
|
||||||
|
#include "log4cxx/logger.h"
|
||||||
|
#include <IrcCommand>
|
||||||
|
#include <IrcMessage>
|
||||||
|
|
||||||
|
using namespace log4cxx;
|
||||||
|
|
||||||
|
static LoggerPtr logger = log4cxx::Logger::getLogger("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);
|
||||||
|
connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData()));
|
||||||
|
|
||||||
|
if (config->getUnregistered().find("service.irc_identify") != config->getUnregistered().end()) {
|
||||||
|
m_identify = config->getUnregistered().find("service.irc_identify")->second;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_identify = "NickServ identify $name $password";
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG4CXX_INFO(logger, "SingleIRCNetworkPlugin for server " << m_server << " initialized.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleIRCNetworkPlugin::readData() {
|
||||||
|
size_t availableBytes = m_socket->bytesAvailable();
|
||||||
|
if (availableBytes == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string d = std::string(m_socket->readAll().data(), availableBytes);
|
||||||
|
handleDataRead(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleIRCNetworkPlugin::sendData(const std::string &string) {
|
||||||
|
m_socket->write(string.c_str(), string.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleIRCNetworkPlugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
|
||||||
|
// legacy name is users nickname
|
||||||
|
if (m_sessions[user] != NULL) {
|
||||||
|
LOG4CXX_WARN(logger, user << ": Already logged in.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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->setPort(6667);
|
||||||
|
|
||||||
|
std::string identify = m_identify;
|
||||||
|
boost::replace_all(identify, "$password", password);
|
||||||
|
boost::replace_all(identify, "$name", legacyName);
|
||||||
|
session->setIdentify(identify);
|
||||||
|
|
||||||
|
session->open();
|
||||||
|
|
||||||
|
m_sessions[user] = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleIRCNetworkPlugin::handleLogoutRequest(const std::string &user, const std::string &legacyName) {
|
||||||
|
if (m_sessions[user] == NULL) {
|
||||||
|
LOG4CXX_WARN(logger, user << ": Already disconnected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG4CXX_INFO(logger, user << ": Disconnecting.");
|
||||||
|
|
||||||
|
m_sessions[user]->close();
|
||||||
|
m_sessions[user]->deleteLater();
|
||||||
|
m_sessions.erase(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleIRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &/*xhtml*/) {
|
||||||
|
if (m_sessions[user] == NULL) {
|
||||||
|
LOG4CXX_WARN(logger, user << ": Message received for unconnected user");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle PMs
|
||||||
|
std::string r = legacyName;
|
||||||
|
if (legacyName.find("/") == std::string::npos) {
|
||||||
|
r = legacyName.substr(0, r.find("@"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
r = legacyName.substr(legacyName.find("/") + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG4CXX_INFO(logger, user << ": Forwarding message to " << r);
|
||||||
|
m_sessions[user]->sendCommand(IrcCommand::createMessage(QString::fromStdString(r), QString::fromStdString(message)));
|
||||||
|
|
||||||
|
if (r.find("#") == 0) {
|
||||||
|
handleMessage(user, legacyName, message, m_sessions[user]->nickName().toStdString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleIRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) {
|
||||||
|
if (m_sessions[user] == NULL) {
|
||||||
|
LOG4CXX_WARN(logger, user << ": Join room requested for unconnected user");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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]->rooms += 1;
|
||||||
|
|
||||||
|
// update nickname, because we have nickname per session, no nickname per room.
|
||||||
|
handleRoomNicknameChanged(user, room, m_sessions[user]->userName().toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleIRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std::string &room) {
|
||||||
|
std::string r = room;
|
||||||
|
std::string u = user;
|
||||||
|
|
||||||
|
if (m_sessions[u] == NULL) {
|
||||||
|
LOG4CXX_WARN(logger, user << ": Leave room requested for unconnected user");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG4CXX_INFO(logger, user << ": Leaving " << room);
|
||||||
|
m_sessions[u]->sendCommand(IrcCommand::createPart(QString::fromStdString(r)));
|
||||||
|
m_sessions[u]->removeAutoJoinChannel(r);
|
||||||
|
m_sessions[u]->rooms -= 1;
|
||||||
|
}
|
40
backends/libcommuni/singleircnetworkplugin.h
Normal file
40
backends/libcommuni/singleircnetworkplugin.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "transport/config.h"
|
||||||
|
#include "transport/networkplugin.h"
|
||||||
|
#include "session.h"
|
||||||
|
#include <QtCore>
|
||||||
|
#include <QtNetwork>
|
||||||
|
#include "Swiften/EventLoop/Qt/QtEventLoop.h"
|
||||||
|
#include "ircnetworkplugin.h"
|
||||||
|
|
||||||
|
|
||||||
|
class SingleIRCNetworkPlugin : public QObject, public NetworkPlugin {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
SingleIRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port);
|
||||||
|
|
||||||
|
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password);
|
||||||
|
|
||||||
|
void handleLogoutRequest(const std::string &user, const std::string &legacyName);
|
||||||
|
|
||||||
|
void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &/*xhtml*/);
|
||||||
|
|
||||||
|
void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password);
|
||||||
|
|
||||||
|
void handleLeaveRoomRequest(const std::string &user, const std::string &room);
|
||||||
|
|
||||||
|
std::map<std::string, MyIrcSession *> m_sessions;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void readData();
|
||||||
|
void sendData(const std::string &string);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Config *config;
|
||||||
|
QTcpSocket *m_socket;
|
||||||
|
std::string m_server;
|
||||||
|
std::string m_identify;
|
||||||
|
};
|
|
@ -1,10 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 2.6)
|
|
||||||
FILE(GLOB SRC *.cpp)
|
|
||||||
FILE(GLOB HEADERS *.h)
|
|
||||||
QT4_WRAP_CPP(SRC ${HEADERS})
|
|
||||||
ADD_EXECUTABLE(spectrum2_libircclient-qt_backend ${SRC})
|
|
||||||
|
|
||||||
target_link_libraries(spectrum2_libircclient-qt_backend ${IRC_LIBRARY} ${QT_LIBRARIES} transport-plugin transport pthread)
|
|
||||||
|
|
||||||
INSTALL(TARGETS spectrum2_libircclient-qt_backend RUNTIME DESTINATION bin)
|
|
||||||
|
|
|
@ -1,232 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com
|
|
||||||
*
|
|
||||||
* This example is free, and not covered by LGPL license. There is no
|
|
||||||
* restriction applied to their modification, redistribution, using and so on.
|
|
||||||
* You can study them, modify them, use them in your own program - either
|
|
||||||
* completely or partially. By using it you may give me some credits in your
|
|
||||||
* program, but you don't have to.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "session.h"
|
|
||||||
#include <QtCore>
|
|
||||||
#include <iostream>
|
|
||||||
#include "Swiften/Elements/StatusShow.h"
|
|
||||||
|
|
||||||
MyIrcSession::MyIrcSession(const std::string &user, NetworkPlugin *np, const std::string &suffix, QObject* parent) : Irc::Session(parent)
|
|
||||||
{
|
|
||||||
this->np = np;
|
|
||||||
this->user = user;
|
|
||||||
this->suffix = suffix;
|
|
||||||
rooms = 0;
|
|
||||||
connect(this, SIGNAL(disconnected()), SLOT(on_disconnected()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyIrcSession::on_connected(){
|
|
||||||
std::cout << "connected:\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyIrcSession::on_disconnected()
|
|
||||||
{
|
|
||||||
std::cout << "disconnected:\n";
|
|
||||||
if (suffix.empty())
|
|
||||||
np->handleDisconnected(user, 0, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyIrcSession::on_bufferAdded(Irc::Buffer* buffer)
|
|
||||||
{
|
|
||||||
qDebug() << "buffer added:" << buffer->receiver();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyIrcSession::on_bufferRemoved(Irc::Buffer* buffer)
|
|
||||||
{
|
|
||||||
qDebug() << "buffer removed:" << buffer->receiver();
|
|
||||||
}
|
|
||||||
|
|
||||||
Irc::Buffer* MyIrcSession::createBuffer(const QString& receiver)
|
|
||||||
{
|
|
||||||
return new MyIrcBuffer(receiver, user, np, suffix, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
MyIrcBuffer::MyIrcBuffer(const QString& receiver, const std::string &user, NetworkPlugin *np, const std::string &suffix, Irc::Session* parent)
|
|
||||||
: Irc::Buffer(receiver, parent)
|
|
||||||
{
|
|
||||||
this->np = np;
|
|
||||||
this->user = user;
|
|
||||||
this->suffix = suffix;
|
|
||||||
p = (MyIrcSession *) parent;
|
|
||||||
connect(this, SIGNAL(receiverChanged(QString)), SLOT(on_receiverChanged(QString)));
|
|
||||||
connect(this, SIGNAL(joined(QString)), SLOT(on_joined(QString)));
|
|
||||||
connect(this, SIGNAL(parted(QString, QString)), SLOT(on_parted(QString, QString)));
|
|
||||||
connect(this, SIGNAL(quit(QString, QString)), SLOT(on_quit(QString, QString)));
|
|
||||||
connect(this, SIGNAL(nickChanged(QString, QString)), SLOT(on_nickChanged(QString, QString)));
|
|
||||||
connect(this, SIGNAL(modeChanged(QString, QString, QString)), SLOT(on_modeChanged(QString, QString, QString)));
|
|
||||||
connect(this, SIGNAL(topicChanged(QString, QString)), SLOT(on_topicChanged(QString, QString)));
|
|
||||||
connect(this, SIGNAL(invited(QString, QString, QString)), SLOT(on_invited(QString, QString, QString)));
|
|
||||||
connect(this, SIGNAL(kicked(QString, QString, QString)), SLOT(on_kicked(QString, QString, QString)));
|
|
||||||
connect(this, SIGNAL(messageReceived(QString, QString, Irc::Buffer::MessageFlags)),
|
|
||||||
SLOT(on_messageReceived(QString, QString, Irc::Buffer::MessageFlags)));
|
|
||||||
connect(this, SIGNAL(noticeReceived(QString, QString, Irc::Buffer::MessageFlags)),
|
|
||||||
SLOT(on_noticeReceived(QString, QString, Irc::Buffer::MessageFlags)));
|
|
||||||
connect(this, SIGNAL(ctcpRequestReceived(QString, QString, Irc::Buffer::MessageFlags)),
|
|
||||||
SLOT(on_ctcpRequestReceived(QString, QString, Irc::Buffer::MessageFlags)));
|
|
||||||
connect(this, SIGNAL(ctcpReplyReceived(QString, QString, Irc::Buffer::MessageFlags)),
|
|
||||||
SLOT(on_ctcpReplyReceived(QString, QString, Irc::Buffer::MessageFlags)));
|
|
||||||
connect(this, SIGNAL(ctcpActionReceived(QString, QString, Irc::Buffer::MessageFlags)),
|
|
||||||
SLOT(on_ctcpActionReceived(QString, QString, Irc::Buffer::MessageFlags)));
|
|
||||||
connect(this, SIGNAL(numericMessageReceived(QString, uint, QStringList)), SLOT(on_numericMessageReceived(QString, uint, QStringList)));
|
|
||||||
connect(this, SIGNAL(unknownMessageReceived(QString, QStringList)), SLOT(on_unknownMessageReceived(QString, QStringList)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyIrcBuffer::on_receiverChanged(const QString& receiver)
|
|
||||||
{
|
|
||||||
qDebug() << "receiver changed:" << receiver;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MyIrcBuffer::correctNickname(std::string &nickname) {
|
|
||||||
bool flags = 0;
|
|
||||||
switch(nickname.at(0)) {
|
|
||||||
case '@': nickname = nickname.substr(1); flags = 1; break;
|
|
||||||
case '+': nickname = nickname.substr(1); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
return flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyIrcBuffer::on_joined(const QString& origin) {
|
|
||||||
qDebug() << "joined:" << receiver() << origin;
|
|
||||||
bool flags = 0;
|
|
||||||
std::string nickname = origin.toStdString();
|
|
||||||
flags = correctNickname(nickname);
|
|
||||||
np->handleParticipantChanged(user, origin.toStdString(), receiver().toStdString() + suffix, (int) flags, pbnetwork::STATUS_ONLINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyIrcBuffer::on_parted(const QString& origin, const QString& message) {
|
|
||||||
qDebug() << "parted:" << receiver() << origin << message;
|
|
||||||
bool flags = 0;
|
|
||||||
std::string nickname = origin.toStdString();
|
|
||||||
flags = correctNickname(nickname);
|
|
||||||
np->handleParticipantChanged(user, nickname, receiver().toStdString() + suffix,(int) flags, pbnetwork::STATUS_NONE, message.toStdString());
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyIrcBuffer::on_quit(const QString& origin, const QString& message)
|
|
||||||
{
|
|
||||||
qDebug() << "quit:" << receiver() << origin << message;
|
|
||||||
on_parted(origin, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyIrcBuffer::on_nickChanged(const QString& origin, const QString& nick) {
|
|
||||||
qDebug() << "nick changed:" << receiver() << origin << nick;
|
|
||||||
std::string nickname = origin.toStdString();
|
|
||||||
bool flags = p->m_modes[receiver().toStdString() + nickname];
|
|
||||||
// std::cout << receiver().toStdString() + nickname << " " << flags << "\n";
|
|
||||||
np->handleParticipantChanged(user, nickname, receiver().toStdString() + suffix,(int) flags, pbnetwork::STATUS_ONLINE, "", nick.toStdString());
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyIrcBuffer::on_modeChanged(const QString& origin, const QString& mode, const QString& args) {
|
|
||||||
// mode changed: "#testik" "HanzZ" "+o" "hanzz_k"
|
|
||||||
qDebug() << "mode changed:" << receiver() << origin << mode << args;
|
|
||||||
std::string nickname = args.toStdString();
|
|
||||||
if (nickname.empty())
|
|
||||||
return;
|
|
||||||
if (mode == "+o") {
|
|
||||||
p->m_modes[receiver().toStdString() + nickname] = 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
p->m_modes[receiver().toStdString() + nickname] = 0;
|
|
||||||
}
|
|
||||||
bool flags = p->m_modes[receiver().toStdString() + nickname];
|
|
||||||
np->handleParticipantChanged(user, nickname, receiver().toStdString() + suffix,(int) flags, pbnetwork::STATUS_ONLINE, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyIrcBuffer::on_topicChanged(const QString& origin, const QString& topic) {
|
|
||||||
//topic changed: "#testik" "HanzZ" "test"
|
|
||||||
qDebug() << "topic changed:" << receiver() << origin << topic;
|
|
||||||
np->handleSubject(user, receiver().toStdString() + suffix, topic.toStdString(), origin.toStdString());
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyIrcBuffer::on_invited(const QString& origin, const QString& receiver, const QString& channel)
|
|
||||||
{
|
|
||||||
qDebug() << "invited:" << Irc::Buffer::receiver() << origin << receiver << channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyIrcBuffer::on_kicked(const QString& origin, const QString& nick, const QString& message)
|
|
||||||
{
|
|
||||||
qDebug() << "kicked:" << receiver() << origin << nick << message;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyIrcBuffer::on_messageReceived(const QString& origin, const QString& message, Irc::Buffer::MessageFlags flags) {
|
|
||||||
qDebug() << "message received:" << receiver() << origin << message << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)");
|
|
||||||
if (!receiver().startsWith("#") && (flags & Irc::Buffer::EchoFlag))
|
|
||||||
return;
|
|
||||||
std::string r = receiver().toStdString();
|
|
||||||
// if (!suffix.empty()) {
|
|
||||||
// r = receiver().replace('@', '%').toStdString();
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (r.find("#") == 0) {
|
|
||||||
np->handleMessage(user, r + suffix, message.toStdString(), origin.toStdString());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
np->handleMessage(user, r + suffix, message.toStdString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyIrcBuffer::on_noticeReceived(const QString& origin, const QString& notice, Irc::Buffer::MessageFlags flags)
|
|
||||||
{
|
|
||||||
qDebug() << "notice received:" << receiver() << origin << notice
|
|
||||||
<< (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyIrcBuffer::on_ctcpRequestReceived(const QString& origin, const QString& request, Irc::Buffer::MessageFlags flags)
|
|
||||||
{
|
|
||||||
qDebug() << "ctcp request received:" << receiver() << origin << request
|
|
||||||
<< (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyIrcBuffer::on_ctcpReplyReceived(const QString& origin, const QString& reply, Irc::Buffer::MessageFlags flags)
|
|
||||||
{
|
|
||||||
qDebug() << "ctcp reply received:" << receiver() << origin << reply
|
|
||||||
<< (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyIrcBuffer::on_ctcpActionReceived(const QString& origin, const QString& action, Irc::Buffer::MessageFlags flags)
|
|
||||||
{
|
|
||||||
qDebug() << "ctcp action received:" << receiver() << origin << action
|
|
||||||
<< (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyIrcBuffer::on_numericMessageReceived(const QString& origin, uint code, const QStringList& params)
|
|
||||||
{
|
|
||||||
switch (code) {
|
|
||||||
case 251:
|
|
||||||
if (suffix.empty())
|
|
||||||
np->handleConnected(user);
|
|
||||||
break;
|
|
||||||
case 332:
|
|
||||||
m_topicData = params.value(2).toStdString();
|
|
||||||
break;
|
|
||||||
case 333:
|
|
||||||
np->handleSubject(user, params.value(1).toStdString() + suffix, m_topicData, params.value(2).toStdString());
|
|
||||||
break;
|
|
||||||
case 353:
|
|
||||||
QString channel = params.value(2);
|
|
||||||
QStringList members = params.value(3).split(" ");
|
|
||||||
|
|
||||||
for (int i = 0; i < members.size(); i++) {
|
|
||||||
bool flags = 0;
|
|
||||||
std::string nickname = members.at(i).toStdString();
|
|
||||||
flags = correctNickname(nickname);
|
|
||||||
p->m_modes[channel.toStdString() + nickname] = flags;
|
|
||||||
std::cout << channel.toStdString() + suffix << " " << flags << "\n";
|
|
||||||
np->handleParticipantChanged(user, nickname, channel.toStdString() + suffix,(int) flags, pbnetwork::STATUS_ONLINE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
qDebug() << "numeric message received:" << receiver() << origin << code << params;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyIrcBuffer::on_unknownMessageReceived(const QString& origin, const QStringList& params)
|
|
||||||
{
|
|
||||||
qDebug() << "unknown message received:" << receiver() << origin << params;
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com
|
|
||||||
*
|
|
||||||
* This example is free, and not covered by LGPL license. There is no
|
|
||||||
* restriction applied to their modification, redistribution, using and so on.
|
|
||||||
* You can study them, modify them, use them in your own program - either
|
|
||||||
* completely or partially. By using it you may give me some credits in your
|
|
||||||
* program, but you don't have to.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SESSION_H
|
|
||||||
#define SESSION_H
|
|
||||||
|
|
||||||
#include <IrcSession>
|
|
||||||
#include <IrcBuffer>
|
|
||||||
#include <transport/networkplugin.h>
|
|
||||||
|
|
||||||
using namespace Transport;
|
|
||||||
|
|
||||||
class MyIrcSession : public Irc::Session
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
MyIrcSession(const std::string &user, NetworkPlugin *np, const std::string &suffix = "", QObject* parent = 0);
|
|
||||||
std::map<std::string, bool> m_modes;
|
|
||||||
std::string suffix;
|
|
||||||
int rooms;
|
|
||||||
|
|
||||||
protected Q_SLOTS:
|
|
||||||
void on_connected();
|
|
||||||
void on_disconnected();
|
|
||||||
|
|
||||||
void on_bufferAdded(Irc::Buffer* buffer);
|
|
||||||
void on_bufferRemoved(Irc::Buffer* buffer);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
NetworkPlugin *np;
|
|
||||||
std::string user;
|
|
||||||
|
|
||||||
virtual Irc::Buffer* createBuffer(const QString& receiver);
|
|
||||||
};
|
|
||||||
|
|
||||||
class MyIrcBuffer : public Irc::Buffer
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
MyIrcBuffer(const QString& receiver, const std::string &user, NetworkPlugin *np, const std::string &suffix, Irc::Session* parent);
|
|
||||||
NetworkPlugin *np;
|
|
||||||
std::string user;
|
|
||||||
MyIrcSession *p;
|
|
||||||
std::string m_topicData;
|
|
||||||
std::string suffix;
|
|
||||||
|
|
||||||
protected Q_SLOTS:
|
|
||||||
void on_receiverChanged(const QString& receiver);
|
|
||||||
void on_joined(const QString& origin);
|
|
||||||
void on_parted(const QString& origin, const QString& message);
|
|
||||||
void on_quit(const QString& origin, const QString& message);
|
|
||||||
void on_nickChanged(const QString& origin, const QString& nick);
|
|
||||||
void on_modeChanged(const QString& origin, const QString& mode, const QString& args);
|
|
||||||
void on_topicChanged(const QString& origin, const QString& topic);
|
|
||||||
void on_invited(const QString& origin, const QString& receiver, const QString& channel);
|
|
||||||
void on_kicked(const QString& origin, const QString& nick, const QString& message);
|
|
||||||
void on_messageReceived(const QString& origin, const QString& message, Irc::Buffer::MessageFlags flags);
|
|
||||||
void on_noticeReceived(const QString& origin, const QString& notice, Irc::Buffer::MessageFlags flags);
|
|
||||||
void on_ctcpRequestReceived(const QString& origin, const QString& request, Irc::Buffer::MessageFlags flags);
|
|
||||||
void on_ctcpReplyReceived(const QString& origin, const QString& reply, Irc::Buffer::MessageFlags flags);
|
|
||||||
void on_ctcpActionReceived(const QString& origin, const QString& action, Irc::Buffer::MessageFlags flags);
|
|
||||||
void on_numericMessageReceived(const QString& origin, uint code, const QStringList& params);
|
|
||||||
void on_unknownMessageReceived(const QString& origin, const QStringList& params);
|
|
||||||
|
|
||||||
bool correctNickname(std::string &nickname);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // SESSION_H
|
|
|
@ -69,6 +69,20 @@ class SpectrumNetworkPlugin;
|
||||||
GKeyFile *keyfile;
|
GKeyFile *keyfile;
|
||||||
SpectrumNetworkPlugin *np;
|
SpectrumNetworkPlugin *np;
|
||||||
|
|
||||||
|
std::string replaceAll(
|
||||||
|
std::string result,
|
||||||
|
const std::string& replaceWhat,
|
||||||
|
const std::string& replaceWithWhat)
|
||||||
|
{
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
const int pos = result.find(replaceWhat);
|
||||||
|
if (pos==-1) break;
|
||||||
|
result.replace(pos,replaceWhat.size(),replaceWithWhat);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static std::string KEYFILE_STRING(const std::string &cat, const std::string &key, const std::string &def = "") {
|
static std::string KEYFILE_STRING(const std::string &cat, const std::string &key, const std::string &def = "") {
|
||||||
gchar *str = g_key_file_get_string(keyfile, cat.c_str(), key.c_str(), 0);
|
gchar *str = g_key_file_get_string(keyfile, cat.c_str(), key.c_str(), 0);
|
||||||
if (!str) {
|
if (!str) {
|
||||||
|
@ -83,6 +97,11 @@ static std::string KEYFILE_STRING(const std::string &cat, const std::string &key
|
||||||
ret.erase(ret.end() - 1);
|
ret.erase(ret.end() - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret.find("$jid") != std::string::npos) {
|
||||||
|
std::string jid = KEYFILE_STRING("service", "jid");
|
||||||
|
ret = replaceAll(ret, "$jid", jid);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -523,6 +542,10 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
|
||||||
while (keys && keys[i] != NULL) {
|
while (keys && keys[i] != NULL) {
|
||||||
std::string key = keys[i];
|
std::string key = keys[i];
|
||||||
|
|
||||||
|
if (key == "fb_api_key" || key == "fb_api_secret") {
|
||||||
|
purple_account_set_bool(account, "auth_fb", TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
PurplePlugin *plugin = purple_find_prpl(purple_account_get_protocol_id(account));
|
PurplePlugin *plugin = purple_find_prpl(purple_account_get_protocol_id(account));
|
||||||
PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
|
PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
@ -570,11 +593,13 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
|
||||||
getProtocolAndName(legacyName, name, protocol);
|
getProtocolAndName(legacyName, name, protocol);
|
||||||
|
|
||||||
if (password.empty()) {
|
if (password.empty()) {
|
||||||
|
LOG4CXX_INFO(logger, name.c_str() << ": Empty password");
|
||||||
np->handleDisconnected(user, 0, "Empty password.");
|
np->handleDisconnected(user, 0, "Empty password.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!purple_find_prpl(protocol.c_str())) {
|
if (!purple_find_prpl(protocol.c_str())) {
|
||||||
|
LOG4CXX_INFO(logger, name.c_str() << ": Invalid protocol '" << protocol << "'");
|
||||||
np->handleDisconnected(user, 0, "Invalid protocol " + protocol);
|
np->handleDisconnected(user, 0, "Invalid protocol " + protocol);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1205,6 +1230,11 @@ static gboolean disconnectMe(void *data) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean pingTimeout(void *data) {
|
||||||
|
np->checkPing();
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void connection_report_disconnect(PurpleConnection *gc, PurpleConnectionError reason, const char *text){
|
static void connection_report_disconnect(PurpleConnection *gc, PurpleConnectionError reason, const char *text){
|
||||||
PurpleAccount *account = purple_connection_get_account(gc);
|
PurpleAccount *account = purple_connection_get_account(gc);
|
||||||
np->handleDisconnected(np->m_accounts[account], (int) reason, text ? text : "");
|
np->handleDisconnected(np->m_accounts[account], (int) reason, text ? text : "");
|
||||||
|
@ -1550,11 +1580,78 @@ static void transport_core_ui_init(void)
|
||||||
// #endif
|
// #endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***** Core Ui Ops *****/
|
||||||
|
static void
|
||||||
|
spectrum_glib_log_handler(const gchar *domain,
|
||||||
|
GLogLevelFlags flags,
|
||||||
|
const gchar *message,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
const char *level;
|
||||||
|
char *new_msg = NULL;
|
||||||
|
char *new_domain = NULL;
|
||||||
|
|
||||||
|
if ((flags & G_LOG_LEVEL_ERROR) == G_LOG_LEVEL_ERROR)
|
||||||
|
level = "ERROR";
|
||||||
|
else if ((flags & G_LOG_LEVEL_CRITICAL) == G_LOG_LEVEL_CRITICAL)
|
||||||
|
level = "CRITICAL";
|
||||||
|
else if ((flags & G_LOG_LEVEL_WARNING) == G_LOG_LEVEL_WARNING)
|
||||||
|
level = "WARNING";
|
||||||
|
else if ((flags & G_LOG_LEVEL_MESSAGE) == G_LOG_LEVEL_MESSAGE)
|
||||||
|
level = "MESSAGE";
|
||||||
|
else if ((flags & G_LOG_LEVEL_INFO) == G_LOG_LEVEL_INFO)
|
||||||
|
level = "INFO";
|
||||||
|
else if ((flags & G_LOG_LEVEL_DEBUG) == G_LOG_LEVEL_DEBUG)
|
||||||
|
level = "DEBUG";
|
||||||
|
else {
|
||||||
|
LOG4CXX_ERROR(logger, "Unknown glib logging level in " << (guint)flags);
|
||||||
|
level = "UNKNOWN"; /* This will never happen. */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message != NULL)
|
||||||
|
new_msg = purple_utf8_try_convert(message);
|
||||||
|
|
||||||
|
if (domain != NULL)
|
||||||
|
new_domain = purple_utf8_try_convert(domain);
|
||||||
|
|
||||||
|
if (new_msg != NULL) {
|
||||||
|
std::string area("glib");
|
||||||
|
area.push_back('/');
|
||||||
|
area.append(level);
|
||||||
|
|
||||||
|
std::string message(new_domain ? new_domain : "g_log");
|
||||||
|
message.push_back(' ');
|
||||||
|
message.append(new_msg);
|
||||||
|
|
||||||
|
LOG4CXX_ERROR(logger, message);
|
||||||
|
g_free(new_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(new_domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
debug_init(void)
|
||||||
|
{
|
||||||
|
#define REGISTER_G_LOG_HANDLER(name) \
|
||||||
|
g_log_set_handler((name), \
|
||||||
|
(GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL \
|
||||||
|
| G_LOG_FLAG_RECURSION), \
|
||||||
|
spectrum_glib_log_handler, NULL)
|
||||||
|
|
||||||
|
REGISTER_G_LOG_HANDLER(NULL);
|
||||||
|
REGISTER_G_LOG_HANDLER("GLib");
|
||||||
|
REGISTER_G_LOG_HANDLER("GModule");
|
||||||
|
REGISTER_G_LOG_HANDLER("GLib-GObject");
|
||||||
|
REGISTER_G_LOG_HANDLER("GThread");
|
||||||
|
|
||||||
|
#undef REGISTER_G_LOD_HANDLER
|
||||||
|
}
|
||||||
|
|
||||||
static PurpleCoreUiOps coreUiOps =
|
static PurpleCoreUiOps coreUiOps =
|
||||||
{
|
{
|
||||||
NULL,
|
NULL,
|
||||||
// debug_init,
|
debug_init,
|
||||||
NULL,
|
|
||||||
transport_core_ui_init,
|
transport_core_ui_init,
|
||||||
NULL,
|
NULL,
|
||||||
spectrum_ui_get_info,
|
spectrum_ui_get_info,
|
||||||
|
@ -1852,7 +1949,7 @@ int main(int argc, char **argv) {
|
||||||
p.load(istream);
|
p.load(istream);
|
||||||
LogString pid, jid;
|
LogString pid, jid;
|
||||||
log4cxx::helpers::Transcoder::decode(stringOf(getpid()), pid);
|
log4cxx::helpers::Transcoder::decode(stringOf(getpid()), pid);
|
||||||
log4cxx::helpers::Transcoder::decode(KEYFILE_STRING("service", "service.jid"), jid);
|
log4cxx::helpers::Transcoder::decode(KEYFILE_STRING("service", "jid"), jid);
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
p.setProperty(L"pid", pid);
|
p.setProperty(L"pid", pid);
|
||||||
p.setProperty(L"jid", jid);
|
p.setProperty(L"jid", jid);
|
||||||
|
@ -1868,6 +1965,7 @@ int main(int argc, char **argv) {
|
||||||
m_sock = create_socket(host, port);
|
m_sock = create_socket(host, port);
|
||||||
|
|
||||||
purple_input_add(m_sock, PURPLE_INPUT_READ, &transportDataReceived, NULL);
|
purple_input_add(m_sock, PURPLE_INPUT_READ, &transportDataReceived, NULL);
|
||||||
|
purple_timeout_add_seconds(30, pingTimeout, NULL);
|
||||||
|
|
||||||
np = new SpectrumNetworkPlugin(host, port);
|
np = new SpectrumNetworkPlugin(host, port);
|
||||||
bool libev = KEYFILE_STRING("service", "eventloop") == "libev";
|
bool libev = KEYFILE_STRING("service", "eventloop") == "libev";
|
||||||
|
|
10
cmake_modules/CommuniConfig.cmake
Normal file
10
cmake_modules/CommuniConfig.cmake
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
FIND_LIBRARY(IRC_LIBRARY NAMES Communi)
|
||||||
|
FIND_PATH(IRC_INCLUDE_DIR NAMES "ircglobal.h" PATH_SUFFIXES Communi qt4/Communi )
|
||||||
|
|
||||||
|
# message( STATUS ${IRC_LIBRARY})
|
||||||
|
if( IRC_LIBRARY AND IRC_INCLUDE_DIR )
|
||||||
|
message( STATUS "Found libCommuni ${IRC_LIBRARY}, ${IRC_INCLUDE_DIR}")
|
||||||
|
set( IRC_FOUND 1 )
|
||||||
|
else()
|
||||||
|
message( STATUS "Could NOT find libCommuni" )
|
||||||
|
endif()
|
|
@ -1,10 +0,0 @@
|
||||||
FIND_LIBRARY(IRC_LIBRARY NAMES ircclient-qt)
|
|
||||||
FIND_PATH(IRC_INCLUDE_DIR NAMES "ircglobal.h" PATH_SUFFIXES ircclient-qt qt4/ircclient-qt )
|
|
||||||
|
|
||||||
# message( STATUS ${IRC_LIBRARY})
|
|
||||||
if( IRC_LIBRARY AND IRC_INCLUDE_DIR )
|
|
||||||
message( STATUS "Found libircclient-qt: ${IRC_LIBRARY}, ${IRC_INCLUDE_DIR}")
|
|
||||||
set( IRC_FOUND 1 )
|
|
||||||
else()
|
|
||||||
message( STATUS "Could NOT find libircclient-qt" )
|
|
||||||
endif()
|
|
|
@ -1,6 +0,0 @@
|
||||||
ADD_SUBDIRECTORY(server_connect)
|
|
||||||
ADD_SUBDIRECTORY(usermanager)
|
|
||||||
|
|
||||||
if (PROTOBUF_FOUND)
|
|
||||||
ADD_SUBDIRECTORY(external_network_plugin)
|
|
||||||
endif()
|
|
|
@ -1,13 +0,0 @@
|
||||||
FILE(GLOB SRC *.cpp)
|
|
||||||
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pbnetwork_pb2.py"
|
|
||||||
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
|
|
||||||
ARGS --python_out ${CMAKE_CURRENT_BINARY_DIR} pbnetwork.proto
|
|
||||||
COMMENT "Running Py protocol buffer compiler on pbnetwork.proto"
|
|
||||||
VERBATIM )
|
|
||||||
|
|
||||||
ADD_EXECUTABLE(external_network_plugin ${SRC} ${CMAKE_CURRENT_BINARY_DIR}/pbnetwork_pb2.py)
|
|
||||||
|
|
||||||
TARGET_LINK_LIBRARIES(external_network_plugin transport ${SWIFTEN_LIBRARIES})
|
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
#include "transport/config.h"
|
|
||||||
#include "transport/transport.h"
|
|
||||||
#include "transport/usermanager.h"
|
|
||||||
#include "transport/logger.h"
|
|
||||||
#include "transport/sqlite3backend.h"
|
|
||||||
#include "transport/userregistration.h"
|
|
||||||
#include "transport/networkpluginserver.h"
|
|
||||||
#include "Swiften/EventLoop/SimpleEventLoop.h"
|
|
||||||
|
|
||||||
using namespace Transport;
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
Config config;
|
|
||||||
if (!config.load("sample.cfg")) {
|
|
||||||
std::cout << "Can't open sample.cfg configuration file.\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Swift::SimpleEventLoop eventLoop;
|
|
||||||
Component transport(&eventLoop, &config, NULL);
|
|
||||||
Logger logger(&transport);
|
|
||||||
|
|
||||||
SQLite3Backend sql(&config);
|
|
||||||
logger.setStorageBackend(&sql);
|
|
||||||
if (!sql.connect()) {
|
|
||||||
std::cout << "Can't connect to database.\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
UserManager userManager(&transport, &sql);
|
|
||||||
UserRegistration userRegistration(&transport, &userManager, &sql);
|
|
||||||
logger.setUserRegistration(&userRegistration);
|
|
||||||
logger.setUserManager(&userManager);
|
|
||||||
|
|
||||||
NetworkPluginServer plugin(&transport, &config, &userManager);
|
|
||||||
|
|
||||||
transport.connect();
|
|
||||||
eventLoop.run();
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
package pbnetwork;
|
|
||||||
|
|
||||||
message Connected {
|
|
||||||
required string name = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message Disconnected {
|
|
||||||
required string name = 1;
|
|
||||||
required int32 error = 2;
|
|
||||||
optional string message = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message Login {
|
|
||||||
required string protocol = 1;
|
|
||||||
required string legacyName = 2;
|
|
||||||
required string password = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message WrapperMessage {
|
|
||||||
enum Type {
|
|
||||||
TYPE_CONNECTED = 1;
|
|
||||||
TYPE_DISCONNECTED = 2;
|
|
||||||
TYPE_LOGIN = 3;
|
|
||||||
TYPE_LOGOUT = 4;
|
|
||||||
}
|
|
||||||
required Type type = 1;
|
|
||||||
required bytes payload = 2;
|
|
||||||
}
|
|
||||||
;
|
|
|
@ -1,29 +0,0 @@
|
||||||
#! /usr/bin/python
|
|
||||||
|
|
||||||
from pbnetwork_pb2 import *
|
|
||||||
import time
|
|
||||||
import sys
|
|
||||||
import socket
|
|
||||||
import struct
|
|
||||||
|
|
||||||
|
|
||||||
connected = Connected()
|
|
||||||
connected.name = "hanzz.k@gmail.com"
|
|
||||||
|
|
||||||
wrapper = WrapperMessage()
|
|
||||||
wrapper.type = WrapperMessage.TYPE_CONNECTED
|
|
||||||
wrapper.payload = connected.SerializeToString()
|
|
||||||
|
|
||||||
sck = socket.socket()
|
|
||||||
sck.connect(("localhost", 10000))
|
|
||||||
|
|
||||||
message = wrapper.SerializeToString();
|
|
||||||
header = struct.pack(">L", len(message))
|
|
||||||
print [header]
|
|
||||||
sck.send(header + message+header + message);
|
|
||||||
sck.send(header + message);
|
|
||||||
sck.send(header + message);
|
|
||||||
sck.send(header + message);
|
|
||||||
sck.send(header + message);
|
|
||||||
|
|
||||||
print sck.recv(255)
|
|
|
@ -1,6 +0,0 @@
|
||||||
FILE(GLOB SRC *.cpp)
|
|
||||||
|
|
||||||
ADD_EXECUTABLE(transport_server_connect ${SRC})
|
|
||||||
|
|
||||||
TARGET_LINK_LIBRARIES(transport_server_connect transport ${SWIFTEN_LIBRARIES})
|
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
#include "transport/config.h"
|
|
||||||
#include "transport/transport.h"
|
|
||||||
#include "transport/logger.h"
|
|
||||||
#include "Swiften/EventLoop/SimpleEventLoop.h"
|
|
||||||
#include "Swiften/Network/BoostTimerFactory.h"
|
|
||||||
#include "Swiften/Network/BoostIOServiceThread.h"
|
|
||||||
#include "Swiften/Network/BoostNetworkFactories.h"
|
|
||||||
#include "Swiften/Server/UserRegistry.h"
|
|
||||||
#include "Swiften/Server/Server.h"
|
|
||||||
#include "Swiften/Swiften.h"
|
|
||||||
|
|
||||||
using namespace Transport;
|
|
||||||
|
|
||||||
class DummyUserRegistry : public Swift::UserRegistry {
|
|
||||||
public:
|
|
||||||
DummyUserRegistry() {}
|
|
||||||
|
|
||||||
virtual bool isValidUserPassword(const Swift::JID&user, const Swift::SafeByteArray&) const {
|
|
||||||
onPasswordValid(user.toString());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
Swift::logging = true;
|
|
||||||
|
|
||||||
Swift::SimpleEventLoop loop;
|
|
||||||
|
|
||||||
Swift::BoostNetworkFactories *m_factories = new Swift::BoostNetworkFactories(&loop);
|
|
||||||
DummyUserRegistry dummyregistry;
|
|
||||||
Swift::Server server(&loop, m_factories, &dummyregistry, "localhost", 5222);
|
|
||||||
server.start();
|
|
||||||
|
|
||||||
loop.run();
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
[service]
|
|
||||||
jid = icq.localhost
|
|
||||||
password = secret
|
|
||||||
server = 127.0.0.1
|
|
||||||
port = 5222
|
|
||||||
server_mode = 1
|
|
|
@ -1,6 +0,0 @@
|
||||||
FILE(GLOB SRC *.cpp)
|
|
||||||
|
|
||||||
ADD_EXECUTABLE(transport_usermanager ${SRC})
|
|
||||||
|
|
||||||
TARGET_LINK_LIBRARIES(transport_usermanager transport ${SWIFTEN_LIBRARIES})
|
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
#include "transport/config.h"
|
|
||||||
#include "transport/transport.h"
|
|
||||||
#include "transport/usermanager.h"
|
|
||||||
#include "transport/logger.h"
|
|
||||||
#include "transport/sqlite3backend.h"
|
|
||||||
#include "transport/userregistration.h"
|
|
||||||
#include "Swiften/EventLoop/SimpleEventLoop.h"
|
|
||||||
|
|
||||||
using namespace Transport;
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
Config config;
|
|
||||||
if (!config.load("sample.cfg")) {
|
|
||||||
std::cout << "Can't open sample.cfg configuration file.\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Swift::SimpleEventLoop eventLoop;
|
|
||||||
Component transport(&eventLoop, &config, NULL);
|
|
||||||
Logger logger(&transport);
|
|
||||||
|
|
||||||
SQLite3Backend sql(&config);
|
|
||||||
logger.setStorageBackend(&sql);
|
|
||||||
if (!sql.connect()) {
|
|
||||||
std::cout << "Can't connect to database.\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
UserManager userManager(&transport, &sql);
|
|
||||||
UserRegistration userRegistration(&transport, &userManager, &sql);
|
|
||||||
logger.setUserRegistration(&userRegistration);
|
|
||||||
logger.setUserManager(&userManager);
|
|
||||||
|
|
||||||
transport.connect();
|
|
||||||
eventLoop.run();
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
[service]
|
|
||||||
jid = icq.localhost
|
|
||||||
password = secret
|
|
||||||
server = 127.0.0.1
|
|
||||||
port = 8888
|
|
||||||
|
|
||||||
[database]
|
|
||||||
database = test.sql
|
|
||||||
prefix=icq
|
|
14
include/Swiften/Elements/StatsPayload.cpp
Normal file
14
include/Swiften/Elements/StatsPayload.cpp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Jan Kaluza
|
||||||
|
* Licensed under the Simplified BSD license.
|
||||||
|
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Swiften/Elements/StatsPayload.h>
|
||||||
|
|
||||||
|
namespace Swift {
|
||||||
|
|
||||||
|
StatsPayload::StatsPayload() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
67
include/Swiften/Elements/StatsPayload.h
Normal file
67
include/Swiften/Elements/StatsPayload.h
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Jan Kaluza
|
||||||
|
* Licensed under the Simplified BSD license.
|
||||||
|
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <Swiften/Elements/Payload.h>
|
||||||
|
|
||||||
|
namespace Swift {
|
||||||
|
class StatsPayload : public Payload {
|
||||||
|
public:
|
||||||
|
class Item {
|
||||||
|
public:
|
||||||
|
Item(const std::string &name = "", const std::string &units = "", const std::string &value = "") :
|
||||||
|
name(name), units(units), value(value) { }
|
||||||
|
|
||||||
|
void setName(const std::string &name) {
|
||||||
|
this->name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string &getName() const {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setUnits(const std::string &units) {
|
||||||
|
this->units = units;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string &getUnits() const {
|
||||||
|
return units;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setValue(const std::string &value) {
|
||||||
|
this->value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string &getValue() const {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string name;
|
||||||
|
std::string units;
|
||||||
|
std::string value;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<StatsPayload::Item> StatsPayloadItems;
|
||||||
|
|
||||||
|
StatsPayload();
|
||||||
|
|
||||||
|
void addItem(const StatsPayload::Item &item) {
|
||||||
|
items.push_back(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
const StatsPayloadItems &getItems() const {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
StatsPayloadItems items;
|
||||||
|
};
|
||||||
|
}
|
43
include/Swiften/Parser/PayloadParsers/StatsParser.cpp
Normal file
43
include/Swiften/Parser/PayloadParsers/StatsParser.cpp
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Jan Kaluza
|
||||||
|
* Licensed under the Simplified BSD license.
|
||||||
|
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Swiften/Parser/PayloadParsers/StatsParser.h>
|
||||||
|
#include <Swiften/Parser/SerializingParser.h>
|
||||||
|
|
||||||
|
namespace Swift {
|
||||||
|
|
||||||
|
StatsParser::StatsParser() : level_(TopLevel), inItem_(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatsParser::handleStartElement(const std::string& element, const std::string& /*ns*/, const AttributeMap& attributes) {
|
||||||
|
if (level_ == PayloadLevel) {
|
||||||
|
if (element == "stat") {
|
||||||
|
inItem_ = true;
|
||||||
|
|
||||||
|
currentItem_ = StatsPayload::Item();
|
||||||
|
|
||||||
|
currentItem_.setName(attributes.getAttribute("name"));
|
||||||
|
currentItem_.setValue(attributes.getAttribute("value"));
|
||||||
|
currentItem_.setUnits(attributes.getAttribute("units"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++level_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatsParser::handleEndElement(const std::string& element, const std::string& /*ns*/) {
|
||||||
|
--level_;
|
||||||
|
if (level_ == PayloadLevel) {
|
||||||
|
if (inItem_) {
|
||||||
|
getPayloadInternal()->addItem(currentItem_);
|
||||||
|
inItem_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatsParser::handleCharacterData(const std::string& data) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
33
include/Swiften/Parser/PayloadParsers/StatsParser.h
Normal file
33
include/Swiften/Parser/PayloadParsers/StatsParser.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Jan Kaluza
|
||||||
|
* Licensed under the Simplified BSD license.
|
||||||
|
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Swiften/Elements/StatsPayload.h>
|
||||||
|
#include <Swiften/Parser/GenericPayloadParser.h>
|
||||||
|
|
||||||
|
namespace Swift {
|
||||||
|
class SerializingParser;
|
||||||
|
|
||||||
|
class StatsParser : public GenericPayloadParser<StatsPayload> {
|
||||||
|
public:
|
||||||
|
StatsParser();
|
||||||
|
|
||||||
|
virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes);
|
||||||
|
virtual void handleEndElement(const std::string& element, const std::string&);
|
||||||
|
virtual void handleCharacterData(const std::string& data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum Level {
|
||||||
|
TopLevel = 0,
|
||||||
|
PayloadLevel = 1,
|
||||||
|
ItemLevel = 2
|
||||||
|
};
|
||||||
|
int level_;
|
||||||
|
bool inItem_;
|
||||||
|
StatsPayload::Item currentItem_;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Jan Kaluza
|
||||||
|
* Licensed under the Simplified BSD license.
|
||||||
|
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Swiften/Serializer/PayloadSerializers/StatsSerializer.h>
|
||||||
|
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
#include <Swiften/Base/foreach.h>
|
||||||
|
#include <Swiften/Serializer/XML/XMLTextNode.h>
|
||||||
|
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
|
||||||
|
#include <Swiften/Serializer/XML/XMLElement.h>
|
||||||
|
|
||||||
|
namespace Swift {
|
||||||
|
|
||||||
|
StatsSerializer::StatsSerializer() : GenericPayloadSerializer<StatsPayload>() {
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string StatsSerializer::serializePayload(boost::shared_ptr<StatsPayload> stats) const {
|
||||||
|
XMLElement queryElement("query", "http://jabber.org/protocol/stats");
|
||||||
|
foreach(const StatsPayload::Item& item, stats->getItems()) {
|
||||||
|
boost::shared_ptr<XMLElement> statElement(new XMLElement("stat"));
|
||||||
|
statElement->setAttribute("name", item.getName());
|
||||||
|
if (!item.getUnits().empty()) {
|
||||||
|
statElement->setAttribute("units", item.getUnits());
|
||||||
|
}
|
||||||
|
if (!item.getValue().empty()) {
|
||||||
|
statElement->setAttribute("value", item.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
queryElement.addNode(statElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
return queryElement.serialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Jan Kaluza
|
||||||
|
* Licensed under the Simplified BSD license.
|
||||||
|
* See Documentation/Licenses/BSD-simplified.txt for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Swiften/Serializer/GenericPayloadSerializer.h>
|
||||||
|
#include <Swiften/Elements/StatsPayload.h>
|
||||||
|
|
||||||
|
namespace Swift {
|
||||||
|
class StatsSerializer : public GenericPayloadSerializer<StatsPayload> {
|
||||||
|
public:
|
||||||
|
StatsSerializer();
|
||||||
|
|
||||||
|
virtual std::string serializePayload(boost::shared_ptr<StatsPayload>) const;
|
||||||
|
};
|
||||||
|
}
|
|
@ -34,6 +34,7 @@
|
||||||
#define CONFIG_BOOL(PTR, KEY) (*PTR)[KEY].as<bool>()
|
#define CONFIG_BOOL(PTR, KEY) (*PTR)[KEY].as<bool>()
|
||||||
#define CONFIG_LIST(PTR, KEY) (*PTR)[KEY].as<std::list<std::string> >()
|
#define CONFIG_LIST(PTR, KEY) (*PTR)[KEY].as<std::list<std::string> >()
|
||||||
#define CONFIG_VECTOR(PTR, KEY) (*PTR)[KEY].as<std::vector<std::string> >()
|
#define CONFIG_VECTOR(PTR, KEY) (*PTR)[KEY].as<std::vector<std::string> >()
|
||||||
|
#define CONFIG_HAS_KEY(PTR, KEY) (*PTR).hasKey(KEY)
|
||||||
|
|
||||||
namespace Transport {
|
namespace Transport {
|
||||||
|
|
||||||
|
@ -60,9 +61,9 @@ class Config {
|
||||||
/// the parser using opts parameter.
|
/// the parser using opts parameter.
|
||||||
/// \param configfile path to config file
|
/// \param configfile path to config file
|
||||||
/// \param opts extra options which will be recognized by a parser
|
/// \param opts extra options which will be recognized by a parser
|
||||||
bool load(const std::string &configfile, boost::program_options::options_description &opts);
|
bool load(const std::string &configfile, boost::program_options::options_description &opts, const std::string &jid = "");
|
||||||
|
|
||||||
bool load(std::istream &ifs, boost::program_options::options_description &opts);
|
bool load(std::istream &ifs, boost::program_options::options_description &opts, const std::string &jid = "");
|
||||||
|
|
||||||
bool load(std::istream &ifs);
|
bool load(std::istream &ifs);
|
||||||
|
|
||||||
|
@ -71,10 +72,14 @@ class Config {
|
||||||
/// This function loads only config variables needed by libtransport.
|
/// This function loads only config variables needed by libtransport.
|
||||||
/// \see load(const std::string &, boost::program_options::options_description &)
|
/// \see load(const std::string &, boost::program_options::options_description &)
|
||||||
/// \param configfile path to config file
|
/// \param configfile path to config file
|
||||||
bool load(const std::string &configfile);
|
bool load(const std::string &configfile, const std::string &jid = "");
|
||||||
|
|
||||||
bool reload();
|
bool reload();
|
||||||
|
|
||||||
|
bool hasKey(const std::string &key) {
|
||||||
|
return m_variables.find(key) != m_variables.end();
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns value of variable defined by key.
|
/// Returns value of variable defined by key.
|
||||||
|
|
||||||
/// For variables in sections you can use "section.variable" key format.
|
/// For variables in sections you can use "section.variable" key format.
|
||||||
|
|
|
@ -74,6 +74,14 @@ class Conversation {
|
||||||
m_nickname = nickname;
|
m_nickname = nickname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string &getNickname() {
|
||||||
|
return m_nickname;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setJID(const Swift::JID &jid) {
|
||||||
|
m_jid = jid;
|
||||||
|
}
|
||||||
|
|
||||||
/// Sends message to Legacy network.
|
/// Sends message to Legacy network.
|
||||||
|
|
||||||
/// \param message Message.
|
/// \param message Message.
|
||||||
|
@ -112,6 +120,7 @@ class Conversation {
|
||||||
std::string m_nickname;
|
std::string m_nickname;
|
||||||
std::string m_room;
|
std::string m_room;
|
||||||
bool m_muc;
|
bool m_muc;
|
||||||
|
Swift::JID m_jid;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,8 @@ class ConversationManager {
|
||||||
/// \param conv Conversation.
|
/// \param conv Conversation.
|
||||||
void removeConversation(Conversation *conv);
|
void removeConversation(Conversation *conv);
|
||||||
|
|
||||||
|
void resetResources();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleMessageReceived(Swift::Message::ref message);
|
void handleMessageReceived(Swift::Message::ref message);
|
||||||
|
|
||||||
|
|
|
@ -214,7 +214,8 @@ class NetworkPlugin {
|
||||||
virtual void handleExitRequest() { exit(1); }
|
virtual void handleExitRequest() { exit(1); }
|
||||||
void handleDataRead(std::string &data);
|
void handleDataRead(std::string &data);
|
||||||
virtual void sendData(const std::string &string) {}
|
virtual void sendData(const std::string &string) {}
|
||||||
|
|
||||||
|
void checkPing();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleLoginPayload(const std::string &payload);
|
void handleLoginPayload(const std::string &payload);
|
||||||
|
|
|
@ -96,7 +96,7 @@ class NetworkPluginServer {
|
||||||
void handleFTDataPayload(Backend *b ,const std::string &payload);
|
void handleFTDataPayload(Backend *b ,const std::string &payload);
|
||||||
|
|
||||||
void handleUserCreated(User *user);
|
void handleUserCreated(User *user);
|
||||||
void handleRoomJoined(User *user, const std::string &room, const std::string &nickname, const std::string &password);
|
void handleRoomJoined(User *user, const Swift::JID &who, const std::string &room, const std::string &nickname, const std::string &password);
|
||||||
void handleRoomLeft(User *user, const std::string &room);
|
void handleRoomLeft(User *user, const std::string &room);
|
||||||
void handleUserReadyToConnect(User *user);
|
void handleUserReadyToConnect(User *user);
|
||||||
void handleUserPresenceChanged(User *user, Swift::Presence::ref presence);
|
void handleUserPresenceChanged(User *user, Swift::Presence::ref presence);
|
||||||
|
|
|
@ -1,5 +1,25 @@
|
||||||
package pbnetwork;
|
package pbnetwork;
|
||||||
|
|
||||||
|
enum ConnectionError {
|
||||||
|
CONNECTION_ERROR_NETWORK_ERROR = 0;
|
||||||
|
CONNECTION_ERROR_INVALID_USERNAME = 1;
|
||||||
|
CONNECTION_ERROR_AUTHENTICATION_FAILED = 2;
|
||||||
|
CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE = 3;
|
||||||
|
CONNECTION_ERROR_NO_SSL_SUPPORT = 4;
|
||||||
|
CONNECTION_ERROR_ENCRYPTION_ERROR = 5;
|
||||||
|
CONNECTION_ERROR_NAME_IN_USE = 6;
|
||||||
|
CONNECTION_ERROR_INVALID_SETTINGS = 7;
|
||||||
|
CONNECTION_ERROR_CERT_NOT_PROVIDED = 8;
|
||||||
|
CONNECTION_ERROR_CERT_UNTRUSTED = 9;
|
||||||
|
CONNECTION_ERROR_CERT_EXPIRED = 10;
|
||||||
|
CONNECTION_ERROR_CERT_NOT_ACTIVATED = 11;
|
||||||
|
CONNECTION_ERROR_CERT_HOSTNAME_MISMATCH = 12;
|
||||||
|
CONNECTION_ERROR_CERT_FINGERPRINT_MISMATCH = 13;
|
||||||
|
CONNECTION_ERROR_CERT_SELF_SIGNED = 14;
|
||||||
|
CONNECTION_ERROR_CERT_OTHER_ERROR = 15;
|
||||||
|
CONNECTION_ERROR_OTHER_ERROR = 16;
|
||||||
|
}
|
||||||
|
|
||||||
enum StatusType {
|
enum StatusType {
|
||||||
STATUS_ONLINE = 0;
|
STATUS_ONLINE = 0;
|
||||||
STATUS_AWAY = 1;
|
STATUS_AWAY = 1;
|
||||||
|
@ -135,4 +155,4 @@ message WrapperMessage {
|
||||||
required Type type = 1;
|
required Type type = 1;
|
||||||
optional bytes payload = 2;
|
optional bytes payload = 2;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
|
@ -49,6 +49,7 @@ class AddressedRosterRequest : public Swift::GenericRequest<Swift::RosterPayload
|
||||||
/// Manages roster of one XMPP user.
|
/// Manages roster of one XMPP user.
|
||||||
class RosterManager {
|
class RosterManager {
|
||||||
public:
|
public:
|
||||||
|
typedef std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > > BuddiesMap;
|
||||||
/// Creates new RosterManager.
|
/// Creates new RosterManager.
|
||||||
/// \param user User associated with this RosterManager.
|
/// \param user User associated with this RosterManager.
|
||||||
/// \param component Transport instance associated with this roster.
|
/// \param component Transport instance associated with this roster.
|
||||||
|
@ -80,6 +81,10 @@ class RosterManager {
|
||||||
/// \return User
|
/// \return User
|
||||||
User *getUser() { return m_user; }
|
User *getUser() { return m_user; }
|
||||||
|
|
||||||
|
const BuddiesMap &getBuddies() {
|
||||||
|
return m_buddies;
|
||||||
|
}
|
||||||
|
|
||||||
bool isRemoteRosterSupported() {
|
bool isRemoteRosterSupported() {
|
||||||
return m_supportRemoteRoster;
|
return m_supportRemoteRoster;
|
||||||
}
|
}
|
||||||
|
@ -125,6 +130,7 @@ class RosterManager {
|
||||||
Swift::Timer::ref m_RIETimer;
|
Swift::Timer::ref m_RIETimer;
|
||||||
std::list <Swift::SetRosterRequest::ref> m_requests;
|
std::list <Swift::SetRosterRequest::ref> m_requests;
|
||||||
bool m_supportRemoteRoster;
|
bool m_supportRemoteRoster;
|
||||||
|
AddressedRosterRequest::ref m_remoteRosterRequest;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
53
include/transport/statsresponder.h
Normal file
53
include/transport/statsresponder.h
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/**
|
||||||
|
* 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 <vector>
|
||||||
|
#include "Swiften/Swiften.h"
|
||||||
|
#include "Swiften/Queries/SetResponder.h"
|
||||||
|
#include "Swiften/Elements/StatsPayload.h"
|
||||||
|
|
||||||
|
namespace Transport {
|
||||||
|
|
||||||
|
class Component;
|
||||||
|
class UserManager;
|
||||||
|
class NetworkPluginServer;
|
||||||
|
class StorageBackend;
|
||||||
|
|
||||||
|
class StatsResponder : public Swift::Responder<Swift::StatsPayload> {
|
||||||
|
public:
|
||||||
|
StatsResponder(Component *component, UserManager *userManager, NetworkPluginServer *server, StorageBackend *storageBackend);
|
||||||
|
~StatsResponder();
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::StatsPayload> payload);
|
||||||
|
virtual bool handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::StatsPayload> payload);
|
||||||
|
|
||||||
|
unsigned long usedMemory();
|
||||||
|
|
||||||
|
Component *m_component;
|
||||||
|
UserManager *m_userManager;
|
||||||
|
NetworkPluginServer *m_server;
|
||||||
|
StorageBackend *m_storageBackend;
|
||||||
|
time_t m_start;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -111,7 +111,7 @@ class User : public Swift::EntityCapsProvider {
|
||||||
|
|
||||||
boost::signal<void ()> onReadyToConnect;
|
boost::signal<void ()> onReadyToConnect;
|
||||||
boost::signal<void (Swift::Presence::ref presence)> onPresenceChanged;
|
boost::signal<void (Swift::Presence::ref presence)> onPresenceChanged;
|
||||||
boost::signal<void (const std::string &room, const std::string &nickname, const std::string &password)> onRoomJoined;
|
boost::signal<void (const Swift::JID &who, const std::string &room, const std::string &nickname, const std::string &password)> onRoomJoined;
|
||||||
boost::signal<void (const std::string &room)> onRoomLeft;
|
boost::signal<void (const std::string &room)> onRoomLeft;
|
||||||
boost::signal<void ()> onDisconnected;
|
boost::signal<void ()> onDisconnected;
|
||||||
|
|
||||||
|
@ -135,6 +135,7 @@ class User : public Swift::EntityCapsProvider {
|
||||||
time_t m_lastActivity;
|
time_t m_lastActivity;
|
||||||
std::map<Swift::JID, Swift::DiscoInfo::ref> m_legacyCaps;
|
std::map<Swift::JID, Swift::DiscoInfo::ref> m_legacyCaps;
|
||||||
std::vector<boost::shared_ptr<Swift::OutgoingFileTransfer> > m_filetransfers;
|
std::vector<boost::shared_ptr<Swift::OutgoingFileTransfer> > m_filetransfers;
|
||||||
|
int m_resources;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include "Swiften/StringCodecs/Base64.h"
|
||||||
|
|
||||||
namespace Transport {
|
namespace Transport {
|
||||||
|
|
||||||
|
@ -31,6 +32,10 @@ namespace Util {
|
||||||
|
|
||||||
void removeEverythingOlderThan(const std::vector<std::string> &dirs, time_t t);
|
void removeEverythingOlderThan(const std::vector<std::string> &dirs, time_t t);
|
||||||
|
|
||||||
|
std::string encryptPassword(const std::string &password, const std::string &key);
|
||||||
|
|
||||||
|
std::string decryptPassword(std::string &encrypted, const std::string &key);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -553,6 +553,13 @@ void NetworkPlugin::send(const std::string &data) {
|
||||||
sendData(std::string(header, 4) + data);
|
sendData(std::string(header, 4) + data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetworkPlugin::checkPing() {
|
||||||
|
if (m_pingReceived == false) {
|
||||||
|
handleExitRequest();
|
||||||
|
}
|
||||||
|
m_pingReceived = false;
|
||||||
|
}
|
||||||
|
|
||||||
void NetworkPlugin::sendPong() {
|
void NetworkPlugin::sendPong() {
|
||||||
m_pingReceived = true;
|
m_pingReceived = true;
|
||||||
std::string message;
|
std::string message;
|
||||||
|
|
|
@ -13,7 +13,7 @@ INSTALL(TARGETS spectrum2 RUNTIME DESTINATION bin)
|
||||||
INSTALL(FILES
|
INSTALL(FILES
|
||||||
sample2.cfg
|
sample2.cfg
|
||||||
RENAME spectrum.cfg.example
|
RENAME spectrum.cfg.example
|
||||||
DESTINATION /etc/spectrum2
|
DESTINATION /etc/spectrum2/transports
|
||||||
)
|
)
|
||||||
|
|
||||||
INSTALL(FILES
|
INSTALL(FILES
|
||||||
|
|
|
@ -8,9 +8,11 @@
|
||||||
#include "transport/userregistration.h"
|
#include "transport/userregistration.h"
|
||||||
#include "transport/networkpluginserver.h"
|
#include "transport/networkpluginserver.h"
|
||||||
#include "transport/admininterface.h"
|
#include "transport/admininterface.h"
|
||||||
|
#include "transport/statsresponder.h"
|
||||||
#include "transport/util.h"
|
#include "transport/util.h"
|
||||||
#include "Swiften/EventLoop/SimpleEventLoop.h"
|
#include "Swiften/EventLoop/SimpleEventLoop.h"
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
#include "sys/signal.h"
|
#include "sys/signal.h"
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
@ -122,6 +124,7 @@ int main(int argc, char **argv)
|
||||||
boost::program_options::variables_map vm;
|
boost::program_options::variables_map vm;
|
||||||
bool no_daemon = false;
|
bool no_daemon = false;
|
||||||
std::string config_file;
|
std::string config_file;
|
||||||
|
std::string jid;
|
||||||
|
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
|
@ -135,11 +138,14 @@ int main(int argc, char **argv)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
boost::program_options::options_description desc("Usage: spectrum [OPTIONS] <config_file.cfg>\nAllowed options");
|
boost::program_options::options_description desc(std::string("Spectrum version: ") + SPECTRUM_VERSION + "\nUsage: spectrum [OPTIONS] <config_file.cfg>\nAllowed options");
|
||||||
desc.add_options()
|
desc.add_options()
|
||||||
("help,h", "help")
|
("help,h", "help")
|
||||||
("no-daemonize,n", "Do not run spectrum as daemon")
|
("no-daemonize,n", "Do not run spectrum as daemon")
|
||||||
|
("no-debug,d", "Create coredumps on crash")
|
||||||
|
("jid,j", boost::program_options::value<std::string>(&jid)->default_value(""), "Specify JID of transport manually")
|
||||||
("config", boost::program_options::value<std::string>(&config_file)->default_value(""), "Config file")
|
("config", boost::program_options::value<std::string>(&config_file)->default_value(""), "Config file")
|
||||||
|
("version,v", "Shows Spectrum version")
|
||||||
;
|
;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -149,7 +155,10 @@ int main(int argc, char **argv)
|
||||||
options(desc).positional(p).run(), vm);
|
options(desc).positional(p).run(), vm);
|
||||||
boost::program_options::notify(vm);
|
boost::program_options::notify(vm);
|
||||||
|
|
||||||
|
if (vm.count("version")) {
|
||||||
|
std::cout << SPECTRUM_VERSION << "\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if(vm.count("help"))
|
if(vm.count("help"))
|
||||||
{
|
{
|
||||||
|
@ -177,31 +186,46 @@ int main(int argc, char **argv)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config.load(vm["config"].as<std::string>())) {
|
if (!config.load(vm["config"].as<std::string>(), jid)) {
|
||||||
std::cerr << "Can't load configuration file.\n";
|
std::cerr << "Can't load configuration file.\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create directories
|
||||||
|
try {
|
||||||
|
boost::filesystem::create_directories(
|
||||||
|
boost::filesystem::path(CONFIG_STRING(&config, "service.pidfile")).parent_path().string()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
std::cerr << "Can't create service.pidfile directory " << boost::filesystem::path(CONFIG_STRING(&config, "service.pidfile")).parent_path().string() << ".\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// create directories
|
||||||
|
try {
|
||||||
|
boost::filesystem::create_directories(CONFIG_STRING(&config, "service.working_dir"));
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
std::cerr << "Can't create service.working_dir directory " << CONFIG_STRING(&config, "service.working_dir") << ".\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(CONFIG_STRING(&config, "service.working_dir").c_str(), pw->pw_uid, gr->gr_gid);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
if (!no_daemon) {
|
if (!no_daemon) {
|
||||||
// create directories
|
|
||||||
try {
|
|
||||||
boost::filesystem::create_directories(CONFIG_STRING(&config, "service.working_dir"));
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
std::cerr << "Can't create service.working_dir directory " << CONFIG_STRING(&config, "service.working_dir") << ".\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
boost::filesystem::create_directories(
|
|
||||||
boost::filesystem::path(CONFIG_STRING(&config, "service.pidfile")).parent_path().string()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
std::cerr << "Can't create service.pidfile directory " << boost::filesystem::path(CONFIG_STRING(&config, "service.pidfile")).parent_path().string() << ".\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// daemonize
|
// daemonize
|
||||||
daemonize(CONFIG_STRING(&config, "service.working_dir").c_str(), CONFIG_STRING(&config, "service.pidfile").c_str());
|
daemonize(CONFIG_STRING(&config, "service.working_dir").c_str(), CONFIG_STRING(&config, "service.pidfile").c_str());
|
||||||
// removeOldIcons(CONFIG_STRING(&config, "service.working_dir") + "/icons");
|
// removeOldIcons(CONFIG_STRING(&config, "service.working_dir") + "/icons");
|
||||||
|
@ -231,6 +255,46 @@ int main(int argc, char **argv)
|
||||||
p.setProperty("pid", pid);
|
p.setProperty("pid", pid);
|
||||||
p.setProperty("jid", jid);
|
p.setProperty("jid", jid);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
std::string dir;
|
||||||
|
BOOST_FOREACH(const log4cxx::LogString &prop, p.propertyNames()) {
|
||||||
|
if (boost::ends_with(prop, ".File")) {
|
||||||
|
dir = p.get(prop);
|
||||||
|
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);
|
log4cxx::PropertyConfigurator::configure(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,12 +306,12 @@ int main(int argc, char **argv)
|
||||||
if (!CONFIG_STRING(&config, "service.group").empty()) {
|
if (!CONFIG_STRING(&config, "service.group").empty()) {
|
||||||
struct group *gr;
|
struct group *gr;
|
||||||
if ((gr = getgrnam(CONFIG_STRING(&config, "service.group").c_str())) == NULL) {
|
if ((gr = getgrnam(CONFIG_STRING(&config, "service.group").c_str())) == NULL) {
|
||||||
LOG4CXX_ERROR(logger, "Invalid service.group name " << CONFIG_STRING(&config, "service.group"));
|
std::cerr << "Invalid service.group name " << CONFIG_STRING(&config, "service.group") << "\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((setgid(gr->gr_gid)) != 0) || (initgroups(CONFIG_STRING(&config, "service.user").c_str(), gr->gr_gid) != 0)) {
|
if (((setgid(gr->gr_gid)) != 0) || (initgroups(CONFIG_STRING(&config, "service.user").c_str(), gr->gr_gid) != 0)) {
|
||||||
LOG4CXX_ERROR(logger, "Failed to set service.group name " << CONFIG_STRING(&config, "service.group") << " - " << gr->gr_gid << ":" << strerror(errno));
|
std::cerr << "Failed to set service.group name " << CONFIG_STRING(&config, "service.group") << " - " << gr->gr_gid << ":" << strerror(errno) << "\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,17 +319,22 @@ int main(int argc, char **argv)
|
||||||
if (!CONFIG_STRING(&config, "service.user").empty()) {
|
if (!CONFIG_STRING(&config, "service.user").empty()) {
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
if ((pw = getpwnam(CONFIG_STRING(&config, "service.user").c_str())) == NULL) {
|
if ((pw = getpwnam(CONFIG_STRING(&config, "service.user").c_str())) == NULL) {
|
||||||
LOG4CXX_ERROR(logger, "Invalid service.user name " << CONFIG_STRING(&config, "service.user"));
|
std::cerr << "Invalid service.user name " << CONFIG_STRING(&config, "service.user") << "\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((setuid(pw->pw_uid)) != 0) {
|
if ((setuid(pw->pw_uid)) != 0) {
|
||||||
LOG4CXX_ERROR(logger, "Failed to set service.user name " << CONFIG_STRING(&config, "service.user") << " - " << pw->pw_uid << ":" << strerror(errno));
|
std::cerr << "Failed to set service.user name " << CONFIG_STRING(&config, "service.user") << " - " << pw->pw_uid << ":" << strerror(errno) << "\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setrlimit(RLIMIT_CORE, &limit);
|
setrlimit(RLIMIT_CORE, &limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct rlimit limit;
|
||||||
|
limit.rlim_max = RLIM_INFINITY;
|
||||||
|
limit.rlim_cur = RLIM_INFINITY;
|
||||||
|
setrlimit(RLIMIT_CORE, &limit);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Swift::SimpleEventLoop eventLoop;
|
Swift::SimpleEventLoop eventLoop;
|
||||||
|
@ -313,6 +382,8 @@ int main(int argc, char **argv)
|
||||||
NetworkPluginServer plugin(&transport, &config, &userManager, &ftManager);
|
NetworkPluginServer plugin(&transport, &config, &userManager, &ftManager);
|
||||||
|
|
||||||
AdminInterface adminInterface(&transport, &userManager, &plugin, storageBackend);
|
AdminInterface adminInterface(&transport, &userManager, &plugin, storageBackend);
|
||||||
|
StatsResponder statsResponder(&transport, &userManager, &plugin, storageBackend);
|
||||||
|
statsResponder.start();
|
||||||
|
|
||||||
eventLoop_ = &eventLoop;
|
eventLoop_ = &eventLoop;
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ server = 127.0.0.1
|
||||||
port = 5222
|
port = 5222
|
||||||
server_mode = 1
|
server_mode = 1
|
||||||
backend_host=localhost
|
backend_host=localhost
|
||||||
|
pidfile=./test.pid
|
||||||
# < this option doesn't work yet
|
# < this option doesn't work yet
|
||||||
backend_port=10001
|
backend_port=10001
|
||||||
admin_username=admin
|
admin_username=admin
|
||||||
|
@ -12,13 +13,14 @@ admin_password=test
|
||||||
#cert=server.pfx #patch to PKCS#12 certificate
|
#cert=server.pfx #patch to PKCS#12 certificate
|
||||||
#cert_password=test #password to that certificate if any
|
#cert_password=test #password to that certificate if any
|
||||||
users_per_backend=10
|
users_per_backend=10
|
||||||
backend=/home/hanzz/code/libtransport/backends/libpurple/spectrum2_libpurple_backend
|
#backend=/home/hanzz/code/libtransport/backends/libpurple/spectrum2_libpurple_backend
|
||||||
#backend=/usr/bin/mono /home/hanzz/code/networkplugin-csharp/msnp-sharp-backend/bin/Debug/msnp-sharp-backend.exe
|
#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/frotz/spectrum2_frotz_backend
|
||||||
#backend=/home/hanzz/code/libtransport/backends/libircclient-qt/spectrum2_libircclient-qt_backend
|
backend=/home/hanzz/code/libtransport/backends/libircclient-qt/spectrum2_libircclient-qt_backend
|
||||||
#protocol=prpl-msn
|
#protocol=prpl-msn
|
||||||
protocol=any
|
protocol=any
|
||||||
#protocol=prpl-icq
|
#protocol=prpl-icq
|
||||||
|
irc_server=irc.freenode.org
|
||||||
|
|
||||||
[backend]
|
[backend]
|
||||||
#default_avatar=catmelonhead.jpg
|
#default_avatar=catmelonhead.jpg
|
||||||
|
|
|
@ -36,8 +36,8 @@ backend_port=10001
|
||||||
users_per_backend=10
|
users_per_backend=10
|
||||||
|
|
||||||
# Full path to backend binary.
|
# Full path to backend binary.
|
||||||
backend=/usr/bin/spectrum_libpurple_backend
|
backend=/usr/bin/spectrum2_libpurple_backend
|
||||||
#backend=/usr/bin/spectrum_libircclient-qt_backend
|
#backend=/usr/bin/spectrum2_libircclient-qt_backend
|
||||||
|
|
||||||
# Libpurple protocol-id for spectrum_libpurple_backend
|
# Libpurple protocol-id for spectrum_libpurple_backend
|
||||||
protocol=prpl-jabber
|
protocol=prpl-jabber
|
||||||
|
@ -62,18 +62,19 @@ type=xmpp
|
||||||
|
|
||||||
[logging]
|
[logging]
|
||||||
# log4cxx/log4j logging configuration file in ini format used for main spectrum2 instance.
|
# log4cxx/log4j logging configuration file in ini format used for main spectrum2 instance.
|
||||||
config = /etc/spectrum2/logging.cfg
|
config = /etc/spectrum2/logging.cfg
|
||||||
|
|
||||||
# log4cxx/log4j logging configuration file in ini format used for backends.
|
# log4cxx/log4j logging configuration file in ini format used for backends.
|
||||||
backend_config = /etc/spectrum2/backend-logging.cfg # log4cxx/log4j logging configuration file for backends
|
backend_config = /etc/spectrum2/backend-logging.cfg
|
||||||
|
|
||||||
[database]
|
[database]
|
||||||
# Database backend type
|
# Database backend type
|
||||||
# "sqlite3", "mysql" or "none" without database backend
|
# "sqlite3", "mysql" or "none" without database backend
|
||||||
type = none
|
type = none
|
||||||
|
|
||||||
# For SQLite3: Full path to database
|
# For SQLite3: Full path to database
|
||||||
# For MySQL: name of database
|
# For MySQL: name of database
|
||||||
|
# database = /var/lib/spectrum2/$jid/database.sql
|
||||||
database = jabber_transport
|
database = jabber_transport
|
||||||
|
|
||||||
# Server.
|
# Server.
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
cmake_minimum_required(VERSION 2.6)
|
cmake_minimum_required(VERSION 2.6)
|
||||||
FILE(GLOB SRC *.cpp)
|
FILE(GLOB SRC *.cpp)
|
||||||
|
|
||||||
ADD_EXECUTABLE(spectrum2_manager ${SRC})
|
ADD_EXECUTABLE(spectrum2_manager ${SRC} ../../src/config.cpp)
|
||||||
|
|
||||||
target_link_libraries(spectrum2_manager transport)
|
target_link_libraries(spectrum2_manager ${SWIFTEN_LIBRARY})
|
||||||
|
|
||||||
INSTALL(TARGETS spectrum2_manager RUNTIME DESTINATION bin)
|
INSTALL(TARGETS spectrum2_manager RUNTIME DESTINATION bin)
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
#include "managerconfig.h"
|
#include "managerconfig.h"
|
||||||
#include "transport/transport.h"
|
#include "transport/config.h"
|
||||||
#include "transport/usermanager.h"
|
#include "Swiften/Swiften.h"
|
||||||
#include "transport/logger.h"
|
|
||||||
#include "transport/sqlite3backend.h"
|
|
||||||
#include "transport/userregistration.h"
|
|
||||||
#include "transport/networkpluginserver.h"
|
|
||||||
#include "Swiften/EventLoop/SimpleEventLoop.h"
|
#include "Swiften/EventLoop/SimpleEventLoop.h"
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
@ -86,12 +82,17 @@ static std::string searchForBinary(const std::string &binary) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Executes new backend
|
// Executes new backend
|
||||||
static unsigned long exec_(std::string path, std::string config) {
|
static unsigned long exec_(std::string path, std::string config, std::string jid = "") {
|
||||||
// fork and exec
|
// fork and exec
|
||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
if ( pid == 0 ) {
|
if ( pid == 0 ) {
|
||||||
// child process
|
// child process
|
||||||
exit(execl(path.c_str(), path.c_str(), config.c_str(), NULL));
|
if (jid.empty()) {
|
||||||
|
exit(execl(path.c_str(), path.c_str(), config.c_str(), NULL));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
exit(execl(path.c_str(), path.c_str(), "-j", jid.c_str(), config.c_str(), NULL));
|
||||||
|
}
|
||||||
} else if ( pid < 0 ) {
|
} else if ( pid < 0 ) {
|
||||||
// fork failed
|
// fork failed
|
||||||
}
|
}
|
||||||
|
@ -147,15 +148,30 @@ static void start_all_instances(ManagerConfig *config) {
|
||||||
Config cfg;
|
Config cfg;
|
||||||
if (cfg.load(itr->path().string()) == false) {
|
if (cfg.load(itr->path().string()) == false) {
|
||||||
std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n";
|
std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n";
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pid = isRunning(CONFIG_STRING(&cfg, "service.pidfile"));
|
|
||||||
if (pid == 0) {
|
std::vector<std::string> vhosts;
|
||||||
std::cout << "Starting " << itr->path() << ": OK\n";
|
if (CONFIG_HAS_KEY(&cfg, "vhosts.vhost"))
|
||||||
exec_(spectrum2_binary, itr->path().string());
|
vhosts = CONFIG_VECTOR(&cfg, "vhosts.vhost");
|
||||||
}
|
vhosts.push_back(CONFIG_STRING(&cfg, "service.jid"));
|
||||||
else {
|
|
||||||
std::cout << "Starting " << itr->path() << ": Already started (PID=" << pid << ")\n";
|
BOOST_FOREACH(std::string &vhost, vhosts) {
|
||||||
|
Config vhostCfg;
|
||||||
|
if (vhostCfg.load(itr->path().string(), vhost) == false) {
|
||||||
|
std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pid = isRunning(CONFIG_STRING(&vhostCfg, "service.pidfile"));
|
||||||
|
if (pid == 0) {
|
||||||
|
std::cout << "Starting " << itr->path() << ": OK\n";
|
||||||
|
exec_(spectrum2_binary, itr->path().string(), vhost);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cout << "Starting " << itr->path() << ": Already started (PID=" << pid << ")\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,13 +204,26 @@ static void stop_all_instances(ManagerConfig *config) {
|
||||||
std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n";
|
std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
int pid = isRunning(CONFIG_STRING(&cfg, "service.pidfile"));
|
std::vector<std::string> vhosts;
|
||||||
if (pid) {
|
if (CONFIG_HAS_KEY(&cfg, "vhosts.vhost"))
|
||||||
std::cout << "Stopping " << itr->path() << ": OK\n";
|
vhosts = CONFIG_VECTOR(&cfg, "vhosts.vhost");
|
||||||
kill(pid, SIGTERM);
|
vhosts.push_back(CONFIG_STRING(&cfg, "service.jid"));
|
||||||
}
|
|
||||||
else {
|
BOOST_FOREACH(std::string &vhost, vhosts) {
|
||||||
std::cout << "Stopping " << itr->path() << ": Not running\n";
|
Config vhostCfg;
|
||||||
|
if (vhostCfg.load(itr->path().string(), vhost) == false) {
|
||||||
|
std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pid = isRunning(CONFIG_STRING(&vhostCfg, "service.pidfile"));
|
||||||
|
if (pid) {
|
||||||
|
std::cout << "Stopping " << itr->path() << ": OK\n";
|
||||||
|
kill(pid, SIGTERM);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cout << "Stopping " << itr->path() << ": Not running\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,9 +35,9 @@ if (CMAKE_COMPILER_IS_GNUCXX)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
TARGET_LINK_LIBRARIES(transport ${Boost_LIBRARIES} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES})
|
TARGET_LINK_LIBRARIES(transport ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES})
|
||||||
else (WIN32)
|
else (WIN32)
|
||||||
TARGET_LINK_LIBRARIES(transport ${Boost_LIBRARIES} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES} ${POPT_LIBRARY})
|
TARGET_LINK_LIBRARIES(transport ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES} ${POPT_LIBRARY})
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
SET_TARGET_PROPERTIES(transport PROPERTIES
|
SET_TARGET_PROPERTIES(transport PROPERTIES
|
||||||
|
|
|
@ -66,6 +66,11 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ignore empty messages
|
||||||
|
if (message->getBody().empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
LOG4CXX_INFO(logger, "Message from admin received");
|
LOG4CXX_INFO(logger, "Message from admin received");
|
||||||
message->setTo(message->getFrom());
|
message->setTo(message->getFrom());
|
||||||
message->setFrom(m_component->getJID());
|
message->setFrom(m_component->getJID());
|
||||||
|
|
|
@ -31,13 +31,13 @@ using namespace boost::program_options;
|
||||||
|
|
||||||
namespace Transport {
|
namespace Transport {
|
||||||
|
|
||||||
bool Config::load(const std::string &configfile, boost::program_options::options_description &opts) {
|
bool Config::load(const std::string &configfile, boost::program_options::options_description &opts, const std::string &jid) {
|
||||||
std::ifstream ifs(configfile.c_str());
|
std::ifstream ifs(configfile.c_str());
|
||||||
if (!ifs.is_open())
|
if (!ifs.is_open())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_file = configfile;
|
m_file = configfile;
|
||||||
bool ret = load(ifs, opts);
|
bool ret = load(ifs, opts, jid);
|
||||||
ifs.close();
|
ifs.close();
|
||||||
|
|
||||||
char path[PATH_MAX] = "";
|
char path[PATH_MAX] = "";
|
||||||
|
@ -49,7 +49,7 @@ bool Config::load(const std::string &configfile, boost::program_options::options
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Config::load(std::istream &ifs, boost::program_options::options_description &opts) {
|
bool Config::load(std::istream &ifs, boost::program_options::options_description &opts, const std::string &_jid) {
|
||||||
m_unregistered.clear();
|
m_unregistered.clear();
|
||||||
opts.add_options()
|
opts.add_options()
|
||||||
("service.jid", value<std::string>()->default_value(""), "Transport Jabber ID")
|
("service.jid", value<std::string>()->default_value(""), "Transport Jabber ID")
|
||||||
|
@ -60,13 +60,13 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
|
||||||
("service.group", value<std::string>()->default_value(""), "The name of group Spectrum runs as.")
|
("service.group", value<std::string>()->default_value(""), "The name of group Spectrum runs as.")
|
||||||
("service.backend", value<std::string>()->default_value("libpurple_backend"), "Backend")
|
("service.backend", value<std::string>()->default_value("libpurple_backend"), "Backend")
|
||||||
("service.protocol", value<std::string>()->default_value(""), "Protocol")
|
("service.protocol", value<std::string>()->default_value(""), "Protocol")
|
||||||
("service.pidfile", value<std::string>()->default_value("/var/run/spectrum2/spectrum2.pid"), "Full path to pid file")
|
("service.pidfile", value<std::string>()->default_value("/var/run/spectrum2/$jid.pid"), "Full path to pid file")
|
||||||
("service.working_dir", value<std::string>()->default_value("/var/lib/spectrum2"), "Working dir")
|
("service.working_dir", value<std::string>()->default_value("/var/lib/spectrum2/$jid"), "Working dir")
|
||||||
("service.allowed_servers", value<std::string>()->default_value(""), "Only users from these servers can connect")
|
("service.allowed_servers", value<std::string>()->default_value(""), "Only users from these servers can connect")
|
||||||
("service.server_mode", value<bool>()->default_value(false), "True if Spectrum should behave as server")
|
("service.server_mode", value<bool>()->default_value(false), "True if Spectrum should behave as server")
|
||||||
("service.users_per_backend", value<int>()->default_value(100), "Number of users per one legacy network backend")
|
("service.users_per_backend", value<int>()->default_value(100), "Number of users per one legacy network backend")
|
||||||
("service.backend_host", value<std::string>()->default_value("localhost"), "Host to bind backend server to")
|
("service.backend_host", value<std::string>()->default_value("localhost"), "Host to bind backend server to")
|
||||||
("service.backend_port", value<std::string>()->default_value("10000"), "Port to bind backend server to")
|
("service.backend_port", value<std::string>()->default_value("0"), "Port to bind backend server to")
|
||||||
("service.cert", value<std::string>()->default_value(""), "PKCS#12 Certificate.")
|
("service.cert", value<std::string>()->default_value(""), "PKCS#12 Certificate.")
|
||||||
("service.cert_password", value<std::string>()->default_value(""), "PKCS#12 Certificate password.")
|
("service.cert_password", value<std::string>()->default_value(""), "PKCS#12 Certificate password.")
|
||||||
("service.admin_jid", value<std::string>()->default_value(""), "Administrator jid.")
|
("service.admin_jid", value<std::string>()->default_value(""), "Administrator jid.")
|
||||||
|
@ -76,15 +76,16 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
|
||||||
("service.memory_collector_time", value<int>()->default_value(0), "Time in seconds after which backend with most memory is set to die.")
|
("service.memory_collector_time", value<int>()->default_value(0), "Time in seconds after which backend with most memory is set to die.")
|
||||||
("service.more_resources", value<bool>()->default_value(false), "Allow more resources to be connected in server mode at the same time.")
|
("service.more_resources", value<bool>()->default_value(false), "Allow more resources to be connected in server mode at the same time.")
|
||||||
("service.enable_privacy_lists", value<bool>()->default_value(true), "")
|
("service.enable_privacy_lists", value<bool>()->default_value(true), "")
|
||||||
|
("vhosts.vhost", value<std::vector<std::string> >()->multitoken(), "")
|
||||||
("identity.name", value<std::string>()->default_value("Spectrum 2 Transport"), "Name showed in service discovery.")
|
("identity.name", value<std::string>()->default_value("Spectrum 2 Transport"), "Name showed in service discovery.")
|
||||||
("identity.category", value<std::string>()->default_value("gateway"), "Disco#info identity category. 'gateway' by default.")
|
("identity.category", value<std::string>()->default_value("gateway"), "Disco#info identity category. 'gateway' by default.")
|
||||||
("identity.type", value<std::string>()->default_value(""), "Type of transport ('icq','msn','gg','irc', ...)")
|
("identity.type", value<std::string>()->default_value(""), "Type of transport ('icq','msn','gg','irc', ...)")
|
||||||
("registration.enable_public_registration", value<bool>()->default_value(true), "True if users should be able to register.")
|
("registration.enable_public_registration", value<bool>()->default_value(true), "True if users should be able to register.")
|
||||||
("registration.language", value<std::string>()->default_value("en"), "Default language for registration form")
|
("registration.language", value<std::string>()->default_value("en"), "Default language for registration form")
|
||||||
("registration.instructions", value<std::string>()->default_value(""), "Instructions showed to user in registration form")
|
("registration.instructions", value<std::string>()->default_value("Enter your legacy network username and password."), "Instructions showed to user in registration form")
|
||||||
("registration.username_field", value<std::string>()->default_value(""), "Label for username field")
|
("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.username_mask", value<std::string>()->default_value(""), "Username mask")
|
||||||
("registration.encoding", value<std::string>()->default_value("en"), "Default encoding in registration form")
|
("registration.encoding", value<std::string>()->default_value("utf8"), "Default encoding in registration form")
|
||||||
("database.type", value<std::string>()->default_value("none"), "Database type.")
|
("database.type", value<std::string>()->default_value("none"), "Database type.")
|
||||||
("database.database", value<std::string>()->default_value(""), "Database used to store data")
|
("database.database", value<std::string>()->default_value(""), "Database used to store data")
|
||||||
("database.server", value<std::string>()->default_value("localhost"), "Database server.")
|
("database.server", value<std::string>()->default_value("localhost"), "Database server.")
|
||||||
|
@ -92,6 +93,7 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
|
||||||
("database.password", value<std::string>()->default_value(""), "Database Password.")
|
("database.password", value<std::string>()->default_value(""), "Database Password.")
|
||||||
("database.port", value<int>()->default_value(0), "Database port.")
|
("database.port", value<int>()->default_value(0), "Database port.")
|
||||||
("database.prefix", value<std::string>()->default_value(""), "Prefix of tables in database")
|
("database.prefix", value<std::string>()->default_value(""), "Prefix of tables in database")
|
||||||
|
("database.encryption_key", value<std::string>()->default_value(""), "Encryption key.")
|
||||||
("logging.config", value<std::string>()->default_value(""), "Path to log4cxx config file which is used for Spectrum 2 instance")
|
("logging.config", value<std::string>()->default_value(""), "Path to log4cxx config file which is used for Spectrum 2 instance")
|
||||||
("logging.backend_config", value<std::string>()->default_value(""), "Path to log4cxx config file which is used for backends")
|
("logging.backend_config", value<std::string>()->default_value(""), "Path to log4cxx config file which is used for backends")
|
||||||
("backend.default_avatar", value<std::string>()->default_value(""), "Full path to default avatar")
|
("backend.default_avatar", value<std::string>()->default_value(""), "Full path to default avatar")
|
||||||
|
@ -101,10 +103,69 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
|
||||||
|
|
||||||
parsed_options parsed = parse_config_file(ifs, opts, true);
|
parsed_options parsed = parse_config_file(ifs, opts, true);
|
||||||
|
|
||||||
BOOST_FOREACH(option opt, parsed.options) {
|
bool found_working = false;
|
||||||
|
bool found_pidfile = false;
|
||||||
|
bool found_backend_port = false;
|
||||||
|
std::string jid = "";
|
||||||
|
BOOST_FOREACH(option &opt, parsed.options) {
|
||||||
|
if (opt.string_key == "service.jid") {
|
||||||
|
if (_jid.empty()) {
|
||||||
|
jid = opt.value[0];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
opt.value[0] = _jid;
|
||||||
|
jid = _jid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (opt.string_key == "service.backend_port") {
|
||||||
|
found_backend_port = true;
|
||||||
|
if (opt.value[0] == "0") {
|
||||||
|
unsigned long r = 0;
|
||||||
|
BOOST_FOREACH(char c, _jid) {
|
||||||
|
r += (int) c;
|
||||||
|
}
|
||||||
|
srand(time(NULL) + r);
|
||||||
|
int randomPort = 30000 + rand() % 10000;
|
||||||
|
opt.value[0] = boost::lexical_cast<std::string>(randomPort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (opt.string_key == "service.working_dir") {
|
||||||
|
found_working = true;
|
||||||
|
}
|
||||||
|
else if (opt.string_key == "service.pidfile") {
|
||||||
|
found_pidfile = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found_working) {
|
||||||
|
std::vector<std::string> value;
|
||||||
|
value.push_back("/var/lib/spectrum2/$jid");
|
||||||
|
parsed.options.push_back(boost::program_options::basic_option<char>("service.working_dir", value));
|
||||||
|
}
|
||||||
|
if (!found_pidfile) {
|
||||||
|
std::vector<std::string> value;
|
||||||
|
value.push_back("/var/run/spectrum2/$jid.pid");
|
||||||
|
parsed.options.push_back(boost::program_options::basic_option<char>("service.pidfile", value));
|
||||||
|
}
|
||||||
|
if (!found_backend_port) {
|
||||||
|
unsigned long r = 0;
|
||||||
|
BOOST_FOREACH(char c, _jid) {
|
||||||
|
r += (int) c;
|
||||||
|
}
|
||||||
|
srand(time(NULL) + r);
|
||||||
|
int randomPort = 30000 + rand() % 10000;
|
||||||
|
std::vector<std::string> value;
|
||||||
|
value.push_back(boost::lexical_cast<std::string>(randomPort));
|
||||||
|
parsed.options.push_back(boost::program_options::basic_option<char>("service.backend_port", value));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_FOREACH(option &opt, parsed.options) {
|
||||||
if (opt.unregistered) {
|
if (opt.unregistered) {
|
||||||
m_unregistered[opt.string_key] = opt.value[0];
|
m_unregistered[opt.string_key] = opt.value[0];
|
||||||
}
|
}
|
||||||
|
else if (opt.value[0].find("$jid") != std::string::npos) {
|
||||||
|
boost::replace_all(opt.value[0], "$jid", jid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
store(parsed, m_variables);
|
store(parsed, m_variables);
|
||||||
|
@ -120,9 +181,9 @@ bool Config::load(std::istream &ifs) {
|
||||||
return load(ifs, opts);
|
return load(ifs, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Config::load(const std::string &configfile) {
|
bool Config::load(const std::string &configfile, const std::string &jid) {
|
||||||
options_description opts("Transport options");
|
options_description opts("Transport options");
|
||||||
return load(configfile, opts);
|
return load(configfile, opts, jid);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Config::reload() {
|
bool Config::reload() {
|
||||||
|
|
|
@ -37,6 +37,7 @@ Conversation::Conversation(ConversationManager *conversationManager, const std::
|
||||||
m_legacyName = legacyName;
|
m_legacyName = legacyName;
|
||||||
m_conversationManager->addConversation(this);
|
m_conversationManager->addConversation(this);
|
||||||
m_muc = isMUC;
|
m_muc = isMUC;
|
||||||
|
m_jid = m_conversationManager->getUser()->getJID().toBare();
|
||||||
}
|
}
|
||||||
|
|
||||||
Conversation::~Conversation() {
|
Conversation::~Conversation() {
|
||||||
|
@ -54,11 +55,16 @@ void Conversation::handleMessage(boost::shared_ptr<Swift::Message> &message, con
|
||||||
else {
|
else {
|
||||||
message->setType(Swift::Message::Chat);
|
message->setType(Swift::Message::Chat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string n = nickname;
|
||||||
|
if (n.empty() && !m_room.empty() && !m_muc) {
|
||||||
|
n = m_nickname;
|
||||||
|
}
|
||||||
|
|
||||||
if (message->getType() != Swift::Message::Groupchat) {
|
if (message->getType() != Swift::Message::Groupchat) {
|
||||||
|
message->setTo(m_jid);
|
||||||
message->setTo(m_conversationManager->getUser()->getJID().toBare());
|
|
||||||
// normal message
|
// normal message
|
||||||
if (nickname.empty()) {
|
if (n.empty()) {
|
||||||
Buddy *buddy = m_conversationManager->getUser()->getRosterManager()->getBuddy(m_legacyName);
|
Buddy *buddy = m_conversationManager->getUser()->getRosterManager()->getBuddy(m_legacyName);
|
||||||
if (buddy) {
|
if (buddy) {
|
||||||
message->setFrom(buddy->getJID());
|
message->setFrom(buddy->getJID());
|
||||||
|
@ -70,10 +76,10 @@ void Conversation::handleMessage(boost::shared_ptr<Swift::Message> &message, con
|
||||||
// PM message
|
// PM message
|
||||||
else {
|
else {
|
||||||
if (m_room.empty()) {
|
if (m_room.empty()) {
|
||||||
message->setFrom(Swift::JID(nickname, m_conversationManager->getComponent()->getJID().toBare(), "user"));
|
message->setFrom(Swift::JID(n, m_conversationManager->getComponent()->getJID().toBare(), "user"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
message->setFrom(Swift::JID(m_room, m_conversationManager->getComponent()->getJID().toBare(), nickname));
|
message->setFrom(Swift::JID(m_room, m_conversationManager->getComponent()->getJID().toBare(), n));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message);
|
m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message);
|
||||||
|
@ -83,7 +89,7 @@ void Conversation::handleMessage(boost::shared_ptr<Swift::Message> &message, con
|
||||||
if (legacyName.find_last_of("@") != std::string::npos) {
|
if (legacyName.find_last_of("@") != std::string::npos) {
|
||||||
legacyName.replace(legacyName.find_last_of("@"), 1, "%"); // OK
|
legacyName.replace(legacyName.find_last_of("@"), 1, "%"); // OK
|
||||||
}
|
}
|
||||||
message->setTo(m_conversationManager->getUser()->getJID().toString());
|
message->setTo(m_jid);
|
||||||
message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), nickname));
|
message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), nickname));
|
||||||
m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message);
|
m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message);
|
||||||
}
|
}
|
||||||
|
@ -99,7 +105,7 @@ void Conversation::handleParticipantChanged(const std::string &nick, int flag, i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
presence->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), nickname));
|
presence->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), nickname));
|
||||||
presence->setTo(m_conversationManager->getUser()->getJID().toString());
|
presence->setTo(m_jid);
|
||||||
presence->setType(Swift::Presence::Available);
|
presence->setType(Swift::Presence::Available);
|
||||||
|
|
||||||
if (!statusMessage.empty())
|
if (!statusMessage.empty())
|
||||||
|
|
|
@ -62,6 +62,15 @@ void ConversationManager::removeConversation(Conversation *conv) {
|
||||||
m_convs.erase(conv->getLegacyName());
|
m_convs.erase(conv->getLegacyName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConversationManager::resetResources() {
|
||||||
|
for (std::map<std::string, Conversation *>::const_iterator it = m_convs.begin(); it != m_convs.end(); it++) {
|
||||||
|
if ((*it).second->isMUC()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
(*it).second->setJID(m_user->getJID().toBare());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ConversationManager::handleMessageReceived(Swift::Message::ref message) {
|
void ConversationManager::handleMessageReceived(Swift::Message::ref message) {
|
||||||
// std::string name = message->getTo().getUnescapedNode();
|
// std::string name = message->getTo().getUnescapedNode();
|
||||||
// if (name.find_last_of("%") != std::string::npos) { // OK when commented
|
// if (name.find_last_of("%") != std::string::npos) { // OK when commented
|
||||||
|
@ -84,10 +93,13 @@ void ConversationManager::handleMessageReceived(Swift::Message::ref message) {
|
||||||
if (!m_convs[name]) {
|
if (!m_convs[name]) {
|
||||||
m_convs[name] = m_component->getFactory()->createConversation(this, name);
|
m_convs[name] = m_component->getFactory()->createConversation(this, name);
|
||||||
m_convs[name]->setRoom(room_name);
|
m_convs[name]->setRoom(room_name);
|
||||||
|
m_convs[name]->setNickname(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update resource and send the message
|
||||||
|
m_convs[name]->setJID(message->getFrom());
|
||||||
m_convs[name]->sendMessage(message);
|
m_convs[name]->sendMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#ifdef WITH_MYSQL
|
#ifdef WITH_MYSQL
|
||||||
|
|
||||||
#include "transport/mysqlbackend.h"
|
#include "transport/mysqlbackend.h"
|
||||||
|
#include "transport/util.h"
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include "log4cxx/logger.h"
|
#include "log4cxx/logger.h"
|
||||||
|
|
||||||
|
@ -409,7 +410,11 @@ bool MySQLBackend::exec(const std::string &query) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLBackend::setUser(const UserInfo &user) {
|
void MySQLBackend::setUser(const UserInfo &user) {
|
||||||
*m_setUser << user.jid << user.uin << user.password << user.language << user.encoding << user.vip << user.password;
|
std::string encrypted = user.password;
|
||||||
|
if (!CONFIG_STRING(m_config, "database.encryption_key").empty()) {
|
||||||
|
encrypted = Util::encryptPassword(encrypted, CONFIG_STRING(m_config, "database.encryption_key"));
|
||||||
|
}
|
||||||
|
*m_setUser << user.jid << user.uin << encrypted << user.language << user.encoding << user.vip << user.password;
|
||||||
EXEC(m_setUser, setUser(user));
|
EXEC(m_setUser, setUser(user));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,6 +428,10 @@ bool MySQLBackend::getUser(const std::string &barejid, UserInfo &user) {
|
||||||
while (m_getUser->fetch() == 0) {
|
while (m_getUser->fetch() == 0) {
|
||||||
ret = true;
|
ret = true;
|
||||||
*m_getUser >> user.id >> user.jid >> user.uin >> user.password >> user.encoding >> user.language >> user.vip;
|
*m_getUser >> user.id >> user.jid >> user.uin >> user.password >> user.encoding >> user.language >> user.vip;
|
||||||
|
|
||||||
|
if (!CONFIG_STRING(m_config, "database.encryption_key").empty()) {
|
||||||
|
user.password = Util::decryptPassword(user.password, CONFIG_STRING(m_config, "database.encryption_key"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -257,6 +257,17 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkPluginServer::~NetworkPluginServer() {
|
NetworkPluginServer::~NetworkPluginServer() {
|
||||||
|
for (std::list<Backend *>::const_iterator it = m_clients.begin(); it != m_clients.end(); it++) {
|
||||||
|
LOG4CXX_INFO(logger, "Stopping backend " << *it);
|
||||||
|
std::string message;
|
||||||
|
pbnetwork::WrapperMessage wrap;
|
||||||
|
wrap.set_type(pbnetwork::WrapperMessage_Type_TYPE_EXIT);
|
||||||
|
wrap.SerializeToString(&message);
|
||||||
|
|
||||||
|
Backend *c = (Backend *) *it;
|
||||||
|
send(c->connection, message);
|
||||||
|
}
|
||||||
|
|
||||||
m_pingTimer->stop();
|
m_pingTimer->stop();
|
||||||
m_server->stop();
|
m_server->stop();
|
||||||
m_server.reset();
|
m_server.reset();
|
||||||
|
@ -924,7 +935,7 @@ void NetworkPluginServer::handleUserCreated(User *user) {
|
||||||
// UserInfo userInfo = user->getUserInfo();
|
// UserInfo userInfo = user->getUserInfo();
|
||||||
user->onReadyToConnect.connect(boost::bind(&NetworkPluginServer::handleUserReadyToConnect, this, user));
|
user->onReadyToConnect.connect(boost::bind(&NetworkPluginServer::handleUserReadyToConnect, this, user));
|
||||||
user->onPresenceChanged.connect(boost::bind(&NetworkPluginServer::handleUserPresenceChanged, this, user, _1));
|
user->onPresenceChanged.connect(boost::bind(&NetworkPluginServer::handleUserPresenceChanged, this, user, _1));
|
||||||
user->onRoomJoined.connect(boost::bind(&NetworkPluginServer::handleRoomJoined, this, user, _1, _2, _3));
|
user->onRoomJoined.connect(boost::bind(&NetworkPluginServer::handleRoomJoined, this, user, _1, _2, _3, _4));
|
||||||
user->onRoomLeft.connect(boost::bind(&NetworkPluginServer::handleRoomLeft, this, user, _1));
|
user->onRoomLeft.connect(boost::bind(&NetworkPluginServer::handleRoomLeft, this, user, _1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -980,7 +991,7 @@ void NetworkPluginServer::handleUserPresenceChanged(User *user, Swift::Presence:
|
||||||
send(c->connection, message);
|
send(c->connection, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkPluginServer::handleRoomJoined(User *user, const std::string &r, const std::string &nickname, const std::string &password) {
|
void NetworkPluginServer::handleRoomJoined(User *user, const Swift::JID &who, const std::string &r, const std::string &nickname, const std::string &password) {
|
||||||
UserInfo userInfo = user->getUserInfo();
|
UserInfo userInfo = user->getUserInfo();
|
||||||
|
|
||||||
pbnetwork::Room room;
|
pbnetwork::Room room;
|
||||||
|
@ -1003,6 +1014,7 @@ void NetworkPluginServer::handleRoomJoined(User *user, const std::string &r, con
|
||||||
NetworkConversation *conv = new NetworkConversation(user->getConversationManager(), r, true);
|
NetworkConversation *conv = new NetworkConversation(user->getConversationManager(), r, true);
|
||||||
conv->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, this, _1, _2));
|
conv->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, this, _1, _2));
|
||||||
conv->setNickname(nickname);
|
conv->setNickname(nickname);
|
||||||
|
conv->setJID(who);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkPluginServer::handleRoomLeft(User *user, const std::string &r) {
|
void NetworkPluginServer::handleRoomLeft(User *user, const std::string &r) {
|
||||||
|
@ -1036,7 +1048,6 @@ void NetworkPluginServer::handleRoomLeft(User *user, const std::string &r) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkPluginServer::handleUserDestroyed(User *user) {
|
void NetworkPluginServer::handleUserDestroyed(User *user) {
|
||||||
std::cout << "HANDLE_DESTROYED\n";
|
|
||||||
m_waitingUsers.remove(user);
|
m_waitingUsers.remove(user);
|
||||||
UserInfo userInfo = user->getUserInfo();
|
UserInfo userInfo = user->getUserInfo();
|
||||||
|
|
||||||
|
|
|
@ -52,9 +52,9 @@ RosterManager::RosterManager(User *user, Component *component){
|
||||||
m_supportRemoteRoster = false;
|
m_supportRemoteRoster = false;
|
||||||
|
|
||||||
if (!m_component->inServerMode()) {
|
if (!m_component->inServerMode()) {
|
||||||
AddressedRosterRequest::ref request = AddressedRosterRequest::ref(new AddressedRosterRequest(m_component->getIQRouter(), m_user->getJID().toBare()));
|
m_remoteRosterRequest = AddressedRosterRequest::ref(new AddressedRosterRequest(m_component->getIQRouter(), m_user->getJID().toBare()));
|
||||||
request->onResponse.connect(boost::bind(&RosterManager::handleRemoteRosterResponse, this, _1, _2));
|
m_remoteRosterRequest->onResponse.connect(boost::bind(&RosterManager::handleRemoteRosterResponse, this, _1, _2));
|
||||||
request->send();
|
m_remoteRosterRequest->send();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +67,11 @@ RosterManager::~RosterManager() {
|
||||||
|
|
||||||
sendUnavailablePresences(m_user->getJID().toBare());
|
sendUnavailablePresences(m_user->getJID().toBare());
|
||||||
|
|
||||||
|
if (m_remoteRosterRequest) {
|
||||||
|
m_remoteRosterRequest->onResponse.disconnect_all_slots();
|
||||||
|
m_component->getIQRouter()->removeHandler(m_remoteRosterRequest);
|
||||||
|
}
|
||||||
|
|
||||||
for (std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
|
for (std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
|
||||||
Buddy *buddy = (*it).second;
|
Buddy *buddy = (*it).second;
|
||||||
if (!buddy) {
|
if (!buddy) {
|
||||||
|
@ -136,8 +141,6 @@ void RosterManager::handleBuddyChanged(Buddy *buddy) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RosterManager::setBuddyCallback(Buddy *buddy) {
|
void RosterManager::setBuddyCallback(Buddy *buddy) {
|
||||||
m_setBuddyTimer->onTick.disconnect(boost::bind(&RosterManager::setBuddyCallback, this, buddy));
|
|
||||||
|
|
||||||
LOG4CXX_INFO(logger, "Associating buddy " << buddy->getName() << " with " << m_user->getJID().toString());
|
LOG4CXX_INFO(logger, "Associating buddy " << buddy->getName() << " with " << m_user->getJID().toString());
|
||||||
m_buddies[buddy->getName()] = buddy;
|
m_buddies[buddy->getName()] = buddy;
|
||||||
onBuddySet(buddy);
|
onBuddySet(buddy);
|
||||||
|
@ -148,21 +151,17 @@ void RosterManager::setBuddyCallback(Buddy *buddy) {
|
||||||
sendBuddyRosterPush(buddy);
|
sendBuddyRosterPush(buddy);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (m_setBuddyTimer->onTick.empty()) {
|
if (m_supportRemoteRoster) {
|
||||||
m_setBuddyTimer->stop();
|
sendBuddyRosterPush(buddy);
|
||||||
|
}
|
||||||
if (m_supportRemoteRoster) {
|
else {
|
||||||
sendBuddyRosterPush(buddy);
|
// Send RIE only if there's resource which supports it.
|
||||||
|
Swift::JID jidWithRIE = m_user->getJIDWithFeature("http://jabber.org/protocol/rosterx");
|
||||||
|
if (jidWithRIE.isValid()) {
|
||||||
|
m_RIETimer->start();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Send RIE only if there's resource which supports it.
|
sendBuddySubscribePresence(buddy);
|
||||||
Swift::JID jidWithRIE = m_user->getJIDWithFeature("http://jabber.org/protocol/rosterx");
|
|
||||||
if (jidWithRIE.isValid()) {
|
|
||||||
m_RIETimer->start();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sendBuddySubscribePresence(buddy);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,6 +197,7 @@ void RosterManager::handleBuddyRosterPushResponse(Swift::ErrorPayload::ref error
|
||||||
}
|
}
|
||||||
|
|
||||||
void RosterManager::handleRemoteRosterResponse(boost::shared_ptr<Swift::RosterPayload> payload, Swift::ErrorPayload::ref error) {
|
void RosterManager::handleRemoteRosterResponse(boost::shared_ptr<Swift::RosterPayload> payload, Swift::ErrorPayload::ref error) {
|
||||||
|
m_remoteRosterRequest.reset();
|
||||||
if (error) {
|
if (error) {
|
||||||
m_supportRemoteRoster = false;
|
m_supportRemoteRoster = false;
|
||||||
LOG4CXX_INFO(logger, m_user->getJID().toString() << ": This server does not support remote roster protoXEP");
|
LOG4CXX_INFO(logger, m_user->getJID().toString() << ": This server does not support remote roster protoXEP");
|
||||||
|
|
142
src/statsresponder.cpp
Normal file
142
src/statsresponder.cpp
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
/**
|
||||||
|
* XMPP - libpurple transport
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "transport/statsresponder.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
#include "Swiften/Queries/IQRouter.h"
|
||||||
|
#include "transport/BlockPayload.h"
|
||||||
|
#include "Swiften/Swiften.h"
|
||||||
|
#include "transport/usermanager.h"
|
||||||
|
#include "transport/user.h"
|
||||||
|
#include "transport/buddy.h"
|
||||||
|
#include "transport/rostermanager.h"
|
||||||
|
#include "transport/memoryusage.h"
|
||||||
|
#include "transport/conversationmanager.h"
|
||||||
|
#include "transport/rostermanager.h"
|
||||||
|
#include "transport/usermanager.h"
|
||||||
|
#include "transport/networkpluginserver.h"
|
||||||
|
#include "log4cxx/logger.h"
|
||||||
|
|
||||||
|
using namespace log4cxx;
|
||||||
|
|
||||||
|
using namespace Swift;
|
||||||
|
using namespace boost;
|
||||||
|
|
||||||
|
namespace Transport {
|
||||||
|
|
||||||
|
static LoggerPtr logger = Logger::getLogger("StatsResponder");
|
||||||
|
|
||||||
|
StatsResponder::StatsResponder(Component *component, UserManager *userManager, NetworkPluginServer *server, StorageBackend *storageBackend) : Swift::Responder<StatsPayload>(component->getIQRouter()) {
|
||||||
|
m_component = component;
|
||||||
|
m_userManager = userManager;
|
||||||
|
m_server = server;
|
||||||
|
m_storageBackend = storageBackend;
|
||||||
|
m_start = time(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
StatsResponder::~StatsResponder() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long StatsResponder::usedMemory() {
|
||||||
|
double shared = 0;
|
||||||
|
double rss = 0;
|
||||||
|
#ifndef WIN32
|
||||||
|
process_mem_usage(shared, rss);
|
||||||
|
#endif
|
||||||
|
rss -= shared;
|
||||||
|
|
||||||
|
const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
|
||||||
|
BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
|
||||||
|
rss += backend->res - backend->shared;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (unsigned long) rss;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StatsResponder::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<StatsPayload> stats) {
|
||||||
|
boost::shared_ptr<StatsPayload> response(new StatsPayload());
|
||||||
|
|
||||||
|
if (stats->getItems().empty()) {
|
||||||
|
response->addItem(StatsPayload::Item("uptime"));
|
||||||
|
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("memory-usage"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unsigned long contactsOnline = 0;
|
||||||
|
unsigned long contactsTotal = 0;
|
||||||
|
|
||||||
|
Swift::StatusShow s;
|
||||||
|
std::string statusMessage;
|
||||||
|
for (std::map<std::string, User *>::const_iterator it = m_userManager->getUsers().begin(); it != m_userManager->getUsers().end(); it++) {
|
||||||
|
if (!(*it).second) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const RosterManager::BuddiesMap &buddies = (*it).second->getRosterManager()->getBuddies();
|
||||||
|
contactsTotal += buddies.size();
|
||||||
|
for(RosterManager::BuddiesMap::const_iterator bt = buddies.begin(); bt != buddies.end(); bt++) {
|
||||||
|
if (!(*bt).second) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!(*bt).second->getStatus(s, statusMessage))
|
||||||
|
continue;
|
||||||
|
if (s.getType() != Swift::StatusShow::None) {
|
||||||
|
contactsOnline++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_FOREACH(const StatsPayload::Item &item, stats->getItems()) {
|
||||||
|
if (item.getName() == "uptime") {
|
||||||
|
response->addItem(StatsPayload::Item("uptime", "seconds", boost::lexical_cast<std::string>(time(0) - m_start)));
|
||||||
|
}
|
||||||
|
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() == "memory-usage") {
|
||||||
|
response->addItem(StatsPayload::Item("memory-usage", "KB", boost::lexical_cast<std::string>(usedMemory())));
|
||||||
|
}
|
||||||
|
else if (item.getName() == "contacts/online") {
|
||||||
|
response->addItem(StatsPayload::Item("contacts/online", "contacts", boost::lexical_cast<std::string>(contactsOnline)));
|
||||||
|
}
|
||||||
|
else if (item.getName() == "contacts/total") {
|
||||||
|
response->addItem(StatsPayload::Item("contacts/total", "contacts", boost::lexical_cast<std::string>(contactsTotal)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sendResponse(from, id, response);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StatsResponder::handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<StatsPayload> stats) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -24,6 +24,7 @@ class RosterManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
|
||||||
CPPUNIT_TEST_SUITE(RosterManagerTest);
|
CPPUNIT_TEST_SUITE(RosterManagerTest);
|
||||||
CPPUNIT_TEST(setBuddy);
|
CPPUNIT_TEST(setBuddy);
|
||||||
CPPUNIT_TEST(sendCurrentPresences);
|
CPPUNIT_TEST(sendCurrentPresences);
|
||||||
|
CPPUNIT_TEST(sendCurrentPresence);
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -132,13 +133,32 @@ class RosterManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
|
||||||
user->getRosterManager()->sendCurrentPresences("user@localhost/resource");
|
user->getRosterManager()->sendCurrentPresences("user@localhost/resource");
|
||||||
|
|
||||||
CPPUNIT_ASSERT_EQUAL(2, (int) received.size());
|
CPPUNIT_ASSERT_EQUAL(2, (int) received.size());
|
||||||
// CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received[2])));
|
|
||||||
// CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast<Swift::Presence *>(getStanza(received[2]))->getShow());
|
for (int i = 0; i < 2; i++) {
|
||||||
// CPPUNIT_ASSERT_EQUAL(std::string("status1"), dynamic_cast<Swift::Presence *>(getStanza(received[2]))->getStatus());
|
CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received[i])));
|
||||||
//
|
CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast<Swift::Presence *>(getStanza(received[i]))->getShow());
|
||||||
// CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received[3])));
|
CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast<Swift::Presence *>(getStanza(received[i]))->getTo().toString());
|
||||||
// CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast<Swift::Presence *>(getStanza(received[3]))->getShow());
|
}
|
||||||
// CPPUNIT_ASSERT_EQUAL(std::string("status2"), dynamic_cast<Swift::Presence *>(getStanza(received[3]))->getStatus());
|
}
|
||||||
|
|
||||||
|
void sendCurrentPresence() {
|
||||||
|
setBuddy();
|
||||||
|
received.clear();
|
||||||
|
|
||||||
|
User *user = userManager->getUser("user@localhost");
|
||||||
|
user->getRosterManager()->sendCurrentPresence("buddy1@localhost", "user@localhost/resource");
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
|
||||||
|
CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received[0])));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast<Swift::Presence *>(getStanza(received[0]))->getShow());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast<Swift::Presence *>(getStanza(received[0]))->getTo().toString());
|
||||||
|
|
||||||
|
received.clear();
|
||||||
|
user->getRosterManager()->sendCurrentPresence("buddy_unknown@localhost", "user@localhost/resource");
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
|
||||||
|
CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received[0])));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(Swift::Presence::Unavailable, dynamic_cast<Swift::Presence *>(getStanza(received[0]))->getType());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast<Swift::Presence *>(getStanza(received[0]))->getTo().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void disconnectUser() {
|
void disconnectUser() {
|
||||||
|
|
45
src/tests/util.cpp
Normal file
45
src/tests/util.cpp
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#include "transport/userregistry.h"
|
||||||
|
#include "transport/config.h"
|
||||||
|
#include "transport/storagebackend.h"
|
||||||
|
#include "transport/user.h"
|
||||||
|
#include "transport/transport.h"
|
||||||
|
#include "transport/conversation.h"
|
||||||
|
#include "transport/usermanager.h"
|
||||||
|
#include "transport/localbuddy.h"
|
||||||
|
#include <cppunit/TestFixture.h>
|
||||||
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
#include <Swiften/Swiften.h>
|
||||||
|
#include <Swiften/EventLoop/DummyEventLoop.h>
|
||||||
|
#include <Swiften/Server/Server.h>
|
||||||
|
#include <Swiften/Network/DummyNetworkFactories.h>
|
||||||
|
#include <Swiften/Network/DummyConnectionServer.h>
|
||||||
|
#include "Swiften/Server/ServerStanzaChannel.h"
|
||||||
|
#include "Swiften/Server/ServerFromClientSession.h"
|
||||||
|
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
|
||||||
|
#include "basictest.h"
|
||||||
|
|
||||||
|
#include "transport/util.h"
|
||||||
|
|
||||||
|
using namespace Transport;
|
||||||
|
|
||||||
|
class UtilTest : public CPPUNIT_NS :: TestFixture{
|
||||||
|
CPPUNIT_TEST_SUITE(UtilTest);
|
||||||
|
CPPUNIT_TEST(encryptDecryptPassword);
|
||||||
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void setUp (void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void tearDown (void) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void encryptDecryptPassword() {
|
||||||
|
std::string encrypted = Util::encryptPassword("password", "key");
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("password"), Util::decryptPassword(encrypted, "key"));
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE_REGISTRATION (UtilTest);
|
|
@ -34,6 +34,8 @@
|
||||||
#include "Swiften/Serializer/PayloadSerializers/AttentionSerializer.h"
|
#include "Swiften/Serializer/PayloadSerializers/AttentionSerializer.h"
|
||||||
#include "Swiften/Parser/PayloadParsers/XHTMLIMParser.h"
|
#include "Swiften/Parser/PayloadParsers/XHTMLIMParser.h"
|
||||||
#include "Swiften/Serializer/PayloadSerializers/XHTMLIMSerializer.h"
|
#include "Swiften/Serializer/PayloadSerializers/XHTMLIMSerializer.h"
|
||||||
|
#include "Swiften/Parser/PayloadParsers/StatsParser.h"
|
||||||
|
#include "Swiften/Serializer/PayloadSerializers/StatsSerializer.h"
|
||||||
#include "transport/BlockParser.h"
|
#include "transport/BlockParser.h"
|
||||||
#include "transport/BlockSerializer.h"
|
#include "transport/BlockSerializer.h"
|
||||||
#include "Swiften/Parser/PayloadParsers/InvisibleParser.h"
|
#include "Swiften/Parser/PayloadParsers/InvisibleParser.h"
|
||||||
|
@ -90,11 +92,13 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories,
|
||||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::XHTMLIMParser>("html", "http://jabber.org/protocol/xhtml-im"));
|
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::XHTMLIMParser>("html", "http://jabber.org/protocol/xhtml-im"));
|
||||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Transport::BlockParser>("block", "urn:xmpp:block:0"));
|
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Transport::BlockParser>("block", "urn:xmpp:block:0"));
|
||||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
|
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->addPayloadSerializer(new Swift::AttentionSerializer());
|
m_server->addPayloadSerializer(new Swift::AttentionSerializer());
|
||||||
m_server->addPayloadSerializer(new Swift::XHTMLIMSerializer());
|
m_server->addPayloadSerializer(new Swift::XHTMLIMSerializer());
|
||||||
m_server->addPayloadSerializer(new Transport::BlockSerializer());
|
m_server->addPayloadSerializer(new Transport::BlockSerializer());
|
||||||
m_server->addPayloadSerializer(new Swift::InvisibleSerializer());
|
m_server->addPayloadSerializer(new Swift::InvisibleSerializer());
|
||||||
|
m_server->addPayloadSerializer(new Swift::StatsSerializer());
|
||||||
|
|
||||||
m_server->onDataRead.connect(boost::bind(&Component::handleDataRead, this, _1));
|
m_server->onDataRead.connect(boost::bind(&Component::handleDataRead, this, _1));
|
||||||
m_server->onDataWritten.connect(boost::bind(&Component::handleDataWritten, this, _1));
|
m_server->onDataWritten.connect(boost::bind(&Component::handleDataWritten, this, _1));
|
||||||
|
@ -113,11 +117,13 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories,
|
||||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::XHTMLIMParser>("html", "http://jabber.org/protocol/xhtml-im"));
|
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::XHTMLIMParser>("html", "http://jabber.org/protocol/xhtml-im"));
|
||||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Transport::BlockParser>("block", "urn:xmpp:block:0"));
|
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Transport::BlockParser>("block", "urn:xmpp:block:0"));
|
||||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
|
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->addPayloadSerializer(new Swift::AttentionSerializer());
|
m_component->addPayloadSerializer(new Swift::AttentionSerializer());
|
||||||
m_component->addPayloadSerializer(new Swift::XHTMLIMSerializer());
|
m_component->addPayloadSerializer(new Swift::XHTMLIMSerializer());
|
||||||
m_component->addPayloadSerializer(new Transport::BlockSerializer());
|
m_component->addPayloadSerializer(new Transport::BlockSerializer());
|
||||||
m_component->addPayloadSerializer(new Swift::InvisibleSerializer());
|
m_component->addPayloadSerializer(new Swift::InvisibleSerializer());
|
||||||
|
m_component->addPayloadSerializer(new Swift::StatsSerializer());
|
||||||
|
|
||||||
m_stanzaChannel = m_component->getStanzaChannel();
|
m_stanzaChannel = m_component->getStanzaChannel();
|
||||||
m_iqRouter = m_component->getIQRouter();
|
m_iqRouter = m_component->getIQRouter();
|
||||||
|
|
77
src/user.cpp
77
src/user.cpp
|
@ -43,7 +43,7 @@ namespace Transport {
|
||||||
static LoggerPtr logger = Logger::getLogger("User");
|
static LoggerPtr logger = Logger::getLogger("User");
|
||||||
|
|
||||||
User::User(const Swift::JID &jid, UserInfo &userInfo, Component *component, UserManager *userManager) {
|
User::User(const Swift::JID &jid, UserInfo &userInfo, Component *component, UserManager *userManager) {
|
||||||
m_jid = jid;
|
m_jid = jid.toBare();
|
||||||
m_data = NULL;
|
m_data = NULL;
|
||||||
|
|
||||||
m_component = component;
|
m_component = component;
|
||||||
|
@ -54,6 +54,7 @@ User::User(const Swift::JID &jid, UserInfo &userInfo, Component *component, User
|
||||||
m_connected = false;
|
m_connected = false;
|
||||||
m_readyForConnect = false;
|
m_readyForConnect = false;
|
||||||
m_ignoreDisconnect = false;
|
m_ignoreDisconnect = false;
|
||||||
|
m_resources = 0;
|
||||||
|
|
||||||
m_reconnectTimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(10000);
|
m_reconnectTimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(10000);
|
||||||
m_reconnectTimer->onTick.connect(boost::bind(&User::onConnectingTimeout, this));
|
m_reconnectTimer->onTick.connect(boost::bind(&User::onConnectingTimeout, this));
|
||||||
|
@ -96,6 +97,10 @@ Swift::JID User::getJIDWithFeature(const std::string &feature) {
|
||||||
else {
|
else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!discoInfo) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
continue;
|
continue;
|
||||||
#endif
|
#endif
|
||||||
|
@ -129,30 +134,37 @@ void User::sendCurrentPresence() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_connected) {
|
std::vector<Swift::Presence::ref> presences = m_presenceOracle->getAllPresence(m_jid);
|
||||||
Swift::Presence::ref highest = m_presenceOracle->getHighestPriorityPresence(m_jid.toBare());
|
foreach(Swift::Presence::ref presence, presences) {
|
||||||
if (highest) {
|
if (presence->getType() == Swift::Presence::Unavailable) {
|
||||||
Swift::Presence::ref response = Swift::Presence::create(highest);
|
continue;
|
||||||
response->setTo(m_jid);
|
}
|
||||||
response->setFrom(m_component->getJID());
|
|
||||||
m_component->getStanzaChannel()->sendPresence(response);
|
if (m_connected) {
|
||||||
|
Swift::Presence::ref highest = m_presenceOracle->getHighestPriorityPresence(m_jid.toBare());
|
||||||
|
if (highest) {
|
||||||
|
Swift::Presence::ref response = Swift::Presence::create(highest);
|
||||||
|
response->setTo(presence->getFrom());
|
||||||
|
response->setFrom(m_component->getJID());
|
||||||
|
m_component->getStanzaChannel()->sendPresence(response);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Swift::Presence::ref response = Swift::Presence::create();
|
||||||
|
response->setTo(presence->getFrom());
|
||||||
|
response->setFrom(m_component->getJID());
|
||||||
|
response->setType(Swift::Presence::Unavailable);
|
||||||
|
m_component->getStanzaChannel()->sendPresence(response);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Swift::Presence::ref response = Swift::Presence::create();
|
Swift::Presence::ref response = Swift::Presence::create();
|
||||||
response->setTo(m_jid.toBare());
|
response->setTo(presence->getFrom());
|
||||||
response->setFrom(m_component->getJID());
|
response->setFrom(m_component->getJID());
|
||||||
response->setType(Swift::Presence::Unavailable);
|
response->setType(Swift::Presence::Unavailable);
|
||||||
|
response->setStatus("Connecting");
|
||||||
m_component->getStanzaChannel()->sendPresence(response);
|
m_component->getStanzaChannel()->sendPresence(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
Swift::Presence::ref response = Swift::Presence::create();
|
|
||||||
response->setTo(m_jid.toBare());
|
|
||||||
response->setFrom(m_component->getJID());
|
|
||||||
response->setType(Swift::Presence::Unavailable);
|
|
||||||
response->setStatus("Connecting");
|
|
||||||
m_component->getStanzaChannel()->sendPresence(response);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void User::setConnected(bool connected) {
|
void User::setConnected(bool connected) {
|
||||||
|
@ -164,6 +176,10 @@ void User::setConnected(bool connected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void User::handlePresence(Swift::Presence::ref presence) {
|
void User::handlePresence(Swift::Presence::ref presence) {
|
||||||
|
int currentResourcesCount = m_presenceOracle->getAllPresence(m_jid).size();
|
||||||
|
|
||||||
|
m_conversationManager->resetResources();
|
||||||
|
|
||||||
if (!m_connected) {
|
if (!m_connected) {
|
||||||
// we are not connected to legacy network, so we should do it when disco#info arrive :)
|
// we are not connected to legacy network, so we should do it when disco#info arrive :)
|
||||||
if (m_readyForConnect == false) {
|
if (m_readyForConnect == false) {
|
||||||
|
@ -210,12 +226,35 @@ void User::handlePresence(Swift::Presence::ref presence) {
|
||||||
if (presence->getPayload<Swift::MUCPayload>() != NULL) {
|
if (presence->getPayload<Swift::MUCPayload>() != NULL) {
|
||||||
password = presence->getPayload<Swift::MUCPayload>()->getPassword() ? *presence->getPayload<Swift::MUCPayload>()->getPassword() : "";
|
password = presence->getPayload<Swift::MUCPayload>()->getPassword() ? *presence->getPayload<Swift::MUCPayload>()->getPassword() : "";
|
||||||
}
|
}
|
||||||
onRoomJoined(room, presence->getTo().getResource(), password);
|
onRoomJoined(presence->getFrom(), room, presence->getTo().getResource(), password);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sendCurrentPresence();
|
|
||||||
|
// User wants to disconnect this resource
|
||||||
|
if (!m_component->inServerMode()) {
|
||||||
|
if (presence->getType() == Swift::Presence::Unavailable) {
|
||||||
|
// Send unavailable presences for online contacts
|
||||||
|
m_rosterManager->sendUnavailablePresences(presence->getFrom());
|
||||||
|
|
||||||
|
// Send unavailable presence for transport contact itself
|
||||||
|
Swift::Presence::ref response = Swift::Presence::create();
|
||||||
|
response->setTo(presence->getFrom());
|
||||||
|
response->setFrom(m_component->getJID());
|
||||||
|
response->setType(Swift::Presence::Unavailable);
|
||||||
|
m_component->getStanzaChannel()->sendPresence(response);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sendCurrentPresence();
|
||||||
|
// This resource is new, so we have to send buddies presences
|
||||||
|
if (currentResourcesCount != m_resources) {
|
||||||
|
m_rosterManager->sendCurrentPresences(presence->getFrom());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_resources = currentResourcesCount;
|
||||||
|
|
||||||
|
|
||||||
// Change legacy network presence
|
// Change legacy network presence
|
||||||
|
|
|
@ -149,7 +149,7 @@ void UserManager::handlePresence(Swift::Presence::ref presence) {
|
||||||
// Create user class if it's not there
|
// Create user class if it's not there
|
||||||
if (!user) {
|
if (!user) {
|
||||||
// Admin user is not legacy network user, so do not create User class instance for him
|
// Admin user is not legacy network user, so do not create User class instance for him
|
||||||
if (CONFIG_STRING(m_component->getConfig(), "service.admin_username") == presence->getFrom().getNode()) {
|
if (m_component->inServerMode() && CONFIG_STRING(m_component->getConfig(), "service.admin_jid") == presence->getFrom().toBare().toString()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,6 +319,11 @@ void UserManager::handleSubscription(Swift::Presence::ref presence) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't let RosterManager to handle presences for us
|
||||||
|
if (presence->getTo().getNode().empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
User *user = getUser(presence->getFrom().toBare().toString());
|
User *user = getUser(presence->getFrom().toBare().toString());
|
||||||
|
|
||||||
if (user) {
|
if (user) {
|
||||||
|
|
|
@ -181,7 +181,7 @@ bool UserRegistration::handleGetRequest(const Swift::JID& from, const Swift::JID
|
||||||
bool registered = m_storageBackend->getUser(barejid, res);
|
bool registered = m_storageBackend->getUser(barejid, res);
|
||||||
|
|
||||||
std::string instructions = CONFIG_STRING(m_config, "registration.instructions");
|
std::string instructions = CONFIG_STRING(m_config, "registration.instructions");
|
||||||
std::string usernameField = CONFIG_STRING(m_config, "registration.username_field");
|
std::string usernameField = CONFIG_STRING(m_config, "registration.username_label");
|
||||||
|
|
||||||
// normal jabber:iq:register
|
// normal jabber:iq:register
|
||||||
reg->setInstructions(instructions);
|
reg->setInstructions(instructions);
|
||||||
|
@ -219,20 +219,21 @@ bool UserRegistration::handleGetRequest(const Swift::JID& from, const Swift::JID
|
||||||
ListSingleFormField::ref language = ListSingleFormField::create();
|
ListSingleFormField::ref language = ListSingleFormField::create();
|
||||||
language->setName("language");
|
language->setName("language");
|
||||||
language->setLabel((("Language")));
|
language->setLabel((("Language")));
|
||||||
|
language->addOption(Swift::FormField::Option(CONFIG_STRING(m_config, "registration.language"), CONFIG_STRING(m_config, "registration.language")));
|
||||||
if (registered)
|
if (registered)
|
||||||
language->setValue(res.language);
|
language->setValue(res.language);
|
||||||
else
|
else
|
||||||
language->setValue(CONFIG_STRING(m_config, "registration.language"));
|
language->setValue(CONFIG_STRING(m_config, "registration.language"));
|
||||||
form->addField(language);
|
form->addField(language);
|
||||||
|
|
||||||
TextSingleFormField::ref encoding = TextSingleFormField::create();
|
// TextSingleFormField::ref encoding = TextSingleFormField::create();
|
||||||
encoding->setName("encoding");
|
// encoding->setName("encoding");
|
||||||
encoding->setLabel((("Encoding")));
|
// encoding->setLabel((("Encoding")));
|
||||||
if (registered)
|
// if (registered)
|
||||||
encoding->setValue(res.encoding);
|
// encoding->setValue(res.encoding);
|
||||||
else
|
// else
|
||||||
encoding->setValue(CONFIG_STRING(m_config, "registration.encoding"));
|
// encoding->setValue(CONFIG_STRING(m_config, "registration.encoding"));
|
||||||
form->addField(encoding);
|
// form->addField(encoding);
|
||||||
|
|
||||||
if (registered) {
|
if (registered) {
|
||||||
BooleanFormField::ref boolean = BooleanFormField::create();
|
BooleanFormField::ref boolean = BooleanFormField::create();
|
||||||
|
@ -328,10 +329,7 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register or change password
|
// Register or change password
|
||||||
if (payload->getUsername()->empty() ||
|
if (payload->getUsername()->empty()) {
|
||||||
(payload->getPassword()->empty() && CONFIG_STRING(m_config, "service.protocol") != "twitter" && CONFIG_STRING(m_config, "service.protocol") != "bonjour")
|
|
||||||
)
|
|
||||||
{
|
|
||||||
sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
|
sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
28
src/util.cpp
28
src/util.cpp
|
@ -75,6 +75,34 @@ void removeEverythingOlderThan(const std::vector<std::string> &dirs, time_t t) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string encryptPassword(const std::string &password, const std::string &key) {
|
||||||
|
std::string encrypted;
|
||||||
|
encrypted.resize(password.size());
|
||||||
|
for (int i = 0; i < password.size(); i++) {
|
||||||
|
char c = password[i];
|
||||||
|
char keychar = key[i % key.size()];
|
||||||
|
c += keychar;
|
||||||
|
encrypted[i] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
encrypted = Swift::Base64::encode(Swift::createByteArray(encrypted));
|
||||||
|
return encrypted;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string decryptPassword(std::string &encrypted, const std::string &key) {
|
||||||
|
encrypted = Swift::byteArrayToString(Swift::Base64::decode(encrypted));
|
||||||
|
std::string password;
|
||||||
|
password.resize(encrypted.size());
|
||||||
|
for (int i = 0; i < encrypted.size(); i++) {
|
||||||
|
char c = encrypted[i];
|
||||||
|
char keychar = key[i % key.size()];
|
||||||
|
c -= keychar;
|
||||||
|
password[i] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
ADD_SUBDIRECTORY(login)
|
|
||||||
ADD_SUBDIRECTORY(login_bad_name)
|
|
||||||
ADD_SUBDIRECTORY(login_bad_name2)
|
|
||||||
|
|
||||||
add_custom_target(tests python runtests.py WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
|
|
@ -1,6 +0,0 @@
|
||||||
FILE(GLOB SRC *.cpp)
|
|
||||||
|
|
||||||
ADD_EXECUTABLE(login_test ${SRC})
|
|
||||||
|
|
||||||
TARGET_LINK_LIBRARIES(login_test transport ${SWIFTEN_LIBRARIES})
|
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include <boost/bind.hpp>
|
|
||||||
|
|
||||||
#include <Swiften/Swiften.h>
|
|
||||||
#include <Swiften/Client/ClientOptions.h>
|
|
||||||
|
|
||||||
using namespace Swift;
|
|
||||||
using namespace boost;
|
|
||||||
|
|
||||||
Client* client;
|
|
||||||
|
|
||||||
static void handleDisconnected(const boost::optional<ClientError> &) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handleConnected() {
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handleMessageReceived(Message::ref message) {
|
|
||||||
// Echo back the incoming message
|
|
||||||
message->setTo(message->getFrom());
|
|
||||||
message->setFrom(JID());
|
|
||||||
client->sendMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int, char **argv) {
|
|
||||||
SimpleEventLoop eventLoop;
|
|
||||||
BoostNetworkFactories networkFactories(&eventLoop);
|
|
||||||
|
|
||||||
client = new Client(argv[1], argv[2], &networkFactories);
|
|
||||||
client->setAlwaysTrustCertificates();
|
|
||||||
client->onConnected.connect(&handleConnected);
|
|
||||||
client->onDisconnected.connect(bind(&handleDisconnected, _1));
|
|
||||||
client->onMessageReceived.connect(bind(&handleMessageReceived, _1));
|
|
||||||
Swift::ClientOptions opt;
|
|
||||||
opt.allowPLAINWithoutTLS = true;
|
|
||||||
client->connect(opt);
|
|
||||||
|
|
||||||
eventLoop.run();
|
|
||||||
|
|
||||||
delete client;
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
FILE(GLOB SRC *.cpp)
|
|
||||||
|
|
||||||
ADD_EXECUTABLE(login_bad_name_test ${SRC})
|
|
||||||
|
|
||||||
TARGET_LINK_LIBRARIES(login_bad_name_test transport ${SWIFTEN_LIBRARIES})
|
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include <boost/bind.hpp>
|
|
||||||
|
|
||||||
#include <Swiften/Swiften.h>
|
|
||||||
#include <Swiften/Client/ClientOptions.h>
|
|
||||||
|
|
||||||
using namespace Swift;
|
|
||||||
using namespace boost;
|
|
||||||
|
|
||||||
Client* client;
|
|
||||||
|
|
||||||
static void handleDisconnected(const boost::optional<ClientError> &error) {
|
|
||||||
exit(error->getType() != ClientError::AuthenticationFailedError);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handleConnected() {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handleMessageReceived(Message::ref message) {
|
|
||||||
// Echo back the incoming message
|
|
||||||
message->setTo(message->getFrom());
|
|
||||||
message->setFrom(JID());
|
|
||||||
client->sendMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int, char **argv) {
|
|
||||||
SimpleEventLoop eventLoop;
|
|
||||||
BoostNetworkFactories networkFactories(&eventLoop);
|
|
||||||
|
|
||||||
JID jid(JID(argv[1]).getNode() + "something", JID(argv[1]).getDomain());
|
|
||||||
client = new Client(jid, argv[2], &networkFactories);
|
|
||||||
client->setAlwaysTrustCertificates();
|
|
||||||
client->onConnected.connect(&handleConnected);
|
|
||||||
client->onDisconnected.connect(bind(&handleDisconnected, _1));
|
|
||||||
client->onMessageReceived.connect(bind(&handleMessageReceived, _1));
|
|
||||||
Swift::ClientOptions opt;
|
|
||||||
opt.allowPLAINWithoutTLS = true;
|
|
||||||
client->connect(opt);
|
|
||||||
|
|
||||||
eventLoop.run();
|
|
||||||
|
|
||||||
delete client;
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
FILE(GLOB SRC *.cpp)
|
|
||||||
|
|
||||||
ADD_EXECUTABLE(login_bad_name2_test ${SRC})
|
|
||||||
|
|
||||||
TARGET_LINK_LIBRARIES(login_bad_name2_test transport ${SWIFTEN_LIBRARIES})
|
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include <boost/bind.hpp>
|
|
||||||
|
|
||||||
#include <Swiften/Swiften.h>
|
|
||||||
#include <Swiften/Client/ClientOptions.h>
|
|
||||||
|
|
||||||
using namespace Swift;
|
|
||||||
using namespace boost;
|
|
||||||
|
|
||||||
Client* client;
|
|
||||||
|
|
||||||
static void handleDisconnected(const boost::optional<ClientError> &error) {
|
|
||||||
exit(error->getType() != ClientError::AuthenticationFailedError);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handleConnected() {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handleMessageReceived(Message::ref message) {
|
|
||||||
// Echo back the incoming message
|
|
||||||
message->setTo(message->getFrom());
|
|
||||||
message->setFrom(JID());
|
|
||||||
client->sendMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int, char **argv) {
|
|
||||||
SimpleEventLoop eventLoop;
|
|
||||||
BoostNetworkFactories networkFactories(&eventLoop);
|
|
||||||
|
|
||||||
JID jid(std::string("something") + JID(argv[1]).getNode(), JID(argv[1]).getDomain());
|
|
||||||
client = new Client(jid, argv[2], &networkFactories);
|
|
||||||
client->setAlwaysTrustCertificates();
|
|
||||||
client->onConnected.connect(&handleConnected);
|
|
||||||
client->onDisconnected.connect(bind(&handleDisconnected, _1));
|
|
||||||
client->onMessageReceived.connect(bind(&handleMessageReceived, _1));
|
|
||||||
Swift::ClientOptions opt;
|
|
||||||
opt.allowPLAINWithoutTLS = true;
|
|
||||||
client->connect(opt);
|
|
||||||
|
|
||||||
eventLoop.run();
|
|
||||||
|
|
||||||
delete client;
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from subprocess import *
|
|
||||||
import time
|
|
||||||
|
|
||||||
def run_spectrum(backend, test):
|
|
||||||
os.system("rm test.sql")
|
|
||||||
f = open("sample.cfg", "w")
|
|
||||||
f.write("\
|
|
||||||
[service]\n\
|
|
||||||
jid = localhost\n\
|
|
||||||
password = secret\n\
|
|
||||||
server = 127.0.0.1\n\
|
|
||||||
port = 5222\n\
|
|
||||||
server_mode = 1\n\
|
|
||||||
backend=../backends/%s/%s_backend\n\
|
|
||||||
protocol=prpl-jabber\n\
|
|
||||||
\
|
|
||||||
[database]\n\
|
|
||||||
database = test.sql\n\
|
|
||||||
prefix=icq\n\
|
|
||||||
" % (backend, backend)
|
|
||||||
)
|
|
||||||
f.close()
|
|
||||||
p = Popen("../spectrum/src/spectrum sample.cfg > " + backend + "_" + test + ".log 2>&1", shell=True)
|
|
||||||
time.sleep(4)
|
|
||||||
return p
|
|
||||||
|
|
||||||
def one_test_run():
|
|
||||||
os.system("killall spectrum 2> /dev/null")
|
|
||||||
os.system("rm *.log")
|
|
||||||
|
|
||||||
for backend in os.listdir("../backends"):
|
|
||||||
if not os.path.isdir("../backends/" + backend) or backend == "CMakeFiles":
|
|
||||||
continue
|
|
||||||
|
|
||||||
for d in os.listdir("."):
|
|
||||||
binary = d + "/" + d + "_test"
|
|
||||||
if not os.path.exists(binary):
|
|
||||||
continue
|
|
||||||
|
|
||||||
if os.path.exists(d + "/.no" + backend):
|
|
||||||
continue
|
|
||||||
|
|
||||||
p = run_spectrum(backend, d)
|
|
||||||
|
|
||||||
if backend.find("purple") >= 0:
|
|
||||||
p = Popen(binary + " pyjim%jabber.cz@localhost test", shell=True)
|
|
||||||
else:
|
|
||||||
p = Popen(binary + " testnickname%irc.freenode.net@localhost test", shell=True)
|
|
||||||
|
|
||||||
seconds = 0
|
|
||||||
while p.poll() is None and seconds < 20:
|
|
||||||
time.sleep(1)
|
|
||||||
seconds += 1
|
|
||||||
|
|
||||||
if p.returncode == 0 and seconds < 20:
|
|
||||||
print "[ PASS ]", backend, binary
|
|
||||||
|
|
||||||
else:
|
|
||||||
if seconds == 20:
|
|
||||||
print "[ TIME ]", backend, binary
|
|
||||||
else:
|
|
||||||
print "[ FAIL ]", backend, binary
|
|
||||||
|
|
||||||
os.system("killall spectrum 2> /dev/null")
|
|
||||||
|
|
||||||
one_test_run()
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue