--- a/libpurple/protocols/ircv3/purpleircv3capabilities.c Thu Jan 05 22:40:46 2023 -0600
+++ b/libpurple/protocols/ircv3/purpleircv3capabilities.c Thu Jan 05 22:41:48 2023 -0600
@@ -56,6 +56,8 @@
+ gatomicrefcount wait_counters; /******************************************************************************
@@ -105,6 +107,9 @@
+ /* cap-notify is implied when we use CAP LS 302, so this is really just to + * make sure it's requested. purple_ircv3_capabilities_lookup(capabilities, "cap-notify", &found);
purple_ircv3_capabilities_request(capabilities, "cap-notify");
@@ -175,6 +180,8 @@
capabilities->caps = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
capabilities->requests = g_ptr_array_new_full(0, g_free);
+ g_atomic_ref_count_init(&capabilities->wait_counters); @@ -386,7 +393,7 @@
* we're done with capability negotiation.
if(capabilities->requests->len == 0) {
- purple_ircv3_capabilities_finish(capabilities);
+ purple_ircv3_capabilities_remove_wait(capabilities); @@ -419,7 +426,7 @@
if(capabilities->requests->len == 0) {
- purple_ircv3_capabilities_finish(capabilities);
+ purple_ircv3_capabilities_remove_wait(capabilities); @@ -592,3 +599,19 @@
+purple_ircv3_capabilities_add_wait(PurpleIRCv3Capabilities *capabilities) { + g_return_if_fail(PURPLE_IRCV3_IS_CAPABILITIES(capabilities)); + g_atomic_ref_count_inc(&capabilities->wait_counters); +purple_ircv3_capabilities_remove_wait(PurpleIRCv3Capabilities *capabilities) { + g_return_if_fail(PURPLE_IRCV3_IS_CAPABILITIES(capabilities)); + if(g_atomic_ref_count_dec(&capabilities->wait_counters)) { + purple_ircv3_capabilities_finish(capabilities); --- a/libpurple/protocols/ircv3/purpleircv3capabilities.h Thu Jan 05 22:40:46 2023 -0600
+++ b/libpurple/protocols/ircv3/purpleircv3capabilities.h Thu Jan 05 22:41:48 2023 -0600
@@ -84,6 +84,32 @@
const char *purple_ircv3_capabilities_lookup(PurpleIRCv3Capabilities *capabilities, const char *name, gboolean *found);
+ * purple_ircv3_capabilties_add_wait: + * @capabilities: The instance. + * Adds a wait counter to @capabilities. This counter is used to delay the + * call of `CAP END` until all capability negotiation has completed. This is + * necessary for SASL and may be necessary for other capabilities as well. +void purple_ircv3_capabilities_add_wait(PurpleIRCv3Capabilities *capabilities); + * purple_ircv3_capabilties_remove_wait: + * @capabilities: The instance. + * Removes a wait counter from @capabilities. Only when this counter reaches 0, + * will `CAP END` be called and registration completed. + * This is necessary for SASL and may be necessary for other capabilities as +void purple_ircv3_capabilities_remove_wait(PurpleIRCv3Capabilities *capabilities); #endif /* PURPLE_IRCV3_CAPABILITIES_H */