kike: be more careful when closing the connection

This commit is contained in:
Přemysl Eric Janouch 2015-03-23 22:57:13 +01:00
parent 2dd191376f
commit 94d4f060ff

26
kike.c
View File

@ -311,6 +311,7 @@ struct client
bool initialized; ///< Has any data been received yet?
bool registered; ///< The user has registered
bool closing_link; ///< Closing link
bool half_closed; ///< Closing link: conn. is half-closed
bool ssl_rx_want_tx; ///< SSL_read() wants to write
bool ssl_tx_want_rx; ///< SSL_write() wants to read
@ -787,7 +788,9 @@ client_kill (struct client *c, const char *reason)
struct server_context *ctx = c->ctx;
if (c->ssl)
// Note that we might have already called this once, but that is fine
(void) SSL_shutdown (c->ssl);
xclose (c->socket_fd);
c->socket_event.closed = true;
@ -2620,8 +2623,27 @@ on_client_ready (const struct pollfd *pfd, void *user_data)
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);
if (c->closing_link && !c->half_closed && !c->write_buffer.len)
{
// To make sure the client has received our ERROR message, we must
// first half-close the connection, otherwise it could happen that they
// receive a RST from our TCP stack first when we receive further data
// We only send the "close notify" alert if libssl can write to the
// socket at this moment. All the other data has been already written,
// though, and the client will receive a TCP half-close as usual, so
// it's not that important if the alert actually gets through.
if (c->ssl)
(void) SSL_shutdown (c->ssl);
// Either the shutdown succeeds, in which case we set a flag so that
// we don't retry this action and wait until we get an EOF, or it fails
// and we just kill the client straight away
if (!shutdown (c->socket_fd, SHUT_WR))
c->half_closed = true;
else
client_kill (c, NULL);
}
}
static void