1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-11-10 21:22:20 +03:00
Commit Graph

96 Commits

Author SHA1 Message Date
Brandon Schlinker
925472bdfc Store weak_ptr to SocketObserverContainer in ConnectionStateBase
Summary:
This diff changes `QuicConnectionStateBase` so that it stores a `std::weak_ptr<SocketObserverContainer>` instead of a `std::shared_ptr<SocketObserverContainer>`.

- `QuicConnectionStateBase` needs a pointer to the `SocketObserverContainer` so that loss / ACK / other processing logic can access the observer container and send the observers notifications. There may not be a `SocketObserverContainer` if the `QuicTransportBase` implementation does not support it.
- A `SocketObserverContainer` must not outlive the instance of the `QuicTransportBase` implementation that it is associated with. This is because observers are notified that the object being observed has been destroyed when the container is destroyed, and thus if the container outlives the lifetime of the transport, then the observers will think the transport is still alive when it is in fact dead.
- By storing a weak pointer to the `SocketObserverContainer` in the `QuicConnectionStateBase`, we provide access to the observer container without extending its lifetime. In parallel, because it is a managed pointer, we avoid the possibility of dereferencing a stale pointer (e.g., a pointer pointing to an object that has since been destroyed).

Reviewed By: mjoras

Differential Revision: D42856161

fbshipit-source-id: f35558a21fea91ba794adcf9b573dd48a626ea1f
2023-01-30 22:45:59 -08:00
Konstantin Tsoy
424ab5c8c1 Remove useless func argument
Summary: Remove useless func argument

Reviewed By: jbeshay

Differential Revision: D42647239

fbshipit-source-id: d27b26391971ca31f8bf727e3648d1a0dbf124be
2023-01-24 14:53:27 -08:00
Brandon Schlinker
5b8e0de5bd Improve transport close handling and observability
Summary:
The current `close` observer event marks when `closeImpl` is called. However, the actual close of the socket may be delayed for some time while the socket drains. I've changed the existing event to `closeStarted` and added a new event `closing` that marks the close of the underlying `AsyncUDPSocket`.

Adding the `closeStarted` event required two other changes which are difficult to separate from this diff:
- When a transport is destroyed, `QuicTransportBase` was calling `closeImpl` and also closing the UDP socket. However, because the `folly::ObserverContainer` used to store observers is maintained in classes that derive from `QuicTransportBase`, the observers are gone by the time the UDP socket is closed in the base class destructor. Thus, the UDP socket should be closed by the derived classes in their respective destructors. This requirement is inline with the existing code: `closeImpl` is called by all derived classes in their destructors. Made this change and added `DCHECK` statements in the `QuicTransportBase` destructor to ensure that derived classes cleanup after themselves.
- Writing tests with draining enabled and disabled required being able to set the transport settings. However, all of the existing `QuicTypedTransportTest` test cases were designed to operate after the connection was accepted (for the server impls) or established (for client impls), and transport settings cannot be updated at this state. Resolving this required adding new test classes in which the accept/connect operation is delayed until requested by the test.

Reviewed By: mjoras

Differential Revision: D39249604

fbshipit-source-id: 0ebf8b719c4d3b01d4f9509cf2b9a4fc72c2e737
2022-09-10 10:39:11 -07:00
Hani Damlaj
6208eca47f Synchronously Query Socket For Max Writable
Summary: - adding an API to the QuicSocket to enable users to synchronously query the socket for the maximum amount of data that should be written.

Reviewed By: mjoras

Differential Revision: D37390086

fbshipit-source-id: 5dd64e28b7f841ba3e28a4bc2a79c1b1e5a95047
2022-07-13 12:08:47 -07:00
Ashkan Nikravesh
8419469204 Create a PacketProcessor abstract class
Summary: PacketProcessors process the packets that we send and their corresponding ack and loss events. We store a vector of packet processors inside `QuicConnectionStateBase` and we call `onPacketSent` and `onPacketAck` whenever their corresponding functions in `CongestionController` class are called. The plan is to make `CongestionController` class extend `PacketProcessor`.

Reviewed By: bschlinker

Differential Revision: D36404668

fbshipit-source-id: 52d63a6a74bfa2031131d31047da25a5e2be12aa
2022-07-05 11:09:03 -07:00
Konstantin Tsoy
e208ceffdd Implement group streams receiver api in transport
Summary: Implement group streams receiver api in transport

Reviewed By: mjoras

Differential Revision: D36419901

fbshipit-source-id: 98bfefa1a4205fde8764f2e4300f51156667e024
2022-06-06 17:11:39 -07:00
Konstantin Tsoy
ad6a0e9cbb Implement group streams sender api in transport
Summary: Implement group streams api in transport

Reviewed By: mjoras

Differential Revision: D36417214

fbshipit-source-id: dee93807fe061f2abd9c779da9a2cd1df1865c3e
2022-06-03 15:47:17 -07:00
Konstantin Tsoy
80b9c6274e Stream groups API
Summary: Add stream groups interface

Reviewed By: mjoras

Differential Revision: D36416440

fbshipit-source-id: 4a757428c9f38f52e4c8d0feb2149d598a748904
2022-06-03 15:47:17 -07:00
Brandon Schlinker
744ae1f78e Use folly::ObserverContainer for socket observer [4/x]
Summary:
This diff is part of larger change to switch to using `folly::ObserverContainer` (introduced in D27062840).

This diff:
- Changes `LegacyObserver` to inherit from the new `Observer` class by adding a compatibility layer. This compatibility layer enables existing observers to continue to be supported.
- Changes generation of observer events so that they are routed through `ObserverContainer::invokeInterfaceMethod`
- Temporarily removes some of the reentrancy protection that previously existed, as it was not being applied consistently — some events had reentrancy protection, some did not. This will be reintroduced in the next diff.
- Improves some unit tests for observers during the transition process.

Differential Revision: D35268271

fbshipit-source-id: 5731c8a9aa8da8a2da1dd23d093e5f2e1a692653
2022-04-18 04:19:31 -07:00
Brandon Schlinker
f20eb76865 Use folly::ObserverContainer for socket observer [3/x]
Summary:
This diff is part of larger change to switch to using `folly::ObserverContainer` (introduced in D27062840).

This diff:
- Adds methods to `QuicSocket` to support adding and removing `ObserverContainer` observers. By default, `QuicSocket` implementations will not support observers as `QuicSocket::getSocketObserverContainer` returns `nullptr`, and this will cause `QuicSocket::addObserver` and `QuicSocket::removeObserver` to fail gracefully.
- Adds support in `QuicClientTransport` and `QuicServerTransport` for `ObserverContainer` observers by overriding `getSocketObserverContainer`. Each implementation creates an `ObserverContainer` on construction that is destroyed on destruction.
- Adds the `close` event to the new observer interface and adds corresponding support in `QuicTransportBase`. This allows both the old and new observers to receive the close event. The next diff will do a hard cutover of the rest of the events.

Differential Revision: D35000960

fbshipit-source-id: e75807c97f4385532bf36244591a259aa0a2f4cc
2022-04-18 04:19:31 -07:00
Brandon Schlinker
ea056eb960 Use folly::ObserverContainer for socket observer [2/x]
Summary:
This diff is part of larger change to switch to using `folly::ObserverContainer` (introduced in D27062840).

This diff:
- Renames `quic::Observer` to `quic::LegacyObserver`.
- Switches to using `quic::SocketObserverInterface` instead of `quic::Observer` when referencing structures used for the observer interface. For instance, `quic::Observer::WriteEvent` changes to `quic::SocketObserverInterface::WriteEvent`.

Differential Revision: D35000152

fbshipit-source-id: f387231fd58e8e763c3d7ed0a9c6fcec3b2324e2
2022-04-18 04:19:31 -07:00
Brandon Schlinker
b243d2bdd8 Number bytes written in packets written event
Summary: Report all bytes written in observer packets written events.

Reviewed By: jbeshay

Differential Revision: D33086404

fbshipit-source-id: 1456cf23a420abd025f047f190cb2b8a9868826e
2022-03-23 08:50:12 -07:00
Hani Damlaj
94cda41d85 FullHandshakeDone Callback
Summary:
```
buck test //quic/server/test:QuicServerTransportTest
```

Reviewed By: mjoras

Differential Revision: D34696930

fbshipit-source-id: df563fc00773df7acb9bea0bb02d26e99c1fb02f
2022-03-11 13:13:00 -08:00
Matt Joras
360c211738 Keepalive timer support
Summary:
This implements a basic keepalive timer at the transport layer.

The basic idea is to leverage the same conditions as the idle timer. The keepalive timer will fire ~15% before the idle timer and trigger a PING frame. This has the effect of keeping the connection open if the PING is acknowledged.

Reviewed By: jbeshay

Differential Revision: D34256174

fbshipit-source-id: a8cee579f5b09bdfa23bcdc7cf4c70de299de3bd
2022-02-24 12:40:01 -08:00
Konstantin Tsoy
a70ffbeb29 Rename ConnectionCallbackNew back to ConnectionCallback
Summary: Rename ConnectionCallbackNew back to ConnectionCallback

Reviewed By: mjoras

Differential Revision: D33979956

fbshipit-source-id: 6c133a406c4bf6799838ffc36701267a938cb4a3
2022-02-23 12:57:31 -08:00
Konstantin Tsoy
bd6e117a56 Add a helper function to set default error code for close() and
Summary:
Add a helper function to set default error code for close() and
closeNow()

Reviewed By: mjoras

Differential Revision: D34191863

fbshipit-source-id: 8f818f471307ea64ed046ec5e93852566247faa3
2022-02-22 14:24:23 -08:00
Konstantin Tsoy
2e468b5e5d Add new connection end cb option to client/server transport
Summary: Add new connection end cb option to client/server transport

Reviewed By: mjoras

Differential Revision: D34190871

fbshipit-source-id: 375cf95bc8dbe4ab759140cfb4b33b732869953f
2022-02-22 14:24:23 -08:00
Konstantin Tsoy
3b6f2cf2c0 Simplify callback invocation on connection end/error
Summary: Simplify callback invocation on connection end/error

Reviewed By: mjoras

Differential Revision: D34190297

fbshipit-source-id: d0a124d392a96cc7596bf7feb45ec35a7e27dbbf
2022-02-16 09:49:35 -08:00
Konstantin Tsoy
54ce32396c get rid of callbacks indirection layer
Summary: get rid of callbacks indirection layer

Reviewed By: mjoras

Differential Revision: D34189595

fbshipit-source-id: e4a0aba768b17054f06091c12ef66f1a8019885f
2022-02-15 11:45:09 -08:00
Konstantin Tsoy
3872f0dd89 Remove unused function
Summary: Remove unused function

Reviewed By: mjoras

Differential Revision: D34184684

fbshipit-source-id: cd254c64790ad8024484bf91e68db6a47e054ce2
2022-02-15 11:45:09 -08:00
Konstantin Tsoy
cecc1ba279 Introduce QuicError struct
Summary: Instead of using std::pair everywhere

Reviewed By: mjoras

Differential Revision: D34146686

fbshipit-source-id: dfe48f43775de868aba06a5b9b5a004e5793bdbb
2022-02-14 16:00:21 -08:00
Elijah Staple
b57802721e Add ReadDatagram struct and update readDatagrams callback
Summary: In order to provide more information about datagrams when we receive them, I'm adding a wrapper around the BufQueue that we currently hold so we can include receiveTimePoint and any other metadata we might want to expose for the Datagram API.

Reviewed By: mjoras

Differential Revision: D33994358

fbshipit-source-id: 805f182cd350908320639bc07eb6f3b7349bbc05
2022-02-10 16:47:06 -08:00
Konstantin Tsoy
dc79176a56 Deprecate old connection callback
Summary: Deprecate old connection callback

Reviewed By: jbeshay, lnicco

Differential Revision: D33695440

fbshipit-source-id: 043baa53b71453b5e2b9f60d890f1adcda7c65b5
2022-02-02 19:03:57 -08:00
Luca Niccolini
3898b5a9d3 QUIC/HTTP3: reset idle timeout on ping
Summary:
Adds a transport callback for ping received.
Uses the callback in the HTTP3 session to reset the timeout
Also now invokes the ping callbacks synchronously to avoid issues during connection shutdown

Reviewed By: mjoras

Differential Revision: D33753068

fbshipit-source-id: 99ac14d0e4b9539f3a20c5c55bb5241351bf1c57
2022-01-26 17:29:53 -08:00
Luca Niccolini
60ad67ffff Back out "QUIC/HTTP3: reset idle timeout on ping"
Summary:
Original commit changeset: d6fcecd22cbd

Original Phabricator Diff: D33101180 (15390c732a)

Reviewed By: afrind, kvtsoy

Differential Revision: D33743341

fbshipit-source-id: 3abf82db83125659a447f1c95330c85f21eed9b6
2022-01-24 08:52:37 -08:00
Luca Niccolini
15390c732a QUIC/HTTP3: reset idle timeout on ping
Summary:
Adds a transport callback for ping received.
Uses the callback in the HTTP3 session to reset the timeout

Reviewed By: mjoras

Differential Revision: D33101180

fbshipit-source-id: d6fcecd22cbd5c311674dd9421c0c54eb04728a0
2022-01-21 16:43:27 -08:00
Hani Damlaj
00e67c1bf9 mvfst License Header Update
Reviewed By: lnicco

Differential Revision: D33587012

fbshipit-source-id: 972eb440f0156c9c04aa6e8787561b18295c1a97
2022-01-18 13:56:12 -08:00
Hani Damlaj
2660a288b3 Update Company Name
Summary: - as title

Reviewed By: lnicco

Differential Revision: D33513410

fbshipit-source-id: 282b6f512cf83b9abb7990402661135b658f7bd1
2022-01-13 12:07:48 -08:00
Brandon Schlinker
c051ff1299 AcksProcessedEvent observer event
Summary:
Providers observers with insight into ACKs received. Works for both client and server transport.

Attempts to prevent wasted memory by removing any allocated memory for ACK events if no packets in flight. In tandem, reduces allocs by _not_ removing allocated memory when packets are in flight (as this means more ACK events will occur soon...).

Reviewed By: jbeshay

Differential Revision: D31221280

fbshipit-source-id: 64b73aa74c757ebbfc27bb9c2a047d08dc7a77ca
2021-12-08 08:16:28 -08:00
Brandon Schlinker
20c17a882b PacketsWrittenEvent observer event
Summary:
Currently the `packetsWritten` observer event is only triggered when ACK-eliciting packets are written to the network. This change makes it so that the event is triggered even when non ACK-eliciting packets are written. In addition, this change increases the information provided in the observer event to reduce the processing that must be performed by observers.

More specifically, this diff makes the following changes:
- It creates two new structs — `WriteEvent` and `PacketsWrittenEvent` — and makes `PacketsWrittenEvent` and `AppLimitedEvent` inherit from `WriteEvent`, which contains the base set of fields that appear in both derived events. The base set of fields includes `writeCount` and the reference to the list of `OutstandingPackets`.
- A `PacketsWrittenEvent` is generated after each write loop during which packets are written.
  - The `PacketsWrittenEvent` records the total number of packets written (the sum of ACK-eliciting and non ACK-eliciting packets written) and the total number of ACK-eliciting packets written during the last loop. By exposing this information, observers can determine whether there is value in inspecting the list of `OutstandingPackets` before doing so.
  - In the future, I'll extend this event to also report the number of stream bytes written.
- It adopts a new builder pattern for observer events to make it easier to create instances of these structures:
  - We use this approach instead of aggregate initialization (specifically designated initializers via aggregate initialization), because designated initializers (C++20 feature, although supported by some compilers long before) is not yet supported on all platforms for which we need this code to compile.
  - I intend to change the other observer events to use this pattern as the number of arguments in some of their constructors makes them increasingly difficult to deal with.

Reviewed By: mjoras

Differential Revision: D31216724

fbshipit-source-id: 42ceb922d46ab0e0dc356f8726c2d0467a219587
2021-12-03 11:17:14 -08:00
Brandon Schlinker
d89e8d344e Observer stream events
Summary: Provide observers with visibility into stream events triggered by local and peer (e.g., new stream opened locally or by peer).

Reviewed By: mjoras

Differential Revision: D31886978

fbshipit-source-id: 7556fef0f336bd0f190b4474f1a7b0120aae6ef1
2021-12-03 11:17:14 -08:00
Joseph Beshay
ea2af0fe10 Control a connections bandwidth utilization factor in QuicTransportBase (background mode)
Summary:
The StreamManager monitors can now have a reference to a new observer interface QuicStreamPrioritiesObserver. If the reference is set, the observer is notified whenever streams are created, removed, or change priorities

QuicTransportBase implements this observer interface. It uses the event notifications to control a connection's background mode based upon the new background mode parameters: priority level threshold, and target utilization factor. When these parameters are set, and all active streams have a priority lower than the threshold, the connection's congestion controller is set to use only the defined utilization factor of the available bandwidth.

Reviewed By: bschlinker

Differential Revision: D31562505

fbshipit-source-id: 9c74fa834301f745d97e851741b911795f756023
2021-10-22 14:52:29 -07:00
Konstantin Tsoy
41be39b61b Introduce split callbacks
Summary:
This diff introduces split callbacks to QUIC.
Old: callback:
* `ConnectionCallback`
Two new callbacks:
* `ConnectionSetupCallback`
* `ConnectionStreamsCallback`

For now the idea is that both old and new callbacks will live side by side and mvfst will decide which callbacks scheme to use via the `useSplitConnectionCallbacks` flag supplied on both QUIC client and server creation.

Reviewed By: mjoras

Differential Revision: D30407129

fbshipit-source-id: 7b726c2652ebe00b47f44bf291cffb9d9f6c884b
2021-09-11 17:38:51 -07:00
Konstantin Tsoy
29e560813b Connection callback indirection object
Summary:
This is another diff preparing mvfst for the new split callbacks.
This change introduces a callback dispatcher. Right now, it simply calls the existing monolithic callback everywhere. In future diffs, this dispatcher will be using the `useSplitCallbacks` flag to decide which callback object to call.

Reviewed By: mjoras

Differential Revision: D30404458

fbshipit-source-id: 5bb919185b845acc3e8ce7c596c0769b541ff69d
2021-08-31 18:27:40 -07:00
Konstantin Tsoy
72ca64176e processConnectionEndError() util func
Summary:
For the split QUIC callbacks, onConnectionError() will be present in both connection setup and normal connection callbacks.

This diff has no functional changes rather just separates the code that will change (in diffs higher up the stack) into a few functions for easiness.

Reviewed By: mjoras, lnicco

Differential Revision: D30400469

fbshipit-source-id: df259f201b74c51704e4284cbf94ad485f80a1ab
2021-08-31 18:27:40 -07:00
Konstantin Tsoy
21ea1990ab Add a useSplitConnectionCallbacks to mvfst
Summary:
This change just adds a (currently no-op) flag that will be used in diffs up the stack.

The idea here is that I'll add split QUIC connection callback interfaces that will live side by side with existing single monolithic callback for now. We will experiment with split callbacks on small scale to see that there is no regressions and then will phase out the old callback gradually.

This flag is to control which callback(s) to use.

Reviewed By: mjoras

Differential Revision: D30399667

fbshipit-source-id: 8fc4e4a005e93cf6d48a987f49edee33b90dbbf1
2021-08-31 18:27:40 -07:00
Konstantin Tsoy
ee59ae43c6 resetConnectionCallbacks() util function
Summary: In preparation for split callbacks

Reviewed By: mjoras, lnicco

Differential Revision: D30398849

fbshipit-source-id: 684c289283d0b06b5935fc1b8ab2dcbd126ec0ce
2021-08-25 16:15:42 -07:00
Hani Damlaj
bc72dbddcb Refactor Callback Handling
Summary: - Refactor callback handling into individual functions.

Reviewed By: mjoras

Differential Revision: D29919788

fbshipit-source-id: 64eaea4dcac9220fc86a6dbe53dfed3dcfb7cea7
2021-07-27 13:54:31 -07:00
Xintong Hu
02c50615a4 Support setting cmsg per accepted socket
Summary:
For each `QuicServerTransport` created by `QuicServerWorker`, we are able to set the `cmsg`s to be sent whenever there's a write.

With this we can set things like TOS/SO_MARK per connection

Reviewed By: bschlinker

Differential Revision: D29313608

fbshipit-source-id: d60c97f65681086ae1079b6b95beade95158ec59
2021-07-16 13:35:48 -07:00
Joseph Beshay
9d01dd7ef7 Add a new API to set MAX_PACING_RATE on a QuicSocket
Summary:
Add a new QuicSocket API that sets the maximum pacing rate in Bytes per second to be used if pacing is enabled. This setting is passed down to the Pacer which enforces it.

The change also includes:
- Refactoring the setPacingRate function of the Pacer to make it more consistent with the other refreshPacingRate function.
- A new flag for testing the MAX_PACING_RATE using tperf.

Reviewed By: mjoras

Differential Revision: D29276789

fbshipit-source-id: 818d86707084b2697f7417b4a47e62cbbce65c73
2021-06-30 13:46:59 -07:00
Alan Frindell
4afac7446c DeliveryCallback -> ByteEventCallback in all QuicSocket APIs
Summary: DeliveryCallback is a ByteEventCallback, so callers shouldn't need to change.

Reviewed By: bschlinker, mjoras

Differential Revision: D28562237

fbshipit-source-id: d7d41bbc3cbc708f7ecda5086fcba46b6a7847b0
2021-05-24 15:05:49 -07:00
Luca Niccolini
f778cfb945 Quic Socket: Datagram APIs
Summary: quic socket API to send and receive datagrams

Reviewed By: mjoras, yangchi

Differential Revision: D20983884

fbshipit-source-id: 70332c5fb9c37c88150fc2f623521e7b0c991eae
2021-05-11 08:24:03 -07:00
Sridhar Srinivasan
3a4783713a Use separate flags to enable app data sent callbacks
Summary:
Previously we were using a single flag appDataSentEvents to enable 3 callbacks
(startWritingFromAppLimited, packetsWritten and appRateLimited). This commit
creates separate flags to enable each of these callbacks, we have use-cases
where Observers might want only packetsWritten events and not the others.

Also, this commit refactors the logic to deliver these 3 callbacks to all
observers into a separate method so they can be unit tested easily.

Reviewed By: bschlinker

Differential Revision: D27925011

fbshipit-source-id: 7f7436dfc3d50c3abcb8ec121b221d20e30b0c4b
2021-05-02 23:07:47 -07:00
Yang Chi
aa59f9ef32 QuicSocket::setDSRPacketizationRequestSender API
Summary:
This assigns a DSRPacketizationRequestSender to a QUIC stream, and let
it own it.

Reviewed By: mjoras

Differential Revision: D27668523

fbshipit-source-id: 4beba6ddf247801368c3e1c24a0a4956490d45cd
2021-04-20 20:09:10 -07:00
Yang Chi
adc1e15eff Write a buffer's meta data into QUIC
Summary:
Instead of writing real data into the transport, we want to support a
use case where only its metadata is written to the transport. Sending of the
real data is delegated to another entity in such setup.

Reviewed By: mjoras

Differential Revision: D26131772

fbshipit-source-id: 4fcfa3a1626203f63c61898e6de089a3079d043d
2021-03-03 23:50:02 -08:00
Matt Joras
382c1cdcc6 Remove partial reliability from mvfst.
Summary: As in title.

Reviewed By: yangchi

Differential Revision: D26701886

fbshipit-source-id: c7b36c616200b17fbf697eff4ba0d18695effb45
2021-03-03 15:30:21 -08:00
Yang Chi
0b42e07216 Getter API of Quic stream priority
Summary: as title

Reviewed By: afrind, avasylev

Differential Revision: D26744365

fbshipit-source-id: 5c5d104ca76c77f14371c20d6f791fca8d7cfe38
2021-03-03 07:26:28 -08:00
Andrii Vasylevskyi
10a6feed49 Reset congestion controller after setting factory
Summary:
Before the change, there's no good way to recreate Cubic CC instance with custom CC factory, because Cubic is created by default.

On client side this requires calling setCongestionControl() or setTransportSettings() after calling setCongestionControllerFactory(), which is normally the case.

Reviewed By: yangchi

Differential Revision: D26401996

fbshipit-source-id: dfda39be835c67b9db42f726b3ac64c7b3d37c2f
2021-02-19 17:55:10 -08:00
Andrii Vasylevskyi
1303281a51 Create pacer before congestion controller
Summary: Allows CongestionControllerFactor to access Pacer and update it's state if needed

Reviewed By: yangchi

Differential Revision: D26382984

fbshipit-source-id: fd73fbb6f0989c52a1a2061670fb9e6b188049d6
2021-02-19 17:55:10 -08:00
Andrii Vasylevskyi
ba71671bb2 QuicConnectionStats for client socket
Summary: Adding QuiConnectionStats to client transport. Moving getConnectionsStats() logic from server worker into transport base class.

Reviewed By: lnicco

Differential Revision: D26316635

fbshipit-source-id: a384eee5d1bc7b23d908e0b03fafcc4ee962b0b9
2021-02-19 10:47:02 -08:00