...
Run Format

Source file src/net/net.go

Documentation: net

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

View as plain text