1 /* $OpenBSD: buffer.c,v 1.3 2004/08/10 19:18:23 henning Exp $ */
4 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/types.h>
31 int buf_write(int, struct buf *);
32 void buf_enqueue(struct msgbuf *, struct buf *);
33 void buf_dequeue(struct msgbuf *, struct buf *);
40 if ((buf = calloc(1, sizeof(struct buf))) == NULL)
42 if ((buf->buf = malloc(len)) == NULL) {
52 buf_add(struct buf *buf, void *data, ssize_t len)
54 if (buf->wpos + len > buf->size)
57 memcpy(buf->buf + buf->wpos, data, len);
63 buf_close(struct msgbuf *msgbuf, struct buf *buf)
65 buf_enqueue(msgbuf, buf);
70 buf_write(int sock, struct buf *buf)
74 if ((n = write(sock, buf->buf + buf->rpos,
75 buf->size - buf->rpos)) == -1) {
76 if (errno == EAGAIN) /* cannot write immediately */
82 if (n == 0) { /* connection closed */
87 if (n < buf->size - buf->rpos) { /* not all data written yet */
95 buf_free(struct buf *buf)
102 msgbuf_init(struct msgbuf *msgbuf)
106 TAILQ_INIT(&msgbuf->bufs);
110 msgbuf_clear(struct msgbuf *msgbuf)
114 while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
115 buf_dequeue(msgbuf, buf);
119 msgbuf_write(struct msgbuf *msgbuf)
123 * when we cannot write out data completely from a buffer,
124 * we MUST return and NOT try to write out stuff from later buffers -
125 * the socket might have become writeable again
127 struct iovec iov[IOV_MAX];
128 struct buf *buf, *next;
132 bzero(&iov, sizeof(iov));
133 TAILQ_FOREACH(buf, &msgbuf->bufs, entries) {
136 iov[i].iov_base = buf->buf + buf->rpos;
137 iov[i].iov_len = buf->size - buf->rpos;
141 if ((n = writev(msgbuf->fd, iov, i)) == -1) {
142 if (errno == EAGAIN) /* cannot write immediately */
148 if (n == 0) { /* connection closed */
153 for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
155 next = TAILQ_NEXT(buf, entries);
156 if (n >= buf->size - buf->rpos) {
157 n -= buf->size - buf->rpos;
158 buf_dequeue(msgbuf, buf);
169 buf_enqueue(struct msgbuf *msgbuf, struct buf *buf)
171 TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entries);
176 buf_dequeue(struct msgbuf *msgbuf, struct buf *buf)
178 TAILQ_REMOVE(&msgbuf->bufs, buf, entries);