forked from Telodendria/Telodendria
[ADD/WIP/UNTESTED] Start creating PDU for client events
Some checks failed
Compile Telodendria / Compile Telodendria (x86, alpine-v3.19) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86, debian-v12.4) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86, freebsd-v14.0) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86, netbsd-v9.3) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86_64, alpine-v3.19) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86_64, debian-v12.4) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86_64, freebsd-v14.0) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86_64, netbsd-v9.3) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86_64, openbsd-v7.4) (push) Has been cancelled
Some checks failed
Compile Telodendria / Compile Telodendria (x86, alpine-v3.19) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86, debian-v12.4) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86, freebsd-v14.0) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86, netbsd-v9.3) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86_64, alpine-v3.19) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86_64, debian-v12.4) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86_64, freebsd-v14.0) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86_64, netbsd-v9.3) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86_64, openbsd-v7.4) (push) Has been cancelled
This commit is contained in:
parent
d0a447a409
commit
001b4821fe
4 changed files with 312 additions and 0 deletions
14
.ycm_extra_conf.py
Normal file
14
.ycm_extra_conf.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import os
|
||||||
|
import ycm_core
|
||||||
|
|
||||||
|
def Settings( **kwargs ):
|
||||||
|
return {
|
||||||
|
'flags': [
|
||||||
|
"-xc",
|
||||||
|
"-I", "src/include",
|
||||||
|
"-I", "Cytoplasm/include",
|
||||||
|
"-I", "build",
|
||||||
|
|
||||||
|
"-std=c99"
|
||||||
|
]
|
||||||
|
}
|
|
@ -22,11 +22,16 @@
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
#include "Cytoplasm/Io.h"
|
||||||
|
#include "Cytoplasm/Stream.h"
|
||||||
#include <CanonicalJson.h>
|
#include <CanonicalJson.h>
|
||||||
|
|
||||||
#include <Cytoplasm/HashMap.h>
|
#include <Cytoplasm/HashMap.h>
|
||||||
|
#include <Cytoplasm/Memory.h>
|
||||||
#include <Cytoplasm/Array.h>
|
#include <Cytoplasm/Array.h>
|
||||||
#include <Cytoplasm/Json.h>
|
#include <Cytoplasm/Json.h>
|
||||||
|
#include <Cytoplasm/Str.h>
|
||||||
|
#include <Cytoplasm/Sha.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -159,3 +164,51 @@ CanonicalJsonEncode(HashMap * object, Stream * out)
|
||||||
ArrayFree(keys);
|
ArrayFree(keys);
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
StringIoRead(void *cookie, void *buf, size_t count)
|
||||||
|
{
|
||||||
|
return -1; /* TODO: Consider reading properly */
|
||||||
|
}
|
||||||
|
static ssize_t
|
||||||
|
StringIoWrite(void *c, void *buf, size_t count)
|
||||||
|
{
|
||||||
|
char **str = c;
|
||||||
|
char *stringised = Malloc(count + 1);
|
||||||
|
char *new;
|
||||||
|
memcpy(stringised, buf, count);
|
||||||
|
new = StrConcat(2, *str, stringised);
|
||||||
|
|
||||||
|
Free(stringised);
|
||||||
|
if (*str)
|
||||||
|
{
|
||||||
|
Free(*str);
|
||||||
|
}
|
||||||
|
*str = new;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
static const IoFunctions Functions = {
|
||||||
|
.read = StringIoRead,
|
||||||
|
.write = StringIoWrite,
|
||||||
|
.close = NULL,
|
||||||
|
.seek = NULL
|
||||||
|
};
|
||||||
|
char *
|
||||||
|
CanonicalJsonHash(HashMap *json)
|
||||||
|
{
|
||||||
|
char *string = NULL;
|
||||||
|
unsigned char *sha;
|
||||||
|
char *shastr;
|
||||||
|
Io *string_writer = IoCreate(&string, Functions);
|
||||||
|
Stream *io_stream = StreamIo(string_writer);
|
||||||
|
CanonicalJsonEncode(json, io_stream);
|
||||||
|
|
||||||
|
sha = Sha256(string);
|
||||||
|
shastr = ShaToHex(sha);
|
||||||
|
|
||||||
|
Free(string);
|
||||||
|
Free(sha);
|
||||||
|
StreamClose(io_stream);
|
||||||
|
|
||||||
|
return shastr;
|
||||||
|
}
|
||||||
|
|
235
src/Room.c
235
src/Room.c
|
@ -23,13 +23,23 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "Cytoplasm/Json.h"
|
||||||
|
#include "Cytoplasm/Stream.h"
|
||||||
|
#include "Parser.h"
|
||||||
#include <Room.h>
|
#include <Room.h>
|
||||||
|
|
||||||
#include <Cytoplasm/Memory.h>
|
#include <Cytoplasm/Memory.h>
|
||||||
|
#include <Cytoplasm/Util.h>
|
||||||
#include <Cytoplasm/Str.h>
|
#include <Cytoplasm/Str.h>
|
||||||
#include <Cytoplasm/Db.h>
|
#include <Cytoplasm/Db.h>
|
||||||
|
|
||||||
#include <Schema/RoomCreateRequest.h>
|
#include <Schema/RoomCreateRequest.h>
|
||||||
|
#include <Schema/PduV1.h>
|
||||||
|
#include <Schema/PduV3.h>
|
||||||
|
|
||||||
|
#include <CanonicalJson.h>
|
||||||
|
#include <Parser.h>
|
||||||
|
#include <State.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
@ -155,3 +165,228 @@ RoomStateGet(Room * room)
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
PopulateEventV1(Room * room, HashMap * event, PduV1 * pdu)
|
||||||
|
{
|
||||||
|
char *unused;
|
||||||
|
if (PduV1FromJson(event, pdu, &unused))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Create a PDU of our own, signed and everything.
|
||||||
|
* https://telodendria.io/blog/matrix-protocol-overview
|
||||||
|
* has some ideas on how this could be done(up until stage 5). */
|
||||||
|
pdu->sender =
|
||||||
|
StrDuplicate(JsonValueAsString(JsonGet(event, 1, "sender")));
|
||||||
|
pdu->auth_events = ArrayCreate();
|
||||||
|
pdu->origin_server_ts = UtilTsMillis();
|
||||||
|
pdu->content = JsonDuplicate(event); /* Copy the original JSON data */
|
||||||
|
|
||||||
|
/* TODO: Signature and alldat. */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
static bool
|
||||||
|
PopulateEventV3(Room * room, HashMap * event, PduV3 *pdu)
|
||||||
|
{
|
||||||
|
char *unused;
|
||||||
|
if (PduV3FromJson(event, pdu, &unused))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Create a PDU of our own, signed and everything.
|
||||||
|
* https://telodendria.io/blog/matrix-protocol-overview
|
||||||
|
* has some ideas on how this could be done(up until stage 5). */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
static AuthoriseCreateV1(PduV1 pdu)
|
||||||
|
{
|
||||||
|
bool ret = true;
|
||||||
|
CommonID sender = { 0 }, room_id = { 0 };
|
||||||
|
char *sender_serv = NULL, *id_serv = NULL;
|
||||||
|
|
||||||
|
if (ArraySize(pdu.auth_events) > 0)
|
||||||
|
{
|
||||||
|
ret = false;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
if (!ParseCommonID(pdu.room_id, &room_id) ||
|
||||||
|
!ParseCommonID(pdu.sender, &sender))
|
||||||
|
{
|
||||||
|
ret = false;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
sender_serv = ParserRecomposeServerPart(sender.server);
|
||||||
|
id_serv = ParserRecomposeServerPart(room_id.server);
|
||||||
|
if (!StrEquals(sender_serv, id_serv))
|
||||||
|
{
|
||||||
|
ret = false;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
/* TODO: Check room_version as in step 1.3 */
|
||||||
|
if (!HashMapGet(pdu.content, "creator"))
|
||||||
|
{
|
||||||
|
ret = false;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
finish:
|
||||||
|
if (sender_serv)
|
||||||
|
{
|
||||||
|
Free(sender_serv);
|
||||||
|
}
|
||||||
|
if (id_serv)
|
||||||
|
{
|
||||||
|
Free(id_serv);
|
||||||
|
}
|
||||||
|
CommonIDFree(sender);
|
||||||
|
CommonIDFree(room_id);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
static bool
|
||||||
|
AuthoriseEventV1(PduV1 pdu)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
if (StrEquals(pdu.type, "m.room.create"))
|
||||||
|
{
|
||||||
|
return AuthoriseCreateV1(pdu);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Consider, everything else! */
|
||||||
|
for (i = 0; i < ArraySize(pdu.auth_events); i++)
|
||||||
|
{
|
||||||
|
char *event_id = ArrayGet(pdu.auth_events, i);
|
||||||
|
/* TODO: Fetch event there */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static char *
|
||||||
|
RoomHashEvent(HashMap * pdu_json)
|
||||||
|
{
|
||||||
|
HashMap * copy = JsonDuplicate(pdu_json);
|
||||||
|
char *hash;
|
||||||
|
JsonValueFree(HashMapDelete(copy, "unsigned"));
|
||||||
|
JsonValueFree(HashMapDelete(copy, "signatures"));
|
||||||
|
JsonValueFree(HashMapDelete(copy, "hashes"));
|
||||||
|
|
||||||
|
hash = CanonicalJsonHash(copy);
|
||||||
|
JsonFree(copy);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
static char *
|
||||||
|
RoomHashEventV1(PduV1 pdu)
|
||||||
|
{
|
||||||
|
HashMap *json = PduV1ToJson(&pdu);
|
||||||
|
char *sha = RoomHashEvent(json);
|
||||||
|
|
||||||
|
JsonFree(json);
|
||||||
|
return sha;
|
||||||
|
}
|
||||||
|
static HashMap *
|
||||||
|
RoomEventSendV1(Room * room, HashMap * event)
|
||||||
|
{
|
||||||
|
PduV1 pdu = { 0 };
|
||||||
|
HashMap *pdu_object = NULL;
|
||||||
|
bool client_event;
|
||||||
|
HashMap *state = NULL;
|
||||||
|
|
||||||
|
client_event = PopulateEventV1(room, event, &pdu);
|
||||||
|
pdu_object = PduV1ToJson(&pdu);
|
||||||
|
|
||||||
|
state = StateResolve(room, pdu_object); /* Compute the state
|
||||||
|
* at that point for later. */
|
||||||
|
if (client_event)
|
||||||
|
{
|
||||||
|
char *event_id;
|
||||||
|
#define AddState(type, key) do \
|
||||||
|
{ \
|
||||||
|
event_id = StateGet(state, type, key); \
|
||||||
|
if (event_id) \
|
||||||
|
{ \
|
||||||
|
char *dup = StrDuplicate(event_id); \
|
||||||
|
ArrayAdd(pdu.auth_events, dup); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implemented from
|
||||||
|
* https://spec.matrix.org/v1.7/server-server-api/
|
||||||
|
* #auth-events-selection */
|
||||||
|
AddState("m.room.create", "");
|
||||||
|
AddState("m.room.power_levels", "");
|
||||||
|
AddState("m.room.member", pdu.sender);
|
||||||
|
if (StrEquals(pdu.type, "m.room.member"))
|
||||||
|
{
|
||||||
|
char *target = pdu.state_key;
|
||||||
|
char *membership =
|
||||||
|
JsonValueAsString(JsonGet(pdu.content, 1, "membership"));
|
||||||
|
char *auth_via =
|
||||||
|
JsonValueAsString(
|
||||||
|
JsonGet(
|
||||||
|
pdu.content, 1, "join_authorised_via_users_server")
|
||||||
|
);
|
||||||
|
HashMap *inv =
|
||||||
|
JsonValueAsObject(
|
||||||
|
JsonGet(pdu.content, 1, "third_party_invite"));
|
||||||
|
|
||||||
|
if (target && !StrEquals(target, pdu.sender))
|
||||||
|
{
|
||||||
|
AddState("m.room.member", target);
|
||||||
|
}
|
||||||
|
if (StrEquals(membership, "join") ||
|
||||||
|
StrEquals(membership, "invite"))
|
||||||
|
{
|
||||||
|
AddState("m.room.join_rules", "");
|
||||||
|
}
|
||||||
|
if (StrEquals(membership, "invite") && inv)
|
||||||
|
{
|
||||||
|
char *token =
|
||||||
|
JsonValueAsString(JsonGet(inv, 2, "signed", "token"));
|
||||||
|
AddState("m.room.third_party_invite", token);
|
||||||
|
}
|
||||||
|
if (auth_via && room->version >= 8)
|
||||||
|
{
|
||||||
|
AddState("m.room.member", auth_via);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pdu.hashes.sha256 = RoomHashEventV1(pdu);
|
||||||
|
#undef AddState
|
||||||
|
}
|
||||||
|
/* TODO: Do a size check! */
|
||||||
|
finish:
|
||||||
|
if (state)
|
||||||
|
{
|
||||||
|
JsonFree(state);
|
||||||
|
}
|
||||||
|
if (pdu_object)
|
||||||
|
{
|
||||||
|
JsonFree(pdu_object);
|
||||||
|
}
|
||||||
|
PduV1Free(&pdu);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
static HashMap *
|
||||||
|
RoomEventSendV3(Room * room, HashMap * event)
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
HashMap *
|
||||||
|
RoomEventSend(Room * room, HashMap * event)
|
||||||
|
{
|
||||||
|
if (!room || !event)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (room->version == 1)
|
||||||
|
{
|
||||||
|
/* Manage with PDUv1 */
|
||||||
|
return RoomEventSendV1(room, event);
|
||||||
|
}
|
||||||
|
/* Manage with PDUv3 otherwise */
|
||||||
|
return RoomEventSendV3(room, event);
|
||||||
|
}
|
||||||
|
|
|
@ -79,6 +79,16 @@
|
||||||
*/
|
*/
|
||||||
extern int CanonicalJsonEncode(HashMap *, Stream *);
|
extern int CanonicalJsonEncode(HashMap *, Stream *);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes a JSON object encoded as Canonical JSON's SHA-256
|
||||||
|
* hash.
|
||||||
|
*
|
||||||
|
* This function returns a SHA-256 string stored on the heap,
|
||||||
|
* which will need to be freed with
|
||||||
|
* .Fn Free .
|
||||||
|
*/
|
||||||
|
extern char * CanonicalJsonHash(HashMap *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode a JSON value following the rules of Canonical JSON.
|
* Encode a JSON value following the rules of Canonical JSON.
|
||||||
* See the documentation for
|
* See the documentation for
|
||||||
|
|
Loading…
Reference in a new issue