github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/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  package http2
    17  
    18  import (
    19  	"bufio"
    20  	"fmt"
    21  	"io"
    22  	"net/http"
    23  	"os"
    24  	"strconv"
    25  	"strings"
    26  	"sync"
    27  )
    28  
    29  var VerboseLogs = strings.Contains(os.Getenv("GODEBUG"), "h2debug=1")
    30  
    31  const (
    32  	// ClientPreface is the string that must be sent by new
    33  	// connections from clients.
    34  	ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
    35  
    36  	// SETTINGS_MAX_FRAME_SIZE default
    37  	// http://http2.github.io/http2-spec/#rfc.section.6.5.2
    38  	initialMaxFrameSize = 16384
    39  
    40  	// NextProtoTLS is the NPN/ALPN protocol negotiated during
    41  	// HTTP/2's TLS setup.
    42  	NextProtoTLS = "h2"
    43  
    44  	// http://http2.github.io/http2-spec/#SettingValues
    45  	initialHeaderTableSize = 4096
    46  
    47  	initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size
    48  
    49  	defaultMaxReadFrameSize = 1 << 20
    50  )
    51  
    52  var (
    53  	clientPreface = []byte(ClientPreface)
    54  )
    55  
    56  type streamState int
    57  
    58  const (
    59  	stateIdle streamState = iota
    60  	stateOpen
    61  	stateHalfClosedLocal
    62  	stateHalfClosedRemote
    63  	stateResvLocal
    64  	stateResvRemote
    65  	stateClosed
    66  )
    67  
    68  var stateName = [...]string{
    69  	stateIdle:             "Idle",
    70  	stateOpen:             "Open",
    71  	stateHalfClosedLocal:  "HalfClosedLocal",
    72  	stateHalfClosedRemote: "HalfClosedRemote",
    73  	stateResvLocal:        "ResvLocal",
    74  	stateResvRemote:       "ResvRemote",
    75  	stateClosed:           "Closed",
    76  }
    77  
    78  func (st streamState) String() string {
    79  	return stateName[st]
    80  }
    81  
    82  // Setting is a setting parameter: which setting it is, and its value.
    83  type Setting struct {
    84  	// ID is which setting is being set.
    85  	// See http://http2.github.io/http2-spec/#SettingValues
    86  	ID SettingID
    87  
    88  	// Val is the value.
    89  	Val uint32
    90  }
    91  
    92  func (s Setting) String() string {
    93  	return fmt.Sprintf("[%v = %d]", s.ID, s.Val)
    94  }
    95  
    96  // Valid reports whether the setting is valid.
    97  func (s Setting) Valid() error {
    98  	// Limits and error codes from 6.5.2 Defined SETTINGS Parameters
    99  	switch s.ID {
   100  	case SettingEnablePush:
   101  		if s.Val != 1 && s.Val != 0 {
   102  			return ConnectionError(ErrCodeProtocol)
   103  		}
   104  	case SettingInitialWindowSize:
   105  		if s.Val > 1<<31-1 {
   106  			return ConnectionError(ErrCodeFlowControl)
   107  		}
   108  	case SettingMaxFrameSize:
   109  		if s.Val < 16384 || s.Val > 1<<24-1 {
   110  			return ConnectionError(ErrCodeProtocol)
   111  		}
   112  	}
   113  	return nil
   114  }
   115  
   116  // A SettingID is an HTTP/2 setting as defined in
   117  // http://http2.github.io/http2-spec/#iana-settings
   118  type SettingID uint16
   119  
   120  const (
   121  	SettingHeaderTableSize      SettingID = 0x1
   122  	SettingEnablePush           SettingID = 0x2
   123  	SettingMaxConcurrentStreams SettingID = 0x3
   124  	SettingInitialWindowSize    SettingID = 0x4
   125  	SettingMaxFrameSize         SettingID = 0x5
   126  	SettingMaxHeaderListSize    SettingID = 0x6
   127  )
   128  
   129  var settingName = map[SettingID]string{
   130  	SettingHeaderTableSize:      "HEADER_TABLE_SIZE",
   131  	SettingEnablePush:           "ENABLE_PUSH",
   132  	SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS",
   133  	SettingInitialWindowSize:    "INITIAL_WINDOW_SIZE",
   134  	SettingMaxFrameSize:         "MAX_FRAME_SIZE",
   135  	SettingMaxHeaderListSize:    "MAX_HEADER_LIST_SIZE",
   136  }
   137  
   138  func (s SettingID) String() string {
   139  	if v, ok := settingName[s]; ok {
   140  		return v
   141  	}
   142  	return fmt.Sprintf("UNKNOWN_SETTING_%d", uint16(s))
   143  }
   144  
   145  func validHeader(v string) bool {
   146  	if len(v) == 0 {
   147  		return false
   148  	}
   149  	for _, r := range v {
   150  		// "Just as in HTTP/1.x, header field names are
   151  		// strings of ASCII characters that are compared in a
   152  		// case-insensitive fashion. However, header field
   153  		// names MUST be converted to lowercase prior to their
   154  		// encoding in HTTP/2. "
   155  		if r >= 127 || ('A' <= r && r <= 'Z') {
   156  			return false
   157  		}
   158  	}
   159  	return true
   160  }
   161  
   162  var httpCodeStringCommon = map[int]string{} // n -> strconv.Itoa(n)
   163  
   164  func init() {
   165  	for i := 100; i <= 999; i++ {
   166  		if v := http.StatusText(i); v != "" {
   167  			httpCodeStringCommon[i] = strconv.Itoa(i)
   168  		}
   169  	}
   170  }
   171  
   172  func httpCodeString(code int) string {
   173  	if s, ok := httpCodeStringCommon[code]; ok {
   174  		return s
   175  	}
   176  	return strconv.Itoa(code)
   177  }
   178  
   179  // from pkg io
   180  type stringWriter interface {
   181  	WriteString(s string) (n int, err error)
   182  }
   183  
   184  // A gate lets two goroutines coordinate their activities.
   185  type gate chan struct{}
   186  
   187  func (g gate) Done() { g <- struct{}{} }
   188  func (g gate) Wait() { <-g }
   189  
   190  // A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed).
   191  type closeWaiter chan struct{}
   192  
   193  // Init makes a closeWaiter usable.
   194  // It exists because so a closeWaiter value can be placed inside a
   195  // larger struct and have the Mutex and Cond's memory in the same
   196  // allocation.
   197  func (cw *closeWaiter) Init() {
   198  	*cw = make(chan struct{})
   199  }
   200  
   201  // Close marks the closeWaiter as closed and unblocks any waiters.
   202  func (cw closeWaiter) Close() {
   203  	close(cw)
   204  }
   205  
   206  // Wait waits for the closeWaiter to become closed.
   207  func (cw closeWaiter) Wait() {
   208  	<-cw
   209  }
   210  
   211  // bufferedWriter is a buffered writer that writes to w.
   212  // Its buffered writer is lazily allocated as needed, to minimize
   213  // idle memory usage with many connections.
   214  type bufferedWriter struct {
   215  	w  io.Writer     // immutable
   216  	bw *bufio.Writer // non-nil when data is buffered
   217  }
   218  
   219  func newBufferedWriter(w io.Writer) *bufferedWriter {
   220  	return &bufferedWriter{w: w}
   221  }
   222  
   223  var bufWriterPool = sync.Pool{
   224  	New: func() interface{} {
   225  		// TODO: pick something better? this is a bit under
   226  		// (3 x typical 1500 byte MTU) at least.
   227  		return bufio.NewWriterSize(nil, 4<<10)
   228  	},
   229  }
   230  
   231  func (w *bufferedWriter) Write(p []byte) (n int, err error) {
   232  	if w.bw == nil {
   233  		bw := bufWriterPool.Get().(*bufio.Writer)
   234  		bw.Reset(w.w)
   235  		w.bw = bw
   236  	}
   237  	return w.bw.Write(p)
   238  }
   239  
   240  func (w *bufferedWriter) Flush() error {
   241  	bw := w.bw
   242  	if bw == nil {
   243  		return nil
   244  	}
   245  	err := bw.Flush()
   246  	bw.Reset(nil)
   247  	bufWriterPool.Put(bw)
   248  	w.bw = nil
   249  	return err
   250  }
   251  
   252  func mustUint31(v int32) uint32 {
   253  	if v < 0 || v > 2147483647 {
   254  		panic("out of range")
   255  	}
   256  	return uint32(v)
   257  }
   258  
   259  // bodyAllowedForStatus reports whether a given response status code
   260  // permits a body. See RFC2616, section 4.4.
   261  func bodyAllowedForStatus(status int) bool {
   262  	switch {
   263  	case status >= 100 && status <= 199:
   264  		return false
   265  	case status == 204:
   266  		return false
   267  	case status == 304:
   268  		return false
   269  	}
   270  	return true
   271  }