From de238538e4963174d3d9d642c24dadb717ec5288 Mon Sep 17 00:00:00 2001 From: Till Faelligen Date: Mon, 15 Nov 2021 21:30:09 +0100 Subject: [PATCH] Make "Existing members see new member's presence" pass --- build/gobind-pinecone/monolith.go | 2 +- build/gobind-yggdrasil/monolith.go | 8 ++-- cmd/dendrite-demo-libp2p/main.go | 2 +- cmd/dendrite-demo-pinecone/main.go | 3 +- cmd/dendrite-demo-yggdrasil/main.go | 2 +- cmd/dendrite-monolith-server/main.go | 4 +- federationsender/api/api.go | 3 ++ federationsender/federationsender.go | 4 +- federationsender/internal/api.go | 8 ++++ federationsender/internal/perform.go | 63 ++++++++++++++++++++++++++++ federationsender/inthttp/client.go | 3 ++ sytest-whitelist | 1 + userapi/internal/api.go | 1 + 13 files changed, 94 insertions(+), 10 deletions(-) diff --git a/build/gobind-pinecone/monolith.go b/build/gobind-pinecone/monolith.go index 21dc128c5..4bd043196 100644 --- a/build/gobind-pinecone/monolith.go +++ b/build/gobind-pinecone/monolith.go @@ -295,7 +295,7 @@ func (m *DendriteMonolith) Start() { ) fsAPI := federationsender.NewInternalAPI( - base, federation, rsAPI, keyRing, true, + base, federation, rsAPI, m.userAPI, keyRing, true, ) keyAPI := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, fsAPI) diff --git a/build/gobind-yggdrasil/monolith.go b/build/gobind-yggdrasil/monolith.go index 693e92368..558fbaee9 100644 --- a/build/gobind-yggdrasil/monolith.go +++ b/build/gobind-yggdrasil/monolith.go @@ -115,14 +115,14 @@ func (m *DendriteMonolith) Start() { base, keyRing, ) - fsAPI := federationsender.NewInternalAPI( - base, federation, rsAPI, keyRing, true, - ) - keyAPI := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, federation) userAPI := userapi.NewInternalAPI(accountDB, &cfg.UserAPI, cfg.Derived.ApplicationServices, keyAPI) keyAPI.SetUserAPI(userAPI) + fsAPI := federationsender.NewInternalAPI( + base, federation, rsAPI, userAPI, keyRing, true, + ) + eduInputAPI := eduserver.NewInternalAPI( base, cache.New(), userAPI, ) diff --git a/cmd/dendrite-demo-libp2p/main.go b/cmd/dendrite-demo-libp2p/main.go index 7606e418c..715cf8ce6 100644 --- a/cmd/dendrite-demo-libp2p/main.go +++ b/cmd/dendrite-demo-libp2p/main.go @@ -168,7 +168,7 @@ func main() { asAPI := appservice.NewInternalAPI(&base.Base, userAPI, rsAPI) rsAPI.SetAppserviceAPI(asAPI) fsAPI := federationsender.NewInternalAPI( - &base.Base, federation, rsAPI, keyRing, true, + &base.Base, federation, rsAPI, userAPI, keyRing, true, ) rsAPI.SetFederationSenderAPI(fsAPI) provider := newPublicRoomsProvider(base.LibP2PPubsub, rsAPI) diff --git a/cmd/dendrite-demo-pinecone/main.go b/cmd/dendrite-demo-pinecone/main.go index 60b83dc70..a4f886199 100644 --- a/cmd/dendrite-demo-pinecone/main.go +++ b/cmd/dendrite-demo-pinecone/main.go @@ -175,12 +175,13 @@ func main() { ) rsAPI := rsComponent fsAPI := federationsender.NewInternalAPI( - base, federation, rsAPI, keyRing, true, + base, federation, rsAPI, nil, keyRing, true, ) keyAPI := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, fsAPI) userAPI := userapi.NewInternalAPI(accountDB, &cfg.UserAPI, nil, keyAPI) keyAPI.SetUserAPI(userAPI) + fsAPI.SetUserAPI(userAPI) eduInputAPI := eduserver.NewInternalAPI( base, cache.New(), userAPI, diff --git a/cmd/dendrite-demo-yggdrasil/main.go b/cmd/dendrite-demo-yggdrasil/main.go index 1b5e1a51a..af7997f62 100644 --- a/cmd/dendrite-demo-yggdrasil/main.go +++ b/cmd/dendrite-demo-yggdrasil/main.go @@ -118,7 +118,7 @@ func main() { asAPI := appservice.NewInternalAPI(base, userAPI, rsAPI) rsAPI.SetAppserviceAPI(asAPI) fsAPI := federationsender.NewInternalAPI( - base, federation, rsAPI, keyRing, true, + base, federation, rsAPI, userAPI, keyRing, true, ) rsComponent.SetFederationSenderAPI(fsAPI) diff --git a/cmd/dendrite-monolith-server/main.go b/cmd/dendrite-monolith-server/main.go index ec8751df3..cec0a8af6 100644 --- a/cmd/dendrite-monolith-server/main.go +++ b/cmd/dendrite-monolith-server/main.go @@ -102,7 +102,7 @@ func main() { } fsAPI := federationsender.NewInternalAPI( - base, federation, rsAPI, keyRing, false, + base, federation, rsAPI, nil, keyRing, false, ) if base.UseHTTPAPIs { federationsender.AddInternalRoutes(base.InternalAPIMux, fsAPI) @@ -115,6 +115,8 @@ func main() { keyAPI := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, fsAPI) userAPI := userapi.NewInternalAPI(accountDB, &cfg.UserAPI, cfg.Derived.ApplicationServices, keyAPI) keyAPI.SetUserAPI(userAPI) + fsAPI.SetUserAPI(userAPI) + if traceInternal { userAPI = &uapi.UserInternalAPITrace{ Impl: userAPI, diff --git a/federationsender/api/api.go b/federationsender/api/api.go index 82cdf9d83..4ebbb3abb 100644 --- a/federationsender/api/api.go +++ b/federationsender/api/api.go @@ -6,6 +6,7 @@ import ( "time" "github.com/matrix-org/dendrite/federationsender/types" + userAPI "github.com/matrix-org/dendrite/userapi/api" "github.com/matrix-org/gomatrix" "github.com/matrix-org/gomatrixserverlib" ) @@ -40,6 +41,8 @@ func (e *FederationClientError) Error() string { type FederationSenderInternalAPI interface { FederationClient + SetUserAPI(api userAPI.UserInternalAPI) + QueryServerKeys(ctx context.Context, request *QueryServerKeysRequest, response *QueryServerKeysResponse) error // PerformDirectoryLookup looks up a remote room ID from a room alias. diff --git a/federationsender/federationsender.go b/federationsender/federationsender.go index 0732c5d38..f34a9ff06 100644 --- a/federationsender/federationsender.go +++ b/federationsender/federationsender.go @@ -26,6 +26,7 @@ import ( roomserverAPI "github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/dendrite/setup" "github.com/matrix-org/dendrite/setup/kafka" + userAPI "github.com/matrix-org/dendrite/userapi/api" "github.com/matrix-org/gomatrixserverlib" "github.com/sirupsen/logrus" ) @@ -42,6 +43,7 @@ func NewInternalAPI( base *setup.BaseDendrite, federation *gomatrixserverlib.FederationClient, rsAPI roomserverAPI.RoomserverInternalAPI, + userAPI userAPI.UserInternalAPI, keyRing *gomatrixserverlib.KeyRing, resetBlacklist bool, ) api.FederationSenderInternalAPI { @@ -95,5 +97,5 @@ func NewInternalAPI( logrus.WithError(err).Panic("failed to start key server consumer") } - return internal.NewFederationSenderInternalAPI(federationSenderDB, cfg, rsAPI, federation, keyRing, stats, queues) + return internal.NewFederationSenderInternalAPI(federationSenderDB, cfg, rsAPI, userAPI, federation, keyRing, stats, queues) } diff --git a/federationsender/internal/api.go b/federationsender/internal/api.go index 11032eda7..d8cf4afcf 100644 --- a/federationsender/internal/api.go +++ b/federationsender/internal/api.go @@ -11,6 +11,7 @@ import ( "github.com/matrix-org/dendrite/federationsender/storage" roomserverAPI "github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/dendrite/setup/config" + userAPI "github.com/matrix-org/dendrite/userapi/api" "github.com/matrix-org/gomatrix" "github.com/matrix-org/gomatrixserverlib" ) @@ -21,6 +22,7 @@ type FederationSenderInternalAPI struct { cfg *config.FederationSender statistics *statistics.Statistics rsAPI roomserverAPI.RoomserverInternalAPI + userAPI userAPI.UserInternalAPI federation *gomatrixserverlib.FederationClient keyRing *gomatrixserverlib.KeyRing queues *queue.OutgoingQueues @@ -30,6 +32,7 @@ type FederationSenderInternalAPI struct { func NewFederationSenderInternalAPI( db storage.Database, cfg *config.FederationSender, rsAPI roomserverAPI.RoomserverInternalAPI, + userAPI userAPI.UserInternalAPI, federation *gomatrixserverlib.FederationClient, keyRing *gomatrixserverlib.KeyRing, statistics *statistics.Statistics, @@ -39,6 +42,7 @@ func NewFederationSenderInternalAPI( db: db, cfg: cfg, rsAPI: rsAPI, + userAPI: userAPI, federation: federation, keyRing: keyRing, statistics: statistics, @@ -46,6 +50,10 @@ func NewFederationSenderInternalAPI( } } +func (f *FederationSenderInternalAPI) SetUserAPI(userAPI userAPI.UserInternalAPI) { + f.userAPI = userAPI +} + func (a *FederationSenderInternalAPI) isBlacklistedOrBackingOff(s gomatrixserverlib.ServerName) (*statistics.ServerStatistics, error) { stats := a.statistics.ForServer(s) until, blacklisted := stats.BackoffInfo() diff --git a/federationsender/internal/perform.go b/federationsender/internal/perform.go index 53fa974b2..afe4517b6 100644 --- a/federationsender/internal/perform.go +++ b/federationsender/internal/perform.go @@ -7,9 +7,11 @@ import ( "fmt" "time" + eduserverAPI "github.com/matrix-org/dendrite/eduserver/api" "github.com/matrix-org/dendrite/federationsender/api" roomserverAPI "github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/dendrite/roomserver/version" + userAPI "github.com/matrix-org/dendrite/userapi/api" "github.com/matrix-org/gomatrix" "github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/util" @@ -103,6 +105,11 @@ func (r *FederationSenderInternalAPI) PerformJoin( continue } + // once we successfully joined a remote room, send available presence data to it + if err := r.sendPresenceData(ctx, request.RoomID, serverName); err != nil { + lastErr = err + } + // We're all good. response.JoinedVia = serverName return @@ -132,6 +139,62 @@ func (r *FederationSenderInternalAPI) PerformJoin( ) } +// sendPresenceData sends presence data for a given roomID +func (r *FederationSenderInternalAPI) sendPresenceData( + ctx context.Context, roomID string, serverName gomatrixserverlib.ServerName, +) (err error) { + // query current presence for users + memberShip := roomserverAPI.QueryMembershipsForRoomResponse{} + if err := r.rsAPI.QueryMembershipsForRoom(ctx, &roomserverAPI.QueryMembershipsForRoomRequest{RoomID: roomID, JoinedOnly: true}, &memberShip); err != nil { + logrus.WithError(err).WithFields(logrus.Fields{ + "server_name": serverName, + "room_id": roomID, + }).Warnf("Failed to query membership for room") + return err + } + + content := eduserverAPI.FederationPresenceData{} + for _, event := range memberShip.JoinEvents { + // only send presence events which originated from us + _, senderServerName, err := gomatrixserverlib.SplitID('@', event.Sender) + if err != nil { + continue + } + if senderServerName != r.cfg.Matrix.ServerName { + continue + } + var presence userAPI.QueryPresenceForUserResponse + if err := r.userAPI.QueryPresenceForUser(ctx, &userAPI.QueryPresenceForUserRequest{UserID: event.Sender}, &presence); err != nil { + logrus.WithError(err).WithFields(logrus.Fields{ + "server_name": serverName, + "room_id": roomID, + }).Warnf("Failed query presence for user") + continue + } + + lastActiveTS := time.Since(presence.LastActiveTS.Time()) + ev := eduserverAPI.FederationPresenceSingle{ + CurrentlyActive: lastActiveTS < time.Minute*5, + LastActiveAgo: int(lastActiveTS.Milliseconds()), + Presence: presence.Presence, + UserID: presence.UserID, + StatusMsg: presence.StatusMsg, + } + content.Push = append(content.Push, ev) + } + + edu := &gomatrixserverlib.EDU{ + Type: gomatrixserverlib.MPresence, + Origin: string(r.cfg.Matrix.ServerName), + } + + if edu.Content, err = json.Marshal(content); err != nil { + return err + } + + return r.queues.SendEDU(edu, r.cfg.Matrix.ServerName, []gomatrixserverlib.ServerName{serverName}) +} + func (r *FederationSenderInternalAPI) performJoinUsingServer( ctx context.Context, roomID, userID string, diff --git a/federationsender/inthttp/client.go b/federationsender/inthttp/client.go index f08e610ae..6420909ce 100644 --- a/federationsender/inthttp/client.go +++ b/federationsender/inthttp/client.go @@ -7,6 +7,7 @@ import ( "github.com/matrix-org/dendrite/federationsender/api" "github.com/matrix-org/dendrite/internal/httputil" + userAPI "github.com/matrix-org/dendrite/userapi/api" "github.com/matrix-org/gomatrix" "github.com/matrix-org/gomatrixserverlib" "github.com/opentracing/opentracing-go" @@ -51,6 +52,8 @@ type httpFederationSenderInternalAPI struct { httpClient *http.Client } +func (f *httpFederationSenderInternalAPI) SetUserAPI(userAPI userAPI.UserInternalAPI) {} + // Handle an instruction to make_leave & send_leave with a remote server. func (h *httpFederationSenderInternalAPI) PerformLeave( ctx context.Context, diff --git a/sytest-whitelist b/sytest-whitelist index d3cbd4878..cfbc80aa0 100644 --- a/sytest-whitelist +++ b/sytest-whitelist @@ -595,3 +595,4 @@ User can invite remote user to room with version 9 Remote user can backfill in a room with version 9 Can reject invites over federation for rooms with version 9 Can receive redactions from regular users over federation in room version 9 +Existing members see new member's presence diff --git a/userapi/internal/api.go b/userapi/internal/api.go index 62b7842d8..7a94d8898 100644 --- a/userapi/internal/api.go +++ b/userapi/internal/api.go @@ -495,6 +495,7 @@ func (a *UserInternalAPI) QueryPresenceForUser(ctx context.Context, req *api.Que res.PresenceStatus = p.Presence res.StatusMsg = p.StatusMsg res.LastActiveTS = p.LastActiveTS + res.UserID = p.UserID maxLastSeen := gomatrixserverlib.Timestamp(maxLastSeenTS) if maxLastSeen.Time().After(p.LastActiveTS.Time()) {