From ffc06794930aced579d9a54bf95c88654b700978 Mon Sep 17 00:00:00 2001 From: LDA Date: Tue, 13 Aug 2024 20:24:32 +0200 Subject: [PATCH] [MOD/WIP] Kill off the stanza sending function The stanza sender is dead. All hail the Stanza Builder. --- README.MD | 2 +- src/Main.c | 6 +- src/MatrixEventHandler.c | 18 +- src/StanzaBuilder.c | 337 ++++++++++++++++++++++++++++++++++++ src/XML/Elements.c | 9 +- src/XMPP/Stanza.c | 167 ------------------ src/include/StanzaBuilder.h | 22 +++ src/include/XMPP.h | 2 - 8 files changed, 379 insertions(+), 184 deletions(-) create mode 100644 src/StanzaBuilder.c create mode 100644 src/include/StanzaBuilder.h diff --git a/README.MD b/README.MD index 12d6d4f..f8e82ac 100644 --- a/README.MD +++ b/README.MD @@ -29,7 +29,7 @@ If there are any Cytoplasm-related build failures, you may want to check the Mak change a few variables (you can set `CYTO_INC` and `CYTO_LIB`) ### DEPENDENCIES -Parsee tries to avoid dependencies aside from [Cytoplasm](https://git.telodendria.io/Telodendria/Cytoplasm). +Parsee tries to avoid dependencies aside from [Cytoplasm](https://git.telodendria.io/Telodendria/Cytoplasm). Itself optionally depends on a good POSIX implementation, and optionally OpenSSL/LMDB (highly recommended, but you can get away without those). ## RUNNING First off, you may want to configure Parsee by running the `config` tool(generally named diff --git a/src/Main.c b/src/Main.c index e8a62a5..226a9e4 100644 --- a/src/Main.c +++ b/src/Main.c @@ -12,12 +12,8 @@ #include #include -#include #include -#include #include -#include -#include #include static HttpServer *server = NULL; @@ -107,7 +103,7 @@ Main(Array *args, HashMap *env) conf.port = parsee_conf->port; conf.threads = parsee_conf->http_threads; - conf.maxConnections = 32; /* TODO */ + conf.maxConnections = conf.threads << 2; conf.handlerArgs = ParseeInitData(jabber); conf.handler = ParseeRequest; diff --git a/src/MatrixEventHandler.c b/src/MatrixEventHandler.c index 17419f4..ce24854 100644 --- a/src/MatrixEventHandler.c +++ b/src/MatrixEventHandler.c @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -229,6 +230,7 @@ static void ParseeMessageHandler(ParseeData *data, HashMap *event) { XMPPComponent *jabber = data->jabber; + StanzaBuilder *builder; DbRef *ref = NULL; HashMap *json; @@ -338,12 +340,16 @@ ParseeMessageHandler(ParseeData *data, HashMap *event) } { char *xmpp_ident = StrRandom(32); - XMPPSendPlainID( - jabber, xmppified_user, to, - xepd ? xepd : body, type, - stanza, sender, ev_id, unauth, origin_id, - xmpp_ident - ); + builder = CreateStanzaBuilder(xmppified_user, to, xmpp_ident); + SetStanzaType(builder, type); + SetStanzaBody(builder, xepd ? xepd : body); + SetStanzaReply(builder, stanza, sender); + SetStanzaLink(builder, unauth); + SetStanzaEdit(builder, origin_id); + SetStanzaXParsee(builder, event); + + WriteoutStanza(builder, jabber); + DestroyStanzaBuilder(builder); if (direct) { diff --git a/src/StanzaBuilder.c b/src/StanzaBuilder.c new file mode 100644 index 0000000..27b16de --- /dev/null +++ b/src/StanzaBuilder.c @@ -0,0 +1,337 @@ +#include + +#include +#include +#include +#include + +#include +#include + +struct StanzaBuilder { + Array *sub_items; + + char *replying_to_stanza; + char *replying_to_sender; + char *from, *to; + char *editing; + char *type; + char *body; + char *oob; + char *id; +}; + +StanzaBuilder * +CreateStanzaBuilder(char *from, char *to, char *id) +{ + StanzaBuilder *builder; + if (!from || !to) + { + return NULL; + } + + builder = Malloc(sizeof(*builder)); + + builder->sub_items = ArrayCreate(); + + builder->id = id ? StrRandom(64) : StrDuplicate(id); + builder->from = StrDuplicate(from); + builder->to = StrDuplicate(to); + + builder->replying_to_stanza = NULL; + builder->replying_to_sender = NULL; + builder->type = NULL; + builder->body = NULL; + builder->oob = NULL; + + return SetStanzaType(builder, "chat"); +} + +StanzaBuilder * +SetStanzaType(StanzaBuilder *builder, char *type) +{ + if (!builder || !type) + { + return builder; + } + + Free(builder->type); + builder->type = StrDuplicate(type); + + return builder; +} + +StanzaBuilder * +SetStanzaReply(StanzaBuilder *builder, char *stanza, char *sender) +{ + if (!builder || !stanza || !sender) + { + return builder; + } + + Free(builder->replying_to_stanza); + Free(builder->replying_to_sender); + builder->replying_to_stanza = StrDuplicate(stanza); + builder->replying_to_sender = StrDuplicate(sender); + return builder; +} +StanzaBuilder * +SetStanzaEdit(StanzaBuilder *builder, char *to) +{ + if (!builder || !to) + { + return builder; + } + + Free(builder->editing); + builder->editing = StrDuplicate(to); + return builder; +} +StanzaBuilder * +SetStanzaBody(StanzaBuilder *builder, char *body) +{ + if (!builder || !body) + { + return builder; + } + + Free(builder->body); + builder->body = StrDuplicate(body); + return builder; +} +StanzaBuilder * +SetStanzaID(StanzaBuilder *builder, char *id) +{ + if (!builder || !id) + { + return builder; + } + + Free(builder->id); + builder->id = StrDuplicate(id); + return builder; +} +StanzaBuilder * +SetStanzaLink(StanzaBuilder *builder, char *oob) +{ + if (!builder || !oob) + { + return builder; + } + + Free(builder->oob); + builder->oob = StrDuplicate(oob); + return builder; +} +StanzaBuilder * +AddStanzaElem(StanzaBuilder *builder, XMLElement *item) +{ + if (!builder || !item) + { + return builder; + } + + ArrayAdd(builder->sub_items, item); + return builder; +} + +XMLElement * +ExportStanza(StanzaBuilder *builder) +{ + XMLElement *elem, *request, *markable; + size_t i; + if (!builder) + { + return NULL; + } + + elem = XMLCreateTag("message"); + XMLAddAttr(elem, "from", builder->from); + XMLAddAttr(elem, "to", builder->to); + XMLAddAttr(elem, "id", builder->id); + XMLAddAttr(elem, "type", builder->type); + + request = XMLCreateTag("request"); + XMLAddAttr(request, "xmlns", "urn:xmpp:receipts"); + XMLAddChild(elem, request); + + markable = XMLCreateTag("markable"); + XMLAddAttr(markable, "xmlns", "urn:xmpp:chat-markers:0"); + XMLAddChild(elem, markable); + + if (builder->editing) + { + XMLElement *xedit = XMLCreateTag("replace"); + XMLAddAttr(xedit, "xmlns", "urn:xmpp:message-correct:0"); + XMLAddAttr(xedit, "id", builder->editing); + XMLAddChild(elem, xedit); + } + if (builder->oob) + { + XMLElement *xoob, *oob_data, *oob_url; + + xoob = XMLCreateTag("x"); + oob_url = XMLCreateTag("url"); + oob_data = XMLCreateText(builder->oob); + + XMLAddAttr(xoob, "xmlns", "jabber:x:oob"); + + XMLAddChild(elem, xoob); + XMLAddChild(xoob, oob_url); + XMLAddChild(oob_url, oob_data); + } + if (builder->replying_to_stanza && + builder->replying_to_sender && + builder->body) + { + int off = ParseeFindDatastart(builder->body); + char *ostr = StrInt(off); + XMLElement *reply = XMLCreateTag("reply"); + XMLElement *fallback = XMLCreateTag("fallback"); + XMLElement *fall_body = XMLCreateTag("body"); + + XMLAddAttr(reply, "to", builder->replying_to_stanza); + XMLAddAttr(reply, "id", builder->replying_to_sender); + XMLAddAttr(reply, "xmlns", "urn:xmpp:reply:0"); + + XMLAddAttr(fallback, "xmlns", "urn:xmpp:fallback:0"); + XMLAddAttr(fallback, "for", "urn:xmpp:reply:0"); + + XMLAddAttr(fall_body, "start", "0"); + XMLAddAttr(fall_body, "end", ostr); + XMLAddChild(fallback, fall_body); + + XMLAddChild(elem, reply); + XMLAddChild(elem, fallback); + + Free(ostr); + } + + if (builder->body) + { + XMLElement *body = XMLCreateTag("body"); + XMLElement *text = XMLCreateText(builder->body); + + XMLAddChild(elem, body); + XMLAddChild(body, text); + } + + for (i = 0; i < ArraySize(builder->sub_items); i++) + { + XMLElement *sub_item = ArrayGet(builder->sub_items, i); + XMLElement *dup = XMLCopy(sub_item); + + XMLAddChild(elem, dup); + } + return elem; +} + +void +WriteoutStanza(StanzaBuilder *builder, XMPPComponent *jabber) +{ + XMLElement *elem; + if (!builder || !jabber) + { + return; + } + + elem = ExportStanza(builder); + pthread_mutex_lock(&jabber->write_lock); + XMLEncode(jabber->stream, elem); + StreamFlush(jabber->stream); + pthread_mutex_unlock(&jabber->write_lock); + + XMLFreeElement(elem); + return; +} + +StanzaBuilder * +SetStanzaXParsee(StanzaBuilder *builder, HashMap *e) +{ + XMLElement *parsee; + if (!builder || !e) + { + return builder; + } + parsee = XMLCreateTag("x-parsee"); + XMLAddAttr(parsee, "xmlns", "https://at.kappach.at/jabber/parsee#info"); + { + XMLElement *parsee_version, *ver_elem; + XMLElement *parsee_link, *link_elem; + XMLElement *parsee_text, *text_elem; + XMLElement *parsee_event, *event_elem; + XMLElement *parsee_json, *json_elem; + char *event_id = GrabString(e, 1, "event_id"); + char *json = NULL; + Stream *stream = StrStreamWriter(&json); + + JsonEncode(e, stream, JSON_DEFAULT); + StreamFlush(stream); + StreamClose(stream); + + parsee_version = XMLCreateTag("version"); + ver_elem = XMLCreateText(VERSION "[" CODE "]"); + XMLAddChild(parsee_version, ver_elem); + XMLAddChild(parsee, parsee_version); + + parsee_json = XMLCreateTag("json"); + json_elem = XMLCreateText(json); + XMLAddChild(parsee_json, json_elem); + XMLAddChild(parsee, parsee_json); + Free(json); + + parsee_link = XMLCreateTag("repository"); + link_elem = XMLCreateText(REPOSITORY); + XMLAddChild(parsee_link, link_elem); + XMLAddChild(parsee, parsee_link); + + parsee_text = XMLCreateTag("zayds-note"); + text_elem = XMLCreateText("\"LDA HANG YOURSELF\" - Zayd"); + XMLAddChild(parsee_text, text_elem); + XMLAddChild(parsee, parsee_text); + + parsee_text = XMLCreateTag("mcnebs-note"); + text_elem = XMLCreateText("LDA will never beat the allegations"); + XMLAddChild(parsee_text, text_elem); + XMLAddChild(parsee, parsee_text); + + if (event_id) + { + parsee_event = XMLCreateTag("event-id"); + event_elem = XMLCreateText(event_id); + XMLAddChild(parsee_event, event_elem); + XMLAddChild(parsee, parsee_event); + } + } + AddStanzaElem(builder, parsee); + return builder; +} + +void +DestroyStanzaBuilder(StanzaBuilder *builder) +{ + size_t i; + if (!builder) + { + return; + } + + for (i = 0; i < ArraySize(builder->sub_items); i++) + { + XMLElement *sub_item = ArrayGet(builder->sub_items, i); + + XMLFreeElement(sub_item); + } + ArrayFree(builder->sub_items); + + Free(builder->replying_to_stanza); + Free(builder->replying_to_sender); + Free(builder->editing); + Free(builder->from); + Free(builder->body); + Free(builder->type); + Free(builder->oob); + Free(builder->to); + Free(builder->id); + Free(builder); +} diff --git a/src/XML/Elements.c b/src/XML/Elements.c index 4eb83b5..9597a92 100644 --- a/src/XML/Elements.c +++ b/src/XML/Elements.c @@ -177,14 +177,17 @@ XMLCopy(XMLElement *original) ret->name = StrDuplicate(original->name); ret->data = StrDuplicate(original->data); - if (original->children) { size_t i; ret->children = ArrayCreate(); - for (i = 0; i < ArraySize(ret->children); i++) + for (i = 0; i < ArraySize(original->children); i++) { - ArrayAdd(ret->children, XMLCopy(ArrayGet(original->children, i))); + XMLElement *child = ArrayGet(original->children, i); + ArrayAdd( + ret->children, + XMLCopy(child) + ); } } if (original->attrs) diff --git a/src/XMPP/Stanza.c b/src/XMPP/Stanza.c index bc1e1c8..5340633 100644 --- a/src/XMPP/Stanza.c +++ b/src/XMPP/Stanza.c @@ -7,13 +7,6 @@ #include #include -void -XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, char *rst, char *rse, char *event_id, char *oob, char *edit) -{ - char *ident = StrRandom(32); - XMPPSendPlainID(comp, fr, to, msg, type, rst, rse, event_id, oob, edit, ident); - Free(ident); -} void XMPPRetract(XMPPComponent *comp, char *fr, char *to, char *type, char *redact) @@ -84,166 +77,6 @@ XMPPRetract(XMPPComponent *comp, char *fr, char *to, char *type, char *redact) Free(ident); } void -XMPPSendPlainID(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, char *rst, char *rse, char *event_id, char *oob, char *edit, char *ident) -{ - XMLElement *message, *body, *data, *parsee; - char *from; - if (!comp || !fr || !to || !msg || !ident) - { - return; - } - - pthread_mutex_lock(&comp->write_lock); - - message = XMLCreateTag("message"); - XMLAddAttr(message, "from", (from = StrConcat(3, fr, "@", comp->host))); - XMLAddAttr(message, "to", to); - XMLAddAttr(message, "type", type); - XMLAddAttr(message, "id", ident); - - body = XMLCreateTag("body"); - data = XMLCreateText(oob ? oob : msg); - - /* TODO: Add Parsee specific fields here */ - parsee = XMLCreateTag("x-parsee"); - { - XMLElement *parsee_version, *ver_elem; - XMLElement *parsee_link, *link_elem; - XMLElement *parsee_text, *text_elem; - XMLElement *parsee_event, *event_elem; - - parsee_version = XMLCreateTag("version"); - ver_elem = XMLCreateText(VERSION); - XMLAddChild(parsee_version, ver_elem); - XMLAddChild(parsee, parsee_version); - - parsee_link = XMLCreateTag("repository"); - link_elem = XMLCreateText(REPOSITORY); - XMLAddChild(parsee_link, link_elem); - XMLAddChild(parsee, parsee_link); - - parsee_text = XMLCreateTag("zayds-note"); - text_elem = XMLCreateText("\"LDA HANG YOURSELF\" - Zayd"); - XMLAddChild(parsee_text, text_elem); - XMLAddChild(parsee, parsee_text); - - parsee_text = XMLCreateTag("mcnebs-note"); - text_elem = XMLCreateText("LDA will never beat the allegations"); - XMLAddChild(parsee_text, text_elem); - XMLAddChild(parsee, parsee_text); - - if (event_id) - { - parsee_event = XMLCreateTag("event-id"); - event_elem = XMLCreateText(event_id); - XMLAddChild(parsee_event, event_elem); - XMLAddChild(parsee, parsee_event); - } - /* TODO: Add custom fields depending on the caller's wishes */ - } - - if (edit) - { - XMLElement *xedit = XMLCreateTag("replace"); - XMLAddAttr(xedit, "xmlns", "urn:xmpp:message-correct:0"); - XMLAddAttr(xedit, "id", edit); - XMLAddChild(message, xedit); - } - - { - XMLElement *request = XMLCreateTag("request"); - XMLAddAttr(request, "xmlns", "urn:xmpp:receipts"); - XMLAddChild(message, request); - } - { - XMLElement *markable = XMLCreateTag("markable"); - XMLAddAttr(markable, "xmlns", "urn:xmpp:chat-markers:0"); - XMLAddChild(message, markable); - } - - if (oob) - { - XMLElement *xoob, *oob_data, *oob_url; - - xoob = XMLCreateTag("x"); - XMLAddAttr(xoob, "xmlns", "jabber:x:oob"); - oob_url = XMLCreateTag("url"); - oob_data = XMLCreateText(oob); - XMLAddChild(oob_url, oob_data); - XMLAddChild(xoob, oob_url); - XMLAddChild(message, xoob); - } - if (rst && rse) - { - int off = ParseeFindDatastart(msg); - char *ostr = StrInt(off); - XMLElement *reply = XMLCreateTag("reply"); - XMLElement *fallback = XMLCreateTag("fallback"); - XMLElement *fall_body = XMLCreateTag("body"); - - XMLAddAttr(reply, "to", rse); - XMLAddAttr(reply, "id", rst); - XMLAddAttr(reply, "xmlns", "urn:xmpp:reply:0"); - - XMLAddAttr(fallback, "xmlns", "urn:xmpp:fallback:0"); - XMLAddAttr(fallback, "for", "urn:xmpp:reply:0"); - - XMLAddAttr(fall_body, "start", "0"); - XMLAddAttr(fall_body, "end", ostr); - XMLAddChild(fallback, fall_body); - - XMLAddChild(message, reply); - XMLAddChild(message, fallback); - - Free(ostr); - } - - XMLAddChild(message, body); - XMLAddChild(message, parsee); - XMLAddChild(body, data); - - XMLEncode(comp->stream, message); - StreamFlush(comp->stream); - XMLFreeElement(message); - Free(from); - - pthread_mutex_unlock(&comp->write_lock); -} -void -XMPPSendMUC(XMPPComponent *comp, char *fr, char *as, char *to, char *msg, char *type) -{ - XMLElement *message, *body, *data; - char *from, *id; - if (!comp || !fr || !to || !as || !msg) - { - return; - } - - pthread_mutex_lock(&comp->write_lock); - - message = XMLCreateTag("message"); - XMLAddAttr(message, "from", - (from = StrConcat(5, fr, "@", comp->host, "/", as))); - XMLAddAttr(message, "to", to); - XMLAddAttr(message, "type", type); - XMLAddAttr(message, "id", (id = StrRandom(8))); - - body = XMLCreateTag("body"); - data = XMLCreateText(msg); - - XMLAddChild(message, body); - XMLAddChild(body, data); - - XMLEncode(comp->stream, message); - StreamFlush(comp->stream); - - XMLFreeElement(message); - Free(from); - Free(id); - - pthread_mutex_unlock(&comp->write_lock); -} -void XMPPLeaveMUC(XMPPComponent *comp, char *fr, char *muc, char *reason) { XMLElement *presence; diff --git a/src/include/StanzaBuilder.h b/src/include/StanzaBuilder.h new file mode 100644 index 0000000..e434e43 --- /dev/null +++ b/src/include/StanzaBuilder.h @@ -0,0 +1,22 @@ +#ifndef PARSEE_STANZABUILDER_H +#define PARSEE_STANZABUILDER_H + +#include +#include + +typedef struct StanzaBuilder StanzaBuilder; + +extern StanzaBuilder * CreateStanzaBuilder(char *from, char *to, char *id); +extern StanzaBuilder * SetStanzaType(StanzaBuilder *builder, char *type); +extern StanzaBuilder * SetStanzaBody(StanzaBuilder *builder, char *body); +extern StanzaBuilder * SetStanzaReply(StanzaBuilder *builder, char *st, char *se); +extern StanzaBuilder * SetStanzaEdit(StanzaBuilder *builder, char *to); +extern StanzaBuilder * SetStanzaLink(StanzaBuilder *builder, char *oob); +extern StanzaBuilder * SetStanzaID(StanzaBuilder *builder, char *id); +extern StanzaBuilder * SetStanzaXParsee(StanzaBuilder *builder, HashMap *e); +extern StanzaBuilder * AddStanzaElem(StanzaBuilder *builder, XMLElement *item); +extern XMLElement * ExportStanza(StanzaBuilder *builder); +extern void WriteoutStanza(StanzaBuilder *builder, XMPPComponent *jabber); +extern void DestroyStanzaBuilder(StanzaBuilder *builder); + +#endif diff --git a/src/include/XMPP.h b/src/include/XMPP.h index 3fb89c9..07fea6a 100644 --- a/src/include/XMPP.h +++ b/src/include/XMPP.h @@ -34,8 +34,6 @@ extern bool XMPPJoinMUC(XMPPComponent *comp, char *fr, char *muc); extern void XMPPLeaveMUC(XMPPComponent *comp, char *fr, char *muc, char *r); /* TODO: XMPP stuff, I don't fucking know, I'm not a Jabbernerd. */ -extern void XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, char *rst, char *rse, char *event_id, char *oob, char *id); -extern void XMPPSendPlainID(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, char *rst, char *rse, char *event_id, char *oob, char *id, char *sid); extern void XMPPRetract(XMPPComponent *comp, char *fr, char *to, char *type, char *redact); /* Finishes a component stream, and doesn't free it. */