2 * This is free and unencumbered software released into the public domain.
4 * Anyone is free to copy, modify, publish, use, compile, sell, or
5 * distribute this software, either in source code form or as a compiled
6 * binary, for any purpose, commercial or non-commercial, and by any
9 * In jurisdictions that recognize copyright laws, the author or authors
10 * of this software dedicate any and all copyright interest in the
11 * software to the public domain. We make this dedication for the benefit
12 * of the public at large and to the detriment of our heirs and
13 * successors. We intend this dedication to be an overt act of
14 * relinquishment in perpetuity of all present and future rights to this
15 * software under copyright law.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
37 #ifndef BUFIO_WITHOUT_TLS
44 buf_init(struct buf *buf)
46 const size_t cap = BIO_CHUNK;
48 memset(buf, 0, sizeof(*buf));
49 if ((buf->buf = malloc(cap)) == NULL)
56 buf_grow(struct buf *buf)
61 newcap = buf->cap + BIO_CHUNK;
62 t = realloc(buf->buf, newcap);
71 buf_write(struct buf *buf, const void *d, size_t len)
73 while (buf->len + len > buf->cap) {
74 if (buf_grow(buf) == -1)
77 memcpy(buf->buf + buf->len, d, len);
83 buf_has_line(struct buf *buf, const char *nl)
85 return (memmem(buf->buf, buf->len, nl, strlen(nl)) != NULL);
89 buf_getdelim(struct buf *buf, const char *nl, size_t *len)
97 if ((endl = memmem(buf->buf, buf->len, nl, nlen)) == NULL)
99 *len = endl + nlen - buf->buf;
105 buf_drain(struct buf *buf, size_t l)
114 memmove(buf->buf, buf->buf + l, buf->len - l);
119 buf_drain_line(struct buf *buf, const char *nl)
125 if ((endln = memmem(buf->buf, buf->len, nl, nlen)) == NULL)
127 buf_drain(buf, endln + nlen - buf->buf);
131 buf_free(struct buf *buf)
134 memset(buf, 0, sizeof(*buf));
138 bufio_init(struct bufio *bio)
140 memset(bio, 0, sizeof(*bio));
143 if (buf_init(&bio->wbuf) == -1)
145 if (buf_init(&bio->rbuf) == -1) {
146 buf_free(&bio->wbuf);
153 bufio_free(struct bufio *bio)
155 #ifndef BUFIO_WITHOUT_TLS
165 buf_free(&bio->rbuf);
166 buf_free(&bio->wbuf);
170 bufio_close(struct bufio *bio)
172 #ifndef BUFIO_WITHOUT_TLS
173 if (bio->ctx == NULL)
176 switch (tls_close(bio->ctx)) {
179 case TLS_WANT_POLLIN:
181 bio->wantev = BUFIO_WANT_READ;
183 case TLS_WANT_POLLOUT:
185 bio->wantev = BUFIO_WANT_WRITE;
196 bufio_reset(struct bufio *bio)
199 return (bufio_init(bio));
203 bufio_set_fd(struct bufio *bio, int fd)
209 bufio_set_chunked(struct bufio *bio, int chunked)
211 bio->chunked = chunked;
215 bufio_starttls(struct bufio *bio, const char *host, int insecure,
216 const uint8_t *cert, size_t certlen, const uint8_t *key, size_t keylen)
218 #ifndef BUFIO_WITHOUT_TLS
219 struct tls_config *conf;
221 if ((conf = tls_config_new()) == NULL)
225 tls_config_insecure_noverifycert(conf);
226 tls_config_insecure_noverifyname(conf);
227 tls_config_insecure_noverifytime(conf);
230 if (cert && tls_config_set_keypair_mem(conf, cert, certlen,
231 key, keylen) == -1) {
232 tls_config_free(conf);
236 if ((bio->ctx = tls_client()) == NULL) {
237 tls_config_free(conf);
241 if (tls_configure(bio->ctx, conf) == -1) {
242 tls_config_free(conf);
246 tls_config_free(conf);
248 if (tls_connect_socket(bio->ctx, bio->fd, host) == -1)
259 bufio_ev(struct bufio *bio)
264 return (bio->wantev);
266 ev = BUFIO_WANT_READ;
267 if (bio->wbuf.len != 0)
268 ev |= BUFIO_WANT_WRITE;
274 bufio_handshake(struct bufio *bio)
276 #ifndef BUFIO_WITHOUT_TLS
277 if (bio->ctx == NULL) {
282 switch (tls_handshake(bio->ctx)) {
285 case TLS_WANT_POLLIN:
287 bio->wantev = BUFIO_WANT_READ;
289 case TLS_WANT_POLLOUT:
291 bio->wantev = BUFIO_WANT_WRITE;
303 bufio_read(struct bufio *bio)
305 struct buf *rbuf = &bio->rbuf;
308 assert(rbuf->cap >= rbuf->len);
309 if (rbuf->cap - rbuf->len < BIO_CHUNK) {
310 if (buf_grow(rbuf) == -1)
314 #ifndef BUFIO_WITHOUT_TLS
316 r = tls_read(bio->ctx, rbuf->buf + rbuf->len,
317 rbuf->cap - rbuf->len);
319 case TLS_WANT_POLLIN:
321 bio->wantev = BUFIO_WANT_READ;
323 case TLS_WANT_POLLOUT:
325 bio->wantev = BUFIO_WANT_WRITE;
337 r = read(bio->fd, rbuf->buf + rbuf->len, rbuf->cap - rbuf->len);
345 bufio_drain(struct bufio *bio, void *d, size_t len)
347 struct buf *rbuf = &bio->rbuf;
351 memcpy(d, rbuf->buf, len);
352 buf_drain(rbuf, len);
357 bufio_write(struct bufio *bio)
359 struct buf *wbuf = &bio->wbuf;
362 #ifndef BUFIO_WITHOUT_TLS
364 switch (w = tls_write(bio->ctx, wbuf->buf, wbuf->len)) {
365 case TLS_WANT_POLLIN:
367 bio->wantev = BUFIO_WANT_READ;
369 case TLS_WANT_POLLOUT:
371 bio->wantev = BUFIO_WANT_WRITE;
383 w = write(bio->fd, wbuf->buf, wbuf->len);
391 bufio_append(struct bufio *bio, const void *d, size_t len)
393 struct buf *wbuf = &bio->wbuf;
398 while (wbuf->cap - wbuf->len < len) {
399 if (buf_grow(wbuf) == -1)
403 memcpy(wbuf->buf + wbuf->len, d, len);
409 bufio_compose(struct bufio *bio, const void *d, size_t len)
415 r = snprintf(n, sizeof(n), "%zx\r\n", len);
416 if (r < 0 || (size_t)r >= sizeof(n))
418 if (bufio_append(bio, n, r) == -1)
422 if (bufio_append(bio, d, len) == -1)
426 return bufio_append(bio, "\r\n", 2);
432 bufio_compose_str(struct bufio *bio, const char *str)
434 return (bufio_compose(bio, str, strlen(str)));
438 bufio_compose_fmt(struct bufio *bio, const char *fmt, ...)
445 r = vasprintf(&str, fmt, ap);
450 r = bufio_compose(bio, str, r);
456 bufio_rewind_cursor(struct bufio *bio)
462 bufio_get_cb(void *d)
464 struct bufio *bio = d;
465 struct buf *rbuf = &bio->rbuf;
467 if (rbuf->cur >= rbuf->len)
469 return (rbuf->buf[rbuf->cur++]);
473 bufio_peek_cb(void *d)
475 struct bufio *bio = d;
476 struct buf *rbuf = &bio->rbuf;
478 if (rbuf->cur >= rbuf->len)
480 return (rbuf->buf[rbuf->cur]);