[ADD/WIP] Begin XMPPwerk

The fuck is a stanza? Presence? Why did Prosody not tell me I'm an idiot
when I clearly made a MALFORMED XML document? This and much more, in the
next commit!
This commit is contained in:
LDA 2024-06-16 11:08:18 +02:00
commit 868f0e4d9c
7 changed files with 207 additions and 11 deletions

View file

@ -4,6 +4,7 @@
#include <string.h>
#include <Parsee.h>
#include <XMPP.h>
#include <XML.h>
#include <AS.h>
@ -15,6 +16,19 @@ Main(void)
ParseeData *data;
const ParseeConfig *parsee_conf;
Stream *yaml;
{
char *as = "TODO";
char *shared = "TODO";
Stream *jabber = XMPPInitialiseCompStream(as, 0);
XMPPAuthenticateCompStream(jabber, as, shared);
while (!StreamEof(jabber))
{
StreamPutc(StreamStderr(), StreamGetc(jabber));
StreamFlush(StreamStderr());
}
XMPPEndCompStream(jabber);
return 0;
}
Log(LOG_INFO, "%s - v%s", NAME, VERSION);
ParseeConfigLoad("parsee.json");

View file

@ -1,12 +1,82 @@
#include <XML.h>
#include <Cytoplasm/Log.h>
/* TODO: The rest of all that. */
XMLElement *
XMLDecode(Stream *stream, bool autofree)
{
/* TODO: Use the existing SAX parser to decode everything */
return NULL;
#define push(x) ArrayAdd(stack, x)
#define pop(x) ArrayDelete(stack, ArraySize(stack) - 1)
#define peek(x) ArrayGet(stack, ArraySize(stack) - 1)
XMLexer *lexer;
XMLEvent *event;
XMLElement *ret = NULL;
XMLElement *top;
char *key, *val;
Array *stack;
if (!stream)
{
return NULL;
}
lexer = XMLCreateLexer(stream, autofree);
stack = ArrayCreate();
while ((event = XMLCrank(lexer)) && (!ret || ArraySize(stack)))
{
switch (event->type)
{
case XML_LEXER_STARTELEM:
/* Create a new element that will populated. */
top = XMLCreateTag(event->element);
Log(LOG_INFO, "<%s>", top->name);
XMLAddChild(peek(), top);
while (HashMapIterate(event->attrs, &key, (void **) &val))
{
XMLAddAttr(top, key, val);
}
if (!ret)
{
/* If we didn't have any element before, this one is
* going to be our top of the stack */
ret = top;
}
push(top);
break;
case XML_LEXER_ELEM:
/* Create a new element that will populated. */
top = XMLCreateTag(event->element);
XMLAddChild(peek(), top);
Log(LOG_INFO, "<%s />", top->name);
while (HashMapIterate(event->attrs, &key, (void **) &val))
{
XMLAddAttr(top, key, val);
}
if (!ret)
{
/* If we didn't have any element before, this one is
* going to be our top of the stack */
ret = top;
}
push(top);
/* Fallthrough */
case XML_LEXER_ENDELEM:
/* Pop out an element out of the DOM. */
Log(LOG_INFO, "</>");
pop();
break;
default: break;
}
XMLFreeEvent(event);
event = NULL;
}
XMLFreeEvent(event);
ArrayFree(stack);
XMLFreeLexer(lexer);
return ret;
}
void

View file

@ -4,7 +4,6 @@
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Array.h>
#include <Cytoplasm/Str.h>
#include <Cytoplasm/Log.h>
#include <string.h>
#include <ctype.h>
@ -24,7 +23,8 @@ struct XMLexer {
XML_STATE_ATTR,
XML_STATE_ATTRHEAD_PROP,
XML_STATE_ATTRTAIL
XML_STATE_ATTRTAIL,
XML_STATE_PI
} state;
struct {
@ -161,6 +161,17 @@ XMLCrank(XMLexer *lexer)
lexer->state = XML_STATE_ATTRTAIL;
break;
}
else if (XMLookahead(lexer, "<?", true))
{
if (lexer->data.str)
{
XMLFreeEvent(event);
event = XMLCreateData(lexer);
}
lexer->state = XML_STATE_PI;
break;
}
else if (XMLookahead(lexer, "<", true))
{
if (lexer->data.str)
@ -189,6 +200,14 @@ XMLCrank(XMLexer *lexer)
return NULL;
}
break;
case XML_STATE_PI:
if (XMLookahead(lexer, "?>", true))
{
lexer->state = XML_STATE_NONE;
break;
}
XMLGetc(lexer);
break;
case XML_STATE_ATTR:
attrname = XMLParseName(lexer);
if (!attrname)
@ -250,7 +269,6 @@ XMLFreeEvent(XMLEvent *event)
void *val;
while (HashMapIterate(event->attrs, &key, &val))
{
Log(LOG_INFO, "Trying to free %s", val);
Free(val);
}
HashMapFree(event->attrs);
@ -640,6 +658,8 @@ XMLParseAttQuote(XMLexer *lexer)
point = XMLInitialiseBuffer(lexer);
/* TODO: My Prosody is actually trolling me.
* GIVE ME A FUCKING STREAM ID YOU RETARD. */
while ((c = XMLGetc(lexer)))
{
if (!IsNormalQ(c))

View file

@ -1,5 +1,9 @@
#include <XMPP.h>
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Str.h>
#include <Cytoplasm/Log.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
@ -28,7 +32,7 @@ XMPPInitialiseCompStream(char *host, int port)
char serv[8];
Stream *stream;
snprintf(serv, sizeof(serv), "%hu", port);
snprintf(serv, sizeof(serv), "%hu", port ? port : DEFAULT_PROSODY_PORT);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
@ -51,6 +55,7 @@ XMPPInitialiseCompStream(char *host, int port)
sd = -1;
continue;
}
Log(LOG_INFO, "Connected to port %s", serv);
break;
}
@ -62,6 +67,7 @@ XMPPInitialiseCompStream(char *host, int port)
freeaddrinfo(res0);
stream = StreamFd(sd);
Log(LOG_INFO, "Got %d via %p", sd, stream);
if (!stream)
{
close(sd);
@ -71,13 +77,97 @@ XMPPInitialiseCompStream(char *host, int port)
return stream;
}
#include <Cytoplasm/Sha.h>
static char *
ComputeHandshake(char *shared, char *stream)
{
char *source;
unsigned char *raw_sha;
char *sha;
source = StrConcat(2, stream, shared);
raw_sha = Sha1(source);
sha = ShaToHex(raw_sha);
Free(raw_sha);
Free(source);
return sha;
}
bool
XMPPAuthenticateCompStream(Stream *stream, char *shared)
XMPPAuthenticateCompStream(Stream *stream, char *as, char *shared)
{
/* TODO */
(void) stream;
(void) shared;
return false;
XMLexer *sax;
XMLEvent *ev;
char *stream_id, *handshake;
bool ret = false;
if (!stream || !as || !shared)
{
return false;
}
StreamPrintf(stream,
"<stream:stream "
"xmlns='jabber:component:accept' "
"xmlns:stream='http://etherx.jabber.org/streams' "
"to='%s'>", as
);
StreamFlush(stream);
sax = XMLCreateLexer(stream, false);
while ((ev = XMLCrank(sax)))
{
if (ev->type == XML_RELAX)
{
XMLFreeEvent(ev);
continue;
}
break;
}
if (ev->type != XML_LEXER_STARTELEM ||
!StrEquals(ev->element, "stream:stream"))
{
Log(LOG_ERR, "Excepted strea:stream element.");
XMLFreeEvent(ev);
goto end;
}
stream_id = StrDuplicate(HashMapGet(ev->attrs, "id"));
handshake = ComputeHandshake(shared, stream_id);
/* y no stream id */
Log(LOG_NOTICE, "- sID='%s'", stream_id);
StreamPrintf(stream, "<handshake>%s</handshake>", handshake);
StreamFlush(stream);
XMLFreeEvent(ev);
while ((ev = XMLCrank(sax)))
{
if (ev->type == XML_RELAX)
{
XMLFreeEvent(ev);
continue;
}
break;
}
if (ev->type != XML_LEXER_ELEM ||
!StrEquals(ev->element, "handshake"))
{
Log(LOG_ERR, "Excepted empty handshake reply, got nonsense.");
Free(stream_id);
Free(handshake);
XMLFreeEvent(ev);
goto end;
}
ret = true;
/* We can uhh, send stanzas, and receive them! */
Log(LOG_INFO, "Communications to '%s' established.", as);
XMLFreeEvent(ev);
Free(stream_id);
Free(handshake);
end:
XMLFreeLexer(sax);
return ret;
}
void

View file

@ -10,8 +10,8 @@ typedef struct XMLEvent {
enum {
XML_LEXER_UNKNOWN = 0,
XML_LEXER_STARTELEM,
XML_LEXER_ELEM, /* Empty attr */
XML_LEXER_DATA,
XML_LEXER_ELEM, /* Empty attr */
XML_LEXER_ENDELEM,
XML_RELAX

View file

@ -10,7 +10,7 @@ extern Stream * XMPPInitialiseCompStream(char *host, int port);
/* Authenticates a component stream with a given shared secret,
* with a stream ID from the server. This should be called right
* after XMPPInitialiseCompStream. */
extern bool XMPPAuthenticateCompStream(Stream *stream, char *shared);
extern bool XMPPAuthenticateCompStream(Stream *stream, char *as, char *shared);
/* TODO: XMPP stuff, I don't fucking know, I'm not a Jabbernerd. */