Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / net / spdy / spdy_protocol.cc
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 #include "net/spdy/spdy_protocol.h"
6
7 namespace net {
8
9 SpdyFrameWithNameValueBlockIR::SpdyFrameWithNameValueBlockIR(
10     SpdyStreamId stream_id) : SpdyFrameWithFinIR(stream_id) {}
11
12 SpdyFrameWithNameValueBlockIR::~SpdyFrameWithNameValueBlockIR() {}
13
14 SpdyDataIR::SpdyDataIR(SpdyStreamId stream_id, const base::StringPiece& data)
15     : SpdyFrameWithFinIR(stream_id),
16       pad_low_(false),
17       pad_high_(false),
18       padding_payload_len_(0) {
19   SetDataDeep(data);
20 }
21
22 SpdyDataIR::SpdyDataIR(SpdyStreamId stream_id)
23     : SpdyFrameWithFinIR(stream_id),
24       pad_low_(false),
25       pad_high_(false),
26       padding_payload_len_(0) {}
27
28 SpdyDataIR::~SpdyDataIR() {}
29
30 bool SpdyConstants::IsValidFrameType(SpdyMajorVersion version,
31                                      int frame_type_field) {
32   switch (version) {
33     case SPDY2:
34     case SPDY3:
35       // SYN_STREAM is the first valid frame.
36       if (frame_type_field < SerializeFrameType(version, SYN_STREAM)) {
37         return false;
38       }
39
40       // WINDOW_UPDATE is the last valid frame.
41       if (frame_type_field > SerializeFrameType(version, WINDOW_UPDATE)) {
42         return false;
43       }
44
45       // The valid range is non-contiguous.
46       if (frame_type_field == NOOP) {
47         return false;
48       }
49
50       return true;
51     case SPDY4:
52     case SPDY5:
53       // DATA is the first valid frame.
54       if (frame_type_field < SerializeFrameType(version, DATA)) {
55         return false;
56       }
57
58       // BLOCKED is the last valid frame.
59       if (frame_type_field > SerializeFrameType(version, BLOCKED)) {
60         return false;
61       }
62
63       return true;
64   }
65
66   LOG(DFATAL) << "Unhandled SPDY version " << version;
67   return false;
68 }
69
70 SpdyFrameType SpdyConstants::ParseFrameType(SpdyMajorVersion version,
71                                             int frame_type_field) {
72   switch (version) {
73     case SPDY2:
74     case SPDY3:
75       switch (frame_type_field) {
76         case 1:
77           return SYN_STREAM;
78         case 2:
79           return SYN_REPLY;
80         case 3:
81           return RST_STREAM;
82         case 4:
83           return SETTINGS;
84         case 6:
85           return PING;
86         case 7:
87           return GOAWAY;
88         case 8:
89           return HEADERS;
90         case 9:
91           return WINDOW_UPDATE;
92       }
93       break;
94     case SPDY4:
95     case SPDY5:
96       switch (frame_type_field) {
97         case 0:
98           return DATA;
99         case 1:
100           return HEADERS;
101         // TODO(hkhalil): Add PRIORITY.
102         case 3:
103           return RST_STREAM;
104         case 4:
105           return SETTINGS;
106         case 5:
107           return PUSH_PROMISE;
108         case 6:
109           return PING;
110         case 7:
111           return GOAWAY;
112         case 8:
113           return WINDOW_UPDATE;
114         case 9:
115           return CONTINUATION;
116         case 10:
117           return BLOCKED;
118       }
119       break;
120   }
121
122   LOG(DFATAL) << "Unhandled frame type " << frame_type_field;
123   return DATA;
124 }
125
126 int SpdyConstants::SerializeFrameType(SpdyMajorVersion version,
127                                       SpdyFrameType frame_type) {
128   switch (version) {
129     case SPDY2:
130     case SPDY3:
131       switch (frame_type) {
132         case SYN_STREAM:
133           return 1;
134         case SYN_REPLY:
135           return 2;
136         case RST_STREAM:
137           return 3;
138         case SETTINGS:
139           return 4;
140         case PING:
141           return 6;
142         case GOAWAY:
143           return 7;
144         case HEADERS:
145           return 8;
146         case WINDOW_UPDATE:
147           return 9;
148         default:
149           LOG(DFATAL) << "Serializing unhandled frame type " << frame_type;
150           return -1;
151       }
152     case SPDY4:
153     case SPDY5:
154       switch (frame_type) {
155         case DATA:
156           return 0;
157         case HEADERS:
158           return 1;
159         // TODO(hkhalil): Add PRIORITY.
160         case RST_STREAM:
161           return 3;
162         case SETTINGS:
163           return 4;
164         case PUSH_PROMISE:
165           return 5;
166         case PING:
167           return 6;
168         case GOAWAY:
169           return 7;
170         case WINDOW_UPDATE:
171           return 8;
172         case CONTINUATION:
173           return 9;
174         case BLOCKED:
175           return 10;
176         default:
177           LOG(DFATAL) << "Serializing unhandled frame type " << frame_type;
178           return -1;
179       }
180   }
181
182   LOG(DFATAL) << "Unhandled SPDY version " << version;
183   return -1;
184 }
185
186 bool SpdyConstants::IsValidSettingId(SpdyMajorVersion version,
187                                      int setting_id_field) {
188   switch (version) {
189     case SPDY2:
190     case SPDY3:
191       // UPLOAD_BANDWIDTH is the first valid setting id.
192       if (setting_id_field <
193           SerializeSettingId(version, SETTINGS_UPLOAD_BANDWIDTH)) {
194         return false;
195       }
196
197       // INITIAL_WINDOW_SIZE is the last valid setting id.
198       if (setting_id_field >
199           SerializeSettingId(version, SETTINGS_INITIAL_WINDOW_SIZE)) {
200         return false;
201       }
202
203       return true;
204     case SPDY4:
205     case SPDY5:
206       // HEADER_TABLE_SIZE is the first valid setting id.
207       if (setting_id_field <
208           SerializeSettingId(version, SETTINGS_HEADER_TABLE_SIZE)) {
209         return false;
210       }
211
212       // INITIAL_WINDOW_SIZE is the last valid setting id.
213       if (setting_id_field >
214           SerializeSettingId(version, SETTINGS_INITIAL_WINDOW_SIZE)) {
215         return false;
216       }
217
218       return true;
219   }
220
221   LOG(DFATAL) << "Unhandled SPDY version " << version;
222   return false;
223 }
224
225 SpdySettingsIds SpdyConstants::ParseSettingId(SpdyMajorVersion version,
226                                               int setting_id_field) {
227   switch (version) {
228     case SPDY2:
229     case SPDY3:
230       switch (setting_id_field) {
231         case 1:
232           return SETTINGS_UPLOAD_BANDWIDTH;
233         case 2:
234           return SETTINGS_DOWNLOAD_BANDWIDTH;
235         case 3:
236           return SETTINGS_ROUND_TRIP_TIME;
237         case 4:
238           return SETTINGS_MAX_CONCURRENT_STREAMS;
239         case 5:
240           return SETTINGS_CURRENT_CWND;
241         case 6:
242           return SETTINGS_DOWNLOAD_RETRANS_RATE;
243         case 7:
244           return SETTINGS_INITIAL_WINDOW_SIZE;
245       }
246       break;
247     case SPDY4:
248     case SPDY5:
249       switch (setting_id_field) {
250         case 1:
251           return SETTINGS_HEADER_TABLE_SIZE;
252         case 2:
253           return SETTINGS_ENABLE_PUSH;
254         case 3:
255           return SETTINGS_MAX_CONCURRENT_STREAMS;
256         case 4:
257           return SETTINGS_INITIAL_WINDOW_SIZE;
258       }
259       break;
260   }
261
262   LOG(DFATAL) << "Unhandled setting ID " << setting_id_field;
263   return SETTINGS_UPLOAD_BANDWIDTH;
264 }
265
266 int SpdyConstants::SerializeSettingId(SpdyMajorVersion version,
267                                        SpdySettingsIds id) {
268   switch (version) {
269     case SPDY2:
270     case SPDY3:
271       switch (id) {
272         case SETTINGS_UPLOAD_BANDWIDTH:
273           return 1;
274         case SETTINGS_DOWNLOAD_BANDWIDTH:
275           return 2;
276         case SETTINGS_ROUND_TRIP_TIME:
277           return 3;
278         case SETTINGS_MAX_CONCURRENT_STREAMS:
279           return 4;
280         case SETTINGS_CURRENT_CWND:
281           return 5;
282         case SETTINGS_DOWNLOAD_RETRANS_RATE:
283           return 6;
284         case SETTINGS_INITIAL_WINDOW_SIZE:
285           return 7;
286         default:
287           LOG(DFATAL) << "Serializing unhandled setting id " << id;
288           return -1;
289       }
290     case SPDY4:
291     case SPDY5:
292       switch (id) {
293         case SETTINGS_HEADER_TABLE_SIZE:
294           return 1;
295         case SETTINGS_ENABLE_PUSH:
296           return 2;
297         case SETTINGS_MAX_CONCURRENT_STREAMS:
298           return 3;
299         case SETTINGS_INITIAL_WINDOW_SIZE:
300           return 4;
301         default:
302           LOG(DFATAL) << "Serializing unhandled setting id " << id;
303           return -1;
304       }
305   }
306   LOG(DFATAL) << "Unhandled SPDY version " << version;
307   return -1;
308 }
309
310 bool SpdyConstants::IsValidRstStreamStatus(SpdyMajorVersion version,
311                                            int rst_stream_status_field) {
312   switch (version) {
313     case SPDY2:
314     case SPDY3:
315       // PROTOCOL_ERROR is the valid first status code.
316       if (rst_stream_status_field <
317           SerializeRstStreamStatus(version, RST_STREAM_PROTOCOL_ERROR)) {
318         return false;
319       }
320
321       // FRAME_TOO_LARGE is the valid last status code.
322       if (rst_stream_status_field >
323           SerializeRstStreamStatus(version, RST_STREAM_FRAME_TOO_LARGE)) {
324         return false;
325       }
326
327       return true;
328     case SPDY4:
329     case SPDY5:
330       // NO_ERROR is the first valid status code.
331       if (rst_stream_status_field <
332           SerializeRstStreamStatus(version, RST_STREAM_PROTOCOL_ERROR)) {
333         return false;
334       }
335
336       // TODO(hkhalil): Omit COMPRESSION_ERROR and SETTINGS_TIMEOUT
337       /*
338       // This works because GOAWAY and RST_STREAM share a namespace.
339       if (rst_stream_status_field ==
340           SerializeGoAwayStatus(version, GOAWAY_COMPRESSION_ERROR) ||
341           rst_stream_status_field ==
342           SerializeGoAwayStatus(version, GOAWAY_SETTINGS_TIMEOUT)) {
343         return false;
344       }
345       */
346
347       // ENHANCE_YOUR_CALM is the last valid status code.
348       if (rst_stream_status_field >
349           SerializeRstStreamStatus(version, RST_STREAM_ENHANCE_YOUR_CALM)) {
350         return false;
351       }
352
353       return true;
354   }
355   LOG(DFATAL) << "Unhandled SPDY version " << version;
356   return false;
357 }
358
359 SpdyRstStreamStatus SpdyConstants::ParseRstStreamStatus(
360     SpdyMajorVersion version,
361     int rst_stream_status_field) {
362   switch (version) {
363     case SPDY2:
364     case SPDY3:
365       switch (rst_stream_status_field) {
366         case 1:
367           return RST_STREAM_PROTOCOL_ERROR;
368         case 2:
369           return RST_STREAM_INVALID_STREAM;
370         case 3:
371           return RST_STREAM_REFUSED_STREAM;
372         case 4:
373           return RST_STREAM_UNSUPPORTED_VERSION;
374         case 5:
375           return RST_STREAM_CANCEL;
376         case 6:
377           return RST_STREAM_INTERNAL_ERROR;
378         case 7:
379           return RST_STREAM_FLOW_CONTROL_ERROR;
380         case 8:
381           return RST_STREAM_STREAM_IN_USE;
382         case 9:
383           return RST_STREAM_STREAM_ALREADY_CLOSED;
384         case 10:
385           return RST_STREAM_INVALID_CREDENTIALS;
386         case 11:
387           return RST_STREAM_FRAME_TOO_LARGE;
388       }
389       break;
390     case SPDY4:
391     case SPDY5:
392       switch (rst_stream_status_field) {
393         case 1:
394           return RST_STREAM_PROTOCOL_ERROR;
395         case 2:
396           return RST_STREAM_INTERNAL_ERROR;
397         case 3:
398           return RST_STREAM_FLOW_CONTROL_ERROR;
399         case 5:
400           return RST_STREAM_STREAM_CLOSED;
401         case 6:
402           return RST_STREAM_FRAME_SIZE_ERROR;
403         case 7:
404           return RST_STREAM_REFUSED_STREAM;
405         case 8:
406           return RST_STREAM_CANCEL;
407         case 10:
408           return RST_STREAM_CONNECT_ERROR;
409         case 11:
410           return RST_STREAM_ENHANCE_YOUR_CALM;
411       }
412       break;
413   }
414
415   LOG(DFATAL) << "Invalid RST_STREAM status " << rst_stream_status_field;
416   return RST_STREAM_PROTOCOL_ERROR;
417 }
418
419 int SpdyConstants::SerializeRstStreamStatus(
420     SpdyMajorVersion version,
421     SpdyRstStreamStatus rst_stream_status) {
422   switch (version) {
423     case SPDY2:
424     case SPDY3:
425       switch (rst_stream_status) {
426         case RST_STREAM_PROTOCOL_ERROR:
427           return 1;
428         case RST_STREAM_INVALID_STREAM:
429           return 2;
430         case RST_STREAM_REFUSED_STREAM:
431           return 3;
432         case RST_STREAM_UNSUPPORTED_VERSION:
433           return 4;
434         case RST_STREAM_CANCEL:
435           return 5;
436         case RST_STREAM_INTERNAL_ERROR:
437           return 6;
438         case RST_STREAM_FLOW_CONTROL_ERROR:
439           return 7;
440         case RST_STREAM_STREAM_IN_USE:
441           return 8;
442         case RST_STREAM_STREAM_ALREADY_CLOSED:
443           return 9;
444         case RST_STREAM_INVALID_CREDENTIALS:
445           return 10;
446         case RST_STREAM_FRAME_TOO_LARGE:
447           return 11;
448         default:
449           LOG(DFATAL) << "Unhandled RST_STREAM status "
450                       << rst_stream_status;
451           return -1;
452       }
453     case SPDY4:
454     case SPDY5:
455       switch (rst_stream_status) {
456         case RST_STREAM_PROTOCOL_ERROR:
457           return 1;
458         case RST_STREAM_INTERNAL_ERROR:
459           return 2;
460         case RST_STREAM_FLOW_CONTROL_ERROR:
461           return 3;
462         case RST_STREAM_STREAM_CLOSED:
463           return 5;
464         case RST_STREAM_FRAME_SIZE_ERROR:
465           return 6;
466         case RST_STREAM_REFUSED_STREAM:
467           return 7;
468         case RST_STREAM_CANCEL:
469           return 8;
470         case RST_STREAM_CONNECT_ERROR:
471           return 10;
472         case RST_STREAM_ENHANCE_YOUR_CALM:
473           return 11;
474         default:
475           LOG(DFATAL) << "Unhandled RST_STREAM status "
476                       << rst_stream_status;
477           return -1;
478       }
479   }
480   LOG(DFATAL) << "Unhandled SPDY version " << version;
481   return -1;
482 }
483
484 bool SpdyConstants::IsValidGoAwayStatus(SpdyMajorVersion version,
485                                         int goaway_status_field) {
486   switch (version) {
487     case SPDY2:
488     case SPDY3:
489       // GOAWAY_OK is the first valid status.
490       if (goaway_status_field < SerializeGoAwayStatus(version, GOAWAY_OK)) {
491         return false;
492       }
493
494       // GOAWAY_INTERNAL_ERROR is the last valid status.
495       if (goaway_status_field > SerializeGoAwayStatus(version,
496                                                       GOAWAY_INTERNAL_ERROR)) {
497         return false;
498       }
499
500       return true;
501     case SPDY4:
502     case SPDY5:
503       // GOAWAY_NO_ERROR is the first valid status.
504       if (goaway_status_field < SerializeGoAwayStatus(version,
505                                                       GOAWAY_NO_ERROR)) {
506         return false;
507       }
508
509       // GOAWAY_INADEQUATE_SECURITY is the last valid status.
510       if (goaway_status_field >
511           SerializeGoAwayStatus(version, GOAWAY_INADEQUATE_SECURITY)) {
512         return false;
513       }
514
515       return true;
516   }
517   LOG(DFATAL) << "Unknown SpdyMajorVersion " << version;
518   return false;
519 }
520
521 SpdyGoAwayStatus SpdyConstants::ParseGoAwayStatus(SpdyMajorVersion version,
522                                                   int goaway_status_field) {
523   switch (version) {
524     case SPDY2:
525     case SPDY3:
526       switch (goaway_status_field) {
527         case 0:
528           return GOAWAY_OK;
529         case 1:
530           return GOAWAY_PROTOCOL_ERROR;
531         case 2:
532           return GOAWAY_INTERNAL_ERROR;
533       }
534       break;
535     case SPDY4:
536     case SPDY5:
537       switch (goaway_status_field) {
538         case 0:
539           return GOAWAY_NO_ERROR;
540         case 1:
541           return GOAWAY_PROTOCOL_ERROR;
542         case 2:
543           return GOAWAY_INTERNAL_ERROR;
544         case 3:
545           return GOAWAY_FLOW_CONTROL_ERROR;
546         case 4:
547           return GOAWAY_SETTINGS_TIMEOUT;
548         case 5:
549           return GOAWAY_STREAM_CLOSED;
550         case 6:
551           return GOAWAY_FRAME_SIZE_ERROR;
552         case 7:
553           return GOAWAY_REFUSED_STREAM;
554         case 8:
555           return GOAWAY_CANCEL;
556         case 9:
557           return GOAWAY_COMPRESSION_ERROR;
558         case 10:
559           return GOAWAY_CONNECT_ERROR;
560         case 11:
561           return GOAWAY_ENHANCE_YOUR_CALM;
562         case 12:
563           return GOAWAY_INADEQUATE_SECURITY;
564       }
565       break;
566   }
567
568   LOG(DFATAL) << "Unhandled GOAWAY status " << goaway_status_field;
569   return GOAWAY_PROTOCOL_ERROR;
570 }
571
572 SpdyMajorVersion SpdyConstants::ParseMajorVersion(int version_number) {
573   switch (version_number) {
574     case 2:
575       return SPDY2;
576     case 3:
577       return SPDY3;
578     case 4:
579       return SPDY4;
580     case 5:
581       return SPDY5;
582     default:
583       LOG(DFATAL) << "Unsupported SPDY version number: " << version_number;
584       return SPDY3;
585   }
586 }
587
588 int SpdyConstants::SerializeMajorVersion(SpdyMajorVersion version) {
589   switch (version) {
590     case SPDY2:
591       return 2;
592     case SPDY3:
593       return 3;
594     case SPDY4:
595       return 4;
596     case SPDY5:
597       return 5;
598     default:
599       LOG(DFATAL) << "Unsupported SPDY major version: " << version;
600       return -1;
601   }
602 }
603
604 std::string SpdyConstants::GetVersionString(SpdyMajorVersion version) {
605   switch (version) {
606     case SPDY2:
607       return "spdy/2";
608     case SPDY3:
609       return "spdy/3";
610     case SPDY4:
611       return "spdy/4";
612     case SPDY5:
613       return "spdy/5";
614     default:
615       LOG(DFATAL) << "Unsupported SPDY major version: " << version;
616       return "spdy/3";
617   }
618 }
619
620 int SpdyConstants::SerializeGoAwayStatus(SpdyMajorVersion version,
621                                          SpdyGoAwayStatus status) {
622   switch (version) {
623     case SPDY2:
624     case SPDY3:
625       switch (status) {
626         case GOAWAY_OK:
627           return 0;
628         case GOAWAY_PROTOCOL_ERROR:
629           return 1;
630         case GOAWAY_INTERNAL_ERROR:
631           return 2;
632         default:
633           LOG(DFATAL) << "Serializing unhandled GOAWAY status " << status;
634           return -1;
635       }
636     case SPDY4:
637     case SPDY5:
638       switch (status) {
639         case GOAWAY_NO_ERROR:
640           return 0;
641         case GOAWAY_PROTOCOL_ERROR:
642           return 1;
643         case GOAWAY_INTERNAL_ERROR:
644           return 2;
645         case GOAWAY_FLOW_CONTROL_ERROR:
646           return 3;
647         case GOAWAY_SETTINGS_TIMEOUT:
648           return 4;
649         case GOAWAY_STREAM_CLOSED:
650           return 5;
651         case GOAWAY_FRAME_SIZE_ERROR:
652           return 6;
653         case GOAWAY_REFUSED_STREAM:
654           return 7;
655         case GOAWAY_CANCEL:
656           return 8;
657         case GOAWAY_COMPRESSION_ERROR:
658           return 9;
659         case GOAWAY_CONNECT_ERROR:
660           return 10;
661         case GOAWAY_ENHANCE_YOUR_CALM:
662           return 11;
663         case GOAWAY_INADEQUATE_SECURITY:
664           return 12;
665         default:
666           LOG(DFATAL) << "Serializing unhandled GOAWAY status " << status;
667           return -1;
668       }
669   }
670   LOG(DFATAL) << "Unknown SpdyMajorVersion " << version;
671   return -1;
672 }
673
674 size_t SpdyConstants::GetDataFrameMinimumSize() {
675   return 8;
676 }
677
678 size_t SpdyConstants::GetControlFrameHeaderSize(SpdyMajorVersion version) {
679   switch (version) {
680     case SPDY2:
681     case SPDY3:
682     case SPDY4:
683     case SPDY5:
684       return 8;
685   }
686   LOG(DFATAL) << "Unhandled SPDY version.";
687   return 0;
688 }
689
690 size_t SpdyConstants::GetPrefixLength(SpdyFrameType type,
691                                       SpdyMajorVersion version) {
692   if (type != DATA) {
693      return GetControlFrameHeaderSize(version);
694   } else {
695      return GetDataFrameMinimumSize();
696   }
697 }
698
699 size_t SpdyConstants::GetFrameMaximumSize(SpdyMajorVersion version) {
700   if (version < SPDY4) {
701     // 24-bit length field plus eight-byte frame header.
702     return ((1<<24) - 1) + 8;
703   } else {
704     // 14-bit length field.
705     return (1<<14) - 1;
706   }
707 }
708
709 void SpdyDataIR::Visit(SpdyFrameVisitor* visitor) const {
710   return visitor->VisitData(*this);
711 }
712
713 void SpdySynStreamIR::Visit(SpdyFrameVisitor* visitor) const {
714   return visitor->VisitSynStream(*this);
715 }
716
717 void SpdySynReplyIR::Visit(SpdyFrameVisitor* visitor) const {
718   return visitor->VisitSynReply(*this);
719 }
720
721 SpdyRstStreamIR::SpdyRstStreamIR(SpdyStreamId stream_id,
722                                  SpdyRstStreamStatus status,
723                                  base::StringPiece description)
724     : SpdyFrameWithStreamIdIR(stream_id),
725       description_(description) {
726   set_status(status);
727 }
728
729 SpdyRstStreamIR::~SpdyRstStreamIR() {}
730
731 void SpdyRstStreamIR::Visit(SpdyFrameVisitor* visitor) const {
732   return visitor->VisitRstStream(*this);
733 }
734
735 SpdySettingsIR::SpdySettingsIR()
736     : clear_settings_(false),
737       is_ack_(false) {}
738
739 SpdySettingsIR::~SpdySettingsIR() {}
740
741 void SpdySettingsIR::Visit(SpdyFrameVisitor* visitor) const {
742   return visitor->VisitSettings(*this);
743 }
744
745 void SpdyPingIR::Visit(SpdyFrameVisitor* visitor) const {
746   return visitor->VisitPing(*this);
747 }
748
749 SpdyGoAwayIR::SpdyGoAwayIR(SpdyStreamId last_good_stream_id,
750                            SpdyGoAwayStatus status,
751                            const base::StringPiece& description)
752     : description_(description) {
753       set_last_good_stream_id(last_good_stream_id);
754   set_status(status);
755 }
756
757 SpdyGoAwayIR::~SpdyGoAwayIR() {}
758
759 const base::StringPiece& SpdyGoAwayIR::description() const {
760   return description_;
761 }
762
763 void SpdyGoAwayIR::Visit(SpdyFrameVisitor* visitor) const {
764   return visitor->VisitGoAway(*this);
765 }
766
767 void SpdyHeadersIR::Visit(SpdyFrameVisitor* visitor) const {
768   return visitor->VisitHeaders(*this);
769 }
770
771 void SpdyWindowUpdateIR::Visit(SpdyFrameVisitor* visitor) const {
772   return visitor->VisitWindowUpdate(*this);
773 }
774
775 void SpdyBlockedIR::Visit(SpdyFrameVisitor* visitor) const {
776   return visitor->VisitBlocked(*this);
777 }
778
779 void SpdyPushPromiseIR::Visit(SpdyFrameVisitor* visitor) const {
780   return visitor->VisitPushPromise(*this);
781 }
782
783 void SpdyContinuationIR::Visit(SpdyFrameVisitor* visitor) const {
784   return visitor->VisitContinuation(*this);
785 }
786
787 }  // namespace net