Annotation of embedaddon/libevent/buffer.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (c) 2002, 2003 Niels Provos <provos@citi.umich.edu>
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. The name of the author may not be used to endorse or promote products
                     14:  *    derived from this software without specific prior written permission.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     19:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     20:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     21:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     22:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     23:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     24:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     25:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     26:  */
                     27: 
                     28: #ifdef HAVE_CONFIG_H
                     29: #include "config.h"
                     30: #endif
                     31: 
                     32: #ifdef WIN32
                     33: #include <winsock2.h>
                     34: #include <windows.h>
                     35: #endif
                     36: 
                     37: #ifdef HAVE_VASPRINTF
                     38: /* If we have vasprintf, we need to define this before we include stdio.h. */
                     39: #define _GNU_SOURCE
                     40: #endif
                     41: 
                     42: #include <sys/types.h>
                     43: 
                     44: #ifdef HAVE_SYS_TIME_H
                     45: #include <sys/time.h>
                     46: #endif
                     47: 
                     48: #ifdef HAVE_SYS_IOCTL_H
                     49: #include <sys/ioctl.h>
                     50: #endif
                     51: 
                     52: #include <assert.h>
                     53: #include <errno.h>
                     54: #include <stdio.h>
                     55: #include <stdlib.h>
                     56: #include <string.h>
                     57: #ifdef HAVE_STDARG_H
                     58: #include <stdarg.h>
                     59: #endif
                     60: #ifdef HAVE_UNISTD_H
                     61: #include <unistd.h>
                     62: #endif
                     63: 
                     64: #include "event.h"
                     65: #include "config.h"
                     66: #include "evutil.h"
                     67: #include "./log.h"
                     68: 
                     69: struct evbuffer *
                     70: evbuffer_new(void)
                     71: {
                     72:        struct evbuffer *buffer;
                     73:        
                     74:        buffer = calloc(1, sizeof(struct evbuffer));
                     75: 
                     76:        return (buffer);
                     77: }
                     78: 
                     79: void
                     80: evbuffer_free(struct evbuffer *buffer)
                     81: {
                     82:        if (buffer->orig_buffer != NULL)
                     83:                free(buffer->orig_buffer);
                     84:        free(buffer);
                     85: }
                     86: 
                     87: /* 
                     88:  * This is a destructive add.  The data from one buffer moves into
                     89:  * the other buffer.
                     90:  */
                     91: 
                     92: #define SWAP(x,y) do { \
                     93:        (x)->buffer = (y)->buffer; \
                     94:        (x)->orig_buffer = (y)->orig_buffer; \
                     95:        (x)->misalign = (y)->misalign; \
                     96:        (x)->totallen = (y)->totallen; \
                     97:        (x)->off = (y)->off; \
                     98: } while (0)
                     99: 
                    100: int
                    101: evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
                    102: {
                    103:        int res;
                    104: 
                    105:        /* Short cut for better performance */
                    106:        if (outbuf->off == 0) {
                    107:                struct evbuffer tmp;
                    108:                size_t oldoff = inbuf->off;
                    109: 
                    110:                /* Swap them directly */
                    111:                SWAP(&tmp, outbuf);
                    112:                SWAP(outbuf, inbuf);
                    113:                SWAP(inbuf, &tmp);
                    114: 
                    115:                /* 
                    116:                 * Optimization comes with a price; we need to notify the
                    117:                 * buffer if necessary of the changes. oldoff is the amount
                    118:                 * of data that we transfered from inbuf to outbuf
                    119:                 */
                    120:                if (inbuf->off != oldoff && inbuf->cb != NULL)
                    121:                        (*inbuf->cb)(inbuf, oldoff, inbuf->off, inbuf->cbarg);
                    122:                if (oldoff && outbuf->cb != NULL)
                    123:                        (*outbuf->cb)(outbuf, 0, oldoff, outbuf->cbarg);
                    124:                
                    125:                return (0);
                    126:        }
                    127: 
                    128:        res = evbuffer_add(outbuf, inbuf->buffer, inbuf->off);
                    129:        if (res == 0) {
                    130:                /* We drain the input buffer on success */
                    131:                evbuffer_drain(inbuf, inbuf->off);
                    132:        }
                    133: 
                    134:        return (res);
                    135: }
                    136: 
                    137: int
                    138: evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)
                    139: {
                    140:        char *buffer;
                    141:        size_t space;
                    142:        size_t oldoff = buf->off;
                    143:        int sz;
                    144:        va_list aq;
                    145: 
                    146:        /* make sure that at least some space is available */
                    147:        evbuffer_expand(buf, 64);
                    148:        for (;;) {
                    149:                size_t used = buf->misalign + buf->off;
                    150:                buffer = (char *)buf->buffer + buf->off;
                    151:                assert(buf->totallen >= used);
                    152:                space = buf->totallen - used;
                    153: 
                    154: #ifndef va_copy
                    155: #define        va_copy(dst, src)       memcpy(&(dst), &(src), sizeof(va_list))
                    156: #endif
                    157:                va_copy(aq, ap);
                    158: 
                    159:                sz = evutil_vsnprintf(buffer, space, fmt, aq);
                    160: 
                    161:                va_end(aq);
                    162: 
                    163:                if (sz < 0)
                    164:                        return (-1);
                    165:                if ((size_t)sz < space) {
                    166:                        buf->off += sz;
                    167:                        if (buf->cb != NULL)
                    168:                                (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
                    169:                        return (sz);
                    170:                }
                    171:                if (evbuffer_expand(buf, sz + 1) == -1)
                    172:                        return (-1);
                    173: 
                    174:        }
                    175:        /* NOTREACHED */
                    176: }
                    177: 
                    178: int
                    179: evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...)
                    180: {
                    181:        int res = -1;
                    182:        va_list ap;
                    183: 
                    184:        va_start(ap, fmt);
                    185:        res = evbuffer_add_vprintf(buf, fmt, ap);
                    186:        va_end(ap);
                    187: 
                    188:        return (res);
                    189: }
                    190: 
                    191: /* Reads data from an event buffer and drains the bytes read */
                    192: 
                    193: int
                    194: evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen)
                    195: {
                    196:        size_t nread = datlen;
                    197:        if (nread >= buf->off)
                    198:                nread = buf->off;
                    199: 
                    200:        memcpy(data, buf->buffer, nread);
                    201:        evbuffer_drain(buf, nread);
                    202:        
                    203:        return (nread);
                    204: }
                    205: 
                    206: /*
                    207:  * Reads a line terminated by either '\r\n', '\n\r' or '\r' or '\n'.
                    208:  * The returned buffer needs to be freed by the called.
                    209:  */
                    210: 
                    211: char *
                    212: evbuffer_readline(struct evbuffer *buffer)
                    213: {
                    214:        u_char *data = EVBUFFER_DATA(buffer);
                    215:        size_t len = EVBUFFER_LENGTH(buffer);
                    216:        char *line;
                    217:        unsigned int i;
                    218: 
                    219:        for (i = 0; i < len; i++) {
                    220:                if (data[i] == '\r' || data[i] == '\n')
                    221:                        break;
                    222:        }
                    223: 
                    224:        if (i == len)
                    225:                return (NULL);
                    226: 
                    227:        if ((line = malloc(i + 1)) == NULL) {
                    228:                fprintf(stderr, "%s: out of memory\n", __func__);
                    229:                return (NULL);
                    230:        }
                    231: 
                    232:        memcpy(line, data, i);
                    233:        line[i] = '\0';
                    234: 
                    235:        /*
                    236:         * Some protocols terminate a line with '\r\n', so check for
                    237:         * that, too.
                    238:         */
                    239:        if ( i < len - 1 ) {
                    240:                char fch = data[i], sch = data[i+1];
                    241: 
                    242:                /* Drain one more character if needed */
                    243:                if ( (sch == '\r' || sch == '\n') && sch != fch )
                    244:                        i += 1;
                    245:        }
                    246: 
                    247:        evbuffer_drain(buffer, i + 1);
                    248: 
                    249:        return (line);
                    250: }
                    251: 
                    252: 
                    253: char *
                    254: evbuffer_readln(struct evbuffer *buffer, size_t *n_read_out,
                    255:                enum evbuffer_eol_style eol_style)
                    256: {
                    257:        u_char *data = EVBUFFER_DATA(buffer);
                    258:        u_char *start_of_eol, *end_of_eol;
                    259:        size_t len = EVBUFFER_LENGTH(buffer);
                    260:        char *line;
                    261:        unsigned int i, n_to_copy, n_to_drain;
                    262: 
                    263:        if (n_read_out)
                    264:                *n_read_out = 0;
                    265: 
                    266:        /* depending on eol_style, set start_of_eol to the first character
                    267:         * in the newline, and end_of_eol to one after the last character. */
                    268:        switch (eol_style) {
                    269:        case EVBUFFER_EOL_ANY:
                    270:                for (i = 0; i < len; i++) {
                    271:                        if (data[i] == '\r' || data[i] == '\n')
                    272:                                break;
                    273:                }
                    274:                if (i == len)
                    275:                        return (NULL);
                    276:                start_of_eol = data+i;
                    277:                ++i;
                    278:                for ( ; i < len; i++) {
                    279:                        if (data[i] != '\r' && data[i] != '\n')
                    280:                                break;
                    281:                }
                    282:                end_of_eol = data+i;
                    283:                break;
                    284:        case EVBUFFER_EOL_CRLF:
                    285:                end_of_eol = memchr(data, '\n', len);
                    286:                if (!end_of_eol)
                    287:                        return (NULL);
                    288:                if (end_of_eol > data && *(end_of_eol-1) == '\r')
                    289:                        start_of_eol = end_of_eol - 1;
                    290:                else
                    291:                        start_of_eol = end_of_eol;
                    292:                end_of_eol++; /*point to one after the LF. */
                    293:                break;
                    294:        case EVBUFFER_EOL_CRLF_STRICT: {
                    295:                u_char *cp = data;
                    296:                while ((cp = memchr(cp, '\r', len-(cp-data)))) {
                    297:                        if (cp < data+len-1 && *(cp+1) == '\n')
                    298:                                break;
                    299:                        if (++cp >= data+len) {
                    300:                                cp = NULL;
                    301:                                break;
                    302:                        }
                    303:                }
                    304:                if (!cp)
                    305:                        return (NULL);
                    306:                start_of_eol = cp;
                    307:                end_of_eol = cp+2;
                    308:                break;
                    309:        }
                    310:        case EVBUFFER_EOL_LF:
                    311:                start_of_eol = memchr(data, '\n', len);
                    312:                if (!start_of_eol)
                    313:                        return (NULL);
                    314:                end_of_eol = start_of_eol + 1;
                    315:                break;
                    316:        default:
                    317:                return (NULL);
                    318:        }
                    319: 
                    320:        n_to_copy = start_of_eol - data;
                    321:        n_to_drain = end_of_eol - data;
                    322: 
                    323:        if ((line = malloc(n_to_copy+1)) == NULL) {
                    324:                event_warn("%s: out of memory\n", __func__);
                    325:                return (NULL);
                    326:        }
                    327: 
                    328:        memcpy(line, data, n_to_copy);
                    329:        line[n_to_copy] = '\0';
                    330: 
                    331:        evbuffer_drain(buffer, n_to_drain);
                    332:        if (n_read_out)
                    333:                *n_read_out = (size_t)n_to_copy;
                    334: 
                    335:        return (line);
                    336: }
                    337: 
                    338: /* Adds data to an event buffer */
                    339: 
                    340: static void
                    341: evbuffer_align(struct evbuffer *buf)
                    342: {
                    343:        memmove(buf->orig_buffer, buf->buffer, buf->off);
                    344:        buf->buffer = buf->orig_buffer;
                    345:        buf->misalign = 0;
                    346: }
                    347: 
                    348: /* Expands the available space in the event buffer to at least datlen */
                    349: 
                    350: int
                    351: evbuffer_expand(struct evbuffer *buf, size_t datlen)
                    352: {
                    353:        size_t need = buf->misalign + buf->off + datlen;
                    354: 
                    355:        /* If we can fit all the data, then we don't have to do anything */
                    356:        if (buf->totallen >= need)
                    357:                return (0);
                    358: 
                    359:        /*
                    360:         * If the misalignment fulfills our data needs, we just force an
                    361:         * alignment to happen.  Afterwards, we have enough space.
                    362:         */
                    363:        if (buf->misalign >= datlen) {
                    364:                evbuffer_align(buf);
                    365:        } else {
                    366:                void *newbuf;
                    367:                size_t length = buf->totallen;
                    368: 
                    369:                if (length < 256)
                    370:                        length = 256;
                    371:                while (length < need)
                    372:                        length <<= 1;
                    373: 
                    374:                if (buf->orig_buffer != buf->buffer)
                    375:                        evbuffer_align(buf);
                    376:                if ((newbuf = realloc(buf->buffer, length)) == NULL)
                    377:                        return (-1);
                    378: 
                    379:                buf->orig_buffer = buf->buffer = newbuf;
                    380:                buf->totallen = length;
                    381:        }
                    382: 
                    383:        return (0);
                    384: }
                    385: 
                    386: int
                    387: evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen)
                    388: {
                    389:        size_t need = buf->misalign + buf->off + datlen;
                    390:        size_t oldoff = buf->off;
                    391: 
                    392:        if (buf->totallen < need) {
                    393:                if (evbuffer_expand(buf, datlen) == -1)
                    394:                        return (-1);
                    395:        }
                    396: 
                    397:        memcpy(buf->buffer + buf->off, data, datlen);
                    398:        buf->off += datlen;
                    399: 
                    400:        if (datlen && buf->cb != NULL)
                    401:                (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
                    402: 
                    403:        return (0);
                    404: }
                    405: 
                    406: void
                    407: evbuffer_drain(struct evbuffer *buf, size_t len)
                    408: {
                    409:        size_t oldoff = buf->off;
                    410: 
                    411:        if (len >= buf->off) {
                    412:                buf->off = 0;
                    413:                buf->buffer = buf->orig_buffer;
                    414:                buf->misalign = 0;
                    415:                goto done;
                    416:        }
                    417: 
                    418:        buf->buffer += len;
                    419:        buf->misalign += len;
                    420: 
                    421:        buf->off -= len;
                    422: 
                    423:  done:
                    424:        /* Tell someone about changes in this buffer */
                    425:        if (buf->off != oldoff && buf->cb != NULL)
                    426:                (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
                    427: 
                    428: }
                    429: 
                    430: /*
                    431:  * Reads data from a file descriptor into a buffer.
                    432:  */
                    433: 
                    434: #define EVBUFFER_MAX_READ      4096
                    435: 
                    436: int
                    437: evbuffer_read(struct evbuffer *buf, int fd, int howmuch)
                    438: {
                    439:        u_char *p;
                    440:        size_t oldoff = buf->off;
                    441:        int n = EVBUFFER_MAX_READ;
                    442: 
                    443: #if defined(FIONREAD)
                    444: #ifdef WIN32
                    445:        long lng = n;
                    446:        if (ioctlsocket(fd, FIONREAD, &lng) == -1 || (n=lng) <= 0) {
                    447: #else
                    448:        if (ioctl(fd, FIONREAD, &n) == -1 || n <= 0) {
                    449: #endif
                    450:                n = EVBUFFER_MAX_READ;
                    451:        } else if (n > EVBUFFER_MAX_READ && n > howmuch) {
                    452:                /*
                    453:                 * It's possible that a lot of data is available for
                    454:                 * reading.  We do not want to exhaust resources
                    455:                 * before the reader has a chance to do something
                    456:                 * about it.  If the reader does not tell us how much
                    457:                 * data we should read, we artifically limit it.
                    458:                 */
                    459:                if ((size_t)n > buf->totallen << 2)
                    460:                        n = buf->totallen << 2;
                    461:                if (n < EVBUFFER_MAX_READ)
                    462:                        n = EVBUFFER_MAX_READ;
                    463:        }
                    464: #endif 
                    465:        if (howmuch < 0 || howmuch > n)
                    466:                howmuch = n;
                    467: 
                    468:        /* If we don't have FIONREAD, we might waste some space here */
                    469:        if (evbuffer_expand(buf, howmuch) == -1)
                    470:                return (-1);
                    471: 
                    472:        /* We can append new data at this point */
                    473:        p = buf->buffer + buf->off;
                    474: 
                    475: #ifndef WIN32
                    476:        n = read(fd, p, howmuch);
                    477: #else
                    478:        n = recv(fd, p, howmuch, 0);
                    479: #endif
                    480:        if (n == -1)
                    481:                return (-1);
                    482:        if (n == 0)
                    483:                return (0);
                    484: 
                    485:        buf->off += n;
                    486: 
                    487:        /* Tell someone about changes in this buffer */
                    488:        if (buf->off != oldoff && buf->cb != NULL)
                    489:                (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
                    490: 
                    491:        return (n);
                    492: }
                    493: 
                    494: int
                    495: evbuffer_write(struct evbuffer *buffer, int fd)
                    496: {
                    497:        int n;
                    498: 
                    499: #ifndef WIN32
                    500:        n = write(fd, buffer->buffer, buffer->off);
                    501: #else
                    502:        n = send(fd, buffer->buffer, buffer->off, 0);
                    503: #endif
                    504:        if (n == -1)
                    505:                return (-1);
                    506:        if (n == 0)
                    507:                return (0);
                    508:        evbuffer_drain(buffer, n);
                    509: 
                    510:        return (n);
                    511: }
                    512: 
                    513: u_char *
                    514: evbuffer_find(struct evbuffer *buffer, const u_char *what, size_t len)
                    515: {
                    516:        u_char *search = buffer->buffer, *end = search + buffer->off;
                    517:        u_char *p;
                    518: 
                    519:        while (search < end &&
                    520:            (p = memchr(search, *what, end - search)) != NULL) {
                    521:                if (p + len > end)
                    522:                        break;
                    523:                if (memcmp(p, what, len) == 0)
                    524:                        return (p);
                    525:                search = p + 1;
                    526:        }
                    527: 
                    528:        return (NULL);
                    529: }
                    530: 
                    531: void evbuffer_setcb(struct evbuffer *buffer,
                    532:     void (*cb)(struct evbuffer *, size_t, size_t, void *),
                    533:     void *cbarg)
                    534: {
                    535:        buffer->cb = cb;
                    536:        buffer->cbarg = cbarg;
                    537: }

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