summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSadie Powell <sadie@witchery.services>2024-02-21 16:35:27 +0000
committerSadie Powell <sadie@witchery.services>2024-02-22 00:14:08 +0000
commitc4ab550ec719a80abada719dbe8680be806c370f (patch)
tree371e5b11134303336719c9a18affdfeab3afcb25
parent3ecf6b495b02bdabe317547fe4bcf2179e3fb6d7 (diff)
Add Uplink::Send, rework message formatting.
This is the new way of sending messages to the uplink inspired by the work done in the old git master. This will allow us to do new things involving tags in the future.
-rw-r--r--include/anope.h5
-rw-r--r--include/protocol.h14
-rw-r--r--include/uplink.h28
-rw-r--r--modules/protocol/ngircd.cpp4
-rw-r--r--src/process.cpp66
-rw-r--r--src/uplink.cpp69
6 files changed, 130 insertions, 56 deletions
diff --git a/include/anope.h b/include/anope.h
index 7ffc90729..0f181c87f 100644
--- a/include/anope.h
+++ b/include/anope.h
@@ -728,6 +728,11 @@ public:
/** Convert something to a string
*/
+inline Anope::string stringify(const Anope::string &x)
+{
+ return x;
+}
+
template<typename T> inline Anope::string stringify(const T &x)
{
std::ostringstream stream;
diff --git a/include/protocol.h b/include/protocol.h
index 29943d0e0..ec4570490 100644
--- a/include/protocol.h
+++ b/include/protocol.h
@@ -51,10 +51,20 @@ public:
* @return If the message was well formed then true; otherwise, false.
*/
virtual bool Parse(const Anope::string &message, Anope::map<Anope::string> &tags, Anope::string &source, Anope::string &command, std::vector<Anope::string> &params);
- virtual Anope::string Format(const Anope::string &source, const Anope::string &message);
+
+ /* Formats an outgoing message so it can be sent to the IRC server.
+ * @param message The location to store the formatted message.
+ * @param tags IRCv3 message tags.
+ * @param source Source of the message.
+ * @param command Command name.
+ * @param params Any extra parameters.
+ * @return If the message was formatted then true; otherwise, false.
+ */
+ virtual bool Format(Anope::string &message, const Anope::map<Anope::string> &tags, const MessageSource &source, const Anope::string &command, const std::vector<Anope::string> &params);
/* Modes used by default by our clients */
Anope::string DefaultPseudoclientModes = "+io";
+
/* Can we force change a users's nick? */
bool CanSVSNick = false;
@@ -279,7 +289,7 @@ class CoreExport MessageSource final
Server *s = nullptr;
public:
- MessageSource(const Anope::string &);
+ explicit MessageSource(const Anope::string &);
MessageSource(User *u);
MessageSource(Server *s);
const Anope::string &GetName() const;
diff --git a/include/uplink.h b/include/uplink.h
index 72622de7b..20bd26f80 100644
--- a/include/uplink.h
+++ b/include/uplink.h
@@ -13,10 +13,36 @@
#include "sockets.h"
#include "protocol.h"
+#include "servers.h"
namespace Uplink
{
extern void Connect();
+ extern CoreExport void SendInternal(const Anope::map<Anope::string> &, const MessageSource &, const Anope::string &, const std::vector<Anope::string> &);
+
+ template<typename... Args>
+ void Send(const Anope::map<Anope::string> &tags, const MessageSource &source, const Anope::string &command, Args &&...args)
+ {
+ SendInternal(tags, source, command, { stringify(args)... });
+ }
+
+ template<typename... Args>
+ void Send(const Anope::map<Anope::string> &tags, const Anope::string &command, Args &&...args)
+ {
+ SendInternal(tags, Me, command, { stringify(args)... });
+ }
+
+ template<typename... Args>
+ void Send(const MessageSource &source, const Anope::string &command, Args &&...args)
+ {
+ SendInternal({}, source, command, { stringify(args)... });
+ }
+
+ template<typename... Args>
+ void Send(const Anope::string &command, Args &&...args)
+ {
+ SendInternal({}, Me, command, { stringify(args)... });
+ }
}
/* This is the socket to our uplink */
@@ -33,7 +59,7 @@ public:
void OnError(const Anope::string &) override;
/* A message sent over the uplink socket */
- class CoreExport Message final
+ class CoreExport [[deprecated]] Message final
{
MessageSource source;
std::stringstream buffer;
diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp
index 9a460044d..28018e522 100644
--- a/modules/protocol/ngircd.cpp
+++ b/modules/protocol/ngircd.cpp
@@ -141,9 +141,9 @@ public:
this->SendVhost(u, u->GetIdent(), "");
}
- Anope::string Format(const Anope::string &source, const Anope::string &message) override
+ bool Format(Anope::string &message, const Anope::map<Anope::string> &tags, const MessageSource &source, const Anope::string &command, const std::vector<Anope::string> &params) override
{
- return IRCDProto::Format(source.empty() ? Me->GetSID() : source, message);
+ return IRCDProto::Format(message, tags, source.GetSource().empty() ? source : Me, command, params);
}
};
diff --git a/src/process.cpp b/src/process.cpp
index 94d2b538a..a81340250 100644
--- a/src/process.cpp
+++ b/src/process.cpp
@@ -123,12 +123,68 @@ bool IRCDProto::Parse(const Anope::string &buffer, Anope::map<Anope::string> &ta
return true;
}
-Anope::string IRCDProto::Format(const Anope::string &source, const Anope::string &message)
+bool IRCDProto::Format(Anope::string &message, const Anope::map<Anope::string> &tags, const MessageSource &source, const Anope::string &command, const std::vector<Anope::string> &params)
{
- if (!source.empty())
- return ":" + source + " " + message;
- else
- return message;
+ std::stringstream buffer;
+ if (CanSendTags && !tags.empty())
+ {
+ char separator = '@';
+ for (const auto &[tname, tvalue] : tags)
+ {
+ buffer << separator << tname;
+ if (!tvalue.empty())
+ buffer << '=' << tvalue;
+ separator = ';';
+ }
+ buffer << ' ';
+ }
+
+ if (source.GetServer())
+ {
+ const auto *s = source.GetServer();
+ if (s != Me && !s->IsJuped())
+ {
+ Log(LOG_DEBUG) << "Attempted to send \"" << command << "\" from " << s->GetName() << " who is not from me";
+ return false;
+ }
+
+ buffer << ':' << s->GetSID() << ' ';
+ }
+ else if (source.GetUser())
+ {
+ const auto *u = source.GetUser();
+ if (u->server != Me && !u->server->IsJuped())
+ {
+ Log(LOG_DEBUG) << "Attempted to send \"" << command << "\" from " << u->nick << " who is not from me";
+ return false;
+ }
+
+ const auto *bi = source.GetBot();
+ if (bi && !bi->introduced)
+ {
+ Log(LOG_DEBUG) << "Attempted to send \"" << command << "\" from " << bi->nick << " when not introduced";
+ return false;
+ }
+
+ buffer << ':' << u->GetUID() << ' ';
+ }
+
+ buffer << command;
+ if (!params.empty())
+ {
+ buffer << ' ';
+ for (auto it = params.begin(); it != params.end() - 1; ++it)
+ buffer << *it << ' ';
+
+
+ const auto &last = params.back();
+ if (last.empty() || last[0] == ':' || last.find(' ') != std::string::npos)
+ buffer << ':';
+ buffer << last;
+ }
+
+ message = buffer.str();
+ return true;
}
MessageTokenizer::MessageTokenizer(const Anope::string &msg)
diff --git a/src/uplink.cpp b/src/uplink.cpp
index f173bf10c..c3c6dbd41 100644
--- a/src/uplink.cpp
+++ b/src/uplink.cpp
@@ -61,6 +61,22 @@ void Uplink::Connect()
UplinkSock->Connect(ip, u.port);
}
+void Uplink::SendInternal(const Anope::map<Anope::string> &tags, const MessageSource &source, const Anope::string &command, const std::vector<Anope::string> &params)
+{
+ if (!UplinkSock)
+ {
+ Log(LOG_DEBUG) << "Attempted to send \"" << command << "\" from " << source.GetName() << " with a null uplink socket";
+ return;
+ }
+
+ Anope::string message;
+ if (!IRCD->Format(message, tags, source, command, params))
+ return;
+
+ UplinkSock->Write(message);
+ Log(LOG_RAWIO) << "Sent: " << message;
+}
+
UplinkSocket::UplinkSocket() : Socket(-1, Config->Uplinks[Anope::CurrentUplink].protocol), ConnectionSocket(), BufferedSocket()
{
error = false;
@@ -165,50 +181,11 @@ UplinkSocket::Message::Message(const MessageSource &src) : source(src)
UplinkSocket::Message::~Message()
{
- Anope::string message_source;
-
- if (this->source.GetServer() != NULL)
- {
- const Server *s = this->source.GetServer();
-
- if (s != Me && !s->IsJuped())
- {
- Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" from " << s->GetName() << " who is not from me?";
- return;
- }
-
- message_source = s->GetSID();
- }
- else if (this->source.GetUser() != NULL)
- {
- const User *u = this->source.GetUser();
-
- if (u->server != Me && !u->server->IsJuped())
- {
- Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" from " << u->nick << " who is not from me?";
- return;
- }
-
- const BotInfo *bi = this->source.GetBot();
- if (bi != NULL && bi->introduced == false)
- {
- Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" from " << bi->nick << " when not introduced";
- return;
- }
-
- message_source = u->GetUID();
- }
-
- if (!UplinkSock)
- {
- if (!message_source.empty())
- Log(LOG_DEBUG) << "Attempted to send \"" << message_source << " " << this->buffer.str() << "\" with UplinkSock NULL";
- else
- Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" with UplinkSock NULL";
- return;
- }
-
- Anope::string sent = IRCD->Format(message_source, this->buffer.str());
- UplinkSock->Write(sent);
- Log(LOG_RAWIO) << "Sent: " << sent;
+ // This is all temporary as UplinkSocket::Message is going to to die as soon
+ // as everything is migrated to Uplink::Send.
+ Anope::map<Anope::string> tags;
+ Anope::string unused, command;
+ std::vector<Anope::string> params;
+ if (IRCD->Parse(this->buffer.str(), tags, unused, command, params))
+ Uplink::SendInternal(tags, source, command, params);
}