// Copyright 2015 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.

// Transport code.

package http2

import (
	
	
	
	
	
	
	
	
	
	
	
	
	
	mathrand 
	
	
	
	
	
	
	
	
	

	
	
	
	
)

const (
	// transportDefaultConnFlow is how many connection-level flow control
	// tokens we give the server at start-up, past the default 64k.
	transportDefaultConnFlow = 1 << 30

	// transportDefaultStreamFlow is how many stream-level flow
	// control tokens we announce to the peer, and how many bytes
	// we buffer per stream.
	transportDefaultStreamFlow = 4 << 20

	defaultUserAgent = "Go-http-client/2.0"

	// initialMaxConcurrentStreams is a connections maxConcurrentStreams until
	// it's received servers initial SETTINGS frame, which corresponds with the
	// spec's minimum recommended value.
	initialMaxConcurrentStreams = 100

	// defaultMaxConcurrentStreams is a connections default maxConcurrentStreams
	// if the server doesn't include one in its initial SETTINGS frame.
	defaultMaxConcurrentStreams = 1000
)

// Transport is an HTTP/2 Transport.
//
// A Transport internally caches connections to servers. It is safe
// for concurrent use by multiple goroutines.
type Transport struct {
	// DialTLSContext specifies an optional dial function with context for
	// creating TLS connections for requests.
	//
	// If DialTLSContext and DialTLS is nil, tls.Dial is used.
	//
	// If the returned net.Conn has a ConnectionState method like tls.Conn,
	// it will be used to set http.Response.TLS.
	DialTLSContext func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error)

	// DialTLS specifies an optional dial function for creating
	// TLS connections for requests.
	//
	// If DialTLSContext and DialTLS is nil, tls.Dial is used.
	//
	// Deprecated: Use DialTLSContext instead, which allows the transport
	// to cancel dials as soon as they are no longer needed.
	// If both are set, DialTLSContext takes priority.
	DialTLS func(network, addr string, cfg *tls.Config) (net.Conn, error)

	// TLSClientConfig specifies the TLS configuration to use with
	// tls.Client. If nil, the default configuration is used.
	TLSClientConfig *tls.Config

	// ConnPool optionally specifies an alternate connection pool to use.
	// If nil, the default is used.
	ConnPool ClientConnPool

	// DisableCompression, if true, prevents the Transport from
	// requesting compression with an "Accept-Encoding: gzip"
	// request header when the Request contains no existing
	// Accept-Encoding value. If the Transport requests gzip on
	// its own and gets a gzipped response, it's transparently
	// decoded in the Response.Body. However, if the user
	// explicitly requested gzip it is not automatically
	// uncompressed.
	DisableCompression bool

	// AllowHTTP, if true, permits HTTP/2 requests using the insecure,
	// plain-text "http" scheme. Note that this does not enable h2c support.
	AllowHTTP bool

	// MaxHeaderListSize is the http2 SETTINGS_MAX_HEADER_LIST_SIZE to
	// send in the initial settings frame. It is how many bytes
	// of response headers are allowed. Unlike the http2 spec, zero here
	// means to use a default limit (currently 10MB). If you actually
	// want to advertise an unlimited value to the peer, Transport
	// interprets the highest possible value here (0xffffffff or 1<<32-1)
	// to mean no limit.
	MaxHeaderListSize uint32

	// MaxReadFrameSize is the http2 SETTINGS_MAX_FRAME_SIZE to send in the
	// initial settings frame. It is the size in bytes of the largest frame
	// payload that the sender is willing to receive. If 0, no setting is
	// sent, and the value is provided by the peer, which should be 16384
	// according to the spec:
	// https://datatracker.ietf.org/doc/html/rfc7540#section-6.5.2.
	// Values are bounded in the range 16k to 16M.
	MaxReadFrameSize uint32

	// MaxDecoderHeaderTableSize optionally specifies the http2
	// SETTINGS_HEADER_TABLE_SIZE to send in the initial settings frame. It
	// informs the remote endpoint of the maximum size of the header compression
	// table used to decode header blocks, in octets. If zero, the default value
	// of 4096 is used.
	MaxDecoderHeaderTableSize uint32

	// MaxEncoderHeaderTableSize optionally specifies an upper limit for the
	// header compression table used for encoding request headers. Received
	// SETTINGS_HEADER_TABLE_SIZE settings are capped at this limit. If zero,
	// the default value of 4096 is used.
	MaxEncoderHeaderTableSize uint32

	// StrictMaxConcurrentStreams controls whether the server's
	// SETTINGS_MAX_CONCURRENT_STREAMS should be respected
	// globally. If false, new TCP connections are created to the
	// server as needed to keep each under the per-connection
	// SETTINGS_MAX_CONCURRENT_STREAMS limit. If true, the
	// server's SETTINGS_MAX_CONCURRENT_STREAMS is interpreted as
	// a global limit and callers of RoundTrip block when needed,
	// waiting for their turn.
	StrictMaxConcurrentStreams bool

	// IdleConnTimeout is the maximum amount of time an idle
	// (keep-alive) connection will remain idle before closing
	// itself.
	// Zero means no limit.
	IdleConnTimeout time.Duration

	// ReadIdleTimeout is the timeout after which a health check using ping
	// frame will be carried out if no frame is received on the connection.
	// Note that a ping response will is considered a received frame, so if
	// there is no other traffic on the connection, the health check will
	// be performed every ReadIdleTimeout interval.
	// If zero, no health check is performed.
	ReadIdleTimeout time.Duration

	// PingTimeout is the timeout after which the connection will be closed
	// if a response to Ping is not received.
	// Defaults to 15s.
	PingTimeout time.Duration

	// WriteByteTimeout is the timeout after which the connection will be
	// closed no data can be written to it. The timeout begins when data is
	// available to write, and is extended whenever any bytes are written.
	WriteByteTimeout time.Duration

	// CountError, if non-nil, is called on HTTP/2 transport errors.
	// It's intended to increment a metric for monitoring, such
	// as an expvar or Prometheus metric.
	// The errType consists of only ASCII word characters.
	CountError func(errType string)

	// t1, if non-nil, is the standard library Transport using
	// this transport. Its settings are used (but not its
	// RoundTrip method, etc).
	t1 *http.Transport

	connPoolOnce  sync.Once
	connPoolOrDef ClientConnPool // non-nil version of ConnPool

	*transportTestHooks
}

// Hook points used for testing.
// Outside of tests, t.transportTestHooks is nil and these all have minimal implementations.
// Inside tests, see the testSyncHooks function docs.

type transportTestHooks struct {
	newclientconn func(*ClientConn)
	group         synctestGroupInterface
}

func ( *Transport) () {
	if  != nil && .transportTestHooks != nil {
		.transportTestHooks.group.Join()
	}
}

func ( *Transport) () time.Time {
	if  != nil && .transportTestHooks != nil {
		return .transportTestHooks.group.Now()
	}
	return time.Now()
}

func ( *Transport) ( time.Time) time.Duration {
	if  != nil && .transportTestHooks != nil {
		return .now().Sub()
	}
	return time.Since()
}

// newTimer creates a new time.Timer, or a synthetic timer in tests.
func ( *Transport) ( time.Duration) timer {
	if .transportTestHooks != nil {
		return .transportTestHooks.group.NewTimer()
	}
	return timeTimer{time.NewTimer()}
}

// afterFunc creates a new time.AfterFunc timer, or a synthetic timer in tests.
func ( *Transport) ( time.Duration,  func()) timer {
	if .transportTestHooks != nil {
		return .transportTestHooks.group.AfterFunc(, )
	}
	return timeTimer{time.AfterFunc(, )}
}

func ( *Transport) ( context.Context,  time.Duration) (context.Context, context.CancelFunc) {
	if .transportTestHooks != nil {
		return .transportTestHooks.group.ContextWithTimeout(, )
	}
	return context.WithTimeout(, )
}

func ( *Transport) () uint32 {
	 := int64(.MaxHeaderListSize)
	if .t1 != nil && .t1.MaxResponseHeaderBytes != 0 {
		 = .t1.MaxResponseHeaderBytes
		if  > 0 {
			 = adjustHTTP1MaxHeaderSize()
		}
	}
	if  <= 0 {
		return 10 << 20
	}
	if  >= 0xffffffff {
		return 0
	}
	return uint32()
}

func ( *Transport) () bool {
	return .DisableCompression || (.t1 != nil && .t1.DisableCompression)
}

// ConfigureTransport configures a net/http HTTP/1 Transport to use HTTP/2.
// It returns an error if t1 has already been HTTP/2-enabled.
//
// Use ConfigureTransports instead to configure the HTTP/2 Transport.
func ( *http.Transport) error {
	,  := ConfigureTransports()
	return 
}

// ConfigureTransports configures a net/http HTTP/1 Transport to use HTTP/2.
// It returns a new HTTP/2 Transport for further configuration.
// It returns an error if t1 has already been HTTP/2-enabled.
func ( *http.Transport) (*Transport, error) {
	return configureTransports()
}

func ( *http.Transport) (*Transport, error) {
	 := new(clientConnPool)
	 := &Transport{
		ConnPool: noDialClientConnPool{},
		t1:       ,
	}
	.t = 
	if  := registerHTTPSProtocol(, noDialH2RoundTripper{});  != nil {
		return nil, 
	}
	if .TLSClientConfig == nil {
		.TLSClientConfig = new(tls.Config)
	}
	if !strSliceContains(.TLSClientConfig.NextProtos, "h2") {
		.TLSClientConfig.NextProtos = append([]string{"h2"}, .TLSClientConfig.NextProtos...)
	}
	if !strSliceContains(.TLSClientConfig.NextProtos, "http/1.1") {
		.TLSClientConfig.NextProtos = append(.TLSClientConfig.NextProtos, "http/1.1")
	}
	 := func(,  string,  net.Conn) http.RoundTripper {
		 := authorityAddr(, )
		if ,  := .addConnIfNeeded(, , );  != nil {
			go .Close()
			return erringRoundTripper{}
		} else if ! {
			// Turns out we don't need this c.
			// For example, two goroutines made requests to the same host
			// at the same time, both kicking off TCP dials. (since protocol
			// was unknown)
			go .Close()
		}
		if  == "http" {
			return (*unencryptedTransport)()
		}
		return 
	}
	if .TLSNextProto == nil {
		.TLSNextProto = make(map[string]func(string, *tls.Conn) http.RoundTripper)
	}
	.TLSNextProto[NextProtoTLS] = func( string,  *tls.Conn) http.RoundTripper {
		return ("https", , )
	}
	// The "unencrypted_http2" TLSNextProto key is used to pass off non-TLS HTTP/2 conns.
	.TLSNextProto[nextProtoUnencryptedHTTP2] = func( string,  *tls.Conn) http.RoundTripper {
		,  := unencryptedNetConnFromTLSConn()
		if  != nil {
			go .Close()
			return erringRoundTripper{}
		}
		return ("http", , )
	}
	return , nil
}

// unencryptedTransport is a Transport with a RoundTrip method that
// always permits http:// URLs.
type unencryptedTransport Transport

func ( *unencryptedTransport) ( *http.Request) (*http.Response, error) {
	return (*Transport)().RoundTripOpt(, RoundTripOpt{allowHTTP: true})
}

func ( *Transport) () ClientConnPool {
	.connPoolOnce.Do(.initConnPool)
	return .connPoolOrDef
}

func ( *Transport) () {
	if .ConnPool != nil {
		.connPoolOrDef = .ConnPool
	} else {
		.connPoolOrDef = &clientConnPool{t: }
	}
}

// ClientConn is the state of a single HTTP/2 client connection to an
// HTTP/2 server.
type ClientConn struct {
	t             *Transport
	tconn         net.Conn             // usually *tls.Conn, except specialized impls
	tlsState      *tls.ConnectionState // nil only for specialized impls
	atomicReused  uint32               // whether conn is being reused; atomic
	singleUse     bool                 // whether being used for a single http.Request
	getConnCalled bool                 // used by clientConnPool

	// readLoop goroutine fields:
	readerDone chan struct{} // closed on error
	readerErr  error         // set before readerDone is closed

	idleTimeout time.Duration // or 0 for never
	idleTimer   timer

	mu               sync.Mutex // guards following
	cond             *sync.Cond // hold mu; broadcast on flow/closed changes
	flow             outflow    // our conn-level flow control quota (cs.outflow is per stream)
	inflow           inflow     // peer's conn-level flow control
	doNotReuse       bool       // whether conn is marked to not be reused for any future requests
	closing          bool
	closed           bool
	closedOnIdle     bool                     // true if conn was closed for idleness
	seenSettings     bool                     // true if we've seen a settings frame, false otherwise
	seenSettingsChan chan struct{}            // closed when seenSettings is true or frame reading fails
	wantSettingsAck  bool                     // we sent a SETTINGS frame and haven't heard back
	goAway           *GoAwayFrame             // if non-nil, the GoAwayFrame we received
	goAwayDebug      string                   // goAway frame's debug data, retained as a string
	streams          map[uint32]*clientStream // client-initiated
	streamsReserved  int                      // incr by ReserveNewRequest; decr on RoundTrip
	nextStreamID     uint32
	pendingRequests  int                       // requests blocked and waiting to be sent because len(streams) == maxConcurrentStreams
	pings            map[[8]byte]chan struct{} // in flight ping data to notification channel
	br               *bufio.Reader
	lastActive       time.Time
	lastIdle         time.Time // time last idle
	// Settings from peer: (also guarded by wmu)
	maxFrameSize                uint32
	maxConcurrentStreams        uint32
	peerMaxHeaderListSize       uint64
	peerMaxHeaderTableSize      uint32
	initialWindowSize           uint32
	initialStreamRecvWindowSize int32
	readIdleTimeout             time.Duration
	pingTimeout                 time.Duration
	extendedConnectAllowed      bool

	// rstStreamPingsBlocked works around an unfortunate gRPC behavior.
	// gRPC strictly limits the number of PING frames that it will receive.
	// The default is two pings per two hours, but the limit resets every time
	// the gRPC endpoint sends a HEADERS or DATA frame. See golang/go#70575.
	//
	// rstStreamPingsBlocked is set after receiving a response to a PING frame
	// bundled with an RST_STREAM (see pendingResets below), and cleared after
	// receiving a HEADERS or DATA frame.
	rstStreamPingsBlocked bool

	// pendingResets is the number of RST_STREAM frames we have sent to the peer,
	// without confirming that the peer has received them. When we send a RST_STREAM,
	// we bundle it with a PING frame, unless a PING is already in flight. We count
	// the reset stream against the connection's concurrency limit until we get
	// a PING response. This limits the number of requests we'll try to send to a
	// completely unresponsive connection.
	pendingResets int

	// reqHeaderMu is a 1-element semaphore channel controlling access to sending new requests.
	// Write to reqHeaderMu to lock it, read from it to unlock.
	// Lock reqmu BEFORE mu or wmu.
	reqHeaderMu chan struct{}

	// wmu is held while writing.
	// Acquire BEFORE mu when holding both, to avoid blocking mu on network writes.
	// Only acquire both at the same time when changing peer settings.
	wmu  sync.Mutex
	bw   *bufio.Writer
	fr   *Framer
	werr error        // first write error that has occurred
	hbuf bytes.Buffer // HPACK encoder writes into this
	henc *hpack.Encoder
}

// clientStream is the state for a single HTTP/2 stream. One of these
// is created for each Transport.RoundTrip call.
type clientStream struct {
	cc *ClientConn

	// Fields of Request that we may access even after the response body is closed.
	ctx       context.Context
	reqCancel <-chan struct{}

	trace         *httptrace.ClientTrace // or nil
	ID            uint32
	bufPipe       pipe // buffered pipe with the flow-controlled response payload
	requestedGzip bool
	isHead        bool

	abortOnce sync.Once
	abort     chan struct{} // closed to signal stream should end immediately
	abortErr  error         // set if abort is closed

	peerClosed chan struct{} // closed when the peer sends an END_STREAM flag
	donec      chan struct{} // closed after the stream is in the closed state
	on100      chan struct{} // buffered; written to if a 100 is received

	respHeaderRecv chan struct{}  // closed when headers are received
	res            *http.Response // set if respHeaderRecv is closed

	flow        outflow // guarded by cc.mu
	inflow      inflow  // guarded by cc.mu
	bytesRemain int64   // -1 means unknown; owned by transportResponseBody.Read
	readErr     error   // sticky read error; owned by transportResponseBody.Read

	reqBody              io.ReadCloser
	reqBodyContentLength int64         // -1 means unknown
	reqBodyClosed        chan struct{} // guarded by cc.mu; non-nil on Close, closed when done

	// owned by writeRequest:
	sentEndStream bool // sent an END_STREAM flag to the peer
	sentHeaders   bool

	// owned by clientConnReadLoop:
	firstByte       bool  // got the first response byte
	pastHeaders     bool  // got first MetaHeadersFrame (actual headers)
	pastTrailers    bool  // got optional second MetaHeadersFrame (trailers)
	readClosed      bool  // peer sent an END_STREAM flag
	readAborted     bool  // read loop reset the stream
	totalHeaderSize int64 // total size of 1xx headers seen

	trailer    http.Header  // accumulated trailers
	resTrailer *http.Header // client's Response.Trailer
}

var got1xxFuncForTests func(int, textproto.MIMEHeader) error

// get1xxTraceFunc returns the value of request's httptrace.ClientTrace.Got1xxResponse func,
// if any. It returns nil if not set or if the Go version is too old.
func ( *clientStream) () func(int, textproto.MIMEHeader) error {
	if  := got1xxFuncForTests;  != nil {
		return 
	}
	return traceGot1xxResponseFunc(.trace)
}

func ( *clientStream) ( error) {
	.cc.mu.Lock()
	defer .cc.mu.Unlock()
	.abortStreamLocked()
}

func ( *clientStream) ( error) {
	.abortOnce.Do(func() {
		.abortErr = 
		close(.abort)
	})
	if .reqBody != nil {
		.closeReqBodyLocked()
	}
	// TODO(dneil): Clean up tests where cs.cc.cond is nil.
	if .cc.cond != nil {
		// Wake up writeRequestBody if it is waiting on flow control.
		.cc.cond.Broadcast()
	}
}

func ( *clientStream) () {
	 := .cc
	.mu.Lock()
	defer .mu.Unlock()
	if .reqBody != nil && .reqBodyClosed == nil {
		.closeReqBodyLocked()
		.cond.Broadcast()
	}
}

func ( *clientStream) () {
	if .reqBodyClosed != nil {
		return
	}
	.reqBodyClosed = make(chan struct{})
	 := .reqBodyClosed
	go func() {
		.cc.t.markNewGoroutine()
		.reqBody.Close()
		close()
	}()
}

type stickyErrWriter struct {
	group   synctestGroupInterface
	conn    net.Conn
	timeout time.Duration
	err     *error
}

func ( stickyErrWriter) ( []byte) ( int,  error) {
	if *.err != nil {
		return 0, *.err
	}
	,  = writeWithByteTimeout(.group, .conn, .timeout, )
	*.err = 
	return , 
}

// noCachedConnError is the concrete type of ErrNoCachedConn, which
// needs to be detected by net/http regardless of whether it's its
// bundled version (in h2_bundle.go with a rewritten type name) or
// from a user's x/net/http2. As such, as it has a unique method name
// (IsHTTP2NoCachedConnError) that net/http sniffs for via func
// isNoCachedConnError.
type noCachedConnError struct{}

func (noCachedConnError) () {}
func (noCachedConnError) () string             { return "http2: no cached connection was available" }

// isNoCachedConnError reports whether err is of type noCachedConnError
// or its equivalent renamed type in net/http2's h2_bundle.go. Both types
// may coexist in the same running program.
func ( error) bool {
	,  := .(interface{ () })
	return 
}

var ErrNoCachedConn error = noCachedConnError{}

// RoundTripOpt are options for the Transport.RoundTripOpt method.
type RoundTripOpt struct {
	// OnlyCachedConn controls whether RoundTripOpt may
	// create a new TCP connection. If set true and
	// no cached connection is available, RoundTripOpt
	// will return ErrNoCachedConn.
	OnlyCachedConn bool

	allowHTTP bool // allow http:// URLs
}

func ( *Transport) ( *http.Request) (*http.Response, error) {
	return .RoundTripOpt(, RoundTripOpt{})
}

// authorityAddr returns a given authority (a host/IP, or host:port / ip:port)
// and returns a host:port. The port 443 is added if needed.
func ( string,  string) ( string) {
	, ,  := net.SplitHostPort()
	if  != nil { // authority didn't have a port
		 = 
		 = ""
	}
	if  == "" { // authority's port was empty
		 = "443"
		if  == "http" {
			 = "80"
		}
	}
	if ,  := idna.ToASCII();  == nil {
		 = 
	}
	// IPv6 address literal, without a port:
	if strings.HasPrefix(, "[") && strings.HasSuffix(, "]") {
		return  + ":" + 
	}
	return net.JoinHostPort(, )
}

// RoundTripOpt is like RoundTrip, but takes options.
func ( *Transport) ( *http.Request,  RoundTripOpt) (*http.Response, error) {
	switch .URL.Scheme {
	case "https":
		// Always okay.
	case "http":
		if !.AllowHTTP && !.allowHTTP {
			return nil, errors.New("http2: unencrypted HTTP/2 not enabled")
		}
	default:
		return nil, errors.New("http2: unsupported scheme")
	}

	 := authorityAddr(.URL.Scheme, .URL.Host)
	for  := 0; ; ++ {
		,  := .connPool().GetClientConn(, )
		if  != nil {
			.vlogf("http2: Transport failed to get client conn for %s: %v", , )
			return nil, 
		}
		 := !atomic.CompareAndSwapUint32(&.atomicReused, 0, 1)
		traceGotConn(, , )
		,  := .RoundTrip()
		if  != nil &&  <= 6 {
			 := 
			if ,  = shouldRetryRequest(, );  == nil {
				// After the first retry, do exponential backoff with 10% jitter.
				if  == 0 {
					.vlogf("RoundTrip retrying after failure: %v", )
					continue
				}
				 := float64(uint(1) << (uint() - 1))
				 +=  * (0.1 * mathrand.Float64())
				 := time.Second * time.Duration()
				 := .newTimer()
				select {
				case <-.C():
					.vlogf("RoundTrip retrying after failure: %v", )
					continue
				case <-.Context().Done():
					.Stop()
					 = .Context().Err()
				}
			}
		}
		if  == errClientConnNotEstablished {
			// This ClientConn was created recently,
			// this is the first request to use it,
			// and the connection is closed and not usable.
			//
			// In this state, cc.idleTimer will remove the conn from the pool
			// when it fires. Stop the timer and remove it here so future requests
			// won't try to use this connection.
			//
			// If the timer has already fired and we're racing it, the redundant
			// call to MarkDead is harmless.
			if .idleTimer != nil {
				.idleTimer.Stop()
			}
			.connPool().MarkDead()
		}
		if  != nil {
			.vlogf("RoundTrip failure: %v", )
			return nil, 
		}
		return , nil
	}
}

// CloseIdleConnections closes any connections which were previously
// connected from previous requests but are now sitting idle.
// It does not interrupt any connections currently in use.
func ( *Transport) () {
	if ,  := .connPool().(clientConnPoolIdleCloser);  {
		.closeIdleConnections()
	}
}

var (
	errClientConnClosed         = errors.New("http2: client conn is closed")
	errClientConnUnusable       = errors.New("http2: client conn not usable")
	errClientConnNotEstablished = errors.New("http2: client conn could not be established")
	errClientConnGotGoAway      = errors.New("http2: Transport received Server's graceful shutdown GOAWAY")
)

// shouldRetryRequest is called by RoundTrip when a request fails to get
// response headers. It is always called with a non-nil error.
// It returns either a request to retry (either the same request, or a
// modified clone), or an error if the request can't be replayed.
func ( *http.Request,  error) (*http.Request, error) {
	if !canRetryError() {
		return nil, 
	}
	// If the Body is nil (or http.NoBody), it's safe to reuse
	// this request and its Body.
	if .Body == nil || .Body == http.NoBody {
		return , nil
	}

	// If the request body can be reset back to its original
	// state via the optional req.GetBody, do that.
	if .GetBody != nil {
		,  := .GetBody()
		if  != nil {
			return nil, 
		}
		 := *
		.Body = 
		return &, nil
	}

	// The Request.Body can't reset back to the beginning, but we
	// don't seem to have started to read from it yet, so reuse
	// the request directly.
	if  == errClientConnUnusable {
		return , nil
	}

	return nil, fmt.Errorf("http2: Transport: cannot retry err [%v] after Request.Body was written; define Request.GetBody to avoid this error", )
}

func ( error) bool {
	if  == errClientConnUnusable ||  == errClientConnGotGoAway {
		return true
	}
	if ,  := .(StreamError);  {
		if .Code == ErrCodeProtocol && .Cause == errFromPeer {
			// See golang/go#47635, golang/go#42777
			return true
		}
		return .Code == ErrCodeRefusedStream
	}
	return false
}

func ( *Transport) ( context.Context,  string,  bool) (*ClientConn, error) {
	if .transportTestHooks != nil {
		return .newClientConn(nil, )
	}
	, ,  := net.SplitHostPort()
	if  != nil {
		return nil, 
	}
	,  := .dialTLS(, "tcp", , .newTLSConfig())
	if  != nil {
		return nil, 
	}
	return .newClientConn(, )
}

func ( *Transport) ( string) *tls.Config {
	 := new(tls.Config)
	if .TLSClientConfig != nil {
		* = *.TLSClientConfig.Clone()
	}
	if !strSliceContains(.NextProtos, NextProtoTLS) {
		.NextProtos = append([]string{NextProtoTLS}, .NextProtos...)
	}
	if .ServerName == "" {
		.ServerName = 
	}
	return 
}

func ( *Transport) ( context.Context, ,  string,  *tls.Config) (net.Conn, error) {
	if .DialTLSContext != nil {
		return .DialTLSContext(, , , )
	} else if .DialTLS != nil {
		return .DialTLS(, , )
	}

	,  := .dialTLSWithContext(, , , )
	if  != nil {
		return nil, 
	}
	 := .ConnectionState()
	if  := .NegotiatedProtocol;  != NextProtoTLS {
		return nil, fmt.Errorf("http2: unexpected ALPN protocol %q; want %q", , NextProtoTLS)
	}
	if !.NegotiatedProtocolIsMutual {
		return nil, errors.New("http2: could not negotiate protocol mutually")
	}
	return , nil
}

// disableKeepAlives reports whether connections should be closed as
// soon as possible after handling the first request.
func ( *Transport) () bool {
	return .t1 != nil && .t1.DisableKeepAlives
}

func ( *Transport) () time.Duration {
	if .t1 == nil {
		return 0
	}
	return .t1.ExpectContinueTimeout
}

func ( *Transport) ( net.Conn) (*ClientConn, error) {
	return .newClientConn(, .disableKeepAlives())
}

func ( *Transport) ( net.Conn,  bool) (*ClientConn, error) {
	 := configFromTransport()
	 := &ClientConn{
		t:                           ,
		tconn:                       ,
		readerDone:                  make(chan struct{}),
		nextStreamID:                1,
		maxFrameSize:                16 << 10, // spec default
		initialWindowSize:           65535,    // spec default
		initialStreamRecvWindowSize: .MaxUploadBufferPerStream,
		maxConcurrentStreams:        initialMaxConcurrentStreams, // "infinite", per spec. Use a smaller value until we have received server settings.
		peerMaxHeaderListSize:       0xffffffffffffffff,          // "infinite", per spec. Use 2^64-1 instead.
		streams:                     make(map[uint32]*clientStream),
		singleUse:                   ,
		seenSettingsChan:            make(chan struct{}),
		wantSettingsAck:             true,
		readIdleTimeout:             .SendPingTimeout,
		pingTimeout:                 .PingTimeout,
		pings:                       make(map[[8]byte]chan struct{}),
		reqHeaderMu:                 make(chan struct{}, 1),
		lastActive:                  .now(),
	}
	var  synctestGroupInterface
	if .transportTestHooks != nil {
		.markNewGoroutine()
		.transportTestHooks.newclientconn()
		 = .tconn
		 = .group
	}
	if VerboseLogs {
		.vlogf("http2: Transport creating client conn %p to %v", , .RemoteAddr())
	}

	.cond = sync.NewCond(&.mu)
	.flow.add(int32(initialWindowSize))

	// TODO: adjust this writer size to account for frame size +
	// MTU + crypto/tls record padding.
	.bw = bufio.NewWriter(stickyErrWriter{
		group:   ,
		conn:    ,
		timeout: .WriteByteTimeout,
		err:     &.werr,
	})
	.br = bufio.NewReader()
	.fr = NewFramer(.bw, .br)
	.fr.SetMaxReadFrameSize(.MaxReadFrameSize)
	if .CountError != nil {
		.fr.countError = .CountError
	}
	 := .MaxDecoderHeaderTableSize
	.fr.ReadMetaHeaders = hpack.NewDecoder(, nil)
	.fr.MaxHeaderListSize = .maxHeaderListSize()

	.henc = hpack.NewEncoder(&.hbuf)
	.henc.SetMaxDynamicTableSizeLimit(.MaxEncoderHeaderTableSize)
	.peerMaxHeaderTableSize = initialHeaderTableSize

	if ,  := .(connectionStater);  {
		 := .ConnectionState()
		.tlsState = &
	}

	 := []Setting{
		{ID: SettingEnablePush, Val: 0},
		{ID: SettingInitialWindowSize, Val: uint32(.initialStreamRecvWindowSize)},
	}
	 = append(, Setting{ID: SettingMaxFrameSize, Val: .MaxReadFrameSize})
	if  := .maxHeaderListSize();  != 0 {
		 = append(, Setting{ID: SettingMaxHeaderListSize, Val: })
	}
	if  != initialHeaderTableSize {
		 = append(, Setting{ID: SettingHeaderTableSize, Val: })
	}

	.bw.Write(clientPreface)
	.fr.WriteSettings(...)
	.fr.WriteWindowUpdate(0, uint32(.MaxUploadBufferPerConnection))
	.inflow.init(.MaxUploadBufferPerConnection + initialWindowSize)
	.bw.Flush()
	if .werr != nil {
		.Close()
		return nil, .werr
	}

	// Start the idle timer after the connection is fully initialized.
	if  := .idleConnTimeout();  != 0 {
		.idleTimeout = 
		.idleTimer = .afterFunc(, .onIdleTimeout)
	}

	go .readLoop()
	return , nil
}

func ( *ClientConn) () {
	 := .pingTimeout
	// We don't need to periodically ping in the health check, because the readLoop of ClientConn will
	// trigger the healthCheck again if there is no frame received.
	,  := .t.contextWithTimeout(context.Background(), )
	defer ()
	.vlogf("http2: Transport sending health check")
	 := .Ping()
	if  != nil {
		.vlogf("http2: Transport health check failure: %v", )
		.closeForLostPing()
	} else {
		.vlogf("http2: Transport health check success")
	}
}

// SetDoNotReuse marks cc as not reusable for future HTTP requests.
func ( *ClientConn) () {
	.mu.Lock()
	defer .mu.Unlock()
	.doNotReuse = true
}

func ( *ClientConn) ( *GoAwayFrame) {
	.mu.Lock()
	defer .mu.Unlock()

	 := .goAway
	.goAway = 

	// Merge the previous and current GoAway error frames.
	if .goAwayDebug == "" {
		.goAwayDebug = string(.DebugData())
	}
	if  != nil && .ErrCode != ErrCodeNo {
		.goAway.ErrCode = .ErrCode
	}
	 := .LastStreamID
	for ,  := range .streams {
		if  <=  {
			// The server's GOAWAY indicates that it received this stream.
			// It will either finish processing it, or close the connection
			// without doing so. Either way, leave the stream alone for now.
			continue
		}
		if  == 1 && .goAway.ErrCode != ErrCodeNo {
			// Don't retry the first stream on a connection if we get a non-NO error.
			// If the server is sending an error on a new connection,
			// retrying the request on a new one probably isn't going to work.
			.abortStreamLocked(fmt.Errorf("http2: Transport received GOAWAY from server ErrCode:%v", .goAway.ErrCode))
		} else {
			// Aborting the stream with errClentConnGotGoAway indicates that
			// the request should be retried on a new connection.
			.abortStreamLocked(errClientConnGotGoAway)
		}
	}
}

// CanTakeNewRequest reports whether the connection can take a new request,
// meaning it has not been closed or received or sent a GOAWAY.
//
// If the caller is going to immediately make a new request on this
// connection, use ReserveNewRequest instead.
func ( *ClientConn) () bool {
	.mu.Lock()
	defer .mu.Unlock()
	return .canTakeNewRequestLocked()
}

// ReserveNewRequest is like CanTakeNewRequest but also reserves a
// concurrent stream in cc. The reservation is decremented on the
// next call to RoundTrip.
func ( *ClientConn) () bool {
	.mu.Lock()
	defer .mu.Unlock()
	if  := .idleStateLocked(); !.canTakeNewRequest {
		return false
	}
	.streamsReserved++
	return true
}

// ClientConnState describes the state of a ClientConn.
type ClientConnState struct {
	// Closed is whether the connection is closed.
	Closed bool

	// Closing is whether the connection is in the process of
	// closing. It may be closing due to shutdown, being a
	// single-use connection, being marked as DoNotReuse, or
	// having received a GOAWAY frame.
	Closing bool

	// StreamsActive is how many streams are active.
	StreamsActive int

	// StreamsReserved is how many streams have been reserved via
	// ClientConn.ReserveNewRequest.
	StreamsReserved int

	// StreamsPending is how many requests have been sent in excess
	// of the peer's advertised MaxConcurrentStreams setting and
	// are waiting for other streams to complete.
	StreamsPending int

	// MaxConcurrentStreams is how many concurrent streams the
	// peer advertised as acceptable. Zero means no SETTINGS
	// frame has been received yet.
	MaxConcurrentStreams uint32

	// LastIdle, if non-zero, is when the connection last
	// transitioned to idle state.
	LastIdle time.Time
}

// State returns a snapshot of cc's state.
func ( *ClientConn) () ClientConnState {
	.wmu.Lock()
	 := .maxConcurrentStreams
	if !.seenSettings {
		 = 0
	}
	.wmu.Unlock()

	.mu.Lock()
	defer .mu.Unlock()
	return ClientConnState{
		Closed:               .closed,
		Closing:              .closing || .singleUse || .doNotReuse || .goAway != nil,
		StreamsActive:        len(.streams) + .pendingResets,
		StreamsReserved:      .streamsReserved,
		StreamsPending:       .pendingRequests,
		LastIdle:             .lastIdle,
		MaxConcurrentStreams: ,
	}
}

// clientConnIdleState describes the suitability of a client
// connection to initiate a new RoundTrip request.
type clientConnIdleState struct {
	canTakeNewRequest bool
}

func ( *ClientConn) () clientConnIdleState {
	.mu.Lock()
	defer .mu.Unlock()
	return .idleStateLocked()
}

func ( *ClientConn) () ( clientConnIdleState) {
	if .singleUse && .nextStreamID > 1 {
		return
	}
	var  bool
	if .t.StrictMaxConcurrentStreams {
		// We'll tell the caller we can take a new request to
		// prevent the caller from dialing a new TCP
		// connection, but then we'll block later before
		// writing it.
		 = true
	} else {
		// We can take a new request if the total of
		//   - active streams;
		//   - reservation slots for new streams; and
		//   - streams for which we have sent a RST_STREAM and a PING,
		//     but received no subsequent frame
		// is less than the concurrency limit.
		 = .currentRequestCountLocked() < int(.maxConcurrentStreams)
	}

	.canTakeNewRequest = .goAway == nil && !.closed && !.closing &&  &&
		!.doNotReuse &&
		int64(.nextStreamID)+2*int64(.pendingRequests) < math.MaxInt32 &&
		!.tooIdleLocked()

	// If this connection has never been used for a request and is closed,
	// then let it take a request (which will fail).
	// If the conn was closed for idleness, we're racing the idle timer;
	// don't try to use the conn. (Issue #70515.)
	//
	// This avoids a situation where an error early in a connection's lifetime
	// goes unreported.
	if .nextStreamID == 1 && .streamsReserved == 0 && .closed && !.closedOnIdle {
		.canTakeNewRequest = true
	}

	return
}

// currentRequestCountLocked reports the number of concurrency slots currently in use,
// including active streams, reserved slots, and reset streams waiting for acknowledgement.
func ( *ClientConn) () int {
	return len(.streams) + .streamsReserved + .pendingResets
}

func ( *ClientConn) () bool {
	 := .idleStateLocked()
	return .canTakeNewRequest
}

// tooIdleLocked reports whether this connection has been been sitting idle
// for too much wall time.
func ( *ClientConn) () bool {
	// The Round(0) strips the monontonic clock reading so the
	// times are compared based on their wall time. We don't want
	// to reuse a connection that's been sitting idle during
	// VM/laptop suspend if monotonic time was also frozen.
	return .idleTimeout != 0 && !.lastIdle.IsZero() && .t.timeSince(.lastIdle.Round(0)) > .idleTimeout
}

// onIdleTimeout is called from a time.AfterFunc goroutine. It will
// only be called when we're idle, but because we're coming from a new
// goroutine, there could be a new request coming in at the same time,
// so this simply calls the synchronized closeIfIdle to shut down this
// connection. The timer could just call closeIfIdle, but this is more
// clear.
func ( *ClientConn) () {
	.closeIfIdle()
}

func ( *ClientConn) () {
	 := time.AfterFunc(250*time.Millisecond, .forceCloseConn)
	defer .Stop()
	.tconn.Close()
}

// A tls.Conn.Close can hang for a long time if the peer is unresponsive.
// Try to shut it down more aggressively.
func ( *ClientConn) () {
	,  := .tconn.(*tls.Conn)
	if ! {
		return
	}
	if  := .NetConn();  != nil {
		.Close()
	}
}

func ( *ClientConn) () {
	.mu.Lock()
	if len(.streams) > 0 || .streamsReserved > 0 {
		.mu.Unlock()
		return
	}
	.closed = true
	.closedOnIdle = true
	 := .nextStreamID
	// TODO: do clients send GOAWAY too? maybe? Just Close:
	.mu.Unlock()

	if VerboseLogs {
		.vlogf("http2: Transport closing idle conn %p (forSingleUse=%v, maxStream=%v)", , .singleUse, -2)
	}
	.closeConn()
}

func ( *ClientConn) () bool {
	.mu.Lock()
	defer .mu.Unlock()
	return .doNotReuse && len(.streams) == 0
}

var shutdownEnterWaitStateHook = func() {}

// Shutdown gracefully closes the client connection, waiting for running streams to complete.
func ( *ClientConn) ( context.Context) error {
	if  := .sendGoAway();  != nil {
		return 
	}
	// Wait for all in-flight streams to complete or connection to close
	 := make(chan struct{})
	 := false // guarded by cc.mu
	go func() {
		.t.markNewGoroutine()
		.mu.Lock()
		defer .mu.Unlock()
		for {
			if len(.streams) == 0 || .closed {
				.closed = true
				close()
				break
			}
			if  {
				break
			}
			.cond.Wait()
		}
	}()
	shutdownEnterWaitStateHook()
	select {
	case <-:
		.closeConn()
		return nil
	case <-.Done():
		.mu.Lock()
		// Free the goroutine above
		 = true
		.cond.Broadcast()
		.mu.Unlock()
		return .Err()
	}
}

func ( *ClientConn) () error {
	.mu.Lock()
	 := .closing
	.closing = true
	 := .nextStreamID
	.mu.Unlock()
	if  {
		// GOAWAY sent already
		return nil
	}

	.wmu.Lock()
	defer .wmu.Unlock()
	// Send a graceful shutdown frame to server
	if  := .fr.WriteGoAway(, ErrCodeNo, nil);  != nil {
		return 
	}
	if  := .bw.Flush();  != nil {
		return 
	}
	// Prevent new requests
	return nil
}

// closes the client connection immediately. In-flight requests are interrupted.
// err is sent to streams.
func ( *ClientConn) ( error) {
	.mu.Lock()
	.closed = true
	for ,  := range .streams {
		.abortStreamLocked()
	}
	.cond.Broadcast()
	.mu.Unlock()
	.closeConn()
}

// Close closes the client connection immediately.
//
// In-flight requests are interrupted. For a graceful shutdown, use Shutdown instead.
func ( *ClientConn) () error {
	 := errors.New("http2: client connection force closed via ClientConn.Close")
	.closeForError()
	return nil
}

// closes the client connection immediately. In-flight requests are interrupted.
func ( *ClientConn) () {
	 := errors.New("http2: client connection lost")
	if  := .t.CountError;  != nil {
		("conn_close_lost_ping")
	}
	.closeForError()
}

// errRequestCanceled is a copy of net/http's errRequestCanceled because it's not
// exported. At least they'll be DeepEqual for h1-vs-h2 comparisons tests.
var errRequestCanceled = errors.New("net/http: request canceled")

func ( *ClientConn) () time.Duration {
	if .t.t1 != nil {
		return .t.t1.ResponseHeaderTimeout
	}
	// No way to do this (yet?) with just an http2.Transport. Probably
	// no need. Request.Cancel this is the new way. We only need to support
	// this for compatibility with the old http.Transport fields when
	// we're doing transparent http2.
	return 0
}

// actualContentLength returns a sanitized version of
// req.ContentLength, where 0 actually means zero (not unknown) and -1
// means unknown.
func ( *http.Request) int64 {
	if .Body == nil || .Body == http.NoBody {
		return 0
	}
	if .ContentLength != 0 {
		return .ContentLength
	}
	return -1
}

func ( *ClientConn) () {
	.mu.Lock()
	defer .mu.Unlock()
	.decrStreamReservationsLocked()
}

func ( *ClientConn) () {
	if .streamsReserved > 0 {
		.streamsReserved--
	}
}

func ( *ClientConn) ( *http.Request) (*http.Response, error) {
	return .roundTrip(, nil)
}

func ( *ClientConn) ( *http.Request,  func(*clientStream)) (*http.Response, error) {
	 := .Context()
	 := &clientStream{
		cc:                   ,
		ctx:                  ,
		reqCancel:            .Cancel,
		isHead:               .Method == "HEAD",
		reqBody:              .Body,
		reqBodyContentLength: actualContentLength(),
		trace:                httptrace.ContextClientTrace(),
		peerClosed:           make(chan struct{}),
		abort:                make(chan struct{}),
		respHeaderRecv:       make(chan struct{}),
		donec:                make(chan struct{}),
	}

	.requestedGzip = httpcommon.IsRequestGzip(.Method, .Header, .t.disableCompression())

	go .doRequest(, )

	 := func() error {
		select {
		case <-.donec:
			return nil
		case <-.Done():
			return .Err()
		case <-.reqCancel:
			return errRequestCanceled
		}
	}

	 := func() (*http.Response, error) {
		 := .res
		if .StatusCode > 299 {
			// On error or status code 3xx, 4xx, 5xx, etc abort any
			// ongoing write, assuming that the server doesn't care
			// about our request body. If the server replied with 1xx or
			// 2xx, however, then assume the server DOES potentially
			// want our body (e.g. full-duplex streaming:
			// golang.org/issue/13444). If it turns out the server
			// doesn't, they'll RST_STREAM us soon enough. This is a
			// heuristic to avoid adding knobs to Transport. Hopefully
			// we can keep it.
			.abortRequestBodyWrite()
		}
		.Request = 
		.TLS = .tlsState
		if .Body == noBody && actualContentLength() == 0 {
			// If there isn't a request or response body still being
			// written, then wait for the stream to be closed before
			// RoundTrip returns.
			if  := ();  != nil {
				return nil, 
			}
		}
		return , nil
	}

	 := func( *clientStream,  error) error {
		.cc.mu.Lock()
		 := .reqBodyClosed
		.cc.mu.Unlock()
		// Wait for the request body to be closed.
		//
		// If nothing closed the body before now, abortStreamLocked
		// will have started a goroutine to close it.
		//
		// Closing the body before returning avoids a race condition
		// with net/http checking its readTrackingBody to see if the
		// body was read from or closed. See golang/go#60041.
		//
		// The body is closed in a separate goroutine without the
		// connection mutex held, but dropping the mutex before waiting
		// will keep us from holding it indefinitely if the body
		// close is slow for some reason.
		if  != nil {
			<-
		}
		return 
	}

	for {
		select {
		case <-.respHeaderRecv:
			return ()
		case <-.abort:
			select {
			case <-.respHeaderRecv:
				// If both cs.respHeaderRecv and cs.abort are signaling,
				// pick respHeaderRecv. The server probably wrote the
				// response and immediately reset the stream.
				// golang.org/issue/49645
				return ()
			default:
				()
				return nil, .abortErr
			}
		case <-.Done():
			 := .Err()
			.abortStream()
			return nil, (, )
		case <-.reqCancel:
			.abortStream(errRequestCanceled)
			return nil, (, errRequestCanceled)
		}
	}
}

// doRequest runs for the duration of the request lifetime.
//
// It sends the request and performs post-request cleanup (closing Request.Body, etc.).
func ( *clientStream) ( *http.Request,  func(*clientStream)) {
	.cc.t.markNewGoroutine()
	 := .writeRequest(, )
	.cleanupWriteRequest()
}

var errExtendedConnectNotSupported = errors.New("net/http: extended connect not supported by peer")

// writeRequest sends a request.
//
// It returns nil after the request is written, the response read,
// and the request stream is half-closed by the peer.
//
// It returns non-nil if the request ends otherwise.
// If the returned error is StreamError, the error Code may be used in resetting the stream.
func ( *clientStream) ( *http.Request,  func(*clientStream)) ( error) {
	 := .cc
	 := .ctx

	// wait for setting frames to be received, a server can change this value later,
	// but we just wait for the first settings frame
	var  bool
	if .Method == "CONNECT" && .Header.Get(":protocol") != "" {
		 = true
	}

	// Acquire the new-request lock by writing to reqHeaderMu.
	// This lock guards the critical section covering allocating a new stream ID
	// (requires mu) and creating the stream (requires wmu).
	if .reqHeaderMu == nil {
		panic("RoundTrip on uninitialized ClientConn") // for tests
	}
	if  {
		select {
		case <-.reqCancel:
			return errRequestCanceled
		case <-.Done():
			return .Err()
		case <-.seenSettingsChan:
			if !.extendedConnectAllowed {
				return errExtendedConnectNotSupported
			}
		}
	}
	select {
	case .reqHeaderMu <- struct{}{}:
	case <-.reqCancel:
		return errRequestCanceled
	case <-.Done():
		return .Err()
	}

	.mu.Lock()
	if .idleTimer != nil {
		.idleTimer.Stop()
	}
	.decrStreamReservationsLocked()
	if  := .awaitOpenSlotForStreamLocked();  != nil {
		.mu.Unlock()
		<-.reqHeaderMu
		return 
	}
	.addStreamLocked() // assigns stream ID
	if isConnectionCloseRequest() {
		.doNotReuse = true
	}
	.mu.Unlock()

	if  != nil {
		()
	}

	 := .t.expectContinueTimeout()
	if  != 0 {
		if !httpguts.HeaderValuesContainsToken(.Header["Expect"], "100-continue") {
			 = 0
		} else {
			.on100 = make(chan struct{}, 1)
		}
	}

	// Past this point (where we send request headers), it is possible for
	// RoundTrip to return successfully. Since the RoundTrip contract permits
	// the caller to "mutate or reuse" the Request after closing the Response's Body,
	// we must take care when referencing the Request from here on.
	 = .encodeAndWriteHeaders()
	<-.reqHeaderMu
	if  != nil {
		return 
	}

	 := .reqBodyContentLength != 0
	if ! {
		.sentEndStream = true
	} else {
		if  != 0 {
			traceWait100Continue(.trace)
			 := time.NewTimer()
			select {
			case <-.C:
				 = nil
			case <-.on100:
				 = nil
			case <-.abort:
				 = .abortErr
			case <-.Done():
				 = .Err()
			case <-.reqCancel:
				 = errRequestCanceled
			}
			.Stop()
			if  != nil {
				traceWroteRequest(.trace, )
				return 
			}
		}

		if  = .writeRequestBody();  != nil {
			if  != errStopReqBodyWrite {
				traceWroteRequest(.trace, )
				return 
			}
		} else {
			.sentEndStream = true
		}
	}

	traceWroteRequest(.trace, )

	var  <-chan time.Time
	var  chan struct{}
	if  := .responseHeaderTimeout();  != 0 {
		 := .t.newTimer()
		defer .Stop()
		 = .C()
		 = .respHeaderRecv
	}
	// Wait until the peer half-closes its end of the stream,
	// or until the request is aborted (via context, error, or otherwise),
	// whichever comes first.
	for {
		select {
		case <-.peerClosed:
			return nil
		case <-:
			return errTimeout
		case <-:
			 = nil
			 = nil // keep waiting for END_STREAM
		case <-.abort:
			return .abortErr
		case <-.Done():
			return .Err()
		case <-.reqCancel:
			return errRequestCanceled
		}
	}
}

func ( *clientStream) ( *http.Request) error {
	 := .cc
	 := .ctx

	.wmu.Lock()
	defer .wmu.Unlock()

	// If the request was canceled while waiting for cc.mu, just quit.
	select {
	case <-.abort:
		return .abortErr
	case <-.Done():
		return .Err()
	case <-.reqCancel:
		return errRequestCanceled
	default:
	}

	// Encode headers.
	//
	// we send: HEADERS{1}, CONTINUATION{0,} + DATA{0,} (DATA is
	// sent by writeRequestBody below, along with any Trailers,
	// again in form HEADERS{1}, CONTINUATION{0,})
	.hbuf.Reset()
	,  := encodeRequestHeaders(, .requestedGzip, .peerMaxHeaderListSize, func(,  string) {
		.writeHeader(, )
	})
	if  != nil {
		return fmt.Errorf("http2: %w", )
	}
	 := .hbuf.Bytes()

	// Write the request.
	 := !.HasBody && !.HasTrailers
	.sentHeaders = true
	 = .writeHeaders(.ID, , int(.maxFrameSize), )
	traceWroteHeaders(.trace)
	return 
}

func ( *http.Request,  bool,  uint64,  func(,  string)) (httpcommon.EncodeHeadersResult, error) {
	return httpcommon.EncodeHeaders(.Context(), httpcommon.EncodeHeadersParam{
		Request: httpcommon.Request{
			Header:              .Header,
			Trailer:             .Trailer,
			URL:                 .URL,
			Host:                .Host,
			Method:              .Method,
			ActualContentLength: actualContentLength(),
		},
		AddGzipHeader:         ,
		PeerMaxHeaderListSize: ,
		DefaultUserAgent:      defaultUserAgent,
	}, )
}

// cleanupWriteRequest performs post-request tasks.
//
// If err (the result of writeRequest) is non-nil and the stream is not closed,
// cleanupWriteRequest will send a reset to the peer.
func ( *clientStream) ( error) {
	 := .cc

	if .ID == 0 {
		// We were canceled before creating the stream, so return our reservation.
		.decrStreamReservations()
	}

	// TODO: write h12Compare test showing whether
	// Request.Body is closed by the Transport,
	// and in multiple cases: server replies <=299 and >299
	// while still writing request body
	.mu.Lock()
	 := false
	if .reqBody != nil && .reqBodyClosed == nil {
		 = true
		.reqBodyClosed = make(chan struct{})
	}
	 := .reqBodyClosed
	 := .singleUse || .doNotReuse || .t.disableKeepAlives() || .goAway != nil
	.mu.Unlock()
	if  {
		.reqBody.Close()
		close()
	}
	if  != nil {
		<-
	}

	if  != nil && .sentEndStream {
		// If the connection is closed immediately after the response is read,
		// we may be aborted before finishing up here. If the stream was closed
		// cleanly on both sides, there is no error.
		select {
		case <-.peerClosed:
			 = nil
		default:
		}
	}
	if  != nil {
		.abortStream() // possibly redundant, but harmless
		if .sentHeaders {
			if ,  := .(StreamError);  {
				if .Cause != errFromPeer {
					.writeStreamReset(.ID, .Code, false, )
				}
			} else {
				// We're cancelling an in-flight request.
				//
				// This could be due to the server becoming unresponsive.
				// To avoid sending too many requests on a dead connection,
				// we let the request continue to consume a concurrency slot
				// until we can confirm the server is still responding.
				// We do this by sending a PING frame along with the RST_STREAM
				// (unless a ping is already in flight).
				//
				// For simplicity, we don't bother tracking the PING payload:
				// We reset cc.pendingResets any time we receive a PING ACK.
				//
				// We skip this if the conn is going to be closed on idle,
				// because it's short lived and will probably be closed before
				// we get the ping response.
				 := false
				if ! {
					.mu.Lock()
					// rstStreamPingsBlocked works around a gRPC behavior:
					// see comment on the field for details.
					if !.rstStreamPingsBlocked {
						if .pendingResets == 0 {
							 = true
						}
						.pendingResets++
					}
					.mu.Unlock()
				}
				.writeStreamReset(.ID, ErrCodeCancel, , )
			}
		}
		.bufPipe.CloseWithError() // no-op if already closed
	} else {
		if .sentHeaders && !.sentEndStream {
			.writeStreamReset(.ID, ErrCodeNo, false, nil)
		}
		.bufPipe.CloseWithError(errRequestCanceled)
	}
	if .ID != 0 {
		.forgetStreamID(.ID)
	}

	.wmu.Lock()
	 := .werr
	.wmu.Unlock()
	if  != nil {
		.Close()
	}

	close(.donec)
}

// awaitOpenSlotForStreamLocked waits until len(streams) < maxConcurrentStreams.
// Must hold cc.mu.
func ( *ClientConn) ( *clientStream) error {
	for {
		if .closed && .nextStreamID == 1 && .streamsReserved == 0 {
			// This is the very first request sent to this connection.
			// Return a fatal error which aborts the retry loop.
			return errClientConnNotEstablished
		}
		.lastActive = .t.now()
		if .closed || !.canTakeNewRequestLocked() {
			return errClientConnUnusable
		}
		.lastIdle = time.Time{}
		if .currentRequestCountLocked() < int(.maxConcurrentStreams) {
			return nil
		}
		.pendingRequests++
		.cond.Wait()
		.pendingRequests--
		select {
		case <-.abort:
			return .abortErr
		default:
		}
	}
}

// requires cc.wmu be held
func ( *ClientConn) ( uint32,  bool,  int,  []byte) error {
	 := true // first frame written (HEADERS is first, then CONTINUATION)
	for len() > 0 && .werr == nil {
		 := 
		if len() >  {
			 = [:]
		}
		 = [len():]
		 := len() == 0
		if  {
			.fr.WriteHeaders(HeadersFrameParam{
				StreamID:      ,
				BlockFragment: ,
				EndStream:     ,
				EndHeaders:    ,
			})
			 = false
		} else {
			.fr.WriteContinuation(, , )
		}
	}
	.bw.Flush()
	return .werr
}

// internal error values; they don't escape to callers
var (
	// abort request body write; don't send cancel
	errStopReqBodyWrite = errors.New("http2: aborting request body write")

	// abort request body write, but send stream reset of cancel.
	errStopReqBodyWriteAndCancel = errors.New("http2: canceling request")

	errReqBodyTooLong = errors.New("http2: request body larger than specified content length")
)

// frameScratchBufferLen returns the length of a buffer to use for
// outgoing request bodies to read/write to/from.
//
// It returns max(1, min(peer's advertised max frame size,
// Request.ContentLength+1, 512KB)).
func ( *clientStream) ( int) int {
	const  = 512 << 10
	 := int64()
	if  >  {
		 = 
	}
	if  := .reqBodyContentLength;  != -1 && +1 <  {
		// Add an extra byte past the declared content-length to
		// give the caller's Request.Body io.Reader a chance to
		// give us more bytes than they declared, so we can catch it
		// early.
		 =  + 1
	}
	if  < 1 {
		return 1
	}
	return int() // doesn't truncate; max is 512K
}

// Seven bufPools manage different frame sizes. This helps to avoid scenarios where long-running
// streaming requests using small frame sizes occupy large buffers initially allocated for prior
// requests needing big buffers. The size ranges are as follows:
// {0 KB, 16 KB], {16 KB, 32 KB], {32 KB, 64 KB], {64 KB, 128 KB], {128 KB, 256 KB],
// {256 KB, 512 KB], {512 KB, infinity}
// In practice, the maximum scratch buffer size should not exceed 512 KB due to
// frameScratchBufferLen(maxFrameSize), thus the "infinity pool" should never be used.
// It exists mainly as a safety measure, for potential future increases in max buffer size.
var bufPools [7]sync.Pool // of *[]byte
func ( int) int {
	if  <= 16384 {
		return 0
	}
	 -= 1
	 := bits.Len(uint())
	 :=  - 14
	if  >= len(bufPools) {
		return len(bufPools) - 1
	}
	return 
}

func ( *clientStream) ( *http.Request) ( error) {
	 := .cc
	 := .reqBody
	 := false // whether we sent the final DATA frame w/ END_STREAM

	 := .Trailer != nil
	 := .reqBodyContentLength
	 :=  != -1

	.mu.Lock()
	 := int(.maxFrameSize)
	.mu.Unlock()

	// Scratch buffer for reading into & writing from.
	 := .frameScratchBufferLen()
	var  []byte
	 := bufPoolIndex()
	if ,  := bufPools[].Get().(*[]byte);  && len(*) >=  {
		defer bufPools[].Put()
		 = *
	} else {
		 = make([]byte, )
		defer bufPools[].Put(&)
	}

	var  bool
	for ! {
		,  := .Read()
		if  {
			 -= int64()
			if  == 0 &&  == nil {
				// The request body's Content-Length was predeclared and
				// we just finished reading it all, but the underlying io.Reader
				// returned the final chunk with a nil error (which is one of
				// the two valid things a Reader can do at EOF). Because we'd prefer
				// to send the END_STREAM bit early, double-check that we're actually
				// at EOF. Subsequent reads should return (0, EOF) at this point.
				// If either value is different, we return an error in one of two ways below.
				var  [1]byte
				var  int
				,  = .Read([:])
				 -= int64()
			}
			if  < 0 {
				 = errReqBodyTooLong
				return 
			}
		}
		if  != nil {
			.mu.Lock()
			 := .reqBodyClosed != nil
			.mu.Unlock()
			switch {
			case :
				return errStopReqBodyWrite
			case  == io.EOF:
				 = true
				 = nil
			default:
				return 
			}
		}

		 := [:]
		for len() > 0 &&  == nil {
			var  int32
			,  = .awaitFlowControl(len())
			if  != nil {
				return 
			}
			.wmu.Lock()
			 := [:]
			 = [:]
			 =  && len() == 0 && !
			 = .fr.WriteData(.ID, , )
			if  == nil {
				// TODO(bradfitz): this flush is for latency, not bandwidth.
				// Most requests won't need this. Make this opt-in or
				// opt-out?  Use some heuristic on the body type? Nagel-like
				// timers?  Based on 'n'? Only last chunk of this for loop,
				// unless flow control tokens are low? For now, always.
				// If we change this, see comment below.
				 = .bw.Flush()
			}
			.wmu.Unlock()
		}
		if  != nil {
			return 
		}
	}

	if  {
		// Already sent END_STREAM (which implies we have no
		// trailers) and flushed, because currently all
		// WriteData frames above get a flush. So we're done.
		return nil
	}

	// Since the RoundTrip contract permits the caller to "mutate or reuse"
	// a request after the Response's Body is closed, verify that this hasn't
	// happened before accessing the trailers.
	.mu.Lock()
	 := .Trailer
	 = .abortErr
	.mu.Unlock()
	if  != nil {
		return 
	}

	.wmu.Lock()
	defer .wmu.Unlock()
	var  []byte
	if len() > 0 {
		,  = .encodeTrailers()
		if  != nil {
			return 
		}
	}

	// Two ways to send END_STREAM: either with trailers, or
	// with an empty DATA frame.
	if len() > 0 {
		 = .writeHeaders(.ID, true, , )
	} else {
		 = .fr.WriteData(.ID, true, nil)
	}
	if  := .bw.Flush();  != nil &&  == nil {
		 = 
	}
	return 
}

// awaitFlowControl waits for [1, min(maxBytes, cc.cs.maxFrameSize)] flow
// control tokens from the server.
// It returns either the non-zero number of tokens taken or an error
// if the stream is dead.
func ( *clientStream) ( int) ( int32,  error) {
	 := .cc
	 := .ctx
	.mu.Lock()
	defer .mu.Unlock()
	for {
		if .closed {
			return 0, errClientConnClosed
		}
		if .reqBodyClosed != nil {
			return 0, errStopReqBodyWrite
		}
		select {
		case <-.abort:
			return 0, .abortErr
		case <-.Done():
			return 0, .Err()
		case <-.reqCancel:
			return 0, errRequestCanceled
		default:
		}
		if  := .flow.available();  > 0 {
			 := 
			if int() >  {

				 = int32() // can't truncate int; take is int32
			}
			if  > int32(.maxFrameSize) {
				 = int32(.maxFrameSize)
			}
			.flow.take()
			return , nil
		}
		.cond.Wait()
	}
}

// requires cc.wmu be held.
func ( *ClientConn) ( http.Header) ([]byte, error) {
	.hbuf.Reset()

	 := uint64(0)
	for ,  := range  {
		for ,  := range  {
			 := hpack.HeaderField{Name: , Value: }
			 += uint64(.Size())
		}
	}
	if  > .peerMaxHeaderListSize {
		return nil, errRequestHeaderListSize
	}

	for ,  := range  {
		,  := httpcommon.LowerHeader()
		if ! {
			// Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header
			// field names have to be ASCII characters (just as in HTTP/1.x).
			continue
		}
		// Transfer-Encoding, etc.. have already been filtered at the
		// start of RoundTrip
		for ,  := range  {
			.writeHeader(, )
		}
	}
	return .hbuf.Bytes(), nil
}

func ( *ClientConn) (,  string) {
	if VerboseLogs {
		log.Printf("http2: Transport encoding header %q = %q", , )
	}
	.henc.WriteField(hpack.HeaderField{Name: , Value: })
}

type resAndError struct {
	_   incomparable
	res *http.Response
	err error
}

// requires cc.mu be held.
func ( *ClientConn) ( *clientStream) {
	.flow.add(int32(.initialWindowSize))
	.flow.setConnFlow(&.flow)
	.inflow.init(.initialStreamRecvWindowSize)
	.ID = .nextStreamID
	.nextStreamID += 2
	.streams[.ID] = 
	if .ID == 0 {
		panic("assigned stream ID 0")
	}
}

func ( *ClientConn) ( uint32) {
	.mu.Lock()
	 := len(.streams)
	delete(.streams, )
	if len(.streams) != -1 {
		panic("forgetting unknown stream id")
	}
	.lastActive = .t.now()
	if len(.streams) == 0 && .idleTimer != nil {
		.idleTimer.Reset(.idleTimeout)
		.lastIdle = .t.now()
	}
	// Wake up writeRequestBody via clientStream.awaitFlowControl and
	// wake up RoundTrip if there is a pending request.
	.cond.Broadcast()

	 := .singleUse || .doNotReuse || .t.disableKeepAlives() || .goAway != nil
	if  && .streamsReserved == 0 && len(.streams) == 0 {
		if VerboseLogs {
			.vlogf("http2: Transport closing idle conn %p (forSingleUse=%v, maxStream=%v)", , .singleUse, .nextStreamID-2)
		}
		.closed = true
		defer .closeConn()
	}

	.mu.Unlock()
}

// clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop.
type clientConnReadLoop struct {
	_  incomparable
	cc *ClientConn
}

// readLoop runs in its own goroutine and reads and dispatches frames.
func ( *ClientConn) () {
	.t.markNewGoroutine()
	 := &clientConnReadLoop{cc: }
	defer .cleanup()
	.readerErr = .run()
	if ,  := .readerErr.(ConnectionError);  {
		.wmu.Lock()
		.fr.WriteGoAway(0, ErrCode(), nil)
		.wmu.Unlock()
	}
}

// GoAwayError is returned by the Transport when the server closes the
// TCP connection after sending a GOAWAY frame.
type GoAwayError struct {
	LastStreamID uint32
	ErrCode      ErrCode
	DebugData    string
}

func ( GoAwayError) () string {
	return fmt.Sprintf("http2: server sent GOAWAY and closed the connection; LastStreamID=%v, ErrCode=%v, debug=%q",
		.LastStreamID, .ErrCode, .DebugData)
}

func ( error) bool {
	if  == io.EOF {
		return true
	}
	,  := .(*net.OpError)
	return  && .Op == "read"
}

func ( *clientConnReadLoop) () {
	 := .cc
	defer .closeConn()
	defer close(.readerDone)

	if .idleTimer != nil {
		.idleTimer.Stop()
	}

	// Close any response bodies if the server closes prematurely.
	// TODO: also do this if we've written the headers but not
	// gotten a response yet.
	 := .readerErr
	.mu.Lock()
	if .goAway != nil && isEOFOrNetReadError() {
		 = GoAwayError{
			LastStreamID: .goAway.LastStreamID,
			ErrCode:      .goAway.ErrCode,
			DebugData:    .goAwayDebug,
		}
	} else if  == io.EOF {
		 = io.ErrUnexpectedEOF
	}
	.closed = true

	// If the connection has never been used, and has been open for only a short time,
	// leave it in the connection pool for a little while.
	//
	// This avoids a situation where new connections are constantly created,
	// added to the pool, fail, and are removed from the pool, without any error
	// being surfaced to the user.
	 := 5 * time.Second
	if .idleTimeout > 0 &&  > .idleTimeout {
		 = .idleTimeout
	}
	 := .t.now().Sub(.lastActive)
	if atomic.LoadUint32(&.atomicReused) == 0 &&  <  && !.closedOnIdle {
		.idleTimer = .t.afterFunc(-, func() {
			.t.connPool().MarkDead()
		})
	} else {
		.mu.Unlock() // avoid any deadlocks in MarkDead
		.t.connPool().MarkDead()
		.mu.Lock()
	}

	for ,  := range .streams {
		select {
		case <-.peerClosed:
			// The server closed the stream before closing the conn,
			// so no need to interrupt it.
		default:
			.abortStreamLocked()
		}
	}
	.cond.Broadcast()
	.mu.Unlock()

	if !.seenSettings {
		// If we have a pending request that wants extended CONNECT,
		// let it continue and fail with the connection error.
		.extendedConnectAllowed = true
		close(.seenSettingsChan)
	}
}

// countReadFrameError calls Transport.CountError with a string
// representing err.
func ( *ClientConn) ( error) {
	 := .t.CountError
	if  == nil ||  == nil {
		return
	}
	if ,  := .(ConnectionError);  {
		 := ErrCode()
		(fmt.Sprintf("read_frame_conn_error_%s", .stringToken()))
		return
	}
	if errors.Is(, io.EOF) {
		("read_frame_eof")
		return
	}
	if errors.Is(, io.ErrUnexpectedEOF) {
		("read_frame_unexpected_eof")
		return
	}
	if errors.Is(, ErrFrameTooLarge) {
		("read_frame_too_large")
		return
	}
	("read_frame_other")
}

func ( *clientConnReadLoop) () error {
	 := .cc
	 := false
	 := .readIdleTimeout
	var  timer
	if  != 0 {
		 = .t.afterFunc(, .healthCheck)
	}
	for {
		,  := .fr.ReadFrame()
		if  != nil {
			.Reset()
		}
		if  != nil {
			.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", , , )
		}
		if ,  := .(StreamError);  {
			if  := .streamByID(.StreamID, notHeaderOrDataFrame);  != nil {
				if .Cause == nil {
					.Cause = .fr.errDetail
				}
				.endStreamError(, )
			}
			continue
		} else if  != nil {
			.countReadFrameError()
			return 
		}
		if VerboseLogs {
			.vlogf("http2: Transport received %s", summarizeFrame())
		}
		if ! {
			if ,  := .(*SettingsFrame); ! {
				.logf("protocol error: received %T before a SETTINGS frame", )
				return ConnectionError(ErrCodeProtocol)
			}
			 = true
		}

		switch f := .(type) {
		case *MetaHeadersFrame:
			 = .processHeaders()
		case *DataFrame:
			 = .processData()
		case *GoAwayFrame:
			 = .processGoAway()
		case *RSTStreamFrame:
			 = .processResetStream()
		case *SettingsFrame:
			 = .processSettings()
		case *PushPromiseFrame:
			 = .processPushPromise()
		case *WindowUpdateFrame:
			 = .processWindowUpdate()
		case *PingFrame:
			 = .processPing()
		default:
			.logf("Transport: unhandled response frame type %T", )
		}
		if  != nil {
			if VerboseLogs {
				.vlogf("http2: Transport conn %p received error from processing frame %v: %v", , summarizeFrame(), )
			}
			return 
		}
	}
}

func ( *clientConnReadLoop) ( *MetaHeadersFrame) error {
	 := .streamByID(.StreamID, headerOrDataFrame)
	if  == nil {
		// We'd get here if we canceled a request while the
		// server had its response still in flight. So if this
		// was just something we canceled, ignore it.
		return nil
	}
	if .readClosed {
		.endStreamError(, StreamError{
			StreamID: .StreamID,
			Code:     ErrCodeProtocol,
			Cause:    errors.New("protocol error: headers after END_STREAM"),
		})
		return nil
	}
	if !.firstByte {
		if .trace != nil {
			// TODO(bradfitz): move first response byte earlier,
			// when we first read the 9 byte header, not waiting
			// until all the HEADERS+CONTINUATION frames have been
			// merged. This works for now.
			traceFirstResponseByte(.trace)
		}
		.firstByte = true
	}
	if !.pastHeaders {
		.pastHeaders = true
	} else {
		return .processTrailers(, )
	}

	,  := .handleResponse(, )
	if  != nil {
		if ,  := .(ConnectionError);  {
			return 
		}
		// Any other error type is a stream error.
		.endStreamError(, StreamError{
			StreamID: .StreamID,
			Code:     ErrCodeProtocol,
			Cause:    ,
		})
		return nil // return nil from process* funcs to keep conn alive
	}
	if  == nil {
		// (nil, nil) special case. See handleResponse docs.
		return nil
	}
	.resTrailer = &.Trailer
	.res = 
	close(.respHeaderRecv)
	if .StreamEnded() {
		.endStream()
	}
	return nil
}

// may return error types nil, or ConnectionError. Any other error value
// is a StreamError of type ErrCodeProtocol. The returned error in that case
// is the detail.
//
// As a special case, handleResponse may return (nil, nil) to skip the
// frame (currently only used for 1xx responses).
func ( *clientConnReadLoop) ( *clientStream,  *MetaHeadersFrame) (*http.Response, error) {
	if .Truncated {
		return nil, errResponseHeaderListSize
	}

	 := .PseudoValue("status")
	if  == "" {
		return nil, errors.New("malformed response from server: missing status pseudo header")
	}
	,  := strconv.Atoi()
	if  != nil {
		return nil, errors.New("malformed response from server: malformed non-numeric status pseudo header")
	}

	 := .RegularFields()
	 := make([]string, len())
	 := make(http.Header, len())
	 := &http.Response{
		Proto:      "HTTP/2.0",
		ProtoMajor: 2,
		Header:     ,
		StatusCode: ,
		Status:      + " " + http.StatusText(),
	}
	for ,  := range  {
		 := httpcommon.CanonicalHeader(.Name)
		if  == "Trailer" {
			 := .Trailer
			if  == nil {
				 = make(http.Header)
				.Trailer = 
			}
			foreachHeaderElement(.Value, func( string) {
				[httpcommon.CanonicalHeader()] = nil
			})
		} else {
			 := []
			if  == nil && len() > 0 {
				// More than likely this will be a single-element key.
				// Most headers aren't multi-valued.
				// Set the capacity on strs[0] to 1, so any future append
				// won't extend the slice into the other strings.
				,  = [:1:1], [1:]
				[0] = .Value
				[] = 
			} else {
				[] = append(, .Value)
			}
		}
	}

	if  >= 100 &&  <= 199 {
		if .StreamEnded() {
			return nil, errors.New("1xx informational response with END_STREAM flag")
		}
		if  := .get1xxTraceFunc();  != nil {
			// If the 1xx response is being delivered to the user,
			// then they're responsible for limiting the number
			// of responses.
			if  := (, textproto.MIMEHeader());  != nil {
				return nil, 
			}
		} else {
			// If the user didn't examine the 1xx response, then we
			// limit the size of all 1xx headers.
			//
			// This differs a bit from the HTTP/1 implementation, which
			// limits the size of all 1xx headers plus the final response.
			// Use the larger limit of MaxHeaderListSize and
			// net/http.Transport.MaxResponseHeaderBytes.
			 := int64(.cc.t.maxHeaderListSize())
			if  := .cc.t.t1;  != nil && .MaxResponseHeaderBytes >  {
				 = .MaxResponseHeaderBytes
			}
			for ,  := range .Fields {
				.totalHeaderSize += int64(.Size())
			}
			if .totalHeaderSize >  {
				if VerboseLogs {
					log.Printf("http2: 1xx informational responses too large")
				}
				return nil, errors.New("header list too large")
			}
		}
		if  == 100 {
			traceGot100Continue(.trace)
			select {
			case .on100 <- struct{}{}:
			default:
			}
		}
		.pastHeaders = false // do it all again
		return nil, nil
	}

	.ContentLength = -1
	if  := .Header["Content-Length"]; len() == 1 {
		if ,  := strconv.ParseUint([0], 10, 63);  == nil {
			.ContentLength = int64()
		} else {
			// TODO: care? unlike http/1, it won't mess up our framing, so it's
			// more safe smuggling-wise to ignore.
		}
	} else if len() > 1 {
		// TODO: care? unlike http/1, it won't mess up our framing, so it's
		// more safe smuggling-wise to ignore.
	} else if .StreamEnded() && !.isHead {
		.ContentLength = 0
	}

	if .isHead {
		.Body = noBody
		return , nil
	}

	if .StreamEnded() {
		if .ContentLength > 0 {
			.Body = missingBody{}
		} else {
			.Body = noBody
		}
		return , nil
	}

	.bufPipe.setBuffer(&dataBuffer{expected: .ContentLength})
	.bytesRemain = .ContentLength
	.Body = transportResponseBody{}

	if .requestedGzip && asciiEqualFold(.Header.Get("Content-Encoding"), "gzip") {
		.Header.Del("Content-Encoding")
		.Header.Del("Content-Length")
		.ContentLength = -1
		.Body = &gzipReader{body: .Body}
		.Uncompressed = true
	}
	return , nil
}

func ( *clientConnReadLoop) ( *clientStream,  *MetaHeadersFrame) error {
	if .pastTrailers {
		// Too many HEADERS frames for this stream.
		return ConnectionError(ErrCodeProtocol)
	}
	.pastTrailers = true
	if !.StreamEnded() {
		// We expect that any headers for trailers also
		// has END_STREAM.
		return ConnectionError(ErrCodeProtocol)
	}
	if len(.PseudoFields()) > 0 {
		// No pseudo header fields are defined for trailers.
		// TODO: ConnectionError might be overly harsh? Check.
		return ConnectionError(ErrCodeProtocol)
	}

	 := make(http.Header)
	for ,  := range .RegularFields() {
		 := httpcommon.CanonicalHeader(.Name)
		[] = append([], .Value)
	}
	.trailer = 

	.endStream()
	return nil
}

// transportResponseBody is the concrete type of Transport.RoundTrip's
// Response.Body. It is an io.ReadCloser.
type transportResponseBody struct {
	cs *clientStream
}

func ( transportResponseBody) ( []byte) ( int,  error) {
	 := .cs
	 := .cc

	if .readErr != nil {
		return 0, .readErr
	}
	,  = .cs.bufPipe.Read()
	if .bytesRemain != -1 {
		if int64() > .bytesRemain {
			 = int(.bytesRemain)
			if  == nil {
				 = errors.New("net/http: server replied with more than declared Content-Length; truncated")
				.abortStream()
			}
			.readErr = 
			return int(.bytesRemain), 
		}
		.bytesRemain -= int64()
		if  == io.EOF && .bytesRemain > 0 {
			 = io.ErrUnexpectedEOF
			.readErr = 
			return , 
		}
	}
	if  == 0 {
		// No flow control tokens to send back.
		return
	}

	.mu.Lock()
	 := .inflow.add()
	var  int32
	if  == nil { // No need to refresh if the stream is over or failed.
		 = .inflow.add()
	}
	.mu.Unlock()

	if  != 0 ||  != 0 {
		.wmu.Lock()
		defer .wmu.Unlock()
		if  != 0 {
			.fr.WriteWindowUpdate(0, mustUint31())
		}
		if  != 0 {
			.fr.WriteWindowUpdate(.ID, mustUint31())
		}
		.bw.Flush()
	}
	return
}

var errClosedResponseBody = errors.New("http2: response body closed")

func ( transportResponseBody) () error {
	 := .cs
	 := .cc

	.bufPipe.BreakWithError(errClosedResponseBody)
	.abortStream(errClosedResponseBody)

	 := .bufPipe.Len()
	if  > 0 {
		.mu.Lock()
		// Return connection-level flow control.
		 := .inflow.add()
		.mu.Unlock()

		// TODO(dneil): Acquiring this mutex can block indefinitely.
		// Move flow control return to a goroutine?
		.wmu.Lock()
		// Return connection-level flow control.
		if  > 0 {
			.fr.WriteWindowUpdate(0, uint32())
		}
		.bw.Flush()
		.wmu.Unlock()
	}

	select {
	case <-.donec:
	case <-.ctx.Done():
		// See golang/go#49366: The net/http package can cancel the
		// request context after the response body is fully read.
		// Don't treat this as an error.
		return nil
	case <-.reqCancel:
		return errRequestCanceled
	}
	return nil
}

func ( *clientConnReadLoop) ( *DataFrame) error {
	 := .cc
	 := .streamByID(.StreamID, headerOrDataFrame)
	 := .Data()
	if  == nil {
		.mu.Lock()
		 := .nextStreamID
		.mu.Unlock()
		if .StreamID >=  {
			// We never asked for this.
			.logf("http2: Transport received unsolicited DATA frame; closing connection")
			return ConnectionError(ErrCodeProtocol)
		}
		// We probably did ask for this, but canceled. Just ignore it.
		// TODO: be stricter here? only silently ignore things which
		// we canceled, but not things which were closed normally
		// by the peer? Tough without accumulating too much state.

		// But at least return their flow control:
		if .Length > 0 {
			.mu.Lock()
			 := .inflow.take(.Length)
			 := .inflow.add(int(.Length))
			.mu.Unlock()
			if ! {
				return ConnectionError(ErrCodeFlowControl)
			}
			if  > 0 {
				.wmu.Lock()
				.fr.WriteWindowUpdate(0, uint32())
				.bw.Flush()
				.wmu.Unlock()
			}
		}
		return nil
	}
	if .readClosed {
		.logf("protocol error: received DATA after END_STREAM")
		.endStreamError(, StreamError{
			StreamID: .StreamID,
			Code:     ErrCodeProtocol,
		})
		return nil
	}
	if !.pastHeaders {
		.logf("protocol error: received DATA before a HEADERS frame")
		.endStreamError(, StreamError{
			StreamID: .StreamID,
			Code:     ErrCodeProtocol,
		})
		return nil
	}
	if .Length > 0 {
		if .isHead && len() > 0 {
			.logf("protocol error: received DATA on a HEAD request")
			.endStreamError(, StreamError{
				StreamID: .StreamID,
				Code:     ErrCodeProtocol,
			})
			return nil
		}
		// Check connection-level flow control.
		.mu.Lock()
		if !takeInflows(&.inflow, &.inflow, .Length) {
			.mu.Unlock()
			return ConnectionError(ErrCodeFlowControl)
		}
		// Return any padded flow control now, since we won't
		// refund it later on body reads.
		var  int
		if  := int(.Length) - len();  > 0 {
			 += 
		}

		 := false
		var  error
		if len() > 0 {
			if _,  = .bufPipe.Write();  != nil {
				// Return len(data) now if the stream is already closed,
				// since data will never be read.
				 = true
				 += len()
			}
		}

		 := .inflow.add()
		var  int32
		if ! {
			 = .inflow.add()
		}
		.mu.Unlock()

		if  > 0 ||  > 0 {
			.wmu.Lock()
			if  > 0 {
				.fr.WriteWindowUpdate(0, uint32())
			}
			if  > 0 {
				.fr.WriteWindowUpdate(.ID, uint32())
			}
			.bw.Flush()
			.wmu.Unlock()
		}

		if  != nil {
			.endStreamError(, )
			return nil
		}
	}

	if .StreamEnded() {
		.endStream()
	}
	return nil
}

func ( *clientConnReadLoop) ( *clientStream) {
	// TODO: check that any declared content-length matches, like
	// server.go's (*stream).endStream method.
	if !.readClosed {
		.readClosed = true
		// Close cs.bufPipe and cs.peerClosed with cc.mu held to avoid a
		// race condition: The caller can read io.EOF from Response.Body
		// and close the body before we close cs.peerClosed, causing
		// cleanupWriteRequest to send a RST_STREAM.
		.cc.mu.Lock()
		defer .cc.mu.Unlock()
		.bufPipe.closeWithErrorAndCode(io.EOF, .copyTrailers)
		close(.peerClosed)
	}
}

func ( *clientConnReadLoop) ( *clientStream,  error) {
	.readAborted = true
	.abortStream()
}

// Constants passed to streamByID for documentation purposes.
const (
	headerOrDataFrame    = true
	notHeaderOrDataFrame = false
)

// streamByID returns the stream with the given id, or nil if no stream has that id.
// If headerOrData is true, it clears rst.StreamPingsBlocked.
func ( *clientConnReadLoop) ( uint32,  bool) *clientStream {
	.cc.mu.Lock()
	defer .cc.mu.Unlock()
	if  {
		// Work around an unfortunate gRPC behavior.
		// See comment on ClientConn.rstStreamPingsBlocked for details.
		.cc.rstStreamPingsBlocked = false
	}
	 := .cc.streams[]
	if  != nil && !.readAborted {
		return 
	}
	return nil
}

func ( *clientStream) () {
	for ,  := range .trailer {
		 := .resTrailer
		if * == nil {
			* = make(http.Header)
		}
		(*)[] = 
	}
}

func ( *clientConnReadLoop) ( *GoAwayFrame) error {
	 := .cc
	.t.connPool().MarkDead()
	if .ErrCode != 0 {
		// TODO: deal with GOAWAY more. particularly the error code
		.vlogf("transport got GOAWAY with error code = %v", .ErrCode)
		if  := .t.CountError;  != nil {
			("recv_goaway_" + .ErrCode.stringToken())
		}
	}
	.setGoAway()
	return nil
}

func ( *clientConnReadLoop) ( *SettingsFrame) error {
	 := .cc
	// Locking both mu and wmu here allows frame encoding to read settings with only wmu held.
	// Acquiring wmu when f.IsAck() is unnecessary, but convenient and mostly harmless.
	.wmu.Lock()
	defer .wmu.Unlock()

	if  := .processSettingsNoWrite();  != nil {
		return 
	}
	if !.IsAck() {
		.fr.WriteSettingsAck()
		.bw.Flush()
	}
	return nil
}

func ( *clientConnReadLoop) ( *SettingsFrame) error {
	 := .cc
	.mu.Lock()
	defer .mu.Unlock()

	if .IsAck() {
		if .wantSettingsAck {
			.wantSettingsAck = false
			return nil
		}
		return ConnectionError(ErrCodeProtocol)
	}

	var  bool
	 := .ForeachSetting(func( Setting) error {
		switch .ID {
		case SettingMaxFrameSize:
			.maxFrameSize = .Val
		case SettingMaxConcurrentStreams:
			.maxConcurrentStreams = .Val
			 = true
		case SettingMaxHeaderListSize:
			.peerMaxHeaderListSize = uint64(.Val)
		case SettingInitialWindowSize:
			// Values above the maximum flow-control
			// window size of 2^31-1 MUST be treated as a
			// connection error (Section 5.4.1) of type
			// FLOW_CONTROL_ERROR.
			if .Val > math.MaxInt32 {
				return ConnectionError(ErrCodeFlowControl)
			}

			// Adjust flow control of currently-open
			// frames by the difference of the old initial
			// window size and this one.
			 := int32(.Val) - int32(.initialWindowSize)
			for ,  := range .streams {
				.flow.add()
			}
			.cond.Broadcast()

			.initialWindowSize = .Val
		case SettingHeaderTableSize:
			.henc.SetMaxDynamicTableSize(.Val)
			.peerMaxHeaderTableSize = .Val
		case SettingEnableConnectProtocol:
			if  := .Valid();  != nil {
				return 
			}
			// If the peer wants to send us SETTINGS_ENABLE_CONNECT_PROTOCOL,
			// we require that it do so in the first SETTINGS frame.
			//
			// When we attempt to use extended CONNECT, we wait for the first
			// SETTINGS frame to see if the server supports it. If we let the
			// server enable the feature with a later SETTINGS frame, then
			// users will see inconsistent results depending on whether we've
			// seen that frame or not.
			if !.seenSettings {
				.extendedConnectAllowed = .Val == 1
			}
		default:
			.vlogf("Unhandled Setting: %v", )
		}
		return nil
	})
	if  != nil {
		return 
	}

	if !.seenSettings {
		if ! {
			// This was the servers initial SETTINGS frame and it
			// didn't contain a MAX_CONCURRENT_STREAMS field so
			// increase the number of concurrent streams this
			// connection can establish to our default.
			.maxConcurrentStreams = defaultMaxConcurrentStreams
		}
		close(.seenSettingsChan)
		.seenSettings = true
	}

	return nil
}

func ( *clientConnReadLoop) ( *WindowUpdateFrame) error {
	 := .cc
	 := .streamByID(.StreamID, notHeaderOrDataFrame)
	if .StreamID != 0 &&  == nil {
		return nil
	}

	.mu.Lock()
	defer .mu.Unlock()

	 := &.flow
	if  != nil {
		 = &.flow
	}
	if !.add(int32(.Increment)) {
		// For stream, the sender sends RST_STREAM with an error code of FLOW_CONTROL_ERROR
		if  != nil {
			.endStreamError(, StreamError{
				StreamID: .StreamID,
				Code:     ErrCodeFlowControl,
			})
			return nil
		}

		return ConnectionError(ErrCodeFlowControl)
	}
	.cond.Broadcast()
	return nil
}

func ( *clientConnReadLoop) ( *RSTStreamFrame) error {
	 := .streamByID(.StreamID, notHeaderOrDataFrame)
	if  == nil {
		// TODO: return error if server tries to RST_STREAM an idle stream
		return nil
	}
	 := streamError(.ID, .ErrCode)
	.Cause = errFromPeer
	if .ErrCode == ErrCodeProtocol {
		.cc.SetDoNotReuse()
	}
	if  := .cc.t.CountError;  != nil {
		("recv_rststream_" + .ErrCode.stringToken())
	}
	.abortStream()

	.bufPipe.CloseWithError()
	return nil
}

// Ping sends a PING frame to the server and waits for the ack.
func ( *ClientConn) ( context.Context) error {
	 := make(chan struct{})
	// Generate a random payload
	var  [8]byte
	for {
		if ,  := rand.Read([:]);  != nil {
			return 
		}
		.mu.Lock()
		// check for dup before insert
		if ,  := .pings[]; ! {
			.pings[] = 
			.mu.Unlock()
			break
		}
		.mu.Unlock()
	}
	var  error
	 := make(chan struct{})
	go func() {
		.t.markNewGoroutine()
		.wmu.Lock()
		defer .wmu.Unlock()
		if  = .fr.WritePing(false, );  != nil {
			close()
			return
		}
		if  = .bw.Flush();  != nil {
			close()
			return
		}
	}()
	select {
	case <-:
		return nil
	case <-:
		return 
	case <-.Done():
		return .Err()
	case <-.readerDone:
		// connection closed
		return .readerErr
	}
}

func ( *clientConnReadLoop) ( *PingFrame) error {
	if .IsAck() {
		 := .cc
		.mu.Lock()
		defer .mu.Unlock()
		// If ack, notify listener if any
		if ,  := .pings[.Data];  {
			close()
			delete(.pings, .Data)
		}
		if .pendingResets > 0 {
			// See clientStream.cleanupWriteRequest.
			.pendingResets = 0
			.rstStreamPingsBlocked = true
			.cond.Broadcast()
		}
		return nil
	}
	 := .cc
	.wmu.Lock()
	defer .wmu.Unlock()
	if  := .fr.WritePing(true, .Data);  != nil {
		return 
	}
	return .bw.Flush()
}

func ( *clientConnReadLoop) ( *PushPromiseFrame) error {
	// We told the peer we don't want them.
	// Spec says:
	// "PUSH_PROMISE MUST NOT be sent if the SETTINGS_ENABLE_PUSH
	// setting of the peer endpoint is set to 0. An endpoint that
	// has set this setting and has received acknowledgement MUST
	// treat the receipt of a PUSH_PROMISE frame as a connection
	// error (Section 5.4.1) of type PROTOCOL_ERROR."
	return ConnectionError(ErrCodeProtocol)
}

// writeStreamReset sends a RST_STREAM frame.
// When ping is true, it also sends a PING frame with a random payload.
func ( *ClientConn) ( uint32,  ErrCode,  bool,  error) {
	// TODO: map err to more interesting error codes, once the
	// HTTP community comes up with some. But currently for
	// RST_STREAM there's no equivalent to GOAWAY frame's debug
	// data, and the error codes are all pretty vague ("cancel").
	.wmu.Lock()
	.fr.WriteRSTStream(, )
	if  {
		var  [8]byte
		rand.Read([:])
		.fr.WritePing(false, )
	}
	.bw.Flush()
	.wmu.Unlock()
}

var (
	errResponseHeaderListSize = errors.New("http2: response header list larger than advertised limit")
	errRequestHeaderListSize  = httpcommon.ErrRequestHeaderListSize
)

func ( *ClientConn) ( string,  ...interface{}) {
	.t.logf(, ...)
}

func ( *ClientConn) ( string,  ...interface{}) {
	.t.vlogf(, ...)
}

func ( *Transport) ( string,  ...interface{}) {
	if VerboseLogs {
		.logf(, ...)
	}
}

func ( *Transport) ( string,  ...interface{}) {
	log.Printf(, ...)
}

var noBody io.ReadCloser = noBodyReader{}

type noBodyReader struct{}

func (noBodyReader) () error             { return nil }
func (noBodyReader) ([]byte) (int, error) { return 0, io.EOF }

type missingBody struct{}

func (missingBody) () error             { return nil }
func (missingBody) ([]byte) (int, error) { return 0, io.ErrUnexpectedEOF }

func ( []string,  string) bool {
	for ,  := range  {
		if  ==  {
			return true
		}
	}
	return false
}

type erringRoundTripper struct{ err error }

func ( erringRoundTripper) () error                             { return .err }
func ( erringRoundTripper) (*http.Request) (*http.Response, error) { return nil, .err }

// gzipReader wraps a response body so it can lazily
// call gzip.NewReader on the first call to Read
type gzipReader struct {
	_    incomparable
	body io.ReadCloser // underlying Response.Body
	zr   *gzip.Reader  // lazily-initialized gzip reader
	zerr error         // sticky error
}

func ( *gzipReader) ( []byte) ( int,  error) {
	if .zerr != nil {
		return 0, .zerr
	}
	if .zr == nil {
		.zr,  = gzip.NewReader(.body)
		if  != nil {
			.zerr = 
			return 0, 
		}
	}
	return .zr.Read()
}

func ( *gzipReader) () error {
	if  := .body.Close();  != nil {
		return 
	}
	.zerr = fs.ErrClosed
	return nil
}

type errorReader struct{ err error }

func ( errorReader) ( []byte) (int, error) { return 0, .err }

// isConnectionCloseRequest reports whether req should use its own
// connection for a single request and then close the connection.
func ( *http.Request) bool {
	return .Close || httpguts.HeaderValuesContainsToken(.Header["Connection"], "close")
}

// registerHTTPSProtocol calls Transport.RegisterProtocol but
// converting panics into errors.
func ( *http.Transport,  noDialH2RoundTripper) ( error) {
	defer func() {
		if  := recover();  != nil {
			 = fmt.Errorf("%v", )
		}
	}()
	.RegisterProtocol("https", )
	return nil
}

// noDialH2RoundTripper is a RoundTripper which only tries to complete the request
// if there's already has a cached connection to the host.
// (The field is exported so it can be accessed via reflect from net/http; tested
// by TestNoDialH2RoundTripperType)
type noDialH2RoundTripper struct{ *Transport }

func ( noDialH2RoundTripper) ( *http.Request) (*http.Response, error) {
	,  := .Transport.RoundTrip()
	if isNoCachedConnError() {
		return nil, http.ErrSkipAltProtocol
	}
	return , 
}

func ( *Transport) () time.Duration {
	// to keep things backwards compatible, we use non-zero values of
	// IdleConnTimeout, followed by using the IdleConnTimeout on the underlying
	// http1 transport, followed by 0
	if .IdleConnTimeout != 0 {
		return .IdleConnTimeout
	}

	if .t1 != nil {
		return .t1.IdleConnTimeout
	}

	return 0
}

func ( *http.Request,  string) {
	 := httptrace.ContextClientTrace(.Context())
	if  == nil || .GetConn == nil {
		return
	}
	.GetConn()
}

func ( *http.Request,  *ClientConn,  bool) {
	 := httptrace.ContextClientTrace(.Context())
	if  == nil || .GotConn == nil {
		return
	}
	 := httptrace.GotConnInfo{Conn: .tconn}
	.Reused = 
	.mu.Lock()
	.WasIdle = len(.streams) == 0 && 
	if .WasIdle && !.lastActive.IsZero() {
		.IdleTime = .t.timeSince(.lastActive)
	}
	.mu.Unlock()

	.GotConn()
}

func ( *httptrace.ClientTrace) {
	if  != nil && .WroteHeaders != nil {
		.WroteHeaders()
	}
}

func ( *httptrace.ClientTrace) {
	if  != nil && .Got100Continue != nil {
		.Got100Continue()
	}
}

func ( *httptrace.ClientTrace) {
	if  != nil && .Wait100Continue != nil {
		.Wait100Continue()
	}
}

func ( *httptrace.ClientTrace,  error) {
	if  != nil && .WroteRequest != nil {
		.WroteRequest(httptrace.WroteRequestInfo{Err: })
	}
}

func ( *httptrace.ClientTrace) {
	if  != nil && .GotFirstResponseByte != nil {
		.GotFirstResponseByte()
	}
}

func ( *httptrace.ClientTrace) func(int, textproto.MIMEHeader) error {
	if  != nil {
		return .Got1xxResponse
	}
	return nil
}

// dialTLSWithContext uses tls.Dialer, added in Go 1.15, to open a TLS
// connection.
func ( *Transport) ( context.Context, ,  string,  *tls.Config) (*tls.Conn, error) {
	 := &tls.Dialer{
		Config: ,
	}
	,  := .DialContext(, , )
	if  != nil {
		return nil, 
	}
	 := .(*tls.Conn) // DialContext comment promises this will always succeed
	return , nil
}