[MOD/WIP] Externalise and add errors to commands

Still need forms...
This commit is contained in:
LDA 2024-07-13 22:34:51 +02:00
commit a880769c48
9 changed files with 311 additions and 89 deletions

View file

@ -19,8 +19,8 @@ SOURCE=src
OBJECT=build OBJECT=build
INCLUDES=src/include INCLUDES=src/include
CC=cc CC=cc
CFLAGS=-I$(INCLUDES) -I$(CYTO_INC) -DNAME="\"$(NAME)\"" -DVERSION="\"$(VERSION)\"" -DREPOSITORY=\"$(REPOSITORY)\" -O3 -g -ggdb -Wall -Werror -flto CFLAGS=-I$(INCLUDES) -I$(CYTO_INC) -DNAME="\"$(NAME)\"" -DVERSION="\"$(VERSION)\"" -DREPOSITORY=\"$(REPOSITORY)\" -O3 -g -ggdb -Wall -Werror
LDFLAGS=-L $(CYTO_LIB) -lCytoplasm -Wl,--export-dynamic -O3 -g -ggdb -flto LDFLAGS=-L $(CYTO_LIB) -lCytoplasm -Wl,--export-dynamic -O3 -g -ggdb
BINARY=parsee BINARY=parsee
# ============================ Compilation ================================= # ============================ Compilation =================================
SRC_FILES:=$(shell find $(SOURCE) -name '*.c') SRC_FILES:=$(shell find $(SOURCE) -name '*.c')

View file

@ -108,13 +108,13 @@ XMPPCommandRequiresForm(XMPPCommand *cmd)
return cmd ? !!cmd->options : false; return cmd ? !!cmd->options : false;
} }
void void
XMPPExecuteCommand(XMPPCommandManager *m, XMPPCommand *cmd, XMLElement *to, HashMap *arg_table) XMPPExecuteCommand(XMPPCommandManager *m, XMPPCommand *cmd, char *from, XMLElement *to, HashMap *arg_table)
{ {
if (!m || !cmd || !to) if (!m || !cmd || !from || !to)
{ {
return; return;
} }
cmd->callback(m, arg_table, to); cmd->callback(m, from, arg_table, to);
/* TODO Free arg_table's strings */ /* TODO Free arg_table's strings */
HashMapFree(arg_table); HashMapFree(arg_table);

View file

@ -32,6 +32,8 @@ struct XMPPCommandManager {
HashMap *commands; HashMap *commands;
HashMap *sessions; HashMap *sessions;
void *cookie;
}; };
static void static void
XMPPDestroySession(XMPPSession *session) XMPPDestroySession(XMPPSession *session)
@ -99,13 +101,14 @@ XMPPRegisterSession(XMPPCommandManager *m, char *p_jid, char *s_jid, char *node)
XMPPCommandManager * XMPPCommandManager *
XMPPCreateManager(void) XMPPCreateManager(void *cookie)
{ {
XMPPCommandManager *ret = Malloc(sizeof(*ret)); XMPPCommandManager *ret = Malloc(sizeof(*ret));
pthread_mutex_init(&ret->lock, NULL); pthread_mutex_init(&ret->lock, NULL);
ret->commands = HashMapCreate(); ret->commands = HashMapCreate();
ret->sessions = HashMapCreate(); ret->sessions = HashMapCreate();
ret->cookie = cookie;
return ret; return ret;
} }
@ -237,7 +240,7 @@ XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeData *data)
XMLAddAttr(command_xml, "node", node); XMLAddAttr(command_xml, "node", node);
XMLAddAttr(command_xml, "status", "completed"); XMLAddAttr(command_xml, "status", "completed");
XMLAddAttr(command_xml, "sessionid", session_id); XMLAddAttr(command_xml, "sessionid", session_id);
XMPPExecuteCommand(m, cmd, command_xml, NULL); XMPPExecuteCommand(m, cmd, from, command_xml, NULL);
XMLAddChild(iq, command_xml); XMLAddChild(iq, command_xml);
pthread_mutex_lock(&jabber->write_lock); pthread_mutex_lock(&jabber->write_lock);
@ -258,3 +261,8 @@ end:
pthread_mutex_unlock(&m->lock); pthread_mutex_unlock(&m->lock);
return good; return good;
} }
void *
XMPPGetManagerCookie(XMPPCommandManager *manager)
{
return manager ? manager->cookie : NULL;
}

68
src/XMPPCommands/Admins.c Normal file
View file

@ -0,0 +1,68 @@
#include <Cytoplasm/HashMap.h>
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Json.h>
#include <Cytoplasm/Util.h>
#include <Cytoplasm/Str.h>
#include <Cytoplasm/Log.h>
#include <XMPPFormTool.h>
#include <XMPPCommand.h>
#include <Parsee.h>
#include <XMPP.h>
void
AdminsCallback(XMPPCommandManager *m, char *from, HashMap *form, XMLElement *out)
{
ParseeData *data = XMPPGetManagerCookie(m);
char *trimmed = ParseeTrimJID(from);
size_t i;
XMLElement *x;
XMLElement *title;
XMLElement *reported, *item, *field, *value, *txt;
if (!ParseeIsAdmin(data, trimmed))
{
XMLElement *note = XMLCreateTag("note");
XMLAddAttr(note, "type", "error");
txt = XMLCreateText("User is not authorised to execute command.");
XMLAddChild(note, txt);
XMLAddChild(out, note);
Free(trimmed);
return;
}
Free(trimmed);
x = XMLCreateTag("x");
title = XMLCreateTag("title");
{
XMLElement *title_text = XMLCreateText("Parsee administrators");
XMLAddChild(title, title_text);
}
XMLAddChild(x, title);
XMLAddAttr(x, "xmlns", "jabber:x:data");
XMLAddAttr(x, "type", "result");
{
DbRef *ref = DbLock(data->db, 1, "admins");
Array *admins = GrabArray(DbJson(ref), 1, "admins");
reported = XMLCreateTag("reported");
XMLAddChild(x, reported);
/* Report */
Report("admins", "Administrator globs");
/* Set */
for (i = 0; i < ArraySize(admins); i++)
{
char *glob = JsonValueAsString(ArrayGet(admins, i));
BeginItem();
SetField("admins", glob);
EndItem();
}
DbUnlock(data->db, ref);
}
XMLAddChild(out, x);
}

89
src/XMPPCommands/Nofly.c Normal file
View file

@ -0,0 +1,89 @@
#include <Cytoplasm/HashMap.h>
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Json.h>
#include <Cytoplasm/Util.h>
#include <Cytoplasm/Str.h>
#include <Cytoplasm/Log.h>
#include <XMPPFormTool.h>
#include <XMPPCommand.h>
#include <Parsee.h>
#include <XMPP.h>
#define TITLE "Parsee global bans"
void
NoflyCallback(XMPPCommandManager *m, char *from, HashMap *form, XMLElement *out)
{
ParseeData *data = XMPPGetManagerCookie(m);
char *trimmed = ParseeTrimJID(from);
XMLElement *x;
XMLElement *title;
XMLElement *reported, *item, *field, *value, *txt;
if (!ParseeIsAdmin(data, trimmed))
{
XMLElement *note = XMLCreateTag("note");
XMLAddAttr(note, "type", "error");
txt = XMLCreateText("User is not authorised to execute command.");
XMLAddChild(note, txt);
XMLAddChild(out, note);
Free(trimmed);
return;
}
x = XMLCreateTag("x");
XMLAddAttr(x, "xmlns", "jabber:x:data");
title = XMLCreateTag("title");
XMLAddChild(x, title);
XMLAddChild(out, x);
Free(trimmed);
{
XMLElement *title_text = XMLCreateText(TITLE);
XMLAddChild(title, title_text);
}
XMLAddAttr(x, "type", "result");
{
DbRef *ref = DbLock(data->db, 1, "global_bans");
HashMap *bans = DbJson(ref);
char *banned, *reason;
JsonValue *ban_val;
reported = XMLCreateTag("reported");
XMLAddChild(x, reported);
/* Report */
Report("ban", "Banned glob");
Report("reason", "Reason for the nofly");
Report("ts", "UNIX timestamp for creation");
/* Set */
while (HashMapIterate(bans, &banned, (void **) &ban_val))
{
HashMap *ban_obj = JsonValueAsObject(ban_val);
reason = GrabString(ban_obj, 1, "reason");
char *ts = StrDuplicate("N/A");
if (!reason)
{
reason = "N/A";
}
if (HashMapGet(ban_obj, "date"))
{
Free(ts);
ts = StrInt(GrabInteger(ban_obj, 1, "date") / (1 SECONDS));
}
BeginItem();
SetField("ban", banned);
SetField("reason", reason);
SetField("ts", ts);
EndItem();
Free(ts);
}
DbUnlock(data->db, ref);
}
}

77
src/XMPPCommands/Status.c Normal file
View file

@ -0,0 +1,77 @@
#include <Cytoplasm/HashMap.h>
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Json.h>
#include <Cytoplasm/Util.h>
#include <Cytoplasm/Str.h>
#include <Cytoplasm/Log.h>
#include <XMPPFormTool.h>
#include <XMPPCommand.h>
#include <Parsee.h>
#include <XMPP.h>
void
StatusCallback(XMPPCommandManager *m, char *from, HashMap *form, XMLElement *out)
{
ParseeData *data = XMPPGetManagerCookie(m);
char *trimmed = ParseeTrimJID(from);
size_t alloc = MemoryAllocated();
size_t kb = alloc >> 10;
size_t mb = kb >> 10;
size_t gb = mb >> 10;
size_t min = gb ? gb : (mb ? mb : (kb ? kb : alloc));
char *unit = gb ? "GB" : (mb ? "MB" : (kb ? "KB" : "B"));
XMLElement *x;
XMLElement *title, *txt;
if (!ParseeIsAdmin(data, trimmed))
{
XMLElement *note = XMLCreateTag("note");
XMLAddAttr(note, "type", "error");
txt = XMLCreateText("User is not authorised to execute command.");
XMLAddChild(note, txt);
XMLAddChild(out, note);
Free(trimmed);
return;
}
Free(trimmed);
x = XMLCreateTag("x");
title = XMLCreateTag("title");
{
XMLElement *title_text = XMLCreateText("Parsee statistics");
XMLAddChild(title, title_text);
}
XMLAddChild(x, title);
XMLAddAttr(x, "xmlns", "jabber:x:data");
XMLAddAttr(x, "type", "result");
{
XMLElement *reported, *item, *field, *value;
reported = XMLCreateTag("reported");
XMLAddChild(x, reported);
/* Report */
Report("mem-alloc", "Heap allocated with Cytoplasm");
Report("xml-congest", "Unprocessed stanzas(congestion)");
/* Set */
BeginItem();
{
char *min_str = StrInt(min);
char *congest = StrInt(ParseeCongestion());
char *alloc = StrConcat(3, min_str, " ", unit);
SetField("mem-alloc", alloc);
SetField("xml-congest", congest);
Free(congest);
Free(min_str);
Free(alloc);
}
EndItem();
}
XMLAddChild(out, x);
}

View file

@ -1565,78 +1565,6 @@ ParseeCongestion(void)
return congestion; return congestion;
} }
static void
StatusCallback(XMPPCommandManager *m, HashMap *data, XMLElement *out)
{
size_t alloc = MemoryAllocated();
size_t kb = alloc >> 10;
size_t mb = kb >> 10;
size_t gb = mb >> 10;
size_t min = gb ? gb : (mb ? mb : (kb ? kb : alloc));
char *unit = gb ? "GB" : (mb ? "MB" : (kb ? "KB" : "B"));
XMLElement *x = XMLCreateTag("x");
XMLElement *title = XMLCreateTag("title");
{
XMLElement *title_text = XMLCreateText("Parsee statistics");
XMLAddChild(title, title_text);
}
XMLAddChild(x, title);
XMLAddAttr(x, "xmlns", "jabber:x:data");
XMLAddAttr(x, "type", "result");
{
XMLElement *reported, *item, *field, *value, *txt;
reported = XMLCreateTag("reported");
XMLAddChild(x, reported);
#define Report(id, label) do \
{ \
field = XMLCreateTag("field"); \
XMLAddAttr(field, "var", id); \
XMLAddAttr(field, "label", label); \
XMLAddChild(reported, field); \
} \
while(0)
#define BeginItem() item = XMLCreateTag("item")
#define EndItem() XMLAddChild(x, item)
#define SetField(id, val) do \
{ \
field = XMLCreateTag("field"); \
value = XMLCreateTag("value"); \
txt = XMLCreateText(val); \
XMLAddAttr(field, "var", id); \
XMLAddChild(value, txt); \
XMLAddChild(field, value); \
XMLAddChild(item, field); \
} \
while(0)
/* Report */
Report("mem-alloc", "Heap allocated with Cytoplasm");
Report("xml-congest", "Unprocessed stanzas(congestion)");
/* Set */
BeginItem();
{
char *min_str = StrInt(min);
char *congest = StrInt(ParseeCongestion());
char *alloc = StrConcat(3, min_str, " ", unit);
SetField("mem-alloc", alloc);
SetField("xml-congest", congest);
Free(congest);
Free(min_str);
Free(alloc);
}
EndItem();
#undef SetField
#undef EndItem
#undef BeginItem
#undef Report
}
XMLAddChild(out, x);
}
void * void *
ParseeXMPPThread(void *argp) ParseeXMPPThread(void *argp)
{ {
@ -1649,15 +1577,17 @@ ParseeXMPPThread(void *argp)
await_table = HashMapCreate(); await_table = HashMapCreate();
/* Initialise the command manager, and add all ad-hoc commands */ /* Initialise the command manager, and add all ad-hoc commands */
info.m = XMPPCreateManager(); info.m = XMPPCreateManager(args);
{ {
XMPPCommand *cmd; XMPPCommand *cmd;
#define XMPP_COMMAND(f,n,t,s) \
cmd = XMPPBasicCmd( cmd = XMPPBasicCmd( \
"status", "Get status about Parsee", n, t, f \
StatusCallback ); \
); s \
XMPPRegisterCommand(info.m, cmd); XMPPRegisterCommand(info.m, cmd);
XMPPCOMMANDS
#undef XMPP_COMMAND
} }
/* Initialise the FIFO */ /* Initialise the FIFO */

View file

@ -10,15 +10,16 @@
typedef struct XMPPCommandManager XMPPCommandManager; typedef struct XMPPCommandManager XMPPCommandManager;
typedef struct XMPPCommand XMPPCommand; typedef struct XMPPCommand XMPPCommand;
typedef struct XMPPOption XMPPOption; typedef struct XMPPOption XMPPOption;
typedef void (*XMPPCmdCallback)(XMPPCommandManager *, HashMap *, XMLElement *); typedef void (*XMPPCmdCallback)(XMPPCommandManager *, char *, HashMap *, XMLElement *);
/** Creates a simple XMPP command manager, which routes commands /** Creates a simple XMPP command manager, which routes commands
* with a single-stage form system. * with a single-stage form system, with a {cookie}
* ------------------------------------------- * -------------------------------------------
* Returns: An opaque command manager[LA:HEAP] * Returns: An opaque command manager[LA:HEAP]
* Modifies: NOTHING * Modifies: NOTHING
* See-Also: XMPPFreeManager */ * See-Also: XMPPFreeManager */
extern XMPPCommandManager * XMPPCreateManager(void); extern XMPPCommandManager * XMPPCreateManager(void *cookie);
extern void * XMPPGetManagerCookie(XMPPCommandManager *manager);
/** Create a basic command with a node and name description /** Create a basic command with a node and name description
* ----------------------------------------------------- * -----------------------------------------------------
@ -31,7 +32,7 @@ extern XMLElement * XMPPFormifyCommand(XMPPCommand *cmd);
extern char * XMPPGetCommandNode(XMPPCommand *cmd); extern char * XMPPGetCommandNode(XMPPCommand *cmd);
extern char * XMPPGetCommandDesc(XMPPCommand *cmd); extern char * XMPPGetCommandDesc(XMPPCommand *cmd);
extern bool XMPPCommandRequiresForm(XMPPCommand *cmd); extern bool XMPPCommandRequiresForm(XMPPCommand *cmd);
extern void XMPPExecuteCommand(XMPPCommandManager *m, XMPPCommand *cmd, XMLElement *to, HashMap *arg_table); extern void XMPPExecuteCommand(XMPPCommandManager *m, XMPPCommand *cmd, char *from, XMLElement *to, HashMap *arg_table);
/** Create a basic option. /** Create a basic option.
* ----------------------------------------------------- * -----------------------------------------------------
@ -80,4 +81,15 @@ extern void XMPPFreeManager(XMPPCommandManager *manager);
* Modifies: {manager} * Modifies: {manager}
* See-Also: XMPPCreateManager */ * See-Also: XMPPCreateManager */
extern bool XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeData *data); extern bool XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeData *data);
/* --------------------------------- COMMANDS --------------------------------- */
#define XMPPCOMMANDS \
XMPP_COMMAND(StatusCallback, "stats", "Get Parsee statistics", {}) \
XMPP_COMMAND(AdminsCallback, "admin", "Get Parsee admin list", {}) \
XMPP_COMMAND(NoflyCallback, "nofly", "Get Parsee nofly list", {})
#define XMPP_COMMAND(f,n,t,s) extern void f(XMPPCommandManager *, char *, HashMap *, XMLElement *);
XMPPCOMMANDS
#undef XMPP_COMMAND
#endif #endif

View file

@ -0,0 +1,38 @@
#ifndef PARSEE_FORM_H
#define PARSEE_FORM_H
#define Report(id, label) do \
{ \
field = XMLCreateTag("field"); \
XMLAddAttr(field, "var", id); \
XMLAddAttr(field, "label", label); \
XMLAddChild(reported, field); \
} \
while(0)
#define BeginItem() item = XMLCreateTag("item")
#define EndItem() XMLAddChild(x, item)
#define SetField(id, val) do \
{ \
field = XMLCreateTag("field"); \
value = XMLCreateTag("value"); \
txt = XMLCreateText(val); \
XMLAddAttr(field, "var", id); \
XMLAddChild(value, txt); \
XMLAddChild(field, value); \
XMLAddChild(item, field); \
} \
while(0)
#define SetFixed(id, val) do \
{ \
field = XMLCreateTag("field"); \
value = XMLCreateTag("value"); \
txt = XMLCreateText(val); \
XMLAddAttr(field, "var", id); \
XMLAddAttr(field, "type", "fixed"); \
XMLAddChild(value, txt); \
XMLAddChild(field, value); \
XMLAddChild(item, field); \
} \
while(0)
#endif