Blame


1 ce062d50 2019-08-21 martijn /* $OpenBSD: iobuf.c,v 1.11 2019/06/12 17:42:53 eric Exp $ */
2 ce062d50 2019-08-21 martijn /*
3 ce062d50 2019-08-21 martijn * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
4 ce062d50 2019-08-21 martijn *
5 ce062d50 2019-08-21 martijn * Permission to use, copy, modify, and distribute this software for any
6 ce062d50 2019-08-21 martijn * purpose with or without fee is hereby granted, provided that the above
7 ce062d50 2019-08-21 martijn * copyright notice and this permission notice appear in all copies.
8 ce062d50 2019-08-21 martijn *
9 ce062d50 2019-08-21 martijn * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 ce062d50 2019-08-21 martijn * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 ce062d50 2019-08-21 martijn * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 ce062d50 2019-08-21 martijn * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 ce062d50 2019-08-21 martijn * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 ce062d50 2019-08-21 martijn * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 ce062d50 2019-08-21 martijn * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 ce062d50 2019-08-21 martijn */
17 ce062d50 2019-08-21 martijn
18 957c2372 2019-11-14 martijn #define _GNU_SOURCE 1
19 13f08f83 2019-11-14 martijn #define _BSD_SOURCE 1
20 957c2372 2019-11-14 martijn
21 ce062d50 2019-08-21 martijn #include <sys/types.h>
22 ce062d50 2019-08-21 martijn #include <sys/socket.h>
23 ce062d50 2019-08-21 martijn #include <sys/uio.h>
24 ce062d50 2019-08-21 martijn
25 ce062d50 2019-08-21 martijn #include <errno.h>
26 ce062d50 2019-08-21 martijn #include <limits.h>
27 ce062d50 2019-08-21 martijn #include <stdarg.h>
28 ce062d50 2019-08-21 martijn #include <stdio.h>
29 ce062d50 2019-08-21 martijn #include <stdlib.h>
30 ce062d50 2019-08-21 martijn #include <string.h>
31 ce062d50 2019-08-21 martijn #include <unistd.h>
32 ce062d50 2019-08-21 martijn
33 ce062d50 2019-08-21 martijn #ifdef IO_TLS
34 ce062d50 2019-08-21 martijn #include <openssl/err.h>
35 ce062d50 2019-08-21 martijn #include <openssl/ssl.h>
36 ce062d50 2019-08-21 martijn #endif
37 ce062d50 2019-08-21 martijn
38 957c2372 2019-11-14 martijn #include "openbsd-compat.h"
39 ce062d50 2019-08-21 martijn #include "iobuf.h"
40 ce062d50 2019-08-21 martijn
41 ce062d50 2019-08-21 martijn #define IOBUF_MAX 65536
42 ce062d50 2019-08-21 martijn #define IOBUFQ_MIN 4096
43 ce062d50 2019-08-21 martijn
44 ce062d50 2019-08-21 martijn struct ioqbuf *ioqbuf_alloc(struct iobuf *, size_t);
45 ce062d50 2019-08-21 martijn void iobuf_drain(struct iobuf *, size_t);
46 ce062d50 2019-08-21 martijn
47 ce062d50 2019-08-21 martijn int
48 ce062d50 2019-08-21 martijn iobuf_init(struct iobuf *io, size_t size, size_t max)
49 ce062d50 2019-08-21 martijn {
50 ce062d50 2019-08-21 martijn memset(io, 0, sizeof *io);
51 ce062d50 2019-08-21 martijn
52 ce062d50 2019-08-21 martijn if (max == 0)
53 ce062d50 2019-08-21 martijn max = IOBUF_MAX;
54 ce062d50 2019-08-21 martijn
55 ce062d50 2019-08-21 martijn if (size == 0)
56 ce062d50 2019-08-21 martijn size = max;
57 ce062d50 2019-08-21 martijn
58 ce062d50 2019-08-21 martijn if (size > max)
59 ce062d50 2019-08-21 martijn return (-1);
60 ce062d50 2019-08-21 martijn
61 ce062d50 2019-08-21 martijn if ((io->buf = calloc(size, 1)) == NULL)
62 ce062d50 2019-08-21 martijn return (-1);
63 ce062d50 2019-08-21 martijn
64 ce062d50 2019-08-21 martijn io->size = size;
65 ce062d50 2019-08-21 martijn io->max = max;
66 ce062d50 2019-08-21 martijn
67 ce062d50 2019-08-21 martijn return (0);
68 ce062d50 2019-08-21 martijn }
69 ce062d50 2019-08-21 martijn
70 ce062d50 2019-08-21 martijn void
71 ce062d50 2019-08-21 martijn iobuf_clear(struct iobuf *io)
72 ce062d50 2019-08-21 martijn {
73 ce062d50 2019-08-21 martijn struct ioqbuf *q;
74 ce062d50 2019-08-21 martijn
75 ce062d50 2019-08-21 martijn free(io->buf);
76 ce062d50 2019-08-21 martijn
77 ce062d50 2019-08-21 martijn while ((q = io->outq)) {
78 ce062d50 2019-08-21 martijn io->outq = q->next;
79 ce062d50 2019-08-21 martijn free(q);
80 ce062d50 2019-08-21 martijn }
81 ce062d50 2019-08-21 martijn
82 ce062d50 2019-08-21 martijn memset(io, 0, sizeof (*io));
83 ce062d50 2019-08-21 martijn }
84 ce062d50 2019-08-21 martijn
85 ce062d50 2019-08-21 martijn void
86 ce062d50 2019-08-21 martijn iobuf_drain(struct iobuf *io, size_t n)
87 ce062d50 2019-08-21 martijn {
88 ce062d50 2019-08-21 martijn struct ioqbuf *q;
89 ce062d50 2019-08-21 martijn size_t left = n;
90 ce062d50 2019-08-21 martijn
91 ce062d50 2019-08-21 martijn while ((q = io->outq) && left) {
92 ce062d50 2019-08-21 martijn if ((q->wpos - q->rpos) > left) {
93 ce062d50 2019-08-21 martijn q->rpos += left;
94 ce062d50 2019-08-21 martijn left = 0;
95 ce062d50 2019-08-21 martijn } else {
96 ce062d50 2019-08-21 martijn left -= q->wpos - q->rpos;
97 ce062d50 2019-08-21 martijn io->outq = q->next;
98 ce062d50 2019-08-21 martijn free(q);
99 ce062d50 2019-08-21 martijn }
100 ce062d50 2019-08-21 martijn }
101 ce062d50 2019-08-21 martijn
102 ce062d50 2019-08-21 martijn io->queued -= (n - left);
103 ce062d50 2019-08-21 martijn if (io->outq == NULL)
104 ce062d50 2019-08-21 martijn io->outqlast = NULL;
105 ce062d50 2019-08-21 martijn }
106 ce062d50 2019-08-21 martijn
107 ce062d50 2019-08-21 martijn int
108 ce062d50 2019-08-21 martijn iobuf_extend(struct iobuf *io, size_t n)
109 ce062d50 2019-08-21 martijn {
110 ce062d50 2019-08-21 martijn char *t;
111 ce062d50 2019-08-21 martijn
112 ce062d50 2019-08-21 martijn if (n > io->max)
113 ce062d50 2019-08-21 martijn return (-1);
114 ce062d50 2019-08-21 martijn
115 ce062d50 2019-08-21 martijn if (io->max - io->size < n)
116 ce062d50 2019-08-21 martijn return (-1);
117 ce062d50 2019-08-21 martijn
118 ce062d50 2019-08-21 martijn t = recallocarray(io->buf, io->size, io->size + n, 1);
119 ce062d50 2019-08-21 martijn if (t == NULL)
120 ce062d50 2019-08-21 martijn return (-1);
121 ce062d50 2019-08-21 martijn
122 ce062d50 2019-08-21 martijn io->size += n;
123 ce062d50 2019-08-21 martijn io->buf = t;
124 ce062d50 2019-08-21 martijn
125 ce062d50 2019-08-21 martijn return (0);
126 ce062d50 2019-08-21 martijn }
127 ce062d50 2019-08-21 martijn
128 ce062d50 2019-08-21 martijn size_t
129 ce062d50 2019-08-21 martijn iobuf_left(struct iobuf *io)
130 ce062d50 2019-08-21 martijn {
131 ce062d50 2019-08-21 martijn return io->size - io->wpos;
132 ce062d50 2019-08-21 martijn }
133 ce062d50 2019-08-21 martijn
134 ce062d50 2019-08-21 martijn size_t
135 ce062d50 2019-08-21 martijn iobuf_space(struct iobuf *io)
136 ce062d50 2019-08-21 martijn {
137 ce062d50 2019-08-21 martijn return io->size - (io->wpos - io->rpos);
138 ce062d50 2019-08-21 martijn }
139 ce062d50 2019-08-21 martijn
140 ce062d50 2019-08-21 martijn size_t
141 ce062d50 2019-08-21 martijn iobuf_len(struct iobuf *io)
142 ce062d50 2019-08-21 martijn {
143 ce062d50 2019-08-21 martijn return io->wpos - io->rpos;
144 ce062d50 2019-08-21 martijn }
145 ce062d50 2019-08-21 martijn
146 ce062d50 2019-08-21 martijn char *
147 ce062d50 2019-08-21 martijn iobuf_data(struct iobuf *io)
148 ce062d50 2019-08-21 martijn {
149 ce062d50 2019-08-21 martijn return io->buf + io->rpos;
150 ce062d50 2019-08-21 martijn }
151 ce062d50 2019-08-21 martijn
152 ce062d50 2019-08-21 martijn void
153 ce062d50 2019-08-21 martijn iobuf_drop(struct iobuf *io, size_t n)
154 ce062d50 2019-08-21 martijn {
155 ce062d50 2019-08-21 martijn if (n >= iobuf_len(io)) {
156 ce062d50 2019-08-21 martijn io->rpos = io->wpos = 0;
157 ce062d50 2019-08-21 martijn return;
158 ce062d50 2019-08-21 martijn }
159 ce062d50 2019-08-21 martijn
160 ce062d50 2019-08-21 martijn io->rpos += n;
161 ce062d50 2019-08-21 martijn }
162 ce062d50 2019-08-21 martijn
163 ce062d50 2019-08-21 martijn char *
164 ce062d50 2019-08-21 martijn iobuf_getline(struct iobuf *iobuf, size_t *rlen)
165 ce062d50 2019-08-21 martijn {
166 ce062d50 2019-08-21 martijn char *buf;
167 ce062d50 2019-08-21 martijn size_t len, i;
168 ce062d50 2019-08-21 martijn
169 ce062d50 2019-08-21 martijn buf = iobuf_data(iobuf);
170 ce062d50 2019-08-21 martijn len = iobuf_len(iobuf);
171 ce062d50 2019-08-21 martijn
172 ce062d50 2019-08-21 martijn for (i = 0; i + 1 <= len; i++)
173 ce062d50 2019-08-21 martijn if (buf[i] == '\n') {
174 ce062d50 2019-08-21 martijn /* Note: the returned address points into the iobuf
175 ce062d50 2019-08-21 martijn * buffer. We NUL-end it for convenience, and discard
176 ce062d50 2019-08-21 martijn * the data from the iobuf, so that the caller doesn't
177 ce062d50 2019-08-21 martijn * have to do it. The data remains "valid" as long
178 ce062d50 2019-08-21 martijn * as the iobuf does not overwrite it, that is until
179 ce062d50 2019-08-21 martijn * the next call to iobuf_normalize() or iobuf_extend().
180 ce062d50 2019-08-21 martijn */
181 ce062d50 2019-08-21 martijn iobuf_drop(iobuf, i + 1);
182 ce062d50 2019-08-21 martijn len = (i && buf[i - 1] == '\r') ? i - 1 : i;
183 ce062d50 2019-08-21 martijn buf[len] = '\0';
184 ce062d50 2019-08-21 martijn if (rlen)
185 ce062d50 2019-08-21 martijn *rlen = len;
186 ce062d50 2019-08-21 martijn return (buf);
187 ce062d50 2019-08-21 martijn }
188 ce062d50 2019-08-21 martijn
189 ce062d50 2019-08-21 martijn return (NULL);
190 ce062d50 2019-08-21 martijn }
191 ce062d50 2019-08-21 martijn
192 ce062d50 2019-08-21 martijn void
193 ce062d50 2019-08-21 martijn iobuf_normalize(struct iobuf *io)
194 ce062d50 2019-08-21 martijn {
195 ce062d50 2019-08-21 martijn if (io->rpos == 0)
196 ce062d50 2019-08-21 martijn return;
197 ce062d50 2019-08-21 martijn
198 ce062d50 2019-08-21 martijn if (io->rpos == io->wpos) {
199 ce062d50 2019-08-21 martijn io->rpos = io->wpos = 0;
200 ce062d50 2019-08-21 martijn return;
201 ce062d50 2019-08-21 martijn }
202 ce062d50 2019-08-21 martijn
203 ce062d50 2019-08-21 martijn memmove(io->buf, io->buf + io->rpos, io->wpos - io->rpos);
204 ce062d50 2019-08-21 martijn io->wpos -= io->rpos;
205 ce062d50 2019-08-21 martijn io->rpos = 0;
206 ce062d50 2019-08-21 martijn }
207 ce062d50 2019-08-21 martijn
208 ce062d50 2019-08-21 martijn ssize_t
209 ce062d50 2019-08-21 martijn iobuf_read(struct iobuf *io, int fd)
210 ce062d50 2019-08-21 martijn {
211 ce062d50 2019-08-21 martijn ssize_t n;
212 ce062d50 2019-08-21 martijn
213 ce062d50 2019-08-21 martijn n = read(fd, io->buf + io->wpos, iobuf_left(io));
214 ce062d50 2019-08-21 martijn if (n == -1) {
215 ce062d50 2019-08-21 martijn /* XXX is this really what we want? */
216 ce062d50 2019-08-21 martijn if (errno == EAGAIN || errno == EINTR)
217 ce062d50 2019-08-21 martijn return (IOBUF_WANT_READ);
218 ce062d50 2019-08-21 martijn return (IOBUF_ERROR);
219 ce062d50 2019-08-21 martijn }
220 ce062d50 2019-08-21 martijn if (n == 0)
221 ce062d50 2019-08-21 martijn return (IOBUF_CLOSED);
222 ce062d50 2019-08-21 martijn
223 ce062d50 2019-08-21 martijn io->wpos += n;
224 ce062d50 2019-08-21 martijn
225 ce062d50 2019-08-21 martijn return (n);
226 ce062d50 2019-08-21 martijn }
227 ce062d50 2019-08-21 martijn
228 ce062d50 2019-08-21 martijn struct ioqbuf *
229 ce062d50 2019-08-21 martijn ioqbuf_alloc(struct iobuf *io, size_t len)
230 ce062d50 2019-08-21 martijn {
231 ce062d50 2019-08-21 martijn struct ioqbuf *q;
232 ce062d50 2019-08-21 martijn
233 ce062d50 2019-08-21 martijn if (len < IOBUFQ_MIN)
234 ce062d50 2019-08-21 martijn len = IOBUFQ_MIN;
235 ce062d50 2019-08-21 martijn
236 ce062d50 2019-08-21 martijn if ((q = malloc(sizeof(*q) + len)) == NULL)
237 ce062d50 2019-08-21 martijn return (NULL);
238 ce062d50 2019-08-21 martijn
239 ce062d50 2019-08-21 martijn q->rpos = 0;
240 ce062d50 2019-08-21 martijn q->wpos = 0;
241 ce062d50 2019-08-21 martijn q->size = len;
242 ce062d50 2019-08-21 martijn q->next = NULL;
243 ce062d50 2019-08-21 martijn q->buf = (char *)(q) + sizeof(*q);
244 ce062d50 2019-08-21 martijn
245 ce062d50 2019-08-21 martijn if (io->outqlast == NULL)
246 ce062d50 2019-08-21 martijn io->outq = q;
247 ce062d50 2019-08-21 martijn else
248 ce062d50 2019-08-21 martijn io->outqlast->next = q;
249 ce062d50 2019-08-21 martijn io->outqlast = q;
250 ce062d50 2019-08-21 martijn
251 ce062d50 2019-08-21 martijn return (q);
252 ce062d50 2019-08-21 martijn }
253 ce062d50 2019-08-21 martijn
254 ce062d50 2019-08-21 martijn size_t
255 ce062d50 2019-08-21 martijn iobuf_queued(struct iobuf *io)
256 ce062d50 2019-08-21 martijn {
257 ce062d50 2019-08-21 martijn return io->queued;
258 ce062d50 2019-08-21 martijn }
259 ce062d50 2019-08-21 martijn
260 ce062d50 2019-08-21 martijn void *
261 ce062d50 2019-08-21 martijn iobuf_reserve(struct iobuf *io, size_t len)
262 ce062d50 2019-08-21 martijn {
263 ce062d50 2019-08-21 martijn struct ioqbuf *q;
264 ce062d50 2019-08-21 martijn void *r;
265 ce062d50 2019-08-21 martijn
266 ce062d50 2019-08-21 martijn if (len == 0)
267 ce062d50 2019-08-21 martijn return (NULL);
268 ce062d50 2019-08-21 martijn
269 ce062d50 2019-08-21 martijn if (((q = io->outqlast) == NULL) || q->size - q->wpos <= len) {
270 ce062d50 2019-08-21 martijn if ((q = ioqbuf_alloc(io, len)) == NULL)
271 ce062d50 2019-08-21 martijn return (NULL);
272 ce062d50 2019-08-21 martijn }
273 ce062d50 2019-08-21 martijn
274 ce062d50 2019-08-21 martijn r = q->buf + q->wpos;
275 ce062d50 2019-08-21 martijn q->wpos += len;
276 ce062d50 2019-08-21 martijn io->queued += len;
277 ce062d50 2019-08-21 martijn
278 ce062d50 2019-08-21 martijn return (r);
279 ce062d50 2019-08-21 martijn }
280 ce062d50 2019-08-21 martijn
281 ce062d50 2019-08-21 martijn int
282 ce062d50 2019-08-21 martijn iobuf_queue(struct iobuf *io, const void *data, size_t len)
283 ce062d50 2019-08-21 martijn {
284 ce062d50 2019-08-21 martijn void *buf;
285 ce062d50 2019-08-21 martijn
286 ce062d50 2019-08-21 martijn if (len == 0)
287 ce062d50 2019-08-21 martijn return (0);
288 ce062d50 2019-08-21 martijn
289 ce062d50 2019-08-21 martijn if ((buf = iobuf_reserve(io, len)) == NULL)
290 ce062d50 2019-08-21 martijn return (-1);
291 ce062d50 2019-08-21 martijn
292 ce062d50 2019-08-21 martijn memmove(buf, data, len);
293 ce062d50 2019-08-21 martijn
294 ce062d50 2019-08-21 martijn return (len);
295 ce062d50 2019-08-21 martijn }
296 ce062d50 2019-08-21 martijn
297 ce062d50 2019-08-21 martijn int
298 ce062d50 2019-08-21 martijn iobuf_queuev(struct iobuf *io, const struct iovec *iov, int iovcnt)
299 ce062d50 2019-08-21 martijn {
300 ce062d50 2019-08-21 martijn int i;
301 ce062d50 2019-08-21 martijn size_t len = 0;
302 ce062d50 2019-08-21 martijn char *buf;
303 ce062d50 2019-08-21 martijn
304 ce062d50 2019-08-21 martijn for (i = 0; i < iovcnt; i++)
305 ce062d50 2019-08-21 martijn len += iov[i].iov_len;
306 ce062d50 2019-08-21 martijn
307 ce062d50 2019-08-21 martijn if ((buf = iobuf_reserve(io, len)) == NULL)
308 ce062d50 2019-08-21 martijn return (-1);
309 ce062d50 2019-08-21 martijn
310 ce062d50 2019-08-21 martijn for (i = 0; i < iovcnt; i++) {
311 ce062d50 2019-08-21 martijn if (iov[i].iov_len == 0)
312 ce062d50 2019-08-21 martijn continue;
313 ce062d50 2019-08-21 martijn memmove(buf, iov[i].iov_base, iov[i].iov_len);
314 ce062d50 2019-08-21 martijn buf += iov[i].iov_len;
315 ce062d50 2019-08-21 martijn }
316 ce062d50 2019-08-21 martijn
317 ce062d50 2019-08-21 martijn return (0);
318 ce062d50 2019-08-21 martijn
319 ce062d50 2019-08-21 martijn }
320 ce062d50 2019-08-21 martijn
321 ce062d50 2019-08-21 martijn int
322 ce062d50 2019-08-21 martijn iobuf_fqueue(struct iobuf *io, const char *fmt, ...)
323 ce062d50 2019-08-21 martijn {
324 ce062d50 2019-08-21 martijn va_list ap;
325 ce062d50 2019-08-21 martijn int len;
326 ce062d50 2019-08-21 martijn
327 ce062d50 2019-08-21 martijn va_start(ap, fmt);
328 ce062d50 2019-08-21 martijn len = iobuf_vfqueue(io, fmt, ap);
329 ce062d50 2019-08-21 martijn va_end(ap);
330 ce062d50 2019-08-21 martijn
331 ce062d50 2019-08-21 martijn return (len);
332 ce062d50 2019-08-21 martijn }
333 ce062d50 2019-08-21 martijn
334 ce062d50 2019-08-21 martijn int
335 ce062d50 2019-08-21 martijn iobuf_vfqueue(struct iobuf *io, const char *fmt, va_list ap)
336 ce062d50 2019-08-21 martijn {
337 ce062d50 2019-08-21 martijn char *buf;
338 ce062d50 2019-08-21 martijn int len;
339 ce062d50 2019-08-21 martijn
340 ce062d50 2019-08-21 martijn len = vasprintf(&buf, fmt, ap);
341 ce062d50 2019-08-21 martijn
342 ce062d50 2019-08-21 martijn if (len == -1)
343 ce062d50 2019-08-21 martijn return (-1);
344 ce062d50 2019-08-21 martijn
345 ce062d50 2019-08-21 martijn len = iobuf_queue(io, buf, len);
346 ce062d50 2019-08-21 martijn free(buf);
347 ce062d50 2019-08-21 martijn
348 ce062d50 2019-08-21 martijn return (len);
349 ce062d50 2019-08-21 martijn }
350 ce062d50 2019-08-21 martijn
351 ce062d50 2019-08-21 martijn ssize_t
352 ce062d50 2019-08-21 martijn iobuf_write(struct iobuf *io, int fd)
353 ce062d50 2019-08-21 martijn {
354 ce062d50 2019-08-21 martijn struct iovec iov[IOV_MAX];
355 ce062d50 2019-08-21 martijn struct ioqbuf *q;
356 ce062d50 2019-08-21 martijn int i;
357 ce062d50 2019-08-21 martijn ssize_t n;
358 ce062d50 2019-08-21 martijn
359 ce062d50 2019-08-21 martijn i = 0;
360 ce062d50 2019-08-21 martijn for (q = io->outq; q ; q = q->next) {
361 ce062d50 2019-08-21 martijn if (i >= IOV_MAX)
362 ce062d50 2019-08-21 martijn break;
363 ce062d50 2019-08-21 martijn iov[i].iov_base = q->buf + q->rpos;
364 ce062d50 2019-08-21 martijn iov[i].iov_len = q->wpos - q->rpos;
365 ce062d50 2019-08-21 martijn i++;
366 ce062d50 2019-08-21 martijn }
367 ce062d50 2019-08-21 martijn
368 ce062d50 2019-08-21 martijn n = writev(fd, iov, i);
369 ce062d50 2019-08-21 martijn if (n == -1) {
370 ce062d50 2019-08-21 martijn if (errno == EAGAIN || errno == EINTR)
371 ce062d50 2019-08-21 martijn return (IOBUF_WANT_WRITE);
372 ce062d50 2019-08-21 martijn if (errno == EPIPE)
373 ce062d50 2019-08-21 martijn return (IOBUF_CLOSED);
374 ce062d50 2019-08-21 martijn return (IOBUF_ERROR);
375 ce062d50 2019-08-21 martijn }
376 ce062d50 2019-08-21 martijn
377 ce062d50 2019-08-21 martijn iobuf_drain(io, n);
378 ce062d50 2019-08-21 martijn
379 ce062d50 2019-08-21 martijn return (n);
380 ce062d50 2019-08-21 martijn }
381 ce062d50 2019-08-21 martijn
382 ce062d50 2019-08-21 martijn int
383 ce062d50 2019-08-21 martijn iobuf_flush(struct iobuf *io, int fd)
384 ce062d50 2019-08-21 martijn {
385 ce062d50 2019-08-21 martijn ssize_t s;
386 ce062d50 2019-08-21 martijn
387 ce062d50 2019-08-21 martijn while (io->queued)
388 ce062d50 2019-08-21 martijn if ((s = iobuf_write(io, fd)) < 0)
389 ce062d50 2019-08-21 martijn return (s);
390 ce062d50 2019-08-21 martijn
391 ce062d50 2019-08-21 martijn return (0);
392 ce062d50 2019-08-21 martijn }
393 ce062d50 2019-08-21 martijn
394 ce062d50 2019-08-21 martijn #ifdef IO_TLS
395 ce062d50 2019-08-21 martijn
396 ce062d50 2019-08-21 martijn int
397 ce062d50 2019-08-21 martijn iobuf_flush_tls(struct iobuf *io, void *tls)
398 ce062d50 2019-08-21 martijn {
399 ce062d50 2019-08-21 martijn ssize_t s;
400 ce062d50 2019-08-21 martijn
401 ce062d50 2019-08-21 martijn while (io->queued)
402 ce062d50 2019-08-21 martijn if ((s = iobuf_write_tls(io, tls)) < 0)
403 ce062d50 2019-08-21 martijn return (s);
404 ce062d50 2019-08-21 martijn
405 ce062d50 2019-08-21 martijn return (0);
406 ce062d50 2019-08-21 martijn }
407 ce062d50 2019-08-21 martijn
408 ce062d50 2019-08-21 martijn ssize_t
409 ce062d50 2019-08-21 martijn iobuf_write_tls(struct iobuf *io, void *tls)
410 ce062d50 2019-08-21 martijn {
411 ce062d50 2019-08-21 martijn struct ioqbuf *q;
412 ce062d50 2019-08-21 martijn int r;
413 ce062d50 2019-08-21 martijn ssize_t n;
414 ce062d50 2019-08-21 martijn
415 ce062d50 2019-08-21 martijn q = io->outq;
416 ce062d50 2019-08-21 martijn n = SSL_write(tls, q->buf + q->rpos, q->wpos - q->rpos);
417 ce062d50 2019-08-21 martijn if (n <= 0) {
418 ce062d50 2019-08-21 martijn switch ((r = SSL_get_error(tls, n))) {
419 ce062d50 2019-08-21 martijn case SSL_ERROR_WANT_READ:
420 ce062d50 2019-08-21 martijn return (IOBUF_WANT_READ);
421 ce062d50 2019-08-21 martijn case SSL_ERROR_WANT_WRITE:
422 ce062d50 2019-08-21 martijn return (IOBUF_WANT_WRITE);
423 ce062d50 2019-08-21 martijn case SSL_ERROR_ZERO_RETURN: /* connection closed */
424 ce062d50 2019-08-21 martijn return (IOBUF_CLOSED);
425 ce062d50 2019-08-21 martijn case SSL_ERROR_SYSCALL:
426 ce062d50 2019-08-21 martijn if (ERR_peek_last_error())
427 ce062d50 2019-08-21 martijn return (IOBUF_TLSERROR);
428 ce062d50 2019-08-21 martijn if (r == 0)
429 ce062d50 2019-08-21 martijn errno = EPIPE;
430 ce062d50 2019-08-21 martijn return (IOBUF_ERROR);
431 ce062d50 2019-08-21 martijn default:
432 ce062d50 2019-08-21 martijn return (IOBUF_TLSERROR);
433 ce062d50 2019-08-21 martijn }
434 ce062d50 2019-08-21 martijn }
435 ce062d50 2019-08-21 martijn iobuf_drain(io, n);
436 ce062d50 2019-08-21 martijn
437 ce062d50 2019-08-21 martijn return (n);
438 ce062d50 2019-08-21 martijn }
439 ce062d50 2019-08-21 martijn
440 ce062d50 2019-08-21 martijn ssize_t
441 ce062d50 2019-08-21 martijn iobuf_read_tls(struct iobuf *io, void *tls)
442 ce062d50 2019-08-21 martijn {
443 ce062d50 2019-08-21 martijn ssize_t n;
444 ce062d50 2019-08-21 martijn int r;
445 ce062d50 2019-08-21 martijn
446 ce062d50 2019-08-21 martijn n = SSL_read(tls, io->buf + io->wpos, iobuf_left(io));
447 ce062d50 2019-08-21 martijn if (n < 0) {
448 ce062d50 2019-08-21 martijn switch ((r = SSL_get_error(tls, n))) {
449 ce062d50 2019-08-21 martijn case SSL_ERROR_WANT_READ:
450 ce062d50 2019-08-21 martijn return (IOBUF_WANT_READ);
451 ce062d50 2019-08-21 martijn case SSL_ERROR_WANT_WRITE:
452 ce062d50 2019-08-21 martijn return (IOBUF_WANT_WRITE);
453 ce062d50 2019-08-21 martijn case SSL_ERROR_SYSCALL:
454 ce062d50 2019-08-21 martijn if (ERR_peek_last_error())
455 ce062d50 2019-08-21 martijn return (IOBUF_TLSERROR);
456 ce062d50 2019-08-21 martijn if (r == 0)
457 ce062d50 2019-08-21 martijn errno = EPIPE;
458 ce062d50 2019-08-21 martijn return (IOBUF_ERROR);
459 ce062d50 2019-08-21 martijn default:
460 ce062d50 2019-08-21 martijn return (IOBUF_TLSERROR);
461 ce062d50 2019-08-21 martijn }
462 ce062d50 2019-08-21 martijn } else if (n == 0)
463 ce062d50 2019-08-21 martijn return (IOBUF_CLOSED);
464 ce062d50 2019-08-21 martijn
465 ce062d50 2019-08-21 martijn io->wpos += n;
466 ce062d50 2019-08-21 martijn
467 ce062d50 2019-08-21 martijn return (n);
468 ce062d50 2019-08-21 martijn }
469 ce062d50 2019-08-21 martijn
470 ce062d50 2019-08-21 martijn #endif /* IO_TLS */