github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/net/net.go (about)

     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 cgo resolver
    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 Plan 9, the resolver always accesses /net/cs and /net/dns.
    75  
    76  On Windows, the resolver always uses C library functions, such as GetAddrInfo and DnsQuery.
    77  
    78  */
    79  package net
    80  
    81  import (
    82  	"context"
    83  	"errors"
    84  	"io"
    85  	"os"
    86  	"syscall"
    87  	"time"
    88  )
    89  
    90  // netGo and netCgo contain the state of the build tags used
    91  // to build this binary, and whether cgo is available.
    92  // conf.go mirrors these into conf for easier testing.
    93  var (
    94  	netGo  bool // set true in cgo_stub.go for build tag "netgo" (or no cgo)
    95  	netCgo bool // set true in conf_netcgo.go for build tag "netcgo"
    96  )
    97  
    98  func init() {
    99  	sysInit()
   100  	supportsIPv4 = probeIPv4Stack()
   101  	supportsIPv6, supportsIPv4map = probeIPv6Stack()
   102  }
   103  
   104  // Addr represents a network end point address.
   105  //
   106  // The two methods Network and String conventionally return strings
   107  // that can be passed as the arguments to Dial, but the exact form
   108  // and meaning of the strings is up to the implementation.
   109  type Addr interface {
   110  	Network() string // name of the network (for example, "tcp", "udp")
   111  	String() string  // string form of address (for example, "192.0.2.1:25", "[2001:db8::1]:80")
   112  }
   113  
   114  // Conn is a generic stream-oriented network connection.
   115  //
   116  // Multiple goroutines may invoke methods on a Conn simultaneously.
   117  type Conn interface {
   118  	// Read reads data from the connection.
   119  	// Read can be made to time out and return an Error with Timeout() == true
   120  	// after a fixed time limit; see SetDeadline and SetReadDeadline.
   121  	Read(b []byte) (n int, err error)
   122  
   123  	// Write writes data to the connection.
   124  	// Write can be made to time out and return an Error with Timeout() == true
   125  	// after a fixed time limit; see SetDeadline and SetWriteDeadline.
   126  	Write(b []byte) (n int, err error)
   127  
   128  	// Close closes the connection.
   129  	// Any blocked Read or Write operations will be unblocked and return errors.
   130  	Close() error
   131  
   132  	// LocalAddr returns the local network address.
   133  	LocalAddr() Addr
   134  
   135  	// RemoteAddr returns the remote network address.
   136  	RemoteAddr() Addr
   137  
   138  	// SetDeadline sets the read and write deadlines associated
   139  	// with the connection. It is equivalent to calling both
   140  	// SetReadDeadline and SetWriteDeadline.
   141  	//
   142  	// A deadline is an absolute time after which I/O operations
   143  	// fail with a timeout (see type Error) instead of
   144  	// blocking. The deadline applies to all future and pending
   145  	// I/O, not just the immediately following call to Read or
   146  	// Write. After a deadline has been exceeded, the connection
   147  	// can be refreshed by setting a deadline in the future.
   148  	//
   149  	// An idle timeout can be implemented by repeatedly extending
   150  	// the deadline after successful Read or Write calls.
   151  	//
   152  	// A zero value for t means I/O operations will not time out.
   153  	SetDeadline(t time.Time) error
   154  
   155  	// SetReadDeadline sets the deadline for future Read calls
   156  	// and any currently-blocked Read call.
   157  	// A zero value for t means Read will not time out.
   158  	SetReadDeadline(t time.Time) error
   159  
   160  	// SetWriteDeadline sets the deadline for future Write calls
   161  	// and any currently-blocked Write call.
   162  	// Even if write times out, it may return n > 0, indicating that
   163  	// some of the data was successfully written.
   164  	// A zero value for t means Write will not time out.
   165  	SetWriteDeadline(t time.Time) error
   166  }
   167  
   168  type conn struct {
   169  	fd *netFD
   170  }
   171  
   172  func (c *conn) ok() bool { return c != nil && c.fd != nil }
   173  
   174  // Implementation of the Conn interface.
   175  
   176  // Read implements the Conn Read method.
   177  func (c *conn) Read(b []byte) (int, error) {
   178  	if !c.ok() {
   179  		return 0, syscall.EINVAL
   180  	}
   181  	n, err := c.fd.Read(b)
   182  	if err != nil && err != io.EOF {
   183  		err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   184  	}
   185  	return n, err
   186  }
   187  
   188  // Write implements the Conn Write method.
   189  func (c *conn) Write(b []byte) (int, error) {
   190  	if !c.ok() {
   191  		return 0, syscall.EINVAL
   192  	}
   193  	n, err := c.fd.Write(b)
   194  	if err != nil {
   195  		err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   196  	}
   197  	return n, err
   198  }
   199  
   200  // Close closes the connection.
   201  func (c *conn) Close() error {
   202  	if !c.ok() {
   203  		return syscall.EINVAL
   204  	}
   205  	err := c.fd.Close()
   206  	if err != nil {
   207  		err = &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   208  	}
   209  	return err
   210  }
   211  
   212  // LocalAddr returns the local network address.
   213  // The Addr returned is shared by all invocations of LocalAddr, so
   214  // do not modify it.
   215  func (c *conn) LocalAddr() Addr {
   216  	if !c.ok() {
   217  		return nil
   218  	}
   219  	return c.fd.laddr
   220  }
   221  
   222  // RemoteAddr returns the remote network address.
   223  // The Addr returned is shared by all invocations of RemoteAddr, so
   224  // do not modify it.
   225  func (c *conn) RemoteAddr() Addr {
   226  	if !c.ok() {
   227  		return nil
   228  	}
   229  	return c.fd.raddr
   230  }
   231  
   232  // SetDeadline implements the Conn SetDeadline method.
   233  func (c *conn) SetDeadline(t time.Time) error {
   234  	if !c.ok() {
   235  		return syscall.EINVAL
   236  	}
   237  	if err := c.fd.setDeadline(t); err != nil {
   238  		return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
   239  	}
   240  	return nil
   241  }
   242  
   243  // SetReadDeadline implements the Conn SetReadDeadline method.
   244  func (c *conn) SetReadDeadline(t time.Time) error {
   245  	if !c.ok() {
   246  		return syscall.EINVAL
   247  	}
   248  	if err := c.fd.setReadDeadline(t); err != nil {
   249  		return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
   250  	}
   251  	return nil
   252  }
   253  
   254  // SetWriteDeadline implements the Conn SetWriteDeadline method.
   255  func (c *conn) SetWriteDeadline(t time.Time) error {
   256  	if !c.ok() {
   257  		return syscall.EINVAL
   258  	}
   259  	if err := c.fd.setWriteDeadline(t); err != nil {
   260  		return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
   261  	}
   262  	return nil
   263  }
   264  
   265  // SetReadBuffer sets the size of the operating system's
   266  // receive buffer associated with the connection.
   267  func (c *conn) SetReadBuffer(bytes int) error {
   268  	if !c.ok() {
   269  		return syscall.EINVAL
   270  	}
   271  	if err := setReadBuffer(c.fd, bytes); err != nil {
   272  		return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
   273  	}
   274  	return nil
   275  }
   276  
   277  // SetWriteBuffer sets the size of the operating system's
   278  // transmit buffer associated with the connection.
   279  func (c *conn) SetWriteBuffer(bytes int) error {
   280  	if !c.ok() {
   281  		return syscall.EINVAL
   282  	}
   283  	if err := setWriteBuffer(c.fd, bytes); err != nil {
   284  		return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
   285  	}
   286  	return nil
   287  }
   288  
   289  // File sets the underlying os.File to blocking mode and returns a copy.
   290  // It is the caller's responsibility to close f when finished.
   291  // Closing c does not affect f, and closing f does not affect c.
   292  //
   293  // The returned os.File's file descriptor is different from the connection's.
   294  // Attempting to change properties of the original using this duplicate
   295  // may or may not have the desired effect.
   296  func (c *conn) File() (f *os.File, err error) {
   297  	f, err = c.fd.dup()
   298  	if err != nil {
   299  		err = &OpError{Op: "file", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   300  	}
   301  	return
   302  }
   303  
   304  // PacketConn is a generic packet-oriented network connection.
   305  //
   306  // Multiple goroutines may invoke methods on a PacketConn simultaneously.
   307  type PacketConn interface {
   308  	// ReadFrom reads a packet from the connection,
   309  	// copying the payload into b. It returns the number of
   310  	// bytes copied into b and the return address that
   311  	// was on the packet.
   312  	// ReadFrom can be made to time out and return
   313  	// an Error with Timeout() == true after a fixed time limit;
   314  	// see SetDeadline and SetReadDeadline.
   315  	ReadFrom(b []byte) (n int, addr Addr, err error)
   316  
   317  	// WriteTo writes a packet with payload b to addr.
   318  	// WriteTo can be made to time out and return
   319  	// an Error with Timeout() == true after a fixed time limit;
   320  	// see SetDeadline and SetWriteDeadline.
   321  	// On packet-oriented connections, write timeouts are rare.
   322  	WriteTo(b []byte, addr Addr) (n int, err error)
   323  
   324  	// Close closes the connection.
   325  	// Any blocked ReadFrom or WriteTo operations will be unblocked and return errors.
   326  	Close() error
   327  
   328  	// LocalAddr returns the local network address.
   329  	LocalAddr() Addr
   330  
   331  	// SetDeadline sets the read and write deadlines associated
   332  	// with the connection. It is equivalent to calling both
   333  	// SetReadDeadline and SetWriteDeadline.
   334  	//
   335  	// A deadline is an absolute time after which I/O operations
   336  	// fail with a timeout (see type Error) instead of
   337  	// blocking. The deadline applies to all future and pending
   338  	// I/O, not just the immediately following call to ReadFrom or
   339  	// WriteTo. After a deadline has been exceeded, the connection
   340  	// can be refreshed by setting a deadline in the future.
   341  	//
   342  	// An idle timeout can be implemented by repeatedly extending
   343  	// the deadline after successful ReadFrom or WriteTo calls.
   344  	//
   345  	// A zero value for t means I/O operations will not time out.
   346  	SetDeadline(t time.Time) error
   347  
   348  	// SetReadDeadline sets the deadline for future ReadFrom calls
   349  	// and any currently-blocked ReadFrom call.
   350  	// A zero value for t means ReadFrom will not time out.
   351  	SetReadDeadline(t time.Time) error
   352  
   353  	// SetWriteDeadline sets the deadline for future WriteTo calls
   354  	// and any currently-blocked WriteTo call.
   355  	// Even if write times out, it may return n > 0, indicating that
   356  	// some of the data was successfully written.
   357  	// A zero value for t means WriteTo will not time out.
   358  	SetWriteDeadline(t time.Time) error
   359  }
   360  
   361  var listenerBacklog = maxListenerBacklog()
   362  
   363  // A Listener is a generic network listener for stream-oriented protocols.
   364  //
   365  // Multiple goroutines may invoke methods on a Listener simultaneously.
   366  type Listener interface {
   367  	// Accept waits for and returns the next connection to the listener.
   368  	Accept() (Conn, error)
   369  
   370  	// Close closes the listener.
   371  	// Any blocked Accept operations will be unblocked and return errors.
   372  	Close() error
   373  
   374  	// Addr returns the listener's network address.
   375  	Addr() Addr
   376  }
   377  
   378  // An Error represents a network error.
   379  type Error interface {
   380  	error
   381  	Timeout() bool   // Is the error a timeout?
   382  	Temporary() bool // Is the error temporary?
   383  }
   384  
   385  // Various errors contained in OpError.
   386  var (
   387  	// For connection setup operations.
   388  	errNoSuitableAddress = errors.New("no suitable address found")
   389  
   390  	// For connection setup and write operations.
   391  	errMissingAddress = errors.New("missing address")
   392  
   393  	// For both read and write operations.
   394  	errTimeout          error = &timeoutError{}
   395  	errCanceled               = errors.New("operation was canceled")
   396  	errClosing                = errors.New("use of closed network connection")
   397  	ErrWriteToConnected       = errors.New("use of WriteTo with pre-connected connection")
   398  )
   399  
   400  // mapErr maps from the context errors to the historical internal net
   401  // error values.
   402  //
   403  // TODO(bradfitz): get rid of this after adjusting tests and making
   404  // context.DeadlineExceeded implement net.Error?
   405  func mapErr(err error) error {
   406  	switch err {
   407  	case context.Canceled:
   408  		return errCanceled
   409  	case context.DeadlineExceeded:
   410  		return errTimeout
   411  	default:
   412  		return err
   413  	}
   414  }
   415  
   416  // OpError is the error type usually returned by functions in the net
   417  // package. It describes the operation, network type, and address of
   418  // an error.
   419  type OpError struct {
   420  	// Op is the operation which caused the error, such as
   421  	// "read" or "write".
   422  	Op string
   423  
   424  	// Net is the network type on which this error occurred,
   425  	// such as "tcp" or "udp6".
   426  	Net string
   427  
   428  	// For operations involving a remote network connection, like
   429  	// Dial, Read, or Write, Source is the corresponding local
   430  	// network address.
   431  	Source Addr
   432  
   433  	// Addr is the network address for which this error occurred.
   434  	// For local operations, like Listen or SetDeadline, Addr is
   435  	// the address of the local endpoint being manipulated.
   436  	// For operations involving a remote network connection, like
   437  	// Dial, Read, or Write, Addr is the remote address of that
   438  	// connection.
   439  	Addr Addr
   440  
   441  	// Err is the error that occurred during the operation.
   442  	Err error
   443  }
   444  
   445  func (e *OpError) Error() string {
   446  	if e == nil {
   447  		return "<nil>"
   448  	}
   449  	s := e.Op
   450  	if e.Net != "" {
   451  		s += " " + e.Net
   452  	}
   453  	if e.Source != nil {
   454  		s += " " + e.Source.String()
   455  	}
   456  	if e.Addr != nil {
   457  		if e.Source != nil {
   458  			s += "->"
   459  		} else {
   460  			s += " "
   461  		}
   462  		s += e.Addr.String()
   463  	}
   464  	s += ": " + e.Err.Error()
   465  	return s
   466  }
   467  
   468  var (
   469  	// aLongTimeAgo is a non-zero time, far in the past, used for
   470  	// immediate cancelation of dials.
   471  	aLongTimeAgo = time.Unix(233431200, 0)
   472  
   473  	// nonDeadline and noCancel are just zero values for
   474  	// readability with functions taking too many parameters.
   475  	noDeadline = time.Time{}
   476  	noCancel   = (chan struct{})(nil)
   477  )
   478  
   479  type timeout interface {
   480  	Timeout() bool
   481  }
   482  
   483  func (e *OpError) Timeout() bool {
   484  	if ne, ok := e.Err.(*os.SyscallError); ok {
   485  		t, ok := ne.Err.(timeout)
   486  		return ok && t.Timeout()
   487  	}
   488  	t, ok := e.Err.(timeout)
   489  	return ok && t.Timeout()
   490  }
   491  
   492  type temporary interface {
   493  	Temporary() bool
   494  }
   495  
   496  func (e *OpError) Temporary() bool {
   497  	if ne, ok := e.Err.(*os.SyscallError); ok {
   498  		t, ok := ne.Err.(temporary)
   499  		return ok && t.Temporary()
   500  	}
   501  	t, ok := e.Err.(temporary)
   502  	return ok && t.Temporary()
   503  }
   504  
   505  type timeoutError struct{}
   506  
   507  func (e *timeoutError) Error() string   { return "i/o timeout" }
   508  func (e *timeoutError) Timeout() bool   { return true }
   509  func (e *timeoutError) Temporary() bool { return true }
   510  
   511  // A ParseError is the error type of literal network address parsers.
   512  type ParseError struct {
   513  	// Type is the type of string that was expected, such as
   514  	// "IP address", "CIDR address".
   515  	Type string
   516  
   517  	// Text is the malformed text string.
   518  	Text string
   519  }
   520  
   521  func (e *ParseError) Error() string { return "invalid " + e.Type + ": " + e.Text }
   522  
   523  type AddrError struct {
   524  	Err  string
   525  	Addr string
   526  }
   527  
   528  func (e *AddrError) Error() string {
   529  	if e == nil {
   530  		return "<nil>"
   531  	}
   532  	s := e.Err
   533  	if e.Addr != "" {
   534  		s = "address " + e.Addr + ": " + s
   535  	}
   536  	return s
   537  }
   538  
   539  func (e *AddrError) Timeout() bool   { return false }
   540  func (e *AddrError) Temporary() bool { return false }
   541  
   542  type UnknownNetworkError string
   543  
   544  func (e UnknownNetworkError) Error() string   { return "unknown network " + string(e) }
   545  func (e UnknownNetworkError) Timeout() bool   { return false }
   546  func (e UnknownNetworkError) Temporary() bool { return false }
   547  
   548  type InvalidAddrError string
   549  
   550  func (e InvalidAddrError) Error() string   { return string(e) }
   551  func (e InvalidAddrError) Timeout() bool   { return false }
   552  func (e InvalidAddrError) Temporary() bool { return false }
   553  
   554  // DNSConfigError represents an error reading the machine's DNS configuration.
   555  // (No longer used; kept for compatibility.)
   556  type DNSConfigError struct {
   557  	Err error
   558  }
   559  
   560  func (e *DNSConfigError) Error() string   { return "error reading DNS config: " + e.Err.Error() }
   561  func (e *DNSConfigError) Timeout() bool   { return false }
   562  func (e *DNSConfigError) Temporary() bool { return false }
   563  
   564  // Various errors contained in DNSError.
   565  var (
   566  	errNoSuchHost = errors.New("no such host")
   567  )
   568  
   569  // DNSError represents a DNS lookup error.
   570  type DNSError struct {
   571  	Err         string // description of the error
   572  	Name        string // name looked for
   573  	Server      string // server used
   574  	IsTimeout   bool   // if true, timed out; not all timeouts set this
   575  	IsTemporary bool   // if true, error is temporary; not all errors set this
   576  }
   577  
   578  func (e *DNSError) Error() string {
   579  	if e == nil {
   580  		return "<nil>"
   581  	}
   582  	s := "lookup " + e.Name
   583  	if e.Server != "" {
   584  		s += " on " + e.Server
   585  	}
   586  	s += ": " + e.Err
   587  	return s
   588  }
   589  
   590  // Timeout reports whether the DNS lookup is known to have timed out.
   591  // This is not always known; a DNS lookup may fail due to a timeout
   592  // and return a DNSError for which Timeout returns false.
   593  func (e *DNSError) Timeout() bool { return e.IsTimeout }
   594  
   595  // Temporary reports whether the DNS error is known to be temporary.
   596  // This is not always known; a DNS lookup may fail due to a temporary
   597  // error and return a DNSError for which Temporary returns false.
   598  func (e *DNSError) Temporary() bool { return e.IsTimeout || e.IsTemporary }
   599  
   600  type writerOnly struct {
   601  	io.Writer
   602  }
   603  
   604  // Fallback implementation of io.ReaderFrom's ReadFrom, when sendfile isn't
   605  // applicable.
   606  func genericReadFrom(w io.Writer, r io.Reader) (n int64, err error) {
   607  	// Use wrapper to hide existing r.ReadFrom from io.Copy.
   608  	return io.Copy(writerOnly{w}, r)
   609  }
   610  
   611  // Limit the number of concurrent cgo-using goroutines, because
   612  // each will block an entire operating system thread. The usual culprit
   613  // is resolving many DNS names in separate goroutines but the DNS
   614  // server is not responding. Then the many lookups each use a different
   615  // thread, and the system or the program runs out of threads.
   616  
   617  var threadLimit = make(chan struct{}, 500)
   618  
   619  func acquireThread() {
   620  	threadLimit <- struct{}{}
   621  }
   622  
   623  func releaseThread() {
   624  	<-threadLimit
   625  }
   626  
   627  // buffersWriter is the interface implemented by Conns that support a
   628  // "writev"-like batch write optimization.
   629  // writeBuffers should fully consume and write all chunks from the
   630  // provided Buffers, else it should report a non-nil error.
   631  type buffersWriter interface {
   632  	writeBuffers(*Buffers) (int64, error)
   633  }
   634  
   635  var testHookDidWritev = func(wrote int) {}
   636  
   637  // Buffers contains zero or more runs of bytes to write.
   638  //
   639  // On certain machines, for certain types of connections, this is
   640  // optimized into an OS-specific batch write operation (such as
   641  // "writev").
   642  type Buffers [][]byte
   643  
   644  var (
   645  	_ io.WriterTo = (*Buffers)(nil)
   646  	_ io.Reader   = (*Buffers)(nil)
   647  )
   648  
   649  func (v *Buffers) WriteTo(w io.Writer) (n int64, err error) {
   650  	if wv, ok := w.(buffersWriter); ok {
   651  		return wv.writeBuffers(v)
   652  	}
   653  	for _, b := range *v {
   654  		nb, err := w.Write(b)
   655  		n += int64(nb)
   656  		if err != nil {
   657  			v.consume(n)
   658  			return n, err
   659  		}
   660  	}
   661  	v.consume(n)
   662  	return n, nil
   663  }
   664  
   665  func (v *Buffers) Read(p []byte) (n int, err error) {
   666  	for len(p) > 0 && len(*v) > 0 {
   667  		n0 := copy(p, (*v)[0])
   668  		v.consume(int64(n0))
   669  		p = p[n0:]
   670  		n += n0
   671  	}
   672  	if len(*v) == 0 {
   673  		err = io.EOF
   674  	}
   675  	return
   676  }
   677  
   678  func (v *Buffers) consume(n int64) {
   679  	for len(*v) > 0 {
   680  		ln0 := int64(len((*v)[0]))
   681  		if ln0 > n {
   682  			(*v)[0] = (*v)[0][n:]
   683  			return
   684  		}
   685  		n -= ln0
   686  		*v = (*v)[1:]
   687  	}
   688  }