ubus[2]-libus

11037 ワード

libus
データ構造
struct ubus_event_handler {
    struct ubus_object obj;

    ubus_event_handler_t cb;
};

struct ubus_context {
    struct list_head requests;
    struct avl_tree objects;    /** client object    */
    struct list_head pending;

    struct uloop_fd sock;       /** client sock   */

    uint32_t local_id;          /** ubusd   client id */
    uint16_t request_seq;
    int stack_depth;

/**          */
    void (*connection_lost)(struct ubus_context *ctx);

    struct {
        struct ubus_msghdr hdr;
        char data[UBUS_MAX_MSGLEN];
    } msgbuf;                   /**      */
};

struct ubus_object_data {
    uint32_t id;
    uint32_t type_id;
    const char *path;
    struct blob_attr *signature;
};

struct ubus_request_data {
    uint32_t object;
    uint32_t peer;
    uint16_t seq;

    /* internal use */
    bool deferred;
    int fd;
};

struct ubus_request {
    struct list_head list;

    struct list_head pending;
    int status_code;
    bool status_msg;
    bool blocked;
    bool cancelled;
    bool notify;

    uint32_t peer;
    uint16_t seq;

    ubus_data_handler_t raw_data_cb;
    ubus_data_handler_t data_cb;
    ubus_fd_handler_t fd_cb;
    ubus_complete_handler_t complete_cb;

    struct ubus_context *ctx;
    void *priv;
};

struct ubus_notify_request {
    struct ubus_request req;

    ubus_notify_complete_handler_t status_cb;
    ubus_notify_complete_handler_t complete_cb;

    uint32_t pending;
    uint32_t id[UBUS_MAX_NOTIFY_PEERS + 1];
};

struct ubus_auto_conn {
    struct ubus_context ctx;
    struct uloop_timeout timer;
    const char *path;
    ubus_connect_handler_t cb;
};
インターフェースの説明
/**
 *    client context  ,   ubusd
 */
struct ubus_context *ubus_connect(const char *path)

/**
 *  ubus_connect()        ,                 
 */
void ubus_auto_connect(struct ubus_auto_conn *conn)

/**
 *      
 */
int ubus_register_event_handler(struct ubus_context *ctx,
                struct ubus_event_handler *ev,
                const char *pattern)

/**
 *       
 */
int ubus_send_event(struct ubus_context *ctx, const char *id,
            struct blob_attr *data)

/**
 *  ubusd    UBUS_ATTR_OBJPATH        
 *           ubus_lookup_handler_t        
 */
int ubus_lookup(struct ubus_context *ctx, const char *path,
        ubus_lookup_handler_t cb, void *priv)

/**
 *  ubusd    UBUS_ATTR_OBJPATH   ID 
 */
int ubus_lookup_id(struct ubus_context *ctx, const char *path, uint32_t *id)
libus-i
インターフェースの説明
/**
 * libubus            
 */
static const struct blob_attr_info ubus_policy[UBUS_ATTR_MAX] = {
    [UBUS_ATTR_STATUS] = { .type = BLOB_ATTR_INT32 },
    [UBUS_ATTR_OBJID] = { .type = BLOB_ATTR_INT32 },
    [UBUS_ATTR_OBJPATH] = { .type = BLOB_ATTR_STRING },
    [UBUS_ATTR_METHOD] = { .type = BLOB_ATTR_STRING },
    [UBUS_ATTR_ACTIVE] = { .type = BLOB_ATTR_INT8 },
    [UBUS_ATTR_NO_REPLY] = { .type = BLOB_ATTR_INT8 },
    [UBUS_ATTR_SUBSCRIBERS] = { .type = BLOB_ATTR_NESTED },
};

/**
 *  libubus             blob_attr  
 */
__hidden struct blob_attr **ubus_parse_msg(struct blob_attr *msg)

/**
 *     
 * 
 * @param ctx    - client     
 * @param seq    -       hdr.seq
 * @param msg    -      
 * @param cmd    -      hdr.type
 * @param perr   -
 * @param fd     -           ,  -1      
 */
int __hidden ubus_send_msg(struct ubus_context *ctx, uint32_t seq,
               struct blob_attr *msg, int cmd, uint32_t peer, int fd)

/**
 * client fd      
 */
void __hidden ubus_handle_data(struct uloop_fd *u, unsigned int events)

/**
 * client   fd      
 */
void __hidden ubus_poll_data(struct ubus_context *ctx, int timeout)

/**
 * client  ubusd server
 */
int ubus_reconnect(struct ubus_context *ctx, const char *path)
libus-obj
データ構造
struct ubus_object {
    struct avl_node avl;  /**    struct ubus_context objects */

    const char *name;     /** UBUS_ATTR_OBJPATH */
    uint32_t id;          /**  ubusd server   obj id */

    const char *path;
    struct ubus_object_type *type;

/**  1       1         */
    ubus_state_handler_t subscribe_cb;
    bool has_subscribers;    /**          */

    const struct ubus_method *methods;  /**      */
    int n_methods;                      /**        */
};

struct ubus_object_type {
    const char *name;
    uint32_t id;            /**  ubusd server   obj type id */

    const struct ubus_method *methods;  /**      */
    int n_methods;                      /**        */
};

struct ubus_method {
    const char *name;         /**      */
    ubus_handler_t handler;   /**          */

    unsigned long mask;                   /**        */
    const struct blobmsg_policy *policy;  /**        */
    int n_policy;                         /**          */
};
インターフェースの説明
/**
 * client  ubusd server       object
 */
int ubus_add_object(struct ubus_context *ctx, struct ubus_object *obj)

/**
 * client  ubusd server      object
 */
int ubus_remove_object(struct ubus_context *ctx, struct ubus_object *obj)

/**
 *      object    
 */
void __hidden ubus_process_obj_msg(struct ubus_context *ctx, 
                                   struct ubus_msghdr *hdr)

/**
 *   UBUS_MSG_INVOKE  
 */
static void
ubus_process_invoke(struct ubus_context *ctx, struct ubus_msghdr *hdr,
            struct ubus_object *obj, struct blob_attr **attrbuf)

/**
 *   UBUS_MSG_UNSUBSCRIBE  
 */
static void
ubus_process_unsubscribe(struct ubus_context *ctx, struct ubus_msghdr *hdr,
             struct ubus_object *obj, struct blob_attr **attrbuf)

/**
 *   UBUS_MSG_NOTIFY  
 */
static void
ubus_process_notify(struct ubus_context *ctx, struct ubus_msghdr *hdr,
            struct ubus_object *obj, struct blob_attr **attrbuf)
libus-sub
データ構造
struct ubus_subscriber {
    struct ubus_object obj;

    ubus_handler_t cb;
    ubus_remove_handler_t remove_cb;
};
インターフェースの説明
/**
 * 
 */
int ubus_register_subscriber(struct ubus_context *ctx, struct ubus_subscriber *s)

/**
 * 
 */
int ubus_subscribe(struct ubus_context *ctx, struct ubus_subscriber *obj, 
                   uint32_t id)

/**
 *
 */
int ubus_unsubscribe(struct ubus_context *ctx, struct ubus_subscriber *obj,
                     uint32_t id)
libus-req
データ構造
struct ubus_request_data {
    uint32_t object;
    uint32_t peer;
    uint16_t seq;

    /* internal use */
    bool deferred;
    int fd;
};

struct ubus_request {
    struct list_head list;

    struct list_head pending;
    int status_code;
    bool status_msg;
    bool blocked;
    bool cancelled;
    bool notify;

    uint32_t peer;
    uint16_t seq;

    ubus_data_handler_t raw_data_cb;
    ubus_data_handler_t data_cb;
    ubus_fd_handler_t fd_cb;
    ubus_complete_handler_t complete_cb;

    struct ubus_context *ctx;
    void *priv;
};

struct ubus_notify_request {
    struct ubus_request req;

    ubus_notify_complete_handler_t status_cb;
    ubus_notify_complete_handler_t complete_cb;

    uint32_t pending;
    uint32_t id[UBUS_MAX_NOTIFY_PEERS + 1];
};
インターフェースの説明
/**
 *       ,    UBUS_MSG_DATA
 */
int ubus_send_reply(struct ubus_context *ctx, struct ubus_request_data *req,
            struct blob_attr *msg)

/**
 *       object     
 */
int ubus_invoke_async(struct ubus_context *ctx, uint32_t obj, const char *method,
                       struct blob_attr *msg, struct ubus_request *req)

/**
 *       object     
 */

int ubus_invoke(struct ubus_context *ctx, uint32_t obj, const char *method,
                struct blob_attr *msg, ubus_data_handler_t cb, void *priv,
        int timeout)

/**
 *         
 */
int ubus_notify_async(struct ubus_context *ctx, struct ubus_object *obj,
              const char *type, struct blob_attr *msg,
              struct ubus_notify_request *req)

/**
 *         
 */
int ubus_notify(struct ubus_context *ctx, struct ubus_object *obj,
        const char *type, struct blob_attr *msg, int timeout)

新しいobjectをubusdに登録します.
objectを定義する方法:
enum {
    OBJ_SET_ARG1,
    OBJ_SET_ARG2,
    __OBJ_SET_ATTR_MAX
};

/**   set       */
static const struct blobmsg_policy obj_set_attrs[__OBJ_SET_ATTR_MAX] = {
    [OBJ_SET_ARG1] = { .name = "arg1", .type = BLOBMSG_TYPE_STRING },
    [OBJ_SET_ARG2 ] = { .name = "arg2", .type = BLOBMSG_TYPE_STRING },
};

static struct ubus_method obj_methods[] = {
    { .name = "enable", .handler = obj_enable },
    UBUS_METHOD("set", obj_set, obj_set_attrs),
    { .name = "dump", .handler = obj_dump },
};
objectのタイプを定義します
static struct ubus_object_type obj_type = 
    UBUS_OBJECT_TYPE("my_obj", obj_methods);
定義object:
static struct ubus_object obj = {
    .name = "myobj",
    .type = &obj_type,
    .methods = obj_methods,
    .n_methods = ARRAR_SIZE(obj_methods),
};
新しいobjectを登録する:
    uloop_init();

    struct ubus_context *ubus_ctx = ubus_connect(NULL);
    ubus_add_uloop(ubus_ctx);
    ubus_add_object(ubus_ctx, &obj);

    uloop_run();
ubusd登録イベントの傍受
イベントトリガのコールバック方法を指定します.
static void
event_receive_cb(struct ubus_context *ctx, struct ubus_event_handler *ev, 
                const char *type, struct blob_attr *msg)
{
    enum {
        EV_ACTION,
        EV_IFNAME,
        __EV_MAX
    };
    static const struct blobmsg_policy ev_policy[__EV_MAX] = {
        [EV_ACTION] = { .name = "action", .type = BLOBMSG_TYPE_STRING },
        [EV_IFNAME] = { .name = "interface", .type = BLOBMSG_TYPE_STRING },
    };
    struct blob_attr *tb[__EV_MAX];

    blobmsg_parse(ev_policy, __EV_MAX, tb, blob_data(msg), blob_len(msg));

    /* do something */
}
登録傍受イベント
static void
event_listen(void)
{
    static struct ubus_event_handler listener;
    memset(&listener, 0, sizeof(listener));

    /**   netwrok.interface   */
    ubus_register_event_handler(ubus_ctx, &listener, "network.interface");
}
ubusdにコマンドを送信します.
コマンドの折り返し方法を指定します.
static void
command_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
    if (!msg)
        return;

    enum {
        ADDR_IPV4,
        __ADDR_MAX,
    };
    static const struct blobmsg_policy policy[__ADDR_MAX] = {
        [ADDR_IPV4] = { .name = "ipv4-address", .type = BLOBMSG_TYPE_ARRAY },
    };
    struct blob_attr *tb[__ADDR_MAX];

    blobmsg_parse(policy, __ADDR_MAX, tb, blobmsg_data(msg), blobmsg_len(msg));

    /** do something */
}
コマンドを送信:
static void
invoke_command(char *net)
{
    uint32_t id;
    char path[64] = {0};

    sprintf(path, "network.interface.%s", net);

    /** lookup `network.interface.%s` object id */
    ubus_lookup_id(ubus_ctx, path, &id);

    /** invoke command `status` */
    ubus_invoke(ubus_ctx, id, "status", NULL, command_cb, NULL, 500);
}