mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +01:00
param: make command sinks (fail/success) return a special type.
These routines free the 'struct command': a common coding error is not to return immediately. To catch this, we make them return a non-NULL 'struct command_result *', and we're going to make the command handlers return the same (to encourage 'return command_fail(...)'-style usage). We also provide two sources for external use: 1. command_param_failed() when param() fails. 2. command_its_complicated() for some complex cases. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -7,10 +7,12 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
struct command;
|
struct command;
|
||||||
|
struct command_result;
|
||||||
|
|
||||||
/* Caller supplied this: param assumes it can call it. */
|
/* Caller supplied this: param assumes it can call it. */
|
||||||
void PRINTF_FMT(3, 4) command_fail(struct command *cmd, int code,
|
struct command_result *command_fail(struct command *cmd, int code,
|
||||||
const char *fmt, ...);
|
const char *fmt, ...)
|
||||||
|
PRINTF_FMT(3, 4);
|
||||||
|
|
||||||
/* Also caller supplied: is this invoked simply to get usage? */
|
/* Also caller supplied: is this invoked simply to get usage? */
|
||||||
bool command_usage_only(const struct command *cmd);
|
bool command_usage_only(const struct command *cmd);
|
||||||
|
|||||||
@@ -22,13 +22,15 @@ static bool check_fail(void) {
|
|||||||
|
|
||||||
struct command *cmd;
|
struct command *cmd;
|
||||||
|
|
||||||
void command_fail(struct command *cmd, int code, const char *fmt, ...)
|
struct command_result *command_fail(struct command *cmd,
|
||||||
|
int code, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
failed = true;
|
failed = true;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
fail_msg = tal_vfmt(cmd, fmt, ap);
|
fail_msg = tal_vfmt(cmd, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* AUTOGENERATED MOCKS START */
|
/* AUTOGENERATED MOCKS START */
|
||||||
|
|||||||
@@ -45,6 +45,23 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
|
||||||
|
/* Dummy structure. */
|
||||||
|
struct command_result {
|
||||||
|
char c;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct command_result param_failed, complete, pending, unknown;
|
||||||
|
|
||||||
|
struct command_result *command_param_failed(void)
|
||||||
|
{
|
||||||
|
return ¶m_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct command_result *command_its_complicated(void)
|
||||||
|
{
|
||||||
|
return &unknown;
|
||||||
|
}
|
||||||
|
|
||||||
/* This represents a JSON RPC connection. It can invoke multiple commands, but
|
/* This represents a JSON RPC connection. It can invoke multiple commands, but
|
||||||
* a command can outlive the connection, which could close any time. */
|
* a command can outlive the connection, which could close any time. */
|
||||||
struct json_connection {
|
struct json_connection {
|
||||||
@@ -383,7 +400,8 @@ static void destroy_command(struct command *cmd)
|
|||||||
list_del_from(&cmd->jcon->commands, &cmd->list);
|
list_del_from(&cmd->jcon->commands, &cmd->list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void command_raw_complete(struct command *cmd, struct json_stream *result)
|
struct command_result *command_raw_complete(struct command *cmd,
|
||||||
|
struct json_stream *result)
|
||||||
{
|
{
|
||||||
json_stream_close(result, cmd);
|
json_stream_close(result, cmd);
|
||||||
|
|
||||||
@@ -392,28 +410,31 @@ void command_raw_complete(struct command *cmd, struct json_stream *result)
|
|||||||
tal_steal(cmd->jcon, result);
|
tal_steal(cmd->jcon, result);
|
||||||
|
|
||||||
tal_free(cmd);
|
tal_free(cmd);
|
||||||
|
return &complete;
|
||||||
}
|
}
|
||||||
|
|
||||||
void command_success(struct command *cmd, struct json_stream *result)
|
struct command_result *command_success(struct command *cmd,
|
||||||
|
struct json_stream *result)
|
||||||
{
|
{
|
||||||
assert(cmd);
|
assert(cmd);
|
||||||
assert(cmd->have_json_stream);
|
assert(cmd->have_json_stream);
|
||||||
json_stream_append(result, " }\n\n");
|
json_stream_append(result, " }\n\n");
|
||||||
|
|
||||||
command_raw_complete(cmd, result);
|
return command_raw_complete(cmd, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void command_failed(struct command *cmd, struct json_stream *result)
|
struct command_result *command_failed(struct command *cmd,
|
||||||
|
struct json_stream *result)
|
||||||
{
|
{
|
||||||
assert(cmd->have_json_stream);
|
assert(cmd->have_json_stream);
|
||||||
/* Have to close error */
|
/* Have to close error */
|
||||||
json_stream_append(result, " } }\n\n");
|
json_stream_append(result, " } }\n\n");
|
||||||
|
|
||||||
command_raw_complete(cmd, result);
|
return command_raw_complete(cmd, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PRINTF_FMT(3, 4) command_fail(struct command *cmd, int code,
|
struct command_result *command_fail(struct command *cmd, int code,
|
||||||
const char *fmt, ...)
|
const char *fmt, ...)
|
||||||
{
|
{
|
||||||
const char *errmsg;
|
const char *errmsg;
|
||||||
struct json_stream *r;
|
struct json_stream *r;
|
||||||
@@ -424,13 +445,14 @@ void PRINTF_FMT(3, 4) command_fail(struct command *cmd, int code,
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
r = json_stream_fail_nodata(cmd, code, errmsg);
|
r = json_stream_fail_nodata(cmd, code, errmsg);
|
||||||
|
|
||||||
command_failed(cmd, r);
|
return command_failed(cmd, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
void command_still_pending(struct command *cmd)
|
struct command_result *command_still_pending(struct command *cmd)
|
||||||
{
|
{
|
||||||
notleak_with_children(cmd);
|
notleak_with_children(cmd);
|
||||||
cmd->pending = true;
|
cmd->pending = true;
|
||||||
|
return &pending;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void json_command_malformed(struct json_connection *jcon,
|
static void json_command_malformed(struct json_connection *jcon,
|
||||||
|
|||||||
@@ -41,6 +41,12 @@ struct command {
|
|||||||
bool have_json_stream;
|
bool have_json_stream;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dummy structure to make sure you call one of
|
||||||
|
* command_success / command_failed / command_still_pending.
|
||||||
|
*/
|
||||||
|
struct command_result;
|
||||||
|
|
||||||
struct json_command {
|
struct json_command {
|
||||||
const char *name;
|
const char *name;
|
||||||
void (*dispatch)(struct command *,
|
void (*dispatch)(struct command *,
|
||||||
@@ -87,15 +93,37 @@ struct json_stream *json_stream_fail_nodata(struct command *cmd,
|
|||||||
const char *errmsg);
|
const char *errmsg);
|
||||||
|
|
||||||
struct json_stream *null_response(struct command *cmd);
|
struct json_stream *null_response(struct command *cmd);
|
||||||
void command_success(struct command *cmd, struct json_stream *response);
|
|
||||||
void command_failed(struct command *cmd, struct json_stream *result);
|
/* These returned values are never NULL. */
|
||||||
|
struct command_result *command_success(struct command *cmd,
|
||||||
|
struct json_stream *response);
|
||||||
|
struct command_result *command_failed(struct command *cmd,
|
||||||
|
struct json_stream *result);
|
||||||
|
|
||||||
/* Mainly for documentation, that we plan to close this later. */
|
/* Mainly for documentation, that we plan to close this later. */
|
||||||
void command_still_pending(struct command *cmd);
|
struct command_result *command_still_pending(struct command *cmd);
|
||||||
|
|
||||||
/* For low-level JSON stream access: */
|
/* For low-level JSON stream access: */
|
||||||
struct json_stream *json_stream_raw_for_cmd(struct command *cmd);
|
struct json_stream *json_stream_raw_for_cmd(struct command *cmd);
|
||||||
void command_raw_complete(struct command *cmd, struct json_stream *result);
|
struct command_result *command_raw_complete(struct command *cmd,
|
||||||
|
struct json_stream *result);
|
||||||
|
|
||||||
|
/* To return if param() fails. */
|
||||||
|
extern struct command_result *command_param_failed(void);
|
||||||
|
|
||||||
|
/* Wrapper for pending commands (ignores return) */
|
||||||
|
static inline void was_pending(const struct command_result *res)
|
||||||
|
{
|
||||||
|
assert(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Transition for ignoring command */
|
||||||
|
static inline void fixme_ignore(const struct command_result *res)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: For the few cases where return value is indeterminate */
|
||||||
|
struct command_result *command_its_complicated(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new jsonrpc to wrap all related information.
|
* Create a new jsonrpc to wrap all related information.
|
||||||
|
|||||||
@@ -41,17 +41,20 @@ bool channel_tell_funding_locked(struct lightningd *ld UNNEEDED,
|
|||||||
u32 depth UNNEEDED)
|
u32 depth UNNEEDED)
|
||||||
{ fprintf(stderr, "channel_tell_funding_locked called!\n"); abort(); }
|
{ fprintf(stderr, "channel_tell_funding_locked called!\n"); abort(); }
|
||||||
/* Generated stub for command_fail */
|
/* Generated stub for command_fail */
|
||||||
void command_fail(struct command *cmd UNNEEDED, int code UNNEEDED,
|
struct command_result *command_fail(struct command *cmd UNNEEDED, int code UNNEEDED,
|
||||||
const char *fmt UNNEEDED, ...)
|
const char *fmt UNNEEDED, ...)
|
||||||
|
|
||||||
{ fprintf(stderr, "command_fail called!\n"); abort(); }
|
{ fprintf(stderr, "command_fail called!\n"); abort(); }
|
||||||
/* Generated stub for command_failed */
|
/* Generated stub for command_failed */
|
||||||
void command_failed(struct command *cmd UNNEEDED, struct json_stream *result UNNEEDED)
|
struct command_result *command_failed(struct command *cmd UNNEEDED,
|
||||||
|
struct json_stream *result UNNEEDED)
|
||||||
{ fprintf(stderr, "command_failed called!\n"); abort(); }
|
{ fprintf(stderr, "command_failed called!\n"); abort(); }
|
||||||
/* Generated stub for command_still_pending */
|
/* Generated stub for command_still_pending */
|
||||||
void command_still_pending(struct command *cmd UNNEEDED)
|
struct command_result *command_still_pending(struct command *cmd UNNEEDED)
|
||||||
{ fprintf(stderr, "command_still_pending called!\n"); abort(); }
|
{ fprintf(stderr, "command_still_pending called!\n"); abort(); }
|
||||||
/* Generated stub for command_success */
|
/* Generated stub for command_success */
|
||||||
void command_success(struct command *cmd UNNEEDED, struct json_stream *response UNNEEDED)
|
struct command_result *command_success(struct command *cmd UNNEEDED,
|
||||||
|
struct json_stream *response UNNEEDED)
|
||||||
{ fprintf(stderr, "command_success called!\n"); abort(); }
|
{ fprintf(stderr, "command_success called!\n"); abort(); }
|
||||||
/* Generated stub for connect_succeeded */
|
/* Generated stub for connect_succeeded */
|
||||||
void connect_succeeded(struct lightningd *ld UNNEEDED, const struct pubkey *id UNNEEDED)
|
void connect_succeeded(struct lightningd *ld UNNEEDED, const struct pubkey *id UNNEEDED)
|
||||||
|
|||||||
@@ -51,14 +51,16 @@ bool channel_tell_funding_locked(struct lightningd *ld UNNEEDED,
|
|||||||
u32 depth UNNEEDED)
|
u32 depth UNNEEDED)
|
||||||
{ fprintf(stderr, "channel_tell_funding_locked called!\n"); abort(); }
|
{ fprintf(stderr, "channel_tell_funding_locked called!\n"); abort(); }
|
||||||
/* Generated stub for command_fail */
|
/* Generated stub for command_fail */
|
||||||
void command_fail(struct command *cmd UNNEEDED, int code UNNEEDED,
|
struct command_result *command_fail(struct command *cmd UNNEEDED, int code UNNEEDED,
|
||||||
const char *fmt UNNEEDED, ...)
|
const char *fmt UNNEEDED, ...)
|
||||||
|
|
||||||
{ fprintf(stderr, "command_fail called!\n"); abort(); }
|
{ fprintf(stderr, "command_fail called!\n"); abort(); }
|
||||||
/* Generated stub for command_still_pending */
|
/* Generated stub for command_still_pending */
|
||||||
void command_still_pending(struct command *cmd UNNEEDED)
|
struct command_result *command_still_pending(struct command *cmd UNNEEDED)
|
||||||
{ fprintf(stderr, "command_still_pending called!\n"); abort(); }
|
{ fprintf(stderr, "command_still_pending called!\n"); abort(); }
|
||||||
/* Generated stub for command_success */
|
/* Generated stub for command_success */
|
||||||
void command_success(struct command *cmd UNNEEDED, struct json_stream *response UNNEEDED)
|
struct command_result *command_success(struct command *cmd UNNEEDED,
|
||||||
|
struct json_stream *response UNNEEDED)
|
||||||
{ fprintf(stderr, "command_success called!\n"); abort(); }
|
{ fprintf(stderr, "command_success called!\n"); abort(); }
|
||||||
/* Generated stub for connect_succeeded */
|
/* Generated stub for connect_succeeded */
|
||||||
void connect_succeeded(struct lightningd *ld UNNEEDED, const struct pubkey *id UNNEEDED)
|
void connect_succeeded(struct lightningd *ld UNNEEDED, const struct pubkey *id UNNEEDED)
|
||||||
@@ -264,6 +266,12 @@ bool json_tok_bool(struct command *cmd UNNEEDED, const char *name UNNEEDED,
|
|||||||
bool json_tok_channel_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
|
bool json_tok_channel_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
|
||||||
struct channel_id *cid UNNEEDED)
|
struct channel_id *cid UNNEEDED)
|
||||||
{ fprintf(stderr, "json_tok_channel_id called!\n"); abort(); }
|
{ fprintf(stderr, "json_tok_channel_id called!\n"); abort(); }
|
||||||
|
/* Generated stub for json_tok_full */
|
||||||
|
const char *json_tok_full(const char *buffer UNNEEDED, const jsmntok_t *t UNNEEDED)
|
||||||
|
{ fprintf(stderr, "json_tok_full called!\n"); abort(); }
|
||||||
|
/* Generated stub for json_tok_full_len */
|
||||||
|
int json_tok_full_len(const jsmntok_t *t UNNEEDED)
|
||||||
|
{ fprintf(stderr, "json_tok_full_len called!\n"); abort(); }
|
||||||
/* Generated stub for json_tok_loglevel */
|
/* Generated stub for json_tok_loglevel */
|
||||||
bool json_tok_loglevel(struct command *cmd UNNEEDED, const char *name UNNEEDED,
|
bool json_tok_loglevel(struct command *cmd UNNEEDED, const char *name UNNEEDED,
|
||||||
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
|
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
|
||||||
|
|||||||
Reference in New Issue
Block a user