splice_linux.go 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  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. package net
  5. import (
  6. "internal/poll"
  7. "io"
  8. )
  9. // splice transfers data from r to c using the splice system call to minimize
  10. // copies from and to userspace. c must be a TCP connection. Currently, splice
  11. // is only enabled if r is a TCP or a stream-oriented Unix connection.
  12. //
  13. // If splice returns handled == false, it has performed no work.
  14. func splice(c *netFD, r io.Reader) (written int64, err error, handled bool) {
  15. var remain int64 = 1 << 62 // by default, copy until EOF
  16. lr, ok := r.(*io.LimitedReader)
  17. if ok {
  18. remain, r = lr.N, lr.R
  19. if remain <= 0 {
  20. return 0, nil, true
  21. }
  22. }
  23. var s *netFD
  24. if tc, ok := r.(*TCPConn); ok {
  25. s = tc.fd
  26. } else if uc, ok := r.(*UnixConn); ok {
  27. if uc.fd.net != "unix" {
  28. return 0, nil, false
  29. }
  30. s = uc.fd
  31. } else {
  32. return 0, nil, false
  33. }
  34. written, handled, sc, err := poll.Splice(&c.pfd, &s.pfd, remain)
  35. if lr != nil {
  36. lr.N -= written
  37. }
  38. return written, wrapSyscallError(sc, err), handled
  39. }