ubusd_event.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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. #include <arpa/inet.h>
  14. #include "ubusd.h"
  15. static struct avl_tree patterns;
  16. static struct ubus_object *event_obj;
  17. static int event_seq = 0;
  18. static int obj_event_seq = 1;
  19. struct event_source {
  20. struct list_head list;
  21. struct ubus_object *obj;
  22. struct avl_node avl;
  23. bool partial;
  24. };
  25. static void ubusd_delete_event_source(struct event_source *evs)
  26. {
  27. list_del(&evs->list);
  28. avl_delete(&patterns, &evs->avl);
  29. free(evs);
  30. }
  31. void ubusd_event_cleanup_object(struct ubus_object *obj)
  32. {
  33. struct event_source *ev;
  34. while (!list_empty(&obj->events)) {
  35. ev = list_first_entry(&obj->events, struct event_source, list);
  36. ubusd_delete_event_source(ev);
  37. }
  38. }
  39. enum {
  40. EVREG_PATTERN,
  41. EVREG_OBJECT,
  42. EVREG_LAST,
  43. };
  44. static struct blobmsg_policy evr_policy[] = {
  45. [EVREG_PATTERN] = { .name = "pattern", .type = BLOBMSG_TYPE_STRING },
  46. [EVREG_OBJECT] = { .name = "object", .type = BLOBMSG_TYPE_INT32 },
  47. };
  48. static int ubusd_alloc_event_pattern(struct ubus_client *cl, struct blob_attr *msg)
  49. {
  50. struct event_source *ev;
  51. struct ubus_object *obj;
  52. struct blob_attr *attr[EVREG_LAST];
  53. char *pattern, *name;
  54. uint32_t id;
  55. bool partial = false;
  56. int len;
  57. blobmsg_parse(evr_policy, EVREG_LAST, attr, blob_data(msg), blob_len(msg));
  58. if (!attr[EVREG_OBJECT] || !attr[EVREG_PATTERN])
  59. return UBUS_STATUS_INVALID_ARGUMENT;
  60. id = blobmsg_get_u32(attr[EVREG_OBJECT]);
  61. if (id < UBUS_SYSTEM_OBJECT_MAX)
  62. return UBUS_STATUS_PERMISSION_DENIED;
  63. obj = ubusd_find_object(id);
  64. if (!obj)
  65. return UBUS_STATUS_NOT_FOUND;
  66. if (obj->client != cl)
  67. return UBUS_STATUS_PERMISSION_DENIED;
  68. pattern = blobmsg_data(attr[EVREG_PATTERN]);
  69. len = strlen(pattern);
  70. if (pattern[len - 1] == '*') {
  71. partial = true;
  72. pattern[len - 1] = 0;
  73. len--;
  74. }
  75. ev = calloc(1, sizeof(*ev) + len + 1);
  76. if (!ev)
  77. return UBUS_STATUS_NO_DATA;
  78. list_add(&ev->list, &obj->events);
  79. ev->obj = obj;
  80. ev->partial = partial;
  81. name = (char *) (ev + 1);
  82. strcpy(name, pattern);
  83. ev->avl.key = name;
  84. avl_insert(&patterns, &ev->avl);
  85. return 0;
  86. }
  87. typedef struct ubus_msg_buf *(*event_fill_cb)(void *priv, const char *id);
  88. static void ubusd_send_event_msg(struct ubus_msg_buf **ub, struct ubus_client *cl,
  89. struct ubus_object *obj, const char *id,
  90. event_fill_cb fill_cb, void *cb_priv)
  91. {
  92. uint32_t *objid_ptr;
  93. /* do not loop back events */
  94. if (obj->client == cl)
  95. return;
  96. /* do not send duplicate events */
  97. if (obj->event_seen == obj_event_seq)
  98. return;
  99. obj->event_seen = obj_event_seq;
  100. if (!*ub) {
  101. *ub = fill_cb(cb_priv, id);
  102. (*ub)->hdr.type = UBUS_MSG_INVOKE;
  103. (*ub)->hdr.peer = 0;
  104. }
  105. objid_ptr = blob_data(blob_data((*ub)->data));
  106. *objid_ptr = htonl(obj->id.id);
  107. (*ub)->hdr.seq = ++event_seq;
  108. ubus_msg_send(obj->client, *ub, false);
  109. }
  110. static bool strmatch_len(const char *s1, const char *s2, int *len)
  111. {
  112. for (*len = 0; s1[*len] == s2[*len]; (*len)++)
  113. if (!s1[*len])
  114. return true;
  115. return false;
  116. }
  117. static int ubusd_send_event(struct ubus_client *cl, const char *id,
  118. event_fill_cb fill_cb, void *cb_priv)
  119. {
  120. struct ubus_msg_buf *ub = NULL;
  121. struct event_source *ev;
  122. int match_len = 0;
  123. obj_event_seq++;
  124. /*
  125. * Since this tree is sorted alphabetically, we can only expect to find
  126. * matching entries as long as the number of matching characters
  127. * between the pattern string and our string is monotonically increasing.
  128. */
  129. avl_for_each_element(&patterns, ev, avl) {
  130. const char *key = ev->avl.key;
  131. int cur_match_len;
  132. bool full_match;
  133. full_match = strmatch_len(id, key, &cur_match_len);
  134. if (cur_match_len < match_len)
  135. break;
  136. match_len = cur_match_len;
  137. if (!full_match) {
  138. if (!ev->partial)
  139. continue;
  140. if (match_len != strlen(key))
  141. continue;
  142. }
  143. ubusd_send_event_msg(&ub, cl, ev->obj, id, fill_cb, cb_priv);
  144. }
  145. if (ub)
  146. ubus_msg_free(ub);
  147. return 0;
  148. }
  149. enum {
  150. EVMSG_ID,
  151. EVMSG_DATA,
  152. EVMSG_LAST,
  153. };
  154. static struct blobmsg_policy ev_policy[] = {
  155. [EVMSG_ID] = { .name = "id", .type = BLOBMSG_TYPE_STRING },
  156. [EVMSG_DATA] = { .name = "data", .type = BLOBMSG_TYPE_TABLE },
  157. };
  158. static struct ubus_msg_buf *
  159. ubusd_create_event_from_msg(void *priv, const char *id)
  160. {
  161. struct blob_attr *msg = priv;
  162. blob_buf_init(&b, 0);
  163. blob_put_int32(&b, UBUS_ATTR_OBJID, 0);
  164. blob_put_string(&b, UBUS_ATTR_METHOD, id);
  165. blob_put(&b, UBUS_ATTR_DATA, blobmsg_data(msg), blobmsg_data_len(msg));
  166. return ubus_msg_new(b.head, blob_raw_len(b.head), true);
  167. }
  168. static int ubusd_forward_event(struct ubus_client *cl, struct blob_attr *msg)
  169. {
  170. struct blob_attr *data;
  171. struct blob_attr *attr[EVMSG_LAST];
  172. const char *id;
  173. blobmsg_parse(ev_policy, EVMSG_LAST, attr, blob_data(msg), blob_len(msg));
  174. if (!attr[EVMSG_ID] || !attr[EVMSG_DATA])
  175. return UBUS_STATUS_INVALID_ARGUMENT;
  176. id = blobmsg_data(attr[EVMSG_ID]);
  177. data = attr[EVMSG_DATA];
  178. if (!strncmp(id, "ubus.", 5))
  179. return UBUS_STATUS_PERMISSION_DENIED;
  180. return ubusd_send_event(cl, id, ubusd_create_event_from_msg, data);
  181. }
  182. static int ubusd_event_recv(struct ubus_client *cl, struct ubus_msg_buf *ub, const char *method, struct blob_attr *msg)
  183. {
  184. if (!strcmp(method, "register"))
  185. return ubusd_alloc_event_pattern(cl, msg);
  186. if (!strcmp(method, "send"))
  187. return ubusd_forward_event(cl, msg);
  188. return UBUS_STATUS_INVALID_COMMAND;
  189. }
  190. static struct ubus_msg_buf *
  191. ubusd_create_object_event_msg(void *priv, const char *id)
  192. {
  193. struct ubus_object *obj = priv;
  194. void *s;
  195. blob_buf_init(&b, 0);
  196. blob_put_int32(&b, UBUS_ATTR_OBJID, 0);
  197. blob_put_string(&b, UBUS_ATTR_METHOD, id);
  198. s = blob_nest_start(&b, UBUS_ATTR_DATA);
  199. blobmsg_add_u32(&b, "id", obj->id.id);
  200. blobmsg_add_string(&b, "path", obj->path.key);
  201. blob_nest_end(&b, s);
  202. return ubus_msg_new(b.head, blob_raw_len(b.head), true);
  203. }
  204. void ubusd_send_obj_event(struct ubus_object *obj, bool add)
  205. {
  206. const char *id = add ? "ubus.object.add" : "ubus.object.remove";
  207. ubusd_send_event(NULL, id, ubusd_create_object_event_msg, obj);
  208. }
  209. void ubusd_event_init(void)
  210. {
  211. ubus_init_string_tree(&patterns, true);
  212. event_obj = ubusd_create_object_internal(NULL, UBUS_SYSTEM_OBJECT_EVENT);
  213. if (event_obj != NULL)
  214. event_obj->recv_msg = ubusd_event_recv;
  215. }