That's what this project showcases.

Currently there are three viable methods to communicate with a server after page load:
- HTTP requests
- Websockets
- WebRTC
All three support reliable-and-ordered communication (i.e.: streams), but WebRTC distinguishes itself by supporting unreliable and unordered packets too. Removing these constraints can drastically improve latency in many cases. Ordering relative to other packets is generally not required, and packets relaying high-frequency information can afford to miss a couple so long as the most up-to-date one arrives.
This demo utilises both the reliable-ordered mode for sending chat messages, and an unreliable-unordered mode for sending realtime user input (a 'wave' button).
It turns out getting WebRTC working is quite an ordeal.
In this project, I've rolled a webserver (which provides the webpage), a WebRTC signalling subsystem, the WebRTC peer connection code, and the 'chat app' logic into a single program.
This is how the connection is established:
- Provide the client with a client applet (
index.html) via the webserver (currentlyaxum) - Client POSTs a WebRTC
offervia./connect. The offer is a single communication channel. - Webserver communicates with the signalling system to create a response.
- A WebRTC peer on the server is created from the
offerwith a short lifetime. - The
acceptSTP message along with the direct connect ICE candidates are sent back as a JSON object.- These candidates (serverside running
collect_ice_candidates()) are the Client's IP as seen by the server and the server's LAN IP.
- These candidates (serverside running
- A WebRTC peer on the server is created from the
- Client processes the response and attempts to connect as a WebRTC peer to the server.
- Server's WebRTC peer accepts the connection.
- Server's application takes control of the connection and communicates over the channel.
There's talk of a Raw UDP Socket Api which could replace WebRTC for unreliable-mode, but could be slower for reliable-mode since more processing needs to be done in JS-land instead of Browserville.
The server will recognise network-related disconnects as end-of-session. A real application may attempt to restore the session instead.
These also constitute an end-of-session:
- Trying to send a packet but the channel is closed
- The WebRTC connection status swaps to 'failed'
To build this project, you will need:
- The rust build system
cargo - A node-like build tool (e.g.:
pnpm) makemakes building for release a bit more convenient. Else you just type a few commands.
cargo runwill host the web server. Static pages will be served from./webclient/distrelative to working directory.pnpm devwill run the parcel server in the background, automatically rebuilding the web pages as you change the source. Changes are visible as soon as you refresh the page (take care with browser-side caching).
make releaseor type the commands contained into your terminal- Output is a single file
./target/release/webrtc_native_receiver.exethat has static assets built in.
- Statically bundles assets on release build both uncompressed and with brotli compression, serve the correct form.
- Minify web assets with
parcel - Typescript support for webpages (+demo)
Packets are characterised by their direction, packet id (u8), and their length.
Types:
str:uvarintlength (bytes), thenutf8encoded bufferexhaustive_strautf8buffer that reads to the end of the packet.uvarint: Unsigned variable length integer. Little endian encoded, setting the top bit of the byte indicates more the next byte contains 7 more bits. Max length is 4 bytes -> 28 bits (top bit of last byte is ignored).sessionid: 64 bits /[8]u8[]T:uvarintlength prefixed array of typeT.
C2S (client to server)
0; Hello- If contains a
sessionidthat's nonzero; Reintroduce
- If contains a
1; Send messageexhaustive_strbody
2; Set nameexhaustive_strname
3; Goodbye. Ends the existing session4; (Unreliable channel). Wave button. 1/true indicates waving, 0/false indicates released. Sends 10x per second.
S2C (server to client)
0; HelloReply- Contains the new
sessionidof the client. The client caches their sessionid between connections. If the sessionid returned by the server does not match the client's record, then the server does not recognise the client and a new session is starting - Also contains your initial
exhaustive_strusername.
- Contains the new
1; Receive messagestrbody
2; Set name responsestrnew name, or old name if the change was denied
3; Lobby info[]strOnline users and their usernames Sent to the client whenever someone enters, exits, or is lost from the lobby.
