diff options
-rw-r--r-- | include/anope.h | 5 | ||||
-rw-r--r-- | include/protocol.h | 14 | ||||
-rw-r--r-- | include/uplink.h | 28 | ||||
-rw-r--r-- | modules/protocol/ngircd.cpp | 4 | ||||
-rw-r--r-- | src/process.cpp | 66 | ||||
-rw-r--r-- | src/uplink.cpp | 69 |
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> ¶ms); - 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> ¶ms); /* 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> ¶ms) 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> ¶ms) { - 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> ¶ms) +{ + 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); } |