blob: 30daee3a887d2828a835eaf47d1bf54d79bec36c [file] [log] [blame] [edit]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file contains some protocol structures for use with Spdy.
#ifndef NET_SPDY_SPDY_PROTOCOL_H_
#define NET_SPDY_SPDY_PROTOCOL_H_
#include <limits>
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/sys_byteorder.h"
#include "net/spdy/spdy_bitmasks.h"
// Data Frame Format
// +----------------------------------+
// |0| Stream-ID (31bits) |
// +----------------------------------+
// | flags (8) | Length (24 bits) |
// +----------------------------------+
// | Data |
// +----------------------------------+
//
// Control Frame Format
// +----------------------------------+
// |1| Version(15bits) | Type(16bits) |
// +----------------------------------+
// | flags (8) | Length (24 bits) |
// +----------------------------------+
// | Data |
// +----------------------------------+
//
// Control Frame: SYN_STREAM
// +----------------------------------+
// |1|000000000000001|0000000000000001|
// +----------------------------------+
// | flags (8) | Length (24 bits) | >= 12
// +----------------------------------+
// |X| Stream-ID(31bits) |
// +----------------------------------+
// |X|Associated-To-Stream-ID (31bits)|
// +----------------------------------+
// |Pri| unused | Length (16bits)|
// +----------------------------------+
//
// Control Frame: SYN_REPLY
// +----------------------------------+
// |1|000000000000001|0000000000000010|
// +----------------------------------+
// | flags (8) | Length (24 bits) | >= 8
// +----------------------------------+
// |X| Stream-ID(31bits) |
// +----------------------------------+
// | unused (16 bits)| Length (16bits)|
// +----------------------------------+
//
// Control Frame: RST_STREAM
// +----------------------------------+
// |1|000000000000001|0000000000000011|
// +----------------------------------+
// | flags (8) | Length (24 bits) | >= 4
// +----------------------------------+
// |X| Stream-ID(31bits) |
// +----------------------------------+
// | Status code (32 bits) |
// +----------------------------------+
//
// Control Frame: SETTINGS
// +----------------------------------+
// |1|000000000000001|0000000000000100|
// +----------------------------------+
// | flags (8) | Length (24 bits) |
// +----------------------------------+
// | # of entries (32) |
// +----------------------------------+
//
// Control Frame: NOOP
// +----------------------------------+
// |1|000000000000001|0000000000000101|
// +----------------------------------+
// | flags (8) | Length (24 bits) | = 0
// +----------------------------------+
//
// Control Frame: PING
// +----------------------------------+
// |1|000000000000001|0000000000000110|
// +----------------------------------+
// | flags (8) | Length (24 bits) | = 4
// +----------------------------------+
// | Unique id (32 bits) |
// +----------------------------------+
//
// Control Frame: GOAWAY
// +----------------------------------+
// |1|000000000000001|0000000000000111|
// +----------------------------------+
// | flags (8) | Length (24 bits) | = 4
// +----------------------------------+
// |X| Last-accepted-stream-id |
// +----------------------------------+
//
// Control Frame: HEADERS
// +----------------------------------+
// |1|000000000000001|0000000000001000|
// +----------------------------------+
// | flags (8) | Length (24 bits) | >= 8
// +----------------------------------+
// |X| Stream-ID (31 bits) |
// +----------------------------------+
// | unused (16 bits)| Length (16bits)|
// +----------------------------------+
//
// Control Frame: WINDOW_UPDATE
// +----------------------------------+
// |1|000000000000001|0000000000001001|
// +----------------------------------+
// | flags (8) | Length (24 bits) | = 8
// +----------------------------------+
// |X| Stream-ID (31 bits) |
// +----------------------------------+
// | Delta-Window-Size (32 bits) |
// +----------------------------------+
//
// Control Frame: CREDENTIAL
// +----------------------------------+
// |1|000000000000001|0000000000001010|
// +----------------------------------+
// | flags (8) | Length (24 bits) | >= 12
// +----------------------------------+
// | Slot (16 bits) | |
// +-----------------+ |
// | Proof Length (32 bits) |
// +----------------------------------+
// | Proof |
// +----------------------------------+ <+
// | Certificate Length (32 bits) | |
// +----------------------------------+ | Repeated until end of frame
// | Certificate | |
// +----------------------------------+ <+
//
namespace net {
// Initial window size for a Spdy stream
const int32 kSpdyStreamInitialWindowSize = 64 * 1024; // 64 KBytes
// Maximum window size for a Spdy stream
const int32 kSpdyStreamMaximumWindowSize = 0x7FFFFFFF; // Max signed 32bit int
// SPDY 2 dictionary.
// This is just a hacked dictionary to use for shrinking HTTP-like headers.
const char kV2Dictionary[] =
"optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-"
"languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi"
"f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser"
"-agent10010120020120220320420520630030130230330430530630740040140240340440"
"5406407408409410411412413414415416417500501502503504505accept-rangesageeta"
"glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic"
"ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran"
"sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati"
"oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo"
"ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe"
"pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic"
"ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1"
".1statusversionurl";
const int kV2DictionarySize = arraysize(kV2Dictionary);
// SPDY 3 dictionary.
const char kV3Dictionary[] = {
0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, // ....opti
0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, // ons....h
0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, // ead....p
0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, // ost....p
0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, // ut....de
0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, // lete....
0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, // trace...
0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, // .accept.
0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, // ...accep
0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // t-charse
0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, // t....acc
0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // ept-enco
0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, // ding....
0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, // accept-l
0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, // anguage.
0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, // ...accep
0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, // t-ranges
0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, // ....age.
0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, // ...allow
0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, // ....auth
0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, // orizatio
0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, // n....cac
0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, // he-contr
0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, // ol....co
0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, // nnection
0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, // ....cont
0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, // ent-base
0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, // ....cont
0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // ent-enco
0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, // ding....
0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, // content-
0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, // language
0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, // ....cont
0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, // ent-leng
0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, // th....co
0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, // ntent-lo
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, // cation..
0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // ..conten
0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, // t-md5...
0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, // .content
0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, // -range..
0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // ..conten
0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, // t-type..
0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, // ..date..
0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, // ..etag..
0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, // ..expect
0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, // ....expi
0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, // res....f
0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, // rom....h
0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, // ost....i
0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, // f-match.
0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, // ...if-mo
0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, // dified-s
0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, // ince....
0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, // if-none-
0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, // match...
0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, // .if-rang
0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, // e....if-
0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, // unmodifi
0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, // ed-since
0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, // ....last
0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, // -modifie
0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, // d....loc
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, // ation...
0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, // .max-for
0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, // wards...
0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, // .pragma.
0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, // ...proxy
0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, // -authent
0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, // icate...
0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, // .proxy-a
0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, // uthoriza
0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, // tion....
0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, // range...
0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, // .referer
0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, // ....retr
0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, // y-after.
0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, // ...serve
0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, // r....te.
0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, // ...trail
0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, // er....tr
0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, // ansfer-e
0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, // ncoding.
0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, // ...upgra
0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, // de....us
0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, // er-agent
0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, // ....vary
0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, // ....via.
0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, // ...warni
0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, // ng....ww
0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, // w-authen
0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, // ticate..
0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, // ..method
0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, // ....get.
0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, // ...statu
0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, // s....200
0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, // .OK....v
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, // ersion..
0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, // ..HTTP.1
0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, // .1....ur
0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, // l....pub
0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, // lic....s
0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, // et-cooki
0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, // e....kee
0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, // p-alive.
0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, // ...origi
0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, // n1001012
0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, // 01202205
0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, // 20630030
0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, // 23033043
0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, // 05306307
0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, // 40240540
0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, // 64074084
0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, // 09410411
0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, // 41241341
0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, // 44154164
0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, // 17502504
0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, // 505203.N
0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, // on-Autho
0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, // ritative
0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, // .Informa
0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, // tion204.
0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, // No.Conte
0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, // nt301.Mo
0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, // ved.Perm
0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, // anently4
0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, // 00.Bad.R
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, // equest40
0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, // 1.Unauth
0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, // orized40
0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, // 3.Forbid
0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, // den404.N
0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, // ot.Found
0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, // 500.Inte
0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, // rnal.Ser
0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, // ver.Erro
0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, // r501.Not
0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, // .Impleme
0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, // nted503.
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, // Service.
0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, // Unavaila
0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, // bleJan.F
0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, // eb.Mar.A
0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, // pr.May.J
0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, // un.Jul.A
0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, // ug.Sept.
0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, // Oct.Nov.
0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, // Dec.00.0
0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, // 0.00.Mon
0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, // ..Tue..W
0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, // ed..Thu.
0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, // .Fri..Sa
0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, // t..Sun..
0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, // GMTchunk
0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, // ed.text.
0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, // html.ima
0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, // ge.png.i
0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, // mage.jpg
0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, // .image.g
0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // if.appli
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // cation.x
0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // ml.appli
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // cation.x
0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, // html.xml
0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, // .text.pl
0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, // ain.text
0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, // .javascr
0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, // ipt.publ
0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, // icprivat
0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, // emax-age
0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, // .gzip.de
0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, // flate.sd
0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // chcharse
0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, // t.utf-8c
0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, // harset.i
0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, // so-8859-
0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, // 1.utf-..
0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e // .enq.0.
};
const int kV3DictionarySize = arraysize(kV3Dictionary);
// Note: all protocol data structures are on-the-wire format. That means that
// data is stored in network-normalized order. Readers must use the
// accessors provided or call ntohX() functions.
// Types of Spdy Control Frames.
enum SpdyControlType {
SYN_STREAM = 1,
SYN_REPLY,
RST_STREAM,
SETTINGS,
NOOP, // Because it is valid in SPDY/2, kept for identifiability/enum order.
PING,
GOAWAY,
HEADERS,
WINDOW_UPDATE,
CREDENTIAL,
NUM_CONTROL_FRAME_TYPES
};
// Flags on data packets.
enum SpdyDataFlags {
DATA_FLAG_NONE = 0,
DATA_FLAG_FIN = 1,
};
// Flags on control packets
enum SpdyControlFlags {
CONTROL_FLAG_NONE = 0,
CONTROL_FLAG_FIN = 1,
CONTROL_FLAG_UNIDIRECTIONAL = 2
};
// Flags on the SETTINGS control frame.
enum SpdySettingsControlFlags {
SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS = 0x1
};
// Flags for settings within a SETTINGS frame.
enum SpdySettingsFlags {
SETTINGS_FLAG_NONE = 0x0,
SETTINGS_FLAG_PLEASE_PERSIST = 0x1,
SETTINGS_FLAG_PERSISTED = 0x2
};
// List of known settings.
enum SpdySettingsIds {
SETTINGS_UPLOAD_BANDWIDTH = 0x1,
SETTINGS_DOWNLOAD_BANDWIDTH = 0x2,
// Network round trip time in milliseconds.
SETTINGS_ROUND_TRIP_TIME = 0x3,
SETTINGS_MAX_CONCURRENT_STREAMS = 0x4,
// TCP congestion window in packets.
SETTINGS_CURRENT_CWND = 0x5,
// Downstream byte retransmission rate in percentage.
SETTINGS_DOWNLOAD_RETRANS_RATE = 0x6,
// Initial window size in bytes
SETTINGS_INITIAL_WINDOW_SIZE = 0x7
};
// Status codes, as used in control frames (primarily RST_STREAM).
// TODO(hkhalil): Rename to SpdyRstStreamStatus
enum SpdyStatusCodes {
INVALID = 0,
PROTOCOL_ERROR = 1,
INVALID_STREAM = 2,
REFUSED_STREAM = 3,
UNSUPPORTED_VERSION = 4,
CANCEL = 5,
INTERNAL_ERROR = 6,
FLOW_CONTROL_ERROR = 7,
STREAM_IN_USE = 8,
STREAM_ALREADY_CLOSED = 9,
INVALID_CREDENTIALS = 10,
FRAME_TOO_LARGE = 11,
NUM_STATUS_CODES = 12
};
enum SpdyGoAwayStatus {
GOAWAY_INVALID = -1,
GOAWAY_OK = 0,
GOAWAY_PROTOCOL_ERROR = 1,
GOAWAY_INTERNAL_ERROR = 2,
GOAWAY_NUM_STATUS_CODES = 3
};
// A SPDY stream id is a 31 bit entity.
typedef uint32 SpdyStreamId;
// A SPDY priority is a number between 0 and 7 (inclusive).
// SPDY priority range is version-dependant. For SPDY 2 and below, priority is a
// number between 0 and 3.
typedef uint8 SpdyPriority;
// -------------------------------------------------------------------------
// These structures mirror the protocol structure definitions.
// For the control data structures, we pack so that sizes match the
// protocol over-the-wire sizes.
#pragma pack(push)
#pragma pack(1)
// A special structure for the 8 bit flags and 24 bit length fields.
union FlagsAndLength {
uint8 flags_[4]; // 8 bits
uint32 length_; // 24 bits
};
// The basic SPDY Frame structure.
struct SpdyFrameBlock {
union {
struct {
uint16 version_;
uint16 type_;
} control_;
struct {
SpdyStreamId stream_id_;
} data_;
};
FlagsAndLength flags_length_;
};
// A SYN_STREAM Control Frame structure.
struct SpdySynStreamControlFrameBlock : SpdyFrameBlock {
SpdyStreamId stream_id_;
SpdyStreamId associated_stream_id_;
SpdyPriority priority_;
uint8 credential_slot_;
};
// A SYN_REPLY Control Frame structure.
struct SpdySynReplyControlFrameBlock : SpdyFrameBlock {
SpdyStreamId stream_id_;
};
// A RST_STREAM Control Frame structure.
struct SpdyRstStreamControlFrameBlock : SpdyFrameBlock {
SpdyStreamId stream_id_;
uint32 status_;
};
// A SETTINGS Control Frame structure.
struct SpdySettingsControlFrameBlock : SpdyFrameBlock {
uint32 num_entries_;
// Variable data here.
};
// A PING Control Frame structure.
struct SpdyPingControlFrameBlock : SpdyFrameBlock {
uint32 unique_id_;
};
// TODO(avd): remove this struct
// A CREDENTIAL Control Frame structure.
struct SpdyCredentialControlFrameBlock : SpdyFrameBlock {
uint16 slot_;
uint32 proof_len_;
// Variable data here.
// proof data
// for each certificate: unit32 certificate_len + certificate_data[i]
};
// A GOAWAY Control Frame structure.
struct SpdyGoAwayControlFrameBlock : SpdyFrameBlock {
SpdyStreamId last_accepted_stream_id_;
SpdyGoAwayStatus status_;
};
// A HEADERS Control Frame structure.
struct SpdyHeadersControlFrameBlock : SpdyFrameBlock {
SpdyStreamId stream_id_;
};
// A WINDOW_UPDATE Control Frame structure
struct SpdyWindowUpdateControlFrameBlock : SpdyFrameBlock {
SpdyStreamId stream_id_;
uint32 delta_window_size_;
};
#pragma pack(pop)
// -------------------------------------------------------------------------
// Wrapper classes for various SPDY frames.
// All Spdy Frame types derive from this SpdyFrame class.
class SpdyFrame {
public:
// Create a SpdyFrame for a given sized buffer.
explicit SpdyFrame(size_t size) : frame_(NULL), owns_buffer_(true) {
DCHECK_GE(size, sizeof(struct SpdyFrameBlock));
char* buffer = new char[size];
memset(buffer, 0, size);
frame_ = reinterpret_cast<struct SpdyFrameBlock*>(buffer);
}
// Create a SpdyFrame using a pre-created buffer.
// If |owns_buffer| is true, this class takes ownership of the buffer
// and will delete it on cleanup. The buffer must have been created using
// new char[].
// If |owns_buffer| is false, the caller retains ownership of the buffer and
// is responsible for making sure the buffer outlives this frame. In other
// words, this class does NOT create a copy of the buffer.
SpdyFrame(char* data, bool owns_buffer)
: frame_(reinterpret_cast<struct SpdyFrameBlock*>(data)),
owns_buffer_(owns_buffer) {
DCHECK(frame_);
}
~SpdyFrame() {
if (owns_buffer_) {
char* buffer = reinterpret_cast<char*>(frame_);
delete [] buffer;
}
frame_ = NULL;
}
// Provides access to the frame bytes, which is a buffer containing
// the frame packed as expected for sending over the wire.
char* data() const { return reinterpret_cast<char*>(frame_); }
uint8 flags() const { return frame_->flags_length_.flags_[0]; }
void set_flags(uint8 flags) { frame_->flags_length_.flags_[0] = flags; }
uint32 length() const {
return ntohl(frame_->flags_length_.length_) & kLengthMask;
}
void set_length(uint32 length) {
DCHECK_EQ(0u, (length & ~kLengthMask));
/*
+----------------------------------+
| Flags (8) | Length (24 bits) |
+----------------------------------+
*/
frame_->flags_length_.length_ = htonl((length & kLengthMask)
| (flags() << 24));
}
bool is_control_frame() const {
return (ntohs(frame_->control_.version_) & kControlFlagMask) ==
kControlFlagMask;
}
// The size of the SpdyFrameBlock structure.
// Every SpdyFrame* class has a static size() method for accessing
// the size of the data structure which will be sent over the wire.
// Note: this is not the same as sizeof(SpdyFrame).
enum { kHeaderSize = sizeof(struct SpdyFrameBlock) };
protected:
SpdyFrameBlock* frame_;
private:
bool owns_buffer_;
DISALLOW_COPY_AND_ASSIGN(SpdyFrame);
};
// A Data Frame.
class SpdyDataFrame : public SpdyFrame {
public:
SpdyDataFrame() : SpdyFrame(size()) {}
SpdyDataFrame(char* data, bool owns_buffer)
: SpdyFrame(data, owns_buffer) {}
SpdyStreamId stream_id() const {
return ntohl(frame_->data_.stream_id_) & kStreamIdMask;
}
// Note that setting the stream id sets the control bit to false.
// As stream id should always be set, this means the control bit
// should always be set correctly.
void set_stream_id(SpdyStreamId id) {
DCHECK_EQ(0u, (id & ~kStreamIdMask));
frame_->data_.stream_id_ = htonl(id & kStreamIdMask);
}
// Returns the size of the SpdyFrameBlock structure.
// Note: this is not the size of the SpdyDataFrame class.
static size_t size() { return SpdyFrame::kHeaderSize; }
const char* payload() const {
return reinterpret_cast<const char*>(frame_) + size();
}
private:
DISALLOW_COPY_AND_ASSIGN(SpdyDataFrame);
};
// A Control Frame.
class SpdyControlFrame : public SpdyFrame {
public:
explicit SpdyControlFrame(size_t size) : SpdyFrame(size) {}
SpdyControlFrame(char* data, bool owns_buffer)
: SpdyFrame(data, owns_buffer) {}
// Callers can use this method to check if the frame appears to be a valid
// frame. Does not guarantee that there are no errors.
bool AppearsToBeAValidControlFrame() const {
// Right now we only check if the frame has an out-of-bounds type.
uint16 type = ntohs(block()->control_.type_);
// NOOP is not a 'valid' control frame in SPDY/3 and beyond.
return type >= SYN_STREAM &&
type < NUM_CONTROL_FRAME_TYPES &&
(version() == 2 || type != NOOP);
}
uint16 version() const {
const int kVersionMask = 0x7fff;
return static_cast<uint16>(
ntohs((block()->control_.version_)) & kVersionMask);
}
void set_version(uint16 version) {
/*
+----------------------------------+
|C| Version(15bits) | Type(16bits) |
+----------------------------------+
*/
DCHECK_EQ(0U, version & kControlFlagMask);
mutable_block()->control_.version_ = htons(kControlFlagMask | version);
}
SpdyControlType type() const {
uint16 type = ntohs(block()->control_.type_);
LOG_IF(DFATAL, type < SYN_STREAM || type >= NUM_CONTROL_FRAME_TYPES)
<< "Invalid control frame type " << type;
return static_cast<SpdyControlType>(type);
}
void set_type(SpdyControlType type) {
DCHECK(type >= SYN_STREAM && type < NUM_CONTROL_FRAME_TYPES);
mutable_block()->control_.type_ = htons(static_cast<uint16>(type));
}
// Returns true if this control frame is of a type that has a header block,
// otherwise it returns false.
bool has_header_block() const {
return type() == SYN_STREAM || type() == SYN_REPLY || type() == HEADERS;
}
private:
const struct SpdyFrameBlock* block() const {
return frame_;
}
struct SpdyFrameBlock* mutable_block() {
return frame_;
}
DISALLOW_COPY_AND_ASSIGN(SpdyControlFrame);
};
// A SYN_STREAM frame.
class SpdySynStreamControlFrame : public SpdyControlFrame {
public:
SpdySynStreamControlFrame() : SpdyControlFrame(size()) {}
SpdySynStreamControlFrame(char* data, bool owns_buffer)
: SpdyControlFrame(data, owns_buffer) {}
SpdyStreamId stream_id() const {
return ntohl(block()->stream_id_) & kStreamIdMask;
}
void set_stream_id(SpdyStreamId id) {
mutable_block()->stream_id_ = htonl(id & kStreamIdMask);
}
SpdyStreamId associated_stream_id() const {
return ntohl(block()->associated_stream_id_) & kStreamIdMask;
}
void set_associated_stream_id(SpdyStreamId id) {
mutable_block()->associated_stream_id_ = htonl(id & kStreamIdMask);
}
SpdyPriority priority() const {
if (version() < 3) {
return (block()->priority_ & kSpdy2PriorityMask) >> 6;
} else {
return (block()->priority_ & kSpdy3PriorityMask) >> 5;
}
}
uint8 credential_slot() const {
if (version() < 3) {
return 0;
} else {
return block()->credential_slot_;
}
}
void set_credential_slot(uint8 credential_slot) {
DCHECK(version() >= 3);
mutable_block()->credential_slot_ = credential_slot;
}
// The number of bytes in the header block beyond the frame header length.
int header_block_len() const {
return static_cast<int>(length() - (size() - SpdyFrame::kHeaderSize));
}
const char* header_block() const {
return reinterpret_cast<const char*>(block()) + size();
}
// Returns the size of the SpdySynStreamControlFrameBlock structure.
// Note: this is not the size of the SpdySynStreamControlFrame class.
static size_t size() { return sizeof(SpdySynStreamControlFrameBlock); }
private:
const struct SpdySynStreamControlFrameBlock* block() const {
return static_cast<SpdySynStreamControlFrameBlock*>(frame_);
}
struct SpdySynStreamControlFrameBlock* mutable_block() {
return static_cast<SpdySynStreamControlFrameBlock*>(frame_);
}
DISALLOW_COPY_AND_ASSIGN(SpdySynStreamControlFrame);
};
// A SYN_REPLY frame.
class SpdySynReplyControlFrame : public SpdyControlFrame {
public:
SpdySynReplyControlFrame() : SpdyControlFrame(size()) {}
SpdySynReplyControlFrame(char* data, bool owns_buffer)
: SpdyControlFrame(data, owns_buffer) {}
SpdyStreamId stream_id() const {
return ntohl(block()->stream_id_) & kStreamIdMask;
}
void set_stream_id(SpdyStreamId id) {
mutable_block()->stream_id_ = htonl(id & kStreamIdMask);
}
int header_block_len() const {
size_t header_block_len = length() - (size() - SpdyFrame::kHeaderSize);
// SPDY 2 had 2 bytes of unused space preceeding the header block.
if (version() < 3) {
header_block_len -= 2;
}
return static_cast<int>(header_block_len);
}
const char* header_block() const {
const char* header_block = reinterpret_cast<const char*>(block()) + size();
// SPDY 2 had 2 bytes of unused space preceeding the header block.
if (version() < 3) {
header_block += 2;
}
return header_block;
}
// Returns the size of the SpdySynReplyControlFrameBlock structure.
// Note: this is not the size of the SpdySynReplyControlFrame class.
static size_t size() { return sizeof(SpdySynReplyControlFrameBlock); }
private:
const struct SpdySynReplyControlFrameBlock* block() const {
return static_cast<SpdySynReplyControlFrameBlock*>(frame_);
}
struct SpdySynReplyControlFrameBlock* mutable_block() {
return static_cast<SpdySynReplyControlFrameBlock*>(frame_);
}
DISALLOW_COPY_AND_ASSIGN(SpdySynReplyControlFrame);
};
// A RST_STREAM frame.
class SpdyRstStreamControlFrame : public SpdyControlFrame {
public:
SpdyRstStreamControlFrame() : SpdyControlFrame(size()) {}
SpdyRstStreamControlFrame(char* data, bool owns_buffer)
: SpdyControlFrame(data, owns_buffer) {}
SpdyStreamId stream_id() const {
return ntohl(block()->stream_id_) & kStreamIdMask;
}
void set_stream_id(SpdyStreamId id) {
mutable_block()->stream_id_ = htonl(id & kStreamIdMask);
}
SpdyStatusCodes status() const {
SpdyStatusCodes status =
static_cast<SpdyStatusCodes>(ntohl(block()->status_));
if (status < INVALID || status >= NUM_STATUS_CODES) {
status = INVALID;
}
return status;
}
void set_status(SpdyStatusCodes status) {
mutable_block()->status_ = htonl(static_cast<uint32>(status));
}
// Returns the size of the SpdyRstStreamControlFrameBlock structure.
// Note: this is not the size of the SpdyRstStreamControlFrame class.
static size_t size() { return sizeof(SpdyRstStreamControlFrameBlock); }
private:
const struct SpdyRstStreamControlFrameBlock* block() const {
return static_cast<SpdyRstStreamControlFrameBlock*>(frame_);
}
struct SpdyRstStreamControlFrameBlock* mutable_block() {
return static_cast<SpdyRstStreamControlFrameBlock*>(frame_);
}
DISALLOW_COPY_AND_ASSIGN(SpdyRstStreamControlFrame);
};
class SpdySettingsControlFrame : public SpdyControlFrame {
public:
SpdySettingsControlFrame() : SpdyControlFrame(size()) {}
SpdySettingsControlFrame(char* data, bool owns_buffer)
: SpdyControlFrame(data, owns_buffer) {}
uint32 num_entries() const {
return ntohl(block()->num_entries_);
}
void set_num_entries(int val) {
mutable_block()->num_entries_ = htonl(static_cast<uint32>(val));
}
int header_block_len() const {
return static_cast<int>(length() - (size() - SpdyFrame::kHeaderSize));
}
const char* header_block() const {
return reinterpret_cast<const char*>(block()) + size();
}
// Returns the size of the SpdySettingsControlFrameBlock structure.
// Note: this is not the size of the SpdySettingsControlFrameBlock class.
static size_t size() { return sizeof(SpdySettingsControlFrameBlock); }
private:
const struct SpdySettingsControlFrameBlock* block() const {
return static_cast<SpdySettingsControlFrameBlock*>(frame_);
}
struct SpdySettingsControlFrameBlock* mutable_block() {
return static_cast<SpdySettingsControlFrameBlock*>(frame_);
}
DISALLOW_COPY_AND_ASSIGN(SpdySettingsControlFrame);
};
class SpdyPingControlFrame : public SpdyControlFrame {
public:
SpdyPingControlFrame() : SpdyControlFrame(size()) {}
SpdyPingControlFrame(char* data, bool owns_buffer)
: SpdyControlFrame(data, owns_buffer) {}
uint32 unique_id() const {
return ntohl(block()->unique_id_);
}
void set_unique_id(uint32 unique_id) {
mutable_block()->unique_id_ = htonl(unique_id);
}
static size_t size() { return sizeof(SpdyPingControlFrameBlock); }
private:
const struct SpdyPingControlFrameBlock* block() const {
return static_cast<SpdyPingControlFrameBlock*>(frame_);
}
struct SpdyPingControlFrameBlock* mutable_block() {
return static_cast<SpdyPingControlFrameBlock*>(frame_);
}
};
class SpdyCredentialControlFrame : public SpdyControlFrame {
public:
SpdyCredentialControlFrame() : SpdyControlFrame(size()) {}
SpdyCredentialControlFrame(char* data, bool owns_buffer)
: SpdyControlFrame(data, owns_buffer) {}
const char* payload() const {
return reinterpret_cast<const char*>(block()) + SpdyFrame::kHeaderSize;
}
static size_t size() { return sizeof(SpdyCredentialControlFrameBlock); }
private:
const struct SpdyCredentialControlFrameBlock* block() const {
return static_cast<SpdyCredentialControlFrameBlock*>(frame_);
}
DISALLOW_COPY_AND_ASSIGN(SpdyCredentialControlFrame);
};
class SpdyGoAwayControlFrame : public SpdyControlFrame {
public:
SpdyGoAwayControlFrame() : SpdyControlFrame(size()) {}
SpdyGoAwayControlFrame(char* data, bool owns_buffer)
: SpdyControlFrame(data, owns_buffer) {}
SpdyStreamId last_accepted_stream_id() const {
return ntohl(block()->last_accepted_stream_id_) & kStreamIdMask;
}
SpdyGoAwayStatus status() const {
if (version() < 3) {
LOG(DFATAL) << "Attempted to access status of SPDY 2 GOAWAY.";
return GOAWAY_INVALID;
} else {
uint32 status = ntohl(block()->status_);
if (status >= GOAWAY_NUM_STATUS_CODES) {
return GOAWAY_INVALID;
} else {
return static_cast<SpdyGoAwayStatus>(status);
}
}
}
void set_last_accepted_stream_id(SpdyStreamId id) {
mutable_block()->last_accepted_stream_id_ = htonl(id & kStreamIdMask);
}
static size_t size() { return sizeof(SpdyGoAwayControlFrameBlock); }
private:
const struct SpdyGoAwayControlFrameBlock* block() const {
return static_cast<SpdyGoAwayControlFrameBlock*>(frame_);
}
struct SpdyGoAwayControlFrameBlock* mutable_block() {
return static_cast<SpdyGoAwayControlFrameBlock*>(frame_);
}
DISALLOW_COPY_AND_ASSIGN(SpdyGoAwayControlFrame);
};
// A HEADERS frame.
class SpdyHeadersControlFrame : public SpdyControlFrame {
public:
SpdyHeadersControlFrame() : SpdyControlFrame(size()) {}
SpdyHeadersControlFrame(char* data, bool owns_buffer)
: SpdyControlFrame(data, owns_buffer) {}
SpdyStreamId stream_id() const {
return ntohl(block()->stream_id_) & kStreamIdMask;
}
void set_stream_id(SpdyStreamId id) {
mutable_block()->stream_id_ = htonl(id & kStreamIdMask);
}
// The number of bytes in the header block beyond the frame header length.
int header_block_len() const {
size_t header_block_len = length() - (size() - SpdyFrame::kHeaderSize);
// SPDY 2 had 2 bytes of unused space preceeding the header block.
if (version() < 3) {
header_block_len -= 2;
}
return static_cast<int>(header_block_len);
}
const char* header_block() const {
const char* header_block = reinterpret_cast<const char*>(block()) + size();
// SPDY 2 had 2 bytes of unused space preceeding the header block.
if (version() < 3) {
header_block += 2;
}
return header_block;
}
// Returns the size of the SpdyHeadersControlFrameBlock structure.
// Note: this is not the size of the SpdyHeadersControlFrame class.
static size_t size() { return sizeof(SpdyHeadersControlFrameBlock); }
private:
const struct SpdyHeadersControlFrameBlock* block() const {
return static_cast<SpdyHeadersControlFrameBlock*>(frame_);
}
struct SpdyHeadersControlFrameBlock* mutable_block() {
return static_cast<SpdyHeadersControlFrameBlock*>(frame_);
}
DISALLOW_COPY_AND_ASSIGN(SpdyHeadersControlFrame);
};
// A WINDOW_UPDATE frame.
class SpdyWindowUpdateControlFrame : public SpdyControlFrame {
public:
SpdyWindowUpdateControlFrame() : SpdyControlFrame(size()) {}
SpdyWindowUpdateControlFrame(char* data, bool owns_buffer)
: SpdyControlFrame(data, owns_buffer) {}
SpdyStreamId stream_id() const {
return ntohl(block()->stream_id_) & kStreamIdMask;
}
void set_stream_id(SpdyStreamId id) {
mutable_block()->stream_id_ = htonl(id & kStreamIdMask);
}
uint32 delta_window_size() const {
return ntohl(block()->delta_window_size_);
}
void set_delta_window_size(uint32 delta_window_size) {
mutable_block()->delta_window_size_ = htonl(delta_window_size);
}
// Returns the size of the SpdyWindowUpdateControlFrameBlock structure.
// Note: this is not the size of the SpdyWindowUpdateControlFrame class.
static size_t size() { return sizeof(SpdyWindowUpdateControlFrameBlock); }
private:
const struct SpdyWindowUpdateControlFrameBlock* block() const {
return static_cast<SpdyWindowUpdateControlFrameBlock*>(frame_);
}
struct SpdyWindowUpdateControlFrameBlock* mutable_block() {
return static_cast<SpdyWindowUpdateControlFrameBlock*>(frame_);
}
DISALLOW_COPY_AND_ASSIGN(SpdyWindowUpdateControlFrame);
};
} // namespace net
#endif // NET_SPDY_SPDY_PROTOCOL_H_