...

Source file src/pkg/net/net.go

     1	// Copyright 2009 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	/*
     6	Package net provides a portable interface for network I/O, including
     7	TCP/IP, UDP, domain name resolution, and Unix domain sockets.
     8	
     9	Although the package provides access to low-level networking
    10	primitives, most clients will need only the basic interface provided
    11	by the Dial, Listen, and Accept functions and the associated
    12	Conn and Listener interfaces. The crypto/tls package uses
    13	the same interfaces and similar Dial and Listen functions.
    14	
    15	The Dial function connects to a server:
    16	
    17		conn, err := net.Dial("tcp", "golang.org:80")
    18		if err != nil {
    19			// handle error
    20		}
    21		fmt.Fprintf(conn, "GET / HTTP/1.0\r\n\r\n")
    22		status, err := bufio.NewReader(conn).ReadString('\n')
    23		// ...
    24	
    25	The Listen function creates servers:
    26	
    27		ln, err := net.Listen("tcp", ":8080")
    28		if err != nil {
    29			// handle error
    30		}
    31		for {
    32			conn, err := ln.Accept()
    33			if err != nil {
    34				// handle error
    35			}
    36			go handleConnection(conn)
    37		}
    38	
    39	Name Resolution
    40	
    41	The method for resolving domain names, whether indirectly with functions like Dial
    42	or directly with functions like LookupHost and LookupAddr, varies by operating system.
    43	
    44	On Unix systems, the resolver has two options for resolving names.
    45	It can use a pure Go resolver that sends DNS requests directly to the servers
    46	listed in /etc/resolv.conf, or it can use a cgo-based resolver that calls C
    47	library routines such as getaddrinfo and getnameinfo.
    48	
    49	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		//
   150		// Note that if a TCP connection has keep-alive turned on,
   151		// which is the default unless overridden by Dialer.KeepAlive
   152		// or ListenConfig.KeepAlive, then a keep-alive failure may
   153		// also return a timeout error. On Unix systems a keep-alive
   154		// failure on I/O can be detected using
   155		// errors.Is(err, syscall.ETIMEDOUT).
   156		SetDeadline(t time.Time) error
   157	
   158		// SetReadDeadline sets the deadline for future Read calls
   159		// and any currently-blocked Read call.
   160		// A zero value for t means Read will not time out.
   161		SetReadDeadline(t time.Time) error
   162	
   163		// SetWriteDeadline sets the deadline for future Write calls
   164		// and any currently-blocked Write call.
   165		// Even if write times out, it may return n > 0, indicating that
   166		// some of the data was successfully written.
   167		// A zero value for t means Write will not time out.
   168		SetWriteDeadline(t time.Time) error
   169	}
   170	
   171	type conn struct {
   172		fd *netFD
   173	}
   174	
   175	func (c *conn) ok() bool { return c != nil && c.fd != nil }
   176	
   177	// Implementation of the Conn interface.
   178	
   179	// Read implements the Conn Read method.
   180	func (c *conn) Read(b []byte) (int, error) {
   181		if !c.ok() {
   182			return 0, syscall.EINVAL
   183		}
   184		n, err := c.fd.Read(b)
   185		if err != nil && err != io.EOF {
   186			err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   187		}
   188		return n, err
   189	}
   190	
   191	// Write implements the Conn Write method.
   192	func (c *conn) Write(b []byte) (int, error) {
   193		if !c.ok() {
   194			return 0, syscall.EINVAL
   195		}
   196		n, err := c.fd.Write(b)
   197		if err != nil {
   198			err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   199		}
   200		return n, err
   201	}
   202	
   203	// Close closes the connection.
   204	func (c *conn) Close() error {
   205		if !c.ok() {
   206			return syscall.EINVAL
   207		}
   208		err := c.fd.Close()
   209		if err != nil {
   210			err = &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   211		}
   212		return err
   213	}
   214	
   215	// LocalAddr returns the local network address.
   216	// The Addr returned is shared by all invocations of LocalAddr, so
   217	// do not modify it.
   218	func (c *conn) LocalAddr() Addr {
   219		if !c.ok() {
   220			return nil
   221		}
   222		return c.fd.laddr
   223	}
   224	
   225	// RemoteAddr returns the remote network address.
   226	// The Addr returned is shared by all invocations of RemoteAddr, so
   227	// do not modify it.
   228	func (c *conn) RemoteAddr() Addr {
   229		if !c.ok() {
   230			return nil
   231		}
   232		return c.fd.raddr
   233	}
   234	
   235	// SetDeadline implements the Conn SetDeadline method.
   236	func (c *conn) SetDeadline(t time.Time) error {
   237		if !c.ok() {
   238			return syscall.EINVAL
   239		}
   240		if err := c.fd.SetDeadline(t); err != nil {
   241			return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
   242		}
   243		return nil
   244	}
   245	
   246	// SetReadDeadline implements the Conn SetReadDeadline method.
   247	func (c *conn) SetReadDeadline(t time.Time) error {
   248		if !c.ok() {
   249			return syscall.EINVAL
   250		}
   251		if err := c.fd.SetReadDeadline(t); err != nil {
   252			return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
   253		}
   254		return nil
   255	}
   256	
   257	// SetWriteDeadline implements the Conn SetWriteDeadline method.
   258	func (c *conn) SetWriteDeadline(t time.Time) error {
   259		if !c.ok() {
   260			return syscall.EINVAL
   261		}
   262		if err := c.fd.SetWriteDeadline(t); err != nil {
   263			return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
   264		}
   265		return nil
   266	}
   267	
   268	// SetReadBuffer sets the size of the operating system's
   269	// receive buffer associated with the connection.
   270	func (c *conn) SetReadBuffer(bytes int) error {
   271		if !c.ok() {
   272			return syscall.EINVAL
   273		}
   274		if err := setReadBuffer(c.fd, bytes); err != nil {
   275			return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
   276		}
   277		return nil
   278	}
   279	
   280	// SetWriteBuffer sets the size of the operating system's
   281	// transmit buffer associated with the connection.
   282	func (c *conn) SetWriteBuffer(bytes int) error {
   283		if !c.ok() {
   284			return syscall.EINVAL
   285		}
   286		if err := setWriteBuffer(c.fd, bytes); err != nil {
   287			return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
   288		}
   289		return nil
   290	}
   291	
   292	// File returns a copy of the underlying os.File.
   293	// It is the caller's responsibility to close f when finished.
   294	// Closing c does not affect f, and closing f does not affect c.
   295	//
   296	// The returned os.File's file descriptor is different from the connection's.
   297	// Attempting to change properties of the original using this duplicate
   298	// may or may not have the desired effect.
   299	func (c *conn) File() (f *os.File, err error) {
   300		f, err = c.fd.dup()
   301		if err != nil {
   302			err = &OpError{Op: "file", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   303		}
   304		return
   305	}
   306	
   307	// PacketConn is a generic packet-oriented network connection.
   308	//
   309	// Multiple goroutines may invoke methods on a PacketConn simultaneously.
   310	type PacketConn interface {
   311		// ReadFrom reads a packet from the connection,
   312		// copying the payload into p. It returns the number of
   313		// bytes copied into p and the return address that
   314		// was on the packet.
   315		// It returns the number of bytes read (0 <= n <= len(p))
   316		// and any error encountered. Callers should always process
   317		// the n > 0 bytes returned before considering the error err.
   318		// ReadFrom can be made to time out and return
   319		// an Error with Timeout() == true after a fixed time limit;
   320		// 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
   325		// an Error with Timeout() == true after a fixed time limit;
   326		// see SetDeadline and SetWriteDeadline.
   327		// On packet-oriented connections, write timeouts are rare.
   328		WriteTo(p []byte, addr Addr) (n int, err error)
   329	
   330		// Close closes the connection.
   331		// Any blocked ReadFrom or WriteTo operations will be unblocked and return errors.
   332		Close() error
   333	
   334		// LocalAddr returns the local network address.
   335		LocalAddr() Addr
   336	
   337		// SetDeadline sets the read and write deadlines associated
   338		// with the connection. It is equivalent to calling both
   339		// SetReadDeadline and SetWriteDeadline.
   340		//
   341		// A deadline is an absolute time after which I/O operations
   342		// fail with a timeout (see type Error) instead of
   343		// blocking. The deadline applies to all future and pending
   344		// I/O, not just the immediately following call to ReadFrom or
   345		// WriteTo. After a deadline has been exceeded, the connection
   346		// can be refreshed by setting a deadline in the future.
   347		//
   348		// An idle timeout can be implemented by repeatedly extending
   349		// the deadline after successful ReadFrom or WriteTo calls.
   350		//
   351		// A zero value for t means I/O operations will not time out.
   352		SetDeadline(t time.Time) error
   353	
   354		// SetReadDeadline sets the deadline for future ReadFrom calls
   355		// and any currently-blocked ReadFrom call.
   356		// A zero value for t means ReadFrom will not time out.
   357		SetReadDeadline(t time.Time) error
   358	
   359		// SetWriteDeadline sets the deadline for future WriteTo calls
   360		// and any currently-blocked WriteTo call.
   361		// Even if write times out, it may return n > 0, indicating that
   362		// some of the data was successfully written.
   363		// A zero value for t means WriteTo will not time out.
   364		SetWriteDeadline(t time.Time) error
   365	}
   366	
   367	var listenerBacklogCache struct {
   368		sync.Once
   369		val int
   370	}
   371	
   372	// listenerBacklog is a caching wrapper around maxListenerBacklog.
   373	func listenerBacklog() int {
   374		listenerBacklogCache.Do(func() { listenerBacklogCache.val = maxListenerBacklog() })
   375		return listenerBacklogCache.val
   376	}
   377	
   378	// A Listener is a generic network listener for stream-oriented protocols.
   379	//
   380	// Multiple goroutines may invoke methods on a Listener simultaneously.
   381	type Listener interface {
   382		// Accept waits for and returns the next connection to the listener.
   383		Accept() (Conn, error)
   384	
   385		// Close closes the listener.
   386		// Any blocked Accept operations will be unblocked and return errors.
   387		Close() error
   388	
   389		// Addr returns the listener's network address.
   390		Addr() Addr
   391	}
   392	
   393	// An Error represents a network error.
   394	type Error interface {
   395		error
   396		Timeout() bool   // Is the error a timeout?
   397		Temporary() bool // Is the error temporary?
   398	}
   399	
   400	// Various errors contained in OpError.
   401	var (
   402		// For connection setup operations.
   403		errNoSuitableAddress = errors.New("no suitable address found")
   404	
   405		// For connection setup and write operations.
   406		errMissingAddress = errors.New("missing address")
   407	
   408		// For both read and write operations.
   409		errCanceled         = errors.New("operation was canceled")
   410		ErrWriteToConnected = errors.New("use of WriteTo with pre-connected connection")
   411	)
   412	
   413	// mapErr maps from the context errors to the historical internal net
   414	// error values.
   415	//
   416	// TODO(bradfitz): get rid of this after adjusting tests and making
   417	// context.DeadlineExceeded implement net.Error?
   418	func mapErr(err error) error {
   419		switch err {
   420		case context.Canceled:
   421			return errCanceled
   422		case context.DeadlineExceeded:
   423			return poll.ErrTimeout
   424		default:
   425			return err
   426		}
   427	}
   428	
   429	// OpError is the error type usually returned by functions in the net
   430	// package. It describes the operation, network type, and address of
   431	// an error.
   432	type OpError struct {
   433		// Op is the operation which caused the error, such as
   434		// "read" or "write".
   435		Op string
   436	
   437		// Net is the network type on which this error occurred,
   438		// such as "tcp" or "udp6".
   439		Net string
   440	
   441		// For operations involving a remote network connection, like
   442		// Dial, Read, or Write, Source is the corresponding local
   443		// network address.
   444		Source Addr
   445	
   446		// Addr is the network address for which this error occurred.
   447		// For local operations, like Listen or SetDeadline, Addr is
   448		// the address of the local endpoint being manipulated.
   449		// For operations involving a remote network connection, like
   450		// Dial, Read, or Write, Addr is the remote address of that
   451		// connection.
   452		Addr Addr
   453	
   454		// Err is the error that occurred during the operation.
   455		Err error
   456	}
   457	
   458	func (e *OpError) Unwrap() error { return e.Err }
   459	
   460	func (e *OpError) Error() string {
   461		if e == nil {
   462			return "<nil>"
   463		}
   464		s := e.Op
   465		if e.Net != "" {
   466			s += " " + e.Net
   467		}
   468		if e.Source != nil {
   469			s += " " + e.Source.String()
   470		}
   471		if e.Addr != nil {
   472			if e.Source != nil {
   473				s += "->"
   474			} else {
   475				s += " "
   476			}
   477			s += e.Addr.String()
   478		}
   479		s += ": " + e.Err.Error()
   480		return s
   481	}
   482	
   483	var (
   484		// aLongTimeAgo is a non-zero time, far in the past, used for
   485		// immediate cancellation of dials.
   486		aLongTimeAgo = time.Unix(1, 0)
   487	
   488		// nonDeadline and noCancel are just zero values for
   489		// readability with functions taking too many parameters.
   490		noDeadline = time.Time{}
   491		noCancel   = (chan struct{})(nil)
   492	)
   493	
   494	type timeout interface {
   495		Timeout() bool
   496	}
   497	
   498	func (e *OpError) Timeout() bool {
   499		if ne, ok := e.Err.(*os.SyscallError); ok {
   500			t, ok := ne.Err.(timeout)
   501			return ok && t.Timeout()
   502		}
   503		t, ok := e.Err.(timeout)
   504		return ok && t.Timeout()
   505	}
   506	
   507	type temporary interface {
   508		Temporary() bool
   509	}
   510	
   511	func (e *OpError) Temporary() bool {
   512		// Treat ECONNRESET and ECONNABORTED as temporary errors when
   513		// they come from calling accept. See issue 6163.
   514		if e.Op == "accept" && isConnError(e.Err) {
   515			return true
   516		}
   517	
   518		if ne, ok := e.Err.(*os.SyscallError); ok {
   519			t, ok := ne.Err.(temporary)
   520			return ok && t.Temporary()
   521		}
   522		t, ok := e.Err.(temporary)
   523		return ok && t.Temporary()
   524	}
   525	
   526	// A ParseError is the error type of literal network address parsers.
   527	type ParseError struct {
   528		// Type is the type of string that was expected, such as
   529		// "IP address", "CIDR address".
   530		Type string
   531	
   532		// Text is the malformed text string.
   533		Text string
   534	}
   535	
   536	func (e *ParseError) Error() string { return "invalid " + e.Type + ": " + e.Text }
   537	
   538	type AddrError struct {
   539		Err  string
   540		Addr string
   541	}
   542	
   543	func (e *AddrError) Error() string {
   544		if e == nil {
   545			return "<nil>"
   546		}
   547		s := e.Err
   548		if e.Addr != "" {
   549			s = "address " + e.Addr + ": " + s
   550		}
   551		return s
   552	}
   553	
   554	func (e *AddrError) Timeout() bool   { return false }
   555	func (e *AddrError) Temporary() bool { return false }
   556	
   557	type UnknownNetworkError string
   558	
   559	func (e UnknownNetworkError) Error() string   { return "unknown network " + string(e) }
   560	func (e UnknownNetworkError) Timeout() bool   { return false }
   561	func (e UnknownNetworkError) Temporary() bool { return false }
   562	
   563	type InvalidAddrError string
   564	
   565	func (e InvalidAddrError) Error() string   { return string(e) }
   566	func (e InvalidAddrError) Timeout() bool   { return false }
   567	func (e InvalidAddrError) Temporary() bool { return false }
   568	
   569	// DNSConfigError represents an error reading the machine's DNS configuration.
   570	// (No longer used; kept for compatibility.)
   571	type DNSConfigError struct {
   572		Err error
   573	}
   574	
   575	func (e *DNSConfigError) Unwrap() error   { return e.Err }
   576	func (e *DNSConfigError) Error() string   { return "error reading DNS config: " + e.Err.Error() }
   577	func (e *DNSConfigError) Timeout() bool   { return false }
   578	func (e *DNSConfigError) Temporary() bool { return false }
   579	
   580	// Various errors contained in DNSError.
   581	var (
   582		errNoSuchHost = errors.New("no such host")
   583	)
   584	
   585	// DNSError represents a DNS lookup error.
   586	type DNSError struct {
   587		Err         string // description of the error
   588		Name        string // name looked for
   589		Server      string // server used
   590		IsTimeout   bool   // if true, timed out; not all timeouts set this
   591		IsTemporary bool   // if true, error is temporary; not all errors set this
   592		IsNotFound  bool   // if true, host could not be found
   593	}
   594	
   595	func (e *DNSError) Error() string {
   596		if e == nil {
   597			return "<nil>"
   598		}
   599		s := "lookup " + e.Name
   600		if e.Server != "" {
   601			s += " on " + e.Server
   602		}
   603		s += ": " + e.Err
   604		return s
   605	}
   606	
   607	// Timeout reports whether the DNS lookup is known to have timed out.
   608	// This is not always known; a DNS lookup may fail due to a timeout
   609	// and return a DNSError for which Timeout returns false.
   610	func (e *DNSError) Timeout() bool { return e.IsTimeout }
   611	
   612	// Temporary reports whether the DNS error is known to be temporary.
   613	// This is not always known; a DNS lookup may fail due to a temporary
   614	// error and return a DNSError for which Temporary returns false.
   615	func (e *DNSError) Temporary() bool { return e.IsTimeout || e.IsTemporary }
   616	
   617	type writerOnly struct {
   618		io.Writer
   619	}
   620	
   621	// Fallback implementation of io.ReaderFrom's ReadFrom, when sendfile isn't
   622	// applicable.
   623	func genericReadFrom(w io.Writer, r io.Reader) (n int64, err error) {
   624		// Use wrapper to hide existing r.ReadFrom from io.Copy.
   625		return io.Copy(writerOnly{w}, r)
   626	}
   627	
   628	// Limit the number of concurrent cgo-using goroutines, because
   629	// each will block an entire operating system thread. The usual culprit
   630	// is resolving many DNS names in separate goroutines but the DNS
   631	// server is not responding. Then the many lookups each use a different
   632	// thread, and the system or the program runs out of threads.
   633	
   634	var threadLimit chan struct{}
   635	
   636	var threadOnce sync.Once
   637	
   638	func acquireThread() {
   639		threadOnce.Do(func() {
   640			threadLimit = make(chan struct{}, concurrentThreadsLimit())
   641		})
   642		threadLimit <- struct{}{}
   643	}
   644	
   645	func releaseThread() {
   646		<-threadLimit
   647	}
   648	
   649	// buffersWriter is the interface implemented by Conns that support a
   650	// "writev"-like batch write optimization.
   651	// writeBuffers should fully consume and write all chunks from the
   652	// provided Buffers, else it should report a non-nil error.
   653	type buffersWriter interface {
   654		writeBuffers(*Buffers) (int64, error)
   655	}
   656	
   657	// Buffers contains zero or more runs of bytes to write.
   658	//
   659	// On certain machines, for certain types of connections, this is
   660	// optimized into an OS-specific batch write operation (such as
   661	// "writev").
   662	type Buffers [][]byte
   663	
   664	var (
   665		_ io.WriterTo = (*Buffers)(nil)
   666		_ io.Reader   = (*Buffers)(nil)
   667	)
   668	
   669	func (v *Buffers) WriteTo(w io.Writer) (n int64, err error) {
   670		if wv, ok := w.(buffersWriter); ok {
   671			return wv.writeBuffers(v)
   672		}
   673		for _, b := range *v {
   674			nb, err := w.Write(b)
   675			n += int64(nb)
   676			if err != nil {
   677				v.consume(n)
   678				return n, err
   679			}
   680		}
   681		v.consume(n)
   682		return n, nil
   683	}
   684	
   685	func (v *Buffers) Read(p []byte) (n int, err error) {
   686		for len(p) > 0 && len(*v) > 0 {
   687			n0 := copy(p, (*v)[0])
   688			v.consume(int64(n0))
   689			p = p[n0:]
   690			n += n0
   691		}
   692		if len(*v) == 0 {
   693			err = io.EOF
   694		}
   695		return
   696	}
   697	
   698	func (v *Buffers) consume(n int64) {
   699		for len(*v) > 0 {
   700			ln0 := int64(len((*v)[0]))
   701			if ln0 > n {
   702				(*v)[0] = (*v)[0][n:]
   703				return
   704			}
   705			n -= ln0
   706			*v = (*v)[1:]
   707		}
   708	}
   709	

View as plain text