struct ubus_msg_buf { uint32_t refcount; /* ~0: uses external data buffer */ struct ubus_msghdr hdr; struct blob_attr *data; int fd; /** 發送msg端進程傳過來的fd,用於UBUS_MSG_STATUS消息 */ int len; }; struct ubus_client { struct ubus_id id; struct uloop_fd sock; struct list_head objects; struct ubus_msg_buf *tx_queue[UBUSD_CLIENT_BACKLOG]; /** * txq_cur - tx隊列未處理頭結點 * txq_tail - tx隊列可用結點頭 * txq_ofs - 當前結點已發送offset */ unsigned int txq_cur, txq_tail, txq_ofs; struct ubus_msg_buf *pending_msg; int pending_msg_offset; int pending_msg_fd; /** 對端進程傳過來的fd */ struct { struct ubus_msghdr hdr; struct blob_attr data; } hdrbuf; /** 報文格式頭 */ }; struct ubus_path { struct list_head list; const char name[]; };
ubusd
啓動時自動調用初始化函數ubusd_obj_init(void)
分別建立objects、obj_types、path三個AVL tree頭節點,同時調用ubusd_event_init()
函數初始化patterns AVL tree頭節點,建立event_obj全局事件對象,對象ID等於1(UBUS_SYSTEM_OBJECT_EVENT)node
Server_fd監聽函數server_cb註冊到uloop中數據結構
新client鏈接時
建立struct ubus_client數據結構,初始化client fd回調函數client_cb,並加入到全局clients avl_tree中進行維護,最後把此client註冊到uloop中函數
收到client報文時
若是發送隊列中存在數據,則儘可能把隊列中全部內容發出
先收取報文頭部數據,以肯定整個報文內容長度,報文頭部數據結構以下oop
struct { struct ubus_msghdr hdr; struct blob_attr data; } hdrbuf; struct ubus_msghdr { uint8_t version; uint8_t type; uint16_t seq; uint32_t peer; } __packetdata; struct blob_attr { uint32_t id_len; char data[]; } __packed;
收取整個報文內容,存放到struct ubus_msg_buf
結構中
調用ubusd_proto_receive_message()
函數處理報文內容,此函數根據hdr.type
在註冊的handlers中查詢對應的函數,具體請看ubusd_proto說明ui
消息類型 | 處理函數 |
---|---|
UBUS_MSG_PING | ubusd_send_pong |
UBUS_MSG_ADD_OBJECT | ubusd_handle_add_object |
UBUS_MSG_REMOVE_OBJECT | ubusd_handle_remove_object |
UBUS_MSG_LOOKUP | ubusd_handle_lookup |
UBUS_MSG_INVOKE | ubusd_handle_invoke |
UBUS_MSG_STATUS | ubusd_handle_response |
UBUS_MSG_DATA | ubusd_handle_response |
UBUS_MSG_SUBSCRIBE | ubusd_handle_add_watch |
UBUS_MSG_UNSUBSCRIBE | ubusd_handle_remove_watch |
UBUS_MSG_NOTIFY | ubusd_handle_notify |
保活探測報文,收到後迴應一個類型爲UBUS_MSG_DATA的報文便可code
建立內部object,迴應一個類型爲UBUS_MSG_DATA的報文,報文內容有由ubusd生成的UBUS_ATTR_OBJIDserver
刪除內部object,根據請求報文UBUS_ATTR_OBJID查找對應的內容object,若是存在且object建立者等於刪除請求者,則刪除此object,迴應一個類型爲UBUS_MSG_DATA的報文,報文內容有刪除object的UBUS_ATTR_OBJID對象
查詢object,根據請求報文UBUS_ATTR_OBJPATH查找對應的object,使用ubusd_send_obj()函數把查詢出object內容迴應給查詢請求者接口
執行object,根據請求報文UBUS_ATTR_OBJID查找對應的object,若是object爲ubusd本地對象(event_object)則由本地對象處理,不然使用ubusd_forward_invoke()函數把消息轉發給object擁有者,消息類型爲UBUS_MSG_INVOKE隊列
處理結果狀態,把結果轉發給請求者
同UBUS_MSG_STATUS
通知全部訂閱者,使用ubusd_forward_invoke()函數通知訂閱請求者全部訂閱者
訂閱object,使用ubus_subscribe()函數訂閱指定object
退訂object,使用ubus_unsubscribe()函數退訂全部已訂閱的object
struct event_source { struct list_head list; /** object結構中events隊列 */ struct ubus_object *obj; /** 指向事件object實體 */ struct avl_node avl; /** patterns全局avl tree隊列 */ bool partial; };
static struct blobmsg_policy evr_policy[] = { [EVREG_PATTERN] = { .name = "pattern", .type = BLOBMSG_TYPE_STRING }, [EVREG_OBJECT] = { .name = "object", .type = BLOBMSG_TYPE_INT32 }, };
Send轉發某個事件內容,使用ubusd_forward_event()函數把指定事件內容轉發給此事件所屬的object擁有者
事件報文內容
static struct blobmsg_policy ev_policy[] = { [EVMSG_ID] = { .name = "id", .type = BLOBMSG_TYPE_STRING }, [EVMSG_DATA] = { .name = "data", .type = BLOBMSG_TYPE_TABLE }, };
提供ubusd_send_obj_event()接口發佈"ubus.object.add"和"ubus.object.remove"事件
struct ubus_id { struct avl_node avl; uint32_t id; };
void ubus_init_id_tree(struct avl_tree *tree); /** * @param dup - 容許存在相同結點 */ void ubus_init_string_tree(struct avl_tree *tree, bool dup); static inline void ubus_free_id(struct avl_tree *tree, struct ubus_id *id)
/** * 添加新ubus_id到val樹中 * * @param tree - val樹根結點 * @param id - 新ubus_id * @param val - 新ubus_id值,若是爲0則表示自動隨機生成 * @return true - 成功;false - 失敗 */ bool ubus_alloc_id(struct avl_tree *tree, struct ubus_id *id, uint32_t val)
static inline struct ubus_id *ubus_find_id(struct avl_tree *tree, uint32_t id)
struct ubus_object_type { struct ubus_id id; int refcount; struct list_head methods; }; struct ubus_method { struct list_head list; const char *name; struct blob_attr data[]; }; struct ubus_subscription { struct list_head list, target_list; struct ubus_object *subscriber, *target; }; struct ubus_object { struct ubus_id id; struct list_head list; struct list_head events; /** 事件鏈表頭 */ /** * subscribers - 被哪些對象訂閱鏈表頭 * target_list - 已訂閱哪些對象鏈表頭 */ struct list_head subscribers, target_list; struct ubus_object_type *type; struct avl_node path; struct ubus_client *client; int (*recv_msg)(struct ubus_client *client, const char *method, struct blob_attr *msg); int event_seen; unsigned int invoke_seq; };
/** * 建立新ubus_object * * @param attr - UBUS_ATTR_OBJTYPE UBUS_ATTR_SIGNATURE UBUS_ATTR_OBJPATH */ struct ubus_object *ubusd_create_object(struct ubus_client *cl, struct blob_attr **attr); /** * 建立新ubus_object */ struct ubus_object *ubusd_create_object_internal(struct ubus_object_type *type, uint32_t id); /** * 銷燬ubus_object */ void ubusd_free_object(struct ubus_object *obj);
static inline struct ubus_object *ubusd_find_object(uint32_t objid);
/** * obj訂閱target * * @param obj - 訂閱者對象 * @param target - 被訂閱對象 */ void ubus_subscribe(struct ubus_object *obj, struct ubus_object *target); /** * 退訂 */ void ubus_unsubscribe(struct ubus_subscription *s);