| Index: net/quic/quartc/quartc_session.cc
|
| diff --git a/net/quic/quartc/quartc_session.cc b/net/quic/quartc/quartc_session.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..72d1c873ced42b20715eea1be695fd4d32751950
|
| --- /dev/null
|
| +++ b/net/quic/quartc/quartc_session.cc
|
| @@ -0,0 +1,288 @@
|
| +// Copyright (c) 2016 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 "net/quic/quartc/quartc_session.h"
|
| +
|
| +#include "base/rand_util.h"
|
| +
|
| +namespace {
|
| +
|
| +// Default priority for incoming QUIC streams.
|
| +// TODO(zhihuang): Determine if this value is correct.
|
| +static const net::SpdyPriority kDefaultPriority = 3;
|
| +
|
| +// Arbitrary server port number for net::QuicCryptoClientConfig.
|
| +const int kQuicServerPort = 0;
|
| +
|
| +// Length of HKDF input keying material, equal to its number of bytes.
|
| +// https://tools.ietf.org/html/rfc5869#section-2.2.
|
| +// TODO(zhihuang): Verify that input keying material length is correct.
|
| +const size_t kInputKeyingMaterialLength = 32;
|
| +
|
| +// Used by QuicCryptoServerConfig to provide dummy proof credentials.
|
| +// TODO(zhihuang): Remove when secure P2P QUIC handshake is possible.
|
| +class DummyProofSource : public net::ProofSource {
|
| + public:
|
| + DummyProofSource() {}
|
| + ~DummyProofSource() override {}
|
| +
|
| + // ProofSource override.
|
| + bool GetProof(const net::IPAddress& server_ip,
|
| + const std::string& hostname,
|
| + const std::string& server_config,
|
| + net::QuicVersion quic_version,
|
| + base::StringPiece chlo_hash,
|
| + scoped_refptr<net::ProofSource::Chain>* out_chain,
|
| + std::string* out_signature,
|
| + std::string* out_leaf_cert_sct) override {
|
| + std::vector<std::string> certs;
|
| + certs.push_back("Dummy cert");
|
| + *out_chain = new ProofSource::Chain(certs);
|
| + *out_signature = "Dummy signature";
|
| + *out_leaf_cert_sct = "Dummy timestamp";
|
| + return true;
|
| + }
|
| +
|
| + void GetProof(const net::IPAddress& server_ip,
|
| + const std::string& hostname,
|
| + const std::string& server_config,
|
| + net::QuicVersion quic_version,
|
| + base::StringPiece chlo_hash,
|
| + std::unique_ptr<Callback> callback) override {}
|
| +};
|
| +
|
| +// Used by QuicCryptoClientConfig to ignore the peer's credentials
|
| +// and establish an insecure QUIC connection.
|
| +// TODO(zhihuang): Remove when secure P2P QUIC handshake is possible.
|
| +class InsecureProofVerifier : public net::ProofVerifier {
|
| + public:
|
| + InsecureProofVerifier() {}
|
| + ~InsecureProofVerifier() override {}
|
| +
|
| + // ProofVerifier override.
|
| + net::QuicAsyncStatus VerifyProof(
|
| + const std::string& hostname,
|
| + const uint16_t port,
|
| + const std::string& server_config,
|
| + net::QuicVersion quic_version,
|
| + base::StringPiece chlo_hash,
|
| + const std::vector<std::string>& certs,
|
| + const std::string& cert_sct,
|
| + const std::string& signature,
|
| + const net::ProofVerifyContext* context,
|
| + std::string* error_details,
|
| + std::unique_ptr<net::ProofVerifyDetails>* verify_details,
|
| + std::unique_ptr<net::ProofVerifierCallback> callback) override {
|
| + return net::QUIC_SUCCESS;
|
| + }
|
| +
|
| + net::QuicAsyncStatus VerifyCertChain(
|
| + const std::string& hostname,
|
| + const std::vector<std::string>& certs,
|
| + const net::ProofVerifyContext* context,
|
| + std::string* error_details,
|
| + std::unique_ptr<net::ProofVerifyDetails>* details,
|
| + std::unique_ptr<net::ProofVerifierCallback> callback) override {
|
| + return net::QUIC_SUCCESS;
|
| + }
|
| +};
|
| +}
|
| +
|
| +namespace net {
|
| +
|
| +QuicConnectionId QuartcCryptoServerStreamHelper::GenerateConnectionIdForReject(
|
| + QuicConnectionId connection_id) const {
|
| + return 0;
|
| +}
|
| +
|
| +bool QuartcCryptoServerStreamHelper::CanAcceptClientHello(
|
| + const CryptoHandshakeMessage& message,
|
| + const IPEndPoint& self_address,
|
| + std::string* error_details) const {
|
| + return true;
|
| +}
|
| +
|
| +QuartcSession::QuartcSession(std::unique_ptr<QuicConnection> connection,
|
| + const QuicConfig& config,
|
| + const std::string& unique_remote_server_id,
|
| + Perspective perspective,
|
| + QuicConnectionHelperInterface* helper)
|
| + : QuicSession(connection.get(), config),
|
| + unique_remote_server_id_(unique_remote_server_id),
|
| + perspective_(perspective),
|
| + connection_(std::move(connection)),
|
| + helper_(helper) {
|
| + // Initialization with default crypto configuration.
|
| + if (perspective_ == Perspective::IS_CLIENT) {
|
| + std::unique_ptr<ProofVerifier> proof_verifier(new InsecureProofVerifier);
|
| + quic_crypto_client_config_.reset(
|
| + new QuicCryptoClientConfig(std::move(proof_verifier)));
|
| + } else {
|
| + std::unique_ptr<ProofSource> proof_source(new DummyProofSource);
|
| + std::string source_address_token_secret =
|
| + base::RandBytesAsString(kInputKeyingMaterialLength);
|
| + quic_crypto_server_config_.reset(new QuicCryptoServerConfig(
|
| + source_address_token_secret, helper_->GetRandomGenerator(),
|
| + std::move(proof_source)));
|
| + // Provide server with serialized config string to prove ownership.
|
| + QuicCryptoServerConfig::ConfigOptions options;
|
| + quic_crypto_server_config_->AddDefaultConfig(helper_->GetRandomGenerator(),
|
| + helper_->GetClock(), options);
|
| + }
|
| +}
|
| +
|
| +QuartcSession::~QuartcSession() {}
|
| +
|
| +QuicCryptoStream* QuartcSession::GetCryptoStream() {
|
| + return crypto_stream_.get();
|
| +}
|
| +
|
| +QuartcStream* QuartcSession::CreateOutgoingDynamicStream(
|
| + SpdyPriority priority) {
|
| + return CreateDataStream(GetNextOutgoingStreamId(), priority);
|
| +}
|
| +
|
| +void QuartcSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
|
| + QuicSession::OnCryptoHandshakeEvent(event);
|
| + if (event == HANDSHAKE_CONFIRMED) {
|
| + DCHECK(IsEncryptionEstablished());
|
| + DCHECK(IsCryptoHandshakeConfirmed());
|
| +
|
| + DCHECK(session_delegate_);
|
| + session_delegate_->OnCryptoHandshakeComplete();
|
| + }
|
| +}
|
| +
|
| +void QuartcSession::CloseStream(QuicStreamId stream_id) {
|
| + if (IsClosedStream(stream_id)) {
|
| + // When CloseStream has been called recursively (via
|
| + // ReliableQuicStream::OnClose), the stream is already closed so return.
|
| + return;
|
| + }
|
| + write_blocked_streams()->UnregisterStream(stream_id);
|
| + QuicSession::CloseStream(stream_id);
|
| +}
|
| +
|
| +void QuartcSession::OnConnectionClosed(QuicErrorCode error,
|
| + const std::string& error_details,
|
| + ConnectionCloseSource source) {
|
| + QuicSession::OnConnectionClosed(error, error_details, source);
|
| + DCHECK(session_delegate_);
|
| + session_delegate_->OnConnectionClosed(
|
| + error, source == ConnectionCloseSource::FROM_PEER);
|
| +}
|
| +
|
| +void QuartcSession::StartCryptoHandshake() {
|
| + if (perspective_ == Perspective::IS_CLIENT) {
|
| + QuicServerId server_id(unique_remote_server_id_, kQuicServerPort);
|
| + QuicCryptoClientStream* crypto_stream =
|
| + new QuicCryptoClientStream(server_id, this, new ProofVerifyContext(),
|
| + quic_crypto_client_config_.get(), this);
|
| + crypto_stream_.reset(crypto_stream);
|
| + QuicSession::Initialize();
|
| + crypto_stream->CryptoConnect();
|
| + } else {
|
| + quic_compressed_certs_cache_.reset(new QuicCompressedCertsCache(
|
| + QuicCompressedCertsCache::kQuicCompressedCertsCacheSize));
|
| + bool use_stateless_rejects_if_peer_supported = false;
|
| + QuicCryptoServerStream* crypto_stream = new QuicCryptoServerStream(
|
| + quic_crypto_server_config_.get(), quic_compressed_certs_cache_.get(),
|
| + use_stateless_rejects_if_peer_supported, this, &stream_helper_);
|
| + crypto_stream_.reset(crypto_stream);
|
| + QuicSession::Initialize();
|
| + }
|
| +}
|
| +
|
| +bool QuartcSession::ExportKeyingMaterial(const std::string& label,
|
| + const uint8_t* context,
|
| + size_t context_len,
|
| + bool used_context,
|
| + uint8_t* result,
|
| + size_t result_len) {
|
| + std::string quic_context(reinterpret_cast<const char*>(context), context_len);
|
| + std::string quic_result;
|
| + bool success = crypto_stream_->ExportKeyingMaterial(label, quic_context,
|
| + result_len, &quic_result);
|
| + quic_result.copy(reinterpret_cast<char*>(result), result_len);
|
| + DCHECK(quic_result.length() == result_len);
|
| + return success;
|
| +}
|
| +
|
| +QuartcStreamInterface* QuartcSession::CreateOutgoingStream(
|
| + const OutgoingStreamParameters& param) {
|
| + // The |param| is for forward-compatibility. Not used for now.
|
| + return CreateOutgoingDynamicStream(kDefaultPriority);
|
| +}
|
| +
|
| +void QuartcSession::SetDelegate(
|
| + QuartcSessionInterface::Delegate* session_delegate) {
|
| + if (session_delegate_) {
|
| + LOG(WARNING) << "The delegate for the session has already been set.";
|
| + }
|
| + session_delegate_ = session_delegate;
|
| + DCHECK(session_delegate_);
|
| +}
|
| +
|
| +void QuartcSession::OnTransportCanWrite() {
|
| + if (HasDataToWrite()) {
|
| + connection()->OnCanWrite();
|
| + }
|
| +}
|
| +
|
| +bool QuartcSession::OnTransportReceived(const char* data, size_t data_len) {
|
| + QuicReceivedPacket packet(data, data_len, clock_.Now());
|
| + ProcessUdpPacket(connection()->self_address(), connection()->peer_address(),
|
| + packet);
|
| + return true;
|
| +}
|
| +
|
| +void QuartcSession::OnProofValid(
|
| + const QuicCryptoClientConfig::CachedState& cached) {
|
| + // TODO(zhihuang): Handle the proof verification.
|
| +}
|
| +
|
| +void QuartcSession::OnProofVerifyDetailsAvailable(
|
| + const ProofVerifyDetails& verify_details) {
|
| + // TODO(zhihuang): Handle the proof verification.
|
| +}
|
| +
|
| +void QuartcSession::SetClientCryptoConfig(
|
| + QuicCryptoClientConfig* client_config) {
|
| + quic_crypto_client_config_.reset(client_config);
|
| +}
|
| +
|
| +void QuartcSession::SetServerCryptoConfig(
|
| + QuicCryptoServerConfig* server_config) {
|
| + quic_crypto_server_config_.reset(server_config);
|
| +}
|
| +
|
| +ReliableQuicStream* QuartcSession::CreateIncomingDynamicStream(
|
| + QuicStreamId id) {
|
| + QuartcStream* stream = CreateDataStream(id, kDefaultPriority);
|
| + if (stream) {
|
| + DCHECK(session_delegate_);
|
| + session_delegate_->OnIncomingStream(stream);
|
| + }
|
| + return stream;
|
| +}
|
| +
|
| +QuartcStream* QuartcSession::CreateDataStream(QuicStreamId id,
|
| + SpdyPriority priority) {
|
| + if (crypto_stream_ == nullptr || !crypto_stream_->encryption_established()) {
|
| + // Encryption not active so no stream created
|
| + return nullptr;
|
| + }
|
| + QuartcStream* stream = new QuartcStream(id, this);
|
| + if (stream) {
|
| + // Make QuicSession take ownership of the stream.
|
| + ActivateStream(stream);
|
| + // Register the stream to the QuicWriteBlockedList. |priority| is clamped
|
| + // between 0 and 7, with 0 being the highest priority and 7 the lowest
|
| + // priority.
|
| + write_blocked_streams()->RegisterStream(stream->id(), priority);
|
| + }
|
| + return stream;
|
| +}
|
| +
|
| +} // namespace net
|
|
|