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

     1  package wire
     2  
     3  import (
     4  	"bytes"
     5  	"log"
     6  	"os"
     7  
     8  	"github.com/apernet/quic-go/internal/protocol"
     9  	"github.com/apernet/quic-go/internal/utils"
    10  	"github.com/apernet/quic-go/quicvarint"
    11  
    12  	. "github.com/onsi/ginkgo/v2"
    13  	. "github.com/onsi/gomega"
    14  )
    15  
    16  var _ = Describe("Header", func() {
    17  	Context("Writing", func() {
    18  		Context("Long Header, version 1", func() {
    19  			srcConnID := protocol.ParseConnectionID([]byte{1, 2, 3, 4, 5, 6, 7, 8})
    20  
    21  			It("writes", func() {
    22  				b, err := (&ExtendedHeader{
    23  					Header: Header{
    24  						Type:             protocol.PacketTypeHandshake,
    25  						DestConnectionID: protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe}),
    26  						SrcConnectionID:  protocol.ParseConnectionID([]byte{0xde, 0xca, 0xfb, 0xad, 0x0, 0x0, 0x13, 0x37}),
    27  						Version:          0x1020304,
    28  						Length:           protocol.InitialPacketSizeIPv4,
    29  					},
    30  					PacketNumber:    0xdecaf,
    31  					PacketNumberLen: protocol.PacketNumberLen3,
    32  				}).Append(nil, protocol.Version1)
    33  				Expect(err).ToNot(HaveOccurred())
    34  				expected := []byte{
    35  					0xc0 | 0x2<<4 | 0x2,
    36  					0x1, 0x2, 0x3, 0x4, // version number
    37  					0x6,                                // dest connection ID length
    38  					0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, // dest connection ID
    39  					0x8,                                          // src connection ID length
    40  					0xde, 0xca, 0xfb, 0xad, 0x0, 0x0, 0x13, 0x37, // source connection ID
    41  				}
    42  				expected = append(expected, encodeVarInt(protocol.InitialPacketSizeIPv4)...) // length
    43  				expected = append(expected, []byte{0xd, 0xec, 0xaf}...)                      // packet number
    44  				Expect(b).To(Equal(expected))
    45  			})
    46  
    47  			It("writes a header with a 20 byte connection ID", func() {
    48  				b, err := (&ExtendedHeader{
    49  					Header: Header{
    50  						SrcConnectionID:  srcConnID,
    51  						DestConnectionID: protocol.ParseConnectionID([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}), // connection IDs must be at most 20 bytes long
    52  						Version:          0x1020304,
    53  						Type:             0x5,
    54  					},
    55  					PacketNumber:    0xdecafbad,
    56  					PacketNumberLen: protocol.PacketNumberLen4,
    57  				}).Append(nil, protocol.Version1)
    58  				Expect(err).ToNot(HaveOccurred())
    59  				Expect(b).To(ContainSubstring(string([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20})))
    60  			})
    61  
    62  			It("writes an Initial containing a token", func() {
    63  				token := []byte("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
    64  				b, err := (&ExtendedHeader{
    65  					Header: Header{
    66  						Version: 0x1020304,
    67  						Type:    protocol.PacketTypeInitial,
    68  						Token:   token,
    69  					},
    70  					PacketNumber:    0xdecafbad,
    71  					PacketNumberLen: protocol.PacketNumberLen4,
    72  				}).Append(nil, protocol.Version1)
    73  				Expect(err).ToNot(HaveOccurred())
    74  				Expect(b[0]>>4&0b11 == 0)
    75  				expectedSubstring := append(encodeVarInt(uint64(len(token))), token...)
    76  				Expect(b).To(ContainSubstring(string(expectedSubstring)))
    77  			})
    78  
    79  			It("uses a 2-byte encoding for the length on Initial packets", func() {
    80  				b, err := (&ExtendedHeader{
    81  					Header: Header{
    82  						Version: 0x1020304,
    83  						Type:    protocol.PacketTypeInitial,
    84  						Length:  37,
    85  					},
    86  					PacketNumber:    0xdecafbad,
    87  					PacketNumberLen: protocol.PacketNumberLen4,
    88  				}).Append(nil, protocol.Version1)
    89  				Expect(err).ToNot(HaveOccurred())
    90  				lengthEncoded := quicvarint.AppendWithLen(nil, 37, 2)
    91  				Expect(b[len(b)-6 : len(b)-4]).To(Equal(lengthEncoded))
    92  			})
    93  
    94  			It("writes a Retry packet", func() {
    95  				token := []byte("Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.")
    96  				b, err := (&ExtendedHeader{Header: Header{
    97  					Version: protocol.Version1,
    98  					Type:    protocol.PacketTypeRetry,
    99  					Token:   token,
   100  				}}).Append(nil, protocol.Version1)
   101  				Expect(err).ToNot(HaveOccurred())
   102  				expected := []byte{0xc0 | 0b11<<4}
   103  				expected = appendVersion(expected, protocol.Version1)
   104  				expected = append(expected, 0x0) // dest connection ID length
   105  				expected = append(expected, 0x0) // src connection ID length
   106  				expected = append(expected, token...)
   107  				Expect(b).To(Equal(expected))
   108  			})
   109  		})
   110  
   111  		Context("long header, version 2", func() {
   112  			It("writes an Initial", func() {
   113  				b, err := (&ExtendedHeader{
   114  					Header: Header{
   115  						Version: protocol.Version2,
   116  						Type:    protocol.PacketTypeInitial,
   117  					},
   118  					PacketNumber:    0xdecafbad,
   119  					PacketNumberLen: protocol.PacketNumberLen4,
   120  				}).Append(nil, protocol.Version2)
   121  				Expect(err).ToNot(HaveOccurred())
   122  				Expect(b[0]>>4&0b11 == 0b01)
   123  			})
   124  
   125  			It("writes a Retry packet", func() {
   126  				token := []byte("Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.")
   127  				b, err := (&ExtendedHeader{Header: Header{
   128  					Version: protocol.Version2,
   129  					Type:    protocol.PacketTypeRetry,
   130  					Token:   token,
   131  				}}).Append(nil, protocol.Version2)
   132  				Expect(err).ToNot(HaveOccurred())
   133  				expected := []byte{0xc0 | 0b00<<4}
   134  				expected = appendVersion(expected, protocol.Version2)
   135  				expected = append(expected, 0x0) // dest connection ID length
   136  				expected = append(expected, 0x0) // src connection ID length
   137  				expected = append(expected, token...)
   138  				Expect(b).To(Equal(expected))
   139  			})
   140  
   141  			It("writes a Handshake Packet", func() {
   142  				b, err := (&ExtendedHeader{
   143  					Header: Header{
   144  						Version: protocol.Version2,
   145  						Type:    protocol.PacketTypeHandshake,
   146  					},
   147  					PacketNumber:    0xdecafbad,
   148  					PacketNumberLen: protocol.PacketNumberLen4,
   149  				}).Append(nil, protocol.Version2)
   150  				Expect(err).ToNot(HaveOccurred())
   151  				Expect(b[0]>>4&0b11 == 0b11)
   152  			})
   153  
   154  			It("writes a 0-RTT Packet", func() {
   155  				b, err := (&ExtendedHeader{
   156  					Header: Header{
   157  						Version: protocol.Version2,
   158  						Type:    protocol.PacketType0RTT,
   159  					},
   160  					PacketNumber:    0xdecafbad,
   161  					PacketNumberLen: protocol.PacketNumberLen4,
   162  				}).Append(nil, protocol.Version2)
   163  				Expect(err).ToNot(HaveOccurred())
   164  				Expect(b[0]>>4&0b11 == 0b10)
   165  			})
   166  		})
   167  	})
   168  
   169  	Context("getting the length", func() {
   170  		It("has the right length for the Long Header, for a short length", func() {
   171  			h := &ExtendedHeader{
   172  				Header: Header{
   173  					Type:             protocol.PacketTypeHandshake,
   174  					DestConnectionID: protocol.ParseConnectionID([]byte{1, 2, 3, 4, 5, 6, 7, 8}),
   175  					SrcConnectionID:  protocol.ParseConnectionID([]byte{1, 2, 3, 4, 5, 6, 7, 8}),
   176  					Length:           1,
   177  				},
   178  				PacketNumberLen: protocol.PacketNumberLen1,
   179  			}
   180  			expectedLen := 1 /* type byte */ + 4 /* version */ + 1 /* dest conn ID len */ + 8 /* dest conn id */ + 1 /* src conn ID len */ + 8 /* src conn id */ + 2 /* length */ + 1 /* packet number */
   181  			Expect(h.GetLength(protocol.Version1)).To(BeEquivalentTo(expectedLen))
   182  			b, err := h.Append(nil, protocol.Version1)
   183  			Expect(err).ToNot(HaveOccurred())
   184  			Expect(b).To(HaveLen(expectedLen))
   185  		})
   186  
   187  		It("has the right length for the Long Header, for a long length", func() {
   188  			h := &ExtendedHeader{
   189  				Header: Header{
   190  					Type:             protocol.PacketTypeHandshake,
   191  					DestConnectionID: protocol.ParseConnectionID([]byte{1, 2, 3, 4, 5, 6, 7, 8}),
   192  					SrcConnectionID:  protocol.ParseConnectionID([]byte{1, 2, 3, 4, 5, 6, 7, 8}),
   193  					Length:           1500,
   194  				},
   195  				PacketNumberLen: protocol.PacketNumberLen2,
   196  			}
   197  			expectedLen := 1 /* type byte */ + 4 /* version */ + 1 /* dest conn id len */ + 8 /* dest conn id */ + 1 /* src conn ID len */ + 8 /* src conn id */ + 2 /* long len */ + 2 /* packet number */
   198  			Expect(h.GetLength(protocol.Version1)).To(BeEquivalentTo(expectedLen))
   199  			b, err := h.Append(nil, protocol.Version1)
   200  			Expect(err).ToNot(HaveOccurred())
   201  			Expect(b).To(HaveLen(expectedLen))
   202  		})
   203  
   204  		It("has the right length for an Initial that has a short length", func() {
   205  			h := &ExtendedHeader{
   206  				Header: Header{
   207  					Type:             protocol.PacketTypeInitial,
   208  					DestConnectionID: protocol.ParseConnectionID([]byte{1, 2, 3, 4, 5, 6, 7, 8}),
   209  					SrcConnectionID:  protocol.ParseConnectionID([]byte{1, 2, 3, 4}),
   210  					Length:           15,
   211  				},
   212  				PacketNumberLen: protocol.PacketNumberLen2,
   213  			}
   214  			expectedLen := 1 /* type byte */ + 4 /* version */ + 1 /* dest conn id len */ + 8 /* dest conn id */ + 1 /* src conn ID len */ + 4 /* src conn id */ + 1 /* token length */ + 2 /* length len */ + 2 /* packet number */
   215  			Expect(h.GetLength(protocol.Version1)).To(BeEquivalentTo(expectedLen))
   216  			b, err := h.Append(nil, protocol.Version1)
   217  			Expect(err).ToNot(HaveOccurred())
   218  			Expect(b).To(HaveLen(expectedLen))
   219  		})
   220  
   221  		It("has the right length for an Initial not containing a Token", func() {
   222  			h := &ExtendedHeader{
   223  				Header: Header{
   224  					Type:             protocol.PacketTypeInitial,
   225  					DestConnectionID: protocol.ParseConnectionID([]byte{1, 2, 3, 4, 5, 6, 7, 8}),
   226  					SrcConnectionID:  protocol.ParseConnectionID([]byte{1, 2, 3, 4}),
   227  					Length:           1500,
   228  				},
   229  				PacketNumberLen: protocol.PacketNumberLen2,
   230  			}
   231  			expectedLen := 1 /* type byte */ + 4 /* version */ + 1 /* dest conn id len */ + 8 /* dest conn id */ + 1 /* src conn ID len */ + 4 /* src conn id */ + 1 /* token length */ + 2 /* length len */ + 2 /* packet number */
   232  			Expect(h.GetLength(protocol.Version1)).To(BeEquivalentTo(expectedLen))
   233  			b, err := h.Append(nil, protocol.Version1)
   234  			Expect(err).ToNot(HaveOccurred())
   235  			Expect(b).To(HaveLen(expectedLen))
   236  		})
   237  
   238  		It("has the right length for an Initial containing a Token", func() {
   239  			h := &ExtendedHeader{
   240  				Header: Header{
   241  					DestConnectionID: protocol.ParseConnectionID([]byte{1, 2, 3, 4, 5, 6, 7, 8}),
   242  					SrcConnectionID:  protocol.ParseConnectionID([]byte{1, 2, 3, 4}),
   243  					Type:             protocol.PacketTypeInitial,
   244  					Length:           1500,
   245  					Token:            []byte("foo"),
   246  				},
   247  				PacketNumberLen: protocol.PacketNumberLen2,
   248  			}
   249  			expectedLen := 1 /* type byte */ + 4 /* version */ + 1 /* dest conn id len */ + 8 /* dest conn id */ + 1 /* src conn id len */ + 4 /* src conn id */ + 1 /* token length */ + 3 /* token */ + 2 /* long len */ + 2 /* packet number */
   250  			Expect(h.GetLength(protocol.Version1)).To(BeEquivalentTo(expectedLen))
   251  			b, err := h.Append(nil, protocol.Version1)
   252  			Expect(err).ToNot(HaveOccurred())
   253  			Expect(b).To(HaveLen(expectedLen))
   254  		})
   255  	})
   256  
   257  	Context("Logging", func() {
   258  		var (
   259  			buf    *bytes.Buffer
   260  			logger utils.Logger
   261  		)
   262  
   263  		BeforeEach(func() {
   264  			buf = &bytes.Buffer{}
   265  			logger = utils.DefaultLogger
   266  			logger.SetLogLevel(utils.LogLevelDebug)
   267  			log.SetOutput(buf)
   268  		})
   269  
   270  		AfterEach(func() {
   271  			log.SetOutput(os.Stdout)
   272  		})
   273  
   274  		It("logs Long Headers", func() {
   275  			(&ExtendedHeader{
   276  				Header: Header{
   277  					DestConnectionID: protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37}),
   278  					SrcConnectionID:  protocol.ParseConnectionID([]byte{0xde, 0xca, 0xfb, 0xad, 0x013, 0x37, 0x13, 0x37}),
   279  					Type:             protocol.PacketTypeHandshake,
   280  					Length:           54321,
   281  					Version:          0xfeed,
   282  				},
   283  				PacketNumber:    1337,
   284  				PacketNumberLen: protocol.PacketNumberLen2,
   285  			}).Log(logger)
   286  			Expect(buf.String()).To(ContainSubstring("Long Header{Type: Handshake, DestConnectionID: deadbeefcafe1337, SrcConnectionID: decafbad13371337, PacketNumber: 1337, PacketNumberLen: 2, Length: 54321, Version: 0xfeed}"))
   287  		})
   288  
   289  		It("logs Initial Packets with a Token", func() {
   290  			(&ExtendedHeader{
   291  				Header: Header{
   292  					DestConnectionID: protocol.ParseConnectionID([]byte{0xca, 0xfe, 0x13, 0x37}),
   293  					SrcConnectionID:  protocol.ParseConnectionID([]byte{0xde, 0xca, 0xfb, 0xad}),
   294  					Type:             protocol.PacketTypeInitial,
   295  					Token:            []byte{0xde, 0xad, 0xbe, 0xef},
   296  					Length:           100,
   297  					Version:          0xfeed,
   298  				},
   299  				PacketNumber:    42,
   300  				PacketNumberLen: protocol.PacketNumberLen2,
   301  			}).Log(logger)
   302  			Expect(buf.String()).To(ContainSubstring("Long Header{Type: Initial, DestConnectionID: cafe1337, SrcConnectionID: decafbad, Token: 0xdeadbeef, PacketNumber: 42, PacketNumberLen: 2, Length: 100, Version: 0xfeed}"))
   303  		})
   304  
   305  		It("logs Initial packets without a Token", func() {
   306  			(&ExtendedHeader{
   307  				Header: Header{
   308  					DestConnectionID: protocol.ParseConnectionID([]byte{0xca, 0xfe, 0x13, 0x37}),
   309  					SrcConnectionID:  protocol.ParseConnectionID([]byte{0xde, 0xca, 0xfb, 0xad}),
   310  					Type:             protocol.PacketTypeInitial,
   311  					Length:           100,
   312  					Version:          0xfeed,
   313  				},
   314  				PacketNumber:    42,
   315  				PacketNumberLen: protocol.PacketNumberLen2,
   316  			}).Log(logger)
   317  			Expect(buf.String()).To(ContainSubstring("Long Header{Type: Initial, DestConnectionID: cafe1337, SrcConnectionID: decafbad, Token: (empty), PacketNumber: 42, PacketNumberLen: 2, Length: 100, Version: 0xfeed}"))
   318  		})
   319  
   320  		It("logs Retry packets with a Token", func() {
   321  			(&ExtendedHeader{
   322  				Header: Header{
   323  					DestConnectionID: protocol.ParseConnectionID([]byte{0xca, 0xfe, 0x13, 0x37}),
   324  					SrcConnectionID:  protocol.ParseConnectionID([]byte{0xde, 0xca, 0xfb, 0xad}),
   325  					Type:             protocol.PacketTypeRetry,
   326  					Token:            []byte{0x12, 0x34, 0x56},
   327  					Version:          0xfeed,
   328  				},
   329  			}).Log(logger)
   330  			Expect(buf.String()).To(ContainSubstring("Long Header{Type: Retry, DestConnectionID: cafe1337, SrcConnectionID: decafbad, Token: 0x123456, Version: 0xfeed}"))
   331  		})
   332  	})
   333  })