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