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