summaryrefslogtreecommitdiff
path: root/vendor/github.com/pion/turn/v2/server.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/pion/turn/v2/server.go')
-rw-r--r--vendor/github.com/pion/turn/v2/server.go161
1 files changed, 161 insertions, 0 deletions
diff --git a/vendor/github.com/pion/turn/v2/server.go b/vendor/github.com/pion/turn/v2/server.go
new file mode 100644
index 0000000..c8deba8
--- /dev/null
+++ b/vendor/github.com/pion/turn/v2/server.go
@@ -0,0 +1,161 @@
+// Package turn contains the public API for pion/turn, a toolkit for building TURN clients and servers
+package turn
+
+import (
+ "fmt"
+ "net"
+ "sync"
+ "time"
+
+ "github.com/pion/logging"
+ "github.com/pion/turn/v2/internal/allocation"
+ "github.com/pion/turn/v2/internal/proto"
+ "github.com/pion/turn/v2/internal/server"
+)
+
+const (
+ inboundMTU = 1500
+)
+
+// Server is an instance of the Pion TURN Server
+type Server struct {
+ log logging.LeveledLogger
+ authHandler AuthHandler
+ realm string
+ channelBindTimeout time.Duration
+ nonces *sync.Map
+
+ packetConnConfigs []PacketConnConfig
+ listenerConfigs []ListenerConfig
+}
+
+// NewServer creates the Pion TURN server
+func NewServer(config ServerConfig) (*Server, error) {
+ if err := config.validate(); err != nil {
+ return nil, err
+ }
+
+ loggerFactory := config.LoggerFactory
+ if loggerFactory == nil {
+ loggerFactory = logging.NewDefaultLoggerFactory()
+ }
+
+ s := &Server{
+ log: loggerFactory.NewLogger("turn"),
+ authHandler: config.AuthHandler,
+ realm: config.Realm,
+ channelBindTimeout: config.ChannelBindTimeout,
+ packetConnConfigs: config.PacketConnConfigs,
+ listenerConfigs: config.ListenerConfigs,
+ nonces: &sync.Map{},
+ }
+
+ if s.channelBindTimeout == 0 {
+ s.channelBindTimeout = proto.DefaultLifetime
+ }
+
+ for i := range s.packetConnConfigs {
+ go func(p PacketConnConfig) {
+ allocationManager, err := allocation.NewManager(allocation.ManagerConfig{
+ AllocatePacketConn: p.RelayAddressGenerator.AllocatePacketConn,
+ AllocateConn: p.RelayAddressGenerator.AllocateConn,
+ LeveledLogger: s.log,
+ })
+ if err != nil {
+ s.log.Errorf("exit read loop on error: %s", err.Error())
+ return
+ }
+ defer func() {
+ if err := allocationManager.Close(); err != nil {
+ s.log.Errorf("Failed to close AllocationManager: %s", err.Error())
+ }
+ }()
+
+ s.readLoop(p.PacketConn, allocationManager)
+ }(s.packetConnConfigs[i])
+ }
+
+ for _, listener := range s.listenerConfigs {
+ go func(l ListenerConfig) {
+ allocationManager, err := allocation.NewManager(allocation.ManagerConfig{
+ AllocatePacketConn: l.RelayAddressGenerator.AllocatePacketConn,
+ AllocateConn: l.RelayAddressGenerator.AllocateConn,
+ LeveledLogger: s.log,
+ })
+ if err != nil {
+ s.log.Errorf("exit read loop on error: %s", err.Error())
+ return
+ }
+ defer func() {
+ if err := allocationManager.Close(); err != nil {
+ s.log.Errorf("Failed to close AllocationManager: %s", err.Error())
+ }
+ }()
+
+ for {
+ conn, err := l.Listener.Accept()
+ if err != nil {
+ s.log.Debugf("exit accept loop on error: %s", err.Error())
+ return
+ }
+
+ go s.readLoop(NewSTUNConn(conn), allocationManager)
+ }
+ }(listener)
+ }
+
+ return s, nil
+}
+
+// Close stops the TURN Server. It cleans up any associated state and closes all connections it is managing
+func (s *Server) Close() error {
+ var errors []error
+
+ for _, p := range s.packetConnConfigs {
+ if err := p.PacketConn.Close(); err != nil {
+ errors = append(errors, err)
+ }
+ }
+
+ for _, l := range s.listenerConfigs {
+ if err := l.Listener.Close(); err != nil {
+ errors = append(errors, err)
+ }
+ }
+
+ if len(errors) == 0 {
+ return nil
+ }
+
+ err := errFailedToClose
+ for _, e := range errors {
+ err = fmt.Errorf("%s; Close error (%v) ", err.Error(), e) //nolint:goerr113
+ }
+
+ return err
+}
+
+func (s *Server) readLoop(p net.PacketConn, allocationManager *allocation.Manager) {
+ buf := make([]byte, inboundMTU)
+ for {
+ n, addr, err := p.ReadFrom(buf)
+ if err != nil {
+ s.log.Debugf("exit read loop on error: %s", err.Error())
+ return
+ }
+
+ if err := server.HandleRequest(server.Request{
+ Conn: p,
+ SrcAddr: addr,
+ Buff: buf[:n],
+ Log: s.log,
+ AuthHandler: s.authHandler,
+ Realm: s.realm,
+ AllocationManager: allocationManager,
+ ChannelBindTimeout: s.channelBindTimeout,
+ Nonces: s.nonces,
+ }); err != nil {
+ s.log.Errorf("error when handling datagram: %v", err)
+ }
+ }
+}