ubus: use local "blob_buf" in uh_ubus_handle_request_object()
[project/uhttpd.git] / ubus.c
diff --git a/ubus.c b/ubus.c
index 4fa03192d42075b5dda54a01d7812b9e7b888dc8..062e973585135d2369bc25f3159fbbfa8710359c 100644 (file)
--- a/ubus.c
+++ b/ubus.c
@@ -34,7 +34,7 @@ static struct config *_conf;
 static struct ubus_context *ctx;
 static struct blob_buf buf;
 
-#define UH_UBUS_MAX_POST_SIZE  4096
+#define UH_UBUS_MAX_POST_SIZE  65536
 #define UH_UBUS_DEFAULT_SID    "00000000000000000000000000000000"
 
 enum {
@@ -48,7 +48,7 @@ enum {
 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_PARAMS] = { .name = "params", .type = BLOBMSG_TYPE_UNSPEC },
        [RPC_ID] = { .name = "id", .type = BLOBMSG_TYPE_UNSPEC },
 };
 
@@ -144,11 +144,11 @@ static void uh_ubus_add_cors_headers(struct client *cl)
        }
 
        ustream_printf(cl->us, "Access-Control-Allow-Origin: %s\r\n",
-                      blobmsg_data(tb[HDR_ORIGIN]));
+                      blobmsg_get_string(tb[HDR_ORIGIN]));
 
        if (tb[HDR_ACCESS_CONTROL_REQUEST_HEADERS])
                ustream_printf(cl->us, "Access-Control-Allow-Headers: %s\r\n",
-                              blobmsg_data(tb[HDR_ACCESS_CONTROL_REQUEST_HEADERS]));
+                              blobmsg_get_string(tb[HDR_ACCESS_CONTROL_REQUEST_HEADERS]));
 
        ustream_printf(cl->us, "Access-Control-Allow-Methods: POST, OPTIONS\r\n");
        ustream_printf(cl->us, "Access-Control-Allow-Credentials: true\r\n");
@@ -192,16 +192,15 @@ static void uh_ubus_send_response(struct client *cl)
 static void uh_ubus_init_response(struct client *cl)
 {
        struct dispatch_ubus *du = &cl->dispatch.ubus;
-       struct json_object *obj = du->jsobj_cur;
+       struct json_object *obj = du->jsobj_cur, *obj2 = NULL;
 
-       blob_buf_init(&buf, 0);
        blobmsg_add_string(&buf, "jsonrpc", "2.0");
 
        if (obj)
-               obj = json_object_object_get(obj, "id");
+               json_object_object_get_ex(obj, "id", &obj2);
 
-       if (obj)
-               blobmsg_add_json_element(&buf, "id", obj);
+       if (obj2)
+               blobmsg_add_json_element(&buf, "id", obj2);
        else
                blobmsg_add_field(&buf, BLOBMSG_TYPE_UNSPEC, "id", NULL, 0);
 }
@@ -288,7 +287,7 @@ static void uh_ubus_single_error(struct client *cl, enum rpc_error type)
        ops->request_done(cl);
 }
 
-static void uh_ubus_send_request(struct client *cl, json_object *obj, const char *sid, struct blob_attr *args)
+static void uh_ubus_send_request(struct client *cl, const char *sid, struct blob_attr *args)
 {
        struct dispatch *d = &cl->dispatch;
        struct dispatch_ubus *du = &d->ubus;
@@ -370,7 +369,7 @@ static void uh_ubus_list_cb(struct ubus_context *ctx, struct ubus_object_data *o
        blobmsg_close_table(data->buf, o);
 }
 
-static void uh_ubus_send_list(struct client *cl, json_object *obj, struct blob_attr *params)
+static void uh_ubus_send_list(struct client *cl, struct blob_attr *params)
 {
        struct blob_attr *cur, *dup;
        struct list_data data = { .buf = &cl->dispatch.ubus.buf, .verbose = false };
@@ -409,14 +408,7 @@ static void uh_ubus_send_list(struct client *cl, json_object *obj, struct blob_a
 
 static bool parse_json_rpc(struct rpc_data *d, struct blob_attr *data)
 {
-       const struct blobmsg_policy data_policy[] = {
-               { .type = BLOBMSG_TYPE_STRING },
-               { .type = BLOBMSG_TYPE_STRING },
-               { .type = BLOBMSG_TYPE_STRING },
-               { .type = BLOBMSG_TYPE_TABLE },
-       };
        struct blob_attr *tb[__RPC_MAX];
-       struct blob_attr *tb2[4];
        struct blob_attr *cur;
 
        blobmsg_parse(rpc_policy, __RPC_MAX, tb, blob_data(data), blob_len(data));
@@ -440,24 +432,38 @@ static bool parse_json_rpc(struct rpc_data *d, struct blob_attr *data)
        if (!d->params)
                return false;
 
-       blobmsg_parse_array(data_policy, ARRAY_SIZE(data_policy), tb2,
+       return true;
+}
+
+static void parse_call_params(struct rpc_data *d)
+{
+       const struct blobmsg_policy data_policy[] = {
+               { .type = BLOBMSG_TYPE_STRING },
+               { .type = BLOBMSG_TYPE_STRING },
+               { .type = BLOBMSG_TYPE_STRING },
+               { .type = BLOBMSG_TYPE_TABLE },
+       };
+       struct blob_attr *tb[4];
+
+       if (!d->params || blobmsg_type(d->params) != BLOBMSG_TYPE_ARRAY)
+               return;
+
+       blobmsg_parse_array(data_policy, ARRAY_SIZE(data_policy), tb,
                            blobmsg_data(d->params), blobmsg_data_len(d->params));
 
-       if (tb2[0])
-               d->sid = blobmsg_data(tb2[0]);
+       if (tb[0])
+               d->sid = blobmsg_data(tb[0]);
 
        if (conf.ubus_noauth && (!d->sid || !*d->sid))
                d->sid = UH_UBUS_DEFAULT_SID;
 
-       if (tb2[1])
-               d->object = blobmsg_data(tb2[1]);
+       if (tb[1])
+               d->object = blobmsg_data(tb[1]);
 
-       if (tb2[2])
-               d->function = blobmsg_data(tb2[2]);
+       if (tb[2])
+               d->function = blobmsg_data(tb[2]);
 
-       d->data = tb2[3];
-
-       return true;
+       d->data = tb[3];
 }
 
 static void uh_ubus_init_batch(struct client *cl)
@@ -513,6 +519,7 @@ static void uh_ubus_handle_request_object(struct client *cl, struct json_object
        struct dispatch_ubus *du = &cl->dispatch.ubus;
        struct rpc_data data = {};
        enum rpc_error err = ERROR_PARSE;
+       static struct blob_buf req;
 
        uh_client_ref(cl);
 
@@ -520,14 +527,16 @@ static void uh_ubus_handle_request_object(struct client *cl, struct json_object
                goto error;
 
        du->jsobj_cur = obj;
-       blob_buf_init(&buf, 0);
-       if (!blobmsg_add_object(&buf, obj))
+       blob_buf_init(&req, 0);
+       if (!blobmsg_add_object(&req, obj))
                goto error;
 
-       if (!parse_json_rpc(&data, buf.head))
+       if (!parse_json_rpc(&data, req.head))
                goto error;
 
        if (!strcmp(data.method, "call")) {
+               parse_call_params(&data);
+
                if (!data.sid || !data.object || !data.function || !data.data)
                        goto error;
 
@@ -542,11 +551,11 @@ static void uh_ubus_handle_request_object(struct client *cl, struct json_object
                        goto error;
                }
 
-               uh_ubus_send_request(cl, obj, data.sid, data.data);
+               uh_ubus_send_request(cl, data.sid, data.data);
                goto out;
        }
        else if (!strcmp(data.method, "list")) {
-               uh_ubus_send_list(cl, obj, data.params);
+               uh_ubus_send_list(cl, data.params);
                goto out;
        }
        else {