]>
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
);
29 zbuf_init(zb
, zb
+ 1, size
, 0);
35 void zbuf_init(struct zbuf
*zb
, void *buf
, size_t len
, size_t datalen
)
39 .end
= (uint8_t *)buf
+ len
,
41 .tail
= (uint8_t *)buf
+ datalen
,
45 void zbuf_free(struct zbuf
*zb
)
48 XFREE(MTYPE_ZBUF_DATA
, zb
);
51 void zbuf_reset(struct zbuf
*zb
)
53 zb
->head
= zb
->tail
= zb
->buf
;
57 void zbuf_reset_head(struct zbuf
*zb
, void *ptr
)
59 zassert((void *)zb
->buf
<= ptr
&& ptr
<= (void *)zb
->tail
);
63 static void zbuf_remove_headroom(struct zbuf
*zb
)
65 ssize_t headroom
= zbuf_headroom(zb
);
68 memmove(zb
->buf
, zb
->head
, zbuf_used(zb
));
73 ssize_t
zbuf_read(struct zbuf
*zb
, int fd
, size_t maxlen
)
80 zbuf_remove_headroom(zb
);
81 if (maxlen
> zbuf_tailroom(zb
))
82 maxlen
= zbuf_tailroom(zb
);
84 r
= read(fd
, zb
->tail
, maxlen
);
89 else if (r
< 0 && ERRNO_IO_RETRY(errno
))
95 ssize_t
zbuf_write(struct zbuf
*zb
, int fd
)
102 r
= write(fd
, zb
->head
, zbuf_used(zb
));
105 if (zb
->head
== zb
->tail
)
109 else if (r
< 0 && ERRNO_IO_RETRY(errno
))
115 ssize_t
zbuf_recv(struct zbuf
*zb
, int fd
)
122 zbuf_remove_headroom(zb
);
123 r
= recv(fd
, zb
->tail
, zbuf_tailroom(zb
), 0);
128 else if (r
< 0 && ERRNO_IO_RETRY(errno
))
133 ssize_t
zbuf_send(struct zbuf
*zb
, int fd
)
140 r
= send(fd
, zb
->head
, zbuf_used(zb
), 0);
147 void *zbuf_may_pull_until(struct zbuf
*zb
, const char *sep
, struct zbuf
*msg
)
149 size_t seplen
= strlen(sep
), len
;
152 ptr
= memmem(zb
->head
, zbuf_used(zb
), sep
, seplen
);
156 len
= ptr
- zb
->head
+ seplen
;
157 zbuf_init(msg
, zbuf_pulln(zb
, len
), len
, len
);
161 void zbufq_init(struct zbuf_queue
*zbq
)
163 *zbq
= (struct zbuf_queue
){
164 .queue_head
= LIST_INITIALIZER(zbq
->queue_head
),
168 void zbufq_reset(struct zbuf_queue
*zbq
)
170 struct zbuf
*buf
, *bufn
;
172 list_for_each_entry_safe(buf
, bufn
, &zbq
->queue_head
, queue_list
)
174 list_del(&buf
->queue_list
);
179 void zbufq_queue(struct zbuf_queue
*zbq
, struct zbuf
*zb
)
181 list_add_tail(&zb
->queue_list
, &zbq
->queue_head
);
184 int zbufq_write(struct zbuf_queue
*zbq
, int fd
)
186 struct iovec iov
[16];
187 struct zbuf
*zb
, *zbn
;
191 list_for_each_entry_safe(zb
, zbn
, &zbq
->queue_head
, queue_list
)
193 iov
[iovcnt
++] = (struct iovec
){
194 .iov_base
= zb
->head
, .iov_len
= zbuf_used(zb
),
196 if (iovcnt
>= ZEBRA_NUM_OF(iov
))
200 r
= writev(fd
, iov
, iovcnt
);
204 list_for_each_entry_safe(zb
, zbn
, &zbq
->queue_head
, queue_list
)
206 if (r
< (ssize_t
)zbuf_used(zb
)) {
212 list_del(&zb
->queue_list
);
219 void zbuf_copy(struct zbuf
*zdst
, struct zbuf
*zsrc
, size_t len
)
224 dst
= zbuf_pushn(zdst
, len
);
225 src
= zbuf_pulln(zsrc
, len
);
228 memcpy(dst
, src
, len
);