|  | // 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. | 
|  |  | 
|  | #ifndef NET_SPDY_SPDY_PROTOCOL_H_ | 
|  | #define NET_SPDY_SPDY_PROTOCOL_H_ | 
|  |  | 
|  | #include <limits> | 
|  |  | 
|  | #include "base/basictypes.h" | 
|  | #include "base/logging.h" | 
|  | #include "base/sys_byteorder.h" | 
|  | #include "net/spdy/spdy_bitmasks.h" | 
|  |  | 
|  | //  Data Frame Format | 
|  | //  +----------------------------------+ | 
|  | //  |0|       Stream-ID (31bits)       | | 
|  | //  +----------------------------------+ | 
|  | //  | flags (8)  |  Length (24 bits)   | | 
|  | //  +----------------------------------+ | 
|  | //  |               Data               | | 
|  | //  +----------------------------------+ | 
|  | // | 
|  | //  Control Frame Format | 
|  | //  +----------------------------------+ | 
|  | //  |1| Version(15bits) | Type(16bits) | | 
|  | //  +----------------------------------+ | 
|  | //  | flags (8)  |  Length (24 bits)   | | 
|  | //  +----------------------------------+ | 
|  | //  |               Data               | | 
|  | //  +----------------------------------+ | 
|  | // | 
|  | //  Control Frame: SYN_STREAM | 
|  | //  +----------------------------------+ | 
|  | //  |1|000000000000001|0000000000000001| | 
|  | //  +----------------------------------+ | 
|  | //  | flags (8)  |  Length (24 bits)   |  >= 12 | 
|  | //  +----------------------------------+ | 
|  | //  |X|       Stream-ID(31bits)        | | 
|  | //  +----------------------------------+ | 
|  | //  |X|Associated-To-Stream-ID (31bits)| | 
|  | //  +----------------------------------+ | 
|  | //  |Pri| unused      | Length (16bits)| | 
|  | //  +----------------------------------+ | 
|  | // | 
|  | //  Control Frame: SYN_REPLY | 
|  | //  +----------------------------------+ | 
|  | //  |1|000000000000001|0000000000000010| | 
|  | //  +----------------------------------+ | 
|  | //  | flags (8)  |  Length (24 bits)   |  >= 8 | 
|  | //  +----------------------------------+ | 
|  | //  |X|       Stream-ID(31bits)        | | 
|  | //  +----------------------------------+ | 
|  | //  | unused (16 bits)| Length (16bits)| | 
|  | //  +----------------------------------+ | 
|  | // | 
|  | //  Control Frame: RST_STREAM | 
|  | //  +----------------------------------+ | 
|  | //  |1|000000000000001|0000000000000011| | 
|  | //  +----------------------------------+ | 
|  | //  | flags (8)  |  Length (24 bits)   |  >= 4 | 
|  | //  +----------------------------------+ | 
|  | //  |X|       Stream-ID(31bits)        | | 
|  | //  +----------------------------------+ | 
|  | //  |        Status code (32 bits)     | | 
|  | //  +----------------------------------+ | 
|  | // | 
|  | //  Control Frame: SETTINGS | 
|  | //  +----------------------------------+ | 
|  | //  |1|000000000000001|0000000000000100| | 
|  | //  +----------------------------------+ | 
|  | //  | flags (8)  |  Length (24 bits)   | | 
|  | //  +----------------------------------+ | 
|  | //  |        # of entries (32)         | | 
|  | //  +----------------------------------+ | 
|  | // | 
|  | //  Control Frame: NOOP | 
|  | //  +----------------------------------+ | 
|  | //  |1|000000000000001|0000000000000101| | 
|  | //  +----------------------------------+ | 
|  | //  | flags (8)  |  Length (24 bits)   | = 0 | 
|  | //  +----------------------------------+ | 
|  | // | 
|  | //  Control Frame: PING | 
|  | //  +----------------------------------+ | 
|  | //  |1|000000000000001|0000000000000110| | 
|  | //  +----------------------------------+ | 
|  | //  | flags (8)  |  Length (24 bits)   | = 4 | 
|  | //  +----------------------------------+ | 
|  | //  |        Unique id (32 bits)       | | 
|  | //  +----------------------------------+ | 
|  | // | 
|  | //  Control Frame: GOAWAY | 
|  | //  +----------------------------------+ | 
|  | //  |1|000000000000001|0000000000000111| | 
|  | //  +----------------------------------+ | 
|  | //  | flags (8)  |  Length (24 bits)   | = 4 | 
|  | //  +----------------------------------+ | 
|  | //  |X|  Last-accepted-stream-id       | | 
|  | //  +----------------------------------+ | 
|  | // | 
|  | //  Control Frame: HEADERS | 
|  | //  +----------------------------------+ | 
|  | //  |1|000000000000001|0000000000001000| | 
|  | //  +----------------------------------+ | 
|  | //  | flags (8)  |  Length (24 bits)   | >= 8 | 
|  | //  +----------------------------------+ | 
|  | //  |X|      Stream-ID (31 bits)       | | 
|  | //  +----------------------------------+ | 
|  | //  | unused (16 bits)| Length (16bits)| | 
|  | //  +----------------------------------+ | 
|  | // | 
|  | //  Control Frame: WINDOW_UPDATE | 
|  | //  +----------------------------------+ | 
|  | //  |1|000000000000001|0000000000001001| | 
|  | //  +----------------------------------+ | 
|  | //  | flags (8)  |  Length (24 bits)   | = 8 | 
|  | //  +----------------------------------+ | 
|  | //  |X|      Stream-ID (31 bits)       | | 
|  | //  +----------------------------------+ | 
|  | //  |   Delta-Window-Size (32 bits)    | | 
|  | //  +----------------------------------+ | 
|  | // | 
|  | //  Control Frame: CREDENTIAL | 
|  | //  +----------------------------------+ | 
|  | //  |1|000000000000001|0000000000001010| | 
|  | //  +----------------------------------+ | 
|  | //  | flags (8)  |  Length (24 bits)   | >= 12 | 
|  | //  +----------------------------------+ | 
|  | //  |  Slot (16 bits) |                | | 
|  | //  +-----------------+                | | 
|  | //  |      Proof Length (32 bits)      | | 
|  | //  +----------------------------------+ | 
|  | //  |               Proof              | | 
|  | //  +----------------------------------+ <+ | 
|  | //  |   Certificate Length (32 bits)   |  | | 
|  | //  +----------------------------------+  | Repeated until end of frame | 
|  | //  |            Certificate           |  | | 
|  | //  +----------------------------------+ <+ | 
|  | // | 
|  |  | 
|  | namespace net { | 
|  |  | 
|  | // Initial window size for a Spdy stream | 
|  | const int32 kSpdyStreamInitialWindowSize = 64 * 1024;  // 64 KBytes | 
|  |  | 
|  | // Maximum window size for a Spdy stream | 
|  | const int32 kSpdyStreamMaximumWindowSize = 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); | 
|  |  | 
|  | // Note: all protocol data structures are on-the-wire format.  That means that | 
|  | //       data is stored in network-normalized order.  Readers must use the | 
|  | //       accessors provided or call ntohX() functions. | 
|  |  | 
|  | // Types of Spdy Control Frames. | 
|  | enum SpdyControlType { | 
|  | SYN_STREAM = 1, | 
|  | SYN_REPLY, | 
|  | RST_STREAM, | 
|  | SETTINGS, | 
|  | NOOP,  // Because it is valid in SPDY/2, kept for identifiability/enum order. | 
|  | PING, | 
|  | GOAWAY, | 
|  | HEADERS, | 
|  | WINDOW_UPDATE, | 
|  | CREDENTIAL, | 
|  | NUM_CONTROL_FRAME_TYPES | 
|  | }; | 
|  |  | 
|  | // 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, as used in control frames (primarily RST_STREAM). | 
|  | // TODO(hkhalil): Rename to SpdyRstStreamStatus | 
|  | enum SpdyStatusCodes { | 
|  | INVALID = 0, | 
|  | PROTOCOL_ERROR = 1, | 
|  | INVALID_STREAM = 2, | 
|  | REFUSED_STREAM = 3, | 
|  | UNSUPPORTED_VERSION = 4, | 
|  | CANCEL = 5, | 
|  | INTERNAL_ERROR = 6, | 
|  | FLOW_CONTROL_ERROR = 7, | 
|  | STREAM_IN_USE = 8, | 
|  | STREAM_ALREADY_CLOSED = 9, | 
|  | INVALID_CREDENTIALS = 10, | 
|  | FRAME_TOO_LARGE = 11, | 
|  | NUM_STATUS_CODES = 12 | 
|  | }; | 
|  |  | 
|  | enum SpdyGoAwayStatus { | 
|  | GOAWAY_INVALID = -1, | 
|  | GOAWAY_OK = 0, | 
|  | GOAWAY_PROTOCOL_ERROR = 1, | 
|  | GOAWAY_INTERNAL_ERROR = 2, | 
|  | GOAWAY_NUM_STATUS_CODES = 3 | 
|  | }; | 
|  |  | 
|  | // A SPDY stream id is a 31 bit entity. | 
|  | typedef uint32 SpdyStreamId; | 
|  |  | 
|  | // 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; | 
|  |  | 
|  | // ------------------------------------------------------------------------- | 
|  | // These structures mirror the protocol structure definitions. | 
|  |  | 
|  | // For the control data structures, we pack so that sizes match the | 
|  | // protocol over-the-wire sizes. | 
|  | #pragma pack(push) | 
|  | #pragma pack(1) | 
|  |  | 
|  | // A special structure for the 8 bit flags and 24 bit length fields. | 
|  | union FlagsAndLength { | 
|  | uint8 flags_[4];  // 8 bits | 
|  | uint32 length_;   // 24 bits | 
|  | }; | 
|  |  | 
|  | // The basic SPDY Frame structure. | 
|  | struct SpdyFrameBlock { | 
|  | union { | 
|  | struct { | 
|  | uint16 version_; | 
|  | uint16 type_; | 
|  | } control_; | 
|  | struct { | 
|  | SpdyStreamId stream_id_; | 
|  | } data_; | 
|  | }; | 
|  | FlagsAndLength flags_length_; | 
|  | }; | 
|  |  | 
|  | // A SYN_STREAM Control Frame structure. | 
|  | struct SpdySynStreamControlFrameBlock : SpdyFrameBlock { | 
|  | SpdyStreamId stream_id_; | 
|  | SpdyStreamId associated_stream_id_; | 
|  | SpdyPriority priority_; | 
|  | uint8 credential_slot_; | 
|  | }; | 
|  |  | 
|  | // A SYN_REPLY Control Frame structure. | 
|  | struct SpdySynReplyControlFrameBlock : SpdyFrameBlock { | 
|  | SpdyStreamId stream_id_; | 
|  | }; | 
|  |  | 
|  | // A RST_STREAM Control Frame structure. | 
|  | struct SpdyRstStreamControlFrameBlock : SpdyFrameBlock { | 
|  | SpdyStreamId stream_id_; | 
|  | uint32 status_; | 
|  | }; | 
|  |  | 
|  | // A SETTINGS Control Frame structure. | 
|  | struct SpdySettingsControlFrameBlock : SpdyFrameBlock { | 
|  | uint32 num_entries_; | 
|  | // Variable data here. | 
|  | }; | 
|  |  | 
|  | // A PING Control Frame structure. | 
|  | struct SpdyPingControlFrameBlock : SpdyFrameBlock { | 
|  | uint32 unique_id_; | 
|  | }; | 
|  |  | 
|  | // TODO(avd): remove this struct | 
|  | // A CREDENTIAL Control Frame structure. | 
|  | struct SpdyCredentialControlFrameBlock : SpdyFrameBlock { | 
|  | uint16 slot_; | 
|  | uint32 proof_len_; | 
|  | // Variable data here. | 
|  | // proof data | 
|  | // for each certificate: unit32 certificate_len + certificate_data[i] | 
|  | }; | 
|  |  | 
|  | // A GOAWAY Control Frame structure. | 
|  | struct SpdyGoAwayControlFrameBlock : SpdyFrameBlock { | 
|  | SpdyStreamId last_accepted_stream_id_; | 
|  | SpdyGoAwayStatus status_; | 
|  | }; | 
|  |  | 
|  | // A HEADERS Control Frame structure. | 
|  | struct SpdyHeadersControlFrameBlock : SpdyFrameBlock { | 
|  | SpdyStreamId stream_id_; | 
|  | }; | 
|  |  | 
|  | // A WINDOW_UPDATE Control Frame structure | 
|  | struct SpdyWindowUpdateControlFrameBlock : SpdyFrameBlock { | 
|  | SpdyStreamId stream_id_; | 
|  | uint32 delta_window_size_; | 
|  | }; | 
|  |  | 
|  | #pragma pack(pop) | 
|  |  | 
|  | // ------------------------------------------------------------------------- | 
|  | // Wrapper classes for various SPDY frames. | 
|  |  | 
|  | // All Spdy Frame types derive from this SpdyFrame class. | 
|  | class SpdyFrame { | 
|  | public: | 
|  | // Create a SpdyFrame for a given sized buffer. | 
|  | explicit SpdyFrame(size_t size) : frame_(NULL), owns_buffer_(true) { | 
|  | DCHECK_GE(size, sizeof(struct SpdyFrameBlock)); | 
|  | char* buffer = new char[size]; | 
|  | memset(buffer, 0, size); | 
|  | frame_ = reinterpret_cast<struct SpdyFrameBlock*>(buffer); | 
|  | } | 
|  |  | 
|  | // 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, bool owns_buffer) | 
|  | : frame_(reinterpret_cast<struct SpdyFrameBlock*>(data)), | 
|  | owns_buffer_(owns_buffer) { | 
|  | DCHECK(frame_); | 
|  | } | 
|  |  | 
|  | ~SpdyFrame() { | 
|  | if (owns_buffer_) { | 
|  | char* buffer = reinterpret_cast<char*>(frame_); | 
|  | delete [] buffer; | 
|  | } | 
|  | 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 reinterpret_cast<char*>(frame_); } | 
|  |  | 
|  | uint8 flags() const { return frame_->flags_length_.flags_[0]; } | 
|  | void set_flags(uint8 flags) { frame_->flags_length_.flags_[0] = flags; } | 
|  |  | 
|  | uint32 length() const { | 
|  | return base::NetToHost32(frame_->flags_length_.length_) & kLengthMask; | 
|  | } | 
|  |  | 
|  | void set_length(uint32 length) { | 
|  | DCHECK_EQ(0u, (length & ~kLengthMask)); | 
|  | /* | 
|  | +----------------------------------+ | 
|  | | Flags (8)  |  Length (24 bits)   | | 
|  | +----------------------------------+ | 
|  | */ | 
|  | frame_->flags_length_.length_ = | 
|  | base::HostToNet32((length & kLengthMask) | (flags() << 24)); | 
|  | } | 
|  |  | 
|  | bool is_control_frame() const { | 
|  | return (base::NetToHost16(frame_->control_.version_) & kControlFlagMask) == | 
|  | kControlFlagMask; | 
|  | } | 
|  |  | 
|  | // The size of the SpdyFrameBlock structure. | 
|  | // Every SpdyFrame* class has a static size() method for accessing | 
|  | // the size of the data structure which will be sent over the wire. | 
|  | // Note:  this is not the same as sizeof(SpdyFrame). | 
|  | enum { kHeaderSize = sizeof(struct SpdyFrameBlock) }; | 
|  |  | 
|  | protected: | 
|  | SpdyFrameBlock* frame_; | 
|  |  | 
|  | private: | 
|  | bool owns_buffer_; | 
|  | DISALLOW_COPY_AND_ASSIGN(SpdyFrame); | 
|  | }; | 
|  |  | 
|  | // A Data Frame. | 
|  | class SpdyDataFrame : public SpdyFrame { | 
|  | public: | 
|  | SpdyDataFrame() : SpdyFrame(size()) {} | 
|  | SpdyDataFrame(char* data, bool owns_buffer) | 
|  | : SpdyFrame(data, owns_buffer) {} | 
|  |  | 
|  | SpdyStreamId stream_id() const { | 
|  | return base::NetToHost32(frame_->data_.stream_id_) & kStreamIdMask; | 
|  | } | 
|  |  | 
|  | // Note that setting the stream id sets the control bit to false. | 
|  | // As stream id should always be set, this means the control bit | 
|  | // should always be set correctly. | 
|  | void set_stream_id(SpdyStreamId id) { | 
|  | DCHECK_EQ(0u, (id & ~kStreamIdMask)); | 
|  | frame_->data_.stream_id_ = base::HostToNet32(id & kStreamIdMask); | 
|  | } | 
|  |  | 
|  | // Returns the size of the SpdyFrameBlock structure. | 
|  | // Note: this is not the size of the SpdyDataFrame class. | 
|  | static size_t size() { return SpdyFrame::kHeaderSize; } | 
|  |  | 
|  | const char* payload() const { | 
|  | return reinterpret_cast<const char*>(frame_) + size(); | 
|  | } | 
|  |  | 
|  | private: | 
|  | DISALLOW_COPY_AND_ASSIGN(SpdyDataFrame); | 
|  | }; | 
|  |  | 
|  | // A Control Frame. | 
|  | class SpdyControlFrame : public SpdyFrame { | 
|  | public: | 
|  | explicit SpdyControlFrame(size_t size) : SpdyFrame(size) {} | 
|  | SpdyControlFrame(char* data, bool owns_buffer) | 
|  | : SpdyFrame(data, owns_buffer) {} | 
|  |  | 
|  | // Callers can use this method to check if the frame appears to be a valid | 
|  | // frame.  Does not guarantee that there are no errors. | 
|  | bool AppearsToBeAValidControlFrame() const { | 
|  | // Right now we only check if the frame has an out-of-bounds type. | 
|  | uint16 type = base::NetToHost16(block()->control_.type_); | 
|  | // NOOP is not a 'valid' control frame in SPDY/3 and beyond. | 
|  | return type >= SYN_STREAM && | 
|  | type < NUM_CONTROL_FRAME_TYPES && | 
|  | (version() == 2 || type != NOOP); | 
|  | } | 
|  |  | 
|  | uint16 version() const { | 
|  | const int kVersionMask = 0x7fff; | 
|  | return static_cast<uint16>(base::NetToHost16((block()->control_.version_)) & | 
|  | kVersionMask); | 
|  | } | 
|  |  | 
|  | void set_version(uint16 version) { | 
|  | /* | 
|  | +----------------------------------+ | 
|  | |C| Version(15bits) | Type(16bits) | | 
|  | +----------------------------------+ | 
|  | */ | 
|  | DCHECK_EQ(0U, version & kControlFlagMask); | 
|  | mutable_block()->control_.version_ = | 
|  | base::HostToNet16(kControlFlagMask | version); | 
|  | } | 
|  |  | 
|  | SpdyControlType type() const { | 
|  | uint16 type = base::NetToHost16(block()->control_.type_); | 
|  | LOG_IF(DFATAL, type < SYN_STREAM || type >= NUM_CONTROL_FRAME_TYPES) | 
|  | << "Invalid control frame type " << type; | 
|  | return static_cast<SpdyControlType>(type); | 
|  | } | 
|  |  | 
|  | void set_type(SpdyControlType type) { | 
|  | DCHECK(type >= SYN_STREAM && type < NUM_CONTROL_FRAME_TYPES); | 
|  | mutable_block()->control_.type_ = | 
|  | base::HostToNet16(static_cast<uint16>(type)); | 
|  | } | 
|  |  | 
|  | // Returns true if this control frame is of a type that has a header block, | 
|  | // otherwise it returns false. | 
|  | bool has_header_block() const { | 
|  | return type() == SYN_STREAM || type() == SYN_REPLY || type() == HEADERS; | 
|  | } | 
|  |  | 
|  | private: | 
|  | const struct SpdyFrameBlock* block() const { | 
|  | return frame_; | 
|  | } | 
|  | struct SpdyFrameBlock* mutable_block() { | 
|  | return frame_; | 
|  | } | 
|  | DISALLOW_COPY_AND_ASSIGN(SpdyControlFrame); | 
|  | }; | 
|  |  | 
|  | // A SYN_STREAM frame. | 
|  | class SpdySynStreamControlFrame : public SpdyControlFrame { | 
|  | public: | 
|  | SpdySynStreamControlFrame() : SpdyControlFrame(size()) {} | 
|  | SpdySynStreamControlFrame(char* data, bool owns_buffer) | 
|  | : SpdyControlFrame(data, owns_buffer) {} | 
|  |  | 
|  | SpdyStreamId stream_id() const { | 
|  | return base::NetToHost32(block()->stream_id_) & kStreamIdMask; | 
|  | } | 
|  |  | 
|  | void set_stream_id(SpdyStreamId id) { | 
|  | mutable_block()->stream_id_ = base::HostToNet32(id & kStreamIdMask); | 
|  | } | 
|  |  | 
|  | SpdyStreamId associated_stream_id() const { | 
|  | return base::NetToHost32(block()->associated_stream_id_) & kStreamIdMask; | 
|  | } | 
|  |  | 
|  | void set_associated_stream_id(SpdyStreamId id) { | 
|  | mutable_block()->associated_stream_id_ = | 
|  | base::HostToNet32(id & kStreamIdMask); | 
|  | } | 
|  |  | 
|  | SpdyPriority priority() const { | 
|  | if (version() < 3) { | 
|  | return (block()->priority_ & kSpdy2PriorityMask) >> 6; | 
|  | } else { | 
|  | return (block()->priority_ & kSpdy3PriorityMask) >> 5; | 
|  | } | 
|  | } | 
|  |  | 
|  | uint8 credential_slot() const { | 
|  | if (version() < 3) { | 
|  | return 0; | 
|  | } else { | 
|  | return block()->credential_slot_; | 
|  | } | 
|  | } | 
|  |  | 
|  | void set_credential_slot(uint8 credential_slot) { | 
|  | DCHECK(version() >= 3); | 
|  | mutable_block()->credential_slot_ = credential_slot; | 
|  | } | 
|  |  | 
|  | // The number of bytes in the header block beyond the frame header length. | 
|  | int header_block_len() const { | 
|  | return static_cast<int>(length() - (size() - SpdyFrame::kHeaderSize)); | 
|  | } | 
|  |  | 
|  | const char* header_block() const { | 
|  | return reinterpret_cast<const char*>(block()) + size(); | 
|  | } | 
|  |  | 
|  | // Returns the size of the SpdySynStreamControlFrameBlock structure. | 
|  | // Note: this is not the size of the SpdySynStreamControlFrame class. | 
|  | static size_t size() { return sizeof(SpdySynStreamControlFrameBlock); } | 
|  |  | 
|  | private: | 
|  | const struct SpdySynStreamControlFrameBlock* block() const { | 
|  | return static_cast<SpdySynStreamControlFrameBlock*>(frame_); | 
|  | } | 
|  | struct SpdySynStreamControlFrameBlock* mutable_block() { | 
|  | return static_cast<SpdySynStreamControlFrameBlock*>(frame_); | 
|  | } | 
|  | DISALLOW_COPY_AND_ASSIGN(SpdySynStreamControlFrame); | 
|  | }; | 
|  |  | 
|  | // A SYN_REPLY frame. | 
|  | class SpdySynReplyControlFrame : public SpdyControlFrame { | 
|  | public: | 
|  | SpdySynReplyControlFrame() : SpdyControlFrame(size()) {} | 
|  | SpdySynReplyControlFrame(char* data, bool owns_buffer) | 
|  | : SpdyControlFrame(data, owns_buffer) {} | 
|  |  | 
|  | SpdyStreamId stream_id() const { | 
|  | return base::NetToHost32(block()->stream_id_) & kStreamIdMask; | 
|  | } | 
|  |  | 
|  | void set_stream_id(SpdyStreamId id) { | 
|  | mutable_block()->stream_id_ = base::HostToNet32(id & kStreamIdMask); | 
|  | } | 
|  |  | 
|  | int header_block_len() const { | 
|  | size_t header_block_len = length() - (size() - SpdyFrame::kHeaderSize); | 
|  | // SPDY 2 had 2 bytes of unused space preceeding the header block. | 
|  | if (version() < 3) { | 
|  | header_block_len -= 2; | 
|  | } | 
|  | return static_cast<int>(header_block_len); | 
|  | } | 
|  |  | 
|  | const char* header_block() const { | 
|  | const char* header_block = reinterpret_cast<const char*>(block()) + size(); | 
|  | // SPDY 2 had 2 bytes of unused space preceeding the header block. | 
|  | if (version() < 3) { | 
|  | header_block += 2; | 
|  | } | 
|  | return header_block; | 
|  | } | 
|  |  | 
|  | // Returns the size of the SpdySynReplyControlFrameBlock structure. | 
|  | // Note: this is not the size of the SpdySynReplyControlFrame class. | 
|  | static size_t size() { return sizeof(SpdySynReplyControlFrameBlock); } | 
|  |  | 
|  | private: | 
|  | const struct SpdySynReplyControlFrameBlock* block() const { | 
|  | return static_cast<SpdySynReplyControlFrameBlock*>(frame_); | 
|  | } | 
|  | struct SpdySynReplyControlFrameBlock* mutable_block() { | 
|  | return static_cast<SpdySynReplyControlFrameBlock*>(frame_); | 
|  | } | 
|  | DISALLOW_COPY_AND_ASSIGN(SpdySynReplyControlFrame); | 
|  | }; | 
|  |  | 
|  | // A RST_STREAM frame. | 
|  | class SpdyRstStreamControlFrame : public SpdyControlFrame { | 
|  | public: | 
|  | SpdyRstStreamControlFrame() : SpdyControlFrame(size()) {} | 
|  | SpdyRstStreamControlFrame(char* data, bool owns_buffer) | 
|  | : SpdyControlFrame(data, owns_buffer) {} | 
|  |  | 
|  | SpdyStreamId stream_id() const { | 
|  | return base::NetToHost32(block()->stream_id_) & kStreamIdMask; | 
|  | } | 
|  |  | 
|  | void set_stream_id(SpdyStreamId id) { | 
|  | mutable_block()->stream_id_ = base::HostToNet32(id & kStreamIdMask); | 
|  | } | 
|  |  | 
|  | SpdyStatusCodes status() const { | 
|  | SpdyStatusCodes status = | 
|  | static_cast<SpdyStatusCodes>(base::NetToHost32(block()->status_)); | 
|  | if (status < INVALID || status >= NUM_STATUS_CODES) { | 
|  | status = INVALID; | 
|  | } | 
|  | return status; | 
|  | } | 
|  | void set_status(SpdyStatusCodes status) { | 
|  | mutable_block()->status_ = base::HostToNet32(static_cast<uint32>(status)); | 
|  | } | 
|  |  | 
|  | // Returns the size of the SpdyRstStreamControlFrameBlock structure. | 
|  | // Note: this is not the size of the SpdyRstStreamControlFrame class. | 
|  | static size_t size() { return sizeof(SpdyRstStreamControlFrameBlock); } | 
|  |  | 
|  | private: | 
|  | const struct SpdyRstStreamControlFrameBlock* block() const { | 
|  | return static_cast<SpdyRstStreamControlFrameBlock*>(frame_); | 
|  | } | 
|  | struct SpdyRstStreamControlFrameBlock* mutable_block() { | 
|  | return static_cast<SpdyRstStreamControlFrameBlock*>(frame_); | 
|  | } | 
|  | DISALLOW_COPY_AND_ASSIGN(SpdyRstStreamControlFrame); | 
|  | }; | 
|  |  | 
|  | class SpdySettingsControlFrame : public SpdyControlFrame { | 
|  | public: | 
|  | SpdySettingsControlFrame() : SpdyControlFrame(size()) {} | 
|  | SpdySettingsControlFrame(char* data, bool owns_buffer) | 
|  | : SpdyControlFrame(data, owns_buffer) {} | 
|  |  | 
|  | uint32 num_entries() const { | 
|  | return base::NetToHost32(block()->num_entries_); | 
|  | } | 
|  |  | 
|  | void set_num_entries(int val) { | 
|  | mutable_block()->num_entries_ = base::HostToNet32(static_cast<uint32>(val)); | 
|  | } | 
|  |  | 
|  | int header_block_len() const { | 
|  | return static_cast<int>(length() - (size() - SpdyFrame::kHeaderSize)); | 
|  | } | 
|  |  | 
|  | const char* header_block() const { | 
|  | return reinterpret_cast<const char*>(block()) + size(); | 
|  | } | 
|  |  | 
|  | // Returns the size of the SpdySettingsControlFrameBlock structure. | 
|  | // Note: this is not the size of the SpdySettingsControlFrameBlock class. | 
|  | static size_t size() { return sizeof(SpdySettingsControlFrameBlock); } | 
|  |  | 
|  | private: | 
|  | const struct SpdySettingsControlFrameBlock* block() const { | 
|  | return static_cast<SpdySettingsControlFrameBlock*>(frame_); | 
|  | } | 
|  | struct SpdySettingsControlFrameBlock* mutable_block() { | 
|  | return static_cast<SpdySettingsControlFrameBlock*>(frame_); | 
|  | } | 
|  | DISALLOW_COPY_AND_ASSIGN(SpdySettingsControlFrame); | 
|  | }; | 
|  |  | 
|  | class SpdyPingControlFrame : public SpdyControlFrame { | 
|  | public: | 
|  | SpdyPingControlFrame() : SpdyControlFrame(size()) {} | 
|  | SpdyPingControlFrame(char* data, bool owns_buffer) | 
|  | : SpdyControlFrame(data, owns_buffer) {} | 
|  |  | 
|  | uint32 unique_id() const { return base::NetToHost32(block()->unique_id_); } | 
|  |  | 
|  | void set_unique_id(uint32 unique_id) { | 
|  | mutable_block()->unique_id_ = base::HostToNet32(unique_id); | 
|  | } | 
|  |  | 
|  | static size_t size() { return sizeof(SpdyPingControlFrameBlock); } | 
|  |  | 
|  | private: | 
|  | const struct SpdyPingControlFrameBlock* block() const { | 
|  | return static_cast<SpdyPingControlFrameBlock*>(frame_); | 
|  | } | 
|  | struct SpdyPingControlFrameBlock* mutable_block() { | 
|  | return static_cast<SpdyPingControlFrameBlock*>(frame_); | 
|  | } | 
|  | }; | 
|  |  | 
|  | class SpdyCredentialControlFrame : public SpdyControlFrame { | 
|  | public: | 
|  | SpdyCredentialControlFrame() : SpdyControlFrame(size()) {} | 
|  | SpdyCredentialControlFrame(char* data, bool owns_buffer) | 
|  | : SpdyControlFrame(data, owns_buffer) {} | 
|  |  | 
|  | const char* payload() const { | 
|  | return reinterpret_cast<const char*>(block()) + SpdyFrame::kHeaderSize; | 
|  | } | 
|  |  | 
|  | static size_t size() { return sizeof(SpdyCredentialControlFrameBlock); } | 
|  |  | 
|  | private: | 
|  | const struct SpdyCredentialControlFrameBlock* block() const { | 
|  | return static_cast<SpdyCredentialControlFrameBlock*>(frame_); | 
|  | } | 
|  | DISALLOW_COPY_AND_ASSIGN(SpdyCredentialControlFrame); | 
|  | }; | 
|  |  | 
|  | class SpdyGoAwayControlFrame : public SpdyControlFrame { | 
|  | public: | 
|  | SpdyGoAwayControlFrame() : SpdyControlFrame(size()) {} | 
|  | SpdyGoAwayControlFrame(char* data, bool owns_buffer) | 
|  | : SpdyControlFrame(data, owns_buffer) {} | 
|  |  | 
|  | SpdyStreamId last_accepted_stream_id() const { | 
|  | return base::NetToHost32(block()->last_accepted_stream_id_) & kStreamIdMask; | 
|  | } | 
|  |  | 
|  | SpdyGoAwayStatus status() const { | 
|  | if (version() < 3) { | 
|  | LOG(DFATAL) << "Attempted to access status of SPDY 2 GOAWAY."; | 
|  | return GOAWAY_INVALID; | 
|  | } else { | 
|  | uint32 status = base::NetToHost32(block()->status_); | 
|  | if (status >= GOAWAY_NUM_STATUS_CODES) { | 
|  | return GOAWAY_INVALID; | 
|  | } else { | 
|  | return static_cast<SpdyGoAwayStatus>(status); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void set_last_accepted_stream_id(SpdyStreamId id) { | 
|  | mutable_block()->last_accepted_stream_id_ = | 
|  | base::HostToNet32(id & kStreamIdMask); | 
|  | } | 
|  |  | 
|  | static size_t size() { return sizeof(SpdyGoAwayControlFrameBlock); } | 
|  |  | 
|  | private: | 
|  | const struct SpdyGoAwayControlFrameBlock* block() const { | 
|  | return static_cast<SpdyGoAwayControlFrameBlock*>(frame_); | 
|  | } | 
|  | struct SpdyGoAwayControlFrameBlock* mutable_block() { | 
|  | return static_cast<SpdyGoAwayControlFrameBlock*>(frame_); | 
|  | } | 
|  | DISALLOW_COPY_AND_ASSIGN(SpdyGoAwayControlFrame); | 
|  | }; | 
|  |  | 
|  | // A HEADERS frame. | 
|  | class SpdyHeadersControlFrame : public SpdyControlFrame { | 
|  | public: | 
|  | SpdyHeadersControlFrame() : SpdyControlFrame(size()) {} | 
|  | SpdyHeadersControlFrame(char* data, bool owns_buffer) | 
|  | : SpdyControlFrame(data, owns_buffer) {} | 
|  |  | 
|  | SpdyStreamId stream_id() const { | 
|  | return base::NetToHost32(block()->stream_id_) & kStreamIdMask; | 
|  | } | 
|  |  | 
|  | void set_stream_id(SpdyStreamId id) { | 
|  | mutable_block()->stream_id_ = base::HostToNet32(id & kStreamIdMask); | 
|  | } | 
|  |  | 
|  | // The number of bytes in the header block beyond the frame header length. | 
|  | int header_block_len() const { | 
|  | size_t header_block_len = length() - (size() - SpdyFrame::kHeaderSize); | 
|  | // SPDY 2 had 2 bytes of unused space preceeding the header block. | 
|  | if (version() < 3) { | 
|  | header_block_len -= 2; | 
|  | } | 
|  | return static_cast<int>(header_block_len); | 
|  | } | 
|  |  | 
|  | const char* header_block() const { | 
|  | const char* header_block = reinterpret_cast<const char*>(block()) + size(); | 
|  | // SPDY 2 had 2 bytes of unused space preceeding the header block. | 
|  | if (version() < 3) { | 
|  | header_block += 2; | 
|  | } | 
|  | return header_block; | 
|  | } | 
|  |  | 
|  | // Returns the size of the SpdyHeadersControlFrameBlock structure. | 
|  | // Note: this is not the size of the SpdyHeadersControlFrame class. | 
|  | static size_t size() { return sizeof(SpdyHeadersControlFrameBlock); } | 
|  |  | 
|  | private: | 
|  | const struct SpdyHeadersControlFrameBlock* block() const { | 
|  | return static_cast<SpdyHeadersControlFrameBlock*>(frame_); | 
|  | } | 
|  | struct SpdyHeadersControlFrameBlock* mutable_block() { | 
|  | return static_cast<SpdyHeadersControlFrameBlock*>(frame_); | 
|  | } | 
|  | DISALLOW_COPY_AND_ASSIGN(SpdyHeadersControlFrame); | 
|  | }; | 
|  |  | 
|  | // A WINDOW_UPDATE frame. | 
|  | class SpdyWindowUpdateControlFrame : public SpdyControlFrame { | 
|  | public: | 
|  | SpdyWindowUpdateControlFrame() : SpdyControlFrame(size()) {} | 
|  | SpdyWindowUpdateControlFrame(char* data, bool owns_buffer) | 
|  | : SpdyControlFrame(data, owns_buffer) {} | 
|  |  | 
|  | SpdyStreamId stream_id() const { | 
|  | return base::NetToHost32(block()->stream_id_) & kStreamIdMask; | 
|  | } | 
|  |  | 
|  | void set_stream_id(SpdyStreamId id) { | 
|  | mutable_block()->stream_id_ = base::HostToNet32(id & kStreamIdMask); | 
|  | } | 
|  |  | 
|  | uint32 delta_window_size() const { | 
|  | return base::NetToHost32(block()->delta_window_size_); | 
|  | } | 
|  |  | 
|  | void set_delta_window_size(uint32 delta_window_size) { | 
|  | mutable_block()->delta_window_size_ = base::HostToNet32(delta_window_size); | 
|  | } | 
|  |  | 
|  | // Returns the size of the SpdyWindowUpdateControlFrameBlock structure. | 
|  | // Note: this is not the size of the SpdyWindowUpdateControlFrame class. | 
|  | static size_t size() { return sizeof(SpdyWindowUpdateControlFrameBlock); } | 
|  |  | 
|  | private: | 
|  | const struct SpdyWindowUpdateControlFrameBlock* block() const { | 
|  | return static_cast<SpdyWindowUpdateControlFrameBlock*>(frame_); | 
|  | } | 
|  | struct SpdyWindowUpdateControlFrameBlock* mutable_block() { | 
|  | return static_cast<SpdyWindowUpdateControlFrameBlock*>(frame_); | 
|  | } | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(SpdyWindowUpdateControlFrame); | 
|  | }; | 
|  |  | 
|  | }  // namespace net | 
|  |  | 
|  | #endif  // NET_SPDY_SPDY_PROTOCOL_H_ |