Return to libvici.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / vici |
1.1 misho 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: /**
1.1.1.2 ! misho 51: * Private vici connection context.
1.1 misho 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, uint32_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, uint32_t len)
144: {
145: vici_message_t *message;
146: event_t *event;
147: uint8_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: uint32_t len;
202: uint8_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: uint32_t len;
362: uint8_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: free(req->name);
431: req->b->destroy(req->b);
432: free(req);
433: }
434:
435: int vici_dump(vici_res_t *res, char *label, int pretty, FILE *out)
436: {
437: if (res->message->dump(res->message, label, pretty, out))
438: {
439: return 0;
440: }
441: errno = EBADMSG;
442: return 1;
443: }
444:
445: vici_parse_t vici_parse(vici_res_t *res)
446: {
447: if (!res->enumerator->enumerate(res->enumerator,
448: &res->type, &res->name, &res->value))
449: {
450: return VICI_PARSE_ERROR;
451: }
452: switch (res->type)
453: {
454: case VICI_END:
455: return VICI_PARSE_END;
456: case VICI_SECTION_START:
457: return VICI_PARSE_BEGIN_SECTION;
458: case VICI_SECTION_END:
459: return VICI_PARSE_END_SECTION;
460: case VICI_LIST_START:
461: return VICI_PARSE_BEGIN_LIST;
462: case VICI_LIST_ITEM:
463: return VICI_PARSE_LIST_ITEM;
464: case VICI_LIST_END:
465: return VICI_PARSE_END_LIST;
466: case VICI_KEY_VALUE:
467: return VICI_PARSE_KEY_VALUE;
468: default:
469: return VICI_PARSE_ERROR;
470: }
471: }
472:
473: char* vici_parse_name(vici_res_t *res)
474: {
475: char *name;
476:
477: switch (res->type)
478: {
479: case VICI_SECTION_START:
480: case VICI_LIST_START:
481: case VICI_KEY_VALUE:
482: name = strdup(res->name);
483: res->strings->insert_last(res->strings, name);
484: return name;
485: default:
486: errno = EINVAL;
487: return NULL;
488: }
489: }
490:
491: int vici_parse_name_eq(vici_res_t *res, char *name)
492: {
493: switch (res->type)
494: {
495: case VICI_SECTION_START:
496: case VICI_LIST_START:
497: case VICI_KEY_VALUE:
498: return streq(name, res->name) ? 1 : 0;
499: default:
500: return 0;
501: }
502: }
503:
504: void* vici_parse_value(vici_res_t *res, int *len)
505: {
506: switch (res->type)
507: {
508: case VICI_LIST_ITEM:
509: case VICI_KEY_VALUE:
510: *len = res->value.len;
511: return res->value.ptr;
512: default:
513: *len = 0;
514: errno = EINVAL;
515: return NULL;
516: }
517: }
518:
519: char* vici_parse_value_str(vici_res_t *res)
520: {
521: char *val;
522:
523: switch (res->type)
524: {
525: case VICI_LIST_ITEM:
526: case VICI_KEY_VALUE:
527: if (!chunk_printable(res->value, NULL, 0))
528: {
529: errno = EBADMSG;
530: return NULL;
531: }
532: val = strndup(res->value.ptr, res->value.len);
533: res->strings->insert_last(res->strings, val);
534: return val;
535: default:
536: errno = EINVAL;
537: return NULL;
538: }
539: }
540:
541: int vici_parse_cb(vici_res_t *res, vici_parse_section_cb_t section,
542: vici_parse_value_cb_t kv, vici_parse_value_cb_t li,
543: void *user)
544: {
545: char *name, *list = NULL;
546: void *value;
547: int base, len, ret;
548:
549: base = res->level;
550:
551: while (TRUE)
552: {
553: switch (vici_parse(res))
554: {
555: case VICI_PARSE_KEY_VALUE:
556: if (res->level == base)
557: {
558: if (kv)
559: {
560: name = vici_parse_name(res);
561: value = vici_parse_value(res, &len);
562: if (name && value)
563: {
564: ret = kv(user, res, name, value, len);
565: if (ret)
566: {
567: return ret;
568: }
569: }
570: }
571: }
572: break;
573: case VICI_PARSE_BEGIN_SECTION:
574: if (res->level++ == base)
575: {
576: if (section)
577: {
578: name = vici_parse_name(res);
579: if (name)
580: {
581: ret = section(user, res, name);
582: if (ret)
583: {
584: return ret;
585: }
586: }
587: }
588: }
589: break;
590: case VICI_PARSE_END_SECTION:
591: if (res->level-- == base)
592: {
593: return 0;
594: }
595: break;
596: case VICI_PARSE_END:
597: res->level = 0;
598: return 0;
599: case VICI_PARSE_BEGIN_LIST:
600: if (res->level == base)
601: {
602: list = vici_parse_name(res);
603: }
604: break;
605: case VICI_PARSE_LIST_ITEM:
606: if (list && li)
607: {
608: value = vici_parse_value(res, &len);
609: if (value)
610: {
611: ret = li(user, res, list, value, len);
612: if (ret)
613: {
614: return ret;
615: }
616: }
617: }
618: break;
619: case VICI_PARSE_END_LIST:
620: if (res->level == base)
621: {
622: list = NULL;
623: }
624: break;
625: case VICI_PARSE_ERROR:
626: res->level = 0;
627: errno = EBADMSG;
628: return 1;
629: }
630: }
631: }
632:
633: void* vici_find(vici_res_t *res, int *len, char *fmt, ...)
634: {
635: va_list args;
636: chunk_t value;
637:
638: va_start(args, fmt);
639: value = res->message->vget_value(res->message, chunk_empty, fmt, args);
640: va_end(args);
641:
642: *len = value.len;
643: return value.ptr;
644: }
645:
646: char* vici_find_str(vici_res_t *res, char *def, char *fmt, ...)
647: {
648: va_list args;
649: char *str;
650:
651: va_start(args, fmt);
652: str = res->message->vget_str(res->message, def, fmt, args);
653: va_end(args);
654:
655: return str;
656: }
657:
658: int vici_find_int(vici_res_t *res, int def, char *fmt, ...)
659: {
660: va_list args;
661: int val;
662:
663: va_start(args, fmt);
664: val = res->message->vget_int(res->message, def, fmt, args);
665: va_end(args);
666:
667: return val;
668: }
669:
670: void vici_free_res(vici_res_t *res)
671: {
672: res->strings->destroy_function(res->strings, free);
673: res->message->destroy(res->message);
674: res->enumerator->destroy(res->enumerator);
675: free(res);
676: }
677:
678: int vici_register(vici_conn_t *conn, char *name, vici_event_cb_t cb, void *user)
679: {
680: event_t *event;
681: uint32_t len;
682: uint8_t namelen, op;
683: int ret = 1;
684:
685: op = cb ? VICI_EVENT_REGISTER : VICI_EVENT_UNREGISTER;
686: namelen = strlen(name);
687: len = htonl(sizeof(op) + sizeof(namelen) + namelen);
688: if (!conn->stream->write_all(conn->stream, &len, sizeof(len)) ||
689: !conn->stream->write_all(conn->stream, &op, sizeof(op)) ||
690: !conn->stream->write_all(conn->stream, &namelen, sizeof(namelen)) ||
691: !conn->stream->write_all(conn->stream, name, namelen))
692: {
693: return 1;
694: }
695:
696: conn->mutex->lock(conn->mutex);
697: while (conn->wait == WAIT_IDLE)
698: {
699: conn->cond->wait(conn->cond, conn->mutex);
700: }
701: switch (conn->wait)
702: {
703: case WAIT_SUCCESS:
704: ret = 0;
705: break;
706: case WAIT_READ_ERROR:
707: errno = conn->error;
708: break;
709: case WAIT_FAILURE:
710: default:
711: errno = ENOENT;
712: break;
713: }
714: conn->wait = WAIT_IDLE;
715: conn->mutex->unlock(conn->mutex);
716:
717: conn->stream->on_read(conn->stream, on_read, conn);
718:
719: if (ret == 0)
720: {
721: conn->mutex->lock(conn->mutex);
722: if (cb)
723: {
724: INIT(event,
725: .name = strdup(name),
726: .cb = cb,
727: .user = user,
728: );
729: event = conn->events->put(conn->events, event->name, event);
730: }
731: else
732: {
733: event = conn->events->remove(conn->events, name);
734: }
735: conn->mutex->unlock(conn->mutex);
736:
737: if (event)
738: {
739: free(event->name);
740: free(event);
741: }
742: }
743: return ret;
744: }
745:
746: void vici_init()
747: {
748: library_init(NULL, "vici");
749: if (lib->processor->get_total_threads(lib->processor) < 4)
750: {
751: dbg_default_set_level(0);
752: lib->processor->set_threads(lib->processor, 4);
753: dbg_default_set_level(1);
754: }
755: }
756:
757: void vici_deinit()
758: {
759: lib->processor->cancel(lib->processor);
760: library_deinit();
761: }