aboutsummaryrefslogtreecommitdiff
path: root/federationapi/routing/send.go
diff options
context:
space:
mode:
Diffstat (limited to 'federationapi/routing/send.go')
-rw-r--r--federationapi/routing/send.go52
1 files changed, 39 insertions, 13 deletions
diff --git a/federationapi/routing/send.go b/federationapi/routing/send.go
index 1013a44c..5a9766f8 100644
--- a/federationapi/routing/send.go
+++ b/federationapi/routing/send.go
@@ -71,14 +71,28 @@ func Send(
util.GetLogger(httpReq.Context()).Infof("Received transaction %q containing %d PDUs, %d EDUs", txnID, len(t.PDUs), len(t.EDUs))
resp, err := t.processTransaction()
- if err != nil {
+ switch err.(type) {
+ // No error? Great! Send back a 200.
+ case nil:
+ return util.JSONResponse{
+ Code: http.StatusOK,
+ JSON: resp,
+ }
+ // Handle known error cases as we will return a 400 error for these.
+ case roomNotFoundError:
+ case unmarshalError:
+ case verifySigError:
+ // Handle unknown error cases. Sending 500 errors back should be a last
+ // resort as this can make other homeservers back off sending federation
+ // events.
+ default:
util.GetLogger(httpReq.Context()).WithError(err).Error("t.processTransaction failed")
return jsonerror.InternalServerError()
}
-
+ // Return a 400 error for bad requests as fallen through from above.
return util.JSONResponse{
- Code: http.StatusOK,
- JSON: resp,
+ Code: http.StatusBadRequest,
+ JSON: jsonerror.BadJSON(err.Error()),
}
}
@@ -93,6 +107,8 @@ type txnReq struct {
}
func (t *txnReq) processTransaction() (*gomatrixserverlib.RespSend, error) {
+ results := make(map[string]gomatrixserverlib.PDUResult)
+
var pdus []gomatrixserverlib.HeaderedEvent
for _, pdu := range t.PDUs {
var header struct {
@@ -100,28 +116,27 @@ func (t *txnReq) processTransaction() (*gomatrixserverlib.RespSend, error) {
}
if err := json.Unmarshal(pdu, &header); err != nil {
util.GetLogger(t.context).WithError(err).Warn("Transaction: Failed to extract room ID from event")
- return nil, err
+ return nil, unmarshalError{err}
}
verReq := api.QueryRoomVersionForRoomRequest{RoomID: header.RoomID}
verRes := api.QueryRoomVersionForRoomResponse{}
if err := t.query.QueryRoomVersionForRoom(t.context, &verReq, &verRes); err != nil {
util.GetLogger(t.context).WithError(err).Warn("Transaction: Failed to query room version for room", verReq.RoomID)
- return nil, err
+ return nil, roomNotFoundError{verReq.RoomID}
}
event, err := gomatrixserverlib.NewEventFromUntrustedJSON(pdu, verRes.RoomVersion)
if err != nil {
util.GetLogger(t.context).WithError(err).Warnf("Transaction: Failed to parse event JSON of event %q", event.EventID())
- return nil, err
+ return nil, unmarshalError{err}
}
if err := gomatrixserverlib.VerifyAllEventSignatures(t.context, []gomatrixserverlib.Event{event}, t.keys); err != nil {
util.GetLogger(t.context).WithError(err).Warnf("Transaction: Couldn't validate signature of event %q", event.EventID())
- return nil, err
+ return nil, verifySigError{event.EventID(), err}
}
pdus = append(pdus, event.Headered(verRes.RoomVersion))
}
// Process the events.
- results := map[string]gomatrixserverlib.PDUResult{}
for _, e := range pdus {
err := t.processEvent(e.Unwrap())
if err != nil {
@@ -141,7 +156,7 @@ func (t *txnReq) processTransaction() (*gomatrixserverlib.RespSend, error) {
// If we bail and stop processing then we risk wedging incoming
// transactions from that server forever.
switch err.(type) {
- case unknownRoomError:
+ case roomNotFoundError:
case *gomatrixserverlib.NotAllowed:
default:
// Any other error should be the result of a temporary error in
@@ -162,11 +177,22 @@ func (t *txnReq) processTransaction() (*gomatrixserverlib.RespSend, error) {
return &gomatrixserverlib.RespSend{PDUs: results}, nil
}
-type unknownRoomError struct {
+type roomNotFoundError struct {
roomID string
}
+type unmarshalError struct {
+ err error
+}
+type verifySigError struct {
+ eventID string
+ err error
+}
-func (e unknownRoomError) Error() string { return fmt.Sprintf("unknown room %q", e.roomID) }
+func (e roomNotFoundError) Error() string { return fmt.Sprintf("room %q not found", e.roomID) }
+func (e unmarshalError) Error() string { return fmt.Sprintf("unable to parse event: %s", e.err) }
+func (e verifySigError) Error() string {
+ return fmt.Sprintf("unable to verify signature of event %q: %s", e.eventID, e.err)
+}
func (t *txnReq) processEDUs(edus []gomatrixserverlib.EDU) {
for _, e := range edus {
@@ -213,7 +239,7 @@ func (t *txnReq) processEvent(e gomatrixserverlib.Event) error {
// that this server is unaware of.
// However generally speaking we should reject events for rooms we
// aren't a member of.
- return unknownRoomError{e.RoomID()}
+ return roomNotFoundError{e.RoomID()}
}
if !stateResp.PrevEventsExist {