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 ¶
const ( Version1 uint8 = 1 CurrentVersion = Version1 )
Version is a 3-bit ORP protocol version field.
const HeaderSize = 8
HeaderSize is the fixed ORP frame header length in bytes.
const MaxPayload = 1 << 24
MaxPayload is the maximum payload size (16 MiB).
Variables ¶
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") )
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 ¶
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 ¶
UnmarshalProto decodes f.Payload into dst. Returns ErrTypeMismatch if expectedType is non-zero and f.Type differs.
Types ¶
type Frame ¶
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 ¶
MarshalProto wraps a protobuf payload in a Frame of the given type. Most callers should use this rather than constructing Frame literals.
func ParseFrame ¶
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 ¶
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.
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 (*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.
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.