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
This commit is contained in:
2025-12-06 15:06:02 +03:00
parent d09adad0e1
commit fdb615a213
10 changed files with 105 additions and 0 deletions

View File

@@ -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)
{

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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);