mirror of
https://github.com/openlibrecommunity/olcrtc.git
synced 2026-05-26 23:19:47 +00:00
127 lines
4.3 KiB
Go
127 lines
4.3 KiB
Go
// Package engine defines the wire-level transport engine that connects to a
|
|
// remote SFU. An engine is independent of how the room credentials were
|
|
// obtained: it accepts a signaling URL and an access token, and exposes the
|
|
// byte/video primitives the rest of olcrtc consumes.
|
|
//
|
|
// Engines model the SFU protocol family (e.g. LiveKit, Goolom). Service-
|
|
// specific bits (e.g. WB / Telemost API flows) live in the auth
|
|
// package, not here.
|
|
package engine
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"github.com/pion/webrtc/v4"
|
|
)
|
|
|
|
var (
|
|
// ErrEngineNotFound is returned when a requested engine is not registered.
|
|
ErrEngineNotFound = errors.New("engine not found")
|
|
// ErrByteStreamUnsupported is returned when an engine cannot expose a byte stream.
|
|
ErrByteStreamUnsupported = errors.New("engine does not support byte stream")
|
|
// ErrVideoTrackUnsupported is returned when an engine cannot exchange video tracks.
|
|
ErrVideoTrackUnsupported = errors.New("engine does not support video tracks")
|
|
)
|
|
|
|
// Capabilities describes the transport primitives an engine can expose.
|
|
type Capabilities struct {
|
|
ByteStream bool
|
|
VideoTrack bool
|
|
}
|
|
|
|
// Credentials are produced by an auth provider - duplicated here to avoid an
|
|
// import cycle between engine and auth.
|
|
type Credentials struct {
|
|
URL string
|
|
Token string
|
|
Extra map[string]string
|
|
}
|
|
|
|
// Config is the runtime input to an engine factory. URL/Token are produced by
|
|
// an auth provider (or supplied directly by the caller for "none" auth).
|
|
// Extra carries engine-specific fields that don't fit the common shape
|
|
// (e.g. providers that need metadata beyond URL/token can pass it here).
|
|
//
|
|
// Refresh, when set, is called by an engine whose protocol requires fresh
|
|
// credentials on each reconnect (e.g. Goolom: every reconnect needs a new
|
|
// peerID/credentials tuple from the room-info HTTP endpoint). Engines that
|
|
// don't need this should ignore it.
|
|
type Config struct {
|
|
URL string
|
|
Token string
|
|
Name string
|
|
Extra map[string]string
|
|
OnData func([]byte)
|
|
OnPeerData func(peerID string, data []byte)
|
|
DNSServer string
|
|
ProxyAddr string
|
|
ProxyPort int
|
|
Refresh func(ctx context.Context) (Credentials, error)
|
|
}
|
|
|
|
// Session is the engine-level runtime handle. It is shaped to match what
|
|
// the upper transport layer expects: send/receive bytes, optional video
|
|
// tracks, and lifecycle callbacks.
|
|
//
|
|
//nolint:interfacebloat // mirrors the historical provider.Provider surface that the rest of olcrtc consumes
|
|
type Session interface {
|
|
Connect(ctx context.Context) error
|
|
Send(data []byte) error
|
|
Close() error
|
|
SetReconnectCallback(cb func(*webrtc.DataChannel))
|
|
SetShouldReconnect(fn func() bool)
|
|
SetEndedCallback(cb func(string))
|
|
WatchConnection(ctx context.Context)
|
|
CanSend() bool
|
|
GetSendQueue() chan []byte
|
|
GetBufferedAmount() uint64
|
|
Capabilities() Capabilities
|
|
// Reconnect asks the engine to tear down and re-establish the underlying
|
|
// SFU connection. Used by upper layers when a liveness probe declares the
|
|
// carrier dead before the engine has noticed (e.g. silent packet loss on
|
|
// a video track). Implementations should be best-effort and idempotent;
|
|
// reason is logged for diagnostics.
|
|
Reconnect(reason string)
|
|
}
|
|
|
|
// PeerSession is implemented by engines that can address byte payloads to a
|
|
// specific remote endpoint and report the sender endpoint on receive.
|
|
type PeerSession interface {
|
|
SendTo(peerID string, data []byte) error
|
|
}
|
|
|
|
// VideoTrackCapable is implemented by engines that can exchange video tracks.
|
|
type VideoTrackCapable interface {
|
|
AddVideoTrack(track webrtc.TrackLocal) error
|
|
SetVideoTrackHandler(cb func(*webrtc.TrackRemote, *webrtc.RTPReceiver))
|
|
}
|
|
|
|
// Factory creates a new engine session.
|
|
type Factory func(ctx context.Context, cfg Config) (Session, error)
|
|
|
|
var registry = make(map[string]Factory) //nolint:gochecknoglobals // package-level state intentional
|
|
|
|
// Register adds an engine factory to the registry.
|
|
func Register(name string, factory Factory) {
|
|
registry[name] = factory
|
|
}
|
|
|
|
// New creates an engine session by name.
|
|
func New(ctx context.Context, name string, cfg Config) (Session, error) {
|
|
factory, ok := registry[name]
|
|
if !ok {
|
|
return nil, ErrEngineNotFound
|
|
}
|
|
return factory(ctx, cfg)
|
|
}
|
|
|
|
// Available returns the list of registered engine names.
|
|
func Available() []string {
|
|
names := make([]string, 0, len(registry))
|
|
for name := range registry {
|
|
names = append(names, name)
|
|
}
|
|
return names
|
|
}
|