diff options
Diffstat (limited to 'src/protocol.cpp')
-rw-r--r-- | src/protocol.cpp | 318 |
1 files changed, 100 insertions, 218 deletions
diff --git a/src/protocol.cpp b/src/protocol.cpp index 9907a7f29..ad2bef770 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -18,17 +18,18 @@ #include "uplink.h" #include "bots.h" #include "channels.h" +#include "numeric.h" IRCDProto *IRCD = NULL; -IRCDProto::IRCDProto(Module *creator, const Anope::string &p) : Service(creator, "IRCDProto", creator->name), proto_name(p) +IRCDProto::IRCDProto(Module *creator, const Anope::string &p) + : Service(creator, "IRCDProto", creator->name) + , proto_name(p) + , MaxChannel(Config->GetBlock("networkinfo")->Get<unsigned>("chanlen", "32")) + , MaxHost(Config->GetBlock("networkinfo")->Get<unsigned>("hostlen", "64")) + , MaxNick(Config->GetBlock("networkinfo")->Get<unsigned>("nicklen", "31")) + , MaxUser(Config->GetBlock("networkinfo")->Get<unsigned>("userlen", "10")) { - DefaultPseudoclientModes = "+io"; - CanSVSNick = CanSVSJoin = CanSetVHost = CanSetVIdent = CanSNLine = CanSQLine = CanSQLineChannel - = CanSZLine = CanSVSHold = CanSVSO = CanCertFP = RequiresID = AmbiguousID = false; - MaxModes = 3; - MaxLine = 512; - if (IRCD == NULL) IRCD = this; } @@ -39,11 +40,6 @@ IRCDProto::~IRCDProto() IRCD = NULL; } -const Anope::string &IRCDProto::GetProtocolName() -{ - return this->proto_name; -} - static inline char nextID(int pos, Anope::string &buf) { char &c = buf[pos]; @@ -94,179 +90,112 @@ Anope::string IRCDProto::SID_Retrieve() return current_sid; } +time_t IRCDProto::ExtractTimestamp(const Anope::string &str) +{ + auto ts = Anope::TryConvert<time_t>(str); + if (!ts.has_value()) + throw ProtocolException("Invalid timestamp: " + str); + return ts.value(); +} + +void IRCDProto::SendError(const Anope::string &reason) +{ + Uplink::Send("ERROR", reason); +} + void IRCDProto::SendKill(const MessageSource &source, const Anope::string &target, const Anope::string &reason) { - UplinkSocket::Message(source) << "KILL " << target << " :" << reason; + Uplink::Send(source, "KILL", target, reason); } -void IRCDProto::SendSVSKillInternal(const MessageSource &source, User *user, const Anope::string &buf) +void IRCDProto::SendSVSKill(const MessageSource &source, User *user, const Anope::string &buf) { - UplinkSocket::Message(source) << "KILL " << user->GetUID() << " :" << buf; + Uplink::Send(source, "KILL", user->GetUID(), buf); } -void IRCDProto::SendModeInternal(const MessageSource &source, const Channel *dest, const Anope::string &buf) +void IRCDProto::SendModeInternal(const MessageSource &source, Channel *chan, const Anope::string &modes, const std::vector<Anope::string> &values) { - UplinkSocket::Message(source) << "MODE " << dest->name << " " << buf; + auto params = values; + params.insert(params.begin(), { chan->name, modes }); + Uplink::SendInternal({}, source, "MODE", params); } -void IRCDProto::SendModeInternal(const MessageSource &source, User *dest, const Anope::string &buf) +void IRCDProto::SendModeInternal(const MessageSource &source, User *dest, const Anope::string &modes, const std::vector<Anope::string> &values) { - UplinkSocket::Message(source) << "MODE " << dest->GetUID() << " " << buf; + auto params = values; + params.insert(params.begin(), { dest->GetUID(), modes }); + Uplink::SendInternal({}, source, "MODE", params); } -void IRCDProto::SendKickInternal(const MessageSource &source, const Channel *c, User *u, const Anope::string &r) +void IRCDProto::SendKick(const MessageSource &source, const Channel *c, User *u, const Anope::string &r) { if (!r.empty()) - UplinkSocket::Message(source) << "KICK " << c->name << " " << u->GetUID() << " :" << r; + Uplink::Send(source, "KICK", c->name, u->GetUID(), r); else - UplinkSocket::Message(source) << "KICK " << c->name << " " << u->GetUID(); + Uplink::Send(source, "KICK", c->name, u->GetUID()); } -void IRCDProto::SendNoticeInternal(const MessageSource &source, const Anope::string &dest, const Anope::string &msg) +void IRCDProto::SendNotice(const MessageSource &source, const Anope::string &dest, const Anope::string &msg, const Anope::map<Anope::string> &tags) { - UplinkSocket::Message(source) << "NOTICE " << dest << " :" << msg; + Uplink::Send(tags, source, "NOTICE", dest, msg.empty() ? " " : msg); } -void IRCDProto::SendPrivmsgInternal(const MessageSource &source, const Anope::string &dest, const Anope::string &buf) +void IRCDProto::SendPrivmsg(const MessageSource &source, const Anope::string &dest, const Anope::string &msg, const Anope::map<Anope::string> &tags) { - UplinkSocket::Message(source) << "PRIVMSG " << dest << " :" << buf; + Uplink::Send(tags, source, "PRIVMSG", dest, msg.empty() ? " " : msg); } -void IRCDProto::SendQuitInternal(User *u, const Anope::string &buf) +void IRCDProto::SendTagmsg(const MessageSource &source, const Anope::string &dest, const Anope::map<Anope::string> &tags) { - if (!buf.empty()) - UplinkSocket::Message(u) << "QUIT :" << buf; - else - UplinkSocket::Message(u) << "QUIT"; + if (CanTagMessage) + Uplink::Send(tags, source, "TAGMSG", dest); } -void IRCDProto::SendPartInternal(User *u, const Channel *chan, const Anope::string &buf) +void IRCDProto::SendQuit(User *u, const Anope::string &buf) { if (!buf.empty()) - UplinkSocket::Message(u) << "PART " << chan->name << " :" << buf; + Uplink::Send(u, "QUIT", buf); else - UplinkSocket::Message(u) << "PART " << chan->name; + Uplink::Send(u, "QUIT"); } -void IRCDProto::SendGlobopsInternal(const MessageSource &source, const Anope::string &buf) +void IRCDProto::SendPart(User *u, const Channel *chan, const Anope::string &buf) { - UplinkSocket::Message(source) << "GLOBOPS :" << buf; + if (!buf.empty()) + Uplink::Send(u, "PART", chan->name, buf); + else + Uplink::Send(u, "PART", chan->name); } -void IRCDProto::SendCTCPInternal(const MessageSource &source, const Anope::string &dest, const Anope::string &buf) +void IRCDProto::SendGlobops(const MessageSource &source, const Anope::string &message) { - Anope::string s = Anope::NormalizeBuffer(buf); - this->SendNoticeInternal(source, dest, "\1" + s + "\1"); + Uplink::Send(source, "GLOBOPS", message); } -void IRCDProto::SendNumericInternal(int numeric, const Anope::string &dest, const Anope::string &buf) +void IRCDProto::SendNumericInternal(int numeric, const Anope::string &dest, const std::vector<Anope::string> ¶ms) { - Anope::string n = stringify(numeric); + Anope::string n = Anope::ToString(numeric); if (numeric < 10) n = "0" + n; if (numeric < 100) n = "0" + n; - UplinkSocket::Message(Me) << n << " " << dest << " " << buf; -} - -void IRCDProto::SendTopic(const MessageSource &source, Channel *c) -{ - UplinkSocket::Message(source) << "TOPIC " << c->name << " :" << c->topic; -} -void IRCDProto::SendSVSKill(const MessageSource &source, User *user, const char *fmt, ...) -{ - if (!user || !fmt) - return; - - va_list args; - char buf[BUFSIZE] = ""; - va_start(args, fmt); - vsnprintf(buf, BUFSIZE - 1, fmt, args); - va_end(args); - SendSVSKillInternal(source, user, buf); -} - -void IRCDProto::SendMode(const MessageSource &source, const Channel *dest, const char *fmt, ...) -{ - va_list args; - char buf[BUFSIZE] = ""; - va_start(args, fmt); - vsnprintf(buf, BUFSIZE - 1, fmt, args); - va_end(args); - SendModeInternal(source, dest, buf); -} - -void IRCDProto::SendMode(const MessageSource &source, User *u, const char *fmt, ...) -{ - va_list args; - char buf[BUFSIZE] = ""; - va_start(args, fmt); - vsnprintf(buf, BUFSIZE - 1, fmt, args); - va_end(args); - SendModeInternal(source, u, buf); -} - -void IRCDProto::SendKick(const MessageSource &source, const Channel *chan, User *user, const char *fmt, ...) -{ - if (!chan || !user) - return; - - va_list args; - char buf[BUFSIZE] = ""; - va_start(args, fmt); - vsnprintf(buf, BUFSIZE - 1, fmt, args); - va_end(args); - SendKickInternal(source, chan, user, buf); -} - -void IRCDProto::SendNotice(const MessageSource &source, const Anope::string &dest, const char *fmt, ...) -{ - va_list args; - char buf[BUFSIZE] = ""; - va_start(args, fmt); - vsnprintf(buf, BUFSIZE - 1, fmt, args); - va_end(args); - SendNoticeInternal(source, dest, buf); -} - -void IRCDProto::SendAction(const MessageSource &source, const Anope::string &dest, const char *fmt, ...) -{ - va_list args; - char buf[BUFSIZE] = ""; - va_start(args, fmt); - vsnprintf(buf, BUFSIZE - 1, fmt, args); - va_end(args); - Anope::string actionbuf = Anope::string("\1ACTION ") + buf + '\1'; - SendPrivmsgInternal(source, dest, actionbuf); + auto newparams = params; + newparams.insert(newparams.begin(), dest); + Uplink::SendInternal({}, Me, n, newparams); } -void IRCDProto::SendPrivmsg(const MessageSource &source, const Anope::string &dest, const char *fmt, ...) -{ - va_list args; - char buf[BUFSIZE] = ""; - va_start(args, fmt); - vsnprintf(buf, BUFSIZE - 1, fmt, args); - va_end(args); - SendPrivmsgInternal(source, dest, buf); -} - -void IRCDProto::SendQuit(User *u, const char *fmt, ...) +void IRCDProto::SendTopic(const MessageSource &source, Channel *c) { - va_list args; - char buf[BUFSIZE] = ""; - va_start(args, fmt); - vsnprintf(buf, BUFSIZE - 1, fmt, args); - va_end(args); - SendQuitInternal(u, buf); + Uplink::Send(source, "TOPIC", c->name, c->topic); } void IRCDProto::SendPing(const Anope::string &servname, const Anope::string &who) { if (servname.empty()) - UplinkSocket::Message(Me) << "PING " << who; + Uplink::Send("PING", who); else - UplinkSocket::Message(Me) << "PING " << servname << " " << who; + Uplink::Send("PING", servname, who); } /** @@ -278,74 +207,29 @@ void IRCDProto::SendPing(const Anope::string &servname, const Anope::string &who void IRCDProto::SendPong(const Anope::string &servname, const Anope::string &who) { if (servname.empty()) - UplinkSocket::Message(Me) << "PONG " << who; + Uplink::Send("PONG", who); else - UplinkSocket::Message(Me) << "PONG " << servname << " " << who; + Uplink::Send("PONG", servname, who); } void IRCDProto::SendInvite(const MessageSource &source, const Channel *c, User *u) { - UplinkSocket::Message(source) << "INVITE " << u->GetUID() << " " << c->name; -} - -void IRCDProto::SendPart(User *user, const Channel *chan, const char *fmt, ...) -{ - if (fmt) - { - va_list args; - char buf[BUFSIZE] = ""; - va_start(args, fmt); - vsnprintf(buf, BUFSIZE - 1, fmt, args); - va_end(args); - SendPartInternal(user, chan, buf); - } - else - SendPartInternal(user, chan, ""); -} - -void IRCDProto::SendGlobops(const MessageSource &source, const char *fmt, ...) -{ - va_list args; - char buf[BUFSIZE] = ""; - va_start(args, fmt); - vsnprintf(buf, BUFSIZE - 1, fmt, args); - va_end(args); - SendGlobopsInternal(source, buf); + Uplink::Send(source, "INVITE", u->GetUID(), c->name); } void IRCDProto::SendSquit(Server *s, const Anope::string &message) { - UplinkSocket::Message() << "SQUIT " << s->GetSID() << " :" << message; + Uplink::Send("SQUIT", s->GetSID(), message); } void IRCDProto::SendNickChange(User *u, const Anope::string &newnick) { - UplinkSocket::Message(u) << "NICK " << newnick << " " << Anope::CurTime; + Uplink::Send(u, "NICK", newnick, Anope::CurTime); } void IRCDProto::SendForceNickChange(User *u, const Anope::string &newnick, time_t when) { - UplinkSocket::Message() << "SVSNICK " << u->GetUID() << " " << newnick << " " << when; -} - -void IRCDProto::SendCTCP(const MessageSource &source, const Anope::string &dest, const char *fmt, ...) -{ - va_list args; - char buf[BUFSIZE] = ""; - va_start(args, fmt); - vsnprintf(buf, BUFSIZE - 1, fmt, args); - va_end(args); - SendCTCPInternal(source, dest, buf); -} - -void IRCDProto::SendNumeric(int numeric, const Anope::string &dest, const char *fmt, ...) -{ - va_list args; - char buf[BUFSIZE] = ""; - va_start(args, fmt); - vsnprintf(buf, BUFSIZE - 1, fmt, args); - va_end(args); - SendNumericInternal(numeric, dest, buf); + Uplink::Send("SVSNICK", u->GetUID(), newnick, when); } bool IRCDProto::IsNickValid(const Anope::string &nick) @@ -364,10 +248,10 @@ bool IRCDProto::IsNickValid(const Anope::string &nick) Anope::string special = "[]\\`_^{|}"; for (unsigned i = 0; i < nick.length(); ++i) - if (!(nick[i] >= 'A' && nick[i] <= 'Z') && !(nick[i] >= 'a' && nick[i] <= 'z') + if ((nick[i] < 'A' || nick[i] > 'Z') && (nick[i] < 'a' || nick[i] > 'z') && special.find(nick[i]) == Anope::string::npos && (Config && Config->NickChars.find(nick[i]) == Anope::string::npos) - && (!i || (!(nick[i] >= '0' && nick[i] <= '9') && nick[i] != '-'))) + && (!i || ((nick[i] < '0' || nick[i] > '9') && nick[i] != '-'))) return false; return true; @@ -375,7 +259,7 @@ bool IRCDProto::IsNickValid(const Anope::string &nick) bool IRCDProto::IsChannelValid(const Anope::string &chan) { - if (chan.empty() || chan[0] != '#' || chan.length() > Config->GetBlock("networkinfo")->Get<unsigned>("chanlen")) + if (chan.empty() || chan[0] != '#' || chan.length() > IRCD->MaxChannel) return false; if (chan.find_first_of(" ,") != Anope::string::npos) @@ -386,13 +270,11 @@ bool IRCDProto::IsChannelValid(const Anope::string &chan) bool IRCDProto::IsIdentValid(const Anope::string &ident) { - if (ident.empty() || ident.length() > Config->GetBlock("networkinfo")->Get<unsigned>("userlen")) + if (ident.empty() || ident.length() > IRCD->MaxUser) return false; - for (unsigned i = 0; i < ident.length(); ++i) + for (auto c : ident) { - const char &c = ident[i]; - if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.' || c == '-') continue; @@ -404,7 +286,7 @@ bool IRCDProto::IsIdentValid(const Anope::string &ident) bool IRCDProto::IsHostValid(const Anope::string &host) { - if (host.empty() || host.length() > Config->GetBlock("networkinfo")->Get<unsigned>("hostlen")) + if (host.empty() || host.length() > IRCD->MaxHost) return false; const Anope::string &vhostdisablebe = Config->GetBlock("networkinfo")->Get<const Anope::string>("disallow_start_or_end"), @@ -416,11 +298,11 @@ bool IRCDProto::IsHostValid(const Anope::string &host) return false; int dots = 0; - for (unsigned i = 0; i < host.length(); ++i) + for (auto chr : host) { - if (host[i] == '.') + if (chr == '.') ++dots; - if (vhostchars.find_first_of(host[i]) == Anope::string::npos) + if (vhostchars.find_first_of(chr) == Anope::string::npos) return false; } @@ -429,18 +311,13 @@ bool IRCDProto::IsHostValid(const Anope::string &host) void IRCDProto::SendOper(User *u) { - SendNumericInternal(381, u->GetUID(), ":You are now an IRC operator (set by services)"); + SendNumeric(RPL_YOUREOPER, u->GetUID(), "You are now an IRC operator (set by services)"); u->SetMode(NULL, "OPER"); } -unsigned IRCDProto::GetMaxListFor(Channel *c) -{ - return c->HasMode("LBAN") ? 0 : Config->GetBlock("networkinfo")->Get<int>("modelistsize"); -} - -unsigned IRCDProto::GetMaxListFor(Channel *c, ChannelMode *cm) +size_t IRCDProto::GetMaxListFor(Channel *c, ChannelMode *cm) { - return GetMaxListFor(c); + return c->HasMode("LBAN") ? 0 : Config->GetBlock("networkinfo")->Get<size_t>("modelistsize", "100"); } Anope::string IRCDProto::NormalizeMask(const Anope::string &mask) @@ -450,7 +327,21 @@ Anope::string IRCDProto::NormalizeMask(const Anope::string &mask) return Entry("", mask).GetNUHMask(); } -MessageSource::MessageSource(const Anope::string &src) : source(src), u(NULL), s(NULL) +void IRCDProto::SendContextNotice(BotInfo *bi, User *target, Channel *context, const Anope::string &msg) +{ + IRCD->SendNotice(bi, target->GetUID(), Anope::printf("[%s] %s", context->name.c_str(), msg.c_str()), { + { "+draft/channel-context", context->name }, + }); +} + +void IRCDProto::SendContextPrivmsg(BotInfo *bi, User *target, Channel *context, const Anope::string &msg) +{ + IRCD->SendPrivmsg(bi, target->GetUID(), Anope::printf("[%s] %s", context->name.c_str(), msg.c_str()), { + { "+draft/channel-context", context->name }, + }); +} + +MessageSource::MessageSource(const Anope::string &src) : source(src) { /* no source for incoming message is our uplink */ if (src.empty()) @@ -461,11 +352,11 @@ MessageSource::MessageSource(const Anope::string &src) : source(src), u(NULL), s this->u = User::Find(src); } -MessageSource::MessageSource(User *_u) : source(_u ? _u->nick : ""), u(_u), s(NULL) +MessageSource::MessageSource(User *_u) : source(_u ? _u->nick : ""), u(_u) { } -MessageSource::MessageSource(Server *_s) : source(_s ? _s->GetName() : ""), u(NULL), s(_s) +MessageSource::MessageSource(Server *_s) : source(_s ? _s->GetName() : ""), s(_s) { } @@ -499,18 +390,9 @@ Server *MessageSource::GetServer() const return this->s; } -IRCDMessage::IRCDMessage(Module *o, const Anope::string &n, unsigned p) : Service(o, "IRCDMessage", o->name + "/" + n.lower()), name(n), param_count(p) -{ -} - -unsigned IRCDMessage::GetParamCount() const +IRCDMessage::IRCDMessage(Module *o, const Anope::string &n, size_t pc) + : Service(o, "IRCDMessage", o->name + "/" + n.lower()) + , name(n) + , param_count(pc) { - return this->param_count; } - -void IRCDMessage::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags) -{ - // Most IRCds don't support message tags yet so use the tagless variant. - Run(source, params); -} - |