diff options
Diffstat (limited to 'src/net/splice_linux.go')
-rw-r--r-- | src/net/splice_linux.go | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/src/net/splice_linux.go b/src/net/splice_linux.go new file mode 100644 index 0000000..69c3f65 --- /dev/null +++ b/src/net/splice_linux.go @@ -0,0 +1,44 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package net + +import ( + "internal/poll" + "io" +) + +// splice transfers data from r to c using the splice system call to minimize +// copies from and to userspace. c must be a TCP connection. Currently, splice +// is only enabled if r is a TCP or a stream-oriented Unix connection. +// +// If splice returns handled == false, it has performed no work. +func splice(c *netFD, r io.Reader) (written int64, err error, handled bool) { + var remain int64 = 1 << 62 // by default, copy until EOF + lr, ok := r.(*io.LimitedReader) + if ok { + remain, r = lr.N, lr.R + if remain <= 0 { + return 0, nil, true + } + } + + var s *netFD + if tc, ok := r.(*TCPConn); ok { + s = tc.fd + } else if uc, ok := r.(*UnixConn); ok { + if uc.fd.net != "unix" { + return 0, nil, false + } + s = uc.fd + } else { + return 0, nil, false + } + + written, handled, sc, err := poll.Splice(&c.pfd, &s.pfd, remain) + if lr != nil { + lr.N -= written + } + return written, wrapSyscallError(sc, err), handled +} |