examples/server: send a file descriptor as part of the request to the "hello" method
[project/ubus.git] / libubus-req.c
index 4d0adb6..79e5643 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2011-2014 Felix Fietkau <nbd@openwrt.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License version 2.1
@@ -11,6 +11,7 @@
  * GNU General Public License for more details.
  */
 
+#include <unistd.h>
 #include "libubus.h"
 #include "libubus-internal.h"
 
@@ -61,12 +62,12 @@ int __hidden ubus_start_request(struct ubus_context *ctx, struct ubus_request *r
        req->ctx = ctx;
        req->peer = peer;
        req->seq = ++ctx->request_seq;
-       return ubus_send_msg(ctx, req->seq, msg, cmd, peer);
+       return ubus_send_msg(ctx, req->seq, msg, cmd, peer, -1);
 }
 
 void ubus_abort_request(struct ubus_context *ctx, struct ubus_request *req)
 {
-       if (!list_empty(&req->list))
+       if (list_empty(&req->list))
                return;
 
        req->cancelled = true;
@@ -157,6 +158,8 @@ int ubus_complete_request(struct ubus_context *ctx, struct ubus_request *req,
                uloop_cancelled = cancelled;
        }
        ctx->stack_depth--;
+       if (ctx->stack_depth)
+               uloop_cancelled = true;
 
        if (timeout)
                uloop_timeout_cancel(&cb.timeout);
@@ -182,7 +185,7 @@ void ubus_complete_deferred_request(struct ubus_context *ctx, struct ubus_reques
        blob_buf_init(&b, 0);
        blob_put_int32(&b, UBUS_ATTR_STATUS, ret);
        blob_put_int32(&b, UBUS_ATTR_OBJID, req->object);
-       ubus_send_msg(ctx, req->seq, b.head, UBUS_MSG_STATUS, req->peer);
+       ubus_send_msg(ctx, req->seq, b.head, UBUS_MSG_STATUS, req->peer, req->fd);
 }
 
 int ubus_send_reply(struct ubus_context *ctx, struct ubus_request_data *req,
@@ -193,7 +196,7 @@ int ubus_send_reply(struct ubus_context *ctx, struct ubus_request_data *req,
        blob_buf_init(&b, 0);
        blob_put_int32(&b, UBUS_ATTR_OBJID, req->object);
        blob_put(&b, UBUS_ATTR_DATA, blob_data(msg), blob_len(msg));
-       ret = ubus_send_msg(ctx, req->seq, b.head, UBUS_MSG_DATA, req->peer);
+       ret = ubus_send_msg(ctx, req->seq, b.head, UBUS_MSG_DATA, req->peer, -1);
        if (ret < 0)
                return UBUS_STATUS_NO_DATA;
 
@@ -285,15 +288,17 @@ int ubus_notify(struct ubus_context *ctx, struct ubus_object *obj,
        if (ret < 0)
                return ret;
 
-       if (timeout < 0)
+       if (timeout < 0) {
+               ubus_abort_request(ctx, &req.req);
                return 0;
+       }
 
        return ubus_complete_request(ctx, &req.req, timeout);
 }
 
 static bool ubus_get_status(struct ubus_msghdr *hdr, int *ret)
 {
-       struct blob_attr **attrbuf = ubus_parse_msg(hdr->data);
+       struct blob_attr **attrbuf = ubus_parse_msg(ubus_msghdr_data(hdr));
 
        if (!attrbuf[UBUS_ATTR_STATUS])
                return false;
@@ -317,12 +322,13 @@ ubus_process_req_status(struct ubus_request *req, struct ubus_msghdr *hdr)
 static void
 ubus_process_req_data(struct ubus_request *req, struct ubus_msghdr *hdr)
 {
+       struct blob_attr *msg_data = ubus_msghdr_data(hdr);
        struct ubus_pending_data *data;
        int len;
 
        if (!req->blocked) {
                req->blocked = true;
-               req_data_cb(req, hdr->type, hdr->data);
+               req_data_cb(req, hdr->type, msg_data);
                __ubus_process_req_data(req);
                req->blocked = false;
 
@@ -332,13 +338,13 @@ ubus_process_req_data(struct ubus_request *req, struct ubus_msghdr *hdr)
                return;
        }
 
-       len = blob_raw_len(hdr->data);
+       len = blob_raw_len(msg_data);
        data = calloc(1, sizeof(*data) + len);
        if (!data)
                return;
 
        data->type = hdr->type;
-       memcpy(data->data, hdr->data, len);
+       memcpy(data->data, msg_data, len);
        list_add(&data->list, &req->pending);
 }
 
@@ -392,14 +398,14 @@ static void ubus_process_notify_status(struct ubus_request *req, int id, struct
        struct blob_attr **tb;
        struct blob_attr *cur;
        int rem, idx = 1;
-       int ret;
+       int ret = 0;
 
        nreq = container_of(req, struct ubus_notify_request, req);
        nreq->pending &= ~(1 << id);
 
        if (!id) {
                /* first id: ubusd's status message with a list of ids */
-               tb = ubus_parse_msg(hdr->data);
+               tb = ubus_parse_msg(ubus_msghdr_data(hdr));
                if (tb[UBUS_ATTR_SUBSCRIBERS]) {
                        blob_for_each_attr(cur, tb[UBUS_ATTR_SUBSCRIBERS], rem) {
                                if (!blob_check_type(blob_data(cur), blob_len(cur), BLOB_ATTR_INT32))
@@ -423,7 +429,7 @@ static void ubus_process_notify_status(struct ubus_request *req, int id, struct
                ubus_set_req_status(req, 0);
 }
 
-void __hidden ubus_process_req_msg(struct ubus_context *ctx, struct ubus_msghdr *hdr)
+void __hidden ubus_process_req_msg(struct ubus_context *ctx, struct ubus_msghdr *hdr, int fd)
 {
        struct ubus_request *req;
        int id = -1;
@@ -434,6 +440,13 @@ void __hidden ubus_process_req_msg(struct ubus_context *ctx, struct ubus_msghdr
                if (!req)
                        break;
 
+               if (fd >= 0) {
+                       if (req->fd_cb)
+                               req->fd_cb(req, fd);
+                       else
+                               close(fd);
+               }
+
                if (id >= 0)
                        ubus_process_notify_status(req, id, hdr);
                else