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 // This file contains some protocol structures for use with SPDY 2 and 3
      6 // The SPDY 2 spec can be found at:
      7 // http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft2
      8 // The SPDY 3 spec can be found at:
      9 // http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3
     10 
     11 #ifndef NET_SPDY_SPDY_PROTOCOL_H_
     12 #define NET_SPDY_SPDY_PROTOCOL_H_
     13 
     14 #include <map>
     15 #include <string>
     16 #include <vector>
     17 
     18 #include "base/basictypes.h"
     19 #include "base/compiler_specific.h"
     20 #include "base/logging.h"
     21 #include "base/memory/scoped_ptr.h"
     22 #include "base/strings/string_piece.h"
     23 #include "base/sys_byteorder.h"
     24 #include "net/base/net_export.h"
     25 #include "net/spdy/spdy_bitmasks.h"
     26 
     27 namespace net {
     28 
     29 // The major versions of SPDY. Major version differences indicate
     30 // framer-layer incompatibility, as opposed to minor version numbers
     31 // which indicate application-layer incompatibility. It is guaranteed
     32 // that the enum value SPDYn maps to the integer n.
     33 enum SpdyMajorVersion {
     34   SPDY2 = 2,
     35   SPDY_MIN_VERSION = SPDY2,
     36   SPDY3 = 3,
     37   SPDY4 = 4,
     38   SPDY_MAX_VERSION = SPDY4
     39 };
     40 
     41 // A SPDY stream id is a 31 bit entity.
     42 typedef uint32 SpdyStreamId;
     43 
     44 // Specifies the stream ID used to denote the current session (for
     45 // flow control).
     46 const SpdyStreamId kSessionFlowControlStreamId = 0;
     47 
     48 // Initial window size for a Spdy stream in bytes.
     49 const int32 kSpdyStreamInitialWindowSize = 64 * 1024;  // 64 KBytes
     50 
     51 // Initial window size for a Spdy session in bytes.
     52 const int32 kSpdySessionInitialWindowSize = 64 * 1024;  // 64 KBytes
     53 
     54 // Maximum window size for a Spdy stream or session.
     55 const int32 kSpdyMaximumWindowSize = 0x7FFFFFFF;  // Max signed 32bit int
     56 
     57 // SPDY 2 dictionary.
     58 // This is just a hacked dictionary to use for shrinking HTTP-like headers.
     59 const char kV2Dictionary[] =
     60   "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-"
     61   "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi"
     62   "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser"
     63   "-agent10010120020120220320420520630030130230330430530630740040140240340440"
     64   "5406407408409410411412413414415416417500501502503504505accept-rangesageeta"
     65   "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic"
     66   "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran"
     67   "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati"
     68   "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo"
     69   "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe"
     70   "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic"
     71   "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1"
     72   ".1statusversionurl";
     73 const int kV2DictionarySize = arraysize(kV2Dictionary);
     74 
     75 // SPDY 3 dictionary.
     76 const char kV3Dictionary[] = {
     77   0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69,  // ....opti
     78   0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68,  // ons....h
     79   0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70,  // ead....p
     80   0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70,  // ost....p
     81   0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65,  // ut....de
     82   0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05,  // lete....
     83   0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00,  // trace...
     84   0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00,  // .accept.
     85   0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70,  // ...accep
     86   0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65,  // t-charse
     87   0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63,  // t....acc
     88   0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f,  // ept-enco
     89   0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f,  // ding....
     90   0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c,  // accept-l
     91   0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00,  // anguage.
     92   0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70,  // ...accep
     93   0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73,  // t-ranges
     94   0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00,  // ....age.
     95   0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77,  // ...allow
     96   0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68,  // ....auth
     97   0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f,  // orizatio
     98   0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63,  // n....cac
     99   0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72,  // he-contr
    100   0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f,  // ol....co
    101   0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,  // nnection
    102   0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74,  // ....cont
    103   0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65,  // ent-base
    104   0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74,  // ....cont
    105   0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f,  // ent-enco
    106   0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10,  // ding....
    107   0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d,  // content-
    108   0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65,  // language
    109   0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74,  // ....cont
    110   0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67,  // ent-leng
    111   0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f,  // th....co
    112   0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f,  // ntent-lo
    113   0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,  // cation..
    114   0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,  // ..conten
    115   0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00,  // t-md5...
    116   0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,  // .content
    117   0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00,  // -range..
    118   0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,  // ..conten
    119   0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00,  // t-type..
    120   0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00,  // ..date..
    121   0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00,  // ..etag..
    122   0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74,  // ..expect
    123   0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69,  // ....expi
    124   0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66,  // res....f
    125   0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68,  // rom....h
    126   0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69,  // ost....i
    127   0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00,  // f-match.
    128   0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f,  // ...if-mo
    129   0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73,  // dified-s
    130   0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d,  // ince....
    131   0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d,  // if-none-
    132   0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00,  // match...
    133   0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67,  // .if-rang
    134   0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d,  // e....if-
    135   0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69,  // unmodifi
    136   0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65,  // ed-since
    137   0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74,  // ....last
    138   0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65,  // -modifie
    139   0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63,  // d....loc
    140   0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00,  // ation...
    141   0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72,  // .max-for
    142   0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00,  // wards...
    143   0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00,  // .pragma.
    144   0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79,  // ...proxy
    145   0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74,  // -authent
    146   0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00,  // icate...
    147   0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61,  // .proxy-a
    148   0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61,  // uthoriza
    149   0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05,  // tion....
    150   0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00,  // range...
    151   0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72,  // .referer
    152   0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72,  // ....retr
    153   0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00,  // y-after.
    154   0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65,  // ...serve
    155   0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00,  // r....te.
    156   0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c,  // ...trail
    157   0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72,  // er....tr
    158   0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65,  // ansfer-e
    159   0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00,  // ncoding.
    160   0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61,  // ...upgra
    161   0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73,  // de....us
    162   0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74,  // er-agent
    163   0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79,  // ....vary
    164   0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00,  // ....via.
    165   0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69,  // ...warni
    166   0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77,  // ng....ww
    167   0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e,  // w-authen
    168   0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00,  // ticate..
    169   0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64,  // ..method
    170   0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00,  // ....get.
    171   0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,  // ...statu
    172   0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30,  // s....200
    173   0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76,  // .OK....v
    174   0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00,  // ersion..
    175   0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31,  // ..HTTP.1
    176   0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72,  // .1....ur
    177   0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62,  // l....pub
    178   0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73,  // lic....s
    179   0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69,  // et-cooki
    180   0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65,  // e....kee
    181   0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00,  // p-alive.
    182   0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69,  // ...origi
    183   0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32,  // n1001012
    184   0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35,  // 01202205
    185   0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30,  // 20630030
    186   0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33,  // 23033043
    187   0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37,  // 05306307
    188   0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30,  // 40240540
    189   0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34,  // 64074084
    190   0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31,  // 09410411
    191   0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31,  // 41241341
    192   0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34,  // 44154164
    193   0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34,  // 17502504
    194   0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e,  // 505203.N
    195   0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f,  // on-Autho
    196   0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65,  // ritative
    197   0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61,  // .Informa
    198   0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20,  // tion204.
    199   0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65,  // No.Conte
    200   0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f,  // nt301.Mo
    201   0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d,  // ved.Perm
    202   0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34,  // anently4
    203   0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52,  // 00.Bad.R
    204   0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30,  // equest40
    205   0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68,  // 1.Unauth
    206   0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30,  // orized40
    207   0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64,  // 3.Forbid
    208   0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e,  // den404.N
    209   0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64,  // ot.Found
    210   0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65,  // 500.Inte
    211   0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72,  // rnal.Ser
    212   0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f,  // ver.Erro
    213   0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74,  // r501.Not
    214   0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65,  // .Impleme
    215   0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20,  // nted503.
    216   0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20,  // Service.
    217   0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61,  // Unavaila
    218   0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46,  // bleJan.F
    219   0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41,  // eb.Mar.A
    220   0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a,  // pr.May.J
    221   0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41,  // un.Jul.A
    222   0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20,  // ug.Sept.
    223   0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20,  // Oct.Nov.
    224   0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30,  // Dec.00.0
    225   0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e,  // 0.00.Mon
    226   0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57,  // ..Tue..W
    227   0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c,  // ed..Thu.
    228   0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61,  // .Fri..Sa
    229   0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20,  // t..Sun..
    230   0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b,  // GMTchunk
    231   0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f,  // ed.text.
    232   0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61,  // html.ima
    233   0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69,  // ge.png.i
    234   0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67,  // mage.jpg
    235   0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67,  // .image.g
    236   0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69,  // if.appli
    237   0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78,  // cation.x
    238   0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69,  // ml.appli
    239   0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78,  // cation.x
    240   0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c,  // html.xml
    241   0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c,  // .text.pl
    242   0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74,  // ain.text
    243   0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72,  // .javascr
    244   0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c,  // ipt.publ
    245   0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74,  // icprivat
    246   0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65,  // emax-age
    247   0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65,  // .gzip.de
    248   0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64,  // flate.sd
    249   0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65,  // chcharse
    250   0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63,  // t.utf-8c
    251   0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69,  // harset.i
    252   0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d,  // so-8859-
    253   0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a,  // 1.utf-..
    254   0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e         // .enq.0.
    255 };
    256 const int kV3DictionarySize = arraysize(kV3Dictionary);
    257 
    258 // The HTTP/2 connection header prefix, which must be the first bytes
    259 // sent by the client upon starting an HTTP/2 connection, and which
    260 // must be followed by a SETTINGS frame.
    261 //
    262 // Equivalent to the string "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
    263 // (without the null terminator).
    264 const char kHttp2ConnectionHeaderPrefix[] = {
    265   0x50, 0x52, 0x49, 0x20, 0x2a, 0x20, 0x48, 0x54,  // PRI * HT
    266   0x54, 0x50, 0x2f, 0x32, 0x2e, 0x30, 0x0d, 0x0a,  // TP/2.0..
    267   0x0d, 0x0a, 0x53, 0x4d, 0x0d, 0x0a, 0x0d, 0x0a   // ..SM....
    268 };
    269 const int kHttp2ConnectionHeaderPrefixSize =
    270     arraysize(kHttp2ConnectionHeaderPrefix);
    271 
    272 // Types of SPDY frames.
    273 enum SpdyFrameType {
    274   DATA = 0,
    275   SYN_STREAM = 1,
    276   FIRST_CONTROL_TYPE = SYN_STREAM,
    277   SYN_REPLY,
    278   RST_STREAM,
    279   SETTINGS,
    280   NOOP,  // Because it is valid in SPDY/2, kept for identifiability/enum order.
    281   PING,
    282   GOAWAY,
    283   HEADERS,
    284   WINDOW_UPDATE,
    285   CREDENTIAL,
    286   BLOCKED,
    287   PUSH_PROMISE,
    288   LAST_CONTROL_TYPE = PUSH_PROMISE
    289 };
    290 
    291 // Flags on data packets.
    292 enum SpdyDataFlags {
    293   DATA_FLAG_NONE = 0,
    294   DATA_FLAG_FIN = 1,
    295 };
    296 
    297 // Flags on control packets
    298 enum SpdyControlFlags {
    299   CONTROL_FLAG_NONE = 0,
    300   CONTROL_FLAG_FIN = 1,
    301   CONTROL_FLAG_UNIDIRECTIONAL = 2
    302 };
    303 
    304 // Flags on the SETTINGS control frame.
    305 enum SpdySettingsControlFlags {
    306   SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS = 0x1
    307 };
    308 
    309 // Flags for settings within a SETTINGS frame.
    310 enum SpdySettingsFlags {
    311   SETTINGS_FLAG_NONE = 0x0,
    312   SETTINGS_FLAG_PLEASE_PERSIST = 0x1,
    313   SETTINGS_FLAG_PERSISTED = 0x2
    314 };
    315 
    316 // List of known settings.
    317 enum SpdySettingsIds {
    318   SETTINGS_UPLOAD_BANDWIDTH = 0x1,
    319   SETTINGS_DOWNLOAD_BANDWIDTH = 0x2,
    320   // Network round trip time in milliseconds.
    321   SETTINGS_ROUND_TRIP_TIME = 0x3,
    322   SETTINGS_MAX_CONCURRENT_STREAMS = 0x4,
    323   // TCP congestion window in packets.
    324   SETTINGS_CURRENT_CWND = 0x5,
    325   // Downstream byte retransmission rate in percentage.
    326   SETTINGS_DOWNLOAD_RETRANS_RATE = 0x6,
    327   // Initial window size in bytes
    328   SETTINGS_INITIAL_WINDOW_SIZE = 0x7
    329 };
    330 
    331 // Status codes for RST_STREAM frames.
    332 enum SpdyRstStreamStatus {
    333   RST_STREAM_INVALID = 0,
    334   RST_STREAM_PROTOCOL_ERROR = 1,
    335   RST_STREAM_INVALID_STREAM = 2,
    336   RST_STREAM_REFUSED_STREAM = 3,
    337   RST_STREAM_UNSUPPORTED_VERSION = 4,
    338   RST_STREAM_CANCEL = 5,
    339   RST_STREAM_INTERNAL_ERROR = 6,
    340   RST_STREAM_FLOW_CONTROL_ERROR = 7,
    341   RST_STREAM_STREAM_IN_USE = 8,
    342   RST_STREAM_STREAM_ALREADY_CLOSED = 9,
    343   RST_STREAM_INVALID_CREDENTIALS = 10,
    344   RST_STREAM_FRAME_TOO_LARGE = 11,
    345   RST_STREAM_NUM_STATUS_CODES = 12
    346 };
    347 
    348 // Status codes for GOAWAY frames.
    349 enum SpdyGoAwayStatus {
    350   GOAWAY_INVALID = -1,
    351   GOAWAY_OK = 0,
    352   GOAWAY_PROTOCOL_ERROR = 1,
    353   GOAWAY_INTERNAL_ERROR = 2,
    354   GOAWAY_NUM_STATUS_CODES = 3
    355 };
    356 
    357 // A SPDY priority is a number between 0 and 7 (inclusive).
    358 // SPDY priority range is version-dependant. For SPDY 2 and below, priority is a
    359 // number between 0 and 3.
    360 typedef uint8 SpdyPriority;
    361 
    362 typedef uint8 SpdyCredentialSlot;
    363 
    364 typedef std::map<std::string, std::string> SpdyNameValueBlock;
    365 
    366 typedef uint32 SpdyPingId;
    367 
    368 class SpdyFrame;
    369 typedef SpdyFrame SpdySerializedFrame;
    370 
    371 class SpdyFrameVisitor;
    372 
    373 // Intermediate representation for SPDY frames.
    374 // TODO(hkhalil): Rename this class to SpdyFrame when the existing SpdyFrame is
    375 // gone.
    376 class SpdyFrameIR {
    377  public:
    378   virtual ~SpdyFrameIR() {}
    379 
    380   virtual void Visit(SpdyFrameVisitor* visitor) const = 0;
    381 
    382  protected:
    383   SpdyFrameIR() {}
    384 
    385  private:
    386   DISALLOW_COPY_AND_ASSIGN(SpdyFrameIR);
    387 };
    388 
    389 // Abstract class intended to be inherited by IRs that have a stream associated
    390 // to them.
    391 class SpdyFrameWithStreamIdIR : public SpdyFrameIR {
    392  public:
    393   virtual ~SpdyFrameWithStreamIdIR() {}
    394   SpdyStreamId stream_id() const { return stream_id_; }
    395   void set_stream_id(SpdyStreamId stream_id) {
    396     DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
    397     stream_id_ = stream_id;
    398   }
    399 
    400  protected:
    401   explicit SpdyFrameWithStreamIdIR(SpdyStreamId stream_id) {
    402     set_stream_id(stream_id);
    403   }
    404 
    405  private:
    406   SpdyStreamId stream_id_;
    407 
    408   DISALLOW_COPY_AND_ASSIGN(SpdyFrameWithStreamIdIR);
    409 };
    410 
    411 // Abstract class intended to be inherited by IRs that have the option of a FIN
    412 // flag. Implies SpdyFrameWithStreamIdIR.
    413 class SpdyFrameWithFinIR : public SpdyFrameWithStreamIdIR {
    414  public:
    415   virtual ~SpdyFrameWithFinIR() {}
    416   bool fin() const { return fin_; }
    417   void set_fin(bool fin) { fin_ = fin; }
    418 
    419  protected:
    420   explicit SpdyFrameWithFinIR(SpdyStreamId stream_id)
    421       : SpdyFrameWithStreamIdIR(stream_id),
    422         fin_(false) {}
    423 
    424  private:
    425   bool fin_;
    426 
    427   DISALLOW_COPY_AND_ASSIGN(SpdyFrameWithFinIR);
    428 };
    429 
    430 // Abstract class intended to be inherited by IRs that contain a name-value
    431 // block. Implies SpdyFrameWithFinIR.
    432 class NET_EXPORT_PRIVATE SpdyFrameWithNameValueBlockIR
    433     : public NON_EXPORTED_BASE(SpdyFrameWithFinIR) {
    434  public:
    435   const SpdyNameValueBlock& name_value_block() const {
    436     return name_value_block_;
    437   }
    438   SpdyNameValueBlock* GetMutableNameValueBlock() { return &name_value_block_; }
    439   void SetHeader(const base::StringPiece& name,
    440                  const base::StringPiece& value) {
    441     name_value_block_[name.as_string()] = value.as_string();
    442   }
    443 
    444  protected:
    445   explicit SpdyFrameWithNameValueBlockIR(SpdyStreamId stream_id);
    446   virtual ~SpdyFrameWithNameValueBlockIR();
    447 
    448  private:
    449   SpdyNameValueBlock name_value_block_;
    450 
    451   DISALLOW_COPY_AND_ASSIGN(SpdyFrameWithNameValueBlockIR);
    452 };
    453 
    454 class NET_EXPORT_PRIVATE SpdyDataIR
    455     : public NON_EXPORTED_BASE(SpdyFrameWithFinIR) {
    456  public:
    457   // Performs deep copy on data.
    458   SpdyDataIR(SpdyStreamId stream_id, const base::StringPiece& data);
    459 
    460   // Use in conjunction with SetDataShallow() for shallow-copy on data.
    461   explicit SpdyDataIR(SpdyStreamId stream_id);
    462 
    463   virtual ~SpdyDataIR();
    464 
    465   base::StringPiece data() const { return data_; }
    466 
    467   // Deep-copy of data (keep private copy).
    468   void SetDataDeep(const base::StringPiece& data) {
    469     data_store_.reset(new std::string(data.data(), data.length()));
    470     data_ = *(data_store_.get());
    471   }
    472 
    473   // Shallow-copy of data (do not keep private copy).
    474   void SetDataShallow(const base::StringPiece& data) {
    475     data_store_.reset();
    476     data_ = data;
    477   }
    478 
    479   virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
    480 
    481  private:
    482   // Used to store data that this SpdyDataIR should own.
    483   scoped_ptr<std::string> data_store_;
    484   base::StringPiece data_;
    485 
    486   DISALLOW_COPY_AND_ASSIGN(SpdyDataIR);
    487 };
    488 
    489 class NET_EXPORT_PRIVATE SpdySynStreamIR
    490     : public SpdyFrameWithNameValueBlockIR {
    491  public:
    492   explicit SpdySynStreamIR(SpdyStreamId stream_id)
    493       : SpdyFrameWithNameValueBlockIR(stream_id),
    494         associated_to_stream_id_(0),
    495         priority_(0),
    496         slot_(0),
    497         unidirectional_(false) {}
    498   SpdyStreamId associated_to_stream_id() const {
    499     return associated_to_stream_id_;
    500   }
    501   void set_associated_to_stream_id(SpdyStreamId stream_id) {
    502     associated_to_stream_id_ = stream_id;
    503   }
    504   SpdyPriority priority() const { return priority_; }
    505   void set_priority(SpdyPriority priority) { priority_ = priority; }
    506   SpdyCredentialSlot slot() const { return slot_; }
    507   void set_slot(SpdyCredentialSlot slot) { slot_ = slot; }
    508   bool unidirectional() const { return unidirectional_; }
    509   void set_unidirectional(bool unidirectional) {
    510     unidirectional_ = unidirectional;
    511   }
    512 
    513   virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
    514 
    515  private:
    516   SpdyStreamId associated_to_stream_id_;
    517   SpdyPriority priority_;
    518   SpdyCredentialSlot slot_;
    519   bool unidirectional_;
    520 
    521   DISALLOW_COPY_AND_ASSIGN(SpdySynStreamIR);
    522 };
    523 
    524 class SpdySynReplyIR : public SpdyFrameWithNameValueBlockIR {
    525  public:
    526   explicit SpdySynReplyIR(SpdyStreamId stream_id)
    527       : SpdyFrameWithNameValueBlockIR(stream_id) {}
    528 
    529   virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
    530 
    531  private:
    532   DISALLOW_COPY_AND_ASSIGN(SpdySynReplyIR);
    533 };
    534 
    535 class SpdyRstStreamIR : public SpdyFrameWithStreamIdIR {
    536  public:
    537   SpdyRstStreamIR(SpdyStreamId stream_id, SpdyRstStreamStatus status)
    538       : SpdyFrameWithStreamIdIR(stream_id) {
    539     set_status(status);
    540   }
    541   SpdyRstStreamStatus status() const {
    542     return status_;
    543   }
    544   void set_status(SpdyRstStreamStatus status) {
    545     DCHECK_NE(status, RST_STREAM_INVALID);
    546     DCHECK_LT(status, RST_STREAM_NUM_STATUS_CODES);
    547     status_ = status;
    548   }
    549 
    550   virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
    551 
    552  private:
    553   SpdyRstStreamStatus status_;
    554 
    555   DISALLOW_COPY_AND_ASSIGN(SpdyRstStreamIR);
    556 };
    557 
    558 class SpdySettingsIR : public SpdyFrameIR {
    559  public:
    560   // Associates flags with a value.
    561   struct Value {
    562     Value() : persist_value(false),
    563               persisted(false),
    564               value(0) {}
    565     bool persist_value;
    566     bool persisted;
    567     int32 value;
    568   };
    569   typedef std::map<SpdySettingsIds, Value> ValueMap;
    570 
    571   SpdySettingsIR();
    572 
    573   virtual ~SpdySettingsIR();
    574 
    575   // Overwrites as appropriate.
    576   const ValueMap& values() const { return values_; }
    577   void AddSetting(SpdySettingsIds id,
    578                   bool persist_value,
    579                   bool persisted,
    580                   int32 value) {
    581     // TODO(hkhalil): DCHECK_LE(SETTINGS_UPLOAD_BANDWIDTH, id);
    582     // TODO(hkhalil): DCHECK_GE(SETTINGS_INITIAL_WINDOW_SIZE, id);
    583     values_[id].persist_value = persist_value;
    584     values_[id].persisted = persisted;
    585     values_[id].value = value;
    586   }
    587   bool clear_settings() const { return clear_settings_; }
    588   void set_clear_settings(bool clear_settings) {
    589     clear_settings_ = clear_settings;
    590   }
    591 
    592   virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
    593 
    594  private:
    595   ValueMap values_;
    596   bool clear_settings_;
    597 
    598   DISALLOW_COPY_AND_ASSIGN(SpdySettingsIR);
    599 };
    600 
    601 class SpdyPingIR : public SpdyFrameIR {
    602  public:
    603   explicit SpdyPingIR(SpdyPingId id) : id_(id) {}
    604   SpdyPingId id() const { return id_; }
    605 
    606   virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
    607 
    608  private:
    609   SpdyPingId id_;
    610 
    611   DISALLOW_COPY_AND_ASSIGN(SpdyPingIR);
    612 };
    613 
    614 class SpdyGoAwayIR : public SpdyFrameIR {
    615  public:
    616   SpdyGoAwayIR(SpdyStreamId last_good_stream_id, SpdyGoAwayStatus status) {
    617     set_last_good_stream_id(last_good_stream_id);
    618     set_status(status);
    619   }
    620   SpdyStreamId last_good_stream_id() const { return last_good_stream_id_; }
    621   void set_last_good_stream_id(SpdyStreamId last_good_stream_id) {
    622     DCHECK_LE(0u, last_good_stream_id);
    623     DCHECK_EQ(0u, last_good_stream_id & ~kStreamIdMask);
    624     last_good_stream_id_ = last_good_stream_id;
    625   }
    626   SpdyGoAwayStatus status() const { return status_; }
    627   void set_status(SpdyGoAwayStatus status) {
    628     // TODO(hkhalil): Check valid ranges of status?
    629     status_ = status;
    630   }
    631 
    632   virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
    633 
    634  private:
    635   SpdyStreamId last_good_stream_id_;
    636   SpdyGoAwayStatus status_;
    637 
    638   DISALLOW_COPY_AND_ASSIGN(SpdyGoAwayIR);
    639 };
    640 
    641 class SpdyHeadersIR : public SpdyFrameWithNameValueBlockIR {
    642  public:
    643   explicit SpdyHeadersIR(SpdyStreamId stream_id)
    644       : SpdyFrameWithNameValueBlockIR(stream_id) {}
    645 
    646   virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
    647 
    648  private:
    649   DISALLOW_COPY_AND_ASSIGN(SpdyHeadersIR);
    650 };
    651 
    652 class SpdyWindowUpdateIR : public SpdyFrameWithStreamIdIR {
    653  public:
    654   SpdyWindowUpdateIR(SpdyStreamId stream_id, int32 delta)
    655       : SpdyFrameWithStreamIdIR(stream_id) {
    656     set_delta(delta);
    657   }
    658   int32 delta() const { return delta_; }
    659   void set_delta(int32 delta) {
    660     DCHECK_LT(0, delta);
    661     DCHECK_LE(delta, kSpdyMaximumWindowSize);
    662     delta_ = delta;
    663   }
    664 
    665   virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
    666 
    667  private:
    668   int32 delta_;
    669 
    670   DISALLOW_COPY_AND_ASSIGN(SpdyWindowUpdateIR);
    671 };
    672 
    673 class SpdyCredentialIR : public SpdyFrameIR {
    674  public:
    675   typedef std::vector<std::string> CertificateList;
    676 
    677   explicit SpdyCredentialIR(int16 slot);
    678   virtual ~SpdyCredentialIR();
    679 
    680   int16 slot() const { return slot_; }
    681   void set_slot(int16 slot) {
    682     // TODO(hkhalil): Verify valid slot range?
    683     slot_ = slot;
    684   }
    685   base::StringPiece proof() const { return proof_; }
    686   void set_proof(const base::StringPiece& proof) {
    687     proof.CopyToString(&proof_);
    688   }
    689   const CertificateList* certificates() const { return &certificates_; }
    690   void AddCertificate(const base::StringPiece& certificate) {
    691     certificates_.push_back(certificate.as_string());
    692   }
    693 
    694   virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
    695 
    696  private:
    697   int16 slot_;
    698   std::string proof_;
    699   CertificateList certificates_;
    700 
    701   DISALLOW_COPY_AND_ASSIGN(SpdyCredentialIR);
    702 };
    703 
    704 class NET_EXPORT_PRIVATE SpdyBlockedIR
    705     : public NON_EXPORTED_BASE(SpdyFrameWithStreamIdIR) {
    706   public:
    707    explicit SpdyBlockedIR(SpdyStreamId stream_id)
    708        : SpdyFrameWithStreamIdIR(stream_id) {}
    709 
    710   virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
    711 
    712   private:
    713    DISALLOW_COPY_AND_ASSIGN(SpdyBlockedIR);
    714 };
    715 
    716 class SpdyPushPromiseIR : public SpdyFrameWithNameValueBlockIR {
    717  public:
    718   SpdyPushPromiseIR(SpdyStreamId stream_id, SpdyStreamId promised_stream_id)
    719       : SpdyFrameWithNameValueBlockIR(stream_id),
    720         promised_stream_id_(promised_stream_id) {}
    721   SpdyStreamId promised_stream_id() const { return promised_stream_id_; }
    722   void set_promised_stream_id(SpdyStreamId id) { promised_stream_id_ = id; }
    723 
    724   virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
    725 
    726  private:
    727   SpdyStreamId promised_stream_id_;
    728   DISALLOW_COPY_AND_ASSIGN(SpdyPushPromiseIR);
    729 };
    730 
    731 
    732 // -------------------------------------------------------------------------
    733 // Wrapper classes for various SPDY frames.
    734 
    735 // All Spdy Frame types derive from this SpdyFrame class.
    736 class SpdyFrame {
    737  public:
    738   // Create a SpdyFrame using a pre-created buffer.
    739   // If |owns_buffer| is true, this class takes ownership of the buffer
    740   // and will delete it on cleanup.  The buffer must have been created using
    741   // new char[].
    742   // If |owns_buffer| is false, the caller retains ownership of the buffer and
    743   // is responsible for making sure the buffer outlives this frame.  In other
    744   // words, this class does NOT create a copy of the buffer.
    745   SpdyFrame(char* data, size_t size, bool owns_buffer)
    746       : frame_(data),
    747         size_(size),
    748         owns_buffer_(owns_buffer) {
    749     DCHECK(frame_);
    750   }
    751 
    752   ~SpdyFrame() {
    753     if (owns_buffer_) {
    754       delete [] frame_;
    755     }
    756     frame_ = NULL;
    757   }
    758 
    759   // Provides access to the frame bytes, which is a buffer containing
    760   // the frame packed as expected for sending over the wire.
    761   char* data() const { return frame_; }
    762 
    763   // Returns the actual size of the underlying buffer.
    764   size_t size() const { return size_; }
    765 
    766  protected:
    767   char* frame_;
    768 
    769  private:
    770   size_t size_;
    771   bool owns_buffer_;
    772   DISALLOW_COPY_AND_ASSIGN(SpdyFrame);
    773 };
    774 
    775 // This interface is for classes that want to process SpdyFrameIRs without
    776 // having to know what type they are.  An instance of this interface can be
    777 // passed to a SpdyFrameIR's Visit method, and the appropriate type-specific
    778 // method of this class will be called.
    779 class SpdyFrameVisitor {
    780  public:
    781   virtual void VisitSynStream(const SpdySynStreamIR& syn_stream) = 0;
    782   virtual void VisitSynReply(const SpdySynReplyIR& syn_reply) = 0;
    783   virtual void VisitRstStream(const SpdyRstStreamIR& rst_stream) = 0;
    784   virtual void VisitSettings(const SpdySettingsIR& settings) = 0;
    785   virtual void VisitPing(const SpdyPingIR& ping) = 0;
    786   virtual void VisitGoAway(const SpdyGoAwayIR& goaway) = 0;
    787   virtual void VisitHeaders(const SpdyHeadersIR& headers) = 0;
    788   virtual void VisitWindowUpdate(const SpdyWindowUpdateIR& window_update) = 0;
    789   virtual void VisitCredential(const SpdyCredentialIR& credential) = 0;
    790   virtual void VisitBlocked(const SpdyBlockedIR& blocked) = 0;
    791   virtual void VisitPushPromise(const SpdyPushPromiseIR& push_promise) = 0;
    792   virtual void VisitData(const SpdyDataIR& data) = 0;
    793 
    794  protected:
    795   SpdyFrameVisitor() {}
    796   virtual ~SpdyFrameVisitor() {}
    797 
    798  private:
    799   DISALLOW_COPY_AND_ASSIGN(SpdyFrameVisitor);
    800 };
    801 
    802 }  // namespace net
    803 
    804 #endif  // NET_SPDY_SPDY_PROTOCOL_H_
    805