http2.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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. // See https://code.google.com/p/go/source/browse/CONTRIBUTORS
  5. // Licensed under the same terms as Go itself:
  6. // https://code.google.com/p/go/source/browse/LICENSE
  7. // Package http2 implements the HTTP/2 protocol.
  8. //
  9. // This is a work in progress. This package is low-level and intended
  10. // to be used directly by very few people. Most users will use it
  11. // indirectly through integration with the net/http package. See
  12. // ConfigureServer. That ConfigureServer call will likely be automatic
  13. // or available via an empty import in the future.
  14. //
  15. // This package currently targets draft-14. See http://http2.github.io/
  16. package http2
  17. import (
  18. "bufio"
  19. "fmt"
  20. "io"
  21. "net/http"
  22. "strconv"
  23. "sync"
  24. )
  25. var VerboseLogs = false
  26. const (
  27. // ClientPreface is the string that must be sent by new
  28. // connections from clients.
  29. ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
  30. // SETTINGS_MAX_FRAME_SIZE default
  31. // http://http2.github.io/http2-spec/#rfc.section.6.5.2
  32. initialMaxFrameSize = 16384
  33. npnProto = "h2-14"
  34. // http://http2.github.io/http2-spec/#SettingValues
  35. initialHeaderTableSize = 4096
  36. initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size
  37. defaultMaxReadFrameSize = 1 << 20
  38. )
  39. var (
  40. clientPreface = []byte(ClientPreface)
  41. )
  42. type streamState int
  43. const (
  44. stateIdle streamState = iota
  45. stateOpen
  46. stateHalfClosedLocal
  47. stateHalfClosedRemote
  48. stateResvLocal
  49. stateResvRemote
  50. stateClosed
  51. )
  52. var stateName = [...]string{
  53. stateIdle: "Idle",
  54. stateOpen: "Open",
  55. stateHalfClosedLocal: "HalfClosedLocal",
  56. stateHalfClosedRemote: "HalfClosedRemote",
  57. stateResvLocal: "ResvLocal",
  58. stateResvRemote: "ResvRemote",
  59. stateClosed: "Closed",
  60. }
  61. func (st streamState) String() string {
  62. return stateName[st]
  63. }
  64. // Setting is a setting parameter: which setting it is, and its value.
  65. type Setting struct {
  66. // ID is which setting is being set.
  67. // See http://http2.github.io/http2-spec/#SettingValues
  68. ID SettingID
  69. // Val is the value.
  70. Val uint32
  71. }
  72. func (s Setting) String() string {
  73. return fmt.Sprintf("[%v = %d]", s.ID, s.Val)
  74. }
  75. // Valid reports whether the setting is valid.
  76. func (s Setting) Valid() error {
  77. // Limits and error codes from 6.5.2 Defined SETTINGS Parameters
  78. switch s.ID {
  79. case SettingEnablePush:
  80. if s.Val != 1 && s.Val != 0 {
  81. return ConnectionError(ErrCodeProtocol)
  82. }
  83. case SettingInitialWindowSize:
  84. if s.Val > 1<<31-1 {
  85. return ConnectionError(ErrCodeFlowControl)
  86. }
  87. case SettingMaxFrameSize:
  88. if s.Val < 16384 || s.Val > 1<<24-1 {
  89. return ConnectionError(ErrCodeProtocol)
  90. }
  91. }
  92. return nil
  93. }
  94. // A SettingID is an HTTP/2 setting as defined in
  95. // http://http2.github.io/http2-spec/#iana-settings
  96. type SettingID uint16
  97. const (
  98. SettingHeaderTableSize SettingID = 0x1
  99. SettingEnablePush SettingID = 0x2
  100. SettingMaxConcurrentStreams SettingID = 0x3
  101. SettingInitialWindowSize SettingID = 0x4
  102. SettingMaxFrameSize SettingID = 0x5
  103. SettingMaxHeaderListSize SettingID = 0x6
  104. )
  105. var settingName = map[SettingID]string{
  106. SettingHeaderTableSize: "HEADER_TABLE_SIZE",
  107. SettingEnablePush: "ENABLE_PUSH",
  108. SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS",
  109. SettingInitialWindowSize: "INITIAL_WINDOW_SIZE",
  110. SettingMaxFrameSize: "MAX_FRAME_SIZE",
  111. SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE",
  112. }
  113. func (s SettingID) String() string {
  114. if v, ok := settingName[s]; ok {
  115. return v
  116. }
  117. return fmt.Sprintf("UNKNOWN_SETTING_%d", uint8(s))
  118. }
  119. func validHeader(v string) bool {
  120. if len(v) == 0 {
  121. return false
  122. }
  123. for _, r := range v {
  124. // "Just as in HTTP/1.x, header field names are
  125. // strings of ASCII characters that are compared in a
  126. // case-insensitive fashion. However, header field
  127. // names MUST be converted to lowercase prior to their
  128. // encoding in HTTP/2. "
  129. if r >= 127 || ('A' <= r && r <= 'Z') {
  130. return false
  131. }
  132. }
  133. return true
  134. }
  135. var httpCodeStringCommon = map[int]string{} // n -> strconv.Itoa(n)
  136. func init() {
  137. for i := 100; i <= 999; i++ {
  138. if v := http.StatusText(i); v != "" {
  139. httpCodeStringCommon[i] = strconv.Itoa(i)
  140. }
  141. }
  142. }
  143. func httpCodeString(code int) string {
  144. if s, ok := httpCodeStringCommon[code]; ok {
  145. return s
  146. }
  147. return strconv.Itoa(code)
  148. }
  149. // from pkg io
  150. type stringWriter interface {
  151. WriteString(s string) (n int, err error)
  152. }
  153. // A gate lets two goroutines coordinate their activities.
  154. type gate chan struct{}
  155. func (g gate) Done() { g <- struct{}{} }
  156. func (g gate) Wait() { <-g }
  157. // A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed).
  158. type closeWaiter struct {
  159. m sync.Mutex
  160. c sync.Cond
  161. closed bool
  162. }
  163. // Init makes a closeWaiter usable.
  164. // It exists because so a closeWaiter value can be placed inside a
  165. // larger struct and have the Mutex and Cond's memory in the same
  166. // allocation.
  167. func (cw *closeWaiter) Init() {
  168. cw.c.L = &cw.m
  169. }
  170. // Close marks the closeWwaiter as closed and unblocks any waiters.
  171. func (cw *closeWaiter) Close() {
  172. cw.m.Lock()
  173. cw.closed = true
  174. cw.m.Unlock()
  175. cw.c.Broadcast()
  176. }
  177. // Wait waits for the closeWaiter to become closed.
  178. func (cw *closeWaiter) Wait() {
  179. cw.m.Lock()
  180. defer cw.m.Unlock()
  181. for !cw.closed {
  182. cw.c.Wait()
  183. }
  184. }
  185. // bufferedWriter is a buffered writer that writes to w.
  186. // Its buffered writer is lazily allocated as needed, to minimize
  187. // idle memory usage with many connections.
  188. type bufferedWriter struct {
  189. w io.Writer // immutable
  190. bw *bufio.Writer // non-nil when data is buffered
  191. }
  192. func newBufferedWriter(w io.Writer) *bufferedWriter {
  193. return &bufferedWriter{w: w}
  194. }
  195. var bufWriterPool = sync.Pool{
  196. New: func() interface{} {
  197. // TODO: pick something better? this is a bit under
  198. // (3 x typical 1500 byte MTU) at least.
  199. return bufio.NewWriterSize(nil, 4<<10)
  200. },
  201. }
  202. func (w *bufferedWriter) Write(p []byte) (n int, err error) {
  203. if w.bw == nil {
  204. bw := bufWriterPool.Get().(*bufio.Writer)
  205. bw.Reset(w.w)
  206. w.bw = bw
  207. }
  208. return w.bw.Write(p)
  209. }
  210. func (w *bufferedWriter) Flush() error {
  211. bw := w.bw
  212. if bw == nil {
  213. return nil
  214. }
  215. err := bw.Flush()
  216. bw.Reset(nil)
  217. bufWriterPool.Put(bw)
  218. w.bw = nil
  219. return err
  220. }