pissircd/src/modules/rpc/log.c

197 lines
4.3 KiB
C

/* log.* RPC calls
* (C) Copyright 2023-.. Bram Matthys (Syzop) and the UnrealIRCd team
* License: GPLv2 or later
*/
#include "unrealircd.h"
ModuleHeader MOD_HEADER
= {
"rpc/log",
"1.0.2",
"log.* RPC calls",
"UnrealIRCd Team",
"unrealircd-6",
};
/* Forward declarations */
void rpc_log_hook_subscribe(Client *client, json_t *request, json_t *params);
void rpc_log_hook_unsubscribe(Client *client, json_t *request, json_t *params);
void rpc_log_list(Client *client, json_t *request, json_t *params);
int rpc_log_hook(LogLevel loglevel, const char *subsystem, const char *event_id, MultiLine *msg, json_t *json, const char *json_serialized, const char *timebuf);
MOD_INIT()
{
RPCHandlerInfo r;
MARK_AS_OFFICIAL_MODULE(modinfo);
memset(&r, 0, sizeof(r));
r.method = "log.subscribe";
r.loglevel = ULOG_DEBUG;
r.call = rpc_log_hook_subscribe;
if (!RPCHandlerAdd(modinfo->handle, &r))
{
config_error("[rpc/log] Could not register RPC handler");
return MOD_FAILED;
}
memset(&r, 0, sizeof(r));
r.method = "log.unsubscribe";
r.loglevel = ULOG_DEBUG;
r.call = rpc_log_hook_unsubscribe;
if (!RPCHandlerAdd(modinfo->handle, &r))
{
config_error("[rpc/log] Could not register RPC handler");
return MOD_FAILED;
}
memset(&r, 0, sizeof(r));
r.method = "log.list";
r.loglevel = ULOG_DEBUG;
r.call = rpc_log_list;
if (!RPCHandlerAdd(modinfo->handle, &r))
{
config_error("[rpc/log] Could not register RPC handler");
return MOD_FAILED;
}
HookAdd(modinfo->handle, HOOKTYPE_LOG, 0, rpc_log_hook);
return MOD_SUCCESS;
}
MOD_LOAD()
{
return MOD_SUCCESS;
}
MOD_UNLOAD()
{
return MOD_SUCCESS;
}
void rpc_log_hook_subscribe(Client *client, json_t *request, json_t *params)
{
json_t *result;
json_t *sources;
size_t index;
json_t *value;
const char *str;
LogSource *s;
sources = json_object_get(params, "sources");
if (!sources || !json_is_array(sources))
{
rpc_error_fmt(client, request, JSON_RPC_ERROR_INVALID_PARAMS, "Missing parameter: '%s'", "sources");
return;
}
/* Erase the old subscriptions first */
free_log_sources(client->rpc->log_sources);
client->rpc->log_sources = NULL;
/* Add subscriptions... */
json_array_foreach(sources, index, value)
{
str = json_get_value(value);
if (!str)
continue;
s = add_log_source(str);
AddListItem(s, client->rpc->log_sources);
}
result = json_boolean(1);
rpc_response(client, request, result);
json_decref(result);
}
/** log.unsubscribe: unsubscribe from all log messages */
void rpc_log_hook_unsubscribe(Client *client, json_t *request, json_t *params)
{
json_t *result;
free_log_sources(client->rpc->log_sources);
client->rpc->log_sources = NULL;
result = json_boolean(1);
rpc_response(client, request, result);
json_decref(result);
}
int rpc_log_hook(LogLevel loglevel, const char *subsystem, const char *event_id, MultiLine *msg, json_t *json, const char *json_serialized, const char *timebuf)
{
Client *client;
json_t *request = NULL;
if (!strcmp(subsystem, "rawtraffic") || (loglevel == ULOG_DEBUG))
return 0;
list_for_each_entry(client, &unknown_list, lclient_node)
{
if (IsRPC(client) && client->rpc->log_sources &&
log_sources_match(client->rpc->log_sources, loglevel, subsystem, event_id, 0))
{
if (request == NULL)
{
/* Lazy initalization */
request = json_object();
json_object_set_new(request, "method", json_string_unreal("log.event"));
}
rpc_response(client, request, json);
}
}
if (request)
json_decref(request);
return 0;
}
void rpc_log_list(Client *client, json_t *request, json_t *params)
{
json_t *sources;
size_t index;
json_t *value;
const char *str;
json_t *result = json_object();
json_t *list = json_array();
LogEntry *e;
int i;
LogSource *log_sources = NULL;
LogSource *s;
/* Optionally filter on sources: */
sources = json_object_get(params, "sources");
if (sources && json_is_array(sources))
{
json_array_foreach(sources, index, value)
{
str = json_get_value(value);
if (!str)
continue;
s = add_log_source(str);
AddListItem(s, log_sources);
}
}
json_object_set_new(result, "list", list);
for (e = memory_log; e; e = e->next)
{
if (log_sources &&
!log_sources_match(log_sources, e->loglevel, e->subsystem, e->event_id, 0))
{
continue;
}
json_array_append(list, e->json);
}
rpc_response(client, request, result);
json_decref(result);
free_log_sources(log_sources);
}