github.com/apernet/quic-go@v0.43.1-0.20240515053213-5e9e635fd9f0/internal/wire/datagram_frame_test.go (about)

     1  package wire
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  
     7  	"github.com/apernet/quic-go/internal/protocol"
     8  	"github.com/apernet/quic-go/quicvarint"
     9  
    10  	. "github.com/onsi/ginkgo/v2"
    11  	. "github.com/onsi/gomega"
    12  )
    13  
    14  var _ = Describe("STREAM frame", func() {
    15  	Context("when parsing", func() {
    16  		It("parses a frame containing a length", func() {
    17  			data := encodeVarInt(0x6) // length
    18  			data = append(data, []byte("foobar")...)
    19  			r := bytes.NewReader(data)
    20  			frame, err := parseDatagramFrame(r, 0x30^0x1, protocol.Version1)
    21  			Expect(err).ToNot(HaveOccurred())
    22  			Expect(frame.Data).To(Equal([]byte("foobar")))
    23  			Expect(frame.DataLenPresent).To(BeTrue())
    24  			Expect(r.Len()).To(BeZero())
    25  		})
    26  
    27  		It("parses a frame without length", func() {
    28  			data := []byte("Lorem ipsum dolor sit amet")
    29  			r := bytes.NewReader(data)
    30  			frame, err := parseDatagramFrame(r, 0x30, protocol.Version1)
    31  			Expect(err).ToNot(HaveOccurred())
    32  			Expect(frame.Data).To(Equal([]byte("Lorem ipsum dolor sit amet")))
    33  			Expect(frame.DataLenPresent).To(BeFalse())
    34  			Expect(r.Len()).To(BeZero())
    35  		})
    36  
    37  		It("errors when the length is longer than the rest of the frame", func() {
    38  			data := encodeVarInt(0x6) // length
    39  			data = append(data, []byte("fooba")...)
    40  			r := bytes.NewReader(data)
    41  			_, err := parseDatagramFrame(r, 0x30^0x1, protocol.Version1)
    42  			Expect(err).To(MatchError(io.EOF))
    43  		})
    44  
    45  		It("errors on EOFs", func() {
    46  			const typ = 0x30 ^ 0x1
    47  			data := encodeVarInt(6) // length
    48  			data = append(data, []byte("foobar")...)
    49  			_, err := parseDatagramFrame(bytes.NewReader(data), typ, protocol.Version1)
    50  			Expect(err).NotTo(HaveOccurred())
    51  			for i := range data {
    52  				_, err = parseDatagramFrame(bytes.NewReader(data[0:i]), typ, protocol.Version1)
    53  				Expect(err).To(MatchError(io.EOF))
    54  			}
    55  		})
    56  	})
    57  
    58  	Context("when writing", func() {
    59  		It("writes a frame with length", func() {
    60  			f := &DatagramFrame{
    61  				DataLenPresent: true,
    62  				Data:           []byte("foobar"),
    63  			}
    64  			b, err := f.Append(nil, protocol.Version1)
    65  			Expect(err).ToNot(HaveOccurred())
    66  			expected := []byte{0x30 ^ 0x1}
    67  			expected = append(expected, encodeVarInt(0x6)...)
    68  			expected = append(expected, []byte("foobar")...)
    69  			Expect(b).To(Equal(expected))
    70  		})
    71  
    72  		It("writes a frame without length", func() {
    73  			f := &DatagramFrame{Data: []byte("Lorem ipsum")}
    74  			b, err := f.Append(nil, protocol.Version1)
    75  			Expect(err).ToNot(HaveOccurred())
    76  			expected := []byte{0x30}
    77  			expected = append(expected, []byte("Lorem ipsum")...)
    78  			Expect(b).To(Equal(expected))
    79  		})
    80  	})
    81  
    82  	Context("length", func() {
    83  		It("has the right length for a frame with length", func() {
    84  			f := &DatagramFrame{
    85  				DataLenPresent: true,
    86  				Data:           []byte("foobar"),
    87  			}
    88  			Expect(f.Length(protocol.Version1)).To(BeEquivalentTo(1 + quicvarint.Len(6) + 6))
    89  		})
    90  
    91  		It("has the right length for a frame without length", func() {
    92  			f := &DatagramFrame{Data: []byte("foobar")}
    93  			Expect(f.Length(protocol.Version1)).To(Equal(protocol.ByteCount(1 + 6)))
    94  		})
    95  	})
    96  
    97  	Context("max data length", func() {
    98  		const maxSize = 3000
    99  
   100  		It("returns a data length such that the resulting frame has the right size, if data length is not present", func() {
   101  			data := make([]byte, maxSize)
   102  			f := &DatagramFrame{}
   103  			b := &bytes.Buffer{}
   104  			for i := 1; i < 3000; i++ {
   105  				b.Reset()
   106  				f.Data = nil
   107  				maxDataLen := f.MaxDataLen(protocol.ByteCount(i), protocol.Version1)
   108  				if maxDataLen == 0 { // 0 means that no valid STREAM frame can be written
   109  					// check that writing a minimal size STREAM frame (i.e. with 1 byte data) is actually larger than the desired size
   110  					f.Data = []byte{0}
   111  					b, err := f.Append(nil, protocol.Version1)
   112  					Expect(err).ToNot(HaveOccurred())
   113  					Expect(len(b)).To(BeNumerically(">", i))
   114  					continue
   115  				}
   116  				f.Data = data[:int(maxDataLen)]
   117  				b, err := f.Append(nil, protocol.Version1)
   118  				Expect(err).ToNot(HaveOccurred())
   119  				Expect(b).To(HaveLen(i))
   120  			}
   121  		})
   122  
   123  		It("always returns a data length such that the resulting frame has the right size, if data length is present", func() {
   124  			data := make([]byte, maxSize)
   125  			f := &DatagramFrame{DataLenPresent: true}
   126  			var frameOneByteTooSmallCounter int
   127  			for i := 1; i < 3000; i++ {
   128  				f.Data = nil
   129  				maxDataLen := f.MaxDataLen(protocol.ByteCount(i), protocol.Version1)
   130  				if maxDataLen == 0 { // 0 means that no valid STREAM frame can be written
   131  					// check that writing a minimal size STREAM frame (i.e. with 1 byte data) is actually larger than the desired size
   132  					f.Data = []byte{0}
   133  					b, err := f.Append(nil, protocol.Version1)
   134  					Expect(err).ToNot(HaveOccurred())
   135  					Expect(len(b)).To(BeNumerically(">", i))
   136  					continue
   137  				}
   138  				f.Data = data[:int(maxDataLen)]
   139  				b, err := f.Append(nil, protocol.Version1)
   140  				Expect(err).ToNot(HaveOccurred())
   141  				// There's *one* pathological case, where a data length of x can be encoded into 1 byte
   142  				// but a data lengths of x+1 needs 2 bytes
   143  				// In that case, it's impossible to create a STREAM frame of the desired size
   144  				if len(b) == i-1 {
   145  					frameOneByteTooSmallCounter++
   146  					continue
   147  				}
   148  				Expect(b).To(HaveLen(i))
   149  			}
   150  			Expect(frameOneByteTooSmallCounter).To(Equal(1))
   151  		})
   152  	})
   153  })