1 /* $NetBSD: buffer.c,v 1.4 2017/01/31 23:17:39 christos Exp $ */ 2 /* 3 * Copyright (c) 2002-2007 Niels Provos <provos@citi.umich.edu> 4 * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "event2/event-config.h" 30 #include <sys/cdefs.h> 31 __RCSID("$NetBSD: buffer.c,v 1.4 2017/01/31 23:17:39 christos Exp $"); 32 #include "evconfig-private.h" 33 34 #ifdef _WIN32 35 #include <winsock2.h> 36 #include <windows.h> 37 #include <io.h> 38 #endif 39 40 #ifdef EVENT__HAVE_VASPRINTF 41 /* If we have vasprintf, we need to define _GNU_SOURCE before we include 42 * stdio.h. This comes from evconfig-private.h. 43 */ 44 #endif 45 46 #include <sys/types.h> 47 48 #ifdef EVENT__HAVE_SYS_TIME_H 49 #include <sys/time.h> 50 #endif 51 52 #ifdef EVENT__HAVE_SYS_SOCKET_H 53 #include <sys/socket.h> 54 #endif 55 56 #ifdef EVENT__HAVE_SYS_UIO_H 57 #include <sys/uio.h> 58 #endif 59 60 #ifdef EVENT__HAVE_SYS_IOCTL_H 61 #include <sys/ioctl.h> 62 #endif 63 64 #ifdef EVENT__HAVE_SYS_MMAN_H 65 #include <sys/mman.h> 66 #endif 67 68 #ifdef EVENT__HAVE_SYS_SENDFILE_H 69 #include <sys/sendfile.h> 70 #endif 71 #ifdef EVENT__HAVE_SYS_STAT_H 72 #include <sys/stat.h> 73 #endif 74 75 76 #include <errno.h> 77 #include <stdio.h> 78 #include <stdlib.h> 79 #include <string.h> 80 #ifdef EVENT__HAVE_STDARG_H 81 #include <stdarg.h> 82 #endif 83 #ifdef EVENT__HAVE_UNISTD_H 84 #include <unistd.h> 85 #endif 86 #include <limits.h> 87 88 #include "event2/event.h" 89 #include "event2/buffer.h" 90 #include "event2/buffer_compat.h" 91 #include "event2/bufferevent.h" 92 #include "event2/bufferevent_compat.h" 93 #include "event2/bufferevent_struct.h" 94 #include "event2/thread.h" 95 #include "log-internal.h" 96 #include "mm-internal.h" 97 #include "util-internal.h" 98 #include "evthread-internal.h" 99 #include "evbuffer-internal.h" 100 #include "bufferevent-internal.h" 101 102 /* some systems do not have MAP_FAILED */ 103 #ifndef MAP_FAILED 104 #define MAP_FAILED ((void *)-1) 105 #endif 106 107 /* send file support */ 108 #if defined(EVENT__HAVE_SYS_SENDFILE_H) && defined(EVENT__HAVE_SENDFILE) && defined(__linux__) 109 #define USE_SENDFILE 1 110 #define SENDFILE_IS_LINUX 1 111 #elif defined(EVENT__HAVE_SENDFILE) && defined(__FreeBSD__) 112 #define USE_SENDFILE 1 113 #define SENDFILE_IS_FREEBSD 1 114 #elif defined(EVENT__HAVE_SENDFILE) && defined(__APPLE__) 115 #define USE_SENDFILE 1 116 #define SENDFILE_IS_MACOSX 1 117 #elif defined(EVENT__HAVE_SENDFILE) && defined(__sun__) && defined(__svr4__) 118 #define USE_SENDFILE 1 119 #define SENDFILE_IS_SOLARIS 1 120 #endif 121 122 /* Mask of user-selectable callback flags. */ 123 #define EVBUFFER_CB_USER_FLAGS 0xffff 124 /* Mask of all internal-use-only flags. */ 125 #define EVBUFFER_CB_INTERNAL_FLAGS 0xffff0000 126 127 /* Flag set if the callback is using the cb_obsolete function pointer */ 128 #define EVBUFFER_CB_OBSOLETE 0x00040000 129 130 /* evbuffer_chain support */ 131 #define CHAIN_SPACE_PTR(ch) ((ch)->buffer + (ch)->misalign + (ch)->off) 132 #define CHAIN_SPACE_LEN(ch) ((ch)->flags & EVBUFFER_IMMUTABLE ? \ 133 0 : (ch)->buffer_len - ((ch)->misalign + (ch)->off)) 134 135 #define CHAIN_PINNED(ch) (((ch)->flags & EVBUFFER_MEM_PINNED_ANY) != 0) 136 #define CHAIN_PINNED_R(ch) (((ch)->flags & EVBUFFER_MEM_PINNED_R) != 0) 137 138 /* evbuffer_ptr support */ 139 #define PTR_NOT_FOUND(ptr) do { \ 140 (ptr)->pos = -1; \ 141 (ptr)->internal_.chain = NULL; \ 142 (ptr)->internal_.pos_in_chain = 0; \ 143 } while (0) 144 145 static void evbuffer_chain_align(struct evbuffer_chain *chain); 146 static int evbuffer_chain_should_realign(struct evbuffer_chain *chain, 147 size_t datalen); 148 static void evbuffer_deferred_callback(struct event_callback *cb, void *arg); 149 static int evbuffer_ptr_memcmp(const struct evbuffer *buf, 150 const struct evbuffer_ptr *pos, const char *mem, size_t len); 151 static struct evbuffer_chain *evbuffer_expand_singlechain(struct evbuffer *buf, 152 size_t datlen); 153 static int evbuffer_ptr_subtract(struct evbuffer *buf, struct evbuffer_ptr *pos, 154 size_t howfar); 155 static int evbuffer_file_segment_materialize(struct evbuffer_file_segment *seg); 156 static inline void evbuffer_chain_incref(struct evbuffer_chain *chain); 157 158 static struct evbuffer_chain * 159 evbuffer_chain_new(size_t size) 160 { 161 struct evbuffer_chain *chain; 162 size_t to_alloc; 163 164 if (size > EVBUFFER_CHAIN_MAX - EVBUFFER_CHAIN_SIZE) 165 return (NULL); 166 167 size += EVBUFFER_CHAIN_SIZE; 168 169 /* get the next largest memory that can hold the buffer */ 170 if (size < EVBUFFER_CHAIN_MAX / 2) { 171 to_alloc = MIN_BUFFER_SIZE; 172 while (to_alloc < size) { 173 to_alloc <<= 1; 174 } 175 } else { 176 to_alloc = size; 177 } 178 179 /* we get everything in one chunk */ 180 if ((chain = mm_malloc(to_alloc)) == NULL) 181 return (NULL); 182 183 memset(chain, 0, EVBUFFER_CHAIN_SIZE); 184 185 chain->buffer_len = to_alloc - EVBUFFER_CHAIN_SIZE; 186 187 /* this way we can manipulate the buffer to different addresses, 188 * which is required for mmap for example. 189 */ 190 chain->buffer = EVBUFFER_CHAIN_EXTRA(unsigned char, chain); 191 192 chain->refcnt = 1; 193 194 return (chain); 195 } 196 197 static inline void 198 evbuffer_chain_free(struct evbuffer_chain *chain) 199 { 200 EVUTIL_ASSERT(chain->refcnt > 0); 201 if (--chain->refcnt > 0) { 202 /* chain is still referenced by other chains */ 203 return; 204 } 205 206 if (CHAIN_PINNED(chain)) { 207 /* will get freed once no longer dangling */ 208 chain->refcnt++; 209 chain->flags |= EVBUFFER_DANGLING; 210 return; 211 } 212 213 /* safe to release chain, it's either a referencing 214 * chain or all references to it have been freed */ 215 if (chain->flags & EVBUFFER_REFERENCE) { 216 struct evbuffer_chain_reference *info = 217 EVBUFFER_CHAIN_EXTRA( 218 struct evbuffer_chain_reference, 219 chain); 220 if (info->cleanupfn) 221 (*info->cleanupfn)(chain->buffer, 222 chain->buffer_len, 223 info->extra); 224 } 225 if (chain->flags & EVBUFFER_FILESEGMENT) { 226 struct evbuffer_chain_file_segment *info = 227 EVBUFFER_CHAIN_EXTRA( 228 struct evbuffer_chain_file_segment, 229 chain); 230 if (info->segment) { 231 #ifdef _WIN32 232 if (info->segment->is_mapping) 233 UnmapViewOfFile(chain->buffer); 234 #endif 235 evbuffer_file_segment_free(info->segment); 236 } 237 } 238 if (chain->flags & EVBUFFER_MULTICAST) { 239 struct evbuffer_multicast_parent *info = 240 EVBUFFER_CHAIN_EXTRA( 241 struct evbuffer_multicast_parent, 242 chain); 243 /* referencing chain is being freed, decrease 244 * refcounts of source chain and associated 245 * evbuffer (which get freed once both reach 246 * zero) */ 247 EVUTIL_ASSERT(info->source != NULL); 248 EVUTIL_ASSERT(info->parent != NULL); 249 EVBUFFER_LOCK(info->source); 250 evbuffer_chain_free(info->parent); 251 evbuffer_decref_and_unlock_(info->source); 252 } 253 254 mm_free(chain); 255 } 256 257 static void 258 evbuffer_free_all_chains(struct evbuffer_chain *chain) 259 { 260 struct evbuffer_chain *next; 261 for (; chain; chain = next) { 262 next = chain->next; 263 evbuffer_chain_free(chain); 264 } 265 } 266 267 #ifndef NDEBUG 268 static int 269 evbuffer_chains_all_empty(struct evbuffer_chain *chain) 270 { 271 for (; chain; chain = chain->next) { 272 if (chain->off) 273 return 0; 274 } 275 return 1; 276 } 277 #else 278 /* The definition is needed for EVUTIL_ASSERT, which uses sizeof to avoid 279 "unused variable" warnings. */ 280 static inline int evbuffer_chains_all_empty(struct evbuffer_chain *chain) { 281 return 1; 282 } 283 #endif 284 285 /* Free all trailing chains in 'buf' that are neither pinned nor empty, prior 286 * to replacing them all with a new chain. Return a pointer to the place 287 * where the new chain will go. 288 * 289 * Internal; requires lock. The caller must fix up buf->last and buf->first 290 * as needed; they might have been freed. 291 */ 292 static struct evbuffer_chain ** 293 evbuffer_free_trailing_empty_chains(struct evbuffer *buf) 294 { 295 struct evbuffer_chain **ch = buf->last_with_datap; 296 /* Find the first victim chain. It might be *last_with_datap */ 297 while ((*ch) && ((*ch)->off != 0 || CHAIN_PINNED(*ch))) 298 ch = &(*ch)->next; 299 if (*ch) { 300 EVUTIL_ASSERT(evbuffer_chains_all_empty(*ch)); 301 evbuffer_free_all_chains(*ch); 302 *ch = NULL; 303 } 304 return ch; 305 } 306 307 /* Add a single chain 'chain' to the end of 'buf', freeing trailing empty 308 * chains as necessary. Requires lock. Does not schedule callbacks. 309 */ 310 static void 311 evbuffer_chain_insert(struct evbuffer *buf, 312 struct evbuffer_chain *chain) 313 { 314 ASSERT_EVBUFFER_LOCKED(buf); 315 if (*buf->last_with_datap == NULL) { 316 /* There are no chains data on the buffer at all. */ 317 EVUTIL_ASSERT(buf->last_with_datap == &buf->first); 318 EVUTIL_ASSERT(buf->first == NULL); 319 buf->first = buf->last = chain; 320 } else { 321 struct evbuffer_chain **chp; 322 chp = evbuffer_free_trailing_empty_chains(buf); 323 *chp = chain; 324 if (chain->off) 325 buf->last_with_datap = chp; 326 buf->last = chain; 327 } 328 buf->total_len += chain->off; 329 } 330 331 static inline struct evbuffer_chain * 332 evbuffer_chain_insert_new(struct evbuffer *buf, size_t datlen) 333 { 334 struct evbuffer_chain *chain; 335 if ((chain = evbuffer_chain_new(datlen)) == NULL) 336 return NULL; 337 evbuffer_chain_insert(buf, chain); 338 return chain; 339 } 340 341 void 342 evbuffer_chain_pin_(struct evbuffer_chain *chain, unsigned flag) 343 { 344 EVUTIL_ASSERT((chain->flags & flag) == 0); 345 chain->flags |= flag; 346 } 347 348 void 349 evbuffer_chain_unpin_(struct evbuffer_chain *chain, unsigned flag) 350 { 351 EVUTIL_ASSERT((chain->flags & flag) != 0); 352 chain->flags &= ~flag; 353 if (chain->flags & EVBUFFER_DANGLING) 354 evbuffer_chain_free(chain); 355 } 356 357 static inline void 358 evbuffer_chain_incref(struct evbuffer_chain *chain) 359 { 360 ++chain->refcnt; 361 } 362 363 struct evbuffer * 364 evbuffer_new(void) 365 { 366 struct evbuffer *buffer; 367 368 buffer = mm_calloc(1, sizeof(struct evbuffer)); 369 if (buffer == NULL) 370 return (NULL); 371 372 LIST_INIT(&buffer->callbacks); 373 buffer->refcnt = 1; 374 buffer->last_with_datap = &buffer->first; 375 376 return (buffer); 377 } 378 379 int 380 evbuffer_set_flags(struct evbuffer *buf, ev_uint64_t flags) 381 { 382 EVBUFFER_LOCK(buf); 383 buf->flags |= (ev_uint32_t)flags; 384 EVBUFFER_UNLOCK(buf); 385 return 0; 386 } 387 388 int 389 evbuffer_clear_flags(struct evbuffer *buf, ev_uint64_t flags) 390 { 391 EVBUFFER_LOCK(buf); 392 buf->flags &= ~(ev_uint32_t)flags; 393 EVBUFFER_UNLOCK(buf); 394 return 0; 395 } 396 397 void 398 evbuffer_incref_(struct evbuffer *buf) 399 { 400 EVBUFFER_LOCK(buf); 401 ++buf->refcnt; 402 EVBUFFER_UNLOCK(buf); 403 } 404 405 void 406 evbuffer_incref_and_lock_(struct evbuffer *buf) 407 { 408 EVBUFFER_LOCK(buf); 409 ++buf->refcnt; 410 } 411 412 int 413 evbuffer_defer_callbacks(struct evbuffer *buffer, struct event_base *base) 414 { 415 EVBUFFER_LOCK(buffer); 416 buffer->cb_queue = base; 417 buffer->deferred_cbs = 1; 418 event_deferred_cb_init_(&buffer->deferred, 419 event_base_get_npriorities(base) / 2, 420 evbuffer_deferred_callback, buffer); 421 EVBUFFER_UNLOCK(buffer); 422 return 0; 423 } 424 425 int 426 evbuffer_enable_locking(struct evbuffer *buf, void *lock) 427 { 428 #ifdef EVENT__DISABLE_THREAD_SUPPORT 429 return -1; 430 #else 431 if (buf->lock) 432 return -1; 433 434 if (!lock) { 435 EVTHREAD_ALLOC_LOCK(lock, EVTHREAD_LOCKTYPE_RECURSIVE); 436 if (!lock) 437 return -1; 438 buf->lock = lock; 439 buf->own_lock = 1; 440 } else { 441 buf->lock = lock; 442 buf->own_lock = 0; 443 } 444 445 return 0; 446 #endif 447 } 448 449 void 450 evbuffer_set_parent_(struct evbuffer *buf, struct bufferevent *bev) 451 { 452 EVBUFFER_LOCK(buf); 453 buf->parent = bev; 454 EVBUFFER_UNLOCK(buf); 455 } 456 457 static void 458 evbuffer_run_callbacks(struct evbuffer *buffer, int running_deferred) 459 { 460 struct evbuffer_cb_entry *cbent, *next; 461 struct evbuffer_cb_info info; 462 size_t new_size; 463 ev_uint32_t mask, masked_val; 464 int clear = 1; 465 466 if (running_deferred) { 467 mask = EVBUFFER_CB_NODEFER|EVBUFFER_CB_ENABLED; 468 masked_val = EVBUFFER_CB_ENABLED; 469 } else if (buffer->deferred_cbs) { 470 mask = EVBUFFER_CB_NODEFER|EVBUFFER_CB_ENABLED; 471 masked_val = EVBUFFER_CB_NODEFER|EVBUFFER_CB_ENABLED; 472 /* Don't zero-out n_add/n_del, since the deferred callbacks 473 will want to see them. */ 474 clear = 0; 475 } else { 476 mask = EVBUFFER_CB_ENABLED; 477 masked_val = EVBUFFER_CB_ENABLED; 478 } 479 480 ASSERT_EVBUFFER_LOCKED(buffer); 481 482 if (LIST_EMPTY(&buffer->callbacks)) { 483 buffer->n_add_for_cb = buffer->n_del_for_cb = 0; 484 return; 485 } 486 if (buffer->n_add_for_cb == 0 && buffer->n_del_for_cb == 0) 487 return; 488 489 new_size = buffer->total_len; 490 info.orig_size = new_size + buffer->n_del_for_cb - buffer->n_add_for_cb; 491 info.n_added = buffer->n_add_for_cb; 492 info.n_deleted = buffer->n_del_for_cb; 493 if (clear) { 494 buffer->n_add_for_cb = 0; 495 buffer->n_del_for_cb = 0; 496 } 497 for (cbent = LIST_FIRST(&buffer->callbacks); 498 cbent != LIST_END(&buffer->callbacks); 499 cbent = next) { 500 /* Get the 'next' pointer now in case this callback decides 501 * to remove itself or something. */ 502 next = LIST_NEXT(cbent, next); 503 504 if ((cbent->flags & mask) != masked_val) 505 continue; 506 507 if ((cbent->flags & EVBUFFER_CB_OBSOLETE)) 508 cbent->cb.cb_obsolete(buffer, 509 info.orig_size, new_size, cbent->cbarg); 510 else 511 cbent->cb.cb_func(buffer, &info, cbent->cbarg); 512 } 513 } 514 515 void 516 evbuffer_invoke_callbacks_(struct evbuffer *buffer) 517 { 518 if (LIST_EMPTY(&buffer->callbacks)) { 519 buffer->n_add_for_cb = buffer->n_del_for_cb = 0; 520 return; 521 } 522 523 if (buffer->deferred_cbs) { 524 if (event_deferred_cb_schedule_(buffer->cb_queue, &buffer->deferred)) { 525 evbuffer_incref_and_lock_(buffer); 526 if (buffer->parent) 527 bufferevent_incref_(buffer->parent); 528 } 529 EVBUFFER_UNLOCK(buffer); 530 } 531 532 evbuffer_run_callbacks(buffer, 0); 533 } 534 535 static void 536 evbuffer_deferred_callback(struct event_callback *cb, void *arg) 537 { 538 struct bufferevent *parent = NULL; 539 struct evbuffer *buffer = arg; 540 541 /* XXXX It would be better to run these callbacks without holding the 542 * lock */ 543 EVBUFFER_LOCK(buffer); 544 parent = buffer->parent; 545 evbuffer_run_callbacks(buffer, 1); 546 evbuffer_decref_and_unlock_(buffer); 547 if (parent) 548 bufferevent_decref_(parent); 549 } 550 551 static void 552 evbuffer_remove_all_callbacks(struct evbuffer *buffer) 553 { 554 struct evbuffer_cb_entry *cbent; 555 556 while ((cbent = LIST_FIRST(&buffer->callbacks))) { 557 LIST_REMOVE(cbent, next); 558 mm_free(cbent); 559 } 560 } 561 562 void 563 evbuffer_decref_and_unlock_(struct evbuffer *buffer) 564 { 565 struct evbuffer_chain *chain, *next; 566 ASSERT_EVBUFFER_LOCKED(buffer); 567 568 EVUTIL_ASSERT(buffer->refcnt > 0); 569 570 if (--buffer->refcnt > 0) { 571 EVBUFFER_UNLOCK(buffer); 572 return; 573 } 574 575 for (chain = buffer->first; chain != NULL; chain = next) { 576 next = chain->next; 577 evbuffer_chain_free(chain); 578 } 579 evbuffer_remove_all_callbacks(buffer); 580 if (buffer->deferred_cbs) 581 event_deferred_cb_cancel_(buffer->cb_queue, &buffer->deferred); 582 583 EVBUFFER_UNLOCK(buffer); 584 if (buffer->own_lock) 585 EVTHREAD_FREE_LOCK(buffer->lock, EVTHREAD_LOCKTYPE_RECURSIVE); 586 mm_free(buffer); 587 } 588 589 void 590 evbuffer_free(struct evbuffer *buffer) 591 { 592 EVBUFFER_LOCK(buffer); 593 evbuffer_decref_and_unlock_(buffer); 594 } 595 596 void 597 evbuffer_lock(struct evbuffer *buf) 598 { 599 EVBUFFER_LOCK(buf); 600 } 601 602 void 603 evbuffer_unlock(struct evbuffer *buf) 604 { 605 EVBUFFER_UNLOCK(buf); 606 } 607 608 size_t 609 evbuffer_get_length(const struct evbuffer *buffer) 610 { 611 size_t result; 612 613 EVBUFFER_LOCK(buffer); 614 615 result = (buffer->total_len); 616 617 EVBUFFER_UNLOCK(buffer); 618 619 return result; 620 } 621 622 size_t 623 evbuffer_get_contiguous_space(const struct evbuffer *buf) 624 { 625 struct evbuffer_chain *chain; 626 size_t result; 627 628 EVBUFFER_LOCK(buf); 629 chain = buf->first; 630 result = (chain != NULL ? chain->off : 0); 631 EVBUFFER_UNLOCK(buf); 632 633 return result; 634 } 635 636 size_t 637 evbuffer_add_iovec(struct evbuffer * buf, struct evbuffer_iovec * vec, int n_vec) { 638 int n; 639 size_t res; 640 size_t to_alloc; 641 642 EVBUFFER_LOCK(buf); 643 644 res = to_alloc = 0; 645 646 for (n = 0; n < n_vec; n++) { 647 to_alloc += vec[n].iov_len; 648 } 649 650 if (evbuffer_expand_fast_(buf, to_alloc, 2) < 0) { 651 goto done; 652 } 653 654 for (n = 0; n < n_vec; n++) { 655 /* XXX each 'add' call here does a bunch of setup that's 656 * obviated by evbuffer_expand_fast_, and some cleanup that we 657 * would like to do only once. Instead we should just extract 658 * the part of the code that's needed. */ 659 660 if (evbuffer_add(buf, vec[n].iov_base, vec[n].iov_len) < 0) { 661 goto done; 662 } 663 664 res += vec[n].iov_len; 665 } 666 667 done: 668 EVBUFFER_UNLOCK(buf); 669 return res; 670 } 671 672 int 673 evbuffer_reserve_space(struct evbuffer *buf, ev_ssize_t size, 674 struct evbuffer_iovec *vec, int n_vecs) 675 { 676 struct evbuffer_chain *chain, **chainp; 677 int n = -1; 678 679 EVBUFFER_LOCK(buf); 680 if (buf->freeze_end) 681 goto done; 682 if (n_vecs < 1) 683 goto done; 684 if (n_vecs == 1) { 685 if ((chain = evbuffer_expand_singlechain(buf, size)) == NULL) 686 goto done; 687 688 vec[0].iov_base = (void *)CHAIN_SPACE_PTR(chain); 689 vec[0].iov_len = (size_t)CHAIN_SPACE_LEN(chain); 690 EVUTIL_ASSERT(size<0 || (size_t)vec[0].iov_len >= (size_t)size); 691 n = 1; 692 } else { 693 if (evbuffer_expand_fast_(buf, size, n_vecs)<0) 694 goto done; 695 n = evbuffer_read_setup_vecs_(buf, size, vec, n_vecs, 696 &chainp, 0); 697 } 698 699 done: 700 EVBUFFER_UNLOCK(buf); 701 return n; 702 703 } 704 705 static int 706 advance_last_with_data(struct evbuffer *buf) 707 { 708 int n = 0; 709 ASSERT_EVBUFFER_LOCKED(buf); 710 711 if (!*buf->last_with_datap) 712 return 0; 713 714 while ((*buf->last_with_datap)->next && (*buf->last_with_datap)->next->off) { 715 buf->last_with_datap = &(*buf->last_with_datap)->next; 716 ++n; 717 } 718 return n; 719 } 720 721 int 722 evbuffer_commit_space(struct evbuffer *buf, 723 struct evbuffer_iovec *vec, int n_vecs) 724 { 725 struct evbuffer_chain *chain, **firstchainp, **chainp; 726 int result = -1; 727 size_t added = 0; 728 int i; 729 730 EVBUFFER_LOCK(buf); 731 732 if (buf->freeze_end) 733 goto done; 734 if (n_vecs == 0) { 735 result = 0; 736 goto done; 737 } else if (n_vecs == 1 && 738 (buf->last && vec[0].iov_base == (void *)CHAIN_SPACE_PTR(buf->last))) { 739 /* The user only got or used one chain; it might not 740 * be the first one with space in it. */ 741 if ((size_t)vec[0].iov_len > (size_t)CHAIN_SPACE_LEN(buf->last)) 742 goto done; 743 buf->last->off += vec[0].iov_len; 744 added = vec[0].iov_len; 745 if (added) 746 advance_last_with_data(buf); 747 goto okay; 748 } 749 750 /* Advance 'firstchain' to the first chain with space in it. */ 751 firstchainp = buf->last_with_datap; 752 if (!*firstchainp) 753 goto done; 754 if (CHAIN_SPACE_LEN(*firstchainp) == 0) { 755 firstchainp = &(*firstchainp)->next; 756 } 757 758 chain = *firstchainp; 759 /* pass 1: make sure that the pointers and lengths of vecs[] are in 760 * bounds before we try to commit anything. */ 761 for (i=0; i<n_vecs; ++i) { 762 if (!chain) 763 goto done; 764 if (vec[i].iov_base != (void *)CHAIN_SPACE_PTR(chain) || 765 (size_t)vec[i].iov_len > CHAIN_SPACE_LEN(chain)) 766 goto done; 767 chain = chain->next; 768 } 769 /* pass 2: actually adjust all the chains. */ 770 chainp = firstchainp; 771 for (i=0; i<n_vecs; ++i) { 772 (*chainp)->off += vec[i].iov_len; 773 added += vec[i].iov_len; 774 if (vec[i].iov_len) { 775 buf->last_with_datap = chainp; 776 } 777 chainp = &(*chainp)->next; 778 } 779 780 okay: 781 buf->total_len += added; 782 buf->n_add_for_cb += added; 783 result = 0; 784 evbuffer_invoke_callbacks_(buf); 785 786 done: 787 EVBUFFER_UNLOCK(buf); 788 return result; 789 } 790 791 static inline int 792 HAS_PINNED_R(struct evbuffer *buf) 793 { 794 return (buf->last && CHAIN_PINNED_R(buf->last)); 795 } 796 797 static inline void 798 ZERO_CHAIN(struct evbuffer *dst) 799 { 800 ASSERT_EVBUFFER_LOCKED(dst); 801 dst->first = NULL; 802 dst->last = NULL; 803 dst->last_with_datap = &(dst)->first; 804 dst->total_len = 0; 805 } 806 807 /* Prepares the contents of src to be moved to another buffer by removing 808 * read-pinned chains. The first pinned chain is saved in first, and the 809 * last in last. If src has no read-pinned chains, first and last are set 810 * to NULL. */ 811 static int 812 PRESERVE_PINNED(struct evbuffer *src, struct evbuffer_chain **first, 813 struct evbuffer_chain **last) 814 { 815 struct evbuffer_chain *chain, **pinned; 816 817 ASSERT_EVBUFFER_LOCKED(src); 818 819 if (!HAS_PINNED_R(src)) { 820 *first = *last = NULL; 821 return 0; 822 } 823 824 pinned = src->last_with_datap; 825 if (!CHAIN_PINNED_R(*pinned)) 826 pinned = &(*pinned)->next; 827 EVUTIL_ASSERT(CHAIN_PINNED_R(*pinned)); 828 chain = *first = *pinned; 829 *last = src->last; 830 831 /* If there's data in the first pinned chain, we need to allocate 832 * a new chain and copy the data over. */ 833 if (chain->off) { 834 struct evbuffer_chain *tmp; 835 836 EVUTIL_ASSERT(pinned == src->last_with_datap); 837 tmp = evbuffer_chain_new(chain->off); 838 if (!tmp) 839 return -1; 840 memcpy(tmp->buffer, chain->buffer + chain->misalign, 841 chain->off); 842 tmp->off = chain->off; 843 *src->last_with_datap = tmp; 844 src->last = tmp; 845 chain->misalign += chain->off; 846 chain->off = 0; 847 } else { 848 src->last = *src->last_with_datap; 849 *pinned = NULL; 850 } 851 852 return 0; 853 } 854 855 static inline void 856 RESTORE_PINNED(struct evbuffer *src, struct evbuffer_chain *pinned, 857 struct evbuffer_chain *last) 858 { 859 ASSERT_EVBUFFER_LOCKED(src); 860 861 if (!pinned) { 862 ZERO_CHAIN(src); 863 return; 864 } 865 866 src->first = pinned; 867 src->last = last; 868 src->last_with_datap = &src->first; 869 src->total_len = 0; 870 } 871 872 static inline void 873 COPY_CHAIN(struct evbuffer *dst, struct evbuffer *src) 874 { 875 ASSERT_EVBUFFER_LOCKED(dst); 876 ASSERT_EVBUFFER_LOCKED(src); 877 dst->first = src->first; 878 if (src->last_with_datap == &src->first) 879 dst->last_with_datap = &dst->first; 880 else 881 dst->last_with_datap = src->last_with_datap; 882 dst->last = src->last; 883 dst->total_len = src->total_len; 884 } 885 886 static void 887 APPEND_CHAIN(struct evbuffer *dst, struct evbuffer *src) 888 { 889 struct evbuffer_chain **chp; 890 891 ASSERT_EVBUFFER_LOCKED(dst); 892 ASSERT_EVBUFFER_LOCKED(src); 893 894 chp = evbuffer_free_trailing_empty_chains(dst); 895 *chp = src->first; 896 897 if (src->last_with_datap == &src->first) 898 dst->last_with_datap = chp; 899 else 900 dst->last_with_datap = src->last_with_datap; 901 dst->last = src->last; 902 dst->total_len += src->total_len; 903 } 904 905 static inline void 906 APPEND_CHAIN_MULTICAST(struct evbuffer *dst, struct evbuffer *src) 907 { 908 struct evbuffer_chain *tmp; 909 struct evbuffer_chain *chain = src->first; 910 struct evbuffer_multicast_parent *extra; 911 912 ASSERT_EVBUFFER_LOCKED(dst); 913 ASSERT_EVBUFFER_LOCKED(src); 914 915 for (; chain; chain = chain->next) { 916 if (!chain->off || chain->flags & EVBUFFER_DANGLING) { 917 /* skip empty chains */ 918 continue; 919 } 920 921 tmp = evbuffer_chain_new(sizeof(struct evbuffer_multicast_parent)); 922 if (!tmp) { 923 event_warn("%s: out of memory", __func__); 924 return; 925 } 926 extra = EVBUFFER_CHAIN_EXTRA(struct evbuffer_multicast_parent, tmp); 927 /* reference evbuffer containing source chain so it 928 * doesn't get released while the chain is still 929 * being referenced to */ 930 evbuffer_incref_(src); 931 extra->source = src; 932 /* reference source chain which now becomes immutable */ 933 evbuffer_chain_incref(chain); 934 extra->parent = chain; 935 chain->flags |= EVBUFFER_IMMUTABLE; 936 tmp->buffer_len = chain->buffer_len; 937 tmp->misalign = chain->misalign; 938 tmp->off = chain->off; 939 tmp->flags |= EVBUFFER_MULTICAST|EVBUFFER_IMMUTABLE; 940 tmp->buffer = chain->buffer; 941 evbuffer_chain_insert(dst, tmp); 942 } 943 } 944 945 static void 946 PREPEND_CHAIN(struct evbuffer *dst, struct evbuffer *src) 947 { 948 ASSERT_EVBUFFER_LOCKED(dst); 949 ASSERT_EVBUFFER_LOCKED(src); 950 src->last->next = dst->first; 951 dst->first = src->first; 952 dst->total_len += src->total_len; 953 if (*dst->last_with_datap == NULL) { 954 if (src->last_with_datap == &(src)->first) 955 dst->last_with_datap = &dst->first; 956 else 957 dst->last_with_datap = src->last_with_datap; 958 } else if (dst->last_with_datap == &dst->first) { 959 dst->last_with_datap = &src->last->next; 960 } 961 } 962 963 int 964 evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf) 965 { 966 struct evbuffer_chain *pinned, *last; 967 size_t in_total_len, out_total_len; 968 int result = 0; 969 970 EVBUFFER_LOCK2(inbuf, outbuf); 971 in_total_len = inbuf->total_len; 972 out_total_len = outbuf->total_len; 973 974 if (in_total_len == 0 || outbuf == inbuf) 975 goto done; 976 977 if (outbuf->freeze_end || inbuf->freeze_start) { 978 result = -1; 979 goto done; 980 } 981 982 if (PRESERVE_PINNED(inbuf, &pinned, &last) < 0) { 983 result = -1; 984 goto done; 985 } 986 987 if (out_total_len == 0) { 988 /* There might be an empty chain at the start of outbuf; free 989 * it. */ 990 evbuffer_free_all_chains(outbuf->first); 991 COPY_CHAIN(outbuf, inbuf); 992 } else { 993 APPEND_CHAIN(outbuf, inbuf); 994 } 995 996 RESTORE_PINNED(inbuf, pinned, last); 997 998 inbuf->n_del_for_cb += in_total_len; 999 outbuf->n_add_for_cb += in_total_len; 1000 1001 evbuffer_invoke_callbacks_(inbuf); 1002 evbuffer_invoke_callbacks_(outbuf); 1003 1004 done: 1005 EVBUFFER_UNLOCK2(inbuf, outbuf); 1006 return result; 1007 } 1008 1009 int 1010 evbuffer_add_buffer_reference(struct evbuffer *outbuf, struct evbuffer *inbuf) 1011 { 1012 size_t in_total_len, out_total_len; 1013 struct evbuffer_chain *chain; 1014 int result = 0; 1015 1016 EVBUFFER_LOCK2(inbuf, outbuf); 1017 in_total_len = inbuf->total_len; 1018 out_total_len = outbuf->total_len; 1019 chain = inbuf->first; 1020 1021 if (in_total_len == 0) 1022 goto done; 1023 1024 if (outbuf->freeze_end || outbuf == inbuf) { 1025 result = -1; 1026 goto done; 1027 } 1028 1029 for (; chain; chain = chain->next) { 1030 if ((chain->flags & (EVBUFFER_FILESEGMENT|EVBUFFER_SENDFILE|EVBUFFER_MULTICAST)) != 0) { 1031 /* chain type can not be referenced */ 1032 result = -1; 1033 goto done; 1034 } 1035 } 1036 1037 if (out_total_len == 0) { 1038 /* There might be an empty chain at the start of outbuf; free 1039 * it. */ 1040 evbuffer_free_all_chains(outbuf->first); 1041 } 1042 APPEND_CHAIN_MULTICAST(outbuf, inbuf); 1043 1044 outbuf->n_add_for_cb += in_total_len; 1045 evbuffer_invoke_callbacks_(outbuf); 1046 1047 done: 1048 EVBUFFER_UNLOCK2(inbuf, outbuf); 1049 return result; 1050 } 1051 1052 int 1053 evbuffer_prepend_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf) 1054 { 1055 struct evbuffer_chain *pinned, *last; 1056 size_t in_total_len, out_total_len; 1057 int result = 0; 1058 1059 EVBUFFER_LOCK2(inbuf, outbuf); 1060 1061 in_total_len = inbuf->total_len; 1062 out_total_len = outbuf->total_len; 1063 1064 if (!in_total_len || inbuf == outbuf) 1065 goto done; 1066 1067 if (outbuf->freeze_start || inbuf->freeze_start) { 1068 result = -1; 1069 goto done; 1070 } 1071 1072 if (PRESERVE_PINNED(inbuf, &pinned, &last) < 0) { 1073 result = -1; 1074 goto done; 1075 } 1076 1077 if (out_total_len == 0) { 1078 /* There might be an empty chain at the start of outbuf; free 1079 * it. */ 1080 evbuffer_free_all_chains(outbuf->first); 1081 COPY_CHAIN(outbuf, inbuf); 1082 } else { 1083 PREPEND_CHAIN(outbuf, inbuf); 1084 } 1085 1086 RESTORE_PINNED(inbuf, pinned, last); 1087 1088 inbuf->n_del_for_cb += in_total_len; 1089 outbuf->n_add_for_cb += in_total_len; 1090 1091 evbuffer_invoke_callbacks_(inbuf); 1092 evbuffer_invoke_callbacks_(outbuf); 1093 done: 1094 EVBUFFER_UNLOCK2(inbuf, outbuf); 1095 return result; 1096 } 1097 1098 int 1099 evbuffer_drain(struct evbuffer *buf, size_t len) 1100 { 1101 struct evbuffer_chain *chain, *next; 1102 size_t remaining, old_len; 1103 int result = 0; 1104 1105 EVBUFFER_LOCK(buf); 1106 old_len = buf->total_len; 1107 1108 if (old_len == 0) 1109 goto done; 1110 1111 if (buf->freeze_start) { 1112 result = -1; 1113 goto done; 1114 } 1115 1116 if (len >= old_len && !HAS_PINNED_R(buf)) { 1117 len = old_len; 1118 for (chain = buf->first; chain != NULL; chain = next) { 1119 next = chain->next; 1120 evbuffer_chain_free(chain); 1121 } 1122 1123 ZERO_CHAIN(buf); 1124 } else { 1125 if (len >= old_len) 1126 len = old_len; 1127 1128 buf->total_len -= len; 1129 remaining = len; 1130 for (chain = buf->first; 1131 remaining >= chain->off; 1132 chain = next) { 1133 next = chain->next; 1134 remaining -= chain->off; 1135 1136 if (chain == *buf->last_with_datap) { 1137 buf->last_with_datap = &buf->first; 1138 } 1139 if (&chain->next == buf->last_with_datap) 1140 buf->last_with_datap = &buf->first; 1141 1142 if (CHAIN_PINNED_R(chain)) { 1143 EVUTIL_ASSERT(remaining == 0); 1144 chain->misalign += chain->off; 1145 chain->off = 0; 1146 break; 1147 } else 1148 evbuffer_chain_free(chain); 1149 } 1150 1151 buf->first = chain; 1152 EVUTIL_ASSERT(chain && remaining <= chain->off); 1153 chain->misalign += remaining; 1154 chain->off -= remaining; 1155 } 1156 1157 buf->n_del_for_cb += len; 1158 /* Tell someone about changes in this buffer */ 1159 evbuffer_invoke_callbacks_(buf); 1160 1161 done: 1162 EVBUFFER_UNLOCK(buf); 1163 return result; 1164 } 1165 1166 /* Reads data from an event buffer and drains the bytes read */ 1167 int 1168 evbuffer_remove(struct evbuffer *buf, void *data_out, size_t datlen) 1169 { 1170 ev_ssize_t n; 1171 EVBUFFER_LOCK(buf); 1172 n = evbuffer_copyout_from(buf, NULL, data_out, datlen); 1173 if (n > 0) { 1174 if (evbuffer_drain(buf, n)<0) 1175 n = -1; 1176 } 1177 EVBUFFER_UNLOCK(buf); 1178 return (int)n; 1179 } 1180 1181 ev_ssize_t 1182 evbuffer_copyout(struct evbuffer *buf, void *data_out, size_t datlen) 1183 { 1184 return evbuffer_copyout_from(buf, NULL, data_out, datlen); 1185 } 1186 1187 ev_ssize_t 1188 evbuffer_copyout_from(struct evbuffer *buf, const struct evbuffer_ptr *pos, 1189 void *data_out, size_t datlen) 1190 { 1191 /*XXX fails badly on sendfile case. */ 1192 struct evbuffer_chain *chain; 1193 char *data = data_out; 1194 size_t nread; 1195 ev_ssize_t result = 0; 1196 size_t pos_in_chain; 1197 1198 EVBUFFER_LOCK(buf); 1199 1200 if (pos) { 1201 if (datlen > (size_t)(EV_SSIZE_MAX - pos->pos)) { 1202 result = -1; 1203 goto done; 1204 } 1205 chain = pos->internal_.chain; 1206 pos_in_chain = pos->internal_.pos_in_chain; 1207 if (datlen + pos->pos > buf->total_len) 1208 datlen = buf->total_len - pos->pos; 1209 } else { 1210 chain = buf->first; 1211 pos_in_chain = 0; 1212 if (datlen > buf->total_len) 1213 datlen = buf->total_len; 1214 } 1215 1216 1217 if (datlen == 0) 1218 goto done; 1219 1220 if (buf->freeze_start) { 1221 result = -1; 1222 goto done; 1223 } 1224 1225 nread = datlen; 1226 1227 while (datlen && datlen >= chain->off - pos_in_chain) { 1228 size_t copylen = chain->off - pos_in_chain; 1229 memcpy(data, 1230 chain->buffer + chain->misalign + pos_in_chain, 1231 copylen); 1232 data += copylen; 1233 datlen -= copylen; 1234 1235 chain = chain->next; 1236 pos_in_chain = 0; 1237 EVUTIL_ASSERT(chain || datlen==0); 1238 } 1239 1240 if (datlen) { 1241 EVUTIL_ASSERT(chain); 1242 EVUTIL_ASSERT(datlen+pos_in_chain <= chain->off); 1243 1244 memcpy(data, chain->buffer + chain->misalign + pos_in_chain, 1245 datlen); 1246 } 1247 1248 result = nread; 1249 done: 1250 EVBUFFER_UNLOCK(buf); 1251 return result; 1252 } 1253 1254 /* reads data from the src buffer to the dst buffer, avoids memcpy as 1255 * possible. */ 1256 /* XXXX should return ev_ssize_t */ 1257 int 1258 evbuffer_remove_buffer(struct evbuffer *src, struct evbuffer *dst, 1259 size_t datlen) 1260 { 1261 /*XXX We should have an option to force this to be zero-copy.*/ 1262 1263 /*XXX can fail badly on sendfile case. */ 1264 struct evbuffer_chain *chain, *previous; 1265 size_t nread = 0; 1266 int result; 1267 1268 EVBUFFER_LOCK2(src, dst); 1269 1270 chain = previous = src->first; 1271 1272 if (datlen == 0 || dst == src) { 1273 result = 0; 1274 goto done; 1275 } 1276 1277 if (dst->freeze_end || src->freeze_start) { 1278 result = -1; 1279 goto done; 1280 } 1281 1282 /* short-cut if there is no more data buffered */ 1283 if (datlen >= src->total_len) { 1284 datlen = src->total_len; 1285 evbuffer_add_buffer(dst, src); 1286 result = (int)datlen; /*XXXX should return ev_ssize_t*/ 1287 goto done; 1288 } 1289 1290 /* removes chains if possible */ 1291 while (chain->off <= datlen) { 1292 /* We can't remove the last with data from src unless we 1293 * remove all chains, in which case we would have done the if 1294 * block above */ 1295 EVUTIL_ASSERT(chain != *src->last_with_datap); 1296 nread += chain->off; 1297 datlen -= chain->off; 1298 previous = chain; 1299 if (src->last_with_datap == &chain->next) 1300 src->last_with_datap = &src->first; 1301 chain = chain->next; 1302 } 1303 1304 if (nread) { 1305 /* we can remove the chain */ 1306 struct evbuffer_chain **chp; 1307 chp = evbuffer_free_trailing_empty_chains(dst); 1308 1309 if (dst->first == NULL) { 1310 dst->first = src->first; 1311 } else { 1312 *chp = src->first; 1313 } 1314 dst->last = previous; 1315 previous->next = NULL; 1316 src->first = chain; 1317 advance_last_with_data(dst); 1318 1319 dst->total_len += nread; 1320 dst->n_add_for_cb += nread; 1321 } 1322 1323 /* we know that there is more data in the src buffer than 1324 * we want to read, so we manually drain the chain */ 1325 evbuffer_add(dst, chain->buffer + chain->misalign, datlen); 1326 chain->misalign += datlen; 1327 chain->off -= datlen; 1328 nread += datlen; 1329 1330 /* You might think we would want to increment dst->n_add_for_cb 1331 * here too. But evbuffer_add above already took care of that. 1332 */ 1333 src->total_len -= nread; 1334 src->n_del_for_cb += nread; 1335 1336 if (nread) { 1337 evbuffer_invoke_callbacks_(dst); 1338 evbuffer_invoke_callbacks_(src); 1339 } 1340 result = (int)nread;/*XXXX should change return type */ 1341 1342 done: 1343 EVBUFFER_UNLOCK2(src, dst); 1344 return result; 1345 } 1346 1347 unsigned char * 1348 evbuffer_pullup(struct evbuffer *buf, ev_ssize_t size) 1349 { 1350 struct evbuffer_chain *chain, *next, *tmp, *last_with_data; 1351 unsigned char *buffer, *result = NULL; 1352 ev_ssize_t remaining; 1353 int removed_last_with_data = 0; 1354 int removed_last_with_datap = 0; 1355 1356 EVBUFFER_LOCK(buf); 1357 1358 chain = buf->first; 1359 1360 if (size < 0) 1361 size = buf->total_len; 1362 /* if size > buf->total_len, we cannot guarantee to the user that she 1363 * is going to have a long enough buffer afterwards; so we return 1364 * NULL */ 1365 if (size == 0 || (size_t)size > buf->total_len) 1366 goto done; 1367 1368 /* No need to pull up anything; the first size bytes are 1369 * already here. */ 1370 if (chain->off >= (size_t)size) { 1371 result = chain->buffer + chain->misalign; 1372 goto done; 1373 } 1374 1375 /* Make sure that none of the chains we need to copy from is pinned. */ 1376 remaining = size - chain->off; 1377 EVUTIL_ASSERT(remaining >= 0); 1378 for (tmp=chain->next; tmp; tmp=tmp->next) { 1379 if (CHAIN_PINNED(tmp)) 1380 goto done; 1381 if (tmp->off >= (size_t)remaining) 1382 break; 1383 remaining -= tmp->off; 1384 } 1385 1386 if (CHAIN_PINNED(chain)) { 1387 size_t old_off = chain->off; 1388 if (CHAIN_SPACE_LEN(chain) < size - chain->off) { 1389 /* not enough room at end of chunk. */ 1390 goto done; 1391 } 1392 buffer = CHAIN_SPACE_PTR(chain); 1393 tmp = chain; 1394 tmp->off = size; 1395 size -= old_off; 1396 chain = chain->next; 1397 } else if (chain->buffer_len - chain->misalign >= (size_t)size) { 1398 /* already have enough space in the first chain */ 1399 size_t old_off = chain->off; 1400 buffer = chain->buffer + chain->misalign + chain->off; 1401 tmp = chain; 1402 tmp->off = size; 1403 size -= old_off; 1404 chain = chain->next; 1405 } else { 1406 if ((tmp = evbuffer_chain_new(size)) == NULL) { 1407 event_warn("%s: out of memory", __func__); 1408 goto done; 1409 } 1410 buffer = tmp->buffer; 1411 tmp->off = size; 1412 buf->first = tmp; 1413 } 1414 1415 /* TODO(niels): deal with buffers that point to NULL like sendfile */ 1416 1417 /* Copy and free every chunk that will be entirely pulled into tmp */ 1418 last_with_data = *buf->last_with_datap; 1419 for (; chain != NULL && (size_t)size >= chain->off; chain = next) { 1420 next = chain->next; 1421 1422 memcpy(buffer, chain->buffer + chain->misalign, chain->off); 1423 size -= chain->off; 1424 buffer += chain->off; 1425 if (chain == last_with_data) 1426 removed_last_with_data = 1; 1427 if (&chain->next == buf->last_with_datap) 1428 removed_last_with_datap = 1; 1429 1430 evbuffer_chain_free(chain); 1431 } 1432 1433 if (chain != NULL) { 1434 memcpy(buffer, chain->buffer + chain->misalign, size); 1435 chain->misalign += size; 1436 chain->off -= size; 1437 } else { 1438 buf->last = tmp; 1439 } 1440 1441 tmp->next = chain; 1442 1443 if (removed_last_with_data) { 1444 buf->last_with_datap = &buf->first; 1445 } else if (removed_last_with_datap) { 1446 if (buf->first->next && buf->first->next->off) 1447 buf->last_with_datap = &buf->first->next; 1448 else 1449 buf->last_with_datap = &buf->first; 1450 } 1451 1452 result = (tmp->buffer + tmp->misalign); 1453 1454 done: 1455 EVBUFFER_UNLOCK(buf); 1456 return result; 1457 } 1458 1459 /* 1460 * Reads a line terminated by either '\r\n', '\n\r' or '\r' or '\n'. 1461 * The returned buffer needs to be freed by the called. 1462 */ 1463 char * 1464 evbuffer_readline(struct evbuffer *buffer) 1465 { 1466 return evbuffer_readln(buffer, NULL, EVBUFFER_EOL_ANY); 1467 } 1468 1469 static inline ev_ssize_t 1470 evbuffer_strchr(struct evbuffer_ptr *it, const char chr) 1471 { 1472 struct evbuffer_chain *chain = it->internal_.chain; 1473 size_t i = it->internal_.pos_in_chain; 1474 while (chain != NULL) { 1475 char *buffer = (char *)chain->buffer + chain->misalign; 1476 char *cp = memchr(buffer+i, chr, chain->off-i); 1477 if (cp) { 1478 it->internal_.chain = chain; 1479 it->internal_.pos_in_chain = cp - buffer; 1480 it->pos += (cp - buffer - i); 1481 return it->pos; 1482 } 1483 it->pos += chain->off - i; 1484 i = 0; 1485 chain = chain->next; 1486 } 1487 1488 return (-1); 1489 } 1490 1491 static inline char * 1492 find_eol_char(char *s, size_t len) 1493 { 1494 #define CHUNK_SZ 128 1495 /* Lots of benchmarking found this approach to be faster in practice 1496 * than doing two memchrs over the whole buffer, doin a memchr on each 1497 * char of the buffer, or trying to emulate memchr by hand. */ 1498 char *s_end, *cr, *lf; 1499 s_end = s+len; 1500 while (s < s_end) { 1501 size_t chunk = (s + CHUNK_SZ < s_end) ? CHUNK_SZ : (s_end - s); 1502 cr = memchr(s, '\r', chunk); 1503 lf = memchr(s, '\n', chunk); 1504 if (cr) { 1505 if (lf && lf < cr) 1506 return lf; 1507 return cr; 1508 } else if (lf) { 1509 return lf; 1510 } 1511 s += CHUNK_SZ; 1512 } 1513 1514 return NULL; 1515 #undef CHUNK_SZ 1516 } 1517 1518 static ev_ssize_t 1519 evbuffer_find_eol_char(struct evbuffer_ptr *it) 1520 { 1521 struct evbuffer_chain *chain = it->internal_.chain; 1522 size_t i = it->internal_.pos_in_chain; 1523 while (chain != NULL) { 1524 char *buffer = (char *)chain->buffer + chain->misalign; 1525 char *cp = find_eol_char(buffer+i, chain->off-i); 1526 if (cp) { 1527 it->internal_.chain = chain; 1528 it->internal_.pos_in_chain = cp - buffer; 1529 it->pos += (cp - buffer) - i; 1530 return it->pos; 1531 } 1532 it->pos += chain->off - i; 1533 i = 0; 1534 chain = chain->next; 1535 } 1536 1537 return (-1); 1538 } 1539 1540 static inline int 1541 evbuffer_strspn( 1542 struct evbuffer_ptr *ptr, const char *chrset) 1543 { 1544 int count = 0; 1545 struct evbuffer_chain *chain = ptr->internal_.chain; 1546 size_t i = ptr->internal_.pos_in_chain; 1547 1548 if (!chain) 1549 return 0; 1550 1551 while (1) { 1552 char *buffer = (char *)chain->buffer + chain->misalign; 1553 for (; i < chain->off; ++i) { 1554 const char *p = chrset; 1555 while (*p) { 1556 if (buffer[i] == *p++) 1557 goto next; 1558 } 1559 ptr->internal_.chain = chain; 1560 ptr->internal_.pos_in_chain = i; 1561 ptr->pos += count; 1562 return count; 1563 next: 1564 ++count; 1565 } 1566 i = 0; 1567 1568 if (! chain->next) { 1569 ptr->internal_.chain = chain; 1570 ptr->internal_.pos_in_chain = i; 1571 ptr->pos += count; 1572 return count; 1573 } 1574 1575 chain = chain->next; 1576 } 1577 } 1578 1579 1580 static inline int 1581 evbuffer_getchr(struct evbuffer_ptr *it) 1582 { 1583 struct evbuffer_chain *chain = it->internal_.chain; 1584 size_t off = it->internal_.pos_in_chain; 1585 1586 if (chain == NULL) 1587 return -1; 1588 1589 return (unsigned char)chain->buffer[chain->misalign + off]; 1590 } 1591 1592 struct evbuffer_ptr 1593 evbuffer_search_eol(struct evbuffer *buffer, 1594 struct evbuffer_ptr *start, size_t *eol_len_out, 1595 enum evbuffer_eol_style eol_style) 1596 { 1597 struct evbuffer_ptr it, it2; 1598 size_t extra_drain = 0; 1599 int ok = 0; 1600 1601 /* Avoid locking in trivial edge cases */ 1602 if (start && start->internal_.chain == NULL) { 1603 PTR_NOT_FOUND(&it); 1604 if (eol_len_out) 1605 *eol_len_out = extra_drain; 1606 return it; 1607 } 1608 1609 EVBUFFER_LOCK(buffer); 1610 1611 if (start) { 1612 memcpy(&it, start, sizeof(it)); 1613 } else { 1614 it.pos = 0; 1615 it.internal_.chain = buffer->first; 1616 it.internal_.pos_in_chain = 0; 1617 } 1618 1619 /* the eol_style determines our first stop character and how many 1620 * characters we are going to drain afterwards. */ 1621 switch (eol_style) { 1622 case EVBUFFER_EOL_ANY: 1623 if (evbuffer_find_eol_char(&it) < 0) 1624 goto done; 1625 memcpy(&it2, &it, sizeof(it)); 1626 extra_drain = evbuffer_strspn(&it2, "\r\n"); 1627 break; 1628 case EVBUFFER_EOL_CRLF_STRICT: { 1629 it = evbuffer_search(buffer, "\r\n", 2, &it); 1630 if (it.pos < 0) 1631 goto done; 1632 extra_drain = 2; 1633 break; 1634 } 1635 case EVBUFFER_EOL_CRLF: { 1636 ev_ssize_t start_pos = it.pos; 1637 /* Look for a LF ... */ 1638 if (evbuffer_strchr(&it, '\n') < 0) 1639 goto done; 1640 extra_drain = 1; 1641 /* ... optionally preceeded by a CR. */ 1642 if (it.pos == start_pos) 1643 break; /* If the first character is \n, don't back up */ 1644 /* This potentially does an extra linear walk over the first 1645 * few chains. Probably, that's not too expensive unless you 1646 * have a really pathological setup. */ 1647 memcpy(&it2, &it, sizeof(it)); 1648 if (evbuffer_ptr_subtract(buffer, &it2, 1)<0) 1649 break; 1650 if (evbuffer_getchr(&it2) == '\r') { 1651 memcpy(&it, &it2, sizeof(it)); 1652 extra_drain = 2; 1653 } 1654 break; 1655 } 1656 case EVBUFFER_EOL_LF: 1657 if (evbuffer_strchr(&it, '\n') < 0) 1658 goto done; 1659 extra_drain = 1; 1660 break; 1661 case EVBUFFER_EOL_NUL: 1662 if (evbuffer_strchr(&it, '\0') < 0) 1663 goto done; 1664 extra_drain = 1; 1665 break; 1666 default: 1667 goto done; 1668 } 1669 1670 ok = 1; 1671 done: 1672 EVBUFFER_UNLOCK(buffer); 1673 1674 if (!ok) 1675 PTR_NOT_FOUND(&it); 1676 if (eol_len_out) 1677 *eol_len_out = extra_drain; 1678 1679 return it; 1680 } 1681 1682 char * 1683 evbuffer_readln(struct evbuffer *buffer, size_t *n_read_out, 1684 enum evbuffer_eol_style eol_style) 1685 { 1686 struct evbuffer_ptr it; 1687 char *line; 1688 size_t n_to_copy=0, extra_drain=0; 1689 char *result = NULL; 1690 1691 EVBUFFER_LOCK(buffer); 1692 1693 if (buffer->freeze_start) { 1694 goto done; 1695 } 1696 1697 it = evbuffer_search_eol(buffer, NULL, &extra_drain, eol_style); 1698 if (it.pos < 0) 1699 goto done; 1700 n_to_copy = it.pos; 1701 1702 if ((line = mm_malloc(n_to_copy+1)) == NULL) { 1703 event_warn("%s: out of memory", __func__); 1704 goto done; 1705 } 1706 1707 evbuffer_remove(buffer, line, n_to_copy); 1708 line[n_to_copy] = '\0'; 1709 1710 evbuffer_drain(buffer, extra_drain); 1711 result = line; 1712 done: 1713 EVBUFFER_UNLOCK(buffer); 1714 1715 if (n_read_out) 1716 *n_read_out = result ? n_to_copy : 0; 1717 1718 return result; 1719 } 1720 1721 #define EVBUFFER_CHAIN_MAX_AUTO_SIZE 4096 1722 1723 /* Adds data to an event buffer */ 1724 1725 int 1726 evbuffer_add(struct evbuffer *buf, const void *data_in, size_t datlen) 1727 { 1728 struct evbuffer_chain *chain, *tmp; 1729 const unsigned char *data = data_in; 1730 size_t remain, to_alloc; 1731 int result = -1; 1732 1733 EVBUFFER_LOCK(buf); 1734 1735 if (buf->freeze_end) { 1736 goto done; 1737 } 1738 /* Prevent buf->total_len overflow */ 1739 if (datlen > EV_SIZE_MAX - buf->total_len) { 1740 goto done; 1741 } 1742 1743 if (*buf->last_with_datap == NULL) { 1744 chain = buf->last; 1745 } else { 1746 chain = *buf->last_with_datap; 1747 } 1748 1749 /* If there are no chains allocated for this buffer, allocate one 1750 * big enough to hold all the data. */ 1751 if (chain == NULL) { 1752 chain = evbuffer_chain_new(datlen); 1753 if (!chain) 1754 goto done; 1755 evbuffer_chain_insert(buf, chain); 1756 } 1757 1758 if ((chain->flags & EVBUFFER_IMMUTABLE) == 0) { 1759 /* Always true for mutable buffers */ 1760 EVUTIL_ASSERT(chain->misalign >= 0 && 1761 (ev_uint64_t)chain->misalign <= EVBUFFER_CHAIN_MAX); 1762 remain = chain->buffer_len - (size_t)chain->misalign - chain->off; 1763 if (remain >= datlen) { 1764 /* there's enough space to hold all the data in the 1765 * current last chain */ 1766 memcpy(chain->buffer + chain->misalign + chain->off, 1767 data, datlen); 1768 chain->off += datlen; 1769 buf->total_len += datlen; 1770 buf->n_add_for_cb += datlen; 1771 goto out; 1772 } else if (!CHAIN_PINNED(chain) && 1773 evbuffer_chain_should_realign(chain, datlen)) { 1774 /* we can fit the data into the misalignment */ 1775 evbuffer_chain_align(chain); 1776 1777 memcpy(chain->buffer + chain->off, data, datlen); 1778 chain->off += datlen; 1779 buf->total_len += datlen; 1780 buf->n_add_for_cb += datlen; 1781 goto out; 1782 } 1783 } else { 1784 /* we cannot write any data to the last chain */ 1785 remain = 0; 1786 } 1787 1788 /* we need to add another chain */ 1789 to_alloc = chain->buffer_len; 1790 if (to_alloc <= EVBUFFER_CHAIN_MAX_AUTO_SIZE/2) 1791 to_alloc <<= 1; 1792 if (datlen > to_alloc) 1793 to_alloc = datlen; 1794 tmp = evbuffer_chain_new(to_alloc); 1795 if (tmp == NULL) 1796 goto done; 1797 1798 if (remain) { 1799 memcpy(chain->buffer + chain->misalign + chain->off, 1800 data, remain); 1801 chain->off += remain; 1802 buf->total_len += remain; 1803 buf->n_add_for_cb += remain; 1804 } 1805 1806 data += remain; 1807 datlen -= remain; 1808 1809 memcpy(tmp->buffer, data, datlen); 1810 tmp->off = datlen; 1811 evbuffer_chain_insert(buf, tmp); 1812 buf->n_add_for_cb += datlen; 1813 1814 out: 1815 evbuffer_invoke_callbacks_(buf); 1816 result = 0; 1817 done: 1818 EVBUFFER_UNLOCK(buf); 1819 return result; 1820 } 1821 1822 int 1823 evbuffer_prepend(struct evbuffer *buf, const void *data, size_t datlen) 1824 { 1825 struct evbuffer_chain *chain, *tmp; 1826 int result = -1; 1827 1828 EVBUFFER_LOCK(buf); 1829 1830 if (buf->freeze_start) { 1831 goto done; 1832 } 1833 if (datlen > EV_SIZE_MAX - buf->total_len) { 1834 goto done; 1835 } 1836 1837 chain = buf->first; 1838 1839 if (chain == NULL) { 1840 chain = evbuffer_chain_new(datlen); 1841 if (!chain) 1842 goto done; 1843 evbuffer_chain_insert(buf, chain); 1844 } 1845 1846 /* we cannot touch immutable buffers */ 1847 if ((chain->flags & EVBUFFER_IMMUTABLE) == 0) { 1848 /* Always true for mutable buffers */ 1849 EVUTIL_ASSERT(chain->misalign >= 0 && 1850 (ev_uint64_t)chain->misalign <= EVBUFFER_CHAIN_MAX); 1851 1852 /* If this chain is empty, we can treat it as 1853 * 'empty at the beginning' rather than 'empty at the end' */ 1854 if (chain->off == 0) 1855 chain->misalign = chain->buffer_len; 1856 1857 if ((size_t)chain->misalign >= datlen) { 1858 /* we have enough space to fit everything */ 1859 memcpy(chain->buffer + chain->misalign - datlen, 1860 data, datlen); 1861 chain->off += datlen; 1862 chain->misalign -= datlen; 1863 buf->total_len += datlen; 1864 buf->n_add_for_cb += datlen; 1865 goto out; 1866 } else if (chain->misalign) { 1867 /* we can only fit some of the data. */ 1868 memcpy(chain->buffer, 1869 (const char*)data + datlen - chain->misalign, 1870 (size_t)chain->misalign); 1871 chain->off += (size_t)chain->misalign; 1872 buf->total_len += (size_t)chain->misalign; 1873 buf->n_add_for_cb += (size_t)chain->misalign; 1874 datlen -= (size_t)chain->misalign; 1875 chain->misalign = 0; 1876 } 1877 } 1878 1879 /* we need to add another chain */ 1880 if ((tmp = evbuffer_chain_new(datlen)) == NULL) 1881 goto done; 1882 buf->first = tmp; 1883 if (buf->last_with_datap == &buf->first) 1884 buf->last_with_datap = &tmp->next; 1885 1886 tmp->next = chain; 1887 1888 tmp->off = datlen; 1889 EVUTIL_ASSERT(datlen <= tmp->buffer_len); 1890 tmp->misalign = tmp->buffer_len - datlen; 1891 1892 memcpy(tmp->buffer + tmp->misalign, data, datlen); 1893 buf->total_len += datlen; 1894 buf->n_add_for_cb += datlen; 1895 1896 out: 1897 evbuffer_invoke_callbacks_(buf); 1898 result = 0; 1899 done: 1900 EVBUFFER_UNLOCK(buf); 1901 return result; 1902 } 1903 1904 /** Helper: realigns the memory in chain->buffer so that misalign is 0. */ 1905 static void 1906 evbuffer_chain_align(struct evbuffer_chain *chain) 1907 { 1908 EVUTIL_ASSERT(!(chain->flags & EVBUFFER_IMMUTABLE)); 1909 EVUTIL_ASSERT(!(chain->flags & EVBUFFER_MEM_PINNED_ANY)); 1910 memmove(chain->buffer, chain->buffer + chain->misalign, chain->off); 1911 chain->misalign = 0; 1912 } 1913 1914 #define MAX_TO_COPY_IN_EXPAND 4096 1915 #define MAX_TO_REALIGN_IN_EXPAND 2048 1916 1917 /** Helper: return true iff we should realign chain to fit datalen bytes of 1918 data in it. */ 1919 static int 1920 evbuffer_chain_should_realign(struct evbuffer_chain *chain, 1921 size_t datlen) 1922 { 1923 return chain->buffer_len - chain->off >= datlen && 1924 (chain->off < chain->buffer_len / 2) && 1925 (chain->off <= MAX_TO_REALIGN_IN_EXPAND); 1926 } 1927 1928 /* Expands the available space in the event buffer to at least datlen, all in 1929 * a single chunk. Return that chunk. */ 1930 static struct evbuffer_chain * 1931 evbuffer_expand_singlechain(struct evbuffer *buf, size_t datlen) 1932 { 1933 struct evbuffer_chain *chain, **chainp; 1934 struct evbuffer_chain *result = NULL; 1935 ASSERT_EVBUFFER_LOCKED(buf); 1936 1937 chainp = buf->last_with_datap; 1938 1939 /* XXX If *chainp is no longer writeable, but has enough space in its 1940 * misalign, this might be a bad idea: we could still use *chainp, not 1941 * (*chainp)->next. */ 1942 if (*chainp && CHAIN_SPACE_LEN(*chainp) == 0) 1943 chainp = &(*chainp)->next; 1944 1945 /* 'chain' now points to the first chain with writable space (if any) 1946 * We will either use it, realign it, replace it, or resize it. */ 1947 chain = *chainp; 1948 1949 if (chain == NULL || 1950 (chain->flags & (EVBUFFER_IMMUTABLE|EVBUFFER_MEM_PINNED_ANY))) { 1951 /* We can't use the last_with_data chain at all. Just add a 1952 * new one that's big enough. */ 1953 goto insert_new; 1954 } 1955 1956 /* If we can fit all the data, then we don't have to do anything */ 1957 if (CHAIN_SPACE_LEN(chain) >= datlen) { 1958 result = chain; 1959 goto ok; 1960 } 1961 1962 /* If the chain is completely empty, just replace it by adding a new 1963 * empty chain. */ 1964 if (chain->off == 0) { 1965 goto insert_new; 1966 } 1967 1968 /* If the misalignment plus the remaining space fulfills our data 1969 * needs, we could just force an alignment to happen. Afterwards, we 1970 * have enough space. But only do this if we're saving a lot of space 1971 * and not moving too much data. Otherwise the space savings are 1972 * probably offset by the time lost in copying. 1973 */ 1974 if (evbuffer_chain_should_realign(chain, datlen)) { 1975 evbuffer_chain_align(chain); 1976 result = chain; 1977 goto ok; 1978 } 1979 1980 /* At this point, we can either resize the last chunk with space in 1981 * it, use the next chunk after it, or If we add a new chunk, we waste 1982 * CHAIN_SPACE_LEN(chain) bytes in the former last chunk. If we 1983 * resize, we have to copy chain->off bytes. 1984 */ 1985 1986 /* Would expanding this chunk be affordable and worthwhile? */ 1987 if (CHAIN_SPACE_LEN(chain) < chain->buffer_len / 8 || 1988 chain->off > MAX_TO_COPY_IN_EXPAND || 1989 datlen >= (EVBUFFER_CHAIN_MAX - chain->off)) { 1990 /* It's not worth resizing this chain. Can the next one be 1991 * used? */ 1992 if (chain->next && CHAIN_SPACE_LEN(chain->next) >= datlen) { 1993 /* Yes, we can just use the next chain (which should 1994 * be empty. */ 1995 result = chain->next; 1996 goto ok; 1997 } else { 1998 /* No; append a new chain (which will free all 1999 * terminal empty chains.) */ 2000 goto insert_new; 2001 } 2002 } else { 2003 /* Okay, we're going to try to resize this chain: Not doing so 2004 * would waste at least 1/8 of its current allocation, and we 2005 * can do so without having to copy more than 2006 * MAX_TO_COPY_IN_EXPAND bytes. */ 2007 /* figure out how much space we need */ 2008 size_t length = chain->off + datlen; 2009 struct evbuffer_chain *tmp = evbuffer_chain_new(length); 2010 if (tmp == NULL) 2011 goto err; 2012 2013 /* copy the data over that we had so far */ 2014 tmp->off = chain->off; 2015 memcpy(tmp->buffer, chain->buffer + chain->misalign, 2016 chain->off); 2017 /* fix up the list */ 2018 EVUTIL_ASSERT(*chainp == chain); 2019 result = *chainp = tmp; 2020 2021 if (buf->last == chain) 2022 buf->last = tmp; 2023 2024 tmp->next = chain->next; 2025 evbuffer_chain_free(chain); 2026 goto ok; 2027 } 2028 2029 insert_new: 2030 result = evbuffer_chain_insert_new(buf, datlen); 2031 if (!result) 2032 goto err; 2033 ok: 2034 EVUTIL_ASSERT(result); 2035 EVUTIL_ASSERT(CHAIN_SPACE_LEN(result) >= datlen); 2036 err: 2037 return result; 2038 } 2039 2040 /* Make sure that datlen bytes are available for writing in the last n 2041 * chains. Never copies or moves data. */ 2042 int 2043 evbuffer_expand_fast_(struct evbuffer *buf, size_t datlen, int n) 2044 { 2045 struct evbuffer_chain *chain = buf->last, *tmp, *next; 2046 size_t avail; 2047 int used; 2048 2049 ASSERT_EVBUFFER_LOCKED(buf); 2050 EVUTIL_ASSERT(n >= 2); 2051 2052 if (chain == NULL || (chain->flags & EVBUFFER_IMMUTABLE)) { 2053 /* There is no last chunk, or we can't touch the last chunk. 2054 * Just add a new chunk. */ 2055 chain = evbuffer_chain_new(datlen); 2056 if (chain == NULL) 2057 return (-1); 2058 2059 evbuffer_chain_insert(buf, chain); 2060 return (0); 2061 } 2062 2063 used = 0; /* number of chains we're using space in. */ 2064 avail = 0; /* how much space they have. */ 2065 /* How many bytes can we stick at the end of buffer as it is? Iterate 2066 * over the chains at the end of the buffer, tring to see how much 2067 * space we have in the first n. */ 2068 for (chain = *buf->last_with_datap; chain; chain = chain->next) { 2069 if (chain->off) { 2070 size_t space = (size_t) CHAIN_SPACE_LEN(chain); 2071 EVUTIL_ASSERT(chain == *buf->last_with_datap); 2072 if (space) { 2073 avail += space; 2074 ++used; 2075 } 2076 } else { 2077 /* No data in chain; realign it. */ 2078 chain->misalign = 0; 2079 avail += chain->buffer_len; 2080 ++used; 2081 } 2082 if (avail >= datlen) { 2083 /* There is already enough space. Just return */ 2084 return (0); 2085 } 2086 if (used == n) 2087 break; 2088 } 2089 2090 /* There wasn't enough space in the first n chains with space in 2091 * them. Either add a new chain with enough space, or replace all 2092 * empty chains with one that has enough space, depending on n. */ 2093 if (used < n) { 2094 /* The loop ran off the end of the chains before it hit n 2095 * chains; we can add another. */ 2096 EVUTIL_ASSERT(chain == NULL); 2097 2098 tmp = evbuffer_chain_new(datlen - avail); 2099 if (tmp == NULL) 2100 return (-1); 2101 2102 buf->last->next = tmp; 2103 buf->last = tmp; 2104 /* (we would only set last_with_data if we added the first 2105 * chain. But if the buffer had no chains, we would have 2106 * just allocated a new chain earlier) */ 2107 return (0); 2108 } else { 2109 /* Nuke _all_ the empty chains. */ 2110 int rmv_all = 0; /* True iff we removed last_with_data. */ 2111 chain = *buf->last_with_datap; 2112 if (!chain->off) { 2113 EVUTIL_ASSERT(chain == buf->first); 2114 rmv_all = 1; 2115 avail = 0; 2116 } else { 2117 /* can't overflow, since only mutable chains have 2118 * huge misaligns. */ 2119 avail = (size_t) CHAIN_SPACE_LEN(chain); 2120 chain = chain->next; 2121 } 2122 2123 2124 for (; chain; chain = next) { 2125 next = chain->next; 2126 EVUTIL_ASSERT(chain->off == 0); 2127 evbuffer_chain_free(chain); 2128 } 2129 EVUTIL_ASSERT(datlen >= avail); 2130 tmp = evbuffer_chain_new(datlen - avail); 2131 if (tmp == NULL) { 2132 if (rmv_all) { 2133 ZERO_CHAIN(buf); 2134 } else { 2135 buf->last = *buf->last_with_datap; 2136 (*buf->last_with_datap)->next = NULL; 2137 } 2138 return (-1); 2139 } 2140 2141 if (rmv_all) { 2142 buf->first = buf->last = tmp; 2143 buf->last_with_datap = &buf->first; 2144 } else { 2145 (*buf->last_with_datap)->next = tmp; 2146 buf->last = tmp; 2147 } 2148 return (0); 2149 } 2150 } 2151 2152 int 2153 evbuffer_expand(struct evbuffer *buf, size_t datlen) 2154 { 2155 struct evbuffer_chain *chain; 2156 2157 EVBUFFER_LOCK(buf); 2158 chain = evbuffer_expand_singlechain(buf, datlen); 2159 EVBUFFER_UNLOCK(buf); 2160 return chain ? 0 : -1; 2161 } 2162 2163 /* 2164 * Reads data from a file descriptor into a buffer. 2165 */ 2166 2167 #if defined(EVENT__HAVE_SYS_UIO_H) || defined(_WIN32) 2168 #define USE_IOVEC_IMPL 2169 #endif 2170 2171 #ifdef USE_IOVEC_IMPL 2172 2173 #ifdef EVENT__HAVE_SYS_UIO_H 2174 /* number of iovec we use for writev, fragmentation is going to determine 2175 * how much we end up writing */ 2176 2177 #define DEFAULT_WRITE_IOVEC 128 2178 2179 #if defined(UIO_MAXIOV) && UIO_MAXIOV < DEFAULT_WRITE_IOVEC 2180 #define NUM_WRITE_IOVEC UIO_MAXIOV 2181 #elif defined(IOV_MAX) && IOV_MAX < DEFAULT_WRITE_IOVEC 2182 #define NUM_WRITE_IOVEC IOV_MAX 2183 #else 2184 #define NUM_WRITE_IOVEC DEFAULT_WRITE_IOVEC 2185 #endif 2186 2187 #define IOV_TYPE struct iovec 2188 #define IOV_PTR_FIELD iov_base 2189 #define IOV_LEN_FIELD iov_len 2190 #define IOV_LEN_TYPE size_t 2191 #else 2192 #define NUM_WRITE_IOVEC 16 2193 #define IOV_TYPE WSABUF 2194 #define IOV_PTR_FIELD buf 2195 #define IOV_LEN_FIELD len 2196 #define IOV_LEN_TYPE unsigned long 2197 #endif 2198 #endif 2199 #define NUM_READ_IOVEC 4 2200 2201 #define EVBUFFER_MAX_READ 4096 2202 2203 /** Helper function to figure out which space to use for reading data into 2204 an evbuffer. Internal use only. 2205 2206 @param buf The buffer to read into 2207 @param howmuch How much we want to read. 2208 @param vecs An array of two or more iovecs or WSABUFs. 2209 @param n_vecs_avail The length of vecs 2210 @param chainp A pointer to a variable to hold the first chain we're 2211 reading into. 2212 @param exact Boolean: if true, we do not provide more than 'howmuch' 2213 space in the vectors, even if more space is available. 2214 @return The number of buffers we're using. 2215 */ 2216 int 2217 evbuffer_read_setup_vecs_(struct evbuffer *buf, ev_ssize_t howmuch, 2218 struct evbuffer_iovec *vecs, int n_vecs_avail, 2219 struct evbuffer_chain ***chainp, int exact) 2220 { 2221 struct evbuffer_chain *chain; 2222 struct evbuffer_chain **firstchainp; 2223 size_t so_far; 2224 int i; 2225 ASSERT_EVBUFFER_LOCKED(buf); 2226 2227 if (howmuch < 0) 2228 return -1; 2229 2230 so_far = 0; 2231 /* Let firstchain be the first chain with any space on it */ 2232 firstchainp = buf->last_with_datap; 2233 if (CHAIN_SPACE_LEN(*firstchainp) == 0) { 2234 firstchainp = &(*firstchainp)->next; 2235 } 2236 2237 chain = *firstchainp; 2238 for (i = 0; i < n_vecs_avail && so_far < (size_t)howmuch; ++i) { 2239 size_t avail = (size_t) CHAIN_SPACE_LEN(chain); 2240 if (avail > (howmuch - so_far) && exact) 2241 avail = howmuch - so_far; 2242 vecs[i].iov_base = (void *)CHAIN_SPACE_PTR(chain); 2243 vecs[i].iov_len = avail; 2244 so_far += avail; 2245 chain = chain->next; 2246 } 2247 2248 *chainp = firstchainp; 2249 return i; 2250 } 2251 2252 static int 2253 get_n_bytes_readable_on_socket(evutil_socket_t fd) 2254 { 2255 #if defined(FIONREAD) && defined(_WIN32) 2256 unsigned long lng = EVBUFFER_MAX_READ; 2257 if (ioctlsocket(fd, FIONREAD, &lng) < 0) 2258 return -1; 2259 /* Can overflow, but mostly harmlessly. XXXX */ 2260 return (int)lng; 2261 #elif defined(FIONREAD) 2262 int n = EVBUFFER_MAX_READ; 2263 if (ioctl(fd, FIONREAD, &n) < 0) 2264 return -1; 2265 return n; 2266 #else 2267 return EVBUFFER_MAX_READ; 2268 #endif 2269 } 2270 2271 /* TODO(niels): should this function return ev_ssize_t and take ev_ssize_t 2272 * as howmuch? */ 2273 int 2274 evbuffer_read(struct evbuffer *buf, evutil_socket_t fd, int howmuch) 2275 { 2276 struct evbuffer_chain **chainp; 2277 int n; 2278 int result; 2279 2280 #ifdef USE_IOVEC_IMPL 2281 int nvecs, i, remaining; 2282 #else 2283 struct evbuffer_chain *chain; 2284 unsigned char *p; 2285 #endif 2286 2287 EVBUFFER_LOCK(buf); 2288 2289 if (buf->freeze_end) { 2290 result = -1; 2291 goto done; 2292 } 2293 2294 n = get_n_bytes_readable_on_socket(fd); 2295 if (n <= 0 || n > EVBUFFER_MAX_READ) 2296 n = EVBUFFER_MAX_READ; 2297 if (howmuch < 0 || howmuch > n) 2298 howmuch = n; 2299 2300 #ifdef USE_IOVEC_IMPL 2301 /* Since we can use iovecs, we're willing to use the last 2302 * NUM_READ_IOVEC chains. */ 2303 if (evbuffer_expand_fast_(buf, howmuch, NUM_READ_IOVEC) == -1) { 2304 result = -1; 2305 goto done; 2306 } else { 2307 IOV_TYPE vecs[NUM_READ_IOVEC]; 2308 #ifdef EVBUFFER_IOVEC_IS_NATIVE_ 2309 nvecs = evbuffer_read_setup_vecs_(buf, howmuch, vecs, 2310 NUM_READ_IOVEC, &chainp, 1); 2311 #else 2312 /* We aren't using the native struct iovec. Therefore, 2313 we are on win32. */ 2314 struct evbuffer_iovec ev_vecs[NUM_READ_IOVEC]; 2315 nvecs = evbuffer_read_setup_vecs_(buf, howmuch, ev_vecs, 2, 2316 &chainp, 1); 2317 2318 for (i=0; i < nvecs; ++i) 2319 WSABUF_FROM_EVBUFFER_IOV(&vecs[i], &ev_vecs[i]); 2320 #endif 2321 2322 #ifdef _WIN32 2323 { 2324 DWORD bytesRead; 2325 DWORD flags=0; 2326 if (WSARecv(fd, vecs, nvecs, &bytesRead, &flags, NULL, NULL)) { 2327 /* The read failed. It might be a close, 2328 * or it might be an error. */ 2329 if (WSAGetLastError() == WSAECONNABORTED) 2330 n = 0; 2331 else 2332 n = -1; 2333 } else 2334 n = bytesRead; 2335 } 2336 #else 2337 n = readv(fd, vecs, nvecs); 2338 #endif 2339 } 2340 2341 #else /*!USE_IOVEC_IMPL*/ 2342 /* If we don't have FIONREAD, we might waste some space here */ 2343 /* XXX we _will_ waste some space here if there is any space left 2344 * over on buf->last. */ 2345 if ((chain = evbuffer_expand_singlechain(buf, howmuch)) == NULL) { 2346 result = -1; 2347 goto done; 2348 } 2349 2350 /* We can append new data at this point */ 2351 p = chain->buffer + chain->misalign + chain->off; 2352 2353 #ifndef _WIN32 2354 n = read(fd, p, howmuch); 2355 #else 2356 n = recv(fd, p, howmuch, 0); 2357 #endif 2358 #endif /* USE_IOVEC_IMPL */ 2359 2360 if (n == -1) { 2361 result = -1; 2362 goto done; 2363 } 2364 if (n == 0) { 2365 result = 0; 2366 goto done; 2367 } 2368 2369 #ifdef USE_IOVEC_IMPL 2370 remaining = n; 2371 for (i=0; i < nvecs; ++i) { 2372 /* can't overflow, since only mutable chains have 2373 * huge misaligns. */ 2374 size_t space = (size_t) CHAIN_SPACE_LEN(*chainp); 2375 /* XXXX This is a kludge that can waste space in perverse 2376 * situations. */ 2377 if (space > EVBUFFER_CHAIN_MAX) 2378 space = EVBUFFER_CHAIN_MAX; 2379 if ((ev_ssize_t)space < remaining) { 2380 (*chainp)->off += space; 2381 remaining -= (int)space; 2382 } else { 2383 (*chainp)->off += remaining; 2384 buf->last_with_datap = chainp; 2385 break; 2386 } 2387 chainp = &(*chainp)->next; 2388 } 2389 #else 2390 chain->off += n; 2391 advance_last_with_data(buf); 2392 #endif 2393 buf->total_len += n; 2394 buf->n_add_for_cb += n; 2395 2396 /* Tell someone about changes in this buffer */ 2397 evbuffer_invoke_callbacks_(buf); 2398 result = n; 2399 done: 2400 EVBUFFER_UNLOCK(buf); 2401 return result; 2402 } 2403 2404 #ifdef USE_IOVEC_IMPL 2405 static inline int 2406 evbuffer_write_iovec(struct evbuffer *buffer, evutil_socket_t fd, 2407 ev_ssize_t howmuch) 2408 { 2409 IOV_TYPE iov[NUM_WRITE_IOVEC]; 2410 struct evbuffer_chain *chain = buffer->first; 2411 int n, i = 0; 2412 2413 if (howmuch < 0) 2414 return -1; 2415 2416 ASSERT_EVBUFFER_LOCKED(buffer); 2417 /* XXX make this top out at some maximal data length? if the 2418 * buffer has (say) 1MB in it, split over 128 chains, there's 2419 * no way it all gets written in one go. */ 2420 while (chain != NULL && i < NUM_WRITE_IOVEC && howmuch) { 2421 #ifdef USE_SENDFILE 2422 /* we cannot write the file info via writev */ 2423 if (chain->flags & EVBUFFER_SENDFILE) 2424 break; 2425 #endif 2426 iov[i].IOV_PTR_FIELD = (void *) (chain->buffer + chain->misalign); 2427 if ((size_t)howmuch >= chain->off) { 2428 /* XXXcould be problematic when windows supports mmap*/ 2429 iov[i++].IOV_LEN_FIELD = (IOV_LEN_TYPE)chain->off; 2430 howmuch -= chain->off; 2431 } else { 2432 /* XXXcould be problematic when windows supports mmap*/ 2433 iov[i++].IOV_LEN_FIELD = (IOV_LEN_TYPE)howmuch; 2434 break; 2435 } 2436 chain = chain->next; 2437 } 2438 if (! i) 2439 return 0; 2440 2441 #ifdef _WIN32 2442 { 2443 DWORD bytesSent; 2444 if (WSASend(fd, iov, i, &bytesSent, 0, NULL, NULL)) 2445 n = -1; 2446 else 2447 n = bytesSent; 2448 } 2449 #else 2450 n = writev(fd, iov, i); 2451 #endif 2452 return (n); 2453 } 2454 #endif 2455 2456 #ifdef USE_SENDFILE 2457 static inline int 2458 evbuffer_write_sendfile(struct evbuffer *buffer, evutil_socket_t dest_fd, 2459 ev_ssize_t howmuch) 2460 { 2461 struct evbuffer_chain *chain = buffer->first; 2462 struct evbuffer_chain_file_segment *info = 2463 EVBUFFER_CHAIN_EXTRA(struct evbuffer_chain_file_segment, 2464 chain); 2465 const int source_fd = info->segment->fd; 2466 #if defined(SENDFILE_IS_MACOSX) || defined(SENDFILE_IS_FREEBSD) 2467 int res; 2468 ev_off_t len = chain->off; 2469 #elif defined(SENDFILE_IS_LINUX) || defined(SENDFILE_IS_SOLARIS) 2470 ev_ssize_t res; 2471 ev_off_t offset = chain->misalign; 2472 #endif 2473 2474 ASSERT_EVBUFFER_LOCKED(buffer); 2475 2476 #if defined(SENDFILE_IS_MACOSX) 2477 res = sendfile(source_fd, dest_fd, chain->misalign, &len, NULL, 0); 2478 if (res == -1 && !EVUTIL_ERR_RW_RETRIABLE(errno)) 2479 return (-1); 2480 2481 return (len); 2482 #elif defined(SENDFILE_IS_FREEBSD) 2483 res = sendfile(source_fd, dest_fd, chain->misalign, chain->off, NULL, &len, 0); 2484 if (res == -1 && !EVUTIL_ERR_RW_RETRIABLE(errno)) 2485 return (-1); 2486 2487 return (len); 2488 #elif defined(SENDFILE_IS_LINUX) 2489 /* TODO(niels): implement splice */ 2490 res = sendfile(dest_fd, source_fd, &offset, chain->off); 2491 if (res == -1 && EVUTIL_ERR_RW_RETRIABLE(errno)) { 2492 /* if this is EAGAIN or EINTR return 0; otherwise, -1 */ 2493 return (0); 2494 } 2495 return (res); 2496 #elif defined(SENDFILE_IS_SOLARIS) 2497 { 2498 const off_t offset_orig = offset; 2499 res = sendfile(dest_fd, source_fd, &offset, chain->off); 2500 if (res == -1 && EVUTIL_ERR_RW_RETRIABLE(errno)) { 2501 if (offset - offset_orig) 2502 return offset - offset_orig; 2503 /* if this is EAGAIN or EINTR and no bytes were 2504 * written, return 0 */ 2505 return (0); 2506 } 2507 return (res); 2508 } 2509 #endif 2510 } 2511 #endif 2512 2513 int 2514 evbuffer_write_atmost(struct evbuffer *buffer, evutil_socket_t fd, 2515 ev_ssize_t howmuch) 2516 { 2517 int n = -1; 2518 2519 EVBUFFER_LOCK(buffer); 2520 2521 if (buffer->freeze_start) { 2522 goto done; 2523 } 2524 2525 if (howmuch < 0 || (size_t)howmuch > buffer->total_len) 2526 howmuch = buffer->total_len; 2527 2528 if (howmuch > 0) { 2529 #ifdef USE_SENDFILE 2530 struct evbuffer_chain *chain = buffer->first; 2531 if (chain != NULL && (chain->flags & EVBUFFER_SENDFILE)) 2532 n = evbuffer_write_sendfile(buffer, fd, howmuch); 2533 else { 2534 #endif 2535 #ifdef USE_IOVEC_IMPL 2536 n = evbuffer_write_iovec(buffer, fd, howmuch); 2537 #elif defined(_WIN32) 2538 /* XXX(nickm) Don't disable this code until we know if 2539 * the WSARecv code above works. */ 2540 void *p = evbuffer_pullup(buffer, howmuch); 2541 EVUTIL_ASSERT(p || !howmuch); 2542 n = send(fd, p, howmuch, 0); 2543 #else 2544 void *p = evbuffer_pullup(buffer, howmuch); 2545 EVUTIL_ASSERT(p || !howmuch); 2546 n = write(fd, p, howmuch); 2547 #endif 2548 #ifdef USE_SENDFILE 2549 } 2550 #endif 2551 } 2552 2553 if (n > 0) 2554 evbuffer_drain(buffer, n); 2555 2556 done: 2557 EVBUFFER_UNLOCK(buffer); 2558 return (n); 2559 } 2560 2561 int 2562 evbuffer_write(struct evbuffer *buffer, evutil_socket_t fd) 2563 { 2564 return evbuffer_write_atmost(buffer, fd, -1); 2565 } 2566 2567 unsigned char * 2568 evbuffer_find(struct evbuffer *buffer, const unsigned char *what, size_t len) 2569 { 2570 unsigned char *search; 2571 struct evbuffer_ptr ptr; 2572 2573 EVBUFFER_LOCK(buffer); 2574 2575 ptr = evbuffer_search(buffer, (const char *)what, len, NULL); 2576 if (ptr.pos < 0) { 2577 search = NULL; 2578 } else { 2579 search = evbuffer_pullup(buffer, ptr.pos + len); 2580 if (search) 2581 search += ptr.pos; 2582 } 2583 EVBUFFER_UNLOCK(buffer); 2584 return search; 2585 } 2586 2587 /* Subract <b>howfar</b> from the position of <b>pos</b> within 2588 * <b>buf</b>. Returns 0 on success, -1 on failure. 2589 * 2590 * This isn't exposed yet, because of potential inefficiency issues. 2591 * Maybe it should be. */ 2592 static int 2593 evbuffer_ptr_subtract(struct evbuffer *buf, struct evbuffer_ptr *pos, 2594 size_t howfar) 2595 { 2596 if (pos->pos < 0) 2597 return -1; 2598 if (howfar > (size_t)pos->pos) 2599 return -1; 2600 if (pos->internal_.chain && howfar <= pos->internal_.pos_in_chain) { 2601 pos->internal_.pos_in_chain -= howfar; 2602 pos->pos -= howfar; 2603 return 0; 2604 } else { 2605 const size_t newpos = pos->pos - howfar; 2606 /* Here's the inefficient part: it walks over the 2607 * chains until we hit newpos. */ 2608 return evbuffer_ptr_set(buf, pos, newpos, EVBUFFER_PTR_SET); 2609 } 2610 } 2611 2612 int 2613 evbuffer_ptr_set(struct evbuffer *buf, struct evbuffer_ptr *pos, 2614 size_t position, enum evbuffer_ptr_how how) 2615 { 2616 size_t left = position; 2617 struct evbuffer_chain *chain = NULL; 2618 int result = 0; 2619 2620 EVBUFFER_LOCK(buf); 2621 2622 switch (how) { 2623 case EVBUFFER_PTR_SET: 2624 chain = buf->first; 2625 pos->pos = position; 2626 position = 0; 2627 break; 2628 case EVBUFFER_PTR_ADD: 2629 /* this avoids iterating over all previous chains if 2630 we just want to advance the position */ 2631 if (pos->pos < 0 || EV_SIZE_MAX - position < (size_t)pos->pos) { 2632 EVBUFFER_UNLOCK(buf); 2633 return -1; 2634 } 2635 chain = pos->internal_.chain; 2636 pos->pos += position; 2637 position = pos->internal_.pos_in_chain; 2638 break; 2639 } 2640 2641 EVUTIL_ASSERT(EV_SIZE_MAX - left >= position); 2642 while (chain && position + left >= chain->off) { 2643 left -= chain->off - position; 2644 chain = chain->next; 2645 position = 0; 2646 } 2647 if (chain) { 2648 pos->internal_.chain = chain; 2649 pos->internal_.pos_in_chain = position + left; 2650 } else if (left == 0) { 2651 /* The first byte in the (nonexistent) chain after the last chain */ 2652 pos->internal_.chain = NULL; 2653 pos->internal_.pos_in_chain = 0; 2654 } else { 2655 PTR_NOT_FOUND(pos); 2656 result = -1; 2657 } 2658 2659 EVBUFFER_UNLOCK(buf); 2660 2661 return result; 2662 } 2663 2664 /** 2665 Compare the bytes in buf at position pos to the len bytes in mem. Return 2666 less than 0, 0, or greater than 0 as memcmp. 2667 */ 2668 static int 2669 evbuffer_ptr_memcmp(const struct evbuffer *buf, const struct evbuffer_ptr *pos, 2670 const char *mem, size_t len) 2671 { 2672 struct evbuffer_chain *chain; 2673 size_t position; 2674 int r; 2675 2676 ASSERT_EVBUFFER_LOCKED(buf); 2677 2678 if (pos->pos < 0 || 2679 EV_SIZE_MAX - len < (size_t)pos->pos || 2680 pos->pos + len > buf->total_len) 2681 return -1; 2682 2683 chain = pos->internal_.chain; 2684 position = pos->internal_.pos_in_chain; 2685 while (len && chain) { 2686 size_t n_comparable; 2687 if (len + position > chain->off) 2688 n_comparable = chain->off - position; 2689 else 2690 n_comparable = len; 2691 r = memcmp(chain->buffer + chain->misalign + position, mem, 2692 n_comparable); 2693 if (r) 2694 return r; 2695 mem += n_comparable; 2696 len -= n_comparable; 2697 position = 0; 2698 chain = chain->next; 2699 } 2700 2701 return 0; 2702 } 2703 2704 struct evbuffer_ptr 2705 evbuffer_search(struct evbuffer *buffer, const char *what, size_t len, const struct evbuffer_ptr *start) 2706 { 2707 return evbuffer_search_range(buffer, what, len, start, NULL); 2708 } 2709 2710 struct evbuffer_ptr 2711 evbuffer_search_range(struct evbuffer *buffer, const char *what, size_t len, const struct evbuffer_ptr *start, const struct evbuffer_ptr *end) 2712 { 2713 struct evbuffer_ptr pos; 2714 struct evbuffer_chain *chain, *last_chain = NULL; 2715 const unsigned char *p; 2716 char first; 2717 2718 EVBUFFER_LOCK(buffer); 2719 2720 if (start) { 2721 memcpy(&pos, start, sizeof(pos)); 2722 chain = pos.internal_.chain; 2723 } else { 2724 pos.pos = 0; 2725 chain = pos.internal_.chain = buffer->first; 2726 pos.internal_.pos_in_chain = 0; 2727 } 2728 2729 if (end) 2730 last_chain = end->internal_.chain; 2731 2732 if (!len || len > EV_SSIZE_MAX) 2733 goto done; 2734 2735 first = what[0]; 2736 2737 while (chain) { 2738 const unsigned char *start_at = 2739 chain->buffer + chain->misalign + 2740 pos.internal_.pos_in_chain; 2741 p = memchr(start_at, first, 2742 chain->off - pos.internal_.pos_in_chain); 2743 if (p) { 2744 pos.pos += p - start_at; 2745 pos.internal_.pos_in_chain += p - start_at; 2746 if (!evbuffer_ptr_memcmp(buffer, &pos, what, len)) { 2747 if (end && pos.pos + (ev_ssize_t)len > end->pos) 2748 goto not_found; 2749 else 2750 goto done; 2751 } 2752 ++pos.pos; 2753 ++pos.internal_.pos_in_chain; 2754 if (pos.internal_.pos_in_chain == chain->off) { 2755 chain = pos.internal_.chain = chain->next; 2756 pos.internal_.pos_in_chain = 0; 2757 } 2758 } else { 2759 if (chain == last_chain) 2760 goto not_found; 2761 pos.pos += chain->off - pos.internal_.pos_in_chain; 2762 chain = pos.internal_.chain = chain->next; 2763 pos.internal_.pos_in_chain = 0; 2764 } 2765 } 2766 2767 not_found: 2768 PTR_NOT_FOUND(&pos); 2769 done: 2770 EVBUFFER_UNLOCK(buffer); 2771 return pos; 2772 } 2773 2774 int 2775 evbuffer_peek(struct evbuffer *buffer, ev_ssize_t len, 2776 struct evbuffer_ptr *start_at, 2777 struct evbuffer_iovec *vec, int n_vec) 2778 { 2779 struct evbuffer_chain *chain; 2780 int idx = 0; 2781 ev_ssize_t len_so_far = 0; 2782 2783 /* Avoid locking in trivial edge cases */ 2784 if (start_at && start_at->internal_.chain == NULL) 2785 return 0; 2786 2787 EVBUFFER_LOCK(buffer); 2788 2789 if (start_at) { 2790 chain = start_at->internal_.chain; 2791 len_so_far = chain->off 2792 - start_at->internal_.pos_in_chain; 2793 idx = 1; 2794 if (n_vec > 0) { 2795 vec[0].iov_base = (void *)(chain->buffer + chain->misalign 2796 + start_at->internal_.pos_in_chain); 2797 vec[0].iov_len = len_so_far; 2798 } 2799 chain = chain->next; 2800 } else { 2801 chain = buffer->first; 2802 } 2803 2804 if (n_vec == 0 && len < 0) { 2805 /* If no vectors are provided and they asked for "everything", 2806 * pretend they asked for the actual available amount. */ 2807 len = buffer->total_len; 2808 if (start_at) { 2809 len -= start_at->pos; 2810 } 2811 } 2812 2813 while (chain) { 2814 if (len >= 0 && len_so_far >= len) 2815 break; 2816 if (idx<n_vec) { 2817 vec[idx].iov_base = (void *)(chain->buffer + chain->misalign); 2818 vec[idx].iov_len = chain->off; 2819 } else if (len<0) { 2820 break; 2821 } 2822 ++idx; 2823 len_so_far += chain->off; 2824 chain = chain->next; 2825 } 2826 2827 EVBUFFER_UNLOCK(buffer); 2828 2829 return idx; 2830 } 2831 2832 2833 int 2834 evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap) 2835 { 2836 char *buffer; 2837 size_t space; 2838 int sz, result = -1; 2839 va_list aq; 2840 struct evbuffer_chain *chain; 2841 2842 2843 EVBUFFER_LOCK(buf); 2844 2845 if (buf->freeze_end) { 2846 goto done; 2847 } 2848 2849 /* make sure that at least some space is available */ 2850 if ((chain = evbuffer_expand_singlechain(buf, 64)) == NULL) 2851 goto done; 2852 2853 for (;;) { 2854 #if 0 2855 size_t used = chain->misalign + chain->off; 2856 buffer = (char *)chain->buffer + chain->misalign + chain->off; 2857 EVUTIL_ASSERT(chain->buffer_len >= used); 2858 space = chain->buffer_len - used; 2859 #endif 2860 buffer = (char*) CHAIN_SPACE_PTR(chain); 2861 space = (size_t) CHAIN_SPACE_LEN(chain); 2862 2863 #ifndef va_copy 2864 #define va_copy(dst, src) memcpy(&(dst), &(src), sizeof(va_list)) 2865 #endif 2866 va_copy(aq, ap); 2867 2868 sz = evutil_vsnprintf(buffer, space, fmt, aq); 2869 2870 va_end(aq); 2871 2872 if (sz < 0) 2873 goto done; 2874 if (INT_MAX >= EVBUFFER_CHAIN_MAX && 2875 (size_t)sz >= EVBUFFER_CHAIN_MAX) 2876 goto done; 2877 if ((size_t)sz < space) { 2878 chain->off += sz; 2879 buf->total_len += sz; 2880 buf->n_add_for_cb += sz; 2881 2882 advance_last_with_data(buf); 2883 evbuffer_invoke_callbacks_(buf); 2884 result = sz; 2885 goto done; 2886 } 2887 if ((chain = evbuffer_expand_singlechain(buf, sz + 1)) == NULL) 2888 goto done; 2889 } 2890 /* NOTREACHED */ 2891 2892 done: 2893 EVBUFFER_UNLOCK(buf); 2894 return result; 2895 } 2896 2897 int 2898 evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...) 2899 { 2900 int res = -1; 2901 va_list ap; 2902 2903 va_start(ap, fmt); 2904 res = evbuffer_add_vprintf(buf, fmt, ap); 2905 va_end(ap); 2906 2907 return (res); 2908 } 2909 2910 int 2911 evbuffer_add_reference(struct evbuffer *outbuf, 2912 const void *data, size_t datlen, 2913 evbuffer_ref_cleanup_cb cleanupfn, void *extra) 2914 { 2915 struct evbuffer_chain *chain; 2916 struct evbuffer_chain_reference *info; 2917 int result = -1; 2918 2919 chain = evbuffer_chain_new(sizeof(struct evbuffer_chain_reference)); 2920 if (!chain) 2921 return (-1); 2922 chain->flags |= EVBUFFER_REFERENCE | EVBUFFER_IMMUTABLE; 2923 chain->buffer = __UNCONST(data); 2924 chain->buffer_len = datlen; 2925 chain->off = datlen; 2926 2927 info = EVBUFFER_CHAIN_EXTRA(struct evbuffer_chain_reference, chain); 2928 info->cleanupfn = cleanupfn; 2929 info->extra = extra; 2930 2931 EVBUFFER_LOCK(outbuf); 2932 if (outbuf->freeze_end) { 2933 /* don't call chain_free; we do not want to actually invoke 2934 * the cleanup function */ 2935 mm_free(chain); 2936 goto done; 2937 } 2938 evbuffer_chain_insert(outbuf, chain); 2939 outbuf->n_add_for_cb += datlen; 2940 2941 evbuffer_invoke_callbacks_(outbuf); 2942 2943 result = 0; 2944 done: 2945 EVBUFFER_UNLOCK(outbuf); 2946 2947 return result; 2948 } 2949 2950 /* TODO(niels): we may want to add to automagically convert to mmap, in 2951 * case evbuffer_remove() or evbuffer_pullup() are being used. 2952 */ 2953 struct evbuffer_file_segment * 2954 evbuffer_file_segment_new( 2955 int fd, ev_off_t offset, ev_off_t length, unsigned flags) 2956 { 2957 struct evbuffer_file_segment *seg = 2958 mm_calloc(sizeof(struct evbuffer_file_segment), 1); 2959 if (!seg) 2960 return NULL; 2961 seg->refcnt = 1; 2962 seg->fd = fd; 2963 seg->flags = flags; 2964 seg->file_offset = offset; 2965 seg->cleanup_cb = NULL; 2966 seg->cleanup_cb_arg = NULL; 2967 #ifdef _WIN32 2968 #ifndef lseek 2969 #define lseek _lseeki64 2970 #endif 2971 #ifndef fstat 2972 #define fstat _fstat 2973 #endif 2974 #ifndef stat 2975 #define stat _stat 2976 #endif 2977 #endif 2978 if (length == -1) { 2979 struct stat st; 2980 if (fstat(fd, &st) < 0) 2981 goto err; 2982 length = st.st_size; 2983 } 2984 seg->length = length; 2985 2986 if (offset < 0 || length < 0 || 2987 ((ev_uint64_t)length > EVBUFFER_CHAIN_MAX) || 2988 (ev_uint64_t)offset > (ev_uint64_t)(EVBUFFER_CHAIN_MAX - length)) 2989 goto err; 2990 2991 #if defined(USE_SENDFILE) 2992 if (!(flags & EVBUF_FS_DISABLE_SENDFILE)) { 2993 seg->can_sendfile = 1; 2994 goto done; 2995 } 2996 #endif 2997 2998 if (evbuffer_file_segment_materialize(seg)<0) 2999 goto err; 3000 3001 #if defined(USE_SENDFILE) 3002 done: 3003 #endif 3004 if (!(flags & EVBUF_FS_DISABLE_LOCKING)) { 3005 EVTHREAD_ALLOC_LOCK(seg->lock, 0); 3006 } 3007 return seg; 3008 err: 3009 mm_free(seg); 3010 return NULL; 3011 } 3012 3013 #ifdef EVENT__HAVE_MMAP 3014 static long 3015 get_page_size(void) 3016 { 3017 #ifdef SC_PAGE_SIZE 3018 return sysconf(SC_PAGE_SIZE); 3019 #elif defined(_SC_PAGE_SIZE) 3020 return sysconf(_SC_PAGE_SIZE); 3021 #else 3022 return 1; 3023 #endif 3024 } 3025 #endif 3026 3027 /* DOCDOC */ 3028 /* Requires lock */ 3029 static int 3030 evbuffer_file_segment_materialize(struct evbuffer_file_segment *seg) 3031 { 3032 const unsigned flags = seg->flags; 3033 const int fd = seg->fd; 3034 const ev_off_t length = seg->length; 3035 const ev_off_t offset = seg->file_offset; 3036 3037 if (seg->contents) 3038 return 0; /* already materialized */ 3039 3040 #if defined(EVENT__HAVE_MMAP) 3041 if (!(flags & EVBUF_FS_DISABLE_MMAP)) { 3042 off_t offset_rounded = 0, offset_leftover = 0; 3043 void *mapped; 3044 if (offset) { 3045 /* mmap implementations don't generally like us 3046 * to have an offset that isn't a round */ 3047 long page_size = get_page_size(); 3048 if (page_size == -1) 3049 goto err; 3050 offset_leftover = offset % page_size; 3051 offset_rounded = offset - offset_leftover; 3052 } 3053 mapped = mmap(NULL, length + offset_leftover, 3054 PROT_READ, 3055 #ifdef MAP_NOCACHE 3056 MAP_NOCACHE | /* ??? */ 3057 #endif 3058 #ifdef MAP_FILE 3059 MAP_FILE | 3060 #endif 3061 MAP_PRIVATE, 3062 fd, offset_rounded); 3063 if (mapped == MAP_FAILED) { 3064 event_warn("%s: mmap(%d, %d, %zu) failed", 3065 __func__, fd, 0, (size_t)(offset + length)); 3066 } else { 3067 seg->mapping = mapped; 3068 seg->contents = (char*)mapped+offset_leftover; 3069 seg->mmap_offset = 0; 3070 seg->is_mapping = 1; 3071 goto done; 3072 } 3073 } 3074 #endif 3075 #ifdef _WIN32 3076 if (!(flags & EVBUF_FS_DISABLE_MMAP)) { 3077 intptr_t h = _get_osfhandle(fd); 3078 HANDLE m; 3079 ev_uint64_t total_size = length+offset; 3080 if ((HANDLE)h == INVALID_HANDLE_VALUE) 3081 goto err; 3082 m = CreateFileMapping((HANDLE)h, NULL, PAGE_READONLY, 3083 (total_size >> 32), total_size & 0xfffffffful, 3084 NULL); 3085 if (m != INVALID_HANDLE_VALUE) { /* Does h leak? */ 3086 seg->mapping_handle = m; 3087 seg->mmap_offset = offset; 3088 seg->is_mapping = 1; 3089 goto done; 3090 } 3091 } 3092 #endif 3093 { 3094 ev_off_t start_pos = lseek(fd, 0, SEEK_CUR), pos; 3095 ev_off_t read_so_far = 0; 3096 char *mem; 3097 int e; 3098 ev_ssize_t n = 0; 3099 if (!(mem = mm_malloc(length))) 3100 goto err; 3101 if (start_pos < 0) { 3102 mm_free(mem); 3103 goto err; 3104 } 3105 if (lseek(fd, offset, SEEK_SET) < 0) { 3106 mm_free(mem); 3107 goto err; 3108 } 3109 while (read_so_far < length) { 3110 n = read(fd, mem+read_so_far, length-read_so_far); 3111 if (n <= 0) 3112 break; 3113 read_so_far += n; 3114 } 3115 3116 e = errno; 3117 pos = lseek(fd, start_pos, SEEK_SET); 3118 if (n < 0 || (n == 0 && length > read_so_far)) { 3119 mm_free(mem); 3120 errno = e; 3121 goto err; 3122 } else if (pos < 0) { 3123 mm_free(mem); 3124 goto err; 3125 } 3126 3127 seg->contents = mem; 3128 } 3129 3130 done: 3131 return 0; 3132 err: 3133 return -1; 3134 } 3135 3136 void evbuffer_file_segment_add_cleanup_cb(struct evbuffer_file_segment *seg, 3137 evbuffer_file_segment_cleanup_cb cb, void* arg) 3138 { 3139 EVUTIL_ASSERT(seg->refcnt > 0); 3140 seg->cleanup_cb = cb; 3141 seg->cleanup_cb_arg = arg; 3142 } 3143 3144 void 3145 evbuffer_file_segment_free(struct evbuffer_file_segment *seg) 3146 { 3147 int refcnt; 3148 EVLOCK_LOCK(seg->lock, 0); 3149 refcnt = --seg->refcnt; 3150 EVLOCK_UNLOCK(seg->lock, 0); 3151 if (refcnt > 0) 3152 return; 3153 EVUTIL_ASSERT(refcnt == 0); 3154 3155 if (seg->is_mapping) { 3156 #ifdef _WIN32 3157 CloseHandle(seg->mapping_handle); 3158 #elif defined (EVENT__HAVE_MMAP) 3159 off_t offset_leftover; 3160 offset_leftover = seg->file_offset % get_page_size(); 3161 if (munmap(seg->mapping, seg->length + offset_leftover) == -1) 3162 event_warn("%s: munmap failed", __func__); 3163 #endif 3164 } else if (seg->contents) { 3165 mm_free(seg->contents); 3166 } 3167 3168 if ((seg->flags & EVBUF_FS_CLOSE_ON_FREE) && seg->fd >= 0) { 3169 close(seg->fd); 3170 } 3171 3172 if (seg->cleanup_cb) { 3173 (*seg->cleanup_cb)((struct evbuffer_file_segment const*)seg, 3174 seg->flags, seg->cleanup_cb_arg); 3175 seg->cleanup_cb = NULL; 3176 seg->cleanup_cb_arg = NULL; 3177 } 3178 3179 EVTHREAD_FREE_LOCK(seg->lock, 0); 3180 mm_free(seg); 3181 } 3182 3183 int 3184 evbuffer_add_file_segment(struct evbuffer *buf, 3185 struct evbuffer_file_segment *seg, ev_off_t offset, ev_off_t length) 3186 { 3187 struct evbuffer_chain *chain; 3188 struct evbuffer_chain_file_segment *extra; 3189 int can_use_sendfile = 0; 3190 3191 EVBUFFER_LOCK(buf); 3192 EVLOCK_LOCK(seg->lock, 0); 3193 if (buf->flags & EVBUFFER_FLAG_DRAINS_TO_FD) { 3194 can_use_sendfile = 1; 3195 } else { 3196 if (!seg->contents) { 3197 if (evbuffer_file_segment_materialize(seg)<0) { 3198 EVLOCK_UNLOCK(seg->lock, 0); 3199 EVBUFFER_UNLOCK(buf); 3200 return -1; 3201 } 3202 } 3203 } 3204 ++seg->refcnt; 3205 EVLOCK_UNLOCK(seg->lock, 0); 3206 3207 if (buf->freeze_end) 3208 goto err; 3209 3210 if (length < 0) { 3211 if (offset > seg->length) 3212 goto err; 3213 length = seg->length - offset; 3214 } 3215 3216 /* Can we actually add this? */ 3217 if (offset+length > seg->length) 3218 goto err; 3219 3220 chain = evbuffer_chain_new(sizeof(struct evbuffer_chain_file_segment)); 3221 if (!chain) 3222 goto err; 3223 extra = EVBUFFER_CHAIN_EXTRA(struct evbuffer_chain_file_segment, chain); 3224 3225 chain->flags |= EVBUFFER_IMMUTABLE|EVBUFFER_FILESEGMENT; 3226 if (can_use_sendfile && seg->can_sendfile) { 3227 chain->flags |= EVBUFFER_SENDFILE; 3228 chain->misalign = seg->file_offset + offset; 3229 chain->off = length; 3230 chain->buffer_len = chain->misalign + length; 3231 } else if (seg->is_mapping) { 3232 #ifdef _WIN32 3233 ev_uint64_t total_offset = seg->mmap_offset+offset; 3234 ev_uint64_t offset_rounded=0, offset_remaining=0; 3235 LPVOID data; 3236 if (total_offset) { 3237 SYSTEM_INFO si; 3238 memset(&si, 0, sizeof(si)); /* cargo cult */ 3239 GetSystemInfo(&si); 3240 offset_remaining = total_offset % si.dwAllocationGranularity; 3241 offset_rounded = total_offset - offset_remaining; 3242 } 3243 data = MapViewOfFile( 3244 seg->mapping_handle, 3245 FILE_MAP_READ, 3246 offset_rounded >> 32, 3247 offset_rounded & 0xfffffffful, 3248 length + offset_remaining); 3249 if (data == NULL) { 3250 mm_free(chain); 3251 goto err; 3252 } 3253 chain->buffer = (unsigned char*) data; 3254 chain->buffer_len = length+offset_remaining; 3255 chain->misalign = offset_remaining; 3256 chain->off = length; 3257 #else 3258 chain->buffer = (unsigned char*)(seg->contents + offset); 3259 chain->buffer_len = length; 3260 chain->off = length; 3261 #endif 3262 } else { 3263 chain->buffer = (unsigned char*)(seg->contents + offset); 3264 chain->buffer_len = length; 3265 chain->off = length; 3266 } 3267 3268 extra->segment = seg; 3269 buf->n_add_for_cb += length; 3270 evbuffer_chain_insert(buf, chain); 3271 3272 evbuffer_invoke_callbacks_(buf); 3273 3274 EVBUFFER_UNLOCK(buf); 3275 3276 return 0; 3277 err: 3278 EVBUFFER_UNLOCK(buf); 3279 evbuffer_file_segment_free(seg); /* Lowers the refcount */ 3280 return -1; 3281 } 3282 3283 int 3284 evbuffer_add_file(struct evbuffer *buf, int fd, ev_off_t offset, ev_off_t length) 3285 { 3286 struct evbuffer_file_segment *seg; 3287 unsigned flags = EVBUF_FS_CLOSE_ON_FREE; 3288 int r; 3289 3290 seg = evbuffer_file_segment_new(fd, offset, length, flags); 3291 if (!seg) 3292 return -1; 3293 r = evbuffer_add_file_segment(buf, seg, 0, length); 3294 if (r == 0) 3295 evbuffer_file_segment_free(seg); 3296 return r; 3297 } 3298 3299 void 3300 evbuffer_setcb(struct evbuffer *buffer, evbuffer_cb cb, void *cbarg) 3301 { 3302 EVBUFFER_LOCK(buffer); 3303 3304 if (!LIST_EMPTY(&buffer->callbacks)) 3305 evbuffer_remove_all_callbacks(buffer); 3306 3307 if (cb) { 3308 struct evbuffer_cb_entry *ent = 3309 evbuffer_add_cb(buffer, NULL, cbarg); 3310 ent->cb.cb_obsolete = cb; 3311 ent->flags |= EVBUFFER_CB_OBSOLETE; 3312 } 3313 EVBUFFER_UNLOCK(buffer); 3314 } 3315 3316 struct evbuffer_cb_entry * 3317 evbuffer_add_cb(struct evbuffer *buffer, evbuffer_cb_func cb, void *cbarg) 3318 { 3319 struct evbuffer_cb_entry *e; 3320 if (! (e = mm_calloc(1, sizeof(struct evbuffer_cb_entry)))) 3321 return NULL; 3322 EVBUFFER_LOCK(buffer); 3323 e->cb.cb_func = cb; 3324 e->cbarg = cbarg; 3325 e->flags = EVBUFFER_CB_ENABLED; 3326 LIST_INSERT_HEAD(&buffer->callbacks, e, next); 3327 EVBUFFER_UNLOCK(buffer); 3328 return e; 3329 } 3330 3331 int 3332 evbuffer_remove_cb_entry(struct evbuffer *buffer, 3333 struct evbuffer_cb_entry *ent) 3334 { 3335 EVBUFFER_LOCK(buffer); 3336 LIST_REMOVE(ent, next); 3337 EVBUFFER_UNLOCK(buffer); 3338 mm_free(ent); 3339 return 0; 3340 } 3341 3342 int 3343 evbuffer_remove_cb(struct evbuffer *buffer, evbuffer_cb_func cb, void *cbarg) 3344 { 3345 struct evbuffer_cb_entry *cbent; 3346 int result = -1; 3347 EVBUFFER_LOCK(buffer); 3348 LIST_FOREACH(cbent, &buffer->callbacks, next) { 3349 if (cb == cbent->cb.cb_func && cbarg == cbent->cbarg) { 3350 result = evbuffer_remove_cb_entry(buffer, cbent); 3351 goto done; 3352 } 3353 } 3354 done: 3355 EVBUFFER_UNLOCK(buffer); 3356 return result; 3357 } 3358 3359 int 3360 evbuffer_cb_set_flags(struct evbuffer *buffer, 3361 struct evbuffer_cb_entry *cb, ev_uint32_t flags) 3362 { 3363 /* the user isn't allowed to mess with these. */ 3364 flags &= ~EVBUFFER_CB_INTERNAL_FLAGS; 3365 EVBUFFER_LOCK(buffer); 3366 cb->flags |= flags; 3367 EVBUFFER_UNLOCK(buffer); 3368 return 0; 3369 } 3370 3371 int 3372 evbuffer_cb_clear_flags(struct evbuffer *buffer, 3373 struct evbuffer_cb_entry *cb, ev_uint32_t flags) 3374 { 3375 /* the user isn't allowed to mess with these. */ 3376 flags &= ~EVBUFFER_CB_INTERNAL_FLAGS; 3377 EVBUFFER_LOCK(buffer); 3378 cb->flags &= ~flags; 3379 EVBUFFER_UNLOCK(buffer); 3380 return 0; 3381 } 3382 3383 int 3384 evbuffer_freeze(struct evbuffer *buffer, int start) 3385 { 3386 EVBUFFER_LOCK(buffer); 3387 if (start) 3388 buffer->freeze_start = 1; 3389 else 3390 buffer->freeze_end = 1; 3391 EVBUFFER_UNLOCK(buffer); 3392 return 0; 3393 } 3394 3395 int 3396 evbuffer_unfreeze(struct evbuffer *buffer, int start) 3397 { 3398 EVBUFFER_LOCK(buffer); 3399 if (start) 3400 buffer->freeze_start = 0; 3401 else 3402 buffer->freeze_end = 0; 3403 EVBUFFER_UNLOCK(buffer); 3404 return 0; 3405 } 3406 3407 #if 0 3408 void 3409 evbuffer_cb_suspend(struct evbuffer *buffer, struct evbuffer_cb_entry *cb) 3410 { 3411 if (!(cb->flags & EVBUFFER_CB_SUSPENDED)) { 3412 cb->size_before_suspend = evbuffer_get_length(buffer); 3413 cb->flags |= EVBUFFER_CB_SUSPENDED; 3414 } 3415 } 3416 3417 void 3418 evbuffer_cb_unsuspend(struct evbuffer *buffer, struct evbuffer_cb_entry *cb) 3419 { 3420 if ((cb->flags & EVBUFFER_CB_SUSPENDED)) { 3421 unsigned call = (cb->flags & EVBUFFER_CB_CALL_ON_UNSUSPEND); 3422 size_t sz = cb->size_before_suspend; 3423 cb->flags &= ~(EVBUFFER_CB_SUSPENDED| 3424 EVBUFFER_CB_CALL_ON_UNSUSPEND); 3425 cb->size_before_suspend = 0; 3426 if (call && (cb->flags & EVBUFFER_CB_ENABLED)) { 3427 cb->cb(buffer, sz, evbuffer_get_length(buffer), cb->cbarg); 3428 } 3429 } 3430 } 3431 #endif 3432 3433 int 3434 evbuffer_get_callbacks_(struct evbuffer *buffer, struct event_callback **cbs, 3435 int max_cbs) 3436 { 3437 int r = 0; 3438 EVBUFFER_LOCK(buffer); 3439 if (buffer->deferred_cbs) { 3440 if (max_cbs < 1) { 3441 r = -1; 3442 goto done; 3443 } 3444 cbs[0] = &buffer->deferred; 3445 r = 1; 3446 } 3447 done: 3448 EVBUFFER_UNLOCK(buffer); 3449 return r; 3450 } 3451