wsframe

package
v0.331.0 Latest Latest
Warning

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

Go to latest
Published: May 21, 2026 License: AGPL-3.0 Imports: 5 Imported by: 0

Documentation

Overview

Package wsframe decodes WebSocket frames per RFC 6455.

Wrap-vs-native judgement

Native. RFC 6455 is fully public; the wire format is a
tight bit-packed header (FIN/RSV/opcode/MASK/payload-len)
with two variable-length escape hatches (extended 16-bit
and extended 64-bit payload length) and an optional
4-byte mask key. The walker handles fragmentation
(Continuation opcode 0x0 after a Text/Binary opener) and
demasks payload bytes when the MASK bit is set
(client→server frames per §5.3 must be masked).
Operators paste WebSocket frame bytes from a mitmproxy /
wsdump / Chrome DevTools Network panel export and inspect
every documented field. Pure offline parser — no
transport, no hardware.

What this package covers

  • Frame header (2 bytes minimum): byte 0: FIN | RSV1 | RSV2 | RSV3 | opcode (4) byte 1: MASK | payload-len (7)

  • Extended payload length: when payload-len == 126, the next 2 bytes are the actual length (uint16 BE); when payload-len == 127, the next 8 bytes are the actual length (uint64 BE).

  • Mask key: 4 bytes immediately after the length field when MASK == 1. Per RFC 6455 §5.3, every client→server frame MUST be masked; server→client frames MUST NOT be masked.

  • Opcodes (RFC 6455 §11.8): 0x0 Continuation 0x1 Text (UTF-8) 0x2 Binary 0x3-0x7 reserved (non-control) 0x8 Close 0x9 Ping 0xA Pong 0xB-0xF reserved (control)

  • Payload demasking: when MASK == 1, each payload byte b[i] is XORed with maskKey[i%4] to recover plaintext.

  • Close frame body (opcode 0x8): first 2 bytes are a uint16 BE status code (RFC 6455 §7.4.1), remaining bytes are optional UTF-8 reason text. The status-code table covers documented 1xxx codes (1000-1015) plus the user/library ranges (3000-3999 / 4000-4999).

  • Text/Binary frame body: text is surfaced as a string when the bytes are valid UTF-8 and free of control characters; otherwise as uppercase hex. Binary frames always surface as uppercase hex.

  • Multi-frame buffer walking: a single buffer may carry several concatenated frames (server→client streams often do this). The walker iterates frame-by-frame until the buffer is consumed and surfaces a summary of opcodes seen.

What this package does NOT cover (deliberately out of scope)

  • HTTP/1.x Upgrade handshake (Sec-WebSocket-Key / Accept / Version / Extensions / Protocol) — already handled by internal/httpmsg (the Upgrade headers are preserved verbatim; this package starts at the first frame after the 101 Switching Protocols response).

  • Per-message Deflate (RFC 7692) — RSV1 indicates that the payload is permessage-deflate compressed; we surface RSV1=true and the raw (still-compressed) payload as hex. Operators who need cleartext can pipe the bytes through their own decompressor.

  • Subprotocols (e.g. MQTT-over-WebSocket, STOMP, graphql-ws) — opcode 0x1/0x2 payloads are surfaced as text or hex; subprotocol-specific framing belongs in a sibling helper.

  • Statefulness across frames — fragmentation is detected (FIN=0 + opcode!=0 on opener; FIN=0/1 + opcode=0 on continuation) and surfaced in each frame's flags, but the package does not reassemble continuation chains into a single logical message.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CloseInfo

type CloseInfo struct {
	StatusCode int    `json:"status_code"`
	StatusName string `json:"status_name"`
	Reason     string `json:"reason,omitempty"`
}

CloseInfo is the parsed Close-frame body (opcode 0x8).

type Frame

type Frame struct {
	FIN            bool       `json:"fin"`
	RSV1           bool       `json:"rsv1"`
	RSV2           bool       `json:"rsv2"`
	RSV3           bool       `json:"rsv3"`
	Opcode         int        `json:"opcode"`
	OpcodeName     string     `json:"opcode_name"`
	IsControl      bool       `json:"is_control"`
	Masked         bool       `json:"masked"`
	PayloadLenRaw  int        `json:"payload_len_raw"`
	PayloadLength  uint64     `json:"payload_length"`
	MaskKey        string     `json:"mask_key,omitempty"`
	HeaderBytes    int        `json:"header_bytes"`
	FrameBytes     int        `json:"frame_bytes"`
	PayloadHex     string     `json:"payload_hex,omitempty"`
	PayloadHexClip bool       `json:"payload_hex_truncated,omitempty"`
	PayloadText    string     `json:"payload_text,omitempty"`
	Close          *CloseInfo `json:"close,omitempty"`
	Notes          []string   `json:"notes,omitempty"`
}

Frame is one decoded WebSocket frame.

type Result

type Result struct {
	Frames     []Frame `json:"frames"`
	FrameCount int     `json:"frame_count"`
	TotalBytes int     `json:"total_bytes"`
	Summary    string  `json:"summary"`
}

Result is the top-level decoded view.

func Decode

func Decode(hexStr string) (*Result, error)

Decode parses a buffer of one or more concatenated WebSocket frames from hex.

Jump to

Keyboard shortcuts

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