Skip to content
This repository has been archived by the owner on Nov 7, 2024. It is now read-only.

The CloudLink Protocol

Mike J. Renaker / "MikeDEV edited this page Sep 29, 2023 · 4 revisions

Work in progress!

The CloudLink Protocol

This page outlines CLPv4.1. Packets within CLPv4.1 are compliant with UPLv2.2.

Uniform Packet Layout 2.2

UPLv2.2 is a formatting scheme that simplifies the protocol, and has existed since CLPv3.

In short, each packet that is UPL compliant is a JSON encoded text frame.

Each JSON message will have no more than these root keys:

{
    "cmd": String,             // Required for all commands, The CL Protocol command to execute.
    "val": [                   // Command-specific. Not required for some commands.
        String,
        Integer,
        Boolean,
        List,
        Object,                // Dictionary in Python terms
        Float
    ],
    "mode": String,            // Only used for server to client ulist command
    "name": String,            // Required for variable-related commands.
    "id": String,              // Required for direct or private message commands.
    "relay": String,           // Optional, same as id, but will relay the entire packet instead. Will only work on servers 0.2.0 or newer.
    "listener": String         // Optional, attach to message to get a response.
    "rooms": [                 // Optional for client to server messages, required for server to client messages if a client is linked to rooms
        String,
        List                   // List of strings
    ],
    "origin": Object,          // User object of originating client, only used with private messages or the direct command.
    "details": String          // For error messages only. It's value is a description of what went wrong and how to fix the error.
}

handshake: Starting up connections

When a client connects to a CloudLink server, it is recommended that the first message to be sent client to server is the handshake command. For future use, it is recommended to include metadata regarding your client's version info.

Request

{
    "cmd": "handshake",
    "val": {
        "language": String,    // Python, JavaScript, Golang, etc.
        "version": String,     // Example: 0.2.0
    },
    "listener": String         // Optional
}

Responses

  1. The server will return the detected IP address of the client.
{
    "cmd": "client_ip",
    "val": String
}
  1. The server will report what version it's running.
{
    "cmd": "server_version",
    "val": String
}
  1. If enabled, the server will provide its "Message of the Day".
{
    "cmd": "motd",
    "val": String
}
  1. The server will provide the client it's user object info.
{
    "cmd": "client_obj",
    "val": {
        "id": String,          // Snowflake ID
        "uuid": String         // UUID
    }
}
  1. The server will report the current userlist of the default room.
{
    "cmd": "ulist",
    "mode": "set",
    "val": [],                 // List of user objects, following the same format as client_obj
    "rooms": "default"
}
  1. The server will return a status code (and a listener, if specified).
{
    "cmd": "statuscode",
    "code": "I:100 | OK",
    "code_id": 100,
    "listener": String
}

Afterwards, the client does not need to send the handshake command during the remainder of the websocket connection.

gmsg: Global messages

This command broadcasts a message to everyone in your currently linked rooms (defaults to a single room: "default").

Request

{
    "cmd": "gmsg",
    "val": [                   // Whatever you would like to broadcast
        String,
        Integer,
        Boolean,
        List,
        Object,                // Dictionary in Python terms
        Float
    ]
    "listener": String         // Optional
}

Responses

If you specified a listener in your message, the server will broadcast this message to all clients (excluding yours):

{
    "cmd": "gmsg",
    "val": [                   // Whatever you broadcasted
        String,
        Integer,
        Boolean,
        List,
        Object,                // Dictionary in Python terms
        Float
    ]
}

Afterwards, it will return with the same message with your listener.

{
    "cmd": "gmsg",
    "val": [                   // Whatever you broadcasted
        String,
        Integer,
        Boolean,
        Object,                // Dictionary in Python terms
        Float
    ]
    "listener": String
}

If you didn't specify a listener in your message, you will receive the exact same message as every other client.

gvar: Global variables

This command broadcasts a variable to everyone in your currently linked rooms (defaults to a single room: "default").

Request

{
    "cmd": "gvar",
    "name": String             // Variable name
    "val": [                   // Whatever you would like to broadcast
        String,
        Integer,
        Boolean,
        List,
        Object,                // Dictionary in Python terms
        Float
    ]
    "listener": String         // Optional
}

Responses

If you specified a listener in your message, the server will broadcast this message to all clients (excluding yours):

{
    "cmd": "gvar",
    "name": String             // Variable name
    "val": [                   // Whatever you broadcasted
        String,
        Integer,
        Boolean,
        List,
        Object,                // Dictionary in Python terms
        Float
    ]
}

Afterwards, it will return with the same message with your listener.

{
    "cmd": "gvar",
    "name": String             // Variable name
    "val": [                   // Whatever you broadcasted
        String,
        Integer,
        Boolean,
        List,
        Object,                // Dictionary in Python terms
        Float
    ]
    "listener": String         // Optional
}

If you didn't specify a listener in your message, you will receive the exact same message as every other client.

setid: Setting username

Before you can utilize link, unlink, pmsg, pvar, direct, or relay commands, you will need to set a username for your client.

Request

{
    "cmd": "setid",
    "val": String             // Username,
    "listener": String        // Optional
}

Response

  1. The server will broadcast a ulist add command to other clients. This message does not get sent to your client.
{
    "cmd": "ulist",
    "mode": "add",
    "val": {
        "id": String,         // Your Snowflake ID
        "username": String,   // Your Username
        "uuid": String        // Your UUID
    },
    "rooms": "default"
}
  1. The server will return to you with a ulist set command.
{
    "cmd": "ulist",
    "mode": "set",
    "val": []                 // List of user objects, which will include your updated user object
    "rooms": "default"
}
  1. The server will return a status code (and a listener, if specified).
{
    "cmd": "statuscode",
    "code": "I:100 | OK",
    "code_id": 100,
    "listener": String
}

pmsg: Private messages

pmsg is similar to gmsg, but it allows you to send a message to a specific client, or a series of clients. This comes with security and speed benefits. Unlike direct, this message respects rooms, and requires your recipient(s) to be in the same room(s) as your client.

For any private command, you can specify a single string username/snowflake ID/UUID to select a client. You can also specify a list of string usernames/snowflake IDs/UUIDs. For compatibility between differing server languages, it is suggested to specify a user object instead.

Request

{
    "cmd": "pmsg",
    "id": [
        String,                // Username/Snowflake ID/UUID of the client to send to
        Object,                // Complete user object
        List                   // Collection of Strings or User Objects
    ],
    "val": [                   // Whatever you would like to broadcast
        String,
        Integer,
        Boolean,
        List,
        Object,                // Dictionary in Python terms
        Float
    ]
    "listener": String         // Optional
}

Response

  1. Each recipient will receive your message excluding a listener. It will include the origin key containing a copy of your client's user object.
{
    "cmd": "pmsg",
    "origin": Object,          // Your client object
    "val": [                   // Whatever you broadcasted
        String,
        Integer,
        Boolean,
        List,
        Object,                // Dictionary in Python terms
        Float
    ]
}
  1. Upon successful sending, the server will return to you with a statuscode.
{
    "cmd": "statuscode",
    "code": "I:100 | OK",
    "code_id": 100,
    "listener": String
}

pvar: Private variables

pvar is similar to gvar, but it allows you to send a variable to a specific client, or a series of clients. This comes with security and speed benefits. Unlike direct, this message respects rooms, and requires your recipient(s) to be in the same room(s) as your client.

For any private command, you can specify a single string username/snowflake ID/UUID to select a client. You can also specify a list of string usernames/snowflake IDs/UUIDs. For compatibility between differing server languages, it is suggested to specify a user object instead.

Request

{
    "cmd": "pvar",
    "name": String,            // Variable name
    "id": [
        String,                // Username/Snowflake ID/UUID of the client to send to
        Object,                // Complete user object
        List                   // Collection of Strings or User Objects
    ],
    "val": [                   // Whatever you would like to broadcast
        String,
        Integer,
        Boolean,
        List,
        Object,                // Dictionary in Python terms
        Float
    ]
    "listener": String         // Optional
}

Response

  1. Each recipient will receive your message excluding a listener. It will include the origin key containing a copy of your client's user object.
{
    "cmd": "pvar",
    "name": String,            // Variable name
    "origin": Object,          // Your client object
    "val": [                   // Whatever you broadcasted
        String,
        Integer,
        Boolean,
        List,
        Object,                // Dictionary in Python terms
        Float
    ]
}
  1. Upon successful sending, the server will return to you with a statuscode.
{
    "cmd": "statuscode",
    "code": "I:100 | OK",
    "code_id": 100,
    "listener": String
}

direct: Unconditional private messages

This command is identical to pmsg, however, it will send messages regardless of rooms. All that is required is that your message's recipient(s) must be connected during transit.

Request

{
    "cmd": "direct",
    "id": [
        String,                // Username/Snowflake ID/UUID of the client to send to
        Object,                // Complete user object
        List                   // Collection of Strings or User Objects
    ],
    "val": [                   // Whatever you would like to broadcast
        String,
        Integer,
        Boolean,
        List,
        Object,                // Dictionary in Python terms
        Float
    ]
    "listener": String         // Optional
}

Response

  1. Each recipient will receive your message excluding a listener. It will include the origin key containing a copy of your client's user object.
{
    "cmd": "direct",
    "origin": Object,          // Your client object
    "val": [                   // Whatever you broadcasted
        String,
        Integer,
        Boolean,
        List,
        Object,                // Dictionary in Python terms
        Float
    ]
}
  1. Upon successful sending, the server will return to you with a statuscode.
{
    "cmd": "statuscode",
    "code": "I:100 | OK",
    "code_id": 100,
    "listener": String
}

Statuscodes / Errors

{
    "cmd": "statuscode",
    "code": String,            // Human readable error code (Also for compatibility with older CL projects)
    "code_id": Integer,        // Code #
    "details": String          // If the command specifies this key, this will provide a description of what went wrong, and how to fix your error.
}
Code # Description
0 Testing usage only.
1 Echo usage only.
100 The request has been processed successfully.
101 A syntax error has occurred.
102 A value in the request has an invalid/incompatible datatype.
103 The ID/IDs specified in the "id" key did not resolve any clients.
104 The ID/IDs specified in the "id" key found more than one result. Only occurs if the server is configured to warn about multiple matches.
105 Generic error message when the server encounters an internal error. See logs for details.
106 The server received an empty packet.
107 The client attempted to set it's username, but it's username was already set.
108 The server understood the request, but refused to process it.
109 The client sent an invalid command.
110 The client sent a command that was disabled.
111 The client attempted to use a command that requires setting a username.
112 A username conflict has occurred.
113 The client sent a request that was too large.
114 The client sent incorrectly formatted / corrupt JSON.
115 The client attempted to access a room that was not previously joined.