### Asynchronous Server Pattern in C Source: https://github.com/openwrt/ubus/blob/master/_autodocs/overview.md Illustrates the setup for an asynchronous server, including connecting, adding an object, starting the event loop, and shutting down. ```c struct ubus_context *ctx = ubus_connect(NULL); ubus_add_object(ctx, &obj); ubus_add_uloop(ctx); uloop_run(); ubus_shutdown(&ctx); ``` -------------------------------- ### Add Subdirectories for Lua and Examples Source: https://github.com/openwrt/ubus/blob/master/CMakeLists.txt Includes build configurations from the 'lua' and 'examples' subdirectories. ```cmake ADD_SUBDIRECTORY(lua) ADD_SUBDIRECTORY(examples) ``` -------------------------------- ### Install Targets and Headers Source: https://github.com/openwrt/ubus/blob/master/CMakeLists.txt Defines installation rules for the 'ubus' and 'ubusd' executables, the 'ubus' library, and header files. ```cmake INSTALL(TARGETS ubus cli ARCHIVE DESTINATION lib LIBRARY DESTINATION lib RUNTIME DESTINATION bin ) INSTALL(TARGETS ubusd RUNTIME DESTINATION sbin ) INSTALL(FILES ubusmsg.h ubus_common.h libubus.h DESTINATION include) ``` -------------------------------- ### Minimal uBus Setup Source: https://github.com/openwrt/ubus/blob/master/_autodocs/configuration.md Establishes a minimal uBus connection using the default socket. Frees the context after use. ```c struct ubus_context *ctx = ubus_connect(NULL); if (!ctx) { fprintf(stderr, "Failed to connect\n"); return -1; } // Use context ubus_free(ctx); ``` -------------------------------- ### Set up Python Virtual Environment for Cram Tests Source: https://github.com/openwrt/ubus/blob/master/tests/cram/CMakeLists.txt Configures a Python virtual environment and installs the 'cram' testing tool. This setup is required before running cram tests. ```cmake FIND_PACKAGE(PythonInterp 3 REQUIRED) FILE(GLOB test_cases "test_*.t") SET(PYTHON_VENV_DIR "${CMAKE_CURRENT_BINARY_DIR}/.venv") SET(PYTHON_VENV_PIP "${PYTHON_VENV_DIR}/bin/pip") SET(PYTHON_VENV_CRAM "${PYTHON_VENV_DIR}/bin/cram") ADD_CUSTOM_COMMAND( OUTPUT ${PYTHON_VENV_CRAM} COMMAND ${PYTHON_EXECUTABLE} -m venv ${PYTHON_VENV_DIR} COMMAND ${PYTHON_VENV_PIP} install cram ) ADD_CUSTOM_TARGET(prepare-cram-venv ALL DEPENDS ${PYTHON_VENV_CRAM}) ``` -------------------------------- ### Build Options for Lua and Examples Source: https://github.com/openwrt/ubus/blob/master/CMakeLists.txt Defines build options to enable or disable the building of the Lua plugin and examples. Defaults are set to ON. ```cmake OPTION(BUILD_LUA "build Lua plugin" ON) OPTION(BUILD_EXAMPLES "build examples" ON) ``` -------------------------------- ### Example uBus Method with Tags Source: https://github.com/openwrt/ubus/blob/master/_autodocs/configuration.md Demonstrates defining uBus methods with associated tags, such as `UBUS_TAG_STATUS` for status methods and `UBUS_TAG_ADMIN` for administrative methods. ```c struct ubus_method methods[] = { UBUS_METHOD_TAG("status", status_handler, status_policy, UBUS_TAG_STATUS), UBUS_METHOD_TAG("reboot", reboot_handler, NULL, UBUS_TAG_ADMIN), }; ``` -------------------------------- ### Set up ubus Monitor Callback Source: https://github.com/openwrt/ubus/blob/master/_autodocs/configuration.md Configure a callback function to monitor ubus messages. Assign the callback to `ctx->monitor_cb` and start monitoring with `ubus_monitor_start`. Remember to stop monitoring with `ubus_monitor_stop` when done. ```c void monitor_callback(struct ubus_context *ctx, uint32_t seq, struct blob_attr *data) { // Inspect monitored message printf("Message seq: %u\n", seq); } ctx->monitor_cb = monitor_callback; ubus_monitor_start(ctx); // ... ubus_monitor_stop(ctx); ``` -------------------------------- ### Object Notification in C Source: https://github.com/openwrt/ubus/blob/master/_autodocs/overview.md Example of sending a notification for an object. ```c ubus_notify(ctx, &obj, "type", data, timeout); ``` -------------------------------- ### Full uBus Setup with Custom Configuration Source: https://github.com/openwrt/ubus/blob/master/_autodocs/configuration.md Connects to a specific uBus socket, sets a custom connection lost handler, adds the context to the event loop, registers objects, and runs the event loop. ```c struct ubus_context ctx; if (ubus_connect_ctx(&ctx, "/var/run/ubus.sock") < 0) { fprintf(stderr, "Connection failed\n"); return -1; } // Custom connection loss handler ctx.connection_lost = my_handler; // Add to event loop ubus_add_uloop(&ctx); // Register objects, subscribe, etc. ubus_add_object(&ctx, &my_object); // Run event loop uloop_run(); // Cleanup ubus_shutdown(&ctx); ``` -------------------------------- ### uBus Server with Custom Objects and Methods Source: https://github.com/openwrt/ubus/blob/master/_autodocs/configuration.md Defines and registers a uBus object with methods ('hello', 'status') and starts a uBus server to handle requests. ```c static struct ubus_method methods[] = { UBUS_METHOD("hello", hello_handler, NULL), UBUS_METHOD_NOARG("status", status_handler), }; static struct ubus_object_type object_type = UBUS_OBJECT_TYPE("myapp", methods); static struct ubus_object obj = { .name = "myapp", .type = &object_type, .methods = methods, .n_methods = ARRAY_SIZE(methods), }; struct ubus_context *ctx = ubus_connect(NULL); ubus_add_object(ctx, &obj); ubus_add_uloop(ctx); uloop_run(); ubus_free(ctx); ``` -------------------------------- ### ubus_monitor_start Source: https://github.com/openwrt/ubus/blob/master/_autodocs/api-reference-objects.md Starts monitoring uBus message traffic. This function initializes the monitoring of messages flowing through the uBus system. ```APIDOC ## ubus_monitor_start ### Description Starts monitoring uBus message traffic. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Method Not Applicable (C function) ### Endpoint Not Applicable (C function) ### Request Example ```c struct ubus_context *ctx = ubus_connect(NULL); if (ctx) { ubus_monitor_start(ctx); // Monitor messages... ubus_monitor_stop(ctx); ubus_free(ctx); } ``` ### Response #### Success Response Returns 0 on success. #### Response Example ```c 0 ``` ``` -------------------------------- ### Example uBus Method with Mask Source: https://github.com/openwrt/ubus/blob/master/_autodocs/configuration.md Illustrates using `UBUS_METHOD_MASK` to define a method where only specific parameters (e.g., param1 and param3) are required, indicated by a bitmask. ```c // Policy with 4 parameters struct blobmsg_policy policy[] = { { .name = "param1", .type = BLOBMSG_TYPE_STRING }, { .name = "param2", .type = BLOBMSG_TYPE_INT32 }, { .name = "param3", .type = BLOBMSG_TYPE_BOOL }, { .name = "param4", .type = BLOBMSG_TYPE_TABLE } }; // Only param1 and param3 required (bits 0 and 2) #define PARAM_MASK ((1 << 0) | (1 << 2)) struct ubus_method methods[] = { UBUS_METHOD_MASK("test", handler, policy, PARAM_MASK) }; ``` -------------------------------- ### Define and Register ubus Server Method Source: https://github.com/openwrt/ubus/blob/master/_autodocs/overview.md Defines a server-side method, registers it with a ubus object, and starts the ubus event loop. This is for creating custom ubus services. ```c static int my_method(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { struct blob_buf b = {}; blob_buf_init(&b, 0); blobmsg_add_string(&b, "status", "ok"); ubus_send_reply(ctx, req, b.head); blob_buf_free(&b); return 0; } static struct ubus_method methods[] = { UBUS_METHOD("test", my_method, NULL) }; static struct ubus_object_type obj_type = UBUS_OBJECT_TYPE("myapp", methods); static struct ubus_object obj = { .name = "myapp", .type = &obj_type, .methods = methods, .n_methods = ARRAY_SIZE(methods) }; struct ubus_context *ctx = ubus_connect(NULL); ubus_add_object(ctx, &obj); ubus_add_uloop(ctx); uloop_run(); ubus_free(ctx); ``` -------------------------------- ### Start uBus Message Monitoring Source: https://github.com/openwrt/ubus/blob/master/_autodocs/api-reference-objects.md Call this function to begin monitoring uBus message traffic. Ensure a valid ubus_context is provided. The function returns UBUS_STATUS_OK on success. ```c static inline int ubus_monitor_start(struct ubus_context *ctx); ``` ```c ubus_monitor_start(ctx); // Monitor messages... ubus_monitor_stop(ctx); ``` -------------------------------- ### Handle UBUS Connection Errors Source: https://github.com/openwrt/ubus/blob/master/_autodocs/errors.md Check if ubus_connect returned NULL, indicating a connection failure. Provides guidance on starting the daemon or checking the socket. ```c // Scenario: Daemon not running struct ubus_context *ctx = ubus_connect(NULL); if (!ctx) { // ubus_connect returns NULL on connection failure perror("ubus_connect"); // Start daemon or check /var/run/ubus.sock } ``` -------------------------------- ### Connect to uBus Daemon (Initializes Existing Context) Source: https://github.com/openwrt/ubus/blob/master/_autodocs/api-reference-connection.md Initializes an existing uBus context structure and connects to the daemon. Returns 0 on success, -1 on failure. The context is shut down with ubus_shutdown(). ```c int ubus_connect_ctx(struct ubus_context *ctx, const char *path); ``` ```c struct ubus_context ctx; if (ubus_connect_ctx(&ctx, NULL) < 0) { perror("ubus_connect_ctx"); return -1; } // Use ctx... ubus_shutdown(&ctx); ``` -------------------------------- ### ubus_monitor_stop Source: https://github.com/openwrt/ubus/blob/master/_autodocs/api-reference-objects.md Stops monitoring uBus message traffic. This function deactivates the monitoring of messages previously started with ubus_monitor_start. ```APIDOC ## ubus_monitor_stop ### Description Stops monitoring uBus message traffic. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Method Not Applicable (C function) ### Endpoint Not Applicable (C function) ### Request Example ```c struct ubus_context *ctx = ubus_connect(NULL); if (ctx) { ubus_monitor_start(ctx); // Monitor messages... ubus_monitor_stop(ctx); ubus_free(ctx); } ``` ### Response #### Success Response Returns 0 on success. #### Response Example ```c 0 ``` ``` -------------------------------- ### Event Listening in C Source: https://github.com/openwrt/ubus/blob/master/_autodocs/overview.md Demonstrates how to register a handler to listen for specific events. ```c ubus_register_event_handler(ctx, &handler, "event.*"); ``` -------------------------------- ### Synchronous Client Pattern in C Source: https://github.com/openwrt/ubus/blob/master/_autodocs/overview.md Demonstrates the basic steps for a synchronous client to connect, look up an object ID, invoke a method, and disconnect. ```c struct ubus_context *ctx = ubus_connect(NULL); uint32_t id; ubus_lookup_id(ctx, "path", &id); ubus_invoke(ctx, id, "method", msg, callback, priv, timeout); ubus_free(ctx); ``` -------------------------------- ### Connect to uBus Daemon (Allocates Context) Source: https://github.com/openwrt/ubus/blob/master/_autodocs/api-reference-connection.md Allocates and initializes a new uBus context, then connects to the daemon. The returned context must be freed with ubus_free(). ```c struct ubus_context *ubus_connect(const char *path); ``` ```c struct ubus_context *ctx = ubus_connect("/var/run/ubus.sock"); if (!ctx) { perror("ubus_connect"); return -1; } // Use ctx... ubus_free(ctx); ``` -------------------------------- ### ubus_complete_request_async Source: https://github.com/openwrt/ubus/blob/master/_autodocs/api-reference-methods.md Registers an asynchronous request for background processing. This function is used to finalize the setup of an asynchronous UBUS request that will be handled in the background. ```APIDOC ## ubus_complete_request_async ### Description Registers an asynchronous request for background processing. ### Method `void ubus_complete_request_async(struct ubus_context *ctx, struct ubus_request *req);` ### Parameters #### Path Parameters - **ctx** (struct ubus_context *) - Yes - Connection context - **req** (struct ubus_request *) - Yes - Request to register ### Request Example ```c static void on_complete(struct ubus_request *req, int ret) { printf("Request completed with status: %d\n", ret); } struct ubus_request req; ubus_invoke_async(ctx, obj_id, "test", msg, &req); req.complete_cb = on_complete; ubus_complete_request_async(ctx, &req); // Request will complete asynchronously ``` ``` -------------------------------- ### ubus_strerror Source: https://github.com/openwrt/ubus/blob/master/_autodocs/api-reference-connection.md Gets a human-readable error message for a given uBus error code. This is helpful for debugging and providing user-friendly error feedback. ```APIDOC ## ubus_strerror ### Description Gets a human-readable error message for a uBus error code. ### Signature ```c const char *ubus_strerror(int error); ``` ### Parameters #### Path Parameters - **error** (int) - Required - Error code (enum ubus_msg_status) ### Return Type `const char *` - Returns a static string describing the error. ### Request Example ```c int ret = ubus_invoke(ctx, obj_id, "method", msg, cb, NULL, 3000); if (ret != UBUS_STATUS_OK) { fprintf(stderr, "Error: %s\n", ubus_strerror(ret)); } ``` ``` -------------------------------- ### Subscriber Pattern in C Source: https://github.com/openwrt/ubus/blob/master/_autodocs/overview.md Illustrates how to register a subscriber and then subscribe to a target ID. ```c ubus_register_subscriber(ctx, &sub); ubus_subscribe(ctx, &sub, target_id); ``` -------------------------------- ### Registering Event Handlers with Wildcard Patterns Source: https://github.com/openwrt/ubus/blob/master/_autodocs/configuration.md Shows how to register event handlers using wildcard patterns to match specific or all events. Use patterns like 'ubus.object.*' for specific prefixes or '*' for all events. ```c // Match all events starting with "ubus.object" ubus_register_event_handler(ctx, &handler, "ubus.object.*"); ``` ```c // Match all events ubus_register_event_handler(ctx, &handler, "*"); ``` ```c // Exact match ubus_register_event_handler(ctx, &handler, "ubus.system.boot"); ``` -------------------------------- ### ubus_connect_ctx Source: https://github.com/openwrt/ubus/blob/master/_autodocs/api-reference-connection.md Initializes an existing uBus context structure and connects to the daemon. Returns 0 on success, -1 on failure. ```APIDOC ## ubus_connect_ctx ### Description Initializes an existing uBus context structure and connects to the daemon. ### Signature ```c int ubus_connect_ctx(struct ubus_context *ctx, const char *path); ``` ### Parameters #### Path Parameters - **ctx** (struct ubus_context *) - Required - Pre-allocated context to initialize - **path** (const char *) - Optional - Path to uBus socket (NULL uses default) ### Return Type `int` Returns 0 on success, -1 on failure. ### Example ```c struct ubus_context ctx; if (ubus_connect_ctx(&ctx, NULL) < 0) { perror("ubus_connect_ctx"); return -1; } // Use ctx... ubus_shutdown(&ctx); ``` ``` -------------------------------- ### Event Handler Configuration Source: https://github.com/openwrt/ubus/blob/master/_autodocs/configuration.md Shows how to register event handlers with wildcard patterns and configure auto-subscription to new objects. ```APIDOC ## Event Handler Configuration ### Event Pattern Matching Event handlers accept wildcard patterns: ```c // Match all events starting with "ubus.object" ubus_register_event_handler(ctx, &handler, "ubus.object.* "); // Match all events ubus_register_event_handler(ctx, &handler, "*"); // Exact match ubus_register_event_handler(ctx, &handler, "ubus.system.boot"); ``` ### Auto-Subscription Configuration Subscribers can automatically subscribe to new objects: ```c static bool new_obj_filter(struct ubus_context *ctx, struct ubus_subscriber *sub, const char *path) { // Return true to auto-subscribe to this object return strstr(path, "target") != NULL; } struct ubus_subscriber subscriber = { .new_obj_cb = new_obj_filter // Enable auto-subscription }; ``` ``` -------------------------------- ### Get uBus Error Message Source: https://github.com/openwrt/ubus/blob/master/_autodocs/api-reference-connection.md Retrieves a human-readable error message for a given uBus error code. Useful for logging or user feedback when a uBus operation fails. ```c const char *ubus_strerror(int error); ``` ```c int ret = ubus_invoke(ctx, obj_id, "method", msg, cb, NULL, 3000); if (ret != UBUS_STATUS_OK) { fprintf(stderr, "Error: %s\n", ubus_strerror(ret)); } ``` -------------------------------- ### Handle UBUS Connection Failed Error Source: https://github.com/openwrt/ubus/blob/master/_autodocs/errors.md Manage UBUS_STATUS_CONNECTION_FAILED errors, which indicate a lost or unestablished connection to the UBUS daemon. This example shows how to attempt reconnection and retry the operation. ```c struct ubus_context *ctx = ubus_connect(NULL); if (!ctx) { fprintf(stderr, "Failed to connect to ubus daemon\n"); } int ret = ubus_invoke(ctx, obj_id, "method", msg, cb, NULL, 3000); if (ret == UBUS_STATUS_CONNECTION_FAILED) { fprintf(stderr, "Connection lost during request\n"); // Attempt reconnect if (ubus_reconnect(ctx, NULL) == 0) { // Retry operation } } ``` -------------------------------- ### Event Broadcasting in C Source: https://github.com/openwrt/ubus/blob/master/_autodocs/overview.md Shows how to broadcast an event to registered listeners. ```c ubus_send_event(ctx, "event.name", data); ``` -------------------------------- ### ubus_connect Source: https://github.com/openwrt/ubus/blob/master/_autodocs/api-reference-connection.md Allocates and initializes a new uBus context and connects to the daemon. The returned context must be freed with `ubus_free()`. ```APIDOC ## ubus_connect ### Description Allocates and initializes a new uBus context and connects to the daemon. ### Signature ```c struct ubus_context *ubus_connect(const char *path); ``` ### Parameters #### Path Parameters - **path** (const char *) - Optional - Path to uBus socket (NULL uses default) ### Return Type `struct ubus_context *` Returns an allocated context on success, or NULL on failure. ### Example ```c struct ubus_context *ctx = ubus_connect("/var/run/ubus.sock"); if (!ctx) { perror("ubus_connect"); return -1; } // Use ctx... ubus_free(ctx); ``` ``` -------------------------------- ### Get Ubus Error Message Source: https://github.com/openwrt/ubus/blob/master/_autodocs/errors.md Use `ubus_strerror()` to convert an integer error code into a human-readable string. This is typically done after a failed ubus operation to understand the cause of the error. ```c int ret = ubus_invoke(ctx, obj_id, "method", msg, NULL, NULL, 3000); if (ret != UBUS_STATUS_OK) { fprintf(stderr, "Error: %s\n", ubus_strerror(ret)); } ``` -------------------------------- ### Handle Invalid Argument Error (UBUS_STATUS_INVALID_ARGUMENT) Source: https://github.com/openwrt/ubus/blob/master/_autodocs/errors.md Check for UBUS_STATUS_INVALID_ARGUMENT when a required parameter is missing, invalid, or has an incorrect type. This can happen during method invocation, object registration, or event handler setup. ```c int ret = ubus_invoke(ctx, obj_id, NULL, msg, cb, NULL, 3000); if (ret == UBUS_STATUS_INVALID_ARGUMENT) { fprintf(stderr, "Invalid argument provided\n"); } ``` -------------------------------- ### uBus Event and Notification Handling (C) Source: https://github.com/openwrt/ubus/blob/master/_autodocs/README.md Shows how to send object-specific notifications and system-wide events, as well as how to register handlers to listen for events. ```c // Object notification to subscribers ubus_notify(ctx, &obj, "event_name", data, 1000); ``` ```c // System event broadcast ubus_send_event(ctx, "ubus.system.boot", data); ``` ```c // Listen for events ubus_register_event_handler(ctx, &handler, "ubus.object.*"); ``` -------------------------------- ### uBus Object and Method Definition Source: https://github.com/openwrt/ubus/blob/master/_autodocs/README.md Demonstrates how to define a uBus object with a method and register it with the uBus context. ```APIDOC ## uBus Object and Method Definition ### Description This example shows the C code structure for defining a uBus method handler, registering it within an object type, and then adding the object to the uBus context. ### Code Example ```c // Define a method handler static int hello_handler(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { ubus_send_reply(ctx, req, NULL); return 0; } // Define the methods for the object static struct ubus_method methods[] = { UBUS_METHOD_NOARG("hello", hello_handler) }; // Define the object type static struct ubus_object_type object_type = UBUS_OBJECT_TYPE("test", methods); // Define the object instance static struct ubus_object test_obj = { .name = "test", .type = &object_type, .methods = methods, .n_methods = ARRAY_SIZE(methods) }; // Add the object to the uBus context ubus_add_object(ctx, &test_obj); ``` ``` -------------------------------- ### Configuration Options Source: https://github.com/openwrt/ubus/blob/master/_autodocs/README.md Details the various configuration options available for the uBus library. ```APIDOC ## Configuration ### Options - Connection configuration (socket path, defaults) - Message buffer settings - Object configuration (method tags, masks) - System object IDs - Notification configuration - Request timeout handling - File descriptor configuration - Event handler patterns - ACL configuration - Channel mode configuration - Connection loss handling ``` -------------------------------- ### Automate Test Discovery Source: https://github.com/openwrt/ubus/blob/master/tests/CMakeLists.txt Globbing for C test files and iterating to register them as unit tests. ```cmake FILE(GLOB test_cases "test-*.c") FOREACH(test_case ${test_cases}) GET_FILENAME_COMPONENT(test_case ${test_case} NAME_WE) ADD_UNIT_TEST(${test_case}) ADD_UNIT_TEST_SAN(${test_case}) ENDFOREACH(test_case) ``` -------------------------------- ### Asynchronous Invoke with Callback Source: https://github.com/openwrt/ubus/blob/master/_autodocs/callbacks.md Shows how to initiate an asynchronous UBUS method invocation. The function returns immediately, and a callback is executed upon completion of the request. ```APIDOC ## Asynchronous Invoke with Callback ### Description Initiates an asynchronous UBUS method invocation. The request is processed in the background, and a completion callback is triggered upon its finalization. ### Function Signatures `void ubus_invoke_async(struct ubus_context *ctx, uint32_t id, const char *method, struct blob_attr *msg, struct ubus_request *req)` `void ubus_complete_request_async(struct ubus_context *ctx, struct ubus_request *req)` ### Parameters - `ctx` (struct ubus_context *): The UBUS context. - `id` (uint32_t): The object ID to invoke the method on. - `method` (const char *): The name of the method to invoke. - `msg` (struct blob_attr *): The message payload for the method. - `req` (struct ubus_request *): Pointer to a `ubus_request` structure to manage the asynchronous operation. ### Callback Function Signature `static void my_complete(struct ubus_request *req, int ret)` ### Example ```c static void my_complete(struct ubus_request *req, int ret) { printf("Request completed with status: %d\n", ret); } struct ubus_request req; ubus_invoke_async(ctx, obj_id, "method", msg, &req); req.complete_cb = my_complete; ubus_complete_request_async(ctx, &req); ``` ``` -------------------------------- ### Configure ubus build targets with CMake Source: https://github.com/openwrt/ubus/blob/master/examples/CMakeLists.txt Defines include paths and conditional compilation for server and client binaries using ubus, ubox, blob, and json libraries. ```cmake ADD_DEFINITIONS(-I..) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/..) IF (BUILD_EXAMPLES) ADD_EXECUTABLE(server server.c count.c) TARGET_LINK_LIBRARIES(server ubus ${ubox_library} ${blob_library} ${json}) ADD_EXECUTABLE(client client.c count.c) TARGET_LINK_LIBRARIES(client ubus ${ubox_library}) ENDIF() ``` -------------------------------- ### Create ubus Channel Context Source: https://github.com/openwrt/ubus/blob/master/_autodocs/configuration.md Use `ubus_channel_create` to set up a context that operates as a channel instead of connecting to the daemon. The `remote_fd` can be passed to another process. The context is then in channel mode. ```c int remote_fd; int ret = ubus_channel_create(&ctx, &remote_fd, handle_request); if (ret < 0) { perror("ubus_channel_create"); return -1; } // Pass remote_fd to another process // ctx is now in channel mode ``` -------------------------------- ### File Descriptor Passing Source: https://github.com/openwrt/ubus/blob/master/_autodocs/configuration.md Demonstrates how to pass file descriptors with UBUS method invocations and responses. ```APIDOC ## File Descriptor Passing File descriptors can be passed with method invocations and responses: ```c int fd = open("file.txt", O_RDONLY); int ret = ubus_invoke_fd(ctx, obj_id, "method", msg, cb, NULL, 3000, fd); // fd must be closed by caller // In handler int received_fd = ubus_request_get_caller_fd(&req); if (received_fd >= 0) { // Use fd close(received_fd); } // In response ubus_request_set_fd(ctx, &req, response_fd); ``` ``` -------------------------------- ### Connect uBus Context to File Descriptor Source: https://github.com/openwrt/ubus/blob/master/_autodocs/api-reference-connection.md Connects a uBus context to an existing file descriptor for channel-based communication. A handler function is required to process incoming requests. Returns 0 on success, -1 on failure. ```c int ubus_channel_connect(struct ubus_context *ctx, int fd, ubus_handler_t handler); ``` ```c int handle_request(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { // Handle incoming request return 0; } int channel_fd = accept(listen_socket, NULL, NULL); if (ubus_channel_connect(&ctx, channel_fd, handle_request) < 0) { perror("ubus_channel_connect"); close(channel_fd); } ``` -------------------------------- ### Connect to Default uBus Socket Source: https://github.com/openwrt/ubus/blob/master/_autodocs/configuration.md Use `ubus_connect(NULL)` to connect to the default uBus socket path, typically `/var/run/ubus.sock` on OpenWRT. ```c struct ubus_context *ctx = ubus_connect(NULL); // Uses default path ``` -------------------------------- ### Synchronous vs. Asynchronous uBus Invocation (C) Source: https://github.com/openwrt/ubus/blob/master/_autodocs/README.md Demonstrates both synchronous and asynchronous methods for invoking uBus functions. Synchronous calls block until a response is received, while asynchronous calls return immediately. ```c // Synchronous: blocks until response int ret = ubus_invoke(ctx, obj_id, "method", msg, callback, NULL, 3000); ``` ```c // Asynchronous: returns immediately struct ubus_request req; ubus_invoke_async(ctx, obj_id, "method", msg, &req); req.complete_cb = on_complete; ubus_complete_request_async(ctx, &req); ``` -------------------------------- ### Basic Notification Source: https://github.com/openwrt/ubus/blob/master/_autodocs/api-reference-events.md Demonstrates how to send a basic notification to all subscribers of a registered object. ```APIDOC ## Basic Notification ### Description Sends a notification to all subscribers of a given object. ### Usage 1. Define a notifiable UBUS object. 2. Add the object to the UBUS context. 3. Prepare the notification data using `blob_buf`. 4. Call `ubus_notify` to send the notification. ### Code Example ```c // Define a notifiable object static struct ubus_object notifiable_obj = { .name = "broadcaster", .type = &obj_type, .methods = methods, .n_methods = ARRAY_SIZE(methods) }; ubus_add_object(ctx, ¬ifiable_obj); // Send notification to all subscribers struct blob_buf b = {}; blob_buf_init(&b, 0); blobmsg_add_string(&b, "message", "Hello subscribers"); ubus_notify(ctx, ¬ifiable_obj, "broadcast", b.head, 1000); blob_buf_free(&b); ``` ``` -------------------------------- ### Asynchronous Notification with Callbacks Source: https://github.com/openwrt/ubus/blob/master/_autodocs/api-reference-events.md Shows how to send notifications asynchronously and handle responses using callbacks. ```APIDOC ## Asynchronous Notification with Callbacks ### Description Allows sending notifications asynchronously and processing received data and completion status via callback functions. ### Usage 1. Define callback functions for data reception (`on_notify_data`) and completion (`on_notify_complete`). 2. Initialize a `ubus_notify_request` structure. 3. Send the notification asynchronously using `ubus_notify_async`. 4. Assign the callback functions to the `data_cb` and `complete_cb` fields of the request. 5. Complete the request processing using `ubus_complete_request_async`. ### Callback Types - `ubus_notify_data_handler_t`: Called when notification response data is received. - `ubus_notify_complete_handler_t`: Called when a notification completes. ### Code Example ```c static void on_notify_data(struct ubus_notify_request *req, int type, struct blob_attr *msg) { printf("Received subscriber response\n"); } static void on_notify_complete(struct ubus_notify_request *req, int idx, int ret) { printf("Subscriber %d responded with status: %d\n", idx, ret); } struct ubus_notify_request notify_req; memset(¬ify_req, 0, sizeof(notify_req)); ubus_notify_async(ctx, ¬ifiable_obj, "update", msg, ¬ify_req); notify_req.data_cb = on_notify_data; notify_req.complete_cb = on_notify_complete; ubus_complete_request_async(ctx, ¬ify_req.req); ``` ``` -------------------------------- ### Synchronous and Asynchronous uBus Invocation Source: https://github.com/openwrt/ubus/blob/master/_autodocs/README.md Illustrates how to make synchronous and asynchronous calls to uBus methods. ```APIDOC ## Synchronous and Asynchronous uBus Invocation ### Description This section provides examples of both synchronous (blocking) and asynchronous (non-blocking) invocation of uBus methods. Synchronous calls wait for a response, while asynchronous calls return immediately, allowing for background processing. ### Synchronous Call ```c // Synchronous: blocks until response int ret = ubus_invoke(ctx, obj_id, "method", msg, callback, NULL, 3000); ``` ### Asynchronous Call ```c // Asynchronous: returns immediately struct ubus_request req; ubus_invoke_async(ctx, obj_id, "method", msg, &req); req.complete_cb = on_complete; ubus_complete_request_async(ctx, &req); ``` ``` -------------------------------- ### Connect to Custom uBus Socket Source: https://github.com/openwrt/ubus/blob/master/_autodocs/configuration.md Specify a custom socket path when connecting to uBus using `ubus_connect()` with a non-NULL path argument. Error handling for connection failure is included. ```c const char *custom_path = "/custom/path/ubus.sock"; struct ubus_context *ctx = ubus_connect(custom_path); if (!ctx) { perror("ubus_connect"); return -1; } ``` -------------------------------- ### Asynchronous Invoke with Multiple Callbacks Source: https://github.com/openwrt/ubus/blob/master/_autodocs/callbacks.md Illustrates how to handle asynchronous UBUS method invocations using multiple callback functions for data, file descriptors, and completion events. ```APIDOC ## Asynchronous Invoke with Multiple Callbacks ### Description Enables handling of asynchronous UBUS method invocations by registering separate callback functions for receiving data, handling file descriptors, and signaling request completion. ### Function Signatures `void ubus_invoke_async(struct ubus_context *ctx, uint32_t id, const char *method, struct blob_attr *msg, struct ubus_request *req)` `void ubus_complete_request_async(struct ubus_context *ctx, struct ubus_request *req)` ### Parameters - `ctx` (struct ubus_context *): The UBUS context. - `id` (uint32_t): The object ID to invoke the method on. - `method` (const char *): The name of the method to invoke. - `msg` (struct blob_attr *): The message payload for the method. - `req` (struct ubus_request *): Pointer to a `ubus_request` structure to manage the asynchronous operation. ### Callback Function Signatures `static void response_data(struct ubus_request *req, int type, struct blob_attr *msg)` `static void response_fd(struct ubus_request *req, int fd)` `static void on_done(struct ubus_request *req, int ret)` ### Example ```c static void response_data(struct ubus_request *req, int type, struct blob_attr *msg) { printf("Response data received\n"); } static void response_fd(struct ubus_request *req, int fd) { printf("FD received: %d\n", fd); } static void on_done(struct ubus_request *req, int ret) { printf("Request complete\n"); } struct ubus_request req; ubus_invoke_async(ctx, obj_id, "method", msg, &req); req.data_cb = response_data; req.fd_cb = response_fd; req.complete_cb = on_done; ubus_complete_request_async(ctx, &req); ``` ``` -------------------------------- ### Enable Testing and Add Sanitized Unit Tests Source: https://github.com/openwrt/ubus/blob/master/CMakeLists.txt If UNIT_TESTING is enabled, this section enables testing and adds sanitized versions of the 'cli' and 'ubusd_main' executables using the ADD_UNIT_TEST_SAN macro. ```cmake IF(UNIT_TESTING) ENABLE_TESTING() ADD_SUBDIRECTORY(tests) ADD_UNIT_TEST_SAN(cli ubus-san) ADD_UNIT_TEST_SAN(ubusd_main ubusd-san) ENDIF() ``` -------------------------------- ### Compiler Options Configuration Source: https://github.com/openwrt/ubus/blob/master/CMakeLists.txt Configures compiler warnings and optimization levels. Includes specific flags for C99 standard and error handling for format security and implicit function declarations. ```cmake ADD_COMPILE_OPTIONS(-Wall -Werror) IF(CMAKE_C_COMPILER_VERSION VERSION_GREATER 6) ADD_COMPILE_OPTIONS(-Wextra -Wformat -Werror=format-security -Werror=format-nonliteral) ADD_COMPILE_OPTIONS($<$:-Werror=implicit-function-declaration>) ENDIF() ADD_COMPILE_OPTIONS(-Os -g3 -Wmissing-declarations -Wno-unused-parameter) ADD_COMPILE_OPTIONS($<$:-std=gnu99>) ``` -------------------------------- ### ACL Configuration Source: https://github.com/openwrt/ubus/blob/master/_autodocs/configuration.md Details the structure of ACL keys and how to register ACL handling for access control. ```APIDOC ## ACL Configuration ### ACL Key Structure Access control is defined by user, group, and object: ```c struct ubus_acl_key { const char *user; // Username const char *group; // Group name const char *object; // Object path }; ``` ### ACL Registration Register ACL handling: ```c int ret = ubus_register_acl(ctx); if (ret != UBUS_STATUS_OK) { fprintf(stderr, "Failed to register ACL: %s\n", ubus_strerror(ret)); } ``` ``` -------------------------------- ### Event Broadcasting Source: https://github.com/openwrt/ubus/blob/master/_autodocs/api-reference-events.md Illustrates how to register for and send system events within UBUS. ```APIDOC ## Event Broadcasting ### Description Enables registering handlers for specific event types and broadcasting custom events to the system. ### Usage 1. Define an event handler function (`on_system_event`). 2. Create a `ubus_event_handler` structure and assign the callback. 3. Register the handler for a pattern (e.g., `ubus.system.*`) using `ubus_register_event_handler`. 4. Prepare event data using `blob_buf`. 5. Send the event using `ubus_send_event`. ### Code Example ```c static void on_system_event(struct ubus_context *ctx, struct ubus_event_handler *ev, const char *type, struct blob_attr *msg) { printf("System event: %s\n", type); } struct ubus_event_handler event_handler = { .cb = on_system_event }; ubus_register_event_handler(ctx, &event_handler, "ubus.system.*"); // Later send an event struct blob_buf b = {}; blob_buf_init(&b, 0); blobmsg_add_string(&b, "version", "1.2.3"); ubus_send_event(ctx, "ubus.system.boot", b.head); blob_buf_free(&b); ``` ``` -------------------------------- ### Define and Register uBus Object (C) Source: https://github.com/openwrt/ubus/blob/master/_autodocs/README.md Defines a uBus method and registers an object with that method. Use this to expose functionality through uBus. ```c // Define a method static int hello_handler(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { ubus_send_reply(ctx, req, NULL); return 0; } // Register object static struct ubus_method methods[] = { UBUS_METHOD_NOARG("hello", hello_handler) }; static struct ubus_object_type object_type = UBUS_OBJECT_TYPE("test", methods); static struct ubus_object test_obj = { .name = "test", .type = &object_type, .methods = methods, .n_methods = ARRAY_SIZE(methods) }; ubus_add_object(ctx, &test_obj); ``` -------------------------------- ### Basic Ubus Notification Source: https://github.com/openwrt/ubus/blob/master/_autodocs/api-reference-events.md Demonstrates how to define a notifiable ubus object and send a basic notification to all subscribers. Ensure the ubus context is initialized and the object is added. ```c // Define a notifiable object static struct ubus_object notifiable_obj = { .name = "broadcaster", .type = &obj_type, .methods = methods, .n_methods = ARRAY_SIZE(methods) }; ubus_add_object(ctx, ¬ifiable_obj); // Send notification to all subscribers struct blob_buf b = {}; blob_buf_init(&b, 0); blobmsg_add_string(&b, "message", "Hello subscribers"); ubus_notify(ctx, ¬ifiable_obj, "broadcast", b.head, 1000); blob_buf_free(&b); ``` -------------------------------- ### Invoke Method with Timeout Source: https://github.com/openwrt/ubus/blob/master/_autodocs/configuration.md Demonstrates how to invoke a uBus method with a specified timeout in milliseconds. A timeout of 0 means to wait indefinitely. ```c // 3 second timeout int ret = ubus_invoke(ctx, obj_id, "method", msg, cb, NULL, 3000); // No timeout (wait indefinitely) int ret = ubus_invoke(ctx, obj_id, "method", msg, cb, NULL, 0); ``` -------------------------------- ### Connect to ubus and Lookup Object ID Source: https://github.com/openwrt/ubus/blob/master/_autodocs/overview.md Connects to the ubus daemon and looks up the object ID for a given name. Ensure the ubus daemon is running before connecting. ```c struct ubus_context *ctx = ubus_connect(NULL); if (!ctx) return -1; uint32_t obj_id; if (ubus_lookup_id(ctx, "system.info", &obj_id) < 0) return -1; ``` -------------------------------- ### ubus_add_uloop Source: https://github.com/openwrt/ubus/blob/master/_autodocs/api-reference-connection.md Registers the uBus context socket with the event loop (uloop). This allows uBus events to be processed within the application's event loop. ```APIDOC ## ubus_add_uloop ### Description Registers the uBus context socket with the event loop (uloop). ### Signature ```c static inline void ubus_add_uloop(struct ubus_context *ctx); ``` ### Parameters #### Path Parameters - **ctx** (struct ubus_context *) - Required - Context to register ### Request Example ```c struct ubus_context *ctx = ubus_connect(NULL); ubus_add_uloop(ctx); uloop_run(); // Start event loop ``` ``` -------------------------------- ### Asynchronous Ubus Notification with Callbacks Source: https://github.com/openwrt/ubus/blob/master/_autodocs/api-reference-events.md Shows how to send a ubus notification asynchronously and handle responses using callback functions. Define `on_notify_data` and `on_notify_complete` for custom logic. ```c static void on_notify_data(struct ubus_notify_request *req, int type, struct blob_attr *msg) { printf("Received subscriber response\n"); } static void on_notify_complete(struct ubus_notify_request *req, int idx, int ret) { printf("Subscriber %d responded with status: %d\n", idx, ret); } struct ubus_notify_request notify_req; memset(¬ify_req, 0, sizeof(notify_req)); ubus_notify_async(ctx, ¬ifiable_obj, "update", msg, ¬ify_req); notify_req.data_cb = on_notify_data; notify_req.complete_cb = on_notify_complete; ubus_complete_request_async(ctx, ¬ify_req.req); ``` -------------------------------- ### Multiple Callbacks for UBus Async Request Source: https://github.com/openwrt/ubus/blob/master/_autodocs/callbacks.md Handles different types of asynchronous responses, including data, file descriptors, and completion. ```c static void response_data(struct ubus_request *req, int type, struct blob_attr *msg) { printf("Response data received\n"); } static void response_fd(struct ubus_request *req, int fd) { printf("FD received: %d\n", fd); } static void on_done(struct ubus_request *req, int ret) { printf("Request complete\n"); } struct ubus_request req; ubus_invoke_async(ctx, obj_id, "method", msg, &req); req.data_cb = response_data; req.fd_cb = response_fd; req.complete_cb = on_done; ubus_complete_request_async(ctx, &req); ``` -------------------------------- ### Handle ubus Asynchronous Request Response Source: https://github.com/openwrt/ubus/blob/master/_autodocs/overview.md Sets up callbacks for handling asynchronous ubus request responses and completion. Use this when you don't want to block while waiting for a reply. ```c static void on_response(struct ubus_request *req, int type, struct blob_attr *msg) { printf("Response received\n"); } static void on_complete(struct ubus_request *req, int ret) { printf("Request complete: %s\n", ubus_strerror(ret)); } struct ubus_request req; ubus_invoke_async(ctx, obj_id, "method", msg, &req); req.data_cb = on_response; req.complete_cb = on_complete; ubus_complete_request_async(ctx, &req); ``` -------------------------------- ### Ubus Event Broadcasting Source: https://github.com/openwrt/ubus/blob/master/_autodocs/api-reference-events.md Demonstrates registering an event handler for system events and sending custom events. Use `ubus_register_event_handler` to subscribe and `ubus_send_event` to broadcast. ```c static void on_system_event(struct ubus_context *ctx, struct ubus_event_handler *ev, const char *type, struct blob_attr *msg) { printf("System event: %s\n", type); } struct ubus_event_handler event_handler = { .cb = on_system_event }; ubus_register_event_handler(ctx, &event_handler, "ubus.system.*"); // Later send an event struct blob_buf b = {}; blob_buf_init(&b, 0); blobmsg_add_string(&b, "version", "1.2.3"); ubus_send_event(ctx, "ubus.system.boot", b.head); blob_buf_free(&b); ``` -------------------------------- ### uBus Events and Notifications Source: https://github.com/openwrt/ubus/blob/master/_autodocs/README.md Shows how to send and listen for uBus events and notifications. ```APIDOC ## uBus Events and Notifications ### Description This section covers the mechanisms for broadcasting events and sending object-specific notifications within the uBus system, as well as how to register handlers to listen for these events. ### Sending Notifications/Events ```c // Object notification to subscribers ubus_notify(ctx, &obj, "event_name", data, 1000); // System event broadcast ubus_send_event(ctx, "ubus.system.boot", data); ``` ### Listening for Events ```c // Listen for events ubus_register_event_handler(ctx, &handler, "ubus.object.*"); ``` ``` -------------------------------- ### Add CLI Executable Target Source: https://github.com/openwrt/ubus/blob/master/CMakeLists.txt Creates the command-line interface executable 'ubus', setting its output name and linking necessary libraries. ```cmake ADD_EXECUTABLE(cli cli.c) SET_TARGET_PROPERTIES(cli PROPERTIES OUTPUT_NAME ubus) TARGET_LINK_LIBRARIES(cli ubus ${ubox_library} ${blob_library} ${json}) ``` -------------------------------- ### Configuring Auto-Subscription for New Objects Source: https://github.com/openwrt/ubus/blob/master/_autodocs/configuration.md Enables automatic subscription to new ubus objects by providing a filter callback function. The callback determines whether to subscribe based on the object's path. ```c static bool new_obj_filter(struct ubus_context *ctx, struct ubus_subscriber *sub, const char *path) { // Return true to auto-subscribe to this object return strstr(path, "target") != NULL; } struct ubus_subscriber subscriber = { .new_obj_cb = new_obj_filter // Enable auto-subscription }; ``` -------------------------------- ### Handle UBUS Not Supported Error Source: https://github.com/openwrt/ubus/blob/master/_autodocs/errors.md Respond to UBUS_STATUS_NOT_SUPPORTED when the requested operation is not implemented by the daemon or the protocol. ```c if (ret == UBUS_STATUS_NOT_SUPPORTED) { fprintf(stderr, "Operation not supported by this daemon\n"); } ``` -------------------------------- ### Find ubox and blobmsg_json Libraries Source: https://github.com/openwrt/ubus/blob/master/CMakeLists.txt Locates the necessary ubox and blobmsg_json libraries. It differentiates between static (.a) and shared library names based on the BUILD_STATIC option. ```cmake IF(BUILD_STATIC) FIND_LIBRARY(ubox_library NAMES libubox.a) FIND_LIBRARY(blob_library NAMES libblobmsg_json.a) ELSE(BUILD_STATIC) FIND_LIBRARY(ubox_library NAMES ubox) FIND_LIBRARY(blob_library NAMES blobmsg_json) ENDIF(BUILD_STATIC) ``` -------------------------------- ### Process Test Cases with Fuzzer Macro Source: https://github.com/openwrt/ubus/blob/master/tests/fuzz/CMakeLists.txt Iterates through a list of test case source files and applies the ADD_FUZZER_TEST macro to each one, setting up individual fuzzer executables and tests. ```cmake FILE(GLOB test_cases "test-*.c") FOREACH(test_case ${test_cases}) GET_FILENAME_COMPONENT(test_case ${test_case} NAME_WE) ADD_FUZZER_TEST(${test_case}) ENDFOREACH(test_case) ``` -------------------------------- ### Configure C++ Support and Fuzzing Source: https://github.com/openwrt/ubus/blob/master/tests/CMakeLists.txt Enables C++11 support and conditionally adds the fuzzing subdirectory for Clang compilers. ```cmake ENABLE_LANGUAGE(CXX) ADD_COMPILE_OPTIONS($<$:-std=gnu++11>) ADD_UNIT_TEST_CPP(test-cplusplus) ADD_TEST(NAME cplusplus COMMAND test-cplusplus) IF(CMAKE_C_COMPILER_ID STREQUAL "Clang") ADD_SUBDIRECTORY(fuzz) ENDIF() ``` -------------------------------- ### Object and Method Registration Functions Source: https://github.com/openwrt/ubus/blob/master/_autodocs/INDEX.md Functions for registering, unregistering, and discovering objects and methods within the uBus system. ```APIDOC ## Object and Method Registration ### `ubus_add_object()` #### Description Registers a new object with the uBus system. ### `ubus_remove_object()` #### Description Unregisters an object from the uBus system. ### `ubus_lookup()` #### Description Finds uBus objects based on a pattern. ### `ubus_lookup_id()` #### Description Retrieves the unique ID of an object given its path. ### `ubus_register_subscriber()` #### Description Registers a subscriber for uBus events or notifications. ### `ubus_subscribe()` #### Description Subscribes to specific uBus notifications or events. ### `ubus_unsubscribe()` #### Description Unsubscribes from uBus notifications or events. ### `ubus_monitor_start()` / `ubus_monitor_stop()` #### Description Starts or stops monitoring uBus traffic. ```