blob: c85a0ff661537b2308ebc7b325f71a9076c304d5 [file] [log] [blame]
// 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_HTTP_HTTP_STREAM_POOL_JOB_H_
#define NET_HTTP_HTTP_STREAM_POOL_JOB_H_
#include <memory>
#include <optional>
#include <set>
#include "base/containers/unique_ptr_adapters.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "net/base/load_states.h"
#include "net/base/net_error_details.h"
#include "net/base/priority_queue.h"
#include "net/base/request_priority.h"
#include "net/dns/host_resolver.h"
#include "net/dns/public/resolve_error_info.h"
#include "net/http/http_stream_pool.h"
#include "net/http/http_stream_request.h"
#include "net/log/net_log_with_source.h"
#include "net/socket/stream_attempt.h"
#include "url/gurl.h"
namespace net {
class HttpNetworkSession;
class NetLog;
class HttpStreamKey;
// Maintains in-flight HTTP stream requests. Peforms DNS resolution.
class HttpStreamPool::Job
: public HostResolver::ServiceEndpointRequest::Delegate {
public:
// `group` must outlive `this`.
Job(Group* group, NetLog* net_log);
Job(const Job&) = delete;
Job& operator=(const Job&) = delete;
~Job() override;
// Creates an HttpStreamRequest. Will call delegate's methods. See the
// comments of HttpStreamRequest::Delegate methods for details.
// TODO(crbug.com/346835898): Support TLS, HTTP/2 and QUIC.
std::unique_ptr<HttpStreamRequest> RequestStream(
HttpStreamRequest::Delegate* delegate,
RequestPriority priority,
const NetLogWithSource& net_log);
// HostResolver::ServiceEndpointRequest::Delegate implementation:
void OnServiceEndpointsUpdated() override;
void OnServiceEndpointRequestFinished(int rv) override;
// Called when a stream socket is released to `group_`.
void OnStreamSocketReleased();
// Returns the number of in-flight attempts.
size_t InFlightAttemptCount() const { return in_flight_attempts_.size(); }
// Returns the number of pending requests. The number is calculated by
// subtracting the number of in-flight attempts from the number of total
// requests.
size_t PendingRequestCount() const;
private:
// A peer of an HttpStreamRequest. Holds the HttpStreamRequest's delegate
// pointer and implements HttpStreamRequest::Helper.
class RequestEntry : public HttpStreamRequest::Helper {
public:
explicit RequestEntry(Job* job);
RequestEntry(RequestEntry&) = delete;
RequestEntry& operator=(const RequestEntry&) = delete;
~RequestEntry() override;
std::unique_ptr<HttpStreamRequest> CreateRequest(
HttpStreamRequest::Delegate* delegate,
const NetLogWithSource& net_log);
HttpStreamRequest* request() const { return request_; }
HttpStreamRequest::Delegate* delegate() const { return delegate_; }
// HttpStreamRequest::Helper methods:
LoadState GetLoadState() const override;
void OnRequestComplete() override;
int RestartTunnelWithProxyAuth() override;
void SetPriority(RequestPriority priority) override;
private:
const raw_ptr<Job> job_;
raw_ptr<HttpStreamRequest> request_;
raw_ptr<HttpStreamRequest::Delegate> delegate_;
};
using RequestQueue = PriorityQueue<std::unique_ptr<RequestEntry>>;
struct InFlightAttempt;
const HttpStreamKey& stream_key() const;
HttpNetworkSession* http_network_session();
bool UsingTls() const;
// Returns the current load state.
LoadState GetLoadState() const;
// Returns the highest priority in `requests_`.
RequestPriority GetPriority() const;
// Returns true if we can't make any connection attempts due to per-pool or
// per-group limits.
bool ReachedMaxStreamLimit() const;
void ResolveServiceEndpoint(RequestPriority initial_priority);
void MaybeChangeServiceEndpointRequestPriority();
void MaybeAttemptConnection();
std::optional<IPEndPoint> GetIPEndPointToAttempt();
std::optional<IPEndPoint> FindUnattemptedIPEndPoint(
const std::vector<IPEndPoint>& ip_endpoints);
void NotifyFailure(int rv);
// Extracts an entry from `requests_` of which priority is highest. The
// ownership of the entry is moved to `notified_requests_`.
RequestEntry* ExtractFirstRequestToNotify();
// Called when the priority of `request` is set.
void SetRequestPriority(HttpStreamRequest* request, RequestPriority priority);
// Called when an HttpStreamRequest associated with `entry` is going to
// be destroyed.
void OnRequestComplete(RequestEntry* entry);
void OnInFlightAttemptComplete(InFlightAttempt* raw_attempt, int rv);
void MaybeComplete();
const raw_ptr<Group> group_;
const NetLogWithSource net_log_;
ProxyInfo proxy_info_;
// Holds requests that are waiting for notifications (a delegate method call
// to indicate success or failure).
RequestQueue requests_;
// Holds requests that are already notified results. We need to keep them
// to avoid dangling pointers.
std::set<std::unique_ptr<RequestEntry>, base::UniquePtrComparator>
notified_requests_;
std::unique_ptr<HostResolver::ServiceEndpointRequest>
service_endpoint_request_;
bool service_endpoint_request_finished_ = false;
NetErrorDetails net_error_details_;
ResolveErrorInfo resolve_error_info_;
// Set to the latest stream attempt failure result. Used to notify delegates
// when all attempts failed.
int last_attempt_error_ = ERR_FAILED;
StreamAttemptParams attempt_params_;
std::set<std::unique_ptr<InFlightAttempt>, base::UniquePtrComparator>
in_flight_attempts_;
// Updated when a stream attempt failed. Used to calculate next IPEndPoint to
// attempt.
std::set<IPEndPoint> failed_ip_endpoints_;
base::WeakPtrFactory<Job> weak_ptr_factory_{this};
};
} // namespace net
#endif // NET_HTTP_HTTP_STREAM_POOL_JOB_H_