Home | History | Annotate | Download | only in hpack
      1 // Copyright 2014 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package hpack
      6 
      7 import (
      8 	"fmt"
      9 )
     10 
     11 // headerFieldTable implements a list of HeaderFields.
     12 // This is used to implement the static and dynamic tables.
     13 type headerFieldTable struct {
     14 	// For static tables, entries are never evicted.
     15 	//
     16 	// For dynamic tables, entries are evicted from ents[0] and added to the end.
     17 	// Each entry has a unique id that starts at one and increments for each
     18 	// entry that is added. This unique id is stable across evictions, meaning
     19 	// it can be used as a pointer to a specific entry. As in hpack, unique ids
     20 	// are 1-based. The unique id for ents[k] is k + evictCount + 1.
     21 	//
     22 	// Zero is not a valid unique id.
     23 	//
     24 	// evictCount should not overflow in any remotely practical situation. In
     25 	// practice, we will have one dynamic table per HTTP/2 connection. If we
     26 	// assume a very powerful server that handles 1M QPS per connection and each
     27 	// request adds (then evicts) 100 entries from the table, it would still take
     28 	// 2M years for evictCount to overflow.
     29 	ents       []HeaderField
     30 	evictCount uint64
     31 
     32 	// byName maps a HeaderField name to the unique id of the newest entry with
     33 	// the same name. See above for a definition of "unique id".
     34 	byName map[string]uint64
     35 
     36 	// byNameValue maps a HeaderField name/value pair to the unique id of the newest
     37 	// entry with the same name and value. See above for a definition of "unique id".
     38 	byNameValue map[pairNameValue]uint64
     39 }
     40 
     41 type pairNameValue struct {
     42 	name, value string
     43 }
     44 
     45 func (t *headerFieldTable) init() {
     46 	t.byName = make(map[string]uint64)
     47 	t.byNameValue = make(map[pairNameValue]uint64)
     48 }
     49 
     50 // len reports the number of entries in the table.
     51 func (t *headerFieldTable) len() int {
     52 	return len(t.ents)
     53 }
     54 
     55 // addEntry adds a new entry.
     56 func (t *headerFieldTable) addEntry(f HeaderField) {
     57 	id := uint64(t.len()) + t.evictCount + 1
     58 	t.byName[f.Name] = id
     59 	t.byNameValue[pairNameValue{f.Name, f.Value}] = id
     60 	t.ents = append(t.ents, f)
     61 }
     62 
     63 // evictOldest evicts the n oldest entries in the table.
     64 func (t *headerFieldTable) evictOldest(n int) {
     65 	if n > t.len() {
     66 		panic(fmt.Sprintf("evictOldest(%v) on table with %v entries", n, t.len()))
     67 	}
     68 	for k := 0; k < n; k++ {
     69 		f := t.ents[k]
     70 		id := t.evictCount + uint64(k) + 1
     71 		if t.byName[f.Name] == id {
     72 			delete(t.byName, f.Name)
     73 		}
     74 		if p := (pairNameValue{f.Name, f.Value}); t.byNameValue[p] == id {
     75 			delete(t.byNameValue, p)
     76 		}
     77 	}
     78 	copy(t.ents, t.ents[n:])
     79 	for k := t.len() - n; k < t.len(); k++ {
     80 		t.ents[k] = HeaderField{} // so strings can be garbage collected
     81 	}
     82 	t.ents = t.ents[:t.len()-n]
     83 	if t.evictCount+uint64(n) < t.evictCount {
     84 		panic("evictCount overflow")
     85 	}
     86 	t.evictCount += uint64(n)
     87 }
     88 
     89 // search finds f in the table. If there is no match, i is 0.
     90 // If both name and value match, i is the matched index and nameValueMatch
     91 // becomes true. If only name matches, i points to that index and
     92 // nameValueMatch becomes false.
     93 //
     94 // The returned index is a 1-based HPACK index. For dynamic tables, HPACK says
     95 // that index 1 should be the newest entry, but t.ents[0] is the oldest entry,
     96 // meaning t.ents is reversed for dynamic tables. Hence, when t is a dynamic
     97 // table, the return value i actually refers to the entry t.ents[t.len()-i].
     98 //
     99 // All tables are assumed to be a dynamic tables except for the global
    100 // staticTable pointer.
    101 //
    102 // See Section 2.3.3.
    103 func (t *headerFieldTable) search(f HeaderField) (i uint64, nameValueMatch bool) {
    104 	if !f.Sensitive {
    105 		if id := t.byNameValue[pairNameValue{f.Name, f.Value}]; id != 0 {
    106 			return t.idToIndex(id), true
    107 		}
    108 	}
    109 	if id := t.byName[f.Name]; id != 0 {
    110 		return t.idToIndex(id), false
    111 	}
    112 	return 0, false
    113 }
    114 
    115 // idToIndex converts a unique id to an HPACK index.
    116 // See Section 2.3.3.
    117 func (t *headerFieldTable) idToIndex(id uint64) uint64 {
    118 	if id <= t.evictCount {
    119 		panic(fmt.Sprintf("id (%v) <= evictCount (%v)", id, t.evictCount))
    120 	}
    121 	k := id - t.evictCount - 1 // convert id to an index t.ents[k]
    122 	if t != staticTable {
    123 		return uint64(t.len()) - k // dynamic table
    124 	}
    125 	return k + 1
    126 }
    127 
    128 // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B
    129 var staticTable = newStaticTable()
    130 var staticTableEntries = [...]HeaderField{
    131 	HeaderField{Name: ":authority"},
    132 	HeaderField{Name: ":method", Value: "GET"},
    133 	HeaderField{Name: ":method", Value: "POST"},
    134 	HeaderField{Name: ":path", Value: "/"},
    135 	HeaderField{Name: ":path", Value: "/index.html"},
    136 	HeaderField{Name: ":scheme", Value: "http"},
    137 	HeaderField{Name: ":scheme", Value: "https"},
    138 	HeaderField{Name: ":status", Value: "200"},
    139 	HeaderField{Name: ":status", Value: "204"},
    140 	HeaderField{Name: ":status", Value: "206"},
    141 	HeaderField{Name: ":status", Value: "304"},
    142 	HeaderField{Name: ":status", Value: "400"},
    143 	HeaderField{Name: ":status", Value: "404"},
    144 	HeaderField{Name: ":status", Value: "500"},
    145 	HeaderField{Name: "accept-charset"},
    146 	HeaderField{Name: "accept-encoding", Value: "gzip, deflate"},
    147 	HeaderField{Name: "accept-language"},
    148 	HeaderField{Name: "accept-ranges"},
    149 	HeaderField{Name: "accept"},
    150 	HeaderField{Name: "access-control-allow-origin"},
    151 	HeaderField{Name: "age"},
    152 	HeaderField{Name: "allow"},
    153 	HeaderField{Name: "authorization"},
    154 	HeaderField{Name: "cache-control"},
    155 	HeaderField{Name: "content-disposition"},
    156 	HeaderField{Name: "content-encoding"},
    157 	HeaderField{Name: "content-language"},
    158 	HeaderField{Name: "content-length"},
    159 	HeaderField{Name: "content-location"},
    160 	HeaderField{Name: "content-range"},
    161 	HeaderField{Name: "content-type"},
    162 	HeaderField{Name: "cookie"},
    163 	HeaderField{Name: "date"},
    164 	HeaderField{Name: "etag"},
    165 	HeaderField{Name: "expect"},
    166 	HeaderField{Name: "expires"},
    167 	HeaderField{Name: "from"},
    168 	HeaderField{Name: "host"},
    169 	HeaderField{Name: "if-match"},
    170 	HeaderField{Name: "if-modified-since"},
    171 	HeaderField{Name: "if-none-match"},
    172 	HeaderField{Name: "if-range"},
    173 	HeaderField{Name: "if-unmodified-since"},
    174 	HeaderField{Name: "last-modified"},
    175 	HeaderField{Name: "link"},
    176 	HeaderField{Name: "location"},
    177 	HeaderField{Name: "max-forwards"},
    178 	HeaderField{Name: "proxy-authenticate"},
    179 	HeaderField{Name: "proxy-authorization"},
    180 	HeaderField{Name: "range"},
    181 	HeaderField{Name: "referer"},
    182 	HeaderField{Name: "refresh"},
    183 	HeaderField{Name: "retry-after"},
    184 	HeaderField{Name: "server"},
    185 	HeaderField{Name: "set-cookie"},
    186 	HeaderField{Name: "strict-transport-security"},
    187 	HeaderField{Name: "transfer-encoding"},
    188 	HeaderField{Name: "user-agent"},
    189 	HeaderField{Name: "vary"},
    190 	HeaderField{Name: "via"},
    191 	HeaderField{Name: "www-authenticate"},
    192 }
    193 
    194 func newStaticTable() *headerFieldTable {
    195 	t := &headerFieldTable{}
    196 	t.init()
    197 	for _, e := range staticTableEntries[:] {
    198 		t.addEntry(e)
    199 	}
    200 	return t
    201 }
    202 
    203 var huffmanCodes = [256]uint32{
    204 	0x1ff8,
    205 	0x7fffd8,
    206 	0xfffffe2,
    207 	0xfffffe3,
    208 	0xfffffe4,
    209 	0xfffffe5,
    210 	0xfffffe6,
    211 	0xfffffe7,
    212 	0xfffffe8,
    213 	0xffffea,
    214 	0x3ffffffc,
    215 	0xfffffe9,
    216 	0xfffffea,
    217 	0x3ffffffd,
    218 	0xfffffeb,
    219 	0xfffffec,
    220 	0xfffffed,
    221 	0xfffffee,
    222 	0xfffffef,
    223 	0xffffff0,
    224 	0xffffff1,
    225 	0xffffff2,
    226 	0x3ffffffe,
    227 	0xffffff3,
    228 	0xffffff4,
    229 	0xffffff5,
    230 	0xffffff6,
    231 	0xffffff7,
    232 	0xffffff8,
    233 	0xffffff9,
    234 	0xffffffa,
    235 	0xffffffb,
    236 	0x14,
    237 	0x3f8,
    238 	0x3f9,
    239 	0xffa,
    240 	0x1ff9,
    241 	0x15,
    242 	0xf8,
    243 	0x7fa,
    244 	0x3fa,
    245 	0x3fb,
    246 	0xf9,
    247 	0x7fb,
    248 	0xfa,
    249 	0x16,
    250 	0x17,
    251 	0x18,
    252 	0x0,
    253 	0x1,
    254 	0x2,
    255 	0x19,
    256 	0x1a,
    257 	0x1b,
    258 	0x1c,
    259 	0x1d,
    260 	0x1e,
    261 	0x1f,
    262 	0x5c,
    263 	0xfb,
    264 	0x7ffc,
    265 	0x20,
    266 	0xffb,
    267 	0x3fc,
    268 	0x1ffa,
    269 	0x21,
    270 	0x5d,
    271 	0x5e,
    272 	0x5f,
    273 	0x60,
    274 	0x61,
    275 	0x62,
    276 	0x63,
    277 	0x64,
    278 	0x65,
    279 	0x66,
    280 	0x67,
    281 	0x68,
    282 	0x69,
    283 	0x6a,
    284 	0x6b,
    285 	0x6c,
    286 	0x6d,
    287 	0x6e,
    288 	0x6f,
    289 	0x70,
    290 	0x71,
    291 	0x72,
    292 	0xfc,
    293 	0x73,
    294 	0xfd,
    295 	0x1ffb,
    296 	0x7fff0,
    297 	0x1ffc,
    298 	0x3ffc,
    299 	0x22,
    300 	0x7ffd,
    301 	0x3,
    302 	0x23,
    303 	0x4,
    304 	0x24,
    305 	0x5,
    306 	0x25,
    307 	0x26,
    308 	0x27,
    309 	0x6,
    310 	0x74,
    311 	0x75,
    312 	0x28,
    313 	0x29,
    314 	0x2a,
    315 	0x7,
    316 	0x2b,
    317 	0x76,
    318 	0x2c,
    319 	0x8,
    320 	0x9,
    321 	0x2d,
    322 	0x77,
    323 	0x78,
    324 	0x79,
    325 	0x7a,
    326 	0x7b,
    327 	0x7ffe,
    328 	0x7fc,
    329 	0x3ffd,
    330 	0x1ffd,
    331 	0xffffffc,
    332 	0xfffe6,
    333 	0x3fffd2,
    334 	0xfffe7,
    335 	0xfffe8,
    336 	0x3fffd3,
    337 	0x3fffd4,
    338 	0x3fffd5,
    339 	0x7fffd9,
    340 	0x3fffd6,
    341 	0x7fffda,
    342 	0x7fffdb,
    343 	0x7fffdc,
    344 	0x7fffdd,
    345 	0x7fffde,
    346 	0xffffeb,
    347 	0x7fffdf,
    348 	0xffffec,
    349 	0xffffed,
    350 	0x3fffd7,
    351 	0x7fffe0,
    352 	0xffffee,
    353 	0x7fffe1,
    354 	0x7fffe2,
    355 	0x7fffe3,
    356 	0x7fffe4,
    357 	0x1fffdc,
    358 	0x3fffd8,
    359 	0x7fffe5,
    360 	0x3fffd9,
    361 	0x7fffe6,
    362 	0x7fffe7,
    363 	0xffffef,
    364 	0x3fffda,
    365 	0x1fffdd,
    366 	0xfffe9,
    367 	0x3fffdb,
    368 	0x3fffdc,
    369 	0x7fffe8,
    370 	0x7fffe9,
    371 	0x1fffde,
    372 	0x7fffea,
    373 	0x3fffdd,
    374 	0x3fffde,
    375 	0xfffff0,
    376 	0x1fffdf,
    377 	0x3fffdf,
    378 	0x7fffeb,
    379 	0x7fffec,
    380 	0x1fffe0,
    381 	0x1fffe1,
    382 	0x3fffe0,
    383 	0x1fffe2,
    384 	0x7fffed,
    385 	0x3fffe1,
    386 	0x7fffee,
    387 	0x7fffef,
    388 	0xfffea,
    389 	0x3fffe2,
    390 	0x3fffe3,
    391 	0x3fffe4,
    392 	0x7ffff0,
    393 	0x3fffe5,
    394 	0x3fffe6,
    395 	0x7ffff1,
    396 	0x3ffffe0,
    397 	0x3ffffe1,
    398 	0xfffeb,
    399 	0x7fff1,
    400 	0x3fffe7,
    401 	0x7ffff2,
    402 	0x3fffe8,
    403 	0x1ffffec,
    404 	0x3ffffe2,
    405 	0x3ffffe3,
    406 	0x3ffffe4,
    407 	0x7ffffde,
    408 	0x7ffffdf,
    409 	0x3ffffe5,
    410 	0xfffff1,
    411 	0x1ffffed,
    412 	0x7fff2,
    413 	0x1fffe3,
    414 	0x3ffffe6,
    415 	0x7ffffe0,
    416 	0x7ffffe1,
    417 	0x3ffffe7,
    418 	0x7ffffe2,
    419 	0xfffff2,
    420 	0x1fffe4,
    421 	0x1fffe5,
    422 	0x3ffffe8,
    423 	0x3ffffe9,
    424 	0xffffffd,
    425 	0x7ffffe3,
    426 	0x7ffffe4,
    427 	0x7ffffe5,
    428 	0xfffec,
    429 	0xfffff3,
    430 	0xfffed,
    431 	0x1fffe6,
    432 	0x3fffe9,
    433 	0x1fffe7,
    434 	0x1fffe8,
    435 	0x7ffff3,
    436 	0x3fffea,
    437 	0x3fffeb,
    438 	0x1ffffee,
    439 	0x1ffffef,
    440 	0xfffff4,
    441 	0xfffff5,
    442 	0x3ffffea,
    443 	0x7ffff4,
    444 	0x3ffffeb,
    445 	0x7ffffe6,
    446 	0x3ffffec,
    447 	0x3ffffed,
    448 	0x7ffffe7,
    449 	0x7ffffe8,
    450 	0x7ffffe9,
    451 	0x7ffffea,
    452 	0x7ffffeb,
    453 	0xffffffe,
    454 	0x7ffffec,
    455 	0x7ffffed,
    456 	0x7ffffee,
    457 	0x7ffffef,
    458 	0x7fffff0,
    459 	0x3ffffee,
    460 }
    461 
    462 var huffmanCodeLen = [256]uint8{
    463 	13, 23, 28, 28, 28, 28, 28, 28, 28, 24, 30, 28, 28, 30, 28, 28,
    464 	28, 28, 28, 28, 28, 28, 30, 28, 28, 28, 28, 28, 28, 28, 28, 28,
    465 	6, 10, 10, 12, 13, 6, 8, 11, 10, 10, 8, 11, 8, 6, 6, 6,
    466 	5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 8, 15, 6, 12, 10,
    467 	13, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    468 	7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 13, 19, 13, 14, 6,
    469 	15, 5, 6, 5, 6, 5, 6, 6, 6, 5, 7, 7, 6, 6, 6, 5,
    470 	6, 7, 6, 5, 5, 6, 7, 7, 7, 7, 7, 15, 11, 14, 13, 28,
    471 	20, 22, 20, 20, 22, 22, 22, 23, 22, 23, 23, 23, 23, 23, 24, 23,
    472 	24, 24, 22, 23, 24, 23, 23, 23, 23, 21, 22, 23, 22, 23, 23, 24,
    473 	22, 21, 20, 22, 22, 23, 23, 21, 23, 22, 22, 24, 21, 22, 23, 23,
    474 	21, 21, 22, 21, 23, 22, 23, 23, 20, 22, 22, 22, 23, 22, 22, 23,
    475 	26, 26, 20, 19, 22, 23, 22, 25, 26, 26, 26, 27, 27, 26, 24, 25,
    476 	19, 21, 26, 27, 27, 26, 27, 24, 21, 21, 26, 26, 28, 27, 27, 27,
    477 	20, 24, 20, 21, 22, 21, 21, 23, 22, 22, 25, 25, 24, 24, 26, 23,
    478 	26, 27, 26, 26, 27, 27, 27, 27, 27, 28, 27, 27, 27, 27, 27, 26,
    479 }
    480