From bc8283f844afdfcdb0e71dafa6649dbe846e05fa Mon Sep 17 00:00:00 2001 From: Jordan Bancino Date: Fri, 7 Jul 2023 02:56:09 +0000 Subject: [PATCH] Begin prototyping room API. --- src/Room.c | 119 ++++++++++++++++++++++++++++++++++++++ src/include/Event.h | 54 +++++++++++++++++ src/include/Room.h | 138 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 311 insertions(+) create mode 100644 src/Room.c create mode 100644 src/include/Event.h create mode 100644 src/include/Room.h diff --git a/src/Room.c b/src/Room.c new file mode 100644 index 0000000..c5a3ac5 --- /dev/null +++ b/src/Room.c @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2022-2023 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 + +#include +#include +#include + +struct Room +{ + Db *db; + DbRef *ref; + + char *id; + int version; +}; + +Room * +RoomCreate(Db *db, HashMap *json) +{ + return NULL; +} + +Room * +RoomLock(Db *db, char *id) +{ + DbRef *ref; + Room *room; + + if (!db || !id) + { + return NULL; + } + + ref = DbLock(db, 3, "rooms", id, "state"); + + if (!ref) + { + return NULL; + } + + room = Malloc(sizeof(Room)); + if (!room) + { + DbUnlock(db, ref); + return NULL; + } + + room->db = db; + room->ref = ref; + room->id = StrDuplicate(id); + + return room; +} + +int +RoomUnlock(Room *room) +{ + Db *db; + DbRef *ref; + + if (!room) + { + return 0; + } + + db = room->db; + ref = room->ref; + + Free(room->id); + Free(room); + + return DbUnlock(db, ref); +} + +char * +RoomIdGet(Room *room) +{ + return room ? room->id : NULL; +} + +int +RoomVersionGet(Room *room) +{ + return room ? room->version : 0; +} + +HashMap * +RoomStateGet(Room *room) +{ + if (!room) + { + return NULL; + } + + return NULL; +} diff --git a/src/include/Event.h b/src/include/Event.h new file mode 100644 index 0000000..cff349b --- /dev/null +++ b/src/include/Event.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2022-2023 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_EVENT_H +#define TELODENDRIA_EVENT_H + +#include + +#include + +/** + * Compute the content hash of an event. This involves + * converting it to a canonical JSON string and then + * hashing it. + */ +extern char * EventContentHash(HashMap *); + +/** + * Get the full event ID, including the sigil, and, if + * applicable, the server name. This function requires + * the room handle that the event belongs to because + * certain room versions have the event ID embedded in + * the event itself, and others are calculated. Note + * that if an event is being loaded from the database, + * the ID is already known. Since this is a computationally + * and memory intensive operation, it should not be + * performed more than absolutely necessary, namely, when + * an event comes in from the federation APIs or the + * homeserver has finished generating a PDU for a client + * event. +extern char * EventIdGet(Room *, HashMap *); + +#endif /* TELODENDRIA_EVENT_H */ diff --git a/src/include/Room.h b/src/include/Room.h new file mode 100644 index 0000000..a1e7c7b --- /dev/null +++ b/src/include/Room.h @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2022-2023 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_ROOM_H +#define TELODENDRIA_ROOM_H + +/*** + * @Nm Room + * @Nd API for creating and manipulating Rooms. + * @Dd July 6 2023 + * @Xr Event + * + * The core component of the Matrix specification is the Room, + * which holds a directed acyclic graph (DAG) of Events. + * .Nm + * provides a way of working with persistent rooms. + */ + +#include +#include + +/** + * The functions in this API operate on an opaque structure. + */ +typedef struct Room Room; + +/** + * Create a new room in the given database using the given + * JSON body. The JSON body is the request body from the + * room creation API, which is used to configure the room + * as requested. A handle to the newly created room is + * returned, or NULL if there was an error creating the + * room. + * .Pp + * The JSON should be validated before being passed into + * this function. Malformed JSON will cause this function + * to fail, but since the only way it can indicate an + * error is by returning NULL, it's impossible to tell + * the client what the specific error is. + */ +extern Room * RoomCreate(Db *, HashMap *); + +/** + * Lock the existing room in the specified database, + * identified by the specified ID, which is expected + * to include the server name and room ID sigil. + * .Pp + * this function returns NULL if there was an error + * locking the room, such as the room not existing. + */ +extern Room * RoomLock(Db *, char *); + +/** + * Unlock a room handle, returning it to the database. + * This function returns the result of calling + * .Fn DbUnlock() on the internal room reference. + */ +extern int RoomUnlock(Room *); + +/** + * Get the full ID of the specified room, including + * the sigil and server name. This function returns + * NULL if there was an error getting the room ID. + */ +extern char * RoomIdGet(Room *); + +/** + * Get the numeric room version for the specified + * room. The room version is determined by and stored + * in the m.room.create event as a string, but since this + * is expected to be a relatively frequent operation, + * the integer representation is stored in the room + * information so it can be accessed without having + * to lock the room state and m.room.create event. + */ +extern int RoomVersionGet(Room *); + +/** + * Resolve the state for the latest events in the + * room. This function uses the appropriate state + * resolution algorithm to compute the latest state, + * which is used to select auth events on incoming + * client events. + */ +extern HashMap * RoomStateGet(Room *); + +/** + * Get a list of the most recent events in the + * room. When ingressing client events, these events + * should be copied to the incoming event's prev_events. + * Note that this function returns an array of actual + * events themselves, not just IDs, even though that's + * what's stored in the database. + */ +extern Array * RoomPrevEventsGet(Room *); + +/** + * Set the list of most recent events in the room. + * When ingressing client events, this list will be + * manipulated. Unfortunately it can't be manipulated + * in place with the current design, so this function + * is responsible for copying the modified list into + * place. + */ +extern int RoomPrevEventsSet(Room *, Array *); + +/** + * Send a single event to the specified room. This + * function can take either a client event or a + * federation PDU. Depending on which is supplied, + * the appropriate logic is applied. Client events + * are converted into their federation format for + * the room version, which includes setting the + * prev_events and auth_events fields correctly. + */ +extern HashMap * RoomEventSend(Room *, HashMap *); + +#endif /* TELODENDRIA_ROOM_H */