From 56b2bf3a1a742971a5de7ced1b57024424fc78b8 Mon Sep 17 00:00:00 2001 From: Shane Synan Date: Tue, 6 Sep 2016 16:33:58 -0500 Subject: [PATCH] Show IRC server error messages when unexpected Handle ERROR replies from IRC servers, displaying the error message in the status buffer. Add method 'disconnectExpected' to CoreNetwork to expose when a disconnect is expected. As we're expecting a server error message when issuing QUIT, hide it to avoid showing redundant information. This fixes users getting disconnected by the server without any way to find out why. Resolves GH-238. --- src/common/eventmanager.h | 1 + src/core/corenetwork.h | 9 +++++++++ src/core/coresessioneventprocessor.cpp | 15 +++++++++++++++ src/core/coresessioneventprocessor.h | 1 + src/core/eventstringifier.cpp | 9 +++++++++ src/core/eventstringifier.h | 1 + 6 files changed, 36 insertions(+) diff --git a/src/common/eventmanager.h b/src/common/eventmanager.h index 2d88143a..33c41c9f 100644 --- a/src/common/eventmanager.h +++ b/src/common/eventmanager.h @@ -104,6 +104,7 @@ public : IrcEventPrivmsg, IrcEventQuit, IrcEventTopic, + IrcEventError, /// ERROR message from server IrcEventWallops, IrcEventRawPrivmsg, ///< Undecoded privmsg (still needs CTCP parsing) IrcEventRawNotice, ///< Undecoded notice (still needs CTCP parsing) diff --git a/src/core/corenetwork.h b/src/core/corenetwork.h index 8201b437..4d4e673a 100644 --- a/src/core/corenetwork.h +++ b/src/core/corenetwork.h @@ -101,6 +101,15 @@ public: inline quint16 localPort() const { return socket.localPort(); } inline quint16 peerPort() const { return socket.peerPort(); } + /** + * Gets whether or not a disconnect was expected. + * + * Distinguishes desired quits from unexpected disconnections such as socket errors or timeouts. + * + * @return True if disconnect was requested, otherwise false. + */ + inline bool disconnectExpected() const { return _disconnectExpected; } + QList> splitMessage(const QString &cmd, const QString &message, std::function(QString &)> cmdGenerator); // IRCv3 capability negotiation diff --git a/src/core/coresessioneventprocessor.cpp b/src/core/coresessioneventprocessor.cpp index eef1e262..c3e6cc10 100644 --- a/src/core/coresessioneventprocessor.cpp +++ b/src/core/coresessioneventprocessor.cpp @@ -662,6 +662,21 @@ void CoreSessionEventProcessor::processIrcEventTopic(IrcEvent *e) } } +/* ERROR - "ERROR :reason" +Example: ERROR :Closing Link: nickname[xxx.xxx.xxx.xxx] (Large base64 image paste.) +See https://tools.ietf.org/html/rfc2812#section-3.7.4 */ +void CoreSessionEventProcessor::processIrcEventError(IrcEvent *e) +{ + if (!checkParamCount(e, 1)) + return; + + if (coreNetwork(e)->disconnectExpected()) { + // During QUIT, the server should send an error (often, but not always, "Closing Link"). As + // we're expecting it, don't show this to the user. + e->setFlag(EventManager::Silent); + } +} + #ifdef HAVE_QCA2 void CoreSessionEventProcessor::processKeyEvent(KeyEvent *e) diff --git a/src/core/coresessioneventprocessor.h b/src/core/coresessioneventprocessor.h index 3a1070d2..52aa3db0 100644 --- a/src/core/coresessioneventprocessor.h +++ b/src/core/coresessioneventprocessor.h @@ -62,6 +62,7 @@ public: Q_INVOKABLE void processIrcEventQuit(IrcEvent *event); Q_INVOKABLE void lateProcessIrcEventQuit(IrcEvent *event); Q_INVOKABLE void processIrcEventTopic(IrcEvent *event); + Q_INVOKABLE void processIrcEventError(IrcEvent *event); /// ERROR message from server #ifdef HAVE_QCA2 Q_INVOKABLE void processKeyEvent(KeyEvent *event); #endif diff --git a/src/core/eventstringifier.cpp b/src/core/eventstringifier.cpp index f18af109..6ef3f8ad 100644 --- a/src/core/eventstringifier.cpp +++ b/src/core/eventstringifier.cpp @@ -356,6 +356,15 @@ void EventStringifier::processIrcEventTopic(IrcEvent *e) .arg(e->nick(), e->params().at(0), e->params().at(1)), QString(), e->params().at(0)); } +void EventStringifier::processIrcEventError(IrcEvent *e) +{ + // Need an error reason + if (!checkParamCount(e, 1)) + return; + + displayMsg(e, Message::Server, tr("Error from server: ") + e->params().join("")); +} + void EventStringifier::processIrcEventWallops(IrcEvent *e) { displayMsg(e, Message::Server, tr("[Operwall] %1: %2").arg(e->nick(), e->params().join(" "))); diff --git a/src/core/eventstringifier.h b/src/core/eventstringifier.h index bef6ab86..499a7666 100644 --- a/src/core/eventstringifier.h +++ b/src/core/eventstringifier.h @@ -64,6 +64,7 @@ public: Q_INVOKABLE void processIrcEventPong(IrcEvent *event); Q_INVOKABLE void processIrcEventQuit(IrcEvent *event); Q_INVOKABLE void processIrcEventTopic(IrcEvent *event); + Q_INVOKABLE void processIrcEventError(IrcEvent *event); /// ERROR message from server Q_INVOKABLE void processIrcEventWallops(IrcEvent *event); Q_INVOKABLE void processIrcEvent005(IrcEvent *event); // RPL_ISUPPORT -- 2.20.1