Merge branch 'insp3' into master.

This commit is contained in:
Sadie Powell 2020-02-19 01:29:45 +00:00
commit 7bdd72f634
43 changed files with 313 additions and 143 deletions

View File

@ -35,5 +35,5 @@ Tick the boxes for the checks you have made.
I have ensured that:
- [ ] This pull request does not introduce any incompatible API changes.
- [ ] If ABI changes have been made I have incremented INSPIRCD_VERSION_API.
- [ ] If ABI changes have been made I have incremented MODULE_ABI in `moduledefs.h`.
- [ ] I have documented any features added by this pull request.

View File

@ -14,8 +14,10 @@ jobs:
- uses: actions/checkout@v2
- name: Install dependencies
run: |
brew update
brew upgrade
brew install pkg-config gnutls libmaxminddb libpq mbedtls mysql-client openssl@1.1 pcre re2 sqlite3 tre
brew link --force libpq
brew link --force mysql-client
brew link --force --overwrite libpq
brew link --force --overwrite mysql-client
- name: Run test-build
run: ./tools/test-build c++

View File

@ -4,7 +4,7 @@ InspIRCd is a modular C++ Internet Relay Chat (IRC) server for UNIX-like and Win
## Supported Platforms
InspIRCd is supported on on the following platforms:
InspIRCd is supported on the following platforms:
- Most recent BSD variants using the Clang 3.8+ or GCC 5+ compilers and the GNU toolchains (Make, etc).

2
configure vendored
View File

@ -430,7 +430,7 @@ print_format <<"EOM";
<|GREEN Execution User:|> $config{USER} ($config{UID})
<|GREEN Socket Engine:|> $config{SOCKETENGINE}
To build with these settings run '<|GREEN make -j${\get_cpu_count} install|>' now.
To build with these settings run '<|GREEN make -j${\get_cpu_count + 1} install|>' now.
EOM

View File

@ -901,7 +901,7 @@
# other modules that need it using the libMaxMindDB library. #
# #
# This module is in extras. Re-run configure with: #
# ./configure --enable-extras=m_geo_maxmind.cpp
# ./configure --enable-extras geo_maxmind
# and run make install, then uncomment this module to enable it. #
# #
# This module requires libMaxMindDB to be installed on your system. #
@ -1220,7 +1220,7 @@
# LDAP module: Allows other SQL modules to access a LDAP database
# through a unified API.
# This modules is in extras. Re-run configure with:
# ./configure --enable-extras=m_ldap.cpp
# ./configure --enable-extras ldap
# and run make install, then uncomment this module to enable it.
#
#<module name="ldap">
@ -1364,7 +1364,7 @@
# MySQL module: Allows other SQL modules to access MySQL databases
# through a unified API.
# This module is in extras. Re-run configure with:
# ./configure --enable-extras=m_mysql.cpp
# ./configure --enable-extras mysql
# and run make install, then uncomment this module to enable it.
#<module name="mysql">
#
@ -1655,7 +1655,7 @@
# PostgreSQL module: Allows other SQL modules to access PgSQL databases
# through a unified API.
# This module is in extras. Re-run configure with:
# ./configure --enable-extras=m_pgsql.cpp
# ./configure --enable-extras pgsql
# and run make install, then uncomment this module to enable it.
#<module name="pgsql">
#
@ -2058,7 +2058,7 @@
# SSL rehash signal module: Allows the SSL modules to be rehashed by
# sending SIGUSR1 to a running InspIRCd process.
# This modules is in extras. Re-run configure with:
# ./configure --enable-extras=m_sslrehashsignal.cpp
# ./configure --enable-extras sslrehashsignal
# and run make install, then uncomment this module to enable it.
#<module name="sslrehashsignal">
@ -2135,7 +2135,7 @@
# SQLite3 module: Allows other SQL modules to access SQLite3 #
# databases through a unified API. #
# This module is in extras. Re-run configure with: #
# ./configure --enable-extras=m_sqlite3.cpp
# ./configure --enable-extras sqlite3
# and run make install, then uncomment this module to enable it. #
#
#<module name="sqlite3">

View File

@ -52,6 +52,11 @@ class IRCv3::Replies::Reply
user->Send(ev);
}
void SendNoticeInternal(LocalUser* user, Command* command, const std::string& description)
{
user->WriteNotice(InspIRCd::Format("*** %s: %s", command->name.c_str(), description.c_str()));
}
protected:
/** Initializes a new instance of the Reply class.
* @param Creator The module which created this instance.
@ -163,7 +168,57 @@ class IRCv3::Replies::Reply
if (cap.get(user))
Send(user, command, code, description);
else
user->WriteNotice(InspIRCd::Format("*** %s: %s", command->name.c_str(), description.c_str()));
SendNoticeInternal(user, command, description);
}
template<typename T1>
void SendIfCap(LocalUser* user, const Cap::Capability& cap, Command* command, const std::string& code,
const T1& p1, const std::string& description)
{
if (cap.get(user))
Send(user, command, code, p1, description);
else
SendNoticeInternal(user, command, description);
}
template<typename T1, typename T2>
void SendIfCap(LocalUser* user, const Cap::Capability& cap, Command* command, const std::string& code,
const T1& p1, const T2& p2, const std::string& description)
{
if (cap.get(user))
Send(user, command, code, p1, p2, description);
else
SendNoticeInternal(user, command, description);
}
template<typename T1, typename T2, typename T3>
void SendIfCap(LocalUser* user, const Cap::Capability& cap, Command* command, const std::string& code,
const T1& p1, const T2& p2, const T3& p3, const std::string& description)
{
if (cap.get(user))
Send(user, command, code, p1, p2, p3, description);
else
SendNoticeInternal(user, command, description);
}
template<typename T1, typename T2, typename T3, typename T4>
void SendIfCap(LocalUser* user, const Cap::Capability& cap, Command* command, const std::string& code,
const T1& p1, const T2& p2, const T3& p3, const T4& p4, const std::string& description)
{
if (cap.get(user))
Send(user, command, code, p1, p2, p3, p4, description);
else
SendNoticeInternal(user, command, description);
}
template<typename T1, typename T2, typename T3, typename T4, typename T5>
void SendIfCap(LocalUser* user, const Cap::Capability& cap, Command* command, const std::string& code,
const T1& p1, const T2& p2, const T3& p3, const T4& p4, const T5& p5, const std::string& description)
{
if (cap.get(user))
Send(user, command, code, p1, p2, p3, p4, p5, description);
else
SendNoticeInternal(user, command, description);
}
};

View File

@ -50,6 +50,7 @@ enum
RPL_ENDMAP = 17, // ircu
RPL_MAPUSERS = 18, // insp-specific
RPL_STATS = 210, // From aircd.
RPL_UMODEIS = 221,
RPL_LUSERCLIENT = 251,
@ -85,8 +86,6 @@ enum
RPL_USERIP = 340,
RPL_INVITING = 341,
RPL_INVITELIST = 346, // insp-specific (stolen from ircu)
RPL_ENDOFINVITELIST = 347, // insp-specific (stolen from ircu)
RPL_VERSION = 351,
RPL_NAMREPLY = 353,
RPL_LINKS = 364,

View File

@ -182,6 +182,9 @@ class CoreExport EventHandler : public classbase
*/
inline int GetFd() const { return fd; }
/** Checks if this event handler has a fd associated with it. */
inline bool HasFd() const { return fd >= 0; }
inline int GetEventMask() const { return event_mask; }
/** Set a new file desciptor

View File

@ -528,14 +528,12 @@ class CoreExport XLineManager
*/
void ApplyLines();
/** Handle /STATS for a given type.
* NOTE: Any items in the list for this particular line type which have expired
* will be expired and removed before the list is displayed.
* @param type The type of stats to show
* @param numeric The numeric to give to each result line
* @param stats Stats context
/** Generates a /STATS response for the given X-line type.
* @param type The type of X-line to look up.
* @param context The stats context to respond with.
* @return True if a response was sent; otherwise, false.
*/
void InvokeStats(const std::string& type, unsigned int numeric, Stats::Context& stats);
bool InvokeStats(const std::string& type, Stats::Context& context);
/** Expire X-lines which were added by the server configuration and have been removed. */
void ExpireRemovedConfigLines(const std::string& type, const insp::flat_set<std::string>& configlines);

View File

@ -31,6 +31,13 @@
#include "core_channel.h"
#include "invite.h"
enum
{
// From ircd-hybrid.
RPL_INVITELIST = 336,
RPL_ENDOFINVITELIST = 337
};
CommandInvite::CommandInvite(Module* parent, Invite::APIImpl& invapiimpl)
: Command(parent, "INVITE", 0, 0)
, invapi(invapiimpl)

View File

@ -50,6 +50,13 @@ namespace Invite
};
}
enum
{
// From RFC 1459.
RPL_BANLIST = 367,
RPL_ENDOFBANLIST = 368
};
/** Handle /INVITE.
*/
class CommandInvite : public Command
@ -164,7 +171,7 @@ class ModeChannelBan : public ListModeBase
{
public:
ModeChannelBan(Module* Creator)
: ListModeBase(Creator, "ban", 'b', "End of channel ban list", 367, 368, true)
: ListModeBase(Creator, "ban", 'b', "End of channel ban list", RPL_BANLIST, RPL_ENDOFBANLIST, true)
{
syntax = "<mask>";
}

View File

@ -701,7 +701,7 @@ class MyManager : public Manager, public Timer, public EventHandler
void Rehash(const std::string& dnsserver, std::string sourceaddr, unsigned int sourceport)
{
if (this->GetFd() > -1)
if (this->HasFd())
{
SocketEngine::Shutdown(this, 2);
SocketEngine::Close(this);

View File

@ -720,11 +720,9 @@ class ReloadAction : public ActionBase
ReloadModule::DataKeeper datakeeper;
datakeeper.Save(mod);
DLLManager* dll = mod->ModuleDLLManager;
std::string name = mod->ModuleSourceFile;
ServerInstance->Modules.DoSafeUnload(mod);
ServerInstance->GlobalCulls.Apply();
delete dll;
bool result = ServerInstance->Modules.Load(name);
if (result)

View File

@ -195,19 +195,19 @@ void CommandStats::DoStats(Stats::Context& stats)
break;
case 'k':
ServerInstance->XLines->InvokeStats("K",216,stats);
ServerInstance->XLines->InvokeStats("K", stats);
break;
case 'g':
ServerInstance->XLines->InvokeStats("G",223,stats);
ServerInstance->XLines->InvokeStats("G", stats);
break;
case 'q':
ServerInstance->XLines->InvokeStats("Q",217,stats);
ServerInstance->XLines->InvokeStats("Q", stats);
break;
case 'Z':
ServerInstance->XLines->InvokeStats("Z",223,stats);
ServerInstance->XLines->InvokeStats("Z", stats);
break;
case 'e':
ServerInstance->XLines->InvokeStats("E",223,stats);
ServerInstance->XLines->InvokeStats("E", stats);
break;
case 'E':
{

View File

@ -130,7 +130,7 @@ ListenSocket::ListenSocket(ConfigTag* tag, const irc::sockets::sockaddrs& bind_t
ListenSocket::~ListenSocket()
{
if (this->GetFd() > -1)
if (this->HasFd())
{
ServerInstance->Logs.Log("SOCKET", LOG_DEBUG, "Shut down listener on fd %d", this->fd);
SocketEngine::Shutdown(this, 2);

View File

@ -57,6 +57,8 @@ Version::Version(const std::string &desc, int flags, const std::string& linkdata
// These declarations define the behavours of the base class Module (which does nothing at all)
CullResult Module::cull()
{
if (ModuleDLLManager)
ServerInstance->GlobalCulls.AddItem(ModuleDLLManager);
return classbase::cull();
}
@ -441,11 +443,8 @@ namespace
UnloadAction(Module* m) : mod(m) {}
void Call() override
{
DLLManager* dll = mod->ModuleDLLManager;
ServerInstance->Modules.DoSafeUnload(mod);
ServerInstance->GlobalCulls.Apply();
// In pure static mode this is always NULL
delete dll;
ServerInstance->GlobalCulls.AddItem(this);
}
};

View File

@ -24,13 +24,18 @@
#include "inspircd.h"
#include "listmode.h"
/** Handles +w channel mode
*/
enum
{
// InspIRCd-specific.
RPL_ACCESSLIST = 910,
RPL_ENDOFACCESSLIST = 911
};
class AutoOpList : public ListModeBase
{
public:
AutoOpList(Module* Creator)
: ListModeBase(Creator, "autoop", 'w', "End of Channel Access List", 910, 911, true)
: ListModeBase(Creator, "autoop", 'w', "End of Channel Access List", RPL_ACCESSLIST, RPL_ENDOFACCESSLIST, true)
{
ranktoset = ranktounset = OP_VALUE;
syntax = "<prefix>:<mask>";

View File

@ -27,28 +27,23 @@
#include "listmode.h"
#include "modules/isupport.h"
/* Written by Om<om@inspircd.org>, April 2005. */
/* Rewritten to use the listmode utility by Om, December 2005 */
/* Adapted from m_exception, which was originally based on m_chanprotect and m_silence */
enum
{
// From RFC 2812.
RPL_EXCEPTLIST = 348,
RPL_ENDOFEXCEPTLIST = 349
};
// The +e channel mode takes a nick!ident@host, glob patterns allowed,
// and if a user matches an entry on the +e list then they can join the channel, overriding any (+b) bans set on them
// Now supports CIDR and IP addresses -- Brain
/** Handles +e channel mode
*/
class BanException : public ListModeBase
{
public:
BanException(Module* Creator)
: ListModeBase(Creator, "banexception", 'e', "End of Channel Exception List", 348, 349, true)
: ListModeBase(Creator, "banexception", 'e', "End of Channel Exception List", RPL_EXCEPTLIST, RPL_ENDOFEXCEPTLIST, true)
{
syntax = "<mask>";
}
};
class ModuleBanException
: public Module
, public ISupport::EventListener

View File

@ -188,7 +188,7 @@ class ModuleCBan : public Module, public Stats::EventListener
if (stats.GetSymbol() != 'C')
return MOD_RES_PASSTHRU;
ServerInstance->XLines->InvokeStats("CBAN", 210, stats);
ServerInstance->XLines->InvokeStats("CBAN", stats);
return MOD_RES_DENY;
}

View File

@ -27,15 +27,20 @@
#include "listmode.h"
#include "modules/exemption.h"
/** Handles channel mode +g
*/
enum
{
// InspIRCd-specific.
RPL_ENDOFSPAMFILTER = 940,
RPL_SPAMFILTER = 941
};
class ChanFilter : public ListModeBase
{
public:
unsigned long maxlen;
ChanFilter(Module* Creator)
: ListModeBase(Creator, "filter", 'g', "End of channel spamfilter list", 941, 940, false)
: ListModeBase(Creator, "filter", 'g', "End of channel spamfilter list", RPL_SPAMFILTER, RPL_ENDOFSPAMFILTER, false)
{
syntax = "<pattern>";
}

View File

@ -154,6 +154,8 @@ class DCCAllowExt : public SimpleExtItem<dccallowlist>
list->push_back(dccallow);
}
// The value was well formed.
set(user, list);
}
std::string ToInternal(const Extensible* container, void* item) const override

View File

@ -25,13 +25,17 @@
#include "listmode.h"
#include "modules/exemption.h"
/** Handles channel mode +X
*/
enum
{
RPL_ENDOFEXEMPTIONLIST = 953,
RPL_EXEMPTIONLIST = 954
};
class ExemptChanOps : public ListModeBase
{
public:
ExemptChanOps(Module* Creator)
: ListModeBase(Creator, "exemptchanops", 'X', "End of channel exemptchanops list", 954, 953, false)
: ListModeBase(Creator, "exemptchanops", 'X', "End of channel exemptchanops list", RPL_EXEMPTIONLIST, RPL_ENDOFEXEMPTIONLIST, false)
{
syntax = "<restriction>:<prefix>";
}

View File

@ -897,7 +897,7 @@ ModResult ModuleFilter::OnStats(Stats::Context& stats)
{
for (std::vector<FilterResult>::iterator i = filters.begin(); i != filters.end(); i++)
{
stats.AddRow(223, RegexEngine.GetProvider()+":"+i->freeform+" "+i->GetFlags()+" "+FilterActionToString(i->action)+" "+ConvToStr(i->duration)+" :"+i->reason);
stats.AddRow(223, RegexEngine.GetProvider(), i->freeform, i->GetFlags(), FilterActionToString(i->action), i->duration, i->reason);
}
for (ExemptTargetSet::const_iterator i = exemptedchans.begin(); i != exemptedchans.end(); ++i)
{

View File

@ -234,10 +234,12 @@ class HttpServerSocket : public BufferedSocket, public Timer, public insp::intru
void SendHTTPError(unsigned int response)
{
HTTPHeaders empty;
static HTTPHeaders empty;
std::string data = InspIRCd::Format(
"<html><head></head><body>Server error %u: %s<br>"
"<small>Powered by <a href='https://www.inspircd.org'>InspIRCd</a></small></body></html>", response, http_status_str((http_status)response));
"<html><head></head><body style='font-family: sans-serif; text-align: center'>"
"<h1 style='font-size: 48pt'>Error %u</h1><h2 style='font-size: 24pt'>%s</h2><hr>"
"<small>Powered by <a href='https://www.inspircd.org'>InspIRCd</a></small></body></html>",
response, http_status_str((http_status)response));
Page(data, response, &empty);
}

View File

@ -103,7 +103,13 @@ class ModuleHTTPAccessList : public Module, public HTTPACLEventListener
{
ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "BlockAccess (%u)", returnval);
std::stringstream data("Access to this resource is denied by an access control list. Please contact your IRC administrator.");
std::stringstream data;
data << "<html><head></head><body style='font-family: sans-serif; text-align: center'>"
<< "<h1 style='font-size: 48pt'>Error " << returnval << "</h1>"
<< "<h2 style='font-size: 24pt'>Access to this resource is denied by an access control list.</h2>"
<< "<h2 style='font-size: 24pt'>Please contact your IRC administrator.</h2><hr>"
<< "<small>Powered by <a href='https://www.inspircd.org'>InspIRCd</a></small></body></html>";
HTTPDocumentResponse response(this, *http, &data, returnval);
response.headers.SetHeader("X-Powered-By", MODNAME);
if (!extraheaderkey.empty())

View File

@ -187,7 +187,7 @@ class IdentRequestSocket : public EventHandler
/* Remove ident socket from engine, and close it, but dont detatch it
* from its parent user class, or attempt to delete its memory.
*/
if (GetFd() > -1)
if (HasFd())
{
ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "Close ident socket %d", GetFd());
SocketEngine::Close(this);

View File

@ -27,23 +27,18 @@
#include "listmode.h"
#include "modules/isupport.h"
/*
* Written by Om <om@inspircd.org>, April 2005.
* Based on m_exception, which was originally based on m_chanprotect and m_silence
*
* The +I channel mode takes a nick!ident@host, glob patterns allowed,
* and if a user matches an entry on the +I list then they can join the channel,
* ignoring if +i is set on the channel
* Now supports CIDR and IP addresses -- Brain
*/
enum
{
// From RFC 2812.
RPL_INVEXLIST = 346,
RPL_ENDOFINVEXLIST = 347
};
/** Handles channel mode +I
*/
class InviteException : public ListModeBase
{
public:
InviteException(Module* Creator)
: ListModeBase(Creator, "invex", 'I', "End of Channel Invite Exception List", 346, 347, true)
: ListModeBase(Creator, "invex", 'I', "End of Channel Invite Exception List", RPL_INVEXLIST, RPL_ENDOFINVEXLIST, true)
{
syntax = "<mask>";
}

View File

@ -103,7 +103,7 @@ class ModuleIRCv3CapNotify : public Module, public Cap::EventListener, public Re
continue;
// Check that this user can actually see the cap.
if (!cap->OnList(user))
if (add && (!cap || !cap->OnList(user)))
continue;
// If the cap is being added and the client supports cap values then show the value, if any

View File

@ -70,6 +70,7 @@ class STSCap : public Cap::Capability
STSCap(Module* mod)
: Cap::Capability(mod, "sts")
{
DisableAutoRegister();
}
~STSCap()
@ -173,6 +174,9 @@ class ModuleIRCv3STS : public Module
unsigned long duration = tag->getDuration("duration", 60*60*24*30*2);
bool preload = tag->getBool("preload");
cap.SetPolicy(host, duration, port, preload);
if (!cap.IsRegistered())
ServerInstance->Modules.AddService(cap);
}
Version GetVersion() override

View File

@ -33,6 +33,8 @@ enum
ERR_CANNOTKNOCK = 480,
// From ircd-ratbox.
RPL_KNOCK = 710,
RPL_KNOCKDLVR = 711,
ERR_CHANOPEN = 713,
ERR_KNOCKONCHAN = 714
};
@ -84,18 +86,22 @@ class CommandKnock : public Command
}
if (sendnotice)
{
c->WriteNotice(InspIRCd::Format("User %s is KNOCKing on %s (%s)", user->nick.c_str(), c->name.c_str(), parameters[1].c_str()));
user->WriteNotice("KNOCKing on " + c->name);
}
if (sendnumeric)
{
Numeric::Numeric numeric(710);
Numeric::Numeric numeric(RPL_KNOCK);
numeric.push(c->name).push(user->GetFullHost()).push("is KNOCKing: " + parameters[1]);
ClientProtocol::Messages::Numeric numericmsg(numeric, c->name);
c->Write(ServerInstance->GetRFCEvents().numeric, numericmsg);
user->WriteNumeric(RPL_KNOCKDLVR, c->name, "KNOCKing on channel");
}
user->WriteNotice("KNOCKing on " + c->name);
return CMD_SUCCESS;
}

View File

@ -306,7 +306,7 @@ class ModuleRLine : public Module, public Stats::EventListener
if (stats.GetSymbol() != 'R')
return MOD_RES_PASSTHRU;
ServerInstance->XLines->InvokeStats("R", 223, stats);
ServerInstance->XLines->InvokeStats("R", stats);
return MOD_RES_DENY;
}

View File

@ -26,45 +26,58 @@
#include "inspircd.h"
#include "modules/ircv3.h"
#include "modules/ircv3_replies.h"
class CommandSetname : public Command
class CommandSetName : public SplitCommand
{
private:
IRCv3::Replies::Fail fail;
public:
Cap::Capability cap;
bool notifyopers;
CommandSetname(Module* Creator) : Command(Creator,"SETNAME", 1, 1)
CommandSetName(Module* Creator)
: SplitCommand(Creator, "SETNAME", 1, 1)
, fail(Creator)
, cap(Creator, "setname")
{
allow_empty_last_param = false;
syntax = ":<realname>";
}
CmdResult Handle(User* user, const Params& parameters) override
CmdResult HandleLocal(LocalUser* user, const Params& parameters) override
{
if (parameters[0].size() > ServerInstance->Config->Limits.MaxReal)
{
user->WriteNotice("*** SETNAME: Real name is too long");
fail.SendIfCap(user, cap, this, "INVALID_REALNAME", "Real name is too long");
return CMD_FAILURE;
}
if (user->ChangeRealName(parameters[0]))
if (!user->ChangeRealName(parameters[0]))
{
if (notifyopers)
ServerInstance->SNO.WriteGlobalSno('a', "%s used SETNAME to change their real name to '%s'",
user->nick.c_str(), parameters[0].c_str());
fail.SendIfCap(user, cap, this, "CANNOT_CHANGE_REALNAME", "Unable to change your real name");
return CMD_FAILURE;
}
if (notifyopers)
ServerInstance->SNO.WriteGlobalSno('a', "%s used SETNAME to change their real name to '%s'",
user->nick.c_str(), parameters[0].c_str());
return CMD_SUCCESS;
}
};
class ModuleSetName : public Module
{
CommandSetname cmd;
private:
CommandSetName cmd;
ClientProtocol::EventProvider setnameevprov;
public:
ModuleSetName()
: cmd(this)
, setnameevprov(this, "SETNAME")
{
}
@ -80,6 +93,17 @@ class ModuleSetName : public Module
cmd.notifyopers = tag->getBool("notifyopers", !operonly);
}
void OnChangeRealName(User* user, const std::string& real) override
{
if (!(user->registered & REG_NICKUSER))
return;
ClientProtocol::Message msg("SETNAME", user);
msg.PushParamRef(real);
ClientProtocol::Event protoev(setnameevprov, msg);
IRCv3::WriteNeighborsWithCap(user, protoev, cmd.cap, true);
}
Version GetVersion() override
{
return Version("Provides the SETNAME command", VF_VENDOR);

View File

@ -187,7 +187,7 @@ class ModuleShun : public Module, public Stats::EventListener
if (stats.GetSymbol() != 'H')
return MOD_RES_PASSTHRU;
ServerInstance->XLines->InvokeStats("SHUN", 223, stats);
ServerInstance->XLines->InvokeStats("SHUN", stats);
return MOD_RES_DENY;
}

View File

@ -219,11 +219,7 @@ void ModuleSpanningTree::ConnectServer(Link* x, Autoconnect* y)
{
// Create a TreeServer object that will start connecting immediately in the background
TreeSocket* newsocket = new TreeSocket(x, y, sa);
if (newsocket->GetFd() > -1)
{
/* Handled automatically on success */
}
else
if (!newsocket->HasFd())
{
ServerInstance->SNO.WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: %s.",
x->Name.c_str(), newsocket->getError().c_str());

View File

@ -71,11 +71,7 @@ void ServernameResolver::OnLookupComplete(const DNS::Query *r)
if (!CheckDupe) /* Check that nobody tried to connect it successfully while we were resolving */
{
TreeSocket* newsocket = new TreeSocket(MyLink, myautoconnect, sa);
if (newsocket->GetFd() > -1)
{
/* We're all OK */
}
else
if (!newsocket->HasFd())
{
/* Something barfed, show the opers */
ServerInstance->SNO.WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: %s.",

View File

@ -203,7 +203,7 @@ class ModuleSVSHold : public Module, public Stats::EventListener
if (stats.GetSymbol() != 'S')
return MOD_RES_PASSTHRU;
ServerInstance->XLines->InvokeStats("SVSHOLD", 210, stats);
ServerInstance->XLines->InvokeStats("SVSHOLD", stats);
return MOD_RES_DENY;
}

View File

@ -47,7 +47,7 @@ bool InspIRCd::BindPort(ConfigTag* tag, const irc::sockets::sockaddrs& sa, std::
}
ListenSocket* ll = new ListenSocket(tag, sa);
if (ll->GetFd() < 0)
if (!ll->HasFd())
{
ServerInstance->Logs.Log("SOCKET", LOG_DEFAULT, "Failed to listen on %s from tag at %s: %s",
sa.str().c_str(), tag->getTagLocation().c_str(), strerror(errno));

View File

@ -180,11 +180,7 @@ EventHandler* SocketEngine::GetRef(int fd)
bool SocketEngine::BoundsCheckFd(EventHandler* eh)
{
if (!eh)
return false;
if (eh->GetFd() < 0)
return false;
return true;
return eh && eh->HasFd();
}

View File

@ -477,34 +477,30 @@ void XLineManager::ApplyLines()
pending_lines.clear();
}
void XLineManager::InvokeStats(const std::string& type, unsigned int numeric, Stats::Context& stats)
bool XLineManager::InvokeStats(const std::string& type, Stats::Context& context)
{
ContainerIter n = lookup_lines.find(type);
ContainerIter citer = lookup_lines.find(type);
if (citer == lookup_lines.end())
return false;
time_t current = ServerInstance->Time();
LookupIter safei;
if (n != lookup_lines.end())
for (LookupIter liter = citer->second.begin(); liter != citer->second.end(); )
{
XLineLookup& list = n->second;
for (LookupIter i = list.begin(); i != list.end(); )
// We might be about to expire the XLine so we have to increment the
// iterator early to avoid doing that causing iterator invalidation.
LookupIter current = liter++;
XLine* xline = current->second;
if (xline->duration && xline->expiry <= ServerInstance->Time())
{
safei = i;
safei++;
if (i->second->duration && current > i->second->expiry)
{
ExpireLine(n, i);
}
else
stats.AddRow(numeric, i->second->Displayable()+" "+
ConvToStr(i->second->set_time)+" "+ConvToStr(i->second->duration)+" "+i->second->source+" :"+i->second->reason);
i = safei;
// This XLine has expired so remove and skip it.
ExpireLine(citer, current);
continue;
}
}
}
context.AddRow(RPL_STATS, context.GetSymbol(), xline->Displayable(), xline->set_time, xline->duration, xline->source, xline->reason);
}
return true;
}
XLineManager::XLineManager()
{

View File

@ -64,7 +64,7 @@ foreach my $compiler (@compilers) {
say "Failed to configure using the $compiler compiler and the $socketengine socket engine!";
exit 1;
}
if (execute 'make', '--jobs', get_cpu_count, 'install') {
if (execute 'make', '--jobs', get_cpu_count + 1, 'install') {
say "Failed to compile using the $compiler compiler and the $socketengine socket engine!";
exit 1;
}

2
vendor/README.md vendored
View File

@ -18,7 +18,7 @@ This directory contains vendored dependencies that are shipped with InspIRCd to
**License** &mdash; MIT License
**Version** &mdash; v2.9.2
**Version** &mdash; v2.9.3
**Website** &mdash; [https://github.com/nodejs/http-parser](https://github.com/nodejs/http-parser)

View File

@ -381,7 +381,10 @@ enum header_states
, h_transfer_encoding
, h_upgrade
, h_matching_transfer_encoding_token_start
, h_matching_transfer_encoding_chunked
, h_matching_transfer_encoding_token
, h_matching_connection_token_start
, h_matching_connection_keep_alive
, h_matching_connection_close
@ -1335,6 +1338,7 @@ reexecute:
parser->header_state = h_general;
} else if (parser->index == sizeof(TRANSFER_ENCODING)-2) {
parser->header_state = h_transfer_encoding;
parser->flags |= F_TRANSFER_ENCODING;
}
break;
@ -1416,10 +1420,14 @@ reexecute:
if ('c' == c) {
parser->header_state = h_matching_transfer_encoding_chunked;
} else {
parser->header_state = h_general;
parser->header_state = h_matching_transfer_encoding_token;
}
break;
/* Multi-value `Transfer-Encoding` header */
case h_matching_transfer_encoding_token_start:
break;
case h_content_length:
if (UNLIKELY(!IS_NUM(ch))) {
SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
@ -1563,16 +1571,41 @@ reexecute:
goto error;
/* Transfer-Encoding: chunked */
case h_matching_transfer_encoding_token_start:
/* looking for 'Transfer-Encoding: chunked' */
if ('c' == c) {
h_state = h_matching_transfer_encoding_chunked;
} else if (STRICT_TOKEN(c)) {
/* TODO(indutny): similar code below does this, but why?
* At the very least it seems to be inconsistent given that
* h_matching_transfer_encoding_token does not check for
* `STRICT_TOKEN`
*/
h_state = h_matching_transfer_encoding_token;
} else if (c == ' ' || c == '\t') {
/* Skip lws */
} else {
h_state = h_general;
}
break;
case h_matching_transfer_encoding_chunked:
parser->index++;
if (parser->index > sizeof(CHUNKED)-1
|| c != CHUNKED[parser->index]) {
h_state = h_general;
h_state = h_matching_transfer_encoding_token;
} else if (parser->index == sizeof(CHUNKED)-2) {
h_state = h_transfer_encoding_chunked;
}
break;
case h_matching_transfer_encoding_token:
if (ch == ',') {
h_state = h_matching_transfer_encoding_token_start;
parser->index = 0;
}
break;
case h_matching_connection_token_start:
/* looking for 'Connection: keep-alive' */
if (c == 'k') {
@ -1631,7 +1664,7 @@ reexecute:
break;
case h_transfer_encoding_chunked:
if (ch != ' ') h_state = h_general;
if (ch != ' ') h_state = h_matching_transfer_encoding_token;
break;
case h_connection_keep_alive:
@ -1765,12 +1798,17 @@ reexecute:
REEXECUTE();
}
/* Cannot use chunked encoding and a content-length header together
per the HTTP specification. */
if ((parser->flags & F_CHUNKED) &&
/* Cannot us transfer-encoding and a content-length header together
per the HTTP specification. (RFC 7230 Section 3.3.3) */
if ((parser->flags & F_TRANSFER_ENCODING) &&
(parser->flags & F_CONTENTLENGTH)) {
SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
goto error;
/* Allow it for lenient parsing as long as `Transfer-Encoding` is
* not `chunked`
*/
if (!lenient || (parser->flags & F_CHUNKED)) {
SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
goto error;
}
}
UPDATE_STATE(s_headers_done);
@ -1845,8 +1883,31 @@ reexecute:
UPDATE_STATE(NEW_MESSAGE());
CALLBACK_NOTIFY(message_complete);
} else if (parser->flags & F_CHUNKED) {
/* chunked encoding - ignore Content-Length header */
/* chunked encoding - ignore Content-Length header,
* prepare for a chunk */
UPDATE_STATE(s_chunk_size_start);
} else if (parser->flags & F_TRANSFER_ENCODING) {
if (parser->type == HTTP_REQUEST && !lenient) {
/* RFC 7230 3.3.3 */
/* If a Transfer-Encoding header field
* is present in a request and the chunked transfer coding is not
* the final encoding, the message body length cannot be determined
* reliably; the server MUST respond with the 400 (Bad Request)
* status code and then close the connection.
*/
SET_ERRNO(HPE_INVALID_TRANSFER_ENCODING);
RETURN(p - data); /* Error */
} else {
/* RFC 7230 3.3.3 */
/* If a Transfer-Encoding header field is present in a response and
* the chunked transfer coding is not the final encoding, the
* message body length is determined by reading the connection until
* it is closed by the server.
*/
UPDATE_STATE(s_body_identity_eof);
}
} else {
if (parser->content_length == 0) {
/* Content-Length header given but zero: Content-Length: 0\r\n */
@ -2100,6 +2161,12 @@ http_message_needs_eof (const http_parser *parser)
return 0;
}
/* RFC 7230 3.3.3, see `s_headers_almost_done` */
if ((parser->flags & F_TRANSFER_ENCODING) &&
(parser->flags & F_CHUNKED) == 0) {
return 1;
}
if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) {
return 0;
}

View File

@ -27,7 +27,7 @@ extern "C" {
/* Also update SONAME in the Makefile whenever you change these. */
#define HTTP_PARSER_VERSION_MAJOR 2
#define HTTP_PARSER_VERSION_MINOR 9
#define HTTP_PARSER_VERSION_PATCH 2
#define HTTP_PARSER_VERSION_PATCH 3
#include <stddef.h>
#if defined(_WIN32) && !defined(__MINGW32__) && \
@ -225,6 +225,7 @@ enum flags
, F_UPGRADE = 1 << 5
, F_SKIPBODY = 1 << 6
, F_CONTENTLENGTH = 1 << 7
, F_TRANSFER_ENCODING = 1 << 8
};
@ -271,6 +272,8 @@ enum flags
"unexpected content-length header") \
XX(INVALID_CHUNK_SIZE, \
"invalid character in chunk size header") \
XX(INVALID_TRANSFER_ENCODING, \
"request has invalid transfer-encoding") \
XX(INVALID_CONSTANT, "invalid constant string") \
XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\
XX(STRICT, "strict mode assertion failed") \
@ -293,11 +296,11 @@ enum http_errno {
struct http_parser {
/** PRIVATE **/
unsigned int type : 2; /* enum http_parser_type */
unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */
unsigned int state : 7; /* enum state from http_parser.c */
unsigned int header_state : 7; /* enum header_state from http_parser.c */
unsigned int index : 7; /* index into current matcher */
unsigned int lenient_http_headers : 1;
unsigned int flags : 16; /* F_* values from 'flags' enum; semi-public */
uint32_t nread; /* # bytes read in various scenarios */
uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */