2 b8a11905 2023-08-31 op * This is free and unencumbered software released into the public domain.
4 b8a11905 2023-08-31 op * Anyone is free to copy, modify, publish, use, compile, sell, or
5 b8a11905 2023-08-31 op * distribute this software, either in source code form or as a compiled
6 b8a11905 2023-08-31 op * binary, for any purpose, commercial or non-commercial, and by any
9 b8a11905 2023-08-31 op * In jurisdictions that recognize copyright laws, the author or authors
10 b8a11905 2023-08-31 op * of this software dedicate any and all copyright interest in the
11 b8a11905 2023-08-31 op * software to the public domain. We make this dedication for the benefit
12 b8a11905 2023-08-31 op * of the public at large and to the detriment of our heirs and
13 b8a11905 2023-08-31 op * successors. We intend this dedication to be an overt act of
14 b8a11905 2023-08-31 op * relinquishment in perpetuity of all present and future rights to this
15 b8a11905 2023-08-31 op * software under copyright law.
17 b8a11905 2023-08-31 op * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 b8a11905 2023-08-31 op * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 b8a11905 2023-08-31 op * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 b8a11905 2023-08-31 op * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 b8a11905 2023-08-31 op * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 b8a11905 2023-08-31 op * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 b8a11905 2023-08-31 op * OTHER DEALINGS IN THE SOFTWARE.
26 cc89e101 2023-09-02 op #include "config.h"
28 b8a11905 2023-08-31 op #include <assert.h>
29 b8a11905 2023-08-31 op #include <errno.h>
30 b8a11905 2023-08-31 op #include <stdarg.h>
31 cc89e101 2023-09-02 op #include <stdint.h>
32 b8a11905 2023-08-31 op #include <stdio.h>
33 b8a11905 2023-08-31 op #include <stdlib.h>
34 b8a11905 2023-08-31 op #include <string.h>
35 b8a11905 2023-08-31 op #include <unistd.h>
37 6be81433 2024-04-14 op #ifndef BUFIO_WITHOUT_TLS
38 6be81433 2024-04-14 op #include <tls.h>
41 b8a11905 2023-08-31 op #include "bufio.h"
44 6be81433 2024-04-14 op buf_init(struct buf *buf)
46 b8a11905 2023-08-31 op const size_t cap = BIO_CHUNK;
48 b8a11905 2023-08-31 op memset(buf, 0, sizeof(*buf));
49 b8a11905 2023-08-31 op if ((buf->buf = malloc(cap)) == NULL)
51 b8a11905 2023-08-31 op buf->cap = cap;
56 6be81433 2024-04-14 op buf_grow(struct buf *buf)
58 b8a11905 2023-08-31 op size_t newcap;
61 b8a11905 2023-08-31 op newcap = buf->cap + BIO_CHUNK;
62 b8a11905 2023-08-31 op t = realloc(buf->buf, newcap);
63 b8a11905 2023-08-31 op if (t == NULL)
66 b8a11905 2023-08-31 op buf->cap = newcap;
71 6be81433 2024-04-14 op buf_write(struct buf *buf, const void *d, size_t len)
73 d20f7b51 2023-09-08 op while (buf->len + len > buf->cap) {
74 2216d3fb 2023-09-07 op if (buf_grow(buf) == -1)
77 2216d3fb 2023-09-07 op memcpy(buf->buf + buf->len, d, len);
78 2216d3fb 2023-09-07 op buf->len += len;
83 6be81433 2024-04-14 op buf_has_line(struct buf *buf, const char *nl)
85 b8a11905 2023-08-31 op return (memmem(buf->buf, buf->len, nl, strlen(nl)) != NULL);
89 6be81433 2024-04-14 op buf_getdelim(struct buf *buf, const char *nl, size_t *len)
91 6be81433 2024-04-14 op uint8_t *endl;
96 6be81433 2024-04-14 op nlen = strlen(nl);
97 6be81433 2024-04-14 op if ((endl = memmem(buf->buf, buf->len, nl, nlen)) == NULL)
98 6be81433 2024-04-14 op return (NULL);
99 6be81433 2024-04-14 op *len = endl + nlen - buf->buf;
100 6be81433 2024-04-14 op *endl = '\0';
101 6be81433 2024-04-14 op return (buf->buf);
105 6be81433 2024-04-14 op buf_drain(struct buf *buf, size_t l)
107 6be81433 2024-04-14 op buf->cur = 0;
109 b8a11905 2023-08-31 op if (l >= buf->len) {
110 b8a11905 2023-08-31 op buf->len = 0;
114 b8a11905 2023-08-31 op memmove(buf->buf, buf->buf + l, buf->len - l);
115 b8a11905 2023-08-31 op buf->len -= l;
119 6be81433 2024-04-14 op buf_drain_line(struct buf *buf, const char *nl)
121 b8a11905 2023-08-31 op uint8_t *endln;
124 b8a11905 2023-08-31 op nlen = strlen(nl);
125 b8a11905 2023-08-31 op if ((endln = memmem(buf->buf, buf->len, nl, nlen)) == NULL)
127 b8a11905 2023-08-31 op buf_drain(buf, endln + nlen - buf->buf);
131 6be81433 2024-04-14 op buf_free(struct buf *buf)
133 b8a11905 2023-08-31 op free(buf->buf);
134 b8a11905 2023-08-31 op memset(buf, 0, sizeof(*buf));
138 b8a11905 2023-08-31 op bufio_init(struct bufio *bio)
140 b8a11905 2023-08-31 op memset(bio, 0, sizeof(*bio));
141 b8a11905 2023-08-31 op bio->fd = -1;
143 b8a11905 2023-08-31 op if (buf_init(&bio->wbuf) == -1)
145 b8a11905 2023-08-31 op if (buf_init(&bio->rbuf) == -1) {
146 b8a11905 2023-08-31 op buf_free(&bio->wbuf);
153 d48ffc66 2023-08-31 op bufio_free(struct bufio *bio)
155 6be81433 2024-04-14 op #ifndef BUFIO_WITHOUT_TLS
156 6be81433 2024-04-14 op if (bio->ctx)
157 6be81433 2024-04-14 op tls_free(bio->ctx);
158 6be81433 2024-04-14 op bio->ctx = NULL;
161 b8a11905 2023-08-31 op if (bio->fd != -1)
162 b8a11905 2023-08-31 op close(bio->fd);
163 6be81433 2024-04-14 op bio->fd = -1;
165 b8a11905 2023-08-31 op buf_free(&bio->rbuf);
166 b8a11905 2023-08-31 op buf_free(&bio->wbuf);
170 6be81433 2024-04-14 op bufio_close(struct bufio *bio)
172 6be81433 2024-04-14 op #ifndef BUFIO_WITHOUT_TLS
173 6be81433 2024-04-14 op if (bio->ctx == NULL)
176 6be81433 2024-04-14 op switch (tls_close(bio->ctx)) {
179 6be81433 2024-04-14 op case TLS_WANT_POLLIN:
180 6be81433 2024-04-14 op errno = EAGAIN;
181 6be81433 2024-04-14 op bio->wantev = BUFIO_WANT_READ;
183 6be81433 2024-04-14 op case TLS_WANT_POLLOUT:
184 6be81433 2024-04-14 op errno = EAGAIN;
185 6be81433 2024-04-14 op bio->wantev = BUFIO_WANT_WRITE;
196 d48ffc66 2023-08-31 op bufio_reset(struct bufio *bio)
198 d48ffc66 2023-08-31 op bufio_free(bio);
199 b8a11905 2023-08-31 op return (bufio_init(bio));
203 b8a11905 2023-08-31 op bufio_set_fd(struct bufio *bio, int fd)
205 b8a11905 2023-08-31 op bio->fd = fd;
209 d48ffc66 2023-08-31 op bufio_set_chunked(struct bufio *bio, int chunked)
211 d48ffc66 2023-08-31 op bio->chunked = chunked;
215 6be81433 2024-04-14 op bufio_starttls(struct bufio *bio, const char *host, int insecure,
216 6be81433 2024-04-14 op const uint8_t *cert, size_t certlen, const uint8_t *key, size_t keylen)
218 6be81433 2024-04-14 op #ifndef BUFIO_WITHOUT_TLS
219 6be81433 2024-04-14 op struct tls_config *conf;
221 6be81433 2024-04-14 op if ((conf = tls_config_new()) == NULL)
224 6be81433 2024-04-14 op if (insecure) {
225 6be81433 2024-04-14 op tls_config_insecure_noverifycert(conf);
226 6be81433 2024-04-14 op tls_config_insecure_noverifyname(conf);
227 6be81433 2024-04-14 op tls_config_insecure_noverifytime(conf);
230 6be81433 2024-04-14 op if (cert && tls_config_set_keypair_mem(conf, cert, certlen,
231 6be81433 2024-04-14 op key, keylen) == -1) {
232 6be81433 2024-04-14 op tls_config_free(conf);
236 6be81433 2024-04-14 op if ((bio->ctx = tls_client()) == NULL) {
237 6be81433 2024-04-14 op tls_config_free(conf);
241 6be81433 2024-04-14 op if (tls_configure(bio->ctx, conf) == -1) {
242 6be81433 2024-04-14 op tls_config_free(conf);
246 6be81433 2024-04-14 op tls_config_free(conf);
248 6be81433 2024-04-14 op if (tls_connect_socket(bio->ctx, bio->fd, host) == -1)
253 6be81433 2024-04-14 op errno = EINVAL;
259 6be81433 2024-04-14 op bufio_ev(struct bufio *bio)
263 6be81433 2024-04-14 op if (bio->wantev)
264 6be81433 2024-04-14 op return (bio->wantev);
266 6be81433 2024-04-14 op ev = BUFIO_WANT_READ;
267 6be81433 2024-04-14 op if (bio->wbuf.len != 0)
268 6be81433 2024-04-14 op ev |= BUFIO_WANT_WRITE;
274 6be81433 2024-04-14 op bufio_handshake(struct bufio *bio)
276 6be81433 2024-04-14 op #ifndef BUFIO_WITHOUT_TLS
277 6be81433 2024-04-14 op if (bio->ctx == NULL) {
278 6be81433 2024-04-14 op errno = EINVAL;
282 6be81433 2024-04-14 op switch (tls_handshake(bio->ctx)) {
285 6be81433 2024-04-14 op case TLS_WANT_POLLIN:
286 6be81433 2024-04-14 op errno = EAGAIN;
287 6be81433 2024-04-14 op bio->wantev = BUFIO_WANT_READ;
289 6be81433 2024-04-14 op case TLS_WANT_POLLOUT:
290 6be81433 2024-04-14 op errno = EAGAIN;
291 6be81433 2024-04-14 op bio->wantev = BUFIO_WANT_WRITE;
297 6be81433 2024-04-14 op errno = EINVAL;
303 b8a11905 2023-08-31 op bufio_read(struct bufio *bio)
305 6be81433 2024-04-14 op struct buf *rbuf = &bio->rbuf;
308 b8a11905 2023-08-31 op assert(rbuf->cap >= rbuf->len);
309 b8a11905 2023-08-31 op if (rbuf->cap - rbuf->len < BIO_CHUNK) {
310 b8a11905 2023-08-31 op if (buf_grow(rbuf) == -1)
314 6be81433 2024-04-14 op #ifndef BUFIO_WITHOUT_TLS
315 6be81433 2024-04-14 op if (bio->ctx) {
316 6be81433 2024-04-14 op r = tls_read(bio->ctx, rbuf->buf + rbuf->len,
317 6be81433 2024-04-14 op rbuf->cap - rbuf->len);
319 6be81433 2024-04-14 op case TLS_WANT_POLLIN:
320 6be81433 2024-04-14 op errno = EAGAIN;
321 6be81433 2024-04-14 op bio->wantev = BUFIO_WANT_READ;
323 6be81433 2024-04-14 op case TLS_WANT_POLLOUT:
324 6be81433 2024-04-14 op errno = EAGAIN;
325 6be81433 2024-04-14 op bio->wantev = BUFIO_WANT_WRITE;
330 6be81433 2024-04-14 op bio->wantev = 0;
331 6be81433 2024-04-14 op rbuf->len += r;
337 b8a11905 2023-08-31 op r = read(bio->fd, rbuf->buf + rbuf->len, rbuf->cap - rbuf->len);
340 b8a11905 2023-08-31 op rbuf->len += r;
345 d48ffc66 2023-08-31 op bufio_drain(struct bufio *bio, void *d, size_t len)
347 6be81433 2024-04-14 op struct buf *rbuf = &bio->rbuf;
349 d48ffc66 2023-08-31 op if (len > rbuf->len)
350 d48ffc66 2023-08-31 op len = rbuf->len;
351 d48ffc66 2023-08-31 op memcpy(d, rbuf->buf, len);
352 d48ffc66 2023-08-31 op buf_drain(rbuf, len);
353 d48ffc66 2023-08-31 op return (len);
357 b8a11905 2023-08-31 op bufio_write(struct bufio *bio)
359 6be81433 2024-04-14 op struct buf *wbuf = &bio->wbuf;
362 6be81433 2024-04-14 op #ifndef BUFIO_WITHOUT_TLS
363 6be81433 2024-04-14 op if (bio->ctx) {
364 6be81433 2024-04-14 op switch (w = tls_write(bio->ctx, wbuf->buf, wbuf->len)) {
365 6be81433 2024-04-14 op case TLS_WANT_POLLIN:
366 6be81433 2024-04-14 op errno = EAGAIN;
367 6be81433 2024-04-14 op bio->wantev = BUFIO_WANT_READ;
369 6be81433 2024-04-14 op case TLS_WANT_POLLOUT:
370 6be81433 2024-04-14 op errno = EAGAIN;
371 6be81433 2024-04-14 op bio->wantev = BUFIO_WANT_WRITE;
376 6be81433 2024-04-14 op bio->wantev = 0;
377 6be81433 2024-04-14 op buf_drain(wbuf, w);
383 b8a11905 2023-08-31 op w = write(bio->fd, wbuf->buf, wbuf->len);
386 b8a11905 2023-08-31 op buf_drain(wbuf, w);
391 d48ffc66 2023-08-31 op bufio_append(struct bufio *bio, const void *d, size_t len)
393 6be81433 2024-04-14 op struct buf *wbuf = &bio->wbuf;
395 d48ffc66 2023-08-31 op if (len == 0)
398 b8a11905 2023-08-31 op while (wbuf->cap - wbuf->len < len) {
399 b8a11905 2023-08-31 op if (buf_grow(wbuf) == -1)
403 b8a11905 2023-08-31 op memcpy(wbuf->buf + wbuf->len, d, len);
404 b8a11905 2023-08-31 op wbuf->len += len;
409 d48ffc66 2023-08-31 op bufio_compose(struct bufio *bio, const void *d, size_t len)
414 d48ffc66 2023-08-31 op if (bio->chunked) {
415 d48ffc66 2023-08-31 op r = snprintf(n, sizeof(n), "%zx\r\n", len);
416 d48ffc66 2023-08-31 op if (r < 0 || (size_t)r >= sizeof(n))
418 d48ffc66 2023-08-31 op if (bufio_append(bio, n, r) == -1)
422 d48ffc66 2023-08-31 op if (bufio_append(bio, d, len) == -1)
425 d48ffc66 2023-08-31 op if (bio->chunked)
426 d48ffc66 2023-08-31 op return bufio_append(bio, "\r\n", 2);
432 b8a11905 2023-08-31 op bufio_compose_str(struct bufio *bio, const char *str)
434 b8a11905 2023-08-31 op return (bufio_compose(bio, str, strlen(str)));
438 b8a11905 2023-08-31 op bufio_compose_fmt(struct bufio *bio, const char *fmt, ...)
444 b8a11905 2023-08-31 op va_start(ap, fmt);
445 b8a11905 2023-08-31 op r = vasprintf(&str, fmt, ap);
450 b8a11905 2023-08-31 op r = bufio_compose(bio, str, r);
456 6be81433 2024-04-14 op bufio_rewind_cursor(struct bufio *bio)
458 6be81433 2024-04-14 op bio->rbuf.cur = 0;
462 6be81433 2024-04-14 op bufio_get_cb(void *d)
464 6be81433 2024-04-14 op struct bufio *bio = d;
465 6be81433 2024-04-14 op struct buf *rbuf = &bio->rbuf;
467 6be81433 2024-04-14 op if (rbuf->cur >= rbuf->len)
468 6be81433 2024-04-14 op return (EOF);
469 6be81433 2024-04-14 op return (rbuf->buf[rbuf->cur++]);
473 6be81433 2024-04-14 op bufio_peek_cb(void *d)
475 6be81433 2024-04-14 op struct bufio *bio = d;
476 6be81433 2024-04-14 op struct buf *rbuf = &bio->rbuf;
478 6be81433 2024-04-14 op if (rbuf->cur >= rbuf->len)
479 6be81433 2024-04-14 op return (EOF);
480 6be81433 2024-04-14 op return (rbuf->buf[rbuf->cur]);