summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);
}