1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-11-10 21:22:20 +03:00
Files
mvfst/quic/server/state/ServerStateMachine.h
Matt Joras 50d5c29346 Cipher dropping take 2
Summary:
Now we won't have a zero PTO and we will properly clear out the outstanding packets.

Note that this cipher dropping is not what the draft prescribes, instead dropping both the initial and handshake ciphers when we know 1-rtt communication is functioning.

Reviewed By: yangchi

Differential Revision: D20388737

fbshipit-source-id: 0b89eb80c8faa796ab09eda3eaa10a00dcf7bae9
2020-05-06 11:14:20 -07:00

201 lines
6.5 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its 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/logging/QuicLogger.h>
#include <quic/loss/QuicLossFunctions.h>
#include <quic/server/handshake/ServerHandshake.h>
#include <quic/server/state/ServerConnectionIdRejector.h>
#include <quic/state/AckHandlers.h>
#include <quic/state/QPRFunctions.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;
};
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};
folly::Optional<ConnectionIdData> createAndAddNewSelfConnId() override;
QuicServerConnectionState() : QuicConnectionStateBase(QuicNodeType::Server) {
state = ServerState::Open;
// Create the crypto stream.
cryptoState = std::make_unique<QuicCryptoState>();
congestionController = std::make_unique<Cubic>(*this);
// TODO: this is wrong, it should be the handshake finish time. But i need
// a relatively sane time now to make the timestamps all sane.
connectionTime = Clock::now();
supportedVersions = std::vector<QuicVersion>{
{QuicVersion::MVFST, QuicVersion::MVFST_D24, QuicVersion::QUIC_DRAFT}};
originalVersion = QuicVersion::MVFST;
serverHandshakeLayer = new ServerHandshake(this);
handshakeLayer.reset(serverHandshakeLayer);
// 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);
}
};
// 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,
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);
} // namespace quic