http2.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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. // It currently targets draft-14. See http://http2.github.io/
  10. package http2
  11. import (
  12. "bytes"
  13. "crypto/tls"
  14. "io"
  15. "log"
  16. "net/http"
  17. "strings"
  18. "github.com/bradfitz/http2/hpack"
  19. )
  20. const (
  21. // ClientPreface is the string that must be sent by new
  22. // connections from clients.
  23. ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
  24. )
  25. var (
  26. clientPreface = []byte(ClientPreface)
  27. )
  28. const (
  29. npnProto = "h2-14"
  30. // http://http2.github.io/http2-spec/#SettingValues
  31. initialHeaderTableSize = 4096
  32. )
  33. // Server is an HTTP2 server.
  34. type Server struct {
  35. // MaxStreams optionally ...
  36. MaxStreams int
  37. }
  38. func (srv *Server) handleConn(hs *http.Server, c *tls.Conn, h http.Handler) {
  39. sc := &serverConn{
  40. hs: hs,
  41. conn: c,
  42. handler: h,
  43. framer: NewFramer(c, c),
  44. streams: make(map[uint32]*stream),
  45. canonHeader: make(map[string]string),
  46. }
  47. sc.hpackDecoder = hpack.NewDecoder(initialHeaderTableSize, sc.onNewHeaderField)
  48. sc.serve()
  49. }
  50. type serverConn struct {
  51. hs *http.Server
  52. conn *tls.Conn
  53. handler http.Handler
  54. framer *Framer
  55. maxStreamID uint32 // max ever seen
  56. streams map[uint32]*stream
  57. // State related to parsing current headers:
  58. hpackDecoder *hpack.Decoder
  59. header http.Header
  60. canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case
  61. method, path, scheme, authority string
  62. // curHeaderStreamID is non-zero if we're in the middle
  63. // of parsing headers that span multiple frames.
  64. curHeaderStreamID uint32
  65. }
  66. type streamState int
  67. const (
  68. stateIdle streamState = iota
  69. stateOpen
  70. stateHalfClosedLocal
  71. stateHalfClosedRemote
  72. stateResvLocal
  73. stateResvRemote
  74. stateClosed
  75. )
  76. type stream struct {
  77. id uint32
  78. state streamState // owned by serverConn's processing loop
  79. }
  80. func (sc *serverConn) state(streamID uint32) streamState {
  81. // http://http2.github.io/http2-spec/#rfc.section.5.1
  82. if st, ok := sc.streams[streamID]; ok {
  83. return st.state
  84. }
  85. // "The first use of a new stream identifier implicitly closes all
  86. // streams in the "idle" state that might have been initiated by
  87. // that peer with a lower-valued stream identifier. For example, if
  88. // a client sends a HEADERS frame on stream 7 without ever sending a
  89. // frame on stream 5, then stream 5 transitions to the "closed"
  90. // state when the first frame for stream 7 is sent or received."
  91. if streamID <= sc.maxStreamID {
  92. return stateClosed
  93. }
  94. return stateIdle
  95. }
  96. func (sc *serverConn) logf(format string, args ...interface{}) {
  97. if lg := sc.hs.ErrorLog; lg != nil {
  98. lg.Printf(format, args...)
  99. } else {
  100. log.Printf(format, args...)
  101. }
  102. }
  103. func (sc *serverConn) onNewHeaderField(f hpack.HeaderField) {
  104. log.Printf("Header field: +%v", f)
  105. if strings.HasPrefix(f.Name, ":") {
  106. switch f.Name {
  107. case ":method":
  108. sc.method = f.Value
  109. case ":path":
  110. sc.path = f.Value
  111. case ":scheme":
  112. sc.scheme = f.Value
  113. case ":authority":
  114. sc.authority = f.Value
  115. default:
  116. log.Printf("Ignoring unknown pseudo-header %q", f.Name)
  117. }
  118. return
  119. }
  120. sc.header.Add(sc.canonicalHeader(f.Name), f.Value)
  121. }
  122. func (sc *serverConn) canonicalHeader(v string) string {
  123. // TODO: use a sync.Pool instead of putting the cache on *serverConn?
  124. cv, ok := sc.canonHeader[v]
  125. if !ok {
  126. cv = http.CanonicalHeaderKey(v)
  127. sc.canonHeader[v] = cv
  128. }
  129. return cv
  130. }
  131. func (sc *serverConn) serve() {
  132. defer sc.conn.Close()
  133. log.Printf("HTTP/2 connection from %v on %p", sc.conn.RemoteAddr(), sc.hs)
  134. buf := make([]byte, len(ClientPreface))
  135. // TODO: timeout reading from the client
  136. if _, err := io.ReadFull(sc.conn, buf); err != nil {
  137. sc.logf("error reading client preface: %v", err)
  138. return
  139. }
  140. if !bytes.Equal(buf, clientPreface) {
  141. sc.logf("bogus greeting from client: %q", buf)
  142. return
  143. }
  144. log.Printf("client %v said hello", sc.conn.RemoteAddr())
  145. for {
  146. f, err := sc.framer.ReadFrame()
  147. if err == nil {
  148. log.Printf("got %v: %#v", f.Header(), f)
  149. err = sc.processFrame(f)
  150. }
  151. if h2e, ok := err.(Error); ok {
  152. if h2e.IsConnectionError() {
  153. sc.logf("Disconnection; connection error: %v", err)
  154. return
  155. }
  156. // TODO: stream errors, etc
  157. }
  158. if err != nil {
  159. sc.logf("Disconnection due to other error: %v", err)
  160. return
  161. }
  162. }
  163. }
  164. func (sc *serverConn) processFrame(f Frame) error {
  165. if s := sc.curHeaderStreamID; s != 0 {
  166. if cf, ok := f.(*ContinuationFrame); !ok {
  167. return ConnectionError(ErrCodeProtocol)
  168. } else if cf.Header().StreamID != s {
  169. return ConnectionError(ErrCodeProtocol)
  170. }
  171. }
  172. switch f := f.(type) {
  173. case *SettingsFrame:
  174. return sc.processSettings(f)
  175. case *HeadersFrame:
  176. return sc.processHeaders(f)
  177. case *ContinuationFrame:
  178. return sc.processContinuation(f)
  179. default:
  180. log.Printf("Ignoring unknown %v", f.Header)
  181. return nil
  182. }
  183. }
  184. func (sc *serverConn) processSettings(f *SettingsFrame) error {
  185. f.ForeachSetting(func(s SettingID, v uint32) {
  186. log.Printf(" setting %s = %v", s, v)
  187. })
  188. return nil
  189. }
  190. func (sc *serverConn) processHeaders(f *HeadersFrame) error {
  191. id := f.Header().StreamID
  192. // http://http2.github.io/http2-spec/#rfc.section.5.1.1
  193. if id%2 != 1 || id <= sc.maxStreamID {
  194. // Streams initiated by a client MUST use odd-numbered
  195. // stream identifiers. [...] The identifier of a newly
  196. // established stream MUST be numerically greater than all
  197. // streams that the initiating endpoint has opened or
  198. // reserved. [...] An endpoint that receives an unexpected
  199. // stream identifier MUST respond with a connection error
  200. // (Section 5.4.1) of type PROTOCOL_ERROR.
  201. return ConnectionError(ErrCodeProtocol)
  202. }
  203. if id > sc.maxStreamID {
  204. sc.maxStreamID = id
  205. }
  206. sc.header = make(http.Header)
  207. sc.curHeaderStreamID = id
  208. return sc.processHeaderBlockFragment(f.HeaderBlockFragment(), f.HeadersEnded())
  209. }
  210. func (sc *serverConn) processHeaderBlockFragment(frag []byte, end bool) error {
  211. if _, err := sc.hpackDecoder.Write(frag); err != nil {
  212. // TODO: convert to stream error I assume?
  213. }
  214. if end {
  215. if err := sc.hpackDecoder.Close(); err != nil {
  216. // TODO: convert to stream error I assume?
  217. return err
  218. }
  219. sc.curHeaderStreamID = 0
  220. // TODO: transition state
  221. }
  222. return nil
  223. }
  224. func (sc *serverConn) processContinuation(f *ContinuationFrame) error {
  225. return sc.processHeaderBlockFragment(f.HeaderBlockFragment(), f.HeadersEnded())
  226. }
  227. // ConfigureServer adds HTTP2 support to s as configured by the HTTP/2
  228. // server configuration in conf. The configuration may be nil.
  229. //
  230. // ConfigureServer must be called before s begins serving.
  231. func ConfigureServer(s *http.Server, conf *Server) {
  232. if conf == nil {
  233. conf = new(Server)
  234. }
  235. if s.TLSConfig == nil {
  236. s.TLSConfig = new(tls.Config)
  237. }
  238. haveNPN := false
  239. for _, p := range s.TLSConfig.NextProtos {
  240. if p == npnProto {
  241. haveNPN = true
  242. break
  243. }
  244. }
  245. if !haveNPN {
  246. s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, npnProto)
  247. }
  248. if s.TLSNextProto == nil {
  249. s.TLSNextProto = map[string]func(*http.Server, *tls.Conn, http.Handler){}
  250. }
  251. s.TLSNextProto[npnProto] = func(hs *http.Server, c *tls.Conn, h http.Handler) {
  252. if testHookOnConn != nil {
  253. testHookOnConn()
  254. }
  255. conf.handleConn(hs, c, h)
  256. }
  257. }
  258. var testHookOnConn func() // for testing