OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef NET_SPDY_SPDY_FRAMER_H_ | 5 #ifndef NET_SPDY_SPDY_FRAMER_H_ |
6 #define NET_SPDY_SPDY_FRAMER_H_ | 6 #define NET_SPDY_SPDY_FRAMER_H_ |
7 #pragma once | 7 #pragma once |
8 | 8 |
9 #include <list> | 9 #include <list> |
10 #include <map> | 10 #include <map> |
(...skipping 19 matching lines...) Expand all Loading... |
30 class SpdyProxyClientSocketTest; | 30 class SpdyProxyClientSocketTest; |
31 class SpdySessionTest; | 31 class SpdySessionTest; |
32 class SpdyStreamTest; | 32 class SpdyStreamTest; |
33 class SpdyWebSocketStreamTest; | 33 class SpdyWebSocketStreamTest; |
34 class WebSocketJobTest; | 34 class WebSocketJobTest; |
35 } | 35 } |
36 | 36 |
37 namespace spdy { | 37 namespace spdy { |
38 | 38 |
39 class SpdyFramer; | 39 class SpdyFramer; |
| 40 class SpdyFrameBuilder; |
40 class SpdyFramerTest; | 41 class SpdyFramerTest; |
41 | 42 |
42 namespace test { | 43 namespace test { |
| 44 |
43 class TestSpdyVisitor; | 45 class TestSpdyVisitor; |
44 void FramerSetEnableCompressionHelper(SpdyFramer* framer, bool compress); | 46 |
45 } // namespace test | 47 } // namespace test |
46 | 48 |
47 // A datastructure for holding a set of headers from either a | 49 // A datastructure for holding a set of headers from either a |
48 // SYN_STREAM or SYN_REPLY frame. | 50 // SYN_STREAM or SYN_REPLY frame. |
49 typedef std::map<std::string, std::string> SpdyHeaderBlock; | 51 typedef std::map<std::string, std::string> SpdyHeaderBlock; |
50 | 52 |
| 53 // A datastructure for holding the ID and flag fields for SETTINGS. |
| 54 // Conveniently handles converstion to/from wire format. |
| 55 class NET_EXPORT_PRIVATE SettingsFlagsAndId { |
| 56 public: |
| 57 static SettingsFlagsAndId FromWireFormat(int version, uint32 wire); |
| 58 |
| 59 SettingsFlagsAndId() : flags_(0), id_(0) {} |
| 60 |
| 61 // TODO(hkhalil): restrict to enums instead of free-form ints. |
| 62 SettingsFlagsAndId(uint8 flags, uint32 id); |
| 63 |
| 64 uint32 GetWireFormat(int version) const; |
| 65 |
| 66 uint32 id() const { return id_; } |
| 67 uint8 flags() const { return flags_; } |
| 68 |
| 69 private: |
| 70 static void ConvertFlagsAndIdForSpdy2(uint32* val); |
| 71 |
| 72 uint8 flags_; |
| 73 uint32 id_; |
| 74 }; |
| 75 |
51 // A datastructure for holding a set of ID/value pairs for a SETTINGS frame. | 76 // A datastructure for holding a set of ID/value pairs for a SETTINGS frame. |
52 typedef std::pair<spdy::SettingsFlagsAndId, uint32> SpdySetting; | 77 typedef std::pair<SettingsFlagsAndId, uint32> SpdySetting; |
53 typedef std::list<SpdySetting> SpdySettings; | 78 typedef std::list<SpdySetting> SpdySettings; |
54 | 79 |
55 // A datastrcture for holding the contents of a CREDENTIAL frame. | 80 // A datastrcture for holding the contents of a CREDENTIAL frame. |
56 struct NET_EXPORT_PRIVATE SpdyCredential { | 81 struct NET_EXPORT_PRIVATE SpdyCredential { |
57 SpdyCredential(); | 82 SpdyCredential(); |
58 ~SpdyCredential(); | 83 ~SpdyCredential(); |
59 | 84 |
60 uint16 slot; | 85 uint16 slot; |
61 std::vector<std::string> certs; | 86 std::vector<std::string> certs; |
62 std::string proof; | 87 std::string proof; |
63 }; | 88 }; |
64 | 89 |
| 90 // Scratch space necessary for processing SETTINGS frames. |
| 91 struct NET_EXPORT_PRIVATE SpdySettingsScratch { |
| 92 SpdySettingsScratch() { Reset(); } |
| 93 |
| 94 void Reset() { |
| 95 setting_buf_len = 0; |
| 96 last_setting_id = 0; |
| 97 } |
| 98 |
| 99 // Buffer contains up to one complete key/value pair. |
| 100 char setting_buf[8]; |
| 101 |
| 102 // The amount of the buffer that is filled with valid data. |
| 103 size_t setting_buf_len; |
| 104 |
| 105 // The ID of the last setting that was processed in the current SETTINGS |
| 106 // frame. Used for detecting out-of-order or duplicate keys within a settings |
| 107 // frame. Set to 0 before first key/value pair is processed. |
| 108 uint32 last_setting_id; |
| 109 }; |
| 110 |
65 // SpdyFramerVisitorInterface is a set of callbacks for the SpdyFramer. | 111 // SpdyFramerVisitorInterface is a set of callbacks for the SpdyFramer. |
66 // Implement this interface to receive event callbacks as frames are | 112 // Implement this interface to receive event callbacks as frames are |
67 // decoded from the framer. | 113 // decoded from the framer. |
68 // | 114 // |
69 // Control frames that contain SPDY header blocks (SYN_STREAM, SYN_REPLY, and | 115 // Control frames that contain SPDY header blocks (SYN_STREAM, SYN_REPLY, and |
70 // HEADER) are processed in fashion that allows the decompressed header block | 116 // HEADER) are processed in fashion that allows the decompressed header block |
71 // to be delivered in chunks to the visitor. The following steps are followed: | 117 // to be delivered in chunks to the visitor. The following steps are followed: |
72 // 1. OnControl is called, with either a SpdySynStreamControlFrame, | 118 // 1. OnControl is called, with either a SpdySynStreamControlFrame, |
73 // SpdySynReplyControlFrame, or a SpdyHeaderControlFrame argument. | 119 // SpdySynReplyControlFrame, or a SpdyHeaderControlFrame argument. |
74 // 2. Repeated: OnControlFrameHeaderData is called with chunks of the | 120 // 2. Repeated: OnControlFrameHeaderData is called with chunks of the |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 // When this function returns true the visitor indicates that it accepted | 152 // When this function returns true the visitor indicates that it accepted |
107 // all of the data. Returning false indicates that that an unrecoverable | 153 // all of the data. Returning false indicates that that an unrecoverable |
108 // error has occurred, such as bad header data or resource exhaustion. | 154 // error has occurred, such as bad header data or resource exhaustion. |
109 virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id, | 155 virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id, |
110 const char* header_data, | 156 const char* header_data, |
111 size_t len) = 0; | 157 size_t len) = 0; |
112 | 158 |
113 // Called when a chunk of payload data for a credential frame is available. | 159 // Called when a chunk of payload data for a credential frame is available. |
114 // This is called after OnControl() is called with the credential frame | 160 // This is called after OnControl() is called with the credential frame |
115 // associated with the payload being delivered here. | 161 // associated with the payload being delivered here. |
116 // |frame_data| A buffer containing the header data chunk received. | 162 // |header_data| A buffer containing the header data chunk received. |
117 // |len| The length of the header data buffer. A length of zero indicates | 163 // |len| The length of the header data buffer. A length of zero indicates |
118 // that the header data block has been completely sent. | 164 // that the header data block has been completely sent. |
119 // When this function returns true the visitor indicates that it accepted | 165 // When this function returns true the visitor indicates that it accepted |
120 // all of the data. Returning false indicates that that an unrecoverable | 166 // all of the data. Returning false indicates that that an unrecoverable |
121 // error has occurred, such as bad header data or resource exhaustion. | 167 // error has occurred, such as bad header data or resource exhaustion. |
122 virtual bool OnCredentialFrameData(const char* frame_data, | 168 virtual bool OnCredentialFrameData(const char* header_data, |
123 size_t len) = 0; | 169 size_t len) = 0; |
124 | 170 |
125 // Called when a data frame header is received. The frame's data | 171 // Called when a data frame header is received. The frame's data |
126 // payload will be provided via subsequent calls to | 172 // payload will be provided via subsequent calls to |
127 // OnStreamFrameData(). | 173 // OnStreamFrameData(). |
128 virtual void OnDataFrameHeader(const SpdyDataFrame* frame) = 0; | 174 virtual void OnDataFrameHeader(const SpdyDataFrame* frame) = 0; |
129 | 175 |
130 // Called when data is received. | 176 // Called when data is received. |
131 // |stream_id| The stream receiving data. | 177 // |stream_id| The stream receiving data. |
132 // |data| A buffer containing the data received. | 178 // |data| A buffer containing the data received. |
133 // |len| The length of the data buffer. | 179 // |len| The length of the data buffer. |
134 // When the other side has finished sending data on this stream, | 180 // When the other side has finished sending data on this stream, |
135 // this method will be called with a zero-length buffer. | 181 // this method will be called with a zero-length buffer. |
136 virtual void OnStreamFrameData(SpdyStreamId stream_id, | 182 virtual void OnStreamFrameData(SpdyStreamId stream_id, |
137 const char* data, | 183 const char* data, |
138 size_t len) = 0; | 184 size_t len) = 0; |
| 185 |
| 186 // Called when a complete setting within a SETTINGS frame has been parsed and |
| 187 // validated. |
| 188 virtual void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) = 0; |
139 }; | 189 }; |
140 | 190 |
141 class NET_EXPORT_PRIVATE SpdyFramer { | 191 class NET_EXPORT_PRIVATE SpdyFramer { |
142 public: | 192 public: |
143 // SPDY states. | 193 // SPDY states. |
144 // TODO(mbelshe): Can we move these into the implementation | 194 // TODO(mbelshe): Can we move these into the implementation |
145 // and avoid exposing through the header. (Needed for test) | 195 // and avoid exposing through the header. (Needed for test) |
146 enum SpdyState { | 196 enum SpdyState { |
147 SPDY_ERROR, | 197 SPDY_ERROR, |
148 SPDY_DONE, | 198 SPDY_DONE, |
149 SPDY_RESET, | 199 SPDY_RESET, |
150 SPDY_AUTO_RESET, | 200 SPDY_AUTO_RESET, |
151 SPDY_READING_COMMON_HEADER, | 201 SPDY_READING_COMMON_HEADER, |
152 SPDY_CONTROL_FRAME_PAYLOAD, | 202 SPDY_CONTROL_FRAME_PAYLOAD, |
153 SPDY_IGNORE_REMAINING_PAYLOAD, | 203 SPDY_IGNORE_REMAINING_PAYLOAD, |
154 SPDY_FORWARD_STREAM_FRAME, | 204 SPDY_FORWARD_STREAM_FRAME, |
155 SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, | 205 SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, |
156 SPDY_CONTROL_FRAME_HEADER_BLOCK, | 206 SPDY_CONTROL_FRAME_HEADER_BLOCK, |
157 SPDY_CREDENTIAL_FRAME_PAYLOAD, | 207 SPDY_CREDENTIAL_FRAME_PAYLOAD, |
| 208 SPDY_SETTINGS_FRAME_PAYLOAD, |
158 }; | 209 }; |
159 | 210 |
160 // SPDY error codes. | 211 // SPDY error codes. |
161 enum SpdyError { | 212 enum SpdyError { |
162 SPDY_NO_ERROR, | 213 SPDY_NO_ERROR, |
163 SPDY_INVALID_CONTROL_FRAME, // Control frame is mal-formatted. | 214 SPDY_INVALID_CONTROL_FRAME, // Control frame is mal-formatted. |
164 SPDY_CONTROL_PAYLOAD_TOO_LARGE, // Control frame payload was too large. | 215 SPDY_CONTROL_PAYLOAD_TOO_LARGE, // Control frame payload was too large. |
165 SPDY_ZLIB_INIT_FAILURE, // The Zlib library could not initialize. | 216 SPDY_ZLIB_INIT_FAILURE, // The Zlib library could not initialize. |
166 SPDY_UNSUPPORTED_VERSION, // Control frame has unsupported version. | 217 SPDY_UNSUPPORTED_VERSION, // Control frame has unsupported version. |
167 SPDY_DECOMPRESS_FAILURE, // There was an error decompressing. | 218 SPDY_DECOMPRESS_FAILURE, // There was an error decompressing. |
168 SPDY_COMPRESS_FAILURE, // There was an error compressing. | 219 SPDY_COMPRESS_FAILURE, // There was an error compressing. |
169 SPDY_CREDENTIAL_FRAME_CORRUPT, // CREDENTIAL frame could not be parsed. | 220 SPDY_CREDENTIAL_FRAME_CORRUPT, // CREDENTIAL frame could not be parsed. |
170 | 221 |
171 LAST_ERROR, // Must be the last entry in the enum. | 222 LAST_ERROR, // Must be the last entry in the enum. |
172 }; | 223 }; |
173 | 224 |
174 // Constant for invalid (or unknown) stream IDs. | 225 // Constant for invalid (or unknown) stream IDs. |
175 static const SpdyStreamId kInvalidStream; | 226 static const SpdyStreamId kInvalidStream; |
176 | 227 |
177 // The maximum size of header data chunks delivered to the framer visitor | 228 // The maximum size of header data chunks delivered to the framer visitor |
178 // through OnControlFrameHeaderData. (It is exposed here for unit test | 229 // through OnControlFrameHeaderData. (It is exposed here for unit test |
179 // purposes.) | 230 // purposes.) |
180 static const size_t kHeaderDataChunkMaxSize; | 231 static const size_t kHeaderDataChunkMaxSize; |
181 | 232 |
182 // Create a new Framer. | 233 // Create a new Framer, provided a SPDY version. |
183 SpdyFramer(); | 234 explicit SpdyFramer(int version); |
184 virtual ~SpdyFramer(); | 235 virtual ~SpdyFramer(); |
185 | 236 |
186 // Set callbacks to be called from the framer. A visitor must be set, or | 237 // Set callbacks to be called from the framer. A visitor must be set, or |
187 // else the framer will likely crash. It is acceptable for the visitor | 238 // else the framer will likely crash. It is acceptable for the visitor |
188 // to do nothing. If this is called multiple times, only the last visitor | 239 // to do nothing. If this is called multiple times, only the last visitor |
189 // will be used. | 240 // will be used. |
190 void set_visitor(SpdyFramerVisitorInterface* visitor) { | 241 void set_visitor(SpdyFramerVisitorInterface* visitor) { |
191 visitor_ = visitor; | 242 visitor_ = visitor; |
192 } | 243 } |
193 | 244 |
194 // Pass data into the framer for parsing. | 245 // Pass data into the framer for parsing. |
195 // Returns the number of bytes consumed. It is safe to pass more bytes in | 246 // Returns the number of bytes consumed. It is safe to pass more bytes in |
196 // than may be consumed. | 247 // than may be consumed. |
197 size_t ProcessInput(const char* data, size_t len); | 248 size_t ProcessInput(const char* data, size_t len); |
198 | 249 |
199 // Resets the framer state after a frame has been successfully decoded. | 250 // Resets the framer state after a frame has been successfully decoded. |
200 // TODO(mbelshe): can we make this private? | 251 // TODO(mbelshe): can we make this private? |
201 void Reset(); | 252 void Reset(); |
202 | 253 |
203 // Check the state of the framer. | 254 // Check the state of the framer. |
204 SpdyError error_code() const { return error_code_; } | 255 SpdyError error_code() const { return error_code_; } |
205 SpdyState state() const { return state_; } | 256 SpdyState state() const { return state_; } |
206 | 257 |
207 bool MessageFullyRead() { | 258 bool MessageFullyRead() { |
208 return state_ == SPDY_DONE || state_ == SPDY_AUTO_RESET; | 259 return state_ == SPDY_DONE || state_ == SPDY_AUTO_RESET; |
209 } | 260 } |
210 bool HasError() { return state_ == SPDY_ERROR; } | 261 bool HasError() { return state_ == SPDY_ERROR; } |
211 | 262 |
212 // Further parsing utilities. | |
213 // Given a control frame, parse out a SpdyHeaderBlock. Only | |
214 // valid for SYN_STREAM and SYN_REPLY frames. | |
215 // Returns true if successfully parsed, false otherwise. | |
216 bool ParseHeaderBlock(const SpdyFrame* frame, SpdyHeaderBlock* block); | |
217 | |
218 // Given a buffer containing a decompressed header block in SPDY | 263 // Given a buffer containing a decompressed header block in SPDY |
219 // serialized format, parse out a SpdyHeaderBlock, putting the results | 264 // serialized format, parse out a SpdyHeaderBlock, putting the results |
220 // in the given header block. | 265 // in the given header block. |
221 // Returns true if successfully parsed, false otherwise. | 266 // Returns true if successfully parsed, false otherwise. |
222 static bool ParseHeaderBlockInBuffer(const char* header_data, | 267 bool ParseHeaderBlockInBuffer(const char* header_data, |
223 size_t header_length, | 268 size_t header_length, |
224 SpdyHeaderBlock* block); | 269 SpdyHeaderBlock* block); |
225 | 270 |
226 // Create a SpdySynStreamControlFrame. | 271 // Create a SpdySynStreamControlFrame. |
227 // |stream_id| is the id for this stream. | 272 // |stream_id| is the id for this stream. |
228 // |associated_stream_id| is the associated stream id for this stream. | 273 // |associated_stream_id| is the associated stream id for this stream. |
229 // |priority| is the priority (0-3) for this stream. | 274 // |priority| is the priority (GetHighestPriority()-GetLowestPriority) for |
| 275 // this stream. |
230 // |flags| is the flags to use with the data. | 276 // |flags| is the flags to use with the data. |
231 // To mark this frame as the last frame, enable CONTROL_FLAG_FIN. | 277 // To mark this frame as the last frame, enable CONTROL_FLAG_FIN. |
232 // |compressed| specifies whether the frame should be compressed. | 278 // |compressed| specifies whether the frame should be compressed. |
233 // |headers| is the header block to include in the frame. | 279 // |headers| is the header block to include in the frame. |
234 SpdySynStreamControlFrame* CreateSynStream(SpdyStreamId stream_id, | 280 SpdySynStreamControlFrame* CreateSynStream(SpdyStreamId stream_id, |
235 SpdyStreamId associated_stream_id, | 281 SpdyStreamId associated_stream_id, |
236 int priority, | 282 SpdyPriority priority, |
237 SpdyControlFlags flags, | 283 SpdyControlFlags flags, |
238 bool compressed, | 284 bool compressed, |
239 const SpdyHeaderBlock* headers); | 285 const SpdyHeaderBlock* headers); |
240 | 286 |
241 // Create a SpdySynReplyControlFrame. | 287 // Create a SpdySynReplyControlFrame. |
242 // |stream_id| is the stream for this frame. | 288 // |stream_id| is the stream for this frame. |
243 // |flags| is the flags to use with the data. | 289 // |flags| is the flags to use with the data. |
244 // To mark this frame as the last frame, enable CONTROL_FLAG_FIN. | 290 // To mark this frame as the last frame, enable CONTROL_FLAG_FIN. |
245 // |compressed| specifies whether the frame should be compressed. | 291 // |compressed| specifies whether the frame should be compressed. |
246 // |headers| is the header block to include in the frame. | 292 // |headers| is the header block to include in the frame. |
247 SpdySynReplyControlFrame* CreateSynReply(SpdyStreamId stream_id, | 293 SpdySynReplyControlFrame* CreateSynReply(SpdyStreamId stream_id, |
248 SpdyControlFlags flags, | 294 SpdyControlFlags flags, |
249 bool compressed, | 295 bool compressed, |
250 const SpdyHeaderBlock* headers); | 296 const SpdyHeaderBlock* headers); |
251 | 297 |
252 static SpdyRstStreamControlFrame* CreateRstStream(SpdyStreamId stream_id, | 298 SpdyRstStreamControlFrame* CreateRstStream(SpdyStreamId stream_id, |
253 SpdyStatusCodes status); | 299 SpdyStatusCodes status) const; |
254 | 300 |
255 // Creates an instance of SpdySettingsControlFrame. The SETTINGS frame is | 301 // Creates an instance of SpdySettingsControlFrame. The SETTINGS frame is |
256 // used to communicate name/value pairs relevant to the communication channel. | 302 // used to communicate name/value pairs relevant to the communication channel. |
257 // TODO(mbelshe): add the name/value pairs!! | 303 SpdySettingsControlFrame* CreateSettings(const SpdySettings& values) const; |
258 static SpdySettingsControlFrame* CreateSettings(const SpdySettings& values); | |
259 | |
260 static SpdyNoOpControlFrame* CreateNopFrame(); | |
261 | 304 |
262 // Creates an instance of SpdyPingControlFrame. The unique_id is used to | 305 // Creates an instance of SpdyPingControlFrame. The unique_id is used to |
263 // identify the ping request/response. | 306 // identify the ping request/response. |
264 static SpdyPingControlFrame* CreatePingFrame(uint32 unique_id); | 307 SpdyPingControlFrame* CreatePingFrame(uint32 unique_id) const; |
265 | 308 |
266 // Creates an instance of SpdyGoAwayControlFrame. The GOAWAY frame is used | 309 // Creates an instance of SpdyGoAwayControlFrame. The GOAWAY frame is used |
267 // prior to the shutting down of the TCP connection, and includes the | 310 // prior to the shutting down of the TCP connection, and includes the |
268 // stream_id of the last stream the sender of the frame is willing to process | 311 // stream_id of the last stream the sender of the frame is willing to process |
269 // to completion. | 312 // to completion. |
270 static SpdyGoAwayControlFrame* CreateGoAway( | 313 SpdyGoAwayControlFrame* CreateGoAway( |
271 SpdyStreamId last_accepted_stream_id); | 314 SpdyStreamId last_accepted_stream_id) const; |
272 | 315 |
273 // Creates an instance of SpdyHeadersControlFrame. The HEADERS frame is used | 316 // Creates an instance of SpdyHeadersControlFrame. The HEADERS frame is used |
274 // for sending additional headers outside of a SYN_STREAM/SYN_REPLY. The | 317 // for sending additional headers outside of a SYN_STREAM/SYN_REPLY. The |
275 // arguments are the same as for CreateSynReply. | 318 // arguments are the same as for CreateSynReply. |
276 SpdyHeadersControlFrame* CreateHeaders(SpdyStreamId stream_id, | 319 SpdyHeadersControlFrame* CreateHeaders(SpdyStreamId stream_id, |
277 SpdyControlFlags flags, | 320 SpdyControlFlags flags, |
278 bool compressed, | 321 bool compressed, |
279 const SpdyHeaderBlock* headers); | 322 const SpdyHeaderBlock* headers); |
280 | 323 |
281 // Creates an instance of SpdyWindowUpdateControlFrame. The WINDOW_UPDATE | 324 // Creates an instance of SpdyWindowUpdateControlFrame. The WINDOW_UPDATE |
282 // frame is used to implement per stream flow control in SPDY. | 325 // frame is used to implement per stream flow control in SPDY. |
283 static SpdyWindowUpdateControlFrame* CreateWindowUpdate( | 326 SpdyWindowUpdateControlFrame* CreateWindowUpdate( |
284 SpdyStreamId stream_id, | 327 SpdyStreamId stream_id, |
285 uint32 delta_window_size); | 328 uint32 delta_window_size) const; |
286 | 329 |
287 // Creates an instance of SpdyCredentialControlFrame. The CREDENTIAL | 330 // Creates an instance of SpdyCredentialControlFrame. The CREDENTIAL |
288 // frame is used to send a client certificate to the server when | 331 // frame is used to send a client certificate to the server when |
289 // request more than one origin are sent over the same SPDY session. | 332 // request more than one origin are sent over the same SPDY session. |
290 static SpdyCredentialControlFrame* CreateCredentialFrame( | 333 SpdyCredentialControlFrame* CreateCredentialFrame( |
291 const SpdyCredential& credential); | 334 const SpdyCredential& credential) const; |
292 | 335 |
293 // Given a SpdySettingsControlFrame, extract the settings. | 336 // Given a SpdySettingsControlFrame, extract the settings. |
294 // Returns true on successful parse, false otherwise. | 337 // Returns true on successful parse, false otherwise. |
295 static bool ParseSettings(const SpdySettingsControlFrame* frame, | 338 static bool ParseSettings(const SpdySettingsControlFrame* frame, |
296 SpdySettings* settings); | 339 SpdySettings* settings); |
297 | 340 |
298 // Given a SpdyCredentialControlFrame's payload, extract the credential. | 341 // Given a SpdyCredentialControlFrame's payload, extract the credential. |
299 // Returns true on successful parse, false otherwise. | 342 // Returns true on successful parse, false otherwise. |
300 // TODO(hkhalil): Implement CREDENTIAL frame parsing in SpdyFramer | 343 // TODO(hkhalil): Implement CREDENTIAL frame parsing in SpdyFramer |
301 // and eliminate this method. | 344 // and eliminate this method. |
(...skipping 21 matching lines...) Expand all Loading... |
323 // not build its state in a serial (stream based) manner.... For now, we're | 366 // not build its state in a serial (stream based) manner.... For now, we're |
324 // using zlib anyway. | 367 // using zlib anyway. |
325 | 368 |
326 // Compresses a SpdyFrame. | 369 // Compresses a SpdyFrame. |
327 // On success, returns a new SpdyFrame with the payload compressed. | 370 // On success, returns a new SpdyFrame with the payload compressed. |
328 // Compression state is maintained as part of the SpdyFramer. | 371 // Compression state is maintained as part of the SpdyFramer. |
329 // Returned frame must be freed with "delete". | 372 // Returned frame must be freed with "delete". |
330 // On failure, returns NULL. | 373 // On failure, returns NULL. |
331 SpdyFrame* CompressFrame(const SpdyFrame& frame); | 374 SpdyFrame* CompressFrame(const SpdyFrame& frame); |
332 | 375 |
333 // Decompresses a SpdyFrame. | |
334 // On success, returns a new SpdyFrame with the payload decompressed. | |
335 // Compression state is maintained as part of the SpdyFramer. | |
336 // Returned frame must be freed with "delete". | |
337 // On failure, returns NULL. | |
338 SpdyFrame* DecompressFrame(const SpdyFrame& frame); | |
339 | |
340 // Create a copy of a frame. | 376 // Create a copy of a frame. |
341 // Returned frame must be freed with "delete". | 377 // Returned frame must be freed with "delete". |
342 SpdyFrame* DuplicateFrame(const SpdyFrame& frame); | 378 SpdyFrame* DuplicateFrame(const SpdyFrame& frame); |
343 | 379 |
344 // Returns true if a frame could be compressed. | 380 // Returns true if a frame could be compressed. |
345 bool IsCompressible(const SpdyFrame& frame) const; | 381 bool IsCompressible(const SpdyFrame& frame) const; |
346 | 382 |
347 // Get the minimum size of the control frame for the given control frame | 383 // Get the minimum size of the control frame for the given control frame |
348 // type. This is useful for validating frame blocks. | 384 // type. This is useful for validating frame blocks. |
349 static size_t GetMinimumControlFrameSize(SpdyControlType type); | 385 static size_t GetMinimumControlFrameSize(SpdyControlType type); |
(...skipping 16 matching lines...) Expand all Loading... |
366 void set_display_protocol(const std::string& protocol) { | 402 void set_display_protocol(const std::string& protocol) { |
367 display_protocol_ = protocol; | 403 display_protocol_ = protocol; |
368 } | 404 } |
369 | 405 |
370 // For debugging. | 406 // For debugging. |
371 static const char* StateToString(int state); | 407 static const char* StateToString(int state); |
372 static const char* ErrorCodeToString(int error_code); | 408 static const char* ErrorCodeToString(int error_code); |
373 static const char* StatusCodeToString(int status_code); | 409 static const char* StatusCodeToString(int status_code); |
374 static const char* ControlTypeToString(SpdyControlType type); | 410 static const char* ControlTypeToString(SpdyControlType type); |
375 | 411 |
376 static void set_protocol_version(int version) { spdy_version_= version; } | 412 // TODO(hkhalil): Remove SpdyFramer::set_protocol_version() |
377 static int protocol_version() { return spdy_version_; } | 413 void set_protocol_version(int version) { spdy_version_= version; } |
| 414 int protocol_version() const { return spdy_version_; } |
378 | 415 |
379 // Export the compression dictionary | 416 bool probable_http_response() { return probable_http_response_; } |
380 static const char kDictionary[]; | 417 |
381 static const int kDictionarySize; | 418 SpdyPriority GetLowestPriority() const { return spdy_version_ < 3 ? 3 : 7; } |
| 419 SpdyPriority GetHighestPriority() const { return 0; } |
382 | 420 |
383 protected: | 421 protected: |
| 422 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, BasicCompression); |
| 423 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ControlFrameSizesAreValidated); |
384 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, HeaderCompression); | 424 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, HeaderCompression); |
| 425 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, DecompressUncompressedFrame); |
385 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ExpandBuffer_HeapSmash); | 426 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ExpandBuffer_HeapSmash); |
386 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, HugeHeaderBlock); | 427 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, HugeHeaderBlock); |
387 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, UnclosedStreamDataCompressors); | 428 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, UnclosedStreamDataCompressors); |
| 429 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, |
| 430 UnclosedStreamDataCompressorsOneByteAtATime); |
| 431 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, |
| 432 UncompressLargerThanFrameBufferInitialSize); |
| 433 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ReadLargeSettingsFrame); |
| 434 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ReadLargeSettingsFrameInSmallChunks); |
388 friend class net::HttpNetworkLayer; // This is temporary for the server. | 435 friend class net::HttpNetworkLayer; // This is temporary for the server. |
389 friend class net::HttpNetworkTransactionTest; | 436 friend class net::HttpNetworkTransactionTest; |
390 friend class net::HttpProxyClientSocketPoolTest; | 437 friend class net::HttpProxyClientSocketPoolTest; |
391 friend class net::SpdyHttpStreamTest; | 438 friend class net::SpdyHttpStreamTest; |
392 friend class net::SpdyNetworkTransactionTest; | 439 friend class net::SpdyNetworkTransactionTest; |
393 friend class net::SpdyProxyClientSocketTest; | 440 friend class net::SpdyProxyClientSocketTest; |
394 friend class net::SpdySessionTest; | 441 friend class net::SpdySessionTest; |
395 friend class net::SpdyStreamTest; | 442 friend class net::SpdyStreamTest; |
396 friend class net::SpdyWebSocketStreamTest; | 443 friend class net::SpdyWebSocketStreamTest; |
397 friend class net::WebSocketJobTest; | 444 friend class net::WebSocketJobTest; |
398 friend class test::TestSpdyVisitor; | 445 friend class test::TestSpdyVisitor; |
399 friend void test::FramerSetEnableCompressionHelper(SpdyFramer* framer, | |
400 bool compress); | |
401 | 446 |
402 private: | 447 private: |
403 typedef std::map<SpdyStreamId, z_stream*> CompressorMap; | 448 typedef std::map<SpdyStreamId, z_stream*> CompressorMap; |
404 | 449 |
405 // Internal breakout from ProcessInput. Returns the number of bytes | 450 // Internal breakouts from ProcessInput. Each returns the number of bytes |
406 // consumed from the data. | 451 // consumed from the data. |
407 size_t ProcessCommonHeader(const char* data, size_t len); | 452 size_t ProcessCommonHeader(const char* data, size_t len); |
408 void ProcessControlFrameHeader(); | |
409 size_t ProcessControlFramePayload(const char* data, size_t len); | 453 size_t ProcessControlFramePayload(const char* data, size_t len); |
410 size_t ProcessCredentialFramePayload(const char* data, size_t len); | 454 size_t ProcessCredentialFramePayload(const char* data, size_t len); |
411 size_t ProcessControlFrameBeforeHeaderBlock(const char* data, size_t len); | 455 size_t ProcessControlFrameBeforeHeaderBlock(const char* data, size_t len); |
412 size_t ProcessControlFrameHeaderBlock(const char* data, size_t len); | 456 size_t ProcessControlFrameHeaderBlock(const char* data, size_t len); |
| 457 size_t ProcessSettingsFramePayload(const char* data, size_t len); |
413 size_t ProcessDataFramePayload(const char* data, size_t len); | 458 size_t ProcessDataFramePayload(const char* data, size_t len); |
414 | 459 |
| 460 // Helpers for above internal breakouts from ProcessInput. |
| 461 void ProcessControlFrameHeader(); |
| 462 bool ProcessSetting(const char* data); // Always passed exactly 8 bytes. |
| 463 |
415 // Get (and lazily initialize) the ZLib state. | 464 // Get (and lazily initialize) the ZLib state. |
416 z_stream* GetHeaderCompressor(); | 465 z_stream* GetHeaderCompressor(); |
417 z_stream* GetHeaderDecompressor(); | 466 z_stream* GetHeaderDecompressor(); |
418 z_stream* GetStreamCompressor(SpdyStreamId id); | |
419 z_stream* GetStreamDecompressor(SpdyStreamId id); | 467 z_stream* GetStreamDecompressor(SpdyStreamId id); |
420 | 468 |
421 // Compression helpers | 469 // Compression helpers |
422 SpdyControlFrame* CompressControlFrame(const SpdyControlFrame& frame); | 470 SpdyControlFrame* CompressControlFrame(const SpdyControlFrame& frame); |
423 SpdyDataFrame* CompressDataFrame(const SpdyDataFrame& frame); | |
424 SpdyControlFrame* DecompressControlFrame(const SpdyControlFrame& frame); | |
425 SpdyDataFrame* DecompressDataFrame(const SpdyDataFrame& frame); | |
426 SpdyFrame* CompressFrameWithZStream(const SpdyFrame& frame, | |
427 z_stream* compressor); | |
428 SpdyFrame* DecompressFrameWithZStream(const SpdyFrame& frame, | |
429 z_stream* decompressor); | |
430 void CleanupCompressorForStream(SpdyStreamId id); | 471 void CleanupCompressorForStream(SpdyStreamId id); |
431 void CleanupDecompressorForStream(SpdyStreamId id); | 472 void CleanupDecompressorForStream(SpdyStreamId id); |
432 void CleanupStreamCompressorsAndDecompressors(); | 473 void CleanupStreamCompressorsAndDecompressors(); |
433 | 474 |
434 // Not used (yet) | |
435 size_t BytesSafeToRead() const; | |
436 | |
437 // Deliver the given control frame's compressed headers block to the visitor | 475 // Deliver the given control frame's compressed headers block to the visitor |
438 // in decompressed form, in chunks. Returns true if the visitor has | 476 // in decompressed form, in chunks. Returns true if the visitor has |
439 // accepted all of the chunks. | 477 // accepted all of the chunks. |
440 bool IncrementallyDecompressControlFrameHeaderData( | 478 bool IncrementallyDecompressControlFrameHeaderData( |
441 const SpdyControlFrame* frame, | 479 const SpdyControlFrame* frame, |
442 const char* data, | 480 const char* data, |
443 size_t len); | 481 size_t len); |
444 | 482 |
445 // Deliver the given control frame's uncompressed headers block to the | 483 // Deliver the given control frame's uncompressed headers block to the |
446 // visitor in chunks. Returns true if the visitor has accepted all of the | 484 // visitor in chunks. Returns true if the visitor has accepted all of the |
447 // chunks. | 485 // chunks. |
448 bool IncrementallyDeliverControlFrameHeaderData(const SpdyControlFrame* frame, | 486 bool IncrementallyDeliverControlFrameHeaderData(const SpdyControlFrame* frame, |
449 const char* data, | 487 const char* data, |
450 size_t len); | 488 size_t len); |
451 | 489 |
452 // Utility to copy the given data block to the current frame buffer, up | 490 // Utility to copy the given data block to the current frame buffer, up |
453 // to the given maximum number of bytes, and update the buffer | 491 // to the given maximum number of bytes, and update the buffer |
454 // data (pointer and length). Returns the number of bytes | 492 // data (pointer and length). Returns the number of bytes |
455 // read, and: | 493 // read, and: |
456 // *data is advanced the number of bytes read. | 494 // *data is advanced the number of bytes read. |
457 // *len is reduced by the number of bytes read. | 495 // *len is reduced by the number of bytes read. |
458 size_t UpdateCurrentFrameBuffer(const char** data, size_t* len, | 496 size_t UpdateCurrentFrameBuffer(const char** data, size_t* len, |
459 size_t max_bytes); | 497 size_t max_bytes); |
460 | 498 |
| 499 // Retrieve serialized length of SpdyHeaderBlock. |
| 500 size_t GetSerializedLength(const SpdyHeaderBlock* headers) const; |
| 501 |
| 502 // Serializes a SpdyHeaderBlock. |
| 503 void WriteHeaderBlock(SpdyFrameBuilder* frame, |
| 504 const SpdyHeaderBlock* headers) const; |
| 505 |
461 // Set the error code and moves the framer into the error state. | 506 // Set the error code and moves the framer into the error state. |
462 void set_error(SpdyError error); | 507 void set_error(SpdyError error); |
463 | 508 |
464 // Expands the control frame buffer to accomodate a particular payload size. | 509 // Expands the control frame buffer to accomodate a particular payload size. |
465 void ExpandControlFrameBuffer(size_t size); | 510 void ExpandControlFrameBuffer(size_t size); |
466 | 511 |
467 // Given a frame, breakdown the variable payload length, the static header | 512 // Given a frame, breakdown the variable payload length, the static header |
468 // header length, and variable payload pointer. | 513 // header length, and variable payload pointer. |
469 bool GetFrameBoundaries(const SpdyFrame& frame, int* payload_length, | 514 bool GetFrameBoundaries(const SpdyFrame& frame, int* payload_length, |
470 int* header_length, const char** payload) const; | 515 int* header_length, const char** payload) const; |
(...skipping 12 matching lines...) Expand all Loading... |
483 // This exists because we don't do stream (de)compressed control frame data to | 528 // This exists because we don't do stream (de)compressed control frame data to |
484 // our visitor; we instead buffer the entirety of the control frame and then | 529 // our visitor; we instead buffer the entirety of the control frame and then |
485 // decompress in one fell swoop. | 530 // decompress in one fell swoop. |
486 // Since this is only used for control frame headers, the maximum control | 531 // Since this is only used for control frame headers, the maximum control |
487 // frame header size (18B) is sufficient; all remaining control frame data is | 532 // frame header size (18B) is sufficient; all remaining control frame data is |
488 // streamed to the visitor. | 533 // streamed to the visitor. |
489 // In addition to the maximum control frame header size, we account for any | 534 // In addition to the maximum control frame header size, we account for any |
490 // LOAS checksumming (16B) that may occur in the VTL case. | 535 // LOAS checksumming (16B) that may occur in the VTL case. |
491 // TODO(hkhalil): Remove post code-yellow once streamed inflate is properly | 536 // TODO(hkhalil): Remove post code-yellow once streamed inflate is properly |
492 // implemented. | 537 // implemented. |
493 static const size_t kUncompressedControlFrameBufferInitialSize = 18 + 16; | 538 static size_t kUncompressedControlFrameBufferInitialSize; |
494 | 539 |
495 // The maximum size of the control frame buffer that we support. | 540 // The maximum size of the control frame buffer that we support. |
496 // TODO(mbelshe): We should make this stream-based so there are no limits. | 541 // TODO(mbelshe): We should make this stream-based so there are no limits. |
497 static size_t kControlFrameBufferMaxSize; | 542 static size_t kControlFrameBufferMaxSize; |
498 | 543 |
499 // The size of the buffer into which compressed frames are inflated. | |
500 static const size_t kDecompressionBufferSize = 8 * 1024; | |
501 | |
502 SpdyState state_; | 544 SpdyState state_; |
503 SpdyError error_code_; | 545 SpdyError error_code_; |
504 size_t remaining_data_; | 546 size_t remaining_data_; |
505 | 547 |
506 // The number of bytes remaining to read from the current control frame's | 548 // The number of bytes remaining to read from the current control frame's |
507 // payload. | 549 // payload. |
508 size_t remaining_control_payload_; | 550 size_t remaining_control_payload_; |
509 | 551 |
510 // The number of bytes remaining to read from the current control frame's | 552 // The number of bytes remaining to read from the current control frame's |
511 // headers. Note that header data blocks (for control types that have them) | 553 // headers. Note that header data blocks (for control types that have them) |
512 // are part of the frame's payload, and not the frame's headers. | 554 // are part of the frame's payload, and not the frame's headers. |
513 size_t remaining_control_header_; | 555 size_t remaining_control_header_; |
514 | 556 |
515 char* current_frame_buffer_; | 557 char* current_frame_buffer_; |
516 size_t current_frame_len_; // Number of bytes read into the current_frame_. | 558 size_t current_frame_len_; // Number of bytes read into the current_frame_. |
517 size_t current_frame_capacity_; | 559 size_t current_frame_capacity_; |
518 | 560 |
| 561 // Scratch space for handling SETTINGS frames. |
| 562 // TODO(hkhalil): Unify memory for this scratch space with |
| 563 // current_frame_buffer_. |
| 564 SpdySettingsScratch settings_scratch_; |
| 565 |
519 bool validate_control_frame_sizes_; | 566 bool validate_control_frame_sizes_; |
520 bool enable_compression_; // Controls all compression | 567 bool enable_compression_; // Controls all compression |
521 // SPDY header compressors. | 568 // SPDY header compressors. |
522 scoped_ptr<z_stream> header_compressor_; | 569 scoped_ptr<z_stream> header_compressor_; |
523 scoped_ptr<z_stream> header_decompressor_; | 570 scoped_ptr<z_stream> header_decompressor_; |
524 | 571 |
525 // Per-stream data compressors. | 572 // Per-stream data compressors. |
526 CompressorMap stream_compressors_; | 573 CompressorMap stream_compressors_; |
527 CompressorMap stream_decompressors_; | 574 CompressorMap stream_decompressors_; |
528 | 575 |
529 SpdyFramerVisitorInterface* visitor_; | 576 SpdyFramerVisitorInterface* visitor_; |
530 | 577 |
531 std::string display_protocol_; | 578 std::string display_protocol_; |
532 | 579 |
| 580 int spdy_version_; |
| 581 |
| 582 // Tracks if we've ever gotten far enough in framing to see a control frame of |
| 583 // type SYN_STREAM or SYN_REPLY. |
| 584 // |
| 585 // If we ever get something which looks like a data frame before we've had a |
| 586 // SYN, we explicitly check to see if it looks like we got an HTTP response to |
| 587 // a SPDY request. This boolean lets us do that. |
| 588 bool syn_frame_processed_; |
| 589 |
| 590 // If we ever get a data frame before a SYN frame, we check to see if it |
| 591 // starts with HTTP. If it does, we likely have an HTTP response. This |
| 592 // isn't guaranteed though: we could have gotten a settings frame and then |
| 593 // corrupt data that just looks like HTTP, but deterministic checking requires |
| 594 // a lot more state. |
| 595 bool probable_http_response_; |
| 596 |
533 static bool compression_default_; | 597 static bool compression_default_; |
534 static int spdy_version_; | |
535 }; | 598 }; |
536 | 599 |
537 } // namespace spdy | 600 } // namespace spdy |
538 | 601 |
539 #endif // NET_SPDY_SPDY_FRAMER_H_ | 602 #endif // NET_SPDY_SPDY_FRAMER_H_ |
OLD | NEW |