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 }