diff --git a/src/kike.c b/src/kike.c index bc64180..73b6df1 100644 --- a/src/kike.c +++ b/src/kike.c @@ -446,6 +446,7 @@ server_context_free (struct server_context *self) static void client_cancel_timers (struct client *); static void client_set_kill_timer (struct client *); +static void client_update_poller (struct client *, const struct pollfd *); static void client_unregister (struct client *c, const char *reason) @@ -497,10 +498,12 @@ static void irc_send_str (struct client *c, const struct str *s) { // TODO: kill the connection above some "SendQ" threshold (careful!) - str_append_data (&c->write_buffer, s->str, s->len > IRC_MAX_MESSAGE_LENGTH ? IRC_MAX_MESSAGE_LENGTH : s->len); str_append (&c->write_buffer, "\r\n"); + // XXX: we might want to move this elsewhere, so that it doesn't get called + // as often; it's going to cause a lot of syscalls with epoll. + client_update_poller (c, NULL); } static void irc_send (struct client *c, @@ -1243,15 +1246,29 @@ on_irc_client_ready (const struct pollfd *pfd, void *user_data) client_set_ping_timer (c); } - int new_events = 0; if (c->ssl) { // Reads may want to write, writes may want to read, poll() may // return unexpected things in `revents'... let's try both if (!irc_try_read_ssl (c) || !irc_try_write_ssl (c)) return; + } + else if (!irc_try_read (c) || !irc_try_write (c)) + return; - new_events |= POLLIN; + client_update_poller (c, pfd); + + // The purpose of the `closing_link' state is to transfer the `ERROR' + if (c->closing_link && !c->write_buffer.len) + client_kill (c, NULL); +} + +static void +client_update_poller (struct client *c, const struct pollfd *pfd) +{ + int new_events = POLLIN; + if (c->ssl) + { if (c->write_buffer.len || c->ssl_rx_want_tx) new_events |= POLLOUT; @@ -1259,24 +1276,13 @@ on_irc_client_ready (const struct pollfd *pfd, void *user_data) if (c->ssl_rx_want_tx) new_events &= ~POLLIN; if (c->ssl_tx_want_rx) new_events &= ~POLLOUT; } - else - { - if (!irc_try_read (c) || !irc_try_write (c)) - return; - - new_events |= POLLIN; - if (c->write_buffer.len) - new_events |= POLLOUT; - } + else if (c->write_buffer.len) + new_events |= POLLOUT; hard_assert (new_events != 0); - if (pfd->events != new_events) + if (!pfd || pfd->events != new_events) poller_set (&c->ctx->poller, c->socket_fd, new_events, (poller_dispatcher_func) on_irc_client_ready, c); - - // The purpose of the `closing_link' state is to transfer the `ERROR' - if (c->closing_link && !c->write_buffer.len) - client_kill (c, NULL); } static void @@ -1329,8 +1335,7 @@ on_irc_client_available (const struct pollfd *pfd, void *user_data) ctx->n_clients++; set_blocking (fd, false); - poller_set (&ctx->poller, fd, POLLIN, - (poller_dispatcher_func) on_irc_client_ready, c); + client_update_poller (c, NULL); client_set_kill_timer (c); } }