From 02a89270c04e3d395d77d14cac410ead3c8f95c2 Mon Sep 17 00:00:00 2001 From: LDA Date: Sun, 20 Oct 2024 12:53:07 +0200 Subject: [PATCH] [FIX] Kill Parsee on unexcepted stream closure --- README.MD | 11 ++++++++--- src/Main.c | 3 ++- src/Parsee/Data.c | 4 ++++ src/Signal.c | 21 +++++++++++---------- src/XMPPThread/ReListener.c | 14 ++++++++++++++ src/include/Parsee.h | 11 ++++++++++- 6 files changed, 49 insertions(+), 15 deletions(-) diff --git a/README.MD b/README.MD index e6e7185..7522deb 100644 --- a/README.MD +++ b/README.MD @@ -92,14 +92,19 @@ restricted to Parsee admins, with permission from MUC owners, too be false by default. - Currently, MUC owners may kick Parsee out, with the effect of unlinking the MUC. +- Rewrite the XMPP command management to actually be aware of context, instead of +being a baked-in X-macro. It could be useful for MUC admins, which may use commands +specifically within the MUC's own context rather than the global Parsee context(for +Parsee admins). - Look at XEPS-TBD.TXT for XEPs to be done - Add a MUC server to Parsee, such that it may be able to hook onto it and therefore support XMPP->Matrix bridging. - Manage MUC DMs in a reasonable manner. Thanks `@freeoffers4u:matrix.org` for being a fucking annoyance and DMing an old Parsee semi-anon user for no clear reason. -- Make Parsee cope well with unexcepted stream closures (e.g: with an XMPP server -turning off, etc...). Shutting it off seems like an easy solution, but would go -against principles. +- Make Parsee cope with stream closures(i.e: XMPP server turning off) better. As of +now, it just kills itself when that happens, instead of trying to negociate a new +connection, which would be a better method that would actually fit Parsee's own +principles. ## DONATING/CONTRIBUTING If you know things about XMPP or Matrix, yet aren't familiar with C99, or just diff --git a/src/Main.c b/src/Main.c index d407d60..42cc40d 100644 --- a/src/Main.c +++ b/src/Main.c @@ -265,8 +265,9 @@ Main(Array *args, HashMap *env) } server = HttpServerCreate(&conf); + ((ParseeData *) conf.handlerArgs)->server = server; - if (!ParseeInitialiseSignals(server, xmpp_thr, jabber)) + if (!ParseeInitialiseSignals(conf.handlerArgs, xmpp_thr)) { goto end; } diff --git a/src/Parsee/Data.c b/src/Parsee/Data.c index 0ca2dce..446e766 100644 --- a/src/Parsee/Data.c +++ b/src/Parsee/Data.c @@ -32,6 +32,9 @@ ParseeInitData(XMPPComponent *comp) data->oid_servers = HashMapCreate(); pthread_mutex_init(&data->oidl, NULL); + data->halted = false; + pthread_mutex_init(&data->halt_lock, NULL); + if (data->config->db_size) { data->db = DbOpenLMDB(data->config->db_path, data->config->db_size); @@ -109,6 +112,7 @@ ParseeFreeData(ParseeData *data) } HashMapFree(data->oid_servers); pthread_mutex_destroy(&data->oidl); + pthread_mutex_destroy(&data->halt_lock); Free(data->id); XMPPEndCompStream(data->jabber); DbClose(data->db); diff --git a/src/Signal.c b/src/Signal.c index 9335897..e9d00e8 100644 --- a/src/Signal.c +++ b/src/Signal.c @@ -6,39 +6,40 @@ #include -static HttpServer *server = NULL; +static ParseeData *data; static pthread_t xmpp_thr; -static XMPPComponent *jabber = NULL; static void SignalHandler(int signal) { - if (server && (signal == SIGTERM || signal == SIGINT)) + if (data->server && (signal == SIGTERM || signal == SIGINT)) { Log(LOG_INFO, "Killing thread..."); - XMPPFinishCompStream(jabber); + + pthread_mutex_lock(&data->halt_lock); + data->halted = true; + pthread_mutex_unlock(&data->halt_lock); + + XMPPFinishCompStream(data->jabber); pthread_join(xmpp_thr, NULL); Log(LOG_INFO, "Stopping server..."); - HttpServerStop(server); + HttpServerStop(data->server); return; } if (signal == SIGPIPE) { Log(LOG_DEBUG, "Caught a SIGPIPE..."); - XMPPFinishCompStream(jabber); - pthread_join(xmpp_thr, NULL); return; } } bool -ParseeInitialiseSignals(HttpServer *s, pthread_t xmpp, XMPPComponent *j) +ParseeInitialiseSignals(ParseeData *d, pthread_t xmpp) { struct sigaction sa; - server = s; + data = d; xmpp_thr = xmpp; - jabber = j; sigfillset(&sa.sa_mask); sa.sa_handler = SignalHandler; diff --git a/src/XMPPThread/ReListener.c b/src/XMPPThread/ReListener.c index 1b5e5f1..0bbfbd5 100644 --- a/src/XMPPThread/ReListener.c +++ b/src/XMPPThread/ReListener.c @@ -136,6 +136,8 @@ ParseeXMPPThread(void *argp) XMLElement *stanza = NULL; HashMap *await_table2; size_t i; + + bool error = false; /* Initialise the await table */ await_table = HashMapCreate(); @@ -243,6 +245,14 @@ ParseeXMPPThread(void *argp) * few threads to be busy, while the rest of Parsee works. */ PushStanza(&info, stanza); } + pthread_mutex_lock(&args->halt_lock); + if (!args->halted) + { + Log(LOG_WARNING, "XMPP server is closing stream..."); + Log(LOG_WARNING, "Stopping %s...", NAME); + error = true; + } + pthread_mutex_unlock(&args->halt_lock); info.running = false; for (i = 0; i < info.available_dispatchers; i++) @@ -278,6 +288,10 @@ ParseeXMPPThread(void *argp) DestroyPEPManager(info.pep_manager); XMPPFreeManager(info.m); + if (error) + { + HttpServerStop(args->server); /* minor trolling */ + } return NULL; } diff --git a/src/include/Parsee.h b/src/include/Parsee.h index ea9edcf..1cc93bf 100644 --- a/src/include/Parsee.h +++ b/src/include/Parsee.h @@ -60,6 +60,7 @@ typedef struct ParseeData { HttpRouter *router; CommandRouter *handler; + HttpServer *server; XMPPComponent *jabber; Db *db; @@ -69,6 +70,10 @@ typedef struct ParseeData { HashMap *oid_servers; pthread_mutex_t oidl; + + /* If Parsee was intentionally halted */ + bool halted; + pthread_mutex_t halt_lock; } ParseeData; typedef struct Argument { @@ -285,7 +290,11 @@ extern bool ParseeGetDMOrigin(ParseeData *data, char *chat_id, char *ev, char ** /* Sends presence requests for every MUC around as a fake JID */ extern void ParseeSendPresence(ParseeData *); -extern bool ParseeInitialiseSignals(HttpServer *, pthread_t, XMPPComponent *); +/** Initialises signal-handling code within Parsee. + * -------------------- + * Modifies: the signal handler + * Returns: whenever it has properly been setup */ +extern bool ParseeInitialiseSignals(ParseeData *data, pthread_t xmpp); /* Job used to cleanup Parsee data that isn't necessary anymore. */ extern void ParseeCleanup(void *data);