From 718e3744195351130f4ce7dbe0613f4b3e23df93 Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 13 Dec 2002 20:15:29 +0000 Subject: Initial revision --- lib/stream.c | 479 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 479 insertions(+) create mode 100644 lib/stream.c (limited to 'lib/stream.c') diff --git a/lib/stream.c b/lib/stream.c new file mode 100644 index 00000000..2d4de760 --- /dev/null +++ b/lib/stream.c @@ -0,0 +1,479 @@ +/* + * Packet interface + * Copyright (C) 1999 Kunihiro Ishiguro + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include + +#include "stream.h" +#include "memory.h" +#include "network.h" +#include "prefix.h" + + +/*A macro to check pointers in order to not + go behind the allocated mem block + S -- stream reference + Z -- size of data to be written +*/ + +#define CHECK_SIZE(S, Z) \ + if (((S)->putp + (Z)) > (S)->size) \ + (Z) = (S)->size - (S)->putp; + +/* Stream is fixed length buffer for network output/input. */ + +/* Make stream buffer. */ +struct stream * +stream_new (size_t size) +{ + struct stream *s; + + s = XCALLOC (MTYPE_STREAM, sizeof (struct stream)); + + s->data = XCALLOC (MTYPE_STREAM_DATA, size); + s->size = size; + return s; +} + +/* Free it now. */ +void +stream_free (struct stream *s) +{ + XFREE (MTYPE_STREAM_DATA, s->data); + XFREE (MTYPE_STREAM, s); +} + +unsigned long +stream_get_getp (struct stream *s) +{ + return s->getp; +} + +unsigned long +stream_get_putp (struct stream *s) +{ + return s->putp; +} + +unsigned long +stream_get_endp (struct stream *s) +{ + return s->endp; +} + +unsigned long +stream_get_size (struct stream *s) +{ + return s->size; +} + +/* Stream structre' stream pointer related functions. */ +void +stream_set_getp (struct stream *s, unsigned long pos) +{ + s->getp = pos; +} + +void +stream_set_putp (struct stream *s, unsigned long pos) +{ + s->putp = pos; +} + +/* Forward pointer. */ +void +stream_forward (struct stream *s, int size) +{ + s->getp += size; +} + +/* Copy from stream to destination. */ +void +stream_get (void *dst, struct stream *s, size_t size) +{ + memcpy (dst, s->data + s->getp, size); + s->getp += size; +} + +/* Get next character from the stream. */ +u_char +stream_getc (struct stream *s) +{ + u_char c; + + c = s->data[s->getp]; + s->getp++; + return c; +} + +/* Get next character from the stream. */ +u_char +stream_getc_from (struct stream *s, unsigned long from) +{ + u_char c; + + c = s->data[from]; + return c; +} + +/* Get next word from the stream. */ +u_int16_t +stream_getw (struct stream *s) +{ + u_int16_t w; + + w = s->data[s->getp++] << 8; + w |= s->data[s->getp++]; + return w; +} + +/* Get next word from the stream. */ +u_int16_t +stream_getw_from (struct stream *s, unsigned long from) +{ + u_int16_t w; + + w = s->data[from++] << 8; + w |= s->data[from]; + return w; +} + +/* Get next long word from the stream. */ +u_int32_t +stream_getl (struct stream *s) +{ + u_int32_t l; + + l = s->data[s->getp++] << 24; + l |= s->data[s->getp++] << 16; + l |= s->data[s->getp++] << 8; + l |= s->data[s->getp++]; + return l; +} + +/* Get next long word from the stream. */ +u_int32_t +stream_get_ipv4 (struct stream *s) +{ + u_int32_t l; + + memcpy (&l, s->data + s->getp, 4); + s->getp += 4; + + return l; +} + +/* Copy to source to stream. */ +void +stream_put (struct stream *s, void *src, size_t size) +{ + + CHECK_SIZE(s, size); + + if (src) + memcpy (s->data + s->putp, src, size); + else + memset (s->data + s->putp, 0, size); + + s->putp += size; + if (s->putp > s->endp) + s->endp = s->putp; +} + +/* Put character to the stream. */ +int +stream_putc (struct stream *s, u_char c) +{ + if (s->putp >= s->size) return 0; + + s->data[s->putp] = c; + s->putp++; + if (s->putp > s->endp) + s->endp = s->putp; + return 1; +} + +/* Put word to the stream. */ +int +stream_putw (struct stream *s, u_int16_t w) +{ + if ((s->size - s->putp) < 2) return 0; + + s->data[s->putp++] = (u_char)(w >> 8); + s->data[s->putp++] = (u_char) w; + + if (s->putp > s->endp) + s->endp = s->putp; + return 2; +} + +/* Put long word to the stream. */ +int +stream_putl (struct stream *s, u_int32_t l) +{ + if ((s->size - s->putp) < 4) return 0; + + s->data[s->putp++] = (u_char)(l >> 24); + s->data[s->putp++] = (u_char)(l >> 16); + s->data[s->putp++] = (u_char)(l >> 8); + s->data[s->putp++] = (u_char)l; + + if (s->putp > s->endp) + s->endp = s->putp; + return 4; +} + +int +stream_putc_at (struct stream *s, unsigned long putp, u_char c) +{ + s->data[putp] = c; + return 1; +} + +int +stream_putw_at (struct stream *s, unsigned long putp, u_int16_t w) +{ + s->data[putp] = (u_char)(w >> 8); + s->data[putp + 1] = (u_char) w; + return 2; +} + +int +stream_putl_at (struct stream *s, unsigned long putp, u_int32_t l) +{ + s->data[putp] = (u_char)(l >> 24); + s->data[putp + 1] = (u_char)(l >> 16); + s->data[putp + 2] = (u_char)(l >> 8); + s->data[putp + 3] = (u_char)l; + return 4; +} + +/* Put long word to the stream. */ +int +stream_put_ipv4 (struct stream *s, u_int32_t l) +{ + if ((s->size - s->putp) < 4) + return 0; + + memcpy (s->data + s->putp, &l, 4); + s->putp += 4; + + if (s->putp > s->endp) + s->endp = s->putp; + return 4; +} + +/* Put long word to the stream. */ +int +stream_put_in_addr (struct stream *s, struct in_addr *addr) +{ + if ((s->size - s->putp) < 4) + return 0; + + memcpy (s->data + s->putp, addr, 4); + s->putp += 4; + + if (s->putp > s->endp) + s->endp = s->putp; + return 4; +} + +/* Put prefix by nlri type format. */ +int +stream_put_prefix (struct stream *s, struct prefix *p) +{ + u_char psize; + + psize = PSIZE (p->prefixlen); + + if ((s->size - s->putp) < psize) return 0; + + stream_putc (s, p->prefixlen); + memcpy (s->data + s->putp, &p->u.prefix, psize); + s->putp += psize; + + if (s->putp > s->endp) + s->endp = s->putp; + + return psize; +} + +/* Read size from fd. */ +int +stream_read (struct stream *s, int fd, size_t size) +{ + int nbytes; + + nbytes = readn (fd, s->data + s->putp, size); + + if (nbytes > 0) + { + s->putp += nbytes; + s->endp += nbytes; + } + return nbytes; +} + +/* Read size from fd. */ +int +stream_read_unblock (struct stream *s, int fd, size_t size) +{ + int nbytes; + int val; + + val = fcntl (fd, F_GETFL, 0); + fcntl (fd, F_SETFL, val|O_NONBLOCK); + nbytes = read (fd, s->data + s->putp, size); + fcntl (fd, F_SETFL, val); + + if (nbytes > 0) + { + s->putp += nbytes; + s->endp += nbytes; + } + return nbytes; +} + +/* Write data to buffer. */ +int +stream_write (struct stream *s, u_char *ptr, size_t size) +{ + + CHECK_SIZE(s, size); + + memcpy (s->data + s->putp, ptr, size); + s->putp += size; + if (s->putp > s->endp) + s->endp = s->putp; + return size; +} + +/* Return current read pointer. */ +u_char * +stream_pnt (struct stream *s) +{ + return s->data + s->getp; +} + +/* Check does this stream empty? */ +int +stream_empty (struct stream *s) +{ + if (s->putp == 0 && s->endp == 0 && s->getp == 0) + return 1; + else + return 0; +} + +/* Reset stream. */ +void +stream_reset (struct stream *s) +{ + s->putp = 0; + s->endp = 0; + s->getp = 0; +} + +/* Write stream contens to the file discriptor. */ +int +stream_flush (struct stream *s, int fd) +{ + int nbytes; + + nbytes = write (fd, s->data + s->getp, s->endp - s->getp); + + return nbytes; +} + +/* Stream first in first out queue. */ + +struct stream_fifo * +stream_fifo_new () +{ + struct stream_fifo *new; + + new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo)); + return new; +} + +/* Add new stream to fifo. */ +void +stream_fifo_push (struct stream_fifo *fifo, struct stream *s) +{ + if (fifo->tail) + fifo->tail->next = s; + else + fifo->head = s; + + fifo->tail = s; + + fifo->count++; +} + +/* Delete first stream from fifo. */ +struct stream * +stream_fifo_pop (struct stream_fifo *fifo) +{ + struct stream *s; + + s = fifo->head; + + if (s) + { + fifo->head = s->next; + + if (fifo->head == NULL) + fifo->tail = NULL; + } + + fifo->count--; + + return s; +} + +/* Return first fifo entry. */ +struct stream * +stream_fifo_head (struct stream_fifo *fifo) +{ + return fifo->head; +} + +void +stream_fifo_clean (struct stream_fifo *fifo) +{ + struct stream *s; + struct stream *next; + + for (s = fifo->head; s; s = next) + { + next = s->next; + stream_free (s); + } + fifo->head = fifo->tail = NULL; + fifo->count = 0; +} + +void +stream_fifo_free (struct stream_fifo *fifo) +{ + stream_fifo_clean (fifo); + XFREE (MTYPE_STREAM_FIFO, fifo); +} -- cgit v1.2.3 From 0e43a2bcc0b044ec8e92108811c1341076938af9 Mon Sep 17 00:00:00 2001 From: paul Date: Wed, 22 Dec 2004 00:15:34 +0000 Subject: 2004-12-21 Paul Jakma * stream.c: Dont allocate streams with 0 sized data buffers --- lib/stream.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib/stream.c') diff --git a/lib/stream.c b/lib/stream.c index 2d4de760..1b85b130 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -46,6 +46,11 @@ stream_new (size_t size) { struct stream *s; + assert (size > 0); + + if (size == 0) + return NULL; + s = XCALLOC (MTYPE_STREAM, sizeof (struct stream)); s->data = XCALLOC (MTYPE_STREAM_DATA, size); -- cgit v1.2.3 From 9985f83ce7102f64b15f744b60320f8d14a8a5ff Mon Sep 17 00:00:00 2001 From: paul Date: Wed, 9 Feb 2005 15:51:56 +0000 Subject: 2005-02-09 Paul Jakma * (global) Update code to match stream.h changes. stream_get_putp effectively replaced with stream_get_endp. stream_forward renamed to stream_forward_getp. stream_forward_endp introduced to replace some previous setting/manual twiddling of putp by daemons. * lib/stream.h: Remove putp. Update reference to putp with endp. Add stream_forward_endp, which daemons were doing manually. Rename stream_forward to stream_forward_getp. lib/stream.c: Remove/update references to putp. introduce stream_forward_endp. --- lib/stream.c | 108 +++++++++++++++++++++++------------------------------------ 1 file changed, 41 insertions(+), 67 deletions(-) (limited to 'lib/stream.c') diff --git a/lib/stream.c b/lib/stream.c index 1b85b130..7a8bc458 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -35,8 +35,8 @@ */ #define CHECK_SIZE(S, Z) \ - if (((S)->putp + (Z)) > (S)->size) \ - (Z) = (S)->size - (S)->putp; + if (((S)->endp + (Z)) > (S)->size) \ + (Z) = (S)->size - (S)->endp; /* Stream is fixed length buffer for network output/input. */ @@ -72,12 +72,6 @@ stream_get_getp (struct stream *s) return s->getp; } -unsigned long -stream_get_putp (struct stream *s) -{ - return s->putp; -} - unsigned long stream_get_endp (struct stream *s) { @@ -97,17 +91,17 @@ stream_set_getp (struct stream *s, unsigned long pos) s->getp = pos; } +/* Forward pointer. */ void -stream_set_putp (struct stream *s, unsigned long pos) +stream_forward_getp (struct stream *s, int size) { - s->putp = pos; + s->getp += size; } -/* Forward pointer. */ void -stream_forward (struct stream *s, int size) +stream_forward_endp (struct stream *s, int size) { - s->getp += size; + s->endp += size; } /* Copy from stream to destination. */ @@ -194,25 +188,22 @@ stream_put (struct stream *s, void *src, size_t size) CHECK_SIZE(s, size); if (src) - memcpy (s->data + s->putp, src, size); + memcpy (s->data + s->endp, src, size); else - memset (s->data + s->putp, 0, size); + memset (s->data + s->endp, 0, size); - s->putp += size; - if (s->putp > s->endp) - s->endp = s->putp; + s->endp += size; } /* Put character to the stream. */ int stream_putc (struct stream *s, u_char c) { - if (s->putp >= s->size) return 0; + if (s->endp >= s->size) return 0; + + s->data[s->endp] = c; + s->endp++; - s->data[s->putp] = c; - s->putp++; - if (s->putp > s->endp) - s->endp = s->putp; return 1; } @@ -220,13 +211,11 @@ stream_putc (struct stream *s, u_char c) int stream_putw (struct stream *s, u_int16_t w) { - if ((s->size - s->putp) < 2) return 0; + if ((s->size - s->endp) < 2) return 0; - s->data[s->putp++] = (u_char)(w >> 8); - s->data[s->putp++] = (u_char) w; + s->data[s->endp++] = (u_char)(w >> 8); + s->data[s->endp++] = (u_char) w; - if (s->putp > s->endp) - s->endp = s->putp; return 2; } @@ -234,15 +223,13 @@ stream_putw (struct stream *s, u_int16_t w) int stream_putl (struct stream *s, u_int32_t l) { - if ((s->size - s->putp) < 4) return 0; + if ((s->size - s->endp) < 4) return 0; - s->data[s->putp++] = (u_char)(l >> 24); - s->data[s->putp++] = (u_char)(l >> 16); - s->data[s->putp++] = (u_char)(l >> 8); - s->data[s->putp++] = (u_char)l; + s->data[s->endp++] = (u_char)(l >> 24); + s->data[s->endp++] = (u_char)(l >> 16); + s->data[s->endp++] = (u_char)(l >> 8); + s->data[s->endp++] = (u_char)l; - if (s->putp > s->endp) - s->endp = s->putp; return 4; } @@ -275,14 +262,12 @@ stream_putl_at (struct stream *s, unsigned long putp, u_int32_t l) int stream_put_ipv4 (struct stream *s, u_int32_t l) { - if ((s->size - s->putp) < 4) + if ((s->size - s->endp) < 4) return 0; - memcpy (s->data + s->putp, &l, 4); - s->putp += 4; + memcpy (s->data + s->endp, &l, 4); + s->endp += 4; - if (s->putp > s->endp) - s->endp = s->putp; return 4; } @@ -290,14 +275,12 @@ stream_put_ipv4 (struct stream *s, u_int32_t l) int stream_put_in_addr (struct stream *s, struct in_addr *addr) { - if ((s->size - s->putp) < 4) + if ((s->size - s->endp) < 4) return 0; - memcpy (s->data + s->putp, addr, 4); - s->putp += 4; + memcpy (s->data + s->endp, addr, 4); + s->endp += 4; - if (s->putp > s->endp) - s->endp = s->putp; return 4; } @@ -309,15 +292,12 @@ stream_put_prefix (struct stream *s, struct prefix *p) psize = PSIZE (p->prefixlen); - if ((s->size - s->putp) < psize) return 0; + if ((s->size - s->endp) < psize) return 0; stream_putc (s, p->prefixlen); - memcpy (s->data + s->putp, &p->u.prefix, psize); - s->putp += psize; + memcpy (s->data + s->endp, &p->u.prefix, psize); + s->endp += psize; - if (s->putp > s->endp) - s->endp = s->putp; - return psize; } @@ -327,13 +307,11 @@ stream_read (struct stream *s, int fd, size_t size) { int nbytes; - nbytes = readn (fd, s->data + s->putp, size); + nbytes = readn (fd, s->data + s->endp, size); if (nbytes > 0) - { - s->putp += nbytes; - s->endp += nbytes; - } + s->endp += nbytes; + return nbytes; } @@ -346,14 +324,12 @@ stream_read_unblock (struct stream *s, int fd, size_t size) val = fcntl (fd, F_GETFL, 0); fcntl (fd, F_SETFL, val|O_NONBLOCK); - nbytes = read (fd, s->data + s->putp, size); + nbytes = read (fd, s->data + s->endp, size); fcntl (fd, F_SETFL, val); if (nbytes > 0) - { - s->putp += nbytes; - s->endp += nbytes; - } + s->endp += nbytes; + return nbytes; } @@ -364,10 +340,9 @@ stream_write (struct stream *s, u_char *ptr, size_t size) CHECK_SIZE(s, size); - memcpy (s->data + s->putp, ptr, size); - s->putp += size; - if (s->putp > s->endp) - s->endp = s->putp; + memcpy (s->data + s->endp, ptr, size); + s->endp += size; + return size; } @@ -382,7 +357,7 @@ stream_pnt (struct stream *s) int stream_empty (struct stream *s) { - if (s->putp == 0 && s->endp == 0 && s->getp == 0) + if (s->endp == 0 && s->getp == 0) return 1; else return 0; @@ -392,7 +367,6 @@ stream_empty (struct stream *s) void stream_reset (struct stream *s) { - s->putp = 0; s->endp = 0; s->getp = 0; } -- cgit v1.2.3 From f2e6c429375adf0d3c5deaa409734d5d41ac15ce Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 12 Feb 2005 14:35:49 +0000 Subject: 2005-02-12 Paul Jakma * stream.h: Unsigned long updated to size_t * stream.c: ditto --- lib/stream.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'lib/stream.c') diff --git a/lib/stream.c b/lib/stream.c index 7a8bc458..ebeea333 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -66,19 +66,19 @@ stream_free (struct stream *s) XFREE (MTYPE_STREAM, s); } -unsigned long +size_t stream_get_getp (struct stream *s) { return s->getp; } -unsigned long +size_t stream_get_endp (struct stream *s) { return s->endp; } -unsigned long +size_t stream_get_size (struct stream *s) { return s->size; @@ -86,7 +86,7 @@ stream_get_size (struct stream *s) /* Stream structre' stream pointer related functions. */ void -stream_set_getp (struct stream *s, unsigned long pos) +stream_set_getp (struct stream *s, size_t pos) { s->getp = pos; } @@ -125,7 +125,7 @@ stream_getc (struct stream *s) /* Get next character from the stream. */ u_char -stream_getc_from (struct stream *s, unsigned long from) +stream_getc_from (struct stream *s, size_t from) { u_char c; @@ -146,7 +146,7 @@ stream_getw (struct stream *s) /* Get next word from the stream. */ u_int16_t -stream_getw_from (struct stream *s, unsigned long from) +stream_getw_from (struct stream *s, size_t from) { u_int16_t w; @@ -234,14 +234,14 @@ stream_putl (struct stream *s, u_int32_t l) } int -stream_putc_at (struct stream *s, unsigned long putp, u_char c) +stream_putc_at (struct stream *s, size_t putp, u_char c) { s->data[putp] = c; return 1; } int -stream_putw_at (struct stream *s, unsigned long putp, u_int16_t w) +stream_putw_at (struct stream *s, size_t putp, u_int16_t w) { s->data[putp] = (u_char)(w >> 8); s->data[putp + 1] = (u_char) w; @@ -249,7 +249,7 @@ stream_putw_at (struct stream *s, unsigned long putp, u_int16_t w) } int -stream_putl_at (struct stream *s, unsigned long putp, u_int32_t l) +stream_putl_at (struct stream *s, size_t putp, u_int32_t l) { s->data[putp] = (u_char)(l >> 24); s->data[putp + 1] = (u_char)(l >> 16); -- cgit v1.2.3 From 050c013ac35337d86b03f140fb17d2e8e33a8baa Mon Sep 17 00:00:00 2001 From: paul Date: Mon, 14 Feb 2005 23:47:47 +0000 Subject: 2005-02-14 Paul Jakma * stream.h: Unsigned long updated to size_t * stream.c: ditto * stream.h: Add stream_copy, stream_dup, stream_recvmsg. Add comment describing struct stream abstraction, and various other comments. Deprecate several unsafe/ambigious macros. Add STREAM_WRITEABLE and STREAM_READABLE. Add (stream_getl_from) for symmetry. Update stream_forward_{endp,getp} to use size_t offset. Make stream data a 0 length array, rather than a seperate malloc. * stream.c: Add consistency checks. Update to follow stream.h changes. (stream_new) Alloc stream+data in one go. (stream_copy) new function, copy a stream. (stream_dup) new function, dup a stream. (stream_recvmsg) new function, recvmsg data into a stream. (stream_empty) no need to check getp == 0. --- lib/stream.c | 434 +++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 376 insertions(+), 58 deletions(-) (limited to 'lib/stream.c') diff --git a/lib/stream.c b/lib/stream.c index ebeea333..e15d0426 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -1,4 +1,4 @@ -/* + /* * Packet interface * Copyright (C) 1999 Kunihiro Ishiguro * @@ -20,25 +20,70 @@ * 02111-1307, USA. */ +#include #include #include "stream.h" #include "memory.h" #include "network.h" #include "prefix.h" +#include "log.h" +/* Tests whether a position is valid */ +#define GETP_VALID(S,G) \ + ((G) <= (S)->endp) +#define PUT_AT_VALID(S,G) GETP_VALID(S,G) +#define ENDP_VALID(S,E) \ + ((E) <= (S)->size) -/*A macro to check pointers in order to not - go behind the allocated mem block - S -- stream reference - Z -- size of data to be written -*/ - +/* asserting sanity checks. Following must be true before + * stream functions are called: + * + * Following must always be true of stream elements + * before and after calls to stream functions: + * + * getp <= endp <= size + * + * Note that after a stream function is called following may be true: + * if (getp == endp) then stream is no longer readable + * if (endp == size) then stream is no longer writeable + * + * It is valid to put to anywhere within the size of the stream, but only + * using stream_put..._at() functions. + */ +#define STREAM_WARN_OFFSETS(S) \ + zlog_warn ("&(struct stream): %p, size: %lu, endp: %lu, getp: %lu\n", \ + (S), \ + (unsigned long) (S)->size, \ + (unsigned long) (S)->getp, \ + (unsigned long) (S)->endp)\ + +#define STREAM_VERIFY_SANE(S) \ + do { \ + if ( !(GETP_VALID(S, (S)->getp)) && ENDP_VALID(S, (S)->endp) ) \ + STREAM_WARN_OFFSETS(S); \ + assert ( GETP_VALID(S, (S)->getp) ); \ + assert ( ENDP_VALID(S, (S)->endp) ); \ + } while (0) + +#define STREAM_BOUND_WARN(S, WHAT) \ + do { \ + zlog_warn ("%s: Attempt to %s out of bounds", __func__, (WHAT)); \ + STREAM_WARN_OFFSETS(S); \ + assert (0); \ + } while (0) + +/* XXX: Deprecated macro: do not use */ #define CHECK_SIZE(S, Z) \ - if (((S)->endp + (Z)) > (S)->size) \ - (Z) = (S)->size - (S)->endp; - -/* Stream is fixed length buffer for network output/input. */ + do { \ + if (((S)->endp + (Z)) > (S)->size) \ + { \ + zlog_warn ("CHECK_SIZE: truncating requested size %lu\n", \ + (unsigned long) (Z)); \ + STREAM_WARN_OFFSETS(S); \ + (Z) = (S)->size - (S)->endp; \ + } \ + } while (0); /* Make stream buffer. */ struct stream * @@ -49,11 +94,16 @@ stream_new (size_t size) assert (size > 0); if (size == 0) - return NULL; + { + zlog_warn ("stream_new(): called with 0 size!"); + return NULL; + } - s = XCALLOC (MTYPE_STREAM, sizeof (struct stream)); + s = XCALLOC (MTYPE_STREAM, offsetof(struct stream, size)); - s->data = XCALLOC (MTYPE_STREAM_DATA, size); + if (s == NULL) + return s; + s->size = size; return s; } @@ -62,25 +112,56 @@ stream_new (size_t size) void stream_free (struct stream *s) { - XFREE (MTYPE_STREAM_DATA, s->data); XFREE (MTYPE_STREAM, s); } + +struct stream * +stream_copy (struct stream *new, struct stream *src) +{ + STREAM_VERIFY_SANE (src); + + assert (new != NULL); + assert (STREAM_SIZE(new) >= src->endp); + + new->endp = src->endp; + new->getp = src->getp; + + memcpy (new->data, src->data, src->endp); + + return new; +} + +struct stream * +stream_dup (struct stream *s) +{ + struct stream *new; + + STREAM_VERIFY_SANE (s); + + if ( (new = stream_new (s->endp)) == NULL) + return NULL; + + return (stream_copy (new, s)); +} size_t stream_get_getp (struct stream *s) { + STREAM_VERIFY_SANE(s); return s->getp; } size_t stream_get_endp (struct stream *s) { + STREAM_VERIFY_SANE(s); return s->endp; } size_t stream_get_size (struct stream *s) { + STREAM_VERIFY_SANE(s); return s->size; } @@ -88,19 +169,43 @@ stream_get_size (struct stream *s) void stream_set_getp (struct stream *s, size_t pos) { + STREAM_VERIFY_SANE(s); + + if (!GETP_VALID (s, pos)) + { + STREAM_BOUND_WARN (s, "set getp"); + pos = s->endp; + } + s->getp = pos; } /* Forward pointer. */ void -stream_forward_getp (struct stream *s, int size) +stream_forward_getp (struct stream *s, size_t size) { + STREAM_VERIFY_SANE(s); + + if (!GETP_VALID (s, s->getp + size)) + { + STREAM_BOUND_WARN (s, "seek getp"); + return; + } + s->getp += size; } void -stream_forward_endp (struct stream *s, int size) +stream_forward_endp (struct stream *s, size_t size) { + STREAM_VERIFY_SANE(s); + + if (!ENDP_VALID (s, s->endp + size)) + { + STREAM_BOUND_WARN (s, "seek endp"); + return; + } + s->endp += size; } @@ -108,6 +213,14 @@ stream_forward_endp (struct stream *s, int size) void stream_get (void *dst, struct stream *s, size_t size) { + STREAM_VERIFY_SANE(s); + + if (STREAM_READABLE(s) < size) + { + STREAM_BOUND_WARN (s, "get"); + return; + } + memcpy (dst, s->data + s->getp, size); s->getp += size; } @@ -117,9 +230,16 @@ u_char stream_getc (struct stream *s) { u_char c; + + STREAM_VERIFY_SANE (s); - c = s->data[s->getp]; - s->getp++; + if (STREAM_READABLE(s) < sizeof (u_char)) + { + STREAM_BOUND_WARN (s, "get char"); + return 0; + } + c = s->data[s->getp++]; + return c; } @@ -129,7 +249,16 @@ stream_getc_from (struct stream *s, size_t from) { u_char c; + STREAM_VERIFY_SANE(s); + + if (!GETP_VALID (s, from + sizeof (u_char))) + { + STREAM_BOUND_WARN (s, "get char"); + return 0; + } + c = s->data[from]; + return c; } @@ -139,8 +268,17 @@ stream_getw (struct stream *s) { u_int16_t w; + STREAM_VERIFY_SANE (s); + + if (STREAM_READABLE (s) < sizeof (u_int16_t)) + { + STREAM_BOUND_WARN (s, "get "); + return 0; + } + w = s->data[s->getp++] << 8; w |= s->data[s->getp++]; + return w; } @@ -150,43 +288,102 @@ stream_getw_from (struct stream *s, size_t from) { u_int16_t w; + STREAM_VERIFY_SANE(s); + + if (!GETP_VALID (s, from + sizeof (u_int16_t))) + { + STREAM_BOUND_WARN (s, "get "); + return 0; + } + w = s->data[from++] << 8; w |= s->data[from]; + return w; } /* Get next long word from the stream. */ +u_int32_t +stream_getl_from (struct stream *s, size_t from) +{ + u_int32_t l; + + STREAM_VERIFY_SANE(s); + + if (!GETP_VALID (s, from + sizeof (u_int32_t))) + { + STREAM_BOUND_WARN (s, "get long"); + return 0; + } + + l = s->data[from++] << 24; + l |= s->data[from++] << 16; + l |= s->data[from++] << 8; + l |= s->data[from]; + + return l; +} + u_int32_t stream_getl (struct stream *s) { u_int32_t l; + STREAM_VERIFY_SANE(s); + + if (STREAM_READABLE (s) < sizeof (u_int32_t)) + { + STREAM_BOUND_WARN (s, "get long"); + return 0; + } + l = s->data[s->getp++] << 24; l |= s->data[s->getp++] << 16; l |= s->data[s->getp++] << 8; l |= s->data[s->getp++]; + return l; } - /* Get next long word from the stream. */ u_int32_t stream_get_ipv4 (struct stream *s) { u_int32_t l; - memcpy (&l, s->data + s->getp, 4); - s->getp += 4; + STREAM_VERIFY_SANE(s); + + if (STREAM_READABLE (s) < sizeof(u_int32_t)) + { + STREAM_BOUND_WARN (s, "get ipv4"); + return 0; + } + + memcpy (&l, s->data + s->getp, sizeof(u_int32_t)); + s->getp += sizeof(u_int32_t); return l; } -/* Copy to source to stream. */ +/* Copy to source to stream. + * + * XXX: This uses CHECK_SIZE and hence has funny semantics -> Size will wrap + * around. This should be fixed once the stream updates are working. + */ void stream_put (struct stream *s, void *src, size_t size) { + /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */ CHECK_SIZE(s, size); - + + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE (s) < size) + { + STREAM_BOUND_WARN (s, "put"); + return; + } + if (src) memcpy (s->data + s->endp, src, size); else @@ -199,20 +396,30 @@ stream_put (struct stream *s, void *src, size_t size) int stream_putc (struct stream *s, u_char c) { - if (s->endp >= s->size) return 0; - - s->data[s->endp] = c; - s->endp++; - - return 1; + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE (s) < sizeof(u_char)) + { + STREAM_BOUND_WARN (s, "put"); + return 0; + } + + s->data[s->endp++] = c; + return sizeof (u_char); } /* Put word to the stream. */ int stream_putw (struct stream *s, u_int16_t w) { - if ((s->size - s->endp) < 2) return 0; + STREAM_VERIFY_SANE (s); + if (STREAM_WRITEABLE (s) < sizeof (u_int16_t)) + { + STREAM_BOUND_WARN (s, "put"); + return 0; + } + s->data[s->endp++] = (u_char)(w >> 8); s->data[s->endp++] = (u_char) w; @@ -223,8 +430,14 @@ stream_putw (struct stream *s, u_int16_t w) int stream_putl (struct stream *s, u_int32_t l) { - if ((s->size - s->endp) < 4) return 0; + STREAM_VERIFY_SANE (s); + if (STREAM_WRITEABLE (s) < sizeof (u_int32_t)) + { + STREAM_BOUND_WARN (s, "put"); + return 0; + } + s->data[s->endp++] = (u_char)(l >> 24); s->data[s->endp++] = (u_char)(l >> 16); s->data[s->endp++] = (u_char)(l >> 8); @@ -236,25 +449,51 @@ stream_putl (struct stream *s, u_int32_t l) int stream_putc_at (struct stream *s, size_t putp, u_char c) { + STREAM_VERIFY_SANE(s); + + if (!PUT_AT_VALID (s, putp + sizeof (u_char))) + { + STREAM_BOUND_WARN (s, "put"); + return 0; + } + s->data[putp] = c; + return 1; } int stream_putw_at (struct stream *s, size_t putp, u_int16_t w) { + STREAM_VERIFY_SANE(s); + + if (!PUT_AT_VALID (s, putp + sizeof (u_int16_t))) + { + STREAM_BOUND_WARN (s, "put"); + return 0; + } + s->data[putp] = (u_char)(w >> 8); s->data[putp + 1] = (u_char) w; + return 2; } int stream_putl_at (struct stream *s, size_t putp, u_int32_t l) { + STREAM_VERIFY_SANE(s); + + if (!PUT_AT_VALID (s, putp + sizeof (u_int32_t))) + { + STREAM_BOUND_WARN (s, "put"); + return 0; + } s->data[putp] = (u_char)(l >> 24); s->data[putp + 1] = (u_char)(l >> 16); s->data[putp + 2] = (u_char)(l >> 8); s->data[putp + 3] = (u_char)l; + return 4; } @@ -262,38 +501,53 @@ stream_putl_at (struct stream *s, size_t putp, u_int32_t l) int stream_put_ipv4 (struct stream *s, u_int32_t l) { - if ((s->size - s->endp) < 4) - return 0; - - memcpy (s->data + s->endp, &l, 4); - s->endp += 4; + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE (s) < sizeof (u_int32_t)) + { + STREAM_BOUND_WARN (s, "put"); + return 0; + } + memcpy (s->data + s->endp, &l, sizeof (u_int32_t)); + s->endp += sizeof (u_int32_t); - return 4; + return sizeof (u_int32_t); } /* Put long word to the stream. */ int stream_put_in_addr (struct stream *s, struct in_addr *addr) { - if ((s->size - s->endp) < 4) - return 0; + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE (s) < sizeof (u_int32_t)) + { + STREAM_BOUND_WARN (s, "put"); + return 0; + } - memcpy (s->data + s->endp, addr, 4); - s->endp += 4; + memcpy (s->data + s->endp, addr, sizeof (u_int32_t)); + s->endp += sizeof (u_int32_t); - return 4; + return sizeof (u_int32_t); } /* Put prefix by nlri type format. */ int stream_put_prefix (struct stream *s, struct prefix *p) { - u_char psize; - + size_t psize; + + STREAM_VERIFY_SANE(s); + psize = PSIZE (p->prefixlen); - - if ((s->size - s->endp) < psize) return 0; - + + if (STREAM_WRITEABLE (s) < psize) + { + STREAM_BOUND_WARN (s, "put"); + return 0; + } + stream_putc (s, p->prefixlen); memcpy (s->data + s->endp, &p->u.prefix, psize); s->endp += psize; @@ -307,6 +561,14 @@ stream_read (struct stream *s, int fd, size_t size) { int nbytes; + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE (s) < size) + { + STREAM_BOUND_WARN (s, "put"); + return 0; + } + nbytes = readn (fd, s->data + s->endp, size); if (nbytes > 0) @@ -321,7 +583,15 @@ stream_read_unblock (struct stream *s, int fd, size_t size) { int nbytes; int val; - + + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE (s) < size) + { + STREAM_BOUND_WARN (s, "put"); + return 0; + } + val = fcntl (fd, F_GETFL, 0); fcntl (fd, F_SETFL, val|O_NONBLOCK); nbytes = read (fd, s->data + s->endp, size); @@ -333,6 +603,39 @@ stream_read_unblock (struct stream *s, int fd, size_t size) return nbytes; } +/* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting + * from endp. + * First iovec will be used to receive the data. + * Stream need not be empty. + */ +int +stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags, + size_t size) +{ + int nbytes; + struct iovec *iov; + + STREAM_VERIFY_SANE(s); + assert (msgh->msg_iovlen > 0); + + if (STREAM_WRITEABLE (s) < size) + { + STREAM_BOUND_WARN (s, "put"); + return 0; + } + + iov = &(msgh->msg_iov[0]); + iov->iov_base = (s->data + s->endp); + iov->iov_len = size; + + nbytes = recvmsg (fd, msgh, flags); + + if (nbytes > 0) + s->endp += nbytes; + + return nbytes; +} + /* Write data to buffer. */ int stream_write (struct stream *s, u_char *ptr, size_t size) @@ -340,16 +643,29 @@ stream_write (struct stream *s, u_char *ptr, size_t size) CHECK_SIZE(s, size); + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE (s) < size) + { + STREAM_BOUND_WARN (s, "put"); + return 0; + } + memcpy (s->data + s->endp, ptr, size); s->endp += size; return size; } -/* Return current read pointer. */ +/* Return current read pointer. + * DEPRECATED! + * Use stream_get_pnt_to if you must, but decoding streams properly + * is preferred + */ u_char * stream_pnt (struct stream *s) { + STREAM_VERIFY_SANE(s); return s->data + s->getp; } @@ -357,18 +673,18 @@ stream_pnt (struct stream *s) int stream_empty (struct stream *s) { - if (s->endp == 0 && s->getp == 0) - return 1; - else - return 0; + STREAM_VERIFY_SANE(s); + + return (s->endp == 0); } /* Reset stream. */ void stream_reset (struct stream *s) { - s->endp = 0; - s->getp = 0; + STREAM_VERIFY_SANE (s); + + s->getp = s->endp = 0; } /* Write stream contens to the file discriptor. */ @@ -376,9 +692,11 @@ int stream_flush (struct stream *s, int fd) { int nbytes; - + + STREAM_VERIFY_SANE(s); + nbytes = write (fd, s->data + s->getp, s->endp - s->getp); - + return nbytes; } -- cgit v1.2.3 From 262feb1ad0838bb585955b6ada5acbe106dbc9bf Mon Sep 17 00:00:00 2001 From: ajs Date: Wed, 16 Feb 2005 20:35:47 +0000 Subject: 2005-02-16 Andrew J. Schorr * stream.h: Declare new function stream_read_try suitable for use with non-blocking file descriptors. Indicate that stream_read and stream_read_unblock are deprecated. * stream.c: (stream_read_try) New function for use with non-blocking I/O. (stream_recvmsg) Should return -1 if the stream is too small to contain the data. --- lib/stream.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'lib/stream.c') diff --git a/lib/stream.c b/lib/stream.c index e15d0426..7e75f0da 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -603,6 +603,31 @@ stream_read_unblock (struct stream *s, int fd, size_t size) return nbytes; } +ssize_t +stream_read_try(struct stream *s, int fd, size_t size) +{ + ssize_t nbytes; + + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE(s) < size) + { + STREAM_BOUND_WARN (s, "put"); + /* Fatal (not transient) error, since retrying will not help + (stream is too small to contain the desired data). */ + return -1; + } + + if ((nbytes = read(fd, s->data + s->endp, size)) >= 0) + { + s->endp += nbytes; + return nbytes; + } + /* Error: was it transient (return -2) or fatal (return -1)? */ + return ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINTR)) ? + -2 : -1; +} + /* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting * from endp. * First iovec will be used to receive the data. @@ -621,7 +646,9 @@ stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags, if (STREAM_WRITEABLE (s) < size) { STREAM_BOUND_WARN (s, "put"); - return 0; + /* This is a logic error in the calling code: the stream is too small + to hold the desired data! */ + return -1; } iov = &(msgh->msg_iov[0]); -- cgit v1.2.3 From 53270116df3f54b1f9411f0832567e9effa87593 Mon Sep 17 00:00:00 2001 From: ajs Date: Thu, 17 Feb 2005 20:07:22 +0000 Subject: 2005-02-17 Andrew J. Schorr * stream.c: (stream_read_try) Use new ERRNO_IO_RETRY macro. --- lib/stream.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/stream.c') diff --git a/lib/stream.c b/lib/stream.c index 7e75f0da..a50835eb 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -624,8 +624,7 @@ stream_read_try(struct stream *s, int fd, size_t size) return nbytes; } /* Error: was it transient (return -2) or fatal (return -1)? */ - return ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINTR)) ? - -2 : -1; + return ERRNO_IO_RETRY(errno) ? -2 : -1; } /* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting -- cgit v1.2.3 From 109ac96f0296fd66d5a1d37def44db3cef7ca0fb Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 19 Feb 2005 01:17:07 +0000 Subject: 2005-02-19 Paul Jakma * stream.c: (stream_new) fix dumb mistake. --- lib/stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/stream.c') diff --git a/lib/stream.c b/lib/stream.c index a50835eb..821ad6e5 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -99,7 +99,7 @@ stream_new (size_t size) return NULL; } - s = XCALLOC (MTYPE_STREAM, offsetof(struct stream, size)); + s = XCALLOC (MTYPE_STREAM, offsetof(struct stream, data[size])); if (s == NULL) return s; -- cgit v1.2.3 From 81fb32404c942432d2bea1e50a4d53bf75fd0f70 Mon Sep 17 00:00:00 2001 From: ajs Date: Thu, 24 Feb 2005 16:02:53 +0000 Subject: 2005-02-24 Andrew J. Schorr * stream.c: (stream_read_try) Log a warning message if a fatal I/O error occurs. (stream_fifo_new) Fix prototype. * stream.h: Fix prototype for stream_fifo_new (need void arg). --- lib/stream.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'lib/stream.c') diff --git a/lib/stream.c b/lib/stream.c index 821ad6e5..b71b8ee9 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -624,7 +624,10 @@ stream_read_try(struct stream *s, int fd, size_t size) return nbytes; } /* Error: was it transient (return -2) or fatal (return -1)? */ - return ERRNO_IO_RETRY(errno) ? -2 : -1; + if (ERRNO_IO_RETRY(errno)) + return -2; + zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno)); + return -1; } /* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting @@ -729,7 +732,7 @@ stream_flush (struct stream *s, int fd) /* Stream first in first out queue. */ struct stream_fifo * -stream_fifo_new () +stream_fifo_new (void) { struct stream_fifo *new; -- cgit v1.2.3 From 0dab930314e215a627f848ffa824ed995eb2e13c Mon Sep 17 00:00:00 2001 From: paul Date: Tue, 3 May 2005 09:07:56 +0000 Subject: 2005-05-03 Paul Jakma * stream.h: Add comment about the special zero-ing ability of stream_put. (stream_recvmsg, stream_write) should return ssize_t and size_t respectively. Should both be extern linkage. (stream_recvfrom) Stream aware wrapper around recvfrom, in style of stream_read_try. * stream.c: (stream_recvfrom) new function, wrapper around recvfrom. (stream_recvmsg, stream_write) ssize_t and size_t return values --- lib/stream.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'lib/stream.c') diff --git a/lib/stream.c b/lib/stream.c index b71b8ee9..d8c10882 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -368,6 +368,8 @@ stream_get_ipv4 (struct stream *s) * * XXX: This uses CHECK_SIZE and hence has funny semantics -> Size will wrap * around. This should be fixed once the stream updates are working. + * + * stream_write() is saner */ void stream_put (struct stream *s, void *src, size_t size) @@ -630,12 +632,44 @@ stream_read_try(struct stream *s, int fd, size_t size) return -1; } +/* Read up to size bytes into the stream from the fd, using recvmsgfrom + * whose arguments match the remaining arguments to this function + */ +ssize_t +stream_recvfrom (struct stream *s, int fd, size_t size, int flags, + struct sockaddr *from, socklen_t *fromlen) +{ + ssize_t nbytes; + + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE(s) < size) + { + STREAM_BOUND_WARN (s, "put"); + /* Fatal (not transient) error, since retrying will not help + (stream is too small to contain the desired data). */ + return -1; + } + + if ((nbytes = recvfrom (fd, s->data + s->endp, size, + flags, from, fromlen)) >= 0) + { + s->endp += nbytes; + return nbytes; + } + /* Error: was it transient (return -2) or fatal (return -1)? */ + if (ERRNO_IO_RETRY(errno)) + return -2; + zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno)); + return -1; +} + /* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting * from endp. * First iovec will be used to receive the data. * Stream need not be empty. */ -int +ssize_t stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags, size_t size) { @@ -666,7 +700,7 @@ stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags, } /* Write data to buffer. */ -int +size_t stream_write (struct stream *s, u_char *ptr, size_t size) { -- cgit v1.2.3 From 4b201d46348b81bd9d59aa626c81f7457ea6ef38 Mon Sep 17 00:00:00 2001 From: paul Date: Tue, 10 Jan 2006 14:35:19 +0000 Subject: [stream] Add quad-word support and stream_resize 2006-01-10 Paul Jakma * stream.c: (stream_new) Allocate stream data as seperate object. (stream_free) free the data. (stream_resize) new function, resize stream to new size. (stream_{get,put}q*) new functions to get/put quad word size types. * stream.h: (struct stream) make data seperate from the stream. Export new stream_resize and quad-word get/put functions. --- lib/stream.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 133 insertions(+), 1 deletion(-) (limited to 'lib/stream.c') diff --git a/lib/stream.c b/lib/stream.c index d8c10882..4c5c44ad 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -99,11 +99,17 @@ stream_new (size_t size) return NULL; } - s = XCALLOC (MTYPE_STREAM, offsetof(struct stream, data[size])); + s = XCALLOC (MTYPE_STREAM, sizeof (struct stream)); if (s == NULL) return s; + if ( (s->data = XMALLOC (MTYPE_STREAM_DATA, size)) == NULL) + { + XFREE (MTYPE_STREAM, s); + return NULL; + } + s->size = size; return s; } @@ -112,6 +118,10 @@ stream_new (size_t size) void stream_free (struct stream *s) { + if (!s) + return; + + XFREE (MTYPE_STREAM_DATA, s->data); XFREE (MTYPE_STREAM, s); } @@ -143,6 +153,30 @@ stream_dup (struct stream *s) return (stream_copy (new, s)); } + +size_t +stream_resize (struct stream *s, size_t newsize) +{ + u_char *newdata; + STREAM_VERIFY_SANE (s); + + newdata = XREALLOC (MTYPE_STREAM_DATA, s->data, newsize); + + if (newdata == NULL) + return s->size; + + s->data = newdata; + s->size = newsize; + + if (s->endp > s->size) + s->endp = s->size; + if (s->getp > s->endp) + s->getp = s->endp; + + STREAM_VERIFY_SANE (s); + + return s->size; +} size_t stream_get_getp (struct stream *s) @@ -344,6 +378,58 @@ stream_getl (struct stream *s) return l; } + +/* Get next quad word from the stream. */ +uint64_t +stream_getq_from (struct stream *s, size_t from) +{ + u_int64_t q; + + STREAM_VERIFY_SANE(s); + + if (!GETP_VALID (s, from + sizeof (uint64_t))) + { + STREAM_BOUND_WARN (s, "get quad"); + return 0; + } + + q = ((uint64_t) s->data[from++]) << 56; + q |= ((uint64_t) s->data[from++]) << 48; + q |= ((uint64_t) s->data[from++]) << 40; + q |= ((uint64_t) s->data[from++]) << 32; + q |= ((uint64_t) s->data[from++]) << 24; + q |= ((uint64_t) s->data[from++]) << 16; + q |= ((uint64_t) s->data[from++]) << 8; + q |= ((uint64_t) s->data[from++]); + + return q; +} + +uint64_t +stream_getq (struct stream *s) +{ + uint64_t q; + + STREAM_VERIFY_SANE(s); + + if (STREAM_READABLE (s) < sizeof (uint64_t)) + { + STREAM_BOUND_WARN (s, "get quad"); + return 0; + } + + q = ((uint64_t) s->data[s->getp++]) << 56; + q |= ((uint64_t) s->data[s->getp++]) << 48; + q |= ((uint64_t) s->data[s->getp++]) << 40; + q |= ((uint64_t) s->data[s->getp++]) << 32; + q |= ((uint64_t) s->data[s->getp++]) << 24; + q |= ((uint64_t) s->data[s->getp++]) << 16; + q |= ((uint64_t) s->data[s->getp++]) << 8; + q |= ((uint64_t) s->data[s->getp++]); + + return q; +} + /* Get next long word from the stream. */ u_int32_t stream_get_ipv4 (struct stream *s) @@ -448,6 +534,30 @@ stream_putl (struct stream *s, u_int32_t l) return 4; } +/* Put quad word to the stream. */ +int +stream_putq (struct stream *s, uint64_t q) +{ + STREAM_VERIFY_SANE (s); + + if (STREAM_WRITEABLE (s) < sizeof (uint64_t)) + { + STREAM_BOUND_WARN (s, "put quad"); + return 0; + } + + s->data[s->endp++] = (u_char)(q >> 56); + s->data[s->endp++] = (u_char)(q >> 48); + s->data[s->endp++] = (u_char)(q >> 40); + s->data[s->endp++] = (u_char)(q >> 32); + s->data[s->endp++] = (u_char)(q >> 24); + s->data[s->endp++] = (u_char)(q >> 16); + s->data[s->endp++] = (u_char)(q >> 8); + s->data[s->endp++] = (u_char)q; + + return 8; +} + int stream_putc_at (struct stream *s, size_t putp, u_char c) { @@ -499,6 +609,28 @@ stream_putl_at (struct stream *s, size_t putp, u_int32_t l) return 4; } +int +stream_putq_at (struct stream *s, size_t putp, uint64_t q) +{ + STREAM_VERIFY_SANE(s); + + if (!PUT_AT_VALID (s, putp + sizeof (uint64_t))) + { + STREAM_BOUND_WARN (s, "put"); + return 0; + } + s->data[putp] = (u_char)(q >> 56); + s->data[putp + 1] = (u_char)(q >> 48); + s->data[putp + 2] = (u_char)(q >> 40); + s->data[putp + 3] = (u_char)(q >> 32); + s->data[putp + 4] = (u_char)(q >> 24); + s->data[putp + 5] = (u_char)(q >> 16); + s->data[putp + 6] = (u_char)(q >> 8); + s->data[putp + 7] = (u_char)q; + + return 8; +} + /* Put long word to the stream. */ int stream_put_ipv4 (struct stream *s, u_int32_t l) -- cgit v1.2.3 From 581a02a9f71f43012c67217fe12d97808875c352 Mon Sep 17 00:00:00 2001 From: paul Date: Thu, 19 Jan 2006 20:22:16 +0000 Subject: [lib/stream] small compile fix, use uint64_t, not u_int64_t. 2006-01-19 Paul Jakma * stream.c: (stream_getq_from) should use POSIX uint64_t not u_int64_t. Latter is neither a traditional BSD type, nor a POSIX type. --- lib/stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/stream.c') diff --git a/lib/stream.c b/lib/stream.c index 4c5c44ad..7034d904 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -383,7 +383,7 @@ stream_getl (struct stream *s) uint64_t stream_getq_from (struct stream *s, size_t from) { - u_int64_t q; + uint64_t q; STREAM_VERIFY_SANE(s); -- cgit v1.2.3 From 15382922a695cd9245da8a57546d51154c6a35f4 Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 7 Jun 2008 20:42:07 +0000 Subject: [lib] trivial: add const qualifier to stream_put/write 2008-06-07 Paul Jakma * stream.{c,h}: (stream_{put,write}) add const qualifier to source argument. Change u_char to void *. --- lib/stream.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/stream.c') diff --git a/lib/stream.c b/lib/stream.c index 7034d904..983330ff 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -458,7 +458,7 @@ stream_get_ipv4 (struct stream *s) * stream_write() is saner */ void -stream_put (struct stream *s, void *src, size_t size) +stream_put (struct stream *s, const void *src, size_t size) { /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */ @@ -833,7 +833,7 @@ stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags, /* Write data to buffer. */ size_t -stream_write (struct stream *s, u_char *ptr, size_t size) +stream_write (struct stream *s, const void *ptr, size_t size) { CHECK_SIZE(s, size); -- cgit v1.2.3