[LEDE-DEV] [PATCH] Allow sending a fd along a ubus_request
Amine Aouled Hamed
amine.ahd at gmail.com
Mon Dec 19 01:31:54 PST 2016
Sorry for the duplicate, for some reasons gmail doesn't show the email
as a reply to the first email sent.
Amine.
On Mon, Dec 19, 2016 at 10:30 AM, amine.ahd <amine.ahd at gmail.com> wrote:
> Signed-off-by: amine.ahd <amine.ahd at gmail.com>
> ---
> libubus-internal.h | 4 +++-
> libubus-obj.c | 24 ++++++++++++++++--------
> libubus-req.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++---
> libubus.c | 2 +-
> libubus.h | 19 +++++++++++++++++++
> ubusd_proto.c | 6 +++++-
> 6 files changed, 91 insertions(+), 14 deletions(-)
>
> diff --git a/libubus-internal.h b/libubus-internal.h
> index f62edc3..c4067d3 100644
> --- a/libubus-internal.h
> +++ b/libubus-internal.h
> @@ -24,7 +24,9 @@ int ubus_send_msg(struct ubus_context *ctx, uint32_t seq,
> void ubus_process_msg(struct ubus_context *ctx, struct ubus_msghdr_buf *buf, int fd);
> int __hidden ubus_start_request(struct ubus_context *ctx, struct ubus_request *req,
> struct blob_attr *msg, int cmd, uint32_t peer);
> -void ubus_process_obj_msg(struct ubus_context *ctx, struct ubus_msghdr_buf *buf);
> +int __hidden __ubus_start_request(struct ubus_context *ctx, struct ubus_request *req,
> + struct blob_attr *msg, int cmd, uint32_t peer);
> +void ubus_process_obj_msg(struct ubus_context *ctx, struct ubus_msghdr_buf *buf, int fd);
> void ubus_process_req_msg(struct ubus_context *ctx, struct ubus_msghdr_buf *buf, int fd);
> void __hidden ubus_poll_data(struct ubus_context *ctx, int timeout);
>
> diff --git a/libubus-obj.c b/libubus-obj.c
> index 990d04b..a9972c5 100644
> --- a/libubus-obj.c
> +++ b/libubus-obj.c
> @@ -11,12 +11,13 @@
> * GNU General Public License for more details.
> */
>
> +#include <unistd.h>
> #include "libubus.h"
> #include "libubus-internal.h"
>
> static void
> ubus_process_unsubscribe(struct ubus_context *ctx, struct ubus_msghdr *hdr,
> - struct ubus_object *obj, struct blob_attr **attrbuf)
> + struct ubus_object *obj, struct blob_attr **attrbuf, int fd)
> {
> struct ubus_subscriber *s;
>
> @@ -29,11 +30,13 @@ ubus_process_unsubscribe(struct ubus_context *ctx, struct ubus_msghdr *hdr,
> s = container_of(obj, struct ubus_subscriber, obj);
> if (s->remove_cb)
> s->remove_cb(ctx, s, blob_get_u32(attrbuf[UBUS_ATTR_TARGET]));
> +
> + close(fd);
> }
>
> static void
> ubus_process_notify(struct ubus_context *ctx, struct ubus_msghdr *hdr,
> - struct ubus_object *obj, struct blob_attr **attrbuf)
> + struct ubus_object *obj, struct blob_attr **attrbuf, int fd)
> {
> if (!obj || !attrbuf[UBUS_ATTR_ACTIVE])
> return;
> @@ -41,14 +44,18 @@ ubus_process_notify(struct ubus_context *ctx, struct ubus_msghdr *hdr,
> obj->has_subscribers = blob_get_u8(attrbuf[UBUS_ATTR_ACTIVE]);
> if (obj->subscribe_cb)
> obj->subscribe_cb(ctx, obj);
> +
> + close(fd);
> }
> static void
> ubus_process_invoke(struct ubus_context *ctx, struct ubus_msghdr *hdr,
> - struct ubus_object *obj, struct blob_attr **attrbuf)
> + struct ubus_object *obj, struct blob_attr **attrbuf, int fd)
> {
> struct ubus_request_data req = {
> .fd = -1,
> + .req_fd = fd,
> };
> +
> int method;
> int ret;
> bool no_reply = false;
> @@ -65,7 +72,7 @@ ubus_process_invoke(struct ubus_context *ctx, struct ubus_msghdr *hdr,
>
> if (attrbuf[UBUS_ATTR_NO_REPLY])
> no_reply = blob_get_int8(attrbuf[UBUS_ATTR_NO_REPLY]);
> -
> +
> req.peer = hdr->peer;
> req.seq = hdr->seq;
> req.object = obj->id;
> @@ -88,6 +95,7 @@ found:
> ret = obj->methods[method].handler(ctx, obj, &req,
> blob_data(attrbuf[UBUS_ATTR_METHOD]),
> attrbuf[UBUS_ATTR_DATA]);
> + close(req.req_fd);
> if (req.deferred || no_reply)
> return;
>
> @@ -95,16 +103,16 @@ send:
> ubus_complete_deferred_request(ctx, &req, ret);
> }
>
> -void __hidden ubus_process_obj_msg(struct ubus_context *ctx, struct ubus_msghdr_buf *buf)
> +
> +void __hidden ubus_process_obj_msg(struct ubus_context *ctx, struct ubus_msghdr_buf *buf, int fd)
> {
> void (*cb)(struct ubus_context *, struct ubus_msghdr *,
> - struct ubus_object *, struct blob_attr **);
> + struct ubus_object *, struct blob_attr **, int fd);
> struct ubus_msghdr *hdr = &buf->hdr;
> struct blob_attr **attrbuf;
> struct ubus_object *obj;
> uint32_t objid;
> void *prev_data = NULL;
> -
> attrbuf = ubus_parse_msg(buf->data);
> if (!attrbuf[UBUS_ATTR_OBJID])
> return;
> @@ -131,7 +139,7 @@ void __hidden ubus_process_obj_msg(struct ubus_context *ctx, struct ubus_msghdr_
> buf->data = NULL;
> }
>
> - cb(ctx, hdr, obj, attrbuf);
> + cb(ctx, hdr, obj, attrbuf, fd);
>
> if (prev_data) {
> if (buf->data)
> diff --git a/libubus-req.c b/libubus-req.c
> index 416adab..5180a6f 100644
> --- a/libubus-req.c
> +++ b/libubus-req.c
> @@ -49,10 +49,9 @@ static void __ubus_process_req_data(struct ubus_request *req)
> }
> }
>
> -int __hidden ubus_start_request(struct ubus_context *ctx, struct ubus_request *req,
> +int __hidden __ubus_start_request(struct ubus_context *ctx, struct ubus_request *req,
> struct blob_attr *msg, int cmd, uint32_t peer)
> {
> - memset(req, 0, sizeof(*req));
>
> if (msg && blob_pad_len(msg) > UBUS_MAX_MSGLEN)
> return -1;
> @@ -62,9 +61,21 @@ 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, -1);
> +
> + return ubus_send_msg(ctx, req->seq, msg, cmd, peer, req->fd);
> }
>
> +int __hidden ubus_start_request(struct ubus_context *ctx, struct ubus_request *req,
> + struct blob_attr *msg, int cmd, uint32_t peer)
> +{
> + memset(req, 0, sizeof(*req));
> +
> + req->fd = -1;
> +
> + return __ubus_start_request(ctx, req, msg, cmd, peer);
> +}
> +
> +
> void ubus_abort_request(struct ubus_context *ctx, struct ubus_request *req)
> {
> if (list_empty(&req->list))
> @@ -224,6 +235,23 @@ int ubus_invoke_async(struct ubus_context *ctx, uint32_t obj, const char *method
> return 0;
> }
>
> +
> +int ubus_invoke_async_fd(struct ubus_context *ctx, uint32_t obj, const char *method,
> + struct blob_attr *msg, struct ubus_request *req, int fd)
> +{
> + blob_buf_init(&b, 0);
> + blob_put_int32(&b, UBUS_ATTR_OBJID, obj);
> + blob_put_string(&b, UBUS_ATTR_METHOD, method);
> + if (msg)
> + blob_put(&b, UBUS_ATTR_DATA, blob_data(msg), blob_len(msg));
> +
> + memset(req, 0, sizeof(*req));
> + req->fd = fd;
> + if (__ubus_start_request(ctx, req, b.head, UBUS_MSG_INVOKE, obj) < 0)
> + return UBUS_STATUS_INVALID_ARGUMENT;
> + return 0;
> +}
> +
> 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)
> @@ -240,6 +268,22 @@ int ubus_invoke(struct ubus_context *ctx, uint32_t obj, const char *method,
> return ubus_complete_request(ctx, &req, timeout);
> }
>
> +int ubus_invoke_fd(struct ubus_context *ctx, uint32_t obj, const char *method,
> + struct blob_attr *msg, ubus_data_handler_t cb, void *priv,
> + int timeout, int fd)
> +{
> + struct ubus_request req;
> + int rc;
> +
> + rc = ubus_invoke_async_fd(ctx, obj, method, msg, &req, fd);
> + if (rc)
> + return rc;
> +
> + req.data_cb = cb;
> + req.priv = priv;
> + return ubus_complete_request(ctx, &req, timeout);
> +}
> +
> static void
> ubus_notify_complete_cb(struct ubus_request *req, int ret)
> {
> diff --git a/libubus.c b/libubus.c
> index 8163ff7..b25d8b0 100644
> --- a/libubus.c
> +++ b/libubus.c
> @@ -103,7 +103,7 @@ ubus_process_msg(struct ubus_context *ctx, struct ubus_msghdr_buf *buf, int fd)
> break;
> }
>
> - ubus_process_obj_msg(ctx, buf);
> + ubus_process_obj_msg(ctx, buf, fd);
> break;
> case UBUS_MSG_MONITOR:
> if (ctx->monitor_cb)
> diff --git a/libubus.h b/libubus.h
> index 07239d6..350e694 100644
> --- a/libubus.h
> +++ b/libubus.h
> @@ -188,6 +188,7 @@ struct ubus_request_data {
> /* internal use */
> bool deferred;
> int fd;
> + int req_fd; /* fd received from the initial request */
> };
>
> struct ubus_request {
> @@ -208,6 +209,8 @@ struct ubus_request {
> ubus_fd_handler_t fd_cb;
> ubus_complete_handler_t complete_cb;
>
> + int fd;
> +
> struct ubus_context *ctx;
> void *priv;
> };
> @@ -336,6 +339,14 @@ int ubus_invoke(struct ubus_context *ctx, uint32_t obj, const char *method,
> int ubus_invoke_async(struct ubus_context *ctx, uint32_t obj, const char *method,
> struct blob_attr *msg, struct ubus_request *req);
>
> +int ubus_invoke_fd(struct ubus_context *ctx, uint32_t obj, const char *method,
> + struct blob_attr *msg, ubus_data_handler_t cb, void *priv,
> + int timeout, int fd);
> +
> +/* asynchronous version of ubus_invoke() */
> +int ubus_invoke_async_fd(struct ubus_context *ctx, uint32_t obj, const char *method,
> + struct blob_attr *msg, struct ubus_request *req, int fd);
> +
> /* send a reply to an incoming object method call */
> int ubus_send_reply(struct ubus_context *ctx, struct ubus_request_data *req,
> struct blob_attr *msg);
> @@ -356,6 +367,14 @@ static inline void ubus_request_set_fd(struct ubus_context *ctx,
> req->fd = fd;
> }
>
> +static inline int ubus_request_get_caller_fd(struct ubus_request_data *req)
> +{
> + int fd = req->req_fd;
> + req->req_fd = -1;
> +
> + return fd;
> +}
> +
> void ubus_complete_deferred_request(struct ubus_context *ctx,
> struct ubus_request_data *req, int ret);
>
> diff --git a/ubusd_proto.c b/ubusd_proto.c
> index b591384..49b4ea9 100644
> --- a/ubusd_proto.c
> +++ b/ubusd_proto.c
> @@ -80,11 +80,15 @@ void
> ubus_proto_send_msg_from_blob(struct ubus_client *cl, struct ubus_msg_buf *ub,
> uint8_t type)
> {
> + /* keep the fd to be passed if it is UBUS_MSG_INVOKE */
> + int fd = ub->fd;
> ub = ubus_reply_from_blob(ub, true);
> if (!ub)
> return;
>
> ub->hdr.type = type;
> + ub->fd = fd;
> +
> ubus_msg_send(cl, ub, true);
> }
>
> @@ -446,7 +450,7 @@ void ubusd_proto_receive_message(struct ubus_client *cl, struct ubus_msg_buf *ub
> if (ub->hdr.type < __UBUS_MSG_LAST)
> cb = handlers[ub->hdr.type];
>
> - if (ub->hdr.type != UBUS_MSG_STATUS)
> + if (ub->hdr.type != UBUS_MSG_STATUS && ub->hdr.type != UBUS_MSG_INVOKE)
> ubus_msg_close_fd(ub);
>
> if (cb)
> --
> 2.6.6
>
More information about the Lede-dev
mailing list