feat: support UDP in TURN (#61)

1. Add UDP option to TURN
2. GetLocalIPAddress default to IPv4
This commit is contained in:
hn8
2021-07-20 00:21:59 +08:00
committed by GitHub
parent c493022f0f
commit 06c44ca8f6
6 changed files with 83 additions and 42 deletions
+6 -2
View File
@@ -3,7 +3,6 @@ package main
import (
"fmt"
"os"
"strconv"
"time"
"github.com/livekit/protocol/auth"
@@ -40,7 +39,12 @@ func printPorts(c *cli.Context) error {
}
if conf.TURN.Enabled {
tcpPorts = append(tcpPorts, strconv.Itoa(conf.TURN.TLSPort))
if conf.TURN.TLSPort > 0 {
tcpPorts = append(tcpPorts, fmt.Sprintf("%d - TURN/TLS", conf.TURN.TLSPort))
}
if conf.TURN.UDPPort > 0 {
udpPorts = append(udpPorts, fmt.Sprintf("%d - TURN/UDP", conf.TURN.UDPPort))
}
}
fmt.Println("TCP Ports")
+4 -2
View File
@@ -95,10 +95,12 @@ keys:
# # - using cert_file and key_file below
# # defaults to false
# enabled: false
# # needs to match tls cert domain
# domain: turn.myhost.com
# # defaults to 3478 - recommended to 443 if not running HTTP3/QUIC server
# udp_port: 3478
# # defaults to 3478 - if not using a load balancer, this must be set to 443
# tls_port: 3478
# # needs to match tls cert domain
# domain: turn.myhost.com
# # optional
# # cert_file: /path/to/cert.pem
# # key_file: /path/to/key.pem
+2
View File
@@ -91,6 +91,7 @@ type TURNConfig struct {
CertFile string `yaml:"cert_file"`
KeyFile string `yaml:"key_file"`
TLSPort int `yaml:"tls_port"`
UDPPort int `yaml:"udp_port"`
}
func NewConfig(confString string, c *cli.Context) (*Config, error) {
@@ -135,6 +136,7 @@ func NewConfig(confString string, c *cli.Context) (*Config, error) {
TURN: TURNConfig{
Enabled: false,
TLSPort: 3478,
UDPPort: 3478,
},
Keys: map[string]string{},
}
+5 -2
View File
@@ -41,12 +41,15 @@ func GetLocalIPAddress() (string, error) {
var ip net.IP
switch v := addr.(type) {
case *net.IPNet:
ip = v.IP
ip = v.IP.To4()
case *net.IPAddr:
ip = v.IP
ip = v.IP.To4()
default:
continue
}
if ip == nil {
continue
}
if ip.IsLoopback() {
loopBack = ip.String()
} else {
+14 -5
View File
@@ -513,11 +513,20 @@ func (r *RoomManager) iceServersForRoom(ri *livekit.Room) []*livekit.ICEServer {
})
}
if r.config.TURN.Enabled {
iceServers = append(iceServers, &livekit.ICEServer{
Urls: []string{fmt.Sprintf("turns:%s:443?transport=tcp", r.config.TURN.Domain)},
Username: ri.Name,
Credential: ri.TurnPassword,
})
var urls []string
if r.config.TURN.UDPPort > 0 {
urls = append(urls, fmt.Sprintf("turn:%s:%d?transport=udp", r.config.RTC.NodeIP, r.config.TURN.UDPPort))
}
if r.config.TURN.TLSPort > 0 {
urls = append(urls, fmt.Sprintf("turns:%s:443?transport=tcp", r.config.TURN.Domain))
}
if len(urls) > 0 {
iceServers = append(iceServers, &livekit.ICEServer{
Urls: urls,
Username: ri.Name,
Credential: ri.TurnPassword,
})
}
}
return iceServers
}
+52 -31
View File
@@ -25,46 +25,67 @@ func NewTurnServer(conf *config.Config, roomStore RoomStore, node routing.LocalN
if !turnConf.Enabled {
return nil, nil
}
if turnConf.Domain == "" {
return nil, errors.New("TURN domain required")
}
if turnConf.TLSPort == 0 {
return nil, errors.New("invalid TURN tcp port")
}
cert, err := tls.LoadX509KeyPair(turnConf.CertFile, turnConf.KeyFile)
if err != nil {
return nil, errors.Wrap(err, "TURN tls cert required")
}
tlsListener, err := tls.Listen("tcp4", "0.0.0.0:"+strconv.Itoa(turnConf.TLSPort), &tls.Config{
MinVersion: tls.VersionTLS12,
Certificates: []tls.Certificate{cert},
})
if err != nil {
return nil, errors.Wrap(err, "could not listen on TURN TCP port")
if turnConf.TLSPort == 0 && turnConf.UDPPort == 0 {
return nil, errors.New("invalid TURN ports")
}
serverConfig := turn.ServerConfig{
Realm: livekitRealm,
AuthHandler: newTurnAuthHandler(roomStore),
LoggerFactory: logger.LoggerFactory(),
ListenerConfigs: []turn.ListenerConfig{
{
Listener: tlsListener,
RelayAddressGenerator: &turn.RelayAddressGeneratorPortRange{
RelayAddress: net.ParseIP(node.Ip),
Address: "0.0.0.0",
MinPort: turnMinPort,
MaxPort: turnMaxPort,
MaxRetries: allocateRetries,
},
},
},
}
relayAddrGen := &turn.RelayAddressGeneratorPortRange{
RelayAddress: net.ParseIP(node.Ip),
Address: "0.0.0.0",
MinPort: turnMinPort,
MaxPort: turnMaxPort,
MaxRetries: allocateRetries,
}
var logValues []interface{}
if turnConf.TLSPort > 0 {
if turnConf.Domain == "" {
return nil, errors.New("TURN domain required")
}
cert, err := tls.LoadX509KeyPair(turnConf.CertFile, turnConf.KeyFile)
if err != nil {
return nil, errors.Wrap(err, "TURN tls cert required")
}
tlsListener, err := tls.Listen("tcp4", "0.0.0.0:"+strconv.Itoa(turnConf.TLSPort),
&tls.Config{
MinVersion: tls.VersionTLS12,
Certificates: []tls.Certificate{cert},
})
if err != nil {
return nil, errors.Wrap(err, "could not listen on TURN TCP port")
}
listenerConfig := turn.ListenerConfig{
Listener: tlsListener,
RelayAddressGenerator: relayAddrGen,
}
serverConfig.ListenerConfigs = append(serverConfig.ListenerConfigs, listenerConfig)
logValues = append(logValues, "turn.portTLS", turnConf.TLSPort)
}
logger.Infow("Starting TURN server",
"TLS port", turnConf.TLSPort)
if turnConf.UDPPort > 0 {
udpListener, err := net.ListenPacket("udp4", "0.0.0.0:"+strconv.Itoa(turnConf.UDPPort))
if err != nil {
return nil, errors.Wrap(err, "could not listen on TURN UDP port")
}
packetConfig := turn.PacketConnConfig{
PacketConn: udpListener,
RelayAddressGenerator: relayAddrGen,
}
serverConfig.PacketConnConfigs = append(serverConfig.PacketConnConfigs, packetConfig)
logValues = append(logValues, "turn.portUDP", turnConf.UDPPort)
}
logger.Infow("Starting TURN server", logValues...)
return turn.NewServer(serverConfig)
}