github.com/tumi8/quic-go@v0.37.4-tum/noninternal/wire/frame_parser_test.go (about)

     1  package wire
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/tumi8/quic-go/noninternal/protocol"
     7  	"github.com/tumi8/quic-go/noninternal/qerr"
     8  	. "github.com/onsi/ginkgo/v2"
     9  	. "github.com/onsi/gomega"
    10  )
    11  
    12  var _ = Describe("Frame parsing", func() {
    13  	var parser FrameParser
    14  
    15  	BeforeEach(func() {
    16  		parser = NewFrameParser(true)
    17  	})
    18  
    19  	It("returns nil if there's nothing more to read", func() {
    20  		l, f, err := parser.ParseNext(nil, protocol.Encryption1RTT, protocol.Version1)
    21  		Expect(err).ToNot(HaveOccurred())
    22  		Expect(l).To(BeZero())
    23  		Expect(f).To(BeNil())
    24  	})
    25  
    26  	It("skips PADDING frames", func() {
    27  		b := []byte{0, 0} // 2 PADDING frames
    28  		b, err := (&PingFrame{}).Append(b, protocol.Version1)
    29  		Expect(err).ToNot(HaveOccurred())
    30  		l, f, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
    31  		Expect(err).ToNot(HaveOccurred())
    32  		Expect(f).To(Equal(&PingFrame{}))
    33  		Expect(l).To(Equal(2 + 1))
    34  	})
    35  
    36  	It("handles PADDING at the end", func() {
    37  		l, f, err := parser.ParseNext([]byte{0, 0, 0}, protocol.Encryption1RTT, protocol.Version1)
    38  		Expect(err).ToNot(HaveOccurred())
    39  		Expect(f).To(BeNil())
    40  		Expect(l).To(Equal(3))
    41  	})
    42  
    43  	It("parses a single frame", func() {
    44  		var b []byte
    45  		for i := 0; i < 10; i++ {
    46  			var err error
    47  			b, err = (&PingFrame{}).Append(b, protocol.Version1)
    48  			Expect(err).ToNot(HaveOccurred())
    49  		}
    50  		l, f, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
    51  		Expect(err).ToNot(HaveOccurred())
    52  		Expect(f).To(BeAssignableToTypeOf(&PingFrame{}))
    53  		Expect(l).To(Equal(1))
    54  	})
    55  
    56  	It("unpacks ACK frames", func() {
    57  		f := &AckFrame{AckRanges: []AckRange{{Smallest: 1, Largest: 0x13}}}
    58  		b, err := f.Append(nil, protocol.Version1)
    59  		Expect(err).ToNot(HaveOccurred())
    60  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
    61  		Expect(err).ToNot(HaveOccurred())
    62  		Expect(frame).ToNot(BeNil())
    63  		Expect(frame).To(BeAssignableToTypeOf(f))
    64  		Expect(frame.(*AckFrame).LargestAcked()).To(Equal(protocol.PacketNumber(0x13)))
    65  		Expect(l).To(Equal(len(b)))
    66  	})
    67  
    68  	It("uses the custom ack delay exponent for 1RTT packets", func() {
    69  		parser.SetAckDelayExponent(protocol.AckDelayExponent + 2)
    70  		f := &AckFrame{
    71  			AckRanges: []AckRange{{Smallest: 1, Largest: 1}},
    72  			DelayTime: time.Second,
    73  		}
    74  		b, err := f.Append(nil, protocol.Version1)
    75  		Expect(err).ToNot(HaveOccurred())
    76  		_, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
    77  		Expect(err).ToNot(HaveOccurred())
    78  		// The ACK frame is always written using the protocol.AckDelayExponent.
    79  		// That's why we expect a different value when parsing.
    80  		Expect(frame.(*AckFrame).DelayTime).To(Equal(4 * time.Second))
    81  	})
    82  
    83  	It("uses the default ack delay exponent for non-1RTT packets", func() {
    84  		parser.SetAckDelayExponent(protocol.AckDelayExponent + 2)
    85  		f := &AckFrame{
    86  			AckRanges: []AckRange{{Smallest: 1, Largest: 1}},
    87  			DelayTime: time.Second,
    88  		}
    89  		b, err := f.Append(nil, protocol.Version1)
    90  		Expect(err).ToNot(HaveOccurred())
    91  		_, frame, err := parser.ParseNext(b, protocol.EncryptionHandshake, protocol.Version1)
    92  		Expect(err).ToNot(HaveOccurred())
    93  		Expect(frame.(*AckFrame).DelayTime).To(Equal(time.Second))
    94  	})
    95  
    96  	It("unpacks RESET_STREAM frames", func() {
    97  		f := &ResetStreamFrame{
    98  			StreamID:  0xdeadbeef,
    99  			FinalSize: 0xdecafbad1234,
   100  			ErrorCode: 0x1337,
   101  		}
   102  		b, err := f.Append(nil, protocol.Version1)
   103  		Expect(err).ToNot(HaveOccurred())
   104  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   105  		Expect(err).ToNot(HaveOccurred())
   106  		Expect(frame).To(Equal(f))
   107  		Expect(l).To(Equal(len(b)))
   108  	})
   109  
   110  	It("unpacks STOP_SENDING frames", func() {
   111  		f := &StopSendingFrame{StreamID: 0x42}
   112  		b, err := f.Append(nil, protocol.Version1)
   113  		Expect(err).ToNot(HaveOccurred())
   114  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   115  		Expect(err).ToNot(HaveOccurred())
   116  		Expect(frame).To(Equal(f))
   117  		Expect(l).To(Equal(len(b)))
   118  	})
   119  
   120  	It("unpacks CRYPTO frames", func() {
   121  		f := &CryptoFrame{
   122  			Offset: 0x1337,
   123  			Data:   []byte("lorem ipsum"),
   124  		}
   125  		b, err := f.Append(nil, protocol.Version1)
   126  		Expect(err).ToNot(HaveOccurred())
   127  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   128  		Expect(err).ToNot(HaveOccurred())
   129  		Expect(frame).ToNot(BeNil())
   130  		Expect(frame).To(Equal(f))
   131  		Expect(l).To(Equal(len(b)))
   132  	})
   133  
   134  	It("unpacks NEW_TOKEN frames", func() {
   135  		f := &NewTokenFrame{Token: []byte("foobar")}
   136  		b, err := f.Append(nil, protocol.Version1)
   137  		Expect(err).ToNot(HaveOccurred())
   138  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   139  		Expect(err).ToNot(HaveOccurred())
   140  		Expect(frame).ToNot(BeNil())
   141  		Expect(frame).To(Equal(f))
   142  		Expect(l).To(Equal(len(b)))
   143  	})
   144  
   145  	It("unpacks STREAM frames", func() {
   146  		f := &StreamFrame{
   147  			StreamID: 0x42,
   148  			Offset:   0x1337,
   149  			Fin:      true,
   150  			Data:     []byte("foobar"),
   151  		}
   152  		b, err := f.Append(nil, protocol.Version1)
   153  		Expect(err).ToNot(HaveOccurred())
   154  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   155  		Expect(err).ToNot(HaveOccurred())
   156  		Expect(frame).ToNot(BeNil())
   157  		Expect(frame).To(Equal(f))
   158  		Expect(l).To(Equal(len(b)))
   159  	})
   160  
   161  	It("unpacks MAX_DATA frames", func() {
   162  		f := &MaxDataFrame{
   163  			MaximumData: 0xcafe,
   164  		}
   165  		b, err := f.Append(nil, protocol.Version1)
   166  		Expect(err).ToNot(HaveOccurred())
   167  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   168  		Expect(err).ToNot(HaveOccurred())
   169  		Expect(frame).To(Equal(f))
   170  		Expect(l).To(Equal(len(b)))
   171  	})
   172  
   173  	It("unpacks MAX_STREAM_DATA frames", func() {
   174  		f := &MaxStreamDataFrame{
   175  			StreamID:          0xdeadbeef,
   176  			MaximumStreamData: 0xdecafbad,
   177  		}
   178  		b, err := f.Append(nil, protocol.Version1)
   179  		Expect(err).ToNot(HaveOccurred())
   180  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   181  		Expect(err).ToNot(HaveOccurred())
   182  		Expect(frame).To(Equal(f))
   183  		Expect(l).To(Equal(len(b)))
   184  	})
   185  
   186  	It("unpacks MAX_STREAMS frames", func() {
   187  		f := &MaxStreamsFrame{
   188  			Type:         protocol.StreamTypeBidi,
   189  			MaxStreamNum: 0x1337,
   190  		}
   191  		b, err := f.Append(nil, protocol.Version1)
   192  		Expect(err).ToNot(HaveOccurred())
   193  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   194  		Expect(err).ToNot(HaveOccurred())
   195  		Expect(frame).To(Equal(f))
   196  		Expect(l).To(Equal(len(b)))
   197  	})
   198  
   199  	It("unpacks DATA_BLOCKED frames", func() {
   200  		f := &DataBlockedFrame{MaximumData: 0x1234}
   201  		b, err := f.Append(nil, protocol.Version1)
   202  		Expect(err).ToNot(HaveOccurred())
   203  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   204  		Expect(err).ToNot(HaveOccurred())
   205  		Expect(frame).To(Equal(f))
   206  		Expect(l).To(Equal(len(b)))
   207  	})
   208  
   209  	It("unpacks STREAM_DATA_BLOCKED frames", func() {
   210  		f := &StreamDataBlockedFrame{
   211  			StreamID:          0xdeadbeef,
   212  			MaximumStreamData: 0xdead,
   213  		}
   214  		b, err := f.Append(nil, protocol.Version1)
   215  		Expect(err).ToNot(HaveOccurred())
   216  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   217  		Expect(err).ToNot(HaveOccurred())
   218  		Expect(frame).To(Equal(f))
   219  		Expect(l).To(Equal(len(b)))
   220  	})
   221  
   222  	It("unpacks STREAMS_BLOCKED frames", func() {
   223  		f := &StreamsBlockedFrame{
   224  			Type:        protocol.StreamTypeBidi,
   225  			StreamLimit: 0x1234567,
   226  		}
   227  		b, err := f.Append(nil, protocol.Version1)
   228  		Expect(err).ToNot(HaveOccurred())
   229  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   230  		Expect(err).ToNot(HaveOccurred())
   231  		Expect(frame).To(Equal(f))
   232  		Expect(l).To(Equal(len(b)))
   233  	})
   234  
   235  	It("unpacks NEW_CONNECTION_ID frames", func() {
   236  		f := &NewConnectionIDFrame{
   237  			SequenceNumber:      0x1337,
   238  			ConnectionID:        protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef}),
   239  			StatelessResetToken: protocol.StatelessResetToken{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   240  		}
   241  		b, err := f.Append(nil, protocol.Version1)
   242  		Expect(err).ToNot(HaveOccurred())
   243  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   244  		Expect(err).ToNot(HaveOccurred())
   245  		Expect(frame).To(Equal(f))
   246  		Expect(l).To(Equal(len(b)))
   247  	})
   248  
   249  	It("unpacks RETIRE_CONNECTION_ID frames", func() {
   250  		f := &RetireConnectionIDFrame{SequenceNumber: 0x1337}
   251  		b, err := f.Append(nil, protocol.Version1)
   252  		Expect(err).ToNot(HaveOccurred())
   253  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   254  		Expect(err).ToNot(HaveOccurred())
   255  		Expect(frame).To(Equal(f))
   256  		Expect(l).To(Equal(len(b)))
   257  	})
   258  
   259  	It("unpacks PATH_CHALLENGE frames", func() {
   260  		f := &PathChallengeFrame{Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8}}
   261  		b, err := f.Append(nil, protocol.Version1)
   262  		Expect(err).ToNot(HaveOccurred())
   263  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   264  		Expect(err).ToNot(HaveOccurred())
   265  		Expect(frame).ToNot(BeNil())
   266  		Expect(frame).To(BeAssignableToTypeOf(f))
   267  		Expect(frame.(*PathChallengeFrame).Data).To(Equal([8]byte{1, 2, 3, 4, 5, 6, 7, 8}))
   268  		Expect(l).To(Equal(len(b)))
   269  	})
   270  
   271  	It("unpacks PATH_RESPONSE frames", func() {
   272  		f := &PathResponseFrame{Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8}}
   273  		b, err := f.Append(nil, protocol.Version1)
   274  		Expect(err).ToNot(HaveOccurred())
   275  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   276  		Expect(err).ToNot(HaveOccurred())
   277  		Expect(frame).ToNot(BeNil())
   278  		Expect(frame).To(BeAssignableToTypeOf(f))
   279  		Expect(frame.(*PathResponseFrame).Data).To(Equal([8]byte{1, 2, 3, 4, 5, 6, 7, 8}))
   280  		Expect(l).To(Equal(len(b)))
   281  	})
   282  
   283  	It("unpacks CONNECTION_CLOSE frames", func() {
   284  		f := &ConnectionCloseFrame{
   285  			IsApplicationError: true,
   286  			ReasonPhrase:       "foobar",
   287  		}
   288  		b, err := f.Append(nil, protocol.Version1)
   289  		Expect(err).ToNot(HaveOccurred())
   290  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   291  		Expect(err).ToNot(HaveOccurred())
   292  		Expect(frame).To(Equal(f))
   293  		Expect(l).To(Equal(len(b)))
   294  	})
   295  
   296  	It("unpacks HANDSHAKE_DONE frames", func() {
   297  		f := &HandshakeDoneFrame{}
   298  		b, err := f.Append(nil, protocol.Version1)
   299  		Expect(err).ToNot(HaveOccurred())
   300  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   301  		Expect(err).ToNot(HaveOccurred())
   302  		Expect(frame).To(Equal(f))
   303  		Expect(l).To(Equal(len(b)))
   304  	})
   305  
   306  	It("unpacks DATAGRAM frames", func() {
   307  		f := &DatagramFrame{Data: []byte("foobar")}
   308  		b, err := f.Append(nil, protocol.Version1)
   309  		Expect(err).ToNot(HaveOccurred())
   310  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   311  		Expect(err).ToNot(HaveOccurred())
   312  		Expect(frame).To(Equal(f))
   313  		Expect(l).To(Equal(len(b)))
   314  	})
   315  
   316  	It("errors when DATAGRAM frames are not supported", func() {
   317  		parser = NewFrameParser(false)
   318  		f := &DatagramFrame{Data: []byte("foobar")}
   319  		b, err := f.Append(nil, protocol.Version1)
   320  		Expect(err).ToNot(HaveOccurred())
   321  		_, _, err = parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   322  		Expect(err).To(MatchError(&qerr.TransportError{
   323  			ErrorCode:    qerr.FrameEncodingError,
   324  			FrameType:    0x30,
   325  			ErrorMessage: "unknown frame type",
   326  		}))
   327  	})
   328  
   329  	It("errors on invalid type", func() {
   330  		_, _, err := parser.ParseNext(encodeVarInt(0x42), protocol.Encryption1RTT, protocol.Version1)
   331  		Expect(err).To(MatchError(&qerr.TransportError{
   332  			ErrorCode:    qerr.FrameEncodingError,
   333  			FrameType:    0x42,
   334  			ErrorMessage: "unknown frame type",
   335  		}))
   336  	})
   337  
   338  	It("errors on invalid frames", func() {
   339  		f := &MaxStreamDataFrame{
   340  			StreamID:          0x1337,
   341  			MaximumStreamData: 0xdeadbeef,
   342  		}
   343  		b, err := f.Append(nil, protocol.Version1)
   344  		Expect(err).ToNot(HaveOccurred())
   345  		_, _, err = parser.ParseNext(b[:len(b)-2], protocol.Encryption1RTT, protocol.Version1)
   346  		Expect(err).To(HaveOccurred())
   347  		Expect(err.(*qerr.TransportError).ErrorCode).To(Equal(qerr.FrameEncodingError))
   348  	})
   349  
   350  	Context("encryption level check", func() {
   351  		frames := []Frame{
   352  			&PingFrame{},
   353  			&AckFrame{AckRanges: []AckRange{{Smallest: 1, Largest: 42}}},
   354  			&ResetStreamFrame{},
   355  			&StopSendingFrame{},
   356  			&CryptoFrame{},
   357  			&NewTokenFrame{Token: []byte("lorem ipsum")},
   358  			&StreamFrame{Data: []byte("foobar")},
   359  			&MaxDataFrame{},
   360  			&MaxStreamDataFrame{},
   361  			&MaxStreamsFrame{},
   362  			&DataBlockedFrame{},
   363  			&StreamDataBlockedFrame{},
   364  			&StreamsBlockedFrame{},
   365  			&NewConnectionIDFrame{ConnectionID: protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef})},
   366  			&RetireConnectionIDFrame{},
   367  			&PathChallengeFrame{},
   368  			&PathResponseFrame{},
   369  			&ConnectionCloseFrame{},
   370  			&HandshakeDoneFrame{},
   371  			&DatagramFrame{},
   372  		}
   373  
   374  		var framesSerialized [][]byte
   375  
   376  		BeforeEach(func() {
   377  			framesSerialized = nil
   378  			for _, frame := range frames {
   379  				b, err := frame.Append(nil, protocol.Version1)
   380  				Expect(err).ToNot(HaveOccurred())
   381  				framesSerialized = append(framesSerialized, b)
   382  			}
   383  		})
   384  
   385  		It("rejects all frames but ACK, CRYPTO, PING and CONNECTION_CLOSE in Initial packets", func() {
   386  			for i, b := range framesSerialized {
   387  				_, _, err := parser.ParseNext(b, protocol.EncryptionInitial, protocol.Version1)
   388  				switch frames[i].(type) {
   389  				case *AckFrame, *ConnectionCloseFrame, *CryptoFrame, *PingFrame:
   390  					Expect(err).ToNot(HaveOccurred())
   391  				default:
   392  					Expect(err).To(BeAssignableToTypeOf(&qerr.TransportError{}))
   393  					Expect(err.(*qerr.TransportError).ErrorCode).To(Equal(qerr.FrameEncodingError))
   394  					Expect(err.(*qerr.TransportError).ErrorMessage).To(ContainSubstring("not allowed at encryption level Initial"))
   395  				}
   396  			}
   397  		})
   398  
   399  		It("rejects all frames but ACK, CRYPTO, PING and CONNECTION_CLOSE in Handshake packets", func() {
   400  			for i, b := range framesSerialized {
   401  				_, _, err := parser.ParseNext(b, protocol.EncryptionHandshake, protocol.Version1)
   402  				switch frames[i].(type) {
   403  				case *AckFrame, *ConnectionCloseFrame, *CryptoFrame, *PingFrame:
   404  					Expect(err).ToNot(HaveOccurred())
   405  				default:
   406  					Expect(err).To(BeAssignableToTypeOf(&qerr.TransportError{}))
   407  					Expect(err.(*qerr.TransportError).ErrorCode).To(Equal(qerr.FrameEncodingError))
   408  					Expect(err.(*qerr.TransportError).ErrorMessage).To(ContainSubstring("not allowed at encryption level Handshake"))
   409  				}
   410  			}
   411  		})
   412  
   413  		It("rejects all frames but ACK, CRYPTO, CONNECTION_CLOSE, NEW_TOKEN, PATH_RESPONSE and RETIRE_CONNECTION_ID in 0-RTT packets", func() {
   414  			for i, b := range framesSerialized {
   415  				_, _, err := parser.ParseNext(b, protocol.Encryption0RTT, protocol.Version1)
   416  				switch frames[i].(type) {
   417  				case *AckFrame, *ConnectionCloseFrame, *CryptoFrame, *NewTokenFrame, *PathResponseFrame, *RetireConnectionIDFrame:
   418  					Expect(err).To(BeAssignableToTypeOf(&qerr.TransportError{}))
   419  					Expect(err.(*qerr.TransportError).ErrorCode).To(Equal(qerr.FrameEncodingError))
   420  					Expect(err.(*qerr.TransportError).ErrorMessage).To(ContainSubstring("not allowed at encryption level 0-RTT"))
   421  				default:
   422  					Expect(err).ToNot(HaveOccurred())
   423  				}
   424  			}
   425  		})
   426  
   427  		It("accepts all frame types in 1-RTT packets", func() {
   428  			for _, b := range framesSerialized {
   429  				_, _, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   430  				Expect(err).ToNot(HaveOccurred())
   431  			}
   432  		})
   433  	})
   434  })