aboutsummaryrefslogtreecommitdiff
path: root/federationapi
diff options
context:
space:
mode:
authorkegsay <kegan@matrix.org>2022-05-06 12:39:26 +0100
committerGitHub <noreply@github.com>2022-05-06 12:39:26 +0100
commit85704eff207f7690d197172abb991ae1ac238239 (patch)
tree3d43faf35034c270ebaf40a27a75a646e40829d7 /federationapi
parent4705f5761e620e7f8a35151eeb2007e884847152 (diff)
Clean up interface definitions (#2427)
* tidy up interfaces * remove unused GetCreatorIDForAlias * Add RoomserverUserAPI interface * Define more interfaces * Use AppServiceInternalAPI for consistent naming * clean up federationapi constructor a bit * Fix monolith in -http mode
Diffstat (limited to 'federationapi')
-rw-r--r--federationapi/api/api.go76
-rw-r--r--federationapi/federationapi.go17
-rw-r--r--federationapi/federationapi_test.go4
-rw-r--r--federationapi/internal/perform.go30
-rw-r--r--federationapi/inthttp/client.go13
-rw-r--r--federationapi/inthttp/server.go14
-rw-r--r--federationapi/routing/devices.go2
-rw-r--r--federationapi/routing/keys.go4
-rw-r--r--federationapi/routing/routing.go118
-rw-r--r--federationapi/routing/send.go4
10 files changed, 151 insertions, 131 deletions
diff --git a/federationapi/api/api.go b/federationapi/api/api.go
index 87b03718..fc25194e 100644
--- a/federationapi/api/api.go
+++ b/federationapi/api/api.go
@@ -10,30 +10,6 @@ import (
"github.com/matrix-org/gomatrixserverlib"
)
-// FederationClient is a subset of gomatrixserverlib.FederationClient functions which the fedsender
-// implements as proxy calls, with built-in backoff/retries/etc. Errors returned from functions in
-// this interface are of type FederationClientError
-type FederationClient interface {
- gomatrixserverlib.FederatedStateClient
- GetUserDevices(ctx context.Context, s gomatrixserverlib.ServerName, userID string) (res gomatrixserverlib.RespUserDevices, err error)
- ClaimKeys(ctx context.Context, s gomatrixserverlib.ServerName, oneTimeKeys map[string]map[string]string) (res gomatrixserverlib.RespClaimKeys, err error)
- QueryKeys(ctx context.Context, s gomatrixserverlib.ServerName, keys map[string][]string) (res gomatrixserverlib.RespQueryKeys, err error)
- MSC2836EventRelationships(ctx context.Context, dst gomatrixserverlib.ServerName, r gomatrixserverlib.MSC2836EventRelationshipsRequest, roomVersion gomatrixserverlib.RoomVersion) (res gomatrixserverlib.MSC2836EventRelationshipsResponse, err error)
- MSC2946Spaces(ctx context.Context, dst gomatrixserverlib.ServerName, roomID string, suggestedOnly bool) (res gomatrixserverlib.MSC2946SpacesResponse, err error)
- LookupServerKeys(ctx context.Context, s gomatrixserverlib.ServerName, keyRequests map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp) ([]gomatrixserverlib.ServerKeys, error)
-}
-
-// FederationClientError is returned from FederationClient methods in the event of a problem.
-type FederationClientError struct {
- Err string
- RetryAfter time.Duration
- Blacklisted bool
-}
-
-func (e *FederationClientError) Error() string {
- return fmt.Sprintf("%s - (retry_after=%s, blacklisted=%v)", e.Err, e.RetryAfter.String(), e.Blacklisted)
-}
-
// FederationInternalAPI is used to query information from the federation sender.
type FederationInternalAPI interface {
FederationClient
@@ -43,22 +19,7 @@ type FederationInternalAPI interface {
QueryServerKeys(ctx context.Context, request *QueryServerKeysRequest, response *QueryServerKeysResponse) error
- // Query the server names of the joined hosts in a room.
- // Unlike QueryJoinedHostsInRoom, this function returns a de-duplicated slice
- // containing only the server names (without information for membership events).
- // The response will include this server if they are joined to the room.
- QueryJoinedHostServerNamesInRoom(
- ctx context.Context,
- request *QueryJoinedHostServerNamesInRoomRequest,
- response *QueryJoinedHostServerNamesInRoomResponse,
- ) error
- // Notifies the federation sender that these servers may be online and to retry sending messages.
- PerformServersAlive(
- ctx context.Context,
- request *PerformServersAliveRequest,
- response *PerformServersAliveResponse,
- ) error
- // Broadcasts an EDU to all servers in rooms we are joined to.
+ // Broadcasts an EDU to all servers in rooms we are joined to. Used in the yggdrasil demos.
PerformBroadcastEDU(
ctx context.Context,
request *PerformBroadcastEDURequest,
@@ -67,6 +28,10 @@ type FederationInternalAPI interface {
}
type ClientFederationAPI interface {
+ // Query the server names of the joined hosts in a room.
+ // Unlike QueryJoinedHostsInRoom, this function returns a de-duplicated slice
+ // containing only the server names (without information for membership events).
+ // The response will include this server if they are joined to the room.
QueryJoinedHostServerNamesInRoom(ctx context.Context, request *QueryJoinedHostServerNamesInRoomRequest, response *QueryJoinedHostServerNamesInRoomResponse) error
}
@@ -95,6 +60,30 @@ type RoomserverFederationAPI interface {
LookupMissingEvents(ctx context.Context, s gomatrixserverlib.ServerName, roomID string, missing gomatrixserverlib.MissingEvents, roomVersion gomatrixserverlib.RoomVersion) (res gomatrixserverlib.RespMissingEvents, err error)
}
+// FederationClient is a subset of gomatrixserverlib.FederationClient functions which the fedsender
+// implements as proxy calls, with built-in backoff/retries/etc. Errors returned from functions in
+// this interface are of type FederationClientError
+type FederationClient interface {
+ gomatrixserverlib.FederatedStateClient
+ GetUserDevices(ctx context.Context, s gomatrixserverlib.ServerName, userID string) (res gomatrixserverlib.RespUserDevices, err error)
+ ClaimKeys(ctx context.Context, s gomatrixserverlib.ServerName, oneTimeKeys map[string]map[string]string) (res gomatrixserverlib.RespClaimKeys, err error)
+ QueryKeys(ctx context.Context, s gomatrixserverlib.ServerName, keys map[string][]string) (res gomatrixserverlib.RespQueryKeys, err error)
+ MSC2836EventRelationships(ctx context.Context, dst gomatrixserverlib.ServerName, r gomatrixserverlib.MSC2836EventRelationshipsRequest, roomVersion gomatrixserverlib.RoomVersion) (res gomatrixserverlib.MSC2836EventRelationshipsResponse, err error)
+ MSC2946Spaces(ctx context.Context, dst gomatrixserverlib.ServerName, roomID string, suggestedOnly bool) (res gomatrixserverlib.MSC2946SpacesResponse, err error)
+ LookupServerKeys(ctx context.Context, s gomatrixserverlib.ServerName, keyRequests map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp) ([]gomatrixserverlib.ServerKeys, error)
+}
+
+// FederationClientError is returned from FederationClient methods in the event of a problem.
+type FederationClientError struct {
+ Err string
+ RetryAfter time.Duration
+ Blacklisted bool
+}
+
+func (e *FederationClientError) Error() string {
+ return fmt.Sprintf("%s - (retry_after=%s, blacklisted=%v)", e.Err, e.RetryAfter.String(), e.Blacklisted)
+}
+
type QueryServerKeysRequest struct {
ServerName gomatrixserverlib.ServerName
KeyIDToCriteria map[gomatrixserverlib.KeyID]gomatrixserverlib.PublicKeyNotaryQueryCriteria
@@ -174,13 +163,6 @@ type PerformInviteResponse struct {
Event *gomatrixserverlib.HeaderedEvent `json:"event"`
}
-type PerformServersAliveRequest struct {
- Servers []gomatrixserverlib.ServerName
-}
-
-type PerformServersAliveResponse struct {
-}
-
// QueryJoinedHostServerNamesInRoomRequest is a request to QueryJoinedHostServerNames
type QueryJoinedHostServerNamesInRoomRequest struct {
RoomID string `json:"room_id"`
diff --git a/federationapi/federationapi.go b/federationapi/federationapi.go
index 632994db..e52377c9 100644
--- a/federationapi/federationapi.go
+++ b/federationapi/federationapi.go
@@ -50,8 +50,8 @@ func AddPublicRoutes(
federation *gomatrixserverlib.FederationClient,
keyRing gomatrixserverlib.JSONVerifier,
rsAPI roomserverAPI.FederationRoomserverAPI,
- federationAPI federationAPI.FederationInternalAPI,
- keyAPI keyserverAPI.KeyInternalAPI,
+ fedAPI federationAPI.FederationInternalAPI,
+ keyAPI keyserverAPI.FederationKeyAPI,
servers federationAPI.ServersInRoomProvider,
) {
cfg := &base.Cfg.FederationAPI
@@ -67,12 +67,23 @@ func AddPublicRoutes(
UserAPI: userAPI,
}
+ // the federationapi component is a bit unique in that it attaches public routes AND serves
+ // internal APIs (because it used to be 2 components: the 2nd being fedsender). As a result,
+ // the constructor shape is a bit wonky in that it is not valid to AddPublicRoutes without a
+ // concrete impl of FederationInternalAPI as the public routes and the internal API _should_
+ // be the same thing now.
+ f, ok := fedAPI.(*internal.FederationInternalAPI)
+ if !ok {
+ panic("federationapi.AddPublicRoutes called with a FederationInternalAPI impl which was not " +
+ "FederationInternalAPI. This is a programming error.")
+ }
+
routing.Setup(
base.PublicFederationAPIMux,
base.PublicKeyAPIMux,
base.PublicWellKnownAPIMux,
cfg,
- rsAPI, federationAPI, keyRing,
+ rsAPI, f, keyRing,
federation, userAPI, keyAPI, mscCfg,
servers, producer,
)
diff --git a/federationapi/federationapi_test.go b/federationapi/federationapi_test.go
index 68724164..eedebc6c 100644
--- a/federationapi/federationapi_test.go
+++ b/federationapi/federationapi_test.go
@@ -7,6 +7,7 @@ import (
"testing"
"github.com/matrix-org/dendrite/federationapi"
+ "github.com/matrix-org/dendrite/federationapi/internal"
"github.com/matrix-org/dendrite/internal/test"
"github.com/matrix-org/dendrite/setup/base"
"github.com/matrix-org/dendrite/setup/config"
@@ -27,10 +28,9 @@ func TestRoomsV3URLEscapeDoNot404(t *testing.T) {
cfg.FederationAPI.Database.ConnectionString = config.DataSource("file::memory:")
base := base.NewBaseDendrite(cfg, "Monolith")
keyRing := &test.NopJSONVerifier{}
- fsAPI := base.FederationAPIHTTPClient()
// TODO: This is pretty fragile, as if anything calls anything on these nils this test will break.
// Unfortunately, it makes little sense to instantiate these dependencies when we just want to test routing.
- federationapi.AddPublicRoutes(base, nil, nil, keyRing, nil, fsAPI, nil, nil)
+ federationapi.AddPublicRoutes(base, nil, nil, keyRing, nil, &internal.FederationInternalAPI{}, nil, nil)
baseURL, cancel := test.ListenAndServe(t, base.PublicFederationAPIMux, true)
defer cancel()
serverName := gomatrixserverlib.ServerName(strings.TrimPrefix(baseURL, "https://"))
diff --git a/federationapi/internal/perform.go b/federationapi/internal/perform.go
index aac36cc7..577cb70e 100644
--- a/federationapi/internal/perform.go
+++ b/federationapi/internal/perform.go
@@ -564,20 +564,6 @@ func (r *FederationInternalAPI) PerformInvite(
}
// PerformServersAlive implements api.FederationInternalAPI
-func (r *FederationInternalAPI) PerformServersAlive(
- ctx context.Context,
- request *api.PerformServersAliveRequest,
- response *api.PerformServersAliveResponse,
-) (err error) {
- for _, srv := range request.Servers {
- _ = r.db.RemoveServerFromBlacklist(srv)
- r.queues.RetryServer(srv)
- }
-
- return nil
-}
-
-// PerformServersAlive implements api.FederationInternalAPI
func (r *FederationInternalAPI) PerformBroadcastEDU(
ctx context.Context,
request *api.PerformBroadcastEDURequest,
@@ -600,18 +586,18 @@ func (r *FederationInternalAPI) PerformBroadcastEDU(
if err = r.queues.SendEDU(edu, r.cfg.Matrix.ServerName, destinations); err != nil {
return fmt.Errorf("r.queues.SendEDU: %w", err)
}
-
- wakeReq := &api.PerformServersAliveRequest{
- Servers: destinations,
- }
- wakeRes := &api.PerformServersAliveResponse{}
- if err := r.PerformServersAlive(ctx, wakeReq, wakeRes); err != nil {
- return fmt.Errorf("r.PerformServersAlive: %w", err)
- }
+ r.MarkServersAlive(destinations)
return nil
}
+func (r *FederationInternalAPI) MarkServersAlive(destinations []gomatrixserverlib.ServerName) {
+ for _, srv := range destinations {
+ _ = r.db.RemoveServerFromBlacklist(srv)
+ r.queues.RetryServer(srv)
+ }
+}
+
func sanityCheckAuthChain(authChain []*gomatrixserverlib.Event) error {
// sanity check we have a create event and it has a known room version
for _, ev := range authChain {
diff --git a/federationapi/inthttp/client.go b/federationapi/inthttp/client.go
index 01ca6595..295ddc49 100644
--- a/federationapi/inthttp/client.go
+++ b/federationapi/inthttp/client.go
@@ -23,7 +23,6 @@ const (
FederationAPIPerformLeaveRequestPath = "/federationapi/performLeaveRequest"
FederationAPIPerformInviteRequestPath = "/federationapi/performInviteRequest"
FederationAPIPerformOutboundPeekRequestPath = "/federationapi/performOutboundPeekRequest"
- FederationAPIPerformServersAlivePath = "/federationapi/performServersAlive"
FederationAPIPerformBroadcastEDUPath = "/federationapi/performBroadcastEDU"
FederationAPIGetUserDevicesPath = "/federationapi/client/getUserDevices"
@@ -97,18 +96,6 @@ func (h *httpFederationInternalAPI) PerformOutboundPeek(
return httputil.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
}
-func (h *httpFederationInternalAPI) PerformServersAlive(
- ctx context.Context,
- request *api.PerformServersAliveRequest,
- response *api.PerformServersAliveResponse,
-) error {
- span, ctx := opentracing.StartSpanFromContext(ctx, "PerformServersAlive")
- defer span.Finish()
-
- apiURL := h.federationAPIURL + FederationAPIPerformServersAlivePath
- return httputil.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
-}
-
// QueryJoinedHostServerNamesInRoom implements FederationInternalAPI
func (h *httpFederationInternalAPI) QueryJoinedHostServerNamesInRoom(
ctx context.Context,
diff --git a/federationapi/inthttp/server.go b/federationapi/inthttp/server.go
index ca4930f2..28e52b32 100644
--- a/federationapi/inthttp/server.go
+++ b/federationapi/inthttp/server.go
@@ -82,20 +82,6 @@ func AddRoutes(intAPI api.FederationInternalAPI, internalAPIMux *mux.Router) {
}),
)
internalAPIMux.Handle(
- FederationAPIPerformServersAlivePath,
- httputil.MakeInternalAPI("PerformServersAliveRequest", func(req *http.Request) util.JSONResponse {
- var request api.PerformServersAliveRequest
- var response api.PerformServersAliveResponse
- if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
- return util.MessageResponse(http.StatusBadRequest, err.Error())
- }
- if err := intAPI.PerformServersAlive(req.Context(), &request, &response); err != nil {
- return util.ErrorResponse(err)
- }
- return util.JSONResponse{Code: http.StatusOK, JSON: &response}
- }),
- )
- internalAPIMux.Handle(
FederationAPIPerformBroadcastEDUPath,
httputil.MakeInternalAPI("PerformBroadcastEDU", func(req *http.Request) util.JSONResponse {
var request api.PerformBroadcastEDURequest
diff --git a/federationapi/routing/devices.go b/federationapi/routing/devices.go
index 57286fa9..1a092645 100644
--- a/federationapi/routing/devices.go
+++ b/federationapi/routing/devices.go
@@ -26,7 +26,7 @@ import (
// GetUserDevices for the given user id
func GetUserDevices(
req *http.Request,
- keyAPI keyapi.KeyInternalAPI,
+ keyAPI keyapi.FederationKeyAPI,
userID string,
) util.JSONResponse {
var res keyapi.QueryDeviceMessagesResponse
diff --git a/federationapi/routing/keys.go b/federationapi/routing/keys.go
index 49a6c558..b1a9b671 100644
--- a/federationapi/routing/keys.go
+++ b/federationapi/routing/keys.go
@@ -37,7 +37,7 @@ type queryKeysRequest struct {
// QueryDeviceKeys returns device keys for users on this server.
// https://matrix.org/docs/spec/server_server/latest#post-matrix-federation-v1-user-keys-query
func QueryDeviceKeys(
- httpReq *http.Request, request *gomatrixserverlib.FederationRequest, keyAPI api.KeyInternalAPI, thisServer gomatrixserverlib.ServerName,
+ httpReq *http.Request, request *gomatrixserverlib.FederationRequest, keyAPI api.FederationKeyAPI, thisServer gomatrixserverlib.ServerName,
) util.JSONResponse {
var qkr queryKeysRequest
err := json.Unmarshal(request.Content(), &qkr)
@@ -89,7 +89,7 @@ type claimOTKsRequest struct {
// ClaimOneTimeKeys claims OTKs for users on this server.
// https://matrix.org/docs/spec/server_server/latest#post-matrix-federation-v1-user-keys-claim
func ClaimOneTimeKeys(
- httpReq *http.Request, request *gomatrixserverlib.FederationRequest, keyAPI api.KeyInternalAPI, thisServer gomatrixserverlib.ServerName,
+ httpReq *http.Request, request *gomatrixserverlib.FederationRequest, keyAPI api.FederationKeyAPI, thisServer gomatrixserverlib.ServerName,
) util.JSONResponse {
var cor claimOTKsRequest
err := json.Unmarshal(request.Content(), &cor)
diff --git a/federationapi/routing/routing.go b/federationapi/routing/routing.go
index 51adc279..9f95ed07 100644
--- a/federationapi/routing/routing.go
+++ b/federationapi/routing/routing.go
@@ -18,10 +18,14 @@ import (
"context"
"fmt"
"net/http"
+ "sync"
+ "time"
+ "github.com/getsentry/sentry-go"
"github.com/gorilla/mux"
"github.com/matrix-org/dendrite/clientapi/jsonerror"
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
+ fedInternal "github.com/matrix-org/dendrite/federationapi/internal"
"github.com/matrix-org/dendrite/federationapi/producers"
"github.com/matrix-org/dendrite/internal"
"github.com/matrix-org/dendrite/internal/httputil"
@@ -48,11 +52,11 @@ func Setup(
fedMux, keyMux, wkMux *mux.Router,
cfg *config.FederationAPI,
rsAPI roomserverAPI.FederationRoomserverAPI,
- fsAPI federationAPI.FederationInternalAPI,
+ fsAPI *fedInternal.FederationInternalAPI,
keys gomatrixserverlib.JSONVerifier,
federation *gomatrixserverlib.FederationClient,
userAPI userapi.FederationUserAPI,
- keyAPI keyserverAPI.KeyInternalAPI,
+ keyAPI keyserverAPI.FederationKeyAPI,
mscCfg *config.MSCs,
servers federationAPI.ServersInRoomProvider,
producer *producers.SyncAPIProducer,
@@ -65,7 +69,7 @@ func Setup(
v1fedmux := fedMux.PathPrefix("/v1").Subrouter()
v2fedmux := fedMux.PathPrefix("/v2").Subrouter()
- wakeup := &httputil.FederationWakeups{
+ wakeup := &FederationWakeups{
FsAPI: fsAPI,
}
@@ -119,7 +123,7 @@ func Setup(
v2keysmux.Handle("/query/{serverName}/{keyID}", notaryKeys).Methods(http.MethodGet)
mu := internal.NewMutexByRoom()
- v1fedmux.Handle("/send/{txnID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/send/{txnID}", MakeFedAPI(
"federation_send", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
return Send(
@@ -129,7 +133,7 @@ func Setup(
},
)).Methods(http.MethodPut, http.MethodOptions)
- v1fedmux.Handle("/invite/{roomID}/{eventID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/invite/{roomID}/{eventID}", MakeFedAPI(
"federation_invite", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -145,7 +149,7 @@ func Setup(
},
)).Methods(http.MethodPut, http.MethodOptions)
- v2fedmux.Handle("/invite/{roomID}/{eventID}", httputil.MakeFedAPI(
+ v2fedmux.Handle("/invite/{roomID}/{eventID}", MakeFedAPI(
"federation_invite", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -167,7 +171,7 @@ func Setup(
},
)).Methods(http.MethodPost, http.MethodOptions)
- v1fedmux.Handle("/exchange_third_party_invite/{roomID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/exchange_third_party_invite/{roomID}", MakeFedAPI(
"exchange_third_party_invite", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
return ExchangeThirdPartyInvite(
@@ -176,7 +180,7 @@ func Setup(
},
)).Methods(http.MethodPut, http.MethodOptions)
- v1fedmux.Handle("/event/{eventID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/event/{eventID}", MakeFedAPI(
"federation_get_event", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
return GetEvent(
@@ -185,7 +189,7 @@ func Setup(
},
)).Methods(http.MethodGet)
- v1fedmux.Handle("/state/{roomID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/state/{roomID}", MakeFedAPI(
"federation_get_state", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -200,7 +204,7 @@ func Setup(
},
)).Methods(http.MethodGet)
- v1fedmux.Handle("/state_ids/{roomID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/state_ids/{roomID}", MakeFedAPI(
"federation_get_state_ids", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -215,7 +219,7 @@ func Setup(
},
)).Methods(http.MethodGet)
- v1fedmux.Handle("/event_auth/{roomID}/{eventID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/event_auth/{roomID}/{eventID}", MakeFedAPI(
"federation_get_event_auth", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -230,7 +234,7 @@ func Setup(
},
)).Methods(http.MethodGet)
- v1fedmux.Handle("/query/directory", httputil.MakeFedAPI(
+ v1fedmux.Handle("/query/directory", MakeFedAPI(
"federation_query_room_alias", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
return RoomAliasToID(
@@ -239,7 +243,7 @@ func Setup(
},
)).Methods(http.MethodGet)
- v1fedmux.Handle("/query/profile", httputil.MakeFedAPI(
+ v1fedmux.Handle("/query/profile", MakeFedAPI(
"federation_query_profile", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
return GetProfile(
@@ -248,7 +252,7 @@ func Setup(
},
)).Methods(http.MethodGet)
- v1fedmux.Handle("/user/devices/{userID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/user/devices/{userID}", MakeFedAPI(
"federation_user_devices", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
return GetUserDevices(
@@ -258,7 +262,7 @@ func Setup(
)).Methods(http.MethodGet)
if mscCfg.Enabled("msc2444") {
- v1fedmux.Handle("/peek/{roomID}/{peekID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/peek/{roomID}/{peekID}", MakeFedAPI(
"federation_peek", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -289,7 +293,7 @@ func Setup(
)).Methods(http.MethodPut, http.MethodDelete)
}
- v1fedmux.Handle("/make_join/{roomID}/{userID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/make_join/{roomID}/{userID}", MakeFedAPI(
"federation_make_join", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -320,7 +324,7 @@ func Setup(
},
)).Methods(http.MethodGet)
- v1fedmux.Handle("/send_join/{roomID}/{eventID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/send_join/{roomID}/{eventID}", MakeFedAPI(
"federation_send_join", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -352,7 +356,7 @@ func Setup(
},
)).Methods(http.MethodPut)
- v2fedmux.Handle("/send_join/{roomID}/{eventID}", httputil.MakeFedAPI(
+ v2fedmux.Handle("/send_join/{roomID}/{eventID}", MakeFedAPI(
"federation_send_join", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -369,7 +373,7 @@ func Setup(
},
)).Methods(http.MethodPut)
- v1fedmux.Handle("/make_leave/{roomID}/{eventID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/make_leave/{roomID}/{eventID}", MakeFedAPI(
"federation_make_leave", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -386,7 +390,7 @@ func Setup(
},
)).Methods(http.MethodGet)
- v1fedmux.Handle("/send_leave/{roomID}/{eventID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/send_leave/{roomID}/{eventID}", MakeFedAPI(
"federation_send_leave", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -418,7 +422,7 @@ func Setup(
},
)).Methods(http.MethodPut)
- v2fedmux.Handle("/send_leave/{roomID}/{eventID}", httputil.MakeFedAPI(
+ v2fedmux.Handle("/send_leave/{roomID}/{eventID}", MakeFedAPI(
"federation_send_leave", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -442,7 +446,7 @@ func Setup(
},
)).Methods(http.MethodGet)
- v1fedmux.Handle("/get_missing_events/{roomID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/get_missing_events/{roomID}", MakeFedAPI(
"federation_get_missing_events", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -455,7 +459,7 @@ func Setup(
},
)).Methods(http.MethodPost)
- v1fedmux.Handle("/backfill/{roomID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/backfill/{roomID}", MakeFedAPI(
"federation_backfill", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -474,14 +478,14 @@ func Setup(
}),
).Methods(http.MethodGet, http.MethodPost)
- v1fedmux.Handle("/user/keys/claim", httputil.MakeFedAPI(
+ v1fedmux.Handle("/user/keys/claim", MakeFedAPI(
"federation_keys_claim", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
return ClaimOneTimeKeys(httpReq, request, keyAPI, cfg.Matrix.ServerName)
},
)).Methods(http.MethodPost)
- v1fedmux.Handle("/user/keys/query", httputil.MakeFedAPI(
+ v1fedmux.Handle("/user/keys/query", MakeFedAPI(
"federation_keys_query", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
return QueryDeviceKeys(httpReq, request, keyAPI, cfg.Matrix.ServerName)
@@ -518,3 +522,67 @@ func ErrorIfLocalServerNotInRoom(
}
return nil
}
+
+// MakeFedAPI makes an http.Handler that checks matrix federation authentication.
+func MakeFedAPI(
+ metricsName string,
+ serverName gomatrixserverlib.ServerName,
+ keyRing gomatrixserverlib.JSONVerifier,
+ wakeup *FederationWakeups,
+ f func(*http.Request, *gomatrixserverlib.FederationRequest, map[string]string) util.JSONResponse,
+) http.Handler {
+ h := func(req *http.Request) util.JSONResponse {
+ fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest(
+ req, time.Now(), serverName, keyRing,
+ )
+ if fedReq == nil {
+ return errResp
+ }
+ // add the user to Sentry, if enabled
+ hub := sentry.GetHubFromContext(req.Context())
+ if hub != nil {
+ hub.Scope().SetTag("origin", string(fedReq.Origin()))
+ hub.Scope().SetTag("uri", fedReq.RequestURI())
+ }
+ defer func() {
+ if r := recover(); r != nil {
+ if hub != nil {
+ hub.CaptureException(fmt.Errorf("%s panicked", req.URL.Path))
+ }
+ // re-panic to return the 500
+ panic(r)
+ }
+ }()
+ go wakeup.Wakeup(req.Context(), fedReq.Origin())
+ vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
+ if err != nil {
+ return util.MatrixErrorResponse(400, "M_UNRECOGNISED", "badly encoded query params")
+ }
+
+ jsonRes := f(req, fedReq, vars)
+ // do not log 4xx as errors as they are client fails, not server fails
+ if hub != nil && jsonRes.Code >= 500 {
+ hub.Scope().SetExtra("response", jsonRes)
+ hub.CaptureException(fmt.Errorf("%s returned HTTP %d", req.URL.Path, jsonRes.Code))
+ }
+ return jsonRes
+ }
+ return httputil.MakeExternalAPI(metricsName, h)
+}
+
+type FederationWakeups struct {
+ FsAPI *fedInternal.FederationInternalAPI
+ origins sync.Map
+}
+
+func (f *FederationWakeups) Wakeup(ctx context.Context, origin gomatrixserverlib.ServerName) {
+ key, keyok := f.origins.Load(origin)
+ if keyok {
+ lastTime, ok := key.(time.Time)
+ if ok && time.Since(lastTime) < time.Minute {
+ return
+ }
+ }
+ f.FsAPI.MarkServersAlive([]gomatrixserverlib.ServerName{origin})
+ f.origins.Store(origin, time.Now())
+}
diff --git a/federationapi/routing/send.go b/federationapi/routing/send.go
index b9b6d33b..55a11367 100644
--- a/federationapi/routing/send.go
+++ b/federationapi/routing/send.go
@@ -83,7 +83,7 @@ func Send(
txnID gomatrixserverlib.TransactionID,
cfg *config.FederationAPI,
rsAPI api.FederationRoomserverAPI,
- keyAPI keyapi.KeyInternalAPI,
+ keyAPI keyapi.FederationKeyAPI,
keys gomatrixserverlib.JSONVerifier,
federation *gomatrixserverlib.FederationClient,
mu *internal.MutexByRoom,
@@ -183,7 +183,7 @@ func Send(
type txnReq struct {
gomatrixserverlib.Transaction
rsAPI api.FederationRoomserverAPI
- keyAPI keyapi.KeyInternalAPI
+ keyAPI keyapi.FederationKeyAPI
ourServerName gomatrixserverlib.ServerName
keys gomatrixserverlib.JSONVerifier
federation txnFederationClient