From b2a4d38e8c7ccee495845e6be7d36d9ec0771ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Thu, 17 Jul 2014 23:51:34 +0200 Subject: [PATCH] Implement TIME, VERSION, MOTD, LUSERS --- src/common.c | 1 + src/kike.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 72 insertions(+), 5 deletions(-) diff --git a/src/common.c b/src/common.c index 73f8e5c..4b72e39 100644 --- a/src/common.c +++ b/src/common.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include diff --git a/src/kike.c b/src/kike.c index 0082179..7632a35 100644 --- a/src/kike.c +++ b/src/kike.c @@ -514,10 +514,13 @@ enum IRC_RPL_LUSERCHANNELS = 254, IRC_RPL_LUSERME = 255, + IRC_RPL_VERSION = 351, IRC_RPL_MOTD = 372, IRC_RPL_MOTDSTART = 375, IRC_RPL_ENDOFMOTD = 376, + IRC_RPL_TIME = 391, + IRC_ERR_NOSUCHSERVER = 402, IRC_ERR_NOORIGIN = 409, IRC_ERR_UNKNOWNCOMMAND = 421, IRC_ERR_NOMOTD = 422, @@ -542,10 +545,13 @@ static const char *g_default_replies[] = [IRC_RPL_LUSERCHANNELS] = "%d :channels formed", [IRC_RPL_LUSERME] = ":I have %d clients and %d servers", + [IRC_RPL_VERSION] = "%s.%d %s :%s", [IRC_RPL_MOTD] = ":- %s", [IRC_RPL_MOTDSTART] = ":- %s Message of the day - ", [IRC_RPL_ENDOFMOTD] = ":End of MOTD command", + [IRC_RPL_TIME] = "%s :%s", + [IRC_ERR_NOSUCHSERVER] = "%s :No such server", [IRC_ERR_NOORIGIN] = ":No origin specified", [IRC_ERR_UNKNOWNCOMMAND] = "%s: Unknown command", [IRC_ERR_NOMOTD] = ":MOTD File is missing", @@ -625,6 +631,12 @@ irc_send_lusers (struct client *c) } static bool +irc_is_this_me (struct server_context *ctx, const char *target) +{ + return !fnmatch (target, ctx->server_name, 0); +} + +static void irc_try_finish_registration (struct client *c) { struct server_context *ctx = c->ctx; @@ -737,17 +749,66 @@ irc_handle_user (const struct irc_message *msg, struct client *c) irc_try_finish_registration (c); } +static void +irc_handle_lusers (const struct irc_message *msg, struct client *c) +{ + if (msg->params.len > 1 && !irc_is_this_me (c->ctx, msg->params.vector[1])) + { + irc_send_reply (c, IRC_ERR_NOSUCHSERVER, msg->params.vector[1]); + return; + } + else + irc_send_lusers (c); + +} + +static void +irc_handle_motd (const struct irc_message *msg, struct client *c) +{ + if (msg->params.len > 0 && !irc_is_this_me (c->ctx, msg->params.vector[0])) + irc_send_reply (c, IRC_ERR_NOSUCHSERVER, msg->params.vector[0]); + else + irc_send_motd (c); +} + static void irc_handle_ping (const struct irc_message *msg, struct client *c) { // XXX: the RFC is pretty incomprehensible about the exact usage - if (msg->params.len < 1) + if (msg->params.len > 1 && !irc_is_this_me (c->ctx, msg->params.vector[1])) + irc_send_reply (c, IRC_ERR_NOSUCHSERVER, msg->params.vector[1]); + else if (msg->params.len < 1) irc_send_reply (c, IRC_ERR_NOORIGIN); else irc_send (c, ":%s PONG :%s", c->ctx->server_name, msg->params.vector[0]); } +static void +irc_handle_time (const struct irc_message *msg, struct client *c) +{ + if (msg->params.len > 0 && !irc_is_this_me (c->ctx, msg->params.vector[0])) + irc_send_reply (c, IRC_ERR_NOSUCHSERVER, msg->params.vector[0]); + else + { + char buf[32]; + time_t now = time (NULL); + struct tm tm; + strftime (buf, sizeof buf, "%a %b %d %Y %T", localtime_r (&now, &tm)); + irc_send_reply (c, IRC_RPL_TIME, c->ctx->server_name, buf); + } +} + +static void +irc_handle_version (const struct irc_message *msg, struct client *c) +{ + if (msg->params.len > 0 && !irc_is_this_me (c->ctx, msg->params.vector[0])) + irc_send_reply (c, IRC_ERR_NOSUCHSERVER, msg->params.vector[0]); + else + irc_send_reply (c, IRC_RPL_VERSION, PROGRAM_VERSION, g_debug_mode, + c->ctx->server_name, PROGRAM_NAME " " PROGRAM_VERSION); +} + // ----------------------------------------------------------------------------- struct irc_command @@ -760,13 +821,18 @@ struct irc_command static void irc_register_handlers (struct server_context *ctx) { + // TODO: add an index for IRC_ERR_NOSUCHSERVER validation? static const struct irc_command message_handlers[] = { - { "PASS", false, irc_handle_pass }, - { "NICK", false, irc_handle_nick }, - { "USER", false, irc_handle_user }, + { "PASS", false, irc_handle_pass }, + { "NICK", false, irc_handle_nick }, + { "USER", false, irc_handle_user }, - { "PING", true, irc_handle_ping } + { "LUSERS", true, irc_handle_lusers }, + { "MOTD", true, irc_handle_motd }, + { "PING", true, irc_handle_ping }, + { "TIME", true, irc_handle_time }, + { "VERSION", true, irc_handle_version }, }; for (size_t i = 0; i < N_ELEMENTS (message_handlers); i++)