orama/pkg/gateway/sfu/signaling.go
2026-02-20 18:24:32 +02:00

146 lines
4.6 KiB
Go

package sfu
import (
"encoding/json"
"github.com/pion/webrtc/v4"
)
// MessageType represents the type of signaling message
type MessageType string
const (
// Client -> Server message types
MessageTypeJoin MessageType = "join"
MessageTypeLeave MessageType = "leave"
MessageTypeOffer MessageType = "offer"
MessageTypeAnswer MessageType = "answer"
MessageTypeICECandidate MessageType = "ice-candidate"
MessageTypeMute MessageType = "mute"
MessageTypeUnmute MessageType = "unmute"
MessageTypeStartVideo MessageType = "start-video"
MessageTypeStopVideo MessageType = "stop-video"
// Server -> Client message types
MessageTypeWelcome MessageType = "welcome"
MessageTypeParticipantJoined MessageType = "participant-joined"
MessageTypeParticipantLeft MessageType = "participant-left"
MessageTypeTrackAdded MessageType = "track-added"
MessageTypeTrackRemoved MessageType = "track-removed"
MessageTypeError MessageType = "error"
)
// ClientMessage represents a message from client to server
type ClientMessage struct {
Type MessageType `json:"type"`
Data json.RawMessage `json:"data,omitempty"`
}
// ServerMessage represents a message from server to client
type ServerMessage struct {
Type MessageType `json:"type"`
Data interface{} `json:"data,omitempty"`
}
// JoinData is the payload for join messages
type JoinData struct {
DisplayName string `json:"displayName"`
AudioOnly bool `json:"audioOnly,omitempty"`
}
// OfferData is the payload for offer messages
type OfferData struct {
SDP string `json:"sdp"`
}
// AnswerData is the payload for answer messages
type AnswerData struct {
SDP string `json:"sdp"`
}
// ICECandidateData is the payload for ICE candidate messages
type ICECandidateData struct {
Candidate string `json:"candidate"`
SDPMid string `json:"sdpMid,omitempty"`
SDPMLineIndex uint16 `json:"sdpMLineIndex,omitempty"`
UsernameFragment string `json:"usernameFragment,omitempty"`
}
// ToWebRTCCandidate converts ICECandidateData to webrtc.ICECandidateInit
func (c *ICECandidateData) ToWebRTCCandidate() webrtc.ICECandidateInit {
return webrtc.ICECandidateInit{
Candidate: c.Candidate,
SDPMid: &c.SDPMid,
SDPMLineIndex: &c.SDPMLineIndex,
UsernameFragment: &c.UsernameFragment,
}
}
// WelcomeData is sent to a client when they successfully join
type WelcomeData struct {
ParticipantID string `json:"participantId"`
RoomID string `json:"roomId"`
Participants []ParticipantInfo `json:"participants"`
}
// ParticipantInfo contains public information about a participant
type ParticipantInfo struct {
ID string `json:"id"`
UserID string `json:"userId"`
DisplayName string `json:"displayName"`
HasAudio bool `json:"hasAudio"`
HasVideo bool `json:"hasVideo"`
AudioMuted bool `json:"audioMuted"`
VideoMuted bool `json:"videoMuted"`
}
// ParticipantJoinedData is sent when a new participant joins
type ParticipantJoinedData struct {
Participant ParticipantInfo `json:"participant"`
}
// ParticipantLeftData is sent when a participant leaves
type ParticipantLeftData struct {
ParticipantID string `json:"participantId"`
}
// TrackAddedData is sent when a new track is available
type TrackAddedData struct {
ParticipantID string `json:"participantId"` // Internal SFU peer ID
UserID string `json:"userId"` // The user's actual ID for easier mapping
TrackID string `json:"trackId"` // Format: "{kind}-{participantId}"
StreamID string `json:"streamId"` // Same as userId (for WebRTC stream matching)
Kind string `json:"kind"` // "audio" or "video"
}
// TrackRemovedData is sent when a track is removed
type TrackRemovedData struct {
ParticipantID string `json:"participantId"`
UserID string `json:"userId"` // The user's actual ID for easier mapping
TrackID string `json:"trackId"`
StreamID string `json:"streamId"`
Kind string `json:"kind"`
}
// ErrorData is sent when an error occurs
type ErrorData struct {
Code string `json:"code"`
Message string `json:"message"`
}
// NewServerMessage creates a new server message
func NewServerMessage(msgType MessageType, data interface{}) *ServerMessage {
return &ServerMessage{
Type: msgType,
Data: data,
}
}
// NewErrorMessage creates a new error message
func NewErrorMessage(code, message string) *ServerMessage {
return NewServerMessage(MessageTypeError, &ErrorData{
Code: code,
Message: message,
})
}