mirror of
https://github.com/unrealircd/unrealircd.git
synced 2026-06-12 17:14:46 +02:00
Add RPC API (the beginning..)
This commit is contained in:
+4
-1
@@ -184,7 +184,7 @@ EXP_OBJ_FILES=src/ircd_vars.obj src/channel.obj src/send.obj src/socket.obj \
|
||||
src/version.obj src/ircsprintf.obj \
|
||||
src/scache.obj src/dns.obj src/modules.obj \
|
||||
src/aliases.obj src/api-event.obj src/api-usermode.obj src/auth.obj src/tls.obj \
|
||||
src/random.obj src/api-channelmode.obj src/api-moddata.obj src/mempool.obj \
|
||||
src/random.obj src/api-channelmode.obj src/api-moddata.obj src/api-rpc.obj src/mempool.obj \
|
||||
src/dispatch.obj src/api-isupport.obj src/api-command.obj \
|
||||
src/api-clicap.obj src/api-messagetag.obj src/api-history-backend.obj \
|
||||
src/api-extban.obj src/api-efunctions.obj src/crypt_blowfish.obj \
|
||||
@@ -583,6 +583,9 @@ src/api-channelmode.obj: src/api-channelmode.c $(INCLUDES)
|
||||
src/api-moddata.obj: src/api-moddata.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/api-moddata.c
|
||||
|
||||
src/api-rpc.obj: src/api-rpc.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/api-rpc.c
|
||||
|
||||
src/mempool.obj: src/mempool.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/mempool.c
|
||||
|
||||
|
||||
@@ -107,6 +107,7 @@ typedef enum ModuleObjectType {
|
||||
MOBJ_CLICAP = 16,
|
||||
MOBJ_MTAG = 17,
|
||||
MOBJ_HISTORY_BACKEND = 18,
|
||||
MOBJ_RPC = 18,
|
||||
} ModuleObjectType;
|
||||
|
||||
typedef struct Umode Umode;
|
||||
@@ -604,6 +605,35 @@ typedef struct {
|
||||
int (*history_destroy)(const char *object);
|
||||
} HistoryBackendInfo;
|
||||
|
||||
/** @defgroup RPCAPI RPC API
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** No special flags set */
|
||||
#define RPC_HANDLER_FLAGS_NONE 0x0
|
||||
|
||||
/** Message Tag Handler */
|
||||
typedef struct RPCHandler RPCHandler;
|
||||
struct RPCHandler {
|
||||
RPCHandler *prev, *next;
|
||||
char *method; /**< Name of the method handler, eg "client.get" */
|
||||
int flags; /**< A flag of RPC_HANDLER_FLAG_* */
|
||||
int (*call)(Client *, json_t *request); /**< RPC call */
|
||||
Module *owner; /**< Module introducing this. */
|
||||
char unloaded; /**< Internal flag to indicate module is being unloaded */
|
||||
};
|
||||
|
||||
/** The struct used to register a RPC handler.
|
||||
* For documentation, see the RPCHandler struct.
|
||||
*/
|
||||
typedef struct {
|
||||
char *method;
|
||||
int flags;
|
||||
int (*call)(Client *, json_t *request);
|
||||
} RPCHandlerInfo;
|
||||
|
||||
/** @} */
|
||||
|
||||
struct Hook {
|
||||
Hook *prev, *next;
|
||||
int priority;
|
||||
@@ -688,6 +718,7 @@ typedef struct ModuleObject {
|
||||
ClientCapability *clicap;
|
||||
MessageTagHandler *mtag;
|
||||
HistoryBackend *history_backend;
|
||||
RPCHandler *rpc;
|
||||
} object;
|
||||
} ModuleObject;
|
||||
|
||||
@@ -825,6 +856,10 @@ extern HistoryBackend *HistoryBackendFind(const char *name);
|
||||
extern HistoryBackend *HistoryBackendAdd(Module *module, HistoryBackendInfo *mreq);
|
||||
extern void HistoryBackendDel(HistoryBackend *m);
|
||||
|
||||
extern RPCHandler *RPCHandlerFind(const char *method);
|
||||
extern RPCHandler *RPCHandlerAdd(Module *module, RPCHandlerInfo *mreq);
|
||||
extern void RPCHandlerDel(RPCHandler *m);
|
||||
|
||||
#ifndef GCC_TYPECHECKING
|
||||
#define HookAdd(module, hooktype, priority, func) HookAddMain(module, hooktype, priority, func, NULL, NULL, NULL)
|
||||
#define HookAddVoid(module, hooktype, priority, func) HookAddMain(module, hooktype, priority, NULL, func, NULL, NULL)
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ OBJS=ircd_vars.o dns.o auth.o channel.o crule.o dbuf.o \
|
||||
version.o whowas.o random.o api-usermode.o api-channelmode.o \
|
||||
api-moddata.o api-extban.o api-isupport.o api-command.o \
|
||||
api-clicap.o api-messagetag.o api-history-backend.o api-efunctions.o \
|
||||
api-event.o \
|
||||
api-event.o api-rpc.o \
|
||||
crypt_blowfish.o unrealdb.o crashreport.o modulemanager.o \
|
||||
utf8.o log.o \
|
||||
openssl_hostname_validation.o $(URL)
|
||||
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
/************************************************************************
|
||||
* UnrealIRCd - Unreal Internet Relay Chat Daemon - src/api-rpc.c
|
||||
* (c) 2022- Bram Matthys and The UnrealIRCd Team
|
||||
* License: GPLv2 or later
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* @brief RPC API
|
||||
*/
|
||||
#include "unrealircd.h"
|
||||
|
||||
/** This is the RPC API used for web requests.
|
||||
* For an overview of available RPC's (not the API)
|
||||
* see https://www.unrealircd.org/docs/RPC
|
||||
* @defgroup RPCAPI RPC API
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** List of RPC handlers */
|
||||
MODVAR RPCHandler *rpchandlers = NULL;
|
||||
|
||||
/* Forward declarations */
|
||||
static void unload_rpc_handler_commit(RPCHandler *m);
|
||||
|
||||
/** Adds a new RPC handler.
|
||||
* @param module The module which owns this RPC handler.
|
||||
* @param mreq The details of the request such as the method name, callback, etc.
|
||||
* @return Returns the handle to the RPC handler if successful, otherwise NULL.
|
||||
* The module's error code contains specific information about the
|
||||
* error.
|
||||
*/
|
||||
RPCHandler *RPCHandlerAdd(Module *module, RPCHandlerInfo *mreq)
|
||||
{
|
||||
RPCHandler *m;
|
||||
ModuleObject *mobj;
|
||||
|
||||
/* Some consistency checks to avoid a headache for module devs later on: */
|
||||
if (!mreq->method || !mreq->call)
|
||||
{
|
||||
unreal_log(ULOG_ERROR, "module", "RPCHANDLERADD_API_ERROR", NULL,
|
||||
"RPCHandlerAdd() from module $module_name: "
|
||||
"Missing required fields.",
|
||||
log_data_string("module_name", module->header->name));
|
||||
abort();
|
||||
}
|
||||
|
||||
m = RPCHandlerFind(mreq->method);
|
||||
if (m)
|
||||
{
|
||||
if (m->unloaded)
|
||||
{
|
||||
m->unloaded = 0;
|
||||
} else {
|
||||
if (module)
|
||||
module->errorcode = MODERR_EXISTS;
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
/* New RPC handler */
|
||||
m = safe_alloc(sizeof(RPCHandler));
|
||||
safe_strdup(m->method, mreq->method);
|
||||
AddListItem(m, rpchandlers);
|
||||
}
|
||||
/* Add or update the following fields: */
|
||||
m->owner = module;
|
||||
m->flags = mreq->flags;
|
||||
m->call = mreq->call;
|
||||
|
||||
/* Add module object */
|
||||
mobj = safe_alloc(sizeof(ModuleObject));
|
||||
mobj->type = MOBJ_RPC;
|
||||
mobj->object.rpc = m;
|
||||
AddListItem(mobj, module->objects);
|
||||
module->errorcode = MODERR_NOERROR;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/** Returns the RPC handler for the given method name.
|
||||
* @param method The method to search for.
|
||||
* @return Returns the handle to the RPC handler,
|
||||
* or NULL if not found.
|
||||
*/
|
||||
RPCHandler *RPCHandlerFind(const char *method)
|
||||
{
|
||||
RPCHandler *m;
|
||||
|
||||
for (m = rpchandlers; m; m = m->next)
|
||||
{
|
||||
if (!strcasecmp(method, m->method))
|
||||
return m;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Remove the specified RPC handler - modules should not call this.
|
||||
* This is done automatically for modules on unload, so is only called internally.
|
||||
* @param m The PRC handler to remove.
|
||||
*/
|
||||
void RPCHandlerDel(RPCHandler *m)
|
||||
{
|
||||
if (m->owner)
|
||||
{
|
||||
ModuleObject *mobj;
|
||||
for (mobj = m->owner->objects; mobj; mobj = mobj->next) {
|
||||
if (mobj->type == MOBJ_RPC && mobj->object.rpc == m)
|
||||
{
|
||||
DelListItem(mobj, m->owner->objects);
|
||||
safe_free(mobj);
|
||||
break;
|
||||
}
|
||||
}
|
||||
m->owner = NULL;
|
||||
}
|
||||
|
||||
if (loop.rehashing)
|
||||
m->unloaded = 1;
|
||||
else
|
||||
unload_rpc_handler_commit(m);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
static void unload_rpc_handler_commit(RPCHandler *m)
|
||||
{
|
||||
/* This is an unusual operation, I think we should log it. */
|
||||
unreal_log(ULOG_INFO, "module", "UNLOAD_RPC_HANDLER", NULL,
|
||||
"Unloading RPC handler for '$method'",
|
||||
log_data_string("method", m->method));
|
||||
|
||||
/* Destroy the object */
|
||||
DelListItem(m, rpchandlers);
|
||||
safe_free(m->method);
|
||||
safe_free(m);
|
||||
}
|
||||
|
||||
void unload_all_unused_rpc_handlers(void)
|
||||
{
|
||||
RPCHandler *m, *m_next;
|
||||
|
||||
for (m = rpchandlers; m; m = m_next)
|
||||
{
|
||||
m_next = m->next;
|
||||
if (m->unloaded)
|
||||
unload_rpc_handler_commit(m);
|
||||
}
|
||||
}
|
||||
@@ -560,6 +560,9 @@ void FreeModObj(ModuleObject *obj, Module *m)
|
||||
else if (obj->type == MOBJ_HISTORY_BACKEND) {
|
||||
HistoryBackendDel(obj->object.history_backend);
|
||||
}
|
||||
else if (obj->type == MOBJ_RPC) {
|
||||
RPCHandlerDel(obj->object.rpc);
|
||||
}
|
||||
else
|
||||
{
|
||||
unreal_log(ULOG_FATAL, "module", "FREEMODOBJ_UNKNOWN_TYPE", NULL,
|
||||
|
||||
Reference in New Issue
Block a user