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