From 58fbe0d388c610c490c93191056853142ad87b22 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Tue, 12 Feb 2013 09:30:24 +0100 Subject: [PATCH] Communi: Handle and forward socket errors. Fixes for example situation when user tries to join the room on server which does not exist. --- backends/libcommuni/ircnetworkplugin.cpp | 6 +++++- backends/libcommuni/session.cpp | 26 +++++++++++++++++++++++- backends/libcommuni/session.h | 9 ++++++-- include/transport/conversation.h | 3 ++- include/transport/protocol.proto | 1 + src/conversation.cpp | 9 +++++++- 6 files changed, 48 insertions(+), 6 deletions(-) diff --git a/backends/libcommuni/ircnetworkplugin.cpp b/backends/libcommuni/ircnetworkplugin.cpp index e520ed6c..57f0fcf7 100644 --- a/backends/libcommuni/ircnetworkplugin.cpp +++ b/backends/libcommuni/ircnetworkplugin.cpp @@ -95,7 +95,7 @@ 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_servers.empty()) { - // legacy name is users nickname + // legacy name is user's nickname if (m_sessions[user] != NULL) { LOG4CXX_WARN(logger, user << ": Already logged in."); return; @@ -154,6 +154,10 @@ void IRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const s } std::string target = getTargetName(legacyName); + // We are sending PM message. On XMPP side, user is sending PM using the particular channel, + // for example #room@irc.freenode.org/hanzz. On IRC side, we are forwarding this message + // just to "hanzz". Therefore we have to somewhere store, that message from "hanzz" should + // be mapped to #room@irc.freenode.org/hanzz. if (legacyName.find("/") != std::string::npos) { m_sessions[session]->addPM(target, legacyName.substr(0, legacyName.find("@"))); } diff --git a/backends/libcommuni/session.cpp b/backends/libcommuni/session.cpp index a75bc523..579bbbbb 100644 --- a/backends/libcommuni/session.cpp +++ b/backends/libcommuni/session.cpp @@ -70,7 +70,31 @@ void MyIrcSession::on_connected() { } void MyIrcSession::on_socketError(QAbstractSocket::SocketError error) { - on_disconnected(); + std::string reason; + switch(error) { + case QAbstractSocket::ConnectionRefusedError: reason = "The connection was refused by the peer (or timed out)."; break; + case QAbstractSocket::RemoteHostClosedError: reason = "The remote host closed the connection."; break; + case QAbstractSocket::HostNotFoundError: reason = "The host address was not found."; break; + case QAbstractSocket::SocketAccessError: reason = "The socket operation failed because the application lacked the required privileges."; break; + case QAbstractSocket::SocketResourceError: reason = "The local system ran out of resources."; break; + case QAbstractSocket::SocketTimeoutError: reason = "The socket operation timed out."; break; + case QAbstractSocket::DatagramTooLargeError: reason = "The datagram was larger than the operating system's limit."; break; + case QAbstractSocket::NetworkError: reason = "An error occurred with the network."; break; + case QAbstractSocket::SslHandshakeFailedError: reason = "The SSL/TLS handshake failed, so the connection was closed"; break; + case QAbstractSocket::UnknownSocketError: reason = "An unidentified error occurred."; break; + default: reason= "Unknown error."; break; + }; + + if (!suffix.empty()) { + for(AutoJoinMap::iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) { + np->handleParticipantChanged(user, TO_UTF8(nickName()), it->second->getChannel() + suffix, pbnetwork::PARTICIPANT_FLAG_ROOM_NOT_FOUND, pbnetwork::STATUS_NONE, reason); + } + } + else { + np->handleDisconnected(user, 0, reason); + np->tryNextServer(); + } + m_connected = false; } void MyIrcSession::on_disconnected() { diff --git a/backends/libcommuni/session.h b/backends/libcommuni/session.h index 95d88aa7..7a8ff9f3 100644 --- a/backends/libcommuni/session.h +++ b/backends/libcommuni/session.h @@ -69,8 +69,6 @@ public: MyIrcSession(const std::string &user, IRCNetworkPlugin *np, const std::string &suffix = "", QObject* parent = 0); virtual ~MyIrcSession(); - std::string suffix; - int rooms; void addAutoJoinChannel(const std::string &channel, const std::string &password) { m_autoJoin[channel] = boost::make_shared(channel, password, 12 + m_autoJoin.size()); @@ -81,6 +79,10 @@ public: removeIRCBuddies(channel); } + // We are sending PM message. On XMPP side, user is sending PM using the particular channel, + // for example #room@irc.freenode.org/hanzz. On IRC side, we are forwarding this message + // just to "hanzz". Therefore we have to somewhere store, that message from "hanzz" should + // be mapped to #room@irc.freenode.org/hanzz. void addPM(const std::string &name, const std::string &room) { m_pms[name] = room; } @@ -120,6 +122,9 @@ public: void on_messageReceived(IrcMessage *message); void on_numericMessageReceived(IrcMessage *message); + std::string suffix; + int rooms; + protected Q_SLOTS: void on_connected(); void on_disconnected(); diff --git a/include/transport/conversation.h b/include/transport/conversation.h index 78aa5266..83e22672 100644 --- a/include/transport/conversation.h +++ b/include/transport/conversation.h @@ -40,7 +40,8 @@ class Conversation { PARTICIPANT_FLAG_BANNED = 4, PARTICIPANT_FLAG_NOT_AUTHORIZED = 8, PARTICIPANT_FLAG_ME = 16, - PARTICIPANT_FLAG_KICKED = 32 + PARTICIPANT_FLAG_KICKED = 32, + PARTICIPANT_FLAG_ROOM_NOT_FOUD = 64 } ParticipantFlag; typedef struct _Participant { diff --git a/include/transport/protocol.proto b/include/transport/protocol.proto index 4a5b8f00..8d48386d 100644 --- a/include/transport/protocol.proto +++ b/include/transport/protocol.proto @@ -95,6 +95,7 @@ enum ParticipantFlag { PARTICIPANT_FLAG_NOT_AUTHORIZED = 8; PARTICIPANT_FLAG_ME = 16; PARTICIPANT_FLAG_KICKED = 32; + PARTICIPANT_FLAG_ROOM_NOT_FOUND = 64; } message Participant { diff --git a/src/conversation.cpp b/src/conversation.cpp index 7f4fe73c..fbf1be34 100644 --- a/src/conversation.cpp +++ b/src/conversation.cpp @@ -257,7 +257,14 @@ Swift::Presence::ref Conversation::generatePresence(const std::string &nick, int delete p; presence->setType(Swift::Presence::Error); presence->addPayload(boost::shared_ptr(new Swift::MUCPayload())); - presence->addPayload(boost::shared_ptr(new Swift::ErrorPayload(Swift::ErrorPayload::NotAuthorized, Swift::ErrorPayload::Auth))); + presence->addPayload(boost::shared_ptr(new Swift::ErrorPayload(Swift::ErrorPayload::NotAuthorized, Swift::ErrorPayload::Auth, statusMessage))); + return presence; + } + else if (flag & PARTICIPANT_FLAG_ROOM_NOT_FOUD) { + delete p; + presence->setType(Swift::Presence::Error); + presence->addPayload(boost::shared_ptr(new Swift::MUCPayload())); + presence->addPayload(boost::shared_ptr(new Swift::ErrorPayload(Swift::ErrorPayload::ItemNotFound, Swift::ErrorPayload::Cancel, statusMessage))); return presence; } else {