kike: implement WHOWAS
This commit is contained in:
parent
17be991dce
commit
ba14a30c0a
|
@ -17,6 +17,7 @@
|
||||||
311 IRC_RPL_WHOISUSER "%s %s %s * :%s"
|
311 IRC_RPL_WHOISUSER "%s %s %s * :%s"
|
||||||
312 IRC_RPL_WHOISSERVER "%s %s :%s"
|
312 IRC_RPL_WHOISSERVER "%s %s :%s"
|
||||||
313 IRC_RPL_WHOISOPERATOR "%s :is an IRC operator"
|
313 IRC_RPL_WHOISOPERATOR "%s :is an IRC operator"
|
||||||
|
314 IRC_RPL_WHOWASUSER "%s %s %s * :%s"
|
||||||
315 IRC_RPL_ENDOFWHO "%s :End of WHO list"
|
315 IRC_RPL_ENDOFWHO "%s :End of WHO list"
|
||||||
317 IRC_RPL_WHOISIDLE "%s %d :seconds idle"
|
317 IRC_RPL_WHOISIDLE "%s %d :seconds idle"
|
||||||
318 IRC_RPL_ENDOFWHOIS "%s :End of WHOIS list"
|
318 IRC_RPL_ENDOFWHOIS "%s :End of WHOIS list"
|
||||||
|
@ -39,6 +40,7 @@
|
||||||
366 IRC_RPL_ENDOFNAMES "%s :End of NAMES list"
|
366 IRC_RPL_ENDOFNAMES "%s :End of NAMES list"
|
||||||
367 IRC_RPL_BANLIST "%s %s"
|
367 IRC_RPL_BANLIST "%s %s"
|
||||||
368 IRC_RPL_ENDOFBANLIST "%s :End of channel ban list"
|
368 IRC_RPL_ENDOFBANLIST "%s :End of channel ban list"
|
||||||
|
369 IRC_RPL_ENDOFWHOWAS "%s :End of WHOWAS"
|
||||||
372 IRC_RPL_MOTD ":- %s"
|
372 IRC_RPL_MOTD ":- %s"
|
||||||
375 IRC_RPL_MOTDSTART ":- %s Message of the day - "
|
375 IRC_RPL_MOTDSTART ":- %s Message of the day - "
|
||||||
376 IRC_RPL_ENDOFMOTD ":End of MOTD command"
|
376 IRC_RPL_ENDOFMOTD ":End of MOTD command"
|
||||||
|
@ -47,6 +49,7 @@
|
||||||
402 IRC_ERR_NOSUCHSERVER "%s :No such server"
|
402 IRC_ERR_NOSUCHSERVER "%s :No such server"
|
||||||
403 IRC_ERR_NOSUCHCHANNEL "%s :No such channel"
|
403 IRC_ERR_NOSUCHCHANNEL "%s :No such channel"
|
||||||
404 IRC_ERR_CANNOTSENDTOCHAN "%s :Cannot send to channel"
|
404 IRC_ERR_CANNOTSENDTOCHAN "%s :Cannot send to channel"
|
||||||
|
406 IRC_ERR_WASNOSUCHNICK "%s :There was no such nickname"
|
||||||
409 IRC_ERR_NOORIGIN ":No origin specified"
|
409 IRC_ERR_NOORIGIN ":No origin specified"
|
||||||
410 IRC_ERR_INVALIDCAPCMD "%s :%s"
|
410 IRC_ERR_INVALIDCAPCMD "%s :%s"
|
||||||
411 IRC_ERR_NORECIPIENT ":No recipient given (%s)"
|
411 IRC_ERR_NORECIPIENT ":No recipient given (%s)"
|
||||||
|
|
89
kike.c
89
kike.c
|
@ -535,6 +535,37 @@ channel_user_count (const struct channel *chan)
|
||||||
|
|
||||||
// --- IRC server context ------------------------------------------------------
|
// --- IRC server context ------------------------------------------------------
|
||||||
|
|
||||||
|
struct whowas_info
|
||||||
|
{
|
||||||
|
char *nickname; ///< IRC nickname
|
||||||
|
char *username; ///< IRC username
|
||||||
|
char *realname; ///< IRC realname
|
||||||
|
char *hostname; ///< Hostname shown to the network
|
||||||
|
};
|
||||||
|
|
||||||
|
struct whowas_info *
|
||||||
|
whowas_info_new (struct client *c)
|
||||||
|
{
|
||||||
|
struct whowas_info *self = xmalloc (sizeof *self);
|
||||||
|
self->nickname = xstrdup (c->nickname);
|
||||||
|
self->username = xstrdup (c->username);
|
||||||
|
self->realname = xstrdup (c->realname);
|
||||||
|
self->hostname = xstrdup (c->hostname);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
whowas_info_destroy (struct whowas_info *self)
|
||||||
|
{
|
||||||
|
free (self->nickname);
|
||||||
|
free (self->username);
|
||||||
|
free (self->realname);
|
||||||
|
free (self->hostname);
|
||||||
|
free (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
struct server_context
|
struct server_context
|
||||||
{
|
{
|
||||||
int *listen_fds; ///< Listening socket FD's
|
int *listen_fds; ///< Listening socket FD's
|
||||||
|
@ -550,6 +581,8 @@ struct server_context
|
||||||
struct str_map handlers; ///< Message handlers
|
struct str_map handlers; ///< Message handlers
|
||||||
struct str_map cap_handlers; ///< CAP message handlers
|
struct str_map cap_handlers; ///< CAP message handlers
|
||||||
|
|
||||||
|
struct str_map whowas; ///< WHOWAS registry
|
||||||
|
|
||||||
struct poller poller; ///< Manages polled description
|
struct poller poller; ///< Manages polled description
|
||||||
struct poller_timer quit_timer; ///< Quit timeout timer
|
struct poller_timer quit_timer; ///< Quit timeout timer
|
||||||
bool quitting; ///< User requested quitting
|
bool quitting; ///< User requested quitting
|
||||||
|
@ -589,6 +622,10 @@ server_context_init (struct server_context *self)
|
||||||
str_map_init (&self->cap_handlers);
|
str_map_init (&self->cap_handlers);
|
||||||
self->cap_handlers.key_xfrm = irc_strxfrm;
|
self->cap_handlers.key_xfrm = irc_strxfrm;
|
||||||
|
|
||||||
|
str_map_init (&self->whowas);
|
||||||
|
self->whowas.key_xfrm = irc_strxfrm;
|
||||||
|
self->whowas.free = (void (*) (void *)) whowas_info_destroy;
|
||||||
|
|
||||||
poller_init (&self->poller);
|
poller_init (&self->poller);
|
||||||
poller_timer_init (&self->quit_timer, &self->poller);
|
poller_timer_init (&self->quit_timer, &self->poller);
|
||||||
self->quit_timer.dispatcher = on_irc_quit_timeout;
|
self->quit_timer.dispatcher = on_irc_quit_timeout;
|
||||||
|
@ -638,6 +675,7 @@ server_context_free (struct server_context *self)
|
||||||
str_map_free (&self->channels);
|
str_map_free (&self->channels);
|
||||||
str_map_free (&self->handlers);
|
str_map_free (&self->handlers);
|
||||||
str_map_free (&self->cap_handlers);
|
str_map_free (&self->cap_handlers);
|
||||||
|
str_map_free (&self->whowas);
|
||||||
poller_free (&self->poller);
|
poller_free (&self->poller);
|
||||||
|
|
||||||
str_vector_free (&self->motd);
|
str_vector_free (&self->motd);
|
||||||
|
@ -784,6 +822,15 @@ client_send (struct client *c, const char *format, ...)
|
||||||
str_free (&tmp);
|
str_free (&tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
client_add_to_whowas (struct client *c)
|
||||||
|
{
|
||||||
|
// Only keeping one entry for each nickname
|
||||||
|
// TODO: make sure this list doesn't get too long, for example by
|
||||||
|
// putting them in a linked list ordered by time
|
||||||
|
str_map_set (&c->ctx->whowas, c->nickname, whowas_info_new (c));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
client_unregister (struct client *c, const char *reason)
|
client_unregister (struct client *c, const char *reason)
|
||||||
{
|
{
|
||||||
|
@ -808,6 +855,8 @@ client_unregister (struct client *c, const char *reason)
|
||||||
irc_channel_destroy_if_empty (c->ctx, chan);
|
irc_channel_destroy_if_empty (c->ctx, chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
client_add_to_whowas (c);
|
||||||
|
|
||||||
str_map_set (&c->ctx->users, c->nickname, NULL);
|
str_map_set (&c->ctx->users, c->nickname, NULL);
|
||||||
free (c->nickname);
|
free (c->nickname);
|
||||||
c->nickname = NULL;
|
c->nickname = NULL;
|
||||||
|
@ -1126,6 +1175,8 @@ irc_try_finish_registration (struct client *c)
|
||||||
client_send (c, ":%s NOTICE %s :"
|
client_send (c, ":%s NOTICE %s :"
|
||||||
"Your SSL client certificate fingerprint is %s",
|
"Your SSL client certificate fingerprint is %s",
|
||||||
ctx->server_name, c->nickname, c->ssl_cert_fingerprint);
|
ctx->server_name, c->nickname, c->ssl_cert_fingerprint);
|
||||||
|
|
||||||
|
str_map_set (&ctx->whowas, c->nickname, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -1328,6 +1379,8 @@ irc_handle_nick (const struct irc_message *msg, struct client *c)
|
||||||
|
|
||||||
if (c->registered)
|
if (c->registered)
|
||||||
{
|
{
|
||||||
|
client_add_to_whowas (c);
|
||||||
|
|
||||||
char *message = xstrdup_printf (":%s!%s@%s NICK :%s",
|
char *message = xstrdup_printf (":%s!%s@%s NICK :%s",
|
||||||
c->nickname, c->username, c->hostname, nickname);
|
c->nickname, c->username, c->hostname, nickname);
|
||||||
irc_send_to_roommates (c, message);
|
irc_send_to_roommates (c, message);
|
||||||
|
@ -2306,8 +2359,8 @@ static void
|
||||||
irc_send_whois_reply (struct client *c, const struct client *target)
|
irc_send_whois_reply (struct client *c, const struct client *target)
|
||||||
{
|
{
|
||||||
const char *nick = target->nickname;
|
const char *nick = target->nickname;
|
||||||
irc_send_reply (c, IRC_RPL_WHOISUSER, nick, target->username,
|
irc_send_reply (c, IRC_RPL_WHOISUSER, nick,
|
||||||
target->hostname, target->realname);
|
target->username, target->hostname, target->realname);
|
||||||
irc_send_reply (c, IRC_RPL_WHOISSERVER, nick, target->ctx->server_name,
|
irc_send_reply (c, IRC_RPL_WHOISSERVER, nick, target->ctx->server_name,
|
||||||
str_map_find (&c->ctx->config, "server_info"));
|
str_map_find (&c->ctx->config, "server_info"));
|
||||||
if (target->mode & IRC_USER_MODE_OPERATOR)
|
if (target->mode & IRC_USER_MODE_OPERATOR)
|
||||||
|
@ -2386,6 +2439,37 @@ irc_handle_whois (const struct irc_message *msg, struct client *c)
|
||||||
str_vector_free (&masks);
|
str_vector_free (&masks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
irc_handle_whowas (const struct irc_message *msg, struct client *c)
|
||||||
|
{
|
||||||
|
if (msg->params.len < 1)
|
||||||
|
RETURN_WITH_REPLY (c, IRC_ERR_NEEDMOREPARAMS, msg->command);
|
||||||
|
if (msg->params.len > 2 && !irc_is_this_me (c->ctx, msg->params.vector[2]))
|
||||||
|
RETURN_WITH_REPLY (c, IRC_ERR_NOSUCHSERVER, msg->params.vector[2]);
|
||||||
|
// The "count" parameter is ignored, we only store one entry for a nick
|
||||||
|
|
||||||
|
struct str_vector nicks;
|
||||||
|
str_vector_init (&nicks);
|
||||||
|
split_str_ignore_empty (msg->params.vector[0], ',', &nicks);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < nicks.len; i++)
|
||||||
|
{
|
||||||
|
const char *nick = nicks.vector[i];
|
||||||
|
struct whowas_info *info = str_map_find (&c->ctx->whowas, nick);
|
||||||
|
if (!info)
|
||||||
|
irc_send_reply (c, IRC_ERR_WASNOSUCHNICK, nick);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
irc_send_reply (c, IRC_RPL_WHOWASUSER, nick,
|
||||||
|
info->username, info->hostname, info->realname);
|
||||||
|
irc_send_reply (c, IRC_RPL_WHOISSERVER, nick, c->ctx->server_name,
|
||||||
|
str_map_find (&c->ctx->config, "server_info"));
|
||||||
|
}
|
||||||
|
irc_send_reply (c, IRC_RPL_ENDOFWHOWAS, nick);
|
||||||
|
}
|
||||||
|
str_vector_free (&nicks);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
irc_send_rpl_topic (struct client *c, struct channel *chan)
|
irc_send_rpl_topic (struct client *c, struct channel *chan)
|
||||||
{
|
{
|
||||||
|
@ -2812,6 +2896,7 @@ irc_register_handlers (struct server_context *ctx)
|
||||||
{ "NAMES", true, irc_handle_names },
|
{ "NAMES", true, irc_handle_names },
|
||||||
{ "WHO", true, irc_handle_who },
|
{ "WHO", true, irc_handle_who },
|
||||||
{ "WHOIS", true, irc_handle_whois },
|
{ "WHOIS", true, irc_handle_whois },
|
||||||
|
{ "WHOWAS", true, irc_handle_whowas },
|
||||||
{ "ISON", true, irc_handle_ison },
|
{ "ISON", true, irc_handle_ison },
|
||||||
|
|
||||||
{ "KILL", true, irc_handle_kill },
|
{ "KILL", true, irc_handle_kill },
|
||||||
|
|
Loading…
Reference in New Issue