From 3fef0ed889eecb40b96a597924254560c81d4a09 Mon Sep 17 00:00:00 2001 From: Attila Molnar Date: Sun, 26 Jan 2014 13:12:01 +0100 Subject: [PATCH] Add ProtocolInterface::BroadcastEncap() and infrastructure for manually forwarding ENCAPs --- include/command_parse.h | 4 +++- include/ctables.h | 6 ++++++ include/protocol.h | 10 ++++++++++ src/command_parse.cpp | 4 +++- src/modules/m_spanningtree/encap.cpp | 6 +++++- src/modules/m_spanningtree/protocolinterface.cpp | 11 +++++++++++ src/modules/m_spanningtree/protocolinterface.h | 1 + 7 files changed, 39 insertions(+), 3 deletions(-) diff --git a/include/command_parse.h b/include/command_parse.h index 6682bc4fb..70544b0c8 100644 --- a/include/command_parse.h +++ b/include/command_parse.h @@ -49,13 +49,15 @@ class CoreExport CommandParser * @param commandname The command to find. This should be in uppercase. * @param parameters Parameter list * @param user The user to call the handler on behalf of + * @param cmd If non-NULL and the command was executed it is set to the command handler, + * otherwise it isn't written to. * @return This method will return CMD_SUCCESS if the command handler was found and called, * and the command completeld successfully. It will return CMD_FAILURE if the command handler was found * and called, but the command did not complete successfully, and it will return CMD_INVALID if the * command simply did not exist at all or the wrong number of parameters were given, or the user * was not privilaged enough to execute the command. */ - CmdResult CallHandler(const std::string &commandname, const std::vector& parameters, User *user); + CmdResult CallHandler(const std::string& commandname, const std::vector& parameters, User* user, Command** cmd = NULL); /** Get the handler function for a command. * @param commandname The command required. Always use uppercase for this parameter. diff --git a/include/ctables.h b/include/ctables.h index 81b841e81..a69f5c86f 100644 --- a/include/ctables.h +++ b/include/ctables.h @@ -224,8 +224,14 @@ class CoreExport CommandBase : public ServiceProvider class CoreExport Command : public CommandBase { public: + /** If true, the command will not be forwarded by the linking module even if it comes via ENCAP. + * Can be used to forward commands before their effects. + */ + bool force_manual_route; + Command(Module* me, const std::string& cmd, unsigned int minpara = 0, unsigned int maxpara = 0) : CommandBase(me, cmd, minpara, maxpara) + , force_manual_route(false) { } diff --git a/include/protocol.h b/include/protocol.h index 4c58c78ba..01eb145f1 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -68,6 +68,16 @@ class CoreExport ProtocolInterface */ virtual bool SendEncapsulatedData(const std::string& targetmask, const std::string& cmd, const parameterlist& params, User* source = NULL) { return false; } + /** Send an ENCAP message to all servers. + * See the protocol documentation for the purpose of ENCAP. + * @param cmd The ENCAP subcommand + * @param params List of string parameters which are dependant on the subcommand + * @param source The source of the message (prefix), must be a local user or a user behind 'omit' + * or NULL which is equivalent to the local server + * @param omit If non-NULL the message won't be sent in the direction of this server, useful for forwarding messages + */ + virtual void BroadcastEncap(const std::string& cmd, const parameterlist& params, User* source = NULL, User* omit = NULL) { } + /** Send metadata for a channel to other linked servers. * @param chan The channel to send metadata for * @param key The 'key' of the data, e.g. "swhois" for swhois desc on a user diff --git a/src/command_parse.cpp b/src/command_parse.cpp index 66b8dcd67..7133b3f05 100644 --- a/src/command_parse.cpp +++ b/src/command_parse.cpp @@ -118,7 +118,7 @@ Command* CommandParser::GetHandler(const std::string &commandname) // calls a handler function for a command -CmdResult CommandParser::CallHandler(const std::string &commandname, const std::vector& parameters, User *user) +CmdResult CommandParser::CallHandler(const std::string& commandname, const std::vector& parameters, User* user, Command** cmd) { Commandtable::iterator n = cmdlist.find(commandname); @@ -150,6 +150,8 @@ CmdResult CommandParser::CallHandler(const std::string &commandname, const std:: if (bOkay) { + if (cmd) + *cmd = n->second; return n->second->Handle(parameters,user); } } diff --git a/src/modules/m_spanningtree/encap.cpp b/src/modules/m_spanningtree/encap.cpp index 12ab2b664..566f15da8 100644 --- a/src/modules/m_spanningtree/encap.cpp +++ b/src/modules/m_spanningtree/encap.cpp @@ -27,8 +27,12 @@ CmdResult CommandEncap::Handle(User* user, std::vector& params) if (ServerInstance->Config->GetSID() == params[0] || InspIRCd::Match(ServerInstance->Config->ServerName, params[0])) { parameterlist plist(params.begin() + 2, params.end()); - ServerInstance->Parser->CallHandler(params[1], plist, user); + Command* cmd = NULL; + ServerInstance->Parser->CallHandler(params[1], plist, user, &cmd); // Discard return value, ENCAP shall succeed even if the command does not exist + + if ((cmd) && (cmd->force_manual_route)) + return CMD_FAILURE; } return CMD_SUCCESS; } diff --git a/src/modules/m_spanningtree/protocolinterface.cpp b/src/modules/m_spanningtree/protocolinterface.cpp index ee5e31984..192f7cff2 100644 --- a/src/modules/m_spanningtree/protocolinterface.cpp +++ b/src/modules/m_spanningtree/protocolinterface.cpp @@ -71,6 +71,17 @@ bool SpanningTreeProtocolInterface::SendEncapsulatedData(const std::string& targ return true; } +void SpanningTreeProtocolInterface::BroadcastEncap(const std::string& cmd, const parameterlist& params, User* source, User* omit) +{ + if (!source) + source = ServerInstance->FakeClient; + + // If omit is non-NULL we pass the route belonging to the user to Forward(), + // otherwise we pass NULL, which is equivalent to Broadcast() + TreeServer* server = (omit ? TreeServer::Get(omit)->GetRoute() : NULL); + CmdBuilder(source, "ENCAP * ").push_raw(cmd).insert(params).Forward(server); +} + void SpanningTreeProtocolInterface::SendMetaData(User* u, const std::string& key, const std::string& data) { CommandMetadata::Builder(u, key, data).Broadcast(); diff --git a/src/modules/m_spanningtree/protocolinterface.h b/src/modules/m_spanningtree/protocolinterface.h index 04b56c181..97648f4b4 100644 --- a/src/modules/m_spanningtree/protocolinterface.h +++ b/src/modules/m_spanningtree/protocolinterface.h @@ -32,6 +32,7 @@ class SpanningTreeProtocolInterface : public ProtocolInterface }; bool SendEncapsulatedData(const std::string& targetmask, const std::string& cmd, const parameterlist& params, User* source) CXX11_OVERRIDE; + void BroadcastEncap(const std::string& cmd, const parameterlist& params, User* source, User* omit) CXX11_OVERRIDE; void SendMetaData(User* user, const std::string& key, const std::string& data) CXX11_OVERRIDE; void SendMetaData(Channel* chan, const std::string& key, const std::string& data) CXX11_OVERRIDE; void SendMetaData(const std::string& key, const std::string& data) CXX11_OVERRIDE; -- 2.39.2