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