]>
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.
19 #define ERRNO_IO_RETRY(EN) (((EN) == EAGAIN) || ((EN) == EWOULDBLOCK) || ((EN) == EINTR))
21 DEFINE_MTYPE_STATIC(NHRPD
, ZBUF_DATA
, "NHRPD zbuf data")
23 struct zbuf
*zbuf_alloc(size_t size
)
27 zb
= XMALLOC(MTYPE_ZBUF_DATA
, sizeof(*zb
) + size
);
31 zbuf_init(zb
, zb
+ 1, size
, 0);
37 void zbuf_init(struct zbuf
*zb
, void *buf
, size_t len
, size_t datalen
)
41 .end
= (uint8_t *)buf
+ len
,
43 .tail
= (uint8_t *)buf
+ datalen
,
47 void zbuf_free(struct zbuf
*zb
)
50 XFREE(MTYPE_ZBUF_DATA
, zb
);
53 void zbuf_reset(struct zbuf
*zb
)
55 zb
->head
= zb
->tail
= zb
->buf
;
59 void zbuf_reset_head(struct zbuf
*zb
, void *ptr
)
61 zassert((void *)zb
->buf
<= ptr
&& ptr
<= (void *)zb
->tail
);
65 static void zbuf_remove_headroom(struct zbuf
*zb
)
67 ssize_t headroom
= zbuf_headroom(zb
);
70 memmove(zb
->buf
, zb
->head
, zbuf_used(zb
));
75 ssize_t
zbuf_read(struct zbuf
*zb
, int fd
, size_t maxlen
)
82 zbuf_remove_headroom(zb
);
83 if (maxlen
> zbuf_tailroom(zb
))
84 maxlen
= zbuf_tailroom(zb
);
86 r
= read(fd
, zb
->tail
, maxlen
);
91 else if (r
< 0 && ERRNO_IO_RETRY(errno
))
97 ssize_t
zbuf_write(struct zbuf
*zb
, int fd
)
104 r
= write(fd
, zb
->head
, zbuf_used(zb
));
107 if (zb
->head
== zb
->tail
)
111 else if (r
< 0 && ERRNO_IO_RETRY(errno
))
117 ssize_t
zbuf_recv(struct zbuf
*zb
, int fd
)
124 zbuf_remove_headroom(zb
);
125 r
= recv(fd
, zb
->tail
, zbuf_tailroom(zb
), 0);
130 else if (r
< 0 && ERRNO_IO_RETRY(errno
))
135 ssize_t
zbuf_send(struct zbuf
*zb
, int fd
)
142 r
= send(fd
, zb
->head
, zbuf_used(zb
), 0);
149 void *zbuf_may_pull_until(struct zbuf
*zb
, const char *sep
, struct zbuf
*msg
)
151 size_t seplen
= strlen(sep
), len
;
154 ptr
= memmem(zb
->head
, zbuf_used(zb
), sep
, seplen
);
158 len
= ptr
- zb
->head
+ seplen
;
159 zbuf_init(msg
, zbuf_pulln(zb
, len
), len
, len
);
163 void zbufq_init(struct zbuf_queue
*zbq
)
165 *zbq
= (struct zbuf_queue
){
166 .queue_head
= LIST_INITIALIZER(zbq
->queue_head
),
170 void zbufq_reset(struct zbuf_queue
*zbq
)
172 struct zbuf
*buf
, *bufn
;
174 list_for_each_entry_safe(buf
, bufn
, &zbq
->queue_head
, queue_list
)
176 list_del(&buf
->queue_list
);
181 void zbufq_queue(struct zbuf_queue
*zbq
, struct zbuf
*zb
)
183 list_add_tail(&zb
->queue_list
, &zbq
->queue_head
);
186 int zbufq_write(struct zbuf_queue
*zbq
, int fd
)
188 struct iovec iov
[16];
189 struct zbuf
*zb
, *zbn
;
193 list_for_each_entry_safe(zb
, zbn
, &zbq
->queue_head
, queue_list
)
195 iov
[iovcnt
++] = (struct iovec
){
196 .iov_base
= zb
->head
, .iov_len
= zbuf_used(zb
),
198 if (iovcnt
>= ZEBRA_NUM_OF(iov
))
202 r
= writev(fd
, iov
, iovcnt
);
206 list_for_each_entry_safe(zb
, zbn
, &zbq
->queue_head
, queue_list
)
208 if (r
< (ssize_t
)zbuf_used(zb
)) {
214 list_del(&zb
->queue_list
);
221 void zbuf_copy(struct zbuf
*zdst
, struct zbuf
*zsrc
, size_t len
)
226 dst
= zbuf_pushn(zdst
, len
);
227 src
= zbuf_pulln(zsrc
, len
);
230 memcpy(dst
, src
, len
);