Documentation
¶
Overview ¶
Package relay wraps a pion/turn/v5 TURN server with ggscale's tenant + player identity model. Credentials are issued via the standard TURN REST API (RFC draft-uberti-rtcweb-turn-rest-00) so any client SDK can consume them; the server-side AuthHandler reconstructs the HMAC password for incoming TURN auth checks.
The username embeds a short key id so multiple shared secrets can be accepted at once: the active (first) secret signs new credentials while older secrets stay valid, giving a zero-downtime rotation window equal to the credential TTL.
Index ¶
- Variables
- func ValidateTURNURI(raw string) error
- type Credentials
- type Issuer
- type Server
- func (s *Server) ActiveAllocations() int64
- func (s *Server) ActiveWork() int64
- func (s *Server) AllocThrottled() int64
- func (s *Server) AuthFailures() int64
- func (s *Server) BeginDrain()
- func (s *Server) Close() error
- func (s *Server) EndDrain()
- func (s *Server) PeerRejected() int64
- func (s *Server) PublicIP() string
- func (s *Server) RefusedWork() int64
- func (s *Server) RejectedAllocations() int64
- func (s *Server) Transports() []string
- type ServerConfig
Constants ¶
This section is empty.
Variables ¶
var ErrCredentialsExpired = errors.New("relay: credentials expired")
ErrCredentialsExpired is returned by Verify when the encoded expiry has already elapsed.
var ErrCredentialsInvalid = errors.New("relay: credentials invalid")
ErrCredentialsInvalid is returned by Verify on any other failure (unparseable username, unknown key id, HMAC mismatch).
Functions ¶
func ValidateTURNURI ¶
ValidateTURNURI accepts the turn:/turns: URI forms clients dial. TURN URIs are opaque (turn:host:port?transport=udp), so the host lands in Opaque rather than Host after url.Parse.
Types ¶
type Credentials ¶
type Credentials struct {
Username string `json:"username" example:"1767225600:3:42:k1"`
Password string `json:"password" example:"dGVzdC1obWFjLXNhbXBsZS12YWx1ZQ=="`
TTLSeconds int64 `json:"ttl" example:"600"`
Realm string `json:"realm" example:"ggscale"`
URLs []string `json:"urls,omitempty" example:"turn:relay.example.com:3478?transport=udp"`
Region string `json:"region" example:"us-east"`
STUNURLs []string `json:"stun_urls,omitempty" example:"stun:stun.example.com:3478"`
}
Credentials are the values returned to a client. URLs are the TURN URIs of the relay nodes the client should dial, and Region is the region they were chosen from, or "" when they span regions. The API server fills both from the relay node registry; Issue leaves them empty.
type Issuer ¶
type Issuer struct {
// contains filtered or unexported fields
}
Issuer mints and verifies short-lived TURN-REST credentials. One Issuer per process; safe for concurrent use once constructed.
func NewIssuer ¶
NewIssuer returns an Issuer with a single shared secret and realm. ttl is the validity window encoded into each issued username; the server-side AuthHandler rejects requests after this elapses.
func NewIssuerWithSecrets ¶
NewIssuerWithSecrets returns an Issuer whose first secret signs new credentials and every non-empty secret is accepted for verification. This backs zero-downtime rotation: configure old + new together, promote the new secret to first, then drop the old one after a credential-TTL overlap.
func (*Issuer) Issue ¶
func (i *Issuer) Issue(tenantID, playerID int64) (*Credentials, error)
Issue returns a fresh credential pair scoped to (tenantID, playerID), signed by the active secret and tagged with its key id.
func (*Issuer) SetSTUNURLs ¶
SetSTUNURLs sets the discovery-only STUN URIs returned alongside TURN credentials so WebRTC clients can gather direct server-reflexive candidates.
func (*Issuer) Verify ¶
Verify checks the username + password pair against every accepted secret, returning the embedded (tenantID, playerID) on success. The in-process TURN server authenticates via authForUsername (pion recomputes and compares the HMAC key itself); Verify is the standalone entrypoint for verifying a credential pair out of band — e.g. an external relay or a conformance test.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server wraps pion/turn/v5. One Server per process. It owns every listener it opens (UDP packet conns + TCP/TLS listeners); Close releases them all.
func NewServer ¶
func NewServer(cfg ServerConfig) (*Server, error)
NewServer binds the configured listeners and starts the underlying pion server. The returned Server owns the listeners; callers must invoke Close to release the ports.
func (*Server) ActiveAllocations ¶
ActiveAllocations reports the number of currently-live relay allocations.
func (*Server) ActiveWork ¶
ActiveWork reports the work a drain waits on: every Allocate admitted through the drain gate, from admission until its relayed socket closes.
func (*Server) AllocThrottled ¶
AllocThrottled reports the cumulative count of authenticated allocations refused by the per-player rate limit.
func (*Server) AuthFailures ¶
AuthFailures reports the cumulative count of rejected TURN auth attempts.
func (*Server) BeginDrain ¶
func (s *Server) BeginDrain()
BeginDrain refuses new TURN Allocate requests. Existing allocations keep refreshing, binding permissions, and relaying data.
func (*Server) EndDrain ¶
func (s *Server) EndDrain()
EndDrain accepts new TURN Allocate requests again.
func (*Server) PeerRejected ¶
PeerRejected reports the cumulative count of CreatePermission/ChannelBind attempts refused because the peer address was private and private peers are disallowed.
func (*Server) RefusedWork ¶
RefusedWork reports the cumulative count of Allocate requests refused while draining.
func (*Server) RejectedAllocations ¶
RejectedAllocations reports the cumulative count of allocations refused because the node allocation cap was reached.
func (*Server) Transports ¶
Transports lists the client transports this relay listens on: "udp", then "tcp" and "tls" when enabled.
type ServerConfig ¶
type ServerConfig struct {
PublicIP string
BindAddr string // host portion of the bind address; empty -> 0.0.0.0
BindPort int // UDP port
TCPPort int // TURN-over-TCP port; 0 disables
TLSPort int // TURNS (TLS) port; 0 disables
TLSCertFile string // required when TLSPort != 0
TLSKeyFile string // required when TLSPort != 0
// RelayMinPort/RelayMaxPort bound the UDP ports allocated for relayed
// media. Both 0 (the default) allocates from the OS ephemeral range;
// setting a range lets the firewall open only those ports. The range width
// caps the number of concurrent relay allocations.
RelayMinPort int
RelayMaxPort int
// MaxAllocations caps concurrently-live relay allocations node-wide,
// bounding port-range exhaustion from a single credential. 0 = unlimited.
MaxAllocations int
// PlayerAllocPerMinute/PlayerAllocBurst throttle authenticated allocations
// per player so one credential can't monopolise the global pool. <=0 disables.
PlayerAllocPerMinute int
PlayerAllocBurst int
// AllowPrivatePeers lets clients relay to loopback/RFC1918/link-local/ULA
// peer addresses. Default false: the relay refuses to proxy into private
// space, so a valid credential can't turn the node into an SSRF hop to
// internal services. Set true only for a self-host relay that legitimately
// bridges private peers on a trusted network.
AllowPrivatePeers bool
// Logger receives the pion server's internal events; nil uses slog.Default.
Logger *slog.Logger
Issuer *Issuer
}
ServerConfig wires NewServer. PublicIP is the address peers connect to; BindPort is the local UDP port the listener binds (default 3478). TCPPort and TLSPort are optional TURN/TCP and TURNS/TLS transports (0 = off) so clients behind UDP-blocking firewalls can still reach the relay.