Source file
src/net/tcpsock.go
1
2
3
4
5 package net
6
7 import (
8 "context"
9 "internal/itoa"
10 "io"
11 "net/netip"
12 "os"
13 "syscall"
14 "time"
15 )
16
17
18
19
20
21 type TCPAddr struct {
22 IP IP
23 Port int
24 Zone string
25 }
26
27
28
29
30
31
32 func (a *TCPAddr) AddrPort() netip.AddrPort {
33 if a == nil {
34 return netip.AddrPort{}
35 }
36 na, _ := netip.AddrFromSlice(a.IP)
37 na = na.WithZone(a.Zone)
38 return netip.AddrPortFrom(na, uint16(a.Port))
39 }
40
41
42 func (a *TCPAddr) Network() string { return "tcp" }
43
44 func (a *TCPAddr) String() string {
45 if a == nil {
46 return "<nil>"
47 }
48 ip := ipEmptyString(a.IP)
49 if a.Zone != "" {
50 return JoinHostPort(ip+"%"+a.Zone, itoa.Itoa(a.Port))
51 }
52 return JoinHostPort(ip, itoa.Itoa(a.Port))
53 }
54
55 func (a *TCPAddr) isWildcard() bool {
56 if a == nil || a.IP == nil {
57 return true
58 }
59 return a.IP.IsUnspecified()
60 }
61
62 func (a *TCPAddr) opAddr() Addr {
63 if a == nil {
64 return nil
65 }
66 return a
67 }
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 func ResolveTCPAddr(network, address string) (*TCPAddr, error) {
85 switch network {
86 case "tcp", "tcp4", "tcp6":
87 case "":
88 network = "tcp"
89 default:
90 return nil, UnknownNetworkError(network)
91 }
92 addrs, err := DefaultResolver.internetAddrList(context.Background(), network, address)
93 if err != nil {
94 return nil, err
95 }
96 return addrs.forResolve(network, address).(*TCPAddr), nil
97 }
98
99
100
101
102 func TCPAddrFromAddrPort(addr netip.AddrPort) *TCPAddr {
103 return &TCPAddr{
104 IP: addr.Addr().AsSlice(),
105 Zone: addr.Addr().Zone(),
106 Port: int(addr.Port()),
107 }
108 }
109
110
111
112 type TCPConn struct {
113 conn
114 }
115
116
117
118 func (c *TCPConn) SyscallConn() (syscall.RawConn, error) {
119 if !c.ok() {
120 return nil, syscall.EINVAL
121 }
122 return newRawConn(c.fd)
123 }
124
125
126 func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {
127 if !c.ok() {
128 return 0, syscall.EINVAL
129 }
130 n, err := c.readFrom(r)
131 if err != nil && err != io.EOF {
132 err = &OpError{Op: "readfrom", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
133 }
134 return n, err
135 }
136
137
138
139 func (c *TCPConn) CloseRead() error {
140 if !c.ok() {
141 return syscall.EINVAL
142 }
143 if err := c.fd.closeRead(); err != nil {
144 return &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
145 }
146 return nil
147 }
148
149
150
151 func (c *TCPConn) CloseWrite() error {
152 if !c.ok() {
153 return syscall.EINVAL
154 }
155 if err := c.fd.closeWrite(); err != nil {
156 return &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
157 }
158 return nil
159 }
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175 func (c *TCPConn) SetLinger(sec int) error {
176 if !c.ok() {
177 return syscall.EINVAL
178 }
179 if err := setLinger(c.fd, sec); err != nil {
180 return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
181 }
182 return nil
183 }
184
185
186
187 func (c *TCPConn) SetKeepAlive(keepalive bool) error {
188 if !c.ok() {
189 return syscall.EINVAL
190 }
191 if err := setKeepAlive(c.fd, keepalive); err != nil {
192 return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
193 }
194 return nil
195 }
196
197
198 func (c *TCPConn) SetKeepAlivePeriod(d time.Duration) error {
199 if !c.ok() {
200 return syscall.EINVAL
201 }
202 if err := setKeepAlivePeriod(c.fd, d); err != nil {
203 return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
204 }
205 return nil
206 }
207
208
209
210
211
212 func (c *TCPConn) SetNoDelay(noDelay bool) error {
213 if !c.ok() {
214 return syscall.EINVAL
215 }
216 if err := setNoDelay(c.fd, noDelay); err != nil {
217 return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
218 }
219 return nil
220 }
221
222
223
224
225
226
227
228
229
230
231 func (c *TCPConn) MultipathTCP() (bool, error) {
232 if !c.ok() {
233 return false, syscall.EINVAL
234 }
235 return isUsingMultipathTCP(c.fd), nil
236 }
237
238 func newTCPConn(fd *netFD, keepAlive time.Duration, keepAliveHook func(time.Duration)) *TCPConn {
239 setNoDelay(fd, true)
240 if keepAlive == 0 {
241 keepAlive = defaultTCPKeepAlive
242 }
243 if keepAlive > 0 {
244 setKeepAlive(fd, true)
245 setKeepAlivePeriod(fd, keepAlive)
246 if keepAliveHook != nil {
247 keepAliveHook(keepAlive)
248 }
249 }
250 return &TCPConn{conn{fd}}
251 }
252
253
254
255
256
257
258
259
260 func DialTCP(network string, laddr, raddr *TCPAddr) (*TCPConn, error) {
261 switch network {
262 case "tcp", "tcp4", "tcp6":
263 default:
264 return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: UnknownNetworkError(network)}
265 }
266 if raddr == nil {
267 return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: nil, Err: errMissingAddress}
268 }
269 sd := &sysDialer{network: network, address: raddr.String()}
270 c, err := sd.dialTCP(context.Background(), laddr, raddr)
271 if err != nil {
272 return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
273 }
274 return c, nil
275 }
276
277
278
279 type TCPListener struct {
280 fd *netFD
281 lc ListenConfig
282 }
283
284
285
286
287
288
289 func (l *TCPListener) SyscallConn() (syscall.RawConn, error) {
290 if !l.ok() {
291 return nil, syscall.EINVAL
292 }
293 return newRawListener(l.fd)
294 }
295
296
297
298 func (l *TCPListener) AcceptTCP() (*TCPConn, error) {
299 if !l.ok() {
300 return nil, syscall.EINVAL
301 }
302 c, err := l.accept()
303 if err != nil {
304 return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
305 }
306 return c, nil
307 }
308
309
310
311 func (l *TCPListener) Accept() (Conn, error) {
312 if !l.ok() {
313 return nil, syscall.EINVAL
314 }
315 c, err := l.accept()
316 if err != nil {
317 return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
318 }
319 return c, nil
320 }
321
322
323
324 func (l *TCPListener) Close() error {
325 if !l.ok() {
326 return syscall.EINVAL
327 }
328 if err := l.close(); err != nil {
329 return &OpError{Op: "close", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
330 }
331 return nil
332 }
333
334
335
336
337 func (l *TCPListener) Addr() Addr { return l.fd.laddr }
338
339
340
341 func (l *TCPListener) SetDeadline(t time.Time) error {
342 if !l.ok() {
343 return syscall.EINVAL
344 }
345 if err := l.fd.pfd.SetDeadline(t); err != nil {
346 return &OpError{Op: "set", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
347 }
348 return nil
349 }
350
351
352
353
354
355
356
357
358 func (l *TCPListener) File() (f *os.File, err error) {
359 if !l.ok() {
360 return nil, syscall.EINVAL
361 }
362 f, err = l.file()
363 if err != nil {
364 return nil, &OpError{Op: "file", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
365 }
366 return
367 }
368
369
370
371
372
373
374
375
376
377
378 func ListenTCP(network string, laddr *TCPAddr) (*TCPListener, error) {
379 switch network {
380 case "tcp", "tcp4", "tcp6":
381 default:
382 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(network)}
383 }
384 if laddr == nil {
385 laddr = &TCPAddr{}
386 }
387 sl := &sysListener{network: network, address: laddr.String()}
388 ln, err := sl.listenTCP(context.Background(), laddr)
389 if err != nil {
390 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: err}
391 }
392 return ln, nil
393 }
394
395
396 func roundDurationUp(d time.Duration, to time.Duration) time.Duration {
397 return (d + to - 1) / to
398 }
399
View as plain text