Skip to content
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

Preliminary Version Negotiation Support #14

Merged
merged 17 commits into from Jul 3, 2023
Merged

Conversation

btoms20
Copy link
Collaborator

@btoms20 btoms20 commented Jul 2, 2023

Preliminary Support for Version Negotiation

As described in RFC9000 - Section 6

What

This PR adds preliminary support for version negotiation at the beginning of a Connection.

How

Server Side

  • The ConnectionMuxer responds with a VersionNegotiationPacket when it encounters an InitialPacket created with an unsupported version.

Note
Server Side Connections are only instantiated with supported versions (there are no version negotiation events for server side connections)

Client Side

  • The connection is established using the first Version passed into the QUICClientHandler's initializer.
  • If we receive a VersionNegotiationPacket in response to our Initial Client Hello packet.
    • The PacketProtectorHandler cycles through our supported versions and the servers supported versions searching for the best match.
      • if we find a Version match
        • The PacketProtectorHandler fires a VersionNegotiated event down the pipeline for our StateHandler to receive.
        • The Statehandler reinitializes the NIOSSLHandler with the correct version dependent params and writes the newly generated ClientHello out to be padded and encrypted by the PacketProtectorHandler using the newly generated keys.
      • else (we don't have a supported version overlap)
        • The PacketProtectorHandler enters the .incompatible state and fires a VersionNegotiationFailed event down the pipeline for the StateHandler to receive.
        • The StateHandler is responsible for closing / terminating the connection upon receiving the event.
  • Otherwise the server agreed to our proposed version and the connection continues Handshaking normally.

Testing it

Swift Server <--> Go Client
Using the Go example code provided in the Go Client Handshake Test file. The Go Client will attempt to establish a connection using .version1. If we change our supported versions in the Quic file to only .versionDraft29 then we will trigger a Version Negotiation to take place. The Go Client, will re send the Initial Client Hello packet using the versionDraft29 spec and the connection will proceed as usual.

Swift Client <--> Go Server
Using the Go example code provided in the Go Server Handshake Test file. The Go Server supports .version2, .version1 and .versionDraft29. So we need to provide a fake / unknown version in order trigger a version negotiation. If we change .version2's tag from the correct identifier 0x6b33_43cf to an incorrect identifier of 0x2 then attempt to connect to the Go Server using the supported versions: [.version2, .version1]. We'll receive a VersionNegotiationPacket in response to the unknown version 0x2 and our PacketProtectorHandler will match on the next best supported version .version1. At which point the logic stated above plays out and the connection is established using the negotiated version, .version1.

@btoms20 btoms20 changed the title Version negotiation Preliminary Version Negotiation Support Jul 2, 2023
@btoms20 btoms20 merged commit 16a5309 into develop Jul 3, 2023
2 checks passed
@btoms20 btoms20 deleted the version-negotiation branch July 3, 2023 15:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant