Skip to content

Canvas Client

The CanvasClient is the primary integration point for applications. It manages the network connection, session state, and synchronizes the local simulation with the authoritative Canvas Server.

The client aggregates several specialized sub-systems to handle different aspects of the protocol. It implements the IDataProvider interface, allowing it to feed data directly into the SceneGraph.

classDiagram
    class Application {
        +update()
        +render()
    }

    class CanvasClient {
        +connect()
        +poll()
        -SessionHandle session
        -ConnectionHandle connection
    }

    class AssetClient {
        +resolve()
        +fetch()
        +upload()
    }

    class SessionManager {
        +createSession()
        +joinSession()
    }

    Application --> CanvasClient : Owns
    CanvasClient *-- AssetClient : Contains
    CanvasClient *-- SessionManager : Uses
    CanvasClient --|> IDataProvider : Implements

The client operates as a state machine managing the connection to the Entropy Grid.

  1. Discovery: The application uses CanvasDiscovery to find running Entropy instances (e.g., local daemon checking /tmp/canvasengine.sock or Windows pipes).
  2. Connection: CanvasClient::connect() initiates the transport layer.
  3. Handshake: The client negotiates protocol version and capabilities.
  4. Session: Once established, the client enters the “Synced” state and begins receiving Scene Snapshots.
  5. Heartbeat: A dedicated background thread maintains connection health (startHeartbeatTimer).
sequenceDiagram
    participant App
    participant Disc as CanvasDiscovery
    participant Client as CanvasClient
    participant Server

    App->>Disc: findLocal()
    Disc->>Server: Probe (/tmp/canvasengine.sock)
    Server-->>Disc: Active (Version 1.2)
    Disc-->>App: List<Endpoint>

    App->>Client: connect(Endpoint)
    Client->>Server: Handshake(ClientInfo)
    Server-->>Client: SessionAccepted
    
    loop Heartbeat Thread
        Client->>Server: Ping
        Server-->>Client: Pong
    end

The CanvasClient is designed for Main-Thread Integration with Background I/O.

  • Main Thread: poll() must be called here. It processes the incoming message queue and triggers callbacks (e.g., EntityCreated, PropertyUpdate) safely within the application’s frame loop.
  • Network Thread: Underlying transport (Asio/WebRTC) runs on efficiently managed background threads.
  • Heartbeat Thread: A dedicated std::thread ensures connection liveness even if the main application loop stalls.

The CanvasClient exposes specialized clients for specific data types:

  • AssetClient: Generic asset operations. Handles chunked uploads and encrypted streams.
  • TextureClient: Optimized texture streaming.
  • ShaderClient: Shader compilation and variant management.

The recommended integration pattern is to poll the client in the application’s main loop to ensure thread safety for ECS synchronization:

CanvasClient client;
if (client.connect(endpoint)) {
while (app.running()) {
client.poll(); // Process network messages on main thread
// Sync ECS or Scene Graph
client.syncWorld(flecsWorld);
app.render();
}
}