github.com/ergo-services/ergo@v1.999.224/gen/udp_handler.go (about)

     1  package gen
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/ergo-services/ergo/etf"
     8  	"github.com/ergo-services/ergo/lib"
     9  )
    10  
    11  type UDPHandlerBehavior interface {
    12  	ServerBehavior
    13  
    14  	// Mandatory callback
    15  	HandlePacket(process *UDPHandlerProcess, data []byte, packet UDPPacket)
    16  
    17  	// Optional callbacks
    18  	HandleTimeout(process *UDPHandlerProcess)
    19  
    20  	HandleUDPHandlerCall(process *UDPHandlerProcess, from ServerFrom, message etf.Term) (etf.Term, ServerStatus)
    21  	HandleUDPHandlerCast(process *UDPHandlerProcess, message etf.Term) ServerStatus
    22  	HandleUDPHandlerInfo(process *UDPHandlerProcess, message etf.Term) ServerStatus
    23  	HandleUDPHandlerTerminate(process *UDPHandlerProcess, reason string)
    24  }
    25  
    26  type UDPHandler struct {
    27  	Server
    28  }
    29  
    30  type UDPHandlerProcess struct {
    31  	ServerProcess
    32  	behavior UDPHandlerBehavior
    33  
    34  	lastPacket  int64
    35  	idleTimeout int
    36  	id          int
    37  }
    38  
    39  type optsUDPHandler struct {
    40  	id          int
    41  	idleTimeout int
    42  }
    43  type messageUDPHandlerIdleCheck struct{}
    44  type messageUDPHandlerPacket struct {
    45  	data   *lib.Buffer
    46  	packet UDPPacket
    47  	n      int
    48  }
    49  type messageUDPHandlerTimeout struct{}
    50  
    51  func (udph *UDPHandler) Init(process *ServerProcess, args ...etf.Term) error {
    52  	behavior, ok := process.Behavior().(UDPHandlerBehavior)
    53  	if !ok {
    54  		return fmt.Errorf("UDP: not a UDPHandlerBehavior")
    55  	}
    56  	handlerProcess := &UDPHandlerProcess{
    57  		ServerProcess: *process,
    58  		behavior:      behavior,
    59  	}
    60  	if len(args) == 0 {
    61  		return fmt.Errorf("UDP: can not start with no args")
    62  	}
    63  
    64  	if a, ok := args[0].(optsUDPHandler); ok {
    65  		handlerProcess.idleTimeout = a.idleTimeout
    66  		handlerProcess.id = a.id
    67  	} else {
    68  		return fmt.Errorf("UDP: wrong args for the UDPHandler")
    69  	}
    70  
    71  	// do not inherit parent State
    72  	handlerProcess.State = nil
    73  	process.State = handlerProcess
    74  
    75  	if handlerProcess.idleTimeout > 0 {
    76  		process.CastAfter(process.Self(), messageUDPHandlerIdleCheck{}, 5*time.Second)
    77  	}
    78  
    79  	return nil
    80  }
    81  
    82  func (udph *UDPHandler) HandleCall(process *ServerProcess, from ServerFrom, message etf.Term) (etf.Term, ServerStatus) {
    83  	udpp := process.State.(*UDPHandlerProcess)
    84  	return udpp.behavior.HandleUDPHandlerCall(udpp, from, message)
    85  }
    86  
    87  func (udph *UDPHandler) HandleCast(process *ServerProcess, message etf.Term) ServerStatus {
    88  	udpp := process.State.(*UDPHandlerProcess)
    89  	switch m := message.(type) {
    90  	case messageUDPHandlerIdleCheck:
    91  		if time.Now().Unix()-udpp.lastPacket > int64(udpp.idleTimeout) {
    92  			return ServerStatusStop
    93  		}
    94  		process.CastAfter(process.Self(), messageUDPHandlerIdleCheck{}, 5*time.Second)
    95  
    96  	case messageUDPHandlerPacket:
    97  		udpp.lastPacket = time.Now().Unix()
    98  		udpp.behavior.HandlePacket(udpp, m.data.B[:m.n], m.packet)
    99  		lib.ReleaseBuffer(m.data)
   100  
   101  	case messageUDPHandlerTimeout:
   102  		udpp.behavior.HandleTimeout(udpp)
   103  
   104  	default:
   105  		return udpp.behavior.HandleUDPHandlerCast(udpp, message)
   106  	}
   107  	return ServerStatusOK
   108  }
   109  
   110  func (udph *UDPHandler) HandleInfo(process *ServerProcess, message etf.Term) ServerStatus {
   111  	udpp := process.State.(*UDPHandlerProcess)
   112  	return udpp.behavior.HandleUDPHandlerInfo(udpp, message)
   113  }
   114  
   115  func (udph *UDPHandler) Terminate(process *ServerProcess, reason string) {
   116  	udpp := process.State.(*UDPHandlerProcess)
   117  	udpp.behavior.HandleUDPHandlerTerminate(udpp, reason)
   118  }
   119  
   120  //
   121  // default callbacks
   122  //
   123  
   124  func (udph *UDPHandler) HandleTimeout(process *UDPHandlerProcess) {
   125  	return
   126  }
   127  
   128  // HandleUDPHandlerCall
   129  func (udph *UDPHandler) HandleUDPHandlerCall(process *UDPHandlerProcess, from ServerFrom, message etf.Term) (etf.Term, ServerStatus) {
   130  	lib.Warning("HandleUDPHandlerCall: unhandled message (from %#v) %#v", from, message)
   131  	return etf.Atom("ok"), ServerStatusOK
   132  }
   133  
   134  // HandleUDPHandlerCast
   135  func (udph *UDPHandler) HandleUDPHandlerCast(process *UDPHandlerProcess, message etf.Term) ServerStatus {
   136  	lib.Warning("HandleUDPHandlerCast: unhandled message %#v", message)
   137  	return ServerStatusOK
   138  }
   139  
   140  // HandleUDPHandlerInfo
   141  func (udph *UDPHandler) HandleUDPHandlerInfo(process *UDPHandlerProcess, message etf.Term) ServerStatus {
   142  	lib.Warning("HandleUDPHandlerInfo: unhandled message %#v", message)
   143  	return ServerStatusOK
   144  }
   145  func (udph *UDPHandler) HandleUDPHandlerTerminate(process *UDPHandlerProcess, reason string) {
   146  	return
   147  }
   148  
   149  // we should disable SetTrapExit for the UDPHandlerProcess by overriding it.
   150  func (udpp *UDPHandlerProcess) SetTrapExit(trap bool) {
   151  	lib.Warning("[%s] method 'SetTrapExit' is disabled for UDPHandlerProcess", udpp.Self())
   152  }