|
@@ -10,30 +10,53 @@ const (
|
|
|
udpServerReceiveBufferSize = 1024
|
|
|
)
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+type UDPServerRequestCallback func(data []byte) (send bool, responseBytes []byte, err error)
|
|
|
+
|
|
|
type UDPServerOption func(opt *UDPServerOptions)
|
|
|
|
|
|
-func WithReceiveBufferSize(receiveBufferSize int) UDPServerOption {
|
|
|
+func WithUDPServerReceiveBufferSize(receiveBufferSize int) UDPServerOption {
|
|
|
+ return func(opt *UDPServerOptions) {
|
|
|
+ opt.receiveBufferSize = receiveBufferSize
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func WithUDPServerWriteTimeout(timeout time.Duration) UDPServerOption {
|
|
|
return func(opt *UDPServerOptions) {
|
|
|
- opt.ReceiveBufferSize = receiveBufferSize
|
|
|
+ opt.writeTimeout = timeout
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func WithWriteTimeout(timeout time.Duration) UDPServerOption {
|
|
|
+func WithUDPServerReadTimeout(timeout time.Duration) UDPServerOption {
|
|
|
return func(opt *UDPServerOptions) {
|
|
|
- opt.WriteTimeout = timeout
|
|
|
+ opt.readTimeout = timeout
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func WithReadTimeout(timeout time.Duration) UDPServerOption {
|
|
|
+func WithUDPServerRequestCallback(requestCallback UDPServerRequestCallback) UDPServerOption {
|
|
|
return func(opt *UDPServerOptions) {
|
|
|
- opt.ReadTimeout = timeout
|
|
|
+ opt.requestCallback = requestCallback
|
|
|
}
|
|
|
}
|
|
|
|
|
|
type UDPServerOptions struct {
|
|
|
- ReceiveBufferSize int
|
|
|
- WriteTimeout time.Duration
|
|
|
- ReadTimeout time.Duration
|
|
|
+
|
|
|
+ receiveBufferSize int
|
|
|
+
|
|
|
+
|
|
|
+ writeTimeout time.Duration
|
|
|
+
|
|
|
+
|
|
|
+ readTimeout time.Duration
|
|
|
+
|
|
|
+
|
|
|
+ requestCallback UDPServerRequestCallback
|
|
|
}
|
|
|
|
|
|
func NewUDPServerOptions(opts ...UDPServerOption) *UDPServerOptions {
|
|
@@ -43,24 +66,17 @@ func NewUDPServerOptions(opts ...UDPServerOption) *UDPServerOptions {
|
|
|
opt(options)
|
|
|
}
|
|
|
|
|
|
- if options.ReceiveBufferSize == 0 {
|
|
|
- options.ReceiveBufferSize = udpServerReceiveBufferSize
|
|
|
+ if options.receiveBufferSize == 0 {
|
|
|
+ options.receiveBufferSize = udpServerReceiveBufferSize
|
|
|
}
|
|
|
|
|
|
return options
|
|
|
}
|
|
|
|
|
|
type UDPServer struct {
|
|
|
- options *UDPServerOptions
|
|
|
- conn *net.UDPConn
|
|
|
- doneChan chan any
|
|
|
- dealRequestChan chan *remoteData
|
|
|
- dealRequestDoneChan chan any
|
|
|
-}
|
|
|
-
|
|
|
-type remoteData struct {
|
|
|
- data []byte
|
|
|
- rAddr *net.UDPAddr
|
|
|
+ options *UDPServerOptions
|
|
|
+ conn *net.UDPConn
|
|
|
+ doneChan chan any
|
|
|
}
|
|
|
|
|
|
|
|
@@ -81,7 +97,7 @@ func (server *UDPServer) Connect(address string, options *UDPServerOptions) erro
|
|
|
server.doneChan = make(chan any)
|
|
|
|
|
|
|
|
|
- go server.readRequest()
|
|
|
+ server.readRequest()
|
|
|
|
|
|
return nil
|
|
|
}
|
|
@@ -97,38 +113,62 @@ func (server *UDPServer) Disconnect() {
|
|
|
}
|
|
|
|
|
|
func (server *UDPServer) readRequest() {
|
|
|
- server.dealRequestChan = make(chan *remoteData)
|
|
|
- server.dealRequestDoneChan = make(chan any)
|
|
|
-
|
|
|
- go server.dealRequestAndResponse()
|
|
|
+ dealRequestDoneChannels := make([]chan any, 0)
|
|
|
|
|
|
for {
|
|
|
select {
|
|
|
case <-server.doneChan:
|
|
|
- server.dealRequestDoneChan <- nil
|
|
|
- close(server.dealRequestDoneChan)
|
|
|
- server.dealRequestDoneChan = nil
|
|
|
-
|
|
|
- close(server.dealRequestChan)
|
|
|
- server.dealRequestChan = nil
|
|
|
+ for _, dealRequestDoneChan := range dealRequestDoneChannels {
|
|
|
+ dealRequestDoneChan <- nil
|
|
|
+ close(dealRequestDoneChan)
|
|
|
+ }
|
|
|
|
|
|
return
|
|
|
default:
|
|
|
-
|
|
|
- data, rAddr, err := readUDP(server.conn, server.options.ReceiveBufferSize, WithReadDeadline(server.options.ReadTimeout))
|
|
|
+
|
|
|
+ data, rAddr, err := readUDP(server.conn, server.options.receiveBufferSize, WithReadDeadline(server.options.readTimeout))
|
|
|
if err != nil {
|
|
|
fmt.Println(err)
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
- server.dealRequestChan <- &remoteData{
|
|
|
- data: data,
|
|
|
- rAddr: rAddr,
|
|
|
+
|
|
|
+ dealRequestDoneChan := make(chan any)
|
|
|
+ dealRequestDoneChannels = append(dealRequestDoneChannels, dealRequestDoneChan)
|
|
|
+ go server.dealRequest(data, rAddr, dealRequestDoneChan)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func (server *UDPServer) dealRequest(data []byte, rAddr *net.UDPAddr, doneChan chan any) {
|
|
|
+ for {
|
|
|
+ select {
|
|
|
+ case <-doneChan:
|
|
|
+ return
|
|
|
+ default:
|
|
|
+ if server.options.requestCallback == nil {
|
|
|
+ server.response(server.conn, rAddr, data)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ send, responseBytes, err := server.options.requestCallback(data)
|
|
|
+ if !send {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ server.response(server.conn, rAddr, []byte(err.Error()))
|
|
|
}
|
|
|
+
|
|
|
+ server.response(server.conn, rAddr, responseBytes)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func (server *UDPServer) dealRequestAndResponse() {
|
|
|
-
|
|
|
+func (server *UDPServer) response(conn *net.UDPConn, rAddr *net.UDPAddr, data []byte) {
|
|
|
+ err := writeUDPWithRemoteAddr(conn, rAddr, data, WithWriteDeadline(server.options.writeTimeout))
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("Response Error:", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
}
|