mirror of
https://forge.fsky.io/lda/Parsee.git
synced 2026-03-13 21:35:10 +00:00
[FIX] Remove duplicate file
sorry bros oh btw mein jid ist lda@freetards.xyz
This commit is contained in:
parent
143bdf0a5a
commit
a686449a4d
1 changed files with 0 additions and 381 deletions
|
|
@ -1,381 +0,0 @@
|
||||||
#include <Parsee.h>
|
|
||||||
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include <Cytoplasm/Memory.h>
|
|
||||||
#include <Cytoplasm/Base64.h>
|
|
||||||
#include <Cytoplasm/Util.h>
|
|
||||||
#include <Cytoplasm/Log.h>
|
|
||||||
#include <Cytoplasm/Str.h>
|
|
||||||
#include <Cytoplasm/Sha.h>
|
|
||||||
|
|
||||||
#include <StringStream.h>
|
|
||||||
#include <XMPPCommand.h>
|
|
||||||
#include <Matrix.h>
|
|
||||||
#include <XMPP.h>
|
|
||||||
#include <XML.h>
|
|
||||||
#include <AS.h>
|
|
||||||
|
|
||||||
#include "XMPPThread/internal.h"
|
|
||||||
|
|
||||||
/* Generates a SHA-256 hash of the ver field. */
|
|
||||||
char *
|
|
||||||
XMPPGenerateVer(void)
|
|
||||||
{
|
|
||||||
char *S = NULL;
|
|
||||||
unsigned char *Sha = NULL;
|
|
||||||
Array *identities = ArrayCreate();
|
|
||||||
Array *features = ArrayCreate();
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
/* Initialise identity table, to be sorted */
|
|
||||||
#define IdentitySimple(cat, Type, Name) { \
|
|
||||||
XMPPIdentity *id = Malloc(sizeof(*id)); \
|
|
||||||
id->category = cat; \
|
|
||||||
id->lang = NULL; \
|
|
||||||
id->type = Type; \
|
|
||||||
id->name = Name; \
|
|
||||||
ArrayAdd(identities, id); }
|
|
||||||
IQ_IDENTITY
|
|
||||||
#undef IdentitySimple
|
|
||||||
#define AdvertiseSimple(feature) ArrayAdd(features, feature);
|
|
||||||
IQ_ADVERT
|
|
||||||
#undef AdvertiseSimple
|
|
||||||
ArraySort(identities, IdentitySort);
|
|
||||||
for (i = 0; i < ArraySize(identities); i++)
|
|
||||||
{
|
|
||||||
XMPPIdentity *identity = ArrayGet(identities, i);
|
|
||||||
char *id_chunk = StrConcat(7,
|
|
||||||
identity->category, "/",
|
|
||||||
identity->type, "/",
|
|
||||||
identity->lang, "/",
|
|
||||||
identity->name);
|
|
||||||
char *tmp = S;
|
|
||||||
S = StrConcat(3, S, id_chunk, "<");
|
|
||||||
Free(tmp);
|
|
||||||
Free(id_chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
ArraySort(features, ((int (*) (void *, void *)) ICollate));
|
|
||||||
for (i = 0; i < ArraySize(features); i++)
|
|
||||||
{
|
|
||||||
char *feature = ArrayGet(features, i);
|
|
||||||
char *tmp = S;
|
|
||||||
S = StrConcat(3, S, feature, "<");
|
|
||||||
Free(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
Sha = Sha1(S);
|
|
||||||
Free(S);
|
|
||||||
S = Base64Encode((const char *) Sha, 20);
|
|
||||||
Free(Sha);
|
|
||||||
|
|
||||||
ArrayFree(features);
|
|
||||||
for (i = 0; i < ArraySize(identities); i++)
|
|
||||||
{
|
|
||||||
XMPPIdentity *identity = ArrayGet(identities, i);
|
|
||||||
/* We don't have to do anything here. */
|
|
||||||
Free(identity);
|
|
||||||
}
|
|
||||||
ArrayFree(identities);
|
|
||||||
|
|
||||||
return S;
|
|
||||||
}
|
|
||||||
|
|
||||||
XMLElement *
|
|
||||||
RetrieveStanza(XMPPThread *thread)
|
|
||||||
{
|
|
||||||
XMLElement *ret = NULL;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&thread->info->lock);
|
|
||||||
ret = ArrayDelete(thread->info->stanzas, 0);
|
|
||||||
pthread_mutex_unlock(&thread->info->lock);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
static void
|
|
||||||
PushStanza(XMPPThreadInfo *info, XMLElement *stanza)
|
|
||||||
{
|
|
||||||
pthread_mutex_lock(&info->lock);
|
|
||||||
ArrayAdd(info->stanzas, stanza);
|
|
||||||
pthread_mutex_unlock(&info->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *
|
|
||||||
XMPPDispatcher(void *argp)
|
|
||||||
{
|
|
||||||
XMPPThread *thread = argp;
|
|
||||||
ParseeData *args = thread->info->args;
|
|
||||||
|
|
||||||
while (thread->info->running)
|
|
||||||
{
|
|
||||||
XMLElement *stanza = RetrieveStanza(thread);
|
|
||||||
|
|
||||||
/* TODO: I've seen some spikes in some threads. */
|
|
||||||
if (!stanza)
|
|
||||||
{
|
|
||||||
UtilSleepMillis(5);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StrEquals(stanza->name, "presence"))
|
|
||||||
{
|
|
||||||
PresenceStanza(args, stanza);
|
|
||||||
XMLFreeElement(stanza);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (StrEquals(stanza->name, "message"))
|
|
||||||
{
|
|
||||||
if (!MessageStanza(args, stanza, thread))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (StrEquals(stanza->name, "iq"))
|
|
||||||
{
|
|
||||||
IQStanza(args, stanza, thread);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log(LOG_WARNING, "Unknown stanza '%s':", stanza->name);
|
|
||||||
XMLEncode(StreamStdout(), stanza);
|
|
||||||
StreamPrintf(StreamStdout(), "\n");
|
|
||||||
StreamFlush(StreamStdout());
|
|
||||||
}
|
|
||||||
XMLFreeElement(stanza);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct XMPPAwait {
|
|
||||||
pthread_mutex_t cond_lock;
|
|
||||||
pthread_cond_t condition;
|
|
||||||
bool usable;
|
|
||||||
|
|
||||||
XMLElement *stanza;
|
|
||||||
} XMPPAwait;
|
|
||||||
|
|
||||||
static pthread_mutex_t await_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
static HashMap *await_table = NULL;
|
|
||||||
static XMPPThreadInfo info;
|
|
||||||
|
|
||||||
size_t
|
|
||||||
ParseeCongestion(void)
|
|
||||||
{
|
|
||||||
size_t congestion;
|
|
||||||
pthread_mutex_lock(&info.lock);
|
|
||||||
congestion = ArraySize(info.stanzas);
|
|
||||||
pthread_mutex_unlock(&info.lock);
|
|
||||||
|
|
||||||
return congestion;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
ParseeXMPPThread(void *argp)
|
|
||||||
{
|
|
||||||
ParseeData *args = argp;
|
|
||||||
XMPPComponent *jabber = args->jabber;
|
|
||||||
XMLElement *stanza = NULL;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
/* Initialise the await table */
|
|
||||||
await_table = HashMapCreate();
|
|
||||||
|
|
||||||
/* Initialise the command manager, and add all ad-hoc commands */
|
|
||||||
info.m = XMPPCreateManager(args);
|
|
||||||
{
|
|
||||||
XMPPCommand *cmd;
|
|
||||||
#define XMPP_COMMAND(f,n,t,s) \
|
|
||||||
cmd = XMPPBasicCmd( \
|
|
||||||
n, t, f \
|
|
||||||
); \
|
|
||||||
s \
|
|
||||||
XMPPRegisterCommand(info.m, cmd);
|
|
||||||
XMPPCOMMANDS
|
|
||||||
#undef XMPP_COMMAND
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialise the FIFO */
|
|
||||||
info.stanzas = ArrayCreate();
|
|
||||||
pthread_mutex_init(&info.lock, NULL);
|
|
||||||
|
|
||||||
/* ... and its readers. */
|
|
||||||
/* TODO: Make that configurable. */
|
|
||||||
info.available_dispatchers = 16;
|
|
||||||
info.dispatchers = Malloc(
|
|
||||||
sizeof(*info.dispatchers) * info.available_dispatchers
|
|
||||||
);
|
|
||||||
|
|
||||||
info.args = args;
|
|
||||||
info.jabber = jabber;
|
|
||||||
info.running = true;
|
|
||||||
pthread_mutex_init(&info.chk_lock, NULL);
|
|
||||||
|
|
||||||
for (i = 0; i < info.available_dispatchers; i++)
|
|
||||||
{
|
|
||||||
pthread_t *thr = &info.dispatchers[i].thr;
|
|
||||||
info.dispatchers[i].info = &info;
|
|
||||||
|
|
||||||
pthread_create(thr, NULL, XMPPDispatcher, &info.dispatchers[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
char *id;
|
|
||||||
|
|
||||||
stanza = XMLDecode(jabber->stream, false);
|
|
||||||
if (!stanza)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
id = HashMapGet(stanza->attrs, "id");
|
|
||||||
if (id)
|
|
||||||
{
|
|
||||||
XMPPAwait *await;
|
|
||||||
/* Lock out the table to see if we're awaiting. */
|
|
||||||
pthread_mutex_lock(&await_lock);
|
|
||||||
if ((await = HashMapGet(await_table, id)))
|
|
||||||
{
|
|
||||||
pthread_mutex_lock(&await->cond_lock);
|
|
||||||
await->stanza = stanza;
|
|
||||||
pthread_cond_broadcast(&await->condition);
|
|
||||||
pthread_mutex_unlock(&await->cond_lock);
|
|
||||||
|
|
||||||
HashMapDelete(await_table, id);
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&await_lock);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&await_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Push it into the stanza FIFO. A dispatcher thread should then
|
|
||||||
* be able to freely grab a value(locked by a mutex). We can't make
|
|
||||||
* dispatchers read stanzas on their own, since that's _not_ how
|
|
||||||
* streams work, but this should mitigate some issues, and allow a
|
|
||||||
* few threads to be busy, while the rest of Parsee works. */
|
|
||||||
PushStanza(&info, stanza);
|
|
||||||
}
|
|
||||||
|
|
||||||
info.running = false;
|
|
||||||
Log(LOG_INFO, "Joining subthreads...");
|
|
||||||
for (i = 0; i < info.available_dispatchers; i++)
|
|
||||||
{
|
|
||||||
pthread_t thr = info.dispatchers[i].thr;
|
|
||||||
pthread_join(thr, NULL);
|
|
||||||
}
|
|
||||||
Log(LOG_INFO, "Joined subthreads...");
|
|
||||||
Free(info.dispatchers);
|
|
||||||
|
|
||||||
for (i = 0; i < ArraySize(info.stanzas); i++)
|
|
||||||
{
|
|
||||||
XMLFreeElement(ArrayGet(info.stanzas, i));
|
|
||||||
}
|
|
||||||
ArrayFree(info.stanzas);
|
|
||||||
|
|
||||||
HashMapFree(await_table);
|
|
||||||
|
|
||||||
pthread_mutex_destroy(&info.lock);
|
|
||||||
|
|
||||||
XMPPFreeManager(info.m);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
/* TODO: This function does NIT behave well. */
|
|
||||||
XMLElement *
|
|
||||||
ParseeAwaitStanza(char *identifier, int64_t timeout)
|
|
||||||
{
|
|
||||||
/* TODO: Pthreads HATE me using Malloc here, so I'm abusing stackspace.
|
|
||||||
* Not *too much* of a problem, just a weird oddity. If anyone has a clue
|
|
||||||
* on why that happens (at least on ARM64 with a Pi4 running Debian), let
|
|
||||||
* me know! */
|
|
||||||
XMPPAwait awa;
|
|
||||||
XMLElement *stanza;
|
|
||||||
struct timespec ts;
|
|
||||||
if (!identifier)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert into an absolute timeout.
|
|
||||||
* =================================
|
|
||||||
* XXX: For anyone using timespecs: MAKE ABSOLUTELY FUCKING SURE YOUR NANOS
|
|
||||||
* ARE IN RANGE. THIS UNIRONICALLY CAUSED SOME REAL CONCURRENCY ERRORS ON MY
|
|
||||||
* SIDE FROM TV_NSEC OVERFLOWING AND TIMEDWAIT RETURNING EINVAL. */
|
|
||||||
if (timeout > 0)
|
|
||||||
{
|
|
||||||
int64_t seconds = timeout / (1 SECONDS);
|
|
||||||
int64_t msecond = timeout % (1 SECONDS);
|
|
||||||
|
|
||||||
clock_gettime(CLOCK_REALTIME, &ts);
|
|
||||||
|
|
||||||
ts.tv_sec += seconds ;
|
|
||||||
ts.tv_nsec+= msecond * 1000000 ;
|
|
||||||
if (ts.tv_nsec > 999999999)
|
|
||||||
{
|
|
||||||
int64_t sec_delta = ts.tv_nsec / 1000000000;
|
|
||||||
int64_t nsc_delta = ts.tv_nsec % 1000000000;
|
|
||||||
|
|
||||||
ts.tv_nsec = nsc_delta;
|
|
||||||
ts.tv_sec += sec_delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
(void) msecond;
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_lock(&await_lock);
|
|
||||||
|
|
||||||
pthread_cond_init(&awa.condition, NULL);
|
|
||||||
pthread_mutex_init(&awa.cond_lock, NULL);
|
|
||||||
awa.stanza = NULL;
|
|
||||||
|
|
||||||
HashMapSet(await_table, identifier, &awa);
|
|
||||||
pthread_mutex_unlock(&await_lock);
|
|
||||||
|
|
||||||
pthread_mutex_lock(&awa.cond_lock);
|
|
||||||
while (!awa.stanza)
|
|
||||||
{
|
|
||||||
int code;
|
|
||||||
|
|
||||||
if (timeout <= 0)
|
|
||||||
{
|
|
||||||
pthread_cond_wait(&awa.condition, &awa.cond_lock);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
code = pthread_cond_timedwait(&awa.condition, &awa.cond_lock, &ts);
|
|
||||||
if (code == ETIMEDOUT)
|
|
||||||
{
|
|
||||||
/* Timeout detected, give up regardless of the status of our
|
|
||||||
* search. */
|
|
||||||
HashMapDelete(await_table, identifier);
|
|
||||||
pthread_mutex_unlock(&await_lock);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (code == EINVAL)
|
|
||||||
{
|
|
||||||
Log(LOG_ERR, "=========== Achievement GET! ===========");
|
|
||||||
Log(LOG_ERR, "%s: TIMEDWAIT RETURNED EINVAL.", __func__);
|
|
||||||
Log(LOG_ERR, "THIS IS, LET'S SAY, NOT GOOD, AND A SIGN OF ");
|
|
||||||
Log(LOG_ERR, "A PROGRAMMER ERROR. PLEASE PKILL -9 PARSEE.");
|
|
||||||
Log(LOG_ERR, "");
|
|
||||||
Log(LOG_ERR, "YOU, HOWEVER, GET TO WIN AN AWARD FOR THIS.");
|
|
||||||
Log(LOG_ERR, "I AM SIMPLY JEALOUS OF YOU GETTING SUCH A ");
|
|
||||||
Log(LOG_ERR, "GOOD ERROR MESSAGE.");
|
|
||||||
Log(LOG_ERR, "=========== Achievement GET! ===========");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stanza = awa.stanza;
|
|
||||||
pthread_mutex_unlock(&awa.cond_lock);
|
|
||||||
|
|
||||||
pthread_cond_destroy(&awa.condition);
|
|
||||||
pthread_mutex_destroy(&awa.cond_lock);
|
|
||||||
return stanza;
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue