LCOV - code coverage report
Current view: directory - ipc/chromium/src/third_party/libevent - buffer.c (source / functions) Found Hit Coverage
Test: app.info Lines: 168 0 0.0 %
Date: 2012-06-02 Functions: 15 0 0.0 %

       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                 : 
      68                 : struct evbuffer *
      69               0 : evbuffer_new(void)
      70                 : {
      71                 :         struct evbuffer *buffer;
      72                 :         
      73               0 :         buffer = calloc(1, sizeof(struct evbuffer));
      74                 : 
      75               0 :         return (buffer);
      76                 : }
      77                 : 
      78                 : void
      79               0 : evbuffer_free(struct evbuffer *buffer)
      80                 : {
      81               0 :         if (buffer->orig_buffer != NULL)
      82               0 :                 free(buffer->orig_buffer);
      83               0 :         free(buffer);
      84               0 : }
      85                 : 
      86                 : /* 
      87                 :  * This is a destructive add.  The data from one buffer moves into
      88                 :  * the other buffer.
      89                 :  */
      90                 : 
      91                 : #define SWAP(x,y) do { \
      92                 :         (x)->buffer = (y)->buffer; \
      93                 :         (x)->orig_buffer = (y)->orig_buffer; \
      94                 :         (x)->misalign = (y)->misalign; \
      95                 :         (x)->totallen = (y)->totallen; \
      96                 :         (x)->off = (y)->off; \
      97                 : } while (0)
      98                 : 
      99                 : int
     100               0 : evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
     101                 : {
     102                 :         int res;
     103                 : 
     104                 :         /* Short cut for better performance */
     105               0 :         if (outbuf->off == 0) {
     106                 :                 struct evbuffer tmp;
     107               0 :                 size_t oldoff = inbuf->off;
     108                 : 
     109                 :                 /* Swap them directly */
     110               0 :                 SWAP(&tmp, outbuf);
     111               0 :                 SWAP(outbuf, inbuf);
     112               0 :                 SWAP(inbuf, &tmp);
     113                 : 
     114                 :                 /* 
     115                 :                  * Optimization comes with a price; we need to notify the
     116                 :                  * buffer if necessary of the changes. oldoff is the amount
     117                 :                  * of data that we transfered from inbuf to outbuf
     118                 :                  */
     119               0 :                 if (inbuf->off != oldoff && inbuf->cb != NULL)
     120               0 :                         (*inbuf->cb)(inbuf, oldoff, inbuf->off, inbuf->cbarg);
     121               0 :                 if (oldoff && outbuf->cb != NULL)
     122               0 :                         (*outbuf->cb)(outbuf, 0, oldoff, outbuf->cbarg);
     123                 :                 
     124               0 :                 return (0);
     125                 :         }
     126                 : 
     127               0 :         res = evbuffer_add(outbuf, inbuf->buffer, inbuf->off);
     128               0 :         if (res == 0) {
     129                 :                 /* We drain the input buffer on success */
     130               0 :                 evbuffer_drain(inbuf, inbuf->off);
     131                 :         }
     132                 : 
     133               0 :         return (res);
     134                 : }
     135                 : 
     136                 : int
     137               0 : evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)
     138                 : {
     139                 :         char *buffer;
     140                 :         size_t space;
     141               0 :         size_t oldoff = buf->off;
     142                 :         int sz;
     143                 :         va_list aq;
     144                 : 
     145                 :         /* make sure that at least some space is available */
     146               0 :         evbuffer_expand(buf, 64);
     147                 :         for (;;) {
     148               0 :                 size_t used = buf->misalign + buf->off;
     149               0 :                 buffer = (char *)buf->buffer + buf->off;
     150               0 :                 assert(buf->totallen >= used);
     151               0 :                 space = buf->totallen - used;
     152                 : 
     153                 : #ifndef va_copy
     154                 : #define va_copy(dst, src)       memcpy(&(dst), &(src), sizeof(va_list))
     155                 : #endif
     156               0 :                 va_copy(aq, ap);
     157                 : 
     158               0 :                 sz = evutil_vsnprintf(buffer, space, fmt, aq);
     159                 : 
     160               0 :                 va_end(aq);
     161                 : 
     162               0 :                 if (sz < 0)
     163               0 :                         return (-1);
     164               0 :                 if (sz < space) {
     165               0 :                         buf->off += sz;
     166               0 :                         if (buf->cb != NULL)
     167               0 :                                 (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
     168               0 :                         return (sz);
     169                 :                 }
     170               0 :                 if (evbuffer_expand(buf, sz + 1) == -1)
     171               0 :                         return (-1);
     172                 : 
     173               0 :         }
     174                 :         /* NOTREACHED */
     175                 : }
     176                 : 
     177                 : int
     178               0 : evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...)
     179                 : {
     180               0 :         int res = -1;
     181                 :         va_list ap;
     182                 : 
     183               0 :         va_start(ap, fmt);
     184               0 :         res = evbuffer_add_vprintf(buf, fmt, ap);
     185               0 :         va_end(ap);
     186                 : 
     187               0 :         return (res);
     188                 : }
     189                 : 
     190                 : /* Reads data from an event buffer and drains the bytes read */
     191                 : 
     192                 : int
     193               0 : evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen)
     194                 : {
     195               0 :         size_t nread = datlen;
     196               0 :         if (nread >= buf->off)
     197               0 :                 nread = buf->off;
     198                 : 
     199               0 :         memcpy(data, buf->buffer, nread);
     200               0 :         evbuffer_drain(buf, nread);
     201                 :         
     202               0 :         return (nread);
     203                 : }
     204                 : 
     205                 : /*
     206                 :  * Reads a line terminated by either '\r\n', '\n\r' or '\r' or '\n'.
     207                 :  * The returned buffer needs to be freed by the called.
     208                 :  */
     209                 : 
     210                 : char *
     211               0 : evbuffer_readline(struct evbuffer *buffer)
     212                 : {
     213               0 :         u_char *data = EVBUFFER_DATA(buffer);
     214               0 :         size_t len = EVBUFFER_LENGTH(buffer);
     215                 :         char *line;
     216                 :         unsigned int i;
     217                 : 
     218               0 :         for (i = 0; i < len; i++) {
     219               0 :                 if (data[i] == '\r' || data[i] == '\n')
     220                 :                         break;
     221                 :         }
     222                 : 
     223               0 :         if (i == len)
     224               0 :                 return (NULL);
     225                 : 
     226               0 :         if ((line = malloc(i + 1)) == NULL) {
     227               0 :                 fprintf(stderr, "%s: out of memory\n", __func__);
     228               0 :                 evbuffer_drain(buffer, i);
     229               0 :                 return (NULL);
     230                 :         }
     231                 : 
     232               0 :         memcpy(line, data, i);
     233               0 :         line[i] = '\0';
     234                 : 
     235                 :         /*
     236                 :          * Some protocols terminate a line with '\r\n', so check for
     237                 :          * that, too.
     238                 :          */
     239               0 :         if ( i < len - 1 ) {
     240               0 :                 char fch = data[i], sch = data[i+1];
     241                 : 
     242                 :                 /* Drain one more character if needed */
     243               0 :                 if ( (sch == '\r' || sch == '\n') && sch != fch )
     244               0 :                         i += 1;
     245                 :         }
     246                 : 
     247               0 :         evbuffer_drain(buffer, i + 1);
     248                 : 
     249               0 :         return (line);
     250                 : }
     251                 : 
     252                 : /* Adds data to an event buffer */
     253                 : 
     254                 : static void
     255               0 : evbuffer_align(struct evbuffer *buf)
     256                 : {
     257               0 :         memmove(buf->orig_buffer, buf->buffer, buf->off);
     258               0 :         buf->buffer = buf->orig_buffer;
     259               0 :         buf->misalign = 0;
     260               0 : }
     261                 : 
     262                 : /* Expands the available space in the event buffer to at least datlen */
     263                 : 
     264                 : int
     265               0 : evbuffer_expand(struct evbuffer *buf, size_t datlen)
     266                 : {
     267               0 :         size_t need = buf->misalign + buf->off + datlen;
     268                 : 
     269                 :         /* If we can fit all the data, then we don't have to do anything */
     270               0 :         if (buf->totallen >= need)
     271               0 :                 return (0);
     272                 : 
     273                 :         /*
     274                 :          * If the misalignment fulfills our data needs, we just force an
     275                 :          * alignment to happen.  Afterwards, we have enough space.
     276                 :          */
     277               0 :         if (buf->misalign >= datlen) {
     278               0 :                 evbuffer_align(buf);
     279                 :         } else {
     280                 :                 void *newbuf;
     281               0 :                 size_t length = buf->totallen;
     282                 : 
     283               0 :                 if (length < 256)
     284               0 :                         length = 256;
     285               0 :                 while (length < need)
     286               0 :                         length <<= 1;
     287                 : 
     288               0 :                 if (buf->orig_buffer != buf->buffer)
     289               0 :                         evbuffer_align(buf);
     290               0 :                 if ((newbuf = realloc(buf->buffer, length)) == NULL)
     291               0 :                         return (-1);
     292                 : 
     293               0 :                 buf->orig_buffer = buf->buffer = newbuf;
     294               0 :                 buf->totallen = length;
     295                 :         }
     296                 : 
     297               0 :         return (0);
     298                 : }
     299                 : 
     300                 : int
     301               0 : evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen)
     302                 : {
     303               0 :         size_t need = buf->misalign + buf->off + datlen;
     304               0 :         size_t oldoff = buf->off;
     305                 : 
     306               0 :         if (buf->totallen < need) {
     307               0 :                 if (evbuffer_expand(buf, datlen) == -1)
     308               0 :                         return (-1);
     309                 :         }
     310                 : 
     311               0 :         memcpy(buf->buffer + buf->off, data, datlen);
     312               0 :         buf->off += datlen;
     313                 : 
     314               0 :         if (datlen && buf->cb != NULL)
     315               0 :                 (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
     316                 : 
     317               0 :         return (0);
     318                 : }
     319                 : 
     320                 : void
     321               0 : evbuffer_drain(struct evbuffer *buf, size_t len)
     322                 : {
     323               0 :         size_t oldoff = buf->off;
     324                 : 
     325               0 :         if (len >= buf->off) {
     326               0 :                 buf->off = 0;
     327               0 :                 buf->buffer = buf->orig_buffer;
     328               0 :                 buf->misalign = 0;
     329               0 :                 goto done;
     330                 :         }
     331                 : 
     332               0 :         buf->buffer += len;
     333               0 :         buf->misalign += len;
     334                 : 
     335               0 :         buf->off -= len;
     336                 : 
     337                 :  done:
     338                 :         /* Tell someone about changes in this buffer */
     339               0 :         if (buf->off != oldoff && buf->cb != NULL)
     340               0 :                 (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
     341                 : 
     342               0 : }
     343                 : 
     344                 : /*
     345                 :  * Reads data from a file descriptor into a buffer.
     346                 :  */
     347                 : 
     348                 : #define EVBUFFER_MAX_READ       4096
     349                 : 
     350                 : int
     351               0 : evbuffer_read(struct evbuffer *buf, int fd, int howmuch)
     352                 : {
     353                 :         u_char *p;
     354               0 :         size_t oldoff = buf->off;
     355               0 :         int n = EVBUFFER_MAX_READ;
     356                 : 
     357                 : #if defined(FIONREAD)
     358                 : #ifdef WIN32
     359                 :         long lng = n;
     360                 :         if (ioctlsocket(fd, FIONREAD, &lng) == -1 || (n=lng) == 0) {
     361                 : #else
     362               0 :         if (ioctl(fd, FIONREAD, &n) == -1 || n == 0) {
     363                 : #endif
     364               0 :                 n = EVBUFFER_MAX_READ;
     365               0 :         } else if (n > EVBUFFER_MAX_READ && n > howmuch) {
     366                 :                 /*
     367                 :                  * It's possible that a lot of data is available for
     368                 :                  * reading.  We do not want to exhaust resources
     369                 :                  * before the reader has a chance to do something
     370                 :                  * about it.  If the reader does not tell us how much
     371                 :                  * data we should read, we artifically limit it.
     372                 :                  */
     373               0 :                 if (n > buf->totallen << 2)
     374               0 :                         n = buf->totallen << 2;
     375               0 :                 if (n < EVBUFFER_MAX_READ)
     376               0 :                         n = EVBUFFER_MAX_READ;
     377                 :         }
     378                 : #endif  
     379               0 :         if (howmuch < 0 || howmuch > n)
     380               0 :                 howmuch = n;
     381                 : 
     382                 :         /* If we don't have FIONREAD, we might waste some space here */
     383               0 :         if (evbuffer_expand(buf, howmuch) == -1)
     384               0 :                 return (-1);
     385                 : 
     386                 :         /* We can append new data at this point */
     387               0 :         p = buf->buffer + buf->off;
     388                 : 
     389                 : #ifndef WIN32
     390               0 :         n = read(fd, p, howmuch);
     391                 : #else
     392                 :         n = recv(fd, p, howmuch, 0);
     393                 : #endif
     394               0 :         if (n == -1)
     395               0 :                 return (-1);
     396               0 :         if (n == 0)
     397               0 :                 return (0);
     398                 : 
     399               0 :         buf->off += n;
     400                 : 
     401                 :         /* Tell someone about changes in this buffer */
     402               0 :         if (buf->off != oldoff && buf->cb != NULL)
     403               0 :                 (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
     404                 : 
     405               0 :         return (n);
     406                 : }
     407                 : 
     408                 : int
     409               0 : evbuffer_write(struct evbuffer *buffer, int fd)
     410                 : {
     411                 :         int n;
     412                 : 
     413                 : #ifndef WIN32
     414               0 :         n = write(fd, buffer->buffer, buffer->off);
     415                 : #else
     416                 :         n = send(fd, buffer->buffer, buffer->off, 0);
     417                 : #endif
     418               0 :         if (n == -1)
     419               0 :                 return (-1);
     420               0 :         if (n == 0)
     421               0 :                 return (0);
     422               0 :         evbuffer_drain(buffer, n);
     423                 : 
     424               0 :         return (n);
     425                 : }
     426                 : 
     427                 : u_char *
     428               0 : evbuffer_find(struct evbuffer *buffer, const u_char *what, size_t len)
     429                 : {
     430               0 :         u_char *search = buffer->buffer, *end = search + buffer->off;
     431                 :         u_char *p;
     432                 : 
     433               0 :         while (search < end &&
     434               0 :             (p = memchr(search, *what, end - search)) != NULL) {
     435               0 :                 if (p + len > end)
     436               0 :                         break;
     437               0 :                 if (memcmp(p, what, len) == 0)
     438               0 :                         return (p);
     439               0 :                 search = p + 1;
     440                 :         }
     441                 : 
     442               0 :         return (NULL);
     443                 : }
     444                 : 
     445               0 : void evbuffer_setcb(struct evbuffer *buffer,
     446                 :     void (*cb)(struct evbuffer *, size_t, size_t, void *),
     447                 :     void *cbarg)
     448                 : {
     449               0 :         buffer->cb = cb;
     450               0 :         buffer->cbarg = cbarg;
     451               0 : }

Generated by: LCOV version 1.7