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