From 6fb0a652247e853098124d0e86f3721a8b44abe5 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Tue, 30 Aug 2022 11:06:57 +0300 Subject: [PATCH] http3: reduce usage of bytes.Buffer --- http3/client.go | 9 +++--- http3/client_test.go | 65 ++++++++++++++++++------------------- http3/frames.go | 27 ++++++++-------- http3/frames_test.go | 47 +++++++++++---------------- http3/http_stream.go | 15 ++++++--- http3/http_stream_test.go | 24 +++++++------- http3/request_writer.go | 7 ++-- http3/response_writer.go | 14 ++++---- http3/server.go | 9 +++--- http3/server_test.go | 68 ++++++++++++++++++--------------------- 10 files changed, 136 insertions(+), 149 deletions(-) diff --git a/http3/client.go b/http3/client.go index 90115e4b1b8..4f7e24ce6cb 100644 --- a/http3/client.go +++ b/http3/client.go @@ -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 } diff --git a/http3/client_test.go b/http3/client_test.go index beaf29f8345..f8988e7e08c 100644 --- a/http3/client_test.go +++ b/http3/client_test.go @@ -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()) diff --git a/http3/frames.go b/http3/frames.go index af9f28eb9f5..dac71391332 100644 --- a/http3/frames.go +++ b/http3/frames.go @@ -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 } diff --git a/http3/frames_test.go b/http3/frames_test.go index 1066b605ac1..e8f064383eb 100644 --- a/http3/frames_test.go +++ b/http3/frames_test.go @@ -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 diff --git a/http3/http_stream.go b/http3/http_stream.go index 4c69068cdbb..b7593d76108 100644 --- a/http3/http_stream.go +++ b/http3/http_stream.go @@ -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) diff --git a/http3/http_stream_test.go b/http3/http_stream_test.go index ad9833b97c9..c71da5befd9 100644 --- a/http3/http_stream_test.go +++ b/http3/http_stream_test.go @@ -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()) diff --git a/http3/request_writer.go b/http3/request_writer.go index 3dd1cbaef34..cb787b7dd6a 100644 --- a/http3/request_writer.go +++ b/http3/request_writer.go @@ -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()) diff --git a/http3/response_writer.go b/http3/response_writer.go index 70a7cd3f484..4753015e34c 100644 --- a/http3/response_writer.go +++ b/http3/response_writer.go @@ -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) diff --git a/http3/server.go b/http3/server.go index 086bc8e2564..b0204416781 100644 --- a/http3/server.go +++ b/http3/server.go @@ -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) diff --git a/http3/server_test.go b/http3/server_test.go index c185257184f..9008067e8a2 100644 --- a/http3/server_test.go +++ b/http3/server_test.go @@ -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()