wire

package
v0.701.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 21, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package wire formats and parses the line-based JaWS WebSocket protocol.

The package has two message layers. Message is an in-process dispatch record routed through Message.Dest. WsMsg is one browser protocol record; WsMsg.Append serializes it and Parse recovers it.

Each record is What<TAB>Jid<TAB>Data<LF>. One WebSocket text message may contain several records; ReadLoop preserves valid-record order and skips malformed records independently.

WsMsg.Append JSON-quotes Data for commands other than github.com/linkdata/jaws/lib/what.Set and github.com/linkdata/jaws/lib/what.Call. Parse decodes quote-prefixed Data and sanitizes every accepted result as valid UTF-8; unquoted Data is accepted verbatim. Set and Call always carry verbatim path=json Data, which must contain no raw tab or LF delimiters. See github.com/linkdata/jaws/lib/what for command semantics and github.com/linkdata/jaws/lib/tag for destination keys.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AppendJSONQuote added in v0.500.0

func AppendJSONQuote(b []byte, s string) []byte

AppendJSONQuote appends s to b as a JSON string literal accepted by JSON.parse.

Use it instead of strconv.AppendQuote when quoted data is written into a protocol record: strconv emits Go-only escapes (\xNN, \UXXXXXXXX) for control bytes, DEL, and invalid UTF-8 that JSON.parse rejects.

func ReadLoop

func ReadLoop(ctx context.Context, ccf context.CancelCauseFunc, doneCh <-chan struct{}, incomingMsgCh chan<- WsMsg, idleInterval, pingTimeout time.Duration, ws *websocket.Conn)

ReadLoop reads WebSocket text messages and sends each valid protocol record on incomingMsgCh.

Records are LF-terminated and delivered in order. A text message may contain multiple records; malformed records are skipped independently.

A WebSocket read that remains pending for idleInterval triggers a ping bounded by pingTimeout. Incoming data or a successful ping restarts the idle interval. Time spent parsing or delivering an already-read message does not count toward it. If a message is processed while a ping is pending, that ping's failure is ignored. idleInterval and pingTimeout must be positive.

Closes incomingMsgCh on exit.

Canceling ctx or closing doneCh interrupts reads and pings in progress and is not reported through ccf.

ccf may be nil, in which case errors are not reported and only the loop exits.

func WriteLoop

func WriteLoop(ctx context.Context, ccf context.CancelCauseFunc, doneCh <-chan struct{}, outboundMsgCh <-chan WsMsg, writeTimeout time.Duration, ws *websocket.Conn)

WriteLoop formats messages read from outboundMsgCh and writes them to the WebSocket.

Consecutive queued records may be coalesced into one text message.

Each WebSocket write has its own writeTimeout deadline; writeTimeout must be positive.

Closes the WebSocket on exit.

Canceling ctx or closing doneCh interrupts writes in progress and is not reported through ccf.

ccf may be nil, in which case errors are not reported and only the loop exits.

Types

type Message

type Message struct {
	// Dest selects recipients among active Requests: nil targets every active
	// Request, a nonzero request key targets the matching active Request, and any
	// other value is expanded into a tag or tag list. Plain strings and Jid values
	// are illegal destinations.
	Dest any
	What what.What // command to perform
	Data string    // payload: inner HTML content or a tag list
}

Message contains the elements of a message to be sent to requests.

func (*Message) String

func (msg *Message) String() string

String returns the Message in a form suitable for debug output.

Dest is rendered with tag.TagString, so in the default build it shows only its type (and, for a pointer, its address when it can be read safely) and a malformed Dest cannot crash the caller; build with -tags debug or -race for full-value rendering, which is more informative but not crash-safe.

type WsMsg

type WsMsg struct {
	Data string    // data to send
	Jid  jid.Jid   // non-negative Jid to send
	What what.What // command
}

WsMsg is a protocol record sent to or from a WebSocket.

func Parse

func Parse(txt []byte) (WsMsg, bool)

Parse parses one LF-terminated protocol record.

The wire format mirrors WsMsg.Append. For commands other than what.Set and what.Call, if the Data field begins with a double quote it is decoded as a JSON string: strconv.Unquote handles the common case, with a fallback to a JSON string decode for inputs it rejects but the browser's JSON.stringify can produce (notably a lone UTF-16 surrogate, which the fallback maps to U+FFFD). The message is rejected only if both decoders fail. Data that does not begin with a double quote is taken verbatim, as is all Set and Call data. In all cases the resulting data is sanitized with strings.ToValidUTF8.

Inbound what.Set and what.Call data is taken verbatim at the field boundaries and is best-effort: the field ends at the first tab, so a tab inside an inbound Set or Call payload truncates the field.

func (*WsMsg) Append

func (m *WsMsg) Append(b []byte) []byte

Append appends m in wire format to b and returns the extended buffer.

The record is What<TAB>Jid<TAB>Data<LF>, where the Jid field is empty if Jid is zero. The Data field is written verbatim for what.Set and what.Call and JSON-quoted for every other command. Append panics if Jid is negative.

Verbatim Data must contain no tab or newline bytes, which would corrupt the record; ensuring that is the caller's responsibility.

func (*WsMsg) FillAlert

func (m *WsMsg) FillAlert(err error)

FillAlert replaces m with an escaped danger alert for err.

A nil err yields a danger alert with an empty message rather than panicking.

func (*WsMsg) Format

func (m *WsMsg) Format() string

Format returns m in wire format.

Format panics if Jid is negative.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL