spdy_protocol.h revision 5821806d5e7f356e8fa4b058a389a808ea183019
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. 6 7#ifndef NET_SPDY_SPDY_PROTOCOL_H_ 8#define NET_SPDY_SPDY_PROTOCOL_H_ 9 10#include <limits> 11 12#include "base/basictypes.h" 13#include "base/logging.h" 14#include "base/sys_byteorder.h" 15#include "net/spdy/spdy_bitmasks.h" 16 17// Data Frame Format 18// +----------------------------------+ 19// |0| Stream-ID (31bits) | 20// +----------------------------------+ 21// | flags (8) | Length (24 bits) | 22// +----------------------------------+ 23// | Data | 24// +----------------------------------+ 25// 26// Control Frame Format 27// +----------------------------------+ 28// |1| Version(15bits) | Type(16bits) | 29// +----------------------------------+ 30// | flags (8) | Length (24 bits) | 31// +----------------------------------+ 32// | Data | 33// +----------------------------------+ 34// 35// Control Frame: SYN_STREAM 36// +----------------------------------+ 37// |1|000000000000001|0000000000000001| 38// +----------------------------------+ 39// | flags (8) | Length (24 bits) | >= 12 40// +----------------------------------+ 41// |X| Stream-ID(31bits) | 42// +----------------------------------+ 43// |X|Associated-To-Stream-ID (31bits)| 44// +----------------------------------+ 45// |Pri| unused | Length (16bits)| 46// +----------------------------------+ 47// 48// Control Frame: SYN_REPLY 49// +----------------------------------+ 50// |1|000000000000001|0000000000000010| 51// +----------------------------------+ 52// | flags (8) | Length (24 bits) | >= 8 53// +----------------------------------+ 54// |X| Stream-ID(31bits) | 55// +----------------------------------+ 56// | unused (16 bits)| Length (16bits)| 57// +----------------------------------+ 58// 59// Control Frame: RST_STREAM 60// +----------------------------------+ 61// |1|000000000000001|0000000000000011| 62// +----------------------------------+ 63// | flags (8) | Length (24 bits) | >= 4 64// +----------------------------------+ 65// |X| Stream-ID(31bits) | 66// +----------------------------------+ 67// | Status code (32 bits) | 68// +----------------------------------+ 69// 70// Control Frame: SETTINGS 71// +----------------------------------+ 72// |1|000000000000001|0000000000000100| 73// +----------------------------------+ 74// | flags (8) | Length (24 bits) | 75// +----------------------------------+ 76// | # of entries (32) | 77// +----------------------------------+ 78// 79// Control Frame: NOOP 80// +----------------------------------+ 81// |1|000000000000001|0000000000000101| 82// +----------------------------------+ 83// | flags (8) | Length (24 bits) | = 0 84// +----------------------------------+ 85// 86// Control Frame: PING 87// +----------------------------------+ 88// |1|000000000000001|0000000000000110| 89// +----------------------------------+ 90// | flags (8) | Length (24 bits) | = 4 91// +----------------------------------+ 92// | Unique id (32 bits) | 93// +----------------------------------+ 94// 95// Control Frame: GOAWAY 96// +----------------------------------+ 97// |1|000000000000001|0000000000000111| 98// +----------------------------------+ 99// | flags (8) | Length (24 bits) | = 4 100// +----------------------------------+ 101// |X| Last-accepted-stream-id | 102// +----------------------------------+ 103// 104// Control Frame: HEADERS 105// +----------------------------------+ 106// |1|000000000000001|0000000000001000| 107// +----------------------------------+ 108// | flags (8) | Length (24 bits) | >= 8 109// +----------------------------------+ 110// |X| Stream-ID (31 bits) | 111// +----------------------------------+ 112// | unused (16 bits)| Length (16bits)| 113// +----------------------------------+ 114// 115// Control Frame: WINDOW_UPDATE 116// +----------------------------------+ 117// |1|000000000000001|0000000000001001| 118// +----------------------------------+ 119// | flags (8) | Length (24 bits) | = 8 120// +----------------------------------+ 121// |X| Stream-ID (31 bits) | 122// +----------------------------------+ 123// | Delta-Window-Size (32 bits) | 124// +----------------------------------+ 125// 126// Control Frame: CREDENTIAL 127// +----------------------------------+ 128// |1|000000000000001|0000000000001010| 129// +----------------------------------+ 130// | flags (8) | Length (24 bits) | >= 12 131// +----------------------------------+ 132// | Slot (16 bits) | | 133// +-----------------+ | 134// | Proof Length (32 bits) | 135// +----------------------------------+ 136// | Proof | 137// +----------------------------------+ <+ 138// | Certificate Length (32 bits) | | 139// +----------------------------------+ | Repeated until end of frame 140// | Certificate | | 141// +----------------------------------+ <+ 142// 143 144namespace net { 145 146// Initial window size for a Spdy stream 147const int32 kSpdyStreamInitialWindowSize = 64 * 1024; // 64 KBytes 148 149// Maximum window size for a Spdy stream 150const int32 kSpdyStreamMaximumWindowSize = 0x7FFFFFFF; // Max signed 32bit int 151 152// SPDY 2 dictionary. 153// This is just a hacked dictionary to use for shrinking HTTP-like headers. 154const char kV2Dictionary[] = 155 "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-" 156 "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi" 157 "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser" 158 "-agent10010120020120220320420520630030130230330430530630740040140240340440" 159 "5406407408409410411412413414415416417500501502503504505accept-rangesageeta" 160 "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic" 161 "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran" 162 "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati" 163 "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo" 164 "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe" 165 "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic" 166 "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1" 167 ".1statusversionurl"; 168const int kV2DictionarySize = arraysize(kV2Dictionary); 169 170// SPDY 3 dictionary. 171const char kV3Dictionary[] = { 172 0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, // ....opti 173 0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, // ons....h 174 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, // ead....p 175 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, // ost....p 176 0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, // ut....de 177 0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, // lete.... 178 0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, // trace... 179 0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, // .accept. 180 0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, // ...accep 181 0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // t-charse 182 0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, // t....acc 183 0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // ept-enco 184 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, // ding.... 185 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, // accept-l 186 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, // anguage. 187 0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, // ...accep 188 0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, // t-ranges 189 0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, // ....age. 190 0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, // ...allow 191 0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, // ....auth 192 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, // orizatio 193 0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, // n....cac 194 0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, // he-contr 195 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, // ol....co 196 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, // nnection 197 0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, // ....cont 198 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, // ent-base 199 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, // ....cont 200 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // ent-enco 201 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, // ding.... 202 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, // content- 203 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, // language 204 0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, // ....cont 205 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, // ent-leng 206 0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, // th....co 207 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, // ntent-lo 208 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, // cation.. 209 0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // ..conten 210 0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, // t-md5... 211 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, // .content 212 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, // -range.. 213 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // ..conten 214 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, // t-type.. 215 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, // ..date.. 216 0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, // ..etag.. 217 0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, // ..expect 218 0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, // ....expi 219 0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, // res....f 220 0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, // rom....h 221 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, // ost....i 222 0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, // f-match. 223 0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, // ...if-mo 224 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, // dified-s 225 0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, // ince.... 226 0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, // if-none- 227 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, // match... 228 0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, // .if-rang 229 0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, // e....if- 230 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, // unmodifi 231 0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, // ed-since 232 0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, // ....last 233 0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, // -modifie 234 0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, // d....loc 235 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, // ation... 236 0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, // .max-for 237 0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, // wards... 238 0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, // .pragma. 239 0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, // ...proxy 240 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, // -authent 241 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, // icate... 242 0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, // .proxy-a 243 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, // uthoriza 244 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, // tion.... 245 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, // range... 246 0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, // .referer 247 0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, // ....retr 248 0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, // y-after. 249 0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, // ...serve 250 0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, // r....te. 251 0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, // ...trail 252 0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, // er....tr 253 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, // ansfer-e 254 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, // ncoding. 255 0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, // ...upgra 256 0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, // de....us 257 0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, // er-agent 258 0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, // ....vary 259 0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, // ....via. 260 0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, // ...warni 261 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, // ng....ww 262 0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, // w-authen 263 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, // ticate.. 264 0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, // ..method 265 0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, // ....get. 266 0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, // ...statu 267 0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, // s....200 268 0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, // .OK....v 269 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, // ersion.. 270 0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, // ..HTTP.1 271 0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, // .1....ur 272 0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, // l....pub 273 0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, // lic....s 274 0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, // et-cooki 275 0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, // e....kee 276 0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, // p-alive. 277 0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, // ...origi 278 0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, // n1001012 279 0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, // 01202205 280 0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, // 20630030 281 0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, // 23033043 282 0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, // 05306307 283 0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, // 40240540 284 0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, // 64074084 285 0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, // 09410411 286 0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, // 41241341 287 0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, // 44154164 288 0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, // 17502504 289 0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, // 505203.N 290 0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, // on-Autho 291 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, // ritative 292 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, // .Informa 293 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, // tion204. 294 0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, // No.Conte 295 0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, // nt301.Mo 296 0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, // ved.Perm 297 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, // anently4 298 0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, // 00.Bad.R 299 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, // equest40 300 0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, // 1.Unauth 301 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, // orized40 302 0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, // 3.Forbid 303 0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, // den404.N 304 0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, // ot.Found 305 0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, // 500.Inte 306 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, // rnal.Ser 307 0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, // ver.Erro 308 0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, // r501.Not 309 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, // .Impleme 310 0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, // nted503. 311 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, // Service. 312 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, // Unavaila 313 0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, // bleJan.F 314 0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, // eb.Mar.A 315 0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, // pr.May.J 316 0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, // un.Jul.A 317 0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, // ug.Sept. 318 0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, // Oct.Nov. 319 0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, // Dec.00.0 320 0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, // 0.00.Mon 321 0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, // ..Tue..W 322 0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, // ed..Thu. 323 0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, // .Fri..Sa 324 0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, // t..Sun.. 325 0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, // GMTchunk 326 0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, // ed.text. 327 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, // html.ima 328 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, // ge.png.i 329 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, // mage.jpg 330 0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, // .image.g 331 0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // if.appli 332 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // cation.x 333 0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // ml.appli 334 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // cation.x 335 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, // html.xml 336 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, // .text.pl 337 0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, // ain.text 338 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, // .javascr 339 0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, // ipt.publ 340 0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, // icprivat 341 0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, // emax-age 342 0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, // .gzip.de 343 0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, // flate.sd 344 0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // chcharse 345 0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, // t.utf-8c 346 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, // harset.i 347 0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, // so-8859- 348 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, // 1.utf-.. 349 0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e // .enq.0. 350}; 351const int kV3DictionarySize = arraysize(kV3Dictionary); 352 353// Note: all protocol data structures are on-the-wire format. That means that 354// data is stored in network-normalized order. Readers must use the 355// accessors provided or call ntohX() functions. 356 357// Types of Spdy Control Frames. 358enum SpdyControlType { 359 SYN_STREAM = 1, 360 SYN_REPLY, 361 RST_STREAM, 362 SETTINGS, 363 NOOP, // Because it is valid in SPDY/2, kept for identifiability/enum order. 364 PING, 365 GOAWAY, 366 HEADERS, 367 WINDOW_UPDATE, 368 CREDENTIAL, 369 NUM_CONTROL_FRAME_TYPES 370}; 371 372// Flags on data packets. 373enum SpdyDataFlags { 374 DATA_FLAG_NONE = 0, 375 DATA_FLAG_FIN = 1, 376}; 377 378// Flags on control packets 379enum SpdyControlFlags { 380 CONTROL_FLAG_NONE = 0, 381 CONTROL_FLAG_FIN = 1, 382 CONTROL_FLAG_UNIDIRECTIONAL = 2 383}; 384 385// Flags on the SETTINGS control frame. 386enum SpdySettingsControlFlags { 387 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS = 0x1 388}; 389 390// Flags for settings within a SETTINGS frame. 391enum SpdySettingsFlags { 392 SETTINGS_FLAG_NONE = 0x0, 393 SETTINGS_FLAG_PLEASE_PERSIST = 0x1, 394 SETTINGS_FLAG_PERSISTED = 0x2 395}; 396 397// List of known settings. 398enum SpdySettingsIds { 399 SETTINGS_UPLOAD_BANDWIDTH = 0x1, 400 SETTINGS_DOWNLOAD_BANDWIDTH = 0x2, 401 // Network round trip time in milliseconds. 402 SETTINGS_ROUND_TRIP_TIME = 0x3, 403 SETTINGS_MAX_CONCURRENT_STREAMS = 0x4, 404 // TCP congestion window in packets. 405 SETTINGS_CURRENT_CWND = 0x5, 406 // Downstream byte retransmission rate in percentage. 407 SETTINGS_DOWNLOAD_RETRANS_RATE = 0x6, 408 // Initial window size in bytes 409 SETTINGS_INITIAL_WINDOW_SIZE = 0x7 410}; 411 412// Status codes, as used in control frames (primarily RST_STREAM). 413// TODO(hkhalil): Rename to SpdyRstStreamStatus 414enum SpdyStatusCodes { 415 INVALID = 0, 416 PROTOCOL_ERROR = 1, 417 INVALID_STREAM = 2, 418 REFUSED_STREAM = 3, 419 UNSUPPORTED_VERSION = 4, 420 CANCEL = 5, 421 INTERNAL_ERROR = 6, 422 FLOW_CONTROL_ERROR = 7, 423 STREAM_IN_USE = 8, 424 STREAM_ALREADY_CLOSED = 9, 425 INVALID_CREDENTIALS = 10, 426 FRAME_TOO_LARGE = 11, 427 NUM_STATUS_CODES = 12 428}; 429 430enum SpdyGoAwayStatus { 431 GOAWAY_INVALID = -1, 432 GOAWAY_OK = 0, 433 GOAWAY_PROTOCOL_ERROR = 1, 434 GOAWAY_INTERNAL_ERROR = 2, 435 GOAWAY_NUM_STATUS_CODES = 3 436}; 437 438// A SPDY stream id is a 31 bit entity. 439typedef uint32 SpdyStreamId; 440 441// A SPDY priority is a number between 0 and 7 (inclusive). 442// SPDY priority range is version-dependant. For SPDY 2 and below, priority is a 443// number between 0 and 3. 444typedef uint8 SpdyPriority; 445 446// ------------------------------------------------------------------------- 447// These structures mirror the protocol structure definitions. 448 449// For the control data structures, we pack so that sizes match the 450// protocol over-the-wire sizes. 451#pragma pack(push) 452#pragma pack(1) 453 454// A special structure for the 8 bit flags and 24 bit length fields. 455union FlagsAndLength { 456 uint8 flags_[4]; // 8 bits 457 uint32 length_; // 24 bits 458}; 459 460// The basic SPDY Frame structure. 461struct SpdyFrameBlock { 462 union { 463 struct { 464 uint16 version_; 465 uint16 type_; 466 } control_; 467 struct { 468 SpdyStreamId stream_id_; 469 } data_; 470 }; 471 FlagsAndLength flags_length_; 472}; 473 474// A SYN_STREAM Control Frame structure. 475struct SpdySynStreamControlFrameBlock : SpdyFrameBlock { 476 SpdyStreamId stream_id_; 477 SpdyStreamId associated_stream_id_; 478 SpdyPriority priority_; 479 uint8 credential_slot_; 480}; 481 482// A SYN_REPLY Control Frame structure. 483struct SpdySynReplyControlFrameBlock : SpdyFrameBlock { 484 SpdyStreamId stream_id_; 485}; 486 487// A RST_STREAM Control Frame structure. 488struct SpdyRstStreamControlFrameBlock : SpdyFrameBlock { 489 SpdyStreamId stream_id_; 490 uint32 status_; 491}; 492 493// A SETTINGS Control Frame structure. 494struct SpdySettingsControlFrameBlock : SpdyFrameBlock { 495 uint32 num_entries_; 496 // Variable data here. 497}; 498 499// A PING Control Frame structure. 500struct SpdyPingControlFrameBlock : SpdyFrameBlock { 501 uint32 unique_id_; 502}; 503 504// TODO(avd): remove this struct 505// A CREDENTIAL Control Frame structure. 506struct SpdyCredentialControlFrameBlock : SpdyFrameBlock { 507 uint16 slot_; 508 uint32 proof_len_; 509 // Variable data here. 510 // proof data 511 // for each certificate: unit32 certificate_len + certificate_data[i] 512}; 513 514// A GOAWAY Control Frame structure. 515struct SpdyGoAwayControlFrameBlock : SpdyFrameBlock { 516 SpdyStreamId last_accepted_stream_id_; 517 SpdyGoAwayStatus status_; 518}; 519 520// A HEADERS Control Frame structure. 521struct SpdyHeadersControlFrameBlock : SpdyFrameBlock { 522 SpdyStreamId stream_id_; 523}; 524 525// A WINDOW_UPDATE Control Frame structure 526struct SpdyWindowUpdateControlFrameBlock : SpdyFrameBlock { 527 SpdyStreamId stream_id_; 528 uint32 delta_window_size_; 529}; 530 531#pragma pack(pop) 532 533// ------------------------------------------------------------------------- 534// Wrapper classes for various SPDY frames. 535 536// All Spdy Frame types derive from this SpdyFrame class. 537class SpdyFrame { 538 public: 539 // Create a SpdyFrame for a given sized buffer. 540 explicit SpdyFrame(size_t size) : frame_(NULL), owns_buffer_(true) { 541 DCHECK_GE(size, sizeof(struct SpdyFrameBlock)); 542 char* buffer = new char[size]; 543 memset(buffer, 0, size); 544 frame_ = reinterpret_cast<struct SpdyFrameBlock*>(buffer); 545 } 546 547 // Create a SpdyFrame using a pre-created buffer. 548 // If |owns_buffer| is true, this class takes ownership of the buffer 549 // and will delete it on cleanup. The buffer must have been created using 550 // new char[]. 551 // If |owns_buffer| is false, the caller retains ownership of the buffer and 552 // is responsible for making sure the buffer outlives this frame. In other 553 // words, this class does NOT create a copy of the buffer. 554 SpdyFrame(char* data, bool owns_buffer) 555 : frame_(reinterpret_cast<struct SpdyFrameBlock*>(data)), 556 owns_buffer_(owns_buffer) { 557 DCHECK(frame_); 558 } 559 560 ~SpdyFrame() { 561 if (owns_buffer_) { 562 char* buffer = reinterpret_cast<char*>(frame_); 563 delete [] buffer; 564 } 565 frame_ = NULL; 566 } 567 568 // Provides access to the frame bytes, which is a buffer containing 569 // the frame packed as expected for sending over the wire. 570 char* data() const { return reinterpret_cast<char*>(frame_); } 571 572 uint8 flags() const { return frame_->flags_length_.flags_[0]; } 573 void set_flags(uint8 flags) { frame_->flags_length_.flags_[0] = flags; } 574 575 uint32 length() const { 576 return ntohl(frame_->flags_length_.length_) & kLengthMask; 577 } 578 579 void set_length(uint32 length) { 580 DCHECK_EQ(0u, (length & ~kLengthMask)); 581 length = htonl(length & kLengthMask); 582 frame_->flags_length_.length_ = flags() | length; 583 } 584 585 bool is_control_frame() const { 586 return (ntohs(frame_->control_.version_) & kControlFlagMask) == 587 kControlFlagMask; 588 } 589 590 // The size of the SpdyFrameBlock structure. 591 // Every SpdyFrame* class has a static size() method for accessing 592 // the size of the data structure which will be sent over the wire. 593 // Note: this is not the same as sizeof(SpdyFrame). 594 enum { kHeaderSize = sizeof(struct SpdyFrameBlock) }; 595 596 protected: 597 SpdyFrameBlock* frame_; 598 599 private: 600 bool owns_buffer_; 601 DISALLOW_COPY_AND_ASSIGN(SpdyFrame); 602}; 603 604// A Data Frame. 605class SpdyDataFrame : public SpdyFrame { 606 public: 607 SpdyDataFrame() : SpdyFrame(size()) {} 608 SpdyDataFrame(char* data, bool owns_buffer) 609 : SpdyFrame(data, owns_buffer) {} 610 611 SpdyStreamId stream_id() const { 612 return ntohl(frame_->data_.stream_id_) & kStreamIdMask; 613 } 614 615 // Note that setting the stream id sets the control bit to false. 616 // As stream id should always be set, this means the control bit 617 // should always be set correctly. 618 void set_stream_id(SpdyStreamId id) { 619 DCHECK_EQ(0u, (id & ~kStreamIdMask)); 620 frame_->data_.stream_id_ = htonl(id & kStreamIdMask); 621 } 622 623 // Returns the size of the SpdyFrameBlock structure. 624 // Note: this is not the size of the SpdyDataFrame class. 625 static size_t size() { return SpdyFrame::kHeaderSize; } 626 627 const char* payload() const { 628 return reinterpret_cast<const char*>(frame_) + size(); 629 } 630 631 private: 632 DISALLOW_COPY_AND_ASSIGN(SpdyDataFrame); 633}; 634 635// A Control Frame. 636class SpdyControlFrame : public SpdyFrame { 637 public: 638 explicit SpdyControlFrame(size_t size) : SpdyFrame(size) {} 639 SpdyControlFrame(char* data, bool owns_buffer) 640 : SpdyFrame(data, owns_buffer) {} 641 642 // Callers can use this method to check if the frame appears to be a valid 643 // frame. Does not guarantee that there are no errors. 644 bool AppearsToBeAValidControlFrame() const { 645 // Right now we only check if the frame has an out-of-bounds type. 646 uint16 type = ntohs(block()->control_.type_); 647 // NOOP is not a 'valid' control frame in SPDY/3 and beyond. 648 return type >= SYN_STREAM && 649 type < NUM_CONTROL_FRAME_TYPES && 650 (version() == 2 || type != NOOP); 651 } 652 653 uint16 version() const { 654 const int kVersionMask = 0x7fff; 655 return ntohs(block()->control_.version_) & kVersionMask; 656 } 657 658 void set_version(uint16 version) { 659 const uint16 kControlBit = 0x80; 660 DCHECK_EQ(0, version & kControlBit); 661 mutable_block()->control_.version_ = kControlBit | htons(version); 662 } 663 664 SpdyControlType type() const { 665 uint16 type = ntohs(block()->control_.type_); 666 LOG_IF(DFATAL, type < SYN_STREAM || type >= NUM_CONTROL_FRAME_TYPES) 667 << "Invalid control frame type " << type; 668 return static_cast<SpdyControlType>(type); 669 } 670 671 void set_type(SpdyControlType type) { 672 DCHECK(type >= SYN_STREAM && type < NUM_CONTROL_FRAME_TYPES); 673 mutable_block()->control_.type_ = htons(type); 674 } 675 676 // Returns true if this control frame is of a type that has a header block, 677 // otherwise it returns false. 678 bool has_header_block() const { 679 return type() == SYN_STREAM || type() == SYN_REPLY || type() == HEADERS; 680 } 681 682 private: 683 const struct SpdyFrameBlock* block() const { 684 return frame_; 685 } 686 struct SpdyFrameBlock* mutable_block() { 687 return frame_; 688 } 689 DISALLOW_COPY_AND_ASSIGN(SpdyControlFrame); 690}; 691 692// A SYN_STREAM frame. 693class SpdySynStreamControlFrame : public SpdyControlFrame { 694 public: 695 SpdySynStreamControlFrame() : SpdyControlFrame(size()) {} 696 SpdySynStreamControlFrame(char* data, bool owns_buffer) 697 : SpdyControlFrame(data, owns_buffer) {} 698 699 SpdyStreamId stream_id() const { 700 return ntohl(block()->stream_id_) & kStreamIdMask; 701 } 702 703 void set_stream_id(SpdyStreamId id) { 704 mutable_block()->stream_id_ = htonl(id & kStreamIdMask); 705 } 706 707 SpdyStreamId associated_stream_id() const { 708 return ntohl(block()->associated_stream_id_) & kStreamIdMask; 709 } 710 711 void set_associated_stream_id(SpdyStreamId id) { 712 mutable_block()->associated_stream_id_ = htonl(id & kStreamIdMask); 713 } 714 715 SpdyPriority priority() const { 716 if (version() < 3) { 717 return (block()->priority_ & kSpdy2PriorityMask) >> 6; 718 } else { 719 return (block()->priority_ & kSpdy3PriorityMask) >> 5; 720 } 721 } 722 723 uint8 credential_slot() const { 724 if (version() < 3) { 725 return 0; 726 } else { 727 return block()->credential_slot_; 728 } 729 } 730 731 void set_credential_slot(uint8 credential_slot) { 732 DCHECK(version() >= 3); 733 mutable_block()->credential_slot_ = credential_slot; 734 } 735 736 // The number of bytes in the header block beyond the frame header length. 737 int header_block_len() const { 738 return length() - (size() - SpdyFrame::kHeaderSize); 739 } 740 741 const char* header_block() const { 742 return reinterpret_cast<const char*>(block()) + size(); 743 } 744 745 // Returns the size of the SpdySynStreamControlFrameBlock structure. 746 // Note: this is not the size of the SpdySynStreamControlFrame class. 747 static size_t size() { return sizeof(SpdySynStreamControlFrameBlock); } 748 749 private: 750 const struct SpdySynStreamControlFrameBlock* block() const { 751 return static_cast<SpdySynStreamControlFrameBlock*>(frame_); 752 } 753 struct SpdySynStreamControlFrameBlock* mutable_block() { 754 return static_cast<SpdySynStreamControlFrameBlock*>(frame_); 755 } 756 DISALLOW_COPY_AND_ASSIGN(SpdySynStreamControlFrame); 757}; 758 759// A SYN_REPLY frame. 760class SpdySynReplyControlFrame : public SpdyControlFrame { 761 public: 762 SpdySynReplyControlFrame() : SpdyControlFrame(size()) {} 763 SpdySynReplyControlFrame(char* data, bool owns_buffer) 764 : SpdyControlFrame(data, owns_buffer) {} 765 766 SpdyStreamId stream_id() const { 767 return ntohl(block()->stream_id_) & kStreamIdMask; 768 } 769 770 void set_stream_id(SpdyStreamId id) { 771 mutable_block()->stream_id_ = htonl(id & kStreamIdMask); 772 } 773 774 int header_block_len() const { 775 size_t header_block_len = length() - (size() - SpdyFrame::kHeaderSize); 776 // SPDY 2 had 2 bytes of unused space preceeding the header block. 777 if (version() < 3) { 778 header_block_len -= 2; 779 } 780 return header_block_len; 781 } 782 783 const char* header_block() const { 784 const char* header_block = reinterpret_cast<const char*>(block()) + size(); 785 // SPDY 2 had 2 bytes of unused space preceeding the header block. 786 if (version() < 3) { 787 header_block += 2; 788 } 789 return header_block; 790 } 791 792 // Returns the size of the SpdySynReplyControlFrameBlock structure. 793 // Note: this is not the size of the SpdySynReplyControlFrame class. 794 static size_t size() { return sizeof(SpdySynReplyControlFrameBlock); } 795 796 private: 797 const struct SpdySynReplyControlFrameBlock* block() const { 798 return static_cast<SpdySynReplyControlFrameBlock*>(frame_); 799 } 800 struct SpdySynReplyControlFrameBlock* mutable_block() { 801 return static_cast<SpdySynReplyControlFrameBlock*>(frame_); 802 } 803 DISALLOW_COPY_AND_ASSIGN(SpdySynReplyControlFrame); 804}; 805 806// A RST_STREAM frame. 807class SpdyRstStreamControlFrame : public SpdyControlFrame { 808 public: 809 SpdyRstStreamControlFrame() : SpdyControlFrame(size()) {} 810 SpdyRstStreamControlFrame(char* data, bool owns_buffer) 811 : SpdyControlFrame(data, owns_buffer) {} 812 813 SpdyStreamId stream_id() const { 814 return ntohl(block()->stream_id_) & kStreamIdMask; 815 } 816 817 void set_stream_id(SpdyStreamId id) { 818 mutable_block()->stream_id_ = htonl(id & kStreamIdMask); 819 } 820 821 SpdyStatusCodes status() const { 822 SpdyStatusCodes status = 823 static_cast<SpdyStatusCodes>(ntohl(block()->status_)); 824 if (status < INVALID || status >= NUM_STATUS_CODES) { 825 status = INVALID; 826 } 827 return status; 828 } 829 void set_status(SpdyStatusCodes status) { 830 mutable_block()->status_ = htonl(static_cast<uint32>(status)); 831 } 832 833 // Returns the size of the SpdyRstStreamControlFrameBlock structure. 834 // Note: this is not the size of the SpdyRstStreamControlFrame class. 835 static size_t size() { return sizeof(SpdyRstStreamControlFrameBlock); } 836 837 private: 838 const struct SpdyRstStreamControlFrameBlock* block() const { 839 return static_cast<SpdyRstStreamControlFrameBlock*>(frame_); 840 } 841 struct SpdyRstStreamControlFrameBlock* mutable_block() { 842 return static_cast<SpdyRstStreamControlFrameBlock*>(frame_); 843 } 844 DISALLOW_COPY_AND_ASSIGN(SpdyRstStreamControlFrame); 845}; 846 847class SpdySettingsControlFrame : public SpdyControlFrame { 848 public: 849 SpdySettingsControlFrame() : SpdyControlFrame(size()) {} 850 SpdySettingsControlFrame(char* data, bool owns_buffer) 851 : SpdyControlFrame(data, owns_buffer) {} 852 853 uint32 num_entries() const { 854 return ntohl(block()->num_entries_); 855 } 856 857 void set_num_entries(int val) { 858 mutable_block()->num_entries_ = htonl(val); 859 } 860 861 int header_block_len() const { 862 return length() - (size() - SpdyFrame::kHeaderSize); 863 } 864 865 const char* header_block() const { 866 return reinterpret_cast<const char*>(block()) + size(); 867 } 868 869 // Returns the size of the SpdySettingsControlFrameBlock structure. 870 // Note: this is not the size of the SpdySettingsControlFrameBlock class. 871 static size_t size() { return sizeof(SpdySettingsControlFrameBlock); } 872 873 private: 874 const struct SpdySettingsControlFrameBlock* block() const { 875 return static_cast<SpdySettingsControlFrameBlock*>(frame_); 876 } 877 struct SpdySettingsControlFrameBlock* mutable_block() { 878 return static_cast<SpdySettingsControlFrameBlock*>(frame_); 879 } 880 DISALLOW_COPY_AND_ASSIGN(SpdySettingsControlFrame); 881}; 882 883class SpdyPingControlFrame : public SpdyControlFrame { 884 public: 885 SpdyPingControlFrame() : SpdyControlFrame(size()) {} 886 SpdyPingControlFrame(char* data, bool owns_buffer) 887 : SpdyControlFrame(data, owns_buffer) {} 888 889 uint32 unique_id() const { 890 return ntohl(block()->unique_id_); 891 } 892 893 void set_unique_id(uint32 unique_id) { 894 mutable_block()->unique_id_ = htonl(unique_id); 895 } 896 897 static size_t size() { return sizeof(SpdyPingControlFrameBlock); } 898 899 private: 900 const struct SpdyPingControlFrameBlock* block() const { 901 return static_cast<SpdyPingControlFrameBlock*>(frame_); 902 } 903 struct SpdyPingControlFrameBlock* mutable_block() { 904 return static_cast<SpdyPingControlFrameBlock*>(frame_); 905 } 906}; 907 908class SpdyCredentialControlFrame : public SpdyControlFrame { 909 public: 910 SpdyCredentialControlFrame() : SpdyControlFrame(size()) {} 911 SpdyCredentialControlFrame(char* data, bool owns_buffer) 912 : SpdyControlFrame(data, owns_buffer) {} 913 914 const char* payload() const { 915 return reinterpret_cast<const char*>(block()) + SpdyFrame::kHeaderSize; 916 } 917 918 static size_t size() { return sizeof(SpdyCredentialControlFrameBlock); } 919 920 private: 921 const struct SpdyCredentialControlFrameBlock* block() const { 922 return static_cast<SpdyCredentialControlFrameBlock*>(frame_); 923 } 924 DISALLOW_COPY_AND_ASSIGN(SpdyCredentialControlFrame); 925}; 926 927class SpdyGoAwayControlFrame : public SpdyControlFrame { 928 public: 929 SpdyGoAwayControlFrame() : SpdyControlFrame(size()) {} 930 SpdyGoAwayControlFrame(char* data, bool owns_buffer) 931 : SpdyControlFrame(data, owns_buffer) {} 932 933 SpdyStreamId last_accepted_stream_id() const { 934 return ntohl(block()->last_accepted_stream_id_) & kStreamIdMask; 935 } 936 937 SpdyGoAwayStatus status() const { 938 if (version() < 3) { 939 LOG(DFATAL) << "Attempted to access status of SPDY 2 GOAWAY."; 940 return GOAWAY_INVALID; 941 } else { 942 uint32 status = ntohl(block()->status_); 943 if (status >= GOAWAY_NUM_STATUS_CODES) { 944 return GOAWAY_INVALID; 945 } else { 946 return static_cast<SpdyGoAwayStatus>(status); 947 } 948 } 949 } 950 951 void set_last_accepted_stream_id(SpdyStreamId id) { 952 mutable_block()->last_accepted_stream_id_ = htonl(id & kStreamIdMask); 953 } 954 955 static size_t size() { return sizeof(SpdyGoAwayControlFrameBlock); } 956 957 private: 958 const struct SpdyGoAwayControlFrameBlock* block() const { 959 return static_cast<SpdyGoAwayControlFrameBlock*>(frame_); 960 } 961 struct SpdyGoAwayControlFrameBlock* mutable_block() { 962 return static_cast<SpdyGoAwayControlFrameBlock*>(frame_); 963 } 964 DISALLOW_COPY_AND_ASSIGN(SpdyGoAwayControlFrame); 965}; 966 967// A HEADERS frame. 968class SpdyHeadersControlFrame : public SpdyControlFrame { 969 public: 970 SpdyHeadersControlFrame() : SpdyControlFrame(size()) {} 971 SpdyHeadersControlFrame(char* data, bool owns_buffer) 972 : SpdyControlFrame(data, owns_buffer) {} 973 974 SpdyStreamId stream_id() const { 975 return ntohl(block()->stream_id_) & kStreamIdMask; 976 } 977 978 void set_stream_id(SpdyStreamId id) { 979 mutable_block()->stream_id_ = htonl(id & kStreamIdMask); 980 } 981 982 // The number of bytes in the header block beyond the frame header length. 983 int header_block_len() const { 984 size_t header_block_len = length() - (size() - SpdyFrame::kHeaderSize); 985 // SPDY 2 had 2 bytes of unused space preceeding the header block. 986 if (version() < 3) { 987 header_block_len -= 2; 988 } 989 return header_block_len; 990 } 991 992 const char* header_block() const { 993 const char* header_block = reinterpret_cast<const char*>(block()) + size(); 994 // SPDY 2 had 2 bytes of unused space preceeding the header block. 995 if (version() < 3) { 996 header_block += 2; 997 } 998 return header_block; 999 } 1000 1001 // Returns the size of the SpdyHeadersControlFrameBlock structure. 1002 // Note: this is not the size of the SpdyHeadersControlFrame class. 1003 static size_t size() { return sizeof(SpdyHeadersControlFrameBlock); } 1004 1005 private: 1006 const struct SpdyHeadersControlFrameBlock* block() const { 1007 return static_cast<SpdyHeadersControlFrameBlock*>(frame_); 1008 } 1009 struct SpdyHeadersControlFrameBlock* mutable_block() { 1010 return static_cast<SpdyHeadersControlFrameBlock*>(frame_); 1011 } 1012 DISALLOW_COPY_AND_ASSIGN(SpdyHeadersControlFrame); 1013}; 1014 1015// A WINDOW_UPDATE frame. 1016class SpdyWindowUpdateControlFrame : public SpdyControlFrame { 1017 public: 1018 SpdyWindowUpdateControlFrame() : SpdyControlFrame(size()) {} 1019 SpdyWindowUpdateControlFrame(char* data, bool owns_buffer) 1020 : SpdyControlFrame(data, owns_buffer) {} 1021 1022 SpdyStreamId stream_id() const { 1023 return ntohl(block()->stream_id_) & kStreamIdMask; 1024 } 1025 1026 void set_stream_id(SpdyStreamId id) { 1027 mutable_block()->stream_id_ = htonl(id & kStreamIdMask); 1028 } 1029 1030 uint32 delta_window_size() const { 1031 return ntohl(block()->delta_window_size_); 1032 } 1033 1034 void set_delta_window_size(uint32 delta_window_size) { 1035 mutable_block()->delta_window_size_ = htonl(delta_window_size); 1036 } 1037 1038 // Returns the size of the SpdyWindowUpdateControlFrameBlock structure. 1039 // Note: this is not the size of the SpdyWindowUpdateControlFrame class. 1040 static size_t size() { return sizeof(SpdyWindowUpdateControlFrameBlock); } 1041 1042 private: 1043 const struct SpdyWindowUpdateControlFrameBlock* block() const { 1044 return static_cast<SpdyWindowUpdateControlFrameBlock*>(frame_); 1045 } 1046 struct SpdyWindowUpdateControlFrameBlock* mutable_block() { 1047 return static_cast<SpdyWindowUpdateControlFrameBlock*>(frame_); 1048 } 1049 1050 DISALLOW_COPY_AND_ASSIGN(SpdyWindowUpdateControlFrame); 1051}; 1052 1053} // namespace net 1054 1055#endif // NET_SPDY_SPDY_PROTOCOL_H_ 1056