ssp

package
v1.35.0 Latest Latest
Warning

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

Go to latest
Published: Jul 6, 2026 License: AGPL-3.0 Imports: 4 Imported by: 0

Documentation

Overview

Package ssp implements the State Synchronization Protocol (SSP) for efficient terminal streaming. Inspired by Mosh (Mobile Shell), SSP provides:

  • Minimal ANSI escape sequence diffs (not full screen updates)
  • Predictive echo for low-latency typing experience
  • RTT-based adaptive frame rate throttling
  • Automatic resync on sequence mismatch

The Coordinator manages the server-side SSP state for a single session, tracking per-client state and generating optimized diffs.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ClientCapabilities

type ClientCapabilities struct {
	// SupportsPredictiveEcho indicates the client can handle predictive echo
	SupportsPredictiveEcho bool

	// SupportsDiffUpdates indicates the client can process diff messages
	SupportsDiffUpdates bool

	// CompressionAlgorithms supported by the client
	CompressionAlgorithms []string

	// ProtocolVersion is the SSP protocol version supported
	ProtocolVersion uint32

	// MaxDiffSize is the maximum diff size the client can handle
	MaxDiffSize uint32

	// PreferredFrameIntervalMs is the client's preferred update rate
	PreferredFrameIntervalMs uint32
}

ClientCapabilities represents the SSP features a client supports.

type ClientState

type ClientState struct {
	// ClientID is the unique identifier for this client
	ClientID string

	// Capabilities negotiated during connection
	Capabilities *ClientCapabilities

	// LastFramebuffer is the client's last known terminal state
	// Used as the base for generating diffs
	LastFramebuffer *session.TerminalState

	// LastSequence is the sequence number of the last state sent to client
	LastSequence uint64

	// LastEchoAckNum is the last echo acknowledgment sent to client
	LastEchoAckNum uint64

	// RTT estimation using TCP-style SRTT calculation
	SRTT time.Duration // Smoothed RTT

	// Connected timestamp
	ConnectedAt time.Time

	// Statistics
	Stats ClientStats
}

ClientState tracks the SSP state for a single connected client. Each client has its own view of the terminal state for accurate diffing.

func NewClientState

func NewClientState(clientID string, capabilities *ClientCapabilities) *ClientState

NewClientState creates a new client state with the given capabilities.

func (*ClientState) CanHandleDiff

func (cs *ClientState) CanHandleDiff() bool

CanHandleDiff returns true if the client supports diff updates.

func (*ClientState) CanHandlePredictiveEcho

func (cs *ClientState) CanHandlePredictiveEcho() bool

CanHandlePredictiveEcho returns true if the client supports predictive echo.

func (*ClientState) GetMinFrameInterval

func (cs *ClientState) GetMinFrameInterval() time.Duration

GetMinFrameInterval returns the recommended minimum frame interval based on RTT and client preferences.

func (*ClientState) RecordDiffSent

func (cs *ClientState) RecordDiffSent(size int, fullRedraw bool)

RecordDiffSent records statistics for a sent diff.

func (*ClientState) RecordDroppedFrame

func (cs *ClientState) RecordDroppedFrame()

RecordDroppedFrame records a dropped frame due to throttling.

func (*ClientState) RecordEchoAck

func (cs *ClientState) RecordEchoAck()

RecordEchoAck records a sent echo acknowledgment.

func (*ClientState) RecordResync

func (cs *ClientState) RecordResync()

RecordResync records a resync request from client.

func (*ClientState) UpdateRTT

func (cs *ClientState) UpdateRTT(sample time.Duration)

UpdateRTT updates the smoothed RTT using TCP-style calculation. SRTT = (1 - alpha) * SRTT + alpha * sample Using alpha = 0.125 (TCP default)

type ClientStats

type ClientStats struct {
	// BytesSent is the total bytes sent to this client
	BytesSent uint64

	// DiffsSent is the number of diff updates sent
	DiffsSent uint64

	// FullRedraws is the number of full redraws sent
	FullRedraws uint64

	// DroppedFrames is the number of frames dropped due to throttling
	DroppedFrames uint64

	// EchoAcks is the number of echo acknowledgments sent
	EchoAcks uint64

	// ResyncRequests is the number of resync requests from client
	ResyncRequests uint64
}

ClientStats tracks statistics for a client connection.

type Coordinator

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

Coordinator manages SSP state for a single terminal session. It tracks the current framebuffer state and generates diffs for connected clients.

func NewCoordinator

func NewCoordinator(sessionID string, config CoordinatorConfig) *Coordinator

NewCoordinator creates a new SSP coordinator for the given session.

func (*Coordinator) GetClientCount

func (c *Coordinator) GetClientCount() int

GetClientCount returns the number of connected clients.

func (*Coordinator) GetCurrentSequence

func (c *Coordinator) GetCurrentSequence() uint64

GetCurrentSequence returns the current framebuffer sequence number.

func (*Coordinator) ProcessInput

func (c *Coordinator) ProcessInput(clientID string, data []byte, echoNum uint64, clientTimestampMs int64)

ProcessInput handles user input with echo tracking. Returns the echo number for predictive echo acknowledgment.

func (*Coordinator) ProcessPTYOutput

func (c *Coordinator) ProcessPTYOutput(data []byte) map[string]*framebuffer.DiffResult

ProcessPTYOutput handles new PTY output by updating the framebuffer and generating diffs for all connected clients.

Returns a map of clientID -> diff for clients that should receive updates. Some clients may be skipped due to frame rate throttling.

func (*Coordinator) ProcessResize

func (c *Coordinator) ProcessResize(rows, cols int)

ProcessResize handles terminal resize events.

func (*Coordinator) RegisterClient

func (c *Coordinator) RegisterClient(clientID string, capabilities *ClientCapabilities) *framebuffer.DiffResult

RegisterClient adds a new client for SSP updates. Returns the current framebuffer state for initial sync.

func (*Coordinator) RequestResync

func (c *Coordinator) RequestResync(clientID string) *framebuffer.DiffResult

RequestResync requests a full state sync for a client. Used when client detects sequence mismatch.

func (*Coordinator) SetFrameInterval

func (c *Coordinator) SetFrameInterval(interval time.Duration)

SetFrameInterval updates the minimum frame interval. Can be adjusted based on RTT measurements.

func (*Coordinator) UnregisterClient

func (c *Coordinator) UnregisterClient(clientID string)

UnregisterClient removes a client from SSP tracking.

type CoordinatorConfig

type CoordinatorConfig struct {
	// MinFrameIntervalMs is the minimum time between frame updates (default: 16ms = 60fps)
	MinFrameIntervalMs int

	// MaxDiffSize is the maximum diff size before falling back to full state (default: 64KB)
	MaxDiffSize int

	// EchoTimeoutMs is the timeout for predictive echo acknowledgment (default: 50ms, like Mosh)
	EchoTimeoutMs int

	// EchoHistorySize is the number of echo entries to track (default: 1000)
	EchoHistorySize int
}

CoordinatorConfig holds configuration options for the coordinator.

func DefaultConfig

func DefaultConfig() CoordinatorConfig

DefaultConfig returns the default coordinator configuration.

type EchoAck

type EchoAck struct {
	EchoAckNum        uint64
	ServerTimestampMs int64
}

EchoAck represents an echo acknowledgment to be sent to a client.

type EchoEntry

type EchoEntry struct {
	ClientID          string
	EchoNum           uint64
	ClientTimestampMs int64
	ServerTimestampMs int64
	Data              []byte
	Acknowledged      bool
}

EchoEntry represents a single input echo tracking entry.

type EchoHistory

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

EchoHistory tracks user input for predictive echo acknowledgment. Uses a ring buffer to efficiently track recent inputs and their ack status.

func NewEchoHistory

func NewEchoHistory(size int) *EchoHistory

NewEchoHistory creates a new echo history with the given capacity.

func (*EchoHistory) Clear

func (h *EchoHistory) Clear(clientID string)

Clear removes all entries for a client (e.g., on disconnect).

func (*EchoHistory) GetAckNum

func (h *EchoHistory) GetAckNum(clientID string) uint64

GetAckNum returns the highest echo number that should be acknowledged. Uses timeout-based heuristic: if input is older than ackTimeout, consider it processed.

func (*EchoHistory) GetHighestReceived

func (h *EchoHistory) GetHighestReceived(clientID string) uint64

GetHighestReceived returns the highest echo number received from a client.

func (*EchoHistory) GetPendingCount

func (h *EchoHistory) GetPendingCount(clientID string) int

GetPendingCount returns the number of unacknowledged entries for a client.

func (*EchoHistory) MarkAcknowledged

func (h *EchoHistory) MarkAcknowledged(clientID string, upToEchoNum uint64)

MarkAcknowledged marks echo entries up to the given echoNum as acknowledged. Called when PTY output is received, indicating input has been processed.

func (*EchoHistory) Record

func (h *EchoHistory) Record(clientID string, echoNum uint64, clientTimestampMs int64, data []byte)

Record adds a new input entry for echo tracking.

func (*EchoHistory) SetAckTimeout

func (h *EchoHistory) SetAckTimeout(timeout time.Duration)

SetAckTimeout sets the timeout for considering input as processed.

Jump to

Keyboard shortcuts

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