• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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