1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/http/http_basic_stream.h"
6
7 #include <set>
8 #include <string_view>
9 #include <utility>
10
11 #include "base/functional/bind.h"
12 #include "net/http/http_network_session.h"
13 #include "net/http/http_raw_request_headers.h"
14 #include "net/http/http_request_info.h"
15 #include "net/http/http_response_body_drainer.h"
16 #include "net/http/http_stream_parser.h"
17 #include "net/socket/stream_socket_handle.h"
18 #include "net/ssl/ssl_cert_request_info.h"
19 #include "net/ssl/ssl_info.h"
20
21 namespace net {
22
HttpBasicStream(std::unique_ptr<StreamSocketHandle> connection,bool is_for_get_to_http_proxy)23 HttpBasicStream::HttpBasicStream(std::unique_ptr<StreamSocketHandle> connection,
24 bool is_for_get_to_http_proxy)
25 : state_(std::move(connection), is_for_get_to_http_proxy) {}
26
27 HttpBasicStream::~HttpBasicStream() = default;
28
RegisterRequest(const HttpRequestInfo * request_info)29 void HttpBasicStream::RegisterRequest(const HttpRequestInfo* request_info) {
30 DCHECK(request_info);
31 DCHECK(request_info->traffic_annotation.is_valid());
32 request_info_ = request_info;
33 }
34
InitializeStream(bool can_send_early,RequestPriority priority,const NetLogWithSource & net_log,CompletionOnceCallback callback)35 int HttpBasicStream::InitializeStream(bool can_send_early,
36 RequestPriority priority,
37 const NetLogWithSource& net_log,
38 CompletionOnceCallback callback) {
39 DCHECK(request_info_);
40 state_.Initialize(request_info_, priority, net_log);
41 // RequestInfo is no longer needed after this point.
42 request_info_ = nullptr;
43
44 int ret = OK;
45 if (!can_send_early) {
46 // parser() cannot outlive |this|, so we can use base::Unretained().
47 ret = parser()->ConfirmHandshake(
48 base::BindOnce(&HttpBasicStream::OnHandshakeConfirmed,
49 base::Unretained(this), std::move(callback)));
50 }
51 return ret;
52 }
53
SendRequest(const HttpRequestHeaders & headers,HttpResponseInfo * response,CompletionOnceCallback callback)54 int HttpBasicStream::SendRequest(const HttpRequestHeaders& headers,
55 HttpResponseInfo* response,
56 CompletionOnceCallback callback) {
57 DCHECK(parser());
58 if (request_headers_callback_) {
59 HttpRawRequestHeaders raw_headers;
60 raw_headers.set_request_line(state_.GenerateRequestLine());
61 for (HttpRequestHeaders::Iterator it(headers); it.GetNext();) {
62 raw_headers.Add(it.name(), it.value());
63 }
64 request_headers_callback_.Run(std::move(raw_headers));
65 }
66 return parser()->SendRequest(
67 state_.GenerateRequestLine(), headers,
68 NetworkTrafficAnnotationTag(state_.traffic_annotation()), response,
69 std::move(callback));
70 }
71
ReadResponseHeaders(CompletionOnceCallback callback)72 int HttpBasicStream::ReadResponseHeaders(CompletionOnceCallback callback) {
73 return parser()->ReadResponseHeaders(std::move(callback));
74 }
75
ReadResponseBody(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)76 int HttpBasicStream::ReadResponseBody(IOBuffer* buf,
77 int buf_len,
78 CompletionOnceCallback callback) {
79 return parser()->ReadResponseBody(buf, buf_len, std::move(callback));
80 }
81
Close(bool not_reusable)82 void HttpBasicStream::Close(bool not_reusable) {
83 state_.Close(not_reusable);
84 }
85
RenewStreamForAuth()86 std::unique_ptr<HttpStream> HttpBasicStream::RenewStreamForAuth() {
87 DCHECK(IsResponseBodyComplete());
88 DCHECK(!parser()->IsMoreDataBuffered());
89 return std::make_unique<HttpBasicStream>(state_.ReleaseConnection(),
90 state_.is_for_get_to_http_proxy());
91 }
92
IsResponseBodyComplete() const93 bool HttpBasicStream::IsResponseBodyComplete() const {
94 return parser()->IsResponseBodyComplete();
95 }
96
IsConnectionReused() const97 bool HttpBasicStream::IsConnectionReused() const {
98 return state_.IsConnectionReused();
99 }
100
SetConnectionReused()101 void HttpBasicStream::SetConnectionReused() {
102 state_.SetConnectionReused();
103 }
104
CanReuseConnection() const105 bool HttpBasicStream::CanReuseConnection() const {
106 return state_.CanReuseConnection();
107 }
108
GetTotalReceivedBytes() const109 int64_t HttpBasicStream::GetTotalReceivedBytes() const {
110 if (parser())
111 return parser()->received_bytes();
112 return 0;
113 }
114
GetTotalSentBytes() const115 int64_t HttpBasicStream::GetTotalSentBytes() const {
116 if (parser())
117 return parser()->sent_bytes();
118 return 0;
119 }
120
GetLoadTimingInfo(LoadTimingInfo * load_timing_info) const121 bool HttpBasicStream::GetLoadTimingInfo(
122 LoadTimingInfo* load_timing_info) const {
123 if (!state_.GetLoadTimingInfo(load_timing_info) || !parser()) {
124 return false;
125 }
126
127 // If the request waited for handshake confirmation, shift |ssl_end| to
128 // include that time.
129 if (!load_timing_info->connect_timing.ssl_end.is_null() &&
130 !confirm_handshake_end_.is_null()) {
131 load_timing_info->connect_timing.ssl_end = confirm_handshake_end_;
132 load_timing_info->connect_timing.connect_end = confirm_handshake_end_;
133 }
134
135 load_timing_info->receive_headers_start =
136 parser()->first_response_start_time();
137 load_timing_info->receive_non_informational_headers_start =
138 parser()->non_informational_response_start_time();
139 load_timing_info->first_early_hints_time = parser()->first_early_hints_time();
140 return true;
141 }
142
GetAlternativeService(AlternativeService * alternative_service) const143 bool HttpBasicStream::GetAlternativeService(
144 AlternativeService* alternative_service) const {
145 return false;
146 }
147
GetSSLInfo(SSLInfo * ssl_info)148 void HttpBasicStream::GetSSLInfo(SSLInfo* ssl_info) {
149 state_.GetSSLInfo(ssl_info);
150 }
151
GetRemoteEndpoint(IPEndPoint * endpoint)152 int HttpBasicStream::GetRemoteEndpoint(IPEndPoint* endpoint) {
153 return state_.GetRemoteEndpoint(endpoint);
154 }
155
Drain(HttpNetworkSession * session)156 void HttpBasicStream::Drain(HttpNetworkSession* session) {
157 session->StartResponseDrainer(
158 std::make_unique<HttpResponseBodyDrainer>(this));
159 // |drainer| will delete itself.
160 }
161
PopulateNetErrorDetails(NetErrorDetails * details)162 void HttpBasicStream::PopulateNetErrorDetails(NetErrorDetails* details) {
163 // TODO(mmenke): Consumers don't actually care about HTTP version, but seems
164 // like the right version should be reported, if headers were received.
165 details->connection_info = HttpConnectionInfo::kHTTP1_1;
166 return;
167 }
168
SetPriority(RequestPriority priority)169 void HttpBasicStream::SetPriority(RequestPriority priority) {
170 // TODO(akalin): Plumb this through to |connection_|.
171 }
172
SetRequestHeadersCallback(RequestHeadersCallback callback)173 void HttpBasicStream::SetRequestHeadersCallback(
174 RequestHeadersCallback callback) {
175 request_headers_callback_ = std::move(callback);
176 }
177
GetDnsAliases() const178 const std::set<std::string>& HttpBasicStream::GetDnsAliases() const {
179 return state_.GetDnsAliases();
180 }
181
GetAcceptChViaAlps() const182 std::string_view HttpBasicStream::GetAcceptChViaAlps() const {
183 return {};
184 }
185
OnHandshakeConfirmed(CompletionOnceCallback callback,int rv)186 void HttpBasicStream::OnHandshakeConfirmed(CompletionOnceCallback callback,
187 int rv) {
188 if (rv == OK) {
189 // Note this time is only recorded if ConfirmHandshake() completed
190 // asynchronously. If it was synchronous, GetLoadTimingInfo() assumes the
191 // handshake was already confirmed or there was nothing to confirm.
192 confirm_handshake_end_ = base::TimeTicks::Now();
193 }
194 std::move(callback).Run(rv);
195 }
196
197 } // namespace net
198