-
Notifications
You must be signed in to change notification settings - Fork 0
/
conn.go
166 lines (139 loc) · 3.49 KB
/
conn.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package netutil
import (
"context"
"crypto/tls"
"net"
"net/url"
"os"
"strconv"
"strings"
"github.com/pubgo/funk/assert"
"github.com/pubgo/funk/recovery"
)
type sockOpts struct {
path string
cfgCallback func(lc *net.ListenConfig)
}
// SockOpt sets up socket file's creating option
type SockOpt func(opts *sockOpts) error
func Listen(address string, opts ...SockOpt) (_ net.Listener, err error) {
defer recovery.Err(&err)
if !strings.Contains(address, "//") {
address = "tcp4://" + address
}
uri := assert.Must1(url.Parse(address))
if uri.Scheme == "" {
uri.Scheme = "tcp4"
}
var sOpts sockOpts
for i := range opts {
assert.Must(opts[i](&sOpts))
}
var lc net.ListenConfig
if cb := sOpts.cfgCallback; cb != nil {
cb(&lc)
}
return lc.Listen(context.Background(), uri.Scheme, uri.Host)
}
func ListenPacket(address string, opts ...SockOpt) (_ net.PacketConn, err error) {
defer recovery.Err(&err)
uri := assert.Must1(url.Parse(address))
if uri.Scheme == "" {
uri.Scheme = "udp4"
}
var sOpts sockOpts
for i := range opts {
assert.Must(opts[i](&sOpts))
}
var lc net.ListenConfig
if cb := sOpts.cfgCallback; cb != nil {
cb(&lc)
}
return lc.ListenPacket(context.Background(), uri.Scheme, uri.Host)
}
// NewTCPSocket creates a TCP socket listener with the specified address and
// the specified tls configuration. If tlsConfig is set, will encapsulate the
// TCP listener inside a TLS one.
func NewTCPSocket(addr string, tlsConfig *tls.Config) (net.Listener, error) {
l, err := net.Listen("tcp", addr)
if err != nil {
return nil, err
}
if tlsConfig != nil {
tlsConfig.NextProtos = []string{"http/1.1"}
l = tls.NewListener(l, tlsConfig)
}
return l, nil
}
// WithChown modifies the socket file's uid and gid
func WithChown(uid, gid int) SockOpt {
return func(opts *sockOpts) error {
if err := os.Chown(opts.path, uid, gid); err != nil {
return err
}
return nil
}
}
func WithNetCfg(fn func(lc *net.ListenConfig)) SockOpt {
return func(opts *sockOpts) error {
opts.cfgCallback = fn
return nil
}
}
// WithChmod modifies socket file's access mode
func WithChmod(mask os.FileMode) SockOpt {
return func(opts *sockOpts) error {
if err := os.Chmod(opts.path, mask); err != nil {
return err
}
return nil
}
}
func MustGetPort(addrOrNet interface{}) int {
return assert.Must1(GetPort(addrOrNet))
}
// GetPort returns the port of an endpoint address.
func GetPort(addrOrNet interface{}) (int, error) {
var addr string
switch addrNet := addrOrNet.(type) {
case net.Addr:
addr = addrNet.String()
case string:
addr = addrNet
}
_, port, err := net.SplitHostPort(addr)
if err != nil {
return -1, err
}
parsedPort, err := strconv.Atoi(port)
if err != nil {
return -1, err
}
return parsedPort, nil
}
// NewUnixSocketWithOpts creates a unix socket with the specified options
//func NewUnixSocketWithOpts(path string, opts ...SockOpt) (net.Listener, error) {
// if err := syscall.Unlink(path); err != nil && !os.IsNotExist(err) {
// return nil, err
// }
// mask := syscall.Umask(0777)
// defer syscall.Umask(mask)
//
// l, err := net.Listen("unix", path)
// if err != nil {
// return nil, err
// }
//
// for _, op := range opts {
// if err := op(path); err != nil {
// l.Close()
// return nil, err
// }
// }
//
// return l, nil
//}
// NewUnixSocket creates a unix socket with the specified path and group.
//func NewUnixSocket(path string, gid int) (net.Listener, error) {
// return NewUnixSocketWithOpts(path, WithChown(0, gid), WithChmod(0660))
//}