1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  *
7  */
8 
9 #pragma once
10 
11 #include <folly/io/async/AsyncSocketException.h>
12 #include <quic/client/handshake/ClientHandshake.h>
13 #include <quic/client/handshake/ClientHandshakeFactory.h>
14 #include <quic/congestion_control/QuicCubic.h>
15 #include <quic/flowcontrol/QuicFlowController.h>
16 #include <quic/handshake/TransportParameters.h>
17 #include <quic/state/QuicStateFunctions.h>
18 #include <quic/state/StateData.h>
19 
20 namespace quic {
21 
22 struct CachedServerTransportParameters;
23 
24 struct PendingClientData {
25   NetworkDataSingle networkData;
26   folly::SocketAddress peer;
27 
PendingClientDataPendingClientData28   PendingClientData(
29       NetworkDataSingle networkDataIn,
30       folly::SocketAddress peerIn)
31       : networkData(std::move(networkDataIn)), peer(std::move(peerIn)) {}
32 };
33 
34 struct QuicClientConnectionState : public QuicConnectionStateBase {
35   ~QuicClientConnectionState() override = default;
36 
37   // Zero rtt write header cipher.
38   std::unique_ptr<PacketNumberCipher> zeroRttWriteHeaderCipher;
39   // Write cipher for 0-RTT data
40   std::unique_ptr<Aead> zeroRttWriteCipher;
41 
42   // The stateless reset token sent by the server.
43   folly::Optional<StatelessResetToken> statelessResetToken;
44 
45   // The retry token sent by the server.
46   std::string retryToken;
47 
48   // This is the destination connection id that will be sent in the outgoing
49   // client initial packet. It is modified in the event of a retry.
50   folly::Optional<ConnectionId> initialDestinationConnectionId;
51 
52   // This is the original destination connection id. It is the same as the
53   // initialDestinationConnectionId when there is no retry involved. When
54   // there is retry involved, this is the value of the destination connection
55   // id sent in the very first initial packet.
56   folly::Optional<ConnectionId> originalDestinationConnectionId;
57 
58   std::shared_ptr<ClientHandshakeFactory> handshakeFactory;
59   ClientHandshake* clientHandshakeLayer;
60 
61   folly::Optional<TimePoint> lastCloseSentTime;
62 
63   // Save the server transport params here so that client can access the value
64   // when it wants to write the values to psk cache
65   // TODO Save TicketTransportParams here instead of in QuicClientTransport
66   bool serverInitialParamsSet_{false};
67   uint64_t peerAdvertisedInitialMaxData{0};
68   uint64_t peerAdvertisedInitialMaxStreamDataBidiLocal{0};
69   uint64_t peerAdvertisedInitialMaxStreamDataBidiRemote{0};
70   uint64_t peerAdvertisedInitialMaxStreamDataUni{0};
71   uint64_t peerAdvertisedInitialMaxStreamsBidi{0};
72   uint64_t peerAdvertisedInitialMaxStreamsUni{0};
73 
74   struct HappyEyeballsState {
75     // Delay timer
76     folly::HHWheelTimer::Callback* connAttemptDelayTimeout{nullptr};
77 
78     // IPv6 peer address
79     folly::SocketAddress v6PeerAddress;
80 
81     // IPv4 peer address
82     folly::SocketAddress v4PeerAddress;
83 
84     // The address that this socket will try to connect to after connection
85     // attempt delay timeout fires
86     folly::SocketAddress secondPeerAddress;
87 
88     // The UDP socket that will be used for the second connection attempt
89     std::unique_ptr<folly::AsyncUDPSocket> secondSocket;
90 
91     // Whether should write to the first UDP socket
92     bool shouldWriteToFirstSocket{true};
93 
94     // Whether should write to the second UDP socket
95     bool shouldWriteToSecondSocket{false};
96 
97     // Whether HappyEyeballs has finished
98     // The signal of finishing is first successful decryption of a packet
99     bool finished{false};
100   };
101 
102   HappyEyeballsState happyEyeballsState;
103 
104   // Short header packets we received but couldn't yet decrypt.
105   std::vector<PendingClientData> pendingOneRttData;
106   // Handshake packets we received but couldn't yet decrypt.
107   std::vector<PendingClientData> pendingHandshakeData;
108 
QuicClientConnectionStateQuicClientConnectionState109   explicit QuicClientConnectionState(
110       std::shared_ptr<ClientHandshakeFactory> handshakeFactoryIn)
111       : QuicConnectionStateBase(QuicNodeType::Client),
112         handshakeFactory(std::move(handshakeFactoryIn)) {
113     cryptoState = std::make_unique<QuicCryptoState>();
114     congestionController = std::make_unique<Cubic>(*this);
115     connectionTime = Clock::now();
116     originalVersion = QuicVersion::MVFST;
117     DCHECK(handshakeFactory);
118     auto tmpClientHandshake =
119         std::move(*handshakeFactory).makeClientHandshake(this);
120     clientHandshakeLayer = tmpClientHandshake.get();
121     handshakeLayer = std::move(tmpClientHandshake);
122     // We shouldn't normally need to set this until we're starting the
123     // transport, however writing unit tests is much easier if we set this here.
124     updateFlowControlStateWithSettings(flowControlState, transportSettings);
125     streamManager = std::make_unique<QuicStreamManager>(
126         *this, this->nodeType, transportSettings);
127     transportSettings.selfActiveConnectionIdLimit =
128         kDefaultActiveConnectionIdLimit;
129   }
130 };
131 
132 /**
133  * Undos the clients state to be the original state of the client.
134  */
135 std::unique_ptr<QuicClientConnectionState> undoAllClientStateForRetry(
136     std::unique_ptr<QuicClientConnectionState> conn);
137 
138 void processServerInitialParams(
139     QuicClientConnectionState& conn,
140     ServerTransportParameters serverParams,
141     PacketNum packetNum);
142 
143 void cacheServerInitialParams(
144     QuicClientConnectionState& conn,
145     uint64_t peerAdvertisedInitialMaxData,
146     uint64_t peerAdvertisedInitialMaxStreamDataBidiLocal,
147     uint64_t peerAdvertisedInitialMaxStreamDataBidiRemote,
148     uint64_t peerAdvertisedInitialMaxStreamDataUni,
149     uint64_t peerAdvertisedInitialMaxStreamsBidi,
150     uint64_t peerAdvertisedInitialMaxStreamUni);
151 
152 CachedServerTransportParameters getServerCachedTransportParameters(
153     const QuicClientConnectionState& conn);
154 
155 void updateTransportParamsFromCachedEarlyParams(
156     QuicClientConnectionState& conn,
157     const CachedServerTransportParameters& transportParams);
158 
159 } // namespace quic
160