// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file contains some protocol structures for use with SPDY 2 and 3 // The SPDY 2 spec can be found at: // http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft2 // The SPDY 3 spec can be found at: // http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3 #ifndef NET_SPDY_SPDY_PROTOCOL_H_ #define NET_SPDY_SPDY_PROTOCOL_H_ #include #include #include #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string_piece.h" #include "base/sys_byteorder.h" #include "net/base/net_export.h" #include "net/spdy/spdy_bitmasks.h" namespace net { // The major versions of SPDY. Major version differences indicate // framer-layer incompatibility, as opposed to minor version numbers // which indicate application-layer incompatibility. It is guaranteed // that the enum value SPDYn maps to the integer n. enum SpdyMajorVersion { SPDY2 = 2, SPDY_MIN_VERSION = SPDY2, SPDY3 = 3, SPDY4 = 4, SPDY_MAX_VERSION = SPDY4 }; // A SPDY stream id is a 31 bit entity. typedef uint32 SpdyStreamId; // Specifies the stream ID used to denote the current session (for // flow control). const SpdyStreamId kSessionFlowControlStreamId = 0; // Initial window size for a Spdy stream in bytes. const int32 kSpdyStreamInitialWindowSize = 64 * 1024; // 64 KBytes // Initial window size for a Spdy session in bytes. const int32 kSpdySessionInitialWindowSize = 64 * 1024; // 64 KBytes // Maximum window size for a Spdy stream or session. const int32 kSpdyMaximumWindowSize = 0x7FFFFFFF; // Max signed 32bit int // SPDY 2 dictionary. // This is just a hacked dictionary to use for shrinking HTTP-like headers. const char kV2Dictionary[] = "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-" "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi" "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser" "-agent10010120020120220320420520630030130230330430530630740040140240340440" "5406407408409410411412413414415416417500501502503504505accept-rangesageeta" "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic" "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran" "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati" "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo" "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe" "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic" "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1" ".1statusversionurl"; const int kV2DictionarySize = arraysize(kV2Dictionary); // SPDY 3 dictionary. const char kV3Dictionary[] = { 0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, // ....opti 0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, // ons....h 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, // ead....p 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, // ost....p 0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, // ut....de 0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, // lete.... 0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, // trace... 0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, // .accept. 0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, // ...accep 0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // t-charse 0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, // t....acc 0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // ept-enco 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, // ding.... 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, // accept-l 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, // anguage. 0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, // ...accep 0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, // t-ranges 0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, // ....age. 0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, // ...allow 0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, // ....auth 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, // orizatio 0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, // n....cac 0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, // he-contr 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, // ol....co 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, // nnection 0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, // ....cont 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, // ent-base 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, // ....cont 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // ent-enco 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, // ding.... 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, // content- 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, // language 0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, // ....cont 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, // ent-leng 0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, // th....co 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, // ntent-lo 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, // cation.. 0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // ..conten 0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, // t-md5... 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, // .content 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, // -range.. 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // ..conten 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, // t-type.. 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, // ..date.. 0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, // ..etag.. 0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, // ..expect 0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, // ....expi 0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, // res....f 0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, // rom....h 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, // ost....i 0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, // f-match. 0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, // ...if-mo 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, // dified-s 0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, // ince.... 0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, // if-none- 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, // match... 0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, // .if-rang 0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, // e....if- 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, // unmodifi 0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, // ed-since 0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, // ....last 0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, // -modifie 0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, // d....loc 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, // ation... 0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, // .max-for 0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, // wards... 0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, // .pragma. 0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, // ...proxy 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, // -authent 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, // icate... 0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, // .proxy-a 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, // uthoriza 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, // tion.... 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, // range... 0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, // .referer 0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, // ....retr 0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, // y-after. 0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, // ...serve 0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, // r....te. 0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, // ...trail 0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, // er....tr 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, // ansfer-e 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, // ncoding. 0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, // ...upgra 0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, // de....us 0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, // er-agent 0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, // ....vary 0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, // ....via. 0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, // ...warni 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, // ng....ww 0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, // w-authen 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, // ticate.. 0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, // ..method 0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, // ....get. 0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, // ...statu 0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, // s....200 0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, // .OK....v 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, // ersion.. 0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, // ..HTTP.1 0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, // .1....ur 0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, // l....pub 0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, // lic....s 0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, // et-cooki 0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, // e....kee 0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, // p-alive. 0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, // ...origi 0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, // n1001012 0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, // 01202205 0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, // 20630030 0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, // 23033043 0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, // 05306307 0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, // 40240540 0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, // 64074084 0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, // 09410411 0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, // 41241341 0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, // 44154164 0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, // 17502504 0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, // 505203.N 0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, // on-Autho 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, // ritative 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, // .Informa 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, // tion204. 0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, // No.Conte 0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, // nt301.Mo 0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, // ved.Perm 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, // anently4 0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, // 00.Bad.R 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, // equest40 0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, // 1.Unauth 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, // orized40 0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, // 3.Forbid 0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, // den404.N 0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, // ot.Found 0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, // 500.Inte 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, // rnal.Ser 0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, // ver.Erro 0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, // r501.Not 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, // .Impleme 0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, // nted503. 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, // Service. 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, // Unavaila 0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, // bleJan.F 0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, // eb.Mar.A 0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, // pr.May.J 0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, // un.Jul.A 0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, // ug.Sept. 0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, // Oct.Nov. 0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, // Dec.00.0 0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, // 0.00.Mon 0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, // ..Tue..W 0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, // ed..Thu. 0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, // .Fri..Sa 0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, // t..Sun.. 0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, // GMTchunk 0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, // ed.text. 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, // html.ima 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, // ge.png.i 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, // mage.jpg 0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, // .image.g 0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // if.appli 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // cation.x 0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // ml.appli 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // cation.x 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, // html.xml 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, // .text.pl 0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, // ain.text 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, // .javascr 0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, // ipt.publ 0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, // icprivat 0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, // emax-age 0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, // .gzip.de 0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, // flate.sd 0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // chcharse 0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, // t.utf-8c 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, // harset.i 0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, // so-8859- 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, // 1.utf-.. 0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e // .enq.0. }; const int kV3DictionarySize = arraysize(kV3Dictionary); // The HTTP/2 connection header prefix, which must be the first bytes // sent by the client upon starting an HTTP/2 connection, and which // must be followed by a SETTINGS frame. // // Equivalent to the string "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" // (without the null terminator). const char kHttp2ConnectionHeaderPrefix[] = { 0x50, 0x52, 0x49, 0x20, 0x2a, 0x20, 0x48, 0x54, // PRI * HT 0x54, 0x50, 0x2f, 0x32, 0x2e, 0x30, 0x0d, 0x0a, // TP/2.0.. 0x0d, 0x0a, 0x53, 0x4d, 0x0d, 0x0a, 0x0d, 0x0a // ..SM.... }; const int kHttp2ConnectionHeaderPrefixSize = arraysize(kHttp2ConnectionHeaderPrefix); // Types of SPDY frames. enum SpdyFrameType { DATA = 0, SYN_STREAM = 1, FIRST_CONTROL_TYPE = SYN_STREAM, SYN_REPLY, RST_STREAM, SETTINGS, NOOP, // Because it is valid in SPDY/2, kept for identifiability/enum order. PING, GOAWAY, HEADERS, WINDOW_UPDATE, CREDENTIAL, BLOCKED, PUSH_PROMISE, LAST_CONTROL_TYPE = PUSH_PROMISE }; // Flags on data packets. enum SpdyDataFlags { DATA_FLAG_NONE = 0, DATA_FLAG_FIN = 1, }; // Flags on control packets enum SpdyControlFlags { CONTROL_FLAG_NONE = 0, CONTROL_FLAG_FIN = 1, CONTROL_FLAG_UNIDIRECTIONAL = 2 }; // Flags on the SETTINGS control frame. enum SpdySettingsControlFlags { SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS = 0x1 }; // Flags for settings within a SETTINGS frame. enum SpdySettingsFlags { SETTINGS_FLAG_NONE = 0x0, SETTINGS_FLAG_PLEASE_PERSIST = 0x1, SETTINGS_FLAG_PERSISTED = 0x2 }; // List of known settings. enum SpdySettingsIds { SETTINGS_UPLOAD_BANDWIDTH = 0x1, SETTINGS_DOWNLOAD_BANDWIDTH = 0x2, // Network round trip time in milliseconds. SETTINGS_ROUND_TRIP_TIME = 0x3, SETTINGS_MAX_CONCURRENT_STREAMS = 0x4, // TCP congestion window in packets. SETTINGS_CURRENT_CWND = 0x5, // Downstream byte retransmission rate in percentage. SETTINGS_DOWNLOAD_RETRANS_RATE = 0x6, // Initial window size in bytes SETTINGS_INITIAL_WINDOW_SIZE = 0x7 }; // Status codes for RST_STREAM frames. enum SpdyRstStreamStatus { RST_STREAM_INVALID = 0, RST_STREAM_PROTOCOL_ERROR = 1, RST_STREAM_INVALID_STREAM = 2, RST_STREAM_REFUSED_STREAM = 3, RST_STREAM_UNSUPPORTED_VERSION = 4, RST_STREAM_CANCEL = 5, RST_STREAM_INTERNAL_ERROR = 6, RST_STREAM_FLOW_CONTROL_ERROR = 7, RST_STREAM_STREAM_IN_USE = 8, RST_STREAM_STREAM_ALREADY_CLOSED = 9, RST_STREAM_INVALID_CREDENTIALS = 10, RST_STREAM_FRAME_TOO_LARGE = 11, RST_STREAM_NUM_STATUS_CODES = 12 }; // Status codes for GOAWAY frames. enum SpdyGoAwayStatus { GOAWAY_INVALID = -1, GOAWAY_OK = 0, GOAWAY_PROTOCOL_ERROR = 1, GOAWAY_INTERNAL_ERROR = 2, GOAWAY_NUM_STATUS_CODES = 3 }; // A SPDY priority is a number between 0 and 7 (inclusive). // SPDY priority range is version-dependant. For SPDY 2 and below, priority is a // number between 0 and 3. typedef uint8 SpdyPriority; typedef uint8 SpdyCredentialSlot; typedef std::map SpdyNameValueBlock; typedef uint32 SpdyPingId; class SpdyFrame; typedef SpdyFrame SpdySerializedFrame; class SpdyFrameVisitor; // Intermediate representation for SPDY frames. // TODO(hkhalil): Rename this class to SpdyFrame when the existing SpdyFrame is // gone. class SpdyFrameIR { public: virtual ~SpdyFrameIR() {} virtual void Visit(SpdyFrameVisitor* visitor) const = 0; protected: SpdyFrameIR() {} private: DISALLOW_COPY_AND_ASSIGN(SpdyFrameIR); }; // Abstract class intended to be inherited by IRs that have a stream associated // to them. class SpdyFrameWithStreamIdIR : public SpdyFrameIR { public: virtual ~SpdyFrameWithStreamIdIR() {} SpdyStreamId stream_id() const { return stream_id_; } void set_stream_id(SpdyStreamId stream_id) { DCHECK_EQ(0u, stream_id & ~kStreamIdMask); stream_id_ = stream_id; } protected: explicit SpdyFrameWithStreamIdIR(SpdyStreamId stream_id) { set_stream_id(stream_id); } private: SpdyStreamId stream_id_; DISALLOW_COPY_AND_ASSIGN(SpdyFrameWithStreamIdIR); }; // Abstract class intended to be inherited by IRs that have the option of a FIN // flag. Implies SpdyFrameWithStreamIdIR. class SpdyFrameWithFinIR : public SpdyFrameWithStreamIdIR { public: virtual ~SpdyFrameWithFinIR() {} bool fin() const { return fin_; } void set_fin(bool fin) { fin_ = fin; } protected: explicit SpdyFrameWithFinIR(SpdyStreamId stream_id) : SpdyFrameWithStreamIdIR(stream_id), fin_(false) {} private: bool fin_; DISALLOW_COPY_AND_ASSIGN(SpdyFrameWithFinIR); }; // Abstract class intended to be inherited by IRs that contain a name-value // block. Implies SpdyFrameWithFinIR. class NET_EXPORT_PRIVATE SpdyFrameWithNameValueBlockIR : public NON_EXPORTED_BASE(SpdyFrameWithFinIR) { public: const SpdyNameValueBlock& name_value_block() const { return name_value_block_; } SpdyNameValueBlock* GetMutableNameValueBlock() { return &name_value_block_; } void SetHeader(const base::StringPiece& name, const base::StringPiece& value) { name_value_block_[name.as_string()] = value.as_string(); } protected: explicit SpdyFrameWithNameValueBlockIR(SpdyStreamId stream_id); virtual ~SpdyFrameWithNameValueBlockIR(); private: SpdyNameValueBlock name_value_block_; DISALLOW_COPY_AND_ASSIGN(SpdyFrameWithNameValueBlockIR); }; class NET_EXPORT_PRIVATE SpdyDataIR : public NON_EXPORTED_BASE(SpdyFrameWithFinIR) { public: // Performs deep copy on data. SpdyDataIR(SpdyStreamId stream_id, const base::StringPiece& data); // Use in conjunction with SetDataShallow() for shallow-copy on data. explicit SpdyDataIR(SpdyStreamId stream_id); virtual ~SpdyDataIR(); base::StringPiece data() const { return data_; } // Deep-copy of data (keep private copy). void SetDataDeep(const base::StringPiece& data) { data_store_.reset(new std::string(data.data(), data.length())); data_ = *(data_store_.get()); } // Shallow-copy of data (do not keep private copy). void SetDataShallow(const base::StringPiece& data) { data_store_.reset(); data_ = data; } virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE; private: // Used to store data that this SpdyDataIR should own. scoped_ptr data_store_; base::StringPiece data_; DISALLOW_COPY_AND_ASSIGN(SpdyDataIR); }; class NET_EXPORT_PRIVATE SpdySynStreamIR : public SpdyFrameWithNameValueBlockIR { public: explicit SpdySynStreamIR(SpdyStreamId stream_id) : SpdyFrameWithNameValueBlockIR(stream_id), associated_to_stream_id_(0), priority_(0), slot_(0), unidirectional_(false) {} SpdyStreamId associated_to_stream_id() const { return associated_to_stream_id_; } void set_associated_to_stream_id(SpdyStreamId stream_id) { associated_to_stream_id_ = stream_id; } SpdyPriority priority() const { return priority_; } void set_priority(SpdyPriority priority) { priority_ = priority; } SpdyCredentialSlot slot() const { return slot_; } void set_slot(SpdyCredentialSlot slot) { slot_ = slot; } bool unidirectional() const { return unidirectional_; } void set_unidirectional(bool unidirectional) { unidirectional_ = unidirectional; } virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE; private: SpdyStreamId associated_to_stream_id_; SpdyPriority priority_; SpdyCredentialSlot slot_; bool unidirectional_; DISALLOW_COPY_AND_ASSIGN(SpdySynStreamIR); }; class SpdySynReplyIR : public SpdyFrameWithNameValueBlockIR { public: explicit SpdySynReplyIR(SpdyStreamId stream_id) : SpdyFrameWithNameValueBlockIR(stream_id) {} virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE; private: DISALLOW_COPY_AND_ASSIGN(SpdySynReplyIR); }; class SpdyRstStreamIR : public SpdyFrameWithStreamIdIR { public: SpdyRstStreamIR(SpdyStreamId stream_id, SpdyRstStreamStatus status) : SpdyFrameWithStreamIdIR(stream_id) { set_status(status); } SpdyRstStreamStatus status() const { return status_; } void set_status(SpdyRstStreamStatus status) { DCHECK_NE(status, RST_STREAM_INVALID); DCHECK_LT(status, RST_STREAM_NUM_STATUS_CODES); status_ = status; } virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE; private: SpdyRstStreamStatus status_; DISALLOW_COPY_AND_ASSIGN(SpdyRstStreamIR); }; class SpdySettingsIR : public SpdyFrameIR { public: // Associates flags with a value. struct Value { Value() : persist_value(false), persisted(false), value(0) {} bool persist_value; bool persisted; int32 value; }; typedef std::map ValueMap; SpdySettingsIR(); virtual ~SpdySettingsIR(); // Overwrites as appropriate. const ValueMap& values() const { return values_; } void AddSetting(SpdySettingsIds id, bool persist_value, bool persisted, int32 value) { // TODO(hkhalil): DCHECK_LE(SETTINGS_UPLOAD_BANDWIDTH, id); // TODO(hkhalil): DCHECK_GE(SETTINGS_INITIAL_WINDOW_SIZE, id); values_[id].persist_value = persist_value; values_[id].persisted = persisted; values_[id].value = value; } bool clear_settings() const { return clear_settings_; } void set_clear_settings(bool clear_settings) { clear_settings_ = clear_settings; } virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE; private: ValueMap values_; bool clear_settings_; DISALLOW_COPY_AND_ASSIGN(SpdySettingsIR); }; class SpdyPingIR : public SpdyFrameIR { public: explicit SpdyPingIR(SpdyPingId id) : id_(id) {} SpdyPingId id() const { return id_; } virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE; private: SpdyPingId id_; DISALLOW_COPY_AND_ASSIGN(SpdyPingIR); }; class SpdyGoAwayIR : public SpdyFrameIR { public: SpdyGoAwayIR(SpdyStreamId last_good_stream_id, SpdyGoAwayStatus status) { set_last_good_stream_id(last_good_stream_id); set_status(status); } SpdyStreamId last_good_stream_id() const { return last_good_stream_id_; } void set_last_good_stream_id(SpdyStreamId last_good_stream_id) { DCHECK_LE(0u, last_good_stream_id); DCHECK_EQ(0u, last_good_stream_id & ~kStreamIdMask); last_good_stream_id_ = last_good_stream_id; } SpdyGoAwayStatus status() const { return status_; } void set_status(SpdyGoAwayStatus status) { // TODO(hkhalil): Check valid ranges of status? status_ = status; } virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE; private: SpdyStreamId last_good_stream_id_; SpdyGoAwayStatus status_; DISALLOW_COPY_AND_ASSIGN(SpdyGoAwayIR); }; class SpdyHeadersIR : public SpdyFrameWithNameValueBlockIR { public: explicit SpdyHeadersIR(SpdyStreamId stream_id) : SpdyFrameWithNameValueBlockIR(stream_id) {} virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE; private: DISALLOW_COPY_AND_ASSIGN(SpdyHeadersIR); }; class SpdyWindowUpdateIR : public SpdyFrameWithStreamIdIR { public: SpdyWindowUpdateIR(SpdyStreamId stream_id, int32 delta) : SpdyFrameWithStreamIdIR(stream_id) { set_delta(delta); } int32 delta() const { return delta_; } void set_delta(int32 delta) { DCHECK_LT(0, delta); DCHECK_LE(delta, kSpdyMaximumWindowSize); delta_ = delta; } virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE; private: int32 delta_; DISALLOW_COPY_AND_ASSIGN(SpdyWindowUpdateIR); }; class SpdyCredentialIR : public SpdyFrameIR { public: typedef std::vector CertificateList; explicit SpdyCredentialIR(int16 slot); virtual ~SpdyCredentialIR(); int16 slot() const { return slot_; } void set_slot(int16 slot) { // TODO(hkhalil): Verify valid slot range? slot_ = slot; } base::StringPiece proof() const { return proof_; } void set_proof(const base::StringPiece& proof) { proof.CopyToString(&proof_); } const CertificateList* certificates() const { return &certificates_; } void AddCertificate(const base::StringPiece& certificate) { certificates_.push_back(certificate.as_string()); } virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE; private: int16 slot_; std::string proof_; CertificateList certificates_; DISALLOW_COPY_AND_ASSIGN(SpdyCredentialIR); }; class NET_EXPORT_PRIVATE SpdyBlockedIR : public NON_EXPORTED_BASE(SpdyFrameWithStreamIdIR) { public: explicit SpdyBlockedIR(SpdyStreamId stream_id) : SpdyFrameWithStreamIdIR(stream_id) {} virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE; private: DISALLOW_COPY_AND_ASSIGN(SpdyBlockedIR); }; class SpdyPushPromiseIR : public SpdyFrameWithNameValueBlockIR { public: SpdyPushPromiseIR(SpdyStreamId stream_id, SpdyStreamId promised_stream_id) : SpdyFrameWithNameValueBlockIR(stream_id), promised_stream_id_(promised_stream_id) {} SpdyStreamId promised_stream_id() const { return promised_stream_id_; } void set_promised_stream_id(SpdyStreamId id) { promised_stream_id_ = id; } virtual void Visit(SpdyFrameVisitor* visitor) const OVERRIDE; private: SpdyStreamId promised_stream_id_; DISALLOW_COPY_AND_ASSIGN(SpdyPushPromiseIR); }; // ------------------------------------------------------------------------- // Wrapper classes for various SPDY frames. // All Spdy Frame types derive from this SpdyFrame class. class SpdyFrame { public: // Create a SpdyFrame using a pre-created buffer. // If |owns_buffer| is true, this class takes ownership of the buffer // and will delete it on cleanup. The buffer must have been created using // new char[]. // If |owns_buffer| is false, the caller retains ownership of the buffer and // is responsible for making sure the buffer outlives this frame. In other // words, this class does NOT create a copy of the buffer. SpdyFrame(char* data, size_t size, bool owns_buffer) : frame_(data), size_(size), owns_buffer_(owns_buffer) { DCHECK(frame_); } ~SpdyFrame() { if (owns_buffer_) { delete [] frame_; } frame_ = NULL; } // Provides access to the frame bytes, which is a buffer containing // the frame packed as expected for sending over the wire. char* data() const { return frame_; } // Returns the actual size of the underlying buffer. size_t size() const { return size_; } protected: char* frame_; private: size_t size_; bool owns_buffer_; DISALLOW_COPY_AND_ASSIGN(SpdyFrame); }; // This interface is for classes that want to process SpdyFrameIRs without // having to know what type they are. An instance of this interface can be // passed to a SpdyFrameIR's Visit method, and the appropriate type-specific // method of this class will be called. class SpdyFrameVisitor { public: virtual void VisitSynStream(const SpdySynStreamIR& syn_stream) = 0; virtual void VisitSynReply(const SpdySynReplyIR& syn_reply) = 0; virtual void VisitRstStream(const SpdyRstStreamIR& rst_stream) = 0; virtual void VisitSettings(const SpdySettingsIR& settings) = 0; virtual void VisitPing(const SpdyPingIR& ping) = 0; virtual void VisitGoAway(const SpdyGoAwayIR& goaway) = 0; virtual void VisitHeaders(const SpdyHeadersIR& headers) = 0; virtual void VisitWindowUpdate(const SpdyWindowUpdateIR& window_update) = 0; virtual void VisitCredential(const SpdyCredentialIR& credential) = 0; virtual void VisitBlocked(const SpdyBlockedIR& blocked) = 0; virtual void VisitPushPromise(const SpdyPushPromiseIR& push_promise) = 0; virtual void VisitData(const SpdyDataIR& data) = 0; protected: SpdyFrameVisitor() {} virtual ~SpdyFrameVisitor() {} private: DISALLOW_COPY_AND_ASSIGN(SpdyFrameVisitor); }; } // namespace net #endif // NET_SPDY_SPDY_PROTOCOL_H_