summaryrefslogtreecommitdiff
path: root/src/protocol.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/protocol.cpp')
-rw-r--r--src/protocol.cpp318
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> &params)
{
- 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> &params, const Anope::map<Anope::string> &tags)
-{
- // Most IRCds don't support message tags yet so use the tagless variant.
- Run(source, params);
-}
-