]>
git.proxmox.com Git - mirror_frr.git/blob - nhrpd/zbuf.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Stream/packet buffer API implementation
3 * Copyright (c) 2014-2015 Timo Teräs
18 #define ERRNO_IO_RETRY(EN) (((EN) == EAGAIN) || ((EN) == EWOULDBLOCK) || ((EN) == EINTR))
20 DEFINE_MTYPE_STATIC(NHRPD
, ZBUF_DATA
, "NHRPD zbuf data");
22 struct zbuf
*zbuf_alloc(size_t size
)
26 zb
= XCALLOC(MTYPE_ZBUF_DATA
, sizeof(*zb
) + size
);
28 zbuf_init(zb
, zb
+ 1, size
, 0);
34 void zbuf_init(struct zbuf
*zb
, void *buf
, size_t len
, size_t datalen
)
38 .end
= (uint8_t *)buf
+ len
,
40 .tail
= (uint8_t *)buf
+ datalen
,
44 void zbuf_free(struct zbuf
*zb
)
47 XFREE(MTYPE_ZBUF_DATA
, zb
);
50 void zbuf_reset(struct zbuf
*zb
)
52 zb
->head
= zb
->tail
= zb
->buf
;
56 void zbuf_reset_head(struct zbuf
*zb
, void *ptr
)
58 assert((void *)zb
->buf
<= ptr
&& ptr
<= (void *)zb
->tail
);
62 static void zbuf_remove_headroom(struct zbuf
*zb
)
64 ssize_t headroom
= zbuf_headroom(zb
);
67 memmove(zb
->buf
, zb
->head
, zbuf_used(zb
));
72 ssize_t
zbuf_read(struct zbuf
*zb
, int fd
, size_t maxlen
)
79 zbuf_remove_headroom(zb
);
80 if (maxlen
> zbuf_tailroom(zb
))
81 maxlen
= zbuf_tailroom(zb
);
83 r
= read(fd
, zb
->tail
, maxlen
);
88 else if (ERRNO_IO_RETRY(errno
))
94 ssize_t
zbuf_write(struct zbuf
*zb
, int fd
)
101 r
= write(fd
, zb
->head
, zbuf_used(zb
));
104 if (zb
->head
== zb
->tail
)
108 else if (ERRNO_IO_RETRY(errno
))
114 ssize_t
zbuf_recv(struct zbuf
*zb
, int fd
)
121 zbuf_remove_headroom(zb
);
122 r
= recv(fd
, zb
->tail
, zbuf_tailroom(zb
), 0);
127 else if (ERRNO_IO_RETRY(errno
))
132 ssize_t
zbuf_send(struct zbuf
*zb
, int fd
)
139 r
= send(fd
, zb
->head
, zbuf_used(zb
), 0);
146 void *zbuf_may_pull_until(struct zbuf
*zb
, const char *sep
, struct zbuf
*msg
)
148 size_t seplen
= strlen(sep
), len
;
151 ptr
= memmem(zb
->head
, zbuf_used(zb
), sep
, seplen
);
155 len
= ptr
- zb
->head
+ seplen
;
156 zbuf_init(msg
, zbuf_pulln(zb
, len
), len
, len
);
160 void zbufq_init(struct zbuf_queue
*zbq
)
162 *zbq
= (struct zbuf_queue
){
163 .queue_head
= INIT_DLIST(zbq
->queue_head
),
167 void zbufq_reset(struct zbuf_queue
*zbq
)
171 frr_each_safe (zbuf_queue
, &zbq
->queue_head
, buf
) {
172 zbuf_queue_del(&zbq
->queue_head
, buf
);
177 void zbufq_queue(struct zbuf_queue
*zbq
, struct zbuf
*zb
)
179 zbuf_queue_add_tail(&zbq
->queue_head
, zb
);
182 int zbufq_write(struct zbuf_queue
*zbq
, int fd
)
184 struct iovec iov
[16];
189 frr_each_safe (zbuf_queue
, &zbq
->queue_head
, zb
) {
190 iov
[iovcnt
++] = (struct iovec
){
191 .iov_base
= zb
->head
, .iov_len
= zbuf_used(zb
),
193 if (iovcnt
>= array_size(iov
))
197 r
= writev(fd
, iov
, iovcnt
);
201 frr_each_safe (zbuf_queue
, &zbq
->queue_head
, zb
) {
202 if (r
< (ssize_t
)zbuf_used(zb
)) {
208 zbuf_queue_del(&zbq
->queue_head
, zb
);
215 void zbuf_copy(struct zbuf
*zdst
, struct zbuf
*zsrc
, size_t len
)
220 dst
= zbuf_pushn(zdst
, len
);
221 src
= zbuf_pulln(zsrc
, len
);
224 memcpy(dst
, src
, len
);
227 void zbuf_copy_peek(struct zbuf
*zdst
, struct zbuf
*zsrc
, size_t len
)
232 dst
= zbuf_pushn(zdst
, len
);
233 src
= zbuf_pulln(zsrc
, 0);
236 memcpy(dst
, src
, len
);