http2.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  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. "errors"
  21. "io"
  22. "log"
  23. "net/http"
  24. "net/url"
  25. "strconv"
  26. "strings"
  27. "github.com/bradfitz/http2/hpack"
  28. )
  29. const (
  30. // ClientPreface is the string that must be sent by new
  31. // connections from clients.
  32. ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
  33. // SETTINGS_MAX_FRAME_SIZE default
  34. // http://http2.github.io/http2-spec/#rfc.section.6.5.2
  35. initialMaxFrameSize = 16384
  36. )
  37. var (
  38. clientPreface = []byte(ClientPreface)
  39. )
  40. const (
  41. npnProto = "h2-14"
  42. // http://http2.github.io/http2-spec/#SettingValues
  43. initialHeaderTableSize = 4096
  44. )
  45. // Server is an HTTP2 server.
  46. type Server struct {
  47. // MaxStreams optionally ...
  48. MaxStreams int
  49. }
  50. func (srv *Server) handleConn(hs *http.Server, c *tls.Conn, h http.Handler) {
  51. sc := &serverConn{
  52. hs: hs,
  53. conn: c,
  54. handler: h,
  55. framer: NewFramer(c, c),
  56. streams: make(map[uint32]*stream),
  57. canonHeader: make(map[string]string),
  58. readFrameCh: make(chan frameAndProcessed),
  59. readFrameErrCh: make(chan error, 1),
  60. writeHeaderCh: make(chan headerWriteReq), // must not be buffered
  61. doneServing: make(chan struct{}),
  62. maxWriteFrameSize: initialMaxFrameSize,
  63. }
  64. sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
  65. sc.hpackDecoder = hpack.NewDecoder(initialHeaderTableSize, sc.onNewHeaderField)
  66. sc.serve()
  67. }
  68. // frameAndProcessed coordinates the readFrames and serve goroutines, since
  69. // the Framer interface only permits the most recently-read Frame from being
  70. // accessed. The serve goroutine sends on processed to signal to the readFrames
  71. // goroutine that another frame may be read.
  72. type frameAndProcessed struct {
  73. f Frame
  74. processed chan struct{}
  75. }
  76. type serverConn struct {
  77. hs *http.Server
  78. conn *tls.Conn
  79. handler http.Handler
  80. framer *Framer
  81. doneServing chan struct{} // closed when serverConn.serve ends
  82. readFrameCh chan frameAndProcessed // written by serverConn.readFrames
  83. readFrameErrCh chan error
  84. writeHeaderCh chan headerWriteReq // must not be buffered
  85. maxStreamID uint32 // max ever seen
  86. streams map[uint32]*stream
  87. maxWriteFrameSize uint32 // TODO: update this when settings come in
  88. // State related to parsing current headers:
  89. hpackDecoder *hpack.Decoder
  90. header http.Header
  91. canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case
  92. method, path string
  93. scheme, authority string
  94. // State related to writing current headers:
  95. hpackEncoder *hpack.Encoder
  96. headerWriteBuf bytes.Buffer
  97. // curHeaderStreamID is non-zero if we're in the middle
  98. // of parsing headers that span multiple frames.
  99. curHeaderStreamID uint32
  100. curStream *stream
  101. }
  102. type streamState int
  103. const (
  104. stateIdle streamState = iota
  105. stateOpen
  106. stateHalfClosedLocal
  107. stateHalfClosedRemote
  108. stateResvLocal
  109. stateResvRemote
  110. stateClosed
  111. )
  112. type stream struct {
  113. id uint32
  114. state streamState // owned by serverConn's processing loop
  115. }
  116. func (sc *serverConn) state(streamID uint32) streamState {
  117. // http://http2.github.io/http2-spec/#rfc.section.5.1
  118. if st, ok := sc.streams[streamID]; ok {
  119. return st.state
  120. }
  121. // "The first use of a new stream identifier implicitly closes all
  122. // streams in the "idle" state that might have been initiated by
  123. // that peer with a lower-valued stream identifier. For example, if
  124. // a client sends a HEADERS frame on stream 7 without ever sending a
  125. // frame on stream 5, then stream 5 transitions to the "closed"
  126. // state when the first frame for stream 7 is sent or received."
  127. if streamID <= sc.maxStreamID {
  128. return stateClosed
  129. }
  130. return stateIdle
  131. }
  132. func (sc *serverConn) logf(format string, args ...interface{}) {
  133. if lg := sc.hs.ErrorLog; lg != nil {
  134. lg.Printf(format, args...)
  135. } else {
  136. log.Printf(format, args...)
  137. }
  138. }
  139. func (sc *serverConn) onNewHeaderField(f hpack.HeaderField) {
  140. log.Printf("Header field: +%v", f)
  141. if strings.HasPrefix(f.Name, ":") {
  142. switch f.Name {
  143. case ":method":
  144. sc.method = f.Value
  145. case ":path":
  146. sc.path = f.Value
  147. case ":scheme":
  148. sc.scheme = f.Value
  149. case ":authority":
  150. sc.authority = f.Value
  151. default:
  152. log.Printf("Ignoring unknown pseudo-header %q", f.Name)
  153. }
  154. return
  155. }
  156. sc.header.Add(sc.canonicalHeader(f.Name), f.Value)
  157. }
  158. func (sc *serverConn) canonicalHeader(v string) string {
  159. // TODO: use a sync.Pool instead of putting the cache on *serverConn?
  160. cv, ok := sc.canonHeader[v]
  161. if !ok {
  162. cv = http.CanonicalHeaderKey(v)
  163. sc.canonHeader[v] = cv
  164. }
  165. return cv
  166. }
  167. func (sc *serverConn) readFrames() {
  168. processed := make(chan struct{}, 1)
  169. for {
  170. f, err := sc.framer.ReadFrame()
  171. if err != nil {
  172. close(sc.readFrameCh)
  173. sc.readFrameErrCh <- err
  174. return
  175. }
  176. sc.readFrameCh <- frameAndProcessed{f, processed}
  177. <-processed
  178. }
  179. }
  180. func (sc *serverConn) serve() {
  181. defer sc.conn.Close()
  182. defer close(sc.doneServing)
  183. log.Printf("HTTP/2 connection from %v on %p", sc.conn.RemoteAddr(), sc.hs)
  184. // Read the client preface
  185. buf := make([]byte, len(ClientPreface))
  186. // TODO: timeout reading from the client
  187. if _, err := io.ReadFull(sc.conn, buf); err != nil {
  188. sc.logf("error reading client preface: %v", err)
  189. return
  190. }
  191. if !bytes.Equal(buf, clientPreface) {
  192. sc.logf("bogus greeting from client: %q", buf)
  193. return
  194. }
  195. log.Printf("client %v said hello", sc.conn.RemoteAddr())
  196. go sc.readFrames()
  197. for {
  198. select {
  199. case hr := <-sc.writeHeaderCh:
  200. if err := sc.writeHeaderInLoop(hr); err != nil {
  201. // TODO: diff error handling?
  202. sc.logf("error writing response header: %v", err)
  203. return
  204. }
  205. case fp, ok := <-sc.readFrameCh:
  206. if !ok {
  207. err := <-sc.readFrameErrCh
  208. if err != io.EOF {
  209. sc.logf("client %s stopped sending frames: %v", sc.conn.RemoteAddr(), err)
  210. }
  211. return
  212. }
  213. f := fp.f
  214. log.Printf("got %v: %#v", f.Header(), f)
  215. err := sc.processFrame(f)
  216. fp.processed <- struct{}{} // let readFrames proceed
  217. if h2e, ok := err.(Error); ok {
  218. if h2e.IsConnectionError() {
  219. sc.logf("Disconnection; connection error: %v", err)
  220. return
  221. }
  222. // TODO: stream errors, etc
  223. }
  224. if err != nil {
  225. sc.logf("Disconnection due to other error: %v", err)
  226. return
  227. }
  228. }
  229. }
  230. }
  231. func (sc *serverConn) processFrame(f Frame) error {
  232. if s := sc.curHeaderStreamID; s != 0 {
  233. if cf, ok := f.(*ContinuationFrame); !ok {
  234. return ConnectionError(ErrCodeProtocol)
  235. } else if cf.Header().StreamID != s {
  236. return ConnectionError(ErrCodeProtocol)
  237. }
  238. }
  239. switch f := f.(type) {
  240. case *SettingsFrame:
  241. return sc.processSettings(f)
  242. case *HeadersFrame:
  243. return sc.processHeaders(f)
  244. case *ContinuationFrame:
  245. return sc.processContinuation(f)
  246. default:
  247. log.Printf("Ignoring unknown %v", f.Header)
  248. return nil
  249. }
  250. }
  251. func (sc *serverConn) processSettings(f *SettingsFrame) error {
  252. f.ForeachSetting(func(s Setting) {
  253. log.Printf(" setting %s = %v", s.ID, s.Val)
  254. })
  255. return nil
  256. }
  257. func (sc *serverConn) processHeaders(f *HeadersFrame) error {
  258. id := f.Header().StreamID
  259. // http://http2.github.io/http2-spec/#rfc.section.5.1.1
  260. if id%2 != 1 || id <= sc.maxStreamID {
  261. // Streams initiated by a client MUST use odd-numbered
  262. // stream identifiers. [...] The identifier of a newly
  263. // established stream MUST be numerically greater than all
  264. // streams that the initiating endpoint has opened or
  265. // reserved. [...] An endpoint that receives an unexpected
  266. // stream identifier MUST respond with a connection error
  267. // (Section 5.4.1) of type PROTOCOL_ERROR.
  268. return ConnectionError(ErrCodeProtocol)
  269. }
  270. if id > sc.maxStreamID {
  271. sc.maxStreamID = id
  272. }
  273. st := &stream{
  274. id: id,
  275. state: stateOpen,
  276. }
  277. if f.Header().Flags.Has(FlagHeadersEndStream) {
  278. st.state = stateHalfClosedRemote
  279. }
  280. sc.streams[id] = st
  281. sc.header = make(http.Header)
  282. sc.curHeaderStreamID = id
  283. sc.curStream = st
  284. return sc.processHeaderBlockFragment(f.HeaderBlockFragment(), f.HeadersEnded())
  285. }
  286. func (sc *serverConn) processContinuation(f *ContinuationFrame) error {
  287. return sc.processHeaderBlockFragment(f.HeaderBlockFragment(), f.HeadersEnded())
  288. }
  289. func (sc *serverConn) processHeaderBlockFragment(frag []byte, end bool) error {
  290. if _, err := sc.hpackDecoder.Write(frag); err != nil {
  291. // TODO: convert to stream error I assume?
  292. return err
  293. }
  294. if !end {
  295. return nil
  296. }
  297. if err := sc.hpackDecoder.Close(); err != nil {
  298. // TODO: convert to stream error I assume?
  299. return err
  300. }
  301. curStream := sc.curStream
  302. sc.curHeaderStreamID = 0
  303. sc.curStream = nil
  304. // TODO: transition streamID state
  305. go sc.startHandler(curStream.id, curStream.state == stateOpen, sc.method, sc.path, sc.scheme, sc.authority, sc.header)
  306. return nil
  307. }
  308. func (sc *serverConn) startHandler(streamID uint32, bodyOpen bool, method, path, scheme, authority string, reqHeader http.Header) {
  309. var tlsState *tls.ConnectionState // make this non-nil if https
  310. if scheme == "https" {
  311. // TODO: get from sc's ConnectionState
  312. tlsState = &tls.ConnectionState{}
  313. }
  314. req := &http.Request{
  315. Method: method,
  316. URL: &url.URL{},
  317. RemoteAddr: sc.conn.RemoteAddr().String(),
  318. RequestURI: path,
  319. Proto: "HTTP/2.0",
  320. ProtoMajor: 2,
  321. ProtoMinor: 0,
  322. TLS: tlsState,
  323. Host: authority,
  324. Body: &requestBody{
  325. sc: sc,
  326. streamID: streamID,
  327. hasBody: bodyOpen,
  328. },
  329. }
  330. if vv, ok := reqHeader["Content-Length"]; ok {
  331. req.ContentLength, _ = strconv.ParseInt(vv[0], 10, 64)
  332. } else {
  333. req.ContentLength = -1
  334. }
  335. rw := &responseWriter{
  336. sc: sc,
  337. streamID: streamID,
  338. }
  339. defer rw.handlerDone()
  340. // TODO: catch panics like net/http.Server
  341. sc.handler.ServeHTTP(rw, req)
  342. }
  343. // called from handler goroutines
  344. func (sc *serverConn) writeData(streamID uint32, p []byte) (n int, err error) {
  345. // TODO: implement
  346. log.Printf("WRITE on %d: %q", streamID, p)
  347. return len(p), nil
  348. }
  349. // headerWriteReq is a request to write an HTTP response header from a server Handler.
  350. type headerWriteReq struct {
  351. streamID uint32
  352. httpResCode int
  353. h http.Header // may be nil
  354. endStream bool
  355. }
  356. // called from handler goroutines.
  357. // h may be nil.
  358. func (sc *serverConn) writeHeader(req headerWriteReq) {
  359. sc.writeHeaderCh <- req
  360. }
  361. // called from serverConn.serve loop.
  362. func (sc *serverConn) writeHeaderInLoop(req headerWriteReq) error {
  363. sc.headerWriteBuf.Reset()
  364. // TODO: remove this strconv
  365. sc.hpackEncoder.WriteField(hpack.HeaderField{Name: ":status", Value: strconv.Itoa(req.httpResCode)})
  366. for k, vv := range req.h {
  367. for _, v := range vv {
  368. // TODO: for gargage, cache lowercase copies of headers at
  369. // least for common ones and/or popular recent ones for
  370. // this serverConn. LRU?
  371. sc.hpackEncoder.WriteField(hpack.HeaderField{Name: strings.ToLower(k), Value: v})
  372. }
  373. }
  374. headerBlock := sc.headerWriteBuf.Bytes()
  375. if len(headerBlock) > int(sc.maxWriteFrameSize) {
  376. // we'll need continuation ones.
  377. panic("TODO")
  378. }
  379. return sc.framer.WriteHeaders(HeadersFrameParam{
  380. StreamID: req.streamID,
  381. BlockFragment: headerBlock,
  382. EndStream: req.endStream,
  383. EndHeaders: true, // no continuation yet
  384. })
  385. }
  386. // ConfigureServer adds HTTP/2 support to a net/http Server.
  387. //
  388. // The configuration conf may be nil.
  389. //
  390. // ConfigureServer must be called before s begins serving.
  391. func ConfigureServer(s *http.Server, conf *Server) {
  392. if conf == nil {
  393. conf = new(Server)
  394. }
  395. if s.TLSConfig == nil {
  396. s.TLSConfig = new(tls.Config)
  397. }
  398. haveNPN := false
  399. for _, p := range s.TLSConfig.NextProtos {
  400. if p == npnProto {
  401. haveNPN = true
  402. break
  403. }
  404. }
  405. if !haveNPN {
  406. s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, npnProto)
  407. }
  408. if s.TLSNextProto == nil {
  409. s.TLSNextProto = map[string]func(*http.Server, *tls.Conn, http.Handler){}
  410. }
  411. s.TLSNextProto[npnProto] = func(hs *http.Server, c *tls.Conn, h http.Handler) {
  412. if testHookOnConn != nil {
  413. testHookOnConn()
  414. }
  415. conf.handleConn(hs, c, h)
  416. }
  417. }
  418. type requestBody struct {
  419. sc *serverConn
  420. streamID uint32
  421. hasBody bool
  422. closed bool
  423. }
  424. func (b *requestBody) Close() error {
  425. b.closed = true
  426. return nil
  427. }
  428. func (b *requestBody) Read(p []byte) (n int, err error) {
  429. if !b.hasBody {
  430. return 0, io.EOF
  431. }
  432. // TODO: implement
  433. return 0, errors.New("TODO: we don't handle request bodies yet")
  434. }
  435. type responseWriter struct {
  436. sc *serverConn
  437. streamID uint32
  438. wroteHeaders bool
  439. h http.Header
  440. }
  441. // TODO: bufio writing of responseWriter. add Flush, add pools of
  442. // bufio.Writers, adjust bufio writer sized based on frame size
  443. // updates from peer? For now: naive.
  444. func (w *responseWriter) Header() http.Header {
  445. if w.h == nil {
  446. w.h = make(http.Header)
  447. }
  448. return w.h
  449. }
  450. func (w *responseWriter) WriteHeader(code int) {
  451. if w.wroteHeaders {
  452. return
  453. }
  454. // TODO: defer actually writing this frame until a Flush or
  455. // handlerDone, like net/http's Server. then we can coalesce
  456. // e.g. a 204 response to have a Header response frame with
  457. // END_STREAM set, without a separate frame being sent in
  458. // handleDone.
  459. w.wroteHeaders = true
  460. w.sc.writeHeader(headerWriteReq{
  461. streamID: w.streamID,
  462. httpResCode: code,
  463. h: w.h,
  464. })
  465. }
  466. // TODO: responseWriter.WriteString too?
  467. func (w *responseWriter) Write(p []byte) (n int, err error) {
  468. if !w.wroteHeaders {
  469. w.WriteHeader(200)
  470. }
  471. return w.sc.writeData(w.streamID, p) // blocks waiting for tokens
  472. }
  473. func (w *responseWriter) handlerDone() {
  474. if !w.wroteHeaders {
  475. w.sc.writeHeader(headerWriteReq{
  476. streamID: w.streamID,
  477. httpResCode: 200,
  478. h: w.h,
  479. endStream: true, // handler has finished; can't be any data.
  480. })
  481. }
  482. }
  483. var testHookOnConn func() // for testing