]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Fix message tags not being broadcast across the network.
authorPeter Powell <petpow@saberuk.com>
Wed, 2 Jan 2019 17:31:31 +0000 (17:31 +0000)
committerPeter Powell <petpow@saberuk.com>
Wed, 2 Jan 2019 20:28:46 +0000 (20:28 +0000)
include/clientprotocol.h
src/modules/m_spanningtree/commandbuilder.h
src/modules/m_spanningtree/main.cpp
src/modules/m_spanningtree/main.h
src/modules/m_spanningtree/postcommand.cpp
src/modules/m_spanningtree/protocolinterface.cpp
src/modules/m_spanningtree/treesocket.h
src/modules/m_spanningtree/treesocket2.cpp
src/modules/m_spanningtree/utils.cpp
src/modules/m_spanningtree/utils.h

index 260e463eb10f84e89a5f7c9952dadb14966c8c16..10b70e80b231536c597cf1bfe69e70c87c041a7b 100644 (file)
@@ -549,7 +549,7 @@ class ClientProtocol::MessageTagProvider : public Events::ModuleEventListener
         * MOD_RES_PASSTHRU to make no decision. If no hooks accept a tag, the tag is rejected.
         * The default implementation returns MOD_RES_PASSTHRU.
         */
-       virtual ModResult OnClientProtocolProcessTag(LocalUser* user, const std::string& tagname, std::string& tagvalue)
+       virtual ModResult OnClientProtocolProcessTag(User* user, const std::string& tagname, std::string& tagvalue)
        {
                return MOD_RES_PASSTHRU;
        }
index 59de84052b4d80027d5971c3640ca1b52a0ddaab..4bbb60e47ee52e418930975271ad579c088328a2 100644 (file)
@@ -119,6 +119,30 @@ class CmdBuilder
                return *this;
        }
 
+       CmdBuilder& push_tags(const ClientProtocol::TagMap& tags)
+       {
+               if (!tags.empty())
+               {
+                       char separator = '@';
+                       std::string taglist;
+                       for (ClientProtocol::TagMap::const_iterator iter = tags.begin(); iter != tags.end(); ++iter)
+                       {
+                               taglist.push_back(separator);
+                               separator = ';';
+
+                               taglist.append(iter->first);
+                               if (!iter->second.value.empty())
+                               {
+                                       taglist.push_back('=');
+                                       taglist.append(iter->second.value);
+                               }
+                       }
+                       taglist.push_back(' ');
+                       content.insert(0, taglist);
+               }
+               return *this;
+       }
+
        template<typename T>
        CmdBuilder& insert(const T& cont)
        {
index 2a4e927a43f4bb267b51674f9766fd52e28198ca..985762872cc88c17fe16db33ef8adbf721299189 100644 (file)
@@ -46,6 +46,7 @@ ModuleSpanningTree::ModuleSpanningTree()
        , currmembid(0)
        , eventprov(this, "event/server")
        , DNS(this, "DNS")
+       , tagevprov(this, "event/messagetag")
        , loopCall(false)
 {
 }
@@ -410,6 +411,7 @@ void ModuleSpanningTree::OnUserPostMessage(User* user, const MessageTarget& targ
                if (!IS_LOCAL(d))
                {
                        CmdBuilder params(user, message_type);
+                       params.push_tags(details.tags_out);
                        params.push_back(d->uuid);
                        params.push_last(details.text);
                        params.Unicast(d);
@@ -417,12 +419,13 @@ void ModuleSpanningTree::OnUserPostMessage(User* user, const MessageTarget& targ
        }
        else if (target.type == MessageTarget::TYPE_CHANNEL)
        {
-               Utils->SendChannelMessage(user->uuid, target.Get<Channel>(), details.text, target.status, details.exemptions, message_type);
+               Utils->SendChannelMessage(user->uuid, target.Get<Channel>(), details.text, target.status, details.tags_out, details.exemptions, message_type);
        }
        else if (target.type == MessageTarget::TYPE_SERVER)
        {
                const std::string* serverglob = target.Get<std::string>();
                CmdBuilder par(user, message_type);
+               par.push_tags(details.tags_out);
                par.push_back(*serverglob);
                par.push_last(details.text);
                par.Broadcast();
index 4f8875a025a3e5106d8026d33fc0eb93ca62aa34..fa2928687123f46b51a35dd139c0cbe3331567ca 100644 (file)
@@ -83,6 +83,9 @@ class ModuleSpanningTree
  public:
        dynamic_reference<DNS::Manager> DNS;
 
+       /** Event provider for message tags. */
+       Events::ModuleEventProvider tagevprov;
+
        ServerCommandManager CmdManager;
 
        /** Set to true if inside a spanningtree call, to prevent sending
index c7b4707b3a854804f414b13a1a7e5b024c7cc2d2..448bb3b543f5827d553365a6d1dea7ed5b88c08a 100644 (file)
@@ -39,6 +39,7 @@ void SpanningTreeUtilities::RouteCommand(TreeServer* origin, CommandBase* thiscm
 
        const bool encap = ((routing.type == ROUTE_TYPE_OPT_BCAST) || (routing.type == ROUTE_TYPE_OPT_UCAST));
        CmdBuilder params(user, encap ? "ENCAP" : command.c_str());
+       params.push_tags(parameters.GetTags());
        TreeServer* sdest = NULL;
 
        if (routing.type == ROUTE_TYPE_OPT_BCAST)
@@ -100,7 +101,7 @@ void SpanningTreeUtilities::RouteCommand(TreeServer* origin, CommandBase* thiscm
                                return;
                        // TODO OnBuildExemptList hook was here
                        CUList exempts;
-                       SendChannelMessage(user->uuid, c, parameters[1], pfx, exempts, command.c_str(), origin ? origin->GetSocket() : NULL);
+                       SendChannelMessage(user->uuid, c, parameters[1], pfx, parameters.GetTags(), exempts, command.c_str(), origin ? origin->GetSocket() : NULL);
                }
                else if (dest[0] == '$')
                {
index e54a528d99254e42464e5a848e8d2a8b2951911f..56b9370ad9692da44a6777fe3995e7cbe622a7af 100644 (file)
@@ -111,7 +111,8 @@ void SpanningTreeProtocolInterface::SendMessage(Channel* target, char status, co
 {
        const char* cmd = (msgtype == MSG_PRIVMSG ? "PRIVMSG" : "NOTICE");
        CUList exempt_list;
-       Utils->SendChannelMessage(ServerInstance->Config->GetSID(), target, text, status, exempt_list, cmd);
+       ClientProtocol::TagMap tags;
+       Utils->SendChannelMessage(ServerInstance->Config->GetSID(), target, text, status, tags, exempt_list, cmd);
 }
 
 void SpanningTreeProtocolInterface::SendMessage(User* target, const std::string& text, MessageType msgtype)
index 36dd8bb93f8037688bfe2dde3b632fba84339890..878b34ad7523496ff1185c1fb578108c7cde3756 100644 (file)
@@ -294,13 +294,17 @@ class TreeSocket : public BufferedSocket
 
        /** Handle IRC line split
         */
-       void Split(const std::string &line, std::string& prefix, std::string& command, CommandBase::Params& params);
+       void Split(const std::string& line, std::string& tags, std::string& prefix, std::string& command, CommandBase::Params& params);
 
        /** Process complete line from buffer
         */
        void ProcessLine(std::string &line);
 
-       void ProcessConnectedLine(std::string& prefix, std::string& command, CommandBase::Params& params);
+       /** Process message tags received from a remote server. */
+       void ProcessTag(User* source, const std::string& tag, ClientProtocol::TagMap& tags);
+
+       /** Process a message for a fully connected server. */
+       void ProcessConnectedLine(std::string& tags, std::string& prefix, std::string& command, CommandBase::Params& params);
 
        /** Handle socket timeout from connect()
         */
index 293cdd695114fe219f3568c10629ed4377d8993e..9ab8fc49002b541f99db6f3256cb503faae17653 100644 (file)
@@ -38,52 +38,61 @@ void TreeSocket::Error(CommandBase::Params& params)
        SetError("received ERROR " + msg);
 }
 
-void TreeSocket::Split(const std::string& line, std::string& prefix, std::string& command, CommandBase::Params& params)
+void TreeSocket::Split(const std::string& line, std::string& tags, std::string& prefix, std::string& command, CommandBase::Params& params)
 {
+       std::string token;
        irc::tokenstream tokens(line);
 
-       if (!tokens.GetMiddle(prefix))
+       if (!tokens.GetMiddle(token))
                return;
 
-       if (prefix[0] == ':')
+       if (token[0] == '@')
        {
-               prefix.erase(prefix.begin());
-
-               if (prefix.empty())
+               if (token.length() <= 1)
                {
-                       this->SendError("BUG (?) Empty prefix received: " + line);
+                       this->SendError("BUG: Received a message with empty tags: " + line);
                        return;
                }
-               if (!tokens.GetMiddle(command))
+
+               tags.assign(token, 1, std::string::npos);
+               if (!tokens.GetMiddle(token))
                {
-                       this->SendError("BUG (?) Empty command received: " + line);
+                       this->SendError("BUG: Received a message with no command: " + line);
                        return;
                }
        }
-       else
-       {
-               command = prefix;
-               prefix.clear();
-       }
-       if (command.empty())
-               this->SendError("BUG (?) Empty command received: " + line);
 
-       std::string param;
-       while (tokens.GetTrailing(param))
+       if (token[0] == ':')
        {
-               params.push_back(param);
+               if (token.length() <= 1)
+               {
+                       this->SendError("BUG: Received a message with an empty prefix: " + line);
+                       return;
+               }
+
+               prefix.assign(token, 1, std::string::npos);
+               if (!tokens.GetMiddle(token))
+               {
+                       this->SendError("BUG: Received a message with no command: " + line);
+                       return;
+               }
        }
+
+       command.assign(token);
+       while (tokens.GetTrailing(token))
+               params.push_back(token);
 }
 
 void TreeSocket::ProcessLine(std::string &line)
 {
+       std::string tags;
        std::string prefix;
        std::string command;
        CommandBase::Params params;
 
        ServerInstance->Logs->Log(MODNAME, LOG_RAWIO, "S[%d] I %s", this->GetFd(), line.c_str());
 
-       Split(line, prefix, command, params);
+       Split(line, tags, prefix, command, params);
 
        if (command.empty())
                return;
@@ -207,7 +216,7 @@ void TreeSocket::ProcessLine(std::string &line)
                         *  Credentials have been exchanged, we've gotten their 'BURST' (or sent ours).
                         *  Anything from here on should be accepted a little more reasonably.
                         */
-                       this->ProcessConnectedLine(prefix, command, params);
+                       this->ProcessConnectedLine(tags, prefix, command, params);
                break;
                case DYING:
                break;
@@ -263,7 +272,35 @@ User* TreeSocket::FindSource(const std::string& prefix, const std::string& comma
        return NULL;
 }
 
-void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command, CommandBase::Params& params)
+void TreeSocket::ProcessTag(User* source, const std::string& tag, ClientProtocol::TagMap& tags)
+{
+       std::string tagkey;
+       std::string tagval;
+       const std::string::size_type p = tag.find('=');
+       if (p != std::string::npos)
+       {
+               // Tag has a value
+               tagkey.assign(tag, 0, p);
+               tagval.assign(tag, p + 1, std::string::npos);
+       }
+       else
+       {
+               tagkey.assign(tag);
+       }
+
+       const Events::ModuleEventProvider::SubscriberList& list = Utils->Creator->tagevprov.GetSubscribers();
+       for (Events::ModuleEventProvider::SubscriberList::const_iterator i = list.begin(); i != list.end(); ++i)
+       {
+               ClientProtocol::MessageTagProvider* const tagprov = static_cast<ClientProtocol::MessageTagProvider*>(*i);
+               const ModResult res = tagprov->OnClientProtocolProcessTag(source, tagkey, tagval);
+               if (res == MOD_RES_ALLOW)
+                       tags.insert(std::make_pair(tagkey, ClientProtocol::MessageTagData(tagprov, tagval)));
+               else if (res == MOD_RES_DENY)
+                       break;
+       }
+}
+
+void TreeSocket::ProcessConnectedLine(std::string& taglist, std::string& prefix, std::string& command, CommandBase::Params& params)
 {
        User* who = FindSource(prefix, command);
        if (!who)
@@ -344,6 +381,10 @@ void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command,
        else
        {
                ClientProtocol::TagMap tags;
+               std::string tag;
+               irc::sepstream tagstream(taglist, ';');
+               while (tagstream.GetToken(tag))
+                       ProcessTag(who, tag, tags);
                res = cmd->Handle(who, CommandBase::Params(params, tags));
                if (res == CMD_INVALID)
                        throw ProtocolException("Error in command handler");
index 1224b1cf45d5a0316cbc5aecd5532862be9643b6..42eb80de538ac8de354b0457e1e4fbeec25964ed 100644 (file)
@@ -352,9 +352,10 @@ Link* SpanningTreeUtilities::FindLink(const std::string& name)
        return NULL;
 }
 
-void SpanningTreeUtilities::SendChannelMessage(const std::string& prefix, Channel* target, const std::string& text, char status, const CUList& exempt_list, const char* message_type, TreeSocket* omit)
+void SpanningTreeUtilities::SendChannelMessage(const std::string& prefix, Channel* target, const std::string& text, char status, const ClientProtocol::TagMap& tags, const CUList& exempt_list, const char* message_type, TreeSocket* omit)
 {
        CmdBuilder msg(prefix, message_type);
+       msg.push_tags(tags);
        msg.push_raw(' ');
        if (status != 0)
                msg.push_raw(status);
index e83e1c8390a4ad0f1d08c417cb7f12435e9faa76..c6f5822fe715cd7a97de1eb5ddbe5285014c2f96 100644 (file)
@@ -172,7 +172,7 @@ class SpanningTreeUtilities : public classbase
 
        /** Sends a PRIVMSG or a NOTICE to a channel obeying an exempt list and an optional prefix
         */
-       void SendChannelMessage(const std::string& prefix, Channel* target, const std::string& text, char status, const CUList& exempt_list, const char* message_type, TreeSocket* omit = NULL);
+       void SendChannelMessage(const std::string& prefix, Channel* target, const std::string& text, char status, const ClientProtocol::TagMap& tags, const CUList& exempt_list, const char* message_type, TreeSocket* omit = NULL);
 };
 
 inline void SpanningTreeUtilities::DoOneToMany(const CmdBuilder& params)