func (s *Server) handleDataPacket(conn net.PacketConn, srcAddr net.Addr, buf []byte) error {
	s.log.Debugf("received DataPacket from %s", srcAddr.String())
	c := proto.ChannelData{Raw: buf}
	if err := c.Decode(); err != nil {
		return errors.Wrap(err, "Failed to create channel data from packet")
	}
	err := s.handleChannelData(conn, srcAddr, &c)
	if err != nil {
		err = errors.Errorf("unable to handle ChannelData from %v: %v", srcAddr, err)
	}
	return err
}
caller must hold the mutex
package turn
import (
	"crypto/md5"  
	"fmt"
	"io"
	"math/rand"
	"net"
	"strconv"
	"strings"
	"sync"
	"time"
	"github.com/pion/logging"
	"github.com/pion/stun"
	"github.com/pion/transport/vnet"
	"github.com/pion/turn/internal/allocation"
	"github.com/pion/turn/internal/proto"
	"github.com/pkg/errors"
)
const (
	maxStunMessageSize = 1500
)
type AuthHandler func(username string, srcAddr net.Addr) (password string, ok bool)
type ServerConfig struct {
	Realm string
	AuthHandler AuthHandler
	ChannelBindTimeout time.Duration
	ListeningPort int
	LoggerFactory logging.LoggerFactory
	Net *vnet.Net
	Software string
	Sender Sender
}
type listener struct {
	conn    net.PacketConn
	closeCh chan struct{}
}
type Server struct {
	lock               sync.RWMutex
	listeners          []*listener
	listenIPs          []net.IP
	relayIPs           []net.IP
	extIPMappings      [][2]net.IP
	listenPort         int
	realm              string
	authHandler        AuthHandler
	manager            *allocation.Manager
	reservationManager *allocation.ReservationManager
	channelBindTimeout time.Duration
	log                logging.LeveledLogger
	net                *vnet.Net
	software           stun.Software
	sender             Sender
}
func NewServer(config *ServerConfig) *Server {
	log := config.LoggerFactory.NewLogger("turn")
	if config.Net == nil {
		config.Net = vnet.NewNet(nil)  
	} else {
		log.Warn("vnet is enabled")
	}
	if config.Sender == nil {
		config.Sender = defaultBuildAndSend
	}
	manager := allocation.NewManager(&allocation.ManagerConfig{
		LeveledLogger: log,
		Net:           config.Net,
	})
	listenPort := config.ListeningPort
	if listenPort == 0 {
		listenPort = 3478
	}
	channelBindTimeout := config.ChannelBindTimeout
	if channelBindTimeout == 0 {
		channelBindTimeout = proto.DefaultLifetime
	}
	return &Server{
		listenPort:         listenPort,
		realm:              config.Realm,
		authHandler:        config.AuthHandler,
		manager:            manager,
		reservationManager: &allocation.ReservationManager{},
		channelBindTimeout: channelBindTimeout,
		log:                log,
		net:                config.Net,
		software:           stun.NewSoftware(config.Software),
		sender:             config.Sender,
	}
}
func (s *Server) AddListeningIPAddr(addrStr string) error {
	ip := net.ParseIP(addrStr)
	if ip.To4() == nil {
		return fmt.Errorf("Non-IPv4 address is not supported")
	}
	if ip.IsLinkLocalUnicast() {
		return fmt.Errorf("link-local unicast address is not allowed")
	}
	s.listenIPs = append(s.listenIPs, ip)
	return nil
}
func (s *Server) AddRelayIPAddr(addrStr string) error {
	ip := net.ParseIP(addrStr)
	if ip.To4() == nil {
		return fmt.Errorf("Non-IPv4 address is not supported")
	}
	if ip.IsLinkLocalUnicast() {
		return fmt.Errorf("link-local unicast address is not allowed")
	}
	if ip.IsUnspecified() {
		return fmt.Errorf("unspecified IP is not allowed")
	}
	s.relayIPs = append(s.relayIPs, ip)
	return nil
}
func (s *Server) AddExternalIPAddr(mapping string) error {
	var extIP, locIP net.IP
	ipStrs := strings.Split(mapping, "/")
	extIP = net.ParseIP(ipStrs[0])
	if extIP == nil {
		return fmt.Errorf("invalid IP address: %s", ipStrs[0])
	}
	if len(ipStrs) > 1 {
		locIP = net.ParseIP(ipStrs[1])
		if locIP == nil {
			return fmt.Errorf("invalid IP address: %s", ipStrs[1])
		}
	}
	s.extIPMappings = append(s.extIPMappings, [2]net.IP{extIP, locIP})
	return nil
}
func (s *Server) gatherSystemIPAddrs() ([]net.IP, error) {
	s.log.Debug("gathering local IP address...")
	var ips []net.IP
	ifs, err := s.net.Interfaces()
	if err != nil {
		return nil, err
	}
	for _, ifc := range ifs {
		if ifc.Flags&net.FlagUp == 0 {
			continue  
		}
		if ifc.Flags&net.FlagLoopback != 0 {
			continue  
		}
		addrs, err := ifc.Addrs()
		if err != nil {
			continue
		}
		for _, addr := range addrs {
			var ip net.IP
			switch addr := addr.(type) {
			case *net.IPNet:
				ip = addr.IP
			case *net.IPAddr:
				ip = addr.IP
			}
			if ip == nil {
				return nil, fmt.Errorf("invalid IP address: %s", addr.String())
			}
			if ip.To4() == nil {
				continue  
			}
			if ip.IsLinkLocalUnicast() {
				continue
			}
			s.log.Debugf("- found local IP: %s", ip.String())
			ips = append(ips, ip)
		}
	}
	return ips, nil
}
func (s *Server) listen(localIP net.IP) error {
	network := "udp4"
	listenAddr := fmt.Sprintf("%s:%d", localIP.String(), s.listenPort)
	conn, err := s.net.ListenPacket(network, listenAddr)
	if err != nil {
		return errors.Wrap(err, fmt.Sprintf("Failed to listen on %s", listenAddr))
	}
	laddr := conn.LocalAddr()
	s.log.Infof("Listening on %s:%s", laddr.Network(), laddr.String())
	closeCh := make(chan struct{})
	s.listeners = append(s.listeners, &listener{
		conn:    conn,
		closeCh: closeCh,
	})
	go func() {
		buf := make([]byte, maxStunMessageSize)
		for {
			n, addr, err := conn.ReadFrom(buf)
			if err != nil {
				s.log.Debugf("exit read loop on error: %s", err.Error())
				break
			}
			if err := s.handleUDPPacket(conn, addr, buf[:n]); err != nil {
				s.log.Error(err.Error())
			}
		}
		close(closeCh)
	}()
	return nil
}
func (s *Server) Start() error {
	s.lock.Lock()
	defer s.lock.Unlock()
	var ips []net.IP
	if len(s.listenIPs) == 0 {
		var err error
		ips, err = s.gatherSystemIPAddrs()
		if err != nil {
			return err
		}
		if len(ips) == 0 {
			return fmt.Errorf("no local IP address found")
		}
		s.listenIPs = ips
	}
	if len(s.relayIPs) == 0 {
		s.relayIPs = s.listenIPs
	}
	for _, mapping := range s.extIPMappings {
		extIPIsV4 := (mapping[0].To4() != nil)
		if mapping[1] == nil {
			for _, relayIP := range s.relayIPs {
				relayIPIsV4 := (relayIP.To4() != nil)
				if (extIPIsV4 && relayIPIsV4) || (!extIPIsV4 && !relayIPIsV4) {
					s.manager.AddExternalIPMapping(mapping[0], relayIP)
				}
			}
		} else {
			relayIPIsV4 := (mapping[1].To4() != nil)
			if (extIPIsV4 && relayIPIsV4) || (!extIPIsV4 && !relayIPIsV4) {
				s.manager.AddExternalIPMapping(mapping[0], mapping[1])
			}
		}
	}
	for _, localIP := range s.listenIPs {
		err := s.listen(localIP)
		if err != nil {
			return err
		}
	}
	return nil
}
func (s *Server) Close() error {
	var toJoin []*listener
	var err error
	func() {
		s.lock.RLock()
		defer s.lock.RUnlock()
		if err2 := s.manager.Close(); err2 != nil {
			err = err2
		}
		for _, l := range s.listeners {
			err2 := l.conn.Close()
			if err2 != nil {
				s.log.Debugf("Close() returned error: %s", err2.Error())
				continue
			}
			toJoin = append(toJoin, l)
		}
	}()
	for _, l := range s.listeners {
		<-l.closeCh
	}
	return err
}
func (s *Server) handleUDPPacket(conn net.PacketConn, srcAddr net.Addr, buf []byte) error {
	s.lock.Lock()
	defer s.lock.Unlock()
	s.log.Debugf("received %d bytes of udp from %s on %s",
		len(buf),
		srcAddr.String(),
		conn.LocalAddr().String(),
	)
	if proto.IsChannelData(buf) {
		return s.handleDataPacket(conn, srcAddr, buf)
	}
	return s.handleTURNPacket(conn, srcAddr, buf)
}