control channel - RiftCat/vridge-api GitHub Wiki

Table of Contents

Quick facts:

  • Works as REP ZMQ socket listening at port 38219 while VRidge is running.
  • Uses JSON-serialized messages
  • 2 functions
    • Checking current API status
    • Requesting specific data endpoint

Connecting

controlSocket = new RequestSocket();            
controlSocket.Connect("tcp://localhost:38219"); // use ip for remote connections

Checking API status

C# code sample

/// <summary>
/// Sends control request to see what APIs are available. 
/// May return null if control connection dies (automatic reconnect will follow). 
/// </summary>        
public APIStatus GetStatus()
{
    APIStatus status;

    if (controlSocket == null)
    {
        return null;
    }

    controlSocket.SendAsJson(
        new ControlRequestHeader(ControlRequestCode.RequestStatus));

    var success = controlSocket.TryReceiveJson(out status, 500);

    if (success)
    {
        return status;
    }

    // Reconnect if something goes wrong
    controlSocket.Close();
    Connect();

    return null;
}

Raw packet exchange

Raw exchange looks like this:

First, you send a JSON serialized REQ with a code: 2 (RequestStatus).

(See request codes here).

REQ packet

{
    "ProtocolVersion":1,
    "Code":2 // RequestStatus
}                

Server will send you back a reply packet with a list of endpoints and their statuses. See response codes here.

REP packet

{
  "Endpoints": [
    {
      "Name": "HeadTracking",
      "Code": 0
    },
    {
      "Name": "Controller",
      "Code": 0
    },
    {
      "Name": "Broadcast",
      "Code": 0
    }
  ],
  "ProtocolVersion": 3,
  "Code": 0
}

Each packet always contains protocol version field. Current protocol version is 3.

Connecting to service endpoint

Non-control data services include head tracking, controller and broadcast listener APIs. You can use control channel to request a specific service by its name and version. It allows preserving backwards compatibility in case of breaking changes (if you request an older version, we will instantiate an older version on the server side).

General connection flow goes as described below:

  1. API user sends endpoint name, app name and its supported version number.
  2. VRidge API server instantiates API service on its side and marks the service as "in-use" while blocking other apps from connecting. (API Status queries will return InUse for given endpoint.
  3. VRidge API server replies with port number.
  4. You connect to the given ip:port through another REQ socket.
  5. You should disconnect from control channel at this point and use new REQ socket for specific service.

C# Code sample

// Request headtracking endpoint address
var response = controlSocket.SendAsJson(
	new RequestEndpoint("HeadTracking", "My app"));
EndpointCreated response = controlSocket.ReceiveJson();

if(response.Code != (int) ControlResponseCode.OK)
{    
    HandleErrorCode(response.Code); // Refer to status codes
}

headtrackingSocket = new RequestSocket();         
headtrackingSocket.Connect("tcp://localhost:" + response.Port);

controlSocket.Close();

// Keep using headtrackingSocket for your head tracking data stream

Raw packet exchange

REQ packet

{
    "RequestingAppName": "Your app name as a string",
    "RequestedEndpointName":"HeadTracking",
    "ProtocolVersion": 3,
    "Code":1
}

RequestedEndpointName should be a string matching one of two currently available services:

  • "HeadTracking"
  • "Controller"
  • "Broadcast"

REP packet

{
    "ProtocolVersion":3,
    "Code":0,
    "Port": 38320,
    "TimeoutSec":15
}

TimeoutSec defines an interval after which you will be disconnected from the API (socket closes and the API is freed to be used for other clients).

This timer is refreshed every time you send any packet to the endpoint. You can send a single zero byte (byte[]{0}) to service endpoint as a keep-alive ping if you don't have any data to send but you want to stay connected. Server will reply with a zero byte as well and refresh your timeout timer.

Control codes

Request codes

public enum ControlRequestCode
{
    RequestEndpoint = 1,
    RequestStatus = 2,        
}

Response codes

public enum ControlResponseCode
{        
    /// <summary>
    /// API awaits connection at given endpoint.
    /// </summary>
    OK = 0,

    /// <summary>
    /// API is not available because of undefined reason.
    /// </summary>
    NotAvailable = 1,

    /// <summary>
    /// API is in use by another client
    /// </summary>
    InUse = 2,

    /// <summary>
    /// Client is trying to use something that requires API client to be updated to more recent version
    /// </summary>
    ClientOutdated = 3,

    /// <summary>
    /// VRidge needs to be updated or client is not following protocol
    /// </summary>
    ServerOutdated = 4,
}
⚠️ **GitHub.com Fallback** ⚠️