From 35c5a9f9adab04b821896978520af643ea8b697f Mon Sep 17 00:00:00 2001 From: Test_User Date: Fri, 14 Jun 2024 02:51:58 -0400 Subject: Basic channel tracking added --- protocols/inspircd2.c | 222 ++++++++++++++++++++++++++++++++++++++++++++++++++ protocols/inspircd2.h | 7 ++ 2 files changed, 229 insertions(+) (limited to 'protocols') diff --git a/protocols/inspircd2.c b/protocols/inspircd2.c index fa2767f..2226e7e 100644 --- a/protocols/inspircd2.c +++ b/protocols/inspircd2.c @@ -140,6 +140,9 @@ int init_inspircd2_protocol(void) { set_table_index(&inspircd2_protocol_commands, STRING("KILL"), &inspircd2_protocol_handle_kill); set_table_index(&inspircd2_protocol_commands, STRING("FJOIN"), &inspircd2_protocol_handle_fjoin); + set_table_index(&inspircd2_protocol_commands, STRING("PART"), &inspircd2_protocol_handle_part); + + set_table_index(&inspircd2_protocol_commands, STRING("DUMP"), &inspircd2_protocol_handle_dump); return 0; } @@ -630,6 +633,74 @@ void inspircd2_protocol_propagate_kill_user(struct string from, struct string so } } +void inspircd2_protocol_propagate_set_channel(struct string from, struct channel_info *channel, char is_new_server, size_t user_count, struct user_info **users) { + struct server_info *self = get_table_index(server_list, SID); + + for (size_t i = 0; i < self->connected_to.len; i++) { + struct server_info *adjacent = self->connected_to.array[i].ptr; + if (adjacent->protocol != INSPIRCD2_PROTOCOL || STRING_EQ(from, adjacent->sid)) + continue; + + networks[adjacent->net].send(adjacent->handle, STRING(":")); + networks[adjacent->net].send(adjacent->handle, SID); + networks[adjacent->net].send(adjacent->handle, STRING(" FJOIN ")); + networks[adjacent->net].send(adjacent->handle, channel->name); + networks[adjacent->net].send(adjacent->handle, STRING(" ")); + networks[adjacent->net].send(adjacent->handle, channel->channel_ts_str); + networks[adjacent->net].send(adjacent->handle, STRING(" + :")); + for (size_t x = 0; x < user_count; x++) { + networks[adjacent->net].send(adjacent->handle, STRING(",")); + networks[adjacent->net].send(adjacent->handle, users[x]->uid); + if (x != channel->user_list.len - 1) + networks[adjacent->net].send(adjacent->handle, STRING(" ")); + } + networks[adjacent->net].send(adjacent->handle, STRING("\n")); + } +} + +void inspircd2_protocol_propagate_join_channel(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users) { + struct server_info *self = get_table_index(server_list, SID); + + for (size_t i = 0; i < self->connected_to.len; i++) { + struct server_info *adjacent = self->connected_to.array[i].ptr; + if (adjacent->protocol != INSPIRCD2_PROTOCOL || STRING_EQ(from, adjacent->sid)) + continue; + + networks[adjacent->net].send(adjacent->handle, STRING(":")); + networks[adjacent->net].send(adjacent->handle, SID); + networks[adjacent->net].send(adjacent->handle, STRING(" FJOIN ")); + networks[adjacent->net].send(adjacent->handle, channel->name); + networks[adjacent->net].send(adjacent->handle, STRING(" ")); + networks[adjacent->net].send(adjacent->handle, channel->channel_ts_str); + networks[adjacent->net].send(adjacent->handle, STRING(" + :")); + for (size_t x = 0; x < user_count; x++) { + networks[adjacent->net].send(adjacent->handle, STRING(",")); + networks[adjacent->net].send(adjacent->handle, users[x]->uid); + if (x != channel->user_list.len - 1) + networks[adjacent->net].send(adjacent->handle, STRING(" ")); + } + networks[adjacent->net].send(adjacent->handle, STRING("\n")); + } +} + +void inspircd2_protocol_propagate_part_channel(struct string from, struct channel_info *channel, struct user_info *user, struct string reason) { + struct server_info *self = get_table_index(server_list, SID); + + for (size_t i = 0; i < self->connected_to.len; i++) { + struct server_info *adjacent = self->connected_to.array[i].ptr; + if (adjacent->protocol != INSPIRCD2_PROTOCOL || STRING_EQ(from, adjacent->sid)) + continue; + + networks[adjacent->net].send(adjacent->handle, STRING(":")); + networks[adjacent->net].send(adjacent->handle, user->uid); + networks[adjacent->net].send(adjacent->handle, STRING(" PART ")); + networks[adjacent->net].send(adjacent->handle, channel->name); + networks[adjacent->net].send(adjacent->handle, STRING(" :")); + networks[adjacent->net].send(adjacent->handle, reason); + networks[adjacent->net].send(adjacent->handle, STRING("\n")); + } +} + void inspircd2_protocol_do_unlink_inner(struct string from, struct server_info *target, struct string reason) { target->distance = 1; // Reusing distance for `have passed`, since its set to 0 bc severed anyways @@ -725,6 +796,23 @@ void inspircd2_protocol_introduce_user_to(size_t net, void *handle, struct user_ networks[net].send(handle, STRING("\n")); } +void inspircd2_protocol_introduce_channel_to(size_t net, void *handle, struct channel_info *channel) { + networks[net].send(handle, STRING(":")); + networks[net].send(handle, SID); + networks[net].send(handle, STRING(" FJOIN ")); + networks[net].send(handle, channel->name); + networks[net].send(handle, STRING(" ")); + networks[net].send(handle, channel->channel_ts_str); + networks[net].send(handle, STRING(" + :")); + for (size_t i = 0; i < channel->user_list.len; i++) { + networks[net].send(handle, STRING(",")); + networks[net].send(handle, channel->user_list.array[i].name); + if (i != channel->user_list.len - 1) + networks[net].send(handle, STRING(" ")); + } + networks[net].send(handle, STRING("\n")); +} + // CAPAB [ [, ...]] int inspircd2_protocol_init_handle_capab(struct string source, size_t argc, struct string *argv, size_t net, void *handle, struct server_config **config, char is_incoming) { if (argc < 1) { @@ -804,6 +892,9 @@ int inspircd2_protocol_init_handle_server(struct string source, size_t argc, str for (size_t i = 0; i < user_list.len; i++) inspircd2_protocol_introduce_user_to(net, handle, user_list.array[i].ptr); + for (size_t i = 0; i < channel_list.len; i++) + inspircd2_protocol_introduce_channel_to(net, handle, channel_list.array[i].ptr); + networks[net].send(handle, STRING(":")); networks[net].send(handle, SID); networks[net].send(handle, STRING(" ENDBURST\n")); @@ -1125,6 +1216,137 @@ int inspircd2_protocol_handle_kill(struct string source, size_t argc, struct str return 0; } +// [:source] FJOIN [] +int inspircd2_protocol_handle_fjoin(struct string source, size_t argc, struct string *argv, size_t net, void *handle, struct server_config *config, char is_incoming) { + if (argc < 4) { + WRITES(2, STRING("[InspIRCd v2] Invalid FJOIN recieved! (Missing parameters)\r\n")); + return -1; + } + + char err; + size_t timestamp = str_to_unsigned(argv[1], &err); + if (err) { + WRITES(2, STRING("[InspIRCd v2] Invalid FJOIN recieved! (Invalid timestamp)\r\n")); + return -1; + } + + size_t arg_i = 3; + char dir = '?'; + for (size_t i = 0; i < argv[2].len; i++) { + switch(argv[2].data[i]) { + case '+': + case '-': + dir = argv[2].data[i]; + break; + default: + if (dir == '?') { + WRITES(2, STRING("[InspIRCd v2] Invalid FJOIN recieved (Mode direction not set)\r\n")); + return -1; + } + switch(inspircd2_protocol_channel_mode_types[(unsigned char)argv[2].data[i]]) { + case MODE_TYPE_NOARGS: + break; + case MODE_TYPE_REPLACE: + case MODE_TYPE_MODE: + if (dir == '-') + break; + case MODE_TYPE_MULTIPLE: + arg_i++; + break; + case MODE_TYPE_USERS: + WRITES(2, STRING("[InspIRCd v2] Invalid FJOIN recieved! (User mode put in the modes instead of the user list)\r\n")); + return -1; + default: + WRITES(2, STRING("[InspIRCd v2] Invalid FJOIN recieved! (Unknown mode given)\r\n")); + return -1; + } + } + } + + size_t user_count = 0; + for (size_t i = 0; i < argv[arg_i].len;) { + while (i < argv[arg_i].len && argv[arg_i].data[i] != ',') + i++; + + i++; + + user_count++; + + while (i < argv[arg_i].len && argv[arg_i].data[i] != ' ') + i++; + } + + struct user_info **users; + users = malloc(sizeof(**users) * user_count); + if (!users && user_count != 0) { + WRITES(2, STRING("[InspIRCd v2] [FJOIN] OOM! Disconnecting server.\r\n")); + return -1; + } + + for (size_t i = 0, n = 0; i < argv[arg_i].len; n++) { + struct string uid; + while (i < argv[arg_i].len && argv[arg_i].data[i] != ',') + i++; + + i++; + + uid.data = &(argv[arg_i].data[i]); + + while (i < argv[arg_i].len && argv[arg_i].data[i] != ' ') + i++; + + uid.len = (size_t)(&(argv[arg_i].data[i]) - uid.data); + + users[n] = get_table_index(user_list, uid); + if (!users[n]) { // Maybe KILLed or smth + n--; + user_count--; + } + } + + struct channel_info *channel = get_table_index(channel_list, argv[0]); + if (!channel || timestamp < channel->channel_ts) { + if (set_channel(config->sid, argv[0], timestamp, user_count, users) != 0) + goto inspircd2_protocol_handle_fjoin_free_users; + } else { + if (join_channel(config->sid, channel, user_count, users, 1) != 0) + goto inspircd2_protocol_handle_fjoin_free_users; + } + + free(users); + + return 0; + + inspircd2_protocol_handle_fjoin_free_users: + free(users); + return -1; +} + +// :source PART [] +int inspircd2_protocol_handle_part(struct string source, size_t argc, struct string *argv, size_t net, void *handle, struct server_config *config, char is_incoming) { + if (argc < 1) { + WRITES(2, STRING("[InspIRCd v2] Invalid PART recieved! (Missing parameters)\r\n")); + return -1; + } + struct string reason; + if (argc < 2) + reason = STRING(""); + else + reason = argv[1]; + + struct user_info *user = get_table_index(user_list, source); + if (!user) + return 0; + + struct channel_info *channel = get_table_index(channel_list, argv[0]); + if (!channel) + return 0; + + part_channel(config->sid, channel, user, reason, 1); + + return 0; +} + int inspircd2_protocol_handle_dump(struct string source, size_t argc, struct string *argv, size_t net, void *handle, struct server_config *config, char is_incoming) { for (size_t arg = 0; arg < argc; arg++) { if (STRING_EQ(argv[arg], STRING("LATENCIES"))) { diff --git a/protocols/inspircd2.h b/protocols/inspircd2.h index 6d25760..36a6b68 100644 --- a/protocols/inspircd2.h +++ b/protocols/inspircd2.h @@ -49,6 +49,10 @@ void inspircd2_protocol_propagate_rename_user(struct string from, struct user_in void inspircd2_protocol_propagate_remove_user(struct string from, struct user_info *info, struct string reason); void inspircd2_protocol_propagate_kill_user(struct string from, struct string source, struct user_info *info, struct string reason); +void inspircd2_protocol_propagate_set_channel(struct string from, struct channel_info *channel, char is_new_channel, size_t user_count, struct user_info **users); +void inspircd2_protocol_propagate_join_channel(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users); +void inspircd2_protocol_propagate_part_channel(struct string from, struct channel_info *channel, struct user_info *user, struct string reason); + void inspircd2_protocol_do_unlink(struct string from, struct server_info *a, struct server_info *b); void inspircd2_protocol_update_propagations_inner(struct server_info *source); @@ -70,6 +74,9 @@ int inspircd2_protocol_handle_nick(struct string source, size_t argc, struct str int inspircd2_protocol_handle_quit(struct string source, size_t argc, struct string *argv, size_t net, void *handle, struct server_config *config, char is_incoming); int inspircd2_protocol_handle_kill(struct string source, size_t argc, struct string *argv, size_t net, void *handle, struct server_config *config, char is_incoming); +int inspircd2_protocol_handle_fjoin(struct string source, size_t argc, struct string *argv, size_t net, void *handle, struct server_config *config, char is_incoming); +int inspircd2_protocol_handle_part(struct string source, size_t argc, struct string *argv, size_t net, void *handle, struct server_config *config, char is_incoming); + int inspircd2_protocol_handle_dump(struct string source, size_t argc, struct string *argv, size_t net, void *handle, struct server_config *config, char is_incoming); #define MODE_TYPE_UNKNOWN 0 -- cgit v1.2.3