forked from ebhomengo/niki
1
0
Fork 0
niki/vendor/golang.org/x/net/http2/pipe.go

327 lines
4.4 KiB
Go
Raw Normal View History

2024-02-18 10:42:21 +00:00
// Copyright 2014 The Go Authors. All rights reserved.
2024-02-18 10:42:21 +00:00
// Use of this source code is governed by a BSD-style
2024-02-18 10:42:21 +00:00
// license that can be found in the LICENSE file.
package http2
import (
"errors"
"io"
"sync"
)
// pipe is a goroutine-safe io.Reader/io.Writer pair. It's like
2024-02-18 10:42:21 +00:00
// io.Pipe except there are no PipeReader/PipeWriter halves, and the
2024-02-18 10:42:21 +00:00
// underlying buffer is an interface. (io.Pipe is always unbuffered)
2024-02-18 10:42:21 +00:00
type pipe struct {
mu sync.Mutex
c sync.Cond // c.L lazily initialized to &p.mu
b pipeBuffer // nil when done reading
unread int // bytes unread when done
err error // read error once empty. non-nil means closed.
breakErr error // immediate read error (caller doesn't see rest of b)
donec chan struct{} // closed on error
readFn func() // optional code to run in Read before error
2024-02-18 10:42:21 +00:00
}
type pipeBuffer interface {
Len() int
2024-02-18 10:42:21 +00:00
io.Writer
2024-02-18 10:42:21 +00:00
io.Reader
}
// setBuffer initializes the pipe buffer.
2024-02-18 10:42:21 +00:00
// It has no effect if the pipe is already closed.
2024-02-18 10:42:21 +00:00
func (p *pipe) setBuffer(b pipeBuffer) {
2024-02-18 10:42:21 +00:00
p.mu.Lock()
2024-02-18 10:42:21 +00:00
defer p.mu.Unlock()
2024-02-18 10:42:21 +00:00
if p.err != nil || p.breakErr != nil {
2024-02-18 10:42:21 +00:00
return
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
p.b = b
2024-02-18 10:42:21 +00:00
}
func (p *pipe) Len() int {
2024-02-18 10:42:21 +00:00
p.mu.Lock()
2024-02-18 10:42:21 +00:00
defer p.mu.Unlock()
2024-02-18 10:42:21 +00:00
if p.b == nil {
2024-02-18 10:42:21 +00:00
return p.unread
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return p.b.Len()
2024-02-18 10:42:21 +00:00
}
// Read waits until data is available and copies bytes
2024-02-18 10:42:21 +00:00
// from the buffer into p.
2024-02-18 10:42:21 +00:00
func (p *pipe) Read(d []byte) (n int, err error) {
2024-02-18 10:42:21 +00:00
p.mu.Lock()
2024-02-18 10:42:21 +00:00
defer p.mu.Unlock()
2024-02-18 10:42:21 +00:00
if p.c.L == nil {
2024-02-18 10:42:21 +00:00
p.c.L = &p.mu
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
for {
2024-02-18 10:42:21 +00:00
if p.breakErr != nil {
2024-02-18 10:42:21 +00:00
return 0, p.breakErr
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
if p.b != nil && p.b.Len() > 0 {
2024-02-18 10:42:21 +00:00
return p.b.Read(d)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
if p.err != nil {
2024-02-18 10:42:21 +00:00
if p.readFn != nil {
p.readFn() // e.g. copy trailers
2024-02-18 10:42:21 +00:00
p.readFn = nil // not sticky like p.err
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
p.b = nil
2024-02-18 10:42:21 +00:00
return 0, p.err
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
p.c.Wait()
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
}
2024-05-14 13:07:09 +00:00
var (
errClosedPipeWrite = errors.New("write on closed buffer")
2024-05-14 13:07:09 +00:00
errUninitializedPipeWrite = errors.New("write on uninitialized buffer")
)
2024-02-18 10:42:21 +00:00
// Write copies bytes from p into the buffer and wakes a reader.
2024-02-18 10:42:21 +00:00
// It is an error to write more data than the buffer can hold.
2024-02-18 10:42:21 +00:00
func (p *pipe) Write(d []byte) (n int, err error) {
2024-02-18 10:42:21 +00:00
p.mu.Lock()
2024-02-18 10:42:21 +00:00
defer p.mu.Unlock()
2024-02-18 10:42:21 +00:00
if p.c.L == nil {
2024-02-18 10:42:21 +00:00
p.c.L = &p.mu
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
defer p.c.Signal()
2024-02-18 10:42:21 +00:00
if p.err != nil || p.breakErr != nil {
2024-02-18 10:42:21 +00:00
return 0, errClosedPipeWrite
2024-02-18 10:42:21 +00:00
}
2024-05-14 13:07:09 +00:00
// pipe.setBuffer is never invoked, leaving the buffer uninitialized.
2024-05-14 13:07:09 +00:00
// We shouldn't try to write to an uninitialized pipe,
2024-05-14 13:07:09 +00:00
// but returning an error is better than panicking.
2024-05-14 13:07:09 +00:00
if p.b == nil {
2024-05-14 13:07:09 +00:00
return 0, errUninitializedPipeWrite
2024-05-14 13:07:09 +00:00
}
2024-02-18 10:42:21 +00:00
return p.b.Write(d)
2024-02-18 10:42:21 +00:00
}
// CloseWithError causes the next Read (waking up a current blocked
2024-02-18 10:42:21 +00:00
// Read if needed) to return the provided err after all data has been
2024-02-18 10:42:21 +00:00
// read.
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// The error must be non-nil.
2024-02-18 10:42:21 +00:00
func (p *pipe) CloseWithError(err error) { p.closeWithError(&p.err, err, nil) }
// BreakWithError causes the next Read (waking up a current blocked
2024-02-18 10:42:21 +00:00
// Read if needed) to return the provided err immediately, without
2024-02-18 10:42:21 +00:00
// waiting for unread data.
2024-02-18 10:42:21 +00:00
func (p *pipe) BreakWithError(err error) { p.closeWithError(&p.breakErr, err, nil) }
// closeWithErrorAndCode is like CloseWithError but also sets some code to run
2024-02-18 10:42:21 +00:00
// in the caller's goroutine before returning the error.
2024-02-18 10:42:21 +00:00
func (p *pipe) closeWithErrorAndCode(err error, fn func()) { p.closeWithError(&p.err, err, fn) }
func (p *pipe) closeWithError(dst *error, err error, fn func()) {
2024-02-18 10:42:21 +00:00
if err == nil {
2024-02-18 10:42:21 +00:00
panic("err must be non-nil")
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
p.mu.Lock()
2024-02-18 10:42:21 +00:00
defer p.mu.Unlock()
2024-02-18 10:42:21 +00:00
if p.c.L == nil {
2024-02-18 10:42:21 +00:00
p.c.L = &p.mu
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
defer p.c.Signal()
2024-02-18 10:42:21 +00:00
if *dst != nil {
2024-02-18 10:42:21 +00:00
// Already been done.
2024-02-18 10:42:21 +00:00
return
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
p.readFn = fn
2024-02-18 10:42:21 +00:00
if dst == &p.breakErr {
2024-02-18 10:42:21 +00:00
if p.b != nil {
2024-02-18 10:42:21 +00:00
p.unread += p.b.Len()
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
p.b = nil
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
*dst = err
2024-02-18 10:42:21 +00:00
p.closeDoneLocked()
2024-02-18 10:42:21 +00:00
}
// requires p.mu be held.
2024-02-18 10:42:21 +00:00
func (p *pipe) closeDoneLocked() {
2024-02-18 10:42:21 +00:00
if p.donec == nil {
2024-02-18 10:42:21 +00:00
return
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
// Close if unclosed. This isn't racy since we always
2024-02-18 10:42:21 +00:00
// hold p.mu while closing.
2024-02-18 10:42:21 +00:00
select {
2024-02-18 10:42:21 +00:00
case <-p.donec:
2024-02-18 10:42:21 +00:00
default:
2024-02-18 10:42:21 +00:00
close(p.donec)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
}
// Err returns the error (if any) first set by BreakWithError or CloseWithError.
2024-02-18 10:42:21 +00:00
func (p *pipe) Err() error {
2024-02-18 10:42:21 +00:00
p.mu.Lock()
2024-02-18 10:42:21 +00:00
defer p.mu.Unlock()
2024-02-18 10:42:21 +00:00
if p.breakErr != nil {
2024-02-18 10:42:21 +00:00
return p.breakErr
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return p.err
2024-02-18 10:42:21 +00:00
}
// Done returns a channel which is closed if and when this pipe is closed
2024-02-18 10:42:21 +00:00
// with CloseWithError.
2024-02-18 10:42:21 +00:00
func (p *pipe) Done() <-chan struct{} {
2024-02-18 10:42:21 +00:00
p.mu.Lock()
2024-02-18 10:42:21 +00:00
defer p.mu.Unlock()
2024-02-18 10:42:21 +00:00
if p.donec == nil {
2024-02-18 10:42:21 +00:00
p.donec = make(chan struct{})
2024-02-18 10:42:21 +00:00
if p.err != nil || p.breakErr != nil {
2024-02-18 10:42:21 +00:00
// Already hit an error.
2024-02-18 10:42:21 +00:00
p.closeDoneLocked()
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return p.donec
2024-02-18 10:42:21 +00:00
}