mirror of
https://github.com/openlibrecommunity/olcrtc.git
synced 2026-05-26 15:13:40 +00:00
refactor: introduce engine and auth interfaces
Lay the groundwork for splitting service-specific logic (WB / Jazz / Telemost API flows) from wire-level transport engines (LiveKit, Goolom, future Jitsi). An engine takes only URL+Token+Name+network knobs; an auth provider produces those credentials and reports which engine it feeds. RoomCreator is an optional capability for the gen mode. Existing carriers and providers are untouched. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
93
internal/auth/auth.go
Normal file
93
internal/auth/auth.go
Normal file
@@ -0,0 +1,93 @@
|
||||
// Package auth defines how room credentials are produced for an engine.
|
||||
//
|
||||
// An auth provider is responsible for any service-specific HTTP / login flow
|
||||
// (WB Stream, SaluteJazz, Yandex Telemost, Jitsi, ...) and produces a
|
||||
// Credentials value that an engine can use to connect. Some auth providers
|
||||
// also support creating new rooms; that capability is optional and is
|
||||
// expressed via the RoomCreator interface.
|
||||
//
|
||||
// The "none" auth provider passes a caller-supplied URL+Token through
|
||||
// unchanged — this is the path that sing-box and other downstream consumers
|
||||
// take when they want to use olcrtc as a generic LiveKit/Goolom/Jitsi
|
||||
// transport without any service-specific behaviour baked in.
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrAuthNotFound is returned when a requested auth provider is not registered.
|
||||
ErrAuthNotFound = errors.New("auth provider not found")
|
||||
// ErrRoomCreationUnsupported is returned when an auth provider cannot create rooms.
|
||||
ErrRoomCreationUnsupported = errors.New("auth provider does not support room creation")
|
||||
// ErrRoomIDRequired is returned when an auth flow needs an existing room ID and none was supplied.
|
||||
ErrRoomIDRequired = errors.New("room ID required")
|
||||
)
|
||||
|
||||
// Credentials carry everything an engine needs to connect to an SFU.
|
||||
//
|
||||
// URL is the signaling endpoint (e.g. wss://livekit.example/). Token is the
|
||||
// access token (LiveKit JWT, Goolom session credential, etc). Extra is for
|
||||
// engine-specific bits that don't fit the common shape — engines should not
|
||||
// rely on it being populated unless their paired auth provider documents it.
|
||||
type Credentials struct {
|
||||
URL string
|
||||
Token string
|
||||
Extra map[string]string
|
||||
}
|
||||
|
||||
// Config is the input to an auth provider.
|
||||
type Config struct {
|
||||
// RoomURL is the user-facing room link (e.g. https://telemost.yandex.ru/j/123).
|
||||
// Optional for providers that can also create rooms on demand.
|
||||
RoomURL string
|
||||
// Name is the display name to register with.
|
||||
Name string
|
||||
// DNSServer / ProxyAddr / ProxyPort are network knobs for outbound HTTP.
|
||||
DNSServer string
|
||||
ProxyAddr string
|
||||
ProxyPort int
|
||||
}
|
||||
|
||||
// Provider produces engine credentials.
|
||||
type Provider interface {
|
||||
// Engine reports which engine this auth provider feeds. This is what lets
|
||||
// a carrier resolve (auth, engine) pairs consistently — e.g. auth=jazz
|
||||
// always pairs with engine=livekit.
|
||||
Engine() string
|
||||
// Issue obtains credentials for the given room.
|
||||
Issue(ctx context.Context, cfg Config) (Credentials, error)
|
||||
}
|
||||
|
||||
// RoomCreator is implemented by auth providers that can create new rooms
|
||||
// against their backing service. Used by `olcrtc -mode gen`.
|
||||
type RoomCreator interface {
|
||||
CreateRoom(ctx context.Context, cfg Config) (roomID string, err error)
|
||||
}
|
||||
|
||||
var registry = make(map[string]Provider) //nolint:gochecknoglobals // package-level state intentional
|
||||
|
||||
// Register adds an auth provider to the registry.
|
||||
func Register(name string, p Provider) {
|
||||
registry[name] = p
|
||||
}
|
||||
|
||||
// Get returns a registered auth provider by name.
|
||||
func Get(name string) (Provider, error) {
|
||||
p, ok := registry[name]
|
||||
if !ok {
|
||||
return nil, ErrAuthNotFound
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// Available returns the list of registered auth provider names.
|
||||
func Available() []string {
|
||||
names := make([]string, 0, len(registry))
|
||||
for name := range registry {
|
||||
names = append(names, name)
|
||||
}
|
||||
return names
|
||||
}
|
||||
96
internal/engine/engine.go
Normal file
96
internal/engine/engine.go
Normal file
@@ -0,0 +1,96 @@
|
||||
// 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 / Jazz / 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
|
||||
}
|
||||
|
||||
// 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).
|
||||
type Config struct {
|
||||
URL string
|
||||
Token string
|
||||
Name string
|
||||
OnData func([]byte)
|
||||
DNSServer string
|
||||
ProxyAddr string
|
||||
ProxyPort int
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
Reference in New Issue
Block a user