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