Skip to content

Signaling & Opcodes Documentation

Mike J. Renaker / "MikeDEV edited this page Dec 14, 2024 · 1 revision

Signaling & Opcodes Documentation

All signaling messages are JSON-encoded text frames.

{
	opcode: string, // See opcodes
	payload: any, // By default, this will be nested JSON. Otherwise, this will be SDP offers/answers or ICE candidates.
	origin: {
		id: string, // Username
		user: string, // ULID
	}, 
	recipient: string, // ULID, defined client-side to specify which peer to relay to
	listener: string, // Optional, use to keep track of the server's responses to commands
}

All Opcodes

Opcode - The opcode itself.

Type - Either a Command (client->server), Response or Event (server->client).

Description - What does the opcode do?

Opcode Type Description
INIT Command Authenticates the connection given a valid login token.
INIT_OK Response Returns game info and username data upon successful login.
VIOLATION Response Protocol exception.
ANTICIPATE Event Notifying existing peers that a new peer will begin connecting.
DISCOVER Event Used to notify a new peer of existing peers for connecting.
WARNING Response Generic warning message.
CONFIG_REQUIRED Response Warning message when you haven't sent the INIT command.
KEEPALIVE Command / Response Ping/pong.
RELAY_OK Response Generic success code for MAKE_OFFER, MAKE_ANSWER, and ICE.
SESSION_EXISTS Response Warning message when trying to login to the same account on more than one device or attempting to reuse the INIT command.
TOKEN_INVALID Response Warning message when the provided token in INIT is invalid.
SESSION_EXPIRED Event Warning message when the session has expired.
PEER_INVALID Response Peer not found.
CONFIG_HOST Command Tells the server to make the client a game host, and create a lobby.
CONFIG_PEER Command Tells the server to make the client a game peer, and join a lobby.
TRANSITION Event Tells the peer to gracefully close all connections and change into host/peer mode.
TRANSITION_ACK Command Tells the server the client has gracefully closed all connections and is ready to change into host/peer mode.
NEW_HOST Event Server notifies a peer that a new lobby was created.
NEW_PEER Event Server notifies a host that a peer wants to join the lobby.
MAKE_OFFER Command / Response / Event Relay an SDP offer from host to peer.
MAKE_ANSWER Command / Response / Event Relay an SDP answer from peer to host.
ICE Command / Response / Event Relay ICE candidates to/from peer/host.
LOBBY_LIST Command / Response Request a copy of / response containing a list of all public lobbies.
LOBBY_RECLAIM Event This is a status message that indicates the lobby is currently being reclaimed, and is temporarily unavailable.
LOBBY_INFO Command / Response Retrieve / response info about a public lobby.
LOBBY_EXISTS Response Cannot create lobby because it already exists.
LOBBY_NOTFOUND Response Cannot join lobby because it does not exist.
LOBBY_FULL Response Cannot join lobby because it is currently full.
LOBBY_LOCKED Response Cannot join lobby because it is currently locked.
LOBBY_CLOSE Event The host / server has decided to shutdown the lobby.
HOST_GONE Event Server event that notifies peers that the host has disconnected.
PEER_GONE Event Server event that notifies a host that a peer has disconnected.
RECLAIM_HOST Event The lobby has no host and peers need to decide who becomes the new host.
HOST_RECLAIM Event Server has made a different peer the lobby host.
CLAIM_HOST Command Ask the server to become the new lobby host.
TRANSFER_HOST Command Ask the server to transfer ownership of the lobby to a peer.
LOCK Command Ask the server to prevent access to the lobby.
UNLOCK Command Ask the server to allow access to the lobby.
SIZE Command Ask the server to change the maximum peers value for a lobby.
KICK Command Ask the server to remove a peer from a lobby.
PASSWORD_REQUIRED Response Cannot join lobby because it requires a password.
PASSWORD_ACK Response Joining lobby: password accepted.
PASSWORD_FAIL Response Not joining lobby: password rejected.
DIAL Command / Event Request a voice call connection / An incoming voice call request.
RINGING Response Anti-race condition response. Can't request a voice call because a voice call request is currently in progress.
ACCEPT Command / Event Accept a voice call connection / Voice call request accepted.
DECLINE Command / Event Decline a voice call connection / Voice call request declined.
ACK_[...] Response All commands have some form of response. This generic ACK_[opcode] notifies the client that the command has been acknowledged.

Encryption support

CL5 utilizes ECDH-P256-AES-GCM cryptography. Public keys are based on SPKI-BASE64. If a command specifies pubkey in its payload, this will be your SPKI-BASE64 public key. When peers connect, they can share their public keys and negotiate encrypted secure messages.

Opcode-specific syntax

INIT

All clients are required to send this message to the server when connecting.

This authorizes your session with the server and permits connecting to a game.

This requires a valid account on the server, and a valid session token provided by the API.

For clients that implement the new accounts backend, a session will be derived from browser cookies. Sending this message is still mandatory, but doesn't require a payload to be provided.

{
	opcode: "INIT",
	payload: string, // See API docs for getting a session token
}

INIT_OK

This response code is returned by the server upon successful authentication.

The payload contains information about your current username (user) and player ID (id), as well as metadata about the connected game.

Use the id parameter value to identify sessions and to negotiate WebRTC connections using the signaling server.

{
	opcode: "INIT_OK",
	payload: {
		user: string, // Provided for human-friendly identification
		id: string, // Required to identify/relay requests to other peers on the signaling server
		game: string, // Game name
		developer: string, // Developer of game
	},
}

CONFIG_HOST

Send this message to the server to create a game host.

{
	opcode: "CONFIG_HOST",
	payload: {
		lobby_id: string, // Name of the lobby you want to create.
		allow_host_reclaim: bool, // False - This lobby is destroyed as soon as you leave. True - The server or peers will decide who becomes the host. Applies to argument allow_peers_to_claim_host.
		allow_peers_to_claim_host: bool, // False - The server will decide the new host. True - Peers will decide who becomes the host.
		max_peers: int, // set to 0 for unlimited peers
		password: string, // Prevent access to your room with a password. Set to an empty string to allow any peer to join.
		use_server_relay: string, // Enables/disable server-side WebRTC message relay. Useful for large MMOs or en-masse data synchronization.
		pubkey: string, // Optional, Used for message encryption. 
	},
}

CONFIG_PEER format

Send this message to the server to join a game host.

{
	opcode: "CONFIG_PEER",
	payload: {
		lobby_id: string, // Name of your lobby you want to join
		password: string, // Optional. Server will respond with PASSWORD_REQUIRED if blank and the room is configured for a password.
 		pubkey: string, // Optional, Used for message encryption. 
	},
}

NEW_HOST format

When a public lobby is created, this message is broadcasted to all peers. Functionally similar to ANTICIPATE.

{
	opcode: "NEW_HOST",
	payload: {
		id: string, // ULID of the host
		user: string, // gamertag of the host
		lobby_id: string, // lobby ID the host has created
		pubkey: string, // Shared PKEY value (if provided in CONFIG_HOST)
	},
}

NEW_PEER format

This message is sent to a host when a client wishes to connect to your lobby.

{
	opcode: "NEW_PEER",
	payload: {
		id: string, // ULID of the peer
		user: string, // gamertag of the peer
		pubkey: string, // Shared PKEY value (if provided in CONFIG_PEER)
	},
}

HOST_RECLAIM format

This message is sent when the server has made a peer the new host of a lobby.

{
	opcode: "HOST_RECLAIM",
	payload: {
		id: string, // ULID of the peer turned into host
		user: string, // Username of the peer turned into host
		lobby_id: string, // The lobby ID the peer has been made the host on
		pubkey: string, // Shared PKEY value (if provided in CONFIG_PEER)
	},
}

MAKE_OFFER, MAKE_ANSWER, ICE format

These commands will share a similar format. When sending a message, you must specify recipient. The server will relay the request with origin.

{
	opcode: "MAKE_OFFER", // or MAKE_ANSWER or ICE
	payload: {
		type: int, // 0 - data, 1 - voice
                contents: string, // SDP offer/answer or ICE candidate
        },
	recipient: string, // Must be a valid ULID
	origin: {
		id: string, // Username
		user: string, // ULID
	}, // Set by the server, do not manually specify.
}

DIAL, ACCEPT, DECLINE

These opcodes are used to negotiate a voice call request. When using the native MAKE_OFFER, MAKE_ANSWER, and ICE opcodes without predetermining who will be starting the call, it can lead to race conditions. These commands are designed to combat this.

{
	opcode: "DIAL", // or ACCEPT or DECLINE
	recipient: string, // Must be a valid ULID
	origin: {
		id: string, // Username
		user: string, // ULID
	}, // Set by the server, do not manually specify.
}

ANTICIPATE

ANTICIPATE is sent from the server to existing peers if a lobby will receive a new peer, or when connecting to a lobby host. After ANTICIPATE is sent, the existing peers must prepare to accept an incoming connection.

{
	opcode: "ANTICIPATE",
	payload: {
		user: string, // Peer username
		id: string, // Peer ID
		pubkey: string, // Peer public key (if configured)
	},
}

DISCOVER

DISCOVER is sent from the server to new peers in the event that a lobby has multiple existing peers. After DISCOVER is sent, the new peer will use the signaling backend to relay offers, answers, and ICE to all existing peers.

{
	opcode: "DISCOVER",
	payload: {
		user: string, // Peer username
		id: string, // Peer ID
		pubkey: string, // Peer public key (if configured)
	},
}

LOBBY_CLOSE

This message is sent to all clients, regardless of being part of the lobby or not. This lets peers know that the lobby has been shut down, and are expected to disconnect from the server and eachother.

{
	opcode: "LOBBY_CLOSE",
	payload: string, // Lobby ID
}

LOBBY_LIST

This command will generate a list of all open public lobbies for joining. The payload contents will be an array of strings.

Request

{
	opcode: "LOBBY_LIST"
}

Response

{
	opcode: "LOBBY_LIST",
	payload: [...string]
}

LOBBY_INFO

This command will get info about a public lobby before joining.

Request

{
	opcode: "LOBBY_INFO",
	payload: string, // Public lobby ID
}

Response

{
	opcode: "LOBBY_INFO",
	payload: {
		lobby_host_id: string,
		lobby_host_username: string,
		max_peers: int,
		current_peers: int,
	}
}

TRANSITION

If the client wants to change modes (i.e. a host wants to turn into a peer, or vice-versa), this event will be sent to the client. The client is expected to gracefully close all connections to other peers and prepare to begin operating in a different mode.

{
	opcode: "TRANSITION",
	payload: string, // "host" or "peer"
}

To tell the server that the client is ready to transition, send TRANSITION_ACK with no payload.

{
	opcode: "TRANSITION_ACK"
}

Revisions

v1.0 - Initial release.

v1.1 - Minor adjustments.

Adds DIAL, RINGING, ACCEPT, DECLINE, ACK_LOCK, ACK_UNLOCK and LOBBY_RECLAIM. Added the use_server_relay argument to CONFIG_HOST.

v1.2 - Add TRANSITION event and TRANSITION_ACK command.

Clients can now change modes without disconnecting from the game using the TRANSITION event and TRANSITION_ACK command.