// 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

	// 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
}

func ( *Transport) () uint32 {
	if .MaxHeaderListSize == 0 {
		return 10 << 20
	}
	if .MaxHeaderListSize == 0xffffffff {
		return 0
	}
	return .MaxHeaderListSize
}

func ( *Transport) () uint32 {
	if .MaxReadFrameSize == 0 {
		return 0 // use the default provided by the peer
	}
	if .MaxReadFrameSize < minMaxFrameSize {
		return minMaxFrameSize
	}
	if .MaxReadFrameSize > maxFrameSize {
		return maxFrameSize
	}
	return .MaxReadFrameSize
}

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

func ( *Transport) () time.Duration {
	if .PingTimeout == 0 {
		return 15 * time.Second
	}
	return .PingTimeout

}

// 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,  *tls.Conn) http.RoundTripper {
		 := authorityAddr("https", )
		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()
		}
		return 
	}
	if  := .TLSNextProto; len() == 0 {
		.TLSNextProto = map[string]func(string, *tls.Conn) http.RoundTripper{
			"h2": ,
		}
	} else {
		["h2"] = 
	}
	return , nil
}

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
	tconnClosed   bool
	tlsState      *tls.ConnectionState // nil only for specialized impls
	reused        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   *time.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
	seenSettings    bool                     // true if we've seen a settings frame, false otherwise
	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

	// 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)
	num1xx       uint8 // number of 1xx responses seen
	readClosed   bool  // peer sent an END_STREAM flag
	readAborted  bool  // read loop reset the stream

	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() {
		.reqBody.Close()
		close()
	}()
}

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

func ( stickyErrWriter) ( []byte) ( int,  error) {
	if *.err != nil {
		return 0, *.err
	}
	for {
		if .timeout != 0 {
			.conn.SetWriteDeadline(time.Now().Add(.timeout))
		}
		,  := .conn.Write([:])
		 += 
		if  < len() &&  > 0 && errors.Is(, os.ErrDeadlineExceeded) {
			// Keep extending the deadline so long as we're making progress.
			continue
		}
		if .timeout != 0 {
			.conn.SetWriteDeadline(time.Time{})
		}
		*.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
}

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
		 = "443"
		if  == "http" {
			 = "80"
		}
		 = 
	}
	if ,  := idna.ToASCII();  == nil {
		 = 
	}
	// IPv6 address literal, without a port:
	if strings.HasPrefix(, "[") && strings.HasSuffix(, "]") {
		return  + ":" + 
	}
	return net.JoinHostPort(, )
}

var retryBackoffHook func(time.Duration) *time.Timer

func ( time.Duration) *time.Timer {
	if retryBackoffHook != nil {
		return retryBackoffHook()
	}
	return time.NewTimer()
}

// RoundTripOpt is like RoundTrip, but takes options.
func ( *Transport) ( *http.Request,  RoundTripOpt) (*http.Response, error) {
	if !(.URL.Scheme == "https" || (.URL.Scheme == "http" && .AllowHTTP)) {
		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(&.reused, 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()
				 := backoffNewTimer()
				select {
				case <-.C:
					.vlogf("RoundTrip retrying after failure: %v", )
					continue
				case <-.Context().Done():
					.Stop()
					 = .Context().Err()
				}
			}
		}
		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")
	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) {
	, ,  := 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) () uint32 {
	if  := .MaxDecoderHeaderTableSize;  > 0 {
		return 
	}
	return initialHeaderTableSize
}

func ( *Transport) () uint32 {
	if  := .MaxEncoderHeaderTableSize;  > 0 {
		return 
	}
	return initialHeaderTableSize
}

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

func ( *Transport) ( net.Conn,  bool) (*ClientConn, error) {
	 := &ClientConn{
		t:                     ,
		tconn:                 ,
		readerDone:            make(chan struct{}),
		nextStreamID:          1,
		maxFrameSize:          16 << 10,                    // spec default
		initialWindowSize:     65535,                       // spec default
		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:             ,
		wantSettingsAck:       true,
		pings:                 make(map[[8]byte]chan struct{}),
		reqHeaderMu:           make(chan struct{}, 1),
	}
	if  := .idleConnTimeout();  != 0 {
		.idleTimeout = 
		.idleTimer = time.AfterFunc(, .onIdleTimeout)
	}
	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{
		conn:    ,
		timeout: .WriteByteTimeout,
		err:     &.werr,
	})
	.br = bufio.NewReader()
	.fr = NewFramer(.bw, .br)
	if .maxFrameReadSize() != 0 {
		.fr.SetMaxReadFrameSize(.maxFrameReadSize())
	}
	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 .AllowHTTP {
		.nextStreamID = 3
	}

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

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

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

	go .readLoop()
	return , nil
}

func ( *ClientConn) () {
	 := .t.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.
	,  := context.WithTimeout(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  >  {
			.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),
		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 {
		 = int64(len(.streams)+.streamsReserved+1) <= int64(.maxConcurrentStreams)
	}

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

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() && time.Since(.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  := tlsUnderlyingConn();  != nil {
		.Close()
	}
}

func ( *ClientConn) () {
	.mu.Lock()
	if len(.streams) > 0 || .streamsReserved > 0 {
		.mu.Unlock()
		return
	}
	.closed = 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() {
		.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 ( *http.Request) (string, error) {
	 := make([]string, 0, len(.Trailer))
	for  := range .Trailer {
		 = canonicalHeader()
		switch  {
		case "Transfer-Encoding", "Trailer", "Content-Length":
			return "", fmt.Errorf("invalid Trailer key %q", )
		}
		 = append(, )
	}
	if len() > 0 {
		sort.Strings()
		return strings.Join(, ","), nil
	}
	return "", nil
}

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
}

// checkConnHeaders checks whether req has any invalid connection-level headers.
// per RFC 7540 section 8.1.2.2: Connection-Specific Header Fields.
// Certain headers are special-cased as okay but not transmitted later.
func ( *http.Request) error {
	if  := .Header.Get("Upgrade");  != "" {
		return fmt.Errorf("http2: invalid Upgrade request header: %q", .Header["Upgrade"])
	}
	if  := .Header["Transfer-Encoding"]; len() > 0 && (len() > 1 || [0] != "" && [0] != "chunked") {
		return fmt.Errorf("http2: invalid Transfer-Encoding request header: %q", )
	}
	if  := .Header["Connection"]; len() > 0 && (len() > 1 || [0] != "" && !asciiEqualFold([0], "close") && !asciiEqualFold([0], "keep-alive")) {
		return fmt.Errorf("http2: invalid Connection request header: %q", )
	}
	return nil
}

// 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) {
	 := .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{}),
	}
	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
	}

	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) {
	 := .writeRequest()
	.cleanupWriteRequest()
}

// 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) ( error) {
	 := .cc
	 := .ctx

	if  := checkConnHeaders();  != nil {
		return 
	}

	// 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
	}
	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()

	// TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
	if !.t.disableCompression() &&
		.Header.Get("Accept-Encoding") == "" &&
		.Header.Get("Range") == "" &&
		!.isHead {
		// Request gzip only, not deflate. Deflate is ambiguous and
		// not as universally supported anyway.
		// See: https://zlib.net/zlib_faq.html#faq39
		//
		// Note that we don't request this for HEAD requests,
		// due to a bug in nginx:
		//   http://trac.nginx.org/nginx/ticket/358
		//   https://golang.org/issue/5522
		//
		// We don't request gzip if the request is for a range, since
		// auto-decoding a portion of a gzipped document will just fail
		// anyway. See https://golang.org/issue/8923
		.requestedGzip = true
	}

	 := .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 {
		 := time.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,})
	,  := commaSeparatedTrailers()
	if  != nil {
		return 
	}
	 :=  != ""
	 := actualContentLength()
	 :=  != 0
	,  := .encodeHeaders(, .requestedGzip, , )
	if  != nil {
		return 
	}

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

// 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
	.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, )
				}
			} else {
				.writeStreamReset(.ID, ErrCodeCancel, )
			}
		}
		.bufPipe.CloseWithError() // no-op if already closed
	} else {
		if .sentHeaders && !.sentEndStream {
			.writeStreamReset(.ID, ErrCodeNo, 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 {
		.lastActive = time.Now()
		if .closed || !.canTakeNewRequestLocked() {
			return errClientConnUnusable
		}
		.lastIdle = time.Time{}
		if int64(len(.streams)) < int64(.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
}

var bufPool sync.Pool // of *[]byte

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
	if ,  := bufPool.Get().(*[]byte);  && len(*) >=  {
		defer bufPool.Put()
		 = *
	} else {
		 = make([]byte, )
		defer bufPool.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()
	}
}

var errNilRequestURL = errors.New("http2: Request.URI is nil")

// requires cc.wmu be held.
func ( *ClientConn) ( *http.Request,  bool,  string,  int64) ([]byte, error) {
	.hbuf.Reset()
	if .URL == nil {
		return nil, errNilRequestURL
	}

	 := .Host
	if  == "" {
		 = .URL.Host
	}
	,  := httpguts.PunycodeHostPort()
	if  != nil {
		return nil, 
	}

	var  string
	if .Method != "CONNECT" {
		 = .URL.RequestURI()
		if !validPseudoPath() {
			 := 
			 = strings.TrimPrefix(, .URL.Scheme+"://"+)
			if !validPseudoPath() {
				if .URL.Opaque != "" {
					return nil, fmt.Errorf("invalid request :path %q from URL.Opaque = %q", , .URL.Opaque)
				} else {
					return nil, fmt.Errorf("invalid request :path %q", )
				}
			}
		}
	}

	// Check for any invalid headers and return an error before we
	// potentially pollute our hpack state. (We want to be able to
	// continue to reuse the hpack encoder for future requests)
	for ,  := range .Header {
		if !httpguts.ValidHeaderFieldName() {
			return nil, fmt.Errorf("invalid HTTP header name %q", )
		}
		for ,  := range  {
			if !httpguts.ValidHeaderFieldValue() {
				// Don't include the value in the error, because it may be sensitive.
				return nil, fmt.Errorf("invalid HTTP header value for header %q", )
			}
		}
	}

	 := func( func(,  string)) {
		// 8.1.2.3 Request Pseudo-Header Fields
		// The :path pseudo-header field includes the path and query parts of the
		// target URI (the path-absolute production and optionally a '?' character
		// followed by the query production (see Sections 3.3 and 3.4 of
		// [RFC3986]).
		(":authority", )
		 := .Method
		if  == "" {
			 = http.MethodGet
		}
		(":method", )
		if .Method != "CONNECT" {
			(":path", )
			(":scheme", .URL.Scheme)
		}
		if  != "" {
			("trailer", )
		}

		var  bool
		for ,  := range .Header {
			if asciiEqualFold(, "host") || asciiEqualFold(, "content-length") {
				// Host is :authority, already sent.
				// Content-Length is automatic, set below.
				continue
			} else if asciiEqualFold(, "connection") ||
				asciiEqualFold(, "proxy-connection") ||
				asciiEqualFold(, "transfer-encoding") ||
				asciiEqualFold(, "upgrade") ||
				asciiEqualFold(, "keep-alive") {
				// Per 8.1.2.2 Connection-Specific Header
				// Fields, don't send connection-specific
				// fields. We have already checked if any
				// are error-worthy so just ignore the rest.
				continue
			} else if asciiEqualFold(, "user-agent") {
				// Match Go's http1 behavior: at most one
				// User-Agent. If set to nil or empty string,
				// then omit it. Otherwise if not mentioned,
				// include the default (below).
				 = true
				if len() < 1 {
					continue
				}
				 = [:1]
				if [0] == "" {
					continue
				}
			} else if asciiEqualFold(, "cookie") {
				// Per 8.1.2.5 To allow for better compression efficiency, the
				// Cookie header field MAY be split into separate header fields,
				// each with one or more cookie-pairs.
				for ,  := range  {
					for {
						 := strings.IndexByte(, ';')
						if  < 0 {
							break
						}
						("cookie", [:])
						++
						// strip space after semicolon if any.
						for +1 <= len() && [] == ' ' {
							++
						}
						 = [:]
					}
					if len() > 0 {
						("cookie", )
					}
				}
				continue
			}

			for ,  := range  {
				(, )
			}
		}
		if shouldSendReqContentLength(.Method, ) {
			("content-length", strconv.FormatInt(, 10))
		}
		if  {
			("accept-encoding", "gzip")
		}
		if ! {
			("user-agent", defaultUserAgent)
		}
	}

	// Do a first pass over the headers counting bytes to ensure
	// we don't exceed cc.peerMaxHeaderListSize. This is done as a
	// separate pass before encoding the headers to prevent
	// modifying the hpack state.
	 := uint64(0)
	(func(,  string) {
		 := hpack.HeaderField{Name: , Value: }
		 += uint64(.Size())
	})

	if  > .peerMaxHeaderListSize {
		return nil, errRequestHeaderListSize
	}

	 := httptrace.ContextClientTrace(.Context())
	 := traceHasWroteHeaderField()

	// Header list size is ok. Write the headers.
	(func(,  string) {
		,  := 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).
			return
		}
		.writeHeader(, )
		if  {
			traceWroteHeaderField(, , )
		}
	})

	return .hbuf.Bytes(), nil
}

// shouldSendReqContentLength reports whether the http2.Transport should send
// a "content-length" request header. This logic is basically a copy of the net/http
// transferWriter.shouldSendContentLength.
// The contentLength is the corrected contentLength (so 0 means actually 0, not unknown).
// -1 means unknown.
func ( string,  int64) bool {
	if  > 0 {
		return true
	}
	if  < 0 {
		return false
	}
	// For zero bodies, whether we send a content-length depends on the method.
	// It also kinda doesn't matter for http2 either way, with END_STREAM.
	switch  {
	case "POST", "PUT", "PATCH":
		return true
	default:
		return false
	}
}

// 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  {
		,  := 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(transportDefaultStreamFlow)
	.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 = time.Now()
	if len(.streams) == 0 && .idleTimer != nil {
		.idleTimer.Reset(.idleTimeout)
		.lastIdle = time.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) () {
	 := &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
	.t.connPool().MarkDead()
	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

	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()
}

// 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
	 := .t.ReadIdleTimeout
	var  *time.Timer
	if  != 0 {
		 = time.AfterFunc(, .healthCheck)
		defer .Stop()
	}
	for {
		,  := .fr.ReadFrame()
		if  != nil {
			.Reset()
		}
		if  != nil {
			.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", , , )
		}
		if ,  := .(StreamError);  {
			if  := .streamByID(.StreamID);  != 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)
	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  {
		 := canonicalHeader(.Name)
		if  == "Trailer" {
			 := .Trailer
			if  == nil {
				 = make(http.Header)
				.Trailer = 
			}
			foreachHeaderElement(.Value, func( string) {
				[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")
		}
		.num1xx++
		const  = 5 // arbitrary bound on number of informational responses, same as net/http
		if .num1xx >  {
			return nil, errors.New("http2: too many 1xx informational responses")
		}
		if  := .get1xxTraceFunc();  != nil {
			if  := (, textproto.MIMEHeader());  != nil {
				return nil, 
			}
		}
		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() {
		 := 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.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()
	}

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

	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)
	 := .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 !.firstByte {
		.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()
}

func ( *clientConnReadLoop) ( uint32) *clientStream {
	.cc.mu.Lock()
	defer .cc.mu.Unlock()
	 := .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
		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
		}
		.seenSettings = true
	}

	return nil
}

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

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

	 := &.flow
	if  != nil {
		 = &.flow
	}
	if !.add(int32(.Increment)) {
		return ConnectionError(ErrCodeFlowControl)
	}
	.cond.Broadcast()
	return nil
}

func ( *clientConnReadLoop) ( *RSTStreamFrame) error {
	 := .streamByID(.StreamID)
	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()
	}
	 := make(chan error, 1)
	go func() {
		.wmu.Lock()
		defer .wmu.Unlock()
		if  := .fr.WritePing(false, );  != nil {
			 <- 
			return
		}
		if  := .bw.Flush();  != nil {
			 <- 
			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)
		}
		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)
}

func ( *ClientConn) ( uint32,  ErrCode,  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(, )
	.bw.Flush()
	.wmu.Unlock()
}

var (
	errResponseHeaderListSize = errors.New("http2: response header list larger than advertised limit")
	errRequestHeaderListSize  = errors.New("http2: request header list larger than peer's advertised limit")
)

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 {
	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 = time.Since(.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()
	}
}