1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-04-18 17:24:03 +03:00
mvfst/quic/server/state/ServerStateMachine.h
Konstantin Tsoy adf16f9a07 Remove libccp from mvfst
Summary: We don't use it, and the OSS lib hasn't been updated in a while.

Reviewed By: mjoras

Differential Revision: D46707559

fbshipit-source-id: ec102a52183a736cfb1c0241600816a837062108
2023-06-15 18:17:53 -07:00

240 lines
7.7 KiB
C++

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <glog/logging.h>
#include <memory>
#include <vector>
#include <quic/QuicException.h>
#include <quic/codec/Types.h>
#include <quic/congestion_control/CongestionControllerFactory.h>
#include <quic/congestion_control/QuicCubic.h>
#include <quic/flowcontrol/QuicFlowController.h>
#include <quic/loss/QuicLossFunctions.h>
#include <quic/server/handshake/ServerHandshake.h>
#include <quic/server/handshake/ServerHandshakeFactory.h>
#include <quic/server/state/ServerConnectionIdRejector.h>
#include <quic/state/AckHandlers.h>
#include <quic/state/QuicStateFunctions.h>
#include <quic/state/QuicStreamFunctions.h>
#include <quic/state/SimpleFrameFunctions.h>
#include <quic/state/StateData.h>
#include <folly/ExceptionWrapper.h>
#include <folly/IPAddress.h>
#include <folly/Overload.h>
#include <folly/Random.h>
#include <folly/io/async/AsyncSocketException.h>
namespace quic {
enum ServerState {
Open,
Closed,
};
struct ServerEvents {
struct ReadData {
folly::SocketAddress peer;
NetworkDataSingle networkData;
};
struct Close {};
};
struct CongestionAndRttState {
// The corresponding peer address
folly::SocketAddress peerAddress;
// Time when this state is recorded, i.e. when migration happens
TimePoint recordTime;
// Congestion controller
std::unique_ptr<CongestionController> congestionController;
// Smooth rtt
std::chrono::microseconds srtt;
// Latest rtt
std::chrono::microseconds lrtt;
// Rtt var
std::chrono::microseconds rttvar;
// Minimum rtt
std::chrono::microseconds mrtt;
};
struct ConnectionMigrationState {
uint32_t numMigrations{0};
// Previous validated peer addresses, not containing current peer address
std::vector<folly::SocketAddress> previousPeerAddresses;
// Congestion state and rtt stats of last validated peer
folly::Optional<CongestionAndRttState> lastCongestionAndRtt;
};
/**
* State used during processing of MAX_PACING_RATE_KNOB frames.
*/
struct MaxPacingRateKnobState {
uint64_t lastMaxRateBytesPerSec = std::numeric_limits<uint64_t>::max();
bool frameOutOfOrderDetected = false;
};
struct QuicServerConnectionState : public QuicConnectionStateBase {
~QuicServerConnectionState() override = default;
ServerState state;
// Data which we cannot read yet, because the handshake has not completed.
// Zero rtt protected packets
std::unique_ptr<std::vector<ServerEvents::ReadData>> pendingZeroRttData;
// One rtt protected packets
std::unique_ptr<std::vector<ServerEvents::ReadData>> pendingOneRttData;
// Current state of connection migration
ConnectionMigrationState migrationState;
// Parameters to generate server chosen connection id
folly::Optional<ServerConnectionIdParams> serverConnIdParams;
// ConnectionIdAlgo implementation to encode and decode ConnectionId with
// various info, such as routing related info.
ConnectionIdAlgo* connIdAlgo{nullptr};
// ServerConnectionIdRejector can reject a ConnectionId from ConnectionIdAlgo
ServerConnectionIdRejector* connIdRejector{nullptr};
// Source address token that can be saved to client via PSK.
// Address with higher index is more recently used.
std::vector<folly::IPAddress> tokenSourceAddresses;
ServerHandshake* serverHandshakeLayer;
// Whether transport parameters from psk match current server parameters.
// A false value indicates 0-rtt is rejected.
folly::Optional<bool> transportParamsMatching;
// Whether source address token matches client ip.
// A false value indicates either 0-rtt is rejected or inflight bytes are
// limited until CFIN depending on matching policy.
folly::Optional<bool> sourceTokenMatching;
// Server address of VIP. Currently used as input for stateless reset token.
folly::SocketAddress serverAddr;
// Whether we've sent the handshake done signal yet.
bool sentHandshakeDone{false};
// Whether we've sent the new_token frame yet.
bool sentNewTokenFrame{false};
// Number of bytes the server has written during the handshake.
uint64_t numHandshakeBytesSent{0};
// Whether or not the client has verified their address (thru CFIN or
// NewToken).
bool isClientAddrVerified{false};
// State for max pacing rate knob. Currently used to detect out of order
// MAX_PACING_RATE_KNOB frames.
MaxPacingRateKnobState maxPacingRateKnobState{};
// Sequence number of the last received MAX_PACING_RATE_KNOB_SEQUENCED.
folly::Optional<uint64_t> maybeLastMaxPacingRateKnobSeqNum{folly::none};
folly::Optional<ConnectionIdData> createAndAddNewSelfConnId() override;
QuicServerConnectionState(
std::shared_ptr<ServerHandshakeFactory> handshakeFactory)
: QuicConnectionStateBase(QuicNodeType::Server) {
state = ServerState::Open;
// Create the crypto stream.
cryptoState = std::make_unique<QuicCryptoState>();
congestionController = std::make_unique<Cubic>(*this);
connectionTime = Clock::now();
supportedVersions = std::vector<QuicVersion>{
{QuicVersion::MVFST,
QuicVersion::MVFST_EXPERIMENTAL,
QuicVersion::MVFST_EXPERIMENTAL2,
QuicVersion::MVFST_EXPERIMENTAL3,
QuicVersion::MVFST_ALIAS,
QuicVersion::QUIC_V1,
QuicVersion::QUIC_V1_ALIAS,
QuicVersion::QUIC_DRAFT}};
originalVersion = QuicVersion::MVFST;
DCHECK(handshakeFactory);
auto tmpServerHandshake =
std::move(*handshakeFactory).makeServerHandshake(this);
serverHandshakeLayer = tmpServerHandshake.get();
handshakeLayer = std::move(tmpServerHandshake);
// We shouldn't normally need to set this until we're starting the
// transport, however writing unit tests is much easier if we set this here.
updateFlowControlStateWithSettings(flowControlState, transportSettings);
pendingZeroRttData =
std::make_unique<std::vector<ServerEvents::ReadData>>();
pendingOneRttData = std::make_unique<std::vector<ServerEvents::ReadData>>();
streamManager = std::make_unique<QuicStreamManager>(
*this, this->nodeType, transportSettings);
connIdsRetiringSoon.emplace(SmallVec<ConnectionId, 5>{});
}
};
// Transition to error state on invalid state transition.
void ServerInvalidStateHandler(QuicServerConnectionState& state);
void onServerReadData(
QuicServerConnectionState& conn,
ServerEvents::ReadData& readData);
void onServerReadDataFromOpen(
QuicServerConnectionState& conn,
ServerEvents::ReadData& readData);
void onServerReadDataFromClosed(
QuicServerConnectionState& conn,
ServerEvents::ReadData& readData);
void onServerClose(QuicServerConnectionState& conn);
void onServerCloseOpenState(QuicServerConnectionState& conn);
void processClientInitialParams(
QuicServerConnectionState& conn,
const ClientTransportParameters& clientParams);
void updateHandshakeState(QuicServerConnectionState& conn);
bool validateAndUpdateSourceToken(
QuicServerConnectionState& conn,
std::vector<folly::IPAddress> sourceAddresses);
void updateWritableByteLimitOnRecvPacket(QuicServerConnectionState& conn);
void updateTransportParamsFromTicket(
QuicServerConnectionState& conn,
uint64_t idleTimeout,
uint64_t maxRecvPacketSize,
uint64_t initialMaxData,
uint64_t initialMaxStreamDataBidiLocal,
uint64_t initialMaxStreamDataBidiRemote,
uint64_t initialMaxStreamDataUni,
uint64_t initialMaxStreamsBidi,
uint64_t initialMaxStreamsUni);
void onConnectionMigration(
QuicServerConnectionState& conn,
const folly::SocketAddress& newPeerAddress,
bool isIntentional = false);
std::vector<TransportParameter> setSupportedExtensionTransportParameters(
QuicServerConnectionState& conn);
} // namespace quic