diff --git a/doc/conf/rpc.modules.default.conf b/doc/conf/rpc.modules.default.conf index 115475f6f..2d15ba506 100644 --- a/doc/conf/rpc.modules.default.conf +++ b/doc/conf/rpc.modules.default.conf @@ -28,6 +28,7 @@ loadmodule "websocket_common"; loadmodule "rpc/rpc"; /* Now the actual RPC call handlers */ +loadmodule "rpc/stats"; loadmodule "rpc/user"; loadmodule "rpc/server"; loadmodule "rpc/channel"; diff --git a/src/modules/rpc/Makefile.in b/src/modules/rpc/Makefile.in index 0821a7d80..612ca151e 100644 --- a/src/modules/rpc/Makefile.in +++ b/src/modules/rpc/Makefile.in @@ -32,7 +32,7 @@ INCLUDES = ../../include/channel.h \ ../../include/version.h ../../include/whowas.h R_MODULES= \ - rpc.so user.so server.so channel.so server_ban.so server_ban_exception.so name_ban.so spamfilter.so + rpc.so stats.so user.so server.so channel.so server_ban.so server_ban_exception.so name_ban.so spamfilter.so MODULES=$(R_MODULES) MODULEFLAGS=@MODULEFLAGS@ diff --git a/src/modules/rpc/stats.c b/src/modules/rpc/stats.c new file mode 100644 index 000000000..44f6dd727 --- /dev/null +++ b/src/modules/rpc/stats.c @@ -0,0 +1,173 @@ +/* stats.* RPC calls + * (C) Copyright 2022-.. Bram Matthys (Syzop) and the UnrealIRCd team + * License: GPLv2 or later + */ + +#include "unrealircd.h" + +ModuleHeader MOD_HEADER += { + "rpc/stats", + "1.0.0", + "stats.* RPC calls", + "UnrealIRCd Team", + "unrealircd-6", +}; + +/* Forward declarations */ +void rpc_stats_get(Client *client, json_t *request, json_t *params); + +MOD_INIT() +{ + RPCHandlerInfo r; + + MARK_AS_OFFICIAL_MODULE(modinfo); + + memset(&r, 0, sizeof(r)); + r.method = "stats.get"; + r.loglevel = ULOG_DEBUG; + r.call = rpc_stats_get; + if (!RPCHandlerAdd(modinfo->handle, &r)) + { + config_error("[rpc/stats] Could not register RPC handler"); + return MOD_FAILED; + } + + return MOD_SUCCESS; +} + +MOD_LOAD() +{ + return MOD_SUCCESS; +} + +MOD_UNLOAD() +{ + return MOD_SUCCESS; +} + +void rpc_stats_user(json_t *main) +{ + Client *client; + int total = 0, ulined = 0, oper = 0; + json_t *child = json_object(); + json_object_set_new(main, "user", child); + + list_for_each_entry(client, &client_list, client_node) + { + if (IsUser(client)) + { + total++; + if (IsULine(client)) + ulined++; + else if (IsOper(client)) + oper++; + } + } + + json_object_set_new(child, "total", json_integer(total)); + json_object_set_new(child, "ulined", json_integer(ulined)); + json_object_set_new(child, "oper", json_integer(oper)); + json_object_set_new(child, "record", json_integer(irccounts.global_max)); +} + +void rpc_stats_channel(json_t *main) +{ + json_t *child = json_object(); + json_object_set_new(main, "channel", child); + json_object_set_new(child, "total", json_integer(irccounts.channels)); +} + +void rpc_stats_server(json_t *main) +{ + Client *client; + int total = 0, ulined = 0, oper = 0; + json_t *child = json_object(); + json_object_set_new(main, "server", child); + + total++; /* ourselves */ + list_for_each_entry(client, &global_server_list, client_node) + { + if (IsServer(client)) + { + total++; + if (IsULine(client)) + ulined++; + } + } + + json_object_set_new(child, "total", json_integer(total)); + json_object_set_new(child, "ulined", json_integer(ulined)); +} + +void rpc_stats_server_ban(json_t *main) +{ + Client *client; + int index, index2; + TKL *tkl; + int total = 0; + int server_ban = 0; + int server_ban_exception = 0; + int spamfilter = 0; + int name_ban = 0; + json_t *child = json_object(); + json_object_set_new(main, "server_ban", child); + + /* First, hashed entries.. */ + for (index = 0; index < TKLIPHASHLEN1; index++) + { + for (index2 = 0; index2 < TKLIPHASHLEN2; index2++) + { + for (tkl = tklines_ip_hash[index][index2]; tkl; tkl = tkl->next) + { + total++; + if (TKLIsServerBan(tkl)) + server_ban++; + else if (TKLIsBanException(tkl)) + server_ban_exception++; + else if (TKLIsNameBan(tkl)) + name_ban++; + else if (TKLIsSpamfilter(tkl)) + spamfilter++; + } + } + } + + /* Now normal entries.. */ + for (index = 0; index < TKLISTLEN; index++) + { + for (tkl = tklines[index]; tkl; tkl = tkl->next) + { + total++; + if (TKLIsServerBan(tkl)) + server_ban++; + else if (TKLIsBanException(tkl)) + server_ban_exception++; + else if (TKLIsNameBan(tkl)) + name_ban++; + else if (TKLIsSpamfilter(tkl)) + spamfilter++; + } + } + + json_object_set_new(child, "total", json_integer(total)); + json_object_set_new(child, "server_ban", json_integer(server_ban)); + json_object_set_new(child, "spamfilter", json_integer(spamfilter)); + json_object_set_new(child, "name_ban", json_integer(name_ban)); + json_object_set_new(child, "server_ban_exception", json_integer(server_ban_exception)); +} + +void rpc_stats_get(Client *client, json_t *request, json_t *params) +{ + json_t *result, *item; + const char *statsname; + Channel *stats; + + result = json_object(); + rpc_stats_server(result); + rpc_stats_user(result); + rpc_stats_channel(result); + rpc_stats_server_ban(result); + rpc_response(client, request, result); + json_decref(result); +}