2 * Copyright (C) 2016, 2017, 2018 "IoT.bzh"
3 * Author José Bollo <jose.bollo@iot.bzh>
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <json-c/json.h>
24 #define AFB_BINDING_VERSION 3
25 #include <afb/afb-binding.h>
28 #include "afb-apiset.h"
29 #include "afb-api-v3.h"
32 #include "afb-trace.h"
33 #include "afb-session.h"
35 #include "wrap-json.h"
37 #include "monitor-api.inc"
39 static struct afb_apiset *target_set;
41 int afb_monitor_init(struct afb_apiset *declare_set, struct afb_apiset *call_set)
43 target_set = call_set;
44 return -!afb_api_v3_from_binding(&_afb_binding_monitor, declare_set, call_set);
47 /******************************************************************************
48 **** Monitoring verbosity
49 ******************************************************************************/
51 static const char _debug_[] = "debug";
52 static const char _info_[] = "info";
53 static const char _notice_[] = "notice";
54 static const char _warning_[] = "warning";
55 static const char _error_[] = "error";
58 * Translate verbosity indication to an integer value.
59 * @param v the verbosity indication
60 * @return the verbosity level (0, 1, 2 or 3) or -1 in case of error
62 static int decode_verbosity(struct json_object *v)
67 if (!wrap_json_unpack(v, "i", &level)) {
68 level = level < _VERBOSITY_(Log_Level_Error) ? _VERBOSITY_(Log_Level_Error) : level > _VERBOSITY_(Log_Level_Debug) ? _VERBOSITY_(Log_Level_Debug) : level;
69 } else if (!wrap_json_unpack(v, "s", &s)) {
72 if (!strcasecmp(s, _debug_))
73 level = _VERBOSITY_(Log_Level_Debug);
76 if (!strcasecmp(s, _info_))
77 level = _VERBOSITY_(Log_Level_Info);
80 if (!strcasecmp(s, _notice_))
81 level = _VERBOSITY_(Log_Level_Notice);
84 if (!strcasecmp(s, _warning_))
85 level = _VERBOSITY_(Log_Level_Warning);
88 if (!strcasecmp(s, _error_))
89 level = _VERBOSITY_(Log_Level_Error);
97 * callback for setting verbosity on all apis
98 * @param set the apiset
99 * @param the name of the api to set
100 * @param closure the verbosity to set as an integer casted to a pointer
102 static void set_verbosity_to_all_cb(void *closure, struct afb_apiset *set, const char *name, int isalias)
105 afb_apiset_set_logmask(set, name, (int)(intptr_t)closure);
109 * set the verbosity 'level' of the api of 'name'
110 * @param name the api name or "*" for any api or NULL or "" for global verbosity
111 * @param level the verbosity level to set
113 static void set_verbosity_to(const char *name, int level)
115 int mask = verbosity_to_mask(level);
116 if (!name || !name[0])
117 verbosity_set(level);
118 else if (name[0] == '*' && !name[1])
119 afb_apiset_enum(target_set, 1, set_verbosity_to_all_cb, (void*)(intptr_t)mask);
121 afb_apiset_set_logmask(target_set, name, mask);
125 * Set verbosities accordling to specification in 'spec'
126 * @param spec specification of the verbosity to set
128 static void set_verbosity(struct json_object *spec)
131 struct json_object_iterator it, end;
133 if (json_object_is_type(spec, json_type_object)) {
134 it = json_object_iter_begin(spec);
135 end = json_object_iter_end(spec);
136 while (!json_object_iter_equal(&it, &end)) {
137 l = decode_verbosity(json_object_iter_peek_value(&it));
139 set_verbosity_to(json_object_iter_peek_name(&it), l);
140 json_object_iter_next(&it);
143 l = decode_verbosity(spec);
145 set_verbosity_to("", l);
146 set_verbosity_to("*", l);
152 * Translate verbosity level to a protocol indication.
153 * @param level the verbosity
154 * @return the encoded verbosity
156 static struct json_object *encode_verbosity(int level)
158 switch(_DEVERBOSITY_(level)) {
159 case Log_Level_Error: return json_object_new_string(_error_);
160 case Log_Level_Warning: return json_object_new_string(_warning_);
161 case Log_Level_Notice: return json_object_new_string(_notice_);
162 case Log_Level_Info: return json_object_new_string(_info_);
163 case Log_Level_Debug: return json_object_new_string(_debug_);
164 default: return json_object_new_int(level);
169 * callback for getting verbosity of all apis
170 * @param set the apiset
171 * @param the name of the api to set
172 * @param closure the json object to build
174 static void get_verbosity_of_all_cb(void *closure, struct afb_apiset *set, const char *name, int isalias)
176 struct json_object *resu = closure;
177 int m = afb_apiset_get_logmask(set, name);
179 json_object_object_add(resu, name, encode_verbosity(verbosity_from_mask(m)));
183 * get in resu the verbosity of the api of 'name'
184 * @param resu the json object to build
185 * @param name the api name or "*" for any api or NULL or "" for global verbosity
187 static void get_verbosity_of(struct json_object *resu, const char *name)
190 if (!name || !name[0])
191 json_object_object_add(resu, "", encode_verbosity(verbosity_get()));
192 else if (name[0] == '*' && !name[1])
193 afb_apiset_enum(target_set, 1, get_verbosity_of_all_cb, resu);
195 m = afb_apiset_get_logmask(target_set, name);
197 json_object_object_add(resu, name, encode_verbosity(verbosity_from_mask(m)));
202 * get verbosities accordling to specification in 'spec'
203 * @param resu the json object to build
204 * @param spec specification of the verbosity to set
206 static struct json_object *get_verbosity(struct json_object *spec)
209 struct json_object *resu;
210 struct json_object_iterator it, end;
212 resu = json_object_new_object();
213 if (json_object_is_type(spec, json_type_object)) {
214 it = json_object_iter_begin(spec);
215 end = json_object_iter_end(spec);
216 while (!json_object_iter_equal(&it, &end)) {
217 get_verbosity_of(resu, json_object_iter_peek_name(&it));
218 json_object_iter_next(&it);
220 } else if (json_object_is_type(spec, json_type_array)) {
221 n = (int)json_object_array_length(spec);
222 for (i = 0 ; i < n ; i++)
223 get_verbosity_of(resu, json_object_get_string(json_object_array_get_idx(spec, i)));
224 } else if (json_object_is_type(spec, json_type_string)) {
225 get_verbosity_of(resu, json_object_get_string(spec));
226 } else if (json_object_get_boolean(spec)) {
227 get_verbosity_of(resu, "");
228 get_verbosity_of(resu, "*");
233 /******************************************************************************
235 ******************************************************************************/
238 * get apis accordling to specification in 'spec'
239 * @param resu the json object to build
240 * @param spec specification of the verbosity to set
242 static void get_one_api(struct json_object *resu, const char *name, struct json_object *spec)
244 struct json_object *o;
246 o = afb_apiset_describe(target_set, name);
247 if (o || afb_apiset_lookup(target_set, name, 1))
248 json_object_object_add(resu, name, o);
252 * callback for getting verbosity of all apis
253 * @param set the apiset
254 * @param the name of the api to set
255 * @param closure the json object to build
257 static void get_apis_of_all_cb(void *closure, struct afb_apiset *set, const char *name, int isalias)
259 struct json_object *resu = closure;
260 get_one_api(resu, name, NULL);
264 * get apis accordling to specification in 'spec'
265 * @param resu the json object to build
266 * @param spec specification of the verbosity to set
268 static struct json_object *get_apis(struct json_object *spec)
271 struct json_object *resu;
272 struct json_object_iterator it, end;
274 resu = json_object_new_object();
275 if (json_object_is_type(spec, json_type_object)) {
276 it = json_object_iter_begin(spec);
277 end = json_object_iter_end(spec);
278 while (!json_object_iter_equal(&it, &end)) {
279 get_one_api(resu, json_object_iter_peek_name(&it), json_object_iter_peek_value(&it));
280 json_object_iter_next(&it);
282 } else if (json_object_is_type(spec, json_type_array)) {
283 n = (int)json_object_array_length(spec);
284 for (i = 0 ; i < n ; i++)
285 get_one_api(resu, json_object_get_string(json_object_array_get_idx(spec, i)), NULL);
286 } else if (json_object_is_type(spec, json_type_string)) {
287 get_one_api(resu, json_object_get_string(spec), NULL);
288 } else if (json_object_get_boolean(spec)) {
289 afb_apiset_enum(target_set, 1, get_apis_of_all_cb, resu);
294 /******************************************************************************
295 **** Implementation monitoring verbs
296 ******************************************************************************/
298 static const char _verbosity_[] = "verbosity";
299 static const char _apis_[] = "apis";
300 static const char _refresh_token_[] = "refresh-token";
302 static void f_get(afb_req_t req)
304 struct json_object *r;
305 struct json_object *apis = NULL;
306 struct json_object *verbosity = NULL;
308 wrap_json_unpack(afb_req_json(req), "{s?:o,s?:o}", _verbosity_, &verbosity, _apis_, &apis);
310 verbosity = get_verbosity(verbosity);
312 apis = get_apis(apis);
314 wrap_json_pack(&r, "{s:o*,s:o*}", _verbosity_, verbosity, _apis_, apis);
315 afb_req_success(req, r, NULL);
318 static void f_set(afb_req_t req)
320 struct json_object *verbosity = NULL;
322 wrap_json_unpack(afb_req_json(req), "{s?:o}", _verbosity_, &verbosity);
324 set_verbosity(verbosity);
326 afb_req_success(req, NULL, NULL);
329 static void *context_create(void *closure)
331 return afb_trace_create(_afb_binding_monitor.api, NULL);
334 static void context_destroy(void *pointer)
336 struct afb_trace *trace = pointer;
337 afb_trace_unref(trace);
340 static void f_trace(afb_req_t req)
343 struct json_object *add = NULL;
344 struct json_object *drop = NULL;
345 struct afb_trace *trace;
347 trace = afb_req_context(req, 0, context_create, context_destroy, NULL);
348 wrap_json_unpack(afb_req_json(req), "{s?o s?o}", "add", &add, "drop", &drop);
350 rc = afb_trace_add(req, add, trace);
355 rc = afb_trace_drop(req, drop, trace);
359 afb_req_success(req, NULL, NULL);
361 afb_apiset_update_hooks(target_set, NULL);
362 afb_evt_update_hooks();
365 static void f_session(afb_req_t req)
367 struct json_object *r = NULL;
369 struct afb_xreq *xreq = xreq_from_req_x2(req);
371 /* check right to call it */
372 if (xreq->context.super) {
373 afb_req_fail(req, "invalid", "reserved to direct clients");
377 /* renew the token if required */
378 wrap_json_unpack(afb_req_json(req), "{s?:b}", _refresh_token_, &refresh);
380 afb_context_refresh(&xreq->context);
382 /* make the result */
383 wrap_json_pack(&r, "{s:s,s:s,s:i,s:i}",
384 "uuid", afb_session_uuid(xreq->context.session),
385 "token", afb_session_token(xreq->context.session),
386 "timeout", afb_session_timeout(xreq->context.session),
387 "remain", afb_session_what_remains(xreq->context.session));
388 afb_req_success(req, r, NULL);