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
27namespace 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. Do not rely on
32// the mapping from enum value SPDYn to the integer n.
33enum SpdyMajorVersion {
34  SPDY2 = 2,
35  SPDY_MIN_VERSION = SPDY2,
36  SPDY3 = 3,
37  SPDY4 = 4,
38  SPDY5 = 5,
39  SPDY_MAX_VERSION = SPDY5
40};
41
42// A SPDY stream id is a 31 bit entity.
43typedef uint32 SpdyStreamId;
44
45// Specifies the stream ID used to denote the current session (for
46// flow control).
47const SpdyStreamId kSessionFlowControlStreamId = 0;
48
49// Initial window size for a Spdy stream in bytes.
50const int32 kSpdyStreamInitialWindowSize = 64 * 1024;  // 64 KBytes
51
52// The maxmium possible control frame size allowed by the spec.
53const int32 kSpdyMaxControlFrameSize = (1 << 24) - 1;
54
55// The maximum control frame size we actually send/accept.
56const int32 kControlFrameSizeLimit = 1 << 14;
57
58// Initial window size for a Spdy session in bytes.
59const int32 kSpdySessionInitialWindowSize = 64 * 1024;  // 64 KBytes
60
61// Maximum window size for a Spdy stream or session.
62const int32 kSpdyMaximumWindowSize = 0x7FFFFFFF;  // Max signed 32bit int
63
64// Maximum padding size in octets for one DATA or HEADERS or PUSH_PROMISE frame.
65const int32 kPaddingSizePerFrame = 256;
66
67// SPDY 2 dictionary.
68// This is just a hacked dictionary to use for shrinking HTTP-like headers.
69const char kV2Dictionary[] =
70  "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-"
71  "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi"
72  "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser"
73  "-agent10010120020120220320420520630030130230330430530630740040140240340440"
74  "5406407408409410411412413414415416417500501502503504505accept-rangesageeta"
75  "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic"
76  "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran"
77  "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati"
78  "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo"
79  "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe"
80  "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic"
81  "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1"
82  ".1statusversionurl";
83const int kV2DictionarySize = arraysize(kV2Dictionary);
84
85// SPDY 3 dictionary.
86const char kV3Dictionary[] = {
87  0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69,  // ....opti
88  0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68,  // ons....h
89  0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70,  // ead....p
90  0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70,  // ost....p
91  0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65,  // ut....de
92  0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05,  // lete....
93  0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00,  // trace...
94  0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00,  // .accept.
95  0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70,  // ...accep
96  0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65,  // t-charse
97  0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63,  // t....acc
98  0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f,  // ept-enco
99  0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f,  // ding....
100  0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c,  // accept-l
101  0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00,  // anguage.
102  0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70,  // ...accep
103  0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73,  // t-ranges
104  0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00,  // ....age.
105  0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77,  // ...allow
106  0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68,  // ....auth
107  0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f,  // orizatio
108  0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63,  // n....cac
109  0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72,  // he-contr
110  0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f,  // ol....co
111  0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,  // nnection
112  0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74,  // ....cont
113  0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65,  // ent-base
114  0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74,  // ....cont
115  0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f,  // ent-enco
116  0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10,  // ding....
117  0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d,  // content-
118  0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65,  // language
119  0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74,  // ....cont
120  0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67,  // ent-leng
121  0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f,  // th....co
122  0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f,  // ntent-lo
123  0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,  // cation..
124  0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,  // ..conten
125  0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00,  // t-md5...
126  0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,  // .content
127  0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00,  // -range..
128  0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,  // ..conten
129  0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00,  // t-type..
130  0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00,  // ..date..
131  0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00,  // ..etag..
132  0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74,  // ..expect
133  0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69,  // ....expi
134  0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66,  // res....f
135  0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68,  // rom....h
136  0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69,  // ost....i
137  0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00,  // f-match.
138  0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f,  // ...if-mo
139  0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73,  // dified-s
140  0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d,  // ince....
141  0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d,  // if-none-
142  0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00,  // match...
143  0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67,  // .if-rang
144  0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d,  // e....if-
145  0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69,  // unmodifi
146  0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65,  // ed-since
147  0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74,  // ....last
148  0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65,  // -modifie
149  0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63,  // d....loc
150  0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00,  // ation...
151  0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72,  // .max-for
152  0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00,  // wards...
153  0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00,  // .pragma.
154  0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79,  // ...proxy
155  0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74,  // -authent
156  0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00,  // icate...
157  0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61,  // .proxy-a
158  0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61,  // uthoriza
159  0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05,  // tion....
160  0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00,  // range...
161  0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72,  // .referer
162  0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72,  // ....retr
163  0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00,  // y-after.
164  0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65,  // ...serve
165  0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00,  // r....te.
166  0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c,  // ...trail
167  0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72,  // er....tr
168  0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65,  // ansfer-e
169  0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00,  // ncoding.
170  0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61,  // ...upgra
171  0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73,  // de....us
172  0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74,  // er-agent
173  0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79,  // ....vary
174  0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00,  // ....via.
175  0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69,  // ...warni
176  0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77,  // ng....ww
177  0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e,  // w-authen
178  0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00,  // ticate..
179  0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64,  // ..method
180  0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00,  // ....get.
181  0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,  // ...statu
182  0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30,  // s....200
183  0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76,  // .OK....v
184  0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00,  // ersion..
185  0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31,  // ..HTTP.1
186  0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72,  // .1....ur
187  0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62,  // l....pub
188  0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73,  // lic....s
189  0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69,  // et-cooki
190  0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65,  // e....kee
191  0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00,  // p-alive.
192  0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69,  // ...origi
193  0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32,  // n1001012
194  0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35,  // 01202205
195  0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30,  // 20630030
196  0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33,  // 23033043
197  0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37,  // 05306307
198  0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30,  // 40240540
199  0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34,  // 64074084
200  0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31,  // 09410411
201  0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31,  // 41241341
202  0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34,  // 44154164
203  0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34,  // 17502504
204  0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e,  // 505203.N
205  0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f,  // on-Autho
206  0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65,  // ritative
207  0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61,  // .Informa
208  0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20,  // tion204.
209  0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65,  // No.Conte
210  0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f,  // nt301.Mo
211  0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d,  // ved.Perm
212  0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34,  // anently4
213  0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52,  // 00.Bad.R
214  0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30,  // equest40
215  0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68,  // 1.Unauth
216  0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30,  // orized40
217  0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64,  // 3.Forbid
218  0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e,  // den404.N
219  0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64,  // ot.Found
220  0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65,  // 500.Inte
221  0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72,  // rnal.Ser
222  0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f,  // ver.Erro
223  0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74,  // r501.Not
224  0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65,  // .Impleme
225  0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20,  // nted503.
226  0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20,  // Service.
227  0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61,  // Unavaila
228  0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46,  // bleJan.F
229  0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41,  // eb.Mar.A
230  0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a,  // pr.May.J
231  0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41,  // un.Jul.A
232  0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20,  // ug.Sept.
233  0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20,  // Oct.Nov.
234  0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30,  // Dec.00.0
235  0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e,  // 0.00.Mon
236  0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57,  // ..Tue..W
237  0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c,  // ed..Thu.
238  0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61,  // .Fri..Sa
239  0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20,  // t..Sun..
240  0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b,  // GMTchunk
241  0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f,  // ed.text.
242  0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61,  // html.ima
243  0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69,  // ge.png.i
244  0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67,  // mage.jpg
245  0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67,  // .image.g
246  0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69,  // if.appli
247  0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78,  // cation.x
248  0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69,  // ml.appli
249  0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78,  // cation.x
250  0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c,  // html.xml
251  0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c,  // .text.pl
252  0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74,  // ain.text
253  0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72,  // .javascr
254  0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c,  // ipt.publ
255  0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74,  // icprivat
256  0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65,  // emax-age
257  0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65,  // .gzip.de
258  0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64,  // flate.sd
259  0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65,  // chcharse
260  0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63,  // t.utf-8c
261  0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69,  // harset.i
262  0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d,  // so-8859-
263  0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a,  // 1.utf-..
264  0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e         // .enq.0.
265};
266const int kV3DictionarySize = arraysize(kV3Dictionary);
267
268// The HTTP/2 connection header prefix, which must be the first bytes
269// sent by the client upon starting an HTTP/2 connection, and which
270// must be followed by a SETTINGS frame.
271//
272// Equivalent to the string "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
273// (without the null terminator).
274const char kHttp2ConnectionHeaderPrefix[] = {
275  0x50, 0x52, 0x49, 0x20, 0x2a, 0x20, 0x48, 0x54,  // PRI * HT
276  0x54, 0x50, 0x2f, 0x32, 0x2e, 0x30, 0x0d, 0x0a,  // TP/2.0..
277  0x0d, 0x0a, 0x53, 0x4d, 0x0d, 0x0a, 0x0d, 0x0a   // ..SM....
278};
279const int kHttp2ConnectionHeaderPrefixSize =
280    arraysize(kHttp2ConnectionHeaderPrefix);
281
282const char kHttp2VersionString[] = "HTTP/1.1";
283
284// Types of SPDY frames.
285enum SpdyFrameType {
286  DATA,
287  SYN_STREAM,
288  SYN_REPLY,
289  RST_STREAM,
290  SETTINGS,
291  PING,
292  GOAWAY,
293  HEADERS,
294  WINDOW_UPDATE,
295  CREDENTIAL = 10,  // No longer valid.  Kept for identifiability.
296  PUSH_PROMISE,
297  CONTINUATION,
298  PRIORITY,
299  // BLOCKED and ALTSVC are recognized extensions.
300  BLOCKED,
301  ALTSVC,
302};
303
304// Flags on data packets.
305enum SpdyDataFlags {
306  DATA_FLAG_NONE = 0x00,
307  DATA_FLAG_FIN = 0x01,
308  DATA_FLAG_END_SEGMENT = 0x02,
309  DATA_FLAG_PADDED = 0x08,
310  DATA_FLAG_COMPRESSED = 0x20,
311};
312
313// Flags on control packets
314enum SpdyControlFlags {
315  CONTROL_FLAG_NONE = 0x00,
316  CONTROL_FLAG_FIN = 0x01,
317  CONTROL_FLAG_UNIDIRECTIONAL = 0x02,
318};
319
320enum SpdyPingFlags {
321  PING_FLAG_ACK = 0x01,
322};
323
324// Used by HEADERS, PUSH_PROMISE, and CONTINUATION.
325enum SpdyHeadersFlags {
326  HEADERS_FLAG_END_SEGMENT = 0x02,
327  HEADERS_FLAG_END_HEADERS = 0x04,
328  HEADERS_FLAG_PADDED = 0x08,
329  HEADERS_FLAG_PRIORITY = 0x20,
330};
331
332enum SpdyPushPromiseFlags {
333  PUSH_PROMISE_FLAG_END_PUSH_PROMISE = 0x04,
334  PUSH_PROMISE_FLAG_PADDED = 0x08,
335};
336
337// Flags on the SETTINGS control frame.
338enum SpdySettingsControlFlags {
339  SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS = 0x01,
340};
341
342enum Http2SettingsControlFlags {
343  SETTINGS_FLAG_ACK = 0x01,
344};
345
346// Flags for settings within a SETTINGS frame.
347enum SpdySettingsFlags {
348  SETTINGS_FLAG_NONE = 0x00,
349  SETTINGS_FLAG_PLEASE_PERSIST = 0x01,
350  SETTINGS_FLAG_PERSISTED = 0x02,
351};
352
353// List of known settings. Avoid changing these enum values, as persisted
354// settings are keyed on them, and they are also exposed in net-internals.
355enum SpdySettingsIds {
356  SETTINGS_UPLOAD_BANDWIDTH = 0x1,
357  SETTINGS_DOWNLOAD_BANDWIDTH = 0x2,
358  // Network round trip time in milliseconds.
359  SETTINGS_ROUND_TRIP_TIME = 0x3,
360  // The maximum number of simultaneous live streams in each direction.
361  SETTINGS_MAX_CONCURRENT_STREAMS = 0x4,
362  // TCP congestion window in packets.
363  SETTINGS_CURRENT_CWND = 0x5,
364  // Downstream byte retransmission rate in percentage.
365  SETTINGS_DOWNLOAD_RETRANS_RATE = 0x6,
366  // Initial window size in bytes
367  SETTINGS_INITIAL_WINDOW_SIZE = 0x7,
368  // HPACK header table maximum size.
369  SETTINGS_HEADER_TABLE_SIZE = 0x8,
370  // Whether or not server push (PUSH_PROMISE) is enabled.
371  SETTINGS_ENABLE_PUSH = 0x9,
372  // The size of the largest frame payload that a receiver is willing to accept.
373  SETTINGS_MAX_FRAME_SIZE = 0xa,
374  // The maximum size of header list that the sender is prepared to accept.
375  SETTINGS_MAX_HEADER_LIST_SIZE = 0xb,
376};
377
378// Status codes for RST_STREAM frames.
379enum SpdyRstStreamStatus {
380  RST_STREAM_INVALID = 0,
381  RST_STREAM_PROTOCOL_ERROR = 1,
382  RST_STREAM_INVALID_STREAM = 2,
383  RST_STREAM_STREAM_CLOSED = 2,  // Equivalent to INVALID_STREAM
384  RST_STREAM_REFUSED_STREAM = 3,
385  RST_STREAM_UNSUPPORTED_VERSION = 4,
386  RST_STREAM_CANCEL = 5,
387  RST_STREAM_INTERNAL_ERROR = 6,
388  RST_STREAM_FLOW_CONTROL_ERROR = 7,
389  RST_STREAM_STREAM_IN_USE = 8,
390  RST_STREAM_STREAM_ALREADY_CLOSED = 9,
391  RST_STREAM_INVALID_CREDENTIALS = 10,
392  // FRAME_TOO_LARGE (defined by SPDY versions 3.1 and below), and
393  // FRAME_SIZE_ERROR (defined by HTTP/2) are mapped to the same internal
394  // reset status.
395  RST_STREAM_FRAME_TOO_LARGE = 11,
396  RST_STREAM_FRAME_SIZE_ERROR = 11,
397  RST_STREAM_SETTINGS_TIMEOUT = 12,
398  RST_STREAM_CONNECT_ERROR = 13,
399  RST_STREAM_ENHANCE_YOUR_CALM = 14,
400  RST_STREAM_NUM_STATUS_CODES = 15
401};
402
403// Status codes for GOAWAY frames.
404enum SpdyGoAwayStatus {
405  GOAWAY_OK = 0,
406  GOAWAY_NO_ERROR = GOAWAY_OK,
407  GOAWAY_PROTOCOL_ERROR = 1,
408  GOAWAY_INTERNAL_ERROR = 2,
409  GOAWAY_FLOW_CONTROL_ERROR = 3,
410  GOAWAY_SETTINGS_TIMEOUT = 4,
411  GOAWAY_STREAM_CLOSED = 5,
412  GOAWAY_FRAME_SIZE_ERROR = 6,
413  GOAWAY_REFUSED_STREAM = 7,
414  GOAWAY_CANCEL = 8,
415  GOAWAY_COMPRESSION_ERROR = 9,
416  GOAWAY_CONNECT_ERROR = 10,
417  GOAWAY_ENHANCE_YOUR_CALM = 11,
418  GOAWAY_INADEQUATE_SECURITY = 12
419};
420
421// A SPDY priority is a number between 0 and 7 (inclusive).
422// SPDY priority range is version-dependent. For SPDY 2 and below, priority is a
423// number between 0 and 3.
424typedef uint8 SpdyPriority;
425
426typedef std::map<std::string, std::string> SpdyNameValueBlock;
427
428typedef uint64 SpdyPingId;
429
430typedef std::string SpdyProtocolId;
431
432// TODO(hkhalil): Add direct testing for this? It won't increase coverage any,
433// but is good to do anyway.
434class NET_EXPORT_PRIVATE SpdyConstants {
435 public:
436  // Returns true if a given on-the-wire enumeration of a frame type is valid
437  // for a given protocol version, false otherwise.
438  static bool IsValidFrameType(SpdyMajorVersion version, int frame_type_field);
439
440  // Parses a frame type from an on-the-wire enumeration of a given protocol
441  // version.
442  // Behavior is undefined for invalid frame type fields; consumers should first
443  // use IsValidFrameType() to verify validity of frame type fields.
444  static SpdyFrameType ParseFrameType(SpdyMajorVersion version,
445                                      int frame_type_field);
446
447  // Serializes a given frame type to the on-the-wire enumeration value for the
448  // given protocol version.
449  // Returns -1 on failure (I.E. Invalid frame type for the given version).
450  static int SerializeFrameType(SpdyMajorVersion version,
451                                SpdyFrameType frame_type);
452
453  // Returns the frame type for non-control (i.e. data) frames
454  // in the given SPDY version.
455  static int DataFrameType(SpdyMajorVersion version);
456
457  // Returns true if a given on-the-wire enumeration of a setting id is valid
458  // for a given protocol version, false otherwise.
459  static bool IsValidSettingId(SpdyMajorVersion version, int setting_id_field);
460
461  // Parses a setting id from an on-the-wire enumeration of a given protocol
462  // version.
463  // Behavior is undefined for invalid setting id fields; consumers should first
464  // use IsValidSettingId() to verify validity of setting id fields.
465  static SpdySettingsIds ParseSettingId(SpdyMajorVersion version,
466                                        int setting_id_field);
467
468  // Serializes a given setting id to the on-the-wire enumeration value for the
469  // given protocol version.
470  // Returns -1 on failure (I.E. Invalid setting id for the given version).
471  static int SerializeSettingId(SpdyMajorVersion version, SpdySettingsIds id);
472
473  // Returns true if a given on-the-wire enumeration of a RST_STREAM status code
474  // is valid for a given protocol version, false otherwise.
475  static bool IsValidRstStreamStatus(SpdyMajorVersion version,
476                                     int rst_stream_status_field);
477
478  // Parses a RST_STREAM status code from an on-the-wire enumeration of a given
479  // protocol version.
480  // Behavior is undefined for invalid RST_STREAM status code fields; consumers
481  // should first use IsValidRstStreamStatus() to verify validity of RST_STREAM
482  // status code fields..
483  static SpdyRstStreamStatus ParseRstStreamStatus(SpdyMajorVersion version,
484                                                  int rst_stream_status_field);
485
486  // Serializes a given RST_STREAM status code to the on-the-wire enumeration
487  // value for the given protocol version.
488  // Returns -1 on failure (I.E. Invalid RST_STREAM status code for the given
489  // version).
490  static int SerializeRstStreamStatus(SpdyMajorVersion version,
491                                      SpdyRstStreamStatus rst_stream_status);
492
493  // Returns true if a given on-the-wire enumeration of a GOAWAY status code is
494  // valid for the given protocol version, false otherwise.
495  static bool IsValidGoAwayStatus(SpdyMajorVersion version,
496                                  int goaway_status_field);
497
498  // Parses a GOAWAY status from an on-the-wire enumeration of a given protocol
499  // version.
500  // Behavior is undefined for invalid GOAWAY status fields; consumers should
501  // first use IsValidGoAwayStatus() to verify validity of GOAWAY status fields.
502  static SpdyGoAwayStatus ParseGoAwayStatus(SpdyMajorVersion version,
503                                            int goaway_status_field);
504
505  // Serializes a given GOAWAY status to the on-the-wire enumeration value for
506  // the given protocol version.
507  // Returns -1 on failure (I.E. Invalid GOAWAY status for the given version).
508  static int SerializeGoAwayStatus(SpdyMajorVersion version,
509                                   SpdyGoAwayStatus status);
510
511  // Size, in bytes, of the data frame header. Future versions of SPDY
512  // will likely vary this, so we allow for the flexibility of a function call
513  // for this value as opposed to a constant.
514  static size_t GetDataFrameMinimumSize(SpdyMajorVersion version);
515
516  // Size, in bytes, of the control frame header.
517  static size_t GetControlFrameHeaderSize(SpdyMajorVersion version);
518
519  static size_t GetPrefixLength(SpdyFrameType type, SpdyMajorVersion version);
520
521  static size_t GetFrameMaximumSize(SpdyMajorVersion version);
522
523  // Returns the size of a header block size field. Valid only for SPDY
524  // versions <= 3.
525  static size_t GetSizeOfSizeField(SpdyMajorVersion version);
526
527  // Returns the size (in bytes) of a wire setting ID and value.
528  static size_t GetSettingSize(SpdyMajorVersion version);
529
530  static SpdyMajorVersion ParseMajorVersion(int version_number);
531
532  static int SerializeMajorVersion(SpdyMajorVersion version);
533
534  static std::string GetVersionString(SpdyMajorVersion version);
535};
536
537class SpdyFrame;
538typedef SpdyFrame SpdySerializedFrame;
539
540class SpdyFrameVisitor;
541
542// Intermediate representation for SPDY frames.
543// TODO(hkhalil): Rename this class to SpdyFrame when the existing SpdyFrame is
544// gone.
545class NET_EXPORT_PRIVATE SpdyFrameIR {
546 public:
547  virtual ~SpdyFrameIR() {}
548
549  virtual void Visit(SpdyFrameVisitor* visitor) const = 0;
550
551 protected:
552  SpdyFrameIR() {}
553
554 private:
555  DISALLOW_COPY_AND_ASSIGN(SpdyFrameIR);
556};
557
558// Abstract class intended to be inherited by IRs that have a stream associated
559// to them.
560class NET_EXPORT_PRIVATE SpdyFrameWithStreamIdIR : public SpdyFrameIR {
561 public:
562  virtual ~SpdyFrameWithStreamIdIR() {}
563  SpdyStreamId stream_id() const { return stream_id_; }
564  void set_stream_id(SpdyStreamId stream_id) {
565    DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
566    stream_id_ = stream_id;
567  }
568
569 protected:
570  explicit SpdyFrameWithStreamIdIR(SpdyStreamId stream_id) {
571    set_stream_id(stream_id);
572  }
573
574 private:
575  SpdyStreamId stream_id_;
576
577  DISALLOW_COPY_AND_ASSIGN(SpdyFrameWithStreamIdIR);
578};
579
580// Abstract class intended to be inherited by IRs that have the option of a FIN
581// flag. Implies SpdyFrameWithStreamIdIR.
582class NET_EXPORT_PRIVATE SpdyFrameWithFinIR : public SpdyFrameWithStreamIdIR {
583 public:
584  virtual ~SpdyFrameWithFinIR() {}
585  bool fin() const { return fin_; }
586  void set_fin(bool fin) { fin_ = fin; }
587
588 protected:
589  explicit SpdyFrameWithFinIR(SpdyStreamId stream_id)
590      : SpdyFrameWithStreamIdIR(stream_id),
591        fin_(false) {}
592
593 private:
594  bool fin_;
595
596  DISALLOW_COPY_AND_ASSIGN(SpdyFrameWithFinIR);
597};
598
599// Abstract class intended to be inherited by IRs that contain a name-value
600// block. Implies SpdyFrameWithFinIR.
601class NET_EXPORT_PRIVATE SpdyFrameWithNameValueBlockIR
602    : public NON_EXPORTED_BASE(SpdyFrameWithFinIR) {
603 public:
604  const SpdyNameValueBlock& name_value_block() const {
605    return name_value_block_;
606  }
607  void set_name_value_block(const SpdyNameValueBlock& name_value_block) {
608    // Deep copy.
609    name_value_block_ = name_value_block;
610  }
611  void SetHeader(const base::StringPiece& name,
612                 const base::StringPiece& value) {
613    name_value_block_[name.as_string()] = value.as_string();
614  }
615  SpdyNameValueBlock* mutable_name_value_block() {
616    return &name_value_block_;
617  }
618
619 protected:
620  explicit SpdyFrameWithNameValueBlockIR(SpdyStreamId stream_id);
621  virtual ~SpdyFrameWithNameValueBlockIR();
622
623 private:
624  SpdyNameValueBlock name_value_block_;
625
626  DISALLOW_COPY_AND_ASSIGN(SpdyFrameWithNameValueBlockIR);
627};
628
629class NET_EXPORT_PRIVATE SpdyDataIR
630    : public NON_EXPORTED_BASE(SpdyFrameWithFinIR) {
631 public:
632  // Performs deep copy on data.
633  SpdyDataIR(SpdyStreamId stream_id, const base::StringPiece& data);
634
635  // Use in conjunction with SetDataShallow() for shallow-copy on data.
636  explicit SpdyDataIR(SpdyStreamId stream_id);
637
638  virtual ~SpdyDataIR();
639
640  base::StringPiece data() const { return data_; }
641
642  bool padded() const { return padded_; }
643
644  int padding_payload_len() const { return padding_payload_len_; }
645
646  void set_padding_len(int padding_len) {
647    DCHECK_GT(padding_len, 0);
648    DCHECK_LE(padding_len, kPaddingSizePerFrame);
649    padded_ = true;
650    // The pad field takes one octet on the wire.
651    padding_payload_len_ = padding_len - 1;
652  }
653
654  // Deep-copy of data (keep private copy).
655  void SetDataDeep(const base::StringPiece& data) {
656    data_store_.reset(new std::string(data.data(), data.length()));
657    data_ = *(data_store_.get());
658  }
659
660  // Shallow-copy of data (do not keep private copy).
661  void SetDataShallow(const base::StringPiece& data) {
662    data_store_.reset();
663    data_ = data;
664  }
665
666  virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
667
668 private:
669  // Used to store data that this SpdyDataIR should own.
670  scoped_ptr<std::string> data_store_;
671  base::StringPiece data_;
672
673  bool padded_;
674  // padding_payload_len_ = desired padding length - len(padding length field).
675  int padding_payload_len_;
676
677  DISALLOW_COPY_AND_ASSIGN(SpdyDataIR);
678};
679
680class NET_EXPORT_PRIVATE SpdySynStreamIR
681    : public SpdyFrameWithNameValueBlockIR {
682 public:
683  explicit SpdySynStreamIR(SpdyStreamId stream_id)
684      : SpdyFrameWithNameValueBlockIR(stream_id),
685        associated_to_stream_id_(0),
686        priority_(0),
687        unidirectional_(false) {}
688  SpdyStreamId associated_to_stream_id() const {
689    return associated_to_stream_id_;
690  }
691  void set_associated_to_stream_id(SpdyStreamId stream_id) {
692    associated_to_stream_id_ = stream_id;
693  }
694  SpdyPriority priority() const { return priority_; }
695  void set_priority(SpdyPriority priority) { priority_ = priority; }
696  bool unidirectional() const { return unidirectional_; }
697  void set_unidirectional(bool unidirectional) {
698    unidirectional_ = unidirectional;
699  }
700
701  virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
702
703 private:
704  SpdyStreamId associated_to_stream_id_;
705  SpdyPriority priority_;
706  bool unidirectional_;
707
708  DISALLOW_COPY_AND_ASSIGN(SpdySynStreamIR);
709};
710
711class NET_EXPORT_PRIVATE SpdySynReplyIR : public SpdyFrameWithNameValueBlockIR {
712 public:
713  explicit SpdySynReplyIR(SpdyStreamId stream_id)
714      : SpdyFrameWithNameValueBlockIR(stream_id) {}
715
716  virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
717
718 private:
719  DISALLOW_COPY_AND_ASSIGN(SpdySynReplyIR);
720};
721
722class NET_EXPORT_PRIVATE SpdyRstStreamIR : public SpdyFrameWithStreamIdIR {
723 public:
724  SpdyRstStreamIR(SpdyStreamId stream_id, SpdyRstStreamStatus status,
725                  base::StringPiece description);
726
727  virtual ~SpdyRstStreamIR();
728
729  SpdyRstStreamStatus status() const {
730    return status_;
731  }
732  void set_status(SpdyRstStreamStatus status) {
733    status_ = status;
734  }
735
736  base::StringPiece description() const { return description_; }
737
738  void set_description(base::StringPiece description) {
739    description_ = description;
740  }
741
742  virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
743
744 private:
745  SpdyRstStreamStatus status_;
746  base::StringPiece description_;
747
748  DISALLOW_COPY_AND_ASSIGN(SpdyRstStreamIR);
749};
750
751class NET_EXPORT_PRIVATE SpdySettingsIR : public SpdyFrameIR {
752 public:
753  // Associates flags with a value.
754  struct Value {
755    Value() : persist_value(false),
756              persisted(false),
757              value(0) {}
758    bool persist_value;
759    bool persisted;
760    int32 value;
761  };
762  typedef std::map<SpdySettingsIds, Value> ValueMap;
763
764  SpdySettingsIR();
765
766  virtual ~SpdySettingsIR();
767
768  // Overwrites as appropriate.
769  const ValueMap& values() const { return values_; }
770  void AddSetting(SpdySettingsIds id,
771                  bool persist_value,
772                  bool persisted,
773                  int32 value) {
774    values_[id].persist_value = persist_value;
775    values_[id].persisted = persisted;
776    values_[id].value = value;
777  }
778
779  bool clear_settings() const { return clear_settings_; }
780  void set_clear_settings(bool clear_settings) {
781    clear_settings_ = clear_settings;
782  }
783  bool is_ack() const { return is_ack_; }
784  void set_is_ack(bool is_ack) {
785    is_ack_ = is_ack;
786  }
787
788  virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
789
790 private:
791  ValueMap values_;
792  bool clear_settings_;
793  bool is_ack_;
794
795  DISALLOW_COPY_AND_ASSIGN(SpdySettingsIR);
796};
797
798class NET_EXPORT_PRIVATE SpdyPingIR : public SpdyFrameIR {
799 public:
800  explicit SpdyPingIR(SpdyPingId id) : id_(id), is_ack_(false) {}
801  SpdyPingId id() const { return id_; }
802
803  // ACK logic is valid only for SPDY versions 4 and above.
804  bool is_ack() const { return is_ack_; }
805  void set_is_ack(bool is_ack) { is_ack_ = is_ack; }
806
807  virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
808
809 private:
810  SpdyPingId id_;
811  bool is_ack_;
812
813  DISALLOW_COPY_AND_ASSIGN(SpdyPingIR);
814};
815
816class NET_EXPORT_PRIVATE SpdyGoAwayIR : public SpdyFrameIR {
817 public:
818  SpdyGoAwayIR(SpdyStreamId last_good_stream_id, SpdyGoAwayStatus status,
819               const base::StringPiece& description);
820  virtual ~SpdyGoAwayIR();
821  SpdyStreamId last_good_stream_id() const { return last_good_stream_id_; }
822  void set_last_good_stream_id(SpdyStreamId last_good_stream_id) {
823    DCHECK_LE(0u, last_good_stream_id);
824    DCHECK_EQ(0u, last_good_stream_id & ~kStreamIdMask);
825    last_good_stream_id_ = last_good_stream_id;
826  }
827  SpdyGoAwayStatus status() const { return status_; }
828  void set_status(SpdyGoAwayStatus status) {
829    // TODO(hkhalil): Check valid ranges of status?
830    status_ = status;
831  }
832
833  const base::StringPiece& description() const;
834
835  virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
836
837 private:
838  SpdyStreamId last_good_stream_id_;
839  SpdyGoAwayStatus status_;
840  const base::StringPiece description_;
841
842  DISALLOW_COPY_AND_ASSIGN(SpdyGoAwayIR);
843};
844
845class NET_EXPORT_PRIVATE SpdyHeadersIR : public SpdyFrameWithNameValueBlockIR {
846 public:
847  explicit SpdyHeadersIR(SpdyStreamId stream_id)
848    : SpdyFrameWithNameValueBlockIR(stream_id),
849      has_priority_(false),
850      priority_(0) {}
851
852  virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
853
854  bool has_priority() const { return has_priority_; }
855  void set_has_priority(bool has_priority) { has_priority_ = has_priority; }
856  uint32 priority() const { return priority_; }
857  void set_priority(SpdyPriority priority) { priority_ = priority; }
858
859 private:
860  bool has_priority_;
861  // 31-bit priority.
862  uint32 priority_;
863  DISALLOW_COPY_AND_ASSIGN(SpdyHeadersIR);
864};
865
866class NET_EXPORT_PRIVATE SpdyWindowUpdateIR : public SpdyFrameWithStreamIdIR {
867 public:
868  SpdyWindowUpdateIR(SpdyStreamId stream_id, int32 delta)
869      : SpdyFrameWithStreamIdIR(stream_id) {
870    set_delta(delta);
871  }
872  int32 delta() const { return delta_; }
873  void set_delta(int32 delta) {
874    DCHECK_LT(0, delta);
875    DCHECK_LE(delta, kSpdyMaximumWindowSize);
876    delta_ = delta;
877  }
878
879  virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
880
881 private:
882  int32 delta_;
883
884  DISALLOW_COPY_AND_ASSIGN(SpdyWindowUpdateIR);
885};
886
887class NET_EXPORT_PRIVATE SpdyBlockedIR
888    : public NON_EXPORTED_BASE(SpdyFrameWithStreamIdIR) {
889 public:
890  explicit SpdyBlockedIR(SpdyStreamId stream_id)
891      : SpdyFrameWithStreamIdIR(stream_id) {}
892
893  virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
894
895 private:
896  DISALLOW_COPY_AND_ASSIGN(SpdyBlockedIR);
897};
898
899class NET_EXPORT_PRIVATE SpdyPushPromiseIR
900    : public SpdyFrameWithNameValueBlockIR {
901 public:
902  SpdyPushPromiseIR(SpdyStreamId stream_id, SpdyStreamId promised_stream_id)
903      : SpdyFrameWithNameValueBlockIR(stream_id),
904        promised_stream_id_(promised_stream_id) {}
905  SpdyStreamId promised_stream_id() const { return promised_stream_id_; }
906  void set_promised_stream_id(SpdyStreamId id) { promised_stream_id_ = id; }
907
908  virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
909
910 private:
911  SpdyStreamId promised_stream_id_;
912  DISALLOW_COPY_AND_ASSIGN(SpdyPushPromiseIR);
913};
914
915// TODO(jgraettinger): This representation needs review. SpdyContinuationIR
916// needs to frame a portion of a single, arbitrarily-broken encoded buffer.
917class NET_EXPORT_PRIVATE SpdyContinuationIR
918    : public SpdyFrameWithNameValueBlockIR {
919 public:
920  explicit SpdyContinuationIR(SpdyStreamId stream_id)
921      : SpdyFrameWithNameValueBlockIR(stream_id),
922        end_headers_(false) {}
923
924  virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
925
926  bool end_headers() const { return end_headers_; }
927  void set_end_headers(bool end_headers) {end_headers_ = end_headers;}
928
929 private:
930  bool end_headers_;
931  DISALLOW_COPY_AND_ASSIGN(SpdyContinuationIR);
932};
933
934class NET_EXPORT_PRIVATE SpdyAltSvcIR : public SpdyFrameWithStreamIdIR {
935 public:
936  explicit SpdyAltSvcIR(SpdyStreamId stream_id);
937
938  uint32 max_age() const { return max_age_; }
939  uint16 port() const { return port_; }
940  SpdyProtocolId protocol_id() const {
941    return protocol_id_;
942  }
943  std::string host() const { return host_; }
944  std::string origin() const { return origin_; }
945
946  void set_max_age(uint32 max_age) { max_age_ = max_age; }
947  void set_port(uint16 port) { port_ = port; }
948  void set_protocol_id(SpdyProtocolId protocol_id) {
949    protocol_id_ = protocol_id;
950  }
951  void set_host(std::string host) {
952    host_ = host;
953  }
954  void set_origin(std::string origin) {
955    origin_ = origin;
956  }
957
958  virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
959
960 private:
961  uint32 max_age_;
962  uint16 port_;
963  SpdyProtocolId protocol_id_;
964  std::string host_;
965  std::string origin_;
966  DISALLOW_COPY_AND_ASSIGN(SpdyAltSvcIR);
967};
968
969class NET_EXPORT_PRIVATE SpdyPriorityIR : public SpdyFrameWithStreamIdIR {
970 public:
971  explicit SpdyPriorityIR(SpdyStreamId stream_id);
972  explicit SpdyPriorityIR(SpdyStreamId stream_id,
973                          SpdyStreamId parent_stream_id,
974                          uint8 weight,
975                          bool exclusive);
976  SpdyStreamId parent_stream_id() const { return parent_stream_id_; }
977  void set_parent_stream_id(SpdyStreamId id) { parent_stream_id_ = id; }
978  uint8 weight() const { return weight_; }
979  void set_weight(uint8 weight) { weight_ = weight; }
980  bool exclusive() const { return exclusive_; }
981  void set_exclusive(bool exclusive) { exclusive_ = exclusive; }
982
983  virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE;
984
985 private:
986  SpdyStreamId parent_stream_id_;
987  uint8 weight_;
988  bool exclusive_;
989  DISALLOW_COPY_AND_ASSIGN(SpdyPriorityIR);
990};
991
992// -------------------------------------------------------------------------
993// Wrapper classes for various SPDY frames.
994
995// All Spdy Frame types derive from this SpdyFrame class.
996class SpdyFrame {
997 public:
998  // Create a SpdyFrame using a pre-created buffer.
999  // If |owns_buffer| is true, this class takes ownership of the buffer
1000  // and will delete it on cleanup.  The buffer must have been created using
1001  // new char[].
1002  // If |owns_buffer| is false, the caller retains ownership of the buffer and
1003  // is responsible for making sure the buffer outlives this frame.  In other
1004  // words, this class does NOT create a copy of the buffer.
1005  SpdyFrame(char* data, size_t size, bool owns_buffer)
1006      : frame_(data),
1007        size_(size),
1008        owns_buffer_(owns_buffer) {
1009    DCHECK(frame_);
1010  }
1011
1012  ~SpdyFrame() {
1013    if (owns_buffer_) {
1014      delete [] frame_;
1015    }
1016    frame_ = NULL;
1017  }
1018
1019  // Provides access to the frame bytes, which is a buffer containing
1020  // the frame packed as expected for sending over the wire.
1021  char* data() const { return frame_; }
1022
1023  // Returns the actual size of the underlying buffer.
1024  size_t size() const { return size_; }
1025
1026 protected:
1027  char* frame_;
1028
1029 private:
1030  size_t size_;
1031  bool owns_buffer_;
1032  DISALLOW_COPY_AND_ASSIGN(SpdyFrame);
1033};
1034
1035// This interface is for classes that want to process SpdyFrameIRs without
1036// having to know what type they are.  An instance of this interface can be
1037// passed to a SpdyFrameIR's Visit method, and the appropriate type-specific
1038// method of this class will be called.
1039class SpdyFrameVisitor {
1040 public:
1041  virtual void VisitSynStream(const SpdySynStreamIR& syn_stream) = 0;
1042  virtual void VisitSynReply(const SpdySynReplyIR& syn_reply) = 0;
1043  virtual void VisitRstStream(const SpdyRstStreamIR& rst_stream) = 0;
1044  virtual void VisitSettings(const SpdySettingsIR& settings) = 0;
1045  virtual void VisitPing(const SpdyPingIR& ping) = 0;
1046  virtual void VisitGoAway(const SpdyGoAwayIR& goaway) = 0;
1047  virtual void VisitHeaders(const SpdyHeadersIR& headers) = 0;
1048  virtual void VisitWindowUpdate(const SpdyWindowUpdateIR& window_update) = 0;
1049  virtual void VisitBlocked(const SpdyBlockedIR& blocked) = 0;
1050  virtual void VisitPushPromise(const SpdyPushPromiseIR& push_promise) = 0;
1051  virtual void VisitContinuation(const SpdyContinuationIR& continuation) = 0;
1052  virtual void VisitAltSvc(const SpdyAltSvcIR& altsvc) = 0;
1053  virtual void VisitPriority(const SpdyPriorityIR& priority) = 0;
1054  virtual void VisitData(const SpdyDataIR& data) = 0;
1055
1056 protected:
1057  SpdyFrameVisitor() {}
1058  virtual ~SpdyFrameVisitor() {}
1059
1060 private:
1061  DISALLOW_COPY_AND_ASSIGN(SpdyFrameVisitor);
1062};
1063
1064}  // namespace net
1065
1066#endif  // NET_SPDY_SPDY_PROTOCOL_H_
1067