aboutsummaryrefslogtreecommitdiff
path: root/protocols
diff options
context:
space:
mode:
authorTest_User <hax@andrewyu.org>2024-06-14 02:51:58 -0400
committerTest_User <hax@andrewyu.org>2024-06-14 02:51:58 -0400
commit35c5a9f9adab04b821896978520af643ea8b697f (patch)
treeee474fe3e1b54f4e497e5dffa391fba6937d45f3 /protocols
parentdadd3396cf719e1ce659926833efd1e17064f2d5 (diff)
downloadhaxircd-35c5a9f9adab04b821896978520af643ea8b697f.tar.gz
haxircd-35c5a9f9adab04b821896978520af643ea8b697f.zip
Basic channel tracking added
Diffstat (limited to 'protocols')
-rw-r--r--protocols/inspircd2.c222
-rw-r--r--protocols/inspircd2.h7
2 files changed, 229 insertions, 0 deletions
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 <type> [<args> [, ...]]
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 <channel> <timestamp> <modes> [<mode args>] <userlist: modes,uid [...]>
+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 <channel> [<reason>]
+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