blob: 821ad6e5a7394e6008bc14654fed96a933b6f9fd [file] [log] [blame]
paul050c0132005-02-14 23:47:47 +00001 /*
paul718e3742002-12-13 20:15:29 +00002 * 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
paul050c0132005-02-14 23:47:47 +000023#include <stddef.h>
paul718e3742002-12-13 20:15:29 +000024#include <zebra.h>
25
26#include "stream.h"
27#include "memory.h"
28#include "network.h"
29#include "prefix.h"
paul050c0132005-02-14 23:47:47 +000030#include "log.h"
paul718e3742002-12-13 20:15:29 +000031
paul050c0132005-02-14 23:47:47 +000032/* 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)
paul718e3742002-12-13 20:15:29 +000038
paul050c0132005-02-14 23:47:47 +000039/* 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, endp: %lu, getp: %lu\n", \
56 (S), \
57 (unsigned long) (S)->size, \
58 (unsigned long) (S)->getp, \
59 (unsigned long) (S)->endp)\
paul718e3742002-12-13 20:15:29 +000060
paul050c0132005-02-14 23:47:47 +000061#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 */
paul718e3742002-12-13 20:15:29 +000077#define CHECK_SIZE(S, Z) \
paul050c0132005-02-14 23:47:47 +000078 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);
paul718e3742002-12-13 20:15:29 +000087
88/* Make stream buffer. */
89struct stream *
90stream_new (size_t size)
91{
92 struct stream *s;
93
paul0e43a2b2004-12-22 00:15:34 +000094 assert (size > 0);
95
96 if (size == 0)
paul050c0132005-02-14 23:47:47 +000097 {
98 zlog_warn ("stream_new(): called with 0 size!");
99 return NULL;
100 }
paul0e43a2b2004-12-22 00:15:34 +0000101
paul109ac962005-02-19 01:17:07 +0000102 s = XCALLOC (MTYPE_STREAM, offsetof(struct stream, data[size]));
paul718e3742002-12-13 20:15:29 +0000103
paul050c0132005-02-14 23:47:47 +0000104 if (s == NULL)
105 return s;
106
paul718e3742002-12-13 20:15:29 +0000107 s->size = size;
108 return s;
109}
110
111/* Free it now. */
112void
113stream_free (struct stream *s)
114{
paul718e3742002-12-13 20:15:29 +0000115 XFREE (MTYPE_STREAM, s);
116}
paul050c0132005-02-14 23:47:47 +0000117
118struct stream *
119stream_copy (struct stream *new, struct stream *src)
120{
121 STREAM_VERIFY_SANE (src);
122
123 assert (new != NULL);
124 assert (STREAM_SIZE(new) >= src->endp);
125
126 new->endp = src->endp;
127 new->getp = src->getp;
128
129 memcpy (new->data, src->data, src->endp);
130
131 return new;
132}
133
134struct stream *
135stream_dup (struct stream *s)
136{
137 struct stream *new;
138
139 STREAM_VERIFY_SANE (s);
140
141 if ( (new = stream_new (s->endp)) == NULL)
142 return NULL;
143
144 return (stream_copy (new, s));
145}
paul718e3742002-12-13 20:15:29 +0000146
paulf2e6c422005-02-12 14:35:49 +0000147size_t
paul718e3742002-12-13 20:15:29 +0000148stream_get_getp (struct stream *s)
149{
paul050c0132005-02-14 23:47:47 +0000150 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000151 return s->getp;
152}
153
paulf2e6c422005-02-12 14:35:49 +0000154size_t
paul718e3742002-12-13 20:15:29 +0000155stream_get_endp (struct stream *s)
156{
paul050c0132005-02-14 23:47:47 +0000157 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000158 return s->endp;
159}
160
paulf2e6c422005-02-12 14:35:49 +0000161size_t
paul718e3742002-12-13 20:15:29 +0000162stream_get_size (struct stream *s)
163{
paul050c0132005-02-14 23:47:47 +0000164 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000165 return s->size;
166}
167
168/* Stream structre' stream pointer related functions. */
169void
paulf2e6c422005-02-12 14:35:49 +0000170stream_set_getp (struct stream *s, size_t pos)
paul718e3742002-12-13 20:15:29 +0000171{
paul050c0132005-02-14 23:47:47 +0000172 STREAM_VERIFY_SANE(s);
173
174 if (!GETP_VALID (s, pos))
175 {
176 STREAM_BOUND_WARN (s, "set getp");
177 pos = s->endp;
178 }
179
paul718e3742002-12-13 20:15:29 +0000180 s->getp = pos;
181}
182
paul718e3742002-12-13 20:15:29 +0000183/* Forward pointer. */
184void
paul050c0132005-02-14 23:47:47 +0000185stream_forward_getp (struct stream *s, size_t size)
paul718e3742002-12-13 20:15:29 +0000186{
paul050c0132005-02-14 23:47:47 +0000187 STREAM_VERIFY_SANE(s);
188
189 if (!GETP_VALID (s, s->getp + size))
190 {
191 STREAM_BOUND_WARN (s, "seek getp");
192 return;
193 }
194
paul718e3742002-12-13 20:15:29 +0000195 s->getp += size;
196}
paul9985f832005-02-09 15:51:56 +0000197
198void
paul050c0132005-02-14 23:47:47 +0000199stream_forward_endp (struct stream *s, size_t size)
paul9985f832005-02-09 15:51:56 +0000200{
paul050c0132005-02-14 23:47:47 +0000201 STREAM_VERIFY_SANE(s);
202
203 if (!ENDP_VALID (s, s->endp + size))
204 {
205 STREAM_BOUND_WARN (s, "seek endp");
206 return;
207 }
208
paul9985f832005-02-09 15:51:56 +0000209 s->endp += size;
210}
paul718e3742002-12-13 20:15:29 +0000211
212/* Copy from stream to destination. */
213void
214stream_get (void *dst, struct stream *s, size_t size)
215{
paul050c0132005-02-14 23:47:47 +0000216 STREAM_VERIFY_SANE(s);
217
218 if (STREAM_READABLE(s) < size)
219 {
220 STREAM_BOUND_WARN (s, "get");
221 return;
222 }
223
paul718e3742002-12-13 20:15:29 +0000224 memcpy (dst, s->data + s->getp, size);
225 s->getp += size;
226}
227
228/* Get next character from the stream. */
229u_char
230stream_getc (struct stream *s)
231{
232 u_char c;
paul050c0132005-02-14 23:47:47 +0000233
234 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000235
paul050c0132005-02-14 23:47:47 +0000236 if (STREAM_READABLE(s) < sizeof (u_char))
237 {
238 STREAM_BOUND_WARN (s, "get char");
239 return 0;
240 }
241 c = s->data[s->getp++];
242
paul718e3742002-12-13 20:15:29 +0000243 return c;
244}
245
246/* Get next character from the stream. */
247u_char
paulf2e6c422005-02-12 14:35:49 +0000248stream_getc_from (struct stream *s, size_t from)
paul718e3742002-12-13 20:15:29 +0000249{
250 u_char c;
251
paul050c0132005-02-14 23:47:47 +0000252 STREAM_VERIFY_SANE(s);
253
254 if (!GETP_VALID (s, from + sizeof (u_char)))
255 {
256 STREAM_BOUND_WARN (s, "get char");
257 return 0;
258 }
259
paul718e3742002-12-13 20:15:29 +0000260 c = s->data[from];
paul050c0132005-02-14 23:47:47 +0000261
paul718e3742002-12-13 20:15:29 +0000262 return c;
263}
264
265/* Get next word from the stream. */
266u_int16_t
267stream_getw (struct stream *s)
268{
269 u_int16_t w;
270
paul050c0132005-02-14 23:47:47 +0000271 STREAM_VERIFY_SANE (s);
272
273 if (STREAM_READABLE (s) < sizeof (u_int16_t))
274 {
275 STREAM_BOUND_WARN (s, "get ");
276 return 0;
277 }
278
paul718e3742002-12-13 20:15:29 +0000279 w = s->data[s->getp++] << 8;
280 w |= s->data[s->getp++];
paul050c0132005-02-14 23:47:47 +0000281
paul718e3742002-12-13 20:15:29 +0000282 return w;
283}
284
285/* Get next word from the stream. */
286u_int16_t
paulf2e6c422005-02-12 14:35:49 +0000287stream_getw_from (struct stream *s, size_t from)
paul718e3742002-12-13 20:15:29 +0000288{
289 u_int16_t w;
290
paul050c0132005-02-14 23:47:47 +0000291 STREAM_VERIFY_SANE(s);
292
293 if (!GETP_VALID (s, from + sizeof (u_int16_t)))
294 {
295 STREAM_BOUND_WARN (s, "get ");
296 return 0;
297 }
298
paul718e3742002-12-13 20:15:29 +0000299 w = s->data[from++] << 8;
300 w |= s->data[from];
paul050c0132005-02-14 23:47:47 +0000301
paul718e3742002-12-13 20:15:29 +0000302 return w;
303}
304
305/* Get next long word from the stream. */
306u_int32_t
paul050c0132005-02-14 23:47:47 +0000307stream_getl_from (struct stream *s, size_t from)
308{
309 u_int32_t l;
310
311 STREAM_VERIFY_SANE(s);
312
313 if (!GETP_VALID (s, from + sizeof (u_int32_t)))
314 {
315 STREAM_BOUND_WARN (s, "get long");
316 return 0;
317 }
318
319 l = s->data[from++] << 24;
320 l |= s->data[from++] << 16;
321 l |= s->data[from++] << 8;
322 l |= s->data[from];
323
324 return l;
325}
326
327u_int32_t
paul718e3742002-12-13 20:15:29 +0000328stream_getl (struct stream *s)
329{
330 u_int32_t l;
331
paul050c0132005-02-14 23:47:47 +0000332 STREAM_VERIFY_SANE(s);
333
334 if (STREAM_READABLE (s) < sizeof (u_int32_t))
335 {
336 STREAM_BOUND_WARN (s, "get long");
337 return 0;
338 }
339
paul718e3742002-12-13 20:15:29 +0000340 l = s->data[s->getp++] << 24;
341 l |= s->data[s->getp++] << 16;
342 l |= s->data[s->getp++] << 8;
343 l |= s->data[s->getp++];
paul050c0132005-02-14 23:47:47 +0000344
paul718e3742002-12-13 20:15:29 +0000345 return l;
346}
paul718e3742002-12-13 20:15:29 +0000347/* Get next long word from the stream. */
348u_int32_t
349stream_get_ipv4 (struct stream *s)
350{
351 u_int32_t l;
352
paul050c0132005-02-14 23:47:47 +0000353 STREAM_VERIFY_SANE(s);
354
355 if (STREAM_READABLE (s) < sizeof(u_int32_t))
356 {
357 STREAM_BOUND_WARN (s, "get ipv4");
358 return 0;
359 }
360
361 memcpy (&l, s->data + s->getp, sizeof(u_int32_t));
362 s->getp += sizeof(u_int32_t);
paul718e3742002-12-13 20:15:29 +0000363
364 return l;
365}
366
paul050c0132005-02-14 23:47:47 +0000367/* Copy to source to stream.
368 *
369 * XXX: This uses CHECK_SIZE and hence has funny semantics -> Size will wrap
370 * around. This should be fixed once the stream updates are working.
371 */
paul718e3742002-12-13 20:15:29 +0000372void
373stream_put (struct stream *s, void *src, size_t size)
374{
375
paul050c0132005-02-14 23:47:47 +0000376 /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */
paul718e3742002-12-13 20:15:29 +0000377 CHECK_SIZE(s, size);
paul050c0132005-02-14 23:47:47 +0000378
379 STREAM_VERIFY_SANE(s);
380
381 if (STREAM_WRITEABLE (s) < size)
382 {
383 STREAM_BOUND_WARN (s, "put");
384 return;
385 }
386
paul718e3742002-12-13 20:15:29 +0000387 if (src)
paul9985f832005-02-09 15:51:56 +0000388 memcpy (s->data + s->endp, src, size);
paul718e3742002-12-13 20:15:29 +0000389 else
paul9985f832005-02-09 15:51:56 +0000390 memset (s->data + s->endp, 0, size);
paul718e3742002-12-13 20:15:29 +0000391
paul9985f832005-02-09 15:51:56 +0000392 s->endp += size;
paul718e3742002-12-13 20:15:29 +0000393}
394
395/* Put character to the stream. */
396int
397stream_putc (struct stream *s, u_char c)
398{
paul050c0132005-02-14 23:47:47 +0000399 STREAM_VERIFY_SANE(s);
400
401 if (STREAM_WRITEABLE (s) < sizeof(u_char))
402 {
403 STREAM_BOUND_WARN (s, "put");
404 return 0;
405 }
406
407 s->data[s->endp++] = c;
408 return sizeof (u_char);
paul718e3742002-12-13 20:15:29 +0000409}
410
411/* Put word to the stream. */
412int
413stream_putw (struct stream *s, u_int16_t w)
414{
paul050c0132005-02-14 23:47:47 +0000415 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000416
paul050c0132005-02-14 23:47:47 +0000417 if (STREAM_WRITEABLE (s) < sizeof (u_int16_t))
418 {
419 STREAM_BOUND_WARN (s, "put");
420 return 0;
421 }
422
paul9985f832005-02-09 15:51:56 +0000423 s->data[s->endp++] = (u_char)(w >> 8);
424 s->data[s->endp++] = (u_char) w;
paul718e3742002-12-13 20:15:29 +0000425
paul718e3742002-12-13 20:15:29 +0000426 return 2;
427}
428
429/* Put long word to the stream. */
430int
431stream_putl (struct stream *s, u_int32_t l)
432{
paul050c0132005-02-14 23:47:47 +0000433 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000434
paul050c0132005-02-14 23:47:47 +0000435 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
436 {
437 STREAM_BOUND_WARN (s, "put");
438 return 0;
439 }
440
paul9985f832005-02-09 15:51:56 +0000441 s->data[s->endp++] = (u_char)(l >> 24);
442 s->data[s->endp++] = (u_char)(l >> 16);
443 s->data[s->endp++] = (u_char)(l >> 8);
444 s->data[s->endp++] = (u_char)l;
paul718e3742002-12-13 20:15:29 +0000445
paul718e3742002-12-13 20:15:29 +0000446 return 4;
447}
448
449int
paulf2e6c422005-02-12 14:35:49 +0000450stream_putc_at (struct stream *s, size_t putp, u_char c)
paul718e3742002-12-13 20:15:29 +0000451{
paul050c0132005-02-14 23:47:47 +0000452 STREAM_VERIFY_SANE(s);
453
454 if (!PUT_AT_VALID (s, putp + sizeof (u_char)))
455 {
456 STREAM_BOUND_WARN (s, "put");
457 return 0;
458 }
459
paul718e3742002-12-13 20:15:29 +0000460 s->data[putp] = c;
paul050c0132005-02-14 23:47:47 +0000461
paul718e3742002-12-13 20:15:29 +0000462 return 1;
463}
464
465int
paulf2e6c422005-02-12 14:35:49 +0000466stream_putw_at (struct stream *s, size_t putp, u_int16_t w)
paul718e3742002-12-13 20:15:29 +0000467{
paul050c0132005-02-14 23:47:47 +0000468 STREAM_VERIFY_SANE(s);
469
470 if (!PUT_AT_VALID (s, putp + sizeof (u_int16_t)))
471 {
472 STREAM_BOUND_WARN (s, "put");
473 return 0;
474 }
475
paul718e3742002-12-13 20:15:29 +0000476 s->data[putp] = (u_char)(w >> 8);
477 s->data[putp + 1] = (u_char) w;
paul050c0132005-02-14 23:47:47 +0000478
paul718e3742002-12-13 20:15:29 +0000479 return 2;
480}
481
482int
paulf2e6c422005-02-12 14:35:49 +0000483stream_putl_at (struct stream *s, size_t putp, u_int32_t l)
paul718e3742002-12-13 20:15:29 +0000484{
paul050c0132005-02-14 23:47:47 +0000485 STREAM_VERIFY_SANE(s);
486
487 if (!PUT_AT_VALID (s, putp + sizeof (u_int32_t)))
488 {
489 STREAM_BOUND_WARN (s, "put");
490 return 0;
491 }
paul718e3742002-12-13 20:15:29 +0000492 s->data[putp] = (u_char)(l >> 24);
493 s->data[putp + 1] = (u_char)(l >> 16);
494 s->data[putp + 2] = (u_char)(l >> 8);
495 s->data[putp + 3] = (u_char)l;
paul050c0132005-02-14 23:47:47 +0000496
paul718e3742002-12-13 20:15:29 +0000497 return 4;
498}
499
500/* Put long word to the stream. */
501int
502stream_put_ipv4 (struct stream *s, u_int32_t l)
503{
paul050c0132005-02-14 23:47:47 +0000504 STREAM_VERIFY_SANE(s);
505
506 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
507 {
508 STREAM_BOUND_WARN (s, "put");
509 return 0;
510 }
511 memcpy (s->data + s->endp, &l, sizeof (u_int32_t));
512 s->endp += sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000513
paul050c0132005-02-14 23:47:47 +0000514 return sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000515}
516
517/* Put long word to the stream. */
518int
519stream_put_in_addr (struct stream *s, struct in_addr *addr)
520{
paul050c0132005-02-14 23:47:47 +0000521 STREAM_VERIFY_SANE(s);
522
523 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
524 {
525 STREAM_BOUND_WARN (s, "put");
526 return 0;
527 }
paul718e3742002-12-13 20:15:29 +0000528
paul050c0132005-02-14 23:47:47 +0000529 memcpy (s->data + s->endp, addr, sizeof (u_int32_t));
530 s->endp += sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000531
paul050c0132005-02-14 23:47:47 +0000532 return sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000533}
534
535/* Put prefix by nlri type format. */
536int
537stream_put_prefix (struct stream *s, struct prefix *p)
538{
paul050c0132005-02-14 23:47:47 +0000539 size_t psize;
540
541 STREAM_VERIFY_SANE(s);
542
paul718e3742002-12-13 20:15:29 +0000543 psize = PSIZE (p->prefixlen);
paul050c0132005-02-14 23:47:47 +0000544
545 if (STREAM_WRITEABLE (s) < psize)
546 {
547 STREAM_BOUND_WARN (s, "put");
548 return 0;
549 }
550
paul718e3742002-12-13 20:15:29 +0000551 stream_putc (s, p->prefixlen);
paul9985f832005-02-09 15:51:56 +0000552 memcpy (s->data + s->endp, &p->u.prefix, psize);
553 s->endp += psize;
paul718e3742002-12-13 20:15:29 +0000554
paul718e3742002-12-13 20:15:29 +0000555 return psize;
556}
557
558/* Read size from fd. */
559int
560stream_read (struct stream *s, int fd, size_t size)
561{
562 int nbytes;
563
paul050c0132005-02-14 23:47:47 +0000564 STREAM_VERIFY_SANE(s);
565
566 if (STREAM_WRITEABLE (s) < size)
567 {
568 STREAM_BOUND_WARN (s, "put");
569 return 0;
570 }
571
paul9985f832005-02-09 15:51:56 +0000572 nbytes = readn (fd, s->data + s->endp, size);
paul718e3742002-12-13 20:15:29 +0000573
574 if (nbytes > 0)
paul9985f832005-02-09 15:51:56 +0000575 s->endp += nbytes;
576
paul718e3742002-12-13 20:15:29 +0000577 return nbytes;
578}
579
580/* Read size from fd. */
581int
582stream_read_unblock (struct stream *s, int fd, size_t size)
583{
584 int nbytes;
585 int val;
paul050c0132005-02-14 23:47:47 +0000586
587 STREAM_VERIFY_SANE(s);
588
589 if (STREAM_WRITEABLE (s) < size)
590 {
591 STREAM_BOUND_WARN (s, "put");
592 return 0;
593 }
594
paul718e3742002-12-13 20:15:29 +0000595 val = fcntl (fd, F_GETFL, 0);
596 fcntl (fd, F_SETFL, val|O_NONBLOCK);
paul9985f832005-02-09 15:51:56 +0000597 nbytes = read (fd, s->data + s->endp, size);
paul718e3742002-12-13 20:15:29 +0000598 fcntl (fd, F_SETFL, val);
599
600 if (nbytes > 0)
paul9985f832005-02-09 15:51:56 +0000601 s->endp += nbytes;
602
paul718e3742002-12-13 20:15:29 +0000603 return nbytes;
604}
605
ajs262feb12005-02-16 20:35:47 +0000606ssize_t
607stream_read_try(struct stream *s, int fd, size_t size)
608{
609 ssize_t nbytes;
610
611 STREAM_VERIFY_SANE(s);
612
613 if (STREAM_WRITEABLE(s) < size)
614 {
615 STREAM_BOUND_WARN (s, "put");
616 /* Fatal (not transient) error, since retrying will not help
617 (stream is too small to contain the desired data). */
618 return -1;
619 }
620
621 if ((nbytes = read(fd, s->data + s->endp, size)) >= 0)
622 {
623 s->endp += nbytes;
624 return nbytes;
625 }
626 /* Error: was it transient (return -2) or fatal (return -1)? */
ajs53270112005-02-17 20:07:22 +0000627 return ERRNO_IO_RETRY(errno) ? -2 : -1;
ajs262feb12005-02-16 20:35:47 +0000628}
629
paul050c0132005-02-14 23:47:47 +0000630/* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting
631 * from endp.
632 * First iovec will be used to receive the data.
633 * Stream need not be empty.
634 */
635int
636stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags,
637 size_t size)
638{
639 int nbytes;
640 struct iovec *iov;
641
642 STREAM_VERIFY_SANE(s);
643 assert (msgh->msg_iovlen > 0);
644
645 if (STREAM_WRITEABLE (s) < size)
646 {
647 STREAM_BOUND_WARN (s, "put");
ajs262feb12005-02-16 20:35:47 +0000648 /* This is a logic error in the calling code: the stream is too small
649 to hold the desired data! */
650 return -1;
paul050c0132005-02-14 23:47:47 +0000651 }
652
653 iov = &(msgh->msg_iov[0]);
654 iov->iov_base = (s->data + s->endp);
655 iov->iov_len = size;
656
657 nbytes = recvmsg (fd, msgh, flags);
658
659 if (nbytes > 0)
660 s->endp += nbytes;
661
662 return nbytes;
663}
664
paul718e3742002-12-13 20:15:29 +0000665/* Write data to buffer. */
666int
667stream_write (struct stream *s, u_char *ptr, size_t size)
668{
669
670 CHECK_SIZE(s, size);
671
paul050c0132005-02-14 23:47:47 +0000672 STREAM_VERIFY_SANE(s);
673
674 if (STREAM_WRITEABLE (s) < size)
675 {
676 STREAM_BOUND_WARN (s, "put");
677 return 0;
678 }
679
paul9985f832005-02-09 15:51:56 +0000680 memcpy (s->data + s->endp, ptr, size);
681 s->endp += size;
682
paul718e3742002-12-13 20:15:29 +0000683 return size;
684}
685
paul050c0132005-02-14 23:47:47 +0000686/* Return current read pointer.
687 * DEPRECATED!
688 * Use stream_get_pnt_to if you must, but decoding streams properly
689 * is preferred
690 */
paul718e3742002-12-13 20:15:29 +0000691u_char *
692stream_pnt (struct stream *s)
693{
paul050c0132005-02-14 23:47:47 +0000694 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000695 return s->data + s->getp;
696}
697
698/* Check does this stream empty? */
699int
700stream_empty (struct stream *s)
701{
paul050c0132005-02-14 23:47:47 +0000702 STREAM_VERIFY_SANE(s);
703
704 return (s->endp == 0);
paul718e3742002-12-13 20:15:29 +0000705}
706
707/* Reset stream. */
708void
709stream_reset (struct stream *s)
710{
paul050c0132005-02-14 23:47:47 +0000711 STREAM_VERIFY_SANE (s);
712
713 s->getp = s->endp = 0;
paul718e3742002-12-13 20:15:29 +0000714}
715
716/* Write stream contens to the file discriptor. */
717int
718stream_flush (struct stream *s, int fd)
719{
720 int nbytes;
paul050c0132005-02-14 23:47:47 +0000721
722 STREAM_VERIFY_SANE(s);
723
paul718e3742002-12-13 20:15:29 +0000724 nbytes = write (fd, s->data + s->getp, s->endp - s->getp);
paul050c0132005-02-14 23:47:47 +0000725
paul718e3742002-12-13 20:15:29 +0000726 return nbytes;
727}
728
729/* Stream first in first out queue. */
730
731struct stream_fifo *
732stream_fifo_new ()
733{
734 struct stream_fifo *new;
735
736 new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo));
737 return new;
738}
739
740/* Add new stream to fifo. */
741void
742stream_fifo_push (struct stream_fifo *fifo, struct stream *s)
743{
744 if (fifo->tail)
745 fifo->tail->next = s;
746 else
747 fifo->head = s;
748
749 fifo->tail = s;
750
751 fifo->count++;
752}
753
754/* Delete first stream from fifo. */
755struct stream *
756stream_fifo_pop (struct stream_fifo *fifo)
757{
758 struct stream *s;
759
760 s = fifo->head;
761
762 if (s)
763 {
764 fifo->head = s->next;
765
766 if (fifo->head == NULL)
767 fifo->tail = NULL;
768 }
769
770 fifo->count--;
771
772 return s;
773}
774
775/* Return first fifo entry. */
776struct stream *
777stream_fifo_head (struct stream_fifo *fifo)
778{
779 return fifo->head;
780}
781
782void
783stream_fifo_clean (struct stream_fifo *fifo)
784{
785 struct stream *s;
786 struct stream *next;
787
788 for (s = fifo->head; s; s = next)
789 {
790 next = s->next;
791 stream_free (s);
792 }
793 fifo->head = fifo->tail = NULL;
794 fifo->count = 0;
795}
796
797void
798stream_fifo_free (struct stream_fifo *fifo)
799{
800 stream_fifo_clean (fifo);
801 XFREE (MTYPE_STREAM_FIFO, fifo);
802}