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 int evt_broadcast(struct afb_evt_event *evt, struct json_object *object)
68 return afb_evt_broadcast(evt->name, object);
71 int afb_evt_broadcast(const char *event, struct json_object *object)
74 struct afb_evt_listener *listener;
79 listener->send(listener->closure, event, json_object_get(object));
80 listener = listener->next;
82 json_object_put(object);
86 static int evt_push(struct afb_evt_event *evt, struct json_object *obj)
89 struct afb_evt_watch *watch;
90 struct afb_evt_listener *listener;
95 listener = watch->listener;
96 listener->send(listener->closure, evt->name, json_object_get(obj));
97 watch = watch->next_by_event;
103 static void remove_watch(struct afb_evt_watch *watch)
105 struct afb_evt_watch **prv;
107 prv = &watch->event->watchs;
109 prv = &(*prv)->next_by_event;
110 *prv = watch->next_by_event;
112 prv = &watch->listener->watchs;
114 prv = &(*prv)->next_by_listener;
115 *prv = watch->next_by_listener;
120 static void evt_drop(struct afb_evt_event *evt)
123 while(evt->watchs != NULL)
124 remove_watch(evt->watchs);
129 struct afb_event afb_evt_create_event(const char *name)
132 struct afb_evt_event *evt;
135 evt = malloc(len + sizeof * evt);
138 memcpy(evt->name, name, len + 1);
140 return (struct afb_event){ .itf = &afb_evt_event_itf, .closure = evt };
143 struct afb_evt_listener *afb_evt_listener_create(void (*send)(void *closure, const char *event, struct json_object *object), void *closure)
145 struct afb_evt_listener *listener;
147 /* search if an instance already exists */
148 listener = listeners;
149 while (listener != NULL) {
150 if (listener->send == send && listener->closure == closure)
151 return afb_evt_listener_addref(listener);
152 listener = listener->next;
156 listener = calloc(1, sizeof *listener);
157 if (listener != NULL) {
159 listener->next = listeners;
160 listener->send = send;
161 listener->closure = closure;
162 listener->watchs = NULL;
163 listener->refcount = 1;
164 listeners = listener;
169 struct afb_evt_listener *afb_evt_listener_addref(struct afb_evt_listener *listener)
171 listener->refcount++;
175 void afb_evt_listener_unref(struct afb_evt_listener *listener)
177 if (0 == --listener->refcount) {
178 struct afb_evt_listener **prv;
180 /* remove the watchers */
181 while (listener->watchs != NULL)
182 remove_watch(listener->watchs);
184 /* unlink the listener */
186 while (*prv != listener)
188 *prv = listener->next;
190 /* free the listener */
195 int afb_evt_add_watch(struct afb_evt_listener *listener, struct afb_event event)
197 struct afb_evt_watch *watch;
198 struct afb_evt_event *evt;
200 /* check parameter */
201 if (event.itf != &afb_evt_event_itf) {
206 /* search the existing watch */
207 watch = listener->watchs;
208 while(watch != NULL) {
209 if (watch->event == event.closure)
211 watch = watch->next_by_listener;
214 /* not found, allocate a new */
215 watch = malloc(sizeof *watch);
221 /* initialise and link */
224 watch->next_by_event = evt->watchs;
225 watch->listener = listener;
226 watch->next_by_listener = listener->watchs;
228 listener->watchs = watch;
233 int afb_evt_remove_watch(struct afb_evt_listener *listener, struct afb_event event)
235 struct afb_evt_watch *watch;
237 /* check parameter */
238 if (event.itf != &afb_evt_event_itf) {
243 /* search the existing watch */
244 watch = listener->watchs;
245 while(watch != NULL) {
246 if (watch->event == event.closure) {
247 /* found: remove it */
251 watch = watch->next_by_listener;