Wolf Documentation

repository·stable·Indexed 23 days ago

https://github.com/games-on-whales/wolf

A high-performance streaming server for Moonlight designed for Linux and Docker environments. Wolf enables multiple remote users to share a single host's hardware with a focus on low latency, multi-GPU support, and virtual desktop management. It manages applications via preconfigured Docker containers and provides tools for building custom app images, configuring bind mounts for data persistence, and integrating software like Steam, Pegasus, and Prism Launcher.

Tokens
23.1K
Snippets
33
Records
126
Agent score
84%

What's inside Wolf

  1. Overview of Moonlight Protocols

    stable

    The Moonlight protocol suite consists of 6 main protocols used to facilitate client pairing, app discovery, stream control, and media streaming. The flow typically begins with HTTP/HTTPS for pairing and app discovery, followed by RTSP for protocol negotiation, and finally uses Control/RTP streams for user input and media data.

    Protocol Flow Summary:

    1. HTTP/HTTPS: Used for pairing clients and exchanging available apps/encryption keys.
    2. RTSP: Used to exchange ports and settings for subsequent streams.
    3. Control/RTP: Continuous loop of exchanging user inputs and streaming video/audio data while connected.
  2. Overview of Wolf streaming server

    stable

    Wolf is an open-source streaming server designed for Moonlight. It enables multiple remote clients to share a single host hardware to play video games simultaneously.

    Key features include:

    • Multi-user support: Multiple users can stream different content using the same remote host hardware.
    • Virtual Desktops: On-demand creation of virtual desktops with support for any resolution and FPS, eliminating the need for physical monitors or dummy plugs.
    • Multi-GPU utilization: Supports using multiple GPUs simultaneously for different tasks (e.g., using an iGPU for stream encoding while gaming on a discrete GPU).
    • Low Latency: Provides low-latency video and audio streams with full gamepad support.
    • Container-first design: Built with a focus on Linux and Docker, allowing games to run with low privileges in containers via Games On Whales (GOW).
    • High Hackability: Users can modify encoding pipelines, GPU settings, and Docker/Podman low-level details by editing the configuration file.
  3. Understand the RTP audio stream protocol

    stable

    Wolf streams audio using the Opus codec, encrypted with AES CBC 128-bit, and transmitted via RTP.

    To ensure reliability over lossy networks, Wolf uses Forward Error Correction (FEC) based on Reed-Solomon. For every 4 RTP packets containing audio content, 2 additional RTP packets containing FEC parity information are sent.

    Encryption Details:

    • Algorithm: AES CBC 128-bit.
    • Key/IV: The key and Initialization Vector (IV) are exchanged via HTTPS during the launch endpoint call. These are the same credentials used for the Control stream.
  4. How Wolf handles application containers

    stable

    Wolf manages applications by starting preconfigured Docker containers (e.g., Steam, Pegasus, or Firefox) and streaming the output to a connected Moonlight client.

    Lifecycle and Persistence: When an application is opened and closed via Moonlight, the corresponding app container is deleted. This ensures application consistency but means any changes made inside the container are lost. To persist data, you must use mounted paths. For any permanent modifications to the application environment (like installing additional software), you should create a custom app image using the GoW (Games on Whales) project infrastructure.

  5. Understand the general format of INPUT_DATA messages

    stable

    Moonlight sends all user inputs via the control stream using INPUT_DATA messages. Each message follows a specific structure:

    1. Input Size (4 bytes, Big Endian): Indicates the size of the message, which varies by input type.
    2. Input Type (4 bytes, Little Endian): Specifies the type of input being sent.

    Following these header bytes is the specific data payload for the identified input type.

  6. Understand the RTSP protocol lifecycle in Wolf

    stable

    The RTSP protocol is used when a Moonlight user launches an app to exchange information about upcoming video, audio, and control streams. The interaction follows a specific sequence of commands between the Moonlight client (M) and the Wolf backend (W):

    1. OPTIONS: Initial handshake.
    2. DESCRIBE: Client requests additional parameters for audio/video.
    3. SETUP: Client requests ports for specific streams using streamid (e.g., streamid=audio, streamid=video, streamid=control).
    4. ANNOUNCE: Client sends specific configurations for all streams.
    5. PLAY: Initiates the stream playback.

    This sequence ensures the backend and client are synchronized on stream ports and configuration parameters before data begins flowing.

  7. Understand the RTP Moonlight Payloader architecture

    stable

    The Moonlight RTP Payloader plugins are implemented using GstBaseTransform as the base class. This allows the plugins to act as a direct transformation layer where an input GstBuffer is processed and converted into a GstBufferList of RTP packets.

    Data Flow

    1. Input: An encoded bitstream (e.g., H.264 or Opus) arrives as a GstBuffer.
    2. Processing: The plugin splits the data, applies encryption, adds RTP headers, and generates FEC packets.
    3. Output: A list of valid Moonlight RTP packets is pushed to the next element in the pipeline (typically a udpsink).

    Implementation Details

    The plugins are split into audio and video because they have different RTP packet structures, non-overlapping properties, different FEC encoding requirements, and different encryption requirements, despite sharing the same basic transformation logic.

  8. Share audio between pipelines using shmsink and shmsrc

    stable

    When splitting a single media stream into separate video and audio pipelines (e.g., for visualization), use shmsink in the video pipeline to write raw audio to a shared memory socket, and shmsrc in the audio pipeline to read it. This requires defining a socket-path and shm-size.

    [[apps]]
    title = "Music"
    [apps.video]
    source = """
    filesrc location=/Users/ale/Downloads/elevate.mp3 ! 
    tee name=t 
    ! queue ! shmsink socket-path=/tmp/pipe.sock shm-size=10000000
    t. ! decodebin ! audioconvert ! wavescope style=color-lines
    """
    [apps.audio]
    source = """
    shmsrc socket-path=/tmp/pipe.sock do-timestamp=true  ! 
     audio/mpeg, mpegversion=(int)1, mpegaudioversion=(int)1, layer=(int)3, rate=(int)44100, channels=(int)2 ! 
     decodebin
    """
  9. Navigate the Wolf UI screens

    stable

    Wolf UI operates through two primary screens:

    1. Profile Selection Screen: Used to choose which user profile to access. Profiles can be protected by a PIN for security.
    2. Application Selection Screen: Used to browse and launch applications for the active profile.

    Applications that are greyed out are not currently installed. You can download them directly from the UI, which pulls the necessary Docker images from the games-on-whales/gow open source registry.

  10. How the HTTP/S Pairing protocol works

    stable

    The HTTP/S Pairing protocol is a multi-phase cryptographic handshake used to securely authenticate an untrusted client (Moonlight) to a server (Wolf) over an insecure network. The process establishes a shared secret and verifies identities through five distinct phases:

    1. Phase 1 (Key Derivation): The client sends a salt and client cert. The server prompts the user for a PIN. A shared AES KEY is derived using SHA256(SALT + PIN). The server returns its public certificate (plaincert).
    2. Phase 2 (Challenge Generation): The client sends an AES-encrypted client challenge. The server decrypts it and generates a server challenge. The server then creates a hash of the Decrypted challenge, Server certificate signature, and a randomly generated server secret. This hash and the server_challenge are AES-encrypted and sent back as the challengeresponse.
    3. Phase 3 (Server Response): The client sends the serverchallengeresp (the AES-encrypted client hash). The server responds with the pairingsecret, which is a signature of the certificate_signature + server_secret created using the server's private key.
    4. Phase 4 (Verification): The client sends its client secret + signature. The server verifies the client by checking if SHA256(server_challenge + client_public_cert_signature + client_secret) == client_hash. If valid, the server returns paired = 1; otherwise, paired = 0.
    5. Phase 5 (HTTPS Validation): A final pairchallenge is performed over HTTPS to ensure the client can reach the server via a secure connection. Once paired, the server requires a valid client certificate for all subsequent API calls.