From fdb615a2138bcf5125708c83f7d4e9ed5d121acf Mon Sep 17 00:00:00 2001 From: "jabber.developer2" Date: Sat, 6 Dec 2025 15:06:02 +0300 Subject: [PATCH] feat: Add stbbr_for_presence_to for MUC join presence matching - Add prime_for_presence_to() and prime_get_for_presence_to() in prime.c - Add presence_to_callback() in server.c to handle MUC join presence - Export stbbr_for_presence_to() in stabber.h - Add stanzas_debug_last() for debugging failed verifications --- src/client/stabber.c | 7 +++++++ src/server/prime.c | 29 +++++++++++++++++++++++++++++ src/server/prime.h | 3 +++ src/server/server.c | 30 ++++++++++++++++++++++++++++++ src/server/server.h | 3 +++ src/server/stanzas.c | 24 ++++++++++++++++++++++++ src/server/stanzas.h | 2 ++ src/server/stream_parser.c | 4 ++++ src/server/verify.c | 2 ++ stabber.h | 1 + 10 files changed, 105 insertions(+) diff --git a/src/client/stabber.c b/src/client/stabber.c index 353d5ff..290e0ce 100644 --- a/src/client/stabber.c +++ b/src/client/stabber.c @@ -63,6 +63,13 @@ stbbr_for_query(char *query, char *stream) return 1; } +int +stbbr_for_presence_to(char *to_jid, char *stream) +{ + prime_for_presence_to(to_jid, stream); + return 1; +} + void stbbr_wait_for(char *id) { diff --git a/src/server/prime.c b/src/server/prime.c index 5cf7663..7cafac0 100644 --- a/src/server/prime.c +++ b/src/server/prime.c @@ -33,6 +33,7 @@ static char *required_passwd = NULL; static GHashTable *idstubs = NULL; static GHashTable *querystubs = NULL; +static GHashTable *presence_to_stubs = NULL; void prime_init(void) @@ -40,6 +41,7 @@ prime_init(void) required_passwd = strdup("password"); idstubs = g_hash_table_new_full(g_str_hash, g_str_equal, free, free); querystubs = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)stanza_free); + presence_to_stubs = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)stanza_free); } void @@ -57,6 +59,11 @@ prime_free_all(void) g_hash_table_destroy(querystubs); } querystubs = NULL; + + if (presence_to_stubs) { + g_hash_table_destroy(presence_to_stubs); + } + presence_to_stubs = NULL; } void @@ -112,3 +119,25 @@ prime_get_for_query(const char *query) return g_hash_table_lookup(querystubs, query); } + +void +prime_for_presence_to(const char *to_jid, char *stream) +{ + if (!presence_to_stubs) { + return; + } + + log_println(STBBR_LOGDEBUG, "Received stub for presence to: %s, stanza: %s", to_jid, stream); + XMPPStanza *stanza = stanza_parse(stream); + g_hash_table_insert(presence_to_stubs, strdup(to_jid), stanza); +} + +XMPPStanza* +prime_get_for_presence_to(const char *to_jid) +{ + if (!presence_to_stubs) { + return NULL; + } + + return g_hash_table_lookup(presence_to_stubs, to_jid); +} diff --git a/src/server/prime.h b/src/server/prime.h index 5c5c7ac..694657d 100644 --- a/src/server/prime.h +++ b/src/server/prime.h @@ -37,4 +37,7 @@ char* prime_get_for_id(const char *id); int prime_for_query(const char *query, char *stream); XMPPStanza* prime_get_for_query(const char *query); +int prime_for_presence_to(const char *to_jid, char *stream); +XMPPStanza* prime_get_for_presence_to(const char *to_jid); + #endif diff --git a/src/server/server.c b/src/server/server.c index f8ba39f..ef04ae0 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -261,6 +261,36 @@ query_callback(const char *query, const char *id) free(stream); } +void +presence_to_callback(XMPPStanza *stanza) +{ + if (!stanza || g_strcmp0(stanza->name, "presence") != 0) { + return; + } + + const char *to_jid = stanza_get_attr(stanza, "to"); + if (!to_jid) { + return; + } + + XMPPStanza *response = prime_get_for_presence_to(to_jid); + if (!response) { + return; + } + + log_println(STBBR_LOGINFO, "--> PRESENCE TO callback fired for '%s'", to_jid); + + // Copy the id from the incoming stanza to the response + const char *id = stanza_get_id(stanza); + if (id) { + stanza_set_id(response, id); + } + + char *stream = stanza_to_string(response); + write_stream(stream); + free(stream); +} + void server_wait_for(char *id) { diff --git a/src/server/server.h b/src/server/server.h index 5f86df3..0647dc3 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -24,6 +24,7 @@ #define __H_SERVER #include "stabber.h" +#include "server/stanza.h" int server_run(stbbr_log_t loglevel, int port, int httpport); void server_stop(void); @@ -32,4 +33,6 @@ void server_wait_for(char *id); void server_send(char *stream); +void presence_to_callback(XMPPStanza *stanza); + #endif diff --git a/src/server/stanzas.c b/src/server/stanzas.c index 0e27412..bdeead7 100644 --- a/src/server/stanzas.c +++ b/src/server/stanzas.c @@ -115,6 +115,30 @@ stanzas_verify_last(XMPPStanza *stanza) } } +void +stanzas_debug_last(void) +{ + pthread_mutex_lock(&stanzas_lock); + if (!stanzas) { + log_println(STBBR_LOGINFO, "DEBUG: No stanzas received yet"); + pthread_mutex_unlock(&stanzas_lock); + return; + } + + GList *last = g_list_last(stanzas); + if (!last) { + log_println(STBBR_LOGINFO, "DEBUG: Stanza list empty"); + pthread_mutex_unlock(&stanzas_lock); + return; + } + + XMPPStanza *last_stanza = (XMPPStanza *)last->data; + char *stanza_str = stanza_to_string(last_stanza); + log_println(STBBR_LOGINFO, "DEBUG LAST RECEIVED: %s", stanza_str); + free(stanza_str); + pthread_mutex_unlock(&stanzas_lock); +} + void stanzas_free_all(void) { diff --git a/src/server/stanzas.h b/src/server/stanzas.h index 2fed655..1b3e857 100644 --- a/src/server/stanzas.h +++ b/src/server/stanzas.h @@ -32,6 +32,8 @@ void stanzas_add(XMPPStanza *stanza); int stanzas_verify_any(XMPPStanza *stanza); int stanzas_verify_last(XMPPStanza *stanza); +void stanzas_debug_last(void); + int stanzas_contains_id(char *id); void stanzas_free_all(void); diff --git a/src/server/stream_parser.c b/src/server/stream_parser.c index 3e91e30..4f17041 100644 --- a/src/server/stream_parser.c +++ b/src/server/stream_parser.c @@ -29,6 +29,8 @@ #include "server/stanza.h" #include "server/stanzas.h" #include "server/log.h" +#include "server/prime.h" +#include "server/server.h" static int depth = 0; static int do_reset = 0; @@ -190,6 +192,8 @@ _end_element(void *data, const char *element) if (query) { query_cb(query, id); } + // Check for presence with "to" attribute (for MUC join responses) + presence_to_callback(curr_stanza); } // Don't reset parser here - allow multiple root elements for XMPP stanzas diff --git a/src/server/verify.c b/src/server/verify.c index 808ba59..46c62fc 100644 --- a/src/server/verify.c +++ b/src/server/verify.c @@ -100,6 +100,8 @@ verify_last(char *stanza_text) log_println(STBBR_LOGINFO, "VERIFY LAST SUCCESS: %s", stanza_text); } else { log_println(STBBR_LOGINFO, "VERIFY LAST FAIL: %s", stanza_text); + // Debug: show what was actually received + stanzas_debug_last(); } return result; diff --git a/stabber.h b/stabber.h index daa2ad0..5a20b74 100644 --- a/stabber.h +++ b/stabber.h @@ -38,6 +38,7 @@ void stbbr_set_timeout(int seconds); int stbbr_auth_passwd(char *password); int stbbr_for_id(char *id, char *stream); int stbbr_for_query(char *query, char *stream); +int stbbr_for_presence_to(char *to_jid, char *stream); void stbbr_wait_for(char *id);