Skip to content

Instantly share code, notes, and snippets.

@elementbound
Created June 1, 2025 10:51
Show Gist options
  • Save elementbound/917636a974160a7504d6b1232e654f72 to your computer and use it in GitHub Desktop.
Save elementbound/917636a974160a7504d6b1232e654f72 to your computer and use it in GitHub Desktop.
Trimsock specification

Trimsock

Trimsock is a stream-based communication protocol that:

  • is easy to implement
  • is human-readable
  • supports binary
  • can support most use cases via conventions

It is intended for situations where most common protocols ( e.g. HTTP, WebSockets ) are overkill, yet a structured way for exchanging data is still needed. This can mean, among others, cases where pulling in a full-fledged HTTP / WebSocket / other implementation would increase binary sizes too much, or cases where most of the protocol's features would be unused.

Specification

Warning

The specification is still work in progress

Core

Implementing the core specification is enough for conformance. Additional features may be built on top of it as conventions.

Commands

Trimsock exchanges commands, with each command consisting of the command name, a single space, the command data and a single newline character, delimiting the command:

[command name] [command data]\n

An example command:

login [email protected]:ef92b778bafe771e89245b89ecbc08a44a4e166c06659911881f383d4473e94f

A command may omit the command data:

[command name] \n

Note that even without command data, the space character is required.

Commands must be parsed as UTF-8 strings.

Escape sequences

TODO

  • newline -> \n
  • space -> \s

Binary data

To support transmitting binary data, command data may be prefixed with the string \b ( backspace ), and a number declaring the size of the binary data.

The receiving party must consider the next n bytes after the prefix sequence as binary. Once the binary data has been received, the command is terminated with the newline character.

[command name] \b[data size in bytes][binary data]\n

Implementations may impose their own limits on the size of binary data, for security reasons.

Example:

set-picture \b1524...\n

Conventions

Multiple command parameters

In case a command needs multiple parameters instead of a single command data blob, implementations may split the command data into multiple command parameters.

This is done by splitting the command data at every space character:

[command name] [command parameter] [command parameter] [...]\n

For example:

set-user-details Tom Acme [email protected]

Request-response pairs

A common use case is requesting some data, and then receiving it in a response message.

To support this, command names may be extended with a request id that uniquely identifies the request-response exchange:

[command name]:[request-id] [command data]\n

Note that to an implementation that does not handle request-response pairs, this is still a valid command.

The request id must be a string unique to the connection. Implementations are free to choose their own approach, for example sequential IDs, UUIDs, or nanoids.

A request-response exchange happens by both peers using the same request id across multiple commands, for example:

>>> login:i6QhjOtphK2m [email protected]:ef92b778bafe771e89245b89ecbc08a44a4e166c06659911881f383d4473e94f\n
<<< login:i6QhjOtphK2m OK\n

TODO: Does the response have to use the same command, or is it enough to have the same request id?

Streaming

Large amounts of data can be impractical to transmit in one large command. Instead, implementations may use request ID's as outlined in Request-response pairs and use them for streaming.

In this case, each request ID is used to identify a stream. Multiple commands are sent with this request ID, each transmitting a chunk of command data. Once all the data has been streamed, a command is sent omitting command data:

[command name]:[request-id] [command data]\n
[command name]:[request-id] [command data]\n
[command name]:[request-id] \n

An example stream exchange, combined with request-response pairs:

>>> get-file:AUygn0OwMgYu big-video.mp4
<<< get-file:AUygn0OwMgYu \b1024...\n
<<< get-file:AUygn0OwMgYu \b1024...\n
<<< get-file:AUygn0OwMgYu \b1024...\n
<<< get-file:AUygn0OwMgYu \n
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment