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