From fde6f092b4e1aa1eca8af10c94bdc5e83d83fd77 Mon Sep 17 00:00:00 2001 From: LDA Date: Fri, 23 Aug 2024 21:03:55 +0200 Subject: [PATCH] [MOD] Cleanup code a bit, more status hjinks! More work! --- src/Room.c | 54 ++++++++++++++++++++++++++++++----------------------- src/State.c | 13 ++++++++++--- 2 files changed, 41 insertions(+), 26 deletions(-) diff --git a/src/Room.c b/src/Room.c index e9ab1ce..9ccf416 100644 --- a/src/Room.c +++ b/src/Room.c @@ -1677,7 +1677,7 @@ RoomEventSendV1(Room * room, HashMap * event) pdu.hashes.sha256 = RoomHashEventV1(pdu); #undef AddState } - /* TODO: It seems like we need to behave differently in terms of + /* It seems like we need to behave differently in terms of * verifying PDUs from the client/federation. * - In the client, we just do not care about any events that * are incorrect. We simply drop them, as if they never existed. @@ -1703,16 +1703,17 @@ RoomEventSendV1(Room * room, HashMap * event) /* TODO: For PDU events, we should verify their hashes. */ status = RoomGetEventStatusV1(room, &pdu, state, client_event); - Log(LOG_INFO, "status='%s'", PduV1StatusToStr(status)); + Log(LOG_DEBUG, "status='%s'", PduV1StatusToStr(status)); if (status == PDUV1_STATUS_DROPPED) { goto finish; } - StateFree(state); - state = NULL; pdu._unsigned.pdu_status = status; + StateFree(state); + RoomAddEventV1(room, pdu); + state = NULL; valid = true; /* If it is a client event, we should make sure that we shout at @@ -1838,18 +1839,31 @@ RoomAddEventV1(Room *room, PduV1 pdu) char *safe_id; size_t i; - if (!room || room->version >= 3) + if (!room || room->version >= 3 || + pdu._unsigned.pdu_status == PDUV1_STATUS_DROPPED) { return false; } + /* Insert our PDU into the event table, regardless of status */ + safe_id = CreateSafeID(pdu.event_id); + event_ref = DbCreate(room->db, 4, "rooms", room->id, "events", safe_id); + pdu_json = PduV1ToJson(&pdu); + + DbJsonSet(event_ref, pdu_json); + + DbUnlock(room->db, event_ref); + JsonFree(pdu_json); + Free(safe_id); + /* Only accepted PDUs get to do the news */ if (pdu._unsigned.pdu_status == PDUV1_STATUS_ACCEPTED) { + /* Remove managed leaves here. */ leaves_json = DbJson(room->leaves_ref); leaves_val = JsonValueDuplicate(JsonGet(leaves_json, 1, "leaves")); leaves = JsonValueAsArray(leaves_val); - Free(leaves_val); + Free(leaves_val); /* We do not care about the array's JSON shell. */ prev_events = pdu.prev_events; for (i = 0; i < ArraySize(prev_events); i++) @@ -1878,19 +1892,9 @@ RoomAddEventV1(Room *room, PduV1 pdu) } 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); - - /* Only accepted PDUs get to do the news */ - if (pdu._unsigned.pdu_status == PDUV1_STATUS_ACCEPTED) - { - ArrayAdd(leaves, JsonValueObject(pdu_json)); + /* Add our current PDU to the leaves. */ + ArrayAdd(leaves, JsonValueObject(PduV1ToJson(&pdu))); leaves_json = JsonDuplicate(leaves_json); JsonValueFree(HashMapDelete(leaves_json, "leaves")); JsonSet(leaves_json, JsonValueArray(leaves), 1, "leaves"); @@ -1898,8 +1902,6 @@ RoomAddEventV1(Room *room, PduV1 pdu) JsonFree(leaves_json); } - DbUnlock(room->db, event_ref); - for (i = 0; i < ArraySize(prev_events); i++) { JsonValue *event_val = ArrayGet(prev_events, i); @@ -1911,6 +1913,8 @@ RoomAddEventV1(Room *room, PduV1 pdu) event_ref = DbLock(room->db, 4, "rooms", room->id, "events", id); PduV1FromJson(DbJson(event_ref), &prev_pdu, &error); + /* Update the next events view. Note that this works even if + * the event is soft-failed/rejected. */ if (!prev_pdu._unsigned.next_events) { prev_pdu._unsigned.next_events = ArrayCreate(); @@ -1927,12 +1931,17 @@ RoomAddEventV1(Room *room, PduV1 pdu) DbUnlock(room->db, event_ref); } + /* Accepted PDUs should be the only one that users should be + * notified about. */ + if (pdu._unsigned.pdu_status == PDUV1_STATUS_ACCEPTED) { State *state; char *type, *state_key, *event_id; pdu_json = PduV1ToJson(&pdu); + /* If we have a membership change, then add it to the + * proper table. */ if (StrEquals(pdu.type, "m.room.member")) { CommonID *id = UserIdParse(pdu.state_key, NULL); @@ -1961,6 +1970,8 @@ RoomAddEventV1(Room *room, PduV1 pdu) UserIdFree(id); UserUnlock(user); } + + /* Notify the user by pushing out the user */ state = StateCurrent(room); while (StateIterate(state, &type, &state_key, (void **) &event_id)) { @@ -1978,7 +1989,6 @@ RoomAddEventV1(Room *room, PduV1 pdu) Free(state_key); } StateFree(state); - JsonFree(pdu_json); } @@ -2038,8 +2048,6 @@ RoomGetDepth(Room *room) max = depth; } } - (void) i; - (void) pdu; return max; } diff --git a/src/State.c b/src/State.c index a0ca473..2ef3f6f 100644 --- a/src/State.c +++ b/src/State.c @@ -335,6 +335,14 @@ StateFromPrevs(Room *room, Array *states) } } +static bool +IsRejected(HashMap *pdu) +{ + JsonValue *val = JsonGet(pdu, 2, "unsigned", "status"); + + return StrEquals(JsonValueAsString(val), "rejected"); +} + State * StateResolve(Room * room, HashMap * event) { @@ -354,7 +362,6 @@ StateResolve(Room * room, HashMap * event) return NULL; } - /* TODO: Return cached state if it exists */ db = RoomGetDB(room); room_id = JsonValueAsString(HashMapGet(event, "room_id")); event_id = JsonValueAsString(HashMapGet(event, "event_id")); @@ -388,7 +395,7 @@ StateResolve(Room * room, HashMap * event) RoomEventFetch(room, JsonValueAsString(ArrayGet(prevEvents, i))); State *state = StateResolve(room, prevEvent); - if (HashMapGet(prevEvent, "state_key")) + if (HashMapGet(prevEvent, "state_key") && !IsRejected(prevEvent)) { StateSet( state, @@ -442,7 +449,7 @@ StateCurrent(Room *room) JsonValueAsObject(ArrayGet(prevEvents, i)); State *state = StateResolve(room, event); - if (HashMapGet(event, "state_key")) + if (HashMapGet(event, "state_key") && !IsRejected(event)) { StateSet( state,