2 * Copyright (C) 2016, 2017 "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 0
25 #include <afb/afb-binding.h>
28 #include "afb-apiset.h"
29 #include "afb-api-so-v2.h"
32 #include "afb-trace.h"
33 #include "afb-session.h"
35 #include "wrap-json.h"
37 #include "monitor-api.inc"
39 extern struct afb_apiset *main_apiset;
41 static struct afb_binding_data_v2 datav2;
43 int afb_monitor_init()
45 return afb_api_so_v2_add_binding(&_afb_binding_v2_monitor, NULL, main_apiset, &datav2);
48 /******************************************************************************
49 **** Monitoring verbosity
50 ******************************************************************************/
52 static const char _debug_[] = "debug";
53 static const char _info_[] = "info";
54 static const char _notice_[] = "notice";
55 static const char _warning_[] = "warning";
56 static const char _error_[] = "error";
59 * Translate verbosity indication to an integer value.
60 * @param v the verbosity indication
61 * @return the verbosity level (0, 1, 2 or 3) or -1 in case of error
63 static int decode_verbosity(struct json_object *v)
68 if (!wrap_json_unpack(v, "i", &level)) {
69 level = level < Verbosity_Level_Error ? Verbosity_Level_Error : level > Verbosity_Level_Debug ? Verbosity_Level_Debug : level;
70 } else if (!wrap_json_unpack(v, "s", &s)) {
73 if (!strcasecmp(s, _debug_))
74 level = Verbosity_Level_Debug;
77 if (!strcasecmp(s, _info_))
78 level = Verbosity_Level_Info;
81 if (!strcasecmp(s, _notice_))
82 level = Verbosity_Level_Notice;
85 if (!strcasecmp(s, _warning_))
86 level = Verbosity_Level_Warning;
89 if (!strcasecmp(s, _error_))
90 level = Verbosity_Level_Error;
98 * callback for setting verbosity on all apis
99 * @param set the apiset
100 * @param the name of the api to set
101 * @param closure the verbosity to set as an integer casted to a pointer
103 static void set_verbosity_to_all_cb(struct afb_apiset *set, const char *name, void *closure)
105 afb_apiset_set_verbosity(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 if (!name || !name[0])
117 else if (name[0] == '*' && !name[1])
118 afb_apiset_enum(main_apiset, 1, set_verbosity_to_all_cb, (void*)(intptr_t)level);
120 afb_apiset_set_verbosity(main_apiset, name, level);
124 * Set verbosities accordling to specification in 'spec'
125 * @param spec specification of the verbosity to set
127 static void set_verbosity(struct json_object *spec)
130 struct json_object_iterator it, end;
132 if (json_object_is_type(spec, json_type_object)) {
133 it = json_object_iter_begin(spec);
134 end = json_object_iter_end(spec);
135 while (!json_object_iter_equal(&it, &end)) {
136 l = decode_verbosity(json_object_iter_peek_value(&it));
138 set_verbosity_to(json_object_iter_peek_name(&it), l);
139 json_object_iter_next(&it);
142 l = decode_verbosity(spec);
144 set_verbosity_to("", l);
145 set_verbosity_to("*", l);
151 * Translate verbosity level to a protocol indication.
152 * @param level the verbosity
153 * @return the encoded verbosity
155 static struct json_object *encode_verbosity(int level)
158 case Verbosity_Level_Error: return json_object_new_string(_error_);
159 case Verbosity_Level_Warning: return json_object_new_string(_warning_);
160 case Verbosity_Level_Notice: return json_object_new_string(_notice_);
161 case Verbosity_Level_Info: return json_object_new_string(_info_);
162 case Verbosity_Level_Debug: return json_object_new_string(_debug_);
163 default: return json_object_new_int(level);
168 * callback for getting verbosity of all apis
169 * @param set the apiset
170 * @param the name of the api to set
171 * @param closure the json object to build
173 static void get_verbosity_of_all_cb(struct afb_apiset *set, const char *name, void *closure)
175 struct json_object *resu = closure;
176 int l = afb_apiset_get_verbosity(set, name);
178 json_object_object_add(resu, name, encode_verbosity(l));
182 * get in resu the verbosity of the api of 'name'
183 * @param resu the json object to build
184 * @param name the api name or "*" for any api or NULL or "" for global verbosity
186 static void get_verbosity_of(struct json_object *resu, const char *name)
189 if (!name || !name[0])
190 json_object_object_add(resu, "", encode_verbosity(verbosity));
191 else if (name[0] == '*' && !name[1])
192 afb_apiset_enum(main_apiset, 1, get_verbosity_of_all_cb, resu);
194 l = afb_apiset_get_verbosity(main_apiset, name);
196 json_object_object_add(resu, name, encode_verbosity(l));
201 * get verbosities accordling to specification in 'spec'
202 * @param resu the json object to build
203 * @param spec specification of the verbosity to set
205 static struct json_object *get_verbosity(struct json_object *spec)
208 struct json_object *resu;
209 struct json_object_iterator it, end;
211 resu = json_object_new_object();
212 if (json_object_is_type(spec, json_type_object)) {
213 it = json_object_iter_begin(spec);
214 end = json_object_iter_end(spec);
215 while (!json_object_iter_equal(&it, &end)) {
216 get_verbosity_of(resu, json_object_iter_peek_name(&it));
217 json_object_iter_next(&it);
219 } else if (json_object_is_type(spec, json_type_array)) {
220 n = json_object_array_length(spec);
221 for (i = 0 ; i < n ; i++)
222 get_verbosity_of(resu, json_object_get_string(json_object_array_get_idx(spec, i)));
223 } else if (json_object_is_type(spec, json_type_string)) {
224 get_verbosity_of(resu, json_object_get_string(spec));
225 } else if (json_object_get_boolean(spec)) {
226 get_verbosity_of(resu, "");
227 get_verbosity_of(resu, "*");
232 /******************************************************************************
234 ******************************************************************************/
237 * get apis accordling to specification in 'spec'
238 * @param resu the json object to build
239 * @param spec specification of the verbosity to set
241 static void get_one_api(struct json_object *resu, const char *name, struct json_object *spec)
243 struct json_object *o;
245 o = afb_apiset_describe(main_apiset, name);
246 if (o || afb_apiset_lookup(main_apiset, name, 1))
247 json_object_object_add(resu, name, o);
251 * callback for getting verbosity of all apis
252 * @param set the apiset
253 * @param the name of the api to set
254 * @param closure the json object to build
256 static void get_apis_of_all_cb(struct afb_apiset *set, const char *name, void *closure)
258 struct json_object *resu = closure;
259 get_one_api(resu, name, NULL);
263 * get apis accordling to specification in 'spec'
264 * @param resu the json object to build
265 * @param spec specification of the verbosity to set
267 static struct json_object *get_apis(struct json_object *spec)
270 struct json_object *resu;
271 struct json_object_iterator it, end;
273 resu = json_object_new_object();
274 if (json_object_is_type(spec, json_type_object)) {
275 it = json_object_iter_begin(spec);
276 end = json_object_iter_end(spec);
277 while (!json_object_iter_equal(&it, &end)) {
278 get_one_api(resu, json_object_iter_peek_name(&it), json_object_iter_peek_value(&it));
279 json_object_iter_next(&it);
281 } else if (json_object_is_type(spec, json_type_array)) {
282 n = json_object_array_length(spec);
283 for (i = 0 ; i < n ; i++)
284 get_one_api(resu, json_object_get_string(json_object_array_get_idx(spec, i)), NULL);
285 } else if (json_object_is_type(spec, json_type_string)) {
286 get_one_api(resu, json_object_get_string(spec), NULL);
287 } else if (json_object_get_boolean(spec)) {
288 afb_apiset_enum(main_apiset, 1, get_apis_of_all_cb, resu);
293 /******************************************************************************
294 **** Implementation monitoring verbs
295 ******************************************************************************/
297 static const char _verbosity_[] = "verbosity";
298 static const char _apis_[] = "apis";
299 static const char _refresh_token_[] = "refresh-token";
301 static void f_get(struct afb_req req)
303 struct json_object *r;
304 struct json_object *apis = NULL;
305 struct json_object *verbosity = NULL;
307 wrap_json_unpack(afb_req_json(req), "{s?:o,s?:o}", _verbosity_, &verbosity, _apis_, &apis);
309 verbosity = get_verbosity(verbosity);
311 apis = get_apis(apis);
313 wrap_json_pack(&r, "{s:o*,s:o*}", _verbosity_, verbosity, _apis_, apis);
314 afb_req_success(req, r, NULL);
317 static void f_set(struct afb_req req)
319 struct json_object *verbosity = NULL;
321 wrap_json_unpack(afb_req_json(req), "{s?:o}", _verbosity_, &verbosity);
323 set_verbosity(verbosity);
325 afb_req_success(req, NULL, NULL);
328 static void *context_create()
330 return afb_trace_create(_afb_binding_v2_monitor.api, NULL);
333 static void context_destroy(void *pointer)
335 struct afb_trace *trace = pointer;
336 afb_trace_unref(trace);
339 static void f_trace(struct afb_req req)
342 struct json_object *add = NULL;
343 struct json_object *drop = NULL;
344 struct afb_trace *trace;
346 trace = afb_req_context(req, context_create, context_destroy);
347 wrap_json_unpack(afb_req_json(req), "{s?o s?o}", "add", &add, "drop", &drop);
349 rc = afb_trace_add(req, add, trace);
354 rc = afb_trace_drop(req, drop, trace);
358 afb_req_success(req, NULL, NULL);
360 afb_apiset_update_hooks(main_apiset, NULL);
361 afb_evt_update_hooks();
364 static void f_session(struct afb_req req)
366 struct json_object *r = NULL;
368 struct afb_xreq *xreq = xreq_from_request(req.closure);
370 /* check right to call it */
371 if (xreq->context.super) {
372 afb_req_fail(req, "invalid", "reserved to direct clients");
376 /* renew the token if required */
377 wrap_json_unpack(afb_req_json(req), "{s?:b}", _refresh_token_, &refresh);
379 afb_context_refresh(&xreq->context);
381 /* make the result */
382 wrap_json_pack(&r, "{s:s,s:s,s:i,s:i}",
383 "uuid", afb_session_uuid(xreq->context.session),
384 "token", afb_session_token(xreq->context.session),
385 "timeout", afb_session_timeout(xreq->context.session),
386 "remain", afb_session_what_remains(xreq->context.session));
387 afb_req_success(req, r, NULL);