http2.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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. "fmt"
  19. "net/http"
  20. "strconv"
  21. "sync"
  22. )
  23. var VerboseLogs = false
  24. const (
  25. // ClientPreface is the string that must be sent by new
  26. // connections from clients.
  27. ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
  28. // SETTINGS_MAX_FRAME_SIZE default
  29. // http://http2.github.io/http2-spec/#rfc.section.6.5.2
  30. initialMaxFrameSize = 16384
  31. npnProto = "h2-14"
  32. // http://http2.github.io/http2-spec/#SettingValues
  33. initialHeaderTableSize = 4096
  34. initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size
  35. )
  36. var (
  37. clientPreface = []byte(ClientPreface)
  38. )
  39. type streamState int
  40. const (
  41. stateIdle streamState = iota
  42. stateOpen
  43. stateHalfClosedLocal
  44. stateHalfClosedRemote
  45. stateResvLocal
  46. stateResvRemote
  47. stateClosed
  48. )
  49. var stateName = [...]string{
  50. stateIdle: "Idle",
  51. stateOpen: "Open",
  52. stateHalfClosedLocal: "HalfClosedLocal",
  53. stateHalfClosedRemote: "HalfClosedRemote",
  54. stateResvLocal: "ResvLocal",
  55. stateResvRemote: "ResvRemote",
  56. stateClosed: "Closed",
  57. }
  58. func (st streamState) String() string {
  59. return stateName[st]
  60. }
  61. // Setting is a setting parameter: which setting it is, and its value.
  62. type Setting struct {
  63. // ID is which setting is being set.
  64. // See http://http2.github.io/http2-spec/#SettingValues
  65. ID SettingID
  66. // Val is the value.
  67. Val uint32
  68. }
  69. func (s Setting) String() string {
  70. return fmt.Sprintf("[%v = %d]", s.ID, s.Val)
  71. }
  72. // Valid reports whether the setting is valid.
  73. func (s Setting) Valid() error {
  74. // Limits and error codes from 6.5.2 Defined SETTINGS Parameters
  75. switch s.ID {
  76. case SettingEnablePush:
  77. if s.Val != 1 && s.Val != 0 {
  78. return ConnectionError(ErrCodeProtocol)
  79. }
  80. case SettingInitialWindowSize:
  81. if s.Val > 1<<31-1 {
  82. return ConnectionError(ErrCodeFlowControl)
  83. }
  84. case SettingMaxFrameSize:
  85. if s.Val < 16384 || s.Val > 1<<24-1 {
  86. return ConnectionError(ErrCodeProtocol)
  87. }
  88. }
  89. return nil
  90. }
  91. // A SettingID is an HTTP/2 setting as defined in
  92. // http://http2.github.io/http2-spec/#iana-settings
  93. type SettingID uint16
  94. const (
  95. SettingHeaderTableSize SettingID = 0x1
  96. SettingEnablePush SettingID = 0x2
  97. SettingMaxConcurrentStreams SettingID = 0x3
  98. SettingInitialWindowSize SettingID = 0x4
  99. SettingMaxFrameSize SettingID = 0x5
  100. SettingMaxHeaderListSize SettingID = 0x6
  101. )
  102. var settingName = map[SettingID]string{
  103. SettingHeaderTableSize: "HEADER_TABLE_SIZE",
  104. SettingEnablePush: "ENABLE_PUSH",
  105. SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS",
  106. SettingInitialWindowSize: "INITIAL_WINDOW_SIZE",
  107. SettingMaxFrameSize: "MAX_FRAME_SIZE",
  108. SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE",
  109. }
  110. func (s SettingID) String() string {
  111. if v, ok := settingName[s]; ok {
  112. return v
  113. }
  114. return fmt.Sprintf("UNKNOWN_SETTING_%d", uint8(s))
  115. }
  116. func validHeader(v string) bool {
  117. if len(v) == 0 {
  118. return false
  119. }
  120. for _, r := range v {
  121. // "Just as in HTTP/1.x, header field names are
  122. // strings of ASCII characters that are compared in a
  123. // case-insensitive fashion. However, header field
  124. // names MUST be converted to lowercase prior to their
  125. // encoding in HTTP/2. "
  126. if r >= 127 || ('A' <= r && r <= 'Z') {
  127. return false
  128. }
  129. }
  130. return true
  131. }
  132. var httpCodeStringCommon = map[int]string{} // n -> strconv.Itoa(n)
  133. func init() {
  134. for i := 100; i <= 999; i++ {
  135. if v := http.StatusText(i); v != "" {
  136. httpCodeStringCommon[i] = strconv.Itoa(i)
  137. }
  138. }
  139. }
  140. func httpCodeString(code int) string {
  141. if s, ok := httpCodeStringCommon[code]; ok {
  142. return s
  143. }
  144. return strconv.Itoa(code)
  145. }
  146. // from pkg io
  147. type stringWriter interface {
  148. WriteString(s string) (n int, err error)
  149. }
  150. // A gate lets two goroutines coordinate their activities.
  151. type gate chan struct{}
  152. func (g gate) Done() { g <- struct{}{} }
  153. func (g gate) Wait() { <-g }
  154. // A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed).
  155. type closeWaiter struct {
  156. m sync.Mutex
  157. c sync.Cond
  158. closed bool
  159. }
  160. // Init makes a closeWaiter usable.
  161. // It exists because so a closeWaiter value can be placed inside a
  162. // larger struct and have the Mutex and Cond's memory in the same
  163. // allocation.
  164. func (cw *closeWaiter) Init() {
  165. cw.c.L = &cw.m
  166. }
  167. // Close marks the closeWwaiter as closed and unblocks any waiters.
  168. func (cw *closeWaiter) Close() {
  169. cw.m.Lock()
  170. cw.closed = true
  171. cw.m.Unlock()
  172. cw.c.Broadcast()
  173. }
  174. // Wait waits for the closeWaiter to become closed.
  175. func (cw *closeWaiter) Wait() {
  176. cw.m.Lock()
  177. defer cw.m.Unlock()
  178. for !cw.closed {
  179. cw.c.Wait()
  180. }
  181. }