summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSadie Powell <sadie@witchery.services>2024-03-12 00:00:36 +0000
committerSadie Powell <sadie@witchery.services>2024-03-12 00:17:49 +0000
commit1538909ac09a0e84269e36a08da5ae9fce92e8f3 (patch)
tree97a986b375f6e1fbfa0df05d017357efdfc4ced1
parenta15f165a1d2d71c3db54d57779bec34914cbc171 (diff)
Add ProtocolException and use it to send fatal errors.
-rw-r--r--include/protocol.h16
-rw-r--r--modules/protocol/inspircd.cpp35
-rw-r--r--src/process.cpp14
-rw-r--r--src/protocol.cpp5
4 files changed, 39 insertions, 31 deletions
diff --git a/include/protocol.h b/include/protocol.h
index 612593c89..aeac6a069 100644
--- a/include/protocol.h
+++ b/include/protocol.h
@@ -16,6 +16,17 @@
#include "service.h"
#include "modes.h"
+/** Thrown when a protocol error happens. */
+class CoreExport ProtocolException final
+ : public ModuleException
+{
+public:
+ ProtocolException(const Anope::string &message)
+ : ModuleException(message)
+ {
+ }
+};
+
/* Encapsulates the IRCd protocol we are speaking. */
class CoreExport IRCDProto
: public Service
@@ -109,6 +120,11 @@ public:
virtual Anope::string UID_Retrieve();
virtual Anope::string SID_Retrieve();
+ /** Sends an error to the uplink before disconnecting.
+ * @param reason The error message.
+ */
+ virtual void SendError(const Anope::string &reason);
+
/** Sets the server in NOOP mode. If NOOP mode is enabled, no users
* will be able to oper on the server.
* @param s The server
diff --git a/modules/protocol/inspircd.cpp b/modules/protocol/inspircd.cpp
index 191ea5368..f8b0c35eb 100644
--- a/modules/protocol/inspircd.cpp
+++ b/modules/protocol/inspircd.cpp
@@ -1139,12 +1139,7 @@ struct IRCDMessageCapab final
spanningtree_proto_ver = Anope::Convert<size_t>(params[1], 0);
if (spanningtree_proto_ver < 1205)
- {
- Uplink::Send("ERROR", "Protocol mismatch, no or invalid protocol version given in CAPAB START.");
- Anope::QuitReason = "Protocol mismatch, no or invalid protocol version given in CAPAB START";
- Anope::Quitting = true;
- return;
- }
+ throw ProtocolException("Protocol mismatch, no or invalid protocol version given in CAPAB START.");
Servers::Capab.clear();
IRCD->CanClearBans = false;
@@ -1566,39 +1561,19 @@ struct IRCDMessageCapab final
if (spanningtree_proto_ver < 1206)
{
if (!Servers::Capab.count("ACCOUNT") || !Servers::Capab.count("SERVICES"))
- {
- Uplink::Send("ERROR", "The services_account module is not loaded. This is required by Anope.");
- Anope::QuitReason = "ERROR: Remote server does not have the services_account module loaded, and this is required.";
- Anope::Quitting = true;
- return;
- }
+ throw ProtocolException("The services_account module is not loaded. This is required by Anope.");
}
else
{
if (!Servers::Capab.count("ACCOUNT"))
- {
- Uplink::Send("ERROR", "The account module is not loaded. This is required by Anope.");
- Anope::QuitReason = "ERROR: Remote server does not have the account module loaded, and this is required.";
- Anope::Quitting = true;
- return;
- }
+ throw ProtocolException("The account module is not loaded. This is required by Anope.");
if (!Servers::Capab.count("SERVICES"))
- {
- Uplink::Send("ERROR", "The services module is not loaded. This is required by Anope.");
- Anope::QuitReason = "ERROR: Remote server does not have the services module loaded, and this is required.";
- Anope::Quitting = true;
- return;
- }
+ throw ProtocolException("The services module is not loaded. This is required by Anope.");
}
if (!ModeManager::FindUserModeByName("PRIV"))
- {
- Uplink::Send("ERROR", "The hidechans module is not loaded. This is required by Anope.");
- Anope::QuitReason = "ERROR: Remote server does not have the hidechans module loaded, and this is required.";
- Anope::Quitting = true;
- return;
- }
+ throw ProtocolException("The hidechans module is not loaded. This is required by Anope.");
if (!IRCD->CanSVSHold)
Log() << "The remote server does not have the svshold module; fake users will be used for nick protection until the module is loaded.";
diff --git a/src/process.cpp b/src/process.cpp
index eea5bcfe6..f045bc970 100644
--- a/src/process.cpp
+++ b/src/process.cpp
@@ -77,7 +77,19 @@ void Anope::Process(const Anope::string &buffer)
else if (m->HasFlag(IRCDMessage::FLAG_REQUIRE_SERVER) && !source.empty() && !src.GetServer())
Log(LOG_DEBUG) << "unexpected non-server source " << source << " for " << command;
else
- m->Run(src, params, tags);
+ {
+ try
+ {
+ m->Run(src, params, tags);
+ }
+ catch (const ProtocolException &err)
+ {
+ IRCD->SendError(err.GetReason());
+ Anope::QuitReason = "Protocol error: " + err.GetReason();
+ Anope::Quitting = true;
+ Anope::ReturnValue = EXIT_FAILURE;
+ }
+ }
}
bool IRCDProto::Parse(const Anope::string &buffer, Anope::map<Anope::string> &tags, Anope::string &source, Anope::string &command, std::vector<Anope::string> &params)
diff --git a/src/protocol.cpp b/src/protocol.cpp
index 4893173af..5699a2d48 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -86,6 +86,11 @@ Anope::string IRCDProto::SID_Retrieve()
return current_sid;
}
+void IRCDProto::SendError(const Anope::string &reason)
+{
+ Uplink::Send("ERROR", reason);
+}
+
void IRCDProto::SendKill(const MessageSource &source, const Anope::string &target, const Anope::string &reason)
{
Uplink::Send(source, "KILL", target, reason);