http2.go 6.0 KB

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