From 09af6dcd618701bc5994b4a146e6df34e1cf9015 Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Mon, 16 Nov 2020 15:04:39 -0500 Subject: Set client sockets non-blocking Except for during writes. This prevents pounce getting blocked on a client sending only a partial TLS record, for example. Writes still need to block because pounce doesn't have a way to resume them. (And it would do so by having a buffer, but sockets already have a send buffer, so what would be the point of that?) I don't think it should be a problem since outside of stateSync, writes only happen when poll returns POLLOUT. I feel like ideally SO_SNDLOWAT would be set to guarantee a full IRC message can always be written on POLLOUT, but since it's actually TLS records being sent, it's not obvious what the size would be. I'm also making an assumption here that tls_read returning TLS_WANT_POLLOUT is unlikely to happen, since I don't actually set pollfd.events based on that. I'm not sure how wanting to resume a tls_read after a POLLOUT could be cleanly handled. I'm just going to hope that if it does happen, the regular poll loop will eventually sort it out... --- bounce.c | 6 +++--- bounce.h | 3 ++- client.c | 9 +++++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/bounce.c b/bounce.c index b0cdca2..a96f753 100644 --- a/bounce.c +++ b/bounce.c @@ -481,12 +481,12 @@ int main(int argc, char *argv[]) { if (!event.clients[i]) { struct tls *tls; - int fd = localAccept(&tls, event.fds[i].fd); - if (fd < 0) { + int sock = localAccept(&tls, event.fds[i].fd); + if (sock < 0) { warn("accept"); continue; } - eventAdd(fd, clientAlloc(tls)); + eventAdd(sock, clientAlloc(sock, tls)); continue; } diff --git a/bounce.h b/bounce.h index 77e0164..5d6c4a2 100644 --- a/bounce.h +++ b/bounce.h @@ -193,6 +193,7 @@ enum Need { }; struct Client { bool error; + int sock; struct tls *tls; enum Need need; enum Cap caps; @@ -204,7 +205,7 @@ struct Client { extern enum Cap clientCaps; extern char *clientPass; extern char *clientAway; -struct Client *clientAlloc(struct tls *tls); +struct Client *clientAlloc(int sock, struct tls *tls); void clientFree(struct Client *client); void clientRecv(struct Client *client); void clientSend(struct Client *client, const char *ptr, size_t len); diff --git a/client.c b/client.c index 4327a89..6c12405 100644 --- a/client.c +++ b/client.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -47,9 +48,11 @@ char *clientAway; static size_t active; -struct Client *clientAlloc(struct tls *tls) { +struct Client *clientAlloc(int sock, struct tls *tls) { struct Client *client = calloc(1, sizeof(*client)); if (!client) err(EX_OSERR, "calloc"); + fcntl(sock, F_SETFL, O_NONBLOCK); + client->sock = sock; client->tls = tls; client->need = NeedHandshake | NeedNick | NeedUser; if (clientPass) client->need |= NeedPass; @@ -83,17 +86,19 @@ void clientFree(struct Client *client) { void clientSend(struct Client *client, const char *ptr, size_t len) { if (verbose) fprintf(stderr, "\x1B[34m%.*s\x1B[m", (int)len, ptr); + fcntl(client->sock, F_SETFL, 0); while (len) { ssize_t ret = tls_write(client->tls, ptr, len); if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) continue; if (ret < 0) { warnx("client tls_write: %s", tls_error(client->tls)); client->error = true; - return; + break; } ptr += ret; len -= ret; } + fcntl(client->sock, F_SETFL, O_NONBLOCK); } void clientFormat(struct Client *client, const char *format, ...) { -- cgit 1.4.1 with .3 manual pages if I cared to write them. 2019-02-20Add Dirk Gently's Holistic Detective AgencyJune McEnroe 2019-02-20Move /opt/pkg after /usr in PATHJune McEnroe Installing mandoc from pkgsrc also installs a man executable which is horribly broken. Keep using the system man. 2019-02-20Set man_hard_wrap in nvimJune McEnroe Vendoring man.vim until <https://github.com/neovim/neovim/pull/9633> is merged and appears in a release. 2019-02-18Use hi -o anchor in upJune McEnroe 2019-02-18Don't match nested parentheses in Tag for CJune McEnroe Fixes mistaken highlight of: pngWrite(file, (uint8_t []) { 0, 0, 0 }, 3); 2019-02-18Match whitespace between * [] {}June McEnroe 2019-02-18Fix function-like #define regexJune McEnroe A define like #define FOO (1) is not function-like. 2019-02-18Match Tag in RustJune McEnroe 2019-02-18Match sh functions as TagJune McEnroe 2019-02-18Match Sh and Ss as Tag in mdocJune McEnroe 2019-02-18Match statics and typedefs as TagJune McEnroe 2019-02-18Clean up htmlHeaderJune McEnroe 2019-02-18Remove hi line numberingJune McEnroe Tags are much better for referring to specific parts of a file and line numbering is better done by a post-processing tool such as cat -n or producing a two-column HTML <table>. 2019-02-18Add Tag class to hiJune McEnroe 2019-02-17Generate HTML with hi -n -f html -o anchorJune McEnroe Running hi twice to insert stuff between the head and the content is a bit of a hack but oh well. 2019-02-17Add hi -f html -o anchor for line number linksJune McEnroe 2019-02-17Simplify temp trap in upJune McEnroe 2019-02-17Add line numbers to hiJune McEnroe Renames previous -n option to -m to stay consistent with cat -n. Prefixing lines with line numbers affects where the first tab indent ends up relative to the text above it. Not sure if it's worth fixing somehow. 2019-02-17Always split spans after newlinesJune McEnroe Simplifies ANSI and IRC output code, and prepares for line numbered output. 2019-02-15Color format specifiers light cyan in vimJune McEnroe 2019-02-15Highlight Interp as yellowJune McEnroe 2019-02-15Highlight strings in sh command substitutionsJune McEnroe 2019-02-15Add nmap gpJune McEnroe 2019-02-14Avoid newline when copying URL to pasteboardJune McEnroe 2019-02-13Add forgotten "sixth" book of H2G2June McEnroe