@ -1,5 +1,6 @@
# include <ccan/asort/asort.h>
# include <ccan/asort/asort.h>
# include <ccan/tal/str/str.h>
# include <ccan/tal/str/str.h>
# include <common/json_command.h>
# include <common/utils.h>
# include <common/utils.h>
# include <lightningd/json.h>
# include <lightningd/json.h>
# include <lightningd/jsonrpc.h>
# include <lightningd/jsonrpc.h>
@ -63,7 +64,8 @@ static bool post_check(struct command *cmd, struct param *params)
static bool parse_by_position ( struct command * cmd ,
static bool parse_by_position ( struct command * cmd ,
struct param * params ,
struct param * params ,
const char * buffer ,
const char * buffer ,
const jsmntok_t tokens [ ] )
const jsmntok_t tokens [ ] ,
bool allow_extra )
{
{
const jsmntok_t * tok = tokens + 1 ;
const jsmntok_t * tok = tokens + 1 ;
const jsmntok_t * end = json_next ( tokens ) ;
const jsmntok_t * end = json_next ( tokens ) ;
@ -79,7 +81,7 @@ static bool parse_by_position(struct command *cmd,
}
}
/* check for unexpected trailing params */
/* check for unexpected trailing params */
if ( ! cmd - > allow_unused & & tok ! = end ) {
if ( ! allow_extra & & tok ! = end ) {
command_fail ( cmd , JSONRPC2_INVALID_PARAMS ,
command_fail ( cmd , JSONRPC2_INVALID_PARAMS ,
" too many parameters: "
" too many parameters: "
" got %u, expected %zu " ,
" got %u, expected %zu " ,
@ -108,7 +110,8 @@ static struct param *find_param(struct param *params, const char *start,
static bool parse_by_name ( struct command * cmd ,
static bool parse_by_name ( struct command * cmd ,
struct param * params ,
struct param * params ,
const char * buffer ,
const char * buffer ,
const jsmntok_t tokens [ ] )
const jsmntok_t tokens [ ] ,
bool allow_extra )
{
{
const jsmntok_t * first = tokens + 1 ;
const jsmntok_t * first = tokens + 1 ;
const jsmntok_t * last = json_next ( tokens ) ;
const jsmntok_t * last = json_next ( tokens ) ;
@ -117,7 +120,7 @@ static bool parse_by_name(struct command *cmd,
struct param * p = find_param ( params , buffer + first - > start ,
struct param * p = find_param ( params , buffer + first - > start ,
first - > end - first - > start ) ;
first - > end - first - > start ) ;
if ( ! p ) {
if ( ! p ) {
if ( ! cmd - > allow_unused ) {
if ( ! allow_extra ) {
command_fail ( cmd , JSONRPC2_INVALID_PARAMS ,
command_fail ( cmd , JSONRPC2_INVALID_PARAMS ,
" unknown parameter: '%.*s' " ,
" unknown parameter: '%.*s' " ,
first - > end - first - > start ,
first - > end - first - > start ,
@ -239,7 +242,8 @@ static char *param_usage(const tal_t *ctx,
static bool param_arr ( struct command * cmd , const char * buffer ,
static bool param_arr ( struct command * cmd , const char * buffer ,
const jsmntok_t tokens [ ] ,
const jsmntok_t tokens [ ] ,
struct param * params )
struct param * params ,
bool allow_extra )
{
{
# if DEVELOPER
# if DEVELOPER
if ( ! check_params ( params ) ) {
if ( ! check_params ( params ) ) {
@ -248,9 +252,9 @@ static bool param_arr(struct command *cmd, const char *buffer,
}
}
# endif
# endif
if ( tokens - > type = = JSMN_ARRAY )
if ( tokens - > type = = JSMN_ARRAY )
return parse_by_position ( cmd , params , buffer , tokens ) ;
return parse_by_position ( cmd , params , buffer , tokens , allow_extra ) ;
else if ( tokens - > type = = JSMN_OBJECT )
else if ( tokens - > type = = JSMN_OBJECT )
return parse_by_name ( cmd , params , buffer , tokens ) ;
return parse_by_name ( cmd , params , buffer , tokens , allow_extra ) ;
command_fail ( cmd , JSONRPC2_INVALID_PARAMS ,
command_fail ( cmd , JSONRPC2_INVALID_PARAMS ,
" Expected array or object for params " ) ;
" Expected array or object for params " ) ;
@ -263,12 +267,17 @@ bool param(struct command *cmd, const char *buffer,
struct param * params = tal_arr ( cmd , struct param , 0 ) ;
struct param * params = tal_arr ( cmd , struct param , 0 ) ;
const char * name ;
const char * name ;
va_list ap ;
va_list ap ;
bool allow_extra = false ;
va_start ( ap , tokens ) ;
va_start ( ap , tokens ) ;
while ( ( name = va_arg ( ap , const char * ) ) ! = NULL ) {
while ( ( name = va_arg ( ap , const char * ) ) ! = NULL ) {
bool required = va_arg ( ap , int ) ;
bool required = va_arg ( ap , int ) ;
param_cbx cbx = va_arg ( ap , param_cbx ) ;
param_cbx cbx = va_arg ( ap , param_cbx ) ;
void * arg = va_arg ( ap , void * ) ;
void * arg = va_arg ( ap , void * ) ;
if ( streq ( name , " " ) ) {
allow_extra = true ;
continue ;
}
if ( ! param_add ( & params , name , required , cbx , arg ) ) {
if ( ! param_add ( & params , name , required , cbx , arg ) ) {
command_fail ( cmd , PARAM_DEV_ERROR ,
command_fail ( cmd , PARAM_DEV_ERROR ,
" developer error: param_add %s " , name ) ;
" developer error: param_add %s " , name ) ;
@ -278,14 +287,13 @@ bool param(struct command *cmd, const char *buffer,
}
}
va_end ( ap ) ;
va_end ( ap ) ;
if ( cmd - > mode = = CMD_USAGE ) {
if ( command_usage_only ( cmd ) ) {
cmd - > usage = param_usage ( cmd , params ) ;
command_set_usage ( cmd , param_usage ( cmd , params ) ) ;
return false ;
return false ;
}
}
/* Always return false for CMD_USAGE and CMD_CHECK, signaling the caller
/* Always return false if we're simply checking command parameters;
* to return immediately . For CMD_NORMAL , return true if all parameters
* normally this returns true if all parameters are valid . */
* are valid .
return param_arr ( cmd , buffer , tokens , params , allow_extra )
*/
& & ! command_check_only ( cmd ) ;
return param_arr ( cmd , buffer , tokens , params ) & & cmd - > mode = = CMD_NORMAL ;
}
}