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