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 ¶
- type ClientCapabilities
- type ClientState
- func (cs *ClientState) CanHandleDiff() bool
- func (cs *ClientState) CanHandlePredictiveEcho() bool
- func (cs *ClientState) GetMinFrameInterval() time.Duration
- func (cs *ClientState) RecordDiffSent(size int, fullRedraw bool)
- func (cs *ClientState) RecordDroppedFrame()
- func (cs *ClientState) RecordEchoAck()
- func (cs *ClientState) RecordResync()
- func (cs *ClientState) UpdateRTT(sample time.Duration)
- type ClientStats
- type Coordinator
- func (c *Coordinator) GetClientCount() int
- func (c *Coordinator) GetCurrentSequence() uint64
- func (c *Coordinator) ProcessInput(clientID string, data []byte, echoNum uint64, clientTimestampMs int64)
- func (c *Coordinator) ProcessPTYOutput(data []byte) map[string]*framebuffer.DiffResult
- func (c *Coordinator) ProcessResize(rows, cols int)
- func (c *Coordinator) RegisterClient(clientID string, capabilities *ClientCapabilities) *framebuffer.DiffResult
- func (c *Coordinator) RequestResync(clientID string) *framebuffer.DiffResult
- func (c *Coordinator) SetFrameInterval(interval time.Duration)
- func (c *Coordinator) UnregisterClient(clientID string)
- type CoordinatorConfig
- type EchoAck
- type EchoEntry
- type EchoHistory
- func (h *EchoHistory) Clear(clientID string)
- func (h *EchoHistory) GetAckNum(clientID string) uint64
- func (h *EchoHistory) GetHighestReceived(clientID string) uint64
- func (h *EchoHistory) GetPendingCount(clientID string) int
- func (h *EchoHistory) MarkAcknowledged(clientID string, upToEchoNum uint64)
- func (h *EchoHistory) Record(clientID string, echoNum uint64, clientTimestampMs int64, data []byte)
- func (h *EchoHistory) SetAckTimeout(timeout time.Duration)
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 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.