From 0e56fb848472897dea21ef59e94698b5d6b0a351 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Thu, 4 Oct 2012 08:48:14 +0200 Subject: [PATCH] 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.