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.
28 #include "got_compat.h"
43 buf_init(struct buf
*buf
)
45 const size_t cap
= BIO_CHUNK
;
47 memset(buf
, 0, sizeof(*buf
));
48 if ((buf
->buf
= malloc(cap
)) == NULL
)
55 buf_grow(struct buf
*buf
)
60 newcap
= buf
->cap
+ BIO_CHUNK
;
61 t
= realloc(buf
->buf
, newcap
);
70 buf_has_line(struct buf
*buf
, const char *nl
)
72 return (memmem(buf
->buf
, buf
->len
, nl
, strlen(nl
)) != NULL
);
76 buf_getdelim(struct buf
*buf
, const char *nl
, size_t *len
)
84 if ((endl
= memmem(buf
->buf
, buf
->len
, nl
, nlen
)) == NULL
)
86 *len
= endl
+ nlen
- buf
->buf
;
92 buf_drain(struct buf
*buf
, size_t l
)
101 memmove(buf
->buf
, buf
->buf
+ l
, buf
->len
- l
);
106 buf_drain_line(struct buf
*buf
, const char *nl
)
112 if ((endln
= memmem(buf
->buf
, buf
->len
, nl
, nlen
)) == NULL
)
114 buf_drain(buf
, endln
+ nlen
- buf
->buf
);
118 buf_free(struct buf
*buf
)
121 memset(buf
, 0, sizeof(*buf
));
125 bufio_init(struct bufio
*bio
)
127 memset(bio
, 0, sizeof(*bio
));
130 if (buf_init(&bio
->wbuf
) == -1)
132 if (buf_init(&bio
->rbuf
) == -1) {
133 buf_free(&bio
->wbuf
);
140 bufio_free(struct bufio
*bio
)
150 buf_free(&bio
->rbuf
);
151 buf_free(&bio
->wbuf
);
155 bufio_close(struct bufio
*bio
)
157 if (bio
->ctx
== NULL
)
160 switch (tls_close(bio
->ctx
)) {
163 case TLS_WANT_POLLIN
:
165 bio
->wantev
= BUFIO_WANT_READ
;
167 case TLS_WANT_POLLOUT
:
169 bio
->wantev
= BUFIO_WANT_WRITE
;
177 bufio_reset(struct bufio
*bio
)
180 return (bufio_init(bio
));
184 bufio_set_fd(struct bufio
*bio
, int fd
)
190 bufio_starttls(struct bufio
*bio
, const char *host
, int insecure
,
191 const uint8_t *cert
, size_t certlen
, const uint8_t *key
, size_t keylen
)
193 struct tls_config
*conf
;
195 if ((conf
= tls_config_new()) == NULL
)
199 tls_config_insecure_noverifycert(conf
);
200 tls_config_insecure_noverifyname(conf
);
201 tls_config_insecure_noverifytime(conf
);
204 if (cert
&& tls_config_set_keypair_mem(conf
, cert
, certlen
,
205 key
, keylen
) == -1) {
206 tls_config_free(conf
);
210 if ((bio
->ctx
= tls_client()) == NULL
) {
211 tls_config_free(conf
);
215 if (tls_configure(bio
->ctx
, conf
) == -1) {
216 tls_config_free(conf
);
220 tls_config_free(conf
);
222 if (tls_connect_socket(bio
->ctx
, bio
->fd
, host
) == -1)
229 bufio_ev(struct bufio
*bio
)
234 return (bio
->wantev
);
236 ev
= BUFIO_WANT_READ
;
237 if (bio
->wbuf
.len
!= 0)
238 ev
|= BUFIO_WANT_WRITE
;
244 bufio_handshake(struct bufio
*bio
)
246 if (bio
->ctx
== NULL
) {
251 switch (tls_handshake(bio
->ctx
)) {
254 case TLS_WANT_POLLIN
:
256 bio
->wantev
= BUFIO_WANT_READ
;
258 case TLS_WANT_POLLOUT
:
260 bio
->wantev
= BUFIO_WANT_WRITE
;
268 bufio_read(struct bufio
*bio
)
270 struct buf
*rbuf
= &bio
->rbuf
;
273 assert(rbuf
->cap
>= rbuf
->len
);
274 if (rbuf
->cap
- rbuf
->len
< BIO_CHUNK
) {
275 if (buf_grow(rbuf
) == -1)
280 r
= tls_read(bio
->ctx
, rbuf
->buf
+ rbuf
->len
,
281 rbuf
->cap
- rbuf
->len
);
283 case TLS_WANT_POLLIN
:
285 bio
->wantev
= BUFIO_WANT_READ
;
287 case TLS_WANT_POLLOUT
:
289 bio
->wantev
= BUFIO_WANT_WRITE
;
302 r
= read(bio
->fd
, rbuf
->buf
+ rbuf
->len
, rbuf
->cap
- rbuf
->len
);
310 bufio_drain(struct bufio
*bio
, void *d
, size_t len
)
312 struct buf
*rbuf
= &bio
->rbuf
;
316 memcpy(d
, rbuf
->buf
, len
);
317 buf_drain(rbuf
, len
);
322 bufio_write(struct bufio
*bio
)
324 struct buf
*wbuf
= &bio
->wbuf
;
328 switch (w
= tls_write(bio
->ctx
, wbuf
->buf
, wbuf
->len
)) {
329 case TLS_WANT_POLLIN
:
331 bio
->wantev
= BUFIO_WANT_READ
;
333 case TLS_WANT_POLLOUT
:
335 bio
->wantev
= BUFIO_WANT_WRITE
;
346 w
= write(bio
->fd
, wbuf
->buf
, wbuf
->len
);
354 bufio_io_err(struct bufio
*bio
)
357 return tls_error(bio
->ctx
);
359 return strerror(errno
);
363 bufio_compose(struct bufio
*bio
, const void *d
, size_t len
)
365 struct buf
*wbuf
= &bio
->wbuf
;
367 while (wbuf
->cap
- wbuf
->len
< len
) {
368 if (buf_grow(wbuf
) == -1)
372 memcpy(wbuf
->buf
+ wbuf
->len
, d
, len
);
378 bufio_compose_str(struct bufio
*bio
, const char *str
)
380 return (bufio_compose(bio
, str
, strlen(str
)));
384 bufio_compose_fmt(struct bufio
*bio
, const char *fmt
, ...)
391 r
= vasprintf(&str
, fmt
, ap
);
396 r
= bufio_compose(bio
, str
, r
);
402 bufio_rewind_cursor(struct bufio
*bio
)
408 bufio_get_cb(void *d
)
410 struct bufio
*bio
= d
;
411 struct buf
*rbuf
= &bio
->rbuf
;
413 if (rbuf
->cur
>= rbuf
->len
)
415 return (rbuf
->buf
[rbuf
->cur
++]);
419 bufio_peek_cb(void *d
)
421 struct bufio
*bio
= d
;
422 struct buf
*rbuf
= &bio
->rbuf
;
424 if (rbuf
->cur
>= rbuf
->len
)
426 return (rbuf
->buf
[rbuf
->cur
]);