Init
This commit is contained in:
commit
45ee7f4091
20 changed files with 814 additions and 0 deletions
10
.editorconfig
Normal file
10
.editorconfig
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
# specifically for YAML
|
||||||
|
[{yml, yaml}]
|
||||||
|
indent_style = space
|
32
.gitignore
vendored
Normal file
32
.gitignore
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Ww][Ii][Nn]32/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
.vs/
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
## Temp for now so that the js package can be workspaced until we get it on npm or something
|
||||||
|
js/yarn.lock
|
||||||
|
js/node_modules/
|
||||||
|
js/src/gen/
|
||||||
|
js/dist/
|
||||||
|
js/package.tgz
|
||||||
|
js/.yarn/*
|
||||||
|
js/!.yarn/patches
|
||||||
|
js/!.yarn/plugins
|
||||||
|
js/!.yarn/releases
|
||||||
|
js/!.yarn/sdks
|
||||||
|
js/!.yarn/versions
|
||||||
|
js/.pnp.*
|
24
README.md
Normal file
24
README.md
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# CollabVM 3 Protocol
|
||||||
|
|
||||||
|
Current Version: v0.0
|
||||||
|
|
||||||
|
These files make up the Protocol Buffers-based messages that the CollabVM 3 server sends.
|
||||||
|
|
||||||
|
**NOTICE**: The protocol is currently not in a released state, so it can/will change. Do not rely on it being the same or compatible in this stage of development.
|
||||||
|
|
||||||
|
# Protocol Versions
|
||||||
|
|
||||||
|
We will release a major version bump *every time* we make a change (once we have released v1.0) to the protocol that will break older clients (by replacing/removing fields or other protobuf breaks). Non-breaking changes will be a minor version bump.
|
||||||
|
|
||||||
|
Despite the fact Protobuf has data format stability guarantees, we allow breaks on purpose, since if a hacky workaround has to be made, it's probably time for a version bump.
|
||||||
|
|
||||||
|
|
||||||
|
## Protocol Documentation
|
||||||
|
|
||||||
|
### Convention
|
||||||
|
|
||||||
|
All given pieces of the protocol are neatly organized into individual `collabvm.proto.[X]` packages.
|
||||||
|
|
||||||
|
This is to make it a lot less convoluted to work with.
|
||||||
|
|
||||||
|
This may make it a bit harder to build protobufs for but IMO it's better than not caring.
|
50
SPEC.md
Normal file
50
SPEC.md
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
# Flow/protocol spec (TEMP)
|
||||||
|
|
||||||
|
## Connected
|
||||||
|
|
||||||
|
Once connected to the VM WebSocket or WebTransport instance, the server will send the following messages wrapped as ServerMessage:
|
||||||
|
|
||||||
|
- Server hello, which contains the protocol version.
|
||||||
|
|
||||||
|
The client will, upon recieving the server hello send a hello message with its protocol version. If the protocol version is too low or incompatible with the server, the server will simply close the connection.
|
||||||
|
|
||||||
|
Otherwise the server will send initalization data:
|
||||||
|
|
||||||
|
- Chat history
|
||||||
|
- User list (including role colors)
|
||||||
|
- Your own user
|
||||||
|
- Vote states (if votes are currently active)
|
||||||
|
- Turn state (if applicable)
|
||||||
|
- a list of Remoting display formats that the VM can use
|
||||||
|
|
||||||
|
## Normal usage
|
||||||
|
|
||||||
|
The client is expected to send a SelectFormat message (wrapped in ClientMessage) with the format they want to use within 10 seconds.
|
||||||
|
|
||||||
|
Otherwise, the server disconnects with a Disconnect message and closes the WebSocket connection.
|
||||||
|
|
||||||
|
A client is free to select any format that the server itself has advertised to the client.
|
||||||
|
|
||||||
|
Once the client selects the format, the client will start getting Remoting display messages in the format they requested. Currently that is:
|
||||||
|
|
||||||
|
| format enum | description |
|
||||||
|
| --------------------------- | ----------------------------- |
|
||||||
|
| `LEGACY_UGLY_BAD_UGLY_JPEG` | Legacy JPEG bandwidth-waste. |
|
||||||
|
| `STREAM_H264` | An H.264 video stream. |
|
||||||
|
| `STREAM_H265` | An H.265 (HEVC) video stream. |
|
||||||
|
|
||||||
|
If the client selects a video stream format, then the server will not send display size messages.
|
||||||
|
|
||||||
|
This is because the intraframes that are sent by the server upon the screen being resized or a user joining will contain the required parameters to size the display.
|
||||||
|
|
||||||
|
## View mode
|
||||||
|
|
||||||
|
The client does not need to send a SelectFormat message; in fact it actually will be ignored if the client DOES send one, since it would defeat the purpose to handle it.
|
||||||
|
|
||||||
|
The client is required to send screenshot requests to look at the display, since Remoting messages are not sent.
|
||||||
|
|
||||||
|
This is useful for utility bots since they can simply hold a connection and then simply save the response; they do not need to implement JPEG decoding, H.264 decoding, or anything. They just save some data to disk or whatever. Easy!
|
||||||
|
|
||||||
|
## If the user is kicked (or banned)
|
||||||
|
|
||||||
|
The server will send a Disconnect message with an appropiate reason and then close the connection. Otherwise if the connection closes it is assumed the user can simply reconnect.
|
18
check
Normal file
18
check
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# check all //protocol protos generate properly
|
||||||
|
|
||||||
|
# protos to check
|
||||||
|
PROTOS=(
|
||||||
|
admin.proto
|
||||||
|
remoting.proto
|
||||||
|
vm.proto
|
||||||
|
user.proto
|
||||||
|
vote.proto
|
||||||
|
client.proto
|
||||||
|
server.proto
|
||||||
|
)
|
||||||
|
|
||||||
|
mkdir out
|
||||||
|
protoc --cpp_out=out ${PROTOS[@]} || echo "FAILS TO GENERATE! do not check in or I will beat your ass";
|
||||||
|
rm -rf out
|
28
csharp/CollabVM.Protocol.csproj
Normal file
28
csharp/CollabVM.Protocol.csproj
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<PackageId>CollabVM.Protocol</PackageId>
|
||||||
|
<Version>0.1.0</Version>
|
||||||
|
<Authors>Computernewb</Authors>
|
||||||
|
<Description>Protocol buffers for CollabVM 3.0</Description>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
<RepositoryUrl>https://git.computernewb.com/collabvm/collabvm3</RepositoryUrl>
|
||||||
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Google.Protobuf" Version="3.29.2" />
|
||||||
|
<PackageReference Include="Grpc.Tools" Version="2.68.1">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Protobuf Include="..\src\*.proto" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="README.md" Pack="true" PackagePath="\" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
3
csharp/README.md
Normal file
3
csharp/README.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# CollabVM.Protocol (C#)
|
||||||
|
|
||||||
|
C# binding package for the CollabVM3 protocol buffers. See the [CollabVM protocol documentation](../README.md) and the [protobuf documentation](https://protobuf.dev/getting-started/csharptutorial/) for more information.
|
1
js/.yarnrc.yml
Normal file
1
js/.yarnrc.yml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
nodeLinker: node-modules
|
3
js/README.md
Normal file
3
js/README.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# @collabvm3/protocol (JavaScript)
|
||||||
|
|
||||||
|
Provides TypeScript bindings for the CollabVM3 protocol buffers. See the [CollabVM protocol documentation](../README.md) and the [protobuf documentation](https://github.com/bufbuild/protobuf-es/blob/main/MANUAL.md) for more information.
|
8
js/buf.gen.yaml
Normal file
8
js/buf.gen.yaml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
version: v2
|
||||||
|
clean: true
|
||||||
|
inputs:
|
||||||
|
- directory: ../src
|
||||||
|
plugins:
|
||||||
|
- local: protoc-gen-es
|
||||||
|
out: src/gen
|
||||||
|
opt: target=ts
|
26
js/package.json
Normal file
26
js/package.json
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"name": "@collabvm3/protocol",
|
||||||
|
"packageManager": "yarn@4.4.1",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"author": {
|
||||||
|
"name": "Computernewb",
|
||||||
|
"url": "https://computernewb.com/"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"main": "./dist/index.js",
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"build-buf": "buf generate",
|
||||||
|
"build": "tsc",
|
||||||
|
"prepack": "yarn build-buf && yarn build"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@bufbuild/buf": "^1.49.0",
|
||||||
|
"@bufbuild/protoc-gen-es": "^2.2.3",
|
||||||
|
"typescript": "^5.7.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@bufbuild/protobuf": "^2.2.3"
|
||||||
|
}
|
||||||
|
}
|
7
js/src/index.ts
Normal file
7
js/src/index.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
export * from "./gen/admin_pb.js";
|
||||||
|
export * from "./gen/client_pb.js";
|
||||||
|
export * from "./gen/remoting_pb.js";
|
||||||
|
export * from "./gen/server_pb.js";
|
||||||
|
export * from "./gen/user_pb.js";
|
||||||
|
export * from "./gen/vm_pb.js";
|
||||||
|
export * from "./gen/vote_pb.js";
|
15
js/tsconfig.json
Normal file
15
js/tsconfig.json
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2022",
|
||||||
|
"module": "ES2022",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"lib": [
|
||||||
|
"ES2020",
|
||||||
|
"DOM"
|
||||||
|
],
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"rootDir": "./src",
|
||||||
|
"outDir": "./dist",
|
||||||
|
"declaration": true
|
||||||
|
},
|
||||||
|
}
|
132
src/admin.proto
Normal file
132
src/admin.proto
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
//! Moderation and administration definitions.
|
||||||
|
edition = "2023";
|
||||||
|
|
||||||
|
package collabvm.protocol.admin;
|
||||||
|
option csharp_namespace = "CollabVM.Protocol.Admin";
|
||||||
|
|
||||||
|
import "vote.proto";
|
||||||
|
|
||||||
|
enum ControlCommand {
|
||||||
|
/// Reboot the VM.
|
||||||
|
REBOOT_VM = 0;
|
||||||
|
|
||||||
|
RESET_VM = 1;
|
||||||
|
|
||||||
|
/// Pause turns.
|
||||||
|
PAUSE_TURNS = 2;
|
||||||
|
|
||||||
|
UNPAUSE_TURNS = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AdminServerMessage {
|
||||||
|
uint32 uid = 1;
|
||||||
|
|
||||||
|
message StatelessResponse {
|
||||||
|
bool success = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExecuteResponse {
|
||||||
|
string output = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UserInfoResponse {
|
||||||
|
string ip = 1;
|
||||||
|
string subject_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
oneof Resp {
|
||||||
|
/// Used when we do not need to convey state to the calling user.
|
||||||
|
StatelessResponse stateless_response = 2;
|
||||||
|
|
||||||
|
ExecuteResponse execute_response = 3;
|
||||||
|
|
||||||
|
UserInfoResponse user_info_response = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message AdminClientMessage {
|
||||||
|
/// The uID/serial of this message. This is returned to the user with an AdminResponse.
|
||||||
|
uint32 uid = 1;
|
||||||
|
|
||||||
|
/// Kick a user.
|
||||||
|
message Kick {
|
||||||
|
/// The user to kick or ban.
|
||||||
|
string user = 1;
|
||||||
|
/// The reason for the kick. Shown to the user.
|
||||||
|
string reason = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mute a user.
|
||||||
|
message Mute {
|
||||||
|
/// The user to mute.
|
||||||
|
string user = 1;
|
||||||
|
/// The duration of the mute in milliseconds.
|
||||||
|
uint32 mute_duration = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unmute a user.
|
||||||
|
message Unmute {
|
||||||
|
/// The user to unmute.
|
||||||
|
string user = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExecuteCommand {
|
||||||
|
string command = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EndTurn {}
|
||||||
|
|
||||||
|
message EndUserTurn {
|
||||||
|
string user = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BypassTurn {}
|
||||||
|
|
||||||
|
message InfiniteTurn {}
|
||||||
|
|
||||||
|
message ClearTurnQueue {}
|
||||||
|
|
||||||
|
message ForceEndVote {
|
||||||
|
vote.VoteKind vote_id = 1;
|
||||||
|
|
||||||
|
/// Choice of vote to force. Optional; a vote can be ended
|
||||||
|
/// without any choice simply by not sending this field.
|
||||||
|
bool choice = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Control {
|
||||||
|
/// The command to run. Later on more inputs probably
|
||||||
|
ControlCommand command = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Request information about a user. Currently, their IP address, and Subject ID if they are logged in.
|
||||||
|
message UserInfo {
|
||||||
|
string user = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
oneof Request {
|
||||||
|
// execute cmds
|
||||||
|
ExecuteCommand execute_command = 2;
|
||||||
|
|
||||||
|
Kick kick = 3;
|
||||||
|
Mute mute = 4;
|
||||||
|
|
||||||
|
// turn-jacking
|
||||||
|
EndTurn end_turn = 5;
|
||||||
|
EndUserTurn end_user_turn = 6;
|
||||||
|
BypassTurn bypass_turn = 7;
|
||||||
|
InfiniteTurn infinite_turn = 8;
|
||||||
|
|
||||||
|
// vote
|
||||||
|
ForceEndVote force_end_vote = 9;
|
||||||
|
|
||||||
|
Control control = 10;
|
||||||
|
|
||||||
|
UserInfo user_info = 11;
|
||||||
|
|
||||||
|
ClearTurnQueue clear_turn_queue = 12;
|
||||||
|
Unmute unmute = 13;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
67
src/client.proto
Normal file
67
src/client.proto
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
//! Declares "ClientMessage", the super-message the client sends to the server.
|
||||||
|
edition = "2023";
|
||||||
|
package collabvm.protocol;
|
||||||
|
option csharp_namespace = "CollabVM.Protocol";
|
||||||
|
|
||||||
|
import "admin.proto";
|
||||||
|
import "vote.proto";
|
||||||
|
import "remoting.proto";
|
||||||
|
|
||||||
|
message ClientMessage {
|
||||||
|
message ClientHello {
|
||||||
|
/// The protocol version of the client.
|
||||||
|
uint32 protocol_version_major = 1;
|
||||||
|
uint32 protocol_version_minor = 2;
|
||||||
|
// The username requested by the client. The server is not required to honor this request.
|
||||||
|
string username = 3;
|
||||||
|
// Desired display format
|
||||||
|
remoting.DisplayFormat display_format = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TurnRequest {
|
||||||
|
/// Set to true if the user wants to end their turn early,
|
||||||
|
/// or exit the turn queue.
|
||||||
|
bool forfeit_turn = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message StartVote {
|
||||||
|
vote.VoteKind vote_kind = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Vote {
|
||||||
|
/// The vote to vote for
|
||||||
|
vote.VoteKind vote_kind = 1;
|
||||||
|
|
||||||
|
/// The choice you are voting on. True for yes, false for no.
|
||||||
|
bool choice = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SendChat {
|
||||||
|
string message = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Requests a screenshot.
|
||||||
|
message RequestScreenshot {}
|
||||||
|
/// Keepalive message.
|
||||||
|
message Keepalive {}
|
||||||
|
|
||||||
|
oneof Union {
|
||||||
|
ClientHello hello = 1;
|
||||||
|
|
||||||
|
/// A remoting message.
|
||||||
|
remoting.RemotingClientMessage remoting_message = 2;
|
||||||
|
|
||||||
|
admin.AdminClientMessage admin_message = 3;
|
||||||
|
|
||||||
|
// general cvm stuff
|
||||||
|
TurnRequest turn = 4;
|
||||||
|
SendChat chat = 5;
|
||||||
|
|
||||||
|
// vote
|
||||||
|
StartVote start_vote = 6;
|
||||||
|
Vote vote = 7;
|
||||||
|
|
||||||
|
RequestScreenshot request_screenshot = 8;
|
||||||
|
Keepalive keepalive = 9;
|
||||||
|
}
|
||||||
|
}
|
145
src/remoting.proto
Normal file
145
src/remoting.proto
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
//! Remoting. Mostly from CrustTest, modified to be better.
|
||||||
|
|
||||||
|
edition = "2023";
|
||||||
|
package collabvm.protocol.remoting;
|
||||||
|
option csharp_namespace = "CollabVM.Protocol.Remoting";
|
||||||
|
|
||||||
|
enum DisplayFormat {
|
||||||
|
/// The server will not send any display updates.
|
||||||
|
NONE = 0;
|
||||||
|
/// Legacy JPEG rectangles. Slow, bad, and a total bandwidth waste.
|
||||||
|
/// Assumed to be the default for all clients.
|
||||||
|
LEGACY_UGLY_BAD_UGLY_JPEG = 1;
|
||||||
|
|
||||||
|
/// H.264 video stream.
|
||||||
|
STREAM_H264 = 2;
|
||||||
|
|
||||||
|
// STREAM_HEVC? Not implementing right now
|
||||||
|
// maybe once we have webtransport...
|
||||||
|
}
|
||||||
|
|
||||||
|
message KeyboardLEDState {
|
||||||
|
bool scroll_lock = 1;
|
||||||
|
bool num_lock = 2;
|
||||||
|
bool caps_lock = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// a remoting client message
|
||||||
|
message RemotingClientMessage {
|
||||||
|
message KeyMessage { // stable
|
||||||
|
sint32 keysym = 1;
|
||||||
|
bool pressed = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MouseMessage {
|
||||||
|
uint32 mouse_x = 1;
|
||||||
|
uint32 mouse_y = 2;
|
||||||
|
uint32 buttons = 3; // :(
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Used by the client to select a preferred format for the display.
|
||||||
|
/// Display updates are not sent until a format has been selected; however
|
||||||
|
/// selecting one is required within 10 seconds, outside of view mode.
|
||||||
|
message SelectFormat {
|
||||||
|
DisplayFormat selected_format = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
oneof OneOf {
|
||||||
|
KeyMessage key = 1;
|
||||||
|
MouseMessage mouse = 2;
|
||||||
|
|
||||||
|
SelectFormat display_select_format = 3;
|
||||||
|
bool enable_audio = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// A remoting server message
|
||||||
|
message RemotingServerMessage {
|
||||||
|
|
||||||
|
message DisplaySize {
|
||||||
|
uint32 width = 1;
|
||||||
|
uint32 height = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DisplaySupportedFormats {
|
||||||
|
/// Supported formats. The client is free to select a format from this list.
|
||||||
|
repeated DisplayFormat supported_formats = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cursor handling; Currently not used
|
||||||
|
message Cursor {
|
||||||
|
message Move {
|
||||||
|
uint32 cursorX = 1;
|
||||||
|
uint32 cursorY = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Update {
|
||||||
|
uint32 cursorW = 1;
|
||||||
|
uint32 cursorH = 2;
|
||||||
|
bytes cursorImage = 3; // RGBA8888 image of the cursor, possibly zlib packed
|
||||||
|
}
|
||||||
|
|
||||||
|
oneof Kind {
|
||||||
|
Move move = 1;
|
||||||
|
Update update = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
message Update_LegacyBadUglyRect {
|
||||||
|
message Rect {
|
||||||
|
uint32 x = 1;
|
||||||
|
uint32 y = 2;
|
||||||
|
bytes data = 3; // JPEG encoded rect data
|
||||||
|
}
|
||||||
|
|
||||||
|
repeated Rect rects = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Update_Stream {
|
||||||
|
enum FrameType {
|
||||||
|
/// A key frame.
|
||||||
|
KEY = 0;
|
||||||
|
|
||||||
|
/// A inter (P in h264) frame.
|
||||||
|
INTER = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FrameType type = 1;
|
||||||
|
bytes data = 2; // Loosely wrapped data stream; based on DisplayFormat selected by the client.
|
||||||
|
}
|
||||||
|
|
||||||
|
message Audio {
|
||||||
|
message Format {
|
||||||
|
uint32 sampleRate = 1;
|
||||||
|
uint32 nrChannels = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Data {
|
||||||
|
bytes data = 1; // Opus data stream
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oneof OneOf {
|
||||||
|
DisplaySize display_size = 1;
|
||||||
|
|
||||||
|
/// Legacy JPEG based rectangles. Slow and bad
|
||||||
|
Update_LegacyBadUglyRect update_legacy_jpeg = 2;
|
||||||
|
|
||||||
|
/// Stream-based update
|
||||||
|
Update_Stream update_stream = 3;
|
||||||
|
|
||||||
|
// 4..5 resvd. for Cursor
|
||||||
|
// Cursor.Move cursor_move = 4;
|
||||||
|
// Cursor.Update cursor_update = 5;
|
||||||
|
|
||||||
|
|
||||||
|
// 5..10 reserved for audio messages
|
||||||
|
//Audio.Format audioFormat = 5;
|
||||||
|
Audio.Data audioData = 6;
|
||||||
|
|
||||||
|
// 10 ... reserved for future expansion
|
||||||
|
KeyboardLEDState keyboard_led_state = 10;
|
||||||
|
}
|
||||||
|
}
|
96
src/server.proto
Normal file
96
src/server.proto
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
//! Declares "ServerMessage", the super-message the server sends to clients.
|
||||||
|
edition = "2023";
|
||||||
|
package collabvm.protocol;
|
||||||
|
option csharp_namespace = "CollabVM.Protocol";
|
||||||
|
|
||||||
|
import "user.proto";
|
||||||
|
import "admin.proto";
|
||||||
|
import "vm.proto";
|
||||||
|
import "vote.proto";
|
||||||
|
import "remoting.proto";
|
||||||
|
|
||||||
|
message ServerMessage {
|
||||||
|
message ServerHello {
|
||||||
|
/// The protocol version.
|
||||||
|
uint32 protocol_version_major = 1;
|
||||||
|
uint32 protocol_version_minor = 2;
|
||||||
|
|
||||||
|
// server version?
|
||||||
|
}
|
||||||
|
|
||||||
|
message ServerInit {
|
||||||
|
// The client's username
|
||||||
|
string username = 1;
|
||||||
|
user.UserList user_list = 2;
|
||||||
|
vm.ChatHistory chat_history = 3;
|
||||||
|
string motd = 4;
|
||||||
|
uint32 max_chat_length = 5;
|
||||||
|
uint32 rank = 6;
|
||||||
|
remoting.KeyboardLEDState keyboard_led_state = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Disconnect {
|
||||||
|
/// Optional reason.
|
||||||
|
string reason = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ScreenshotResponse {
|
||||||
|
/// Screenshot data as WebP. (This is the same format regardless of display format.)
|
||||||
|
bytes screenshot_data = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Keepalive message.
|
||||||
|
message Keepalive {}
|
||||||
|
|
||||||
|
/// Rate limited
|
||||||
|
message RateLimited {
|
||||||
|
/// The action that was rate limited.
|
||||||
|
string action = 1;
|
||||||
|
/// Milliseconds until the client may perform the action again.
|
||||||
|
uint32 limit_time = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Muted {
|
||||||
|
/// Duration of the mute in milliseconds.
|
||||||
|
uint32 duration = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Unmuted {}
|
||||||
|
|
||||||
|
oneof Union {
|
||||||
|
ServerHello hello = 1;
|
||||||
|
ServerInit init = 2;
|
||||||
|
|
||||||
|
remoting.RemotingServerMessage remoting_message = 3;
|
||||||
|
admin.AdminServerMessage admin_message = 4;
|
||||||
|
|
||||||
|
Disconnect disconnect = 5;
|
||||||
|
|
||||||
|
// user stuff
|
||||||
|
// user.UserList user_list = 6;
|
||||||
|
user.UserJoined add_user = 7;
|
||||||
|
user.UserLeft remove_user = 8;
|
||||||
|
|
||||||
|
// VM turn
|
||||||
|
vm.TurnQueue turn_queue = 10;
|
||||||
|
|
||||||
|
// VM chat
|
||||||
|
vm.ChatMessage chat_message = 11;
|
||||||
|
vm.ChatHistory chat_history = 12;
|
||||||
|
vm.SystemChatMessage system_chat_message = 13;
|
||||||
|
|
||||||
|
// vote messages
|
||||||
|
vote.VoteInformation vote_information = 14;
|
||||||
|
vote.VoteTally vote_tally = 15;
|
||||||
|
vote.VoteEnded vote_ended = 16;
|
||||||
|
vote.VoteStartFailure vote_start_failure = 17;
|
||||||
|
|
||||||
|
ScreenshotResponse screenshot_response = 18;
|
||||||
|
|
||||||
|
Keepalive keepalive = 19;
|
||||||
|
|
||||||
|
RateLimited rate_limited = 20;
|
||||||
|
Muted muted = 21;
|
||||||
|
Unmuted unmuted = 22;
|
||||||
|
}
|
||||||
|
}
|
29
src/user.proto
Normal file
29
src/user.proto
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
//! User protos.
|
||||||
|
edition = "2023";
|
||||||
|
package collabvm.protocol.user;
|
||||||
|
option csharp_namespace = "CollabVM.Protocol.User";
|
||||||
|
|
||||||
|
// Used anywhere we want to reference a user.
|
||||||
|
message UserReference {
|
||||||
|
// Currently used always.
|
||||||
|
string username = 1;
|
||||||
|
|
||||||
|
/// The user's rank
|
||||||
|
uint32 rank = 2;
|
||||||
|
|
||||||
|
/// The user's ISO 3166-1 country code.
|
||||||
|
string country = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The user list.
|
||||||
|
message UserList {
|
||||||
|
repeated UserReference users = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UserJoined {
|
||||||
|
UserReference user = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UserLeft {
|
||||||
|
string username = 1;
|
||||||
|
}
|
50
src/vm.proto
Normal file
50
src/vm.proto
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
//! VM-specific protocol stuff.
|
||||||
|
|
||||||
|
edition = "2023";
|
||||||
|
|
||||||
|
package collabvm.protocol.vm;
|
||||||
|
option csharp_namespace = "CollabVM.Protocol.VM";
|
||||||
|
|
||||||
|
/// A chat message.
|
||||||
|
message ChatMessage {
|
||||||
|
string username = 1;
|
||||||
|
string message_content = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A chat message from the server itself.
|
||||||
|
message SystemChatMessage {
|
||||||
|
string message_content = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ChatHistory {
|
||||||
|
repeated ChatMessage message_history = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TurnState {
|
||||||
|
/// The turn queue is active.
|
||||||
|
ACTIVE = 0;
|
||||||
|
|
||||||
|
/// The turn queue has been paused.
|
||||||
|
PAUSED = 1;
|
||||||
|
|
||||||
|
/// Paused because there is only one user in the queue.
|
||||||
|
/// If another user takes a turn, the queue will re-start
|
||||||
|
/// automatically and switch back to ACTIVE.
|
||||||
|
PAUSED_SOLE_USER = 2;
|
||||||
|
|
||||||
|
/// Paused because an admin is taking an indefinite turn.
|
||||||
|
PAUSED_ADMIN = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TurnQueue {
|
||||||
|
TurnState turn_state = 1;
|
||||||
|
|
||||||
|
/// The queue of users in the turn queue. Index 0 is the user who is currently taking their turn.
|
||||||
|
repeated string queue = 2;
|
||||||
|
|
||||||
|
/// Time in MS for when the next turn will be
|
||||||
|
uint32 next_turn_time_ms = 3;
|
||||||
|
|
||||||
|
/// Time in milliseconds for when your position
|
||||||
|
uint32 turn_queue_time_ms = 4;
|
||||||
|
}
|
70
src/vote.proto
Normal file
70
src/vote.proto
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
edition = "2023";
|
||||||
|
package collabvm.protocol.vote;
|
||||||
|
option csharp_namespace = "CollabVM.Protocol.Vote";
|
||||||
|
|
||||||
|
/// The kind of a vote.
|
||||||
|
enum VoteKind {
|
||||||
|
/// A vote to reset the VM.
|
||||||
|
VOTE_RESET = 0;
|
||||||
|
|
||||||
|
/// A user-defined (in plugins or such) vote.
|
||||||
|
/// This is reasonably far away from any internally defined votes
|
||||||
|
/// so that we don't accidentally run into it. Any value from 1000 onwards
|
||||||
|
/// is treated as a user-defined vote.
|
||||||
|
VOTE_USER_START = 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum VoteStartFailure {
|
||||||
|
/// An ongoing vote is in progress.
|
||||||
|
VOTE_IN_PROGRESS = 0;
|
||||||
|
|
||||||
|
/// You are muted, and thus cannot start a vote.
|
||||||
|
CURRENTLY_MUTED = 1;
|
||||||
|
|
||||||
|
/// A vote was held too recently.
|
||||||
|
VOTE_COOLDOWN = 2;
|
||||||
|
|
||||||
|
/// This VM does not support voting.
|
||||||
|
VM_VOTES_DISABLED = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Tally {
|
||||||
|
repeated string yesVotes = 1;
|
||||||
|
repeated string noVotes = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sent only once to all connected users on the start of a vote (and additionally new users) to indicate the possible choices for a ongoing vote.
|
||||||
|
/// Multiple votes are currently not allowed; but could be at some point.
|
||||||
|
message VoteInformation {
|
||||||
|
/// The kind of the vote.
|
||||||
|
VoteKind kind = 1;
|
||||||
|
|
||||||
|
/// The time until the vote ends.
|
||||||
|
uint32 time_left = 2;
|
||||||
|
|
||||||
|
/// The user who started the vote.
|
||||||
|
string started_by = 3;
|
||||||
|
|
||||||
|
/// Current tally for the vote.
|
||||||
|
Tally tally = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sent to update the current tally
|
||||||
|
message VoteTally {
|
||||||
|
/// The kind of the vote.
|
||||||
|
VoteKind kind = 1;
|
||||||
|
/// Current tally for the vote.
|
||||||
|
Tally tally = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sent to indicate a vote has ended
|
||||||
|
message VoteEnded {
|
||||||
|
/// The kind of the vote.
|
||||||
|
VoteKind kind = 1;
|
||||||
|
|
||||||
|
/// The choice which won. True for yes, false for no.
|
||||||
|
bool choice = 2;
|
||||||
|
|
||||||
|
/// Final tally
|
||||||
|
Tally tally = 3;
|
||||||
|
}
|
Loading…
Reference in a new issue