[MOD/WIP] Kill off the stanza sending function

The stanza sender is dead. All hail the Stanza Builder.
This commit is contained in:
LDA 2024-08-13 20:24:32 +02:00
commit ffc0679493
8 changed files with 379 additions and 184 deletions

View file

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

View file

@ -12,12 +12,8 @@
#include <signal.h>
#include <stdlib.h>
#include <StringStream.h>
#include <Parsee.h>
#include <XEP393.h>
#include <XMPP.h>
#include <Glob.h>
#include <XML.h>
#include <AS.h>
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;

View file

@ -7,6 +7,7 @@
#include <string.h>
#include <stdlib.h>
#include <StanzaBuilder.h>
#include <Matrix.h>
#include <AS.h>
@ -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)
{

337
src/StanzaBuilder.c Normal file
View file

@ -0,0 +1,337 @@
#include <StanzaBuilder.h>
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Array.h>
#include <Cytoplasm/Json.h>
#include <Cytoplasm/Str.h>
#include <StringStream.h>
#include <Parsee.h>
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);
}

View file

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

View file

@ -7,13 +7,6 @@
#include <Parsee.h>
#include <XML.h>
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;

View file

@ -0,0 +1,22 @@
#ifndef PARSEE_STANZABUILDER_H
#define PARSEE_STANZABUILDER_H
#include <XMPP.h>
#include <XML.h>
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

View file

@ -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. */