diff --git a/src/XMPP/MUC.c b/src/XMPP/MUC.c index 1f9ad1e..cbdd91e 100644 --- a/src/XMPP/MUC.c +++ b/src/XMPP/MUC.c @@ -15,7 +15,6 @@ XMPPQueryMUC(XMPPComponent *jabber, char *muc, MUCInfo *out) char *uuid, *from; if (!jabber || !muc) { - Log(LOG_WARNING, ":("); return false; } @@ -40,8 +39,9 @@ XMPPQueryMUC(XMPPComponent *jabber, char *muc, MUCInfo *out) StreamFlush(jabber->stream); XMLFreeElement(iq_query); - /* Except an IQ reply */ - iq_query = ParseeAwaitStanza(uuid); + /* Except an IQ reply. 10 seconds of timeout is pretty + * generous, if you ask me. */ + iq_query = ParseeAwaitStanza(uuid, 10 SECONDS); Free(uuid); if (!iq_query || !StrEquals(iq_query->name, "iq")) { diff --git a/src/XMPPThread.c b/src/XMPPThread.c index 2af4d7d..64a4b32 100644 --- a/src/XMPPThread.c +++ b/src/XMPPThread.c @@ -65,6 +65,7 @@ ParseeMXID(ParseeData *data) ":", data->config->homeserver_host); } +/* Performs i;octet collation. */ static int ICollate(unsigned char *cata, unsigned char *catb) { @@ -1453,8 +1454,11 @@ ParseeXMPPThread(void *argp) pthread_mutex_destroy(&info.lock); return NULL; } + +#include +#include XMLElement * -ParseeAwaitStanza(char *identifier) +ParseeAwaitStanza(char *identifier, int64_t timeout) { /* TODO: Pthreads HATE me using Malloc here, so I'm abusing stackspace. * Not *too much* of a problem, just a weird oddity. If anyone has a clue @@ -1462,11 +1466,24 @@ ParseeAwaitStanza(char *identifier) * me know! */ XMPPAwait awa; XMLElement *stanza; + struct timespec ts; if (!identifier) { return NULL; } + if (timeout > 0) + { + int64_t seconds = timeout / (1 SECONDS); + int64_t msecond = timeout % (1 SECONDS); + + clock_gettime(CLOCK_REALTIME, &ts); + + ts.tv_sec += seconds ; + ts.tv_nsec+= msecond * 1000000 ; + + } + pthread_mutex_lock(&await_lock); pthread_cond_init(&awa.condition, NULL); @@ -1479,8 +1496,20 @@ ParseeAwaitStanza(char *identifier) pthread_mutex_lock(&awa.cond_lock); while (!awa.stanza) { - /* TODO: Allow timeouts. */ - pthread_cond_wait(&awa.condition, &awa.cond_lock); + int code; + + if (timeout <= 0) + { + pthread_cond_wait(&awa.condition, &awa.cond_lock); + continue; + } + code = pthread_cond_timedwait(&awa.condition, &awa.cond_lock, &ts); + if (code == ETIMEDOUT) + { + /* Timeout detected, give up regardless of the status of our + * search. */ + break; + } } stanza = awa.stanza; diff --git a/src/include/Parsee.h b/src/include/Parsee.h index ac4f295..814be5f 100644 --- a/src/include/Parsee.h +++ b/src/include/Parsee.h @@ -115,8 +115,13 @@ extern void ParseeRequest(HttpServerContext *, void *); /* A pthread callback used for listening to a component */ extern void * ParseeXMPPThread(void *data); -/* Wait for a specific stanza with an ID */ -extern XMLElement * ParseeAwaitStanza(char *identifier); +/** Wait for any stanza with an "id" attribute of {identifier}, + * with an optional timeout in milliseconds of {ts} if it is positive. + * -------- + * UB-If: called in the XMPP dispatcher thread itself + * Returns: NULL | XMLElement[LA:HEAP] + * Modifies: NONE */ +extern XMLElement * ParseeAwaitStanza(char *identifier, int64_t ts); /* Finds the room a DM is associated to, from a Matrix user and a Jabber * ID. */ diff --git a/src/include/XMPP.h b/src/include/XMPP.h index 29fe081..550293b 100644 --- a/src/include/XMPP.h +++ b/src/include/XMPP.h @@ -46,12 +46,18 @@ typedef struct MUCInfo { XMLElement *iq_reply; } MUCInfo; -/* Queries a MUC's existence, and if $[out] is set, stores information - * pertaining the MUC itself from an query, to be freed by - * XMPPFreeMUCInfo */ +/** Queries a MUC's existence, and if {out} is set, stores information + * pertaining the MUC itself from an IQ query. + * ---------------------------------------------------------------------- + * Modifies: *out[TBFB:XMPPFreeMUCInfo] + * See-Also: XMPPGetMUCName, XMPPFreeMUCInfo */ extern bool XMPPQueryMUC(XMPPComponent *jabber, char *muc, MUCInfo *out); -/* Retrieves the MUC's name from an IQ reply */ +/** Retrieves the MUC's name from an IQ reply + * ---------------------------------------------------------------------- + * Returns: The MUC's name[LA:HEAP] | NULL + * Modifies: NOTHING + * See-Also: XMPPQueryMUC, XMPPFreeMUCInfo */ extern char * XMPPGetMUCName(MUCInfo info); extern void XMPPFreeMUCInfo(MUCInfo info);