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