blob: 638333e7389b7bba3c3c0675a6b0bb16d2cfd154 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2017 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef QUICHE_QUIC_QUARTC_QUARTC_SESSION_H_
6#define QUICHE_QUIC_QUARTC_QUARTC_SESSION_H_
7
8#include <memory>
9#include <string>
10
11#include "net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h"
12#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
13#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
14#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
15#include "net/third_party/quiche/src/quic/core/quic_session.h"
16#include "net/third_party/quiche/src/quic/core/quic_types.h"
QUICHE team34df5852019-05-29 16:27:22 -070017#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
QUICHE teamea197352019-07-16 16:54:52 -070018#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_storage.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050019#include "net/third_party/quiche/src/quic/quartc/quartc_packet_writer.h"
20#include "net/third_party/quiche/src/quic/quartc/quartc_stream.h"
21
22namespace quic {
23
24// QuartcSession owns and manages a QUIC connection.
25class QuartcSession : public QuicSession,
26 public QuartcPacketTransport::Delegate {
27 public:
28 QuartcSession(std::unique_ptr<QuicConnection> connection,
29 Visitor* visitor,
30 const QuicConfig& config,
31 const ParsedQuicVersionVector& supported_versions,
32 const QuicClock* clock);
33 QuartcSession(const QuartcSession&) = delete;
34 QuartcSession& operator=(const QuartcSession&) = delete;
35 ~QuartcSession() override;
36
37 // QuicSession overrides.
38 QuartcStream* CreateOutgoingBidirectionalStream();
39
40 // Sends short unreliable message using quic message frame (message must fit
41 // in one quic packet). If connection is blocked by congestion control,
42 // message will be queued and resent later after receiving an OnCanWrite
43 // notification.
44 //
45 // Message size must be <= GetLargestMessagePayload().
46 //
47 // Supported in quic version 45 or later.
48 //
49 // Returns false and logs error if message is too long or session does not
50 // support SendMessage API. Other unexpected errors during send will not be
51 // returned, because messages can be sent later if connection is congestion
52 // controlled.
QUICHE team136e7852019-05-13 14:10:34 -070053 //
54 // |datagram_id| is used to notify when message was sent in
55 // Delegate::OnMessageSent.
56 //
57 // TODO(sukhanov): We can not use QUIC message ID for notifications, because
58 // QUIC does not take ownership of messages and if connection is congestion
59 // controlled, message is not sent and does not get message id until it is
60 // sent successfully. It also creates problem of flow control between
61 // messages and streams if they are used together. We discussed it with QUIC
62 // team and there are multiple solutions, but for now we have to use our
63 // own datagram identification.
64 bool SendOrQueueMessage(QuicMemSliceSpan message, int64_t datagram_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -050065
66 // Returns largest message payload acceptable in SendQuartcMessage.
ianswettb239f862019-04-05 09:15:06 -070067 QuicPacketLength GetCurrentLargestMessagePayload() const {
68 return connection()->GetCurrentLargestMessagePayload();
QUICHE teama6ef0a62019-03-07 20:34:33 -050069 }
70
71 // Return true if transport support message frame.
72 bool CanSendMessage() const {
fayangd4291e42019-05-30 10:31:21 -070073 return VersionSupportsMessageFrames(connection()->transport_version());
QUICHE teama6ef0a62019-03-07 20:34:33 -050074 }
75
76 void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
77
78 // QuicConnectionVisitorInterface overrides.
79 void OnCongestionWindowChange(QuicTime now) override;
80 bool ShouldKeepConnectionAlive() const override;
81
82 void OnCanWrite() override;
QUICHE team65d3e322019-04-29 14:19:54 -070083 bool SendProbingData() override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050084
fkastenholz5d880a92019-06-21 09:01:56 -070085 void OnConnectionClosed(const QuicConnectionCloseFrame& frame,
QUICHE teama6ef0a62019-03-07 20:34:33 -050086 ConnectionCloseSource source) override;
87
88 // QuartcSession methods.
89 virtual void StartCryptoHandshake() = 0;
90
91 // Closes the connection with the given human-readable error details.
92 // The connection closes with the QUIC_CONNECTION_CANCELLED error code to
93 // indicate the application closed it.
94 //
95 // Informs the peer that the connection has been closed. This prevents the
96 // peer from waiting until the connection times out.
97 //
98 // Cleans up the underlying QuicConnection's state. Closing the connection
99 // makes it safe to delete the QuartcSession.
vasilvvc48c8712019-03-11 13:38:16 -0700100 void CloseConnection(const std::string& details);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500101
102 // If the given stream is still open, sends a reset frame to cancel it.
103 // Note: This method cancels a stream by QuicStreamId rather than by pointer
104 // (or by a method on QuartcStream) because QuartcSession (and not
105 // the caller) owns the streams. Streams may finish and be deleted before the
106 // caller tries to cancel them, rendering the caller's pointers invalid.
107 void CancelStream(QuicStreamId stream_id);
108
109 // Callbacks called by the QuartcSession to notify the user of the
110 // QuartcSession of certain events.
111 class Delegate {
112 public:
113 virtual ~Delegate() {}
114
115 // Called when the crypto handshake is complete. Crypto handshake on the
116 // client is only completed _after_ SHLO is received, but we can actually
117 // start sending media data right after CHLO is sent.
118 virtual void OnCryptoHandshakeComplete() = 0;
119
120 // Connection can be writable even before crypto handshake is complete.
121 // In particular, on the client, we can start sending data after sending
122 // full CHLO, without waiting for SHLO. This reduces a send delay by 1-rtt.
123 //
124 // This may be called multiple times.
125 virtual void OnConnectionWritable() = 0;
126
127 // Called when a new stream is received from the remote endpoint.
128 virtual void OnIncomingStream(QuartcStream* stream) = 0;
129
130 // Called when network parameters change in response to an ack frame.
131 virtual void OnCongestionControlChange(QuicBandwidth bandwidth_estimate,
132 QuicBandwidth pacing_rate,
133 QuicTime::Delta latest_rtt) = 0;
134
135 // Called when the connection is closed. This means all of the streams will
136 // be closed and no new streams can be created.
fkastenholz5d880a92019-06-21 09:01:56 -0700137 virtual void OnConnectionClosed(const QuicConnectionCloseFrame& frame,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500138 ConnectionCloseSource source) = 0;
139
140 // Called when message (sent as SendMessage) is received.
141 virtual void OnMessageReceived(QuicStringPiece message) = 0;
142
QUICHE team136e7852019-05-13 14:10:34 -0700143 // Called when message is sent to QUIC.
144 //
145 // Takes into account delay due to congestion control, but does not take
146 // into account any additional socket delays.
147 //
148 // Passed |datagram_id| is the same used in SendOrQueueMessage.
149 //
150 // TODO(sukhanov): We can take into account socket delay, but it's not clear
151 // if it's worth doing if we eventually plan to move congestion control to
152 // QUIC in QRTP model. If we need to do it, mellem@ thinks it's fairly
153 // strtaightforward: QUIC does not know about socket delay, but ICE does. We
154 // can tell ICE the QUIC packet number for each packet sent, and it will
155 // echo it back to us when the packet actually goes out. We just need to
156 // plumb that signal up to RTP's congestion control.
157 virtual void OnMessageSent(int64_t datagram_id) = 0;
158
QUICHE team68d15a82019-05-31 15:27:25 -0700159 // Called when message with |datagram_id| gets acked. |receive_timestamp|
160 // indicates when the peer received this message, according to its own
161 // clock.
162 virtual void OnMessageAcked(int64_t datagram_id,
163 QuicTime receive_timestamp) = 0;
164
165 // Called when message with |datagram_id| is lost.
166 virtual void OnMessageLost(int64_t datagram_id) = 0;
QUICHE team34df5852019-05-29 16:27:22 -0700167
QUICHE teama6ef0a62019-03-07 20:34:33 -0500168 // TODO(zhihuang): Add proof verification.
169 };
170
171 // The |delegate| is not owned by QuartcSession.
172 void SetDelegate(Delegate* session_delegate);
173
174 // Called when CanWrite() changes from false to true.
175 void OnTransportCanWrite() override;
176
177 // Called when a packet has been received and should be handled by the
178 // QuicConnection.
179 void OnTransportReceived(const char* data, size_t data_len) override;
180
181 void OnMessageReceived(QuicStringPiece message) override;
182
QUICHE team34df5852019-05-29 16:27:22 -0700183 // Called when message with |message_id| gets acked.
QUICHE team9467db02019-05-30 09:38:45 -0700184 void OnMessageAcked(QuicMessageId message_id,
185 QuicTime receive_timestamp) override;
QUICHE team34df5852019-05-29 16:27:22 -0700186
QUICHE team68d15a82019-05-31 15:27:25 -0700187 void OnMessageLost(QuicMessageId message_id) override;
188
QUICHE teama6ef0a62019-03-07 20:34:33 -0500189 // Returns number of queued (not sent) messages submitted by
190 // SendOrQueueMessage. Messages are queued if connection is congestion
191 // controlled.
192 size_t send_message_queue_size() const { return send_message_queue_.size(); }
193
194 protected:
195 // QuicSession override.
196 QuicStream* CreateIncomingStream(QuicStreamId id) override;
renjietangbaea59c2019-05-29 15:08:14 -0700197 QuicStream* CreateIncomingStream(PendingStream* pending) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500198
199 std::unique_ptr<QuartcStream> CreateDataStream(QuicStreamId id,
200 spdy::SpdyPriority priority);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500201 // Activates a QuartcStream. The session takes ownership of the stream, but
202 // returns an unowned pointer to the stream for convenience.
203 QuartcStream* ActivateDataStream(std::unique_ptr<QuartcStream> stream);
204
205 void ResetStream(QuicStreamId stream_id, QuicRstStreamErrorCode error);
206
207 const QuicClock* clock() { return clock_; }
208
209 private:
210 std::unique_ptr<QuartcStream> InitializeDataStream(
211 std::unique_ptr<QuartcStream> stream,
212 spdy::SpdyPriority priority);
213
QUICHE team136e7852019-05-13 14:10:34 -0700214 // Holds message until it's sent.
215 struct QueuedMessage {
QUICHE teamea197352019-07-16 16:54:52 -0700216 QueuedMessage() : message(nullptr, 0, nullptr, 0), datagram_id(0) {}
217
218 QuicMemSliceStorage message;
QUICHE team136e7852019-05-13 14:10:34 -0700219 int64_t datagram_id;
220 };
221
QUICHE teama6ef0a62019-03-07 20:34:33 -0500222 void ProcessSendMessageQueue();
223
224 // Take ownership of the QuicConnection. Note: if |connection_| changes,
225 // the new value of |connection_| must be given to |packet_writer_| before any
226 // packets are written. Otherwise, |packet_writer_| will crash.
227 std::unique_ptr<QuicConnection> connection_;
228
229 // For recording packet receipt time
230 const QuicClock* clock_;
231
232 // Not owned by QuartcSession.
233 Delegate* session_delegate_ = nullptr;
234
235 // Options passed to the packet writer for each packet.
236 std::unique_ptr<QuartcPerPacketOptions> per_packet_options_;
237
238 // Queue of pending messages sent by SendQuartcMessage that were not sent
239 // yet or blocked by congestion control. Messages are queued in the order
240 // of sent by SendOrQueueMessage().
QUICHE team136e7852019-05-13 14:10:34 -0700241 QuicDeque<QueuedMessage> send_message_queue_;
QUICHE team34df5852019-05-29 16:27:22 -0700242
243 // Maps message ids to datagram ids, so we could translate message ACKs
244 // received from QUIC to datagram ACKs that are propagated up the stack.
245 QuicUnorderedMap<QuicMessageId, int64_t> message_to_datagram_id_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500246};
247
248class QuartcClientSession : public QuartcSession,
249 public QuicCryptoClientStream::ProofHandler {
250 public:
251 QuartcClientSession(
252 std::unique_ptr<QuicConnection> connection,
253 const QuicConfig& config,
254 const ParsedQuicVersionVector& supported_versions,
255 const QuicClock* clock,
256 std::unique_ptr<QuartcPacketWriter> packet_writer,
257 std::unique_ptr<QuicCryptoClientConfig> client_crypto_config,
258 QuicStringPiece server_crypto_config);
259 QuartcClientSession(const QuartcClientSession&) = delete;
260 QuartcClientSession& operator=(const QuartcClientSession&) = delete;
261
262 ~QuartcClientSession() override;
263
264 // Initialize should not be called on a QuartcSession. Instead, call
265 // StartCryptoHandshake().
266 // TODO(mellem): Move creation of the crypto stream into Initialize() and
267 // remove StartCryptoHandshake() to bring QuartcSession in line with other
268 // implementations of QuicSession, which can be started by calling
269 // Initialize().
270 void Initialize() override;
271
272 // Accessors for the client crypto stream.
273 QuicCryptoStream* GetMutableCryptoStream() override;
274 const QuicCryptoStream* GetCryptoStream() const override;
275
276 // Initializes the session and sends a handshake.
277 void StartCryptoHandshake() override;
278
279 // ProofHandler overrides.
280 void OnProofValid(const QuicCryptoClientConfig::CachedState& cached) override;
281
282 // Called by the client crypto handshake when proof verification details
283 // become available, either because proof verification is complete, or when
284 // cached details are used.
285 void OnProofVerifyDetailsAvailable(
286 const ProofVerifyDetails& verify_details) override;
287
288 private:
289 // Packet writer used by |connection_|.
290 std::unique_ptr<QuartcPacketWriter> packet_writer_;
291
292 // Config for QUIC crypto stream.
293 std::unique_ptr<QuicCryptoClientConfig> client_crypto_config_;
294
295 // Client perspective crypto stream.
296 std::unique_ptr<QuicCryptoClientStream> crypto_stream_;
297
vasilvvc48c8712019-03-11 13:38:16 -0700298 const std::string server_config_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500299};
300
301class QuartcServerSession : public QuartcSession {
302 public:
303 QuartcServerSession(std::unique_ptr<QuicConnection> connection,
304 Visitor* visitor,
305 const QuicConfig& config,
306 const ParsedQuicVersionVector& supported_versions,
307 const QuicClock* clock,
308 const QuicCryptoServerConfig* server_crypto_config,
309 QuicCompressedCertsCache* const compressed_certs_cache,
310 QuicCryptoServerStream::Helper* const stream_helper);
311 QuartcServerSession(const QuartcServerSession&) = delete;
312 QuartcServerSession& operator=(const QuartcServerSession&) = delete;
313
314 // Accessors for the server crypto stream.
315 QuicCryptoStream* GetMutableCryptoStream() override;
316 const QuicCryptoStream* GetCryptoStream() const override;
317
318 // Initializes the session and prepares to receive a handshake.
319 void StartCryptoHandshake() override;
320
321 private:
322 // Config for QUIC crypto stream.
323 const QuicCryptoServerConfig* server_crypto_config_;
324
325 // Used by QUIC crypto server stream to track most recently compressed certs.
326 QuicCompressedCertsCache* const compressed_certs_cache_;
327
328 // This helper is needed to create QuicCryptoServerStream.
329 QuicCryptoServerStream::Helper* const stream_helper_;
330
331 // Server perspective crypto stream.
332 std::unique_ptr<QuicCryptoServerStream> crypto_stream_;
333};
334
335} // namespace quic
336
337#endif // QUICHE_QUIC_QUARTC_QUARTC_SESSION_H_