From 74cd11e265a30bc279ab64ccf8d8b0a4e7e10012 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sat, 22 Sep 2012 08:18:38 +0200 Subject: [PATCH 01/20] Fixed communi backend without irc_network option --- backends/libcommuni/ircnetworkplugin.cpp | 8 ++++++++ backends/libcommuni/session.cpp | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/backends/libcommuni/ircnetworkplugin.cpp b/backends/libcommuni/ircnetworkplugin.cpp index 85e55d25..293b8875 100644 --- a/backends/libcommuni/ircnetworkplugin.cpp +++ b/backends/libcommuni/ircnetworkplugin.cpp @@ -35,6 +35,8 @@ void IRCNetworkPlugin::handleLoginRequest(const std::string &user, const std::st MyIrcSession *session = new MyIrcSession(user, this); std::string h = user.substr(0, user.find("@")); session->setNickName(FROM_UTF8(h.substr(0, h.find("%")))); + session->setUserName(FROM_UTF8(h.substr(0, h.find("%")))); + session->setRealName(FROM_UTF8(h.substr(0, h.find("%")))); session->setHost(FROM_UTF8(h.substr(h.find("%") + 1))); session->setPort(6667); session->open(); @@ -79,6 +81,10 @@ void IRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const s } LOG4CXX_INFO(logger, user << ": Session name: " << u << ", message to " << r); m_sessions[u]->sendCommand(IrcCommand::createMessage(FROM_UTF8(r), FROM_UTF8(message))); + + if (r.find("#") == 0) { + handleMessage(user, legacyName, message, TO_UTF8(m_sessions[u]->nickName())); + } } void IRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) { @@ -96,6 +102,8 @@ void IRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std: // suffix is %irc.freenode.net to let MyIrcSession return #room%irc.freenode.net MyIrcSession *session = new MyIrcSession(user, this, room.substr(room.find("@"))); session->setNickName(FROM_UTF8(nickname)); + session->setUserName(FROM_UTF8(nickname)); + session->setRealName(FROM_UTF8(nickname)); session->setHost(FROM_UTF8(room.substr(room.find("@") + 1))); session->setPort(6667); session->open(); diff --git a/backends/libcommuni/session.cpp b/backends/libcommuni/session.cpp index 51505fb4..3799c978 100644 --- a/backends/libcommuni/session.cpp +++ b/backends/libcommuni/session.cpp @@ -161,7 +161,8 @@ void MyIrcSession::on_messageReceived(IrcMessage *message) { bool flags = 0; std::string nickname = TO_UTF8(m->sender().name()); flags = correctNickname(nickname); - np->handleMessage(user, nickname, TO_UTF8(m->message())); + LOG4CXX_INFO(logger, nickname + suffix); + np->handleMessage(user, nickname + suffix, TO_UTF8(m->message())); } } From 05e06dd845aebb0eca3a0065fbd310de42fd21fa Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sat, 22 Sep 2012 10:38:42 +0200 Subject: [PATCH 02/20] Merged SingleIrcNetworkPlugin with IrcNetworkPlugin to not duplicate code. Removed old SingleIrcNetworkPlugin. --- backends/libcommuni/ircnetworkplugin.cpp | 167 +++++++++++------- backends/libcommuni/ircnetworkplugin.h | 7 + backends/libcommuni/main.cpp | 8 +- backends/libcommuni/session.cpp | 1 + .../libcommuni/singleircnetworkplugin.cpp | 138 --------------- backends/libcommuni/singleircnetworkplugin.h | 40 ----- 6 files changed, 108 insertions(+), 253 deletions(-) delete mode 100644 backends/libcommuni/singleircnetworkplugin.cpp delete mode 100644 backends/libcommuni/singleircnetworkplugin.h diff --git a/backends/libcommuni/ircnetworkplugin.cpp b/backends/libcommuni/ircnetworkplugin.cpp index 293b8875..42b4a47d 100644 --- a/backends/libcommuni/ircnetworkplugin.cpp +++ b/backends/libcommuni/ircnetworkplugin.cpp @@ -13,6 +13,14 @@ IRCNetworkPlugin::IRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, con m_socket = new QTcpSocket(); m_socket->connectToHost(FROM_UTF8(host), port); connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData())); + + m_server = CONFIG_STRING_DEFAULTED(config, "service.irc_server", ""); + if (CONFIG_HAS_KEY(config, "service.irc_identify")) { + m_identify = CONFIG_STRING(config, "service.irc_identify"); + } + else { + m_identify = "NickServ identify $name $password"; + } } void IRCNetworkPlugin::readData() { @@ -28,122 +36,145 @@ void IRCNetworkPlugin::sendData(const std::string &string) { m_socket->write(string.c_str(), string.size()); } +MyIrcSession *IRCNetworkPlugin::createSession(const std::string &user, const std::string &hostname, const std::string &nickname, const std::string &password, const std::string &suffix) { + MyIrcSession *session = new MyIrcSession(user, this, suffix); + session->setUserName(FROM_UTF8(nickname)); + session->setNickName(FROM_UTF8(nickname)); + session->setRealName(FROM_UTF8(nickname)); + session->setHost(FROM_UTF8(hostname)); + session->setPort(6667); + session->setEncoding( "utf-8" ); + + if (!password.empty()) { + std::string identify = m_identify; + boost::replace_all(identify, "$password", password); + boost::replace_all(identify, "$name", nickname); + session->setIdentify(identify); + } + + LOG4CXX_INFO(logger, user << ": Connecting " << hostname << " as " << nickname << ", suffix=" << suffix); + + session->open(); + + return session; +} + void IRCNetworkPlugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) { - // In server mode, hostname of the server we want to connect to is stored in "user" JID. - // In component mode we will connect user to the IRC network once he joins the room. - if (CONFIG_BOOL(config, "service.server_mode")) { - MyIrcSession *session = new MyIrcSession(user, this); - std::string h = user.substr(0, user.find("@")); - session->setNickName(FROM_UTF8(h.substr(0, h.find("%")))); - session->setUserName(FROM_UTF8(h.substr(0, h.find("%")))); - session->setRealName(FROM_UTF8(h.substr(0, h.find("%")))); - session->setHost(FROM_UTF8(h.substr(h.find("%") + 1))); - session->setPort(6667); - session->open(); - LOG4CXX_INFO(logger, user << ": Connecting IRC network " << h.substr(h.find("%") + 1)); - m_sessions[user] = session; + if (!m_server.empty()) { + // legacy name is users nickname + if (m_sessions[user] != NULL) { + LOG4CXX_WARN(logger, user << ": Already logged in."); + return; + } + + m_sessions[user] = createSession(user, m_server, legacyName, password, ""); } else { + // We are waiting for first room join to connect user to IRC network, because we don't know which + // network he choose... LOG4CXX_INFO(logger, user << ": Ready for connections"); handleConnected(user); } } void IRCNetworkPlugin::handleLogoutRequest(const std::string &user, const std::string &legacyName) { - if (m_sessions[user] == NULL) + 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 IRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &/*xhtml*/) { +std::string IRCNetworkPlugin::getSessionName(const std::string &user, const std::string &legacyName) { std::string u = user; - if (!CONFIG_BOOL(config, "service.server_mode")) { + if (!CONFIG_BOOL(config, "service.server_mode") && m_server.empty()) { u = user + legacyName.substr(legacyName.find("@") + 1); if (u.find("/") != std::string::npos) { u = u.substr(0, u.find("/")); } } - if (m_sessions[u] == NULL) { - LOG4CXX_WARN(logger, user << ": Session name: " << u << ", No session for user"); - return; - } + return u; +} +std::string IRCNetworkPlugin::getTargetName(const std::string &legacyName) { std::string r = legacyName; - if (!CONFIG_BOOL(config, "service.server_mode")) { +// if (!CONFIG_BOOL(config, "service.server_mode")) { if (legacyName.find("/") == std::string::npos) { r = legacyName.substr(0, r.find("@")); } else { r = legacyName.substr(legacyName.find("/") + 1); } - } - LOG4CXX_INFO(logger, user << ": Session name: " << u << ", message to " << r); - m_sessions[u]->sendCommand(IrcCommand::createMessage(FROM_UTF8(r), FROM_UTF8(message))); +// } + return r; +} - if (r.find("#") == 0) { - handleMessage(user, legacyName, message, TO_UTF8(m_sessions[u]->nickName())); +void IRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &/*xhtml*/) { + std::string session = getSessionName(user, legacyName); + if (m_sessions[session] == NULL) { + LOG4CXX_WARN(logger, user << ": Session name: " << session << ", No session for user"); + return; + } + + std::string target = getTargetName(legacyName); + + LOG4CXX_INFO(logger, user << ": Session name: " << session << ", message to " << target); + m_sessions[session]->sendCommand(IrcCommand::createMessage(FROM_UTF8(target), FROM_UTF8(message))); + + if (target.find("#") == 0) { + handleMessage(user, legacyName, message, TO_UTF8(m_sessions[session]->nickName())); } } void IRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) { - std::string r = room; - std::string u = user; - if (!CONFIG_BOOL(config, "service.server_mode")) { - u = user + room.substr(room.find("@") + 1); - r = room.substr(0, room.find("@")); - } + std::string session = getSessionName(user, room); + std::string target = getTargetName(room); - LOG4CXX_INFO(logger, user << ": Session name: " << u << ", Joining room " << r); - if (m_sessions[u] == NULL) { - // in gateway mode we want to login this user to network according to legacyName - if (room.find("@") != std::string::npos) { - // suffix is %irc.freenode.net to let MyIrcSession return #room%irc.freenode.net - MyIrcSession *session = new MyIrcSession(user, this, room.substr(room.find("@"))); - session->setNickName(FROM_UTF8(nickname)); - session->setUserName(FROM_UTF8(nickname)); - session->setRealName(FROM_UTF8(nickname)); - session->setHost(FROM_UTF8(room.substr(room.find("@") + 1))); - session->setPort(6667); - session->open(); - LOG4CXX_INFO(logger, user << ": Connecting IRC network " << room.substr(room.find("@") + 1)); - m_sessions[u] = session; + LOG4CXX_INFO(logger, user << ": Session name: " << session << ", Joining room " << target); + if (m_sessions[session] == NULL) { + if (m_server.empty()) { + // in gateway mode we want to login this user to network according to legacyName + if (room.find("@") != std::string::npos) { + // suffix is %irc.freenode.net to let MyIrcSession return #room%irc.freenode.net + m_sessions[session] = createSession(user, room.substr(room.find("@") + 1), nickname, "", room.substr(room.find("@"))); + } + else { + LOG4CXX_WARN(logger, user << ": There's no proper server defined in room to which this user wants to join: " << room); + return; + } } else { - LOG4CXX_WARN(logger, user << ": There's no proper server defined in room to which this user wants to join: " << room); + LOG4CXX_WARN(logger, user << ": Join room requested for unconnected user"); return; } } - m_sessions[u]->addAutoJoinChannel(r, password); - m_sessions[u]->sendCommand(IrcCommand::createJoin(FROM_UTF8(r), FROM_UTF8(password))); - m_sessions[u]->rooms += 1; + m_sessions[session]->addAutoJoinChannel(target, password); + m_sessions[session]->sendCommand(IrcCommand::createJoin(FROM_UTF8(target), FROM_UTF8(password))); + m_sessions[session]->rooms += 1; // update nickname, because we have nickname per session, no nickname per room. - handleRoomNicknameChanged(user, r, TO_UTF8(m_sessions[u]->nickName())); + handleRoomNicknameChanged(user, target, TO_UTF8(m_sessions[session]->nickName())); } void IRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std::string &room) { - std::string r = room; - std::string u = user; - if (!CONFIG_BOOL(config, "service.server_mode")) { - r = room.substr(0, room.find("@")); - u = user + room.substr(room.find("@") + 1); - } + std::string session = getSessionName(user, room); + std::string target = getTargetName(room); - if (m_sessions[u] == NULL) + LOG4CXX_INFO(logger, user << ": Session name: " << session << ", Leaving room " << target); + if (m_sessions[session] == NULL) return; - LOG4CXX_INFO(logger, user << ": Session name: " << u << ", Leaving room " << r); + m_sessions[session]->sendCommand(IrcCommand::createPart(FROM_UTF8(target))); + m_sessions[session]->removeAutoJoinChannel(target); + m_sessions[session]->rooms -= 1; - m_sessions[u]->sendCommand(IrcCommand::createPart(FROM_UTF8(r))); - m_sessions[u]->removeAutoJoinChannel(r); - m_sessions[u]->rooms -= 1; - - if (m_sessions[u]->rooms <= 0) { - LOG4CXX_INFO(logger, user << ": Session name: " << u << ", User is not in room, disconnecting from network"); - m_sessions[u]->close(); - m_sessions[u]->deleteLater(); - m_sessions.erase(u); + if (m_sessions[session]->rooms <= 0 && m_server.empty()) { + LOG4CXX_INFO(logger, user << ": Session name: " << session << ", User is not in any room, disconnecting from network"); + m_sessions[session]->close(); + m_sessions[session]->deleteLater(); + m_sessions.erase(session); } } diff --git a/backends/libcommuni/ircnetworkplugin.h b/backends/libcommuni/ircnetworkplugin.h index ff77d2bc..09534425 100644 --- a/backends/libcommuni/ircnetworkplugin.h +++ b/backends/libcommuni/ircnetworkplugin.h @@ -30,8 +30,15 @@ class IRCNetworkPlugin : public QObject, public NetworkPlugin { void readData(); void sendData(const std::string &string); + private: + MyIrcSession *createSession(const std::string &user, const std::string &hostname, const std::string &nickname, const std::string &password, const std::string &suffix = ""); + std::string getSessionName(const std::string &user, const std::string &legacyName); + std::string getTargetName(const std::string &legacyName); + private: Config *config; QTcpSocket *m_socket; std::map m_sessions; + std::string m_server; + std::string m_identify; }; \ No newline at end of file diff --git a/backends/libcommuni/main.cpp b/backends/libcommuni/main.cpp index 4509b9af..99b3bc58 100644 --- a/backends/libcommuni/main.cpp +++ b/backends/libcommuni/main.cpp @@ -16,7 +16,6 @@ #include #include "Swiften/EventLoop/Qt/QtEventLoop.h" #include "ircnetworkplugin.h" -#include "singleircnetworkplugin.h" using namespace boost::program_options; using namespace Transport; @@ -40,12 +39,7 @@ int main (int argc, char* argv[]) { Swift::QtEventLoop eventLoop; - if (!CONFIG_HAS_KEY(cfg, "service.irc_server")) { - np = new IRCNetworkPlugin(cfg, &eventLoop, host, port); - } - else { - np = new SingleIRCNetworkPlugin(cfg, &eventLoop, host, port); - } + np = new IRCNetworkPlugin(cfg, &eventLoop, host, port); return app.exec(); } diff --git a/backends/libcommuni/session.cpp b/backends/libcommuni/session.cpp index 3799c978..3fe1cba1 100644 --- a/backends/libcommuni/session.cpp +++ b/backends/libcommuni/session.cpp @@ -182,6 +182,7 @@ void MyIrcSession::on_numericMessageReceived(IrcMessage *message) { channel = m->parameters().value(2); members = m->parameters().value(3).split(" "); + LOG4CXX_INFO(logger, user << ": Received members for " << TO_UTF8(channel) << suffix); for (int i = 0; i < members.size(); i++) { bool flags = 0; std::string nickname = TO_UTF8(members.at(i)); diff --git a/backends/libcommuni/singleircnetworkplugin.cpp b/backends/libcommuni/singleircnetworkplugin.cpp deleted file mode 100644 index 439d765b..00000000 --- a/backends/libcommuni/singleircnetworkplugin.cpp +++ /dev/null @@ -1,138 +0,0 @@ -#include "singleircnetworkplugin.h" -#include "transport/logging.h" -#include -#include - -#define FROM_UTF8(WHAT) QString::fromUtf8((WHAT).c_str(), (WHAT).size()) -#define TO_UTF8(WHAT) std::string((WHAT).toUtf8().data(), (WHAT).toUtf8().size()) - -DEFINE_LOGGER(logger, "SingleIRCNetworkPlugin"); - -SingleIRCNetworkPlugin::SingleIRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port) { - this->config = config; - if (CONFIG_HAS_KEY(config, "service.irc_server")) { - m_server = CONFIG_STRING(config, "service.irc_server"); - } - else { - LOG4CXX_ERROR(logger, "No [service] irc_server defined, exiting..."); - exit(-1); - } - m_socket = new QTcpSocket(); - m_socket->connectToHost(FROM_UTF8(host), port); - connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData())); - - if (CONFIG_HAS_KEY(config, "service.irc_identify")) { - m_identify = CONFIG_STRING(config, "service.irc_identify"); - } - 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(FROM_UTF8(legacyName)); - session->setNickName(FROM_UTF8(legacyName)); - session->setRealName(FROM_UTF8(legacyName)); - session->setHost(FROM_UTF8(m_server)); - session->setPort(6667); - session->setEncoding( "utf-8" ); - - if (!password.empty()) { - std::string identify = m_identify; - boost::replace_all(identify, "$password", password); - boost::replace_all(identify, "$name", legacyName); - session->setIdentify(identify); - } - - session->open(); - - 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(FROM_UTF8(r), FROM_UTF8(message))); - - if (r.find("#") == 0) { - handleMessage(user, legacyName, message, TO_UTF8(m_sessions[user]->nickName())); - } -} - -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, password); - m_sessions[user]->sendCommand(IrcCommand::createJoin(FROM_UTF8(room), FROM_UTF8(password))); - m_sessions[user]->rooms += 1; - - // update nickname, because we have nickname per session, no nickname per room. - handleRoomNicknameChanged(user, room, TO_UTF8(m_sessions[user]->userName())); -} - -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(FROM_UTF8(r))); - m_sessions[u]->removeAutoJoinChannel(r); - m_sessions[u]->rooms -= 1; -} diff --git a/backends/libcommuni/singleircnetworkplugin.h b/backends/libcommuni/singleircnetworkplugin.h deleted file mode 100644 index e80dd151..00000000 --- a/backends/libcommuni/singleircnetworkplugin.h +++ /dev/null @@ -1,40 +0,0 @@ - -#pragma once - -#include "transport/config.h" -#include "transport/networkplugin.h" -#include "session.h" -#include -#include -#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 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; -}; From 3ff7f9249074ffb9eba4cdf347185007574675fe Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sat, 22 Sep 2012 13:40:28 +0200 Subject: [PATCH 03/20] Send status code 332 when spectrum goes down --- backends/twitter/userdb.cpp | 80 ------------------------------- backends/twitter/userdb.h | 48 ------------------- src/conversation.cpp | 4 ++ src/tests/conversationmanager.cpp | 1 + 4 files changed, 5 insertions(+), 128 deletions(-) delete mode 100644 backends/twitter/userdb.cpp delete mode 100644 backends/twitter/userdb.h diff --git a/backends/twitter/userdb.cpp b/backends/twitter/userdb.cpp deleted file mode 100644 index 12719019..00000000 --- a/backends/twitter/userdb.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "userdb.h" - -#if 0 - -DEFINE_LOGGER(logger, "Twitter Backend Database"); - -UserDB::UserDB(std::string database): errMsg(0), rc(0), dbOpen(false) -{ - rc = sqlite3_open(database.c_str(), &db); - if( rc ) { - LOG4CXX_ERROR(logger, "Failed to open database" << database); - sqlite3_close(db); - exit(0); - } - - LOG4CXX_INFO(logger, "Checking if table users is present") - if(exe(std::string("select * from users limit 1;")) != SQLITE_OK) { - exe("create table users (user text primarykey, key text, secret text);"); - LOG4CXX_INFO(logger, "Created table users in the database"); - } - dbOpen = true; -} - -int UserDB::exe(std::string s_exe) -{ - data.clear(); - - //LOG4CXX_INFO(logger, "Executing: " << s_exe) - rc = sqlite3_get_table(db, s_exe.c_str(), &result, &nRow, &nCol, &errMsg); - if( rc == SQLITE_OK ) { - int col = nCol; //Skip past the headers - for(int i = 0; i < nRow; ++i) { - std::vector row; - for(int j = 0 ; j < nCol ; j++) row.push_back(result[col++]); - data.push_back(row); - } - } - sqlite3_free_table(result); - return rc; -} - -void UserDB::insert(UserData info) -{ - std::string q = "insert into users (user,key,secret) values ('" + info.user + "','" + info.accessTokenKey + "','" + info.accessTokenSecret + "');"; - if(exe(q) != SQLITE_OK) { - LOG4CXX_ERROR(logger, "Failed to insert into database!"); - exit(0); - } -} - -void UserDB::fetch(std::string user, std::vector &row) -{ - std::string q = "select key,secret from users where user='" + user + "'"; - if(exe(q) != SQLITE_OK) { - LOG4CXX_ERROR(logger, "Failed to fetch data from database!"); - exit(0); - } - row = data[0]; -} - -std::set UserDB::getRegisteredUsers() -{ - std::string q = "select user from users"; - if(exe(q) != SQLITE_OK) { - LOG4CXX_ERROR(logger, "Failed to registered users from database!"); - exit(0); - } - - std::set users; - for(int i=0 ; i -#include -#include -#include -#include "transport/logging.h" - -struct UserData -{ - std::string user; - std::string accessTokenKey; - std::string accessTokenSecret; - UserData(){} - UserData(std::string _user, std::string key, std::string secret) { - user = _user; - accessTokenKey = key; - accessTokenSecret = secret; - } -}; - -class UserDB { - private: - sqlite3 *db; - char *errMsg; - char **result; - int rc; - int nRow,nCol; - bool dbOpen; - std::vector< std::vector > data; - - public: - - UserDB (std::string database); - int exe(std::string s_exe); - void insert(UserData info); - void fetch(std::string user, std::vector &row); - std::set getRegisteredUsers(); - ~UserDB(); -}; - -#endif - - -#endif \ No newline at end of file diff --git a/src/conversation.cpp b/src/conversation.cpp index 22799776..1578d40d 100644 --- a/src/conversation.cpp +++ b/src/conversation.cpp @@ -55,6 +55,10 @@ void Conversation::destroyRoom() { Swift::MUCUserPayload *p = new Swift::MUCUserPayload (); p->addItem(item); + Swift::MUCUserPayload::StatusCode c; + c.code = 332; + p->addStatusCode(c); + presence->addPayload(boost::shared_ptr(p)); m_conversationManager->getComponent()->getStanzaChannel()->sendPresence(presence); } diff --git a/src/tests/conversationmanager.cpp b/src/tests/conversationmanager.cpp index 5d517f7c..6fd5ad44 100644 --- a/src/tests/conversationmanager.cpp +++ b/src/tests/conversationmanager.cpp @@ -293,6 +293,7 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::None, dynamic_cast(getStanza(received[0]))->getShow()); CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[0]))->getTo().toString()); CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/nickname"), dynamic_cast(getStanza(received[0]))->getFrom().toString()); + CPPUNIT_ASSERT_EQUAL(332, getStanza(received[0])->getPayload()->getStatusCodes()[0].code); } }; From 2f542b5077193babe95f89d4ada1caeb1264a195 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sat, 22 Sep 2012 18:09:25 +0200 Subject: [PATCH 04/20] Unit tests can now test more resources interaction --- include/transport/user.h | 4 +++ src/tests/basictest.cpp | 63 +++++++++++++++++++++++++++++++++++++-- src/tests/basictest.h | 7 +++++ src/tests/usermanager.cpp | 17 +++++++++++ src/user.cpp | 9 +++--- 5 files changed, 93 insertions(+), 7 deletions(-) diff --git a/include/transport/user.h b/include/transport/user.h index 4e98c4a8..11c253b0 100644 --- a/include/transport/user.h +++ b/include/transport/user.h @@ -110,6 +110,10 @@ class User : public Swift::EntityCapsProvider { return m_connected; } + int getResourceCount() { + return m_resources; + } + boost::signal onReadyToConnect; boost::signal onPresenceChanged; boost::signal onRoomJoined; diff --git a/src/tests/basictest.cpp b/src/tests/basictest.cpp index e9779f9c..9a893e7d 100644 --- a/src/tests/basictest.cpp +++ b/src/tests/basictest.cpp @@ -41,7 +41,7 @@ using namespace Transport; void BasicTest::setMeUp (void) { streamEnded = false; - std::istringstream ifs("service.server_mode = 1\nservice.jid=localhost"); + std::istringstream ifs("service.server_mode = 1\nservice.jid=localhost\nservice.more_resources=1\n"); cfg = new Config(); cfg->load(ifs); @@ -86,6 +86,7 @@ void BasicTest::setMeUp (void) { payloadSerializers->addSerializer(new Swift::GatewayPayloadSerializer()); parser = new Swift::XMPPParser(this, payloadParserFactories, factories->getXMLParserFactory()); + parser2 = new Swift::XMPPParser(this, payloadParserFactories, factories->getXMLParserFactory()); serverFromClientSession = boost::shared_ptr(new Swift::ServerFromClientSession("id", factories->getConnectionFactory()->createConnection(), payloadParserFactories, payloadSerializers, userRegistry, factories->getXMLParserFactory(), Swift::JID("user@localhost/resource"))); @@ -95,13 +96,19 @@ void BasicTest::setMeUp (void) { dynamic_cast(component->getStanzaChannel())->addSession(serverFromClientSession); parser->parse(""); + parser2->parse(""); received.clear(); + received2.clear(); receivedData.clear(); loop->processEvents(); } void BasicTest::tearMeDown (void) { dynamic_cast(component->getStanzaChannel())->removeSession(serverFromClientSession); + if (serverFromClientSession2) { + dynamic_cast(component->getStanzaChannel())->removeSession(serverFromClientSession2); + serverFromClientSession2.reset(); + } delete component; delete userRegistry; delete factories; @@ -109,29 +116,48 @@ void BasicTest::tearMeDown (void) { delete loop; delete cfg; delete parser; + delete parser2; delete storage; delete userRegistration; delete itemsResponder; received.clear(); + received2.clear(); receivedData.clear(); + receivedData2.clear(); } void BasicTest::handleDataReceived(const Swift::SafeByteArray &data) { // std::cout << safeByteArrayToString(data) << "\n"; + stream1_active = true; receivedData += safeByteArrayToString(data) + "\n"; parser->parse(safeByteArrayToString(data)); } +void BasicTest::handleDataReceived2(const Swift::SafeByteArray &data) { +// std::cout << safeByteArrayToString(data) << "\n"; + stream1_active = false; + receivedData2 += safeByteArrayToString(data) + "\n"; + parser2->parse(safeByteArrayToString(data)); +} + void BasicTest::handleStreamStart(const Swift::ProtocolHeader&) { } void BasicTest::dumpReceived() { + std::cout << "\nStream1:\n"; std::cout << receivedData << "\n"; + std::cout << "Stream2:\n"; + std::cout << receivedData2 << "\n"; } void BasicTest::handleElement(boost::shared_ptr element) { - received.push_back(element); + if (stream1_active) { + received.push_back(element); + } + else { + received2.push_back(element); + } } void BasicTest::handleStreamEnd() { @@ -159,6 +185,7 @@ Swift::Stanza *BasicTest::getStanza(boost::shared_ptr element) { void BasicTest::connectUser() { CPPUNIT_ASSERT_EQUAL(0, userManager->getUserCount()); userRegistry->isValidUserPassword(Swift::JID("user@localhost/resource"), serverFromClientSession.get(), Swift::createSafeByteArray("password")); + userRegistry->onPasswordValid(Swift::JID("user@localhost/resource")); loop->processEvents(); CPPUNIT_ASSERT_EQUAL(1, userManager->getUserCount()); @@ -173,9 +200,39 @@ void BasicTest::connectUser() { user->setConnected(true); CPPUNIT_ASSERT(user->isConnected() == true); - CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); + CPPUNIT_ASSERT_EQUAL(2, (int) received.size()); CPPUNIT_ASSERT(getStanza(received[0])->getPayload()); received.clear(); + receivedData.clear(); +} + +void BasicTest::connectSecondResource() { + serverFromClientSession2 = boost::shared_ptr(new Swift::ServerFromClientSession("id", factories->getConnectionFactory()->createConnection(), + payloadParserFactories, payloadSerializers, userRegistry, factories->getXMLParserFactory(), Swift::JID("user@localhost/resource2"))); + serverFromClientSession2->startSession(); + + serverFromClientSession2->onDataWritten.connect(boost::bind(&BasicTest::handleDataReceived2, this, _1)); + + dynamic_cast(component->getStanzaChannel())->addSession(serverFromClientSession2); + + userRegistry->isValidUserPassword(Swift::JID("user@localhost/resource2"), serverFromClientSession2.get(), Swift::createSafeByteArray("password")); + userRegistry->onPasswordValid(Swift::JID("user@localhost/resource2")); + + loop->processEvents(); + + Swift::Presence::ref response = Swift::Presence::create(); + response->setTo("localhost"); + response->setFrom("user@localhost/resource2"); + injectPresence(response); + loop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, userManager->getUserCount()); + + User *user = userManager->getUser("user@localhost"); + CPPUNIT_ASSERT(user); + CPPUNIT_ASSERT_EQUAL(2, user->getResourceCount()); + + CPPUNIT_ASSERT(getStanza(received2[1])->getPayload()); } void BasicTest::disconnectUser() { diff --git a/src/tests/basictest.h b/src/tests/basictest.h index ee4415cd..554ab5b6 100644 --- a/src/tests/basictest.h +++ b/src/tests/basictest.h @@ -205,6 +205,7 @@ class BasicTest : public Swift::XMPPParserClient { void tearMeDown (void); void handleDataReceived(const Swift::SafeByteArray &data); + void handleDataReceived2(const Swift::SafeByteArray &data); void handleStreamStart(const Swift::ProtocolHeader&); @@ -228,6 +229,7 @@ class BasicTest : public Swift::XMPPParserClient { } void connectUser(); + void connectSecondResource(); void disconnectUser(); void add2Buddies(); @@ -237,9 +239,11 @@ class BasicTest : public Swift::XMPPParserClient { bool streamEnded; UserManager *userManager; boost::shared_ptr serverFromClientSession; + boost::shared_ptr serverFromClientSession2; Swift::FullPayloadSerializerCollection* payloadSerializers; Swift::FullPayloadParserFactoryCollection* payloadParserFactories; Swift::XMPPParser *parser; + Swift::XMPPParser *parser2; UserRegistry *userRegistry; Config *cfg; Swift::Server *server; @@ -248,9 +252,12 @@ class BasicTest : public Swift::XMPPParserClient { TestingFactory *factory; Component *component; std::vector > received; + std::vector > received2; std::string receivedData; + std::string receivedData2; StorageBackend *storage; UserRegistration *userRegistration; DiscoItemsResponder *itemsResponder; + bool stream1_active; }; diff --git a/src/tests/usermanager.cpp b/src/tests/usermanager.cpp index 80a78cf7..1f03575d 100644 --- a/src/tests/usermanager.cpp +++ b/src/tests/usermanager.cpp @@ -23,6 +23,7 @@ using namespace Transport; class UserManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest { CPPUNIT_TEST_SUITE(UserManagerTest); CPPUNIT_TEST(connectUser); + CPPUNIT_TEST(connectTwoResources); CPPUNIT_TEST(connectUserTransportDisabled); CPPUNIT_TEST(connectUserRegistrationNeeded); CPPUNIT_TEST(connectUserRegistrationNeededRegistered); @@ -86,6 +87,22 @@ class UserManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest { CPPUNIT_ASSERT_EQUAL(Swift::Presence::Unavailable, presence->getType()); } + void connectTwoResources() { + connectUser(); + add2Buddies(); + connectSecondResource(); + + // we should get presences + CPPUNIT_ASSERT_EQUAL(4, (int) received2.size()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received2[2]))); + CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast(getStanza(received2[2]))->getShow()); + CPPUNIT_ASSERT_EQUAL(std::string("status1"), dynamic_cast(getStanza(received2[2]))->getStatus()); + + CPPUNIT_ASSERT(dynamic_cast(getStanza(received2[3]))); + CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast(getStanza(received2[3]))->getShow()); + CPPUNIT_ASSERT_EQUAL(std::string("status2"), dynamic_cast(getStanza(received2[3]))->getStatus()); + } + }; CPPUNIT_TEST_SUITE_REGISTRATION (UserManagerTest); diff --git a/src/user.cpp b/src/user.cpp index 56f53f72..242afbba 100644 --- a/src/user.cpp +++ b/src/user.cpp @@ -266,13 +266,14 @@ void User::handlePresence(Swift::Presence::ref presence) { } else { sendCurrentPresence(); - // This resource is new, so we have to send buddies presences - if (currentResourcesCount != m_resources) { - m_rosterManager->sendCurrentPresences(presence->getFrom()); - } } } + // This resource is new, so we have to send buddies presences + if (presence->getType() != Swift::Presence::Unavailable && currentResourcesCount != m_resources) { + m_rosterManager->sendCurrentPresences(presence->getFrom()); + } + m_resources = currentResourcesCount; From 88607aff3c0b7df575536c988cbf9a26b407eea6 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sat, 22 Sep 2012 20:19:19 +0200 Subject: [PATCH 05/20] Do not disconnect from room when user uses two clients and shutdown one. --- include/transport/conversation.h | 13 +++++++ src/conversation.cpp | 14 ++++--- src/networkpluginserver.cpp | 2 +- src/tests/conversationmanager.cpp | 4 +- src/tests/user.cpp | 63 +++++++++++++++++++++++++++++++ src/user.cpp | 19 ++++++++-- 6 files changed, 104 insertions(+), 11 deletions(-) diff --git a/include/transport/conversation.h b/include/transport/conversation.h index d228099f..7e477ebd 100644 --- a/include/transport/conversation.h +++ b/include/transport/conversation.h @@ -82,6 +82,18 @@ class Conversation { m_jid = jid; } + void addJID(const Swift::JID &jid) { + m_jids.push_back(jid); + } + + void removeJID(const Swift::JID &jid) { + m_jids.remove(jid); + } + + const std::list &getJIDs() { + return m_jids; + } + /// Sends message to Legacy network. /// \param message Message. @@ -123,6 +135,7 @@ class Conversation { std::string m_room; bool m_muc; Swift::JID m_jid; + std::list m_jids; }; } diff --git a/src/conversation.cpp b/src/conversation.cpp index 1578d40d..770a219e 100644 --- a/src/conversation.cpp +++ b/src/conversation.cpp @@ -115,9 +115,11 @@ void Conversation::handleMessage(boost::shared_ptr &message, con if (n.empty()) { n = " "; } - message->setTo(m_jid); - message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), n)); - m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message); + BOOST_FOREACH(const Swift::JID &jid, m_jids) { + message->setTo(jid); + message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), n)); + m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message); + } } } @@ -131,7 +133,6 @@ void Conversation::handleParticipantChanged(const std::string &nick, int flag, i } } presence->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), nickname)); - presence->setTo(m_jid); presence->setType(Swift::Presence::Available); if (!statusMessage.empty()) @@ -174,7 +175,10 @@ void Conversation::handleParticipantChanged(const std::string &nick, int flag, i p->addItem(item); presence->addPayload(boost::shared_ptr(p)); - m_conversationManager->getComponent()->getStanzaChannel()->sendPresence(presence); + BOOST_FOREACH(const Swift::JID &jid, m_jids) { + presence->setTo(jid); + m_conversationManager->getComponent()->getStanzaChannel()->sendPresence(presence); + } if (!newname.empty()) { handleParticipantChanged(newname, flag, status, statusMessage); } diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index 0c133a2c..04b7ff2a 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -1192,7 +1192,7 @@ void NetworkPluginServer::handleRoomJoined(User *user, const Swift::JID &who, co user->getConversationManager()->addConversation(conv); conv->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, this, _1, _2)); conv->setNickname(nickname); - conv->setJID(who); + conv->addJID(who); } void NetworkPluginServer::handleRoomLeft(User *user, const std::string &r) { diff --git a/src/tests/conversationmanager.cpp b/src/tests/conversationmanager.cpp index 6fd5ad44..a9ff8011 100644 --- a/src/tests/conversationmanager.cpp +++ b/src/tests/conversationmanager.cpp @@ -158,7 +158,7 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe user->getConversationManager()->addConversation(conv); conv->onMessageToSend.connect(boost::bind(&ConversationManagerTest::handleMessageReceived, this, _1, _2)); conv->setNickname("nickname"); - conv->setJID("user@localhost/resource"); + conv->addJID("user@localhost/resource"); // reset resources should not touch this resource user->getConversationManager()->resetResources(); @@ -197,7 +197,7 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe conv->onMessageToSend.connect(boost::bind(&ConversationManagerTest::handleMessageReceived, this, _1, _2)); conv->setNickname("nickname"); - conv->setJID("user@localhost/resource"); + conv->addJID("user@localhost/resource"); // normal presence conv->handleParticipantChanged("anotheruser", 0, Swift::StatusShow::Away, "my status message"); diff --git a/src/tests/user.cpp b/src/tests/user.cpp index 114da87b..ac92dc64 100644 --- a/src/tests/user.cpp +++ b/src/tests/user.cpp @@ -25,7 +25,9 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { CPPUNIT_TEST(sendCurrentPresence); CPPUNIT_TEST(handlePresence); CPPUNIT_TEST(handlePresenceJoinRoom); + CPPUNIT_TEST(handlePresenceJoinRoomTwoResources); CPPUNIT_TEST(handlePresenceLeaveRoom); + CPPUNIT_TEST(handlePresenceLeaveRoomTwoResources); CPPUNIT_TEST(leaveJoinedRoom); CPPUNIT_TEST(handleDisconnected); CPPUNIT_TEST(handleDisconnectedReconnect); @@ -139,6 +141,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { // simulate that backend joined the room TestingConversation *conv = new TestingConversation(user->getConversationManager(), "#room", true); + conv->addJID("user@localhost/resource"); user->getConversationManager()->addConversation(conv); received.clear(); @@ -154,6 +157,24 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword); } + void handlePresenceJoinRoomTwoResources() { + handlePresenceJoinRoom(); + connectSecondResource(); + Swift::Presence::ref response = Swift::Presence::create(); + response->setTo("#room@localhost/hanzz"); + response->setFrom("user@localhost/resource2"); + + Swift::MUCPayload *payload = new Swift::MUCPayload(); + payload->setPassword("password"); + response->addPayload(boost::shared_ptr(payload)); + injectPresence(response); + loop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(std::string(""), room); + CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname); + CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword); + } + void handlePresenceLeaveRoom() { Swift::Presence::ref response = Swift::Presence::create(); response->setTo("#room@localhost/hanzz"); @@ -173,6 +194,48 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword); } + void handlePresenceLeaveRoomTwoResources() { + handlePresenceJoinRoomTwoResources(); + received.clear(); + + // User is still connected from resource2, so he should not leave the room + Swift::Presence::ref response = Swift::Presence::create(); + response->setTo("#room@localhost/hanzz"); + response->setFrom("user@localhost/resource"); + response->setType(Swift::Presence::Unavailable); + + Swift::MUCPayload *payload = new Swift::MUCPayload(); + payload->setPassword("password"); + response->addPayload(boost::shared_ptr(payload)); + injectPresence(response); + loop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(0, (int) received.size()); + + CPPUNIT_ASSERT_EQUAL(std::string(""), room); + CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname); + CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword); + + // disconnect also from resource + // User is still connected from resource2, so he should not leave the room + response = Swift::Presence::create(); + response->setTo("#room@localhost/hanzz"); + response->setFrom("user@localhost/resource2"); + response->setType(Swift::Presence::Unavailable); + + payload = new Swift::MUCPayload(); + payload->setPassword("password"); + response->addPayload(boost::shared_ptr(payload)); + injectPresence(response); + loop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(0, (int) received.size()); + + CPPUNIT_ASSERT_EQUAL(std::string("#room"), room); + CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname); + CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword); + } + void leaveJoinedRoom() { User *user = userManager->getUser("user@localhost"); handlePresenceJoinRoom(); diff --git a/src/user.cpp b/src/user.cpp index 242afbba..82095c5a 100644 --- a/src/user.cpp +++ b/src/user.cpp @@ -218,10 +218,17 @@ void User::handlePresence(Swift::Presence::ref presence) { if (isMUC) { if (presence->getType() == Swift::Presence::Unavailable) { std::string room = Buddy::JIDToLegacyName(presence->getTo()); + Conversation *conv = m_conversationManager->getConversation(room); + if (conv) { + conv->removeJID(presence->getFrom()); + if (!conv->getJIDs().empty()) { + return; + } + } + LOG4CXX_INFO(logger, m_jid.toString() << ": Going to left room " << room); onRoomLeft(room); - Conversation *conv = m_conversationManager->getConversation(room); if (conv) { m_conversationManager->removeConversation(conv); delete conv; @@ -235,8 +242,14 @@ void User::handlePresence(Swift::Presence::ref presence) { onReadyToConnect(); } std::string room = Buddy::JIDToLegacyName(presence->getTo()); - if (m_conversationManager->getConversation(room) != NULL) { - LOG4CXX_INFO(logger, m_jid.toString() << ": User has already tried to join room " << room << " as " << presence->getTo().getResource()); + Conversation *conv = m_conversationManager->getConversation(room); + if (conv != NULL) { + if (std::find(conv->getJIDs().begin(), conv->getJIDs().end(), presence->getFrom()) != conv->getJIDs().end()) { + LOG4CXX_INFO(logger, m_jid.toString() << ": User has already tried to join room " << room << " as " << presence->getTo().getResource()); + } + else { + conv->addJID(presence->getFrom()); + } return; } From 1055c577d2d386050ccffe6bf2502106e3860b54 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sun, 23 Sep 2012 09:48:03 +0200 Subject: [PATCH 06/20] Send participants to second resource when it joins the room --- include/transport/conversation.h | 12 ++++++ src/conversation.cpp | 29 ++++++++++++- src/tests/conversationmanager.cpp | 69 +++++++++++++++++++++++++++++++ src/tests/user.cpp | 18 ++++++++ src/user.cpp | 1 + 5 files changed, 127 insertions(+), 2 deletions(-) diff --git a/include/transport/conversation.h b/include/transport/conversation.h index 7e477ebd..e137b566 100644 --- a/include/transport/conversation.h +++ b/include/transport/conversation.h @@ -34,6 +34,12 @@ class ConversationManager; /// Represents one XMPP-Legacy network conversation. class Conversation { public: + typedef struct _Participant { + int flag; + int status; + std::string statusMessage; + } Participant; + /// Type of participants in MUC rooms. enum ParticipantFlag {None, Moderator}; @@ -128,6 +134,11 @@ class Conversation { void destroyRoom(); + void sendParticipants(const Swift::JID &to); + + private: + Swift::Presence::ref generatePresence(const std::string &nick, int flag, int status, const std::string &statusMessage, const std::string &newname = ""); + private: ConversationManager *m_conversationManager; std::string m_legacyName; @@ -136,6 +147,7 @@ class Conversation { bool m_muc; Swift::JID m_jid; std::list m_jids; + std::map m_participants; }; } diff --git a/src/conversation.cpp b/src/conversation.cpp index 770a219e..f6105461 100644 --- a/src/conversation.cpp +++ b/src/conversation.cpp @@ -123,7 +123,15 @@ void Conversation::handleMessage(boost::shared_ptr &message, con } } -void Conversation::handleParticipantChanged(const std::string &nick, int flag, int status, const std::string &statusMessage, const std::string &newname) { +void Conversation::sendParticipants(const Swift::JID &to) { + for (std::map::iterator it = m_participants.begin(); it != m_participants.end(); it++) { + Swift::Presence::ref presence = generatePresence(it->first, it->second.flag, it->second.status, it->second.statusMessage, ""); + presence->setTo(to); + m_conversationManager->getComponent()->getStanzaChannel()->sendPresence(presence); + } +} + +Swift::Presence::ref Conversation::generatePresence(const std::string &nick, int flag, int status, const std::string &statusMessage, const std::string &newname) { std::string nickname = nick; Swift::Presence::ref presence = Swift::Presence::create(); std::string legacyName = m_legacyName; @@ -173,8 +181,25 @@ void Conversation::handleParticipantChanged(const std::string &nick, int flag, i } p->addItem(item); - presence->addPayload(boost::shared_ptr(p)); + return presence; +} + +void Conversation::handleParticipantChanged(const std::string &nick, int flag, int status, const std::string &statusMessage, const std::string &newname) { + Swift::Presence::ref presence = generatePresence(nick, flag, status, statusMessage, newname); + + if (presence->getType() == Swift::Presence::Unavailable) { + m_participants.erase(nick); + } + else { + Participant p; + p.flag = flag; + p.status = status; + p.statusMessage = statusMessage; + m_participants[nick] = p; + } + + BOOST_FOREACH(const Swift::JID &jid, m_jids) { presence->setTo(jid); m_conversationManager->getComponent()->getStanzaChannel()->sendPresence(presence); diff --git a/src/tests/conversationmanager.cpp b/src/tests/conversationmanager.cpp index a9ff8011..a997f6d5 100644 --- a/src/tests/conversationmanager.cpp +++ b/src/tests/conversationmanager.cpp @@ -25,8 +25,10 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe CPPUNIT_TEST_SUITE(ConversationManagerTest); CPPUNIT_TEST(handleNormalMessages); CPPUNIT_TEST(handleGroupchatMessages); + CPPUNIT_TEST(handleGroupchatMessagesTwoResources); CPPUNIT_TEST(handleChatstateMessages); CPPUNIT_TEST(handleParticipantChanged); + CPPUNIT_TEST(handleParticipantChangedTwoResources); CPPUNIT_TEST(handlePMFromXMPP); CPPUNIT_TEST(handleGroupchatRemoved); CPPUNIT_TEST_SUITE_END(); @@ -191,6 +193,48 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe CPPUNIT_ASSERT_EQUAL(std::string("response!"), m_msg->getBody()); } + void handleGroupchatMessagesTwoResources() { + connectSecondResource(); + received2.clear(); + User *user = userManager->getUser("user@localhost"); + TestingConversation *conv = new TestingConversation(user->getConversationManager(), "#room", true); + user->getConversationManager()->addConversation(conv); + conv->onMessageToSend.connect(boost::bind(&ConversationManagerTest::handleMessageReceived, this, _1, _2)); + conv->setNickname("nickname"); + conv->addJID("user@localhost/resource"); + conv->addJID("user@localhost/resource2"); + + // reset resources should not touch this resource + user->getConversationManager()->resetResources(); + + boost::shared_ptr msg(new Swift::Message()); + msg->setBody("hi there!"); + + // Forward it + conv->handleMessage(msg, "anotheruser"); + + loop->processEvents(); + CPPUNIT_ASSERT_EQUAL(1, (int) received2.size()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received2[0]))); + CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast(getStanza(received2[0]))->getBody()); + CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource2"), dynamic_cast(getStanza(received2[0]))->getTo().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received2[0]))->getFrom().toString()); + + received.clear(); + + // send response + msg->setFrom("user@localhost/resource2"); + msg->setTo("#room@localhost"); + msg->setBody("response!"); + msg->setType(Swift::Message::Groupchat); + injectMessage(msg); + loop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(0, (int) received.size()); + CPPUNIT_ASSERT(m_msg); + CPPUNIT_ASSERT_EQUAL(std::string("response!"), m_msg->getBody()); + } + void handleParticipantChanged() { User *user = userManager->getUser("user@localhost"); TestingConversation *conv = new TestingConversation(user->getConversationManager(), "#room", true); @@ -246,6 +290,31 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe CPPUNIT_ASSERT_EQUAL(303, getStanza(received[0])->getPayload()->getStatusCodes()[0].code); } + void handleParticipantChangedTwoResources() { + connectSecondResource(); + received2.clear(); + User *user = userManager->getUser("user@localhost"); + TestingConversation *conv = new TestingConversation(user->getConversationManager(), "#room", true); + + conv->onMessageToSend.connect(boost::bind(&ConversationManagerTest::handleMessageReceived, this, _1, _2)); + conv->setNickname("nickname"); + conv->addJID("user@localhost/resource"); + conv->addJID("user@localhost/resource2"); + + // normal presence + conv->handleParticipantChanged("anotheruser", 0, Swift::StatusShow::Away, "my status message"); + loop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, (int) received2.size()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received2[0]))); + CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast(getStanza(received2[0]))->getShow()); + CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource2"), dynamic_cast(getStanza(received2[0]))->getTo().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received2[0]))->getFrom().toString()); + CPPUNIT_ASSERT(getStanza(received2[0])->getPayload()); + CPPUNIT_ASSERT_EQUAL(Swift::MUCOccupant::Member, *getStanza(received2[0])->getPayload()->getItems()[0].affiliation); + CPPUNIT_ASSERT_EQUAL(Swift::MUCOccupant::Participant, *getStanza(received2[0])->getPayload()->getItems()[0].role); + } + void handlePMFromXMPP() { User *user = userManager->getUser("user@localhost"); TestingConversation *conv = new TestingConversation(user->getConversationManager(), "#room", true); diff --git a/src/tests/user.cpp b/src/tests/user.cpp index ac92dc64..7b761ca9 100644 --- a/src/tests/user.cpp +++ b/src/tests/user.cpp @@ -159,7 +159,15 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { void handlePresenceJoinRoomTwoResources() { handlePresenceJoinRoom(); + User *user = userManager->getUser("user@localhost"); + + // Add 1 participant + Conversation *conv = user->getConversationManager()->getConversation("#room"); + conv->handleParticipantChanged("anotheruser", 0, Swift::StatusShow::Away, "my status message"); + + // Connect 2nd resource connectSecondResource(); + received2.clear(); Swift::Presence::ref response = Swift::Presence::create(); response->setTo("#room@localhost/hanzz"); response->setFrom("user@localhost/resource2"); @@ -173,6 +181,16 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { CPPUNIT_ASSERT_EQUAL(std::string(""), room); CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname); CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword); + + dumpReceived(); + CPPUNIT_ASSERT_EQUAL(2, (int) received2.size()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received2[1]))); + CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast(getStanza(received2[1]))->getShow()); + CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource2"), dynamic_cast(getStanza(received2[1]))->getTo().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received2[1]))->getFrom().toString()); + CPPUNIT_ASSERT(getStanza(received2[1])->getPayload()); + CPPUNIT_ASSERT_EQUAL(Swift::MUCOccupant::Member, *getStanza(received2[1])->getPayload()->getItems()[0].affiliation); + CPPUNIT_ASSERT_EQUAL(Swift::MUCOccupant::Participant, *getStanza(received2[1])->getPayload()->getItems()[0].role); } void handlePresenceLeaveRoom() { diff --git a/src/user.cpp b/src/user.cpp index 82095c5a..ac37f799 100644 --- a/src/user.cpp +++ b/src/user.cpp @@ -249,6 +249,7 @@ void User::handlePresence(Swift::Presence::ref presence) { } else { conv->addJID(presence->getFrom()); + conv->sendParticipants(presence->getFrom()); } return; } From af6b0137485a46293c19ccf22a147a69f743ef3a Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sun, 23 Sep 2012 09:50:22 +0200 Subject: [PATCH 07/20] Remove forgotten dumpReceived from test --- src/tests/user.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tests/user.cpp b/src/tests/user.cpp index 7b761ca9..5755ad0d 100644 --- a/src/tests/user.cpp +++ b/src/tests/user.cpp @@ -182,7 +182,6 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname); CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword); - dumpReceived(); CPPUNIT_ASSERT_EQUAL(2, (int) received2.size()); CPPUNIT_ASSERT(dynamic_cast(getStanza(received2[1]))); CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast(getStanza(received2[1]))->getShow()); From eb1df41b3ea2729151376acff6ef723e434dc1c8 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Mon, 24 Sep 2012 15:40:41 +0200 Subject: [PATCH 08/20] Set subject on IRC --- backends/libcommuni/ircnetworkplugin.cpp | 11 ++++++++ backends/libcommuni/ircnetworkplugin.h | 2 ++ include/transport/networkplugin.h | 2 ++ plugin/cpp/networkplugin.cpp | 13 ++++++++++ src/networkpluginserver.cpp | 16 ++++++++++++ src/tests/conversationmanager.cpp | 33 ++++++++++++++++++++++++ src/usermanager.cpp | 2 +- 7 files changed, 78 insertions(+), 1 deletion(-) diff --git a/backends/libcommuni/ircnetworkplugin.cpp b/backends/libcommuni/ircnetworkplugin.cpp index 42b4a47d..57e7d289 100644 --- a/backends/libcommuni/ircnetworkplugin.cpp +++ b/backends/libcommuni/ircnetworkplugin.cpp @@ -129,6 +129,17 @@ void IRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const s } } +void IRCNetworkPlugin::handleRoomSubjectChangedRequest(const std::string &user, const std::string &room, const std::string &message) { + std::string session = getSessionName(user, room); + if (m_sessions[session] == NULL) { + LOG4CXX_WARN(logger, user << ": Session name: " << session << ", No session for user"); + return; + } + + std::string target = getTargetName(room); + m_sessions[session]->sendCommand(IrcCommand::createTopic(FROM_UTF8(target), FROM_UTF8(message))); +} + void IRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) { std::string session = getSessionName(user, room); std::string target = getTargetName(room); diff --git a/backends/libcommuni/ircnetworkplugin.h b/backends/libcommuni/ircnetworkplugin.h index 09534425..c2925b77 100644 --- a/backends/libcommuni/ircnetworkplugin.h +++ b/backends/libcommuni/ircnetworkplugin.h @@ -26,6 +26,8 @@ class IRCNetworkPlugin : public QObject, public NetworkPlugin { void handleLeaveRoomRequest(const std::string &user, const std::string &room); + void handleRoomSubjectChangedRequest(const std::string &user, const std::string &room, const std::string &message); + public slots: void readData(); void sendData(const std::string &string); diff --git a/include/transport/networkplugin.h b/include/transport/networkplugin.h index b565f43a..ea594225 100644 --- a/include/transport/networkplugin.h +++ b/include/transport/networkplugin.h @@ -218,6 +218,7 @@ class NetworkPlugin { /// \param photo Raw photo data. virtual void handleVCardUpdatedRequest(const std::string &/*user*/, const std::string &/*photo*/, const std::string &nickname) {} + virtual void handleRoomSubjectChangedRequest(const std::string &/*user*/, const std::string &/*room*/, const std::string &/*message*/) {} virtual void handleJoinRoomRequest(const std::string &/*user*/, const std::string &/*room*/, const std::string &/*nickname*/, const std::string &/*pasword*/) {} virtual void handleLeaveRoomRequest(const std::string &/*user*/, const std::string &/*room*/) {} @@ -260,6 +261,7 @@ class NetworkPlugin { void handleFTFinishPayload(const std::string &payload); void handleFTPausePayload(const std::string &payload); void handleFTContinuePayload(const std::string &payload); + void handleRoomSubjectChangedPayload(const std::string &payload); void send(const std::string &data); void sendPong(); diff --git a/plugin/cpp/networkplugin.cpp b/plugin/cpp/networkplugin.cpp index 6b289cd5..eba6dcff 100644 --- a/plugin/cpp/networkplugin.cpp +++ b/plugin/cpp/networkplugin.cpp @@ -374,6 +374,16 @@ void NetworkPlugin::handleConvMessagePayload(const std::string &data) { handleMessageSendRequest(payload.username(), payload.buddyname(), payload.message(), payload.xhtml()); } +void NetworkPlugin::handleRoomSubjectChangedPayload(const std::string &data) { + pbnetwork::ConversationMessage payload; + if (payload.ParseFromString(data) == false) { + // TODO: ERROR + return; + } + + handleRoomSubjectChangedRequest(payload.username(), payload.buddyname(), payload.message()); +} + void NetworkPlugin::handleAttentionPayload(const std::string &data) { pbnetwork::ConversationMessage payload; if (payload.ParseFromString(data) == false) { @@ -550,6 +560,9 @@ void NetworkPlugin::handleDataRead(std::string &data) { case pbnetwork::WrapperMessage_Type_TYPE_CONV_MESSAGE: handleConvMessagePayload(wrapper.payload()); break; + case pbnetwork::WrapperMessage_Type_TYPE_ROOM_SUBJECT_CHANGED: + handleRoomSubjectChangedPayload(wrapper.payload()); + break; case pbnetwork::WrapperMessage_Type_TYPE_JOIN_ROOM: handleJoinRoomPayload(wrapper.payload()); break; diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index 04b7ff2a..72179d98 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -1301,6 +1301,22 @@ void NetworkPluginServer::handleMessageReceived(NetworkConversation *conv, boost send(c->connection, message); return; } + + if (!msg->getSubject().empty()) { + pbnetwork::ConversationMessage m; + m.set_username(conv->getConversationManager()->getUser()->getJID().toBare()); + m.set_buddyname(conv->getLegacyName()); + m.set_message(msg->getSubject()); + + std::string message; + m.SerializeToString(&message); + + WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_ROOM_SUBJECT_CHANGED); + + Backend *c = (Backend *) conv->getConversationManager()->getUser()->getData(); + send(c->connection, message); + return; + } std::string xhtml; diff --git a/src/tests/conversationmanager.cpp b/src/tests/conversationmanager.cpp index a997f6d5..9aa739fa 100644 --- a/src/tests/conversationmanager.cpp +++ b/src/tests/conversationmanager.cpp @@ -27,6 +27,7 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe CPPUNIT_TEST(handleGroupchatMessages); CPPUNIT_TEST(handleGroupchatMessagesTwoResources); CPPUNIT_TEST(handleChatstateMessages); + CPPUNIT_TEST(handleSubjectMessages); CPPUNIT_TEST(handleParticipantChanged); CPPUNIT_TEST(handleParticipantChangedTwoResources); CPPUNIT_TEST(handlePMFromXMPP); @@ -91,6 +92,38 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe received.clear(); } + void handleSubjectMessages() { + User *user = userManager->getUser("user@localhost"); + + TestingConversation *conv = new TestingConversation(user->getConversationManager(), "buddy1"); + user->getConversationManager()->addConversation(conv); + conv->onMessageToSend.connect(boost::bind(&ConversationManagerTest::handleMessageReceived, this, _1, _2)); + + boost::shared_ptr msg(new Swift::Message()); + msg->setSubject("subject"); + + // Forward it + conv->handleMessage(msg); + loop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[0]))); + CPPUNIT_ASSERT_EQUAL(std::string("subject"), dynamic_cast(getStanza(received[0]))->getSubject()); + received.clear(); + + // send response + msg->setFrom("user@localhost/resource"); + msg->setTo("buddy1@localhost/bot"); + injectMessage(msg); + loop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(0, (int) received.size()); + CPPUNIT_ASSERT(m_msg); + CPPUNIT_ASSERT_EQUAL(std::string("subject"), m_msg->getSubject()); + + received.clear(); + } + void handleNormalMessages() { User *user = userManager->getUser("user@localhost"); diff --git a/src/usermanager.cpp b/src/usermanager.cpp index ebbfb2d1..4342a214 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -340,7 +340,7 @@ void UserManager::handleMessageReceived(Swift::Message::ref message) { messageToBackendSent(); } - if (message->getBody().empty() && !statePayload) { + if (message->getBody().empty() && !statePayload && message->getSubject().empty()) { return; } From 4100b4caf8afe999dafc1720db900f63e0d1ecfc Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Tue, 25 Sep 2012 12:48:30 +0200 Subject: [PATCH 09/20] Remove resource from room when the client disconnects without disconnecting the rooms --- include/transport/conversationmanager.h | 1 + src/conversationmanager.cpp | 6 ++++++ src/tests/user.cpp | 24 ++++++++++++++++++++++++ src/user.cpp | 4 ++++ 4 files changed, 35 insertions(+) diff --git a/include/transport/conversationmanager.h b/include/transport/conversationmanager.h index 44c81888..016914c8 100644 --- a/include/transport/conversationmanager.h +++ b/include/transport/conversationmanager.h @@ -70,6 +70,7 @@ class ConversationManager { void removeConversation(Conversation *conv); void resetResources(); + void removeJID(const Swift::JID &jid); private: void handleMessageReceived(Swift::Message::ref message); diff --git a/src/conversationmanager.cpp b/src/conversationmanager.cpp index 2089238e..4fc23afc 100644 --- a/src/conversationmanager.cpp +++ b/src/conversationmanager.cpp @@ -89,6 +89,12 @@ void ConversationManager::resetResources() { } } +void ConversationManager::removeJID(const Swift::JID &jid) { + for (std::map::const_iterator it = m_convs.begin(); it != m_convs.end(); it++) { + (*it).second->removeJID(jid); + } +} + void ConversationManager::handleMessageReceived(Swift::Message::ref message) { // std::string name = message->getTo().getUnescapedNode(); // if (name.find_last_of("%") != std::string::npos) { // OK when commented diff --git a/src/tests/user.cpp b/src/tests/user.cpp index 5755ad0d..bbafedbb 100644 --- a/src/tests/user.cpp +++ b/src/tests/user.cpp @@ -28,6 +28,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { CPPUNIT_TEST(handlePresenceJoinRoomTwoResources); CPPUNIT_TEST(handlePresenceLeaveRoom); CPPUNIT_TEST(handlePresenceLeaveRoomTwoResources); + CPPUNIT_TEST(handlePresenceLeaveRoomTwoResourcesOneDisconnects); CPPUNIT_TEST(leaveJoinedRoom); CPPUNIT_TEST(handleDisconnected); CPPUNIT_TEST(handleDisconnectedReconnect); @@ -253,6 +254,29 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword); } + void handlePresenceLeaveRoomTwoResourcesOneDisconnects() { + handlePresenceJoinRoomTwoResources(); + received.clear(); + User *user = userManager->getUser("user@localhost"); + + // User is still connected from resource2, so he should not leave the room + Swift::Presence::ref response = Swift::Presence::create(); + response->setTo("localhost/hanzz"); + response->setFrom("user@localhost/resource"); + response->setType(Swift::Presence::Unavailable); + injectPresence(response); + loop->processEvents(); + + + CPPUNIT_ASSERT_EQUAL(std::string(""), room); + CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname); + CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword); + + Conversation *conv = user->getConversationManager()->getConversation("#room"); + CPPUNIT_ASSERT_EQUAL(1, (int) conv->getJIDs().size()); + CPPUNIT_ASSERT_EQUAL(Swift::JID("user@localhost/resource2"), conv->getJIDs().front()); + } + void leaveJoinedRoom() { User *user = userManager->getUser("user@localhost"); handlePresenceJoinRoom(); diff --git a/src/user.cpp b/src/user.cpp index ac37f799..f791b992 100644 --- a/src/user.cpp +++ b/src/user.cpp @@ -263,6 +263,10 @@ void User::handlePresence(Swift::Presence::ref presence) { } return; } + + if (presence->getType() == Swift::Presence::Unavailable) { + m_conversationManager->removeJID(presence->getFrom()); + } // User wants to disconnect this resource From 83113fe69769dbf5714262623996b9ea93e73515 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Wed, 3 Oct 2012 09:48:11 +0200 Subject: [PATCH 10/20] Allow setting more unregistered variables in Config class which can be later accessed using CONFIG_LIST --- include/transport/config.h | 1 + src/config.cpp | 42 ++++++++++++++++++++++++++------------ src/tests/config.cpp | 25 +++++++++++++++++++++++ 3 files changed, 55 insertions(+), 13 deletions(-) diff --git a/include/transport/config.h b/include/transport/config.h index de7888ac..a672abe6 100644 --- a/include/transport/config.h +++ b/include/transport/config.h @@ -37,6 +37,7 @@ #define CONFIG_STRING_DEFAULTED(PTR, KEY, DEF) ((*PTR).hasKey(KEY) ? (*PTR)[KEY].as() : DEF) #define CONFIG_BOOL_DEFAULTED(PTR, KEY, DEF) ((*PTR).hasKey(KEY) ? (*PTR)[KEY].as() : DEF) +#define CONFIG_LIST_DEFAULTED(PTR, KEY, DEF) ((*PTR).hasKey(KEY) ? (*PTR)[KEY].as >() : DEF) namespace Transport { diff --git a/src/config.cpp b/src/config.cpp index 432fb86f..ce49f6d6 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -135,18 +135,6 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description ; - // Load configs passed by command line - if (m_argc != 0 && m_argv) { - basic_command_line_parser parser = command_line_parser(m_argc, m_argv).options(opts).allow_unregistered(); - parsed_options parsed = parser.run(); - BOOST_FOREACH(option &opt, parsed.options) { - if (opt.unregistered && !opt.value.empty()) { - m_unregistered[opt.string_key] = variable_value(opt.value[0], false); - } - } - store(parsed, m_variables); - } - parsed_options parsed = parse_config_file(ifs, opts, true); bool found_working = false; @@ -212,15 +200,43 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description parsed.options.push_back(boost::program_options::basic_option("database.database", value)); } + std::list has_key; BOOST_FOREACH(option &opt, parsed.options) { if (opt.unregistered) { - m_unregistered[opt.string_key] = variable_value(opt.value[0], false); + if (std::find(has_key.begin(), has_key.end(), opt.string_key) == has_key.end()) { + has_key.push_back(opt.string_key); + m_unregistered[opt.string_key] = variable_value(opt.value[0], false); + } + else { + std::list list; + try { + list = m_unregistered[opt.string_key].as >(); + } + catch(...) { + list.push_back(m_unregistered[opt.string_key].as()); + } + + list.push_back(opt.value[0]); + m_unregistered[opt.string_key] = variable_value(list, false); + } } else if (opt.value[0].find("$jid") != std::string::npos) { boost::replace_all(opt.value[0], "$jid", jid); } } + // Load configs passed by command line + if (m_argc != 0 && m_argv) { + basic_command_line_parser parser = command_line_parser(m_argc, m_argv).options(opts).allow_unregistered(); + parsed_options parsed = parser.run(); + BOOST_FOREACH(option &opt, parsed.options) { + if (opt.unregistered && !opt.value.empty()) { + m_unregistered[opt.string_key] = variable_value(opt.value[0], false); + } + } + store(parsed, m_variables); + } + store(parsed, m_variables); notify(m_variables); diff --git a/src/tests/config.cpp b/src/tests/config.cpp index d9e344f0..2f524677 100644 --- a/src/tests/config.cpp +++ b/src/tests/config.cpp @@ -24,7 +24,10 @@ using namespace Transport; class ConfigTest : public CPPUNIT_NS :: TestFixture{ CPPUNIT_TEST_SUITE(ConfigTest); + CPPUNIT_TEST(setStringTwice); CPPUNIT_TEST(updateBackendConfig); + CPPUNIT_TEST(unregisteredList); + CPPUNIT_TEST(unregisteredString); CPPUNIT_TEST_SUITE_END(); public: @@ -35,6 +38,14 @@ class ConfigTest : public CPPUNIT_NS :: TestFixture{ } + void setStringTwice() { + char *argv[3] = {"binary", "--service.jids=localhost", NULL}; + Config cfg(2, argv); + std::istringstream ifs("service.jids = irc.freenode.org\n"); + cfg.load(ifs); + CPPUNIT_ASSERT_EQUAL(std::string("localhost"), CONFIG_STRING(&cfg, "service.jids")); + } + void updateBackendConfig() { Config cfg; CPPUNIT_ASSERT(!cfg.hasKey("registration.needPassword")); @@ -44,6 +55,20 @@ class ConfigTest : public CPPUNIT_NS :: TestFixture{ CPPUNIT_ASSERT_EQUAL(false, CONFIG_BOOL(&cfg, "registration.needPassword")); } + void unregisteredList() { + Config cfg; + std::istringstream ifs("service.irc_server = irc.freenode.org\nservice.irc_server=localhost\n"); + cfg.load(ifs); + CPPUNIT_ASSERT_EQUAL(2, (int) CONFIG_LIST(&cfg, "service.irc_server").size()); + } + + void unregisteredString() { + Config cfg; + std::istringstream ifs("service.irc_server = irc.freenode.org"); + cfg.load(ifs); + CPPUNIT_ASSERT_EQUAL(std::string("irc.freenode.org"), CONFIG_STRING(&cfg, "service.irc_server")); + } + }; CPPUNIT_TEST_SUITE_REGISTRATION (ConfigTest); From 4d2f3bd06950d2e7c7e4e3d40e049dab67d8476f Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Wed, 3 Oct 2012 13:23:58 +0200 Subject: [PATCH 11/20] Check for boost_thread and also boost_thread-mt --- CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a69a1d3c..6c6053b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -145,7 +145,10 @@ else(WIN32) message(STATUS "Using non-multithreaded boost") set(Boost_USE_MULTITHREADED 0) endif(contains) - find_package(Boost COMPONENTS program_options date_time system filesystem regex thread-mt signals REQUIRED) + find_package(Boost COMPONENTS program_options date_time system filesystem regex thread signals REQUIRED) + if (NOT Boost_FOUND) + find_package(Boost COMPONENTS program_options date_time system filesystem regex thread-mt signals REQUIRED) + endif() endif(WIN32) message( STATUS "Found Boost: ${Boost_LIBRARIES}, ${Boost_INCLUDE_DIR}") From 5110f047f1d4ee83320ff373ad69dc4cc55019e3 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Wed, 3 Oct 2012 13:24:53 +0200 Subject: [PATCH 12/20] Check for boost_thread-mt prioritely and fallback to boost_thread --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c6053b1..09ff11de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -145,9 +145,9 @@ else(WIN32) message(STATUS "Using non-multithreaded boost") set(Boost_USE_MULTITHREADED 0) endif(contains) - find_package(Boost COMPONENTS program_options date_time system filesystem regex thread signals REQUIRED) + find_package(Boost COMPONENTS program_options date_time system filesystem regex thread-mt signals REQUIRED) if (NOT Boost_FOUND) - find_package(Boost COMPONENTS program_options date_time system filesystem regex thread-mt signals REQUIRED) + find_package(Boost COMPONENTS program_options date_time system filesystem regex thread signals REQUIRED) endif() endif(WIN32) From 369da03b7ee593f150ce544b24e09bcd529f976f Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Wed, 3 Oct 2012 13:34:25 +0200 Subject: [PATCH 13/20] Check for boost_thread-mt quietly --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 09ff11de..7e1c2792 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -145,8 +145,10 @@ else(WIN32) message(STATUS "Using non-multithreaded boost") set(Boost_USE_MULTITHREADED 0) endif(contains) - find_package(Boost COMPONENTS program_options date_time system filesystem regex thread-mt signals REQUIRED) + set(Boost_FIND_QUIETLY ON) + find_package(Boost COMPONENTS program_options date_time system filesystem regex thread-mt signals) if (NOT Boost_FOUND) + set(Boost_FIND_QUIETLY OFF) find_package(Boost COMPONENTS program_options date_time system filesystem regex thread signals REQUIRED) endif() endif(WIN32) From b7f06ac35251037dc2844d1997a5b971432b13c4 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Wed, 3 Oct 2012 16:40:11 +0200 Subject: [PATCH 14/20] CONFIG_*_DEFAULTED now uses safeAs and should be used everywhere instead of CONFIG_* macros --- include/transport/config.h | 20 +++++++++++++++++--- src/tests/config.cpp | 17 +++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/include/transport/config.h b/include/transport/config.h index a672abe6..3c29dd64 100644 --- a/include/transport/config.h +++ b/include/transport/config.h @@ -28,6 +28,20 @@ #include #include +namespace Transport { + +template +const myType &safeAs(const boost::program_options::variable_value &var, const myType &def) { + try { + return var.as(); + } + catch(...) { + return def; + } +} + +} + #define CONFIG_HAS_KEY(PTR, KEY) (*PTR).hasKey(KEY) #define CONFIG_STRING(PTR, KEY) (*PTR)[KEY].as() #define CONFIG_INT(PTR, KEY) (*PTR)[KEY].as() @@ -35,9 +49,9 @@ #define CONFIG_LIST(PTR, KEY) (*PTR)[KEY].as >() #define CONFIG_VECTOR(PTR, KEY) ((*PTR).hasKey(KEY) ? (*PTR)[KEY].as >() : std::vector()) -#define CONFIG_STRING_DEFAULTED(PTR, KEY, DEF) ((*PTR).hasKey(KEY) ? (*PTR)[KEY].as() : DEF) -#define CONFIG_BOOL_DEFAULTED(PTR, KEY, DEF) ((*PTR).hasKey(KEY) ? (*PTR)[KEY].as() : DEF) -#define CONFIG_LIST_DEFAULTED(PTR, KEY, DEF) ((*PTR).hasKey(KEY) ? (*PTR)[KEY].as >() : DEF) +#define CONFIG_STRING_DEFAULTED(PTR, KEY, DEF) ((*PTR).hasKey(KEY) ? Transport::safeAs((*PTR)[KEY], DEF) : DEF) +#define CONFIG_BOOL_DEFAULTED(PTR, KEY, DEF) ((*PTR).hasKey(KEY) ? Transport::safeAs((*PTR)[KEY], DEF) : DEF) +#define CONFIG_LIST_DEFAULTED(PTR, KEY, DEF) ((*PTR).hasKey(KEY) ? Transport::safeAs >((*PTR)[KEY], DEF) : DEF) namespace Transport { diff --git a/src/tests/config.cpp b/src/tests/config.cpp index 2f524677..24776a74 100644 --- a/src/tests/config.cpp +++ b/src/tests/config.cpp @@ -28,6 +28,8 @@ class ConfigTest : public CPPUNIT_NS :: TestFixture{ CPPUNIT_TEST(updateBackendConfig); CPPUNIT_TEST(unregisteredList); CPPUNIT_TEST(unregisteredString); + CPPUNIT_TEST(unregisteredListAsString); + CPPUNIT_TEST(unregisteredStringAsList); CPPUNIT_TEST_SUITE_END(); public: @@ -69,6 +71,21 @@ class ConfigTest : public CPPUNIT_NS :: TestFixture{ CPPUNIT_ASSERT_EQUAL(std::string("irc.freenode.org"), CONFIG_STRING(&cfg, "service.irc_server")); } + void unregisteredListAsString() { + Config cfg; + std::istringstream ifs("service.irc_server = irc.freenode.orgn\nservice.irc_server = irc2.freenode.org"); + cfg.load(ifs); + CPPUNIT_ASSERT_EQUAL(std::string(""), CONFIG_STRING_DEFAULTED(&cfg, "service.irc_server", "")); + } + + void unregisteredStringAsList() { + Config cfg; + std::istringstream ifs("service.irc_server = irc.freenode.org"); + cfg.load(ifs); + std::list list; + CPPUNIT_ASSERT_EQUAL(0, (int) CONFIG_LIST_DEFAULTED(&cfg, "service.irc_server", list).size()); + } + }; CPPUNIT_TEST_SUITE_REGISTRATION (ConfigTest); From 0e56fb848472897dea21ef59e94698b5d6b0a351 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Thu, 4 Oct 2012 08:48:14 +0200 Subject: [PATCH 15/20] Support more service.irc_server values and try another one when server disconnects us --- backends/libcommuni/ircnetworkplugin.cpp | 32 +++++++++++++++++++----- backends/libcommuni/ircnetworkplugin.h | 5 +++- backends/libcommuni/session.cpp | 17 +++++++++---- backends/libcommuni/session.h | 7 ++++-- include/transport/config.h | 1 - 5 files changed, 47 insertions(+), 15 deletions(-) diff --git a/backends/libcommuni/ircnetworkplugin.cpp b/backends/libcommuni/ircnetworkplugin.cpp index 57e7d289..90e4d663 100644 --- a/backends/libcommuni/ircnetworkplugin.cpp +++ b/backends/libcommuni/ircnetworkplugin.cpp @@ -10,11 +10,23 @@ DEFINE_LOGGER(logger, "IRCNetworkPlugin"); IRCNetworkPlugin::IRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port) { this->config = config; + m_currentServer = 0; m_socket = new QTcpSocket(); m_socket->connectToHost(FROM_UTF8(host), port); connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData())); - m_server = CONFIG_STRING_DEFAULTED(config, "service.irc_server", ""); + std::string server = CONFIG_STRING_DEFAULTED(config, "service.irc_server", ""); + if (!server.empty()) { + m_servers.push_back(server); + } + else { + + std::list list; + list = CONFIG_LIST_DEFAULTED(config, "service.irc_server", list); + + m_servers.insert(m_servers.begin(), list.begin(), list.end()); + } + if (CONFIG_HAS_KEY(config, "service.irc_identify")) { m_identify = CONFIG_STRING(config, "service.irc_identify"); } @@ -23,6 +35,14 @@ IRCNetworkPlugin::IRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, con } } +void IRCNetworkPlugin::tryNextServer() { + if (!m_servers.empty()) { + int nextServer = (m_currentServer + 1) % m_servers.size(); + LOG4CXX_INFO(logger, "Server " << m_servers[m_currentServer] << " disconnected user. Next server to try will be " << m_servers[nextServer]); + m_currentServer = nextServer; + } +} + void IRCNetworkPlugin::readData() { size_t availableBytes = m_socket->bytesAvailable(); if (availableBytes == 0) @@ -60,14 +80,14 @@ MyIrcSession *IRCNetworkPlugin::createSession(const std::string &user, const std } void IRCNetworkPlugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) { - if (!m_server.empty()) { + if (!m_servers.empty()) { // legacy name is users nickname if (m_sessions[user] != NULL) { LOG4CXX_WARN(logger, user << ": Already logged in."); return; } - m_sessions[user] = createSession(user, m_server, legacyName, password, ""); + m_sessions[user] = createSession(user, m_servers[m_currentServer], legacyName, password, ""); } else { // We are waiting for first room join to connect user to IRC network, because we don't know which @@ -90,7 +110,7 @@ void IRCNetworkPlugin::handleLogoutRequest(const std::string &user, const std::s std::string IRCNetworkPlugin::getSessionName(const std::string &user, const std::string &legacyName) { std::string u = user; - if (!CONFIG_BOOL(config, "service.server_mode") && m_server.empty()) { + if (!CONFIG_BOOL(config, "service.server_mode") && m_servers.empty()) { u = user + legacyName.substr(legacyName.find("@") + 1); if (u.find("/") != std::string::npos) { u = u.substr(0, u.find("/")); @@ -146,7 +166,7 @@ void IRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std: LOG4CXX_INFO(logger, user << ": Session name: " << session << ", Joining room " << target); if (m_sessions[session] == NULL) { - if (m_server.empty()) { + if (m_servers.empty()) { // in gateway mode we want to login this user to network according to legacyName if (room.find("@") != std::string::npos) { // suffix is %irc.freenode.net to let MyIrcSession return #room%irc.freenode.net @@ -182,7 +202,7 @@ void IRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std m_sessions[session]->removeAutoJoinChannel(target); m_sessions[session]->rooms -= 1; - if (m_sessions[session]->rooms <= 0 && m_server.empty()) { + if (m_sessions[session]->rooms <= 0 && m_servers.empty()) { LOG4CXX_INFO(logger, user << ": Session name: " << session << ", User is not in any room, disconnecting from network"); m_sessions[session]->close(); m_sessions[session]->deleteLater(); diff --git a/backends/libcommuni/ircnetworkplugin.h b/backends/libcommuni/ircnetworkplugin.h index c2925b77..043089cd 100644 --- a/backends/libcommuni/ircnetworkplugin.h +++ b/backends/libcommuni/ircnetworkplugin.h @@ -28,6 +28,8 @@ class IRCNetworkPlugin : public QObject, public NetworkPlugin { void handleRoomSubjectChangedRequest(const std::string &user, const std::string &room, const std::string &message); + void tryNextServer(); + public slots: void readData(); void sendData(const std::string &string); @@ -41,6 +43,7 @@ class IRCNetworkPlugin : public QObject, public NetworkPlugin { Config *config; QTcpSocket *m_socket; std::map m_sessions; - std::string m_server; + std::vector m_servers; + int m_currentServer; std::string m_identify; }; \ No newline at end of file diff --git a/backends/libcommuni/session.cpp b/backends/libcommuni/session.cpp index 3fe1cba1..2eabfe96 100644 --- a/backends/libcommuni/session.cpp +++ b/backends/libcommuni/session.cpp @@ -14,6 +14,8 @@ #include #include +#include "ircnetworkplugin.h" + #define FROM_UTF8(WHAT) QString::fromUtf8((WHAT).c_str(), (WHAT).size()) #define TO_UTF8(WHAT) std::string((WHAT).toUtf8().data(), (WHAT).toUtf8().size()) @@ -21,7 +23,7 @@ DEFINE_LOGGER(logger, "IRCSession"); -MyIrcSession::MyIrcSession(const std::string &user, NetworkPlugin *np, const std::string &suffix, QObject* parent) : IrcSession(parent) +MyIrcSession::MyIrcSession(const std::string &user, IRCNetworkPlugin *np, const std::string &suffix, QObject* parent) : IrcSession(parent) { this->np = np; this->user = user; @@ -29,6 +31,7 @@ MyIrcSession::MyIrcSession(const std::string &user, NetworkPlugin *np, const std m_connected = false; rooms = 0; connect(this, SIGNAL(disconnected()), SLOT(on_disconnected())); + connect(this, SIGNAL(socketError(QAbstractSocket::SocketError)), SLOT(on_socketError(QAbstractSocket::SocketError))); connect(this, SIGNAL(connected()), SLOT(on_connected())); connect(this, SIGNAL(messageReceived(IrcMessage*)), this, SLOT(onMessageReceived(IrcMessage*))); } @@ -50,9 +53,15 @@ void MyIrcSession::on_connected() { } } +void MyIrcSession::on_socketError(QAbstractSocket::SocketError error) { + on_disconnected(); +} + void MyIrcSession::on_disconnected() { - if (suffix.empty()) + if (suffix.empty()) { np->handleDisconnected(user, 0, ""); + np->tryNextServer(); + } m_connected = false; } @@ -192,9 +201,7 @@ void MyIrcSession::on_numericMessageReceived(IrcMessage *message) { } break; case 432: - if (m_connected) { - np->handleDisconnected(user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Erroneous Nickname"); - } + np->handleDisconnected(user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Erroneous Nickname"); break; default: break; diff --git a/backends/libcommuni/session.h b/backends/libcommuni/session.h index bff2aee4..507feb93 100644 --- a/backends/libcommuni/session.h +++ b/backends/libcommuni/session.h @@ -18,6 +18,8 @@ using namespace Transport; +class IRCNetworkPlugin; + class MyIrcSession : public IrcSession { Q_OBJECT @@ -37,7 +39,7 @@ public: typedef std::map > AutoJoinMap; - MyIrcSession(const std::string &user, NetworkPlugin *np, const std::string &suffix = "", QObject* parent = 0); + MyIrcSession(const std::string &user, IRCNetworkPlugin *np, const std::string &suffix = "", QObject* parent = 0); std::map m_modes; std::string suffix; int rooms; @@ -72,11 +74,12 @@ public: protected Q_SLOTS: void on_connected(); void on_disconnected(); + void on_socketError(QAbstractSocket::SocketError error); void onMessageReceived(IrcMessage* message); protected: - NetworkPlugin *np; + IRCNetworkPlugin *np; std::string user; std::string m_identify; AutoJoinMap m_autoJoin; diff --git a/include/transport/config.h b/include/transport/config.h index 3c29dd64..aa55cd9a 100644 --- a/include/transport/config.h +++ b/include/transport/config.h @@ -53,7 +53,6 @@ const myType &safeAs(const boost::program_options::variable_value &var, const my #define CONFIG_BOOL_DEFAULTED(PTR, KEY, DEF) ((*PTR).hasKey(KEY) ? Transport::safeAs((*PTR)[KEY], DEF) : DEF) #define CONFIG_LIST_DEFAULTED(PTR, KEY, DEF) ((*PTR).hasKey(KEY) ? Transport::safeAs >((*PTR)[KEY], DEF) : DEF) - namespace Transport { /// Represents variable:value pairs. From fe33d765e5b52cb654ffd4a0a7371b8b98041443 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Thu, 4 Oct 2012 09:55:26 +0200 Subject: [PATCH 16/20] include also signal.h --- include/transport/vcardresponder.h | 2 +- src/networkpluginserver.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/transport/vcardresponder.h b/include/transport/vcardresponder.h index 2618a897..156a95e4 100644 --- a/include/transport/vcardresponder.h +++ b/include/transport/vcardresponder.h @@ -59,4 +59,4 @@ class VCardResponder : public Swift::Responder { Swift::Timer::ref m_collectTimer; }; -} \ No newline at end of file +} diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index 72179d98..a7efd8fb 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -56,6 +56,8 @@ #else #include "sys/wait.h" #include "sys/signal.h" +#include +#include #include "popt.h" #endif From 79ff2e46d05773bed67a3cbaf457bc3580e72b2f Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Thu, 4 Oct 2012 10:09:34 +0200 Subject: [PATCH 17/20] Do not use malloc_trim on BSd --- backends/libpurple/main.cpp | 4 ++++ src/usermanager.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index 0a487ea3..a337bcb4 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -17,7 +17,9 @@ #include "geventloop.h" // #include "valgrind/memcheck.h" +#ifndef BSD #include "malloc.h" +#endif #include #include "errno.h" #include @@ -364,8 +366,10 @@ class SpectrumNetworkPlugin : public NetworkPlugin { purple_accounts_delete_wrapped(account); #ifndef WIN32 +#ifndef BSD malloc_trim(0); #endif +#endif // VALGRIND_DO_LEAK_CHECK; } } diff --git a/src/usermanager.cpp b/src/usermanager.cpp index 4342a214..11ec7296 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -31,7 +31,9 @@ #include "Swiften/Swiften.h" #include "Swiften/Server/ServerStanzaChannel.h" #include "Swiften/Elements/StreamError.h" +#ifndef BSD #include "malloc.h" +#endif // #include "valgrind/memcheck.h" namespace Transport { @@ -124,8 +126,10 @@ void UserManager::removeUser(User *user, bool onUserBehalf) { onUserDestroyed(user); delete user; #ifndef WIN32 +#ifndef BSD malloc_trim(0); #endif +#endif // VALGRIND_DO_LEAK_CHECK; } From 6245840e7c6b0fcca6de8281e2fbf90f6fbaaf7b Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Thu, 4 Oct 2012 10:18:35 +0200 Subject: [PATCH 18/20] Show more info about boost filesystem error --- spectrum_manager/src/methods.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/spectrum_manager/src/methods.cpp b/spectrum_manager/src/methods.cpp index eca476c8..87d463d3 100644 --- a/spectrum_manager/src/methods.cpp +++ b/spectrum_manager/src/methods.cpp @@ -195,7 +195,7 @@ int start_instances(ManagerConfig *config, const std::string &_jid) { } } catch (const filesystem_error& ex) { - std::cerr << "boost filesystem error\n"; + std::cerr << "Filesystem error: " << ex.what() << "\n"; return 6; } return rv; @@ -271,7 +271,7 @@ void stop_instances(ManagerConfig *config, const std::string &_jid) { } } catch (const filesystem_error& ex) { - std::cerr << "boost filesystem error\n"; + std::cerr << "Filesystem error: " << ex.what() << "\n"; exit(5); } } @@ -324,7 +324,7 @@ int show_status(ManagerConfig *config) { } } catch (const filesystem_error& ex) { - std::cerr << "boost filesystem error\n"; + std::cerr << "Filesystem error: " << ex.what() << "\n"; exit(5); } return ret; @@ -460,7 +460,7 @@ void ask_local_server(ManagerConfig *config, Swift::BoostNetworkFactories &netwo } } catch (const filesystem_error& ex) { - std::cerr << "boost filesystem error\n"; + std::cerr << "Filesystem error: " << ex.what() << "\n"; exit(5); } } @@ -498,7 +498,7 @@ std::vector show_list(ManagerConfig *config, bool show) { } } catch (const filesystem_error& ex) { - std::cerr << "boost filesystem error\n"; + std::cerr << "Filesystem error: " << ex.what() << "\n"; } return list; } From 95ba00c2fe6ae9ac91dad795a6005d92c21b6fbe Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Thu, 4 Oct 2012 10:47:24 +0200 Subject: [PATCH 19/20] Use __FreeBSD__ instead of BSD --- backends/libpurple/main.cpp | 4 ++-- src/usermanager.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index a337bcb4..22b3ee0b 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -17,7 +17,7 @@ #include "geventloop.h" // #include "valgrind/memcheck.h" -#ifndef BSD +#ifndef __FreeBSD__ #include "malloc.h" #endif #include @@ -366,7 +366,7 @@ class SpectrumNetworkPlugin : public NetworkPlugin { purple_accounts_delete_wrapped(account); #ifndef WIN32 -#ifndef BSD +#ifndef __FreeBSD__ malloc_trim(0); #endif #endif diff --git a/src/usermanager.cpp b/src/usermanager.cpp index 11ec7296..98c75dcf 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -31,7 +31,7 @@ #include "Swiften/Swiften.h" #include "Swiften/Server/ServerStanzaChannel.h" #include "Swiften/Elements/StreamError.h" -#ifndef BSD +#ifndef __FreeBSD__ #include "malloc.h" #endif // #include "valgrind/memcheck.h" @@ -126,7 +126,7 @@ void UserManager::removeUser(User *user, bool onUserBehalf) { onUserDestroyed(user); delete user; #ifndef WIN32 -#ifndef BSD +#ifndef __FreeBSD__ malloc_trim(0); #endif #endif From 7f732f96280b12df0658d835256a141924318584 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Thu, 4 Oct 2012 12:12:49 +0200 Subject: [PATCH 20/20] Don't try to set linux only things on bsd --- backends/libpurple/main.cpp | 4 ++++ src/CMakeLists.txt | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index 22b3ee0b..1c3f8c48 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -1463,8 +1463,10 @@ static void signed_on(PurpleConnection *gc, gpointer unused) { PurpleAccount *account = purple_connection_get_account_wrapped(gc); np->handleConnected(np->m_accounts[account]); #ifndef WIN32 +#ifndef __FreeBSD__ // force returning of memory chunks allocated by libxml2 to kernel malloc_trim(0); +#endif #endif // For prpl-gg @@ -1652,8 +1654,10 @@ static void transportDataReceived(gpointer data, gint source, PurpleInputConditi int main(int argc, char **argv) { #ifndef WIN32 +#ifndef __FreeBSD__ mallopt(M_CHECK_ACTION, 2); mallopt(M_PERTURB, 0xb); +#endif signal(SIGPIPE, SIG_IGN); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 17012906..6c815564 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -38,11 +38,11 @@ else(PROTOBUF_FOUND) ADD_LIBRARY(transport SHARED ${HEADERS} ${SRC} ${SWIFTEN_SRC}) endif(PROTOBUF_FOUND) -if (CMAKE_COMPILER_IS_GNUCXX) +# if (CMAKE_COMPILER_IS_GNUCXX) if (NOT WIN32) ADD_DEFINITIONS(-fPIC) endif() -endif() +# endif() if (WIN32) TARGET_LINK_LIBRARIES(transport transport-plugin sqlite3 ${PQXX_LIBRARY} ${PQ_LIBRARY} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES} ${PROTOBUF_LIBRARY})