github.com/tumi8/quic-go@v0.37.4-tum/http3/frames_test.go (about)

     1  package http3
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"io"
     8  
     9  	"github.com/tumi8/quic-go/quicvarint"
    10  
    11  	. "github.com/onsi/ginkgo/v2"
    12  	. "github.com/onsi/gomega"
    13  )
    14  
    15  type errReader struct{ err error }
    16  
    17  func (e errReader) Read([]byte) (int, error) { return 0, e.err }
    18  
    19  var _ = Describe("Frames", func() {
    20  	It("skips unknown frames", func() {
    21  		b := quicvarint.Append(nil, 0xdeadbeef) // type byte
    22  		b = quicvarint.Append(b, 0x42)
    23  		b = append(b, make([]byte, 0x42)...)
    24  		b = (&dataFrame{Length: 0x1234}).Append(b)
    25  		r := bytes.NewReader(b)
    26  		frame, err := parseNextFrame(r, nil)
    27  		Expect(err).ToNot(HaveOccurred())
    28  		Expect(frame).To(BeAssignableToTypeOf(&dataFrame{}))
    29  		Expect(frame.(*dataFrame).Length).To(Equal(uint64(0x1234)))
    30  	})
    31  
    32  	Context("DATA frames", func() {
    33  		It("parses", func() {
    34  			data := quicvarint.Append(nil, 0) // type byte
    35  			data = quicvarint.Append(data, 0x1337)
    36  			frame, err := parseNextFrame(bytes.NewReader(data), nil)
    37  			Expect(err).ToNot(HaveOccurred())
    38  			Expect(frame).To(BeAssignableToTypeOf(&dataFrame{}))
    39  			Expect(frame.(*dataFrame).Length).To(Equal(uint64(0x1337)))
    40  		})
    41  
    42  		It("writes", func() {
    43  			b := (&dataFrame{Length: 0xdeadbeef}).Append(nil)
    44  			frame, err := parseNextFrame(bytes.NewReader(b), nil)
    45  			Expect(err).ToNot(HaveOccurred())
    46  			Expect(err).ToNot(HaveOccurred())
    47  			Expect(frame).To(BeAssignableToTypeOf(&dataFrame{}))
    48  			Expect(frame.(*dataFrame).Length).To(Equal(uint64(0xdeadbeef)))
    49  		})
    50  	})
    51  
    52  	Context("HEADERS frames", func() {
    53  		It("parses", func() {
    54  			data := quicvarint.Append(nil, 1) // type byte
    55  			data = quicvarint.Append(data, 0x1337)
    56  			frame, err := parseNextFrame(bytes.NewReader(data), nil)
    57  			Expect(err).ToNot(HaveOccurred())
    58  			Expect(frame).To(BeAssignableToTypeOf(&headersFrame{}))
    59  			Expect(frame.(*headersFrame).Length).To(Equal(uint64(0x1337)))
    60  		})
    61  
    62  		It("writes", func() {
    63  			b := (&headersFrame{Length: 0xdeadbeef}).Append(nil)
    64  			frame, err := parseNextFrame(bytes.NewReader(b), nil)
    65  			Expect(err).ToNot(HaveOccurred())
    66  			Expect(err).ToNot(HaveOccurred())
    67  			Expect(frame).To(BeAssignableToTypeOf(&headersFrame{}))
    68  			Expect(frame.(*headersFrame).Length).To(Equal(uint64(0xdeadbeef)))
    69  		})
    70  	})
    71  
    72  	Context("SETTINGS frames", func() {
    73  		It("parses", func() {
    74  			settings := quicvarint.Append(nil, 13)
    75  			settings = quicvarint.Append(settings, 37)
    76  			settings = quicvarint.Append(settings, 0xdead)
    77  			settings = quicvarint.Append(settings, 0xbeef)
    78  			data := quicvarint.Append(nil, 4) // type byte
    79  			data = quicvarint.Append(data, uint64(len(settings)))
    80  			data = append(data, settings...)
    81  			frame, err := parseNextFrame(bytes.NewReader(data), nil)
    82  			Expect(err).ToNot(HaveOccurred())
    83  			Expect(frame).To(BeAssignableToTypeOf(&settingsFrame{}))
    84  			sf := frame.(*settingsFrame)
    85  			Expect(sf.Other).To(HaveKeyWithValue(uint64(13), uint64(37)))
    86  			Expect(sf.Other).To(HaveKeyWithValue(uint64(0xdead), uint64(0xbeef)))
    87  		})
    88  
    89  		It("rejects duplicate settings", func() {
    90  			settings := quicvarint.Append(nil, 13)
    91  			settings = quicvarint.Append(settings, 37)
    92  			settings = quicvarint.Append(settings, 13)
    93  			settings = quicvarint.Append(settings, 38)
    94  			data := quicvarint.Append(nil, 4) // type byte
    95  			data = quicvarint.Append(data, uint64(len(settings)))
    96  			data = append(data, settings...)
    97  			_, err := parseNextFrame(bytes.NewReader(data), nil)
    98  			Expect(err).To(MatchError("duplicate setting: 13"))
    99  		})
   100  
   101  		It("writes", func() {
   102  			sf := &settingsFrame{Other: map[uint64]uint64{
   103  				1:  2,
   104  				99: 999,
   105  				13: 37,
   106  			}}
   107  			frame, err := parseNextFrame(bytes.NewReader(sf.Append(nil)), nil)
   108  			Expect(err).ToNot(HaveOccurred())
   109  			Expect(frame).To(Equal(sf))
   110  		})
   111  
   112  		It("errors on EOF", func() {
   113  			sf := &settingsFrame{Other: map[uint64]uint64{
   114  				13:         37,
   115  				0xdeadbeef: 0xdecafbad,
   116  			}}
   117  			data := sf.Append(nil)
   118  
   119  			_, err := parseNextFrame(bytes.NewReader(data), nil)
   120  			Expect(err).ToNot(HaveOccurred())
   121  
   122  			for i := range data {
   123  				b := make([]byte, i)
   124  				copy(b, data[:i])
   125  				_, err := parseNextFrame(bytes.NewReader(b), nil)
   126  				Expect(err).To(MatchError(io.EOF))
   127  			}
   128  		})
   129  
   130  		Context("H3_DATAGRAM", func() {
   131  			It("reads the H3_DATAGRAM value", func() {
   132  				settings := quicvarint.Append(nil, settingDatagram)
   133  				settings = quicvarint.Append(settings, 1)
   134  				data := quicvarint.Append(nil, 4) // type byte
   135  				data = quicvarint.Append(data, uint64(len(settings)))
   136  				data = append(data, settings...)
   137  				f, err := parseNextFrame(bytes.NewReader(data), nil)
   138  				Expect(err).ToNot(HaveOccurred())
   139  				Expect(f).To(BeAssignableToTypeOf(&settingsFrame{}))
   140  				sf := f.(*settingsFrame)
   141  				Expect(sf.Datagram).To(BeTrue())
   142  			})
   143  
   144  			It("rejects duplicate H3_DATAGRAM entries", func() {
   145  				settings := quicvarint.Append(nil, settingDatagram)
   146  				settings = quicvarint.Append(settings, 1)
   147  				settings = quicvarint.Append(settings, settingDatagram)
   148  				settings = quicvarint.Append(settings, 1)
   149  				data := quicvarint.Append(nil, 4) // type byte
   150  				data = quicvarint.Append(data, uint64(len(settings)))
   151  				data = append(data, settings...)
   152  				_, err := parseNextFrame(bytes.NewReader(data), nil)
   153  				Expect(err).To(MatchError(fmt.Sprintf("duplicate setting: %d", settingDatagram)))
   154  			})
   155  
   156  			It("rejects invalid values for the H3_DATAGRAM entry", func() {
   157  				settings := quicvarint.Append(nil, settingDatagram)
   158  				settings = quicvarint.Append(settings, 1337)
   159  				data := quicvarint.Append(nil, 4) // type byte
   160  				data = quicvarint.Append(data, uint64(len(settings)))
   161  				data = append(data, settings...)
   162  				_, err := parseNextFrame(bytes.NewReader(data), nil)
   163  				Expect(err).To(MatchError("invalid value for H3_DATAGRAM: 1337"))
   164  			})
   165  
   166  			It("writes the H3_DATAGRAM setting", func() {
   167  				sf := &settingsFrame{Datagram: true}
   168  				frame, err := parseNextFrame(bytes.NewReader(sf.Append(nil)), nil)
   169  				Expect(err).ToNot(HaveOccurred())
   170  				Expect(frame).To(Equal(sf))
   171  			})
   172  		})
   173  	})
   174  
   175  	Context("hijacking", func() {
   176  		It("reads a frame without hijacking the stream", func() {
   177  			buf := bytes.NewBuffer(quicvarint.Append(nil, 1337))
   178  			customFrameContents := []byte("foobar")
   179  			buf.Write(customFrameContents)
   180  
   181  			var called bool
   182  			_, err := parseNextFrame(buf, func(ft FrameType, e error) (hijacked bool, err error) {
   183  				Expect(e).ToNot(HaveOccurred())
   184  				Expect(ft).To(BeEquivalentTo(1337))
   185  				called = true
   186  				b := make([]byte, 3)
   187  				_, err = io.ReadFull(buf, b)
   188  				Expect(err).ToNot(HaveOccurred())
   189  				Expect(string(b)).To(Equal("foo"))
   190  				return true, nil
   191  			})
   192  			Expect(err).To(MatchError(errHijacked))
   193  			Expect(called).To(BeTrue())
   194  		})
   195  
   196  		It("passes on errors that occur when reading the frame type", func() {
   197  			testErr := errors.New("test error")
   198  			var called bool
   199  			_, err := parseNextFrame(errReader{err: testErr}, func(ft FrameType, e error) (hijacked bool, err error) {
   200  				Expect(e).To(MatchError(testErr))
   201  				Expect(ft).To(BeZero())
   202  				called = true
   203  				return true, nil
   204  			})
   205  			Expect(err).To(MatchError(errHijacked))
   206  			Expect(called).To(BeTrue())
   207  		})
   208  
   209  		It("reads a frame without hijacking the stream", func() {
   210  			b := quicvarint.Append(nil, 1337)
   211  			customFrameContents := []byte("custom frame")
   212  			b = quicvarint.Append(b, uint64(len(customFrameContents)))
   213  			b = append(b, customFrameContents...)
   214  			b = (&dataFrame{Length: 6}).Append(b)
   215  			b = append(b, []byte("foobar")...)
   216  
   217  			var called bool
   218  			frame, err := parseNextFrame(bytes.NewReader(b), func(ft FrameType, e error) (hijacked bool, err error) {
   219  				Expect(e).ToNot(HaveOccurred())
   220  				Expect(ft).To(BeEquivalentTo(1337))
   221  				called = true
   222  				return false, nil
   223  			})
   224  			Expect(err).ToNot(HaveOccurred())
   225  			Expect(frame).To(Equal(&dataFrame{Length: 6}))
   226  			Expect(called).To(BeTrue())
   227  		})
   228  	})
   229  })