61 #include <amxc/amxc_string_split.h>
66 int retval = amxd_status_ok;
67 amxc_var_t* error = GETI_ARG(result, 2);
71 amxd_status_invalid_function,
72 amxd_status_invalid_arg,
73 amxd_status_function_not_found,
74 amxd_status_object_not_found,
75 amxd_status_unknown_error,
76 amxd_status_permission_denied,
78 amxd_status_not_supported,
79 amxd_status_unknown_error,
80 amxd_status_unknown_error,
83 if((error != NULL) && (GET_ARG(error,
"amxd-error-code") != NULL)) {
88 retval = GET_UINT32(error,
"amxd-error-code");
89 amxc_var_delete(&error);
92 error = GETI_ARG(result, 1);
93 if((amxc_var_type_of(error) == AMXC_VAR_ID_HTABLE) &&
94 amxc_htable_is_empty(amxc_var_constcast(amxc_htable_t, error))) {
95 amxc_var_delete(&error);
98 if((rv >= 0) && (rv < (
int) (
sizeof(status) /
sizeof(
int)))) {
101 retval = AMXB_ERROR_BUS_UNKNOWN;
110 amxc_var_set_type(dest, AMXC_VAR_ID_HTABLE);
111 if(method[0] !=
'_') {
112 amxc_var_add_key(cstring_t, dest,
"method", method);
114 amxc_var_set_key(dest,
"args", args, AMXC_VAR_FLAG_COPY);
116 amxc_var_add_key(amxc_htable_t, dest,
"args", NULL);
120 amxc_var_copy(dest, args);
126 amxc_var_t* out_args = GETI_ARG(result, 1);
127 amxc_var_t* args = GET_ARG(out_args,
"args");
130 amxc_var_init(©_var);
132 when_null(args, exit);
134 amxc_var_move(©_var, args);
135 amxc_var_move(out_args, ©_var);
138 amxc_var_clean(©_var);
144 amxb_request_t* request = amxb_ubus_req->
request;
145 amxc_var_t* var_method_name = GET_ARG(&amxb_ubus_req->
args,
"method");
146 const char* method = GET_CHAR(var_method_name, NULL);
147 const amxb_bus_ctx_t* ctx = amxb_request_get_ctx(request);
150 if((ret == UBUS_STATUS_METHOD_NOT_FOUND) && (method != NULL) && (method[0] !=
'_')) {
151 const amxc_htable_t* htable = amxc_var_constcast(amxc_htable_t, &amxb_ubus_req->
args);
152 blob_buf_init(&amxb_ubus_ctx->
b, 0);
156 ret = ubus_invoke_async(amxb_ubus_ctx->
ubus_ctx,
159 amxb_ubus_ctx->
b.head,
164 amxb_ubus_req->
ubus_req->priv = amxb_ubus_req;
167 amxc_var_set(cstring_t, var_method_name,
"_exec");
168 ubus_complete_request_async(amxb_ubus_ctx->
ubus_ctx, amxb_ubus_req->
ubus_req);
176 request->bus_retval = ret;
181 if(request->done_fn != NULL) {
182 request->done_fn(ctx, request, ret, request->priv);
196 amxb_invoke_t* invoke_ctx,
200 char* method = invoke_ctx->method;
201 amxc_string_t rel_path;
204 amxc_string_init(&rel_path, 64);
205 amxd_path_init(&path, NULL);
206 amxd_path_setf(&path,
true,
"%s", invoke_ctx->object);
208 free(invoke_ctx->object);
209 invoke_ctx->object = NULL;
210 invoke_ctx->method = NULL;
214 object = strdup(amxd_path_get(&path, 0));
216 if(method[0] ==
'_') {
217 amxc_var_t* vrel_path = GET_ARG(args,
"rel_path");
218 if(vrel_path == NULL) {
219 amxc_var_add_key(cstring_t, args,
"rel_path", amxc_string_get(&rel_path, 0));
221 amxc_string_appendf(&rel_path,
"%s", GET_CHAR(vrel_path, NULL));
222 amxc_var_set(cstring_t, vrel_path, amxc_string_get(&rel_path, 0));
224 invoke_ctx->method = method;
227 amxc_var_add_key(cstring_t, args,
"rel_path", amxc_string_get(&rel_path, 0));
228 invoke_ctx->method = strdup(
"_exec");
230 invoke_ctx->object = object;
238 amxc_string_clean(&rel_path);
239 amxd_path_clean(&path);
245 amxc_string_t* rel_path) {
248 const char*
object = NULL;
252 object = amxd_path_get(path, 0);
253 when_str_empty(
object, exit);
254 retval = ubus_lookup_id(amxb_ubus_ctx->
ubus_ctx,
object, &
id);
255 if((retval == 0) && (
id != 0)) {
259 part = amxd_path_get_last(path,
true);
260 amxc_string_prependf(rel_path,
"%s", part);
261 }
while (part != NULL);
269 AMXB_UNUSED
int type,
270 struct blob_attr* msg) {
272 amxb_request_t* request = amxb_ubus_req->
request;
274 amxc_var_t* result = request->result;
275 amxc_var_t* item = NULL;
276 amxc_var_t* rv = NULL;
277 const amxb_bus_ctx_t* ctx = NULL;
280 ctx = amxb_request_get_ctx(request);
282 if((msg != NULL) && (result != NULL)) {
283 amxc_var_set_type(item, AMXC_VAR_ID_HTABLE);
285 rv = GET_ARG(item,
"retval");
287 amxc_var_set_index(result, -1, item, AMXC_VAR_FLAG_DEFAULT);
289 amxc_var_take_it(rv);
290 amxc_var_set_index(result, -1, rv, AMXC_VAR_FLAG_DEFAULT);
291 amxc_var_delete(&item);
295 amxc_var_delete(&item);
298 if((request->cb_fn != NULL) && (item != NULL)) {
299 request->cb_fn(ctx, item, request->priv);
306 amxb_request_t* request,
312 retval = ubus_lookup_id(amxb_ubus_ctx->
ubus_ctx,
object,
id);
317 blob_buf_init(&amxb_ubus_ctx->
b, 0);
320 when_true(amxc_var_type_of(args) != AMXC_VAR_ID_HTABLE, exit);
321 const amxc_htable_t* htable = amxc_var_constcast(amxc_htable_t, args);
325 amxc_var_set_type(request->result, AMXC_VAR_ID_LIST);
332 amxb_invoke_t* invoke_ctx,
334 amxb_request_t* request,
338 int ret = amxd_status_unknown_error;
341 when_str_empty(invoke_ctx->object, exit);
343 when_null(amxb_ubus_req, exit);
344 amxc_var_init(&amxb_ubus_req->
args);
355 &amxb_ubus_req->
args,
359 request->bus_retval = ret;
361 when_failed(ret, exit);
364 amxb_ubus_req->
request = request;
365 request->bus_data = amxb_ubus_req;
367 ret = ubus_invoke(amxb_ubus_ctx->
ubus_ctx,
370 amxb_ubus_ctx->
b.head,
375 if((ret == UBUS_STATUS_METHOD_NOT_FOUND) && (invoke_ctx->method[0] !=
'_')) {
376 const amxc_htable_t* htable = NULL;
377 htable = amxc_var_constcast(amxc_htable_t, &amxb_ubus_req->
args);
378 blob_buf_init(&amxb_ubus_ctx->
b, 0);
382 ret = ubus_invoke(amxb_ubus_ctx->
ubus_ctx,
385 amxb_ubus_ctx->
b.head,
392 request->bus_retval = ret;
398 if(amxb_ubus_req != NULL) {
399 amxc_var_clean(&amxb_ubus_req->
args);
406 amxb_invoke_t* invoke_ctx,
408 amxb_request_t* request) {
414 when_str_empty(invoke_ctx->object, exit);
416 when_null(amxb_ubus_req, exit);
417 amxc_var_init(&amxb_ubus_req->
args);
428 &amxb_ubus_req->
args,
434 amxb_ubus_req->
request = request;
435 amxb_ubus_req->
id = id;
436 request->bus_data = amxb_ubus_req;
438 amxb_ubus_req->
ubus_req = (
struct ubus_request*) calloc(1,
sizeof(
struct ubus_request));
439 when_null(amxb_ubus_req->
ubus_req, exit);
441 ret = ubus_invoke_async(amxb_ubus_ctx->
ubus_ctx,
444 amxb_ubus_ctx->
b.head,
449 amxb_ubus_req->
ubus_req->priv = amxb_ubus_req;
451 ubus_complete_request_async(amxb_ubus_ctx->
ubus_ctx, amxb_ubus_req->
ubus_req);
455 if(amxb_ubus_req != NULL) {
456 amxc_var_clean(&amxb_ubus_req->
args);
460 request->bus_data = NULL;
466 amxb_request_t* request,
470 struct ubus_request* ubus_req = amxb_ubus_req->
ubus_req;
472 return ubus_complete_request(amxb_ubus_ctx->
ubus_ctx, ubus_req, timeout);
476 amxb_request_t* request) {
480 if(amxb_ubus_req != NULL) {
481 struct ubus_request* ubus_req = amxb_ubus_req->
ubus_req;
482 ubus_abort_request(amxb_ubus_ctx->
ubus_ctx, ubus_req);
483 amxc_var_clean(&amxb_ubus_req->
args);
486 request->bus_data = NULL;
int PRIVATE amxb_ubus_format_blob_table(const amxc_htable_t *table, struct blob_buf *b)
int PRIVATE amxb_ubus_parse_blob_table(amxc_var_t *var, struct blob_attr *attr, int len)
static void amxb_ubus_transform_args(amxc_var_t *dest, amxc_var_t *args, const char *method)
int PRIVATE amxb_ubus_close_request(void *const ctx, amxb_request_t *request)
static int amxb_ubus_convert(amxb_ubus_t *amxb_ubus_ctx, amxb_invoke_t *invoke_ctx, amxc_var_t *args)
int PRIVATE amxb_ubus_invoke_base(amxb_ubus_t *amxb_ubus_ctx, const char *object, amxc_var_t *args, amxb_request_t *request, uint32_t *id)
static void amxb_ubus_convert_out_args(amxc_var_t *result)
static int amxb_ubus_status_to_amxd_status(int rv, amxc_var_t *result)
int PRIVATE amxb_ubus_invoke(void *const ctx, amxb_invoke_t *invoke_ctx, amxc_var_t *args, amxb_request_t *request, int timeout)
int PRIVATE amxb_ubus_wait_request(AMXB_UNUSED void *const ctx, amxb_request_t *request, int timeout)
int PRIVATE amxb_ubus_async_invoke(void *const ctx, amxb_invoke_t *invoke_ctx, amxc_var_t *args, amxb_request_t *request)
static void amxb_ubus_request_done(struct ubus_request *req, int ret)
void PRIVATE amxb_ubus_result_data(struct ubus_request *req, AMXB_UNUSED int type, struct blob_attr *msg)
int PRIVATE amxb_ubus_get_longest_path(amxb_ubus_t *amxb_ubus_ctx, amxd_path_t *path, amxc_string_t *rel_path)
struct ubus_request * ubus_req
struct ubus_context * ubus_ctx