orp

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Apr 28, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

Documentation

Overview

Package orp implements the OutRelay Protocol (ORP) wire format and stream state machine. ORP rides on top of QUIC: stream 0 carries control frames, streams N>0 carry per-application data streams.

Each frame is an 8-byte big-endian fixed header followed by a protobuf-encoded payload:

bytes [0:2]  Version(3) | Reserved(2) | Type(11)
bytes [2:4]  Flags
bytes [4:8]  Length (payload bytes, max 2^24)
bytes [8:..] Payload (protobuf-encoded message for the given Type)

Once the relay has paired the two halves of a data stream and entered splice mode, framing stops — the relay just copies raw bytes between the two QUIC streams. ORP framing therefore only applies to control frames (stream 0) and to the negotiation frames at the start of each data stream.

Index

Constants

View Source
const (
	Version1       uint8 = 1
	CurrentVersion       = Version1
)

Version is a 3-bit ORP protocol version field.

View Source
const HeaderSize = 8

HeaderSize is the fixed ORP frame header length in bytes.

View Source
const MaxPayload = 1 << 24

MaxPayload is the maximum payload size (16 MiB).

Variables

View Source
var (
	ErrInvalidVersion  = errors.New("orp: invalid version")
	ErrInvalidType     = errors.New("orp: invalid frame type")
	ErrPayloadTooLarge = errors.New("orp: payload exceeds MaxPayload")
	ErrShortHeader     = errors.New("orp: short header")
)
View Source
var ErrTypeMismatch = errors.New("orp: frame type mismatch")

ErrTypeMismatch is returned when a Frame's Type does not match the expected payload type.

Functions

func IsSupportedVersion

func IsSupportedVersion(v uint8) bool

IsSupportedVersion reports whether v can be processed by this build. Version negotiation today is trivial — only Version1 exists. When v2 ships, this and HELLO/HELLO_ACK payloads gain real negotiation logic.

func UnmarshalProto

func UnmarshalProto(f *Frame, expectedType FrameType, dst proto.Message) error

UnmarshalProto decodes f.Payload into dst. Returns ErrTypeMismatch if expectedType is non-zero and f.Type differs.

func WriteFrame

func WriteFrame(w interface {
	Write([]byte) (int, error)
}, typ FrameType, msg proto.Message) error

WriteFrame marshals msg, wraps it in a Frame, serializes to bytes, and writes it to w. Convenience for "open stream + write one frame" call sites.

Types

type Frame

type Frame struct {
	Version uint8
	Type    FrameType
	Flags   uint16
	Payload []byte
}

Frame is a parsed ORP frame. Payload is a protobuf-encoded message whose type is identified by Type; callers Unmarshal the payload using the matching message in lib/orp/v1.

func MarshalProto

func MarshalProto(typ FrameType, msg proto.Message) (*Frame, error)

MarshalProto wraps a protobuf payload in a Frame of the given type. Most callers should use this rather than constructing Frame literals.

func ParseFrame

func ParseFrame(r io.Reader) (*Frame, error)

ParseFrame reads exactly one frame from r. It returns io.EOF only if r returned io.EOF before any header byte was read; a short header read returns io.ErrUnexpectedEOF.

func (*Frame) MarshalBinary

func (f *Frame) MarshalBinary() ([]byte, error)

MarshalBinary serializes the frame into wire bytes.

type FrameType

type FrameType uint16

FrameType is the 11-bit type code identifying a frame.

const (
	FrameTypeHello          FrameType = 0x001
	FrameTypeHelloAck       FrameType = 0x002
	FrameTypeRegister       FrameType = 0x003
	FrameTypeRegisterAck    FrameType = 0x004
	FrameTypeResolve        FrameType = 0x005
	FrameTypeResolveResp    FrameType = 0x006
	FrameTypeOpenStream     FrameType = 0x010
	FrameTypeIncomingStream FrameType = 0x011
	FrameTypeStreamAccept   FrameType = 0x012
	FrameTypeStreamReject   FrameType = 0x013
	FrameTypePing           FrameType = 0x020
	FrameTypePong           FrameType = 0x021
	FrameTypePolicyUpdate   FrameType = 0x030
	FrameTypeMetricReport   FrameType = 0x040
	FrameTypeGoaway         FrameType = 0x0FF
)

Control frames live on stream 0.

const (
	FrameTypeStreamInit  FrameType = 0x100
	FrameTypeStreamData  FrameType = 0x101
	FrameTypeStreamFin   FrameType = 0x102
	FrameTypeStreamReset FrameType = 0x103
)

Data-stream frames (stream N>0). After splice, the framing is dropped.

const (
	FrameTypeStreamCheckpoint FrameType = 0x110
	FrameTypeStreamResume     FrameType = 0x111
)

Stream-resume frames carry the per-stream byte counters that let agents pick up after a relay-side reconnect; see lib/resume.

const (
	FrameTypeObservedAddrQuery FrameType = 0x120
	FrameTypeObservedAddrResp  FrameType = 0x121
	FrameTypeCandidateOffer    FrameType = 0x122
	FrameTypeCandidateAnswer   FrameType = 0x123
	FrameTypeMigrateToP2P      FrameType = 0x124
	FrameTypeMigrateToRelay    FrameType = 0x125
)

P2P-promotion frames negotiate a direct agent-to-agent path so in-flight streams can migrate off the relay when both sides can reach each other.

const (
	FrameTypeForwardStream FrameType = 0x140
)

Inter-relay forwarding frames. When a target service lives on a peer relay, the local relay opens a new stream to that peer and writes FORWARD_STREAM as the first frame. The peer answers with STREAM_ACCEPT or STREAM_REJECT on the same stream; on accept, both halves enter splice mode.

type StreamEvent

type StreamEvent int

StreamEvent triggers transitions in the stream FSM.

const (
	// EventOpen — initiator sent OPEN_STREAM, or responder received INCOMING_STREAM.
	EventOpen StreamEvent = iota
	// EventAccept — STREAM_ACCEPT observed (provider acknowledged).
	EventAccept
	// EventSplice — Relay completed pairing and entered splice mode.
	EventSplice
	// EventFin — graceful half-close (FIN observed).
	EventFin
	// EventReset — abort (STREAM_REJECT or STREAM_RESET); always terminates.
	EventReset
)

func (StreamEvent) String

func (e StreamEvent) String() string

String returns a human-readable event name.

type StreamFSM

type StreamFSM struct {
	// contains filtered or unexported fields
}

StreamFSM is a small in-memory state machine for a single stream's lifecycle. It is not goroutine-safe; callers serialize Apply.

func NewStreamFSM

func NewStreamFSM() *StreamFSM

NewStreamFSM returns an FSM in StateInit.

func (*StreamFSM) Apply

func (f *StreamFSM) Apply(e StreamEvent) error

Apply transitions the FSM according to e. It returns an error and leaves the state unchanged when the transition is not allowed.

func (*StreamFSM) State

func (f *StreamFSM) State() StreamState

State returns the current state.

type StreamState

type StreamState int

StreamState is the per-stream lifecycle state. The transition table is documented on `transition` below.

const (
	StateInit StreamState = iota
	StateOpening
	StateAccepted
	StateSpliced
	StateClosing
	StateClosed
)

func (StreamState) String

func (s StreamState) String() string

String returns a human-readable state name.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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