Embedded TURN server

This commit is contained in:
David Zhao
2021-03-06 22:47:48 -08:00
parent 2008a2e1e1
commit fa2ffa46e7
14 changed files with 316 additions and 67 deletions
+16 -2
View File
@@ -13,6 +13,7 @@ type Config struct {
RTC RTCConfig `yaml:"rtc"`
Redis RedisConfig `yaml:"redis"`
Audio AudioConfig `yaml:"audio"`
TURN TURNConfig `yaml:"turn"`
KeyFile string `yaml:"key_file"`
Keys map[string]string `yaml:"keys"`
LogLevel string `yaml:"log_level"`
@@ -49,6 +50,13 @@ type RedisConfig struct {
Password string `yaml:"password"`
}
type TURNConfig struct {
Enabled bool `yaml:"enabled"`
ListenPort int `yaml:"listen_port"`
PortRangeStart uint16 `yaml:"port_range_start"`
PortRangeEnd uint16 `yaml:"port_range_end"`
}
func NewConfig(confString string) (*Config, error) {
// start with defaults
conf := &Config{
@@ -56,7 +64,7 @@ func NewConfig(confString string) (*Config, error) {
RTC: RTCConfig{
UseExternalIP: true,
ICEPortRangeStart: 9000,
ICEPortRangeEnd: 9200,
ICEPortRangeEnd: 11000,
StunServers: []string{
"stun.l.google.com:19302",
"stun1.l.google.com:19302",
@@ -69,7 +77,13 @@ func NewConfig(confString string) (*Config, error) {
UpdateInterval: 500,
},
Redis: RedisConfig{},
Keys: map[string]string{},
TURN: TURNConfig{
Enabled: false,
ListenPort: 3478,
PortRangeStart: 12000,
PortRangeEnd: 16000,
},
Keys: map[string]string{},
}
if confString != "" {
yaml.Unmarshal([]byte(confString), conf)
+1
View File
@@ -61,6 +61,7 @@ func (r *RoomManager) CreateRoom(req *livekit.CreateRoomRequest) (*livekit.Room,
Sid: utils.NewGuid(utils.RoomPrefix),
Name: req.Name,
CreationTime: time.Now().Unix(),
TurnPassword: utils.RandomSecret(),
}
} else if err != nil {
return nil, err
+9
View File
@@ -8,6 +8,7 @@ import (
"net/http"
"time"
"github.com/pion/turn/v2"
"github.com/urfave/negroni"
"github.com/livekit/livekit-server/pkg/auth"
@@ -26,6 +27,7 @@ type LivekitServer struct {
httpServer *http.Server
router routing.Router
roomManager *RoomManager
turnServer *turn.Server
currentNode routing.LocalNode
running utils.AtomicFlag
doneChan chan bool
@@ -37,6 +39,7 @@ func NewLivekitServer(conf *config.Config,
keyProvider auth.KeyProvider,
router routing.Router,
roomManager *RoomManager,
turnServer *turn.Server,
currentNode routing.LocalNode,
) (s *LivekitServer, err error) {
s = &LivekitServer{
@@ -45,6 +48,8 @@ func NewLivekitServer(conf *config.Config,
rtcService: rtcService,
router: router,
roomManager: roomManager,
// turn server starts automatically
turnServer: turnServer,
currentNode: currentNode,
}
@@ -132,6 +137,10 @@ func (s *LivekitServer) Start() error {
ctx, _ := context.WithTimeout(context.Background(), time.Second*5)
s.httpServer.Shutdown(ctx)
if s.turnServer != nil {
s.turnServer.Close()
}
return nil
}
+81
View File
@@ -0,0 +1,81 @@
package service
import (
"fmt"
"net"
"strconv"
"github.com/pion/turn/v2"
"github.com/pkg/errors"
"github.com/livekit/livekit-server/pkg/config"
"github.com/livekit/livekit-server/pkg/logger"
"github.com/livekit/livekit-server/pkg/routing"
)
const (
allocateRetries = 1000
livekitRealm = "livekit"
)
func NewTurnServer(conf *config.Config, roomStore RoomStore, node routing.LocalNode) (*turn.Server, error) {
turnConf := conf.TURN
if !turnConf.Enabled {
return nil, nil
}
serverConfig := turn.ServerConfig{
Realm: livekitRealm,
AuthHandler: newTurnAuthHandler(roomStore),
}
tcpListener, err := net.Listen("tcp4", "0.0.0.0:"+strconv.Itoa(turnConf.ListenPort))
if err != nil {
return nil, errors.Wrap(err, "could not listen on TURN TCP port")
}
serverConfig.ListenerConfigs = []turn.ListenerConfig{
{
Listener: tcpListener,
RelayAddressGenerator: &turn.RelayAddressGeneratorPortRange{
RelayAddress: net.ParseIP(node.Ip),
Address: "0.0.0.0",
MinPort: turnConf.PortRangeStart,
MaxPort: turnConf.PortRangeEnd,
MaxRetries: allocateRetries,
},
},
}
udpListener, err := net.ListenPacket("udp4", "0.0.0.0:"+strconv.Itoa(turnConf.ListenPort))
if err != nil {
return nil, errors.Wrap(err, "could not listen on TURN UDP port")
}
serverConfig.PacketConnConfigs = []turn.PacketConnConfig{
{
PacketConn: udpListener,
RelayAddressGenerator: &turn.RelayAddressGeneratorPortRange{
RelayAddress: net.ParseIP(node.Ip), // Claim that we are listening on IP passed by user (This should be your Public IP)
Address: "0.0.0.0", // But actually be listening on every interface
MinPort: turnConf.PortRangeStart,
MaxPort: turnConf.PortRangeEnd,
MaxRetries: allocateRetries,
},
},
}
logger.Infow("Starting TURN server",
"port", turnConf.ListenPort,
"portRange", fmt.Sprintf("%d-%d", turnConf.PortRangeStart, turnConf.PortRangeEnd))
return turn.NewServer(serverConfig)
}
func newTurnAuthHandler(roomStore RoomStore) turn.AuthHandler {
return func(username, realm string, srcAddr net.Addr) (key []byte, ok bool) {
// room id should be the username, create a hashed room id
rm, err := roomStore.GetRoom(username)
if err != nil {
return nil, false
}
return turn.GenerateAuthKey(username, livekitRealm, rm.TurnPassword), true
}
}
+1
View File
@@ -16,6 +16,7 @@ var ServiceSet = wire.NewSet(
NewRTCService,
NewLivekitServer,
NewRoomManager,
NewTurnServer,
config.GetAudioConfig,
wire.Bind(new(livekit.RoomService), new(*RoomService)),
)
+5 -1
View File
@@ -23,7 +23,11 @@ func InitializeServer(conf *config.Config, keyProvider auth.KeyProvider, roomSto
return nil, err
}
rtcService := NewRTCService(conf, roomStore, roomManager, router, currentNode)
livekitServer, err := NewLivekitServer(conf, roomService, rtcService, keyProvider, router, roomManager, currentNode)
server, err := NewTurnServer(conf, roomStore, currentNode)
if err != nil {
return nil, err
}
livekitServer, err := NewLivekitServer(conf, roomService, rtcService, keyProvider, router, roomManager, server, currentNode)
if err != nil {
return nil, err
}