blob: 66f993a59b84adbcf462c429760a9caf08cdd7cf [file] [log] [blame]
vasilvve6472f62019-10-02 06:50:56 -07001// Copyright (c) 2019 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#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.h"
6
vasilvvddf52472019-10-04 15:14:02 -07007#include <cstdint>
8#include <limits>
vasilvve6472f62019-10-02 06:50:56 -07009#include <memory>
vasilvv2b0ab242020-01-07 07:32:09 -080010#include <string>
bnc463f2352019-10-10 04:49:34 -070011#include <utility>
vasilvve6472f62019-10-02 06:50:56 -070012
vasilvv74b16612020-10-09 11:42:53 -070013#include "absl/strings/string_view.h"
vasilvve6472f62019-10-02 06:50:56 -070014#include "url/gurl.h"
vasilvv2b0ab242020-01-07 07:32:09 -080015#include "net/third_party/quiche/src/quic/core/quic_constants.h"
vasilvve6472f62019-10-02 06:50:56 -070016#include "net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h"
vasilvvddf52472019-10-04 15:14:02 -070017#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
18#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
vasilvve6472f62019-10-02 06:50:56 -070019#include "net/third_party/quiche/src/quic/core/quic_session.h"
20#include "net/third_party/quiche/src/quic/core/quic_types.h"
21#include "net/third_party/quiche/src/quic/core/quic_versions.h"
vasilvvd88f1622019-11-04 13:50:53 -080022#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
vasilvve6472f62019-10-02 06:50:56 -070023#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
vasilvvd88f1622019-11-04 13:50:53 -080024#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h"
vasilvv312e3a52019-10-18 15:06:14 -070025#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h"
vasilvve6472f62019-10-02 06:50:56 -070026
27namespace quic {
28
vasilvve6472f62019-10-02 06:50:56 -070029QuicTransportClientSession::QuicTransportClientSession(
30 QuicConnection* connection,
31 Visitor* owner,
32 const QuicConfig& config,
33 const ParsedQuicVersionVector& supported_versions,
vasilvve58d0f12019-12-04 14:35:25 -080034 const GURL& url,
vasilvve6472f62019-10-02 06:50:56 -070035 QuicCryptoClientConfig* crypto_config,
vasilvvdfbd3df2019-11-01 11:58:43 -070036 url::Origin origin,
QUICHE team20456ed2020-11-18 22:24:42 -080037 ClientVisitor* visitor,
38 std::unique_ptr<QuicDatagramQueue::Observer> datagram_observer)
vasilvve6472f62019-10-02 06:50:56 -070039 : QuicSession(connection,
40 owner,
41 config,
42 supported_versions,
QUICHE team20456ed2020-11-18 22:24:42 -080043 /*num_expected_unidirectional_static_streams*/ 0,
44 std::move(datagram_observer)),
vasilvve58d0f12019-12-04 14:35:25 -080045 url_(url),
vasilvvdfbd3df2019-11-01 11:58:43 -070046 origin_(origin),
47 visitor_(visitor) {
vasilvve6472f62019-10-02 06:50:56 -070048 for (const ParsedQuicVersion& version : supported_versions) {
49 QUIC_BUG_IF(version.handshake_protocol != PROTOCOL_TLS1_3)
50 << "QuicTransport requires TLS 1.3 handshake";
51 }
vasilvve6472f62019-10-02 06:50:56 -070052 crypto_stream_ = std::make_unique<QuicCryptoClientStream>(
vasilvve58d0f12019-12-04 14:35:25 -080053 QuicServerId(url.host(), url.EffectiveIntPort()), this,
54 crypto_config->proof_verifier()->CreateDefaultContext(), crypto_config,
vasilvv636b7f22020-08-07 10:37:19 -070055 /*proof_handler=*/this, /*has_application_state = */ true);
vasilvve6472f62019-10-02 06:50:56 -070056}
57
vasilvv74b16612020-10-09 11:42:53 -070058void QuicTransportClientSession::OnAlpnSelected(absl::string_view alpn) {
vasilvv467b4222019-12-09 16:22:11 -080059 // Defense in-depth: ensure the ALPN selected is the desired one.
60 if (alpn != QuicTransportAlpn()) {
61 QUIC_BUG << "QuicTransport negotiated non-QuicTransport ALPN: " << alpn;
62 connection()->CloseConnection(
63 QUIC_INTERNAL_ERROR, "QuicTransport negotiated non-QuicTransport ALPN",
64 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
65 return;
66 }
67
68 alpn_received_ = true;
69}
70
vasilvv312e3a52019-10-18 15:06:14 -070071QuicStream* QuicTransportClientSession::CreateIncomingStream(QuicStreamId id) {
vasilvvdfbd3df2019-11-01 11:58:43 -070072 QUIC_DVLOG(1) << "Creating incoming QuicTransport stream " << id;
vasilvvd88f1622019-11-04 13:50:53 -080073 QuicTransportStream* stream = CreateStream(id);
74 if (stream->type() == BIDIRECTIONAL) {
75 incoming_bidirectional_streams_.push_back(stream);
vasilvvdfbd3df2019-11-01 11:58:43 -070076 visitor_->OnIncomingBidirectionalStreamAvailable();
77 } else {
vasilvvd88f1622019-11-04 13:50:53 -080078 incoming_unidirectional_streams_.push_back(stream);
vasilvvdfbd3df2019-11-01 11:58:43 -070079 visitor_->OnIncomingUnidirectionalStreamAvailable();
80 }
vasilvvd88f1622019-11-04 13:50:53 -080081 return stream;
vasilvv312e3a52019-10-18 15:06:14 -070082}
83
fayangd58736d2019-11-27 13:35:31 -080084void QuicTransportClientSession::SetDefaultEncryptionLevel(
85 EncryptionLevel level) {
86 QuicSession::SetDefaultEncryptionLevel(level);
87 if (level == ENCRYPTION_FORWARD_SECURE) {
88 SendClientIndication();
89 }
90}
91
renjietangc50cc4a2020-08-17 18:33:30 -070092void QuicTransportClientSession::OnTlsHandshakeComplete() {
93 QuicSession::OnTlsHandshakeComplete();
fayangd18bfb92020-03-19 17:24:21 -070094 SendClientIndication();
95}
96
vasilvvdfbd3df2019-11-01 11:58:43 -070097QuicTransportStream*
98QuicTransportClientSession::AcceptIncomingBidirectionalStream() {
99 if (incoming_bidirectional_streams_.empty()) {
100 return nullptr;
101 }
102 QuicTransportStream* stream = incoming_bidirectional_streams_.front();
103 incoming_bidirectional_streams_.pop_front();
104 return stream;
105}
106
107QuicTransportStream*
108QuicTransportClientSession::AcceptIncomingUnidirectionalStream() {
109 if (incoming_unidirectional_streams_.empty()) {
110 return nullptr;
111 }
112 QuicTransportStream* stream = incoming_unidirectional_streams_.front();
113 incoming_unidirectional_streams_.pop_front();
114 return stream;
115}
116
vasilvvd88f1622019-11-04 13:50:53 -0800117QuicTransportStream*
118QuicTransportClientSession::OpenOutgoingBidirectionalStream() {
119 if (!CanOpenNextOutgoingBidirectionalStream()) {
120 QUIC_BUG << "Attempted to open a stream in violation of flow control";
121 return nullptr;
122 }
123 return CreateStream(GetNextOutgoingBidirectionalStreamId());
124}
125
126QuicTransportStream*
127QuicTransportClientSession::OpenOutgoingUnidirectionalStream() {
128 if (!CanOpenNextOutgoingUnidirectionalStream()) {
129 QUIC_BUG << "Attempted to open a stream in violation of flow control";
130 return nullptr;
131 }
132 return CreateStream(GetNextOutgoingUnidirectionalStreamId());
133}
134
135QuicTransportStream* QuicTransportClientSession::CreateStream(QuicStreamId id) {
136 auto stream = std::make_unique<QuicTransportStream>(id, this, this);
137 QuicTransportStream* stream_ptr = stream.get();
138 ActivateStream(std::move(stream));
139 return stream_ptr;
140}
141
vasilvvddf52472019-10-04 15:14:02 -0700142std::string QuicTransportClientSession::SerializeClientIndication() {
143 std::string serialized_origin = origin_.Serialize();
144 if (serialized_origin.size() > std::numeric_limits<uint16_t>::max()) {
145 QUIC_BUG << "Client origin too long";
vasilvve6472f62019-10-02 06:50:56 -0700146 connection()->CloseConnection(
vasilvvddf52472019-10-04 15:14:02 -0700147 QUIC_INTERNAL_ERROR, "Client origin too long",
148 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
149 return "";
150 }
151 QUIC_DLOG(INFO) << "Sending client indication with origin "
152 << serialized_origin;
153
vasilvve58d0f12019-12-04 14:35:25 -0800154 std::string path = url_.PathForRequest();
155 if (path.size() > std::numeric_limits<uint16_t>::max()) {
156 connection()->CloseConnection(
157 QUIC_TRANSPORT_INVALID_CLIENT_INDICATION, "Requested URL path too long",
158 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
159 return "";
160 }
vasilvvddf52472019-10-04 15:14:02 -0700161
vasilvve58d0f12019-12-04 14:35:25 -0800162 constexpr size_t kPrefixSize =
163 sizeof(QuicTransportClientIndicationKeys) + sizeof(uint16_t);
164 const size_t buffer_size =
165 2 * kPrefixSize + serialized_origin.size() + path.size();
166 if (buffer_size > std::numeric_limits<uint16_t>::max()) {
167 connection()->CloseConnection(
168 QUIC_TRANSPORT_INVALID_CLIENT_INDICATION,
169 "Client indication size limit exceeded",
170 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
171 return "";
172 }
173
174 std::string buffer;
175 buffer.resize(buffer_size);
176 QuicDataWriter writer(buffer.size(), &buffer[0]);
177 bool success =
178 writer.WriteUInt16(
179 static_cast<uint16_t>(QuicTransportClientIndicationKeys::kOrigin)) &&
180 writer.WriteUInt16(serialized_origin.size()) &&
181 writer.WriteStringPiece(serialized_origin) &&
182 writer.WriteUInt16(
183 static_cast<uint16_t>(QuicTransportClientIndicationKeys::kPath)) &&
184 writer.WriteUInt16(path.size()) && writer.WriteStringPiece(path);
185 QUIC_BUG_IF(!success) << "Failed to serialize client indication";
186 QUIC_BUG_IF(writer.length() != buffer.length())
187 << "Serialized client indication has length different from expected";
vasilvvddf52472019-10-04 15:14:02 -0700188 return buffer;
189}
190
191void QuicTransportClientSession::SendClientIndication() {
192 if (!crypto_stream_->encryption_established()) {
193 QUIC_BUG << "Client indication may only be sent once the encryption is "
194 "established.";
195 connection()->CloseConnection(
196 QUIC_INTERNAL_ERROR, "Attempted to send client indication unencrypted",
197 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
198 return;
199 }
vasilvv59dc4b62019-10-11 12:56:14 -0700200 if (ready_) {
vasilvvddf52472019-10-04 15:14:02 -0700201 QUIC_BUG << "Client indication may only be sent once.";
202 connection()->CloseConnection(
203 QUIC_INTERNAL_ERROR, "Attempted to send client indication twice",
vasilvve6472f62019-10-02 06:50:56 -0700204 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
205 return;
206 }
207
vasilvvddf52472019-10-04 15:14:02 -0700208 auto client_indication_owned = std::make_unique<ClientIndication>(
vasilvvd88f1622019-11-04 13:50:53 -0800209 /*stream_id=*/GetNextOutgoingUnidirectionalStreamId(), this,
210 /*is_static=*/false, WRITE_UNIDIRECTIONAL);
211 QUIC_BUG_IF(client_indication_owned->id() != ClientIndicationStream())
212 << "Client indication stream is " << client_indication_owned->id()
213 << " instead of expected " << ClientIndicationStream();
vasilvvddf52472019-10-04 15:14:02 -0700214 ClientIndication* client_indication = client_indication_owned.get();
215 ActivateStream(std::move(client_indication_owned));
vasilvve6472f62019-10-02 06:50:56 -0700216
vasilvvddf52472019-10-04 15:14:02 -0700217 client_indication->WriteOrBufferData(SerializeClientIndication(),
218 /*fin=*/true, nullptr);
219 client_indication_sent_ = true;
vasilvv59dc4b62019-10-11 12:56:14 -0700220
vasilvv467b4222019-12-09 16:22:11 -0800221 // Defense in depth: never set the ready bit unless ALPN has been confirmed.
222 if (!alpn_received_) {
223 QUIC_BUG << "ALPN confirmation missing after handshake complete";
224 connection()->CloseConnection(
225 QUIC_INTERNAL_ERROR,
226 "ALPN confirmation missing after handshake complete",
227 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
228 return;
229 }
230
vasilvv59dc4b62019-10-11 12:56:14 -0700231 // Don't set the ready bit if we closed the connection due to any error
232 // beforehand.
233 if (!connection()->connected()) {
234 return;
235 }
vasilvv467b4222019-12-09 16:22:11 -0800236
vasilvv59dc4b62019-10-11 12:56:14 -0700237 ready_ = true;
vasilvv467b4222019-12-09 16:22:11 -0800238 visitor_->OnSessionReady();
vasilvve6472f62019-10-02 06:50:56 -0700239}
240
vasilvv74b16612020-10-09 11:42:53 -0700241void QuicTransportClientSession::OnMessageReceived(absl::string_view message) {
vasilvvda373d42020-01-16 12:36:27 -0800242 visitor_->OnDatagramReceived(message);
vasilvv2b0ab242020-01-07 07:32:09 -0800243}
244
vasilvvec038f12020-01-07 11:58:08 -0800245void QuicTransportClientSession::OnCanCreateNewOutgoingStream(
246 bool unidirectional) {
247 if (unidirectional) {
248 visitor_->OnCanCreateNewOutgoingUnidirectionalStream();
249 } else {
250 visitor_->OnCanCreateNewOutgoingBidirectionalStream();
251 }
252}
253
vasilvv636b7f22020-08-07 10:37:19 -0700254void QuicTransportClientSession::OnProofValid(
255 const QuicCryptoClientConfig::CachedState& /*cached*/) {}
256
257void QuicTransportClientSession::OnProofVerifyDetailsAvailable(
258 const ProofVerifyDetails& /*verify_details*/) {}
259
vasilvve6472f62019-10-02 06:50:56 -0700260} // namespace quic