forked from lda/telodendria
Implement /_matrix/client/versions and /.well-known/matrix/client
This commit is contained in:
parent
13fa07bfcc
commit
45324ce77a
13 changed files with 305 additions and 20 deletions
10
TODO.txt
10
TODO.txt
|
@ -55,11 +55,13 @@ Phase 2: Building a foundation
|
|||
|
||||
Phase 3: Welcome to Matrix
|
||||
|
||||
[ ] client-Server API
|
||||
[~] client-Server API
|
||||
[x] Error responses
|
||||
[x] CORS headers
|
||||
[ ] /_matrix/client/versions
|
||||
[ ] Well-known URIs
|
||||
[x] /_matrix/client/versions
|
||||
[x] Well-known URIs
|
||||
[x] Make base-url optional in config
|
||||
[x] Make identity-server optional in config
|
||||
[ ] Client authentication
|
||||
[ ] Capabilities negotiation
|
||||
[ ] Server-Server API
|
||||
|
@ -88,7 +90,7 @@ Documentation
|
|||
[x] Make a note in Getting the Code that the password for the anoncvs account is just anoncvs
|
||||
[x] Add contributors list
|
||||
[x] Add list of make.sh recipes and what they do
|
||||
[ ] Improve Google Lighthouse score on website
|
||||
[x] Improve Google Lighthouse score on website
|
||||
[!] Image elements do not have explicit width and height
|
||||
[x] Background and foreground colors do not have sufficient contrast ratio (msg-error div)
|
||||
[x] Lists do not contain only <li> elements
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#
|
||||
|
||||
server-name "localhost";
|
||||
base-url "http://localhost:8008";
|
||||
chroot "./chroot";
|
||||
id "jordan";
|
||||
data-dir "./data";
|
||||
|
|
|
@ -10,7 +10,11 @@
|
|||
#
|
||||
|
||||
listen "8008";
|
||||
|
||||
server-name "example.com";
|
||||
base-url "https://matrix.example.com";
|
||||
identity-server "https://identity.example.com";
|
||||
|
||||
chroot "/var/telodendria";
|
||||
id "_telodendria" "_telodendria";
|
||||
data-dir "./data";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.Dd $Mdocdate: September 23 2022 $
|
||||
.Dd $Mdocdate: September 29 2022 $
|
||||
.Dt TELODENDRIA.CONF 5
|
||||
.Os Telodendria Project
|
||||
.Sh NAME
|
||||
|
@ -55,6 +55,29 @@ over.
|
|||
.Ar name
|
||||
should be a DNS name that can be publically resolved. This directive
|
||||
is required.
|
||||
.It Ic base-url Ar url
|
||||
Set the server's base URL.
|
||||
.Ar url
|
||||
should be a valid URL, complete with the protocol. It does not need to
|
||||
be the same as the server name; in fact, it is common for a subdomain of
|
||||
the server name to be the base URL for the Matrix homeserver.
|
||||
.Pp
|
||||
This URL is the URL at which Matrix clients will connect to the server,
|
||||
and is thus served as a part of the
|
||||
.Pa .well-known
|
||||
manifest.
|
||||
.Pp
|
||||
This directive is optional. If it is not specified, it is automatically
|
||||
deduced from the server name.
|
||||
.It Ic identity-server Ar url
|
||||
The identity server that clients should use to perform identity lookups.
|
||||
.Pp
|
||||
.Ar url
|
||||
follows the same rules as
|
||||
.Ic base-url .
|
||||
.Pp
|
||||
This directive is optional. If it is not specified, it is automatically
|
||||
set to be the same as the base URL.
|
||||
.It Ic chroot Ar directory
|
||||
Change the root directory to the specified directory as soon as possible.
|
||||
Note that all other paths and files specified in
|
||||
|
|
|
@ -78,7 +78,7 @@ ArrayDelete(Array * array, size_t index)
|
|||
size_t i;
|
||||
void *element;
|
||||
|
||||
if (!array)
|
||||
if (!array || array->size <= index)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
28
src/Matrix.c
28
src/Matrix.c
|
@ -31,6 +31,8 @@
|
|||
#include <Json.h>
|
||||
#include <Util.h>
|
||||
|
||||
#include <Routes.h>
|
||||
|
||||
void
|
||||
MatrixHttpHandler(HttpServerContext * context, void *argp)
|
||||
{
|
||||
|
@ -99,15 +101,39 @@ MatrixHttpHandler(HttpServerContext * context, void *argp)
|
|||
ArrayAdd(pathParts, decoded);
|
||||
}
|
||||
|
||||
/* TODO: Route requests here */
|
||||
pathPart = MATRIX_PATH_POP(pathParts);
|
||||
|
||||
if (MATRIX_PATH_EQUALS(pathPart, ".well-known"))
|
||||
{
|
||||
response = RouteWellKnown(args, context, pathParts);
|
||||
}
|
||||
else if (MATRIX_PATH_EQUALS(pathPart, "_matrix"))
|
||||
{
|
||||
response = RouteMatrix(args, context, pathParts);
|
||||
}
|
||||
else
|
||||
{
|
||||
HttpResponseStatus(context, HTTP_NOT_FOUND);
|
||||
response = MatrixErrorCreate(M_NOT_FOUND);
|
||||
}
|
||||
|
||||
free(pathPart);
|
||||
|
||||
HttpSendHeaders(context);
|
||||
stream = HttpStream(context);
|
||||
|
||||
if (!response)
|
||||
{
|
||||
Log(lc, LOG_WARNING, "A route handler returned NULL.");
|
||||
HttpResponseStatus(context, HTTP_INTERNAL_SERVER_ERROR);
|
||||
response = MatrixErrorCreate(M_UNKNOWN);
|
||||
}
|
||||
|
||||
JsonEncode(response, stream);
|
||||
fprintf(stream, "\n");
|
||||
|
||||
/* By this point, ArraySize(pathParts) should be 0, but just in
|
||||
* case some elements remain, free them up now */
|
||||
for (i = 0; i < ArraySize(pathParts); i++)
|
||||
{
|
||||
free(ArrayGet(pathParts, i));
|
||||
|
|
68
src/Routes/RouteMatrix.c
Normal file
68
src/Routes/RouteMatrix.c
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (C) 2022 Jordan Bancino <@jordan:bancino.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include <Routes.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <Json.h>
|
||||
#include <HashMap.h>
|
||||
|
||||
ROUTE(RouteMatrix)
|
||||
{
|
||||
HashMap *response = NULL;
|
||||
char *pathPart = MATRIX_PATH_POP(path);
|
||||
|
||||
(void) args;
|
||||
|
||||
if (!MATRIX_PATH_EQUALS(pathPart, "client") || ArraySize(path) != 1)
|
||||
{
|
||||
free(pathPart);
|
||||
HttpResponseStatus(context, HTTP_NOT_FOUND);
|
||||
return MatrixErrorCreate(M_NOT_FOUND);
|
||||
}
|
||||
|
||||
free(pathPart);
|
||||
pathPart = MATRIX_PATH_POP(path);
|
||||
|
||||
if (MATRIX_PATH_EQUALS(pathPart, "versions"))
|
||||
{
|
||||
Array *versions = ArrayCreate();
|
||||
|
||||
free(pathPart);
|
||||
|
||||
ArrayAdd(versions, JsonValueString(UtilStringDuplicate("v1.4")));
|
||||
|
||||
response = HashMapCreate();
|
||||
HashMapSet(response, "versions", JsonValueArray(versions));
|
||||
|
||||
return response;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(pathPart);
|
||||
HttpResponseStatus(context, HTTP_NOT_FOUND);
|
||||
return MatrixErrorCreate(M_NOT_FOUND);
|
||||
}
|
||||
}
|
74
src/Routes/RouteWellKnown.c
Normal file
74
src/Routes/RouteWellKnown.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (C) 2022 Jordan Bancino <@jordan:bancino.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include <Routes.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <Json.h>
|
||||
#include <HashMap.h>
|
||||
|
||||
ROUTE(RouteWellKnown)
|
||||
{
|
||||
HashMap *response = NULL;
|
||||
char *pathPart = MATRIX_PATH_POP(path);
|
||||
|
||||
if (!MATRIX_PATH_EQUALS(pathPart, "matrix") || ArraySize(path) != 1)
|
||||
{
|
||||
free(pathPart);
|
||||
HttpResponseStatus(context, HTTP_NOT_FOUND);
|
||||
return MatrixErrorCreate(M_NOT_FOUND);
|
||||
}
|
||||
|
||||
free(pathPart);
|
||||
pathPart = MATRIX_PATH_POP(path);
|
||||
|
||||
if (MATRIX_PATH_EQUALS(pathPart, "client"))
|
||||
{
|
||||
HashMap *homeserver = HashMapCreate();
|
||||
|
||||
free(pathPart);
|
||||
|
||||
response = HashMapCreate();
|
||||
|
||||
HashMapSet(homeserver, "base_url", JsonValueString(UtilStringDuplicate(args->config->baseUrl)));
|
||||
HashMapSet(response, "m.homeserver", JsonValueObject(homeserver));
|
||||
|
||||
if (args->config->identityServer)
|
||||
{
|
||||
HashMap *identityServer = HashMapCreate();
|
||||
|
||||
HashMapSet(identityServer, "base_url", JsonValueString(UtilStringDuplicate(args->config->identityServer)));
|
||||
HashMapSet(response, "m.identity_server", identityServer);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(pathPart);
|
||||
HttpResponseStatus(context, HTTP_NOT_FOUND);
|
||||
return MatrixErrorCreate(M_NOT_FOUND);
|
||||
}
|
||||
}
|
|
@ -104,7 +104,7 @@ main(int argc, char **argv)
|
|||
/* Signal handling */
|
||||
struct sigaction sigAction;
|
||||
|
||||
MatrixHttpHandlerArgs *matrixArgs;
|
||||
MatrixHttpHandlerArgs matrixArgs;
|
||||
|
||||
lc = LogConfigCreate();
|
||||
|
||||
|
@ -250,6 +250,8 @@ main(int argc, char **argv)
|
|||
LogConfigIndent(lc);
|
||||
Log(lc, LOG_DEBUG, "Listen On: %d", tConfig->listenPort);
|
||||
Log(lc, LOG_DEBUG, "Server Name: %s", tConfig->serverName);
|
||||
Log(lc, LOG_DEBUG, "Base URL: %s", tConfig->baseUrl);
|
||||
Log(lc, LOG_DEBUG, "Identity Server: %s", tConfig->identityServer);
|
||||
Log(lc, LOG_DEBUG, "Chroot: %s", tConfig->chroot);
|
||||
Log(lc, LOG_DEBUG, "Run As: %s:%s", tConfig->uid, tConfig->gid);
|
||||
Log(lc, LOG_DEBUG, "Data Directory: %s", tConfig->dataDir);
|
||||
|
@ -284,19 +286,13 @@ main(int argc, char **argv)
|
|||
Log(lc, LOG_DEBUG, "Found user/group information using getpwnam() and getgrnam().");
|
||||
}
|
||||
|
||||
matrixArgs = malloc(sizeof(MatrixHttpHandlerArgs));
|
||||
if (!matrixArgs)
|
||||
{
|
||||
Log(lc, LOG_ERROR, "Unable to allocate memory for HTTP handler arguments.");
|
||||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
matrixArgs->lc = lc;
|
||||
/* Arguments to pass into the HTTP handler */
|
||||
matrixArgs.lc = lc;
|
||||
matrixArgs.config = tConfig;
|
||||
|
||||
/* Bind the socket before possibly dropping permissions */
|
||||
httpServer = HttpServerCreate(tConfig->listenPort, tConfig->threads, tConfig->maxConnections,
|
||||
MatrixHttpHandler, matrixArgs);
|
||||
MatrixHttpHandler, &matrixArgs);
|
||||
if (!httpServer)
|
||||
{
|
||||
Log(lc, LOG_ERROR, "Unable to create HTTP server on port %d: %s",
|
||||
|
|
|
@ -116,6 +116,45 @@ TelodendriaConfigParse(HashMap * config, LogConfig * lc)
|
|||
ASSERT_VALUES("server-name", 1);
|
||||
COPY_VALUE(tConfig->serverName, 0);
|
||||
|
||||
directive = (ConfigDirective *) HashMapGet(config, "base-url");
|
||||
children = ConfigChildrenGet(directive);
|
||||
value = ConfigValuesGet(directive);
|
||||
|
||||
if (directive)
|
||||
{
|
||||
ASSERT_NO_CHILDREN("base-url");
|
||||
ASSERT_VALUES("base-url", 1);
|
||||
COPY_VALUE(tConfig->baseUrl, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lc, LOG_WARNING, "Base URL not specified. Assuming it's 'https://%s'.", tConfig->serverName);
|
||||
tConfig->baseUrl = malloc(strlen(tConfig->serverName) + 10);
|
||||
if (!tConfig->baseUrl)
|
||||
{
|
||||
Log(lc, LOG_ERROR, "Error allocating memory for default config value 'base-url'.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
sprintf(tConfig->baseUrl, "https://%s", tConfig->serverName);
|
||||
}
|
||||
|
||||
directive = (ConfigDirective *) HashMapGet(config, "identity-server");
|
||||
children = ConfigChildrenGet(directive);
|
||||
value = ConfigValuesGet(directive);
|
||||
|
||||
if (directive)
|
||||
{
|
||||
ASSERT_NO_CHILDREN("identity-server");
|
||||
ASSERT_VALUES("identity-server", 1);
|
||||
COPY_VALUE(tConfig->identityServer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lc, LOG_WARNING, "Identity server not specified. No identity server will be advertised.");
|
||||
tConfig->identityServer = NULL;
|
||||
}
|
||||
|
||||
GET_DIRECTIVE("chroot");
|
||||
ASSERT_NO_CHILDREN("chroot");
|
||||
ASSERT_VALUES("chroot", 1);
|
||||
|
@ -138,7 +177,7 @@ TelodendriaConfigParse(HashMap * config, LogConfig * lc)
|
|||
Log(lc, LOG_ERROR,
|
||||
"Wrong value count in directive 'id': got '%d', but expected 1 or 2.",
|
||||
ArraySize(value));
|
||||
break;
|
||||
goto error;
|
||||
}
|
||||
|
||||
GET_DIRECTIVE("data-dir");
|
||||
|
@ -348,6 +387,9 @@ TelodendriaConfigFree(TelodendriaConfig * tConfig)
|
|||
}
|
||||
|
||||
free(tConfig->serverName);
|
||||
free(tConfig->baseUrl);
|
||||
free(tConfig->identityServer);
|
||||
|
||||
free(tConfig->chroot);
|
||||
free(tConfig->uid);
|
||||
free(tConfig->gid);
|
||||
|
|
|
@ -28,6 +28,12 @@
|
|||
#include <Log.h>
|
||||
#include <HashMap.h>
|
||||
|
||||
#include <TelodendriaConfig.h>
|
||||
|
||||
#define MATRIX_PATH_POP(arr) ArrayDelete(arr, 0)
|
||||
|
||||
#define MATRIX_PATH_EQUALS(pathPart, str) ((pathPart != NULL) && (strcmp(pathPart, str) == 0))
|
||||
|
||||
typedef enum MatrixError
|
||||
{
|
||||
M_FORBIDDEN,
|
||||
|
@ -72,6 +78,7 @@ typedef enum MatrixError
|
|||
typedef struct MatrixHttpHandlerArgs
|
||||
{
|
||||
LogConfig *lc;
|
||||
TelodendriaConfig *config;
|
||||
} MatrixHttpHandlerArgs;
|
||||
|
||||
extern void
|
||||
|
|
39
src/include/Routes.h
Normal file
39
src/include/Routes.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (C) 2022 Jordan Bancino <@jordan:bancino.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#ifndef TELODENDRIA_ROUTES_H
|
||||
#define TELODENDRIA_ROUTES_H
|
||||
|
||||
#include <HashMap.h>
|
||||
#include <Array.h>
|
||||
#include <HttpServer.h>
|
||||
#include <Util.h>
|
||||
|
||||
#include <Matrix.h>
|
||||
|
||||
#define ROUTE(name) HashMap * name(MatrixHttpHandlerArgs *args, HttpServerContext *context, Array *path)
|
||||
|
||||
extern ROUTE(RouteWellKnown);
|
||||
extern ROUTE(RouteMatrix);
|
||||
|
||||
#endif
|
|
@ -53,6 +53,9 @@ typedef enum TelodendriaConfigFlag
|
|||
typedef struct TelodendriaConfig
|
||||
{
|
||||
char *serverName;
|
||||
char *baseUrl;
|
||||
char *identityServer;
|
||||
|
||||
char *chroot;
|
||||
char *uid;
|
||||
char *gid;
|
||||
|
|
Loading…
Reference in a new issue