3 static struct avl_tree patterns
;
4 static LIST_HEAD(catch_all
);
5 static struct ubus_object
*event_obj
;
6 static int event_seq
= 0;
14 struct list_head list
;
15 struct ubus_object
*obj
;
22 struct list_head list
;
27 static void ubusd_delete_event_source(struct event_source
*evs
)
32 avl_delete(&patterns
, &evs
->pattern
.avl
);
35 list_del(&evs
->catchall
.list
);
41 void ubusd_event_cleanup_object(struct ubus_object
*obj
)
43 struct event_source
*ev
;
45 while (!list_empty(&obj
->events
)) {
46 ev
= list_first_entry(&obj
->events
, struct event_source
, list
);
47 ubusd_delete_event_source(ev
);
57 static struct blobmsg_policy evr_policy
[] = {
58 [EVREG_PATTERN
] = { .name
= "pattern", .type
= BLOBMSG_TYPE_STRING
},
59 [EVREG_OBJECT
] = { .name
= "object", .type
= BLOBMSG_TYPE_INT32
},
63 static struct event_source
*ubusd_alloc_event_source(struct ubus_object
*obj
, enum evs_type type
, int datalen
)
65 struct event_source
*evs
;
67 evs
= calloc(1, sizeof(*evs
) + datalen
);
68 list_add(&evs
->list
, &obj
->events
);
74 static int ubusd_alloc_catchall(struct ubus_object
*obj
)
76 struct event_source
*evs
;
78 evs
= ubusd_alloc_event_source(obj
, EVS_CATCHALL
, 0);
79 list_add(&evs
->catchall
.list
, &catch_all
);
84 static int ubusd_alloc_event_pattern(struct ubus_client
*cl
, struct blob_attr
*msg
)
86 struct event_source
*ev
;
87 struct ubus_object
*obj
;
88 struct blob_attr
*attr
[EVREG_LAST
];
92 blobmsg_parse(evr_policy
, EVREG_LAST
, attr
, blob_data(msg
), blob_len(msg
));
93 if (!attr
[EVREG_OBJECT
])
94 return UBUS_STATUS_INVALID_ARGUMENT
;
96 id
= blobmsg_get_u32(attr
[EVREG_OBJECT
]);
97 if (id
< UBUS_SYSTEM_OBJECT_MAX
)
98 return UBUS_STATUS_PERMISSION_DENIED
;
100 obj
= ubusd_find_object(id
);
102 return UBUS_STATUS_NOT_FOUND
;
104 if (obj
->client
!= cl
)
105 return UBUS_STATUS_PERMISSION_DENIED
;
107 if (!attr
[EVREG_PATTERN
])
108 return ubusd_alloc_catchall(obj
);
110 pattern
= blobmsg_data(attr
[EVREG_PATTERN
]);
111 ev
= ubusd_alloc_event_source(obj
, EVS_PATTERN
, strlen(pattern
) + 1);
112 ev
->pattern
.avl
.key
= (void *) (ev
+ 1);
113 strcpy(ev
->pattern
.avl
.key
, pattern
);
114 avl_insert(&patterns
, &ev
->pattern
.avl
);
125 static struct blobmsg_policy ev_policy
[] = {
126 [EVMSG_ID
] = { .name
= "id", .type
= BLOBMSG_TYPE_STRING
},
127 [EVMSG_DATA
] = { .name
= "data", .type
= BLOBMSG_TYPE_TABLE
},
130 static void ubusd_send_event_msg(struct ubus_msg_buf
**ub
, struct ubus_object
*obj
,
131 const char *id
, struct blob_attr
*msg
)
136 objid_ptr
= blob_data(blob_data((*ub
)->data
));
137 *objid_ptr
= htonl(obj
->id
.id
);
139 blob_buf_init(&b
, 0);
140 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
.id
);
141 blob_put_string(&b
, UBUS_ATTR_METHOD
, id
);
142 blob_put(&b
, UBUS_ATTR_DATA
, blobmsg_data(msg
), blobmsg_data_len(msg
));
144 *ub
= ubus_msg_new(b
.head
, blob_raw_len(b
.head
), true);
146 (*ub
)->hdr
.type
= UBUS_MSG_INVOKE
;
149 (*ub
)->hdr
.seq
= ++event_seq
;
150 ubus_msg_send(obj
->client
, *ub
, false);
153 static int ubusd_send_event(struct ubus_client
*cl
, struct blob_attr
*msg
)
155 struct ubus_msg_buf
*ub
= NULL
;
156 struct event_source
*ev
;
157 struct blob_attr
*attr
[EVMSG_LAST
];
160 blobmsg_parse(ev_policy
, EVMSG_LAST
, attr
, blob_data(msg
), blob_len(msg
));
161 if (!attr
[EVMSG_ID
] || !attr
[EVMSG_DATA
])
162 return UBUS_STATUS_INVALID_ARGUMENT
;
164 id
= blobmsg_data(attr
[EVMSG_ID
]);
165 list_for_each_entry(ev
, &catch_all
, catchall
.list
) {
166 /* do not loop back events */
167 if (ev
->obj
->client
== cl
)
170 ubusd_send_event_msg(&ub
, ev
->obj
, id
, attr
[EVMSG_DATA
]);
179 static int ubusd_event_recv(struct ubus_client
*cl
, const char *method
, struct blob_attr
*msg
)
181 if (!strcmp(method
, "register"))
182 return ubusd_alloc_event_pattern(cl
, msg
);
184 if (!strcmp(method
, "send"))
185 return ubusd_send_event(cl
, msg
);
187 return UBUS_STATUS_INVALID_COMMAND
;
190 void ubusd_event_init(void)
192 ubus_init_string_tree(&patterns
, true);
193 event_obj
= ubusd_create_object_internal(NULL
, UBUS_SYSTEM_OBJECT_EVENT
);
194 event_obj
->recv_msg
= ubusd_event_recv
;