mirror of
https://forge.fsky.io/lda/Parsee.git
synced 2026-03-13 21:25:11 +00:00
207 lines
4.4 KiB
C
207 lines
4.4 KiB
C
#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>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <netdb.h>
|
|
|
|
#include <Parsee.h>
|
|
#include <XML.h>
|
|
|
|
/* The default component port Prosody uses. */
|
|
#define DEFAULT_PROSODY_PORT 5347
|
|
|
|
XMPPComponent *
|
|
XMPPInitialiseCompStream(char *host, int port)
|
|
{
|
|
int sd = -1;
|
|
struct addrinfo hints, *res, *res0;
|
|
int error;
|
|
char serv[8];
|
|
Stream *stream;
|
|
XMPPComponent *comp;
|
|
|
|
snprintf(serv, sizeof(serv), "%hu", port ? port : DEFAULT_PROSODY_PORT);
|
|
|
|
memset(&hints, 0, sizeof(hints));
|
|
hints.ai_family = AF_UNSPEC;
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
error = getaddrinfo(host, serv, &hints, &res0);
|
|
|
|
for (res = res0; res; res = res->ai_next)
|
|
{
|
|
sd = socket(res->ai_family, res->ai_socktype,
|
|
res->ai_protocol);
|
|
|
|
if (sd < 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (connect(sd, res->ai_addr, res->ai_addrlen) < 0)
|
|
{
|
|
close(sd);
|
|
sd = -1;
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (sd < 0)
|
|
{
|
|
return NULL;
|
|
}
|
|
freeaddrinfo(res0);
|
|
|
|
stream = StreamFd(sd);
|
|
if (!stream)
|
|
{
|
|
close(sd);
|
|
return NULL;
|
|
}
|
|
|
|
comp = Malloc(sizeof(*comp));
|
|
comp->host = StrDuplicate(host);
|
|
comp->stream = stream;
|
|
pthread_mutex_init(&comp->write_lock, NULL);
|
|
|
|
(void) error;
|
|
|
|
return comp;
|
|
}
|
|
|
|
#include <Cytoplasm/Sha.h>
|
|
static char *
|
|
ComputeHandshake(char *shared, char *stream)
|
|
{
|
|
char *source;
|
|
char *sha;
|
|
|
|
source = StrConcat(2, stream, shared);
|
|
sha = ParseeSHA1(source);
|
|
|
|
Free(source);
|
|
|
|
return sha;
|
|
}
|
|
bool
|
|
XMPPAuthenticateCompStream(XMPPComponent *comp, char *shared)
|
|
{
|
|
/* TODO */
|
|
XMLexer *sax;
|
|
XMLEvent *ev;
|
|
char *stream_id, *handshake;
|
|
bool ret = false;
|
|
Stream *stream;
|
|
char *as;
|
|
if (!comp || !shared)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
pthread_mutex_lock(&comp->write_lock);
|
|
|
|
stream = comp->stream;
|
|
as = comp->host;
|
|
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 stream:stream element.");
|
|
XMLFreeEvent(ev);
|
|
goto end;
|
|
}
|
|
|
|
stream_id = StrDuplicate(HashMapGet(ev->attrs, "id"));
|
|
handshake = ComputeHandshake(shared, stream_id);
|
|
|
|
Log(LOG_DEBUG, "- 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.");
|
|
Log(LOG_ERR, "Another service (possibly Parsee) may have taken over.");
|
|
Log(LOG_ERR, "");
|
|
Log(LOG_ERR, "Simply jealous of that other service...");
|
|
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);
|
|
pthread_mutex_unlock(&comp->write_lock);
|
|
return ret;
|
|
}
|
|
|
|
void
|
|
XMPPFinishCompStream(XMPPComponent *comp)
|
|
{
|
|
if (!comp)
|
|
{
|
|
return;
|
|
}
|
|
pthread_mutex_lock(&comp->write_lock);
|
|
StreamPrintf(comp->stream, "<stream:stream/>");
|
|
StreamFlush(comp->stream);
|
|
pthread_mutex_unlock(&comp->write_lock);
|
|
}
|
|
void
|
|
XMPPEndCompStream(XMPPComponent *comp)
|
|
{
|
|
if (!comp)
|
|
{
|
|
return;
|
|
}
|
|
pthread_mutex_lock(&comp->write_lock);
|
|
StreamClose(comp->stream);
|
|
comp->stream = NULL;
|
|
pthread_mutex_unlock(&comp->write_lock);
|
|
pthread_mutex_destroy(&comp->write_lock);
|
|
Free(comp->host);
|
|
Free(comp);
|
|
}
|