2 * Copyright (C) 2015, 2016 "IoT.bzh"
3 * Author "Fulup Ar Foll"
4 * Author José Bollo <jose.bollo@iot.bzh>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
26 #include <json-c/json.h>
27 #include <afb/afb-event-itf.h>
34 struct afb_evt_listener {
35 struct afb_evt_listener *next;
36 void (*send)(void *closure, const char *event, struct json_object *object);
38 struct afb_evt_watch *watchs;
42 struct afb_evt_event {
43 struct afb_evt_watch *watchs;
47 struct afb_evt_watch {
48 struct afb_evt_event *event;
49 struct afb_evt_watch *next_by_event;
50 struct afb_evt_listener *listener;
51 struct afb_evt_watch *next_by_listener;
54 static int evt_broadcast(struct afb_evt_event *evt, struct json_object *obj);
55 static int evt_push(struct afb_evt_event *evt, struct json_object *obj);
56 static void evt_drop(struct afb_evt_event *evt);
58 static struct afb_event_itf afb_evt_event_itf = {
59 .broadcast = (void*)evt_broadcast,
60 .push = (void*)evt_push,
61 .drop = (void*)evt_drop
64 static struct afb_evt_listener *listeners = NULL;
66 static inline int evt_trash(struct json_object *obj)
71 static int evt_broadcast(struct afb_evt_event *evt, struct json_object *object)
73 return afb_evt_broadcast(evt->name, object);
76 int afb_evt_broadcast(const char *event, struct json_object *object)
79 struct afb_evt_listener *listener;
84 listener->send(listener->closure, event, json_object_get(object));
85 listener = listener->next;
87 json_object_put(object);
91 static int evt_push(struct afb_evt_event *evt, struct json_object *obj)
94 struct afb_evt_watch *watch;
95 struct afb_evt_listener *listener;
100 listener = watch->listener;
101 listener->send(listener->closure, evt->name, json_object_get(obj));
102 watch = watch->next_by_event;
104 json_object_put(obj);
108 static void remove_watch(struct afb_evt_watch *watch)
110 struct afb_evt_watch **prv;
112 prv = &watch->event->watchs;
114 prv = &(*prv)->next_by_event;
115 *prv = watch->next_by_event;
117 prv = &watch->listener->watchs;
119 prv = &(*prv)->next_by_listener;
120 *prv = watch->next_by_listener;
125 static void evt_drop(struct afb_evt_event *evt)
128 while(evt->watchs != NULL)
129 remove_watch(evt->watchs);
134 struct afb_event afb_evt_create_event(const char *name)
137 struct afb_evt_event *evt;
140 evt = malloc(len + sizeof * evt);
143 memcpy(evt->name, name, len + 1);
145 return (struct afb_event){ .itf = &afb_evt_event_itf, .closure = evt };
148 struct afb_evt_listener *afb_evt_listener_create(void (*send)(void *closure, const char *event, struct json_object *object), void *closure)
150 struct afb_evt_listener *listener;
152 /* search if an instance already exists */
153 listener = listeners;
154 while (listener != NULL) {
155 if (listener->send == send && listener->closure == closure)
156 return afb_evt_listener_addref(listener);
157 listener = listener->next;
161 listener = calloc(1, sizeof *listener);
162 if (listener != NULL) {
164 listener->next = listeners;
165 listener->send = send;
166 listener->closure = closure;
167 listener->watchs = NULL;
168 listener->refcount = 1;
169 listeners = listener;
174 struct afb_evt_listener *afb_evt_listener_addref(struct afb_evt_listener *listener)
176 listener->refcount++;
180 void afb_evt_listener_unref(struct afb_evt_listener *listener)
182 if (0 == --listener->refcount) {
183 struct afb_evt_listener **prv;
185 /* remove the watchers */
186 while (listener->watchs != NULL)
187 remove_watch(listener->watchs);
189 /* unlink the listener */
191 while (*prv != listener)
193 *prv = listener->next;
195 /* free the listener */
200 int afb_evt_add_watch(struct afb_evt_listener *listener, struct afb_event event)
202 struct afb_evt_watch *watch;
203 struct afb_evt_event *evt;
205 /* check parameter */
206 if (event.itf != &afb_evt_event_itf) {
211 /* search the existing watch */
212 watch = listener->watchs;
213 while(watch != NULL) {
214 if (watch->event == event.closure)
216 watch = watch->next_by_listener;
219 /* not found, allocate a new */
220 watch = malloc(sizeof *watch);
226 /* initialise and link */
229 watch->next_by_event = evt->watchs;
230 watch->listener = listener;
231 watch->next_by_listener = listener->watchs;
233 listener->watchs = watch;
238 int afb_evt_remove_watch(struct afb_evt_listener *listener, struct afb_event event)
240 struct afb_evt_watch *watch;
242 /* check parameter */
243 if (event.itf != &afb_evt_event_itf) {
248 /* search the existing watch */
249 watch = listener->watchs;
250 while(watch != NULL) {
251 if (watch->event == event.closure) {
252 /* found: remove it */
256 watch = watch->next_by_listener;