github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/net/http2/http2.go (about)

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