diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py
index 62985bab9f..2ea69c5468 100644
--- a/synapse/handlers/federation.py
+++ b/synapse/handlers/federation.py
@@ -637,6 +637,10 @@ class FederationHandler(BaseHandler):
room_id
event_ids
+ If we fail to fetch any of the events, a warning will be logged, and the event
+ will be omitted from the result. Likewise, any events which turn out not to
+ be in the given room.
+
Returns:
map from event_id to event
"""
@@ -644,35 +648,59 @@ class FederationHandler(BaseHandler):
missing_events = set(event_ids) - fetched_events.keys()
- if not missing_events:
- return fetched_events
+ if missing_events:
+ logger.debug(
+ "Fetching unknown state/auth events %s for room %s",
+ missing_events,
+ room_id,
+ )
- logger.debug(
- "Fetching unknown state/auth events %s for room %s",
- missing_events,
- event_ids,
- )
+ room_version = await self.store.get_room_version(room_id)
- room_version = await self.store.get_room_version(room_id)
+ # XXX 20 requests at once? really?
+ for batch in batch_iter(missing_events, 20):
+ deferreds = [
+ run_in_background(
+ self.federation_client.get_pdu,
+ destinations=[destination],
+ event_id=e_id,
+ room_version=room_version,
+ )
+ for e_id in batch
+ ]
- # XXX 20 requests at once? really?
- for batch in batch_iter(missing_events, 20):
- deferreds = [
- run_in_background(
- self.federation_client.get_pdu,
- destinations=[destination],
- event_id=e_id,
- room_version=room_version,
+ res = await make_deferred_yieldable(
+ defer.DeferredList(deferreds, consumeErrors=True)
)
- for e_id in batch
- ]
- res = await make_deferred_yieldable(
- defer.DeferredList(deferreds, consumeErrors=True)
+ for success, result in res:
+ if success and result:
+ fetched_events[result.event_id] = result
+
+ # check for events which were in the wrong room.
+ #
+ # this can happen if a remote server claims that the state or
+ # auth_events at an event in room A are actually events in room B
+
+ bad_events = list(
+ (event_id, event.room_id)
+ for event_id, event in fetched_events.items()
+ if event.room_id != room_id
+ )
+
+ for bad_event_id, bad_room_id in bad_events:
+ # This is a bogus situation, but since we may only discover it a long time
+ # after it happened, we try our best to carry on, by just omitting the
+ # bad events from the returned auth/state set.
+ logger.warning(
+ "Remote server %s claims event %s in room %s is an auth/state "
+ "event in room %s",
+ destination,
+ bad_event_id,
+ bad_room_id,
+ room_id,
)
- for success, result in res:
- if success and result:
- fetched_events[result.event_id] = result
+ del fetched_events[bad_event_id]
return fetched_events
|