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