playback-device-server/server/turn_server.go

93 lines
2.3 KiB
Go

// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT
// Package main implements a simple TURN server
package server
import (
"fmt"
"net"
"os"
"os/signal"
"strconv"
"syscall"
"github.com/pion/turn/v4"
)
type TurnServer struct {
publicIp string
port int
users map[string][]byte
realm string
}
func (t *TurnServer) Start() error {
// Create a UDP listener to pass into pion/turn
// pion/turn itself doesn't allocate any UDP sockets, but lets the user pass them in
// this allows us to add logging, storage or modify inbound/outbound traffic
udpListener, err := net.ListenPacket("udp4", "0.0.0.0:"+strconv.Itoa(t.port))
if err != nil {
return fmt.Errorf("failed to create TURN server listener: %s", err)
}
server, err := turn.NewServer(turn.ServerConfig{
Realm: t.realm,
// Set AuthHandler callback
// This is called every time a user tries to authenticate with the TURN server
// Return the key for that user, or false when no user is found
AuthHandler: func(username string, realm string, srcAddr net.Addr) ([]byte, bool) { // nolint: revive
if key, ok := t.users[username]; ok {
return key, true
}
return nil, false
},
// PacketConnConfigs is a list of UDP Listeners and the configuration around them
PacketConnConfigs: []turn.PacketConnConfig{
{
PacketConn: udpListener,
RelayAddressGenerator: &turn.RelayAddressGeneratorStatic{
// Claim that we are listening on IP passed by user (This should be your Public IP)
RelayAddress: net.ParseIP(t.publicIp),
// But actually be listening on every interface
Address: "0.0.0.0",
},
},
},
})
if err != nil {
return err
}
// Block until user sends SIGINT or SIGTERM
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
<-sigs
if err = server.Close(); err != nil {
return err
}
return nil
}
func (t *TurnServer) AddUser(username string, password string) {
if t.users == nil {
t.users = make(map[string][]byte)
}
t.users[username] = turn.GenerateAuthKey(username, t.realm, password)
}
func (t *TurnServer) SetPublicIp(ip string) {
t.publicIp = ip
}
func (t *TurnServer) SetPort(port int) {
t.port = port
}
func (t *TurnServer) SetRealm(realm string) {
t.realm = realm
}