Parsee/src/XMPPThread/PresenceSub.c
2024-09-19 23:24:46 +02:00

148 lines
3.2 KiB
C

#include "XMPPThread/internal.h"
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Base64.h>
#include <Cytoplasm/Json.h>
#include <Cytoplasm/Log.h>
#include <Cytoplasm/Str.h>
#include <Cytoplasm/Db.h>
#include <string.h>
static char *
SubscriptionHash(ParseeData *data, char *from, char *to)
{
uint8_t *sum;
char *hash;
size_t len;
len = strlen(from) + 1 + strlen(to);
sum = Malloc(len);
memset(sum, 0x00, len);
memcpy(&sum[0], from, strlen(from));
memcpy(&sum[strlen(from) + 1], to, strlen(to));
hash = Base64Encode(sum, len);
Free(sum);
return hash;
}
static void
DecodeSubscription(ParseeData *data, char *hash, char **from, char **to)
{
char *sum;
if (!data || !hash || !from || !to)
{
return;
}
sum = Base64Decode(hash, strlen(hash));
*from = StrDuplicate(sum);
*to = StrDuplicate(sum + strlen(sum) + 1);
Free(sum);
}
void
AddPresenceSubscriber(ParseeData *data, char *from, char *to)
{
Db *database;
DbRef *ref;
char *hash;
if (!data || !from || !to)
{
return;
}
database = data->db;
hash = SubscriptionHash(data, from, to);
ref = DbCreate(database, 2, "subs", hash);
if (!ref)
{
goto end;
}
HashMapSet(DbJson(ref), "from", JsonValueString(from));
HashMapSet(DbJson(ref), "to", JsonValueString(to));
/* I don't think we need more information right now */
end:
DbUnlock(database, ref);
Free(hash);
}
bool
IsSubscribed(ParseeData *data, char *user, char *to)
{
Db *database;
char *hash;
bool ret;
if (!data || !user || !to)
{
return false;
}
database = data->db;
hash = SubscriptionHash(data, user, to);
ret = DbExists(database, 2, "subs", hash);
Free(hash);
return ret;
}
void
ParseeBroadcastStanza(ParseeData *data, char *from, XMLElement *stanza)
{
XMPPComponent *jabber = data ? data->jabber : NULL;
Array *entries;
size_t i;
if (!data || !from || !stanza)
{
return;
}
/* Copy our stanza so that we can freely modify it */
stanza = XMLCopy(stanza);
/* Start doing a storm on Mt. Subs. */
entries = DbList(data->db, 1, "subs");
for (i = 0; i < ArraySize(entries); i++)
{
char *entry = ArrayGet(entries, i);
char *entry_from = NULL, *entry_to = NULL;
char *storm_id; /* ooe */
XMLElement *sub;
DecodeSubscription(data, entry, &entry_from, &entry_to);
if (!StrEquals(entry_to, from))
{
goto end;
}
Log(LOG_DEBUG,
"PRESENCE SYSTEM: "
"We should be brotkasting straight to %s (from %s)",
entry_from, from
);
sub = XMLCopy(stanza);
XMLAddAttr(sub, "from", from);
XMLAddAttr(sub, "to", entry_from);
/* TODO: Should we store IDs somewhere? */
XMLAddAttr(sub, "id", (storm_id = StrRandom(16)));
pthread_mutex_lock(&jabber->write_lock);
XMLEncode(jabber->stream, sub);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(sub);
Free(storm_id);
end:
Free(entry_from);
Free(entry_to);
}
DbListFree(entries);
XMLFreeElement(stanza);
}