forked from Telodendria/Telodendria
Compare commits
3 commits
15b884b04a
...
e36f4357ab
Author | SHA1 | Date | |
---|---|---|---|
e36f4357ab | |||
1753c2188b | |||
9ffa37d7a7 |
7 changed files with 429 additions and 67 deletions
|
@ -51,7 +51,8 @@
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
"redacts": {
|
"redacts": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
|
"required": false
|
||||||
},
|
},
|
||||||
"room_id": {
|
"room_id": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|
|
@ -118,7 +118,10 @@ CanonicalJsonEncode(HashMap * object, Stream * out)
|
||||||
ArrayAdd(keys, key);
|
ArrayAdd(keys, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArraySort(keys, CanonicalJsonKeyCompare);
|
if (ArraySize(keys) != 0)
|
||||||
|
{
|
||||||
|
ArraySort(keys, CanonicalJsonKeyCompare);
|
||||||
|
}
|
||||||
|
|
||||||
/* The total number of bytes written */
|
/* The total number of bytes written */
|
||||||
length = 0;
|
length = 0;
|
||||||
|
|
|
@ -487,7 +487,7 @@ ParserRecomposeCommonID(CommonID id)
|
||||||
if (id.server.hostname)
|
if (id.server.hostname)
|
||||||
{
|
{
|
||||||
char *server = ParserRecomposeServerPart(id.server);
|
char *server = ParserRecomposeServerPart(id.server);
|
||||||
char *tmp = StrConcat(4, "@", ret, ":", server);
|
char *tmp = StrConcat(3, ret, ":", server);
|
||||||
Free(ret);
|
Free(ret);
|
||||||
Free(server);
|
Free(server);
|
||||||
|
|
||||||
|
|
381
src/Room.c
381
src/Room.c
|
@ -52,26 +52,39 @@
|
||||||
struct Room
|
struct Room
|
||||||
{
|
{
|
||||||
Db *db;
|
Db *db;
|
||||||
DbRef *ref;
|
|
||||||
|
DbRef *state_ref;
|
||||||
|
DbRef *leaves_ref; /* Reference to the leaf list */
|
||||||
|
|
||||||
|
ServerPart creator;
|
||||||
|
|
||||||
char *id;
|
char *id;
|
||||||
int version;
|
int version;
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
GenerateRoomId(void)
|
GenerateRoomId(ServerPart s)
|
||||||
{
|
{
|
||||||
return StrRandom(32); /* TODO: Add extra room info somehow
|
CommonID cid;
|
||||||
* (I don't feel like theres really a way to
|
char *string;
|
||||||
* get the server info where we're doing that.) */
|
|
||||||
|
cid.sigil = '!';
|
||||||
|
cid.local = StrRandom(32);
|
||||||
|
cid.server = s;
|
||||||
|
string = ParserRecomposeCommonID(cid);
|
||||||
|
Free(cid.local);
|
||||||
|
|
||||||
|
|
||||||
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
Room *
|
Room *
|
||||||
RoomCreate(Db * db, User *user, RoomCreateRequest * req)
|
RoomCreate(Db * db, User *user, RoomCreateRequest * req, ServerPart s)
|
||||||
{
|
{
|
||||||
Room *room;
|
Room *room;
|
||||||
char *version_string;
|
char *version_string, *full_creator;
|
||||||
int version_num = 1;
|
int version_num = 1;
|
||||||
|
HashMap *json;
|
||||||
if (!db || !req || !user)
|
if (!db || !req || !user)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -87,19 +100,79 @@ RoomCreate(Db * db, User *user, RoomCreateRequest * req)
|
||||||
}
|
}
|
||||||
room = Malloc(sizeof(Room));
|
room = Malloc(sizeof(Room));
|
||||||
room->db = db;
|
room->db = db;
|
||||||
room->id = GenerateRoomId(); /* TODO: Check config. */
|
room->creator.hostname = s.hostname ? StrDuplicate(s.hostname) : NULL;
|
||||||
|
room->creator.port = s.port ? StrDuplicate(s.port) : NULL;
|
||||||
|
room->id = GenerateRoomId(s);
|
||||||
room->version = version_num;
|
room->version = version_num;
|
||||||
|
|
||||||
room->ref = DbCreate(db, 3, "rooms", room->id, "state");
|
room->state_ref = DbCreate(db, 3, "rooms", room->id, "state");
|
||||||
|
room->leaves_ref = DbCreate(db, 3, "rooms", room->id, "leaves");
|
||||||
|
json = DbJson(room->leaves_ref);
|
||||||
|
JsonSet(json, JsonValueArray(ArrayCreate()), 1, "leaves");
|
||||||
|
full_creator = ParserRecomposeServerPart(room->creator);
|
||||||
|
JsonSet(json, JsonValueString(full_creator), 1, "creator");
|
||||||
|
Free(full_creator);
|
||||||
|
|
||||||
/* TODO: Populate room with information */
|
{
|
||||||
|
HashMap *event = HashMapCreate();
|
||||||
|
HashMap *content = HashMapCreate();
|
||||||
|
|
||||||
|
CommonID sender;
|
||||||
|
char *sender_str;
|
||||||
|
|
||||||
|
sender.sigil = '@';
|
||||||
|
sender.local = UserGetName(user);
|
||||||
|
sender.server = s;
|
||||||
|
sender_str = ParserRecomposeCommonID(sender);
|
||||||
|
|
||||||
|
JsonSet(event, JsonValueString(sender_str), 1, "sender");
|
||||||
|
if (room->version <= 10)
|
||||||
|
{
|
||||||
|
JsonSet(content, JsonValueString(sender_str), 1, "creator");
|
||||||
|
}
|
||||||
|
Free(sender_str);
|
||||||
|
JsonSet(event, JsonValueString("m.room.create"), 1, "type");
|
||||||
|
JsonSet(event, JsonValueString(""), 1, "state_key");
|
||||||
|
|
||||||
|
JsonSet(event, JsonValueObject(content), 1, "content");
|
||||||
|
JsonFree(RoomEventSend(room, event));
|
||||||
|
JsonFree(event);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HashMap *event = HashMapCreate();
|
||||||
|
HashMap *content = HashMapCreate();
|
||||||
|
|
||||||
|
CommonID sender;
|
||||||
|
char *sender_str;
|
||||||
|
|
||||||
|
sender.sigil = '@';
|
||||||
|
sender.local = UserGetName(user);
|
||||||
|
sender.server = s;
|
||||||
|
sender_str = ParserRecomposeCommonID(sender);
|
||||||
|
|
||||||
|
JsonSet(event, JsonValueString(sender_str), 1, "sender");
|
||||||
|
|
||||||
|
JsonSet(content, JsonValueString("join"), 1, "membership");
|
||||||
|
|
||||||
|
JsonSet(event, JsonValueString("m.room.member"), 1, "type");
|
||||||
|
JsonSet(event, JsonValueString(sender_str), 1, "state_key");
|
||||||
|
Free(sender_str);
|
||||||
|
|
||||||
|
JsonSet(event, JsonValueObject(content), 1, "content");
|
||||||
|
JsonFree(RoomEventSend(room, event));
|
||||||
|
JsonFree(event);
|
||||||
|
}
|
||||||
|
/* TODO: The rest of the events mandated by the specification on
|
||||||
|
* POST /createRoom. Also clean up that code, so that it is more
|
||||||
|
* straightforward(and short). */
|
||||||
return room;
|
return room;
|
||||||
}
|
}
|
||||||
|
|
||||||
Room *
|
Room *
|
||||||
RoomLock(Db * db, char *id)
|
RoomLock(Db * db, char *id)
|
||||||
{
|
{
|
||||||
DbRef *ref;
|
DbRef *state_ref, *leaves_ref;
|
||||||
|
HashMap *json;
|
||||||
Room *room;
|
Room *room;
|
||||||
|
|
||||||
if (!db || !id)
|
if (!db || !id)
|
||||||
|
@ -107,9 +180,10 @@ RoomLock(Db * db, char *id)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ref = DbLock(db, 3, "rooms", id, "state");
|
state_ref = DbLock(db, 3, "rooms", id, "state");
|
||||||
|
leaves_ref = DbLock(db, 3, "rooms", id, "leaves");
|
||||||
|
|
||||||
if (!ref)
|
if (!state_ref || !leaves_ref)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -117,14 +191,21 @@ RoomLock(Db * db, char *id)
|
||||||
room = Malloc(sizeof(Room));
|
room = Malloc(sizeof(Room));
|
||||||
if (!room)
|
if (!room)
|
||||||
{
|
{
|
||||||
DbUnlock(db, ref);
|
DbUnlock(db, state_ref);
|
||||||
|
DbUnlock(db, leaves_ref);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
room->db = db;
|
room->db = db;
|
||||||
room->ref = ref;
|
room->state_ref = state_ref;
|
||||||
|
room->leaves_ref = leaves_ref;
|
||||||
room->id = StrDuplicate(id);
|
room->id = StrDuplicate(id);
|
||||||
|
|
||||||
|
json = DbJson(room->leaves_ref);
|
||||||
|
ParseServerPart(
|
||||||
|
JsonValueAsString(JsonGet(json, 1, "creator")),
|
||||||
|
&room->creator);
|
||||||
|
|
||||||
return room;
|
return room;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +213,8 @@ int
|
||||||
RoomUnlock(Room * room)
|
RoomUnlock(Room * room)
|
||||||
{
|
{
|
||||||
Db *db;
|
Db *db;
|
||||||
DbRef *ref;
|
DbRef *state_ref;
|
||||||
|
DbRef *leaves_ref;
|
||||||
|
|
||||||
if (!room)
|
if (!room)
|
||||||
{
|
{
|
||||||
|
@ -140,12 +222,16 @@ RoomUnlock(Room * room)
|
||||||
}
|
}
|
||||||
|
|
||||||
db = room->db;
|
db = room->db;
|
||||||
ref = room->ref;
|
state_ref = room->state_ref;
|
||||||
|
leaves_ref = room->leaves_ref;
|
||||||
|
|
||||||
Free(room->id);
|
Free(room->id);
|
||||||
Free(room);
|
Free(room);
|
||||||
|
|
||||||
return DbUnlock(db, ref);
|
ServerPartFree(room->creator);
|
||||||
|
|
||||||
|
return DbUnlock(db, state_ref) &&
|
||||||
|
DbUnlock(db, leaves_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
|
@ -171,7 +257,7 @@ RoomStateGet(Room * room)
|
||||||
|
|
||||||
/* TODO: Consider caching the deserialised result, as doing that on a
|
/* TODO: Consider caching the deserialised result, as doing that on a
|
||||||
* large state would probably eat up a lot of time! */
|
* large state would probably eat up a lot of time! */
|
||||||
database_state = DbJson(room->ref);
|
database_state = DbJson(room->state_ref);
|
||||||
return StateDeserialise(database_state);
|
return StateDeserialise(database_state);
|
||||||
}
|
}
|
||||||
HashMap *
|
HashMap *
|
||||||
|
@ -199,7 +285,7 @@ RoomStateGetID(Room * room, char *event_id)
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
id_##n = StateGet(S, type, key); \
|
id_##n = StateGet(S, type, key); \
|
||||||
if (id_##n) \
|
if (!id_##n) \
|
||||||
{ \
|
{ \
|
||||||
goto finish; \
|
goto finish; \
|
||||||
} \
|
} \
|
||||||
|
@ -252,6 +338,7 @@ RoomUserHasMembership(Room * room, HashMap *state, char *user, char *mbr)
|
||||||
|
|
||||||
membership_value =
|
membership_value =
|
||||||
JsonValueAsString(JsonGet(membership, 2, "content", "membership"));
|
JsonValueAsString(JsonGet(membership, 2, "content", "membership"));
|
||||||
|
|
||||||
ret = StrEquals(membership_value, mbr);
|
ret = StrEquals(membership_value, mbr);
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
|
@ -345,9 +432,12 @@ finish:
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
PopulateEventV1(Room * room, HashMap * event, PduV1 * pdu)
|
PopulateEventV1(Room * room, HashMap * event, PduV1 * pdu, ServerPart serv)
|
||||||
{
|
{
|
||||||
char *unused;
|
char *unused;
|
||||||
|
Array *prev_events;
|
||||||
|
size_t i;
|
||||||
|
CommonID cid;
|
||||||
if (PduV1FromJson(event, pdu, &unused))
|
if (PduV1FromJson(event, pdu, &unused))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@ -358,13 +448,47 @@ PopulateEventV1(Room * room, HashMap * event, PduV1 * pdu)
|
||||||
* has some ideas on how this could be done(up until stage 5). */
|
* has some ideas on how this could be done(up until stage 5). */
|
||||||
pdu->sender =
|
pdu->sender =
|
||||||
StrDuplicate(JsonValueAsString(JsonGet(event, 1, "sender")));
|
StrDuplicate(JsonValueAsString(JsonGet(event, 1, "sender")));
|
||||||
|
pdu->type =
|
||||||
|
StrDuplicate(JsonValueAsString(JsonGet(event, 1, "type")));
|
||||||
|
pdu->redacts = NULL;
|
||||||
|
if (JsonGet(event, 1, "state_key"))
|
||||||
|
{
|
||||||
|
pdu->state_key =
|
||||||
|
StrDuplicate(JsonValueAsString(JsonGet(event, 1, "state_key")));
|
||||||
|
}
|
||||||
pdu->auth_events = ArrayCreate();
|
pdu->auth_events = ArrayCreate();
|
||||||
pdu->origin_server_ts = UtilTsMillis();
|
pdu->origin_server_ts = UtilTsMillis();
|
||||||
pdu->content = JsonDuplicate(event); /* Copy the original JSON data */
|
pdu->content =
|
||||||
|
JsonDuplicate(JsonValueAsObject(JsonGet(event, 1, "content")));
|
||||||
|
pdu->room_id = StrDuplicate(room->id);
|
||||||
|
pdu->signatures = HashMapCreate();
|
||||||
|
|
||||||
|
/* Create a random event ID for this PDU.
|
||||||
|
* TODO: Optionally verify whenever it's already used, but that
|
||||||
|
* would be unlikely considering the lengths of event IDs. */
|
||||||
|
cid.sigil = '$';
|
||||||
|
cid.local = StrRandom(32);
|
||||||
|
cid.server.hostname = StrDuplicate(serv.hostname);
|
||||||
|
cid.server.port = serv.port ? StrDuplicate(serv.port) : NULL;
|
||||||
|
pdu->event_id = ParserRecomposeCommonID(cid);
|
||||||
|
CommonIDFree(cid);
|
||||||
|
|
||||||
|
|
||||||
|
/* Fill prev_events with actual event data.
|
||||||
|
* Note that we don't actually *clear* out these from our list, as
|
||||||
|
* that should be done later. */
|
||||||
|
pdu->prev_events = ArrayCreate();
|
||||||
|
prev_events = RoomPrevEventsGet(room);
|
||||||
|
for (i = 0; i < ArraySize(prev_events); i++)
|
||||||
|
{
|
||||||
|
HashMap *event = JsonValueAsObject(ArrayGet(prev_events, i));
|
||||||
|
JsonValue *event_id = JsonGet(event, 1, "event_id");
|
||||||
|
|
||||||
|
ArrayAdd(pdu->prev_events, JsonValueDuplicate(event_id));
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO: Signature and alldat. */
|
/* TODO: Signature and alldat. */
|
||||||
|
|
||||||
(void) room;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static bool
|
static bool
|
||||||
|
@ -424,6 +548,11 @@ ValidAuthEventV1(PduV1 *auth_pdu, PduV1 *pdu)
|
||||||
/* TODO: Check if it's the latest in terms of [pdu] */
|
/* TODO: Check if it's the latest in terms of [pdu] */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (IsState(auth_pdu, "m.room.member", pdu->sender))
|
||||||
|
{
|
||||||
|
/* TODO: Check if it's the latest in terms of [pdu] */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (StrEquals(pdu->type, "m.room.member"))
|
if (StrEquals(pdu->type, "m.room.member"))
|
||||||
{
|
{
|
||||||
char *membership =
|
char *membership =
|
||||||
|
@ -466,7 +595,7 @@ VerifyPDUV1(PduV1 *auth_pdu)
|
||||||
* https://spec.matrix.org/v1.7/server-server-api/
|
* https://spec.matrix.org/v1.7/server-server-api/
|
||||||
* #checks-performed-on-receipt-of-a-pdu */
|
* #checks-performed-on-receipt-of-a-pdu */
|
||||||
(void) auth_pdu;
|
(void) auth_pdu;
|
||||||
return false; /* This only shows whenever an event was rejected, not
|
return true; /* This only shows whenever an event was rejected, not
|
||||||
* soft-failed */
|
* soft-failed */
|
||||||
}
|
}
|
||||||
static bool
|
static bool
|
||||||
|
@ -479,15 +608,16 @@ ConsiderAuthEventsV1(Room * room, PduV1 pdu)
|
||||||
state_keytype = HashMapCreate();
|
state_keytype = HashMapCreate();
|
||||||
for (i = 0; i < ArraySize(pdu.auth_events); i++)
|
for (i = 0; i < ArraySize(pdu.auth_events); i++)
|
||||||
{
|
{
|
||||||
char *event_id = ArrayGet(pdu.auth_events, i);
|
char *event_id = JsonValueAsString(ArrayGet(pdu.auth_events, i));
|
||||||
HashMap *event = RoomEventFetch(room, event_id);
|
HashMap *event = RoomEventFetch(room, event_id);
|
||||||
PduV1 auth_pdu;
|
PduV1 auth_pdu = { 0 };
|
||||||
|
|
||||||
char *key_type_id;
|
char *key_type_id;
|
||||||
|
|
||||||
if (!PduV1FromJson(event, &auth_pdu, &ignored))
|
if (!PduV1FromJson(event, &auth_pdu, &ignored))
|
||||||
{
|
{
|
||||||
HashMapFree(event);
|
JsonFree(event);
|
||||||
|
HashMapFree(state_keytype);
|
||||||
return false; /* Yeah... we aren't doing that. */
|
return false; /* Yeah... we aren't doing that. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,7 +629,7 @@ ConsiderAuthEventsV1(Room * room, PduV1 pdu)
|
||||||
if (HashMapGet(state_keytype, key_type_id))
|
if (HashMapGet(state_keytype, key_type_id))
|
||||||
{
|
{
|
||||||
/* Duplicate found! We actually ignore it's actual value. */
|
/* Duplicate found! We actually ignore it's actual value. */
|
||||||
HashMapFree(event);
|
JsonFree(event);
|
||||||
PduV1Free(&auth_pdu);
|
PduV1Free(&auth_pdu);
|
||||||
|
|
||||||
HashMapFree(state_keytype);
|
HashMapFree(state_keytype);
|
||||||
|
@ -516,6 +646,9 @@ ConsiderAuthEventsV1(Room * room, PduV1 pdu)
|
||||||
* described in the server specification, reject. */
|
* described in the server specification, reject. */
|
||||||
if (!ValidAuthEventV1(&auth_pdu, &pdu))
|
if (!ValidAuthEventV1(&auth_pdu, &pdu))
|
||||||
{
|
{
|
||||||
|
JsonFree(event);
|
||||||
|
PduV1Free(&auth_pdu);
|
||||||
|
HashMapFree(state_keytype);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* Step 2.3: If there are entries which were themselves rejected
|
/* Step 2.3: If there are entries which were themselves rejected
|
||||||
|
@ -523,6 +656,9 @@ ConsiderAuthEventsV1(Room * room, PduV1 pdu)
|
||||||
* TODO */
|
* TODO */
|
||||||
if (!VerifyPDUV1(&auth_pdu))
|
if (!VerifyPDUV1(&auth_pdu))
|
||||||
{
|
{
|
||||||
|
PduV1Free(&auth_pdu);
|
||||||
|
JsonFree(event);
|
||||||
|
HashMapFree(state_keytype);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,7 +669,7 @@ ConsiderAuthEventsV1(Room * room, PduV1 pdu)
|
||||||
room_create = true; /* Here, we check for the opposite. */
|
room_create = true; /* Here, we check for the opposite. */
|
||||||
}
|
}
|
||||||
|
|
||||||
HashMapFree(event);
|
JsonFree(event);
|
||||||
PduV1Free(&auth_pdu);
|
PduV1Free(&auth_pdu);
|
||||||
}
|
}
|
||||||
HashMapFree(state_keytype);
|
HashMapFree(state_keytype);
|
||||||
|
@ -648,8 +784,10 @@ AuthorizeInviteMembershipV1(Room * room, PduV1 pdu, HashMap *state)
|
||||||
thirdpi_event_sender = JsonValueAsString(JsonGet(third_pi_event, 1, "sender"));
|
thirdpi_event_sender = JsonValueAsString(JsonGet(third_pi_event, 1, "sender"));
|
||||||
if (!StrEquals(thirdpi_event_sender, pdu.sender))
|
if (!StrEquals(thirdpi_event_sender, pdu.sender))
|
||||||
{
|
{
|
||||||
|
JsonFree(third_pi_event);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
JsonFree(third_pi_event);
|
||||||
|
|
||||||
/* TODO:
|
/* TODO:
|
||||||
* Step 5.3.1.7: If any signature in signed matches any public key in
|
* Step 5.3.1.7: If any signature in signed matches any public key in
|
||||||
|
@ -762,23 +900,24 @@ AuthorizeJoinMembershipV1(Room * room, PduV1 pdu, HashMap *state)
|
||||||
Array *prev = pdu.prev_events;
|
Array *prev = pdu.prev_events;
|
||||||
if (ArraySize(prev) == 1)
|
if (ArraySize(prev) == 1)
|
||||||
{
|
{
|
||||||
char *prev_id = ArrayGet(prev, 0);
|
/* Interperet prev properly, as a list of JsonObjects. */
|
||||||
|
char *prev_id = JsonValueAsString(ArrayGet(prev, 0));
|
||||||
char *ignored;
|
char *ignored;
|
||||||
HashMap *prev = RoomEventFetch(room, prev_id);
|
HashMap *prev_event = RoomEventFetch(room, prev_id);
|
||||||
PduV1 prev_pdu;
|
PduV1 prev_pdu;
|
||||||
|
|
||||||
if (prev && PduV1FromJson(prev, &prev_pdu, &ignored))
|
if (prev && PduV1FromJson(prev_event, &prev_pdu, &ignored))
|
||||||
{
|
{
|
||||||
if (StrEquals(prev_pdu.type, "m.room.create") &&
|
if (StrEquals(prev_pdu.type, "m.room.create") &&
|
||||||
StrEquals(prev_pdu.sender, pdu.state_key))
|
StrEquals(prev_pdu.sender, pdu.state_key))
|
||||||
{
|
{
|
||||||
PduV1Free(&prev_pdu);
|
PduV1Free(&prev_pdu);
|
||||||
JsonFree(prev);
|
JsonFree(prev_event);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
PduV1Free(&prev_pdu);
|
PduV1Free(&prev_pdu);
|
||||||
}
|
}
|
||||||
JsonFree(prev);
|
JsonFree(prev_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Step 5.2.2: If the sender does not match state_key, reject. */
|
/* Step 5.2.2: If the sender does not match state_key, reject. */
|
||||||
|
@ -1069,6 +1208,7 @@ RoomAuthoriseEventV1(Room * room, PduV1 pdu, HashMap *state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
JsonFree(create_event);
|
||||||
|
|
||||||
/* Step 4: If type is m.room.aliases */
|
/* Step 4: If type is m.room.aliases */
|
||||||
if (StrEquals(pdu.type, "m.room.aliases"))
|
if (StrEquals(pdu.type, "m.room.aliases"))
|
||||||
|
@ -1168,29 +1308,70 @@ RoomHashEventV1(PduV1 pdu)
|
||||||
JsonFree(json);
|
JsonFree(json);
|
||||||
return sha;
|
return sha;
|
||||||
}
|
}
|
||||||
|
static bool
|
||||||
|
EventFits(HashMap *pdu)
|
||||||
|
{
|
||||||
|
int size = CanonicalJsonEncode(pdu, NULL);
|
||||||
|
JsonValue *key;
|
||||||
|
|
||||||
|
/* Main PDU length is 65536 bytes */
|
||||||
|
if (size > 65536)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#define VerifyKey(k,s) do \
|
||||||
|
{ \
|
||||||
|
if ((key = JsonGet(pdu, 1, k)) && \
|
||||||
|
(strlen(JsonValueAsString(key)) > s)) \
|
||||||
|
{ \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
VerifyKey("sender", 255);
|
||||||
|
VerifyKey("room_id", 255);
|
||||||
|
VerifyKey("state_key", 255);
|
||||||
|
VerifyKey("type", 255);
|
||||||
|
VerifyKey("event_id", 255);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
#undef VerifyKey
|
||||||
|
}
|
||||||
|
static bool
|
||||||
|
EventFitsV1(PduV1 pdu)
|
||||||
|
{
|
||||||
|
HashMap *hm;
|
||||||
|
bool ret;
|
||||||
|
|
||||||
|
hm = PduV1ToJson(&pdu);
|
||||||
|
ret = EventFits(hm);
|
||||||
|
|
||||||
|
JsonFree(hm);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
static HashMap *
|
static HashMap *
|
||||||
RoomEventSendV1(Room * room, HashMap * event)
|
RoomEventSendV1(Room * room, HashMap * event)
|
||||||
{
|
{
|
||||||
PduV1 pdu = { 0 };
|
PduV1 pdu = { 0 };
|
||||||
HashMap *pdu_object = NULL;
|
HashMap *pdu_object = NULL;
|
||||||
bool client_event;
|
bool client_event, valid = false;
|
||||||
HashMap *state = NULL;
|
HashMap *state = NULL;
|
||||||
|
|
||||||
client_event = PopulateEventV1(room, event, &pdu);
|
client_event = !PopulateEventV1(room, event, &pdu, RoomGetCreator(room));
|
||||||
pdu_object = PduV1ToJson(&pdu);
|
pdu_object = PduV1ToJson(&pdu);
|
||||||
|
|
||||||
state = StateResolve(room, pdu_object); /* Compute the state
|
state = StateResolve(room, pdu_object); /* Compute the state
|
||||||
* at that point for later. */
|
* at that point for later. */
|
||||||
if (client_event)
|
if (client_event)
|
||||||
{
|
{
|
||||||
char *event_id;
|
char *ev_id;
|
||||||
#define AddState(type, key) do \
|
#define AddState(type, key) do \
|
||||||
{ \
|
{ \
|
||||||
event_id = StateGet(state, type, key); \
|
ev_id = StateGet(state, type, key); \
|
||||||
if (event_id) \
|
if (ev_id) \
|
||||||
{ \
|
{ \
|
||||||
char *dup = StrDuplicate(event_id); \
|
JsonValue *v = JsonValueString(ev_id); \
|
||||||
ArrayAdd(pdu.auth_events, dup); \
|
ArrayAdd(pdu.auth_events, v); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
|
@ -1239,7 +1420,26 @@ RoomEventSendV1(Room * room, HashMap * event)
|
||||||
pdu.hashes.sha256 = RoomHashEventV1(pdu);
|
pdu.hashes.sha256 = RoomHashEventV1(pdu);
|
||||||
#undef AddState
|
#undef AddState
|
||||||
}
|
}
|
||||||
/* TODO: Do a size check! */
|
/* TODO: For PDU events, we should verify their hashes. */
|
||||||
|
if (!EventFitsV1(pdu))
|
||||||
|
{
|
||||||
|
/* Reject this event as it is too large. */
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
if (!RoomAuthoriseEventV1(room, pdu, state))
|
||||||
|
{
|
||||||
|
/* Reject this event as the current state does not allow it.
|
||||||
|
* TODO: Make the auth check function return a string showing the
|
||||||
|
* error status to the user. */
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
RoomAddEventV1(room, pdu);
|
||||||
|
valid = true;
|
||||||
|
|
||||||
|
/* If it is a client event, we should make sure that we shout at
|
||||||
|
* every other homeserver about our new event. */
|
||||||
|
|
||||||
|
finish:
|
||||||
if (state)
|
if (state)
|
||||||
{
|
{
|
||||||
JsonFree(state);
|
JsonFree(state);
|
||||||
|
@ -1247,9 +1447,14 @@ RoomEventSendV1(Room * room, HashMap * event)
|
||||||
if (pdu_object)
|
if (pdu_object)
|
||||||
{
|
{
|
||||||
JsonFree(pdu_object);
|
JsonFree(pdu_object);
|
||||||
|
pdu_object = NULL;
|
||||||
|
}
|
||||||
|
if (valid)
|
||||||
|
{
|
||||||
|
pdu_object = PduV1ToJson(&pdu);
|
||||||
}
|
}
|
||||||
PduV1Free(&pdu);
|
PduV1Free(&pdu);
|
||||||
return NULL;
|
return pdu_object;
|
||||||
}
|
}
|
||||||
static HashMap *
|
static HashMap *
|
||||||
RoomEventSendV3(Room * room, HashMap * event)
|
RoomEventSendV3(Room * room, HashMap * event)
|
||||||
|
@ -1322,3 +1527,93 @@ finish:
|
||||||
Free(safe_id);
|
Free(safe_id);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Array *
|
||||||
|
RoomPrevEventsGet(Room *room)
|
||||||
|
{
|
||||||
|
HashMap *json;
|
||||||
|
if (!room)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
json = DbJson(room->leaves_ref);
|
||||||
|
return JsonValueAsArray(JsonGet(json, 1, "leaves"));
|
||||||
|
}
|
||||||
|
ServerPart
|
||||||
|
RoomGetCreator(Room *room)
|
||||||
|
{
|
||||||
|
ServerPart ret = { 0 };
|
||||||
|
if (!room)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return room->creator;
|
||||||
|
}
|
||||||
|
bool
|
||||||
|
RoomAddEventV1(Room *room, PduV1 pdu)
|
||||||
|
{
|
||||||
|
DbRef *event_ref;
|
||||||
|
Array *prev_events, *leaves;
|
||||||
|
HashMap *leaves_json, *pdu_json;
|
||||||
|
JsonValue *leaves_val;
|
||||||
|
char *safe_id;
|
||||||
|
size_t i;
|
||||||
|
if (!room || room->version >= 3)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
leaves_json = DbJson(room->leaves_ref);
|
||||||
|
leaves_val = JsonValueDuplicate(JsonGet(leaves_json, 1, "leaves"));
|
||||||
|
leaves = JsonValueAsArray(leaves_val);
|
||||||
|
Free(leaves_val);
|
||||||
|
|
||||||
|
prev_events = pdu.prev_events;
|
||||||
|
for (i = 0; i < ArraySize(prev_events); i++)
|
||||||
|
{
|
||||||
|
JsonValue *event_val = ArrayGet(prev_events, i);
|
||||||
|
char *event_id = JsonValueAsString(event_val);
|
||||||
|
size_t j;
|
||||||
|
ssize_t delete_index = -1;
|
||||||
|
|
||||||
|
for (j = 0; j < ArraySize(leaves); j++)
|
||||||
|
{
|
||||||
|
JsonValue *leaf_val = ArrayGet(leaves, j);
|
||||||
|
HashMap *leaf_object = JsonValueAsObject(leaf_val);
|
||||||
|
char *leaf_id =
|
||||||
|
JsonValueAsString(JsonGet(leaf_object, 1, "event_id"));
|
||||||
|
|
||||||
|
if (StrEquals(leaf_id, event_id))
|
||||||
|
{
|
||||||
|
delete_index = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (delete_index == -1)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
JsonValueFree(ArrayDelete(leaves, delete_index));
|
||||||
|
}
|
||||||
|
|
||||||
|
safe_id = CreateSafeID(pdu.event_id);
|
||||||
|
event_ref = DbCreate(room->db, 4, "rooms", room->id, "events", safe_id);
|
||||||
|
Free(safe_id);
|
||||||
|
|
||||||
|
pdu_json = PduV1ToJson(&pdu);
|
||||||
|
DbJsonSet(event_ref, pdu_json);
|
||||||
|
|
||||||
|
ArrayAdd(leaves, JsonValueObject(pdu_json));
|
||||||
|
leaves_json = JsonDuplicate(leaves_json);
|
||||||
|
JsonValueFree(HashMapDelete(leaves_json, "leaves"));
|
||||||
|
JsonSet(leaves_json, JsonValueArray(leaves), 1, "leaves");
|
||||||
|
DbJsonSet(room->leaves_ref, leaves_json);
|
||||||
|
JsonFree(leaves_json);
|
||||||
|
|
||||||
|
DbUnlock(room->db, event_ref);
|
||||||
|
|
||||||
|
/* TODO: Store DAG relationships, somehow.
|
||||||
|
* Also keep track of PDU depth. */
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <Routes.h>
|
#include <Routes.h>
|
||||||
|
|
||||||
#include <Cytoplasm/Json.h>
|
#include <Cytoplasm/Json.h>
|
||||||
|
#include <Cytoplasm/Log.h>
|
||||||
|
|
||||||
#include <Room.h>
|
#include <Room.h>
|
||||||
#include <User.h>
|
#include <User.h>
|
||||||
|
@ -41,12 +42,17 @@ ROUTE_IMPL(RouteCreateRoom, path, argp)
|
||||||
Db *db = args->matrixArgs->db;
|
Db *db = args->matrixArgs->db;
|
||||||
RoomCreateRequest parsed;
|
RoomCreateRequest parsed;
|
||||||
User *user = NULL;
|
User *user = NULL;
|
||||||
|
Config cfg;
|
||||||
|
ServerPart server;
|
||||||
|
|
||||||
char *token;
|
char *token;
|
||||||
char *err;
|
char *err;
|
||||||
|
|
||||||
(void) path;
|
(void) path;
|
||||||
|
|
||||||
|
ConfigLock(db, &cfg);
|
||||||
|
ParseServerPart(cfg.serverName, &server);
|
||||||
|
|
||||||
if (HttpRequestMethodGet(args->context) != HTTP_POST)
|
if (HttpRequestMethodGet(args->context) != HTTP_POST)
|
||||||
{
|
{
|
||||||
err = "Unknown request method.";
|
err = "Unknown request method.";
|
||||||
|
@ -86,7 +92,9 @@ ROUTE_IMPL(RouteCreateRoom, path, argp)
|
||||||
JsonFree(request);
|
JsonFree(request);
|
||||||
request = NULL;
|
request = NULL;
|
||||||
|
|
||||||
if (!(room = RoomCreate(db, user, &parsed)))
|
Log(LOG_INFO, "Creating room...");
|
||||||
|
|
||||||
|
if (!(room = RoomCreate(db, user, &parsed, server)))
|
||||||
{
|
{
|
||||||
err = "Couldn't create room.";
|
err = "Couldn't create room.";
|
||||||
/* Consider another error status. */
|
/* Consider another error status. */
|
||||||
|
@ -102,5 +110,7 @@ finish:
|
||||||
JsonFree(request);
|
JsonFree(request);
|
||||||
RoomUnlock(room);
|
RoomUnlock(room);
|
||||||
UserUnlock(user);
|
UserUnlock(user);
|
||||||
|
ConfigUnlock(&cfg);
|
||||||
|
ServerPartFree(server);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
78
src/State.c
78
src/State.c
|
@ -40,9 +40,11 @@ int
|
||||||
V1Cmp(void *a, void *b)
|
V1Cmp(void *a, void *b)
|
||||||
{
|
{
|
||||||
HashMap *e1 = a, *e2 = b;
|
HashMap *e1 = a, *e2 = b;
|
||||||
int64_t depth1 =
|
int64_t depth1, depth2;
|
||||||
|
|
||||||
|
depth1 =
|
||||||
JsonValueAsInteger(JsonGet(e1, 1, "depth"));
|
JsonValueAsInteger(JsonGet(e1, 1, "depth"));
|
||||||
int64_t depth2 =
|
depth2 =
|
||||||
JsonValueAsInteger(JsonGet(e2, 1, "depth"));
|
JsonValueAsInteger(JsonGet(e2, 1, "depth"));
|
||||||
|
|
||||||
if (depth1 > depth2)
|
if (depth1 > depth2)
|
||||||
|
@ -94,6 +96,7 @@ StateResolveV1(Room * room, Array * states)
|
||||||
if (HashMapGet(R, tuple))
|
if (HashMapGet(R, tuple))
|
||||||
{
|
{
|
||||||
Array *arr;
|
Array *arr;
|
||||||
|
HashMap *hm;
|
||||||
|
|
||||||
/* Conflicts! */
|
/* Conflicts! */
|
||||||
HashMapDelete(R, tuple);
|
HashMapDelete(R, tuple);
|
||||||
|
@ -102,13 +105,14 @@ StateResolveV1(Room * room, Array * states)
|
||||||
{
|
{
|
||||||
arr = ArrayCreate();
|
arr = ArrayCreate();
|
||||||
}
|
}
|
||||||
ArrayAdd(arr, RoomEventFetch(room, event_id));
|
hm = RoomEventFetch(room, event_id);
|
||||||
|
ArrayAdd(arr, hm);
|
||||||
HashMapSet(conflicts, tuple, arr);
|
HashMapSet(conflicts, tuple, arr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Add to R */
|
/* Add to R */
|
||||||
HashMapSet(R, tuple, event_id);
|
HashMapSet(R, tuple, StrDuplicate(event_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -138,7 +142,13 @@ StateResolveV1(Room * room, Array * states)
|
||||||
Free(type);
|
Free(type);
|
||||||
Free(key);
|
Free(key);
|
||||||
}
|
}
|
||||||
ArraySort(events, V1Cmp);
|
if (ArraySize(events) != 0)
|
||||||
|
{
|
||||||
|
/* TODO: Cytoplasm currently doesn't behave correctly
|
||||||
|
* when the array size is 0, I'll need to file a bug
|
||||||
|
* report/PR eventually. */
|
||||||
|
ArraySort(events, V1Cmp);
|
||||||
|
}
|
||||||
/* Add first event. */
|
/* Add first event. */
|
||||||
first = ArrayDelete(events, 0);
|
first = ArrayDelete(events, 0);
|
||||||
StateSet(
|
StateSet(
|
||||||
|
@ -146,6 +156,7 @@ StateResolveV1(Room * room, Array * states)
|
||||||
JsonValueAsString(JsonGet(first, 1, "type")),
|
JsonValueAsString(JsonGet(first, 1, "type")),
|
||||||
JsonValueAsString(JsonGet(first, 1, "state_key")),
|
JsonValueAsString(JsonGet(first, 1, "state_key")),
|
||||||
JsonValueAsString(JsonGet(first, 1, "event_id")));
|
JsonValueAsString(JsonGet(first, 1, "event_id")));
|
||||||
|
JsonFree(first);
|
||||||
|
|
||||||
for (j = 0; j < (ssize_t) ArraySize(events); j++)
|
for (j = 0; j < (ssize_t) ArraySize(events); j++)
|
||||||
{
|
{
|
||||||
|
@ -161,10 +172,12 @@ StateResolveV1(Room * room, Array * states)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PduV1Free(&pdu);
|
PduV1Free(&pdu);
|
||||||
|
JsonFree(event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
(void) msg;
|
(void) msg;
|
||||||
PduV1Free(&pdu);
|
PduV1Free(&pdu);
|
||||||
|
JsonFree(event);
|
||||||
}
|
}
|
||||||
ArrayFree(events);
|
ArrayFree(events);
|
||||||
/* Delete all elements within a key. */
|
/* Delete all elements within a key. */
|
||||||
|
@ -183,13 +196,16 @@ StateResolveV1(Room * room, Array * states)
|
||||||
StateSet(conflicts, t, state_key, NULL);
|
StateSet(conflicts, t, state_key, NULL);
|
||||||
Free(state_key);
|
Free(state_key);
|
||||||
}
|
}
|
||||||
Free(state_keys);
|
ArrayFree(state_keys);
|
||||||
}
|
}
|
||||||
ArrayFree(types);
|
ArrayFree(types);
|
||||||
|
|
||||||
while (StateIterate(conflicts, &type, &key, (void **) &conflicting))
|
while (StateIterate(conflicts, &type, &key, (void **) &conflicting))
|
||||||
{
|
{
|
||||||
ArraySort(conflicting, V1Cmp);
|
if (ArraySize(conflicting) != 0)
|
||||||
|
{
|
||||||
|
ArraySort(conflicting, V1Cmp);
|
||||||
|
}
|
||||||
for (j = ArraySize(conflicting) - 1; j >= 0; j--)
|
for (j = ArraySize(conflicting) - 1; j >= 0; j--)
|
||||||
{
|
{
|
||||||
HashMap *event = ArrayGet(events, j);
|
HashMap *event = ArrayGet(events, j);
|
||||||
|
@ -210,8 +226,7 @@ StateResolveV1(Room * room, Array * states)
|
||||||
Free(type);
|
Free(type);
|
||||||
Free(key);
|
Free(key);
|
||||||
}
|
}
|
||||||
|
while (HashMapIterate(conflicts, &type, (void **) &conflicting))
|
||||||
while (StateIterate(conflicts, &type, &key, (void **) &conflicting))
|
|
||||||
{
|
{
|
||||||
for (i = 0; i < ArraySize(conflicting); i++)
|
for (i = 0; i < ArraySize(conflicting); i++)
|
||||||
{
|
{
|
||||||
|
@ -239,6 +254,8 @@ StateResolve(Room * room, HashMap * event)
|
||||||
|
|
||||||
Array *prevEvents;
|
Array *prevEvents;
|
||||||
|
|
||||||
|
HashMap *ret_state;
|
||||||
|
|
||||||
if (!room || !event)
|
if (!room || !event)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -251,26 +268,46 @@ StateResolve(Room * room, HashMap * event)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
prevEvents = JsonValueAsArray(HashMapGet(event, "prev_events"));
|
||||||
prevEvents = HashMapGet(event, "prev_events");
|
|
||||||
|
|
||||||
for (i = 0; i < ArraySize(prevEvents); i++)
|
for (i = 0; i < ArraySize(prevEvents); i++)
|
||||||
{
|
{
|
||||||
HashMap *prevEvent = ArrayGet(prevEvents, i);
|
HashMap *prevEvent =
|
||||||
|
RoomEventFetch(room, JsonValueAsString(ArrayGet(prevEvents, i)));
|
||||||
HashMap *state = StateResolve(room, prevEvent);
|
HashMap *state = StateResolve(room, prevEvent);
|
||||||
|
|
||||||
/* TODO: Apply prevEvent to state if it is a state event */
|
if (HashMapGet(prevEvent, "state_key"))
|
||||||
|
{
|
||||||
|
StateSet(
|
||||||
|
state,
|
||||||
|
JsonValueAsString(HashMapGet(prevEvent, "type")),
|
||||||
|
JsonValueAsString(HashMapGet(prevEvent, "state_key")),
|
||||||
|
JsonValueAsString(HashMapGet(prevEvent, "event_id")));
|
||||||
|
}
|
||||||
|
|
||||||
ArrayAdd(states, state);
|
ArrayAdd(states, state);
|
||||||
|
JsonFree(prevEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret_state = NULL;
|
||||||
switch (RoomVersionGet(room))
|
switch (RoomVersionGet(room))
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
return StateResolveV1(room, states);
|
ret_state = StateResolveV1(room, states);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return StateResolveV2(states);
|
ret_state = StateResolveV2(states);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ArraySize(states); i++)
|
||||||
|
{
|
||||||
|
HashMap *state = ArrayGet(states, i);
|
||||||
|
StateFree(state);
|
||||||
|
}
|
||||||
|
ArrayFree(states);
|
||||||
|
|
||||||
|
return ret_state;
|
||||||
}
|
}
|
||||||
bool StateIterate(HashMap *state, char **type, char **key, void **event)
|
bool StateIterate(HashMap *state, char **type, char **key, void **event)
|
||||||
{
|
{
|
||||||
|
@ -282,11 +319,14 @@ bool StateIterate(HashMap *state, char **type, char **key, void **event)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = HashMapIterate(state, &tuple, event);
|
ret = HashMapIterate(state, &tuple, event);
|
||||||
tuple = StrDuplicate(tuple);
|
if (ret)
|
||||||
*(strchr(tuple, ',')) = '\0';
|
{
|
||||||
|
tuple = StrDuplicate(tuple);
|
||||||
|
*(strchr(tuple, ',')) = '\0';
|
||||||
|
|
||||||
*type = tuple;
|
*type = tuple;
|
||||||
*key = StrDuplicate(tuple + strlen(tuple) + 1);
|
*key = StrDuplicate(tuple + strlen(tuple) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include <Schema/RoomCreateRequest.h>
|
#include <Schema/RoomCreateRequest.h>
|
||||||
#include <Schema/PduV1.h>
|
#include <Schema/PduV1.h>
|
||||||
|
|
||||||
|
#include <Parser.h>
|
||||||
#include <User.h>
|
#include <User.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,7 +55,7 @@ typedef struct Room Room;
|
||||||
* Create a new room in the given database using the given
|
* Create a new room in the given database using the given
|
||||||
* RoomCreateRequest.
|
* RoomCreateRequest.
|
||||||
*/
|
*/
|
||||||
extern Room * RoomCreate(Db *, User *, RoomCreateRequest *);
|
extern Room * RoomCreate(Db *, User *, RoomCreateRequest *, ServerPart);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lock the existing room in the specified database,
|
* Lock the existing room in the specified database,
|
||||||
|
@ -151,4 +152,16 @@ extern HashMap * RoomEventFetch(Room *, char *);
|
||||||
*/
|
*/
|
||||||
extern bool RoomAuthoriseEventV1(Room *, PduV1, HashMap *);
|
extern bool RoomAuthoriseEventV1(Room *, PduV1, HashMap *);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the room's creator as a ServerPart. This value should
|
||||||
|
* not be freed, as it lives alongside the room itself
|
||||||
|
*/
|
||||||
|
extern ServerPart RoomGetCreator(Room *);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Puts a PDUv1 into the event list, while updating the leaf
|
||||||
|
* list.
|
||||||
|
*/
|
||||||
|
extern bool RoomAddEventV1(Room *, PduV1);
|
||||||
|
|
||||||
#endif /* TELODENDRIA_ROOM_H */
|
#endif /* TELODENDRIA_ROOM_H */
|
||||||
|
|
Loading…
Reference in a new issue