http2.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  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. "io/ioutil"
  16. "log"
  17. "net/http"
  18. "sync"
  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 npnProto = "h2-14"
  29. // Server is an HTTP2 server.
  30. type Server struct {
  31. // MaxStreams optionally ...
  32. MaxStreams int
  33. mu sync.Mutex
  34. }
  35. func (srv *Server) handleClientConn(hs *http.Server, c *tls.Conn, h http.Handler) {
  36. cc := &clientConn{hs, c, h}
  37. cc.serve()
  38. }
  39. type clientConn struct {
  40. hs *http.Server
  41. c *tls.Conn
  42. h http.Handler
  43. }
  44. func (cc *clientConn) logf(format string, args ...interface{}) {
  45. if lg := cc.hs.ErrorLog; lg != nil {
  46. lg.Printf(format, args...)
  47. } else {
  48. log.Printf(format, args...)
  49. }
  50. }
  51. func (cc *clientConn) serve() {
  52. defer cc.c.Close()
  53. log.Printf("HTTP/2 connection from %v on %p", cc.c.RemoteAddr(), cc.hs)
  54. buf := make([]byte, len(ClientPreface))
  55. // TODO: timeout reading from the client
  56. if _, err := io.ReadFull(cc.c, buf); err != nil {
  57. cc.logf("error reading client preface: %v", err)
  58. return
  59. }
  60. if !bytes.Equal(buf, clientPreface) {
  61. cc.logf("bogus greeting from client: %q", buf)
  62. return
  63. }
  64. log.Printf("client %v said hello", cc.c.RemoteAddr())
  65. var frameReader = io.LimitedReader{
  66. R: cc.c,
  67. }
  68. for {
  69. fh, err := ReadFrameHeader(cc.c)
  70. if err != nil {
  71. if err != io.EOF {
  72. cc.logf("error reading frame: %v", err)
  73. }
  74. return
  75. }
  76. frameReader.N = int64(fh.Length)
  77. f, err := typeFrameParser(fh.Type)(fh, &frameReader)
  78. if h2e, ok := err.(Error); ok {
  79. if h2e.IsConnectionError() {
  80. log.Printf("Disconnection; connection error: %v", err)
  81. return
  82. }
  83. // TODO: stream errors, etc
  84. }
  85. if err != nil {
  86. log.Printf("Disconnection to other error: %v", err)
  87. return
  88. }
  89. if n, _ := io.Copy(ioutil.Discard, &frameReader); n > 0 {
  90. log.Printf("Frame reader for %s failed to read %d bytes", fh.Type, n)
  91. return
  92. }
  93. log.Printf("got frame: %#v", f)
  94. }
  95. }
  96. // ConfigureServer adds HTTP2 support to s as configured by the HTTP/2
  97. // server configuration in conf. The configuration may be nil.
  98. //
  99. // ConfigureServer must be called before s beings serving.
  100. func ConfigureServer(s *http.Server, conf *Server) {
  101. if conf == nil {
  102. conf = new(Server)
  103. }
  104. if s.TLSConfig == nil {
  105. s.TLSConfig = new(tls.Config)
  106. }
  107. haveNPN := false
  108. for _, p := range s.TLSConfig.NextProtos {
  109. if p == npnProto {
  110. haveNPN = true
  111. break
  112. }
  113. }
  114. if !haveNPN {
  115. s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, npnProto)
  116. }
  117. if s.TLSNextProto == nil {
  118. s.TLSNextProto = map[string]func(*http.Server, *tls.Conn, http.Handler){}
  119. }
  120. s.TLSNextProto[npnProto] = func(hs *http.Server, c *tls.Conn, h http.Handler) {
  121. if testHookOnConn != nil {
  122. testHookOnConn()
  123. }
  124. conf.handleClientConn(hs, c, h)
  125. }
  126. }
  127. var testHookOnConn func() // for testing