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