summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAttila Molnar <attilamolnar@hush.com>2014-04-16 13:08:44 +0200
committerAttila Molnar <attilamolnar@hush.com>2014-04-16 13:08:44 +0200
commit3eb205218a321e454d873ae14e2e717ce9d64142 (patch)
tree4f0c4aabf7fe7c51b329e09b59984977869fd786
parent89abc5d517154c8a6bb62b876593b03d51e8edc7 (diff)
m_spanningtree Throw an exception on protocol violations instead of returning CMD_INVALID
Catch CoreExceptions, log and close the link in OnDataReady()
-rw-r--r--src/modules/m_spanningtree/commands.h2
-rw-r--r--src/modules/m_spanningtree/fjoin.cpp15
-rw-r--r--src/modules/m_spanningtree/fmode.cpp2
-rw-r--r--src/modules/m_spanningtree/ijoin.cpp10
-rw-r--r--src/modules/m_spanningtree/metadata.cpp2
-rw-r--r--src/modules/m_spanningtree/nick.cpp2
-rw-r--r--src/modules/m_spanningtree/servercommand.h13
-rw-r--r--src/modules/m_spanningtree/treesocket1.cpp13
-rw-r--r--src/modules/m_spanningtree/treesocket2.cpp24
-rw-r--r--src/modules/m_spanningtree/uid.cpp24
10 files changed, 48 insertions, 59 deletions
diff --git a/src/modules/m_spanningtree/commands.h b/src/modules/m_spanningtree/commands.h
index 0c1ea8e49..d2d138ab2 100644
--- a/src/modules/m_spanningtree/commands.h
+++ b/src/modules/m_spanningtree/commands.h
@@ -130,7 +130,7 @@ class CommandFJoin : public ServerCommand
* @param newname The new name of the channel; must be the same or a case change of the current name
*/
static void LowerTS(Channel* chan, time_t TS, const std::string& newname);
- bool ProcessModeUUIDPair(const std::string& item, TreeSocket* src_socket, Channel* chan, irc::modestacker* modestack);
+ void ProcessModeUUIDPair(const std::string& item, TreeSocket* src_socket, Channel* chan, irc::modestacker* modestack);
public:
CommandFJoin(Module* Creator) : ServerCommand(Creator, "FJOIN", 3) { }
CmdResult Handle(User* user, std::vector<std::string>& params);
diff --git a/src/modules/m_spanningtree/fjoin.cpp b/src/modules/m_spanningtree/fjoin.cpp
index ea7711332..ec7932766 100644
--- a/src/modules/m_spanningtree/fjoin.cpp
+++ b/src/modules/m_spanningtree/fjoin.cpp
@@ -157,8 +157,7 @@ CmdResult CommandFJoin::Handle(User* srcuser, std::vector<std::string>& params)
irc::modestacker* modestackptr = (apply_other_sides_modes ? &modestack : NULL);
while (users.GetToken(item))
{
- if (!ProcessModeUUIDPair(item, src_socket, chan, modestackptr))
- return CMD_INVALID;
+ ProcessModeUUIDPair(item, src_socket, chan, modestackptr);
}
/* Flush mode stacker if we lost the FJOIN or had equal TS */
@@ -168,7 +167,7 @@ CmdResult CommandFJoin::Handle(User* srcuser, std::vector<std::string>& params)
return CMD_SUCCESS;
}
-bool CommandFJoin::ProcessModeUUIDPair(const std::string& item, TreeSocket* src_socket, Channel* chan, irc::modestacker* modestack)
+void CommandFJoin::ProcessModeUUIDPair(const std::string& item, TreeSocket* src_socket, Channel* chan, irc::modestacker* modestack)
{
std::string::size_type comma = item.find(',');
@@ -178,14 +177,14 @@ bool CommandFJoin::ProcessModeUUIDPair(const std::string& item, TreeSocket* src_
if (!who)
{
// Probably KILLed, ignore
- return true;
+ return;
}
/* Check that the user's 'direction' is correct */
TreeServer* route_back_again = TreeServer::Get(who);
if (route_back_again->GetSocket() != src_socket)
{
- return true;
+ return;
}
/* Check if the user received at least one mode */
@@ -196,10 +195,7 @@ bool CommandFJoin::ProcessModeUUIDPair(const std::string& item, TreeSocket* src_
for (std::string::const_iterator i = item.begin(); i != commait; ++i)
{
if (!ServerInstance->Modes->FindMode(*i, MODETYPE_CHANNEL))
- {
- ServerInstance->SNO->WriteToSnoMask('d', "Unrecognised mode '%c' for a user in FJOIN, dropping link", *i);
- return false;
- }
+ throw ProtocolException("Unrecognised mode '" + std::string(1, *i) + "'");
/* Add any modes this user had to the mode stack */
modestack->Push(*i, who->nick);
@@ -207,7 +203,6 @@ bool CommandFJoin::ProcessModeUUIDPair(const std::string& item, TreeSocket* src_
}
chan->ForceJoin(who, NULL, route_back_again->bursting);
- return true;
}
void CommandFJoin::RemoveStatus(Channel* c)
diff --git a/src/modules/m_spanningtree/fmode.cpp b/src/modules/m_spanningtree/fmode.cpp
index 48e4a19b9..5627b023b 100644
--- a/src/modules/m_spanningtree/fmode.cpp
+++ b/src/modules/m_spanningtree/fmode.cpp
@@ -50,7 +50,7 @@ CmdResult CommandFMode::Handle(User* who, std::vector<std::string>& params)
return CMD_FAILURE;
if (IS_SERVER(user))
- return CMD_INVALID;
+ throw ProtocolException("Invalid target");
ourTS = user->age;
}
diff --git a/src/modules/m_spanningtree/ijoin.cpp b/src/modules/m_spanningtree/ijoin.cpp
index a579848c8..637321bcb 100644
--- a/src/modules/m_spanningtree/ijoin.cpp
+++ b/src/modules/m_spanningtree/ijoin.cpp
@@ -48,10 +48,7 @@ CmdResult CommandIJoin::HandleRemote(RemoteUser* user, std::vector<std::string>&
}
if (RemoteTS < chan->age)
- {
- ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Attempted to lower TS via IJOIN. Channel=" + params[0] + " RemoteTS=" + params[1] + " LocalTS=" + ConvToStr(chan->age));
- return CMD_INVALID;
- }
+ throw ProtocolException("Attempted to lower TS via IJOIN. LocalTS=" + ConvToStr(chan->age));
apply_modes = ((params.size() > 2) && (RemoteTS == chan->age));
}
else
@@ -73,10 +70,7 @@ CmdResult CommandResync::HandleServer(TreeServer* server, std::vector<std::strin
}
if (!server->IsLocal())
- {
- ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Received RESYNC with a source that is not directly connected: " + server->GetID());
- return CMD_INVALID;
- }
+ throw ProtocolException("RESYNC from a server that is not directly connected");
// Send all known information about the channel
server->GetSocket()->SyncChannel(chan);
diff --git a/src/modules/m_spanningtree/metadata.cpp b/src/modules/m_spanningtree/metadata.cpp
index 5dea7ffae..d151bc450 100644
--- a/src/modules/m_spanningtree/metadata.cpp
+++ b/src/modules/m_spanningtree/metadata.cpp
@@ -35,7 +35,7 @@ CmdResult CommandMetadata::Handle(User* srcuser, std::vector<std::string>& param
// Channel METADATA has an additional parameter: the channel TS
// :22D METADATA #channel 12345 extname :extdata
if (params.size() < 3)
- return CMD_INVALID;
+ throw ProtocolException("Insufficient parameters for channel METADATA");
Channel* c = ServerInstance->FindChan(params[0]);
if (!c)
diff --git a/src/modules/m_spanningtree/nick.cpp b/src/modules/m_spanningtree/nick.cpp
index 49ce9a767..733901632 100644
--- a/src/modules/m_spanningtree/nick.cpp
+++ b/src/modules/m_spanningtree/nick.cpp
@@ -33,7 +33,7 @@
CmdResult CommandNick::HandleRemote(RemoteUser* user, std::vector<std::string>& params)
{
if ((isdigit(params[0][0])) && (params[0] != user->uuid))
- return CMD_INVALID;
+ throw ProtocolException("Attempted to change nick to an invalid or non-matching UUID");
/* Update timestamp on user when they change nicks */
const time_t newts = ConvToInt(params[1]);
diff --git a/src/modules/m_spanningtree/servercommand.h b/src/modules/m_spanningtree/servercommand.h
index 156b405e4..f99942079 100644
--- a/src/modules/m_spanningtree/servercommand.h
+++ b/src/modules/m_spanningtree/servercommand.h
@@ -22,6 +22,15 @@
#include "utils.h"
#include "treeserver.h"
+class ProtocolException : public ModuleException
+{
+ public:
+ ProtocolException(const std::string& msg)
+ : ModuleException("Protocol violation: " + msg)
+ {
+ }
+};
+
/** Base class for server-to-server commands that may have a (remote) user source or server source.
*/
class ServerCommand : public CommandBase
@@ -47,7 +56,7 @@ class UserOnlyServerCommand : public ServerCommand
{
RemoteUser* remoteuser = IS_REMOTE(user);
if (!remoteuser)
- return CMD_INVALID;
+ throw ProtocolException("Invalid source");
return static_cast<T*>(this)->HandleRemote(remoteuser, parameters);
}
};
@@ -65,7 +74,7 @@ class ServerOnlyServerCommand : public ServerCommand
CmdResult Handle(User* user, std::vector<std::string>& parameters)
{
if (!IS_SERVER(user))
- return CMD_INVALID;
+ throw ProtocolException("Invalid source");
TreeServer* server = TreeServer::Get(user);
return static_cast<T*>(this)->HandleServer(server, parameters);
}
diff --git a/src/modules/m_spanningtree/treesocket1.cpp b/src/modules/m_spanningtree/treesocket1.cpp
index 9da06e829..931bd3f9f 100644
--- a/src/modules/m_spanningtree/treesocket1.cpp
+++ b/src/modules/m_spanningtree/treesocket1.cpp
@@ -251,7 +251,18 @@ void TreeSocket::OnDataReady()
SendError("Read null character from socket");
break;
}
- ProcessLine(line);
+
+ try
+ {
+ ProcessLine(line);
+ }
+ catch (CoreException& ex)
+ {
+ ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Error while processing: " + line);
+ ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, ex.GetReason());
+ SendError(ex.GetReason() + " - check the log file for details");
+ }
+
if (!getError().empty())
break;
}
diff --git a/src/modules/m_spanningtree/treesocket2.cpp b/src/modules/m_spanningtree/treesocket2.cpp
index 4639a237e..8d939d22a 100644
--- a/src/modules/m_spanningtree/treesocket2.cpp
+++ b/src/modules/m_spanningtree/treesocket2.cpp
@@ -313,21 +313,13 @@ void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command,
return;
}
- ServerInstance->Logs->Log(MODNAME, LOG_SPARSE, "Unrecognised S2S command :%s %s %s",
- who->uuid.c_str(), command.c_str(), irc::stringjoiner(params).c_str());
- SendError("Unrecognised command '" + command + "' -- possibly loaded mismatched modules");
- return;
+ throw ProtocolException("Unknown command");
}
cmdbase = cmd;
}
if (params.size() < cmdbase->min_params)
- {
- ServerInstance->Logs->Log(MODNAME, LOG_SPARSE, "Insufficient parameters for S2S command :%s %s %s",
- who->uuid.c_str(), command.c_str(), irc::stringjoiner(params).c_str());
- SendError("Insufficient parameters for command '" + command + "'");
- return;
- }
+ throw ProtocolException("Insufficient parameters");
if ((!params.empty()) && (params.back().empty()) && (!cmdbase->allow_empty_last_param))
{
@@ -341,15 +333,13 @@ void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command,
if (scmd)
res = scmd->Handle(who, params);
else
- res = cmd->Handle(params, who);
-
- if (res == CMD_INVALID)
{
- ServerInstance->Logs->Log(MODNAME, LOG_SPARSE, "Error handling S2S command :%s %s %s",
- who->uuid.c_str(), command.c_str(), irc::stringjoiner(params).c_str());
- SendError("Error handling '" + command + "' -- possibly loaded mismatched modules");
+ res = cmd->Handle(params, who);
+ if (res == CMD_INVALID)
+ throw ProtocolException("Error in command handler");
}
- else if (res == CMD_SUCCESS)
+
+ if (res == CMD_SUCCESS)
Utils->RouteCommand(route_back_again, cmdbase, params, who);
}
diff --git a/src/modules/m_spanningtree/uid.cpp b/src/modules/m_spanningtree/uid.cpp
index 79bd6936f..206f79a48 100644
--- a/src/modules/m_spanningtree/uid.cpp
+++ b/src/modules/m_spanningtree/uid.cpp
@@ -38,14 +38,14 @@ CmdResult CommandUID::HandleServer(TreeServer* remoteserver, std::vector<std::st
/* Is this a valid UID, and not misrouted? */
if (params[0].length() != UIDGenerator::UUID_LENGTH || params[0].substr(0, 3) != remoteserver->GetID())
- return CMD_INVALID;
+ throw ProtocolException("Bogus UUID");
/* Check parameters for validity before introducing the client, discovered by dmb */
if (!age_t)
return CMD_INVALID;
if (!signon)
return CMD_INVALID;
if (modestr[0] != '+')
- return CMD_INVALID;
+ throw ProtocolException("Invalid mode string");
/* check for collision */
User* collideswith = ServerInstance->FindNickOnly(params[2]);
@@ -66,17 +66,10 @@ CmdResult CommandUID::HandleServer(TreeServer* remoteserver, std::vector<std::st
/* IMPORTANT NOTE: For remote users, we pass the UUID in the constructor. This automatically
* sets it up in the UUID hash for us.
+ *
+ * If the UUID already exists User::User() throws an exception which causes this connection to be closed.
*/
- User* _new = NULL;
- try
- {
- _new = new RemoteUser(params[0], remoteserver);
- }
- catch (...)
- {
- ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Duplicate UUID %s in client introduction", params[0].c_str());
- return CMD_INVALID;
- }
+ RemoteUser* _new = new RemoteUser(params[0], remoteserver);
ServerInstance->Users->clientlist[params[2]] = _new;
_new->nick = params[2];
_new->host = params[3];
@@ -98,15 +91,12 @@ CmdResult CommandUID::HandleServer(TreeServer* remoteserver, std::vector<std::st
/* For each mode thats set, find the mode handler and set it on the new user */
ModeHandler* mh = ServerInstance->Modes->FindMode(*v, MODETYPE_USER);
if (!mh)
- {
- ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Unrecognised mode '%c' for a user in UID, dropping link", *v);
- return CMD_INVALID;
- }
+ throw ProtocolException("Unrecognised mode '" + std::string(1, *v) + "'");
if (mh->GetNumParams(true))
{
if (paramptr >= params.size() - 1)
- return CMD_INVALID;
+ throw ProtocolException("Out of parameters while processing modes");
std::string mp = params[paramptr++];
/* IMPORTANT NOTE:
* All modes are assumed to succeed here as they are being set by a remote server.