3 let ubus = require('ubus').connect();
6 * An ucode plugin script is supposed to return a signature object on
7 * invocation which describes the ubus objects the plugin script wants to
8 * register, as well as the related methods and their argument signatures.
12 * Each toplevel key of the returned signature object corresponds to the
13 * name of an ubus object to register.
15 * The value of each key must be a nested dictionary describing the object
20 * Each key within the nested dictionary refers to the name of a method
21 * to define for the parent object.
23 * The value of each method name key must be another nested dictionary
24 * describing the method.
28 * At the very least, each method description dictionary *must*
29 * contain a key "call" with the ucode callback function to call
30 * when the corresponding ubus object method is invoked.
32 * The callback function is supposed to return a dictionary which
33 * is automatically translated into a nested blobmsg structure and
34 * sent back as ubus reply.
36 * Non-dictionary return values are discarded and the ubus method
37 * call will fail with UBUS_STATUS_NO_DATA.
40 return { hello: "world" };
46 * Additionally, method descriptions *may* supply an "args" key
47 * referring to a dictionary describing the ubus method call
50 * The resulting method argument policy is also published to ubus
51 * and visible with "ubus -v list".
53 * The callback function will receive a dictionary containing the
54 * received named arguments as first argument. Only named arguments
55 * present in the "args" dictionary are accepted. Attempts to invoke
56 * ubus methods with arguments not mentioned here or with argument
57 * values not matching the given type hints are rejected with
58 * UBUS_STATUS_INVALID_ARGUMENT.
60 * The expected data type of each named argument is inferred from
61 * the ucode value within the "args" dictionary:
63 * ucode type | ucode value | blob type
64 * -----------+-------------+--------------------
65 * integer | 8 | BLOBMSG_TYPE_INT8
66 * integer | 16 | BLOBMSG_TYPE_INT16
67 * integer | 64 | BLOBMSG_TYPE_INT64
68 * integer | any integer | BLOBMSG_TYPE_INT32
69 * boolean | true, false | BLOBMSG_TYPE_INT8
70 * string | any string | BLOBMSG_TYPE_STRING
71 * double | any double | BLOBMSG_TYPE_DOUBLE
72 * array | any array | BLOBMSG_TYPE_ARRAY
73 * object | any object | BLOBMSG_TYPE_TABLE
75 * The ucode callback function will also receive auxillary status
76 * information about the ubus request within a dictionary passed as
77 * second argument to it. The dictionary will contain details about
78 * the invoked object, the invoked method name (useful in case
79 * multiple methods share the same callback) and the effective ubusd
80 * ACL for this request.
89 call: function(request) {
91 got_args: request.args,
92 got_info: request.info
98 call: function(request) {
100 * Process exit codes are automatically translated to ubus
101 * error status codes. Exit code values outside of the
102 * representable status range are converted to
103 * UBUS_STATUS_UNKNOWN_ERROR.
105 if (request.info.acl.user != "root")
106 exit(UBUS_STATUS_PERMISSION_DENIED);
109 * To invoke nested ubus requests without potentially blocking
110 * rpcd's main loop, use the ubus.defer() method to start an
111 * asynchronous request and issue request.reply() from within
112 * the completion callback. It is important to return the deferred
113 * request value produced by ubus.call_async() to instruct rpcd to
114 * await the completion of the nested request.
116 return ubus.defer('example_object_2', 'method_a', { number: 5 },
117 function(code, reply) {
129 * Runtime exceptions are catched by rpcd, the corresponding
130 * request is replied to with UBUS_STATUS_UNKNOWN_ERROR.
132 die("An error occurred");
139 args: { number: 123 },
140 call: function(request) {
142 * Instead of returning the reply, we can also use the reply
143 * method of the request object.
145 request.reply({ got_number: request.args.number });