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 uloop_cancelled = true; 669 active = uloop_cancelling(); 670 uloop_cancelled = prev; 671 672 return active; 673 } 674 675 static uc_value_t * 676 uc_ubus_call(uc_vm_t *vm, size_t nargs) 677 { 678 uc_value_t *objname, *funname, *funargs, *mret = NULL; 679 uc_ubus_call_res_t res = { 0 }; 680 uc_ubus_connection_t *c; 681 enum ubus_msg_status rv; 682 uint32_t id; 683 684 conn_get(vm, &c); 685 686 args_get(vm, nargs, 687 "object name", UC_STRING, false, &objname, 688 "function name", UC_STRING, false, &funname, 689 "function arguments", UC_OBJECT, true, &funargs, 690 "multiple return", UC_BOOLEAN, true, &mret); 691 692 blob_buf_init(&c->buf, 0); 693 694 if (funargs) 695 ucv_object_to_blob(funargs, &c->buf); 696 697 rv = ubus_lookup_id(&c->ctx, ucv_string_get(objname), &id); 698 699 if (rv != UBUS_STATUS_OK) 700 err_return(rv, "Failed to resolve object name '%s'", 701 ucv_string_get(objname)); 702 703 res.mret = ucv_is_truish(mret); 704 705 rv = ubus_invoke(&c->ctx, id, ucv_string_get(funname), c->buf.head, 706 uc_ubus_call_cb, &res, c->timeout * 1000); 707 708 if (rv != UBUS_STATUS_OK) 709 err_return(rv, "Failed to invoke function '%s' on object '%s'", 710 ucv_string_get(funname), ucv_string_get(objname)); 711 712 ok_return(res.res); 713 } 714 715 static uc_value_t * 716 uc_ubus_defer(uc_vm_t *vm, size_t nargs) 717 { 718 uc_value_t *objname, *funname, *funargs, *replycb, *conn, *res = NULL; 719 uc_ubus_deferred_t *defer; 720 uc_ubus_connection_t *c; 721 enum ubus_msg_status rv; 722 uint32_t id; 723 724 conn_get(vm, &c); 725 726 args_get(vm, nargs, 727 "object name", UC_STRING, false, &objname, 728 "function name", UC_STRING, false, &funname, 729 "function arguments", UC_OBJECT, true, &funargs, 730 "reply callback", UC_CLOSURE, true, &replycb); 731 732 blob_buf_init(&c->buf, 0); 733 734 if (funargs) 735 ucv_object_to_blob(funargs, &c->buf); 736 737 rv = ubus_lookup_id(&c->ctx, ucv_string_get(objname), &id); 738 739 if (rv != UBUS_STATUS_OK) 740 err_return(rv, "Failed to resolve object name '%s'", 741 ucv_string_get(objname)); 742 743 defer = xalloc(sizeof(*defer)); 744 745 rv = ubus_invoke_async(&c->ctx, id, ucv_string_get(funname), 746 c->buf.head, &defer->request); 747 748 if (rv == UBUS_STATUS_OK) { 749 defer->vm = vm; 750 defer->ctx = &c->ctx; 751 752 defer->request.data_cb = uc_ubus_call_data_cb; 753 defer->request.complete_cb = uc_ubus_call_done_cb; 754 ubus_complete_request_async(&c->ctx, &defer->request); 755 756 defer->timeout.cb = uc_ubus_call_timeout_cb; 757 uloop_timeout_set(&defer->timeout, c->timeout * 1000); 758 759 res = uc_resource_new(defer_type, defer); 760 conn = uc_vector_last(&vm->callframes)->ctx; 761 762 defer->registry_index = request_reg_add(vm, ucv_get(res), ucv_get(replycb), ucv_get(conn)); 763 764 if (!uc_ubus_have_uloop()) { 765 have_own_uloop = true; 766 uloop_run(); 767 } 768 } 769 else { 770 uc_vm_stack_push(vm, ucv_get(replycb)); 771 uc_vm_stack_push(vm, ucv_int64_new(rv)); 772 773 if (uc_vm_call(vm, false, 1) == EXCEPTION_NONE) 774 ucv_put(uc_vm_stack_pop(vm)); 775 else 776 uloop_end(); 777 778 free(defer); 779 } 780 781 if (rv != UBUS_STATUS_OK) 782 err_return(rv, "Failed to invoke function '%s' on object '%s'", 783 ucv_string_get(funname), ucv_string_get(objname)); 784 785 ok_return(res); 786 } 787 788 789 /* 790 * ubus object request context functions 791 * -------------------------------------------------------------------------- 792 */ 793 794 static void 795 uc_ubus_request_finish(uc_ubus_request_t *callctx, int code, uc_value_t *reply) 796 { 797 if (callctx->replied) 798 return; 799 800 if (reply) { 801 blob_buf_init(&buf, 0); 802 ucv_object_to_blob(reply, &buf); 803 ubus_send_reply(callctx->ctx, &callctx->req, buf.head); 804 } 805 806 callctx->replied = true; 807 808 ubus_complete_deferred_request(callctx->ctx, &callctx->req, code); 809 request_reg_clear(callctx->vm, callctx->registry_index); 810 } 811 812 static void 813 uc_ubus_request_timeout(struct uloop_timeout *timeout) 814 { 815 uc_ubus_request_t *callctx = container_of(timeout, uc_ubus_request_t, timeout); 816 817 uc_ubus_request_finish(callctx, UBUS_STATUS_TIMEOUT, NULL); 818 } 819 820 static uc_value_t * 821 uc_ubus_request_reply(uc_vm_t *vm, size_t nargs) 822 { 823 uc_ubus_request_t **callctx = uc_fn_this("ubus.request"); 824 int64_t code = UBUS_STATUS_OK; 825 uc_value_t *reply, *rcode; 826 827 if (!callctx || !*callctx) 828 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid call context"); 829 830 args_get(vm, nargs, 831 "reply", UC_OBJECT, true, &reply, 832 "rcode", UC_INTEGER, true, &rcode); 833 834 if ((*callctx)->replied) 835 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Reply has already been sent"); 836 837 if (rcode) { 838 code = ucv_int64_get(rcode); 839 840 if (errno == ERANGE || code < 0 || code > __UBUS_STATUS_LAST) 841 code = UBUS_STATUS_UNKNOWN_ERROR; 842 } 843 844 uc_ubus_request_finish(*callctx, code, reply); 845 846 ok_return(ucv_boolean_new(true)); 847 } 848 849 static uc_value_t * 850 uc_ubus_request_defer(uc_vm_t *vm, size_t nargs) 851 { 852 uc_ubus_request_t *callctx = uc_fn_thisval("ubus.request"); 853 854 if (!callctx) 855 return NULL; 856 857 callctx->deferred = true; 858 return ucv_boolean_new(true); 859 } 860 861 static uc_value_t * 862 uc_ubus_request_error(uc_vm_t *vm, size_t nargs) 863 { 864 uc_ubus_request_t **callctx = uc_fn_this("ubus.request"); 865 uc_value_t *rcode = uc_fn_arg(0); 866 int64_t code; 867 868 if (!callctx || !*callctx) 869 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid call context"); 870 871 args_get(vm, nargs, 872 "rcode", UC_INTEGER, false, &rcode); 873 874 if ((*callctx)->replied) 875 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Reply has already been sent"); 876 877 code = ucv_int64_get(rcode); 878 879 if (errno == ERANGE || code < 0 || code > __UBUS_STATUS_LAST) 880 code = UBUS_STATUS_UNKNOWN_ERROR; 881 882 uc_ubus_request_finish(*callctx, code, NULL); 883 884 ok_return(ucv_boolean_new(true)); 885 } 886 887 888 /* 889 * ubus object notify 890 * -------------------------------------------------------------------------- 891 */ 892 893 static uc_value_t * 894 uc_ubus_notify_completed(uc_vm_t *vm, size_t nargs) 895 { 896 uc_ubus_notify_t **notifyctx = uc_fn_this("ubus.notify"); 897 898 if (!notifyctx || !*notifyctx) 899 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid notify context"); 900 901 ok_return(ucv_boolean_new((*notifyctx)->complete)); 902 } 903 904 static uc_value_t * 905 uc_ubus_notify_abort(uc_vm_t *vm, size_t nargs) 906 { 907 uc_ubus_notify_t **notifyctx = uc_fn_this("ubus.notify"); 908 909 if (!notifyctx || !*notifyctx) 910 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid notify context"); 911 912 if ((*notifyctx)->complete) 913 ok_return(ucv_boolean_new(false)); 914 915 ubus_abort_request((*notifyctx)->ctx, &(*notifyctx)->req.req); 916 (*notifyctx)->complete = true; 917 918 ok_return(ucv_boolean_new(true)); 919 } 920 921 static void 922 uc_ubus_object_notify_data_cb(struct ubus_notify_request *req, int type, struct blob_attr *msg) 923 { 924 uc_ubus_notify_t *notifyctx = (uc_ubus_notify_t *)req; 925 uc_value_t *this, *func; 926 927 notify_reg_get(notifyctx->vm, notifyctx->registry_index, &this, &func, NULL, NULL); 928 929 if (ucv_is_callable(func)) { 930 uc_vm_stack_push(notifyctx->vm, ucv_get(this)); 931 uc_vm_stack_push(notifyctx->vm, ucv_get(func)); 932 uc_vm_stack_push(notifyctx->vm, ucv_int64_new(type)); 933 uc_vm_stack_push(notifyctx->vm, blob_array_to_ucv(notifyctx->vm, blob_data(msg), blob_len(msg), true)); 934 935 if (uc_vm_call(notifyctx->vm, true, 2) == EXCEPTION_NONE) 936 ucv_put(uc_vm_stack_pop(notifyctx->vm)); 937 else 938 uloop_end(); 939 } 940 } 941 942 static void 943 uc_ubus_object_notify_status_cb(struct ubus_notify_request *req, int idx, int ret) 944 { 945 uc_ubus_notify_t *notifyctx = (uc_ubus_notify_t *)req; 946 uc_value_t *this, *func; 947 948 notify_reg_get(notifyctx->vm, notifyctx->registry_index, &this, NULL, &func, NULL); 949 950 if (ucv_is_callable(func)) { 951 uc_vm_stack_push(notifyctx->vm, ucv_get(this)); 952 uc_vm_stack_push(notifyctx->vm, ucv_get(func)); 953 uc_vm_stack_push(notifyctx->vm, ucv_int64_new(idx)); 954 uc_vm_stack_push(notifyctx->vm, ucv_int64_new(ret)); 955 956 if (uc_vm_call(notifyctx->vm, true, 2) == EXCEPTION_NONE) 957 ucv_put(uc_vm_stack_pop(notifyctx->vm)); 958 else 959 uloop_end(); 960 } 961 } 962 963 static void 964 uc_ubus_object_notify_complete_cb(struct ubus_notify_request *req, int idx, int ret) 965 { 966 uc_ubus_notify_t *notifyctx = (uc_ubus_notify_t *)req; 967 uc_value_t *this, *func; 968 969 notify_reg_get(notifyctx->vm, notifyctx->registry_index, &this, NULL, NULL, &func); 970 971 if (ucv_is_callable(func)) { 972 uc_vm_stack_push(notifyctx->vm, ucv_get(this)); 973 uc_vm_stack_push(notifyctx->vm, ucv_get(func)); 974 uc_vm_stack_push(notifyctx->vm, ucv_int64_new(idx)); 975 uc_vm_stack_push(notifyctx->vm, ucv_int64_new(ret)); 976 977 if (uc_vm_call(notifyctx->vm, true, 2) == EXCEPTION_NONE) 978 ucv_put(uc_vm_stack_pop(notifyctx->vm)); 979 else 980 uloop_end(); 981 } 982 983 notifyctx->complete = true; 984 985 notify_reg_clear(notifyctx->vm, notifyctx->registry_index); 986 } 987 988 static uc_value_t * 989 uc_ubus_object_notify(uc_vm_t *vm, size_t nargs) 990 { 991 uc_value_t *typename, *message, *data_cb, *status_cb, *complete_cb, *timeout; 992 uc_ubus_object_t **uuobj = uc_fn_this("ubus.object"); 993 uc_ubus_notify_t *notifyctx; 994 uc_value_t *res; 995 int64_t t; 996 int rv; 997 998 if (!uuobj || !*uuobj) 999 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid object context"); 1000 1001 args_get(vm, nargs, 1002 "typename", UC_STRING, false, &typename, 1003 "message", UC_OBJECT, true, &message, 1004 "data callback", UC_CLOSURE, true, &data_cb, 1005 "status callback", UC_CLOSURE, true, &status_cb, 1006 "completion callback", UC_CLOSURE, true, &complete_cb, 1007 "timeout", UC_INTEGER, true, &timeout); 1008 1009 t = timeout ? ucv_int64_get(timeout) : -1; 1010 1011 if (errno) 1012 err_return(UBUS_STATUS_INVALID_ARGUMENT, 1013 "Invalid timeout value: %s", strerror(errno)); 1014 1015 notifyctx = xalloc(sizeof(*notifyctx)); 1016 notifyctx->vm = vm; 1017 notifyctx->ctx = (*uuobj)->ctx; 1018 1019 blob_buf_init(&buf, 0); 1020 1021 if (message) 1022 ucv_object_to_blob(message, &buf); 1023 1024 rv = ubus_notify_async((*uuobj)->ctx, &(*uuobj)->obj, 1025 ucv_string_get(typename), buf.head, 1026 ¬ifyctx->req); 1027 1028 if (rv != UBUS_STATUS_OK) { 1029 free(notifyctx); 1030 err_return(rv, "Failed to send notification"); 1031 } 1032 1033 notifyctx->req.data_cb = uc_ubus_object_notify_data_cb; 1034 notifyctx->req.status_cb = uc_ubus_object_notify_status_cb; 1035 notifyctx->req.complete_cb = uc_ubus_object_notify_complete_cb; 1036 1037 res = uc_resource_new(notify_type, notifyctx); 1038 1039 notifyctx->registry_index = notify_reg_add(vm, 1040 ucv_get(res), ucv_get(data_cb), ucv_get(status_cb), ucv_get(complete_cb)); 1041 1042 if (t >= 0) { 1043 rv = ubus_complete_request((*uuobj)->ctx, ¬ifyctx->req.req, t); 1044 1045 notify_reg_clear(vm, notifyctx->registry_index); 1046 1047 ucv_put(res); 1048 1049 ok_return(ucv_int64_new(rv)); 1050 } 1051 1052 ubus_complete_request_async((*uuobj)->ctx, ¬ifyctx->req.req); 1053 1054 ok_return(res); 1055 } 1056 1057 1058 /* 1059 * ubus object remove 1060 * -------------------------------------------------------------------------- 1061 */ 1062 1063 static int 1064 uc_ubus_object_remove_common(uc_ubus_object_t *uuobj) 1065 { 1066 int rv = ubus_remove_object(uuobj->ctx, &uuobj->obj); 1067 1068 if (rv == UBUS_STATUS_OK) 1069 object_reg_clear(uuobj->vm, uuobj->registry_index); 1070 1071 return rv; 1072 } 1073 1074 static uc_value_t * 1075 uc_ubus_object_remove(uc_vm_t *vm, size_t nargs) 1076 { 1077 uc_ubus_object_t **uuobj = uc_fn_this("ubus.object"); 1078 int rv; 1079 1080 if (!uuobj || !*uuobj) 1081 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid object context"); 1082 1083 rv = uc_ubus_object_remove_common(*uuobj); 1084 1085 if (rv != UBUS_STATUS_OK) 1086 err_return(rv, "Failed to remove object"); 1087 1088 ok_return(ucv_boolean_new(true)); 1089 } 1090 1091 1092 /* 1093 * ubus object subscription status 1094 */ 1095 1096 static uc_value_t * 1097 uc_ubus_object_subscribed(uc_vm_t *vm, size_t nargs) 1098 { 1099 uc_ubus_object_t **uuobj = uc_fn_this("ubus.object"); 1100 1101 if (!uuobj || !*uuobj) 1102 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid object context"); 1103 1104 ok_return(ucv_boolean_new((*uuobj)->obj.has_subscribers)); 1105 } 1106 1107 1108 /* 1109 * ubus object method call handling 1110 * -------------------------------------------------------------------------- 1111 */ 1112 1113 static int 1114 uc_ubus_object_call_args(struct ubus_object *obj, const char *ubus_method_name, 1115 struct blob_attr *msg, uc_value_t **res) 1116 { 1117 uc_ubus_object_t *uuobj = (uc_ubus_object_t *)obj; 1118 const struct ubus_method *method = NULL; 1119 const struct blobmsg_hdr *hdr; 1120 struct blob_attr *attr; 1121 size_t len; 1122 bool found; 1123 int i; 1124 1125 for (i = 0; i < obj->n_methods; i++) { 1126 if (!strcmp(obj->methods[i].name, ubus_method_name)) { 1127 method = &obj->methods[i]; 1128 break; 1129 } 1130 } 1131 1132 if (!method) 1133 return UBUS_STATUS_METHOD_NOT_FOUND; 1134 1135 len = blob_len(msg); 1136 1137 __blob_for_each_attr(attr, blob_data(msg), len) { 1138 if (!blobmsg_check_attr_len(attr, false, len)) 1139 return UBUS_STATUS_INVALID_ARGUMENT; 1140 1141 if (!blob_is_extended(attr)) 1142 return UBUS_STATUS_INVALID_ARGUMENT; 1143 1144 hdr = blob_data(attr); 1145 found = false; 1146 1147 for (i = 0; i < method->n_policy; i++) { 1148 if (blobmsg_namelen(hdr) != strlen(method->policy[i].name)) 1149 continue; 1150 1151 if (strcmp(method->policy[i].name, (char *)hdr->name)) 1152 continue; 1153 1154 /* named argument found but wrong type */ 1155 if (blob_id(attr) != method->policy[i].type) 1156 goto inval; 1157 1158 found = true; 1159 break; 1160 } 1161 1162 /* named argument not found in policy */ 1163 if (!found) 1164 goto inval; 1165 } 1166 1167 *res = blob_array_to_ucv(uuobj->vm, blob_data(msg), blob_len(msg), true); 1168 1169 return UBUS_STATUS_OK; 1170 1171 inval: 1172 *res = NULL; 1173 1174 return UBUS_STATUS_INVALID_ARGUMENT; 1175 } 1176 1177 static uc_value_t * 1178 uc_ubus_object_call_info(uc_vm_t *vm, 1179 struct ubus_context *ctx, struct ubus_request_data *req, 1180 struct ubus_object *obj, const char *ubus_method_name) 1181 { 1182 uc_value_t *info, *o; 1183 1184 info = ucv_object_new(vm); 1185 1186 o = ucv_object_new(vm); 1187 1188 ucv_object_add(o, "user", ucv_string_new(req->acl.user)); 1189 ucv_object_add(o, "group", ucv_string_new(req->acl.group)); 1190 1191 if (req->acl.object) 1192 ucv_object_add(o, "object", ucv_string_new(req->acl.object)); 1193 1194 ucv_object_add(info, "acl", o); 1195 1196 o = ucv_object_new(vm); 1197 1198 ucv_object_add(o, "id", ucv_int64_new(obj->id)); 1199 1200 if (obj->name) 1201 ucv_object_add(o, "name", ucv_string_new(obj->name)); 1202 1203 if (obj->path) 1204 ucv_object_add(o, "path", ucv_string_new(obj->path)); 1205 1206 ucv_object_add(info, "object", o); 1207 1208 if (ubus_method_name) 1209 ucv_object_add(info, "method", ucv_string_new(ubus_method_name)); 1210 1211 return info; 1212 } 1213 1214 static int 1215 uc_ubus_handle_reply_common(struct ubus_context *ctx, 1216 struct ubus_request_data *req, 1217 uc_vm_t *vm, uc_value_t *this, uc_value_t *func, 1218 uc_value_t *reqproto) 1219 { 1220 uc_ubus_request_t *callctx; 1221 uc_value_t *reqobj, *res; 1222 int rv; 1223 1224 /* allocate deferred method call context */ 1225 callctx = xalloc(sizeof(*callctx)); 1226 callctx->ctx = ctx; 1227 callctx->vm = vm; 1228 1229 ubus_defer_request(ctx, req, &callctx->req); 1230 1231 /* create ucode request type object and set properties */ 1232 reqobj = uc_resource_new(request_type, callctx); 1233 1234 if (reqproto) 1235 ucv_prototype_set(ucv_prototype_get(reqobj), reqproto); 1236 1237 /* push object context, handler and request object onto stack */ 1238 uc_vm_stack_push(vm, ucv_get(this)); 1239 uc_vm_stack_push(vm, ucv_get(func)); 1240 uc_vm_stack_push(vm, ucv_get(reqobj)); 1241 1242 /* execute request handler function */ 1243 switch (uc_vm_call(vm, true, 1)) { 1244 case EXCEPTION_NONE: 1245 res = uc_vm_stack_pop(vm); 1246 1247 /* The handler function invoked a nested aync ubus request and returned it */ 1248 if (ucv_resource_dataptr(res, "ubus.deferred")) { 1249 /* Install guard timer in case the reply callback is never called */ 1250 callctx->timeout.cb = uc_ubus_request_timeout; 1251 uloop_timeout_set(&callctx->timeout, 10000 /* FIXME */); 1252 1253 /* Add wrapped request context into registry to prevent GC'ing 1254 * until reply or timeout occurred */ 1255 callctx->registry_index = request_reg_add(vm, ucv_get(reqobj), NULL, NULL); 1256 } 1257 1258 /* Otherwise, when the function returned an object, treat it as 1259 * reply data and conclude deferred request immediately */ 1260 else if (ucv_type(res) == UC_OBJECT) { 1261 blob_buf_init(&buf, 0); 1262 ucv_object_to_blob(res, &buf); 1263 ubus_send_reply(ctx, &callctx->req, buf.head); 1264 1265 ubus_complete_deferred_request(ctx, &callctx->req, UBUS_STATUS_OK); 1266 callctx->replied = true; 1267 } 1268 1269 /* If neither a deferred ubus request, nor a plain object were 1270 * returned and if reqobj.reply() hasn't been called, immediately 1271 * finish deferred request with UBUS_STATUS_NO_DATA. */ 1272 else if (!callctx->replied && !callctx->deferred) { 1273 rv = UBUS_STATUS_NO_DATA; 1274 1275 if (ucv_type(res) == UC_INTEGER) { 1276 rv = (int)ucv_int64_get(res); 1277 1278 if (rv < 0 || rv > __UBUS_STATUS_LAST) 1279 rv = UBUS_STATUS_UNKNOWN_ERROR; 1280 } 1281 1282 ubus_complete_deferred_request(ctx, &callctx->req, rv); 1283 callctx->replied = true; 1284 } 1285 1286 ucv_put(res); 1287 break; 1288 1289 /* if the handler function invoked exit(), forward exit status as ubus 1290 * return code, map out of range values to UBUS_STATUS_UNKNOWN_ERROR. */ 1291 case EXCEPTION_EXIT: 1292 rv = vm->arg.s32; 1293 1294 if (rv < UBUS_STATUS_OK || rv >= __UBUS_STATUS_LAST) 1295 rv = UBUS_STATUS_UNKNOWN_ERROR; 1296 1297 ubus_complete_deferred_request(ctx, &callctx->req, rv); 1298 callctx->replied = true; 1299 break; 1300 1301 /* treat other exceptions as fatal and halt uloop */ 1302 default: 1303 ubus_complete_deferred_request(ctx, &callctx->req, UBUS_STATUS_UNKNOWN_ERROR); 1304 uloop_end(); 1305 callctx->replied = true; 1306 break; 1307 } 1308 1309 /* release request object */ 1310 ucv_put(reqobj); 1311 1312 /* garbage collect */ 1313 ucv_gc(vm); 1314 1315 return UBUS_STATUS_OK; 1316 } 1317 1318 static int 1319 uc_ubus_object_call_cb(struct ubus_context *ctx, struct ubus_object *obj, 1320 struct ubus_request_data *req, const char *ubus_method_name, 1321 struct blob_attr *msg) 1322 { 1323 uc_value_t *this, *func, *args = NULL, *reqproto, *methods; 1324 uc_ubus_object_t *uuobj = (uc_ubus_object_t *)obj; 1325 int rv; 1326 1327 object_reg_get(uuobj->vm, uuobj->registry_index, &this, &methods, NULL); 1328 1329 func = ucv_object_get(ucv_object_get(methods, ubus_method_name, NULL), "call", NULL); 1330 1331 if (!ucv_is_callable(func)) 1332 return UBUS_STATUS_METHOD_NOT_FOUND; 1333 1334 rv = uc_ubus_object_call_args(obj, ubus_method_name, msg, &args); 1335 1336 if (rv != UBUS_STATUS_OK) 1337 return rv; 1338 1339 reqproto = ucv_object_new(uuobj->vm); 1340 1341 ucv_object_add(reqproto, "args", args); 1342 ucv_object_add(reqproto, "info", 1343 uc_ubus_object_call_info(uuobj->vm, ctx, req, obj, ubus_method_name)); 1344 1345 return uc_ubus_handle_reply_common(ctx, req, uuobj->vm, this, func, reqproto); 1346 } 1347 1348 1349 /* 1350 * ubus object registration 1351 * -------------------------------------------------------------------------- 1352 */ 1353 1354 static void 1355 uc_ubus_object_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj) 1356 { 1357 uc_ubus_object_t *uuobj = (uc_ubus_object_t *)obj; 1358 uc_value_t *this, *func; 1359 1360 object_reg_get(uuobj->vm, uuobj->registry_index, &this, NULL, &func); 1361 1362 uc_vm_stack_push(uuobj->vm, ucv_get(this)); 1363 uc_vm_stack_push(uuobj->vm, ucv_get(func)); 1364 1365 if (uc_vm_call(uuobj->vm, true, 0) == EXCEPTION_NONE) 1366 ucv_put(uc_vm_stack_pop(uuobj->vm)); 1367 else 1368 uloop_end(); 1369 } 1370 1371 static bool 1372 uc_ubus_object_methods_validate(uc_value_t *methods) 1373 { 1374 uc_value_t *func, *args; 1375 1376 ucv_object_foreach(methods, ubus_method_name, ubus_method_definition) { 1377 (void)ubus_method_name; 1378 1379 func = ucv_object_get(ubus_method_definition, "call", NULL); 1380 args = ucv_object_get(ubus_method_definition, "args", NULL); 1381 1382 if (!ucv_is_callable(func)) 1383 err_return(UBUS_STATUS_INVALID_ARGUMENT, 1384 "Method '%s' field 'call' is not a function value", 1385 ubus_method_name); 1386 1387 if (args) { 1388 if (ucv_type(args) != UC_OBJECT) 1389 err_return(UBUS_STATUS_INVALID_ARGUMENT, 1390 "Method '%s' field 'args' is not an object value", 1391 ubus_method_name); 1392 1393 ucv_object_foreach(args, ubus_argument_name, ubus_argument_typehint) { 1394 (void)ubus_argument_name; 1395 1396 switch (ucv_type(ubus_argument_typehint)) { 1397 case UC_BOOLEAN: 1398 case UC_INTEGER: 1399 case UC_DOUBLE: 1400 case UC_STRING: 1401 case UC_ARRAY: 1402 case UC_OBJECT: 1403 continue; 1404 1405 default: 1406 err_return(UBUS_STATUS_INVALID_ARGUMENT, 1407 "Method '%s' field 'args' argument '%s' hint has unsupported type %s", 1408 ubus_method_name, ubus_argument_name, 1409 ucv_typename(ubus_argument_typehint)); 1410 } 1411 } 1412 } 1413 } 1414 1415 ok_return(true); 1416 } 1417 1418 static bool 1419 uc_ubus_object_method_register(struct ubus_method *method, const char *ubus_method_name, 1420 uc_value_t *ubus_method_arguments) 1421 { 1422 struct blobmsg_policy *policy; 1423 enum blobmsg_type type; 1424 1425 method->name = strdup(ubus_method_name); 1426 method->policy = calloc(ucv_object_length(ubus_method_arguments), sizeof(*method->policy)); 1427 method->handler = uc_ubus_object_call_cb; 1428 1429 if (!method->name || !method->policy) 1430 return false; 1431 1432 ucv_object_foreach(ubus_method_arguments, ubus_argument_name, ubus_argument_typehint) { 1433 switch (ucv_type(ubus_argument_typehint)) { 1434 case UC_BOOLEAN: 1435 type = BLOBMSG_TYPE_INT8; 1436 break; 1437 1438 case UC_INTEGER: 1439 switch (ucv_int64_get(ubus_argument_typehint)) { 1440 case 8: 1441 type = BLOBMSG_TYPE_INT8; 1442 break; 1443 1444 case 16: 1445 type = BLOBMSG_TYPE_INT16; 1446 break; 1447 1448 case 64: 1449 type = BLOBMSG_TYPE_INT64; 1450 break; 1451 1452 default: 1453 type = BLOBMSG_TYPE_INT32; 1454 break; 1455 } 1456 1457 break; 1458 1459 case UC_DOUBLE: 1460 type = BLOBMSG_TYPE_DOUBLE; 1461 break; 1462 1463 case UC_ARRAY: 1464 type = BLOBMSG_TYPE_ARRAY; 1465 break; 1466 1467 case UC_OBJECT: 1468 type = BLOBMSG_TYPE_TABLE; 1469 break; 1470 1471 default: 1472 type = BLOBMSG_TYPE_STRING; 1473 break; 1474 } 1475 1476 policy = (struct blobmsg_policy *)&method->policy[method->n_policy++]; 1477 policy->type = type; 1478 policy->name = strdup(ubus_argument_name); 1479 1480 if (!policy->name) 1481 return false; 1482 } 1483 1484 return true; 1485 } 1486 1487 static uc_ubus_object_t * 1488 uc_ubus_object_register(struct ubus_context *ctx, const char *ubus_object_name, 1489 uc_value_t *ubus_object_methods) 1490 { 1491 const struct blobmsg_policy *policy; 1492 uc_ubus_object_t *uuobj = NULL; 1493 int rv = UBUS_STATUS_UNKNOWN_ERROR; 1494 char *tptr, *tnptr, *onptr, *mptr; 1495 struct ubus_method *method; 1496 struct ubus_object *obj; 1497 size_t typelen, namelen; 1498 uc_value_t *args; 1499 1500 namelen = strlen(ubus_object_name); 1501 typelen = strlen("ucode-ubus-") + namelen; 1502 1503 uuobj = calloc_a(sizeof(*uuobj), 1504 &onptr, namelen + 1, 1505 &mptr, ucv_object_length(ubus_object_methods) * sizeof(struct ubus_method), 1506 &tptr, sizeof(struct ubus_object_type), 1507 &tnptr, typelen + 1); 1508 1509 if (!uuobj) 1510 err_return(rv, "Out of memory"); 1511 1512 snprintf(tnptr, typelen, "ucode-ubus-%s", ubus_object_name); 1513 1514 method = (struct ubus_method *)mptr; 1515 1516 obj = &uuobj->obj; 1517 obj->name = memcpy(onptr, ubus_object_name, namelen); 1518 obj->methods = method; 1519 1520 if (ubus_object_methods) { 1521 ucv_object_foreach(ubus_object_methods, ubus_method_name, ubus_method_definition) { 1522 args = ucv_object_get(ubus_method_definition, "args", NULL); 1523 1524 if (!uc_ubus_object_method_register(&method[obj->n_methods++], ubus_method_name, args)) 1525 goto out; 1526 } 1527 } 1528 1529 obj->type = (struct ubus_object_type *)tptr; 1530 obj->type->name = tnptr; 1531 obj->type->methods = obj->methods; 1532 obj->type->n_methods = obj->n_methods; 1533 1534 rv = ubus_add_object(ctx, obj); 1535 1536 if (rv == UBUS_STATUS_OK) 1537 return uuobj; 1538 1539 out: 1540 for (; obj->n_methods > 0; method++, obj->n_methods--) { 1541 for (policy = method->policy; method->n_policy > 0; policy++, method->n_policy--) 1542 free((char *)policy->name); 1543 1544 free((char *)method->name); 1545 free((char *)method->policy); 1546 } 1547 1548 free(uuobj); 1549 1550 err_return(rv, "Unable to add ubus object"); 1551 } 1552 1553 static uc_value_t * 1554 uc_ubus_publish(uc_vm_t *vm, size_t nargs) 1555 { 1556 uc_value_t *objname, *methods, *subscribecb; 1557 uc_ubus_connection_t *c; 1558 uc_ubus_object_t *uuobj; 1559 uc_value_t *res; 1560 1561 conn_get(vm, &c); 1562 1563 args_get(vm, nargs, 1564 "object name", UC_STRING, false, &objname, 1565 "object methods", UC_OBJECT, true, &methods, 1566 "subscribe callback", UC_CLOSURE, true, &subscribecb); 1567 1568 if (!methods && !subscribecb) 1569 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Either methods or subscribe callback required"); 1570 1571 if (methods && !uc_ubus_object_methods_validate(methods)) 1572 return NULL; 1573 1574 uuobj = uc_ubus_object_register(&c->ctx, ucv_string_get(objname), methods); 1575 1576 if (!uuobj) 1577 return NULL; 1578 1579 if (subscribecb) 1580 uuobj->obj.subscribe_cb = uc_ubus_object_subscribe_cb; 1581 1582 res = uc_resource_new(object_type, uuobj); 1583 1584 uuobj->vm = vm; 1585 uuobj->ctx = &c->ctx; 1586 uuobj->registry_index = object_reg_add(vm, ucv_get(res), ucv_get(methods), ucv_get(subscribecb)); 1587 1588 ok_return(res); 1589 } 1590 1591 1592 /* 1593 * ubus events 1594 * -------------------------------------------------------------------------- 1595 */ 1596 1597 static int 1598 uc_ubus_listener_remove_common(uc_ubus_listener_t *uul) 1599 { 1600 int rv = ubus_unregister_event_handler(uul->ctx, &uul->ev); 1601 1602 if (rv == UBUS_STATUS_OK) 1603 listener_reg_clear(uul->vm, uul->registry_index); 1604 1605 return rv; 1606 } 1607 1608 static uc_value_t * 1609 uc_ubus_listener_remove(uc_vm_t *vm, size_t nargs) 1610 { 1611 uc_ubus_listener_t **uul = uc_fn_this("ubus.listener"); 1612 int rv; 1613 1614 if (!uul || !*uul) 1615 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid listener context"); 1616 1617 rv = uc_ubus_listener_remove_common(*uul); 1618 1619 if (rv != UBUS_STATUS_OK) 1620 err_return(rv, "Failed to remove listener object"); 1621 1622 ok_return(ucv_boolean_new(true)); 1623 } 1624 1625 static void 1626 uc_ubus_listener_cb(struct ubus_context *ctx, struct ubus_event_handler *ev, 1627 const char *type, struct blob_attr *msg) 1628 { 1629 uc_ubus_listener_t *uul = (uc_ubus_listener_t *)ev; 1630 uc_value_t *this, *func; 1631 1632 listener_reg_get(uul->vm, uul->registry_index, &this, &func); 1633 1634 uc_vm_stack_push(uul->vm, ucv_get(this)); 1635 uc_vm_stack_push(uul->vm, ucv_get(func)); 1636 uc_vm_stack_push(uul->vm, ucv_string_new(type)); 1637 uc_vm_stack_push(uul->vm, blob_array_to_ucv(uul->vm, blob_data(msg), blob_len(msg), true)); 1638 1639 if (uc_vm_call(uul->vm, true, 2) == EXCEPTION_NONE) 1640 ucv_put(uc_vm_stack_pop(uul->vm)); 1641 else 1642 uloop_end(); 1643 } 1644 1645 static uc_value_t * 1646 uc_ubus_listener(uc_vm_t *vm, size_t nargs) 1647 { 1648 uc_value_t *cb, *pattern; 1649 uc_ubus_connection_t *c; 1650 uc_ubus_listener_t *uul; 1651 uc_value_t *res; 1652 int rv; 1653 1654 conn_get(vm, &c); 1655 1656 args_get(vm, nargs, 1657 "event type pattern", UC_STRING, false, &pattern, 1658 "event callback", UC_CLOSURE, false, &cb); 1659 1660 uul = xalloc(sizeof(*uul)); 1661 uul->vm = vm; 1662 uul->ctx = &c->ctx; 1663 uul->ev.cb = uc_ubus_listener_cb; 1664 1665 rv = ubus_register_event_handler(&c->ctx, &uul->ev, 1666 ucv_string_get(pattern)); 1667 1668 if (rv != UBUS_STATUS_OK) { 1669 free(uul); 1670 err_return(rv, "Failed to register listener object"); 1671 } 1672 1673 res = uc_resource_new(listener_type, uul); 1674 1675 uul->registry_index = listener_reg_add(vm, ucv_get(res), ucv_get(cb)); 1676 1677 ok_return(res); 1678 } 1679 1680 static uc_value_t * 1681 uc_ubus_event(uc_vm_t *vm, size_t nargs) 1682 { 1683 uc_value_t *eventtype, *eventdata; 1684 uc_ubus_connection_t *c; 1685 int rv; 1686 1687 conn_get(vm, &c); 1688 1689 args_get(vm, nargs, 1690 "event id", UC_STRING, false, &eventtype, 1691 "event data", UC_OBJECT, true, &eventdata); 1692 1693 blob_buf_init(&buf, 0); 1694 1695 if (eventdata) 1696 ucv_object_to_blob(eventdata, &buf); 1697 1698 rv = ubus_send_event(&c->ctx, ucv_string_get(eventtype), buf.head); 1699 1700 if (rv != UBUS_STATUS_OK) 1701 err_return(rv, "Unable to send event"); 1702 1703 ok_return(ucv_boolean_new(true)); 1704 } 1705 1706 1707 /* 1708 * ubus subscriptions 1709 * -------------------------------------------------------------------------- 1710 */ 1711 1712 static int 1713 uc_ubus_subscriber_notify_cb(struct ubus_context *ctx, struct ubus_object *obj, 1714 struct ubus_request_data *req, const char *method, 1715 struct blob_attr *msg) 1716 { 1717 struct ubus_subscriber *sub = container_of(obj, struct ubus_subscriber, obj); 1718 uc_ubus_subscriber_t *uusub = container_of(sub, uc_ubus_subscriber_t, sub); 1719 uc_value_t *this, *func, *reqproto; 1720 1721 subscriber_reg_get(uusub->vm, uusub->registry_index, &this, &func, NULL); 1722 1723 if (!ucv_is_callable(func)) 1724 return UBUS_STATUS_METHOD_NOT_FOUND; 1725 1726 reqproto = ucv_object_new(uusub->vm); 1727 1728 ucv_object_add(reqproto, "type", ucv_string_new(method)); 1729 1730 ucv_object_add(reqproto, "data", 1731 blob_array_to_ucv(uusub->vm, blob_data(msg), blob_len(msg), true)); 1732 1733 ucv_object_add(reqproto, "info", 1734 uc_ubus_object_call_info(uusub->vm, ctx, req, obj, NULL)); 1735 1736 return uc_ubus_handle_reply_common(ctx, req, uusub->vm, this, func, reqproto); 1737 } 1738 1739 static void 1740 uc_ubus_subscriber_remove_cb(struct ubus_context *ctx, 1741 struct ubus_subscriber *sub, uint32_t id) 1742 { 1743 uc_ubus_subscriber_t *uusub = container_of(sub, uc_ubus_subscriber_t, sub); 1744 uc_value_t *this, *func; 1745 1746 subscriber_reg_get(uusub->vm, uusub->registry_index, &this, NULL, &func); 1747 1748 if (!ucv_is_callable(func)) 1749 return; 1750 1751 uc_vm_stack_push(uusub->vm, ucv_get(this)); 1752 uc_vm_stack_push(uusub->vm, ucv_get(func)); 1753 uc_vm_stack_push(uusub->vm, ucv_uint64_new(id)); 1754 1755 if (uc_vm_call(uusub->vm, true, 1) == EXCEPTION_NONE) 1756 ucv_put(uc_vm_stack_pop(uusub->vm)); 1757 else 1758 uloop_end(); 1759 } 1760 1761 static uc_value_t * 1762 uc_ubus_subscriber_subunsub_common(uc_vm_t *vm, size_t nargs, bool subscribe) 1763 { 1764 uc_ubus_subscriber_t **uusub = uc_fn_this("ubus.subscriber"); 1765 uc_value_t *objname; 1766 uint32_t id; 1767 int rv; 1768 1769 if (!uusub || !*uusub) 1770 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid subscriber context"); 1771 1772 args_get(vm, nargs, 1773 "object name", UC_STRING, false, &objname); 1774 1775 rv = ubus_lookup_id((*uusub)->ctx, ucv_string_get(objname), &id); 1776 1777 if (rv != UBUS_STATUS_OK) 1778 err_return(rv, "Failed to resolve object name '%s'", 1779 ucv_string_get(objname)); 1780 1781 if (subscribe) 1782 rv = ubus_subscribe((*uusub)->ctx, &(*uusub)->sub, id); 1783 else 1784 rv = ubus_unsubscribe((*uusub)->ctx, &(*uusub)->sub, id); 1785 1786 if (rv != UBUS_STATUS_OK) 1787 err_return(rv, "Failed to %s object '%s'", 1788 subscribe ? "subscribe" : "unsubscribe", 1789 ucv_string_get(objname)); 1790 1791 ok_return(ucv_boolean_new(true)); 1792 } 1793 1794 static uc_value_t * 1795 uc_ubus_subscriber_subscribe(uc_vm_t *vm, size_t nargs) 1796 { 1797 return uc_ubus_subscriber_subunsub_common(vm, nargs, true); 1798 } 1799 1800 static uc_value_t * 1801 uc_ubus_subscriber_unsubscribe(uc_vm_t *vm, size_t nargs) 1802 { 1803 return uc_ubus_subscriber_subunsub_common(vm, nargs, false); 1804 } 1805 1806 static int 1807 uc_ubus_subscriber_remove_common(uc_ubus_subscriber_t *uusub) 1808 { 1809 int rv = ubus_unregister_subscriber(uusub->ctx, &uusub->sub); 1810 1811 if (rv == UBUS_STATUS_OK) 1812 subscriber_reg_clear(uusub->vm, uusub->registry_index); 1813 1814 return rv; 1815 } 1816 1817 static uc_value_t * 1818 uc_ubus_subscriber_remove(uc_vm_t *vm, size_t nargs) 1819 { 1820 uc_ubus_subscriber_t **uusub = uc_fn_this("ubus.subscriber"); 1821 int rv; 1822 1823 if (!uusub || !*uusub) 1824 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid subscriber context"); 1825 1826 rv = uc_ubus_subscriber_remove_common(*uusub); 1827 1828 if (rv != UBUS_STATUS_OK) 1829 err_return(rv, "Failed to remove subscriber object"); 1830 1831 ok_return(ucv_boolean_new(true)); 1832 } 1833 1834 static uc_value_t * 1835 uc_ubus_subscriber(uc_vm_t *vm, size_t nargs) 1836 { 1837 uc_value_t *notify_cb, *remove_cb; 1838 uc_ubus_subscriber_t *uusub; 1839 uc_ubus_connection_t *c; 1840 uc_value_t *res; 1841 int rv; 1842 1843 conn_get(vm, &c); 1844 1845 args_get(vm, nargs, 1846 "notify callback", UC_CLOSURE, true, ¬ify_cb, 1847 "remove callback", UC_CLOSURE, true, &remove_cb); 1848 1849 if (!notify_cb && !remove_cb) 1850 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Either notify or remove callback required"); 1851 1852 uusub = xalloc(sizeof(*uusub)); 1853 uusub->vm = vm; 1854 uusub->ctx = &c->ctx; 1855 1856 rv = ubus_register_subscriber(&c->ctx, &uusub->sub); 1857 1858 if (rv != UBUS_STATUS_OK) { 1859 free(uusub); 1860 err_return(rv, "Failed to register subscriber object"); 1861 } 1862 1863 if (notify_cb) 1864 uusub->sub.cb = uc_ubus_subscriber_notify_cb; 1865 1866 if (remove_cb) 1867 uusub->sub.remove_cb = uc_ubus_subscriber_remove_cb; 1868 1869 res = uc_resource_new(subscriber_type, uusub); 1870 1871 uusub->registry_index = subscriber_reg_add(vm, 1872 ucv_get(res), ucv_get(notify_cb), ucv_get(remove_cb)); 1873 1874 ok_return(res); 1875 } 1876 1877 1878 /* 1879 * connection methods 1880 * -------------------------------------------------------------------------- 1881 */ 1882 1883 static uc_value_t * 1884 uc_ubus_remove(uc_vm_t *vm, size_t nargs) 1885 { 1886 uc_ubus_subscriber_t **uusub; 1887 uc_ubus_connection_t *c; 1888 uc_ubus_object_t **uuobj; 1889 uc_ubus_listener_t **uul; 1890 int rv; 1891 1892 conn_get(vm, &c); 1893 1894 uusub = (uc_ubus_subscriber_t **)ucv_resource_dataptr(uc_fn_arg(0), "ubus.subscriber"); 1895 uuobj = (uc_ubus_object_t **)ucv_resource_dataptr(uc_fn_arg(0), "ubus.object"); 1896 uul = (uc_ubus_listener_t **)ucv_resource_dataptr(uc_fn_arg(0), "ubus.listener"); 1897 1898 if (uusub && *uusub) { 1899 if ((*uusub)->ctx != &c->ctx) 1900 err_return(UBUS_STATUS_INVALID_ARGUMENT, 1901 "Subscriber belongs to different connection"); 1902 1903 rv = uc_ubus_subscriber_remove_common(*uusub); 1904 1905 if (rv != UBUS_STATUS_OK) 1906 err_return(rv, "Unable to remove subscriber"); 1907 } 1908 else if (uuobj && *uuobj) { 1909 if ((*uuobj)->ctx != &c->ctx) 1910 err_return(UBUS_STATUS_INVALID_ARGUMENT, 1911 "Object belongs to different connection"); 1912 1913 rv = uc_ubus_object_remove_common(*uuobj); 1914 1915 if (rv != UBUS_STATUS_OK) 1916 err_return(rv, "Unable to remove object"); 1917 } 1918 else if (uul && *uul) { 1919 if ((*uul)->ctx != &c->ctx) 1920 err_return(UBUS_STATUS_INVALID_ARGUMENT, 1921 "Listener belongs to different connection"); 1922 1923 rv = uc_ubus_listener_remove_common(*uul); 1924 1925 if (rv != UBUS_STATUS_OK) 1926 err_return(rv, "Unable to remove listener"); 1927 } 1928 else { 1929 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Unhandled resource type"); 1930 } 1931 1932 ok_return(ucv_boolean_new(true)); 1933 } 1934 1935 1936 static uc_value_t * 1937 uc_ubus_disconnect(uc_vm_t *vm, size_t nargs) 1938 { 1939 uc_ubus_connection_t *c; 1940 1941 conn_get(vm, &c); 1942 1943 ubus_shutdown(&c->ctx); 1944 c->ctx.sock.fd = -1; 1945 1946 ok_return(ucv_boolean_new(true)); 1947 } 1948 1949 static uc_value_t * 1950 uc_ubus_defer_completed(uc_vm_t *vm, size_t nargs) 1951 { 1952 uc_ubus_deferred_t **d = uc_fn_this("ubus.deferred"); 1953 1954 if (!d || !*d) 1955 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid deferred context"); 1956 1957 ok_return(ucv_boolean_new((*d)->complete)); 1958 } 1959 1960 static uc_value_t * 1961 uc_ubus_defer_abort(uc_vm_t *vm, size_t nargs) 1962 { 1963 uc_ubus_deferred_t **d = uc_fn_this("ubus.deferred"); 1964 1965 if (!d || !*d) 1966 err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid deferred context"); 1967 1968 if ((*d)->complete) 1969 ok_return(ucv_boolean_new(false)); 1970 1971 ubus_abort_request((*d)->ctx, &(*d)->request); 1972 uloop_timeout_cancel(&(*d)->timeout); 1973 1974 request_reg_clear((*d)->vm, (*d)->registry_index); 1975 1976 n_cb_active--; 1977 1978 if (have_own_uloop && n_cb_active == 0) 1979 uloop_end(); 1980 1981 (*d)->complete = true; 1982 1983 ok_return(ucv_boolean_new(true)); 1984 } 1985 1986 1987 static const uc_function_list_t global_fns[] = { 1988 { "error", uc_ubus_error }, 1989 { "connect", uc_ubus_connect }, 1990 }; 1991 1992 static const uc_function_list_t conn_fns[] = { 1993 { "list", uc_ubus_list }, 1994 { "call", uc_ubus_call }, 1995 { "defer", uc_ubus_defer }, 1996 { "publish", uc_ubus_publish }, 1997 { "remove", uc_ubus_remove }, 1998 { "listener", uc_ubus_listener }, 1999 { "subscriber", uc_ubus_subscriber }, 2000 { "event", uc_ubus_event }, 2001 { "error", uc_ubus_error }, 2002 { "disconnect", uc_ubus_disconnect }, 2003 }; 2004 2005 static const uc_function_list_t defer_fns[] = { 2006 { "completed", uc_ubus_defer_completed }, 2007 { "abort", uc_ubus_defer_abort }, 2008 }; 2009 2010 static const uc_function_list_t object_fns[] = { 2011 { "subscribed", uc_ubus_object_subscribed }, 2012 { "notify", uc_ubus_object_notify }, 2013 { "remove", uc_ubus_object_remove }, 2014 }; 2015 2016 static const uc_function_list_t request_fns[] = { 2017 { "reply", uc_ubus_request_reply }, 2018 { "error", uc_ubus_request_error }, 2019 { "defer", uc_ubus_request_defer }, 2020 }; 2021 2022 static const uc_function_list_t notify_fns[] = { 2023 { "completed", uc_ubus_notify_completed }, 2024 { "abort", uc_ubus_notify_abort }, 2025 }; 2026 2027 static const uc_function_list_t listener_fns[] = { 2028 { "remove", uc_ubus_listener_remove }, 2029 }; 2030 2031 static const uc_function_list_t subscriber_fns[] = { 2032 { "subscribe", uc_ubus_subscriber_subscribe }, 2033 { "unsubscribe", uc_ubus_subscriber_unsubscribe }, 2034 { "remove", uc_ubus_subscriber_remove }, 2035 }; 2036 2037 static void free_connection(void *ud) { 2038 uc_ubus_connection_t *conn = ud; 2039 2040 blob_buf_free(&conn->buf); 2041 2042 if (conn->ctx.sock.fd >= 0) 2043 ubus_shutdown(&conn->ctx); 2044 2045 free(conn); 2046 } 2047 2048 static void free_deferred(void *ud) { 2049 uc_ubus_deferred_t *defer = ud; 2050 2051 uloop_timeout_cancel(&defer->timeout); 2052 ucv_put(defer->response); 2053 free(defer); 2054 } 2055 2056 static void free_object(void *ud) { 2057 uc_ubus_object_t *uuobj = ud; 2058 struct ubus_object *obj = &uuobj->obj; 2059 int i, j; 2060 2061 for (i = 0; i < obj->n_methods; i++) { 2062 for (j = 0; j < obj->methods[i].n_policy; j++) 2063 free((char *)obj->methods[i].policy[j].name); 2064 2065 free((char *)obj->methods[i].name); 2066 free((char *)obj->methods[i].policy); 2067 } 2068 2069 free(uuobj); 2070 } 2071 2072 static void free_request(void *ud) { 2073 uc_ubus_request_t *callctx = ud; 2074 2075 uc_ubus_request_finish(callctx, UBUS_STATUS_TIMEOUT, NULL); 2076 uloop_timeout_cancel(&callctx->timeout); 2077 free(callctx); 2078 } 2079 2080 static void free_notify(void *ud) { 2081 uc_ubus_notify_t *notifyctx = ud; 2082 2083 free(notifyctx); 2084 } 2085 2086 static void free_listener(void *ud) { 2087 uc_ubus_listener_t *listener = ud; 2088 2089 free(listener); 2090 } 2091 2092 static void free_subscriber(void *ud) { 2093 uc_ubus_subscriber_t *subscriber = ud; 2094 2095 free(subscriber); 2096 } 2097 2098 void uc_module_init(uc_vm_t *vm, uc_value_t *scope) 2099 { 2100 uc_function_list_register(scope, global_fns); 2101 2102 #define ADD_CONST(x) ucv_object_add(scope, #x, ucv_int64_new(UBUS_##x)) 2103 ADD_CONST(STATUS_OK); 2104 ADD_CONST(STATUS_INVALID_COMMAND); 2105 ADD_CONST(STATUS_INVALID_ARGUMENT); 2106 ADD_CONST(STATUS_METHOD_NOT_FOUND); 2107 ADD_CONST(STATUS_NOT_FOUND); 2108 ADD_CONST(STATUS_NO_DATA); 2109 ADD_CONST(STATUS_PERMISSION_DENIED); 2110 ADD_CONST(STATUS_TIMEOUT); 2111 ADD_CONST(STATUS_NOT_SUPPORTED); 2112 ADD_CONST(STATUS_UNKNOWN_ERROR); 2113 ADD_CONST(STATUS_CONNECTION_FAILED); 2114 2115 #ifdef HAVE_NEW_UBUS_STATUS_CODES 2116 ADD_CONST(STATUS_NO_MEMORY); 2117 ADD_CONST(STATUS_PARSE_ERROR); 2118 ADD_CONST(STATUS_SYSTEM_ERROR); 2119 #endif 2120 2121 conn_type = uc_type_declare(vm, "ubus.connection", conn_fns, free_connection); 2122 defer_type = uc_type_declare(vm, "ubus.deferred", defer_fns, free_deferred); 2123 object_type = uc_type_declare(vm, "ubus.object", object_fns, free_object); 2124 notify_type = uc_type_declare(vm, "ubus.notify", notify_fns, free_notify); 2125 request_type = uc_type_declare(vm, "ubus.request", request_fns, free_request); 2126 listener_type = uc_type_declare(vm, "ubus.listener", listener_fns, free_listener); 2127 subscriber_type = uc_type_declare(vm, "ubus.subscriber", subscriber_fns, free_subscriber); 2128 } 2129
This page was automatically generated by LXR 0.3.1. • OpenWrt