2 * bufio.c was written by Omar Polo <op@omarpolo.com>
4 * This is free and unencumbered software released into the public domain.
6 * Anyone is free to copy, modify, publish, use, compile, sell, or
7 * distribute this software, either in source code form or as a compiled
8 * binary, for any purpose, commercial or non-commercial, and by any
11 * In jurisdictions that recognize copyright laws, the author or authors
12 * of this software dedicate any and all copyright interest in the
13 * software to the public domain. We make this dedication for the benefit
14 * of the public at large and to the detriment of our heirs and
15 * successors. We intend this dedication to be an overt act of
16 * relinquishment in perpetuity of all present and future rights to this
17 * software under copyright law.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
41 buf_init(struct buf *buf)
43 const size_t cap = BIO_CHUNK;
45 memset(buf, 0, sizeof(*buf));
46 if ((buf->buf = malloc(cap)) == NULL)
53 buf_grow(struct buf *buf)
58 newcap = buf->cap + BIO_CHUNK;
59 t = realloc(buf->buf, newcap);
68 buf_has_line(struct buf *buf, const char *nl)
70 return (memmem(buf->buf, buf->len, nl, strlen(nl)) != NULL);
74 buf_getdelim(struct buf *buf, const char *nl, size_t *len)
82 if ((endl = memmem(buf->buf, buf->len, nl, nlen)) == NULL)
84 *len = endl + nlen - buf->buf;
90 buf_drain(struct buf *buf, size_t l)
99 memmove(buf->buf, buf->buf + l, buf->len - l);
104 buf_drain_line(struct buf *buf, const char *nl)
110 if ((endln = memmem(buf->buf, buf->len, nl, nlen)) == NULL)
112 buf_drain(buf, endln + nlen - buf->buf);
116 buf_free(struct buf *buf)
119 memset(buf, 0, sizeof(*buf));
123 bufio_init(struct bufio *bio)
125 memset(bio, 0, sizeof(*bio));
128 if (buf_init(&bio->wbuf) == -1)
130 if (buf_init(&bio->rbuf) == -1) {
131 buf_free(&bio->wbuf);
138 bufio_free(struct bufio *bio)
148 buf_free(&bio->rbuf);
149 buf_free(&bio->wbuf);
153 bufio_close(struct bufio *bio)
155 if (bio->ctx == NULL)
158 switch (tls_close(bio->ctx)) {
161 case TLS_WANT_POLLIN:
163 bio->wantev = BUFIO_WANT_READ;
165 case TLS_WANT_POLLOUT:
167 bio->wantev = BUFIO_WANT_WRITE;
175 bufio_reset(struct bufio *bio)
178 return (bufio_init(bio));
182 bufio_set_fd(struct bufio *bio, int fd)
188 bufio_starttls(struct bufio *bio, const char *host, int insecure,
189 const uint8_t *cert, size_t certlen, const uint8_t *key, size_t keylen)
191 struct tls_config *conf;
193 if ((conf = tls_config_new()) == NULL)
197 tls_config_insecure_noverifycert(conf);
198 tls_config_insecure_noverifyname(conf);
199 tls_config_insecure_noverifytime(conf);
202 if (cert && tls_config_set_keypair_mem(conf, cert, certlen,
203 key, keylen) == -1) {
204 tls_config_free(conf);
208 if ((bio->ctx = tls_client()) == NULL) {
209 tls_config_free(conf);
213 if (tls_configure(bio->ctx, conf) == -1) {
214 tls_config_free(conf);
218 tls_config_free(conf);
220 if (tls_connect_socket(bio->ctx, bio->fd, host) == -1)
227 bufio_ev(struct bufio *bio)
232 return (bio->wantev);
234 ev = BUFIO_WANT_READ;
235 if (bio->wbuf.len != 0)
236 ev |= BUFIO_WANT_WRITE;
242 bufio_handshake(struct bufio *bio)
244 if (bio->ctx == NULL) {
249 switch (tls_handshake(bio->ctx)) {
252 case TLS_WANT_POLLIN:
254 bio->wantev = BUFIO_WANT_READ;
256 case TLS_WANT_POLLOUT:
258 bio->wantev = BUFIO_WANT_WRITE;
266 bufio_read(struct bufio *bio)
268 struct buf *rbuf = &bio->rbuf;
271 assert(rbuf->cap >= rbuf->len);
272 if (rbuf->cap - rbuf->len < BIO_CHUNK) {
273 if (buf_grow(rbuf) == -1)
278 r = tls_read(bio->ctx, rbuf->buf + rbuf->len,
279 rbuf->cap - rbuf->len);
281 case TLS_WANT_POLLIN:
283 bio->wantev = BUFIO_WANT_READ;
285 case TLS_WANT_POLLOUT:
287 bio->wantev = BUFIO_WANT_WRITE;
300 r = read(bio->fd, rbuf->buf + rbuf->len, rbuf->cap - rbuf->len);
308 bufio_drain(struct bufio *bio, void *d, size_t len)
310 struct buf *rbuf = &bio->rbuf;
314 memcpy(d, rbuf->buf, len);
315 buf_drain(rbuf, len);
320 bufio_write(struct bufio *bio)
322 struct buf *wbuf = &bio->wbuf;
326 switch (w = tls_write(bio->ctx, wbuf->buf, wbuf->len)) {
327 case TLS_WANT_POLLIN:
329 bio->wantev = BUFIO_WANT_READ;
331 case TLS_WANT_POLLOUT:
333 bio->wantev = BUFIO_WANT_WRITE;
344 w = write(bio->fd, wbuf->buf, wbuf->len);
352 bufio_io_err(struct bufio *bio)
355 return tls_error(bio->ctx);
357 return strerror(errno);
361 bufio_compose(struct bufio *bio, const void *d, size_t len)
363 struct buf *wbuf = &bio->wbuf;
365 while (wbuf->cap - wbuf->len < len) {
366 if (buf_grow(wbuf) == -1)
370 memcpy(wbuf->buf + wbuf->len, d, len);
376 bufio_compose_str(struct bufio *bio, const char *str)
378 return (bufio_compose(bio, str, strlen(str)));
382 bufio_compose_fmt(struct bufio *bio, const char *fmt, ...)
389 r = vasprintf(&str, fmt, ap);
394 r = bufio_compose(bio, str, r);
400 bufio_rewind_cursor(struct bufio *bio)
406 bufio_get_cb(void *d)
408 struct bufio *bio = d;
409 struct buf *rbuf = &bio->rbuf;
411 if (rbuf->cur >= rbuf->len)
413 return (rbuf->buf[rbuf->cur++]);
417 bufio_peek_cb(void *d)
419 struct bufio *bio = d;
420 struct buf *rbuf = &bio->rbuf;
422 if (rbuf->cur >= rbuf->len)
424 return (rbuf->buf[rbuf->cur]);