diff --git a/synapse/federation/federation_client.py b/synapse/federation/federation_client.py index 4c66d0d323..f68452a12a 100644 --- a/synapse/federation/federation_client.py +++ b/synapse/federation/federation_client.py @@ -146,6 +146,7 @@ class FederationClient(FederationBase): self.server_name = hs.hostname self.signing_key = hs.signing_key + self._room_prejoin_state_types = hs.config.api.room_prejoin_state # Cache mapping `event_id` to a tuple of the event itself and the `pull_origin` # (which server we pulled the event from) @@ -1354,7 +1355,7 @@ class FederationClient(FederationBase): Args: destination: - pdu: Invite event. This function assumes that `unsigned.invite_room_state` is filled in. + pdu: Invite event context: room_version: @@ -1371,35 +1372,9 @@ class FederationClient(FederationBase): # MSC4311: For the federation API, format events in `invite_room_state` as full # PDU's # - # First get all of the expected stripped state events that should be included. - # We will derive these from the `unsigned` part of the PDU which already has - # `invite_room_state` calculated but this doesn't include any event ID - # information so we need to look it up based on the state at the time of the - # invite. - # - # It would also be reasonable to use `hs.config.api.room_prejoin_state` but we - # might as well read from this source of truth to exactly match. - stripped_state_types = [] - unsigned_invite_room_state = pdu.unsigned.get("invite_room_state") - # Scrutinize untyped values - assert isinstance(unsigned_invite_room_state, list), ( - f"Expected `unsigned.invite_room_state` on event_id={pdu.event_id} to exist and be a list (found {unsigned_invite_room_state})." - "This is a Synapse programming error." - ) - for raw_stripped_event in unsigned_invite_room_state: - stripped_state_event = parse_stripped_state_event(raw_stripped_event) - # Since this is our own invite, it should always be well-formed - assert stripped_state_event is not None, ( - f"Unable to parse one of the events from the `unsigned.invite_room_state` on event_id={pdu.event_id} as a stripped state event." - ) - stripped_state_types.append( - (stripped_state_event.type, stripped_state_event.state_key) - ) - # Find the full events based on the state at the time of the invite - state_filter = StateFilter.from_types(stripped_state_types) state_ids = await self.store.get_stripped_room_state_ids_from_event_context( - context, state_filter + context, self._room_prejoin_state_types ) state_events = await self.store.get_events(state_ids) assert set(state_ids) == set(state_events.keys()), ( diff --git a/synapse/federation/federation_server.py b/synapse/federation/federation_server.py index f3e9b855d2..49263b91c7 100644 --- a/synapse/federation/federation_server.py +++ b/synapse/federation/federation_server.py @@ -57,6 +57,7 @@ from synapse.api.room_versions import KNOWN_ROOM_VERSIONS, RoomVersion from synapse.crypto.event_signing import compute_event_signature from synapse.events import EventBase from synapse.events.snapshot import EventPersistencePair +from synapse.events.utils import parse_stripped_state_event from synapse.federation.federation_base import ( FederationBase, InvalidEventSignatureError, @@ -88,6 +89,7 @@ from synapse.storage.databases.main.lock import Lock from synapse.storage.databases.main.roommember import extract_heroes_from_room_summary from synapse.storage.roommember import MemberSummary from synapse.types import JsonDict, StateMap, UserID, get_domain_from_id +from synapse.types.state import StateFilter from synapse.util import unwrapFirstError from synapse.util.async_helpers import Linearizer, concurrently_execute, gather_results from synapse.util.caches.response_cache import ResponseCache @@ -987,20 +989,31 @@ class FederationServer(FederationBase): Returns: The stripped room state. """ + time_now = self._clock.time_msec() + _, context = await self._on_send_membership_event( origin, content, Membership.KNOCK, room_id ) - # Retrieve stripped state events from the room and send them back to the remote - # server. This will allow the remote server's clients to display information - # related to the room while the knock request is pending. - stripped_room_state = ( - # TODO: Implement MSC4311 and use full PDUs here - await self.store.get_stripped_room_state_from_event_context( - context, self._room_prejoin_state_types - ) + # MSC4311: For the federation API, format events in `knock_room_state` as full + # PDU's + # + # Find the full events based on the state at the time of the knock + state_ids = await self.store.get_stripped_room_state_ids_from_event_context( + context, self._room_prejoin_state_types ) - return {"knock_room_state": stripped_room_state} + state_events = await self.store.get_events(state_ids) + assert set(state_ids) == set(state_events.keys()), ( + "We should have all events available that were set as stripped state." + ) + + return { + "knock_room_state": [ + # Use full PDU's according to MSC4311 + state_event.get_pdu_json(time_now) + for state_event in state_events.values() + ] + } async def _on_send_membership_event( self, origin: str, content: JsonDict, membership_type: str, room_id: str