jsonrpc: tolerate null json value for parameters in json-rpc call
Rust lang has notion of empty value `()` which is translated to json null value using serialization library like serde. Thus it means that jsonrpc methods having no parameters translate to parameters with null value (as opposed to a request without parameter member as it is done now in spdk). This change handles null parameter gracefully instead of returning an error - improving interoperability with such clients. Signed-off-by: Jan Kryl <jan.kryl@mayadata.io> Change-Id: I8c3cc5613582aebb10ac6eaee3ac4e6538aaa0b1 Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/463171 Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
parent
490b06e24b
commit
59339feac3
@ -62,6 +62,7 @@ static void
|
|||||||
parse_single_request(struct spdk_jsonrpc_request *request, struct spdk_json_val *values)
|
parse_single_request(struct spdk_jsonrpc_request *request, struct spdk_json_val *values)
|
||||||
{
|
{
|
||||||
struct jsonrpc_request req = {};
|
struct jsonrpc_request req = {};
|
||||||
|
const struct spdk_json_val *params = NULL;
|
||||||
|
|
||||||
if (spdk_json_decode_object(values, jsonrpc_request_decoders,
|
if (spdk_json_decode_object(values, jsonrpc_request_decoders,
|
||||||
SPDK_COUNTOF(jsonrpc_request_decoders),
|
SPDK_COUNTOF(jsonrpc_request_decoders),
|
||||||
@ -89,13 +90,17 @@ parse_single_request(struct spdk_jsonrpc_request *request, struct spdk_json_val
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (req.params) {
|
if (req.params) {
|
||||||
if (req.params->type != SPDK_JSON_VAL_ARRAY_BEGIN &&
|
/* null json value is as if there were no parameters */
|
||||||
req.params->type != SPDK_JSON_VAL_OBJECT_BEGIN) {
|
if (req.params->type != SPDK_JSON_VAL_NULL) {
|
||||||
goto invalid;
|
if (req.params->type != SPDK_JSON_VAL_ARRAY_BEGIN &&
|
||||||
|
req.params->type != SPDK_JSON_VAL_OBJECT_BEGIN) {
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
params = req.params;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spdk_jsonrpc_server_handle_request(request, req.method, req.params);
|
spdk_jsonrpc_server_handle_request(request, req.method, params);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
invalid:
|
invalid:
|
||||||
|
@ -141,6 +141,61 @@ out:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
spdk_jsonrpc_client_check_null_params_method(struct spdk_jsonrpc_client *client)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
bool res = false;
|
||||||
|
struct spdk_jsonrpc_client_response *json_resp = NULL;
|
||||||
|
struct spdk_json_write_ctx *w;
|
||||||
|
struct spdk_jsonrpc_client_request *request;
|
||||||
|
|
||||||
|
request = spdk_jsonrpc_client_create_request();
|
||||||
|
if (request == NULL) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
w = spdk_jsonrpc_begin_request(request, 1, "test_null_params");
|
||||||
|
spdk_json_write_name(w, "params");
|
||||||
|
spdk_json_write_null(w);
|
||||||
|
spdk_jsonrpc_end_request(request, w);
|
||||||
|
spdk_jsonrpc_client_send_request(client, request);
|
||||||
|
|
||||||
|
rc = _rpc_client_wait_for_response(client);
|
||||||
|
if (rc <= 0) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_resp = spdk_jsonrpc_client_get_response(client);
|
||||||
|
if (json_resp == NULL) {
|
||||||
|
SPDK_ERRLOG("spdk_jsonrpc_client_get_response() failed\n");
|
||||||
|
rc = -1;
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for error response */
|
||||||
|
if (json_resp->error != NULL) {
|
||||||
|
SPDK_ERRLOG("Unexpected error response\n");
|
||||||
|
rc = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(json_resp->result);
|
||||||
|
|
||||||
|
if (spdk_json_decode_bool(json_resp->result, &res) != 0 || res != true) {
|
||||||
|
SPDK_ERRLOG("Response is not a boolean or it is not 'true'\n");
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
} else {
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
spdk_jsonrpc_client_free_response(json_resp);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rpc_test_method_startup(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
|
rpc_test_method_startup(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
|
||||||
{
|
{
|
||||||
@ -157,6 +212,24 @@ rpc_test_method_runtime(struct spdk_jsonrpc_request *request, const struct spdk_
|
|||||||
}
|
}
|
||||||
SPDK_RPC_REGISTER("test_method_runtime", rpc_test_method_runtime, SPDK_RPC_RUNTIME)
|
SPDK_RPC_REGISTER("test_method_runtime", rpc_test_method_runtime, SPDK_RPC_RUNTIME)
|
||||||
|
|
||||||
|
static void
|
||||||
|
rpc_test_method_null_params(struct spdk_jsonrpc_request *request,
|
||||||
|
const struct spdk_json_val *params)
|
||||||
|
{
|
||||||
|
struct spdk_json_write_ctx *w;
|
||||||
|
|
||||||
|
if (params != NULL) {
|
||||||
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||||
|
"rpc_test_method_null_params(): Parameters are not NULL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
w = spdk_jsonrpc_begin_result(request);
|
||||||
|
assert(w != NULL);
|
||||||
|
spdk_json_write_bool(w, true);
|
||||||
|
spdk_jsonrpc_end_result(request, w);
|
||||||
|
}
|
||||||
|
SPDK_RPC_REGISTER("test_null_params", rpc_test_method_null_params, SPDK_RPC_RUNTIME)
|
||||||
|
|
||||||
static bool g_conn_close_detected;
|
static bool g_conn_close_detected;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -325,6 +398,12 @@ rpc_client_th(void *arg)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = spdk_jsonrpc_client_check_null_params_method(client);
|
||||||
|
if (rc) {
|
||||||
|
fprintf(stderr, "spdk_jsonrpc_client_null_params_method() failed: rc=%d errno=%d\n", rc, errno);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
rc = spdk_jsonrpc_client_hook_conn_close(client);
|
rc = spdk_jsonrpc_client_hook_conn_close(client);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
fprintf(stderr, "spdk_jsonrpc_client_hook_conn_close() failed: rc=%d errno=%d\n", rc, errno);
|
fprintf(stderr, "spdk_jsonrpc_client_hook_conn_close() failed: rc=%d errno=%d\n", rc, errno);
|
||||||
|
Loading…
Reference in New Issue
Block a user