Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(190)

Side by Side Diff: net/spdy/spdy_deframer_visitor.cc

Issue 2832973003: Split net/spdy into core and chromium subdirectories. (Closed)
Patch Set: Fix some more build rules. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/spdy/spdy_deframer_visitor.h ('k') | net/spdy/spdy_deframer_visitor_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 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 #include "net/spdy/spdy_deframer_visitor.h"
6
7 #include <stdlib.h>
8
9 #include <algorithm>
10 #include <cstdint>
11 #include <limits>
12
13 #include "base/logging.h"
14 #include "base/memory/ptr_util.h"
15 #include "net/spdy/hpack/hpack_constants.h"
16 #include "net/spdy/mock_spdy_framer_visitor.h"
17 #include "net/spdy/spdy_frame_builder.h"
18 #include "net/spdy/spdy_frame_reader.h"
19 #include "net/spdy/spdy_protocol.h"
20 #include "net/spdy/spdy_test_utils.h"
21
22 using ::base::MakeUnique;
23 using ::testing::AssertionFailure;
24 using ::testing::AssertionResult;
25 using ::testing::AssertionSuccess;
26
27 namespace net {
28 namespace test {
29
30 // Specify whether to process headers as request or response in visitor-related
31 // params.
32 enum class HeaderDirection { REQUEST, RESPONSE };
33
34 // Types of HTTP/2 frames, per RFC 7540.
35 // TODO(jamessynge): Switch to using //net/http2/http2_constants.h when ready.
36 enum Http2FrameType {
37 DATA = 0,
38 HEADERS = 1,
39 PRIORITY = 2,
40 RST_STREAM = 3,
41 SETTINGS = 4,
42 PUSH_PROMISE = 5,
43 PING = 6,
44 GOAWAY = 7,
45 WINDOW_UPDATE = 8,
46 CONTINUATION = 9,
47 ALTSVC = 10,
48
49 // Not a frame type.
50 UNSET = -1,
51 UNKNOWN = -2,
52 };
53
54 // TODO(jamessynge): Switch to using //net/http2/http2_constants.h when ready.
55 const char* Http2FrameTypeToString(Http2FrameType v) {
56 switch (v) {
57 case DATA:
58 return "DATA";
59 case HEADERS:
60 return "HEADERS";
61 case PRIORITY:
62 return "PRIORITY";
63 case RST_STREAM:
64 return "RST_STREAM";
65 case SETTINGS:
66 return "SETTINGS";
67 case PUSH_PROMISE:
68 return "PUSH_PROMISE";
69 case PING:
70 return "PING";
71 case GOAWAY:
72 return "GOAWAY";
73 case WINDOW_UPDATE:
74 return "WINDOW_UPDATE";
75 case CONTINUATION:
76 return "CONTINUATION";
77 case ALTSVC:
78 return "ALTSVC";
79 case UNSET:
80 return "UNSET";
81 case UNKNOWN:
82 return "UNKNOWN";
83 default:
84 return "Invalid Http2FrameType";
85 }
86 }
87
88 // TODO(jamessynge): Switch to using //net/http2/http2_constants.h when ready.
89 inline std::ostream& operator<<(std::ostream& out, Http2FrameType v) {
90 return out << Http2FrameTypeToString(v);
91 }
92
93 // Flag bits in the flag field of the common header of HTTP/2 frames
94 // (see https://httpwg.github.io/specs/rfc7540.html#FrameHeader for details on
95 // the fixed 9-octet header structure shared by all frames).
96 // Flag bits are only valid for specified frame types.
97 // TODO(jamessynge): Switch to using //net/http2/http2_constants.h when ready.
98 enum Http2HeaderFlag {
99 NO_FLAGS = 0,
100
101 END_STREAM_FLAG = 0x1,
102 ACK_FLAG = 0x1,
103 END_HEADERS_FLAG = 0x4,
104 PADDED_FLAG = 0x8,
105 PRIORITY_FLAG = 0x20,
106 };
107
108 // Returns name of frame type.
109 // TODO(jamessynge): Switch to using //net/http2/http2_constants.h when ready.
110 const char* Http2FrameTypeToString(Http2FrameType v);
111
112 void SpdyDeframerVisitorInterface::OnPingAck(
113 std::unique_ptr<SpdyPingIR> frame) {
114 OnPing(std::move(frame));
115 }
116
117 void SpdyDeframerVisitorInterface::OnSettingsAck(
118 std::unique_ptr<SpdySettingsIR> frame) {
119 OnSettings(std::move(frame), nullptr);
120 }
121
122 class SpdyTestDeframerImpl : public SpdyTestDeframer,
123 public SpdyHeadersHandlerInterface {
124 public:
125 explicit SpdyTestDeframerImpl(
126 std::unique_ptr<SpdyDeframerVisitorInterface> listener)
127 : listener_(std::move(listener)) {
128 CHECK(listener_);
129 }
130 ~SpdyTestDeframerImpl() override {}
131
132 bool AtFrameEnd() override;
133
134 // Callbacks defined in SpdyFramerVisitorInterface. These are in the
135 // alphabetical order for ease of navigation, and are not in same order
136 // as in SpdyFramerVisitorInterface.
137 void OnAltSvc(SpdyStreamId stream_id,
138 SpdyStringPiece origin,
139 const SpdyAltSvcWireFormat::AlternativeServiceVector&
140 altsvc_vector) override;
141 void OnContinuation(SpdyStreamId stream_id, bool end) override;
142 SpdyHeadersHandlerInterface* OnHeaderFrameStart(
143 SpdyStreamId stream_id) override;
144 void OnHeaderFrameEnd(SpdyStreamId stream_id, bool end_headers) override;
145 void OnDataFrameHeader(SpdyStreamId stream_id,
146 size_t length,
147 bool fin) override;
148 void OnError(SpdyFramer* framer) override;
149 void OnGoAway(SpdyStreamId last_accepted_stream_id,
150 SpdyErrorCode error_code) override;
151 bool OnGoAwayFrameData(const char* goaway_data, size_t len) override;
152 void OnHeaders(SpdyStreamId stream_id,
153 bool has_priority,
154 int weight,
155 SpdyStreamId parent_stream_id,
156 bool exclusive,
157 bool fin,
158 bool end) override;
159 void OnPing(SpdyPingId unique_id, bool is_ack) override;
160 void OnPriority(SpdyStreamId stream_id,
161 SpdyStreamId parent_stream_id,
162 int weight,
163 bool exclusive) override;
164 void OnPushPromise(SpdyStreamId stream_id,
165 SpdyStreamId promised_stream_id,
166 bool end) override;
167 void OnRstStream(SpdyStreamId stream_id, SpdyErrorCode error_code) override;
168 void OnSetting(SpdySettingsIds id, uint32_t value) override;
169 void OnSettings(bool clear_persisted) override;
170 void OnSettingsAck() override;
171 void OnSettingsEnd() override;
172 void OnStreamFrameData(SpdyStreamId stream_id,
173 const char* data,
174 size_t len) override;
175 void OnStreamEnd(SpdyStreamId stream_id) override;
176 void OnStreamPadding(SpdyStreamId stream_id, size_t len) override;
177 bool OnUnknownFrame(SpdyStreamId stream_id, uint8_t frame_type) override;
178 void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override;
179
180 // Callbacks defined in SpdyHeadersHandlerInterface.
181
182 void OnHeaderBlockStart() override;
183 void OnHeader(SpdyStringPiece key, SpdyStringPiece value) override;
184 void OnHeaderBlockEnd(size_t header_bytes_parsed) override;
185 void OnHeaderBlockEnd(size_t header_bytes_parsed,
186 size_t compressed_header_bytes_parsed) override;
187
188 protected:
189 void AtDataEnd();
190 void AtGoAwayEnd();
191 void AtHeadersEnd();
192 void AtPushPromiseEnd();
193
194 // Per-physical frame state.
195 // Frame type of the frame currently being processed.
196 Http2FrameType frame_type_ = UNSET;
197 // Stream id of the frame currently being processed.
198 SpdyStreamId stream_id_;
199 // Did the most recent frame header include the END_HEADERS flag?
200 bool end_ = false;
201 // Did the most recent frame header include the ack flag?
202 bool ack_ = false;
203
204 // Per-HPACK block state. Only valid while processing a HEADERS or
205 // PUSH_PROMISE frame, and its CONTINUATION frames.
206 // Did the most recent HEADERS or PUSH_PROMISE include the END_STREAM flag?
207 // Note that this does not necessarily indicate that the current frame is
208 // the last frame for the stream (may be followed by CONTINUATION frames,
209 // may only half close).
210 bool fin_ = false;
211 bool got_hpack_end_ = false;
212
213 std::unique_ptr<SpdyString> data_;
214
215 // Total length of the data frame.
216 size_t data_len_ = 0;
217
218 // Amount of skipped padding (i.e. total length of padding, including Pad
219 // Length field).
220 size_t padding_len_ = 0;
221
222 std::unique_ptr<SpdyString> goaway_description_;
223 std::unique_ptr<StringPairVector> headers_;
224 std::unique_ptr<SettingVector> settings_;
225 std::unique_ptr<TestHeadersHandler> headers_handler_;
226
227 std::unique_ptr<SpdyGoAwayIR> goaway_ir_;
228 std::unique_ptr<SpdyHeadersIR> headers_ir_;
229 std::unique_ptr<SpdyPushPromiseIR> push_promise_ir_;
230 std::unique_ptr<SpdySettingsIR> settings_ir_;
231
232 private:
233 std::unique_ptr<SpdyDeframerVisitorInterface> listener_;
234
235 DISALLOW_COPY_AND_ASSIGN(SpdyTestDeframerImpl);
236 };
237
238 // static
239 std::unique_ptr<SpdyTestDeframer> SpdyTestDeframer::CreateConverter(
240 std::unique_ptr<SpdyDeframerVisitorInterface> listener) {
241 return MakeUnique<SpdyTestDeframerImpl>(std::move(listener));
242 }
243
244 void SpdyTestDeframerImpl::AtDataEnd() {
245 DVLOG(1) << "AtDataEnd";
246 CHECK_EQ(data_len_, padding_len_ + data_->size());
247 auto ptr = MakeUnique<SpdyDataIR>(stream_id_, std::move(*data_));
248 CHECK_EQ(0u, data_->size());
249 data_.reset();
250
251 CHECK_LE(0u, padding_len_);
252 CHECK_LE(padding_len_, 256u);
253 if (padding_len_ > 0) {
254 ptr->set_padding_len(padding_len_);
255 }
256 padding_len_ = 0;
257
258 ptr->set_fin(fin_);
259 listener_->OnData(std::move(ptr));
260 frame_type_ = UNSET;
261 fin_ = false;
262 data_len_ = 0;
263 }
264
265 void SpdyTestDeframerImpl::AtGoAwayEnd() {
266 DVLOG(1) << "AtDataEnd";
267 CHECK_EQ(frame_type_, GOAWAY);
268 CHECK(goaway_description_);
269 if (goaway_description_->empty()) {
270 listener_->OnGoAway(std::move(goaway_ir_));
271 } else {
272 listener_->OnGoAway(MakeUnique<SpdyGoAwayIR>(
273 goaway_ir_->last_good_stream_id(), goaway_ir_->error_code(),
274 std::move(*goaway_description_)));
275 CHECK_EQ(0u, goaway_description_->size());
276 }
277 goaway_description_.reset();
278 goaway_ir_.reset();
279 frame_type_ = UNSET;
280 }
281
282 void SpdyTestDeframerImpl::AtHeadersEnd() {
283 DVLOG(1) << "AtDataEnd";
284 CHECK(frame_type_ == HEADERS || frame_type_ == CONTINUATION)
285 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
286 CHECK(end_) << " frame_type_=" << Http2FrameTypeToString(frame_type_);
287 CHECK(got_hpack_end_);
288
289 CHECK(headers_ir_);
290 CHECK(headers_);
291 CHECK(headers_handler_);
292
293 CHECK_LE(0u, padding_len_);
294 CHECK_LE(padding_len_, 256u);
295 if (padding_len_ > 0) {
296 headers_ir_->set_padding_len(padding_len_);
297 }
298 padding_len_ = 0;
299
300 headers_ir_->set_header_block(headers_handler_->decoded_block().Clone());
301 headers_handler_.reset();
302 listener_->OnHeaders(std::move(headers_ir_), std::move(headers_));
303
304 frame_type_ = UNSET;
305 fin_ = false;
306 end_ = false;
307 got_hpack_end_ = false;
308 }
309
310 void SpdyTestDeframerImpl::AtPushPromiseEnd() {
311 DVLOG(1) << "AtDataEnd";
312 CHECK(frame_type_ == PUSH_PROMISE || frame_type_ == CONTINUATION)
313 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
314 CHECK(end_) << " frame_type_=" << Http2FrameTypeToString(frame_type_);
315
316 CHECK(push_promise_ir_);
317 CHECK(headers_);
318 CHECK(headers_handler_);
319
320 CHECK_EQ(headers_ir_.get(), nullptr);
321
322 CHECK_LE(0u, padding_len_);
323 CHECK_LE(padding_len_, 256u);
324 if (padding_len_ > 0) {
325 push_promise_ir_->set_padding_len(padding_len_);
326 }
327 padding_len_ = 0;
328
329 push_promise_ir_->set_header_block(headers_handler_->decoded_block().Clone());
330 headers_handler_.reset();
331 listener_->OnPushPromise(std::move(push_promise_ir_), std::move(headers_));
332
333 frame_type_ = UNSET;
334 end_ = false;
335 }
336
337 bool SpdyTestDeframerImpl::AtFrameEnd() {
338 bool incomplete_logical_header = false;
339 // The caller says that the SpdyFrame has reached the end of the frame,
340 // so if we have any accumulated data, flush it.
341 switch (frame_type_) {
342 case DATA:
343 AtDataEnd();
344 break;
345
346 case GOAWAY:
347 AtGoAwayEnd();
348 break;
349
350 case HEADERS:
351 if (end_) {
352 AtHeadersEnd();
353 } else {
354 incomplete_logical_header = true;
355 }
356 break;
357
358 case PUSH_PROMISE:
359 if (end_) {
360 AtPushPromiseEnd();
361 } else {
362 incomplete_logical_header = true;
363 }
364 break;
365
366 case CONTINUATION:
367 if (end_) {
368 if (headers_ir_) {
369 AtHeadersEnd();
370 } else if (push_promise_ir_) {
371 AtPushPromiseEnd();
372 } else {
373 LOG(FATAL) << "Where is the SpdyFrameIR for the headers!";
374 }
375 } else {
376 incomplete_logical_header = true;
377 }
378 break;
379
380 case UNSET:
381 // Except for the frame types above, the others don't leave any record
382 // in the state of this object. Make sure nothing got left by accident.
383 CHECK_EQ(data_.get(), nullptr);
384 CHECK_EQ(goaway_description_.get(), nullptr);
385 CHECK_EQ(goaway_ir_.get(), nullptr);
386 CHECK_EQ(headers_.get(), nullptr);
387 CHECK_EQ(headers_handler_.get(), nullptr);
388 CHECK_EQ(headers_ir_.get(), nullptr);
389 CHECK_EQ(push_promise_ir_.get(), nullptr);
390 CHECK_EQ(settings_.get(), nullptr);
391 CHECK_EQ(settings_ir_.get(), nullptr);
392 break;
393
394 default:
395 SPDY_BUG << "Expected UNSET, instead frame_type_==" << frame_type_;
396 return false;
397 }
398 frame_type_ = UNSET;
399 stream_id_ = 0;
400 end_ = false;
401 ack_ = false;
402 if (!incomplete_logical_header) {
403 fin_ = false;
404 }
405 return true;
406 }
407
408 // Overridden methods from SpdyFramerVisitorInterface in alpha order...
409
410 void SpdyTestDeframerImpl::OnAltSvc(
411 SpdyStreamId stream_id,
412 SpdyStringPiece origin,
413 const SpdyAltSvcWireFormat::AlternativeServiceVector& altsvc_vector) {
414 DVLOG(1) << "OnAltSvc stream_id: " << stream_id;
415 CHECK_EQ(frame_type_, UNSET) << " frame_type_="
416 << Http2FrameTypeToString(frame_type_);
417 CHECK_GT(stream_id, 0u);
418 auto ptr = MakeUnique<SpdyAltSvcIR>(stream_id);
419 ptr->set_origin(SpdyString(origin));
420 for (auto& altsvc : altsvc_vector) {
421 ptr->add_altsvc(altsvc);
422 }
423 listener_->OnAltSvc(std::move(ptr));
424 }
425
426 // A CONTINUATION frame contains a Header Block Fragment, and immediately
427 // follows another frame that contains a Header Block Fragment (HEADERS,
428 // PUSH_PROMISE or CONTINUATION). The last such frame has the END flag set.
429 // SpdyFramer ensures that the behavior is correct before calling the visitor.
430 void SpdyTestDeframerImpl::OnContinuation(SpdyStreamId stream_id, bool end) {
431 DVLOG(1) << "OnContinuation stream_id: " << stream_id;
432 CHECK_EQ(frame_type_, UNSET) << " frame_type_="
433 << Http2FrameTypeToString(frame_type_);
434 CHECK_GT(stream_id, 0u);
435 CHECK_NE(nullptr, headers_.get());
436 frame_type_ = CONTINUATION;
437
438 stream_id_ = stream_id;
439 end_ = end;
440 }
441
442 // Note that length includes the padding length (0 to 256, when the optional
443 // padding length field is counted). Padding comes after the payload, both
444 // for DATA frames and for control frames.
445 void SpdyTestDeframerImpl::OnDataFrameHeader(SpdyStreamId stream_id,
446 size_t length,
447 bool fin) {
448 DVLOG(1) << "OnDataFrameHeader stream_id: " << stream_id;
449 CHECK_EQ(frame_type_, UNSET) << " frame_type_="
450 << Http2FrameTypeToString(frame_type_);
451 CHECK_GT(stream_id, 0u);
452 CHECK_EQ(data_.get(), nullptr);
453 frame_type_ = DATA;
454
455 stream_id_ = stream_id;
456 fin_ = fin;
457 data_len_ = length;
458 data_.reset(new SpdyString());
459 }
460
461 // The SpdyFramer will not process any more data at this point.
462 void SpdyTestDeframerImpl::OnError(SpdyFramer* framer) {
463 DVLOG(1) << "SpdyFramer detected an error in the stream: "
464 << SpdyFramer::SpdyFramerErrorToString(framer->spdy_framer_error())
465 << " frame_type_: " << Http2FrameTypeToString(frame_type_);
466 listener_->OnError(framer, this);
467 }
468
469 // Received a GOAWAY frame from the peer. The last stream id it accepted from us
470 // is |last_accepted_stream_id|. |status| is a protocol defined error code.
471 // The frame may also contain data. After this OnGoAwayFrameData will be called
472 // for any non-zero amount of data, and after that it will be called with len==0
473 // to indicate the end of the GOAWAY frame.
474 void SpdyTestDeframerImpl::OnGoAway(SpdyStreamId last_good_stream_id,
475 SpdyErrorCode error_code) {
476 DVLOG(1) << "OnGoAway last_good_stream_id: " << last_good_stream_id
477 << " error code: " << error_code;
478 CHECK_EQ(frame_type_, UNSET) << " frame_type_="
479 << Http2FrameTypeToString(frame_type_);
480 frame_type_ = GOAWAY;
481 goaway_ir_ = MakeUnique<SpdyGoAwayIR>(last_good_stream_id, error_code, "");
482 goaway_description_.reset(new SpdyString());
483 }
484
485 // If len==0 then we've reached the end of the GOAWAY frame.
486 bool SpdyTestDeframerImpl::OnGoAwayFrameData(const char* goaway_data,
487 size_t len) {
488 DVLOG(1) << "OnGoAwayFrameData";
489 CHECK_EQ(frame_type_, GOAWAY) << " frame_type_="
490 << Http2FrameTypeToString(frame_type_);
491 CHECK(goaway_description_);
492 goaway_description_->append(goaway_data, len);
493 return true;
494 }
495
496 SpdyHeadersHandlerInterface* SpdyTestDeframerImpl::OnHeaderFrameStart(
497 SpdyStreamId stream_id) {
498 return this;
499 }
500
501 void SpdyTestDeframerImpl::OnHeaderFrameEnd(SpdyStreamId stream_id,
502 bool end_headers) {
503 DVLOG(1) << "OnHeaderFrameEnd stream_id: " << stream_id
504 << " end_headers: " << (end_headers ? "true" : "false");
505 }
506
507 // Received the fixed portion of a HEADERS frame. Called before the variable
508 // length (including zero length) Header Block Fragment is processed. If fin
509 // is true then there will be no DATA or trailing HEADERS after this HEADERS
510 // frame.
511 // If end is true, then there will be no CONTINUATION frame(s) following this
512 // frame; else if true then there will be CONTINATION frames(s) immediately
513 // following this frame, terminated by a CONTINUATION frame with end==true.
514 void SpdyTestDeframerImpl::OnHeaders(SpdyStreamId stream_id,
515 bool has_priority,
516 int weight,
517 SpdyStreamId parent_stream_id,
518 bool exclusive,
519 bool fin,
520 bool end) {
521 DVLOG(1) << "OnHeaders stream_id: " << stream_id;
522 CHECK_EQ(frame_type_, UNSET) << " frame_type_="
523 << Http2FrameTypeToString(frame_type_);
524 CHECK_GT(stream_id, 0u);
525 frame_type_ = HEADERS;
526
527 stream_id_ = stream_id;
528 fin_ = fin;
529 end_ = end;
530
531 headers_.reset(new StringPairVector());
532 headers_handler_.reset(new TestHeadersHandler());
533 headers_ir_ = MakeUnique<SpdyHeadersIR>(stream_id);
534 headers_ir_->set_fin(fin);
535 if (has_priority) {
536 headers_ir_->set_has_priority(true);
537 headers_ir_->set_weight(weight);
538 headers_ir_->set_parent_stream_id(parent_stream_id);
539 headers_ir_->set_exclusive(exclusive);
540 }
541 }
542
543 // The HTTP/2 protocol refers to the payload, |unique_id| here, as 8 octets of
544 // opaque data that is to be echoed back to the sender, with the ACK bit added.
545 // It isn't defined as a counter,
546 // or frame id, as the SpdyPingId naming might imply.
547 // Responding to a PING is supposed to be at the highest priority.
548 void SpdyTestDeframerImpl::OnPing(uint64_t unique_id, bool is_ack) {
549 DVLOG(1) << "OnPing unique_id: " << unique_id
550 << " is_ack: " << (is_ack ? "true" : "false");
551 CHECK_EQ(frame_type_, UNSET) << " frame_type_="
552 << Http2FrameTypeToString(frame_type_);
553 auto ptr = MakeUnique<SpdyPingIR>(unique_id);
554 if (is_ack) {
555 ptr->set_is_ack(is_ack);
556 listener_->OnPingAck(std::move(ptr));
557 } else {
558 listener_->OnPing(std::move(ptr));
559 }
560 }
561
562 void SpdyTestDeframerImpl::OnPriority(SpdyStreamId stream_id,
563 SpdyStreamId parent_stream_id,
564 int weight,
565 bool exclusive) {
566 DVLOG(1) << "OnPriority stream_id: " << stream_id;
567 CHECK_EQ(frame_type_, UNSET) << " frame_type_="
568 << Http2FrameTypeToString(frame_type_);
569 CHECK_GT(stream_id, 0u);
570
571 listener_->OnPriority(MakeUnique<SpdyPriorityIR>(stream_id, parent_stream_id,
572 weight, exclusive));
573 }
574
575 void SpdyTestDeframerImpl::OnPushPromise(SpdyStreamId stream_id,
576 SpdyStreamId promised_stream_id,
577 bool end) {
578 DVLOG(1) << "OnPushPromise stream_id: " << stream_id;
579 CHECK_EQ(frame_type_, UNSET) << " frame_type_="
580 << Http2FrameTypeToString(frame_type_);
581 CHECK_GT(stream_id, 0u);
582
583 frame_type_ = PUSH_PROMISE;
584 stream_id_ = stream_id;
585 end_ = end;
586
587 headers_.reset(new StringPairVector());
588 headers_handler_.reset(new TestHeadersHandler());
589 push_promise_ir_ =
590 MakeUnique<SpdyPushPromiseIR>(stream_id, promised_stream_id);
591 }
592
593 // Closes the specified stream. After this the sender may still send PRIORITY
594 // frames for this stream, which we can ignore.
595 void SpdyTestDeframerImpl::OnRstStream(SpdyStreamId stream_id,
596 SpdyErrorCode error_code) {
597 DVLOG(1) << "OnRstStream stream_id: " << stream_id
598 << " error code: " << error_code;
599 CHECK_EQ(frame_type_, UNSET) << " frame_type_="
600 << Http2FrameTypeToString(frame_type_);
601 CHECK_GT(stream_id, 0u);
602
603 listener_->OnRstStream(MakeUnique<SpdyRstStreamIR>(stream_id, error_code));
604 }
605
606 // Called for an individual setting. There is no negotiation, the sender is
607 // stating the value that the sender is using.
608 void SpdyTestDeframerImpl::OnSetting(SpdySettingsIds id, uint32_t value) {
609 DVLOG(1) << "OnSetting id: " << id << std::hex << " value: " << value;
610 CHECK_EQ(frame_type_, SETTINGS) << " frame_type_="
611 << Http2FrameTypeToString(frame_type_);
612 CHECK(settings_);
613 settings_->push_back(std::make_pair(id, value));
614 settings_ir_->AddSetting(id, value);
615 }
616
617 // Called at the start of a SETTINGS frame with setting entries, but not the
618 // (required) ACK of a SETTINGS frame. There is no stream_id because
619 // the settings apply to the entire connection, not to an individual stream.
620 // The |clear_persisted| flag is a pre-HTTP/2 remnant.
621 void SpdyTestDeframerImpl::OnSettings(bool /*clear_persisted*/) {
622 DVLOG(1) << "OnSettings";
623 CHECK_EQ(frame_type_, UNSET) << " frame_type_="
624 << Http2FrameTypeToString(frame_type_);
625 CHECK_EQ(nullptr, settings_ir_.get());
626 CHECK_EQ(nullptr, settings_.get());
627 frame_type_ = SETTINGS;
628 ack_ = false;
629
630 settings_.reset(new SettingVector());
631 settings_ir_.reset(new SpdySettingsIR());
632 }
633
634 void SpdyTestDeframerImpl::OnSettingsAck() {
635 DVLOG(1) << "OnSettingsAck";
636 CHECK_EQ(frame_type_, UNSET) << " frame_type_="
637 << Http2FrameTypeToString(frame_type_);
638 auto ptr = MakeUnique<SpdySettingsIR>();
639 ptr->set_is_ack(true);
640 listener_->OnSettingsAck(std::move(ptr));
641 }
642
643 void SpdyTestDeframerImpl::OnSettingsEnd() {
644 DVLOG(1) << "OnSettingsEnd";
645 CHECK_EQ(frame_type_, SETTINGS) << " frame_type_="
646 << Http2FrameTypeToString(frame_type_);
647 CHECK(!ack_);
648 CHECK_NE(nullptr, settings_ir_.get());
649 CHECK_NE(nullptr, settings_.get());
650 listener_->OnSettings(std::move(settings_ir_), std::move(settings_));
651 frame_type_ = UNSET;
652 }
653
654 // Called for a zero length DATA frame with the END_STREAM flag set, or at the
655 // end a complete HPACK block (and its padding) that started with a HEADERS
656 // frame with the END_STREAM flag set. Doesn't apply to PUSH_PROMISE frames
657 // because they don't have END_STREAM flags.
658 void SpdyTestDeframerImpl::OnStreamEnd(SpdyStreamId stream_id) {
659 DVLOG(1) << "OnStreamEnd stream_id: " << stream_id;
660 CHECK_EQ(stream_id_, stream_id);
661 CHECK(frame_type_ == DATA || frame_type_ == HEADERS ||
662 frame_type_ == CONTINUATION)
663 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
664 CHECK(fin_);
665 }
666
667 // The data arg points into the non-padding payload of a DATA frame.
668 // This must be a DATA frame (i.e. this method will not be
669 // called for HEADERS or CONTINUATION frames).
670 // This method may be called multiple times for a single DATA frame, depending
671 // upon buffer boundaries.
672 void SpdyTestDeframerImpl::OnStreamFrameData(SpdyStreamId stream_id,
673 const char* data,
674 size_t len) {
675 DVLOG(1) << "OnStreamFrameData stream_id: " << stream_id
676 << " len: " << len;
677 CHECK_EQ(stream_id_, stream_id);
678 CHECK_EQ(frame_type_, DATA);
679 data_->append(data, len);
680 }
681
682 // Called when padding is skipped over, including the padding length field at
683 // the start of the frame payload, and the actual padding at the end. len will
684 // be in the range 1 to 255.
685 void SpdyTestDeframerImpl::OnStreamPadding(SpdyStreamId stream_id, size_t len) {
686 DVLOG(1) << "OnStreamPadding stream_id: " << stream_id << " len: " << len;
687 CHECK(frame_type_ == DATA || frame_type_ == HEADERS ||
688 frame_type_ == PUSH_PROMISE)
689 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
690 CHECK_EQ(stream_id_, stream_id);
691 CHECK_LE(1u, len);
692 CHECK_GE(255u, len);
693 padding_len_ += len;
694 CHECK_LE(padding_len_, 256u) << "len=" << len;
695 }
696
697 // WINDOW_UPDATE is supposed to be hop-by-hop, according to the spec.
698 // stream_id is 0 if the update applies to the connection, else stream_id
699 // will be the id of a stream previously seen, which maybe half or fully
700 // closed.
701 void SpdyTestDeframerImpl::OnWindowUpdate(SpdyStreamId stream_id,
702 int delta_window_size) {
703 DVLOG(1) << "OnWindowUpdate stream_id: " << stream_id
704 << " delta_window_size: " << delta_window_size;
705 CHECK_EQ(frame_type_, UNSET) << " frame_type_="
706 << Http2FrameTypeToString(frame_type_);
707 CHECK_NE(0, delta_window_size);
708
709 listener_->OnWindowUpdate(
710 MakeUnique<SpdyWindowUpdateIR>(stream_id, delta_window_size));
711 }
712
713 // Return true to indicate that the stream_id is valid; if not valid then
714 // SpdyFramer considers the connection corrupted. Requires keeping track
715 // of the set of currently open streams. For now we'll assume that unknown
716 // frame types are unsupported.
717 bool SpdyTestDeframerImpl::OnUnknownFrame(SpdyStreamId stream_id,
718 uint8_t frame_type) {
719 DVLOG(1) << "OnAltSvc stream_id: " << stream_id;
720 CHECK_EQ(frame_type_, UNSET) << " frame_type_="
721 << Http2FrameTypeToString(frame_type_);
722 frame_type_ = UNKNOWN;
723
724 stream_id_ = stream_id;
725 return false;
726 }
727
728 // Callbacks defined in SpdyHeadersHandlerInterface.
729
730 void SpdyTestDeframerImpl::OnHeaderBlockStart() {
731 CHECK(frame_type_ == HEADERS || frame_type_ == PUSH_PROMISE)
732 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
733 CHECK(headers_);
734 CHECK_EQ(0u, headers_->size());
735 got_hpack_end_ = false;
736 }
737
738 void SpdyTestDeframerImpl::OnHeader(SpdyStringPiece key,
739 SpdyStringPiece value) {
740 CHECK(frame_type_ == HEADERS || frame_type_ == CONTINUATION ||
741 frame_type_ == PUSH_PROMISE)
742 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
743 CHECK(!got_hpack_end_);
744 CHECK(headers_);
745 headers_->emplace_back(SpdyString(key), SpdyString(value));
746 CHECK(headers_handler_);
747 headers_handler_->OnHeader(key, value);
748 }
749
750 void SpdyTestDeframerImpl::OnHeaderBlockEnd(size_t header_bytes_parsed) {
751 CHECK(headers_);
752 CHECK(frame_type_ == HEADERS || frame_type_ == CONTINUATION ||
753 frame_type_ == PUSH_PROMISE)
754 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
755 CHECK(end_);
756 CHECK(!got_hpack_end_);
757 got_hpack_end_ = true;
758 }
759
760 void SpdyTestDeframerImpl::OnHeaderBlockEnd(
761 size_t /* header_bytes_parsed */,
762 size_t /* compressed_header_bytes_parsed */) {
763 CHECK(headers_);
764 CHECK(frame_type_ == HEADERS || frame_type_ == CONTINUATION ||
765 frame_type_ == PUSH_PROMISE)
766 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
767 CHECK(end_);
768 CHECK(!got_hpack_end_);
769 got_hpack_end_ = true;
770 }
771
772 class LoggingSpdyDeframerDelegate : public SpdyDeframerVisitorInterface {
773 public:
774 explicit LoggingSpdyDeframerDelegate(
775 std::unique_ptr<SpdyDeframerVisitorInterface> wrapped)
776 : wrapped_(std::move(wrapped)) {
777 if (!wrapped_) {
778 wrapped_ = MakeUnique<SpdyDeframerVisitorInterface>();
779 }
780 }
781 ~LoggingSpdyDeframerDelegate() override {}
782
783 void OnAltSvc(std::unique_ptr<SpdyAltSvcIR> frame) override {
784 DVLOG(1) << "LoggingSpdyDeframerDelegate::OnAltSvc";
785 wrapped_->OnAltSvc(std::move(frame));
786 }
787 void OnData(std::unique_ptr<SpdyDataIR> frame) override {
788 DVLOG(1) << "LoggingSpdyDeframerDelegate::OnData";
789 wrapped_->OnData(std::move(frame));
790 }
791 void OnGoAway(std::unique_ptr<SpdyGoAwayIR> frame) override {
792 DVLOG(1) << "LoggingSpdyDeframerDelegate::OnGoAway";
793 wrapped_->OnGoAway(std::move(frame));
794 }
795
796 // SpdyHeadersIR and SpdyPushPromiseIR each has a SpdyHeaderBlock which
797 // significantly modifies the headers, so the actual header entries (name
798 // and value strings) are provided in a vector.
799 void OnHeaders(std::unique_ptr<SpdyHeadersIR> frame,
800 std::unique_ptr<StringPairVector> headers) override {
801 DVLOG(1) << "LoggingSpdyDeframerDelegate::OnHeaders";
802 wrapped_->OnHeaders(std::move(frame), std::move(headers));
803 }
804
805 void OnPing(std::unique_ptr<SpdyPingIR> frame) override {
806 DVLOG(1) << "LoggingSpdyDeframerDelegate::OnPing";
807 wrapped_->OnPing(std::move(frame));
808 }
809 void OnPingAck(std::unique_ptr<SpdyPingIR> frame) override {
810 DVLOG(1) << "LoggingSpdyDeframerDelegate::OnPingAck";
811 wrapped_->OnPingAck(std::move(frame));
812 }
813
814 void OnPriority(std::unique_ptr<SpdyPriorityIR> frame) override {
815 DVLOG(1) << "LoggingSpdyDeframerDelegate::OnPriority";
816 wrapped_->OnPriority(std::move(frame));
817 }
818
819 // SpdyHeadersIR and SpdyPushPromiseIR each has a SpdyHeaderBlock which
820 // significantly modifies the headers, so the actual header entries (name
821 // and value strings) are provided in a vector.
822 void OnPushPromise(std::unique_ptr<SpdyPushPromiseIR> frame,
823 std::unique_ptr<StringPairVector> headers) override {
824 DVLOG(1) << "LoggingSpdyDeframerDelegate::OnPushPromise";
825 wrapped_->OnPushPromise(std::move(frame), std::move(headers));
826 }
827
828 void OnRstStream(std::unique_ptr<SpdyRstStreamIR> frame) override {
829 DVLOG(1) << "LoggingSpdyDeframerDelegate::OnRstStream";
830 wrapped_->OnRstStream(std::move(frame));
831 }
832
833 // SpdySettingsIR has a map for settings, so loses info about the order of
834 // settings, and whether the same setting appeared more than once, so the
835 // the actual settings (parameter and value) are provided in a vector.
836 void OnSettings(std::unique_ptr<SpdySettingsIR> frame,
837 std::unique_ptr<SettingVector> settings) override {
838 DVLOG(1) << "LoggingSpdyDeframerDelegate::OnSettings";
839 wrapped_->OnSettings(std::move(frame), std::move(settings));
840 }
841
842 // A settings frame with an ACK has no content, but for uniformity passing
843 // a frame with the ACK flag set.
844 void OnSettingsAck(std::unique_ptr<SpdySettingsIR> frame) override {
845 DVLOG(1) << "LoggingSpdyDeframerDelegate::OnSettingsAck";
846 wrapped_->OnSettingsAck(std::move(frame));
847 }
848
849 void OnWindowUpdate(std::unique_ptr<SpdyWindowUpdateIR> frame) override {
850 DVLOG(1) << "LoggingSpdyDeframerDelegate::OnWindowUpdate";
851 wrapped_->OnWindowUpdate(std::move(frame));
852 }
853
854 // The SpdyFramer will not process any more data at this point.
855 void OnError(SpdyFramer* framer, SpdyTestDeframer* deframer) override {
856 DVLOG(1) << "LoggingSpdyDeframerDelegate::OnError";
857 wrapped_->OnError(framer, deframer);
858 }
859
860 private:
861 std::unique_ptr<SpdyDeframerVisitorInterface> wrapped_;
862 };
863
864 // static
865 std::unique_ptr<SpdyDeframerVisitorInterface>
866 SpdyDeframerVisitorInterface::LogBeforeVisiting(
867 std::unique_ptr<SpdyDeframerVisitorInterface> wrapped_listener) {
868 return MakeUnique<LoggingSpdyDeframerDelegate>(std::move(wrapped_listener));
869 }
870
871 CollectedFrame::CollectedFrame() {}
872
873 CollectedFrame::CollectedFrame(CollectedFrame&& other)
874 : frame_ir(std::move(other.frame_ir)),
875 headers(std::move(other.headers)),
876 settings(std::move(other.settings)),
877 error_reported(other.error_reported) {}
878
879 CollectedFrame::~CollectedFrame() {}
880
881 CollectedFrame& CollectedFrame::operator=(CollectedFrame&& other) {
882 frame_ir = std::move(other.frame_ir);
883 headers = std::move(other.headers);
884 settings = std::move(other.settings);
885 error_reported = other.error_reported;
886 return *this;
887 }
888
889 AssertionResult CollectedFrame::VerifyHasHeaders(
890 const StringPairVector& expected_headers) const {
891 if (headers.get() == nullptr)
892 return AssertionFailure();
893 if (*headers != expected_headers)
894 return AssertionFailure();
895
896 return AssertionSuccess();
897 }
898
899 AssertionResult CollectedFrame::VerifyHasSettings(
900 const SettingVector& expected_settings) const {
901 if (settings.get() == nullptr)
902 return AssertionFailure();
903 if (*settings != expected_settings)
904 return AssertionFailure();
905
906 return AssertionSuccess();
907 }
908
909 DeframerCallbackCollector::DeframerCallbackCollector(
910 std::vector<CollectedFrame>* collected_frames)
911 : collected_frames_(collected_frames) {
912 CHECK(collected_frames);
913 }
914
915 void DeframerCallbackCollector::OnAltSvc(
916 std::unique_ptr<SpdyAltSvcIR> frame_ir) {
917 CollectedFrame cf;
918 cf.frame_ir = std::move(frame_ir);
919 collected_frames_->push_back(std::move(cf));
920 }
921 void DeframerCallbackCollector::OnData(std::unique_ptr<SpdyDataIR> frame_ir) {
922 CollectedFrame cf;
923 cf.frame_ir = std::move(frame_ir);
924 collected_frames_->push_back(std::move(cf));
925 }
926 void DeframerCallbackCollector::OnGoAway(
927 std::unique_ptr<SpdyGoAwayIR> frame_ir) {
928 CollectedFrame cf;
929 cf.frame_ir = std::move(frame_ir);
930 collected_frames_->push_back(std::move(cf));
931 }
932
933 // SpdyHeadersIR and SpdyPushPromiseIR each has a SpdyHeaderBlock which
934 // significantly modifies the headers, so the actual header entries (name
935 // and value strings) are provided in a vector.
936 void DeframerCallbackCollector::OnHeaders(
937 std::unique_ptr<SpdyHeadersIR> frame_ir,
938 std::unique_ptr<StringPairVector> headers) {
939 CollectedFrame cf;
940 cf.frame_ir = std::move(frame_ir);
941 cf.headers = std::move(headers);
942 collected_frames_->push_back(std::move(cf));
943 }
944
945 void DeframerCallbackCollector::OnPing(std::unique_ptr<SpdyPingIR> frame_ir) {
946 EXPECT_TRUE(frame_ir && !frame_ir->is_ack());
947 CollectedFrame cf;
948 cf.frame_ir = std::move(frame_ir);
949 collected_frames_->push_back(std::move(cf));
950 }
951
952 void DeframerCallbackCollector::OnPingAck(
953 std::unique_ptr<SpdyPingIR> frame_ir) {
954 EXPECT_TRUE(frame_ir && frame_ir->is_ack());
955 CollectedFrame cf;
956 cf.frame_ir = std::move(frame_ir);
957 collected_frames_->push_back(std::move(cf));
958 }
959
960 void DeframerCallbackCollector::OnPriority(
961 std::unique_ptr<SpdyPriorityIR> frame_ir) {
962 CollectedFrame cf;
963 cf.frame_ir = std::move(frame_ir);
964 collected_frames_->push_back(std::move(cf));
965 }
966
967 // SpdyHeadersIR and SpdyPushPromiseIR each has a SpdyHeaderBlock which
968 // significantly modifies the headers, so the actual header entries (name
969 // and value strings) are provided in a vector.
970 void DeframerCallbackCollector::OnPushPromise(
971 std::unique_ptr<SpdyPushPromiseIR> frame_ir,
972 std::unique_ptr<StringPairVector> headers) {
973 CollectedFrame cf;
974 cf.frame_ir = std::move(frame_ir);
975 cf.headers = std::move(headers);
976 collected_frames_->push_back(std::move(cf));
977 }
978
979 void DeframerCallbackCollector::OnRstStream(
980 std::unique_ptr<SpdyRstStreamIR> frame_ir) {
981 CollectedFrame cf;
982 cf.frame_ir = std::move(frame_ir);
983 collected_frames_->push_back(std::move(cf));
984 }
985
986 // SpdySettingsIR has a map for settings, so loses info about the order of
987 // settings, and whether the same setting appeared more than once, so the
988 // the actual settings (parameter and value) are provided in a vector.
989 void DeframerCallbackCollector::OnSettings(
990 std::unique_ptr<SpdySettingsIR> frame_ir,
991 std::unique_ptr<SettingVector> settings) {
992 EXPECT_TRUE(frame_ir && !frame_ir->is_ack());
993 CollectedFrame cf;
994 cf.frame_ir = std::move(frame_ir);
995 cf.settings = std::move(settings);
996 collected_frames_->push_back(std::move(cf));
997 }
998
999 // A settings frame_ir with an ACK has no content, but for uniformity passing
1000 // a frame_ir with the ACK flag set.
1001 void DeframerCallbackCollector::OnSettingsAck(
1002 std::unique_ptr<SpdySettingsIR> frame_ir) {
1003 EXPECT_TRUE(frame_ir && frame_ir->is_ack());
1004 CollectedFrame cf;
1005 cf.frame_ir = std::move(frame_ir);
1006 collected_frames_->push_back(std::move(cf));
1007 }
1008
1009 void DeframerCallbackCollector::OnWindowUpdate(
1010 std::unique_ptr<SpdyWindowUpdateIR> frame_ir) {
1011 CollectedFrame cf;
1012 cf.frame_ir = std::move(frame_ir);
1013 collected_frames_->push_back(std::move(cf));
1014 }
1015
1016 // The SpdyFramer will not process any more data at this point.
1017 void DeframerCallbackCollector::OnError(SpdyFramer* framer,
1018 SpdyTestDeframer* deframer) {
1019 CollectedFrame cf;
1020 cf.error_reported = true;
1021 collected_frames_->push_back(std::move(cf));
1022 }
1023
1024 } // namespace test
1025 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/spdy_deframer_visitor.h ('k') | net/spdy/spdy_deframer_visitor_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698