aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTest_User <hax@andrewyu.org>2024-06-17 03:17:21 -0400
committerTest_User <hax@andrewyu.org>2024-06-17 03:17:58 -0400
commit650bab769f7d07f8538d894a82ad092a5d345e88 (patch)
treeb09c6b9a4284e00b483ceebfd6bf621a48b18856
parentdce234bf05d69b43bf78d0347c108ae008a290be (diff)
downloadhaxircd-650bab769f7d07f8538d894a82ad092a5d345e88.tar.gz
haxircd-650bab769f7d07f8538d894a82ad092a5d345e88.zip
InspIRCd v3 support progress, still not really usable
-rw-r--r--Makefile2
-rw-r--r--README.md2
-rw-r--r--general_network.c49
-rw-r--r--protocols.c452
-rw-r--r--protocols.h54
-rw-r--r--protocols/inspircd2.c77
-rw-r--r--protocols/inspircd2.h24
-rw-r--r--protocols/inspircd3.c310
-rw-r--r--protocols/inspircd3.h24
9 files changed, 782 insertions, 212 deletions
diff --git a/Makefile b/Makefile
index a290510..4e06888 100644
--- a/Makefile
+++ b/Makefile
@@ -283,7 +283,7 @@ DEPS = $(shell $(CC) $(CFLAGS) -M -MT $(1).$(2) $(1).c | sed -z 's/\\\n //g') .m
all: HaxIRCd $(SOFILES)
HaxIRCd: main.c
- $(CC) main.c -o haxserv
+ $(CC) main.c -o HaxIRCd
HaxIRCd.so: $(OFILES) .makeopts Makefile
$(CC) $(OFILES) -shared -o $@ $(LDFLAGS)
diff --git a/README.md b/README.md
index 33577fa..89c2d26 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
traditional IRCDs.
* Could provide internal services (ChanServ, NickServ, HaxServ) and synchronize
the services database, handling collisions gracefully.
-* Correct, Fast and scalable.
+* Correct, fast and scalable.
* Modular.
More extensive runtime module reloading is planned.
* Replace [CoupServ](https://git.andrewyu.org/hax/coupserv.git/about) and
diff --git a/general_network.c b/general_network.c
index b300c87..34f65ec 100644
--- a/general_network.c
+++ b/general_network.c
@@ -296,11 +296,17 @@ int add_user(struct string from, struct string attached_to, struct string uid, s
new_info->channel_list.len = 0;
#ifdef USE_SERVER
+ if (protocols_handle_new_user(from, new_info) != 0)
+ goto add_user_free_channel_list;
+
protocols_propagate_new_user(from, new_info);
#endif
return 0;
+ add_user_free_channel_list:
+ free(new_info->channel_list.array);
+ remove_table_index(&(attached->user_list), uid);
add_user_remove_user_list:
remove_table_index(&user_list, uid);
add_user_free_oper_type:
@@ -341,6 +347,12 @@ int rename_user(struct string from, struct user_info *user, struct string nick,
}
#ifdef USE_SERVER
+ if (protocols_handle_rename_user(from, user, nick, timestamp, timestamp_str) != 0) {
+ free(tmp);
+ free(timestamp_str.data);
+ return 1;
+ }
+
protocols_propagate_rename_user(from, user, nick, timestamp, timestamp_str);
#endif
@@ -357,6 +369,8 @@ void remove_user(struct string from, struct user_info *user, struct string reaso
if (propagate) {
protocols_propagate_remove_user(from, user, reason);
}
+
+ protocols_handle_remove_user(from, user, reason, propagate);
#endif
remove_table_index(&user_list, user->uid);
@@ -401,6 +415,8 @@ int kill_user(struct string from, struct string source, struct user_info *user,
#ifdef USE_SERVER
protocols_propagate_kill_user(from, source, user, reason);
+
+ protocols_handle_kill_user(from, source, user, reason);
#endif
remove_user(from, user, reason, 0);
@@ -414,6 +430,11 @@ int oper_user(struct string from, struct user_info *user, struct string type) {
return 1;
#ifdef USE_SERVER
+ if (protocols_handle_oper_user(from, user, type) != 0) {
+ free(tmp.data);
+ return 1;
+ }
+
protocols_propagate_oper_user(from, user, type);
#endif
@@ -458,14 +479,17 @@ int set_channel(struct string from, struct string name, size_t timestamp, size_t
if (join_channel(from, channel, user_count, users, 0) != 0)
goto set_channel_free_name;
- {
- struct string ts_str;
- if (unsigned_to_str(timestamp, &ts_str) != 0)
- goto set_channel_remove_users;
+ struct string ts_str;
+ if (unsigned_to_str(timestamp, &ts_str) != 0)
+ goto set_channel_remove_users;
- channel->channel_ts_str = ts_str;
- channel->channel_ts = timestamp;
- }
+#ifdef USE_SERVER
+ if (protocols_handle_set_channel(from, channel, is_new_channel, user_count, users))
+ goto set_channel_free_ts_str;
+#endif
+
+ channel->channel_ts_str = ts_str;
+ channel->channel_ts = timestamp;
#ifdef USE_SERVER
protocols_propagate_set_channel(from, channel, is_new_channel, user_count, users);
@@ -473,6 +497,8 @@ int set_channel(struct string from, struct string name, size_t timestamp, size_t
return 0;
+ set_channel_free_ts_str:
+ free(ts_str.data);
set_channel_remove_users:
for (size_t i = 0; i < user_count; i++) {
remove_table_index(&(channel->user_list), users[i]->uid);
@@ -517,12 +543,17 @@ int join_channel(struct string from, struct channel_info *channel, size_t user_c
i++;
}
+#ifdef USE_SERVER
+ if (protocols_handle_join_channel(from, channel, user_count, users, propagate) != 0)
+ goto join_channel_remove_users;
+#endif
+
if (propagate) {
#ifdef USE_CLIENT
#endif
#ifdef USE_SERVER
- protocols_propagate_join_channel(from, channel, user_count, users);
+ protocols_propagate_join_channel(from, channel, user_count, users, propagate);
#endif
}
@@ -691,6 +722,8 @@ int do_trivial_reloads(void) {
if (psuedoclients[HAXSERV_PSUEDOCLIENT].post_reload() != 0) {
abort(); // TODO: Ugh...
}
+
+ reload_psuedoclients[HAXSERV_PSUEDOCLIENT] = 0;
}
#endif
#endif
diff --git a/protocols.c b/protocols.c
index 8d82907..bca7cc1 100644
--- a/protocols.c
+++ b/protocols.c
@@ -39,6 +39,7 @@ struct protocol protocols[NUM_PROTOCOLS] = {
#ifdef USE_INSPIRCD2_PROTOCOL
[INSPIRCD2_PROTOCOL] = {
.init = init_inspircd2_protocol,
+ .fail_init = init_inspircd2_protocol_fail,
.handle_connection = inspircd2_protocol_connection,
.autoconnect = inspircd2_protocol_autoconnect,
@@ -63,12 +64,36 @@ struct protocol protocols[NUM_PROTOCOLS] = {
.propagate_privmsg = inspircd2_protocol_propagate_privmsg,
.propagate_notice = inspircd2_protocol_propagate_notice,
+ .handle_new_server = inspircd2_protocol_handle_new_server,
+ .handle_unlink_server = inspircd2_protocol_handle_unlink_server,
+
+ .handle_new_user = inspircd2_protocol_handle_new_user,
+ .handle_rename_user = inspircd2_protocol_handle_rename_user,
+ .handle_remove_user = inspircd2_protocol_handle_remove_user,
+ .handle_kill_user = inspircd2_protocol_handle_kill_user,
+ .handle_oper_user = inspircd2_protocol_handle_oper_user,
+
+ .handle_set_channel = inspircd2_protocol_handle_set_channel,
+ .handle_join_channel = inspircd2_protocol_handle_join_channel,
+ .handle_part_channel = inspircd2_protocol_handle_part_channel,
+ .handle_kick_channel = inspircd2_protocol_handle_kick_channel,
+
+ .fail_new_server = inspircd2_protocol_fail_new_server,
+
+ .fail_new_user = inspircd2_protocol_fail_new_user,
+ .fail_rename_user = inspircd2_protocol_fail_rename_user,
+ .fail_oper_user = inspircd2_protocol_fail_oper_user,
+
+ .fail_set_channel = inspircd2_protocol_fail_set_channel,
+ .fail_join_channel = inspircd2_protocol_fail_join_channel,
+
.do_unlink = inspircd2_protocol_do_unlink,
},
#endif
#ifdef USE_INSPIRCD3_PROTOCOL
[INSPIRCD3_PROTOCOL] = {
.init = init_inspircd3_protocol,
+ .fail_init = init_inspircd3_protocol_fail,
.handle_connection = inspircd3_protocol_connection,
.autoconnect = inspircd3_protocol_autoconnect,
@@ -93,145 +118,392 @@ struct protocol protocols[NUM_PROTOCOLS] = {
.propagate_privmsg = inspircd3_protocol_propagate_privmsg,
.propagate_notice = inspircd3_protocol_propagate_notice,
+ .handle_new_server = inspircd3_protocol_handle_new_server,
+ .handle_unlink_server = inspircd3_protocol_handle_unlink_server,
+
+ .handle_new_user = inspircd3_protocol_handle_new_user,
+ .handle_rename_user = inspircd3_protocol_handle_rename_user,
+ .handle_remove_user = inspircd3_protocol_handle_remove_user,
+ .handle_kill_user = inspircd3_protocol_handle_kill_user,
+ .handle_oper_user = inspircd3_protocol_handle_oper_user,
+
+ .handle_set_channel = inspircd3_protocol_handle_set_channel,
+ .handle_join_channel = inspircd3_protocol_handle_join_channel,
+ .handle_part_channel = inspircd3_protocol_handle_part_channel,
+ .handle_kick_channel = inspircd3_protocol_handle_kick_channel,
+
+ .fail_new_server = inspircd3_protocol_fail_new_server,
+
+ .fail_new_user = inspircd3_protocol_fail_new_user,
+ .fail_rename_user = inspircd3_protocol_fail_rename_user,
+ .fail_oper_user = inspircd3_protocol_fail_oper_user,
+
+ .fail_set_channel = inspircd3_protocol_fail_set_channel,
+ .fail_join_channel = inspircd3_protocol_fail_join_channel,
+
.do_unlink = inspircd3_protocol_do_unlink,
},
#endif
};
-int protocols_init(void) {
+char active_protocols[NUM_PROTOCOLS] = {
#ifdef USE_INSPIRCD2_PROTOCOL
- if (protocols[INSPIRCD2_PROTOCOL].init() != 0)
- return 1;
+ [INSPIRCD2_PROTOCOL] = 1,
#endif
#ifdef USE_INSPIRCD3_PROTOCOL
- if (protocols[INSPIRCD3_PROTOCOL].init() != 0)
- return 1;
+ [INSPIRCD3_PROTOCOL] = 1,
#endif
+};
+
+int protocols_init(void) {
+ size_t i;
+ for (i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ if (protocols[i].init() != 0)
+ goto protocols_init_fail;
+ }
return 0;
+
+ protocols_init_fail:
+ while (i > 0) {
+ i--;
+ if (!active_protocols[i])
+ continue;
+ protocols[i].fail_init();
+ }
+
+ return 1;
}
void protocols_update_propagations(void) {
-#ifdef USE_INSPIRCD2_PROTOCOL
- protocols[INSPIRCD2_PROTOCOL].update_propagations();
-#endif
-#ifdef USE_INSPIRCD3_PROTOCOL
- protocols[INSPIRCD3_PROTOCOL].update_propagations();
-#endif
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].update_propagations();
+ }
}
void protocols_propagate_new_server(struct string from, struct string attached_to, struct server_info *info) {
-#ifdef USE_INSPIRCD2_PROTOCOL
- protocols[INSPIRCD2_PROTOCOL].propagate_new_server(from, attached_to, info);
-#endif
-#ifdef USE_INSPIRCD3_PROTOCOL
- protocols[INSPIRCD3_PROTOCOL].propagate_new_server(from, attached_to, info);
-#endif
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].propagate_new_server(from, attached_to, info);
+ }
}
void protocols_propagate_unlink_server(struct string from, struct server_info *a, struct server_info *b, size_t protocol) {
-#ifdef USE_INSPIRCD2_PROTOCOL
- protocols[INSPIRCD2_PROTOCOL].propagate_unlink_server(from, a, b, protocol);
-#endif
-#ifdef USE_INSPIRCD3_PROTOCOL
- protocols[INSPIRCD3_PROTOCOL].propagate_unlink_server(from, a, b, protocol);
-#endif
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].propagate_unlink_server(from, a, b, protocol);
+ }
}
void protocols_propagate_new_user(struct string from, struct user_info *info) {
-#ifdef USE_INSPIRCD2_PROTOCOL
- protocols[INSPIRCD2_PROTOCOL].propagate_new_user(from, info);
-#endif
-#ifdef USE_INSPIRCD3_PROTOCOL
- protocols[INSPIRCD3_PROTOCOL].propagate_new_user(from, info);
-#endif
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].propagate_new_user(from, info);
+ }
}
void protocols_propagate_rename_user(struct string from, struct user_info *info, struct string nick, size_t timestamp, struct string timestamp_str) {
-#ifdef USE_INSPIRCD2_PROTOCOL
- protocols[INSPIRCD2_PROTOCOL].propagate_rename_user(from, info, nick, timestamp, timestamp_str);
-#endif
-#ifdef USE_INSPIRCD3_PROTOCOL
- protocols[INSPIRCD3_PROTOCOL].propagate_rename_user(from, info, nick, timestamp, timestamp_str);
-#endif
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].propagate_rename_user(from, info, nick, timestamp, timestamp_str);
+ }
}
void protocols_propagate_remove_user(struct string from, struct user_info *info, struct string reason) {
-#ifdef USE_INSPIRCD2_PROTOCOL
- protocols[INSPIRCD2_PROTOCOL].propagate_remove_user(from, info, reason);
-#endif
-#ifdef USE_INSPIRCD3_PROTOCOL
- protocols[INSPIRCD3_PROTOCOL].propagate_remove_user(from, info, reason);
-#endif
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].propagate_remove_user(from, info, reason);
+ }
}
void protocols_propagate_kill_user(struct string from, struct string source, struct user_info *info, struct string reason) {
-#ifdef USE_INSPIRCD2_PROTOCOL
- protocols[INSPIRCD2_PROTOCOL].propagate_kill_user(from, source, info, reason);
-#endif
-#ifdef USE_INSPIRCD3_PROTOCOL
- protocols[INSPIRCD3_PROTOCOL].propagate_kill_user(from, source, info, reason);
-#endif
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].propagate_kill_user(from, source, info, reason);
+ }
}
void protocols_propagate_oper_user(struct string from, struct user_info *info, struct string type) {
-#ifdef USE_INSPIRCD2_PROTOCOL
- protocols[INSPIRCD2_PROTOCOL].propagate_oper_user(from, info, type);
-#endif
-#ifdef USE_INSPIRCD3_PROTOCOL
- protocols[INSPIRCD3_PROTOCOL].propagate_oper_user(from, info, type);
-#endif
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].propagate_oper_user(from, info, type);
+ }
}
void protocols_propagate_set_channel(struct string from, struct channel_info *channel, char is_new_channel, size_t user_count, struct user_info **users) {
-#ifdef USE_INSPIRCD2_PROTOCOL
- protocols[INSPIRCD2_PROTOCOL].propagate_set_channel(from, channel, is_new_channel, user_count, users);
-#endif
-#ifdef USE_INSPIRCD3_PROTOCOL
- protocols[INSPIRCD3_PROTOCOL].propagate_set_channel(from, channel, is_new_channel, user_count, users);
-#endif
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].propagate_set_channel(from, channel, is_new_channel, user_count, users);
+ }
}
-void protocols_propagate_join_channel(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users) {
-#ifdef USE_INSPIRCD2_PROTOCOL
- protocols[INSPIRCD2_PROTOCOL].propagate_join_channel(from, channel, user_count, users);
-#endif
-#ifdef USE_INSPIRCD3_PROTOCOL
- protocols[INSPIRCD3_PROTOCOL].propagate_join_channel(from, channel, user_count, users);
-#endif
+void protocols_propagate_join_channel(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users, char propagate) {
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].propagate_join_channel(from, channel, user_count, users);
+ }
}
void protocols_propagate_part_channel(struct string from, struct channel_info *channel, struct user_info *user, struct string reason) {
-#ifdef USE_INSPIRCD2_PROTOCOL
- protocols[INSPIRCD2_PROTOCOL].propagate_part_channel(from, channel, user, reason);
-#endif
-#ifdef USE_INSPIRCD3_PROTOCOL
- protocols[INSPIRCD3_PROTOCOL].propagate_part_channel(from, channel, user, reason);
-#endif
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].propagate_part_channel(from, channel, user, reason);
+ }
}
void protocols_propagate_kick_channel(struct string from, struct string source, struct channel_info *channel, struct user_info *user, struct string reason) {
-#ifdef USE_INSPIRCD2_PROTOCOL
- protocols[INSPIRCD2_PROTOCOL].propagate_kick_channel(from, source, channel, user, reason);
-#endif
-#ifdef USE_INSPIRCD3_PROTOCOL
- protocols[INSPIRCD3_PROTOCOL].propagate_kick_channel(from, source, channel, user, reason);
-#endif
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].propagate_kick_channel(from, source, channel, user, reason);
+ }
}
void protocols_propagate_privmsg(struct string from, struct string source, struct string target, struct string msg) {
-#ifdef USE_INSPIRCD2_PROTOCOL
- protocols[INSPIRCD2_PROTOCOL].propagate_privmsg(from, source, target, msg);
-#endif
-#ifdef USE_INSPIRCD3_PROTOCOL
- protocols[INSPIRCD3_PROTOCOL].propagate_privmsg(from, source, target, msg);
-#endif
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].propagate_privmsg(from, source, target, msg);
+ }
}
void protocols_propagate_notice(struct string from, struct string source, struct string target, struct string msg) {
-#ifdef USE_INSPIRCD2_PROTOCOL
- protocols[INSPIRCD2_PROTOCOL].propagate_notice(from, source, target, msg);
-#endif
-#ifdef USE_INSPIRCD3_PROTOCOL
- protocols[INSPIRCD3_PROTOCOL].propagate_notice(from, source, target, msg);
-#endif
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].propagate_notice(from, source, target, msg);
+ }
+}
+
+int protocols_handle_new_server(struct string from, struct string attached_to, struct server_info *info) {
+ size_t i;
+ for (i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ if (protocols[i].handle_new_server(from, attached_to, info) != 0)
+ goto protocols_handle_new_server_fail;
+ }
+
+ return 0;
+
+ protocols_handle_new_server_fail:
+ while (i > 0) {
+ i--;
+ if (!active_protocols[i])
+ continue;
+ protocols[i].fail_new_server(from, attached_to, info);
+ }
+
+ return 1;
+}
+
+void protocols_handle_unlink_server(struct string from, struct server_info *a, struct server_info *b, size_t protocol) {
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].handle_unlink_server(from, a, b, protocol);
+ }
+}
+
+int protocols_handle_new_user(struct string from, struct user_info *info) {
+ size_t i;
+ for (i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ if (protocols[i].handle_new_user(from, info) != 0)
+ goto protocols_handle_new_user_fail;
+ }
+
+ return 0;
+
+ protocols_handle_new_user_fail:
+ while (i > 0) {
+ i--;
+ if (!active_protocols[i])
+ continue;
+ protocols[i].fail_new_user(from, info);
+ }
+
+ return 1;
+}
+
+int protocols_handle_rename_user(struct string from, struct user_info *info, struct string nick, size_t timestamp, struct string timestamp_str) {
+ size_t i;
+ for (i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ if (protocols[i].handle_rename_user(from, info, nick, timestamp, timestamp_str) != 0)
+ goto protocols_handle_rename_user_fail;
+ }
+
+ return 0;
+
+ protocols_handle_rename_user_fail:
+ while (i > 0) {
+ i--;
+ if (!active_protocols[i])
+ continue;
+ protocols[i].fail_rename_user(from, info, nick, timestamp, timestamp_str);
+ }
+
+ return 1;
+}
+
+void protocols_handle_remove_user(struct string from, struct user_info *info, struct string reason, char propagate) {
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].handle_remove_user(from, info, reason, propagate);
+ }
+}
+
+void protocols_handle_kill_user(struct string from, struct string source, struct user_info *info, struct string reason) {
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].handle_kill_user(from, source, info, reason);
+ }
+}
+
+int protocols_handle_oper_user(struct string from, struct user_info *info, struct string type) {
+ size_t i;
+ for (i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ if (protocols[i].handle_oper_user(from, info, type) != 0)
+ goto protocols_handle_oper_user_fail;
+ }
+
+ return 0;
+
+ protocols_handle_oper_user_fail:
+ while (i > 0) {
+ i--;
+ if (!active_protocols[i])
+ continue;
+ protocols[i].fail_oper_user(from, info, type);
+ }
+
+ return 1;
+}
+
+int protocols_handle_set_channel(struct string from, struct channel_info *channel, char is_new_channel, size_t user_count, struct user_info **users) {
+ size_t i;
+ for (i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ if (protocols[i].handle_set_channel(from, channel, is_new_channel, user_count, users) != 0)
+ goto protocols_handle_set_channel_fail;
+ }
+
+ return 0;
+
+ protocols_handle_set_channel_fail:
+ while (i > 0) {
+ i--;
+ if (!active_protocols[i])
+ continue;
+ protocols[i].fail_set_channel(from, channel, is_new_channel, user_count, users);
+ }
+
+ return 1;
+}
+
+int protocols_handle_join_channel(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users, char propagate) {
+ size_t i;
+ for (i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ if (protocols[i].handle_join_channel(from, channel, user_count, users, propagate) != 0)
+ goto protocols_handle_join_channel_fail;
+ }
+
+ return 0;
+
+ protocols_handle_join_channel_fail:
+ while (i > 0) {
+ i--;
+ if (!active_protocols[i])
+ continue;
+ protocols[i].fail_join_channel(from, channel, user_count, users, propagate);
+ }
+
+ return 1;
+}
+
+void protocols_handle_part_channel(struct string from, struct channel_info *channel, struct user_info *user, struct string reason) {
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].handle_part_channel(from, channel, user, reason);
+ }
+}
+
+void protocols_handle_kick_channel(struct string from, struct string source, struct channel_info *channel, struct user_info *user, struct string reason) {
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].handle_kick_channel(from, source, channel, user, reason);
+ }
+}
+
+void protocols_fail_new_server(struct string from, struct string attached_to, struct server_info *info) {
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].fail_new_server(from, attached_to, info);
+ }
+}
+
+void protocols_fail_new_user(struct string from, struct user_info *info) {
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].fail_new_user(from, info);
+ }
+}
+
+void protocols_fail_rename_user(struct string from, struct user_info *info, struct string nick, size_t timestamp, struct string timestamp_str) {
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].fail_rename_user(from, info, nick, timestamp, timestamp_str);
+ }
+}
+
+void protocols_fail_oper_user(struct string from, struct user_info *info, struct string type) {
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].fail_oper_user(from, info, type);
+ }
+}
+
+void protocols_fail_set_channel(struct string from, struct channel_info *channel, char is_new_channel, size_t user_count, struct user_info **users) {
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].fail_set_channel(from, channel, is_new_channel, user_count, users);
+ }
+}
+
+void protocols_fail_join_channel(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users, char propagate) {
+ for (size_t i = 0; i < NUM_PROTOCOLS; i++) {
+ if (!active_protocols[i])
+ continue;
+ protocols[i].fail_join_channel(from, channel, user_count, users, propagate);
+ }
}
diff --git a/protocols.h b/protocols.h
index 61836bd..8ecf232 100644
--- a/protocols.h
+++ b/protocols.h
@@ -35,6 +35,8 @@
struct protocol {
int (*init)(void);
+ void (*fail_init)(void);
+
void * (*handle_connection)(void *info);
void * (*autoconnect)(void *config);
void (*update_propagations)(void);
@@ -58,6 +60,33 @@ struct protocol {
void (*propagate_privmsg)(struct string from, struct string source, struct string target, struct string msg);
void (*propagate_notice)(struct string from, struct string source, struct string target, struct string msg);
+ // Do whatever required with protocol-specific data here
+ int (*handle_new_server)(struct string from, struct string attached_to, struct server_info *info);
+ void (*handle_unlink_server)(struct string from, struct server_info *a, struct server_info *b, size_t protocol);
+
+ int (*handle_new_user)(struct string from, struct user_info *info);
+ int (*handle_rename_user)(struct string from, struct user_info *info, struct string nick, size_t timestamp, struct string timestamp_str);
+ void (*handle_remove_user)(struct string from, struct user_info *info, struct string reason, char propagate);
+ void (*handle_kill_user)(struct string from, struct string source, struct user_info *info, struct string reason);
+ int (*handle_oper_user)(struct string from, struct user_info *info, struct string type);
+
+ int (*handle_set_channel)(struct string from, struct channel_info *channel, char is_new_channel, size_t user_count, struct user_info **users);
+ int (*handle_join_channel)(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users, char propagate);
+ void (*handle_part_channel)(struct string from, struct channel_info *channel, struct user_info *user, struct string reason);
+ void (*handle_kick_channel)(struct string from, struct string source, struct channel_info *channel, struct user_info *user, struct string reason);
+ // ^^^^
+
+ // If some other protocol failed above after ours ran, these get called to clean up
+ void (*fail_new_server)(struct string from, struct string attached_to, struct server_info *info);
+
+ void (*fail_new_user)(struct string from, struct user_info *info);
+ void (*fail_rename_user)(struct string from, struct user_info *info, struct string nick, size_t timestamp, struct string timestamp_str);
+ void (*fail_oper_user)(struct string from, struct user_info *info, struct string type);
+
+ void (*fail_set_channel)(struct string from, struct channel_info *channel, char is_new_channel, size_t user_count, struct user_info **users);
+ void (*fail_join_channel)(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users, char propagate);
+ // ^^^^
+
void (*do_unlink)(struct string from, struct server_info *a, struct server_info *b);
};
@@ -75,11 +104,34 @@ void protocols_propagate_kill_user(struct string from, struct string source, str
void protocols_propagate_oper_user(struct string from, struct user_info *info, struct string type);
void protocols_propagate_set_channel(struct string from, struct channel_info *channel, char is_new_channel, size_t user_count, struct user_info **users);
-void protocols_propagate_join_channel(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users);
+void protocols_propagate_join_channel(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users, char propagate);
void protocols_propagate_part_channel(struct string from, struct channel_info *channel, struct user_info *user, struct string reason);
void protocols_propagate_kick_channel(struct string from, struct string source, struct channel_info *channel, struct user_info *user, struct string reason);
void protocols_propagate_privmsg(struct string from, struct string source, struct string target, struct string msg);
void protocols_propagate_notice(struct string from, struct string source, struct string target, struct string msg);
+int protocols_handle_new_server(struct string from, struct string attached_to, struct server_info *info);
+void protocols_handle_unlink_server(struct string from, struct server_info *a, struct server_info *b, size_t protocol);
+
+int protocols_handle_new_user(struct string from, struct user_info *info);
+int protocols_handle_rename_user(struct string from, struct user_info *info, struct string nick, size_t timestamp, struct string timestamp_str);
+void protocols_handle_remove_user(struct string from, struct user_info *info, struct string reason, char propagate);
+void protocols_handle_kill_user(struct string from, struct string source, struct user_info *info, struct string reason);
+int protocols_handle_oper_user(struct string from, struct user_info *info, struct string type);
+
+int protocols_handle_set_channel(struct string from, struct channel_info *channel, char is_new_channel, size_t user_count, struct user_info **users);
+int protocols_handle_join_channel(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users, char propagate);
+void protocols_handle_part_channel(struct string from, struct channel_info *channel, struct user_info *user, struct string reason);
+void protocols_handle_kick_channel(struct string from, struct string source, struct channel_info *channel, struct user_info *user, struct string reason);
+
+void protocols_fail_new_server(struct string from, struct string attached_to, struct server_info *info);
+
+void protocols_fail_new_user(struct string from, struct user_info *info);
+void protocols_fail_rename_user(struct string from, struct user_info *info, struct string nick, size_t timestamp, struct string timestamp_str);
+void protocols_fail_oper_user(struct string from, struct user_info *info, struct string type);
+
+void protocols_fail_set_channel(struct string from, struct channel_info *channel, char is_new_channel, size_t user_count, struct user_info **users);
+void protocols_fail_join_channel(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users, char propagate);
+
extern struct protocol protocols[NUM_PROTOCOLS];
diff --git a/protocols/inspircd2.c b/protocols/inspircd2.c
index cfc9cf9..0ae466c 100644
--- a/protocols/inspircd2.c
+++ b/protocols/inspircd2.c
@@ -152,6 +152,11 @@ int init_inspircd2_protocol(void) {
return 0;
}
+void init_inspircd2_protocol_fail(void) {
+ clear_table(&inspircd2_protocol_commands);
+ free(inspircd2_protocol_commands.array);
+}
+
void * inspircd2_protocol_connection(void *type) {
struct string address;
size_t net;
@@ -651,7 +656,7 @@ void inspircd2_protocol_propagate_set_channel(struct string from, struct channel
for (size_t x = 0; x < user_count; x++) {
inspircd2_protocol_propagate(from, STRING(","));
inspircd2_protocol_propagate(from, users[x]->uid);
- if (x != channel->user_list.len - 1)
+ if (x != user_count - 1)
inspircd2_protocol_propagate(from, STRING(" "));
}
inspircd2_protocol_propagate(from, STRING("\n"));
@@ -669,7 +674,7 @@ void inspircd2_protocol_propagate_join_channel(struct string from, struct channe
for (size_t x = 0; x < user_count; x++) {
inspircd2_protocol_propagate(from, STRING(","));
inspircd2_protocol_propagate(from, users[x]->uid);
- if (x != channel->user_list.len - 1)
+ if (x != user_count - 1)
inspircd2_protocol_propagate(from, STRING(" "));
}
inspircd2_protocol_propagate(from, STRING("\n"));
@@ -775,6 +780,74 @@ void inspircd2_protocol_propagate_notice(struct string from, struct string sourc
}
}
+int inspircd2_protocol_handle_new_server(struct string from, struct string attached_to, struct server_info *info) {
+ return 0;
+}
+
+void inspircd2_protocol_handle_unlink_server(struct string from, struct server_info *a, struct server_info *b, size_t protocol) {
+ return;
+}
+
+int inspircd2_protocol_handle_new_user(struct string from, struct user_info *info) {
+ return 0;
+}
+
+int inspircd2_protocol_handle_rename_user(struct string from, struct user_info *info, struct string nick, size_t timestamp, struct string timestamp_str) {
+ return 0;
+}
+
+void inspircd2_protocol_handle_remove_user(struct string from, struct user_info *info, struct string reason, char propagate) {
+ return;
+}
+
+void inspircd2_protocol_handle_kill_user(struct string from, struct string source, struct user_info *info, struct string reason) {
+ return;
+}
+
+int inspircd2_protocol_handle_oper_user(struct string from, struct user_info *info, struct string type) {
+ return 0;
+}
+
+int inspircd2_protocol_handle_set_channel(struct string from, struct channel_info *channel, char is_new_channel, size_t user_count, struct user_info **users) {
+ return 0;
+}
+
+int inspircd2_protocol_handle_join_channel(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users, char propagate) {
+ return 0;
+}
+
+void inspircd2_protocol_handle_part_channel(struct string from, struct channel_info *channel, struct user_info *user, struct string reason) {
+ return;
+}
+
+void inspircd2_protocol_handle_kick_channel(struct string from, struct string source, struct channel_info *channel, struct user_info *user, struct string reason) {
+ return;
+}
+
+void inspircd2_protocol_fail_new_server(struct string from, struct string attached_to, struct server_info *info) {
+ return;
+}
+
+void inspircd2_protocol_fail_new_user(struct string from, struct user_info *info) {
+ return;
+}
+
+void inspircd2_protocol_fail_rename_user(struct string from, struct user_info *info, struct string nick, size_t timestamp, struct string timestamp_str) {
+ return;
+}
+
+void inspircd2_protocol_fail_oper_user(struct string from, struct user_info *info, struct string type) {
+ return;
+}
+
+void inspircd2_protocol_fail_set_channel(struct string from, struct channel_info *channel, char is_new_channel, size_t user_count, struct user_info **users) {
+ return;
+}
+
+void inspircd2_protocol_fail_join_channel(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users, char propagate) {
+ return;
+}
+
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
diff --git a/protocols/inspircd2.h b/protocols/inspircd2.h
index 315e012..ef13fa8 100644
--- a/protocols/inspircd2.h
+++ b/protocols/inspircd2.h
@@ -37,6 +37,7 @@ extern struct table inspircd2_protocol_init_commands;
extern struct table inspircd2_protocol_commands;
int init_inspircd2_protocol(void);
+void init_inspircd2_protocol_fail(void);
void * inspircd2_protocol_connection(void *type);
void * inspircd2_protocol_autoconnect(void *type);
@@ -61,6 +62,29 @@ void inspircd2_protocol_propagate_kick_channel(struct string from, struct string
void inspircd2_protocol_propagate_privmsg(struct string from, struct string source, struct string target, struct string msg);
void inspircd2_protocol_propagate_notice(struct string from, struct string source, struct string target, struct string msg);
+int inspircd2_protocol_handle_new_server(struct string from, struct string attached_to, struct server_info *info);
+void inspircd2_protocol_handle_unlink_server(struct string from, struct server_info *a, struct server_info *b, size_t protocol);
+
+int inspircd2_protocol_handle_new_user(struct string from, struct user_info *info);
+int inspircd2_protocol_handle_rename_user(struct string from, struct user_info *info, struct string nick, size_t timestamp, struct string timestamp_str);
+void inspircd2_protocol_handle_remove_user(struct string from, struct user_info *info, struct string reason, char propagate);
+void inspircd2_protocol_handle_kill_user(struct string from, struct string source, struct user_info *info, struct string reason);
+int inspircd2_protocol_handle_oper_user(struct string from, struct user_info *info, struct string type);
+
+int inspircd2_protocol_handle_set_channel(struct string from, struct channel_info *channel, char is_new_channel, size_t user_count, struct user_info **users);
+int inspircd2_protocol_handle_join_channel(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users, char propagate);
+void inspircd2_protocol_handle_part_channel(struct string from, struct channel_info *channel, struct user_info *user, struct string reason);
+void inspircd2_protocol_handle_kick_channel(struct string from, struct string source, struct channel_info *channel, struct user_info *user, struct string reason);
+
+void inspircd2_protocol_fail_new_server(struct string from, struct string attached_to, struct server_info *info);
+
+void inspircd2_protocol_fail_new_user(struct string from, struct user_info *info);
+void inspircd2_protocol_fail_rename_user(struct string from, struct user_info *info, struct string nick, size_t timestamp, struct string timestamp_str);
+void inspircd2_protocol_fail_oper_user(struct string from, struct user_info *info, struct string type);
+
+void inspircd2_protocol_fail_set_channel(struct string from, struct channel_info *channel, char is_new_channel, size_t user_count, struct user_info **users);
+void inspircd2_protocol_fail_join_channel(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users, char propagate);
+
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);
diff --git a/protocols/inspircd3.c b/protocols/inspircd3.c
index 1124dd7..5593e8b 100644
--- a/protocols/inspircd3.c
+++ b/protocols/inspircd3.c
@@ -140,7 +140,7 @@ int init_inspircd3_protocol(void) {
set_table_index(&inspircd3_protocol_commands, STRING("KILL"), &inspircd3_protocol_handle_kill);
set_table_index(&inspircd3_protocol_commands, STRING("OPERTYPE"), &inspircd3_protocol_handle_opertype);
-// set_table_index(&inspircd3_protocol_commands, STRING("FJOIN"), &inspircd3_protocol_handle_fjoin);
+ set_table_index(&inspircd3_protocol_commands, STRING("FJOIN"), &inspircd3_protocol_handle_fjoin);
// set_table_index(&inspircd3_protocol_commands, STRING("PART"), &inspircd3_protocol_handle_part);
// set_table_index(&inspircd3_protocol_commands, STRING("KICK"), &inspircd3_protocol_handle_kick);
//
@@ -150,6 +150,11 @@ int init_inspircd3_protocol(void) {
return 0;
}
+void init_inspircd3_protocol_fail(void) {
+ clear_table(&inspircd3_protocol_commands);
+ free(inspircd3_protocol_commands.array);
+}
+
void * inspircd3_protocol_connection(void *type) {
struct string address;
size_t net;
@@ -661,7 +666,7 @@ void inspircd3_protocol_propagate_set_channel(struct string from, struct channel
for (size_t x = 0; x < user_count; x++) {
inspircd3_protocol_propagate(from, STRING(","));
inspircd3_protocol_propagate(from, users[x]->uid);
- if (x != channel->user_list.len - 1)
+ if (x != user_count - 1)
inspircd3_protocol_propagate(from, STRING(" "));
}
inspircd3_protocol_propagate(from, STRING("\n"));
@@ -679,7 +684,7 @@ void inspircd3_protocol_propagate_join_channel(struct string from, struct channe
for (size_t x = 0; x < user_count; x++) {
inspircd3_protocol_propagate(from, STRING(","));
inspircd3_protocol_propagate(from, users[x]->uid);
- if (x != channel->user_list.len - 1)
+ if (x != user_count - 1)
inspircd3_protocol_propagate(from, STRING(" "));
}
inspircd3_protocol_propagate(from, STRING("\n"));
@@ -785,6 +790,87 @@ void inspircd3_protocol_propagate_notice(struct string from, struct string sourc
}
}
+int inspircd3_protocol_handle_new_server(struct string from, struct string attached_to, struct server_info *info) {
+ return 0;
+}
+
+void inspircd3_protocol_handle_unlink_server(struct string from, struct server_info *a, struct server_info *b, size_t protocol) {
+ return;
+}
+
+int inspircd3_protocol_handle_new_user(struct string from, struct user_info *info) {
+ struct inspircd3_protocol_specific_user *prot_info;
+ prot_info = malloc(sizeof(*prot_info));
+ if (!prot_info)
+ return 1;
+
+ prot_info->memberships.array = malloc(0);
+
+ info->protocol_specific[INSPIRCD3_PROTOCOL] = prot_info;
+
+ return 0;
+}
+
+int inspircd3_protocol_handle_rename_user(struct string from, struct user_info *info, struct string nick, size_t timestamp, struct string timestamp_str) {
+ return 0;
+}
+
+void inspircd3_protocol_handle_remove_user(struct string from, struct user_info *info, struct string reason, char propagate) {
+ return;
+}
+
+void inspircd3_protocol_handle_kill_user(struct string from, struct string source, struct user_info *info, struct string reason) {
+ return;
+}
+
+int inspircd3_protocol_handle_oper_user(struct string from, struct user_info *info, struct string type) {
+ return 0;
+}
+
+int inspircd3_protocol_handle_set_channel(struct string from, struct channel_info *channel, char is_new_channel, size_t user_count, struct user_info **users) {
+ return 0;
+}
+
+int inspircd3_protocol_handle_join_channel(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users, char propagate) {
+ return 0;
+}
+
+void inspircd3_protocol_handle_part_channel(struct string from, struct channel_info *channel, struct user_info *user, struct string reason) {
+ return;
+}
+
+void inspircd3_protocol_handle_kick_channel(struct string from, struct string source, struct channel_info *channel, struct user_info *user, struct string reason) {
+ return;
+}
+
+void inspircd3_protocol_fail_new_server(struct string from, struct string attached_to, struct server_info *info) {
+ return;
+}
+
+void inspircd3_protocol_fail_new_user(struct string from, struct user_info *info) {
+ struct inspircd3_protocol_specific_user *prot_info = info->protocol_specific[INSPIRCD3_PROTOCOL];
+ free(prot_info->memberships.array);
+ free(prot_info);
+
+ return;
+}
+
+void inspircd3_protocol_fail_rename_user(struct string from, struct user_info *info, struct string nick, size_t timestamp, struct string timestamp_str) {
+ return;
+}
+
+void inspircd3_protocol_fail_oper_user(struct string from, struct user_info *info, struct string type) {
+ return;
+}
+
+void inspircd3_protocol_fail_set_channel(struct string from, struct channel_info *channel, char is_new_channel, size_t user_count, struct user_info **users) {
+ return;
+}
+
+void inspircd3_protocol_fail_join_channel(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users, char propagate) {
+ return;
+}
+
void inspircd3_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
@@ -1346,112 +1432,118 @@ int inspircd3_protocol_handle_opertype(struct string source, size_t argc, struct
return 0;
}
-//// [:source] FJOIN <channel> <timestamp> <modes> [<mode args>] <userlist: modes,uid [...]>
-//int inspircd3_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 v3] 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 v3] 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 v3] Invalid FJOIN recieved (Mode direction not set)\r\n"));
-// return -1;
-// }
-// switch(inspircd3_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 v3] Invalid FJOIN recieved! (User mode put in the modes instead of the user list)\r\n"));
-// return -1;
-// default:
-// WRITES(2, STRING("[InspIRCd v3] 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 v3] [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 inspircd3_protocol_handle_fjoin_free_users;
-// } else {
-// if (join_channel(config->sid, channel, user_count, users, 1) != 0)
-// goto inspircd3_protocol_handle_fjoin_free_users;
-// }
-//
-// free(users);
-//
-// return 0;
-//
-// inspircd3_protocol_handle_fjoin_free_users:
-// free(users);
-// return -1;
-//}
-//
+// [:source] FJOIN <channel> <timestamp> <modes> [<mode args>] <userlist: modes,uid [...]>
+int inspircd3_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 v3] 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 v3] 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 v3] Invalid FJOIN recieved (Mode direction not set)\r\n"));
+ return -1;
+ }
+ switch(inspircd3_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 v3] Invalid FJOIN recieved! (User mode put in the modes instead of the user list)\r\n"));
+ return -1;
+ default:
+ WRITES(2, STRING("[InspIRCd v3] 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++;
+
+ while (i < argv[arg_i].len && argv[arg_i].data[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 v3] [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--;
+ }
+
+ while (i < argv[arg_i].len && argv[arg_i].data[i] != ' ')
+ i++;
+ }
+
+ 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 inspircd3_protocol_handle_fjoin_free_users;
+ } else {
+ if (join_channel(config->sid, channel, user_count, users, 1) != 0)
+ goto inspircd3_protocol_handle_fjoin_free_users;
+ }
+
+ free(users);
+
+ return 0;
+
+ inspircd3_protocol_handle_fjoin_free_users:
+ free(users);
+ return -1;
+}
+
//// :source PART <channel> [<reason>]
//int inspircd3_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) {
diff --git a/protocols/inspircd3.h b/protocols/inspircd3.h
index 060e85d..e5a45ba 100644
--- a/protocols/inspircd3.h
+++ b/protocols/inspircd3.h
@@ -41,6 +41,7 @@ extern struct table inspircd3_protocol_init_commands;
extern struct table inspircd3_protocol_commands;
int init_inspircd3_protocol(void);
+void init_inspircd3_protocol_fail(void);
void * inspircd3_protocol_connection(void *type);
void * inspircd3_protocol_autoconnect(void *type);
@@ -65,6 +66,29 @@ void inspircd3_protocol_propagate_kick_channel(struct string from, struct string
void inspircd3_protocol_propagate_privmsg(struct string from, struct string source, struct string target, struct string msg);
void inspircd3_protocol_propagate_notice(struct string from, struct string source, struct string target, struct string msg);
+int inspircd3_protocol_handle_new_server(struct string from, struct string attached_to, struct server_info *info);
+void inspircd3_protocol_handle_unlink_server(struct string from, struct server_info *a, struct server_info *b, size_t protocol);
+
+int inspircd3_protocol_handle_new_user(struct string from, struct user_info *info);
+int inspircd3_protocol_handle_rename_user(struct string from, struct user_info *info, struct string nick, size_t timestamp, struct string timestamp_str);
+void inspircd3_protocol_handle_remove_user(struct string from, struct user_info *info, struct string reason, char propagate);
+void inspircd3_protocol_handle_kill_user(struct string from, struct string source, struct user_info *info, struct string reason);
+int inspircd3_protocol_handle_oper_user(struct string from, struct user_info *info, struct string type);
+
+int inspircd3_protocol_handle_set_channel(struct string from, struct channel_info *channel, char is_new_channel, size_t user_count, struct user_info **users);
+int inspircd3_protocol_handle_join_channel(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users, char propagate);
+void inspircd3_protocol_handle_part_channel(struct string from, struct channel_info *channel, struct user_info *user, struct string reason);
+void inspircd3_protocol_handle_kick_channel(struct string from, struct string source, struct channel_info *channel, struct user_info *user, struct string reason);
+
+void inspircd3_protocol_fail_new_server(struct string from, struct string attached_to, struct server_info *info);
+
+void inspircd3_protocol_fail_new_user(struct string from, struct user_info *info);
+void inspircd3_protocol_fail_rename_user(struct string from, struct user_info *info, struct string nick, size_t timestamp, struct string timestamp_str);
+void inspircd3_protocol_fail_oper_user(struct string from, struct user_info *info, struct string type);
+
+void inspircd3_protocol_fail_set_channel(struct string from, struct channel_info *channel, char is_new_channel, size_t user_count, struct user_info **users);
+void inspircd3_protocol_fail_join_channel(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users, char propagate);
+
void inspircd3_protocol_do_unlink(struct string from, struct server_info *a, struct server_info *b);
void inspircd3_protocol_update_propagations_inner(struct server_info *source);