ubus客戶端向伺服器請求資訊的例子
阿新 • • 發佈:2019-01-23
openwrt使用者空間進中通訊常用的通訊方式是使用ubus通訊,下面給出一個例子,是客戶端向伺服器請求ap的個數。
伺服器端程式碼
#include <unistd.h> #include <signal.h> #include "libubus.h" static struct ubus_context *ctx; static struct blob_buf b; enum { REQ_STATION_COUNT, REQ_AP_NAME, __REQ_MAX }; /* 接收的解析格式, client傳送過來的呼叫是 blobmsg_add_u32(&b, "getcnt", ap_index); */ static const struct blobmsg_policy fun2_message_parse_policy[__REQ_MAX] = { [REQ_STATION_COUNT] = { .name = "getcnt", .type = BLOBMSG_TYPE_INT32 }, [REQ_STATION_COUNT] = { .name = "apname", .type = BLOBMSG_TYPE_STRING }, }; static int fun2_handler(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { struct blob_attr *tb[__REQ_MAX]; //模擬ap陣列中station的個數 int ap_array[] = {-1, 11111,22222,33333}; int ap_index; blobmsg_parse(fun2_message_parse_policy, __REQ_MAX, tb, blob_data(msg), blob_len(msg)); if (!tb[REQ_STATION_COUNT]) return UBUS_STATUS_INVALID_ARGUMENT; ap_index = blobmsg_get_u32(tb[REQ_STATION_COUNT]); fprintf(stdout, "someone ask the ap[%d]' info \n", ap_index); if (ap_index > (sizeof(ap_array) / sizeof(int))) ap_index = 0; blob_buf_init(&b, 0); //返回客戶端請求的station個數 blobmsg_add_u32(&b, "stacnt", ap_array[ap_index]); //傳送 ubus_send_reply(ctx, req, b.head); return 0; } static const struct ubus_method test_methods[] = { UBUS_METHOD("fun2", fun2_handler, fun2_message_parse_policy), }; static struct ubus_object_type test_object_type = UBUS_OBJECT_TYPE("server_fun", test_methods); //定義一個ubus 物件。 //其他程序通過呼叫相應字串給執行對應的回撥函式 //註冊成功後可以通過命令ubus list -v 檢視到obj //' server_fun' @79a8beac // "fun2" : {"getcnt":"Iterger","apname":"String"} static struct ubus_object test_object = { .name = "server_fun", .type = &test_object_type, .methods = test_methods, .n_methods = ARRAY_SIZE(test_methods), }; static void server_main(void) { int ret; //向ubusd新增一個物件,之後test_object在ubusd中有一個id號,其他程序通過該id號來向test_object傳送訊息。 ret = ubus_add_object(ctx, &test_object); if (ret) fprintf(stderr, "Failed to add object: %s\n", ubus_strerror(ret)); uloop_run(); } int main(int argc, char **argv) { const char *ubus_socket = NULL; int ch; while ((ch = getopt(argc, argv, "cs:")) != -1) { switch (ch) { case 's': ubus_socket = optarg; break; default: break; } } argc -= optind; argv += optind; uloop_init(); signal(SIGPIPE, SIG_IGN); ctx = ubus_connect(ubus_socket); if (!ctx) { fprintf(stderr, "Failed to connect to ubus\n"); return -1; } ubus_add_uloop(ctx); server_main(); ubus_free(ctx); uloop_done(); return 0; }
客戶端程式碼
#include <sys/time.h> #include <unistd.h> #include "libubus.h" static struct ubus_context *ctx; static struct blob_buf b; enum { RETURN_CODE, __RETURN_MAX, }; static const struct blobmsg_policy return_policy[__RETURN_MAX] = { [RETURN_CODE] = { .name = "stacnt", .type = BLOBMSG_TYPE_INT32 }, }; static void get_result_data_cb(struct ubus_request *req, int type, struct blob_attr *msg) { struct blob_attr *tb[__RETURN_MAX]; int rc; //返回的資料也是有tlv格式的,按照return_policy格式進行解析。 blobmsg_parse(return_policy, __RETURN_MAX, tb, blob_data(msg), blob_len(msg)); if (!tb[RETURN_CODE]) { fprintf(stderr, "No return code received from server\n"); return; } rc = blobmsg_get_u32(tb[RETURN_CODE]); fprintf(stderr, "get station number is %d \n", rc); } static void client_main(void) { static struct ubus_request req; uint32_t id; int ret; int ap_index=2; //查詢ubusd上的server_fun物件。該物件由server端註冊 if (ubus_lookup_id(ctx, "server_fun", &id)) { fprintf(stderr, "Failed to look up test object\n"); return; } //b 為全域性變數,初始化 blob_buf_init(&b, 0); //添加發送buffer的tlv,格式由server_main.c的fun2_message_parse_policy定義 blobmsg_add_u32(&b, "getcnt", ap_index); //觸發server端註冊的函式,並接收返回值,處理函式為get_result_data_cb ubus_invoke(ctx, id, "fun2", b.head, get_result_data_cb, NULL, 3000); } int main(int argc, char **argv) { const char *ubus_socket = NULL; int ch; while ((ch = getopt(argc, argv, "cs:")) != -1) { switch (ch) { case 's': ubus_socket = optarg; break; default: break; } } argc -= optind; argv += optind; uloop_init(); ctx = ubus_connect(ubus_socket); if (!ctx) { fprintf(stderr, "Failed to connect to ubus\n"); return -1; } ubus_add_uloop(ctx); client_main(); ubus_free(ctx); uloop_done(); return 0; }
以上程式碼:伺服器端向ubusd註冊了個server_fun的伺服器物件,客戶端通過server_fun ubus物件與伺服器端通訊。
其他:ubus shell呼叫格式
ubus send linkinspect '{"ac_cmd":1}'