Implement TIME, VERSION, MOTD, LUSERS

This commit is contained in:
Přemysl Eric Janouch 2014-07-17 23:51:34 +02:00
parent 86e3ae951e
commit b2a4d38e8c
2 changed files with 72 additions and 5 deletions

View File

@ -43,6 +43,7 @@
#include <regex.h> #include <regex.h>
#include <libgen.h> #include <libgen.h>
#include <syslog.h> #include <syslog.h>
#include <fnmatch.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/types.h> #include <sys/types.h>

View File

@ -514,10 +514,13 @@ enum
IRC_RPL_LUSERCHANNELS = 254, IRC_RPL_LUSERCHANNELS = 254,
IRC_RPL_LUSERME = 255, IRC_RPL_LUSERME = 255,
IRC_RPL_VERSION = 351,
IRC_RPL_MOTD = 372, IRC_RPL_MOTD = 372,
IRC_RPL_MOTDSTART = 375, IRC_RPL_MOTDSTART = 375,
IRC_RPL_ENDOFMOTD = 376, IRC_RPL_ENDOFMOTD = 376,
IRC_RPL_TIME = 391,
IRC_ERR_NOSUCHSERVER = 402,
IRC_ERR_NOORIGIN = 409, IRC_ERR_NOORIGIN = 409,
IRC_ERR_UNKNOWNCOMMAND = 421, IRC_ERR_UNKNOWNCOMMAND = 421,
IRC_ERR_NOMOTD = 422, IRC_ERR_NOMOTD = 422,
@ -542,10 +545,13 @@ static const char *g_default_replies[] =
[IRC_RPL_LUSERCHANNELS] = "%d :channels formed", [IRC_RPL_LUSERCHANNELS] = "%d :channels formed",
[IRC_RPL_LUSERME] = ":I have %d clients and %d servers", [IRC_RPL_LUSERME] = ":I have %d clients and %d servers",
[IRC_RPL_VERSION] = "%s.%d %s :%s",
[IRC_RPL_MOTD] = ":- %s", [IRC_RPL_MOTD] = ":- %s",
[IRC_RPL_MOTDSTART] = ":- %s Message of the day - ", [IRC_RPL_MOTDSTART] = ":- %s Message of the day - ",
[IRC_RPL_ENDOFMOTD] = ":End of MOTD command", [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_NOORIGIN] = ":No origin specified",
[IRC_ERR_UNKNOWNCOMMAND] = "%s: Unknown command", [IRC_ERR_UNKNOWNCOMMAND] = "%s: Unknown command",
[IRC_ERR_NOMOTD] = ":MOTD File is missing", [IRC_ERR_NOMOTD] = ":MOTD File is missing",
@ -625,6 +631,12 @@ irc_send_lusers (struct client *c)
} }
static bool 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) irc_try_finish_registration (struct client *c)
{ {
struct server_context *ctx = c->ctx; 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); 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 static void
irc_handle_ping (const struct irc_message *msg, struct client *c) irc_handle_ping (const struct irc_message *msg, struct client *c)
{ {
// XXX: the RFC is pretty incomprehensible about the exact usage // 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); irc_send_reply (c, IRC_ERR_NOORIGIN);
else else
irc_send (c, ":%s PONG :%s", irc_send (c, ":%s PONG :%s",
c->ctx->server_name, msg->params.vector[0]); 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 struct irc_command
@ -760,13 +821,18 @@ struct irc_command
static void static void
irc_register_handlers (struct server_context *ctx) irc_register_handlers (struct server_context *ctx)
{ {
// TODO: add an index for IRC_ERR_NOSUCHSERVER validation?
static const struct irc_command message_handlers[] = static const struct irc_command message_handlers[] =
{ {
{ "PASS", false, irc_handle_pass }, { "PASS", false, irc_handle_pass },
{ "NICK", false, irc_handle_nick }, { "NICK", false, irc_handle_nick },
{ "USER", false, irc_handle_user }, { "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++) for (size_t i = 0; i < N_ELEMENTS (message_handlers); i++)