Support more service.irc_server values and try another one when server disconnects us

This commit is contained in:
Jan Kaluza 2012-10-04 08:48:14 +02:00
parent b7f06ac352
commit 0e56fb8484
5 changed files with 47 additions and 15 deletions

View file

@ -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<std::string> 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();

View file

@ -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<std::string, MyIrcSession *> m_sessions;
std::string m_server;
std::vector<std::string> m_servers;
int m_currentServer;
std::string m_identify;
};

View file

@ -14,6 +14,8 @@
#include <IrcCommand>
#include <IrcMessage>
#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;

View file

@ -18,6 +18,8 @@
using namespace Transport;
class IRCNetworkPlugin;
class MyIrcSession : public IrcSession
{
Q_OBJECT
@ -37,7 +39,7 @@ public:
typedef std::map<std::string, boost::shared_ptr<AutoJoinChannel> > 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<std::string, bool> 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;

View file

@ -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<bool>((*PTR)[KEY], DEF) : DEF)
#define CONFIG_LIST_DEFAULTED(PTR, KEY, DEF) ((*PTR).hasKey(KEY) ? Transport::safeAs<std::list<std::string> >((*PTR)[KEY], DEF) : DEF)
namespace Transport {
/// Represents variable:value pairs.