unrealircd- supernets unrealircd source & configuration |
git clone git://git.acid.vegas/unrealircd.git |
Log | Files | Refs | Archive | README | LICENSE |
api-rpc.c (3653B)
1 /************************************************************************ 2 * UnrealIRCd - Unreal Internet Relay Chat Daemon - src/api-rpc.c 3 * (c) 2022- Bram Matthys and The UnrealIRCd Team 4 * License: GPLv2 or later 5 */ 6 7 /** @file 8 * @brief RPC API 9 */ 10 #include "unrealircd.h" 11 12 /** This is the RPC API used for web requests. 13 * For an overview of available RPC's (not the API) 14 * see https://www.unrealircd.org/docs/RPC 15 * @defgroup RPCAPI RPC API 16 * @{ 17 */ 18 19 /** List of RPC handlers */ 20 MODVAR RPCHandler *rpchandlers = NULL; 21 22 /* Forward declarations */ 23 static void unload_rpc_handler_commit(RPCHandler *m); 24 25 /** Adds a new RPC handler. 26 * @param module The module which owns this RPC handler. 27 * @param mreq The details of the request such as the method name, callback, etc. 28 * @return Returns the handle to the RPC handler if successful, otherwise NULL. 29 * The module's error code contains specific information about the 30 * error. 31 */ 32 RPCHandler *RPCHandlerAdd(Module *module, RPCHandlerInfo *mreq) 33 { 34 RPCHandler *m; 35 ModuleObject *mobj; 36 37 /* Some consistency checks to avoid a headache for module devs later on: */ 38 if (!mreq->method || !mreq->call) 39 { 40 unreal_log(ULOG_ERROR, "module", "RPCHANDLERADD_API_ERROR", NULL, 41 "RPCHandlerAdd() from module $module_name: " 42 "Missing required fields.", 43 log_data_string("module_name", module->header->name)); 44 abort(); 45 } 46 47 m = RPCHandlerFind(mreq->method); 48 if (m) 49 { 50 if (m->unloaded) 51 { 52 m->unloaded = 0; 53 } else { 54 if (module) 55 module->errorcode = MODERR_EXISTS; 56 return NULL; 57 } 58 } else { 59 /* New RPC handler */ 60 m = safe_alloc(sizeof(RPCHandler)); 61 safe_strdup(m->method, mreq->method); 62 AddListItem(m, rpchandlers); 63 } 64 /* Add or update the following fields: */ 65 m->owner = module; 66 m->flags = mreq->flags; 67 m->loglevel = mreq->loglevel; 68 if (!valid_loglevel(m->loglevel)) 69 m->loglevel = ULOG_INFO; 70 m->call = mreq->call; 71 72 /* Add module object */ 73 mobj = safe_alloc(sizeof(ModuleObject)); 74 mobj->type = MOBJ_RPC; 75 mobj->object.rpc = m; 76 AddListItem(mobj, module->objects); 77 module->errorcode = MODERR_NOERROR; 78 79 return m; 80 } 81 82 /** Returns the RPC handler for the given method name. 83 * @param method The method to search for. 84 * @return Returns the handle to the RPC handler, 85 * or NULL if not found. 86 */ 87 RPCHandler *RPCHandlerFind(const char *method) 88 { 89 RPCHandler *m; 90 91 for (m = rpchandlers; m; m = m->next) 92 { 93 if (!strcasecmp(method, m->method)) 94 return m; 95 } 96 return NULL; 97 } 98 99 /** Remove the specified RPC handler - modules should not call this. 100 * This is done automatically for modules on unload, so is only called internally. 101 * @param m The PRC handler to remove. 102 */ 103 void RPCHandlerDel(RPCHandler *m) 104 { 105 if (m->owner) 106 { 107 ModuleObject *mobj; 108 for (mobj = m->owner->objects; mobj; mobj = mobj->next) { 109 if (mobj->type == MOBJ_RPC && mobj->object.rpc == m) 110 { 111 DelListItem(mobj, m->owner->objects); 112 safe_free(mobj); 113 break; 114 } 115 } 116 m->owner = NULL; 117 } 118 119 if (loop.rehashing) 120 m->unloaded = 1; 121 else 122 unload_rpc_handler_commit(m); 123 } 124 125 /** @} */ 126 127 static void unload_rpc_handler_commit(RPCHandler *m) 128 { 129 /* This is an unusual operation, I think we should log it. */ 130 unreal_log(ULOG_INFO, "module", "UNLOAD_RPC_HANDLER", NULL, 131 "Unloading RPC handler for '$method'", 132 log_data_string("method", m->method)); 133 134 /* Destroy the object */ 135 DelListItem(m, rpchandlers); 136 safe_free(m->method); 137 safe_free(m); 138 } 139 140 void unload_all_unused_rpc_handlers(void) 141 { 142 RPCHandler *m, *m_next; 143 144 for (m = rpchandlers; m; m = m_next) 145 { 146 m_next = m->next; 147 if (m->unloaded) 148 unload_rpc_handler_commit(m); 149 } 150 }