vici: Add a libvici low-level client library
[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 };
98
99 /**
100 * Signal wait result for waiting user thread
101 */
102 static bool wait_result(vici_conn_t *conn, wait_state_t wait)
103 {
104 conn->mutex->lock(conn->mutex);
105 conn->wait = wait;
106 conn->mutex->unlock(conn->mutex);
107 conn->cond->signal(conn->cond);
108 return FALSE;
109 }
110
111 /**
112 * Signal wait error result for waiting user thread
113 */
114 static bool read_error(vici_conn_t *conn, int err)
115 {
116 conn->error = err;
117 return wait_result(conn, WAIT_READ_ERROR);
118 }
119
120 /**
121 * Handle a command response message
122 */
123 static bool handle_response(vici_conn_t *conn, u_int16_t len)
124 {
125 chunk_t buf;
126
127 buf = chunk_alloc(len);
128 if (!conn->stream->read_all(conn->stream, buf.ptr, buf.len))
129 {
130 free(buf.ptr);
131 return read_error(conn, errno);
132 }
133 conn->queue = buf;
134 return wait_result(conn, WAIT_SUCCESS);
135 }
136
137 /**
138 * Dispatch received event message
139 */
140 static bool handle_event(vici_conn_t *conn, u_int16_t len)
141 {
142 vici_message_t *message;
143 event_t *event;
144 u_int8_t namelen;
145 char name[257], *buf;
146
147 if (len < sizeof(namelen))
148 {
149 return read_error(conn, EBADMSG);
150 }
151 if (!conn->stream->read_all(conn->stream, &namelen, sizeof(namelen)))
152 {
153 return read_error(conn, errno);
154 }
155 if (namelen > len - sizeof(namelen))
156 {
157 return read_error(conn, EBADMSG);
158 }
159 if (!conn->stream->read_all(conn->stream, name, namelen))
160 {
161 return read_error(conn, errno);
162 }
163 name[namelen] = '\0';
164 len -= sizeof(namelen) + namelen;
165 buf = malloc(len);
166 if (!conn->stream->read_all(conn->stream, buf, len))
167 {
168 free(buf);
169 return read_error(conn, errno);
170 }
171 message = vici_message_create_from_data(chunk_create(buf, len), TRUE);
172
173 conn->mutex->lock(conn->mutex);
174 event = conn->events->get(conn->events, name);
175 if (event)
176 {
177 vici_res_t res = {
178 .message = message,
179 .enumerator = message->create_enumerator(message),
180 .strings = linked_list_create(),
181 };
182
183 event->cb(event->user, name, &res);
184
185 res.enumerator->destroy(res.enumerator);
186 res.strings->destroy_function(res.strings, free);
187 }
188 conn->mutex->unlock(conn->mutex);
189
190 message->destroy(message);
191
192 return TRUE;
193 }
194
195 CALLBACK(on_read, bool,
196 vici_conn_t *conn, stream_t *stream)
197 {
198 u_int16_t len;
199 u_int8_t op;
200
201 if (!stream->read_all(stream, &len, sizeof(len)))
202 {
203 return read_error(conn, errno);
204 }
205 len = ntohs(len);
206 if (len-- < sizeof(op))
207 {
208 return read_error(conn, EBADMSG);
209 }
210 if (!stream->read_all(stream, &op, sizeof(op)))
211 {
212 return read_error(conn, errno);
213 }
214 switch (op)
215 {
216 case VICI_EVENT:
217 return handle_event(conn, len);
218 case VICI_CMD_RESPONSE:
219 return handle_response(conn, len);
220 case VICI_EVENT_CONFIRM:
221 return wait_result(conn, WAIT_SUCCESS);
222 case VICI_CMD_UNKNOWN:
223 case VICI_EVENT_UNKNOWN:
224 return wait_result(conn, WAIT_FAILED);
225 case VICI_CMD_REQUEST:
226 case VICI_EVENT_REGISTER:
227 case VICI_EVENT_UNREGISTER:
228 default:
229 return read_error(conn, EBADMSG);
230 }
231 }
232
233 vici_conn_t* vici_connect(char *uri)
234 {
235 vici_conn_t *conn;
236 stream_t *stream;
237
238 stream = lib->streams->connect(lib->streams, uri ?: VICI_DEFAULT_URI);
239 if (!stream)
240 {
241 return NULL;
242 }
243
244 INIT(conn,
245 .stream = stream,
246 .events = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1),
247 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
248 .cond = condvar_create(CONDVAR_TYPE_DEFAULT),
249 );
250
251 stream->on_read(stream, on_read, conn);
252
253 return conn;
254 }
255
256 void vici_disconnect(vici_conn_t *conn)
257 {
258 enumerator_t *enumerator;
259 event_t *event;
260
261 conn->stream->destroy(conn->stream);
262 enumerator = conn->events->create_enumerator(conn->events);
263 while (enumerator->enumerate(enumerator, NULL, &event))
264 {
265 free(event->name);
266 free(event);
267 }
268 enumerator->destroy(enumerator);
269 conn->events->destroy(conn->events);
270 conn->mutex->destroy(conn->mutex);
271 conn->cond->destroy(conn->cond);
272 free(conn);
273 }
274
275 vici_req_t* vici_begin(char *name)
276 {
277 vici_req_t *req;
278
279 INIT(req,
280 .name = strdup(name),
281 .b = vici_builder_create(),
282 );
283
284 return req;
285 }
286
287 void vici_begin_section(vici_req_t *req, char *name)
288 {
289 req->b->add(req->b, VICI_SECTION_START, name);
290 }
291
292 void vici_end_section(vici_req_t *req)
293 {
294 req->b->add(req->b, VICI_SECTION_END);
295 }
296
297 void vici_add_key_value(vici_req_t *req, char *key, void *buf, int len)
298 {
299 req->b->add(req->b, VICI_KEY_VALUE, key, chunk_create(buf, len));
300 }
301
302 void vici_add_key_valuef(vici_req_t *req, char *key, char *fmt, ...)
303 {
304 va_list args;
305
306 va_start(args, fmt);
307 req->b->vadd_kv(req->b, key, fmt, args);
308 va_end(args);
309 }
310
311 void vici_begin_list(vici_req_t *req, char *name)
312 {
313 req->b->add(req->b, VICI_LIST_START, name);
314 }
315
316 void vici_add_list_item(vici_req_t *req, void *buf, int len)
317 {
318 req->b->add(req->b, VICI_LIST_ITEM, chunk_create(buf, len));
319 }
320
321 void vici_add_list_itemf(vici_req_t *req, char *fmt, ...)
322 {
323 va_list args;
324
325 va_start(args, fmt);
326 req->b->vadd_li(req->b, fmt, args);
327 va_end(args);
328 }
329
330 void vici_end_list(vici_req_t *req)
331 {
332 req->b->add(req->b, VICI_LIST_END);
333 }
334
335 vici_res_t* vici_submit(vici_req_t *req, vici_conn_t *conn)
336 {
337 vici_message_t *message;
338 vici_res_t *res;
339 chunk_t data;
340 u_int16_t len;
341 u_int8_t namelen, op;
342
343 message = req->b->finalize(req->b);
344 if (!message)
345 {
346 errno = EINVAL;
347 return NULL;
348 }
349
350 op = VICI_CMD_REQUEST;
351 namelen = strlen(req->name);
352 data = message->get_encoding(message);
353 len = htons(sizeof(op) + sizeof(namelen) + namelen + data.len);
354
355 if (!conn->stream->write_all(conn->stream, &len, sizeof(len)) ||
356 !conn->stream->write_all(conn->stream, &op, sizeof(op)) ||
357 !conn->stream->write_all(conn->stream, &namelen, sizeof(namelen)) ||
358 !conn->stream->write_all(conn->stream, req->name, namelen) ||
359 !conn->stream->write_all(conn->stream, data.ptr, data.len))
360 {
361 free(req->name);
362 free(req);
363 message->destroy(message);
364 return NULL;
365 }
366 free(req->name);
367 free(req);
368 message->destroy(message);
369
370 message = NULL;
371 conn->mutex->lock(conn->mutex);
372 while (conn->wait == WAIT_IDLE)
373 {
374 conn->cond->wait(conn->cond, conn->mutex);
375 }
376 switch (conn->wait)
377 {
378 case WAIT_SUCCESS:
379 message = vici_message_create_from_data(conn->queue, TRUE);
380 conn->queue = chunk_empty;
381 break;
382 case WAIT_READ_ERROR:
383 errno = conn->error;
384 break;
385 case WAIT_FAILED:
386 default:
387 errno = ENOENT;
388 break;
389 }
390 conn->wait = WAIT_IDLE;
391 conn->mutex->unlock(conn->mutex);
392
393 conn->stream->on_read(conn->stream, on_read, conn);
394
395 if (message)
396 {
397 INIT(res,
398 .message = message,
399 .enumerator = message->create_enumerator(message),
400 .strings = linked_list_create(),
401 );
402 return res;
403 }
404 return NULL;
405 }
406
407 void vici_free_req(vici_req_t *req)
408 {
409 vici_message_t *message;
410
411 free(req->name);
412 message = req->b->finalize(req->b);
413 if (message)
414 {
415 message->destroy(message);
416 }
417 free(req);
418 }
419
420 int vici_dump(vici_res_t *res, FILE *out)
421 {
422 enumerator_t *enumerator;
423 int ident = 0, delta = 2;
424 vici_type_t type;
425 char *name;
426 chunk_t value;
427
428 enumerator = res->message->create_enumerator(res->message);
429 while (enumerator->enumerate(enumerator, &type, &name, &value))
430 {
431 switch (type)
432 {
433 case VICI_SECTION_START:
434 fprintf(out, "%*s%s {\n", ident, "", name);
435 ident += delta;
436 break;
437 case VICI_SECTION_END:
438 ident -= delta;
439 fprintf(out, "%*s}\n", ident, "");
440 break;
441 case VICI_KEY_VALUE:
442 if (chunk_printable(value, NULL, ' '))
443 {
444 fprintf(out, "%*s%s = %.*s\n",
445 ident, "", name, (int)value.len, value.ptr);
446 }
447 else
448 {
449 fprintf(out, "%*s%s = 0x%+#B\n",
450 ident, "", name, &value);
451 }
452 break;
453 case VICI_LIST_START:
454 fprintf(out, "%*s%s = [\n", ident, "", name);
455 ident += delta;
456 break;
457 case VICI_LIST_END:
458 ident -= delta;
459 fprintf(out, "%*s]\n", ident, "");
460 break;
461 case VICI_LIST_ITEM:
462 if (chunk_printable(value, NULL, ' '))
463 {
464 fprintf(out, "%*s%.*s\n",
465 ident, "", (int)value.len, value.ptr);
466 }
467 else
468 {
469 fprintf(out, "%*s 0x%+#B\n", ident, "", &value);
470 }
471 break;
472 case VICI_END:
473 enumerator->destroy(enumerator);
474 return 0;
475 }
476 }
477 enumerator->destroy(enumerator);
478 errno = EBADMSG;
479 return 1;
480 }
481
482 vici_parse_t vici_parse(vici_res_t *res)
483 {
484 if (!res->enumerator->enumerate(res->enumerator,
485 &res->type, &res->name, &res->value))
486 {
487 return VICI_PARSE_ERROR;
488 }
489 switch (res->type)
490 {
491 case VICI_END:
492 return VICI_PARSE_END;
493 case VICI_SECTION_START:
494 return VICI_PARSE_BEGIN_SECTION;
495 case VICI_SECTION_END:
496 return VICI_PARSE_END_SECTION;
497 case VICI_LIST_START:
498 return VICI_PARSE_BEGIN_LIST;
499 case VICI_LIST_ITEM:
500 return VICI_PARSE_LIST_ITEM;
501 case VICI_LIST_END:
502 return VICI_PARSE_END_LIST;
503 case VICI_KEY_VALUE:
504 return VICI_PARSE_KEY_VALUE;
505 default:
506 return VICI_PARSE_ERROR;
507 }
508 }
509
510 char* vici_parse_name(vici_res_t *res)
511 {
512 char *name;
513
514 switch (res->type)
515 {
516 case VICI_SECTION_START:
517 case VICI_LIST_START:
518 case VICI_KEY_VALUE:
519 name = strdup(res->name);
520 res->strings->insert_last(res->strings, name);
521 return name;
522 default:
523 errno = EINVAL;
524 return NULL;
525 }
526 }
527
528 int vici_parse_name_eq(vici_res_t *res, char *name)
529 {
530 switch (res->type)
531 {
532 case VICI_SECTION_START:
533 case VICI_LIST_START:
534 case VICI_KEY_VALUE:
535 return streq(name, res->name) ? 1 : 0;
536 default:
537 return 0;
538 }
539 }
540
541 void* vici_parse_value(vici_res_t *res, int *len)
542 {
543 switch (res->type)
544 {
545 case VICI_LIST_ITEM:
546 case VICI_KEY_VALUE:
547 *len = res->value.len;
548 return res->value.ptr;
549 default:
550 errno = EINVAL;
551 return NULL;
552 }
553 }
554
555 char* vici_parse_value_str(vici_res_t *res)
556 {
557 char *val;
558
559 switch (res->type)
560 {
561 case VICI_LIST_ITEM:
562 case VICI_KEY_VALUE:
563 if (!chunk_printable(res->value, NULL, 0))
564 {
565 errno = EINVAL;
566 return NULL;
567 }
568 val = strndup(res->value.ptr, res->value.len);
569 res->strings->insert_last(res->strings, val);
570 return val;
571 default:
572 errno = EINVAL;
573 return NULL;
574 }
575 }
576
577 void vici_free_res(vici_res_t *res)
578 {
579 res->strings->destroy_function(res->strings, free);
580 res->message->destroy(res->message);
581 res->enumerator->destroy(res->enumerator);
582 free(res);
583 }
584
585 int vici_register(vici_conn_t *conn, char *name, vici_event_cb_t cb, void *user)
586 {
587 event_t *event;
588 u_int16_t len;
589 u_int8_t namelen, op;
590 int ret = 1;
591
592 op = cb ? VICI_EVENT_REGISTER : VICI_EVENT_UNREGISTER;
593 namelen = strlen(name);
594 len = htons(sizeof(op) + sizeof(namelen) + namelen);
595 if (!conn->stream->write_all(conn->stream, &len, sizeof(len)) ||
596 !conn->stream->write_all(conn->stream, &op, sizeof(op)) ||
597 !conn->stream->write_all(conn->stream, &namelen, sizeof(namelen)) ||
598 !conn->stream->write_all(conn->stream, name, namelen))
599 {
600 return 1;
601 }
602
603 conn->mutex->lock(conn->mutex);
604 while (conn->wait == WAIT_IDLE)
605 {
606 conn->cond->wait(conn->cond, conn->mutex);
607 }
608 switch (conn->wait)
609 {
610 case WAIT_SUCCESS:
611 ret = 0;
612 break;
613 case WAIT_READ_ERROR:
614 errno = conn->error;
615 break;
616 case WAIT_FAILED:
617 default:
618 errno = ENOENT;
619 break;
620 }
621 conn->wait = WAIT_IDLE;
622 conn->mutex->unlock(conn->mutex);
623
624 conn->stream->on_read(conn->stream, on_read, conn);
625
626 if (ret == 0)
627 {
628 conn->mutex->lock(conn->mutex);
629 if (cb)
630 {
631 INIT(event,
632 .name = strdup(name),
633 .cb = cb,
634 .user = user,
635 );
636 event = conn->events->put(conn->events, event->name, event);
637 }
638 else
639 {
640 event = conn->events->remove(conn->events, name);
641 }
642 conn->mutex->unlock(conn->mutex);
643
644 if (event)
645 {
646 free(event->name);
647 free(event);
648 }
649 }
650 return ret;
651 }
652
653 void vici_init()
654 {
655 library_init(NULL, "vici");
656 if (lib->processor->get_total_threads(lib->processor) < 4)
657 {
658 lib->processor->set_threads(lib->processor, 4);
659 }
660 }
661
662 void vici_deinit()
663 {
664 library_deinit();
665 }