xref: /aosp_15_r20/external/cronet/net/http/http_stream_parser.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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_stream_parser.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <algorithm>
8*6777b538SAndroid Build Coastguard Worker #include <memory>
9*6777b538SAndroid Build Coastguard Worker #include <string_view>
10*6777b538SAndroid Build Coastguard Worker #include <utility>
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/compiler_specific.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_macros.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/numerics/clamped_math.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/values.h"
21*6777b538SAndroid Build Coastguard Worker #include "net/base/features.h"
22*6777b538SAndroid Build Coastguard Worker #include "net/base/io_buffer.h"
23*6777b538SAndroid Build Coastguard Worker #include "net/base/ip_endpoint.h"
24*6777b538SAndroid Build Coastguard Worker #include "net/base/upload_data_stream.h"
25*6777b538SAndroid Build Coastguard Worker #include "net/http/http_chunked_decoder.h"
26*6777b538SAndroid Build Coastguard Worker #include "net/http/http_connection_info.h"
27*6777b538SAndroid Build Coastguard Worker #include "net/http/http_log_util.h"
28*6777b538SAndroid Build Coastguard Worker #include "net/http/http_request_headers.h"
29*6777b538SAndroid Build Coastguard Worker #include "net/http/http_request_info.h"
30*6777b538SAndroid Build Coastguard Worker #include "net/http/http_response_headers.h"
31*6777b538SAndroid Build Coastguard Worker #include "net/http/http_response_info.h"
32*6777b538SAndroid Build Coastguard Worker #include "net/http/http_status_code.h"
33*6777b538SAndroid Build Coastguard Worker #include "net/http/http_util.h"
34*6777b538SAndroid Build Coastguard Worker #include "net/log/net_log_event_type.h"
35*6777b538SAndroid Build Coastguard Worker #include "net/socket/ssl_client_socket.h"
36*6777b538SAndroid Build Coastguard Worker #include "net/socket/stream_socket.h"
37*6777b538SAndroid Build Coastguard Worker #include "net/ssl/ssl_cert_request_info.h"
38*6777b538SAndroid Build Coastguard Worker #include "net/ssl/ssl_info.h"
39*6777b538SAndroid Build Coastguard Worker #include "url/url_canon.h"
40*6777b538SAndroid Build Coastguard Worker 
41*6777b538SAndroid Build Coastguard Worker namespace net {
42*6777b538SAndroid Build Coastguard Worker 
43*6777b538SAndroid Build Coastguard Worker namespace {
44*6777b538SAndroid Build Coastguard Worker 
45*6777b538SAndroid Build Coastguard Worker const uint64_t kMaxMergedHeaderAndBodySize = 1400;
46*6777b538SAndroid Build Coastguard Worker const size_t kRequestBodyBufferSize = 1 << 14;  // 16KB
47*6777b538SAndroid Build Coastguard Worker 
GetResponseHeaderLines(const HttpResponseHeaders & headers)48*6777b538SAndroid Build Coastguard Worker std::string GetResponseHeaderLines(const HttpResponseHeaders& headers) {
49*6777b538SAndroid Build Coastguard Worker   std::string raw_headers = headers.raw_headers();
50*6777b538SAndroid Build Coastguard Worker   const char* null_separated_headers = raw_headers.c_str();
51*6777b538SAndroid Build Coastguard Worker   const char* header_line = null_separated_headers;
52*6777b538SAndroid Build Coastguard Worker   std::string cr_separated_headers;
53*6777b538SAndroid Build Coastguard Worker   while (header_line[0] != 0) {
54*6777b538SAndroid Build Coastguard Worker     cr_separated_headers += header_line;
55*6777b538SAndroid Build Coastguard Worker     cr_separated_headers += "\n";
56*6777b538SAndroid Build Coastguard Worker     header_line += strlen(header_line) + 1;
57*6777b538SAndroid Build Coastguard Worker   }
58*6777b538SAndroid Build Coastguard Worker   return cr_separated_headers;
59*6777b538SAndroid Build Coastguard Worker }
60*6777b538SAndroid Build Coastguard Worker 
NetLogSendRequestBodyParams(uint64_t length,bool is_chunked,bool did_merge)61*6777b538SAndroid Build Coastguard Worker base::Value::Dict NetLogSendRequestBodyParams(uint64_t length,
62*6777b538SAndroid Build Coastguard Worker                                               bool is_chunked,
63*6777b538SAndroid Build Coastguard Worker                                               bool did_merge) {
64*6777b538SAndroid Build Coastguard Worker   base::Value::Dict dict;
65*6777b538SAndroid Build Coastguard Worker   dict.Set("length", static_cast<int>(length));
66*6777b538SAndroid Build Coastguard Worker   dict.Set("is_chunked", is_chunked);
67*6777b538SAndroid Build Coastguard Worker   dict.Set("did_merge", did_merge);
68*6777b538SAndroid Build Coastguard Worker   return dict;
69*6777b538SAndroid Build Coastguard Worker }
70*6777b538SAndroid Build Coastguard Worker 
NetLogSendRequestBody(const NetLogWithSource & net_log,uint64_t length,bool is_chunked,bool did_merge)71*6777b538SAndroid Build Coastguard Worker void NetLogSendRequestBody(const NetLogWithSource& net_log,
72*6777b538SAndroid Build Coastguard Worker                            uint64_t length,
73*6777b538SAndroid Build Coastguard Worker                            bool is_chunked,
74*6777b538SAndroid Build Coastguard Worker                            bool did_merge) {
75*6777b538SAndroid Build Coastguard Worker   net_log.AddEvent(NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST_BODY, [&] {
76*6777b538SAndroid Build Coastguard Worker     return NetLogSendRequestBodyParams(length, is_chunked, did_merge);
77*6777b538SAndroid Build Coastguard Worker   });
78*6777b538SAndroid Build Coastguard Worker }
79*6777b538SAndroid Build Coastguard Worker 
80*6777b538SAndroid Build Coastguard Worker // Returns true if |error_code| is an error for which we give the server a
81*6777b538SAndroid Build Coastguard Worker // chance to send a body containing error information, if the error was received
82*6777b538SAndroid Build Coastguard Worker // while trying to upload a request body.
ShouldTryReadingOnUploadError(int error_code)83*6777b538SAndroid Build Coastguard Worker bool ShouldTryReadingOnUploadError(int error_code) {
84*6777b538SAndroid Build Coastguard Worker   return (error_code == ERR_CONNECTION_RESET);
85*6777b538SAndroid Build Coastguard Worker }
86*6777b538SAndroid Build Coastguard Worker 
87*6777b538SAndroid Build Coastguard Worker }  // namespace
88*6777b538SAndroid Build Coastguard Worker 
89*6777b538SAndroid Build Coastguard Worker // Similar to DrainableIOBuffer(), but this version comes with its own
90*6777b538SAndroid Build Coastguard Worker // storage. The motivation is to avoid repeated allocations of
91*6777b538SAndroid Build Coastguard Worker // DrainableIOBuffer.
92*6777b538SAndroid Build Coastguard Worker //
93*6777b538SAndroid Build Coastguard Worker // Example:
94*6777b538SAndroid Build Coastguard Worker //
95*6777b538SAndroid Build Coastguard Worker // scoped_refptr<SeekableIOBuffer> buf =
96*6777b538SAndroid Build Coastguard Worker //     base::MakeRefCounted<SeekableIOBuffer>(1024);
97*6777b538SAndroid Build Coastguard Worker // // capacity() == 1024. size() == BytesRemaining() == BytesConsumed() == 0.
98*6777b538SAndroid Build Coastguard Worker // // data() points to the beginning of the buffer.
99*6777b538SAndroid Build Coastguard Worker //
100*6777b538SAndroid Build Coastguard Worker // // Read() takes an IOBuffer.
101*6777b538SAndroid Build Coastguard Worker // int bytes_read = some_reader->Read(buf, buf->capacity());
102*6777b538SAndroid Build Coastguard Worker // buf->DidAppend(bytes_read);
103*6777b538SAndroid Build Coastguard Worker // // size() == BytesRemaining() == bytes_read. data() is unaffected.
104*6777b538SAndroid Build Coastguard Worker //
105*6777b538SAndroid Build Coastguard Worker // while (buf->BytesRemaining() > 0) {
106*6777b538SAndroid Build Coastguard Worker //   // Write() takes an IOBuffer. If it takes const char*, we could
107*6777b538SAndroid Build Coastguard Worker ///  // simply use the regular IOBuffer like buf->data() + offset.
108*6777b538SAndroid Build Coastguard Worker //   int bytes_written = Write(buf, buf->BytesRemaining());
109*6777b538SAndroid Build Coastguard Worker //   buf->DidConsume(bytes_written);
110*6777b538SAndroid Build Coastguard Worker // }
111*6777b538SAndroid Build Coastguard Worker // // BytesRemaining() == 0. BytesConsumed() == size().
112*6777b538SAndroid Build Coastguard Worker // // data() points to the end of the consumed bytes (exclusive).
113*6777b538SAndroid Build Coastguard Worker //
114*6777b538SAndroid Build Coastguard Worker // // If you want to reuse the buffer, be sure to clear the buffer.
115*6777b538SAndroid Build Coastguard Worker // buf->Clear();
116*6777b538SAndroid Build Coastguard Worker // // size() == BytesRemaining() == BytesConsumed() == 0.
117*6777b538SAndroid Build Coastguard Worker // // data() points to the beginning of the buffer.
118*6777b538SAndroid Build Coastguard Worker //
119*6777b538SAndroid Build Coastguard Worker class HttpStreamParser::SeekableIOBuffer : public IOBufferWithSize {
120*6777b538SAndroid Build Coastguard Worker  public:
SeekableIOBuffer(int capacity)121*6777b538SAndroid Build Coastguard Worker   explicit SeekableIOBuffer(int capacity)
122*6777b538SAndroid Build Coastguard Worker       : IOBufferWithSize(capacity), real_data_(data_), capacity_(capacity) {}
123*6777b538SAndroid Build Coastguard Worker 
124*6777b538SAndroid Build Coastguard Worker   // DidConsume() changes the |data_| pointer so that |data_| always points
125*6777b538SAndroid Build Coastguard Worker   // to the first unconsumed byte.
DidConsume(int bytes)126*6777b538SAndroid Build Coastguard Worker   void DidConsume(int bytes) {
127*6777b538SAndroid Build Coastguard Worker     SetOffset(used_ + bytes);
128*6777b538SAndroid Build Coastguard Worker   }
129*6777b538SAndroid Build Coastguard Worker 
130*6777b538SAndroid Build Coastguard Worker   // Returns the number of unconsumed bytes.
BytesRemaining() const131*6777b538SAndroid Build Coastguard Worker   int BytesRemaining() const {
132*6777b538SAndroid Build Coastguard Worker     return size_ - used_;
133*6777b538SAndroid Build Coastguard Worker   }
134*6777b538SAndroid Build Coastguard Worker 
135*6777b538SAndroid Build Coastguard Worker   // Seeks to an arbitrary point in the buffer. The notion of bytes consumed
136*6777b538SAndroid Build Coastguard Worker   // and remaining are updated appropriately.
SetOffset(int bytes)137*6777b538SAndroid Build Coastguard Worker   void SetOffset(int bytes) {
138*6777b538SAndroid Build Coastguard Worker     DCHECK_GE(bytes, 0);
139*6777b538SAndroid Build Coastguard Worker     DCHECK_LE(bytes, size_);
140*6777b538SAndroid Build Coastguard Worker     used_ = bytes;
141*6777b538SAndroid Build Coastguard Worker     data_ = real_data_ + used_;
142*6777b538SAndroid Build Coastguard Worker   }
143*6777b538SAndroid Build Coastguard Worker 
144*6777b538SAndroid Build Coastguard Worker   // Called after data is added to the buffer. Adds |bytes| added to
145*6777b538SAndroid Build Coastguard Worker   // |size_|. data() is unaffected.
DidAppend(int bytes)146*6777b538SAndroid Build Coastguard Worker   void DidAppend(int bytes) {
147*6777b538SAndroid Build Coastguard Worker     DCHECK_GE(bytes, 0);
148*6777b538SAndroid Build Coastguard Worker     DCHECK_GE(size_ + bytes, 0);
149*6777b538SAndroid Build Coastguard Worker     DCHECK_LE(size_ + bytes, capacity_);
150*6777b538SAndroid Build Coastguard Worker     size_ += bytes;
151*6777b538SAndroid Build Coastguard Worker   }
152*6777b538SAndroid Build Coastguard Worker 
153*6777b538SAndroid Build Coastguard Worker   // Changes the logical size to 0, and the offset to 0.
Clear()154*6777b538SAndroid Build Coastguard Worker   void Clear() {
155*6777b538SAndroid Build Coastguard Worker     size_ = 0;
156*6777b538SAndroid Build Coastguard Worker     SetOffset(0);
157*6777b538SAndroid Build Coastguard Worker   }
158*6777b538SAndroid Build Coastguard Worker 
159*6777b538SAndroid Build Coastguard Worker   // Returns the logical size of the buffer (i.e the number of bytes of data
160*6777b538SAndroid Build Coastguard Worker   // in the buffer).
size() const161*6777b538SAndroid Build Coastguard Worker   int size() const { return size_; }
162*6777b538SAndroid Build Coastguard Worker 
163*6777b538SAndroid Build Coastguard Worker   // Returns the capacity of the buffer. The capacity is the size used when
164*6777b538SAndroid Build Coastguard Worker   // the object is created.
capacity() const165*6777b538SAndroid Build Coastguard Worker   int capacity() const { return capacity_; }
166*6777b538SAndroid Build Coastguard Worker 
167*6777b538SAndroid Build Coastguard Worker  private:
~SeekableIOBuffer()168*6777b538SAndroid Build Coastguard Worker   ~SeekableIOBuffer() override {
169*6777b538SAndroid Build Coastguard Worker     // data_ will be deleted in IOBuffer::~IOBuffer().
170*6777b538SAndroid Build Coastguard Worker     data_ = real_data_;
171*6777b538SAndroid Build Coastguard Worker   }
172*6777b538SAndroid Build Coastguard Worker 
173*6777b538SAndroid Build Coastguard Worker   // DanglingUntriaged because it is assigned a DanglingUntriaged pointer.
174*6777b538SAndroid Build Coastguard Worker   raw_ptr<char, AcrossTasksDanglingUntriaged | AllowPtrArithmetic> real_data_;
175*6777b538SAndroid Build Coastguard Worker   const int capacity_;
176*6777b538SAndroid Build Coastguard Worker   int size_ = 0;
177*6777b538SAndroid Build Coastguard Worker   int used_ = 0;
178*6777b538SAndroid Build Coastguard Worker };
179*6777b538SAndroid Build Coastguard Worker 
180*6777b538SAndroid Build Coastguard Worker // 2 CRLFs + max of 8 hex chars.
181*6777b538SAndroid Build Coastguard Worker const size_t HttpStreamParser::kChunkHeaderFooterSize = 12;
182*6777b538SAndroid Build Coastguard Worker 
HttpStreamParser(StreamSocket * stream_socket,bool connection_is_reused,const HttpRequestInfo * request,GrowableIOBuffer * read_buffer,const NetLogWithSource & net_log)183*6777b538SAndroid Build Coastguard Worker HttpStreamParser::HttpStreamParser(StreamSocket* stream_socket,
184*6777b538SAndroid Build Coastguard Worker                                    bool connection_is_reused,
185*6777b538SAndroid Build Coastguard Worker                                    const HttpRequestInfo* request,
186*6777b538SAndroid Build Coastguard Worker                                    GrowableIOBuffer* read_buffer,
187*6777b538SAndroid Build Coastguard Worker                                    const NetLogWithSource& net_log)
188*6777b538SAndroid Build Coastguard Worker     : request_(request),
189*6777b538SAndroid Build Coastguard Worker       read_buf_(read_buffer),
190*6777b538SAndroid Build Coastguard Worker       response_header_start_offset_(std::string::npos),
191*6777b538SAndroid Build Coastguard Worker       stream_socket_(stream_socket),
192*6777b538SAndroid Build Coastguard Worker       connection_is_reused_(connection_is_reused),
193*6777b538SAndroid Build Coastguard Worker       net_log_(net_log),
194*6777b538SAndroid Build Coastguard Worker       truncate_to_content_length_enabled_(base::FeatureList::IsEnabled(
195*6777b538SAndroid Build Coastguard Worker           net::features::kTruncateBodyToContentLength)) {
196*6777b538SAndroid Build Coastguard Worker   io_callback_ = base::BindRepeating(&HttpStreamParser::OnIOComplete,
197*6777b538SAndroid Build Coastguard Worker                                      weak_ptr_factory_.GetWeakPtr());
198*6777b538SAndroid Build Coastguard Worker }
199*6777b538SAndroid Build Coastguard Worker 
200*6777b538SAndroid Build Coastguard Worker HttpStreamParser::~HttpStreamParser() = default;
201*6777b538SAndroid Build Coastguard Worker 
SendRequest(const std::string & request_line,const HttpRequestHeaders & headers,const NetworkTrafficAnnotationTag & traffic_annotation,HttpResponseInfo * response,CompletionOnceCallback callback)202*6777b538SAndroid Build Coastguard Worker int HttpStreamParser::SendRequest(
203*6777b538SAndroid Build Coastguard Worker     const std::string& request_line,
204*6777b538SAndroid Build Coastguard Worker     const HttpRequestHeaders& headers,
205*6777b538SAndroid Build Coastguard Worker     const NetworkTrafficAnnotationTag& traffic_annotation,
206*6777b538SAndroid Build Coastguard Worker     HttpResponseInfo* response,
207*6777b538SAndroid Build Coastguard Worker     CompletionOnceCallback callback) {
208*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(STATE_NONE, io_state_);
209*6777b538SAndroid Build Coastguard Worker   DCHECK(callback_.is_null());
210*6777b538SAndroid Build Coastguard Worker   DCHECK(!callback.is_null());
211*6777b538SAndroid Build Coastguard Worker   DCHECK(response);
212*6777b538SAndroid Build Coastguard Worker 
213*6777b538SAndroid Build Coastguard Worker   NetLogRequestHeaders(net_log_,
214*6777b538SAndroid Build Coastguard Worker                        NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
215*6777b538SAndroid Build Coastguard Worker                        request_line, &headers);
216*6777b538SAndroid Build Coastguard Worker 
217*6777b538SAndroid Build Coastguard Worker   DVLOG(1) << __func__ << "() request_line = \"" << request_line << "\""
218*6777b538SAndroid Build Coastguard Worker            << " headers = \"" << headers.ToString() << "\"";
219*6777b538SAndroid Build Coastguard Worker   traffic_annotation_ = MutableNetworkTrafficAnnotationTag(traffic_annotation);
220*6777b538SAndroid Build Coastguard Worker   response_ = response;
221*6777b538SAndroid Build Coastguard Worker 
222*6777b538SAndroid Build Coastguard Worker   // Put the peer's IP address and port into the response.
223*6777b538SAndroid Build Coastguard Worker   IPEndPoint ip_endpoint;
224*6777b538SAndroid Build Coastguard Worker   int result = stream_socket_->GetPeerAddress(&ip_endpoint);
225*6777b538SAndroid Build Coastguard Worker   if (result != OK)
226*6777b538SAndroid Build Coastguard Worker     return result;
227*6777b538SAndroid Build Coastguard Worker   response_->remote_endpoint = ip_endpoint;
228*6777b538SAndroid Build Coastguard Worker 
229*6777b538SAndroid Build Coastguard Worker   std::string request = request_line + headers.ToString();
230*6777b538SAndroid Build Coastguard Worker   request_headers_length_ = request.size();
231*6777b538SAndroid Build Coastguard Worker 
232*6777b538SAndroid Build Coastguard Worker   if (request_->upload_data_stream != nullptr) {
233*6777b538SAndroid Build Coastguard Worker     request_body_send_buf_ =
234*6777b538SAndroid Build Coastguard Worker         base::MakeRefCounted<SeekableIOBuffer>(kRequestBodyBufferSize);
235*6777b538SAndroid Build Coastguard Worker     if (request_->upload_data_stream->is_chunked()) {
236*6777b538SAndroid Build Coastguard Worker       // Read buffer is adjusted to guarantee that |request_body_send_buf_| is
237*6777b538SAndroid Build Coastguard Worker       // large enough to hold the encoded chunk.
238*6777b538SAndroid Build Coastguard Worker       request_body_read_buf_ = base::MakeRefCounted<SeekableIOBuffer>(
239*6777b538SAndroid Build Coastguard Worker           kRequestBodyBufferSize - kChunkHeaderFooterSize);
240*6777b538SAndroid Build Coastguard Worker     } else {
241*6777b538SAndroid Build Coastguard Worker       // No need to encode request body, just send the raw data.
242*6777b538SAndroid Build Coastguard Worker       request_body_read_buf_ = request_body_send_buf_;
243*6777b538SAndroid Build Coastguard Worker     }
244*6777b538SAndroid Build Coastguard Worker   }
245*6777b538SAndroid Build Coastguard Worker 
246*6777b538SAndroid Build Coastguard Worker   io_state_ = STATE_SEND_HEADERS;
247*6777b538SAndroid Build Coastguard Worker 
248*6777b538SAndroid Build Coastguard Worker   // If we have a small request body, then we'll merge with the headers into a
249*6777b538SAndroid Build Coastguard Worker   // single write.
250*6777b538SAndroid Build Coastguard Worker   bool did_merge = false;
251*6777b538SAndroid Build Coastguard Worker   if (ShouldMergeRequestHeadersAndBody(request, request_->upload_data_stream)) {
252*6777b538SAndroid Build Coastguard Worker     int merged_size = static_cast<int>(
253*6777b538SAndroid Build Coastguard Worker         request_headers_length_ + request_->upload_data_stream->size());
254*6777b538SAndroid Build Coastguard Worker     auto merged_request_headers_and_body =
255*6777b538SAndroid Build Coastguard Worker         base::MakeRefCounted<IOBufferWithSize>(merged_size);
256*6777b538SAndroid Build Coastguard Worker     // We'll repurpose |request_headers_| to store the merged headers and
257*6777b538SAndroid Build Coastguard Worker     // body.
258*6777b538SAndroid Build Coastguard Worker     request_headers_ = base::MakeRefCounted<DrainableIOBuffer>(
259*6777b538SAndroid Build Coastguard Worker         merged_request_headers_and_body, merged_size);
260*6777b538SAndroid Build Coastguard Worker 
261*6777b538SAndroid Build Coastguard Worker     memcpy(request_headers_->data(), request.data(), request_headers_length_);
262*6777b538SAndroid Build Coastguard Worker     request_headers_->DidConsume(request_headers_length_);
263*6777b538SAndroid Build Coastguard Worker 
264*6777b538SAndroid Build Coastguard Worker     uint64_t todo = request_->upload_data_stream->size();
265*6777b538SAndroid Build Coastguard Worker     while (todo) {
266*6777b538SAndroid Build Coastguard Worker       int consumed = request_->upload_data_stream->Read(
267*6777b538SAndroid Build Coastguard Worker           request_headers_.get(), static_cast<int>(todo),
268*6777b538SAndroid Build Coastguard Worker           CompletionOnceCallback());
269*6777b538SAndroid Build Coastguard Worker       // Read() must succeed synchronously if not chunked and in memory.
270*6777b538SAndroid Build Coastguard Worker       DCHECK_GT(consumed, 0);
271*6777b538SAndroid Build Coastguard Worker       request_headers_->DidConsume(consumed);
272*6777b538SAndroid Build Coastguard Worker       todo -= consumed;
273*6777b538SAndroid Build Coastguard Worker     }
274*6777b538SAndroid Build Coastguard Worker     DCHECK(request_->upload_data_stream->IsEOF());
275*6777b538SAndroid Build Coastguard Worker     // Reset the offset, so the buffer can be read from the beginning.
276*6777b538SAndroid Build Coastguard Worker     request_headers_->SetOffset(0);
277*6777b538SAndroid Build Coastguard Worker     did_merge = true;
278*6777b538SAndroid Build Coastguard Worker 
279*6777b538SAndroid Build Coastguard Worker     NetLogSendRequestBody(net_log_, request_->upload_data_stream->size(),
280*6777b538SAndroid Build Coastguard Worker                           false, /* not chunked */
281*6777b538SAndroid Build Coastguard Worker                           true /* merged */);
282*6777b538SAndroid Build Coastguard Worker   }
283*6777b538SAndroid Build Coastguard Worker 
284*6777b538SAndroid Build Coastguard Worker   if (!did_merge) {
285*6777b538SAndroid Build Coastguard Worker     // If we didn't merge the body with the headers, then |request_headers_|
286*6777b538SAndroid Build Coastguard Worker     // contains just the HTTP headers.
287*6777b538SAndroid Build Coastguard Worker     size_t request_size = request.size();
288*6777b538SAndroid Build Coastguard Worker     scoped_refptr<StringIOBuffer> headers_io_buf =
289*6777b538SAndroid Build Coastguard Worker         base::MakeRefCounted<StringIOBuffer>(std::move(request));
290*6777b538SAndroid Build Coastguard Worker     request_headers_ = base::MakeRefCounted<DrainableIOBuffer>(
291*6777b538SAndroid Build Coastguard Worker         std::move(headers_io_buf), request_size);
292*6777b538SAndroid Build Coastguard Worker   }
293*6777b538SAndroid Build Coastguard Worker 
294*6777b538SAndroid Build Coastguard Worker   result = DoLoop(OK);
295*6777b538SAndroid Build Coastguard Worker   if (result == ERR_IO_PENDING)
296*6777b538SAndroid Build Coastguard Worker     callback_ = std::move(callback);
297*6777b538SAndroid Build Coastguard Worker 
298*6777b538SAndroid Build Coastguard Worker   return result > 0 ? OK : result;
299*6777b538SAndroid Build Coastguard Worker }
300*6777b538SAndroid Build Coastguard Worker 
ConfirmHandshake(CompletionOnceCallback callback)301*6777b538SAndroid Build Coastguard Worker int HttpStreamParser::ConfirmHandshake(CompletionOnceCallback callback) {
302*6777b538SAndroid Build Coastguard Worker   int ret = stream_socket_->ConfirmHandshake(
303*6777b538SAndroid Build Coastguard Worker       base::BindOnce(&HttpStreamParser::RunConfirmHandshakeCallback,
304*6777b538SAndroid Build Coastguard Worker                      weak_ptr_factory_.GetWeakPtr()));
305*6777b538SAndroid Build Coastguard Worker   if (ret == ERR_IO_PENDING)
306*6777b538SAndroid Build Coastguard Worker     confirm_handshake_callback_ = std::move(callback);
307*6777b538SAndroid Build Coastguard Worker   return ret;
308*6777b538SAndroid Build Coastguard Worker }
309*6777b538SAndroid Build Coastguard Worker 
ReadResponseHeaders(CompletionOnceCallback callback)310*6777b538SAndroid Build Coastguard Worker int HttpStreamParser::ReadResponseHeaders(CompletionOnceCallback callback) {
311*6777b538SAndroid Build Coastguard Worker   DCHECK(io_state_ == STATE_NONE || io_state_ == STATE_DONE);
312*6777b538SAndroid Build Coastguard Worker   DCHECK(callback_.is_null());
313*6777b538SAndroid Build Coastguard Worker   DCHECK(!callback.is_null());
314*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(0, read_buf_unused_offset_);
315*6777b538SAndroid Build Coastguard Worker   DCHECK(SendRequestBuffersEmpty());
316*6777b538SAndroid Build Coastguard Worker 
317*6777b538SAndroid Build Coastguard Worker   // This function can be called with io_state_ == STATE_DONE if the
318*6777b538SAndroid Build Coastguard Worker   // connection is closed after seeing just a 1xx response code.
319*6777b538SAndroid Build Coastguard Worker   if (io_state_ == STATE_DONE)
320*6777b538SAndroid Build Coastguard Worker     return ERR_CONNECTION_CLOSED;
321*6777b538SAndroid Build Coastguard Worker 
322*6777b538SAndroid Build Coastguard Worker   int result = OK;
323*6777b538SAndroid Build Coastguard Worker   io_state_ = STATE_READ_HEADERS;
324*6777b538SAndroid Build Coastguard Worker 
325*6777b538SAndroid Build Coastguard Worker   if (read_buf_->offset() > 0) {
326*6777b538SAndroid Build Coastguard Worker     // Simulate the state where the data was just read from the socket.
327*6777b538SAndroid Build Coastguard Worker     result = read_buf_->offset();
328*6777b538SAndroid Build Coastguard Worker     read_buf_->set_offset(0);
329*6777b538SAndroid Build Coastguard Worker   }
330*6777b538SAndroid Build Coastguard Worker   if (result > 0)
331*6777b538SAndroid Build Coastguard Worker     io_state_ = STATE_READ_HEADERS_COMPLETE;
332*6777b538SAndroid Build Coastguard Worker 
333*6777b538SAndroid Build Coastguard Worker   result = DoLoop(result);
334*6777b538SAndroid Build Coastguard Worker   if (result == ERR_IO_PENDING)
335*6777b538SAndroid Build Coastguard Worker     callback_ = std::move(callback);
336*6777b538SAndroid Build Coastguard Worker 
337*6777b538SAndroid Build Coastguard Worker   return result > 0 ? OK : result;
338*6777b538SAndroid Build Coastguard Worker }
339*6777b538SAndroid Build Coastguard Worker 
ReadResponseBody(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)340*6777b538SAndroid Build Coastguard Worker int HttpStreamParser::ReadResponseBody(IOBuffer* buf,
341*6777b538SAndroid Build Coastguard Worker                                        int buf_len,
342*6777b538SAndroid Build Coastguard Worker                                        CompletionOnceCallback callback) {
343*6777b538SAndroid Build Coastguard Worker   DCHECK(io_state_ == STATE_NONE || io_state_ == STATE_DONE);
344*6777b538SAndroid Build Coastguard Worker   DCHECK(callback_.is_null());
345*6777b538SAndroid Build Coastguard Worker   DCHECK(!callback.is_null());
346*6777b538SAndroid Build Coastguard Worker   DCHECK_LE(buf_len, kMaxBufSize);
347*6777b538SAndroid Build Coastguard Worker   DCHECK(SendRequestBuffersEmpty());
348*6777b538SAndroid Build Coastguard Worker   // Added to investigate crbug.com/499663.
349*6777b538SAndroid Build Coastguard Worker   CHECK(buf);
350*6777b538SAndroid Build Coastguard Worker 
351*6777b538SAndroid Build Coastguard Worker   if (io_state_ == STATE_DONE)
352*6777b538SAndroid Build Coastguard Worker     return OK;
353*6777b538SAndroid Build Coastguard Worker 
354*6777b538SAndroid Build Coastguard Worker   user_read_buf_ = buf;
355*6777b538SAndroid Build Coastguard Worker   user_read_buf_len_ = buf_len;
356*6777b538SAndroid Build Coastguard Worker   io_state_ = STATE_READ_BODY;
357*6777b538SAndroid Build Coastguard Worker 
358*6777b538SAndroid Build Coastguard Worker   // Invalidate HttpRequestInfo pointer. This is to allow the stream to be
359*6777b538SAndroid Build Coastguard Worker   // shared across multiple consumers.
360*6777b538SAndroid Build Coastguard Worker   // It is safe to reset it at this point since request_->upload_data_stream
361*6777b538SAndroid Build Coastguard Worker   // is also not needed anymore.
362*6777b538SAndroid Build Coastguard Worker   request_ = nullptr;
363*6777b538SAndroid Build Coastguard Worker 
364*6777b538SAndroid Build Coastguard Worker   int result = DoLoop(OK);
365*6777b538SAndroid Build Coastguard Worker   if (result == ERR_IO_PENDING)
366*6777b538SAndroid Build Coastguard Worker     callback_ = std::move(callback);
367*6777b538SAndroid Build Coastguard Worker 
368*6777b538SAndroid Build Coastguard Worker   return result;
369*6777b538SAndroid Build Coastguard Worker }
370*6777b538SAndroid Build Coastguard Worker 
OnIOComplete(int result)371*6777b538SAndroid Build Coastguard Worker void HttpStreamParser::OnIOComplete(int result) {
372*6777b538SAndroid Build Coastguard Worker   result = DoLoop(result);
373*6777b538SAndroid Build Coastguard Worker 
374*6777b538SAndroid Build Coastguard Worker   // The client callback can do anything, including destroying this class,
375*6777b538SAndroid Build Coastguard Worker   // so any pending callback must be issued after everything else is done.
376*6777b538SAndroid Build Coastguard Worker   if (result != ERR_IO_PENDING && !callback_.is_null()) {
377*6777b538SAndroid Build Coastguard Worker     std::move(callback_).Run(result);
378*6777b538SAndroid Build Coastguard Worker   }
379*6777b538SAndroid Build Coastguard Worker }
380*6777b538SAndroid Build Coastguard Worker 
DoLoop(int result)381*6777b538SAndroid Build Coastguard Worker int HttpStreamParser::DoLoop(int result) {
382*6777b538SAndroid Build Coastguard Worker   do {
383*6777b538SAndroid Build Coastguard Worker     DCHECK_NE(ERR_IO_PENDING, result);
384*6777b538SAndroid Build Coastguard Worker     DCHECK_NE(STATE_DONE, io_state_);
385*6777b538SAndroid Build Coastguard Worker     DCHECK_NE(STATE_NONE, io_state_);
386*6777b538SAndroid Build Coastguard Worker     State state = io_state_;
387*6777b538SAndroid Build Coastguard Worker     io_state_ = STATE_NONE;
388*6777b538SAndroid Build Coastguard Worker     switch (state) {
389*6777b538SAndroid Build Coastguard Worker       case STATE_SEND_HEADERS:
390*6777b538SAndroid Build Coastguard Worker         DCHECK_EQ(OK, result);
391*6777b538SAndroid Build Coastguard Worker         result = DoSendHeaders();
392*6777b538SAndroid Build Coastguard Worker         DCHECK_NE(STATE_NONE, io_state_);
393*6777b538SAndroid Build Coastguard Worker         break;
394*6777b538SAndroid Build Coastguard Worker       case STATE_SEND_HEADERS_COMPLETE:
395*6777b538SAndroid Build Coastguard Worker         result = DoSendHeadersComplete(result);
396*6777b538SAndroid Build Coastguard Worker         DCHECK_NE(STATE_NONE, io_state_);
397*6777b538SAndroid Build Coastguard Worker         break;
398*6777b538SAndroid Build Coastguard Worker       case STATE_SEND_BODY:
399*6777b538SAndroid Build Coastguard Worker         DCHECK_EQ(OK, result);
400*6777b538SAndroid Build Coastguard Worker         result = DoSendBody();
401*6777b538SAndroid Build Coastguard Worker         DCHECK_NE(STATE_NONE, io_state_);
402*6777b538SAndroid Build Coastguard Worker         break;
403*6777b538SAndroid Build Coastguard Worker       case STATE_SEND_BODY_COMPLETE:
404*6777b538SAndroid Build Coastguard Worker         result = DoSendBodyComplete(result);
405*6777b538SAndroid Build Coastguard Worker         DCHECK_NE(STATE_NONE, io_state_);
406*6777b538SAndroid Build Coastguard Worker         break;
407*6777b538SAndroid Build Coastguard Worker       case STATE_SEND_REQUEST_READ_BODY_COMPLETE:
408*6777b538SAndroid Build Coastguard Worker         result = DoSendRequestReadBodyComplete(result);
409*6777b538SAndroid Build Coastguard Worker         DCHECK_NE(STATE_NONE, io_state_);
410*6777b538SAndroid Build Coastguard Worker         break;
411*6777b538SAndroid Build Coastguard Worker       case STATE_SEND_REQUEST_COMPLETE:
412*6777b538SAndroid Build Coastguard Worker         result = DoSendRequestComplete(result);
413*6777b538SAndroid Build Coastguard Worker         break;
414*6777b538SAndroid Build Coastguard Worker       case STATE_READ_HEADERS:
415*6777b538SAndroid Build Coastguard Worker         net_log_.BeginEvent(NetLogEventType::HTTP_STREAM_PARSER_READ_HEADERS);
416*6777b538SAndroid Build Coastguard Worker         DCHECK_GE(result, 0);
417*6777b538SAndroid Build Coastguard Worker         result = DoReadHeaders();
418*6777b538SAndroid Build Coastguard Worker         break;
419*6777b538SAndroid Build Coastguard Worker       case STATE_READ_HEADERS_COMPLETE:
420*6777b538SAndroid Build Coastguard Worker         result = DoReadHeadersComplete(result);
421*6777b538SAndroid Build Coastguard Worker         net_log_.EndEventWithNetErrorCode(
422*6777b538SAndroid Build Coastguard Worker             NetLogEventType::HTTP_STREAM_PARSER_READ_HEADERS, result);
423*6777b538SAndroid Build Coastguard Worker         break;
424*6777b538SAndroid Build Coastguard Worker       case STATE_READ_BODY:
425*6777b538SAndroid Build Coastguard Worker         DCHECK_GE(result, 0);
426*6777b538SAndroid Build Coastguard Worker         result = DoReadBody();
427*6777b538SAndroid Build Coastguard Worker         break;
428*6777b538SAndroid Build Coastguard Worker       case STATE_READ_BODY_COMPLETE:
429*6777b538SAndroid Build Coastguard Worker         result = DoReadBodyComplete(result);
430*6777b538SAndroid Build Coastguard Worker         break;
431*6777b538SAndroid Build Coastguard Worker       default:
432*6777b538SAndroid Build Coastguard Worker         NOTREACHED();
433*6777b538SAndroid Build Coastguard Worker         break;
434*6777b538SAndroid Build Coastguard Worker     }
435*6777b538SAndroid Build Coastguard Worker   } while (result != ERR_IO_PENDING &&
436*6777b538SAndroid Build Coastguard Worker            (io_state_ != STATE_DONE && io_state_ != STATE_NONE));
437*6777b538SAndroid Build Coastguard Worker 
438*6777b538SAndroid Build Coastguard Worker   return result;
439*6777b538SAndroid Build Coastguard Worker }
440*6777b538SAndroid Build Coastguard Worker 
DoSendHeaders()441*6777b538SAndroid Build Coastguard Worker int HttpStreamParser::DoSendHeaders() {
442*6777b538SAndroid Build Coastguard Worker   int bytes_remaining = request_headers_->BytesRemaining();
443*6777b538SAndroid Build Coastguard Worker   DCHECK_GT(bytes_remaining, 0);
444*6777b538SAndroid Build Coastguard Worker 
445*6777b538SAndroid Build Coastguard Worker   // Record our best estimate of the 'request time' as the time when we send
446*6777b538SAndroid Build Coastguard Worker   // out the first bytes of the request headers.
447*6777b538SAndroid Build Coastguard Worker   if (bytes_remaining == request_headers_->size())
448*6777b538SAndroid Build Coastguard Worker     response_->request_time = base::Time::Now();
449*6777b538SAndroid Build Coastguard Worker 
450*6777b538SAndroid Build Coastguard Worker   io_state_ = STATE_SEND_HEADERS_COMPLETE;
451*6777b538SAndroid Build Coastguard Worker   return stream_socket_->Write(
452*6777b538SAndroid Build Coastguard Worker       request_headers_.get(), bytes_remaining, io_callback_,
453*6777b538SAndroid Build Coastguard Worker       NetworkTrafficAnnotationTag(traffic_annotation_));
454*6777b538SAndroid Build Coastguard Worker }
455*6777b538SAndroid Build Coastguard Worker 
DoSendHeadersComplete(int result)456*6777b538SAndroid Build Coastguard Worker int HttpStreamParser::DoSendHeadersComplete(int result) {
457*6777b538SAndroid Build Coastguard Worker   if (result < 0) {
458*6777b538SAndroid Build Coastguard Worker     // In the unlikely case that the headers and body were merged, all the
459*6777b538SAndroid Build Coastguard Worker     // the headers were sent, but not all of the body way, and |result| is
460*6777b538SAndroid Build Coastguard Worker     // an error that this should try reading after, stash the error for now and
461*6777b538SAndroid Build Coastguard Worker     // act like the request was successfully sent.
462*6777b538SAndroid Build Coastguard Worker     io_state_ = STATE_SEND_REQUEST_COMPLETE;
463*6777b538SAndroid Build Coastguard Worker     if (request_headers_->BytesConsumed() >= request_headers_length_ &&
464*6777b538SAndroid Build Coastguard Worker         ShouldTryReadingOnUploadError(result)) {
465*6777b538SAndroid Build Coastguard Worker       upload_error_ = result;
466*6777b538SAndroid Build Coastguard Worker       return OK;
467*6777b538SAndroid Build Coastguard Worker     }
468*6777b538SAndroid Build Coastguard Worker     return result;
469*6777b538SAndroid Build Coastguard Worker   }
470*6777b538SAndroid Build Coastguard Worker 
471*6777b538SAndroid Build Coastguard Worker   sent_bytes_ += result;
472*6777b538SAndroid Build Coastguard Worker   request_headers_->DidConsume(result);
473*6777b538SAndroid Build Coastguard Worker   if (request_headers_->BytesRemaining() > 0) {
474*6777b538SAndroid Build Coastguard Worker     io_state_ = STATE_SEND_HEADERS;
475*6777b538SAndroid Build Coastguard Worker     return OK;
476*6777b538SAndroid Build Coastguard Worker   }
477*6777b538SAndroid Build Coastguard Worker 
478*6777b538SAndroid Build Coastguard Worker   if (request_->upload_data_stream != nullptr &&
479*6777b538SAndroid Build Coastguard Worker       (request_->upload_data_stream->is_chunked() ||
480*6777b538SAndroid Build Coastguard Worker        // !IsEOF() indicates that the body wasn't merged.
481*6777b538SAndroid Build Coastguard Worker        (request_->upload_data_stream->size() > 0 &&
482*6777b538SAndroid Build Coastguard Worker         !request_->upload_data_stream->IsEOF()))) {
483*6777b538SAndroid Build Coastguard Worker     NetLogSendRequestBody(net_log_, request_->upload_data_stream->size(),
484*6777b538SAndroid Build Coastguard Worker                           request_->upload_data_stream->is_chunked(),
485*6777b538SAndroid Build Coastguard Worker                           false /* not merged */);
486*6777b538SAndroid Build Coastguard Worker     io_state_ = STATE_SEND_BODY;
487*6777b538SAndroid Build Coastguard Worker     return OK;
488*6777b538SAndroid Build Coastguard Worker   }
489*6777b538SAndroid Build Coastguard Worker 
490*6777b538SAndroid Build Coastguard Worker   // Finished sending the request.
491*6777b538SAndroid Build Coastguard Worker   io_state_ = STATE_SEND_REQUEST_COMPLETE;
492*6777b538SAndroid Build Coastguard Worker   return OK;
493*6777b538SAndroid Build Coastguard Worker }
494*6777b538SAndroid Build Coastguard Worker 
DoSendBody()495*6777b538SAndroid Build Coastguard Worker int HttpStreamParser::DoSendBody() {
496*6777b538SAndroid Build Coastguard Worker   if (request_body_send_buf_->BytesRemaining() > 0) {
497*6777b538SAndroid Build Coastguard Worker     io_state_ = STATE_SEND_BODY_COMPLETE;
498*6777b538SAndroid Build Coastguard Worker     return stream_socket_->Write(
499*6777b538SAndroid Build Coastguard Worker         request_body_send_buf_.get(), request_body_send_buf_->BytesRemaining(),
500*6777b538SAndroid Build Coastguard Worker         io_callback_, NetworkTrafficAnnotationTag(traffic_annotation_));
501*6777b538SAndroid Build Coastguard Worker   }
502*6777b538SAndroid Build Coastguard Worker 
503*6777b538SAndroid Build Coastguard Worker   if (request_->upload_data_stream->is_chunked() && sent_last_chunk_) {
504*6777b538SAndroid Build Coastguard Worker     // Finished sending the request.
505*6777b538SAndroid Build Coastguard Worker     io_state_ = STATE_SEND_REQUEST_COMPLETE;
506*6777b538SAndroid Build Coastguard Worker     return OK;
507*6777b538SAndroid Build Coastguard Worker   }
508*6777b538SAndroid Build Coastguard Worker 
509*6777b538SAndroid Build Coastguard Worker   request_body_read_buf_->Clear();
510*6777b538SAndroid Build Coastguard Worker   io_state_ = STATE_SEND_REQUEST_READ_BODY_COMPLETE;
511*6777b538SAndroid Build Coastguard Worker   return request_->upload_data_stream->Read(
512*6777b538SAndroid Build Coastguard Worker       request_body_read_buf_.get(), request_body_read_buf_->capacity(),
513*6777b538SAndroid Build Coastguard Worker       base::BindOnce(&HttpStreamParser::OnIOComplete,
514*6777b538SAndroid Build Coastguard Worker                      weak_ptr_factory_.GetWeakPtr()));
515*6777b538SAndroid Build Coastguard Worker }
516*6777b538SAndroid Build Coastguard Worker 
DoSendBodyComplete(int result)517*6777b538SAndroid Build Coastguard Worker int HttpStreamParser::DoSendBodyComplete(int result) {
518*6777b538SAndroid Build Coastguard Worker   if (result < 0) {
519*6777b538SAndroid Build Coastguard Worker     // If |result| is an error that this should try reading after, stash the
520*6777b538SAndroid Build Coastguard Worker     // error for now and act like the request was successfully sent.
521*6777b538SAndroid Build Coastguard Worker     io_state_ = STATE_SEND_REQUEST_COMPLETE;
522*6777b538SAndroid Build Coastguard Worker     if (ShouldTryReadingOnUploadError(result)) {
523*6777b538SAndroid Build Coastguard Worker       upload_error_ = result;
524*6777b538SAndroid Build Coastguard Worker       return OK;
525*6777b538SAndroid Build Coastguard Worker     }
526*6777b538SAndroid Build Coastguard Worker     return result;
527*6777b538SAndroid Build Coastguard Worker   }
528*6777b538SAndroid Build Coastguard Worker 
529*6777b538SAndroid Build Coastguard Worker   sent_bytes_ += result;
530*6777b538SAndroid Build Coastguard Worker   request_body_send_buf_->DidConsume(result);
531*6777b538SAndroid Build Coastguard Worker 
532*6777b538SAndroid Build Coastguard Worker   io_state_ = STATE_SEND_BODY;
533*6777b538SAndroid Build Coastguard Worker   return OK;
534*6777b538SAndroid Build Coastguard Worker }
535*6777b538SAndroid Build Coastguard Worker 
DoSendRequestReadBodyComplete(int result)536*6777b538SAndroid Build Coastguard Worker int HttpStreamParser::DoSendRequestReadBodyComplete(int result) {
537*6777b538SAndroid Build Coastguard Worker   // |result| is the result of read from the request body from the last call to
538*6777b538SAndroid Build Coastguard Worker   // DoSendBody().
539*6777b538SAndroid Build Coastguard Worker   if (result < 0) {
540*6777b538SAndroid Build Coastguard Worker     io_state_ = STATE_SEND_REQUEST_COMPLETE;
541*6777b538SAndroid Build Coastguard Worker     return result;
542*6777b538SAndroid Build Coastguard Worker   }
543*6777b538SAndroid Build Coastguard Worker 
544*6777b538SAndroid Build Coastguard Worker   // Chunked data needs to be encoded.
545*6777b538SAndroid Build Coastguard Worker   if (request_->upload_data_stream->is_chunked()) {
546*6777b538SAndroid Build Coastguard Worker     if (result == 0) {  // Reached the end.
547*6777b538SAndroid Build Coastguard Worker       DCHECK(request_->upload_data_stream->IsEOF());
548*6777b538SAndroid Build Coastguard Worker       sent_last_chunk_ = true;
549*6777b538SAndroid Build Coastguard Worker     }
550*6777b538SAndroid Build Coastguard Worker     // Encode the buffer as 1 chunk.
551*6777b538SAndroid Build Coastguard Worker     const std::string_view payload(request_body_read_buf_->data(), result);
552*6777b538SAndroid Build Coastguard Worker     request_body_send_buf_->Clear();
553*6777b538SAndroid Build Coastguard Worker     result = EncodeChunk(payload,
554*6777b538SAndroid Build Coastguard Worker                          request_body_send_buf_->data(),
555*6777b538SAndroid Build Coastguard Worker                          request_body_send_buf_->capacity());
556*6777b538SAndroid Build Coastguard Worker   }
557*6777b538SAndroid Build Coastguard Worker 
558*6777b538SAndroid Build Coastguard Worker   if (result == 0) {  // Reached the end.
559*6777b538SAndroid Build Coastguard Worker     // Reaching EOF means we can finish sending request body unless the data is
560*6777b538SAndroid Build Coastguard Worker     // chunked. (i.e. No need to send the terminal chunk.)
561*6777b538SAndroid Build Coastguard Worker     DCHECK(request_->upload_data_stream->IsEOF());
562*6777b538SAndroid Build Coastguard Worker     DCHECK(!request_->upload_data_stream->is_chunked());
563*6777b538SAndroid Build Coastguard Worker     // Finished sending the request.
564*6777b538SAndroid Build Coastguard Worker     io_state_ = STATE_SEND_REQUEST_COMPLETE;
565*6777b538SAndroid Build Coastguard Worker   } else if (result > 0) {
566*6777b538SAndroid Build Coastguard Worker     request_body_send_buf_->DidAppend(result);
567*6777b538SAndroid Build Coastguard Worker     result = 0;
568*6777b538SAndroid Build Coastguard Worker     io_state_ = STATE_SEND_BODY;
569*6777b538SAndroid Build Coastguard Worker   }
570*6777b538SAndroid Build Coastguard Worker   return result;
571*6777b538SAndroid Build Coastguard Worker }
572*6777b538SAndroid Build Coastguard Worker 
DoSendRequestComplete(int result)573*6777b538SAndroid Build Coastguard Worker int HttpStreamParser::DoSendRequestComplete(int result) {
574*6777b538SAndroid Build Coastguard Worker   DCHECK_NE(result, ERR_IO_PENDING);
575*6777b538SAndroid Build Coastguard Worker   request_headers_ = nullptr;
576*6777b538SAndroid Build Coastguard Worker   request_body_send_buf_ = nullptr;
577*6777b538SAndroid Build Coastguard Worker   request_body_read_buf_ = nullptr;
578*6777b538SAndroid Build Coastguard Worker 
579*6777b538SAndroid Build Coastguard Worker   return result;
580*6777b538SAndroid Build Coastguard Worker }
581*6777b538SAndroid Build Coastguard Worker 
DoReadHeaders()582*6777b538SAndroid Build Coastguard Worker int HttpStreamParser::DoReadHeaders() {
583*6777b538SAndroid Build Coastguard Worker   io_state_ = STATE_READ_HEADERS_COMPLETE;
584*6777b538SAndroid Build Coastguard Worker 
585*6777b538SAndroid Build Coastguard Worker   // Grow the read buffer if necessary.
586*6777b538SAndroid Build Coastguard Worker   if (read_buf_->RemainingCapacity() == 0)
587*6777b538SAndroid Build Coastguard Worker     read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize);
588*6777b538SAndroid Build Coastguard Worker 
589*6777b538SAndroid Build Coastguard Worker   // http://crbug.com/16371: We're seeing |user_buf_->data()| return NULL.
590*6777b538SAndroid Build Coastguard Worker   // See if the user is passing in an IOBuffer with a NULL |data_|.
591*6777b538SAndroid Build Coastguard Worker   CHECK(read_buf_->data());
592*6777b538SAndroid Build Coastguard Worker 
593*6777b538SAndroid Build Coastguard Worker   return stream_socket_->Read(read_buf_.get(), read_buf_->RemainingCapacity(),
594*6777b538SAndroid Build Coastguard Worker                               io_callback_);
595*6777b538SAndroid Build Coastguard Worker }
596*6777b538SAndroid Build Coastguard Worker 
DoReadHeadersComplete(int result)597*6777b538SAndroid Build Coastguard Worker int HttpStreamParser::DoReadHeadersComplete(int result) {
598*6777b538SAndroid Build Coastguard Worker   // DoReadHeadersComplete is called with the result of Socket::Read, which is a
599*6777b538SAndroid Build Coastguard Worker   // (byte_count | error), and returns (error | OK).
600*6777b538SAndroid Build Coastguard Worker 
601*6777b538SAndroid Build Coastguard Worker   result = HandleReadHeaderResult(result);
602*6777b538SAndroid Build Coastguard Worker 
603*6777b538SAndroid Build Coastguard Worker   // TODO(mmenke):  The code below is ugly and hacky.  A much better and more
604*6777b538SAndroid Build Coastguard Worker   // flexible long term solution would be to separate out the read and write
605*6777b538SAndroid Build Coastguard Worker   // loops, though this would involve significant changes, both here and
606*6777b538SAndroid Build Coastguard Worker   // elsewhere (WebSockets, for instance).
607*6777b538SAndroid Build Coastguard Worker 
608*6777b538SAndroid Build Coastguard Worker   // If still reading the headers, or there was no error uploading the request
609*6777b538SAndroid Build Coastguard Worker   // body, just return the result.
610*6777b538SAndroid Build Coastguard Worker   if (io_state_ == STATE_READ_HEADERS || upload_error_ == OK)
611*6777b538SAndroid Build Coastguard Worker     return result;
612*6777b538SAndroid Build Coastguard Worker 
613*6777b538SAndroid Build Coastguard Worker   // If the result is ERR_IO_PENDING, |io_state_| should be STATE_READ_HEADERS.
614*6777b538SAndroid Build Coastguard Worker   DCHECK_NE(ERR_IO_PENDING, result);
615*6777b538SAndroid Build Coastguard Worker 
616*6777b538SAndroid Build Coastguard Worker   // On errors, use the original error received when sending the request.
617*6777b538SAndroid Build Coastguard Worker   // The main cases where these are different is when there's a header-related
618*6777b538SAndroid Build Coastguard Worker   // error code, or when there's an ERR_CONNECTION_CLOSED, which can result in
619*6777b538SAndroid Build Coastguard Worker   // special handling of partial responses and HTTP/0.9 responses.
620*6777b538SAndroid Build Coastguard Worker   if (result < 0) {
621*6777b538SAndroid Build Coastguard Worker     // Nothing else to do.  In the HTTP/0.9 or only partial headers received
622*6777b538SAndroid Build Coastguard Worker     // cases, can normally go to other states after an error reading headers.
623*6777b538SAndroid Build Coastguard Worker     io_state_ = STATE_DONE;
624*6777b538SAndroid Build Coastguard Worker     // Don't let caller see the headers.
625*6777b538SAndroid Build Coastguard Worker     response_->headers = nullptr;
626*6777b538SAndroid Build Coastguard Worker     return upload_error_;
627*6777b538SAndroid Build Coastguard Worker   }
628*6777b538SAndroid Build Coastguard Worker 
629*6777b538SAndroid Build Coastguard Worker   // Skip over 1xx responses as usual, and allow 4xx/5xx error responses to
630*6777b538SAndroid Build Coastguard Worker   // override the error received while uploading the body.
631*6777b538SAndroid Build Coastguard Worker   int response_code_class = response_->headers->response_code() / 100;
632*6777b538SAndroid Build Coastguard Worker   if (response_code_class == 1 || response_code_class == 4 ||
633*6777b538SAndroid Build Coastguard Worker       response_code_class == 5) {
634*6777b538SAndroid Build Coastguard Worker     return result;
635*6777b538SAndroid Build Coastguard Worker   }
636*6777b538SAndroid Build Coastguard Worker 
637*6777b538SAndroid Build Coastguard Worker   // All other status codes are not allowed after an error during upload, to
638*6777b538SAndroid Build Coastguard Worker   // make sure the consumer has some indication there was an error.
639*6777b538SAndroid Build Coastguard Worker 
640*6777b538SAndroid Build Coastguard Worker   // Nothing else to do.
641*6777b538SAndroid Build Coastguard Worker   io_state_ = STATE_DONE;
642*6777b538SAndroid Build Coastguard Worker   // Don't let caller see the headers.
643*6777b538SAndroid Build Coastguard Worker   response_->headers = nullptr;
644*6777b538SAndroid Build Coastguard Worker   return upload_error_;
645*6777b538SAndroid Build Coastguard Worker }
646*6777b538SAndroid Build Coastguard Worker 
DoReadBody()647*6777b538SAndroid Build Coastguard Worker int HttpStreamParser::DoReadBody() {
648*6777b538SAndroid Build Coastguard Worker   io_state_ = STATE_READ_BODY_COMPLETE;
649*6777b538SAndroid Build Coastguard Worker 
650*6777b538SAndroid Build Coastguard Worker   // Added to investigate crbug.com/499663.
651*6777b538SAndroid Build Coastguard Worker   CHECK(user_read_buf_.get());
652*6777b538SAndroid Build Coastguard Worker 
653*6777b538SAndroid Build Coastguard Worker   // There may be additional data after the end of the body waiting in
654*6777b538SAndroid Build Coastguard Worker   // the socket, but in order to find out, we need to read as much as possible.
655*6777b538SAndroid Build Coastguard Worker   // If there is additional data, discard it and close the connection later.
656*6777b538SAndroid Build Coastguard Worker   int64_t remaining_read_len = user_read_buf_len_;
657*6777b538SAndroid Build Coastguard Worker   int64_t remaining_body = 0;
658*6777b538SAndroid Build Coastguard Worker   if (truncate_to_content_length_enabled_ && !chunked_decoder_.get() &&
659*6777b538SAndroid Build Coastguard Worker       response_body_length_ >= 0) {
660*6777b538SAndroid Build Coastguard Worker     remaining_body = response_body_length_ - response_body_read_;
661*6777b538SAndroid Build Coastguard Worker     remaining_read_len = std::min(remaining_read_len, remaining_body);
662*6777b538SAndroid Build Coastguard Worker   }
663*6777b538SAndroid Build Coastguard Worker 
664*6777b538SAndroid Build Coastguard Worker   // There may be some data left over from reading the response headers.
665*6777b538SAndroid Build Coastguard Worker   if (read_buf_->offset()) {
666*6777b538SAndroid Build Coastguard Worker     int64_t available = read_buf_->offset() - read_buf_unused_offset_;
667*6777b538SAndroid Build Coastguard Worker     if (available) {
668*6777b538SAndroid Build Coastguard Worker       CHECK_GT(available, 0);
669*6777b538SAndroid Build Coastguard Worker       int64_t bytes_from_buffer = std::min(available, remaining_read_len);
670*6777b538SAndroid Build Coastguard Worker       memcpy(user_read_buf_->data(),
671*6777b538SAndroid Build Coastguard Worker              read_buf_->StartOfBuffer() + read_buf_unused_offset_,
672*6777b538SAndroid Build Coastguard Worker              bytes_from_buffer);
673*6777b538SAndroid Build Coastguard Worker       read_buf_unused_offset_ += bytes_from_buffer;
674*6777b538SAndroid Build Coastguard Worker       // Clear out the remaining data if we've reached the end of the body.
675*6777b538SAndroid Build Coastguard Worker       if (truncate_to_content_length_enabled_ &&
676*6777b538SAndroid Build Coastguard Worker           (remaining_body == bytes_from_buffer) &&
677*6777b538SAndroid Build Coastguard Worker           (available > bytes_from_buffer)) {
678*6777b538SAndroid Build Coastguard Worker         read_buf_->SetCapacity(0);
679*6777b538SAndroid Build Coastguard Worker         read_buf_unused_offset_ = 0;
680*6777b538SAndroid Build Coastguard Worker         discarded_extra_data_ = true;
681*6777b538SAndroid Build Coastguard Worker       } else if (bytes_from_buffer == available) {
682*6777b538SAndroid Build Coastguard Worker         read_buf_->SetCapacity(0);
683*6777b538SAndroid Build Coastguard Worker         read_buf_unused_offset_ = 0;
684*6777b538SAndroid Build Coastguard Worker       }
685*6777b538SAndroid Build Coastguard Worker       return bytes_from_buffer;
686*6777b538SAndroid Build Coastguard Worker     } else {
687*6777b538SAndroid Build Coastguard Worker       read_buf_->SetCapacity(0);
688*6777b538SAndroid Build Coastguard Worker       read_buf_unused_offset_ = 0;
689*6777b538SAndroid Build Coastguard Worker     }
690*6777b538SAndroid Build Coastguard Worker   }
691*6777b538SAndroid Build Coastguard Worker 
692*6777b538SAndroid Build Coastguard Worker   // Check to see if we're done reading.
693*6777b538SAndroid Build Coastguard Worker   if (IsResponseBodyComplete())
694*6777b538SAndroid Build Coastguard Worker     return 0;
695*6777b538SAndroid Build Coastguard Worker 
696*6777b538SAndroid Build Coastguard Worker   // DoReadBodyComplete will truncate the amount read if necessary whether the
697*6777b538SAndroid Build Coastguard Worker   // read completes synchronously or asynchronously.
698*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(0, read_buf_->offset());
699*6777b538SAndroid Build Coastguard Worker   return stream_socket_->Read(user_read_buf_.get(), user_read_buf_len_,
700*6777b538SAndroid Build Coastguard Worker                               io_callback_);
701*6777b538SAndroid Build Coastguard Worker }
702*6777b538SAndroid Build Coastguard Worker 
DoReadBodyComplete(int result)703*6777b538SAndroid Build Coastguard Worker int HttpStreamParser::DoReadBodyComplete(int result) {
704*6777b538SAndroid Build Coastguard Worker   // Check to see if we've read too much and need to discard data before we
705*6777b538SAndroid Build Coastguard Worker   // increment received_bytes_ and response_body_read_ or otherwise start
706*6777b538SAndroid Build Coastguard Worker   // processing the data.
707*6777b538SAndroid Build Coastguard Worker   if (truncate_to_content_length_enabled_ && !chunked_decoder_.get() &&
708*6777b538SAndroid Build Coastguard Worker       response_body_length_ >= 0) {
709*6777b538SAndroid Build Coastguard Worker     // Calculate how much we should have been allowed to read to not go beyond
710*6777b538SAndroid Build Coastguard Worker     // the Content-Length.
711*6777b538SAndroid Build Coastguard Worker     int64_t remaining_body = response_body_length_ - response_body_read_;
712*6777b538SAndroid Build Coastguard Worker     int64_t remaining_read_len =
713*6777b538SAndroid Build Coastguard Worker         std::min(static_cast<int64_t>(user_read_buf_len_), remaining_body);
714*6777b538SAndroid Build Coastguard Worker     if (result > remaining_read_len) {
715*6777b538SAndroid Build Coastguard Worker       // Truncate to only what is in the body.
716*6777b538SAndroid Build Coastguard Worker       result = remaining_read_len;
717*6777b538SAndroid Build Coastguard Worker       discarded_extra_data_ = true;
718*6777b538SAndroid Build Coastguard Worker     }
719*6777b538SAndroid Build Coastguard Worker   }
720*6777b538SAndroid Build Coastguard Worker 
721*6777b538SAndroid Build Coastguard Worker   // When the connection is closed, there are numerous ways to interpret it.
722*6777b538SAndroid Build Coastguard Worker   //
723*6777b538SAndroid Build Coastguard Worker   //  - If a Content-Length header is present and the body contains exactly that
724*6777b538SAndroid Build Coastguard Worker   //    number of bytes at connection close, the response is successful.
725*6777b538SAndroid Build Coastguard Worker   //
726*6777b538SAndroid Build Coastguard Worker   //  - If a Content-Length header is present and the body contains fewer bytes
727*6777b538SAndroid Build Coastguard Worker   //    than promised by the header at connection close, it may indicate that
728*6777b538SAndroid Build Coastguard Worker   //    the connection was closed prematurely, or it may indicate that the
729*6777b538SAndroid Build Coastguard Worker   //    server sent an invalid Content-Length header. Unfortunately, the invalid
730*6777b538SAndroid Build Coastguard Worker   //    Content-Length header case does occur in practice and other browsers are
731*6777b538SAndroid Build Coastguard Worker   //    tolerant of it. We choose to treat it as an error for now, but the
732*6777b538SAndroid Build Coastguard Worker   //    download system treats it as a non-error, and URLRequestHttpJob also
733*6777b538SAndroid Build Coastguard Worker   //    treats it as OK if the Content-Length is the post-decoded body content
734*6777b538SAndroid Build Coastguard Worker   //    length.
735*6777b538SAndroid Build Coastguard Worker   //
736*6777b538SAndroid Build Coastguard Worker   //  - If chunked encoding is used and the terminating chunk has been processed
737*6777b538SAndroid Build Coastguard Worker   //    when the connection is closed, the response is successful.
738*6777b538SAndroid Build Coastguard Worker   //
739*6777b538SAndroid Build Coastguard Worker   //  - If chunked encoding is used and the terminating chunk has not been
740*6777b538SAndroid Build Coastguard Worker   //    processed when the connection is closed, it may indicate that the
741*6777b538SAndroid Build Coastguard Worker   //    connection was closed prematurely or it may indicate that the server
742*6777b538SAndroid Build Coastguard Worker   //    sent an invalid chunked encoding. We choose to treat it as
743*6777b538SAndroid Build Coastguard Worker   //    an invalid chunked encoding.
744*6777b538SAndroid Build Coastguard Worker   //
745*6777b538SAndroid Build Coastguard Worker   //  - If a Content-Length is not present and chunked encoding is not used,
746*6777b538SAndroid Build Coastguard Worker   //    connection close is the only way to signal that the response is
747*6777b538SAndroid Build Coastguard Worker   //    complete. Unfortunately, this also means that there is no way to detect
748*6777b538SAndroid Build Coastguard Worker   //    early close of a connection. No error is returned.
749*6777b538SAndroid Build Coastguard Worker   if (result == 0 && !IsResponseBodyComplete() && CanFindEndOfResponse()) {
750*6777b538SAndroid Build Coastguard Worker     if (chunked_decoder_.get())
751*6777b538SAndroid Build Coastguard Worker       result = ERR_INCOMPLETE_CHUNKED_ENCODING;
752*6777b538SAndroid Build Coastguard Worker     else
753*6777b538SAndroid Build Coastguard Worker       result = ERR_CONTENT_LENGTH_MISMATCH;
754*6777b538SAndroid Build Coastguard Worker   }
755*6777b538SAndroid Build Coastguard Worker 
756*6777b538SAndroid Build Coastguard Worker   if (result > 0)
757*6777b538SAndroid Build Coastguard Worker     received_bytes_ += result;
758*6777b538SAndroid Build Coastguard Worker 
759*6777b538SAndroid Build Coastguard Worker   // Filter incoming data if appropriate.  FilterBuf may return an error.
760*6777b538SAndroid Build Coastguard Worker   if (result > 0 && chunked_decoder_.get()) {
761*6777b538SAndroid Build Coastguard Worker     result = chunked_decoder_->FilterBuf(user_read_buf_->data(), result);
762*6777b538SAndroid Build Coastguard Worker     if (result == 0 && !chunked_decoder_->reached_eof()) {
763*6777b538SAndroid Build Coastguard Worker       // Don't signal completion of the Read call yet or else it'll look like
764*6777b538SAndroid Build Coastguard Worker       // we received end-of-file.  Wait for more data.
765*6777b538SAndroid Build Coastguard Worker       io_state_ = STATE_READ_BODY;
766*6777b538SAndroid Build Coastguard Worker       return OK;
767*6777b538SAndroid Build Coastguard Worker     }
768*6777b538SAndroid Build Coastguard Worker   }
769*6777b538SAndroid Build Coastguard Worker 
770*6777b538SAndroid Build Coastguard Worker   if (result > 0)
771*6777b538SAndroid Build Coastguard Worker     response_body_read_ += result;
772*6777b538SAndroid Build Coastguard Worker 
773*6777b538SAndroid Build Coastguard Worker   if (result <= 0 || IsResponseBodyComplete()) {
774*6777b538SAndroid Build Coastguard Worker     io_state_ = STATE_DONE;
775*6777b538SAndroid Build Coastguard Worker 
776*6777b538SAndroid Build Coastguard Worker     // Save the overflow data, which can be in two places.  There may be
777*6777b538SAndroid Build Coastguard Worker     // some left over in |user_read_buf_|, plus there may be more
778*6777b538SAndroid Build Coastguard Worker     // in |read_buf_|.  But the part left over in |user_read_buf_| must have
779*6777b538SAndroid Build Coastguard Worker     // come from the |read_buf_|, so there's room to put it back at the
780*6777b538SAndroid Build Coastguard Worker     // start first.
781*6777b538SAndroid Build Coastguard Worker     int additional_save_amount = read_buf_->offset() - read_buf_unused_offset_;
782*6777b538SAndroid Build Coastguard Worker     int save_amount = 0;
783*6777b538SAndroid Build Coastguard Worker     if (chunked_decoder_.get()) {
784*6777b538SAndroid Build Coastguard Worker       save_amount = chunked_decoder_->bytes_after_eof();
785*6777b538SAndroid Build Coastguard Worker     } else if (response_body_length_ >= 0) {
786*6777b538SAndroid Build Coastguard Worker       int64_t extra_data_read = response_body_read_ - response_body_length_;
787*6777b538SAndroid Build Coastguard Worker       if (extra_data_read > 0) {
788*6777b538SAndroid Build Coastguard Worker         save_amount = static_cast<int>(extra_data_read);
789*6777b538SAndroid Build Coastguard Worker         if (result > 0)
790*6777b538SAndroid Build Coastguard Worker           result -= save_amount;
791*6777b538SAndroid Build Coastguard Worker       }
792*6777b538SAndroid Build Coastguard Worker     }
793*6777b538SAndroid Build Coastguard Worker 
794*6777b538SAndroid Build Coastguard Worker     CHECK_LE(save_amount + additional_save_amount, kMaxBufSize);
795*6777b538SAndroid Build Coastguard Worker     if (read_buf_->capacity() < save_amount + additional_save_amount) {
796*6777b538SAndroid Build Coastguard Worker       read_buf_->SetCapacity(save_amount + additional_save_amount);
797*6777b538SAndroid Build Coastguard Worker     }
798*6777b538SAndroid Build Coastguard Worker 
799*6777b538SAndroid Build Coastguard Worker     if (save_amount) {
800*6777b538SAndroid Build Coastguard Worker       received_bytes_ -= save_amount;
801*6777b538SAndroid Build Coastguard Worker       memcpy(read_buf_->StartOfBuffer(), user_read_buf_->data() + result,
802*6777b538SAndroid Build Coastguard Worker              save_amount);
803*6777b538SAndroid Build Coastguard Worker     }
804*6777b538SAndroid Build Coastguard Worker     read_buf_->set_offset(save_amount);
805*6777b538SAndroid Build Coastguard Worker     if (additional_save_amount) {
806*6777b538SAndroid Build Coastguard Worker       memmove(read_buf_->data(),
807*6777b538SAndroid Build Coastguard Worker               read_buf_->StartOfBuffer() + read_buf_unused_offset_,
808*6777b538SAndroid Build Coastguard Worker               additional_save_amount);
809*6777b538SAndroid Build Coastguard Worker       read_buf_->set_offset(save_amount + additional_save_amount);
810*6777b538SAndroid Build Coastguard Worker     }
811*6777b538SAndroid Build Coastguard Worker     read_buf_unused_offset_ = 0;
812*6777b538SAndroid Build Coastguard Worker   } else {
813*6777b538SAndroid Build Coastguard Worker     // Now waiting for more of the body to be read.
814*6777b538SAndroid Build Coastguard Worker     user_read_buf_ = nullptr;
815*6777b538SAndroid Build Coastguard Worker     user_read_buf_len_ = 0;
816*6777b538SAndroid Build Coastguard Worker   }
817*6777b538SAndroid Build Coastguard Worker 
818*6777b538SAndroid Build Coastguard Worker   return result;
819*6777b538SAndroid Build Coastguard Worker }
820*6777b538SAndroid Build Coastguard Worker 
HandleReadHeaderResult(int result)821*6777b538SAndroid Build Coastguard Worker int HttpStreamParser::HandleReadHeaderResult(int result) {
822*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(0, read_buf_unused_offset_);
823*6777b538SAndroid Build Coastguard Worker 
824*6777b538SAndroid Build Coastguard Worker   if (result == 0)
825*6777b538SAndroid Build Coastguard Worker     result = ERR_CONNECTION_CLOSED;
826*6777b538SAndroid Build Coastguard Worker 
827*6777b538SAndroid Build Coastguard Worker   if (result == ERR_CONNECTION_CLOSED) {
828*6777b538SAndroid Build Coastguard Worker     // The connection closed without getting any more data.
829*6777b538SAndroid Build Coastguard Worker     if (read_buf_->offset() == 0) {
830*6777b538SAndroid Build Coastguard Worker       io_state_ = STATE_DONE;
831*6777b538SAndroid Build Coastguard Worker       // If the connection has not been reused, it may have been a 0-length
832*6777b538SAndroid Build Coastguard Worker       // HTTP/0.9 responses, but it was most likely an error, so just return
833*6777b538SAndroid Build Coastguard Worker       // ERR_EMPTY_RESPONSE instead. If the connection was reused, just pass
834*6777b538SAndroid Build Coastguard Worker       // on the original connection close error, as rather than being an
835*6777b538SAndroid Build Coastguard Worker       // empty HTTP/0.9 response it's much more likely the server closed the
836*6777b538SAndroid Build Coastguard Worker       // socket before it received the request.
837*6777b538SAndroid Build Coastguard Worker       if (!connection_is_reused_)
838*6777b538SAndroid Build Coastguard Worker         return ERR_EMPTY_RESPONSE;
839*6777b538SAndroid Build Coastguard Worker       return result;
840*6777b538SAndroid Build Coastguard Worker     }
841*6777b538SAndroid Build Coastguard Worker 
842*6777b538SAndroid Build Coastguard Worker     // Accepting truncated headers over HTTPS is a potential security
843*6777b538SAndroid Build Coastguard Worker     // vulnerability, so just return an error in that case.
844*6777b538SAndroid Build Coastguard Worker     //
845*6777b538SAndroid Build Coastguard Worker     // If response_header_start_offset_ is std::string::npos, this may be a < 8
846*6777b538SAndroid Build Coastguard Worker     // byte HTTP/0.9 response. However, accepting such a response over HTTPS
847*6777b538SAndroid Build Coastguard Worker     // would allow a MITM to truncate an HTTP/1.x status line to look like a
848*6777b538SAndroid Build Coastguard Worker     // short HTTP/0.9 response if the peer put a record boundary at the first 8
849*6777b538SAndroid Build Coastguard Worker     // bytes. To ensure that all response headers received over HTTPS are
850*6777b538SAndroid Build Coastguard Worker     // pristine, treat such responses as errors.
851*6777b538SAndroid Build Coastguard Worker     //
852*6777b538SAndroid Build Coastguard Worker     // TODO(mmenke):  Returning ERR_RESPONSE_HEADERS_TRUNCATED when a response
853*6777b538SAndroid Build Coastguard Worker     // looks like an HTTP/0.9 response is weird.  Should either come up with
854*6777b538SAndroid Build Coastguard Worker     // another error code, or, better, disable HTTP/0.9 over HTTPS (and give
855*6777b538SAndroid Build Coastguard Worker     // that a new error code).
856*6777b538SAndroid Build Coastguard Worker     if (request_->url.SchemeIsCryptographic()) {
857*6777b538SAndroid Build Coastguard Worker       io_state_ = STATE_DONE;
858*6777b538SAndroid Build Coastguard Worker       return ERR_RESPONSE_HEADERS_TRUNCATED;
859*6777b538SAndroid Build Coastguard Worker     }
860*6777b538SAndroid Build Coastguard Worker 
861*6777b538SAndroid Build Coastguard Worker     // Parse things as well as we can and let the caller decide what to do.
862*6777b538SAndroid Build Coastguard Worker     int end_offset;
863*6777b538SAndroid Build Coastguard Worker     if (response_header_start_offset_ != std::string::npos) {
864*6777b538SAndroid Build Coastguard Worker       // The response looks to be a truncated set of HTTP headers.
865*6777b538SAndroid Build Coastguard Worker       io_state_ = STATE_READ_BODY_COMPLETE;
866*6777b538SAndroid Build Coastguard Worker       end_offset = read_buf_->offset();
867*6777b538SAndroid Build Coastguard Worker     } else {
868*6777b538SAndroid Build Coastguard Worker       // The response is apparently using HTTP/0.9.  Treat the entire response
869*6777b538SAndroid Build Coastguard Worker       // as the body.
870*6777b538SAndroid Build Coastguard Worker       end_offset = 0;
871*6777b538SAndroid Build Coastguard Worker     }
872*6777b538SAndroid Build Coastguard Worker     int rv = ParseResponseHeaders(end_offset);
873*6777b538SAndroid Build Coastguard Worker     if (rv < 0)
874*6777b538SAndroid Build Coastguard Worker       return rv;
875*6777b538SAndroid Build Coastguard Worker     return result;
876*6777b538SAndroid Build Coastguard Worker   }
877*6777b538SAndroid Build Coastguard Worker 
878*6777b538SAndroid Build Coastguard Worker   if (result < 0) {
879*6777b538SAndroid Build Coastguard Worker     if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
880*6777b538SAndroid Build Coastguard Worker       // TODO(https://crbug.com/332234173): Assuming this isn't hit, remove the
881*6777b538SAndroid Build Coastguard Worker       // SchemeIsCryptographic() check.
882*6777b538SAndroid Build Coastguard Worker       DUMP_WILL_BE_CHECK(request_->url.SchemeIsCryptographic());
883*6777b538SAndroid Build Coastguard Worker       if (request_->url.SchemeIsCryptographic()) {
884*6777b538SAndroid Build Coastguard Worker         response_->cert_request_info =
885*6777b538SAndroid Build Coastguard Worker             base::MakeRefCounted<SSLCertRequestInfo>();
886*6777b538SAndroid Build Coastguard Worker         stream_socket_->GetSSLCertRequestInfo(
887*6777b538SAndroid Build Coastguard Worker             response_->cert_request_info.get());
888*6777b538SAndroid Build Coastguard Worker       }
889*6777b538SAndroid Build Coastguard Worker     }
890*6777b538SAndroid Build Coastguard Worker     io_state_ = STATE_DONE;
891*6777b538SAndroid Build Coastguard Worker     return result;
892*6777b538SAndroid Build Coastguard Worker   }
893*6777b538SAndroid Build Coastguard Worker 
894*6777b538SAndroid Build Coastguard Worker   // Record our best estimate of the 'response time' as the time when we read
895*6777b538SAndroid Build Coastguard Worker   // the first bytes of the response headers.
896*6777b538SAndroid Build Coastguard Worker   if (read_buf_->offset() == 0) {
897*6777b538SAndroid Build Coastguard Worker     response_->response_time = base::Time::Now();
898*6777b538SAndroid Build Coastguard Worker     // Also keep the time as base::TimeTicks for `first_response_start_time_`
899*6777b538SAndroid Build Coastguard Worker     // and `non_informational_response_start_time_`.
900*6777b538SAndroid Build Coastguard Worker     current_response_start_time_ = base::TimeTicks::Now();
901*6777b538SAndroid Build Coastguard Worker   }
902*6777b538SAndroid Build Coastguard Worker 
903*6777b538SAndroid Build Coastguard Worker   // For |first_response_start_time_|, use the time that we received the first
904*6777b538SAndroid Build Coastguard Worker   // byte of *any* response- including 1XX, as per the resource timing spec for
905*6777b538SAndroid Build Coastguard Worker   // responseStart (see note at
906*6777b538SAndroid Build Coastguard Worker   // https://www.w3.org/TR/resource-timing-2/#dom-performanceresourcetiming-responsestart).
907*6777b538SAndroid Build Coastguard Worker   if (first_response_start_time_.is_null())
908*6777b538SAndroid Build Coastguard Worker     first_response_start_time_ = current_response_start_time_;
909*6777b538SAndroid Build Coastguard Worker 
910*6777b538SAndroid Build Coastguard Worker   read_buf_->set_offset(read_buf_->offset() + result);
911*6777b538SAndroid Build Coastguard Worker   DCHECK_LE(read_buf_->offset(), read_buf_->capacity());
912*6777b538SAndroid Build Coastguard Worker   DCHECK_GT(result, 0);
913*6777b538SAndroid Build Coastguard Worker 
914*6777b538SAndroid Build Coastguard Worker   int end_of_header_offset = FindAndParseResponseHeaders(result);
915*6777b538SAndroid Build Coastguard Worker 
916*6777b538SAndroid Build Coastguard Worker   // Note: -1 is special, it indicates we haven't found the end of headers.
917*6777b538SAndroid Build Coastguard Worker   // Anything less than -1 is a net::Error, so we bail out.
918*6777b538SAndroid Build Coastguard Worker   if (end_of_header_offset < -1)
919*6777b538SAndroid Build Coastguard Worker     return end_of_header_offset;
920*6777b538SAndroid Build Coastguard Worker 
921*6777b538SAndroid Build Coastguard Worker   if (end_of_header_offset == -1) {
922*6777b538SAndroid Build Coastguard Worker     io_state_ = STATE_READ_HEADERS;
923*6777b538SAndroid Build Coastguard Worker     // Prevent growing the headers buffer indefinitely.
924*6777b538SAndroid Build Coastguard Worker     if (read_buf_->offset() >= kMaxHeaderBufSize) {
925*6777b538SAndroid Build Coastguard Worker       io_state_ = STATE_DONE;
926*6777b538SAndroid Build Coastguard Worker       return ERR_RESPONSE_HEADERS_TOO_BIG;
927*6777b538SAndroid Build Coastguard Worker     }
928*6777b538SAndroid Build Coastguard Worker   } else {
929*6777b538SAndroid Build Coastguard Worker     CalculateResponseBodySize();
930*6777b538SAndroid Build Coastguard Worker 
931*6777b538SAndroid Build Coastguard Worker     // Record the response start time if this response is not informational
932*6777b538SAndroid Build Coastguard Worker     // (non-1xx).
933*6777b538SAndroid Build Coastguard Worker     if (response_->headers->response_code() / 100 != 1) {
934*6777b538SAndroid Build Coastguard Worker       DCHECK(non_informational_response_start_time_.is_null());
935*6777b538SAndroid Build Coastguard Worker       non_informational_response_start_time_ = current_response_start_time_;
936*6777b538SAndroid Build Coastguard Worker     }
937*6777b538SAndroid Build Coastguard Worker 
938*6777b538SAndroid Build Coastguard Worker     // If the body is zero length, the caller may not call ReadResponseBody,
939*6777b538SAndroid Build Coastguard Worker     // which is where any extra data is copied to read_buf_, so we move the
940*6777b538SAndroid Build Coastguard Worker     // data here.
941*6777b538SAndroid Build Coastguard Worker     if (response_body_length_ == 0) {
942*6777b538SAndroid Build Coastguard Worker       int extra_bytes = read_buf_->offset() - end_of_header_offset;
943*6777b538SAndroid Build Coastguard Worker       if (extra_bytes) {
944*6777b538SAndroid Build Coastguard Worker         CHECK_GT(extra_bytes, 0);
945*6777b538SAndroid Build Coastguard Worker         memmove(read_buf_->StartOfBuffer(),
946*6777b538SAndroid Build Coastguard Worker                 read_buf_->StartOfBuffer() + end_of_header_offset,
947*6777b538SAndroid Build Coastguard Worker                 extra_bytes);
948*6777b538SAndroid Build Coastguard Worker       }
949*6777b538SAndroid Build Coastguard Worker       read_buf_->SetCapacity(extra_bytes);
950*6777b538SAndroid Build Coastguard Worker       if (response_->headers->response_code() / 100 == 1) {
951*6777b538SAndroid Build Coastguard Worker         // After processing a 1xx response, the caller will ask for the next
952*6777b538SAndroid Build Coastguard Worker         // header, so reset state to support that. We don't completely ignore a
953*6777b538SAndroid Build Coastguard Worker         // 1xx response because it cannot be returned in reply to a CONNECT
954*6777b538SAndroid Build Coastguard Worker         // request so we return OK here, which lets the caller inspect the
955*6777b538SAndroid Build Coastguard Worker         // response and reject it in the event that we're setting up a CONNECT
956*6777b538SAndroid Build Coastguard Worker         // tunnel.
957*6777b538SAndroid Build Coastguard Worker         response_header_start_offset_ = std::string::npos;
958*6777b538SAndroid Build Coastguard Worker         response_body_length_ = -1;
959*6777b538SAndroid Build Coastguard Worker         // Record the timing of the 103 Early Hints response for the experiment
960*6777b538SAndroid Build Coastguard Worker         // (https://crbug.com/1093693).
961*6777b538SAndroid Build Coastguard Worker         if (response_->headers->response_code() == net::HTTP_EARLY_HINTS &&
962*6777b538SAndroid Build Coastguard Worker             first_early_hints_time_.is_null()) {
963*6777b538SAndroid Build Coastguard Worker           first_early_hints_time_ = current_response_start_time_;
964*6777b538SAndroid Build Coastguard Worker         }
965*6777b538SAndroid Build Coastguard Worker         // Now waiting for the second set of headers to be read.
966*6777b538SAndroid Build Coastguard Worker       } else {
967*6777b538SAndroid Build Coastguard Worker         // Only set keep-alive based on final set of headers.
968*6777b538SAndroid Build Coastguard Worker         response_is_keep_alive_ = response_->headers->IsKeepAlive();
969*6777b538SAndroid Build Coastguard Worker 
970*6777b538SAndroid Build Coastguard Worker         io_state_ = STATE_DONE;
971*6777b538SAndroid Build Coastguard Worker       }
972*6777b538SAndroid Build Coastguard Worker       return OK;
973*6777b538SAndroid Build Coastguard Worker     }
974*6777b538SAndroid Build Coastguard Worker 
975*6777b538SAndroid Build Coastguard Worker     // Only set keep-alive based on final set of headers.
976*6777b538SAndroid Build Coastguard Worker     response_is_keep_alive_ = response_->headers->IsKeepAlive();
977*6777b538SAndroid Build Coastguard Worker 
978*6777b538SAndroid Build Coastguard Worker     // Note where the headers stop.
979*6777b538SAndroid Build Coastguard Worker     read_buf_unused_offset_ = end_of_header_offset;
980*6777b538SAndroid Build Coastguard Worker     // Now waiting for the body to be read.
981*6777b538SAndroid Build Coastguard Worker   }
982*6777b538SAndroid Build Coastguard Worker   return OK;
983*6777b538SAndroid Build Coastguard Worker }
984*6777b538SAndroid Build Coastguard Worker 
RunConfirmHandshakeCallback(int rv)985*6777b538SAndroid Build Coastguard Worker void HttpStreamParser::RunConfirmHandshakeCallback(int rv) {
986*6777b538SAndroid Build Coastguard Worker   std::move(confirm_handshake_callback_).Run(rv);
987*6777b538SAndroid Build Coastguard Worker }
988*6777b538SAndroid Build Coastguard Worker 
FindAndParseResponseHeaders(int new_bytes)989*6777b538SAndroid Build Coastguard Worker int HttpStreamParser::FindAndParseResponseHeaders(int new_bytes) {
990*6777b538SAndroid Build Coastguard Worker   DCHECK_GT(new_bytes, 0);
991*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(0, read_buf_unused_offset_);
992*6777b538SAndroid Build Coastguard Worker   size_t end_offset = std::string::npos;
993*6777b538SAndroid Build Coastguard Worker 
994*6777b538SAndroid Build Coastguard Worker   // Look for the start of the status line, if it hasn't been found yet.
995*6777b538SAndroid Build Coastguard Worker   if (response_header_start_offset_ == std::string::npos) {
996*6777b538SAndroid Build Coastguard Worker     response_header_start_offset_ = HttpUtil::LocateStartOfStatusLine(
997*6777b538SAndroid Build Coastguard Worker         read_buf_->StartOfBuffer(), read_buf_->offset());
998*6777b538SAndroid Build Coastguard Worker   }
999*6777b538SAndroid Build Coastguard Worker 
1000*6777b538SAndroid Build Coastguard Worker   if (response_header_start_offset_ != std::string::npos) {
1001*6777b538SAndroid Build Coastguard Worker     // LocateEndOfHeaders looks for two line breaks in a row (With or without
1002*6777b538SAndroid Build Coastguard Worker     // carriage returns). So the end of the headers includes at most the last 3
1003*6777b538SAndroid Build Coastguard Worker     // bytes of the buffer from the past read. This optimization avoids O(n^2)
1004*6777b538SAndroid Build Coastguard Worker     // performance in the case each read only returns a couple bytes. It's not
1005*6777b538SAndroid Build Coastguard Worker     // too important in production, but for fuzzers with memory instrumentation,
1006*6777b538SAndroid Build Coastguard Worker     // it's needed to avoid timing out.
1007*6777b538SAndroid Build Coastguard Worker     size_t lower_bound =
1008*6777b538SAndroid Build Coastguard Worker         (base::ClampedNumeric<size_t>(read_buf_->offset()) - new_bytes - 3)
1009*6777b538SAndroid Build Coastguard Worker             .RawValue();
1010*6777b538SAndroid Build Coastguard Worker     size_t search_start = std::max(response_header_start_offset_, lower_bound);
1011*6777b538SAndroid Build Coastguard Worker     end_offset = HttpUtil::LocateEndOfHeaders(
1012*6777b538SAndroid Build Coastguard Worker         read_buf_->StartOfBuffer(), read_buf_->offset(), search_start);
1013*6777b538SAndroid Build Coastguard Worker   } else if (read_buf_->offset() >= 8) {
1014*6777b538SAndroid Build Coastguard Worker     // Enough data to decide that this is an HTTP/0.9 response.
1015*6777b538SAndroid Build Coastguard Worker     // 8 bytes = (4 bytes of junk) + "http".length()
1016*6777b538SAndroid Build Coastguard Worker     end_offset = 0;
1017*6777b538SAndroid Build Coastguard Worker   }
1018*6777b538SAndroid Build Coastguard Worker 
1019*6777b538SAndroid Build Coastguard Worker   if (end_offset == std::string::npos)
1020*6777b538SAndroid Build Coastguard Worker     return -1;
1021*6777b538SAndroid Build Coastguard Worker 
1022*6777b538SAndroid Build Coastguard Worker   int rv = ParseResponseHeaders(end_offset);
1023*6777b538SAndroid Build Coastguard Worker   if (rv < 0)
1024*6777b538SAndroid Build Coastguard Worker     return rv;
1025*6777b538SAndroid Build Coastguard Worker   return end_offset;
1026*6777b538SAndroid Build Coastguard Worker }
1027*6777b538SAndroid Build Coastguard Worker 
ParseResponseHeaders(int end_offset)1028*6777b538SAndroid Build Coastguard Worker int HttpStreamParser::ParseResponseHeaders(int end_offset) {
1029*6777b538SAndroid Build Coastguard Worker   scoped_refptr<HttpResponseHeaders> headers;
1030*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(0, read_buf_unused_offset_);
1031*6777b538SAndroid Build Coastguard Worker 
1032*6777b538SAndroid Build Coastguard Worker   if (response_header_start_offset_ != std::string::npos) {
1033*6777b538SAndroid Build Coastguard Worker     received_bytes_ += end_offset;
1034*6777b538SAndroid Build Coastguard Worker     headers = HttpResponseHeaders::TryToCreate(
1035*6777b538SAndroid Build Coastguard Worker         std::string_view(read_buf_->StartOfBuffer(), end_offset));
1036*6777b538SAndroid Build Coastguard Worker     if (!headers)
1037*6777b538SAndroid Build Coastguard Worker       return net::ERR_INVALID_HTTP_RESPONSE;
1038*6777b538SAndroid Build Coastguard Worker     has_seen_status_line_ = true;
1039*6777b538SAndroid Build Coastguard Worker   } else {
1040*6777b538SAndroid Build Coastguard Worker     // Enough data was read -- there is no status line, so this is HTTP/0.9, or
1041*6777b538SAndroid Build Coastguard Worker     // the server is broken / doesn't speak HTTP.
1042*6777b538SAndroid Build Coastguard Worker 
1043*6777b538SAndroid Build Coastguard Worker     if (has_seen_status_line_) {
1044*6777b538SAndroid Build Coastguard Worker       // If we saw a status line previously, the server can speak HTTP/1.x so it
1045*6777b538SAndroid Build Coastguard Worker       // is not reasonable to interpret the response as an HTTP/0.9 response.
1046*6777b538SAndroid Build Coastguard Worker       return ERR_INVALID_HTTP_RESPONSE;
1047*6777b538SAndroid Build Coastguard Worker     }
1048*6777b538SAndroid Build Coastguard Worker 
1049*6777b538SAndroid Build Coastguard Worker     std::string_view scheme = request_->url.scheme_piece();
1050*6777b538SAndroid Build Coastguard Worker     if (url::DefaultPortForScheme(scheme.data(), scheme.length()) !=
1051*6777b538SAndroid Build Coastguard Worker         request_->url.EffectiveIntPort()) {
1052*6777b538SAndroid Build Coastguard Worker       // If the port is not the default for the scheme, assume it's not a real
1053*6777b538SAndroid Build Coastguard Worker       // HTTP/0.9 response, and fail the request.
1054*6777b538SAndroid Build Coastguard Worker 
1055*6777b538SAndroid Build Coastguard Worker       // Allow Shoutcast responses over HTTP, as it's somewhat common and relies
1056*6777b538SAndroid Build Coastguard Worker       // on HTTP/0.9 on weird ports to work.
1057*6777b538SAndroid Build Coastguard Worker       // See
1058*6777b538SAndroid Build Coastguard Worker       // https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/qS63pYso4P0
1059*6777b538SAndroid Build Coastguard Worker       if (read_buf_->offset() < 3 || scheme != "http" ||
1060*6777b538SAndroid Build Coastguard Worker           !base::EqualsCaseInsensitiveASCII(
1061*6777b538SAndroid Build Coastguard Worker               std::string_view(read_buf_->StartOfBuffer(), 3), "icy")) {
1062*6777b538SAndroid Build Coastguard Worker         return ERR_INVALID_HTTP_RESPONSE;
1063*6777b538SAndroid Build Coastguard Worker       }
1064*6777b538SAndroid Build Coastguard Worker     }
1065*6777b538SAndroid Build Coastguard Worker 
1066*6777b538SAndroid Build Coastguard Worker     headers = base::MakeRefCounted<HttpResponseHeaders>(
1067*6777b538SAndroid Build Coastguard Worker         std::string("HTTP/0.9 200 OK"));
1068*6777b538SAndroid Build Coastguard Worker   }
1069*6777b538SAndroid Build Coastguard Worker 
1070*6777b538SAndroid Build Coastguard Worker   // Check for multiple Content-Length headers when the response is not
1071*6777b538SAndroid Build Coastguard Worker   // chunked-encoded.  If they exist, and have distinct values, it's a potential
1072*6777b538SAndroid Build Coastguard Worker   // response smuggling attack.
1073*6777b538SAndroid Build Coastguard Worker   if (!headers->IsChunkEncoded()) {
1074*6777b538SAndroid Build Coastguard Worker     if (HttpUtil::HeadersContainMultipleCopiesOfField(*headers,
1075*6777b538SAndroid Build Coastguard Worker                                                       "Content-Length"))
1076*6777b538SAndroid Build Coastguard Worker       return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH;
1077*6777b538SAndroid Build Coastguard Worker   }
1078*6777b538SAndroid Build Coastguard Worker 
1079*6777b538SAndroid Build Coastguard Worker   // Check for multiple Content-Disposition or Location headers.  If they exist,
1080*6777b538SAndroid Build Coastguard Worker   // it's also a potential response smuggling attack.
1081*6777b538SAndroid Build Coastguard Worker   if (HttpUtil::HeadersContainMultipleCopiesOfField(*headers,
1082*6777b538SAndroid Build Coastguard Worker                                                     "Content-Disposition"))
1083*6777b538SAndroid Build Coastguard Worker     return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION;
1084*6777b538SAndroid Build Coastguard Worker   if (HttpUtil::HeadersContainMultipleCopiesOfField(*headers, "Location"))
1085*6777b538SAndroid Build Coastguard Worker     return ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION;
1086*6777b538SAndroid Build Coastguard Worker 
1087*6777b538SAndroid Build Coastguard Worker   response_->headers = headers;
1088*6777b538SAndroid Build Coastguard Worker   if (headers->GetHttpVersion() == HttpVersion(0, 9)) {
1089*6777b538SAndroid Build Coastguard Worker     response_->connection_info = HttpConnectionInfo::kHTTP0_9;
1090*6777b538SAndroid Build Coastguard Worker   } else if (headers->GetHttpVersion() == HttpVersion(1, 0)) {
1091*6777b538SAndroid Build Coastguard Worker     response_->connection_info = HttpConnectionInfo::kHTTP1_0;
1092*6777b538SAndroid Build Coastguard Worker   } else if (headers->GetHttpVersion() == HttpVersion(1, 1)) {
1093*6777b538SAndroid Build Coastguard Worker     response_->connection_info = HttpConnectionInfo::kHTTP1_1;
1094*6777b538SAndroid Build Coastguard Worker   }
1095*6777b538SAndroid Build Coastguard Worker   DVLOG(1) << __func__ << "() content_length = \""
1096*6777b538SAndroid Build Coastguard Worker            << response_->headers->GetContentLength() << "\n\""
1097*6777b538SAndroid Build Coastguard Worker            << " headers = \"" << GetResponseHeaderLines(*response_->headers)
1098*6777b538SAndroid Build Coastguard Worker            << "\"";
1099*6777b538SAndroid Build Coastguard Worker   return OK;
1100*6777b538SAndroid Build Coastguard Worker }
1101*6777b538SAndroid Build Coastguard Worker 
CalculateResponseBodySize()1102*6777b538SAndroid Build Coastguard Worker void HttpStreamParser::CalculateResponseBodySize() {
1103*6777b538SAndroid Build Coastguard Worker   // Figure how to determine EOF:
1104*6777b538SAndroid Build Coastguard Worker 
1105*6777b538SAndroid Build Coastguard Worker   // For certain responses, we know the content length is always 0. From
1106*6777b538SAndroid Build Coastguard Worker   // RFC 7230 Section 3.3 Message Body:
1107*6777b538SAndroid Build Coastguard Worker   //
1108*6777b538SAndroid Build Coastguard Worker   // The presence of a message body in a response depends on both the
1109*6777b538SAndroid Build Coastguard Worker   // request method to which it is responding and the response status code
1110*6777b538SAndroid Build Coastguard Worker   // (Section 3.1.2).  Responses to the HEAD request method (Section 4.3.2
1111*6777b538SAndroid Build Coastguard Worker   // of [RFC7231]) never include a message body because the associated
1112*6777b538SAndroid Build Coastguard Worker   // response header fields (e.g., Transfer-Encoding, Content-Length,
1113*6777b538SAndroid Build Coastguard Worker   // etc.), if present, indicate only what their values would have been if
1114*6777b538SAndroid Build Coastguard Worker   // the request method had been GET (Section 4.3.1 of [RFC7231]). 2xx
1115*6777b538SAndroid Build Coastguard Worker   // (Successful) responses to a CONNECT request method (Section 4.3.6 of
1116*6777b538SAndroid Build Coastguard Worker   // [RFC7231]) switch to tunnel mode instead of having a message body.
1117*6777b538SAndroid Build Coastguard Worker   // All 1xx (Informational), 204 (No Content), and 304 (Not Modified)
1118*6777b538SAndroid Build Coastguard Worker   // responses do not include a message body.  All other responses do
1119*6777b538SAndroid Build Coastguard Worker   // include a message body, although the body might be of zero length.
1120*6777b538SAndroid Build Coastguard Worker   //
1121*6777b538SAndroid Build Coastguard Worker   // From RFC 7231 Section 6.3.6 205 Reset Content:
1122*6777b538SAndroid Build Coastguard Worker   //
1123*6777b538SAndroid Build Coastguard Worker   // Since the 205 status code implies that no additional content will be
1124*6777b538SAndroid Build Coastguard Worker   // provided, a server MUST NOT generate a payload in a 205 response.
1125*6777b538SAndroid Build Coastguard Worker   if (response_->headers->response_code() / 100 == 1) {
1126*6777b538SAndroid Build Coastguard Worker     response_body_length_ = 0;
1127*6777b538SAndroid Build Coastguard Worker   } else {
1128*6777b538SAndroid Build Coastguard Worker     switch (response_->headers->response_code()) {
1129*6777b538SAndroid Build Coastguard Worker       case net::HTTP_NO_CONTENT:     // No Content
1130*6777b538SAndroid Build Coastguard Worker       case net::HTTP_RESET_CONTENT:  // Reset Content
1131*6777b538SAndroid Build Coastguard Worker       case net::HTTP_NOT_MODIFIED:   // Not Modified
1132*6777b538SAndroid Build Coastguard Worker         response_body_length_ = 0;
1133*6777b538SAndroid Build Coastguard Worker         break;
1134*6777b538SAndroid Build Coastguard Worker     }
1135*6777b538SAndroid Build Coastguard Worker   }
1136*6777b538SAndroid Build Coastguard Worker   if (request_->method == "HEAD")
1137*6777b538SAndroid Build Coastguard Worker     response_body_length_ = 0;
1138*6777b538SAndroid Build Coastguard Worker 
1139*6777b538SAndroid Build Coastguard Worker   if (response_body_length_ == -1) {
1140*6777b538SAndroid Build Coastguard Worker     // "Transfer-Encoding: chunked" trumps "Content-Length: N"
1141*6777b538SAndroid Build Coastguard Worker     if (response_->headers->IsChunkEncoded()) {
1142*6777b538SAndroid Build Coastguard Worker       chunked_decoder_ = std::make_unique<HttpChunkedDecoder>();
1143*6777b538SAndroid Build Coastguard Worker     } else {
1144*6777b538SAndroid Build Coastguard Worker       response_body_length_ = response_->headers->GetContentLength();
1145*6777b538SAndroid Build Coastguard Worker       // If response_body_length_ is still -1, then we have to wait
1146*6777b538SAndroid Build Coastguard Worker       // for the server to close the connection.
1147*6777b538SAndroid Build Coastguard Worker     }
1148*6777b538SAndroid Build Coastguard Worker   }
1149*6777b538SAndroid Build Coastguard Worker }
1150*6777b538SAndroid Build Coastguard Worker 
IsResponseBodyComplete() const1151*6777b538SAndroid Build Coastguard Worker bool HttpStreamParser::IsResponseBodyComplete() const {
1152*6777b538SAndroid Build Coastguard Worker   if (chunked_decoder_.get())
1153*6777b538SAndroid Build Coastguard Worker     return chunked_decoder_->reached_eof();
1154*6777b538SAndroid Build Coastguard Worker   if (response_body_length_ != -1)
1155*6777b538SAndroid Build Coastguard Worker     return response_body_read_ >= response_body_length_;
1156*6777b538SAndroid Build Coastguard Worker 
1157*6777b538SAndroid Build Coastguard Worker   return false;  // Must read to EOF.
1158*6777b538SAndroid Build Coastguard Worker }
1159*6777b538SAndroid Build Coastguard Worker 
CanFindEndOfResponse() const1160*6777b538SAndroid Build Coastguard Worker bool HttpStreamParser::CanFindEndOfResponse() const {
1161*6777b538SAndroid Build Coastguard Worker   return chunked_decoder_.get() || response_body_length_ >= 0;
1162*6777b538SAndroid Build Coastguard Worker }
1163*6777b538SAndroid Build Coastguard Worker 
IsMoreDataBuffered() const1164*6777b538SAndroid Build Coastguard Worker bool HttpStreamParser::IsMoreDataBuffered() const {
1165*6777b538SAndroid Build Coastguard Worker   return read_buf_->offset() > read_buf_unused_offset_;
1166*6777b538SAndroid Build Coastguard Worker }
1167*6777b538SAndroid Build Coastguard Worker 
CanReuseConnection() const1168*6777b538SAndroid Build Coastguard Worker bool HttpStreamParser::CanReuseConnection() const {
1169*6777b538SAndroid Build Coastguard Worker   if (!CanFindEndOfResponse())
1170*6777b538SAndroid Build Coastguard Worker     return false;
1171*6777b538SAndroid Build Coastguard Worker 
1172*6777b538SAndroid Build Coastguard Worker   if (!response_is_keep_alive_)
1173*6777b538SAndroid Build Coastguard Worker     return false;
1174*6777b538SAndroid Build Coastguard Worker 
1175*6777b538SAndroid Build Coastguard Worker   // Check if extra data was received after reading the entire response body. If
1176*6777b538SAndroid Build Coastguard Worker   // extra data was received, reusing the socket is not a great idea. This does
1177*6777b538SAndroid Build Coastguard Worker   // have the down side of papering over certain server bugs, but seems to be
1178*6777b538SAndroid Build Coastguard Worker   // the best option here.
1179*6777b538SAndroid Build Coastguard Worker   //
1180*6777b538SAndroid Build Coastguard Worker   // TODO(mmenke): Consider logging this - hard to decipher socket reuse
1181*6777b538SAndroid Build Coastguard Worker   //     behavior makes NetLogs harder to read.
1182*6777b538SAndroid Build Coastguard Worker   if ((IsResponseBodyComplete() && IsMoreDataBuffered()) ||
1183*6777b538SAndroid Build Coastguard Worker       discarded_extra_data_) {
1184*6777b538SAndroid Build Coastguard Worker     return false;
1185*6777b538SAndroid Build Coastguard Worker   }
1186*6777b538SAndroid Build Coastguard Worker 
1187*6777b538SAndroid Build Coastguard Worker   return stream_socket_->IsConnected();
1188*6777b538SAndroid Build Coastguard Worker }
1189*6777b538SAndroid Build Coastguard Worker 
OnConnectionClose()1190*6777b538SAndroid Build Coastguard Worker void HttpStreamParser::OnConnectionClose() {
1191*6777b538SAndroid Build Coastguard Worker   // This is to ensure `stream_socket_` doesn't get dangling on connection
1192*6777b538SAndroid Build Coastguard Worker   // close.
1193*6777b538SAndroid Build Coastguard Worker   stream_socket_ = nullptr;
1194*6777b538SAndroid Build Coastguard Worker }
1195*6777b538SAndroid Build Coastguard Worker 
EncodeChunk(std::string_view payload,char * output,size_t output_size)1196*6777b538SAndroid Build Coastguard Worker int HttpStreamParser::EncodeChunk(std::string_view payload,
1197*6777b538SAndroid Build Coastguard Worker                                   char* output,
1198*6777b538SAndroid Build Coastguard Worker                                   size_t output_size) {
1199*6777b538SAndroid Build Coastguard Worker   if (output_size < payload.size() + kChunkHeaderFooterSize)
1200*6777b538SAndroid Build Coastguard Worker     return ERR_INVALID_ARGUMENT;
1201*6777b538SAndroid Build Coastguard Worker 
1202*6777b538SAndroid Build Coastguard Worker   char* cursor = output;
1203*6777b538SAndroid Build Coastguard Worker   // Add the header.
1204*6777b538SAndroid Build Coastguard Worker   const int num_chars = base::snprintf(output, output_size,
1205*6777b538SAndroid Build Coastguard Worker                                        "%X\r\n",
1206*6777b538SAndroid Build Coastguard Worker                                        static_cast<int>(payload.size()));
1207*6777b538SAndroid Build Coastguard Worker   cursor += num_chars;
1208*6777b538SAndroid Build Coastguard Worker   // Add the payload if any.
1209*6777b538SAndroid Build Coastguard Worker   if (payload.size() > 0) {
1210*6777b538SAndroid Build Coastguard Worker     memcpy(cursor, payload.data(), payload.size());
1211*6777b538SAndroid Build Coastguard Worker     cursor += payload.size();
1212*6777b538SAndroid Build Coastguard Worker   }
1213*6777b538SAndroid Build Coastguard Worker   // Add the trailing CRLF.
1214*6777b538SAndroid Build Coastguard Worker   memcpy(cursor, "\r\n", 2);
1215*6777b538SAndroid Build Coastguard Worker   cursor += 2;
1216*6777b538SAndroid Build Coastguard Worker 
1217*6777b538SAndroid Build Coastguard Worker   return cursor - output;
1218*6777b538SAndroid Build Coastguard Worker }
1219*6777b538SAndroid Build Coastguard Worker 
1220*6777b538SAndroid Build Coastguard Worker // static
ShouldMergeRequestHeadersAndBody(const std::string & request_headers,const UploadDataStream * request_body)1221*6777b538SAndroid Build Coastguard Worker bool HttpStreamParser::ShouldMergeRequestHeadersAndBody(
1222*6777b538SAndroid Build Coastguard Worker     const std::string& request_headers,
1223*6777b538SAndroid Build Coastguard Worker     const UploadDataStream* request_body) {
1224*6777b538SAndroid Build Coastguard Worker   if (request_body != nullptr &&
1225*6777b538SAndroid Build Coastguard Worker       // IsInMemory() ensures that the request body is not chunked.
1226*6777b538SAndroid Build Coastguard Worker       request_body->IsInMemory() && request_body->size() > 0) {
1227*6777b538SAndroid Build Coastguard Worker     uint64_t merged_size = request_headers.size() + request_body->size();
1228*6777b538SAndroid Build Coastguard Worker     if (merged_size <= kMaxMergedHeaderAndBodySize)
1229*6777b538SAndroid Build Coastguard Worker       return true;
1230*6777b538SAndroid Build Coastguard Worker   }
1231*6777b538SAndroid Build Coastguard Worker   return false;
1232*6777b538SAndroid Build Coastguard Worker }
1233*6777b538SAndroid Build Coastguard Worker 
SendRequestBuffersEmpty()1234*6777b538SAndroid Build Coastguard Worker bool HttpStreamParser::SendRequestBuffersEmpty() {
1235*6777b538SAndroid Build Coastguard Worker   return request_headers_ == nullptr && request_body_send_buf_ == nullptr &&
1236*6777b538SAndroid Build Coastguard Worker          request_body_read_buf_ == nullptr;
1237*6777b538SAndroid Build Coastguard Worker }
1238*6777b538SAndroid Build Coastguard Worker 
1239*6777b538SAndroid Build Coastguard Worker }  // namespace net
1240