mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-12-17 03:43:11 -06:00
Improve error handling in federation /send endpoint a bit
This commit is contained in:
parent
3110a81996
commit
e66344587b
|
|
@ -71,14 +71,29 @@ func Send(
|
||||||
util.GetLogger(httpReq.Context()).Infof("Received transaction %q containing %d PDUs, %d EDUs", txnID, len(t.PDUs), len(t.EDUs))
|
util.GetLogger(httpReq.Context()).Infof("Received transaction %q containing %d PDUs, %d EDUs", txnID, len(t.PDUs), len(t.EDUs))
|
||||||
|
|
||||||
resp, err := t.processTransaction()
|
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 unknownRoomError:
|
||||||
|
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")
|
util.GetLogger(httpReq.Context()).WithError(err).Error("t.processTransaction failed")
|
||||||
return jsonerror.InternalServerError()
|
return jsonerror.InternalServerError()
|
||||||
}
|
}
|
||||||
|
// Return a 400 error for bad requests as fallen through from above.
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusOK,
|
Code: http.StatusBadRequest,
|
||||||
JSON: resp,
|
JSON: jsonerror.BadJSON(err.Error()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,6 +108,8 @@ type txnReq struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *txnReq) processTransaction() (*gomatrixserverlib.RespSend, error) {
|
func (t *txnReq) processTransaction() (*gomatrixserverlib.RespSend, error) {
|
||||||
|
results := make(map[string]gomatrixserverlib.PDUResult)
|
||||||
|
|
||||||
var pdus []gomatrixserverlib.HeaderedEvent
|
var pdus []gomatrixserverlib.HeaderedEvent
|
||||||
for _, pdu := range t.PDUs {
|
for _, pdu := range t.PDUs {
|
||||||
var header struct {
|
var header struct {
|
||||||
|
|
@ -100,28 +117,27 @@ func (t *txnReq) processTransaction() (*gomatrixserverlib.RespSend, error) {
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(pdu, &header); err != nil {
|
if err := json.Unmarshal(pdu, &header); err != nil {
|
||||||
util.GetLogger(t.context).WithError(err).Warn("Transaction: Failed to extract room ID from event")
|
util.GetLogger(t.context).WithError(err).Warn("Transaction: Failed to extract room ID from event")
|
||||||
return nil, err
|
return nil, unknownRoomError{}
|
||||||
}
|
}
|
||||||
verReq := api.QueryRoomVersionForRoomRequest{RoomID: header.RoomID}
|
verReq := api.QueryRoomVersionForRoomRequest{RoomID: header.RoomID}
|
||||||
verRes := api.QueryRoomVersionForRoomResponse{}
|
verRes := api.QueryRoomVersionForRoomResponse{}
|
||||||
if err := t.query.QueryRoomVersionForRoom(t.context, &verReq, &verRes); err != nil {
|
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)
|
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)
|
event, err := gomatrixserverlib.NewEventFromUntrustedJSON(pdu, verRes.RoomVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.GetLogger(t.context).WithError(err).Warnf("Transaction: Failed to parse event JSON of event %q", event.EventID())
|
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 {
|
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())
|
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))
|
pdus = append(pdus, event.Headered(verRes.RoomVersion))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process the events.
|
// Process the events.
|
||||||
results := map[string]gomatrixserverlib.PDUResult{}
|
|
||||||
for _, e := range pdus {
|
for _, e := range pdus {
|
||||||
err := t.processEvent(e.Unwrap())
|
err := t.processEvent(e.Unwrap())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -141,7 +157,7 @@ func (t *txnReq) processTransaction() (*gomatrixserverlib.RespSend, error) {
|
||||||
// If we bail and stop processing then we risk wedging incoming
|
// If we bail and stop processing then we risk wedging incoming
|
||||||
// transactions from that server forever.
|
// transactions from that server forever.
|
||||||
switch err.(type) {
|
switch err.(type) {
|
||||||
case unknownRoomError:
|
case roomNotFoundError:
|
||||||
case *gomatrixserverlib.NotAllowed:
|
case *gomatrixserverlib.NotAllowed:
|
||||||
default:
|
default:
|
||||||
// Any other error should be the result of a temporary error in
|
// Any other error should be the result of a temporary error in
|
||||||
|
|
@ -162,11 +178,24 @@ func (t *txnReq) processTransaction() (*gomatrixserverlib.RespSend, error) {
|
||||||
return &gomatrixserverlib.RespSend{PDUs: results}, nil
|
return &gomatrixserverlib.RespSend{PDUs: results}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type unknownRoomError struct {
|
type unknownRoomError struct{}
|
||||||
|
type roomNotFoundError struct {
|
||||||
roomID string
|
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 unknownRoomError) Error() string { return "unable to extract room ID" }
|
||||||
|
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) {
|
func (t *txnReq) processEDUs(edus []gomatrixserverlib.EDU) {
|
||||||
for _, e := range edus {
|
for _, e := range edus {
|
||||||
|
|
@ -213,7 +242,7 @@ func (t *txnReq) processEvent(e gomatrixserverlib.Event) error {
|
||||||
// that this server is unaware of.
|
// that this server is unaware of.
|
||||||
// However generally speaking we should reject events for rooms we
|
// However generally speaking we should reject events for rooms we
|
||||||
// aren't a member of.
|
// aren't a member of.
|
||||||
return unknownRoomError{e.RoomID()}
|
return roomNotFoundError{e.RoomID()}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !stateResp.PrevEventsExist {
|
if !stateResp.PrevEventsExist {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue