diff options
Diffstat (limited to '')
| -rw-r--r-- | src/json_rpc.c | 568 |
1 files changed, 283 insertions, 285 deletions
diff --git a/src/json_rpc.c b/src/json_rpc.c index 2ab4624..6bf9fc5 100644 --- a/src/json_rpc.c +++ b/src/json_rpc.c @@ -18,11 +18,11 @@ #include <string.h> struct jsonrpc_request { - struct json_object* impl; + struct json_object* impl; }; struct jsonrpc_response { - struct json_object* impl; + struct json_object* impl; }; static const char* const jsonrpc_key_version = "jsonrpc"; @@ -33,103 +33,101 @@ static const char* const jsonrpc_key_params = "params"; static const char* const jsonrpc_value_version = "2.0"; static int jsonrpc_check_version(struct json_object* obj) { - const char* key = jsonrpc_key_version; - const char* version = NULL; + const char* key = jsonrpc_key_version; + const char* version = NULL; - int ret = libjson_get_string(obj, key, &version); - if (ret < 0) - return ret; + int ret = libjson_get_string(obj, key, &version); + if (ret < 0) + return ret; - if (strcmp(version, jsonrpc_value_version)) { - log_err("JSON-RPC: invalid '%s' value: %s\n", key, version); - return -1; - } + if (strcmp(version, jsonrpc_value_version)) { + log_err("JSON-RPC: invalid '%s' value: %s\n", key, version); + return -1; + } - return 0; + return 0; } static int jsonrpc_set_version(struct json_object* obj) { - return libjson_set_string_const_key(obj, jsonrpc_key_version, jsonrpc_value_version); + return libjson_set_string_const_key(obj, jsonrpc_key_version, jsonrpc_value_version); } static _Atomic int jsonrpc_id_counter = 1; int jsonrpc_generate_request_id(void) { - return jsonrpc_id_counter++; + return jsonrpc_id_counter++; } static int jsonrpc_check_id_type(struct json_object* id) { - if (!json_object_is_type(id, json_type_string) && !json_object_is_type(id, json_type_int)) { - log_err("JSON-RPC: key '%s' must be either an integer or a string\n", - jsonrpc_key_id); - return -1; - } - return 0; + if (!json_object_is_type(id, json_type_string) && !json_object_is_type(id, json_type_int)) { + log_err("JSON-RPC: key '%s' must be either an integer or a string\n", jsonrpc_key_id); + return -1; + } + return 0; } static int jsonrpc_check_id(struct json_object* obj, int required) { - const char* key = jsonrpc_key_id; + const char* key = jsonrpc_key_id; - if (!libjson_has(obj, key)) { - if (!required) - return 0; - log_err("JSON-RPC: key is missing: %s\n", key); - return -1; - } + if (!libjson_has(obj, key)) { + if (!required) + return 0; + log_err("JSON-RPC: key is missing: %s\n", key); + return -1; + } - struct json_object* id = NULL; + struct json_object* id = NULL; - int ret = libjson_get(obj, key, &id); - if (ret < 0) - return ret; - return jsonrpc_check_id_type(id); + int ret = libjson_get(obj, key, &id); + if (ret < 0) + return ret; + return jsonrpc_check_id_type(id); } static int jsonrpc_set_id(struct json_object* obj, int id) { - return libjson_set_int_const_key(obj, jsonrpc_key_id, id); + return libjson_set_int_const_key(obj, jsonrpc_key_id, id); } static int jsonrpc_check_method(struct json_object* obj) { - const char* key = jsonrpc_key_method; - const char* method = NULL; - return libjson_get_string(obj, key, &method); + const char* key = jsonrpc_key_method; + const char* method = NULL; + return libjson_get_string(obj, key, &method); } static int jsonrpc_set_method(struct json_object* obj, const char* method) { - return libjson_set_string_const_key(obj, jsonrpc_key_method, method); + return libjson_set_string_const_key(obj, jsonrpc_key_method, method); } static int jsonrpc_check_params_type(struct json_object* params) { - if (!json_object_is_type(params, json_type_object) && - !json_object_is_type(params, json_type_array)) { - log_err("JSON-RPC: key '%s' must be either an object or an array\n", - jsonrpc_key_params); - return -1; - } - return 0; + if (!json_object_is_type(params, json_type_object) && + !json_object_is_type(params, json_type_array)) { + log_err("JSON-RPC: key '%s' must be either an object or an array\n", jsonrpc_key_params); + return -1; + } + return 0; } static int jsonrpc_check_params(struct json_object* obj) { - const char* key = jsonrpc_key_params; + const char* key = jsonrpc_key_params; - if (!libjson_has(obj, key)) - return 0; + if (!libjson_has(obj, key)) + return 0; - struct json_object* params = NULL; + struct json_object* params = NULL; - int ret = libjson_get(obj, key, ¶ms); - if (ret < 0) - return ret; - return jsonrpc_check_params_type(params); + int ret = libjson_get(obj, key, ¶ms); + if (ret < 0) + return ret; + return jsonrpc_check_params_type(params); } static int jsonrpc_set_params(struct json_object* obj, struct json_object* params) { - const char* key = jsonrpc_key_params; + const char* key = jsonrpc_key_params; - int ret = jsonrpc_check_params_type(params); - if (ret < 0) - return ret; - return libjson_set_const_key(obj, key, params); + int ret = jsonrpc_check_params_type(params); + if (ret < 0) + return ret; + return libjson_set_const_key(obj, key, params); } static const char* const jsonrpc_key_result = "result"; @@ -139,387 +137,387 @@ static const char* const jsonrpc_key_code = "code"; static const char* const jsonrpc_key_message = "message"; static int jsonrpc_check_error(struct json_object* obj) { - const char* key = jsonrpc_key_error; - struct json_object* error = NULL; + const char* key = jsonrpc_key_error; + struct json_object* error = NULL; - int ret = libjson_get(obj, key, &error); - if (ret < 0) - return ret; + int ret = libjson_get(obj, key, &error); + if (ret < 0) + return ret; - int64_t code = -1; + int64_t code = -1; - ret = libjson_get_int(error, jsonrpc_key_code, &code); - if (ret < 0) { - log_err("JSON-RPC: key is missing or not an integer: %s\n", jsonrpc_key_code); - return -1; - } + ret = libjson_get_int(error, jsonrpc_key_code, &code); + if (ret < 0) { + log_err("JSON-RPC: key is missing or not an integer: %s\n", jsonrpc_key_code); + return -1; + } - const char* message = NULL; + const char* message = NULL; - ret = libjson_get_string(error, jsonrpc_key_message, &message); - if (ret < 0) { - log_err("JSON-RPC: key is missing or not a string: %s\n", jsonrpc_key_message); - return -1; - } + ret = libjson_get_string(error, jsonrpc_key_message, &message); + if (ret < 0) { + log_err("JSON-RPC: key is missing or not a string: %s\n", jsonrpc_key_message); + return -1; + } - return ret; + return ret; } static int jsonrpc_check_result_or_error(struct json_object* obj) { - const char* key_result = jsonrpc_key_result; - const char* key_error = jsonrpc_key_error; + const char* key_result = jsonrpc_key_result; + const char* key_error = jsonrpc_key_error; - if (!libjson_has(obj, key_result) && !libjson_has(obj, key_error)) { - log_err("JSON-RPC: either '%s' or '%s' must be present\n", key_result, key_error); - return -1; - } + if (!libjson_has(obj, key_result) && !libjson_has(obj, key_error)) { + log_err("JSON-RPC: either '%s' or '%s' must be present\n", key_result, key_error); + return -1; + } - if (libjson_has(obj, key_result)) - return 0; + if (libjson_has(obj, key_result)) + return 0; - return jsonrpc_check_error(obj); + return jsonrpc_check_error(obj); } static int jsonrpc_request_create_internal(struct jsonrpc_request** _request, int* id, const char* method, struct json_object* params) { - int ret = 0; + int ret = 0; - struct jsonrpc_request* request = malloc(sizeof(struct jsonrpc_request)); - if (!request) { - log_errno("malloc"); - ret = -1; - goto exit; - } + struct jsonrpc_request* request = malloc(sizeof(struct jsonrpc_request)); + if (!request) { + log_errno("malloc"); + ret = -1; + goto exit; + } - ret = libjson_new_object(&request->impl); - if (ret < 0) - goto free; + ret = libjson_new_object(&request->impl); + if (ret < 0) + goto free; - ret = jsonrpc_set_version(request->impl); - if (ret < 0) - goto free_impl; + ret = jsonrpc_set_version(request->impl); + if (ret < 0) + goto free_impl; - if (id) { - ret = jsonrpc_set_id(request->impl, *id); - if (ret < 0) - goto free_impl; - } + if (id) { + ret = jsonrpc_set_id(request->impl, *id); + if (ret < 0) + goto free_impl; + } - ret = jsonrpc_set_method(request->impl, method); - if (ret < 0) - goto free_impl; + ret = jsonrpc_set_method(request->impl, method); + if (ret < 0) + goto free_impl; - if (params) { - ret = jsonrpc_set_params(request->impl, params); - if (ret < 0) - goto free_impl; - } + if (params) { + ret = jsonrpc_set_params(request->impl, params); + if (ret < 0) + goto free_impl; + } - *_request = request; - goto exit; + *_request = request; + goto exit; free_impl: - libjson_free(request->impl); + libjson_free(request->impl); free: - free(request); + free(request); exit: - return ret; + return ret; } int jsonrpc_request_create(struct jsonrpc_request** _request, int id, const char* method, struct json_object* params) { - return jsonrpc_request_create_internal(_request, &id, method, params); + return jsonrpc_request_create_internal(_request, &id, method, params); } void jsonrpc_request_destroy(struct jsonrpc_request* request) { - libjson_free(request->impl); - free(request); + libjson_free(request->impl); + free(request); } int jsonrpc_notification_create(struct jsonrpc_request** _request, const char* method, struct json_object* params) { - return jsonrpc_request_create_internal(_request, NULL, method, params); + return jsonrpc_request_create_internal(_request, NULL, method, params); } int jsonrpc_request_is_notification(const struct jsonrpc_request* request) { - return !libjson_has(request->impl, jsonrpc_key_id); + return !libjson_has(request->impl, jsonrpc_key_id); } static int jsonrpc_request_from_json(struct jsonrpc_request** _request, struct json_object* impl) { - int ret = 0; + int ret = 0; - ret = jsonrpc_check_version(impl); - if (ret < 0) - return ret; - ret = jsonrpc_check_id(impl, 0); - if (ret < 0) - return ret; - ret = jsonrpc_check_method(impl); - if (ret < 0) - return ret; - ret = jsonrpc_check_params(impl); - if (ret < 0) - return ret; + ret = jsonrpc_check_version(impl); + if (ret < 0) + return ret; + ret = jsonrpc_check_id(impl, 0); + if (ret < 0) + return ret; + ret = jsonrpc_check_method(impl); + if (ret < 0) + return ret; + ret = jsonrpc_check_params(impl); + if (ret < 0) + return ret; - struct jsonrpc_request* request = malloc(sizeof(struct jsonrpc_request)); - if (!request) { - log_errno("malloc"); - return -1; - } - request->impl = impl; + struct jsonrpc_request* request = malloc(sizeof(struct jsonrpc_request)); + if (!request) { + log_errno("malloc"); + return -1; + } + request->impl = impl; - *_request = request; - return ret; + *_request = request; + return ret; } int jsonrpc_request_send(const struct jsonrpc_request* request, int fd) { - return libjson_send(request->impl, fd); + return libjson_send(request->impl, fd); } int jsonrpc_request_recv(struct jsonrpc_request** request, int fd) { - struct json_object* impl = libjson_recv(fd); - if (!impl) { - log_err("JSON-RPC: failed to receive request\n"); - return -1; - } + struct json_object* impl = libjson_recv(fd); + if (!impl) { + log_err("JSON-RPC: failed to receive request\n"); + return -1; + } - int ret = jsonrpc_request_from_json(request, impl); - if (ret < 0) - goto free_impl; + int ret = jsonrpc_request_from_json(request, impl); + if (ret < 0) + goto free_impl; - return ret; + return ret; free_impl: - libjson_free(impl); + libjson_free(impl); - return ret; + return ret; } const char* jsonrpc_request_get_method(const struct jsonrpc_request* request) { - const char* method = NULL; - int ret = libjson_get_string(request->impl, jsonrpc_key_method, &method); - if (ret < 0) { - /* Should never happen. */ - return NULL; - } - return method; + const char* method = NULL; + int ret = libjson_get_string(request->impl, jsonrpc_key_method, &method); + if (ret < 0) { + /* Should never happen. */ + return NULL; + } + return method; } static struct json_object* jsonrpc_request_create_params(struct jsonrpc_request* request) { - int ret = 0; - const char* const key = jsonrpc_key_params; + int ret = 0; + const char* const key = jsonrpc_key_params; - if (!libjson_has(request->impl, key)) { - struct json_object* params = NULL; + if (!libjson_has(request->impl, key)) { + struct json_object* params = NULL; - ret = libjson_new_object(¶ms); - if (ret < 0) - return NULL; + ret = libjson_new_object(¶ms); + if (ret < 0) + return NULL; - ret = libjson_set(request->impl, key, params); - if (ret < 0) { - libjson_free(params); - return NULL; - } - return params; - } + ret = libjson_set(request->impl, key, params); + if (ret < 0) { + libjson_free(params); + return NULL; + } + return params; + } - struct json_object* params = NULL; - ret = libjson_get(request->impl, key, ¶ms); - if (ret < 0) - return NULL; - return params; + struct json_object* params = NULL; + ret = libjson_get(request->impl, key, ¶ms); + if (ret < 0) + return NULL; + return params; } int jsonrpc_request_get_param_string(const struct jsonrpc_request* request, const char* name, const char** value) { - struct json_object* params = NULL; - int ret = libjson_get(request->impl, jsonrpc_key_params, ¶ms); - if (ret < 0) - return ret; - return libjson_get_string(params, name, value); + struct json_object* params = NULL; + int ret = libjson_get(request->impl, jsonrpc_key_params, ¶ms); + if (ret < 0) + return ret; + return libjson_get_string(params, name, value); } int jsonrpc_request_set_param_string(struct jsonrpc_request* request, const char* name, const char* value) { - struct json_object* params = jsonrpc_request_create_params(request); - if (!params) - return -1; - return libjson_set_string(params, name, value); + struct json_object* params = jsonrpc_request_create_params(request); + if (!params) + return -1; + return libjson_set_string(params, name, value); } int jsonrpc_request_get_param_int(const struct jsonrpc_request* request, const char* name, int64_t* value) { - struct json_object* params = NULL; - int ret = libjson_get(request->impl, jsonrpc_key_params, ¶ms); - if (ret < 0) - return ret; - return libjson_get_int(params, name, value); + struct json_object* params = NULL; + int ret = libjson_get(request->impl, jsonrpc_key_params, ¶ms); + if (ret < 0) + return ret; + return libjson_get_int(params, name, value); } int jsonrpc_request_set_param_int(struct jsonrpc_request* request, const char* name, int64_t value) { - struct json_object* params = jsonrpc_request_create_params(request); - if (!params) - return -1; - return libjson_set_int(params, name, value); + struct json_object* params = jsonrpc_request_create_params(request); + if (!params) + return -1; + return libjson_set_int(params, name, value); } const char* jsonrpc_response_to_string(const struct jsonrpc_response* response) { - return libjson_to_string_pretty(response->impl); + return libjson_to_string_pretty(response->impl); } int jsonrpc_response_create_internal(struct jsonrpc_response** _response, const struct jsonrpc_request* request, struct json_object* result, struct json_object* error) { - int ret = 0; + int ret = 0; - struct jsonrpc_response* response = malloc(sizeof(struct jsonrpc_response)); - if (!response) { - log_errno("malloc"); - ret = -1; - goto exit; - } + struct jsonrpc_response* response = malloc(sizeof(struct jsonrpc_response)); + if (!response) { + log_errno("malloc"); + ret = -1; + goto exit; + } - ret = libjson_new_object(&response->impl); - if (ret < 0) - goto free; + ret = libjson_new_object(&response->impl); + if (ret < 0) + goto free; - ret = jsonrpc_set_version(response->impl); - if (ret < 0) - goto free_impl; + ret = jsonrpc_set_version(response->impl); + if (ret < 0) + goto free_impl; - struct json_object* id = NULL; - ret = libjson_clone(request->impl, jsonrpc_key_id, &id); - if (ret < 0) - goto free_impl; + struct json_object* id = NULL; + ret = libjson_clone(request->impl, jsonrpc_key_id, &id); + if (ret < 0) + goto free_impl; - ret = libjson_set(response->impl, jsonrpc_key_id, id); - if (ret < 0) { - libjson_free(id); - goto free_impl; - } + ret = libjson_set(response->impl, jsonrpc_key_id, id); + if (ret < 0) { + libjson_free(id); + goto free_impl; + } - if (error) { - ret = libjson_set_const_key(response->impl, jsonrpc_key_error, error); - if (ret < 0) - goto free_impl; - } else { - ret = libjson_set_const_key(response->impl, jsonrpc_key_result, result); - if (ret < 0) - goto free_impl; - } + if (error) { + ret = libjson_set_const_key(response->impl, jsonrpc_key_error, error); + if (ret < 0) + goto free_impl; + } else { + ret = libjson_set_const_key(response->impl, jsonrpc_key_result, result); + if (ret < 0) + goto free_impl; + } - *_response = response; - goto exit; + *_response = response; + goto exit; free_impl: - libjson_free(response->impl); + libjson_free(response->impl); free: - free(response); + free(response); exit: - return ret; + return ret; } int jsonrpc_response_create(struct jsonrpc_response** response, const struct jsonrpc_request* request, struct json_object* result) { - return jsonrpc_response_create_internal(response, request, result, NULL); + return jsonrpc_response_create_internal(response, request, result, NULL); } void jsonrpc_response_destroy(struct jsonrpc_response* response) { - libjson_free(response->impl); - free(response); + libjson_free(response->impl); + free(response); } int jsonrpc_error_create(struct jsonrpc_response** response, struct jsonrpc_request* request, int code, const char* message) { - int ret = 0; - struct json_object* error = NULL; + int ret = 0; + struct json_object* error = NULL; - ret = libjson_new_object(&error); - if (ret < 0) - return ret; + ret = libjson_new_object(&error); + if (ret < 0) + return ret; - ret = libjson_set_int_const_key(error, jsonrpc_key_code, code); - if (ret < 0) - goto free; - ret = libjson_set_string_const_key(error, jsonrpc_key_message, message); - if (ret < 0) - goto free; + ret = libjson_set_int_const_key(error, jsonrpc_key_code, code); + if (ret < 0) + goto free; + ret = libjson_set_string_const_key(error, jsonrpc_key_message, message); + if (ret < 0) + goto free; - ret = jsonrpc_response_create_internal(response, request, NULL, error); - if (ret < 0) - goto free; + ret = jsonrpc_response_create_internal(response, request, NULL, error); + if (ret < 0) + goto free; - return ret; + return ret; free: - libjson_free(error); + libjson_free(error); - return ret; + return ret; } int jsonrpc_response_is_error(const struct jsonrpc_response* response) { - return libjson_has(response->impl, jsonrpc_key_error); + return libjson_has(response->impl, jsonrpc_key_error); } static int jsonrpc_response_from_json(struct jsonrpc_response** _response, struct json_object* impl) { - int ret = 0; + int ret = 0; - ret = jsonrpc_check_version(impl); - if (ret < 0) - return ret; - ret = jsonrpc_check_id(impl, 1); - if (ret < 0) - return ret; - ret = jsonrpc_check_result_or_error(impl); - if (ret < 0) - return ret; + ret = jsonrpc_check_version(impl); + if (ret < 0) + return ret; + ret = jsonrpc_check_id(impl, 1); + if (ret < 0) + return ret; + ret = jsonrpc_check_result_or_error(impl); + if (ret < 0) + return ret; - struct jsonrpc_response* response = malloc(sizeof(struct jsonrpc_response)); - if (!response) { - log_errno("malloc"); - return -1; - } - response->impl = impl; + struct jsonrpc_response* response = malloc(sizeof(struct jsonrpc_response)); + if (!response) { + log_errno("malloc"); + return -1; + } + response->impl = impl; - *_response = response; - return ret; + *_response = response; + return ret; } int jsonrpc_response_send(const struct jsonrpc_response* response, int fd) { - return libjson_send(response->impl, fd); + return libjson_send(response->impl, fd); } int jsonrpc_response_recv(struct jsonrpc_response** response, int fd) { - struct json_object* impl = libjson_recv(fd); - if (!impl) { - log_err("JSON-RPC: failed to receive response\n"); - return -1; - } + struct json_object* impl = libjson_recv(fd); + if (!impl) { + log_err("JSON-RPC: failed to receive response\n"); + return -1; + } - int ret = jsonrpc_response_from_json(response, impl); - if (ret < 0) - goto free_impl; + int ret = jsonrpc_response_from_json(response, impl); + if (ret < 0) + goto free_impl; - return ret; + return ret; free_impl: - libjson_free(impl); + libjson_free(impl); - return ret; + return ret; } |
