mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-03 20:27:35 +03:00
http3: reduce usage of bytes.Buffer (#3539)
This commit is contained in:
parent
dfd35cb071
commit
62b82789c0
10 changed files with 136 additions and 149 deletions
|
@ -1,7 +1,6 @@
|
|||
package http3
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
|
@ -136,11 +135,11 @@ func (c *client) setupConn() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buf := &bytes.Buffer{}
|
||||
quicvarint.Write(buf, streamTypeControlStream)
|
||||
b := make([]byte, 0, 64)
|
||||
b = quicvarint.Append(b, streamTypeControlStream)
|
||||
// send the SETTINGS frame
|
||||
(&settingsFrame{Datagram: c.opts.EnableDatagram, Other: c.opts.AdditionalSettings}).Write(buf)
|
||||
_, err = str.Write(buf.Bytes())
|
||||
b = (&settingsFrame{Datagram: c.opts.EnableDatagram, Other: c.opts.AdditionalSettings}).Append(b)
|
||||
_, err = str.Write(b)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -455,11 +455,11 @@ var _ = Describe("Client", func() {
|
|||
})
|
||||
|
||||
It("parses the SETTINGS frame", func() {
|
||||
buf := &bytes.Buffer{}
|
||||
quicvarint.Write(buf, streamTypeControlStream)
|
||||
(&settingsFrame{}).Write(buf)
|
||||
b := quicvarint.Append(nil, streamTypeControlStream)
|
||||
b = (&settingsFrame{}).Append(b)
|
||||
r := bytes.NewReader(b)
|
||||
controlStr := mockquic.NewMockStream(mockCtrl)
|
||||
controlStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes()
|
||||
controlStr.EXPECT().Read(gomock.Any()).DoAndReturn(r.Read).AnyTimes()
|
||||
conn.EXPECT().AcceptUniStream(gomock.Any()).DoAndReturn(func(context.Context) (quic.ReceiveStream, error) {
|
||||
return controlStr, nil
|
||||
})
|
||||
|
@ -521,11 +521,11 @@ var _ = Describe("Client", func() {
|
|||
})
|
||||
|
||||
It("errors when the first frame on the control stream is not a SETTINGS frame", func() {
|
||||
buf := &bytes.Buffer{}
|
||||
quicvarint.Write(buf, streamTypeControlStream)
|
||||
(&dataFrame{}).Write(buf)
|
||||
b := quicvarint.Append(nil, streamTypeControlStream)
|
||||
b = (&dataFrame{}).Append(b)
|
||||
r := bytes.NewReader(b)
|
||||
controlStr := mockquic.NewMockStream(mockCtrl)
|
||||
controlStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes()
|
||||
controlStr.EXPECT().Read(gomock.Any()).DoAndReturn(r.Read).AnyTimes()
|
||||
conn.EXPECT().AcceptUniStream(gomock.Any()).DoAndReturn(func(context.Context) (quic.ReceiveStream, error) {
|
||||
return controlStr, nil
|
||||
})
|
||||
|
@ -545,13 +545,11 @@ var _ = Describe("Client", func() {
|
|||
})
|
||||
|
||||
It("errors when parsing the frame on the control stream fails", func() {
|
||||
buf := &bytes.Buffer{}
|
||||
quicvarint.Write(buf, streamTypeControlStream)
|
||||
b := &bytes.Buffer{}
|
||||
(&settingsFrame{}).Write(b)
|
||||
buf.Write(b.Bytes()[:b.Len()-1])
|
||||
b := quicvarint.Append(nil, streamTypeControlStream)
|
||||
b = (&settingsFrame{}).Append(b)
|
||||
r := bytes.NewReader(b[:len(b)-1])
|
||||
controlStr := mockquic.NewMockStream(mockCtrl)
|
||||
controlStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes()
|
||||
controlStr.EXPECT().Read(gomock.Any()).DoAndReturn(r.Read).AnyTimes()
|
||||
conn.EXPECT().AcceptUniStream(gomock.Any()).DoAndReturn(func(context.Context) (quic.ReceiveStream, error) {
|
||||
return controlStr, nil
|
||||
})
|
||||
|
@ -595,11 +593,11 @@ var _ = Describe("Client", func() {
|
|||
|
||||
It("errors when the server advertises datagram support (and we enabled support for it)", func() {
|
||||
client.opts.EnableDatagram = true
|
||||
buf := &bytes.Buffer{}
|
||||
quicvarint.Write(buf, streamTypeControlStream)
|
||||
(&settingsFrame{Datagram: true}).Write(buf)
|
||||
b := quicvarint.Append(nil, streamTypeControlStream)
|
||||
b = (&settingsFrame{Datagram: true}).Append(b)
|
||||
r := bytes.NewReader(b)
|
||||
controlStr := mockquic.NewMockStream(mockCtrl)
|
||||
controlStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes()
|
||||
controlStr.EXPECT().Read(gomock.Any()).DoAndReturn(r.Read).AnyTimes()
|
||||
conn.EXPECT().AcceptUniStream(gomock.Any()).DoAndReturn(func(context.Context) (quic.ReceiveStream, error) {
|
||||
return controlStr, nil
|
||||
})
|
||||
|
@ -631,16 +629,15 @@ var _ = Describe("Client", func() {
|
|||
testDone := make(chan struct{})
|
||||
|
||||
getHeadersFrame := func(headers map[string]string) []byte {
|
||||
buf := &bytes.Buffer{}
|
||||
headerBuf := &bytes.Buffer{}
|
||||
enc := qpack.NewEncoder(headerBuf)
|
||||
for name, value := range headers {
|
||||
Expect(enc.WriteField(qpack.HeaderField{Name: name, Value: value})).To(Succeed())
|
||||
}
|
||||
Expect(enc.Close()).To(Succeed())
|
||||
(&headersFrame{Length: uint64(headerBuf.Len())}).Write(buf)
|
||||
buf.Write(headerBuf.Bytes())
|
||||
return buf.Bytes()
|
||||
b := (&headersFrame{Length: uint64(headerBuf.Len())}).Append(nil)
|
||||
b = append(b, headerBuf.Bytes()...)
|
||||
return b
|
||||
}
|
||||
|
||||
decodeHeader := func(str io.Reader) map[string]string {
|
||||
|
@ -805,18 +802,18 @@ var _ = Describe("Client", func() {
|
|||
|
||||
It("sets the Content-Length", func() {
|
||||
done := make(chan struct{})
|
||||
buf := &bytes.Buffer{}
|
||||
buf.Write(getHeadersFrame(map[string]string{
|
||||
b := getHeadersFrame(map[string]string{
|
||||
":status": "200",
|
||||
"Content-Length": "1337",
|
||||
}))
|
||||
(&dataFrame{Length: 0x6}).Write(buf)
|
||||
buf.Write([]byte("foobar"))
|
||||
})
|
||||
b = (&dataFrame{Length: 0x6}).Append(b)
|
||||
b = append(b, []byte("foobar")...)
|
||||
r := bytes.NewReader(b)
|
||||
str.EXPECT().Close().Do(func() { close(done) })
|
||||
conn.EXPECT().ConnectionState().Return(quic.ConnectionState{})
|
||||
str.EXPECT().CancelWrite(gomock.Any()).MaxTimes(1) // when reading the response errors
|
||||
// the response body is sent asynchronously, while already reading the response
|
||||
str.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes()
|
||||
str.EXPECT().Read(gomock.Any()).DoAndReturn(r.Read).AnyTimes()
|
||||
req, err := client.RoundTripOpt(req, RoundTripOpt{})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(req.ContentLength).To(BeEquivalentTo(1337))
|
||||
|
@ -824,24 +821,24 @@ var _ = Describe("Client", func() {
|
|||
})
|
||||
|
||||
It("closes the connection when the first frame is not a HEADERS frame", func() {
|
||||
buf := &bytes.Buffer{}
|
||||
(&dataFrame{Length: 0x42}).Write(buf)
|
||||
b := (&dataFrame{Length: 0x42}).Append(nil)
|
||||
conn.EXPECT().CloseWithError(quic.ApplicationErrorCode(errorFrameUnexpected), gomock.Any())
|
||||
closed := make(chan struct{})
|
||||
r := bytes.NewReader(b)
|
||||
str.EXPECT().Close().Do(func() { close(closed) })
|
||||
str.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes()
|
||||
str.EXPECT().Read(gomock.Any()).DoAndReturn(r.Read).AnyTimes()
|
||||
_, err := client.RoundTripOpt(req, RoundTripOpt{})
|
||||
Expect(err).To(MatchError("expected first frame to be a HEADERS frame"))
|
||||
Eventually(closed).Should(BeClosed())
|
||||
})
|
||||
|
||||
It("cancels the stream when the HEADERS frame is too large", func() {
|
||||
buf := &bytes.Buffer{}
|
||||
(&headersFrame{Length: 1338}).Write(buf)
|
||||
b := (&headersFrame{Length: 1338}).Append(nil)
|
||||
r := bytes.NewReader(b)
|
||||
str.EXPECT().CancelWrite(quic.StreamErrorCode(errorFrameError))
|
||||
closed := make(chan struct{})
|
||||
str.EXPECT().Close().Do(func() { close(closed) })
|
||||
str.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes()
|
||||
str.EXPECT().Read(gomock.Any()).DoAndReturn(r.Read).AnyTimes()
|
||||
_, err := client.RoundTripOpt(req, RoundTripOpt{})
|
||||
Expect(err).To(MatchError("HEADERS frame too large: 1338 bytes (max: 1337)"))
|
||||
Eventually(closed).Should(BeClosed())
|
||||
|
|
|
@ -74,18 +74,18 @@ type dataFrame struct {
|
|||
Length uint64
|
||||
}
|
||||
|
||||
func (f *dataFrame) Write(b *bytes.Buffer) {
|
||||
quicvarint.Write(b, 0x0)
|
||||
quicvarint.Write(b, f.Length)
|
||||
func (f *dataFrame) Append(b []byte) []byte {
|
||||
b = quicvarint.Append(b, 0x0)
|
||||
return quicvarint.Append(b, f.Length)
|
||||
}
|
||||
|
||||
type headersFrame struct {
|
||||
Length uint64
|
||||
}
|
||||
|
||||
func (f *headersFrame) Write(b *bytes.Buffer) {
|
||||
quicvarint.Write(b, 0x1)
|
||||
quicvarint.Write(b, f.Length)
|
||||
func (f *headersFrame) Append(b []byte) []byte {
|
||||
b = quicvarint.Append(b, 0x1)
|
||||
return quicvarint.Append(b, f.Length)
|
||||
}
|
||||
|
||||
const settingDatagram = 0xffd277
|
||||
|
@ -142,8 +142,8 @@ func parseSettingsFrame(r io.Reader, l uint64) (*settingsFrame, error) {
|
|||
return frame, nil
|
||||
}
|
||||
|
||||
func (f *settingsFrame) Write(b *bytes.Buffer) {
|
||||
quicvarint.Write(b, 0x4)
|
||||
func (f *settingsFrame) Append(b []byte) []byte {
|
||||
b = quicvarint.Append(b, 0x4)
|
||||
var l protocol.ByteCount
|
||||
for id, val := range f.Other {
|
||||
l += quicvarint.Len(id) + quicvarint.Len(val)
|
||||
|
@ -151,13 +151,14 @@ func (f *settingsFrame) Write(b *bytes.Buffer) {
|
|||
if f.Datagram {
|
||||
l += quicvarint.Len(settingDatagram) + quicvarint.Len(1)
|
||||
}
|
||||
quicvarint.Write(b, uint64(l))
|
||||
b = quicvarint.Append(b, uint64(l))
|
||||
if f.Datagram {
|
||||
quicvarint.Write(b, settingDatagram)
|
||||
quicvarint.Write(b, 1)
|
||||
b = quicvarint.Append(b, settingDatagram)
|
||||
b = quicvarint.Append(b, 1)
|
||||
}
|
||||
for id, val := range f.Other {
|
||||
quicvarint.Write(b, id)
|
||||
quicvarint.Write(b, val)
|
||||
b = quicvarint.Append(b, id)
|
||||
b = quicvarint.Append(b, val)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
|
|
@ -24,12 +24,12 @@ var _ = Describe("Frames", func() {
|
|||
}
|
||||
|
||||
It("skips unknown frames", func() {
|
||||
data := appendVarInt(nil, 0xdeadbeef) // type byte
|
||||
data = appendVarInt(data, 0x42)
|
||||
data = append(data, make([]byte, 0x42)...)
|
||||
buf := bytes.NewBuffer(data)
|
||||
(&dataFrame{Length: 0x1234}).Write(buf)
|
||||
frame, err := parseNextFrame(buf, nil)
|
||||
b := appendVarInt(nil, 0xdeadbeef) // type byte
|
||||
b = appendVarInt(b, 0x42)
|
||||
b = append(b, make([]byte, 0x42)...)
|
||||
b = (&dataFrame{Length: 0x1234}).Append(b)
|
||||
r := bytes.NewReader(b)
|
||||
frame, err := parseNextFrame(r, nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(frame).To(BeAssignableToTypeOf(&dataFrame{}))
|
||||
Expect(frame.(*dataFrame).Length).To(Equal(uint64(0x1234)))
|
||||
|
@ -46,9 +46,8 @@ var _ = Describe("Frames", func() {
|
|||
})
|
||||
|
||||
It("writes", func() {
|
||||
buf := &bytes.Buffer{}
|
||||
(&dataFrame{Length: 0xdeadbeef}).Write(buf)
|
||||
frame, err := parseNextFrame(buf, nil)
|
||||
b := (&dataFrame{Length: 0xdeadbeef}).Append(nil)
|
||||
frame, err := parseNextFrame(bytes.NewReader(b), nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(frame).To(BeAssignableToTypeOf(&dataFrame{}))
|
||||
|
@ -67,9 +66,8 @@ var _ = Describe("Frames", func() {
|
|||
})
|
||||
|
||||
It("writes", func() {
|
||||
buf := &bytes.Buffer{}
|
||||
(&headersFrame{Length: 0xdeadbeef}).Write(buf)
|
||||
frame, err := parseNextFrame(buf, nil)
|
||||
b := (&headersFrame{Length: 0xdeadbeef}).Append(nil)
|
||||
frame, err := parseNextFrame(bytes.NewReader(b), nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(frame).To(BeAssignableToTypeOf(&headersFrame{}))
|
||||
|
@ -112,9 +110,7 @@ var _ = Describe("Frames", func() {
|
|||
99: 999,
|
||||
13: 37,
|
||||
}}
|
||||
buf := &bytes.Buffer{}
|
||||
sf.Write(buf)
|
||||
frame, err := parseNextFrame(buf, nil)
|
||||
frame, err := parseNextFrame(bytes.NewReader(sf.Append(nil)), nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(frame).To(Equal(sf))
|
||||
})
|
||||
|
@ -124,10 +120,8 @@ var _ = Describe("Frames", func() {
|
|||
13: 37,
|
||||
0xdeadbeef: 0xdecafbad,
|
||||
}}
|
||||
buf := &bytes.Buffer{}
|
||||
sf.Write(buf)
|
||||
data := sf.Append(nil)
|
||||
|
||||
data := buf.Bytes()
|
||||
_, err := parseNextFrame(bytes.NewReader(data), nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
|
@ -177,9 +171,7 @@ var _ = Describe("Frames", func() {
|
|||
|
||||
It("writes the H3_DATAGRAM setting", func() {
|
||||
sf := &settingsFrame{Datagram: true}
|
||||
buf := &bytes.Buffer{}
|
||||
sf.Write(buf)
|
||||
frame, err := parseNextFrame(buf, nil)
|
||||
frame, err := parseNextFrame(bytes.NewReader(sf.Append(nil)), nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(frame).To(Equal(sf))
|
||||
})
|
||||
|
@ -222,16 +214,15 @@ var _ = Describe("Frames", func() {
|
|||
})
|
||||
|
||||
It("reads a frame without hijacking the stream", func() {
|
||||
buf := &bytes.Buffer{}
|
||||
quicvarint.Write(buf, 1337)
|
||||
b := quicvarint.Append(nil, 1337)
|
||||
customFrameContents := []byte("custom frame")
|
||||
quicvarint.Write(buf, uint64(len(customFrameContents)))
|
||||
buf.Write(customFrameContents)
|
||||
(&dataFrame{Length: 6}).Write(buf)
|
||||
buf.WriteString("foobar")
|
||||
b = quicvarint.Append(b, uint64(len(customFrameContents)))
|
||||
b = append(b, customFrameContents...)
|
||||
b = (&dataFrame{Length: 6}).Append(b)
|
||||
b = append(b, []byte("foobar")...)
|
||||
|
||||
var called bool
|
||||
frame, err := parseNextFrame(buf, func(ft FrameType, e error) (hijacked bool, err error) {
|
||||
frame, err := parseNextFrame(bytes.NewReader(b), func(ft FrameType, e error) (hijacked bool, err error) {
|
||||
Expect(e).ToNot(HaveOccurred())
|
||||
Expect(ft).To(BeEquivalentTo(1337))
|
||||
called = true
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package http3
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
|
@ -16,6 +15,8 @@ type Stream quic.Stream
|
|||
type stream struct {
|
||||
quic.Stream
|
||||
|
||||
buf []byte
|
||||
|
||||
onFrameError func()
|
||||
bytesRemainingInFrame uint64
|
||||
}
|
||||
|
@ -23,7 +24,11 @@ type stream struct {
|
|||
var _ Stream = &stream{}
|
||||
|
||||
func newStream(str quic.Stream, onFrameError func()) *stream {
|
||||
return &stream{Stream: str, onFrameError: onFrameError}
|
||||
return &stream{
|
||||
Stream: str,
|
||||
onFrameError: onFrameError,
|
||||
buf: make([]byte, 0, 16),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stream) Read(b []byte) (int, error) {
|
||||
|
@ -62,9 +67,9 @@ func (s *stream) Read(b []byte) (int, error) {
|
|||
}
|
||||
|
||||
func (s *stream) Write(b []byte) (int, error) {
|
||||
buf := &bytes.Buffer{}
|
||||
(&dataFrame{Length: uint64(len(b))}).Write(buf)
|
||||
if _, err := s.Stream.Write(buf.Bytes()); err != nil {
|
||||
s.buf = s.buf[:0]
|
||||
s.buf = (&dataFrame{Length: uint64(len(b))}).Append(s.buf)
|
||||
if _, err := s.Stream.Write(s.buf); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return s.Stream.Write(b)
|
||||
|
|
|
@ -22,10 +22,8 @@ var _ = Describe("Stream", func() {
|
|||
|
||||
errorCb := func() { errorCbCalled = true }
|
||||
getDataFrame := func(data []byte) []byte {
|
||||
b := &bytes.Buffer{}
|
||||
(&dataFrame{Length: uint64(len(data))}).Write(b)
|
||||
b.Write(data)
|
||||
return b.Bytes()
|
||||
b := (&dataFrame{Length: uint64(len(data))}).Append(nil)
|
||||
return append(b, data...)
|
||||
}
|
||||
|
||||
BeforeEach(func() {
|
||||
|
@ -96,15 +94,16 @@ var _ = Describe("Stream", func() {
|
|||
})
|
||||
|
||||
It("skips HEADERS frames", func() {
|
||||
buf.Write(getDataFrame([]byte("foo")))
|
||||
(&headersFrame{Length: 10}).Write(buf)
|
||||
buf.Write(make([]byte, 10))
|
||||
buf.Write(getDataFrame([]byte("bar")))
|
||||
b := make([]byte, 6)
|
||||
n, err := io.ReadFull(str, b)
|
||||
b := getDataFrame([]byte("foo"))
|
||||
b = (&headersFrame{Length: 10}).Append(b)
|
||||
b = append(b, make([]byte, 10)...)
|
||||
b = append(b, getDataFrame([]byte("bar"))...)
|
||||
buf.Write(b)
|
||||
r := make([]byte, 6)
|
||||
n, err := io.ReadFull(str, r)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(n).To(Equal(6))
|
||||
Expect(b).To(Equal([]byte("foobar")))
|
||||
Expect(r).To(Equal([]byte("foobar")))
|
||||
})
|
||||
|
||||
It("errors when it can't parse the frame", func() {
|
||||
|
@ -114,7 +113,8 @@ var _ = Describe("Stream", func() {
|
|||
})
|
||||
|
||||
It("errors on unexpected frames, and calls the error callback", func() {
|
||||
(&settingsFrame{}).Write(buf)
|
||||
b := (&settingsFrame{}).Append(nil)
|
||||
buf.Write(b)
|
||||
_, err := str.Read([]byte{0})
|
||||
Expect(err).To(MatchError("peer sent an unexpected frame: *http3.settingsFrame"))
|
||||
Expect(errorCbCalled).To(BeTrue())
|
||||
|
|
|
@ -58,10 +58,9 @@ func (w *requestWriter) writeHeaders(wr io.Writer, req *http.Request, gzip bool)
|
|||
return err
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
hf := headersFrame{Length: uint64(w.headerBuf.Len())}
|
||||
hf.Write(buf)
|
||||
if _, err := wr.Write(buf.Bytes()); err != nil {
|
||||
b := make([]byte, 0, 128)
|
||||
b = (&headersFrame{Length: uint64(w.headerBuf.Len())}).Append(b)
|
||||
if _, err := wr.Write(b); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := wr.Write(w.headerBuf.Bytes())
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
type responseWriter struct {
|
||||
conn quic.Connection
|
||||
bufferedStr *bufio.Writer
|
||||
buf []byte
|
||||
|
||||
header http.Header
|
||||
status int // status code passed to WriteHeader
|
||||
|
@ -32,6 +33,7 @@ var (
|
|||
func newResponseWriter(str quic.Stream, conn quic.Connection, logger utils.Logger) *responseWriter {
|
||||
return &responseWriter{
|
||||
header: http.Header{},
|
||||
buf: make([]byte, 16),
|
||||
conn: conn,
|
||||
bufferedStr: bufio.NewWriter(str),
|
||||
logger: logger,
|
||||
|
@ -62,10 +64,10 @@ func (w *responseWriter) WriteHeader(status int) {
|
|||
}
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
(&headersFrame{Length: uint64(headers.Len())}).Write(buf)
|
||||
w.buf = w.buf[:0]
|
||||
w.buf = (&headersFrame{Length: uint64(headers.Len())}).Append(w.buf)
|
||||
w.logger.Infof("Responding with %d", status)
|
||||
if _, err := w.bufferedStr.Write(buf.Bytes()); err != nil {
|
||||
if _, err := w.bufferedStr.Write(w.buf); err != nil {
|
||||
w.logger.Errorf("could not write headers frame: %s", err.Error())
|
||||
}
|
||||
if _, err := w.bufferedStr.Write(headers.Bytes()); err != nil {
|
||||
|
@ -84,9 +86,9 @@ func (w *responseWriter) Write(p []byte) (int, error) {
|
|||
return 0, http.ErrBodyNotAllowed
|
||||
}
|
||||
df := &dataFrame{Length: uint64(len(p))}
|
||||
buf := &bytes.Buffer{}
|
||||
df.Write(buf)
|
||||
if _, err := w.bufferedStr.Write(buf.Bytes()); err != nil {
|
||||
w.buf = w.buf[:0]
|
||||
w.buf = df.Append(w.buf)
|
||||
if _, err := w.bufferedStr.Write(w.buf); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return w.bufferedStr.Write(p)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package http3
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
|
@ -413,10 +412,10 @@ func (s *Server) handleConn(conn quic.EarlyConnection) {
|
|||
s.logger.Debugf("Opening the control stream failed.")
|
||||
return
|
||||
}
|
||||
buf := &bytes.Buffer{}
|
||||
quicvarint.Write(buf, streamTypeControlStream) // stream type
|
||||
(&settingsFrame{Datagram: s.EnableDatagrams, Other: s.AdditionalSettings}).Write(buf)
|
||||
str.Write(buf.Bytes())
|
||||
b := make([]byte, 0, 64)
|
||||
b = quicvarint.Append(b, streamTypeControlStream) // stream type
|
||||
b = (&settingsFrame{Datagram: s.EnableDatagrams, Other: s.AdditionalSettings}).Append(b)
|
||||
str.Write(b)
|
||||
|
||||
go s.handleUnidirectionalStreams(conn)
|
||||
|
||||
|
|
|
@ -438,11 +438,11 @@ var _ = Describe("Server", func() {
|
|||
AfterEach(func() { testDone <- struct{}{} })
|
||||
|
||||
It("parses the SETTINGS frame", func() {
|
||||
buf := &bytes.Buffer{}
|
||||
quicvarint.Write(buf, streamTypeControlStream)
|
||||
(&settingsFrame{}).Write(buf)
|
||||
b := quicvarint.Append(nil, streamTypeControlStream)
|
||||
b = (&settingsFrame{}).Append(b)
|
||||
controlStr := mockquic.NewMockStream(mockCtrl)
|
||||
controlStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes()
|
||||
r := bytes.NewReader(b)
|
||||
controlStr.EXPECT().Read(gomock.Any()).DoAndReturn(r.Read).AnyTimes()
|
||||
conn.EXPECT().AcceptUniStream(gomock.Any()).DoAndReturn(func(context.Context) (quic.ReceiveStream, error) {
|
||||
return controlStr, nil
|
||||
})
|
||||
|
@ -501,11 +501,11 @@ var _ = Describe("Server", func() {
|
|||
})
|
||||
|
||||
It("errors when the first frame on the control stream is not a SETTINGS frame", func() {
|
||||
buf := &bytes.Buffer{}
|
||||
quicvarint.Write(buf, streamTypeControlStream)
|
||||
(&dataFrame{}).Write(buf)
|
||||
b := quicvarint.Append(nil, streamTypeControlStream)
|
||||
b = (&dataFrame{}).Append(b)
|
||||
controlStr := mockquic.NewMockStream(mockCtrl)
|
||||
controlStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes()
|
||||
r := bytes.NewReader(b)
|
||||
controlStr.EXPECT().Read(gomock.Any()).DoAndReturn(r.Read).AnyTimes()
|
||||
conn.EXPECT().AcceptUniStream(gomock.Any()).DoAndReturn(func(context.Context) (quic.ReceiveStream, error) {
|
||||
return controlStr, nil
|
||||
})
|
||||
|
@ -524,13 +524,11 @@ var _ = Describe("Server", func() {
|
|||
})
|
||||
|
||||
It("errors when parsing the frame on the control stream fails", func() {
|
||||
buf := &bytes.Buffer{}
|
||||
quicvarint.Write(buf, streamTypeControlStream)
|
||||
b := &bytes.Buffer{}
|
||||
(&settingsFrame{}).Write(b)
|
||||
buf.Write(b.Bytes()[:b.Len()-1])
|
||||
b := quicvarint.Append(nil, streamTypeControlStream)
|
||||
b = (&settingsFrame{}).Append(b)
|
||||
r := bytes.NewReader(b[:len(b)-1])
|
||||
controlStr := mockquic.NewMockStream(mockCtrl)
|
||||
controlStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes()
|
||||
controlStr.EXPECT().Read(gomock.Any()).DoAndReturn(r.Read).AnyTimes()
|
||||
conn.EXPECT().AcceptUniStream(gomock.Any()).DoAndReturn(func(context.Context) (quic.ReceiveStream, error) {
|
||||
return controlStr, nil
|
||||
})
|
||||
|
@ -549,11 +547,11 @@ var _ = Describe("Server", func() {
|
|||
})
|
||||
|
||||
It("errors when the client opens a push stream", func() {
|
||||
buf := &bytes.Buffer{}
|
||||
quicvarint.Write(buf, streamTypePushStream)
|
||||
(&dataFrame{}).Write(buf)
|
||||
b := quicvarint.Append(nil, streamTypePushStream)
|
||||
b = (&dataFrame{}).Append(b)
|
||||
r := bytes.NewReader(b)
|
||||
controlStr := mockquic.NewMockStream(mockCtrl)
|
||||
controlStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes()
|
||||
controlStr.EXPECT().Read(gomock.Any()).DoAndReturn(r.Read).AnyTimes()
|
||||
conn.EXPECT().AcceptUniStream(gomock.Any()).DoAndReturn(func(context.Context) (quic.ReceiveStream, error) {
|
||||
return controlStr, nil
|
||||
})
|
||||
|
@ -573,11 +571,11 @@ var _ = Describe("Server", func() {
|
|||
|
||||
It("errors when the client advertises datagram support (and we enabled support for it)", func() {
|
||||
s.EnableDatagrams = true
|
||||
buf := &bytes.Buffer{}
|
||||
quicvarint.Write(buf, streamTypeControlStream)
|
||||
(&settingsFrame{Datagram: true}).Write(buf)
|
||||
b := quicvarint.Append(nil, streamTypeControlStream)
|
||||
b = (&settingsFrame{Datagram: true}).Append(b)
|
||||
r := bytes.NewReader(b)
|
||||
controlStr := mockquic.NewMockStream(mockCtrl)
|
||||
controlStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes()
|
||||
controlStr.EXPECT().Read(gomock.Any()).DoAndReturn(r.Read).AnyTimes()
|
||||
conn.EXPECT().AcceptUniStream(gomock.Any()).DoAndReturn(func(context.Context) (quic.ReceiveStream, error) {
|
||||
return controlStr, nil
|
||||
})
|
||||
|
@ -628,11 +626,10 @@ var _ = Describe("Server", func() {
|
|||
})
|
||||
|
||||
requestData := encodeRequest(exampleGetRequest)
|
||||
buf := &bytes.Buffer{}
|
||||
(&dataFrame{Length: 6}).Write(buf) // add a body
|
||||
buf.Write([]byte("foobar"))
|
||||
b := (&dataFrame{Length: 6}).Append(nil) // add a body
|
||||
b = append(b, []byte("foobar")...)
|
||||
responseBuf := &bytes.Buffer{}
|
||||
setRequest(append(requestData, buf.Bytes()...))
|
||||
setRequest(append(requestData, b...))
|
||||
done := make(chan struct{})
|
||||
str.EXPECT().Context().Return(reqContext)
|
||||
str.EXPECT().Write(gomock.Any()).DoAndReturn(responseBuf.Write).AnyTimes()
|
||||
|
@ -655,10 +652,9 @@ var _ = Describe("Server", func() {
|
|||
})
|
||||
|
||||
requestData := encodeRequest(exampleGetRequest)
|
||||
buf := &bytes.Buffer{}
|
||||
(&dataFrame{Length: 6}).Write(buf) // add a body
|
||||
buf.Write([]byte("foobar"))
|
||||
setRequest(append(requestData, buf.Bytes()...))
|
||||
b := (&dataFrame{Length: 6}).Append(nil) // add a body
|
||||
b = append(b, []byte("foobar")...)
|
||||
setRequest(append(requestData, b...))
|
||||
str.EXPECT().Context().Return(reqContext)
|
||||
str.EXPECT().Write([]byte("foobar")).Return(6, nil)
|
||||
|
||||
|
@ -673,11 +669,10 @@ var _ = Describe("Server", func() {
|
|||
})
|
||||
|
||||
requestData := encodeRequest(exampleGetRequest)
|
||||
buf := &bytes.Buffer{}
|
||||
(&dataFrame{Length: 6}).Write(buf) // add a body
|
||||
buf.Write([]byte("foobar"))
|
||||
b := (&dataFrame{Length: 6}).Append(nil) // add a body
|
||||
b = append(b, []byte("foobar")...)
|
||||
responseBuf := &bytes.Buffer{}
|
||||
setRequest(append(requestData, buf.Bytes()...))
|
||||
setRequest(append(requestData, b...))
|
||||
done := make(chan struct{})
|
||||
str.EXPECT().Write(gomock.Any()).DoAndReturn(responseBuf.Write).AnyTimes()
|
||||
str.EXPECT().CancelWrite(quic.StreamErrorCode(errorFrameError)).Do(func(quic.StreamErrorCode) { close(done) })
|
||||
|
@ -707,9 +702,8 @@ var _ = Describe("Server", func() {
|
|||
close(handlerCalled)
|
||||
})
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
(&dataFrame{}).Write(buf)
|
||||
setRequest(buf.Bytes())
|
||||
b := (&dataFrame{}).Append(nil)
|
||||
setRequest(b)
|
||||
str.EXPECT().Write(gomock.Any()).DoAndReturn(func(p []byte) (int, error) {
|
||||
return len(p), nil
|
||||
}).AnyTimes()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue