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