-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathunix.go
129 lines (109 loc) · 3.5 KB
/
unix.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"
"os"
"path/filepath"
ulid "github.com/imdario/go-ulid"
"github.com/pkg/errors"
)
type unixConn interface {
net.Conn
netWriter
ReadFromUnix([]byte) (int, *net.UnixAddr, error)
}
// UnixConn handles OSC over a unix socket.
type UnixConn struct {
unixConn
closeChan chan struct{}
ctx context.Context
errChan chan error
exactMatch bool
}
// DialUnix opens a unix socket for OSC communication.
func DialUnix(network string, laddr, raddr *net.UnixAddr) (*UnixConn, error) {
return DialUnixContext(context.Background(), network, laddr, raddr)
}
// DialUnixContext creates a new UnixConn.
func DialUnixContext(ctx context.Context, network string, laddr, raddr *net.UnixAddr) (*UnixConn, error) {
conn, err := net.DialUnix(network, laddr, raddr)
if err != nil {
return nil, err
}
uc := &UnixConn{
unixConn: conn,
closeChan: make(chan struct{}),
ctx: ctx,
errChan: make(chan error),
}
return uc.initialize()
}
// ListenUnix creates a Unix listener that can be canceled with the provided context.
func ListenUnix(network string, laddr *net.UnixAddr) (*UnixConn, error) {
return ListenUnixContext(context.Background(), network, laddr)
}
// ListenUnixContext creates a Unix listener that can be canceled with the provided context.
func ListenUnixContext(ctx context.Context, network string, laddr *net.UnixAddr) (*UnixConn, error) {
conn, err := net.ListenUnixgram(network, laddr)
if err != nil {
return nil, err
}
uc := &UnixConn{
unixConn: conn,
closeChan: make(chan struct{}),
ctx: ctx,
errChan: make(chan error),
}
return uc.initialize()
}
// Close closes the connection.
func (conn *UnixConn) Close() error {
close(conn.closeChan)
return conn.unixConn.Close()
}
// CloseChan returns a channel that is closed when the connection gets closed.
func (conn *UnixConn) CloseChan() <-chan struct{} {
return conn.closeChan
}
// Context returns the context for the unix conn.
func (conn *UnixConn) Context() context.Context {
return conn.ctx
}
// initialize initializes the connection.
func (conn *UnixConn) initialize() (*UnixConn, error) {
if err := conn.unixConn.SetWriteBuffer(bufSize); err != nil {
return nil, errors.Wrap(err, "setting write buffer size")
}
return conn, nil
}
func (conn *UnixConn) read(data []byte) (int, net.Addr, error) {
return conn.ReadFromUnix(data)
}
// Send sends a Packet.
func (conn *UnixConn) Send(p Packet) error {
_, err := conn.Write(p.Bytes())
return err
}
// SendTo sends a Packet to the provided net.Addr.
func (conn *UnixConn) 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 *UnixConn) Serve(numWorkers int, dispatcher Dispatcher) error {
return serve(conn, numWorkers, conn.exactMatch, dispatcher)
}
// TempSocket creates an absolute path to a temporary socket file.
func TempSocket() string {
return filepath.Join(os.TempDir(), ulid.New().String()) + ".sock"
}
// 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 *UnixConn) SetExactMatch(value bool) {
conn.exactMatch = value
}