Source file src/net/http/internal/http2/http2.go

     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  
     5  // Package http2 implements the HTTP/2 protocol.
     6  //
     7  // This package is low-level and intended to be used directly by very
     8  // few people. Most users will use it indirectly through the automatic
     9  // use by the net/http package (from Go 1.6 and later).
    10  // For use in earlier Go versions see ConfigureServer. (Transport support
    11  // requires Go 1.6 or later)
    12  //
    13  // See https://http2.github.io/ for more information on HTTP/2.
    14  package http2
    15  
    16  import (
    17  	"bufio"
    18  	"crypto/tls"
    19  	"errors"
    20  	"fmt"
    21  	"net"
    22  	"os"
    23  	"sort"
    24  	"strconv"
    25  	"strings"
    26  	"sync"
    27  	"time"
    28  
    29  	"golang.org/x/net/http/httpguts"
    30  )
    31  
    32  var (
    33  	VerboseLogs    bool
    34  	logFrameWrites bool
    35  	logFrameReads  bool
    36  
    37  	// Enabling extended CONNECT by causes browsers to attempt to use
    38  	// WebSockets-over-HTTP/2. This results in problems when the server's websocket
    39  	// package doesn't support extended CONNECT.
    40  	//
    41  	// Disable extended CONNECT by default for now.
    42  	//
    43  	// Issue #71128.
    44  	disableExtendedConnectProtocol = true
    45  
    46  	inTests = false
    47  )
    48  
    49  func init() {
    50  	e := os.Getenv("GODEBUG")
    51  	if strings.Contains(e, "http2debug=1") {
    52  		VerboseLogs = true
    53  	}
    54  	if strings.Contains(e, "http2debug=2") {
    55  		VerboseLogs = true
    56  		logFrameWrites = true
    57  		logFrameReads = true
    58  	}
    59  	if strings.Contains(e, "http2xconnect=1") {
    60  		disableExtendedConnectProtocol = false
    61  	}
    62  }
    63  
    64  const (
    65  	// ClientPreface is the string that must be sent by new
    66  	// connections from clients.
    67  	ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
    68  
    69  	// SETTINGS_MAX_FRAME_SIZE default
    70  	// https://httpwg.org/specs/rfc7540.html#rfc.section.6.5.2
    71  	initialMaxFrameSize = 16384
    72  
    73  	// NextProtoTLS is the NPN/ALPN protocol negotiated during
    74  	// HTTP/2's TLS setup.
    75  	NextProtoTLS = "h2"
    76  
    77  	// https://httpwg.org/specs/rfc7540.html#SettingValues
    78  	initialHeaderTableSize = 4096
    79  
    80  	initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size
    81  
    82  	defaultMaxReadFrameSize = 1 << 20
    83  )
    84  
    85  var (
    86  	clientPreface = []byte(ClientPreface)
    87  )
    88  
    89  type streamState int
    90  
    91  // HTTP/2 stream states.
    92  //
    93  // See http://tools.ietf.org/html/rfc7540#section-5.1.
    94  //
    95  // For simplicity, the server code merges "reserved (local)" into
    96  // "half-closed (remote)". This is one less state transition to track.
    97  // The only downside is that we send PUSH_PROMISEs slightly less
    98  // liberally than allowable. More discussion here:
    99  // https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0599.html
   100  //
   101  // "reserved (remote)" is omitted since the client code does not
   102  // support server push.
   103  const (
   104  	stateIdle streamState = iota
   105  	stateOpen
   106  	stateHalfClosedLocal
   107  	stateHalfClosedRemote
   108  	stateClosed
   109  )
   110  
   111  var stateName = [...]string{
   112  	stateIdle:             "Idle",
   113  	stateOpen:             "Open",
   114  	stateHalfClosedLocal:  "HalfClosedLocal",
   115  	stateHalfClosedRemote: "HalfClosedRemote",
   116  	stateClosed:           "Closed",
   117  }
   118  
   119  func (st streamState) String() string {
   120  	return stateName[st]
   121  }
   122  
   123  // Setting is a setting parameter: which setting it is, and its value.
   124  type Setting struct {
   125  	// ID is which setting is being set.
   126  	// See https://httpwg.org/specs/rfc7540.html#SettingFormat
   127  	ID SettingID
   128  
   129  	// Val is the value.
   130  	Val uint32
   131  }
   132  
   133  func (s Setting) String() string {
   134  	return fmt.Sprintf("[%v = %d]", s.ID, s.Val)
   135  }
   136  
   137  // Valid reports whether the setting is valid.
   138  func (s Setting) Valid() error {
   139  	// Limits and error codes from 6.5.2 Defined SETTINGS Parameters
   140  	switch s.ID {
   141  	case SettingEnablePush:
   142  		if s.Val != 1 && s.Val != 0 {
   143  			return ConnectionError(ErrCodeProtocol)
   144  		}
   145  	case SettingInitialWindowSize:
   146  		if s.Val > 1<<31-1 {
   147  			return ConnectionError(ErrCodeFlowControl)
   148  		}
   149  	case SettingMaxFrameSize:
   150  		if s.Val < 16384 || s.Val > 1<<24-1 {
   151  			return ConnectionError(ErrCodeProtocol)
   152  		}
   153  	case SettingEnableConnectProtocol:
   154  		if s.Val != 1 && s.Val != 0 {
   155  			return ConnectionError(ErrCodeProtocol)
   156  		}
   157  	}
   158  	return nil
   159  }
   160  
   161  // A SettingID is an HTTP/2 setting as defined in
   162  // https://httpwg.org/specs/rfc7540.html#iana-settings
   163  type SettingID uint16
   164  
   165  const (
   166  	SettingHeaderTableSize       SettingID = 0x1
   167  	SettingEnablePush            SettingID = 0x2
   168  	SettingMaxConcurrentStreams  SettingID = 0x3
   169  	SettingInitialWindowSize     SettingID = 0x4
   170  	SettingMaxFrameSize          SettingID = 0x5
   171  	SettingMaxHeaderListSize     SettingID = 0x6
   172  	SettingEnableConnectProtocol SettingID = 0x8
   173  	SettingNoRFC7540Priorities   SettingID = 0x9
   174  )
   175  
   176  var settingName = map[SettingID]string{
   177  	SettingHeaderTableSize:       "HEADER_TABLE_SIZE",
   178  	SettingEnablePush:            "ENABLE_PUSH",
   179  	SettingMaxConcurrentStreams:  "MAX_CONCURRENT_STREAMS",
   180  	SettingInitialWindowSize:     "INITIAL_WINDOW_SIZE",
   181  	SettingMaxFrameSize:          "MAX_FRAME_SIZE",
   182  	SettingMaxHeaderListSize:     "MAX_HEADER_LIST_SIZE",
   183  	SettingEnableConnectProtocol: "ENABLE_CONNECT_PROTOCOL",
   184  	SettingNoRFC7540Priorities:   "NO_RFC7540_PRIORITIES",
   185  }
   186  
   187  func (s SettingID) String() string {
   188  	if v, ok := settingName[s]; ok {
   189  		return v
   190  	}
   191  	return fmt.Sprintf("UNKNOWN_SETTING_%d", uint16(s))
   192  }
   193  
   194  // validWireHeaderFieldName reports whether v is a valid header field
   195  // name (key). See httpguts.ValidHeaderName for the base rules.
   196  //
   197  // Further, http2 says:
   198  //
   199  //	"Just as in HTTP/1.x, header field names are strings of ASCII
   200  //	characters that are compared in a case-insensitive
   201  //	fashion. However, header field names MUST be converted to
   202  //	lowercase prior to their encoding in HTTP/2. "
   203  func validWireHeaderFieldName(v string) bool {
   204  	if len(v) == 0 {
   205  		return false
   206  	}
   207  	for _, r := range v {
   208  		if !httpguts.IsTokenRune(r) {
   209  			return false
   210  		}
   211  		if 'A' <= r && r <= 'Z' {
   212  			return false
   213  		}
   214  	}
   215  	return true
   216  }
   217  
   218  func httpCodeString(code int) string {
   219  	switch code {
   220  	case 200:
   221  		return "200"
   222  	case 404:
   223  		return "404"
   224  	}
   225  	return strconv.Itoa(code)
   226  }
   227  
   228  // A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed).
   229  type closeWaiter chan struct{}
   230  
   231  // Init makes a closeWaiter usable.
   232  // It exists because so a closeWaiter value can be placed inside a
   233  // larger struct and have the Mutex and Cond's memory in the same
   234  // allocation.
   235  func (cw *closeWaiter) Init() {
   236  	*cw = make(chan struct{})
   237  }
   238  
   239  // Close marks the closeWaiter as closed and unblocks any waiters.
   240  func (cw closeWaiter) Close() {
   241  	close(cw)
   242  }
   243  
   244  // Wait waits for the closeWaiter to become closed.
   245  func (cw closeWaiter) Wait() {
   246  	<-cw
   247  }
   248  
   249  // bufferedWriter is a buffered writer that writes to w.
   250  // Its buffered writer is lazily allocated as needed, to minimize
   251  // idle memory usage with many connections.
   252  type bufferedWriter struct {
   253  	_           incomparable
   254  	conn        net.Conn      // immutable
   255  	bw          *bufio.Writer // non-nil when data is buffered
   256  	byteTimeout time.Duration // immutable, WriteByteTimeout
   257  	werr        error
   258  }
   259  
   260  func newBufferedWriter(conn net.Conn, timeout time.Duration) *bufferedWriter {
   261  	return &bufferedWriter{
   262  		conn:        conn,
   263  		byteTimeout: timeout,
   264  	}
   265  }
   266  
   267  // bufWriterPoolBufferSize is the size of bufio.Writer's
   268  // buffers created using bufWriterPool.
   269  //
   270  // TODO: pick a less arbitrary value? this is a bit under
   271  // (3 x typical 1500 byte MTU) at least. Other than that,
   272  // not much thought went into it.
   273  const bufWriterPoolBufferSize = 4 << 10
   274  
   275  var bufWriterPool = sync.Pool{
   276  	New: func() interface{} {
   277  		return bufio.NewWriterSize(nil, bufWriterPoolBufferSize)
   278  	},
   279  }
   280  
   281  func (w *bufferedWriter) Available() int {
   282  	if w.bw == nil {
   283  		return bufWriterPoolBufferSize
   284  	}
   285  	return w.bw.Available()
   286  }
   287  
   288  func (w *bufferedWriter) Write(p []byte) (n int, err error) {
   289  	if w.werr != nil {
   290  		return 0, w.werr
   291  	}
   292  	if w.bw == nil {
   293  		bw := bufWriterPool.Get().(*bufio.Writer)
   294  		bw.Reset((*bufferedWriterTimeoutWriter)(w))
   295  		w.bw = bw
   296  	}
   297  	n, w.werr = w.bw.Write(p)
   298  	return n, w.werr
   299  }
   300  
   301  func (w *bufferedWriter) Flush() error {
   302  	bw := w.bw
   303  	if bw == nil {
   304  		return nil
   305  	}
   306  	if w.werr != nil {
   307  		return w.werr
   308  	}
   309  	w.werr = bw.Flush()
   310  	bw.Reset(nil)
   311  	bufWriterPool.Put(bw)
   312  	w.bw = nil
   313  	return w.werr
   314  }
   315  
   316  type bufferedWriterTimeoutWriter bufferedWriter
   317  
   318  func (w *bufferedWriterTimeoutWriter) Write(p []byte) (n int, err error) {
   319  	return writeWithByteTimeout(w.conn, w.byteTimeout, p)
   320  }
   321  
   322  // writeWithByteTimeout writes to conn.
   323  // If more than timeout passes without any bytes being written to the connection,
   324  // the write fails.
   325  func writeWithByteTimeout(conn net.Conn, timeout time.Duration, p []byte) (n int, err error) {
   326  	if timeout <= 0 {
   327  		return conn.Write(p)
   328  	}
   329  	for {
   330  		conn.SetWriteDeadline(time.Now().Add(timeout))
   331  		nn, err := conn.Write(p[n:])
   332  		n += nn
   333  		if n == len(p) || nn == 0 || !errors.Is(err, os.ErrDeadlineExceeded) {
   334  			// Either we finished the write, made no progress, or hit the deadline.
   335  			// Whichever it is, we're done now.
   336  			conn.SetWriteDeadline(time.Time{})
   337  			return n, err
   338  		}
   339  	}
   340  }
   341  
   342  func mustUint31(v int32) uint32 {
   343  	if v < 0 || v > 2147483647 {
   344  		panic("out of range")
   345  	}
   346  	return uint32(v)
   347  }
   348  
   349  // bodyAllowedForStatus reports whether a given response status code
   350  // permits a body. See RFC 7230, section 3.3.
   351  func bodyAllowedForStatus(status int) bool {
   352  	switch {
   353  	case status >= 100 && status <= 199:
   354  		return false
   355  	case status == 204:
   356  		return false
   357  	case status == 304:
   358  		return false
   359  	}
   360  	return true
   361  }
   362  
   363  type httpError struct {
   364  	_       incomparable
   365  	msg     string
   366  	timeout bool
   367  }
   368  
   369  func (e *httpError) Error() string   { return e.msg }
   370  func (e *httpError) Timeout() bool   { return e.timeout }
   371  func (e *httpError) Temporary() bool { return true }
   372  
   373  var errTimeout error = &httpError{msg: "http2: timeout awaiting response headers", timeout: true}
   374  
   375  type connectionStater interface {
   376  	ConnectionState() tls.ConnectionState
   377  }
   378  
   379  var sorterPool = sync.Pool{New: func() interface{} { return new(sorter) }}
   380  
   381  type sorter struct {
   382  	v []string // owned by sorter
   383  }
   384  
   385  func (s *sorter) Len() int           { return len(s.v) }
   386  func (s *sorter) Swap(i, j int)      { s.v[i], s.v[j] = s.v[j], s.v[i] }
   387  func (s *sorter) Less(i, j int) bool { return s.v[i] < s.v[j] }
   388  
   389  // Keys returns the sorted keys of h.
   390  //
   391  // The returned slice is only valid until s used again or returned to
   392  // its pool.
   393  func (s *sorter) Keys(h Header) []string {
   394  	keys := s.v[:0]
   395  	for k := range h {
   396  		keys = append(keys, k)
   397  	}
   398  	s.v = keys
   399  	sort.Sort(s)
   400  	return keys
   401  }
   402  
   403  func (s *sorter) SortStrings(ss []string) {
   404  	// Our sorter works on s.v, which sorter owns, so
   405  	// stash it away while we sort the user's buffer.
   406  	save := s.v
   407  	s.v = ss
   408  	sort.Sort(s)
   409  	s.v = save
   410  }
   411  
   412  // incomparable is a zero-width, non-comparable type. Adding it to a struct
   413  // makes that struct also non-comparable, and generally doesn't add
   414  // any size (as long as it's first).
   415  type incomparable [0]func()
   416  

View as plain text