forked from ebhomengo/niki
1
0
Fork 0
niki/vendor/golang.org/x/net/http2/http2.go

632 lines
9.6 KiB
Go
Raw Normal View History

2024-02-18 10:42:21 +00:00
// Copyright 2014 The Go Authors. All rights reserved.
2024-02-18 10:42:21 +00:00
// Use of this source code is governed by a BSD-style
2024-02-18 10:42:21 +00:00
// license that can be found in the LICENSE file.
// Package http2 implements the HTTP/2 protocol.
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// This package is low-level and intended to be used directly by very
2024-02-18 10:42:21 +00:00
// few people. Most users will use it indirectly through the automatic
2024-02-18 10:42:21 +00:00
// use by the net/http package (from Go 1.6 and later).
2024-02-18 10:42:21 +00:00
// For use in earlier Go versions see ConfigureServer. (Transport support
2024-02-18 10:42:21 +00:00
// requires Go 1.6 or later)
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// See https://http2.github.io/ for more information on HTTP/2.
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// See https://http2.golang.org/ for a test server running this code.
2024-02-18 10:42:21 +00:00
package http2 // import "golang.org/x/net/http2"
import (
"bufio"
"crypto/tls"
"fmt"
"io"
"net/http"
"os"
"sort"
"strconv"
"strings"
"sync"
"golang.org/x/net/http/httpguts"
)
var (
VerboseLogs bool
2024-02-18 10:42:21 +00:00
logFrameWrites bool
logFrameReads bool
inTests bool
2024-02-18 10:42:21 +00:00
)
func init() {
2024-02-18 10:42:21 +00:00
e := os.Getenv("GODEBUG")
2024-02-18 10:42:21 +00:00
if strings.Contains(e, "http2debug=1") {
2024-02-18 10:42:21 +00:00
VerboseLogs = true
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
if strings.Contains(e, "http2debug=2") {
2024-02-18 10:42:21 +00:00
VerboseLogs = true
2024-02-18 10:42:21 +00:00
logFrameWrites = true
2024-02-18 10:42:21 +00:00
logFrameReads = true
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
}
const (
2024-02-18 10:42:21 +00:00
// ClientPreface is the string that must be sent by new
2024-02-18 10:42:21 +00:00
// connections from clients.
2024-02-18 10:42:21 +00:00
ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
// SETTINGS_MAX_FRAME_SIZE default
2024-02-18 10:42:21 +00:00
// https://httpwg.org/specs/rfc7540.html#rfc.section.6.5.2
2024-02-18 10:42:21 +00:00
initialMaxFrameSize = 16384
// NextProtoTLS is the NPN/ALPN protocol negotiated during
2024-02-18 10:42:21 +00:00
// HTTP/2's TLS setup.
2024-02-18 10:42:21 +00:00
NextProtoTLS = "h2"
// https://httpwg.org/specs/rfc7540.html#SettingValues
2024-02-18 10:42:21 +00:00
initialHeaderTableSize = 4096
initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size
defaultMaxReadFrameSize = 1 << 20
)
var (
clientPreface = []byte(ClientPreface)
)
type streamState int
// HTTP/2 stream states.
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// See http://tools.ietf.org/html/rfc7540#section-5.1.
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// For simplicity, the server code merges "reserved (local)" into
2024-02-18 10:42:21 +00:00
// "half-closed (remote)". This is one less state transition to track.
2024-02-18 10:42:21 +00:00
// The only downside is that we send PUSH_PROMISEs slightly less
2024-02-18 10:42:21 +00:00
// liberally than allowable. More discussion here:
2024-02-18 10:42:21 +00:00
// https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0599.html
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// "reserved (remote)" is omitted since the client code does not
2024-02-18 10:42:21 +00:00
// support server push.
2024-02-18 10:42:21 +00:00
const (
stateIdle streamState = iota
2024-02-18 10:42:21 +00:00
stateOpen
2024-02-18 10:42:21 +00:00
stateHalfClosedLocal
2024-02-18 10:42:21 +00:00
stateHalfClosedRemote
2024-02-18 10:42:21 +00:00
stateClosed
)
var stateName = [...]string{
stateIdle: "Idle",
stateOpen: "Open",
stateHalfClosedLocal: "HalfClosedLocal",
2024-02-18 10:42:21 +00:00
stateHalfClosedRemote: "HalfClosedRemote",
stateClosed: "Closed",
2024-02-18 10:42:21 +00:00
}
func (st streamState) String() string {
2024-02-18 10:42:21 +00:00
return stateName[st]
2024-02-18 10:42:21 +00:00
}
// Setting is a setting parameter: which setting it is, and its value.
2024-02-18 10:42:21 +00:00
type Setting struct {
2024-02-18 10:42:21 +00:00
// ID is which setting is being set.
2024-02-18 10:42:21 +00:00
// See https://httpwg.org/specs/rfc7540.html#SettingFormat
2024-02-18 10:42:21 +00:00
ID SettingID
// Val is the value.
2024-02-18 10:42:21 +00:00
Val uint32
}
func (s Setting) String() string {
2024-02-18 10:42:21 +00:00
return fmt.Sprintf("[%v = %d]", s.ID, s.Val)
2024-02-18 10:42:21 +00:00
}
// Valid reports whether the setting is valid.
2024-02-18 10:42:21 +00:00
func (s Setting) Valid() error {
2024-02-18 10:42:21 +00:00
// Limits and error codes from 6.5.2 Defined SETTINGS Parameters
2024-02-18 10:42:21 +00:00
switch s.ID {
2024-02-18 10:42:21 +00:00
case SettingEnablePush:
2024-02-18 10:42:21 +00:00
if s.Val != 1 && s.Val != 0 {
2024-02-18 10:42:21 +00:00
return ConnectionError(ErrCodeProtocol)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
case SettingInitialWindowSize:
2024-02-18 10:42:21 +00:00
if s.Val > 1<<31-1 {
2024-02-18 10:42:21 +00:00
return ConnectionError(ErrCodeFlowControl)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
case SettingMaxFrameSize:
2024-02-18 10:42:21 +00:00
if s.Val < 16384 || s.Val > 1<<24-1 {
2024-02-18 10:42:21 +00:00
return ConnectionError(ErrCodeProtocol)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return nil
2024-02-18 10:42:21 +00:00
}
// A SettingID is an HTTP/2 setting as defined in
2024-02-18 10:42:21 +00:00
// https://httpwg.org/specs/rfc7540.html#iana-settings
2024-02-18 10:42:21 +00:00
type SettingID uint16
const (
SettingHeaderTableSize SettingID = 0x1
SettingEnablePush SettingID = 0x2
2024-02-18 10:42:21 +00:00
SettingMaxConcurrentStreams SettingID = 0x3
SettingInitialWindowSize SettingID = 0x4
SettingMaxFrameSize SettingID = 0x5
SettingMaxHeaderListSize SettingID = 0x6
2024-02-18 10:42:21 +00:00
)
var settingName = map[SettingID]string{
SettingHeaderTableSize: "HEADER_TABLE_SIZE",
SettingEnablePush: "ENABLE_PUSH",
2024-02-18 10:42:21 +00:00
SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS",
SettingInitialWindowSize: "INITIAL_WINDOW_SIZE",
SettingMaxFrameSize: "MAX_FRAME_SIZE",
SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE",
2024-02-18 10:42:21 +00:00
}
func (s SettingID) String() string {
2024-02-18 10:42:21 +00:00
if v, ok := settingName[s]; ok {
2024-02-18 10:42:21 +00:00
return v
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return fmt.Sprintf("UNKNOWN_SETTING_%d", uint16(s))
2024-02-18 10:42:21 +00:00
}
// validWireHeaderFieldName reports whether v is a valid header field
2024-02-18 10:42:21 +00:00
// name (key). See httpguts.ValidHeaderName for the base rules.
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// Further, http2 says:
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// "Just as in HTTP/1.x, header field names are strings of ASCII
2024-02-18 10:42:21 +00:00
// characters that are compared in a case-insensitive
2024-02-18 10:42:21 +00:00
// fashion. However, header field names MUST be converted to
2024-02-18 10:42:21 +00:00
// lowercase prior to their encoding in HTTP/2. "
2024-02-18 10:42:21 +00:00
func validWireHeaderFieldName(v string) bool {
2024-02-18 10:42:21 +00:00
if len(v) == 0 {
2024-02-18 10:42:21 +00:00
return false
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
for _, r := range v {
2024-02-18 10:42:21 +00:00
if !httpguts.IsTokenRune(r) {
2024-02-18 10:42:21 +00:00
return false
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
if 'A' <= r && r <= 'Z' {
2024-02-18 10:42:21 +00:00
return false
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return true
2024-02-18 10:42:21 +00:00
}
func httpCodeString(code int) string {
2024-02-18 10:42:21 +00:00
switch code {
2024-02-18 10:42:21 +00:00
case 200:
2024-02-18 10:42:21 +00:00
return "200"
2024-02-18 10:42:21 +00:00
case 404:
2024-02-18 10:42:21 +00:00
return "404"
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return strconv.Itoa(code)
2024-02-18 10:42:21 +00:00
}
// from pkg io
2024-02-18 10:42:21 +00:00
type stringWriter interface {
WriteString(s string) (n int, err error)
}
// A gate lets two goroutines coordinate their activities.
2024-02-18 10:42:21 +00:00
type gate chan struct{}
func (g gate) Done() { g <- struct{}{} }
2024-02-18 10:42:21 +00:00
func (g gate) Wait() { <-g }
// A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed).
2024-02-18 10:42:21 +00:00
type closeWaiter chan struct{}
// Init makes a closeWaiter usable.
2024-02-18 10:42:21 +00:00
// It exists because so a closeWaiter value can be placed inside a
2024-02-18 10:42:21 +00:00
// larger struct and have the Mutex and Cond's memory in the same
2024-02-18 10:42:21 +00:00
// allocation.
2024-02-18 10:42:21 +00:00
func (cw *closeWaiter) Init() {
2024-02-18 10:42:21 +00:00
*cw = make(chan struct{})
2024-02-18 10:42:21 +00:00
}
// Close marks the closeWaiter as closed and unblocks any waiters.
2024-02-18 10:42:21 +00:00
func (cw closeWaiter) Close() {
2024-02-18 10:42:21 +00:00
close(cw)
2024-02-18 10:42:21 +00:00
}
// Wait waits for the closeWaiter to become closed.
2024-02-18 10:42:21 +00:00
func (cw closeWaiter) Wait() {
2024-02-18 10:42:21 +00:00
<-cw
2024-02-18 10:42:21 +00:00
}
// bufferedWriter is a buffered writer that writes to w.
2024-02-18 10:42:21 +00:00
// Its buffered writer is lazily allocated as needed, to minimize
2024-02-18 10:42:21 +00:00
// idle memory usage with many connections.
2024-02-18 10:42:21 +00:00
type bufferedWriter struct {
_ incomparable
w io.Writer // immutable
2024-02-18 10:42:21 +00:00
bw *bufio.Writer // non-nil when data is buffered
2024-02-18 10:42:21 +00:00
}
func newBufferedWriter(w io.Writer) *bufferedWriter {
2024-02-18 10:42:21 +00:00
return &bufferedWriter{w: w}
2024-02-18 10:42:21 +00:00
}
// bufWriterPoolBufferSize is the size of bufio.Writer's
2024-02-18 10:42:21 +00:00
// buffers created using bufWriterPool.
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// TODO: pick a less arbitrary value? this is a bit under
2024-02-18 10:42:21 +00:00
// (3 x typical 1500 byte MTU) at least. Other than that,
2024-02-18 10:42:21 +00:00
// not much thought went into it.
2024-02-18 10:42:21 +00:00
const bufWriterPoolBufferSize = 4 << 10
var bufWriterPool = sync.Pool{
2024-02-18 10:42:21 +00:00
New: func() interface{} {
2024-02-18 10:42:21 +00:00
return bufio.NewWriterSize(nil, bufWriterPoolBufferSize)
2024-02-18 10:42:21 +00:00
},
}
func (w *bufferedWriter) Available() int {
2024-02-18 10:42:21 +00:00
if w.bw == nil {
2024-02-18 10:42:21 +00:00
return bufWriterPoolBufferSize
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return w.bw.Available()
2024-02-18 10:42:21 +00:00
}
func (w *bufferedWriter) Write(p []byte) (n int, err error) {
2024-02-18 10:42:21 +00:00
if w.bw == nil {
2024-02-18 10:42:21 +00:00
bw := bufWriterPool.Get().(*bufio.Writer)
2024-02-18 10:42:21 +00:00
bw.Reset(w.w)
2024-02-18 10:42:21 +00:00
w.bw = bw
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return w.bw.Write(p)
2024-02-18 10:42:21 +00:00
}
func (w *bufferedWriter) Flush() error {
2024-02-18 10:42:21 +00:00
bw := w.bw
2024-02-18 10:42:21 +00:00
if bw == nil {
2024-02-18 10:42:21 +00:00
return nil
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
err := bw.Flush()
2024-02-18 10:42:21 +00:00
bw.Reset(nil)
2024-02-18 10:42:21 +00:00
bufWriterPool.Put(bw)
2024-02-18 10:42:21 +00:00
w.bw = nil
2024-02-18 10:42:21 +00:00
return err
2024-02-18 10:42:21 +00:00
}
func mustUint31(v int32) uint32 {
2024-02-18 10:42:21 +00:00
if v < 0 || v > 2147483647 {
2024-02-18 10:42:21 +00:00
panic("out of range")
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return uint32(v)
2024-02-18 10:42:21 +00:00
}
// bodyAllowedForStatus reports whether a given response status code
2024-02-18 10:42:21 +00:00
// permits a body. See RFC 7230, section 3.3.
2024-02-18 10:42:21 +00:00
func bodyAllowedForStatus(status int) bool {
2024-02-18 10:42:21 +00:00
switch {
2024-02-18 10:42:21 +00:00
case status >= 100 && status <= 199:
2024-02-18 10:42:21 +00:00
return false
2024-02-18 10:42:21 +00:00
case status == 204:
2024-02-18 10:42:21 +00:00
return false
2024-02-18 10:42:21 +00:00
case status == 304:
2024-02-18 10:42:21 +00:00
return false
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return true
2024-02-18 10:42:21 +00:00
}
type httpError struct {
_ incomparable
msg string
2024-02-18 10:42:21 +00:00
timeout bool
}
func (e *httpError) Error() string { return e.msg }
func (e *httpError) Timeout() bool { return e.timeout }
2024-02-18 10:42:21 +00:00
func (e *httpError) Temporary() bool { return true }
var errTimeout error = &httpError{msg: "http2: timeout awaiting response headers", timeout: true}
type connectionStater interface {
ConnectionState() tls.ConnectionState
}
var sorterPool = sync.Pool{New: func() interface{} { return new(sorter) }}
type sorter struct {
v []string // owned by sorter
2024-02-18 10:42:21 +00:00
}
func (s *sorter) Len() int { return len(s.v) }
func (s *sorter) Swap(i, j int) { s.v[i], s.v[j] = s.v[j], s.v[i] }
2024-02-18 10:42:21 +00:00
func (s *sorter) Less(i, j int) bool { return s.v[i] < s.v[j] }
// Keys returns the sorted keys of h.
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// The returned slice is only valid until s used again or returned to
2024-02-18 10:42:21 +00:00
// its pool.
2024-02-18 10:42:21 +00:00
func (s *sorter) Keys(h http.Header) []string {
2024-02-18 10:42:21 +00:00
keys := s.v[:0]
2024-02-18 10:42:21 +00:00
for k := range h {
2024-02-18 10:42:21 +00:00
keys = append(keys, k)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
s.v = keys
2024-02-18 10:42:21 +00:00
sort.Sort(s)
2024-02-18 10:42:21 +00:00
return keys
2024-02-18 10:42:21 +00:00
}
func (s *sorter) SortStrings(ss []string) {
2024-02-18 10:42:21 +00:00
// Our sorter works on s.v, which sorter owns, so
2024-02-18 10:42:21 +00:00
// stash it away while we sort the user's buffer.
2024-02-18 10:42:21 +00:00
save := s.v
2024-02-18 10:42:21 +00:00
s.v = ss
2024-02-18 10:42:21 +00:00
sort.Sort(s)
2024-02-18 10:42:21 +00:00
s.v = save
2024-02-18 10:42:21 +00:00
}
// validPseudoPath reports whether v is a valid :path pseudo-header
2024-02-18 10:42:21 +00:00
// value. It must be either:
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// - a non-empty string starting with '/'
2024-02-18 10:42:21 +00:00
// - the string '*', for OPTIONS requests.
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// For now this is only used a quick check for deciding when to clean
2024-02-18 10:42:21 +00:00
// up Opaque URLs before sending requests from the Transport.
2024-02-18 10:42:21 +00:00
// See golang.org/issue/16847
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// We used to enforce that the path also didn't start with "//", but
2024-02-18 10:42:21 +00:00
// Google's GFE accepts such paths and Chrome sends them, so ignore
2024-02-18 10:42:21 +00:00
// that part of the spec. See golang.org/issue/19103.
2024-02-18 10:42:21 +00:00
func validPseudoPath(v string) bool {
2024-02-18 10:42:21 +00:00
return (len(v) > 0 && v[0] == '/') || v == "*"
2024-02-18 10:42:21 +00:00
}
// incomparable is a zero-width, non-comparable type. Adding it to a struct
2024-02-18 10:42:21 +00:00
// makes that struct also non-comparable, and generally doesn't add
2024-02-18 10:42:21 +00:00
// any size (as long as it's first).
2024-02-18 10:42:21 +00:00
type incomparable [0]func()