1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "net/http/http_basic_stream.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <set>
8*6777b538SAndroid Build Coastguard Worker #include <string_view>
9*6777b538SAndroid Build Coastguard Worker #include <utility>
10*6777b538SAndroid Build Coastguard Worker
11*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
12*6777b538SAndroid Build Coastguard Worker #include "net/http/http_network_session.h"
13*6777b538SAndroid Build Coastguard Worker #include "net/http/http_raw_request_headers.h"
14*6777b538SAndroid Build Coastguard Worker #include "net/http/http_request_info.h"
15*6777b538SAndroid Build Coastguard Worker #include "net/http/http_response_body_drainer.h"
16*6777b538SAndroid Build Coastguard Worker #include "net/http/http_stream_parser.h"
17*6777b538SAndroid Build Coastguard Worker #include "net/socket/client_socket_handle.h"
18*6777b538SAndroid Build Coastguard Worker #include "net/ssl/ssl_cert_request_info.h"
19*6777b538SAndroid Build Coastguard Worker #include "net/ssl/ssl_info.h"
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Worker namespace net {
22*6777b538SAndroid Build Coastguard Worker
HttpBasicStream(std::unique_ptr<ClientSocketHandle> connection,bool is_for_get_to_http_proxy)23*6777b538SAndroid Build Coastguard Worker HttpBasicStream::HttpBasicStream(std::unique_ptr<ClientSocketHandle> connection,
24*6777b538SAndroid Build Coastguard Worker bool is_for_get_to_http_proxy)
25*6777b538SAndroid Build Coastguard Worker : state_(std::move(connection), is_for_get_to_http_proxy) {}
26*6777b538SAndroid Build Coastguard Worker
27*6777b538SAndroid Build Coastguard Worker HttpBasicStream::~HttpBasicStream() = default;
28*6777b538SAndroid Build Coastguard Worker
RegisterRequest(const HttpRequestInfo * request_info)29*6777b538SAndroid Build Coastguard Worker void HttpBasicStream::RegisterRequest(const HttpRequestInfo* request_info) {
30*6777b538SAndroid Build Coastguard Worker DCHECK(request_info);
31*6777b538SAndroid Build Coastguard Worker DCHECK(request_info->traffic_annotation.is_valid());
32*6777b538SAndroid Build Coastguard Worker request_info_ = request_info;
33*6777b538SAndroid Build Coastguard Worker }
34*6777b538SAndroid Build Coastguard Worker
InitializeStream(bool can_send_early,RequestPriority priority,const NetLogWithSource & net_log,CompletionOnceCallback callback)35*6777b538SAndroid Build Coastguard Worker int HttpBasicStream::InitializeStream(bool can_send_early,
36*6777b538SAndroid Build Coastguard Worker RequestPriority priority,
37*6777b538SAndroid Build Coastguard Worker const NetLogWithSource& net_log,
38*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback) {
39*6777b538SAndroid Build Coastguard Worker DCHECK(request_info_);
40*6777b538SAndroid Build Coastguard Worker state_.Initialize(request_info_, priority, net_log);
41*6777b538SAndroid Build Coastguard Worker int ret = OK;
42*6777b538SAndroid Build Coastguard Worker if (!can_send_early) {
43*6777b538SAndroid Build Coastguard Worker // parser() cannot outlive |this|, so we can use base::Unretained().
44*6777b538SAndroid Build Coastguard Worker ret = parser()->ConfirmHandshake(
45*6777b538SAndroid Build Coastguard Worker base::BindOnce(&HttpBasicStream::OnHandshakeConfirmed,
46*6777b538SAndroid Build Coastguard Worker base::Unretained(this), std::move(callback)));
47*6777b538SAndroid Build Coastguard Worker }
48*6777b538SAndroid Build Coastguard Worker // RequestInfo is no longer needed after this point.
49*6777b538SAndroid Build Coastguard Worker request_info_ = nullptr;
50*6777b538SAndroid Build Coastguard Worker return ret;
51*6777b538SAndroid Build Coastguard Worker }
52*6777b538SAndroid Build Coastguard Worker
SendRequest(const HttpRequestHeaders & headers,HttpResponseInfo * response,CompletionOnceCallback callback)53*6777b538SAndroid Build Coastguard Worker int HttpBasicStream::SendRequest(const HttpRequestHeaders& headers,
54*6777b538SAndroid Build Coastguard Worker HttpResponseInfo* response,
55*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback) {
56*6777b538SAndroid Build Coastguard Worker DCHECK(parser());
57*6777b538SAndroid Build Coastguard Worker if (request_headers_callback_) {
58*6777b538SAndroid Build Coastguard Worker HttpRawRequestHeaders raw_headers;
59*6777b538SAndroid Build Coastguard Worker raw_headers.set_request_line(state_.GenerateRequestLine());
60*6777b538SAndroid Build Coastguard Worker for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext();)
61*6777b538SAndroid Build Coastguard Worker raw_headers.Add(it.name(), it.value());
62*6777b538SAndroid Build Coastguard Worker request_headers_callback_.Run(std::move(raw_headers));
63*6777b538SAndroid Build Coastguard Worker }
64*6777b538SAndroid Build Coastguard Worker return parser()->SendRequest(
65*6777b538SAndroid Build Coastguard Worker state_.GenerateRequestLine(), headers,
66*6777b538SAndroid Build Coastguard Worker NetworkTrafficAnnotationTag(state_.traffic_annotation()), response,
67*6777b538SAndroid Build Coastguard Worker std::move(callback));
68*6777b538SAndroid Build Coastguard Worker }
69*6777b538SAndroid Build Coastguard Worker
ReadResponseHeaders(CompletionOnceCallback callback)70*6777b538SAndroid Build Coastguard Worker int HttpBasicStream::ReadResponseHeaders(CompletionOnceCallback callback) {
71*6777b538SAndroid Build Coastguard Worker return parser()->ReadResponseHeaders(std::move(callback));
72*6777b538SAndroid Build Coastguard Worker }
73*6777b538SAndroid Build Coastguard Worker
ReadResponseBody(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)74*6777b538SAndroid Build Coastguard Worker int HttpBasicStream::ReadResponseBody(IOBuffer* buf,
75*6777b538SAndroid Build Coastguard Worker int buf_len,
76*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback) {
77*6777b538SAndroid Build Coastguard Worker return parser()->ReadResponseBody(buf, buf_len, std::move(callback));
78*6777b538SAndroid Build Coastguard Worker }
79*6777b538SAndroid Build Coastguard Worker
Close(bool not_reusable)80*6777b538SAndroid Build Coastguard Worker void HttpBasicStream::Close(bool not_reusable) {
81*6777b538SAndroid Build Coastguard Worker // parser() is null if |this| is created by an orphaned HttpStreamFactory::Job
82*6777b538SAndroid Build Coastguard Worker // in which case InitializeStream() will not have been called. This also
83*6777b538SAndroid Build Coastguard Worker // protects against null dereference in the case where
84*6777b538SAndroid Build Coastguard Worker // state_.ReleaseConnection() has been called.
85*6777b538SAndroid Build Coastguard Worker //
86*6777b538SAndroid Build Coastguard Worker // TODO(mmenke): Can these cases be handled a bit more cleanly?
87*6777b538SAndroid Build Coastguard Worker // WebSocketHandshakeStream will need to be updated as well.
88*6777b538SAndroid Build Coastguard Worker if (!parser())
89*6777b538SAndroid Build Coastguard Worker return;
90*6777b538SAndroid Build Coastguard Worker StreamSocket* socket = state_.connection()->socket();
91*6777b538SAndroid Build Coastguard Worker if (not_reusable && socket)
92*6777b538SAndroid Build Coastguard Worker socket->Disconnect();
93*6777b538SAndroid Build Coastguard Worker parser()->OnConnectionClose();
94*6777b538SAndroid Build Coastguard Worker state_.connection()->Reset();
95*6777b538SAndroid Build Coastguard Worker }
96*6777b538SAndroid Build Coastguard Worker
RenewStreamForAuth()97*6777b538SAndroid Build Coastguard Worker std::unique_ptr<HttpStream> HttpBasicStream::RenewStreamForAuth() {
98*6777b538SAndroid Build Coastguard Worker DCHECK(IsResponseBodyComplete());
99*6777b538SAndroid Build Coastguard Worker DCHECK(!parser()->IsMoreDataBuffered());
100*6777b538SAndroid Build Coastguard Worker // The HttpStreamParser object still has a pointer to the connection. Just to
101*6777b538SAndroid Build Coastguard Worker // be extra-sure it doesn't touch the connection again, delete it here rather
102*6777b538SAndroid Build Coastguard Worker // than leaving it until the destructor is called.
103*6777b538SAndroid Build Coastguard Worker state_.DeleteParser();
104*6777b538SAndroid Build Coastguard Worker return std::make_unique<HttpBasicStream>(state_.ReleaseConnection(),
105*6777b538SAndroid Build Coastguard Worker state_.is_for_get_to_http_proxy());
106*6777b538SAndroid Build Coastguard Worker }
107*6777b538SAndroid Build Coastguard Worker
IsResponseBodyComplete() const108*6777b538SAndroid Build Coastguard Worker bool HttpBasicStream::IsResponseBodyComplete() const {
109*6777b538SAndroid Build Coastguard Worker return parser()->IsResponseBodyComplete();
110*6777b538SAndroid Build Coastguard Worker }
111*6777b538SAndroid Build Coastguard Worker
IsConnectionReused() const112*6777b538SAndroid Build Coastguard Worker bool HttpBasicStream::IsConnectionReused() const {
113*6777b538SAndroid Build Coastguard Worker return state_.IsConnectionReused();
114*6777b538SAndroid Build Coastguard Worker }
115*6777b538SAndroid Build Coastguard Worker
SetConnectionReused()116*6777b538SAndroid Build Coastguard Worker void HttpBasicStream::SetConnectionReused() {
117*6777b538SAndroid Build Coastguard Worker state_.connection()->set_reuse_type(ClientSocketHandle::REUSED_IDLE);
118*6777b538SAndroid Build Coastguard Worker }
119*6777b538SAndroid Build Coastguard Worker
CanReuseConnection() const120*6777b538SAndroid Build Coastguard Worker bool HttpBasicStream::CanReuseConnection() const {
121*6777b538SAndroid Build Coastguard Worker return parser() && state_.connection()->socket() &&
122*6777b538SAndroid Build Coastguard Worker parser()->CanReuseConnection();
123*6777b538SAndroid Build Coastguard Worker }
124*6777b538SAndroid Build Coastguard Worker
GetTotalReceivedBytes() const125*6777b538SAndroid Build Coastguard Worker int64_t HttpBasicStream::GetTotalReceivedBytes() const {
126*6777b538SAndroid Build Coastguard Worker if (parser())
127*6777b538SAndroid Build Coastguard Worker return parser()->received_bytes();
128*6777b538SAndroid Build Coastguard Worker return 0;
129*6777b538SAndroid Build Coastguard Worker }
130*6777b538SAndroid Build Coastguard Worker
GetTotalSentBytes() const131*6777b538SAndroid Build Coastguard Worker int64_t HttpBasicStream::GetTotalSentBytes() const {
132*6777b538SAndroid Build Coastguard Worker if (parser())
133*6777b538SAndroid Build Coastguard Worker return parser()->sent_bytes();
134*6777b538SAndroid Build Coastguard Worker return 0;
135*6777b538SAndroid Build Coastguard Worker }
136*6777b538SAndroid Build Coastguard Worker
GetLoadTimingInfo(LoadTimingInfo * load_timing_info) const137*6777b538SAndroid Build Coastguard Worker bool HttpBasicStream::GetLoadTimingInfo(
138*6777b538SAndroid Build Coastguard Worker LoadTimingInfo* load_timing_info) const {
139*6777b538SAndroid Build Coastguard Worker if (!state_.connection()->GetLoadTimingInfo(IsConnectionReused(),
140*6777b538SAndroid Build Coastguard Worker load_timing_info) ||
141*6777b538SAndroid Build Coastguard Worker !parser()) {
142*6777b538SAndroid Build Coastguard Worker return false;
143*6777b538SAndroid Build Coastguard Worker }
144*6777b538SAndroid Build Coastguard Worker
145*6777b538SAndroid Build Coastguard Worker // If the request waited for handshake confirmation, shift |ssl_end| to
146*6777b538SAndroid Build Coastguard Worker // include that time.
147*6777b538SAndroid Build Coastguard Worker if (!load_timing_info->connect_timing.ssl_end.is_null() &&
148*6777b538SAndroid Build Coastguard Worker !confirm_handshake_end_.is_null()) {
149*6777b538SAndroid Build Coastguard Worker load_timing_info->connect_timing.ssl_end = confirm_handshake_end_;
150*6777b538SAndroid Build Coastguard Worker load_timing_info->connect_timing.connect_end = confirm_handshake_end_;
151*6777b538SAndroid Build Coastguard Worker }
152*6777b538SAndroid Build Coastguard Worker
153*6777b538SAndroid Build Coastguard Worker load_timing_info->receive_headers_start =
154*6777b538SAndroid Build Coastguard Worker parser()->first_response_start_time();
155*6777b538SAndroid Build Coastguard Worker load_timing_info->receive_non_informational_headers_start =
156*6777b538SAndroid Build Coastguard Worker parser()->non_informational_response_start_time();
157*6777b538SAndroid Build Coastguard Worker load_timing_info->first_early_hints_time = parser()->first_early_hints_time();
158*6777b538SAndroid Build Coastguard Worker return true;
159*6777b538SAndroid Build Coastguard Worker }
160*6777b538SAndroid Build Coastguard Worker
GetAlternativeService(AlternativeService * alternative_service) const161*6777b538SAndroid Build Coastguard Worker bool HttpBasicStream::GetAlternativeService(
162*6777b538SAndroid Build Coastguard Worker AlternativeService* alternative_service) const {
163*6777b538SAndroid Build Coastguard Worker return false;
164*6777b538SAndroid Build Coastguard Worker }
165*6777b538SAndroid Build Coastguard Worker
GetSSLInfo(SSLInfo * ssl_info)166*6777b538SAndroid Build Coastguard Worker void HttpBasicStream::GetSSLInfo(SSLInfo* ssl_info) {
167*6777b538SAndroid Build Coastguard Worker if (!state_.connection()->socket() ||
168*6777b538SAndroid Build Coastguard Worker !state_.connection()->socket()->GetSSLInfo(ssl_info)) {
169*6777b538SAndroid Build Coastguard Worker ssl_info->Reset();
170*6777b538SAndroid Build Coastguard Worker }
171*6777b538SAndroid Build Coastguard Worker }
172*6777b538SAndroid Build Coastguard Worker
GetRemoteEndpoint(IPEndPoint * endpoint)173*6777b538SAndroid Build Coastguard Worker int HttpBasicStream::GetRemoteEndpoint(IPEndPoint* endpoint) {
174*6777b538SAndroid Build Coastguard Worker if (!state_.connection() || !state_.connection()->socket())
175*6777b538SAndroid Build Coastguard Worker return ERR_SOCKET_NOT_CONNECTED;
176*6777b538SAndroid Build Coastguard Worker
177*6777b538SAndroid Build Coastguard Worker return state_.connection()->socket()->GetPeerAddress(endpoint);
178*6777b538SAndroid Build Coastguard Worker }
179*6777b538SAndroid Build Coastguard Worker
Drain(HttpNetworkSession * session)180*6777b538SAndroid Build Coastguard Worker void HttpBasicStream::Drain(HttpNetworkSession* session) {
181*6777b538SAndroid Build Coastguard Worker session->StartResponseDrainer(
182*6777b538SAndroid Build Coastguard Worker std::make_unique<HttpResponseBodyDrainer>(this));
183*6777b538SAndroid Build Coastguard Worker // |drainer| will delete itself.
184*6777b538SAndroid Build Coastguard Worker }
185*6777b538SAndroid Build Coastguard Worker
PopulateNetErrorDetails(NetErrorDetails * details)186*6777b538SAndroid Build Coastguard Worker void HttpBasicStream::PopulateNetErrorDetails(NetErrorDetails* details) {
187*6777b538SAndroid Build Coastguard Worker // TODO(mmenke): Consumers don't actually care about HTTP version, but seems
188*6777b538SAndroid Build Coastguard Worker // like the right version should be reported, if headers were received.
189*6777b538SAndroid Build Coastguard Worker details->connection_info = HttpConnectionInfo::kHTTP1_1;
190*6777b538SAndroid Build Coastguard Worker return;
191*6777b538SAndroid Build Coastguard Worker }
192*6777b538SAndroid Build Coastguard Worker
SetPriority(RequestPriority priority)193*6777b538SAndroid Build Coastguard Worker void HttpBasicStream::SetPriority(RequestPriority priority) {
194*6777b538SAndroid Build Coastguard Worker // TODO(akalin): Plumb this through to |connection_|.
195*6777b538SAndroid Build Coastguard Worker }
196*6777b538SAndroid Build Coastguard Worker
SetRequestHeadersCallback(RequestHeadersCallback callback)197*6777b538SAndroid Build Coastguard Worker void HttpBasicStream::SetRequestHeadersCallback(
198*6777b538SAndroid Build Coastguard Worker RequestHeadersCallback callback) {
199*6777b538SAndroid Build Coastguard Worker request_headers_callback_ = std::move(callback);
200*6777b538SAndroid Build Coastguard Worker }
201*6777b538SAndroid Build Coastguard Worker
GetDnsAliases() const202*6777b538SAndroid Build Coastguard Worker const std::set<std::string>& HttpBasicStream::GetDnsAliases() const {
203*6777b538SAndroid Build Coastguard Worker return state_.GetDnsAliases();
204*6777b538SAndroid Build Coastguard Worker }
205*6777b538SAndroid Build Coastguard Worker
GetAcceptChViaAlps() const206*6777b538SAndroid Build Coastguard Worker std::string_view HttpBasicStream::GetAcceptChViaAlps() const {
207*6777b538SAndroid Build Coastguard Worker return {};
208*6777b538SAndroid Build Coastguard Worker }
209*6777b538SAndroid Build Coastguard Worker
OnHandshakeConfirmed(CompletionOnceCallback callback,int rv)210*6777b538SAndroid Build Coastguard Worker void HttpBasicStream::OnHandshakeConfirmed(CompletionOnceCallback callback,
211*6777b538SAndroid Build Coastguard Worker int rv) {
212*6777b538SAndroid Build Coastguard Worker if (rv == OK) {
213*6777b538SAndroid Build Coastguard Worker // Note this time is only recorded if ConfirmHandshake() completed
214*6777b538SAndroid Build Coastguard Worker // asynchronously. If it was synchronous, GetLoadTimingInfo() assumes the
215*6777b538SAndroid Build Coastguard Worker // handshake was already confirmed or there was nothing to confirm.
216*6777b538SAndroid Build Coastguard Worker confirm_handshake_end_ = base::TimeTicks::Now();
217*6777b538SAndroid Build Coastguard Worker }
218*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(rv);
219*6777b538SAndroid Build Coastguard Worker }
220*6777b538SAndroid Build Coastguard Worker
221*6777b538SAndroid Build Coastguard Worker } // namespace net
222