Add 'afb_daemon_queue_job' for bindings
[src/app-framework-binder.git] / src / afb-ditf.c
1 /*
2  * Copyright (C) 2016, 2017 "IoT.bzh"
3  * Author José Bollo <jose.bollo@iot.bzh>
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *   http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #define _GNU_SOURCE
19 #define NO_BINDING_VERBOSE_MACRO
20
21 #include <string.h>
22 #include <errno.h>
23
24 #include <json-c/json.h>
25
26 #include <afb/afb-binding.h>
27
28 #include "afb-ditf.h"
29 #include "afb-evt.h"
30 #include "afb-common.h"
31 #include "afb-hook.h"
32 #include "jobs.h"
33 #include "verbose.h"
34
35 /**********************************************
36 * normal flow
37 **********************************************/
38 static void vverbose_cb(void *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
39 {
40         char *p;
41         struct afb_ditf *ditf = closure;
42
43         if (vasprintf(&p, fmt, args) < 0)
44                 vverbose(level, file, line, function, fmt, args);
45         else {
46                 verbose(level, file, line, function, "%s {binding %s}", p, ditf->prefix);
47                 free(p);
48         }
49 }
50
51 static void old_vverbose_cb(void *closure, int level, const char *file, int line, const char *fmt, va_list args)
52 {
53         vverbose_cb(closure, level, file, line, "?", fmt, args);
54 }
55
56 static struct afb_event event_make_cb(void *closure, const char *name)
57 {
58         size_t plen, nlen;
59         char *event;
60         struct afb_ditf *ditf = closure;
61
62         /* makes the event name */
63         plen = strlen(ditf->prefix);
64         nlen = strlen(name);
65         event = alloca(nlen + plen + 2);
66         memcpy(event, ditf->prefix, plen);
67         event[plen] = '/';
68         memcpy(event + plen + 1, name, nlen + 1);
69
70         /* create the event */
71         return afb_evt_create_event(event);
72 }
73
74 static int event_broadcast_cb(void *closure, const char *name, struct json_object *object)
75 {
76         size_t plen, nlen;
77         char *event;
78         struct afb_ditf *ditf = closure;
79
80         /* makes the event name */
81         plen = strlen(ditf->prefix);
82         nlen = strlen(name);
83         event = alloca(nlen + plen + 2);
84         memcpy(event, ditf->prefix, plen);
85         event[plen] = '/';
86         memcpy(event + plen + 1, name, nlen + 1);
87
88         /* broadcast the event */
89         return afb_evt_broadcast(event, object);
90 }
91
92 static int rootdir_open_locale_cb(void *closure, const char *filename, int flags, const char *locale)
93 {
94         return afb_common_rootdir_open_locale(filename, flags, locale);
95 }
96
97 static int queue_job_cb(void *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
98 {
99         return jobs_queue(group, timeout, callback, argument);
100 }
101
102 /**********************************************
103 * hooked flow
104 **********************************************/
105 static void hooked_vverbose_cb(void *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
106 {
107         struct afb_ditf *ditf = closure;
108         vverbose_cb(closure, level, file, line, function, fmt, args);
109         afb_hook_ditf_vverbose(ditf, level, file, line, function, fmt, args);
110         vverbose_cb(closure, level, file, line, function, fmt, args);
111 }
112
113 static void hooked_old_vverbose_cb(void *closure, int level, const char *file, int line, const char *fmt, va_list args)
114 {
115         struct afb_ditf *ditf = closure;
116         old_vverbose_cb(closure, level, file, line, fmt, args);
117         afb_hook_ditf_vverbose(ditf, level, file, line, "", fmt, args);
118 }
119
120 static struct afb_event hooked_event_make_cb(void *closure, const char *name)
121 {
122         struct afb_ditf *ditf = closure;
123         struct afb_event r = event_make_cb(closure, name);
124         return afb_hook_ditf_event_make(ditf, name, r);
125 }
126
127 static int hooked_event_broadcast_cb(void *closure, const char *name, struct json_object *object)
128 {
129         int r;
130         struct afb_ditf *ditf = closure;
131         json_object_get(object);
132         afb_hook_ditf_event_broadcast_before(ditf, name, json_object_get(object));
133         r = event_broadcast_cb(closure, name, object);
134         afb_hook_ditf_event_broadcast_after(ditf, name, object, r);
135         json_object_put(object);
136         return r;
137 }
138
139 static struct sd_event *hooked_get_event_loop(void *closure)
140 {
141         struct afb_ditf *ditf = closure;
142         struct sd_event *r = afb_common_get_event_loop();
143         return afb_hook_ditf_get_event_loop(ditf, r);
144 }
145
146 static struct sd_bus *hooked_get_user_bus(void *closure)
147 {
148         struct afb_ditf *ditf = closure;
149         struct sd_bus *r = afb_common_get_user_bus();
150         return afb_hook_ditf_get_user_bus(ditf, r);
151 }
152
153 static struct sd_bus *hooked_get_system_bus(void *closure)
154 {
155         struct afb_ditf *ditf = closure;
156         struct sd_bus *r = afb_common_get_system_bus();
157         return afb_hook_ditf_get_system_bus(ditf, r);
158 }
159
160 static int hooked_rootdir_get_fd(void *closure)
161 {
162         struct afb_ditf *ditf = closure;
163         int r = afb_common_rootdir_get_fd();
164         return afb_hook_ditf_rootdir_get_fd(ditf, r);
165 }
166
167 static int hooked_rootdir_open_locale_cb(void *closure, const char *filename, int flags, const char *locale)
168 {
169         struct afb_ditf *ditf = closure;
170         int r = rootdir_open_locale_cb(closure, filename, flags, locale);
171         return afb_hook_ditf_rootdir_open_locale(ditf, filename, flags, locale, r);
172 }
173
174 static int hooked_queue_job_cb(void *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
175 {
176         struct afb_ditf *ditf = closure;
177         int r = queue_job_cb(closure, callback, argument, group, timeout);
178         return afb_hook_ditf_queue_job(ditf, callback, argument, group, timeout, r);
179 }
180
181 static const struct afb_daemon_itf daemon_itf = {
182         .vverbose = old_vverbose_cb,
183         .event_make = event_make_cb,
184         .event_broadcast = event_broadcast_cb,
185         .get_event_loop = afb_common_get_event_loop,
186         .get_user_bus = afb_common_get_user_bus,
187         .get_system_bus = afb_common_get_system_bus,
188         .rootdir_get_fd = afb_common_rootdir_get_fd,
189         .rootdir_open_locale = rootdir_open_locale_cb,
190         .queue_job = queue_job_cb
191 };
192
193 static const struct afb_daemon_itf hooked_daemon_itf = {
194         .vverbose = hooked_old_vverbose_cb,
195         .event_make = hooked_event_make_cb,
196         .event_broadcast = hooked_event_broadcast_cb,
197         .get_event_loop = hooked_get_event_loop,
198         .get_user_bus = hooked_get_user_bus,
199         .get_system_bus = hooked_get_system_bus,
200         .rootdir_get_fd = hooked_rootdir_get_fd,
201         .rootdir_open_locale = hooked_rootdir_open_locale_cb,
202         .queue_job = hooked_queue_job_cb
203 };
204
205 void afb_ditf_init(struct afb_ditf *ditf, const char *prefix)
206 {
207         ditf->interface.verbosity = verbosity;
208         ditf->interface.mode = AFB_MODE_LOCAL;
209         ditf->interface.daemon.closure = ditf;
210         afb_ditf_rename(ditf, prefix);
211 }
212
213 void afb_ditf_rename(struct afb_ditf *ditf, const char *prefix)
214 {
215         ditf->prefix = prefix;
216         afb_ditf_update_hook(ditf);
217 }
218
219 void afb_ditf_update_hook(struct afb_ditf *ditf)
220 {
221         if (afb_hook_flags_ditf(ditf->prefix))
222                 ditf->interface.daemon.itf = &hooked_daemon_itf;
223         else
224                 ditf->interface.daemon.itf = &daemon_itf;
225 }
226