Skip to content

4Players/odin-gateway

Repository files navigation

ODIN Gateway

v0.18.0

This is a simple gateway server written in Deno. It regulates access by spreading ODIN clients over available ODIN servers based on current and future usage. It also performs basic checks on customer license conditions.

sequenceDiagram

participant Client
participant Gateway
participant Server

Server ->> Gateway: sfu.GridConfig RPC
activate Gateway
Gateway -->> Server: Receive recommended settings
deactivate Gateway

loop every n seconds
Server ->> Gateway: sfu.Report RPC
activate Gateway
Gateway -->> Server: Receive enqueued tasks
deactivate Gateway
end

autonumber 1

Client ->> Gateway: Connect RPC
activate Gateway
Gateway -->> Client: Receive signed room token 
deactivate Gateway
Client ->> Server: Join Room

Setup Development Environment

The following prerequisites are necessary to start development:

How to Start

# start a HTTP server on port 7000
deno task run

# start a HTTPS server on port 7000
deno task run --ssl

Note: If you don't want to install Deno on the target system, you can also compile the scripts into a self-containing executable. Click here for details.

Configuration

The gateway is configured using a TypeScript configuration file (config.ts). In addition, the following optional command-line arguments are available to enforce specific options:

Option Description
--host The IP address to listen on
--port The TCP port number to listen on
--ssl Enable HTTPS
--certificate The certificate file to use
--privatekey The private key file to use

Note: For local testing, using mkcert is recommended.

Importing Customer Keys

Instead of providing a static list of customer keys in the gateway configuration file, you can also write your own custom import function, which needs to return a Promise<Customer[]> value.

customerApi: {
  updateFunction: myFunction, // async function returning a list of customers
  updateInterval: 300,        // interval in seconds
},

This function can be used to either fetch your customer keys from a RESTful API or a reload file on disk. Here's an example:

async function myFunction(): Promise<Customer[]> {
  try {
    const response = await fetch("https://domain.tld/api/customer-keys");
    if (response.status !== 200) {
      throw "something went wrong";
    }
    return await response.json();
  } catch (_e) {
    // handle error
  }
  return [];
}

Public API

Authentication

Authentication for the public API is done using a Bearer token signed with an ODIN access key. When specified, the audience claim (aud) in the token must be set to gateway. The payload of a decoded JWT looks like this:

{
  "rid": "foo",
  "uid": "bar",
  "aud": "gateway",
  "sub": "connect",
  "exp": 1669852860,
  "nbf": 1669852800
}

For details on generating tokens, please refer to @4players/odin-tokens.

RPC Methods

To use any of the following methods, the JWT used to authorize must have its name listed in the subject claim (sub).

Connect

Authorizes ODIN clients to access the room specified in the Bearer token and responds with a new JWT signed with the gateway master key, which can be used to join a room on an attached ODIN server.

curl --request POST \
  --url http://localhost:7000/ \
  --header 'Authorization: Bearer ${JWT}' \
  --header 'Content-Type: application/json' \
  --data '{
    "jsonrpc": "2.0",
    "method": "Connect",
    "params": {},
    "id": 1
  }'

RoomClose

Closes the specified room (if available) and prevents it from being joined again until ban_time is expired.

curl --request POST \
  --url http://localhost:7000/ \
  --header 'Authorization: Bearer ${JWT}' \
  --header 'Content-Type: application/json' \
  --data '{
    "jsonrpc": "2.0",
    "method": "RoomClose",
    "params": {
      "room_id": "${ROOM_ID}",
      "ban_time": ${OPTIONAL_TIME_IN_SECONDS},
    },
    "id": 1
  }'

RoomUpdate

Updates the global user data of the specified room using the given user_data byte array.

curl --request POST \
  --url https://localhost:7000/ \
  --header 'Authorization: Bearer ${JWT}' \
  --header 'Content-Type: application/json' \
  --data '{
    "jsonrpc": "2.0",
    "method": "RoomUpdate",
    "params": {
      "room_id": "${ROOM_ID}",
      "user_data": ${ARRAY_OF_BYTES}
    },
    "id": 1
  }'

RoomBanClient

Kicks all clients matching the specified user_id from the specified room and prevents them from joining again until ban_time is expired.

curl --request POST \
  --url http://localhost:7000/ \
  --header 'Authorization: Bearer ${JWT}' \
  --header 'Content-Type: application/json' \
  --data '{
    "jsonrpc": "2.0",
    "method": "RoomBanClient",
    "params": {
      "room_id": "${ROOM_ID}",
      "user_id": "${PEER_USER_ID}",
      "ban_time": ${OPTIONAL_TIME_IN_SECONDS},
    },
    "id": 1
  }'

RoomSendMessage

Sends arbitrary data to all clients matching the specified user_id in the specified room.

curl --request POST \
  --url https://localhost:7000/ \
  --header 'Authorization: Bearer ${JWT}' \
  --header 'Content-Type: application/json' \
  --data '{
    "jsonrpc": "2.0",
    "method": "RoomSendMessage",
    "params": {
      "room_id": "${ROOM_ID}",
      "user_id": "${PEER_USER_ID}",
      "message": ${ARRAY_OF_BYTES}
    },
    "id": 1
  }'

About

Gateway to regulate access by spreading clients over available ODIN servers based on current and future usage

Topics

Resources

Stars

Watchers

Forks