Files
g365sfu/turn/turn.go

112 lines
2.1 KiB
Go

package turn
import (
"fmt"
"net"
pionturn "github.com/pion/turn/v4"
)
type Server struct {
udpConn net.PacketConn
tcpListener net.Listener
srv *pionturn.Server
}
type Config struct {
ListenAddr string // "0.0.0.0:3478"
PublicIP string
Realm string
Username string
Password string
MinRelayPort uint16
MaxRelayPort uint16
}
func relayGen(ip net.IP, minPort, maxPort uint16) pionturn.RelayAddressGenerator {
if minPort != 0 && maxPort != 0 && minPort <= maxPort {
return &pionturn.RelayAddressGeneratorPortRange{
RelayAddress: ip,
Address: "0.0.0.0",
MinPort: minPort,
MaxPort: maxPort,
}
}
return &pionturn.RelayAddressGeneratorStatic{
RelayAddress: ip,
Address: "0.0.0.0",
}
}
func Start(cfg Config) (*Server, error) {
ip := net.ParseIP(cfg.PublicIP)
if ip == nil {
return nil, fmt.Errorf("turn: invalid PublicIP: %s", cfg.PublicIP)
}
udpConn, err := net.ListenPacket("udp4", cfg.ListenAddr)
if err != nil {
return nil, err
}
tcpListener, err := net.Listen("tcp4", cfg.ListenAddr)
if err != nil {
_ = udpConn.Close()
return nil, err
}
rg := relayGen(ip, cfg.MinRelayPort, cfg.MaxRelayPort)
srv, err := pionturn.NewServer(pionturn.ServerConfig{
Realm: cfg.Realm,
AuthHandler: func(username, realm string, srcAddr net.Addr) ([]byte, bool) {
if username != cfg.Username {
return nil, false
}
return pionturn.GenerateAuthKey(username, realm, cfg.Password), true
},
PacketConnConfigs: []pionturn.PacketConnConfig{
{
PacketConn: udpConn,
RelayAddressGenerator: rg,
},
},
ListenerConfigs: []pionturn.ListenerConfig{
{
Listener: tcpListener,
RelayAddressGenerator: rg,
},
},
})
if err != nil {
_ = tcpListener.Close()
_ = udpConn.Close()
return nil, err
}
return &Server{
udpConn: udpConn,
tcpListener: tcpListener,
srv: srv,
}, nil
}
func (s *Server) Close() error {
if s == nil {
return nil
}
if s.srv != nil {
_ = s.srv.Close()
}
if s.tcpListener != nil {
_ = s.tcpListener.Close()
}
if s.udpConn != nil {
_ = s.udpConn.Close()
}
return nil
}