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. 49 const int32 kSpdyStreamInitialWindowSize = 64 * 1024; // 64 KBytes 50 51 // Initial window size for a Spdy session. 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