owned this note
owned this note
Published
Linked with GitHub

##### CL4 banner(s) made by [@zedthehedgehog](https://github.com/zedthehedgehog)
# UPDATE
There is a newer version of this documentation page: https://hackmd.io/@MikeDEV/HJiNYwOfo
# Welcome to the Cloudlink docs!
Cloudlink is a free and open-source, websocket-powered API optimized for Scratch 3.0. Cloudlink comes with several powerful utilities and features:
* Super-duper fast messages between clients and servers
* Say goodbye to race conditions - Unlike Scratch's cloud variables, CloudLink gurantees message reliability, and if your client can't keep up, queue it!
* Large data limits - Send up to 1,000 characters per message, an upgrade from Scratch's cloud variable limits!
* Proven reliability - Extensively tested and utilized in [The Meower Project](https://github.com/meower-media-co/)
* Custom links/rooms for high-speed multiplayer or intelligent live updates!
* The CloudLink Suite - enhances functionality of your Scratch projects by adding cross-project file storage (CloudDisk), universal in-game currency (CloudCoin), and smarter user identification (CloudAccount).
## For documenation editors
Please leave a comment stating any changes made.
## Need older documentation?
See https://hackmd.io/@MikeDEV/SywNTBqRD
## Stability levels
::::success
**Stable**
3 (Stable)
2.5 (Stable/Subject to Change)
2 (Subject to Change)
::::
::::warning
**Experimental**
1 (Experimental)
::::
::::info
**Draft/Not Usable**
0 (Draft)
::::
::::danger
**Deprecated**
-1 (Not Recommended)
-2 (Deprecated)
::::
# What's new in Cloudlink 4?
::::success
**Stable**
3 (Stable)
::::
CloudLink 4 brings new features, enhancements, and security fixes. Here's a brief overview of all new features:
* Multicasting - You can send packets to more than one client at a time.
* User ID System - Adds support for multiple identical usernames on a single server.
* Linking/Rooms - Allows clients to communicate without interfering with the parent Cloudlink server. This opens up the possibility of many mini-servers for projects like MMOs, Chats, and other high-speed networking projects.
* Packet Queue/Listeners - The Scratch extension now supports message queuing through listeners, a way to effortlessly manage packets in high-speed applications. This prevents the possibility of race conditions, a common issue with Scratch's cloud variables. If your code can't keep up with messages, the extension queues up messages automatically, and queued messages can be quickly referenced using Listener IDs.
* Custom command loader - Simply create a class storing your custom commands, and Cloudlink will take care of the rest.
* Command disabler - Disable certain Cloudlink commands for more security-focused applications.
* Improved IP management system - Cloudlink can identify clients more effectively by reading IP addresses directly from the system, or through HTTP headers (By default, configured for Cloudflare). If there's a bad client on a known malicious IP address, Cloudlink rejects all connections.
* Reject mode - If you need to put the server in a private mode, you can set Reject mode to deny any new clients from connecting.
* Sandboxed/Unsandboxed support - The Scratch extension supports being loaded in a sandboxed or unsandboxed environment.
# Quickstart
::::success
**Stable**
3 (Stable)
::::
You can try Cloudlink without needing to host your own server. There are several publically-hosted Cloudlink instances available, which can be found in [serverlist.json](https://github.com/MikeDev101/cloudlink/blob/master/serverlist.json) or through the Server List block.
Cloudlink was originally created for Scratch 3.0. You can view the latest version of Cloudlink in any of these Scratch editors:
- [TurboWarp](https://turbowarp.org/editor?extension=https://mikedev101.github.io/cloudlink/B3-0.js)
- [SheepTester's E 羊 icques](https://sheeptester.github.io/scratch-gui/?url=https://mikedev101.github.io/cloudlink/B3-0.js)
- [Ogadaki's Adacraft](https://adacraft.org/studio/)
- [Ogadaki's Adacraft (Beta)](https://beta.adacraft.org/studio/)
Cloudlink is also available as a Python module, which comes bundled with the Cloudlink Server.
There is even a browser friendly version of Cloudlink available as CLJS.
### [Discussion Forum (Archive)](https://scratch.mit.edu/discuss/topic/398473)
### [Cloudlink JS "CLJS"](https://github.com/wgyt/cljs)
### Found an issue?
Please report any bugs, glitches, and/or security vulnerabilities [here](https://github.com/MikeDev101/cloudlink/issues).
# Scratch Client
This would probably be useful if I were to publish the bloody thing
::::info
**Draft/Not Usable**
0 (Draft)
::::
Documenation is still a WIP, please see https://hackmd.io/@MikeDEV/SywNTBqRD as almost all of the CL3 docs apply.
# Python Client
::::info
**Draft/Not Usable**
0 (Draft)
::::
::: danger
# THE CL4 CLIENT HAS NOT BEEN COMPLETED YET!
The CloudLink 4 Python Client is currently in development, and while it IS available for use it is very unstable. **We do not recommend you use this consistently for now.** If you really need a python client for this, use the CloudLink 3 client with a CloudLink 3 server.
:::
### Install the CloudLink python module
If you haven't already, run these commands in a terminal with Python installed to install the CloudLink module.
* ```py -m pip install cloudlink websockets``` (on Windows)
* ```python3.9 -m pip install cloudlink websockets``` (on Linux/Unix)
### Running as Client
Like with CloudLink server, you can run the module as a client, which will emulate the likes of the Scratch extension. Add these lines of code to your python file:
```
from cloudlink import cloudlink
cl = cloudlink()
clc = cl.client()
clc.run()
```
By default, leaving this function with no extra parameters will connect to CloudLink on the Localhost on port 3000, or `ws://127.0.0.1:3000/`.
#### Connecting to an external server or custom IP and Port
You can specify the server IP and port to connect to by adding the “ip” parameter.
```
cl.client().run("ws://12.34.56.78:69420/")
```
This will connect tot he ip 12.34.56.78 with port 69420. You can also enter a Repl server link.
```
cl.client().run("ws://yourservername.yourname.repl.co")
```
If you don't have your own server, you can test the client out by using a server from [serverlist.json](https://github.com/MikeDev101/cloudlink/blob/master/serverlist.json).
#### URL formatting
The server IP must be formatted using the following:
`(ws or wss)://(subdomain).(hostname).(top level domain):(port number (if needed))/`
::: warning
It is **not recommended** to connect to an insecure websocket server (ws://). Ideally, you should connect to a secure websocket server (wss://). The only situation where it is okay to use an insecure websocket server would be when you're testing **locally**.
:::
# Server
::::warning
**Experimental**
1 (Experimental)
::::
Before you continue, make sure you have (preferably) the latest version of Python. If you can't use the latest version, i can't assure you that this will work.
## Installing the CloudLink python module
The CloudLink server is a python module. To install CloudLink and it's dependencies, install it through pypi.
* ```py -m pip install cloudlink websockets``` (on Windows)
* ```python3.9 -m pip install cloudlink websockets``` (on Linux/Unix)
## Instanciating CloudLink
To instanciate CloudLink, add the following lines of code to your python file:
```
from cloudlink import cloudlink
cl = cloudlink()
cls = cl.server()
```
## Basic Usage
::::danger
# **Protect yourself!**
If you are exposing CloudLink to the internet, a good suggestion is to use a reputable **tunneling or reverse proxy service**. Also be sure to install CloudLink into a virtual environment or on a up-to-date machine!
For details on supported services, please see this [GitHub Issue](https://github.com/MikeDev101/cloudlink/issues/9).
::::
### Starting a Server
To start the server, add the following lines of code to **the end** of your Python script:
```
cls.run()
```
::::warning
**ANY CODE ADDED *AFTER* THIS LINE WILL *NOT* RUN. THE CLOUDLINK SERVER WILL BLOCK ANYTHING OTHER CODE FROM RUNNING ONCE IT IS CALLED.**
*…or, you can just run CloudLink in another thread. But that’s some otherworldly stuff there.*
::::
### Custom IPs and Ports
You can specify a custom IP or port for CloudLink to use instead of the default (127.0.0.1:3000). This is possible by specifying the ip and port parameter.
`cls.run(ip = "12.34.56.78", port = 42069)`
* Here, we are specifying CloudLink to run the server at ip 12.34.56.78 with port 42069.
* Instead of running on ip:port 127.0.0.1:3000 (which is the default), the server would theoretically be accessible through 12.34.56.78:42069.
* Changing the "ip" parameter is required if you're running CloudLink on Repl.
# Relay Mode
(Section placeholder - I haven't finished the CL4 default client)
::::info
**Draft/Not Usable**
0 (Draft)
::::
# Cloudlink Spec
::::success
**Stable**
2.5 (Stable/Subject to Change)
::::
This section outlines information to Cloudlink's protocols, formatting, commands, status codes, and more.
## Removed/obsolete functionality in CL4
::::success
**Stable**
3 (Stable)
::::
### Removed
* Client-reported IP addresses - This functionality is known to be spoofed and has been removed in favor of system or HTTP-header provided IP addresses.
### Obsolete
* Callback system - This has been rendered obsolete in favor of the custom command loader. It remains implemented for backwards compatibility.
* UPLv1 (Uniform Packet Layout version 1) - Sending custom commands through the Direct command has been deprecated. Custom commands will now follow the same format as standard CLP (Cloudlink Protocol) commands.
* String-only usernames: This is reimplemented as as backwards compatibility feature. CloudLink 4 will now use JSON objects to reference clients. If there are more than one client(s) with the same username, CloudLink 4 will ask that your username selection to be more specific - Use a JSON object or a client ID instead!
## Uniform Packet Layout (UPL) 2.0
::::success
**Stable**
3 (Stable)
::::
UPL is a Cloudlink standard introduced in Cloudlink 3.0, which defined how Cloudlink packets should be formatted and handled in custom reimplemenations.
UPLv2 retains compatibility for UPLv1 in CloudLink 4 (>=0.1.8), however UPLv2 should not be used when using a server running CloudLink 3 (<0.1.7.x) or older, as it will only support UPLv1.
The UPL standard is extremely simple: All packets are JSON-based and have 2 required keys, and 4 other optional keys.
#### Basic, required format
```json
{
"cmd": "(Packet command)",
"val": (any: Packet Payload)
}
```
#### Sending packets to specific clients
```json
{
"cmd": "(Packet command)",
"val": (any: Packet Payload),
"id": (str, int, dict, or array: Recipient(s))
}
```
#### Sending packets to specific clients in rooms
```json
{
"cmd": "(Packet command)",
"val": (any: Packet Payload),
"id": (str, int, dict, or array: Recipient(s)),
"rooms": (str, or array: Room(s))
}
```
#### Sending packets to specific clients in rooms, with a listener ID assigned
```json
{
"cmd": "(Packet command)",
"val": (any: Packet Payload),
"id": (str, int, dict, or array: Recipient(s)),
"rooms": (str, or array: Room(s)),
"listener": (str: Packet's listener ID)
}
```
#### Sending packets to specific clients in rooms, with a listener ID assigned, and a response code from the server (Should only be added server-side!)
```json
{
"cmd": "(Packet command)",
"val": (any: Packet Payload),
"id": (str, int, dict, or array: Recipient(s)),
"rooms": (str, or array: Room(s)),
"listener": (str: Packet's listener ID),
"code": "(CLP Status code)"
}
```
## Cloudlink Protocol (CLP) 4.0
::::success
**Stable**
2.5 (Stable/Subject to Change)
::::
The Cloudlink Protocol (CLP) stems from the basic formatting rules outlined in UPL, and provides barebones functionality for Cloudlink itself. Cloudlink's most basic form is a set of commands and status codes.
### Commands
::::success
**Stable**
2.5 (Stable/Subject to Change)
::::
| Command (`cmd`) | Description | Takes (sending `val`) | Gives (receiving `val`) | Requires `id` parameter? (Yes -> Returns with `origin` parameter) | Sends from |
| - | - | - | - | - | - |
| `gmsg` | Global data stream | Dict/JSON, String, Float, Int. | Dict/JSON, String, Float, Int. | No | Client or Server |
| `pmsg` | Private data stream | Dict/JSON, String, Float, Int. | Dict/JSON, String, Float, Int. | Yes | Client or Server |
| `gvar` | Global data stream variable | Dict/JSON, String, Float, Int. | Dict/JSON, String, Float, Int. | No | Client or Server |
| `pvar` | Private data stream variable | Dict/JSON, String, Float, Int. | Dict/JSON, String, Float, Int. | Yes | Client or Server |
| `ulist` | Username list | Not applicable | JSON array, storing JSON objects | No | Server only |
| `direct` | Direct server-to-client and client-to-server communications, **Not recommended for use in new applications** | Dict/JSON, String, Float, Int. | Dict/JSON, String, Float, Int. | Yes | Client or Server |
| `setid` | Sets username for client and enables private/direct communications | String | Not Applicable | Not Applicable | Client only |
| `statuscode` | Returns server state info when any packet is handled (Kinda like [**HTTP status codes**](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)). **See Status Codes for more info.** | Not Applicable | String | Not Applicable | Server only |
| `server_version` | Returns server version string when a client connects to the server.| Not Applicable | String | Not Applicable | Server only |
| `client_ip` | Returns the server-reported client IP address when a client connects to the server. | Not Applicable | String | Not Applicable | Server only |
| `motd` | Returns the server-reported Message-Of-The-Day (MOTD). | Not Applicable | String | Not Applicable | Server only |
| `relay` | Relays a packet from one server to another. **Should only be used by Cloudlink Server or Cloudlink Relays.** | Dict/JSON, String, Float, Int. | Dict/JSON, String, Float, Int. | Yes | Server-to-server only |
## Status Codes
::::success
**Stable**
2.5 (Stable/Subject to Change)
::::
`(Type):(Code) | (Description)`
| Type | Code | Description |
| -------- | -------- | -------- |
| Letter (`E` for Error, `I` for Info)| 3-Digit Int. (ex. `123`), describes the info/error in machine-readable format| String, describes the info/error in a human-readable format |
| `Code` | `Type` | Description |
| -------- | -------- | -------- |
| `I:000` | `Test` | Generic status code for debugging. |
| `I:100` | `OK` | Generic response for successful requests. |
| `E:101` | `Syntax` | Returned when a JSON formatting error has occurred, or there are missing keys in the JSON body. |
| `E:102` | `DataType` | Returned when a parameter is using an invalid data type. |
| `E:103` | `IDNotFound` | Selection of usernames, Client IDs, or JSON Objects returned no results. Server couldn't send packet. |
| `E:104` | `IDNotSpecific` | Selection of a string-based username returned more than one result. Specify a Client ID or a JSON Object instead. |
| `E:105` | `InternalServerError` | The server suffered an internal error. |
| `E:106` | `EmptyPacket` | Zero bytes were received. |
| `E:107` | `IDSet` | Username was already set. |
| `E:108` | `Refused` | The server refused to handle the packet. |
| `E:109` | `Invalid` | Invalid command. |
| `E:110` | `Disabled` | Command was disabled. |