| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- // Package server implements the private API to implement a TURN server
- package server
- import (
- "fmt"
- "net"
- "sync"
- "time"
- "github.com/pion/logging"
- "github.com/pion/stun"
- "github.com/pion/turn/v2/internal/allocation"
- "github.com/pion/turn/v2/internal/proto"
- )
- // Request contains all the state needed to process a single incoming datagram
- type Request struct {
- // Current Request State
- Conn net.PacketConn
- SrcAddr net.Addr
- Buff []byte
- // Server State
- AllocationManager *allocation.Manager
- Nonces *sync.Map
- // User Configuration
- AuthHandler func(username string, realm string, srcAddr net.Addr) (key []byte, ok bool)
- Log logging.LeveledLogger
- Realm string
- ChannelBindTimeout time.Duration
- }
- // HandleRequest processes the give Request
- func HandleRequest(r Request) error {
- r.Log.Debugf("received %d bytes of udp from %s on %s", len(r.Buff), r.SrcAddr.String(), r.Conn.LocalAddr().String())
- if proto.IsChannelData(r.Buff) {
- return handleDataPacket(r)
- }
- return handleTURNPacket(r)
- }
- func handleDataPacket(r Request) error {
- r.Log.Debugf("received DataPacket from %s", r.SrcAddr.String())
- c := proto.ChannelData{Raw: r.Buff}
- if err := c.Decode(); err != nil {
- return fmt.Errorf("%w: %v", errFailedToCreateChannelData, err)
- }
- err := handleChannelData(r, &c)
- if err != nil {
- err = fmt.Errorf("%w from %v: %v", errUnableToHandleChannelData, r.SrcAddr, err)
- }
- return err
- }
- func handleTURNPacket(r Request) error {
- r.Log.Debug("handleTURNPacket")
- m := &stun.Message{Raw: append([]byte{}, r.Buff...)}
- if err := m.Decode(); err != nil {
- return fmt.Errorf("%w: %v", errFailedToCreateSTUNPacket, err)
- }
- h, err := getMessageHandler(m.Type.Class, m.Type.Method)
- if err != nil {
- return fmt.Errorf("%w %v-%v from %v: %v", errUnhandledSTUNPacket, m.Type.Method, m.Type.Class, r.SrcAddr, err)
- }
- err = h(r, m)
- if err != nil {
- return fmt.Errorf("%w %v-%v from %v: %v", errFailedToHandle, m.Type.Method, m.Type.Class, r.SrcAddr, err)
- }
- return nil
- }
- func getMessageHandler(class stun.MessageClass, method stun.Method) (func(r Request, m *stun.Message) error, error) {
- switch class {
- case stun.ClassIndication:
- switch method {
- case stun.MethodSend:
- return handleSendIndication, nil
- default:
- return nil, fmt.Errorf("%w: %s", errUnexpectedMethod, method)
- }
- case stun.ClassRequest:
- switch method {
- case stun.MethodAllocate:
- return handleAllocateRequest, nil
- case stun.MethodRefresh:
- return handleRefreshRequest, nil
- case stun.MethodCreatePermission:
- return handleCreatePermissionRequest, nil
- case stun.MethodChannelBind:
- return handleChannelBindRequest, nil
- case stun.MethodBinding:
- return handleBindingRequest, nil
- default:
- return nil, fmt.Errorf("%w: %s", errUnexpectedMethod, method)
- }
- default:
- return nil, fmt.Errorf("%w: %s", errUnexpectedClass, class)
- }
- }
|