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       padded_(false),
     17       padding_payload_len_(0) {
     18   SetDataDeep(data);
     19 }
     20 
     21 SpdyDataIR::SpdyDataIR(SpdyStreamId stream_id)
     22     : SpdyFrameWithFinIR(stream_id),
     23       padded_(false),
     24       padding_payload_len_(0) {}
     25 
     26 SpdyDataIR::~SpdyDataIR() {}
     27 
     28 bool 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 
     69 SpdyFrameType 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 
    128 int 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 
    192 int 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 
    206 bool 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 
    245 SpdySettingsIds 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 
    290 int 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 
    338 bool 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 
    387 SpdyRstStreamStatus 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 
    447 int 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 
    512 bool 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 
    549 SpdyGoAwayStatus 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 
    600 SpdyMajorVersion 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 
    616 int 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 
    632 std::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 
    648 int 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 
    712 size_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 
    725 size_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 
    738 size_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 
    747 size_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 
    760 size_t SpdyConstants::GetSizeOfSizeField(SpdyMajorVersion version) {
    761   return (version < SPDY3) ? sizeof(uint16) : sizeof(uint32);
    762 }
    763 
    764 size_t SpdyConstants::GetSettingSize(SpdyMajorVersion version) {
    765   return version <= SPDY3 ? 8 : 6;
    766 }
    767 
    768 void SpdyDataIR::Visit(SpdyFrameVisitor* visitor) const {
    769   return visitor->VisitData(*this);
    770 }
    771 
    772 void SpdySynStreamIR::Visit(SpdyFrameVisitor* visitor) const {
    773   return visitor->VisitSynStream(*this);
    774 }
    775 
    776 void SpdySynReplyIR::Visit(SpdyFrameVisitor* visitor) const {
    777   return visitor->VisitSynReply(*this);
    778 }
    779 
    780 SpdyRstStreamIR::SpdyRstStreamIR(SpdyStreamId stream_id,
    781                                  SpdyRstStreamStatus status,
    782                                  base::StringPiece description)
    783     : SpdyFrameWithStreamIdIR(stream_id),
    784       description_(description) {
    785   set_status(status);
    786 }
    787 
    788 SpdyRstStreamIR::~SpdyRstStreamIR() {}
    789 
    790 void SpdyRstStreamIR::Visit(SpdyFrameVisitor* visitor) const {
    791   return visitor->VisitRstStream(*this);
    792 }
    793 
    794 SpdySettingsIR::SpdySettingsIR()
    795     : clear_settings_(false),
    796       is_ack_(false) {}
    797 
    798 SpdySettingsIR::~SpdySettingsIR() {}
    799 
    800 void SpdySettingsIR::Visit(SpdyFrameVisitor* visitor) const {
    801   return visitor->VisitSettings(*this);
    802 }
    803 
    804 void SpdyPingIR::Visit(SpdyFrameVisitor* visitor) const {
    805   return visitor->VisitPing(*this);
    806 }
    807 
    808 SpdyGoAwayIR::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 
    816 SpdyGoAwayIR::~SpdyGoAwayIR() {}
    817 
    818 const base::StringPiece& SpdyGoAwayIR::description() const {
    819   return description_;
    820 }
    821 
    822 void SpdyGoAwayIR::Visit(SpdyFrameVisitor* visitor) const {
    823   return visitor->VisitGoAway(*this);
    824 }
    825 
    826 void SpdyHeadersIR::Visit(SpdyFrameVisitor* visitor) const {
    827   return visitor->VisitHeaders(*this);
    828 }
    829 
    830 void SpdyWindowUpdateIR::Visit(SpdyFrameVisitor* visitor) const {
    831   return visitor->VisitWindowUpdate(*this);
    832 }
    833 
    834 void SpdyBlockedIR::Visit(SpdyFrameVisitor* visitor) const {
    835   return visitor->VisitBlocked(*this);
    836 }
    837 
    838 void SpdyPushPromiseIR::Visit(SpdyFrameVisitor* visitor) const {
    839   return visitor->VisitPushPromise(*this);
    840 }
    841 
    842 void SpdyContinuationIR::Visit(SpdyFrameVisitor* visitor) const {
    843   return visitor->VisitContinuation(*this);
    844 }
    845 
    846 SpdyAltSvcIR::SpdyAltSvcIR(SpdyStreamId stream_id)
    847     : SpdyFrameWithStreamIdIR(stream_id),
    848       max_age_(0),
    849       port_(0) {}
    850 
    851 void SpdyAltSvcIR::Visit(SpdyFrameVisitor* visitor) const {
    852   return visitor->VisitAltSvc(*this);
    853 }
    854 
    855 SpdyPriorityIR::SpdyPriorityIR(SpdyStreamId stream_id)
    856     : SpdyFrameWithStreamIdIR(stream_id) {
    857 }
    858 
    859 SpdyPriorityIR::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 
    869 void SpdyPriorityIR::Visit(SpdyFrameVisitor* visitor) const {
    870   return visitor->VisitPriority(*this);
    871 }
    872 
    873 }  // namespace net
    874