1
0
mirror of https://github.com/anope/anope.git synced 2026-07-08 07:43:15 +02:00

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.
This commit is contained in:
Sadie Powell
2024-02-21 16:35:27 +00:00
parent 3ecf6b495b
commit c4ab550ec7
6 changed files with 130 additions and 56 deletions
+5
View File
@@ -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;
+12 -2
View File
@@ -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;
+27 -1
View File
@@ -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;
+2 -2
View File
@@ -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);
}
};
+61 -5
View File
@@ -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)
+23 -46
View File
@@ -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);
}