xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_generic_session.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2023 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 "quiche/quic/core/quic_generic_session.h"
6 
7 #include <cstdint>
8 #include <memory>
9 #include <string>
10 #include <utility>
11 
12 #include "absl/strings/string_view.h"
13 #include "quiche/quic/core/http/web_transport_stream_adapter.h"
14 #include "quiche/quic/core/quic_crypto_client_stream.h"
15 #include "quiche/quic/core/quic_session.h"
16 #include "quiche/quic/core/quic_types.h"
17 #include "quiche/quic/core/quic_utils.h"
18 #include "quiche/quic/core/quic_versions.h"
19 #include "quiche/quic/platform/api/quic_bug_tracker.h"
20 #include "quiche/quic/platform/api/quic_logging.h"
21 #include "quiche/common/simple_buffer_allocator.h"
22 #include "quiche/web_transport/web_transport.h"
23 
24 namespace quic {
25 
26 namespace {
27 
28 class NoOpProofHandler : public QuicCryptoClientStream::ProofHandler {
29  public:
OnProofValid(const QuicCryptoClientConfig::CachedState &)30   void OnProofValid(const QuicCryptoClientConfig::CachedState&) override {}
OnProofVerifyDetailsAvailable(const ProofVerifyDetails &)31   void OnProofVerifyDetailsAvailable(const ProofVerifyDetails&) override {}
32 };
33 
34 class NoOpServerCryptoHelper : public QuicCryptoServerStreamBase::Helper {
35  public:
CanAcceptClientHello(const CryptoHandshakeMessage &,const QuicSocketAddress &,const QuicSocketAddress &,const QuicSocketAddress &,std::string *) const36   bool CanAcceptClientHello(const CryptoHandshakeMessage& /*message*/,
37                             const QuicSocketAddress& /*client_address*/,
38                             const QuicSocketAddress& /*peer_address*/,
39                             const QuicSocketAddress& /*self_address*/,
40                             std::string* /*error_details*/) const override {
41     return true;
42   }
43 };
44 
45 }  // namespace
46 
GetQuicVersionsForGenericSession()47 ParsedQuicVersionVector GetQuicVersionsForGenericSession() {
48   return {ParsedQuicVersion::RFCv1()};
49 }
50 
51 // QuicGenericStream is a stream that provides a general-purpose implementation
52 // of a webtransport::Stream interface.
53 class QUICHE_EXPORT QuicGenericStream : public QuicStream {
54  public:
QuicGenericStream(QuicStreamId id,QuicSession * session)55   QuicGenericStream(QuicStreamId id, QuicSession* session)
56       : QuicStream(id, session, /*is_static=*/false,
57                    QuicUtils::GetStreamType(
58                        id, session->connection()->perspective(),
59                        session->IsIncomingStream(id), session->version())),
60         adapter_(session, this, sequencer()) {}
61 
adapter()62   WebTransportStreamAdapter* adapter() { return &adapter_; }
63 
64   // QuicSession method implementations.
OnDataAvailable()65   void OnDataAvailable() override { adapter_.OnDataAvailable(); }
OnCanWriteNewData()66   void OnCanWriteNewData() override { adapter_.OnCanWriteNewData(); }
67 
68  private:
69   WebTransportStreamAdapter adapter_;
70 };
71 
QuicGenericSessionBase(QuicConnection * connection,bool owns_connection,Visitor * owner,const QuicConfig & config,std::string alpn,WebTransportVisitor * visitor,bool owns_visitor,std::unique_ptr<QuicDatagramQueue::Observer> datagram_observer)72 QuicGenericSessionBase::QuicGenericSessionBase(
73     QuicConnection* connection, bool owns_connection, Visitor* owner,
74     const QuicConfig& config, std::string alpn, WebTransportVisitor* visitor,
75     bool owns_visitor,
76     std::unique_ptr<QuicDatagramQueue::Observer> datagram_observer)
77     : QuicSession(connection, owner, config, GetQuicVersionsForGenericSession(),
78                   /*num_expected_unidirectional_static_streams=*/0,
79                   std::move(datagram_observer)),
80       alpn_(std::move(alpn)),
81       visitor_(visitor),
82       owns_connection_(owns_connection),
83       owns_visitor_(owns_visitor) {}
84 
~QuicGenericSessionBase()85 QuicGenericSessionBase::~QuicGenericSessionBase() {
86   if (owns_connection_) {
87     DeleteConnection();
88   }
89   if (owns_visitor_) {
90     delete visitor_;
91     visitor_ = nullptr;
92   }
93 }
94 
CreateIncomingStream(QuicStreamId id)95 QuicStream* QuicGenericSessionBase::CreateIncomingStream(QuicStreamId id) {
96   QUIC_DVLOG(1) << "Creating incoming QuicGenricStream " << id;
97   QuicGenericStream* stream = CreateStream(id);
98   if (stream->type() == BIDIRECTIONAL) {
99     incoming_bidirectional_streams_.push_back(id);
100     visitor_->OnIncomingBidirectionalStreamAvailable();
101   } else {
102     incoming_unidirectional_streams_.push_back(id);
103     visitor_->OnIncomingUnidirectionalStreamAvailable();
104   }
105   return stream;
106 }
107 
OnTlsHandshakeComplete()108 void QuicGenericSessionBase::OnTlsHandshakeComplete() {
109   QuicSession::OnTlsHandshakeComplete();
110   visitor_->OnSessionReady();
111 }
112 
113 webtransport::Stream*
AcceptIncomingBidirectionalStream()114 QuicGenericSessionBase::AcceptIncomingBidirectionalStream() {
115   while (!incoming_bidirectional_streams_.empty()) {
116     webtransport::Stream* stream =
117         GetStreamById(incoming_bidirectional_streams_.front());
118     incoming_bidirectional_streams_.pop_front();
119     if (stream != nullptr) {
120       return stream;
121     }
122   }
123   return nullptr;
124 }
125 
126 webtransport::Stream*
AcceptIncomingUnidirectionalStream()127 QuicGenericSessionBase::AcceptIncomingUnidirectionalStream() {
128   while (!incoming_unidirectional_streams_.empty()) {
129     webtransport::Stream* stream =
130         GetStreamById(incoming_unidirectional_streams_.front());
131     incoming_unidirectional_streams_.pop_front();
132     if (stream != nullptr) {
133       return stream;
134     }
135   }
136   return nullptr;
137 }
138 
139 webtransport::Stream*
OpenOutgoingBidirectionalStream()140 QuicGenericSessionBase::OpenOutgoingBidirectionalStream() {
141   if (!CanOpenNextOutgoingBidirectionalStream()) {
142     QUIC_BUG(QuicGenericSessionBase_flow_control_violation_bidi)
143         << "Attempted to open a stream in violation of flow control";
144     return nullptr;
145   }
146   return CreateStream(GetNextOutgoingBidirectionalStreamId())->adapter();
147 }
148 
149 webtransport::Stream*
OpenOutgoingUnidirectionalStream()150 QuicGenericSessionBase::OpenOutgoingUnidirectionalStream() {
151   if (!CanOpenNextOutgoingUnidirectionalStream()) {
152     QUIC_BUG(QuicGenericSessionBase_flow_control_violation_unidi)
153         << "Attempted to open a stream in violation of flow control";
154     return nullptr;
155   }
156   return CreateStream(GetNextOutgoingUnidirectionalStreamId())->adapter();
157 }
158 
CreateStream(QuicStreamId id)159 QuicGenericStream* QuicGenericSessionBase::CreateStream(QuicStreamId id) {
160   auto stream = std::make_unique<QuicGenericStream>(id, this);
161   QuicGenericStream* stream_ptr = stream.get();
162   ActivateStream(std::move(stream));
163   return stream_ptr;
164 }
165 
OnMessageReceived(absl::string_view message)166 void QuicGenericSessionBase::OnMessageReceived(absl::string_view message) {
167   visitor_->OnDatagramReceived(message);
168 }
169 
OnCanCreateNewOutgoingStream(bool unidirectional)170 void QuicGenericSessionBase::OnCanCreateNewOutgoingStream(bool unidirectional) {
171   if (unidirectional) {
172     visitor_->OnCanCreateNewOutgoingUnidirectionalStream();
173   } else {
174     visitor_->OnCanCreateNewOutgoingBidirectionalStream();
175   }
176 }
177 
GetStreamById(webtransport::StreamId id)178 webtransport::Stream* QuicGenericSessionBase::GetStreamById(
179     webtransport::StreamId id) {
180   QuicStream* stream = GetActiveStream(id);
181   if (stream == nullptr) {
182     return nullptr;
183   }
184   return static_cast<QuicGenericStream*>(stream)->adapter();
185 }
186 
SendOrQueueDatagram(absl::string_view datagram)187 webtransport::DatagramStatus QuicGenericSessionBase::SendOrQueueDatagram(
188     absl::string_view datagram) {
189   quiche::QuicheBuffer buffer = quiche::QuicheBuffer::Copy(
190       quiche::SimpleBufferAllocator::Get(), datagram);
191   return MessageStatusToWebTransportStatus(
192       datagram_queue()->SendOrQueueDatagram(
193           quiche::QuicheMemSlice(std::move(buffer))));
194 }
195 
OnConnectionClosed(const QuicConnectionCloseFrame & frame,ConnectionCloseSource source)196 void QuicGenericSessionBase::OnConnectionClosed(
197     const QuicConnectionCloseFrame& frame, ConnectionCloseSource source) {
198   QuicSession::OnConnectionClosed(frame, source);
199   visitor_->OnSessionClosed(static_cast<webtransport::SessionErrorCode>(
200                                 frame.transport_close_frame_type),
201                             frame.error_details);
202 }
203 
QuicGenericClientSession(QuicConnection * connection,bool owns_connection,Visitor * owner,const QuicConfig & config,std::string host,uint16_t port,std::string alpn,webtransport::SessionVisitor * visitor,bool owns_visitor,std::unique_ptr<QuicDatagramQueue::Observer> datagram_observer,QuicCryptoClientConfig * crypto_config)204 QuicGenericClientSession::QuicGenericClientSession(
205     QuicConnection* connection, bool owns_connection, Visitor* owner,
206     const QuicConfig& config, std::string host, uint16_t port, std::string alpn,
207     webtransport::SessionVisitor* visitor, bool owns_visitor,
208     std::unique_ptr<QuicDatagramQueue::Observer> datagram_observer,
209     QuicCryptoClientConfig* crypto_config)
210     : QuicGenericSessionBase(connection, owns_connection, owner, config,
211                              std::move(alpn), visitor, owns_visitor,
212                              std::move(datagram_observer)) {
213   static NoOpProofHandler* handler = new NoOpProofHandler();
214   crypto_stream_ = std::make_unique<QuicCryptoClientStream>(
215       QuicServerId(std::move(host), port), this,
216       crypto_config->proof_verifier()->CreateDefaultContext(), crypto_config,
217       /*proof_handler=*/handler, /*has_application_state=*/false);
218 }
219 
QuicGenericClientSession(QuicConnection * connection,bool owns_connection,Visitor * owner,const QuicConfig & config,std::string host,uint16_t port,std::string alpn,CreateWebTransportSessionVisitorCallback create_visitor_callback,std::unique_ptr<QuicDatagramQueue::Observer> datagram_observer,QuicCryptoClientConfig * crypto_config)220 QuicGenericClientSession::QuicGenericClientSession(
221     QuicConnection* connection, bool owns_connection, Visitor* owner,
222     const QuicConfig& config, std::string host, uint16_t port, std::string alpn,
223     CreateWebTransportSessionVisitorCallback create_visitor_callback,
224     std::unique_ptr<QuicDatagramQueue::Observer> datagram_observer,
225     QuicCryptoClientConfig* crypto_config)
226     : QuicGenericClientSession(
227           connection, owns_connection, owner, config, std::move(host), port,
228           std::move(alpn), std::move(create_visitor_callback)(*this).release(),
229           /*owns_visitor=*/true, std::move(datagram_observer), crypto_config) {}
230 
QuicGenericServerSession(QuicConnection * connection,bool owns_connection,Visitor * owner,const QuicConfig & config,std::string alpn,webtransport::SessionVisitor * visitor,bool owns_visitor,std::unique_ptr<QuicDatagramQueue::Observer> datagram_observer,const QuicCryptoServerConfig * crypto_config,QuicCompressedCertsCache * compressed_certs_cache)231 QuicGenericServerSession::QuicGenericServerSession(
232     QuicConnection* connection, bool owns_connection, Visitor* owner,
233     const QuicConfig& config, std::string alpn,
234     webtransport::SessionVisitor* visitor, bool owns_visitor,
235     std::unique_ptr<QuicDatagramQueue::Observer> datagram_observer,
236     const QuicCryptoServerConfig* crypto_config,
237     QuicCompressedCertsCache* compressed_certs_cache)
238     : QuicGenericSessionBase(connection, owns_connection, owner, config,
239                              std::move(alpn), visitor, owns_visitor,
240                              std::move(datagram_observer)) {
241   static NoOpServerCryptoHelper* helper = new NoOpServerCryptoHelper();
242   crypto_stream_ = CreateCryptoServerStream(
243       crypto_config, compressed_certs_cache, this, helper);
244 }
245 
QuicGenericServerSession(QuicConnection * connection,bool owns_connection,Visitor * owner,const QuicConfig & config,std::string alpn,CreateWebTransportSessionVisitorCallback create_visitor_callback,std::unique_ptr<QuicDatagramQueue::Observer> datagram_observer,const QuicCryptoServerConfig * crypto_config,QuicCompressedCertsCache * compressed_certs_cache)246 QuicGenericServerSession::QuicGenericServerSession(
247     QuicConnection* connection, bool owns_connection, Visitor* owner,
248     const QuicConfig& config, std::string alpn,
249     CreateWebTransportSessionVisitorCallback create_visitor_callback,
250     std::unique_ptr<QuicDatagramQueue::Observer> datagram_observer,
251     const QuicCryptoServerConfig* crypto_config,
252     QuicCompressedCertsCache* compressed_certs_cache)
253     : QuicGenericServerSession(
254           connection, owns_connection, owner, config, std::move(alpn),
255           std::move(create_visitor_callback)(*this).release(),
256           /*owns_visitor=*/true, std::move(datagram_observer), crypto_config,
257           compressed_certs_cache) {}
258 
259 }  // namespace quic
260