+enum {
+ RPC_JSONRPC,
+ RPC_METHOD,
+ RPC_PARAMS,
+ RPC_ID,
+ __RPC_MAX,
+};
+
+static const struct blobmsg_policy rpc_policy[__RPC_MAX] = {
+ [RPC_JSONRPC] = { .name = "jsonrpc", .type = BLOBMSG_TYPE_STRING },
+ [RPC_METHOD] = { .name = "method", .type = BLOBMSG_TYPE_STRING },
+ [RPC_PARAMS] = { .name = "params", .type = BLOBMSG_TYPE_ARRAY },
+ [RPC_ID] = { .name = "id", .type = BLOBMSG_TYPE_UNSPEC },
+};
+
+struct rpc_data {
+ struct blob_attr *id;
+ const char *method;
+ const char *object;
+ const char *function;
+ struct blob_attr *data;
+};
+
+enum rpc_error {
+ ERROR_PARSE,
+ ERROR_REQUEST,
+ ERROR_METHOD,
+ ERROR_PARAMS,
+ ERROR_INTERNAL,
+ ERROR_OBJECT,
+ ERROR_SESSION,
+ ERROR_ACCESS,
+ ERROR_TIMEOUT,
+ __ERROR_MAX
+};
+
+static const struct {
+ int code;
+ const char *msg;
+} json_errors[__ERROR_MAX] = {
+ [ERROR_PARSE] = { -32700, "Parse error" },
+ [ERROR_REQUEST] = { -32600, "Invalid request" },
+ [ERROR_METHOD] = { -32601, "Method not found" },
+ [ERROR_PARAMS] = { -32602, "Invalid parameters" },
+ [ERROR_INTERNAL] = { -32603, "Internal error" },
+ [ERROR_OBJECT] = { -32000, "Object not found" },
+ [ERROR_SESSION] = { -32001, "Session not found" },
+ [ERROR_ACCESS] = { -32002, "Access denied" },
+ [ERROR_TIMEOUT] = { -32003, "ubus request timed out" },
+};
+
+static void __uh_ubus_next_batched_request(struct uloop_timeout *timeout);
+
+static void uh_ubus_next_batched_request(struct client *cl)
+{
+ struct dispatch_ubus *du = &cl->dispatch.ubus;
+
+ du->timeout.cb = __uh_ubus_next_batched_request;
+ uloop_timeout_set(&du->timeout, 1);
+}
+
+static void uh_ubus_send_header(struct client *cl)
+{
+ ops->http_header(cl, 200, "OK");
+ ustream_printf(cl->us, "Content-Type: application/json\r\n\r\n");
+}
+
+static void uh_ubus_send_response(struct client *cl)