Source file
src/net/sock_posix.go
1
2
3
4
5
6
7 package net
8
9 import (
10 "context"
11 "internal/poll"
12 "os"
13 "syscall"
14 )
15
16
17
18 func socket(ctx context.Context, net string, family, sotype, proto int, ipv6only bool, laddr, raddr sockaddr, ctrlCtxFn func(context.Context, string, string, syscall.RawConn) error) (fd *netFD, err error) {
19 s, err := sysSocket(family, sotype, proto)
20 if err != nil {
21 return nil, err
22 }
23 if err = setDefaultSockopts(s, family, sotype, ipv6only); err != nil {
24 poll.CloseFunc(s)
25 return nil, err
26 }
27 if fd, err = newFD(s, family, sotype, net); err != nil {
28 poll.CloseFunc(s)
29 return nil, err
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 if laddr != nil && raddr == nil {
55 switch sotype {
56 case syscall.SOCK_STREAM, syscall.SOCK_SEQPACKET:
57 if err := fd.listenStream(ctx, laddr, listenerBacklog(), ctrlCtxFn); err != nil {
58 fd.Close()
59 return nil, err
60 }
61 return fd, nil
62 case syscall.SOCK_DGRAM:
63 if err := fd.listenDatagram(ctx, laddr, ctrlCtxFn); err != nil {
64 fd.Close()
65 return nil, err
66 }
67 return fd, nil
68 }
69 }
70 if err := fd.dial(ctx, laddr, raddr, ctrlCtxFn); err != nil {
71 fd.Close()
72 return nil, err
73 }
74 return fd, nil
75 }
76
77 func (fd *netFD) ctrlNetwork() string {
78 switch fd.net {
79 case "unix", "unixgram", "unixpacket":
80 return fd.net
81 }
82 switch fd.net[len(fd.net)-1] {
83 case '4', '6':
84 return fd.net
85 }
86 if fd.family == syscall.AF_INET {
87 return fd.net + "4"
88 }
89 return fd.net + "6"
90 }
91
92 func (fd *netFD) addrFunc() func(syscall.Sockaddr) Addr {
93 switch fd.family {
94 case syscall.AF_INET, syscall.AF_INET6:
95 switch fd.sotype {
96 case syscall.SOCK_STREAM:
97 return sockaddrToTCP
98 case syscall.SOCK_DGRAM:
99 return sockaddrToUDP
100 case syscall.SOCK_RAW:
101 return sockaddrToIP
102 }
103 case syscall.AF_UNIX:
104 switch fd.sotype {
105 case syscall.SOCK_STREAM:
106 return sockaddrToUnix
107 case syscall.SOCK_DGRAM:
108 return sockaddrToUnixgram
109 case syscall.SOCK_SEQPACKET:
110 return sockaddrToUnixpacket
111 }
112 }
113 return func(syscall.Sockaddr) Addr { return nil }
114 }
115
116 func (fd *netFD) dial(ctx context.Context, laddr, raddr sockaddr, ctrlCtxFn func(context.Context, string, string, syscall.RawConn) error) error {
117 var c *rawConn
118 var err error
119 if ctrlCtxFn != nil {
120 c, err = newRawConn(fd)
121 if err != nil {
122 return err
123 }
124 var ctrlAddr string
125 if raddr != nil {
126 ctrlAddr = raddr.String()
127 } else if laddr != nil {
128 ctrlAddr = laddr.String()
129 }
130 if err := ctrlCtxFn(ctx, fd.ctrlNetwork(), ctrlAddr, c); err != nil {
131 return err
132 }
133 }
134
135 var lsa syscall.Sockaddr
136 if laddr != nil {
137 if lsa, err = laddr.sockaddr(fd.family); err != nil {
138 return err
139 } else if lsa != nil {
140 if err = syscall.Bind(fd.pfd.Sysfd, lsa); err != nil {
141 return os.NewSyscallError("bind", err)
142 }
143 }
144 }
145 var rsa syscall.Sockaddr
146 var crsa syscall.Sockaddr
147 if raddr != nil {
148 if rsa, err = raddr.sockaddr(fd.family); err != nil {
149 return err
150 }
151 if crsa, err = fd.connect(ctx, lsa, rsa); err != nil {
152 return err
153 }
154 fd.isConnected = true
155 } else {
156 if err := fd.init(); err != nil {
157 return err
158 }
159 }
160
161
162
163
164
165
166 lsa, _ = syscall.Getsockname(fd.pfd.Sysfd)
167 if crsa != nil {
168 fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(crsa))
169 } else if rsa, _ = syscall.Getpeername(fd.pfd.Sysfd); rsa != nil {
170 fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(rsa))
171 } else {
172 fd.setAddr(fd.addrFunc()(lsa), raddr)
173 }
174 return nil
175 }
176
177 func (fd *netFD) listenStream(ctx context.Context, laddr sockaddr, backlog int, ctrlCtxFn func(context.Context, string, string, syscall.RawConn) error) error {
178 var err error
179 if err = setDefaultListenerSockopts(fd.pfd.Sysfd); err != nil {
180 return err
181 }
182 var lsa syscall.Sockaddr
183 if lsa, err = laddr.sockaddr(fd.family); err != nil {
184 return err
185 }
186
187 if ctrlCtxFn != nil {
188 c, err := newRawConn(fd)
189 if err != nil {
190 return err
191 }
192 if err := ctrlCtxFn(ctx, fd.ctrlNetwork(), laddr.String(), c); err != nil {
193 return err
194 }
195 }
196
197 if err = syscall.Bind(fd.pfd.Sysfd, lsa); err != nil {
198 return os.NewSyscallError("bind", err)
199 }
200 if err = listenFunc(fd.pfd.Sysfd, backlog); err != nil {
201 return os.NewSyscallError("listen", err)
202 }
203 if err = fd.init(); err != nil {
204 return err
205 }
206 lsa, _ = syscall.Getsockname(fd.pfd.Sysfd)
207 fd.setAddr(fd.addrFunc()(lsa), nil)
208 return nil
209 }
210
211 func (fd *netFD) listenDatagram(ctx context.Context, laddr sockaddr, ctrlCtxFn func(context.Context, string, string, syscall.RawConn) error) error {
212 switch addr := laddr.(type) {
213 case *UDPAddr:
214
215
216
217
218
219
220
221 if addr.IP != nil && addr.IP.IsMulticast() {
222 if err := setDefaultMulticastSockopts(fd.pfd.Sysfd); err != nil {
223 return err
224 }
225 addr := *addr
226 switch fd.family {
227 case syscall.AF_INET:
228 addr.IP = IPv4zero
229 case syscall.AF_INET6:
230 addr.IP = IPv6unspecified
231 }
232 laddr = &addr
233 }
234 }
235 var err error
236 var lsa syscall.Sockaddr
237 if lsa, err = laddr.sockaddr(fd.family); err != nil {
238 return err
239 }
240
241 if ctrlCtxFn != nil {
242 c, err := newRawConn(fd)
243 if err != nil {
244 return err
245 }
246 if err := ctrlCtxFn(ctx, fd.ctrlNetwork(), laddr.String(), c); err != nil {
247 return err
248 }
249 }
250 if err = syscall.Bind(fd.pfd.Sysfd, lsa); err != nil {
251 return os.NewSyscallError("bind", err)
252 }
253 if err = fd.init(); err != nil {
254 return err
255 }
256 lsa, _ = syscall.Getsockname(fd.pfd.Sysfd)
257 fd.setAddr(fd.addrFunc()(lsa), nil)
258 return nil
259 }
260
View as plain text