diff options
Diffstat (limited to 'src/dged/jsonrpc.c')
| -rw-r--r-- | src/dged/jsonrpc.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/src/dged/jsonrpc.c b/src/dged/jsonrpc.c new file mode 100644 index 0000000..215274f --- /dev/null +++ b/src/dged/jsonrpc.c @@ -0,0 +1,118 @@ +#include "jsonrpc.h" + +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> + +struct jsonrpc_message jsonrpc_parse(const uint8_t *buf, uint64_t size) { + + struct json_result res = json_parse(buf, size); + if (!res.ok) { + return (struct jsonrpc_message){ + .type = Jsonrpc_Response, + .document = (struct json_value){.type = Json_Null, .parent = NULL}, + .message.response = (struct jsonrpc_response){ + .id = (struct json_value){.type = Json_Null}, + .ok = false, + .value.error = + (struct jsonrpc_error){ + .code = 0, + .message = s8(res.result.error), + }, + }}; + } + + struct json_value doc = res.result.document; + struct json_object *obj = doc.value.object; + + if (json_contains(obj, s8("error"))) { + struct json_object *err_obj = json_get(obj, s8("error"))->value.object; + return (struct jsonrpc_message){ + .type = Jsonrpc_Response, + .document = doc, + .message.response = + (struct jsonrpc_response){ + .id = *json_get(obj, s8("id")), + .ok = false, + .value.error = + (struct jsonrpc_error){ + .code = json_get(err_obj, s8("code"))->value.number, + .message = + json_get(err_obj, s8("message"))->value.string, + }, + }, + }; + } else if (!json_contains(obj, s8("id"))) { + // no id == notification + return (struct jsonrpc_message){ + .type = Jsonrpc_Notification, + .document = doc, + .message.notification = + (struct jsonrpc_notification){ + .method = json_get(obj, s8("method"))->value.string, + .params = *json_get(obj, s8("params")), + }, + }; + } else if (json_contains(obj, s8("method"))) { + // request + return (struct jsonrpc_message){ + .type = Jsonrpc_Request, + .document = doc, + .message.request = (struct jsonrpc_request){ + .id = *json_get(obj, s8("id")), + .method = json_get(obj, s8("method"))->value.string, + .params = *json_get(obj, s8("params")), + }}; + } + + // response + return (struct jsonrpc_message){ + .type = Jsonrpc_Response, + .document = doc, + .message.response = (struct jsonrpc_response){ + .id = *json_get(obj, s8("id")), + .ok = true, + .value.result = *json_get(obj, s8("result")), + }}; +} + +struct s8 jsonrpc_format_request(struct json_value id, struct s8 method, + struct s8 params) { + const char *fmt = "{ \"jsonrpc\": \"2.0\", \"id\": %d, \"method\": \"%.*s\", " + "\"params\": %.*s }"; + size_t s = snprintf(NULL, 0, fmt, (int)id.value.number, method.l, method.s, + params.l, params.s); + char *buf = calloc(s + 1, 1); + snprintf(buf, s + 1, fmt, (int)id.value.number, method.l, method.s, params.l, + params.s); + + return (struct s8){ + .s = (uint8_t *)buf, + .l = s, + }; +} + +struct s8 jsonrpc_format_response(struct json_value id, struct s8 result) { + const char *fmt = "{ \"jsonrpc\": \"2.0\", \"id\": %d, \"result\": %.*s }"; + size_t s = snprintf(NULL, 0, fmt, (int)id.value.number, result.l, result.s); + char *buf = calloc(s + 1, 1); + snprintf(buf, s + 1, fmt, (int)id.value.number, result.l, result.s); + + return (struct s8){ + .s = (uint8_t *)buf, + .l = s, + }; +} + +struct s8 jsonrpc_format_notification(struct s8 method, struct s8 params) { + const char *fmt = "{ \"jsonrpc\": \"2.0\", \"method\": \"%.*s\", " + "\"params\": %.*s }"; + size_t s = snprintf(NULL, 0, fmt, method.l, method.s, params.l, params.s); + char *buf = calloc(s + 1, 1); + snprintf(buf, s + 1, fmt, method.l, method.s, params.l, params.s); + + return (struct s8){ + .s = (uint8_t *)buf, + .l = s, + }; +} |
