...

Source file src/golang.org/x/net/http2/http2.go

Documentation: golang.org/x/net/http2

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

View as plain text