1package quic 2 3import ( 4 "bytes" 5 "context" 6 "crypto/rand" 7 "crypto/tls" 8 "errors" 9 "fmt" 10 "io" 11 "net" 12 "runtime/pprof" 13 "strings" 14 "time" 15 16 "github.com/lucas-clemente/quic-go/internal/ackhandler" 17 "github.com/lucas-clemente/quic-go/internal/handshake" 18 "github.com/lucas-clemente/quic-go/internal/mocks" 19 mockackhandler "github.com/lucas-clemente/quic-go/internal/mocks/ackhandler" 20 mocklogging "github.com/lucas-clemente/quic-go/internal/mocks/logging" 21 "github.com/lucas-clemente/quic-go/internal/protocol" 22 "github.com/lucas-clemente/quic-go/internal/qerr" 23 "github.com/lucas-clemente/quic-go/internal/testutils" 24 "github.com/lucas-clemente/quic-go/internal/utils" 25 "github.com/lucas-clemente/quic-go/internal/wire" 26 "github.com/lucas-clemente/quic-go/logging" 27 28 "github.com/golang/mock/gomock" 29 30 . "github.com/onsi/ginkgo" 31 . "github.com/onsi/gomega" 32) 33 34func areSessionsRunning() bool { 35 var b bytes.Buffer 36 pprof.Lookup("goroutine").WriteTo(&b, 1) 37 return strings.Contains(b.String(), "quic-go.(*session).run") 38} 39 40func areClosedSessionsRunning() bool { 41 var b bytes.Buffer 42 pprof.Lookup("goroutine").WriteTo(&b, 1) 43 return strings.Contains(b.String(), "quic-go.(*closedLocalSession).run") 44} 45 46var _ = Describe("Session", func() { 47 var ( 48 sess *session 49 sessionRunner *MockSessionRunner 50 mconn *MockSendConn 51 streamManager *MockStreamManager 52 packer *MockPacker 53 cryptoSetup *mocks.MockCryptoSetup 54 tracer *mocklogging.MockConnectionTracer 55 ) 56 remoteAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1337} 57 localAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 7331} 58 srcConnID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8} 59 destConnID := protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1} 60 clientDestConnID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} 61 62 getPacket := func(pn protocol.PacketNumber) *packedPacket { 63 buffer := getPacketBuffer() 64 buffer.Data = append(buffer.Data, []byte("foobar")...) 65 return &packedPacket{ 66 buffer: buffer, 67 packetContents: &packetContents{ 68 header: &wire.ExtendedHeader{PacketNumber: pn}, 69 length: 6, // foobar 70 }, 71 } 72 } 73 74 expectReplaceWithClosed := func() { 75 sessionRunner.EXPECT().ReplaceWithClosed(clientDestConnID, gomock.Any()).MaxTimes(1) 76 sessionRunner.EXPECT().ReplaceWithClosed(srcConnID, gomock.Any()).Do(func(_ protocol.ConnectionID, s packetHandler) { 77 Expect(s).To(BeAssignableToTypeOf(&closedLocalSession{})) 78 s.shutdown() 79 Eventually(areClosedSessionsRunning).Should(BeFalse()) 80 }) 81 } 82 83 BeforeEach(func() { 84 Eventually(areSessionsRunning).Should(BeFalse()) 85 86 sessionRunner = NewMockSessionRunner(mockCtrl) 87 mconn = NewMockSendConn(mockCtrl) 88 mconn.EXPECT().RemoteAddr().Return(remoteAddr).AnyTimes() 89 mconn.EXPECT().LocalAddr().Return(localAddr).AnyTimes() 90 tokenGenerator, err := handshake.NewTokenGenerator(rand.Reader) 91 Expect(err).ToNot(HaveOccurred()) 92 tracer = mocklogging.NewMockConnectionTracer(mockCtrl) 93 tracer.EXPECT().NegotiatedVersion(gomock.Any(), gomock.Any(), gomock.Any()).MaxTimes(1) 94 tracer.EXPECT().SentTransportParameters(gomock.Any()) 95 tracer.EXPECT().UpdatedKeyFromTLS(gomock.Any(), gomock.Any()).AnyTimes() 96 tracer.EXPECT().UpdatedCongestionState(gomock.Any()) 97 sess = newSession( 98 mconn, 99 sessionRunner, 100 nil, 101 nil, 102 clientDestConnID, 103 destConnID, 104 srcConnID, 105 protocol.StatelessResetToken{}, 106 populateServerConfig(&Config{DisablePathMTUDiscovery: true}), 107 nil, // tls.Config 108 tokenGenerator, 109 false, 110 tracer, 111 1234, 112 utils.DefaultLogger, 113 protocol.VersionTLS, 114 ).(*session) 115 streamManager = NewMockStreamManager(mockCtrl) 116 sess.streamsMap = streamManager 117 packer = NewMockPacker(mockCtrl) 118 sess.packer = packer 119 cryptoSetup = mocks.NewMockCryptoSetup(mockCtrl) 120 sess.cryptoStreamHandler = cryptoSetup 121 sess.handshakeComplete = true 122 sess.idleTimeout = time.Hour 123 }) 124 125 AfterEach(func() { 126 Eventually(areSessionsRunning).Should(BeFalse()) 127 }) 128 129 Context("frame handling", func() { 130 Context("handling STREAM frames", func() { 131 It("passes STREAM frames to the stream", func() { 132 f := &wire.StreamFrame{ 133 StreamID: 5, 134 Data: []byte{0xde, 0xca, 0xfb, 0xad}, 135 } 136 str := NewMockReceiveStreamI(mockCtrl) 137 str.EXPECT().handleStreamFrame(f) 138 streamManager.EXPECT().GetOrOpenReceiveStream(protocol.StreamID(5)).Return(str, nil) 139 Expect(sess.handleStreamFrame(f)).To(Succeed()) 140 }) 141 142 It("returns errors", func() { 143 testErr := errors.New("test err") 144 f := &wire.StreamFrame{ 145 StreamID: 5, 146 Data: []byte{0xde, 0xca, 0xfb, 0xad}, 147 } 148 str := NewMockReceiveStreamI(mockCtrl) 149 str.EXPECT().handleStreamFrame(f).Return(testErr) 150 streamManager.EXPECT().GetOrOpenReceiveStream(protocol.StreamID(5)).Return(str, nil) 151 Expect(sess.handleStreamFrame(f)).To(MatchError(testErr)) 152 }) 153 154 It("ignores STREAM frames for closed streams", func() { 155 streamManager.EXPECT().GetOrOpenReceiveStream(protocol.StreamID(5)).Return(nil, nil) // for closed streams, the streamManager returns nil 156 Expect(sess.handleStreamFrame(&wire.StreamFrame{ 157 StreamID: 5, 158 Data: []byte("foobar"), 159 })).To(Succeed()) 160 }) 161 }) 162 163 Context("handling ACK frames", func() { 164 It("informs the SentPacketHandler about ACKs", func() { 165 f := &wire.AckFrame{AckRanges: []wire.AckRange{{Smallest: 2, Largest: 3}}} 166 sph := mockackhandler.NewMockSentPacketHandler(mockCtrl) 167 sph.EXPECT().ReceivedAck(f, protocol.EncryptionHandshake, gomock.Any()) 168 sess.sentPacketHandler = sph 169 err := sess.handleAckFrame(f, protocol.EncryptionHandshake) 170 Expect(err).ToNot(HaveOccurred()) 171 }) 172 }) 173 174 Context("handling RESET_STREAM frames", func() { 175 It("closes the streams for writing", func() { 176 f := &wire.ResetStreamFrame{ 177 StreamID: 555, 178 ErrorCode: 42, 179 FinalSize: 0x1337, 180 } 181 str := NewMockReceiveStreamI(mockCtrl) 182 streamManager.EXPECT().GetOrOpenReceiveStream(protocol.StreamID(555)).Return(str, nil) 183 str.EXPECT().handleResetStreamFrame(f) 184 err := sess.handleResetStreamFrame(f) 185 Expect(err).ToNot(HaveOccurred()) 186 }) 187 188 It("returns errors", func() { 189 f := &wire.ResetStreamFrame{ 190 StreamID: 7, 191 FinalSize: 0x1337, 192 } 193 testErr := errors.New("flow control violation") 194 str := NewMockReceiveStreamI(mockCtrl) 195 streamManager.EXPECT().GetOrOpenReceiveStream(protocol.StreamID(7)).Return(str, nil) 196 str.EXPECT().handleResetStreamFrame(f).Return(testErr) 197 err := sess.handleResetStreamFrame(f) 198 Expect(err).To(MatchError(testErr)) 199 }) 200 201 It("ignores RESET_STREAM frames for closed streams", func() { 202 streamManager.EXPECT().GetOrOpenReceiveStream(protocol.StreamID(3)).Return(nil, nil) 203 Expect(sess.handleFrame(&wire.ResetStreamFrame{ 204 StreamID: 3, 205 ErrorCode: 42, 206 }, protocol.Encryption1RTT, protocol.ConnectionID{})).To(Succeed()) 207 }) 208 }) 209 210 Context("handling MAX_DATA and MAX_STREAM_DATA frames", func() { 211 var connFC *mocks.MockConnectionFlowController 212 213 BeforeEach(func() { 214 connFC = mocks.NewMockConnectionFlowController(mockCtrl) 215 sess.connFlowController = connFC 216 }) 217 218 It("updates the flow control window of a stream", func() { 219 f := &wire.MaxStreamDataFrame{ 220 StreamID: 12345, 221 MaximumStreamData: 0x1337, 222 } 223 str := NewMockSendStreamI(mockCtrl) 224 streamManager.EXPECT().GetOrOpenSendStream(protocol.StreamID(12345)).Return(str, nil) 225 str.EXPECT().updateSendWindow(protocol.ByteCount(0x1337)) 226 Expect(sess.handleMaxStreamDataFrame(f)).To(Succeed()) 227 }) 228 229 It("updates the flow control window of the connection", func() { 230 offset := protocol.ByteCount(0x800000) 231 connFC.EXPECT().UpdateSendWindow(offset) 232 sess.handleMaxDataFrame(&wire.MaxDataFrame{MaximumData: offset}) 233 }) 234 235 It("ignores MAX_STREAM_DATA frames for a closed stream", func() { 236 streamManager.EXPECT().GetOrOpenSendStream(protocol.StreamID(10)).Return(nil, nil) 237 Expect(sess.handleFrame(&wire.MaxStreamDataFrame{ 238 StreamID: 10, 239 MaximumStreamData: 1337, 240 }, protocol.Encryption1RTT, protocol.ConnectionID{})).To(Succeed()) 241 }) 242 }) 243 244 Context("handling MAX_STREAM_ID frames", func() { 245 It("passes the frame to the streamsMap", func() { 246 f := &wire.MaxStreamsFrame{ 247 Type: protocol.StreamTypeUni, 248 MaxStreamNum: 10, 249 } 250 streamManager.EXPECT().HandleMaxStreamsFrame(f) 251 sess.handleMaxStreamsFrame(f) 252 }) 253 }) 254 255 Context("handling STOP_SENDING frames", func() { 256 It("passes the frame to the stream", func() { 257 f := &wire.StopSendingFrame{ 258 StreamID: 5, 259 ErrorCode: 10, 260 } 261 str := NewMockSendStreamI(mockCtrl) 262 streamManager.EXPECT().GetOrOpenSendStream(protocol.StreamID(5)).Return(str, nil) 263 str.EXPECT().handleStopSendingFrame(f) 264 err := sess.handleStopSendingFrame(f) 265 Expect(err).ToNot(HaveOccurred()) 266 }) 267 268 It("ignores STOP_SENDING frames for a closed stream", func() { 269 streamManager.EXPECT().GetOrOpenSendStream(protocol.StreamID(3)).Return(nil, nil) 270 Expect(sess.handleFrame(&wire.StopSendingFrame{ 271 StreamID: 3, 272 ErrorCode: 1337, 273 }, protocol.Encryption1RTT, protocol.ConnectionID{})).To(Succeed()) 274 }) 275 }) 276 277 It("handles NEW_CONNECTION_ID frames", func() { 278 Expect(sess.handleFrame(&wire.NewConnectionIDFrame{ 279 SequenceNumber: 10, 280 ConnectionID: protocol.ConnectionID{1, 2, 3, 4}, 281 }, protocol.Encryption1RTT, protocol.ConnectionID{})).To(Succeed()) 282 Expect(sess.connIDManager.queue.Back().Value.ConnectionID).To(Equal(protocol.ConnectionID{1, 2, 3, 4})) 283 }) 284 285 It("handles PING frames", func() { 286 err := sess.handleFrame(&wire.PingFrame{}, protocol.Encryption1RTT, protocol.ConnectionID{}) 287 Expect(err).NotTo(HaveOccurred()) 288 }) 289 290 It("rejects PATH_RESPONSE frames", func() { 291 err := sess.handleFrame(&wire.PathResponseFrame{Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8}}, protocol.Encryption1RTT, protocol.ConnectionID{}) 292 Expect(err).To(MatchError("unexpected PATH_RESPONSE frame")) 293 }) 294 295 It("handles PATH_CHALLENGE frames", func() { 296 data := [8]byte{1, 2, 3, 4, 5, 6, 7, 8} 297 err := sess.handleFrame(&wire.PathChallengeFrame{Data: data}, protocol.Encryption1RTT, protocol.ConnectionID{}) 298 Expect(err).ToNot(HaveOccurred()) 299 frames, _ := sess.framer.AppendControlFrames(nil, 1000) 300 Expect(frames).To(Equal([]ackhandler.Frame{{Frame: &wire.PathResponseFrame{Data: data}}})) 301 }) 302 303 It("rejects NEW_TOKEN frames", func() { 304 err := sess.handleNewTokenFrame(&wire.NewTokenFrame{}) 305 Expect(err).To(HaveOccurred()) 306 Expect(err).To(BeAssignableToTypeOf(&qerr.TransportError{})) 307 Expect(err.(*qerr.TransportError).ErrorCode).To(Equal(qerr.ProtocolViolation)) 308 }) 309 310 It("handles BLOCKED frames", func() { 311 err := sess.handleFrame(&wire.DataBlockedFrame{}, protocol.Encryption1RTT, protocol.ConnectionID{}) 312 Expect(err).NotTo(HaveOccurred()) 313 }) 314 315 It("handles STREAM_BLOCKED frames", func() { 316 err := sess.handleFrame(&wire.StreamDataBlockedFrame{}, protocol.Encryption1RTT, protocol.ConnectionID{}) 317 Expect(err).NotTo(HaveOccurred()) 318 }) 319 320 It("handles STREAMS_BLOCKED frames", func() { 321 err := sess.handleFrame(&wire.StreamsBlockedFrame{}, protocol.Encryption1RTT, protocol.ConnectionID{}) 322 Expect(err).NotTo(HaveOccurred()) 323 }) 324 325 It("handles CONNECTION_CLOSE frames, with a transport error code", func() { 326 expectedErr := &qerr.TransportError{ 327 Remote: true, 328 ErrorCode: qerr.StreamLimitError, 329 ErrorMessage: "foobar", 330 } 331 streamManager.EXPECT().CloseWithError(expectedErr) 332 sessionRunner.EXPECT().ReplaceWithClosed(srcConnID, gomock.Any()).Do(func(_ protocol.ConnectionID, s packetHandler) { 333 Expect(s).To(BeAssignableToTypeOf(&closedRemoteSession{})) 334 }) 335 sessionRunner.EXPECT().ReplaceWithClosed(clientDestConnID, gomock.Any()).Do(func(_ protocol.ConnectionID, s packetHandler) { 336 Expect(s).To(BeAssignableToTypeOf(&closedRemoteSession{})) 337 }) 338 cryptoSetup.EXPECT().Close() 339 gomock.InOrder( 340 tracer.EXPECT().ClosedConnection(expectedErr), 341 tracer.EXPECT().Close(), 342 ) 343 344 go func() { 345 defer GinkgoRecover() 346 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 347 Expect(sess.run()).To(MatchError(expectedErr)) 348 }() 349 Expect(sess.handleFrame(&wire.ConnectionCloseFrame{ 350 ErrorCode: uint64(qerr.StreamLimitError), 351 ReasonPhrase: "foobar", 352 }, protocol.Encryption1RTT, protocol.ConnectionID{})).To(Succeed()) 353 Eventually(sess.Context().Done()).Should(BeClosed()) 354 }) 355 356 It("handles CONNECTION_CLOSE frames, with an application error code", func() { 357 testErr := &qerr.ApplicationError{ 358 Remote: true, 359 ErrorCode: 0x1337, 360 ErrorMessage: "foobar", 361 } 362 streamManager.EXPECT().CloseWithError(testErr) 363 sessionRunner.EXPECT().ReplaceWithClosed(srcConnID, gomock.Any()).Do(func(_ protocol.ConnectionID, s packetHandler) { 364 Expect(s).To(BeAssignableToTypeOf(&closedRemoteSession{})) 365 }) 366 sessionRunner.EXPECT().ReplaceWithClosed(clientDestConnID, gomock.Any()).Do(func(_ protocol.ConnectionID, s packetHandler) { 367 Expect(s).To(BeAssignableToTypeOf(&closedRemoteSession{})) 368 }) 369 cryptoSetup.EXPECT().Close() 370 gomock.InOrder( 371 tracer.EXPECT().ClosedConnection(testErr), 372 tracer.EXPECT().Close(), 373 ) 374 375 go func() { 376 defer GinkgoRecover() 377 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 378 Expect(sess.run()).To(MatchError(testErr)) 379 }() 380 ccf := &wire.ConnectionCloseFrame{ 381 ErrorCode: 0x1337, 382 ReasonPhrase: "foobar", 383 IsApplicationError: true, 384 } 385 Expect(sess.handleFrame(ccf, protocol.Encryption1RTT, protocol.ConnectionID{})).To(Succeed()) 386 Eventually(sess.Context().Done()).Should(BeClosed()) 387 }) 388 389 It("errors on HANDSHAKE_DONE frames", func() { 390 Expect(sess.handleHandshakeDoneFrame()).To(MatchError(&qerr.TransportError{ 391 ErrorCode: qerr.ProtocolViolation, 392 ErrorMessage: "received a HANDSHAKE_DONE frame", 393 })) 394 }) 395 }) 396 397 It("tells its versions", func() { 398 sess.version = 4242 399 Expect(sess.GetVersion()).To(Equal(protocol.VersionNumber(4242))) 400 }) 401 402 Context("closing", func() { 403 var ( 404 runErr chan error 405 expectedRunErr error 406 ) 407 408 BeforeEach(func() { 409 runErr = make(chan error, 1) 410 expectedRunErr = nil 411 }) 412 413 AfterEach(func() { 414 if expectedRunErr != nil { 415 Eventually(runErr).Should(Receive(MatchError(expectedRunErr))) 416 } else { 417 Eventually(runErr).Should(Receive()) 418 } 419 }) 420 421 runSession := func() { 422 go func() { 423 defer GinkgoRecover() 424 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 425 runErr <- sess.run() 426 }() 427 Eventually(areSessionsRunning).Should(BeTrue()) 428 } 429 430 It("shuts down without error", func() { 431 sess.handshakeComplete = true 432 runSession() 433 streamManager.EXPECT().CloseWithError(&qerr.ApplicationError{}) 434 expectReplaceWithClosed() 435 cryptoSetup.EXPECT().Close() 436 buffer := getPacketBuffer() 437 buffer.Data = append(buffer.Data, []byte("connection close")...) 438 packer.EXPECT().PackApplicationClose(gomock.Any()).DoAndReturn(func(e *qerr.ApplicationError) (*coalescedPacket, error) { 439 Expect(e.ErrorCode).To(BeEquivalentTo(qerr.NoError)) 440 Expect(e.ErrorMessage).To(BeEmpty()) 441 return &coalescedPacket{buffer: buffer}, nil 442 }) 443 mconn.EXPECT().Write([]byte("connection close")) 444 gomock.InOrder( 445 tracer.EXPECT().ClosedConnection(gomock.Any()).Do(func(e error) { 446 var appErr *ApplicationError 447 Expect(errors.As(e, &appErr)).To(BeTrue()) 448 Expect(appErr.Remote).To(BeFalse()) 449 Expect(appErr.ErrorCode).To(BeZero()) 450 }), 451 tracer.EXPECT().Close(), 452 ) 453 sess.shutdown() 454 Eventually(areSessionsRunning).Should(BeFalse()) 455 Expect(sess.Context().Done()).To(BeClosed()) 456 }) 457 458 It("only closes once", func() { 459 runSession() 460 streamManager.EXPECT().CloseWithError(gomock.Any()) 461 expectReplaceWithClosed() 462 cryptoSetup.EXPECT().Close() 463 packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 464 mconn.EXPECT().Write(gomock.Any()) 465 tracer.EXPECT().ClosedConnection(gomock.Any()) 466 tracer.EXPECT().Close() 467 sess.shutdown() 468 sess.shutdown() 469 Eventually(areSessionsRunning).Should(BeFalse()) 470 Expect(sess.Context().Done()).To(BeClosed()) 471 }) 472 473 It("closes with an error", func() { 474 runSession() 475 expectedErr := &qerr.ApplicationError{ 476 ErrorCode: 0x1337, 477 ErrorMessage: "test error", 478 } 479 streamManager.EXPECT().CloseWithError(expectedErr) 480 expectReplaceWithClosed() 481 cryptoSetup.EXPECT().Close() 482 packer.EXPECT().PackApplicationClose(expectedErr).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 483 mconn.EXPECT().Write(gomock.Any()) 484 gomock.InOrder( 485 tracer.EXPECT().ClosedConnection(expectedErr), 486 tracer.EXPECT().Close(), 487 ) 488 sess.CloseWithError(0x1337, "test error") 489 Eventually(areSessionsRunning).Should(BeFalse()) 490 Expect(sess.Context().Done()).To(BeClosed()) 491 }) 492 493 It("includes the frame type in transport-level close frames", func() { 494 runSession() 495 expectedErr := &qerr.TransportError{ 496 ErrorCode: 0x1337, 497 FrameType: 0x42, 498 ErrorMessage: "test error", 499 } 500 streamManager.EXPECT().CloseWithError(expectedErr) 501 expectReplaceWithClosed() 502 cryptoSetup.EXPECT().Close() 503 packer.EXPECT().PackConnectionClose(expectedErr).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 504 mconn.EXPECT().Write(gomock.Any()) 505 gomock.InOrder( 506 tracer.EXPECT().ClosedConnection(expectedErr), 507 tracer.EXPECT().Close(), 508 ) 509 sess.closeLocal(expectedErr) 510 Eventually(areSessionsRunning).Should(BeFalse()) 511 Expect(sess.Context().Done()).To(BeClosed()) 512 }) 513 514 It("destroys the session", func() { 515 runSession() 516 testErr := errors.New("close") 517 streamManager.EXPECT().CloseWithError(gomock.Any()) 518 sessionRunner.EXPECT().Remove(gomock.Any()).AnyTimes() 519 cryptoSetup.EXPECT().Close() 520 // don't EXPECT any calls to mconn.Write() 521 gomock.InOrder( 522 tracer.EXPECT().ClosedConnection(gomock.Any()).Do(func(e error) { 523 var transportErr *TransportError 524 Expect(errors.As(e, &transportErr)).To(BeTrue()) 525 Expect(transportErr.Remote).To(BeFalse()) 526 Expect(transportErr.ErrorCode).To(Equal(qerr.InternalError)) 527 }), 528 tracer.EXPECT().Close(), 529 ) 530 sess.destroy(testErr) 531 Eventually(areSessionsRunning).Should(BeFalse()) 532 expectedRunErr = &qerr.TransportError{ 533 ErrorCode: qerr.InternalError, 534 ErrorMessage: testErr.Error(), 535 } 536 }) 537 538 It("cancels the context when the run loop exists", func() { 539 runSession() 540 streamManager.EXPECT().CloseWithError(gomock.Any()) 541 expectReplaceWithClosed() 542 cryptoSetup.EXPECT().Close() 543 packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 544 returned := make(chan struct{}) 545 go func() { 546 defer GinkgoRecover() 547 ctx := sess.Context() 548 <-ctx.Done() 549 Expect(ctx.Err()).To(MatchError(context.Canceled)) 550 close(returned) 551 }() 552 Consistently(returned).ShouldNot(BeClosed()) 553 mconn.EXPECT().Write(gomock.Any()) 554 tracer.EXPECT().ClosedConnection(gomock.Any()) 555 tracer.EXPECT().Close() 556 sess.shutdown() 557 Eventually(returned).Should(BeClosed()) 558 }) 559 560 It("doesn't send any more packets after receiving a CONNECTION_CLOSE", func() { 561 unpacker := NewMockUnpacker(mockCtrl) 562 sess.handshakeConfirmed = true 563 sess.unpacker = unpacker 564 runSession() 565 cryptoSetup.EXPECT().Close() 566 streamManager.EXPECT().CloseWithError(gomock.Any()) 567 sessionRunner.EXPECT().ReplaceWithClosed(gomock.Any(), gomock.Any()).AnyTimes() 568 buf := &bytes.Buffer{} 569 hdr := &wire.ExtendedHeader{ 570 Header: wire.Header{DestConnectionID: srcConnID}, 571 PacketNumberLen: protocol.PacketNumberLen2, 572 } 573 Expect(hdr.Write(buf, sess.version)).To(Succeed()) 574 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(*wire.Header, time.Time, []byte) (*unpackedPacket, error) { 575 buf := &bytes.Buffer{} 576 Expect((&wire.ConnectionCloseFrame{ErrorCode: uint64(qerr.StreamLimitError)}).Write(buf, sess.version)).To(Succeed()) 577 return &unpackedPacket{ 578 hdr: hdr, 579 data: buf.Bytes(), 580 encryptionLevel: protocol.Encryption1RTT, 581 }, nil 582 }) 583 gomock.InOrder( 584 tracer.EXPECT().StartedConnection(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()), 585 tracer.EXPECT().ReceivedPacket(gomock.Any(), gomock.Any(), gomock.Any()), 586 tracer.EXPECT().ClosedConnection(gomock.Any()), 587 tracer.EXPECT().Close(), 588 ) 589 // don't EXPECT any calls to packer.PackPacket() 590 sess.handlePacket(&receivedPacket{ 591 rcvTime: time.Now(), 592 remoteAddr: &net.UDPAddr{}, 593 buffer: getPacketBuffer(), 594 data: buf.Bytes(), 595 }) 596 // Consistently(pack).ShouldNot(Receive()) 597 Eventually(sess.Context().Done()).Should(BeClosed()) 598 }) 599 600 It("closes when the sendQueue encounters an error", func() { 601 sess.handshakeConfirmed = true 602 conn := NewMockSendConn(mockCtrl) 603 conn.EXPECT().Write(gomock.Any()).Return(io.ErrClosedPipe).AnyTimes() 604 sess.sendQueue = newSendQueue(conn) 605 sph := mockackhandler.NewMockSentPacketHandler(mockCtrl) 606 sph.EXPECT().GetLossDetectionTimeout().Return(time.Now().Add(time.Hour)).AnyTimes() 607 sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes() 608 sph.EXPECT().HasPacingBudget().Return(true).AnyTimes() 609 // only expect a single SentPacket() call 610 sph.EXPECT().SentPacket(gomock.Any()) 611 tracer.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) 612 tracer.EXPECT().ClosedConnection(gomock.Any()) 613 tracer.EXPECT().Close() 614 streamManager.EXPECT().CloseWithError(gomock.Any()) 615 sessionRunner.EXPECT().Remove(gomock.Any()).AnyTimes() 616 cryptoSetup.EXPECT().Close() 617 sess.sentPacketHandler = sph 618 p := getPacket(1) 619 packer.EXPECT().PackPacket().Return(p, nil) 620 packer.EXPECT().PackPacket().Return(nil, nil).AnyTimes() 621 runSession() 622 sess.queueControlFrame(&wire.PingFrame{}) 623 sess.scheduleSending() 624 Eventually(sess.Context().Done()).Should(BeClosed()) 625 }) 626 627 It("closes due to a stateless reset", func() { 628 token := protocol.StatelessResetToken{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} 629 runSession() 630 gomock.InOrder( 631 tracer.EXPECT().ClosedConnection(gomock.Any()).Do(func(e error) { 632 var srErr *StatelessResetError 633 Expect(errors.As(e, &srErr)).To(BeTrue()) 634 Expect(srErr.Token).To(Equal(token)) 635 }), 636 tracer.EXPECT().Close(), 637 ) 638 streamManager.EXPECT().CloseWithError(gomock.Any()) 639 sessionRunner.EXPECT().Remove(gomock.Any()).AnyTimes() 640 cryptoSetup.EXPECT().Close() 641 sess.destroy(&StatelessResetError{Token: token}) 642 }) 643 }) 644 645 Context("receiving packets", func() { 646 var unpacker *MockUnpacker 647 648 BeforeEach(func() { 649 unpacker = NewMockUnpacker(mockCtrl) 650 sess.unpacker = unpacker 651 }) 652 653 getPacket := func(extHdr *wire.ExtendedHeader, data []byte) *receivedPacket { 654 buf := &bytes.Buffer{} 655 Expect(extHdr.Write(buf, sess.version)).To(Succeed()) 656 return &receivedPacket{ 657 data: append(buf.Bytes(), data...), 658 buffer: getPacketBuffer(), 659 rcvTime: time.Now(), 660 } 661 } 662 663 It("drops Retry packets", func() { 664 p := getPacket(&wire.ExtendedHeader{Header: wire.Header{ 665 IsLongHeader: true, 666 Type: protocol.PacketTypeRetry, 667 DestConnectionID: destConnID, 668 SrcConnectionID: srcConnID, 669 Version: sess.version, 670 Token: []byte("foobar"), 671 }}, make([]byte, 16) /* Retry integrity tag */) 672 tracer.EXPECT().DroppedPacket(logging.PacketTypeRetry, p.Size(), logging.PacketDropUnexpectedPacket) 673 Expect(sess.handlePacketImpl(p)).To(BeFalse()) 674 }) 675 676 It("drops Version Negotiation packets", func() { 677 b, err := wire.ComposeVersionNegotiation(srcConnID, destConnID, sess.config.Versions) 678 Expect(err).ToNot(HaveOccurred()) 679 tracer.EXPECT().DroppedPacket(logging.PacketTypeVersionNegotiation, protocol.ByteCount(len(b)), logging.PacketDropUnexpectedPacket) 680 Expect(sess.handlePacketImpl(&receivedPacket{ 681 data: b, 682 buffer: getPacketBuffer(), 683 })).To(BeFalse()) 684 }) 685 686 It("drops packets for which header decryption fails", func() { 687 p := getPacket(&wire.ExtendedHeader{ 688 Header: wire.Header{ 689 IsLongHeader: true, 690 Type: protocol.PacketTypeHandshake, 691 Version: sess.version, 692 }, 693 PacketNumberLen: protocol.PacketNumberLen2, 694 }, nil) 695 p.data[0] ^= 0x40 // unset the QUIC bit 696 tracer.EXPECT().DroppedPacket(logging.PacketTypeNotDetermined, p.Size(), logging.PacketDropHeaderParseError) 697 Expect(sess.handlePacketImpl(p)).To(BeFalse()) 698 }) 699 700 It("drops packets for which the version is unsupported", func() { 701 p := getPacket(&wire.ExtendedHeader{ 702 Header: wire.Header{ 703 IsLongHeader: true, 704 Type: protocol.PacketTypeHandshake, 705 Version: sess.version + 1, 706 }, 707 PacketNumberLen: protocol.PacketNumberLen2, 708 }, nil) 709 tracer.EXPECT().DroppedPacket(logging.PacketTypeNotDetermined, p.Size(), logging.PacketDropUnsupportedVersion) 710 Expect(sess.handlePacketImpl(p)).To(BeFalse()) 711 }) 712 713 It("drops packets with an unsupported version", func() { 714 origSupportedVersions := make([]protocol.VersionNumber, len(protocol.SupportedVersions)) 715 copy(origSupportedVersions, protocol.SupportedVersions) 716 defer func() { 717 protocol.SupportedVersions = origSupportedVersions 718 }() 719 720 protocol.SupportedVersions = append(protocol.SupportedVersions, sess.version+1) 721 p := getPacket(&wire.ExtendedHeader{ 722 Header: wire.Header{ 723 IsLongHeader: true, 724 Type: protocol.PacketTypeHandshake, 725 DestConnectionID: destConnID, 726 SrcConnectionID: srcConnID, 727 Version: sess.version + 1, 728 }, 729 PacketNumberLen: protocol.PacketNumberLen2, 730 }, nil) 731 tracer.EXPECT().DroppedPacket(logging.PacketTypeHandshake, p.Size(), logging.PacketDropUnexpectedVersion) 732 Expect(sess.handlePacketImpl(p)).To(BeFalse()) 733 }) 734 735 It("informs the ReceivedPacketHandler about non-ack-eliciting packets", func() { 736 hdr := &wire.ExtendedHeader{ 737 Header: wire.Header{DestConnectionID: srcConnID}, 738 PacketNumber: 0x37, 739 PacketNumberLen: protocol.PacketNumberLen1, 740 } 741 packet := getPacket(hdr, nil) 742 packet.ecn = protocol.ECNCE 743 rcvTime := time.Now().Add(-10 * time.Second) 744 unpacker.EXPECT().Unpack(gomock.Any(), rcvTime, gomock.Any()).Return(&unpackedPacket{ 745 packetNumber: 0x1337, 746 encryptionLevel: protocol.EncryptionInitial, 747 hdr: hdr, 748 data: []byte{0}, // one PADDING frame 749 }, nil) 750 rph := mockackhandler.NewMockReceivedPacketHandler(mockCtrl) 751 gomock.InOrder( 752 rph.EXPECT().IsPotentiallyDuplicate(protocol.PacketNumber(0x1337), protocol.EncryptionInitial), 753 rph.EXPECT().ReceivedPacket(protocol.PacketNumber(0x1337), protocol.ECNCE, protocol.EncryptionInitial, rcvTime, false), 754 ) 755 sess.receivedPacketHandler = rph 756 packet.rcvTime = rcvTime 757 tracer.EXPECT().StartedConnection(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) 758 tracer.EXPECT().ReceivedPacket(hdr, protocol.ByteCount(len(packet.data)), []logging.Frame{}) 759 Expect(sess.handlePacketImpl(packet)).To(BeTrue()) 760 }) 761 762 It("informs the ReceivedPacketHandler about ack-eliciting packets", func() { 763 hdr := &wire.ExtendedHeader{ 764 Header: wire.Header{DestConnectionID: srcConnID}, 765 PacketNumber: 0x37, 766 PacketNumberLen: protocol.PacketNumberLen1, 767 } 768 rcvTime := time.Now().Add(-10 * time.Second) 769 buf := &bytes.Buffer{} 770 Expect((&wire.PingFrame{}).Write(buf, sess.version)).To(Succeed()) 771 packet := getPacket(hdr, nil) 772 packet.ecn = protocol.ECT1 773 unpacker.EXPECT().Unpack(gomock.Any(), rcvTime, gomock.Any()).Return(&unpackedPacket{ 774 packetNumber: 0x1337, 775 encryptionLevel: protocol.Encryption1RTT, 776 hdr: hdr, 777 data: buf.Bytes(), 778 }, nil) 779 rph := mockackhandler.NewMockReceivedPacketHandler(mockCtrl) 780 gomock.InOrder( 781 rph.EXPECT().IsPotentiallyDuplicate(protocol.PacketNumber(0x1337), protocol.Encryption1RTT), 782 rph.EXPECT().ReceivedPacket(protocol.PacketNumber(0x1337), protocol.ECT1, protocol.Encryption1RTT, rcvTime, true), 783 ) 784 sess.receivedPacketHandler = rph 785 packet.rcvTime = rcvTime 786 tracer.EXPECT().StartedConnection(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) 787 tracer.EXPECT().ReceivedPacket(hdr, protocol.ByteCount(len(packet.data)), []logging.Frame{&logging.PingFrame{}}) 788 Expect(sess.handlePacketImpl(packet)).To(BeTrue()) 789 }) 790 791 It("drops duplicate packets", func() { 792 hdr := &wire.ExtendedHeader{ 793 Header: wire.Header{DestConnectionID: srcConnID}, 794 PacketNumber: 0x37, 795 PacketNumberLen: protocol.PacketNumberLen1, 796 } 797 packet := getPacket(hdr, nil) 798 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(&unpackedPacket{ 799 packetNumber: 0x1337, 800 encryptionLevel: protocol.Encryption1RTT, 801 hdr: hdr, 802 data: []byte("foobar"), 803 }, nil) 804 rph := mockackhandler.NewMockReceivedPacketHandler(mockCtrl) 805 rph.EXPECT().IsPotentiallyDuplicate(protocol.PacketNumber(0x1337), protocol.Encryption1RTT).Return(true) 806 sess.receivedPacketHandler = rph 807 tracer.EXPECT().DroppedPacket(logging.PacketType1RTT, protocol.ByteCount(len(packet.data)), logging.PacketDropDuplicate) 808 Expect(sess.handlePacketImpl(packet)).To(BeFalse()) 809 }) 810 811 It("drops a packet when unpacking fails", func() { 812 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, handshake.ErrDecryptionFailed) 813 streamManager.EXPECT().CloseWithError(gomock.Any()) 814 cryptoSetup.EXPECT().Close() 815 packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 816 go func() { 817 defer GinkgoRecover() 818 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 819 sess.run() 820 }() 821 expectReplaceWithClosed() 822 p := getPacket(&wire.ExtendedHeader{ 823 Header: wire.Header{ 824 IsLongHeader: true, 825 Type: protocol.PacketTypeHandshake, 826 DestConnectionID: srcConnID, 827 Version: sess.version, 828 Length: 2 + 6, 829 }, 830 PacketNumber: 0x1337, 831 PacketNumberLen: protocol.PacketNumberLen2, 832 }, []byte("foobar")) 833 tracer.EXPECT().DroppedPacket(logging.PacketTypeHandshake, p.Size(), logging.PacketDropPayloadDecryptError) 834 sess.handlePacket(p) 835 Consistently(sess.Context().Done()).ShouldNot(BeClosed()) 836 // make the go routine return 837 tracer.EXPECT().ClosedConnection(gomock.Any()) 838 tracer.EXPECT().Close() 839 mconn.EXPECT().Write(gomock.Any()) 840 sess.closeLocal(errors.New("close")) 841 Eventually(sess.Context().Done()).Should(BeClosed()) 842 }) 843 844 It("processes multiple received packets before sending one", func() { 845 sess.sessionCreationTime = time.Now() 846 var pn protocol.PacketNumber 847 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(hdr *wire.Header, rcvTime time.Time, data []byte) (*unpackedPacket, error) { 848 pn++ 849 return &unpackedPacket{ 850 data: []byte{0}, // PADDING frame 851 encryptionLevel: protocol.Encryption1RTT, 852 packetNumber: pn, 853 hdr: &wire.ExtendedHeader{Header: *hdr}, 854 }, nil 855 }).Times(3) 856 tracer.EXPECT().StartedConnection(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) 857 tracer.EXPECT().ReceivedPacket(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(hdr *wire.ExtendedHeader, _ protocol.ByteCount, _ []logging.Frame) { 858 }).Times(3) 859 packer.EXPECT().PackCoalescedPacket() // only expect a single call 860 861 for i := 0; i < 3; i++ { 862 sess.handlePacket(getPacket(&wire.ExtendedHeader{ 863 Header: wire.Header{DestConnectionID: srcConnID}, 864 PacketNumber: 0x1337, 865 PacketNumberLen: protocol.PacketNumberLen2, 866 }, []byte("foobar"))) 867 } 868 869 go func() { 870 defer GinkgoRecover() 871 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 872 sess.run() 873 }() 874 Consistently(sess.Context().Done()).ShouldNot(BeClosed()) 875 876 // make the go routine return 877 streamManager.EXPECT().CloseWithError(gomock.Any()) 878 cryptoSetup.EXPECT().Close() 879 packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 880 expectReplaceWithClosed() 881 tracer.EXPECT().ClosedConnection(gomock.Any()) 882 tracer.EXPECT().Close() 883 mconn.EXPECT().Write(gomock.Any()) 884 sess.closeLocal(errors.New("close")) 885 Eventually(sess.Context().Done()).Should(BeClosed()) 886 }) 887 888 It("doesn't processes multiple received packets before sending one before handshake completion", func() { 889 sess.handshakeComplete = false 890 sess.sessionCreationTime = time.Now() 891 var pn protocol.PacketNumber 892 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(hdr *wire.Header, rcvTime time.Time, data []byte) (*unpackedPacket, error) { 893 pn++ 894 return &unpackedPacket{ 895 data: []byte{0}, // PADDING frame 896 encryptionLevel: protocol.Encryption1RTT, 897 packetNumber: pn, 898 hdr: &wire.ExtendedHeader{Header: *hdr}, 899 }, nil 900 }).Times(3) 901 tracer.EXPECT().StartedConnection(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) 902 tracer.EXPECT().ReceivedPacket(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(hdr *wire.ExtendedHeader, _ protocol.ByteCount, _ []logging.Frame) { 903 }).Times(3) 904 packer.EXPECT().PackCoalescedPacket().Times(3) // only expect a single call 905 906 for i := 0; i < 3; i++ { 907 sess.handlePacket(getPacket(&wire.ExtendedHeader{ 908 Header: wire.Header{DestConnectionID: srcConnID}, 909 PacketNumber: 0x1337, 910 PacketNumberLen: protocol.PacketNumberLen2, 911 }, []byte("foobar"))) 912 } 913 914 go func() { 915 defer GinkgoRecover() 916 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 917 sess.run() 918 }() 919 Consistently(sess.Context().Done()).ShouldNot(BeClosed()) 920 921 // make the go routine return 922 streamManager.EXPECT().CloseWithError(gomock.Any()) 923 cryptoSetup.EXPECT().Close() 924 packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 925 expectReplaceWithClosed() 926 tracer.EXPECT().ClosedConnection(gomock.Any()) 927 tracer.EXPECT().Close() 928 mconn.EXPECT().Write(gomock.Any()) 929 sess.closeLocal(errors.New("close")) 930 Eventually(sess.Context().Done()).Should(BeClosed()) 931 }) 932 933 It("closes the session when unpacking fails because the reserved bits were incorrect", func() { 934 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, wire.ErrInvalidReservedBits) 935 streamManager.EXPECT().CloseWithError(gomock.Any()) 936 cryptoSetup.EXPECT().Close() 937 packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 938 done := make(chan struct{}) 939 go func() { 940 defer GinkgoRecover() 941 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 942 err := sess.run() 943 Expect(err).To(HaveOccurred()) 944 Expect(err).To(BeAssignableToTypeOf(&qerr.TransportError{})) 945 Expect(err.(*qerr.TransportError).ErrorCode).To(Equal(qerr.ProtocolViolation)) 946 close(done) 947 }() 948 expectReplaceWithClosed() 949 mconn.EXPECT().Write(gomock.Any()) 950 packet := getPacket(&wire.ExtendedHeader{ 951 Header: wire.Header{DestConnectionID: srcConnID}, 952 PacketNumberLen: protocol.PacketNumberLen1, 953 }, nil) 954 tracer.EXPECT().ClosedConnection(gomock.Any()) 955 tracer.EXPECT().Close() 956 sess.handlePacket(packet) 957 Eventually(sess.Context().Done()).Should(BeClosed()) 958 }) 959 960 It("ignores packets when unpacking the header fails", func() { 961 testErr := &headerParseError{errors.New("test error")} 962 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, testErr) 963 streamManager.EXPECT().CloseWithError(gomock.Any()) 964 cryptoSetup.EXPECT().Close() 965 runErr := make(chan error) 966 go func() { 967 defer GinkgoRecover() 968 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 969 runErr <- sess.run() 970 }() 971 expectReplaceWithClosed() 972 tracer.EXPECT().DroppedPacket(logging.PacketType1RTT, gomock.Any(), logging.PacketDropHeaderParseError) 973 sess.handlePacket(getPacket(&wire.ExtendedHeader{ 974 Header: wire.Header{DestConnectionID: srcConnID}, 975 PacketNumberLen: protocol.PacketNumberLen1, 976 }, nil)) 977 Consistently(runErr).ShouldNot(Receive()) 978 // make the go routine return 979 packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 980 tracer.EXPECT().ClosedConnection(gomock.Any()) 981 tracer.EXPECT().Close() 982 mconn.EXPECT().Write(gomock.Any()) 983 sess.shutdown() 984 Eventually(sess.Context().Done()).Should(BeClosed()) 985 }) 986 987 It("closes the session when unpacking fails because of an error other than a decryption error", func() { 988 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, &qerr.TransportError{ErrorCode: qerr.ConnectionIDLimitError}) 989 streamManager.EXPECT().CloseWithError(gomock.Any()) 990 cryptoSetup.EXPECT().Close() 991 packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 992 done := make(chan struct{}) 993 go func() { 994 defer GinkgoRecover() 995 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 996 err := sess.run() 997 Expect(err).To(HaveOccurred()) 998 Expect(err).To(BeAssignableToTypeOf(&qerr.TransportError{})) 999 Expect(err.(*qerr.TransportError).ErrorCode).To(Equal(qerr.ConnectionIDLimitError)) 1000 close(done) 1001 }() 1002 expectReplaceWithClosed() 1003 mconn.EXPECT().Write(gomock.Any()) 1004 packet := getPacket(&wire.ExtendedHeader{ 1005 Header: wire.Header{DestConnectionID: srcConnID}, 1006 PacketNumberLen: protocol.PacketNumberLen1, 1007 }, nil) 1008 tracer.EXPECT().ClosedConnection(gomock.Any()) 1009 tracer.EXPECT().Close() 1010 sess.handlePacket(packet) 1011 Eventually(sess.Context().Done()).Should(BeClosed()) 1012 }) 1013 1014 It("rejects packets with empty payload", func() { 1015 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(&unpackedPacket{ 1016 hdr: &wire.ExtendedHeader{}, 1017 data: []byte{}, // no payload 1018 encryptionLevel: protocol.Encryption1RTT, 1019 }, nil) 1020 streamManager.EXPECT().CloseWithError(gomock.Any()) 1021 cryptoSetup.EXPECT().Close() 1022 packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 1023 done := make(chan struct{}) 1024 go func() { 1025 defer GinkgoRecover() 1026 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 1027 Expect(sess.run()).To(MatchError(&qerr.TransportError{ 1028 ErrorCode: qerr.ProtocolViolation, 1029 ErrorMessage: "empty packet", 1030 })) 1031 close(done) 1032 }() 1033 expectReplaceWithClosed() 1034 mconn.EXPECT().Write(gomock.Any()) 1035 tracer.EXPECT().ClosedConnection(gomock.Any()) 1036 tracer.EXPECT().Close() 1037 sess.handlePacket(getPacket(&wire.ExtendedHeader{ 1038 Header: wire.Header{DestConnectionID: srcConnID}, 1039 PacketNumberLen: protocol.PacketNumberLen1, 1040 }, nil)) 1041 Eventually(done).Should(BeClosed()) 1042 }) 1043 1044 It("ignores packets with a different source connection ID", func() { 1045 hdr1 := &wire.ExtendedHeader{ 1046 Header: wire.Header{ 1047 IsLongHeader: true, 1048 Type: protocol.PacketTypeInitial, 1049 DestConnectionID: destConnID, 1050 SrcConnectionID: srcConnID, 1051 Length: 1, 1052 Version: sess.version, 1053 }, 1054 PacketNumberLen: protocol.PacketNumberLen1, 1055 PacketNumber: 1, 1056 } 1057 hdr2 := &wire.ExtendedHeader{ 1058 Header: wire.Header{ 1059 IsLongHeader: true, 1060 Type: protocol.PacketTypeInitial, 1061 DestConnectionID: destConnID, 1062 SrcConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef}, 1063 Length: 1, 1064 Version: sess.version, 1065 }, 1066 PacketNumberLen: protocol.PacketNumberLen1, 1067 PacketNumber: 2, 1068 } 1069 Expect(srcConnID).ToNot(Equal(hdr2.SrcConnectionID)) 1070 // Send one packet, which might change the connection ID. 1071 // only EXPECT one call to the unpacker 1072 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(&unpackedPacket{ 1073 encryptionLevel: protocol.Encryption1RTT, 1074 hdr: hdr1, 1075 data: []byte{0}, // one PADDING frame 1076 }, nil) 1077 p1 := getPacket(hdr1, nil) 1078 tracer.EXPECT().StartedConnection(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) 1079 tracer.EXPECT().ReceivedPacket(gomock.Any(), protocol.ByteCount(len(p1.data)), gomock.Any()) 1080 Expect(sess.handlePacketImpl(p1)).To(BeTrue()) 1081 // The next packet has to be ignored, since the source connection ID doesn't match. 1082 p2 := getPacket(hdr2, nil) 1083 tracer.EXPECT().DroppedPacket(logging.PacketTypeInitial, protocol.ByteCount(len(p2.data)), logging.PacketDropUnknownConnectionID) 1084 Expect(sess.handlePacketImpl(p2)).To(BeFalse()) 1085 }) 1086 1087 It("queues undecryptable packets", func() { 1088 sess.handshakeComplete = false 1089 hdr := &wire.ExtendedHeader{ 1090 Header: wire.Header{ 1091 IsLongHeader: true, 1092 Type: protocol.PacketTypeHandshake, 1093 DestConnectionID: destConnID, 1094 SrcConnectionID: srcConnID, 1095 Length: 1, 1096 Version: sess.version, 1097 }, 1098 PacketNumberLen: protocol.PacketNumberLen1, 1099 PacketNumber: 1, 1100 } 1101 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, handshake.ErrKeysNotYetAvailable) 1102 packet := getPacket(hdr, nil) 1103 tracer.EXPECT().BufferedPacket(logging.PacketTypeHandshake) 1104 Expect(sess.handlePacketImpl(packet)).To(BeFalse()) 1105 Expect(sess.undecryptablePackets).To(Equal([]*receivedPacket{packet})) 1106 }) 1107 1108 Context("updating the remote address", func() { 1109 It("doesn't support connection migration", func() { 1110 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(&unpackedPacket{ 1111 encryptionLevel: protocol.Encryption1RTT, 1112 hdr: &wire.ExtendedHeader{}, 1113 data: []byte{0}, // one PADDING frame 1114 }, nil) 1115 packet := getPacket(&wire.ExtendedHeader{ 1116 Header: wire.Header{DestConnectionID: srcConnID}, 1117 PacketNumberLen: protocol.PacketNumberLen1, 1118 }, nil) 1119 packet.remoteAddr = &net.IPAddr{IP: net.IPv4(192, 168, 0, 100)} 1120 tracer.EXPECT().StartedConnection(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) 1121 tracer.EXPECT().ReceivedPacket(gomock.Any(), protocol.ByteCount(len(packet.data)), gomock.Any()) 1122 Expect(sess.handlePacketImpl(packet)).To(BeTrue()) 1123 }) 1124 }) 1125 1126 Context("coalesced packets", func() { 1127 BeforeEach(func() { 1128 tracer.EXPECT().StartedConnection(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).MaxTimes(1) 1129 }) 1130 getPacketWithLength := func(connID protocol.ConnectionID, length protocol.ByteCount) (int /* header length */, *receivedPacket) { 1131 hdr := &wire.ExtendedHeader{ 1132 Header: wire.Header{ 1133 IsLongHeader: true, 1134 Type: protocol.PacketTypeHandshake, 1135 DestConnectionID: connID, 1136 SrcConnectionID: destConnID, 1137 Version: protocol.VersionTLS, 1138 Length: length, 1139 }, 1140 PacketNumberLen: protocol.PacketNumberLen3, 1141 } 1142 hdrLen := hdr.GetLength(sess.version) 1143 b := make([]byte, 1) 1144 rand.Read(b) 1145 packet := getPacket(hdr, bytes.Repeat(b, int(length)-3)) 1146 return int(hdrLen), packet 1147 } 1148 1149 It("cuts packets to the right length", func() { 1150 hdrLen, packet := getPacketWithLength(srcConnID, 456) 1151 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(_ *wire.Header, _ time.Time, data []byte) (*unpackedPacket, error) { 1152 Expect(data).To(HaveLen(hdrLen + 456 - 3)) 1153 return &unpackedPacket{ 1154 encryptionLevel: protocol.EncryptionHandshake, 1155 data: []byte{0}, 1156 hdr: &wire.ExtendedHeader{}, 1157 }, nil 1158 }) 1159 tracer.EXPECT().ReceivedPacket(gomock.Any(), protocol.ByteCount(len(packet.data)), gomock.Any()) 1160 Expect(sess.handlePacketImpl(packet)).To(BeTrue()) 1161 }) 1162 1163 It("handles coalesced packets", func() { 1164 hdrLen1, packet1 := getPacketWithLength(srcConnID, 456) 1165 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(_ *wire.Header, _ time.Time, data []byte) (*unpackedPacket, error) { 1166 Expect(data).To(HaveLen(hdrLen1 + 456 - 3)) 1167 return &unpackedPacket{ 1168 encryptionLevel: protocol.EncryptionHandshake, 1169 data: []byte{0}, 1170 packetNumber: 1, 1171 hdr: &wire.ExtendedHeader{Header: wire.Header{SrcConnectionID: destConnID}}, 1172 }, nil 1173 }) 1174 hdrLen2, packet2 := getPacketWithLength(srcConnID, 123) 1175 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(_ *wire.Header, _ time.Time, data []byte) (*unpackedPacket, error) { 1176 Expect(data).To(HaveLen(hdrLen2 + 123 - 3)) 1177 return &unpackedPacket{ 1178 encryptionLevel: protocol.EncryptionHandshake, 1179 data: []byte{0}, 1180 packetNumber: 2, 1181 hdr: &wire.ExtendedHeader{Header: wire.Header{SrcConnectionID: destConnID}}, 1182 }, nil 1183 }) 1184 gomock.InOrder( 1185 tracer.EXPECT().ReceivedPacket(gomock.Any(), protocol.ByteCount(len(packet1.data)), gomock.Any()), 1186 tracer.EXPECT().ReceivedPacket(gomock.Any(), protocol.ByteCount(len(packet2.data)), gomock.Any()), 1187 ) 1188 packet1.data = append(packet1.data, packet2.data...) 1189 Expect(sess.handlePacketImpl(packet1)).To(BeTrue()) 1190 }) 1191 1192 It("works with undecryptable packets", func() { 1193 sess.handshakeComplete = false 1194 hdrLen1, packet1 := getPacketWithLength(srcConnID, 456) 1195 hdrLen2, packet2 := getPacketWithLength(srcConnID, 123) 1196 gomock.InOrder( 1197 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, handshake.ErrKeysNotYetAvailable), 1198 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(_ *wire.Header, _ time.Time, data []byte) (*unpackedPacket, error) { 1199 Expect(data).To(HaveLen(hdrLen2 + 123 - 3)) 1200 return &unpackedPacket{ 1201 encryptionLevel: protocol.EncryptionHandshake, 1202 data: []byte{0}, 1203 hdr: &wire.ExtendedHeader{}, 1204 }, nil 1205 }), 1206 ) 1207 gomock.InOrder( 1208 tracer.EXPECT().BufferedPacket(gomock.Any()), 1209 tracer.EXPECT().ReceivedPacket(gomock.Any(), protocol.ByteCount(len(packet2.data)), gomock.Any()), 1210 ) 1211 packet1.data = append(packet1.data, packet2.data...) 1212 Expect(sess.handlePacketImpl(packet1)).To(BeTrue()) 1213 1214 Expect(sess.undecryptablePackets).To(HaveLen(1)) 1215 Expect(sess.undecryptablePackets[0].data).To(HaveLen(hdrLen1 + 456 - 3)) 1216 }) 1217 1218 It("ignores coalesced packet parts if the destination connection IDs don't match", func() { 1219 wrongConnID := protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef} 1220 Expect(srcConnID).ToNot(Equal(wrongConnID)) 1221 hdrLen1, packet1 := getPacketWithLength(srcConnID, 456) 1222 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(_ *wire.Header, _ time.Time, data []byte) (*unpackedPacket, error) { 1223 Expect(data).To(HaveLen(hdrLen1 + 456 - 3)) 1224 return &unpackedPacket{ 1225 encryptionLevel: protocol.EncryptionHandshake, 1226 data: []byte{0}, 1227 hdr: &wire.ExtendedHeader{}, 1228 }, nil 1229 }) 1230 _, packet2 := getPacketWithLength(wrongConnID, 123) 1231 // don't EXPECT any more calls to unpacker.Unpack() 1232 gomock.InOrder( 1233 tracer.EXPECT().ReceivedPacket(gomock.Any(), protocol.ByteCount(len(packet1.data)), gomock.Any()), 1234 tracer.EXPECT().DroppedPacket(gomock.Any(), protocol.ByteCount(len(packet2.data)), logging.PacketDropUnknownConnectionID), 1235 ) 1236 packet1.data = append(packet1.data, packet2.data...) 1237 Expect(sess.handlePacketImpl(packet1)).To(BeTrue()) 1238 }) 1239 }) 1240 }) 1241 1242 Context("sending packets", func() { 1243 var ( 1244 sessionDone chan struct{} 1245 sender *MockSender 1246 ) 1247 1248 BeforeEach(func() { 1249 sender = NewMockSender(mockCtrl) 1250 sender.EXPECT().Run() 1251 sender.EXPECT().WouldBlock().AnyTimes() 1252 sess.sendQueue = sender 1253 sessionDone = make(chan struct{}) 1254 }) 1255 1256 AfterEach(func() { 1257 streamManager.EXPECT().CloseWithError(gomock.Any()) 1258 packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 1259 expectReplaceWithClosed() 1260 cryptoSetup.EXPECT().Close() 1261 mconn.EXPECT().Write(gomock.Any()) 1262 tracer.EXPECT().ClosedConnection(gomock.Any()) 1263 tracer.EXPECT().Close() 1264 sender.EXPECT().Close() 1265 sess.shutdown() 1266 Eventually(sess.Context().Done()).Should(BeClosed()) 1267 Eventually(sessionDone).Should(BeClosed()) 1268 }) 1269 1270 runSession := func() { 1271 go func() { 1272 defer GinkgoRecover() 1273 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 1274 sess.run() 1275 close(sessionDone) 1276 }() 1277 } 1278 1279 It("sends packets", func() { 1280 sess.handshakeConfirmed = true 1281 sph := mockackhandler.NewMockSentPacketHandler(mockCtrl) 1282 sph.EXPECT().TimeUntilSend().AnyTimes() 1283 sph.EXPECT().GetLossDetectionTimeout().AnyTimes() 1284 sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes() 1285 sph.EXPECT().HasPacingBudget().Return(true).AnyTimes() 1286 sph.EXPECT().SentPacket(gomock.Any()) 1287 sess.sentPacketHandler = sph 1288 runSession() 1289 p := getPacket(1) 1290 packer.EXPECT().PackPacket().Return(p, nil) 1291 packer.EXPECT().PackPacket().Return(nil, nil).AnyTimes() 1292 sent := make(chan struct{}) 1293 sender.EXPECT().WouldBlock().AnyTimes() 1294 sender.EXPECT().Send(gomock.Any()).Do(func(packet *packetBuffer) { close(sent) }) 1295 tracer.EXPECT().SentPacket(p.header, p.buffer.Len(), nil, []logging.Frame{}) 1296 sess.scheduleSending() 1297 Eventually(sent).Should(BeClosed()) 1298 }) 1299 1300 It("doesn't send packets if there's nothing to send", func() { 1301 sess.handshakeConfirmed = true 1302 runSession() 1303 packer.EXPECT().PackPacket().Return(nil, nil).AnyTimes() 1304 sess.receivedPacketHandler.ReceivedPacket(0x035e, protocol.ECNNon, protocol.Encryption1RTT, time.Now(), true) 1305 sess.scheduleSending() 1306 time.Sleep(50 * time.Millisecond) // make sure there are no calls to mconn.Write() 1307 }) 1308 1309 It("sends ACK only packets", func() { 1310 sph := mockackhandler.NewMockSentPacketHandler(mockCtrl) 1311 sph.EXPECT().TimeUntilSend().AnyTimes() 1312 sph.EXPECT().GetLossDetectionTimeout().AnyTimes() 1313 sph.EXPECT().SendMode().Return(ackhandler.SendAck) 1314 done := make(chan struct{}) 1315 packer.EXPECT().MaybePackAckPacket(false).Do(func(bool) { close(done) }) 1316 sess.sentPacketHandler = sph 1317 runSession() 1318 sess.scheduleSending() 1319 Eventually(done).Should(BeClosed()) 1320 }) 1321 1322 It("adds a BLOCKED frame when it is connection-level flow control blocked", func() { 1323 sess.handshakeConfirmed = true 1324 sph := mockackhandler.NewMockSentPacketHandler(mockCtrl) 1325 sph.EXPECT().TimeUntilSend().AnyTimes() 1326 sph.EXPECT().GetLossDetectionTimeout().AnyTimes() 1327 sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes() 1328 sph.EXPECT().HasPacingBudget().Return(true).AnyTimes() 1329 sph.EXPECT().SentPacket(gomock.Any()) 1330 sess.sentPacketHandler = sph 1331 fc := mocks.NewMockConnectionFlowController(mockCtrl) 1332 fc.EXPECT().IsNewlyBlocked().Return(true, protocol.ByteCount(1337)) 1333 fc.EXPECT().IsNewlyBlocked() 1334 p := getPacket(1) 1335 packer.EXPECT().PackPacket().Return(p, nil) 1336 packer.EXPECT().PackPacket().Return(nil, nil).AnyTimes() 1337 sess.connFlowController = fc 1338 runSession() 1339 sent := make(chan struct{}) 1340 sender.EXPECT().Send(gomock.Any()).Do(func(packet *packetBuffer) { close(sent) }) 1341 tracer.EXPECT().SentPacket(p.header, p.length, nil, []logging.Frame{}) 1342 sess.scheduleSending() 1343 Eventually(sent).Should(BeClosed()) 1344 frames, _ := sess.framer.AppendControlFrames(nil, 1000) 1345 Expect(frames).To(Equal([]ackhandler.Frame{{Frame: &logging.DataBlockedFrame{MaximumData: 1337}}})) 1346 }) 1347 1348 It("doesn't send when the SentPacketHandler doesn't allow it", func() { 1349 sph := mockackhandler.NewMockSentPacketHandler(mockCtrl) 1350 sph.EXPECT().GetLossDetectionTimeout().AnyTimes() 1351 sph.EXPECT().SendMode().Return(ackhandler.SendNone).AnyTimes() 1352 sph.EXPECT().TimeUntilSend().AnyTimes() 1353 sess.sentPacketHandler = sph 1354 runSession() 1355 sess.scheduleSending() 1356 time.Sleep(50 * time.Millisecond) 1357 }) 1358 1359 for _, enc := range []protocol.EncryptionLevel{protocol.EncryptionInitial, protocol.EncryptionHandshake, protocol.Encryption1RTT} { 1360 encLevel := enc 1361 1362 Context(fmt.Sprintf("sending %s probe packets", encLevel), func() { 1363 var sendMode ackhandler.SendMode 1364 var getFrame func(protocol.ByteCount) wire.Frame 1365 1366 BeforeEach(func() { 1367 //nolint:exhaustive 1368 switch encLevel { 1369 case protocol.EncryptionInitial: 1370 sendMode = ackhandler.SendPTOInitial 1371 getFrame = sess.retransmissionQueue.GetInitialFrame 1372 case protocol.EncryptionHandshake: 1373 sendMode = ackhandler.SendPTOHandshake 1374 getFrame = sess.retransmissionQueue.GetHandshakeFrame 1375 case protocol.Encryption1RTT: 1376 sendMode = ackhandler.SendPTOAppData 1377 getFrame = sess.retransmissionQueue.GetAppDataFrame 1378 } 1379 }) 1380 1381 It("sends a probe packet", func() { 1382 sph := mockackhandler.NewMockSentPacketHandler(mockCtrl) 1383 sph.EXPECT().GetLossDetectionTimeout().AnyTimes() 1384 sph.EXPECT().TimeUntilSend().AnyTimes() 1385 sph.EXPECT().SendMode().Return(sendMode) 1386 sph.EXPECT().SendMode().Return(ackhandler.SendNone) 1387 sph.EXPECT().QueueProbePacket(encLevel) 1388 p := getPacket(123) 1389 packer.EXPECT().MaybePackProbePacket(encLevel).Return(p, nil) 1390 sph.EXPECT().SentPacket(gomock.Any()).Do(func(packet *ackhandler.Packet) { 1391 Expect(packet.PacketNumber).To(Equal(protocol.PacketNumber(123))) 1392 }) 1393 sess.sentPacketHandler = sph 1394 runSession() 1395 sent := make(chan struct{}) 1396 sender.EXPECT().Send(gomock.Any()).Do(func(packet *packetBuffer) { close(sent) }) 1397 tracer.EXPECT().SentPacket(p.header, p.length, gomock.Any(), gomock.Any()) 1398 sess.scheduleSending() 1399 Eventually(sent).Should(BeClosed()) 1400 }) 1401 1402 It("sends a PING as a probe packet", func() { 1403 sph := mockackhandler.NewMockSentPacketHandler(mockCtrl) 1404 sph.EXPECT().GetLossDetectionTimeout().AnyTimes() 1405 sph.EXPECT().TimeUntilSend().AnyTimes() 1406 sph.EXPECT().SendMode().Return(sendMode) 1407 sph.EXPECT().SendMode().Return(ackhandler.SendNone) 1408 sph.EXPECT().QueueProbePacket(encLevel).Return(false) 1409 p := getPacket(123) 1410 packer.EXPECT().MaybePackProbePacket(encLevel).Return(p, nil) 1411 sph.EXPECT().SentPacket(gomock.Any()).Do(func(packet *ackhandler.Packet) { 1412 Expect(packet.PacketNumber).To(Equal(protocol.PacketNumber(123))) 1413 }) 1414 sess.sentPacketHandler = sph 1415 runSession() 1416 sent := make(chan struct{}) 1417 sender.EXPECT().Send(gomock.Any()).Do(func(packet *packetBuffer) { close(sent) }) 1418 tracer.EXPECT().SentPacket(p.header, p.length, gomock.Any(), gomock.Any()) 1419 sess.scheduleSending() 1420 Eventually(sent).Should(BeClosed()) 1421 // We're using a mock packet packer in this test. 1422 // We therefore need to test separately that the PING was actually queued. 1423 Expect(getFrame(1000)).To(BeAssignableToTypeOf(&wire.PingFrame{})) 1424 }) 1425 }) 1426 } 1427 }) 1428 1429 Context("packet pacing", func() { 1430 var ( 1431 sph *mockackhandler.MockSentPacketHandler 1432 sender *MockSender 1433 ) 1434 1435 BeforeEach(func() { 1436 tracer.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() 1437 sph = mockackhandler.NewMockSentPacketHandler(mockCtrl) 1438 sph.EXPECT().GetLossDetectionTimeout().AnyTimes() 1439 sess.handshakeConfirmed = true 1440 sess.handshakeComplete = true 1441 sess.sentPacketHandler = sph 1442 sender = NewMockSender(mockCtrl) 1443 sender.EXPECT().Run() 1444 sess.sendQueue = sender 1445 streamManager.EXPECT().CloseWithError(gomock.Any()) 1446 }) 1447 1448 AfterEach(func() { 1449 // make the go routine return 1450 packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 1451 expectReplaceWithClosed() 1452 cryptoSetup.EXPECT().Close() 1453 mconn.EXPECT().Write(gomock.Any()) 1454 tracer.EXPECT().ClosedConnection(gomock.Any()) 1455 tracer.EXPECT().Close() 1456 sender.EXPECT().Close() 1457 sess.shutdown() 1458 Eventually(sess.Context().Done()).Should(BeClosed()) 1459 }) 1460 1461 It("sends multiple packets one by one immediately", func() { 1462 sph.EXPECT().SentPacket(gomock.Any()).Times(2) 1463 sph.EXPECT().HasPacingBudget().Return(true).Times(2) 1464 sph.EXPECT().HasPacingBudget() 1465 sph.EXPECT().TimeUntilSend().Return(time.Now().Add(time.Hour)) 1466 sph.EXPECT().SendMode().Return(ackhandler.SendAny).Times(3) 1467 packer.EXPECT().PackPacket().Return(getPacket(10), nil) 1468 packer.EXPECT().PackPacket().Return(getPacket(11), nil) 1469 sender.EXPECT().WouldBlock().AnyTimes() 1470 sender.EXPECT().Send(gomock.Any()).Times(2) 1471 go func() { 1472 defer GinkgoRecover() 1473 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 1474 sess.run() 1475 }() 1476 sess.scheduleSending() 1477 time.Sleep(50 * time.Millisecond) // make sure that only 2 packets are sent 1478 }) 1479 1480 It("sends multiple packets, when the pacer allows immediate sending", func() { 1481 sph.EXPECT().SentPacket(gomock.Any()) 1482 sph.EXPECT().HasPacingBudget().Return(true).AnyTimes() 1483 sph.EXPECT().SendMode().Return(ackhandler.SendAny).Times(2) 1484 packer.EXPECT().PackPacket().Return(getPacket(10), nil) 1485 packer.EXPECT().PackPacket().Return(nil, nil) 1486 sender.EXPECT().WouldBlock().AnyTimes() 1487 sender.EXPECT().Send(gomock.Any()) 1488 go func() { 1489 defer GinkgoRecover() 1490 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 1491 sess.run() 1492 }() 1493 sess.scheduleSending() 1494 time.Sleep(50 * time.Millisecond) // make sure that only 1 packet is sent 1495 }) 1496 1497 It("allows an ACK to be sent when pacing limited", func() { 1498 sph.EXPECT().SentPacket(gomock.Any()) 1499 sph.EXPECT().HasPacingBudget() 1500 sph.EXPECT().TimeUntilSend().Return(time.Now().Add(time.Hour)) 1501 sph.EXPECT().SendMode().Return(ackhandler.SendAny) 1502 packer.EXPECT().MaybePackAckPacket(gomock.Any()).Return(getPacket(10), nil) 1503 sender.EXPECT().WouldBlock().AnyTimes() 1504 sender.EXPECT().Send(gomock.Any()) 1505 go func() { 1506 defer GinkgoRecover() 1507 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 1508 sess.run() 1509 }() 1510 sess.scheduleSending() 1511 time.Sleep(50 * time.Millisecond) // make sure that only 1 packet is sent 1512 }) 1513 1514 // when becoming congestion limited, at some point the SendMode will change from SendAny to SendAck 1515 // we shouldn't send the ACK in the same run 1516 It("doesn't send an ACK right after becoming congestion limited", func() { 1517 sph.EXPECT().SentPacket(gomock.Any()) 1518 sph.EXPECT().HasPacingBudget().Return(true) 1519 sph.EXPECT().SendMode().Return(ackhandler.SendAny) 1520 sph.EXPECT().SendMode().Return(ackhandler.SendAck) 1521 packer.EXPECT().PackPacket().Return(getPacket(100), nil) 1522 sender.EXPECT().WouldBlock().AnyTimes() 1523 sender.EXPECT().Send(gomock.Any()) 1524 go func() { 1525 defer GinkgoRecover() 1526 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 1527 sess.run() 1528 }() 1529 sess.scheduleSending() 1530 time.Sleep(50 * time.Millisecond) // make sure that only 1 packet is sent 1531 }) 1532 1533 It("paces packets", func() { 1534 pacingDelay := scaleDuration(100 * time.Millisecond) 1535 sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes() 1536 gomock.InOrder( 1537 sph.EXPECT().HasPacingBudget().Return(true), 1538 packer.EXPECT().PackPacket().Return(getPacket(100), nil), 1539 sph.EXPECT().SentPacket(gomock.Any()), 1540 sph.EXPECT().HasPacingBudget(), 1541 sph.EXPECT().TimeUntilSend().Return(time.Now().Add(pacingDelay)), 1542 sph.EXPECT().HasPacingBudget().Return(true), 1543 packer.EXPECT().PackPacket().Return(getPacket(101), nil), 1544 sph.EXPECT().SentPacket(gomock.Any()), 1545 sph.EXPECT().HasPacingBudget(), 1546 sph.EXPECT().TimeUntilSend().Return(time.Now().Add(time.Hour)), 1547 ) 1548 written := make(chan struct{}, 2) 1549 sender.EXPECT().WouldBlock().AnyTimes() 1550 sender.EXPECT().Send(gomock.Any()).DoAndReturn(func(p *packetBuffer) { written <- struct{}{} }).Times(2) 1551 go func() { 1552 defer GinkgoRecover() 1553 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 1554 sess.run() 1555 }() 1556 sess.scheduleSending() 1557 Eventually(written).Should(HaveLen(1)) 1558 Consistently(written, pacingDelay/2).Should(HaveLen(1)) 1559 Eventually(written, 2*pacingDelay).Should(HaveLen(2)) 1560 }) 1561 1562 It("sends multiple packets at once", func() { 1563 sph.EXPECT().SentPacket(gomock.Any()).Times(3) 1564 sph.EXPECT().HasPacingBudget().Return(true).Times(3) 1565 sph.EXPECT().HasPacingBudget() 1566 sph.EXPECT().TimeUntilSend().Return(time.Now().Add(time.Hour)) 1567 sph.EXPECT().SendMode().Return(ackhandler.SendAny).Times(4) 1568 packer.EXPECT().PackPacket().Return(getPacket(1000), nil) 1569 packer.EXPECT().PackPacket().Return(getPacket(1001), nil) 1570 packer.EXPECT().PackPacket().Return(getPacket(1002), nil) 1571 written := make(chan struct{}, 3) 1572 sender.EXPECT().WouldBlock().AnyTimes() 1573 sender.EXPECT().Send(gomock.Any()).DoAndReturn(func(p *packetBuffer) { written <- struct{}{} }).Times(3) 1574 go func() { 1575 defer GinkgoRecover() 1576 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 1577 sess.run() 1578 }() 1579 sess.scheduleSending() 1580 Eventually(written).Should(HaveLen(3)) 1581 }) 1582 1583 It("doesn't try to send if the send queue is full", func() { 1584 available := make(chan struct{}, 1) 1585 sender.EXPECT().WouldBlock().Return(true) 1586 sender.EXPECT().Available().Return(available) 1587 go func() { 1588 defer GinkgoRecover() 1589 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 1590 sess.run() 1591 }() 1592 sess.scheduleSending() 1593 time.Sleep(scaleDuration(50 * time.Millisecond)) 1594 1595 written := make(chan struct{}) 1596 sender.EXPECT().WouldBlock().AnyTimes() 1597 sph.EXPECT().SentPacket(gomock.Any()) 1598 sph.EXPECT().HasPacingBudget().Return(true).AnyTimes() 1599 sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes() 1600 packer.EXPECT().PackPacket().Return(getPacket(1000), nil) 1601 packer.EXPECT().PackPacket().Return(nil, nil) 1602 sender.EXPECT().Send(gomock.Any()).DoAndReturn(func(p *packetBuffer) { close(written) }) 1603 available <- struct{}{} 1604 Eventually(written).Should(BeClosed()) 1605 }) 1606 1607 It("stops sending when there are new packets to receive", func() { 1608 sender.EXPECT().WouldBlock().AnyTimes() 1609 go func() { 1610 defer GinkgoRecover() 1611 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 1612 sess.run() 1613 }() 1614 1615 written := make(chan struct{}) 1616 sender.EXPECT().WouldBlock().AnyTimes() 1617 sph.EXPECT().SentPacket(gomock.Any()).Do(func(*ackhandler.Packet) { 1618 sph.EXPECT().ReceivedBytes(gomock.Any()) 1619 sess.handlePacket(&receivedPacket{buffer: getPacketBuffer()}) 1620 }) 1621 sph.EXPECT().HasPacingBudget().Return(true).AnyTimes() 1622 sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes() 1623 packer.EXPECT().PackPacket().Return(getPacket(1000), nil) 1624 packer.EXPECT().PackPacket().Return(nil, nil) 1625 sender.EXPECT().Send(gomock.Any()).DoAndReturn(func(p *packetBuffer) { close(written) }) 1626 1627 sess.scheduleSending() 1628 time.Sleep(scaleDuration(50 * time.Millisecond)) 1629 1630 Eventually(written).Should(BeClosed()) 1631 }) 1632 1633 It("stops sending when the send queue is full", func() { 1634 sph.EXPECT().SentPacket(gomock.Any()) 1635 sph.EXPECT().HasPacingBudget().Return(true).AnyTimes() 1636 sph.EXPECT().SendMode().Return(ackhandler.SendAny) 1637 packer.EXPECT().PackPacket().Return(getPacket(1000), nil) 1638 written := make(chan struct{}, 1) 1639 sender.EXPECT().WouldBlock() 1640 sender.EXPECT().WouldBlock().Return(true).Times(2) 1641 sender.EXPECT().Send(gomock.Any()).DoAndReturn(func(p *packetBuffer) { written <- struct{}{} }) 1642 go func() { 1643 defer GinkgoRecover() 1644 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 1645 sess.run() 1646 }() 1647 available := make(chan struct{}, 1) 1648 sender.EXPECT().Available().Return(available) 1649 sess.scheduleSending() 1650 Eventually(written).Should(Receive()) 1651 time.Sleep(scaleDuration(50 * time.Millisecond)) 1652 1653 // now make room in the send queue 1654 sph.EXPECT().SentPacket(gomock.Any()) 1655 sph.EXPECT().HasPacingBudget().Return(true).AnyTimes() 1656 sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes() 1657 sender.EXPECT().WouldBlock().AnyTimes() 1658 packer.EXPECT().PackPacket().Return(getPacket(1001), nil) 1659 packer.EXPECT().PackPacket().Return(nil, nil) 1660 sender.EXPECT().Send(gomock.Any()).DoAndReturn(func(p *packetBuffer) { written <- struct{}{} }) 1661 available <- struct{}{} 1662 Eventually(written).Should(Receive()) 1663 1664 // The send queue is not full any more. Sending on the available channel should have no effect. 1665 available <- struct{}{} 1666 time.Sleep(scaleDuration(50 * time.Millisecond)) 1667 }) 1668 1669 It("doesn't set a pacing timer when there is no data to send", func() { 1670 sph.EXPECT().HasPacingBudget().Return(true) 1671 sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes() 1672 sender.EXPECT().WouldBlock().AnyTimes() 1673 packer.EXPECT().PackPacket() 1674 // don't EXPECT any calls to mconn.Write() 1675 go func() { 1676 defer GinkgoRecover() 1677 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 1678 sess.run() 1679 }() 1680 sess.scheduleSending() // no packet will get sent 1681 time.Sleep(50 * time.Millisecond) 1682 }) 1683 1684 It("sends a Path MTU probe packet", func() { 1685 mtuDiscoverer := NewMockMtuDiscoverer(mockCtrl) 1686 sess.mtuDiscoverer = mtuDiscoverer 1687 sess.config.DisablePathMTUDiscovery = false 1688 sph.EXPECT().SentPacket(gomock.Any()) 1689 sph.EXPECT().HasPacingBudget().Return(true).AnyTimes() 1690 sph.EXPECT().SendMode().Return(ackhandler.SendAny) 1691 sph.EXPECT().SendMode().Return(ackhandler.SendNone) 1692 written := make(chan struct{}, 1) 1693 sender.EXPECT().WouldBlock().AnyTimes() 1694 sender.EXPECT().Send(gomock.Any()).DoAndReturn(func(p *packetBuffer) { written <- struct{}{} }) 1695 gomock.InOrder( 1696 mtuDiscoverer.EXPECT().NextProbeTime(), 1697 mtuDiscoverer.EXPECT().ShouldSendProbe(gomock.Any()).Return(true), 1698 mtuDiscoverer.EXPECT().NextProbeTime(), 1699 ) 1700 ping := ackhandler.Frame{Frame: &wire.PingFrame{}} 1701 mtuDiscoverer.EXPECT().GetPing().Return(ping, protocol.ByteCount(1234)) 1702 packer.EXPECT().PackMTUProbePacket(ping, protocol.ByteCount(1234)).Return(getPacket(1), nil) 1703 go func() { 1704 defer GinkgoRecover() 1705 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 1706 sess.run() 1707 }() 1708 sess.scheduleSending() 1709 Eventually(written).Should(Receive()) 1710 }) 1711 }) 1712 1713 Context("scheduling sending", func() { 1714 var sender *MockSender 1715 1716 BeforeEach(func() { 1717 sender = NewMockSender(mockCtrl) 1718 sender.EXPECT().WouldBlock().AnyTimes() 1719 sender.EXPECT().Run() 1720 sess.sendQueue = sender 1721 sess.handshakeConfirmed = true 1722 }) 1723 1724 AfterEach(func() { 1725 // make the go routine return 1726 expectReplaceWithClosed() 1727 streamManager.EXPECT().CloseWithError(gomock.Any()) 1728 packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 1729 cryptoSetup.EXPECT().Close() 1730 mconn.EXPECT().Write(gomock.Any()) 1731 sender.EXPECT().Close() 1732 tracer.EXPECT().ClosedConnection(gomock.Any()) 1733 tracer.EXPECT().Close() 1734 sess.shutdown() 1735 Eventually(sess.Context().Done()).Should(BeClosed()) 1736 }) 1737 1738 It("sends when scheduleSending is called", func() { 1739 sph := mockackhandler.NewMockSentPacketHandler(mockCtrl) 1740 sph.EXPECT().GetLossDetectionTimeout().AnyTimes() 1741 sph.EXPECT().TimeUntilSend().AnyTimes() 1742 sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes() 1743 sph.EXPECT().HasPacingBudget().Return(true).AnyTimes() 1744 sph.EXPECT().SentPacket(gomock.Any()) 1745 sess.sentPacketHandler = sph 1746 packer.EXPECT().PackPacket().Return(getPacket(1), nil) 1747 packer.EXPECT().PackPacket().Return(nil, nil) 1748 1749 go func() { 1750 defer GinkgoRecover() 1751 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 1752 sess.run() 1753 }() 1754 // don't EXPECT any calls to mconn.Write() 1755 time.Sleep(50 * time.Millisecond) 1756 // only EXPECT calls after scheduleSending is called 1757 written := make(chan struct{}) 1758 sender.EXPECT().Send(gomock.Any()).Do(func(*packetBuffer) { close(written) }) 1759 tracer.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() 1760 sess.scheduleSending() 1761 Eventually(written).Should(BeClosed()) 1762 }) 1763 1764 It("sets the timer to the ack timer", func() { 1765 packer.EXPECT().PackPacket().Return(getPacket(1234), nil) 1766 packer.EXPECT().PackPacket().Return(nil, nil) 1767 sph := mockackhandler.NewMockSentPacketHandler(mockCtrl) 1768 sph.EXPECT().GetLossDetectionTimeout().AnyTimes() 1769 sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes() 1770 sph.EXPECT().HasPacingBudget().Return(true).AnyTimes() 1771 sph.EXPECT().SentPacket(gomock.Any()).Do(func(p *ackhandler.Packet) { 1772 Expect(p.PacketNumber).To(Equal(protocol.PacketNumber(1234))) 1773 }) 1774 sess.sentPacketHandler = sph 1775 rph := mockackhandler.NewMockReceivedPacketHandler(mockCtrl) 1776 rph.EXPECT().GetAlarmTimeout().Return(time.Now().Add(10 * time.Millisecond)) 1777 // make the run loop wait 1778 rph.EXPECT().GetAlarmTimeout().Return(time.Now().Add(time.Hour)).MaxTimes(1) 1779 sess.receivedPacketHandler = rph 1780 1781 written := make(chan struct{}) 1782 sender.EXPECT().Send(gomock.Any()).Do(func(*packetBuffer) { close(written) }) 1783 tracer.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() 1784 go func() { 1785 defer GinkgoRecover() 1786 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 1787 sess.run() 1788 }() 1789 Eventually(written).Should(BeClosed()) 1790 }) 1791 }) 1792 1793 It("sends coalesced packets before the handshake is confirmed", func() { 1794 sess.handshakeComplete = false 1795 sess.handshakeConfirmed = false 1796 sph := mockackhandler.NewMockSentPacketHandler(mockCtrl) 1797 sess.sentPacketHandler = sph 1798 buffer := getPacketBuffer() 1799 buffer.Data = append(buffer.Data, []byte("foobar")...) 1800 packer.EXPECT().PackCoalescedPacket().Return(&coalescedPacket{ 1801 buffer: buffer, 1802 packets: []*packetContents{ 1803 { 1804 header: &wire.ExtendedHeader{ 1805 Header: wire.Header{ 1806 IsLongHeader: true, 1807 Type: protocol.PacketTypeInitial, 1808 }, 1809 PacketNumber: 13, 1810 }, 1811 length: 123, 1812 }, 1813 { 1814 header: &wire.ExtendedHeader{ 1815 Header: wire.Header{ 1816 IsLongHeader: true, 1817 Type: protocol.PacketTypeHandshake, 1818 }, 1819 PacketNumber: 37, 1820 }, 1821 length: 1234, 1822 }, 1823 }, 1824 }, nil) 1825 packer.EXPECT().PackCoalescedPacket().AnyTimes() 1826 1827 sph.EXPECT().GetLossDetectionTimeout().AnyTimes() 1828 sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes() 1829 sph.EXPECT().TimeUntilSend().Return(time.Now()).AnyTimes() 1830 gomock.InOrder( 1831 sph.EXPECT().SentPacket(gomock.Any()).Do(func(p *ackhandler.Packet) { 1832 Expect(p.EncryptionLevel).To(Equal(protocol.EncryptionInitial)) 1833 Expect(p.PacketNumber).To(Equal(protocol.PacketNumber(13))) 1834 Expect(p.Length).To(BeEquivalentTo(123)) 1835 }), 1836 sph.EXPECT().SentPacket(gomock.Any()).Do(func(p *ackhandler.Packet) { 1837 Expect(p.EncryptionLevel).To(Equal(protocol.EncryptionHandshake)) 1838 Expect(p.PacketNumber).To(Equal(protocol.PacketNumber(37))) 1839 Expect(p.Length).To(BeEquivalentTo(1234)) 1840 }), 1841 ) 1842 gomock.InOrder( 1843 tracer.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Do(func(hdr *wire.ExtendedHeader, _ protocol.ByteCount, _ *wire.AckFrame, _ []logging.Frame) { 1844 Expect(hdr.Type).To(Equal(protocol.PacketTypeInitial)) 1845 }), 1846 tracer.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Do(func(hdr *wire.ExtendedHeader, _ protocol.ByteCount, _ *wire.AckFrame, _ []logging.Frame) { 1847 Expect(hdr.Type).To(Equal(protocol.PacketTypeHandshake)) 1848 }), 1849 ) 1850 1851 sent := make(chan struct{}) 1852 mconn.EXPECT().Write([]byte("foobar")).Do(func([]byte) { close(sent) }) 1853 1854 go func() { 1855 defer GinkgoRecover() 1856 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 1857 sess.run() 1858 }() 1859 1860 sess.scheduleSending() 1861 Eventually(sent).Should(BeClosed()) 1862 1863 // make sure the go routine returns 1864 streamManager.EXPECT().CloseWithError(gomock.Any()) 1865 expectReplaceWithClosed() 1866 packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 1867 cryptoSetup.EXPECT().Close() 1868 mconn.EXPECT().Write(gomock.Any()) 1869 tracer.EXPECT().ClosedConnection(gomock.Any()) 1870 tracer.EXPECT().Close() 1871 sess.shutdown() 1872 Eventually(sess.Context().Done()).Should(BeClosed()) 1873 }) 1874 1875 It("cancels the HandshakeComplete context when the handshake completes", func() { 1876 packer.EXPECT().PackCoalescedPacket().AnyTimes() 1877 finishHandshake := make(chan struct{}) 1878 sph := mockackhandler.NewMockSentPacketHandler(mockCtrl) 1879 sess.sentPacketHandler = sph 1880 sph.EXPECT().GetLossDetectionTimeout().AnyTimes() 1881 sph.EXPECT().TimeUntilSend().AnyTimes() 1882 sph.EXPECT().SendMode().AnyTimes() 1883 sph.EXPECT().SetHandshakeConfirmed() 1884 sessionRunner.EXPECT().Retire(clientDestConnID) 1885 go func() { 1886 defer GinkgoRecover() 1887 <-finishHandshake 1888 cryptoSetup.EXPECT().RunHandshake() 1889 cryptoSetup.EXPECT().SetHandshakeConfirmed() 1890 cryptoSetup.EXPECT().GetSessionTicket() 1891 close(sess.handshakeCompleteChan) 1892 sess.run() 1893 }() 1894 handshakeCtx := sess.HandshakeComplete() 1895 Consistently(handshakeCtx.Done()).ShouldNot(BeClosed()) 1896 close(finishHandshake) 1897 Eventually(handshakeCtx.Done()).Should(BeClosed()) 1898 // make sure the go routine returns 1899 streamManager.EXPECT().CloseWithError(gomock.Any()) 1900 expectReplaceWithClosed() 1901 packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 1902 cryptoSetup.EXPECT().Close() 1903 mconn.EXPECT().Write(gomock.Any()) 1904 tracer.EXPECT().ClosedConnection(gomock.Any()) 1905 tracer.EXPECT().Close() 1906 sess.shutdown() 1907 Eventually(sess.Context().Done()).Should(BeClosed()) 1908 }) 1909 1910 It("sends a session ticket when the handshake completes", func() { 1911 const size = protocol.MaxPostHandshakeCryptoFrameSize * 3 / 2 1912 packer.EXPECT().PackCoalescedPacket().AnyTimes() 1913 finishHandshake := make(chan struct{}) 1914 sessionRunner.EXPECT().Retire(clientDestConnID) 1915 go func() { 1916 defer GinkgoRecover() 1917 <-finishHandshake 1918 cryptoSetup.EXPECT().RunHandshake() 1919 cryptoSetup.EXPECT().SetHandshakeConfirmed() 1920 cryptoSetup.EXPECT().GetSessionTicket().Return(make([]byte, size), nil) 1921 close(sess.handshakeCompleteChan) 1922 sess.run() 1923 }() 1924 1925 handshakeCtx := sess.HandshakeComplete() 1926 Consistently(handshakeCtx.Done()).ShouldNot(BeClosed()) 1927 close(finishHandshake) 1928 var frames []ackhandler.Frame 1929 Eventually(func() []ackhandler.Frame { 1930 frames, _ = sess.framer.AppendControlFrames(nil, protocol.MaxByteCount) 1931 return frames 1932 }).ShouldNot(BeEmpty()) 1933 var count int 1934 var s int 1935 for _, f := range frames { 1936 if cf, ok := f.Frame.(*wire.CryptoFrame); ok { 1937 count++ 1938 s += len(cf.Data) 1939 Expect(f.Length(sess.version)).To(BeNumerically("<=", protocol.MaxPostHandshakeCryptoFrameSize)) 1940 } 1941 } 1942 Expect(size).To(BeEquivalentTo(s)) 1943 // make sure the go routine returns 1944 streamManager.EXPECT().CloseWithError(gomock.Any()) 1945 expectReplaceWithClosed() 1946 packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 1947 cryptoSetup.EXPECT().Close() 1948 mconn.EXPECT().Write(gomock.Any()) 1949 tracer.EXPECT().ClosedConnection(gomock.Any()) 1950 tracer.EXPECT().Close() 1951 sess.shutdown() 1952 Eventually(sess.Context().Done()).Should(BeClosed()) 1953 }) 1954 1955 It("doesn't cancel the HandshakeComplete context when the handshake fails", func() { 1956 packer.EXPECT().PackCoalescedPacket().AnyTimes() 1957 streamManager.EXPECT().CloseWithError(gomock.Any()) 1958 expectReplaceWithClosed() 1959 packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 1960 cryptoSetup.EXPECT().Close() 1961 tracer.EXPECT().ClosedConnection(gomock.Any()) 1962 tracer.EXPECT().Close() 1963 go func() { 1964 defer GinkgoRecover() 1965 cryptoSetup.EXPECT().RunHandshake() 1966 sess.run() 1967 }() 1968 handshakeCtx := sess.HandshakeComplete() 1969 Consistently(handshakeCtx.Done()).ShouldNot(BeClosed()) 1970 mconn.EXPECT().Write(gomock.Any()) 1971 sess.closeLocal(errors.New("handshake error")) 1972 Consistently(handshakeCtx.Done()).ShouldNot(BeClosed()) 1973 Eventually(sess.Context().Done()).Should(BeClosed()) 1974 }) 1975 1976 It("sends a HANDSHAKE_DONE frame when the handshake completes", func() { 1977 sph := mockackhandler.NewMockSentPacketHandler(mockCtrl) 1978 sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes() 1979 sph.EXPECT().GetLossDetectionTimeout().AnyTimes() 1980 sph.EXPECT().TimeUntilSend().AnyTimes() 1981 sph.EXPECT().HasPacingBudget().Return(true).AnyTimes() 1982 sph.EXPECT().SetHandshakeConfirmed() 1983 sph.EXPECT().SentPacket(gomock.Any()) 1984 mconn.EXPECT().Write(gomock.Any()) 1985 tracer.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) 1986 sess.sentPacketHandler = sph 1987 done := make(chan struct{}) 1988 sessionRunner.EXPECT().Retire(clientDestConnID) 1989 packer.EXPECT().PackPacket().DoAndReturn(func() (*packedPacket, error) { 1990 frames, _ := sess.framer.AppendControlFrames(nil, protocol.MaxByteCount) 1991 Expect(frames).ToNot(BeEmpty()) 1992 Expect(frames[0].Frame).To(BeEquivalentTo(&wire.HandshakeDoneFrame{})) 1993 defer close(done) 1994 return &packedPacket{ 1995 packetContents: &packetContents{ 1996 header: &wire.ExtendedHeader{}, 1997 }, 1998 buffer: getPacketBuffer(), 1999 }, nil 2000 }) 2001 packer.EXPECT().PackPacket().AnyTimes() 2002 go func() { 2003 defer GinkgoRecover() 2004 cryptoSetup.EXPECT().RunHandshake() 2005 cryptoSetup.EXPECT().SetHandshakeConfirmed() 2006 cryptoSetup.EXPECT().GetSessionTicket() 2007 mconn.EXPECT().Write(gomock.Any()) 2008 close(sess.handshakeCompleteChan) 2009 sess.run() 2010 }() 2011 Eventually(done).Should(BeClosed()) 2012 // make sure the go routine returns 2013 streamManager.EXPECT().CloseWithError(gomock.Any()) 2014 expectReplaceWithClosed() 2015 packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 2016 cryptoSetup.EXPECT().Close() 2017 tracer.EXPECT().ClosedConnection(gomock.Any()) 2018 tracer.EXPECT().Close() 2019 sess.shutdown() 2020 Eventually(sess.Context().Done()).Should(BeClosed()) 2021 }) 2022 2023 It("doesn't return a run error when closing", func() { 2024 done := make(chan struct{}) 2025 go func() { 2026 defer GinkgoRecover() 2027 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 2028 Expect(sess.run()).To(Succeed()) 2029 close(done) 2030 }() 2031 streamManager.EXPECT().CloseWithError(gomock.Any()) 2032 expectReplaceWithClosed() 2033 packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 2034 cryptoSetup.EXPECT().Close() 2035 mconn.EXPECT().Write(gomock.Any()) 2036 tracer.EXPECT().ClosedConnection(gomock.Any()) 2037 tracer.EXPECT().Close() 2038 sess.shutdown() 2039 Eventually(done).Should(BeClosed()) 2040 }) 2041 2042 It("passes errors to the session runner", func() { 2043 testErr := errors.New("handshake error") 2044 done := make(chan struct{}) 2045 go func() { 2046 defer GinkgoRecover() 2047 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 2048 err := sess.run() 2049 Expect(err).To(MatchError(&qerr.ApplicationError{ 2050 ErrorCode: 0x1337, 2051 ErrorMessage: testErr.Error(), 2052 })) 2053 close(done) 2054 }() 2055 streamManager.EXPECT().CloseWithError(gomock.Any()) 2056 expectReplaceWithClosed() 2057 packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 2058 cryptoSetup.EXPECT().Close() 2059 mconn.EXPECT().Write(gomock.Any()) 2060 tracer.EXPECT().ClosedConnection(gomock.Any()) 2061 tracer.EXPECT().Close() 2062 Expect(sess.CloseWithError(0x1337, testErr.Error())).To(Succeed()) 2063 Eventually(done).Should(BeClosed()) 2064 }) 2065 2066 Context("transport parameters", func() { 2067 It("processes transport parameters received from the client", func() { 2068 params := &wire.TransportParameters{ 2069 MaxIdleTimeout: 90 * time.Second, 2070 InitialMaxStreamDataBidiLocal: 0x5000, 2071 InitialMaxData: 0x5000, 2072 ActiveConnectionIDLimit: 3, 2073 // marshaling always sets it to this value 2074 MaxUDPPayloadSize: protocol.MaxPacketBufferSize, 2075 InitialSourceConnectionID: destConnID, 2076 } 2077 streamManager.EXPECT().UpdateLimits(params) 2078 packer.EXPECT().HandleTransportParameters(params) 2079 packer.EXPECT().PackCoalescedPacket().MaxTimes(3) 2080 Expect(sess.earlySessionReady()).ToNot(BeClosed()) 2081 sessionRunner.EXPECT().GetStatelessResetToken(gomock.Any()).Times(2) 2082 sessionRunner.EXPECT().Add(gomock.Any(), sess).Times(2) 2083 tracer.EXPECT().ReceivedTransportParameters(params) 2084 sess.handleTransportParameters(params) 2085 Expect(sess.earlySessionReady()).To(BeClosed()) 2086 }) 2087 }) 2088 2089 Context("keep-alives", func() { 2090 setRemoteIdleTimeout := func(t time.Duration) { 2091 streamManager.EXPECT().UpdateLimits(gomock.Any()) 2092 packer.EXPECT().HandleTransportParameters(gomock.Any()) 2093 tracer.EXPECT().ReceivedTransportParameters(gomock.Any()) 2094 sess.handleTransportParameters(&wire.TransportParameters{ 2095 MaxIdleTimeout: t, 2096 InitialSourceConnectionID: destConnID, 2097 }) 2098 } 2099 2100 runSession := func() { 2101 go func() { 2102 defer GinkgoRecover() 2103 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 2104 sess.run() 2105 }() 2106 } 2107 2108 BeforeEach(func() { 2109 sess.config.MaxIdleTimeout = 30 * time.Second 2110 sess.config.KeepAlive = true 2111 sess.receivedPacketHandler.ReceivedPacket(0, protocol.ECNNon, protocol.EncryptionHandshake, time.Now(), true) 2112 }) 2113 2114 AfterEach(func() { 2115 // make the go routine return 2116 expectReplaceWithClosed() 2117 streamManager.EXPECT().CloseWithError(gomock.Any()) 2118 packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 2119 cryptoSetup.EXPECT().Close() 2120 mconn.EXPECT().Write(gomock.Any()) 2121 tracer.EXPECT().ClosedConnection(gomock.Any()) 2122 tracer.EXPECT().Close() 2123 sess.shutdown() 2124 Eventually(sess.Context().Done()).Should(BeClosed()) 2125 }) 2126 2127 It("sends a PING as a keep-alive after half the idle timeout", func() { 2128 setRemoteIdleTimeout(5 * time.Second) 2129 sess.lastPacketReceivedTime = time.Now().Add(-5 * time.Second / 2) 2130 sent := make(chan struct{}) 2131 packer.EXPECT().PackCoalescedPacket().Do(func() (*packedPacket, error) { 2132 close(sent) 2133 return nil, nil 2134 }) 2135 runSession() 2136 Eventually(sent).Should(BeClosed()) 2137 }) 2138 2139 It("sends a PING after a maximum of protocol.MaxKeepAliveInterval", func() { 2140 sess.config.MaxIdleTimeout = time.Hour 2141 setRemoteIdleTimeout(time.Hour) 2142 sess.lastPacketReceivedTime = time.Now().Add(-protocol.MaxKeepAliveInterval).Add(-time.Millisecond) 2143 sent := make(chan struct{}) 2144 packer.EXPECT().PackCoalescedPacket().Do(func() (*packedPacket, error) { 2145 close(sent) 2146 return nil, nil 2147 }) 2148 runSession() 2149 Eventually(sent).Should(BeClosed()) 2150 }) 2151 2152 It("doesn't send a PING packet if keep-alive is disabled", func() { 2153 setRemoteIdleTimeout(5 * time.Second) 2154 sess.config.KeepAlive = false 2155 sess.lastPacketReceivedTime = time.Now().Add(-time.Second * 5 / 2) 2156 runSession() 2157 // don't EXPECT() any calls to mconn.Write() 2158 time.Sleep(50 * time.Millisecond) 2159 }) 2160 2161 It("doesn't send a PING if the handshake isn't completed yet", func() { 2162 sess.config.HandshakeIdleTimeout = time.Hour 2163 sess.handshakeComplete = false 2164 // Needs to be shorter than our idle timeout. 2165 // Otherwise we'll try to send a CONNECTION_CLOSE. 2166 sess.lastPacketReceivedTime = time.Now().Add(-20 * time.Second) 2167 runSession() 2168 // don't EXPECT() any calls to mconn.Write() 2169 time.Sleep(50 * time.Millisecond) 2170 }) 2171 }) 2172 2173 Context("timeouts", func() { 2174 BeforeEach(func() { 2175 streamManager.EXPECT().CloseWithError(gomock.Any()) 2176 }) 2177 2178 It("times out due to no network activity", func() { 2179 sessionRunner.EXPECT().Remove(gomock.Any()).Times(2) 2180 sess.lastPacketReceivedTime = time.Now().Add(-time.Hour) 2181 done := make(chan struct{}) 2182 cryptoSetup.EXPECT().Close() 2183 gomock.InOrder( 2184 tracer.EXPECT().ClosedConnection(gomock.Any()).Do(func(e error) { 2185 Expect(e).To(MatchError(&qerr.IdleTimeoutError{})) 2186 }), 2187 tracer.EXPECT().Close(), 2188 ) 2189 go func() { 2190 defer GinkgoRecover() 2191 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 2192 err := sess.run() 2193 nerr, ok := err.(net.Error) 2194 Expect(ok).To(BeTrue()) 2195 Expect(nerr.Timeout()).To(BeTrue()) 2196 Expect(err).To(MatchError(qerr.ErrIdleTimeout)) 2197 close(done) 2198 }() 2199 Eventually(done).Should(BeClosed()) 2200 }) 2201 2202 It("times out due to non-completed handshake", func() { 2203 sess.handshakeComplete = false 2204 sess.sessionCreationTime = time.Now().Add(-protocol.DefaultHandshakeTimeout).Add(-time.Second) 2205 sessionRunner.EXPECT().Remove(gomock.Any()).Times(2) 2206 cryptoSetup.EXPECT().Close() 2207 gomock.InOrder( 2208 tracer.EXPECT().ClosedConnection(gomock.Any()).Do(func(e error) { 2209 Expect(e).To(MatchError(&HandshakeTimeoutError{})) 2210 }), 2211 tracer.EXPECT().Close(), 2212 ) 2213 done := make(chan struct{}) 2214 go func() { 2215 defer GinkgoRecover() 2216 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 2217 err := sess.run() 2218 nerr, ok := err.(net.Error) 2219 Expect(ok).To(BeTrue()) 2220 Expect(nerr.Timeout()).To(BeTrue()) 2221 Expect(err).To(MatchError(qerr.ErrHandshakeTimeout)) 2222 close(done) 2223 }() 2224 Eventually(done).Should(BeClosed()) 2225 }) 2226 2227 It("does not use the idle timeout before the handshake complete", func() { 2228 sess.handshakeComplete = false 2229 sess.config.HandshakeIdleTimeout = 9999 * time.Second 2230 sess.config.MaxIdleTimeout = 9999 * time.Second 2231 sess.lastPacketReceivedTime = time.Now().Add(-time.Minute) 2232 packer.EXPECT().PackApplicationClose(gomock.Any()).DoAndReturn(func(e *qerr.ApplicationError) (*coalescedPacket, error) { 2233 Expect(e.ErrorCode).To(BeZero()) 2234 return &coalescedPacket{buffer: getPacketBuffer()}, nil 2235 }) 2236 gomock.InOrder( 2237 tracer.EXPECT().ClosedConnection(gomock.Any()).Do(func(e error) { 2238 idleTimeout := &IdleTimeoutError{} 2239 handshakeTimeout := &HandshakeTimeoutError{} 2240 Expect(errors.As(e, &idleTimeout)).To(BeFalse()) 2241 Expect(errors.As(e, &handshakeTimeout)).To(BeFalse()) 2242 }), 2243 tracer.EXPECT().Close(), 2244 ) 2245 // the handshake timeout is irrelevant here, since it depends on the time the session was created, 2246 // and not on the last network activity 2247 go func() { 2248 defer GinkgoRecover() 2249 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 2250 sess.run() 2251 }() 2252 Consistently(sess.Context().Done()).ShouldNot(BeClosed()) 2253 // make the go routine return 2254 expectReplaceWithClosed() 2255 cryptoSetup.EXPECT().Close() 2256 mconn.EXPECT().Write(gomock.Any()) 2257 sess.shutdown() 2258 Eventually(sess.Context().Done()).Should(BeClosed()) 2259 }) 2260 2261 It("closes the session due to the idle timeout before handshake", func() { 2262 sess.config.HandshakeIdleTimeout = 0 2263 packer.EXPECT().PackCoalescedPacket().AnyTimes() 2264 sessionRunner.EXPECT().Remove(gomock.Any()).AnyTimes() 2265 cryptoSetup.EXPECT().Close() 2266 gomock.InOrder( 2267 tracer.EXPECT().ClosedConnection(gomock.Any()).Do(func(e error) { 2268 Expect(e).To(MatchError(&IdleTimeoutError{})) 2269 }), 2270 tracer.EXPECT().Close(), 2271 ) 2272 done := make(chan struct{}) 2273 sess.handshakeComplete = false 2274 go func() { 2275 defer GinkgoRecover() 2276 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 2277 cryptoSetup.EXPECT().GetSessionTicket().MaxTimes(1) 2278 err := sess.run() 2279 nerr, ok := err.(net.Error) 2280 Expect(ok).To(BeTrue()) 2281 Expect(nerr.Timeout()).To(BeTrue()) 2282 Expect(err).To(MatchError(qerr.ErrIdleTimeout)) 2283 close(done) 2284 }() 2285 Eventually(done).Should(BeClosed()) 2286 }) 2287 2288 It("closes the session due to the idle timeout after handshake", func() { 2289 packer.EXPECT().PackCoalescedPacket().AnyTimes() 2290 gomock.InOrder( 2291 sessionRunner.EXPECT().Retire(clientDestConnID), 2292 sessionRunner.EXPECT().Remove(gomock.Any()), 2293 ) 2294 cryptoSetup.EXPECT().Close() 2295 gomock.InOrder( 2296 tracer.EXPECT().ClosedConnection(gomock.Any()).Do(func(e error) { 2297 Expect(e).To(MatchError(&IdleTimeoutError{})) 2298 }), 2299 tracer.EXPECT().Close(), 2300 ) 2301 sess.idleTimeout = 0 2302 done := make(chan struct{}) 2303 go func() { 2304 defer GinkgoRecover() 2305 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 2306 cryptoSetup.EXPECT().GetSessionTicket().MaxTimes(1) 2307 cryptoSetup.EXPECT().SetHandshakeConfirmed().MaxTimes(1) 2308 close(sess.handshakeCompleteChan) 2309 err := sess.run() 2310 nerr, ok := err.(net.Error) 2311 Expect(ok).To(BeTrue()) 2312 Expect(nerr.Timeout()).To(BeTrue()) 2313 Expect(err).To(MatchError(qerr.ErrIdleTimeout)) 2314 close(done) 2315 }() 2316 Eventually(done).Should(BeClosed()) 2317 }) 2318 2319 It("doesn't time out when it just sent a packet", func() { 2320 sess.lastPacketReceivedTime = time.Now().Add(-time.Hour) 2321 sess.firstAckElicitingPacketAfterIdleSentTime = time.Now().Add(-time.Second) 2322 sess.idleTimeout = 30 * time.Second 2323 go func() { 2324 defer GinkgoRecover() 2325 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 2326 sess.run() 2327 }() 2328 Consistently(sess.Context().Done()).ShouldNot(BeClosed()) 2329 // make the go routine return 2330 packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 2331 expectReplaceWithClosed() 2332 cryptoSetup.EXPECT().Close() 2333 mconn.EXPECT().Write(gomock.Any()) 2334 tracer.EXPECT().ClosedConnection(gomock.Any()) 2335 tracer.EXPECT().Close() 2336 sess.shutdown() 2337 Eventually(sess.Context().Done()).Should(BeClosed()) 2338 }) 2339 }) 2340 2341 It("stores up to MaxSessionUnprocessedPackets packets", func() { 2342 done := make(chan struct{}) 2343 tracer.EXPECT().DroppedPacket(logging.PacketTypeNotDetermined, logging.ByteCount(6), logging.PacketDropDOSPrevention).Do(func(logging.PacketType, logging.ByteCount, logging.PacketDropReason) { 2344 close(done) 2345 }) 2346 // Nothing here should block 2347 for i := protocol.PacketNumber(0); i < protocol.MaxSessionUnprocessedPackets+1; i++ { 2348 sess.handlePacket(&receivedPacket{data: []byte("foobar")}) 2349 } 2350 Eventually(done).Should(BeClosed()) 2351 }) 2352 2353 Context("getting streams", func() { 2354 It("opens streams", func() { 2355 mstr := NewMockStreamI(mockCtrl) 2356 streamManager.EXPECT().OpenStream().Return(mstr, nil) 2357 str, err := sess.OpenStream() 2358 Expect(err).ToNot(HaveOccurred()) 2359 Expect(str).To(Equal(mstr)) 2360 }) 2361 2362 It("opens streams synchronously", func() { 2363 mstr := NewMockStreamI(mockCtrl) 2364 streamManager.EXPECT().OpenStreamSync(context.Background()).Return(mstr, nil) 2365 str, err := sess.OpenStreamSync(context.Background()) 2366 Expect(err).ToNot(HaveOccurred()) 2367 Expect(str).To(Equal(mstr)) 2368 }) 2369 2370 It("opens unidirectional streams", func() { 2371 mstr := NewMockSendStreamI(mockCtrl) 2372 streamManager.EXPECT().OpenUniStream().Return(mstr, nil) 2373 str, err := sess.OpenUniStream() 2374 Expect(err).ToNot(HaveOccurred()) 2375 Expect(str).To(Equal(mstr)) 2376 }) 2377 2378 It("opens unidirectional streams synchronously", func() { 2379 mstr := NewMockSendStreamI(mockCtrl) 2380 streamManager.EXPECT().OpenUniStreamSync(context.Background()).Return(mstr, nil) 2381 str, err := sess.OpenUniStreamSync(context.Background()) 2382 Expect(err).ToNot(HaveOccurred()) 2383 Expect(str).To(Equal(mstr)) 2384 }) 2385 2386 It("accepts streams", func() { 2387 ctx, cancel := context.WithTimeout(context.Background(), time.Minute) 2388 defer cancel() 2389 mstr := NewMockStreamI(mockCtrl) 2390 streamManager.EXPECT().AcceptStream(ctx).Return(mstr, nil) 2391 str, err := sess.AcceptStream(ctx) 2392 Expect(err).ToNot(HaveOccurred()) 2393 Expect(str).To(Equal(mstr)) 2394 }) 2395 2396 It("accepts unidirectional streams", func() { 2397 ctx, cancel := context.WithTimeout(context.Background(), time.Second) 2398 defer cancel() 2399 mstr := NewMockReceiveStreamI(mockCtrl) 2400 streamManager.EXPECT().AcceptUniStream(ctx).Return(mstr, nil) 2401 str, err := sess.AcceptUniStream(ctx) 2402 Expect(err).ToNot(HaveOccurred()) 2403 Expect(str).To(Equal(mstr)) 2404 }) 2405 }) 2406 2407 It("returns the local address", func() { 2408 Expect(sess.LocalAddr()).To(Equal(localAddr)) 2409 }) 2410 2411 It("returns the remote address", func() { 2412 Expect(sess.RemoteAddr()).To(Equal(remoteAddr)) 2413 }) 2414}) 2415 2416var _ = Describe("Client Session", func() { 2417 var ( 2418 sess *session 2419 sessionRunner *MockSessionRunner 2420 packer *MockPacker 2421 mconn *MockSendConn 2422 cryptoSetup *mocks.MockCryptoSetup 2423 tracer *mocklogging.MockConnectionTracer 2424 tlsConf *tls.Config 2425 quicConf *Config 2426 ) 2427 srcConnID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8} 2428 destConnID := protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1} 2429 2430 getPacket := func(hdr *wire.ExtendedHeader, data []byte) *receivedPacket { 2431 buf := &bytes.Buffer{} 2432 Expect(hdr.Write(buf, sess.version)).To(Succeed()) 2433 return &receivedPacket{ 2434 data: append(buf.Bytes(), data...), 2435 buffer: getPacketBuffer(), 2436 } 2437 } 2438 2439 expectReplaceWithClosed := func() { 2440 sessionRunner.EXPECT().ReplaceWithClosed(srcConnID, gomock.Any()).Do(func(_ protocol.ConnectionID, s packetHandler) { 2441 s.shutdown() 2442 Eventually(areClosedSessionsRunning).Should(BeFalse()) 2443 }) 2444 } 2445 2446 BeforeEach(func() { 2447 quicConf = populateClientConfig(&Config{}, true) 2448 tlsConf = nil 2449 }) 2450 2451 JustBeforeEach(func() { 2452 Eventually(areSessionsRunning).Should(BeFalse()) 2453 2454 mconn = NewMockSendConn(mockCtrl) 2455 mconn.EXPECT().RemoteAddr().Return(&net.UDPAddr{}).AnyTimes() 2456 mconn.EXPECT().LocalAddr().Return(&net.UDPAddr{}).AnyTimes() 2457 if tlsConf == nil { 2458 tlsConf = &tls.Config{} 2459 } 2460 sessionRunner = NewMockSessionRunner(mockCtrl) 2461 tracer = mocklogging.NewMockConnectionTracer(mockCtrl) 2462 tracer.EXPECT().NegotiatedVersion(gomock.Any(), gomock.Any(), gomock.Any()).MaxTimes(1) 2463 tracer.EXPECT().SentTransportParameters(gomock.Any()) 2464 tracer.EXPECT().UpdatedKeyFromTLS(gomock.Any(), gomock.Any()).AnyTimes() 2465 tracer.EXPECT().UpdatedCongestionState(gomock.Any()) 2466 sess = newClientSession( 2467 mconn, 2468 sessionRunner, 2469 destConnID, 2470 protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}, 2471 quicConf, 2472 tlsConf, 2473 42, // initial packet number 2474 false, 2475 false, 2476 tracer, 2477 1234, 2478 utils.DefaultLogger, 2479 protocol.VersionTLS, 2480 ).(*session) 2481 packer = NewMockPacker(mockCtrl) 2482 sess.packer = packer 2483 cryptoSetup = mocks.NewMockCryptoSetup(mockCtrl) 2484 sess.cryptoStreamHandler = cryptoSetup 2485 }) 2486 2487 It("changes the connection ID when receiving the first packet from the server", func() { 2488 unpacker := NewMockUnpacker(mockCtrl) 2489 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(hdr *wire.Header, _ time.Time, data []byte) (*unpackedPacket, error) { 2490 return &unpackedPacket{ 2491 encryptionLevel: protocol.Encryption1RTT, 2492 hdr: &wire.ExtendedHeader{Header: *hdr}, 2493 data: []byte{0}, // one PADDING frame 2494 }, nil 2495 }) 2496 sess.unpacker = unpacker 2497 go func() { 2498 defer GinkgoRecover() 2499 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 2500 sess.run() 2501 }() 2502 newConnID := protocol.ConnectionID{1, 3, 3, 7, 1, 3, 3, 7} 2503 p := getPacket(&wire.ExtendedHeader{ 2504 Header: wire.Header{ 2505 IsLongHeader: true, 2506 Type: protocol.PacketTypeHandshake, 2507 SrcConnectionID: newConnID, 2508 DestConnectionID: srcConnID, 2509 Length: 2 + 6, 2510 Version: sess.version, 2511 }, 2512 PacketNumberLen: protocol.PacketNumberLen2, 2513 }, []byte("foobar")) 2514 tracer.EXPECT().ReceivedPacket(gomock.Any(), p.Size(), []logging.Frame{}) 2515 Expect(sess.handlePacketImpl(p)).To(BeTrue()) 2516 // make sure the go routine returns 2517 packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil) 2518 expectReplaceWithClosed() 2519 cryptoSetup.EXPECT().Close() 2520 mconn.EXPECT().Write(gomock.Any()) 2521 tracer.EXPECT().ClosedConnection(gomock.Any()) 2522 tracer.EXPECT().Close() 2523 sess.shutdown() 2524 Eventually(sess.Context().Done()).Should(BeClosed()) 2525 }) 2526 2527 It("continues accepting Long Header packets after using a new connection ID", func() { 2528 unpacker := NewMockUnpacker(mockCtrl) 2529 sess.unpacker = unpacker 2530 sessionRunner.EXPECT().AddResetToken(gomock.Any(), gomock.Any()) 2531 sess.connIDManager.SetHandshakeComplete() 2532 sess.handleNewConnectionIDFrame(&wire.NewConnectionIDFrame{ 2533 SequenceNumber: 1, 2534 ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5}, 2535 }) 2536 Expect(sess.connIDManager.Get()).To(Equal(protocol.ConnectionID{1, 2, 3, 4, 5})) 2537 // now receive a packet with the original source connection ID 2538 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(hdr *wire.Header, _ time.Time, _ []byte) (*unpackedPacket, error) { 2539 return &unpackedPacket{ 2540 hdr: &wire.ExtendedHeader{Header: *hdr}, 2541 data: []byte{0}, 2542 encryptionLevel: protocol.EncryptionHandshake, 2543 }, nil 2544 }) 2545 hdr := &wire.Header{ 2546 IsLongHeader: true, 2547 Type: protocol.PacketTypeHandshake, 2548 DestConnectionID: srcConnID, 2549 SrcConnectionID: destConnID, 2550 } 2551 tracer.EXPECT().ReceivedPacket(gomock.Any(), gomock.Any(), gomock.Any()) 2552 Expect(sess.handleSinglePacket(&receivedPacket{buffer: getPacketBuffer()}, hdr)).To(BeTrue()) 2553 }) 2554 2555 It("handles HANDSHAKE_DONE frames", func() { 2556 sess.peerParams = &wire.TransportParameters{} 2557 sph := mockackhandler.NewMockSentPacketHandler(mockCtrl) 2558 sess.sentPacketHandler = sph 2559 sph.EXPECT().SetHandshakeConfirmed() 2560 cryptoSetup.EXPECT().SetHandshakeConfirmed() 2561 Expect(sess.handleHandshakeDoneFrame()).To(Succeed()) 2562 }) 2563 2564 It("interprets an ACK for 1-RTT packets as confirmation of the handshake", func() { 2565 sess.peerParams = &wire.TransportParameters{} 2566 sph := mockackhandler.NewMockSentPacketHandler(mockCtrl) 2567 sess.sentPacketHandler = sph 2568 ack := &wire.AckFrame{AckRanges: []wire.AckRange{{Smallest: 1, Largest: 3}}} 2569 sph.EXPECT().ReceivedAck(ack, protocol.Encryption1RTT, gomock.Any()).Return(true, nil) 2570 sph.EXPECT().SetHandshakeConfirmed() 2571 cryptoSetup.EXPECT().SetLargest1RTTAcked(protocol.PacketNumber(3)) 2572 cryptoSetup.EXPECT().SetHandshakeConfirmed() 2573 Expect(sess.handleAckFrame(ack, protocol.Encryption1RTT)).To(Succeed()) 2574 }) 2575 2576 Context("handling tokens", func() { 2577 var mockTokenStore *MockTokenStore 2578 2579 BeforeEach(func() { 2580 mockTokenStore = NewMockTokenStore(mockCtrl) 2581 tlsConf = &tls.Config{ServerName: "server"} 2582 quicConf.TokenStore = mockTokenStore 2583 mockTokenStore.EXPECT().Pop(gomock.Any()) 2584 quicConf.TokenStore = mockTokenStore 2585 }) 2586 2587 It("handles NEW_TOKEN frames", func() { 2588 mockTokenStore.EXPECT().Put("server", &ClientToken{data: []byte("foobar")}) 2589 Expect(sess.handleNewTokenFrame(&wire.NewTokenFrame{Token: []byte("foobar")})).To(Succeed()) 2590 }) 2591 }) 2592 2593 Context("handling Version Negotiation", func() { 2594 getVNP := func(versions ...protocol.VersionNumber) *receivedPacket { 2595 b, err := wire.ComposeVersionNegotiation(srcConnID, destConnID, versions) 2596 Expect(err).ToNot(HaveOccurred()) 2597 return &receivedPacket{ 2598 data: b, 2599 buffer: getPacketBuffer(), 2600 } 2601 } 2602 2603 It("closes and returns the right error", func() { 2604 sph := mockackhandler.NewMockSentPacketHandler(mockCtrl) 2605 sess.sentPacketHandler = sph 2606 sph.EXPECT().ReceivedBytes(gomock.Any()) 2607 sph.EXPECT().PeekPacketNumber(protocol.EncryptionInitial).Return(protocol.PacketNumber(128), protocol.PacketNumberLen4) 2608 sess.config.Versions = []protocol.VersionNumber{1234, 4321} 2609 errChan := make(chan error, 1) 2610 go func() { 2611 defer GinkgoRecover() 2612 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 2613 errChan <- sess.run() 2614 }() 2615 sessionRunner.EXPECT().Remove(srcConnID) 2616 tracer.EXPECT().ReceivedVersionNegotiationPacket(gomock.Any(), gomock.Any()).Do(func(hdr *wire.Header, versions []logging.VersionNumber) { 2617 Expect(hdr.Version).To(BeZero()) 2618 Expect(versions).To(And( 2619 ContainElement(protocol.VersionNumber(4321)), 2620 ContainElement(protocol.VersionNumber(1337)), 2621 )) 2622 }) 2623 cryptoSetup.EXPECT().Close() 2624 Expect(sess.handlePacketImpl(getVNP(4321, 1337))).To(BeFalse()) 2625 var err error 2626 Eventually(errChan).Should(Receive(&err)) 2627 Expect(err).To(HaveOccurred()) 2628 Expect(err).To(BeAssignableToTypeOf(&errCloseForRecreating{})) 2629 recreateErr := err.(*errCloseForRecreating) 2630 Expect(recreateErr.nextVersion).To(Equal(protocol.VersionNumber(4321))) 2631 Expect(recreateErr.nextPacketNumber).To(Equal(protocol.PacketNumber(128))) 2632 }) 2633 2634 It("it closes when no matching version is found", func() { 2635 errChan := make(chan error, 1) 2636 go func() { 2637 defer GinkgoRecover() 2638 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 2639 errChan <- sess.run() 2640 }() 2641 sessionRunner.EXPECT().Remove(srcConnID).MaxTimes(1) 2642 gomock.InOrder( 2643 tracer.EXPECT().ReceivedVersionNegotiationPacket(gomock.Any(), gomock.Any()), 2644 tracer.EXPECT().ClosedConnection(gomock.Any()).Do(func(e error) { 2645 var vnErr *VersionNegotiationError 2646 Expect(errors.As(e, &vnErr)).To(BeTrue()) 2647 Expect(vnErr.Theirs).To(ContainElement(logging.VersionNumber(12345678))) 2648 }), 2649 tracer.EXPECT().Close(), 2650 ) 2651 cryptoSetup.EXPECT().Close() 2652 Expect(sess.handlePacketImpl(getVNP(12345678))).To(BeFalse()) 2653 var err error 2654 Eventually(errChan).Should(Receive(&err)) 2655 Expect(err).To(HaveOccurred()) 2656 Expect(err).ToNot(BeAssignableToTypeOf(errCloseForRecreating{})) 2657 Expect(err.Error()).To(ContainSubstring("no compatible QUIC version found")) 2658 }) 2659 2660 It("ignores Version Negotiation packets that offer the current version", func() { 2661 p := getVNP(sess.version) 2662 tracer.EXPECT().DroppedPacket(logging.PacketTypeVersionNegotiation, p.Size(), logging.PacketDropUnexpectedVersion) 2663 Expect(sess.handlePacketImpl(p)).To(BeFalse()) 2664 }) 2665 2666 It("ignores unparseable Version Negotiation packets", func() { 2667 p := getVNP(sess.version) 2668 p.data = p.data[:len(p.data)-2] 2669 tracer.EXPECT().DroppedPacket(logging.PacketTypeVersionNegotiation, p.Size(), logging.PacketDropHeaderParseError) 2670 Expect(sess.handlePacketImpl(p)).To(BeFalse()) 2671 }) 2672 }) 2673 2674 Context("handling Retry", func() { 2675 origDestConnID := protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1} 2676 2677 var retryHdr *wire.ExtendedHeader 2678 2679 JustBeforeEach(func() { 2680 retryHdr = &wire.ExtendedHeader{ 2681 Header: wire.Header{ 2682 IsLongHeader: true, 2683 Type: protocol.PacketTypeRetry, 2684 SrcConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef}, 2685 DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}, 2686 Token: []byte("foobar"), 2687 Version: sess.version, 2688 }, 2689 } 2690 }) 2691 2692 getRetryTag := func(hdr *wire.ExtendedHeader) []byte { 2693 buf := &bytes.Buffer{} 2694 hdr.Write(buf, sess.version) 2695 return handshake.GetRetryIntegrityTag(buf.Bytes(), origDestConnID, hdr.Version)[:] 2696 } 2697 2698 It("handles Retry packets", func() { 2699 sph := mockackhandler.NewMockSentPacketHandler(mockCtrl) 2700 sess.sentPacketHandler = sph 2701 sph.EXPECT().ResetForRetry() 2702 sph.EXPECT().ReceivedBytes(gomock.Any()) 2703 cryptoSetup.EXPECT().ChangeConnectionID(protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef}) 2704 packer.EXPECT().SetToken([]byte("foobar")) 2705 tracer.EXPECT().ReceivedRetry(gomock.Any()).Do(func(hdr *wire.Header) { 2706 Expect(hdr.DestConnectionID).To(Equal(retryHdr.DestConnectionID)) 2707 Expect(hdr.SrcConnectionID).To(Equal(retryHdr.SrcConnectionID)) 2708 Expect(hdr.Token).To(Equal(retryHdr.Token)) 2709 }) 2710 Expect(sess.handlePacketImpl(getPacket(retryHdr, getRetryTag(retryHdr)))).To(BeTrue()) 2711 }) 2712 2713 It("ignores Retry packets after receiving a regular packet", func() { 2714 sess.receivedFirstPacket = true 2715 p := getPacket(retryHdr, getRetryTag(retryHdr)) 2716 tracer.EXPECT().DroppedPacket(logging.PacketTypeRetry, p.Size(), logging.PacketDropUnexpectedPacket) 2717 Expect(sess.handlePacketImpl(p)).To(BeFalse()) 2718 }) 2719 2720 It("ignores Retry packets if the server didn't change the connection ID", func() { 2721 retryHdr.SrcConnectionID = destConnID 2722 p := getPacket(retryHdr, getRetryTag(retryHdr)) 2723 tracer.EXPECT().DroppedPacket(logging.PacketTypeRetry, p.Size(), logging.PacketDropUnexpectedPacket) 2724 Expect(sess.handlePacketImpl(p)).To(BeFalse()) 2725 }) 2726 2727 It("ignores Retry packets with the a wrong Integrity tag", func() { 2728 tag := getRetryTag(retryHdr) 2729 tag[0]++ 2730 p := getPacket(retryHdr, tag) 2731 tracer.EXPECT().DroppedPacket(logging.PacketTypeRetry, p.Size(), logging.PacketDropPayloadDecryptError) 2732 Expect(sess.handlePacketImpl(p)).To(BeFalse()) 2733 }) 2734 }) 2735 2736 Context("transport parameters", func() { 2737 var ( 2738 closed bool 2739 errChan chan error 2740 ) 2741 2742 JustBeforeEach(func() { 2743 errChan = make(chan error, 1) 2744 closed = false 2745 go func() { 2746 defer GinkgoRecover() 2747 cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) 2748 errChan <- sess.run() 2749 close(errChan) 2750 }() 2751 }) 2752 2753 expectClose := func(applicationClose bool) { 2754 if !closed { 2755 sessionRunner.EXPECT().ReplaceWithClosed(gomock.Any(), gomock.Any()).Do(func(_ protocol.ConnectionID, s packetHandler) { 2756 Expect(s).To(BeAssignableToTypeOf(&closedLocalSession{})) 2757 s.shutdown() 2758 }) 2759 if applicationClose { 2760 packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil).MaxTimes(1) 2761 } else { 2762 packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil).MaxTimes(1) 2763 } 2764 cryptoSetup.EXPECT().Close() 2765 mconn.EXPECT().Write(gomock.Any()) 2766 gomock.InOrder( 2767 tracer.EXPECT().ClosedConnection(gomock.Any()), 2768 tracer.EXPECT().Close(), 2769 ) 2770 } 2771 closed = true 2772 } 2773 2774 AfterEach(func() { 2775 sess.shutdown() 2776 Eventually(sess.Context().Done()).Should(BeClosed()) 2777 Eventually(errChan).Should(BeClosed()) 2778 }) 2779 2780 It("uses the preferred_address connection ID", func() { 2781 params := &wire.TransportParameters{ 2782 OriginalDestinationConnectionID: destConnID, 2783 InitialSourceConnectionID: destConnID, 2784 PreferredAddress: &wire.PreferredAddress{ 2785 IPv4: net.IPv4(127, 0, 0, 1), 2786 IPv6: net.IP{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, 2787 ConnectionID: protocol.ConnectionID{1, 2, 3, 4}, 2788 StatelessResetToken: protocol.StatelessResetToken{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, 2789 }, 2790 } 2791 packer.EXPECT().HandleTransportParameters(gomock.Any()) 2792 packer.EXPECT().PackCoalescedPacket().MaxTimes(1) 2793 tracer.EXPECT().ReceivedTransportParameters(params) 2794 sess.handleTransportParameters(params) 2795 sess.handleHandshakeComplete() 2796 // make sure the connection ID is not retired 2797 cf, _ := sess.framer.AppendControlFrames(nil, protocol.MaxByteCount) 2798 Expect(cf).To(BeEmpty()) 2799 sessionRunner.EXPECT().AddResetToken(protocol.StatelessResetToken{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, sess) 2800 Expect(sess.connIDManager.Get()).To(Equal(protocol.ConnectionID{1, 2, 3, 4})) 2801 // shut down 2802 sessionRunner.EXPECT().RemoveResetToken(protocol.StatelessResetToken{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}) 2803 expectClose(true) 2804 }) 2805 2806 It("uses the minimum of the peers' idle timeouts", func() { 2807 sess.config.MaxIdleTimeout = 19 * time.Second 2808 params := &wire.TransportParameters{ 2809 OriginalDestinationConnectionID: destConnID, 2810 InitialSourceConnectionID: destConnID, 2811 MaxIdleTimeout: 18 * time.Second, 2812 } 2813 packer.EXPECT().HandleTransportParameters(gomock.Any()) 2814 tracer.EXPECT().ReceivedTransportParameters(params) 2815 sess.handleTransportParameters(params) 2816 sess.handleHandshakeComplete() 2817 Expect(sess.idleTimeout).To(Equal(18 * time.Second)) 2818 expectClose(true) 2819 }) 2820 2821 It("errors if the transport parameters contain a wrong initial_source_connection_id", func() { 2822 sess.handshakeDestConnID = protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef} 2823 params := &wire.TransportParameters{ 2824 OriginalDestinationConnectionID: destConnID, 2825 InitialSourceConnectionID: protocol.ConnectionID{0xde, 0xca, 0xfb, 0xad}, 2826 StatelessResetToken: &protocol.StatelessResetToken{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, 2827 } 2828 expectClose(false) 2829 tracer.EXPECT().ReceivedTransportParameters(params) 2830 sess.handleTransportParameters(params) 2831 Eventually(errChan).Should(Receive(MatchError(&qerr.TransportError{ 2832 ErrorCode: qerr.TransportParameterError, 2833 ErrorMessage: "expected initial_source_connection_id to equal deadbeef, is decafbad", 2834 }))) 2835 }) 2836 2837 It("errors if the transport parameters don't contain the retry_source_connection_id, if a Retry was performed", func() { 2838 sess.retrySrcConnID = &protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef} 2839 params := &wire.TransportParameters{ 2840 OriginalDestinationConnectionID: destConnID, 2841 InitialSourceConnectionID: destConnID, 2842 StatelessResetToken: &protocol.StatelessResetToken{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, 2843 } 2844 expectClose(false) 2845 tracer.EXPECT().ReceivedTransportParameters(params) 2846 sess.handleTransportParameters(params) 2847 Eventually(errChan).Should(Receive(MatchError(&qerr.TransportError{ 2848 ErrorCode: qerr.TransportParameterError, 2849 ErrorMessage: "missing retry_source_connection_id", 2850 }))) 2851 }) 2852 2853 It("errors if the transport parameters contain the wrong retry_source_connection_id, if a Retry was performed", func() { 2854 sess.retrySrcConnID = &protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef} 2855 params := &wire.TransportParameters{ 2856 OriginalDestinationConnectionID: destConnID, 2857 InitialSourceConnectionID: destConnID, 2858 RetrySourceConnectionID: &protocol.ConnectionID{0xde, 0xad, 0xc0, 0xde}, 2859 StatelessResetToken: &protocol.StatelessResetToken{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, 2860 } 2861 expectClose(false) 2862 tracer.EXPECT().ReceivedTransportParameters(params) 2863 sess.handleTransportParameters(params) 2864 Eventually(errChan).Should(Receive(MatchError(&qerr.TransportError{ 2865 ErrorCode: qerr.TransportParameterError, 2866 ErrorMessage: "expected retry_source_connection_id to equal deadbeef, is deadc0de", 2867 }))) 2868 }) 2869 2870 It("errors if the transport parameters contain the retry_source_connection_id, if no Retry was performed", func() { 2871 params := &wire.TransportParameters{ 2872 OriginalDestinationConnectionID: destConnID, 2873 InitialSourceConnectionID: destConnID, 2874 RetrySourceConnectionID: &protocol.ConnectionID{0xde, 0xad, 0xc0, 0xde}, 2875 StatelessResetToken: &protocol.StatelessResetToken{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, 2876 } 2877 expectClose(false) 2878 tracer.EXPECT().ReceivedTransportParameters(params) 2879 sess.handleTransportParameters(params) 2880 Eventually(errChan).Should(Receive(MatchError(&qerr.TransportError{ 2881 ErrorCode: qerr.TransportParameterError, 2882 ErrorMessage: "received retry_source_connection_id, although no Retry was performed", 2883 }))) 2884 }) 2885 2886 It("errors if the transport parameters contain a wrong original_destination_connection_id", func() { 2887 sess.origDestConnID = protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef} 2888 params := &wire.TransportParameters{ 2889 OriginalDestinationConnectionID: protocol.ConnectionID{0xde, 0xca, 0xfb, 0xad}, 2890 InitialSourceConnectionID: sess.handshakeDestConnID, 2891 StatelessResetToken: &protocol.StatelessResetToken{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, 2892 } 2893 expectClose(false) 2894 tracer.EXPECT().ReceivedTransportParameters(params) 2895 sess.handleTransportParameters(params) 2896 Eventually(errChan).Should(Receive(MatchError(&qerr.TransportError{ 2897 ErrorCode: qerr.TransportParameterError, 2898 ErrorMessage: "expected original_destination_connection_id to equal deadbeef, is decafbad", 2899 }))) 2900 }) 2901 }) 2902 2903 Context("handling potentially injected packets", func() { 2904 var unpacker *MockUnpacker 2905 2906 getPacket := func(extHdr *wire.ExtendedHeader, data []byte) *receivedPacket { 2907 buf := &bytes.Buffer{} 2908 Expect(extHdr.Write(buf, sess.version)).To(Succeed()) 2909 return &receivedPacket{ 2910 data: append(buf.Bytes(), data...), 2911 buffer: getPacketBuffer(), 2912 } 2913 } 2914 2915 // Convert an already packed raw packet into a receivedPacket 2916 wrapPacket := func(packet []byte) *receivedPacket { 2917 return &receivedPacket{ 2918 data: packet, 2919 buffer: getPacketBuffer(), 2920 } 2921 } 2922 2923 // Illustrates that attacker may inject an Initial packet with a different 2924 // source connection ID, causing endpoint to ignore a subsequent real Initial packets. 2925 It("ignores Initial packets with a different source connection ID", func() { 2926 // Modified from test "ignores packets with a different source connection ID" 2927 unpacker = NewMockUnpacker(mockCtrl) 2928 sess.unpacker = unpacker 2929 2930 hdr1 := &wire.ExtendedHeader{ 2931 Header: wire.Header{ 2932 IsLongHeader: true, 2933 Type: protocol.PacketTypeInitial, 2934 DestConnectionID: destConnID, 2935 SrcConnectionID: srcConnID, 2936 Length: 1, 2937 Version: sess.version, 2938 }, 2939 PacketNumberLen: protocol.PacketNumberLen1, 2940 PacketNumber: 1, 2941 } 2942 hdr2 := &wire.ExtendedHeader{ 2943 Header: wire.Header{ 2944 IsLongHeader: true, 2945 Type: protocol.PacketTypeInitial, 2946 DestConnectionID: destConnID, 2947 SrcConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef}, 2948 Length: 1, 2949 Version: sess.version, 2950 }, 2951 PacketNumberLen: protocol.PacketNumberLen1, 2952 PacketNumber: 2, 2953 } 2954 Expect(hdr2.SrcConnectionID).ToNot(Equal(srcConnID)) 2955 // Send one packet, which might change the connection ID. 2956 // only EXPECT one call to the unpacker 2957 unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(&unpackedPacket{ 2958 encryptionLevel: protocol.EncryptionInitial, 2959 hdr: hdr1, 2960 data: []byte{0}, // one PADDING frame 2961 }, nil) 2962 tracer.EXPECT().ReceivedPacket(gomock.Any(), gomock.Any(), gomock.Any()) 2963 Expect(sess.handlePacketImpl(getPacket(hdr1, nil))).To(BeTrue()) 2964 // The next packet has to be ignored, since the source connection ID doesn't match. 2965 tracer.EXPECT().DroppedPacket(gomock.Any(), gomock.Any(), gomock.Any()) 2966 Expect(sess.handlePacketImpl(getPacket(hdr2, nil))).To(BeFalse()) 2967 }) 2968 2969 It("ignores 0-RTT packets", func() { 2970 p := getPacket(&wire.ExtendedHeader{ 2971 Header: wire.Header{ 2972 IsLongHeader: true, 2973 Type: protocol.PacketType0RTT, 2974 DestConnectionID: srcConnID, 2975 Length: 2 + 6, 2976 Version: sess.version, 2977 }, 2978 PacketNumber: 0x42, 2979 PacketNumberLen: protocol.PacketNumberLen2, 2980 }, []byte("foobar")) 2981 tracer.EXPECT().DroppedPacket(logging.PacketType0RTT, p.Size(), gomock.Any()) 2982 Expect(sess.handlePacketImpl(p)).To(BeFalse()) 2983 }) 2984 2985 // Illustrates that an injected Initial with an ACK frame for an unsent packet causes 2986 // the connection to immediately break down 2987 It("fails on Initial-level ACK for unsent packet", func() { 2988 ack := &wire.AckFrame{AckRanges: []wire.AckRange{{Smallest: 2, Largest: 2}}} 2989 initialPacket := testutils.ComposeInitialPacket(destConnID, srcConnID, sess.version, destConnID, []wire.Frame{ack}) 2990 tracer.EXPECT().ReceivedPacket(gomock.Any(), gomock.Any(), gomock.Any()) 2991 Expect(sess.handlePacketImpl(wrapPacket(initialPacket))).To(BeFalse()) 2992 }) 2993 2994 // Illustrates that an injected Initial with a CONNECTION_CLOSE frame causes 2995 // the connection to immediately break down 2996 It("fails on Initial-level CONNECTION_CLOSE frame", func() { 2997 connCloseFrame := &wire.ConnectionCloseFrame{ 2998 IsApplicationError: true, 2999 ReasonPhrase: "mitm attacker", 3000 } 3001 initialPacket := testutils.ComposeInitialPacket(destConnID, srcConnID, sess.version, destConnID, []wire.Frame{connCloseFrame}) 3002 tracer.EXPECT().ReceivedPacket(gomock.Any(), gomock.Any(), gomock.Any()) 3003 Expect(sess.handlePacketImpl(wrapPacket(initialPacket))).To(BeTrue()) 3004 }) 3005 3006 // Illustrates that attacker who injects a Retry packet and changes the connection ID 3007 // can cause subsequent real Initial packets to be ignored 3008 It("ignores Initial packets which use original source id, after accepting a Retry", func() { 3009 sph := mockackhandler.NewMockSentPacketHandler(mockCtrl) 3010 sess.sentPacketHandler = sph 3011 sph.EXPECT().ReceivedBytes(gomock.Any()).Times(2) 3012 sph.EXPECT().ResetForRetry() 3013 newSrcConnID := protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef} 3014 cryptoSetup.EXPECT().ChangeConnectionID(newSrcConnID) 3015 packer.EXPECT().SetToken([]byte("foobar")) 3016 3017 tracer.EXPECT().ReceivedRetry(gomock.Any()) 3018 sess.handlePacketImpl(wrapPacket(testutils.ComposeRetryPacket(newSrcConnID, destConnID, destConnID, []byte("foobar"), sess.version))) 3019 initialPacket := testutils.ComposeInitialPacket(sess.connIDManager.Get(), srcConnID, sess.version, sess.connIDManager.Get(), nil) 3020 tracer.EXPECT().DroppedPacket(gomock.Any(), gomock.Any(), gomock.Any()) 3021 Expect(sess.handlePacketImpl(wrapPacket(initialPacket))).To(BeFalse()) 3022 }) 3023 }) 3024}) 3025