Skip to content

circuitlab/pigeon-message

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pigeon Message 🕊️

Protocol specification and TypeScript implementation for messages exchanged in the pigeon-room ecosystem.

This document is the human-readable source of truth for the wire format. Other-language implementations (Swift, etc.) should follow this spec.

Overview

pigeon-message defines two wire formats:

  • Text message — UTF-8 JSON, sent as a WebSocket text frame. Used for signaling (init, clientOpen/clientClose, ping/pong) and user messages.
  • Binary message — a WebSocket binary frame: a JSON header plus a raw payload. Used for file/blob transfer.

The format is versioned independently from the pigeon-room and pigeon-link packages. The format version is an integer. The current version is 1.

Design principle: envelope vs. content

The spec defines the envelope (protocol mechanics); it never interprets application content.

Concern Owner Fields
Versioning spec ver (text) · ver byte (binary)
Routing spec to, from, address
Ordering spec timestamp
Payload reconstruction (hint) spec payloadMeta
Application dispatch app type
Application meaning app body
  • type is a free string chosen by the application. Note that pigeon-room uses init, ping, pong, clientOpen, clientClose, message, sent with from: host.
  • body is opaque (unknown) in both frame types. Its meaning is decided by the application based on type.

Fields

Field Type Set by Notes
ver number sender Format version. Text only. Absent ⇒ treated as v0.
type string sender Application-defined.
to string[] sender Recipient client IDs, or reserved words all / others / host.
body unknown sender Any valid JSON value. Opaque to the spec.
from string room Sender client ID, or host.
address string room The room the message belongs to.
timestamp number room Time of relay. Unix milliseconds.
payloadMeta object sender Binary only, optional. Describes the payload.

On send, a client only provides type, to, body (plus ver, and payloadMeta for binary). The room sets from, address, and timestamp authoritatively on relay.

Reserved words

all, others, and host are reserved. A client ID must never equal one of these.

  • all — everyone.
  • others — everyone except the sender.
  • host — the pigeon-room host (the server). In to, it addresses the host directly: the message reaches the host and is not relayed to other clients. In from, it marks host-originated messages.

Text message

A UTF-8 JSON string sent as a WebSocket text frame.

{
  ver: number;          // format version (currently 1)
  type: string;
  to: string[];
  body: unknown;
  from?: string;       // set by room
  address?: string;    // set by room
  timestamp?: number;  // set by room
}

Example (init, as sent by the room):

{
  "ver": 1,
  "type": "init",
  "to": ["id-0"],
  "body": { "id": "id-0", "clients": ["id-0", "id-1"] },
  "from": "host",
  "address": "pipopo",
  "timestamp": 1690352186179
}

Binary message (v1)

A WebSocket binary frame. Big-endian.

| ver(1B) | hdrLen(2B, BE) | header (UTF-8 JSON, hdrLen B) | payload |
  • ver — format version byte (currently 0x01). This is the single source of truth for the binary frame's version.
  • hdrLen — byte length of the JSON header. Max 65535 (2 bytes). Builders MUST throw if the header exceeds this; parsers MUST validate 3 + hdrLen <= frame length.
  • header — JSON with the same fields as a text message, plus optional payloadMeta. The header JSON does not carry a ver field — the leading ver byte holds the version. If a ver field appears anyway, the ver byte takes precedence.
  • payload — raw bytes (a single blob). The frame is self-delimiting: the payload runs from offset 3 + hdrLen to the end of the frame.

payloadMeta

Optional, application-defined content describing the payload. Not needed to parse the frame.

example:

"payloadMeta": {
  "name": "photo.png",      // filename; not recoverable from the bytes
  "mimeType": "image/png"   // content type; some formats can't be sniffed (.js vs .txt)
}

Versioning

The format version is an integer embedded in the wire format:

  • Text: the ver field.
  • Binary: the leading ver byte.

Rules:

  • Within a version, new optional fields may be added. Parsers MUST ignore unknown fields.
  • A version bump means the wire skeleton changed (e.g. multiple payloads, wider length fields). Parsers branch on the version.
  • ver absent ⇒ v0. Parsers must not reject; treat as v0. (This applies to text only; binary frames have always carried a ver byte.)
  • pigeon-room and pigeon-link declare a supported range of format versions (e.g. a given release supports message v0–v1).

Package structure

pigeon-message/
  README.md          # this spec (source of truth)
  index.ts           # package exports
  types/
    text.ts          # text message types and constants
    binary.ts        # binary frame types and constants

This package defines the format (spec + types). Encoding/decoding is the responsibility of implementations (pigeon-room, pigeon-link).

Development

deno check index.ts

About

No description, website, or topics provided.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors