diff options
Diffstat (limited to 'include/protocol.h')
-rw-r--r-- | include/protocol.h | 395 |
1 files changed, 200 insertions, 195 deletions
diff --git a/include/protocol.h b/include/protocol.h index 08d4c304d..89186ccd1 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -1,236 +1,98 @@ /* + * Anope IRC Services * - * (C) 2003-2017 Anope Team - * Contact us at team@anope.org + * Copyright (C) 2012-2017 Anope Team <team@anope.org> * - * Please read COPYING and README for further details. + * This file is part of Anope. Anope 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. * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. + * 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 see <http://www.gnu.org/licenses/>. */ -#ifndef PROTOCOL_H -#define PROTOCOL_H +#pragma once #include "services.h" #include "anope.h" #include "service.h" +#include "servers.h" +#include "users.h" +#include "messages.h" + +class IRCMessage; /* Encapsultes the IRCd protocol we are speaking. */ class CoreExport IRCDProto : public Service { Anope::string proto_name; - protected: - IRCDProto(Module *creator, const Anope::string &proto_name); - public: - virtual ~IRCDProto(); - - virtual void SendSVSKillInternal(const MessageSource &, User *, const Anope::string &); - virtual void SendModeInternal(const MessageSource &, const Channel *, const Anope::string &); - virtual void SendModeInternal(const MessageSource &, User *, const Anope::string &); - virtual void SendKickInternal(const MessageSource &, const Channel *, User *, const Anope::string &); - virtual void SendNoticeInternal(const MessageSource &, const Anope::string &dest, const Anope::string &msg); - virtual void SendPrivmsgInternal(const MessageSource &, const Anope::string &dest, const Anope::string &buf); - virtual void SendQuitInternal(User *, const Anope::string &buf); - virtual void SendPartInternal(User *, const Channel *chan, const Anope::string &buf); - virtual void SendGlobopsInternal(const MessageSource &, const Anope::string &buf); - virtual void SendCTCPInternal(const MessageSource &, const Anope::string &dest, const Anope::string &buf); - virtual void SendNumericInternal(int numeric, const Anope::string &dest, const Anope::string &buf); - - const Anope::string &GetProtocolName(); - virtual void Parse(const Anope::string &, Anope::string &, Anope::string &, std::vector<Anope::string> &); - virtual Anope::string Format(const Anope::string &source, const Anope::string &message); +public: + static constexpr const char *NAME = "ircdproto"; /* Modes used by default by our clients */ - Anope::string DefaultPseudoclientModes; + Anope::string DefaultPseudoclientModes = "+io"; /* Can we force change a users's nick? */ - bool CanSVSNick; + bool CanSVSNick = false; /* Can we force join or part users? */ - bool CanSVSJoin; + bool CanSVSJoin = false; /* Can we set vhosts/vidents on users? */ - bool CanSetVHost, CanSetVIdent; + bool CanSetVHost = false, CanSetVIdent = false; /* Can we ban specific gecos from being used? */ - bool CanSNLine; + bool CanSNLine = false; /* Can we ban specific nicknames from being used? */ - bool CanSQLine; + bool CanSQLine = false; /* Can we ban sepcific channel names from being used? */ - bool CanSQLineChannel; + bool CanSQLineChannel = false; /* Can we ban by IP? */ - bool CanSZLine; + bool CanSZLine = false; /* Can we place temporary holds on specific nicknames? */ - bool CanSVSHold; - /* See os_oline */ - bool CanSVSO; + bool CanSVSHold = false; /* See ns_cert */ - bool CanCertFP; + bool CanCertFP = false; /* Whether this IRCd requires unique IDs for each user or server. See TS6/P10. */ - bool RequiresID; + bool RequiresID = false; /* If this IRCd has unique ids, whether the IDs and nicknames are ambiguous */ - bool AmbiguousID; + bool AmbiguousID = false; /* The maximum number of modes we are allowed to set with one MODE command */ - unsigned MaxModes; + unsigned int MaxModes = 3; /* The maximum number of bytes a line may have */ - unsigned MaxLine; - - /* Retrieves the next free UID or SID */ - virtual Anope::string UID_Retrieve(); - virtual Anope::string SID_Retrieve(); - - /** Sets the server in NOOP mode. If NOOP mode is enabled, no users - * will be able to oper on the server. - * @param s The server - * @param mode Whether to turn NOOP on or off - */ - virtual void SendSVSNOOP(const Server *s, bool mode) { } + unsigned int MaxLine = 512; - /** Sets the topic on a channel - * @param bi The bot to set the topic from - * @param c The channel to set the topic on. The topic being set is Channel::topic - */ - virtual void SendTopic(const MessageSource &, Channel *); - - /** Sets a vhost on a user. - * @param u The user - * @param vident The ident to set - * @param vhost The vhost to set - */ - virtual void SendVhost(User *u, const Anope::string &vident, const Anope::string &vhost) { } - virtual void SendVhostDel(User *) { } - - /** Sets an akill. This is a recursive function that can be called multiple times - * for the same xline, but for different users, if the xline is not one that can be - * enforced by the IRCd, such as a nick/user/host/realname combination ban. - * @param u The user affected by the akill, if known - * @param x The akill - */ - virtual void SendAkill(User *, XLine *) = 0; - virtual void SendAkillDel(const XLine *) = 0; - - /* Realname ban */ - virtual void SendSGLine(User *, const XLine *) { } - virtual void SendSGLineDel(const XLine *) { } - - /* IP ban */ - virtual void SendSZLine(User *u, const XLine *) { } - virtual void SendSZLineDel(const XLine *) { } - - /* Nick ban (and sometimes channel) */ - virtual void SendSQLine(User *, const XLine *x) { } - virtual void SendSQLineDel(const XLine *x) { } - - virtual void SendKill(const MessageSource &source, const Anope::string &target, const Anope::string &reason); - - /** Kills a user - * @param source Who is doing the kill - * @param user The user to be killed - * @param fmt Kill reason - */ - virtual void SendSVSKill(const MessageSource &source, User *user, const char *fmt, ...); - - virtual void SendMode(const MessageSource &source, const Channel *dest, const char *fmt, ...); - virtual void SendMode(const MessageSource &source, User *u, const char *fmt, ...); - - /** Introduces a client to the rest of the network - * @param u The client to introduce - */ - virtual void SendClientIntroduction(User *u) = 0; - - virtual void SendKick(const MessageSource &source, const Channel *chan, User *user, const char *fmt, ...); - - virtual void SendNotice(const MessageSource &source, const Anope::string &dest, const char *fmt, ...); - virtual void SendPrivmsg(const MessageSource &source, const Anope::string &dest, const char *fmt, ...); - virtual void SendAction(const MessageSource &source, const Anope::string &dest, const char *fmt, ...); - virtual void SendCTCP(const MessageSource &source, const Anope::string &dest, const char *fmt, ...); - - virtual void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) = 0; - virtual void SendGlobalPrivmsg(BotInfo *bi, const Server *desc, const Anope::string &msg) = 0; + IRCDProto(Module *creator, const Anope::string &proto_name); + virtual ~IRCDProto(); - virtual void SendQuit(User *u, const char *fmt, ...); - virtual void SendPing(const Anope::string &servname, const Anope::string &who); - virtual void SendPong(const Anope::string &servname, const Anope::string &who); + const Anope::string &GetProtocolName() const; - /** Joins one of our users to a channel. - * @param u The user to join - * @param c The channel to join the user to - * @param status The status to set on the user after joining. This may or may not already internally - * be set on the user. This may include the modes in the join, but will usually place them on the mode - * stacker to be set "soon". - */ - virtual void SendJoin(User *u, Channel *c, const ChannelStatus *status) = 0; - virtual void SendPart(User *u, const Channel *chan, const char *fmt, ...); - - /** Force joins a user that isn't ours to a channel. - * @param bi The source of the message - * @param u The user to join - * @param chan The channel to join the user to - * @param param Channel key? - */ - virtual void SendSVSJoin(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string ¶m) { } + virtual void Parse(const Anope::string &, Anope::string &, Anope::string &, std::vector<Anope::string> &); + virtual Anope::string Format(IRCMessage &); - /** Force parts a user that isn't ours from a channel. - * @param source The source of the message - * @param u The user to part - * @param chan The channel to part the user from - * @param param part reason, some IRCds don't support this - */ - virtual void SendSVSPart(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string ¶m) { } + virtual void SendCTCPReply(const MessageSource &, const Anope::string &dest, const Anope::string &buf); + virtual void SendNumeric(int numeric, User *dest, IRCMessage &); - virtual void SendInvite(const MessageSource &source, const Channel *c, User *u); - virtual void SendGlobops(const MessageSource &source, const char *fmt, ...); + /* Retrieves the next free UID or SID */ + virtual Anope::string UID_Retrieve() { return ""; } + virtual Anope::string SID_Retrieve() { return ""; } - /** Sets oper flags on a user, currently only supported by Unreal - */ - virtual void SendSVSO(BotInfo *, const Anope::string &, const Anope::string &) { } - /** Sends a nick change of one of our clients. - */ - virtual void SendNickChange(User *u, const Anope::string &newnick); + virtual void SendAction(const MessageSource &source, const Anope::string &dest, const Anope::string &message); - /** Forces a nick change of a user that isn't ours (SVSNICK) + /** Used to introduce ourselves to our uplink. */ - virtual void SendForceNickChange(User *u, const Anope::string &newnick, time_t when); + virtual void Handshake() anope_abstract; - /** Used to introduce ourselves to our uplink. Usually will SendServer(Me) and any other - * initial handshake requirements. - */ - virtual void SendConnect() = 0; - /** Called right before we begin our burst, after we have handshaked successfully with the uplink. * At this point none of our servers, users, or channels exist on the uplink */ virtual void SendBOB() { } virtual void SendEOB() { } - virtual void SendSVSHold(const Anope::string &, time_t) { } - virtual void SendSVSHoldDel(const Anope::string &) { } - - virtual void SendSWhois(const MessageSource &, const Anope::string &, const Anope::string &) { } - - /** Introduces a server to the uplink - */ - virtual void SendServer(const Server *) = 0; - virtual void SendSquit(Server *, const Anope::string &message); - - virtual void SendNumeric(int numeric, const Anope::string &dest, const char *fmt, ...); - - virtual void SendLogin(User *u, NickAlias *na) = 0; - virtual void SendLogout(User *u) = 0; - - /** Send a channel creation message to the uplink. - * On most TS6 IRCds this is a SJOIN with no nick - */ - virtual void SendChannel(Channel *c) { } - - /** Make the user an IRC operator - * Normally this is a simple +o, though some IRCds require us to send the oper type - */ - virtual void SendOper(User *u); - - virtual void SendSASLMechanisms(std::vector<Anope::string> &) { } - virtual void SendSASLMessage(const SASL::Message &) { } - virtual void SendSVSLogin(const Anope::string &uid, const Anope::string &acc, const Anope::string &vident, const Anope::string &vhost) { } - virtual bool IsNickValid(const Anope::string &); virtual bool IsChannelValid(const Anope::string &); virtual bool IsIdentValid(const Anope::string &); @@ -240,25 +102,98 @@ class CoreExport IRCDProto : public Service /** Retrieve the maximum number of list modes settable on this channel * Defaults to Config->ListSize */ - virtual unsigned GetMaxListFor(Channel *c); + virtual unsigned int GetMaxListFor(Channel *c); virtual Anope::string NormalizeMask(const Anope::string &mask); + + template<typename T, typename... Args> void Send(Args&&... args) + { + ServiceReference<MessageSender<T>> sender(T::NAME); + + if (!sender) + { + const char *const name = T::NAME; + Anope::Logger.Debug("No message sender for type {0}", name); + return; + } + + static_cast<T*>(static_cast<MessageSender<T>*>(sender))->Send(std::forward<Args>(args)...); + } + + /* Templated functions which overload the normal functions to provide format strings */ + template<typename... Args> void SendKill(const MessageSource &source, User *user, const Anope::string &reason, Args&&... args) + { + Send<messages::Kill>(source, user, Anope::Format(reason, std::forward<Args>(args)...)); + } + + template<typename... Args> void SendMode(const MessageSource &source, Channel *chan, const Anope::string &modes, Args&&... args) + { + Send<messages::ModeChannel>(source, chan, Anope::Format(modes, std::forward<Args>(args)...)); + } + + template<typename... Args> void SendMode(const MessageSource &source, User *u, const Anope::string &modes, Args&&... args) + { + Send<messages::ModeUser>(source, u, Anope::Format(modes, std::forward<Args>(args)...)); + } + + template<typename... Args> void SendKick(const MessageSource &source, Channel *chan, User *user, const Anope::string &reason, Args&&... args) + { + Send<messages::Kick>(source, chan, user, Anope::Format(reason, std::forward<Args>(args)...)); + } + + template<typename... Args> void SendNotice(const MessageSource &source, const Anope::string &dest, const Anope::string &message, Args&&... args) + { + Send<messages::Notice>(source, dest, Anope::Format(message, std::forward<Args>(args)...)); + } + + template<typename... Args> void SendPrivmsg(const MessageSource &source, const Anope::string &dest, const Anope::string &message, Args&&... args) + { + Send<messages::Privmsg>(source, dest, Anope::Format(message, std::forward<Args>(args)...)); + } + + template<typename... Args> void SendAction(const MessageSource &source, const Anope::string &dest, const Anope::string &message, Args&&... args) + { + SendAction(source, dest, Anope::Format(message, std::forward<Args>(args)...)); + } + + template<typename... Args> void SendCTCPReply(const MessageSource &source, const Anope::string &dest, const Anope::string &message, Args&&... args) + { + SendCTCPReply(source, dest, Anope::Format(message, std::forward<Args>(args)...)); + } + + template<typename... Args> void SendWallops(const MessageSource &source, const Anope::string &msg, Args&&... args) + { + Send<messages::Wallops>(source, Anope::Format(msg, std::forward<Args>(args)...)); + } + + template<typename... Args> void SendNumeric(int numeric, User *dest, Args&&... args); + + template<typename... Args> void SendQuit(User *u, const Anope::string &reason, Args&&... args) + { + Send<messages::Quit>(u, Anope::Format(reason, std::forward<Args>(args)...)); + } + + template<typename... Args> void SendPart(User *u, Channel *chan, const Anope::string &reason, Args&&... args) + { + Send<messages::Part>(u, chan, Anope::Format(reason, std::forward<Args>(args)...)); + } }; class CoreExport MessageSource { Anope::string source; - User *u; - Server *s; + User *u = nullptr; + Server *s = nullptr; public: MessageSource(const Anope::string &); MessageSource(User *u); MessageSource(Server *s); const Anope::string &GetName() const; + const Anope::string &GetUID() const; const Anope::string &GetSource() const; User *GetUser() const; - BotInfo *GetBot() const; + ServiceBot *GetBot() const; Server *GetServer() const; }; @@ -272,12 +207,14 @@ enum IRCDMessageFlag class CoreExport IRCDMessage : public Service { Anope::string name; - unsigned param_count; + unsigned int param_count; std::set<IRCDMessageFlag> flags; public: - IRCDMessage(Module *owner, const Anope::string &n, unsigned p = 0); - unsigned GetParamCount() const; - virtual void Run(MessageSource &, const std::vector<Anope::string> ¶ms) = 0; + static constexpr const char *NAME = "ircdmessage"; + + IRCDMessage(Module *owner, const Anope::string &n, unsigned int p = 0); + unsigned int GetParamCount() const; + virtual void Run(MessageSource &, const std::vector<Anope::string> ¶ms) anope_abstract; void SetFlag(IRCDMessageFlag f) { flags.insert(f); } bool HasFlag(IRCDMessageFlag f) const { return flags.count(f); } @@ -285,4 +222,72 @@ class CoreExport IRCDMessage : public Service extern CoreExport IRCDProto *IRCD; -#endif // PROTOCOL_H +class IRCMessage +{ + MessageSource source; + Anope::string command; + std::vector<Anope::string> parameters; + + public: + template<typename... Args> + IRCMessage(const MessageSource &_source, const Anope::string &_command, Args&&... args) + : source(_source) + , command(_command) + { + parameters.reserve(sizeof...(args)); + + Push(std::forward<Args>(args)...); + } + + template<typename T, typename... Args> + void Push(const T& t, Args&&... args) + { + parameters.push_back(stringify(t)); + + Push(std::forward<Args>(args)...); + } + + void Push() { } + + void TokenizeAndPush(const Anope::string &buf, char sepToken = ' ') + { + sepstream sep(buf, sepToken); + Anope::string token; + while (sep.GetToken(token)) + Push(token); + } + + const MessageSource &GetSource() const + { + return source; + } + + void SetSource(const MessageSource &_source) + { + this->source = _source; + } + + const Anope::string &GetCommand() const + { + return command; + } + + const std::vector<Anope::string> &GetParameters() const + { + return parameters; + } +}; + +template<typename... Args> +void IRCDProto::SendNumeric(int numeric, User *dest, Args&&... args) +{ + Anope::string numstr = stringify(numeric); + if (numeric < 10) + numstr.insert(numstr.begin(), '0'); + if (numeric < 100) + numstr.insert(numstr.begin(), '0'); + + IRCMessage message(Me, numstr, dest->GetUID()); + message.Push(std::forward<Args>(args)...); + SendNumeric(numeric, dest, message); +} |