package server
import (
"fmt"
"net"
"time"
"github.com/pion/logging"
"github.com/pion/stun/v3"
"github.com/pion/turn/v4/internal/allocation"
"github.com/pion/turn/v4/internal/proto"
)
type Request struct {
Conn net .PacketConn
SrcAddr net .Addr
Buff []byte
AllocationManager *allocation .Manager
NonceHash *NonceHash
AuthHandler func (username string , realm string , srcAddr net .Addr ) (key []byte , ok bool )
Log logging .LeveledLogger
Realm string
ChannelBindTimeout time .Duration
}
func HandleRequest (r Request ) error {
r .Log .Debugf ("Received %d bytes of udp from %s on %s" , len (r .Buff ), r .SrcAddr , r .Conn .LocalAddr ())
if proto .IsChannelData (r .Buff ) {
return handleDataPacket (r )
}
return handleTURNPacket (r )
}
func handleDataPacket(req Request ) error {
req .Log .Debugf ("Received DataPacket from %s" , req .SrcAddr .String ())
c := proto .ChannelData {Raw : req .Buff }
if err := c .Decode (); err != nil {
return fmt .Errorf ("%w: %v" , errFailedToCreateChannelData , err )
}
err := handleChannelData (req , &c )
if err != nil {
err = fmt .Errorf ("%w from %v: %v" , errUnableToHandleChannelData , req .SrcAddr , err )
}
return err
}
func handleTURNPacket(req Request ) error {
req .Log .Debug ("Handling TURN packet" )
stunMsg := &stun .Message {Raw : append ([]byte {}, req .Buff ...)}
if err := stunMsg .Decode (); err != nil {
return fmt .Errorf ("%w: %v" , errFailedToCreateSTUNPacket , err )
}
handler , err := getMessageHandler (stunMsg .Type .Class , stunMsg .Type .Method )
if err != nil {
return fmt .Errorf (
"%w %v-%v from %v: %v" ,
errUnhandledSTUNPacket ,
stunMsg .Type .Method ,
stunMsg .Type .Class ,
req .SrcAddr ,
err ,
)
}
err = handler (req , stunMsg )
if err != nil {
return fmt .Errorf (
"%w %v-%v from %v: %v" ,
errFailedToHandle ,
stunMsg .Type .Method ,
stunMsg .Type .Class ,
req .SrcAddr ,
err ,
)
}
return nil
}
func getMessageHandler(class stun .MessageClass , method stun .Method ) (
func (req Request , stunMsg *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 )
}
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .