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