1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_SOCKET_TLS_STREAM_ATTEMPT_H_
#define NET_SOCKET_TLS_STREAM_ATTEMPT_H_
#include <memory>
#include <optional>
#include <string_view>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/timer/timer.h"
#include "base/types/expected.h"
#include "base/values.h"
#include "net/base/completion_once_callback.h"
#include "net/base/host_port_pair.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_export.h"
#include "net/socket/stream_attempt.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_config.h"
namespace net {
class TcpStreamAttempt;
class SSLClientSocket;
// Represents a single TLS connection attempt.
class NET_EXPORT_PRIVATE TlsStreamAttempt final : public StreamAttempt {
public:
// Timeout for the TLS handshake. The timeout is the same as SSLConnectJob.
static constexpr base::TimeDelta kTlsHandshakeTimeout = base::Seconds(30);
// Represents an error of getting a SSLConfig for an attempt.
enum class GetSSLConfigError {
// The attempt should abort. Currently this happens when we start an attempt
// without waiting for HTTPS RR and the DNS resolution resulted in making
// the attempt SVCB-reliant.
kAbort,
};
// An interface to interact with TlsStreamAttempt.
class NET_EXPORT_PRIVATE Delegate {
public:
Delegate() = default;
virtual ~Delegate() = default;
Delegate(const Delegate&) = delete;
Delegate& operator=(const Delegate&) = delete;
// Called when TCP handshake completes.
virtual void OnTcpHandshakeComplete() = 0;
// Returns OK when a SSLConfig is immediately available. `callback` is never
// invoked. Otherwise, returns ERR_IO_PENDING when `this` can't provide a
// SSLConfig immediately. `callback` is invoked when a SSLConfig is ready.
virtual int WaitForSSLConfigReady(CompletionOnceCallback callback) = 0;
// Returns a SSLConfig. Should be called only after WaitForSSLConfigReady()
// returns OK or the callback is invoked.
virtual base::expected<SSLConfig, GetSSLConfigError> GetSSLConfig() = 0;
};
// `params` and `ssl_config_provider` must outlive `this`.
TlsStreamAttempt(const StreamAttemptParams* params,
IPEndPoint ip_endpoint,
perfetto::Track track,
HostPortPair host_port_pair,
Delegate* delegate);
TlsStreamAttempt(const TlsStreamAttempt&) = delete;
TlsStreamAttempt& operator=(const TlsStreamAttempt&) = delete;
~TlsStreamAttempt() override;
// StreamAttempt implementations:
LoadState GetLoadState() const override;
base::Value::Dict GetInfoAsValue() const override;
scoped_refptr<SSLCertRequestInfo> GetCertRequestInfo() override;
bool IsTcpHandshakeCompleted() { return tcp_handshake_completed_; }
bool IsTlsHandshakeStarted() { return tls_handshake_started_; }
private:
enum class State {
kNone,
kTcpAttempt,
kTcpAttemptComplete,
kTlsAttempt,
kTlsAttemptComplete,
};
static std::string_view StateToString(State state);
// StreamAttempt methods:
int StartInternal() override;
base::Value::Dict GetNetLogStartParams() override;
void OnIOComplete(int rv);
int DoLoop(int rv);
int DoTcpAttempt();
int DoTcpAttemptComplete(int rv);
int DoTlsAttempt(int rv);
int DoTlsAttemptComplete(int rv);
void OnTlsHandshakeTimeout();
void MaybeRecordTlsHandshakeEnd(int rv);
void ResetStateForRestart();
State next_state_ = State::kNone;
const HostPortPair host_port_pair_;
const raw_ptr<Delegate> delegate_;
std::unique_ptr<TcpStreamAttempt> nested_attempt_;
bool tcp_handshake_completed_ = false;
bool tls_handshake_started_ = false;
base::OneShotTimer tls_handshake_timeout_timer_;
std::unique_ptr<SSLClientSocket> ssl_socket_;
scoped_refptr<SSLCertRequestInfo> ssl_cert_request_info_;
std::optional<SSLConfig> ssl_config_;
std::optional<std::vector<uint8_t>> ech_retry_configs_;
// Set to true when the TlsStreamAttempt retries itself after receiving a
// certificate error when sending TLS Trust Anchor IDs. Used to ensure that we
// only retry once per connection attempt.
bool retried_for_trust_anchor_ids_ = false;
// Used for metrics. Set to true when the initial connection attempt used a
// DNS endpoint that advertised TLS Trust Anchor IDs.
bool trust_anchor_ids_from_dns_ = false;
base::WeakPtrFactory<TlsStreamAttempt> weak_ptr_factory_{this};
};
} // namespace net
#endif // NET_SOCKET_TLS_STREAM_ATTEMPT_H_
|