kike: fix quitting + code shuffling

This commit is contained in:
Přemysl Eric Janouch 2015-06-13 23:41:54 +02:00
parent abc0e4f821
commit d25377599c

70
kike.c
View File

@ -388,7 +388,8 @@ client_free (struct client *self)
str_map_free (&self->invites); str_map_free (&self->invites);
} }
static void client_close_link (struct client *, const char *); static void client_close_link (struct client *c, const char *reason);
static void client_kill (struct client *c, const char *reason);
static void client_send (struct client *, const char *, ...) static void client_send (struct client *, const char *, ...)
ATTRIBUTE_PRINTF (2, 3); ATTRIBUTE_PRINTF (2, 3);
static void client_cancel_timers (struct client *); static void client_cancel_timers (struct client *);
@ -623,8 +624,13 @@ static void
on_irc_quit_timeout (void *user_data) on_irc_quit_timeout (void *user_data)
{ {
struct server_context *ctx = user_data; struct server_context *ctx = user_data;
// Clients are closed in server_context_free() struct client *iter, *next;
ctx->polling = false; for (iter = ctx->clients; iter; iter = next)
{
next = iter->next;
// irc_initiate_quit() has already unregistered the client
client_kill (iter, "Shutting down");
}
} }
static void static void
@ -676,19 +682,9 @@ server_context_free (struct server_context *self)
free (self->listen_fds); free (self->listen_fds);
free (self->listen_events); free (self->listen_events);
hard_assert (!self->clients);
if (self->ssl_ctx) if (self->ssl_ctx)
SSL_CTX_free (self->ssl_ctx); SSL_CTX_free (self->ssl_ctx);
struct client *link, *tmp;
for (link = self->clients; link; link = tmp)
{
tmp = link->next;
// FIXME: either make sure this isn't called (which it can as of now,
// see on_irc_quit_timeout) or fix client_free() to unregister from
// the poller before closing the socket (we could also just
// set .closed = true).
client_free (link);
free (link);
}
free (self->server_name); free (self->server_name);
str_map_free (&self->users); str_map_free (&self->users);
@ -729,10 +725,6 @@ irc_initiate_quit (struct server_context *ctx)
{ {
print_status ("shutting down"); print_status ("shutting down");
for (struct client *iter = ctx->clients; iter; iter = iter->next)
if (!iter->closing_link)
client_close_link (iter, "Shutting down");
for (size_t i = 0; i < ctx->n_listen_fds; i++) for (size_t i = 0; i < ctx->n_listen_fds; i++)
{ {
xclose (ctx->listen_fds[i]); xclose (ctx->listen_fds[i]);
@ -741,6 +733,10 @@ irc_initiate_quit (struct server_context *ctx)
} }
ctx->n_listen_fds = 0; ctx->n_listen_fds = 0;
for (struct client *iter = ctx->clients; iter; iter = iter->next)
if (!iter->closing_link)
client_close_link (iter, "Shutting down");
ctx->quitting = true; ctx->quitting = true;
poller_timer_set (&ctx->quit_timer, 5000); poller_timer_set (&ctx->quit_timer, 5000);
irc_try_finish_quit (ctx); irc_try_finish_quit (ctx);
@ -888,6 +884,25 @@ client_unregister (struct client *c, const char *reason)
c->registered = false; c->registered = false;
} }
static void
client_close_link (struct client *c, const char *reason)
{
if (!soft_assert (!c->closing_link))
return;
// We push an `ERROR' message to the write buffer and let the poller send
// it, with some arbitrary timeout. The `closing_link' state makes sure
// that a/ we ignore any successive messages, and b/ that the connection
// is killed after the write buffer is transferred and emptied.
client_send (c, "ERROR :Closing Link: %s[%s] (%s)",
c->nickname ? c->nickname : "*",
c->hostname /* TODO host IP? */, reason);
c->closing_link = true;
client_unregister (c, reason);
client_set_kill_timer (c);
}
static void static void
client_kill (struct client *c, const char *reason) client_kill (struct client *c, const char *reason)
{ {
@ -917,25 +932,6 @@ client_kill (struct client *c, const char *reason)
irc_try_finish_quit (ctx); irc_try_finish_quit (ctx);
} }
static void
client_close_link (struct client *c, const char *reason)
{
if (!soft_assert (!c->closing_link))
return;
// We push an `ERROR' message to the write buffer and let the poller send
// it, with some arbitrary timeout. The `closing_link' state makes sure
// that a/ we ignore any successive messages, and b/ that the connection
// is killed after the write buffer is transferred and emptied.
client_send (c, "ERROR :Closing Link: %s[%s] (%s)",
c->nickname ? c->nickname : "*",
c->hostname /* TODO host IP? */, reason);
c->closing_link = true;
client_unregister (c, reason);
client_set_kill_timer (c);
}
static bool static bool
client_in_mask_list (const struct client *c, const struct str_vector *mask) client_in_mask_list (const struct client *c, const struct str_vector *mask)
{ {