github.com/tumi8/quic-go@v0.37.4-tum/noninternal/wire/transport_parameter_test.go (about) 1 package wire 2 3 import ( 4 "bytes" 5 "fmt" 6 "math" 7 "net" 8 "time" 9 10 "golang.org/x/exp/rand" 11 "github.com/tumi8/quic-go/noninternal/protocol" 12 "github.com/tumi8/quic-go/noninternal/qerr" 13 "github.com/tumi8/quic-go/quicvarint" 14 15 . "github.com/onsi/ginkgo/v2" 16 . "github.com/onsi/gomega" 17 ) 18 19 var _ = Describe("Transport Parameters", func() { 20 getRandomValueUpTo := func(max int64) uint64 { 21 maxVals := []int64{math.MaxUint8 / 4, math.MaxUint16 / 4, math.MaxUint32 / 4, math.MaxUint64 / 4} 22 m := maxVals[int(rand.Int31n(4))] 23 if m > max { 24 m = max 25 } 26 return uint64(rand.Int63n(m)) 27 } 28 29 getRandomValue := func() uint64 { 30 return getRandomValueUpTo(math.MaxInt64) 31 } 32 33 BeforeEach(func() { 34 rand.Seed(uint64(GinkgoRandomSeed())) 35 }) 36 37 appendInitialSourceConnectionID := func(b []byte) []byte { 38 b = quicvarint.Append(b, uint64(initialSourceConnectionIDParameterID)) 39 b = quicvarint.Append(b, 6) 40 return append(b, []byte("foobar")...) 41 } 42 43 It("has a string representation", func() { 44 rcid := protocol.ParseConnectionID([]byte{0xde, 0xad, 0xc0, 0xde}) 45 p := &TransportParameters{ 46 InitialMaxStreamDataBidiLocal: 1234, 47 InitialMaxStreamDataBidiRemote: 2345, 48 InitialMaxStreamDataUni: 3456, 49 InitialMaxData: 4567, 50 MaxBidiStreamNum: 1337, 51 MaxUniStreamNum: 7331, 52 MaxIdleTimeout: 42 * time.Second, 53 OriginalDestinationConnectionID: protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef}), 54 InitialSourceConnectionID: protocol.ParseConnectionID([]byte{0xde, 0xca, 0xfb, 0xad}), 55 RetrySourceConnectionID: &rcid, 56 AckDelayExponent: 14, 57 MaxAckDelay: 37 * time.Millisecond, 58 StatelessResetToken: &protocol.StatelessResetToken{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00}, 59 ActiveConnectionIDLimit: 123, 60 MaxDatagramFrameSize: 876, 61 } 62 Expect(p.String()).To(Equal("&wire.TransportParameters{OriginalDestinationConnectionID: deadbeef, InitialSourceConnectionID: decafbad, RetrySourceConnectionID: deadc0de, InitialMaxStreamDataBidiLocal: 1234, InitialMaxStreamDataBidiRemote: 2345, InitialMaxStreamDataUni: 3456, InitialMaxData: 4567, MaxBidiStreamNum: 1337, MaxUniStreamNum: 7331, MaxIdleTimeout: 42s, AckDelayExponent: 14, MaxAckDelay: 37ms, ActiveConnectionIDLimit: 123, StatelessResetToken: 0x112233445566778899aabbccddeeff00, MaxDatagramFrameSize: 876}")) 63 }) 64 65 It("has a string representation, if there's no stateless reset token, no Retry source connection id and no datagram support", func() { 66 p := &TransportParameters{ 67 InitialMaxStreamDataBidiLocal: 1234, 68 InitialMaxStreamDataBidiRemote: 2345, 69 InitialMaxStreamDataUni: 3456, 70 InitialMaxData: 4567, 71 MaxBidiStreamNum: 1337, 72 MaxUniStreamNum: 7331, 73 MaxIdleTimeout: 42 * time.Second, 74 OriginalDestinationConnectionID: protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef}), 75 InitialSourceConnectionID: protocol.ParseConnectionID([]byte{}), 76 AckDelayExponent: 14, 77 MaxAckDelay: 37 * time.Second, 78 ActiveConnectionIDLimit: 89, 79 MaxDatagramFrameSize: protocol.InvalidByteCount, 80 } 81 Expect(p.String()).To(Equal("&wire.TransportParameters{OriginalDestinationConnectionID: deadbeef, InitialSourceConnectionID: (empty), InitialMaxStreamDataBidiLocal: 1234, InitialMaxStreamDataBidiRemote: 2345, InitialMaxStreamDataUni: 3456, InitialMaxData: 4567, MaxBidiStreamNum: 1337, MaxUniStreamNum: 7331, MaxIdleTimeout: 42s, AckDelayExponent: 14, MaxAckDelay: 37s, ActiveConnectionIDLimit: 89}")) 82 }) 83 84 It("marshals and unmarshals", func() { 85 var token protocol.StatelessResetToken 86 rand.Read(token[:]) 87 rcid := protocol.ParseConnectionID([]byte{0xde, 0xad, 0xc0, 0xde}) 88 params := &TransportParameters{ 89 InitialMaxStreamDataBidiLocal: protocol.ByteCount(getRandomValue()), 90 InitialMaxStreamDataBidiRemote: protocol.ByteCount(getRandomValue()), 91 InitialMaxStreamDataUni: protocol.ByteCount(getRandomValue()), 92 InitialMaxData: protocol.ByteCount(getRandomValue()), 93 MaxIdleTimeout: 0xcafe * time.Second, 94 MaxBidiStreamNum: protocol.StreamNum(getRandomValueUpTo(int64(protocol.MaxStreamCount))), 95 MaxUniStreamNum: protocol.StreamNum(getRandomValueUpTo(int64(protocol.MaxStreamCount))), 96 DisableActiveMigration: true, 97 StatelessResetToken: &token, 98 OriginalDestinationConnectionID: protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef}), 99 InitialSourceConnectionID: protocol.ParseConnectionID([]byte{0xde, 0xca, 0xfb, 0xad}), 100 RetrySourceConnectionID: &rcid, 101 AckDelayExponent: 13, 102 MaxAckDelay: 42 * time.Millisecond, 103 ActiveConnectionIDLimit: 2 + getRandomValueUpTo(math.MaxInt64-2), 104 MaxDatagramFrameSize: protocol.ByteCount(getRandomValue()), 105 } 106 data := params.Marshal(protocol.PerspectiveServer) 107 108 p := &TransportParameters{} 109 Expect(p.Unmarshal(data, protocol.PerspectiveServer)).To(Succeed()) 110 Expect(p.InitialMaxStreamDataBidiLocal).To(Equal(params.InitialMaxStreamDataBidiLocal)) 111 Expect(p.InitialMaxStreamDataBidiRemote).To(Equal(params.InitialMaxStreamDataBidiRemote)) 112 Expect(p.InitialMaxStreamDataUni).To(Equal(params.InitialMaxStreamDataUni)) 113 Expect(p.InitialMaxData).To(Equal(params.InitialMaxData)) 114 Expect(p.MaxUniStreamNum).To(Equal(params.MaxUniStreamNum)) 115 Expect(p.MaxBidiStreamNum).To(Equal(params.MaxBidiStreamNum)) 116 Expect(p.MaxIdleTimeout).To(Equal(params.MaxIdleTimeout)) 117 Expect(p.DisableActiveMigration).To(Equal(params.DisableActiveMigration)) 118 Expect(p.StatelessResetToken).To(Equal(params.StatelessResetToken)) 119 Expect(p.OriginalDestinationConnectionID).To(Equal(protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef}))) 120 Expect(p.InitialSourceConnectionID).To(Equal(protocol.ParseConnectionID([]byte{0xde, 0xca, 0xfb, 0xad}))) 121 Expect(p.RetrySourceConnectionID).To(Equal(&rcid)) 122 Expect(p.AckDelayExponent).To(Equal(uint8(13))) 123 Expect(p.MaxAckDelay).To(Equal(42 * time.Millisecond)) 124 Expect(p.ActiveConnectionIDLimit).To(Equal(params.ActiveConnectionIDLimit)) 125 Expect(p.MaxDatagramFrameSize).To(Equal(params.MaxDatagramFrameSize)) 126 }) 127 128 It("marshals additional transport parameters (used for testing large ClientHellos)", func() { 129 origAdditionalTransportParametersClient := AdditionalTransportParametersClient 130 defer func() { 131 AdditionalTransportParametersClient = origAdditionalTransportParametersClient 132 }() 133 AdditionalTransportParametersClient = map[uint64][]byte{1337: []byte("foobar")} 134 135 result := quicvarint.Append([]byte{}, 1337) 136 result = quicvarint.Append(result, 6) 137 result = append(result, []byte("foobar")...) 138 139 params := &TransportParameters{} 140 Expect(bytes.Contains(params.Marshal(protocol.PerspectiveClient), result)).To(BeTrue()) 141 Expect(bytes.Contains(params.Marshal(protocol.PerspectiveServer), result)).To(BeFalse()) 142 }) 143 144 It("doesn't marshal a retry_source_connection_id, if no Retry was performed", func() { 145 data := (&TransportParameters{ 146 StatelessResetToken: &protocol.StatelessResetToken{}, 147 ActiveConnectionIDLimit: 2, 148 }).Marshal(protocol.PerspectiveServer) 149 p := &TransportParameters{} 150 Expect(p.Unmarshal(data, protocol.PerspectiveServer)).To(Succeed()) 151 Expect(p.RetrySourceConnectionID).To(BeNil()) 152 }) 153 154 It("marshals a zero-length retry_source_connection_id", func() { 155 rcid := protocol.ParseConnectionID([]byte{}) 156 data := (&TransportParameters{ 157 RetrySourceConnectionID: &rcid, 158 StatelessResetToken: &protocol.StatelessResetToken{}, 159 ActiveConnectionIDLimit: 2, 160 }).Marshal(protocol.PerspectiveServer) 161 p := &TransportParameters{} 162 Expect(p.Unmarshal(data, protocol.PerspectiveServer)).To(Succeed()) 163 Expect(p.RetrySourceConnectionID).ToNot(BeNil()) 164 Expect(p.RetrySourceConnectionID.Len()).To(BeZero()) 165 }) 166 167 It("errors when the stateless_reset_token has the wrong length", func() { 168 b := quicvarint.Append(nil, uint64(statelessResetTokenParameterID)) 169 b = quicvarint.Append(b, 15) 170 b = append(b, make([]byte, 15)...) 171 Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ 172 ErrorCode: qerr.TransportParameterError, 173 ErrorMessage: "wrong length for stateless_reset_token: 15 (expected 16)", 174 })) 175 }) 176 177 It("errors when the max_packet_size is too small", func() { 178 b := quicvarint.Append(nil, uint64(maxUDPPayloadSizeParameterID)) 179 b = quicvarint.Append(b, uint64(quicvarint.Len(1199))) 180 b = quicvarint.Append(b, 1199) 181 Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ 182 ErrorCode: qerr.TransportParameterError, 183 ErrorMessage: "invalid value for max_packet_size: 1199 (minimum 1200)", 184 })) 185 }) 186 187 It("errors when disable_active_migration has content", func() { 188 b := quicvarint.Append(nil, uint64(disableActiveMigrationParameterID)) 189 b = quicvarint.Append(b, 6) 190 b = append(b, []byte("foobar")...) 191 Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ 192 ErrorCode: qerr.TransportParameterError, 193 ErrorMessage: "wrong length for disable_active_migration: 6 (expected empty)", 194 })) 195 }) 196 197 It("errors when the server doesn't set the original_destination_connection_id", func() { 198 b := quicvarint.Append(nil, uint64(statelessResetTokenParameterID)) 199 b = quicvarint.Append(b, 16) 200 b = append(b, make([]byte, 16)...) 201 b = appendInitialSourceConnectionID(b) 202 Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ 203 ErrorCode: qerr.TransportParameterError, 204 ErrorMessage: "missing original_destination_connection_id", 205 })) 206 }) 207 208 It("errors when the initial_source_connection_id is missing", func() { 209 Expect((&TransportParameters{}).Unmarshal([]byte{}, protocol.PerspectiveClient)).To(MatchError(&qerr.TransportError{ 210 ErrorCode: qerr.TransportParameterError, 211 ErrorMessage: "missing initial_source_connection_id", 212 })) 213 }) 214 215 It("errors when the max_ack_delay is too large", func() { 216 data := (&TransportParameters{ 217 MaxAckDelay: 1 << 14 * time.Millisecond, 218 StatelessResetToken: &protocol.StatelessResetToken{}, 219 }).Marshal(protocol.PerspectiveServer) 220 p := &TransportParameters{} 221 Expect(p.Unmarshal(data, protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ 222 ErrorCode: qerr.TransportParameterError, 223 ErrorMessage: "invalid value for max_ack_delay: 16384ms (maximum 16383ms)", 224 })) 225 }) 226 227 It("doesn't send the max_ack_delay, if it has the default value", func() { 228 const num = 1000 229 var defaultLen, dataLen int 230 // marshal 1000 times to average out the greasing transport parameter 231 maxAckDelay := protocol.DefaultMaxAckDelay + time.Millisecond 232 for i := 0; i < num; i++ { 233 dataDefault := (&TransportParameters{ 234 MaxAckDelay: protocol.DefaultMaxAckDelay, 235 StatelessResetToken: &protocol.StatelessResetToken{}, 236 }).Marshal(protocol.PerspectiveServer) 237 defaultLen += len(dataDefault) 238 data := (&TransportParameters{ 239 MaxAckDelay: maxAckDelay, 240 StatelessResetToken: &protocol.StatelessResetToken{}, 241 }).Marshal(protocol.PerspectiveServer) 242 dataLen += len(data) 243 } 244 entryLen := quicvarint.Len(uint64(ackDelayExponentParameterID)) /* parameter id */ + quicvarint.Len(uint64(quicvarint.Len(uint64(maxAckDelay.Milliseconds())))) /*length */ + quicvarint.Len(uint64(maxAckDelay.Milliseconds())) /* value */ 245 Expect(float32(dataLen) / num).To(BeNumerically("~", float32(defaultLen)/num+float32(entryLen), 1)) 246 }) 247 248 It("errors when the active_connection_id_limit is too small", func() { 249 data := (&TransportParameters{ 250 ActiveConnectionIDLimit: 1, 251 StatelessResetToken: &protocol.StatelessResetToken{}, 252 }).Marshal(protocol.PerspectiveServer) 253 p := &TransportParameters{} 254 Expect(p.Unmarshal(data, protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ 255 ErrorCode: qerr.TransportParameterError, 256 ErrorMessage: "invalid value for active_connection_id_limit: 1 (minimum 2)", 257 })) 258 }) 259 260 It("errors when the ack_delay_exponenent is too large", func() { 261 data := (&TransportParameters{ 262 AckDelayExponent: 21, 263 StatelessResetToken: &protocol.StatelessResetToken{}, 264 }).Marshal(protocol.PerspectiveServer) 265 p := &TransportParameters{} 266 Expect(p.Unmarshal(data, protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ 267 ErrorCode: qerr.TransportParameterError, 268 ErrorMessage: "invalid value for ack_delay_exponent: 21 (maximum 20)", 269 })) 270 }) 271 272 It("doesn't send the ack_delay_exponent, if it has the default value", func() { 273 const num = 1000 274 var defaultLen, dataLen int 275 // marshal 1000 times to average out the greasing transport parameter 276 for i := 0; i < num; i++ { 277 dataDefault := (&TransportParameters{ 278 AckDelayExponent: protocol.DefaultAckDelayExponent, 279 StatelessResetToken: &protocol.StatelessResetToken{}, 280 }).Marshal(protocol.PerspectiveServer) 281 defaultLen += len(dataDefault) 282 data := (&TransportParameters{ 283 AckDelayExponent: protocol.DefaultAckDelayExponent + 1, 284 StatelessResetToken: &protocol.StatelessResetToken{}, 285 }).Marshal(protocol.PerspectiveServer) 286 dataLen += len(data) 287 } 288 entryLen := quicvarint.Len(uint64(ackDelayExponentParameterID)) /* parameter id */ + quicvarint.Len(uint64(quicvarint.Len(protocol.DefaultAckDelayExponent+1))) /* length */ + quicvarint.Len(protocol.DefaultAckDelayExponent+1) /* value */ 289 Expect(float32(dataLen) / num).To(BeNumerically("~", float32(defaultLen)/num+float32(entryLen), 1)) 290 }) 291 292 It("sets the default value for the ack_delay_exponent and max_active_connection_id_limit, when no values were sent", func() { 293 data := (&TransportParameters{ 294 AckDelayExponent: protocol.DefaultAckDelayExponent, 295 StatelessResetToken: &protocol.StatelessResetToken{}, 296 ActiveConnectionIDLimit: protocol.DefaultActiveConnectionIDLimit, 297 }).Marshal(protocol.PerspectiveServer) 298 p := &TransportParameters{} 299 Expect(p.Unmarshal(data, protocol.PerspectiveServer)).To(Succeed()) 300 Expect(p.AckDelayExponent).To(BeEquivalentTo(protocol.DefaultAckDelayExponent)) 301 Expect(p.ActiveConnectionIDLimit).To(BeEquivalentTo(protocol.DefaultActiveConnectionIDLimit)) 302 }) 303 304 It("errors when the varint value has the wrong length", func() { 305 b := quicvarint.Append(nil, uint64(initialMaxStreamDataBidiLocalParameterID)) 306 b = quicvarint.Append(b, 2) 307 val := uint64(0xdeadbeef) 308 Expect(quicvarint.Len(val)).ToNot(BeEquivalentTo(2)) 309 b = quicvarint.Append(b, val) 310 b = appendInitialSourceConnectionID(b) 311 Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ 312 ErrorCode: qerr.TransportParameterError, 313 ErrorMessage: fmt.Sprintf("inconsistent transport parameter length for transport parameter %#x", initialMaxStreamDataBidiLocalParameterID), 314 })) 315 }) 316 317 It("errors if initial_max_streams_bidi is too large", func() { 318 b := quicvarint.Append(nil, uint64(initialMaxStreamsBidiParameterID)) 319 b = quicvarint.Append(b, uint64(quicvarint.Len(uint64(protocol.MaxStreamCount+1)))) 320 b = quicvarint.Append(b, uint64(protocol.MaxStreamCount+1)) 321 b = appendInitialSourceConnectionID(b) 322 Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ 323 ErrorCode: qerr.TransportParameterError, 324 ErrorMessage: "initial_max_streams_bidi too large: 1152921504606846977 (maximum 1152921504606846976)", 325 })) 326 }) 327 328 It("errors if initial_max_streams_uni is too large", func() { 329 b := quicvarint.Append(nil, uint64(initialMaxStreamsUniParameterID)) 330 b = quicvarint.Append(b, uint64(quicvarint.Len(uint64(protocol.MaxStreamCount+1)))) 331 b = quicvarint.Append(b, uint64(protocol.MaxStreamCount+1)) 332 b = appendInitialSourceConnectionID(b) 333 Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ 334 ErrorCode: qerr.TransportParameterError, 335 ErrorMessage: "initial_max_streams_uni too large: 1152921504606846977 (maximum 1152921504606846976)", 336 })) 337 }) 338 339 It("handles huge max_ack_delay values", func() { 340 val := uint64(math.MaxUint64) / 5 341 b := quicvarint.Append(nil, uint64(maxAckDelayParameterID)) 342 b = quicvarint.Append(b, uint64(quicvarint.Len(val))) 343 b = quicvarint.Append(b, val) 344 b = appendInitialSourceConnectionID(b) 345 Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveClient)).To(MatchError(&qerr.TransportError{ 346 ErrorCode: qerr.TransportParameterError, 347 ErrorMessage: "invalid value for max_ack_delay: 3689348814741910323ms (maximum 16383ms)", 348 })) 349 }) 350 351 It("skips unknown parameters", func() { 352 // write a known parameter 353 b := quicvarint.Append(nil, uint64(initialMaxStreamDataBidiLocalParameterID)) 354 b = quicvarint.Append(b, uint64(quicvarint.Len(0x1337))) 355 b = quicvarint.Append(b, 0x1337) 356 // write an unknown parameter 357 b = quicvarint.Append(b, 0x42) 358 b = quicvarint.Append(b, 6) 359 b = append(b, []byte("foobar")...) 360 // write a known parameter 361 b = quicvarint.Append(b, uint64(initialMaxStreamDataBidiRemoteParameterID)) 362 b = quicvarint.Append(b, uint64(quicvarint.Len(0x42))) 363 b = quicvarint.Append(b, 0x42) 364 b = appendInitialSourceConnectionID(b) 365 p := &TransportParameters{} 366 Expect(p.Unmarshal(b, protocol.PerspectiveClient)).To(Succeed()) 367 Expect(p.InitialMaxStreamDataBidiLocal).To(Equal(protocol.ByteCount(0x1337))) 368 Expect(p.InitialMaxStreamDataBidiRemote).To(Equal(protocol.ByteCount(0x42))) 369 }) 370 371 It("rejects duplicate parameters", func() { 372 // write first parameter 373 b := quicvarint.Append(nil, uint64(initialMaxStreamDataBidiLocalParameterID)) 374 b = quicvarint.Append(b, uint64(quicvarint.Len(0x1337))) 375 b = quicvarint.Append(b, 0x1337) 376 // write a second parameter 377 b = quicvarint.Append(b, uint64(initialMaxStreamDataBidiRemoteParameterID)) 378 b = quicvarint.Append(b, uint64(quicvarint.Len(0x42))) 379 b = quicvarint.Append(b, 0x42) 380 // write first parameter again 381 b = quicvarint.Append(b, uint64(initialMaxStreamDataBidiLocalParameterID)) 382 b = quicvarint.Append(b, uint64(quicvarint.Len(0x1337))) 383 b = quicvarint.Append(b, 0x1337) 384 b = appendInitialSourceConnectionID(b) 385 Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveClient)).To(MatchError(&qerr.TransportError{ 386 ErrorCode: qerr.TransportParameterError, 387 ErrorMessage: fmt.Sprintf("received duplicate transport parameter %#x", initialMaxStreamDataBidiLocalParameterID), 388 })) 389 }) 390 391 It("errors if there's not enough data to read", func() { 392 b := quicvarint.Append(nil, 0x42) 393 b = quicvarint.Append(b, 7) 394 b = append(b, []byte("foobar")...) 395 p := &TransportParameters{} 396 Expect(p.Unmarshal(b, protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ 397 ErrorCode: qerr.TransportParameterError, 398 ErrorMessage: "remaining length (6) smaller than parameter length (7)", 399 })) 400 }) 401 402 It("errors if the client sent a stateless_reset_token", func() { 403 b := quicvarint.Append(nil, uint64(statelessResetTokenParameterID)) 404 b = quicvarint.Append(b, uint64(quicvarint.Len(16))) 405 b = append(b, make([]byte, 16)...) 406 Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveClient)).To(MatchError(&qerr.TransportError{ 407 ErrorCode: qerr.TransportParameterError, 408 ErrorMessage: "client sent a stateless_reset_token", 409 })) 410 }) 411 412 It("errors if the client sent the original_destination_connection_id", func() { 413 b := quicvarint.Append(nil, uint64(originalDestinationConnectionIDParameterID)) 414 b = quicvarint.Append(b, 6) 415 b = append(b, []byte("foobar")...) 416 Expect((&TransportParameters{}).Unmarshal(b, protocol.PerspectiveClient)).To(MatchError(&qerr.TransportError{ 417 ErrorCode: qerr.TransportParameterError, 418 ErrorMessage: "client sent an original_destination_connection_id", 419 })) 420 }) 421 422 Context("preferred address", func() { 423 var pa *PreferredAddress 424 425 BeforeEach(func() { 426 pa = &PreferredAddress{ 427 IPv4: net.IPv4(127, 0, 0, 1), 428 IPv4Port: 42, 429 IPv6: net.IP{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, 430 IPv6Port: 13, 431 ConnectionID: protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef}), 432 StatelessResetToken: protocol.StatelessResetToken{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, 433 } 434 }) 435 436 It("marshals and unmarshals", func() { 437 data := (&TransportParameters{ 438 PreferredAddress: pa, 439 StatelessResetToken: &protocol.StatelessResetToken{}, 440 ActiveConnectionIDLimit: 2, 441 }).Marshal(protocol.PerspectiveServer) 442 p := &TransportParameters{} 443 Expect(p.Unmarshal(data, protocol.PerspectiveServer)).To(Succeed()) 444 Expect(p.PreferredAddress.IPv4.String()).To(Equal(pa.IPv4.String())) 445 Expect(p.PreferredAddress.IPv4Port).To(Equal(pa.IPv4Port)) 446 Expect(p.PreferredAddress.IPv6.String()).To(Equal(pa.IPv6.String())) 447 Expect(p.PreferredAddress.IPv6Port).To(Equal(pa.IPv6Port)) 448 Expect(p.PreferredAddress.ConnectionID).To(Equal(pa.ConnectionID)) 449 Expect(p.PreferredAddress.StatelessResetToken).To(Equal(pa.StatelessResetToken)) 450 }) 451 452 It("errors if the client sent a preferred_address", func() { 453 b := quicvarint.Append(nil, uint64(preferredAddressParameterID)) 454 b = quicvarint.Append(b, 6) 455 b = append(b, []byte("foobar")...) 456 p := &TransportParameters{} 457 Expect(p.Unmarshal(b, protocol.PerspectiveClient)).To(MatchError(&qerr.TransportError{ 458 ErrorCode: qerr.TransportParameterError, 459 ErrorMessage: "client sent a preferred_address", 460 })) 461 }) 462 463 It("errors on zero-length connection IDs", func() { 464 pa.ConnectionID = protocol.ParseConnectionID([]byte{}) 465 data := (&TransportParameters{ 466 PreferredAddress: pa, 467 StatelessResetToken: &protocol.StatelessResetToken{}, 468 }).Marshal(protocol.PerspectiveServer) 469 p := &TransportParameters{} 470 Expect(p.Unmarshal(data, protocol.PerspectiveServer)).To(MatchError(&qerr.TransportError{ 471 ErrorCode: qerr.TransportParameterError, 472 ErrorMessage: "invalid connection ID length: 0", 473 })) 474 }) 475 476 It("errors on EOF", func() { 477 raw := []byte{ 478 127, 0, 0, 1, // IPv4 479 0, 42, // IPv4 Port 480 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, // IPv6 481 13, 37, // IPv6 Port, 482 4, // conn ID len 483 0xde, 0xad, 0xbe, 0xef, 484 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, // stateless reset token 485 } 486 for i := 1; i < len(raw); i++ { 487 b := quicvarint.Append(nil, uint64(preferredAddressParameterID)) 488 b = append(b, raw[:i]...) 489 p := &TransportParameters{} 490 Expect(p.Unmarshal(b, protocol.PerspectiveServer)).ToNot(Succeed()) 491 } 492 }) 493 }) 494 495 Context("saving and retrieving from a session ticket", func() { 496 It("saves and retrieves the parameters", func() { 497 params := &TransportParameters{ 498 InitialMaxStreamDataBidiLocal: protocol.ByteCount(getRandomValue()), 499 InitialMaxStreamDataBidiRemote: protocol.ByteCount(getRandomValue()), 500 InitialMaxStreamDataUni: protocol.ByteCount(getRandomValue()), 501 InitialMaxData: protocol.ByteCount(getRandomValue()), 502 MaxBidiStreamNum: protocol.StreamNum(getRandomValueUpTo(int64(protocol.MaxStreamCount))), 503 MaxUniStreamNum: protocol.StreamNum(getRandomValueUpTo(int64(protocol.MaxStreamCount))), 504 ActiveConnectionIDLimit: 2 + getRandomValueUpTo(math.MaxInt64-2), 505 } 506 Expect(params.ValidFor0RTT(params)).To(BeTrue()) 507 b := params.MarshalForSessionTicket(nil) 508 var tp TransportParameters 509 Expect(tp.UnmarshalFromSessionTicket(bytes.NewReader(b))).To(Succeed()) 510 Expect(tp.InitialMaxStreamDataBidiLocal).To(Equal(params.InitialMaxStreamDataBidiLocal)) 511 Expect(tp.InitialMaxStreamDataBidiRemote).To(Equal(params.InitialMaxStreamDataBidiRemote)) 512 Expect(tp.InitialMaxStreamDataUni).To(Equal(params.InitialMaxStreamDataUni)) 513 Expect(tp.InitialMaxData).To(Equal(params.InitialMaxData)) 514 Expect(tp.MaxBidiStreamNum).To(Equal(params.MaxBidiStreamNum)) 515 Expect(tp.MaxUniStreamNum).To(Equal(params.MaxUniStreamNum)) 516 Expect(tp.ActiveConnectionIDLimit).To(Equal(params.ActiveConnectionIDLimit)) 517 }) 518 519 It("rejects the parameters if it can't parse them", func() { 520 var p TransportParameters 521 Expect(p.UnmarshalFromSessionTicket(bytes.NewReader([]byte("foobar")))).ToNot(Succeed()) 522 }) 523 524 It("rejects the parameters if the version changed", func() { 525 var p TransportParameters 526 data := p.MarshalForSessionTicket(nil) 527 b := quicvarint.Append(nil, transportParameterMarshalingVersion+1) 528 b = append(b, data[quicvarint.Len(transportParameterMarshalingVersion):]...) 529 Expect(p.UnmarshalFromSessionTicket(bytes.NewReader(b))).To(MatchError(fmt.Sprintf("unknown transport parameter marshaling version: %d", transportParameterMarshalingVersion+1))) 530 }) 531 532 Context("rejects the parameters if they changed", func() { 533 var p TransportParameters 534 saved := &TransportParameters{ 535 InitialMaxStreamDataBidiLocal: 1, 536 InitialMaxStreamDataBidiRemote: 2, 537 InitialMaxStreamDataUni: 3, 538 InitialMaxData: 4, 539 MaxBidiStreamNum: 5, 540 MaxUniStreamNum: 6, 541 ActiveConnectionIDLimit: 7, 542 } 543 544 BeforeEach(func() { 545 p = *saved 546 Expect(p.ValidFor0RTT(saved)).To(BeTrue()) 547 }) 548 549 It("rejects the parameters if the InitialMaxStreamDataBidiLocal was reduced", func() { 550 p.InitialMaxStreamDataBidiLocal = saved.InitialMaxStreamDataBidiLocal - 1 551 Expect(p.ValidFor0RTT(saved)).To(BeFalse()) 552 }) 553 554 It("doesn't reject the parameters if the InitialMaxStreamDataBidiLocal was increased", func() { 555 p.InitialMaxStreamDataBidiLocal = saved.InitialMaxStreamDataBidiLocal + 1 556 Expect(p.ValidFor0RTT(saved)).To(BeTrue()) 557 }) 558 559 It("rejects the parameters if the InitialMaxStreamDataBidiRemote was reduced", func() { 560 p.InitialMaxStreamDataBidiRemote = saved.InitialMaxStreamDataBidiRemote - 1 561 Expect(p.ValidFor0RTT(saved)).To(BeFalse()) 562 }) 563 564 It("doesn't reject the parameters if the InitialMaxStreamDataBidiRemote was increased", func() { 565 p.InitialMaxStreamDataBidiRemote = saved.InitialMaxStreamDataBidiRemote + 1 566 Expect(p.ValidFor0RTT(saved)).To(BeTrue()) 567 }) 568 569 It("rejects the parameters if the InitialMaxStreamDataUni was reduced", func() { 570 p.InitialMaxStreamDataUni = saved.InitialMaxStreamDataUni - 1 571 Expect(p.ValidFor0RTT(saved)).To(BeFalse()) 572 }) 573 574 It("doesn't reject the parameters if the InitialMaxStreamDataUni was increased", func() { 575 p.InitialMaxStreamDataUni = saved.InitialMaxStreamDataUni + 1 576 Expect(p.ValidFor0RTT(saved)).To(BeTrue()) 577 }) 578 579 It("rejects the parameters if the InitialMaxData was reduced", func() { 580 p.InitialMaxData = saved.InitialMaxData - 1 581 Expect(p.ValidFor0RTT(saved)).To(BeFalse()) 582 }) 583 584 It("doesn't reject the parameters if the InitialMaxData was increased", func() { 585 p.InitialMaxData = saved.InitialMaxData + 1 586 Expect(p.ValidFor0RTT(saved)).To(BeTrue()) 587 }) 588 589 It("rejects the parameters if the MaxBidiStreamNum was reduced", func() { 590 p.MaxBidiStreamNum = saved.MaxBidiStreamNum - 1 591 Expect(p.ValidFor0RTT(saved)).To(BeFalse()) 592 }) 593 594 It("accepts the parameters if the MaxBidiStreamNum was increased", func() { 595 p.MaxBidiStreamNum = saved.MaxBidiStreamNum + 1 596 Expect(p.ValidFor0RTT(saved)).To(BeTrue()) 597 }) 598 599 It("rejects the parameters if the MaxUniStreamNum changed", func() { 600 p.MaxUniStreamNum = saved.MaxUniStreamNum - 1 601 Expect(p.ValidFor0RTT(saved)).To(BeFalse()) 602 }) 603 604 It("accepts the parameters if the MaxUniStreamNum was increased", func() { 605 p.MaxUniStreamNum = saved.MaxUniStreamNum + 1 606 Expect(p.ValidFor0RTT(saved)).To(BeTrue()) 607 }) 608 609 It("rejects the parameters if the ActiveConnectionIDLimit changed", func() { 610 p.ActiveConnectionIDLimit = 0 611 Expect(p.ValidFor0RTT(saved)).To(BeFalse()) 612 }) 613 }) 614 615 Context("client checks the parameters after successfully sending 0-RTT data", func() { 616 var p TransportParameters 617 saved := &TransportParameters{ 618 InitialMaxStreamDataBidiLocal: 1, 619 InitialMaxStreamDataBidiRemote: 2, 620 InitialMaxStreamDataUni: 3, 621 InitialMaxData: 4, 622 MaxBidiStreamNum: 5, 623 MaxUniStreamNum: 6, 624 ActiveConnectionIDLimit: 7, 625 } 626 627 BeforeEach(func() { 628 p = *saved 629 Expect(p.ValidForUpdate(saved)).To(BeTrue()) 630 }) 631 632 It("rejects the parameters if the InitialMaxStreamDataBidiLocal was reduced", func() { 633 p.InitialMaxStreamDataBidiLocal = saved.InitialMaxStreamDataBidiLocal - 1 634 Expect(p.ValidForUpdate(saved)).To(BeFalse()) 635 }) 636 637 It("doesn't reject the parameters if the InitialMaxStreamDataBidiLocal was increased", func() { 638 p.InitialMaxStreamDataBidiLocal = saved.InitialMaxStreamDataBidiLocal + 1 639 Expect(p.ValidForUpdate(saved)).To(BeTrue()) 640 }) 641 642 It("rejects the parameters if the InitialMaxStreamDataBidiRemote was reduced", func() { 643 p.InitialMaxStreamDataBidiRemote = saved.InitialMaxStreamDataBidiRemote - 1 644 Expect(p.ValidForUpdate(saved)).To(BeFalse()) 645 }) 646 647 It("doesn't reject the parameters if the InitialMaxStreamDataBidiRemote was increased", func() { 648 p.InitialMaxStreamDataBidiRemote = saved.InitialMaxStreamDataBidiRemote + 1 649 Expect(p.ValidForUpdate(saved)).To(BeTrue()) 650 }) 651 652 It("rejects the parameters if the InitialMaxStreamDataUni was reduced", func() { 653 p.InitialMaxStreamDataUni = saved.InitialMaxStreamDataUni - 1 654 Expect(p.ValidForUpdate(saved)).To(BeFalse()) 655 }) 656 657 It("doesn't reject the parameters if the InitialMaxStreamDataUni was increased", func() { 658 p.InitialMaxStreamDataUni = saved.InitialMaxStreamDataUni + 1 659 Expect(p.ValidForUpdate(saved)).To(BeTrue()) 660 }) 661 662 It("rejects the parameters if the InitialMaxData was reduced", func() { 663 p.InitialMaxData = saved.InitialMaxData - 1 664 Expect(p.ValidForUpdate(saved)).To(BeFalse()) 665 }) 666 667 It("doesn't reject the parameters if the InitialMaxData was increased", func() { 668 p.InitialMaxData = saved.InitialMaxData + 1 669 Expect(p.ValidForUpdate(saved)).To(BeTrue()) 670 }) 671 672 It("rejects the parameters if the MaxBidiStreamNum was reduced", func() { 673 p.MaxBidiStreamNum = saved.MaxBidiStreamNum - 1 674 Expect(p.ValidForUpdate(saved)).To(BeFalse()) 675 }) 676 677 It("doesn't reject the parameters if the MaxBidiStreamNum was increased", func() { 678 p.MaxBidiStreamNum = saved.MaxBidiStreamNum + 1 679 Expect(p.ValidForUpdate(saved)).To(BeTrue()) 680 }) 681 682 It("rejects the parameters if the MaxUniStreamNum reduced", func() { 683 p.MaxUniStreamNum = saved.MaxUniStreamNum - 1 684 Expect(p.ValidForUpdate(saved)).To(BeFalse()) 685 }) 686 687 It("doesn't reject the parameters if the MaxUniStreamNum was increased", func() { 688 p.MaxUniStreamNum = saved.MaxUniStreamNum + 1 689 Expect(p.ValidForUpdate(saved)).To(BeTrue()) 690 }) 691 692 It("rejects the parameters if the ActiveConnectionIDLimit reduced", func() { 693 p.ActiveConnectionIDLimit = saved.ActiveConnectionIDLimit - 1 694 Expect(p.ValidForUpdate(saved)).To(BeFalse()) 695 }) 696 697 It("doesn't reject the parameters if the ActiveConnectionIDLimit increased", func() { 698 p.ActiveConnectionIDLimit = saved.ActiveConnectionIDLimit + 1 699 Expect(p.ValidForUpdate(saved)).To(BeTrue()) 700 }) 701 }) 702 }) 703 })