Bugfixes for 'If remote user leaves room we no longer receive device updates' (#1262)

* Bugfixes for 'If remote user leaves room we no longer receive device updates'

* Update whitelist and README
main
Kegsay 2020-08-12 10:50:52 +01:00 committed by GitHub
parent bcdf9577a3
commit b8b854d642
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 34 additions and 15 deletions

View File

@ -33,7 +33,7 @@ Then point your favourite Matrix client at `http://localhost:8008`. For full ins
We use a script called Are We Synapse Yet which checks Sytest compliance rates. Sytest is a black-box homeserver
test rig with around 900 tests. The script works out how many of these tests are passing on Dendrite and it
updates with CI. As of July 2020 we're at around 48% CS API coverage and 50% Federation coverage, though check
updates with CI. As of August 2020 we're at around 52% CS API coverage and 65% Federation coverage, though check
CI for the latest numbers. In practice, this means you can communicate locally and via federation with Synapse
servers such as matrix.org reasonably well. There's a long list of features that are not implemented, notably:
- Receipts
@ -42,7 +42,6 @@ servers such as matrix.org reasonably well. There's a long list of features that
- User Directory
- Presence
- Guests
- E2E keys and device lists
We are prioritising features that will benefit single-user homeservers first (e.g Receipts, E2E) rather
than features that massive deployments may be interested in (User Directory, OpenID, Guests, Admin APIs, AS API).
@ -56,6 +55,7 @@ This means Dendrite supports amongst others:
- Media APIs
- Redaction
- Tagging
- E2E keys and device lists
# Contributing

View File

@ -831,6 +831,7 @@ psh Trying to get push rules with unknown scope fails with 400
psh Trying to get push rules with unknown template fails with 400
psh Trying to get push rules with unknown attribute fails with 400
psh Trying to get push rules with unknown rule_id fails with 404
psh Rooms with names are correctly named in pushes
v1s GET /initialSync with non-numeric 'limit'
v1s GET /events with non-numeric 'limit'
v1s GET /events with negative 'limit'
@ -839,7 +840,7 @@ ath Event size limits
syn Check creating invalid filters returns 4xx
f,pre New federated private chats get full presence information (SYN-115)
pre Left room members do not cause problems for presence
crm Rooms can be created with an initial invite list (SYN-205)
crm Rooms can be created with an initial invite list (SYN-205) (1 subtests)
typ Typing notifications don't leak
ban Non-present room members cannot ban others
psh Getting push rules doesn't corrupt the cache SYN-390

View File

@ -230,6 +230,7 @@ func (u *DeviceListUpdater) worker(ch chan gomatrixserverlib.ServerName) {
}
// on failure, spin up a short-lived goroutine to inject the server name again.
scheduledRetries := make(map[gomatrixserverlib.ServerName]time.Time)
inject := func(srv gomatrixserverlib.ServerName, duration time.Duration) {
time.Sleep(duration)
ch <- srv
@ -237,13 +238,20 @@ func (u *DeviceListUpdater) worker(ch chan gomatrixserverlib.ServerName) {
for serverName := range ch {
if !shouldProcess(serverName) {
// do not inject into the channel as we know there will be a sleeping goroutine
// which will do it after the cooloff period expires
continue
if time.Now().Before(scheduledRetries[serverName]) {
// do not inject into the channel as we know there will be a sleeping goroutine
// which will do it after the cooloff period expires
continue
} else {
scheduledRetries[serverName] = time.Now().Add(cooloffPeriod)
go inject(serverName, cooloffPeriod) // TODO: Backoff?
continue
}
}
lastProcessed[serverName] = time.Now()
shouldRetry := u.processServer(serverName)
if shouldRetry {
scheduledRetries[serverName] = time.Now().Add(cooloffPeriod)
go inject(serverName, cooloffPeriod) // TODO: Backoff?
}
}

View File

@ -96,7 +96,8 @@ func DeviceListCatchup(
return hasNew, nil
}
// QueryKeyChanges gets ALL users who have changed keys, we want the ones who share rooms with the user.
queryRes.UserIDs = filterSharedUsers(ctx, stateAPI, userID, queryRes.UserIDs)
var sharedUsersMap map[string]int
sharedUsersMap, queryRes.UserIDs = filterSharedUsers(ctx, stateAPI, userID, queryRes.UserIDs)
util.GetLogger(ctx).Debugf(
"QueryKeyChanges request p=%d,off=%d,to=%d response p=%d off=%d uids=%v",
partition, offset, toOffset, queryRes.Partition, queryRes.Offset, queryRes.UserIDs,
@ -114,13 +115,20 @@ func DeviceListCatchup(
}
// if the response has any join/leave events, add them now.
// TODO: This is sub-optimal because we will add users to `changed` even if we already shared a room with them.
for _, userID := range membershipEvents(res) {
joinUserIDs, leaveUserIDs := membershipEvents(res)
for _, userID := range joinUserIDs {
if !userSet[userID] {
res.DeviceLists.Changed = append(res.DeviceLists.Changed, userID)
hasNew = true
userSet[userID] = true
}
}
for _, userID := range leaveUserIDs {
if sharedUsersMap[userID] == 0 {
// we no longer share a room with this user when they left, so add to left list.
res.DeviceLists.Left = append(res.DeviceLists.Left, userID)
}
}
// set the new token
to.SetLog(DeviceListLogName, &types.LogPosition{
Partition: queryRes.Partition,
@ -221,7 +229,7 @@ func TrackChangedUsers(
func filterSharedUsers(
ctx context.Context, stateAPI currentstateAPI.CurrentStateInternalAPI, userID string, usersWithChangedKeys []string,
) []string {
) (map[string]int, []string) {
var result []string
var sharedUsersRes currentstateAPI.QuerySharedUsersResponse
err := stateAPI.QuerySharedUsers(ctx, &currentstateAPI.QuerySharedUsersRequest{
@ -229,7 +237,7 @@ func filterSharedUsers(
}, &sharedUsersRes)
if err != nil {
// default to all users so we do needless queries rather than miss some important device update
return usersWithChangedKeys
return nil, usersWithChangedKeys
}
// We forcibly put ourselves in this list because we should be notified about our own device updates
// and if we are in 0 rooms then we don't technically share any room with ourselves so we wouldn't
@ -241,7 +249,7 @@ func filterSharedUsers(
result = append(result, uid)
}
}
return result
return sharedUsersRes.UserIDsToCount, result
}
func joinedRooms(res *types.Response, userID string) []string {
@ -288,16 +296,16 @@ func membershipEventPresent(events []gomatrixserverlib.ClientEvent, userID strin
// "For optimal performance, Alice should be added to changed in Bob's sync only when she adds a new device,
// or when Alice and Bob now share a room but didn't share any room previously. However, for the sake of simpler
// logic, a server may add Alice to changed when Alice and Bob share a new room, even if they previously already shared a room."
func membershipEvents(res *types.Response) (userIDs []string) {
func membershipEvents(res *types.Response) (joinUserIDs, leaveUserIDs []string) {
for _, room := range res.Rooms.Join {
for _, ev := range room.Timeline.Events {
if ev.Type == gomatrixserverlib.MRoomMember && ev.StateKey != nil {
if strings.Contains(string(ev.Content), `"join"`) {
userIDs = append(userIDs, *ev.StateKey)
joinUserIDs = append(joinUserIDs, *ev.StateKey)
} else if strings.Contains(string(ev.Content), `"leave"`) {
userIDs = append(userIDs, *ev.StateKey)
leaveUserIDs = append(leaveUserIDs, *ev.StateKey)
} else if strings.Contains(string(ev.Content), `"ban"`) {
userIDs = append(userIDs, *ev.StateKey)
leaveUserIDs = append(leaveUserIDs, *ev.StateKey)
}
}
}

View File

@ -142,6 +142,8 @@ Server correctly handles incoming m.device_list_update
Device deletion propagates over federation
If remote user leaves room, changes device and rejoins we see update in sync
If remote user leaves room, changes device and rejoins we see update in /keys/changes
If remote user leaves room we no longer receive device updates
Get left notifs in sync and /keys/changes when other user leaves
Can query remote device keys using POST after notification
Can add account data
Can add account data to room