4 static struct avl_tree patterns
;
5 static LIST_HEAD(catch_all
);
6 static struct ubus_object
*event_obj
;
7 static int event_seq
= 0;
8 static int obj_event_seq
= 0;
16 struct list_head list
;
17 struct ubus_object
*obj
;
25 struct list_head list
;
30 static void ubusd_delete_event_source(struct event_source
*evs
)
35 avl_delete(&patterns
, &evs
->pattern
.avl
);
38 list_del(&evs
->catchall
.list
);
44 void ubusd_event_cleanup_object(struct ubus_object
*obj
)
46 struct event_source
*ev
;
48 while (!list_empty(&obj
->events
)) {
49 ev
= list_first_entry(&obj
->events
, struct event_source
, list
);
50 ubusd_delete_event_source(ev
);
60 static struct blobmsg_policy evr_policy
[] = {
61 [EVREG_PATTERN
] = { .name
= "pattern", .type
= BLOBMSG_TYPE_STRING
},
62 [EVREG_OBJECT
] = { .name
= "object", .type
= BLOBMSG_TYPE_INT32
},
66 static struct event_source
*ubusd_alloc_event_source(struct ubus_object
*obj
, enum evs_type type
, int datalen
)
68 struct event_source
*evs
;
70 evs
= calloc(1, sizeof(*evs
) + datalen
);
71 list_add(&evs
->list
, &obj
->events
);
77 static int ubusd_alloc_catchall(struct ubus_object
*obj
)
79 struct event_source
*evs
;
81 evs
= ubusd_alloc_event_source(obj
, EVS_CATCHALL
, 0);
82 list_add(&evs
->catchall
.list
, &catch_all
);
87 static int ubusd_alloc_event_pattern(struct ubus_client
*cl
, struct blob_attr
*msg
)
89 struct event_source
*ev
;
90 struct ubus_object
*obj
;
91 struct blob_attr
*attr
[EVREG_LAST
];
97 blobmsg_parse(evr_policy
, EVREG_LAST
, attr
, blob_data(msg
), blob_len(msg
));
98 if (!attr
[EVREG_OBJECT
])
99 return UBUS_STATUS_INVALID_ARGUMENT
;
101 id
= blobmsg_get_u32(attr
[EVREG_OBJECT
]);
102 if (id
< UBUS_SYSTEM_OBJECT_MAX
)
103 return UBUS_STATUS_PERMISSION_DENIED
;
105 obj
= ubusd_find_object(id
);
107 return UBUS_STATUS_NOT_FOUND
;
109 if (obj
->client
!= cl
)
110 return UBUS_STATUS_PERMISSION_DENIED
;
112 if (!attr
[EVREG_PATTERN
])
113 return ubusd_alloc_catchall(obj
);
115 pattern
= blobmsg_data(attr
[EVREG_PATTERN
]);
117 len
= strlen(pattern
);
118 if (pattern
[len
- 1] == '*') {
120 pattern
[len
- 1] = 0;
124 ev
= ubusd_alloc_event_source(obj
, EVS_PATTERN
, len
+ 1);
125 ev
->pattern
.partial
= partial
;
126 ev
->pattern
.avl
.key
= (void *) (ev
+ 1);
127 strcpy(ev
->pattern
.avl
.key
, pattern
);
128 avl_insert(&patterns
, &ev
->pattern
.avl
);
133 static void ubusd_send_event_msg(struct ubus_msg_buf
**ub
, struct ubus_client
*cl
,
134 struct ubus_object
*obj
, const char *id
,
135 struct blob_attr
*msg
)
139 /* do not loop back events */
140 if (obj
->client
== cl
)
143 /* do not send duplicate events */
144 if (obj
->event_seen
== obj_event_seq
)
147 obj
->event_seen
= obj_event_seq
;
150 objid_ptr
= blob_data(blob_data((*ub
)->data
));
151 *objid_ptr
= htonl(obj
->id
.id
);
153 blob_buf_init(&b
, 0);
154 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
.id
);
155 blob_put_string(&b
, UBUS_ATTR_METHOD
, id
);
156 blob_put(&b
, UBUS_ATTR_DATA
, blobmsg_data(msg
), blobmsg_data_len(msg
));
158 *ub
= ubus_msg_new(b
.head
, blob_raw_len(b
.head
), true);
160 (*ub
)->hdr
.type
= UBUS_MSG_INVOKE
;
163 (*ub
)->hdr
.seq
= ++event_seq
;
164 ubus_msg_send(obj
->client
, *ub
, false);
167 bool strmatch_len(const char *s1
, const char *s2
, int *len
)
169 for (*len
= 0; s1
[*len
] == s2
[*len
]; (*len
)++)
176 static int ubusd_send_event(struct ubus_client
*cl
, const char *id
,
177 struct blob_attr
*data
, struct ubus_msg_buf
*ub
)
179 struct event_source
*ev
;
182 list_for_each_entry(ev
, &catch_all
, catchall
.list
)
183 ubusd_send_event_msg(&ub
, cl
, ev
->obj
, id
, data
);
188 * Since this tree is sorted alphabetically, we can only expect to find
189 * matching entries as long as the number of matching characters
190 * between the pattern string and our string is monotonically increasing.
192 avl_for_each_element(&patterns
, ev
, pattern
.avl
) {
193 const char *key
= ev
->pattern
.avl
.key
;
197 full_match
= strmatch_len(id
, key
, &cur_match_len
);
198 if (cur_match_len
< match_len
)
201 match_len
= cur_match_len
;
204 if (!ev
->pattern
.partial
)
207 if (match_len
!= strlen(key
))
211 ubusd_send_event_msg(&ub
, cl
, ev
->obj
, id
, data
);
226 static struct blobmsg_policy ev_policy
[] = {
227 [EVMSG_ID
] = { .name
= "id", .type
= BLOBMSG_TYPE_STRING
},
228 [EVMSG_DATA
] = { .name
= "data", .type
= BLOBMSG_TYPE_TABLE
},
231 static int ubusd_forward_event(struct ubus_client
*cl
, struct blob_attr
*msg
)
233 struct blob_attr
*data
;
234 struct blob_attr
*attr
[EVMSG_LAST
];
237 blobmsg_parse(ev_policy
, EVMSG_LAST
, attr
, blob_data(msg
), blob_len(msg
));
238 if (!attr
[EVMSG_ID
] || !attr
[EVMSG_DATA
])
239 return UBUS_STATUS_INVALID_ARGUMENT
;
241 id
= blobmsg_data(attr
[EVMSG_ID
]);
242 data
= attr
[EVMSG_DATA
];
244 if (!strncmp(id
, "ubus.", 5))
245 return UBUS_STATUS_PERMISSION_DENIED
;
247 return ubusd_send_event(cl
, id
, data
, NULL
);
250 static int ubusd_event_recv(struct ubus_client
*cl
, const char *method
, struct blob_attr
*msg
)
252 if (!strcmp(method
, "register"))
253 return ubusd_alloc_event_pattern(cl
, msg
);
255 if (!strcmp(method
, "send"))
256 return ubusd_forward_event(cl
, msg
);
258 return UBUS_STATUS_INVALID_COMMAND
;
261 void ubusd_event_init(void)
263 ubus_init_string_tree(&patterns
, true);
264 event_obj
= ubusd_create_object_internal(NULL
, UBUS_SYSTEM_OBJECT_EVENT
);
265 event_obj
->recv_msg
= ubusd_event_recv
;