cloud-game
cloud-game copied to clipboard
New net code
This PR contains updated network code. The basic communication architecture was left intact.
Changelog
- All network client IDs now have custom type
network.Uid
backed by gofrs' UUID(v4) lib and a byte slice.The string representation of a UUID takes 32 bytes, and the new type will take just 16. Because of Golang JSON serialization problems with omitting zero-length empty slices (it can't) and the need to use UID values as map keys (maps don't support slices as keys), IDs are stored as strings (for now).
- A whole new WebSocket client/server implementation was added, as well as a new communication layer with synchronous and async call handlers.
- WebSocket connections now support dedicated Ping/Pong frames as opposed to original ping text messages.
- Used Gorilla WebSocket library doesn't allow concurrent (simultaneous) reads and writes, so this part was handled via send channel synchronization.
- New API structures can be found in the
pkg/api
folder. - Updated communication protocol is based on JSON-encoded messaging through WebSocket and has the following structure:
Packet [id] string — a globally unique identification tag for the packet to track it trough a chain of requests. t uint8 — contains packet type information (i.e. INIT_PACKET, SDP_OFFER_PACKET, ...). [p] interface{} — contains packet data (any type). Each packet is a text message in JSON-serialized form (WebSocket control frames obviously not).
The main principle of this protocol and the duplex data exchange is: the one who initializes connection is called a client, and the one who is being connected to is called a server. With the current architecture, the coordinator is the server, the user browsers and workers are the clients. ____ ____ ↓ ↑ ↑ ↓ browser ⟶ coordinator ⟵ worker (c) (s) (c) One of the most crucial performance vise parts of these interactions is that all the server-initiated calls to clients should be asynchronous only!
- In order to track synchronous calls (packets) with an asynchronous protocol, such as WebSocket, each packet may have an
id
that should be copied in all subsequent requests/responses. - The old
sessionID
param was replaced byid
that should be stored inside thep
(payload) part of the packet.
- In order to track synchronous calls (packets) with an asynchronous protocol, such as WebSocket, each packet may have an
- It is possible to skip the default ping check for all connected workers on every user connection and just pick the first available with the new
roundRobin
param in the coordinator config file.coordinator: # get any free workers unconditionally on user connection roundRobin: true ...
- Added structured logging system (zerolog) for better logging and cloud services integration.
TODO
- [x] Fix slow worker retention on user disconnect.
- [ ] Migrate CI
- [ ] Use state machine for async initialization procedure.
- [ ] Update STREAMING.md.
- [ ] Check socket read crash when a debugger enabled