pidgin/pidgin

Parents 92c8a7e3aaf5
Children b7f9345b02a4
Add an atomic reference counters to the IRCv3 capabilities to track when we're done with negotiation

Testing Done:
Connected an IRCv3 account to a local ergo instance and verified that the capabilties we ended properly.

Reviewed at https://reviews.imfreedom.org/r/2180/
--- 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 @@
GHashTable *caps;
GPtrArray *requests;
+
+ gatomicrefcount wait_counters;
};
/******************************************************************************
@@ -105,6 +107,9 @@
{
gboolean found = FALSE;
+ /* 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);
if(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,
g_free);
capabilities->requests = g_ptr_array_new_full(0, g_free);
+
+ g_atomic_ref_count_init(&capabilities->wait_counters);
}
static void
@@ -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 @@
g_free(caps);
if(capabilities->requests->len == 0) {
- purple_ircv3_capabilities_finish(capabilities);
+ purple_ircv3_capabilities_remove_wait(capabilities);
}
return ret;
@@ -592,3 +599,19 @@
return value;
}
+
+void
+purple_ircv3_capabilities_add_wait(PurpleIRCv3Capabilities *capabilities) {
+ g_return_if_fail(PURPLE_IRCV3_IS_CAPABILITIES(capabilities));
+
+ g_atomic_ref_count_inc(&capabilities->wait_counters);
+}
+
+void
+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.
+ *
+ * Since: 3.0.0
+ */
+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
+ * well.
+ *
+ * Since: 3.0.0
+ */
+void purple_ircv3_capabilities_remove_wait(PurpleIRCv3Capabilities *capabilities);
+
G_END_DECLS
#endif /* PURPLE_IRCV3_CAPABILITIES_H */