Browse Source

jsonrpc: Generalize plugin_request to jsonrpc_request

There is very little that is plugin specific in the jsonrpc_request so
this just extracts the common parts so we can reuse them outside of
the plugin compilation unit as well.
plugin-timeout-inc
Christian Decker 6 years ago
committed by Rusty Russell
parent
commit
ff897f8788
  1. 36
      lightningd/jsonrpc.c
  2. 26
      lightningd/jsonrpc.h
  3. 92
      lightningd/plugin.c

36
lightningd/jsonrpc.c

@ -1027,6 +1027,42 @@ void jsonrpc_notification_end(struct jsonrpc_notification *n)
json_stream_append(n->stream, "\n\n"); json_stream_append(n->stream, "\n\n");
} }
struct jsonrpc_request *jsonrpc_request_start_(
const tal_t *ctx, const char *method,
void (*response_cb)(const char *buffer, const jsmntok_t *toks,
const jsmntok_t *idtok, void *),
void *response_cb_arg)
{
struct jsonrpc_request *r = tal(ctx, struct jsonrpc_request);
static u64 next_request_id = 0;
r->id = next_request_id++;
r->response_cb = response_cb;
r->response_cb_arg = response_cb_arg;
r->method = NULL;
r->stream = new_json_stream(r, NULL);
/* If no method is specified we don't prefill the JSON-RPC
* request with the header. This serves as an escape hatch to
* get a raw request, but get a valid request-id assigned. */
if (method != NULL) {
r->method = tal_strdup(r, method);
json_object_start(r->stream, NULL);
json_add_string(r->stream, "jsonrpc", "2.0");
json_add_u64(r->stream, "id", r->id);
json_add_string(r->stream, "method", method);
json_object_start(r->stream, "params");
}
return r;
}
void jsonrpc_request_end(struct jsonrpc_request *r)
{
json_object_end(r->stream); /* closes '.params' */
json_object_end(r->stream); /* closes '.' */
json_stream_append(r->stream, "\n\n");
}
/* We add this destructor as a canary to detect cmd failing. */ /* We add this destructor as a canary to detect cmd failing. */
static void destroy_command_canary(struct command *cmd, bool *failed) static void destroy_command_canary(struct command *cmd, bool *failed)
{ {

26
lightningd/jsonrpc.h

@ -66,6 +66,15 @@ struct jsonrpc_notification {
struct json_stream *stream; struct json_stream *stream;
}; };
struct jsonrpc_request {
u64 id;
const char *method;
struct json_stream *stream;
void (*response_cb)(const char *buffer, const jsmntok_t *toks,
const jsmntok_t *idtok, void *);
void *response_cb_arg;
};
/** /**
* json_stream_success - start streaming a successful json result. * json_stream_success - start streaming a successful json result.
* @cmd: the command we're running. * @cmd: the command we're running.
@ -183,5 +192,22 @@ struct jsonrpc_notification *jsonrpc_notification_start(const tal_t *ctx, const
*/ */
void jsonrpc_notification_end(struct jsonrpc_notification *n); void jsonrpc_notification_end(struct jsonrpc_notification *n);
#define jsonrpc_request_start(ctx, method, response_cb, response_cb_arg) \
jsonrpc_request_start_( \
(ctx), (method), \
typesafe_cb_preargs(void, void *, (response_cb), (response_cb_arg), \
const char *buffer, \
const jsmntok_t *toks, \
const jsmntok_t *idtok), \
(response_cb_arg))
struct jsonrpc_request *jsonrpc_request_start_(
const tal_t *ctx, const char *method,
void (*response_cb)(const char *buffer, const jsmntok_t *toks,
const jsmntok_t *idtok, void *),
void *response_cb_arg);
void jsonrpc_request_end(struct jsonrpc_request *request);
AUTODATA_TYPE(json_command, struct json_command); AUTODATA_TYPE(json_command, struct json_command);
#endif /* LIGHTNING_LIGHTNINGD_JSONRPC_H */ #endif /* LIGHTNING_LIGHTNINGD_JSONRPC_H */

92
lightningd/plugin.c

@ -66,24 +66,12 @@ struct plugin {
char **subscriptions; char **subscriptions;
}; };
struct plugin_request {
u64 id;
struct json_stream *stream;
/* The response handler to be called when plugin gives us an object. */
void (*cb)(const char *buffer,
const jsmntok_t *toks,
const jsmntok_t *idtok,
void *);
void *arg;
};
struct plugins { struct plugins {
struct list_head plugins; struct list_head plugins;
size_t pending_manifests; size_t pending_manifests;
/* Currently pending requests by their request ID */ /* Currently pending requests by their request ID */
UINTMAP(struct plugin_request *) pending_requests; UINTMAP(struct jsonrpc_request *) pending_requests;
struct log *log; struct log *log;
struct log_book *log_book; struct log_book *log_book;
@ -192,39 +180,29 @@ static void PRINTF_FMT(2,3) plugin_kill(struct plugin *plugin, char *fmt, ...)
* *
* The caller needs to add the request to req->stream. * The caller needs to add the request to req->stream.
*/ */
static struct plugin_request * static struct jsonrpc_request *
plugin_request_new_(struct plugin *plugin, plugin_request_new_(struct plugin *plugin,
const char *method,
void (*cb)(const char *buffer, void (*cb)(const char *buffer,
const jsmntok_t *toks, const jsmntok_t *toks,
const jsmntok_t *idtok, const jsmntok_t *idtok,
void *), void *),
void *arg) void *arg)
{ {
static u64 next_request_id = 0; struct jsonrpc_request *req = jsonrpc_request_start(plugin, method, cb, arg);
struct plugin_request *req = tal(plugin, struct plugin_request);
req->id = next_request_id++;
req->cb = cb;
req->arg = arg;
/* We will not concurrently drain, if we do we must set the
* writer to non-NULL */
req->stream = new_json_stream(req, NULL);
/* Add to map so we can find it later when routing the response */ /* Add to map so we can find it later when routing the response */
uintmap_add(&plugin->plugins->pending_requests, req->id, req); uintmap_add(&plugin->plugins->pending_requests, req->id, req);
return req; return req;
} }
#define plugin_request_new(plugin, method, response_cb, response_cb_arg) \
#define plugin_request_new(plugin, cb, arg) \ plugin_request_new_((plugin), (method), \
plugin_request_new_( \ typesafe_cb_preargs(void, void *, (response_cb), \
(plugin), \ (response_cb_arg), \
typesafe_cb_preargs(void, void *, (cb), (arg), \ const char *buffer, \
const char *buffer, \ const jsmntok_t *toks, \
const jsmntok_t *toks, \ const jsmntok_t *idtok), \
const jsmntok_t *idtok), \ (response_cb_arg))
(arg))
/** /**
* Send a JSON-RPC message (request or notification) to the plugin. * Send a JSON-RPC message (request or notification) to the plugin.
*/ */
@ -303,7 +281,7 @@ static void plugin_response_handle(struct plugin *plugin,
const jsmntok_t *toks, const jsmntok_t *toks,
const jsmntok_t *idtok) const jsmntok_t *idtok)
{ {
struct plugin_request *request; struct jsonrpc_request *request;
u64 id; u64 id;
/* We only send u64 ids, so if this fails it's a critical error (note /* We only send u64 ids, so if this fails it's a critical error (note
* that this also works if id is inside a JSON string!). */ * that this also works if id is inside a JSON string!). */
@ -323,7 +301,7 @@ static void plugin_response_handle(struct plugin *plugin,
} }
/* We expect the request->cb to copy if needed */ /* We expect the request->cb to copy if needed */
request->cb(plugin->buffer, toks, idtok, request->arg); request->response_cb(plugin->buffer, toks, idtok, request->response_cb_arg);
uintmap_del(&plugin->plugins->pending_requests, id); uintmap_del(&plugin->plugins->pending_requests, id);
tal_free(request); tal_free(request);
@ -666,7 +644,7 @@ static struct command_result *plugin_rpcmethod_dispatch(struct command *cmd,
{ {
const jsmntok_t *idtok; const jsmntok_t *idtok;
struct plugin *plugin; struct plugin *plugin;
struct plugin_request *req; struct jsonrpc_request *req;
char id[STR_MAX_CHARS(u64)]; char id[STR_MAX_CHARS(u64)];
if (cmd->mode == CMD_USAGE || cmd->mode == CMD_CHECK) { if (cmd->mode == CMD_USAGE || cmd->mode == CMD_CHECK) {
@ -681,7 +659,7 @@ static struct command_result *plugin_rpcmethod_dispatch(struct command *cmd,
idtok = json_get_member(buffer, toks, "id"); idtok = json_get_member(buffer, toks, "id");
assert(idtok != NULL); assert(idtok != NULL);
req = plugin_request_new(plugin, plugin_rpcmethod_cb, cmd); req = plugin_request_new(plugin, NULL, plugin_rpcmethod_cb, cmd);
snprintf(id, ARRAY_SIZE(id), "%"PRIu64, req->id); snprintf(id, ARRAY_SIZE(id), "%"PRIu64, req->id);
json_stream_forward_change_id(req->stream, buffer, toks, idtok, id); json_stream_forward_change_id(req->stream, buffer, toks, idtok, id);
@ -920,30 +898,13 @@ void clear_plugins(struct plugins *plugins)
tal_free(p); tal_free(p);
} }
/* For our own "getmanifest" and "init" requests: starts params[] */
static void start_simple_request(struct plugin_request *req, const char *reqname)
{
json_object_start(req->stream, NULL);
json_add_string(req->stream, "jsonrpc", "2.0");
json_add_string(req->stream, "method", reqname);
json_add_u64(req->stream, "id", req->id);
}
static void end_simple_request(struct plugin *plugin, struct plugin_request *req)
{
json_object_end(req->stream);
json_stream_append(req->stream, "\n\n");
plugin_send(plugin, req->stream);
req->stream = NULL;
}
void plugins_init(struct plugins *plugins, const char *dev_plugin_debug) void plugins_init(struct plugins *plugins, const char *dev_plugin_debug)
{ {
struct plugin *p; struct plugin *p;
char **cmd; char **cmd;
int stdin, stdout; int stdin, stdout;
struct timer *expired; struct timer *expired;
struct plugin_request *req; struct jsonrpc_request *req;
plugins->pending_manifests = 0; plugins->pending_manifests = 0;
uintmap_init(&plugins->pending_requests); uintmap_init(&plugins->pending_requests);
@ -969,11 +930,10 @@ void plugins_init(struct plugins *plugins, const char *dev_plugin_debug)
* write-only on p->stdout */ * write-only on p->stdout */
io_new_conn(p, stdout, plugin_stdout_conn_init, p); io_new_conn(p, stdout, plugin_stdout_conn_init, p);
io_new_conn(p, stdin, plugin_stdin_conn_init, p); io_new_conn(p, stdin, plugin_stdin_conn_init, p);
req = plugin_request_new(p, plugin_manifest_cb, p); req = plugin_request_new(p, "getmanifest", plugin_manifest_cb, p);
start_simple_request(req, "getmanifest"); jsonrpc_request_end(req);
json_array_start(req->stream, "params"); plugin_send(p, req->stream);
json_array_end(req->stream);
end_simple_request(p, req);
plugins->pending_manifests++; plugins->pending_manifests++;
/* Don't timeout if they're running a debugger. */ /* Don't timeout if they're running a debugger. */
if (debug) if (debug)
@ -1011,13 +971,11 @@ static void plugin_config(struct plugin *plugin)
{ {
struct plugin_opt *opt; struct plugin_opt *opt;
const char *name; const char *name;
struct plugin_request *req; struct jsonrpc_request *req;
struct lightningd *ld = plugin->plugins->ld; struct lightningd *ld = plugin->plugins->ld;
/* No writer since we don't flush concurrently. */ /* No writer since we don't flush concurrently. */
req = plugin_request_new(plugin, plugin_config_cb, plugin); req = plugin_request_new(plugin, "init", plugin_config_cb, plugin);
start_simple_request(req, "init");
json_object_start(req->stream, "params"); /* start of .params */
/* Add .params.options */ /* Add .params.options */
json_object_start(req->stream, "options"); json_object_start(req->stream, "options");
@ -1034,8 +992,8 @@ static void plugin_config(struct plugin *plugin)
json_add_string(req->stream, "rpc-file", ld->rpc_filename); json_add_string(req->stream, "rpc-file", ld->rpc_filename);
json_object_end(req->stream); json_object_end(req->stream);
json_object_end(req->stream); /* end of .params */ jsonrpc_request_end(req);
end_simple_request(plugin, req); plugin_send(plugin, req->stream);
} }
void plugins_config(struct plugins *plugins) void plugins_config(struct plugins *plugins)

Loading…
Cancel
Save