libubus: refactor ubus_context msgbuf data to be dynamically allocated
authorAlexandru Ardelean <ardeleanalex@gmail.com>
Fri, 27 Jun 2014 16:11:39 +0000 (19:11 +0300)
committerFelix Fietkau <nbd@openwrt.org>
Thu, 3 Jul 2014 10:42:42 +0000 (12:42 +0200)
libubus-io.c
libubus.c
libubus.h

index 9a6c7cd77ec168be2b6779fc9fe05aea751c0fa2..c63a9201cd713256ed6616b75427ff4f9087034e 100644 (file)
@@ -212,7 +212,7 @@ static int recv_retry(int fd, struct iovec *iov, bool wait, int *recv_fd)
 
 static bool ubus_validate_hdr(struct ubus_msghdr *hdr)
 {
-       struct blob_attr *data = ubus_msghdr_data(hdr);
+       struct blob_attr *data = (struct blob_attr *) (hdr + 1);
 
        if (hdr->version != 0)
                return false;
@@ -228,11 +228,14 @@ static bool ubus_validate_hdr(struct ubus_msghdr *hdr)
 
 static bool get_next_msg(struct ubus_context *ctx, int *recv_fd)
 {
-       struct iovec iov = STATIC_IOV(ctx->msgbuf.hdr);
+       struct {
+               struct ubus_msghdr hdr;
+               struct blob_attr data;
+       } hdrbuf;
+       struct iovec iov = STATIC_IOV(hdrbuf);
        int r;
 
        /* receive header + start attribute */
-       iov.iov_len += sizeof(struct blob_attr);
        r = recv_retry(ctx->sock.fd, &iov, false, recv_fd);
        if (r <= 0) {
                if (r < 0)
@@ -241,11 +244,18 @@ static bool get_next_msg(struct ubus_context *ctx, int *recv_fd)
                return false;
        }
 
-       iov.iov_len = blob_len(ubus_msghdr_data(&ctx->msgbuf.hdr));
+       if (!ubus_validate_hdr(&hdrbuf.hdr))
+               return false;
+
+       memcpy(&ctx->msgbuf.hdr, &hdrbuf.hdr, sizeof(hdrbuf.hdr));
+       memcpy(ctx->msgbuf.data, &hdrbuf.data, sizeof(hdrbuf.data));
+
+       iov.iov_base = (char *)ctx->msgbuf.data + sizeof(hdrbuf.data);
+       iov.iov_len = blob_len(ctx->msgbuf.data);
        if (iov.iov_len > 0 && !recv_retry(ctx->sock.fd, &iov, true, NULL))
                return false;
 
-       return ubus_validate_hdr(&ctx->msgbuf.hdr);
+       return true;
 }
 
 void __hidden ubus_handle_data(struct uloop_fd *u, unsigned int events)
index 1a550c126265aaa72ce4ba623d00dfb370773e29..83a2c43540c828f5e36c7e868f4b1799c627a72b 100644 (file)
--- a/libubus.c
+++ b/libubus.c
@@ -40,7 +40,7 @@ struct blob_buf b __hidden = {};
 
 struct ubus_pending_msg {
        struct list_head list;
-       struct ubus_msghdr hdr;
+       struct ubus_msghdr_buf hdr;
 };
 
 static int ubus_cmp_id(const void *k1, const void *k2, void *ptr)
@@ -75,11 +75,15 @@ ubus_queue_msg(struct ubus_context *ctx, struct ubus_msghdr *hdr)
 {
        struct ubus_pending_msg *pending;
 
-       pending = calloc(1, sizeof(*pending) + blob_raw_len(ubus_msghdr_data(hdr)));
+       pending = calloc(1, sizeof(*pending));
        if (!pending)
                return;
+       pending->hdr.data = calloc(1, blob_raw_len(ubus_msghdr_data(hdr)));
+       if (!pending->hdr.data)
+               return;
 
-       memcpy(&pending->hdr, hdr, sizeof(*hdr) + blob_raw_len(ubus_msghdr_data(hdr)));
+       memcpy(&pending->hdr.hdr, hdr, sizeof(*hdr));
+       memcpy(pending->hdr.data, ubus_msghdr_data(hdr), blob_raw_len(ubus_msghdr_data(hdr)));
        list_add(&pending->list, &ctx->pending);
        if (ctx->sock.registered)
                uloop_timeout_set(&ctx->pending_timer, 1);
@@ -116,7 +120,8 @@ static void ubus_process_pending_msg(struct uloop_timeout *timeout)
        while (!ctx->stack_depth && !list_empty(&ctx->pending)) {
                pending = list_first_entry(&ctx->pending, struct ubus_pending_msg, list);
                list_del(&pending->list);
-               ubus_process_msg(ctx, &pending->hdr, -1);
+               ubus_process_msg(ctx, &pending->hdr.hdr, -1);
+               free(pending->hdr.data);
                free(pending);
        }
 }
@@ -275,11 +280,17 @@ static int _ubus_connect(struct ubus_context *ctx, const char *path)
        ctx->connection_lost = ubus_default_connection_lost;
        ctx->pending_timer.cb = ubus_process_pending_msg;
 
+       ctx->msgbuf.data = calloc(UBUS_MAX_MSGLEN, sizeof(char));
+       if (!ctx->msgbuf.data)
+               return -1;
+
        INIT_LIST_HEAD(&ctx->requests);
        INIT_LIST_HEAD(&ctx->pending);
        avl_init(&ctx->objects, ubus_cmp_id, false, NULL);
-       if (ubus_reconnect(ctx, path))
+       if (ubus_reconnect(ctx, path)) {
+               free(ctx->msgbuf.data);
                return -1;
+       }
 
        return 0;
 }
@@ -343,5 +354,6 @@ void ubus_free(struct ubus_context *ctx)
 {
        blob_buf_free(&b);
        close(ctx->sock.fd);
+       free(ctx->msgbuf.data);
        free(ctx);
 }
index 6c560b4fe5b380f324356ba129499b4b788b5f27..33a99aafd317c8d4680324a62e6566c5630412b2 100644 (file)
--- a/libubus.h
+++ b/libubus.h
@@ -34,10 +34,16 @@ struct ubus_event_handler;
 struct ubus_subscriber;
 struct ubus_notify_request;
 
+struct ubus_msghdr_buf {
+       struct ubus_msghdr hdr;
+       struct blob_attr *data;
+};
+
 static inline struct blob_attr *
 ubus_msghdr_data(struct ubus_msghdr *hdr)
 {
-       return (struct blob_attr *) (hdr + 1);
+       struct ubus_msghdr_buf *hdrbuf = container_of(hdr, typeof(*hdrbuf), hdr);
+       return hdrbuf->data;
 }
 
 typedef void (*ubus_lookup_handler_t)(struct ubus_context *ctx,
@@ -148,10 +154,7 @@ struct ubus_context {
 
        void (*connection_lost)(struct ubus_context *ctx);
 
-       struct {
-               struct ubus_msghdr hdr;
-               char data[UBUS_MAX_MSGLEN];
-       } msgbuf;
+       struct ubus_msghdr_buf msgbuf;
 };
 
 struct ubus_object_data {