spdy_protocol.h revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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// TODO(akalin): Convert this to an enum.
30const int32 kSpdyVersion2 = 2;
31const int32 kSpdyVersion3 = 3;
32const int32 kSpdyVersion4 = 4;
33
34// A SPDY stream id is a 31 bit entity.
35typedef uint32 SpdyStreamId;
36
37// Specifies the stream ID used to denote the current session (for
38// flow control).
39const SpdyStreamId kSessionFlowControlStreamId = 0;
40
41// Initial window size for a Spdy stream.
42const int32 kSpdyStreamInitialWindowSize = 64 * 1024;  // 64 KBytes
43
44// Initial window size for a Spdy session.
45const int32 kSpdySessionInitialWindowSize = 64 * 1024;  // 64 KBytes
46
47// Maximum window size for a Spdy stream or session.
48const int32 kSpdyMaximumWindowSize = 0x7FFFFFFF;  // Max signed 32bit int
49
50// SPDY 2 dictionary.
51// This is just a hacked dictionary to use for shrinking HTTP-like headers.
52const char kV2Dictionary[] =
53  "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-"
54  "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi"
55  "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser"
56  "-agent10010120020120220320420520630030130230330430530630740040140240340440"
57  "5406407408409410411412413414415416417500501502503504505accept-rangesageeta"
58  "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic"
59  "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran"
60  "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati"
61  "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo"
62  "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe"
63  "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic"
64  "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1"
65  ".1statusversionurl";
66const int kV2DictionarySize = arraysize(kV2Dictionary);
67
68// SPDY 3 dictionary.
69const char kV3Dictionary[] = {
70  0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69,  // ....opti
71  0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68,  // ons....h
72  0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70,  // ead....p
73  0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70,  // ost....p
74  0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65,  // ut....de
75  0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05,  // lete....
76  0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00,  // trace...
77  0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00,  // .accept.
78  0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70,  // ...accep
79  0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65,  // t-charse
80  0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63,  // t....acc
81  0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f,  // ept-enco
82  0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f,  // ding....
83  0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c,  // accept-l
84  0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00,  // anguage.
85  0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70,  // ...accep
86  0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73,  // t-ranges
87  0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00,  // ....age.
88  0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77,  // ...allow
89  0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68,  // ....auth
90  0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f,  // orizatio
91  0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63,  // n....cac
92  0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72,  // he-contr
93  0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f,  // ol....co
94  0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,  // nnection
95  0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74,  // ....cont
96  0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65,  // ent-base
97  0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74,  // ....cont
98  0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f,  // ent-enco
99  0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10,  // ding....
100  0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d,  // content-
101  0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65,  // language
102  0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74,  // ....cont
103  0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67,  // ent-leng
104  0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f,  // th....co
105  0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f,  // ntent-lo
106  0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,  // cation..
107  0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,  // ..conten
108  0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00,  // t-md5...
109  0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,  // .content
110  0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00,  // -range..
111  0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,  // ..conten
112  0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00,  // t-type..
113  0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00,  // ..date..
114  0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00,  // ..etag..
115  0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74,  // ..expect
116  0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69,  // ....expi
117  0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66,  // res....f
118  0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68,  // rom....h
119  0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69,  // ost....i
120  0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00,  // f-match.
121  0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f,  // ...if-mo
122  0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73,  // dified-s
123  0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d,  // ince....
124  0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d,  // if-none-
125  0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00,  // match...
126  0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67,  // .if-rang
127  0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d,  // e....if-
128  0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69,  // unmodifi
129  0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65,  // ed-since
130  0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74,  // ....last
131  0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65,  // -modifie
132  0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63,  // d....loc
133  0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00,  // ation...
134  0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72,  // .max-for
135  0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00,  // wards...
136  0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00,  // .pragma.
137  0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79,  // ...proxy
138  0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74,  // -authent
139  0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00,  // icate...
140  0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61,  // .proxy-a
141  0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61,  // uthoriza
142  0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05,  // tion....
143  0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00,  // range...
144  0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72,  // .referer
145  0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72,  // ....retr
146  0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00,  // y-after.
147  0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65,  // ...serve
148  0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00,  // r....te.
149  0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c,  // ...trail
150  0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72,  // er....tr
151  0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65,  // ansfer-e
152  0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00,  // ncoding.
153  0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61,  // ...upgra
154  0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73,  // de....us
155  0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74,  // er-agent
156  0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79,  // ....vary
157  0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00,  // ....via.
158  0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69,  // ...warni
159  0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77,  // ng....ww
160  0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e,  // w-authen
161  0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00,  // ticate..
162  0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64,  // ..method
163  0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00,  // ....get.
164  0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,  // ...statu
165  0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30,  // s....200
166  0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76,  // .OK....v
167  0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00,  // ersion..
168  0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31,  // ..HTTP.1
169  0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72,  // .1....ur
170  0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62,  // l....pub
171  0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73,  // lic....s
172  0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69,  // et-cooki
173  0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65,  // e....kee
174  0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00,  // p-alive.
175  0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69,  // ...origi
176  0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32,  // n1001012
177  0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35,  // 01202205
178  0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30,  // 20630030
179  0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33,  // 23033043
180  0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37,  // 05306307
181  0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30,  // 40240540
182  0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34,  // 64074084
183  0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31,  // 09410411
184  0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31,  // 41241341
185  0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34,  // 44154164
186  0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34,  // 17502504
187  0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e,  // 505203.N
188  0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f,  // on-Autho
189  0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65,  // ritative
190  0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61,  // .Informa
191  0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20,  // tion204.
192  0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65,  // No.Conte
193  0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f,  // nt301.Mo
194  0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d,  // ved.Perm
195  0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34,  // anently4
196  0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52,  // 00.Bad.R
197  0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30,  // equest40
198  0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68,  // 1.Unauth
199  0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30,  // orized40
200  0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64,  // 3.Forbid
201  0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e,  // den404.N
202  0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64,  // ot.Found
203  0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65,  // 500.Inte
204  0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72,  // rnal.Ser
205  0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f,  // ver.Erro
206  0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74,  // r501.Not
207  0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65,  // .Impleme
208  0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20,  // nted503.
209  0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20,  // Service.
210  0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61,  // Unavaila
211  0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46,  // bleJan.F
212  0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41,  // eb.Mar.A
213  0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a,  // pr.May.J
214  0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41,  // un.Jul.A
215  0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20,  // ug.Sept.
216  0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20,  // Oct.Nov.
217  0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30,  // Dec.00.0
218  0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e,  // 0.00.Mon
219  0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57,  // ..Tue..W
220  0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c,  // ed..Thu.
221  0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61,  // .Fri..Sa
222  0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20,  // t..Sun..
223  0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b,  // GMTchunk
224  0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f,  // ed.text.
225  0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61,  // html.ima
226  0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69,  // ge.png.i
227  0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67,  // mage.jpg
228  0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67,  // .image.g
229  0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69,  // if.appli
230  0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78,  // cation.x
231  0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69,  // ml.appli
232  0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78,  // cation.x
233  0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c,  // html.xml
234  0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c,  // .text.pl
235  0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74,  // ain.text
236  0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72,  // .javascr
237  0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c,  // ipt.publ
238  0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74,  // icprivat
239  0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65,  // emax-age
240  0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65,  // .gzip.de
241  0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64,  // flate.sd
242  0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65,  // chcharse
243  0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63,  // t.utf-8c
244  0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69,  // harset.i
245  0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d,  // so-8859-
246  0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a,  // 1.utf-..
247  0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e         // .enq.0.
248};
249const int kV3DictionarySize = arraysize(kV3Dictionary);
250
251// Note: all protocol data structures are on-the-wire format.  That means that
252//       data is stored in network-normalized order.  Readers must use the
253//       accessors provided or call base::NetworkToHostX() functions.
254// TODO(hkhalil): remove above note.
255
256// Types of SPDY frames.
257enum SpdyFrameType {
258  DATA = 0,
259  SYN_STREAM = 1,
260  FIRST_CONTROL_TYPE = SYN_STREAM,
261  SYN_REPLY,
262  RST_STREAM,
263  SETTINGS,
264  NOOP,  // Because it is valid in SPDY/2, kept for identifiability/enum order.
265  PING,
266  GOAWAY,
267  HEADERS,
268  WINDOW_UPDATE,
269  CREDENTIAL,
270  LAST_CONTROL_TYPE = CREDENTIAL
271};
272
273// Flags on data packets.
274enum SpdyDataFlags {
275  DATA_FLAG_NONE = 0,
276  DATA_FLAG_FIN = 1,
277};
278
279// Flags on control packets
280enum SpdyControlFlags {
281  CONTROL_FLAG_NONE = 0,
282  CONTROL_FLAG_FIN = 1,
283  CONTROL_FLAG_UNIDIRECTIONAL = 2
284};
285
286// Flags on the SETTINGS control frame.
287enum SpdySettingsControlFlags {
288  SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS = 0x1
289};
290
291// Flags for settings within a SETTINGS frame.
292enum SpdySettingsFlags {
293  SETTINGS_FLAG_NONE = 0x0,
294  SETTINGS_FLAG_PLEASE_PERSIST = 0x1,
295  SETTINGS_FLAG_PERSISTED = 0x2
296};
297
298// List of known settings.
299enum SpdySettingsIds {
300  SETTINGS_UPLOAD_BANDWIDTH = 0x1,
301  SETTINGS_DOWNLOAD_BANDWIDTH = 0x2,
302  // Network round trip time in milliseconds.
303  SETTINGS_ROUND_TRIP_TIME = 0x3,
304  SETTINGS_MAX_CONCURRENT_STREAMS = 0x4,
305  // TCP congestion window in packets.
306  SETTINGS_CURRENT_CWND = 0x5,
307  // Downstream byte retransmission rate in percentage.
308  SETTINGS_DOWNLOAD_RETRANS_RATE = 0x6,
309  // Initial window size in bytes
310  SETTINGS_INITIAL_WINDOW_SIZE = 0x7
311};
312
313// Status codes for RST_STREAM frames.
314enum SpdyRstStreamStatus {
315  RST_STREAM_INVALID = 0,
316  RST_STREAM_PROTOCOL_ERROR = 1,
317  RST_STREAM_INVALID_STREAM = 2,
318  RST_STREAM_REFUSED_STREAM = 3,
319  RST_STREAM_UNSUPPORTED_VERSION = 4,
320  RST_STREAM_CANCEL = 5,
321  RST_STREAM_INTERNAL_ERROR = 6,
322  RST_STREAM_FLOW_CONTROL_ERROR = 7,
323  RST_STREAM_STREAM_IN_USE = 8,
324  RST_STREAM_STREAM_ALREADY_CLOSED = 9,
325  RST_STREAM_INVALID_CREDENTIALS = 10,
326  RST_STREAM_FRAME_TOO_LARGE = 11,
327  RST_STREAM_NUM_STATUS_CODES = 12
328};
329
330// Status codes for GOAWAY frames.
331enum SpdyGoAwayStatus {
332  GOAWAY_INVALID = -1,
333  GOAWAY_OK = 0,
334  GOAWAY_PROTOCOL_ERROR = 1,
335  GOAWAY_INTERNAL_ERROR = 2,
336  GOAWAY_NUM_STATUS_CODES = 3
337};
338
339// A SPDY priority is a number between 0 and 7 (inclusive).
340// SPDY priority range is version-dependant. For SPDY 2 and below, priority is a
341// number between 0 and 3.
342typedef uint8 SpdyPriority;
343
344typedef uint8 SpdyCredentialSlot;
345
346typedef std::map<std::string, std::string> SpdyNameValueBlock;
347
348typedef uint32 SpdyPingId;
349
350class SpdyFrame;
351typedef SpdyFrame SpdySerializedFrame;
352
353class SpdyFramer;
354class SpdyFrameBuilder;
355
356// Intermediate representation for SPDY frames.
357// TODO(hkhalil): Rename this class to SpdyFrame when the existing SpdyFrame is
358// gone.
359class SpdyFrameIR {
360 public:
361  virtual ~SpdyFrameIR() {}
362
363 protected:
364  SpdyFrameIR() {}
365
366 private:
367  DISALLOW_COPY_AND_ASSIGN(SpdyFrameIR);
368};
369
370// Abstract class intended to be inherited by IRs that have a stream associated
371// to them.
372class SpdyFrameWithStreamIdIR : public SpdyFrameIR {
373 public:
374  virtual ~SpdyFrameWithStreamIdIR() {}
375  SpdyStreamId stream_id() const { return stream_id_; }
376  void set_stream_id(SpdyStreamId stream_id) {
377    // TODO(hkhalil): DCHECK_LT(0u, stream_id);
378    DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
379    stream_id_ = stream_id;
380  }
381
382 protected:
383  explicit SpdyFrameWithStreamIdIR(SpdyStreamId stream_id) {
384    set_stream_id(stream_id);
385  }
386
387 private:
388  SpdyStreamId stream_id_;
389
390  DISALLOW_COPY_AND_ASSIGN(SpdyFrameWithStreamIdIR);
391};
392
393// Abstract class intended to be inherited by IRs that have the option of a FIN
394// flag. Implies SpdyFrameWithStreamIdIR.
395class SpdyFrameWithFinIR : public SpdyFrameWithStreamIdIR {
396 public:
397  virtual ~SpdyFrameWithFinIR() {}
398  bool fin() const { return fin_; }
399  void set_fin(bool fin) { fin_ = fin; }
400
401 protected:
402  explicit SpdyFrameWithFinIR(SpdyStreamId stream_id)
403      : SpdyFrameWithStreamIdIR(stream_id),
404        fin_(false) {}
405
406 private:
407  bool fin_;
408
409  DISALLOW_COPY_AND_ASSIGN(SpdyFrameWithFinIR);
410};
411
412// Abstract class intended to be inherited by IRs that contain a name-value
413// block. Implies SpdyFrameWithFinIR.
414class NET_EXPORT_PRIVATE SpdyFrameWithNameValueBlockIR
415    : public NON_EXPORTED_BASE(SpdyFrameWithFinIR) {
416 public:
417  const SpdyNameValueBlock& name_value_block() const {
418    return name_value_block_;
419  }
420  SpdyNameValueBlock* GetMutableNameValueBlock() { return &name_value_block_; }
421  void SetHeader(const base::StringPiece& name,
422                 const base::StringPiece& value) {
423    name_value_block_[name.as_string()] = value.as_string();
424  }
425
426 protected:
427  explicit SpdyFrameWithNameValueBlockIR(SpdyStreamId stream_id);
428  virtual ~SpdyFrameWithNameValueBlockIR();
429
430 private:
431  SpdyNameValueBlock name_value_block_;
432
433  DISALLOW_COPY_AND_ASSIGN(SpdyFrameWithNameValueBlockIR);
434};
435
436class NET_EXPORT_PRIVATE SpdyDataIR
437    : public NON_EXPORTED_BASE(SpdyFrameWithFinIR) {
438 public:
439  // Performs deep copy on data.
440  SpdyDataIR(SpdyStreamId stream_id, const base::StringPiece& data);
441
442  // Use in conjunction with SetDataShallow() for shallow-copy on data.
443  explicit SpdyDataIR(SpdyStreamId stream_id);
444
445  virtual ~SpdyDataIR();
446
447  base::StringPiece data() const { return data_; }
448
449  // Deep-copy of data (keep private copy).
450  void SetDataDeep(const base::StringPiece& data) {
451    data_store_.reset(new std::string(data.data(), data.length()));
452    data_ = *(data_store_.get());
453  }
454
455  // Shallow-copy of data (do not keep private copy).
456  void SetDataShallow(const base::StringPiece& data) {
457    data_store_.reset();
458    data_ = data;
459  }
460
461 private:
462  // Used to store data that this SpdyDataIR should own.
463  scoped_ptr<std::string> data_store_;
464  base::StringPiece data_;
465
466  DISALLOW_COPY_AND_ASSIGN(SpdyDataIR);
467};
468
469class SpdySynStreamIR : public SpdyFrameWithNameValueBlockIR {
470 public:
471  explicit SpdySynStreamIR(SpdyStreamId stream_id)
472      : SpdyFrameWithNameValueBlockIR(stream_id),
473        associated_to_stream_id_(0),
474        priority_(0),
475        slot_(0),
476        unidirectional_(false) {}
477  SpdyStreamId associated_to_stream_id() const {
478    return associated_to_stream_id_;
479  }
480  void set_associated_to_stream_id(SpdyStreamId stream_id) {
481    associated_to_stream_id_ = stream_id;
482  }
483  SpdyPriority priority() const { return priority_; }
484  void set_priority(SpdyPriority priority) { priority_ = priority; }
485  SpdyCredentialSlot slot() const { return slot_; }
486  void set_slot(SpdyCredentialSlot slot) { slot_ = slot; }
487  bool unidirectional() const { return unidirectional_; }
488  void set_unidirectional(bool unidirectional) {
489    unidirectional_ = unidirectional;
490  }
491
492 private:
493  SpdyStreamId associated_to_stream_id_;
494  SpdyPriority priority_;
495  SpdyCredentialSlot slot_;
496  bool unidirectional_;
497
498  DISALLOW_COPY_AND_ASSIGN(SpdySynStreamIR);
499};
500
501class SpdySynReplyIR : public SpdyFrameWithNameValueBlockIR {
502 public:
503  explicit SpdySynReplyIR(SpdyStreamId stream_id)
504      : SpdyFrameWithNameValueBlockIR(stream_id) {}
505
506 private:
507  DISALLOW_COPY_AND_ASSIGN(SpdySynReplyIR);
508};
509
510class SpdyRstStreamIR : public SpdyFrameWithStreamIdIR {
511 public:
512  SpdyRstStreamIR(SpdyStreamId stream_id, SpdyRstStreamStatus status)
513      : SpdyFrameWithStreamIdIR(stream_id) {
514    set_status(status);
515  }
516  SpdyRstStreamStatus status() const {
517    return status_;
518  }
519  void set_status(SpdyRstStreamStatus status) {
520    DCHECK_NE(status, RST_STREAM_INVALID);
521    DCHECK_LT(status, RST_STREAM_NUM_STATUS_CODES);
522    status_ = status;
523  }
524
525 private:
526  SpdyRstStreamStatus status_;
527
528  DISALLOW_COPY_AND_ASSIGN(SpdyRstStreamIR);
529};
530
531class SpdySettingsIR : public SpdyFrameIR {
532 public:
533  // Associates flags with a value.
534  struct Value {
535    Value() : persist_value(false),
536              persisted(false),
537              value(0) {}
538    bool persist_value;
539    bool persisted;
540    int32 value;
541  };
542  typedef std::map<SpdySettingsIds, Value> ValueMap;
543
544  SpdySettingsIR();
545
546  virtual ~SpdySettingsIR();
547
548  // Overwrites as appropriate.
549  const ValueMap& values() const { return values_; }
550  void AddSetting(SpdySettingsIds id,
551                  bool persist_value,
552                  bool persisted,
553                  int32 value) {
554    // TODO(hkhalil): DCHECK_LE(SETTINGS_UPLOAD_BANDWIDTH, id);
555    // TODO(hkhalil): DCHECK_GE(SETTINGS_INITIAL_WINDOW_SIZE, id);
556    values_[id].persist_value = persist_value;
557    values_[id].persisted = persisted;
558    values_[id].value = value;
559  }
560  bool clear_settings() const { return clear_settings_; }
561  void set_clear_settings(bool clear_settings) {
562    clear_settings_ = clear_settings;
563  }
564
565 private:
566  ValueMap values_;
567  bool clear_settings_;
568
569  DISALLOW_COPY_AND_ASSIGN(SpdySettingsIR);
570};
571
572class SpdyPingIR : public SpdyFrameIR {
573 public:
574  explicit SpdyPingIR(SpdyPingId id) : id_(id) {}
575  SpdyPingId id() const { return id_; }
576
577 private:
578  SpdyPingId id_;
579
580  DISALLOW_COPY_AND_ASSIGN(SpdyPingIR);
581};
582
583class SpdyGoAwayIR : public SpdyFrameIR {
584 public:
585  SpdyGoAwayIR(SpdyStreamId last_good_stream_id, SpdyGoAwayStatus status) {
586    set_last_good_stream_id(last_good_stream_id);
587    set_status(status);
588  }
589  SpdyStreamId last_good_stream_id() const { return last_good_stream_id_; }
590  void set_last_good_stream_id(SpdyStreamId last_good_stream_id) {
591    DCHECK_LE(0u, last_good_stream_id);
592    DCHECK_EQ(0u, last_good_stream_id & ~kStreamIdMask);
593    last_good_stream_id_ = last_good_stream_id;
594  }
595  SpdyGoAwayStatus status() const { return status_; }
596  void set_status(SpdyGoAwayStatus status) {
597    // TODO(hkhalil): Check valid ranges of status?
598    status_ = status;
599  }
600
601 private:
602  SpdyStreamId last_good_stream_id_;
603  SpdyGoAwayStatus status_;
604
605  DISALLOW_COPY_AND_ASSIGN(SpdyGoAwayIR);
606};
607
608class SpdyHeadersIR : public SpdyFrameWithNameValueBlockIR {
609 public:
610  explicit SpdyHeadersIR(SpdyStreamId stream_id)
611      : SpdyFrameWithNameValueBlockIR(stream_id) {}
612
613 private:
614  DISALLOW_COPY_AND_ASSIGN(SpdyHeadersIR);
615};
616
617class SpdyWindowUpdateIR : public SpdyFrameWithStreamIdIR {
618 public:
619  SpdyWindowUpdateIR(SpdyStreamId stream_id, int32 delta)
620      : SpdyFrameWithStreamIdIR(stream_id) {
621    set_delta(delta);
622  }
623  int32 delta() const { return delta_; }
624  void set_delta(int32 delta) {
625    DCHECK_LT(0, delta);
626    DCHECK_LE(delta, kSpdyMaximumWindowSize);
627    delta_ = delta;
628  }
629
630 private:
631  int32 delta_;
632
633  DISALLOW_COPY_AND_ASSIGN(SpdyWindowUpdateIR);
634};
635
636class SpdyCredentialIR : public SpdyFrameIR {
637 public:
638  typedef std::vector<std::string> CertificateList;
639
640  explicit SpdyCredentialIR(int16 slot);
641  virtual ~SpdyCredentialIR();
642
643  int16 slot() const { return slot_; }
644  void set_slot(int16 slot) {
645    // TODO(hkhalil): Verify valid slot range?
646    slot_ = slot;
647  }
648  base::StringPiece proof() const { return proof_; }
649  void set_proof(const base::StringPiece& proof) {
650    proof.CopyToString(&proof_);
651  }
652  const CertificateList* certificates() const { return &certificates_; }
653  void AddCertificate(const base::StringPiece& certificate) {
654    certificates_.push_back(certificate.as_string());
655  }
656
657 private:
658  int16 slot_;
659  std::string proof_;
660  CertificateList certificates_;
661
662  DISALLOW_COPY_AND_ASSIGN(SpdyCredentialIR);
663};
664
665// -------------------------------------------------------------------------
666// Wrapper classes for various SPDY frames.
667
668// All Spdy Frame types derive from this SpdyFrame class.
669class SpdyFrame {
670 public:
671  // Create a SpdyFrame using a pre-created buffer.
672  // If |owns_buffer| is true, this class takes ownership of the buffer
673  // and will delete it on cleanup.  The buffer must have been created using
674  // new char[].
675  // If |owns_buffer| is false, the caller retains ownership of the buffer and
676  // is responsible for making sure the buffer outlives this frame.  In other
677  // words, this class does NOT create a copy of the buffer.
678  SpdyFrame(char* data, size_t size, bool owns_buffer)
679      : frame_(data),
680        size_(size),
681        owns_buffer_(owns_buffer) {
682    DCHECK(frame_);
683  }
684
685  ~SpdyFrame() {
686    if (owns_buffer_) {
687      delete [] frame_;
688    }
689    frame_ = NULL;
690  }
691
692  // Provides access to the frame bytes, which is a buffer containing
693  // the frame packed as expected for sending over the wire.
694  char* data() const { return frame_; }
695
696  // Returns the actual size of the underlying buffer.
697  size_t size() const { return size_; }
698
699 protected:
700  char* frame_;
701
702 private:
703  size_t size_;
704  bool owns_buffer_;
705  DISALLOW_COPY_AND_ASSIGN(SpdyFrame);
706};
707
708}  // namespace net
709
710#endif  // NET_SPDY_SPDY_PROTOCOL_H_
711