{"id":20426193,"url":"https://github.com/vldr/relay","last_synced_at":"2025-07-07T17:39:33.598Z","repository":{"id":170170581,"uuid":"640652298","full_name":"vldr/Relay","owner":"vldr","description":"A fast and simple WebSocket relay, built in Rust, that enables a peer-to-peer-like network communication.","archived":false,"fork":false,"pushed_at":"2024-08-10T02:38:04.000Z","size":100,"stargazers_count":10,"open_issues_count":0,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-08-10T03:33:35.695Z","etag":null,"topics":["proxy","relay","rust","websocket"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vldr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-05-14T19:37:09.000Z","updated_at":"2024-08-10T03:33:44.648Z","dependencies_parsed_at":"2024-08-10T03:33:33.987Z","dependency_job_id":null,"html_url":"https://github.com/vldr/Relay","commit_stats":null,"previous_names":["vldr/relay"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vldr%2FRelay","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vldr%2FRelay/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vldr%2FRelay/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vldr%2FRelay/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vldr","download_url":"https://codeload.github.com/vldr/Relay/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224742348,"owners_count":17362232,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["proxy","relay","rust","websocket"],"created_at":"2024-11-15T07:15:51.066Z","updated_at":"2024-11-15T07:15:51.939Z","avatar_url":"https://github.com/vldr.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003cimg src='logo.svg?raw=true'\u003e\n\u003c/p\u003e\n\n---\n\nA fast and simple WebSocket relay, built in Rust, that enables a peer-to-peer-like network communication.\n\n- [Getting Started](#getting-started)\n- [Protocol](#protocol)\n  - [Text Protocol](#text-protocol)\n    - [`create` packet](#create-packet)\n    - [`join` packet](#join-packet)\n    - [`leave` packet](#leave-packet)\n    - [`error` packet](#error-packet)\n  - [Binary Protocol](#binary-protocol)\n- [Examples](#examples)\n- [Building](#building)\n\n# Getting Started\n\n### Binaries\n\nTo get started, you can either [build](#building) or download the precompiled binaries for your platform:\n\n- [Windows](https://github.com/vldr/Relay/releases/download/master/relay-windows-amd64.exe)\n- [Linux](https://github.com/vldr/Relay/releases/download/master/relay-linux-amd64)\n- [MacOS](https://github.com/vldr/Relay/releases/download/master/relay-macos-amd64)\n\n### Running\n\nThe following are the command-line arguments for the application:\n\n`relay \u003cIP\u003e \u003cPORT\u003e \u003cHOST\u003e`\n\n- `\u003cIP\u003e` is the IP address that should be bound to, for example: `127.0.0.1`\n- `\u003cPORT\u003e` is the port that should be bound to, for example: `8080`\n- `\u003cHOST\u003e` is the domain suffix of the [origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin) request header.\n  - For example, using `example.com` will allow requests from `example.com`, `a.example.com`, and `a.b.example.com`, while requests that do not match this suffix will be rejected.\n  - If left blank, then the origin header is not checked, and requests from any origin are accepted.\n\n# Protocol\n\nRelay uses the concept of rooms, which represent a list of clients that wish to send data between each other. A client can create a room and have other clients join the room. Once inside a room, data can be relayed.\n\n- To create and join rooms, we use the _text protocol_.\n- To send data between clients, we use the _binary protocol_.\n\nThe **text protocol** uses JSON to communicate between the client and the relay server to create and join rooms.\n\nThe **binary protocol** uses a single byte at the start of your data to indicate the destination (when sending) and the source (when receiving).\n\n**Example:**\n\nTo use the text protocol in JavaScript, you would write:\n\n```javascript\nconst webSocket = new WebSocket(\"\u003cURL\u003e\");\nwebSocket.send(`{\"type\": \"create\"}`);\n```\n\nTo use the binary protocol in JavaScript, you would write:\n\n```javascript\nconst webSocket = new WebSocket(\"\u003cURL\u003e\");\nwebSocket.send(new Uint8Array(255, 1, 2, 3));\n```\n\n**Note:** Text can still be sent using the binary protocol, it would just need to be wrapped in a Uint8Array or be sent using the binary opcode (if using a WebSocket library).\n\n## Text Protocol\n\n### `create` packet\n\nCreates a new room.\n\n- When creating a room, if an error occurs, an [`error`](#error-packet) packet is sent as a response.\n\n- You cannot create a room while you are already inside another room.\n\n**Request:**\n\n| Field           | Type     | Description                                                                                                         |\n| --------------- | -------- | ------------------------------------------------------------------------------------------------------------------- |\n| type            | `string` | The value should be \"create\".                                                                                       |\n| size | `number \\| undefined` | Specifies the size of the room. \u003cbr\u003e\u003cbr\u003eThe minimum value is _1_, the maximum value is _254_, and the default value is _2_. |\n\n**Example:**\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003cth\u003eCreating a room of size 10\u003c/th\u003e\n\u003cth\u003eCreating a room of size 2 (default)\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\n\n```json\n{\n  \"type\": \"create\",\n  \"size\": 10\n}\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```json\n{\n  \"type\": \"create\"\n}\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n**Response:**\n\n| Field | Type     | Description                                                                                     |\n| ----- | -------- | ----------------------------------------------------------------------------------------------- |\n| type  | `string` | The value will be \"create\".                                                                     |\n| id    | `string` | The UUID identifier of the room, which is used to join the room. |\n\n**Example:**\n\n```json\n{\n  \"type\": \"create\",\n  \"id\": \"f4b087df-1e2c-4482-b434-d23b723cf6d\"\n}\n```\n\n---\n\n### `join` packet\n\nJoins a room. \n\n- When joining a room, if an error occurs, an [`error`](#error-packet) packet is sent as a response.\n\n- You cannot join a room while you are already inside another room.\n\n**Request:**\n\n| Field | Type     | Description                         |\n| ----- | -------- | ----------------------------------- |\n| type  | `string` | The value should be \"join\".         |\n| id    | `string` | The UUID identifier of the room to join. |\n\n**Example:**\n\n```json\n{\n  \"type\": \"join\",\n  \"id\": \"f4b087df-1e2c-4482-b434-d23b723cf6d\"\n}\n```\n\n**Response:**\n\n| Field              | Type             | Description                                                                                                                                                                                                        |\n| ------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| type               | `string`         | The value will be \"join\".                                                                                                                                                                                          |\n| size | `number \\| undefined` | The client that sent the \"join\" packet will receive the number of clients currently in the room (excluding themselves). \u003cbr\u003e\u003cbr\u003e All other clients in the room will receive the \"join\" packet without a size field. |\n\n**Example:**\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003cth\u003eSender\u003c/th\u003e\n\u003cth\u003eEveryone else\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\n\n```json\n{\n  \"type\": \"join\",\n  \"size\": 4\n}\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```json\n{\n  \"type\": \"join\"\n}\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n---\n\n### `leave` packet\n\nIndicates that a client has left a room.\n\n**Response:**\n\n| Field | Type     | Description                            |\n| ----- | -------- | -------------------------------------- |\n| type  | `string` | The value will be \"leave\".             |\n| index | `number` | The index of the client that has left. |\n\n**Example:**\n\n```json\n{\n  \"type\": \"leave\",\n  \"index\": 0\n}\n```\n\n---\n\n### `error` packet\n\nIndicates that an error occurred when either joining or creating a room.\n\n- You can assume that if you get this packet, then you're not in a room.\n\n**Response:**\n\n| Field   | Type     | Description                                |\n| ------- | -------- | ------------------------------------------ |\n| type    | `string` | The value will be \"error\".                 |\n| message | `\"InvalidSize\" \\| \"AlreadyExists\" \\| \"DoesNotExist\" \\| \"IsFull\"` | `\"InvalidSize\"` \u003cbr\u003eThe size parameter in the [`create`](#create-packet) packet is not valid. \u003cbr\u003e\u003cbr\u003e `\"AlreadyExists\"` \u003cbr\u003e The room already exists. \u003cbr\u003e\u003cbr\u003e `\"DoesNotExist\"` \u003cbr\u003e The room does not exist. \u003cbr\u003e\u003cbr\u003e `\"IsFull\"` \u003cbr\u003eThe room is full. |\n\n**Example:**\n\n```json\n{\n  \"type\": \"error\",\n  \"message\": \"DoesNotExist\"\n}\n```\n\n## Binary Protocol\n\n\u003ctable\u003e\n    \u003cthead\u003e\n        \u003ctr\u003e\n            \u003cth\u003e0\u003c/th\u003e\n            \u003cth\u003e1\u003c/th\u003e\n            \u003cth\u003e2\u003c/th\u003e\n            \u003cth\u003e3\u003c/th\u003e\n            \u003cth\u003e...\u003c/th\u003e\n            \u003cth\u003eN\u003c/th\u003e\n        \u003c/tr\u003e\n    \u003c/thead\u003e\n    \u003ctbody\u003e\n        \u003ctr\u003e\n            \u003ctd\u003eIndex\u003c/td\u003e\n            \u003ctd colspan=5\u003eData\u003c/td\u003e\n        \u003c/tr\u003e\n    \u003c/tbody\u003e\n\u003c/table\u003e\n\n**Index:**\n\nWhen _sending_, the index byte indicates which client the packet should be sent to.\n\n- A value of _255_ indicates a broadcast, which means the packet will be sent to everyone in the room (excluding the sender).\n- A value between _0_ and _254_ indicates the index of the client that the packet will be sent to (a client can send to itself).\n\nWhen _receiving_, the index byte will contain the index of the sender of the packet.\n\n- A value between _0_ and _254_ indicates the index of the client that sent the packet.\n\n**Data:**\n\nThe data region contains _N_ user-defined bytes, where _N_ ≥ 0.\n\n# Examples\n\n[Cubic](https://github.com/vldr/Cubic)  \nA multiplayer WebGL voxel sandbox game.\n\n[Share](https://github.com/vldr/Share)  \nA real-time, peer-to-peer file transfer platform.\n\n[Chat](examples/chat)  \nA simple chat application.\n\n# Building\n\n**Note:** The following instructions assume that you are in a terminal (bash, cmd, etc).\n\n1. Install [Rust](https://www.rust-lang.org/learn/get-started) and [Git](https://git-scm.com/).\n2. Run `git clone https://github.com/vldr/relay`\n3. Navigate to the cloned directory.\n4. Run `cargo build --release`\n\nAfter the build process finishes, the output executable will be located in the `target/release` folder.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvldr%2Frelay","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvldr%2Frelay","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvldr%2Frelay/lists"}