unrealircd

- supernets unrealircd source & configuration
git clone git://git.acid.vegas/unrealircd.git
Log | Files | Refs | Archive | README | LICENSE

rpc.c (50812B)

      1 /*
      2  * RPC module - for remote management of UnrealIRCd
      3  * (C)Copyright 2022 Bram Matthys and the UnrealIRCd team
      4  * License: GPLv2 or later
      5  */
      6    
      7 #include "unrealircd.h"
      8 #include "dns.h"
      9 
     10 ModuleHeader MOD_HEADER
     11   = {
     12 	"rpc/rpc",
     13 	"1.0.4",
     14 	"RPC module for remote management",
     15 	"UnrealIRCd Team",
     16 	"unrealircd-6",
     17     };
     18 
     19 /** Maximum length of an rpc-user THIS { }.
     20  * As we use the "RPC:" prefix it is nicklen minus that.
     21  */
     22 #define RPCUSERLEN (NICKLEN-4)
     23 
     24 /** Timers can be minimum every <this> msec */
     25 #define RPC_MINIMUM_TIMER_MSEC 250
     26 
     27 /* Structs */
     28 typedef struct RPCUser RPCUser;
     29 struct RPCUser {
     30 	RPCUser *prev, *next;
     31 	SecurityGroup *match;
     32 	char *name;
     33 	AuthConfig *auth;
     34 };
     35 
     36 typedef struct RRPC RRPC;
     37 struct RRPC {
     38 	RRPC *prev, *next;
     39 	int request;
     40 	char source[IDLEN+1];
     41 	char destination[IDLEN+1];
     42 	char *requestid;
     43 	dbuf data;
     44 };
     45 
     46 typedef struct OutstandingRRPC OutstandingRRPC;
     47 struct OutstandingRRPC {
     48 	OutstandingRRPC *prev, *next;
     49 	time_t sent;
     50 	char source[IDLEN+1];
     51 	char destination[IDLEN+1];
     52 	char *requestid;
     53 };
     54 
     55 typedef struct RPCTimer RPCTimer;
     56 struct RPCTimer {
     57 	RPCTimer *prev, *next;
     58 	long every_msec;
     59 	Client *client;
     60 	char *timer_id;
     61 	json_t *request;
     62 	struct timeval last_run;
     63 };
     64 
     65 /* Forward declarations */
     66 int rpc_config_test_listen(ConfigFile *cf, ConfigEntry *ce, int type, int *errs);
     67 int rpc_config_run_ex_listen(ConfigFile *cf, ConfigEntry *ce, int type, void *ptr);
     68 int rpc_config_test_rpc_user(ConfigFile *cf, ConfigEntry *ce, int type, int *errs);
     69 int rpc_config_run_rpc_user(ConfigFile *cf, ConfigEntry *ce, int type);
     70 int rpc_client_accept(Client *client);
     71 int rpc_pre_local_handshake_timeout(Client *client, const char **comment);
     72 void rpc_client_handshake_unix_socket(Client *client);
     73 void rpc_client_handshake_web(Client *client);
     74 int rpc_handle_webrequest(Client *client, WebRequest *web);
     75 int rpc_handle_webrequest_websocket(Client *client, WebRequest *web);
     76 int rpc_websocket_handshake_send_response(Client *client);
     77 int rpc_handle_webrequest_data(Client *client, WebRequest *web, const char *buf, int len);
     78 int rpc_handle_body_websocket(Client *client, WebRequest *web, const char *readbuf2, int length2);
     79 int rpc_packet_in_websocket(Client *client, char *readbuf, int length);
     80 int rpc_packet_in_unix_socket(Client *client, const char *readbuf, int *length);
     81 void rpc_call_text(Client *client, const char *buf, int len);
     82 void rpc_call(Client *client, json_t *request);
     83 void _rpc_response(Client *client, json_t *request, json_t *result);
     84 void _rpc_error(Client *client, json_t *request, JsonRpcError error_code, const char *error_message);
     85 void _rpc_error_fmt(Client *client, json_t *request, JsonRpcError error_code, FORMAT_STRING(const char *fmt), ...) __attribute__((format(printf,4,5)));
     86 void _rpc_send_request_to_remote(Client *source, Client *target, json_t *request);
     87 void _rpc_send_response_to_remote(Client *source, Client *target, json_t *response);
     88 int _rrpc_supported_simple(Client *target, char **problem_server);
     89 int _rrpc_supported(Client *target, const char *module, const char *minimum_version, char **problem_server);
     90 int rpc_handle_auth(Client *client, WebRequest *web);
     91 int rpc_parse_auth_basic_auth(Client *client, WebRequest *web, char **username, char **password);
     92 int rpc_parse_auth_uri(Client *client, WebRequest *web, char **username, char **password);
     93 RPC_CALL_FUNC(rpc_rpc_info);
     94 RPC_CALL_FUNC(rpc_rpc_set_issuer);
     95 RPC_CALL_FUNC(rpc_rpc_add_timer);
     96 RPC_CALL_FUNC(rpc_rpc_del_timer);
     97 CMD_FUNC(cmd_rrpc);
     98 EVENT(rpc_remote_timeout);
     99 EVENT(rpc_do_timers);
    100 json_t *rrpc_data(RRPC *r);
    101 void free_rrpc_list(ModData *m);
    102 void free_outstanding_rrpc_list(ModData *m);
    103 void free_rpc_timer(RPCTimer *r);
    104 void free_rpc_timer_list(ModData *m);
    105 void rpc_call_remote(RRPC *r);
    106 void rpc_response_remote(RRPC *r);
    107 int rpc_handle_free_client(Client *client);
    108 int rpc_handle_server_quit(Client *client, MessageTag *mtags);
    109 int rpc_json_expand_client_server(Client *client, int detail, json_t *j, json_t *child);
    110 const char *rrpc_md_serialize(ModData *m);
    111 void rrpc_md_unserialize(const char *str, ModData *m);
    112 void rrpc_md_free(ModData *m);
    113 
    114 /* Macros */
    115 #define RPC_PORT(client)  ((client->local && client->local->listener) ? client->local->listener->rpc_options : 0)
    116 #define WSU(client)     ((WebSocketUser *)moddata_client(client, websocket_md).ptr)
    117 
    118 /* Global variables */
    119 ModDataInfo *websocket_md = NULL; /* (imported) */
    120 RPCUser *rpcusers = NULL;
    121 RRPC *rrpc_list = NULL;
    122 OutstandingRRPC *outstanding_rrpc_list = NULL;
    123 RPCTimer *rpc_timer_list = NULL;
    124 ModDataInfo *rrpc_md;
    125 
    126 MOD_TEST()
    127 {
    128 	MARK_AS_OFFICIAL_MODULE(modinfo);
    129 	HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, rpc_config_test_listen);
    130 	HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, rpc_config_test_rpc_user);
    131 	EfunctionAddVoid(modinfo->handle, EFUNC_RPC_RESPONSE, _rpc_response);
    132 	EfunctionAddVoid(modinfo->handle, EFUNC_RPC_ERROR, _rpc_error);
    133 	EfunctionAddVoid(modinfo->handle, EFUNC_RPC_ERROR_FMT, TO_VOIDFUNC(_rpc_error_fmt));
    134 	EfunctionAddVoid(modinfo->handle, EFUNC_RPC_SEND_REQUEST_TO_REMOTE, _rpc_send_request_to_remote);
    135 	EfunctionAddVoid(modinfo->handle, EFUNC_RPC_SEND_RESPONSE_TO_REMOTE, _rpc_send_response_to_remote);
    136 	EfunctionAdd(modinfo->handle, EFUNC_RRPC_SUPPORTED, _rrpc_supported);
    137 	EfunctionAdd(modinfo->handle, EFUNC_RRPC_SUPPORTED_SIMPLE, _rrpc_supported_simple);
    138 
    139 	/* Call MOD_INIT very early, since we manage sockets, but depend on websocket_common */
    140 	ModuleSetOptions(modinfo->handle, MOD_OPT_PRIORITY, WEBSOCKET_MODULE_PRIORITY_INIT+1);
    141 
    142 	return MOD_SUCCESS;
    143 }
    144 
    145 MOD_INIT()
    146 {
    147 	ModDataInfo mreq;
    148 	RPCHandlerInfo r;
    149 
    150 	MARK_AS_OFFICIAL_MODULE(modinfo);
    151 
    152 	websocket_md = findmoddata_byname("websocket", MODDATATYPE_CLIENT); /* can be NULL */
    153 
    154 	HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN_EX, 0, rpc_config_run_ex_listen);
    155 	HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, rpc_config_run_rpc_user);
    156 	HookAdd(modinfo->handle, HOOKTYPE_HANDSHAKE, -5000, rpc_client_accept);
    157 	HookAdd(modinfo->handle, HOOKTYPE_PRE_LOCAL_HANDSHAKE_TIMEOUT, 0, rpc_pre_local_handshake_timeout);
    158 	HookAdd(modinfo->handle, HOOKTYPE_RAWPACKET_IN, INT_MIN, rpc_packet_in_unix_socket);
    159 	HookAdd(modinfo->handle, HOOKTYPE_SERVER_QUIT, 0, rpc_handle_server_quit);
    160 	HookAdd(modinfo->handle, HOOKTYPE_FREE_CLIENT, 0, rpc_handle_free_client);
    161 	HookAdd(modinfo->handle, HOOKTYPE_JSON_EXPAND_CLIENT_SERVER, 0, rpc_json_expand_client_server);
    162 
    163 	memset(&r, 0, sizeof(r));
    164 	r.method = "rpc.info";
    165 	r.loglevel = ULOG_DEBUG;
    166 	r.call = rpc_rpc_info;
    167 	if (!RPCHandlerAdd(modinfo->handle, &r))
    168 	{
    169 		config_error("[rpc.info] Could not register RPC handler");
    170 		return MOD_FAILED;
    171 	}
    172 
    173 	memset(&r, 0, sizeof(r));
    174 	r.method = "rpc.set_issuer";
    175 	r.loglevel = ULOG_DEBUG;
    176 	r.call = rpc_rpc_set_issuer;
    177 	if (!RPCHandlerAdd(modinfo->handle, &r))
    178 	{
    179 		config_error("[rpc.set_issuer] Could not register RPC handler");
    180 		return MOD_FAILED;
    181 	}
    182 
    183 	memset(&r, 0, sizeof(r));
    184 	r.method = "rpc.add_timer";
    185 	r.loglevel = ULOG_DEBUG;
    186 	r.call = rpc_rpc_add_timer;
    187 	if (!RPCHandlerAdd(modinfo->handle, &r))
    188 	{
    189 		config_error("[rpc.add_timer] Could not register RPC handler");
    190 		return MOD_FAILED;
    191 	}
    192 
    193 	memset(&r, 0, sizeof(r));
    194 	r.method = "rpc.del_timer";
    195 	r.loglevel = ULOG_DEBUG;
    196 	r.call = rpc_rpc_del_timer;
    197 	if (!RPCHandlerAdd(modinfo->handle, &r))
    198 	{
    199 		config_error("[rpc.del_timer] Could not register RPC handler");
    200 		return MOD_FAILED;
    201 	}
    202 
    203 	memset(&mreq, 0, sizeof(mreq));
    204 	mreq.name = "rrpc";
    205 	mreq.type = MODDATATYPE_CLIENT;
    206 	mreq.serialize = rrpc_md_serialize;
    207 	mreq.unserialize = rrpc_md_unserialize;
    208 	mreq.free = rrpc_md_free;
    209 	mreq.sync = 1;
    210 	mreq.self_write = 1;
    211 	rrpc_md = ModDataAdd(modinfo->handle, mreq);
    212 	if (!rrpc_md)
    213 	{
    214 		config_error("[rpc/rpc] Unable to ModDataAdd() -- too many 3rd party modules loaded perhaps?");
    215 		abort();
    216 	}
    217 
    218 	LoadPersistentPointer(modinfo, rrpc_list, free_rrpc_list);
    219 	LoadPersistentPointer(modinfo, outstanding_rrpc_list, free_outstanding_rrpc_list);
    220 	LoadPersistentPointer(modinfo, rpc_timer_list, free_rpc_timer_list);
    221 
    222 	CommandAdd(modinfo->handle, "RRPC", cmd_rrpc, MAXPARA, CMD_SERVER);
    223 
    224 	EventAdd(modinfo->handle, "rpc_remote_timeout", rpc_remote_timeout, NULL, 1000, 0);
    225 	EventAdd(modinfo->handle, "rpc_do_timers", rpc_do_timers, NULL, RPC_MINIMUM_TIMER_MSEC, 0);
    226 
    227 	/* Call MOD_LOAD very late, since we manage sockets, but depend on websocket_common */
    228 	ModuleSetOptions(modinfo->handle, MOD_OPT_PRIORITY, WEBSOCKET_MODULE_PRIORITY_UNLOAD-1);
    229 
    230 	return MOD_SUCCESS;
    231 }
    232 
    233 #define MYRRPCMODULES		me.moddata[rrpc_md->slot].ptr
    234 #define RRPCMODULES(client)	((NameValuePrioList *)moddata_client(client, rrpc_md).ptr)
    235 
    236 void rpc_do_moddata(void)
    237 {
    238 	Module *m;
    239 
    240 	free_nvplist(MYRRPCMODULES);
    241 	MYRRPCMODULES = NULL;
    242 
    243 	for (m = Modules; m; m = m->next)
    244 		if (!strncmp(m->header->name, "rpc/", 4))
    245 			add_nvplist((NameValuePrioList **)&MYRRPCMODULES, 0, m->header->name + 4, m->header->version);
    246 }
    247 
    248 MOD_LOAD()
    249 {
    250 	rpc_do_moddata();
    251 	return MOD_SUCCESS;
    252 }
    253 
    254 void free_config(void)
    255 {
    256 	RPCUser *e, *e_next;
    257 	for (e = rpcusers; e; e = e_next)
    258 	{
    259 		e_next = e->next;
    260 		safe_free(e->name);
    261 		free_security_group(e->match);
    262 		Auth_FreeAuthConfig(e->auth);
    263 		safe_free(e);
    264 	}
    265 	rpcusers = NULL;
    266 }
    267 
    268 MOD_UNLOAD()
    269 {
    270 	free_config();
    271 	SavePersistentPointer(modinfo, rrpc_list);
    272 	SavePersistentPointer(modinfo, outstanding_rrpc_list);
    273 	SavePersistentPointer(modinfo, rpc_timer_list);
    274 	return MOD_SUCCESS;
    275 }
    276 
    277 int rpc_config_test_listen(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
    278 {
    279 	int errors = 0;
    280 	int ext = 0;
    281 	ConfigEntry *cep;
    282 
    283 	if (type != CONFIG_LISTEN_OPTIONS)
    284 		return 0;
    285 
    286 	/* We are only interested in listen::options::rpc.. */
    287 	if (!ce || !ce->name || strcmp(ce->name, "rpc"))
    288 		return 0;
    289 
    290 	/* No options atm */
    291 
    292 	*errs = errors;
    293 	return errors ? -1 : 1;
    294 }
    295 
    296 int rpc_config_run_ex_listen(ConfigFile *cf, ConfigEntry *ce, int type, void *ptr)
    297 {
    298 	ConfigEntry *cep, *cepp;
    299 	ConfigItem_listen *l;
    300 
    301 	if (type != CONFIG_LISTEN_OPTIONS)
    302 		return 0;
    303 
    304 	/* We are only interrested in listen::options::rpc.. */
    305 	if (!ce || !ce->name || strcmp(ce->name, "rpc"))
    306 		return 0;
    307 
    308 	l = (ConfigItem_listen *)ptr;
    309 	l->options |= LISTENER_NO_CHECK_CONNECT_FLOOD;
    310 	if (l->socket_type == SOCKET_TYPE_UNIX)
    311 	{
    312 		l->start_handshake = rpc_client_handshake_unix_socket;
    313 	} else {
    314 		l->options |= LISTENER_TLS;
    315 		l->start_handshake = rpc_client_handshake_web;
    316 		l->webserver = safe_alloc(sizeof(WebServer));
    317 		l->webserver->handle_request = rpc_handle_webrequest;
    318 		l->webserver->handle_body = rpc_handle_webrequest_data;
    319 	}
    320 	l->rpc_options = 1;
    321 
    322 	return 1;
    323 }
    324 
    325 /** Valid name for rpc-user THISNAME { } ? */
    326 static int valid_rpc_user_name(const char *str)
    327 {
    328 	const char *p;
    329 
    330 	if (strlen(str) > RPCUSERLEN)
    331 		return 0;
    332 
    333 	for (p = str; *p; p++)
    334 		if (!isalnum(*p) && !strchr("_-", *p))
    335 			return 0;
    336 
    337 	return 1;
    338 }
    339 
    340 int rpc_config_test_rpc_user(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
    341 {
    342 	int errors = 0;
    343 	char has_match = 1, has_password = 1;
    344 	ConfigEntry *cep;
    345 
    346 	/* We are only interested in rpc-user { } */
    347 	if ((type != CONFIG_MAIN) || !ce || !ce->name || strcmp(ce->name, "rpc-user"))
    348 		return 0;
    349 
    350 	if (!ce->value)
    351 	{
    352 		config_error("%s:%d: rpc-user block needs to have a name, eg: rpc-user apiuser { }",
    353 		             ce->file->filename, ce->line_number);
    354 		*errs = 1;
    355 		return -1; /* quick return */
    356 	}
    357 
    358 	if (!valid_rpc_user_name(ce->value))
    359 	{
    360 		config_error("%s:%d: rpc-user block has invalid name '%s'. "
    361 		             "Can be max %d long and may only contain a-z, A-Z, 0-9, - and _.",
    362 		             ce->file->filename, ce->line_number,
    363 		             ce->value, RPCUSERLEN);
    364 		errors++;
    365 	}
    366 	for (cep = ce->items; cep; cep = cep->next)
    367 	{
    368 		if (!strcmp(cep->name, "match"))
    369 		{
    370 			has_match = 1;
    371 			test_match_block(cf, cep, &errors);
    372 		} else
    373 		if (!strcmp(cep->name, "password"))
    374 		{
    375 			has_password = 1;
    376 			if (Auth_CheckError(cep) < 0)
    377 				errors++;
    378 		}
    379 	}
    380 
    381 	*errs = errors;
    382 	return errors ? -1 : 1;
    383 }
    384 
    385 int rpc_config_run_rpc_user(ConfigFile *cf, ConfigEntry *ce, int type)
    386 {
    387 	ConfigEntry *cep;
    388 	RPCUser *e;
    389 
    390 	/* We are only interested in rpc-user { } */
    391 	if ((type != CONFIG_MAIN) || !ce || !ce->name || strcmp(ce->name, "rpc-user"))
    392 		return 0;
    393 
    394 	e = safe_alloc(sizeof(RPCUser));
    395 	safe_strdup(e->name, ce->value);
    396 	AddListItem(e, rpcusers);
    397 
    398 	for (cep = ce->items; cep; cep = cep->next)
    399 	{
    400 		if (!strcmp(cep->name, "match"))
    401 		{
    402 			conf_match_block(cf, cep, &e->match);
    403 		} else
    404 		if (!strcmp(cep->name, "password"))
    405 		{
    406 			e->auth = AuthBlockToAuthConfig(cep);
    407 		}
    408 	}
    409 	return 1;
    410 }
    411 
    412 /** Incoming HTTP request: delegate it to websocket handler or HTTP POST */
    413 int rpc_handle_webrequest(Client *client, WebRequest *web)
    414 {
    415 	if (!rpc_handle_auth(client, web))
    416 		return 0; /* rejected */
    417 
    418 	if (get_nvplist(web->headers, "Sec-WebSocket-Key"))
    419 		return rpc_handle_webrequest_websocket(client, web);
    420 
    421 	if (!strcmp(web->uri, "/api"))
    422 	{
    423 		if (web->method != HTTP_METHOD_POST)
    424 		{
    425 			webserver_send_response(client, 200, "To use the UnrealIRCd RPC API you need to make a POST request. See https://www.unrealircd.org/docs/RPC\n");
    426 			return 0;
    427 		}
    428 		webserver_send_response(client, 200, NULL); /* continue.. */
    429 		return 1; /* accept */
    430 	}
    431 
    432 	webserver_send_response(client, 404, "Page not found.\n");
    433 	return 0;
    434 }
    435 
    436 /** Handle HTTP request - websockets handshake.
    437  */
    438 int rpc_handle_webrequest_websocket(Client *client, WebRequest *web)
    439 {
    440 	NameValuePrioList *r;
    441 	const char *value;
    442 
    443 	if (!websocket_md)
    444 	{
    445 		webserver_send_response(client, 405, "Websockets are disabled on this server (module 'websocket_common' not loaded).\n");
    446 		return 0;
    447 	}
    448 
    449 	/* Allocate a new WebSocketUser struct for this session */
    450 	moddata_client(client, websocket_md).ptr = safe_alloc(sizeof(WebSocketUser));
    451 	/* ...and set the default protocol (text or binary) */
    452 	WSU(client)->type = WEBSOCKET_TYPE_TEXT;
    453 
    454 	value = get_nvplist(web->headers, "Sec-WebSocket-Key");
    455 	if (strchr(value, ':'))
    456 	{
    457 		/* This would cause unserialization issues. Should be base64 anyway */
    458 		webserver_send_response(client, 400, "Invalid characters in Sec-WebSocket-Key");
    459 		return 0; // FIXME: 0 here, -1 in the other, what is it ???
    460 	}
    461 	safe_strdup(WSU(client)->handshake_key, value);
    462 
    463 	rpc_websocket_handshake_send_response(client);
    464 	return 1; /* ACCEPT */
    465 }
    466 
    467 /** Complete the handshake by sending the appropriate HTTP 101 response etc. */
    468 int rpc_websocket_handshake_send_response(Client *client)
    469 {
    470 	char buf[512], hashbuf[64];
    471 	char sha1out[20]; /* 160 bits */
    472 
    473 	WSU(client)->handshake_completed = 1;
    474 
    475 	snprintf(buf, sizeof(buf), "%s%s", WSU(client)->handshake_key, WEBSOCKET_MAGIC_KEY);
    476 	sha1hash_binary(sha1out, buf, strlen(buf));
    477 	b64_encode(sha1out, sizeof(sha1out), hashbuf, sizeof(hashbuf));
    478 
    479 	snprintf(buf, sizeof(buf),
    480 	         "HTTP/1.1 101 Switching Protocols\r\n"
    481 	         "Upgrade: websocket\r\n"
    482 	         "Connection: Upgrade\r\n"
    483 	         "Sec-WebSocket-Accept: %s\r\n\r\n",
    484 	         hashbuf);
    485 
    486 	/* Caution: we bypass sendQ flood checking by doing it this way.
    487 	 * Risk is minimal, though, as we only permit limited text only
    488 	 * once per session.
    489 	 */
    490 	dbuf_put(&client->local->sendQ, buf, strlen(buf));
    491 	send_queued(client);
    492 
    493 	return 0;
    494 }
    495 
    496 int rpc_handle_webrequest_data(Client *client, WebRequest *web, const char *buf, int len)
    497 {
    498 	if (WSU(client))
    499 	{
    500 		/* Websocket user */
    501 		return rpc_handle_body_websocket(client, web, buf, len);
    502 	}
    503 
    504 	/* We only handle POST to /api -- reject all the rest */
    505 	if (strcmp(web->uri, "/api") || (web->method != HTTP_METHOD_POST))
    506 	{
    507 		webserver_send_response(client, 404, "Page not found\n");
    508 		return 0;
    509 	}
    510 
    511 	// NB: content_length
    512 	// NB: chunked transfers?
    513 	if (!webserver_handle_body(client, web, buf, len))
    514 	{
    515 		webserver_send_response(client, 400, "Error handling POST body data\n");
    516 		return 0;
    517 	}
    518 
    519 
    520 	if (web->request_body_complete)
    521 	{
    522 		if (!web->request_buffer)
    523 		{
    524 			webserver_send_response(client, 500, "Error while processing POST body data\n");
    525 			return 0;
    526 		}
    527 		//config_status("GOT: '%s'", buf);
    528 		rpc_call_text(client, web->request_buffer, web->request_buffer_size);
    529 		send_queued(client);
    530 		webserver_close_client(client);
    531 	}
    532 
    533 	return 0;
    534 }
    535 
    536 int rpc_handle_body_websocket(Client *client, WebRequest *web, const char *readbuf2, int length2)
    537 {
    538 	return websocket_handle_websocket(client, web, readbuf2, length2, rpc_packet_in_websocket);
    539 }
    540 
    541 int rpc_packet_in_websocket(Client *client, char *readbuf, int length)
    542 {
    543 	rpc_call_text(client, readbuf, length);
    544 	return 0; /* and if dead?? */
    545 }
    546 
    547 int rpc_packet_in_unix_socket(Client *client, const char *readbuf, int *length)
    548 {
    549 	char buf[READBUFSIZE];
    550 
    551 	if (!RPC_PORT(client) || !(client->local->listener->socket_type == SOCKET_TYPE_UNIX) || (*length <= 0))
    552 		return 1; /* Not for us */
    553 
    554 	dbuf_put(&client->local->recvQ, readbuf, *length);
    555 
    556 	while (DBufLength(&client->local->recvQ))
    557 	{
    558 		int len = dbuf_getmsg(&client->local->recvQ, buf);
    559 		if (len <= 0)
    560 			break;
    561 		rpc_call_text(client, buf, len);
    562 		if (IsDead(client))
    563 			break;
    564 	}
    565 
    566 	return 0;
    567 }
    568 
    569 void rpc_close(Client *client)
    570 {
    571 	send_queued(client);
    572 
    573 	/* May not be a web request actually, but this works: */
    574 	webserver_close_client(client);
    575 }
    576 
    577 /** Handle the RPC request: input is a buffer with a certain length.
    578  * This calls rpc_call()
    579  */
    580 void rpc_call_text(Client *client, const char *readbuf, int len)
    581 {
    582 	json_t *request = NULL;
    583 	json_error_t jerr;
    584 #if JANSSON_VERSION_HEX >= 0x020100
    585 	const char *buf = readbuf;
    586 	request = json_loadb(buf, len, JSON_REJECT_DUPLICATES, &jerr);
    587 #else
    588 	char buf[2048];
    589 
    590 	*buf = '\0';
    591 	strlncpy(buf, readbuf, sizeof(buf), len);
    592 
    593 	request = json_loads(buf, JSON_REJECT_DUPLICATES, &jerr);
    594 #endif
    595 	if (!request)
    596 	{
    597 		unreal_log(ULOG_INFO, "rpc", "RPC_INVALID_JSON", client,
    598 		           "Received unparsable JSON request from $client",
    599 		           log_data_string("json_incoming", buf));
    600 		rpc_error(client, NULL, JSON_RPC_ERROR_PARSE_ERROR, "Unparsable JSON data");
    601 		/* This is a fatal error */
    602 		rpc_close(client);
    603 		return;
    604 	}
    605 	rpc_call(client, request);
    606 	json_decref(request);
    607 }
    608 
    609 void rpc_sendto(Client *client, const char *buf, int len)
    610 {
    611 	if (IsDead(client))
    612 		return;
    613 	if (MyConnect(client) && IsRPC(client) && WSU(client) && WSU(client)->handshake_completed)
    614 	{
    615 		/* Websocket */
    616 		int utf8bufsize = len*2 + 16;
    617 		char *utf8buf = safe_alloc(utf8bufsize);
    618 		char *newbuf = unrl_utf8_make_valid(buf, utf8buf, utf8bufsize, 1);
    619 		int newlen = strlen(newbuf);
    620 		int ws_sendbufsize = newlen + 64 + ((newlen / 1024) * 64); // some random magic
    621 		char *ws_sendbuf = safe_alloc(ws_sendbufsize);
    622 		websocket_create_packet_ex(WSOP_TEXT, &newbuf, &newlen, ws_sendbuf, ws_sendbufsize);
    623 		dbuf_put(&client->local->sendQ, newbuf, newlen);
    624 		safe_free(ws_sendbuf);
    625 		safe_free(utf8buf);
    626 	} else {
    627 		/* Unix domain socket or HTTP */
    628 		dbuf_put(&client->local->sendQ, buf, len);
    629 		dbuf_put(&client->local->sendQ, "\n", 1);
    630 	}
    631 	mark_data_to_send(client);
    632 }
    633 
    634 void _rpc_error(Client *client, json_t *request, JsonRpcError error_code, const char *error_message)
    635 {
    636 	/* Careful, we are in the "error" routine, so everything can be NULL */
    637 	const char *method = NULL;
    638 	json_t *id = NULL;
    639 	char *json_serialized;
    640 	json_t *error;
    641 
    642 	/* Start a new object for the error response */
    643 	json_t *j = json_object();
    644 
    645 	if (request)
    646 	{
    647 		method = json_object_get_string(request, "method");
    648 		id = json_object_get(request, "id");
    649 	}
    650 
    651 	json_object_set_new(j, "jsonrpc", json_string_unreal("2.0"));
    652 	if (method)
    653 		json_object_set_new(j, "method", json_string_unreal(method));
    654 	if (id)
    655 		json_object_set(j, "id", id);
    656 
    657 	error = json_object();
    658 	json_object_set_new(j, "error", error);
    659 	json_object_set_new(error, "code", json_integer(error_code));
    660 	json_object_set_new(error, "message", json_string_unreal(error_message));
    661 
    662 	unreal_log(ULOG_INFO, "rpc", "RPC_CALL_ERROR", client,
    663 	           "[rpc] Client $client: RPC call $method",
    664 	           log_data_string("method", method ? method : "<invalid>"));
    665 
    666 
    667 	json_serialized = json_dumps(j, 0);
    668 	if (!json_serialized)
    669 	{
    670 		unreal_log(ULOG_WARNING, "rpc", "BUG_RPC_ERROR_SERIALIZE_FAILED", NULL,
    671 		           "[BUG] rpc_error() failed to serialize response "
    672 		           "for request from $client ($method)",
    673 		           log_data_string("method", method));
    674 		json_decref(j);
    675 		return;
    676 	}
    677 
    678 	if (MyConnect(client))
    679 		rpc_sendto(client, json_serialized, strlen(json_serialized));
    680 	else
    681 		rpc_send_response_to_remote(&me, client, j);
    682 
    683 #ifdef DEBUGMODE
    684 	unreal_log(ULOG_DEBUG, "rpc", "RPC_CALL_DEBUG", client,
    685 		   "[rpc] Client $client: RPC result error: $response",
    686 		   log_data_string("response", json_serialized));
    687 #endif
    688 	json_decref(j);
    689 	safe_free(json_serialized);
    690 }
    691 
    692 void _rpc_error_fmt(Client *client, json_t *request, JsonRpcError error_code, const char *fmt, ...)
    693 {
    694 	char buf[512];
    695 
    696 	va_list vl;
    697 	va_start(vl, fmt);
    698 	vsnprintf(buf, sizeof(buf), fmt, vl);
    699 	va_end(vl);
    700 	rpc_error(client, request, error_code, buf);
    701 }
    702 
    703 void _rpc_response(Client *client, json_t *request, json_t *result)
    704 {
    705 	const char *method = json_object_get_string(request, "method");
    706 	json_t *id = json_object_get(request, "id");
    707 	char *json_serialized;
    708 	json_t *j = json_object();
    709 
    710 	json_object_set_new(j, "jsonrpc", json_string_unreal("2.0"));
    711 	json_object_set_new(j, "method", json_string_unreal(method));
    712 	if (id)
    713 		json_object_set(j, "id", id); /* 'id' is optional */
    714 	json_object_set(j, "result", result);
    715 
    716 	json_serialized = json_dumps(j, 0);
    717 	if (!json_serialized)
    718 	{
    719 		unreal_log(ULOG_WARNING, "rpc", "BUG_RPC_RESPONSE_SERIALIZE_FAILED", NULL,
    720 		           "[BUG] rpc_response() failed to serialize response "
    721 		           "for request from $client ($method)",
    722 		           log_data_string("method", method));
    723 		json_decref(j);
    724 		return;
    725 	}
    726 
    727 	if (MyConnect(client))
    728 		rpc_sendto(client, json_serialized, strlen(json_serialized));
    729 	else
    730 		rpc_send_response_to_remote(&me, client, j);
    731 
    732 #ifdef DEBUGMODE
    733 	unreal_log(ULOG_DEBUG, "rpc", "RPC_CALL_DEBUG", client,
    734 		   "[rpc] Client $client: RPC response result: $response",
    735 		   log_data_string("response", json_serialized));
    736 #endif
    737 	json_decref(j);
    738 	safe_free(json_serialized);
    739 }
    740 
    741 int sanitize_params_actual(Client *client, json_t *request, const char *str)
    742 {
    743 	if (!str)
    744 		return 1;
    745 
    746 	if (strlen(str) > 510)
    747 	{
    748 		rpc_error(client, request, JSON_RPC_ERROR_INVALID_REQUEST, "Strings cannot be longer than 510 characters in the request");
    749 		return 0;
    750 	}
    751 
    752 	if (strchr(str, '\n') || strchr(str, '\r'))
    753 	{
    754 		rpc_error(client, request, JSON_RPC_ERROR_INVALID_REQUEST, "Strings may not contain \n or \r in the request");
    755 		return 0;
    756 	}
    757 
    758 	return 1;
    759 }
    760 
    761 int sanitize_params(Client *client, json_t *request, json_t *j)
    762 {
    763 	/* Check the current object itself */
    764 	const char *str = json_string_value(j);
    765 	if (str && !sanitize_params_actual(client, request, str))
    766 		return 0;
    767 
    768 	/* Now walk through the object, if needed */
    769 
    770 	if (json_is_array(j))
    771 	{
    772 		size_t index;
    773 		json_t *value;
    774 		json_array_foreach(j, index, value)
    775 		{
    776 			if (!sanitize_params(client, request, value))
    777 				return 0;
    778 		}
    779 	} else
    780 	if (json_is_object(j))
    781 	{
    782 		const char *key;
    783 		json_t *value;
    784 		json_object_foreach(j, key, value)
    785 		{
    786 			if (!sanitize_params_actual(client, request, key))
    787 				return 0;
    788 			if (!sanitize_params(client, request, value))
    789 				return 0;
    790 		}
    791 	}
    792 
    793 	return 1;
    794 }
    795 
    796 /** Log the RPC request */
    797 void rpc_call_log(Client *client, RPCHandler *handler, json_t *request, const char *method, json_t *params)
    798 {
    799 	const char *key;
    800 	json_t *value_object;
    801 	char params_string[512], tbuf[256];
    802 
    803 	*params_string = '\0';
    804 	json_object_foreach(params, key, value_object)
    805 	{
    806 		const char *value = json_get_value(value_object);
    807 		if (value)
    808 		{
    809 			snprintf(tbuf, sizeof(tbuf), "%s='%s', ", key, value);
    810 			strlcat(params_string, tbuf, sizeof(params_string));
    811 		}
    812 	}
    813 	if (*params_string)
    814 		params_string[strlen(params_string)-2] = '\0'; /* cut off last comma */
    815 
    816 	// TODO: pass log_data_json() or something, pass the entire 'request' ? For JSON logging
    817 
    818 	if (client->rpc && client->rpc->issuer)
    819 	{
    820 		if (*params_string)
    821 		{
    822 			unreal_log(handler->loglevel, "rpc", "RPC_CALL", client,
    823 				   "[rpc] RPC call $method by $client ($issuer): $params_string",
    824 				   log_data_string("issuer", client->rpc->issuer),
    825 				   log_data_string("method", method),
    826 				   log_data_string("params_string", params_string));
    827 		} else {
    828 			unreal_log(handler->loglevel, "rpc", "RPC_CALL", client,
    829 				   "[rpc] RPC call $method by $client ($issuer)",
    830 				   log_data_string("issuer", client->rpc->issuer),
    831 				   log_data_string("method", method));
    832 		}
    833 	} else {
    834 		if (*params_string)
    835 		{
    836 			unreal_log(handler->loglevel, "rpc", "RPC_CALL", client,
    837 				   "[rpc] RPC call $method by $client: $params_string",
    838 				   log_data_string("method", method),
    839 				   log_data_string("params_string", params_string));
    840 		} else {
    841 			unreal_log(handler->loglevel, "rpc", "RPC_CALL", client,
    842 				   "[rpc] RPC call $method by $client",
    843 				   log_data_string("method", method));
    844 		}
    845 	}
    846 }
    847 
    848 /** Parse an RPC request, except that it does not validate 'params'.
    849  * @param client	The client issuing the request
    850  * @param mainrequest	The underlying request that we should send errors to (usually same as 'request')
    851  * @param request	The request that needs parsing
    852  * @param method	This will be filled in if successfully parsed
    853  * @param handler	This will be filled in if the handler is found
    854  * @retval 0		An error occured while parsing or the method was not found.
    855  * @retval 1		All good. You still need to validate 'params', though.
    856  */
    857 int parse_rpc_call(Client *client, json_t *mainrequest, json_t *request, const char **method, RPCHandler **handler)
    858 {
    859 	const char *jsonrpc;
    860 	json_t *id;
    861 	const char *str;
    862 
    863 	*method = NULL;
    864 	*handler = NULL;
    865 
    866 	jsonrpc = json_object_get_string(request, "jsonrpc");
    867 	if (!jsonrpc || strcasecmp(jsonrpc, "2.0"))
    868 	{
    869 		rpc_error(client, mainrequest, JSON_RPC_ERROR_INVALID_REQUEST, "Only JSON-RPC version 2.0 is supported");
    870 		return 0;
    871 	}
    872 
    873 	id = json_object_get(request, "id");
    874 	if (!id)
    875 	{
    876 		rpc_error(client, mainrequest, JSON_RPC_ERROR_INVALID_REQUEST, "Missing 'id'");
    877 		return 0;
    878 	}
    879 
    880 	if ((str = json_string_value(id)))
    881 	{
    882 		if (strlen(str) > 32)
    883 		{
    884 			rpc_error(client, mainrequest, JSON_RPC_ERROR_INVALID_REQUEST, "The 'id' cannot be longer than 32 characters in UnrealIRCd JSON-RPC");
    885 			return 0;
    886 		}
    887 		if (strchr(str, '\n') || strchr(str, '\r'))
    888 		{
    889 			rpc_error(client, mainrequest, JSON_RPC_ERROR_INVALID_REQUEST, "The 'id' may not contain \n or \r in UnrealIRCd JSON-RPC");
    890 			return 0;
    891 		}
    892 	} else if (!json_is_integer(id))
    893 	{
    894 		rpc_error(client, mainrequest, JSON_RPC_ERROR_INVALID_REQUEST, "The 'id' must be a string or an integer in UnrealIRCd JSON-RPC");
    895 		return 0;
    896 	}
    897 
    898 	*method = json_object_get_string(request, "method");
    899 	if (!*method)
    900 	{
    901 		rpc_error(client, mainrequest, JSON_RPC_ERROR_INVALID_REQUEST, "Missing 'method' to call");
    902 		return 0;
    903 	}
    904 
    905 	*handler = RPCHandlerFind(*method);
    906 	if (!*handler)
    907 	{
    908 		rpc_error(client, mainrequest, JSON_RPC_ERROR_METHOD_NOT_FOUND, "Unsupported method");
    909 		return 0;
    910 	}
    911 
    912 	return 1;
    913 }
    914 
    915 /** Handle the RPC request: request is in JSON */
    916 void rpc_call(Client *client, json_t *request)
    917 {
    918 	const char *method;
    919 	json_t *params;
    920 	RPCHandler *handler;
    921 
    922 	if (!parse_rpc_call(client, request, request, &method, &handler))
    923 		return; /* Error already returned to caller */
    924 
    925 	params = json_object_get(request, "params");
    926 	if (params)
    927 	{
    928 		if (!(handler->flags & RPC_HANDLER_FLAGS_UNFILTERED) &&
    929 		    !sanitize_params(client, request, params))
    930 		{
    931 			return;
    932 		}
    933 	} else
    934 	{
    935 		/* Params is optional, so create an empty params object instead
    936 		 * to make life easier of the RPC handlers (no need to check NULL).
    937 		 */
    938 		params = json_object();
    939 		json_object_set_new(request, "params", params);
    940 	}
    941 
    942 	rpc_call_log(client, handler, request, method, params);
    943 
    944 #ifdef DEBUGMODE
    945 	{
    946 		char *call = json_dumps(request, 0);
    947 		if (call)
    948 		{
    949 			unreal_log(ULOG_DEBUG, "rpc", "RPC_CALL_DEBUG", client,
    950 				   "[rpc] Client $client: RPC call: $call",
    951 				   log_data_string("call", call));
    952 			safe_free(call);
    953 		}
    954 	}
    955 #endif
    956 	handler->call(client, request, params);
    957 }
    958 
    959 /** Called very early on accept() of the socket, before TLS is ready */
    960 int rpc_client_accept(Client *client)
    961 {
    962 	if (RPC_PORT(client))
    963 	{
    964 		SetRPC(client);
    965 		client->rpc = safe_alloc(sizeof(RPCClient));
    966 	}
    967 	return 0;
    968 }
    969 
    970 /** Called upon handshake of unix socket (direct JSON usage, no auth) */
    971 void rpc_client_handshake_unix_socket(Client *client)
    972 {
    973 	if (client->local->listener->socket_type != SOCKET_TYPE_UNIX)
    974 		abort(); /* impossible */
    975 
    976 	strlcpy(client->name, "RPC:local", sizeof(client->name));
    977 	SetRPC(client);
    978 	client->rpc = safe_alloc(sizeof(RPCClient));
    979 	safe_strdup(client->rpc->rpc_user, "<local>");
    980 
    981 	/* Allow incoming data to be read from now on.. */
    982 	fd_setselect(client->local->fd, FD_SELECT_READ, read_packet, client);
    983 }
    984 
    985 /** Called upon handshake, after TLS is ready (before any HTTP header parsing) */
    986 void rpc_client_handshake_web(Client *client)
    987 {
    988 	RPCUser *r;
    989 	char found = 0;
    990 
    991 	/* Explicitly mark as RPC, since the TLS layer may
    992 	 * have set us to SetUnknown() after the TLS handshake.
    993 	 */
    994 	SetRPC(client);
    995 	if (!client->rpc)
    996 		client->rpc = safe_alloc(sizeof(RPCClient));
    997 
    998 	/* Is the client allowed by any rpc-user { } block?
    999 	 * If not, reject the client immediately, before
   1000 	 * processing any HTTP data.
   1001 	 */
   1002 	for (r = rpcusers; r; r = r->next)
   1003 	{
   1004 		if (user_allowed_by_security_group(client, r->match))
   1005 		{
   1006 			found = 1;
   1007 			break;
   1008 		}
   1009 	}
   1010 	if (!found)
   1011 	{
   1012 		webserver_send_response(client, 401, "Access denied");
   1013 		return;
   1014 	}
   1015 
   1016 	/* Allow incoming data to be read from now on.. */
   1017 	fd_setselect(client->local->fd, FD_SELECT_READ, read_packet, client);
   1018 }
   1019 
   1020 #define RPC_WEBSOCKET_PING_TIME 120
   1021 
   1022 int rpc_pre_local_handshake_timeout(Client *client, const char **comment)
   1023 {
   1024 	/* Don't hang up websocket connections */
   1025 	if (IsRPC(client) && WSU(client) && WSU(client)->handshake_completed)
   1026 	{
   1027 		long t = TStime() - client->local->last_msg_received;
   1028 		if ((t > RPC_WEBSOCKET_PING_TIME*2) && IsPingSent(client))
   1029 		{
   1030 			*comment = "No websocket PONG received in time.";
   1031 			return HOOK_CONTINUE;
   1032 		} else
   1033 		if ((t > RPC_WEBSOCKET_PING_TIME) && !IsPingSent(client) && !IsDead(client))
   1034 		{
   1035 			char pingbuf[4];
   1036 			const char *pkt = pingbuf;
   1037 			int pktlen = sizeof(pingbuf);
   1038 			pingbuf[0] = 0x11;
   1039 			pingbuf[1] = 0x22;
   1040 			pingbuf[2] = 0x33;
   1041 			pingbuf[3] = 0x44;
   1042 			websocket_create_packet_simple(WSOP_PING, &pkt, &pktlen);
   1043 			dbuf_put(&client->local->sendQ, pkt, pktlen);
   1044 			send_queued(client);
   1045 			SetPingSent(client);
   1046 		}
   1047 		return HOOK_ALLOW; /* prevent closing the connection due to timeout */
   1048 	}
   1049 
   1050 	return HOOK_CONTINUE;
   1051 }
   1052 
   1053 RPCUser *find_rpc_user(const char *username)
   1054 {
   1055 	RPCUser *r;
   1056 	for (r = rpcusers; r; r = r->next)
   1057 		if (!strcmp(r->name, username))
   1058 			return r;
   1059 	return NULL;
   1060 }
   1061 
   1062 /** This function deals with authentication after the HTTP request was received.
   1063  * It is called for both ordinary HTTP(S) requests and Websockets.
   1064  * Note that there has also been some pre-filtering done in rpc_client_handshake()
   1065  * to see if the IP address was allowed to connect at all (::match),
   1066  * but here we actually check the 'correct' rpc-user { } block.
   1067  * @param client	The client to authenticate
   1068  * @param web		The webrequest (containing the headers)
   1069  * @return 1 on success, 0 on failure
   1070  */
   1071 int rpc_handle_auth(Client *client, WebRequest *web)
   1072 {
   1073 	char *username = NULL, *password = NULL;
   1074 	RPCUser *r;
   1075 
   1076 	if (!rpc_parse_auth_basic_auth(client, web, &username, &password) &&
   1077 	    !rpc_parse_auth_uri(client, web, &username, &password))
   1078 	{
   1079 		webserver_send_response(client, 401, "Authentication required");
   1080 		return 0;
   1081 	}
   1082 
   1083 	if (username && password && ((r = find_rpc_user(username))))
   1084 	{
   1085 		if (user_allowed_by_security_group(client, r->match) &&
   1086 		    Auth_Check(client, r->auth, password))
   1087 		{
   1088 			/* Authenticated! */
   1089 			snprintf(client->name, sizeof(client->name), "RPC:%s", r->name);
   1090 			safe_strdup(client->rpc->rpc_user, r->name);
   1091 			return 1;
   1092 		}
   1093 	}
   1094 
   1095 	/* Authentication failed */
   1096 	webserver_send_response(client, 401, "Authentication required");
   1097 	return 0;
   1098 }
   1099 
   1100 int rpc_parse_auth_basic_auth(Client *client, WebRequest *web, char **username, char **password)
   1101 {
   1102 	const char *auth_header = get_nvplist(web->headers, "Authorization");
   1103 	static char buf[512];
   1104 	char *p;
   1105 	int n;
   1106 
   1107 	if (!auth_header)
   1108 		return 0;
   1109 
   1110 	/* We only support basic auth */
   1111 	if (strncasecmp(auth_header, "Basic ", 6))
   1112 		return 0;
   1113 
   1114 	p = strchr(auth_header, ' ');
   1115 	skip_whitespace(&p);
   1116 	n = b64_decode(p, buf, sizeof(buf)-1);
   1117 	if (n <= 1)
   1118 		return 0;
   1119 	buf[n] = '\0';
   1120 
   1121 	p = strchr(buf, ':');
   1122 	if (!p)
   1123 		return 0;
   1124 	*p++ = '\0';
   1125 
   1126 	*username = buf;
   1127 	*password = p;
   1128 	return 1;
   1129 }
   1130 
   1131 // TODO: the ?a=b&c=d stuff should be urldecoded by 'webserver'
   1132 int rpc_parse_auth_uri(Client *client, WebRequest *web, char **username, char **password)
   1133 {
   1134 	static char buf[2048];
   1135 	char *str, *p;
   1136 
   1137 	if (!web->uri)
   1138 		return 0;
   1139 
   1140 	strlcpy(buf, web->uri, sizeof(buf));
   1141 	str = strstr(buf, "username=");
   1142 	if (!str)
   1143 		return 0;
   1144 	str += 9;
   1145 	*username = str;
   1146 	p = strchr(str, '&');
   1147 	if (p)
   1148 	{
   1149 		*p++ = '\0';
   1150 		p = strstr(p, "password=");
   1151 		if (p)
   1152 		{
   1153 			p += 9;
   1154 			*password = p;
   1155 			p = strchr(str, '&');
   1156 			if (p)
   1157 				*p = '\0';
   1158 		}
   1159 	}
   1160 	return 1;
   1161 }
   1162 
   1163 RPC_CALL_FUNC(rpc_rpc_info)
   1164 {
   1165 	json_t *result, *methods, *item;
   1166 	RPCHandler *r;
   1167 
   1168 	result = json_object();
   1169 	methods = json_object();
   1170 	json_object_set_new(result, "methods", methods);
   1171 
   1172 	for (r = rpchandlers; r; r = r->next)
   1173 	{
   1174 		item = json_object();
   1175 		json_object_set_new(item, "name", json_string_unreal(r->method));
   1176 		if (r->owner)
   1177 		{
   1178 			json_object_set_new(item, "module", json_string_unreal(r->owner->header->name));
   1179 			json_object_set_new(item, "version", json_string_unreal(r->owner->header->version));
   1180 		}
   1181 		json_object_set_new(methods, r->method, item);
   1182 	}
   1183 
   1184 	rpc_response(client, request, result);
   1185 	json_decref(result);
   1186 }
   1187 
   1188 RPC_CALL_FUNC(rpc_rpc_set_issuer)
   1189 {
   1190 	json_t *result;
   1191 	const char *name;
   1192 	char buf[512];
   1193 
   1194 	REQUIRE_PARAM_STRING("name", name);
   1195 
   1196 	/* Do some validation on the name */
   1197 	strlcpy(buf, name, sizeof(buf));
   1198 	if (!do_remote_nick_name(buf) || strcmp(buf, name))
   1199 	{
   1200 		rpc_error(client, request, JSON_RPC_ERROR_INVALID_NAME,
   1201 		          "The 'name' contains illegal characters or is too long. "
   1202 		          "The same rules as for nick names apply.");
   1203 		return;
   1204 	}
   1205 
   1206 	safe_strdup(client->rpc->issuer, name);
   1207 
   1208 	result = json_boolean(1);
   1209 	rpc_response(client, request, result);
   1210 	json_decref(result);
   1211 }
   1212 
   1213 void free_rrpc(RRPC *r)
   1214 {
   1215 	safe_free(r->requestid);
   1216 	DBufClear(&r->data);
   1217 	DelListItem(r, rrpc_list);
   1218 	safe_free(r);
   1219 }
   1220 
   1221 /* Admin unloading the RPC module for good (not called on rehash) */
   1222 void free_rrpc_list(ModData *m)
   1223 {
   1224 	RRPC *r, *r_next;
   1225 
   1226 	for (r = rrpc_list; r; r = r_next)
   1227 	{
   1228 		r_next = r->next;
   1229 		free_rrpc(r);
   1230 	}
   1231 }
   1232 
   1233 void free_outstanding_rrpc(OutstandingRRPC *r)
   1234 {
   1235 	safe_free(r->requestid);
   1236 	DelListItem(r, outstanding_rrpc_list);
   1237 	safe_free(r);
   1238 }
   1239 
   1240 /* Admin unloading the RPC module for good (not called on rehash) */
   1241 void free_outstanding_rrpc_list(ModData *m)
   1242 {
   1243 	OutstandingRRPC *r, *r_next;
   1244 
   1245 	for (r = outstanding_rrpc_list; r; r = r_next)
   1246 	{
   1247 		r_next = r->next;
   1248 		free_outstanding_rrpc(r);
   1249 	}
   1250 }
   1251 
   1252 /** Remove timer from rpc_timer_list and free it */
   1253 void free_rpc_timer(RPCTimer *r)
   1254 {
   1255 	safe_free(r->timer_id);
   1256 	json_decref(r->request);
   1257 	DelListItem(r, rpc_timer_list);
   1258 	safe_free(r);
   1259 }
   1260 
   1261 /* Admin unloading the RPC module for good (not called on rehash) */
   1262 void free_rpc_timer_list(ModData *m)
   1263 {
   1264 	RPCTimer *r, *r_next;
   1265 
   1266 	for (r = rpc_timer_list; r; r = r_next)
   1267 	{
   1268 		r_next = r->next;
   1269 		free_rpc_timer(r);
   1270 	}
   1271 }
   1272 
   1273 /* Admin unloading the RPC module for good (not called on rehash) */
   1274 void free_rpc_timers_for_user(Client *client)
   1275 {
   1276 	RPCTimer *r, *r_next;
   1277 
   1278 	for (r = rpc_timer_list; r; r = r_next)
   1279 	{
   1280 		r_next = r->next;
   1281 		if (r->client == client)
   1282 			free_rpc_timer(r);
   1283 	}
   1284 }
   1285 
   1286 RPCTimer *find_rpc_timer(Client *client, const char *timer_id)
   1287 {
   1288 	RPCTimer *r;
   1289 
   1290 	for (r = rpc_timer_list; r; r = r->next)
   1291 	{
   1292 		if ((r->client == client) && !strcmp(timer_id, r->timer_id))
   1293 			return r;
   1294 	}
   1295 	return NULL;
   1296 }
   1297 
   1298 /** When a server quits, cancel all the RPC requests to/from those clients */
   1299 int rpc_handle_server_quit(Client *client, MessageTag *mtags)
   1300 {
   1301 	RRPC *r, *r_next;
   1302 	OutstandingRRPC *or, *or_next;
   1303 
   1304 	for (r = rrpc_list; r; r = r_next)
   1305 	{
   1306 		r_next = r->next;
   1307 		if (!strncmp(client->id, r->source, SIDLEN) ||
   1308 		    !strncmp(client->id, r->destination, SIDLEN))
   1309 		{
   1310 			free_rrpc(r);
   1311 		}
   1312 	}
   1313 
   1314 	for (or = outstanding_rrpc_list; or; or = or_next)
   1315 	{
   1316 		or_next = or->next;
   1317 		if (!strcmp(client->id, or->destination))
   1318 		{
   1319 			Client *client = find_client(or->source, NULL);
   1320 			if (client)
   1321 			{
   1322 				json_t *j = json_object();
   1323 				json_object_set_new(j, "id", json_string_unreal(or->requestid));
   1324 				rpc_error(client, NULL, JSON_RPC_ERROR_SERVER_GONE, "Remote server disconnected while processing the request");
   1325 				json_decref(j);
   1326 			}
   1327 			free_outstanding_rrpc(or);
   1328 		}
   1329 	}
   1330 
   1331 	return 0;
   1332 }
   1333 
   1334 EVENT(rpc_remote_timeout)
   1335 {
   1336 	OutstandingRRPC *or, *or_next;
   1337 	time_t deadline = TStime() - 15;
   1338 
   1339 	for (or = outstanding_rrpc_list; or; or = or_next)
   1340 	{
   1341 		or_next = or->next;
   1342 		if (or->sent < deadline)
   1343 		{
   1344 			Client *client = find_client(or->source, NULL);
   1345 			if (client)
   1346 			{
   1347 				json_t *request = json_object();
   1348 				json_object_set_new(request, "id", json_string_unreal(or->requestid));
   1349 				rpc_error(client, request, JSON_RPC_ERROR_TIMEOUT, "Request timed out");
   1350 				json_decref(request);
   1351 			}
   1352 			free_outstanding_rrpc(or);
   1353 		}
   1354 	}
   1355 }
   1356 
   1357 RRPC *find_rrpc(const char *source, const char *destination, const char *requestid)
   1358 {
   1359 	RRPC *r;
   1360 	for (r = rrpc_list; r; r = r->next)
   1361 	{
   1362 		if (!strcmp(r->source, source) &&
   1363 		    !strcmp(r->destination, destination) &&
   1364 		    !strcmp(r->requestid, requestid))
   1365 		{
   1366 			return r;
   1367 		}
   1368 	}
   1369 	return NULL;
   1370 }
   1371 
   1372 OutstandingRRPC *find_outstandingrrpc(const char *source, const char *requestid)
   1373 {
   1374 	OutstandingRRPC *r;
   1375 	for (r = outstanding_rrpc_list; r; r = r->next)
   1376 	{
   1377 		if (!strcmp(r->source, source) &&
   1378 		    !strcmp(r->requestid, requestid))
   1379 		{
   1380 			return r;
   1381 		}
   1382 	}
   1383 	return NULL;
   1384 }
   1385 
   1386 /* Remote RPC call over the network (RRPC)
   1387  * :<server> RRPC <REQ|RES> <source> <destination> <requestid> [S|C|F] :<request data>
   1388  * S = Start
   1389  * C = Continuation
   1390  * F = Finish
   1391  */
   1392 CMD_FUNC(cmd_rrpc)
   1393 {
   1394 	int request;
   1395 	const char *source, *destination, *requestid, *type, *data;
   1396 	RRPC *r;
   1397 	Client *dest;
   1398 	char sid[SIDLEN+1];
   1399 	char binarydata[BUFSIZE+1];
   1400 	int binarydatalen;
   1401 
   1402 	if ((parc < 7) || BadPtr(parv[6]))
   1403 	{
   1404 		sendnumeric(client, ERR_NEEDMOREPARAMS, "KNOCK");
   1405 		return;
   1406 	}
   1407 
   1408 	if (!strcmp(parv[1], "REQ"))
   1409 	{
   1410 		request = 1;
   1411 	} else if (!strcmp(parv[1], "RES"))
   1412 	{
   1413 		request = 0;
   1414 	} else {
   1415 		sendnumeric(client, ERR_CANNOTDOCOMMAND, "RRPC", "Invalid parameter");
   1416 		return;
   1417 	}
   1418 
   1419 	source = parv[2];
   1420 	destination = parv[3];
   1421 	requestid = parv[4];
   1422 	type = parv[5];
   1423 	data = parv[6];
   1424 
   1425 	/* Search by SID (first 3 characters of destination)
   1426 	 * so we can always deliver, even forn unknown UID destinations
   1427 	 * in case this is a response.
   1428 	 */
   1429 	strlcpy(sid, destination, sizeof(sid));
   1430 	dest = find_server_quick(sid);
   1431 	if (!dest)
   1432 	{
   1433 		sendnumeric(client, ERR_NOSUCHSERVER, sid);
   1434 		return;
   1435 	}
   1436 
   1437 	if (dest != &me)
   1438 	{
   1439 		/* Just pass it along... */
   1440 		sendto_one(dest, recv_mtags, ":%s RRPC %s %s %s %s %s :%s",
   1441 		           client->id, parv[1], parv[2], parv[3], parv[4], parv[5], parv[6]);
   1442 		return;
   1443 	}
   1444 
   1445 	/* It's for us! So handle it ;) */
   1446 
   1447 	if (strchr(type, 'S'))
   1448 	{
   1449 		r = find_rrpc(source, destination, requestid);
   1450 		if (r)
   1451 		{
   1452 			sendnumeric(client, ERR_CANNOTDOCOMMAND, "RRPC", "Duplicate request found");
   1453 			/* We actually terminate the existing RRPC as well,
   1454 			 * because there's a big risk of the the two different ones
   1455 			 * merging in subsequent RRPC... C ... commands. Bad!
   1456 			 * (and yeah this does not handle the case where you have
   1457 			 *  like 3 or more duplicate request id requests... so be it..)
   1458 			 */
   1459 			free_rrpc(r);
   1460 			return;
   1461 		}
   1462 		/* A new request */
   1463 		r = safe_alloc(sizeof(RRPC));
   1464 		strlcpy(r->source, source, sizeof(r->source));
   1465 		strlcpy(r->destination, destination, sizeof(r->destination));
   1466 		safe_strdup(r->requestid, requestid);
   1467 		r->request = request;
   1468 		dbuf_queue_init(&r->data);
   1469 		AddListItem(r, rrpc_list);
   1470 	} else
   1471 	if (strchr(type, 'C') || strchr(type, 'F'))
   1472 	{
   1473 		r = find_rrpc(source, destination, requestid);
   1474 		if (!r)
   1475 		{
   1476 			sendnumeric(client, ERR_CANNOTDOCOMMAND, "RRPC", "Request not found");
   1477 			return;
   1478 		}
   1479 	} else
   1480 	{
   1481 		sendnumeric(client, ERR_CANNOTDOCOMMAND, "RRPC", "Only actions S/C/F are supported");
   1482 		return;
   1483 	}
   1484 
   1485 	/* Append the data */
   1486 	dbuf_put(&r->data, data, strlen(data));
   1487 
   1488 	/* Now check if the request happens to be terminated */
   1489 	if (strchr(type, 'F'))
   1490 	{
   1491 		if (r->request)
   1492 			rpc_call_remote(r);
   1493 		else
   1494 			rpc_response_remote(r);
   1495 		free_rrpc(r);
   1496 		return;
   1497 	}
   1498 }
   1499 
   1500 /** Convert the RRPC data to actual workable JSON output */
   1501 json_t *rrpc_data(RRPC *r)
   1502 {
   1503 	int datalen;
   1504 	char *data;
   1505 	json_t *j;
   1506 	json_error_t jerr;
   1507 
   1508 	datalen = dbuf_get(&r->data, &data);
   1509 	j = json_loads(data, JSON_REJECT_DUPLICATES, &jerr);
   1510 	safe_free(data);
   1511 
   1512 	return j;
   1513 }
   1514 
   1515 /** Received a remote RPC request (from a client on another server) */
   1516 void rpc_call_remote(RRPC *r)
   1517 {
   1518 	json_t *request = NULL;
   1519 	Client *server;
   1520 	Client *client;
   1521 	char sid[SIDLEN+1];
   1522 
   1523 	request = rrpc_data(r);
   1524 	if (!request)
   1525 	{
   1526 		// TODO: handle invalid JSON
   1527 		return;
   1528 	}
   1529 
   1530 	/* Create a (fake) client structure */
   1531 	strlcpy(sid, r->source, sizeof(sid));
   1532 	server = find_server_quick(sid);
   1533 	if (!server)
   1534 	{
   1535 		return;
   1536 	}
   1537 	client = make_client(server->direction, server);
   1538 	strlcpy(client->id, r->source, sizeof(client->id));
   1539 	client->rpc = safe_alloc(sizeof(RPCClient));
   1540 	strlcpy(client->name, "RPC:remote", sizeof(client->name));
   1541 	safe_strdup(client->rpc->rpc_user, "<remote>");
   1542 	// Note: NOT added to hash table or id table etc.
   1543 	list_add(&client->client_node, &rpc_remote_list);
   1544 	rpc_call(client, request);
   1545 	json_decref(request);
   1546 
   1547 	/* And free the temporary client, unless it is async... */
   1548 	if (!IsAsyncRPC(client))
   1549 		free_client(client);
   1550 }
   1551 
   1552 /** Received a remote RPC response (from another server) to our local RPC client */
   1553 void rpc_response_remote(RRPC *r)
   1554 {
   1555 	OutstandingRRPC *or;
   1556 	Client *client = find_client(r->destination, NULL);
   1557 	json_t *json, *j;
   1558 
   1559 	if (!client)
   1560 		return;
   1561 
   1562 	or = find_outstandingrrpc(client->id, r->requestid);
   1563 	if (!or)
   1564 		return; /* Not a known outstanding request, maybe the client left already */
   1565 
   1566 	json = rrpc_data(r);
   1567 	if (!json)
   1568 		return;
   1569 
   1570 	if ((j = json_object_get(json, "result")))
   1571 	{
   1572 		rpc_response(client, json, j);
   1573 	} else if ((j = json_object_get(json, "error")))
   1574 	{
   1575 		json_t *x;
   1576 		int errorcode = 0;
   1577 		const char *error_message = json_object_get_string(j, "message");
   1578 		if ((x = json_object_get(j, "errorcode")))
   1579 			errorcode = json_integer_value(x);
   1580 		if (errorcode == 0)
   1581 			errorcode = JSON_RPC_ERROR_INTERNAL_ERROR;
   1582 		rpc_error(client, json, errorcode, error_message ? error_message : "");
   1583 	}
   1584 
   1585 	json_decref(json);
   1586 
   1587 	free_outstanding_rrpc(or);
   1588 }
   1589 
   1590 const char *rpc_id(json_t *request)
   1591 {
   1592 	static char rid[128];
   1593 	const char *requestid;
   1594 	json_t *j;
   1595 
   1596 	j = json_object_get(request, "id");
   1597 	if (!j)
   1598 		return NULL;
   1599 
   1600 	requestid = json_string_value(j);
   1601 	if (!requestid)
   1602 	{
   1603 		json_int_t v = json_integer_value(j);
   1604 		if (v == 0)
   1605 			return NULL;
   1606 		snprintf(rid, sizeof(rid), "%lld", (long long)v);
   1607 		requestid = rid;
   1608 	}
   1609 
   1610 	return requestid;
   1611 }
   1612 
   1613 /** Send a remote RPC (RRPC) request 'request' to server 'target'. */
   1614 void rpc_send_generic_to_remote(Client *source, Client *target, const char *requesttype, json_t *json)
   1615 {
   1616 	char *json_serialized;
   1617 	json_t *j;
   1618 	const char *type;
   1619 	const char *requestid;
   1620 	char *str;
   1621 	int bytes; /* bytes in this frame */
   1622 	int bytes_remaining; /* bytes remaining overall */
   1623 	int start_frame = 1; /* set to 1 if this is the start frame */
   1624 	char data[451];
   1625 
   1626 	requestid = rpc_id(json);
   1627 	if (!requestid)
   1628 		return;
   1629 
   1630 	json_serialized = json_dumps(json, 0);
   1631 	if (!json_serialized)
   1632 		return;
   1633 
   1634 	/* :<server> RRPC REQ <source> <destination> <requestid> [S|C|F] :<request data>
   1635 	 * S = Start
   1636 	 * C = Continuation
   1637 	 * F = Finish
   1638 	 */
   1639 
   1640 	bytes_remaining = strlen(json_serialized);
   1641 	for (str = json_serialized, bytes = MIN(bytes_remaining, 450);
   1642 	     str && *str && bytes_remaining;
   1643 	     str += bytes, bytes = MIN(bytes_remaining, 450))
   1644 	{
   1645 		bytes_remaining -= bytes;
   1646 		if (start_frame == 1)
   1647 		{
   1648 			start_frame = 0;
   1649 			if (bytes_remaining > 0)
   1650 				type = "S"; /* start (with later continuation frames) */
   1651 			else
   1652 				type = "SF"; /* start and finish */
   1653 		} else
   1654 		if (bytes_remaining > 0)
   1655 		{
   1656 			type = "C"; /* continuation frame (with later a finish frame) */
   1657 		} else {
   1658 			type = "F"; /* finish frame (the last frame) */
   1659 		}
   1660 
   1661 		strlncpy(data, str, sizeof(data), bytes);
   1662 
   1663 		sendto_one(target, NULL, ":%s RRPC %s %s %s %s %s :%s",
   1664 		           me.id,
   1665 		           requesttype,
   1666 		           source->id,
   1667 		           target->id,
   1668 		           requestid,
   1669 		           type,
   1670 		           data);
   1671 	}
   1672 
   1673 	safe_free(json_serialized);
   1674 }
   1675 
   1676 int _rrpc_supported_simple(Client *target, char **problem_server)
   1677 {
   1678 	if (!moddata_client_get(target, "rrpc"))
   1679 	{
   1680 		if (problem_server)
   1681 			*problem_server = target->name;
   1682 		return 0;
   1683 	}
   1684 	if ((target != target->direction) && !rrpc_supported_simple(target->direction, problem_server))
   1685 		return 0;
   1686 	return 1;
   1687 }
   1688 
   1689 int _rrpc_supported(Client *target, const char *module, const char *minimum_version, char **problem_server)
   1690 {
   1691 	if (!moddata_client_get(target, "rrpc"))
   1692 	{
   1693 		if (problem_server)
   1694 			*problem_server = target->name;
   1695 		return 0;
   1696 	}
   1697 	if ((target != target->direction) && !rrpc_supported_simple(target->direction, problem_server))
   1698 		return 0;
   1699 	return 1;
   1700 }
   1701 
   1702 /** Send a remote RPC (RRPC) request 'request' to server 'target'. */
   1703 void _rpc_send_request_to_remote(Client *source, Client *target, json_t *request)
   1704 {
   1705 	OutstandingRRPC *r;
   1706 	const char *requestid = rpc_id(request);
   1707 	char *problem_server = NULL;
   1708 
   1709 	if (!requestid)
   1710 	{
   1711 		/* should never happen, since already covered upstream, but just to be sure... */
   1712 		rpc_error(source, NULL, JSON_RPC_ERROR_INVALID_REQUEST, "The 'id' must be a string or an integer in UnrealIRCd JSON-RPC");
   1713 		return;
   1714 	}
   1715 
   1716 	if (find_outstandingrrpc(source->id, requestid))
   1717 	{
   1718 		rpc_error(source, NULL, JSON_RPC_ERROR_INVALID_REQUEST, "A request with that id is already in progress. Use unique id's!");
   1719 		return;
   1720 	}
   1721 
   1722 	/* If we already detect that next server cannot satisfy the request then stop it right now */
   1723 	if (!rrpc_supported_simple(target, &problem_server))
   1724 	{
   1725 		rpc_error_fmt(source, request, JSON_RPC_ERROR_REMOTE_SERVER_NO_RPC, "Server %s does not support remote JSON-RPC", problem_server);
   1726 		return;
   1727 	}
   1728 
   1729 	/* Add the request to the "Outstanding RRPC list" */
   1730 	r = safe_alloc(sizeof(OutstandingRRPC));
   1731 	r->sent = TStime();
   1732 	strlcpy(r->source, source->id, sizeof(r->source));
   1733 	strlcpy(r->destination, target->id, sizeof(r->destination));
   1734 	safe_strdup(r->requestid, requestid);
   1735 	AddListItem(r, outstanding_rrpc_list);
   1736 
   1737 	/* And send it! */
   1738 	rpc_send_generic_to_remote(source, target, "REQ", request);
   1739 }
   1740 
   1741 /** Send a remote RPC (RRPC) request 'request' to server 'target'. */
   1742 void _rpc_send_response_to_remote(Client *source, Client *target, json_t *response)
   1743 {
   1744 	rpc_send_generic_to_remote(source, target, "RES", response);
   1745 }
   1746 
   1747 const char *rrpc_md_serialize(ModData *m)
   1748 {
   1749 	static char buf[512];
   1750 	char tmp[128];
   1751 	NameValuePrioList *nv;
   1752 
   1753 	if (m->ptr == NULL)
   1754 		return NULL;
   1755 
   1756 	*buf = '\0';
   1757 	for (nv = m->ptr; nv; nv = nv->next)
   1758 	{
   1759 		snprintf(tmp, sizeof(tmp), "%s:%s,", nv->name, nv->value);
   1760 		strlcat(buf, tmp, sizeof(buf));
   1761 	}
   1762 	if (*buf)
   1763 		buf[strlen(buf)-1] = '\0'; // strip last comma
   1764 
   1765 	return buf;
   1766 }
   1767 
   1768 void rrpc_md_unserialize(const char *str, ModData *m)
   1769 {
   1770 	char buf[1024], *p, *name, *value;
   1771 
   1772 	/* First free everything if needed */
   1773 	if (m->ptr)
   1774 	{
   1775 		free_nvplist(m->ptr);
   1776 		m->ptr = NULL;
   1777 	}
   1778 
   1779 	if (BadPtr(str))
   1780 		return; /* Done already */
   1781 
   1782 	strlcpy(buf, str, sizeof(buf));
   1783 	for (name = strtoken(&p, buf, ","); name; name = strtoken(&p, NULL, ","))
   1784 	{
   1785 		value = strchr(name, ':');
   1786 		if (!value)
   1787 			continue;
   1788 		*value++ = '\0';
   1789 		add_nvplist((NameValuePrioList **)&m->ptr, 0, name, value);
   1790 	}
   1791 }
   1792 
   1793 void rrpc_md_free(ModData *m)
   1794 {
   1795 	if (m->ptr)
   1796 	{
   1797 		free_nvplist(m->ptr);
   1798 		m->ptr = NULL;
   1799 	}
   1800 }
   1801 
   1802 int rpc_json_expand_client_server(Client *client, int detail, json_t *j, json_t *child)
   1803 {
   1804 	NameValuePrioList *nv = RRPCMODULES(client);
   1805 	json_t *rpc_modules;
   1806 
   1807 	if (!nv || (detail < 2))
   1808 		return 0;
   1809 
   1810 	/* All this belongs under 'features' */
   1811 	child = json_object_get(child, "features");
   1812 	if (!child)
   1813 		return 0;
   1814 
   1815 	rpc_modules = json_array();
   1816 	json_object_set_new(child, "rpc_modules", rpc_modules);
   1817 	for (; nv; nv = nv->next)
   1818 	{
   1819 		json_t *e = json_object();
   1820 		json_object_set_new(e, "name", json_string_unreal(nv->name));
   1821 		json_object_set_new(e, "version", json_string_unreal(nv->value));
   1822 		json_array_append_new(rpc_modules, e);
   1823 	}
   1824 	return 0;
   1825 }
   1826 
   1827 RPC_CALL_FUNC(rpc_rpc_add_timer)
   1828 {
   1829 	json_t *result;
   1830 	json_t *subrequest;
   1831 	long every_msec;
   1832 	const char *timer_id;
   1833 	const char *method;
   1834 	RPCHandler *handler;
   1835 	RPCTimer *timer;
   1836 
   1837 	REQUIRE_PARAM_INTEGER("every_msec", every_msec);
   1838 	REQUIRE_PARAM_STRING("timer_id", timer_id);
   1839 
   1840 	subrequest = json_object_get(params, "request");
   1841 	if (!subrequest)
   1842 	{
   1843 		rpc_error_fmt(client, request, JSON_RPC_ERROR_INVALID_PARAMS, "Missing parameter: '%s'", "request");
   1844 		return;
   1845 	}
   1846 
   1847 	if (every_msec < RPC_MINIMUM_TIMER_MSEC)
   1848 	{
   1849 		rpc_error_fmt(client, request, JSON_RPC_ERROR_INVALID_PARAMS,
   1850 		              "Value for every_msec may not be less than %d",
   1851 		              (int)RPC_MINIMUM_TIMER_MSEC);
   1852 		return;
   1853 	}
   1854 
   1855 	/* Do some validation on the name */
   1856 	if (!parse_rpc_call(client, request, subrequest, &method, &handler))
   1857 		return; /* Error already returned to caller */
   1858 
   1859 	/* We don't validate 'params' here, but do so at runtime */
   1860 
   1861 	/* Check if a timer with that same name already exists FOR THIS CLIENT */
   1862 	if (find_rpc_timer(client, timer_id))
   1863 	{
   1864 		rpc_error_fmt(client, request, JSON_RPC_ERROR_ALREADY_EXISTS, "Timer already exists with timer_id '%s'", timer_id);
   1865 		return;
   1866 	}
   1867 
   1868 	timer = safe_alloc(sizeof(RPCTimer));
   1869 	timer->every_msec = every_msec;
   1870 	timer->client = client;
   1871 	safe_strdup(timer->timer_id, timer_id);
   1872 	json_incref(subrequest);
   1873 	timer->request = subrequest;
   1874 	AddListItem(timer, rpc_timer_list);
   1875 	result = json_boolean(1);
   1876 	rpc_response(client, request, result);
   1877 	json_decref(result);
   1878 }
   1879 
   1880 EVENT(rpc_do_timers)
   1881 {
   1882 	RPCTimer *e, *e_next;
   1883 
   1884 	for (e = rpc_timer_list; e; e = e_next)
   1885 	{
   1886 		e_next = e->next;
   1887 		if (minimum_msec_since_last_run(&e->last_run, e->every_msec))
   1888 		{
   1889 			rpc_call(e->client, e->request);
   1890 		}
   1891 		// TODO: maybe do counts as well?
   1892 	}
   1893 }
   1894 
   1895 /** Client being freed? If RPC then cancel timers, if any */
   1896 int rpc_handle_free_client(Client *client)
   1897 {
   1898 	if (IsRPC(client))
   1899 		free_rpc_timers_for_user(client);
   1900 	return 0;
   1901 }
   1902 
   1903 RPC_CALL_FUNC(rpc_rpc_del_timer)
   1904 {
   1905 	const char *timer_id;
   1906 	RPCTimer *r;
   1907 	json_t *result;
   1908 
   1909 	REQUIRE_PARAM_STRING("timer_id", timer_id);
   1910 
   1911 	r = find_rpc_timer(client, timer_id);
   1912 	if (!r)
   1913 	{
   1914 		rpc_error_fmt(client, request, JSON_RPC_ERROR_NOT_FOUND, "Timer not found with timer_id '%s'", timer_id);
   1915 		return;
   1916 	}
   1917 	free_rpc_timer(r);
   1918 
   1919 	result = json_boolean(1);
   1920 	rpc_response(client, request, result);
   1921 	json_decref(result);
   1922 }