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