diff --git a/src/github.com/matrix-org/dendrite/clientapi/routing/routing.go b/src/github.com/matrix-org/dendrite/clientapi/routing/routing.go index b32ddf147..2d71d14d6 100644 --- a/src/github.com/matrix-org/dendrite/clientapi/routing/routing.go +++ b/src/github.com/matrix-org/dendrite/clientapi/routing/routing.go @@ -352,23 +352,4 @@ func Setup( return util.JSONResponse{Code: 200, JSON: struct{}{}} }), ).Methods("PUT", "OPTIONS") - - // Stub implementations for sytest - r0mux.Handle("/events", - common.MakeExternalAPI("events", func(req *http.Request) util.JSONResponse { - return util.JSONResponse{Code: 200, JSON: map[string]interface{}{ - "chunk": []interface{}{}, - "start": "", - "end": "", - }} - }), - ).Methods("GET") - - r0mux.Handle("/initialSync", - common.MakeExternalAPI("initial_sync", func(req *http.Request) util.JSONResponse { - return util.JSONResponse{Code: 200, JSON: map[string]interface{}{ - "end": "", - }} - }), - ).Methods("GET") } diff --git a/src/github.com/matrix-org/dendrite/cmd/dendrite-monolith-server/main.go b/src/github.com/matrix-org/dendrite/cmd/dendrite-monolith-server/main.go index 811c708ac..3567dda17 100644 --- a/src/github.com/matrix-org/dendrite/cmd/dendrite-monolith-server/main.go +++ b/src/github.com/matrix-org/dendrite/cmd/dendrite-monolith-server/main.go @@ -336,7 +336,7 @@ func (m *monolith) setupAPIs() { syncapi_routing.Setup(m.api, syncapi_sync.NewRequestPool( m.syncAPIDB, m.syncAPINotifier, m.accountDB, - ), m.deviceDB) + ), m.deviceDB, m.syncAPIDB) federationapi_routing.Setup( m.api, *m.cfg, m.queryAPI, m.roomServerProducer, m.keyRing, m.federation, diff --git a/src/github.com/matrix-org/dendrite/cmd/dendrite-sync-api-server/main.go b/src/github.com/matrix-org/dendrite/cmd/dendrite-sync-api-server/main.go index ec6eebb64..d180c3de6 100644 --- a/src/github.com/matrix-org/dendrite/cmd/dendrite-sync-api-server/main.go +++ b/src/github.com/matrix-org/dendrite/cmd/dendrite-sync-api-server/main.go @@ -104,7 +104,7 @@ func main() { log.Info("Starting sync server on ", cfg.Listen.SyncAPI) api := mux.NewRouter() - routing.Setup(api, sync.NewRequestPool(db, n, adb), deviceDB) + routing.Setup(api, sync.NewRequestPool(db, n, adb), deviceDB, db) common.SetupHTTPAPI(http.DefaultServeMux, api) log.Fatal(http.ListenAndServe(string(cfg.Listen.SyncAPI), nil)) diff --git a/src/github.com/matrix-org/dendrite/syncapi/routing/routing.go b/src/github.com/matrix-org/dendrite/syncapi/routing/routing.go index 5bad22b53..ecb296007 100644 --- a/src/github.com/matrix-org/dendrite/syncapi/routing/routing.go +++ b/src/github.com/matrix-org/dendrite/syncapi/routing/routing.go @@ -21,6 +21,7 @@ import ( "github.com/matrix-org/dendrite/clientapi/auth/authtypes" "github.com/matrix-org/dendrite/clientapi/auth/storage/devices" "github.com/matrix-org/dendrite/common" + "github.com/matrix-org/dendrite/syncapi/storage" "github.com/matrix-org/dendrite/syncapi/sync" "github.com/matrix-org/util" ) @@ -28,7 +29,12 @@ import ( const pathPrefixR0 = "/_matrix/client/r0" // Setup configures the given mux with sync-server listeners -func Setup(apiMux *mux.Router, srp *sync.RequestPool, deviceDB *devices.Database) { +func Setup( + apiMux *mux.Router, + srp *sync.RequestPool, + deviceDB *devices.Database, + syncDB *storage.SyncServerDatabase, +) { r0mux := apiMux.PathPrefix(pathPrefixR0).Subrouter() r0mux.Handle("/sync", common.MakeAuthAPI("sync", deviceDB, func(req *http.Request, device *authtypes.Device) util.JSONResponse { @@ -39,4 +45,23 @@ func Setup(apiMux *mux.Router, srp *sync.RequestPool, deviceDB *devices.Database vars := mux.Vars(req) return srp.OnIncomingStateRequest(req, vars["roomID"]) })).Methods("GET") + + // Stub implementations for sytest + r0mux.Handle("/events", + common.MakeExternalAPI("events", func(req *http.Request) util.JSONResponse { + return util.JSONResponse{Code: 200, JSON: map[string]interface{}{ + "chunk": []interface{}{}, + "start": "", + "end": "", + }} + }), + ).Methods("GET") + + r0mux.Handle("/initialSync", + common.MakeAuthAPI("initial_sync", deviceDB, func(req *http.Request, device *authtypes.Device) util.JSONResponse { + return sync.GetInitialSync( + req, device, syncDB, + ) + }), + ).Methods("GET") } diff --git a/src/github.com/matrix-org/dendrite/syncapi/sync/intitial_sync.go b/src/github.com/matrix-org/dendrite/syncapi/sync/intitial_sync.go new file mode 100644 index 000000000..8a3eb4dfd --- /dev/null +++ b/src/github.com/matrix-org/dendrite/syncapi/sync/intitial_sync.go @@ -0,0 +1,93 @@ +// Copyright 2017 Vector Creations Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sync + +import ( + "net/http" + + "github.com/matrix-org/dendrite/clientapi/auth/authtypes" + "github.com/matrix-org/dendrite/clientapi/httputil" + "github.com/matrix-org/dendrite/syncapi/storage" + "github.com/matrix-org/dendrite/syncapi/types" + "github.com/matrix-org/gomatrixserverlib" + "github.com/matrix-org/util" +) + +// GetInitialSync gets called on an /initialSync request. +func GetInitialSync( + req *http.Request, device *authtypes.Device, + db *storage.SyncServerDatabase, +) util.JSONResponse { + // TODO: Support limit + syncResponse, err := db.CompleteSync( + req.Context(), device.UserID, DefaultTimelineLimit, + ) + + if err != nil { + return httputil.LogThenError(req, err) + } + + intialSyncResponse := syncResponseToIntialSync(syncResponse) + + return util.JSONResponse{ + Code: 200, + JSON: intialSyncResponse, + } +} + +func syncResponseToIntialSync(syncResponse *types.Response) initialSyncResponse { + rooms := []initialSyncRoomResponse{} + + for roomID, room := range syncResponse.Rooms.Join { + rooms = append(rooms, initialSyncRoomResponse{ + RoomID: roomID, + Membership: "join", + + Messages: initialSyncChunk{ + Chunk: room.Timeline.Events, // TODO: Correctly format events + End: room.Timeline.PrevBatch, // TODO: Start? + }, + + State: initialSyncChunk{ + Chunk: room.State.Events, // TODO: Add state from timeline + }, + }) + } + + // TODO: Invites, leaves, account data, presence, etc. + + return initialSyncResponse{ + Rooms: rooms, + End: syncResponse.NextBatch, + } +} + +type initialSyncResponse struct { + End string `json:"end"` + Rooms []initialSyncRoomResponse `json:"rooms"` +} + +type initialSyncRoomResponse struct { + Membership string `json:"membership"` + RoomID string `json:"room_id"` + Messages initialSyncChunk `json:"messages,omitempty"` + State initialSyncChunk `json:"state,omitempty"` +} + +type initialSyncChunk struct { + Start string `json:"start"` + End string `json:"end"` + Chunk []gomatrixserverlib.ClientEvent `json:"chunk"` +} diff --git a/src/github.com/matrix-org/dendrite/syncapi/sync/notifier_test.go b/src/github.com/matrix-org/dendrite/syncapi/sync/notifier_test.go index 358243bc5..7090badab 100644 --- a/src/github.com/matrix-org/dendrite/syncapi/sync/notifier_test.go +++ b/src/github.com/matrix-org/dendrite/syncapi/sync/notifier_test.go @@ -286,7 +286,7 @@ func newTestSyncRequest(userID string, since types.StreamPosition) syncRequest { timeout: 1 * time.Minute, since: since, wantFullState: false, - limit: defaultTimelineLimit, + limit: DefaultTimelineLimit, log: util.GetLogger(context.TODO()), } } diff --git a/src/github.com/matrix-org/dendrite/syncapi/sync/request.go b/src/github.com/matrix-org/dendrite/syncapi/sync/request.go index e8579271f..e53d02ef7 100644 --- a/src/github.com/matrix-org/dendrite/syncapi/sync/request.go +++ b/src/github.com/matrix-org/dendrite/syncapi/sync/request.go @@ -26,7 +26,10 @@ import ( ) const defaultSyncTimeout = time.Duration(30) * time.Second -const defaultTimelineLimit = 20 + +// DefaultTimelineLimit is the default number limit of timeline entries if no +// limit was given. +const DefaultTimelineLimit = 20 // syncRequest represents a /sync request, with sensible defaults/sanity checks applied. type syncRequest struct { @@ -54,7 +57,7 @@ func newSyncRequest(req *http.Request, userID string) (*syncRequest, error) { timeout: timeout, since: since, wantFullState: wantFullState, - limit: defaultTimelineLimit, // TODO: read from filter + limit: DefaultTimelineLimit, // TODO: read from filter log: util.GetLogger(req.Context()), }, nil }