diff --git a/cmd/olcrtc/main.go b/cmd/olcrtc/main.go index 3785c56..402a8a7 100644 --- a/cmd/olcrtc/main.go +++ b/cmd/olcrtc/main.go @@ -3,7 +3,6 @@ package main import ( "context" - "errors" "flag" "fmt" "os" @@ -12,16 +11,9 @@ import ( "syscall" "time" - "github.com/openlibrecommunity/olcrtc/internal/client" + "github.com/openlibrecommunity/olcrtc/internal/app/session" "github.com/openlibrecommunity/olcrtc/internal/logger" "github.com/openlibrecommunity/olcrtc/internal/names" - "github.com/openlibrecommunity/olcrtc/internal/provider" - "github.com/openlibrecommunity/olcrtc/internal/provider/jazz" - "github.com/openlibrecommunity/olcrtc/internal/provider/telemost" - "github.com/openlibrecommunity/olcrtc/internal/provider/wbstream" - "github.com/openlibrecommunity/olcrtc/internal/server" - "github.com/openlibrecommunity/olcrtc/internal/transport" - "github.com/openlibrecommunity/olcrtc/internal/transport/datachannel" ) type config struct { @@ -39,14 +31,6 @@ type config struct { socksProxyPort int } -var ( - errRoomIDRequired = errors.New("room ID required") - errModeRequired = errors.New("specify -mode srv or -mode cnc") - errProviderRequired = errors.New("provider required (use -provider telemost or -provider jazz)") - errUnsupportedProvider = errors.New("unsupported provider") - errUnsupportedTransport = errors.New("unsupported transport") -) - func main() { if err := run(); err != nil { logger.Error(err) @@ -55,15 +39,12 @@ func main() { } func run() error { - provider.Register("jazz", jazz.New) - provider.Register("telemost", telemost.New) - provider.Register("wb_stream", wbstream.New) - transport.Register("datachannel", datachannel.New) + session.RegisterDefaults() cfg := parseFlags() configureLogging(cfg.debug) - if err := validateConfig(cfg); err != nil { + if err := session.Validate(toSessionConfig(cfg)); err != nil { return err } @@ -83,7 +64,9 @@ func run() error { signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM) errCh := make(chan error, 1) - go runMode(ctx, cfg, errCh) + go func() { + errCh <- session.Run(ctx, toSessionConfig(cfg)) + }() select { case <-sigCh: @@ -121,41 +104,6 @@ func configureLogging(debug bool) { } } -func validateConfig(cfg config) error { - availableProviders := provider.Available() - validProvider := false - for _, p := range availableProviders { - if cfg.provider == p { - validProvider = true - break - } - } - - availableTransports := transport.Available() - validTransport := false - for _, t := range availableTransports { - if cfg.transport == t { - validTransport = true - break - } - } - - switch { - case cfg.provider == "": - return errProviderRequired - case !validProvider: - return fmt.Errorf("%w: %s (available: %v)", errUnsupportedProvider, cfg.provider, availableProviders) - case !validTransport: - return fmt.Errorf("%w: %s (available: %v)", errUnsupportedTransport, cfg.transport, availableTransports) - case cfg.roomID == "" && cfg.provider != "jazz": - return errRoomIDRequired - case cfg.mode != "srv" && cfg.mode != "cnc": - return errModeRequired - default: - return nil - } -} - func resolveDataDir(dataDir string) (string, error) { if filepath.IsAbs(dataDir) { return dataDir, nil @@ -179,49 +127,18 @@ func loadNames(dataDir string) error { return nil } -func runMode(ctx context.Context, cfg config, errCh chan<- error) { - roomURL := buildRoomURL(cfg.provider, cfg.roomID) - - switch cfg.mode { - case "srv": - errCh <- server.Run( - ctx, - cfg.transport, - cfg.provider, - roomURL, - cfg.keyHex, - cfg.dnsServer, - cfg.socksProxyAddr, - cfg.socksProxyPort, - ) - case "cnc": - errCh <- client.Run( - ctx, - cfg.transport, - cfg.provider, - roomURL, - cfg.keyHex, - fmt.Sprintf("%s:%d", cfg.socksHost, cfg.socksPort), - cfg.dnsServer, - "", - "", - ) - } -} - -func buildRoomURL(providerName, roomID string) string { - switch providerName { - case "telemost": - return "https://telemost.yandex.ru/j/" + roomID - case "jazz": - if roomID == "" { - return "any" - } - return roomID - case "wb_stream": - return roomID - default: - return roomID +func toSessionConfig(cfg config) session.Config { + return session.Config{ + Mode: cfg.mode, + Transport: cfg.transport, + Provider: cfg.provider, + RoomID: cfg.roomID, + KeyHex: cfg.keyHex, + SOCKSHost: cfg.socksHost, + SOCKSPort: cfg.socksPort, + DNSServer: cfg.dnsServer, + SOCKSProxyAddr: cfg.socksProxyAddr, + SOCKSProxyPort: cfg.socksProxyPort, } } diff --git a/internal/app/session/session.go b/internal/app/session/session.go new file mode 100644 index 0000000..f183956 --- /dev/null +++ b/internal/app/session/session.go @@ -0,0 +1,138 @@ +// Package session wires runtime configuration to application mode entrypoints. +package session + +import ( + "context" + "errors" + "fmt" + + "github.com/openlibrecommunity/olcrtc/internal/client" + "github.com/openlibrecommunity/olcrtc/internal/provider" + "github.com/openlibrecommunity/olcrtc/internal/provider/jazz" + "github.com/openlibrecommunity/olcrtc/internal/provider/telemost" + "github.com/openlibrecommunity/olcrtc/internal/provider/wbstream" + "github.com/openlibrecommunity/olcrtc/internal/server" + "github.com/openlibrecommunity/olcrtc/internal/transport" + "github.com/openlibrecommunity/olcrtc/internal/transport/datachannel" +) + +var ( + // ErrRoomIDRequired indicates that a room id is required for the selected provider. + ErrRoomIDRequired = errors.New("room ID required") + // ErrModeRequired indicates that mode is not one of the supported values. + ErrModeRequired = errors.New("specify -mode srv or -mode cnc") + // ErrProviderRequired indicates that no provider was selected. + ErrProviderRequired = errors.New("provider required (use -provider telemost or -provider jazz)") + // ErrUnsupportedProvider indicates that provider is not registered. + ErrUnsupportedProvider = errors.New("unsupported provider") + // ErrUnsupportedTransport indicates that transport is not registered. + ErrUnsupportedTransport = errors.New("unsupported transport") +) + +// Config holds runtime session settings. +type Config struct { + Mode string + Transport string + Provider string + RoomID string + KeyHex string + SOCKSHost string + SOCKSPort int + DNSServer string + SOCKSProxyAddr string + SOCKSProxyPort int +} + +// RegisterDefaults registers built-in providers and transports. +func RegisterDefaults() { + provider.Register("jazz", jazz.New) + provider.Register("telemost", telemost.New) + provider.Register("wb_stream", wbstream.New) + + transport.Register("datachannel", datachannel.New) +} + +// Validate verifies that the runtime config refers to registered components. +func Validate(cfg Config) error { + availableProviders := provider.Available() + validProvider := false + for _, p := range availableProviders { + if cfg.Provider == p { + validProvider = true + break + } + } + + availableTransports := transport.Available() + validTransport := false + for _, t := range availableTransports { + if cfg.Transport == t { + validTransport = true + break + } + } + + switch { + case cfg.Provider == "": + return ErrProviderRequired + case !validProvider: + return fmt.Errorf("%w: %s (available: %v)", ErrUnsupportedProvider, cfg.Provider, availableProviders) + case !validTransport: + return fmt.Errorf("%w: %s (available: %v)", ErrUnsupportedTransport, cfg.Transport, availableTransports) + case cfg.RoomID == "" && cfg.Provider != "jazz": + return ErrRoomIDRequired + case cfg.Mode != "srv" && cfg.Mode != "cnc": + return ErrModeRequired + default: + return nil + } +} + +// Run starts the configured mode. +func Run(ctx context.Context, cfg Config) error { + roomURL := buildRoomURL(cfg.Provider, cfg.RoomID) + + switch cfg.Mode { + case "srv": + return server.Run( + ctx, + cfg.Transport, + cfg.Provider, + roomURL, + cfg.KeyHex, + cfg.DNSServer, + cfg.SOCKSProxyAddr, + cfg.SOCKSProxyPort, + ) + case "cnc": + return client.Run( + ctx, + cfg.Transport, + cfg.Provider, + roomURL, + cfg.KeyHex, + fmt.Sprintf("%s:%d", cfg.SOCKSHost, cfg.SOCKSPort), + cfg.DNSServer, + "", + "", + ) + default: + return ErrModeRequired + } +} + +func buildRoomURL(providerName, roomID string) string { + switch providerName { + case "telemost": + return "https://telemost.yandex.ru/j/" + roomID + case "jazz": + if roomID == "" { + return "any" + } + return roomID + case "wb_stream": + return roomID + default: + return roomID + } +}