// Package builtin wires the built-in auth providers to their engines and // registers a name-keyed factory that transports use to obtain an // [engine.Session]. The factory replaces the former carrier layer: when // the auth provider is "none" the caller supplies engine/URL/token // directly; otherwise the named provider issues credentials and the // matching engine is constructed. package builtin import ( "context" "errors" "fmt" "github.com/openlibrecommunity/olcrtc/internal/auth" authJitsi "github.com/openlibrecommunity/olcrtc/internal/auth/jitsi" authTelemost "github.com/openlibrecommunity/olcrtc/internal/auth/telemost" authWBStream "github.com/openlibrecommunity/olcrtc/internal/auth/wbstream" "github.com/openlibrecommunity/olcrtc/internal/engine" _ "github.com/openlibrecommunity/olcrtc/internal/engine/goolom" // register goolom engine via init _ "github.com/openlibrecommunity/olcrtc/internal/engine/jitsi" // register jitsi engine via init _ "github.com/openlibrecommunity/olcrtc/internal/engine/livekit" // register livekit engine via init ) // ErrCarrierNotFound is returned when an unregistered carrier name is requested. var ErrCarrierNotFound = errors.New("carrier not found") // ErrAuthFailed wraps an auth provider rejection. It pairs with the inner // provider error returned from [Open]. var ErrAuthFailed = errors.New("carrier auth failed") // Config holds the inputs to [Open]. The fields mirror the subset of // transport.Config that engines consume. type Config struct { RoomURL string Name string OnData func([]byte) OnPeerData func(peerID string, data []byte) DNSServer string ProxyAddr string ProxyPort int // Engine, URL, Token are honoured only for the "none" carrier (direct // engine access); other carriers derive them from their auth provider. Engine string URL string Token string } // Factory creates an engine session for a given carrier. type Factory func(ctx context.Context, cfg Config) (engine.Session, error) var registry = map[string]Factory{} //nolint:gochecknoglobals // package-level registry // Register adds a carrier factory. func Register(name string, f Factory) { registry[name] = f } // Open looks up the carrier factory and creates an engine session. func Open(ctx context.Context, name string, cfg Config) (engine.Session, error) { f, ok := registry[name] if !ok { return nil, fmt.Errorf("%w: %q", ErrCarrierNotFound, name) } return f(ctx, cfg) } // Available reports all registered carrier names. func Available() []string { names := make([]string, 0, len(registry)) for name := range registry { names = append(names, name) } return names } // RegisterDefaults wires the built-in carriers: jitsi, telemost, wbstream // and "none" (direct engine access). func RegisterDefaults() { registerEngineAuth("wbstream", authWBStream.Provider{}) registerEngineAuth("telemost", authTelemost.Provider{}) registerEngineAuth("jitsi", authJitsi.Provider{}) registerDirect("none") } // registerDirect registers a carrier that skips auth: the caller supplies // engine/URL/token directly via [Config]. func registerDirect(name string) { Register(name, func(ctx context.Context, cfg Config) (engine.Session, error) { engineName := cfg.Engine if engineName == "" { engineName = "livekit" } sess, err := engine.New(ctx, engineName, engine.Config{ URL: cfg.URL, Token: cfg.Token, Name: cfg.Name, OnData: cfg.OnData, OnPeerData: cfg.OnPeerData, DNSServer: cfg.DNSServer, ProxyAddr: cfg.ProxyAddr, ProxyPort: cfg.ProxyPort, }) if err != nil { return nil, fmt.Errorf("engine new: %w", err) } return sess, nil }) } // registerEngineAuth registers a carrier that resolves credentials through an // auth provider and connects via the engine the auth provider reports. func registerEngineAuth(name string, provider auth.Provider) { Register(name, func(ctx context.Context, cfg Config) (engine.Session, error) { authCfg := auth.Config{ RoomURL: cfg.RoomURL, Name: cfg.Name, DNSServer: cfg.DNSServer, ProxyAddr: cfg.ProxyAddr, ProxyPort: cfg.ProxyPort, } creds, err := provider.Issue(ctx, authCfg) if err != nil { return nil, fmt.Errorf("%w: %w", ErrAuthFailed, err) } sess, err := engine.New(ctx, provider.Engine(), engine.Config{ URL: creds.URL, Token: creds.Token, Name: cfg.Name, Extra: creds.Extra, OnData: cfg.OnData, OnPeerData: cfg.OnPeerData, DNSServer: cfg.DNSServer, ProxyAddr: cfg.ProxyAddr, ProxyPort: cfg.ProxyPort, Refresh: func(ctx context.Context) (engine.Credentials, error) { fresh, err := provider.Issue(ctx, authCfg) if err != nil { return engine.Credentials{}, fmt.Errorf("auth refresh: %w", err) } return engine.Credentials{URL: fresh.URL, Token: fresh.Token, Extra: fresh.Extra}, nil }, }) if err != nil { return nil, fmt.Errorf("engine new: %w", err) } return sess, nil }) }