4 Geek Stuff
Neale Pickett edited this page 2022-06-06 15:09:38 -06:00

Message Format

Vail uses WebSockets at https://vail.woozle.org/chat?repeater=Foo. It accepts two subprotocols: both of these provide the same message information, in different encodings.

The server will accept packets in either format, but will only send packets in the format described by the subprotocol.

Subprotocol binary.vail.woozle.org

Network byte order, "binary" version of a Message structure. To send messages in this format, be sure you specify a binary WebSocket message.

// Message is a single Vail message.
type Message struct {
	// Timestamp of this message. Milliseconds since epoch.
	Timestamp int64

	// Number of connected clients.
	Clients uint16

	// Message timing in milliseconds.
	// Timings alternate between tone and silence.
	// For example, `A` could be sent as [80, 80, 240]
	Duration []uint16
}

Subprotocol json.vail.woozle.org

A JSON encoded version of the message structure. Be sure to specify a text WebSocket message.

Example:

{
  "Timestamp": 1654548878301,
  "Clients": 3,
  "Duration": [101, 100, 103, 98, 97, 106, 315]
}

How Vail Gets Realtime Morse Code across the Internet

The Internet isn't exactly like radio waves: it still goes at near the speed of light, but there are multiple hops between endpoints, which buffer up transmissions, and multiplex them onto a single uplink connection. These repeaters (routers) are also allowed to just drop things if they need to. It's the responsibility of the communicating parties to work out whether something needs to be retransmitted. Because of this, there's no telling how long it will take for a transmission to get to a destination.

Each Vail transmission (packet) consists of:

  • timestamp (milliseconds since 1 Jan 1970, 00:00:00 in Reykjavík)
  • transmission duration (milliseconds)

The repeater does nothing but broadcast everything it gets to every connected Vail client, including the one that sent the packet. When your client gets back the exact same thing it sent, it compares the current time to the time in the packet. This is the round-trip time: the time it takes for a packet to get from your computer to the repeater and back.

When the client gets a packet it didn't send, it adds the receive delay to the timestamp, and schedules to play the tones and silences in the packet at that time.

By adding the maximum round-trip time to the longest recent transmission (the length of a dah, hopefully), your client can make a guess about how much time needs to be added to a received timestamp, in order to have it play back in the future at the time it comes in. This is just a guess. If you're communicating with somebody with a higher round-trip time than you have, you'll need to raise your receive delay to account for it.