]>
git.proxmox.com Git - mirror_frr.git/blob - nhrpd/zbuf.c
1 /* Stream/packet buffer API implementation
2 * Copyright (c) 2014-2015 Timo Teräs
4 * This file is free software: you may copy, redistribute and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
22 #define ERRNO_IO_RETRY(EN) (((EN) == EAGAIN) || ((EN) == EWOULDBLOCK) || ((EN) == EINTR))
24 DEFINE_MTYPE_STATIC(NHRPD
, ZBUF_DATA
, "NHRPD zbuf data");
26 struct zbuf
*zbuf_alloc(size_t size
)
30 zb
= XCALLOC(MTYPE_ZBUF_DATA
, sizeof(*zb
) + size
);
32 zbuf_init(zb
, zb
+ 1, size
, 0);
38 void zbuf_init(struct zbuf
*zb
, void *buf
, size_t len
, size_t datalen
)
42 .end
= (uint8_t *)buf
+ len
,
44 .tail
= (uint8_t *)buf
+ datalen
,
48 void zbuf_free(struct zbuf
*zb
)
51 XFREE(MTYPE_ZBUF_DATA
, zb
);
54 void zbuf_reset(struct zbuf
*zb
)
56 zb
->head
= zb
->tail
= zb
->buf
;
60 void zbuf_reset_head(struct zbuf
*zb
, void *ptr
)
62 zassert((void *)zb
->buf
<= ptr
&& ptr
<= (void *)zb
->tail
);
66 static void zbuf_remove_headroom(struct zbuf
*zb
)
68 ssize_t headroom
= zbuf_headroom(zb
);
71 memmove(zb
->buf
, zb
->head
, zbuf_used(zb
));
76 ssize_t
zbuf_read(struct zbuf
*zb
, int fd
, size_t maxlen
)
83 zbuf_remove_headroom(zb
);
84 if (maxlen
> zbuf_tailroom(zb
))
85 maxlen
= zbuf_tailroom(zb
);
87 r
= read(fd
, zb
->tail
, maxlen
);
92 else if (r
< 0 && ERRNO_IO_RETRY(errno
))
98 ssize_t
zbuf_write(struct zbuf
*zb
, int fd
)
105 r
= write(fd
, zb
->head
, zbuf_used(zb
));
108 if (zb
->head
== zb
->tail
)
112 else if (r
< 0 && ERRNO_IO_RETRY(errno
))
118 ssize_t
zbuf_recv(struct zbuf
*zb
, int fd
)
125 zbuf_remove_headroom(zb
);
126 r
= recv(fd
, zb
->tail
, zbuf_tailroom(zb
), 0);
131 else if (r
< 0 && ERRNO_IO_RETRY(errno
))
136 ssize_t
zbuf_send(struct zbuf
*zb
, int fd
)
143 r
= send(fd
, zb
->head
, zbuf_used(zb
), 0);
150 void *zbuf_may_pull_until(struct zbuf
*zb
, const char *sep
, struct zbuf
*msg
)
152 size_t seplen
= strlen(sep
), len
;
155 ptr
= memmem(zb
->head
, zbuf_used(zb
), sep
, seplen
);
159 len
= ptr
- zb
->head
+ seplen
;
160 zbuf_init(msg
, zbuf_pulln(zb
, len
), len
, len
);
164 void zbufq_init(struct zbuf_queue
*zbq
)
166 *zbq
= (struct zbuf_queue
){
167 .queue_head
= LIST_INITIALIZER(zbq
->queue_head
),
171 void zbufq_reset(struct zbuf_queue
*zbq
)
173 struct zbuf
*buf
, *bufn
;
175 list_for_each_entry_safe(buf
, bufn
, &zbq
->queue_head
, queue_list
)
177 list_del(&buf
->queue_list
);
182 void zbufq_queue(struct zbuf_queue
*zbq
, struct zbuf
*zb
)
184 list_add_tail(&zb
->queue_list
, &zbq
->queue_head
);
187 int zbufq_write(struct zbuf_queue
*zbq
, int fd
)
189 struct iovec iov
[16];
190 struct zbuf
*zb
, *zbn
;
194 list_for_each_entry_safe(zb
, zbn
, &zbq
->queue_head
, queue_list
)
196 iov
[iovcnt
++] = (struct iovec
){
197 .iov_base
= zb
->head
, .iov_len
= zbuf_used(zb
),
199 if (iovcnt
>= array_size(iov
))
203 r
= writev(fd
, iov
, iovcnt
);
207 list_for_each_entry_safe(zb
, zbn
, &zbq
->queue_head
, queue_list
)
209 if (r
< (ssize_t
)zbuf_used(zb
)) {
215 list_del(&zb
->queue_list
);
222 void zbuf_copy(struct zbuf
*zdst
, struct zbuf
*zsrc
, size_t len
)
227 dst
= zbuf_pushn(zdst
, len
);
228 src
= zbuf_pulln(zsrc
, len
);
231 memcpy(dst
, src
, len
);
234 void zbuf_copy_peek(struct zbuf
*zdst
, struct zbuf
*zsrc
, size_t len
)
239 dst
= zbuf_pushn(zdst
, len
);
240 src
= zbuf_pulln(zsrc
, 0);
243 memcpy(dst
, src
, len
);