From dc05890407daeea1468a8c3f7469f85d36054c01 Mon Sep 17 00:00:00 2001 From: David Sheldrick Date: Sat, 16 Mar 2024 10:21:37 +0000 Subject: [PATCH] [sync] allow connections from v4 clients (#3173) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See discussion on discord in development channel ### Change Type - [ ] `sdk` — Changes the tldraw SDK - [x] `dotcom` — Changes the tldraw.com web app - [ ] `docs` — Changes to the documentation, examples, or templates. - [ ] `vs code` — Changes to the vscode plugin - [ ] `internal` — Does not affect user-facing stuff - [x] `bugfix` — Bug fix - [ ] `feature` — New feature - [ ] `improvement` — Improving existing features - [ ] `chore` — Updating dependencies, other boring stuff - [ ] `galaxy brain` — Architectural changes - [ ] `tests` — Changes to any test code - [ ] `tools` — Changes to infrastructure, CI, internal scripts, debugging tools, etc. - [ ] `dunno` — I don't know ### Test Plan 1. Add a step-by-step description of how to test your PR here. 2. - [ ] Unit Tests - [ ] End to end tests ### Release Notes - Add a brief release note for your PR here. --- packages/tlsync/src/lib/RoomSession.ts | 1 + packages/tlsync/src/lib/TLSyncClient.ts | 7 +++++++ packages/tlsync/src/lib/TLSyncRoom.ts | 20 ++++++++++++++++--- packages/tlsync/src/lib/protocol.ts | 1 + .../tlsync/src/test/upgradeDowngrade.test.ts | 2 +- 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/packages/tlsync/src/lib/RoomSession.ts b/packages/tlsync/src/lib/RoomSession.ts index 69c25be0a..b4b3f45bc 100644 --- a/packages/tlsync/src/lib/RoomSession.ts +++ b/packages/tlsync/src/lib/RoomSession.ts @@ -33,6 +33,7 @@ export type RoomSession = state: typeof RoomSessionState.Connected sessionKey: string presenceId: string + isV4Client: boolean socket: TLRoomSocket serializedSchema: SerializedSchema lastInteractionTime: number diff --git a/packages/tlsync/src/lib/TLSyncClient.ts b/packages/tlsync/src/lib/TLSyncClient.ts index 987042531..46b0b99e6 100644 --- a/packages/tlsync/src/lib/TLSyncClient.ts +++ b/packages/tlsync/src/lib/TLSyncClient.ts @@ -367,6 +367,13 @@ export class TLSyncClient = Store console.error('Restarting socket') this.socket.restart() break + // legacy v4 events + case 'patch': + case 'push_result': + if (!this.isConnectedToRoom) break + this.incomingDiffBuffer.push(event) + this.scheduleRebase() + break case 'data': // wait for a connect to succeed before processing more events if (!this.isConnectedToRoom) break diff --git a/packages/tlsync/src/lib/TLSyncRoom.ts b/packages/tlsync/src/lib/TLSyncRoom.ts index 25b643028..a815329e2 100644 --- a/packages/tlsync/src/lib/TLSyncRoom.ts +++ b/packages/tlsync/src/lib/TLSyncRoom.ts @@ -413,7 +413,9 @@ export class TLSyncRoom { } else { if (session.debounceTimer === null) { // this is the first message since the last flush, don't delay it - session.socket.sendMessage({ type: 'data', data: [message] }) + session.socket.sendMessage( + session.isV4Client ? message : { type: 'data', data: [message] } + ) session.debounceTimer = setTimeout( () => this._flushDataMessages(sessionKey), @@ -440,7 +442,14 @@ export class TLSyncRoom { session.debounceTimer = null if (session.outstandingDataMessages.length > 0) { - session.socket.sendMessage({ type: 'data', data: session.outstandingDataMessages }) + if (session.isV4Client) { + // v4 clients don't support the "data" message, so we need to send each message separately + for (const message of session.outstandingDataMessages) { + session.socket.sendMessage(message) + } + } else { + session.socket.sendMessage({ type: 'data', data: session.outstandingDataMessages }) + } session.outstandingDataMessages.length = 0 } } @@ -662,7 +671,11 @@ export class TLSyncRoom { // if the protocol versions don't match, disconnect the client // we will eventually want to try to make our protocol backwards compatible to some degree // and have a MIN_PROTOCOL_VERSION constant that the TLSyncRoom implements support for - if (message.protocolVersion == null || message.protocolVersion < TLSYNC_PROTOCOL_VERSION) { + const isV4Client = message.protocolVersion === 4 && TLSYNC_PROTOCOL_VERSION === 5 + if ( + message.protocolVersion == null || + (message.protocolVersion < TLSYNC_PROTOCOL_VERSION && !isV4Client) + ) { this.rejectSession(session, TLIncompatibilityReason.ClientTooOld) return } else if (message.protocolVersion > TLSYNC_PROTOCOL_VERSION) { @@ -688,6 +701,7 @@ export class TLSyncRoom { state: RoomSessionState.Connected, sessionKey: session.sessionKey, presenceId: session.presenceId, + isV4Client, socket: session.socket, serializedSchema: sessionSchema, lastInteractionTime: Date.now(), diff --git a/packages/tlsync/src/lib/protocol.ts b/packages/tlsync/src/lib/protocol.ts index d7ca22cd8..9bc21d364 100644 --- a/packages/tlsync/src/lib/protocol.ts +++ b/packages/tlsync/src/lib/protocol.ts @@ -39,6 +39,7 @@ export type TLSocketServerSentEvent = type: 'pong' } | { type: 'data'; data: TLSocketServerSentDataEvent[] } + | TLSocketServerSentDataEvent /** @public */ export type TLSocketServerSentDataEvent = diff --git a/packages/tlsync/src/test/upgradeDowngrade.test.ts b/packages/tlsync/src/test/upgradeDowngrade.test.ts index 58f8d5317..c984fdc8c 100644 --- a/packages/tlsync/src/test/upgradeDowngrade.test.ts +++ b/packages/tlsync/src/test/upgradeDowngrade.test.ts @@ -362,7 +362,7 @@ test('clients using an out-of-date protocol will receive compatibility errors', type: 'connect', connectRequestId: 'test', lastServerClock: 0, - protocolVersion: TLSYNC_PROTOCOL_VERSION - 1, + protocolVersion: TLSYNC_PROTOCOL_VERSION - 2, schema: schemaV2.serialize(), })