]> git.proxmox.com Git - mirror_frr.git/blob - nhrpd/zbuf.h
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / nhrpd / zbuf.h
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Stream/packet buffer API
3 * Copyright (c) 2014-2015 Timo Teräs
4 */
5
6 #ifndef ZBUF_H
7 #define ZBUF_H
8
9 #include <stdint.h>
10 #include <string.h>
11 #include <endian.h>
12 #include <sys/types.h>
13
14 #include "typesafe.h"
15
16 PREDECL_DLIST(zbuf_queue);
17
18 struct zbuf {
19 struct zbuf_queue_item queue_entry;
20 unsigned allocated : 1;
21 unsigned error : 1;
22 uint8_t *buf, *end;
23 uint8_t *head, *tail;
24 };
25
26 DECLARE_DLIST(zbuf_queue, struct zbuf, queue_entry);
27
28 struct zbuf_queue {
29 struct zbuf_queue_head queue_head;
30 };
31
32 struct zbuf *zbuf_alloc(size_t size);
33 void zbuf_init(struct zbuf *zb, void *buf, size_t len, size_t datalen);
34 void zbuf_free(struct zbuf *zb);
35
36 static inline size_t zbuf_size(struct zbuf *zb)
37 {
38 return zb->end - zb->buf;
39 }
40
41 static inline size_t zbuf_used(struct zbuf *zb)
42 {
43 return zb->tail - zb->head;
44 }
45
46 static inline size_t zbuf_tailroom(struct zbuf *zb)
47 {
48 return zb->end - zb->tail;
49 }
50
51 static inline size_t zbuf_headroom(struct zbuf *zb)
52 {
53 return zb->head - zb->buf;
54 }
55
56 void zbuf_reset(struct zbuf *zb);
57 void zbuf_reset_head(struct zbuf *zb, void *ptr);
58 ssize_t zbuf_read(struct zbuf *zb, int fd, size_t maxlen);
59 ssize_t zbuf_write(struct zbuf *zb, int fd);
60 ssize_t zbuf_recv(struct zbuf *zb, int fd);
61 ssize_t zbuf_send(struct zbuf *zb, int fd);
62
63 static inline void zbuf_set_rerror(struct zbuf *zb)
64 {
65 zb->error = 1;
66 zb->head = zb->tail;
67 }
68
69 static inline void zbuf_set_werror(struct zbuf *zb)
70 {
71 zb->error = 1;
72 zb->tail = zb->end;
73 }
74
75 static inline void *__zbuf_pull(struct zbuf *zb, size_t size, int error)
76 {
77 void *head = zb->head;
78 if (size > zbuf_used(zb)) {
79 if (error)
80 zbuf_set_rerror(zb);
81 return NULL;
82 }
83 zb->head += size;
84 return head;
85 }
86
87 #define zbuf_pull(zb, type) ((type *)__zbuf_pull(zb, sizeof(type), 1))
88 #define zbuf_pulln(zb, sz) (__zbuf_pull(zb, sz, 1))
89 #define zbuf_may_pull(zb, type) ((type *)__zbuf_pull(zb, sizeof(type), 0))
90 #define zbuf_may_pulln(zb, sz) (__zbuf_pull(zb, sz, 0))
91
92 void *zbuf_may_pull_until(struct zbuf *zb, const char *sep, struct zbuf *msg);
93
94 static inline void zbuf_get(struct zbuf *zb, void *dst, size_t len)
95 {
96 void *src = zbuf_pulln(zb, len);
97 if (src)
98 memcpy(dst, src, len);
99 }
100
101 static inline uint8_t zbuf_get8(struct zbuf *zb)
102 {
103 uint8_t *src = zbuf_pull(zb, uint8_t);
104 if (src)
105 return *src;
106 return 0;
107 }
108
109 static inline uint32_t zbuf_get32(struct zbuf *zb)
110 {
111 struct unaligned32 {
112 uint32_t value;
113 } __attribute__((packed));
114
115 struct unaligned32 *v = zbuf_pull(zb, struct unaligned32);
116 if (v)
117 return v->value;
118 return 0;
119 }
120
121 static inline uint16_t zbuf_get_be16(struct zbuf *zb)
122 {
123 struct unaligned16 {
124 uint16_t value;
125 } __attribute__((packed));
126
127 struct unaligned16 *v = zbuf_pull(zb, struct unaligned16);
128 if (v)
129 return be16toh(v->value);
130 return 0;
131 }
132
133 static inline uint32_t zbuf_get_be32(struct zbuf *zb)
134 {
135 return be32toh(zbuf_get32(zb));
136 }
137
138 static inline void *__zbuf_push(struct zbuf *zb, size_t size, int error)
139 {
140 void *tail = zb->tail;
141 if (size > zbuf_tailroom(zb)) {
142 if (error)
143 zbuf_set_werror(zb);
144 return NULL;
145 }
146 zb->tail += size;
147 return tail;
148 }
149
150 #define zbuf_push(zb, type) ((type *)__zbuf_push(zb, sizeof(type), 1))
151 #define zbuf_pushn(zb, sz) (__zbuf_push(zb, sz, 1))
152 #define zbuf_may_push(zb, type) ((type *)__zbuf_may_push(zb, sizeof(type), 0))
153 #define zbuf_may_pushn(zb, sz) (__zbuf_push(zb, sz, 0))
154
155 static inline void zbuf_put(struct zbuf *zb, const void *src, size_t len)
156 {
157 void *dst = zbuf_pushn(zb, len);
158 if (dst)
159 memcpy(dst, src, len);
160 }
161
162 static inline void zbuf_put8(struct zbuf *zb, uint8_t val)
163 {
164 uint8_t *dst = zbuf_push(zb, uint8_t);
165 if (dst)
166 *dst = val;
167 }
168
169 static inline void zbuf_put_be16(struct zbuf *zb, uint16_t val)
170 {
171 struct unaligned16 {
172 uint16_t value;
173 } __attribute__((packed));
174
175 struct unaligned16 *v = zbuf_push(zb, struct unaligned16);
176 if (v)
177 v->value = htobe16(val);
178 }
179
180 static inline void zbuf_put_be32(struct zbuf *zb, uint32_t val)
181 {
182 struct unaligned32 {
183 uint32_t value;
184 } __attribute__((packed));
185
186 struct unaligned32 *v = zbuf_push(zb, struct unaligned32);
187 if (v)
188 v->value = htobe32(val);
189 }
190
191 void zbuf_copy(struct zbuf *zb, struct zbuf *src, size_t len);
192 void zbuf_copy_peek(struct zbuf *zdst, struct zbuf *zsrc, size_t len);
193
194 void zbufq_init(struct zbuf_queue *);
195 void zbufq_reset(struct zbuf_queue *);
196 void zbufq_queue(struct zbuf_queue *, struct zbuf *);
197 int zbufq_write(struct zbuf_queue *, int);
198
199 #endif