diff --git a/src/Room.c b/src/Room.c index 34a4029..6766773 100644 --- a/src/Room.c +++ b/src/Room.c @@ -1815,32 +1815,44 @@ RoomAddEventV1(Room *room, PduV1 pdu) /* TODO: Store DAG relationships, somehow. * Also keep track of PDU depth. */ - if (StrEquals(pdu.type, "m.room.member")) + pdu_json = PduV1ToJson(&pdu); { - CommonID *id = UserIdParse(pdu.state_key, NULL); - User *user = UserLock(room->db, id->local); - char *membership = JsonValueAsString( - HashMapGet(pdu.content, "membership") - ); + CommonID *sid= UserIdParse(pdu.sender, NULL); + User *suser = UserLock(room->db, sid->local); + if (StrEquals(pdu.type, "m.room.member")) + { + CommonID *id = UserIdParse(pdu.state_key, NULL); + User *user = UserLock(room->db, id->local); + char *membership = JsonValueAsString( + HashMapGet(pdu.content, "membership") + ); - if (StrEquals(membership, "join") && user) - { - UserAddJoin(user, room->id); - } - else if (StrEquals(membership, "invite") && user) - { - UserAddInvite(user, room->id); - } - else if ((StrEquals(membership, "leave") && user) || - StrEquals(membership, "ban")) - { - UserRemoveInvite(user, room->id); - UserRemoveJoin(user, room->id); + if (StrEquals(membership, "join") && user) + { + UserAddJoin(user, room->id); + UserPushJoinSync(user, room->id); + } + else if (StrEquals(membership, "invite") && user) + { + UserAddInvite(user, room->id); + UserPushInviteSync(user, room->id); + } + else if ((StrEquals(membership, "leave") && user) || + StrEquals(membership, "ban")) + { + UserRemoveInvite(user, room->id); + UserRemoveJoin(user, room->id); + } + + UserIdFree(id); + UserUnlock(user); } - UserIdFree(id); - UserUnlock(user); + UserPushEvent(suser, pdu_json); + UserIdFree(sid); + UserUnlock(suser); } + JsonFree(pdu_json); return true; } diff --git a/src/User.c b/src/User.c index 4bdab9f..8d38ea3 100644 --- a/src/User.c +++ b/src/User.c @@ -22,6 +22,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ +#include #include #include #include @@ -1114,3 +1115,149 @@ UserFreeList(Array *arr) ArrayFree(arr); } +char * +UserInitSyncDiff(User *user) +{ + char *nextBatch; + DbRef *syncRef; + HashMap *data; + + if (!user) + { + return NULL; + } + + nextBatch = StrRandom(16); + syncRef = DbCreate(user->db, 4, "users", user->name, "sync", nextBatch); + if (!syncRef) + { + Free(nextBatch); + return NULL; + } + + data = DbJson(syncRef); + + HashMapSet(data, "nextBatch", JsonValueString(nextBatch)); + HashMapSet(data, "invites", JsonValueArray(ArrayCreate())); + HashMapSet(data, "leaves", JsonValueArray(ArrayCreate())); + HashMapSet(data, "joins", JsonValueObject(HashMapCreate())); + + DbUnlock(user->db, syncRef); + + return nextBatch; +} + +void +UserPushInviteSync(User *user, char *roomId) +{ + DbRef *syncRef; + HashMap *data; + Array *entries; + Array *invites; + size_t i; + if (!user || !roomId) + { + return; + } + + entries = DbList(user->db, 3, "users", user->name, "sync"); + for (i = 0; i < ArraySize(entries); i++) + { + char *entry = ArrayGet(entries, i); + syncRef = DbLock(user->db, 4, "users", user->name, "sync", entry); + data = DbJson(syncRef); + invites = JsonValueAsArray(HashMapGet(data, "invites")); + + ArrayAdd(invites, JsonValueString(roomId)); + + DbUnlock(user->db, syncRef); + } + DbListFree(entries); +} +void +UserPushJoinSync(User *user, char *roomId) +{ + DbRef *syncRef; + HashMap *data; + Array *entries; + HashMap *join; + size_t i; + if (!user || !roomId) + { + return; + } + + entries = DbList(user->db, 3, "users", user->name, "sync"); + for (i = 0; i < ArraySize(entries); i++) + { + char *entry = ArrayGet(entries, i); + HashMap *joinEntry; + syncRef = DbLock(user->db, 4, "users", user->name, "sync", entry); + data = DbJson(syncRef); + join = JsonValueAsObject(HashMapGet(data, "joins")); + + /* TODO */ + joinEntry = HashMapCreate(); + HashMapSet(joinEntry, "timeline", JsonValueArray(ArrayCreate())); + + if (!HashMapGet(join, roomId)) + { + JsonFree(HashMapSet(join, roomId, JsonValueObject(joinEntry))); + } + else + { + JsonFree(joinEntry); + } + + DbUnlock(user->db, syncRef); + } + DbListFree(entries); +} + +void +UserPushEvent(User *user, HashMap *event) +{ + DbRef *syncRef; + HashMap *data; + Array *entries; + HashMap *join; + size_t i; + char *roomId, *eventId; + if (!user || !event) + { + return; + } + + roomId = JsonValueAsString(HashMapGet(event, "room_id")); + eventId = JsonValueAsString(HashMapGet(event, "event_id")); + + UserPushJoinSync(user, roomId); + + entries = DbList(user->db, 3, "users", user->name, "sync"); + for (i = 0; i < ArraySize(entries); i++) + { + char *entry = ArrayGet(entries, i); + HashMap *joinEntry; + Array *timeline; + syncRef = DbLock(user->db, 4, "users", user->name, "sync", entry); + data = DbJson(syncRef); + join = JsonValueAsObject(HashMapGet(data, "joins")); + + joinEntry = JsonValueAsObject(HashMapGet(join, roomId)); + timeline = JsonValueAsArray(HashMapGet(joinEntry, "timeline")); + + ArrayAdd(timeline, JsonValueString(eventId)); + + DbUnlock(user->db, syncRef); + } + DbListFree(entries); +} +void +UserDropSync(User *user, char *batch) +{ + if (!user || !batch) + { + return; + } + DbDelete(user->db, 4, "users", user->name, "sync", batch); +} diff --git a/src/include/User.h b/src/include/User.h index 632f892..f67794a 100644 --- a/src/include/User.h +++ b/src/include/User.h @@ -314,6 +314,7 @@ extern HashMap * UserGetTransaction(User *, char *, char *); */ extern void UserSetTransaction(User *, char *, char *, HashMap *); + /** * Puts a room (indexed by room ID) in a user's invite list. */ @@ -361,4 +362,30 @@ extern void UserFreeList(Array *); */ extern void UserIdFree(CommonID *); +/** + * Initialises a sync diff table, and returns a next_batch parameter, + * which is stored on the heap. + */ +extern char * UserInitSyncDiff(User *); + +/** + * Pushes an invite onto all sync diff tables. + */ +extern void UserPushInviteSync(User *, char *); + +/** + * Pushes a join onto all sync diff tables. + */ +extern void UserPushJoinSync(User *, char *); + +/** + * Pushes an event (ID) into every diff table of a user. + */ +extern void UserPushEvent(User *, HashMap *); + +/** + * Drops a sync diff, denoted by it's previous batch ID, if it + * exists. + */ +extern void UserDropSync(User *, char *); #endif /* TELODENDRIA_USER_H */