Annotation of embedaddon/strongswan/src/libcharon/plugins/vici/libvici.c, revision 1.1.1.1

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: /**
                     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, 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: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>