1 /* 2 * Packet interface 3 * Copyright (C) 1999 Kunihiro Ishiguro 4 * 5 * This file is part of GNU Zebra. 6 * 7 * GNU Zebra is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; either version 2, or (at your option) any 10 * later version. 11 * 12 * GNU Zebra is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with GNU Zebra; see the file COPYING. If not, write to the Free 19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 20 * 02111-1307, USA. 21 */ 22 23#include <stddef.h> 24#include <zebra.h> 25 26#include "stream.h" 27#include "memory.h" 28#include "network.h" 29#include "prefix.h" 30#include "log.h" 31 32/* Tests whether a position is valid */ 33#define GETP_VALID(S,G) \ 34 ((G) <= (S)->endp) 35#define PUT_AT_VALID(S,G) GETP_VALID(S,G) 36#define ENDP_VALID(S,E) \ 37 ((E) <= (S)->size) 38 39/* asserting sanity checks. Following must be true before 40 * stream functions are called: 41 * 42 * Following must always be true of stream elements 43 * before and after calls to stream functions: 44 * 45 * getp <= endp <= size 46 * 47 * Note that after a stream function is called following may be true: 48 * if (getp == endp) then stream is no longer readable 49 * if (endp == size) then stream is no longer writeable 50 * 51 * It is valid to put to anywhere within the size of the stream, but only 52 * using stream_put..._at() functions. 53 */ 54#define STREAM_WARN_OFFSETS(S) \ 55 zlog_warn ("&(struct stream): %p, size: %lu, getp: %lu, endp: %lu\n", \ 56 (S), \ 57 (unsigned long) (S)->size, \ 58 (unsigned long) (S)->getp, \ 59 (unsigned long) (S)->endp)\ 60 61#define STREAM_VERIFY_SANE(S) \ 62 do { \ 63 if ( !(GETP_VALID(S, (S)->getp)) && ENDP_VALID(S, (S)->endp) ) \ 64 STREAM_WARN_OFFSETS(S); \ 65 assert ( GETP_VALID(S, (S)->getp) ); \ 66 assert ( ENDP_VALID(S, (S)->endp) ); \ 67 } while (0) 68 69#define STREAM_BOUND_WARN(S, WHAT) \ 70 do { \ 71 zlog_warn ("%s: Attempt to %s out of bounds", __func__, (WHAT)); \ 72 STREAM_WARN_OFFSETS(S); \ 73 assert (0); \ 74 } while (0) 75 76/* XXX: Deprecated macro: do not use */ 77#define CHECK_SIZE(S, Z) \ 78 do { \ 79 if (((S)->endp + (Z)) > (S)->size) \ 80 { \ 81 zlog_warn ("CHECK_SIZE: truncating requested size %lu\n", \ 82 (unsigned long) (Z)); \ 83 STREAM_WARN_OFFSETS(S); \ 84 (Z) = (S)->size - (S)->endp; \ 85 } \ 86 } while (0); 87 88/* Make stream buffer. */ 89struct stream * 90stream_new (size_t size) 91{ 92 struct stream *s; 93 94 assert (size > 0); 95 96 if (size == 0) 97 { 98 zlog_warn ("stream_new(): called with 0 size!"); 99 return NULL; 100 } 101 102 s = XCALLOC (MTYPE_STREAM, sizeof (struct stream)); 103 104 if (s == NULL) 105 return s; 106 107 if ( (s->data = XMALLOC (MTYPE_STREAM_DATA, size)) == NULL) 108 { 109 XFREE (MTYPE_STREAM, s); 110 return NULL; 111 } 112 113 s->size = size; 114 return s; 115} 116 117/* Free it now. */ 118void 119stream_free (struct stream *s) 120{ 121 if (!s) 122 return; 123 124 XFREE (MTYPE_STREAM_DATA, s->data); 125 XFREE (MTYPE_STREAM, s); 126} 127 128struct stream * 129stream_copy (struct stream *new, struct stream *src) 130{ 131 STREAM_VERIFY_SANE (src); 132 133 assert (new != NULL); 134 assert (STREAM_SIZE(new) >= src->endp); 135 136 new->endp = src->endp; 137 new->getp = src->getp; 138 139 memcpy (new->data, src->data, src->endp); 140 141 return new; 142} 143 144struct stream * 145stream_dup (struct stream *s) 146{ 147 struct stream *new; 148 149 STREAM_VERIFY_SANE (s); 150 151 if ( (new = stream_new (s->endp)) == NULL) 152 return NULL; 153 154 return (stream_copy (new, s)); 155} 156 157struct stream * 158stream_dupcat (struct stream *s1, struct stream *s2, size_t offset) 159{ 160 struct stream *new; 161 162 STREAM_VERIFY_SANE (s1); 163 STREAM_VERIFY_SANE (s2); 164 165 if ( (new = stream_new (s1->endp + s2->endp)) == NULL) 166 return NULL; 167 168 memcpy (new->data, s1->data, offset); 169 memcpy (new->data + offset, s2->data, s2->endp); 170 memcpy (new->data + offset + s2->endp, s1->data + offset, 171 (s1->endp - offset)); 172 new->endp = s1->endp + s2->endp; 173 return new; 174} 175 176size_t 177stream_resize (struct stream *s, size_t newsize) 178{ 179 u_char *newdata; 180 STREAM_VERIFY_SANE (s); 181 182 newdata = XREALLOC (MTYPE_STREAM_DATA, s->data, newsize); 183 184 if (newdata == NULL) 185 return s->size; 186 187 s->data = newdata; 188 s->size = newsize; 189 190 if (s->endp > s->size) 191 s->endp = s->size; 192 if (s->getp > s->endp) 193 s->getp = s->endp; 194 195 STREAM_VERIFY_SANE (s); 196 197 return s->size; 198} 199 200size_t 201stream_get_getp (struct stream *s) 202{ 203 STREAM_VERIFY_SANE(s); 204 return s->getp; 205} 206 207size_t 208stream_get_endp (struct stream *s) 209{ 210 STREAM_VERIFY_SANE(s); 211 return s->endp; 212} 213 214size_t 215stream_get_size (struct stream *s) 216{ 217 STREAM_VERIFY_SANE(s); 218 return s->size; 219} 220 221/* Stream structre' stream pointer related functions. */ 222void 223stream_set_getp (struct stream *s, size_t pos) 224{ 225 STREAM_VERIFY_SANE(s); 226 227 if (!GETP_VALID (s, pos)) 228 { 229 STREAM_BOUND_WARN (s, "set getp"); 230 pos = s->endp; 231 } 232 233 s->getp = pos; 234} 235 236void 237stream_set_endp (struct stream *s, size_t pos) 238{ 239 STREAM_VERIFY_SANE(s); 240 241 if (!ENDP_VALID(s, pos)) 242 { 243 STREAM_BOUND_WARN (s, "set endp"); 244 return; 245 } 246 247 /* 248 * Make sure the current read pointer is not beyond the new endp. 249 */ 250 if (s->getp > pos) 251 { 252 STREAM_BOUND_WARN(s, "set endp"); 253 return; 254 } 255 256 s->endp = pos; 257 STREAM_VERIFY_SANE(s); 258} 259 260/* Forward pointer. */ 261void 262stream_forward_getp (struct stream *s, size_t size) 263{ 264 STREAM_VERIFY_SANE(s); 265 266 if (!GETP_VALID (s, s->getp + size)) 267 { 268 STREAM_BOUND_WARN (s, "seek getp"); 269 return; 270 } 271 272 s->getp += size; 273} 274 275void 276stream_forward_endp (struct stream *s, size_t size) 277{ 278 STREAM_VERIFY_SANE(s); 279 280 if (!ENDP_VALID (s, s->endp + size)) 281 { 282 STREAM_BOUND_WARN (s, "seek endp"); 283 return; 284 } 285 286 s->endp += size; 287} 288 289/* Copy from stream to destination. */ 290void 291stream_get (void *dst, struct stream *s, size_t size) 292{ 293 STREAM_VERIFY_SANE(s); 294 295 if (STREAM_READABLE(s) < size) 296 { 297 STREAM_BOUND_WARN (s, "get"); 298 return; 299 } 300 301 memcpy (dst, s->data + s->getp, size); 302 s->getp += size; 303} 304 305/* Get next character from the stream. */ 306u_char 307stream_getc (struct stream *s) 308{ 309 u_char c; 310 311 STREAM_VERIFY_SANE (s); 312 313 if (STREAM_READABLE(s) < sizeof (u_char)) 314 { 315 STREAM_BOUND_WARN (s, "get char"); 316 return 0; 317 } 318 c = s->data[s->getp++]; 319 320 return c; 321} 322 323/* Get next character from the stream. */ 324u_char 325stream_getc_from (struct stream *s, size_t from) 326{ 327 u_char c; 328 329 STREAM_VERIFY_SANE(s); 330 331 if (!GETP_VALID (s, from + sizeof (u_char))) 332 { 333 STREAM_BOUND_WARN (s, "get char"); 334 return 0; 335 } 336 337 c = s->data[from]; 338 339 return c; 340} 341 342/* Get next word from the stream. */ 343u_int16_t 344stream_getw (struct stream *s) 345{ 346 u_int16_t w; 347 348 STREAM_VERIFY_SANE (s); 349 350 if (STREAM_READABLE (s) < sizeof (u_int16_t)) 351 { 352 STREAM_BOUND_WARN (s, "get "); 353 return 0; 354 } 355 356 w = s->data[s->getp++] << 8; 357 w |= s->data[s->getp++]; 358 359 return w; 360} 361 362/* Get next word from the stream. */ 363u_int16_t 364stream_getw_from (struct stream *s, size_t from) 365{ 366 u_int16_t w; 367 368 STREAM_VERIFY_SANE(s); 369 370 if (!GETP_VALID (s, from + sizeof (u_int16_t))) 371 { 372 STREAM_BOUND_WARN (s, "get "); 373 return 0; 374 } 375 376 w = s->data[from++] << 8; 377 w |= s->data[from]; 378 379 return w; 380} 381 382/* Get next long word from the stream. */ 383u_int32_t 384stream_getl_from (struct stream *s, size_t from) 385{ 386 u_int32_t l; 387 388 STREAM_VERIFY_SANE(s); 389 390 if (!GETP_VALID (s, from + sizeof (u_int32_t))) 391 { 392 STREAM_BOUND_WARN (s, "get long"); 393 return 0; 394 } 395 396 l = s->data[from++] << 24; 397 l |= s->data[from++] << 16; 398 l |= s->data[from++] << 8; 399 l |= s->data[from]; 400 401 return l; 402} 403 404u_int32_t 405stream_getl (struct stream *s) 406{ 407 u_int32_t l; 408 409 STREAM_VERIFY_SANE(s); 410 411 if (STREAM_READABLE (s) < sizeof (u_int32_t)) 412 { 413 STREAM_BOUND_WARN (s, "get long"); 414 return 0; 415 } 416 417 l = s->data[s->getp++] << 24; 418 l |= s->data[s->getp++] << 16; 419 l |= s->data[s->getp++] << 8; 420 l |= s->data[s->getp++]; 421 422 return l; 423} 424 425/* Get next quad word from the stream. */ 426uint64_t 427stream_getq_from (struct stream *s, size_t from) 428{ 429 uint64_t q; 430 431 STREAM_VERIFY_SANE(s); 432 433 if (!GETP_VALID (s, from + sizeof (uint64_t))) 434 { 435 STREAM_BOUND_WARN (s, "get quad"); 436 return 0; 437 } 438 439 q = ((uint64_t) s->data[from++]) << 56; 440 q |= ((uint64_t) s->data[from++]) << 48; 441 q |= ((uint64_t) s->data[from++]) << 40; 442 q |= ((uint64_t) s->data[from++]) << 32; 443 q |= ((uint64_t) s->data[from++]) << 24; 444 q |= ((uint64_t) s->data[from++]) << 16; 445 q |= ((uint64_t) s->data[from++]) << 8; 446 q |= ((uint64_t) s->data[from++]); 447 448 return q; 449} 450 451uint64_t 452stream_getq (struct stream *s) 453{ 454 uint64_t q; 455 456 STREAM_VERIFY_SANE(s); 457 458 if (STREAM_READABLE (s) < sizeof (uint64_t)) 459 { 460 STREAM_BOUND_WARN (s, "get quad"); 461 return 0; 462 } 463 464 q = ((uint64_t) s->data[s->getp++]) << 56; 465 q |= ((uint64_t) s->data[s->getp++]) << 48; 466 q |= ((uint64_t) s->data[s->getp++]) << 40; 467 q |= ((uint64_t) s->data[s->getp++]) << 32; 468 q |= ((uint64_t) s->data[s->getp++]) << 24; 469 q |= ((uint64_t) s->data[s->getp++]) << 16; 470 q |= ((uint64_t) s->data[s->getp++]) << 8; 471 q |= ((uint64_t) s->data[s->getp++]); 472 473 return q; 474} 475 476/* Get next long word from the stream. */ 477u_int32_t 478stream_get_ipv4 (struct stream *s) 479{ 480 u_int32_t l; 481 482 STREAM_VERIFY_SANE(s); 483 484 if (STREAM_READABLE (s) < sizeof(u_int32_t)) 485 { 486 STREAM_BOUND_WARN (s, "get ipv4"); 487 return 0; 488 } 489 490 memcpy (&l, s->data + s->getp, sizeof(u_int32_t)); 491 s->getp += sizeof(u_int32_t); 492 493 return l; 494} 495 496/* Copy to source to stream. 497 * 498 * XXX: This uses CHECK_SIZE and hence has funny semantics -> Size will wrap 499 * around. This should be fixed once the stream updates are working. 500 * 501 * stream_write() is saner 502 */ 503void 504stream_put (struct stream *s, const void *src, size_t size) 505{ 506 507 /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */ 508 CHECK_SIZE(s, size); 509 510 STREAM_VERIFY_SANE(s); 511 512 if (STREAM_WRITEABLE (s) < size) 513 { 514 STREAM_BOUND_WARN (s, "put"); 515 return; 516 } 517 518 if (src) 519 memcpy (s->data + s->endp, src, size); 520 else 521 memset (s->data + s->endp, 0, size); 522 523 s->endp += size; 524} 525 526/* Put character to the stream. */ 527int 528stream_putc (struct stream *s, u_char c) 529{ 530 STREAM_VERIFY_SANE(s); 531 532 if (STREAM_WRITEABLE (s) < sizeof(u_char)) 533 { 534 STREAM_BOUND_WARN (s, "put"); 535 return 0; 536 } 537 538 s->data[s->endp++] = c; 539 return sizeof (u_char); 540} 541 542/* Put word to the stream. */ 543int 544stream_putw (struct stream *s, u_int16_t w) 545{ 546 STREAM_VERIFY_SANE (s); 547 548 if (STREAM_WRITEABLE (s) < sizeof (u_int16_t)) 549 { 550 STREAM_BOUND_WARN (s, "put"); 551 return 0; 552 } 553 554 s->data[s->endp++] = (u_char)(w >> 8); 555 s->data[s->endp++] = (u_char) w; 556 557 return 2; 558} 559 560/* Put long word to the stream. */ 561int 562stream_putl (struct stream *s, u_int32_t l) 563{ 564 STREAM_VERIFY_SANE (s); 565 566 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t)) 567 { 568 STREAM_BOUND_WARN (s, "put"); 569 return 0; 570 } 571 572 s->data[s->endp++] = (u_char)(l >> 24); 573 s->data[s->endp++] = (u_char)(l >> 16); 574 s->data[s->endp++] = (u_char)(l >> 8); 575 s->data[s->endp++] = (u_char)l; 576 577 return 4; 578} 579 580/* Put quad word to the stream. */ 581int 582stream_putq (struct stream *s, uint64_t q) 583{ 584 STREAM_VERIFY_SANE (s); 585 586 if (STREAM_WRITEABLE (s) < sizeof (uint64_t)) 587 { 588 STREAM_BOUND_WARN (s, "put quad"); 589 return 0; 590 } 591 592 s->data[s->endp++] = (u_char)(q >> 56); 593 s->data[s->endp++] = (u_char)(q >> 48); 594 s->data[s->endp++] = (u_char)(q >> 40); 595 s->data[s->endp++] = (u_char)(q >> 32); 596 s->data[s->endp++] = (u_char)(q >> 24); 597 s->data[s->endp++] = (u_char)(q >> 16); 598 s->data[s->endp++] = (u_char)(q >> 8); 599 s->data[s->endp++] = (u_char)q; 600 601 return 8; 602} 603 604int 605stream_putc_at (struct stream *s, size_t putp, u_char c) 606{ 607 STREAM_VERIFY_SANE(s); 608 609 if (!PUT_AT_VALID (s, putp + sizeof (u_char))) 610 { 611 STREAM_BOUND_WARN (s, "put"); 612 return 0; 613 } 614 615 s->data[putp] = c; 616 617 return 1; 618} 619 620int 621stream_putw_at (struct stream *s, size_t putp, u_int16_t w) 622{ 623 STREAM_VERIFY_SANE(s); 624 625 if (!PUT_AT_VALID (s, putp + sizeof (u_int16_t))) 626 { 627 STREAM_BOUND_WARN (s, "put"); 628 return 0; 629 } 630 631 s->data[putp] = (u_char)(w >> 8); 632 s->data[putp + 1] = (u_char) w; 633 634 return 2; 635} 636 637int 638stream_putl_at (struct stream *s, size_t putp, u_int32_t l) 639{ 640 STREAM_VERIFY_SANE(s); 641 642 if (!PUT_AT_VALID (s, putp + sizeof (u_int32_t))) 643 { 644 STREAM_BOUND_WARN (s, "put"); 645 return 0; 646 } 647 s->data[putp] = (u_char)(l >> 24); 648 s->data[putp + 1] = (u_char)(l >> 16); 649 s->data[putp + 2] = (u_char)(l >> 8); 650 s->data[putp + 3] = (u_char)l; 651 652 return 4; 653} 654 655int 656stream_putq_at (struct stream *s, size_t putp, uint64_t q) 657{ 658 STREAM_VERIFY_SANE(s); 659 660 if (!PUT_AT_VALID (s, putp + sizeof (uint64_t))) 661 { 662 STREAM_BOUND_WARN (s, "put"); 663 return 0; 664 } 665 s->data[putp] = (u_char)(q >> 56); 666 s->data[putp + 1] = (u_char)(q >> 48); 667 s->data[putp + 2] = (u_char)(q >> 40); 668 s->data[putp + 3] = (u_char)(q >> 32); 669 s->data[putp + 4] = (u_char)(q >> 24); 670 s->data[putp + 5] = (u_char)(q >> 16); 671 s->data[putp + 6] = (u_char)(q >> 8); 672 s->data[putp + 7] = (u_char)q; 673 674 return 8; 675} 676 677/* Put long word to the stream. */ 678int 679stream_put_ipv4 (struct stream *s, u_int32_t l) 680{ 681 STREAM_VERIFY_SANE(s); 682 683 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t)) 684 { 685 STREAM_BOUND_WARN (s, "put"); 686 return 0; 687 } 688 memcpy (s->data + s->endp, &l, sizeof (u_int32_t)); 689 s->endp += sizeof (u_int32_t); 690 691 return sizeof (u_int32_t); 692} 693 694/* Put long word to the stream. */ 695int 696stream_put_in_addr (struct stream *s, struct in_addr *addr) 697{ 698 STREAM_VERIFY_SANE(s); 699 700 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t)) 701 { 702 STREAM_BOUND_WARN (s, "put"); 703 return 0; 704 } 705 706 memcpy (s->data + s->endp, addr, sizeof (u_int32_t)); 707 s->endp += sizeof (u_int32_t); 708 709 return sizeof (u_int32_t); 710} 711 712/* Put prefix by nlri type format. */ 713int 714stream_put_prefix (struct stream *s, struct prefix *p) 715{ 716 size_t psize; 717 718 STREAM_VERIFY_SANE(s); 719 720 psize = PSIZE (p->prefixlen); 721 722 if (STREAM_WRITEABLE (s) < (psize + sizeof (u_char))) 723 { 724 STREAM_BOUND_WARN (s, "put"); 725 return 0; 726 } 727 728 s->data[s->endp++] = p->prefixlen; 729 memcpy (s->data + s->endp, &p->u.prefix, psize); 730 s->endp += psize; 731 732 return psize; 733} 734 735/* Read size from fd. */ 736int 737stream_read (struct stream *s, int fd, size_t size) 738{ 739 int nbytes; 740 741 STREAM_VERIFY_SANE(s); 742 743 if (STREAM_WRITEABLE (s) < size) 744 { 745 STREAM_BOUND_WARN (s, "put"); 746 return 0; 747 } 748 749 nbytes = readn (fd, s->data + s->endp, size); 750 751 if (nbytes > 0) 752 s->endp += nbytes; 753 754 return nbytes; 755} 756 757ssize_t 758stream_read_try(struct stream *s, int fd, size_t size) 759{ 760 ssize_t nbytes; 761 762 STREAM_VERIFY_SANE(s); 763 764 if (STREAM_WRITEABLE(s) < size) 765 { 766 STREAM_BOUND_WARN (s, "put"); 767 /* Fatal (not transient) error, since retrying will not help 768 (stream is too small to contain the desired data). */ 769 return -1; 770 } 771 772 if ((nbytes = read(fd, s->data + s->endp, size)) >= 0) 773 { 774 s->endp += nbytes; 775 return nbytes; 776 } 777 /* Error: was it transient (return -2) or fatal (return -1)? */ 778 if (ERRNO_IO_RETRY(errno)) 779 return -2; 780 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno)); 781 return -1; 782} 783 784/* Read up to size bytes into the stream from the fd, using recvmsgfrom 785 * whose arguments match the remaining arguments to this function 786 */ 787ssize_t 788stream_recvfrom (struct stream *s, int fd, size_t size, int flags, 789 struct sockaddr *from, socklen_t *fromlen) 790{ 791 ssize_t nbytes; 792 793 STREAM_VERIFY_SANE(s); 794 795 if (STREAM_WRITEABLE(s) < size) 796 { 797 STREAM_BOUND_WARN (s, "put"); 798 /* Fatal (not transient) error, since retrying will not help 799 (stream is too small to contain the desired data). */ 800 return -1; 801 } 802 803 if ((nbytes = recvfrom (fd, s->data + s->endp, size, 804 flags, from, fromlen)) >= 0) 805 { 806 s->endp += nbytes; 807 return nbytes; 808 } 809 /* Error: was it transient (return -2) or fatal (return -1)? */ 810 if (ERRNO_IO_RETRY(errno)) 811 return -2; 812 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno)); 813 return -1; 814} 815 816/* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting 817 * from endp. 818 * First iovec will be used to receive the data. 819 * Stream need not be empty. 820 */ 821ssize_t 822stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags, 823 size_t size) 824{ 825 int nbytes; 826 struct iovec *iov; 827 828 STREAM_VERIFY_SANE(s); 829 assert (msgh->msg_iovlen > 0); 830 831 if (STREAM_WRITEABLE (s) < size) 832 { 833 STREAM_BOUND_WARN (s, "put"); 834 /* This is a logic error in the calling code: the stream is too small 835 to hold the desired data! */ 836 return -1; 837 } 838 839 iov = &(msgh->msg_iov[0]); 840 iov->iov_base = (s->data + s->endp); 841 iov->iov_len = size; 842 843 nbytes = recvmsg (fd, msgh, flags); 844 845 if (nbytes > 0) 846 s->endp += nbytes; 847 848 return nbytes; 849} 850 851/* Write data to buffer. */ 852size_t 853stream_write (struct stream *s, const void *ptr, size_t size) 854{ 855 856 CHECK_SIZE(s, size); 857 858 STREAM_VERIFY_SANE(s); 859 860 if (STREAM_WRITEABLE (s) < size) 861 { 862 STREAM_BOUND_WARN (s, "put"); 863 return 0; 864 } 865 866 memcpy (s->data + s->endp, ptr, size); 867 s->endp += size; 868 869 return size; 870} 871 872/* Return current read pointer. 873 * DEPRECATED! 874 * Use stream_get_pnt_to if you must, but decoding streams properly 875 * is preferred 876 */ 877u_char * 878stream_pnt (struct stream *s) 879{ 880 STREAM_VERIFY_SANE(s); 881 return s->data + s->getp; 882} 883 884/* Check does this stream empty? */ 885int 886stream_empty (struct stream *s) 887{ 888 STREAM_VERIFY_SANE(s); 889 890 return (s->endp == 0); 891} 892 893/* Reset stream. */ 894void 895stream_reset (struct stream *s) 896{ 897 STREAM_VERIFY_SANE (s); 898 899 s->getp = s->endp = 0; 900} 901 902/* Write stream contens to the file discriptor. */ 903int 904stream_flush (struct stream *s, int fd) 905{ 906 int nbytes; 907 908 STREAM_VERIFY_SANE(s); 909 910 nbytes = write (fd, s->data + s->getp, s->endp - s->getp); 911 912 return nbytes; 913} 914 915/* Stream first in first out queue. */ 916 917struct stream_fifo * 918stream_fifo_new (void) 919{ 920 struct stream_fifo *new; 921 922 new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo)); 923 return new; 924} 925 926/* Add new stream to fifo. */ 927void 928stream_fifo_push (struct stream_fifo *fifo, struct stream *s) 929{ 930 if (fifo->tail) 931 fifo->tail->next = s; 932 else 933 fifo->head = s; 934 935 fifo->tail = s; 936 937 fifo->count++; 938} 939 940/* Delete first stream from fifo. */ 941struct stream * 942stream_fifo_pop (struct stream_fifo *fifo) 943{ 944 struct stream *s; 945 946 s = fifo->head; 947 948 if (s) 949 { 950 fifo->head = s->next; 951 952 if (fifo->head == NULL) 953 fifo->tail = NULL; 954 955 fifo->count--; 956 } 957 958 return s; 959} 960 961/* Return first fifo entry. */ 962struct stream * 963stream_fifo_head (struct stream_fifo *fifo) 964{ 965 return fifo->head; 966} 967 968void 969stream_fifo_clean (struct stream_fifo *fifo) 970{ 971 struct stream *s; 972 struct stream *next; 973 974 for (s = fifo->head; s; s = next) 975 { 976 next = s->next; 977 stream_free (s); 978 } 979 fifo->head = fifo->tail = NULL; 980 fifo->count = 0; 981} 982 983void 984stream_fifo_free (struct stream_fifo *fifo) 985{ 986 stream_fifo_clean (fifo); 987 XFREE (MTYPE_STREAM_FIFO, fifo); 988} 989