// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT

// Package server implements the private API to implement a TURN server
package server import ( ) // 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 NonceHash *NonceHash // 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 ( Request) error { .Log.Debugf("Received %d bytes of udp from %s on %s", len(.Buff), .SrcAddr, .Conn.LocalAddr()) if proto.IsChannelData(.Buff) { return handleDataPacket() } return handleTURNPacket() } func handleDataPacket( Request) error { .Log.Debugf("Received DataPacket from %s", .SrcAddr.String()) := proto.ChannelData{Raw: .Buff} if := .Decode(); != nil { return fmt.Errorf("%w: %v", errFailedToCreateChannelData, ) //nolint:errorlint } := handleChannelData(, &) if != nil { = fmt.Errorf("%w from %v: %v", errUnableToHandleChannelData, .SrcAddr, ) //nolint:errorlint } return } func handleTURNPacket( Request) error { .Log.Debug("Handling TURN packet") := &stun.Message{Raw: append([]byte{}, .Buff...)} if := .Decode(); != nil { // nolint:errorlint return fmt.Errorf("%w: %v", errFailedToCreateSTUNPacket, ) } , := getMessageHandler(.Type.Class, .Type.Method) if != nil { // nolint:errorlint return fmt.Errorf( "%w %v-%v from %v: %v", errUnhandledSTUNPacket, .Type.Method, .Type.Class, .SrcAddr, , ) } = (, ) if != nil { // nolint:errorlint return fmt.Errorf( "%w %v-%v from %v: %v", errFailedToHandle, .Type.Method, .Type.Class, .SrcAddr, , ) } return nil } func getMessageHandler( stun.MessageClass, stun.Method) ( // nolint:cyclop func( Request, *stun.Message) error, error, ) { switch { case stun.ClassIndication: switch { case stun.MethodSend: return handleSendIndication, nil default: return nil, fmt.Errorf("%w: %s", errUnexpectedMethod, ) } case stun.ClassRequest: switch { 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, ) } default: return nil, fmt.Errorf("%w: %s", errUnexpectedClass, ) } }