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