package clientapi import ( "net/http" "github.com/dariuszjaniak/warp/server/internal/httputil" "github.com/dariuszjaniak/warp/server/internal/userapi" ) // syncResponse is the subset of the /sync body that is meaningful before // there are any rooms. type syncResponse struct { NextBatch string `json:"next_batch"` Rooms syncRooms `json:"rooms"` Presence syncEventList `json:"presence"` AccountData syncEventList `json:"account_data"` ToDevice syncEventList `json:"to_device"` DeviceLists syncDeviceLists `json:"device_lists"` } type syncRooms struct { Join map[string]any `json:"join"` Invite map[string]any `json:"invite"` Leave map[string]any `json:"leave"` Knock map[string]any `json:"knock"` } type syncEventList struct { Events []any `json:"events"` } type syncDeviceLists struct { Changed []string `json:"changed"` Left []string `json:"left"` } // syncPlaceholderToken is the only stream position Phase 1 can be at. // // It is a real token shape rather than an empty string so that a client // storing it and sending it back as ?since= gets the same answer, which is // the correct one: nothing has happened. const syncPlaceholderToken = "s0_0" // handleSync implements GET /_matrix/client/v3/sync as far as Phase 1 can. // // This is a placeholder, and deliberately a working one. There are no rooms // until Phase 3 and no event streams until Phase 4, so an empty sync is not // a lie — it is the complete state of this server. What it buys in the // meantime is the thing every client and the test suite check first: that a // valid token syncs and a revoked one does not. Without it, "logging out // invalidates the session" cannot be observed at all. // // Phase 4 replaces this wholesale with the syncapi: stream tokens, long // polling, filters and lazy-loaded members. func (c *ClientAPI) handleSync(w http.ResponseWriter, _ *http.Request, _ userapi.Authenticated) error { // The `timeout` parameter is ignored rather than honoured: blocking for // 30 seconds to return a response that cannot change would hold a // connection open for nothing. httputil.WriteJSON(w, http.StatusOK, syncResponse{ NextBatch: syncPlaceholderToken, Rooms: syncRooms{ Join: map[string]any{}, Invite: map[string]any{}, Leave: map[string]any{}, Knock: map[string]any{}, }, Presence: syncEventList{Events: []any{}}, AccountData: syncEventList{Events: []any{}}, ToDevice: syncEventList{Events: []any{}}, DeviceLists: syncDeviceLists{Changed: []string{}, Left: []string{}}, }) return nil }