blob: d01903c388da24022c05fb1fa4dc681b42610b0b [file] [log] [blame]
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <cstdint>
#include <memory>
#include "absl/strings/string_view.h"
#include "url/gurl.h"
#include "url/origin.h"
#include "quic/core/crypto/quic_crypto_client_config.h"
#include "quic/core/quic_config.h"
#include "quic/core/quic_connection.h"
#include "quic/core/quic_crypto_client_stream.h"
#include "quic/core/quic_crypto_stream.h"
#include "quic/core/quic_datagram_queue.h"
#include "quic/core/quic_server_id.h"
#include "quic/core/quic_session.h"
#include "quic/core/quic_stream.h"
#include "quic/core/quic_versions.h"
#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_containers.h"
#include "quic/quic_transport/quic_transport_protocol.h"
#include "quic/quic_transport/quic_transport_session_interface.h"
#include "quic/quic_transport/quic_transport_stream.h"
namespace quic {
// A client session for the QuicTransport protocol.
class QUIC_EXPORT_PRIVATE QuicTransportClientSession
: public QuicSession,
public QuicTransportSessionInterface,
public QuicCryptoClientStream::ProofHandler {
class QUIC_EXPORT_PRIVATE ClientVisitor {
virtual ~ClientVisitor() {}
// Notifies the visitor when the client indication has been sent and the
// connection is ready to exchange application data.
virtual void OnSessionReady() = 0;
// Notifies the visitor when a new stream has been received. The stream in
// question can be retrieved using AcceptIncomingBidirectionalStream() or
// AcceptIncomingUnidirectionalStream().
virtual void OnIncomingBidirectionalStreamAvailable() = 0;
virtual void OnIncomingUnidirectionalStreamAvailable() = 0;
// Notifies the visitor when a new datagram has been received.
virtual void OnDatagramReceived(absl::string_view datagram) = 0;
// Notifies the visitor that a new outgoing stream can now be created.
virtual void OnCanCreateNewOutgoingBidirectionalStream() = 0;
virtual void OnCanCreateNewOutgoingUnidirectionalStream() = 0;
QuicConnection* connection,
Visitor* owner,
const QuicConfig& config,
const ParsedQuicVersionVector& supported_versions,
const GURL& url,
QuicCryptoClientConfig* crypto_config,
url::Origin origin,
ClientVisitor* visitor,
std::unique_ptr<QuicDatagramQueue::Observer> datagram_observer);
std::vector<std::string> GetAlpnsToOffer() const override {
return std::vector<std::string>({QuicTransportAlpn()});
void OnAlpnSelected(absl::string_view alpn) override;
bool alpn_received() const { return alpn_received_; }
void CryptoConnect() { crypto_stream_->CryptoConnect(); }
bool ShouldKeepConnectionAlive() const override { return true; }
QuicCryptoStream* GetMutableCryptoStream() override {
return crypto_stream_.get();
const QuicCryptoStream* GetCryptoStream() const override {
return crypto_stream_.get();
// Returns true once the encryption has been established and the client
// indication has been sent. No application data will be read or written
// before the connection is ready. Once the connection becomes ready, this
// method will never return false.
bool IsSessionReady() const override { return ready_; }
QuicStream* CreateIncomingStream(QuicStreamId id) override;
QuicStream* CreateIncomingStream(PendingStream* /*pending*/) override {
QUIC_BUG << "QuicTransportClientSession::CreateIncomingStream("
"PendingStream) not implemented";
return nullptr;
void SetDefaultEncryptionLevel(EncryptionLevel level) override;
void OnTlsHandshakeComplete() override;
void OnMessageReceived(absl::string_view message) override;
// Return the earliest incoming stream that has been received by the session
// but has not been accepted. Returns nullptr if there are no incoming
// streams.
QuicTransportStream* AcceptIncomingBidirectionalStream();
QuicTransportStream* AcceptIncomingUnidirectionalStream();
using QuicSession::CanOpenNextOutgoingBidirectionalStream;
using QuicSession::CanOpenNextOutgoingUnidirectionalStream;
QuicTransportStream* OpenOutgoingBidirectionalStream();
QuicTransportStream* OpenOutgoingUnidirectionalStream();
using QuicSession::datagram_queue;
// QuicCryptoClientStream::ProofHandler implementation.
void OnProofValid(const QuicCryptoClientConfig::CachedState& cached) override;
void OnProofVerifyDetailsAvailable(
const ProofVerifyDetails& verify_details) override;
class QUIC_EXPORT_PRIVATE ClientIndication : public QuicStream {
using QuicStream::QuicStream;
// This method should never be called, since the stream is client-initiated
// unidirectional.
void OnDataAvailable() override {
QUIC_BUG << "Received data on a write-only stream";
// Creates and activates a QuicTransportStream for the given ID.
QuicTransportStream* CreateStream(QuicStreamId id);
// Serializes the client indication as described in
std::string SerializeClientIndication();
// Creates the client indication stream and sends the client indication on it.
void SendClientIndication();
void OnCanCreateNewOutgoingStream(bool unidirectional) override;
std::unique_ptr<QuicCryptoClientStream> crypto_stream_;
GURL url_;
url::Origin origin_;
ClientVisitor* visitor_; // not owned
bool client_indication_sent_ = false;
bool alpn_received_ = false;
bool ready_ = false;
// Contains all of the streams that has been received by the session but have
// not been processed by the application.
// TODO(vasilvv): currently, we always send MAX_STREAMS as long as the overall
// maximum number of streams for the connection has not been exceeded. We
// should also limit the maximum number of streams that the consuming code
// has not accepted to a smaller number, by checking the size of
// |incoming_bidirectional_streams_| and |incoming_unidirectional_streams_|
// before sending MAX_STREAMS.
QuicCircularDeque<QuicTransportStream*> incoming_bidirectional_streams_;
QuicCircularDeque<QuicTransportStream*> incoming_unidirectional_streams_;
} // namespace quic