kike: shuffle things around
No functional change, I hope.
This commit is contained in:
parent
9bfdc741fe
commit
a5953147c3
341
src/kike.c
341
src/kike.c
@ -490,13 +490,6 @@ server_context_free (struct server_context *self)
|
|||||||
catclose (self->catalog);
|
catclose (self->catalog);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Main program ------------------------------------------------------------
|
|
||||||
|
|
||||||
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 *, const char *);
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
irc_try_finish_quit (struct server_context *ctx)
|
irc_try_finish_quit (struct server_context *ctx)
|
||||||
{
|
{
|
||||||
@ -504,29 +497,82 @@ irc_try_finish_quit (struct server_context *ctx)
|
|||||||
ctx->polling = false;
|
ctx->polling = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static const char *
|
||||||
client_kill (struct client *c, const char *reason)
|
irc_get_text (struct server_context *ctx, int id, const char *def)
|
||||||
{
|
{
|
||||||
client_unregister (c, reason ? reason : "Client exited");
|
if (!soft_assert (def != NULL))
|
||||||
|
def = "";
|
||||||
struct server_context *ctx = c->ctx;
|
if (ctx->catalog == (nl_catd) -1)
|
||||||
ssize_t i = poller_find_by_fd (&ctx->poller, c->socket_fd);
|
return def;
|
||||||
if (i != -1)
|
return catgets (ctx->catalog, 1, id, def);
|
||||||
poller_remove_at_index (&ctx->poller, i);
|
|
||||||
client_cancel_timers (c);
|
|
||||||
|
|
||||||
if (c->ssl)
|
|
||||||
(void) SSL_shutdown (c->ssl);
|
|
||||||
xclose (c->socket_fd);
|
|
||||||
c->socket_fd = -1;
|
|
||||||
client_free (c);
|
|
||||||
LIST_UNLINK (ctx->clients, c);
|
|
||||||
ctx->n_clients--;
|
|
||||||
free (c);
|
|
||||||
|
|
||||||
irc_try_finish_quit (ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Channels ----------------------------------------------------------------
|
||||||
|
|
||||||
|
static struct channel_user *
|
||||||
|
channel_get_user (const struct channel *chan, const struct client *c)
|
||||||
|
{
|
||||||
|
for (struct channel_user *iter = chan->users; iter; iter = iter->next)
|
||||||
|
if (!irc_strcmp (iter->nickname, c->nickname))
|
||||||
|
return iter;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct channel_user *
|
||||||
|
channel_add_user (struct channel *chan, const struct client *c)
|
||||||
|
{
|
||||||
|
size_t nick_len = strlen (c->nickname);
|
||||||
|
struct channel_user *link = xcalloc (1, sizeof *link + nick_len + 1);
|
||||||
|
memcpy (link->nickname, c->nickname, nick_len + 1);
|
||||||
|
LIST_PREPEND (chan->users, link);
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
channel_remove_user (struct channel *chan, struct channel_user *user)
|
||||||
|
{
|
||||||
|
LIST_UNLINK (chan->users, user);
|
||||||
|
free (user);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
channel_user_count (const struct channel *chan)
|
||||||
|
{
|
||||||
|
size_t result = 0;
|
||||||
|
for (struct channel_user *iter = chan->users; iter; iter = iter->next)
|
||||||
|
result++;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct channel *
|
||||||
|
channel_create (struct server_context *ctx, const char *name)
|
||||||
|
{
|
||||||
|
struct channel *chan = xcalloc (1, sizeof *chan);
|
||||||
|
channel_init (chan);
|
||||||
|
str_map_set (&ctx->channels, name, chan);
|
||||||
|
|
||||||
|
chan->ctx = ctx;
|
||||||
|
chan->name = xstrdup (name);
|
||||||
|
return chan;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
channel_destroy_if_empty (struct server_context *ctx, struct channel *chan)
|
||||||
|
{
|
||||||
|
if (!chan->users)
|
||||||
|
{
|
||||||
|
str_map_set (&ctx->channels, chan->name, NULL);
|
||||||
|
channel_free (chan);
|
||||||
|
free (chan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Clients -----------------------------------------------------------------
|
||||||
|
|
||||||
|
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
|
static void
|
||||||
irc_send_str (struct client *c, const struct str *s)
|
irc_send_str (struct client *c, const struct str *s)
|
||||||
{
|
{
|
||||||
@ -559,14 +605,87 @@ irc_send (struct client *c, const char *format, ...)
|
|||||||
str_free (&tmp);
|
str_free (&tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static void
|
||||||
irc_get_text (struct server_context *ctx, int id, const char *def)
|
client_send_to_roommates (struct client *c, const char *message)
|
||||||
{
|
{
|
||||||
if (!soft_assert (def != NULL))
|
struct str_map targets;
|
||||||
def = "";
|
str_map_init (&targets);
|
||||||
if (ctx->catalog == (nl_catd) -1)
|
targets.key_xfrm = irc_strxfrm;
|
||||||
return def;
|
|
||||||
return catgets (ctx->catalog, 1, id, def);
|
struct str_map_iter iter;
|
||||||
|
str_map_iter_init (&iter, &c->ctx->channels);
|
||||||
|
struct channel *chan;
|
||||||
|
while ((chan = str_map_iter_next (&iter)))
|
||||||
|
{
|
||||||
|
if (chan->modes & IRC_CHAN_MODE_QUIET
|
||||||
|
|| !channel_get_user (chan, c))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// When we're unregistering, the str_map_find() will return zero,
|
||||||
|
// which will prevent sending the QUIT message to ourselves.
|
||||||
|
for (struct channel_user *iter = chan->users; iter; iter = iter->next)
|
||||||
|
str_map_set (&targets, iter->nickname,
|
||||||
|
str_map_find (&c->ctx->users, iter->nickname));
|
||||||
|
}
|
||||||
|
|
||||||
|
str_map_iter_init (&iter, &targets);
|
||||||
|
struct client *target;
|
||||||
|
while ((target = str_map_iter_next (&iter)))
|
||||||
|
irc_send (target, "%s", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
client_unregister (struct client *c, const char *reason)
|
||||||
|
{
|
||||||
|
if (!c->registered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Make the user effectively non-existent
|
||||||
|
str_map_set (&c->ctx->users, c->nickname, NULL);
|
||||||
|
|
||||||
|
char *message = xstrdup_printf (":%s!%s@%s QUIT :%s",
|
||||||
|
c->nickname, c->username, c->hostname, reason);
|
||||||
|
client_send_to_roommates (c, message);
|
||||||
|
free (message);
|
||||||
|
|
||||||
|
struct str_map_iter iter;
|
||||||
|
str_map_iter_init (&iter, &c->ctx->channels);
|
||||||
|
struct channel *chan;
|
||||||
|
while ((chan = str_map_iter_next (&iter)))
|
||||||
|
{
|
||||||
|
struct channel_user *user;
|
||||||
|
if (!(user = channel_get_user (chan, c)))
|
||||||
|
continue;
|
||||||
|
channel_remove_user (chan, user);
|
||||||
|
channel_destroy_if_empty (c->ctx, chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
free (c->nickname);
|
||||||
|
c->nickname = NULL;
|
||||||
|
c->registered = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
client_kill (struct client *c, const char *reason)
|
||||||
|
{
|
||||||
|
client_unregister (c, reason ? reason : "Client exited");
|
||||||
|
|
||||||
|
struct server_context *ctx = c->ctx;
|
||||||
|
ssize_t i = poller_find_by_fd (&ctx->poller, c->socket_fd);
|
||||||
|
if (i != -1)
|
||||||
|
poller_remove_at_index (&ctx->poller, i);
|
||||||
|
client_cancel_timers (c);
|
||||||
|
|
||||||
|
if (c->ssl)
|
||||||
|
(void) SSL_shutdown (c->ssl);
|
||||||
|
xclose (c->socket_fd);
|
||||||
|
c->socket_fd = -1;
|
||||||
|
client_free (c);
|
||||||
|
LIST_UNLINK (ctx->clients, c);
|
||||||
|
ctx->n_clients--;
|
||||||
|
free (c);
|
||||||
|
|
||||||
|
irc_try_finish_quit (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -587,6 +706,26 @@ irc_close_link (struct client *c, const char *reason)
|
|||||||
client_set_kill_timer (c);
|
client_set_kill_timer (c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
client_in_mask_list (const struct client *c, const struct str_vector *mask)
|
||||||
|
{
|
||||||
|
struct str client;
|
||||||
|
str_init (&client);
|
||||||
|
str_append_printf (&client, "%s!%s@%s",
|
||||||
|
c->nickname, c->username, c->hostname);
|
||||||
|
irc_strxfrm (client.str, client.str, client.len);
|
||||||
|
bool result = false;
|
||||||
|
for (size_t i = 0; i < mask->len; i++)
|
||||||
|
// FIXME: irc_strxfrm() for the mask (save in canonical format?)
|
||||||
|
if (!fnmatch (client.str, mask->vector[i], 0))
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
str_free (&client);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// --- Timers ------------------------------------------------------------------
|
// --- Timers ------------------------------------------------------------------
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -814,132 +953,6 @@ irc_send_motd (struct client *c)
|
|||||||
irc_send_reply (c, IRC_RPL_ENDOFMOTD);
|
irc_send_reply (c, IRC_RPL_ENDOFMOTD);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct channel_user *
|
|
||||||
channel_get_user (const struct channel *chan, const struct client *c)
|
|
||||||
{
|
|
||||||
for (struct channel_user *iter = chan->users; iter; iter = iter->next)
|
|
||||||
if (!irc_strcmp (iter->nickname, c->nickname))
|
|
||||||
return iter;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct channel_user *
|
|
||||||
channel_add_user (struct channel *chan, const struct client *c)
|
|
||||||
{
|
|
||||||
size_t nick_len = strlen (c->nickname);
|
|
||||||
struct channel_user *link = xcalloc (1, sizeof *link + nick_len + 1);
|
|
||||||
memcpy (link->nickname, c->nickname, nick_len + 1);
|
|
||||||
LIST_PREPEND (chan->users, link);
|
|
||||||
return link;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
channel_remove_user (struct channel *chan, struct channel_user *user)
|
|
||||||
{
|
|
||||||
LIST_UNLINK (chan->users, user);
|
|
||||||
free (user);
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t
|
|
||||||
channel_user_count (const struct channel *chan)
|
|
||||||
{
|
|
||||||
size_t result = 0;
|
|
||||||
for (struct channel_user *iter = chan->users; iter; iter = iter->next)
|
|
||||||
result++;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
channel_destroy_if_empty (struct server_context *ctx, struct channel *chan)
|
|
||||||
{
|
|
||||||
if (!chan->users)
|
|
||||||
{
|
|
||||||
str_map_set (&ctx->channels, chan->name, NULL);
|
|
||||||
channel_free (chan);
|
|
||||||
free (chan);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
client_in_mask_list (const struct client *c, const struct str_vector *mask)
|
|
||||||
{
|
|
||||||
struct str client;
|
|
||||||
str_init (&client);
|
|
||||||
str_append_printf (&client, "%s!%s@%s",
|
|
||||||
c->nickname, c->username, c->hostname);
|
|
||||||
irc_strxfrm (client.str, client.str, client.len);
|
|
||||||
bool result = false;
|
|
||||||
for (size_t i = 0; i < mask->len; i++)
|
|
||||||
// FIXME: irc_strxfrm() for the mask (save in canonical format?)
|
|
||||||
if (!fnmatch (client.str, mask->vector[i], 0))
|
|
||||||
{
|
|
||||||
result = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
str_free (&client);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
client_send_to_roommates (struct client *c, const char *message)
|
|
||||||
{
|
|
||||||
struct str_map targets;
|
|
||||||
str_map_init (&targets);
|
|
||||||
targets.key_xfrm = irc_strxfrm;
|
|
||||||
|
|
||||||
struct str_map_iter iter;
|
|
||||||
str_map_iter_init (&iter, &c->ctx->channels);
|
|
||||||
struct channel *chan;
|
|
||||||
while ((chan = str_map_iter_next (&iter)))
|
|
||||||
{
|
|
||||||
if (chan->modes & IRC_CHAN_MODE_QUIET
|
|
||||||
|| !channel_get_user (chan, c))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// When we're unregistering, the str_map_find() will return zero,
|
|
||||||
// which will prevent sending the QUIT message to ourselves.
|
|
||||||
for (struct channel_user *iter = chan->users; iter; iter = iter->next)
|
|
||||||
str_map_set (&targets, iter->nickname,
|
|
||||||
str_map_find (&c->ctx->users, iter->nickname));
|
|
||||||
}
|
|
||||||
|
|
||||||
str_map_iter_init (&iter, &targets);
|
|
||||||
struct client *target;
|
|
||||||
while ((target = str_map_iter_next (&iter)))
|
|
||||||
irc_send (target, "%s", message);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
client_unregister (struct client *c, const char *reason)
|
|
||||||
{
|
|
||||||
if (!c->registered)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Make the user effectively non-existent
|
|
||||||
str_map_set (&c->ctx->users, c->nickname, NULL);
|
|
||||||
|
|
||||||
char *message = xstrdup_printf (":%s!%s@%s QUIT :%s",
|
|
||||||
c->nickname, c->username, c->hostname, reason);
|
|
||||||
client_send_to_roommates (c, message);
|
|
||||||
free (message);
|
|
||||||
|
|
||||||
struct str_map_iter iter;
|
|
||||||
str_map_iter_init (&iter, &c->ctx->channels);
|
|
||||||
struct channel *chan;
|
|
||||||
while ((chan = str_map_iter_next (&iter)))
|
|
||||||
{
|
|
||||||
struct channel_user *user;
|
|
||||||
if (!(user = channel_get_user (chan, c)))
|
|
||||||
continue;
|
|
||||||
channel_remove_user (chan, user);
|
|
||||||
channel_destroy_if_empty (c->ctx, chan);
|
|
||||||
}
|
|
||||||
|
|
||||||
free (c->nickname);
|
|
||||||
c->nickname = NULL;
|
|
||||||
c->registered = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
irc_send_lusers (struct client *c)
|
irc_send_lusers (struct client *c)
|
||||||
{
|
{
|
||||||
@ -1539,14 +1552,8 @@ irc_try_join (struct client *c, const char *channel_name, const char *key)
|
|||||||
{
|
{
|
||||||
if (irc_validate_channel_name (channel_name) != VALIDATION_OK)
|
if (irc_validate_channel_name (channel_name) != VALIDATION_OK)
|
||||||
RETURN_WITH_REPLY (c, IRC_ERR_BADCHANMASK, channel_name);
|
RETURN_WITH_REPLY (c, IRC_ERR_BADCHANMASK, channel_name);
|
||||||
|
chan = channel_create (c->ctx, channel_name);
|
||||||
user_mode = IRC_CHAN_MODE_OPERATOR;
|
user_mode = IRC_CHAN_MODE_OPERATOR;
|
||||||
|
|
||||||
chan = xcalloc (1, sizeof *chan);
|
|
||||||
channel_init (chan);
|
|
||||||
str_map_set (&c->ctx->channels, channel_name, chan);
|
|
||||||
|
|
||||||
chan->ctx = c->ctx;
|
|
||||||
chan->name = xstrdup (channel_name);
|
|
||||||
}
|
}
|
||||||
else if (channel_get_user (chan, c))
|
else if (channel_get_user (chan, c))
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user