hpack.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. // Copyright 2014 The Go Authors.
  2. // See https://code.google.com/p/go/source/browse/CONTRIBUTORS
  3. // Licensed under the same terms as Go itself:
  4. // https://code.google.com/p/go/source/browse/LICENSE
  5. // Package hpack implements HPACK, a compression format for
  6. // efficiently representing HTTP header fields in the context of HTTP/2.
  7. //
  8. // See http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-09
  9. package hpack
  10. import (
  11. "errors"
  12. "fmt"
  13. "io"
  14. )
  15. // A DecodingError is something the spec defines as a decoding error.
  16. type DecodingError struct {
  17. Err error
  18. }
  19. func (de DecodingError) Error() string {
  20. return fmt.Sprintf("decoding error: %v", de.Err)
  21. }
  22. // An InvalidIndexError is returned when an encoder references a table
  23. // entry before the static table or after the end of the dynamic table.
  24. type InvalidIndexError int
  25. func (e InvalidIndexError) Error() string {
  26. return fmt.Sprintf("invalid indexed representation index %d", int(e))
  27. }
  28. // A HeaderField is a name-value pair. Both the name and value are
  29. // treated as opaque sequences of octets.
  30. type HeaderField struct {
  31. Name, Value string
  32. }
  33. func (hf *HeaderField) size() uint32 {
  34. // http://http2.github.io/http2-spec/compression.html#rfc.section.4.1
  35. // "The size of the dynamic table is the sum of the size of
  36. // its entries. The size of an entry is the sum of its name's
  37. // length in octets (as defined in Section 5.2), its value's
  38. // length in octets (see Section 5.2), plus 32. The size of
  39. // an entry is calculated using the length of the name and
  40. // value without any Huffman encoding applied."
  41. // This can overflow if somebody makes a large HeaderField
  42. // Name and/or Value by hand, but we don't care, because that
  43. // won't happen on the wire because the encoding doesn't allow
  44. // it.
  45. return uint32(len(hf.Name) + len(hf.Value) + 32)
  46. }
  47. // A Decoder is the decoding context for incremental processing of
  48. // header blocks.
  49. type Decoder struct {
  50. dynTab dynamicTable
  51. emit func(f HeaderField, sensitive bool)
  52. }
  53. func NewDecoder(maxSize uint32, emitFunc func(f HeaderField, sensitive bool)) *Decoder {
  54. d := &Decoder{
  55. emit: emitFunc,
  56. }
  57. d.dynTab.setMaxSize(maxSize)
  58. return d
  59. }
  60. // TODO: add method *Decoder.Reset(maxSize, emitFunc) to let callers re-use Decoders and their
  61. // underlying buffers for garbage reasons.
  62. func (d *Decoder) SetMaxDynamicTableSize(v uint32) {
  63. d.dynTab.setMaxSize(v)
  64. }
  65. type dynamicTable struct {
  66. // s is the FIFO described at
  67. // http://http2.github.io/http2-spec/compression.html#rfc.section.2.3.2
  68. // The newest (low index) is append at the end, and items are
  69. // evicted from the front.
  70. ents []HeaderField
  71. size uint32
  72. maxSize uint32
  73. }
  74. func (dt *dynamicTable) setMaxSize(v uint32) {
  75. dt.maxSize = v
  76. dt.evict()
  77. }
  78. // TODO: change dynamicTable to be a struct with a slice and a size int field,
  79. // per http://http2.github.io/http2-spec/compression.html#rfc.section.4.1:
  80. //
  81. //
  82. // Then make add increment the size. maybe the max size should move from Decoder to
  83. // dynamicTable and add should return an ok bool if there was enough space.
  84. //
  85. // Later we'll need a remove operation on dynamicTable.
  86. func (dt *dynamicTable) add(f HeaderField) {
  87. dt.ents = append(dt.ents, f)
  88. dt.size += f.size()
  89. dt.evict()
  90. }
  91. // If we're too big, evict old stuff (front of the slice)
  92. func (dt *dynamicTable) evict() {
  93. base := dt.ents // keep base pointer of slice
  94. for dt.size > dt.maxSize {
  95. dt.size -= dt.ents[0].size()
  96. dt.ents = dt.ents[1:]
  97. }
  98. // Shift slice contents down if we evicted things.
  99. if len(dt.ents) != len(base) {
  100. copy(base, dt.ents)
  101. dt.ents = base[:len(dt.ents)]
  102. }
  103. }
  104. func (d *Decoder) maxTableIndex() int {
  105. return len(d.dynTab.ents) + len(staticTable)
  106. }
  107. func (d *Decoder) at(i int) (hf HeaderField, ok bool) {
  108. if i < 1 {
  109. return
  110. }
  111. if i > d.maxTableIndex() {
  112. return
  113. }
  114. if i <= len(staticTable) {
  115. return staticTable[i-1], true
  116. }
  117. dents := d.dynTab.ents
  118. return dents[len(dents)-(i-len(staticTable))], true
  119. }
  120. // Decode decodes an entire block.
  121. //
  122. // TODO: remove this method and make it incremental later? This is
  123. // easier for debugging now.
  124. func (d *Decoder) Decode(p []byte) ([]HeaderField, error) {
  125. var hf []HeaderField
  126. // TODO: This is trashy. temporary development aid.
  127. saveFunc := d.emit
  128. defer func() { d.emit = saveFunc }()
  129. d.emit = func(f HeaderField, sensitive bool) {
  130. hf = append(hf, f)
  131. }
  132. for len(p) > 0 {
  133. // Look at first byte to see what we're dealing with.
  134. switch {
  135. case p[0]&(1<<7) != 0:
  136. // Indexed representation.
  137. // http://http2.github.io/http2-spec/compression.html#rfc.section.6.1
  138. idx, size, err := readVarInt(7, p)
  139. if err != nil {
  140. return nil, err
  141. }
  142. if size == 0 {
  143. // TODO: will later stop processing
  144. // here and wait for more (buffering
  145. // what we've got), but this is the
  146. // all-at-once Decode debug version.
  147. return nil, io.ErrUnexpectedEOF
  148. }
  149. if idx > uint64(d.maxTableIndex()) {
  150. return nil, DecodingError{InvalidIndexError(idx)}
  151. }
  152. hf, ok := d.at(int(idx))
  153. if !ok {
  154. return nil, DecodingError{InvalidIndexError(idx)}
  155. }
  156. d.emit(hf, false /* TODO: sensitive ? */)
  157. p = p[size:]
  158. default:
  159. panic("TODO")
  160. }
  161. }
  162. return hf, nil
  163. }
  164. var errVarintOverflow = DecodingError{errors.New("varint integer overflow")}
  165. // readVarInt reads an unsigned variable length integer off the
  166. // beginning of p. n is the parameter as described in
  167. // http://http2.github.io/http2-spec/compression.html#rfc.section.5.1.
  168. //
  169. // n must always be between 1 and 8.
  170. //
  171. // The returned consumed parameter is the number of bytes that were
  172. // consumed from the beginning of p. It is zero if the end of the
  173. // integer's representation wasn't included in p. (In this case,
  174. // callers should wait for more data to arrive and try again with a
  175. // larger p buffer).
  176. func readVarInt(n byte, p []byte) (i uint64, consumed int, err error) {
  177. if n < 1 || n > 8 {
  178. panic("bad n")
  179. }
  180. if len(p) == 0 {
  181. return
  182. }
  183. i = uint64(p[0])
  184. if n < 8 {
  185. i &= (1 << uint64(n)) - 1
  186. }
  187. if i < (1<<uint64(n))-1 {
  188. return i, 1, nil
  189. }
  190. p = p[1:]
  191. consumed++
  192. var m uint64
  193. for len(p) > 0 {
  194. b := p[0]
  195. consumed++
  196. i += uint64(b&127) << m
  197. if b&128 == 0 {
  198. return
  199. }
  200. p = p[1:]
  201. m += 7
  202. if m >= 63 { // TODO: proper overflow check. making this up.
  203. return 0, 0, errVarintOverflow
  204. }
  205. }
  206. return 0, 0, nil
  207. }