github.com/mikelsr/quic-go@v0.36.1-0.20230701132136-1d9415b66898/http3/http_stream.go (about)

     1  package http3
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/mikelsr/quic-go"
     7  )
     8  
     9  // A Stream is a HTTP/3 stream.
    10  // When writing to and reading from the stream, data is framed in HTTP/3 DATA frames.
    11  type Stream quic.Stream
    12  
    13  // The stream conforms to the quic.Stream interface, but instead of writing to and reading directly
    14  // from the QUIC stream, it writes to and reads from the HTTP stream.
    15  type stream struct {
    16  	quic.Stream
    17  
    18  	buf []byte
    19  
    20  	onFrameError          func()
    21  	bytesRemainingInFrame uint64
    22  }
    23  
    24  var _ Stream = &stream{}
    25  
    26  func newStream(str quic.Stream, onFrameError func()) *stream {
    27  	return &stream{
    28  		Stream:       str,
    29  		onFrameError: onFrameError,
    30  		buf:          make([]byte, 0, 16),
    31  	}
    32  }
    33  
    34  func (s *stream) Read(b []byte) (int, error) {
    35  	if s.bytesRemainingInFrame == 0 {
    36  	parseLoop:
    37  		for {
    38  			frame, err := parseNextFrame(s.Stream, nil)
    39  			if err != nil {
    40  				return 0, err
    41  			}
    42  			switch f := frame.(type) {
    43  			case *headersFrame:
    44  				// skip HEADERS frames
    45  				continue
    46  			case *dataFrame:
    47  				s.bytesRemainingInFrame = f.Length
    48  				break parseLoop
    49  			default:
    50  				s.onFrameError()
    51  				// parseNextFrame skips over unknown frame types
    52  				// Therefore, this condition is only entered when we parsed another known frame type.
    53  				return 0, fmt.Errorf("peer sent an unexpected frame: %T", f)
    54  			}
    55  		}
    56  	}
    57  
    58  	var n int
    59  	var err error
    60  	if s.bytesRemainingInFrame < uint64(len(b)) {
    61  		n, err = s.Stream.Read(b[:s.bytesRemainingInFrame])
    62  	} else {
    63  		n, err = s.Stream.Read(b)
    64  	}
    65  	s.bytesRemainingInFrame -= uint64(n)
    66  	return n, err
    67  }
    68  
    69  func (s *stream) Write(b []byte) (int, error) {
    70  	s.buf = s.buf[:0]
    71  	s.buf = (&dataFrame{Length: uint64(len(b))}).Append(s.buf)
    72  	if _, err := s.Stream.Write(s.buf); err != nil {
    73  		return 0, err
    74  	}
    75  	return s.Stream.Write(b)
    76  }