aboutsummaryrefslogtreecommitdiff
path: root/modules/spanningtree/msgbuilder.cpp
diff options
context:
space:
mode:
authorGravatar Sadie Powell2026-03-11 21:54:40 +0000
committerGravatar Sadie Powell2026-03-12 00:18:06 +0000
commitfcb3090055429a108b9837dbd4ba505d9c291129 (patch)
tree5c55fd77d3b24adeda54e250d91b2a44badc9c5d /modules/spanningtree/msgbuilder.cpp
parentMark all acting extbans as MATCH_REQUIRE_CHANNEL. (diff)
Rework sending server protocol messages.
- Replace CmdBuilder with MessageBuilder. This has a less footgun API. All message building has to go through this now so we can implement other message formats in the future. - Replace the message parsing in WriteLine with an analogue to PreProcessOldProtocolMessage. This should be much faster. - Move parameter translation from the core to spanningtree. - Change EncodeParameter to return the value instead of updating in place. - Replace the OnBuild*Message events with one OnServerMessage that can now access all parts of the message and change them.
Diffstat (limited to 'modules/spanningtree/msgbuilder.cpp')
-rw-r--r--modules/spanningtree/msgbuilder.cpp114
1 files changed, 114 insertions, 0 deletions
diff --git a/modules/spanningtree/msgbuilder.cpp b/modules/spanningtree/msgbuilder.cpp
new file mode 100644
index 000000000..4b7b73301
--- /dev/null
+++ b/modules/spanningtree/msgbuilder.cpp
@@ -0,0 +1,114 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2026 Sadie Powell <sadie@witchery.services>
+ *
+ * This file is part of InspIRCd. InspIRCd is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sstream>
+
+#include "main.h"
+#include "msgbuilder.h"
+
+void MessageBuilder::Broadcast(const TreeServer* omit)
+{
+ for (const auto* server : Utils->TreeRoot->GetChildren())
+ {
+ if (!omit || omit != server)
+ Unicast(server->GetSocket());
+ }
+}
+
+MessageBuilder& MessageBuilder::PushParams(const CommandBase::Params& newparams)
+{
+ for (const auto& param : newparams)
+ Push(param);
+ PushTags(newparams.GetTags());
+ return *this;
+}
+
+MessageBuilder& MessageBuilder::PushTags(ClientProtocol::TagMap newtags)
+{
+ auto& oldtags = this->parameters.GetTags();
+ newtags.insert(oldtags.begin(), oldtags.end());
+ std::swap(oldtags, newtags);
+ return *this;
+}
+
+void MessageBuilder::Finalize()
+{
+ if (!Utils || this->finalized)
+ return; // Should never happen
+
+ Utils->Creator->messageeventprov.Call(&ServerProtocol::MessageEventListener::OnServerMessage,
+ this->source, this->command, this->parameters);
+
+ finalized = true;
+}
+
+std::string MessageBuilder::ToRFC1459() const
+{
+ std::stringstream buffer;
+
+ const auto& tags = this->parameters.GetTags();
+ if (!tags.empty())
+ {
+ auto separator = '@';
+ for (const auto &[tname, tinfo] : tags)
+ {
+ buffer << separator << tname;
+ if (!tinfo.value.empty())
+ buffer << '=' << tinfo.value;
+ separator = ';';
+ }
+ if (separator != '@')
+ buffer << ' ';
+ }
+
+ if (this->source)
+ buffer << ':' << source->uuid << ' ';
+
+ buffer << command;
+ if (!this->parameters.empty())
+ {
+ buffer << ' ';
+ for (auto it = this->parameters.begin(); it != this->parameters.end() - 1; ++it)
+ buffer << *it << ' ';
+
+ const auto &last = this->parameters.back();
+ if (last.empty() || last[0] == ':' || last.find(' ') != std::string::npos)
+ buffer << ':';
+ buffer << last;
+ }
+
+ return buffer.str();
+}
+
+void MessageBuilder::Unicast(TreeServer* server)
+{
+ if (server->GetSocket())
+ Unicast(server->GetSocket());
+}
+
+void MessageBuilder::Unicast(TreeSocket* socket)
+{
+ this->Finalize();
+ socket->SendMessage(*this);
+}
+
+void MessageBuilder::Unicast(const User* user)
+{
+ if (user->server)
+ Unicast(static_cast<TreeServer*>(user->server));
+}