commit 6be8143330044a05a09e0ea4510d28027f79c13a from: Omar Polo date: Sun Apr 14 08:34:50 2024 UTC bring in newer ev and bufio from telescope merge our local changes to bufio though. commit - 6eaaaab872315df9626e7237d13ed8d5aeb81fc5 commit + 6be8143330044a05a09e0ea4510d28027f79c13a blob - f6f8be81a73ad894f9c8ba465171001997a72ff4 blob + 1a65819f0cf1669eabd51b18d3eb54dae677dbf0 --- amused.c +++ amused.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -108,13 +107,13 @@ main_dispatch_player(int sig, int event, void *d) ssize_t n; int shut = 0; - if (event & POLLIN) { + if (event & EV_READ) { if ((n = imsg_read(imsgbuf)) == -1 && errno != EAGAIN) fatal("imsg_read error"); if (n == 0) /* Connection closed */ shut = 1; } - if (event & POLLOUT) { + if (event & EV_WRITE) { if ((n = msgbuf_write(&imsgbuf->w)) == -1 && errno != EAGAIN) fatal("msgbuf_write"); if (n == 0) /* Connection closed */ @@ -277,7 +276,7 @@ amused_main(void) iev_player = xmalloc(sizeof(*iev_player)); imsg_init(&iev_player->imsgbuf, pipe_main2player[0]); iev_player->handler = main_dispatch_player; - iev_player->events = POLLIN; + iev_player->events = EV_READ; ev_add(iev_player->imsgbuf.fd, iev_player->events, iev_player->handler, iev_player); @@ -365,9 +364,9 @@ spawn_daemon(void) void imsg_event_add(struct imsgev *iev) { - iev->events = POLLIN; + iev->events = EV_READ; if (iev->imsgbuf.w.queued) - iev->events |= POLLOUT; + iev->events |= EV_WRITE; ev_add(iev->imsgbuf.fd, iev->events, iev->handler, iev); } blob - 257d02f7f78471a6a377b68930cc73a5e8554f20 blob + c1c975ce279ad3396c8951b9dab02f4ef2374241 --- control.c +++ control.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -45,6 +44,7 @@ struct { int fd; + unsigned int tout; struct playlist play; int tx; } control_state = {.fd = -1, .tx = -1}; @@ -113,7 +113,8 @@ control_init(char *path) static void enable_accept(int fd, int ev, void *bula) { - ev_add(control_state.fd, POLLIN, control_accept, NULL); + control_state.tout = 0; + ev_add(control_state.fd, EV_READ, control_accept, NULL); } int @@ -150,7 +151,9 @@ control_accept(int listenfd, int event, void *bula) struct timeval evtpause = { 1, 0 }; ev_del(control_state.fd); - ev_timer(&evtpause, enable_accept, NULL); + control_state.tout = ev_timer(&evtpause, enable_accept, NULL); + if (control_state.tout == 0) + fatal("ev_timer failed"); } else if (errno != EWOULDBLOCK && errno != EINTR && errno != ECONNABORTED) log_warn("%s: accept4", __func__); @@ -171,7 +174,7 @@ control_accept(int listenfd, int event, void *bula) imsg_init(&c->iev.imsgbuf, connfd); c->iev.handler = control_dispatch_imsg; - c->iev.events = POLLIN; + c->iev.events = EV_READ; ev_add(c->iev.imsgbuf.fd, c->iev.events, c->iev.handler, &c->iev); TAILQ_INSERT_TAIL(&ctl_conns, c, entry); @@ -226,9 +229,9 @@ control_close(int fd) close(c->iev.imsgbuf.fd); /* Some file descriptors are available again. */ - if (ev_timer_pending()) { + if (ev_timer_pending(control_state.tout)) { ev_timer(NULL, NULL, NULL); - ev_add(control_state.fd, POLLIN, control_accept, NULL); + ev_add(control_state.fd, EV_READ, control_accept, NULL); } free(c); @@ -285,14 +288,14 @@ control_dispatch_imsg(int fd, int event, void *bula) imsgbuf = &c->iev.imsgbuf; - if (event & POLLIN) { + if (event & EV_READ) { if (((n = imsg_read(imsgbuf)) == -1 && errno != EAGAIN) || n == 0) { control_close(fd); return; } } - if (event & POLLOUT) { + if (event & EV_WRITE) { if (msgbuf_write(&imsgbuf->w) <= 0 && errno != EAGAIN) { control_close(fd); return; blob - 34f6474a60c36c69c8755554776633328c8cb829 blob + ee52583d16e300a724a09907f9e0217847264343 --- ev.c +++ ev.c @@ -25,12 +25,15 @@ #include "config.h" +#include + #include #include #include #include #include #include +#include #include #include @@ -41,6 +44,12 @@ struct evcb { void *udata; }; +struct evtimer { + unsigned int id; + struct timeval tv; + struct evcb cb; +}; + struct evbase { size_t len; @@ -53,8 +62,19 @@ struct evbase { int sigpipe[2]; struct evcb sigcb; - int timeout; - struct evcb toutcb; + unsigned int tid; + + /* + * Binary heap of timers. At runtime, new timers are added in + * the ``reserve'', a space after the caninocal end of the + * array, and at the end of every tick they're added to the + * heap. + */ + struct evtimer *timers; + size_t ntimers; + size_t reserve_from; + size_t reserve_till; + size_t timerscap; }; static struct evbase *base; @@ -98,7 +118,6 @@ ev_init(void) base->sigpipe[0] = -1; base->sigpipe[1] = -1; - base->timeout = INFTIM; if (ev_resize(16) == -1) { free(base->pfds); @@ -111,16 +130,35 @@ ev_init(void) return 0; } +static inline int +ev2poll(int ev) +{ + int ret = 0; + + if (ev & EV_READ) + ret |= POLLIN; + if (ev & EV_WRITE) + ret |= POLLOUT; + + return (ret); +} + int ev_add(int fd, int ev, void (*cb)(int, int, void *), void *udata) { - if (fd >= base->len) { + if (fd < 0) { + errno = EBADF; + return -1; + } + + if ((size_t)fd >= base->len) { if (ev_resize(fd + 1) == -1) return -1; } base->pfds[fd].fd = fd; - base->pfds[fd].events = ev; + base->pfds[fd].events = ev2poll(ev); + base->pfds[fd].revents = 0; base->cbs[fd].cb = cb; base->cbs[fd].udata = udata; @@ -154,7 +192,7 @@ ev_sigdispatch(int fd, int ev, void *data) if (read(fd, &signo, sizeof(signo)) != sizeof(signo)) return; - base->sigcb.cb(signo, 0, base->sigcb.udata); + base->sigcb.cb(signo, EV_SIGNAL, base->sigcb.udata); } int @@ -171,7 +209,7 @@ ev_signal(int sig, void (*cb)(int, int, void *), void fcntl(base->sigpipe[1], F_SETFL, flags | O_NONBLOCK) == -1) return -1; - if (ev_add(base->sigpipe[0], POLLIN, ev_sigdispatch, NULL) + if (ev_add(base->sigpipe[0], EV_READ, ev_sigdispatch, NULL) == -1) return -1; } @@ -183,31 +221,148 @@ ev_signal(int sig, void (*cb)(int, int, void *), void return 0; } -int +unsigned int ev_timer(const struct timeval *tv, void (*cb)(int, int, void*), void *udata) { - base->timeout = INFTIM; - if (tv) { - base->timeout = tv->tv_sec * 1000; - base->timeout += tv->tv_usec / 1000; + struct evtimer *evt; + void *t; + size_t newcap; + unsigned int nextid; + + if (tv == NULL) { + errno = EINVAL; + return 0; } - base->toutcb.cb = cb; - base->toutcb.udata = udata; + if (base->reserve_till == base->timerscap) { + newcap = base->timerscap + 8; + t = recallocarray(base->timers, base->timerscap, newcap, + sizeof(*base->timers)); + if (t == NULL) + return 0; + base->timers = t; + base->timerscap = newcap; + } - return 0; -} + if ((nextid = ++base->tid) == 0) + nextid = ++base->tid; -int -ev_timer_pending(void) + evt = &base->timers[base->reserve_till]; + evt->id = nextid; + memcpy(&evt->tv, tv, sizeof(*tv)); + evt->cb.cb = cb; + evt->cb.udata = udata; + + base->reserve_till++; + return (nextid); +} + +static int +find_timer(unsigned int id, size_t *pos) { - return base->timeout != INFTIM; + size_t i; + + if (id == 0) + return (0); + + for (i = 0; i < base->ntimers; ++i) { + if (base->timers[i].id == id) { + *pos = i; + return (1); + } + } + + for (i = base->reserve_from; i < base->reserve_till; ++i) { + if (base->timers[i].id == id) { + *pos = i; + return (1); + } + } + + return (0); } +int +ev_timer_pending(unsigned int id) +{ + size_t i; + + return (find_timer(id, &i)); +} + +static void +bubbledown(size_t i) +{ + struct evtimer tmp; + size_t l, r, s; + + for (;;) { + l = 2 * i + 1; + r = 2 * i + 2; + + /* base case: there are no children */ + if (l >= base->ntimers) + return; + + /* find the smaller child */ + s = r; + if (r >= base->ntimers || + timercmp(&base->timers[l].tv, &base->timers[r].tv, <)) + s = l; + + /* other base case: it's at the right place */ + if (timercmp(&base->timers[i].tv, &base->timers[s].tv, <)) + return; + + /* swap */ + memcpy(&tmp, &base->timers[s], sizeof(tmp)); + memcpy(&base->timers[s], &base->timers[i], sizeof(tmp)); + memcpy(&base->timers[i], &tmp, sizeof(tmp)); + + i = s; + } +} + +static inline void +cancel_timer(size_t i) +{ + base->ntimers--; + if (i != base->ntimers) { + memcpy(&base->timers[i], &base->timers[base->ntimers], + sizeof(*base->timers)); + bubbledown(i); + } +} + int +ev_timer_cancel(unsigned int id) +{ + size_t i; + + if (!find_timer(id, &i)) + return (-1); + + if (i < base->ntimers) { + cancel_timer(i); + return (0); + } + + base->reserve_till--; + if (i != base->reserve_till) + memcpy(&base->timers[i], &base->timers[base->reserve_till], + sizeof(*base->timers)); + return (0); +} + +int ev_del(int fd) { - if (fd >= base->len) { + if (fd < 0) { + errno = EBADF; + return -1; + } + + if ((size_t)fd >= base->len) { errno = ERANGE; return -1; } @@ -221,43 +376,125 @@ ev_del(int fd) return 0; } +static void +timerheapify(void) +{ + size_t i, reserve, gap; + + reserve = base->reserve_till - base->reserve_from; + if (reserve == 0) + return; + + gap = base->reserve_from - base->ntimers; + if (gap != 0) { + memmove(&base->timers[base->ntimers], + &base->timers[base->reserve_from], + reserve * sizeof(*base->timers)); + base->reserve_from -= gap; + base->reserve_till -= gap; + } + + base->ntimers = base->reserve_till; + + if (base->ntimers < 2) + return; + + i = base->ntimers / 2 - 1; + for (;;) { + bubbledown(i); + if (i == 0) + break; + i--; + } +} + +static inline int +poll2ev(int ev) +{ + int r = 0; + + if (ev & (POLLIN|POLLHUP)) + r |= EV_READ; + if (ev & (POLLOUT|POLLWRNORM|POLLWRBAND)) + r |= EV_WRITE; + + return (r); +} + int -ev_loop(void) +ev_step(void) { struct timespec elapsed, beg, end; - int n, em; + struct timeval tv, sub, *min; + struct evcb cb; + int n, msec; size_t i; - while (!ev_stop) { - clock_gettime(CLOCK_MONOTONIC, &beg); - if ((n = poll(base->pfds, base->len, base->timeout)) == -1) { - if (errno != EINTR) - return -1; - } - clock_gettime(CLOCK_MONOTONIC, &end); + timerheapify(); + base->reserve_from = base->ntimers; + base->reserve_till = base->ntimers; + min = NULL; + msec = -1; + if (base->ntimers) { + min = &base->timers[0].tv; + msec = min->tv_sec * 1000 + (min->tv_usec + 999) / 1000; + } + + clock_gettime(CLOCK_MONOTONIC, &beg); + if ((n = poll(base->pfds, base->len, msec)) == -1) { + if (errno != EINTR) + return -1; + } + + if (n == 0 && min) + memcpy(&tv, min, sizeof(tv)); + else { + clock_gettime(CLOCK_MONOTONIC, &end); timespecsub(&end, &beg, &elapsed); - em = elapsed.tv_sec * 1000 + elapsed.tv_nsec / 1000000; - if (base->timeout != INFTIM) { - if (base->timeout - em < 0 || n == 0) { - base->timeout = INFTIM; - base->toutcb.cb(-1, 0, base->toutcb.udata); - } else - base->timeout -= em; + TIMESPEC_TO_TIMEVAL(&tv, &elapsed); + } + + for (i = 0; i < base->ntimers && !ev_stop; /* nop */) { + timersub(&base->timers[i].tv, &tv, &sub); + if (sub.tv_sec <= 0) { + /* + * delete the timer before calling its + * callback; protects from timer that + * attempt to delete themselves. + */ + memcpy(&cb, &base->timers[i].cb, sizeof(cb)); + cancel_timer(i); + cb.cb(-1, EV_TIMEOUT, cb.udata); + continue; } - for (i = 0; i < base->len && n > 0 && !ev_stop; ++i) { - if (base->pfds[i].fd == -1) - continue; - if (base->pfds[i].revents & (POLLIN|POLLOUT|POLLHUP)) { - n--; - base->cbs[i].cb(base->pfds[i].fd, - base->pfds[i].revents, - base->cbs[i].udata); - } + memcpy(&base->timers[i].tv, &sub, sizeof(sub)); + i++; + } + + for (i = 0; i < base->len && n > 0 && !ev_stop; ++i) { + if (base->pfds[i].fd == -1) + continue; + if (base->pfds[i].revents & (POLLIN|POLLOUT|POLLHUP)) { + n--; + base->cbs[i].cb(base->pfds[i].fd, + poll2ev(base->pfds[i].revents), + base->cbs[i].udata); } } + return (0); +} + +int +ev_loop(void) +{ + while (!ev_stop) { + if (ev_step() == -1) + return (-1); + } + return 0; } blob - 7acacfe73721b2c98e67bc1df641f3c9510c1c61 blob + eced7ccf6ec9531156df977c26ab0244f27348fa --- ev.h +++ ev.h @@ -25,11 +25,20 @@ struct timeval; -int ev_init(void); -int ev_add(int, int, void(*)(int, int, void *), void *); -int ev_signal(int, void(*)(int, int, void * ), void *); -int ev_timer(const struct timeval *, void(*)(int, int, void *), void *); -int ev_timer_pending(void); -int ev_del(int); -int ev_loop(void); -void ev_break(void); +#define EV_READ 0x1 +#define EV_WRITE 0x2 +#define EV_SIGNAL 0x4 +#define EV_TIMEOUT 0x8 + +int ev_init(void); +int ev_add(int, int, void(*)(int, int, void *), void *); +int ev_signal(int, void(*)(int, int, void * ), void *); +unsigned int ev_timer(const struct timeval *, void(*)(int, int, void *), + void *); +int ev_timer_pending(unsigned int); +int ev_timer_cancel(unsigned int); +int ev_del(int); +int ev_step(void); +int ev_step(void); +int ev_loop(void); +void ev_break(void); blob - b6666792ae040e1ee339dc20a68db0cf74208e6f blob + 7ed26ffa838545a2a5e2e82b66f57f527e4aef7a --- web/Makefile +++ web/Makefile @@ -44,7 +44,7 @@ uninstall: rm ${DESTDIR}${MANDIR}/man1/${PROG}.1 .c.o: - ${CC} -I../ ${CFLAGS} -c $< -o $@ + ${CC} -I../ ${CFLAGS} -DBUFIO_WITHOUT_TLS -c $< -o $@ # --- maintainer targets --- blob - da7bde52d49d841a387fa5a9526fe9bb66410503 blob + 424516bc75c38f21feafbd73cdcc6c5b22799fd1 --- web/bufio.c +++ web/bufio.c @@ -27,7 +27,6 @@ #include #include -#include #include #include #include @@ -35,10 +34,14 @@ #include #include +#ifndef BUFIO_WITHOUT_TLS +#include +#endif + #include "bufio.h" int -buf_init(struct buffer *buf) +buf_init(struct buf *buf) { const size_t cap = BIO_CHUNK; @@ -50,7 +53,7 @@ buf_init(struct buffer *buf) } static int -buf_grow(struct buffer *buf) +buf_grow(struct buf *buf) { size_t newcap; void *t; @@ -65,7 +68,7 @@ buf_grow(struct buffer *buf) } int -buf_write(struct buffer *buf, const void *d, size_t len) +buf_write(struct buf *buf, const void *d, size_t len) { while (buf->len + len > buf->cap) { if (buf_grow(buf) == -1) @@ -77,14 +80,32 @@ buf_write(struct buffer *buf, const void *d, size_t le } int -buf_has_line(struct buffer *buf, const char *nl) +buf_has_line(struct buf *buf, const char *nl) { return (memmem(buf->buf, buf->len, nl, strlen(nl)) != NULL); } +char * +buf_getdelim(struct buf *buf, const char *nl, size_t *len) +{ + uint8_t *endl; + size_t nlen; + + *len = 0; + + nlen = strlen(nl); + if ((endl = memmem(buf->buf, buf->len, nl, nlen)) == NULL) + return (NULL); + *len = endl + nlen - buf->buf; + *endl = '\0'; + return (buf->buf); +} + void -buf_drain(struct buffer *buf, size_t l) +buf_drain(struct buf *buf, size_t l) { + buf->cur = 0; + if (l >= buf->len) { buf->len = 0; return; @@ -95,7 +116,7 @@ buf_drain(struct buffer *buf, size_t l) } void -buf_drain_line(struct buffer *buf, const char *nl) +buf_drain_line(struct buf *buf, const char *nl) { uint8_t *endln; size_t nlen; @@ -107,7 +128,7 @@ buf_drain_line(struct buffer *buf, const char *nl) } void -buf_free(struct buffer *buf) +buf_free(struct buf *buf) { free(buf->buf); memset(buf, 0, sizeof(*buf)); @@ -131,14 +152,47 @@ bufio_init(struct bufio *bio) void bufio_free(struct bufio *bio) { +#ifndef BUFIO_WITHOUT_TLS + if (bio->ctx) + tls_free(bio->ctx); + bio->ctx = NULL; +#endif + if (bio->fd != -1) close(bio->fd); + bio->fd = -1; buf_free(&bio->rbuf); buf_free(&bio->wbuf); } int +bufio_close(struct bufio *bio) +{ +#ifndef BUFIO_WITHOUT_TLS + if (bio->ctx == NULL) + return (0); + + switch (tls_close(bio->ctx)) { + case 0: + return 0; + case TLS_WANT_POLLIN: + errno = EAGAIN; + bio->wantev = BUFIO_WANT_READ; + return (-1); + case TLS_WANT_POLLOUT: + errno = EAGAIN; + bio->wantev = BUFIO_WANT_WRITE; + return (-1); + default: + return (-1); + } +#else + return (0); +#endif +} + +int bufio_reset(struct bufio *bio) { bufio_free(bio); @@ -157,22 +211,98 @@ bufio_set_chunked(struct bufio *bio, int chunked) bio->chunked = chunked; } -short -bufio_pollev(struct bufio *bio) +int +bufio_starttls(struct bufio *bio, const char *host, int insecure, + const uint8_t *cert, size_t certlen, const uint8_t *key, size_t keylen) { - short ev; +#ifndef BUFIO_WITHOUT_TLS + struct tls_config *conf; - ev = POLLIN; - if (bio->wbuf.len != 0) - ev |= POLLOUT; + 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 (cert && tls_config_set_keypair_mem(conf, cert, certlen, + key, keylen) == -1) { + tls_config_free(conf); + return (-1); + } + + 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); +#else + errno = EINVAL; + return (-1); +#endif +} + +int +bufio_ev(struct bufio *bio) +{ + short ev; + if (bio->wantev) + return (bio->wantev); + + ev = BUFIO_WANT_READ; + if (bio->wbuf.len != 0) + ev |= BUFIO_WANT_WRITE; + return (ev); } +int +bufio_handshake(struct bufio *bio) +{ +#ifndef BUFIO_WITHOUT_TLS + if (bio->ctx == NULL) { + errno = EINVAL; + return (-1); + } + + switch (tls_handshake(bio->ctx)) { + case 0: + return (0); + case TLS_WANT_POLLIN: + errno = EAGAIN; + bio->wantev = BUFIO_WANT_READ; + return (-1); + case TLS_WANT_POLLOUT: + errno = EAGAIN; + bio->wantev = BUFIO_WANT_WRITE; + return (-1); + default: + return (-1); + } +#else + errno = EINVAL; + return (-1); +#endif +} + ssize_t bufio_read(struct bufio *bio) { - struct buffer *rbuf = &bio->rbuf; + struct buf *rbuf = &bio->rbuf; ssize_t r; assert(rbuf->cap >= rbuf->len); @@ -181,6 +311,29 @@ bufio_read(struct bufio *bio) return (-1); } +#ifndef BUFIO_WITHOUT_TLS + if (bio->ctx) { + r = tls_read(bio->ctx, rbuf->buf + rbuf->len, + rbuf->cap - rbuf->len); + switch (r) { + case TLS_WANT_POLLIN: + errno = EAGAIN; + bio->wantev = BUFIO_WANT_READ; + return (-1); + case TLS_WANT_POLLOUT: + errno = EAGAIN; + bio->wantev = BUFIO_WANT_WRITE; + return (-1); + case -1: + return (-1); + default: + bio->wantev = 0; + rbuf->len += r; + return (r); + } + } +#endif + r = read(bio->fd, rbuf->buf + rbuf->len, rbuf->cap - rbuf->len); if (r == -1) return (-1); @@ -191,7 +344,7 @@ bufio_read(struct bufio *bio) size_t bufio_drain(struct bufio *bio, void *d, size_t len) { - struct buffer *rbuf = &bio->rbuf; + struct buf *rbuf = &bio->rbuf; if (len > rbuf->len) len = rbuf->len; @@ -203,9 +356,30 @@ bufio_drain(struct bufio *bio, void *d, size_t len) ssize_t bufio_write(struct bufio *bio) { - struct buffer *wbuf = &bio->wbuf; + struct buf *wbuf = &bio->wbuf; ssize_t w; +#ifndef BUFIO_WITHOUT_TLS + if (bio->ctx) { + switch (w = tls_write(bio->ctx, wbuf->buf, wbuf->len)) { + case TLS_WANT_POLLIN: + errno = EAGAIN; + bio->wantev = BUFIO_WANT_READ; + return (-1); + case TLS_WANT_POLLOUT: + errno = EAGAIN; + bio->wantev = BUFIO_WANT_WRITE; + return (-1); + case -1: + return (-1); + default: + bio->wantev = 0; + buf_drain(wbuf, w); + return (w); + } + } +#endif + w = write(bio->fd, wbuf->buf, wbuf->len); if (w == -1) return (-1); @@ -216,7 +390,7 @@ bufio_write(struct bufio *bio) static int bufio_append(struct bufio *bio, const void *d, size_t len) { - struct buffer *wbuf = &bio->wbuf; + struct buf *wbuf = &bio->wbuf; if (len == 0) return (0); @@ -277,3 +451,31 @@ bufio_compose_fmt(struct bufio *bio, const char *fmt, 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 buf *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 buf *rbuf = &bio->rbuf; + + if (rbuf->cur >= rbuf->len) + return (EOF); + return (rbuf->buf[rbuf->cur]); +} blob - 98fdeb1d1412eae123638b65b2c840c85352e4ea blob + 257a931f662a9d92b602a0b41305198f2ced784c --- web/bufio.h +++ web/bufio.h @@ -23,33 +23,50 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#define BIO_CHUNK 1024 -struct buffer { +#ifndef BUFIO_WITHOUT_TLS +struct tls; +#endif + +#define BIO_CHUNK 128 +struct buf { uint8_t *buf; size_t len; size_t cap; + size_t cur; }; struct bufio { int fd; int chunked; - struct buffer wbuf; - struct buffer rbuf; +#ifndef BUFIO_WITHOUT_TLS + struct tls *ctx; +#endif + int wantev; + struct buf wbuf; + struct buf rbuf; }; -int buf_init(struct buffer *); -int buf_write(struct buffer *, const void *, size_t); -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 *); +#define BUFIO_WANT_READ 0x1 +#define BUFIO_WANT_WRITE 0x2 +int buf_init(struct buf *); +int buf_write(struct buf *, const void *, size_t); +int buf_has_line(struct buf *, const char *); +char *buf_getdelim(struct buf *, const char *, size_t *); +void buf_drain(struct buf *, size_t); +void buf_drain_line(struct buf *, const char *); +void buf_free(struct buf *); + int bufio_init(struct bufio *); void bufio_free(struct bufio *); +int bufio_close(struct bufio *); int bufio_reset(struct bufio *); void bufio_set_fd(struct bufio *, int); void bufio_set_chunked(struct bufio *, int); -short bufio_pollev(struct bufio *); +int bufio_starttls(struct bufio *, const char *, int, + const uint8_t *, size_t, const uint8_t *, size_t); +int bufio_ev(struct bufio *); +int bufio_handshake(struct bufio *); ssize_t bufio_read(struct bufio *); size_t bufio_drain(struct bufio *, void *, size_t); ssize_t bufio_write(struct bufio *); @@ -57,3 +74,8 @@ 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 *); blob - 75b8cd43bfd889cd1f33d56beb1869ad32225af7 blob + b24bd2f26157718c7e62a92aea5c2ae4fbfe148a --- web/http.c +++ web/http.c @@ -61,7 +61,7 @@ http_init(struct client *clt, int fd) int http_parse(struct client *clt) { - struct buffer *rbuf = &clt->bio.rbuf; + struct buf *rbuf = &clt->bio.rbuf; struct request *req = &clt->req; size_t len; uint8_t *endln; @@ -188,7 +188,7 @@ int http_read(struct client *clt) { struct request *req = &clt->req; - struct buffer *rbuf = &clt->bio.rbuf; + struct buf *rbuf = &clt->bio.rbuf; size_t left; /* clients may have sent more data than advertised */ blob - b6888f4d5f07b6e4310164980fc32c0d3a82f9be blob + 16ad7fe7ebf1a6a063c5bd5e0c857c199237825b --- web/web.c +++ web/web.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -272,6 +271,20 @@ const char *js = const char *foot = ""; +static inline int +bio_ev(struct bufio *bio) +{ + int ret, ev; + + ret = 0; + ev = bufio_ev(bio); + if (ev & BUFIO_WANT_READ) + ret |= EV_READ; + if (ev & BUFIO_WANT_WRITE) + ret |= EV_WRITE; + return ret; +} + static int dial(const char *sock) { @@ -355,7 +368,7 @@ dispatch_event(const char *msg) if (ws_compose(clt, WST_TEXT, msg, len) == -1) ret = -1; - ev_add(clt->bio.fd, POLLIN|POLLOUT, client_ev, clt); + ev_add(clt->bio.fd, EV_READ|EV_WRITE, client_ev, clt); } return (ret); @@ -445,13 +458,13 @@ imsg_dispatch(int fd, int ev, void *d) size_t datalen; int r; - if (ev & (POLLIN|POLLHUP)) { + if (ev & EV_READ) { if ((n = imsg_read(&imsgbuf)) == -1 && errno != EAGAIN) fatal("imsg_read"); if (n == 0) fatalx("pipe closed"); } - if (ev & POLLOUT) { + if (ev & EV_WRITE) { if ((n = msgbuf_write(&imsgbuf.w)) == -1 && errno != EAGAIN) fatal("msgbuf_write"); if (n == 0) @@ -563,9 +576,9 @@ imsg_dispatch(int fd, int ev, void *d) } } - ev = POLLIN; + ev = EV_READ; if (imsgbuf.w.queued) - ev |= POLLOUT; + ev |= EV_WRITE; ev_add(fd, ev, imsg_dispatch, NULL); } @@ -691,7 +704,7 @@ route_jump(struct client *clt) imsg_compose(&imsgbuf, IMSG_CTL_JUMP, 0, 0, -1, path, sizeof(path)); - ev_add(imsgbuf.w.fd, POLLIN|POLLOUT, imsg_dispatch, NULL); + ev_add(imsgbuf.w.fd, EV_READ|EV_WRITE, imsg_dispatch, NULL); break; } @@ -783,7 +796,7 @@ route_mode(struct client *clt) imsg_compose(&imsgbuf, IMSG_CTL_MODE, 0, 0, -1, &pm, sizeof(pm)); - ev_add(imsgbuf.w.fd, POLLIN|POLLOUT, imsg_dispatch, NULL); + ev_add(imsgbuf.w.fd, EV_READ|EV_WRITE, imsg_dispatch, NULL); break; } @@ -804,7 +817,7 @@ route_mode(struct client *clt) static void route_handle_ws(struct client *clt) { - struct buffer *rbuf = &clt->bio.rbuf; + struct buf *rbuf = &clt->bio.rbuf; int type; size_t len; @@ -923,14 +936,14 @@ client_ev(int fd, int ev, void *d) { struct client *clt = d; - if (ev & (POLLIN|POLLHUP)) { + if (ev & EV_READ) { if (bufio_read(&clt->bio) == -1 && errno != EAGAIN) { log_warn("bufio_read"); goto err; } } - if (ev & POLLOUT) { + if (ev & EV_WRITE) { if (bufio_write(&clt->bio) == -1 && errno != EAGAIN) { log_warn("bufio_write"); goto err; @@ -959,8 +972,8 @@ client_ev(int fd, int ev, void *d) clt->route(clt); again: - ev = bufio_pollev(&clt->bio); - if (ev == POLLIN && (clt->done || clt->err)) { + ev = bio_ev(&clt->bio); + if (ev == EV_READ && (clt->done || clt->err)) { goto err; /* done with this client */ } @@ -993,7 +1006,7 @@ web_accept(int psock, int ev, void *d) TAILQ_INSERT_TAIL(&clients, clt, clients); - client_ev(sock, POLLIN, clt); + client_ev(sock, EV_READ, clt); return; } @@ -1070,7 +1083,7 @@ main(int argc, char **argv) imsg_compose(&imsgbuf, IMSG_CTL_SHOW, 0, 0, -1, NULL, 0); imsg_compose(&imsgbuf, IMSG_CTL_STATUS, 0, 0, -1, NULL, 0); imsg_compose(&imsgbuf, IMSG_CTL_MONITOR, 0, 0, -1, NULL, 0); - ev_add(amused_sock, POLLIN|POLLOUT, imsg_dispatch, NULL); + ev_add(amused_sock, EV_READ|EV_WRITE, imsg_dispatch, NULL); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; @@ -1105,7 +1118,7 @@ main(int argc, char **argv) if (listen(fd, 5) == -1) err(1, "listen"); - if (ev_add(fd, POLLIN, web_accept, NULL) == -1) + if (ev_add(fd, EV_READ, web_accept, NULL) == -1) fatal("ev_add"); nsock++; } blob - 16fab184ad65d5ba6cbe6e2c5fa25f9b404af1f1 blob + 0e7302da3d95b628068ffacd9a5d67dd102a5cc1 --- web/ws.c +++ web/ws.c @@ -129,7 +129,7 @@ ws_accept_hdr(const char *secret, char *out, size_t ol int ws_read(struct client *clt, int *type, size_t *len) { - struct buffer *rbuf = &clt->bio.rbuf; + struct buf *rbuf = &clt->bio.rbuf; size_t i; uint32_t mask; uint8_t first, second, op, plen;