Annotation of embedaddon/quagga/lib/stream.c, revision 1.1.1.2
1.1 misho 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) \
1.1.1.2 ! misho 55: zlog_warn ("&(struct stream): %p, size: %lu, getp: %lu, endp: %lu\n", \
1.1 misho 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. */
89: struct stream *
90: stream_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. */
118: void
119: stream_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:
128: struct stream *
129: stream_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:
144: struct stream *
145: stream_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:
157: size_t
158: stream_resize (struct stream *s, size_t newsize)
159: {
160: u_char *newdata;
161: STREAM_VERIFY_SANE (s);
162:
163: newdata = XREALLOC (MTYPE_STREAM_DATA, s->data, newsize);
164:
165: if (newdata == NULL)
166: return s->size;
167:
168: s->data = newdata;
169: s->size = newsize;
170:
171: if (s->endp > s->size)
172: s->endp = s->size;
173: if (s->getp > s->endp)
174: s->getp = s->endp;
175:
176: STREAM_VERIFY_SANE (s);
177:
178: return s->size;
179: }
180:
181: size_t
182: stream_get_getp (struct stream *s)
183: {
184: STREAM_VERIFY_SANE(s);
185: return s->getp;
186: }
187:
188: size_t
189: stream_get_endp (struct stream *s)
190: {
191: STREAM_VERIFY_SANE(s);
192: return s->endp;
193: }
194:
195: size_t
196: stream_get_size (struct stream *s)
197: {
198: STREAM_VERIFY_SANE(s);
199: return s->size;
200: }
201:
202: /* Stream structre' stream pointer related functions. */
203: void
204: stream_set_getp (struct stream *s, size_t pos)
205: {
206: STREAM_VERIFY_SANE(s);
207:
208: if (!GETP_VALID (s, pos))
209: {
210: STREAM_BOUND_WARN (s, "set getp");
211: pos = s->endp;
212: }
213:
214: s->getp = pos;
215: }
216:
1.1.1.2 ! misho 217: void
! 218: stream_set_endp (struct stream *s, size_t pos)
! 219: {
! 220: STREAM_VERIFY_SANE(s);
! 221:
! 222: if (!GETP_VALID (s, pos))
! 223: {
! 224: STREAM_BOUND_WARN (s, "set endp");
! 225: pos = s->endp;
! 226: }
! 227:
! 228: s->endp = pos;
! 229: }
! 230:
1.1 misho 231: /* Forward pointer. */
232: void
233: stream_forward_getp (struct stream *s, size_t size)
234: {
235: STREAM_VERIFY_SANE(s);
236:
237: if (!GETP_VALID (s, s->getp + size))
238: {
239: STREAM_BOUND_WARN (s, "seek getp");
240: return;
241: }
242:
243: s->getp += size;
244: }
245:
246: void
247: stream_forward_endp (struct stream *s, size_t size)
248: {
249: STREAM_VERIFY_SANE(s);
250:
251: if (!ENDP_VALID (s, s->endp + size))
252: {
253: STREAM_BOUND_WARN (s, "seek endp");
254: return;
255: }
256:
257: s->endp += size;
258: }
259:
260: /* Copy from stream to destination. */
261: void
262: stream_get (void *dst, struct stream *s, size_t size)
263: {
264: STREAM_VERIFY_SANE(s);
265:
266: if (STREAM_READABLE(s) < size)
267: {
268: STREAM_BOUND_WARN (s, "get");
269: return;
270: }
271:
272: memcpy (dst, s->data + s->getp, size);
273: s->getp += size;
274: }
275:
276: /* Get next character from the stream. */
277: u_char
278: stream_getc (struct stream *s)
279: {
280: u_char c;
281:
282: STREAM_VERIFY_SANE (s);
283:
284: if (STREAM_READABLE(s) < sizeof (u_char))
285: {
286: STREAM_BOUND_WARN (s, "get char");
287: return 0;
288: }
289: c = s->data[s->getp++];
290:
291: return c;
292: }
293:
294: /* Get next character from the stream. */
295: u_char
296: stream_getc_from (struct stream *s, size_t from)
297: {
298: u_char c;
299:
300: STREAM_VERIFY_SANE(s);
301:
302: if (!GETP_VALID (s, from + sizeof (u_char)))
303: {
304: STREAM_BOUND_WARN (s, "get char");
305: return 0;
306: }
307:
308: c = s->data[from];
309:
310: return c;
311: }
312:
313: /* Get next word from the stream. */
314: u_int16_t
315: stream_getw (struct stream *s)
316: {
317: u_int16_t w;
318:
319: STREAM_VERIFY_SANE (s);
320:
321: if (STREAM_READABLE (s) < sizeof (u_int16_t))
322: {
323: STREAM_BOUND_WARN (s, "get ");
324: return 0;
325: }
326:
327: w = s->data[s->getp++] << 8;
328: w |= s->data[s->getp++];
329:
330: return w;
331: }
332:
333: /* Get next word from the stream. */
334: u_int16_t
335: stream_getw_from (struct stream *s, size_t from)
336: {
337: u_int16_t w;
338:
339: STREAM_VERIFY_SANE(s);
340:
341: if (!GETP_VALID (s, from + sizeof (u_int16_t)))
342: {
343: STREAM_BOUND_WARN (s, "get ");
344: return 0;
345: }
346:
347: w = s->data[from++] << 8;
348: w |= s->data[from];
349:
350: return w;
351: }
352:
353: /* Get next long word from the stream. */
354: u_int32_t
355: stream_getl_from (struct stream *s, size_t from)
356: {
357: u_int32_t l;
358:
359: STREAM_VERIFY_SANE(s);
360:
361: if (!GETP_VALID (s, from + sizeof (u_int32_t)))
362: {
363: STREAM_BOUND_WARN (s, "get long");
364: return 0;
365: }
366:
367: l = s->data[from++] << 24;
368: l |= s->data[from++] << 16;
369: l |= s->data[from++] << 8;
370: l |= s->data[from];
371:
372: return l;
373: }
374:
375: u_int32_t
376: stream_getl (struct stream *s)
377: {
378: u_int32_t l;
379:
380: STREAM_VERIFY_SANE(s);
381:
382: if (STREAM_READABLE (s) < sizeof (u_int32_t))
383: {
384: STREAM_BOUND_WARN (s, "get long");
385: return 0;
386: }
387:
388: l = s->data[s->getp++] << 24;
389: l |= s->data[s->getp++] << 16;
390: l |= s->data[s->getp++] << 8;
391: l |= s->data[s->getp++];
392:
393: return l;
394: }
395:
396: /* Get next quad word from the stream. */
397: uint64_t
398: stream_getq_from (struct stream *s, size_t from)
399: {
400: uint64_t q;
401:
402: STREAM_VERIFY_SANE(s);
403:
404: if (!GETP_VALID (s, from + sizeof (uint64_t)))
405: {
406: STREAM_BOUND_WARN (s, "get quad");
407: return 0;
408: }
409:
410: q = ((uint64_t) s->data[from++]) << 56;
411: q |= ((uint64_t) s->data[from++]) << 48;
412: q |= ((uint64_t) s->data[from++]) << 40;
413: q |= ((uint64_t) s->data[from++]) << 32;
414: q |= ((uint64_t) s->data[from++]) << 24;
415: q |= ((uint64_t) s->data[from++]) << 16;
416: q |= ((uint64_t) s->data[from++]) << 8;
417: q |= ((uint64_t) s->data[from++]);
418:
419: return q;
420: }
421:
422: uint64_t
423: stream_getq (struct stream *s)
424: {
425: uint64_t q;
426:
427: STREAM_VERIFY_SANE(s);
428:
429: if (STREAM_READABLE (s) < sizeof (uint64_t))
430: {
431: STREAM_BOUND_WARN (s, "get quad");
432: return 0;
433: }
434:
435: q = ((uint64_t) s->data[s->getp++]) << 56;
436: q |= ((uint64_t) s->data[s->getp++]) << 48;
437: q |= ((uint64_t) s->data[s->getp++]) << 40;
438: q |= ((uint64_t) s->data[s->getp++]) << 32;
439: q |= ((uint64_t) s->data[s->getp++]) << 24;
440: q |= ((uint64_t) s->data[s->getp++]) << 16;
441: q |= ((uint64_t) s->data[s->getp++]) << 8;
442: q |= ((uint64_t) s->data[s->getp++]);
443:
444: return q;
445: }
446:
447: /* Get next long word from the stream. */
448: u_int32_t
449: stream_get_ipv4 (struct stream *s)
450: {
451: u_int32_t l;
452:
453: STREAM_VERIFY_SANE(s);
454:
455: if (STREAM_READABLE (s) < sizeof(u_int32_t))
456: {
457: STREAM_BOUND_WARN (s, "get ipv4");
458: return 0;
459: }
460:
461: memcpy (&l, s->data + s->getp, sizeof(u_int32_t));
462: s->getp += sizeof(u_int32_t);
463:
464: return l;
465: }
466:
467: /* Copy to source to stream.
468: *
469: * XXX: This uses CHECK_SIZE and hence has funny semantics -> Size will wrap
470: * around. This should be fixed once the stream updates are working.
471: *
472: * stream_write() is saner
473: */
474: void
475: stream_put (struct stream *s, const void *src, size_t size)
476: {
477:
478: /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */
479: CHECK_SIZE(s, size);
480:
481: STREAM_VERIFY_SANE(s);
482:
483: if (STREAM_WRITEABLE (s) < size)
484: {
485: STREAM_BOUND_WARN (s, "put");
486: return;
487: }
488:
489: if (src)
490: memcpy (s->data + s->endp, src, size);
491: else
492: memset (s->data + s->endp, 0, size);
493:
494: s->endp += size;
495: }
496:
497: /* Put character to the stream. */
498: int
499: stream_putc (struct stream *s, u_char c)
500: {
501: STREAM_VERIFY_SANE(s);
502:
503: if (STREAM_WRITEABLE (s) < sizeof(u_char))
504: {
505: STREAM_BOUND_WARN (s, "put");
506: return 0;
507: }
508:
509: s->data[s->endp++] = c;
510: return sizeof (u_char);
511: }
512:
513: /* Put word to the stream. */
514: int
515: stream_putw (struct stream *s, u_int16_t w)
516: {
517: STREAM_VERIFY_SANE (s);
518:
519: if (STREAM_WRITEABLE (s) < sizeof (u_int16_t))
520: {
521: STREAM_BOUND_WARN (s, "put");
522: return 0;
523: }
524:
525: s->data[s->endp++] = (u_char)(w >> 8);
526: s->data[s->endp++] = (u_char) w;
527:
528: return 2;
529: }
530:
531: /* Put long word to the stream. */
532: int
533: stream_putl (struct stream *s, u_int32_t l)
534: {
535: STREAM_VERIFY_SANE (s);
536:
537: if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
538: {
539: STREAM_BOUND_WARN (s, "put");
540: return 0;
541: }
542:
543: s->data[s->endp++] = (u_char)(l >> 24);
544: s->data[s->endp++] = (u_char)(l >> 16);
545: s->data[s->endp++] = (u_char)(l >> 8);
546: s->data[s->endp++] = (u_char)l;
547:
548: return 4;
549: }
550:
551: /* Put quad word to the stream. */
552: int
553: stream_putq (struct stream *s, uint64_t q)
554: {
555: STREAM_VERIFY_SANE (s);
556:
557: if (STREAM_WRITEABLE (s) < sizeof (uint64_t))
558: {
559: STREAM_BOUND_WARN (s, "put quad");
560: return 0;
561: }
562:
563: s->data[s->endp++] = (u_char)(q >> 56);
564: s->data[s->endp++] = (u_char)(q >> 48);
565: s->data[s->endp++] = (u_char)(q >> 40);
566: s->data[s->endp++] = (u_char)(q >> 32);
567: s->data[s->endp++] = (u_char)(q >> 24);
568: s->data[s->endp++] = (u_char)(q >> 16);
569: s->data[s->endp++] = (u_char)(q >> 8);
570: s->data[s->endp++] = (u_char)q;
571:
572: return 8;
573: }
574:
575: int
576: stream_putc_at (struct stream *s, size_t putp, u_char c)
577: {
578: STREAM_VERIFY_SANE(s);
579:
580: if (!PUT_AT_VALID (s, putp + sizeof (u_char)))
581: {
582: STREAM_BOUND_WARN (s, "put");
583: return 0;
584: }
585:
586: s->data[putp] = c;
587:
588: return 1;
589: }
590:
591: int
592: stream_putw_at (struct stream *s, size_t putp, u_int16_t w)
593: {
594: STREAM_VERIFY_SANE(s);
595:
596: if (!PUT_AT_VALID (s, putp + sizeof (u_int16_t)))
597: {
598: STREAM_BOUND_WARN (s, "put");
599: return 0;
600: }
601:
602: s->data[putp] = (u_char)(w >> 8);
603: s->data[putp + 1] = (u_char) w;
604:
605: return 2;
606: }
607:
608: int
609: stream_putl_at (struct stream *s, size_t putp, u_int32_t l)
610: {
611: STREAM_VERIFY_SANE(s);
612:
613: if (!PUT_AT_VALID (s, putp + sizeof (u_int32_t)))
614: {
615: STREAM_BOUND_WARN (s, "put");
616: return 0;
617: }
618: s->data[putp] = (u_char)(l >> 24);
619: s->data[putp + 1] = (u_char)(l >> 16);
620: s->data[putp + 2] = (u_char)(l >> 8);
621: s->data[putp + 3] = (u_char)l;
622:
623: return 4;
624: }
625:
626: int
627: stream_putq_at (struct stream *s, size_t putp, uint64_t q)
628: {
629: STREAM_VERIFY_SANE(s);
630:
631: if (!PUT_AT_VALID (s, putp + sizeof (uint64_t)))
632: {
633: STREAM_BOUND_WARN (s, "put");
634: return 0;
635: }
636: s->data[putp] = (u_char)(q >> 56);
637: s->data[putp + 1] = (u_char)(q >> 48);
638: s->data[putp + 2] = (u_char)(q >> 40);
639: s->data[putp + 3] = (u_char)(q >> 32);
640: s->data[putp + 4] = (u_char)(q >> 24);
641: s->data[putp + 5] = (u_char)(q >> 16);
642: s->data[putp + 6] = (u_char)(q >> 8);
643: s->data[putp + 7] = (u_char)q;
644:
645: return 8;
646: }
647:
648: /* Put long word to the stream. */
649: int
650: stream_put_ipv4 (struct stream *s, u_int32_t l)
651: {
652: STREAM_VERIFY_SANE(s);
653:
654: if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
655: {
656: STREAM_BOUND_WARN (s, "put");
657: return 0;
658: }
659: memcpy (s->data + s->endp, &l, sizeof (u_int32_t));
660: s->endp += sizeof (u_int32_t);
661:
662: return sizeof (u_int32_t);
663: }
664:
665: /* Put long word to the stream. */
666: int
667: stream_put_in_addr (struct stream *s, struct in_addr *addr)
668: {
669: STREAM_VERIFY_SANE(s);
670:
671: if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
672: {
673: STREAM_BOUND_WARN (s, "put");
674: return 0;
675: }
676:
677: memcpy (s->data + s->endp, addr, sizeof (u_int32_t));
678: s->endp += sizeof (u_int32_t);
679:
680: return sizeof (u_int32_t);
681: }
682:
683: /* Put prefix by nlri type format. */
684: int
685: stream_put_prefix (struct stream *s, struct prefix *p)
686: {
687: size_t psize;
688:
689: STREAM_VERIFY_SANE(s);
690:
691: psize = PSIZE (p->prefixlen);
692:
693: if (STREAM_WRITEABLE (s) < psize)
694: {
695: STREAM_BOUND_WARN (s, "put");
696: return 0;
697: }
698:
699: stream_putc (s, p->prefixlen);
700: memcpy (s->data + s->endp, &p->u.prefix, psize);
701: s->endp += psize;
702:
703: return psize;
704: }
705:
706: /* Read size from fd. */
707: int
708: stream_read (struct stream *s, int fd, size_t size)
709: {
710: int nbytes;
711:
712: STREAM_VERIFY_SANE(s);
713:
714: if (STREAM_WRITEABLE (s) < size)
715: {
716: STREAM_BOUND_WARN (s, "put");
717: return 0;
718: }
719:
720: nbytes = readn (fd, s->data + s->endp, size);
721:
722: if (nbytes > 0)
723: s->endp += nbytes;
724:
725: return nbytes;
726: }
727:
728: /* Read size from fd. */
729: int
730: stream_read_unblock (struct stream *s, int fd, size_t size)
731: {
732: int nbytes;
733: int val;
734:
735: STREAM_VERIFY_SANE(s);
736:
737: if (STREAM_WRITEABLE (s) < size)
738: {
739: STREAM_BOUND_WARN (s, "put");
740: return 0;
741: }
742:
743: val = fcntl (fd, F_GETFL, 0);
744: fcntl (fd, F_SETFL, val|O_NONBLOCK);
745: nbytes = read (fd, s->data + s->endp, size);
746: fcntl (fd, F_SETFL, val);
747:
748: if (nbytes > 0)
749: s->endp += nbytes;
750:
751: return nbytes;
752: }
753:
754: ssize_t
755: stream_read_try(struct stream *s, int fd, size_t size)
756: {
757: ssize_t nbytes;
758:
759: STREAM_VERIFY_SANE(s);
760:
761: if (STREAM_WRITEABLE(s) < size)
762: {
763: STREAM_BOUND_WARN (s, "put");
764: /* Fatal (not transient) error, since retrying will not help
765: (stream is too small to contain the desired data). */
766: return -1;
767: }
768:
769: if ((nbytes = read(fd, s->data + s->endp, size)) >= 0)
770: {
771: s->endp += nbytes;
772: return nbytes;
773: }
774: /* Error: was it transient (return -2) or fatal (return -1)? */
775: if (ERRNO_IO_RETRY(errno))
776: return -2;
777: zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
778: return -1;
779: }
780:
781: /* Read up to size bytes into the stream from the fd, using recvmsgfrom
782: * whose arguments match the remaining arguments to this function
783: */
784: ssize_t
785: stream_recvfrom (struct stream *s, int fd, size_t size, int flags,
786: struct sockaddr *from, socklen_t *fromlen)
787: {
788: ssize_t nbytes;
789:
790: STREAM_VERIFY_SANE(s);
791:
792: if (STREAM_WRITEABLE(s) < size)
793: {
794: STREAM_BOUND_WARN (s, "put");
795: /* Fatal (not transient) error, since retrying will not help
796: (stream is too small to contain the desired data). */
797: return -1;
798: }
799:
800: if ((nbytes = recvfrom (fd, s->data + s->endp, size,
801: flags, from, fromlen)) >= 0)
802: {
803: s->endp += nbytes;
804: return nbytes;
805: }
806: /* Error: was it transient (return -2) or fatal (return -1)? */
807: if (ERRNO_IO_RETRY(errno))
808: return -2;
809: zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
810: return -1;
811: }
812:
813: /* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting
814: * from endp.
815: * First iovec will be used to receive the data.
816: * Stream need not be empty.
817: */
818: ssize_t
819: stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags,
820: size_t size)
821: {
822: int nbytes;
823: struct iovec *iov;
824:
825: STREAM_VERIFY_SANE(s);
826: assert (msgh->msg_iovlen > 0);
827:
828: if (STREAM_WRITEABLE (s) < size)
829: {
830: STREAM_BOUND_WARN (s, "put");
831: /* This is a logic error in the calling code: the stream is too small
832: to hold the desired data! */
833: return -1;
834: }
835:
836: iov = &(msgh->msg_iov[0]);
837: iov->iov_base = (s->data + s->endp);
838: iov->iov_len = size;
839:
840: nbytes = recvmsg (fd, msgh, flags);
841:
842: if (nbytes > 0)
843: s->endp += nbytes;
844:
845: return nbytes;
846: }
847:
848: /* Write data to buffer. */
849: size_t
850: stream_write (struct stream *s, const void *ptr, size_t size)
851: {
852:
853: CHECK_SIZE(s, size);
854:
855: STREAM_VERIFY_SANE(s);
856:
857: if (STREAM_WRITEABLE (s) < size)
858: {
859: STREAM_BOUND_WARN (s, "put");
860: return 0;
861: }
862:
863: memcpy (s->data + s->endp, ptr, size);
864: s->endp += size;
865:
866: return size;
867: }
868:
869: /* Return current read pointer.
870: * DEPRECATED!
871: * Use stream_get_pnt_to if you must, but decoding streams properly
872: * is preferred
873: */
874: u_char *
875: stream_pnt (struct stream *s)
876: {
877: STREAM_VERIFY_SANE(s);
878: return s->data + s->getp;
879: }
880:
881: /* Check does this stream empty? */
882: int
883: stream_empty (struct stream *s)
884: {
885: STREAM_VERIFY_SANE(s);
886:
887: return (s->endp == 0);
888: }
889:
890: /* Reset stream. */
891: void
892: stream_reset (struct stream *s)
893: {
894: STREAM_VERIFY_SANE (s);
895:
896: s->getp = s->endp = 0;
897: }
898:
899: /* Write stream contens to the file discriptor. */
900: int
901: stream_flush (struct stream *s, int fd)
902: {
903: int nbytes;
904:
905: STREAM_VERIFY_SANE(s);
906:
907: nbytes = write (fd, s->data + s->getp, s->endp - s->getp);
908:
909: return nbytes;
910: }
911:
912: /* Stream first in first out queue. */
913:
914: struct stream_fifo *
915: stream_fifo_new (void)
916: {
917: struct stream_fifo *new;
918:
919: new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo));
920: return new;
921: }
922:
923: /* Add new stream to fifo. */
924: void
925: stream_fifo_push (struct stream_fifo *fifo, struct stream *s)
926: {
927: if (fifo->tail)
928: fifo->tail->next = s;
929: else
930: fifo->head = s;
931:
932: fifo->tail = s;
933:
934: fifo->count++;
935: }
936:
937: /* Delete first stream from fifo. */
938: struct stream *
939: stream_fifo_pop (struct stream_fifo *fifo)
940: {
941: struct stream *s;
942:
943: s = fifo->head;
944:
945: if (s)
946: {
947: fifo->head = s->next;
948:
949: if (fifo->head == NULL)
950: fifo->tail = NULL;
951:
1.1.1.2 ! misho 952: fifo->count--;
! 953: }
1.1 misho 954:
955: return s;
956: }
957:
958: /* Return first fifo entry. */
959: struct stream *
960: stream_fifo_head (struct stream_fifo *fifo)
961: {
962: return fifo->head;
963: }
964:
965: void
966: stream_fifo_clean (struct stream_fifo *fifo)
967: {
968: struct stream *s;
969: struct stream *next;
970:
971: for (s = fifo->head; s; s = next)
972: {
973: next = s->next;
974: stream_free (s);
975: }
976: fifo->head = fifo->tail = NULL;
977: fifo->count = 0;
978: }
979:
980: void
981: stream_fifo_free (struct stream_fifo *fifo)
982: {
983: stream_fifo_clean (fifo);
984: XFREE (MTYPE_STREAM_FIFO, fifo);
985: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>