websocket

package
v0.0.0-...-74bcc06 Latest Latest
Warning

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

Go to latest
Published: Jan 21, 2026 License: AGPL-3.0 Imports: 16 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// is sent when a user updates the code
	TypeCodeUpdate = "code_update"

	// is sent when a new user joins the session
	TypeUserJoined = "user_joined"

	// is sent when a user leaves the session
	TypeUserLeft = "user_left"

	// is sent when a user sends a chat message
	TypeChatMessage = "chat_message"

	// is sent when an error occurs
	TypeError = "error"

	// is sent by clients to keep the connection alive
	TypePing = "ping"

	// is sent by server in response to ping
	TypePong = "pong"

	// is sent by server before shutdown
	TypeServerShutdown = "server_shutdown"

	// is sent to connecting client with session info
	TypeSessionState = "session_state"

	// is sent when host/co-author starts playback
	TypePlay = "play"

	// is sent when host/co-author stops playback
	TypeStop = "stop"

	// is sent when host ends the session
	TypeSessionEnded = "session_ended"

	// is sent when paste lock status changes
	TypePasteLockChanged = "paste_lock_changed"

	// is sent when a user moves their cursor
	TypeCursorPosition = "cursor_position"
)

message type constants for websocket communication

Variables

View Source
var (
	ErrSessionNotFound         = errors.New("session not found")
	ErrUnauthorized            = errors.New("unauthorized")
	ErrInvalidMessage          = errors.New("invalid message format")
	ErrClientNotFound          = errors.New("client not found")
	ErrClientAlreadyRegistered = errors.New("client already registered")
	ErrSessionFull             = errors.New("session is full")
	ErrReadOnly                = errors.New("read-only access")
	ErrConnectionClosed        = errors.New("connection closed")
	ErrRateLimitExceeded       = errors.New("rate limit exceeded")
	ErrCodeTooLarge            = errors.New("code too large")
)

errors

Functions

func CheckOrigin

func CheckOrigin(r *http.Request) bool

func GenerateClientID

func GenerateClientID() (string, error)

Types

type ChatMessagePayload

type ChatMessagePayload struct {
	Message     string `json:"message"`
	DisplayName string `json:"display_name,omitempty"`
}

contains a chat message from a user

type Client

type Client struct {
	// unique identifier for this client
	ID string

	// session ID this client is connected to
	SessionID string

	// user ID (empty for anonymous users)
	UserID string

	// display name for this client
	DisplayName string

	// role in the session (host, co-author, viewer)
	Role string

	// whether this client has an authenticated user account
	IsAuthenticated bool

	// IP address of the client (for connection tracking)
	IPAddress string

	// initial code to send on connect (for joining existing sessions)
	InitialCode string

	// initial chat history to send on connect
	InitialChatHistory []SessionStateChatMessage
	// contains filtered or unexported fields
}

represents a websocket client connection

func NewClient

func NewClient(id, sessionID, userID, displayName, role, ipAddress, initialCode string, initialChatHistory []SessionStateChatMessage, isAuthenticated bool, conn *websocket.Conn, hub *Hub) *Client

creates a new websocket client connection

func (*Client) CanWrite

func (c *Client) CanWrite() bool

checks if the client has write permissions

func (*Client) Close

func (c *Client) Close()

closes the client connection

func (*Client) IsClosed

func (c *Client) IsClosed() bool

checks if the client is closed

func (*Client) ReadPump

func (c *Client) ReadPump()

reads messages from the websocket connection to the hub for processing

func (*Client) Send

func (c *Client) Send(msg *Message) (err error)

sends a message to the client

func (*Client) SendError

func (c *Client) SendError(code, message, details string)

sends an error message to the client

func (*Client) SendErrorWithRequestID

func (c *Client) SendErrorWithRequestID(code, message, details string, requestID *string)

sends an error message to the client with request_id for correlation

func (*Client) WritePump

func (c *Client) WritePump()

writes messages from the hub to the websocket connection for sending to the client

type CodeUpdatePayload

type CodeUpdatePayload struct {
	Code        string `json:"code"`
	CursorLine  int    `json:"cursor_line,omitempty"`
	CursorCol   int    `json:"cursor_col,omitempty"`
	DisplayName string `json:"display_name,omitempty"`
	UserID      string `json:"user_id,omitempty"`
	Role        string `json:"role,omitempty"`   // "host", "co-author" - for cursor tracking
	Source      string `json:"source,omitempty"` // 'typed' | 'loaded_strudel' | 'forked' | 'paste'
}

contains code update information

type CursorPositionPayload

type CursorPositionPayload struct {
	Line        int    `json:"line"`                   // 1-indexed line number
	Col         int    `json:"col"`                    // 0-indexed column number
	UserID      string `json:"user_id,omitempty"`      // user ID (added by backend)
	DisplayName string `json:"display_name,omitempty"` // display name (added by backend)
	Role        string `json:"role,omitempty"`         // role (added by backend)
}

contains cursor position information for collaboration

type Hub

type Hub struct {

	// register requests from clients
	Register chan *Client

	// unregister requests from clients
	Unregister chan *Client

	// broadcast messages to all clients in a session
	Broadcast chan *Message
	// contains filtered or unexported fields
}

maintains the set of active clients and broadcasts messages to sessions

func NewHub

func NewHub() *Hub

func (*Hub) BroadcastToSession

func (h *Hub) BroadcastToSession(sessionID string, msg *Message, excludeClientID string)

sends a message to all clients in a session

func (*Hub) BroadcastToWriters

func (h *Hub) BroadcastToWriters(sessionID string, msg *Message, excludeClientID string)

sends a message only to clients with write permissions (host and co-authors)

func (*Hub) CanAcceptConnection

func (h *Hub) CanAcceptConnection(userID, ipAddress string) (bool, string)

checks if a new connection should be allowed based on limits

func (*Hub) EndSession

func (h *Hub) EndSession(sessionID string, reason string)

broadcasts session_ended to all clients and closes their connections

func (*Hub) GetClientCount

func (h *Hub) GetClientCount(sessionID string) int

returns the number of clients in a session

func (*Hub) GetSessionClients

func (h *Hub) GetSessionClients(sessionID string) []*Client

returns all clients in a session

func (*Hub) GetSessionCount

func (h *Hub) GetSessionCount() int

func (*Hub) IsSessionActive

func (h *Hub) IsSessionActive(sessionID string) bool

IsSessionActive checks if a session has any active WebSocket connections

func (*Hub) OnClientDisconnect

func (h *Hub) OnClientDisconnect(callback func(client *Client))

sets callback to be called when a client disconnects

func (*Hub) OnClientRegistered

func (h *Hub) OnClientRegistered(callback func(client *Client))

sets callback to be called after a client is registered and session_state is sent

func (*Hub) RegisterHandler

func (h *Hub) RegisterHandler(messageType string, handler MessageHandler)

registers a handler for a specific message type

func (*Hub) Run

func (h *Hub) Run()

starts the hub's main loop

func (*Hub) Shutdown

func (h *Hub) Shutdown()

func (*Hub) TrackIPConnection

func (h *Hub) TrackIPConnection(ipAddress string)

increments the connection count for an IP address

func (*Hub) UntrackIPConnection

func (h *Hub) UntrackIPConnection(ipAddress string)

decrements the connection count for an IP address

type Message

type Message struct {
	Type      string          `json:"type"`
	SessionID string          `json:"session_id"`
	ClientID  string          `json:"-"` // Internal only, not sent to clients
	UserID    string          `json:"user_id,omitempty"`
	Timestamp time.Time       `json:"timestamp"`
	Sequence  uint64          `json:"seq,omitempty"`
	Payload   json.RawMessage `json:"payload"`
}

represents a websocket message with typed payload

func NewMessage

func NewMessage(msgType, sessionID, userID string, payload interface{}) (*Message, error)

creates a new message with the given type and payload

func (*Message) UnmarshalPayload

func (m *Message) UnmarshalPayload(v interface{}) error

unmarshals the payload into the provided struct

type MessageHandler

type MessageHandler func(hub *Hub, client *Client, msg *Message) error

processes a specific message type

func ChatHandler

func ChatHandler(sessionRepo sessions.Repository) MessageHandler

handles session chat message messages

func CodeUpdateHandler

func CodeUpdateHandler(sessionRepo sessions.Repository, detector *ccsignals.Detector) MessageHandler

handles code update messages with CC signals detection

func CursorPositionHandler

func CursorPositionHandler() MessageHandler

handles cursor position messages for collaboration

func PingHandler

func PingHandler() MessageHandler

handles ping messages from clients (keep-alive)

func PlayHandler

func PlayHandler() MessageHandler

handles play messages from host/co-author

func StopHandler

func StopHandler() MessageHandler

handles stop messages from host/co-author

type PasteLockChangedPayload

type PasteLockChangedPayload struct {
	Locked bool   `json:"locked"`
	Reason string `json:"reason,omitempty"` // "paste_detected", "edits_sufficient", "ttl_expired"
}

contains paste lock status change

type PlayPayload

type PlayPayload struct {
	DisplayName string `json:"display_name"`
}

contains playback start information

type ServerShutdownPayload

type ServerShutdownPayload struct {
	Reason string `json:"reason"`
}

contains information about server shutdown

type SessionEndedPayload

type SessionEndedPayload struct {
	Reason string `json:"reason,omitempty"`
}

contains session termination information

type SessionStateChatMessage

type SessionStateChatMessage struct {
	DisplayName string `json:"display_name"`
	AvatarURL   string `json:"avatar_url,omitempty"`
	Content     string `json:"content"`
	Timestamp   int64  `json:"timestamp"` // Unix milliseconds
}

represents a chat message in the chat history

type SessionStateParticipant

type SessionStateParticipant struct {
	UserID      string `json:"user_id,omitempty"`
	DisplayName string `json:"display_name"`
	Role        string `json:"role"`
}

represents a participant in session_state

type SessionStatePayload

type SessionStatePayload struct {
	Code            string                    `json:"code"`
	YourRole        string                    `json:"your_role"`
	YourDisplayName string                    `json:"your_display_name"`
	Participants    []SessionStateParticipant `json:"participants"`
	ChatHistory     []SessionStateChatMessage `json:"chat_history"`
}

contains session info sent to connecting client

type StopPayload

type StopPayload struct {
	DisplayName string `json:"display_name"`
}

contains playback stop information

type UserJoinedPayload

type UserJoinedPayload struct {
	UserID      string `json:"user_id,omitempty"`
	DisplayName string `json:"display_name"`
	Role        string `json:"role"` // "host", "co-author", "viewer"
}

contains information about a newly joined user

type UserLeftPayload

type UserLeftPayload struct {
	UserID      string `json:"user_id,omitempty"`
	DisplayName string `json:"display_name"`
}

contains information about a user who left

Jump to

Keyboard shortcuts

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