relay

package
v1.0.5 Latest Latest
Warning

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

Go to latest
Published: Aug 22, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package relay maintains fort serve's outbound tunnel to the 028 gateway: one WebSocket to the broker, per-client-session Noise IK handshakes (exec/relay/secure), and sealed HTTP/SSE service against an injected http.Handler — the transport never imports ui (seam: it moves bytes).

Config{URL, Token, Key, MinBackoff, OnConnectionEvent}; New(handler, cfg) *Transport; (t *Transport) Run(ctx) error — reconnect loop with exponential backoff (MinBackoff..30s, jittered) until ctx is done.

Per inbound frame:

hs1  -> NewResponder(cfg.Key) for that stream; ReadMessage(payload);
        WriteMessage -> reply kind hs2; store Session on completion.
req  -> sess.Open -> ReqPayload -> serve:
          non-stream: httptest.NewRecorder over the handler; reply res.
          stream (Accept: text/event-stream): spawn goroutine with a
          cancelable context; a streamWriter ResponseWriter seals+sends a
          res{Stream:true} on WriteHeader, then chunk frames on each
          Flush; register cancel under (stream,id) for "end".
end  -> sess.Open -> id -> cancel that request.
bye  -> drop the stream's session + cancel its in-flight requests.

Writes to the socket are serialized with a mutex — and, crucially, each Seal happens under that same lock immediately before its write, so the AEAD nonce order (per session) always matches wire order, which is what the peer decrypts in. A dropped socket cancels every in-flight request and re-dials.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ChunkPayload

type ChunkPayload struct {
	ID   string `json:"id"`
	Data []byte `json:"data,omitempty"`
	End  bool   `json:"end,omitempty"`
}

ChunkPayload is the sealed plaintext of a "chunk" frame (SSE piece).

type Config

type Config struct {
	URL               string         // broker WebSocket URL (e.g. wss://gw/tunnel)
	Token             string         // device token, sent as Authorization: Bearer
	Key               secure.Keypair // this daemon's pinned static identity
	MinBackoff        time.Duration  // reconnect backoff floor (default 1s)
	OnConnectionEvent func(ConnectionEvent)
}

Config configures the outbound tunnel.

type ConnectionEvent added in v0.13.0

type ConnectionEvent struct {
	State   ConnectionState
	Err     error
	RetryIn time.Duration
}

ConnectionEvent reports connection lifecycle without exposing the relay URL, device token, or application payloads. RetryIn is set only for failures that will be retried. The callback runs synchronously and should return quickly.

type ConnectionState added in v0.13.0

type ConnectionState string

ConnectionState is one observable transition in the outbound relay socket.

const (
	ConnectionDialing      ConnectionState = "dialing"
	ConnectionConnected    ConnectionState = "connected"
	ConnectionDialFailed   ConnectionState = "dial_failed"
	ConnectionDisconnected ConnectionState = "disconnected"
)

type Frame

type Frame struct {
	Stream string `json:"stream"`
	Kind   string `json:"kind"` // hs1|hs2|req|res|chunk|end|bye
	B64    string `json:"b64,omitempty"`
}

Frame is the single WebSocket envelope of the gateway wire contract (spec 028). The broker routes on Stream/Kind and never sees inside B64 once a session is sealed.

type ReqPayload

type ReqPayload struct {
	ID      string            `json:"id"`
	Method  string            `json:"method"`
	Path    string            `json:"path"`
	Headers map[string]string `json:"headers,omitempty"`
	Body    []byte            `json:"body,omitempty"`
}

ReqPayload is the sealed plaintext of a "req" frame.

type ResPayload

type ResPayload struct {
	ID      string            `json:"id"`
	Status  int               `json:"status"`
	Headers map[string]string `json:"headers,omitempty"`
	Body    []byte            `json:"body,omitempty"`
	Stream  bool              `json:"stream,omitempty"` // true => chunks follow
}

ResPayload is the sealed plaintext of a "res" frame.

type Transport

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

Transport maintains one outbound WebSocket, serving handler through it.

func New

func New(handler http.Handler, cfg Config) *Transport

New builds a transport that serves handler over the tunnel described by cfg.

func (*Transport) Run

func (t *Transport) Run(ctx context.Context) error

Run maintains the outbound socket, reconnecting with jittered exponential backoff until ctx is done. It returns ctx.Err() on shutdown.

Directories

Path Synopsis
Package secure is Fort's E2E crypto contract for the relay (spec 028): a Noise IK handshake (X25519) between a client and the daemon's pinned static key, then ChaCha20-Poly1305 AEAD framing.
Package secure is Fort's E2E crypto contract for the relay (spec 028): a Noise IK handshake (X25519) between a client and the daemon's pinned static key, then ChaCha20-Poly1305 AEAD framing.

Jump to

Keyboard shortcuts

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