• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/ubus/libubus-sub.c

  1 /*
  2  * Copyright (C) 2011-2012 Felix Fietkau <nbd@openwrt.org>
  3  *
  4  * This program is free software; you can redistribute it and/or modify
  5  * it under the terms of the GNU Lesser General Public License version 2.1
  6  * as published by the Free Software Foundation
  7  *
  8  * This program is distributed in the hope that it will be useful,
  9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 11  * GNU General Public License for more details.
 12  */
 13 
 14 #include "libubus.h"
 15 #include "libubus-internal.h"
 16 
 17 static int ubus_subscriber_cb(struct ubus_context *ctx, struct ubus_object *obj,
 18                          struct ubus_request_data *req,
 19                          const char *method, struct blob_attr *msg)
 20 {
 21         struct ubus_subscriber *s;
 22 
 23         s = container_of(obj, struct ubus_subscriber, obj);
 24         if (s->cb)
 25                 return s->cb(ctx, obj, req, method, msg);
 26         return 0;
 27 }
 28 
 29 const struct ubus_method watch_method __hidden = {
 30         .name = NULL,
 31         .handler = ubus_subscriber_cb,
 32 };
 33 
 34 static void
 35 ubus_auto_sub_event_handler_cb(struct ubus_context *ctx,  struct ubus_event_handler *ev,
 36                                const char *type, struct blob_attr *msg)
 37 {
 38         enum {
 39                 EVENT_ID,
 40                 EVENT_PATH,
 41                 __EVENT_MAX
 42         };
 43 
 44         static const struct blobmsg_policy event_policy[__EVENT_MAX] = {
 45                 [EVENT_ID] = { .name = "id", .type = BLOBMSG_TYPE_INT32 },
 46                 [EVENT_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
 47         };
 48 
 49         struct blob_attr *tb[__EVENT_MAX];
 50         struct ubus_subscriber *s;
 51         const char *path;
 52         int id;
 53 
 54         blobmsg_parse(event_policy, __EVENT_MAX, tb, blob_data(msg), blob_len(msg));
 55 
 56         if (!tb[EVENT_ID] || !tb[EVENT_PATH])
 57                 return;
 58 
 59         path = blobmsg_get_string(tb[EVENT_PATH]);
 60         id = blobmsg_get_u32(tb[EVENT_ID]);
 61 
 62         list_for_each_entry(s, &ctx->auto_subscribers, list)
 63                 if (s->new_obj_cb(ctx, s, path))
 64                         ubus_subscribe(ctx, s, id);
 65 }
 66 
 67 static void
 68 ubus_auto_sub_lookup(struct ubus_context *ctx, struct ubus_object_data *obj,
 69                      void *priv)
 70 {
 71         struct ubus_subscriber *s = priv;
 72 
 73         if (s->new_obj_cb(ctx, s, obj->path))
 74                 ubus_subscribe(ctx, s, obj->id);
 75 }
 76 
 77 int ubus_register_subscriber(struct ubus_context *ctx, struct ubus_subscriber *s)
 78 {
 79         struct ubus_object *obj = &s->obj;
 80         int ret;
 81 
 82         if (ubus_context_is_channel(ctx))
 83                 return UBUS_STATUS_INVALID_ARGUMENT;
 84 
 85         INIT_LIST_HEAD(&s->list);
 86         obj->methods = &watch_method;
 87         obj->n_methods = 1;
 88 
 89         ret = ubus_add_object(ctx, obj);
 90         if (ret)
 91                 return ret;
 92 
 93         if (s->new_obj_cb) {
 94                 struct ubus_event_handler *ev = &ctx->auto_subscribe_event_handler;
 95                 list_add(&s->list, &ctx->auto_subscribers);
 96                 ev->cb = ubus_auto_sub_event_handler_cb;
 97                 if (!ev->obj.id)
 98                         ubus_register_event_handler(ctx, ev, "ubus.object.add");
 99                 ubus_lookup(ctx, NULL, ubus_auto_sub_lookup, s);
100         }
101 
102         return 0;
103 }
104 
105 static int
106 __ubus_subscribe_request(struct ubus_context *ctx, struct ubus_object *obj, uint32_t id, int type)
107 {
108         struct ubus_request req;
109 
110         if (ubus_context_is_channel(ctx))
111                 return UBUS_STATUS_INVALID_ARGUMENT;
112 
113         blob_buf_init(&b, 0);
114         blob_put_int32(&b, UBUS_ATTR_OBJID, obj->id);
115         blob_put_int32(&b, UBUS_ATTR_TARGET, id);
116 
117         if (ubus_start_request(ctx, &req, b.head, type, 0) < 0)
118                 return UBUS_STATUS_INVALID_ARGUMENT;
119 
120         return ubus_complete_request(ctx, &req, 0);
121 
122 }
123 
124 int ubus_subscribe(struct ubus_context *ctx, struct ubus_subscriber *obj, uint32_t id)
125 {
126         return __ubus_subscribe_request(ctx, &obj->obj, id, UBUS_MSG_SUBSCRIBE);
127 }
128 
129 int ubus_unsubscribe(struct ubus_context *ctx, struct ubus_subscriber *obj, uint32_t id)
130 {
131         return __ubus_subscribe_request(ctx, &obj->obj, id, UBUS_MSG_UNSUBSCRIBE);
132 }
133 
134 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt