From cf76cfe4ebdda930ad37f41f78daf9cfc6f28e87 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Mon, 28 Sep 2020 12:51:39 +0100 Subject: [PATCH] Try to ask other servers in the room for missing events if the origin won't provide them --- federationapi/routing/send.go | 56 ++++++++++++++++++++---------- roomserver/api/query.go | 2 ++ roomserver/internal/query/query.go | 7 +++- 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/federationapi/routing/send.go b/federationapi/routing/send.go index 5f20b2d8e..66ef0c031 100644 --- a/federationapi/routing/send.go +++ b/federationapi/routing/send.go @@ -637,15 +637,43 @@ func (t *txnReq) getMissingEvents(ctx context.Context, e gomatrixserverlib.Event if minDepth < 0 { minDepth = 0 } - missingResp, err := t.federation.LookupMissingEvents(ctx, t.Origin, e.RoomID(), gomatrixserverlib.MissingEvents{ - Limit: 20, - // synapse uses the min depth they've ever seen in that room - MinDepth: minDepth, - // The latest event IDs that the sender already has. These are skipped when retrieving the previous events of latest_events. - EarliestEvents: latestEvents, - // The event IDs to retrieve the previous events for. - LatestEvents: []string{e.EventID()}, - }, roomVersion) + + servers := []gomatrixserverlib.ServerName{t.Origin} + serverReq := &api.QueryServerJoinedToRoomRequest{ + RoomID: e.RoomID(), + } + serverRes := &api.QueryServerJoinedToRoomResponse{} + if err = t.rsAPI.QueryServerJoinedToRoom(ctx, serverReq, serverRes); err == nil { + servers = append(servers, serverRes.ServerNames...) + } + + var missingResp *gomatrixserverlib.RespMissingEvents + for _, server := range servers { + var m gomatrixserverlib.RespMissingEvents + if m, err = t.federation.LookupMissingEvents(ctx, server, e.RoomID(), gomatrixserverlib.MissingEvents{ + Limit: 20, + // synapse uses the min depth they've ever seen in that room + MinDepth: minDepth, + // The latest event IDs that the sender already has. These are skipped when retrieving the previous events of latest_events. + EarliestEvents: latestEvents, + // The event IDs to retrieve the previous events for. + LatestEvents: []string{e.EventID()}, + }, roomVersion); err == nil { + missingResp = &m + break + } + } + + if missingResp == nil { + logger.WithError(err).Errorf( + "%s pushed us an event but %d server(s) couldn't give us details about prev_events via /get_missing_events - dropping this event until it can", + len(servers), t.Origin, + ) + return nil, missingPrevEventsError{ + eventID: e.EventID(), + err: err, + } + } // security: how we handle failures depends on whether or not this event will become the new forward extremity for the room. // There's 2 scenarios to consider: @@ -658,16 +686,6 @@ func (t *txnReq) getMissingEvents(ctx context.Context, e gomatrixserverlib.Event // https://github.com/matrix-org/synapse/pull/3456 // https://github.com/matrix-org/synapse/blob/229eb81498b0fe1da81e9b5b333a0285acde9446/synapse/handlers/federation.py#L335 // For now, we do not allow Case B, so reject the event. - if err != nil { - logger.WithError(err).Errorf( - "%s pushed us an event but couldn't give us details about prev_events via /get_missing_events - dropping this event until it can", - t.Origin, - ) - return nil, missingPrevEventsError{ - eventID: e.EventID(), - err: err, - } - } logger.Infof("get_missing_events returned %d events", len(missingResp.Events)) // topologically sort and sanity check that we are making forward progress diff --git a/roomserver/api/query.go b/roomserver/api/query.go index 5d61e862c..ba1a702be 100644 --- a/roomserver/api/query.go +++ b/roomserver/api/query.go @@ -154,6 +154,8 @@ type QueryServerJoinedToRoomResponse struct { RoomExists bool `json:"room_exists"` // True if we still believe that we are participating in the room IsInRoom bool `json:"is_in_room"` + // List of servers that are also in the room + ServerNames []gomatrixserverlib.ServerName `json:"server_names"` } // QueryServerAllowedToSeeEventRequest is a request to QueryServerAllowedToSeeEvent diff --git a/roomserver/internal/query/query.go b/roomserver/internal/query/query.go index 58cb44933..aa2e36165 100644 --- a/roomserver/internal/query/query.go +++ b/roomserver/internal/query/query.go @@ -255,19 +255,24 @@ func (r *Queryer) QueryServerJoinedToRoom( return fmt.Errorf("r.DB.Events: %w", err) } + servers := map[gomatrixserverlib.ServerName]struct{}{} for _, e := range events { if e.Type() == gomatrixserverlib.MRoomMember && e.StateKey() != nil { _, serverName, err := gomatrixserverlib.SplitID('@', *e.StateKey()) if err != nil { continue } + servers[serverName] = struct{}{} if serverName == request.ServerName { response.IsInRoom = true - break } } } + for server := range servers { + response.ServerNames = append(response.ServerNames, server) + } + return nil }