1 /* 2 * Copyright (C) 2020-2021 Jo-Philipp Wich <jo@mein.io> 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include <unistd.h> 18 #include <libubus.h> 19 #include <libubox/blobmsg.h> 20 21 #include "ucode/module.h" 22 23 #define ok_return(expr) do { set_error(0, NULL); return (expr); } while(0) 24 #define err_return(err, ...) do { set_error(err, __VA_ARGS__); return NULL; } while(0) 25 26 static struct { 27 enum ubus_msg_status code; 28 char *msg; 29 } last_error; 30 31 __attribute__((format(printf, 2, 3))) static void 32 set_error(int errcode, const char *fmt, ...) 33 { 34 va_list ap; 35 36 free(last_error.msg); 37 38 last_error.code = errcode; 39 last_error.msg = NULL; 40 41 if (fmt) { 42 va_start(ap, fmt); 43 xvasprintf(&last_error.msg, fmt, ap); 44 va_end(ap); 45 } 46 } 47 48 static char * 49 _arg_type(uc_type_t type) 50 { 51 switch (type) { 52 case UC_INTEGER: return "an integer value"; 53 case UC_BOOLEAN: return "a boolean value"; 54 case UC_STRING: return "a string value"; 55 case UC_DOUBLE: return "a double value"; 56 case UC_ARRAY: return "an array"; 57 case UC_OBJECT: return "an object"; 58 case UC_REGEXP: return "a regular expression"; 59 case UC_CLOSURE: return "a function"; 60 default: return "the expected type"; 61 } 62 } 63 64 static bool 65 _args_get(uc_vm_t *vm, size_t nargs, ...) 66 { 67 uc_value_t **ptr, *arg; 68 uc_type_t type, t; 69 const char *name; 70 size_t index = 0; 71 va_list ap; 72 bool opt; 73 74 va_start(ap, nargs); 75 76 while (true) { 77 name = va_arg(ap, const char *); 78 79 if (!name) 80 break; 81 82 arg = uc_fn_arg(index++); 83 84 type = va_arg(ap, uc_type_t); 85 opt = va_arg(ap, int); 86 ptr = va_arg(ap, uc_value_t **); 87 88 if (!opt && !arg) 89 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Argument %s is required", name); 90 91 t = ucv_type(arg); 92 93 if (t == UC_CFUNCTION) 94 t = UC_CLOSURE; 95 96 if (arg && t != type) 97 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Argument %s is not %s", name, _arg_type(type)); 98 99 *ptr = arg; 100 } 101 102 va_end(ap); 103 104 ok_return(true); 105 } 106 107 #define args_get(vm, nargs, ...) do { if (!_args_get(vm, nargs, __VA_ARGS__, NULL)) return NULL; } while(0) 108 109 static uc_resource_type_t *subscriber_type; 110 static uc_resource_type_t *listener_type; 111 static uc_resource_type_t *request_type; 112 static uc_resource_type_t *notify_type; 113 static uc_resource_type_t *object_type; 114 static uc_resource_type_t *defer_type; 115 static uc_resource_type_t *conn_type; 116 117 static uint64_t n_cb_active; 118 static bool have_own_uloop; 119 120 static struct blob_buf buf; 121 122 typedef struct { 123 struct ubus_context ctx; 124 struct blob_buf buf; 125 int timeout; 126 } uc_ubus_connection_t; 127 128 typedef struct { 129 struct ubus_request request; 130 struct uloop_timeout timeout; 131 struct ubus_context *ctx; 132 size_t registry_index; 133 bool complete; 134 uc_vm_t *vm; 135 uc_value_t *callback; 136 uc_value_t *response; 137 } uc_ubus_deferred_t; 138 139 typedef struct { 140 struct ubus_object obj; 141 struct ubus_context *ctx; 142 size_t registry_index; 143 uc_vm_t *vm; 144 } uc_ubus_object_t; 145 146 typedef struct { 147 struct ubus_request_data req; 148 struct uloop_timeout timeout; 149 struct ubus_context *ctx; 150 size_t registry_index; 151 bool deferred; 152 bool replied; 153 uc_vm_t *vm; 154 } uc_ubus_request_t; 155 156 typedef struct { 157 struct ubus_notify_request req; 158 struct ubus_context *ctx; 159 size_t registry_index; 160 bool complete; 161 uc_vm_t *vm; 162 } uc_ubus_notify_t; 163 164 typedef struct { 165 struct ubus_event_handler ev; 166 struct ubus_context *ctx; 167 size_t registry_index; 168 uc_vm_t *vm; 169 } uc_ubus_listener_t; 170 171 typedef struct { 172 struct ubus_subscriber sub; 173 struct ubus_context *ctx; 174 size_t registry_index; 175 uc_vm_t *vm; 176 } uc_ubus_subscriber_t; 177 178 typedef struct { 179 bool mret; 180 uc_value_t *res; 181 } uc_ubus_call_res_t; 182 183 static uc_value_t * 184 uc_ubus_error(uc_vm_t *vm, size_t nargs) 185 { 186 uc_value_t *numeric = uc_fn_arg(0), *rv; 187 uc_stringbuf_t *buf; 188 const char *s; 189 190 if (last_error.code == 0) 191 return NULL; 192 193 if (ucv_is_truish(numeric)) { 194 rv = ucv_int64_new(last_error.code); 195 } 196 else { 197 buf = ucv_stringbuf_new(); 198 199 if (last_error.code == UBUS_STATUS_UNKNOWN_ERROR && last_error.msg) { 200 ucv_stringbuf_addstr(buf, last_error.msg, strlen(last_error.msg)); 201 } 202 else { 203 s = ubus_strerror(last_error.code); 204 205 ucv_stringbuf_addstr(buf, s, strlen(s)); 206 207 if (last_error.msg) 208 ucv_stringbuf_printf(buf, ": %s", last_error.msg); 209 } 210 211 rv = ucv_stringbuf_finish(buf); 212 } 213 214 set_error(0, NULL); 215 216 return rv; 217 } 218 219 static void 220 _uc_reg_get(uc_vm_t *vm, const char *key, size_t idx, size_t nptrs, ...) 221 { 222 uc_value_t *reg = uc_vm_registry_get(vm, key), **val; 223 va_list ap; 224 size_t i; 225 226 va_start(ap, nptrs); 227 228 for (i = 0; i < nptrs; i++) { 229 val = va_arg(ap, uc_value_t **); 230 231 if (val) 232 *val = ucv_array_get(reg, idx + i); 233 } 234 235 va_end(ap); 236 } 237 238 static size_t 239 _uc_reg_add(uc_vm_t *vm, const char *key, size_t nptrs, ...) 240 { 241 uc_value_t *reg = uc_vm_registry_get(vm, key); 242 size_t idx, i; 243 va_list ap; 244 245 if (!reg) { 246 reg = ucv_array_new(vm); 247 uc_vm_registry_set(vm, key, reg); 248 } 249 250 va_start(ap, nptrs); 251 252 for (idx = 0;; idx += nptrs) { 253 if (ucv_array_get(reg, idx) == NULL) { 254 for (i = 0; i < nptrs; i++) 255 ucv_array_set(reg, idx + i, va_arg(ap, uc_value_t *)); 256 257 break; 258 } 259 } 260 261 va_end(ap); 262 263 return idx; 264 } 265 266 static void 267 _uc_reg_clear(uc_vm_t *vm, const char *key, size_t idx, size_t nptrs) 268 { 269 uc_value_t *reg = uc_vm_registry_get(vm, key); 270 271 while (nptrs > 0) { 272 nptrs--; 273 ucv_array_set(reg, idx + nptrs, NULL); 274 } 275 } 276 277 278 #define request_reg_add(vm, request, cb, conn) \ 279 _uc_reg_add(vm, "ubus.requests", 3, request, cb, conn) 280 281 #define request_reg_get(vm, idx, request, cb) \ 282 _uc_reg_get(vm, "ubus.requests", idx, 2, request, cb) 283 284 #define request_reg_clear(vm, idx) \ 285 _uc_reg_clear(vm, "ubus.requests", idx, 3) 286 287 288 #define object_reg_add(vm, obj, msg, cb) \ 289 _uc_reg_add(vm, "ubus.objects", 3, obj, msg, cb) 290 291 #define object_reg_get(vm, idx, obj, msg, cb) \ 292 _uc_reg_get(vm, "ubus.objects", idx, 3, obj, msg, cb) 293 294 #define object_reg_clear(vm, idx) \ 295 _uc_reg_clear(vm, "ubus.objects", idx, 3) 296 297 298 #define notify_reg_add(vm, notify, dcb, scb, ccb) \ 299 _uc_reg_add(vm, "ubus.notifications", 4, notify, dcb, scb, ccb) 300 301 #define notify_reg_get(vm, idx, notify, dcb, scb, ccb) \ 302 _uc_reg_get(vm, "ubus.notifications", idx, 4, notify, dcb, scb, ccb) 303 304 #define notify_reg_clear(vm, idx) \ 305 _uc_reg_clear(vm, "ubus.notifications", idx, 4) 306 307 308 #define listener_reg_add(vm, listener, cb) \ 309 _uc_reg_add(vm, "ubus.listeners", 2, listener, cb) 310 311 #define listener_reg_get(vm, idx, listener, cb) \ 312 _uc_reg_get(vm, "ubus.listeners", idx, 2, listener, cb) 313 314 #define listener_reg_clear(vm, idx) \ 315 _uc_reg_clear(vm, "ubus.listeners", idx, 2) 316 317 318 #define subscriber_reg_add(vm, subscriber, ncb, rcb) \ 319 _uc_reg_add(vm, "ubus.subscribers", 3, subscriber, ncb, rcb) 320 321 #define subscriber_reg_get(vm, idx, subscriber, ncb, rcb) \ 322 _uc_reg_get(vm, "ubus.subscribers", idx, 3, subscriber, ncb, rcb) 323 324 #define subscriber_reg_clear(vm, idx) \ 325 _uc_reg_clear(vm, "ubus.subscribers", idx, 3) 326 327 328 static uc_value_t * 329 blob_to_ucv(uc_vm_t *vm, struct blob_attr *attr, bool table, const char **name); 330 331 static uc_value_t * 332 blob_array_to_ucv(uc_vm_t *vm, struct blob_attr *attr, size_t len, bool table) 333 { 334 uc_value_t *o = table ? ucv_object_new(vm) : ucv_array_new(vm); 335 uc_value_t *v; 336 struct blob_attr *pos; 337 size_t rem = len; 338 const char *name; 339 340 if (!o) 341 return NULL; 342 343 __blob_for_each_attr(pos, attr, rem) { 344 name = NULL; 345 v = blob_to_ucv(vm, pos, table, &name); 346 347 if (table && name) 348 ucv_object_add(o, name, v); 349 else if (!table) 350 ucv_array_push(o, v); 351 else 352 ucv_put(v); 353 } 354 355 return o; 356 } 357 358 static uc_value_t * 359 blob_to_ucv(uc_vm_t *vm, struct blob_attr *attr, bool table, const char **name) 360 { 361 void *data; 362 int len; 363 364 if (!blobmsg_check_attr(attr, false)) 365 return NULL; 366 367 if (table && blobmsg_name(attr)[0]) 368 *name = blobmsg_name(attr); 369 370 data = blobmsg_data(attr); 371 len = blobmsg_data_len(attr); 372 373 switch (blob_id(attr)) { 374 case BLOBMSG_TYPE_BOOL: 375 return ucv_boolean_new(*(uint8_t *)data); 376 377 case BLOBMSG_TYPE_INT16: 378 return ucv_int64_new((int16_t)be16_to_cpu(*(uint16_t *)data)); 379 380 case BLOBMSG_TYPE_INT32: 381 return ucv_int64_new((int32_t)be32_to_cpu(*(uint32_t *)data)); 382 383 case BLOBMSG_TYPE_INT64: 384 return ucv_int64_new((int64_t)be64_to_cpu(*(uint64_t *)data)); 385 386 case BLOBMSG_TYPE_DOUBLE: 387 ; 388 union { 389 double d; 390 uint64_t u64; 391 } v; 392 393 v.u64 = be64_to_cpu(*(uint64_t *)data); 394 395 return ucv_double_new(v.d); 396 397 case BLOBMSG_TYPE_STRING: 398 return ucv_string_new_length(data, len - 1); 399 400 case BLOBMSG_TYPE_ARRAY: 401 return blob_array_to_ucv(vm, data, len, false); 402 403 case BLOBMSG_TYPE_TABLE: 404 return blob_array_to_ucv(vm, data, len, true); 405 406 default: 407 return NULL; 408 } 409 } 410 411 static void 412 ucv_array_to_blob(uc_value_t *val, struct blob_buf *blob); 413 414 static void 415 ucv_object_to_blob(uc_value_t *val, struct blob_buf *blob); 416 417 static void 418 ucv_to_blob(const char *name, uc_value_t *val, struct blob_buf *blob) 419 { 420 int64_t n; 421 void *c; 422 423 switch (ucv_type(val)) { 424 case UC_NULL: 425 blobmsg_add_field(blob, BLOBMSG_TYPE_UNSPEC, name, NULL, 0); 426 break; 427 428 case UC_BOOLEAN: 429 blobmsg_add_u8(blob, name, ucv_boolean_get(val)); 430 break; 431 432 case UC_INTEGER: 433 n = ucv_int64_get(val); 434 435 if (errno == ERANGE) 436 blobmsg_add_u64(blob, name, ucv_uint64_get(val)); 437 else if (n >= INT32_MIN && n <= INT32_MAX) 438 blobmsg_add_u32(blob, name, n); 439 else 440 blobmsg_add_u64(blob, name, n); 441 442 break; 443 444 case UC_DOUBLE: 445 blobmsg_add_double(blob, name, ucv_double_get(val)); 446 break; 447 448 case UC_STRING: 449 blobmsg_add_field(blob, BLOBMSG_TYPE_STRING, name, 450 ucv_string_get(val), ucv_string_length(val) + 1); 451 break; 452 453 case UC_ARRAY: 454 c = blobmsg_open_array(blob, name); 455 ucv_array_to_blob(val, blob); 456 blobmsg_close_array(blob, c); 457 break; 458 459 case UC_OBJECT: 460 c = blobmsg_open_table(blob, name); 461 ucv_object_to_blob(val, blob); 462 blobmsg_close_table(blob, c); 463 break; 464 465 default: 466 break; 467 } 468 } 469 470 static void 471 ucv_array_to_blob(uc_value_t *val, struct blob_buf *blob) 472 { 473 size_t i; 474 475 for (i = 0; i < ucv_array_length(val); i++) 476 ucv_to_blob(NULL, ucv_array_get(val, i), blob); 477 } 478 479 static void 480 ucv_object_to_blob(uc_value_t *val, struct blob_buf *blob) 481 { 482 ucv_object_foreach(val, k, v) 483 ucv_to_blob(k, v, blob); 484 } 485 486 487 static uc_value_t * 488 uc_ubus_connect(uc_vm_t *vm, size_t nargs) 489 { 490 uc_value_t *socket, *timeout; 491 uc_ubus_connection_t *c; 492 493 args_get(vm, nargs, 494 "socket", UC_STRING, true, &socket, 495 "timeout", UC_INTEGER, true, &timeout); 496 497 c = xalloc(sizeof(*c)); 498 c->timeout = timeout ? ucv_int64_get(timeout) : 30; 499 500 if (ubus_connect_ctx(&c->ctx, socket ? ucv_string_get(socket) : NULL)) { 501 free(c); 502 err_return(UBUS_STATUS_UNKNOWN_ERROR, "Unable to connect to ubus socket"); 503 } 504 505 if (c->timeout < 0) 506 c->timeout = 30; 507 508 ubus_add_uloop(&c->ctx); 509 510 ok_return(uc_resource_new(conn_type, c)); 511 } 512 513 static void 514 uc_ubus_signatures_cb(struct ubus_context *c, struct ubus_object_data *o, void *p) 515 { 516 uc_value_t *arr = p; 517 uc_value_t *sig; 518 519 if (!o->signature) 520 return; 521 522 sig = blob_array_to_ucv(NULL, blob_data(o->signature), blob_len(o->signature), true); 523 524 if (sig) 525 ucv_array_push(arr, sig); 526 } 527 528 static void 529 uc_ubus_objects_cb(struct ubus_context *c, struct ubus_object_data *o, void *p) 530 { 531 uc_value_t *arr = p; 532 533 ucv_array_push(arr, ucv_string_new(o->path)); 534 } 535 536 static bool 537 _conn_get(uc_vm_t *vm, uc_ubus_connection_t **conn) 538 { 539 uc_ubus_connection_t *c = uc_fn_thisval("ubus.connection"); 540 541 if (!c) 542 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid connection context"); 543 544 if (c->ctx.sock.fd < 0) 545 err_return(UBUS_STATUS_CONNECTION_FAILED, "Connection is closed"); 546 547 *conn = c; 548 549 ok_return(true); 550 } 551 552 #define conn_get(vm, ptr) do { if (!_conn_get(vm, ptr)) return NULL; } while(0) 553 554 static uc_value_t * 555 uc_ubus_list(uc_vm_t *vm, size_t nargs) 556 { 557 uc_ubus_connection_t *c; 558 uc_value_t *objname, *res = NULL; 559 enum ubus_msg_status rv; 560 561 conn_get(vm, &c); 562 563 args_get(vm, nargs, 564 "object name", UC_STRING, true, &objname); 565 566 res = ucv_array_new(vm); 567 568 rv = ubus_lookup(&c->ctx, 569 objname ? ucv_string_get(objname) : NULL, 570 objname ? uc_ubus_signatures_cb : uc_ubus_objects_cb, 571 res); 572 573 if (rv != UBUS_STATUS_OK) { 574 ucv_put(res); 575 err_return(rv, NULL); 576 } 577 578 ok_return(res); 579 } 580 581 static void 582 uc_ubus_call_cb(struct ubus_request *req, int type, struct blob_attr *msg) 583 { 584 uc_ubus_call_res_t *res = req->priv; 585 uc_value_t *val; 586 587 val = msg ? blob_array_to_ucv(NULL, blob_data(msg), blob_len(msg), true) : NULL; 588 589 if (res->mret) { 590 if (!res->res) 591 res->res = ucv_array_new(NULL); 592 593 ucv_array_push(res->res, val); 594 } 595 else if (!res->res) { 596 res->res = val; 597 } 598 } 599 600 static void 601 uc_ubus_call_user_cb(uc_ubus_deferred_t *defer, int ret, uc_value_t *reply) 602 { 603 uc_value_t *this, *func; 604 605 request_reg_get(defer->vm, defer->registry_index, &this, &func); 606 607 if (ucv_is_callable(func)) { 608 uc_vm_stack_push(defer->vm, ucv_get(this)); 609 uc_vm_stack_push(defer->vm, ucv_get(func)); 610 uc_vm_stack_push(defer->vm, ucv_int64_new(ret)); 611 uc_vm_stack_push(defer->vm, ucv_get(reply)); 612 613 if (uc_vm_call(defer->vm, true, 2) == EXCEPTION_NONE) 614 ucv_put(uc_vm_stack_pop(defer->vm)); 615 } 616 617 request_reg_clear(defer->vm, defer->registry_index); 618 619 n_cb_active--; 620 621 if (have_own_uloop && n_cb_active == 0) 622 uloop_end(); 623 } 624 625 static void 626 uc_ubus_call_data_cb(struct ubus_request *req, int type, struct blob_attr *msg) 627 { 628 uc_ubus_deferred_t *defer = container_of(req, uc_ubus_deferred_t, request); 629 630 if (defer->response == NULL) 631 defer->response = blob_array_to_ucv(defer->vm, blob_data(msg), blob_len(msg), true); 632 } 633 634 static void 635 uc_ubus_call_done_cb(struct ubus_request *req, int ret) 636 { 637 uc_ubus_deferred_t *defer = container_of(req, uc_ubus_deferred_t, request); 638 639 if (defer->complete) 640 return; 641 642 defer->complete = true; 643 uloop_timeout_cancel(&defer->timeout); 644 645 uc_ubus_call_user_cb(defer, ret, defer->response); 646 } 647 648 static void 649 uc_ubus_call_timeout_cb(struct uloop_timeout *timeout) 650 { 651 uc_ubus_deferred_t *defer = container_of(timeout, uc_ubus_deferred_t, timeout); 652 653 if (defer->complete) 654 return; 655 656 defer->complete = true; 657 ubus_abort_request(defer->ctx, &defer->request); 658 659 uc_ubus_call_user_cb(defer, UBUS_STATUS_TIMEOUT, NULL); 660 } 661 662 static bool 663 uc_ubus_have_uloop(void) 664 { 665 bool prev = uloop_cancelled; 666 bool active; 667 668 #ifdef HAVE_ULOOP_FD_SET_CB 669 if (uloop_fd_set_cb) 670 return true; 671 #endif 672 673 uloop_cancelled = true; 674 active = uloop_cancelling(); 675 uloop_cancelled = prev; 676 677 return active; 678 } 679 680 static uc_value_t * 681 uc_ubus_call(uc_vm_t *vm, size_t nargs) 682 { 683 uc_value_t *objname, *funname, *funargs, *mret = NULL; 684 uc_ubus_call_res_t res = { 0 }; 685 uc_ubus_connection_t *c; 686 enum ubus_msg_status rv; 687 uint32_t id; 688 689 conn_get(vm, &c); 690 691 args_get(vm, nargs, 692 "object name", UC_STRING, false, &objname, 693 "function name", UC_STRING, false, &funname, 694 "function arguments", UC_OBJECT, true, &funargs, 695 "multiple return", UC_BOOLEAN, true, &mret); 696 697 blob_buf_init(&c->buf, 0); 698 699 if (funargs) 700 ucv_object_to_blob(funargs, &c->buf); 701 702 rv = ubus_lookup_id(&c->ctx, ucv_string_get(objname), &id); 703 704 if (rv != UBUS_STATUS_OK) 705 err_return(rv, "Failed to resolve object name '%s'", 706 ucv_string_get(objname)); 707 708 res.mret = ucv_is_truish(mret); 709 710 rv = ubus_invoke(&c->ctx, id, ucv_string_get(funname), c->buf.head, 711 uc_ubus_call_cb, &res, c->timeout * 1000); 712 713 if (rv != UBUS_STATUS_OK) 714 err_return(rv, "Failed to invoke function '%s' on object '%s'", 715 ucv_string_get(funname), ucv_string_get(objname)); 716 717 ok_return(res.res); 718 } 719 720 static uc_value_t * 721 uc_ubus_defer(uc_vm_t *vm, size_t nargs) 722 { 723 uc_value_t *objname, *funname, *funargs, *replycb, *conn, *res = NULL; 724 uc_ubus_deferred_t *defer; 725 uc_ubus_connection_t *c; 726 enum ubus_msg_status rv; 727 uc_callframe_t *frame; 728 uint32_t id; 729 730 conn_get(vm, &c); 731 732 args_get(vm, nargs, 733 "object name", UC_STRING, false, &objname, 734 "function name", UC_STRING, false, &funname, 735 "function arguments", UC_OBJECT, true, &funargs, 736 "reply callback", UC_CLOSURE, true, &replycb); 737 738 blob_buf_init(&c->buf, 0); 739 740 if (funargs) 741 ucv_object_to_blob(funargs, &c->buf); 742 743 rv = ubus_lookup_id(&c->ctx, ucv_string_get(objname), &id); 744 745 if (rv != UBUS_STATUS_OK) 746 err_return(rv, "Failed to resolve object name '%s'", 747 ucv_string_get(objname)); 748 749 defer = xalloc(sizeof(*defer)); 750 751 rv = ubus_invoke_async(&c->ctx, id, ucv_string_get(funname), 752 c->buf.head, &defer->request); 753 754 if (rv == UBUS_STATUS_OK) { 755 defer->vm = vm; 756 defer->ctx = &c->ctx; 757 758 defer->request.data_cb = uc_ubus_call_data_cb; 759 defer->request.complete_cb = uc_ubus_call_done_cb; 760 ubus_complete_request_async(&c->ctx, &defer->request); 761 762 defer->timeout.cb = uc_ubus_call_timeout_cb; 763 uloop_timeout_set(&defer->timeout, c->timeout * 1000); 764 765 res = uc_resource_new(defer_type, defer); 766 frame = uc_vector_last(&vm->callframes); 767 conn = frame ? frame->ctx : NULL; 768 769 defer->registry_index = request_reg_add(vm, ucv_get(res), ucv_get(replycb), ucv_get(conn)); 770 771 if (!uc_ubus_have_uloop()) { 772 have_own_uloop = true; 773 uloop_run(); 774 } 775 } 776 else { 777 uc_vm_stack_push(vm, ucv_get(replycb)); 778 uc_vm_stack_push(vm, ucv_int64_new(rv)); 779 780 if (uc_vm_call(vm, false, 1) == EXCEPTION_NONE) 781 ucv_put(uc_vm_stack_pop(vm)); 782 else 783 uloop_end(); 784 785 free(defer); 786 } 787 788 if (rv != UBUS_STATUS_OK) 789 err_return(rv, "Failed to invoke function '%s' on object '%s'", 790 ucv_string_get(funname), ucv_string_get(objname)); 791 792 ok_return(res); 793 } 794 795 796 /* 797 * ubus object request context functions 798 * -------------------------------------------------------------------------- 799 */ 800 801 static void 802 uc_ubus_request_finish(uc_ubus_request_t *callctx, int code, uc_value_t *reply) 803 { 804 if (callctx->replied) 805 return; 806 807 if (reply) { 808 blob_buf_init(&buf, 0); 809 ucv_object_to_blob(reply, &buf); 810 ubus_send_reply(callctx->ctx, &callctx->req, buf.head); 811 } 812 813 callctx->replied = true; 814 815 ubus_complete_deferred_request(callctx->ctx, &callctx->req, code); 816 request_reg_clear(callctx->vm, callctx->registry_index); 817 } 818 819 static void 820 uc_ubus_request_timeout(struct uloop_timeout *timeout) 821 { 822 uc_ubus_request_t *callctx = container_of(timeout, uc_ubus_request_t, timeout); 823 824 uc_ubus_request_finish(callctx, UBUS_STATUS_TIMEOUT, NULL); 825 } 826 827 static uc_value_t * 828 uc_ubus_request_reply(uc_vm_t *vm, size_t nargs) 829 { 830 uc_ubus_request_t **callctx = uc_fn_this("ubus.request"); 831 int64_t code = UBUS_STATUS_OK; 832 uc_value_t *reply, *rcode; 833 834 if (!callctx || !*callctx) 835 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid call context"); 836 837 args_get(vm, nargs, 838 "reply", UC_OBJECT, true, &reply, 839 "rcode", UC_INTEGER, true, &rcode); 840 841 if ((*callctx)->replied) 842 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Reply has already been sent"); 843 844 if (rcode) { 845 code = ucv_int64_get(rcode); 846 847 if (errno == ERANGE || code < 0 || code > __UBUS_STATUS_LAST) 848 code = UBUS_STATUS_UNKNOWN_ERROR; 849 } 850 851 uc_ubus_request_finish(*callctx, code, reply); 852 853 ok_return(ucv_boolean_new(true)); 854 } 855 856 static uc_value_t * 857 uc_ubus_request_defer(uc_vm_t *vm, size_t nargs) 858 { 859 uc_ubus_request_t *callctx = uc_fn_thisval("ubus.request"); 860 861 if (!callctx) 862 return NULL; 863 864 callctx->deferred = true; 865 return ucv_boolean_new(true); 866 } 867 868 static uc_value_t * 869 uc_ubus_request_error(uc_vm_t *vm, size_t nargs) 870 { 871 uc_ubus_request_t **callctx = uc_fn_this("ubus.request"); 872 uc_value_t *rcode = uc_fn_arg(0); 873 int64_t code; 874 875 if (!callctx || !*callctx) 876 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid call context"); 877 878 args_get(vm, nargs, 879 "rcode", UC_INTEGER, false, &rcode); 880 881 if ((*callctx)->replied) 882 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Reply has already been sent"); 883 884 code = ucv_int64_get(rcode); 885 886 if (errno == ERANGE || code < 0 || code > __UBUS_STATUS_LAST) 887 code = UBUS_STATUS_UNKNOWN_ERROR; 888 889 uc_ubus_request_finish(*callctx, code, NULL); 890 891 ok_return(ucv_boolean_new(true)); 892 } 893 894 895 /* 896 * ubus object notify 897 * -------------------------------------------------------------------------- 898 */ 899 900 static uc_value_t * 901 uc_ubus_notify_completed(uc_vm_t *vm, size_t nargs) 902 { 903 uc_ubus_notify_t **notifyctx = uc_fn_this("ubus.notify"); 904 905 if (!notifyctx || !*notifyctx) 906 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid notify context"); 907 908 ok_return(ucv_boolean_new((*notifyctx)->complete)); 909 } 910 911 static uc_value_t * 912 uc_ubus_notify_abort(uc_vm_t *vm, size_t nargs) 913 { 914 uc_ubus_notify_t **notifyctx = uc_fn_this("ubus.notify"); 915 916 if (!notifyctx || !*notifyctx) 917 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid notify context"); 918 919 if ((*notifyctx)->complete) 920 ok_return(ucv_boolean_new(false)); 921 922 ubus_abort_request((*notifyctx)->ctx, &(*notifyctx)->req.req); 923 (*notifyctx)->complete = true; 924 925 ok_return(ucv_boolean_new(true)); 926 } 927 928 static void 929 uc_ubus_object_notify_data_cb(struct ubus_notify_request *req, int type, struct blob_attr *msg) 930 { 931 uc_ubus_notify_t *notifyctx = (uc_ubus_notify_t *)req; 932 uc_value_t *this, *func; 933 934 notify_reg_get(notifyctx->vm, notifyctx->registry_index, &this, &func, NULL, NULL); 935 936 if (ucv_is_callable(func)) { 937 uc_vm_stack_push(notifyctx->vm, ucv_get(this)); 938 uc_vm_stack_push(notifyctx->vm, ucv_get(func)); 939 uc_vm_stack_push(notifyctx->vm, ucv_int64_new(type)); 940 uc_vm_stack_push(notifyctx->vm, blob_array_to_ucv(notifyctx->vm, blob_data(msg), blob_len(msg), true)); 941 942 if (uc_vm_call(notifyctx->vm, true, 2) == EXCEPTION_NONE) 943 ucv_put(uc_vm_stack_pop(notifyctx->vm)); 944 else 945 uloop_end(); 946 } 947 } 948 949 static void 950 uc_ubus_object_notify_status_cb(struct ubus_notify_request *req, int idx, int ret) 951 { 952 uc_ubus_notify_t *notifyctx = (uc_ubus_notify_t *)req; 953 uc_value_t *this, *func; 954 955 notify_reg_get(notifyctx->vm, notifyctx->registry_index, &this, NULL, &func, NULL); 956 957 if (ucv_is_callable(func)) { 958 uc_vm_stack_push(notifyctx->vm, ucv_get(this)); 959 uc_vm_stack_push(notifyctx->vm, ucv_get(func)); 960 uc_vm_stack_push(notifyctx->vm, ucv_int64_new(idx)); 961 uc_vm_stack_push(notifyctx->vm, ucv_int64_new(ret)); 962 963 if (uc_vm_call(notifyctx->vm, true, 2) == EXCEPTION_NONE) 964 ucv_put(uc_vm_stack_pop(notifyctx->vm)); 965 else 966 uloop_end(); 967 } 968 } 969 970 static void 971 uc_ubus_object_notify_complete_cb(struct ubus_notify_request *req, int idx, int ret) 972 { 973 uc_ubus_notify_t *notifyctx = (uc_ubus_notify_t *)req; 974 uc_value_t *this, *func; 975 976 notify_reg_get(notifyctx->vm, notifyctx->registry_index, &this, NULL, NULL, &func); 977 978 if (ucv_is_callable(func)) { 979 uc_vm_stack_push(notifyctx->vm, ucv_get(this)); 980 uc_vm_stack_push(notifyctx->vm, ucv_get(func)); 981 uc_vm_stack_push(notifyctx->vm, ucv_int64_new(idx)); 982 uc_vm_stack_push(notifyctx->vm, ucv_int64_new(ret)); 983 984 if (uc_vm_call(notifyctx->vm, true, 2) == EXCEPTION_NONE) 985 ucv_put(uc_vm_stack_pop(notifyctx->vm)); 986 else 987 uloop_end(); 988 } 989 990 notifyctx->complete = true; 991 992 notify_reg_clear(notifyctx->vm, notifyctx->registry_index); 993 } 994 995 static uc_value_t * 996 uc_ubus_object_notify(uc_vm_t *vm, size_t nargs) 997 { 998 uc_value_t *typename, *message, *data_cb, *status_cb, *complete_cb, *timeout; 999 uc_ubus_object_t **uuobj = uc_fn_this("ubus.object"); 1000 uc_ubus_notify_t *notifyctx; 1001 uc_value_t *res; 1002 int64_t t; 1003 int rv; 1004 1005 if (!uuobj || !*uuobj) 1006 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid object context"); 1007 1008 args_get(vm, nargs, 1009 "typename", UC_STRING, false, &typename, 1010 "message", UC_OBJECT, true, &message, 1011 "data callback", UC_CLOSURE, true, &data_cb, 1012 "status callback", UC_CLOSURE, true, &status_cb, 1013 "completion callback", UC_CLOSURE, true, &complete_cb, 1014 "timeout", UC_INTEGER, true, &timeout); 1015 1016 t = timeout ? ucv_int64_get(timeout) : -1; 1017 1018 if (errno) 1019 err_return(UBUS_STATUS_INVALID_ARGUMENT, 1020 "Invalid timeout value: %s", strerror(errno)); 1021 1022 notifyctx = xalloc(sizeof(*notifyctx)); 1023 notifyctx->vm = vm; 1024 notifyctx->ctx = (*uuobj)->ctx; 1025 1026 blob_buf_init(&buf, 0); 1027 1028 if (message) 1029 ucv_object_to_blob(message, &buf); 1030 1031 rv = ubus_notify_async((*uuobj)->ctx, &(*uuobj)->obj, 1032 ucv_string_get(typename), buf.head, 1033 ¬ifyctx->req); 1034 1035 if (rv != UBUS_STATUS_OK) { 1036 free(notifyctx); 1037 err_return(rv, "Failed to send notification"); 1038 } 1039 1040 notifyctx->req.data_cb = uc_ubus_object_notify_data_cb; 1041 notifyctx->req.status_cb = uc_ubus_object_notify_status_cb; 1042 notifyctx->req.complete_cb = uc_ubus_object_notify_complete_cb; 1043 1044 res = uc_resource_new(notify_type, notifyctx); 1045 1046 notifyctx->registry_index = notify_reg_add(vm, 1047 ucv_get(res), ucv_get(data_cb), ucv_get(status_cb), ucv_get(complete_cb)); 1048 1049 if (t >= 0) { 1050 rv = ubus_complete_request((*uuobj)->ctx, ¬ifyctx->req.req, t); 1051 1052 notify_reg_clear(vm, notifyctx->registry_index); 1053 1054 ucv_put(res); 1055 1056 ok_return(ucv_int64_new(rv)); 1057 } 1058 1059 ubus_complete_request_async((*uuobj)->ctx, ¬ifyctx->req.req); 1060 1061 ok_return(res); 1062 } 1063 1064 1065 /* 1066 * ubus object remove 1067 * -------------------------------------------------------------------------- 1068 */ 1069 1070 static int 1071 uc_ubus_object_remove_common(uc_ubus_object_t *uuobj) 1072 { 1073 int rv = ubus_remove_object(uuobj->ctx, &uuobj->obj); 1074 1075 if (rv == UBUS_STATUS_OK) 1076 object_reg_clear(uuobj->vm, uuobj->registry_index); 1077 1078 return rv; 1079 } 1080 1081 static uc_value_t * 1082 uc_ubus_object_remove(uc_vm_t *vm, size_t nargs) 1083 { 1084 uc_ubus_object_t **uuobj = uc_fn_this("ubus.object"); 1085 int rv; 1086 1087 if (!uuobj || !*uuobj) 1088 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid object context"); 1089 1090 rv = uc_ubus_object_remove_common(*uuobj); 1091 1092 if (rv != UBUS_STATUS_OK) 1093 err_return(rv, "Failed to remove object"); 1094 1095 ok_return(ucv_boolean_new(true)); 1096 } 1097 1098 1099 /* 1100 * ubus object subscription status 1101 */ 1102 1103 static uc_value_t * 1104 uc_ubus_object_subscribed(uc_vm_t *vm, size_t nargs) 1105 { 1106 uc_ubus_object_t **uuobj = uc_fn_this("ubus.object"); 1107 1108 if (!uuobj || !*uuobj) 1109 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid object context"); 1110 1111 ok_return(ucv_boolean_new((*uuobj)->obj.has_subscribers)); 1112 } 1113 1114 1115 /* 1116 * ubus object method call handling 1117 * -------------------------------------------------------------------------- 1118 */ 1119 1120 static int 1121 uc_ubus_object_call_args(struct ubus_object *obj, const char *ubus_method_name, 1122 struct blob_attr *msg, uc_value_t **res) 1123 { 1124 uc_ubus_object_t *uuobj = (uc_ubus_object_t *)obj; 1125 const struct ubus_method *method = NULL; 1126 const struct blobmsg_hdr *hdr; 1127 struct blob_attr *attr; 1128 size_t len; 1129 bool found; 1130 int i; 1131 1132 for (i = 0; i < obj->n_methods; i++) { 1133 if (!strcmp(obj->methods[i].name, ubus_method_name)) { 1134 method = &obj->methods[i]; 1135 break; 1136 } 1137 } 1138 1139 if (!method) 1140 return UBUS_STATUS_METHOD_NOT_FOUND; 1141 1142 len = blob_len(msg); 1143 1144 __blob_for_each_attr(attr, blob_data(msg), len) { 1145 if (!blobmsg_check_attr_len(attr, false, len)) 1146 return UBUS_STATUS_INVALID_ARGUMENT; 1147 1148 if (!blob_is_extended(attr)) 1149 return UBUS_STATUS_INVALID_ARGUMENT; 1150 1151 hdr = blob_data(attr); 1152 found = false; 1153 1154 for (i = 0; i < method->n_policy; i++) { 1155 if (blobmsg_namelen(hdr) != strlen(method->policy[i].name)) 1156 continue; 1157 1158 if (strcmp(method->policy[i].name, (char *)hdr->name)) 1159 continue; 1160 1161 /* named argument found but wrong type */ 1162 if (blob_id(attr) != method->policy[i].type) 1163 goto inval; 1164 1165 found = true; 1166 break; 1167 } 1168 1169 /* named argument not found in policy */ 1170 if (!found) 1171 goto inval; 1172 } 1173 1174 *res = blob_array_to_ucv(uuobj->vm, blob_data(msg), blob_len(msg), true); 1175 1176 return UBUS_STATUS_OK; 1177 1178 inval: 1179 *res = NULL; 1180 1181 return UBUS_STATUS_INVALID_ARGUMENT; 1182 } 1183 1184 static uc_value_t * 1185 uc_ubus_object_call_info(uc_vm_t *vm, 1186 struct ubus_context *ctx, struct ubus_request_data *req, 1187 struct ubus_object *obj, const char *ubus_method_name) 1188 { 1189 uc_value_t *info, *o; 1190 1191 info = ucv_object_new(vm); 1192 1193 o = ucv_object_new(vm); 1194 1195 ucv_object_add(o, "user", ucv_string_new(req->acl.user)); 1196 ucv_object_add(o, "group", ucv_string_new(req->acl.group)); 1197 1198 if (req->acl.object) 1199 ucv_object_add(o, "object", ucv_string_new(req->acl.object)); 1200 1201 ucv_object_add(info, "acl", o); 1202 1203 o = ucv_object_new(vm); 1204 1205 ucv_object_add(o, "id", ucv_int64_new(obj->id)); 1206 1207 if (obj->name) 1208 ucv_object_add(o, "name", ucv_string_new(obj->name)); 1209 1210 if (obj->path) 1211 ucv_object_add(o, "path", ucv_string_new(obj->path)); 1212 1213 ucv_object_add(info, "object", o); 1214 1215 if (ubus_method_name) 1216 ucv_object_add(info, "method", ucv_string_new(ubus_method_name)); 1217 1218 return info; 1219 } 1220 1221 static int 1222 uc_ubus_handle_reply_common(struct ubus_context *ctx, 1223 struct ubus_request_data *req, 1224 uc_vm_t *vm, uc_value_t *this, uc_value_t *func, 1225 uc_value_t *reqproto) 1226 { 1227 uc_ubus_request_t *callctx; 1228 uc_value_t *reqobj, *res; 1229 int rv; 1230 1231 /* allocate deferred method call context */ 1232 callctx = xalloc(sizeof(*callctx)); 1233 callctx->ctx = ctx; 1234 callctx->vm = vm; 1235 1236 ubus_defer_request(ctx, req, &callctx->req); 1237 1238 /* create ucode request type object and set properties */ 1239 reqobj = uc_resource_new(request_type, callctx); 1240 1241 if (reqproto) 1242 ucv_prototype_set(ucv_prototype_get(reqobj), reqproto); 1243 1244 /* push object context, handler and request object onto stack */ 1245 uc_vm_stack_push(vm, ucv_get(this)); 1246 uc_vm_stack_push(vm, ucv_get(func)); 1247 uc_vm_stack_push(vm, ucv_get(reqobj)); 1248 1249 /* execute request handler function */ 1250 switch (uc_vm_call(vm, true, 1)) { 1251 case EXCEPTION_NONE: 1252 res = uc_vm_stack_pop(vm); 1253 1254 /* The handler function invoked a nested aync ubus request and returned it */ 1255 if (ucv_resource_dataptr(res, "ubus.deferred")) { 1256 /* Install guard timer in case the reply callback is never called */ 1257 callctx->timeout.cb = uc_ubus_request_timeout; 1258 uloop_timeout_set(&callctx->timeout, 10000 /* FIXME */); 1259 1260 /* Add wrapped request context into registry to prevent GC'ing 1261 * until reply or timeout occurred */ 1262 callctx->registry_index = request_reg_add(vm, ucv_get(reqobj), NULL, NULL); 1263 } 1264 1265 /* Otherwise, when the function returned an object, treat it as 1266 * reply data and conclude deferred request immediately */ 1267 else if (ucv_type(res) == UC_OBJECT) { 1268 blob_buf_init(&buf, 0); 1269 ucv_object_to_blob(res, &buf); 1270 ubus_send_reply(ctx, &callctx->req, buf.head); 1271 1272 ubus_complete_deferred_request(ctx, &callctx->req, UBUS_STATUS_OK); 1273 callctx->replied = true; 1274 } 1275 1276 /* If neither a deferred ubus request, nor a plain object were 1277 * returned and if reqobj.reply() hasn't been called, immediately 1278 * finish deferred request with UBUS_STATUS_NO_DATA. */ 1279 else if (!callctx->replied && !callctx->deferred) { 1280 rv = UBUS_STATUS_NO_DATA; 1281 1282 if (ucv_type(res) == UC_INTEGER) { 1283 rv = (int)ucv_int64_get(res); 1284 1285 if (rv < 0 || rv > __UBUS_STATUS_LAST) 1286 rv = UBUS_STATUS_UNKNOWN_ERROR; 1287 } 1288 1289 ubus_complete_deferred_request(ctx, &callctx->req, rv); 1290 callctx->replied = true; 1291 } 1292 1293 ucv_put(res); 1294 break; 1295 1296 /* if the handler function invoked exit(), forward exit status as ubus 1297 * return code, map out of range values to UBUS_STATUS_UNKNOWN_ERROR. */ 1298 case EXCEPTION_EXIT: 1299 rv = vm->arg.s32; 1300 1301 if (rv < UBUS_STATUS_OK || rv >= __UBUS_STATUS_LAST) 1302 rv = UBUS_STATUS_UNKNOWN_ERROR; 1303 1304 ubus_complete_deferred_request(ctx, &callctx->req, rv); 1305 callctx->replied = true; 1306 break; 1307 1308 /* treat other exceptions as fatal and halt uloop */ 1309 default: 1310 ubus_complete_deferred_request(ctx, &callctx->req, UBUS_STATUS_UNKNOWN_ERROR); 1311 uloop_end(); 1312 callctx->replied = true; 1313 break; 1314 } 1315 1316 /* release request object */ 1317 ucv_put(reqobj); 1318 1319 /* garbage collect */ 1320 ucv_gc(vm); 1321 1322 return UBUS_STATUS_OK; 1323 } 1324 1325 static int 1326 uc_ubus_object_call_cb(struct ubus_context *ctx, struct ubus_object *obj, 1327 struct ubus_request_data *req, const char *ubus_method_name, 1328 struct blob_attr *msg) 1329 { 1330 uc_value_t *this, *func, *args = NULL, *reqproto, *methods; 1331 uc_ubus_object_t *uuobj = (uc_ubus_object_t *)obj; 1332 int rv; 1333 1334 object_reg_get(uuobj->vm, uuobj->registry_index, &this, &methods, NULL); 1335 1336 func = ucv_object_get(ucv_object_get(methods, ubus_method_name, NULL), "call", NULL); 1337 1338 if (!ucv_is_callable(func)) 1339 return UBUS_STATUS_METHOD_NOT_FOUND; 1340 1341 rv = uc_ubus_object_call_args(obj, ubus_method_name, msg, &args); 1342 1343 if (rv != UBUS_STATUS_OK) 1344 return rv; 1345 1346 reqproto = ucv_object_new(uuobj->vm); 1347 1348 ucv_object_add(reqproto, "args", args); 1349 ucv_object_add(reqproto, "info", 1350 uc_ubus_object_call_info(uuobj->vm, ctx, req, obj, ubus_method_name)); 1351 1352 return uc_ubus_handle_reply_common(ctx, req, uuobj->vm, this, func, reqproto); 1353 } 1354 1355 1356 /* 1357 * ubus object registration 1358 * -------------------------------------------------------------------------- 1359 */ 1360 1361 static void 1362 uc_ubus_object_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj) 1363 { 1364 uc_ubus_object_t *uuobj = (uc_ubus_object_t *)obj; 1365 uc_value_t *this, *func; 1366 1367 object_reg_get(uuobj->vm, uuobj->registry_index, &this, NULL, &func); 1368 1369 uc_vm_stack_push(uuobj->vm, ucv_get(this)); 1370 uc_vm_stack_push(uuobj->vm, ucv_get(func)); 1371 1372 if (uc_vm_call(uuobj->vm, true, 0) == EXCEPTION_NONE) 1373 ucv_put(uc_vm_stack_pop(uuobj->vm)); 1374 else 1375 uloop_end(); 1376 } 1377 1378 static bool 1379 uc_ubus_object_methods_validate(uc_value_t *methods) 1380 { 1381 uc_value_t *func, *args; 1382 1383 ucv_object_foreach(methods, ubus_method_name, ubus_method_definition) { 1384 (void)ubus_method_name; 1385 1386 func = ucv_object_get(ubus_method_definition, "call", NULL); 1387 args = ucv_object_get(ubus_method_definition, "args", NULL); 1388 1389 if (!ucv_is_callable(func)) 1390 err_return(UBUS_STATUS_INVALID_ARGUMENT, 1391 "Method '%s' field 'call' is not a function value", 1392 ubus_method_name); 1393 1394 if (args) { 1395 if (ucv_type(args) != UC_OBJECT) 1396 err_return(UBUS_STATUS_INVALID_ARGUMENT, 1397 "Method '%s' field 'args' is not an object value", 1398 ubus_method_name); 1399 1400 ucv_object_foreach(args, ubus_argument_name, ubus_argument_typehint) { 1401 (void)ubus_argument_name; 1402 1403 switch (ucv_type(ubus_argument_typehint)) { 1404 case UC_BOOLEAN: 1405 case UC_INTEGER: 1406 case UC_DOUBLE: 1407 case UC_STRING: 1408 case UC_ARRAY: 1409 case UC_OBJECT: 1410 continue; 1411 1412 default: 1413 err_return(UBUS_STATUS_INVALID_ARGUMENT, 1414 "Method '%s' field 'args' argument '%s' hint has unsupported type %s", 1415 ubus_method_name, ubus_argument_name, 1416 ucv_typename(ubus_argument_typehint)); 1417 } 1418 } 1419 } 1420 } 1421 1422 ok_return(true); 1423 } 1424 1425 static bool 1426 uc_ubus_object_method_register(struct ubus_method *method, const char *ubus_method_name, 1427 uc_value_t *ubus_method_arguments) 1428 { 1429 struct blobmsg_policy *policy; 1430 enum blobmsg_type type; 1431 1432 method->name = strdup(ubus_method_name); 1433 method->policy = calloc(ucv_object_length(ubus_method_arguments), sizeof(*method->policy)); 1434 method->handler = uc_ubus_object_call_cb; 1435 1436 if (!method->name || !method->policy) 1437 return false; 1438 1439 ucv_object_foreach(ubus_method_arguments, ubus_argument_name, ubus_argument_typehint) { 1440 switch (ucv_type(ubus_argument_typehint)) { 1441 case UC_BOOLEAN: 1442 type = BLOBMSG_TYPE_INT8; 1443 break; 1444 1445 case UC_INTEGER: 1446 switch (ucv_int64_get(ubus_argument_typehint)) { 1447 case 8: 1448 type = BLOBMSG_TYPE_INT8; 1449 break; 1450 1451 case 16: 1452 type = BLOBMSG_TYPE_INT16; 1453 break; 1454 1455 case 64: 1456 type = BLOBMSG_TYPE_INT64; 1457 break; 1458 1459 default: 1460 type = BLOBMSG_TYPE_INT32; 1461 break; 1462 } 1463 1464 break; 1465 1466 case UC_DOUBLE: 1467 type = BLOBMSG_TYPE_DOUBLE; 1468 break; 1469 1470 case UC_ARRAY: 1471 type = BLOBMSG_TYPE_ARRAY; 1472 break; 1473 1474 case UC_OBJECT: 1475 type = BLOBMSG_TYPE_TABLE; 1476 break; 1477 1478 default: 1479 type = BLOBMSG_TYPE_STRING; 1480 break; 1481 } 1482 1483 policy = (struct blobmsg_policy *)&method->policy[method->n_policy++]; 1484 policy->type = type; 1485 policy->name = strdup(ubus_argument_name); 1486 1487 if (!policy->name) 1488 return false; 1489 } 1490 1491 return true; 1492 } 1493 1494 static uc_ubus_object_t * 1495 uc_ubus_object_register(struct ubus_context *ctx, const char *ubus_object_name, 1496 uc_value_t *ubus_object_methods) 1497 { 1498 const struct blobmsg_policy *policy; 1499 uc_ubus_object_t *uuobj = NULL; 1500 int rv = UBUS_STATUS_UNKNOWN_ERROR; 1501 char *tptr, *tnptr, *onptr, *mptr; 1502 struct ubus_method *method; 1503 struct ubus_object *obj; 1504 size_t typelen, namelen; 1505 uc_value_t *args; 1506 1507 namelen = strlen(ubus_object_name); 1508 typelen = strlen("ucode-ubus-") + namelen; 1509 1510 uuobj = calloc_a(sizeof(*uuobj), 1511 &onptr, namelen + 1, 1512 &mptr, ucv_object_length(ubus_object_methods) * sizeof(struct ubus_method), 1513 &tptr, sizeof(struct ubus_object_type), 1514 &tnptr, typelen + 1); 1515 1516 if (!uuobj) 1517 err_return(rv, "Out of memory"); 1518 1519 snprintf(tnptr, typelen, "ucode-ubus-%s", ubus_object_name); 1520 1521 method = (struct ubus_method *)mptr; 1522 1523 obj = &uuobj->obj; 1524 obj->name = memcpy(onptr, ubus_object_name, namelen); 1525 obj->methods = method; 1526 1527 if (ubus_object_methods) { 1528 ucv_object_foreach(ubus_object_methods, ubus_method_name, ubus_method_definition) { 1529 args = ucv_object_get(ubus_method_definition, "args", NULL); 1530 1531 if (!uc_ubus_object_method_register(&method[obj->n_methods++], ubus_method_name, args)) 1532 goto out; 1533 } 1534 } 1535 1536 obj->type = (struct ubus_object_type *)tptr; 1537 obj->type->name = tnptr; 1538 obj->type->methods = obj->methods; 1539 obj->type->n_methods = obj->n_methods; 1540 1541 rv = ubus_add_object(ctx, obj); 1542 1543 if (rv == UBUS_STATUS_OK) 1544 return uuobj; 1545 1546 out: 1547 for (; obj->n_methods > 0; method++, obj->n_methods--) { 1548 for (policy = method->policy; method->n_policy > 0; policy++, method->n_policy--) 1549 free((char *)policy->name); 1550 1551 free((char *)method->name); 1552 free((char *)method->policy); 1553 } 1554 1555 free(uuobj); 1556 1557 err_return(rv, "Unable to add ubus object"); 1558 } 1559 1560 static uc_value_t * 1561 uc_ubus_publish(uc_vm_t *vm, size_t nargs) 1562 { 1563 uc_value_t *objname, *methods, *subscribecb; 1564 uc_ubus_connection_t *c; 1565 uc_ubus_object_t *uuobj; 1566 uc_value_t *res; 1567 1568 conn_get(vm, &c); 1569 1570 args_get(vm, nargs, 1571 "object name", UC_STRING, false, &objname, 1572 "object methods", UC_OBJECT, true, &methods, 1573 "subscribe callback", UC_CLOSURE, true, &subscribecb); 1574 1575 if (!methods && !subscribecb) 1576 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Either methods or subscribe callback required"); 1577 1578 if (methods && !uc_ubus_object_methods_validate(methods)) 1579 return NULL; 1580 1581 uuobj = uc_ubus_object_register(&c->ctx, ucv_string_get(objname), methods); 1582 1583 if (!uuobj) 1584 return NULL; 1585 1586 if (subscribecb) 1587 uuobj->obj.subscribe_cb = uc_ubus_object_subscribe_cb; 1588 1589 res = uc_resource_new(object_type, uuobj); 1590 1591 uuobj->vm = vm; 1592 uuobj->ctx = &c->ctx; 1593 uuobj->registry_index = object_reg_add(vm, ucv_get(res), ucv_get(methods), ucv_get(subscribecb)); 1594 1595 ok_return(res); 1596 } 1597 1598 1599 /* 1600 * ubus events 1601 * -------------------------------------------------------------------------- 1602 */ 1603 1604 static int 1605 uc_ubus_listener_remove_common(uc_ubus_listener_t *uul) 1606 { 1607 int rv = ubus_unregister_event_handler(uul->ctx, &uul->ev); 1608 1609 if (rv == UBUS_STATUS_OK) 1610 listener_reg_clear(uul->vm, uul->registry_index); 1611 1612 return rv; 1613 } 1614 1615 static uc_value_t * 1616 uc_ubus_listener_remove(uc_vm_t *vm, size_t nargs) 1617 { 1618 uc_ubus_listener_t **uul = uc_fn_this("ubus.listener"); 1619 int rv; 1620 1621 if (!uul || !*uul) 1622 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid listener context"); 1623 1624 rv = uc_ubus_listener_remove_common(*uul); 1625 1626 if (rv != UBUS_STATUS_OK) 1627 err_return(rv, "Failed to remove listener object"); 1628 1629 ok_return(ucv_boolean_new(true)); 1630 } 1631 1632 static void 1633 uc_ubus_listener_cb(struct ubus_context *ctx, struct ubus_event_handler *ev, 1634 const char *type, struct blob_attr *msg) 1635 { 1636 uc_ubus_listener_t *uul = (uc_ubus_listener_t *)ev; 1637 uc_value_t *this, *func; 1638 1639 listener_reg_get(uul->vm, uul->registry_index, &this, &func); 1640 1641 uc_vm_stack_push(uul->vm, ucv_get(this)); 1642 uc_vm_stack_push(uul->vm, ucv_get(func)); 1643 uc_vm_stack_push(uul->vm, ucv_string_new(type)); 1644 uc_vm_stack_push(uul->vm, blob_array_to_ucv(uul->vm, blob_data(msg), blob_len(msg), true)); 1645 1646 if (uc_vm_call(uul->vm, true, 2) == EXCEPTION_NONE) 1647 ucv_put(uc_vm_stack_pop(uul->vm)); 1648 else 1649 uloop_end(); 1650 } 1651 1652 static uc_value_t * 1653 uc_ubus_listener(uc_vm_t *vm, size_t nargs) 1654 { 1655 uc_value_t *cb, *pattern; 1656 uc_ubus_connection_t *c; 1657 uc_ubus_listener_t *uul; 1658 uc_value_t *res; 1659 int rv; 1660 1661 conn_get(vm, &c); 1662 1663 args_get(vm, nargs, 1664 "event type pattern", UC_STRING, false, &pattern, 1665 "event callback", UC_CLOSURE, false, &cb); 1666 1667 uul = xalloc(sizeof(*uul)); 1668 uul->vm = vm; 1669 uul->ctx = &c->ctx; 1670 uul->ev.cb = uc_ubus_listener_cb; 1671 1672 rv = ubus_register_event_handler(&c->ctx, &uul->ev, 1673 ucv_string_get(pattern)); 1674 1675 if (rv != UBUS_STATUS_OK) { 1676 free(uul); 1677 err_return(rv, "Failed to register listener object"); 1678 } 1679 1680 res = uc_resource_new(listener_type, uul); 1681 1682 uul->registry_index = listener_reg_add(vm, ucv_get(res), ucv_get(cb)); 1683 1684 ok_return(res); 1685 } 1686 1687 static uc_value_t * 1688 uc_ubus_event(uc_vm_t *vm, size_t nargs) 1689 { 1690 uc_value_t *eventtype, *eventdata; 1691 uc_ubus_connection_t *c; 1692 int rv; 1693 1694 conn_get(vm, &c); 1695 1696 args_get(vm, nargs, 1697 "event id", UC_STRING, false, &eventtype, 1698 "event data", UC_OBJECT, true, &eventdata); 1699 1700 blob_buf_init(&buf, 0); 1701 1702 if (eventdata) 1703 ucv_object_to_blob(eventdata, &buf); 1704 1705 rv = ubus_send_event(&c->ctx, ucv_string_get(eventtype), buf.head); 1706 1707 if (rv != UBUS_STATUS_OK) 1708 err_return(rv, "Unable to send event"); 1709 1710 ok_return(ucv_boolean_new(true)); 1711 } 1712 1713 1714 /* 1715 * ubus subscriptions 1716 * -------------------------------------------------------------------------- 1717 */ 1718 1719 static int 1720 uc_ubus_subscriber_notify_cb(struct ubus_context *ctx, struct ubus_object *obj, 1721 struct ubus_request_data *req, const char *method, 1722 struct blob_attr *msg) 1723 { 1724 struct ubus_subscriber *sub = container_of(obj, struct ubus_subscriber, obj); 1725 uc_ubus_subscriber_t *uusub = container_of(sub, uc_ubus_subscriber_t, sub); 1726 uc_value_t *this, *func, *reqproto; 1727 1728 subscriber_reg_get(uusub->vm, uusub->registry_index, &this, &func, NULL); 1729 1730 if (!ucv_is_callable(func)) 1731 return UBUS_STATUS_METHOD_NOT_FOUND; 1732 1733 reqproto = ucv_object_new(uusub->vm); 1734 1735 ucv_object_add(reqproto, "type", ucv_string_new(method)); 1736 1737 ucv_object_add(reqproto, "data", 1738 blob_array_to_ucv(uusub->vm, blob_data(msg), blob_len(msg), true)); 1739 1740 ucv_object_add(reqproto, "info", 1741 uc_ubus_object_call_info(uusub->vm, ctx, req, obj, NULL)); 1742 1743 return uc_ubus_handle_reply_common(ctx, req, uusub->vm, this, func, reqproto); 1744 } 1745 1746 static void 1747 uc_ubus_subscriber_remove_cb(struct ubus_context *ctx, 1748 struct ubus_subscriber *sub, uint32_t id) 1749 { 1750 uc_ubus_subscriber_t *uusub = container_of(sub, uc_ubus_subscriber_t, sub); 1751 uc_value_t *this, *func; 1752 1753 subscriber_reg_get(uusub->vm, uusub->registry_index, &this, NULL, &func); 1754 1755 if (!ucv_is_callable(func)) 1756 return; 1757 1758 uc_vm_stack_push(uusub->vm, ucv_get(this)); 1759 uc_vm_stack_push(uusub->vm, ucv_get(func)); 1760 uc_vm_stack_push(uusub->vm, ucv_uint64_new(id)); 1761 1762 if (uc_vm_call(uusub->vm, true, 1) == EXCEPTION_NONE) 1763 ucv_put(uc_vm_stack_pop(uusub->vm)); 1764 else 1765 uloop_end(); 1766 } 1767 1768 static uc_value_t * 1769 uc_ubus_subscriber_subunsub_common(uc_vm_t *vm, size_t nargs, bool subscribe) 1770 { 1771 uc_ubus_subscriber_t **uusub = uc_fn_this("ubus.subscriber"); 1772 uc_value_t *objname; 1773 uint32_t id; 1774 int rv; 1775 1776 if (!uusub || !*uusub) 1777 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid subscriber context"); 1778 1779 args_get(vm, nargs, 1780 "object name", UC_STRING, false, &objname); 1781 1782 rv = ubus_lookup_id((*uusub)->ctx, ucv_string_get(objname), &id); 1783 1784 if (rv != UBUS_STATUS_OK) 1785 err_return(rv, "Failed to resolve object name '%s'", 1786 ucv_string_get(objname)); 1787 1788 if (subscribe) 1789 rv = ubus_subscribe((*uusub)->ctx, &(*uusub)->sub, id); 1790 else 1791 rv = ubus_unsubscribe((*uusub)->ctx, &(*uusub)->sub, id); 1792 1793 if (rv != UBUS_STATUS_OK) 1794 err_return(rv, "Failed to %s object '%s'", 1795 subscribe ? "subscribe" : "unsubscribe", 1796 ucv_string_get(objname)); 1797 1798 ok_return(ucv_boolean_new(true)); 1799 } 1800 1801 static uc_value_t * 1802 uc_ubus_subscriber_subscribe(uc_vm_t *vm, size_t nargs) 1803 { 1804 return uc_ubus_subscriber_subunsub_common(vm, nargs, true); 1805 } 1806 1807 static uc_value_t * 1808 uc_ubus_subscriber_unsubscribe(uc_vm_t *vm, size_t nargs) 1809 { 1810 return uc_ubus_subscriber_subunsub_common(vm, nargs, false); 1811 } 1812 1813 static int 1814 uc_ubus_subscriber_remove_common(uc_ubus_subscriber_t *uusub) 1815 { 1816 int rv = ubus_unregister_subscriber(uusub->ctx, &uusub->sub); 1817 1818 if (rv == UBUS_STATUS_OK) 1819 subscriber_reg_clear(uusub->vm, uusub->registry_index); 1820 1821 return rv; 1822 } 1823 1824 static uc_value_t * 1825 uc_ubus_subscriber_remove(uc_vm_t *vm, size_t nargs) 1826 { 1827 uc_ubus_subscriber_t **uusub = uc_fn_this("ubus.subscriber"); 1828 int rv; 1829 1830 if (!uusub || !*uusub) 1831 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid subscriber context"); 1832 1833 rv = uc_ubus_subscriber_remove_common(*uusub); 1834 1835 if (rv != UBUS_STATUS_OK) 1836 err_return(rv, "Failed to remove subscriber object"); 1837 1838 ok_return(ucv_boolean_new(true)); 1839 } 1840 1841 static uc_value_t * 1842 uc_ubus_subscriber(uc_vm_t *vm, size_t nargs) 1843 { 1844 uc_value_t *notify_cb, *remove_cb; 1845 uc_ubus_subscriber_t *uusub; 1846 uc_ubus_connection_t *c; 1847 uc_value_t *res; 1848 int rv; 1849 1850 conn_get(vm, &c); 1851 1852 args_get(vm, nargs, 1853 "notify callback", UC_CLOSURE, true, ¬ify_cb, 1854 "remove callback", UC_CLOSURE, true, &remove_cb); 1855 1856 if (!notify_cb && !remove_cb) 1857 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Either notify or remove callback required"); 1858 1859 uusub = xalloc(sizeof(*uusub)); 1860 uusub->vm = vm; 1861 uusub->ctx = &c->ctx; 1862 1863 rv = ubus_register_subscriber(&c->ctx, &uusub->sub); 1864 1865 if (rv != UBUS_STATUS_OK) { 1866 free(uusub); 1867 err_return(rv, "Failed to register subscriber object"); 1868 } 1869 1870 if (notify_cb) 1871 uusub->sub.cb = uc_ubus_subscriber_notify_cb; 1872 1873 if (remove_cb) 1874 uusub->sub.remove_cb = uc_ubus_subscriber_remove_cb; 1875 1876 res = uc_resource_new(subscriber_type, uusub); 1877 1878 uusub->registry_index = subscriber_reg_add(vm, 1879 ucv_get(res), ucv_get(notify_cb), ucv_get(remove_cb)); 1880 1881 ok_return(res); 1882 } 1883 1884 1885 /* 1886 * connection methods 1887 * -------------------------------------------------------------------------- 1888 */ 1889 1890 static uc_value_t * 1891 uc_ubus_remove(uc_vm_t *vm, size_t nargs) 1892 { 1893 uc_ubus_subscriber_t **uusub; 1894 uc_ubus_connection_t *c; 1895 uc_ubus_object_t **uuobj; 1896 uc_ubus_listener_t **uul; 1897 int rv; 1898 1899 conn_get(vm, &c); 1900 1901 uusub = (uc_ubus_subscriber_t **)ucv_resource_dataptr(uc_fn_arg(0), "ubus.subscriber"); 1902 uuobj = (uc_ubus_object_t **)ucv_resource_dataptr(uc_fn_arg(0), "ubus.object"); 1903 uul = (uc_ubus_listener_t **)ucv_resource_dataptr(uc_fn_arg(0), "ubus.listener"); 1904 1905 if (uusub && *uusub) { 1906 if ((*uusub)->ctx != &c->ctx) 1907 err_return(UBUS_STATUS_INVALID_ARGUMENT, 1908 "Subscriber belongs to different connection"); 1909 1910 rv = uc_ubus_subscriber_remove_common(*uusub); 1911 1912 if (rv != UBUS_STATUS_OK) 1913 err_return(rv, "Unable to remove subscriber"); 1914 } 1915 else if (uuobj && *uuobj) { 1916 if ((*uuobj)->ctx != &c->ctx) 1917 err_return(UBUS_STATUS_INVALID_ARGUMENT, 1918 "Object belongs to different connection"); 1919 1920 rv = uc_ubus_object_remove_common(*uuobj); 1921 1922 if (rv != UBUS_STATUS_OK) 1923 err_return(rv, "Unable to remove object"); 1924 } 1925 else if (uul && *uul) { 1926 if ((*uul)->ctx != &c->ctx) 1927 err_return(UBUS_STATUS_INVALID_ARGUMENT, 1928 "Listener belongs to different connection"); 1929 1930 rv = uc_ubus_listener_remove_common(*uul); 1931 1932 if (rv != UBUS_STATUS_OK) 1933 err_return(rv, "Unable to remove listener"); 1934 } 1935 else { 1936 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Unhandled resource type"); 1937 } 1938 1939 ok_return(ucv_boolean_new(true)); 1940 } 1941 1942 1943 static uc_value_t * 1944 uc_ubus_disconnect(uc_vm_t *vm, size_t nargs) 1945 { 1946 uc_ubus_connection_t *c; 1947 1948 conn_get(vm, &c); 1949 1950 ubus_shutdown(&c->ctx); 1951 c->ctx.sock.fd = -1; 1952 1953 ok_return(ucv_boolean_new(true)); 1954 } 1955 1956 static uc_value_t * 1957 uc_ubus_defer_completed(uc_vm_t *vm, size_t nargs) 1958 { 1959 uc_ubus_deferred_t **d = uc_fn_this("ubus.deferred"); 1960 1961 if (!d || !*d) 1962 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid deferred context"); 1963 1964 ok_return(ucv_boolean_new((*d)->complete)); 1965 } 1966 1967 static uc_value_t * 1968 uc_ubus_defer_abort(uc_vm_t *vm, size_t nargs) 1969 { 1970 uc_ubus_deferred_t **d = uc_fn_this("ubus.deferred"); 1971 1972 if (!d || !*d) 1973 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid deferred context"); 1974 1975 if ((*d)->complete) 1976 ok_return(ucv_boolean_new(false)); 1977 1978 ubus_abort_request((*d)->ctx, &(*d)->request); 1979 uloop_timeout_cancel(&(*d)->timeout); 1980 1981 request_reg_clear((*d)->vm, (*d)->registry_index); 1982 1983 n_cb_active--; 1984 1985 if (have_own_uloop && n_cb_active == 0) 1986 uloop_end(); 1987 1988 (*d)->complete = true; 1989 1990 ok_return(ucv_boolean_new(true)); 1991 } 1992 1993 1994 static const uc_function_list_t global_fns[] = { 1995 { "error", uc_ubus_error }, 1996 { "connect", uc_ubus_connect }, 1997 }; 1998 1999 static const uc_function_list_t conn_fns[] = { 2000 { "list", uc_ubus_list }, 2001 { "call", uc_ubus_call }, 2002 { "defer", uc_ubus_defer }, 2003 { "publish", uc_ubus_publish }, 2004 { "remove", uc_ubus_remove }, 2005 { "listener", uc_ubus_listener }, 2006 { "subscriber", uc_ubus_subscriber }, 2007 { "event", uc_ubus_event }, 2008 { "error", uc_ubus_error }, 2009 { "disconnect", uc_ubus_disconnect }, 2010 }; 2011 2012 static const uc_function_list_t defer_fns[] = { 2013 { "completed", uc_ubus_defer_completed }, 2014 { "abort", uc_ubus_defer_abort }, 2015 }; 2016 2017 static const uc_function_list_t object_fns[] = { 2018 { "subscribed", uc_ubus_object_subscribed }, 2019 { "notify", uc_ubus_object_notify }, 2020 { "remove", uc_ubus_object_remove }, 2021 }; 2022 2023 static const uc_function_list_t request_fns[] = { 2024 { "reply", uc_ubus_request_reply }, 2025 { "error", uc_ubus_request_error }, 2026 { "defer", uc_ubus_request_defer }, 2027 }; 2028 2029 static const uc_function_list_t notify_fns[] = { 2030 { "completed", uc_ubus_notify_completed }, 2031 { "abort", uc_ubus_notify_abort }, 2032 }; 2033 2034 static const uc_function_list_t listener_fns[] = { 2035 { "remove", uc_ubus_listener_remove }, 2036 }; 2037 2038 static const uc_function_list_t subscriber_fns[] = { 2039 { "subscribe", uc_ubus_subscriber_subscribe }, 2040 { "unsubscribe", uc_ubus_subscriber_unsubscribe }, 2041 { "remove", uc_ubus_subscriber_remove }, 2042 }; 2043 2044 static void free_connection(void *ud) { 2045 uc_ubus_connection_t *conn = ud; 2046 2047 blob_buf_free(&conn->buf); 2048 2049 if (conn->ctx.sock.fd >= 0) 2050 ubus_shutdown(&conn->ctx); 2051 2052 free(conn); 2053 } 2054 2055 static void free_deferred(void *ud) { 2056 uc_ubus_deferred_t *defer = ud; 2057 2058 uloop_timeout_cancel(&defer->timeout); 2059 ucv_put(defer->response); 2060 free(defer); 2061 } 2062 2063 static void free_object(void *ud) { 2064 uc_ubus_object_t *uuobj = ud; 2065 struct ubus_object *obj = &uuobj->obj; 2066 int i, j; 2067 2068 for (i = 0; i < obj->n_methods; i++) { 2069 for (j = 0; j < obj->methods[i].n_policy; j++) 2070 free((char *)obj->methods[i].policy[j].name); 2071 2072 free((char *)obj->methods[i].name); 2073 free((char *)obj->methods[i].policy); 2074 } 2075 2076 free(uuobj); 2077 } 2078 2079 static void free_request(void *ud) { 2080 uc_ubus_request_t *callctx = ud; 2081 2082 uc_ubus_request_finish(callctx, UBUS_STATUS_TIMEOUT, NULL); 2083 uloop_timeout_cancel(&callctx->timeout); 2084 free(callctx); 2085 } 2086 2087 static void free_notify(void *ud) { 2088 uc_ubus_notify_t *notifyctx = ud; 2089 2090 free(notifyctx); 2091 } 2092 2093 static void free_listener(void *ud) { 2094 uc_ubus_listener_t *listener = ud; 2095 2096 free(listener); 2097 } 2098 2099 static void free_subscriber(void *ud) { 2100 uc_ubus_subscriber_t *subscriber = ud; 2101 2102 free(subscriber); 2103 } 2104 2105 void uc_module_init(uc_vm_t *vm, uc_value_t *scope) 2106 { 2107 uc_function_list_register(scope, global_fns); 2108 2109 #define ADD_CONST(x) ucv_object_add(scope, #x, ucv_int64_new(UBUS_##x)) 2110 ADD_CONST(STATUS_OK); 2111 ADD_CONST(STATUS_INVALID_COMMAND); 2112 ADD_CONST(STATUS_INVALID_ARGUMENT); 2113 ADD_CONST(STATUS_METHOD_NOT_FOUND); 2114 ADD_CONST(STATUS_NOT_FOUND); 2115 ADD_CONST(STATUS_NO_DATA); 2116 ADD_CONST(STATUS_PERMISSION_DENIED); 2117 ADD_CONST(STATUS_TIMEOUT); 2118 ADD_CONST(STATUS_NOT_SUPPORTED); 2119 ADD_CONST(STATUS_UNKNOWN_ERROR); 2120 ADD_CONST(STATUS_CONNECTION_FAILED); 2121 2122 #ifdef HAVE_NEW_UBUS_STATUS_CODES 2123 ADD_CONST(STATUS_NO_MEMORY); 2124 ADD_CONST(STATUS_PARSE_ERROR); 2125 ADD_CONST(STATUS_SYSTEM_ERROR); 2126 #endif 2127 2128 conn_type = uc_type_declare(vm, "ubus.connection", conn_fns, free_connection); 2129 defer_type = uc_type_declare(vm, "ubus.deferred", defer_fns, free_deferred); 2130 object_type = uc_type_declare(vm, "ubus.object", object_fns, free_object); 2131 notify_type = uc_type_declare(vm, "ubus.notify", notify_fns, free_notify); 2132 request_type = uc_type_declare(vm, "ubus.request", request_fns, free_request); 2133 listener_type = uc_type_declare(vm, "ubus.listener", listener_fns, free_listener); 2134 subscriber_type = uc_type_declare(vm, "ubus.subscriber", subscriber_fns, free_subscriber); 2135 } 2136
This page was automatically generated by LXR 0.3.1. • OpenWrt