http2.go 8.9 KB

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