http2.go raw

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