-
Notifications
You must be signed in to change notification settings - Fork 450
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add basic handshake negotiation #341
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This change updates how the client and server communicate when first connecting, in a non-breaking way. ## Current behaviour - client creates and connects to a socket - client constructs a `Connection` object with the socket - the backend binds to the socket and constructs an `Agent` - the `Agent` sends an `init` message down the socket when constructed - the `Connection` receives the `init` message and initialises itself using information in the message ## Motivation for change There are currently a few things that would be nice to "negotiate" when a client connects. For example, clients may wish to: - the same `src` value when reconnecting, so that it persists as a stable "session ID" - set their default type - establish the exact versions of OT types being used - establish plugins and versions to use More detail can be found here: #337 ## New behaviour - client creates and connects to a socket - client constructs a `Connection` object with the socket - the backend binds to the socket and constructs an `Agent` - the `Agent` sends an `init` message down the socket when constructed - **new behaviour starts here** - the `Connection` checks the `init` message to see if the backend is capable of handshaking - if the backend _cannot_ handshake (ie it's old), then the client initialises itself as before - if the backend _can_ handshake, then it will disregard the `init` message, and send its own `hs` "handshake" message to the server - the backend receives the handshake message and sends a response - the `Connection` receives the new `hs` message and initialises itself using information in the message (like before, but with more or different information information) ## Other changes No changes have been made to the information being shared. In other words, this commit only updates the way in which the backend and the client communicate when first connecting. As a convenience for some tests, which had to be tweaked (because they assumed the connection was established immediately), this change also adds an optional `callback` parameter to `Backend.connect`, which will be invoked once the connection handshake completes.
Right now, whenever a `Connection` is disconnected it: - sets its ID to `null` - resets its `seq` to `1` - clears its `Agent` This makes it difficult for the server, and for remote clients, to keep track of who is represented by a given ID (or `src`). This change uses the new handshake protocol to allow the client to keep its existing ID, so that it can persist even across a reconnection.
Previously, `seq` would get reset every time a client reconnects. Whilst not entirely robust, it did help to mitigate the possibility that very long-lived connections might hit an integer overflow when incrementing their `seq`. This change adds a guard against this case, and throws a sensible error, both on the client, and on the server. Note that we cannot rely on the client's `Number.MAX_SAFE_INTEGER`, because it is not supported by Internet Explorer.
alecgibson
commented
Jan 30, 2020
alecgibson
commented
Jan 30, 2020
alecgibson
commented
Jan 30, 2020
alecgibson
commented
Jan 30, 2020
alecgibson
commented
Feb 5, 2020
ericyhwang
reviewed
Feb 5, 2020
This change moves the handshake initialisation to the socket's `onopen`. This avoids us having to wait for a message from the server before initiating the handshake, saving us half a round-trip. It should also make it easier to eventually refactor out the legacy initialisation.
This change adds an `Agent.src` field, which will accept a client-provided ID. This is kept separate from the Agent-generated `clientId` so that the agent's ID does not change during the handshake (which could confuse any consumers relying on a stable client ID in the `connect` middleware). Any internal references to `clientId` then give precedence to the consumer-provided `src`. If it hasn't been set (ie we're dealing with a legacy client), then we fall back to using `clientId`.
This change adds a "legacy" version of ShareDB as a development dependency so that we can unit test the new handshake logic against old clients.
ericyhwang
approved these changes
Feb 19, 2020
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This change updates how the client and server communicate when first
connecting, in a non-breaking way.
Current behaviour
Connection
object with the socketAgent
Agent
sends aninit
message down the socket when constructedConnection
receives theinit
message and initialises itselfusing information in the message
Motivation for change
There are currently a few things that would be nice to "negotiate" when
a client connects. For example, clients may wish to:
src
value when reconnecting, so that it persists as astable "session ID" (which has been implemented here)
More detail can be found here: #337
New behaviour
Connection
object with the socketAgent
Agent
sends aninit
message down the socket when constructedConnection
checks theinit
message to see if the backend iscapable of handshaking
initialises itself as before
init
message, and send its own
hs
"handshake" message to the serverConnection
receives the newhs
message and initialises itselfusing information in the message (like before, but with more or
different information information)
Other changes
As a convenience for some tests, which had to be tweaked (because they
assumed the connection was established immediately), this change also
adds an optional
callback
parameter toBackend.connect
, which willbe invoked once the connection handshake completes.
We also add a guard for arbitrarily large
seq
, which will no longer bereset on reconnection, so might hit integer overflow on particularly
long-lived
Connection
objects.