| OLD | NEW |
| (Empty) |
| 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 if (evbuffer_expand(buf, 64) < 0) | |
| 148 return (-1); | |
| 149 for (;;) { | |
| 150 size_t used = buf->misalign + buf->off; | |
| 151 buffer = (char *)buf->buffer + buf->off; | |
| 152 assert(buf->totallen >= used); | |
| 153 space = buf->totallen - used; | |
| 154 | |
| 155 #ifndef va_copy | |
| 156 #define va_copy(dst, src) memcpy(&(dst), &(src), sizeof(va_list)) | |
| 157 #endif | |
| 158 va_copy(aq, ap); | |
| 159 | |
| 160 sz = evutil_vsnprintf(buffer, space, fmt, aq); | |
| 161 | |
| 162 va_end(aq); | |
| 163 | |
| 164 if (sz < 0) | |
| 165 return (-1); | |
| 166 if ((size_t)sz < space) { | |
| 167 buf->off += sz; | |
| 168 if (buf->cb != NULL) | |
| 169 (*buf->cb)(buf, oldoff, buf->off, buf->cbarg); | |
| 170 return (sz); | |
| 171 } | |
| 172 if (evbuffer_expand(buf, sz + 1) == -1) | |
| 173 return (-1); | |
| 174 | |
| 175 } | |
| 176 /* NOTREACHED */ | |
| 177 } | |
| 178 | |
| 179 int | |
| 180 evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...) | |
| 181 { | |
| 182 int res = -1; | |
| 183 va_list ap; | |
| 184 | |
| 185 va_start(ap, fmt); | |
| 186 res = evbuffer_add_vprintf(buf, fmt, ap); | |
| 187 va_end(ap); | |
| 188 | |
| 189 return (res); | |
| 190 } | |
| 191 | |
| 192 /* Reads data from an event buffer and drains the bytes read */ | |
| 193 | |
| 194 int | |
| 195 evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen) | |
| 196 { | |
| 197 size_t nread = datlen; | |
| 198 if (nread >= buf->off) | |
| 199 nread = buf->off; | |
| 200 | |
| 201 memcpy(data, buf->buffer, nread); | |
| 202 evbuffer_drain(buf, nread); | |
| 203 | |
| 204 return (nread); | |
| 205 } | |
| 206 | |
| 207 /* | |
| 208 * Reads a line terminated by either '\r\n', '\n\r' or '\r' or '\n'. | |
| 209 * The returned buffer needs to be freed by the called. | |
| 210 */ | |
| 211 | |
| 212 char * | |
| 213 evbuffer_readline(struct evbuffer *buffer) | |
| 214 { | |
| 215 u_char *data = EVBUFFER_DATA(buffer); | |
| 216 size_t len = EVBUFFER_LENGTH(buffer); | |
| 217 char *line; | |
| 218 unsigned int i; | |
| 219 | |
| 220 for (i = 0; i < len; i++) { | |
| 221 if (data[i] == '\r' || data[i] == '\n') | |
| 222 break; | |
| 223 } | |
| 224 | |
| 225 if (i == len) | |
| 226 return (NULL); | |
| 227 | |
| 228 if ((line = malloc(i + 1)) == NULL) { | |
| 229 fprintf(stderr, "%s: out of memory\n", __func__); | |
| 230 return (NULL); | |
| 231 } | |
| 232 | |
| 233 memcpy(line, data, i); | |
| 234 line[i] = '\0'; | |
| 235 | |
| 236 /* | |
| 237 * Some protocols terminate a line with '\r\n', so check for | |
| 238 * that, too. | |
| 239 */ | |
| 240 if ( i < len - 1 ) { | |
| 241 char fch = data[i], sch = data[i+1]; | |
| 242 | |
| 243 /* Drain one more character if needed */ | |
| 244 if ( (sch == '\r' || sch == '\n') && sch != fch ) | |
| 245 i += 1; | |
| 246 } | |
| 247 | |
| 248 evbuffer_drain(buffer, i + 1); | |
| 249 | |
| 250 return (line); | |
| 251 } | |
| 252 | |
| 253 | |
| 254 char * | |
| 255 evbuffer_readln(struct evbuffer *buffer, size_t *n_read_out, | |
| 256 enum evbuffer_eol_style eol_style) | |
| 257 { | |
| 258 u_char *data = EVBUFFER_DATA(buffer); | |
| 259 u_char *start_of_eol, *end_of_eol; | |
| 260 size_t len = EVBUFFER_LENGTH(buffer); | |
| 261 char *line; | |
| 262 unsigned int i, n_to_copy, n_to_drain; | |
| 263 | |
| 264 if (n_read_out) | |
| 265 *n_read_out = 0; | |
| 266 | |
| 267 /* depending on eol_style, set start_of_eol to the first character | |
| 268 * in the newline, and end_of_eol to one after the last character. */ | |
| 269 switch (eol_style) { | |
| 270 case EVBUFFER_EOL_ANY: | |
| 271 for (i = 0; i < len; i++) { | |
| 272 if (data[i] == '\r' || data[i] == '\n') | |
| 273 break; | |
| 274 } | |
| 275 if (i == len) | |
| 276 return (NULL); | |
| 277 start_of_eol = data+i; | |
| 278 ++i; | |
| 279 for ( ; i < len; i++) { | |
| 280 if (data[i] != '\r' && data[i] != '\n') | |
| 281 break; | |
| 282 } | |
| 283 end_of_eol = data+i; | |
| 284 break; | |
| 285 case EVBUFFER_EOL_CRLF: | |
| 286 end_of_eol = memchr(data, '\n', len); | |
| 287 if (!end_of_eol) | |
| 288 return (NULL); | |
| 289 if (end_of_eol > data && *(end_of_eol-1) == '\r') | |
| 290 start_of_eol = end_of_eol - 1; | |
| 291 else | |
| 292 start_of_eol = end_of_eol; | |
| 293 end_of_eol++; /*point to one after the LF. */ | |
| 294 break; | |
| 295 case EVBUFFER_EOL_CRLF_STRICT: { | |
| 296 u_char *cp = data; | |
| 297 while ((cp = memchr(cp, '\r', len-(cp-data)))) { | |
| 298 if (cp < data+len-1 && *(cp+1) == '\n') | |
| 299 break; | |
| 300 if (++cp >= data+len) { | |
| 301 cp = NULL; | |
| 302 break; | |
| 303 } | |
| 304 } | |
| 305 if (!cp) | |
| 306 return (NULL); | |
| 307 start_of_eol = cp; | |
| 308 end_of_eol = cp+2; | |
| 309 break; | |
| 310 } | |
| 311 case EVBUFFER_EOL_LF: | |
| 312 start_of_eol = memchr(data, '\n', len); | |
| 313 if (!start_of_eol) | |
| 314 return (NULL); | |
| 315 end_of_eol = start_of_eol + 1; | |
| 316 break; | |
| 317 default: | |
| 318 return (NULL); | |
| 319 } | |
| 320 | |
| 321 n_to_copy = start_of_eol - data; | |
| 322 n_to_drain = end_of_eol - data; | |
| 323 | |
| 324 if ((line = malloc(n_to_copy+1)) == NULL) { | |
| 325 event_warn("%s: out of memory\n", __func__); | |
| 326 return (NULL); | |
| 327 } | |
| 328 | |
| 329 memcpy(line, data, n_to_copy); | |
| 330 line[n_to_copy] = '\0'; | |
| 331 | |
| 332 evbuffer_drain(buffer, n_to_drain); | |
| 333 if (n_read_out) | |
| 334 *n_read_out = (size_t)n_to_copy; | |
| 335 | |
| 336 return (line); | |
| 337 } | |
| 338 | |
| 339 /* Adds data to an event buffer */ | |
| 340 | |
| 341 static void | |
| 342 evbuffer_align(struct evbuffer *buf) | |
| 343 { | |
| 344 memmove(buf->orig_buffer, buf->buffer, buf->off); | |
| 345 buf->buffer = buf->orig_buffer; | |
| 346 buf->misalign = 0; | |
| 347 } | |
| 348 | |
| 349 #ifndef SIZE_MAX | |
| 350 #define SIZE_MAX ((size_t)-1) | |
| 351 #endif | |
| 352 | |
| 353 /* Expands the available space in the event buffer to at least datlen */ | |
| 354 | |
| 355 int | |
| 356 evbuffer_expand(struct evbuffer *buf, size_t datlen) | |
| 357 { | |
| 358 size_t used = buf->misalign + buf->off; | |
| 359 | |
| 360 assert(buf->totallen >= used); | |
| 361 | |
| 362 /* If we can fit all the data, then we don't have to do anything */ | |
| 363 if (buf->totallen - used >= datlen) | |
| 364 return (0); | |
| 365 /* If we would need to overflow to fit this much data, we can't | |
| 366 * do anything. */ | |
| 367 if (datlen > SIZE_MAX - buf->off) | |
| 368 return (-1); | |
| 369 | |
| 370 /* | |
| 371 * If the misalignment fulfills our data needs, we just force an | |
| 372 * alignment to happen. Afterwards, we have enough space. | |
| 373 */ | |
| 374 if (buf->totallen - buf->off >= datlen) { | |
| 375 evbuffer_align(buf); | |
| 376 } else { | |
| 377 void *newbuf; | |
| 378 size_t length = buf->totallen; | |
| 379 size_t need = buf->off + datlen; | |
| 380 | |
| 381 if (length < 256) | |
| 382 length = 256; | |
| 383 if (need < SIZE_MAX / 2) { | |
| 384 while (length < need) { | |
| 385 length <<= 1; | |
| 386 } | |
| 387 } else { | |
| 388 length = need; | |
| 389 } | |
| 390 | |
| 391 if (buf->orig_buffer != buf->buffer) | |
| 392 evbuffer_align(buf); | |
| 393 if ((newbuf = realloc(buf->buffer, length)) == NULL) | |
| 394 return (-1); | |
| 395 | |
| 396 buf->orig_buffer = buf->buffer = newbuf; | |
| 397 buf->totallen = length; | |
| 398 } | |
| 399 | |
| 400 return (0); | |
| 401 } | |
| 402 | |
| 403 int | |
| 404 evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen) | |
| 405 { | |
| 406 size_t used = buf->misalign + buf->off; | |
| 407 size_t oldoff = buf->off; | |
| 408 | |
| 409 if (buf->totallen - used < datlen) { | |
| 410 if (evbuffer_expand(buf, datlen) == -1) | |
| 411 return (-1); | |
| 412 } | |
| 413 | |
| 414 memcpy(buf->buffer + buf->off, data, datlen); | |
| 415 buf->off += datlen; | |
| 416 | |
| 417 if (datlen && buf->cb != NULL) | |
| 418 (*buf->cb)(buf, oldoff, buf->off, buf->cbarg); | |
| 419 | |
| 420 return (0); | |
| 421 } | |
| 422 | |
| 423 void | |
| 424 evbuffer_drain(struct evbuffer *buf, size_t len) | |
| 425 { | |
| 426 size_t oldoff = buf->off; | |
| 427 | |
| 428 if (len >= buf->off) { | |
| 429 buf->off = 0; | |
| 430 buf->buffer = buf->orig_buffer; | |
| 431 buf->misalign = 0; | |
| 432 goto done; | |
| 433 } | |
| 434 | |
| 435 buf->buffer += len; | |
| 436 buf->misalign += len; | |
| 437 | |
| 438 buf->off -= len; | |
| 439 | |
| 440 done: | |
| 441 /* Tell someone about changes in this buffer */ | |
| 442 if (buf->off != oldoff && buf->cb != NULL) | |
| 443 (*buf->cb)(buf, oldoff, buf->off, buf->cbarg); | |
| 444 | |
| 445 } | |
| 446 | |
| 447 /* | |
| 448 * Reads data from a file descriptor into a buffer. | |
| 449 */ | |
| 450 | |
| 451 #define EVBUFFER_MAX_READ 4096 | |
| 452 | |
| 453 int | |
| 454 evbuffer_read(struct evbuffer *buf, int fd, int howmuch) | |
| 455 { | |
| 456 u_char *p; | |
| 457 size_t oldoff = buf->off; | |
| 458 int n = EVBUFFER_MAX_READ; | |
| 459 | |
| 460 #if defined(FIONREAD) | |
| 461 #ifdef WIN32 | |
| 462 long lng = n; | |
| 463 if (ioctlsocket(fd, FIONREAD, &lng) == -1 || (n=lng) <= 0) { | |
| 464 #else | |
| 465 if (ioctl(fd, FIONREAD, &n) == -1 || n <= 0) { | |
| 466 #endif | |
| 467 n = EVBUFFER_MAX_READ; | |
| 468 } else if (n > EVBUFFER_MAX_READ && n > howmuch) { | |
| 469 /* | |
| 470 * It's possible that a lot of data is available for | |
| 471 * reading. We do not want to exhaust resources | |
| 472 * before the reader has a chance to do something | |
| 473 * about it. If the reader does not tell us how much | |
| 474 * data we should read, we artifically limit it. | |
| 475 */ | |
| 476 if ((size_t)n > buf->totallen << 2) | |
| 477 n = buf->totallen << 2; | |
| 478 if (n < EVBUFFER_MAX_READ) | |
| 479 n = EVBUFFER_MAX_READ; | |
| 480 } | |
| 481 #endif | |
| 482 if (howmuch < 0 || howmuch > n) | |
| 483 howmuch = n; | |
| 484 | |
| 485 /* If we don't have FIONREAD, we might waste some space here */ | |
| 486 if (evbuffer_expand(buf, howmuch) == -1) | |
| 487 return (-1); | |
| 488 | |
| 489 /* We can append new data at this point */ | |
| 490 p = buf->buffer + buf->off; | |
| 491 | |
| 492 #ifndef WIN32 | |
| 493 n = read(fd, p, howmuch); | |
| 494 #else | |
| 495 n = recv(fd, p, howmuch, 0); | |
| 496 #endif | |
| 497 if (n == -1) | |
| 498 return (-1); | |
| 499 if (n == 0) | |
| 500 return (0); | |
| 501 | |
| 502 buf->off += n; | |
| 503 | |
| 504 /* Tell someone about changes in this buffer */ | |
| 505 if (buf->off != oldoff && buf->cb != NULL) | |
| 506 (*buf->cb)(buf, oldoff, buf->off, buf->cbarg); | |
| 507 | |
| 508 return (n); | |
| 509 } | |
| 510 | |
| 511 int | |
| 512 evbuffer_write(struct evbuffer *buffer, int fd) | |
| 513 { | |
| 514 int n; | |
| 515 | |
| 516 #ifndef WIN32 | |
| 517 n = write(fd, buffer->buffer, buffer->off); | |
| 518 #else | |
| 519 n = send(fd, buffer->buffer, buffer->off, 0); | |
| 520 #endif | |
| 521 if (n == -1) | |
| 522 return (-1); | |
| 523 if (n == 0) | |
| 524 return (0); | |
| 525 evbuffer_drain(buffer, n); | |
| 526 | |
| 527 return (n); | |
| 528 } | |
| 529 | |
| 530 u_char * | |
| 531 evbuffer_find(struct evbuffer *buffer, const u_char *what, size_t len) | |
| 532 { | |
| 533 u_char *search = buffer->buffer, *end = search + buffer->off; | |
| 534 u_char *p; | |
| 535 | |
| 536 while (search < end && | |
| 537 (p = memchr(search, *what, end - search)) != NULL) { | |
| 538 if (p + len > end) | |
| 539 break; | |
| 540 if (memcmp(p, what, len) == 0) | |
| 541 return (p); | |
| 542 search = p + 1; | |
| 543 } | |
| 544 | |
| 545 return (NULL); | |
| 546 } | |
| 547 | |
| 548 void evbuffer_setcb(struct evbuffer *buffer, | |
| 549 void (*cb)(struct evbuffer *, size_t, size_t, void *), | |
| 550 void *cbarg) | |
| 551 { | |
| 552 buffer->cb = cb; | |
| 553 buffer->cbarg = cbarg; | |
| 554 } | |
| OLD | NEW |