/
udpserver.go
92 lines (73 loc) · 1.83 KB
/
udpserver.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package sunrpc
import (
"net"
"strconv"
"gopkg.in/Sirupsen/logrus.v0"
)
// MaxUdpSize is the maximum size of an RPC message we accept over UDP.
const MaxUdpSize = 65507
// UDPServer is an RPC server over UDP.
type UDPServer struct {
server
}
// NewUDPServer creates a new UDPServer for the given RPC program identifier and program version.
func NewUDPServer(program uint32, version uint32) Server {
return &UDPServer{
server: newServer(program, version, logrus.Fields{"proto": "udp"}),
}
}
// Serve starts the RPC server.
func (server *UDPServer) Serve(addr string) error {
// Parse and deconstruct host and port
host, portString, err := net.SplitHostPort(addr)
if err != nil {
return err
}
port, err := strconv.Atoi(portString)
if err != nil {
return err
}
// Start UDP Server
conn, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.ParseIP(host), Port: port})
if err != nil {
return err
}
if err := conn.SetReadBuffer(MaxUdpSize); err != nil {
return err
}
if err := conn.SetWriteBuffer(MaxUdpSize); err != nil {
return err
}
if err := server.registerToPortmapper(Udp, port); err != nil {
return err
}
go func() {
for {
server.handleCall(conn)
}
}()
return nil
}
//
// Private
//
func (s *UDPServer) handleCall(conn *net.UDPConn) {
// Read and buffer UDP datagram
b := make([]byte, MaxUdpSize)
packetSize, callerAddr, err := conn.ReadFromUDP(b)
if err != nil {
s.server.log.WithField("err", err).Error("Cannot read UDP datagram")
return
}
reply, err := s.server.handleRecord(b[0:packetSize])
if err != nil {
s.server.log.WithField("err", err).Error("handling record")
}
if _, err := conn.WriteToUDP(reply.Bytes(), callerAddr); err != nil {
s.server.log.WithFields(logrus.Fields{
"callerAddr": callerAddr.String(),
"err": err,
}).Error("Cannot send reply over UDP")
return
}
}