Draft: Unreliable+unordered WebRTC data channel transport for Snowflake rev2
This merge request adds a non-production-ready version of snowflake that use udp like transport mode to reduce abstraction cost. It is based on the rev1 version at !219 (closed), which is based on https://gitlab.torproject.org/shelikhoo/snowflake/-/tree/dev-speedwithudp?ref_type=heads .
There are some script ready for testing: https://gist.github.com/xiaokangwang/3dc8f703879cbd3764f8ed6dfa2da047
To build the code, run build.sh
with Dockerfile
in the same directory.
To start the network, run start_network.sh
.
See run a client
for example for how to get a client working.
Addresses #40352.
Summary of Changes
The primary change is not changed and remain the same, copied from @dcf 's summary.
These changes aim to let the WebRTC link between client and proxy use an unreliable, unordered (UDP-like) data channel, in place of the reliable, ordered (TCP-like) data channels that are now used. Packets from KCP, instead of being getting length-prefixed and written into the data channel stream, are written 1:1 as discrete data channel messages. Any retransmission or reordering of message payloads is the responsibility of KCP, not of the data channel.
The core change is here, where
Ordered = false
andMaxRetransmits = 0
are passed towebrtc.DataChannelInit
. (Compare RFC 8831: "Limiting the number of retransmissions to zero, combined with unordered delivery, provides a UDP-like service where each user message is sent exactly once and delivered in the order received.")
As for the transfer the ClientID, it is now transfer with the protocol field of the channel opening message. Here is a break down of different version of channel opening messages:
Current:
(empty)
Rev1:
u
Rev2:
u
+ [Space] + hex(ClientID
)
The proxy will transfer the entire proxy field as a http query parameter and send it to server, without looking into it.
The server is the one that will parse the protocl field back to its components.
On the client side, the client id is now generated by caller and then propagated to different part of instances.