Source file src/net/splice_linux.go

     1  // Copyright 2018 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  package net
     6  
     7  import (
     8  	"internal/poll"
     9  	"io"
    10  )
    11  
    12  var pollSplice = poll.Splice
    13  
    14  // spliceFrom transfers data from r to c using the splice system call to minimize
    15  // copies from and to userspace. c must be a TCP connection.
    16  // Currently, spliceFrom is only enabled if r is a TCP or a stream-oriented Unix connection.
    17  //
    18  // If spliceFrom returns handled == false, it has performed no work.
    19  func spliceFrom(c *netFD, r io.Reader) (written int64, err error, handled bool) {
    20  	var remain int64 = 1<<63 - 1 // by default, copy until EOF
    21  	lr, ok := r.(*io.LimitedReader)
    22  	if ok {
    23  		remain, r = lr.N, lr.R
    24  		if remain <= 0 {
    25  			return 0, nil, true
    26  		}
    27  	}
    28  
    29  	var s *netFD
    30  	switch v := r.(type) {
    31  	case *TCPConn:
    32  		s = v.fd
    33  	case tcpConnWithoutWriteTo:
    34  		s = v.fd
    35  	case *UnixConn:
    36  		if v.fd.net != "unix" {
    37  			return 0, nil, false
    38  		}
    39  		s = v.fd
    40  	default:
    41  		return 0, nil, false
    42  	}
    43  
    44  	written, handled, err = pollSplice(&c.pfd, &s.pfd, remain)
    45  	if lr != nil {
    46  		lr.N -= written
    47  	}
    48  	return written, wrapSyscallError("splice", err), handled
    49  }
    50  
    51  // spliceTo transfers data from c to w using the splice system call to minimize
    52  // copies from and to userspace. c must be a TCP connection.
    53  // Currently, spliceTo is only enabled if w is a stream-oriented Unix connection.
    54  //
    55  // If spliceTo returns handled == false, it has performed no work.
    56  func spliceTo(w io.Writer, c *netFD) (written int64, err error, handled bool) {
    57  	uc, ok := w.(*UnixConn)
    58  	if !ok || uc.fd.net != "unix" {
    59  		return
    60  	}
    61  
    62  	written, handled, err = pollSplice(&uc.fd.pfd, &c.pfd, 1<<63-1)
    63  	return written, wrapSyscallError("splice", err), handled
    64  }
    65  

View as plain text