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