mirror of
https://github.com/DeBrosOfficial/orama.git
synced 2026-03-17 16:06:58 +00:00
- Add signaling package with message types and structures for SFU communication. - Implement client and server message serialization/deserialization tests. - Enhance systemd manager to handle SFU and TURN services, including start/stop logic. - Create TURN server configuration and main server logic with HMAC-SHA1 authentication. - Add tests for TURN server credential generation and validation. - Define systemd service files for SFU and TURN services.
81 lines
2.5 KiB
Go
81 lines
2.5 KiB
Go
package sfu
|
|
|
|
import "fmt"
|
|
|
|
// Config holds configuration for the SFU server
|
|
type Config struct {
|
|
// ListenAddr is the address to bind the signaling WebSocket server.
|
|
// Must be a WireGuard IP (10.0.0.x) — never 0.0.0.0.
|
|
ListenAddr string `yaml:"listen_addr"`
|
|
|
|
// Namespace this SFU instance belongs to
|
|
Namespace string `yaml:"namespace"`
|
|
|
|
// MediaPortRange defines the UDP port range for RTP media
|
|
MediaPortStart int `yaml:"media_port_start"`
|
|
MediaPortEnd int `yaml:"media_port_end"`
|
|
|
|
// TURN servers this SFU should advertise to peers
|
|
TURNServers []TURNServerConfig `yaml:"turn_servers"`
|
|
|
|
// TURNSecret is the shared HMAC-SHA1 secret for generating TURN credentials
|
|
TURNSecret string `yaml:"turn_secret"`
|
|
|
|
// TURNCredentialTTL is the lifetime of TURN credentials in seconds
|
|
TURNCredentialTTL int `yaml:"turn_credential_ttl"`
|
|
|
|
// RQLiteDSN is the namespace-local RQLite DSN for room state
|
|
RQLiteDSN string `yaml:"rqlite_dsn"`
|
|
}
|
|
|
|
// TURNServerConfig represents a single TURN server endpoint
|
|
type TURNServerConfig struct {
|
|
Host string `yaml:"host"` // IP or hostname
|
|
Port int `yaml:"port"` // UDP port (3478 or 443)
|
|
}
|
|
|
|
// Validate checks the SFU configuration for errors
|
|
func (c *Config) Validate() []error {
|
|
var errs []error
|
|
|
|
if c.ListenAddr == "" {
|
|
errs = append(errs, fmt.Errorf("sfu.listen_addr: must not be empty"))
|
|
}
|
|
|
|
if c.Namespace == "" {
|
|
errs = append(errs, fmt.Errorf("sfu.namespace: must not be empty"))
|
|
}
|
|
|
|
if c.MediaPortStart <= 0 || c.MediaPortEnd <= 0 {
|
|
errs = append(errs, fmt.Errorf("sfu.media_port_range: start and end must be positive"))
|
|
} else if c.MediaPortEnd <= c.MediaPortStart {
|
|
errs = append(errs, fmt.Errorf("sfu.media_port_range: end (%d) must be greater than start (%d)", c.MediaPortEnd, c.MediaPortStart))
|
|
}
|
|
|
|
if len(c.TURNServers) == 0 {
|
|
errs = append(errs, fmt.Errorf("sfu.turn_servers: at least one TURN server must be configured"))
|
|
}
|
|
for i, ts := range c.TURNServers {
|
|
if ts.Host == "" {
|
|
errs = append(errs, fmt.Errorf("sfu.turn_servers[%d].host: must not be empty", i))
|
|
}
|
|
if ts.Port <= 0 || ts.Port > 65535 {
|
|
errs = append(errs, fmt.Errorf("sfu.turn_servers[%d].port: must be between 1 and 65535", i))
|
|
}
|
|
}
|
|
|
|
if c.TURNSecret == "" {
|
|
errs = append(errs, fmt.Errorf("sfu.turn_secret: must not be empty"))
|
|
}
|
|
|
|
if c.TURNCredentialTTL <= 0 {
|
|
errs = append(errs, fmt.Errorf("sfu.turn_credential_ttl: must be positive"))
|
|
}
|
|
|
|
if c.RQLiteDSN == "" {
|
|
errs = append(errs, fmt.Errorf("sfu.rqlite_dsn: must not be empty"))
|
|
}
|
|
|
|
return errs
|
|
}
|