diff --git a/http3/capsule_test.go b/http3/capsule_test.go index d79dad41..4920e887 100644 --- a/http3/capsule_test.go +++ b/http3/capsule_test.go @@ -12,12 +12,11 @@ import ( var _ = Describe("Capsule", func() { It("parses Capsules", func() { - var buf bytes.Buffer - quicvarint.Write(&buf, 1337) - quicvarint.Write(&buf, 6) - buf.WriteString("foobar") + b := quicvarint.Append(nil, 1337) + b = quicvarint.Append(b, 6) + b = append(b, []byte("foobar")...) - ct, r, err := ParseCapsule(&buf) + ct, r, err := ParseCapsule(bytes.NewReader(b)) Expect(err).ToNot(HaveOccurred()) Expect(ct).To(BeEquivalentTo(1337)) val, err := io.ReadAll(r) @@ -38,14 +37,12 @@ var _ = Describe("Capsule", func() { }) It("errors on EOF", func() { - var buf bytes.Buffer - quicvarint.Write(&buf, 1337) - quicvarint.Write(&buf, 6) - buf.WriteString("foobar") - data := buf.Bytes() + b := quicvarint.Append(nil, 1337) + b = quicvarint.Append(b, 6) + b = append(b, []byte("foobar")...) - for i := range data { - ct, r, err := ParseCapsule(bytes.NewReader(data[:i])) + for i := range b { + ct, r, err := ParseCapsule(bytes.NewReader(b[:i])) if err != nil { Expect(err).To(MatchError(io.ErrUnexpectedEOF)) continue diff --git a/http3/client_test.go b/http3/client_test.go index 79ad281a..6851e84c 100644 --- a/http3/client_test.go +++ b/http3/client_test.go @@ -226,8 +226,7 @@ var _ = Describe("Client", func() { return true, nil } - buf := &bytes.Buffer{} - quicvarint.Write(buf, 0x41) + buf := bytes.NewBuffer(quicvarint.Append(nil, 0x41)) unknownStr := mockquic.NewMockStream(mockCtrl) unknownStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes() conn.EXPECT().AcceptStream(gomock.Any()).Return(unknownStr, nil) @@ -249,8 +248,7 @@ var _ = Describe("Client", func() { return false, nil } - buf := &bytes.Buffer{} - quicvarint.Write(buf, 0x41) + buf := bytes.NewBuffer(quicvarint.Append(nil, 0x41)) unknownStr := mockquic.NewMockStream(mockCtrl) unknownStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes() conn.EXPECT().AcceptStream(gomock.Any()).Return(unknownStr, nil) @@ -272,8 +270,7 @@ var _ = Describe("Client", func() { return false, errors.New("error in hijacker") } - buf := &bytes.Buffer{} - quicvarint.Write(buf, 0x41) + buf := bytes.NewBuffer(quicvarint.Append(nil, 0x41)) unknownStr := mockquic.NewMockStream(mockCtrl) unknownStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes() conn.EXPECT().AcceptStream(gomock.Any()).Return(unknownStr, nil) @@ -354,8 +351,7 @@ var _ = Describe("Client", func() { return true } - buf := &bytes.Buffer{} - quicvarint.Write(buf, 0x54) + buf := bytes.NewBuffer(quicvarint.Append(nil, 0x54)) unknownStr := mockquic.NewMockStream(mockCtrl) unknownStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes() conn.EXPECT().AcceptUniStream(gomock.Any()).DoAndReturn(func(context.Context) (quic.ReceiveStream, error) { @@ -403,8 +399,7 @@ var _ = Describe("Client", func() { return false } - buf := &bytes.Buffer{} - quicvarint.Write(buf, 0x54) + buf := bytes.NewBuffer(quicvarint.Append(nil, 0x54)) unknownStr := mockquic.NewMockStream(mockCtrl) unknownStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes() unknownStr.EXPECT().CancelRead(quic.StreamErrorCode(errorStreamCreationError)) @@ -480,8 +475,7 @@ var _ = Describe("Client", func() { } It(fmt.Sprintf("ignores the QPACK %s streams", name), func() { - buf := &bytes.Buffer{} - quicvarint.Write(buf, streamType) + buf := bytes.NewBuffer(quicvarint.Append(nil, streamType)) str := mockquic.NewMockStream(mockCtrl) str.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes() @@ -499,8 +493,7 @@ var _ = Describe("Client", func() { } It("resets streams Other than the control stream and the QPACK streams", func() { - buf := &bytes.Buffer{} - quicvarint.Write(buf, 1337) + buf := bytes.NewBuffer(quicvarint.Append(nil, 0x1337)) str := mockquic.NewMockStream(mockCtrl) str.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes() done := make(chan struct{}) @@ -569,8 +562,7 @@ var _ = Describe("Client", func() { }) It("errors when parsing the server opens a push stream", func() { - buf := &bytes.Buffer{} - quicvarint.Write(buf, streamTypePushStream) + buf := bytes.NewBuffer(quicvarint.Append(nil, streamTypePushStream)) controlStr := mockquic.NewMockStream(mockCtrl) controlStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes() conn.EXPECT().AcceptUniStream(gomock.Any()).DoAndReturn(func(context.Context) (quic.ReceiveStream, error) { diff --git a/http3/frames_test.go b/http3/frames_test.go index 9f9a71ba..04e583d2 100644 --- a/http3/frames_test.go +++ b/http3/frames_test.go @@ -17,15 +17,9 @@ type errReader struct{ err error } func (e errReader) Read([]byte) (int, error) { return 0, e.err } var _ = Describe("Frames", func() { - appendVarInt := func(b []byte, val uint64) []byte { - buf := &bytes.Buffer{} - quicvarint.Write(buf, val) - return append(b, buf.Bytes()...) - } - It("skips unknown frames", func() { - b := appendVarInt(nil, 0xdeadbeef) // type byte - b = appendVarInt(b, 0x42) + b := quicvarint.Append(nil, 0xdeadbeef) // type byte + b = quicvarint.Append(b, 0x42) b = append(b, make([]byte, 0x42)...) b = (&dataFrame{Length: 0x1234}).Append(b) r := bytes.NewReader(b) @@ -37,8 +31,8 @@ var _ = Describe("Frames", func() { Context("DATA frames", func() { It("parses", func() { - data := appendVarInt(nil, 0) // type byte - data = appendVarInt(data, 0x1337) + data := quicvarint.Append(nil, 0) // type byte + data = quicvarint.Append(data, 0x1337) frame, err := parseNextFrame(bytes.NewReader(data), nil) Expect(err).ToNot(HaveOccurred()) Expect(frame).To(BeAssignableToTypeOf(&dataFrame{})) @@ -57,8 +51,8 @@ var _ = Describe("Frames", func() { Context("HEADERS frames", func() { It("parses", func() { - data := appendVarInt(nil, 1) // type byte - data = appendVarInt(data, 0x1337) + data := quicvarint.Append(nil, 1) // type byte + data = quicvarint.Append(data, 0x1337) frame, err := parseNextFrame(bytes.NewReader(data), nil) Expect(err).ToNot(HaveOccurred()) Expect(frame).To(BeAssignableToTypeOf(&headersFrame{})) @@ -77,12 +71,12 @@ var _ = Describe("Frames", func() { Context("SETTINGS frames", func() { It("parses", func() { - settings := appendVarInt(nil, 13) - settings = appendVarInt(settings, 37) - settings = appendVarInt(settings, 0xdead) - settings = appendVarInt(settings, 0xbeef) - data := appendVarInt(nil, 4) // type byte - data = appendVarInt(data, uint64(len(settings))) + settings := quicvarint.Append(nil, 13) + settings = quicvarint.Append(settings, 37) + settings = quicvarint.Append(settings, 0xdead) + settings = quicvarint.Append(settings, 0xbeef) + data := quicvarint.Append(nil, 4) // type byte + data = quicvarint.Append(data, uint64(len(settings))) data = append(data, settings...) frame, err := parseNextFrame(bytes.NewReader(data), nil) Expect(err).ToNot(HaveOccurred()) @@ -93,12 +87,12 @@ var _ = Describe("Frames", func() { }) It("rejects duplicate settings", func() { - settings := appendVarInt(nil, 13) - settings = appendVarInt(settings, 37) - settings = appendVarInt(settings, 13) - settings = appendVarInt(settings, 38) - data := appendVarInt(nil, 4) // type byte - data = appendVarInt(data, uint64(len(settings))) + settings := quicvarint.Append(nil, 13) + settings = quicvarint.Append(settings, 37) + settings = quicvarint.Append(settings, 13) + settings = quicvarint.Append(settings, 38) + data := quicvarint.Append(nil, 4) // type byte + data = quicvarint.Append(data, uint64(len(settings))) data = append(data, settings...) _, err := parseNextFrame(bytes.NewReader(data), nil) Expect(err).To(MatchError("duplicate setting: 13")) @@ -135,10 +129,10 @@ var _ = Describe("Frames", func() { Context("H3_DATAGRAM", func() { It("reads the H3_DATAGRAM value", func() { - settings := appendVarInt(nil, settingDatagram) - settings = appendVarInt(settings, 1) - data := appendVarInt(nil, 4) // type byte - data = appendVarInt(data, uint64(len(settings))) + settings := quicvarint.Append(nil, settingDatagram) + settings = quicvarint.Append(settings, 1) + data := quicvarint.Append(nil, 4) // type byte + data = quicvarint.Append(data, uint64(len(settings))) data = append(data, settings...) f, err := parseNextFrame(bytes.NewReader(data), nil) Expect(err).ToNot(HaveOccurred()) @@ -148,22 +142,22 @@ var _ = Describe("Frames", func() { }) It("rejects duplicate H3_DATAGRAM entries", func() { - settings := appendVarInt(nil, settingDatagram) - settings = appendVarInt(settings, 1) - settings = appendVarInt(settings, settingDatagram) - settings = appendVarInt(settings, 1) - data := appendVarInt(nil, 4) // type byte - data = appendVarInt(data, uint64(len(settings))) + settings := quicvarint.Append(nil, settingDatagram) + settings = quicvarint.Append(settings, 1) + settings = quicvarint.Append(settings, settingDatagram) + settings = quicvarint.Append(settings, 1) + data := quicvarint.Append(nil, 4) // type byte + data = quicvarint.Append(data, uint64(len(settings))) data = append(data, settings...) _, err := parseNextFrame(bytes.NewReader(data), nil) Expect(err).To(MatchError(fmt.Sprintf("duplicate setting: %d", settingDatagram))) }) It("rejects invalid values for the H3_DATAGRAM entry", func() { - settings := appendVarInt(nil, settingDatagram) - settings = appendVarInt(settings, 1337) - data := appendVarInt(nil, 4) // type byte - data = appendVarInt(data, uint64(len(settings))) + settings := quicvarint.Append(nil, settingDatagram) + settings = quicvarint.Append(settings, 1337) + data := quicvarint.Append(nil, 4) // type byte + data = quicvarint.Append(data, uint64(len(settings))) data = append(data, settings...) _, err := parseNextFrame(bytes.NewReader(data), nil) Expect(err).To(MatchError("invalid value for H3_DATAGRAM: 1337")) @@ -180,8 +174,7 @@ var _ = Describe("Frames", func() { Context("hijacking", func() { It("reads a frame without hijacking the stream", func() { - buf := &bytes.Buffer{} - quicvarint.Write(buf, 1337) + buf := bytes.NewBuffer(quicvarint.Append(nil, 1337)) customFrameContents := []byte("foobar") buf.Write(customFrameContents) diff --git a/http3/server_test.go b/http3/server_test.go index 9b2a7e43..93fdaa31 100644 --- a/http3/server_test.go +++ b/http3/server_test.go @@ -260,8 +260,7 @@ var _ = Describe("Server", func() { return true, nil } - buf := &bytes.Buffer{} - quicvarint.Write(buf, 0x41) + buf := bytes.NewBuffer(quicvarint.Append(nil, 0x41)) unknownStr := mockquic.NewMockStream(mockCtrl) unknownStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes() conn.EXPECT().AcceptStream(gomock.Any()).Return(unknownStr, nil) @@ -283,8 +282,7 @@ var _ = Describe("Server", func() { return false, nil } - buf := &bytes.Buffer{} - quicvarint.Write(buf, 0x41) + buf := bytes.NewBuffer(quicvarint.Append(nil, 0x41)) unknownStr := mockquic.NewMockStream(mockCtrl) unknownStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes() unknownStr.EXPECT().CancelWrite(quic.StreamErrorCode(errorRequestIncomplete)) @@ -307,8 +305,7 @@ var _ = Describe("Server", func() { return false, errors.New("error in hijacker") } - buf := &bytes.Buffer{} - quicvarint.Write(buf, 0x41) + buf := bytes.NewBuffer(quicvarint.Append(nil, 0x41)) unknownStr := mockquic.NewMockStream(mockCtrl) unknownStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes() unknownStr.EXPECT().CancelWrite(quic.StreamErrorCode(errorRequestIncomplete)) @@ -373,8 +370,7 @@ var _ = Describe("Server", func() { return true } - buf := &bytes.Buffer{} - quicvarint.Write(buf, 0x54) + buf := bytes.NewBuffer(quicvarint.Append(nil, 0x54)) unknownStr := mockquic.NewMockStream(mockCtrl) unknownStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes() conn.EXPECT().AcceptUniStream(gomock.Any()).DoAndReturn(func(context.Context) (quic.ReceiveStream, error) { @@ -420,8 +416,7 @@ var _ = Describe("Server", func() { return false } - buf := &bytes.Buffer{} - quicvarint.Write(buf, 0x54) + buf := bytes.NewBuffer(quicvarint.Append(nil, 0x54)) unknownStr := mockquic.NewMockStream(mockCtrl) unknownStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes() unknownStr.EXPECT().CancelRead(quic.StreamErrorCode(errorStreamCreationError)) @@ -480,8 +475,7 @@ var _ = Describe("Server", func() { } It(fmt.Sprintf("ignores the QPACK %s streams", name), func() { - buf := &bytes.Buffer{} - quicvarint.Write(buf, streamType) + buf := bytes.NewBuffer(quicvarint.Append(nil, streamType)) str := mockquic.NewMockStream(mockCtrl) str.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes() @@ -498,8 +492,7 @@ var _ = Describe("Server", func() { } It("reset streams other than the control stream and the QPACK streams", func() { - buf := &bytes.Buffer{} - quicvarint.Write(buf, 1337) + buf := bytes.NewBuffer(quicvarint.Append(nil, 0o1337)) str := mockquic.NewMockStream(mockCtrl) str.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes() done := make(chan struct{}) diff --git a/internal/handshake/session_ticket_test.go b/internal/handshake/session_ticket_test.go index 13c589f7..67e33b22 100644 --- a/internal/handshake/session_ticket_test.go +++ b/internal/handshake/session_ticket_test.go @@ -1,7 +1,6 @@ package handshake import ( - "bytes" "time" "github.com/quic-go/quic-go/internal/wire" @@ -34,22 +33,19 @@ var _ = Describe("Session Ticket", func() { }) It("refuses to unmarshal if the revision doesn't match", func() { - b := &bytes.Buffer{} - quicvarint.Write(b, 1337) - Expect((&sessionTicket{}).Unmarshal(b.Bytes())).To(MatchError("unknown session ticket revision: 1337")) + b := quicvarint.Append(nil, 1337) + Expect((&sessionTicket{}).Unmarshal(b)).To(MatchError("unknown session ticket revision: 1337")) }) It("refuses to unmarshal if the RTT cannot be read", func() { - b := &bytes.Buffer{} - quicvarint.Write(b, sessionTicketRevision) - Expect((&sessionTicket{}).Unmarshal(b.Bytes())).To(MatchError("failed to read RTT")) + b := quicvarint.Append(nil, sessionTicketRevision) + Expect((&sessionTicket{}).Unmarshal(b)).To(MatchError("failed to read RTT")) }) It("refuses to unmarshal if unmarshaling the transport parameters fails", func() { - b := &bytes.Buffer{} - quicvarint.Write(b, sessionTicketRevision) - b.Write([]byte("foobar")) - err := (&sessionTicket{}).Unmarshal(b.Bytes()) + b := quicvarint.Append(nil, sessionTicketRevision) + b = append(b, []byte("foobar")...) + err := (&sessionTicket{}).Unmarshal(b) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("unmarshaling transport parameters from session ticket failed")) }) diff --git a/internal/wire/transport_parameter_test.go b/internal/wire/transport_parameter_test.go index c7186b19..813ffeef 100644 --- a/internal/wire/transport_parameter_test.go +++ b/internal/wire/transport_parameter_test.go @@ -34,10 +34,10 @@ var _ = Describe("Transport Parameters", func() { rand.Seed(GinkgoRandomSeed()) }) - addInitialSourceConnectionID := func(b *bytes.Buffer) { - quicvarint.Write(b, uint64(initialSourceConnectionIDParameterID)) - quicvarint.Write(b, 6) - b.Write([]byte("foobar")) + appendInitialSourceConnectionID := func(b []byte) []byte { + b = quicvarint.Append(b, uint64(initialSourceConnectionIDParameterID)) + b = quicvarint.Append(b, 6) + return append(b, []byte("foobar")...) } It("has a string representation", func() { @@ -149,45 +149,41 @@ var _ = Describe("Transport Parameters", func() { }) It("errors when the stateless_reset_token has the wrong length", func() { - b := &bytes.Buffer{} - quicvarint.Write(b, uint64(statelessResetTokenParameterID)) - quicvarint.Write(b, 15) - b.Write(make([]byte, 15)) - Expect((&TransportParameters{}).Unmarshal(b.Bytes(), protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ + b := quicvarint.Append(nil, uint64(statelessResetTokenParameterID)) + b = quicvarint.Append(b, 15) + b = append(b, make([]byte, 15)...) + Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ ErrorCode: qerr.TransportParameterError, ErrorMessage: "wrong length for stateless_reset_token: 15 (expected 16)", })) }) It("errors when the max_packet_size is too small", func() { - b := &bytes.Buffer{} - quicvarint.Write(b, uint64(maxUDPPayloadSizeParameterID)) - quicvarint.Write(b, uint64(quicvarint.Len(1199))) - quicvarint.Write(b, 1199) - Expect((&TransportParameters{}).Unmarshal(b.Bytes(), protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ + b := quicvarint.Append(nil, uint64(maxUDPPayloadSizeParameterID)) + b = quicvarint.Append(b, uint64(quicvarint.Len(1199))) + b = quicvarint.Append(b, 1199) + Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ ErrorCode: qerr.TransportParameterError, ErrorMessage: "invalid value for max_packet_size: 1199 (minimum 1200)", })) }) It("errors when disable_active_migration has content", func() { - b := &bytes.Buffer{} - quicvarint.Write(b, uint64(disableActiveMigrationParameterID)) - quicvarint.Write(b, 6) - b.Write([]byte("foobar")) - Expect((&TransportParameters{}).Unmarshal(b.Bytes(), protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ + b := quicvarint.Append(nil, uint64(disableActiveMigrationParameterID)) + b = quicvarint.Append(b, 6) + b = append(b, []byte("foobar")...) + Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ ErrorCode: qerr.TransportParameterError, ErrorMessage: "wrong length for disable_active_migration: 6 (expected empty)", })) }) It("errors when the server doesn't set the original_destination_connection_id", func() { - b := &bytes.Buffer{} - quicvarint.Write(b, uint64(statelessResetTokenParameterID)) - quicvarint.Write(b, 16) - b.Write(make([]byte, 16)) - addInitialSourceConnectionID(b) - Expect((&TransportParameters{}).Unmarshal(b.Bytes(), protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ + b := quicvarint.Append(nil, uint64(statelessResetTokenParameterID)) + b = quicvarint.Append(b, 16) + b = append(b, make([]byte, 16)...) + b = appendInitialSourceConnectionID(b) + Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ ErrorCode: qerr.TransportParameterError, ErrorMessage: "missing original_destination_connection_id", })) @@ -289,127 +285,118 @@ var _ = Describe("Transport Parameters", func() { }) It("errors when the varint value has the wrong length", func() { - b := &bytes.Buffer{} - quicvarint.Write(b, uint64(initialMaxStreamDataBidiLocalParameterID)) - quicvarint.Write(b, 2) + b := quicvarint.Append(nil, uint64(initialMaxStreamDataBidiLocalParameterID)) + b = quicvarint.Append(b, 2) val := uint64(0xdeadbeef) Expect(quicvarint.Len(val)).ToNot(BeEquivalentTo(2)) - quicvarint.Write(b, val) - addInitialSourceConnectionID(b) - Expect((&TransportParameters{}).Unmarshal(b.Bytes(), protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ + b = quicvarint.Append(b, val) + b = appendInitialSourceConnectionID(b) + Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ ErrorCode: qerr.TransportParameterError, ErrorMessage: fmt.Sprintf("inconsistent transport parameter length for transport parameter %#x", initialMaxStreamDataBidiLocalParameterID), })) }) It("errors if initial_max_streams_bidi is too large", func() { - b := &bytes.Buffer{} - quicvarint.Write(b, uint64(initialMaxStreamsBidiParameterID)) - quicvarint.Write(b, uint64(quicvarint.Len(uint64(protocol.MaxStreamCount+1)))) - quicvarint.Write(b, uint64(protocol.MaxStreamCount+1)) - addInitialSourceConnectionID(b) - Expect((&TransportParameters{}).Unmarshal(b.Bytes(), protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ + b := quicvarint.Append(nil, uint64(initialMaxStreamsBidiParameterID)) + b = quicvarint.Append(b, uint64(quicvarint.Len(uint64(protocol.MaxStreamCount+1)))) + b = quicvarint.Append(b, uint64(protocol.MaxStreamCount+1)) + b = appendInitialSourceConnectionID(b) + Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ ErrorCode: qerr.TransportParameterError, ErrorMessage: "initial_max_streams_bidi too large: 1152921504606846977 (maximum 1152921504606846976)", })) }) It("errors if initial_max_streams_uni is too large", func() { - b := &bytes.Buffer{} - quicvarint.Write(b, uint64(initialMaxStreamsUniParameterID)) - quicvarint.Write(b, uint64(quicvarint.Len(uint64(protocol.MaxStreamCount+1)))) - quicvarint.Write(b, uint64(protocol.MaxStreamCount+1)) - addInitialSourceConnectionID(b) - Expect((&TransportParameters{}).Unmarshal(b.Bytes(), protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ + b := quicvarint.Append(nil, uint64(initialMaxStreamsUniParameterID)) + b = quicvarint.Append(b, uint64(quicvarint.Len(uint64(protocol.MaxStreamCount+1)))) + b = quicvarint.Append(b, uint64(protocol.MaxStreamCount+1)) + b = appendInitialSourceConnectionID(b) + Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ ErrorCode: qerr.TransportParameterError, ErrorMessage: "initial_max_streams_uni too large: 1152921504606846977 (maximum 1152921504606846976)", })) }) It("handles huge max_ack_delay values", func() { - b := &bytes.Buffer{} val := uint64(math.MaxUint64) / 5 - quicvarint.Write(b, uint64(maxAckDelayParameterID)) - quicvarint.Write(b, uint64(quicvarint.Len(val))) - quicvarint.Write(b, val) - addInitialSourceConnectionID(b) - Expect((&TransportParameters{}).Unmarshal(b.Bytes(), protocol.PerspectiveClient)).To(MatchError(&qerr.TransportError{ + b := quicvarint.Append(nil, uint64(maxAckDelayParameterID)) + b = quicvarint.Append(b, uint64(quicvarint.Len(val))) + b = quicvarint.Append(b, val) + b = appendInitialSourceConnectionID(b) + Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveClient)).To(MatchError(&qerr.TransportError{ ErrorCode: qerr.TransportParameterError, ErrorMessage: "invalid value for max_ack_delay: 3689348814741910323ms (maximum 16383ms)", })) }) It("skips unknown parameters", func() { - b := &bytes.Buffer{} // write a known parameter - quicvarint.Write(b, uint64(initialMaxStreamDataBidiLocalParameterID)) - quicvarint.Write(b, uint64(quicvarint.Len(0x1337))) - quicvarint.Write(b, 0x1337) + b := quicvarint.Append(nil, uint64(initialMaxStreamDataBidiLocalParameterID)) + b = quicvarint.Append(b, uint64(quicvarint.Len(0x1337))) + b = quicvarint.Append(b, 0x1337) // write an unknown parameter - quicvarint.Write(b, 0x42) - quicvarint.Write(b, 6) - b.Write([]byte("foobar")) + b = quicvarint.Append(b, 0x42) + b = quicvarint.Append(b, 6) + b = append(b, []byte("foobar")...) // write a known parameter - quicvarint.Write(b, uint64(initialMaxStreamDataBidiRemoteParameterID)) - quicvarint.Write(b, uint64(quicvarint.Len(0x42))) - quicvarint.Write(b, 0x42) - addInitialSourceConnectionID(b) + b = quicvarint.Append(b, uint64(initialMaxStreamDataBidiRemoteParameterID)) + b = quicvarint.Append(b, uint64(quicvarint.Len(0x42))) + b = quicvarint.Append(b, 0x42) + b = appendInitialSourceConnectionID(b) p := &TransportParameters{} - Expect(p.Unmarshal(b.Bytes(), protocol.PerspectiveClient)).To(Succeed()) + Expect(p.Unmarshal(b, protocol.PerspectiveClient)).To(Succeed()) Expect(p.InitialMaxStreamDataBidiLocal).To(Equal(protocol.ByteCount(0x1337))) Expect(p.InitialMaxStreamDataBidiRemote).To(Equal(protocol.ByteCount(0x42))) }) It("rejects duplicate parameters", func() { - b := &bytes.Buffer{} // write first parameter - quicvarint.Write(b, uint64(initialMaxStreamDataBidiLocalParameterID)) - quicvarint.Write(b, uint64(quicvarint.Len(0x1337))) - quicvarint.Write(b, 0x1337) + b := quicvarint.Append(nil, uint64(initialMaxStreamDataBidiLocalParameterID)) + b = quicvarint.Append(b, uint64(quicvarint.Len(0x1337))) + b = quicvarint.Append(b, 0x1337) // write a second parameter - quicvarint.Write(b, uint64(initialMaxStreamDataBidiRemoteParameterID)) - quicvarint.Write(b, uint64(quicvarint.Len(0x42))) - quicvarint.Write(b, 0x42) + b = quicvarint.Append(b, uint64(initialMaxStreamDataBidiRemoteParameterID)) + b = quicvarint.Append(b, uint64(quicvarint.Len(0x42))) + b = quicvarint.Append(b, 0x42) // write first parameter again - quicvarint.Write(b, uint64(initialMaxStreamDataBidiLocalParameterID)) - quicvarint.Write(b, uint64(quicvarint.Len(0x1337))) - quicvarint.Write(b, 0x1337) - addInitialSourceConnectionID(b) - Expect((&TransportParameters{}).Unmarshal(b.Bytes(), protocol.PerspectiveClient)).To(MatchError(&qerr.TransportError{ + b = quicvarint.Append(b, uint64(initialMaxStreamDataBidiLocalParameterID)) + b = quicvarint.Append(b, uint64(quicvarint.Len(0x1337))) + b = quicvarint.Append(b, 0x1337) + b = appendInitialSourceConnectionID(b) + Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveClient)).To(MatchError(&qerr.TransportError{ ErrorCode: qerr.TransportParameterError, ErrorMessage: fmt.Sprintf("received duplicate transport parameter %#x", initialMaxStreamDataBidiLocalParameterID), })) }) It("errors if there's not enough data to read", func() { - b := &bytes.Buffer{} - quicvarint.Write(b, 0x42) - quicvarint.Write(b, 7) - b.Write([]byte("foobar")) + b := quicvarint.Append(nil, 0x42) + b = quicvarint.Append(b, 7) + b = append(b, []byte("foobar")...) p := &TransportParameters{} - Expect(p.Unmarshal(b.Bytes(), protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ + Expect(p.Unmarshal(b, protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ ErrorCode: qerr.TransportParameterError, ErrorMessage: "remaining length (6) smaller than parameter length (7)", })) }) It("errors if the client sent a stateless_reset_token", func() { - b := &bytes.Buffer{} - quicvarint.Write(b, uint64(statelessResetTokenParameterID)) - quicvarint.Write(b, uint64(quicvarint.Len(16))) - b.Write(make([]byte, 16)) - Expect((&TransportParameters{}).Unmarshal(b.Bytes(), protocol.PerspectiveClient)).To(MatchError(&qerr.TransportError{ + b := quicvarint.Append(nil, uint64(statelessResetTokenParameterID)) + b = quicvarint.Append(b, uint64(quicvarint.Len(16))) + b = append(b, make([]byte, 16)...) + Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveClient)).To(MatchError(&qerr.TransportError{ ErrorCode: qerr.TransportParameterError, ErrorMessage: "client sent a stateless_reset_token", })) }) It("errors if the client sent the original_destination_connection_id", func() { - b := &bytes.Buffer{} - quicvarint.Write(b, uint64(originalDestinationConnectionIDParameterID)) - quicvarint.Write(b, 6) - b.Write([]byte("foobar")) - Expect((&TransportParameters{}).Unmarshal(b.Bytes(), protocol.PerspectiveClient)).To(MatchError(&qerr.TransportError{ + b := quicvarint.Append(nil, uint64(originalDestinationConnectionIDParameterID)) + b = quicvarint.Append(b, 6) + b = append(b, []byte("foobar")...) + Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveClient)).To(MatchError(&qerr.TransportError{ ErrorCode: qerr.TransportParameterError, ErrorMessage: "client sent an original_destination_connection_id", })) @@ -446,12 +433,11 @@ var _ = Describe("Transport Parameters", func() { }) It("errors if the client sent a preferred_address", func() { - b := &bytes.Buffer{} - quicvarint.Write(b, uint64(preferredAddressParameterID)) - quicvarint.Write(b, 6) - b.Write([]byte("foobar")) + b := quicvarint.Append(nil, uint64(preferredAddressParameterID)) + b = quicvarint.Append(b, 6) + b = append(b, []byte("foobar")...) p := &TransportParameters{} - Expect(p.Unmarshal(b.Bytes(), protocol.PerspectiveClient)).To(MatchError(&qerr.TransportError{ + Expect(p.Unmarshal(b, protocol.PerspectiveClient)).To(MatchError(&qerr.TransportError{ ErrorCode: qerr.TransportParameterError, ErrorMessage: "client sent a preferred_address", })) @@ -481,11 +467,10 @@ var _ = Describe("Transport Parameters", func() { 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, // stateless reset token } for i := 1; i < len(raw); i++ { - buf := &bytes.Buffer{} - quicvarint.Write(buf, uint64(preferredAddressParameterID)) - buf.Write(raw[:i]) + b := quicvarint.Append(nil, uint64(preferredAddressParameterID)) + b = append(b, raw[:i]...) p := &TransportParameters{} - Expect(p.Unmarshal(buf.Bytes(), protocol.PerspectiveServer)).ToNot(Succeed()) + Expect(p.Unmarshal(b, protocol.PerspectiveServer)).ToNot(Succeed()) } }) }) @@ -522,10 +507,9 @@ var _ = Describe("Transport Parameters", func() { It("rejects the parameters if the version changed", func() { var p TransportParameters data := p.MarshalForSessionTicket(nil) - b := &bytes.Buffer{} - quicvarint.Write(b, transportParameterMarshalingVersion+1) - b.Write(data[quicvarint.Len(transportParameterMarshalingVersion):]) - Expect(p.UnmarshalFromSessionTicket(bytes.NewReader(b.Bytes()))).To(MatchError(fmt.Sprintf("unknown transport parameter marshaling version: %d", transportParameterMarshalingVersion+1))) + b := quicvarint.Append(nil, transportParameterMarshalingVersion+1) + b = append(b, data[quicvarint.Len(transportParameterMarshalingVersion):]...) + Expect(p.UnmarshalFromSessionTicket(bytes.NewReader(b))).To(MatchError(fmt.Sprintf("unknown transport parameter marshaling version: %d", transportParameterMarshalingVersion+1))) }) Context("rejects the parameters if they changed", func() { diff --git a/internal/wire/wire_suite_test.go b/internal/wire/wire_suite_test.go index d3a4cdca..d68c6ee7 100644 --- a/internal/wire/wire_suite_test.go +++ b/internal/wire/wire_suite_test.go @@ -1,7 +1,6 @@ package wire import ( - "bytes" "encoding/binary" "testing" @@ -18,9 +17,7 @@ func TestWire(t *testing.T) { } func encodeVarInt(i uint64) []byte { - b := &bytes.Buffer{} - quicvarint.Write(b, i) - return b.Bytes() + return quicvarint.Append(nil, i) } func appendVersion(data []byte, v protocol.VersionNumber) []byte { diff --git a/quicvarint/io_test.go b/quicvarint/io_test.go index 561e5af1..8205b1ca 100644 --- a/quicvarint/io_test.go +++ b/quicvarint/io_test.go @@ -80,10 +80,7 @@ var _ = Describe("Varint I/O", func() { }) It("correctly handles io.EOF", func() { - buf := &bytes.Buffer{} - Write(buf, 1337) - - r := NewReader(&eofReader{Data: buf.Bytes()}) + r := NewReader(&eofReader{Data: Append(nil, 1337)}) n, err := Read(r) Expect(err).ToNot(HaveOccurred()) Expect(n).To(BeEquivalentTo(1337)) diff --git a/quicvarint/varint.go b/quicvarint/varint.go index ea1a9107..cbebfe61 100644 --- a/quicvarint/varint.go +++ b/quicvarint/varint.go @@ -71,6 +71,7 @@ func Read(r io.ByteReader) (uint64, error) { } // Write writes i in the QUIC varint format to w. +// Deprecated: use Append instead. func Write(w Writer, i uint64) { if i <= maxVarInt1 { w.WriteByte(uint8(i)) @@ -88,6 +89,7 @@ func Write(w Writer, i uint64) { } } +// Append appends i in the QUIC varint format. func Append(b []byte, i uint64) []byte { if i <= maxVarInt1 { return append(b, uint8(i)) diff --git a/quicvarint/varint_test.go b/quicvarint/varint_test.go index 155cf283..2519d26a 100644 --- a/quicvarint/varint_test.go +++ b/quicvarint/varint_test.go @@ -2,7 +2,6 @@ package quicvarint import ( "bytes" - "math/rand" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -64,79 +63,59 @@ var _ = Describe("Varint encoding / decoding", func() { Context("encoding", func() { Context("with minimal length", func() { It("writes a 1 byte number", func() { - b := &bytes.Buffer{} - Write(b, 37) - Expect(b.Bytes()).To(Equal([]byte{0x25})) + Expect(Append(nil, 37)).To(Equal([]byte{0x25})) }) It("writes the maximum 1 byte number in 1 byte", func() { - b := &bytes.Buffer{} - Write(b, maxVarInt1) - Expect(b.Bytes()).To(Equal([]byte{0b00111111})) + Expect(Append(nil, maxVarInt1)).To(Equal([]byte{0b00111111})) }) It("writes the minimum 2 byte number in 2 bytes", func() { - b := &bytes.Buffer{} - Write(b, maxVarInt1+1) - Expect(b.Bytes()).To(Equal([]byte{0x40, maxVarInt1 + 1})) + Expect(Append(nil, maxVarInt1+1)).To(Equal([]byte{0x40, maxVarInt1 + 1})) }) It("writes a 2 byte number", func() { - b := &bytes.Buffer{} - Write(b, 15293) - Expect(b.Bytes()).To(Equal([]byte{0b01000000 ^ 0x3b, 0xbd})) + Expect(Append(nil, 15293)).To(Equal([]byte{0b01000000 ^ 0x3b, 0xbd})) }) It("writes the maximum 2 byte number in 2 bytes", func() { - b := &bytes.Buffer{} - Write(b, maxVarInt2) - Expect(b.Bytes()).To(Equal([]byte{0b01111111, 0xff})) + Expect(Append(nil, maxVarInt2)).To(Equal([]byte{0b01111111, 0xff})) }) It("writes the minimum 4 byte number in 4 bytes", func() { - b := &bytes.Buffer{} - Write(b, maxVarInt2+1) - Expect(b.Len()).To(Equal(4)) - num, err := Read(b) + b := Append(nil, maxVarInt2+1) + Expect(b).To(HaveLen(4)) + num, err := Read(bytes.NewReader(b)) Expect(err).ToNot(HaveOccurred()) Expect(num).To(Equal(uint64(maxVarInt2 + 1))) }) It("writes a 4 byte number", func() { - b := &bytes.Buffer{} - Write(b, 494878333) - Expect(b.Bytes()).To(Equal([]byte{0b10000000 ^ 0x1d, 0x7f, 0x3e, 0x7d})) + Expect(Append(nil, 494878333)).To(Equal([]byte{0b10000000 ^ 0x1d, 0x7f, 0x3e, 0x7d})) }) It("writes the maximum 4 byte number in 4 bytes", func() { - b := &bytes.Buffer{} - Write(b, maxVarInt4) - Expect(b.Bytes()).To(Equal([]byte{0b10111111, 0xff, 0xff, 0xff})) + Expect(Append(nil, maxVarInt4)).To(Equal([]byte{0b10111111, 0xff, 0xff, 0xff})) }) It("writes the minimum 8 byte number in 8 bytes", func() { - b := &bytes.Buffer{} - Write(b, maxVarInt4+1) - Expect(b.Len()).To(Equal(8)) - num, err := Read(b) + b := Append(nil, maxVarInt4+1) + Expect(b).To(HaveLen(8)) + num, err := Read(bytes.NewReader(b)) Expect(err).ToNot(HaveOccurred()) Expect(num).To(Equal(uint64(maxVarInt4 + 1))) }) It("writes an 8 byte number", func() { - b := &bytes.Buffer{} - Write(b, 151288809941952652) - Expect(b.Bytes()).To(Equal([]byte{0xc2, 0x19, 0x7c, 0x5e, 0xff, 0x14, 0xe8, 0x8c})) + Expect(Append(nil, 151288809941952652)).To(Equal([]byte{0xc2, 0x19, 0x7c, 0x5e, 0xff, 0x14, 0xe8, 0x8c})) }) It("writes the maximum 8 byte number in 8 bytes", func() { - b := &bytes.Buffer{} - Write(b, maxVarInt8) - Expect(b.Bytes()).To(Equal([]byte{0xff /* 11111111 */, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff})) + Expect(Append(nil, maxVarInt8)).To(Equal([]byte{0xff /* 11111111 */, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff})) }) It("panics when given a too large number (> 62 bit)", func() { - Expect(func() { Write(&bytes.Buffer{}, maxVarInt8+1) }).Should(Panic()) + Expect(func() { Append(nil, maxVarInt8+1) }).Should(Panic()) }) }) @@ -185,34 +164,6 @@ var _ = Describe("Varint encoding / decoding", func() { Expect(Read(bytes.NewReader(b))).To(BeEquivalentTo(494878333)) }) }) - - Context("appending", func() { - It("panics when given a too large number (> 62 bit)", func() { - Expect(func() { Append(nil, maxVarInt8+1) }).Should(Panic()) - }) - - It("appends", func() { - for i := 0; i < 10000; i++ { - var limit int64 - switch rand.Int() % 4 { - case 0: - limit = maxVarInt1 - case 1: - limit = maxVarInt2 - case 2: - limit = maxVarInt4 - case 3: - limit = maxVarInt8 - } - - n := uint64(rand.Int63n(limit)) - b := Append(nil, n) - buf := &bytes.Buffer{} - Write(buf, n) - Expect(b).To(Equal(buf.Bytes())) - } - }) - }) }) Context("determining the length needed for encoding", func() {