OLD | NEW |
| (Empty) |
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_SPDY_SPDY_FRAMER_H_ | |
6 #define NET_SPDY_SPDY_FRAMER_H_ | |
7 | |
8 #include <stddef.h> | |
9 #include <stdint.h> | |
10 | |
11 #include <cstdint> | |
12 #include <map> | |
13 #include <memory> | |
14 #include <utility> | |
15 | |
16 #include "base/sys_byteorder.h" | |
17 #include "net/base/net_export.h" | |
18 #include "net/spdy/hpack/hpack_decoder_interface.h" | |
19 #include "net/spdy/hpack/hpack_encoder.h" | |
20 #include "net/spdy/platform/api/spdy_string.h" | |
21 #include "net/spdy/platform/api/spdy_string_piece.h" | |
22 #include "net/spdy/spdy_alt_svc_wire_format.h" | |
23 #include "net/spdy/spdy_flags.h" | |
24 #include "net/spdy/spdy_header_block.h" | |
25 #include "net/spdy/spdy_headers_handler_interface.h" | |
26 #include "net/spdy/spdy_protocol.h" | |
27 #include "net/spdy/zero_copy_output_buffer.h" | |
28 | |
29 namespace net { | |
30 | |
31 class HttpProxyClientSocketPoolTest; | |
32 class HttpNetworkLayer; | |
33 class HttpNetworkTransactionTest; | |
34 class SpdyHttpStreamTest; | |
35 class SpdyNetworkTransactionTest; | |
36 class SpdyProxyClientSocketTest; | |
37 class SpdySessionTest; | |
38 class SpdyStreamTest; | |
39 | |
40 class SpdyFramer; | |
41 class SpdyFrameBuilder; | |
42 class SpdyFramerDecoderAdapter; | |
43 | |
44 namespace test { | |
45 | |
46 class TestSpdyVisitor; | |
47 class SpdyFramerPeer; | |
48 | |
49 } // namespace test | |
50 | |
51 // SpdyFramerVisitorInterface is a set of callbacks for the SpdyFramer. | |
52 // Implement this interface to receive event callbacks as frames are | |
53 // decoded from the framer. | |
54 // | |
55 // Control frames that contain HTTP2 header blocks (HEADER, and PUSH_PROMISE) | |
56 // are processed in fashion that allows the decompressed header block to be | |
57 // delivered in chunks to the visitor. | |
58 // The following steps are followed: | |
59 // 1. OnHeaders, or OnPushPromise is called. | |
60 // 2. OnHeaderFrameStart is called; visitor is expected to return an instance | |
61 // of SpdyHeadersHandlerInterface that will receive the header key-value | |
62 // pairs. | |
63 // 3. OnHeaderFrameEnd is called, indicating that the full header block has | |
64 // been delivered for the control frame. | |
65 // During step 2, if the visitor is not interested in accepting the header data, | |
66 // it should return a no-op implementation of SpdyHeadersHandlerInterface. | |
67 class NET_EXPORT_PRIVATE SpdyFramerVisitorInterface { | |
68 public: | |
69 virtual ~SpdyFramerVisitorInterface() {} | |
70 | |
71 // Called if an error is detected in the SpdySerializedFrame protocol. | |
72 virtual void OnError(SpdyFramer* framer) = 0; | |
73 | |
74 // Called when the common header for a frame is received. Validating the | |
75 // common header occurs in later processing. | |
76 virtual void OnCommonHeader(SpdyStreamId stream_id, | |
77 size_t length, | |
78 uint8_t type, | |
79 uint8_t flags) {} | |
80 | |
81 // Called when a data frame header is received. The frame's data | |
82 // payload will be provided via subsequent calls to | |
83 // OnStreamFrameData(). | |
84 virtual void OnDataFrameHeader(SpdyStreamId stream_id, | |
85 size_t length, | |
86 bool fin) = 0; | |
87 | |
88 // Called when data is received. | |
89 // |stream_id| The stream receiving data. | |
90 // |data| A buffer containing the data received. | |
91 // |len| The length of the data buffer. | |
92 virtual void OnStreamFrameData(SpdyStreamId stream_id, | |
93 const char* data, | |
94 size_t len) = 0; | |
95 | |
96 // Called when the other side has finished sending data on this stream. | |
97 // |stream_id| The stream that was receivin data. | |
98 virtual void OnStreamEnd(SpdyStreamId stream_id) = 0; | |
99 | |
100 // Called when padding is received (padding length field or padding octets). | |
101 // |stream_id| The stream receiving data. | |
102 // |len| The number of padding octets. | |
103 virtual void OnStreamPadding(SpdyStreamId stream_id, size_t len) = 0; | |
104 | |
105 // Called just before processing the payload of a frame containing header | |
106 // data. Should return an implementation of SpdyHeadersHandlerInterface that | |
107 // will receive headers for stream |stream_id|. The caller will not take | |
108 // ownership of the headers handler. The same instance should remain live | |
109 // and be returned for all header frames comprising a logical header block | |
110 // (i.e. until OnHeaderFrameEnd() is called with end_headers == true). | |
111 virtual SpdyHeadersHandlerInterface* OnHeaderFrameStart( | |
112 SpdyStreamId stream_id) = 0; | |
113 | |
114 // Called after processing the payload of a frame containing header data. | |
115 // |end_headers| is true if there will not be any subsequent CONTINUATION | |
116 // frames. | |
117 virtual void OnHeaderFrameEnd(SpdyStreamId stream_id, bool end_headers) = 0; | |
118 | |
119 // Called when a RST_STREAM frame has been parsed. | |
120 virtual void OnRstStream(SpdyStreamId stream_id, | |
121 SpdyErrorCode error_code) = 0; | |
122 | |
123 // Called when a SETTINGS frame is received. | |
124 // |clear_persisted| True if the respective flag is set on the SETTINGS frame. | |
125 virtual void OnSettings(bool clear_persisted) {} | |
126 | |
127 // Called when a complete setting within a SETTINGS frame has been parsed and | |
128 // validated. | |
129 virtual void OnSetting(SpdySettingsIds id, uint32_t value) = 0; | |
130 | |
131 // Called when a SETTINGS frame is received with the ACK flag set. | |
132 virtual void OnSettingsAck() {} | |
133 | |
134 // Called before and after parsing SETTINGS id and value tuples. | |
135 virtual void OnSettingsEnd() = 0; | |
136 | |
137 // Called when a PING frame has been parsed. | |
138 virtual void OnPing(SpdyPingId unique_id, bool is_ack) = 0; | |
139 | |
140 // Called when a GOAWAY frame has been parsed. | |
141 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id, | |
142 SpdyErrorCode error_code) = 0; | |
143 | |
144 // Called when a HEADERS frame is received. | |
145 // Note that header block data is not included. See OnHeaderFrameStart(). | |
146 // |stream_id| The stream receiving the header. | |
147 // |has_priority| Whether or not the headers frame included a priority value, | |
148 // and stream dependency info. | |
149 // |weight| If |has_priority| is true, then weight (in the range [1, 256]) | |
150 // for the receiving stream, otherwise 0. | |
151 // |parent_stream_id| If |has_priority| is true the parent stream of the | |
152 // receiving stream, else 0. | |
153 // |exclusive| If |has_priority| is true the exclusivity of dependence on the | |
154 // parent stream, else false. | |
155 // |fin| Whether FIN flag is set in frame headers. | |
156 // |end| False if HEADERs frame is to be followed by a CONTINUATION frame, | |
157 // or true if not. | |
158 virtual void OnHeaders(SpdyStreamId stream_id, | |
159 bool has_priority, | |
160 int weight, | |
161 SpdyStreamId parent_stream_id, | |
162 bool exclusive, | |
163 bool fin, | |
164 bool end) = 0; | |
165 | |
166 // Called when a WINDOW_UPDATE frame has been parsed. | |
167 virtual void OnWindowUpdate(SpdyStreamId stream_id, | |
168 int delta_window_size) = 0; | |
169 | |
170 // Called when a goaway frame opaque data is available. | |
171 // |goaway_data| A buffer containing the opaque GOAWAY data chunk received. | |
172 // |len| The length of the header data buffer. A length of zero indicates | |
173 // that the header data block has been completely sent. | |
174 // When this function returns true the visitor indicates that it accepted | |
175 // all of the data. Returning false indicates that that an error has | |
176 // occurred while processing the data. Default implementation returns true. | |
177 virtual bool OnGoAwayFrameData(const char* goaway_data, size_t len); | |
178 | |
179 // Called when a PUSH_PROMISE frame is received. | |
180 // Note that header block data is not included. See OnHeaderFrameStart(). | |
181 virtual void OnPushPromise(SpdyStreamId stream_id, | |
182 SpdyStreamId promised_stream_id, | |
183 bool end) = 0; | |
184 | |
185 // Called when a CONTINUATION frame is received. | |
186 // Note that header block data is not included. See OnHeaderFrameStart(). | |
187 virtual void OnContinuation(SpdyStreamId stream_id, bool end) = 0; | |
188 | |
189 // Called when an ALTSVC frame has been parsed. | |
190 virtual void OnAltSvc( | |
191 SpdyStreamId stream_id, | |
192 SpdyStringPiece origin, | |
193 const SpdyAltSvcWireFormat::AlternativeServiceVector& altsvc_vector) {} | |
194 | |
195 // Called when a PRIORITY frame is received. | |
196 // |stream_id| The stream to update the priority of. | |
197 // |parent_stream_id| The parent stream of |stream_id|. | |
198 // |weight| Stream weight, in the range [1, 256]. | |
199 // |exclusive| Whether |stream_id| should be an only child of | |
200 // |parent_stream_id|. | |
201 virtual void OnPriority(SpdyStreamId stream_id, | |
202 SpdyStreamId parent_stream_id, | |
203 int weight, | |
204 bool exclusive) {} | |
205 | |
206 // Called when a frame type we don't recognize is received. | |
207 // Return true if this appears to be a valid extension frame, false otherwise. | |
208 // We distinguish between extension frames and nonsense by checking | |
209 // whether the stream id is valid. | |
210 virtual bool OnUnknownFrame(SpdyStreamId stream_id, uint8_t frame_type) = 0; | |
211 }; | |
212 | |
213 class SpdyFrameSequence { | |
214 public: | |
215 virtual ~SpdyFrameSequence() {} | |
216 | |
217 // Serializes the next frame in the sequence to |output|. Returns the number | |
218 // of bytes written to |output|. | |
219 virtual size_t NextFrame(ZeroCopyOutputBuffer* output) = 0; | |
220 | |
221 // Returns true iff there is at least one more frame in the sequence. | |
222 virtual bool HasNextFrame() const = 0; | |
223 }; | |
224 | |
225 class ExtensionVisitorInterface { | |
226 public: | |
227 virtual ~ExtensionVisitorInterface() {} | |
228 | |
229 // Called when non-standard SETTINGS are received. | |
230 virtual void OnSetting(uint16_t id, uint32_t value) = 0; | |
231 | |
232 // Called when non-standard frames are received. | |
233 virtual bool OnFrameHeader(SpdyStreamId stream_id, | |
234 size_t length, | |
235 uint8_t type, | |
236 uint8_t flags) = 0; | |
237 | |
238 // The payload for a single frame may be delivered as multiple calls to | |
239 // OnFramePayload. Since the length field is passed in OnFrameHeader, there is | |
240 // no explicit indication of the end of the frame payload. | |
241 virtual void OnFramePayload(const char* data, size_t len) = 0; | |
242 }; | |
243 | |
244 // Optionally, and in addition to SpdyFramerVisitorInterface, a class supporting | |
245 // SpdyFramerDebugVisitorInterface may be used in conjunction with SpdyFramer in | |
246 // order to extract debug/internal information about the SpdyFramer as it | |
247 // operates. | |
248 // | |
249 // Most HTTP2 implementations need not bother with this interface at all. | |
250 class NET_EXPORT_PRIVATE SpdyFramerDebugVisitorInterface { | |
251 public: | |
252 virtual ~SpdyFramerDebugVisitorInterface() {} | |
253 | |
254 // Called after compressing a frame with a payload of | |
255 // a list of name-value pairs. | |
256 // |payload_len| is the uncompressed payload size. | |
257 // |frame_len| is the compressed frame size. | |
258 virtual void OnSendCompressedFrame(SpdyStreamId stream_id, | |
259 SpdyFrameType type, | |
260 size_t payload_len, | |
261 size_t frame_len) {} | |
262 | |
263 // Called when a frame containing a compressed payload of | |
264 // name-value pairs is received. | |
265 // |frame_len| is the compressed frame size. | |
266 virtual void OnReceiveCompressedFrame(SpdyStreamId stream_id, | |
267 SpdyFrameType type, | |
268 size_t frame_len) {} | |
269 }; | |
270 | |
271 class NET_EXPORT_PRIVATE SpdyFramer { | |
272 public: | |
273 // HTTP2 states. | |
274 enum SpdyState { | |
275 SPDY_ERROR, | |
276 SPDY_READY_FOR_FRAME, // Framer is ready for reading the next frame. | |
277 SPDY_FRAME_COMPLETE, // Framer has finished reading a frame, need to reset. | |
278 SPDY_READING_COMMON_HEADER, | |
279 SPDY_CONTROL_FRAME_PAYLOAD, | |
280 SPDY_READ_DATA_FRAME_PADDING_LENGTH, | |
281 SPDY_CONSUME_PADDING, | |
282 SPDY_IGNORE_REMAINING_PAYLOAD, | |
283 SPDY_FORWARD_STREAM_FRAME, | |
284 SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, | |
285 SPDY_CONTROL_FRAME_HEADER_BLOCK, | |
286 SPDY_GOAWAY_FRAME_PAYLOAD, | |
287 SPDY_SETTINGS_FRAME_HEADER, | |
288 SPDY_SETTINGS_FRAME_PAYLOAD, | |
289 SPDY_ALTSVC_FRAME_PAYLOAD, | |
290 SPDY_EXTENSION_FRAME_PAYLOAD, | |
291 }; | |
292 | |
293 // Framer error codes. | |
294 enum SpdyFramerError { | |
295 SPDY_NO_ERROR, | |
296 SPDY_INVALID_STREAM_ID, // Stream ID is invalid | |
297 SPDY_INVALID_CONTROL_FRAME, // Control frame is mal-formatted. | |
298 SPDY_CONTROL_PAYLOAD_TOO_LARGE, // Control frame payload was too large. | |
299 SPDY_ZLIB_INIT_FAILURE, // The Zlib library could not initialize. | |
300 SPDY_UNSUPPORTED_VERSION, // Control frame has unsupported version. | |
301 SPDY_DECOMPRESS_FAILURE, // There was an error decompressing. | |
302 SPDY_COMPRESS_FAILURE, // There was an error compressing. | |
303 SPDY_GOAWAY_FRAME_CORRUPT, // GOAWAY frame could not be parsed. | |
304 SPDY_RST_STREAM_FRAME_CORRUPT, // RST_STREAM frame could not be parsed. | |
305 SPDY_INVALID_PADDING, // HEADERS or DATA frame padding invalid | |
306 SPDY_INVALID_DATA_FRAME_FLAGS, // Data frame has invalid flags. | |
307 SPDY_INVALID_CONTROL_FRAME_FLAGS, // Control frame has invalid flags. | |
308 SPDY_UNEXPECTED_FRAME, // Frame received out of order. | |
309 SPDY_INTERNAL_FRAMER_ERROR, // SpdyFramer was used incorrectly. | |
310 SPDY_INVALID_CONTROL_FRAME_SIZE, // Control frame not sized to spec | |
311 SPDY_OVERSIZED_PAYLOAD, // Payload size was too large | |
312 | |
313 LAST_ERROR, // Must be the last entry in the enum. | |
314 }; | |
315 | |
316 enum CompressionOption { | |
317 ENABLE_COMPRESSION, | |
318 DISABLE_COMPRESSION, | |
319 }; | |
320 | |
321 // Typedef for a function used to create SpdyFramerDecoderAdapter's. | |
322 // Defined in support of evaluating an alternate HTTP/2 decoder. | |
323 typedef std::unique_ptr<SpdyFramerDecoderAdapter> (*DecoderAdapterFactoryFn)( | |
324 SpdyFramer* outer); | |
325 | |
326 // Constant for invalid (or unknown) stream IDs. | |
327 static const SpdyStreamId kInvalidStream; | |
328 | |
329 // The maximum size of header data decompressed/delivered at once to the | |
330 // header block parser. (Exposed here for unit test purposes.) | |
331 static const size_t kHeaderDataChunkMaxSize; | |
332 | |
333 void SerializeHeaderBlockWithoutCompression( | |
334 SpdyFrameBuilder* builder, | |
335 const SpdyHeaderBlock& header_block) const; | |
336 | |
337 // Retrieve serialized length of SpdyHeaderBlock. | |
338 static size_t GetSerializedLength(const SpdyHeaderBlock* headers); | |
339 | |
340 // Gets the serialized flags for the given |frame|. | |
341 static uint8_t GetSerializedFlags(const SpdyFrameIR& frame); | |
342 | |
343 explicit SpdyFramer(CompressionOption option); | |
344 | |
345 // Used recursively from the above constructor in order to support | |
346 // instantiating a SpdyFramerDecoderAdapter selected via flags or some other | |
347 // means. | |
348 SpdyFramer(DecoderAdapterFactoryFn adapter_factory, CompressionOption option); | |
349 | |
350 virtual ~SpdyFramer(); | |
351 | |
352 // Set callbacks to be called from the framer. A visitor must be set, or | |
353 // else the framer will likely crash. It is acceptable for the visitor | |
354 // to do nothing. If this is called multiple times, only the last visitor | |
355 // will be used. | |
356 void set_visitor(SpdyFramerVisitorInterface* visitor); | |
357 | |
358 // Set extension callbacks to be called from the framer. (Optional.) | |
359 void set_extension_visitor(ExtensionVisitorInterface* extension); | |
360 | |
361 // Set debug callbacks to be called from the framer. The debug visitor is | |
362 // completely optional and need not be set in order for normal operation. | |
363 // If this is called multiple times, only the last visitor will be used. | |
364 void set_debug_visitor(SpdyFramerDebugVisitorInterface* debug_visitor); | |
365 | |
366 // Sets whether or not ProcessInput returns after finishing a frame, or | |
367 // continues processing additional frames. Normally ProcessInput processes | |
368 // all input, but this method enables the caller (and visitor) to work with | |
369 // a single frame at a time (or that portion of the frame which is provided | |
370 // as input). Reset() does not change the value of this flag. | |
371 void set_process_single_input_frame(bool v); | |
372 | |
373 // Pass data into the framer for parsing. | |
374 // Returns the number of bytes consumed. It is safe to pass more bytes in | |
375 // than may be consumed. | |
376 size_t ProcessInput(const char* data, size_t len); | |
377 | |
378 // Resets the framer state after a frame has been successfully decoded. | |
379 // TODO(mbelshe): can we make this private? | |
380 void Reset(); | |
381 | |
382 // Check the state of the framer. | |
383 SpdyFramerError spdy_framer_error() const; | |
384 SpdyState state() const; | |
385 bool HasError() const { return state() == SPDY_ERROR; } | |
386 | |
387 // Given a buffer containing a serialized header block parse out a | |
388 // SpdyHeaderBlock, putting the results in the given header block. | |
389 // Returns true if successfully parsed, false otherwise. | |
390 bool ParseHeaderBlockInBuffer(const char* header_data, | |
391 size_t header_length, | |
392 SpdyHeaderBlock* block) const; | |
393 | |
394 // Iteratively converts a SpdyFrameWithHeaderBlockIR into an appropriate | |
395 // sequence of SpdySerializedFrames. | |
396 class NET_EXPORT_PRIVATE SpdyFrameIterator { | |
397 public: | |
398 // Creates an iterator with the provided framer. | |
399 // Does not take ownership of |framer|. | |
400 // |framer| must outlive this instance. | |
401 explicit SpdyFrameIterator(SpdyFramer* framer); | |
402 virtual ~SpdyFrameIterator(); | |
403 | |
404 // Serializes the next frame in the sequence to |output|. Returns the number | |
405 // of bytes written to |output|. | |
406 virtual bool NextFrame(ZeroCopyOutputBuffer* output); | |
407 | |
408 // Returns true iff there is at least one more frame in the sequence. | |
409 virtual bool HasNextFrame() const; | |
410 | |
411 // SpdyFrameIterator is neither copyable nor movable. | |
412 SpdyFrameIterator(const SpdyFrameIterator&) = delete; | |
413 SpdyFrameIterator& operator=(const SpdyFrameIterator&) = delete; | |
414 | |
415 protected: | |
416 virtual SpdyFrameWithHeaderBlockIR* GetIR() const = 0; | |
417 virtual size_t GetFrameSizeSansBlock() const = 0; | |
418 virtual bool SerializeGivenEncoding(const SpdyString& encoding, | |
419 ZeroCopyOutputBuffer* output) const = 0; | |
420 | |
421 SpdyFramer* GetFramer() const { return framer_; } | |
422 void SetEncoder(SpdyFrameWithHeaderBlockIR* ir) { | |
423 encoder_ = | |
424 framer_->GetHpackEncoder()->EncodeHeaderSet(ir->header_block()); | |
425 } | |
426 | |
427 private: | |
428 SpdyFramer* const framer_; | |
429 std::unique_ptr<HpackEncoder::ProgressiveEncoder> encoder_; | |
430 bool is_first_frame_; | |
431 bool has_next_frame_; | |
432 | |
433 // Field for debug reporting. | |
434 size_t debug_total_size_; | |
435 }; | |
436 | |
437 // Iteratively converts a SpdyHeadersIR (with a possibly huge | |
438 // SpdyHeaderBlock) into an appropriate sequence of SpdySerializedFrames, and | |
439 // write to the output. | |
440 class NET_EXPORT_PRIVATE SpdyHeaderFrameIterator : public SpdyFrameIterator { | |
441 public: | |
442 // Does not take ownership of |framer|. Take ownership of |headers_ir|. | |
443 SpdyHeaderFrameIterator(SpdyFramer* framer, | |
444 std::unique_ptr<SpdyHeadersIR> headers_ir); | |
445 | |
446 ~SpdyHeaderFrameIterator() override; | |
447 | |
448 private: | |
449 SpdyFrameWithHeaderBlockIR* GetIR() const override; | |
450 size_t GetFrameSizeSansBlock() const override; | |
451 bool SerializeGivenEncoding(const SpdyString& encoding, | |
452 ZeroCopyOutputBuffer* output) const override; | |
453 | |
454 const std::unique_ptr<SpdyHeadersIR> headers_ir_; | |
455 }; | |
456 | |
457 // Iteratively converts a SpdyPushPromiseIR (with a possibly huge | |
458 // SpdyHeaderBlock) into an appropriate sequence of SpdySerializedFrames, and | |
459 // write to the output. | |
460 class NET_EXPORT_PRIVATE SpdyPushPromiseFrameIterator | |
461 : public SpdyFrameIterator { | |
462 public: | |
463 // Does not take ownership of |framer|. Take ownership of |push_promise_ir|. | |
464 SpdyPushPromiseFrameIterator( | |
465 SpdyFramer* framer, | |
466 std::unique_ptr<SpdyPushPromiseIR> push_promise_ir); | |
467 | |
468 ~SpdyPushPromiseFrameIterator() override; | |
469 | |
470 private: | |
471 SpdyFrameWithHeaderBlockIR* GetIR() const override; | |
472 size_t GetFrameSizeSansBlock() const override; | |
473 bool SerializeGivenEncoding(const SpdyString& encoding, | |
474 ZeroCopyOutputBuffer* output) const override; | |
475 | |
476 const std::unique_ptr<SpdyPushPromiseIR> push_promise_ir_; | |
477 }; | |
478 | |
479 // Serialize a data frame. | |
480 SpdySerializedFrame SerializeData(const SpdyDataIR& data) const; | |
481 // Serializes the data frame header and optionally padding length fields, | |
482 // excluding actual data payload and padding. | |
483 SpdySerializedFrame SerializeDataFrameHeaderWithPaddingLengthField( | |
484 const SpdyDataIR& data) const; | |
485 | |
486 SpdySerializedFrame SerializeRstStream( | |
487 const SpdyRstStreamIR& rst_stream) const; | |
488 | |
489 // Serializes a SETTINGS frame. The SETTINGS frame is | |
490 // used to communicate name/value pairs relevant to the communication channel. | |
491 SpdySerializedFrame SerializeSettings(const SpdySettingsIR& settings) const; | |
492 | |
493 // Serializes a PING frame. The unique_id is used to | |
494 // identify the ping request/response. | |
495 SpdySerializedFrame SerializePing(const SpdyPingIR& ping) const; | |
496 | |
497 // Serializes a GOAWAY frame. The GOAWAY frame is used | |
498 // prior to the shutting down of the TCP connection, and includes the | |
499 // stream_id of the last stream the sender of the frame is willing to process | |
500 // to completion. | |
501 SpdySerializedFrame SerializeGoAway(const SpdyGoAwayIR& goaway) const; | |
502 | |
503 // Serializes a HEADERS frame. The HEADERS frame is used | |
504 // for sending headers. | |
505 SpdySerializedFrame SerializeHeaders(const SpdyHeadersIR& headers); | |
506 | |
507 // Serializes a WINDOW_UPDATE frame. The WINDOW_UPDATE | |
508 // frame is used to implement per stream flow control. | |
509 SpdySerializedFrame SerializeWindowUpdate( | |
510 const SpdyWindowUpdateIR& window_update) const; | |
511 | |
512 // Serializes a PUSH_PROMISE frame. The PUSH_PROMISE frame is used | |
513 // to inform the client that it will be receiving an additional stream | |
514 // in response to the original request. The frame includes synthesized | |
515 // headers to explain the upcoming data. | |
516 SpdySerializedFrame SerializePushPromise( | |
517 const SpdyPushPromiseIR& push_promise); | |
518 | |
519 // Serializes a CONTINUATION frame. The CONTINUATION frame is used | |
520 // to continue a sequence of header block fragments. | |
521 SpdySerializedFrame SerializeContinuation( | |
522 const SpdyContinuationIR& continuation) const; | |
523 | |
524 // Serializes an ALTSVC frame. The ALTSVC frame advertises the | |
525 // availability of an alternative service to the client. | |
526 SpdySerializedFrame SerializeAltSvc(const SpdyAltSvcIR& altsvc); | |
527 | |
528 // Serializes a PRIORITY frame. The PRIORITY frame advises a change in | |
529 // the relative priority of the given stream. | |
530 SpdySerializedFrame SerializePriority(const SpdyPriorityIR& priority) const; | |
531 | |
532 // Serialize a frame of unknown type. | |
533 SpdySerializedFrame SerializeFrame(const SpdyFrameIR& frame); | |
534 | |
535 // Serialize a data frame. | |
536 bool SerializeData(const SpdyDataIR& data, | |
537 ZeroCopyOutputBuffer* output) const; | |
538 | |
539 // Serializes the data frame header and optionally padding length fields, | |
540 // excluding actual data payload and padding. | |
541 bool SerializeDataFrameHeaderWithPaddingLengthField( | |
542 const SpdyDataIR& data, | |
543 ZeroCopyOutputBuffer* output) const; | |
544 | |
545 bool SerializeRstStream(const SpdyRstStreamIR& rst_stream, | |
546 ZeroCopyOutputBuffer* output) const; | |
547 | |
548 // Serializes a SETTINGS frame. The SETTINGS frame is | |
549 // used to communicate name/value pairs relevant to the communication channel. | |
550 bool SerializeSettings(const SpdySettingsIR& settings, | |
551 ZeroCopyOutputBuffer* output) const; | |
552 | |
553 // Serializes a PING frame. The unique_id is used to | |
554 // identify the ping request/response. | |
555 bool SerializePing(const SpdyPingIR& ping, | |
556 ZeroCopyOutputBuffer* output) const; | |
557 | |
558 // Serializes a GOAWAY frame. The GOAWAY frame is used | |
559 // prior to the shutting down of the TCP connection, and includes the | |
560 // stream_id of the last stream the sender of the frame is willing to process | |
561 // to completion. | |
562 bool SerializeGoAway(const SpdyGoAwayIR& goaway, | |
563 ZeroCopyOutputBuffer* output) const; | |
564 | |
565 // Serializes a HEADERS frame. The HEADERS frame is used | |
566 // for sending headers. | |
567 bool SerializeHeaders(const SpdyHeadersIR& headers, | |
568 ZeroCopyOutputBuffer* output); | |
569 | |
570 // Serializes a WINDOW_UPDATE frame. The WINDOW_UPDATE | |
571 // frame is used to implement per stream flow control. | |
572 bool SerializeWindowUpdate(const SpdyWindowUpdateIR& window_update, | |
573 ZeroCopyOutputBuffer* output) const; | |
574 | |
575 // Serializes a PUSH_PROMISE frame. The PUSH_PROMISE frame is used | |
576 // to inform the client that it will be receiving an additional stream | |
577 // in response to the original request. The frame includes synthesized | |
578 // headers to explain the upcoming data. | |
579 bool SerializePushPromise(const SpdyPushPromiseIR& push_promise, | |
580 ZeroCopyOutputBuffer* output); | |
581 | |
582 // Serializes a CONTINUATION frame. The CONTINUATION frame is used | |
583 // to continue a sequence of header block fragments. | |
584 bool SerializeContinuation(const SpdyContinuationIR& continuation, | |
585 ZeroCopyOutputBuffer* output) const; | |
586 | |
587 // Serializes an ALTSVC frame. The ALTSVC frame advertises the | |
588 // availability of an alternative service to the client. | |
589 bool SerializeAltSvc(const SpdyAltSvcIR& altsvc, | |
590 ZeroCopyOutputBuffer* output); | |
591 | |
592 // Serializes a PRIORITY frame. The PRIORITY frame advises a change in | |
593 // the relative priority of the given stream. | |
594 bool SerializePriority(const SpdyPriorityIR& priority, | |
595 ZeroCopyOutputBuffer* output) const; | |
596 | |
597 // Serialize a frame of unknown type. | |
598 bool SerializeFrame(const SpdyFrameIR& frame, ZeroCopyOutputBuffer* output); | |
599 | |
600 // Returns whether this SpdyFramer will compress header blocks using HPACK. | |
601 bool compression_enabled() const { | |
602 return compression_option_ == ENABLE_COMPRESSION; | |
603 } | |
604 | |
605 void SetHpackIndexingPolicy(HpackEncoder::IndexingPolicy policy) { | |
606 GetHpackEncoder()->SetIndexingPolicy(std::move(policy)); | |
607 } | |
608 | |
609 // Returns the (minimum) size of frames (sans variable-length portions). | |
610 size_t GetDataFrameMinimumSize() const; | |
611 size_t GetFrameHeaderSize() const; | |
612 size_t GetRstStreamSize() const; | |
613 size_t GetSettingsMinimumSize() const; | |
614 size_t GetPingSize() const; | |
615 size_t GetGoAwayMinimumSize() const; | |
616 size_t GetHeadersMinimumSize() const; | |
617 size_t GetWindowUpdateSize() const; | |
618 size_t GetPushPromiseMinimumSize() const; | |
619 size_t GetContinuationMinimumSize() const; | |
620 size_t GetAltSvcMinimumSize() const; | |
621 size_t GetPrioritySize() const; | |
622 | |
623 // Returns the minimum size a frame can be (data or control). | |
624 size_t GetFrameMinimumSize() const; | |
625 | |
626 // Returns the maximum size a frame can be (data or control). | |
627 size_t GetFrameMaximumSize() const; | |
628 | |
629 // Returns the maximum payload size of a DATA frame. | |
630 size_t GetDataFrameMaximumPayload() const; | |
631 | |
632 // For debugging. | |
633 static const char* StateToString(int state); | |
634 static const char* SpdyFramerErrorToString(SpdyFramerError spdy_framer_error); | |
635 | |
636 // Did the most recent frame header appear to be an HTTP/1.x (or earlier) | |
637 // response (i.e. start with "HTTP/")? | |
638 bool probable_http_response() const; | |
639 | |
640 SpdyPriority GetLowestPriority() const { return kV3LowestPriority; } | |
641 | |
642 SpdyPriority GetHighestPriority() const { return kV3HighestPriority; } | |
643 | |
644 // Updates the maximum size of the header encoder compression table. | |
645 void UpdateHeaderEncoderTableSize(uint32_t value); | |
646 | |
647 // Updates the maximum size of the header decoder compression table. | |
648 void UpdateHeaderDecoderTableSize(uint32_t value); | |
649 | |
650 // Returns the maximum size of the header encoder compression table. | |
651 size_t header_encoder_table_size() const; | |
652 | |
653 void set_max_decode_buffer_size_bytes(size_t max_decode_buffer_size_bytes) { | |
654 GetHpackDecoder()->set_max_decode_buffer_size_bytes( | |
655 max_decode_buffer_size_bytes); | |
656 } | |
657 | |
658 size_t send_frame_size_limit() const { return send_frame_size_limit_; } | |
659 void set_send_frame_size_limit(size_t send_frame_size_limit) { | |
660 send_frame_size_limit_ = send_frame_size_limit; | |
661 } | |
662 | |
663 size_t recv_frame_size_limit() const { return recv_frame_size_limit_; } | |
664 void set_recv_frame_size_limit(size_t recv_frame_size_limit) { | |
665 recv_frame_size_limit_ = recv_frame_size_limit; | |
666 } | |
667 | |
668 void SetDecoderHeaderTableDebugVisitor( | |
669 std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor); | |
670 | |
671 void SetEncoderHeaderTableDebugVisitor( | |
672 std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor); | |
673 | |
674 // For use in SpdyFramerDecoderAdapter implementations; returns a HPACK | |
675 // decoder to be used. | |
676 HpackDecoderInterface* GetHpackDecoderForAdapter() { | |
677 return GetHpackDecoder(); | |
678 } | |
679 | |
680 // Returns the estimate of dynamically allocated memory in bytes. | |
681 size_t EstimateMemoryUsage() const; | |
682 | |
683 protected: | |
684 friend class BufferedSpdyFramer; | |
685 friend class HttpNetworkLayer; // This is temporary for the server. | |
686 friend class HttpNetworkTransactionTest; | |
687 friend class HttpProxyClientSocketPoolTest; | |
688 friend class SpdyHttpStreamTest; | |
689 friend class SpdyNetworkTransactionTest; | |
690 friend class SpdyProxyClientSocketTest; | |
691 friend class SpdySessionTest; | |
692 friend class SpdyStreamTest; | |
693 friend class test::TestSpdyVisitor; | |
694 friend class test::SpdyFramerPeer; | |
695 | |
696 private: | |
697 class CharBuffer { | |
698 public: | |
699 explicit CharBuffer(size_t capacity); | |
700 ~CharBuffer(); | |
701 | |
702 void CopyFrom(const char* data, size_t size); | |
703 void Rewind(); | |
704 | |
705 const char* data() const { return buffer_.get(); } | |
706 size_t len() const { return len_; } | |
707 | |
708 size_t EstimateMemoryUsage() const; | |
709 | |
710 private: | |
711 std::unique_ptr<char[]> buffer_; | |
712 size_t capacity_; | |
713 size_t len_; | |
714 }; | |
715 | |
716 // Scratch space necessary for processing SETTINGS frames. | |
717 struct SpdySettingsScratch { | |
718 SpdySettingsScratch(); | |
719 void Reset(); | |
720 size_t EstimateMemoryUsage() const; | |
721 | |
722 // Buffer contains up to one complete key/value pair. | |
723 CharBuffer buffer; | |
724 | |
725 // The ID of the last setting that was processed in the current SETTINGS | |
726 // frame. Used for detecting out-of-order or duplicate keys within a | |
727 // settings frame. Set to -1 before first key/value pair is processed. | |
728 int last_setting_id; | |
729 }; | |
730 | |
731 // Internal breakouts from ProcessInput. Each returns the number of bytes | |
732 // consumed from the data. | |
733 size_t ProcessCommonHeader(const char* data, size_t len); | |
734 size_t ProcessControlFramePayload(const char* data, size_t len); | |
735 size_t ProcessControlFrameBeforeHeaderBlock(const char* data, size_t len); | |
736 // HPACK data is re-encoded as SPDY3 and re-entrantly delivered through | |
737 // |ProcessControlFrameHeaderBlock()|. |is_hpack_header_block| controls | |
738 // whether data is treated as HPACK- vs SPDY3-encoded. | |
739 size_t ProcessControlFrameHeaderBlock(const char* data, size_t len); | |
740 size_t ProcessDataFramePaddingLength(const char* data, size_t len); | |
741 size_t ProcessFramePadding(const char* data, size_t len); | |
742 size_t ProcessDataFramePayload(const char* data, size_t len); | |
743 size_t ProcessGoAwayFramePayload(const char* data, size_t len); | |
744 size_t ProcessSettingsFrameHeader(const char* data, size_t len); | |
745 size_t ProcessSettingsFramePayload(const char* data, size_t len); | |
746 size_t ProcessAltSvcFramePayload(const char* data, size_t len); | |
747 size_t ProcessIgnoredControlFramePayload(/*const char* data,*/ size_t len); | |
748 size_t ProcessExtensionFramePayload(const char* data, size_t len); | |
749 | |
750 // Validates the frame header against the current protocol, e.g. | |
751 // Frame type must be known, must specify a non-zero stream id. | |
752 // | |
753 // is_control_frame : the control bit | |
754 // frame_type_field : the unparsed frame type octet(s) | |
755 // payload_length_field: the stated length in octets of the frame payload | |
756 // | |
757 // For valid frames, returns the correct SpdyFrameType. | |
758 // Otherwise returns a best guess at invalid frame type, | |
759 // after setting the appropriate SpdyFramerError. | |
760 SpdyFrameType ValidateFrameHeader(bool is_control_frame, | |
761 uint8_t frame_type_field, | |
762 size_t payload_length_field); | |
763 | |
764 // Helpers for above internal breakouts from ProcessInput. | |
765 void ProcessControlFrameHeader(); | |
766 // Always passed exactly 1 setting's worth of data. | |
767 bool ProcessSetting(const char* data); | |
768 | |
769 // Get (and lazily initialize) the HPACK state. | |
770 HpackEncoder* GetHpackEncoder(); | |
771 HpackDecoderInterface* GetHpackDecoder(); | |
772 | |
773 size_t GetNumberRequiredContinuationFrames(size_t size); | |
774 | |
775 bool WritePayloadWithContinuation(SpdyFrameBuilder* builder, | |
776 const SpdyString& hpack_encoding, | |
777 SpdyStreamId stream_id, | |
778 SpdyFrameType type, | |
779 int padding_payload_len); | |
780 | |
781 // Utility to copy the given data block to the current frame buffer, up | |
782 // to the given maximum number of bytes, and update the buffer | |
783 // data (pointer and length). Returns the number of bytes | |
784 // read, and: | |
785 // *data is advanced the number of bytes read. | |
786 // *len is reduced by the number of bytes read. | |
787 size_t UpdateCurrentFrameBuffer(const char** data, size_t* len, | |
788 size_t max_bytes); | |
789 | |
790 // Serializes a HEADERS frame from the given SpdyHeadersIR and encoded header | |
791 // block. Does not need or use the SpdyHeaderBlock inside SpdyHeadersIR. | |
792 // Return false if the serialization fails. |encoding| should not be empty. | |
793 bool SerializeHeadersGivenEncoding(const SpdyHeadersIR& headers, | |
794 const SpdyString& encoding, | |
795 ZeroCopyOutputBuffer* output) const; | |
796 | |
797 // Serializes a PUSH_PROMISE frame from the given SpdyPushPromiseIR and | |
798 // encoded header block. Does not need or use the SpdyHeaderBlock inside | |
799 // SpdyHeadersIR. | |
800 bool SerializePushPromiseGivenEncoding(const SpdyPushPromiseIR& push_promise, | |
801 const SpdyString& encoding, | |
802 ZeroCopyOutputBuffer* output) const; | |
803 | |
804 // Calculates the number of bytes required to serialize a SpdyHeadersIR, not | |
805 // including the bytes to be used for the encoded header set. | |
806 size_t GetHeaderFrameSizeSansBlock(const SpdyHeadersIR& header_ir) const; | |
807 | |
808 // Calculates the number of bytes required to serialize a SpdyPushPromiseIR, | |
809 // not including the bytes to be used for the encoded header set. | |
810 size_t GetPushPromiseFrameSizeSansBlock( | |
811 const SpdyPushPromiseIR& push_promise_ir) const; | |
812 | |
813 // Serializes the flags octet for a given SpdyHeadersIR. | |
814 uint8_t SerializeHeaderFrameFlags(const SpdyHeadersIR& header_ir) const; | |
815 | |
816 // Serializes the flags octet for a given SpdyPushPromiseIR. | |
817 uint8_t SerializePushPromiseFrameFlags( | |
818 const SpdyPushPromiseIR& push_promise_ir) const; | |
819 | |
820 // Set the error code and moves the framer into the error state. | |
821 void set_error(SpdyFramerError error); | |
822 | |
823 // Helper functions to prepare the input for SpdyFrameBuilder. | |
824 void SerializeDataBuilderHelper(const SpdyDataIR& data_ir, | |
825 uint8_t* flags, | |
826 int* num_padding_fields, | |
827 size_t* size_with_padding) const; | |
828 void SerializeDataFrameHeaderWithPaddingLengthFieldBuilderHelper( | |
829 const SpdyDataIR& data_ir, | |
830 uint8_t* flags, | |
831 size_t* frame_size, | |
832 size_t* num_padding_fields) const; | |
833 void SerializeSettingsBuilderHelper(const SpdySettingsIR& settings, | |
834 uint8_t* flags, | |
835 const SettingsMap* values, | |
836 size_t* size) const; | |
837 void SerializeAltSvcBuilderHelper(const SpdyAltSvcIR& altsvc_ir, | |
838 SpdyString* value, | |
839 size_t* size) const; | |
840 void SerializeHeadersBuilderHelper(const SpdyHeadersIR& headers, | |
841 uint8_t* flags, | |
842 size_t* size, | |
843 SpdyString* hpack_encoding, | |
844 int* weight, | |
845 size_t* length_field); | |
846 void SerializePushPromiseBuilderHelper(const SpdyPushPromiseIR& push_promise, | |
847 uint8_t* flags, | |
848 SpdyString* hpack_encoding, | |
849 size_t* size); | |
850 | |
851 // The size of the control frame buffer. | |
852 // Since this is only used for control frame headers, the maximum control | |
853 // frame header size is sufficient; all remaining control | |
854 // frame data is streamed to the visitor. | |
855 static const size_t kControlFrameBufferSize; | |
856 | |
857 // The maximum size of the control frames that we send, including the size of | |
858 // the header. This limit is arbitrary. We can enforce it here or at the | |
859 // application layer. We chose the framing layer, but this can be changed (or | |
860 // removed) if necessary later down the line. | |
861 // TODO(diannahu): Rename to make it clear that this limit is for sending. | |
862 static const size_t kMaxControlFrameSize; | |
863 // The maximum size for the payload of DATA frames to send. | |
864 static const size_t kMaxDataPayloadSendSize; | |
865 // The size of one parameter in SETTINGS frame. | |
866 static const size_t kOneSettingParameterSize; | |
867 | |
868 SpdyState state_; | |
869 SpdyState previous_state_; | |
870 SpdyFramerError spdy_framer_error_; | |
871 | |
872 // Note that for DATA frame, remaining_data_length_ is sum of lengths of | |
873 // frame header, padding length field (optional), data payload (optional) and | |
874 // padding payload (optional). | |
875 size_t remaining_data_length_; | |
876 | |
877 // The length (in bytes) of the padding payload to be processed. | |
878 size_t remaining_padding_payload_length_; | |
879 | |
880 // The number of bytes remaining to read from the current control frame's | |
881 // headers. Note that header data blocks (for control types that have them) | |
882 // are part of the frame's payload, and not the frame's headers. | |
883 size_t remaining_control_header_; | |
884 | |
885 // The limit on the size of sent HTTP/2 payloads as specified in the | |
886 // SETTINGS_MAX_FRAME_SIZE received from peer. | |
887 size_t send_frame_size_limit_ = kSpdyInitialFrameSizeLimit; | |
888 | |
889 // The limit on the size of received HTTP/2 payloads as specified in the | |
890 // SETTINGS_MAX_FRAME_SIZE advertised to peer. | |
891 size_t recv_frame_size_limit_ = kSpdyInitialFrameSizeLimit; | |
892 | |
893 CharBuffer current_frame_buffer_; | |
894 | |
895 // The type of the frame currently being read. | |
896 SpdyFrameType current_frame_type_; | |
897 | |
898 // The total length of the frame currently being read, including frame header. | |
899 uint32_t current_frame_length_; | |
900 | |
901 // The stream ID field of the frame currently being read, if applicable. | |
902 SpdyStreamId current_frame_stream_id_; | |
903 | |
904 // Set this to the current stream when we receive a HEADERS, PUSH_PROMISE, or | |
905 // CONTINUATION frame without the END_HEADERS(0x4) bit set. These frames must | |
906 // be followed by a CONTINUATION frame, or else we throw a PROTOCOL_ERROR. | |
907 // A value of 0 indicates that we are not expecting a CONTINUATION frame. | |
908 SpdyStreamId expect_continuation_; | |
909 | |
910 // Scratch space for handling SETTINGS frames. | |
911 // TODO(hkhalil): Unify memory for this scratch space with | |
912 // current_frame_buffer_. | |
913 SpdySettingsScratch settings_scratch_; | |
914 | |
915 std::unique_ptr<CharBuffer> altsvc_scratch_; | |
916 | |
917 std::unique_ptr<HpackEncoder> hpack_encoder_; | |
918 std::unique_ptr<HpackDecoderInterface> hpack_decoder_; | |
919 | |
920 SpdyFramerVisitorInterface* visitor_; | |
921 ExtensionVisitorInterface* extension_; | |
922 SpdyFramerDebugVisitorInterface* debug_visitor_; | |
923 | |
924 SpdyHeadersHandlerInterface* header_handler_; | |
925 | |
926 // Optional decoder to use instead of this instance. | |
927 std::unique_ptr<SpdyFramerDecoderAdapter> decoder_adapter_; | |
928 | |
929 // The flags field of the frame currently being read. | |
930 uint8_t current_frame_flags_; | |
931 | |
932 // Determines whether HPACK compression is used. | |
933 const CompressionOption compression_option_; | |
934 | |
935 // On the first read, we check to see if the data starts with HTTP. | |
936 // If it does, we likely have an HTTP response. This isn't guaranteed | |
937 // though: we could have gotten a settings frame and then corrupt data that | |
938 // just looks like HTTP, but deterministic checking requires a lot more state. | |
939 bool probable_http_response_; | |
940 | |
941 // If a HEADERS frame is followed by a CONTINUATION frame, the FIN/END_STREAM | |
942 // flag is still carried in the HEADERS frame. If it's set, flip this so that | |
943 // we know to terminate the stream when the entire header block has been | |
944 // processed. | |
945 bool end_stream_when_done_; | |
946 | |
947 // If true, then ProcessInput returns after processing a full frame, | |
948 // rather than reading all available input. | |
949 bool process_single_input_frame_ = false; | |
950 | |
951 // Latched value of FLAGS_chromium_http2_flag_remove_rewritelength. | |
952 bool skip_rewritelength_ = false; | |
953 }; | |
954 | |
955 } // namespace net | |
956 | |
957 #endif // NET_SPDY_SPDY_FRAMER_H_ | |
OLD | NEW |