-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathudp.go
129 lines (108 loc) · 3.51 KB
/
udp.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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package osc
import (
"context"
"net"
"github.com/pkg/errors"
)
// udpConn includes exactly the methods we need from *net.UDPConn
type udpConn interface {
net.Conn
netWriter
ReadFromUDP([]byte) (int, *net.UDPAddr, error)
}
// UDPConn is an OSC connection over UDP.
type UDPConn struct {
udpConn
closeChan chan struct{}
ctx context.Context
errChan chan error
exactMatch bool
}
// DialUDP creates a new OSC connection over UDP.
func DialUDP(network string, laddr, raddr *net.UDPAddr) (Conn, error) {
return DialUDPContext(context.Background(), network, laddr, raddr)
}
// DialUDPContext returns a new OSC connection over UDP that can be canceled with the provided context.
func DialUDPContext(ctx context.Context, network string, laddr, raddr *net.UDPAddr) (*UDPConn, error) {
conn, err := net.DialUDP(network, laddr, raddr)
if err != nil {
return nil, err
}
uc := &UDPConn{
udpConn: conn,
closeChan: make(chan struct{}),
ctx: ctx,
errChan: make(chan error),
}
return uc.initialize()
}
// ListenUDP creates a new UDP server.
func ListenUDP(network string, laddr *net.UDPAddr) (*UDPConn, error) {
return ListenUDPContext(context.Background(), network, laddr)
}
// ListenUDPContext creates a UDP listener that can be canceled with the provided context.
func ListenUDPContext(ctx context.Context, network string, laddr *net.UDPAddr) (*UDPConn, error) {
conn, err := net.ListenUDP(network, laddr)
if err != nil {
return nil, err
}
uc := &UDPConn{
udpConn: conn,
closeChan: make(chan struct{}),
ctx: ctx,
errChan: make(chan error),
}
return uc.initialize()
}
// Close closes the udp conn.
func (conn *UDPConn) Close() error {
close(conn.closeChan)
return conn.udpConn.Close()
}
// CloseChan returns a channel that is closed when the connection gets closed.
func (conn *UDPConn) CloseChan() <-chan struct{} {
return conn.closeChan
}
// Context returns the context associated with the conn.
func (conn *UDPConn) Context() context.Context {
return conn.ctx
}
// initialize initializes a UDP connection.
func (conn *UDPConn) initialize() (*UDPConn, error) {
if err := conn.udpConn.SetWriteBuffer(bufSize); err != nil {
return nil, errors.Wrap(err, "setting write buffer size")
}
return conn, nil
}
// read reads bytes and returns the net.Addr of the sender.
func (conn *UDPConn) read(data []byte) (int, net.Addr, error) {
return conn.ReadFromUDP(data)
}
// Send sends an OSC message over UDP.
func (conn *UDPConn) Send(p Packet) error {
_, err := conn.Write(p.Bytes())
return err
}
// SendTo sends a packet to the given address.
func (conn *UDPConn) SendTo(addr net.Addr, p Packet) error {
_, err := conn.WriteTo(p.Bytes(), addr)
return err
}
// Serve starts dispatching OSC.
// Any errors returned from a dispatched method will be returned.
// Note that this means that errors returned from a dispatcher method will kill your server.
// If context.Canceled or context.DeadlineExceeded are encountered they will be returned directly.
func (conn *UDPConn) Serve(numWorkers int, dispatcher Dispatcher) error {
return serve(conn, numWorkers, conn.exactMatch, dispatcher)
}
// SetContext sets the context associated with the conn.
func (conn *UDPConn) SetContext(ctx context.Context) {
conn.ctx = ctx
}
// SetExactMatch changes the behavior of the Serve method so that
// messages will only be dispatched to methods whose addresses
// match the message's address exactly.
// This should provide some performance improvement.
func (conn *UDPConn) SetExactMatch(value bool) {
conn.exactMatch = value
}