live-sfu-demo/internal/config/config.go

154 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package config
import (
"os"
"strings"
"time"
)
// Config 承载直播 SFU 分流 Demo 的运行参数。
// 优先级:环境变量 > 默认值。Cloudflare Realtime 为主 SFU,SRS 为本地对照后端。
// 默认 DB 使用 Turso 嵌入式 (libSQL file) 持久化房间拓扑;同时支持 JWT/Casbin 登录。
type Config struct {
HTTPPort string
GRPCPort string
ProviderOrder string // 逗号分隔的后端顺序,如 "cloudflare,srs"
SRSBaseURL string
SRSHttpURL string
SRSApp string
SRSSecret string
SRSCandidate string
CFAppID string
CFAppSecret string
CFBaseURL string
CFStunURL string
TokenSecret string
TokenRequired bool
JWTSecret string
JWTTTL time.Duration
AuthModel string
AuthPolicy string
AuthUserFile string
AllowRegister bool
DatabaseURL string // TURSO_DATABASE_URL 或 DATABASE_URL,默认 file:./data/live-sfu.db
AuthToken string // 兼容远程 Turso,嵌入模式可为空
}
func Load() *Config {
c := &Config{
HTTPPort: getenv("HTTP_PORT", "8088"),
GRPCPort: getenv("GRPC_PORT", "9090"),
ProviderOrder: getenv("SFU_PROVIDER", "cloudflare,srs"),
SRSBaseURL: getenv("SRS_API_BASE", "http://localhost:1985"),
SRSHttpURL: getenv("SRS_HTTP_BASE", "http://localhost:8080"),
SRSApp: getenv("SRS_APP", "live"),
SRSSecret: getenv("SRS_SECRET", ""),
SRSCandidate: getenv("SRS_CANDIDATE", "127.0.0.1"),
CFAppID: getenv("CF_APP_ID", ""),
CFAppSecret: getenv("CF_APP_SECRET", ""),
CFBaseURL: getenv("CF_BASE_URL", "https://rtc.live.cloudflare.com/v1"),
CFStunURL: getenv("CF_STUN_URL", "stun:stun.cloudflare.com:3478"),
TokenSecret: getenv("DEMO_TOKEN_SECRET", ""),
TokenRequired: getenv("SFU_TOKEN_REQUIRED", "0") == "1",
JWTSecret: getenv("JWT_SECRET", ""),
JWTTTL: parseDuration(getenv("JWT_TTL", "2h"), 2*time.Hour),
AuthModel: getenv("CASBIN_MODEL", "internal/auth/model.conf"),
AuthPolicy: getenv("CASBIN_POLICY", "internal/auth/policy.csv"),
AuthUserFile: getenv("AUTH_USER_FILE", "data/users.json"),
AllowRegister: getenv("ALLOW_REGISTER", "1") == "1",
DatabaseURL: getenv("TURSO_DATABASE_URL", "file:./data/live-sfu.db?cache=shared&_journal_mode=WAL"),
AuthToken: getenv("TURSO_AUTH_TOKEN", ""),
}
if c.TokenSecret == "" {
c.TokenSecret = "insecure-demo-secret-change-me"
}
if c.JWTSecret == "" {
c.JWTSecret = c.TokenSecret
if c.JWTSecret == "" {
c.JWTSecret = "insecure-jwt-secret-change-me"
}
}
if c.DatabaseURL == "file:./data/live-sfu.db?cache=shared&_journal_mode=WAL" {
if v := os.Getenv("DATABASE_URL"); v != "" {
c.DatabaseURL = v
} else if v := os.Getenv("LIBSQL_URL"); v != "" {
c.DatabaseURL = v
}
}
if c.AuthToken == "" {
if v := os.Getenv("TURSO_AUTH_TOKEN"); v != "" {
c.AuthToken = v
} else if v := os.Getenv("LIBSQL_AUTH_TOKEN"); v != "" {
c.AuthToken = v
}
}
return c
}
func getenv(k, def string) string {
if v := os.Getenv(k); v != "" {
return v
}
return def
}
func parseDuration(s string, def time.Duration) time.Duration {
if s == "" {
return def
}
if d, err := time.ParseDuration(s); err == nil {
return d
}
return def
}
func (c *Config) ProviderList() []string {
parts := strings.Split(c.ProviderOrder, ",")
out := make([]string, 0, len(parts))
seen := make(map[string]struct{}, len(parts))
for _, p := range parts {
p = strings.TrimSpace(strings.ToLower(p))
if p == "" || p == "both" || p == "all" {
if p == "both" || p == "all" {
for _, b := range []string{"cloudflare", "srs"} {
if _, ok := seen[b]; !ok {
seen[b] = struct{}{}
out = append(out, b)
}
}
}
continue
}
if _, ok := seen[p]; !ok {
seen[p] = struct{}{}
out = append(out, p)
}
}
return out
}
func (c *Config) DSN() string {
if c.AuthToken != "" && strings.HasPrefix(c.DatabaseURL, "libsql://") && !strings.Contains(c.DatabaseURL, "authToken") {
sep := "?"
if strings.Contains(c.DatabaseURL, "?") {
sep = "&"
}
return c.DatabaseURL + sep + "authToken=" + c.AuthToken
}
return c.DatabaseURL
}
func (c *Config) IsRemoteTurso() bool {
return strings.HasPrefix(c.DatabaseURL, "libsql://") || strings.HasPrefix(c.DatabaseURL, "https://")
}