mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +01:00
libplugin: datastore helpers.
Plugins are supposed to store their data in the datastore, and commando does so: let's make it easier for them by providing convenience APIs. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -490,20 +490,18 @@ static struct json_out *start_json_request(const tal_t *ctx,
|
|||||||
return jout;
|
return jout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Synchronous routine to send command and extract fields from response */
|
static const char *rpc_scan_core(const tal_t *ctx,
|
||||||
void rpc_scan(struct plugin *plugin,
|
struct plugin *plugin,
|
||||||
const char *method,
|
const char *method,
|
||||||
const struct json_out *params TAKES,
|
const struct json_out *params TAKES,
|
||||||
const char *guide,
|
const char *guide,
|
||||||
...)
|
va_list ap)
|
||||||
{
|
{
|
||||||
bool error;
|
bool error;
|
||||||
const char *err;
|
|
||||||
const jsmntok_t *contents;
|
const jsmntok_t *contents;
|
||||||
int reqlen;
|
int reqlen;
|
||||||
const char *p;
|
const char *p;
|
||||||
struct json_out *jout;
|
struct json_out *jout;
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
jout = start_json_request(tmpctx, 0, method, params);
|
jout = start_json_request(tmpctx, 0, method, params);
|
||||||
finish_and_send_json(plugin->rpc_conn->fd, jout);
|
finish_and_send_json(plugin->rpc_conn->fd, jout);
|
||||||
@@ -514,15 +512,116 @@ void rpc_scan(struct plugin *plugin,
|
|||||||
method, reqlen, membuf_elems(&plugin->rpc_conn->mb));
|
method, reqlen, membuf_elems(&plugin->rpc_conn->mb));
|
||||||
|
|
||||||
p = membuf_consume(&plugin->rpc_conn->mb, reqlen);
|
p = membuf_consume(&plugin->rpc_conn->mb, reqlen);
|
||||||
|
return json_scanv(ctx, p, contents, guide, ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Synchronous routine to send command and extract fields from response */
|
||||||
|
void rpc_scan(struct plugin *plugin,
|
||||||
|
const char *method,
|
||||||
|
const struct json_out *params TAKES,
|
||||||
|
const char *guide,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
const char *err;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, guide);
|
va_start(ap, guide);
|
||||||
err = json_scanv(tmpctx, p, contents, guide, ap);
|
err = rpc_scan_core(tmpctx, plugin, method, params, guide, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
plugin_err(plugin, "Could not parse %s in reply to %s: %s: '%.*s'",
|
plugin_err(plugin, "Could not parse %s in reply to %s: %s",
|
||||||
guide, method, err,
|
guide, method, err);
|
||||||
reqlen, membuf_elems(&plugin->rpc_conn->mb));
|
}
|
||||||
|
|
||||||
|
static void json_add_keypath(struct json_out *jout, const char *fieldname, const char *path)
|
||||||
|
{
|
||||||
|
char **parts = tal_strsplit(tmpctx, path, "/", STR_EMPTY_OK);
|
||||||
|
|
||||||
|
json_out_start(jout, fieldname, '[');
|
||||||
|
for (size_t i = 0; parts[i]; parts++)
|
||||||
|
json_out_addstr(jout, NULL, parts[i]);
|
||||||
|
json_out_end(jout, ']');
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool rpc_scan_datastore(struct plugin *plugin,
|
||||||
|
const char *path,
|
||||||
|
const char *hex_or_string,
|
||||||
|
va_list ap)
|
||||||
|
{
|
||||||
|
const char *guide;
|
||||||
|
struct json_out *params;
|
||||||
|
const char *err;
|
||||||
|
|
||||||
|
params = json_out_new(NULL);
|
||||||
|
json_out_start(params, NULL, '{');
|
||||||
|
json_add_keypath(params, "key", path);
|
||||||
|
json_out_end(params, '}');
|
||||||
|
json_out_finished(params);
|
||||||
|
|
||||||
|
guide = tal_fmt(tmpctx, "{datastore:[0:{%s:%%}]}", hex_or_string);
|
||||||
|
/* FIXME: Could be some other error, but that's probably a caller bug! */
|
||||||
|
err = rpc_scan_core(tmpctx, plugin, "listdatastore", take(params), guide, ap);
|
||||||
|
if (!err)
|
||||||
|
return true;
|
||||||
|
plugin_log(plugin, LOG_DBG, "listdatastore error %s: %s", path, err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rpc_scan_datastore_str(struct plugin *plugin,
|
||||||
|
const char *path,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, path);
|
||||||
|
ret = rpc_scan_datastore(plugin, path, "string", ap);
|
||||||
|
va_end(ap);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This variant scans the hex encoding, not the string */
|
||||||
|
bool rpc_scan_datastore_hex(struct plugin *plugin,
|
||||||
|
const char *path,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, path);
|
||||||
|
ret = rpc_scan_datastore(plugin, path, "hex", ap);
|
||||||
|
va_end(ap);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct command_result *jsonrpc_set_datastore_(struct plugin *plugin,
|
||||||
|
struct command *cmd,
|
||||||
|
const char *path,
|
||||||
|
const void *value,
|
||||||
|
bool value_is_string,
|
||||||
|
const char *mode,
|
||||||
|
struct command_result *(*cb)(struct command *command,
|
||||||
|
const char *buf,
|
||||||
|
const jsmntok_t *result,
|
||||||
|
void *arg),
|
||||||
|
struct command_result *(*errcb)(struct command *command,
|
||||||
|
const char *buf,
|
||||||
|
const jsmntok_t *result,
|
||||||
|
void *arg),
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
struct out_req *req;
|
||||||
|
|
||||||
|
req = jsonrpc_request_start(plugin, cmd, "datastore", cb, errcb, arg);
|
||||||
|
|
||||||
|
json_add_keypath(req->js->jout, "key", path);
|
||||||
|
if (value_is_string)
|
||||||
|
json_add_string(req->js, "string", value);
|
||||||
|
else
|
||||||
|
json_add_hex_talarr(req->js, "hex", value);
|
||||||
|
json_add_string(req->js, "mode", mode);
|
||||||
|
return send_outreq(plugin, req);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_rpc_reply(struct plugin *plugin, const jsmntok_t *toks)
|
static void handle_rpc_reply(struct plugin *plugin, const jsmntok_t *toks)
|
||||||
|
|||||||
@@ -160,6 +160,51 @@ struct json_stream *jsonrpc_stream_fail_data(struct command *cmd,
|
|||||||
int code,
|
int code,
|
||||||
const char *err);
|
const char *err);
|
||||||
|
|
||||||
|
/* Helper to jsonrpc_request_start() and send_outreq() to update datastore. */
|
||||||
|
struct command_result *jsonrpc_set_datastore_(struct plugin *plugin,
|
||||||
|
struct command *cmd,
|
||||||
|
const char *path,
|
||||||
|
const void *value,
|
||||||
|
bool value_is_string,
|
||||||
|
const char *mode,
|
||||||
|
struct command_result *(*cb)(struct command *command,
|
||||||
|
const char *buf,
|
||||||
|
const jsmntok_t *result,
|
||||||
|
void *arg),
|
||||||
|
struct command_result *(*errcb)(struct command *command,
|
||||||
|
const char *buf,
|
||||||
|
const jsmntok_t *result,
|
||||||
|
void *arg),
|
||||||
|
void *arg);
|
||||||
|
|
||||||
|
#define jsonrpc_set_datastore_string(plugin, cmd, path, str, mode, cb, errcb, arg) \
|
||||||
|
jsonrpc_set_datastore_((plugin), (cmd), (path), (str), true, (mode), \
|
||||||
|
typesafe_cb_preargs(struct command_result *, void *, \
|
||||||
|
(cb), (arg), \
|
||||||
|
struct command *command, \
|
||||||
|
const char *buf, \
|
||||||
|
const jsmntok_t *result), \
|
||||||
|
typesafe_cb_preargs(struct command_result *, void *, \
|
||||||
|
(errcb), (arg), \
|
||||||
|
struct command *command, \
|
||||||
|
const char *buf, \
|
||||||
|
const jsmntok_t *result), \
|
||||||
|
(arg))
|
||||||
|
|
||||||
|
#define jsonrpc_set_datastore_binary(plugin, cmd, path, tal_ptr, mode, cb, errcb, arg) \
|
||||||
|
jsonrpc_set_datastore_((plugin), (cmd), (path), (tal_ptr), false, (mode), \
|
||||||
|
typesafe_cb_preargs(struct command_result *, void *, \
|
||||||
|
(cb), (arg), \
|
||||||
|
struct command *command, \
|
||||||
|
const char *buf, \
|
||||||
|
const jsmntok_t *result), \
|
||||||
|
typesafe_cb_preargs(struct command_result *, void *, \
|
||||||
|
(errcb), (arg), \
|
||||||
|
struct command *command, \
|
||||||
|
const char *buf, \
|
||||||
|
const jsmntok_t *result), \
|
||||||
|
(arg))
|
||||||
|
|
||||||
/* This command is finished, here's the response (the content of the
|
/* This command is finished, here's the response (the content of the
|
||||||
* "result" or "error" field) */
|
* "result" or "error" field) */
|
||||||
WARN_UNUSED_RESULT
|
WARN_UNUSED_RESULT
|
||||||
@@ -220,6 +265,19 @@ void rpc_scan(struct plugin *plugin,
|
|||||||
const char *guide,
|
const char *guide,
|
||||||
...);
|
...);
|
||||||
|
|
||||||
|
/* Helper to scan datastore: can only be used in init callback. *
|
||||||
|
Returns false if field does not exist. * path is /-separated. Final
|
||||||
|
arg is JSON_SCAN or JSON_SCAN_TAL.
|
||||||
|
*/
|
||||||
|
bool rpc_scan_datastore_str(struct plugin *plugin,
|
||||||
|
const char *path,
|
||||||
|
...);
|
||||||
|
/* This variant scans the hex encoding, not the string */
|
||||||
|
bool rpc_scan_datastore_hex(struct plugin *plugin,
|
||||||
|
const char *path,
|
||||||
|
...);
|
||||||
|
|
||||||
|
|
||||||
/* Send an async rpc request to lightningd. */
|
/* Send an async rpc request to lightningd. */
|
||||||
struct command_result *send_outreq(struct plugin *plugin,
|
struct command_result *send_outreq(struct plugin *plugin,
|
||||||
const struct out_req *req);
|
const struct out_req *req);
|
||||||
|
|||||||
Reference in New Issue
Block a user