From 1efc234a54bd66714f9743ca7d1f3d5c0be3628e Mon Sep 17 00:00:00 2001 From: Sadie Powell Date: Thu, 12 Mar 2020 17:27:11 +0000 Subject: Implement support for the SERVLIST command. --- include/moduledefs.h | 2 +- include/usermanager.h | 11 +++--- src/coremods/core_info/cmd_servlist.cpp | 59 +++++++++++++++++++++++++++++++++ src/coremods/core_info/core_info.cpp | 4 ++- src/coremods/core_info/core_info.h | 10 ++++++ src/usermanager.cpp | 1 - src/users.cpp | 6 ++-- 7 files changed, 83 insertions(+), 10 deletions(-) create mode 100644 src/coremods/core_info/cmd_servlist.cpp diff --git a/include/moduledefs.h b/include/moduledefs.h index 9f54e3eeb..a706a8883 100644 --- a/include/moduledefs.h +++ b/include/moduledefs.h @@ -22,7 +22,7 @@ class Module; /** The version of the InspIRCd ABI which is presently in use. */ -#define MODULE_ABI 3011UL +#define MODULE_ABI 3012UL /** Stringifies the value of a symbol. */ #define MODULE_STRINGIFY_SYM1(DEF) MODULE_STRINGIFY_SYM2(DEF) diff --git a/include/usermanager.h b/include/usermanager.h index ad09d968c..2a18393ab 100644 --- a/include/usermanager.h +++ b/include/usermanager.h @@ -46,6 +46,9 @@ class CoreExport UserManager : public fakederef */ typedef std::vector OperList; + /** A list containing users who are on a U-lined servers. */ + typedef std::vector ULineList; + /** A list holding local users */ typedef insp::intrusive_list LocalList; @@ -89,14 +92,14 @@ class CoreExport UserManager : public fakederef */ OperList all_opers; + /** A list of users on U-lined servers. */ + ULineList all_ulines; + /** Number of unregistered users online right now. * (Unregistered means before USER/NICK/dns) */ unsigned int unregistered_count; - /** The number of users on U-lined servers. */ - unsigned int uline_count; - /** Perform background user events for all local users such as PING checks, registration timeouts, * penalty management and recvq processing for users who have data in their recvq due to throttling. */ @@ -175,7 +178,7 @@ class CoreExport UserManager : public fakederef /** Return a count of users on a u-lined servers. * @return The number of users on u-lined servers. */ - unsigned int ULineCount() const { return this->uline_count; } + unsigned int ULineCount() const { return this->all_ulines.size(); } /** Return a count of local registered users * @return The number of registered local users diff --git a/src/coremods/core_info/cmd_servlist.cpp b/src/coremods/core_info/cmd_servlist.cpp new file mode 100644 index 000000000..f400124d2 --- /dev/null +++ b/src/coremods/core_info/cmd_servlist.cpp @@ -0,0 +1,59 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2020 Sadie Powell + * + * This file is part of InspIRCd. InspIRCd 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. + * + * 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 . + */ + + +#include "inspircd.h" +#include "core_info.h" + +enum +{ + // From RFC 2812. + RPL_SERVLIST = 234, + RPL_SERVLISTEND = 235 +}; + +CommandServList::CommandServList(Module* parent) + : SplitCommand(parent, "SERVLIST") + , invisiblemode(parent, "invisible") +{ + allow_empty_last_param = false; + syntax = "[]"; +} + +CmdResult CommandServList::HandleLocal(LocalUser* user, const Params& parameters) +{ + const std::string& mask = parameters.empty() ? "*" : parameters[0]; + for (UserManager::ULineList::const_iterator iter = ServerInstance->Users.all_ulines.begin(); iter != ServerInstance->Users.all_ulines.end(); ++iter) + { + User* uline = *iter; + if (uline->IsModeSet(invisiblemode) || !InspIRCd::Match(uline->nick, mask)) + continue; + + Numeric::Numeric numeric(RPL_SERVLIST); + numeric + .push(uline->nick) + .push(uline->server->GetName()) + .push(mask) + .push(0) + .push(0) + .push(uline->GetRealName()); + user->WriteNumeric(numeric); + } + user->WriteNumeric(RPL_SERVLISTEND, mask, 0, "End of service listing"); + return CMD_SUCCESS; +} diff --git a/src/coremods/core_info/core_info.cpp b/src/coremods/core_info/core_info.cpp index 507e43250..b172372e5 100644 --- a/src/coremods/core_info/core_info.cpp +++ b/src/coremods/core_info/core_info.cpp @@ -46,6 +46,7 @@ class CoreModInfo : public Module CommandInfo cmdinfo; CommandModules cmdmodules; CommandMotd cmdmotd; + CommandServList cmdservlist; CommandTime cmdtime; CommandVersion cmdversion; Numeric::Numeric numeric004; @@ -91,6 +92,7 @@ class CoreModInfo : public Module , cmdinfo(this) , cmdmodules(this) , cmdmotd(this) + , cmdservlist(this) , cmdtime(this) , cmdversion(this) , numeric004(RPL_MYINFO) @@ -176,7 +178,7 @@ class CoreModInfo : public Module Version GetVersion() CXX11_OVERRIDE { - return Version("Provides the ADMIN, COMMANDS, INFO, MODULES, MOTD, TIME, and VERSION commands", VF_VENDOR|VF_CORE); + return Version("Provides the ADMIN, COMMANDS, INFO, MODULES, MOTD, TIME, SERVLIST, and VERSION commands", VF_VENDOR|VF_CORE); } }; diff --git a/src/coremods/core_info/core_info.h b/src/coremods/core_info/core_info.h index 08aab4cd1..ecd4f78e7 100644 --- a/src/coremods/core_info/core_info.h +++ b/src/coremods/core_info/core_info.h @@ -137,6 +137,16 @@ class CommandMotd : public ServerTargetCommand CmdResult Handle(User* user, const Params& parameters) CXX11_OVERRIDE; }; +class CommandServList : public SplitCommand +{ + private: + UserModeReference invisiblemode; + + public: + CommandServList(Module* parent); + CmdResult HandleLocal(LocalUser* user, const Params& parameters) CXX11_OVERRIDE; +}; + /** Handle /TIME. */ class CommandTime : public ServerTargetCommand diff --git a/src/usermanager.cpp b/src/usermanager.cpp index 9c8bde1e2..812f43113 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -119,7 +119,6 @@ namespace UserManager::UserManager() : already_sent_id(0) , unregistered_count(0) - , uline_count(0) { } diff --git a/src/users.cpp b/src/users.cpp index 0c95ecc0b..2571d15f2 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -91,7 +91,7 @@ User::User(const std::string& uid, Server* srv, UserType type) ServerInstance->Logs->Log("USERS", LOG_DEBUG, "New UUID for user: %s", uuid.c_str()); if (srv->IsULine()) - ServerInstance->Users->uline_count++; + ServerInstance->Users.all_ulines.push_back(this); // Do not insert FakeUsers into the uuidlist so FindUUID() won't return them which is the desired behavior if (type != USERTYPE_SERVER) @@ -354,8 +354,8 @@ CullResult User::cull() if (client_sa.family() != AF_UNSPEC) ServerInstance->Users->RemoveCloneCounts(this); - if (server->IsULine() && ServerInstance->Users->uline_count) - ServerInstance->Users->uline_count--; + if (server->IsULine()) + stdalgo::erase(ServerInstance->Users->all_ulines, this); return Extensible::cull(); } -- cgit v1.2.3