http_stream_parser.h revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 <string> 9 10#include "base/basictypes.h" 11#include "base/memory/ref_counted.h" 12#include "base/memory/scoped_ptr.h" 13#include "base/memory/weak_ptr.h" 14#include "base/string_piece.h" 15#include "net/base/completion_callback.h" 16#include "net/base/net_export.h" 17#include "net/base/net_log.h" 18#include "net/base/upload_progress.h" 19 20namespace net { 21 22class ClientSocketHandle; 23class DrainableIOBuffer; 24class GrowableIOBuffer; 25class HttpChunkedDecoder; 26struct HttpRequestInfo; 27class HttpRequestHeaders; 28class HttpResponseInfo; 29class IOBuffer; 30class IOBufferWithSize; 31class SSLCertRequestInfo; 32class SSLInfo; 33class UploadDataStream; 34 35class NET_EXPORT_PRIVATE HttpStreamParser { 36 public: 37 // Any data in |read_buffer| will be used before reading from the socket 38 // and any data left over after parsing the stream will be put into 39 // |read_buffer|. The left over data will start at offset 0 and the 40 // buffer's offset will be set to the first free byte. |read_buffer| may 41 // have its capacity changed. 42 HttpStreamParser(ClientSocketHandle* connection, 43 const HttpRequestInfo* request, 44 GrowableIOBuffer* read_buffer, 45 const BoundNetLog& net_log); 46 virtual ~HttpStreamParser(); 47 48 // These functions implement the interface described in HttpStream with 49 // some additional functionality 50 int SendRequest(const std::string& request_line, 51 const HttpRequestHeaders& headers, 52 UploadDataStream* request_body, 53 HttpResponseInfo* response, 54 const CompletionCallback& callback); 55 56 int ReadResponseHeaders(const CompletionCallback& callback); 57 58 int ReadResponseBody(IOBuffer* buf, int buf_len, 59 const CompletionCallback& callback); 60 61 void Close(bool not_reusable); 62 63 // Returns the progress of uploading. When data is chunked, size is set to 64 // zero, but position will not be. 65 UploadProgress GetUploadProgress() const; 66 67 HttpResponseInfo* GetResponseInfo(); 68 69 bool IsResponseBodyComplete() const; 70 71 bool CanFindEndOfResponse() const; 72 73 bool IsMoreDataBuffered() const; 74 75 bool IsConnectionReused() const; 76 77 void SetConnectionReused(); 78 79 bool IsConnectionReusable() const; 80 81 void GetSSLInfo(SSLInfo* ssl_info); 82 83 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info); 84 85 // Encodes the given |payload| in the chunked format to |output|. 86 // Returns the number of bytes written to |output|. |output_size| should 87 // be large enough to store the encoded chunk, which is payload.size() + 88 // kChunkHeaderFooterSize. Returns ERR_INVALID_ARGUMENT if |output_size| 89 // is not large enough. 90 // 91 // The output will look like: "HEX\r\n[payload]\r\n" 92 // where HEX is a length in hexdecimal (without the "0x" prefix). 93 static int EncodeChunk(const base::StringPiece& payload, 94 char* output, 95 size_t output_size); 96 97 // Returns true if request headers and body should be merged (i.e. the 98 // sum is small enough and the body is in memory, and not chunked). 99 static bool ShouldMergeRequestHeadersAndBody( 100 const std::string& request_headers, 101 const UploadDataStream* request_body); 102 103 // The number of extra bytes required to encode a chunk. 104 static const size_t kChunkHeaderFooterSize; 105 106 private: 107 class SeekableIOBuffer; 108 109 // FOO_COMPLETE states implement the second half of potentially asynchronous 110 // operations and don't necessarily mean that FOO is complete. 111 enum State { 112 STATE_NONE, 113 STATE_SENDING_HEADERS, 114 // If the request comes with a body, either of the following two 115 // states will be executed, depending on whether the body is chunked 116 // or not. 117 STATE_SENDING_BODY, 118 STATE_SEND_REQUEST_READING_BODY, 119 STATE_REQUEST_SENT, 120 STATE_READ_HEADERS, 121 STATE_READ_HEADERS_COMPLETE, 122 STATE_BODY_PENDING, 123 STATE_READ_BODY, 124 STATE_READ_BODY_COMPLETE, 125 STATE_DONE 126 }; 127 128 // The number of bytes by which the header buffer is grown when it reaches 129 // capacity. 130 static const int kHeaderBufInitialSize = 4 * 1024; // 4K 131 132 // |kMaxHeaderBufSize| is the number of bytes that the response headers can 133 // grow to. If the body start is not found within this range of the 134 // response, the transaction will fail with ERR_RESPONSE_HEADERS_TOO_BIG. 135 // Note: |kMaxHeaderBufSize| should be a multiple of |kHeaderBufInitialSize|. 136 static const int kMaxHeaderBufSize = kHeaderBufInitialSize * 64; // 256K 137 138 // The maximum sane buffer size. 139 static const int kMaxBufSize = 2 * 1024 * 1024; // 2M 140 141 // Handle callbacks. 142 void OnIOComplete(int result); 143 144 // Try to make progress sending/receiving the request/response. 145 int DoLoop(int result); 146 147 // The implementations of each state of the state machine. 148 int DoSendHeaders(int result); 149 int DoSendBody(int result); 150 int DoSendRequestReadingBody(int result); 151 int DoReadHeaders(); 152 int DoReadHeadersComplete(int result); 153 int DoReadBody(); 154 int DoReadBodyComplete(int result); 155 156 // Examines |read_buf_| to find the start and end of the headers. If they are 157 // found, parse them with DoParseResponseHeaders(). Return the offset for 158 // the end of the headers, or -1 if the complete headers were not found, or 159 // with a net::Error if we encountered an error during parsing. 160 int ParseResponseHeaders(); 161 162 // Parse the headers into response_. Returns OK on success or a net::Error on 163 // failure. 164 int DoParseResponseHeaders(int end_of_header_offset); 165 166 // Examine the parsed headers to try to determine the response body size. 167 void CalculateResponseBodySize(); 168 169 // Current state of the request. 170 State io_state_; 171 172 // The request to send. 173 const HttpRequestInfo* request_; 174 175 // The request header data. 176 scoped_refptr<DrainableIOBuffer> request_headers_; 177 178 // The request body data. 179 UploadDataStream* request_body_; 180 181 // Temporary buffer for reading. 182 scoped_refptr<GrowableIOBuffer> read_buf_; 183 184 // Offset of the first unused byte in |read_buf_|. May be nonzero due to 185 // a 1xx header, or body data in the same packet as header data. 186 int read_buf_unused_offset_; 187 188 // The amount beyond |read_buf_unused_offset_| where the status line starts; 189 // -1 if not found yet. 190 int response_header_start_offset_; 191 192 // The parsed response headers. Owned by the caller. 193 HttpResponseInfo* response_; 194 195 // Indicates the content length. If this value is less than zero 196 // (and chunked_decoder_ is null), then we must read until the server 197 // closes the connection. 198 int64 response_body_length_; 199 200 // Keep track of the number of response body bytes read so far. 201 int64 response_body_read_; 202 203 // Helper if the data is chunked. 204 scoped_ptr<HttpChunkedDecoder> chunked_decoder_; 205 206 // Where the caller wants the body data. 207 scoped_refptr<IOBuffer> user_read_buf_; 208 int user_read_buf_len_; 209 210 // The callback to notify a user that their request or response is 211 // complete or there was an error 212 CompletionCallback callback_; 213 214 // In the client callback, the client can do anything, including 215 // destroying this class, so any pending callback must be issued 216 // after everything else is done. When it is time to issue the client 217 // callback, move it from |callback_| to |scheduled_callback_|. 218 CompletionCallback scheduled_callback_; 219 220 // The underlying socket. 221 ClientSocketHandle* const connection_; 222 223 BoundNetLog net_log_; 224 225 // Callback to be used when doing IO. 226 CompletionCallback io_callback_; 227 228 // Buffer used to read the request body from UploadDataStream. 229 scoped_refptr<SeekableIOBuffer> request_body_read_buf_; 230 // Buffer used to send the request body. This points the same buffer as 231 // |request_body_read_buf_| unless the data is chunked. 232 scoped_refptr<SeekableIOBuffer> request_body_send_buf_; 233 bool sent_last_chunk_; 234 235 base::WeakPtrFactory<HttpStreamParser> weak_ptr_factory_; 236 237 DISALLOW_COPY_AND_ASSIGN(HttpStreamParser); 238}; 239 240} // namespace net 241 242#endif // NET_HTTP_HTTP_STREAM_PARSER_H_ 243