Bindings V2: Remove explicit references to daemon/service
[src/app-framework-binder.git] / src / afb-monitor.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 AFB_BINDING_PRAGMA_NO_VERBOSE_MACRO
20
21 #include <string.h>
22
23 #include <json-c/json.h>
24 #include <afb/afb-binding-v2.h>
25
26 #include "afb-api.h"
27 #include "afb-apiset.h"
28 #include "afb-api-so-v2.h"
29 #include "afb-ditf.h"
30 #include "afb-xreq.h"
31 #include "verbose.h"
32
33 #include "monitor-api.inc"
34
35 extern struct afb_apiset *main_apiset;
36
37 static struct afb_binding_data_v2 datav2;
38
39 int afb_monitor_init()
40 {
41         return afb_api_so_v2_add_binding(&_afb_binding_v2_monitor, NULL, main_apiset, &datav2);
42 }
43
44 /******************************************************************************
45 **** Monitoring verbosity
46 ******************************************************************************/
47
48 static const char _debug_[] = "debug";
49 static const char _info_[] = "info";
50 static const char _notice_[] = "notice";
51 static const char _warning_[] = "warning";
52 static const char _error_[] = "error";
53
54 /**
55  * Translate verbosity indication to an integer value.
56  * @param v the verbosity indication
57  * @return the verbosity level (0, 1, 2 or 3) or -1 in case of error
58  */
59 static int decode_verbosity(struct json_object *v)
60 {
61         const char *s;
62         int level = -1;
63         if (json_object_is_type(v, json_type_int)) {
64                 level = json_object_get_int(v);
65                 level = level < 0 ? 0 : level > 3 ? 3 : level;
66         } else if (json_object_is_type(v, json_type_string)) {
67                 s = json_object_get_string(v);
68                 switch(*s&~' ') {
69                 case 'D':
70                         if (!strcasecmp(s, _debug_))
71                                 level = 3;
72                         break;
73                 case 'I':
74                         if (!strcasecmp(s, _info_))
75                                 level = 2;
76                         break;
77                 case 'N':
78                         if (!strcasecmp(s, _notice_))
79                                 level = 1;
80                         break;
81                 case 'W':
82                         if (!strcasecmp(s, _warning_))
83                                 level = 1;
84                         break;
85                 case 'E':
86                         if (!strcasecmp(s, _error_))
87                                 level = 0;
88                         break;
89                 }
90         }
91         return level;
92 }
93
94 /**
95  * callback for setting verbosity on all apis
96  * @param set the apiset
97  * @param the name of the api to set
98  * @param closure the verbosity to set as an integer casted to a pointer
99  */
100 static void set_verbosity_to_all_cb(struct afb_apiset *set, const char *name, void *closure)
101 {
102         afb_apiset_set_verbosity(set, name, (int)(intptr_t)closure);
103 }
104
105 /**
106  * set the verbosity 'level' of the api of 'name'
107  * @param name the api name or "*" for any api or NULL or "" for global verbosity
108  * @param level the verbosity level to set
109  */
110 static void set_verbosity_to(const char *name, int level)
111 {
112         if (!name || !name[0])
113                 verbosity = level;
114         else if (name[0] == '*' && !name[1])
115                 afb_apiset_enum(main_apiset, set_verbosity_to_all_cb, (void*)(intptr_t)level);
116         else
117                 afb_apiset_set_verbosity(main_apiset, name, level);
118 }
119
120 /**
121  * Set verbosities accordling to specification in 'spec'
122  * @param spec specification of the verbosity to set
123  */
124 static void set_verbosity(struct json_object *spec)
125 {
126         int l;
127         struct json_object_iterator it, end;
128
129         if (json_object_is_type(spec, json_type_object)) {
130                 it = json_object_iter_begin(spec);
131                 end = json_object_iter_end(spec);
132                 while (!json_object_iter_equal(&it, &end)) {
133                         l = decode_verbosity(json_object_iter_peek_value(&it));
134                         if (l >= 0)
135                                 set_verbosity_to(json_object_iter_peek_name(&it), l);
136                         json_object_iter_next(&it);
137                 }
138         } else {
139                 l = decode_verbosity(spec);
140                 if (l >= 0) {
141                         set_verbosity_to("", l);
142                         set_verbosity_to("*", l);
143                 }
144         }
145 }
146
147 /**
148  * Translate verbosity level to a protocol indication.
149  * @param level the verbosity 
150  * @return the encoded verbosity
151  */
152 static struct json_object *encode_verbosity(int level)
153 {
154         switch(level) {
155         case 0: return json_object_new_string(_error_);
156         case 1: return json_object_new_string(_notice_);
157         case 2: return json_object_new_string(_info_);
158         case 3: return json_object_new_string(_debug_);
159         default: return json_object_new_int(level);
160         }
161 }
162
163 /**
164  * callback for getting verbosity of all apis
165  * @param set the apiset
166  * @param the name of the api to set
167  * @param closure the json object to build
168  */
169 static void get_verbosity_of_all_cb(struct afb_apiset *set, const char *name, void *closure)
170 {
171         struct json_object *resu = closure;
172         int l = afb_apiset_get_verbosity(set, name);
173         if (l >= 0)
174                 json_object_object_add(resu, name, encode_verbosity(l));
175 }
176
177 /**
178  * get in resu the verbosity of the api of 'name'
179  * @param resu the json object to build
180  * @param name the api name or "*" for any api or NULL or "" for global verbosity
181  */
182 static void get_verbosity_of(struct json_object *resu, const char *name)
183 {
184         int l;
185         if (!name || !name[0])
186                 json_object_object_add(resu, "", encode_verbosity(verbosity));
187         else if (name[0] == '*' && !name[1])
188                 afb_apiset_enum(main_apiset, get_verbosity_of_all_cb, resu);
189         else {
190                 l = afb_apiset_get_verbosity(main_apiset, name);
191                 if (l >= 0)
192                         json_object_object_add(resu, name, encode_verbosity(l));
193         }
194 }
195
196 /**
197  * get verbosities accordling to specification in 'spec'
198  * @param resu the json object to build
199  * @param spec specification of the verbosity to set
200  */
201 static void get_verbosity(struct json_object *resu, struct json_object *spec)
202 {
203         int i, n;
204         struct json_object_iterator it, end;
205
206         if (json_object_is_type(spec, json_type_object)) {
207                 it = json_object_iter_begin(spec);
208                 end = json_object_iter_end(spec);
209                 while (!json_object_iter_equal(&it, &end)) {
210                         get_verbosity_of(resu, json_object_iter_peek_name(&it));
211                         json_object_iter_next(&it);
212                 }
213         } else if (json_object_is_type(spec, json_type_array)) {
214                 n = json_object_array_length(spec);
215                 for (i = 0 ; i < n ; i++)
216                         get_verbosity_of(resu, json_object_get_string(json_object_array_get_idx(spec, i)));
217         } else if (json_object_is_type(spec, json_type_string)) {
218                 get_verbosity_of(resu, json_object_get_string(spec));
219         } else if (json_object_get_boolean(spec)) {
220                 get_verbosity_of(resu, "");
221                 get_verbosity_of(resu, "*");
222         }
223 }
224
225 /******************************************************************************
226 **** Monitoring apis
227 ******************************************************************************/
228
229 /**
230  * get apis accordling to specification in 'spec'
231  * @param resu the json object to build
232  * @param spec specification of the verbosity to set
233  */
234 static void get_one_api(struct json_object *resu, const char *name, struct json_object *spec)
235 {
236         struct json_object *o;
237         struct afb_api api;
238         int rc;
239
240         rc = afb_apiset_lookup(main_apiset, name, &api);
241         if (!rc) {
242                 o = api.itf->describe ? api.itf->describe(api.closure) : NULL;
243                 json_object_object_add(resu, name, o);
244         }
245 }
246
247 /**
248  * callback for getting verbosity of all apis
249  * @param set the apiset
250  * @param the name of the api to set
251  * @param closure the json object to build
252  */
253 static void get_apis_of_all_cb(struct afb_apiset *set, const char *name, void *closure)
254 {
255         struct json_object *resu = closure;
256         get_one_api(resu, name, NULL);
257 }
258
259 /**
260  * get apis accordling to specification in 'spec'
261  * @param resu the json object to build
262  * @param spec specification of the verbosity to set
263  */
264 static void get_apis(struct json_object *resu, struct json_object *spec)
265 {
266         int i, n;
267         struct json_object_iterator it, end;
268
269         if (json_object_is_type(spec, json_type_object)) {
270                 it = json_object_iter_begin(spec);
271                 end = json_object_iter_end(spec);
272                 while (!json_object_iter_equal(&it, &end)) {
273                         get_one_api(resu, json_object_iter_peek_name(&it), json_object_iter_peek_value(&it));
274                         json_object_iter_next(&it);
275                 }
276         } else if (json_object_is_type(spec, json_type_array)) {
277                 n = json_object_array_length(spec);
278                 for (i = 0 ; i < n ; i++)
279                         get_one_api(resu, json_object_get_string(json_object_array_get_idx(spec, i)), NULL);
280         } else if (json_object_is_type(spec, json_type_string)) {
281                 get_one_api(resu, json_object_get_string(spec), NULL);
282         } else if (json_object_get_boolean(spec)) {
283                 afb_apiset_enum(main_apiset, get_apis_of_all_cb, resu);
284         }
285 }
286
287 /******************************************************************************
288 **** Implementation monitoring verbs
289 ******************************************************************************/
290
291 static const char _verbosity_[] = "verbosity";
292 static const char _apis_[] = "apis";
293
294 static void f_get(struct afb_req req)
295 {
296         struct json_object *o, *v, *r, *x;
297
298         r = json_object_new_object();
299         o = afb_req_json(req);
300
301         if (json_object_object_get_ex(o, _verbosity_, &v)) {
302                 x = json_object_new_object();
303                 json_object_object_add(r, _verbosity_, x);
304                 get_verbosity(x, v);
305         }
306
307         if (json_object_object_get_ex(o, _apis_, &v)) {
308                 x = json_object_new_object();
309                 json_object_object_add(r, _apis_, x);
310                 get_apis(x, v);
311         }
312
313         afb_req_success(req, json_object_get(r), NULL);
314         json_object_put(r);
315 }
316
317 static void f_set(struct afb_req req)
318 {
319         struct json_object *o, *v;
320
321         o = afb_req_json(req);
322         if (json_object_object_get_ex(o, _verbosity_, &v)) {
323                 set_verbosity(v);
324         }
325
326         afb_req_success(req, NULL, NULL);
327 }
328
329 #if 0
330 static void f_hook(struct afb_xreq *xreq)
331 {
332         struct json_object *o, *v;
333
334         o = afb_xreq_json(xreq);
335         if (json_object_object_get_ex(o, _verbosity_, &v)) {
336                 set_verbosity(v);
337         }
338
339         if (!xreq->replied)
340                 afb_xreq_success(xreq, NULL, NULL);
341 }
342 #endif
343