xref: /aosp_15_r20/external/cronet/net/http/http_stream_parser.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef NET_HTTP_HTTP_STREAM_PARSER_H_
6 #define NET_HTTP_HTTP_STREAM_PARSER_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <memory>
12 #include <string>
13 #include <string_view>
14 
15 #include "base/memory/raw_ptr.h"
16 #include "base/memory/scoped_refptr.h"
17 #include "base/memory/weak_ptr.h"
18 #include "base/time/time.h"
19 #include "crypto/ec_private_key.h"
20 #include "net/base/completion_once_callback.h"
21 #include "net/base/completion_repeating_callback.h"
22 #include "net/base/net_errors.h"
23 #include "net/base/net_export.h"
24 #include "net/log/net_log_with_source.h"
25 #include "net/traffic_annotation/network_traffic_annotation.h"
26 
27 namespace net {
28 
29 class DrainableIOBuffer;
30 class GrowableIOBuffer;
31 class HttpChunkedDecoder;
32 struct HttpRequestInfo;
33 class HttpRequestHeaders;
34 class HttpResponseInfo;
35 class IOBuffer;
36 class StreamSocket;
37 class UploadDataStream;
38 
39 class NET_EXPORT_PRIVATE HttpStreamParser {
40  public:
41   // |connection_is_reused| must be |true| if |stream_socket| has previously
42   // been used successfully for an HTTP/1.x request.
43   //
44   // Any data in |read_buffer| will be used before reading from the socket
45   // and any data left over after parsing the stream will be put into
46   // |read_buffer|.  The left over data will start at offset 0 and the
47   // buffer's offset will be set to the first free byte. |read_buffer| may
48   // have its capacity changed.
49   //
50   // It is not safe to call into the HttpStreamParser after destroying the
51   // |stream_socket|.
52   HttpStreamParser(StreamSocket* stream_socket,
53                    bool connection_is_reused,
54                    const HttpRequestInfo* request,
55                    GrowableIOBuffer* read_buffer,
56                    const NetLogWithSource& net_log);
57 
58   HttpStreamParser(const HttpStreamParser&) = delete;
59   HttpStreamParser& operator=(const HttpStreamParser&) = delete;
60 
61   virtual ~HttpStreamParser();
62 
63   // These functions implement the interface described in HttpStream with
64   // some additional functionality
65   int SendRequest(const std::string& request_line,
66                   const HttpRequestHeaders& headers,
67                   const NetworkTrafficAnnotationTag& traffic_annotation,
68                   HttpResponseInfo* response,
69                   CompletionOnceCallback callback);
70 
71   int ConfirmHandshake(CompletionOnceCallback callback);
72 
73   int ReadResponseHeaders(CompletionOnceCallback callback);
74 
75   int ReadResponseBody(IOBuffer* buf,
76                        int buf_len,
77                        CompletionOnceCallback callback);
78 
79   bool IsResponseBodyComplete() const;
80 
81   bool CanFindEndOfResponse() const;
82 
83   bool IsMoreDataBuffered() const;
84 
85   // Returns true if the underlying connection can be reused.
86   // The connection can be reused if:
87   // * It's still connected.
88   // * The response headers indicate the connection can be kept alive.
89   // * The end of the response can be found, though it may not have yet been
90   //     received.
91   //
92   // Note that if response headers have yet to be received, this will return
93   // false.
94   bool CanReuseConnection() const;
95 
96   // Called when stream is closed.
97   void OnConnectionClose();
98 
received_bytes()99   int64_t received_bytes() const { return received_bytes_; }
100 
sent_bytes()101   int64_t sent_bytes() const { return sent_bytes_; }
102 
first_response_start_time()103   base::TimeTicks first_response_start_time() const {
104     return first_response_start_time_;
105   }
non_informational_response_start_time()106   base::TimeTicks non_informational_response_start_time() const {
107     return non_informational_response_start_time_;
108   }
first_early_hints_time()109   base::TimeTicks first_early_hints_time() { return first_early_hints_time_; }
110 
111   // Encodes the given |payload| in the chunked format to |output|.
112   // Returns the number of bytes written to |output|. |output_size| should
113   // be large enough to store the encoded chunk, which is payload.size() +
114   // kChunkHeaderFooterSize. Returns ERR_INVALID_ARGUMENT if |output_size|
115   // is not large enough.
116   //
117   // The output will look like: "HEX\r\n[payload]\r\n"
118   // where HEX is a length in hexdecimal (without the "0x" prefix).
119   static int EncodeChunk(std::string_view payload,
120                          char* output,
121                          size_t output_size);
122 
123   // Returns true if request headers and body should be merged (i.e. the
124   // sum is small enough and the body is in memory, and not chunked).
125   static bool ShouldMergeRequestHeadersAndBody(
126       const std::string& request_headers,
127       const UploadDataStream* request_body);
128 
129   // The number of extra bytes required to encode a chunk.
130   static const size_t kChunkHeaderFooterSize;
131 
132  private:
133   class SeekableIOBuffer;
134 
135   // FOO_COMPLETE states implement the second half of potentially asynchronous
136   // operations and don't necessarily mean that FOO is complete.
137   enum State {
138     // STATE_NONE indicates that this is waiting on an external call before
139     // continuing.
140     STATE_NONE,
141     STATE_SEND_HEADERS,
142     STATE_SEND_HEADERS_COMPLETE,
143     STATE_SEND_BODY,
144     STATE_SEND_BODY_COMPLETE,
145     STATE_SEND_REQUEST_READ_BODY_COMPLETE,
146     STATE_SEND_REQUEST_COMPLETE,
147     STATE_READ_HEADERS,
148     STATE_READ_HEADERS_COMPLETE,
149     STATE_READ_BODY,
150     STATE_READ_BODY_COMPLETE,
151     STATE_DONE
152   };
153 
154   // The number of bytes by which the header buffer is grown when it reaches
155   // capacity.
156   static const int kHeaderBufInitialSize = 4 * 1024;  // 4K
157 
158   // |kMaxHeaderBufSize| is the number of bytes that the response headers can
159   // grow to. If the body start is not found within this range of the
160   // response, the transaction will fail with ERR_RESPONSE_HEADERS_TOO_BIG.
161   // Note: |kMaxHeaderBufSize| should be a multiple of |kHeaderBufInitialSize|.
162   static const int kMaxHeaderBufSize = kHeaderBufInitialSize * 64;  // 256K
163 
164   // The maximum sane buffer size.
165   static const int kMaxBufSize = 2 * 1024 * 1024;  // 2M
166 
167   // Handle callbacks.
168   void OnIOComplete(int result);
169 
170   // Try to make progress sending/receiving the request/response.
171   int DoLoop(int result);
172 
173   // The implementations of each state of the state machine.
174   int DoSendHeaders();
175   int DoSendHeadersComplete(int result);
176   int DoSendBody();
177   int DoSendBodyComplete(int result);
178   int DoSendRequestReadBodyComplete(int result);
179   int DoSendRequestComplete(int result);
180   int DoReadHeaders();
181   int DoReadHeadersComplete(int result);
182   int DoReadBody();
183   int DoReadBodyComplete(int result);
184 
185   // This handles most of the logic for DoReadHeadersComplete.
186   int HandleReadHeaderResult(int result);
187 
188   void RunConfirmHandshakeCallback(int rv);
189 
190   // Examines |read_buf_| to find the start and end of the headers. If they are
191   // found, parse them with DoParseResponseHeaders().  Return the offset for
192   // the end of the headers, or -1 if the complete headers were not found, or
193   // with a net::Error if we encountered an error during parsing.
194   //
195   // |new_bytes| is the number of new bytes that have been appended to the end
196   // of |read_buf_| since the last call to this method (which must have returned
197   // -1).
198   int FindAndParseResponseHeaders(int new_bytes);
199 
200   // Parse the headers into response_.  Returns OK on success or a net::Error on
201   // failure.
202   int ParseResponseHeaders(int end_of_header_offset);
203 
204   // Examine the parsed headers to try to determine the response body size.
205   void CalculateResponseBodySize();
206 
207   // Check if buffers used to send the request are empty.
208   bool SendRequestBuffersEmpty();
209 
210   // Next state of the request, when the current one completes.
211   State io_state_ = STATE_NONE;
212 
213   // Null when read state machine is invoked.
214   raw_ptr<const HttpRequestInfo, AcrossTasksDanglingUntriaged> request_;
215 
216   // The request header data.  May include a merged request body.
217   scoped_refptr<DrainableIOBuffer> request_headers_;
218 
219   // Size of just the request headers.  May be less than the length of
220   // |request_headers_| if the body was merged with the headers.
221   int request_headers_length_ = 0;
222 
223   // Temporary buffer for reading.
224   scoped_refptr<GrowableIOBuffer> read_buf_;
225 
226   // Offset of the first unused byte in |read_buf_|.  May be nonzero due to
227   // body data in the same packet as header data but is zero when reading
228   // headers.
229   int read_buf_unused_offset_ = 0;
230 
231   // The amount beyond |read_buf_unused_offset_| where the status line starts;
232   // std::string::npos if not found yet.
233   size_t response_header_start_offset_;
234 
235   // The amount of received data.  If connection is reused then intermediate
236   // value may be bigger than final.
237   int64_t received_bytes_ = 0;
238 
239   // The amount of sent data.
240   int64_t sent_bytes_ = 0;
241 
242   // The parsed response headers.  Owned by the caller of SendRequest.   This
243   // cannot be safely accessed after reading the final set of headers, as the
244   // caller of SendRequest may have been destroyed - this happens in the case an
245   // HttpResponseBodyDrainer is used.
246   raw_ptr<HttpResponseInfo, AcrossTasksDanglingUntriaged> response_ = nullptr;
247 
248   // Time at which the first bytes of the first header response including
249   // informational responses (1xx) are about to be parsed. This corresponds to
250   // |LoadTimingInfo::receive_headers_start|. See also comments there.
251   base::TimeTicks first_response_start_time_;
252 
253   // Time at which the first bytes of the current header response are about to
254   // be parsed. This is reset every time new response headers including
255   // non-informational responses (1xx) are parsed.
256   base::TimeTicks current_response_start_time_;
257 
258   // Time at which the first byte of the non-informational header response
259   // (non-1xx) are about to be parsed. This corresponds to
260   // |LoadTimingInfo::receive_non_informational_headers_start|. See also
261   // comments there.
262   base::TimeTicks non_informational_response_start_time_;
263 
264   // Time at which the first 103 Early Hints response is received. This
265   // corresponds to |LoadTimingInfo::first_early_hints_time|.
266   base::TimeTicks first_early_hints_time_;
267 
268   // Indicates the content length.  If this value is less than zero
269   // (and chunked_decoder_ is null), then we must read until the server
270   // closes the connection.
271   int64_t response_body_length_ = -1;
272 
273   // True if reading a keep-alive response. False if not, or if don't yet know.
274   bool response_is_keep_alive_ = false;
275 
276   // True if we've seen a response that has an HTTP status line. This is
277   // persistent across multiple response parsing. If we see a status line
278   // for a response, this will remain true forever.
279   bool has_seen_status_line_ = false;
280 
281   // Keep track of the number of response body bytes read so far.
282   int64_t response_body_read_ = 0;
283 
284   // Helper if the data is chunked.
285   std::unique_ptr<HttpChunkedDecoder> chunked_decoder_;
286 
287   // Where the caller wants the body data.
288   scoped_refptr<IOBuffer> user_read_buf_;
289   int user_read_buf_len_ = 0;
290 
291   // The callback to notify a user that the handshake has been confirmed.
292   CompletionOnceCallback confirm_handshake_callback_;
293 
294   // The callback to notify a user that their request or response is
295   // complete or there was an error
296   CompletionOnceCallback callback_;
297 
298   // The underlying socket, owned by the caller. The HttpStreamParser must be
299   // destroyed before the caller destroys the socket, or relinquishes ownership
300   // of it.
301   raw_ptr<StreamSocket> stream_socket_;
302 
303   // Whether the socket has already been used. Only used in HTTP/0.9 detection
304   // logic.
305   const bool connection_is_reused_;
306 
307   NetLogWithSource net_log_;
308 
309   // Callback to be used when doing IO.
310   CompletionRepeatingCallback io_callback_;
311 
312   // Buffer used to read the request body from UploadDataStream.
313   scoped_refptr<SeekableIOBuffer> request_body_read_buf_;
314   // Buffer used to send the request body. This points the same buffer as
315   // |request_body_read_buf_| unless the data is chunked.
316   scoped_refptr<SeekableIOBuffer> request_body_send_buf_;
317   bool sent_last_chunk_ = false;
318 
319   // Whether the Content-Length was known and extra data was discarded.
320   bool discarded_extra_data_ = false;
321 
322   // Whether the response body should be truncated to the Content-Length.
323   const bool truncate_to_content_length_enabled_;
324 
325   // Error received when uploading the body, if any.
326   int upload_error_ = OK;
327 
328   MutableNetworkTrafficAnnotationTag traffic_annotation_;
329 
330   base::WeakPtrFactory<HttpStreamParser> weak_ptr_factory_{this};
331 };
332 
333 }  // namespace net
334 
335 #endif  // NET_HTTP_HTTP_STREAM_PARSER_H_
336