]>
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
);
87 if (r
> 0) zb
->tail
+= r
;
88 else if (r
== 0) r
= -2;
89 else if (r
< 0 && ERRNO_IO_RETRY(errno
)) r
= 0;
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
)
107 else if (r
== 0) r
= -2;
108 else if (r
< 0 && ERRNO_IO_RETRY(errno
)) r
= 0;
113 ssize_t
zbuf_recv(struct zbuf
*zb
, int fd
)
120 zbuf_remove_headroom(zb
);
121 r
= recv(fd
, zb
->tail
, zbuf_tailroom(zb
), 0);
122 if (r
> 0) zb
->tail
+= r
;
123 else if (r
== 0) r
= -2;
124 else if (r
< 0 && ERRNO_IO_RETRY(errno
)) r
= 0;
128 ssize_t
zbuf_send(struct zbuf
*zb
, int fd
)
135 r
= send(fd
, zb
->head
, zbuf_used(zb
), 0);
142 void *zbuf_may_pull_until(struct zbuf
*zb
, const char *sep
, struct zbuf
*msg
)
144 size_t seplen
= strlen(sep
), len
;
147 ptr
= memmem(zb
->head
, zbuf_used(zb
), sep
, seplen
);
148 if (!ptr
) return NULL
;
150 len
= ptr
- zb
->head
+ seplen
;
151 zbuf_init(msg
, zbuf_pulln(zb
, len
), len
, len
);
155 void zbufq_init(struct zbuf_queue
*zbq
)
157 *zbq
= (struct zbuf_queue
) {
158 .queue_head
= LIST_INITIALIZER(zbq
->queue_head
),
162 void zbufq_reset(struct zbuf_queue
*zbq
)
164 struct zbuf
*buf
, *bufn
;
166 list_for_each_entry_safe(buf
, bufn
, &zbq
->queue_head
, queue_list
) {
167 list_del(&buf
->queue_list
);
172 void zbufq_queue(struct zbuf_queue
*zbq
, struct zbuf
*zb
)
174 list_add_tail(&zb
->queue_list
, &zbq
->queue_head
);
177 int zbufq_write(struct zbuf_queue
*zbq
, int fd
)
179 struct iovec iov
[16];
180 struct zbuf
*zb
, *zbn
;
184 list_for_each_entry_safe(zb
, zbn
, &zbq
->queue_head
, queue_list
) {
185 iov
[iovcnt
++] = (struct iovec
) {
186 .iov_base
= zb
->head
,
187 .iov_len
= zbuf_used(zb
),
189 if (iovcnt
>= ZEBRA_NUM_OF(iov
))
193 r
= writev(fd
, iov
, iovcnt
);
197 list_for_each_entry_safe(zb
, zbn
, &zbq
->queue_head
, queue_list
) {
198 if (r
< (ssize_t
)zbuf_used(zb
)) {
204 list_del(&zb
->queue_list
);
211 void zbuf_copy(struct zbuf
*zdst
, struct zbuf
*zsrc
, size_t len
)
216 dst
= zbuf_pushn(zdst
, len
);
217 src
= zbuf_pulln(zsrc
, len
);
218 if (!dst
|| !src
) return;
219 memcpy(dst
, src
, len
);