1 // Copyright (c) 2012 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/core/http/quic_spdy_client_session.h"
6 
7 #include <string>
8 #include <utility>
9 
10 #include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
11 #include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h"
12 #include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
13 #include "net/third_party/quiche/src/quic/core/quic_server_id.h"
14 #include "net/third_party/quiche/src/quic/core/quic_utils.h"
15 #include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
16 #include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
17 #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
18 #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
19 #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
20 
21 namespace quic {
22 
QuicSpdyClientSession(const QuicConfig & config,const ParsedQuicVersionVector & supported_versions,QuicConnection * connection,const QuicServerId & server_id,QuicCryptoClientConfig * crypto_config,QuicClientPushPromiseIndex * push_promise_index)23 QuicSpdyClientSession::QuicSpdyClientSession(
24     const QuicConfig& config,
25     const ParsedQuicVersionVector& supported_versions,
26     QuicConnection* connection,
27     const QuicServerId& server_id,
28     QuicCryptoClientConfig* crypto_config,
29     QuicClientPushPromiseIndex* push_promise_index)
30     : QuicSpdyClientSessionBase(connection,
31                                 push_promise_index,
32                                 config,
33                                 supported_versions),
34       server_id_(server_id),
35       crypto_config_(crypto_config),
36       respect_goaway_(true) {}
37 
38 QuicSpdyClientSession::~QuicSpdyClientSession() = default;
39 
Initialize()40 void QuicSpdyClientSession::Initialize() {
41   crypto_stream_ = CreateQuicCryptoStream();
42   if (config()->HasClientRequestedIndependentOption(kQLVE,
43                                                     Perspective::IS_CLIENT)) {
44     connection()->EnableLegacyVersionEncapsulation(server_id_.host());
45   }
46   QuicSpdyClientSessionBase::Initialize();
47 }
48 
OnProofValid(const QuicCryptoClientConfig::CachedState &)49 void QuicSpdyClientSession::OnProofValid(
50     const QuicCryptoClientConfig::CachedState& /*cached*/) {}
51 
OnProofVerifyDetailsAvailable(const ProofVerifyDetails &)52 void QuicSpdyClientSession::OnProofVerifyDetailsAvailable(
53     const ProofVerifyDetails& /*verify_details*/) {}
54 
ShouldCreateOutgoingBidirectionalStream()55 bool QuicSpdyClientSession::ShouldCreateOutgoingBidirectionalStream() {
56   if (!crypto_stream_->encryption_established()) {
57     QUIC_DLOG(INFO) << "Encryption not active so no outgoing stream created.";
58     return false;
59   }
60   if (goaway_received() && respect_goaway_) {
61     QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. "
62                     << "Already received goaway.";
63     return false;
64   }
65   return CanOpenNextOutgoingBidirectionalStream();
66 }
67 
ShouldCreateOutgoingUnidirectionalStream()68 bool QuicSpdyClientSession::ShouldCreateOutgoingUnidirectionalStream() {
69   QUIC_BUG << "Try to create outgoing unidirectional client data streams";
70   return false;
71 }
72 
73 QuicSpdyClientStream*
CreateOutgoingBidirectionalStream()74 QuicSpdyClientSession::CreateOutgoingBidirectionalStream() {
75   if (!ShouldCreateOutgoingBidirectionalStream()) {
76     return nullptr;
77   }
78   std::unique_ptr<QuicSpdyClientStream> stream = CreateClientStream();
79   QuicSpdyClientStream* stream_ptr = stream.get();
80   ActivateStream(std::move(stream));
81   return stream_ptr;
82 }
83 
84 QuicSpdyClientStream*
CreateOutgoingUnidirectionalStream()85 QuicSpdyClientSession::CreateOutgoingUnidirectionalStream() {
86   QUIC_BUG << "Try to create outgoing unidirectional client data streams";
87   return nullptr;
88 }
89 
90 std::unique_ptr<QuicSpdyClientStream>
CreateClientStream()91 QuicSpdyClientSession::CreateClientStream() {
92   return std::make_unique<QuicSpdyClientStream>(
93       GetNextOutgoingBidirectionalStreamId(), this, BIDIRECTIONAL);
94 }
95 
GetMutableCryptoStream()96 QuicCryptoClientStreamBase* QuicSpdyClientSession::GetMutableCryptoStream() {
97   return crypto_stream_.get();
98 }
99 
GetCryptoStream() const100 const QuicCryptoClientStreamBase* QuicSpdyClientSession::GetCryptoStream()
101     const {
102   return crypto_stream_.get();
103 }
104 
CryptoConnect()105 void QuicSpdyClientSession::CryptoConnect() {
106   DCHECK(flow_controller());
107   crypto_stream_->CryptoConnect();
108 }
109 
GetNumSentClientHellos() const110 int QuicSpdyClientSession::GetNumSentClientHellos() const {
111   return crypto_stream_->num_sent_client_hellos();
112 }
113 
EarlyDataAccepted() const114 bool QuicSpdyClientSession::EarlyDataAccepted() const {
115   return crypto_stream_->EarlyDataAccepted();
116 }
117 
ReceivedInchoateReject() const118 bool QuicSpdyClientSession::ReceivedInchoateReject() const {
119   return crypto_stream_->ReceivedInchoateReject();
120 }
121 
GetNumReceivedServerConfigUpdates() const122 int QuicSpdyClientSession::GetNumReceivedServerConfigUpdates() const {
123   return crypto_stream_->num_scup_messages_received();
124 }
125 
ShouldCreateIncomingStream(QuicStreamId id)126 bool QuicSpdyClientSession::ShouldCreateIncomingStream(QuicStreamId id) {
127   if (!connection()->connected()) {
128     QUIC_BUG << "ShouldCreateIncomingStream called when disconnected";
129     return false;
130   }
131   if (goaway_received() && respect_goaway_) {
132     QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. "
133                     << "Already received goaway.";
134     return false;
135   }
136 
137   if (QuicUtils::IsClientInitiatedStreamId(transport_version(), id)) {
138     QUIC_BUG << "ShouldCreateIncomingStream called with client initiated "
139                 "stream ID.";
140     return false;
141   }
142 
143   if (QuicUtils::IsClientInitiatedStreamId(transport_version(), id)) {
144     QUIC_LOG(WARNING) << "Received invalid push stream id " << id;
145     connection()->CloseConnection(
146         QUIC_INVALID_STREAM_ID,
147         "Server created non write unidirectional stream",
148         ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
149     return false;
150   }
151 
152   if (VersionHasIetfQuicFrames(transport_version()) &&
153       QuicUtils::IsBidirectionalStreamId(id, version())) {
154     connection()->CloseConnection(
155         QUIC_HTTP_SERVER_INITIATED_BIDIRECTIONAL_STREAM,
156         "Server created bidirectional stream.",
157         ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
158     return false;
159   }
160 
161   return true;
162 }
163 
CreateIncomingStream(PendingStream * pending)164 QuicSpdyStream* QuicSpdyClientSession::CreateIncomingStream(
165     PendingStream* pending) {
166   QuicSpdyStream* stream =
167       new QuicSpdyClientStream(pending, this, READ_UNIDIRECTIONAL);
168   ActivateStream(QuicWrapUnique(stream));
169   return stream;
170 }
171 
CreateIncomingStream(QuicStreamId id)172 QuicSpdyStream* QuicSpdyClientSession::CreateIncomingStream(QuicStreamId id) {
173   if (!ShouldCreateIncomingStream(id)) {
174     return nullptr;
175   }
176   QuicSpdyStream* stream =
177       new QuicSpdyClientStream(id, this, READ_UNIDIRECTIONAL);
178   ActivateStream(QuicWrapUnique(stream));
179   return stream;
180 }
181 
182 std::unique_ptr<QuicCryptoClientStreamBase>
CreateQuicCryptoStream()183 QuicSpdyClientSession::CreateQuicCryptoStream() {
184   return std::make_unique<QuicCryptoClientStream>(
185       server_id_, this,
186       crypto_config_->proof_verifier()->CreateDefaultContext(), crypto_config_,
187       this, /*has_application_state = */ version().UsesHttp3());
188 }
189 
IsAuthorized(const std::string &)190 bool QuicSpdyClientSession::IsAuthorized(const std::string& /*authority*/) {
191   return true;
192 }
193 
194 }  // namespace quic
195