[ADD] Proper stanza limits

This commit is contained in:
LDA 2024-10-25 18:03:05 +02:00
commit 7c60ab28cb
18 changed files with 74 additions and 39 deletions

View file

@ -13,7 +13,7 @@ commit done between releases.
*There is currently no beta releases of Parsee* *There is currently no beta releases of Parsee*
## Alpha ## Alpha
### v0.2.0[star-of-hope] <X/X/2024?> ### v0.2.0[star-of-hope] <8/11/2024?>
Fixes some media metadata things, replaces the build system, Fixes some media metadata things, replaces the build system,
tries out avatar support some more and speeds up Parsee a tad tries out avatar support some more and speeds up Parsee a tad
bit. bit.
@ -25,8 +25,8 @@ the MUC.
- Start adding basic documentation to Parsee, through the - Start adding basic documentation to Parsee, through the
wiki page. wiki page.
- Add MUC whitelists for plumbing, alongside a `whitelist` tool - Add MUC whitelists for plumbing, alongside a `whitelist` tool
- Add (yet unused) parameter for setting the max stanza size - Add parameter for setting the max stanza size allowed, with
allowed. the default being the XMPP minimum of 10000 bytes.
- Allows experimental MbedTLS through a specific Cytoplasm - Allows experimental MbedTLS through a specific Cytoplasm
patch (though still unstable AND slow). patch (though still unstable AND slow).
- Does basic work towards NetBSD support - Does basic work towards NetBSD support

View file

@ -1,6 +1,6 @@
." The last field is the codename, by the way. ." The last field is the codename, by the way.
." ALL MANPAGES FOR PARSEE ARE UNDER PUBLIC DOMAIN ." ALL MANPAGES FOR PARSEE ARE UNDER PUBLIC DOMAIN
.TH parsee-config 1 "Parsee Utility" "tomboyish-bridges-adventure" .TH parsee-config 1 "Parsee Utility" "star-of-hope"
.SH NAME .SH NAME
parsee-config - generate a basic configuration file parsee-config - generate a basic configuration file
@ -13,6 +13,7 @@ parsee-config
.B [-J JABBER_HOST] .B [-J JABBER_HOST]
.B [-p JABBER_PORT] .B [-p JABBER_PORT]
.B [-d DATABASE] .B [-d DATABASE]
.B [-M MAX_STANZA]
.B [-S DATABASE size] .B [-S DATABASE size]
.SH DESCRIPTION .SH DESCRIPTION
@ -54,6 +55,10 @@ For example, if you except Parsee users to be on
.I SHARED_SECRET .I SHARED_SECRET
is a shared secret known by Parsee and the XMPP component to authenticate. is a shared secret known by Parsee and the XMPP component to authenticate.
.TP .TP
.BR -M MAX_STANZA
.I MAX_STANZA
is the maximum stanza size accepted by the XMPP host. If it is less than 10000 bytes, then it shall be set to that limit(the standardised value).
.TP
.BR -m MEDIA_URL .BR -m MEDIA_URL
.I MEDIA_URL .I MEDIA_URL
is an optional field used by Parsee as an address that points to Matrix is an optional field used by Parsee as an address that points to Matrix

View file

@ -487,7 +487,7 @@ ParseeMessageHandler(ParseeData *data, HashMap *event)
SetStanzaEdit(builder, origin_id); SetStanzaEdit(builder, origin_id);
SetStanzaXParsee(builder, event); SetStanzaXParsee(builder, event);
WriteoutStanza(builder, jabber); WriteoutStanza(builder, jabber, data->config->max_stanza_size);
DestroyStanzaBuilder(builder); DestroyStanzaBuilder(builder);
if (direct) if (direct)
@ -542,8 +542,7 @@ ParseeEventHandler(ParseeData *data, HashMap *event)
return; return;
} }
else if (StrEquals(event_type, "m.room.message") || else if (StrEquals(event_type, "m.room.message") ||
StrEquals(event_type, "m.sticker")) /* TODO: Actual sticker StrEquals(event_type, "m.sticker"))
* support here... */
{ {
ParseeMessageHandler(data, event); ParseeMessageHandler(data, event);
Free(parsee); Free(parsee);

View file

@ -66,7 +66,7 @@ ParseeConfigLoad(char *conf)
if (!config->max_stanza_size) if (!config->max_stanza_size)
{ {
/* Standard XMPP "minimum" maximum */ /* Standard XMPP "minimum" maximum */
config->max_stanza_size = 10 KB; config->max_stanza_size = 10000;
} }
CopyToStr(media_base, "media_base"); CopyToStr(media_base, "media_base");

View file

@ -228,16 +228,20 @@ ExportStanza(StanzaBuilder *builder)
} }
void void
WriteoutStanza(StanzaBuilder *builder, XMPPComponent *jabber) WriteoutStanza(StanzaBuilder *builder, XMPPComponent *jabber, size_t max)
{ {
XMLElement *elem; XMLElement *elem;
if (!builder || !jabber) if (!builder || !jabber)
{ {
return; return;
} }
if (!max)
{
max = 10000; /* XMPP recommended limit */
}
elem = ExportStanza(builder); elem = ExportStanza(builder);
XMPPSendStanza(jabber, elem); XMPPSendStanza(jabber, elem, max);
XMLFreeElement(elem); XMLFreeElement(elem);
} }

View file

@ -214,17 +214,34 @@ XMPPEndCompStream(XMPPComponent *comp)
Free(comp); Free(comp);
} }
void void
XMPPSendStanza(XMPPComponent *comp, XMLElement *stanza) XMPPSendStanza(XMPPComponent *comp, XMLElement *stanza, size_t max)
{ {
size_t len;
char *c = NULL;
Stream *stringWriter;
if (!comp || !stanza) if (!comp || !stanza)
{ {
return; return;
} }
stringWriter = StrStreamWriter(&c);
XMLEncode(stringWriter, stanza);
StreamFlush(stringWriter);
StreamClose(stringWriter);
if (c && max && (len = strlen(c)) > max)
{
Log(LOG_WARNING,
"Unexceptedly large stanza received (len=%d max=%d).",
(int) len, (int) max
);
Free(c);
return;
}
pthread_mutex_lock(&comp->write_lock); pthread_mutex_lock(&comp->write_lock);
/* TODO: Find a way to negociate to the server about stanza size StreamPrintf(comp->stream, c);
* (beyond the 10KB limit that is REQUIRED by XMPP standards) */
XMLEncode(comp->stream, stanza);
StreamFlush(comp->stream); StreamFlush(comp->stream);
pthread_mutex_unlock(&comp->write_lock); pthread_mutex_unlock(&comp->write_lock);
Free(c);
} }

View file

@ -33,7 +33,7 @@ XMPPQueryMUC(XMPPComponent *jabber, char *muc, MUCInfo *out)
{ {
XMLElement *identity; XMLElement *identity;
XMPPSendStanza(jabber, iq_query); XMPPSendStanza(jabber, iq_query, 10000);
XMLFreeElement(iq_query); XMLFreeElement(iq_query);
/* Except an IQ reply. 10 seconds of timeout is pretty /* Except an IQ reply. 10 seconds of timeout is pretty
@ -153,7 +153,7 @@ XMPPRequestVoice(XMPPComponent *jabber, char *from, char *muc)
} }
XMLAddChild(stanza, x); XMLAddChild(stanza, x);
} }
XMPPSendStanza(jabber, stanza); XMPPSendStanza(jabber, stanza, 10000);
XMLFreeElement(stanza); XMLFreeElement(stanza);
Free(identifier); Free(identifier);
@ -201,7 +201,7 @@ XMPPJoinMUC(XMPPComponent *comp, char *fr, char *muc, char *hash, int time, bool
XMLAddChild(presence, x); XMLAddChild(presence, x);
} }
XMPPSendStanza(comp, presence); XMPPSendStanza(comp, presence, 10000);
XMLFreeElement(presence); XMLFreeElement(presence);
Free(from); Free(from);
@ -248,7 +248,7 @@ XMPPLeaveMUC(XMPPComponent *comp, char *fr, char *muc, char *reason)
XMPPAnnotatePresence(presence); XMPPAnnotatePresence(presence);
XMPPSendStanza(comp, presence); XMPPSendStanza(comp, presence, 10000);
XMLFreeElement(presence); XMLFreeElement(presence);
Free(from); Free(from);

View file

@ -66,7 +66,7 @@ XMPPRetract(XMPPComponent *comp, char *fr, char *to, char *type, char *redact)
} }
XMPPSendStanza(comp, message); XMPPSendStanza(comp, message, 10000);
XMLFreeElement(message); XMLFreeElement(message);
Free(from); Free(from);
@ -264,7 +264,7 @@ XMPPSendDisco(ParseeData *data, char *from, char *to)
XMLAddChild(iq, query); XMLAddChild(iq, query);
} }
XMPPSendStanza(jabber, iq); XMPPSendStanza(jabber, iq, 10000);
XMLFreeElement(iq); XMLFreeElement(iq);
ret = ParseeAwaitStanza(identifier, 1.25 SECONDS); ret = ParseeAwaitStanza(identifier, 1.25 SECONDS);

View file

@ -274,7 +274,7 @@ XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeData *data)
x = XMPPFormifyCommand(m, cmd, from); x = XMPPFormifyCommand(m, cmd, from);
XMLAddChild(command_xml, x); XMLAddChild(command_xml, x);
XMPPSendStanza(jabber, iq); XMPPSendStanza(jabber, iq, data->config->max_stanza_size);
XMLFreeElement(iq); XMLFreeElement(iq);
goto end; goto end;
@ -302,7 +302,7 @@ XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeData *data)
XMPPExecuteCommand(m, cmd, from, command_xml, NULL); XMPPExecuteCommand(m, cmd, from, command_xml, NULL);
XMLAddChild(iq, command_xml); XMLAddChild(iq, command_xml);
XMPPSendStanza(jabber, iq); XMPPSendStanza(jabber, iq, data->config->max_stanza_size);
XMLFreeElement(iq); XMLFreeElement(iq);
InvalidateSession(m, session_id); InvalidateSession(m, session_id);
@ -342,7 +342,7 @@ XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeData *data)
XMPPExecuteCommand(m, cmd, from, command_xml, x_form); XMPPExecuteCommand(m, cmd, from, command_xml, x_form);
XMLAddChild(iq, command_xml); XMLAddChild(iq, command_xml);
XMPPSendStanza(jabber, iq); XMPPSendStanza(jabber, iq, data->config->max_stanza_size);
XMLFreeElement(iq); XMLFreeElement(iq);
InvalidateSession(m, session_given); InvalidateSession(m, session_given);

View file

@ -72,7 +72,7 @@ PEPAvatarEvent(PEPManager *m, XMLElement *stanza, XMLElement *item)
char *url = HashMapGet(item->attrs, "url"); char *url = HashMapGet(item->attrs, "url");
XMLElement *request = CreateAvatarRequest(from, to, id); XMLElement *request = CreateAvatarRequest(from, to, id);
XMPPSendStanza(jabber, request); XMPPSendStanza(jabber, request, args->config->max_stanza_size);
XMLFreeElement(request); XMLFreeElement(request);
(void) url; /* TODO */ (void) url; /* TODO */

View file

@ -113,7 +113,7 @@ PEPVCardEvent(PEPManager *m, XMLElement *stanza, XMLElement *item)
} }
} }
XMPPSendStanza(jabber, reply); XMPPSendStanza(jabber, reply, data->config->max_stanza_size);
XMLFreeElement(reply); XMLFreeElement(reply);
(void) item; (void) item;
} }

View file

@ -131,7 +131,7 @@ ParseeBroadcastStanza(ParseeData *data, char *from, XMLElement *stanza)
/* TODO: Should we store IDs somewhere? */ /* TODO: Should we store IDs somewhere? */
XMLAddAttr(sub, "id", (storm_id = StrRandom(16))); XMLAddAttr(sub, "id", (storm_id = StrRandom(16)));
XMPPSendStanza(jabber, sub); XMPPSendStanza(jabber, sub, data->config->max_stanza_size);
XMLFreeElement(sub); XMLFreeElement(sub);
Free(storm_id); Free(storm_id);
end: end:

View file

@ -175,7 +175,7 @@ IQDiscoGet(ParseeData *args, XMPPComponent *jabber, XMLElement *stanza)
} }
XMLAddChild(iq_reply, query); XMLAddChild(iq_reply, query);
XMPPSendStanza(jabber, iq_reply); XMPPSendStanza(jabber, iq_reply, args->config->max_stanza_size);
XMLFreeElement(iq_reply); XMLFreeElement(iq_reply);
(void) args; (void) args;
@ -412,7 +412,7 @@ IQGet(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
XMPPShoveCommandList(thr->info->m, to, q); XMPPShoveCommandList(thr->info->m, to, q);
XMLAddChild(iq_reply, q); XMLAddChild(iq_reply, q);
} }
XMPPSendStanza(jabber, iq_reply); XMPPSendStanza(jabber, iq_reply, args->config->max_stanza_size);
XMLFreeElement(iq_reply); XMLFreeElement(iq_reply);
} }
else if (XMLookForTKV(stanza, "vCard", "xmlns", "vcard-temp")) else if (XMLookForTKV(stanza, "vCard", "xmlns", "vcard-temp"))
@ -450,7 +450,7 @@ IQGet(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
XMLAddChild(iqVCard, vCard); XMLAddChild(iqVCard, vCard);
} }
XMPPSendStanza(jabber, iqVCard); XMPPSendStanza(jabber, iqVCard, args->config->max_stanza_size);
XMLFreeElement(iqVCard); XMLFreeElement(iqVCard);
Free(to_matrix); Free(to_matrix);
Free(name); Free(name);
@ -477,7 +477,7 @@ IQGet(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
XMLAddChild(iqVCard, vCard); XMLAddChild(iqVCard, vCard);
} }
XMPPSendStanza(jabber, iqVCard); XMPPSendStanza(jabber, iqVCard, args->config->max_stanza_size);
XMLFreeElement(iqVCard); XMLFreeElement(iqVCard);
Free(to_matrix); Free(to_matrix);
Free(name); Free(name);
@ -531,7 +531,7 @@ IQGet(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
XMLAddChild(reply, ps); XMLAddChild(reply, ps);
} }
XMPPSendStanza(jabber, reply); XMPPSendStanza(jabber, reply, args->config->max_stanza_size);
XMLFreeElement(reply); XMLFreeElement(reply);
Free(to_matrix); Free(to_matrix);
@ -569,7 +569,7 @@ IQGet(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
XMLAddChild(query, version); XMLAddChild(query, version);
XMLAddChild(iq_reply, query); XMLAddChild(iq_reply, query);
XMPPSendStanza(jabber, iq_reply); XMPPSendStanza(jabber, iq_reply, args->config->max_stanza_size);
XMLFreeElement(iq_reply); XMLFreeElement(iq_reply);
} }
else else

View file

@ -370,13 +370,13 @@ end_error:
ps = CreatePubsubRequest( ps = CreatePubsubRequest(
parsee, decode_from, "urn:xmpp:avatar:metadata" parsee, decode_from, "urn:xmpp:avatar:metadata"
); );
XMPPSendStanza(jabber, ps); XMPPSendStanza(jabber, ps, args->config->max_stanza_size);
XMLFreeElement(ps); XMLFreeElement(ps);
ps = CreatePubsubRequest( ps = CreatePubsubRequest(
parsee, trim, "urn:xmpp:avatar:metadata" parsee, trim, "urn:xmpp:avatar:metadata"
); );
XMPPSendStanza(jabber, ps); XMPPSendStanza(jabber, ps, args->config->max_stanza_size);
XMLFreeElement(ps); XMLFreeElement(ps);
if (args->verbosity >= PARSEE_VERBOSE_TIMINGS) if (args->verbosity >= PARSEE_VERBOSE_TIMINGS)
{ {

View file

@ -381,7 +381,7 @@ end_item:
from, HashMapGet(stanza->attrs, "from") from, HashMapGet(stanza->attrs, "from")
); );
XMPPSendStanza(jabber, vcard_request); XMPPSendStanza(jabber, vcard_request, args->config->max_stanza_size);
XMLFreeElement(vcard_request); XMLFreeElement(vcard_request);
Free(from); Free(from);
} }

View file

@ -16,7 +16,7 @@ extern StanzaBuilder * SetStanzaID(StanzaBuilder *builder, char *id);
extern StanzaBuilder * SetStanzaXParsee(StanzaBuilder *builder, HashMap *e); extern StanzaBuilder * SetStanzaXParsee(StanzaBuilder *builder, HashMap *e);
extern StanzaBuilder * AddStanzaElem(StanzaBuilder *builder, XMLElement *item); extern StanzaBuilder * AddStanzaElem(StanzaBuilder *builder, XMLElement *item);
extern XMLElement * ExportStanza(StanzaBuilder *builder); extern XMLElement * ExportStanza(StanzaBuilder *builder);
extern void WriteoutStanza(StanzaBuilder *builder, XMPPComponent *jabber); extern void WriteoutStanza(StanzaBuilder *builder, XMPPComponent *jabber, size_t max);
extern void DestroyStanzaBuilder(StanzaBuilder *builder); extern void DestroyStanzaBuilder(StanzaBuilder *builder);
#endif #endif

View file

@ -30,11 +30,12 @@ extern XMPPComponent * XMPPInitialiseCompStream(char *host, int port);
extern bool XMPPAuthenticateCompStream(XMPPComponent *comp, char *shared); extern bool XMPPAuthenticateCompStream(XMPPComponent *comp, char *shared);
/** Writes an XML stanza through a component, while making sure any locking /** Writes an XML stanza through a component, while making sure any locking
* work is done. * work is done. If {max} is non-zero, then this function will not send
* stanzas beyond {max} bytes.
* ----------------------- * -----------------------
* Modifies: {comp}, the XMPP stream * Modifies: {comp}, the XMPP stream
* See-Also: XMPPInitialiseCompStream, XMPPAuthenticateCompStream, XMPP-core RFC */ * See-Also: XMPPInitialiseCompStream, XMPPAuthenticateCompStream, XMPP-core RFC */
extern void XMPPSendStanza(XMPPComponent *comp, XMLElement *stanza); extern void XMPPSendStanza(XMPPComponent *comp, XMLElement *stanza, size_t max);
/* Makes a user join/leave a MUC */ /* Makes a user join/leave a MUC */
extern bool XMPPJoinMUC(XMPPComponent *comp, char *fr, char *muc, char *hash, int secs, bool ret); extern bool XMPPJoinMUC(XMPPComponent *comp, char *fr, char *muc, char *hash, int secs, bool ret);

View file

@ -23,11 +23,12 @@ Main(Array *args, HashMap *env)
int flag, code = EXIT_FAILURE; int flag, code = EXIT_FAILURE;
int port = 5347; int port = 5347;
size_t lmdb_size = 0; size_t lmdb_size = 0;
size_t max_stanza = 10000;
listen = "localhost"; listen = "localhost";
ArgParseStateInit(&state); ArgParseStateInit(&state);
while ((flag = ArgParse(&state, args, "H:J:s:d:p:m:l:S:")) != -1) while ((flag = ArgParse(&state, args, "H:J:s:d:p:m:l:S:M:")) != -1)
{ {
switch (flag) switch (flag)
{ {
@ -56,6 +57,12 @@ Main(Array *args, HashMap *env)
case 'S': case 'S':
lmdb_size = strtol(state.optArg, NULL, 10) * 1024 * 1024; lmdb_size = strtol(state.optArg, NULL, 10) * 1024 * 1024;
break; break;
case 'M':
max_stanza = strtol(state.optArg, NULL, 10);
if (max_stanza < 10000)
{
max_stanza = 10000;
}
} }
} }
@ -71,6 +78,7 @@ Main(Array *args, HashMap *env)
"-l [Host/IP to listen as] " "-l [Host/IP to listen as] "
"-p [XMPP component port=5347] " "-p [XMPP component port=5347] "
"-J [parsee.xmppserver.ex]", "-J [parsee.xmppserver.ex]",
"-M [max stanza size>=10000]",
"-S [LMDB size]", "-S [LMDB size]",
ArrayGet(args, 0) ArrayGet(args, 0)
); );
@ -109,6 +117,7 @@ Main(Array *args, HashMap *env)
JsonSet(json, JsonValueString(jabber), 1, "component_host"); JsonSet(json, JsonValueString(jabber), 1, "component_host");
JsonSet(json, JsonValueInteger(port), 1, "component_port"); JsonSet(json, JsonValueInteger(port), 1, "component_port");
JsonSet(json, JsonValueInteger(max_stanza), 1, "max_stanza_size");
JsonSet(json, JsonValueString(jcp), 1, "shared_secret"); JsonSet(json, JsonValueString(jcp), 1, "shared_secret");