diff options
author | Felix Fietkau <nbd@nbd.name> | 2024-04-07 09:58:25 +0200 |
---|---|---|
committer | Felix Fietkau <nbd@nbd.name> | 2024-04-07 10:30:37 +0200 |
commit | 4ade84e8fb819eb296856452bd4258461d746ef8 (patch) | |
tree | aa53bb013ab0b8b1cc224cb3d001201b1bffa6e1 /lib/ubus.c | |
parent | 55ee75b6e08c64a850f9da2613eef127f8014d98 (diff) |
ubus: add explicit support for deferring incoming requests
This is needed when asynchronously processing requests via uloop, e.g.
using uclient.
Example script:
let libubus = require("ubus");
let uloop = require("uloop");
uloop.init();
let ubus = libubus.connect();
ubus.publish("test", {
test: {
call: function(req) {
req.defer();
uloop.timer(1000, () => {
req.reply({ msg: "Hello, world!" }, 0);
});
},
args: {}
},
});
uloop.run();
uloop.done();
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'lib/ubus.c')
-rw-r--r-- | lib/ubus.c | 17 |
1 files changed, 16 insertions, 1 deletions
@@ -148,6 +148,7 @@ typedef struct { struct uloop_timeout timeout; struct ubus_context *ctx; size_t registry_index; + bool deferred; bool replied; uc_vm_t *vm; } uc_ubus_request_t; @@ -846,6 +847,18 @@ uc_ubus_request_reply(uc_vm_t *vm, size_t nargs) } static uc_value_t * +uc_ubus_request_defer(uc_vm_t *vm, size_t nargs) +{ + uc_ubus_request_t *callctx = uc_fn_thisval("ubus.request"); + + if (!callctx) + return NULL; + + callctx->deferred = true; + return ucv_boolean_new(true); +} + +static uc_value_t * uc_ubus_request_error(uc_vm_t *vm, size_t nargs) { uc_ubus_request_t **callctx = uc_fn_this("ubus.request"); @@ -1256,7 +1269,7 @@ uc_ubus_handle_reply_common(struct ubus_context *ctx, /* If neither a deferred ubus request, nor a plain object were * returned and if reqobj.reply() hasn't been called, immediately * finish deferred request with UBUS_STATUS_NO_DATA. */ - else if (!callctx->replied) { + else if (!callctx->replied && !callctx->deferred) { rv = UBUS_STATUS_NO_DATA; if (ucv_type(res) == UC_INTEGER) { @@ -2003,6 +2016,7 @@ static const uc_function_list_t object_fns[] = { static const uc_function_list_t request_fns[] = { { "reply", uc_ubus_request_reply }, { "error", uc_ubus_request_error }, + { "defer", uc_ubus_request_defer }, }; static const uc_function_list_t notify_fns[] = { @@ -2058,6 +2072,7 @@ static void free_object(void *ud) { static void free_request(void *ud) { uc_ubus_request_t *callctx = ud; + uc_ubus_request_finish(callctx, UBUS_STATUS_TIMEOUT, NULL); uloop_timeout_cancel(&callctx->timeout); free(callctx); } |