Amxb_Ubus  3.3.1
Ambiorix Ubus API
amxb_ubus_invoke.c File Reference
#include <stdlib.h>
#include <amxc/amxc_string_split.h>
#include "amxb_ubus.h"

Go to the source code of this file.

Macros

#define _GNU_SOURCE
 

Functions

static int amxb_ubus_status_to_amxd_status (int rv, amxc_var_t *result)
 
static void amxb_ubus_transform_args (amxc_var_t *dest, amxc_var_t *args, const char *method)
 
static void amxb_ubus_convert_out_args (amxc_var_t *result)
 
static void amxb_ubus_request_done (struct ubus_request *req, int ret)
 
static int amxb_ubus_convert (amxb_ubus_t *amxb_ubus_ctx, amxb_invoke_t *invoke_ctx, amxc_var_t *args)
 
int PRIVATE amxb_ubus_get_longest_path (amxb_ubus_t *amxb_ubus_ctx, amxd_path_t *path, amxc_string_t *rel_path)
 
void PRIVATE amxb_ubus_result_data (struct ubus_request *req, AMXB_UNUSED int type, struct blob_attr *msg)
 
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)
 
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_async_invoke (void *const ctx, amxb_invoke_t *invoke_ctx, amxc_var_t *args, amxb_request_t *request)
 
int PRIVATE amxb_ubus_wait_request (AMXB_UNUSED void *const ctx, amxb_request_t *request, int timeout)
 
int PRIVATE amxb_ubus_close_request (void *const ctx, amxb_request_t *request)
 

Macro Definition Documentation

◆ _GNU_SOURCE

#define _GNU_SOURCE

Definition at line 56 of file amxb_ubus_invoke.c.

Function Documentation

◆ amxb_ubus_async_invoke()

int PRIVATE amxb_ubus_async_invoke ( void *const  ctx,
amxb_invoke_t *  invoke_ctx,
amxc_var_t *  args,
amxb_request_t *  request 
)

Definition at line 405 of file amxb_ubus_invoke.c.

408  {
409  amxb_ubus_t* amxb_ubus_ctx = (amxb_ubus_t*) ctx;
410  uint32_t id = 0;
411  int ret = -1;
412  amxb_ubus_request_t* amxb_ubus_req = NULL;
413 
414  when_str_empty(invoke_ctx->object, exit);
415  amxb_ubus_req = (amxb_ubus_request_t*) calloc(1, sizeof(amxb_ubus_request_t));
416  when_null(amxb_ubus_req, exit);
417  amxc_var_init(&amxb_ubus_req->args);
418  amxb_ubus_transform_args(&amxb_ubus_req->args, args, invoke_ctx->method);
419 
420  if(amxb_ubus_invoke_base(amxb_ubus_ctx,
421  invoke_ctx->object,
422  args,
423  request,
424  &id) != 0) {
425  when_failed(amxb_ubus_convert(amxb_ubus_ctx, invoke_ctx, &amxb_ubus_req->args), exit);
426  when_failed(amxb_ubus_invoke_base(amxb_ubus_ctx,
427  invoke_ctx->object,
428  &amxb_ubus_req->args,
429  request,
430  &id),
431  exit);
432  }
433 
434  amxb_ubus_req->request = request;
435  amxb_ubus_req->id = id;
436  request->bus_data = amxb_ubus_req;
437 
438  amxb_ubus_req->ubus_req = (struct ubus_request*) calloc(1, sizeof(struct ubus_request));
439  when_null(amxb_ubus_req->ubus_req, exit);
440 
441  ret = ubus_invoke_async(amxb_ubus_ctx->ubus_ctx,
442  id,
443  invoke_ctx->method,
444  amxb_ubus_ctx->b.head,
445  amxb_ubus_req->ubus_req);
446 
447  amxb_ubus_req->ubus_req->data_cb = amxb_ubus_result_data;
448  amxb_ubus_req->ubus_req->complete_cb = amxb_ubus_request_done;
449  amxb_ubus_req->ubus_req->priv = amxb_ubus_req;
450 
451  ubus_complete_request_async(amxb_ubus_ctx->ubus_ctx, amxb_ubus_req->ubus_req);
452 
453 exit:
454  if(ret != 0) {
455  if(amxb_ubus_req != NULL) {
456  amxc_var_clean(&amxb_ubus_req->args);
457  free(amxb_ubus_req->ubus_req);
458  }
459  free(amxb_ubus_req);
460  request->bus_data = NULL;
461  }
462  return ret;
463 }
static void amxb_ubus_transform_args(amxc_var_t *dest, amxc_var_t *args, const char *method)
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_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)
struct ubus_request * ubus_req
Definition: amxb_ubus.h:106
amxb_request_t * request
Definition: amxb_ubus.h:109
amxc_var_t args
Definition: amxb_ubus.h:108
struct blob_buf b
Definition: amxb_ubus.h:89
struct ubus_context * ubus_ctx
Definition: amxb_ubus.h:87
Here is the call graph for this function:

◆ amxb_ubus_close_request()

int PRIVATE amxb_ubus_close_request ( void *const  ctx,
amxb_request_t *  request 
)

Definition at line 475 of file amxb_ubus_invoke.c.

476  {
477  amxb_ubus_t* amxb_ubus_ctx = (amxb_ubus_t*) ctx;
478  amxb_ubus_request_t* amxb_ubus_req = (amxb_ubus_request_t*) request->bus_data;
479 
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);
484  free(ubus_req);
485  free(amxb_ubus_req);
486  request->bus_data = NULL;
487  }
488  return 0;
489 }

◆ amxb_ubus_convert()

static int amxb_ubus_convert ( amxb_ubus_t amxb_ubus_ctx,
amxb_invoke_t *  invoke_ctx,
amxc_var_t *  args 
)
static

Definition at line 195 of file amxb_ubus_invoke.c.

197  {
198  amxd_path_t path;
199  char* object = NULL;
200  char* method = invoke_ctx->method;
201  amxc_string_t rel_path;
202  int retval = -1;
203 
204  amxc_string_init(&rel_path, 64);
205  amxd_path_init(&path, NULL);
206  amxd_path_setf(&path, true, "%s", invoke_ctx->object);
207 
208  free(invoke_ctx->object);
209  invoke_ctx->object = NULL;
210  invoke_ctx->method = NULL;
211 
212  when_failed(amxb_ubus_get_longest_path(amxb_ubus_ctx, &path, &rel_path), exit);
213 
214  object = strdup(amxd_path_get(&path, 0));
215 
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));
220  } else {
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));
223  }
224  invoke_ctx->method = method;
225  method = NULL;
226  } else {
227  amxc_var_add_key(cstring_t, args, "rel_path", amxc_string_get(&rel_path, 0));
228  invoke_ctx->method = strdup("_exec");
229  }
230  invoke_ctx->object = object;
231  object = NULL;
232 
233  retval = 0;
234 
235 exit:
236  free(object);
237  free(method);
238  amxc_string_clean(&rel_path);
239  amxd_path_clean(&path);
240  return retval;
241 }
int PRIVATE amxb_ubus_get_longest_path(amxb_ubus_t *amxb_ubus_ctx, amxd_path_t *path, amxc_string_t *rel_path)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ amxb_ubus_convert_out_args()

static void amxb_ubus_convert_out_args ( amxc_var_t *  result)
static

Definition at line 125 of file amxb_ubus_invoke.c.

125  {
126  amxc_var_t* out_args = GETI_ARG(result, 1);
127  amxc_var_t* args = GET_ARG(out_args, "args");
128  amxc_var_t copy_var;
129 
130  amxc_var_init(&copy_var);
131 
132  when_null(args, exit);
133 
134  amxc_var_move(&copy_var, args);
135  amxc_var_move(out_args, &copy_var);
136 
137 exit:
138  amxc_var_clean(&copy_var);
139  return;
140 }
Here is the caller graph for this function:

◆ amxb_ubus_get_longest_path()

int PRIVATE amxb_ubus_get_longest_path ( amxb_ubus_t amxb_ubus_ctx,
amxd_path_t *  path,
amxc_string_t *  rel_path 
)

Definition at line 243 of file amxb_ubus_invoke.c.

245  {
246  int retval = -1;
247  char* part = NULL;
248  const char* object = NULL;
249  uint32_t id = 0;
250 
251  do{
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)) {
256  break;
257  }
258  free(part);
259  part = amxd_path_get_last(path, true);
260  amxc_string_prependf(rel_path, "%s", part);
261  } while (part != NULL);
262 
263 exit:
264  free(part);
265  return retval;
266 }
Here is the caller graph for this function:

◆ amxb_ubus_invoke()

int PRIVATE amxb_ubus_invoke ( void *const  ctx,
amxb_invoke_t *  invoke_ctx,
amxc_var_t *  args,
amxb_request_t *  request,
int  timeout 
)

Definition at line 331 of file amxb_ubus_invoke.c.

335  {
336  amxb_ubus_t* amxb_ubus_ctx = (amxb_ubus_t*) ctx;
337  uint32_t id = 0;
338  int ret = amxd_status_unknown_error;
339  amxb_ubus_request_t* amxb_ubus_req = NULL;
340 
341  when_str_empty(invoke_ctx->object, exit);
342  amxb_ubus_req = (amxb_ubus_request_t*) calloc(1, sizeof(amxb_ubus_request_t));
343  when_null(amxb_ubus_req, exit);
344  amxc_var_init(&amxb_ubus_req->args);
345  amxb_ubus_transform_args(&amxb_ubus_req->args, args, invoke_ctx->method);
346 
347  if(amxb_ubus_invoke_base(amxb_ubus_ctx,
348  invoke_ctx->object,
349  args,
350  request,
351  &id) != 0) {
352  when_failed(amxb_ubus_convert(amxb_ubus_ctx, invoke_ctx, &amxb_ubus_req->args), exit);
353  ret = amxb_ubus_invoke_base(amxb_ubus_ctx,
354  invoke_ctx->object,
355  &amxb_ubus_req->args,
356  request,
357  &id);
358  ret = amxb_ubus_status_to_amxd_status(ret, request->result);
359  request->bus_retval = ret;
360  amxb_ubus_req->converted = true;
361  when_failed(ret, exit);
362  }
363 
364  amxb_ubus_req->request = request;
365  request->bus_data = amxb_ubus_req;
366 
367  ret = ubus_invoke(amxb_ubus_ctx->ubus_ctx,
368  id,
369  invoke_ctx->method,
370  amxb_ubus_ctx->b.head,
372  amxb_ubus_req,
373  timeout * 1000);
374 
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);
379 
380  amxb_ubus_format_blob_table(htable, &amxb_ubus_ctx->b);
381 
382  ret = ubus_invoke(amxb_ubus_ctx->ubus_ctx,
383  id,
384  "_exec",
385  amxb_ubus_ctx->b.head,
387  amxb_ubus_req,
388  timeout * 1000);
389  }
390 
391  ret = amxb_ubus_status_to_amxd_status(ret, request->result);
392  request->bus_retval = ret;
393  if(amxb_ubus_req->converted) {
394  amxb_ubus_convert_out_args(request->result);
395  }
396 
397 exit:
398  if(amxb_ubus_req != NULL) {
399  amxc_var_clean(&amxb_ubus_req->args);
400  }
401  free(amxb_ubus_req);
402  return ret;
403 }
int PRIVATE amxb_ubus_format_blob_table(const amxc_htable_t *table, struct blob_buf *b)
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)
Here is the call graph for this function:

◆ amxb_ubus_invoke_base()

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 
)

Definition at line 303 of file amxb_ubus_invoke.c.

307  {
308  int retval = -1;
309 
310  // lookup id can cause the ubus blob msg to be overwritten
311  // first do the lookup and then initialize the blob
312  retval = ubus_lookup_id(amxb_ubus_ctx->ubus_ctx, object, id);
313  if(retval != 0) {
314  goto exit;
315  }
316 
317  blob_buf_init(&amxb_ubus_ctx->b, 0);
318 
319  if(args != NULL) {
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);
322  when_failed(amxb_ubus_format_blob_table(htable, &amxb_ubus_ctx->b), exit);
323  }
324 
325  amxc_var_set_type(request->result, AMXC_VAR_ID_LIST);
326 
327 exit:
328  return retval;
329 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ amxb_ubus_request_done()

static void amxb_ubus_request_done ( struct ubus_request *  req,
int  ret 
)
static

Definition at line 142 of file amxb_ubus_invoke.c.

142  {
143  amxb_ubus_request_t* amxb_ubus_req = (amxb_ubus_request_t*) req->priv;
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);
148  amxb_ubus_t* amxb_ubus_ctx = (amxb_ubus_t*) ctx->bus_ctx;
149 
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);
153 
154  amxb_ubus_format_blob_table(htable, &amxb_ubus_ctx->b);
155 
156  ret = ubus_invoke_async(amxb_ubus_ctx->ubus_ctx,
157  amxb_ubus_req->id,
158  "_exec",
159  amxb_ubus_ctx->b.head,
160  amxb_ubus_req->ubus_req);
161 
162  amxb_ubus_req->ubus_req->data_cb = amxb_ubus_result_data;
163  amxb_ubus_req->ubus_req->complete_cb = amxb_ubus_request_done;
164  amxb_ubus_req->ubus_req->priv = amxb_ubus_req;
165  amxb_ubus_req->converted = true;
166 
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);
169 
170  if(ret == 0) {
171  return;
172  }
173  }
174 
175  ret = amxb_ubus_status_to_amxd_status(ret, request->result);
176  request->bus_retval = ret;
177  if(amxb_ubus_req->converted) {
178  amxb_ubus_convert_out_args(request->result);
179  }
180 
181  if(request->done_fn != NULL) {
182  request->done_fn(ctx, request, ret, request->priv);
183  }
184 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ amxb_ubus_result_data()

void PRIVATE amxb_ubus_result_data ( struct ubus_request *  req,
AMXB_UNUSED int  type,
struct blob_attr *  msg 
)

Definition at line 268 of file amxb_ubus_invoke.c.

270  {
271  amxb_ubus_request_t* amxb_ubus_req = (amxb_ubus_request_t*) req->priv;
272  amxb_request_t* request = amxb_ubus_req->request;
273 
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;
278 
279  amxc_var_new(&item);
280  ctx = amxb_request_get_ctx(request);
281 
282  if((msg != NULL) && (result != NULL)) {
283  amxc_var_set_type(item, AMXC_VAR_ID_HTABLE);
284  amxb_ubus_parse_blob_table(item, (struct blob_attr*) blob_data(msg), blob_len(msg));
285  rv = GET_ARG(item, "retval");
286  if(rv == NULL) {
287  amxc_var_set_index(result, -1, item, AMXC_VAR_FLAG_DEFAULT);
288  } else {
289  amxc_var_take_it(rv);
290  amxc_var_set_index(result, -1, rv, AMXC_VAR_FLAG_DEFAULT);
291  amxc_var_delete(&item);
292  item = rv;
293  }
294  } else {
295  amxc_var_delete(&item);
296  }
297 
298  if((request->cb_fn != NULL) && (item != NULL)) {
299  request->cb_fn(ctx, item, request->priv);
300  }
301 }
int PRIVATE amxb_ubus_parse_blob_table(amxc_var_t *var, struct blob_attr *attr, int len)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ amxb_ubus_status_to_amxd_status()

static int amxb_ubus_status_to_amxd_status ( int  rv,
amxc_var_t *  result 
)
static

Definition at line 65 of file amxb_ubus_invoke.c.

65  {
66  int retval = amxd_status_ok;
67  amxc_var_t* error = GETI_ARG(result, 2);
68 
69  int status[] = {
70  amxd_status_ok, // UBUS_STATUS_OK
71  amxd_status_invalid_function, // UBUS_STATUS_INVALID_COMMAND
72  amxd_status_invalid_arg, // UBUS_STATUS_INVALID_ARGUMENT
73  amxd_status_function_not_found, // UBUS_STATUS_METHOD_NOT_FOUND
74  amxd_status_object_not_found, // UBUS_STATUS_NOT_FOUND,
75  amxd_status_unknown_error, // UBUS_STATUS_NO_DATA
76  amxd_status_permission_denied, // UBUS_STATUS_PERMISSION_DENIED
77  amxd_status_timeout, // UBUS_STATUS_TIMEOUT
78  amxd_status_not_supported, // UBUS_STATUS_NOT_SUPPORTED
79  amxd_status_unknown_error, // UBUS_STATUS_UNKNOWN_ERROR
80  amxd_status_unknown_error, // UBUS_STATUS_CONNECTION_FAILED
81  };
82 
83  if((error != NULL) && (GET_ARG(error, "amxd-error-code") != NULL)) {
84  // to be able to pass the amxd error code 3 results are passed over ubus
85  // 1 - the function return value
86  // 2 - the function out arguments
87  // 3 - the amxd error code
88  retval = GET_UINT32(error, "amxd-error-code");
89  amxc_var_delete(&error);
90  // if the error code was found, check if nr 2 is an empty table,
91  // if an empty table remove it from the result.
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);
96  }
97  } else {
98  if((rv >= 0) && (rv < (int) (sizeof(status) / sizeof(int)))) {
99  retval = status[rv];
100  } else {
101  retval = AMXB_ERROR_BUS_UNKNOWN;
102  }
103  }
104 
105  return retval;
106 }
Here is the caller graph for this function:

◆ amxb_ubus_transform_args()

static void amxb_ubus_transform_args ( amxc_var_t *  dest,
amxc_var_t *  args,
const char *  method 
)
static

Definition at line 109 of file amxb_ubus_invoke.c.

109  {
110  amxc_var_set_type(dest, AMXC_VAR_ID_HTABLE);
111  if(method[0] != '_') {
112  amxc_var_add_key(cstring_t, dest, "method", method);
113  if(args != NULL) {
114  amxc_var_set_key(dest, "args", args, AMXC_VAR_FLAG_COPY);
115  } else {
116  amxc_var_add_key(amxc_htable_t, dest, "args", NULL);
117  }
118  } else {
119  if(args != NULL) {
120  amxc_var_copy(dest, args);
121  }
122  }
123 }
Here is the caller graph for this function:

◆ amxb_ubus_wait_request()

int PRIVATE amxb_ubus_wait_request ( AMXB_UNUSED void *const  ctx,
amxb_request_t *  request,
int  timeout 
)

Definition at line 465 of file amxb_ubus_invoke.c.

467  {
468  amxb_ubus_t* amxb_ubus_ctx = (amxb_ubus_t*) ctx;
469  amxb_ubus_request_t* amxb_ubus_req = (amxb_ubus_request_t*) request->bus_data;
470  struct ubus_request* ubus_req = amxb_ubus_req->ubus_req;
471 
472  return ubus_complete_request(amxb_ubus_ctx->ubus_ctx, ubus_req, timeout);
473 }