cloud-game/docs/STREAMING.md
2021-05-09 18:59:00 +03:00

6.4 KiB
Vendored

Streaming process description

This document describes the step-by-step process of media streaming through the whole application.

All begins when a player (p) opens the application page (index.html) served by the coordinator (c).

  • The user's browser tries to open a new WebSocket connection to the coordinator — socket.init(roomId, zone) web/js/network/socket.js:32

In the initial HTTP-to-WS Upgrade request query it may send two params: roomId — an identification number for already created game rooms if a user knows this ID and opens the application page with the ?id=xxxxxx query param, zone — or, more precisely, region — serves the purpose of CDN and geographical segmentation of the streaming.

  • On the coordinator side this request goes into a dedicated handler (/ws) — func (o *Server) WS(w http.ResponseWriter, r *http.Request) pkg/coordinator/handlers.go:150
  • There, it unconditionally accepts a new WebSocket connection, registers user connection with some ID in storage, starts to listen to WebSocket messages from the user's side, and a new connection should be considered as established.
  • Next, given provided query params, the coordinator tries to find a suitable worker (w) whose job is to directly stream emulated games to a user.

This process of choosing the right worker is as follows: if there is no roomId param then coordinator gathers the full list of available workers, filters them by a zone value if it's provided, sends through WebSocket back to the user a list of public worker endpoints (URLs) that the user can ping and send results back to the coordinator after that coordinator chooses the fastest one and internally assigns that worker to that user. Alternatively, if the user did provide some roomId then the coordinator directly assigns that worker which runs that room (workers have 1:1 mapping to rooms). All the information exchange initiated from the worker side is handled in a separate endpoint (/wso) pkg/coordinator/handlers.go#L81.

Following a standard WebRTC call negotiation procedure, the coordinator acts as a mediator between users and workers. Signalling protocol there are just text messages through WebSocket transport.

  • Coordinator notifies assigned to the user earlier worker that it wants to establish a new PeerConnection or (RTC call). That part is being handled in pkg/worker/internalhandlers.go:42.

It is worth noting that the worker makes SDP offer and waits for an SDP answer.

At this point all the connections should be successfully established and the user should just send a request for game start. The coordinator should notify the worker about that and the worker should start pushing A/V frames, listen to the input through the already established direct to the user WebRTC data cahnnel.

Possible streaming initialization failures

  • Worker server should not have any closed UDP ports in order to be able to provide suitable ICE candidates.
  • Coordinator should have at least one non-blocked TCP port (default: 8000) for HTTP/WebSocket signaling connections from users and workers.
  • Browser should not block WebRTC and support it (check here).