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