]> git.proxmox.com Git - mirror_frr.git/blob - lib/stream.c
2004-07-23 Paul Jakma <paul@dishone.st>
[mirror_frr.git] / lib / stream.c
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 <zebra.h>
24
25 #include "stream.h"
26 #include "memory.h"
27 #include "network.h"
28 #include "prefix.h"
29
30
31 /*A macro to check pointers in order to not
32 go behind the allocated mem block
33 S -- stream reference
34 Z -- size of data to be written
35 */
36
37 #define CHECK_SIZE(S, Z) \
38 if (((S)->putp + (Z)) > (S)->size) \
39 (Z) = (S)->size - (S)->putp;
40
41 /* Stream is fixed length buffer for network output/input. */
42
43 /* Make stream buffer. */
44 struct stream *
45 stream_new (size_t size)
46 {
47 struct stream *s;
48
49 s = XCALLOC (MTYPE_STREAM, sizeof (struct stream));
50
51 s->data = XCALLOC (MTYPE_STREAM_DATA, size);
52 s->size = size;
53 return s;
54 }
55
56 /* Free it now. */
57 void
58 stream_free (struct stream *s)
59 {
60 XFREE (MTYPE_STREAM_DATA, s->data);
61 XFREE (MTYPE_STREAM, s);
62 }
63 \f
64 unsigned long
65 stream_get_getp (struct stream *s)
66 {
67 return s->getp;
68 }
69
70 unsigned long
71 stream_get_putp (struct stream *s)
72 {
73 return s->putp;
74 }
75
76 unsigned long
77 stream_get_endp (struct stream *s)
78 {
79 return s->endp;
80 }
81
82 unsigned long
83 stream_get_size (struct stream *s)
84 {
85 return s->size;
86 }
87
88 /* Stream structre' stream pointer related functions. */
89 void
90 stream_set_getp (struct stream *s, unsigned long pos)
91 {
92 s->getp = pos;
93 }
94
95 void
96 stream_set_putp (struct stream *s, unsigned long pos)
97 {
98 s->putp = pos;
99 }
100
101 /* Forward pointer. */
102 void
103 stream_forward (struct stream *s, int size)
104 {
105 s->getp += size;
106 }
107 \f
108 /* Copy from stream to destination. */
109 void
110 stream_get (void *dst, struct stream *s, size_t size)
111 {
112 memcpy (dst, s->data + s->getp, size);
113 s->getp += size;
114 }
115
116 /* Get next character from the stream. */
117 u_char
118 stream_getc (struct stream *s)
119 {
120 u_char c;
121
122 c = s->data[s->getp];
123 s->getp++;
124 return c;
125 }
126
127 /* Get next character from the stream. */
128 u_char
129 stream_getc_from (struct stream *s, unsigned long from)
130 {
131 u_char c;
132
133 c = s->data[from];
134 return c;
135 }
136
137 /* Get next word from the stream. */
138 u_int16_t
139 stream_getw (struct stream *s)
140 {
141 u_int16_t w;
142
143 w = s->data[s->getp++] << 8;
144 w |= s->data[s->getp++];
145 return w;
146 }
147
148 /* Get next word from the stream. */
149 u_int16_t
150 stream_getw_from (struct stream *s, unsigned long from)
151 {
152 u_int16_t w;
153
154 w = s->data[from++] << 8;
155 w |= s->data[from];
156 return w;
157 }
158
159 /* Get next long word from the stream. */
160 u_int32_t
161 stream_getl (struct stream *s)
162 {
163 u_int32_t l;
164
165 l = s->data[s->getp++] << 24;
166 l |= s->data[s->getp++] << 16;
167 l |= s->data[s->getp++] << 8;
168 l |= s->data[s->getp++];
169 return l;
170 }
171
172 /* Get next long word from the stream. */
173 u_int32_t
174 stream_get_ipv4 (struct stream *s)
175 {
176 u_int32_t l;
177
178 memcpy (&l, s->data + s->getp, 4);
179 s->getp += 4;
180
181 return l;
182 }
183 \f
184 /* Copy to source to stream. */
185 void
186 stream_put (struct stream *s, void *src, size_t size)
187 {
188
189 CHECK_SIZE(s, size);
190
191 if (src)
192 memcpy (s->data + s->putp, src, size);
193 else
194 memset (s->data + s->putp, 0, size);
195
196 s->putp += size;
197 if (s->putp > s->endp)
198 s->endp = s->putp;
199 }
200
201 /* Put character to the stream. */
202 int
203 stream_putc (struct stream *s, u_char c)
204 {
205 if (s->putp >= s->size) return 0;
206
207 s->data[s->putp] = c;
208 s->putp++;
209 if (s->putp > s->endp)
210 s->endp = s->putp;
211 return 1;
212 }
213
214 /* Put word to the stream. */
215 int
216 stream_putw (struct stream *s, u_int16_t w)
217 {
218 if ((s->size - s->putp) < 2) return 0;
219
220 s->data[s->putp++] = (u_char)(w >> 8);
221 s->data[s->putp++] = (u_char) w;
222
223 if (s->putp > s->endp)
224 s->endp = s->putp;
225 return 2;
226 }
227
228 /* Put long word to the stream. */
229 int
230 stream_putl (struct stream *s, u_int32_t l)
231 {
232 if ((s->size - s->putp) < 4) return 0;
233
234 s->data[s->putp++] = (u_char)(l >> 24);
235 s->data[s->putp++] = (u_char)(l >> 16);
236 s->data[s->putp++] = (u_char)(l >> 8);
237 s->data[s->putp++] = (u_char)l;
238
239 if (s->putp > s->endp)
240 s->endp = s->putp;
241 return 4;
242 }
243
244 int
245 stream_putc_at (struct stream *s, unsigned long putp, u_char c)
246 {
247 s->data[putp] = c;
248 return 1;
249 }
250
251 int
252 stream_putw_at (struct stream *s, unsigned long putp, u_int16_t w)
253 {
254 s->data[putp] = (u_char)(w >> 8);
255 s->data[putp + 1] = (u_char) w;
256 return 2;
257 }
258
259 int
260 stream_putl_at (struct stream *s, unsigned long putp, u_int32_t l)
261 {
262 s->data[putp] = (u_char)(l >> 24);
263 s->data[putp + 1] = (u_char)(l >> 16);
264 s->data[putp + 2] = (u_char)(l >> 8);
265 s->data[putp + 3] = (u_char)l;
266 return 4;
267 }
268
269 /* Put long word to the stream. */
270 int
271 stream_put_ipv4 (struct stream *s, u_int32_t l)
272 {
273 if ((s->size - s->putp) < 4)
274 return 0;
275
276 memcpy (s->data + s->putp, &l, 4);
277 s->putp += 4;
278
279 if (s->putp > s->endp)
280 s->endp = s->putp;
281 return 4;
282 }
283
284 /* Put long word to the stream. */
285 int
286 stream_put_in_addr (struct stream *s, struct in_addr *addr)
287 {
288 if ((s->size - s->putp) < 4)
289 return 0;
290
291 memcpy (s->data + s->putp, addr, 4);
292 s->putp += 4;
293
294 if (s->putp > s->endp)
295 s->endp = s->putp;
296 return 4;
297 }
298
299 /* Put prefix by nlri type format. */
300 int
301 stream_put_prefix (struct stream *s, struct prefix *p)
302 {
303 u_char psize;
304
305 psize = PSIZE (p->prefixlen);
306
307 if ((s->size - s->putp) < psize) return 0;
308
309 stream_putc (s, p->prefixlen);
310 memcpy (s->data + s->putp, &p->u.prefix, psize);
311 s->putp += psize;
312
313 if (s->putp > s->endp)
314 s->endp = s->putp;
315
316 return psize;
317 }
318 \f
319 /* Read size from fd. */
320 int
321 stream_read (struct stream *s, int fd, size_t size)
322 {
323 int nbytes;
324
325 nbytes = readn (fd, s->data + s->putp, size);
326
327 if (nbytes > 0)
328 {
329 s->putp += nbytes;
330 s->endp += nbytes;
331 }
332 return nbytes;
333 }
334
335 /* Read size from fd. */
336 int
337 stream_read_unblock (struct stream *s, int fd, size_t size)
338 {
339 int nbytes;
340 int val;
341
342 val = fcntl (fd, F_GETFL, 0);
343 fcntl (fd, F_SETFL, val|O_NONBLOCK);
344 nbytes = read (fd, s->data + s->putp, size);
345 fcntl (fd, F_SETFL, val);
346
347 if (nbytes > 0)
348 {
349 s->putp += nbytes;
350 s->endp += nbytes;
351 }
352 return nbytes;
353 }
354
355 /* Write data to buffer. */
356 int
357 stream_write (struct stream *s, u_char *ptr, size_t size)
358 {
359
360 CHECK_SIZE(s, size);
361
362 memcpy (s->data + s->putp, ptr, size);
363 s->putp += size;
364 if (s->putp > s->endp)
365 s->endp = s->putp;
366 return size;
367 }
368
369 /* Return current read pointer. */
370 u_char *
371 stream_pnt (struct stream *s)
372 {
373 return s->data + s->getp;
374 }
375
376 /* Check does this stream empty? */
377 int
378 stream_empty (struct stream *s)
379 {
380 if (s->putp == 0 && s->endp == 0 && s->getp == 0)
381 return 1;
382 else
383 return 0;
384 }
385
386 /* Reset stream. */
387 void
388 stream_reset (struct stream *s)
389 {
390 s->putp = 0;
391 s->endp = 0;
392 s->getp = 0;
393 }
394
395 /* Write stream contens to the file discriptor. */
396 int
397 stream_flush (struct stream *s, int fd)
398 {
399 int nbytes;
400
401 nbytes = write (fd, s->data + s->getp, s->endp - s->getp);
402
403 return nbytes;
404 }
405 \f
406 /* Stream first in first out queue. */
407
408 struct stream_fifo *
409 stream_fifo_new ()
410 {
411 struct stream_fifo *new;
412
413 new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo));
414 return new;
415 }
416
417 /* Add new stream to fifo. */
418 void
419 stream_fifo_push (struct stream_fifo *fifo, struct stream *s)
420 {
421 if (fifo->tail)
422 fifo->tail->next = s;
423 else
424 fifo->head = s;
425
426 fifo->tail = s;
427
428 fifo->count++;
429 }
430
431 /* Delete first stream from fifo. */
432 struct stream *
433 stream_fifo_pop (struct stream_fifo *fifo)
434 {
435 struct stream *s;
436
437 s = fifo->head;
438
439 if (s)
440 {
441 fifo->head = s->next;
442
443 if (fifo->head == NULL)
444 fifo->tail = NULL;
445 }
446
447 fifo->count--;
448
449 return s;
450 }
451
452 /* Return first fifo entry. */
453 struct stream *
454 stream_fifo_head (struct stream_fifo *fifo)
455 {
456 return fifo->head;
457 }
458
459 void
460 stream_fifo_clean (struct stream_fifo *fifo)
461 {
462 struct stream *s;
463 struct stream *next;
464
465 for (s = fifo->head; s; s = next)
466 {
467 next = s->next;
468 stream_free (s);
469 }
470 fifo->head = fifo->tail = NULL;
471 fifo->count = 0;
472 }
473
474 void
475 stream_fifo_free (struct stream_fifo *fifo)
476 {
477 stream_fifo_clean (fifo);
478 XFREE (MTYPE_STREAM_FIFO, fifo);
479 }