commit - 3a60c27797deb05f9272733f00d59ea77ee2fb70
commit + b8a11905ab2402519db36742b5eb16646ad0347b
blob - /dev/null
blob + dd4aed5ca5e4940451abf38fb462bc8f67886df8 (mode 644)
--- /dev/null
+++ web/bufio.c
+/*
+ * This is free and unencumbered software released into the public domain.
+ *
+ * Anyone is free to copy, modify, publish, use, compile, sell, or
+ * distribute this software, either in source code form or as a compiled
+ * binary, for any purpose, commercial or non-commercial, and by any
+ * means.
+ *
+ * In jurisdictions that recognize copyright laws, the author or authors
+ * of this software dedicate any and all copyright interest in the
+ * software to the public domain. We make this dedication for the benefit
+ * of the public at large and to the detriment of our heirs and
+ * successors. We intend this dedication to be an overt act of
+ * relinquishment in perpetuity of all present and future rights to this
+ * software under copyright law.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <poll.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tls.h>
+#include <unistd.h>
+
+#include "bufio.h"
+
+int
+buf_init(struct buffer *buf)
+{
+ const size_t cap = BIO_CHUNK;
+
+ memset(buf, 0, sizeof(*buf));
+ if ((buf->buf = malloc(cap)) == NULL)
+ return (-1);
+ buf->cap = cap;
+ return (0);
+}
+
+static int
+buf_grow(struct buffer *buf)
+{
+ size_t newcap;
+ void *t;
+
+ newcap = buf->cap + BIO_CHUNK;
+ t = realloc(buf->buf, newcap);
+ if (t == NULL)
+ return (-1);
+ buf->buf = t;
+ buf->cap = newcap;
+ return (0);
+}
+
+int
+buf_has_line(struct buffer *buf, const char *nl)
+{
+ return (memmem(buf->buf, buf->len, nl, strlen(nl)) != NULL);
+}
+
+void
+buf_drain(struct buffer *buf, size_t l)
+{
+ buf->cur = 0;
+
+ if (l >= buf->len) {
+ buf->len = 0;
+ return;
+ }
+
+ memmove(buf->buf, buf->buf + l, buf->len - l);
+ buf->len -= l;
+}
+
+void
+buf_drain_line(struct buffer *buf, const char *nl)
+{
+ uint8_t *endln;
+ size_t nlen;
+
+ nlen = strlen(nl);
+ if ((endln = memmem(buf->buf, buf->len, nl, nlen)) == NULL)
+ return;
+ buf_drain(buf, endln + nlen - buf->buf);
+}
+
+void
+buf_free(struct buffer *buf)
+{
+ free(buf->buf);
+ memset(buf, 0, sizeof(*buf));
+}
+
+int
+bufio_init(struct bufio *bio)
+{
+ memset(bio, 0, sizeof(*bio));
+ bio->fd = -1;
+
+ if (buf_init(&bio->wbuf) == -1)
+ return (-1);
+ if (buf_init(&bio->rbuf) == -1) {
+ buf_free(&bio->wbuf);
+ return (-1);
+ }
+ return (0);
+}
+
+int
+bufio_reset(struct bufio *bio)
+{
+ if (bio->ctx)
+ tls_close(bio->ctx);
+ if (bio->fd != -1)
+ close(bio->fd);
+
+ buf_free(&bio->rbuf);
+ buf_free(&bio->wbuf);
+ return (bufio_init(bio));
+}
+
+void
+bufio_set_fd(struct bufio *bio, int fd)
+{
+ bio->fd = fd;
+}
+
+int
+bufio_starttls(struct bufio *bio, const char *host, int insecure)
+{
+ struct tls_config *conf;
+
+ if ((conf = tls_config_new()) == NULL)
+ return (-1);
+
+ if (insecure) {
+ tls_config_insecure_noverifycert(conf);
+ tls_config_insecure_noverifyname(conf);
+ tls_config_insecure_noverifytime(conf);
+ }
+
+ if ((bio->ctx = tls_client()) == NULL) {
+ tls_config_free(conf);
+ return (-1);
+ }
+
+ if (tls_configure(bio->ctx, conf) == -1) {
+ tls_config_free(conf);
+ return (-1);
+ }
+
+ tls_config_free(conf);
+
+ if (tls_connect_socket(bio->ctx, bio->fd, host) == -1)
+ return (-1);
+
+ return (0);
+}
+
+short
+bufio_pollev(struct bufio *bio)
+{
+ short ev;
+
+ if (bio->pflags)
+ return (bio->pflags);
+
+ ev = POLLIN;
+ if (bio->wbuf.len != 0)
+ ev |= POLLOUT;
+
+ return (ev);
+}
+
+ssize_t
+bufio_read(struct bufio *bio)
+{
+ struct buffer *rbuf = &bio->rbuf;
+ ssize_t r;
+
+ assert(rbuf->cap >= rbuf->len);
+ if (rbuf->cap - rbuf->len < BIO_CHUNK) {
+ if (buf_grow(rbuf) == -1)
+ return (-1);
+ }
+
+ if (bio->ctx) {
+ r = tls_read(bio->ctx, rbuf->buf + rbuf->len,
+ rbuf->cap - rbuf->cap);
+ switch (r) {
+ case TLS_WANT_POLLIN:
+ case TLS_WANT_POLLOUT:
+ bio->pflags = POLLIN | POLLOUT;
+ errno = EAGAIN;
+ return (-1);
+ case -1:
+ return (-1);
+ default:
+ bio->pflags = 0;
+ rbuf->len += r;
+ return (r);
+ }
+ }
+
+ r = read(bio->fd, rbuf->buf + rbuf->len, rbuf->cap - rbuf->len);
+ if (r == -1)
+ return (-1);
+ rbuf->len += r;
+ return (r);
+}
+
+ssize_t
+bufio_write(struct bufio *bio)
+{
+ struct buffer *wbuf = &bio->wbuf;
+ ssize_t w;
+
+ if (bio->ctx) {
+ switch (w = tls_write(bio->ctx, wbuf->buf, wbuf->len)) {
+ case TLS_WANT_POLLIN:
+ case TLS_WANT_POLLOUT:
+ bio->pflags = POLLIN | POLLOUT;
+ errno = EAGAIN;
+ return (-1);
+ case -1:
+ return (-1);
+ default:
+ bio->pflags = 0;
+ buf_drain(wbuf, w);
+ return (w);
+ }
+ }
+
+ w = write(bio->fd, wbuf->buf, wbuf->len);
+ if (w == -1)
+ return (-1);
+ buf_drain(wbuf, w);
+ return (w);
+}
+
+int
+bufio_compose(struct bufio *bio, const void *d, size_t len)
+{
+ struct buffer *wbuf = &bio->wbuf;
+
+ while (wbuf->cap - wbuf->len < len) {
+ if (buf_grow(wbuf) == -1)
+ return (-1);
+ }
+
+ memcpy(wbuf->buf + wbuf->len, d, len);
+ wbuf->len += len;
+ return (0);
+}
+
+int
+bufio_compose_str(struct bufio *bio, const char *str)
+{
+ return (bufio_compose(bio, str, strlen(str)));
+}
+
+int
+bufio_compose_fmt(struct bufio *bio, const char *fmt, ...)
+{
+ va_list ap;
+ char *str;
+ int r;
+
+ va_start(ap, fmt);
+ r = vasprintf(&str, fmt, ap);
+ va_end(ap);
+
+ if (r == -1)
+ return (-1);
+ r = bufio_compose(bio, str, r);
+ free(str);
+ return (r);
+}
+
+void
+bufio_rewind_cursor(struct bufio *bio)
+{
+ bio->rbuf.cur = 0;
+}
+
+int
+bufio_get_cb(void *d)
+{
+ struct bufio *bio = d;
+ struct buffer *rbuf = &bio->rbuf;
+
+ if (rbuf->cur >= rbuf->len)
+ return (EOF);
+ return (rbuf->buf[rbuf->cur++]);
+}
+
+int
+bufio_peek_cb(void *d)
+{
+ struct bufio *bio = d;
+ struct buffer *rbuf = &bio->rbuf;
+
+ if (rbuf->cur >= rbuf->len)
+ return (EOF);
+ return (rbuf->buf[rbuf->cur]);
+}
blob - /dev/null
blob + 372ba5655fc53797a09fcac4603f8391fce721a2 (mode 644)
--- /dev/null
+++ web/bufio.h
+/*
+ * This is free and unencumbered software released into the public domain.
+ *
+ * Anyone is free to copy, modify, publish, use, compile, sell, or
+ * distribute this software, either in source code form or as a compiled
+ * binary, for any purpose, commercial or non-commercial, and by any
+ * means.
+ *
+ * In jurisdictions that recognize copyright laws, the author or authors
+ * of this software dedicate any and all copyright interest in the
+ * software to the public domain. We make this dedication for the benefit
+ * of the public at large and to the detriment of our heirs and
+ * successors. We intend this dedication to be an overt act of
+ * relinquishment in perpetuity of all present and future rights to this
+ * software under copyright law.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#define BIO_CHUNK 128
+struct buffer {
+ uint8_t *buf;
+ size_t len;
+ size_t cap;
+ size_t cur;
+};
+
+struct bufio {
+ int fd;
+ struct tls *ctx;
+ int pflags; /* poll flags */
+ struct buffer wbuf;
+ struct buffer rbuf;
+};
+
+int buf_init(struct buffer *);
+int buf_has_line(struct buffer *, const char *);
+void buf_drain(struct buffer *, size_t);
+void buf_drain_line(struct buffer *, const char *);
+void buf_free(struct buffer *);
+
+int bufio_init(struct bufio *);
+int bufio_reset(struct bufio *);
+int bufio_reset(struct bufio *);
+void bufio_set_fd(struct bufio *, int);
+int bufio_starttls(struct bufio *, const char *, int);
+short bufio_pollev(struct bufio *);
+ssize_t bufio_read(struct bufio *);
+ssize_t bufio_write(struct bufio *);
+int bufio_compose(struct bufio *, const void *, size_t);
+int bufio_compose_str(struct bufio *, const char *);
+int bufio_compose_fmt(struct bufio *, const char *, ...)
+ __attribute__((__format__ (printf, 2, 3)));
+void bufio_rewind_cursor(struct bufio *);
+
+/* callbacks for pdjson */
+int bufio_get_cb(void *);
+int bufio_peek_cb(void *);