Ubus
OpenWrt system message/RPC bus.
ubusd_obj.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2011 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 "ubusd.h"
15 #include "ubusd_obj.h"
16 
17 struct avl_tree obj_types;
18 struct avl_tree objects;
19 struct avl_tree path;
20 
22 {
23  struct ubus_method *m, *tmp;
24 
25  if (--type->refcount > 0)
26  return;
27 
28  list_for_each_entry_safe(m, tmp, &type->methods, list) {
29  list_del(&m->list);
30  free(m);
31  }
32 
33  ubus_free_id(&obj_types, &type->id);
34  free(type);
35 }
36 
37 static bool ubus_create_obj_method(struct ubus_object_type *type, struct blob_attr *attr)
38 {
39  struct ubus_method *m;
40  int bloblen = blob_raw_len(attr);
41 
42  m = calloc(1, sizeof(*m) + bloblen);
43  if (!m)
44  return false;
45 
46  list_add_tail(&m->list, &type->methods);
47  memcpy(m->data, attr, bloblen);
48  m->name = blobmsg_name(m->data);
49 
50  return true;
51 }
52 
53 static struct ubus_object_type *ubus_create_obj_type(struct blob_attr *sig)
54 {
55  struct ubus_object_type *type;
56  struct blob_attr *pos;
57  size_t rem;
58 
59  type = calloc(1, sizeof(*type));
60  if (!type)
61  return NULL;
62 
63  type->refcount = 1;
64 
65  if (!ubus_alloc_id(&obj_types, &type->id, 0))
66  goto error_free;
67 
68  INIT_LIST_HEAD(&type->methods);
69 
70  blob_for_each_attr(pos, sig, rem) {
71  if (!blobmsg_check_attr(pos, true))
72  goto error_unref;
73 
74  if (!ubus_create_obj_method(type, pos))
75  goto error_unref;
76  }
77 
78  return type;
79 
80 error_unref:
82  return NULL;
83 
84 error_free:
85  free(type);
86  return NULL;
87 }
88 
89 static struct ubus_object_type *ubus_get_obj_type(uint32_t obj_id)
90 {
91  struct ubus_object_type *type;
92  struct ubus_id *id;
93 
94  id = ubus_find_id(&obj_types, obj_id);
95  if (!id)
96  return NULL;
97 
98  type = container_of(id, struct ubus_object_type, id);
99  type->refcount++;
100  return type;
101 }
102 
104 {
105  struct ubus_object *obj;
106 
107  obj = calloc(1, sizeof(*obj));
108  if (!obj)
109  return NULL;
110 
111  if (!ubus_alloc_id(&objects, &obj->id, id))
112  goto error_free;
113 
114  obj->type = type;
115  INIT_LIST_HEAD(&obj->list);
116  INIT_LIST_HEAD(&obj->events);
117  INIT_LIST_HEAD(&obj->subscribers);
118  INIT_LIST_HEAD(&obj->target_list);
119  if (type)
120  type->refcount++;
121 
122  return obj;
123 
124 error_free:
125  free(obj);
126  return NULL;
127 }
128 
129 struct ubus_object *ubusd_create_object(struct ubus_client *cl, struct blob_attr **attr)
130 {
131  struct ubus_object *obj;
132  struct ubus_object_type *type = NULL;
133 
134  if (attr[UBUS_ATTR_OBJTYPE])
135  type = ubus_get_obj_type(blob_get_u32(attr[UBUS_ATTR_OBJTYPE]));
136  else if (attr[UBUS_ATTR_SIGNATURE])
138 
140  if (type)
142 
143  if (!obj)
144  return NULL;
145 
146  if (attr[UBUS_ATTR_OBJPATH]) {
147  if (ubusd_acl_check(cl, blob_data(attr[UBUS_ATTR_OBJPATH]), NULL, UBUS_ACL_PUBLISH))
148  goto free;
149 
150  obj->path.key = strdup(blob_data(attr[UBUS_ATTR_OBJPATH]));
151  if (!obj->path.key)
152  goto free;
153 
154  if (avl_insert(&path, &obj->path) != 0) {
155  free((void *) obj->path.key);
156  obj->path.key = NULL;
157  goto free;
158  }
159  ubusd_send_obj_event(obj, true);
160  }
161 
162  obj->client = cl;
163  list_add(&obj->list, &cl->objects);
164 
165  return obj;
166 
167 free:
168  ubusd_free_object(obj);
169  return NULL;
170 }
171 
172 void ubus_subscribe(struct ubus_object *obj, struct ubus_object *target)
173 {
174  struct ubus_subscription *s;
175  bool first = list_empty(&target->subscribers);
176 
177  s = calloc(1, sizeof(*s));
178  if (!s)
179  return;
180 
181  s->subscriber = obj;
182  s->target = target;
183  list_add(&s->list, &target->subscribers);
184  list_add(&s->target_list, &obj->target_list);
185 
186  if (first)
188 }
189 
191 {
192  struct ubus_object *obj = s->target;
193 
194  list_del(&s->list);
195  list_del(&s->target_list);
196  free(s);
197 
198  if (list_empty(&obj->subscribers))
200 }
201 
203 {
204  struct ubus_subscription *s, *tmp;
205 
206  list_for_each_entry_safe(s, tmp, &obj->target_list, target_list) {
207  ubus_unsubscribe(s);
208  }
209  list_for_each_entry_safe(s, tmp, &obj->subscribers, list) {
211  }
212 
214  if (obj->path.key) {
215  ubusd_send_obj_event(obj, false);
216  avl_delete(&path, &obj->path);
217  free((void *) obj->path.key);
218  }
219  if (!list_empty(&obj->list))
220  list_del(&obj->list);
221  ubus_free_id(&objects, &obj->id);
222  if (obj->type)
224  free(obj);
225 }
226 
227 static void __constructor ubusd_obj_init(void)
228 {
231  ubus_init_string_tree(&path, false);
233  ubusd_acl_init();
235 }
struct list_head objects
Definition: ubusd.h:60
uint32_t id
Definition: ubusd_id.h:22
struct blob_attr data[]
Definition: ubusd_obj.h:35
const char * name
Definition: libubus.h:109
struct list_head list
Definition: ubusd_obj.h:33
uint32_t id
Definition: libubus.h:130
struct ubus_object_type * type
Definition: libubus.h:133
struct list_head subscribers target_list
Definition: ubusd_obj.h:49
struct ubus_client * client
Definition: ubusd_obj.h:54
const char * path
Definition: libubus.h:132
struct list_head list
Definition: ubusd_obj.h:45
struct list_head events
Definition: ubusd_obj.h:47
struct ubus_object * target
Definition: ubusd_obj.h:40
struct list_head list target_list
Definition: ubusd_obj.h:39
struct ubus_object * subscriber
Definition: ubusd_obj.h:40
void ubusd_event_init(void)
Definition: ubusd_event.c:266
void ubusd_monitor_init(void)
void ubusd_send_obj_event(struct ubus_object *obj, bool add)
Definition: ubusd_event.c:259
void ubusd_acl_init(void)
Definition: ubusd_acl.c:568
void ubusd_event_cleanup_object(struct ubus_object *obj)
Definition: ubusd_event.c:36
int ubusd_acl_check(struct ubus_client *cl, const char *obj, const char *method, enum ubusd_acl_type type)
Definition: ubusd_acl.c:90
@ UBUS_ACL_PUBLISH
Definition: ubusd_acl.h:18
void ubus_init_id_tree(struct avl_tree *tree)
Definition: ubusd_id.c:40
void ubus_init_string_tree(struct avl_tree *tree, bool dup)
Definition: ubusd_id.c:35
bool ubus_alloc_id(struct avl_tree *tree, struct ubus_id *id, uint32_t val)
Definition: ubusd_id.c:53
static void ubus_free_id(struct avl_tree *tree, struct ubus_id *id)
Definition: ubusd_id.h:29
static struct ubus_id * ubus_find_id(struct avl_tree *tree, uint32_t id)
Definition: ubusd_id.h:34
static bool ubus_create_obj_method(struct ubus_object_type *type, struct blob_attr *attr)
Definition: ubusd_obj.c:37
void ubus_unsubscribe(struct ubus_subscription *s)
Definition: ubusd_obj.c:190
static struct ubus_object_type * ubus_create_obj_type(struct blob_attr *sig)
Definition: ubusd_obj.c:53
struct ubus_object * ubusd_create_object(struct ubus_client *cl, struct blob_attr **attr)
Definition: ubusd_obj.c:129
void ubus_subscribe(struct ubus_object *obj, struct ubus_object *target)
Definition: ubusd_obj.c:172
static struct ubus_object_type * ubus_get_obj_type(uint32_t obj_id)
Definition: ubusd_obj.c:89
struct avl_tree objects
Definition: ubusd_obj.c:18
static void ubus_unref_object_type(struct ubus_object_type *type)
Definition: ubusd_obj.c:21
static void __constructor ubusd_obj_init(void)
Definition: ubusd_obj.c:227
struct avl_tree obj_types
Definition: ubusd_obj.c:17
struct avl_tree path
Definition: ubusd_obj.c:19
struct ubus_object * ubusd_create_object_internal(struct ubus_object_type *type, uint32_t id)
Definition: ubusd_obj.c:103
void ubusd_free_object(struct ubus_object *obj)
Definition: ubusd_obj.c:202
void ubus_notify_unsubscribe(struct ubus_subscription *s)
Definition: ubusd_proto.c:633
void ubus_notify_subscription(struct ubus_object *obj)
Definition: ubusd_proto.c:615
uint8_t type
Definition: ubusmsg.h:1
@ UBUS_ATTR_OBJTYPE
Definition: ubusmsg.h:88
@ UBUS_ATTR_OBJPATH
Definition: ubusmsg.h:84
@ UBUS_ATTR_SIGNATURE
Definition: ubusmsg.h:89