diff options
Diffstat (limited to 'handle.c')
| -rw-r--r-- | handle.c | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/handle.c b/handle.c new file mode 100644 index 0000000..79a3b9a --- /dev/null +++ b/handle.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2026 Nakidai Perumenei <nakidai at disroot dot org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ircd.h" + +#include <stddef.h> +#include <stdio.h> +#include <string.h> + + +#define ensure(cond, iffalse, doexit) if (!(cond)) { iffalse; if (doexit >= 0) return doexit; } + +static int +nick(struct Message *msg, struct Peer *peer) +{ + ensure(msg->params[0] && msg->params[0], writef( + peer->fd, + ":%s 431 %s :No nickname given", + hostname, + getnick(peer) + ), 0); + + user_reg(peer, msg->params[0], NULL, NULL); + + return 0; +} + +static int +privmsg(struct Message *msg, struct Peer *peer) +{ + size_t i; + + ensure(peer->type, writef( + peer->fd, + ":%s 451 %s :You have not registered", + hostname, + getnick(peer) + ), 0); + ensure(msg->params[0] && *msg->params[0], writef( + peer->fd, + ":%s 411 %s :No recipient given (PRIVMSG)", + hostname, + getnick(peer) + ), 0); + ensure(msg->params[1] && *msg->params[1], writef( + peer->fd, + ":%s 412 %s :No text to send", + hostname, + getnick(peer) + ), 0); + + /* TODO: implement channels */ + ensure(!strchr("!+#&", *msg->params[0]), writef( + peer->fd, + ":%s 421 %s :Channels are not supported yet", + hostname, + getnick(peer) + ), 0); + + /* TODO: implement server-to-server communication */ + for (i = 0; i < PEERS_MAX; ++i) + if (peers[i].type == CLIENT && !strcmp(peers[i].nick, msg->params[0])) + writef( + peers[i].fd, + ":%s!%s@%s PRIVMSG %s :%s", + peer->nick, + peer->user, + peer->host, + peer->nick, + msg->params[1] + ); + return 0; +} + +static int +quit(struct Message *msg, struct Peer *peer) +{ + return 1; +} + +static int +user(struct Message *msg, struct Peer *peer) +{ + size_t i; + + ensure(!peer->type, writef( + peer->fd, + ":%s 462 %s :Unauthorized command (already registered)", + hostname, + getnick(peer) + ), 0); + for (i = 0; i < 4; ++i) + ensure(msg->params[i] && *msg->params[i], writef( + peer->fd, + ":%s 461 %s %s :Not enough parameters", + hostname, + getnick(peer), + msg->command + ), 0); + + user_reg(peer, NULL, msg->params[0], msg->params[3]); + + return 0; +} + +static int +default_handler(struct Message *msg, struct Peer *peer) +{ + ensure(peer->type, 0, 0); + + writef(peer->fd, ":%s 421 %s %s :Unknown command", hostname, getnick(peer), msg->command); + return 0; +} + +static struct Handler { + const char *name; + Handler *handler; +} handlers[] = +{ + { "nick", nick }, + { "privmsg", privmsg }, + { "quit", quit }, + { "user", user }, +}; + +Handler * +find(const char *command) +{ + struct Handler *l, *m, *r; + int res; + + l = handlers; + r = handlers + lengthof(handlers) - 1; + while (l <= r) + { + m = l + (r - l) / 2; + res = strcmp(command, m->name); + if (res > 0) + l = ++m; + else if (res < 0) + r = --m; + else + return m->handler; + } + + return default_handler; +} |