vici: Add a callback based recursive parser function
[strongswan.git] / src / libcharon / plugins / vici / libvici.c
1 /*
2 * Copyright (C) 2014 Martin Willi
3 * Copyright (C) 2014 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "libvici.h"
17 #include "vici_builder.h"
18 #include "vici_dispatcher.h"
19
20 #include <library.h>
21 #include <threading/mutex.h>
22 #include <threading/condvar.h>
23 #include <collections/hashtable.h>
24
25 #include <errno.h>
26
27 /**
28 * Event registration
29 */
30 typedef struct {
31 /** name of event */
32 char *name;
33 /** callback function */
34 vici_event_cb_t cb;
35 /** user data for callback */
36 void *user;
37 } event_t;
38
39 /**
40 * Wait state signaled by asynchronous on_read callback
41 */
42 typedef enum {
43 WAIT_IDLE = 0,
44 WAIT_SUCCESS,
45 WAIT_FAILED,
46 WAIT_READ_ERROR,
47 } wait_state_t;
48
49 /**
50 * Private vici connection contex.
51 */
52 struct vici_conn_t {
53 /** connection stream */
54 stream_t *stream;
55 /** event registrations, as char* => event_t */
56 hashtable_t *events;
57 /** connection lock */
58 mutex_t *mutex;
59 /** condvar to signal incoming response */
60 condvar_t *cond;
61 /** queued response message */
62 chunk_t queue;
63 /** asynchronous read error */
64 int error;
65 /** wait state */
66 wait_state_t wait;
67 };
68
69 /**
70 * Private vici request message.
71 */
72 struct vici_req_t {
73 /** connection context */
74 vici_conn_t *conn;
75 /** name of request message */
76 char *name;
77 /** message builder */
78 vici_builder_t *b;
79 };
80
81 /**
82 * Private vici response/event message.
83 */
84 struct vici_res_t {
85 /** response message */
86 vici_message_t *message;
87 /** allocated strings */
88 linked_list_t *strings;
89 /** item enumerator */
90 enumerator_t *enumerator;
91 /** currently enumerating type */
92 vici_type_t type;
93 /** currently enumerating name */
94 char *name;
95 /** currently enumerating value */
96 chunk_t value;
97 /** section nesting level of callback parser */
98 int level;
99 };
100
101 /**
102 * Signal wait result for waiting user thread
103 */
104 static bool wait_result(vici_conn_t *conn, wait_state_t wait)
105 {
106 conn->mutex->lock(conn->mutex);
107 conn->wait = wait;
108 conn->mutex->unlock(conn->mutex);
109 conn->cond->signal(conn->cond);
110 return FALSE;
111 }
112
113 /**
114 * Signal wait error result for waiting user thread
115 */
116 static bool read_error(vici_conn_t *conn, int err)
117 {
118 conn->error = err;
119 return wait_result(conn, WAIT_READ_ERROR);
120 }
121
122 /**
123 * Handle a command response message
124 */
125 static bool handle_response(vici_conn_t *conn, u_int16_t len)
126 {
127 chunk_t buf;
128
129 buf = chunk_alloc(len);
130 if (!conn->stream->read_all(conn->stream, buf.ptr, buf.len))
131 {
132 free(buf.ptr);
133 return read_error(conn, errno);
134 }
135 conn->queue = buf;
136 return wait_result(conn, WAIT_SUCCESS);
137 }
138
139 /**
140 * Dispatch received event message
141 */
142 static bool handle_event(vici_conn_t *conn, u_int16_t len)
143 {
144 vici_message_t *message;
145 event_t *event;
146 u_int8_t namelen;
147 char name[257], *buf;
148
149 if (len < sizeof(namelen))
150 {
151 return read_error(conn, EBADMSG);
152 }
153 if (!conn->stream->read_all(conn->stream, &namelen, sizeof(namelen)))
154 {
155 return read_error(conn, errno);
156 }
157 if (namelen > len - sizeof(namelen))
158 {
159 return read_error(conn, EBADMSG);
160 }
161 if (!conn->stream->read_all(conn->stream, name, namelen))
162 {
163 return read_error(conn, errno);
164 }
165 name[namelen] = '\0';
166 len -= sizeof(namelen) + namelen;
167 buf = malloc(len);
168 if (!conn->stream->read_all(conn->stream, buf, len))
169 {
170 free(buf);
171 return read_error(conn, errno);
172 }
173 message = vici_message_create_from_data(chunk_create(buf, len), TRUE);
174
175 conn->mutex->lock(conn->mutex);
176 event = conn->events->get(conn->events, name);
177 if (event)
178 {
179 vici_res_t res = {
180 .message = message,
181 .enumerator = message->create_enumerator(message),
182 .strings = linked_list_create(),
183 };
184
185 event->cb(event->user, name, &res);
186
187 res.enumerator->destroy(res.enumerator);
188 res.strings->destroy_function(res.strings, free);
189 }
190 conn->mutex->unlock(conn->mutex);
191
192 message->destroy(message);
193
194 return TRUE;
195 }
196
197 CALLBACK(on_read, bool,
198 vici_conn_t *conn, stream_t *stream)
199 {
200 u_int16_t len;
201 u_int8_t op;
202
203 if (!stream->read_all(stream, &len, sizeof(len)))
204 {
205 return read_error(conn, errno);
206 }
207 len = ntohs(len);
208 if (len-- < sizeof(op))
209 {
210 return read_error(conn, EBADMSG);
211 }
212 if (!stream->read_all(stream, &op, sizeof(op)))
213 {
214 return read_error(conn, errno);
215 }
216 switch (op)
217 {
218 case VICI_EVENT:
219 return handle_event(conn, len);
220 case VICI_CMD_RESPONSE:
221 return handle_response(conn, len);
222 case VICI_EVENT_CONFIRM:
223 return wait_result(conn, WAIT_SUCCESS);
224 case VICI_CMD_UNKNOWN:
225 case VICI_EVENT_UNKNOWN:
226 return wait_result(conn, WAIT_FAILED);
227 case VICI_CMD_REQUEST:
228 case VICI_EVENT_REGISTER:
229 case VICI_EVENT_UNREGISTER:
230 default:
231 return read_error(conn, EBADMSG);
232 }
233 }
234
235 vici_conn_t* vici_connect(char *uri)
236 {
237 vici_conn_t *conn;
238 stream_t *stream;
239
240 stream = lib->streams->connect(lib->streams, uri ?: VICI_DEFAULT_URI);
241 if (!stream)
242 {
243 return NULL;
244 }
245
246 INIT(conn,
247 .stream = stream,
248 .events = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1),
249 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
250 .cond = condvar_create(CONDVAR_TYPE_DEFAULT),
251 );
252
253 stream->on_read(stream, on_read, conn);
254
255 return conn;
256 }
257
258 void vici_disconnect(vici_conn_t *conn)
259 {
260 enumerator_t *enumerator;
261 event_t *event;
262
263 conn->stream->destroy(conn->stream);
264 enumerator = conn->events->create_enumerator(conn->events);
265 while (enumerator->enumerate(enumerator, NULL, &event))
266 {
267 free(event->name);
268 free(event);
269 }
270 enumerator->destroy(enumerator);
271 conn->events->destroy(conn->events);
272 conn->mutex->destroy(conn->mutex);
273 conn->cond->destroy(conn->cond);
274 free(conn);
275 }
276
277 vici_req_t* vici_begin(char *name)
278 {
279 vici_req_t *req;
280
281 INIT(req,
282 .name = strdup(name),
283 .b = vici_builder_create(),
284 );
285
286 return req;
287 }
288
289 void vici_begin_section(vici_req_t *req, char *name)
290 {
291 req->b->add(req->b, VICI_SECTION_START, name);
292 }
293
294 void vici_end_section(vici_req_t *req)
295 {
296 req->b->add(req->b, VICI_SECTION_END);
297 }
298
299 void vici_add_key_value(vici_req_t *req, char *key, void *buf, int len)
300 {
301 req->b->add(req->b, VICI_KEY_VALUE, key, chunk_create(buf, len));
302 }
303
304 void vici_add_key_valuef(vici_req_t *req, char *key, char *fmt, ...)
305 {
306 va_list args;
307
308 va_start(args, fmt);
309 req->b->vadd_kv(req->b, key, fmt, args);
310 va_end(args);
311 }
312
313 void vici_begin_list(vici_req_t *req, char *name)
314 {
315 req->b->add(req->b, VICI_LIST_START, name);
316 }
317
318 void vici_add_list_item(vici_req_t *req, void *buf, int len)
319 {
320 req->b->add(req->b, VICI_LIST_ITEM, chunk_create(buf, len));
321 }
322
323 void vici_add_list_itemf(vici_req_t *req, char *fmt, ...)
324 {
325 va_list args;
326
327 va_start(args, fmt);
328 req->b->vadd_li(req->b, fmt, args);
329 va_end(args);
330 }
331
332 void vici_end_list(vici_req_t *req)
333 {
334 req->b->add(req->b, VICI_LIST_END);
335 }
336
337 vici_res_t* vici_submit(vici_req_t *req, vici_conn_t *conn)
338 {
339 vici_message_t *message;
340 vici_res_t *res;
341 chunk_t data;
342 u_int16_t len;
343 u_int8_t namelen, op;
344
345 message = req->b->finalize(req->b);
346 if (!message)
347 {
348 errno = EINVAL;
349 return NULL;
350 }
351
352 op = VICI_CMD_REQUEST;
353 namelen = strlen(req->name);
354 data = message->get_encoding(message);
355 len = htons(sizeof(op) + sizeof(namelen) + namelen + data.len);
356
357 if (!conn->stream->write_all(conn->stream, &len, sizeof(len)) ||
358 !conn->stream->write_all(conn->stream, &op, sizeof(op)) ||
359 !conn->stream->write_all(conn->stream, &namelen, sizeof(namelen)) ||
360 !conn->stream->write_all(conn->stream, req->name, namelen) ||
361 !conn->stream->write_all(conn->stream, data.ptr, data.len))
362 {
363 free(req->name);
364 free(req);
365 message->destroy(message);
366 return NULL;
367 }
368 free(req->name);
369 free(req);
370 message->destroy(message);
371
372 message = NULL;
373 conn->mutex->lock(conn->mutex);
374 while (conn->wait == WAIT_IDLE)
375 {
376 conn->cond->wait(conn->cond, conn->mutex);
377 }
378 switch (conn->wait)
379 {
380 case WAIT_SUCCESS:
381 message = vici_message_create_from_data(conn->queue, TRUE);
382 conn->queue = chunk_empty;
383 break;
384 case WAIT_READ_ERROR:
385 errno = conn->error;
386 break;
387 case WAIT_FAILED:
388 default:
389 errno = ENOENT;
390 break;
391 }
392 conn->wait = WAIT_IDLE;
393 conn->mutex->unlock(conn->mutex);
394
395 conn->stream->on_read(conn->stream, on_read, conn);
396
397 if (message)
398 {
399 INIT(res,
400 .message = message,
401 .enumerator = message->create_enumerator(message),
402 .strings = linked_list_create(),
403 );
404 return res;
405 }
406 return NULL;
407 }
408
409 void vici_free_req(vici_req_t *req)
410 {
411 vici_message_t *message;
412
413 free(req->name);
414 message = req->b->finalize(req->b);
415 if (message)
416 {
417 message->destroy(message);
418 }
419 free(req);
420 }
421
422 int vici_dump(vici_res_t *res, char *label, FILE *out)
423 {
424 if (res->message->dump(res->message, label, out))
425 {
426 return 0;
427 }
428 errno = EBADMSG;
429 return 1;
430 }
431
432 vici_parse_t vici_parse(vici_res_t *res)
433 {
434 if (!res->enumerator->enumerate(res->enumerator,
435 &res->type, &res->name, &res->value))
436 {
437 return VICI_PARSE_ERROR;
438 }
439 switch (res->type)
440 {
441 case VICI_END:
442 return VICI_PARSE_END;
443 case VICI_SECTION_START:
444 return VICI_PARSE_BEGIN_SECTION;
445 case VICI_SECTION_END:
446 return VICI_PARSE_END_SECTION;
447 case VICI_LIST_START:
448 return VICI_PARSE_BEGIN_LIST;
449 case VICI_LIST_ITEM:
450 return VICI_PARSE_LIST_ITEM;
451 case VICI_LIST_END:
452 return VICI_PARSE_END_LIST;
453 case VICI_KEY_VALUE:
454 return VICI_PARSE_KEY_VALUE;
455 default:
456 return VICI_PARSE_ERROR;
457 }
458 }
459
460 char* vici_parse_name(vici_res_t *res)
461 {
462 char *name;
463
464 switch (res->type)
465 {
466 case VICI_SECTION_START:
467 case VICI_LIST_START:
468 case VICI_KEY_VALUE:
469 name = strdup(res->name);
470 res->strings->insert_last(res->strings, name);
471 return name;
472 default:
473 errno = EINVAL;
474 return NULL;
475 }
476 }
477
478 int vici_parse_name_eq(vici_res_t *res, char *name)
479 {
480 switch (res->type)
481 {
482 case VICI_SECTION_START:
483 case VICI_LIST_START:
484 case VICI_KEY_VALUE:
485 return streq(name, res->name) ? 1 : 0;
486 default:
487 return 0;
488 }
489 }
490
491 void* vici_parse_value(vici_res_t *res, int *len)
492 {
493 switch (res->type)
494 {
495 case VICI_LIST_ITEM:
496 case VICI_KEY_VALUE:
497 *len = res->value.len;
498 return res->value.ptr;
499 default:
500 *len = 0;
501 errno = EINVAL;
502 return NULL;
503 }
504 }
505
506 char* vici_parse_value_str(vici_res_t *res)
507 {
508 char *val;
509
510 switch (res->type)
511 {
512 case VICI_LIST_ITEM:
513 case VICI_KEY_VALUE:
514 if (!chunk_printable(res->value, NULL, 0))
515 {
516 errno = EINVAL;
517 return NULL;
518 }
519 val = strndup(res->value.ptr, res->value.len);
520 res->strings->insert_last(res->strings, val);
521 return val;
522 default:
523 errno = EINVAL;
524 return NULL;
525 }
526 }
527
528 int vici_parse_cb(vici_res_t *res, vici_parse_section_cb_t section,
529 vici_parse_value_cb_t kv, vici_parse_value_cb_t li,
530 void *user)
531 {
532 char *name, *list = NULL;
533 void *value;
534 int base, len, ret;
535
536 base = res->level;
537
538 while (TRUE)
539 {
540 switch (vici_parse(res))
541 {
542 case VICI_PARSE_KEY_VALUE:
543 if (res->level == base)
544 {
545 if (kv)
546 {
547 name = vici_parse_name(res);
548 value = vici_parse_value(res, &len);
549 if (name && value)
550 {
551 ret = kv(user, res, name, value, len);
552 if (ret)
553 {
554 return ret;
555 }
556 }
557 }
558 }
559 break;
560 case VICI_PARSE_BEGIN_SECTION:
561 if (res->level++ == base)
562 {
563 if (section)
564 {
565 name = vici_parse_name(res);
566 if (name)
567 {
568 ret = section(user, res, name);
569 if (ret)
570 {
571 return ret;
572 }
573 }
574 }
575 }
576 break;
577 case VICI_PARSE_END_SECTION:
578 if (res->level-- == base)
579 {
580 return 0;
581 }
582 break;
583 case VICI_PARSE_END:
584 res->level = 0;
585 return 0;
586 case VICI_PARSE_BEGIN_LIST:
587 if (res->level == base)
588 {
589 list = vici_parse_name(res);
590 }
591 break;
592 case VICI_PARSE_LIST_ITEM:
593 if (list && li)
594 {
595 value = vici_parse_value(res, &len);
596 if (value)
597 {
598 ret = li(user, res, list, value, len);
599 if (ret)
600 {
601 return ret;
602 }
603 }
604 }
605 break;
606 case VICI_PARSE_END_LIST:
607 if (res->level == base)
608 {
609 list = NULL;
610 }
611 break;
612 case VICI_PARSE_ERROR:
613 res->level = 0;
614 errno = EBADMSG;
615 return 1;
616 }
617 }
618 }
619
620 void* vici_find(vici_res_t *res, int *len, char *fmt, ...)
621 {
622 va_list args;
623 chunk_t value;
624
625 va_start(args, fmt);
626 value = res->message->vget_value(res->message, chunk_empty, fmt, args);
627 va_end(args);
628
629 *len = value.len;
630 return value.ptr;
631 }
632
633 char* vici_find_str(vici_res_t *res, char *def, char *fmt, ...)
634 {
635 va_list args;
636 char *str;
637
638 va_start(args, fmt);
639 str = res->message->vget_str(res->message, def, fmt, args);
640 va_end(args);
641
642 return str;
643 }
644
645 int vici_find_int(vici_res_t *res, int def, char *fmt, ...)
646 {
647 va_list args;
648 int val;
649
650 va_start(args, fmt);
651 val = res->message->vget_int(res->message, def, fmt, args);
652 va_end(args);
653
654 return val;
655 }
656
657 void vici_free_res(vici_res_t *res)
658 {
659 res->strings->destroy_function(res->strings, free);
660 res->message->destroy(res->message);
661 res->enumerator->destroy(res->enumerator);
662 free(res);
663 }
664
665 int vici_register(vici_conn_t *conn, char *name, vici_event_cb_t cb, void *user)
666 {
667 event_t *event;
668 u_int16_t len;
669 u_int8_t namelen, op;
670 int ret = 1;
671
672 op = cb ? VICI_EVENT_REGISTER : VICI_EVENT_UNREGISTER;
673 namelen = strlen(name);
674 len = htons(sizeof(op) + sizeof(namelen) + namelen);
675 if (!conn->stream->write_all(conn->stream, &len, sizeof(len)) ||
676 !conn->stream->write_all(conn->stream, &op, sizeof(op)) ||
677 !conn->stream->write_all(conn->stream, &namelen, sizeof(namelen)) ||
678 !conn->stream->write_all(conn->stream, name, namelen))
679 {
680 return 1;
681 }
682
683 conn->mutex->lock(conn->mutex);
684 while (conn->wait == WAIT_IDLE)
685 {
686 conn->cond->wait(conn->cond, conn->mutex);
687 }
688 switch (conn->wait)
689 {
690 case WAIT_SUCCESS:
691 ret = 0;
692 break;
693 case WAIT_READ_ERROR:
694 errno = conn->error;
695 break;
696 case WAIT_FAILED:
697 default:
698 errno = ENOENT;
699 break;
700 }
701 conn->wait = WAIT_IDLE;
702 conn->mutex->unlock(conn->mutex);
703
704 conn->stream->on_read(conn->stream, on_read, conn);
705
706 if (ret == 0)
707 {
708 conn->mutex->lock(conn->mutex);
709 if (cb)
710 {
711 INIT(event,
712 .name = strdup(name),
713 .cb = cb,
714 .user = user,
715 );
716 event = conn->events->put(conn->events, event->name, event);
717 }
718 else
719 {
720 event = conn->events->remove(conn->events, name);
721 }
722 conn->mutex->unlock(conn->mutex);
723
724 if (event)
725 {
726 free(event->name);
727 free(event);
728 }
729 }
730 return ret;
731 }
732
733 void vici_init()
734 {
735 library_init(NULL, "vici");
736 if (lib->processor->get_total_threads(lib->processor) < 4)
737 {
738 lib->processor->set_threads(lib->processor, 4);
739 }
740 }
741
742 void vici_deinit()
743 {
744 library_deinit();
745 }