Parsee/tools/config.c

201 lines
5.3 KiB
C

/* config.c - Generates a nice Parsee config file
* ============================================================
* Example of usage(for a blow.hole HS and a xmpp.blow.hole JCP):
* tools/out/config \
* -d '/var/lib/parsee' \
* -m 'https://pmedia.blow.hole' \
* -H 'blow.hole' \
* -s 'The Dark Blowhole shared secret' \
* -J 'xmpp.blow.hole'
* Under CC0, as its a rather useful example of a Parsee tool.
* See LICENSE for more information about Parsee's licensing. */
#include <Cytoplasm/HttpClient.h>
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Json.h>
#include <Cytoplasm/Args.h>
#include <Cytoplasm/Util.h>
#include <Cytoplasm/Log.h>
#include <Cytoplasm/Uri.h>
#include <Cytoplasm/Str.h>
#include <Cytoplasm/Db.h>
#include <stdlib.h>
static Uri *
DelegateServer(char *raw)
{
HttpClientContext *ctx = NULL;
Stream *stream = NULL;
HashMap *reply = NULL;
Uri *ret = NULL;
if (!raw)
{
return NULL;
}
ctx = HttpRequest(
HTTP_GET,
HTTP_FLAG_TLS, 443,
raw, "/.well-known/matrix/client"
);
HttpRequestSendHeaders(ctx);
switch (HttpRequestSend(ctx))
{
case HTTP_OK:
stream = HttpClientStream(ctx);
reply = JsonDecode(stream);
if (!reply)
{
goto end;
}
ret = UriParse(JsonValueAsString(JsonGet(
reply, 2,
"m.homeserver", "base_url"
)));
break;
default:
/* TODO */
break;
}
if (ret && !ret->port && StrEquals(ret->proto, "https"))
{
ret->port = 443;
}
if (ret && !ret->port)
{
ret->port = 80;
}
end:
HttpClientContextFree(ctx);
JsonFree(reply);
return ret;
}
int
Main(Array *args, HashMap *env)
{
/* TODO: Not user friendly either. */
ArgParseState state;
Uri *api_base;
char *homeserver = NULL, *jcp = NULL, *jabber = NULL;
char *data = NULL, *media = NULL, *listen = NULL;
int flag, code = EXIT_FAILURE;
int port = 5347;
size_t lmdb_size = 0;
listen = "localhost";
ArgParseStateInit(&state);
while ((flag = ArgParse(&state, args, "H:J:s:d:p:m:l:S:")) != -1)
{
switch (flag)
{
case 'H':
homeserver = state.optArg;
break;
case 's':
jcp = state.optArg;
break;
case 'm':
Free(media);
media = StrDuplicate(state.optArg);
break;
case 'J':
jabber = state.optArg;
break;
case 'd':
data = state.optArg;
break;
case 'l':
listen = state.optArg;
break;
case 'p':
port = strtol(state.optArg, NULL, 10);
break;
case 'S':
lmdb_size = strtol(state.optArg, NULL, 10) * 1024 * 1024;
break;
}
}
api_base = DelegateServer(homeserver);
if (!api_base || !jcp || !jabber || !data || !listen)
{
Log(LOG_ERR,
"Usage: %s "
"-d [Database directory] "
"-m <Base URL for media files>"
"-H [matrixserv.fed] "
"-s [XMPP shared secret] "
"-l [Host/IP to listen as] "
"-p [XMPP component port=5347] "
"-J [parsee.xmppserver.ex]",
"-S [LMDB size]",
ArrayGet(args, 0)
);
goto end;
}
if (!media)
{
char *s_port = StrInt(port);
media = StrConcat(4, "http://", listen, ":", s_port);
Free(s_port);
}
{
HashMap *json = HashMapCreate();
Stream *file = StreamOpen("parsee.json", "w");
char *as_token, *hs_token;
as_token = StrRandom(32);
hs_token = StrRandom(32);
UtilMkdir(data, 0755);
JsonSet(json, JsonValueString(data), 1, "db");
JsonSet(json, JsonValueInteger(lmdb_size), 1, "db_size");
JsonSet(json, JsonValueString(homeserver), 1, "hs_base");
JsonSet(json, JsonValueString(api_base->host), 1, "hs_host");
JsonSet(json, JsonValueInteger(api_base->port), 1, "hs_port");
JsonSet(json, JsonValueString(as_token), 1, "as_token");
JsonSet(json, JsonValueString(hs_token), 1, "hs_token");
JsonSet(json, JsonValueString("_p_"), 1, "namespace");
JsonSet(json, JsonValueString("_parsee"), 1, "sender");
JsonSet(json, JsonValueInteger(7642), 1, "port");
JsonSet(json, JsonValueString(jabber), 1, "component_host");
JsonSet(json, JsonValueInteger(port), 1, "component_port");
JsonSet(json, JsonValueString(jcp), 1, "shared_secret");
JsonSet(json, JsonValueString(media), 1, "media_base");
JsonSet(json, JsonValueString(listen), 1, "listen_as");
JsonEncode(json, file, JSON_PRETTY);
StreamFlush(file);
StreamClose(file);
Log(LOG_INFO, "AS token=%s", as_token);
Log(LOG_INFO, "HS token=%s", hs_token);
Free(as_token);
Free(hs_token);
JsonFree(json);
}
code = EXIT_SUCCESS;
end:
UriFree(api_base);
Free(media);
return code;
}