| // Copyright 2018 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/socket/connect_job.h" |
| |
| #include <set> |
| #include <utility> |
| |
| #include "net/base/connection_endpoint_metadata.h" |
| #include "net/base/net_errors.h" |
| #include "net/base/trace_constants.h" |
| #include "net/base/tracing.h" |
| #include "net/dns/public/host_resolver_results.h" |
| #include "net/dns/public/secure_dns_policy.h" |
| #include "net/http/http_auth_controller.h" |
| #include "net/http/http_proxy_connect_job.h" |
| #include "net/log/net_log.h" |
| #include "net/log/net_log_event_type.h" |
| #include "net/socket/client_socket_handle.h" |
| #include "net/socket/socket_tag.h" |
| #include "net/socket/socks_connect_job.h" |
| #include "net/socket/ssl_connect_job.h" |
| #include "net/socket/stream_socket.h" |
| #include "net/socket/transport_connect_job.h" |
| #include "net/traffic_annotation/network_traffic_annotation.h" |
| |
| namespace net { |
| |
| CommonConnectJobParams::CommonConnectJobParams( |
| ClientSocketFactory* client_socket_factory, |
| HostResolver* host_resolver, |
| HttpAuthCache* http_auth_cache, |
| HttpAuthHandlerFactory* http_auth_handler_factory, |
| SpdySessionPool* spdy_session_pool, |
| const quic::ParsedQuicVersionVector* quic_supported_versions, |
| QuicStreamFactory* quic_stream_factory, |
| ProxyDelegate* proxy_delegate, |
| const HttpUserAgentSettings* http_user_agent_settings, |
| SSLClientContext* ssl_client_context, |
| SocketPerformanceWatcherFactory* socket_performance_watcher_factory, |
| NetworkQualityEstimator* network_quality_estimator, |
| NetLog* net_log, |
| WebSocketEndpointLockManager* websocket_endpoint_lock_manager) |
| : client_socket_factory(client_socket_factory), |
| host_resolver(host_resolver), |
| http_auth_cache(http_auth_cache), |
| http_auth_handler_factory(http_auth_handler_factory), |
| spdy_session_pool(spdy_session_pool), |
| quic_supported_versions(quic_supported_versions), |
| quic_stream_factory(quic_stream_factory), |
| proxy_delegate(proxy_delegate), |
| http_user_agent_settings(http_user_agent_settings), |
| ssl_client_context(ssl_client_context), |
| socket_performance_watcher_factory(socket_performance_watcher_factory), |
| network_quality_estimator(network_quality_estimator), |
| net_log(net_log), |
| websocket_endpoint_lock_manager(websocket_endpoint_lock_manager) {} |
| |
| CommonConnectJobParams::CommonConnectJobParams( |
| const CommonConnectJobParams& other) = default; |
| |
| CommonConnectJobParams::~CommonConnectJobParams() = default; |
| |
| CommonConnectJobParams& CommonConnectJobParams::operator=( |
| const CommonConnectJobParams& other) = default; |
| |
| ConnectJob::ConnectJob(RequestPriority priority, |
| const SocketTag& socket_tag, |
| base::TimeDelta timeout_duration, |
| const CommonConnectJobParams* common_connect_job_params, |
| Delegate* delegate, |
| const NetLogWithSource* net_log, |
| NetLogSourceType net_log_source_type, |
| NetLogEventType net_log_connect_event_type) |
| : timeout_duration_(timeout_duration), |
| priority_(priority), |
| socket_tag_(socket_tag), |
| common_connect_job_params_(common_connect_job_params), |
| delegate_(delegate), |
| top_level_job_(net_log == nullptr), |
| net_log_(net_log |
| ? *net_log |
| : NetLogWithSource::Make(common_connect_job_params->net_log, |
| net_log_source_type)), |
| net_log_connect_event_type_(net_log_connect_event_type) { |
| DCHECK(delegate); |
| if (top_level_job_) |
| net_log_.BeginEvent(NetLogEventType::CONNECT_JOB); |
| } |
| |
| ConnectJob::~ConnectJob() { |
| // Log end of Connect event if ConnectJob was still in-progress when |
| // destroyed. |
| if (delegate_) |
| LogConnectCompletion(ERR_ABORTED); |
| if (top_level_job_) |
| net_log().EndEvent(NetLogEventType::CONNECT_JOB); |
| } |
| |
| std::unique_ptr<StreamSocket> ConnectJob::PassSocket() { |
| return std::move(socket_); |
| } |
| |
| void ConnectJob::ChangePriority(RequestPriority priority) { |
| priority_ = priority; |
| ChangePriorityInternal(priority); |
| } |
| |
| int ConnectJob::Connect() { |
| if (!timeout_duration_.is_zero()) |
| timer_.Start(FROM_HERE, timeout_duration_, this, &ConnectJob::OnTimeout); |
| |
| LogConnectStart(); |
| |
| int rv = ConnectInternal(); |
| |
| if (rv != ERR_IO_PENDING) { |
| LogConnectCompletion(rv); |
| delegate_ = nullptr; |
| } |
| |
| return rv; |
| } |
| |
| ConnectionAttempts ConnectJob::GetConnectionAttempts() const { |
| // Return empty list by default - used by proxy classes. |
| return ConnectionAttempts(); |
| } |
| |
| bool ConnectJob::IsSSLError() const { |
| return false; |
| } |
| |
| scoped_refptr<SSLCertRequestInfo> ConnectJob::GetCertRequestInfo() { |
| return nullptr; |
| } |
| |
| void ConnectJob::set_done_closure(base::OnceClosure done_closure) { |
| done_closure_ = base::ScopedClosureRunner(std::move(done_closure)); |
| } |
| |
| absl::optional<HostResolverEndpointResult> |
| ConnectJob::GetHostResolverEndpointResult() const { |
| return absl::nullopt; |
| } |
| |
| void ConnectJob::SetSocket(std::unique_ptr<StreamSocket> socket, |
| absl::optional<std::set<std::string>> dns_aliases) { |
| if (socket) { |
| net_log().AddEventReferencingSource(NetLogEventType::CONNECT_JOB_SET_SOCKET, |
| socket->NetLog().source()); |
| if (dns_aliases) |
| socket->SetDnsAliases(std::move(dns_aliases.value())); |
| } |
| socket_ = std::move(socket); |
| } |
| |
| void ConnectJob::NotifyDelegateOfCompletion(int rv) { |
| TRACE_EVENT0(NetTracingCategory(), "ConnectJob::NotifyDelegateOfCompletion"); |
| // The delegate will own |this|. |
| Delegate* delegate = delegate_; |
| delegate_ = nullptr; |
| |
| LogConnectCompletion(rv); |
| delegate->OnConnectJobComplete(rv, this); |
| } |
| |
| void ConnectJob::NotifyDelegateOfProxyAuth( |
| const HttpResponseInfo& response, |
| HttpAuthController* auth_controller, |
| base::OnceClosure restart_with_auth_callback) { |
| delegate_->OnNeedsProxyAuth(response, auth_controller, |
| std::move(restart_with_auth_callback), this); |
| } |
| |
| void ConnectJob::ResetTimer(base::TimeDelta remaining_time) { |
| timer_.Stop(); |
| if (!remaining_time.is_zero()) |
| timer_.Start(FROM_HERE, remaining_time, this, &ConnectJob::OnTimeout); |
| } |
| |
| bool ConnectJob::TimerIsRunning() const { |
| return timer_.IsRunning(); |
| } |
| |
| void ConnectJob::LogConnectStart() { |
| connect_timing_.connect_start = base::TimeTicks::Now(); |
| net_log().BeginEvent(net_log_connect_event_type_); |
| } |
| |
| void ConnectJob::LogConnectCompletion(int net_error) { |
| connect_timing_.connect_end = base::TimeTicks::Now(); |
| net_log().EndEventWithNetErrorCode(net_log_connect_event_type_, net_error); |
| } |
| |
| void ConnectJob::OnTimeout() { |
| // Make sure the socket is NULL before calling into |delegate|. |
| SetSocket(nullptr, absl::nullopt /* dns_aliases */); |
| |
| OnTimedOutInternal(); |
| |
| net_log_.AddEvent(NetLogEventType::CONNECT_JOB_TIMED_OUT); |
| |
| NotifyDelegateOfCompletion(ERR_TIMED_OUT); |
| } |
| |
| void ConnectJob::OnTimedOutInternal() {} |
| |
| } // namespace net |