-
Notifications
You must be signed in to change notification settings - Fork 34
The CloudLink Protocol
Work in progress!
This page outlines CLPv4.1. Packets within CLPv4.1 are compliant with UPLv2.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.
}
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
- The server will return the detected IP address of the client.
{
"cmd": "client_ip",
"val": String
}
- The server will report what version it's running.
{
"cmd": "server_version",
"val": String
}
- If enabled, the server will provide its "Message of the Day".
{
"cmd": "motd",
"val": String
}
- The server will provide the client it's user object info.
{
"cmd": "client_obj",
"val": {
"id": String, // Snowflake ID
"uuid": String // UUID
}
}
- 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"
}
- 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.
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.
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.
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
- 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"
}
- 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"
}
- The server will return a status code (and a listener, if specified).
{
"cmd": "statuscode",
"code": "I:100 | OK",
"code_id": 100,
"listener": String
}
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
- 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
]
}
- Upon successful sending, the server will return to you with a statuscode.
{
"cmd": "statuscode",
"code": "I:100 | OK",
"code_id": 100,
"listener": String
}
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
- 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
]
}
- Upon successful sending, the server will return to you with a statuscode.
{
"cmd": "statuscode",
"code": "I:100 | OK",
"code_id": 100,
"listener": String
}
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
- 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
]
}
- Upon successful sending, the server will return to you with a statuscode.
{
"cmd": "statuscode",
"code": "I:100 | OK",
"code_id": 100,
"listener": String
}
{
"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. |