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
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include "Cytoplasm/Io.h"
|
||||
#include "Cytoplasm/Stream.h"
|
||||
#include <CanonicalJson.h>
|
||||
|
||||
#include <Cytoplasm/HashMap.h>
|
||||
#include <Cytoplasm/Memory.h>
|
||||
#include <Cytoplasm/Array.h>
|
||||
#include <Cytoplasm/Json.h>
|
||||
#include <Cytoplasm/Str.h>
|
||||
#include <Cytoplasm/Sha.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -159,3 +164,51 @@ CanonicalJsonEncode(HashMap * object, Stream * out)
|
|||
ArrayFree(keys);
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "Cytoplasm/Json.h"
|
||||
#include "Cytoplasm/Stream.h"
|
||||
#include "Parser.h"
|
||||
#include <Room.h>
|
||||
|
||||
#include <Cytoplasm/Memory.h>
|
||||
#include <Cytoplasm/Util.h>
|
||||
#include <Cytoplasm/Str.h>
|
||||
#include <Cytoplasm/Db.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>
|
||||
|
||||
|
@ -155,3 +165,228 @@ RoomStateGet(Room * room)
|
|||
|
||||
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 *);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* See the documentation for
|
||||
|
|
Loading…
Reference in a new issue