2017-04-20 23:40:52 +01:00
// Copyright 2017 Vector Creations Ltd
2020-02-05 18:06:39 +00:00
// Copyright 2018 New Vector Ltd
// Copyright 2019-2020 The Matrix.org Foundation C.I.C.
2017-04-20 23:40:52 +01:00
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2020-05-01 10:48:17 +01:00
package internal
2017-02-07 17:20:05 +00:00
import (
2017-09-13 16:30:19 +01:00
"context"
Improve federation sender performance, implement backoff and blacklisting, fix up invites a bit (#1007)
* Improve federation sender performance and behaviour, add backoff
* Tweaks
* Tweaks
* Tweaks
* Take copies of events before passing to destination queues
* Don't accidentally drop queued messages
* Don't take copies again
* Tidy up a bit
* Break out statistics (tracked component-wide), report success and failures from Perform actions
* Fix comment, use atomic add
* Improve logic a bit, don't block on wakeup, move idle check
* Don't retry sucessful invites, don't dispatch sendEvent, sendInvite etc
* Dedupe destinations, fix other bug hopefully
* Dispatch sends again
* Federation sender to ignore invites that are destined locally
* Loopback invite events
* Remodel a bit with channels
* Linter
* Only loopback invite event if we know the room
* We should tell other resident servers about the invite if we know about the room
* Correct invite signing
* Fix invite loopback
* Check HTTP response codes, push new invites to front of queue
* Review comments
2020-05-07 12:42:06 +01:00
"errors"
2017-08-21 16:37:11 +01:00
"fmt"
"github.com/matrix-org/dendrite/common"
2017-02-07 17:20:05 +00:00
"github.com/matrix-org/dendrite/roomserver/api"
2017-03-08 15:10:26 +00:00
"github.com/matrix-org/dendrite/roomserver/state"
2020-04-24 10:38:58 +01:00
"github.com/matrix-org/dendrite/roomserver/storage"
2017-02-09 16:48:14 +00:00
"github.com/matrix-org/dendrite/roomserver/types"
2017-02-07 17:20:05 +00:00
"github.com/matrix-org/gomatrixserverlib"
2020-04-28 11:46:47 +01:00
"github.com/sirupsen/logrus"
2020-04-03 14:29:06 +01:00
log "github.com/sirupsen/logrus"
2017-02-07 17:20:05 +00:00
)
2017-12-15 15:22:06 +00:00
// processRoomEvent can only be called once at a time
//
// TODO(#375): This should be rewritten to allow concurrent calls. The
// difficulty is in ensuring that we correctly annotate events with the correct
// state deltas when sending to kafka streams
2020-05-20 18:03:06 +01:00
func ( r * RoomserverInternalAPI ) processRoomEvent (
2017-09-13 16:30:19 +01:00
ctx context . Context ,
input api . InputRoomEvent ,
2018-05-26 12:03:35 +01:00
) ( eventID string , err error ) {
2017-02-07 17:20:05 +00:00
// Parse and validate the event JSON
2020-03-27 16:28:22 +00:00
headered := input . Event
event := headered . Unwrap ( )
2017-02-07 17:20:05 +00:00
2020-05-18 17:49:24 +01:00
// Check that the event passes authentication checks and work out
// the numeric IDs for the auth events.
2020-05-20 18:03:06 +01:00
authEventNIDs , err := checkAuthEvents ( ctx , r . DB , headered , input . AuthEventIDs )
2017-02-09 16:48:14 +00:00
if err != nil {
2020-05-12 16:24:28 +01:00
logrus . WithError ( err ) . WithField ( "event_id" , event . EventID ( ) ) . WithField ( "auth_event_ids" , input . AuthEventIDs ) . Error ( "processRoomEvent.checkAuthEvents failed for event" )
2018-05-26 12:03:35 +01:00
return
}
2020-05-18 17:49:24 +01:00
// If we don't have a transaction ID then get one.
2018-05-26 12:03:35 +01:00
if input . TransactionID != nil {
tdID := input . TransactionID
2020-05-20 18:03:06 +01:00
eventID , err = r . DB . GetTransactionEventID (
2020-03-27 16:28:22 +00:00
ctx , tdID . TransactionID , tdID . SessionID , event . Sender ( ) ,
2018-05-26 12:03:35 +01:00
)
// On error OR event with the transaction already processed/processesing
if err != nil || eventID != "" {
return
}
2017-02-07 17:20:05 +00:00
}
2020-05-18 17:49:24 +01:00
// Store the event.
2020-05-20 18:03:06 +01:00
roomNID , stateAtEvent , err := r . DB . StoreEvent ( ctx , event , input . TransactionID , authEventNIDs )
2017-02-15 11:05:45 +00:00
if err != nil {
2018-05-26 12:03:35 +01:00
return
2017-02-09 16:48:14 +00:00
}
2017-02-07 17:20:05 +00:00
2020-05-18 17:49:24 +01:00
// For outliers we can stop after we've stored the event itself as it
// doesn't have any associated state to store and we don't need to
// notify anyone about it.
2017-02-07 17:20:05 +00:00
if input . Kind == api . KindOutlier {
2020-05-18 17:49:24 +01:00
logrus . WithFields ( logrus . Fields {
"event_id" : event . EventID ( ) ,
"type" : event . Type ( ) ,
"room" : event . RoomID ( ) ,
} ) . Info ( "Stored outlier" )
2018-05-26 12:03:35 +01:00
return event . EventID ( ) , nil
2017-02-07 17:20:05 +00:00
}
2017-02-15 11:05:45 +00:00
if stateAtEvent . BeforeStateSnapshotNID == 0 {
// We haven't calculated a state for this event yet.
// Lets calculate one.
2020-05-20 18:03:06 +01:00
err = r . calculateAndSetState ( ctx , input , roomNID , & stateAtEvent , event )
2017-09-20 10:59:19 +01:00
if err != nil {
2018-05-26 12:03:35 +01:00
return
2017-09-20 10:59:19 +01:00
}
2017-02-15 11:05:45 +00:00
}
2020-05-20 18:03:06 +01:00
if err = r . updateLatestEvents (
2020-05-18 17:49:24 +01:00
ctx , // context
roomNID , // room NID to update
stateAtEvent , // state at event (below)
event , // event
input . SendAsServer , // send as server
input . TransactionID , // transaction ID
) ; err != nil {
return
}
2017-02-21 14:50:30 +00:00
// Update the extremities of the event graph for the room
2020-05-18 17:49:24 +01:00
return event . EventID ( ) , nil
2018-05-26 12:03:35 +01:00
}
2020-05-20 18:03:06 +01:00
func ( r * RoomserverInternalAPI ) calculateAndSetState (
2018-05-26 12:03:35 +01:00
ctx context . Context ,
input api . InputRoomEvent ,
roomNID types . RoomNID ,
stateAtEvent * types . StateAtEvent ,
event gomatrixserverlib . Event ,
) error {
2020-03-19 18:33:04 +00:00
var err error
2020-05-20 18:03:06 +01:00
roomState := state . NewStateResolution ( r . DB )
2020-02-05 16:25:58 +00:00
2018-05-26 12:03:35 +01:00
if input . HasState {
2020-05-20 18:03:06 +01:00
// Check here if we think we're in the room already.
2020-05-18 17:49:24 +01:00
stateAtEvent . Overwrite = true
2020-05-20 18:03:06 +01:00
var joinEventNIDs [ ] types . EventNID
// Request join memberships only for local users only.
if joinEventNIDs , err = r . DB . GetMembershipEventNIDsForRoom ( ctx , roomNID , true , true ) ; err == nil {
// If we have no local users that are joined to the room then any state about
// the room that we have is quite possibly out of date. Therefore in that case
// we should overwrite it rather than merge it.
stateAtEvent . Overwrite = len ( joinEventNIDs ) == 0
}
2020-05-18 17:49:24 +01:00
2018-05-26 12:03:35 +01:00
// We've been told what the state at the event is so we don't need to calculate it.
// Check that those state events are in the database and store the state.
var entries [ ] types . StateEntry
2020-05-20 18:03:06 +01:00
if entries , err = r . DB . StateEntriesForEventIDs ( ctx , input . StateEventIDs ) ; err != nil {
2018-05-26 12:03:35 +01:00
return err
}
2020-05-20 18:03:06 +01:00
if stateAtEvent . BeforeStateSnapshotNID , err = r . DB . AddState ( ctx , roomNID , nil , entries ) ; err != nil {
2018-05-26 12:03:35 +01:00
return err
}
} else {
2020-05-18 17:49:24 +01:00
stateAtEvent . Overwrite = false
2018-05-26 12:03:35 +01:00
// We haven't been told what the state at the event is so we need to calculate it from the prev_events
2020-02-05 18:06:39 +00:00
if stateAtEvent . BeforeStateSnapshotNID , err = roomState . CalculateAndStoreStateBeforeEvent ( ctx , event , roomNID ) ; err != nil {
2018-05-26 12:03:35 +01:00
return err
}
}
2020-05-20 18:03:06 +01:00
return r . DB . SetState ( ctx , stateAtEvent . EventNID , stateAtEvent . BeforeStateSnapshotNID )
2017-08-21 16:37:11 +01:00
}
2020-05-20 18:03:06 +01:00
func ( r * RoomserverInternalAPI ) processInviteEvent (
2017-09-13 16:30:19 +01:00
ctx context . Context ,
Improve federation sender performance, implement backoff and blacklisting, fix up invites a bit (#1007)
* Improve federation sender performance and behaviour, add backoff
* Tweaks
* Tweaks
* Tweaks
* Take copies of events before passing to destination queues
* Don't accidentally drop queued messages
* Don't take copies again
* Tidy up a bit
* Break out statistics (tracked component-wide), report success and failures from Perform actions
* Fix comment, use atomic add
* Improve logic a bit, don't block on wakeup, move idle check
* Don't retry sucessful invites, don't dispatch sendEvent, sendInvite etc
* Dedupe destinations, fix other bug hopefully
* Dispatch sends again
* Federation sender to ignore invites that are destined locally
* Loopback invite events
* Remodel a bit with channels
* Linter
* Only loopback invite event if we know the room
* We should tell other resident servers about the invite if we know about the room
* Correct invite signing
* Fix invite loopback
* Check HTTP response codes, push new invites to front of queue
* Review comments
2020-05-07 12:42:06 +01:00
ow * RoomserverInternalAPI ,
2017-09-13 16:30:19 +01:00
input api . InputInviteEvent ,
Improve federation sender performance, implement backoff and blacklisting, fix up invites a bit (#1007)
* Improve federation sender performance and behaviour, add backoff
* Tweaks
* Tweaks
* Tweaks
* Take copies of events before passing to destination queues
* Don't accidentally drop queued messages
* Don't take copies again
* Tidy up a bit
* Break out statistics (tracked component-wide), report success and failures from Perform actions
* Fix comment, use atomic add
* Improve logic a bit, don't block on wakeup, move idle check
* Don't retry sucessful invites, don't dispatch sendEvent, sendInvite etc
* Dedupe destinations, fix other bug hopefully
* Dispatch sends again
* Federation sender to ignore invites that are destined locally
* Loopback invite events
* Remodel a bit with channels
* Linter
* Only loopback invite event if we know the room
* We should tell other resident servers about the invite if we know about the room
* Correct invite signing
* Fix invite loopback
* Check HTTP response codes, push new invites to front of queue
* Review comments
2020-05-07 12:42:06 +01:00
) ( * api . InputRoomEvent , error ) {
2017-08-21 16:37:11 +01:00
if input . Event . StateKey ( ) == nil {
Improve federation sender performance, implement backoff and blacklisting, fix up invites a bit (#1007)
* Improve federation sender performance and behaviour, add backoff
* Tweaks
* Tweaks
* Tweaks
* Take copies of events before passing to destination queues
* Don't accidentally drop queued messages
* Don't take copies again
* Tidy up a bit
* Break out statistics (tracked component-wide), report success and failures from Perform actions
* Fix comment, use atomic add
* Improve logic a bit, don't block on wakeup, move idle check
* Don't retry sucessful invites, don't dispatch sendEvent, sendInvite etc
* Dedupe destinations, fix other bug hopefully
* Dispatch sends again
* Federation sender to ignore invites that are destined locally
* Loopback invite events
* Remodel a bit with channels
* Linter
* Only loopback invite event if we know the room
* We should tell other resident servers about the invite if we know about the room
* Correct invite signing
* Fix invite loopback
* Check HTTP response codes, push new invites to front of queue
* Review comments
2020-05-07 12:42:06 +01:00
return nil , fmt . Errorf ( "invite must be a state event" )
2017-08-21 16:37:11 +01:00
}
roomID := input . Event . RoomID ( )
targetUserID := * input . Event . StateKey ( )
2020-04-03 14:29:06 +01:00
log . WithFields ( log . Fields {
"event_id" : input . Event . EventID ( ) ,
"room_id" : roomID ,
"room_version" : input . RoomVersion ,
"target_user_id" : targetUserID ,
} ) . Info ( "processing invite event" )
2020-05-20 18:03:06 +01:00
_ , domain , _ := gomatrixserverlib . SplitID ( '@' , targetUserID )
isTargetLocalUser := domain == r . Cfg . Matrix . ServerName
updater , err := r . DB . MembershipUpdater ( ctx , roomID , targetUserID , isTargetLocalUser , input . RoomVersion )
2017-08-21 16:37:11 +01:00
if err != nil {
Improve federation sender performance, implement backoff and blacklisting, fix up invites a bit (#1007)
* Improve federation sender performance and behaviour, add backoff
* Tweaks
* Tweaks
* Tweaks
* Take copies of events before passing to destination queues
* Don't accidentally drop queued messages
* Don't take copies again
* Tidy up a bit
* Break out statistics (tracked component-wide), report success and failures from Perform actions
* Fix comment, use atomic add
* Improve logic a bit, don't block on wakeup, move idle check
* Don't retry sucessful invites, don't dispatch sendEvent, sendInvite etc
* Dedupe destinations, fix other bug hopefully
* Dispatch sends again
* Federation sender to ignore invites that are destined locally
* Loopback invite events
* Remodel a bit with channels
* Linter
* Only loopback invite event if we know the room
* We should tell other resident servers about the invite if we know about the room
* Correct invite signing
* Fix invite loopback
* Check HTTP response codes, push new invites to front of queue
* Review comments
2020-05-07 12:42:06 +01:00
return nil , err
2017-08-21 16:37:11 +01:00
}
succeeded := false
2020-02-13 17:27:33 +00:00
defer func ( ) {
txerr := common . EndTransaction ( updater , & succeeded )
if err == nil && txerr != nil {
err = txerr
}
} ( )
2017-08-21 16:37:11 +01:00
if updater . IsJoin ( ) {
// If the user is joined to the room then that takes precedence over this
// invite event. It makes little sense to move a user that is already
// joined to the room into the invite state.
// This could plausibly happen if an invite request raced with a join
// request for a user. For example if a user was invited to a public
// room and they joined the room at the same time as the invite was sent.
// The other way this could plausibly happen is if an invite raced with
// a kick. For example if a user was kicked from a room in error and in
// response someone else in the room re-invited them then it is possible
// for the invite request to race with the leave event so that the
// target receives invite before it learns that it has been kicked.
// There are a few ways this could be plausibly handled in the roomserver.
// 1) Store the invite, but mark it as retired. That will result in the
// permanent rejection of that invite event. So even if the target
// user leaves the room and the invite is retransmitted it will be
// ignored. However a new invite with a new event ID would still be
// accepted.
// 2) Silently discard the invite event. This means that if the event
// was retransmitted at a later date after the target user had left
// the room we would accept the invite. However since we hadn't told
// the sending server that the invite had been discarded it would
// have no reason to attempt to retry.
// 3) Signal the sending server that the user is already joined to the
// room.
// For now we will implement option 2. Since in the abesence of a retry
// mechanism it will be equivalent to option 1, and we don't have a
// signalling mechanism to implement option 3.
Improve federation sender performance, implement backoff and blacklisting, fix up invites a bit (#1007)
* Improve federation sender performance and behaviour, add backoff
* Tweaks
* Tweaks
* Tweaks
* Take copies of events before passing to destination queues
* Don't accidentally drop queued messages
* Don't take copies again
* Tidy up a bit
* Break out statistics (tracked component-wide), report success and failures from Perform actions
* Fix comment, use atomic add
* Improve logic a bit, don't block on wakeup, move idle check
* Don't retry sucessful invites, don't dispatch sendEvent, sendInvite etc
* Dedupe destinations, fix other bug hopefully
* Dispatch sends again
* Federation sender to ignore invites that are destined locally
* Loopback invite events
* Remodel a bit with channels
* Linter
* Only loopback invite event if we know the room
* We should tell other resident servers about the invite if we know about the room
* Correct invite signing
* Fix invite loopback
* Check HTTP response codes, push new invites to front of queue
* Review comments
2020-05-07 12:42:06 +01:00
return nil , nil
2017-08-21 16:37:11 +01:00
}
Improve federation sender performance, implement backoff and blacklisting, fix up invites a bit (#1007)
* Improve federation sender performance and behaviour, add backoff
* Tweaks
* Tweaks
* Tweaks
* Take copies of events before passing to destination queues
* Don't accidentally drop queued messages
* Don't take copies again
* Tidy up a bit
* Break out statistics (tracked component-wide), report success and failures from Perform actions
* Fix comment, use atomic add
* Improve logic a bit, don't block on wakeup, move idle check
* Don't retry sucessful invites, don't dispatch sendEvent, sendInvite etc
* Dedupe destinations, fix other bug hopefully
* Dispatch sends again
* Federation sender to ignore invites that are destined locally
* Loopback invite events
* Remodel a bit with channels
* Linter
* Only loopback invite event if we know the room
* We should tell other resident servers about the invite if we know about the room
* Correct invite signing
* Fix invite loopback
* Check HTTP response codes, push new invites to front of queue
* Review comments
2020-05-07 12:42:06 +01:00
// Normally, with a federated invite, the federation sender would do
// the /v2/invite request (in which the remote server signs the invite)
// and then the signed event gets sent back to the roomserver as an input
// event. When the invite is local, we don't interact with the federation
// sender therefore we need to generate the loopback invite event for
// the room ourselves.
loopback , err := localInviteLoopback ( ow , input )
if err != nil {
return nil , err
}
2020-04-03 14:29:06 +01:00
Improve federation sender performance, implement backoff and blacklisting, fix up invites a bit (#1007)
* Improve federation sender performance and behaviour, add backoff
* Tweaks
* Tweaks
* Tweaks
* Take copies of events before passing to destination queues
* Don't accidentally drop queued messages
* Don't take copies again
* Tidy up a bit
* Break out statistics (tracked component-wide), report success and failures from Perform actions
* Fix comment, use atomic add
* Improve logic a bit, don't block on wakeup, move idle check
* Don't retry sucessful invites, don't dispatch sendEvent, sendInvite etc
* Dedupe destinations, fix other bug hopefully
* Dispatch sends again
* Federation sender to ignore invites that are destined locally
* Loopback invite events
* Remodel a bit with channels
* Linter
* Only loopback invite event if we know the room
* We should tell other resident servers about the invite if we know about the room
* Correct invite signing
* Fix invite loopback
* Check HTTP response codes, push new invites to front of queue
* Review comments
2020-05-07 12:42:06 +01:00
event := input . Event . Unwrap ( )
2020-04-24 16:30:25 +01:00
if len ( input . InviteRoomState ) > 0 {
// If we were supplied with some invite room state already (which is
// most likely to be if the event came in over federation) then use
// that.
if err = event . SetUnsignedField ( "invite_room_state" , input . InviteRoomState ) ; err != nil {
Improve federation sender performance, implement backoff and blacklisting, fix up invites a bit (#1007)
* Improve federation sender performance and behaviour, add backoff
* Tweaks
* Tweaks
* Tweaks
* Take copies of events before passing to destination queues
* Don't accidentally drop queued messages
* Don't take copies again
* Tidy up a bit
* Break out statistics (tracked component-wide), report success and failures from Perform actions
* Fix comment, use atomic add
* Improve logic a bit, don't block on wakeup, move idle check
* Don't retry sucessful invites, don't dispatch sendEvent, sendInvite etc
* Dedupe destinations, fix other bug hopefully
* Dispatch sends again
* Federation sender to ignore invites that are destined locally
* Loopback invite events
* Remodel a bit with channels
* Linter
* Only loopback invite event if we know the room
* We should tell other resident servers about the invite if we know about the room
* Correct invite signing
* Fix invite loopback
* Check HTTP response codes, push new invites to front of queue
* Review comments
2020-05-07 12:42:06 +01:00
return nil , err
2020-04-24 16:30:25 +01:00
}
} else {
// There's no invite room state, so let's have a go at building it
// up from local data (which is most likely to be if the event came
// from the CS API). If we know about the room then we can insert
// the invite room state, if we don't then we just fail quietly.
2020-05-20 18:03:06 +01:00
if irs , ierr := buildInviteStrippedState ( ctx , r . DB , input ) ; ierr == nil {
2020-04-24 16:30:25 +01:00
if err = event . SetUnsignedField ( "invite_room_state" , irs ) ; err != nil {
Improve federation sender performance, implement backoff and blacklisting, fix up invites a bit (#1007)
* Improve federation sender performance and behaviour, add backoff
* Tweaks
* Tweaks
* Tweaks
* Take copies of events before passing to destination queues
* Don't accidentally drop queued messages
* Don't take copies again
* Tidy up a bit
* Break out statistics (tracked component-wide), report success and failures from Perform actions
* Fix comment, use atomic add
* Improve logic a bit, don't block on wakeup, move idle check
* Don't retry sucessful invites, don't dispatch sendEvent, sendInvite etc
* Dedupe destinations, fix other bug hopefully
* Dispatch sends again
* Federation sender to ignore invites that are destined locally
* Loopback invite events
* Remodel a bit with channels
* Linter
* Only loopback invite event if we know the room
* We should tell other resident servers about the invite if we know about the room
* Correct invite signing
* Fix invite loopback
* Check HTTP response codes, push new invites to front of queue
* Review comments
2020-05-07 12:42:06 +01:00
return nil , err
2020-04-24 16:30:25 +01:00
}
}
2020-04-03 14:29:06 +01:00
}
outputUpdates , err := updateToInviteMembership ( updater , & event , nil , input . Event . RoomVersion )
2017-08-21 16:37:11 +01:00
if err != nil {
Improve federation sender performance, implement backoff and blacklisting, fix up invites a bit (#1007)
* Improve federation sender performance and behaviour, add backoff
* Tweaks
* Tweaks
* Tweaks
* Take copies of events before passing to destination queues
* Don't accidentally drop queued messages
* Don't take copies again
* Tidy up a bit
* Break out statistics (tracked component-wide), report success and failures from Perform actions
* Fix comment, use atomic add
* Improve logic a bit, don't block on wakeup, move idle check
* Don't retry sucessful invites, don't dispatch sendEvent, sendInvite etc
* Dedupe destinations, fix other bug hopefully
* Dispatch sends again
* Federation sender to ignore invites that are destined locally
* Loopback invite events
* Remodel a bit with channels
* Linter
* Only loopback invite event if we know the room
* We should tell other resident servers about the invite if we know about the room
* Correct invite signing
* Fix invite loopback
* Check HTTP response codes, push new invites to front of queue
* Review comments
2020-05-07 12:42:06 +01:00
return nil , err
2017-08-21 16:37:11 +01:00
}
if err = ow . WriteOutputEvents ( roomID , outputUpdates ) ; err != nil {
Improve federation sender performance, implement backoff and blacklisting, fix up invites a bit (#1007)
* Improve federation sender performance and behaviour, add backoff
* Tweaks
* Tweaks
* Tweaks
* Take copies of events before passing to destination queues
* Don't accidentally drop queued messages
* Don't take copies again
* Tidy up a bit
* Break out statistics (tracked component-wide), report success and failures from Perform actions
* Fix comment, use atomic add
* Improve logic a bit, don't block on wakeup, move idle check
* Don't retry sucessful invites, don't dispatch sendEvent, sendInvite etc
* Dedupe destinations, fix other bug hopefully
* Dispatch sends again
* Federation sender to ignore invites that are destined locally
* Loopback invite events
* Remodel a bit with channels
* Linter
* Only loopback invite event if we know the room
* We should tell other resident servers about the invite if we know about the room
* Correct invite signing
* Fix invite loopback
* Check HTTP response codes, push new invites to front of queue
* Review comments
2020-05-07 12:42:06 +01:00
return nil , err
2017-08-21 16:37:11 +01:00
}
succeeded = true
Improve federation sender performance, implement backoff and blacklisting, fix up invites a bit (#1007)
* Improve federation sender performance and behaviour, add backoff
* Tweaks
* Tweaks
* Tweaks
* Take copies of events before passing to destination queues
* Don't accidentally drop queued messages
* Don't take copies again
* Tidy up a bit
* Break out statistics (tracked component-wide), report success and failures from Perform actions
* Fix comment, use atomic add
* Improve logic a bit, don't block on wakeup, move idle check
* Don't retry sucessful invites, don't dispatch sendEvent, sendInvite etc
* Dedupe destinations, fix other bug hopefully
* Dispatch sends again
* Federation sender to ignore invites that are destined locally
* Loopback invite events
* Remodel a bit with channels
* Linter
* Only loopback invite event if we know the room
* We should tell other resident servers about the invite if we know about the room
* Correct invite signing
* Fix invite loopback
* Check HTTP response codes, push new invites to front of queue
* Review comments
2020-05-07 12:42:06 +01:00
return loopback , nil
}
func localInviteLoopback (
ow * RoomserverInternalAPI ,
input api . InputInviteEvent ,
) ( ire * api . InputRoomEvent , err error ) {
if input . Event . StateKey ( ) == nil {
return nil , errors . New ( "no state key on invite event" )
}
ourServerName := string ( ow . Cfg . Matrix . ServerName )
_ , theirServerName , err := gomatrixserverlib . SplitID ( '@' , * input . Event . StateKey ( ) )
if err != nil {
return nil , err
}
// Check if the invite originated locally and is destined locally.
if input . Event . Origin ( ) == ow . Cfg . Matrix . ServerName && string ( theirServerName ) == ourServerName {
rsEvent := input . Event . Sign (
ourServerName ,
ow . Cfg . Matrix . KeyID ,
ow . Cfg . Matrix . PrivateKey ,
) . Headered ( input . RoomVersion )
ire = & api . InputRoomEvent {
Kind : api . KindNew ,
Event : rsEvent ,
AuthEventIDs : rsEvent . AuthEventIDs ( ) ,
SendAsServer : ourServerName ,
TransactionID : nil ,
}
}
return ire , nil
2017-02-07 17:20:05 +00:00
}
2020-04-24 16:30:25 +01:00
func buildInviteStrippedState (
ctx context . Context ,
db storage . Database ,
input api . InputInviteEvent ,
) ( [ ] gomatrixserverlib . InviteV2StrippedState , error ) {
roomNID , err := db . RoomNID ( ctx , input . Event . RoomID ( ) )
if err != nil || roomNID == 0 {
return nil , fmt . Errorf ( "room %q unknown" , input . Event . RoomID ( ) )
}
stateWanted := [ ] gomatrixserverlib . StateKeyTuple { }
for _ , t := range [ ] string {
gomatrixserverlib . MRoomName , gomatrixserverlib . MRoomCanonicalAlias ,
gomatrixserverlib . MRoomAliases , gomatrixserverlib . MRoomJoinRules ,
} {
stateWanted = append ( stateWanted , gomatrixserverlib . StateKeyTuple {
EventType : t ,
StateKey : "" ,
} )
}
_ , currentStateSnapshotNID , _ , err := db . LatestEventIDs ( ctx , roomNID )
if err != nil {
return nil , err
}
roomState := state . NewStateResolution ( db )
stateEntries , err := roomState . LoadStateAtSnapshotForStringTuples (
ctx , currentStateSnapshotNID , stateWanted ,
)
if err != nil {
return nil , err
}
stateNIDs := [ ] types . EventNID { }
for _ , stateNID := range stateEntries {
stateNIDs = append ( stateNIDs , stateNID . EventNID )
}
stateEvents , err := db . Events ( ctx , stateNIDs )
if err != nil {
return nil , err
}
inviteState := [ ] gomatrixserverlib . InviteV2StrippedState {
gomatrixserverlib . NewInviteV2StrippedState ( & input . Event . Event ) ,
}
2020-05-07 16:46:11 +01:00
stateEvents = append ( stateEvents , types . Event { Event : input . Event . Unwrap ( ) } )
2020-04-24 16:30:25 +01:00
for _ , event := range stateEvents {
inviteState = append ( inviteState , gomatrixserverlib . NewInviteV2StrippedState ( & event . Event ) )
}
return inviteState , nil
}