Source file src/net/net.go
1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 /* 6 Package net provides a portable interface for network I/O, including 7 TCP/IP, UDP, domain name resolution, and Unix domain sockets. 8 9 Although the package provides access to low-level networking 10 primitives, most clients will need only the basic interface provided 11 by the [Dial], [Listen], and Accept functions and the associated 12 [Conn] and [Listener] interfaces. The crypto/tls package uses 13 the same interfaces and similar Dial and Listen functions. 14 15 The Dial function connects to a server: 16 17 conn, err := net.Dial("tcp", "golang.org:80") 18 if err != nil { 19 // handle error 20 } 21 fmt.Fprintf(conn, "GET / HTTP/1.0\r\n\r\n") 22 status, err := bufio.NewReader(conn).ReadString('\n') 23 // ... 24 25 The Listen function creates servers: 26 27 ln, err := net.Listen("tcp", ":8080") 28 if err != nil { 29 // handle error 30 } 31 for { 32 conn, err := ln.Accept() 33 if err != nil { 34 // handle error 35 } 36 go handleConnection(conn) 37 } 38 39 # Name Resolution 40 41 The method for resolving domain names, whether indirectly with functions like Dial 42 or directly with functions like [LookupHost] and [LookupAddr], varies by operating system. 43 44 On Unix systems, the resolver has two options for resolving names. 45 It can use a pure Go resolver that sends DNS requests directly to the servers 46 listed in /etc/resolv.conf, or it can use a cgo-based resolver that calls C 47 library routines such as getaddrinfo and getnameinfo. 48 49 On Unix the pure Go resolver is preferred over the cgo resolver, because a blocked DNS 50 request consumes only a goroutine, while a blocked C call consumes an operating system thread. 51 When cgo is available, the cgo-based resolver is used instead under a variety of 52 conditions: on systems that do not let programs make direct DNS requests (OS X), 53 when the LOCALDOMAIN environment variable is present (even if empty), 54 when the RES_OPTIONS or HOSTALIASES environment variable is non-empty, 55 when the ASR_CONFIG environment variable is non-empty (OpenBSD only), 56 when /etc/resolv.conf or /etc/nsswitch.conf specify the use of features that the 57 Go resolver does not implement. 58 59 On all systems (except Plan 9), when the cgo resolver is being used 60 this package applies a concurrent cgo lookup limit to prevent the system 61 from running out of system threads. Currently, it is limited to 500 concurrent lookups. 62 63 The resolver decision can be overridden by setting the netdns value of the 64 GODEBUG environment variable (see package runtime) to go or cgo, as in: 65 66 export GODEBUG=netdns=go # force pure Go resolver 67 export GODEBUG=netdns=cgo # force native resolver (cgo, win32) 68 69 The decision can also be forced while building the Go source tree 70 by setting the netgo or netcgo build tag. 71 72 A numeric netdns setting, as in GODEBUG=netdns=1, causes the resolver 73 to print debugging information about its decisions. 74 To force a particular resolver while also printing debugging information, 75 join the two settings by a plus sign, as in GODEBUG=netdns=go+1. 76 77 On macOS, if Go code that uses the net package is built with 78 -buildmode=c-archive, linking the resulting archive into a C program 79 requires passing -lresolv when linking the C code. 80 81 On Plan 9, the resolver always accesses /net/cs and /net/dns. 82 83 On Windows, in Go 1.18.x and earlier, the resolver always used C 84 library functions, such as GetAddrInfo and DnsQuery. 85 */ 86 package net 87 88 import ( 89 "context" 90 "errors" 91 "internal/poll" 92 "io" 93 "os" 94 "sync" 95 "syscall" 96 "time" 97 ) 98 99 // Addr represents a network end point address. 100 // 101 // The two methods [Addr.Network] and [Addr.String] conventionally return strings 102 // that can be passed as the arguments to [Dial], but the exact form 103 // and meaning of the strings is up to the implementation. 104 type Addr interface { 105 Network() string // name of the network (for example, "tcp", "udp") 106 String() string // string form of address (for example, "192.0.2.1:25", "[2001:db8::1]:80") 107 } 108 109 // Conn is a generic stream-oriented network connection. 110 // 111 // Multiple goroutines may invoke methods on a Conn simultaneously. 112 type Conn interface { 113 // Read reads data from the connection. 114 // Read can be made to time out and return an error after a fixed 115 // time limit; see SetDeadline and SetReadDeadline. 116 Read(b []byte) (n int, err error) 117 118 // Write writes data to the connection. 119 // Write can be made to time out and return an error after a fixed 120 // time limit; see SetDeadline and SetWriteDeadline. 121 Write(b []byte) (n int, err error) 122 123 // Close closes the connection. 124 // Any blocked Read or Write operations will be unblocked and return errors. 125 Close() error 126 127 // LocalAddr returns the local network address, if known. 128 LocalAddr() Addr 129 130 // RemoteAddr returns the remote network address, if known. 131 RemoteAddr() Addr 132 133 // SetDeadline sets the read and write deadlines associated 134 // with the connection. It is equivalent to calling both 135 // SetReadDeadline and SetWriteDeadline. 136 // 137 // A deadline is an absolute time after which I/O operations 138 // fail instead of blocking. The deadline applies to all future 139 // and pending I/O, not just the immediately following call to 140 // Read or Write. After a deadline has been exceeded, the 141 // connection can be refreshed by setting a deadline in the future. 142 // 143 // If the deadline is exceeded a call to Read or Write or to other 144 // I/O methods will return an error that wraps os.ErrDeadlineExceeded. 145 // This can be tested using errors.Is(err, os.ErrDeadlineExceeded). 146 // The error's Timeout method will return true, but note that there 147 // are other possible errors for which the Timeout method will 148 // return true even if the deadline has not been exceeded. 149 // 150 // An idle timeout can be implemented by repeatedly extending 151 // the deadline after successful Read or Write calls. 152 // 153 // A zero value for t means I/O operations will not time out. 154 SetDeadline(t time.Time) error 155 156 // SetReadDeadline sets the deadline for future Read calls 157 // and any currently-blocked Read call. 158 // A zero value for t means Read will not time out. 159 SetReadDeadline(t time.Time) error 160 161 // SetWriteDeadline sets the deadline for future Write calls 162 // and any currently-blocked Write call. 163 // Even if write times out, it may return n > 0, indicating that 164 // some of the data was successfully written. 165 // A zero value for t means Write will not time out. 166 SetWriteDeadline(t time.Time) error 167 } 168 169 type conn struct { 170 fd *netFD 171 } 172 173 func (c *conn) ok() bool { return c != nil && c.fd != nil } 174 175 // Implementation of the Conn interface. 176 177 // Read implements the Conn Read method. 178 func (c *conn) Read(b []byte) (int, error) { 179 if !c.ok() { 180 return 0, syscall.EINVAL 181 } 182 n, err := c.fd.Read(b) 183 if err != nil && err != io.EOF { 184 err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} 185 } 186 return n, err 187 } 188 189 // Write implements the Conn Write method. 190 func (c *conn) Write(b []byte) (int, error) { 191 if !c.ok() { 192 return 0, syscall.EINVAL 193 } 194 n, err := c.fd.Write(b) 195 if err != nil { 196 err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} 197 } 198 return n, err 199 } 200 201 // Close closes the connection. 202 func (c *conn) Close() error { 203 if !c.ok() { 204 return syscall.EINVAL 205 } 206 err := c.fd.Close() 207 if err != nil { 208 err = &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} 209 } 210 return err 211 } 212 213 // LocalAddr returns the local network address. 214 // The Addr returned is shared by all invocations of LocalAddr, so 215 // do not modify it. 216 func (c *conn) LocalAddr() Addr { 217 if !c.ok() { 218 return nil 219 } 220 return c.fd.laddr 221 } 222 223 // RemoteAddr returns the remote network address. 224 // The Addr returned is shared by all invocations of RemoteAddr, so 225 // do not modify it. 226 func (c *conn) RemoteAddr() Addr { 227 if !c.ok() { 228 return nil 229 } 230 return c.fd.raddr 231 } 232 233 // SetDeadline implements the Conn SetDeadline method. 234 func (c *conn) SetDeadline(t time.Time) error { 235 if !c.ok() { 236 return syscall.EINVAL 237 } 238 if err := c.fd.SetDeadline(t); err != nil { 239 return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err} 240 } 241 return nil 242 } 243 244 // SetReadDeadline implements the Conn SetReadDeadline method. 245 func (c *conn) SetReadDeadline(t time.Time) error { 246 if !c.ok() { 247 return syscall.EINVAL 248 } 249 if err := c.fd.SetReadDeadline(t); err != nil { 250 return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err} 251 } 252 return nil 253 } 254 255 // SetWriteDeadline implements the Conn SetWriteDeadline method. 256 func (c *conn) SetWriteDeadline(t time.Time) error { 257 if !c.ok() { 258 return syscall.EINVAL 259 } 260 if err := c.fd.SetWriteDeadline(t); err != nil { 261 return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err} 262 } 263 return nil 264 } 265 266 // SetReadBuffer sets the size of the operating system's 267 // receive buffer associated with the connection. 268 func (c *conn) SetReadBuffer(bytes int) error { 269 if !c.ok() { 270 return syscall.EINVAL 271 } 272 if err := setReadBuffer(c.fd, bytes); err != nil { 273 return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err} 274 } 275 return nil 276 } 277 278 // SetWriteBuffer sets the size of the operating system's 279 // transmit buffer associated with the connection. 280 func (c *conn) SetWriteBuffer(bytes int) error { 281 if !c.ok() { 282 return syscall.EINVAL 283 } 284 if err := setWriteBuffer(c.fd, bytes); err != nil { 285 return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err} 286 } 287 return nil 288 } 289 290 // File returns a copy of the underlying [os.File]. 291 // It is the caller's responsibility to close f when finished. 292 // Closing c does not affect f, and closing f does not affect c. 293 // 294 // The returned os.File's file descriptor is different from the connection's. 295 // Attempting to change properties of the original using this duplicate 296 // may or may not have the desired effect. 297 func (c *conn) File() (f *os.File, err error) { 298 f, err = c.fd.dup() 299 if err != nil { 300 err = &OpError{Op: "file", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} 301 } 302 return 303 } 304 305 // PacketConn is a generic packet-oriented network connection. 306 // 307 // Multiple goroutines may invoke methods on a PacketConn simultaneously. 308 type PacketConn interface { 309 // ReadFrom reads a packet from the connection, 310 // copying the payload into p. It returns the number of 311 // bytes copied into p and the return address that 312 // was on the packet. 313 // It returns the number of bytes read (0 <= n <= len(p)) 314 // and any error encountered. Callers should always process 315 // the n > 0 bytes returned before considering the error err. 316 // ReadFrom can be made to time out and return an error after a 317 // fixed time limit; see SetDeadline and SetReadDeadline. 318 ReadFrom(p []byte) (n int, addr Addr, err error) 319 320 // WriteTo writes a packet with payload p to addr. 321 // WriteTo can be made to time out and return an Error after a 322 // fixed time limit; see SetDeadline and SetWriteDeadline. 323 // On packet-oriented connections, write timeouts are rare. 324 WriteTo(p []byte, addr Addr) (n int, err error) 325 326 // Close closes the connection. 327 // Any blocked ReadFrom or WriteTo operations will be unblocked and return errors. 328 Close() error 329 330 // LocalAddr returns the local network address, if known. 331 LocalAddr() Addr 332 333 // SetDeadline sets the read and write deadlines associated 334 // with the connection. It is equivalent to calling both 335 // SetReadDeadline and SetWriteDeadline. 336 // 337 // A deadline is an absolute time after which I/O operations 338 // fail instead of blocking. The deadline applies to all future 339 // and pending I/O, not just the immediately following call to 340 // Read or Write. After a deadline has been exceeded, the 341 // connection can be refreshed by setting a deadline in the future. 342 // 343 // If the deadline is exceeded a call to Read or Write or to other 344 // I/O methods will return an error that wraps os.ErrDeadlineExceeded. 345 // This can be tested using errors.Is(err, os.ErrDeadlineExceeded). 346 // The error's Timeout method will return true, but note that there 347 // are other possible errors for which the Timeout method will 348 // return true even if the deadline has not been exceeded. 349 // 350 // An idle timeout can be implemented by repeatedly extending 351 // the deadline after successful ReadFrom or WriteTo calls. 352 // 353 // A zero value for t means I/O operations will not time out. 354 SetDeadline(t time.Time) error 355 356 // SetReadDeadline sets the deadline for future ReadFrom calls 357 // and any currently-blocked ReadFrom call. 358 // A zero value for t means ReadFrom will not time out. 359 SetReadDeadline(t time.Time) error 360 361 // SetWriteDeadline sets the deadline for future WriteTo calls 362 // and any currently-blocked WriteTo call. 363 // Even if write times out, it may return n > 0, indicating that 364 // some of the data was successfully written. 365 // A zero value for t means WriteTo will not time out. 366 SetWriteDeadline(t time.Time) error 367 } 368 369 var listenerBacklogCache struct { 370 sync.Once 371 val int 372 } 373 374 // listenerBacklog is a caching wrapper around maxListenerBacklog. 375 func listenerBacklog() int { 376 listenerBacklogCache.Do(func() { listenerBacklogCache.val = maxListenerBacklog() }) 377 return listenerBacklogCache.val 378 } 379 380 // A Listener is a generic network listener for stream-oriented protocols. 381 // 382 // Multiple goroutines may invoke methods on a Listener simultaneously. 383 type Listener interface { 384 // Accept waits for and returns the next connection to the listener. 385 Accept() (Conn, error) 386 387 // Close closes the listener. 388 // Any blocked Accept operations will be unblocked and return errors. 389 Close() error 390 391 // Addr returns the listener's network address. 392 Addr() Addr 393 } 394 395 // An Error represents a network error. 396 type Error interface { 397 error 398 Timeout() bool // Is the error a timeout? 399 400 // Deprecated: Temporary errors are not well-defined. 401 // Most "temporary" errors are timeouts, and the few exceptions are surprising. 402 // Do not use this method. 403 Temporary() bool 404 } 405 406 // Various errors contained in OpError. 407 var ( 408 // For connection setup operations. 409 errNoSuitableAddress = errors.New("no suitable address found") 410 411 // For connection setup and write operations. 412 errMissingAddress = errors.New("missing address") 413 414 // For both read and write operations. 415 errCanceled = canceledError{} 416 ErrWriteToConnected = errors.New("use of WriteTo with pre-connected connection") 417 ) 418 419 // canceledError lets us return the same error string we have always 420 // returned, while still being Is context.Canceled. 421 type canceledError struct{} 422 423 func (canceledError) Error() string { return "operation was canceled" } 424 425 func (canceledError) Is(err error) bool { return err == context.Canceled } 426 427 // mapErr maps from the context errors to the historical internal net 428 // error values. 429 func mapErr(err error) error { 430 switch err { 431 case context.Canceled: 432 return errCanceled 433 case context.DeadlineExceeded: 434 return errTimeout 435 default: 436 return err 437 } 438 } 439 440 // OpError is the error type usually returned by functions in the net 441 // package. It describes the operation, network type, and address of 442 // an error. 443 type OpError struct { 444 // Op is the operation which caused the error, such as 445 // "read" or "write". 446 Op string 447 448 // Net is the network type on which this error occurred, 449 // such as "tcp" or "udp6". 450 Net string 451 452 // For operations involving a remote network connection, like 453 // Dial, Read, or Write, Source is the corresponding local 454 // network address. 455 Source Addr 456 457 // Addr is the network address for which this error occurred. 458 // For local operations, like Listen or SetDeadline, Addr is 459 // the address of the local endpoint being manipulated. 460 // For operations involving a remote network connection, like 461 // Dial, Read, or Write, Addr is the remote address of that 462 // connection. 463 Addr Addr 464 465 // Err is the error that occurred during the operation. 466 // The Error method panics if the error is nil. 467 Err error 468 } 469 470 func (e *OpError) Unwrap() error { return e.Err } 471 472 func (e *OpError) Error() string { 473 if e == nil { 474 return "<nil>" 475 } 476 s := e.Op 477 if e.Net != "" { 478 s += " " + e.Net 479 } 480 if e.Source != nil { 481 s += " " + e.Source.String() 482 } 483 if e.Addr != nil { 484 if e.Source != nil { 485 s += "->" 486 } else { 487 s += " " 488 } 489 s += e.Addr.String() 490 } 491 s += ": " + e.Err.Error() 492 return s 493 } 494 495 var ( 496 // aLongTimeAgo is a non-zero time, far in the past, used for 497 // immediate cancellation of dials. 498 aLongTimeAgo = time.Unix(1, 0) 499 500 // noDeadline and noCancel are just zero values for 501 // readability with functions taking too many parameters. 502 noDeadline = time.Time{} 503 noCancel = (chan struct{})(nil) 504 ) 505 506 type timeout interface { 507 Timeout() bool 508 } 509 510 func (e *OpError) Timeout() bool { 511 if ne, ok := e.Err.(*os.SyscallError); ok { 512 t, ok := ne.Err.(timeout) 513 return ok && t.Timeout() 514 } 515 t, ok := e.Err.(timeout) 516 return ok && t.Timeout() 517 } 518 519 type temporary interface { 520 Temporary() bool 521 } 522 523 func (e *OpError) Temporary() bool { 524 // Treat ECONNRESET and ECONNABORTED as temporary errors when 525 // they come from calling accept. See issue 6163. 526 if e.Op == "accept" && isConnError(e.Err) { 527 return true 528 } 529 530 if ne, ok := e.Err.(*os.SyscallError); ok { 531 t, ok := ne.Err.(temporary) 532 return ok && t.Temporary() 533 } 534 t, ok := e.Err.(temporary) 535 return ok && t.Temporary() 536 } 537 538 // A ParseError is the error type of literal network address parsers. 539 type ParseError struct { 540 // Type is the type of string that was expected, such as 541 // "IP address", "CIDR address". 542 Type string 543 544 // Text is the malformed text string. 545 Text string 546 } 547 548 func (e *ParseError) Error() string { return "invalid " + e.Type + ": " + e.Text } 549 550 func (e *ParseError) Timeout() bool { return false } 551 func (e *ParseError) Temporary() bool { return false } 552 553 type AddrError struct { 554 Err string 555 Addr string 556 } 557 558 func (e *AddrError) Error() string { 559 if e == nil { 560 return "<nil>" 561 } 562 s := e.Err 563 if e.Addr != "" { 564 s = "address " + e.Addr + ": " + s 565 } 566 return s 567 } 568 569 func (e *AddrError) Timeout() bool { return false } 570 func (e *AddrError) Temporary() bool { return false } 571 572 type UnknownNetworkError string 573 574 func (e UnknownNetworkError) Error() string { return "unknown network " + string(e) } 575 func (e UnknownNetworkError) Timeout() bool { return false } 576 func (e UnknownNetworkError) Temporary() bool { return false } 577 578 type InvalidAddrError string 579 580 func (e InvalidAddrError) Error() string { return string(e) } 581 func (e InvalidAddrError) Timeout() bool { return false } 582 func (e InvalidAddrError) Temporary() bool { return false } 583 584 // errTimeout exists to return the historical "i/o timeout" string 585 // for context.DeadlineExceeded. See mapErr. 586 // It is also used when Dialer.Deadline is exceeded. 587 // error.Is(errTimeout, context.DeadlineExceeded) returns true. 588 // 589 // TODO(iant): We could consider changing this to os.ErrDeadlineExceeded 590 // in the future, if we make 591 // 592 // errors.Is(os.ErrDeadlineExceeded, context.DeadlineExceeded) 593 // 594 // return true. 595 var errTimeout error = &timeoutError{} 596 597 type timeoutError struct{} 598 599 func (e *timeoutError) Error() string { return "i/o timeout" } 600 func (e *timeoutError) Timeout() bool { return true } 601 func (e *timeoutError) Temporary() bool { return true } 602 603 func (e *timeoutError) Is(err error) bool { 604 return err == context.DeadlineExceeded 605 } 606 607 // DNSConfigError represents an error reading the machine's DNS configuration. 608 // (No longer used; kept for compatibility.) 609 type DNSConfigError struct { 610 Err error 611 } 612 613 func (e *DNSConfigError) Unwrap() error { return e.Err } 614 func (e *DNSConfigError) Error() string { return "error reading DNS config: " + e.Err.Error() } 615 func (e *DNSConfigError) Timeout() bool { return false } 616 func (e *DNSConfigError) Temporary() bool { return false } 617 618 // Various errors contained in DNSError. 619 var ( 620 errNoSuchHost = ¬FoundError{"no such host"} 621 errUnknownPort = ¬FoundError{"unknown port"} 622 ) 623 624 // notFoundError is a special error understood by the newDNSError function, 625 // which causes a creation of a DNSError with IsNotFound field set to true. 626 type notFoundError struct{ s string } 627 628 func (e *notFoundError) Error() string { return e.s } 629 630 // temporaryError is an error type that implements the [Error] interface. 631 // It returns true from the Temporary method. 632 type temporaryError struct{ s string } 633 634 func (e *temporaryError) Error() string { return e.s } 635 func (e *temporaryError) Temporary() bool { return true } 636 func (e *temporaryError) Timeout() bool { return false } 637 638 // DNSError represents a DNS lookup error. 639 type DNSError struct { 640 UnwrapErr error // error returned by the [DNSError.Unwrap] method, might be nil 641 Err string // description of the error 642 Name string // name looked for 643 Server string // server used 644 IsTimeout bool // if true, timed out; not all timeouts set this 645 IsTemporary bool // if true, error is temporary; not all errors set this 646 647 // IsNotFound is set to true when the requested name does not 648 // contain any records of the requested type (data not found), 649 // or the name itself was not found (NXDOMAIN). 650 IsNotFound bool 651 } 652 653 // newDNSError creates a new *DNSError. 654 // Based on the err, it sets the UnwrapErr, IsTimeout, IsTemporary, IsNotFound fields. 655 func newDNSError(err error, name, server string) *DNSError { 656 var ( 657 isTimeout bool 658 isTemporary bool 659 unwrapErr error 660 ) 661 662 if err, ok := err.(Error); ok { 663 isTimeout = err.Timeout() 664 isTemporary = err.Temporary() 665 } 666 667 // At this time, the only errors we wrap are context errors, to allow 668 // users to check for canceled/timed out requests. 669 if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) { 670 unwrapErr = err 671 } 672 673 _, isNotFound := err.(*notFoundError) 674 return &DNSError{ 675 UnwrapErr: unwrapErr, 676 Err: err.Error(), 677 Name: name, 678 Server: server, 679 IsTimeout: isTimeout, 680 IsTemporary: isTemporary, 681 IsNotFound: isNotFound, 682 } 683 } 684 685 // Unwrap returns e.UnwrapErr. 686 func (e *DNSError) Unwrap() error { return e.UnwrapErr } 687 688 func (e *DNSError) Error() string { 689 if e == nil { 690 return "<nil>" 691 } 692 s := "lookup " + e.Name 693 if e.Server != "" { 694 s += " on " + e.Server 695 } 696 s += ": " + e.Err 697 return s 698 } 699 700 // Timeout reports whether the DNS lookup is known to have timed out. 701 // This is not always known; a DNS lookup may fail due to a timeout 702 // and return a [DNSError] for which Timeout returns false. 703 func (e *DNSError) Timeout() bool { return e.IsTimeout } 704 705 // Temporary reports whether the DNS error is known to be temporary. 706 // This is not always known; a DNS lookup may fail due to a temporary 707 // error and return a [DNSError] for which Temporary returns false. 708 func (e *DNSError) Temporary() bool { return e.IsTimeout || e.IsTemporary } 709 710 // errClosed exists just so that the docs for ErrClosed don't mention 711 // the internal package poll. 712 var errClosed = poll.ErrNetClosing 713 714 // ErrClosed is the error returned by an I/O call on a network 715 // connection that has already been closed, or that is closed by 716 // another goroutine before the I/O is completed. This may be wrapped 717 // in another error, and should normally be tested using 718 // errors.Is(err, net.ErrClosed). 719 var ErrClosed error = errClosed 720 721 // noReadFrom can be embedded alongside another type to 722 // hide the ReadFrom method of that other type. 723 type noReadFrom struct{} 724 725 // ReadFrom hides another ReadFrom method. 726 // It should never be called. 727 func (noReadFrom) ReadFrom(io.Reader) (int64, error) { 728 panic("can't happen") 729 } 730 731 // tcpConnWithoutReadFrom implements all the methods of *TCPConn other 732 // than ReadFrom. This is used to permit ReadFrom to call io.Copy 733 // without leading to a recursive call to ReadFrom. 734 type tcpConnWithoutReadFrom struct { 735 noReadFrom 736 *TCPConn 737 } 738 739 // Fallback implementation of io.ReaderFrom's ReadFrom, when sendfile isn't 740 // applicable. 741 func genericReadFrom(c *TCPConn, r io.Reader) (n int64, err error) { 742 // Use wrapper to hide existing r.ReadFrom from io.Copy. 743 return io.Copy(tcpConnWithoutReadFrom{TCPConn: c}, r) 744 } 745 746 // noWriteTo can be embedded alongside another type to 747 // hide the WriteTo method of that other type. 748 type noWriteTo struct{} 749 750 // WriteTo hides another WriteTo method. 751 // It should never be called. 752 func (noWriteTo) WriteTo(io.Writer) (int64, error) { 753 panic("can't happen") 754 } 755 756 // tcpConnWithoutWriteTo implements all the methods of *TCPConn other 757 // than WriteTo. This is used to permit WriteTo to call io.Copy 758 // without leading to a recursive call to WriteTo. 759 type tcpConnWithoutWriteTo struct { 760 noWriteTo 761 *TCPConn 762 } 763 764 // Fallback implementation of io.WriterTo's WriteTo, when zero-copy isn't applicable. 765 func genericWriteTo(c *TCPConn, w io.Writer) (n int64, err error) { 766 // Use wrapper to hide existing w.WriteTo from io.Copy. 767 return io.Copy(w, tcpConnWithoutWriteTo{TCPConn: c}) 768 } 769 770 // Limit the number of concurrent cgo-using goroutines, because 771 // each will block an entire operating system thread. The usual culprit 772 // is resolving many DNS names in separate goroutines but the DNS 773 // server is not responding. Then the many lookups each use a different 774 // thread, and the system or the program runs out of threads. 775 776 var threadLimit chan struct{} 777 778 var threadOnce sync.Once 779 780 func acquireThread(ctx context.Context) error { 781 threadOnce.Do(func() { 782 threadLimit = make(chan struct{}, concurrentThreadsLimit()) 783 }) 784 select { 785 case threadLimit <- struct{}{}: 786 return nil 787 case <-ctx.Done(): 788 return ctx.Err() 789 } 790 } 791 792 func releaseThread() { 793 <-threadLimit 794 } 795 796 // buffersWriter is the interface implemented by Conns that support a 797 // "writev"-like batch write optimization. 798 // writeBuffers should fully consume and write all chunks from the 799 // provided Buffers, else it should report a non-nil error. 800 type buffersWriter interface { 801 writeBuffers(*Buffers) (int64, error) 802 } 803 804 // Buffers contains zero or more runs of bytes to write. 805 // 806 // On certain machines, for certain types of connections, this is 807 // optimized into an OS-specific batch write operation (such as 808 // "writev"). 809 type Buffers [][]byte 810 811 var ( 812 _ io.WriterTo = (*Buffers)(nil) 813 _ io.Reader = (*Buffers)(nil) 814 ) 815 816 // WriteTo writes contents of the buffers to w. 817 // 818 // WriteTo implements [io.WriterTo] for [Buffers]. 819 // 820 // WriteTo modifies the slice v as well as v[i] for 0 <= i < len(v), 821 // but does not modify v[i][j] for any i, j. 822 func (v *Buffers) WriteTo(w io.Writer) (n int64, err error) { 823 if wv, ok := w.(buffersWriter); ok { 824 return wv.writeBuffers(v) 825 } 826 for _, b := range *v { 827 nb, err := w.Write(b) 828 n += int64(nb) 829 if err != nil { 830 v.consume(n) 831 return n, err 832 } 833 } 834 v.consume(n) 835 return n, nil 836 } 837 838 // Read from the buffers. 839 // 840 // Read implements [io.Reader] for [Buffers]. 841 // 842 // Read modifies the slice v as well as v[i] for 0 <= i < len(v), 843 // but does not modify v[i][j] for any i, j. 844 func (v *Buffers) Read(p []byte) (n int, err error) { 845 for len(p) > 0 && len(*v) > 0 { 846 n0 := copy(p, (*v)[0]) 847 v.consume(int64(n0)) 848 p = p[n0:] 849 n += n0 850 } 851 if len(*v) == 0 { 852 err = io.EOF 853 } 854 return 855 } 856 857 func (v *Buffers) consume(n int64) { 858 for len(*v) > 0 { 859 ln0 := int64(len((*v)[0])) 860 if ln0 > n { 861 (*v)[0] = (*v)[0][n:] 862 return 863 } 864 n -= ln0 865 (*v)[0] = nil 866 *v = (*v)[1:] 867 } 868 } 869