kike: fix quitting + code shuffling
This commit is contained in:
parent
abc0e4f821
commit
d25377599c
70
kike.c
70
kike.c
@ -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)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user