diff options
| author | Nakidai <nakidai@disroot.org> | 2026-01-06 04:01:24 +0300 |
|---|---|---|
| committer | Nakidai <nakidai@disroot.org> | 2026-01-06 04:01:24 +0300 |
| commit | 833c53b1ad3338677056445c32c490cac0a08875 (patch) | |
| tree | 24e60715c46ff89c26c5efc254e036b84aebcb13 /handle.c | |
| parent | 78426afe18d9ce730a4d92033ca261f9b2f173a0 (diff) | |
| download | libreircd-833c53b1ad3338677056445c32c490cac0a08875.tar.gz libreircd-833c53b1ad3338677056445c32c490cac0a08875.zip | |
Add basic channels
Though they don't have modes, and JOIN/PART must be able to parse comma separated list of channels
Diffstat (limited to 'handle.c')
| -rw-r--r-- | handle.c | 150 |
1 files changed, 106 insertions, 44 deletions
diff --git a/handle.c b/handle.c index 79a3b9a..61b34f7 100644 --- a/handle.c +++ b/handle.c @@ -20,18 +20,46 @@ #include <stdio.h> #include <string.h> +#include <err.h> -#define ensure(cond, iffalse, doexit) if (!(cond)) { iffalse; if (doexit >= 0) return doexit; } + +static int +join(struct Message *msg, struct Peer *peer) +{ + size_t i, j; + + /* TODO: support comma separated list of channels, keys */ + ensure(peer->type, reply(peer, 451), 0); + ensure(msg->params[0] && *msg->params[0], reply(peer, 461), 0); + ensure(peer->channels_c != lengthof(peer->channels), reply(peer, 405, msg->params[0]), 0) + ensure(*msg->params[0] == '#', reply(peer, 403, msg->params[0]), 0); + + for (i = 0; i < channels_c; ++i) + { + if (strcmp(channels[i].name, msg->params[0])) + continue; + + for (j = 0; j < channels[i].users_c; ++j) + ensure( + strcmp(channels[i].users[j]->nick, peer->nick), + (void)0, + 0 + ); + + ensure(!channel_join(&channels[i], peer), reply(peer, 471), 0); + return 0; + } + + channels[channels_c] = (struct Channel){0}; + strlcpy(channels[channels_c].name, msg->params[0], sizeof(channels->name)); + channel_join(&channels[channels_c++], peer); + return 0; +} 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); + ensure(msg->params[0] && msg->params[0], reply(peer, 431), 0); user_reg(peer, msg->params[0], NULL, NULL); @@ -39,31 +67,43 @@ nick(struct Message *msg, struct Peer *peer) } static int +part(struct Message *msg, struct Peer *peer) +{ + size_t i; + + ensure(peer->type, reply(peer, 451), 0); + ensure(msg->params[0] && *msg->params[0], reply(peer, 461), 0); + + for (i = 0; i < peer->channels_c; ++i) + if (!strcmp(peer->channels[i]->name, msg->params[0])) + break; + ensure(i != peer->channels_c, reply(peer, 442, msg->params[0]), 0) + + writechanf( + 0, + peer->channels[i], + ":%s!%s@%s PART %s :%s", + getnick(peer), + peer->user, + peer->host, + msg->params[0], + msg->params[1] ? msg->params[1] : getnick(peer) + ); + channel_exit(peer->channels[i], peer); + 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); + ensure(peer->type, reply(peer, 451), 0); + ensure(msg->params[0] && *msg->params[0], reply(peer, 411), 0); + ensure(msg->params[1] && *msg->params[1], reply(peer, 412), 0); /* TODO: implement channels */ - ensure(!strchr("!+#&", *msg->params[0]), writef( + ensure(!strchr("!+&", *msg->params[0]), writef( peer->fd, ":%s 421 %s :Channels are not supported yet", hostname, @@ -71,17 +111,48 @@ privmsg(struct Message *msg, struct Peer *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])) + switch (*msg->params[0]) + { + case '#': + { + for (i = 0; i < channels_c; ++i) + if (!strcmp(channels[i].name, msg->params[0])) + { + writechanf( + peer, + &channels[i], + ":%s!%s@%s PRIVMSG %s :%s", + peer->nick, + peer->user, + peer->host, + msg->params[0], + msg->params[1] + ); + break; + } + ensure(i != channels_c, reply(peer, 401, msg->params[0]), 0); + } break; + default: + { + for (i = 0; i < peers_c; ++i) + { + if (peers[i].type != CLIENT || strcmp(peers[i].nick, msg->params[0])) + continue; + writef( peers[i].fd, ":%s!%s@%s PRIVMSG %s :%s", peer->nick, peer->user, peer->host, - peer->nick, + msg->params[0], msg->params[1] ); + break; + } + ensure(i != peers_c, reply(peer, 401, msg->params[0]), 0); + } break; + } return 0; } @@ -96,20 +167,9 @@ 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); + ensure(!peer->type, reply(peer, 462), 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); + ensure(msg->params[i] && *msg->params[i], reply(peer, 461), 0); user_reg(peer, NULL, msg->params[0], msg->params[3]); @@ -119,9 +179,9 @@ user(struct Message *msg, struct Peer *peer) static int default_handler(struct Message *msg, struct Peer *peer) { - ensure(peer->type, 0, 0); + ensure(peer->type, (void)0, 0); - writef(peer->fd, ":%s 421 %s %s :Unknown command", hostname, getnick(peer), msg->command); + reply(peer, 421, msg->command); return 0; } @@ -130,7 +190,9 @@ static struct Handler { Handler *handler; } handlers[] = { + { "join", join }, { "nick", nick }, + { "part", part }, { "privmsg", privmsg }, { "quit", quit }, { "user", user }, |