| 205 | } |
| 206 | |
| 207 | func (t *txnReq) processTransaction(ctx context.Context) (*gomatrixserverlib.RespSend, *util.JSONResponse) { |
| 208 | var wg sync.WaitGroup |
| 209 | wg.Add(1) |
| 210 | go func() { |
| 211 | defer wg.Done() |
| 212 | t.processEDUs(ctx) |
| 213 | }() |
| 214 | |
| 215 | results := make(map[string]gomatrixserverlib.PDUResult) |
| 216 | roomVersions := make(map[string]gomatrixserverlib.RoomVersion) |
| 217 | getRoomVersion := func(roomID string) gomatrixserverlib.RoomVersion { |
| 218 | if v, ok := roomVersions[roomID]; ok { |
| 219 | return v |
| 220 | } |
| 221 | verReq := api.QueryRoomVersionForRoomRequest{RoomID: roomID} |
| 222 | verRes := api.QueryRoomVersionForRoomResponse{} |
| 223 | if err := t.rsAPI.QueryRoomVersionForRoom(ctx, &verReq, &verRes); err != nil { |
| 224 | util.GetLogger(ctx).WithError(err).Debug("Transaction: Failed to query room version for room", verReq.RoomID) |
| 225 | return "" |
| 226 | } |
| 227 | roomVersions[roomID] = verRes.RoomVersion |
| 228 | return verRes.RoomVersion |
| 229 | } |
| 230 | |
| 231 | for _, pdu := range t.PDUs { |
| 232 | pduCountTotal.WithLabelValues("total").Inc() |
| 233 | var header struct { |
| 234 | RoomID string `json:"room_id"` |
| 235 | } |
| 236 | if err := json.Unmarshal(pdu, &header); err != nil { |
| 237 | util.GetLogger(ctx).WithError(err).Debug("Transaction: Failed to extract room ID from event") |
| 238 | // We don't know the event ID at this point so we can't return the |
| 239 | // failure in the PDU results |
| 240 | continue |
| 241 | } |
| 242 | roomVersion := getRoomVersion(header.RoomID) |
| 243 | event, err := gomatrixserverlib.NewEventFromUntrustedJSON(pdu, roomVersion) |
| 244 | if err != nil { |
| 245 | if _, ok := err.(gomatrixserverlib.BadJSONError); ok { |
| 246 | // Room version 6 states that homeservers should strictly enforce canonical JSON |
| 247 | // on PDUs. |
| 248 | |
| 249 | // This enforces that the entire transaction is rejected if a single bad PDU is |
| 250 | // sent. It is unclear if this is the correct behaviour or not. |
| 251 | |
| 252 | // See https://github.com/matrix-org/synapse/issues/7543 |
| 253 | return nil, &util.JSONResponse{ |
| 254 | Code: 400, |
| 255 | JSON: jsonerror.BadJSON("PDU contains bad JSON"), |
| 256 | } |
| 257 | } |
| 258 | util.GetLogger(ctx).WithError(err).Debugf("Transaction: Failed to parse event JSON of event %s", string(pdu)) |
| 259 | continue |
| 260 | } |
| 261 | if event.Type() == gomatrixserverlib.MRoomCreate && event.StateKeyEquals("") { |
| 262 | continue |
| 263 | } |
| 264 | if api.IsServerBannedFromRoom(ctx, t.rsAPI, event.RoomID(), t.Origin) { |