From c660db6c36ce50e2aa1c3ec99cb62d9aaf3c0102 Mon Sep 17 00:00:00 2001 From: Test_User Date: Tue, 8 Aug 2023 03:25:57 -0400 Subject: User lists for channels and such --- client_network.c | 55 +++++++------- general_network.c | 49 +++++++++++++ network.h | 15 +++- server_network.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 274 insertions(+), 56 deletions(-) diff --git a/client_network.c b/client_network.c index bbeaec3..ca82379 100644 --- a/client_network.c +++ b/client_network.c @@ -43,8 +43,6 @@ #include "table.h" #include "tls.h" -// TODO: Lock sends (everywhere) - struct table client_network_commands = {0}; struct string client_nick = {0}; uint8_t client_connected; @@ -111,7 +109,7 @@ int client_user_handler(uint64_t argc, struct string *argv) { SENDCLIENT(STRING(":hax.irc.andrewyu.org 001 ")); SENDCLIENT(client_nick); - SENDCLIENT(STRING(" :Welcome to the RunxiIRC Network\r\n")); + SENDCLIENT(STRING(" :Welcome to the Rexnet IRC Network\r\n")); SENDCLIENT(STRING(":hax.irc.andrewyu.org 002 ")); SENDCLIENT(client_nick); SENDCLIENT(STRING(" :Your host is hax.irc.andrewyu.org, running a totally not sus IRCd\r\n")); @@ -153,7 +151,6 @@ int client_join_handler(uint64_t argc, struct string *argv) { } current_time = (uint64_t)ctime; } - snprintf(current_time_nulstr, 22, "%lu", time(NULL)); struct string channels = argv[0]; while (1) { @@ -174,6 +171,8 @@ int client_join_handler(uint64_t argc, struct string *argv) { } *channel_info = (struct channel_info){ .ts = current_time, + .topic = {.data = malloc(0), .len = 0}, + .topic_ts = 0, .modes = {.array = malloc(0), .len = 0}, .user_list = {.array = malloc(0), .len = 0}, .metadata = {.array = malloc(0), .len = 0}, @@ -181,33 +180,37 @@ int client_join_handler(uint64_t argc, struct string *argv) { set_table_index(&channel_list, channels, channel_info); } + if (channel_info->ts < current_time) + current_time = channel_info->ts; - set_table_index(&(channel_info->user_list), STRING("1HC000001"), get_table_index(user_list, STRING("1HC000001"))); // TODO: Actually add local users to that + snprintf(current_time_nulstr, 22, "%lu", current_time); SENDCLIENT(STRING(":")); SENDCLIENT(client_nick); SENDCLIENT(STRING("!e@e JOIN :")); SENDCLIENT(channels); + for (uint64_t i = 0; i < channel_info->user_list.len; i++) { + struct string user; + struct user_info *info = channel_info->user_list.array[i].ptr; + if (info) + user = info->nick; + else + user = user_list.array[i].name; + + if (i%5 != 0) { + SENDCLIENT(STRING(" ")); + SENDCLIENT(user); + } else { + SENDCLIENT(STRING("\r\n")); + SENDCLIENT(STRING(":hax.irc.andrewyu.org 353 ")); + SENDCLIENT(client_nick); + SENDCLIENT(STRING(" = ")); + SENDCLIENT(channels); + SENDCLIENT(STRING(" :")); + SENDCLIENT(user); + } + } SENDCLIENT(STRING("\r\n")); - SENDCLIENT(STRING(":hax.irc.andrewyu.org 332 ")); - SENDCLIENT(client_nick); - SENDCLIENT(STRING(" ")); - SENDCLIENT(channels); - SENDCLIENT(STRING(" :\r\n")); // TODO: Actual topic - SENDCLIENT(STRING(":hax.irc.andrewyu.org 333 ")); - SENDCLIENT(client_nick); - SENDCLIENT(STRING(" ")); - SENDCLIENT(channels); - SENDCLIENT(STRING(" ")); - SENDCLIENT(client_nick); // TODO: Actual channel creator - SENDCLIENT(STRING(" :")); - SENDCLIENT(((struct string){.data = current_time_nulstr, .len = strlen(current_time_nulstr)})); - SENDCLIENT(STRING("\r\n")); - SENDCLIENT(STRING(":hax.irc.andrewyu.org 353 ")); - SENDCLIENT(client_nick); - SENDCLIENT(STRING(" = ")); - SENDCLIENT(channels); - SENDCLIENT(STRING(" :\r\n")); // TODO: NAMES list SENDCLIENT(STRING(":hax.irc.andrewyu.org 366 ")); SENDCLIENT(client_nick); SENDCLIENT(STRING(" ")); @@ -218,7 +221,9 @@ int client_join_handler(uint64_t argc, struct string *argv) { SEND(channels); SEND(STRING(" ")); SEND(((struct string){.data = current_time_nulstr, .len = strlen(current_time_nulstr)})); - SEND(STRING(" +Cnt :,1HC000001\n")); + SEND(STRING(" + :,1HC000001\n")); + + set_table_index(&(channel_info->user_list), STRING("1HC000001"), get_table_index(user_list, STRING("1HC000001"))); // TODO: Actually add local users to user_list channels.len = oldlen; diff --git a/general_network.c b/general_network.c index 63d3d7d..9da36ce 100644 --- a/general_network.c +++ b/general_network.c @@ -27,11 +27,60 @@ // OTHER DEALINGS IN THE SOFTWARE. #include +#include #include "network.h" #include "tls.h" #include "config.h" +char channel_mode_types[UCHAR_MAX] = { + ['v'] = MODE_TYPE_USERS, + ['h'] = MODE_TYPE_USERS, + ['o'] = MODE_TYPE_USERS, + ['a'] = MODE_TYPE_USERS, + ['q'] = MODE_TYPE_USERS, + ['b'] = MODE_TYPE_MULTIPLE, + ['e'] = MODE_TYPE_MULTIPLE, + ['I'] = MODE_TYPE_MULTIPLE, + ['c'] = MODE_TYPE_NOARGS, + ['d'] = MODE_TYPE_REPLACE, + ['f'] = MODE_TYPE_REPLACE, + ['g'] = MODE_TYPE_MULTIPLE, + ['i'] = MODE_TYPE_NOARGS, + ['j'] = MODE_TYPE_REPLACE, + ['k'] = MODE_TYPE_REPLACE, + ['l'] = MODE_TYPE_REPLACE, + ['m'] = MODE_TYPE_NOARGS, + ['n'] = MODE_TYPE_NOARGS, + ['p'] = MODE_TYPE_NOARGS, + ['r'] = MODE_TYPE_NOARGS, + ['s'] = MODE_TYPE_NOARGS, + ['t'] = MODE_TYPE_NOARGS, + ['u'] = MODE_TYPE_NOARGS, + ['w'] = MODE_TYPE_MULTIPLE, + ['z'] = MODE_TYPE_NOARGS, + ['A'] = MODE_TYPE_NOARGS, + ['B'] = MODE_TYPE_NOARGS, + ['C'] = MODE_TYPE_NOARGS, + ['D'] = MODE_TYPE_NOARGS, + ['E'] = MODE_TYPE_REPLACE, + ['F'] = MODE_TYPE_REPLACE, + ['G'] = MODE_TYPE_NOARGS, + ['H'] = MODE_TYPE_REPLACE, + ['J'] = MODE_TYPE_REPLACE, + ['K'] = MODE_TYPE_NOARGS, + ['L'] = MODE_TYPE_REPLACE, + ['M'] = MODE_TYPE_NOARGS, + ['N'] = MODE_TYPE_NOARGS, + ['O'] = MODE_TYPE_NOARGS, + ['P'] = MODE_TYPE_NOARGS, + ['Q'] = MODE_TYPE_NOARGS, + ['R'] = MODE_TYPE_NOARGS, + ['S'] = MODE_TYPE_NOARGS, + ['T'] = MODE_TYPE_NOARGS, + ['X'] = MODE_TYPE_MULTIPLE, +}; + int PRIVMSG(struct string source, struct string target, struct string message) { if (!(target.len == 9 && memcmp(target.data, "1HC000001", 9) == 0)) { // if not sending to our one local user if (source.len != 0) { diff --git a/network.h b/network.h index 67d308d..7682ed4 100644 --- a/network.h +++ b/network.h @@ -30,12 +30,13 @@ #include #include +#include #include "types.h" #include "table.h" // ID is the index you got this from -struct remote_server { +struct server_info { uint64_t distance; // gl if you exceed this struct string address; @@ -69,6 +70,9 @@ struct user_info { struct channel_info { uint64_t ts; + struct string topic; + uint64_t topic_ts; + struct table modes; // TODO: Parse modes properly struct table user_list; // points to corresponding user_info struct (if available, currently not) @@ -93,6 +97,15 @@ extern int resolve(char* address, char* port, struct sockaddr *server); extern int initservernetwork(void); extern int initclientnetwork(void); +#define MODE_TYPE_UNKNOWN 0 +#define MODE_TYPE_NOARGS 1 +#define MODE_TYPE_REPLACE 2 +#define MODE_TYPE_MULTIPLE 3 +// Mode goes away when the user leaves the channel +#define MODE_TYPE_USERS 4 + +extern char channel_mode_types[UCHAR_MAX]; + #define SENDCLIENT(x) write(client_fd, x.data, x.len) extern int PRIVMSG(struct string source, struct string target, struct string message); diff --git a/server_network.c b/server_network.c index cf7c435..3b58e70 100644 --- a/server_network.c +++ b/server_network.c @@ -117,7 +117,7 @@ int server_handler(struct string sender, uint64_t argc, struct string *argv) { } if (sender.len != 0) { - struct remote_server *from = get_table_index(server_list, sender); + struct server_info *from = get_table_index(server_list, sender); if (!from) { puts("Invalid SERVER recieved! (Unknown source)"); return 1; @@ -147,7 +147,7 @@ int server_handler(struct string sender, uint64_t argc, struct string *argv) { name.len = argv[4].len; memcpy(name.data, argv[4].data, argv[4].len); - struct remote_server *server = malloc(sizeof(*server)); + struct server_info *server = malloc(sizeof(*server)); if (server == 0) goto server_handler_free_name; @@ -163,7 +163,7 @@ int server_handler(struct string sender, uint64_t argc, struct string *argv) { via = (struct string){0}; } - *server = (struct remote_server){ + *server = (struct server_info){ .name = name, .address = address, .distance = distance, @@ -360,6 +360,25 @@ int quit_handler(struct string sender, uint64_t argc, struct string *argv) { return 1; } + for (uint64_t i = 0; i < channel_list.len; i++) { // TODO: Use channel list attached to the user (doesn't exist yet) + struct channel_info *chan_info = channel_list.array[i].ptr; + if (has_table_index(chan_info->user_list, STRING("1HC000001"))) { + SENDCLIENT(STRING(":")); + SENDCLIENT(info->nick); + SENDCLIENT(STRING("!")); + SENDCLIENT(info->ident); + SENDCLIENT(STRING("@")); + SENDCLIENT(info->vhost); + if (argc >= 1) { + SENDCLIENT(STRING(" QUIT :")); + SENDCLIENT(argv[0]); + SENDCLIENT(STRING("\r\n")); + } else { + SENDCLIENT(STRING(" QUIT\r\n")); + } + } + } + free(info->server.data); free(info->nick.data); if (info->opertype.len) @@ -431,6 +450,23 @@ int nick_handler(struct string sender, uint64_t argc, struct string *argv) { return 1; } + for (uint64_t i = 0; i < channel_list.len; i++) { // TODO: More efficient way of doing this + struct channel_info *channel = channel_list.array[i].ptr; + if (has_table_index(channel->user_list, sender) && has_table_index(channel->user_list, STRING("1HC000001"))) { + SENDCLIENT(STRING(":")); + SENDCLIENT(info->nick); + SENDCLIENT(STRING("!")); + SENDCLIENT(info->ident); + SENDCLIENT(STRING("@")); + SENDCLIENT(info->vhost); + SENDCLIENT(STRING(" NICK :")); + SENDCLIENT(argv[0]); + SENDCLIENT(STRING("\r\n")); + + break; + } + } + void *tmp = malloc(argv[0].len); if (!tmp) { WRITES(2, STRING("OOM! (nick_handler)\n")); @@ -464,38 +500,101 @@ int fjoin_handler(struct string sender, uint64_t argc, struct string *argv) { return 1; } -// uint8_t err; -// uint64_t timestamp = str_to_unsigned(argv[1], &err); -// if (err) { -// WRITES(2, STRING("Invalid FJOIN recieved! (Invalid timestamp given)\n")); -// return 1; -// } -// -// // TODO: Parse modes, then make the rest of this work -// -// -// struct channel_info *channel = get_table_index(channel_list, argv[0]); -// if (!channel) { -// channel = malloc(sizeof(*channel)); -// if (!channel) { -// WRITES(2, STRING("OOM! (fjoin_handler)\n")); -// return 1; -// } -// *channel = (struct channel_info){ -// .ts = timestamp, -// -// -// set_table_index(&channel_list, argv[0], channel); -// -// -// } + uint8_t err; + uint64_t timestamp = str_to_unsigned(argv[1], &err); + if (err) { + WRITES(2, STRING("Invalid FJOIN recieved! (Invalid timestamp given)\n")); + return 1; + } + + // TODO: Parse modes, then make the rest of this work + uint64_t userlist_offset = 3; + { + char dir = '?'; + for (uint64_t offset = 0; offset < argv[2].len; offset++) { + if (argv[2].data[offset] == '+') { + dir = '+'; + } else if (argv[2].data[offset] == '-') { + dir = '-'; + } else if (dir == '?') { + WRITES(2, STRING("Invalid FJOIN recieved! (No direction set for modes)\n")); + return 1; + } else if (channel_mode_types[(unsigned char)argv[2].data[offset]] == MODE_TYPE_UNKNOWN) { + WRITES(2, STRING("Invalid FJOIN recieved! (Unknown mode set on the channel)\n")); + return 1; + } else if (channel_mode_types[(unsigned char)argv[2].data[offset]] != MODE_TYPE_NOARGS && dir == '+') { + userlist_offset++; + } + } + } + + if (argc < userlist_offset + 1) { + WRITES(2, STRING("Invalid FJOIN recieved! (Missing mode parameters or user list)\n")); + return 1; + } + + struct channel_info *channel = get_table_index(channel_list, argv[0]); + if (!channel) { + channel = malloc(sizeof(*channel)); + if (!channel) { + WRITES(2, STRING("OOM! (fjoin_handler)\n")); + return 1; + } + *channel = (struct channel_info){ + .ts = timestamp, + .topic = {.data = malloc(0), .len = 0}, + .topic_ts = 0, + .modes = {.array = malloc(0), .len = 0}, + .user_list = {.array = malloc(0), .len = 0}, + .metadata = {.array = malloc(0), .len = 0}, + }; + + set_table_index(&channel_list, argv[0], channel); + } + + struct string userlist = argv[userlist_offset]; + + if (userlist.len < 10) // Not enough for any users + return 0; + + uint8_t sendclient = has_table_index(channel->user_list, STRING("1HC000001")); + + uint64_t offset = 0; + while (1) { + while (offset < userlist.len && userlist.data[offset] != ',') + offset++; + + if (offset > (userlist.len - 1) - 9) + break; + + offset++; + + struct string user = {.data = &(userlist.data[offset]), .len = 9}; + struct user_info *user_info = get_table_index(user_list, user); + + set_table_index(&(channel->user_list), user, user_info); + + if (user_info && sendclient) { + SENDCLIENT(STRING(":")); + SENDCLIENT(user_info->nick); + SENDCLIENT(STRING("!")); + SENDCLIENT(user_info->ident); + SENDCLIENT(STRING("@")); + SENDCLIENT(user_info->vhost); + SENDCLIENT(STRING(" JOIN :")); + SENDCLIENT(argv[0]); + SENDCLIENT(STRING("\r\n")); + } + + offset += 10; + } return 0; } int squit_handler(struct string sender, uint64_t argc, struct string *argv) { if (argc < 1) { - WRITES(2, STRING("Invalid SQUIT recieved! (Missing parameters)")); + WRITES(2, STRING("Invalid SQUIT recieved! (Missing parameters)\n")); return 1; } @@ -521,7 +620,7 @@ int squit_handler(struct string sender, uint64_t argc, struct string *argv) { } } - struct remote_server *server = remove_table_index(&server_list, argv[0]); + struct server_info *server = remove_table_index(&server_list, argv[0]); free(server->name.data); free(server->address.data); if (server->via.data != 0) @@ -572,6 +671,30 @@ int privmsg_handler(struct string sender, uint64_t argc, struct string *argv) { SENDCLIENT(argv[1]); SENDCLIENT(STRING("\r\n")); } + } else { + struct server_info *server = get_table_index(server_list, sender); + if (server) { + if (argv[0].data[0] == '#') { + struct channel_info *channel = get_table_index(channel_list, argv[0]); + if (channel && has_table_index(channel->user_list, STRING("1HC000001"))) { + SENDCLIENT(STRING(":")); + SENDCLIENT(server->address); + SENDCLIENT(STRING(" PRIVMSG ")); + SENDCLIENT(argv[0]); + SENDCLIENT(STRING(" :")); + SENDCLIENT(argv[1]); + SENDCLIENT(STRING("\r\n")); + } + } else if (argv[0].len == 9 && memcmp(argv[0].data, "1HC000001", 9) == 0) { + SENDCLIENT(STRING(":")); + SENDCLIENT(server->address); + SENDCLIENT(STRING(" PRIVMSG ")); + SENDCLIENT(client_nick); + SENDCLIENT(STRING(" :")); + SENDCLIENT(argv[1]); + SENDCLIENT(STRING("\r\n")); + } + } } uint64_t offset; @@ -689,6 +812,33 @@ int privmsg_handler(struct string sender, uint64_t argc, struct string *argv) { } } +int part_handler(struct string sender, uint64_t argc, struct string *argv) { + if (argc < 1) { + WRITES(2, STRING("Invalid PART received! (Missing parameters)\n")); + return 1; + } + + struct channel_info *channel = get_table_index(channel_list, argv[0]); + struct user_info *user = get_table_index(user_list, sender); + if (user && channel && has_table_index(channel->user_list, STRING("1HC000001"))) { + SENDCLIENT(STRING(":")); + SENDCLIENT(user->nick); + SENDCLIENT(STRING("!")); + SENDCLIENT(user->ident); + SENDCLIENT(STRING("@")); + SENDCLIENT(user->vhost); + SENDCLIENT(STRING(" PART ")); + SENDCLIENT(argv[0]); + if (argc >= 2) { + SENDCLIENT(STRING(" :")); + SENDCLIENT(argv[1]); + } + SENDCLIENT(STRING("\r\n")); + } + + return 0; +} + int initservernetwork(void) { server_network_commands.array = malloc(0); server_list.array = malloc(0); @@ -705,6 +855,7 @@ int initservernetwork(void) { set_table_index(&server_network_commands, STRING("NICK"), &nick_handler); set_table_index(&server_network_commands, STRING("FJOIN"), &fjoin_handler); set_table_index(&server_network_commands, STRING("SQUIT"), &squit_handler); + set_table_index(&server_network_commands, STRING("PART"), &part_handler); init_user_commands(); -- cgit v1.2.3