mirror of
https://forge.fsky.io/lda/Parsee.git
synced 2026-03-13 15:05:11 +00:00
[ADD/WIP] Add some HTTP request code
We can now *register* users!
This commit is contained in:
parent
47c98cbbe3
commit
0fa95c2d14
12 changed files with 320 additions and 11 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,3 +1,4 @@
|
||||||
build/*
|
build/*
|
||||||
build
|
build
|
||||||
|
parsee*
|
||||||
parsee
|
parsee
|
||||||
|
|
|
||||||
56
src/AS.c
Normal file
56
src/AS.c
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
#include <AS.h>
|
||||||
|
|
||||||
|
#include <Cytoplasm/Memory.h>
|
||||||
|
#include <Cytoplasm/Str.h>
|
||||||
|
#include <Cytoplasm/Log.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <Matrix.h>
|
||||||
|
|
||||||
|
HashMap *
|
||||||
|
ASVerifyRequest(ParseeHttpArg *arg)
|
||||||
|
{
|
||||||
|
HashMap *ret = NULL;
|
||||||
|
HashMap *params;
|
||||||
|
char *authorisation;
|
||||||
|
if (!arg)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
params = HttpRequestHeaders(arg->ctx);
|
||||||
|
authorisation = HashMapGet(params, "authorization");
|
||||||
|
|
||||||
|
if (!authorisation || strncmp(authorisation, "Bearer ", 7))
|
||||||
|
{
|
||||||
|
Log(LOG_INFO, "Bad auth %s", authorisation);
|
||||||
|
HttpResponseStatus(arg->ctx, HTTP_FORBIDDEN);
|
||||||
|
ret = MatrixCreateError("M_MISSING_TOKEN", "No 'hs_token' given in.");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
authorisation += 7;
|
||||||
|
if (!StrEquals(authorisation, arg->data->config->hs_token))
|
||||||
|
{
|
||||||
|
HttpResponseStatus(arg->ctx, HTTP_FORBIDDEN);
|
||||||
|
ret = MatrixCreateError("M_FORBIDDEN","Incorrect authorisation given");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASAuthenticateRequest(ParseeConfig *data, HttpClientContext *ctx)
|
||||||
|
{
|
||||||
|
char *bearer;
|
||||||
|
if (!data || !ctx)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bearer = StrConcat(2, "Bearer ", data->as_token);
|
||||||
|
HttpRequestHeader(ctx, "Authorization", bearer);
|
||||||
|
Free(bearer);
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include <Cytoplasm/Log.h>
|
#include <Cytoplasm/Log.h>
|
||||||
#include <Cytoplasm/Str.h>
|
#include <Cytoplasm/Str.h>
|
||||||
|
|
||||||
|
#include <Matrix.h>
|
||||||
#include <Routes.h>
|
#include <Routes.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -28,11 +29,18 @@ ParseeRequest(HttpServerContext *ctx, void *argp)
|
||||||
|
|
||||||
arg.stream = stream;
|
arg.stream = stream;
|
||||||
|
|
||||||
|
Log(LOG_NOTICE, "%s %s",
|
||||||
|
HttpRequestMethodToString(HttpRequestMethodGet(ctx)),
|
||||||
|
path
|
||||||
|
);
|
||||||
|
|
||||||
if (!HttpRouterRoute(data->router, path, &arg, (void **) &response))
|
if (!HttpRouterRoute(data->router, path, &arg, (void **) &response))
|
||||||
{
|
{
|
||||||
|
Log(LOG_NOTICE, "Couldn't route %s", path);
|
||||||
HttpResponseStatus(ctx, HTTP_NOT_FOUND);
|
HttpResponseStatus(ctx, HTTP_NOT_FOUND);
|
||||||
JsonFree(response);
|
JsonFree(response);
|
||||||
response = NULL;
|
|
||||||
|
response = MatrixCreateError("M_NOT_FOUND", "Route not found.");
|
||||||
/* TODO: Set a thing */
|
/* TODO: Set a thing */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,3 +58,43 @@ ParseeRequest(HttpServerContext *ctx, void *argp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HttpClientContext *
|
||||||
|
ParseeCreateRequest(ParseeConfig *conf, HttpRequestMethod meth, char *path)
|
||||||
|
{
|
||||||
|
HttpClientContext *ctx;
|
||||||
|
if (!conf || !path)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = HttpRequest(
|
||||||
|
meth,
|
||||||
|
HTTP_FLAG_TLS,
|
||||||
|
conf->homeserver_port, conf->homeserver_host,
|
||||||
|
path
|
||||||
|
);
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
HttpStatus
|
||||||
|
ParseeSetRequestJSON(HttpClientContext *ctx, HashMap *json)
|
||||||
|
{
|
||||||
|
Stream *stream;
|
||||||
|
int size;
|
||||||
|
char *sizestr;
|
||||||
|
if (!ctx || !json)
|
||||||
|
{
|
||||||
|
return HTTP_STATUS_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = JsonEncode(json, NULL, JSON_DEFAULT);
|
||||||
|
sizestr = StrInt(size);
|
||||||
|
HttpRequestHeader(ctx, "Content-Length", sizestr);
|
||||||
|
Free(sizestr);
|
||||||
|
|
||||||
|
stream = HttpClientStream(ctx);
|
||||||
|
HttpRequestSendHeaders(ctx);
|
||||||
|
JsonEncode(json, stream, JSON_DEFAULT);
|
||||||
|
return HttpRequestSend(ctx);
|
||||||
|
}
|
||||||
|
|
|
||||||
27
src/Main.c
27
src/Main.c
|
|
@ -4,6 +4,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <Parsee.h>
|
#include <Parsee.h>
|
||||||
|
#include <AS.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
Main(void)
|
Main(void)
|
||||||
|
|
@ -12,12 +13,36 @@ Main(void)
|
||||||
HttpServerConfig conf;
|
HttpServerConfig conf;
|
||||||
ParseeData *data;
|
ParseeData *data;
|
||||||
const ParseeConfig *parseeConf;
|
const ParseeConfig *parseeConf;
|
||||||
|
Stream *yaml;
|
||||||
|
|
||||||
Log(LOG_INFO, "%s - v%s", NAME, VERSION);
|
Log(LOG_INFO, "%s - v%s", NAME, VERSION);
|
||||||
|
ParseeConfigLoad("parsee.json");
|
||||||
ParseeConfigInit();
|
ParseeConfigInit();
|
||||||
ParseeExportConfigYAML(StreamStdout());
|
|
||||||
|
yaml = StreamOpen("parsee.yaml", "w");
|
||||||
|
ParseeExportConfigYAML(yaml);
|
||||||
|
StreamClose(yaml);
|
||||||
|
|
||||||
parseeConf = ParseeConfigGet();
|
parseeConf = ParseeConfigGet();
|
||||||
|
Log(LOG_INFO, "HS token: %s", parseeConf->hs_token);
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Create user. We don't actually care about the value as we can
|
||||||
|
* masquerade, as long as it exists. */
|
||||||
|
HttpClientContext *ctx = ParseeCreateRequest(
|
||||||
|
parseeConf,
|
||||||
|
HTTP_POST, "/_matrix/client/v3/register"
|
||||||
|
);
|
||||||
|
HashMap *json = HashMapCreate();
|
||||||
|
|
||||||
|
HashMapSet(json,"type",JsonValueString("m.login.application_service"));
|
||||||
|
HashMapSet(json,"username",JsonValueString(parseeConf->sender_localpart));
|
||||||
|
|
||||||
|
ASAuthenticateRequest(parseeConf, ctx);
|
||||||
|
Log(LOG_INFO, "Got %d", ParseeSetRequestJSON(ctx, json));
|
||||||
|
HttpClientContextFree(ctx);
|
||||||
|
JsonFree(json);
|
||||||
|
}
|
||||||
|
|
||||||
memset(&conf, 0, sizeof(conf));
|
memset(&conf, 0, sizeof(conf));
|
||||||
conf.port = parseeConf->port;
|
conf.port = parseeConf->port;
|
||||||
|
|
|
||||||
17
src/MatrixError.c
Normal file
17
src/MatrixError.c
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#include <Matrix.h>
|
||||||
|
|
||||||
|
HashMap *
|
||||||
|
MatrixCreateError(char *err, char *msg)
|
||||||
|
{
|
||||||
|
HashMap *map;
|
||||||
|
if (!err || !msg)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
map = HashMapCreate();
|
||||||
|
HashMapSet(map, "errcode", JsonValueString(err));
|
||||||
|
HashMapSet(map, "error", JsonValueString(msg));
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <Parsee.h>
|
#include <Parsee.h>
|
||||||
|
|
||||||
#include <Cytoplasm/Memory.h>
|
#include <Cytoplasm/Memory.h>
|
||||||
|
#include <Cytoplasm/Json.h>
|
||||||
#include <Cytoplasm/Str.h>
|
#include <Cytoplasm/Str.h>
|
||||||
|
|
||||||
static ParseeConfig *config = NULL;
|
static ParseeConfig *config = NULL;
|
||||||
|
|
@ -8,6 +9,8 @@ static ParseeConfig *config = NULL;
|
||||||
void
|
void
|
||||||
ParseeConfigInit(void)
|
ParseeConfigInit(void)
|
||||||
{
|
{
|
||||||
|
Stream *stream;
|
||||||
|
HashMap *json;
|
||||||
if (config)
|
if (config)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
@ -19,6 +22,53 @@ ParseeConfigInit(void)
|
||||||
config->namespace_base = StrDuplicate("_parsee_j");
|
config->namespace_base = StrDuplicate("_parsee_j");
|
||||||
config->listen_as = StrDuplicate("localhost");
|
config->listen_as = StrDuplicate("localhost");
|
||||||
config->port = 7642; /* proposed by Saint */
|
config->port = 7642; /* proposed by Saint */
|
||||||
|
|
||||||
|
stream = StreamOpen("parsee.json", "w");
|
||||||
|
json = HashMapCreate();
|
||||||
|
HashMapSet(json, "as_token", JsonValueString(config->as_token));
|
||||||
|
HashMapSet(json, "hs_token", JsonValueString(config->hs_token));
|
||||||
|
|
||||||
|
HashMapSet(json, "sender", JsonValueString(config->sender_localpart));
|
||||||
|
HashMapSet(json, "namespace", JsonValueString(config->namespace_base));
|
||||||
|
HashMapSet(json, "listen_as", JsonValueString(config->listen_as));
|
||||||
|
HashMapSet(json, "port", JsonValueInteger(config->port));
|
||||||
|
|
||||||
|
JsonEncode(json, stream, JSON_PRETTY);
|
||||||
|
HashMapFree(json);
|
||||||
|
StreamClose(stream);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
ParseeConfigLoad(char *conf)
|
||||||
|
{
|
||||||
|
Stream *stream;
|
||||||
|
HashMap *json;
|
||||||
|
if (config)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stream = StreamOpen("parsee.json", "r");
|
||||||
|
json = JsonDecode(stream);
|
||||||
|
|
||||||
|
config = Malloc(sizeof(*config));
|
||||||
|
#define CopyToStr(to, str) config->to = StrDuplicate( \
|
||||||
|
JsonValueAsString(HashMapGet(json, str)) \
|
||||||
|
)
|
||||||
|
#define CopyToInt(to, str) config->to = (int) ( \
|
||||||
|
JsonValueAsInteger(HashMapGet(json, str)) \
|
||||||
|
)
|
||||||
|
|
||||||
|
CopyToStr(as_token, "as_token");
|
||||||
|
CopyToStr(hs_token, "hs_token");
|
||||||
|
CopyToStr(sender_localpart, "sender");
|
||||||
|
CopyToStr(namespace_base, "namespace");
|
||||||
|
CopyToStr(listen_as, "listen_as");
|
||||||
|
CopyToInt(port, "port");
|
||||||
|
|
||||||
|
CopyToStr(homeserver_host, "hs_host");
|
||||||
|
CopyToInt(homeserver_port, "hs_port");
|
||||||
|
|
||||||
|
JsonFree(json);
|
||||||
|
StreamClose(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <Parsee.h>
|
#include <Parsee.h>
|
||||||
|
|
||||||
#include <Cytoplasm/Memory.h>
|
#include <Cytoplasm/Memory.h>
|
||||||
|
#include <Cytoplasm/Log.h>
|
||||||
|
|
||||||
#include <Routes.h>
|
#include <Routes.h>
|
||||||
|
|
||||||
|
|
@ -17,7 +18,13 @@ ParseeInitData(void)
|
||||||
data->config = ParseeConfigGet();
|
data->config = ParseeConfigGet();
|
||||||
data->router = HttpRouterCreate();
|
data->router = HttpRouterCreate();
|
||||||
|
|
||||||
#define X_ROUTE(path, func) HttpRouterAdd(data->router, path, func);
|
#define X_ROUTE(path, func) do {\
|
||||||
|
if (!HttpRouterAdd(data->router, path, func))\
|
||||||
|
{\
|
||||||
|
Log(LOG_ERR, "Can't register %s", path);\
|
||||||
|
}\
|
||||||
|
}\
|
||||||
|
while (0);
|
||||||
ROUTES
|
ROUTES
|
||||||
#undef X_ROUTE
|
#undef X_ROUTE
|
||||||
return data;
|
return data;
|
||||||
|
|
|
||||||
52
src/Routes/Transactions.c
Normal file
52
src/Routes/Transactions.c
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
#include <Routes.h>
|
||||||
|
|
||||||
|
#include <Cytoplasm/Log.h>
|
||||||
|
|
||||||
|
#include <Matrix.h>
|
||||||
|
#include <AS.h>
|
||||||
|
|
||||||
|
RouteHead(RouteTxns, arr, argp)
|
||||||
|
{
|
||||||
|
ParseeHttpArg *args = argp;
|
||||||
|
HashMap *request = NULL;
|
||||||
|
HashMap *response = NULL;
|
||||||
|
Array *events;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
Log(LOG_INFO, "Caught one!");
|
||||||
|
response = ASVerifyRequest(args);
|
||||||
|
if (response)
|
||||||
|
{
|
||||||
|
Log(LOG_INFO, ":(");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (HttpRequestMethodGet(args->ctx) != HTTP_PUT)
|
||||||
|
{
|
||||||
|
HttpResponseStatus(args->ctx, HTTP_METHOD_NOT_ALLOWED);
|
||||||
|
response = MatrixCreateError(
|
||||||
|
"M_UNRECOGNIZED",
|
||||||
|
"Path /transactions only accepts PUT as a valid method."
|
||||||
|
);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(LOG_INFO, "Caught a decent one!");
|
||||||
|
RequestJSON();
|
||||||
|
|
||||||
|
/* TODO: Do a thing with these. */
|
||||||
|
events = JsonValueAsArray(HashMapGet(request, "events"));
|
||||||
|
for (i = 0; i < ArraySize(events); i++)
|
||||||
|
{
|
||||||
|
HashMap *event = JsonValueAsObject(ArrayGet(events, i));
|
||||||
|
Log(LOG_INFO, "Event by '%s', with type '%s'",
|
||||||
|
JsonValueAsString(HashMapGet(event, "sender")),
|
||||||
|
JsonValueAsString(HashMapGet(event, "type"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(LOG_INFO, "OK!");
|
||||||
|
response = HashMapCreate();
|
||||||
|
end:
|
||||||
|
JsonFree(request);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
18
src/include/AS.h
Normal file
18
src/include/AS.h
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef PARSEE_AS_H
|
||||||
|
#define PARSEE_AS_H
|
||||||
|
|
||||||
|
#include <Cytoplasm/HttpClient.h>
|
||||||
|
#include <Cytoplasm/Json.h>
|
||||||
|
|
||||||
|
#include <Parsee.h>
|
||||||
|
#include <Routes.h>
|
||||||
|
|
||||||
|
/* Verifies a request from the homeserver to match the
|
||||||
|
* hs_token. */
|
||||||
|
extern HashMap * ASVerifyRequest(ParseeHttpArg *);
|
||||||
|
|
||||||
|
/* Authenticates a request with the correct as_token.
|
||||||
|
* It does not send the request, however. */
|
||||||
|
extern void ASAuthenticateRequest(ParseeConfig *, HttpClientContext *);
|
||||||
|
|
||||||
|
#endif
|
||||||
8
src/include/Matrix.h
Normal file
8
src/include/Matrix.h
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef PARSEE_MATRIX_H
|
||||||
|
#define PARSEE_MATRIX_H
|
||||||
|
|
||||||
|
#include <Cytoplasm/Json.h>
|
||||||
|
|
||||||
|
/* Creates an error message JSON, with the specified code and message. */
|
||||||
|
extern HashMap * MatrixCreateError(char *err, char *msg);
|
||||||
|
#endif
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <Cytoplasm/HttpServer.h>
|
#include <Cytoplasm/HttpServer.h>
|
||||||
#include <Cytoplasm/HttpRouter.h>
|
#include <Cytoplasm/HttpRouter.h>
|
||||||
|
#include <Cytoplasm/HttpClient.h>
|
||||||
#include <Cytoplasm/Stream.h>
|
#include <Cytoplasm/Stream.h>
|
||||||
|
|
||||||
typedef struct ParseeConfig {
|
typedef struct ParseeConfig {
|
||||||
|
|
@ -13,6 +14,10 @@ typedef struct ParseeConfig {
|
||||||
|
|
||||||
char *listen_as;
|
char *listen_as;
|
||||||
int port;
|
int port;
|
||||||
|
|
||||||
|
/* Homeserver port info */
|
||||||
|
char *homeserver_host;
|
||||||
|
int homeserver_port;
|
||||||
} ParseeConfig;
|
} ParseeConfig;
|
||||||
|
|
||||||
typedef struct ParseeData {
|
typedef struct ParseeData {
|
||||||
|
|
@ -42,4 +47,9 @@ extern void ParseeFreeData(ParseeData *);
|
||||||
|
|
||||||
/* HTTP server handler for Parsee, takes in a config. */
|
/* HTTP server handler for Parsee, takes in a config. */
|
||||||
extern void ParseeRequest(HttpServerContext *, void *);
|
extern void ParseeRequest(HttpServerContext *, void *);
|
||||||
|
|
||||||
|
extern HttpClientContext * ParseeCreateRequest(ParseeConfig *, HttpRequestMethod, char *);
|
||||||
|
|
||||||
|
/* Sends headers, and writes the JSON object. */
|
||||||
|
extern HttpStatus ParseeSetRequestJSON(HttpClientContext *, HashMap *);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ typedef struct ParseeHttpArg {
|
||||||
} ParseeHttpArg;
|
} ParseeHttpArg;
|
||||||
|
|
||||||
/* A list of all routes. */
|
/* A list of all routes. */
|
||||||
#define ROUTES X_ROUTE("/", RouteRoot)
|
#define ROUTES X_ROUTE("/", RouteRoot) \
|
||||||
|
X_ROUTE("/_matrix/app/v1/transactions/(.*)", RouteTxns)
|
||||||
|
|
||||||
#define X_ROUTE(path, name) extern void * name(Array *, void *);
|
#define X_ROUTE(path, name) extern void * name(Array *, void *);
|
||||||
ROUTES
|
ROUTES
|
||||||
|
|
@ -17,4 +18,20 @@ typedef struct ParseeHttpArg {
|
||||||
|
|
||||||
#define RouteHead(name, pathargs, argp) void * \
|
#define RouteHead(name, pathargs, argp) void * \
|
||||||
name(Array * pathargs, void *argp)
|
name(Array * pathargs, void *argp)
|
||||||
|
#define RequestJSON() do \
|
||||||
|
{ \
|
||||||
|
Stream *s = args->stream;\
|
||||||
|
if (!(request = JsonDecode(s))) \
|
||||||
|
{ \
|
||||||
|
HttpResponseStatus( \
|
||||||
|
args->ctx, \
|
||||||
|
HTTP_BAD_REQUEST \
|
||||||
|
); \
|
||||||
|
response = MatrixCreateError(\
|
||||||
|
"M_NO_JSON", \
|
||||||
|
"Invalid JSON stream." \
|
||||||
|
); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue