From: Egor Date: Thu, 19 Oct 2023 13:59:50 +0000 (+0300) Subject: killConnection: never block X-Git-Url: https://git.patchysicp.xyz/?a=commitdiff_plain;h=b7727940cb1f07e4f7c285cb086d9b7645c1b824;p=patchyircd.git killConnection: never block --- diff --git a/src/common.h b/src/common.h index 4750193..f857071 100644 --- a/src/common.h +++ b/src/common.h @@ -56,6 +56,8 @@ struct client_data { unsigned want_write_for_read :1; unsigned want_read_for_write :1; unsigned want_write_for_write :1; + unsigned want_read_for_close :1; + unsigned want_write_for_close :1; }; struct channel { char *key; diff --git a/src/main.c b/src/main.c index fc9d75e..97dcffa 100644 --- a/src/main.c +++ b/src/main.c @@ -323,8 +323,9 @@ int main(int argc, char *argv[]) FD_SET(self_sock, &readfds); #endif for (struct client_data *cl = clients; cl; cl = cl->next) { - FD_SET(cl->FD, &readfds); - if (cl->want_write_for_read || cl->want_write_for_write) + if (!cl->want_write_for_close) + FD_SET(cl->FD, &readfds); + if (cl->want_write_for_read || cl->want_write_for_write || cl->want_write_for_close) FD_SET(cl->FD, &writefds); } @@ -365,10 +366,13 @@ int main(int argc, char *argv[]) struct client_data *next = cl->next; int isr = FD_ISSET(cl->FD, &readfds); int isw = FD_ISSET(cl->FD, &writefds); - if (isr || (cl->want_write_for_read && isw)) - recvProc(cl); + if (!cl->want_read_for_close && !cl->want_write_for_close) + if (isr || (cl->want_write_for_read && isw)) + recvProc(cl); if ((cl->want_read_for_write && isr) || (cl->want_write_for_write && isw)) sendClient(cl, 0, 0); + if ((cl->want_read_for_close && isr) || (cl->want_write_for_close && isw)) + killConnectionPart2(cl); cl = next; } } @@ -377,6 +381,8 @@ int main(int argc, char *argv[]) for (struct client_data *cl = clients; cl;) { struct client_data *next = cl->next; killConnection(cl, 0); + /* FIXME: who is going to wait for these connections to actually get + * killed? */ cl = next; } net_cleanup(); diff --git a/src/net.c b/src/net.c index 906bfc8..e17a167 100644 --- a/src/net.c +++ b/src/net.c @@ -7,34 +7,9 @@ struct client_data *allocClient() return calloc(1, sizeof(struct client_data)); } -#ifdef HAS_TLS -static void block(struct client_data *cl, int out) +void killConnection(struct client_data *cl, int byChoice) { -#ifdef _WIN32 - fd_set fds; - FD_ZERO(&fds); - FD_SET(cl->FD, &fds); - if (out) - select(cl->FD+1, 0, &fds, 0, 0); - else - select(cl->FD+1, &fds, 0, 0, 0); -#else - struct pollfd pfd; - pfd.fd = cl->FD; - pfd.events = out ? POLLOUT : POLLIN; - poll(&pfd, 1, 0); -#endif -} -#endif - -void killConnection(struct client_data *cl, int byChoice) { if (!cl) return; - for (struct client_data **next = &clients; *next; next = &(*next)->next) { - if (*next == cl) { - *next = cl->next; - break; - } - } if (cl->peername) fprintf(stderr, "Client disconnected from Socket: %"PRISocket", IP: %s PORT: %d\n", cl->FD, cl->peername, cl->peerport); if(!byChoice && cl->nick && cl->username) { @@ -44,17 +19,27 @@ void killConnection(struct client_data *cl, int byChoice) { // Send error to client informing them that they will be disconnected msg_error("Closing Link"); sendbuf(cl); + killConnectionPart2(cl); +} +void killConnectionPart2(struct client_data *cl) +{ + /* FIXME: we have to flush existing data somehow */ + /* A better implementation would be to keep a separate list of disconnected + * clients. This way we can do all PARTing right away and only concern + * ourselves with tls_write/tls_close. */ + cl->want_read_for_close = 0; + cl->want_write_for_close = 0; if (cl->FD != INVALID_SOCKET) { #ifdef HAS_TLS if (cl->cctx) { - // FIXME: this blocks - int rv; - for (;;) { - rv = tls_close(cl->cctx); - if (rv == TLS_WANT_POLLIN || rv == TLS_WANT_POLLOUT) - block(cl, rv == TLS_WANT_POLLOUT); - else - break; + int rv = tls_close(cl->cctx); + if (rv == TLS_WANT_POLLIN) { + cl->want_read_for_close = 1; + return; + } + if (rv == TLS_WANT_POLLOUT) { + cl->want_write_for_close = 1; + return; } if (rv == -1) { fprintf(stderr, "tls_close (%"PRISocket"): %s\n", cl->FD, tls_error(cl->cctx)); @@ -66,6 +51,12 @@ void killConnection(struct client_data *cl, int byChoice) { shutdown(cl->FD, SHUT_RDWR); closesocket(cl->FD); } + for (struct client_data **next = &clients; *next; next = &(*next)->next) { + if (*next == cl) { + *next = cl->next; + break; + } + } struct trie_find *f = NULL; if (trie_findfirst(&f, &cl->channels) == 1) do { diff --git a/src/net.h b/src/net.h index c147b03..d0d4bde 100644 --- a/src/net.h +++ b/src/net.h @@ -6,6 +6,7 @@ void sendbuf(struct client_data *client); void sendbuf_visible(struct client_data *client); struct client_data *allocClient(); void killConnection(struct client_data *client, int byChoice); +void killConnectionPart2(struct client_data *cl); void recvProc(struct client_data *cl); void sendClient(struct client_data *cl, const char *buf, size_t len);