//go:build !nethttpomithttp2

// Code generated by golang.org/x/tools/cmd/bundle. DO NOT EDIT.
//   $ bundle -o=h2_bundle.go -prefix=http2 -tags=!nethttpomithttp2 golang.org/x/net/http2

// Package http2 implements the HTTP/2 protocol.
//
// This package is low-level and intended to be used directly by very
// few people. Most users will use it indirectly through the automatic
// use by the net/http package (from Go 1.6 and later).
// For use in earlier Go versions see ConfigureServer. (Transport support
// requires Go 1.6 or later)
//
// See https://http2.github.io/ for more information on HTTP/2.
//
// See https://http2.golang.org/ for a test server running this code.
//
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//

package http

import (
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	mathrand 
	
	
	
	
	
	
	
	
	
	
	
	
	

	
	
	
)

// The HTTP protocols are defined in terms of ASCII, not Unicode. This file
// contains helper functions which may use Unicode-aware functions which would
// otherwise be unsafe and could introduce vulnerabilities if used improperly.

// asciiEqualFold is strings.EqualFold, ASCII only. It reports whether s and t
// are equal, ASCII-case-insensitively.
func http2asciiEqualFold(,  string) bool {
	if len() != len() {
		return false
	}
	for  := 0;  < len(); ++ {
		if http2lower([]) != http2lower([]) {
			return false
		}
	}
	return true
}

// lower returns the ASCII lowercase version of b.
func http2lower( byte) byte {
	if 'A' <=  &&  <= 'Z' {
		return  + ('a' - 'A')
	}
	return 
}

// isASCIIPrint returns whether s is ASCII and printable according to
// https://tools.ietf.org/html/rfc20#section-4.2.
func http2isASCIIPrint( string) bool {
	for  := 0;  < len(); ++ {
		if [] < ' ' || [] > '~' {
			return false
		}
	}
	return true
}

// asciiToLower returns the lowercase version of s if s is ASCII and printable,
// and whether or not it was.
func http2asciiToLower( string) ( string,  bool) {
	if !http2isASCIIPrint() {
		return "", false
	}
	return strings.ToLower(), true
}

// A list of the possible cipher suite ids. Taken from
// https://www.iana.org/assignments/tls-parameters/tls-parameters.txt

const (
	http2cipher_TLS_NULL_WITH_NULL_NULL               uint16 = 0x0000
	http2cipher_TLS_RSA_WITH_NULL_MD5                 uint16 = 0x0001
	http2cipher_TLS_RSA_WITH_NULL_SHA                 uint16 = 0x0002
	http2cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5        uint16 = 0x0003
	http2cipher_TLS_RSA_WITH_RC4_128_MD5              uint16 = 0x0004
	http2cipher_TLS_RSA_WITH_RC4_128_SHA              uint16 = 0x0005
	http2cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5    uint16 = 0x0006
	http2cipher_TLS_RSA_WITH_IDEA_CBC_SHA             uint16 = 0x0007
	http2cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA     uint16 = 0x0008
	http2cipher_TLS_RSA_WITH_DES_CBC_SHA              uint16 = 0x0009
	http2cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA         uint16 = 0x000A
	http2cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA  uint16 = 0x000B
	http2cipher_TLS_DH_DSS_WITH_DES_CBC_SHA           uint16 = 0x000C
	http2cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA      uint16 = 0x000D
	http2cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA  uint16 = 0x000E
	http2cipher_TLS_DH_RSA_WITH_DES_CBC_SHA           uint16 = 0x000F
	http2cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA      uint16 = 0x0010
	http2cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0011
	http2cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA          uint16 = 0x0012
	http2cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA     uint16 = 0x0013
	http2cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0014
	http2cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA          uint16 = 0x0015
	http2cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA     uint16 = 0x0016
	http2cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5    uint16 = 0x0017
	http2cipher_TLS_DH_anon_WITH_RC4_128_MD5          uint16 = 0x0018
	http2cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0019
	http2cipher_TLS_DH_anon_WITH_DES_CBC_SHA          uint16 = 0x001A
	http2cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA     uint16 = 0x001B
	// Reserved uint16 =  0x001C-1D
	http2cipher_TLS_KRB5_WITH_DES_CBC_SHA             uint16 = 0x001E
	http2cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA        uint16 = 0x001F
	http2cipher_TLS_KRB5_WITH_RC4_128_SHA             uint16 = 0x0020
	http2cipher_TLS_KRB5_WITH_IDEA_CBC_SHA            uint16 = 0x0021
	http2cipher_TLS_KRB5_WITH_DES_CBC_MD5             uint16 = 0x0022
	http2cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5        uint16 = 0x0023
	http2cipher_TLS_KRB5_WITH_RC4_128_MD5             uint16 = 0x0024
	http2cipher_TLS_KRB5_WITH_IDEA_CBC_MD5            uint16 = 0x0025
	http2cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA   uint16 = 0x0026
	http2cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA   uint16 = 0x0027
	http2cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA       uint16 = 0x0028
	http2cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5   uint16 = 0x0029
	http2cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5   uint16 = 0x002A
	http2cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5       uint16 = 0x002B
	http2cipher_TLS_PSK_WITH_NULL_SHA                 uint16 = 0x002C
	http2cipher_TLS_DHE_PSK_WITH_NULL_SHA             uint16 = 0x002D
	http2cipher_TLS_RSA_PSK_WITH_NULL_SHA             uint16 = 0x002E
	http2cipher_TLS_RSA_WITH_AES_128_CBC_SHA          uint16 = 0x002F
	http2cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA       uint16 = 0x0030
	http2cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA       uint16 = 0x0031
	http2cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA      uint16 = 0x0032
	http2cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA      uint16 = 0x0033
	http2cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA      uint16 = 0x0034
	http2cipher_TLS_RSA_WITH_AES_256_CBC_SHA          uint16 = 0x0035
	http2cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA       uint16 = 0x0036
	http2cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA       uint16 = 0x0037
	http2cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA      uint16 = 0x0038
	http2cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA      uint16 = 0x0039
	http2cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA      uint16 = 0x003A
	http2cipher_TLS_RSA_WITH_NULL_SHA256              uint16 = 0x003B
	http2cipher_TLS_RSA_WITH_AES_128_CBC_SHA256       uint16 = 0x003C
	http2cipher_TLS_RSA_WITH_AES_256_CBC_SHA256       uint16 = 0x003D
	http2cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256    uint16 = 0x003E
	http2cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256    uint16 = 0x003F
	http2cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256   uint16 = 0x0040
	http2cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA     uint16 = 0x0041
	http2cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA  uint16 = 0x0042
	http2cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA  uint16 = 0x0043
	http2cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0044
	http2cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0045
	http2cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0046
	// Reserved uint16 =  0x0047-4F
	// Reserved uint16 =  0x0050-58
	// Reserved uint16 =  0x0059-5C
	// Unassigned uint16 =  0x005D-5F
	// Reserved uint16 =  0x0060-66
	http2cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x0067
	http2cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256  uint16 = 0x0068
	http2cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256  uint16 = 0x0069
	http2cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 uint16 = 0x006A
	http2cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x006B
	http2cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256 uint16 = 0x006C
	http2cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256 uint16 = 0x006D
	// Unassigned uint16 =  0x006E-83
	http2cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA        uint16 = 0x0084
	http2cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA     uint16 = 0x0085
	http2cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA     uint16 = 0x0086
	http2cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA    uint16 = 0x0087
	http2cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA    uint16 = 0x0088
	http2cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA    uint16 = 0x0089
	http2cipher_TLS_PSK_WITH_RC4_128_SHA                 uint16 = 0x008A
	http2cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA            uint16 = 0x008B
	http2cipher_TLS_PSK_WITH_AES_128_CBC_SHA             uint16 = 0x008C
	http2cipher_TLS_PSK_WITH_AES_256_CBC_SHA             uint16 = 0x008D
	http2cipher_TLS_DHE_PSK_WITH_RC4_128_SHA             uint16 = 0x008E
	http2cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA        uint16 = 0x008F
	http2cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA         uint16 = 0x0090
	http2cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA         uint16 = 0x0091
	http2cipher_TLS_RSA_PSK_WITH_RC4_128_SHA             uint16 = 0x0092
	http2cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA        uint16 = 0x0093
	http2cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA         uint16 = 0x0094
	http2cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA         uint16 = 0x0095
	http2cipher_TLS_RSA_WITH_SEED_CBC_SHA                uint16 = 0x0096
	http2cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA             uint16 = 0x0097
	http2cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA             uint16 = 0x0098
	http2cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA            uint16 = 0x0099
	http2cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA            uint16 = 0x009A
	http2cipher_TLS_DH_anon_WITH_SEED_CBC_SHA            uint16 = 0x009B
	http2cipher_TLS_RSA_WITH_AES_128_GCM_SHA256          uint16 = 0x009C
	http2cipher_TLS_RSA_WITH_AES_256_GCM_SHA384          uint16 = 0x009D
	http2cipher_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256      uint16 = 0x009E
	http2cipher_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384      uint16 = 0x009F
	http2cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256       uint16 = 0x00A0
	http2cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384       uint16 = 0x00A1
	http2cipher_TLS_DHE_DSS_WITH_AES_128_GCM_SHA256      uint16 = 0x00A2
	http2cipher_TLS_DHE_DSS_WITH_AES_256_GCM_SHA384      uint16 = 0x00A3
	http2cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256       uint16 = 0x00A4
	http2cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384       uint16 = 0x00A5
	http2cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256      uint16 = 0x00A6
	http2cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384      uint16 = 0x00A7
	http2cipher_TLS_PSK_WITH_AES_128_GCM_SHA256          uint16 = 0x00A8
	http2cipher_TLS_PSK_WITH_AES_256_GCM_SHA384          uint16 = 0x00A9
	http2cipher_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256      uint16 = 0x00AA
	http2cipher_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384      uint16 = 0x00AB
	http2cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256      uint16 = 0x00AC
	http2cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384      uint16 = 0x00AD
	http2cipher_TLS_PSK_WITH_AES_128_CBC_SHA256          uint16 = 0x00AE
	http2cipher_TLS_PSK_WITH_AES_256_CBC_SHA384          uint16 = 0x00AF
	http2cipher_TLS_PSK_WITH_NULL_SHA256                 uint16 = 0x00B0
	http2cipher_TLS_PSK_WITH_NULL_SHA384                 uint16 = 0x00B1
	http2cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256      uint16 = 0x00B2
	http2cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384      uint16 = 0x00B3
	http2cipher_TLS_DHE_PSK_WITH_NULL_SHA256             uint16 = 0x00B4
	http2cipher_TLS_DHE_PSK_WITH_NULL_SHA384             uint16 = 0x00B5
	http2cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256      uint16 = 0x00B6
	http2cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384      uint16 = 0x00B7
	http2cipher_TLS_RSA_PSK_WITH_NULL_SHA256             uint16 = 0x00B8
	http2cipher_TLS_RSA_PSK_WITH_NULL_SHA384             uint16 = 0x00B9
	http2cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256     uint16 = 0x00BA
	http2cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256  uint16 = 0x00BB
	http2cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256  uint16 = 0x00BC
	http2cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BD
	http2cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BE
	http2cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BF
	http2cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256     uint16 = 0x00C0
	http2cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256  uint16 = 0x00C1
	http2cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256  uint16 = 0x00C2
	http2cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C3
	http2cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C4
	http2cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C5
	// Unassigned uint16 =  0x00C6-FE
	http2cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV uint16 = 0x00FF
	// Unassigned uint16 =  0x01-55,*
	http2cipher_TLS_FALLBACK_SCSV uint16 = 0x5600
	// Unassigned                                   uint16 = 0x5601 - 0xC000
	http2cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA                 uint16 = 0xC001
	http2cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA              uint16 = 0xC002
	http2cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA         uint16 = 0xC003
	http2cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA          uint16 = 0xC004
	http2cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA          uint16 = 0xC005
	http2cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA                uint16 = 0xC006
	http2cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA             uint16 = 0xC007
	http2cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA        uint16 = 0xC008
	http2cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA         uint16 = 0xC009
	http2cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA         uint16 = 0xC00A
	http2cipher_TLS_ECDH_RSA_WITH_NULL_SHA                   uint16 = 0xC00B
	http2cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA                uint16 = 0xC00C
	http2cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA           uint16 = 0xC00D
	http2cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA            uint16 = 0xC00E
	http2cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA            uint16 = 0xC00F
	http2cipher_TLS_ECDHE_RSA_WITH_NULL_SHA                  uint16 = 0xC010
	http2cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA               uint16 = 0xC011
	http2cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA          uint16 = 0xC012
	http2cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA           uint16 = 0xC013
	http2cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA           uint16 = 0xC014
	http2cipher_TLS_ECDH_anon_WITH_NULL_SHA                  uint16 = 0xC015
	http2cipher_TLS_ECDH_anon_WITH_RC4_128_SHA               uint16 = 0xC016
	http2cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA          uint16 = 0xC017
	http2cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA           uint16 = 0xC018
	http2cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA           uint16 = 0xC019
	http2cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA            uint16 = 0xC01A
	http2cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA        uint16 = 0xC01B
	http2cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA        uint16 = 0xC01C
	http2cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA             uint16 = 0xC01D
	http2cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA         uint16 = 0xC01E
	http2cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA         uint16 = 0xC01F
	http2cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA             uint16 = 0xC020
	http2cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA         uint16 = 0xC021
	http2cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA         uint16 = 0xC022
	http2cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256      uint16 = 0xC023
	http2cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384      uint16 = 0xC024
	http2cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256       uint16 = 0xC025
	http2cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384       uint16 = 0xC026
	http2cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256        uint16 = 0xC027
	http2cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384        uint16 = 0xC028
	http2cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256         uint16 = 0xC029
	http2cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384         uint16 = 0xC02A
	http2cipher_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256      uint16 = 0xC02B
	http2cipher_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384      uint16 = 0xC02C
	http2cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256       uint16 = 0xC02D
	http2cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384       uint16 = 0xC02E
	http2cipher_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256        uint16 = 0xC02F
	http2cipher_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384        uint16 = 0xC030
	http2cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256         uint16 = 0xC031
	http2cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384         uint16 = 0xC032
	http2cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA               uint16 = 0xC033
	http2cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA          uint16 = 0xC034
	http2cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA           uint16 = 0xC035
	http2cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA           uint16 = 0xC036
	http2cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256        uint16 = 0xC037
	http2cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384        uint16 = 0xC038
	http2cipher_TLS_ECDHE_PSK_WITH_NULL_SHA                  uint16 = 0xC039
	http2cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256               uint16 = 0xC03A
	http2cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384               uint16 = 0xC03B
	http2cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256             uint16 = 0xC03C
	http2cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384             uint16 = 0xC03D
	http2cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256          uint16 = 0xC03E
	http2cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384          uint16 = 0xC03F
	http2cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256          uint16 = 0xC040
	http2cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384          uint16 = 0xC041
	http2cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256         uint16 = 0xC042
	http2cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384         uint16 = 0xC043
	http2cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256         uint16 = 0xC044
	http2cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384         uint16 = 0xC045
	http2cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256         uint16 = 0xC046
	http2cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384         uint16 = 0xC047
	http2cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256     uint16 = 0xC048
	http2cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384     uint16 = 0xC049
	http2cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256      uint16 = 0xC04A
	http2cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384      uint16 = 0xC04B
	http2cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256       uint16 = 0xC04C
	http2cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384       uint16 = 0xC04D
	http2cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256        uint16 = 0xC04E
	http2cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384        uint16 = 0xC04F
	http2cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256             uint16 = 0xC050
	http2cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384             uint16 = 0xC051
	http2cipher_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256         uint16 = 0xC052
	http2cipher_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384         uint16 = 0xC053
	http2cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256          uint16 = 0xC054
	http2cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384          uint16 = 0xC055
	http2cipher_TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256         uint16 = 0xC056
	http2cipher_TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384         uint16 = 0xC057
	http2cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256          uint16 = 0xC058
	http2cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384          uint16 = 0xC059
	http2cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256         uint16 = 0xC05A
	http2cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384         uint16 = 0xC05B
	http2cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256     uint16 = 0xC05C
	http2cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384     uint16 = 0xC05D
	http2cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256      uint16 = 0xC05E
	http2cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384      uint16 = 0xC05F
	http2cipher_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256       uint16 = 0xC060
	http2cipher_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384       uint16 = 0xC061
	http2cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256        uint16 = 0xC062
	http2cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384        uint16 = 0xC063
	http2cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256             uint16 = 0xC064
	http2cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384             uint16 = 0xC065
	http2cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256         uint16 = 0xC066
	http2cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384         uint16 = 0xC067
	http2cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256         uint16 = 0xC068
	http2cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384         uint16 = 0xC069
	http2cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256             uint16 = 0xC06A
	http2cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384             uint16 = 0xC06B
	http2cipher_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256         uint16 = 0xC06C
	http2cipher_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384         uint16 = 0xC06D
	http2cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256         uint16 = 0xC06E
	http2cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384         uint16 = 0xC06F
	http2cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256       uint16 = 0xC070
	http2cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384       uint16 = 0xC071
	http2cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC072
	http2cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC073
	http2cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256  uint16 = 0xC074
	http2cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384  uint16 = 0xC075
	http2cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256   uint16 = 0xC076
	http2cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384   uint16 = 0xC077
	http2cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256    uint16 = 0xC078
	http2cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384    uint16 = 0xC079
	http2cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256         uint16 = 0xC07A
	http2cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384         uint16 = 0xC07B
	http2cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256     uint16 = 0xC07C
	http2cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384     uint16 = 0xC07D
	http2cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256      uint16 = 0xC07E
	http2cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384      uint16 = 0xC07F
	http2cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256     uint16 = 0xC080
	http2cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384     uint16 = 0xC081
	http2cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256      uint16 = 0xC082
	http2cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384      uint16 = 0xC083
	http2cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256     uint16 = 0xC084
	http2cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384     uint16 = 0xC085
	http2cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC086
	http2cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC087
	http2cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256  uint16 = 0xC088
	http2cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384  uint16 = 0xC089
	http2cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256   uint16 = 0xC08A
	http2cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384   uint16 = 0xC08B
	http2cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256    uint16 = 0xC08C
	http2cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384    uint16 = 0xC08D
	http2cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256         uint16 = 0xC08E
	http2cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384         uint16 = 0xC08F
	http2cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256     uint16 = 0xC090
	http2cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384     uint16 = 0xC091
	http2cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256     uint16 = 0xC092
	http2cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384     uint16 = 0xC093
	http2cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256         uint16 = 0xC094
	http2cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384         uint16 = 0xC095
	http2cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256     uint16 = 0xC096
	http2cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384     uint16 = 0xC097
	http2cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256     uint16 = 0xC098
	http2cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384     uint16 = 0xC099
	http2cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256   uint16 = 0xC09A
	http2cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384   uint16 = 0xC09B
	http2cipher_TLS_RSA_WITH_AES_128_CCM                     uint16 = 0xC09C
	http2cipher_TLS_RSA_WITH_AES_256_CCM                     uint16 = 0xC09D
	http2cipher_TLS_DHE_RSA_WITH_AES_128_CCM                 uint16 = 0xC09E
	http2cipher_TLS_DHE_RSA_WITH_AES_256_CCM                 uint16 = 0xC09F
	http2cipher_TLS_RSA_WITH_AES_128_CCM_8                   uint16 = 0xC0A0
	http2cipher_TLS_RSA_WITH_AES_256_CCM_8                   uint16 = 0xC0A1
	http2cipher_TLS_DHE_RSA_WITH_AES_128_CCM_8               uint16 = 0xC0A2
	http2cipher_TLS_DHE_RSA_WITH_AES_256_CCM_8               uint16 = 0xC0A3
	http2cipher_TLS_PSK_WITH_AES_128_CCM                     uint16 = 0xC0A4
	http2cipher_TLS_PSK_WITH_AES_256_CCM                     uint16 = 0xC0A5
	http2cipher_TLS_DHE_PSK_WITH_AES_128_CCM                 uint16 = 0xC0A6
	http2cipher_TLS_DHE_PSK_WITH_AES_256_CCM                 uint16 = 0xC0A7
	http2cipher_TLS_PSK_WITH_AES_128_CCM_8                   uint16 = 0xC0A8
	http2cipher_TLS_PSK_WITH_AES_256_CCM_8                   uint16 = 0xC0A9
	http2cipher_TLS_PSK_DHE_WITH_AES_128_CCM_8               uint16 = 0xC0AA
	http2cipher_TLS_PSK_DHE_WITH_AES_256_CCM_8               uint16 = 0xC0AB
	http2cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM             uint16 = 0xC0AC
	http2cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CCM             uint16 = 0xC0AD
	http2cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8           uint16 = 0xC0AE
	http2cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8           uint16 = 0xC0AF
	// Unassigned uint16 =  0xC0B0-FF
	// Unassigned uint16 =  0xC1-CB,*
	// Unassigned uint16 =  0xCC00-A7
	http2cipher_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256   uint16 = 0xCCA8
	http2cipher_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCA9
	http2cipher_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256     uint16 = 0xCCAA
	http2cipher_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256         uint16 = 0xCCAB
	http2cipher_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256   uint16 = 0xCCAC
	http2cipher_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256     uint16 = 0xCCAD
	http2cipher_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256     uint16 = 0xCCAE
)

// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
// References:
// https://tools.ietf.org/html/rfc7540#appendix-A
// Reject cipher suites from Appendix A.
// "This list includes those cipher suites that do not
// offer an ephemeral key exchange and those that are
// based on the TLS null, stream or block cipher type"
func http2isBadCipher( uint16) bool {
	switch  {
	case http2cipher_TLS_NULL_WITH_NULL_NULL,
		http2cipher_TLS_RSA_WITH_NULL_MD5,
		http2cipher_TLS_RSA_WITH_NULL_SHA,
		http2cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5,
		http2cipher_TLS_RSA_WITH_RC4_128_MD5,
		http2cipher_TLS_RSA_WITH_RC4_128_SHA,
		http2cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
		http2cipher_TLS_RSA_WITH_IDEA_CBC_SHA,
		http2cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA,
		http2cipher_TLS_RSA_WITH_DES_CBC_SHA,
		http2cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
		http2cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
		http2cipher_TLS_DH_DSS_WITH_DES_CBC_SHA,
		http2cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA,
		http2cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
		http2cipher_TLS_DH_RSA_WITH_DES_CBC_SHA,
		http2cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,
		http2cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
		http2cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA,
		http2cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
		http2cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
		http2cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA,
		http2cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
		http2cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5,
		http2cipher_TLS_DH_anon_WITH_RC4_128_MD5,
		http2cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
		http2cipher_TLS_DH_anon_WITH_DES_CBC_SHA,
		http2cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
		http2cipher_TLS_KRB5_WITH_DES_CBC_SHA,
		http2cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA,
		http2cipher_TLS_KRB5_WITH_RC4_128_SHA,
		http2cipher_TLS_KRB5_WITH_IDEA_CBC_SHA,
		http2cipher_TLS_KRB5_WITH_DES_CBC_MD5,
		http2cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5,
		http2cipher_TLS_KRB5_WITH_RC4_128_MD5,
		http2cipher_TLS_KRB5_WITH_IDEA_CBC_MD5,
		http2cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA,
		http2cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA,
		http2cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA,
		http2cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5,
		http2cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5,
		http2cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5,
		http2cipher_TLS_PSK_WITH_NULL_SHA,
		http2cipher_TLS_DHE_PSK_WITH_NULL_SHA,
		http2cipher_TLS_RSA_PSK_WITH_NULL_SHA,
		http2cipher_TLS_RSA_WITH_AES_128_CBC_SHA,
		http2cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA,
		http2cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA,
		http2cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
		http2cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
		http2cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA,
		http2cipher_TLS_RSA_WITH_AES_256_CBC_SHA,
		http2cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA,
		http2cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA,
		http2cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
		http2cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
		http2cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA,
		http2cipher_TLS_RSA_WITH_NULL_SHA256,
		http2cipher_TLS_RSA_WITH_AES_128_CBC_SHA256,
		http2cipher_TLS_RSA_WITH_AES_256_CBC_SHA256,
		http2cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256,
		http2cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256,
		http2cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
		http2cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
		http2cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA,
		http2cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA,
		http2cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
		http2cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
		http2cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA,
		http2cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
		http2cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256,
		http2cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256,
		http2cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
		http2cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
		http2cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256,
		http2cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256,
		http2cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
		http2cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA,
		http2cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA,
		http2cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
		http2cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
		http2cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA,
		http2cipher_TLS_PSK_WITH_RC4_128_SHA,
		http2cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA,
		http2cipher_TLS_PSK_WITH_AES_128_CBC_SHA,
		http2cipher_TLS_PSK_WITH_AES_256_CBC_SHA,
		http2cipher_TLS_DHE_PSK_WITH_RC4_128_SHA,
		http2cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
		http2cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
		http2cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
		http2cipher_TLS_RSA_PSK_WITH_RC4_128_SHA,
		http2cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
		http2cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
		http2cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
		http2cipher_TLS_RSA_WITH_SEED_CBC_SHA,
		http2cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA,
		http2cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA,
		http2cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA,
		http2cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA,
		http2cipher_TLS_DH_anon_WITH_SEED_CBC_SHA,
		http2cipher_TLS_RSA_WITH_AES_128_GCM_SHA256,
		http2cipher_TLS_RSA_WITH_AES_256_GCM_SHA384,
		http2cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256,
		http2cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384,
		http2cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256,
		http2cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384,
		http2cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256,
		http2cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384,
		http2cipher_TLS_PSK_WITH_AES_128_GCM_SHA256,
		http2cipher_TLS_PSK_WITH_AES_256_GCM_SHA384,
		http2cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
		http2cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
		http2cipher_TLS_PSK_WITH_AES_128_CBC_SHA256,
		http2cipher_TLS_PSK_WITH_AES_256_CBC_SHA384,
		http2cipher_TLS_PSK_WITH_NULL_SHA256,
		http2cipher_TLS_PSK_WITH_NULL_SHA384,
		http2cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
		http2cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
		http2cipher_TLS_DHE_PSK_WITH_NULL_SHA256,
		http2cipher_TLS_DHE_PSK_WITH_NULL_SHA384,
		http2cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
		http2cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
		http2cipher_TLS_RSA_PSK_WITH_NULL_SHA256,
		http2cipher_TLS_RSA_PSK_WITH_NULL_SHA384,
		http2cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
		http2cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256,
		http2cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
		http2cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,
		http2cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
		http2cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256,
		http2cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
		http2cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256,
		http2cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256,
		http2cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,
		http2cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
		http2cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256,
		http2cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
		http2cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA,
		http2cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
		http2cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
		http2cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
		http2cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
		http2cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA,
		http2cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
		http2cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
		http2cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
		http2cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
		http2cipher_TLS_ECDH_RSA_WITH_NULL_SHA,
		http2cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA,
		http2cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
		http2cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
		http2cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
		http2cipher_TLS_ECDHE_RSA_WITH_NULL_SHA,
		http2cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA,
		http2cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
		http2cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
		http2cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
		http2cipher_TLS_ECDH_anon_WITH_NULL_SHA,
		http2cipher_TLS_ECDH_anon_WITH_RC4_128_SHA,
		http2cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,
		http2cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA,
		http2cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA,
		http2cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
		http2cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
		http2cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
		http2cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
		http2cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
		http2cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
		http2cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA,
		http2cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
		http2cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
		http2cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
		http2cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
		http2cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
		http2cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
		http2cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
		http2cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
		http2cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
		http2cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
		http2cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
		http2cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
		http2cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
		http2cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
		http2cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA,
		http2cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
		http2cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
		http2cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
		http2cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
		http2cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
		http2cipher_TLS_ECDHE_PSK_WITH_NULL_SHA,
		http2cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256,
		http2cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384,
		http2cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256,
		http2cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384,
		http2cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256,
		http2cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384,
		http2cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256,
		http2cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384,
		http2cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256,
		http2cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384,
		http2cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
		http2cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
		http2cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256,
		http2cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384,
		http2cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
		http2cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
		http2cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
		http2cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
		http2cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
		http2cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
		http2cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
		http2cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
		http2cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
		http2cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
		http2cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256,
		http2cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384,
		http2cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256,
		http2cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384,
		http2cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256,
		http2cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384,
		http2cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
		http2cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
		http2cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
		http2cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
		http2cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256,
		http2cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384,
		http2cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
		http2cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
		http2cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,
		http2cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,
		http2cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
		http2cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
		http2cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
		http2cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
		http2cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
		http2cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
		http2cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
		http2cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
		http2cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
		http2cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
		http2cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
		http2cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
		http2cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
		http2cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,
		http2cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,
		http2cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,
		http2cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
		http2cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
		http2cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256,
		http2cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384,
		http2cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256,
		http2cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384,
		http2cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
		http2cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
		http2cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
		http2cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
		http2cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,
		http2cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,
		http2cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256,
		http2cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384,
		http2cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
		http2cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
		http2cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
		http2cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
		http2cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
		http2cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
		http2cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
		http2cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
		http2cipher_TLS_RSA_WITH_AES_128_CCM,
		http2cipher_TLS_RSA_WITH_AES_256_CCM,
		http2cipher_TLS_RSA_WITH_AES_128_CCM_8,
		http2cipher_TLS_RSA_WITH_AES_256_CCM_8,
		http2cipher_TLS_PSK_WITH_AES_128_CCM,
		http2cipher_TLS_PSK_WITH_AES_256_CCM,
		http2cipher_TLS_PSK_WITH_AES_128_CCM_8,
		http2cipher_TLS_PSK_WITH_AES_256_CCM_8:
		return true
	default:
		return false
	}
}

// ClientConnPool manages a pool of HTTP/2 client connections.
type http2ClientConnPool interface {
	// GetClientConn returns a specific HTTP/2 connection (usually
	// a TLS-TCP connection) to an HTTP/2 server. On success, the
	// returned ClientConn accounts for the upcoming RoundTrip
	// call, so the caller should not omit it. If the caller needs
	// to, ClientConn.RoundTrip can be called with a bogus
	// new(http.Request) to release the stream reservation.
	GetClientConn(req *Request, addr string) (*http2ClientConn, error)
	MarkDead(*http2ClientConn)
}

// clientConnPoolIdleCloser is the interface implemented by ClientConnPool
// implementations which can close their idle connections.
type http2clientConnPoolIdleCloser interface {
	http2ClientConnPool
	closeIdleConnections()
}

var (
	_ http2clientConnPoolIdleCloser = (*http2clientConnPool)(nil)
	_ http2clientConnPoolIdleCloser = http2noDialClientConnPool{}
)

// TODO: use singleflight for dialing and addConnCalls?
type http2clientConnPool struct {
	t *http2Transport

	mu sync.Mutex // TODO: maybe switch to RWMutex
	// TODO: add support for sharing conns based on cert names
	// (e.g. share conn for googleapis.com and appspot.com)
	conns        map[string][]*http2ClientConn // key is host:port
	dialing      map[string]*http2dialCall     // currently in-flight dials
	keys         map[*http2ClientConn][]string
	addConnCalls map[string]*http2addConnCall // in-flight addConnIfNeeded calls
}

func ( *http2clientConnPool) ( *Request,  string) (*http2ClientConn, error) {
	return .getClientConn(, , http2dialOnMiss)
}

const (
	http2dialOnMiss   = true
	http2noDialOnMiss = false
)

func ( *http2clientConnPool) ( *Request,  string,  bool) (*http2ClientConn, error) {
	// TODO(dneil): Dial a new connection when t.DisableKeepAlives is set?
	if http2isConnectionCloseRequest() &&  {
		// It gets its own connection.
		http2traceGetConn(, )
		const  = true
		,  := .t.dialClientConn(.Context(), , )
		if  != nil {
			return nil, 
		}
		return , nil
	}
	for {
		.mu.Lock()
		for ,  := range .conns[] {
			if .ReserveNewRequest() {
				// When a connection is presented to us by the net/http package,
				// the GetConn hook has already been called.
				// Don't call it a second time here.
				if !.getConnCalled {
					http2traceGetConn(, )
				}
				.getConnCalled = false
				.mu.Unlock()
				return , nil
			}
		}
		if ! {
			.mu.Unlock()
			return nil, http2ErrNoCachedConn
		}
		http2traceGetConn(, )
		 := .getStartDialLocked(.Context(), )
		.mu.Unlock()
		<-.done
		if http2shouldRetryDial(, ) {
			continue
		}
		,  := .res, .err
		if  != nil {
			return nil, 
		}
		if .ReserveNewRequest() {
			return , nil
		}
	}
}

// dialCall is an in-flight Transport dial call to a host.
type http2dialCall struct {
	_ http2incomparable
	p *http2clientConnPool
	// the context associated with the request
	// that created this dialCall
	ctx  context.Context
	done chan struct{}    // closed when done
	res  *http2ClientConn // valid after done is closed
	err  error            // valid after done is closed
}

// requires p.mu is held.
func ( *http2clientConnPool) ( context.Context,  string) *http2dialCall {
	if ,  := .dialing[];  {
		// A dial is already in-flight. Don't start another.
		return 
	}
	 := &http2dialCall{p: , done: make(chan struct{}), ctx: }
	if .dialing == nil {
		.dialing = make(map[string]*http2dialCall)
	}
	.dialing[] = 
	go .dial(.ctx, )
	return 
}

// run in its own goroutine.
func ( *http2dialCall) ( context.Context,  string) {
	const  = false // shared conn
	.res, .err = .p.t.dialClientConn(, , )

	.p.mu.Lock()
	delete(.p.dialing, )
	if .err == nil {
		.p.addConnLocked(, .res)
	}
	.p.mu.Unlock()

	close(.done)
}

// addConnIfNeeded makes a NewClientConn out of c if a connection for key doesn't
// already exist. It coalesces concurrent calls with the same key.
// This is used by the http1 Transport code when it creates a new connection. Because
// the http1 Transport doesn't de-dup TCP dials to outbound hosts (because it doesn't know
// the protocol), it can get into a situation where it has multiple TLS connections.
// This code decides which ones live or die.
// The return value used is whether c was used.
// c is never closed.
func ( *http2clientConnPool) ( string,  *http2Transport,  net.Conn) ( bool,  error) {
	.mu.Lock()
	for ,  := range .conns[] {
		if .CanTakeNewRequest() {
			.mu.Unlock()
			return false, nil
		}
	}
	,  := .addConnCalls[]
	if ! {
		if .addConnCalls == nil {
			.addConnCalls = make(map[string]*http2addConnCall)
		}
		 = &http2addConnCall{
			p:    ,
			done: make(chan struct{}),
		}
		.addConnCalls[] = 
		go .run(, , )
	}
	.mu.Unlock()

	<-.done
	if .err != nil {
		return false, .err
	}
	return !, nil
}

type http2addConnCall struct {
	_    http2incomparable
	p    *http2clientConnPool
	done chan struct{} // closed when done
	err  error
}

func ( *http2addConnCall) ( *http2Transport,  string,  net.Conn) {
	,  := .NewClientConn()

	 := .p
	.mu.Lock()
	if  != nil {
		.err = 
	} else {
		.getConnCalled = true // already called by the net/http package
		.addConnLocked(, )
	}
	delete(.addConnCalls, )
	.mu.Unlock()
	close(.done)
}

// p.mu must be held
func ( *http2clientConnPool) ( string,  *http2ClientConn) {
	for ,  := range .conns[] {
		if  ==  {
			return
		}
	}
	if .conns == nil {
		.conns = make(map[string][]*http2ClientConn)
	}
	if .keys == nil {
		.keys = make(map[*http2ClientConn][]string)
	}
	.conns[] = append(.conns[], )
	.keys[] = append(.keys[], )
}

func ( *http2clientConnPool) ( *http2ClientConn) {
	.mu.Lock()
	defer .mu.Unlock()
	for ,  := range .keys[] {
		,  := .conns[]
		if ! {
			continue
		}
		 := http2filterOutClientConn(, )
		if len() > 0 {
			.conns[] = 
		} else {
			delete(.conns, )
		}
	}
	delete(.keys, )
}

func ( *http2clientConnPool) () {
	.mu.Lock()
	defer .mu.Unlock()
	// TODO: don't close a cc if it was just added to the pool
	// milliseconds ago and has never been used. There's currently
	// a small race window with the HTTP/1 Transport's integration
	// where it can add an idle conn just before using it, and
	// somebody else can concurrently call CloseIdleConns and
	// break some caller's RoundTrip.
	for ,  := range .conns {
		for ,  := range  {
			.closeIfIdle()
		}
	}
}

func http2filterOutClientConn( []*http2ClientConn,  *http2ClientConn) []*http2ClientConn {
	 := [:0]
	for ,  := range  {
		if  !=  {
			 = append(, )
		}
	}
	// If we filtered it out, zero out the last item to prevent
	// the GC from seeing it.
	if len() != len() {
		[len()-1] = nil
	}
	return 
}

// noDialClientConnPool is an implementation of http2.ClientConnPool
// which never dials. We let the HTTP/1.1 client dial and use its TLS
// connection instead.
type http2noDialClientConnPool struct{ *http2clientConnPool }

func ( http2noDialClientConnPool) ( *Request,  string) (*http2ClientConn, error) {
	return .getClientConn(, , http2noDialOnMiss)
}

// shouldRetryDial reports whether the current request should
// retry dialing after the call finished unsuccessfully, for example
// if the dial was canceled because of a context cancellation or
// deadline expiry.
func http2shouldRetryDial( *http2dialCall,  *Request) bool {
	if .err == nil {
		// No error, no need to retry
		return false
	}
	if .ctx == .Context() {
		// If the call has the same context as the request, the dial
		// should not be retried, since any cancellation will have come
		// from this request.
		return false
	}
	if !errors.Is(.err, context.Canceled) && !errors.Is(.err, context.DeadlineExceeded) {
		// If the call error is not because of a context cancellation or a deadline expiry,
		// the dial should not be retried.
		return false
	}
	// Only retry if the error is a context cancellation error or deadline expiry
	// and the context associated with the call was canceled or expired.
	return .ctx.Err() != nil
}

// http2Config is a package-internal version of net/http.HTTP2Config.
//
// http.HTTP2Config was added in Go 1.24.
// When running with a version of net/http that includes HTTP2Config,
// we merge the configuration with the fields in Transport or Server
// to produce an http2Config.
//
// Zero valued fields in http2Config are interpreted as in the
// net/http.HTTPConfig documentation.
//
// Precedence order for reconciling configurations is:
//
//   - Use the net/http.{Server,Transport}.HTTP2Config value, when non-zero.
//   - Otherwise use the http2.{Server.Transport} value.
//   - If the resulting value is zero or out of range, use a default.
type http2http2Config struct {
	MaxConcurrentStreams         uint32
	MaxDecoderHeaderTableSize    uint32
	MaxEncoderHeaderTableSize    uint32
	MaxReadFrameSize             uint32
	MaxUploadBufferPerConnection int32
	MaxUploadBufferPerStream     int32
	SendPingTimeout              time.Duration
	PingTimeout                  time.Duration
	WriteByteTimeout             time.Duration
	PermitProhibitedCipherSuites bool
	CountError                   func(errType string)
}

// configFromServer merges configuration settings from
// net/http.Server.HTTP2Config and http2.Server.
func http2configFromServer( *Server,  *http2Server) http2http2Config {
	 := http2http2Config{
		MaxConcurrentStreams:         .MaxConcurrentStreams,
		MaxEncoderHeaderTableSize:    .MaxEncoderHeaderTableSize,
		MaxDecoderHeaderTableSize:    .MaxDecoderHeaderTableSize,
		MaxReadFrameSize:             .MaxReadFrameSize,
		MaxUploadBufferPerConnection: .MaxUploadBufferPerConnection,
		MaxUploadBufferPerStream:     .MaxUploadBufferPerStream,
		SendPingTimeout:              .ReadIdleTimeout,
		PingTimeout:                  .PingTimeout,
		WriteByteTimeout:             .WriteByteTimeout,
		PermitProhibitedCipherSuites: .PermitProhibitedCipherSuites,
		CountError:                   .CountError,
	}
	http2fillNetHTTPServerConfig(&, )
	http2setConfigDefaults(&, true)
	return 
}

// configFromServer merges configuration settings from h2 and h2.t1.HTTP2
// (the net/http Transport).
func http2configFromTransport( *http2Transport) http2http2Config {
	 := http2http2Config{
		MaxEncoderHeaderTableSize: .MaxEncoderHeaderTableSize,
		MaxDecoderHeaderTableSize: .MaxDecoderHeaderTableSize,
		MaxReadFrameSize:          .MaxReadFrameSize,
		SendPingTimeout:           .ReadIdleTimeout,
		PingTimeout:               .PingTimeout,
		WriteByteTimeout:          .WriteByteTimeout,
	}

	// Unlike most config fields, where out-of-range values revert to the default,
	// Transport.MaxReadFrameSize clips.
	if .MaxReadFrameSize < http2minMaxFrameSize {
		.MaxReadFrameSize = http2minMaxFrameSize
	} else if .MaxReadFrameSize > http2maxFrameSize {
		.MaxReadFrameSize = http2maxFrameSize
	}

	if .t1 != nil {
		http2fillNetHTTPTransportConfig(&, .t1)
	}
	http2setConfigDefaults(&, false)
	return 
}

func http2setDefault[ ~int | ~int32 | ~uint32 | ~int64]( *, , ,  ) {
	if * <  || * >  {
		* = 
	}
}

func http2setConfigDefaults( *http2http2Config,  bool) {
	http2setDefault(&.MaxConcurrentStreams, 1, math.MaxUint32, http2defaultMaxStreams)
	http2setDefault(&.MaxEncoderHeaderTableSize, 1, math.MaxUint32, http2initialHeaderTableSize)
	http2setDefault(&.MaxDecoderHeaderTableSize, 1, math.MaxUint32, http2initialHeaderTableSize)
	if  {
		http2setDefault(&.MaxUploadBufferPerConnection, http2initialWindowSize, math.MaxInt32, 1<<20)
	} else {
		http2setDefault(&.MaxUploadBufferPerConnection, http2initialWindowSize, math.MaxInt32, http2transportDefaultConnFlow)
	}
	if  {
		http2setDefault(&.MaxUploadBufferPerStream, 1, math.MaxInt32, 1<<20)
	} else {
		http2setDefault(&.MaxUploadBufferPerStream, 1, math.MaxInt32, http2transportDefaultStreamFlow)
	}
	http2setDefault(&.MaxReadFrameSize, http2minMaxFrameSize, http2maxFrameSize, http2defaultMaxReadFrameSize)
	http2setDefault(&.PingTimeout, 1, math.MaxInt64, 15*time.Second)
}

// adjustHTTP1MaxHeaderSize converts a limit in bytes on the size of an HTTP/1 header
// to an HTTP/2 MAX_HEADER_LIST_SIZE value.
func http2adjustHTTP1MaxHeaderSize( int64) int64 {
	// http2's count is in a slightly different unit and includes 32 bytes per pair.
	// So, take the net/http.Server value and pad it up a bit, assuming 10 headers.
	const  = 32 // per http2 spec
	const  = 10   // conservative
	return  + *
}

// fillNetHTTPServerConfig sets fields in conf from srv.HTTP2.
func http2fillNetHTTPServerConfig( *http2http2Config,  *Server) {
	http2fillNetHTTPConfig(, .HTTP2)
}

// fillNetHTTPServerConfig sets fields in conf from tr.HTTP2.
func http2fillNetHTTPTransportConfig( *http2http2Config,  *Transport) {
	http2fillNetHTTPConfig(, .HTTP2)
}

func http2fillNetHTTPConfig( *http2http2Config,  *HTTP2Config) {
	if  == nil {
		return
	}
	if .MaxConcurrentStreams != 0 {
		.MaxConcurrentStreams = uint32(.MaxConcurrentStreams)
	}
	if .MaxEncoderHeaderTableSize != 0 {
		.MaxEncoderHeaderTableSize = uint32(.MaxEncoderHeaderTableSize)
	}
	if .MaxDecoderHeaderTableSize != 0 {
		.MaxDecoderHeaderTableSize = uint32(.MaxDecoderHeaderTableSize)
	}
	if .MaxConcurrentStreams != 0 {
		.MaxConcurrentStreams = uint32(.MaxConcurrentStreams)
	}
	if .MaxReadFrameSize != 0 {
		.MaxReadFrameSize = uint32(.MaxReadFrameSize)
	}
	if .MaxReceiveBufferPerConnection != 0 {
		.MaxUploadBufferPerConnection = int32(.MaxReceiveBufferPerConnection)
	}
	if .MaxReceiveBufferPerStream != 0 {
		.MaxUploadBufferPerStream = int32(.MaxReceiveBufferPerStream)
	}
	if .SendPingTimeout != 0 {
		.SendPingTimeout = .SendPingTimeout
	}
	if .PingTimeout != 0 {
		.PingTimeout = .PingTimeout
	}
	if .WriteByteTimeout != 0 {
		.WriteByteTimeout = .WriteByteTimeout
	}
	if .PermitProhibitedCipherSuites {
		.PermitProhibitedCipherSuites = true
	}
	if .CountError != nil {
		.CountError = .CountError
	}
}

// Buffer chunks are allocated from a pool to reduce pressure on GC.
// The maximum wasted space per dataBuffer is 2x the largest size class,
// which happens when the dataBuffer has multiple chunks and there is
// one unread byte in both the first and last chunks. We use a few size
// classes to minimize overheads for servers that typically receive very
// small request bodies.
//
// TODO: Benchmark to determine if the pools are necessary. The GC may have
// improved enough that we can instead allocate chunks like this:
// make([]byte, max(16<<10, expectedBytesRemaining))
var http2dataChunkPools = [...]sync.Pool{
	{New: func() interface{} { return new([1 << 10]byte) }},
	{New: func() interface{} { return new([2 << 10]byte) }},
	{New: func() interface{} { return new([4 << 10]byte) }},
	{New: func() interface{} { return new([8 << 10]byte) }},
	{New: func() interface{} { return new([16 << 10]byte) }},
}

func http2getDataBufferChunk( int64) []byte {
	switch {
	case  <= 1<<10:
		return http2dataChunkPools[0].Get().(*[1 << 10]byte)[:]
	case  <= 2<<10:
		return http2dataChunkPools[1].Get().(*[2 << 10]byte)[:]
	case  <= 4<<10:
		return http2dataChunkPools[2].Get().(*[4 << 10]byte)[:]
	case  <= 8<<10:
		return http2dataChunkPools[3].Get().(*[8 << 10]byte)[:]
	default:
		return http2dataChunkPools[4].Get().(*[16 << 10]byte)[:]
	}
}

func http2putDataBufferChunk( []byte) {
	switch len() {
	case 1 << 10:
		http2dataChunkPools[0].Put((*[1 << 10]byte)())
	case 2 << 10:
		http2dataChunkPools[1].Put((*[2 << 10]byte)())
	case 4 << 10:
		http2dataChunkPools[2].Put((*[4 << 10]byte)())
	case 8 << 10:
		http2dataChunkPools[3].Put((*[8 << 10]byte)())
	case 16 << 10:
		http2dataChunkPools[4].Put((*[16 << 10]byte)())
	default:
		panic(fmt.Sprintf("unexpected buffer len=%v", len()))
	}
}

// dataBuffer is an io.ReadWriter backed by a list of data chunks.
// Each dataBuffer is used to read DATA frames on a single stream.
// The buffer is divided into chunks so the server can limit the
// total memory used by a single connection without limiting the
// request body size on any single stream.
type http2dataBuffer struct {
	chunks   [][]byte
	r        int   // next byte to read is chunks[0][r]
	w        int   // next byte to write is chunks[len(chunks)-1][w]
	size     int   // total buffered bytes
	expected int64 // we expect at least this many bytes in future Write calls (ignored if <= 0)
}

var http2errReadEmpty = errors.New("read from empty dataBuffer")

// Read copies bytes from the buffer into p.
// It is an error to read when no data is available.
func ( *http2dataBuffer) ( []byte) (int, error) {
	if .size == 0 {
		return 0, http2errReadEmpty
	}
	var  int
	for len() > 0 && .size > 0 {
		 := .bytesFromFirstChunk()
		 := copy(, )
		 = [:]
		 += 
		.r += 
		.size -= 
		// If the first chunk has been consumed, advance to the next chunk.
		if .r == len(.chunks[0]) {
			http2putDataBufferChunk(.chunks[0])
			 := len(.chunks) - 1
			copy(.chunks[:], .chunks[1:])
			.chunks[] = nil
			.chunks = .chunks[:]
			.r = 0
		}
	}
	return , nil
}

func ( *http2dataBuffer) () []byte {
	if len(.chunks) == 1 {
		return .chunks[0][.r:.w]
	}
	return .chunks[0][.r:]
}

// Len returns the number of bytes of the unread portion of the buffer.
func ( *http2dataBuffer) () int {
	return .size
}

// Write appends p to the buffer.
func ( *http2dataBuffer) ( []byte) (int, error) {
	 := len()
	for len() > 0 {
		// If the last chunk is empty, allocate a new chunk. Try to allocate
		// enough to fully copy p plus any additional bytes we expect to
		// receive. However, this may allocate less than len(p).
		 := int64(len())
		if .expected >  {
			 = .expected
		}
		 := .lastChunkOrAlloc()
		 := copy([.w:], )
		 = [:]
		.w += 
		.size += 
		.expected -= int64()
	}
	return , nil
}

func ( *http2dataBuffer) ( int64) []byte {
	if len(.chunks) != 0 {
		 := .chunks[len(.chunks)-1]
		if .w < len() {
			return 
		}
	}
	 := http2getDataBufferChunk()
	.chunks = append(.chunks, )
	.w = 0
	return 
}

// An ErrCode is an unsigned 32-bit error code as defined in the HTTP/2 spec.
type http2ErrCode uint32

const (
	http2ErrCodeNo                 http2ErrCode = 0x0
	http2ErrCodeProtocol           http2ErrCode = 0x1
	http2ErrCodeInternal           http2ErrCode = 0x2
	http2ErrCodeFlowControl        http2ErrCode = 0x3
	http2ErrCodeSettingsTimeout    http2ErrCode = 0x4
	http2ErrCodeStreamClosed       http2ErrCode = 0x5
	http2ErrCodeFrameSize          http2ErrCode = 0x6
	http2ErrCodeRefusedStream      http2ErrCode = 0x7
	http2ErrCodeCancel             http2ErrCode = 0x8
	http2ErrCodeCompression        http2ErrCode = 0x9
	http2ErrCodeConnect            http2ErrCode = 0xa
	http2ErrCodeEnhanceYourCalm    http2ErrCode = 0xb
	http2ErrCodeInadequateSecurity http2ErrCode = 0xc
	http2ErrCodeHTTP11Required     http2ErrCode = 0xd
)

var http2errCodeName = map[http2ErrCode]string{
	http2ErrCodeNo:                 "NO_ERROR",
	http2ErrCodeProtocol:           "PROTOCOL_ERROR",
	http2ErrCodeInternal:           "INTERNAL_ERROR",
	http2ErrCodeFlowControl:        "FLOW_CONTROL_ERROR",
	http2ErrCodeSettingsTimeout:    "SETTINGS_TIMEOUT",
	http2ErrCodeStreamClosed:       "STREAM_CLOSED",
	http2ErrCodeFrameSize:          "FRAME_SIZE_ERROR",
	http2ErrCodeRefusedStream:      "REFUSED_STREAM",
	http2ErrCodeCancel:             "CANCEL",
	http2ErrCodeCompression:        "COMPRESSION_ERROR",
	http2ErrCodeConnect:            "CONNECT_ERROR",
	http2ErrCodeEnhanceYourCalm:    "ENHANCE_YOUR_CALM",
	http2ErrCodeInadequateSecurity: "INADEQUATE_SECURITY",
	http2ErrCodeHTTP11Required:     "HTTP_1_1_REQUIRED",
}

func ( http2ErrCode) () string {
	if ,  := http2errCodeName[];  {
		return 
	}
	return fmt.Sprintf("unknown error code 0x%x", uint32())
}

func ( http2ErrCode) () string {
	if ,  := http2errCodeName[];  {
		return 
	}
	return fmt.Sprintf("ERR_UNKNOWN_%d", uint32())
}

// ConnectionError is an error that results in the termination of the
// entire connection.
type http2ConnectionError http2ErrCode

func ( http2ConnectionError) () string {
	return fmt.Sprintf("connection error: %s", http2ErrCode())
}

// StreamError is an error that only affects one stream within an
// HTTP/2 connection.
type http2StreamError struct {
	StreamID uint32
	Code     http2ErrCode
	Cause    error // optional additional detail
}

// errFromPeer is a sentinel error value for StreamError.Cause to
// indicate that the StreamError was sent from the peer over the wire
// and wasn't locally generated in the Transport.
var http2errFromPeer = errors.New("received from peer")

func http2streamError( uint32,  http2ErrCode) http2StreamError {
	return http2StreamError{StreamID: , Code: }
}

func ( http2StreamError) () string {
	if .Cause != nil {
		return fmt.Sprintf("stream error: stream ID %d; %v; %v", .StreamID, .Code, .Cause)
	}
	return fmt.Sprintf("stream error: stream ID %d; %v", .StreamID, .Code)
}

// 6.9.1 The Flow Control Window
// "If a sender receives a WINDOW_UPDATE that causes a flow control
// window to exceed this maximum it MUST terminate either the stream
// or the connection, as appropriate. For streams, [...]; for the
// connection, a GOAWAY frame with a FLOW_CONTROL_ERROR code."
type http2goAwayFlowError struct{}

func (http2goAwayFlowError) () string { return "connection exceeded flow control window size" }

// connError represents an HTTP/2 ConnectionError error code, along
// with a string (for debugging) explaining why.
//
// Errors of this type are only returned by the frame parser functions
// and converted into ConnectionError(Code), after stashing away
// the Reason into the Framer's errDetail field, accessible via
// the (*Framer).ErrorDetail method.
type http2connError struct {
	Code   http2ErrCode // the ConnectionError error code
	Reason string       // additional reason
}

func ( http2connError) () string {
	return fmt.Sprintf("http2: connection error: %v: %v", .Code, .Reason)
}

type http2pseudoHeaderError string

func ( http2pseudoHeaderError) () string {
	return fmt.Sprintf("invalid pseudo-header %q", string())
}

type http2duplicatePseudoHeaderError string

func ( http2duplicatePseudoHeaderError) () string {
	return fmt.Sprintf("duplicate pseudo-header %q", string())
}

type http2headerFieldNameError string

func ( http2headerFieldNameError) () string {
	return fmt.Sprintf("invalid header field name %q", string())
}

type http2headerFieldValueError string

func ( http2headerFieldValueError) () string {
	return fmt.Sprintf("invalid header field value for %q", string())
}

var (
	http2errMixPseudoHeaderTypes = errors.New("mix of request and response pseudo headers")
	http2errPseudoAfterRegular   = errors.New("pseudo header field after regular")
)

// inflowMinRefresh is the minimum number of bytes we'll send for a
// flow control window update.
const http2inflowMinRefresh = 4 << 10

// inflow accounts for an inbound flow control window.
// It tracks both the latest window sent to the peer (used for enforcement)
// and the accumulated unsent window.
type http2inflow struct {
	avail  int32
	unsent int32
}

// init sets the initial window.
func ( *http2inflow) ( int32) {
	.avail = 
}

// add adds n bytes to the window, with a maximum window size of max,
// indicating that the peer can now send us more data.
// For example, the user read from a {Request,Response} body and consumed
// some of the buffered data, so the peer can now send more.
// It returns the number of bytes to send in a WINDOW_UPDATE frame to the peer.
// Window updates are accumulated and sent when the unsent capacity
// is at least inflowMinRefresh or will at least double the peer's available window.
func ( *http2inflow) ( int) ( int32) {
	if  < 0 {
		panic("negative update")
	}
	 := int64(.unsent) + int64()
	// "A sender MUST NOT allow a flow-control window to exceed 2^31-1 octets."
	// RFC 7540 Section 6.9.1.
	const  = 1<<31 - 1
	if +int64(.avail) >  {
		panic("flow control update exceeds maximum window size")
	}
	.unsent = int32()
	if .unsent < http2inflowMinRefresh && .unsent < .avail {
		// If there aren't at least inflowMinRefresh bytes of window to send,
		// and this update won't at least double the window, buffer the update for later.
		return 0
	}
	.avail += .unsent
	.unsent = 0
	return int32()
}

// take attempts to take n bytes from the peer's flow control window.
// It reports whether the window has available capacity.
func ( *http2inflow) ( uint32) bool {
	if  > uint32(.avail) {
		return false
	}
	.avail -= int32()
	return true
}

// takeInflows attempts to take n bytes from two inflows,
// typically connection-level and stream-level flows.
// It reports whether both windows have available capacity.
func http2takeInflows(,  *http2inflow,  uint32) bool {
	if  > uint32(.avail) ||  > uint32(.avail) {
		return false
	}
	.avail -= int32()
	.avail -= int32()
	return true
}

// outflow is the outbound flow control window's size.
type http2outflow struct {
	_ http2incomparable

	// n is the number of DATA bytes we're allowed to send.
	// An outflow is kept both on a conn and a per-stream.
	n int32

	// conn points to the shared connection-level outflow that is
	// shared by all streams on that conn. It is nil for the outflow
	// that's on the conn directly.
	conn *http2outflow
}

func ( *http2outflow) ( *http2outflow) { .conn =  }

func ( *http2outflow) () int32 {
	 := .n
	if .conn != nil && .conn.n <  {
		 = .conn.n
	}
	return 
}

func ( *http2outflow) ( int32) {
	if  > .available() {
		panic("internal error: took too much")
	}
	.n -= 
	if .conn != nil {
		.conn.n -= 
	}
}

// add adds n bytes (positive or negative) to the flow control window.
// It returns false if the sum would exceed 2^31-1.
func ( *http2outflow) ( int32) bool {
	 := .n + 
	if ( > ) == (.n > 0) {
		.n = 
		return true
	}
	return false
}

const http2frameHeaderLen = 9

var http2padZeros = make([]byte, 255) // zeros for padding

// A FrameType is a registered frame type as defined in
// https://httpwg.org/specs/rfc7540.html#rfc.section.11.2
type http2FrameType uint8

const (
	http2FrameData         http2FrameType = 0x0
	http2FrameHeaders      http2FrameType = 0x1
	http2FramePriority     http2FrameType = 0x2
	http2FrameRSTStream    http2FrameType = 0x3
	http2FrameSettings     http2FrameType = 0x4
	http2FramePushPromise  http2FrameType = 0x5
	http2FramePing         http2FrameType = 0x6
	http2FrameGoAway       http2FrameType = 0x7
	http2FrameWindowUpdate http2FrameType = 0x8
	http2FrameContinuation http2FrameType = 0x9
)

var http2frameName = map[http2FrameType]string{
	http2FrameData:         "DATA",
	http2FrameHeaders:      "HEADERS",
	http2FramePriority:     "PRIORITY",
	http2FrameRSTStream:    "RST_STREAM",
	http2FrameSettings:     "SETTINGS",
	http2FramePushPromise:  "PUSH_PROMISE",
	http2FramePing:         "PING",
	http2FrameGoAway:       "GOAWAY",
	http2FrameWindowUpdate: "WINDOW_UPDATE",
	http2FrameContinuation: "CONTINUATION",
}

func ( http2FrameType) () string {
	if ,  := http2frameName[];  {
		return 
	}
	return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", uint8())
}

// Flags is a bitmask of HTTP/2 flags.
// The meaning of flags varies depending on the frame type.
type http2Flags uint8

// Has reports whether f contains all (0 or more) flags in v.
func ( http2Flags) ( http2Flags) bool {
	return ( & ) == 
}

// Frame-specific FrameHeader flag bits.
const (
	// Data Frame
	http2FlagDataEndStream http2Flags = 0x1
	http2FlagDataPadded    http2Flags = 0x8

	// Headers Frame
	http2FlagHeadersEndStream  http2Flags = 0x1
	http2FlagHeadersEndHeaders http2Flags = 0x4
	http2FlagHeadersPadded     http2Flags = 0x8
	http2FlagHeadersPriority   http2Flags = 0x20

	// Settings Frame
	http2FlagSettingsAck http2Flags = 0x1

	// Ping Frame
	http2FlagPingAck http2Flags = 0x1

	// Continuation Frame
	http2FlagContinuationEndHeaders http2Flags = 0x4

	http2FlagPushPromiseEndHeaders http2Flags = 0x4
	http2FlagPushPromisePadded     http2Flags = 0x8
)

var http2flagName = map[http2FrameType]map[http2Flags]string{
	http2FrameData: {
		http2FlagDataEndStream: "END_STREAM",
		http2FlagDataPadded:    "PADDED",
	},
	http2FrameHeaders: {
		http2FlagHeadersEndStream:  "END_STREAM",
		http2FlagHeadersEndHeaders: "END_HEADERS",
		http2FlagHeadersPadded:     "PADDED",
		http2FlagHeadersPriority:   "PRIORITY",
	},
	http2FrameSettings: {
		http2FlagSettingsAck: "ACK",
	},
	http2FramePing: {
		http2FlagPingAck: "ACK",
	},
	http2FrameContinuation: {
		http2FlagContinuationEndHeaders: "END_HEADERS",
	},
	http2FramePushPromise: {
		http2FlagPushPromiseEndHeaders: "END_HEADERS",
		http2FlagPushPromisePadded:     "PADDED",
	},
}

// a frameParser parses a frame given its FrameHeader and payload
// bytes. The length of payload will always equal fh.Length (which
// might be 0).
type http2frameParser func(fc *http2frameCache, fh http2FrameHeader, countError func(string), payload []byte) (http2Frame, error)

var http2frameParsers = map[http2FrameType]http2frameParser{
	http2FrameData:         http2parseDataFrame,
	http2FrameHeaders:      http2parseHeadersFrame,
	http2FramePriority:     http2parsePriorityFrame,
	http2FrameRSTStream:    http2parseRSTStreamFrame,
	http2FrameSettings:     http2parseSettingsFrame,
	http2FramePushPromise:  http2parsePushPromise,
	http2FramePing:         http2parsePingFrame,
	http2FrameGoAway:       http2parseGoAwayFrame,
	http2FrameWindowUpdate: http2parseWindowUpdateFrame,
	http2FrameContinuation: http2parseContinuationFrame,
}

func http2typeFrameParser( http2FrameType) http2frameParser {
	if  := http2frameParsers[];  != nil {
		return 
	}
	return http2parseUnknownFrame
}

// A FrameHeader is the 9 byte header of all HTTP/2 frames.
//
// See https://httpwg.org/specs/rfc7540.html#FrameHeader
type http2FrameHeader struct {
	valid bool // caller can access []byte fields in the Frame

	// Type is the 1 byte frame type. There are ten standard frame
	// types, but extension frame types may be written by WriteRawFrame
	// and will be returned by ReadFrame (as UnknownFrame).
	Type http2FrameType

	// Flags are the 1 byte of 8 potential bit flags per frame.
	// They are specific to the frame type.
	Flags http2Flags

	// Length is the length of the frame, not including the 9 byte header.
	// The maximum size is one byte less than 16MB (uint24), but only
	// frames up to 16KB are allowed without peer agreement.
	Length uint32

	// StreamID is which stream this frame is for. Certain frames
	// are not stream-specific, in which case this field is 0.
	StreamID uint32
}

// Header returns h. It exists so FrameHeaders can be embedded in other
// specific frame types and implement the Frame interface.
func ( http2FrameHeader) () http2FrameHeader { return  }

func ( http2FrameHeader) () string {
	var  bytes.Buffer
	.WriteString("[FrameHeader ")
	.writeDebug(&)
	.WriteByte(']')
	return .String()
}

func ( http2FrameHeader) ( *bytes.Buffer) {
	.WriteString(.Type.String())
	if .Flags != 0 {
		.WriteString(" flags=")
		 := 0
		for  := uint8(0);  < 8; ++ {
			if .Flags&(1<<) == 0 {
				continue
			}
			++
			if  > 1 {
				.WriteByte('|')
			}
			 := http2flagName[.Type][http2Flags(1<<)]
			if  != "" {
				.WriteString()
			} else {
				fmt.Fprintf(, "0x%x", 1<<)
			}
		}
	}
	if .StreamID != 0 {
		fmt.Fprintf(, " stream=%d", .StreamID)
	}
	fmt.Fprintf(, " len=%d", .Length)
}

func ( *http2FrameHeader) () {
	if !.valid {
		panic("Frame accessor called on non-owned Frame")
	}
}

func ( *http2FrameHeader) () { .valid = false }

// frame header bytes.
// Used only by ReadFrameHeader.
var http2fhBytes = sync.Pool{
	New: func() interface{} {
		 := make([]byte, http2frameHeaderLen)
		return &
	},
}

// ReadFrameHeader reads 9 bytes from r and returns a FrameHeader.
// Most users should use Framer.ReadFrame instead.
func http2ReadFrameHeader( io.Reader) (http2FrameHeader, error) {
	 := http2fhBytes.Get().(*[]byte)
	defer http2fhBytes.Put()
	return http2readFrameHeader(*, )
}

func http2readFrameHeader( []byte,  io.Reader) (http2FrameHeader, error) {
	,  := io.ReadFull(, [:http2frameHeaderLen])
	if  != nil {
		return http2FrameHeader{}, 
	}
	return http2FrameHeader{
		Length:   (uint32([0])<<16 | uint32([1])<<8 | uint32([2])),
		Type:     http2FrameType([3]),
		Flags:    http2Flags([4]),
		StreamID: binary.BigEndian.Uint32([5:]) & (1<<31 - 1),
		valid:    true,
	}, nil
}

// A Frame is the base interface implemented by all frame types.
// Callers will generally type-assert the specific frame type:
// *HeadersFrame, *SettingsFrame, *WindowUpdateFrame, etc.
//
// Frames are only valid until the next call to Framer.ReadFrame.
type http2Frame interface {
	Header() http2FrameHeader

	// invalidate is called by Framer.ReadFrame to make this
	// frame's buffers as being invalid, since the subsequent
	// frame will reuse them.
	invalidate()
}

// A Framer reads and writes Frames.
type http2Framer struct {
	r         io.Reader
	lastFrame http2Frame
	errDetail error

	// countError is a non-nil func that's called on a frame parse
	// error with some unique error path token. It's initialized
	// from Transport.CountError or Server.CountError.
	countError func(errToken string)

	// lastHeaderStream is non-zero if the last frame was an
	// unfinished HEADERS/CONTINUATION.
	lastHeaderStream uint32

	maxReadSize uint32
	headerBuf   [http2frameHeaderLen]byte

	// TODO: let getReadBuf be configurable, and use a less memory-pinning
	// allocator in server.go to minimize memory pinned for many idle conns.
	// Will probably also need to make frame invalidation have a hook too.
	getReadBuf func(size uint32) []byte
	readBuf    []byte // cache for default getReadBuf

	maxWriteSize uint32 // zero means unlimited; TODO: implement

	w    io.Writer
	wbuf []byte

	// AllowIllegalWrites permits the Framer's Write methods to
	// write frames that do not conform to the HTTP/2 spec. This
	// permits using the Framer to test other HTTP/2
	// implementations' conformance to the spec.
	// If false, the Write methods will prefer to return an error
	// rather than comply.
	AllowIllegalWrites bool

	// AllowIllegalReads permits the Framer's ReadFrame method
	// to return non-compliant frames or frame orders.
	// This is for testing and permits using the Framer to test
	// other HTTP/2 implementations' conformance to the spec.
	// It is not compatible with ReadMetaHeaders.
	AllowIllegalReads bool

	// ReadMetaHeaders if non-nil causes ReadFrame to merge
	// HEADERS and CONTINUATION frames together and return
	// MetaHeadersFrame instead.
	ReadMetaHeaders *hpack.Decoder

	// MaxHeaderListSize is the http2 MAX_HEADER_LIST_SIZE.
	// It's used only if ReadMetaHeaders is set; 0 means a sane default
	// (currently 16MB)
	// If the limit is hit, MetaHeadersFrame.Truncated is set true.
	MaxHeaderListSize uint32

	// TODO: track which type of frame & with which flags was sent
	// last. Then return an error (unless AllowIllegalWrites) if
	// we're in the middle of a header block and a
	// non-Continuation or Continuation on a different stream is
	// attempted to be written.

	logReads, logWrites bool

	debugFramer       *http2Framer // only use for logging written writes
	debugFramerBuf    *bytes.Buffer
	debugReadLoggerf  func(string, ...interface{})
	debugWriteLoggerf func(string, ...interface{})

	frameCache *http2frameCache // nil if frames aren't reused (default)
}

func ( *http2Framer) () uint32 {
	if .MaxHeaderListSize == 0 {
		return 16 << 20 // sane default, per docs
	}
	return .MaxHeaderListSize
}

func ( *http2Framer) ( http2FrameType,  http2Flags,  uint32) {
	// Write the FrameHeader.
	.wbuf = append(.wbuf[:0],
		0, // 3 bytes of length, filled in in endWrite
		0,
		0,
		byte(),
		byte(),
		byte(>>24),
		byte(>>16),
		byte(>>8),
		byte())
}

func ( *http2Framer) () error {
	// Now that we know the final size, fill in the FrameHeader in
	// the space previously reserved for it. Abuse append.
	 := len(.wbuf) - http2frameHeaderLen
	if  >= (1 << 24) {
		return http2ErrFrameTooLarge
	}
	_ = append(.wbuf[:0],
		byte(>>16),
		byte(>>8),
		byte())
	if .logWrites {
		.logWrite()
	}

	,  := .w.Write(.wbuf)
	if  == nil &&  != len(.wbuf) {
		 = io.ErrShortWrite
	}
	return 
}

func ( *http2Framer) () {
	if .debugFramer == nil {
		.debugFramerBuf = new(bytes.Buffer)
		.debugFramer = http2NewFramer(nil, .debugFramerBuf)
		.debugFramer.logReads = false // we log it ourselves, saying "wrote" below
		// Let us read anything, even if we accidentally wrote it
		// in the wrong order:
		.debugFramer.AllowIllegalReads = true
	}
	.debugFramerBuf.Write(.wbuf)
	,  := .debugFramer.ReadFrame()
	if  != nil {
		.debugWriteLoggerf("http2: Framer %p: failed to decode just-written frame", )
		return
	}
	.debugWriteLoggerf("http2: Framer %p: wrote %v", , http2summarizeFrame())
}

func ( *http2Framer) ( byte) { .wbuf = append(.wbuf, ) }

func ( *http2Framer) ( []byte) { .wbuf = append(.wbuf, ...) }

func ( *http2Framer) ( uint16) { .wbuf = append(.wbuf, byte(>>8), byte()) }

func ( *http2Framer) ( uint32) {
	.wbuf = append(.wbuf, byte(>>24), byte(>>16), byte(>>8), byte())
}

const (
	http2minMaxFrameSize = 1 << 14
	http2maxFrameSize    = 1<<24 - 1
)

// SetReuseFrames allows the Framer to reuse Frames.
// If called on a Framer, Frames returned by calls to ReadFrame are only
// valid until the next call to ReadFrame.
func ( *http2Framer) () {
	if .frameCache != nil {
		return
	}
	.frameCache = &http2frameCache{}
}

type http2frameCache struct {
	dataFrame http2DataFrame
}

func ( *http2frameCache) () *http2DataFrame {
	if  == nil {
		return &http2DataFrame{}
	}
	return &.dataFrame
}

// NewFramer returns a Framer that writes frames to w and reads them from r.
func http2NewFramer( io.Writer,  io.Reader) *http2Framer {
	 := &http2Framer{
		w:                 ,
		r:                 ,
		countError:        func(string) {},
		logReads:          http2logFrameReads,
		logWrites:         http2logFrameWrites,
		debugReadLoggerf:  log.Printf,
		debugWriteLoggerf: log.Printf,
	}
	.getReadBuf = func( uint32) []byte {
		if cap(.readBuf) >= int() {
			return .readBuf[:]
		}
		.readBuf = make([]byte, )
		return .readBuf
	}
	.SetMaxReadFrameSize(http2maxFrameSize)
	return 
}

// SetMaxReadFrameSize sets the maximum size of a frame
// that will be read by a subsequent call to ReadFrame.
// It is the caller's responsibility to advertise this
// limit with a SETTINGS frame.
func ( *http2Framer) ( uint32) {
	if  > http2maxFrameSize {
		 = http2maxFrameSize
	}
	.maxReadSize = 
}

// ErrorDetail returns a more detailed error of the last error
// returned by Framer.ReadFrame. For instance, if ReadFrame
// returns a StreamError with code PROTOCOL_ERROR, ErrorDetail
// will say exactly what was invalid. ErrorDetail is not guaranteed
// to return a non-nil value and like the rest of the http2 package,
// its return value is not protected by an API compatibility promise.
// ErrorDetail is reset after the next call to ReadFrame.
func ( *http2Framer) () error {
	return .errDetail
}

// ErrFrameTooLarge is returned from Framer.ReadFrame when the peer
// sends a frame that is larger than declared with SetMaxReadFrameSize.
var http2ErrFrameTooLarge = errors.New("http2: frame too large")

// terminalReadFrameError reports whether err is an unrecoverable
// error from ReadFrame and no other frames should be read.
func http2terminalReadFrameError( error) bool {
	if ,  := .(http2StreamError);  {
		return false
	}
	return  != nil
}

// ReadFrame reads a single frame. The returned Frame is only valid
// until the next call to ReadFrame.
//
// If the frame is larger than previously set with SetMaxReadFrameSize, the
// returned error is ErrFrameTooLarge. Other errors may be of type
// ConnectionError, StreamError, or anything else from the underlying
// reader.
//
// If ReadFrame returns an error and a non-nil Frame, the Frame's StreamID
// indicates the stream responsible for the error.
func ( *http2Framer) () (http2Frame, error) {
	.errDetail = nil
	if .lastFrame != nil {
		.lastFrame.invalidate()
	}
	,  := http2readFrameHeader(.headerBuf[:], .r)
	if  != nil {
		return nil, 
	}
	if .Length > .maxReadSize {
		return nil, http2ErrFrameTooLarge
	}
	 := .getReadBuf(.Length)
	if ,  := io.ReadFull(.r, );  != nil {
		return nil, 
	}
	,  := http2typeFrameParser(.Type)(.frameCache, , .countError, )
	if  != nil {
		if ,  := .(http2connError);  {
			return nil, .connError(.Code, .Reason)
		}
		return nil, 
	}
	if  := .checkFrameOrder();  != nil {
		return nil, 
	}
	if .logReads {
		.debugReadLoggerf("http2: Framer %p: read %v", , http2summarizeFrame())
	}
	if .Type == http2FrameHeaders && .ReadMetaHeaders != nil {
		return .readMetaFrame(.(*http2HeadersFrame))
	}
	return , nil
}

// connError returns ConnectionError(code) but first
// stashes away a public reason to the caller can optionally relay it
// to the peer before hanging up on them. This might help others debug
// their implementations.
func ( *http2Framer) ( http2ErrCode,  string) error {
	.errDetail = errors.New()
	return http2ConnectionError()
}

// checkFrameOrder reports an error if f is an invalid frame to return
// next from ReadFrame. Mostly it checks whether HEADERS and
// CONTINUATION frames are contiguous.
func ( *http2Framer) ( http2Frame) error {
	 := .lastFrame
	.lastFrame = 
	if .AllowIllegalReads {
		return nil
	}

	 := .Header()
	if .lastHeaderStream != 0 {
		if .Type != http2FrameContinuation {
			return .connError(http2ErrCodeProtocol,
				fmt.Sprintf("got %s for stream %d; expected CONTINUATION following %s for stream %d",
					.Type, .StreamID,
					.Header().Type, .lastHeaderStream))
		}
		if .StreamID != .lastHeaderStream {
			return .connError(http2ErrCodeProtocol,
				fmt.Sprintf("got CONTINUATION for stream %d; expected stream %d",
					.StreamID, .lastHeaderStream))
		}
	} else if .Type == http2FrameContinuation {
		return .connError(http2ErrCodeProtocol, fmt.Sprintf("unexpected CONTINUATION for stream %d", .StreamID))
	}

	switch .Type {
	case http2FrameHeaders, http2FrameContinuation:
		if .Flags.Has(http2FlagHeadersEndHeaders) {
			.lastHeaderStream = 0
		} else {
			.lastHeaderStream = .StreamID
		}
	}

	return nil
}

// A DataFrame conveys arbitrary, variable-length sequences of octets
// associated with a stream.
// See https://httpwg.org/specs/rfc7540.html#rfc.section.6.1
type http2DataFrame struct {
	http2FrameHeader
	data []byte
}

func ( *http2DataFrame) () bool {
	return .http2FrameHeader.Flags.Has(http2FlagDataEndStream)
}

// Data returns the frame's data octets, not including any padding
// size byte or padding suffix bytes.
// The caller must not retain the returned memory past the next
// call to ReadFrame.
func ( *http2DataFrame) () []byte {
	.checkValid()
	return .data
}

func http2parseDataFrame( *http2frameCache,  http2FrameHeader,  func(string),  []byte) (http2Frame, error) {
	if .StreamID == 0 {
		// DATA frames MUST be associated with a stream. If a
		// DATA frame is received whose stream identifier
		// field is 0x0, the recipient MUST respond with a
		// connection error (Section 5.4.1) of type
		// PROTOCOL_ERROR.
		("frame_data_stream_0")
		return nil, http2connError{http2ErrCodeProtocol, "DATA frame with stream ID 0"}
	}
	 := .getDataFrame()
	.http2FrameHeader = 

	var  byte
	if .Flags.Has(http2FlagDataPadded) {
		var  error
		, ,  = http2readByte()
		if  != nil {
			("frame_data_pad_byte_short")
			return nil, 
		}
	}
	if int() > len() {
		// If the length of the padding is greater than the
		// length of the frame payload, the recipient MUST
		// treat this as a connection error.
		// Filed: https://github.com/http2/http2-spec/issues/610
		("frame_data_pad_too_big")
		return nil, http2connError{http2ErrCodeProtocol, "pad size larger than data payload"}
	}
	.data = [:len()-int()]
	return , nil
}

var (
	http2errStreamID    = errors.New("invalid stream ID")
	http2errDepStreamID = errors.New("invalid dependent stream ID")
	http2errPadLength   = errors.New("pad length too large")
	http2errPadBytes    = errors.New("padding bytes must all be zeros unless AllowIllegalWrites is enabled")
)

func http2validStreamIDOrZero( uint32) bool {
	return &(1<<31) == 0
}

func http2validStreamID( uint32) bool {
	return  != 0 && &(1<<31) == 0
}

// WriteData writes a DATA frame.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility not to violate the maximum frame size
// and to not call other Write methods concurrently.
func ( *http2Framer) ( uint32,  bool,  []byte) error {
	return .WriteDataPadded(, , , nil)
}

// WriteDataPadded writes a DATA frame with optional padding.
//
// If pad is nil, the padding bit is not sent.
// The length of pad must not exceed 255 bytes.
// The bytes of pad must all be zero, unless f.AllowIllegalWrites is set.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility not to violate the maximum frame size
// and to not call other Write methods concurrently.
func ( *http2Framer) ( uint32,  bool, ,  []byte) error {
	if  := .startWriteDataPadded(, , , );  != nil {
		return 
	}
	return .endWrite()
}

// startWriteDataPadded is WriteDataPadded, but only writes the frame to the Framer's internal buffer.
// The caller should call endWrite to flush the frame to the underlying writer.
func ( *http2Framer) ( uint32,  bool, ,  []byte) error {
	if !http2validStreamID() && !.AllowIllegalWrites {
		return http2errStreamID
	}
	if len() > 0 {
		if len() > 255 {
			return http2errPadLength
		}
		if !.AllowIllegalWrites {
			for ,  := range  {
				if  != 0 {
					// "Padding octets MUST be set to zero when sending."
					return http2errPadBytes
				}
			}
		}
	}
	var  http2Flags
	if  {
		 |= http2FlagDataEndStream
	}
	if  != nil {
		 |= http2FlagDataPadded
	}
	.startWrite(http2FrameData, , )
	if  != nil {
		.wbuf = append(.wbuf, byte(len()))
	}
	.wbuf = append(.wbuf, ...)
	.wbuf = append(.wbuf, ...)
	return nil
}

// A SettingsFrame conveys configuration parameters that affect how
// endpoints communicate, such as preferences and constraints on peer
// behavior.
//
// See https://httpwg.org/specs/rfc7540.html#SETTINGS
type http2SettingsFrame struct {
	http2FrameHeader
	p []byte
}

func http2parseSettingsFrame( *http2frameCache,  http2FrameHeader,  func(string),  []byte) (http2Frame, error) {
	if .Flags.Has(http2FlagSettingsAck) && .Length > 0 {
		// When this (ACK 0x1) bit is set, the payload of the
		// SETTINGS frame MUST be empty. Receipt of a
		// SETTINGS frame with the ACK flag set and a length
		// field value other than 0 MUST be treated as a
		// connection error (Section 5.4.1) of type
		// FRAME_SIZE_ERROR.
		("frame_settings_ack_with_length")
		return nil, http2ConnectionError(http2ErrCodeFrameSize)
	}
	if .StreamID != 0 {
		// SETTINGS frames always apply to a connection,
		// never a single stream. The stream identifier for a
		// SETTINGS frame MUST be zero (0x0).  If an endpoint
		// receives a SETTINGS frame whose stream identifier
		// field is anything other than 0x0, the endpoint MUST
		// respond with a connection error (Section 5.4.1) of
		// type PROTOCOL_ERROR.
		("frame_settings_has_stream")
		return nil, http2ConnectionError(http2ErrCodeProtocol)
	}
	if len()%6 != 0 {
		("frame_settings_mod_6")
		// Expecting even number of 6 byte settings.
		return nil, http2ConnectionError(http2ErrCodeFrameSize)
	}
	 := &http2SettingsFrame{http2FrameHeader: , p: }
	if ,  := .Value(http2SettingInitialWindowSize);  &&  > (1<<31)-1 {
		("frame_settings_window_size_too_big")
		// 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.
		return nil, http2ConnectionError(http2ErrCodeFlowControl)
	}
	return , nil
}

func ( *http2SettingsFrame) () bool {
	return .http2FrameHeader.Flags.Has(http2FlagSettingsAck)
}

func ( *http2SettingsFrame) ( http2SettingID) ( uint32,  bool) {
	.checkValid()
	for  := 0;  < .NumSettings(); ++ {
		if  := .Setting(); .ID ==  {
			return .Val, true
		}
	}
	return 0, false
}

// Setting returns the setting from the frame at the given 0-based index.
// The index must be >= 0 and less than f.NumSettings().
func ( *http2SettingsFrame) ( int) http2Setting {
	 := .p
	return http2Setting{
		ID:  http2SettingID(binary.BigEndian.Uint16([*6 : *6+2])),
		Val: binary.BigEndian.Uint32([*6+2 : *6+6]),
	}
}

func ( *http2SettingsFrame) () int { return len(.p) / 6 }

// HasDuplicates reports whether f contains any duplicate setting IDs.
func ( *http2SettingsFrame) () bool {
	 := .NumSettings()
	if  == 0 {
		return false
	}
	// If it's small enough (the common case), just do the n^2
	// thing and avoid a map allocation.
	if  < 10 {
		for  := 0;  < ; ++ {
			 := .Setting().ID
			for  :=  + 1;  < ; ++ {
				 := .Setting().ID
				if  ==  {
					return true
				}
			}
		}
		return false
	}
	 := map[http2SettingID]bool{}
	for  := 0;  < ; ++ {
		 := .Setting().ID
		if [] {
			return true
		}
		[] = true
	}
	return false
}

// ForeachSetting runs fn for each setting.
// It stops and returns the first error.
func ( *http2SettingsFrame) ( func(http2Setting) error) error {
	.checkValid()
	for  := 0;  < .NumSettings(); ++ {
		if  := (.Setting());  != nil {
			return 
		}
	}
	return nil
}

// WriteSettings writes a SETTINGS frame with zero or more settings
// specified and the ACK bit not set.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func ( *http2Framer) ( ...http2Setting) error {
	.startWrite(http2FrameSettings, 0, 0)
	for ,  := range  {
		.writeUint16(uint16(.ID))
		.writeUint32(.Val)
	}
	return .endWrite()
}

// WriteSettingsAck writes an empty SETTINGS frame with the ACK bit set.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func ( *http2Framer) () error {
	.startWrite(http2FrameSettings, http2FlagSettingsAck, 0)
	return .endWrite()
}

// A PingFrame is a mechanism for measuring a minimal round trip time
// from the sender, as well as determining whether an idle connection
// is still functional.
// See https://httpwg.org/specs/rfc7540.html#rfc.section.6.7
type http2PingFrame struct {
	http2FrameHeader
	Data [8]byte
}

func ( *http2PingFrame) () bool { return .Flags.Has(http2FlagPingAck) }

func http2parsePingFrame( *http2frameCache,  http2FrameHeader,  func(string),  []byte) (http2Frame, error) {
	if len() != 8 {
		("frame_ping_length")
		return nil, http2ConnectionError(http2ErrCodeFrameSize)
	}
	if .StreamID != 0 {
		("frame_ping_has_stream")
		return nil, http2ConnectionError(http2ErrCodeProtocol)
	}
	 := &http2PingFrame{http2FrameHeader: }
	copy(.Data[:], )
	return , nil
}

func ( *http2Framer) ( bool,  [8]byte) error {
	var  http2Flags
	if  {
		 = http2FlagPingAck
	}
	.startWrite(http2FramePing, , 0)
	.writeBytes([:])
	return .endWrite()
}

// A GoAwayFrame informs the remote peer to stop creating streams on this connection.
// See https://httpwg.org/specs/rfc7540.html#rfc.section.6.8
type http2GoAwayFrame struct {
	http2FrameHeader
	LastStreamID uint32
	ErrCode      http2ErrCode
	debugData    []byte
}

// DebugData returns any debug data in the GOAWAY frame. Its contents
// are not defined.
// The caller must not retain the returned memory past the next
// call to ReadFrame.
func ( *http2GoAwayFrame) () []byte {
	.checkValid()
	return .debugData
}

func http2parseGoAwayFrame( *http2frameCache,  http2FrameHeader,  func(string),  []byte) (http2Frame, error) {
	if .StreamID != 0 {
		("frame_goaway_has_stream")
		return nil, http2ConnectionError(http2ErrCodeProtocol)
	}
	if len() < 8 {
		("frame_goaway_short")
		return nil, http2ConnectionError(http2ErrCodeFrameSize)
	}
	return &http2GoAwayFrame{
		http2FrameHeader: ,
		LastStreamID:     binary.BigEndian.Uint32([:4]) & (1<<31 - 1),
		ErrCode:          http2ErrCode(binary.BigEndian.Uint32([4:8])),
		debugData:        [8:],
	}, nil
}

func ( *http2Framer) ( uint32,  http2ErrCode,  []byte) error {
	.startWrite(http2FrameGoAway, 0, 0)
	.writeUint32( & (1<<31 - 1))
	.writeUint32(uint32())
	.writeBytes()
	return .endWrite()
}

// An UnknownFrame is the frame type returned when the frame type is unknown
// or no specific frame type parser exists.
type http2UnknownFrame struct {
	http2FrameHeader
	p []byte
}

// Payload returns the frame's payload (after the header).  It is not
// valid to call this method after a subsequent call to
// Framer.ReadFrame, nor is it valid to retain the returned slice.
// The memory is owned by the Framer and is invalidated when the next
// frame is read.
func ( *http2UnknownFrame) () []byte {
	.checkValid()
	return .p
}

func http2parseUnknownFrame( *http2frameCache,  http2FrameHeader,  func(string),  []byte) (http2Frame, error) {
	return &http2UnknownFrame{, }, nil
}

// A WindowUpdateFrame is used to implement flow control.
// See https://httpwg.org/specs/rfc7540.html#rfc.section.6.9
type http2WindowUpdateFrame struct {
	http2FrameHeader
	Increment uint32 // never read with high bit set
}

func http2parseWindowUpdateFrame( *http2frameCache,  http2FrameHeader,  func(string),  []byte) (http2Frame, error) {
	if len() != 4 {
		("frame_windowupdate_bad_len")
		return nil, http2ConnectionError(http2ErrCodeFrameSize)
	}
	 := binary.BigEndian.Uint32([:4]) & 0x7fffffff // mask off high reserved bit
	if  == 0 {
		// A receiver MUST treat the receipt of a
		// WINDOW_UPDATE frame with an flow control window
		// increment of 0 as a stream error (Section 5.4.2) of
		// type PROTOCOL_ERROR; errors on the connection flow
		// control window MUST be treated as a connection
		// error (Section 5.4.1).
		if .StreamID == 0 {
			("frame_windowupdate_zero_inc_conn")
			return nil, http2ConnectionError(http2ErrCodeProtocol)
		}
		("frame_windowupdate_zero_inc_stream")
		return nil, http2streamError(.StreamID, http2ErrCodeProtocol)
	}
	return &http2WindowUpdateFrame{
		http2FrameHeader: ,
		Increment:        ,
	}, nil
}

// WriteWindowUpdate writes a WINDOW_UPDATE frame.
// The increment value must be between 1 and 2,147,483,647, inclusive.
// If the Stream ID is zero, the window update applies to the
// connection as a whole.
func ( *http2Framer) (,  uint32) error {
	// "The legal range for the increment to the flow control window is 1 to 2^31-1 (2,147,483,647) octets."
	if ( < 1 ||  > 2147483647) && !.AllowIllegalWrites {
		return errors.New("illegal window increment value")
	}
	.startWrite(http2FrameWindowUpdate, 0, )
	.writeUint32()
	return .endWrite()
}

// A HeadersFrame is used to open a stream and additionally carries a
// header block fragment.
type http2HeadersFrame struct {
	http2FrameHeader

	// Priority is set if FlagHeadersPriority is set in the FrameHeader.
	Priority http2PriorityParam

	headerFragBuf []byte // not owned
}

func ( *http2HeadersFrame) () []byte {
	.checkValid()
	return .headerFragBuf
}

func ( *http2HeadersFrame) () bool {
	return .http2FrameHeader.Flags.Has(http2FlagHeadersEndHeaders)
}

func ( *http2HeadersFrame) () bool {
	return .http2FrameHeader.Flags.Has(http2FlagHeadersEndStream)
}

func ( *http2HeadersFrame) () bool {
	return .http2FrameHeader.Flags.Has(http2FlagHeadersPriority)
}

func http2parseHeadersFrame( *http2frameCache,  http2FrameHeader,  func(string),  []byte) ( http2Frame,  error) {
	 := &http2HeadersFrame{
		http2FrameHeader: ,
	}
	if .StreamID == 0 {
		// HEADERS frames MUST be associated with a stream. If a HEADERS frame
		// is received whose stream identifier field is 0x0, the recipient MUST
		// respond with a connection error (Section 5.4.1) of type
		// PROTOCOL_ERROR.
		("frame_headers_zero_stream")
		return nil, http2connError{http2ErrCodeProtocol, "HEADERS frame with stream ID 0"}
	}
	var  uint8
	if .Flags.Has(http2FlagHeadersPadded) {
		if , ,  = http2readByte();  != nil {
			("frame_headers_pad_short")
			return
		}
	}
	if .Flags.Has(http2FlagHeadersPriority) {
		var  uint32
		, ,  = http2readUint32()
		if  != nil {
			("frame_headers_prio_short")
			return nil, 
		}
		.Priority.StreamDep =  & 0x7fffffff
		.Priority.Exclusive = ( != .Priority.StreamDep) // high bit was set
		, .Priority.Weight,  = http2readByte()
		if  != nil {
			("frame_headers_prio_weight_short")
			return nil, 
		}
	}
	if len()-int() < 0 {
		("frame_headers_pad_too_big")
		return nil, http2streamError(.StreamID, http2ErrCodeProtocol)
	}
	.headerFragBuf = [:len()-int()]
	return , nil
}

// HeadersFrameParam are the parameters for writing a HEADERS frame.
type http2HeadersFrameParam struct {
	// StreamID is the required Stream ID to initiate.
	StreamID uint32
	// BlockFragment is part (or all) of a Header Block.
	BlockFragment []byte

	// EndStream indicates that the header block is the last that
	// the endpoint will send for the identified stream. Setting
	// this flag causes the stream to enter one of "half closed"
	// states.
	EndStream bool

	// EndHeaders indicates that this frame contains an entire
	// header block and is not followed by any
	// CONTINUATION frames.
	EndHeaders bool

	// PadLength is the optional number of bytes of zeros to add
	// to this frame.
	PadLength uint8

	// Priority, if non-zero, includes stream priority information
	// in the HEADER frame.
	Priority http2PriorityParam
}

// WriteHeaders writes a single HEADERS frame.
//
// This is a low-level header writing method. Encoding headers and
// splitting them into any necessary CONTINUATION frames is handled
// elsewhere.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func ( *http2Framer) ( http2HeadersFrameParam) error {
	if !http2validStreamID(.StreamID) && !.AllowIllegalWrites {
		return http2errStreamID
	}
	var  http2Flags
	if .PadLength != 0 {
		 |= http2FlagHeadersPadded
	}
	if .EndStream {
		 |= http2FlagHeadersEndStream
	}
	if .EndHeaders {
		 |= http2FlagHeadersEndHeaders
	}
	if !.Priority.IsZero() {
		 |= http2FlagHeadersPriority
	}
	.startWrite(http2FrameHeaders, , .StreamID)
	if .PadLength != 0 {
		.writeByte(.PadLength)
	}
	if !.Priority.IsZero() {
		 := .Priority.StreamDep
		if !http2validStreamIDOrZero() && !.AllowIllegalWrites {
			return http2errDepStreamID
		}
		if .Priority.Exclusive {
			 |= 1 << 31
		}
		.writeUint32()
		.writeByte(.Priority.Weight)
	}
	.wbuf = append(.wbuf, .BlockFragment...)
	.wbuf = append(.wbuf, http2padZeros[:.PadLength]...)
	return .endWrite()
}

// A PriorityFrame specifies the sender-advised priority of a stream.
// See https://httpwg.org/specs/rfc7540.html#rfc.section.6.3
type http2PriorityFrame struct {
	http2FrameHeader
	http2PriorityParam
}

// PriorityParam are the stream prioritzation parameters.
type http2PriorityParam struct {
	// StreamDep is a 31-bit stream identifier for the
	// stream that this stream depends on. Zero means no
	// dependency.
	StreamDep uint32

	// Exclusive is whether the dependency is exclusive.
	Exclusive bool

	// Weight is the stream's zero-indexed weight. It should be
	// set together with StreamDep, or neither should be set. Per
	// the spec, "Add one to the value to obtain a weight between
	// 1 and 256."
	Weight uint8
}

func ( http2PriorityParam) () bool {
	return  == http2PriorityParam{}
}

func http2parsePriorityFrame( *http2frameCache,  http2FrameHeader,  func(string),  []byte) (http2Frame, error) {
	if .StreamID == 0 {
		("frame_priority_zero_stream")
		return nil, http2connError{http2ErrCodeProtocol, "PRIORITY frame with stream ID 0"}
	}
	if len() != 5 {
		("frame_priority_bad_length")
		return nil, http2connError{http2ErrCodeFrameSize, fmt.Sprintf("PRIORITY frame payload size was %d; want 5", len())}
	}
	 := binary.BigEndian.Uint32([:4])
	 :=  & 0x7fffffff // mask off high bit
	return &http2PriorityFrame{
		http2FrameHeader: ,
		http2PriorityParam: http2PriorityParam{
			Weight:    [4],
			StreamDep: ,
			Exclusive:  != , // was high bit set?
		},
	}, nil
}

// WritePriority writes a PRIORITY frame.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func ( *http2Framer) ( uint32,  http2PriorityParam) error {
	if !http2validStreamID() && !.AllowIllegalWrites {
		return http2errStreamID
	}
	if !http2validStreamIDOrZero(.StreamDep) {
		return http2errDepStreamID
	}
	.startWrite(http2FramePriority, 0, )
	 := .StreamDep
	if .Exclusive {
		 |= 1 << 31
	}
	.writeUint32()
	.writeByte(.Weight)
	return .endWrite()
}

// A RSTStreamFrame allows for abnormal termination of a stream.
// See https://httpwg.org/specs/rfc7540.html#rfc.section.6.4
type http2RSTStreamFrame struct {
	http2FrameHeader
	ErrCode http2ErrCode
}

func http2parseRSTStreamFrame( *http2frameCache,  http2FrameHeader,  func(string),  []byte) (http2Frame, error) {
	if len() != 4 {
		("frame_rststream_bad_len")
		return nil, http2ConnectionError(http2ErrCodeFrameSize)
	}
	if .StreamID == 0 {
		("frame_rststream_zero_stream")
		return nil, http2ConnectionError(http2ErrCodeProtocol)
	}
	return &http2RSTStreamFrame{, http2ErrCode(binary.BigEndian.Uint32([:4]))}, nil
}

// WriteRSTStream writes a RST_STREAM frame.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func ( *http2Framer) ( uint32,  http2ErrCode) error {
	if !http2validStreamID() && !.AllowIllegalWrites {
		return http2errStreamID
	}
	.startWrite(http2FrameRSTStream, 0, )
	.writeUint32(uint32())
	return .endWrite()
}

// A ContinuationFrame is used to continue a sequence of header block fragments.
// See https://httpwg.org/specs/rfc7540.html#rfc.section.6.10
type http2ContinuationFrame struct {
	http2FrameHeader
	headerFragBuf []byte
}

func http2parseContinuationFrame( *http2frameCache,  http2FrameHeader,  func(string),  []byte) (http2Frame, error) {
	if .StreamID == 0 {
		("frame_continuation_zero_stream")
		return nil, http2connError{http2ErrCodeProtocol, "CONTINUATION frame with stream ID 0"}
	}
	return &http2ContinuationFrame{, }, nil
}

func ( *http2ContinuationFrame) () []byte {
	.checkValid()
	return .headerFragBuf
}

func ( *http2ContinuationFrame) () bool {
	return .http2FrameHeader.Flags.Has(http2FlagContinuationEndHeaders)
}

// WriteContinuation writes a CONTINUATION frame.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func ( *http2Framer) ( uint32,  bool,  []byte) error {
	if !http2validStreamID() && !.AllowIllegalWrites {
		return http2errStreamID
	}
	var  http2Flags
	if  {
		 |= http2FlagContinuationEndHeaders
	}
	.startWrite(http2FrameContinuation, , )
	.wbuf = append(.wbuf, ...)
	return .endWrite()
}

// A PushPromiseFrame is used to initiate a server stream.
// See https://httpwg.org/specs/rfc7540.html#rfc.section.6.6
type http2PushPromiseFrame struct {
	http2FrameHeader
	PromiseID     uint32
	headerFragBuf []byte // not owned
}

func ( *http2PushPromiseFrame) () []byte {
	.checkValid()
	return .headerFragBuf
}

func ( *http2PushPromiseFrame) () bool {
	return .http2FrameHeader.Flags.Has(http2FlagPushPromiseEndHeaders)
}

func http2parsePushPromise( *http2frameCache,  http2FrameHeader,  func(string),  []byte) ( http2Frame,  error) {
	 := &http2PushPromiseFrame{
		http2FrameHeader: ,
	}
	if .StreamID == 0 {
		// PUSH_PROMISE frames MUST be associated with an existing,
		// peer-initiated stream. The stream identifier of a
		// PUSH_PROMISE frame indicates the stream it is associated
		// with. If the stream identifier field specifies the value
		// 0x0, a recipient MUST respond with a connection error
		// (Section 5.4.1) of type PROTOCOL_ERROR.
		("frame_pushpromise_zero_stream")
		return nil, http2ConnectionError(http2ErrCodeProtocol)
	}
	// The PUSH_PROMISE frame includes optional padding.
	// Padding fields and flags are identical to those defined for DATA frames
	var  uint8
	if .Flags.Has(http2FlagPushPromisePadded) {
		if , ,  = http2readByte();  != nil {
			("frame_pushpromise_pad_short")
			return
		}
	}

	, .PromiseID,  = http2readUint32()
	if  != nil {
		("frame_pushpromise_promiseid_short")
		return
	}
	.PromiseID = .PromiseID & (1<<31 - 1)

	if int() > len() {
		// like the DATA frame, error out if padding is longer than the body.
		("frame_pushpromise_pad_too_big")
		return nil, http2ConnectionError(http2ErrCodeProtocol)
	}
	.headerFragBuf = [:len()-int()]
	return , nil
}

// PushPromiseParam are the parameters for writing a PUSH_PROMISE frame.
type http2PushPromiseParam struct {
	// StreamID is the required Stream ID to initiate.
	StreamID uint32

	// PromiseID is the required Stream ID which this
	// Push Promises
	PromiseID uint32

	// BlockFragment is part (or all) of a Header Block.
	BlockFragment []byte

	// EndHeaders indicates that this frame contains an entire
	// header block and is not followed by any
	// CONTINUATION frames.
	EndHeaders bool

	// PadLength is the optional number of bytes of zeros to add
	// to this frame.
	PadLength uint8
}

// WritePushPromise writes a single PushPromise Frame.
//
// As with Header Frames, This is the low level call for writing
// individual frames. Continuation frames are handled elsewhere.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func ( *http2Framer) ( http2PushPromiseParam) error {
	if !http2validStreamID(.StreamID) && !.AllowIllegalWrites {
		return http2errStreamID
	}
	var  http2Flags
	if .PadLength != 0 {
		 |= http2FlagPushPromisePadded
	}
	if .EndHeaders {
		 |= http2FlagPushPromiseEndHeaders
	}
	.startWrite(http2FramePushPromise, , .StreamID)
	if .PadLength != 0 {
		.writeByte(.PadLength)
	}
	if !http2validStreamID(.PromiseID) && !.AllowIllegalWrites {
		return http2errStreamID
	}
	.writeUint32(.PromiseID)
	.wbuf = append(.wbuf, .BlockFragment...)
	.wbuf = append(.wbuf, http2padZeros[:.PadLength]...)
	return .endWrite()
}

// WriteRawFrame writes a raw frame. This can be used to write
// extension frames unknown to this package.
func ( *http2Framer) ( http2FrameType,  http2Flags,  uint32,  []byte) error {
	.startWrite(, , )
	.writeBytes()
	return .endWrite()
}

func http2readByte( []byte) ( []byte,  byte,  error) {
	if len() == 0 {
		return nil, 0, io.ErrUnexpectedEOF
	}
	return [1:], [0], nil
}

func http2readUint32( []byte) ( []byte,  uint32,  error) {
	if len() < 4 {
		return nil, 0, io.ErrUnexpectedEOF
	}
	return [4:], binary.BigEndian.Uint32([:4]), nil
}

type http2streamEnder interface {
	StreamEnded() bool
}

type http2headersEnder interface {
	HeadersEnded() bool
}

type http2headersOrContinuation interface {
	http2headersEnder
	HeaderBlockFragment() []byte
}

// A MetaHeadersFrame is the representation of one HEADERS frame and
// zero or more contiguous CONTINUATION frames and the decoding of
// their HPACK-encoded contents.
//
// This type of frame does not appear on the wire and is only returned
// by the Framer when Framer.ReadMetaHeaders is set.
type http2MetaHeadersFrame struct {
	*http2HeadersFrame

	// Fields are the fields contained in the HEADERS and
	// CONTINUATION frames. The underlying slice is owned by the
	// Framer and must not be retained after the next call to
	// ReadFrame.
	//
	// Fields are guaranteed to be in the correct http2 order and
	// not have unknown pseudo header fields or invalid header
	// field names or values. Required pseudo header fields may be
	// missing, however. Use the MetaHeadersFrame.Pseudo accessor
	// method access pseudo headers.
	Fields []hpack.HeaderField

	// Truncated is whether the max header list size limit was hit
	// and Fields is incomplete. The hpack decoder state is still
	// valid, however.
	Truncated bool
}

// PseudoValue returns the given pseudo header field's value.
// The provided pseudo field should not contain the leading colon.
func ( *http2MetaHeadersFrame) ( string) string {
	for ,  := range .Fields {
		if !.IsPseudo() {
			return ""
		}
		if .Name[1:] ==  {
			return .Value
		}
	}
	return ""
}

// RegularFields returns the regular (non-pseudo) header fields of mh.
// The caller does not own the returned slice.
func ( *http2MetaHeadersFrame) () []hpack.HeaderField {
	for ,  := range .Fields {
		if !.IsPseudo() {
			return .Fields[:]
		}
	}
	return nil
}

// PseudoFields returns the pseudo header fields of mh.
// The caller does not own the returned slice.
func ( *http2MetaHeadersFrame) () []hpack.HeaderField {
	for ,  := range .Fields {
		if !.IsPseudo() {
			return .Fields[:]
		}
	}
	return .Fields
}

func ( *http2MetaHeadersFrame) () error {
	var ,  bool
	 := .PseudoFields()
	for ,  := range  {
		switch .Name {
		case ":method", ":path", ":scheme", ":authority", ":protocol":
			 = true
		case ":status":
			 = true
		default:
			return http2pseudoHeaderError(.Name)
		}
		// Check for duplicates.
		// This would be a bad algorithm, but N is 5.
		// And this doesn't allocate.
		for ,  := range [:] {
			if .Name == .Name {
				return http2duplicatePseudoHeaderError(.Name)
			}
		}
	}
	if  &&  {
		return http2errMixPseudoHeaderTypes
	}
	return nil
}

func ( *http2Framer) () int {
	 := int(.maxHeaderListSize())
	if  < 0 {
		// If maxHeaderListSize overflows an int, use no limit (0).
		return 0
	}
	return 
}

// readMetaFrame returns 0 or more CONTINUATION frames from fr and
// merge them into the provided hf and returns a MetaHeadersFrame
// with the decoded hpack values.
func ( *http2Framer) ( *http2HeadersFrame) (http2Frame, error) {
	if .AllowIllegalReads {
		return nil, errors.New("illegal use of AllowIllegalReads with ReadMetaHeaders")
	}
	 := &http2MetaHeadersFrame{
		http2HeadersFrame: ,
	}
	var  = .maxHeaderListSize()
	var  bool

	var  error // pseudo header field errors
	 := .ReadMetaHeaders
	.SetEmitEnabled(true)
	.SetMaxStringLength(.maxHeaderStringLen())
	.SetEmitFunc(func( hpack.HeaderField) {
		if http2VerboseLogs && .logReads {
			.debugReadLoggerf("http2: decoded hpack field %+v", )
		}
		if !httpguts.ValidHeaderFieldValue(.Value) {
			// Don't include the value in the error, because it may be sensitive.
			 = http2headerFieldValueError(.Name)
		}
		 := strings.HasPrefix(.Name, ":")
		if  {
			if  {
				 = http2errPseudoAfterRegular
			}
		} else {
			 = true
			if !http2validWireHeaderFieldName(.Name) {
				 = http2headerFieldNameError(.Name)
			}
		}

		if  != nil {
			.SetEmitEnabled(false)
			return
		}

		 := .Size()
		if  >  {
			.SetEmitEnabled(false)
			.Truncated = true
			 = 0
			return
		}
		 -= 

		.Fields = append(.Fields, )
	})
	// Lose reference to MetaHeadersFrame:
	defer .SetEmitFunc(func( hpack.HeaderField) {})

	var  http2headersOrContinuation = 
	for {
		 := .HeaderBlockFragment()

		// Avoid parsing large amounts of headers that we will then discard.
		// If the sender exceeds the max header list size by too much,
		// skip parsing the fragment and close the connection.
		//
		// "Too much" is either any CONTINUATION frame after we've already
		// exceeded the max header list size (in which case remainSize is 0),
		// or a frame whose encoded size is more than twice the remaining
		// header list bytes we're willing to accept.
		if int64(len()) > int64(2*) {
			if http2VerboseLogs {
				log.Printf("http2: header list too large")
			}
			// It would be nice to send a RST_STREAM before sending the GOAWAY,
			// but the structure of the server's frame writer makes this difficult.
			return , http2ConnectionError(http2ErrCodeProtocol)
		}

		// Also close the connection after any CONTINUATION frame following an
		// invalid header, since we stop tracking the size of the headers after
		// an invalid one.
		if  != nil {
			if http2VerboseLogs {
				log.Printf("http2: invalid header: %v", )
			}
			// It would be nice to send a RST_STREAM before sending the GOAWAY,
			// but the structure of the server's frame writer makes this difficult.
			return , http2ConnectionError(http2ErrCodeProtocol)
		}

		if ,  := .Write();  != nil {
			return , http2ConnectionError(http2ErrCodeCompression)
		}

		if .HeadersEnded() {
			break
		}
		if ,  := .ReadFrame();  != nil {
			return nil, 
		} else {
			 = .(*http2ContinuationFrame) // guaranteed by checkFrameOrder
		}
	}

	.http2HeadersFrame.headerFragBuf = nil
	.http2HeadersFrame.invalidate()

	if  := .Close();  != nil {
		return , http2ConnectionError(http2ErrCodeCompression)
	}
	if  != nil {
		.errDetail = 
		if http2VerboseLogs {
			log.Printf("http2: invalid header: %v", )
		}
		return nil, http2StreamError{.StreamID, http2ErrCodeProtocol, }
	}
	if  := .checkPseudos();  != nil {
		.errDetail = 
		if http2VerboseLogs {
			log.Printf("http2: invalid pseudo headers: %v", )
		}
		return nil, http2StreamError{.StreamID, http2ErrCodeProtocol, }
	}
	return , nil
}

func http2summarizeFrame( http2Frame) string {
	var  bytes.Buffer
	.Header().writeDebug(&)
	switch f := .(type) {
	case *http2SettingsFrame:
		 := 0
		.ForeachSetting(func( http2Setting) error {
			++
			if  == 1 {
				.WriteString(", settings:")
			}
			fmt.Fprintf(&, " %v=%v,", .ID, .Val)
			return nil
		})
		if  > 0 {
			.Truncate(.Len() - 1) // remove trailing comma
		}
	case *http2DataFrame:
		 := .Data()
		const  = 256
		if len() >  {
			 = [:]
		}
		fmt.Fprintf(&, " data=%q", )
		if len(.Data()) >  {
			fmt.Fprintf(&, " (%d bytes omitted)", len(.Data())-)
		}
	case *http2WindowUpdateFrame:
		if .StreamID == 0 {
			.WriteString(" (conn)")
		}
		fmt.Fprintf(&, " incr=%v", .Increment)
	case *http2PingFrame:
		fmt.Fprintf(&, " ping=%q", .Data[:])
	case *http2GoAwayFrame:
		fmt.Fprintf(&, " LastStreamID=%v ErrCode=%v Debug=%q",
			.LastStreamID, .ErrCode, .debugData)
	case *http2RSTStreamFrame:
		fmt.Fprintf(&, " ErrCode=%v", .ErrCode)
	}
	return .String()
}

var http2DebugGoroutines = os.Getenv("DEBUG_HTTP2_GOROUTINES") == "1"

type http2goroutineLock uint64

func http2newGoroutineLock() http2goroutineLock {
	if !http2DebugGoroutines {
		return 0
	}
	return http2goroutineLock(http2curGoroutineID())
}

func ( http2goroutineLock) () {
	if !http2DebugGoroutines {
		return
	}
	if http2curGoroutineID() != uint64() {
		panic("running on the wrong goroutine")
	}
}

func ( http2goroutineLock) () {
	if !http2DebugGoroutines {
		return
	}
	if http2curGoroutineID() == uint64() {
		panic("running on the wrong goroutine")
	}
}

var http2goroutineSpace = []byte("goroutine ")

func http2curGoroutineID() uint64 {
	 := http2littleBuf.Get().(*[]byte)
	defer http2littleBuf.Put()
	 := *
	 = [:runtime.Stack(, false)]
	// Parse the 4707 out of "goroutine 4707 ["
	 = bytes.TrimPrefix(, http2goroutineSpace)
	 := bytes.IndexByte(, ' ')
	if  < 0 {
		panic(fmt.Sprintf("No space found in %q", ))
	}
	 = [:]
	,  := http2parseUintBytes(, 10, 64)
	if  != nil {
		panic(fmt.Sprintf("Failed to parse goroutine ID out of %q: %v", , ))
	}
	return 
}

var http2littleBuf = sync.Pool{
	New: func() interface{} {
		 := make([]byte, 64)
		return &
	},
}

// parseUintBytes is like strconv.ParseUint, but using a []byte.
func http2parseUintBytes( []byte,  int,  int) ( uint64,  error) {
	var ,  uint64

	if  == 0 {
		 = int(strconv.IntSize)
	}

	 := 
	switch {
	case len() < 1:
		 = strconv.ErrSyntax
		goto 

	case 2 <=  &&  <= 36:
		// valid base; nothing to do

	case  == 0:
		// Look for octal, hex prefix.
		switch {
		case [0] == '0' && len() > 1 && ([1] == 'x' || [1] == 'X'):
			 = 16
			 = [2:]
			if len() < 1 {
				 = strconv.ErrSyntax
				goto 
			}
		case [0] == '0':
			 = 8
		default:
			 = 10
		}

	default:
		 = errors.New("invalid base " + strconv.Itoa())
		goto 
	}

	 = 0
	 = http2cutoff64()
	 = 1<<uint() - 1

	for  := 0;  < len(); ++ {
		var  byte
		 := []
		switch {
		case '0' <=  &&  <= '9':
			 =  - '0'
		case 'a' <=  &&  <= 'z':
			 =  - 'a' + 10
		case 'A' <=  &&  <= 'Z':
			 =  - 'A' + 10
		default:
			 = 0
			 = strconv.ErrSyntax
			goto 
		}
		if int() >=  {
			 = 0
			 = strconv.ErrSyntax
			goto 
		}

		if  >=  {
			// n*base overflows
			 = 1<<64 - 1
			 = strconv.ErrRange
			goto 
		}
		 *= uint64()

		 :=  + uint64()
		if  <  ||  >  {
			// n+v overflows
			 = 1<<64 - 1
			 = strconv.ErrRange
			goto 
		}
		 = 
	}

	return , nil

:
	return , &strconv.NumError{Func: "ParseUint", Num: string(), Err: }
}

// Return the first number n such that n*base >= 1<<64.
func http2cutoff64( int) uint64 {
	if  < 2 {
		return 0
	}
	return (1<<64-1)/uint64() + 1
}

var (
	http2commonBuildOnce   sync.Once
	http2commonLowerHeader map[string]string // Go-Canonical-Case -> lower-case
	http2commonCanonHeader map[string]string // lower-case -> Go-Canonical-Case
)

func http2buildCommonHeaderMapsOnce() {
	http2commonBuildOnce.Do(http2buildCommonHeaderMaps)
}

func http2buildCommonHeaderMaps() {
	 := []string{
		"accept",
		"accept-charset",
		"accept-encoding",
		"accept-language",
		"accept-ranges",
		"age",
		"access-control-allow-credentials",
		"access-control-allow-headers",
		"access-control-allow-methods",
		"access-control-allow-origin",
		"access-control-expose-headers",
		"access-control-max-age",
		"access-control-request-headers",
		"access-control-request-method",
		"allow",
		"authorization",
		"cache-control",
		"content-disposition",
		"content-encoding",
		"content-language",
		"content-length",
		"content-location",
		"content-range",
		"content-type",
		"cookie",
		"date",
		"etag",
		"expect",
		"expires",
		"from",
		"host",
		"if-match",
		"if-modified-since",
		"if-none-match",
		"if-unmodified-since",
		"last-modified",
		"link",
		"location",
		"max-forwards",
		"origin",
		"proxy-authenticate",
		"proxy-authorization",
		"range",
		"referer",
		"refresh",
		"retry-after",
		"server",
		"set-cookie",
		"strict-transport-security",
		"trailer",
		"transfer-encoding",
		"user-agent",
		"vary",
		"via",
		"www-authenticate",
		"x-forwarded-for",
		"x-forwarded-proto",
	}
	http2commonLowerHeader = make(map[string]string, len())
	http2commonCanonHeader = make(map[string]string, len())
	for ,  := range  {
		 := CanonicalHeaderKey()
		http2commonLowerHeader[] = 
		http2commonCanonHeader[] = 
	}
}

func http2lowerHeader( string) ( string,  bool) {
	http2buildCommonHeaderMapsOnce()
	if ,  := http2commonLowerHeader[];  {
		return , true
	}
	return http2asciiToLower()
}

func http2canonicalHeader( string) string {
	http2buildCommonHeaderMapsOnce()
	if ,  := http2commonCanonHeader[];  {
		return 
	}
	return CanonicalHeaderKey()
}

var (
	http2VerboseLogs                    bool
	http2logFrameWrites                 bool
	http2logFrameReads                  bool
	http2inTests                        bool
	http2disableExtendedConnectProtocol bool
)

func init() {
	 := os.Getenv("GODEBUG")
	if strings.Contains(, "http2debug=1") {
		http2VerboseLogs = true
	}
	if strings.Contains(, "http2debug=2") {
		http2VerboseLogs = true
		http2logFrameWrites = true
		http2logFrameReads = true
	}
	if strings.Contains(, "http2xconnect=0") {
		http2disableExtendedConnectProtocol = true
	}
}

const (
	// ClientPreface is the string that must be sent by new
	// connections from clients.
	http2ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"

	// SETTINGS_MAX_FRAME_SIZE default
	// https://httpwg.org/specs/rfc7540.html#rfc.section.6.5.2
	http2initialMaxFrameSize = 16384

	// NextProtoTLS is the NPN/ALPN protocol negotiated during
	// HTTP/2's TLS setup.
	http2NextProtoTLS = "h2"

	// https://httpwg.org/specs/rfc7540.html#SettingValues
	http2initialHeaderTableSize = 4096

	http2initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size

	http2defaultMaxReadFrameSize = 1 << 20
)

var (
	http2clientPreface = []byte(http2ClientPreface)
)

type http2streamState int

// HTTP/2 stream states.
//
// See http://tools.ietf.org/html/rfc7540#section-5.1.
//
// For simplicity, the server code merges "reserved (local)" into
// "half-closed (remote)". This is one less state transition to track.
// The only downside is that we send PUSH_PROMISEs slightly less
// liberally than allowable. More discussion here:
// https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0599.html
//
// "reserved (remote)" is omitted since the client code does not
// support server push.
const (
	http2stateIdle http2streamState = iota
	http2stateOpen
	http2stateHalfClosedLocal
	http2stateHalfClosedRemote
	http2stateClosed
)

var http2stateName = [...]string{
	http2stateIdle:             "Idle",
	http2stateOpen:             "Open",
	http2stateHalfClosedLocal:  "HalfClosedLocal",
	http2stateHalfClosedRemote: "HalfClosedRemote",
	http2stateClosed:           "Closed",
}

func ( http2streamState) () string {
	return http2stateName[]
}

// Setting is a setting parameter: which setting it is, and its value.
type http2Setting struct {
	// ID is which setting is being set.
	// See https://httpwg.org/specs/rfc7540.html#SettingFormat
	ID http2SettingID

	// Val is the value.
	Val uint32
}

func ( http2Setting) () string {
	return fmt.Sprintf("[%v = %d]", .ID, .Val)
}

// Valid reports whether the setting is valid.
func ( http2Setting) () error {
	// Limits and error codes from 6.5.2 Defined SETTINGS Parameters
	switch .ID {
	case http2SettingEnablePush:
		if .Val != 1 && .Val != 0 {
			return http2ConnectionError(http2ErrCodeProtocol)
		}
	case http2SettingInitialWindowSize:
		if .Val > 1<<31-1 {
			return http2ConnectionError(http2ErrCodeFlowControl)
		}
	case http2SettingMaxFrameSize:
		if .Val < 16384 || .Val > 1<<24-1 {
			return http2ConnectionError(http2ErrCodeProtocol)
		}
	case http2SettingEnableConnectProtocol:
		if .Val != 1 && .Val != 0 {
			return http2ConnectionError(http2ErrCodeProtocol)
		}
	}
	return nil
}

// A SettingID is an HTTP/2 setting as defined in
// https://httpwg.org/specs/rfc7540.html#iana-settings
type http2SettingID uint16

const (
	http2SettingHeaderTableSize       http2SettingID = 0x1
	http2SettingEnablePush            http2SettingID = 0x2
	http2SettingMaxConcurrentStreams  http2SettingID = 0x3
	http2SettingInitialWindowSize     http2SettingID = 0x4
	http2SettingMaxFrameSize          http2SettingID = 0x5
	http2SettingMaxHeaderListSize     http2SettingID = 0x6
	http2SettingEnableConnectProtocol http2SettingID = 0x8
)

var http2settingName = map[http2SettingID]string{
	http2SettingHeaderTableSize:       "HEADER_TABLE_SIZE",
	http2SettingEnablePush:            "ENABLE_PUSH",
	http2SettingMaxConcurrentStreams:  "MAX_CONCURRENT_STREAMS",
	http2SettingInitialWindowSize:     "INITIAL_WINDOW_SIZE",
	http2SettingMaxFrameSize:          "MAX_FRAME_SIZE",
	http2SettingMaxHeaderListSize:     "MAX_HEADER_LIST_SIZE",
	http2SettingEnableConnectProtocol: "ENABLE_CONNECT_PROTOCOL",
}

func ( http2SettingID) () string {
	if ,  := http2settingName[];  {
		return 
	}
	return fmt.Sprintf("UNKNOWN_SETTING_%d", uint16())
}

// validWireHeaderFieldName reports whether v is a valid header field
// name (key). See httpguts.ValidHeaderName for the base rules.
//
// Further, http2 says:
//
//	"Just as in HTTP/1.x, header field names are strings of ASCII
//	characters that are compared in a case-insensitive
//	fashion. However, header field names MUST be converted to
//	lowercase prior to their encoding in HTTP/2. "
func http2validWireHeaderFieldName( string) bool {
	if len() == 0 {
		return false
	}
	for ,  := range  {
		if !httpguts.IsTokenRune() {
			return false
		}
		if 'A' <=  &&  <= 'Z' {
			return false
		}
	}
	return true
}

func http2httpCodeString( int) string {
	switch  {
	case 200:
		return "200"
	case 404:
		return "404"
	}
	return strconv.Itoa()
}

// from pkg io
type http2stringWriter interface {
	WriteString(s string) (n int, err error)
}

// A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed).
type http2closeWaiter chan struct{}

// Init makes a closeWaiter usable.
// It exists because so a closeWaiter value can be placed inside a
// larger struct and have the Mutex and Cond's memory in the same
// allocation.
func ( *http2closeWaiter) () {
	* = make(chan struct{})
}

// Close marks the closeWaiter as closed and unblocks any waiters.
func ( http2closeWaiter) () {
	close()
}

// Wait waits for the closeWaiter to become closed.
func ( http2closeWaiter) () {
	<-
}

// bufferedWriter is a buffered writer that writes to w.
// Its buffered writer is lazily allocated as needed, to minimize
// idle memory usage with many connections.
type http2bufferedWriter struct {
	_           http2incomparable
	group       http2synctestGroupInterface // immutable
	conn        net.Conn                    // immutable
	bw          *bufio.Writer               // non-nil when data is buffered
	byteTimeout time.Duration               // immutable, WriteByteTimeout
}

func http2newBufferedWriter( http2synctestGroupInterface,  net.Conn,  time.Duration) *http2bufferedWriter {
	return &http2bufferedWriter{
		group:       ,
		conn:        ,
		byteTimeout: ,
	}
}

// bufWriterPoolBufferSize is the size of bufio.Writer's
// buffers created using bufWriterPool.
//
// TODO: pick a less arbitrary value? this is a bit under
// (3 x typical 1500 byte MTU) at least. Other than that,
// not much thought went into it.
const http2bufWriterPoolBufferSize = 4 << 10

var http2bufWriterPool = sync.Pool{
	New: func() interface{} {
		return bufio.NewWriterSize(nil, http2bufWriterPoolBufferSize)
	},
}

func ( *http2bufferedWriter) () int {
	if .bw == nil {
		return http2bufWriterPoolBufferSize
	}
	return .bw.Available()
}

func ( *http2bufferedWriter) ( []byte) ( int,  error) {
	if .bw == nil {
		 := http2bufWriterPool.Get().(*bufio.Writer)
		.Reset((*http2bufferedWriterTimeoutWriter)())
		.bw = 
	}
	return .bw.Write()
}

func ( *http2bufferedWriter) () error {
	 := .bw
	if  == nil {
		return nil
	}
	 := .Flush()
	.Reset(nil)
	http2bufWriterPool.Put()
	.bw = nil
	return 
}

type http2bufferedWriterTimeoutWriter http2bufferedWriter

func ( *http2bufferedWriterTimeoutWriter) ( []byte) ( int,  error) {
	return http2writeWithByteTimeout(.group, .conn, .byteTimeout, )
}

// writeWithByteTimeout writes to conn.
// If more than timeout passes without any bytes being written to the connection,
// the write fails.
func http2writeWithByteTimeout( http2synctestGroupInterface,  net.Conn,  time.Duration,  []byte) ( int,  error) {
	if  <= 0 {
		return .Write()
	}
	for {
		var  time.Time
		if  == nil {
			 = time.Now()
		} else {
			 = .Now()
		}
		.SetWriteDeadline(.Add())
		,  := .Write([:])
		 += 
		if  == len() ||  == 0 || !errors.Is(, os.ErrDeadlineExceeded) {
			// Either we finished the write, made no progress, or hit the deadline.
			// Whichever it is, we're done now.
			.SetWriteDeadline(time.Time{})
			return , 
		}
	}
}

func http2mustUint31( int32) uint32 {
	if  < 0 ||  > 2147483647 {
		panic("out of range")
	}
	return uint32()
}

// bodyAllowedForStatus reports whether a given response status code
// permits a body. See RFC 7230, section 3.3.
func http2bodyAllowedForStatus( int) bool {
	switch {
	case  >= 100 &&  <= 199:
		return false
	case  == 204:
		return false
	case  == 304:
		return false
	}
	return true
}

type http2httpError struct {
	_       http2incomparable
	msg     string
	timeout bool
}

func ( *http2httpError) () string { return .msg }

func ( *http2httpError) () bool { return .timeout }

func ( *http2httpError) () bool { return true }

var http2errTimeout error = &http2httpError{msg: "http2: timeout awaiting response headers", timeout: true}

type http2connectionStater interface {
	ConnectionState() tls.ConnectionState
}

var http2sorterPool = sync.Pool{New: func() interface{} { return new(http2sorter) }}

type http2sorter struct {
	v []string // owned by sorter
}

func ( *http2sorter) () int { return len(.v) }

func ( *http2sorter) (,  int) { .v[], .v[] = .v[], .v[] }

func ( *http2sorter) (,  int) bool { return .v[] < .v[] }

// Keys returns the sorted keys of h.
//
// The returned slice is only valid until s used again or returned to
// its pool.
func ( *http2sorter) ( Header) []string {
	 := .v[:0]
	for  := range  {
		 = append(, )
	}
	.v = 
	sort.Sort()
	return 
}

func ( *http2sorter) ( []string) {
	// Our sorter works on s.v, which sorter owns, so
	// stash it away while we sort the user's buffer.
	 := .v
	.v = 
	sort.Sort()
	.v = 
}

// validPseudoPath reports whether v is a valid :path pseudo-header
// value. It must be either:
//
//   - a non-empty string starting with '/'
//   - the string '*', for OPTIONS requests.
//
// For now this is only used a quick check for deciding when to clean
// up Opaque URLs before sending requests from the Transport.
// See golang.org/issue/16847
//
// We used to enforce that the path also didn't start with "//", but
// Google's GFE accepts such paths and Chrome sends them, so ignore
// that part of the spec. See golang.org/issue/19103.
func http2validPseudoPath( string) bool {
	return (len() > 0 && [0] == '/') ||  == "*"
}

// incomparable is a zero-width, non-comparable type. Adding it to a struct
// makes that struct also non-comparable, and generally doesn't add
// any size (as long as it's first).
type http2incomparable [0]func()

// synctestGroupInterface is the methods of synctestGroup used by Server and Transport.
// It's defined as an interface here to let us keep synctestGroup entirely test-only
// and not a part of non-test builds.
type http2synctestGroupInterface interface {
	Join()
	Now() time.Time
	NewTimer(d time.Duration) http2timer
	AfterFunc(d time.Duration, f func()) http2timer
	ContextWithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc)
}

// pipe is a goroutine-safe io.Reader/io.Writer pair. It's like
// io.Pipe except there are no PipeReader/PipeWriter halves, and the
// underlying buffer is an interface. (io.Pipe is always unbuffered)
type http2pipe struct {
	mu       sync.Mutex
	c        sync.Cond       // c.L lazily initialized to &p.mu
	b        http2pipeBuffer // nil when done reading
	unread   int             // bytes unread when done
	err      error           // read error once empty. non-nil means closed.
	breakErr error           // immediate read error (caller doesn't see rest of b)
	donec    chan struct{}   // closed on error
	readFn   func()          // optional code to run in Read before error
}

type http2pipeBuffer interface {
	Len() int
	io.Writer
	io.Reader
}

// setBuffer initializes the pipe buffer.
// It has no effect if the pipe is already closed.
func ( *http2pipe) ( http2pipeBuffer) {
	.mu.Lock()
	defer .mu.Unlock()
	if .err != nil || .breakErr != nil {
		return
	}
	.b = 
}

func ( *http2pipe) () int {
	.mu.Lock()
	defer .mu.Unlock()
	if .b == nil {
		return .unread
	}
	return .b.Len()
}

// Read waits until data is available and copies bytes
// from the buffer into p.
func ( *http2pipe) ( []byte) ( int,  error) {
	.mu.Lock()
	defer .mu.Unlock()
	if .c.L == nil {
		.c.L = &.mu
	}
	for {
		if .breakErr != nil {
			return 0, .breakErr
		}
		if .b != nil && .b.Len() > 0 {
			return .b.Read()
		}
		if .err != nil {
			if .readFn != nil {
				.readFn()     // e.g. copy trailers
				.readFn = nil // not sticky like p.err
			}
			.b = nil
			return 0, .err
		}
		.c.Wait()
	}
}

var (
	http2errClosedPipeWrite        = errors.New("write on closed buffer")
	http2errUninitializedPipeWrite = errors.New("write on uninitialized buffer")
)

// Write copies bytes from p into the buffer and wakes a reader.
// It is an error to write more data than the buffer can hold.
func ( *http2pipe) ( []byte) ( int,  error) {
	.mu.Lock()
	defer .mu.Unlock()
	if .c.L == nil {
		.c.L = &.mu
	}
	defer .c.Signal()
	if .err != nil || .breakErr != nil {
		return 0, http2errClosedPipeWrite
	}
	// pipe.setBuffer is never invoked, leaving the buffer uninitialized.
	// We shouldn't try to write to an uninitialized pipe,
	// but returning an error is better than panicking.
	if .b == nil {
		return 0, http2errUninitializedPipeWrite
	}
	return .b.Write()
}

// CloseWithError causes the next Read (waking up a current blocked
// Read if needed) to return the provided err after all data has been
// read.
//
// The error must be non-nil.
func ( *http2pipe) ( error) { .closeWithError(&.err, , nil) }

// BreakWithError causes the next Read (waking up a current blocked
// Read if needed) to return the provided err immediately, without
// waiting for unread data.
func ( *http2pipe) ( error) { .closeWithError(&.breakErr, , nil) }

// closeWithErrorAndCode is like CloseWithError but also sets some code to run
// in the caller's goroutine before returning the error.
func ( *http2pipe) ( error,  func()) { .closeWithError(&.err, , ) }

func ( *http2pipe) ( *error,  error,  func()) {
	if  == nil {
		panic("err must be non-nil")
	}
	.mu.Lock()
	defer .mu.Unlock()
	if .c.L == nil {
		.c.L = &.mu
	}
	defer .c.Signal()
	if * != nil {
		// Already been done.
		return
	}
	.readFn = 
	if  == &.breakErr {
		if .b != nil {
			.unread += .b.Len()
		}
		.b = nil
	}
	* = 
	.closeDoneLocked()
}

// requires p.mu be held.
func ( *http2pipe) () {
	if .donec == nil {
		return
	}
	// Close if unclosed. This isn't racy since we always
	// hold p.mu while closing.
	select {
	case <-.donec:
	default:
		close(.donec)
	}
}

// Err returns the error (if any) first set by BreakWithError or CloseWithError.
func ( *http2pipe) () error {
	.mu.Lock()
	defer .mu.Unlock()
	if .breakErr != nil {
		return .breakErr
	}
	return .err
}

// Done returns a channel which is closed if and when this pipe is closed
// with CloseWithError.
func ( *http2pipe) () <-chan struct{} {
	.mu.Lock()
	defer .mu.Unlock()
	if .donec == nil {
		.donec = make(chan struct{})
		if .err != nil || .breakErr != nil {
			// Already hit an error.
			.closeDoneLocked()
		}
	}
	return .donec
}

const (
	http2prefaceTimeout        = 10 * time.Second
	http2firstSettingsTimeout  = 2 * time.Second // should be in-flight with preface anyway
	http2handlerChunkWriteSize = 4 << 10
	http2defaultMaxStreams     = 250 // TODO: make this 100 as the GFE seems to?

	// maxQueuedControlFrames is the maximum number of control frames like
	// SETTINGS, PING and RST_STREAM that will be queued for writing before
	// the connection is closed to prevent memory exhaustion attacks.
	http2maxQueuedControlFrames = 10000
)

var (
	http2errClientDisconnected = errors.New("client disconnected")
	http2errClosedBody         = errors.New("body closed by handler")
	http2errHandlerComplete    = errors.New("http2: request body closed due to handler exiting")
	http2errStreamClosed       = errors.New("http2: stream closed")
)

var http2responseWriterStatePool = sync.Pool{
	New: func() interface{} {
		 := &http2responseWriterState{}
		.bw = bufio.NewWriterSize(http2chunkWriter{}, http2handlerChunkWriteSize)
		return 
	},
}

// Test hooks.
var (
	http2testHookOnConn        func()
	http2testHookGetServerConn func(*http2serverConn)
	http2testHookOnPanicMu     *sync.Mutex // nil except in tests
	http2testHookOnPanic       func(sc *http2serverConn, panicVal interface{}) (rePanic bool)
)

// Server is an HTTP/2 server.
type http2Server struct {
	// MaxHandlers limits the number of http.Handler ServeHTTP goroutines
	// which may run at a time over all connections.
	// Negative or zero no limit.
	// TODO: implement
	MaxHandlers int

	// MaxConcurrentStreams optionally specifies the number of
	// concurrent streams that each client may have open at a
	// time. This is unrelated to the number of http.Handler goroutines
	// which may be active globally, which is MaxHandlers.
	// If zero, MaxConcurrentStreams defaults to at least 100, per
	// the HTTP/2 spec's recommendations.
	MaxConcurrentStreams 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

	// MaxReadFrameSize optionally specifies the largest frame
	// this server is willing to read. A valid value is between
	// 16k and 16M, inclusive. If zero or otherwise invalid, a
	// default value is used.
	MaxReadFrameSize uint32

	// PermitProhibitedCipherSuites, if true, permits the use of
	// cipher suites prohibited by the HTTP/2 spec.
	PermitProhibitedCipherSuites bool

	// IdleTimeout specifies how long until idle clients should be
	// closed with a GOAWAY frame. PING frames are not considered
	// activity for the purposes of IdleTimeout.
	// If zero or negative, there is no timeout.
	IdleTimeout time.Duration

	// ReadIdleTimeout is the timeout after which a health check using a ping
	// frame will be carried out if no frame is received on the connection.
	// 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 a ping is not received.
	// If zero, a default of 15 seconds is used.
	PingTimeout time.Duration

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

	// MaxUploadBufferPerConnection is the size of the initial flow
	// control window for each connections. The HTTP/2 spec does not
	// allow this to be smaller than 65535 or larger than 2^32-1.
	// If the value is outside this range, a default value will be
	// used instead.
	MaxUploadBufferPerConnection int32

	// MaxUploadBufferPerStream is the size of the initial flow control
	// window for each stream. The HTTP/2 spec does not allow this to
	// be larger than 2^32-1. If the value is zero or larger than the
	// maximum, a default value will be used instead.
	MaxUploadBufferPerStream int32

	// NewWriteScheduler constructs a write scheduler for a connection.
	// If nil, a default scheduler is chosen.
	NewWriteScheduler func() http2WriteScheduler

	// CountError, if non-nil, is called on HTTP/2 server 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)

	// Internal state. This is a pointer (rather than embedded directly)
	// so that we don't embed a Mutex in this struct, which will make the
	// struct non-copyable, which might break some callers.
	state *http2serverInternalState

	// Synchronization group used for testing.
	// Outside of tests, this is nil.
	group http2synctestGroupInterface
}

func ( *http2Server) () {
	if .group != nil {
		.group.Join()
	}
}

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

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

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

type http2serverInternalState struct {
	mu          sync.Mutex
	activeConns map[*http2serverConn]struct{}
}

func ( *http2serverInternalState) ( *http2serverConn) {
	if  == nil {
		return // if the Server was used without calling ConfigureServer
	}
	.mu.Lock()
	.activeConns[] = struct{}{}
	.mu.Unlock()
}

func ( *http2serverInternalState) ( *http2serverConn) {
	if  == nil {
		return // if the Server was used without calling ConfigureServer
	}
	.mu.Lock()
	delete(.activeConns, )
	.mu.Unlock()
}

func ( *http2serverInternalState) () {
	if  == nil {
		return // if the Server was used without calling ConfigureServer
	}
	.mu.Lock()
	for  := range .activeConns {
		.startGracefulShutdown()
	}
	.mu.Unlock()
}

// ConfigureServer adds HTTP/2 support to a net/http Server.
//
// The configuration conf may be nil.
//
// ConfigureServer must be called before s begins serving.
func http2ConfigureServer( *Server,  *http2Server) error {
	if  == nil {
		panic("nil *http.Server")
	}
	if  == nil {
		 = new(http2Server)
	}
	.state = &http2serverInternalState{activeConns: make(map[*http2serverConn]struct{})}
	if ,  := , ; .IdleTimeout == 0 {
		if .IdleTimeout != 0 {
			.IdleTimeout = .IdleTimeout
		} else {
			.IdleTimeout = .ReadTimeout
		}
	}
	.RegisterOnShutdown(.state.startGracefulShutdown)

	if .TLSConfig == nil {
		.TLSConfig = new(tls.Config)
	} else if .TLSConfig.CipherSuites != nil && .TLSConfig.MinVersion < tls.VersionTLS13 {
		// If they already provided a TLS 1.0–1.2 CipherSuite list, return an
		// error if it is missing ECDHE_RSA_WITH_AES_128_GCM_SHA256 or
		// ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
		 := false
		for ,  := range .TLSConfig.CipherSuites {
			switch  {
			case tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
				// Alternative MTI cipher to not discourage ECDSA-only servers.
				// See http://golang.org/cl/30721 for further information.
				tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
				 = true
			}
		}
		if ! {
			return fmt.Errorf("http2: TLSConfig.CipherSuites is missing an HTTP/2-required AES_128_GCM_SHA256 cipher (need at least one of TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 or TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)")
		}
	}

	// Note: not setting MinVersion to tls.VersionTLS12,
	// as we don't want to interfere with HTTP/1.1 traffic
	// on the user's server. We enforce TLS 1.2 later once
	// we accept a connection. Ideally this should be done
	// during next-proto selection, but using TLS <1.2 with
	// HTTP/2 is still the client's bug.

	.TLSConfig.PreferServerCipherSuites = true

	if !http2strSliceContains(.TLSConfig.NextProtos, http2NextProtoTLS) {
		.TLSConfig.NextProtos = append(.TLSConfig.NextProtos, http2NextProtoTLS)
	}
	if !http2strSliceContains(.TLSConfig.NextProtos, "http/1.1") {
		.TLSConfig.NextProtos = append(.TLSConfig.NextProtos, "http/1.1")
	}

	if .TLSNextProto == nil {
		.TLSNextProto = map[string]func(*Server, *tls.Conn, Handler){}
	}
	 := func( *Server,  net.Conn,  Handler,  bool) {
		if http2testHookOnConn != nil {
			http2testHookOnConn()
		}
		// The TLSNextProto interface predates contexts, so
		// the net/http package passes down its per-connection
		// base context via an exported but unadvertised
		// method on the Handler. This is for internal
		// net/http<=>http2 use only.
		var  context.Context
		type  interface {
			() context.Context
		}
		if ,  := .();  {
			 = .()
		}
		.ServeConn(, &http2ServeConnOpts{
			Context:          ,
			Handler:          ,
			BaseConfig:       ,
			SawClientPreface: ,
		})
	}
	.TLSNextProto[http2NextProtoTLS] = func( *Server,  *tls.Conn,  Handler) {
		(, , , false)
	}
	// The "unencrypted_http2" TLSNextProto key is used to pass off non-TLS HTTP/2 conns.
	//
	// A connection passed in this method has already had the HTTP/2 preface read from it.
	.TLSNextProto[http2nextProtoUnencryptedHTTP2] = func( *Server,  *tls.Conn,  Handler) {
		,  := http2unencryptedNetConnFromTLSConn()
		if  != nil {
			if  := .ErrorLog;  != nil {
				.Print()
			} else {
				log.Print()
			}
			go .Close()
			return
		}
		(, , , true)
	}
	return nil
}

// ServeConnOpts are options for the Server.ServeConn method.
type http2ServeConnOpts struct {
	// Context is the base context to use.
	// If nil, context.Background is used.
	Context context.Context

	// BaseConfig optionally sets the base configuration
	// for values. If nil, defaults are used.
	BaseConfig *Server

	// Handler specifies which handler to use for processing
	// requests. If nil, BaseConfig.Handler is used. If BaseConfig
	// or BaseConfig.Handler is nil, http.DefaultServeMux is used.
	Handler Handler

	// UpgradeRequest is an initial request received on a connection
	// undergoing an h2c upgrade. The request body must have been
	// completely read from the connection before calling ServeConn,
	// and the 101 Switching Protocols response written.
	UpgradeRequest *Request

	// Settings is the decoded contents of the HTTP2-Settings header
	// in an h2c upgrade request.
	Settings []byte

	// SawClientPreface is set if the HTTP/2 connection preface
	// has already been read from the connection.
	SawClientPreface bool
}

func ( *http2ServeConnOpts) () context.Context {
	if  != nil && .Context != nil {
		return .Context
	}
	return context.Background()
}

func ( *http2ServeConnOpts) () *Server {
	if  != nil && .BaseConfig != nil {
		return .BaseConfig
	}
	return new(Server)
}

func ( *http2ServeConnOpts) () Handler {
	if  != nil {
		if .Handler != nil {
			return .Handler
		}
		if .BaseConfig != nil && .BaseConfig.Handler != nil {
			return .BaseConfig.Handler
		}
	}
	return DefaultServeMux
}

// ServeConn serves HTTP/2 requests on the provided connection and
// blocks until the connection is no longer readable.
//
// ServeConn starts speaking HTTP/2 assuming that c has not had any
// reads or writes. It writes its initial settings frame and expects
// to be able to read the preface and settings frame from the
// client. If c has a ConnectionState method like a *tls.Conn, the
// ConnectionState is used to verify the TLS ciphersuite and to set
// the Request.TLS field in Handlers.
//
// ServeConn does not support h2c by itself. Any h2c support must be
// implemented in terms of providing a suitably-behaving net.Conn.
//
// The opts parameter is optional. If nil, default values are used.
func ( *http2Server) ( net.Conn,  *http2ServeConnOpts) {
	.serveConn(, , nil)
}

func ( *http2Server) ( net.Conn,  *http2ServeConnOpts,  func(*http2serverConn)) {
	,  := http2serverConnBaseContext(, )
	defer ()

	 := .baseConfig()
	 := http2configFromServer(, )
	 := &http2serverConn{
		srv:                         ,
		hs:                          ,
		conn:                        ,
		baseCtx:                     ,
		remoteAddrStr:               .RemoteAddr().String(),
		bw:                          http2newBufferedWriter(.group, , .WriteByteTimeout),
		handler:                     .handler(),
		streams:                     make(map[uint32]*http2stream),
		readFrameCh:                 make(chan http2readFrameResult),
		wantWriteFrameCh:            make(chan http2FrameWriteRequest, 8),
		serveMsgCh:                  make(chan interface{}, 8),
		wroteFrameCh:                make(chan http2frameWriteResult, 1), // buffered; one send in writeFrameAsync
		bodyReadCh:                  make(chan http2bodyReadMsg),         // buffering doesn't matter either way
		doneServing:                 make(chan struct{}),
		clientMaxStreams:            math.MaxUint32, // Section 6.5.2: "Initially, there is no limit to this value"
		advMaxStreams:               .MaxConcurrentStreams,
		initialStreamSendWindowSize: http2initialWindowSize,
		initialStreamRecvWindowSize: .MaxUploadBufferPerStream,
		maxFrameSize:                http2initialMaxFrameSize,
		pingTimeout:                 .PingTimeout,
		countErrorFunc:              .CountError,
		serveG:                      http2newGoroutineLock(),
		pushEnabled:                 true,
		sawClientPreface:            .SawClientPreface,
	}
	if  != nil {
		()
	}

	.state.registerConn()
	defer .state.unregisterConn()

	// The net/http package sets the write deadline from the
	// http.Server.WriteTimeout during the TLS handshake, but then
	// passes the connection off to us with the deadline already set.
	// Write deadlines are set per stream in serverConn.newStream.
	// Disarm the net.Conn write deadline here.
	if .hs.WriteTimeout > 0 {
		.conn.SetWriteDeadline(time.Time{})
	}

	if .NewWriteScheduler != nil {
		.writeSched = .NewWriteScheduler()
	} else {
		.writeSched = http2newRoundRobinWriteScheduler()
	}

	// These start at the RFC-specified defaults. If there is a higher
	// configured value for inflow, that will be updated when we send a
	// WINDOW_UPDATE shortly after sending SETTINGS.
	.flow.add(http2initialWindowSize)
	.inflow.init(http2initialWindowSize)
	.hpackEncoder = hpack.NewEncoder(&.headerWriteBuf)
	.hpackEncoder.SetMaxDynamicTableSizeLimit(.MaxEncoderHeaderTableSize)

	 := http2NewFramer(.bw, )
	if .CountError != nil {
		.countError = .CountError
	}
	.ReadMetaHeaders = hpack.NewDecoder(.MaxDecoderHeaderTableSize, nil)
	.MaxHeaderListSize = .maxHeaderListSize()
	.SetMaxReadFrameSize(.MaxReadFrameSize)
	.framer = 

	if ,  := .(http2connectionStater);  {
		.tlsState = new(tls.ConnectionState)
		*.tlsState = .ConnectionState()
		// 9.2 Use of TLS Features
		// An implementation of HTTP/2 over TLS MUST use TLS
		// 1.2 or higher with the restrictions on feature set
		// and cipher suite described in this section. Due to
		// implementation limitations, it might not be
		// possible to fail TLS negotiation. An endpoint MUST
		// immediately terminate an HTTP/2 connection that
		// does not meet the TLS requirements described in
		// this section with a connection error (Section
		// 5.4.1) of type INADEQUATE_SECURITY.
		if .tlsState.Version < tls.VersionTLS12 {
			.rejectConn(http2ErrCodeInadequateSecurity, "TLS version too low")
			return
		}

		if .tlsState.ServerName == "" {
			// Client must use SNI, but we don't enforce that anymore,
			// since it was causing problems when connecting to bare IP
			// addresses during development.
			//
			// TODO: optionally enforce? Or enforce at the time we receive
			// a new request, and verify the ServerName matches the :authority?
			// But that precludes proxy situations, perhaps.
			//
			// So for now, do nothing here again.
		}

		if !.PermitProhibitedCipherSuites && http2isBadCipher(.tlsState.CipherSuite) {
			// "Endpoints MAY choose to generate a connection error
			// (Section 5.4.1) of type INADEQUATE_SECURITY if one of
			// the prohibited cipher suites are negotiated."
			//
			// We choose that. In my opinion, the spec is weak
			// here. It also says both parties must support at least
			// TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 so there's no
			// excuses here. If we really must, we could allow an
			// "AllowInsecureWeakCiphers" option on the server later.
			// Let's see how it plays out first.
			.rejectConn(http2ErrCodeInadequateSecurity, fmt.Sprintf("Prohibited TLS 1.2 Cipher Suite: %x", .tlsState.CipherSuite))
			return
		}
	}

	if .Settings != nil {
		 := &http2SettingsFrame{
			http2FrameHeader: http2FrameHeader{valid: true},
			p:                .Settings,
		}
		if  := .ForeachSetting(.processSetting);  != nil {
			.rejectConn(http2ErrCodeProtocol, "invalid settings")
			return
		}
		.Settings = nil
	}

	if  := http2testHookGetServerConn;  != nil {
		()
	}

	if .UpgradeRequest != nil {
		.upgradeRequest(.UpgradeRequest)
		.UpgradeRequest = nil
	}

	.serve()
}

func http2serverConnBaseContext( net.Conn,  *http2ServeConnOpts) ( context.Context,  func()) {
	,  = context.WithCancel(.context())
	 = context.WithValue(, LocalAddrContextKey, .LocalAddr())
	if  := .baseConfig();  != nil {
		 = context.WithValue(, ServerContextKey, )
	}
	return
}

func ( *http2serverConn) ( http2ErrCode,  string) {
	.vlogf("http2: server rejecting conn: %v, %s", , )
	// ignoring errors. hanging up anyway.
	.framer.WriteGoAway(0, , []byte())
	.bw.Flush()
	.conn.Close()
}

type http2serverConn struct {
	// Immutable:
	srv              *http2Server
	hs               *Server
	conn             net.Conn
	bw               *http2bufferedWriter // writing to conn
	handler          Handler
	baseCtx          context.Context
	framer           *http2Framer
	doneServing      chan struct{}               // closed when serverConn.serve ends
	readFrameCh      chan http2readFrameResult   // written by serverConn.readFrames
	wantWriteFrameCh chan http2FrameWriteRequest // from handlers -> serve
	wroteFrameCh     chan http2frameWriteResult  // from writeFrameAsync -> serve, tickles more frame writes
	bodyReadCh       chan http2bodyReadMsg       // from handlers -> serve
	serveMsgCh       chan interface{}            // misc messages & code to send to / run on the serve loop
	flow             http2outflow                // conn-wide (not stream-specific) outbound flow control
	inflow           http2inflow                 // conn-wide inbound flow control
	tlsState         *tls.ConnectionState        // shared by all handlers, like net/http
	remoteAddrStr    string
	writeSched       http2WriteScheduler
	countErrorFunc   func(errType string)

	// Everything following is owned by the serve loop; use serveG.check():
	serveG                      http2goroutineLock // used to verify funcs are on serve()
	pushEnabled                 bool
	sawClientPreface            bool // preface has already been read, used in h2c upgrade
	sawFirstSettings            bool // got the initial SETTINGS frame after the preface
	needToSendSettingsAck       bool
	unackedSettings             int    // how many SETTINGS have we sent without ACKs?
	queuedControlFrames         int    // control frames in the writeSched queue
	clientMaxStreams            uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit)
	advMaxStreams               uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
	curClientStreams            uint32 // number of open streams initiated by the client
	curPushedStreams            uint32 // number of open streams initiated by server push
	curHandlers                 uint32 // number of running handler goroutines
	maxClientStreamID           uint32 // max ever seen from client (odd), or 0 if there have been no client requests
	maxPushPromiseID            uint32 // ID of the last push promise (even), or 0 if there have been no pushes
	streams                     map[uint32]*http2stream
	unstartedHandlers           []http2unstartedHandler
	initialStreamSendWindowSize int32
	initialStreamRecvWindowSize int32
	maxFrameSize                int32
	peerMaxHeaderListSize       uint32            // zero means unknown (default)
	canonHeader                 map[string]string // http2-lower-case -> Go-Canonical-Case
	canonHeaderKeysSize         int               // canonHeader keys size in bytes
	writingFrame                bool              // started writing a frame (on serve goroutine or separate)
	writingFrameAsync           bool              // started a frame on its own goroutine but haven't heard back on wroteFrameCh
	needsFrameFlush             bool              // last frame write wasn't a flush
	inGoAway                    bool              // we've started to or sent GOAWAY
	inFrameScheduleLoop         bool              // whether we're in the scheduleFrameWrite loop
	needToSendGoAway            bool              // we need to schedule a GOAWAY frame write
	pingSent                    bool
	sentPingData                [8]byte
	goAwayCode                  http2ErrCode
	shutdownTimer               http2timer // nil until used
	idleTimer                   http2timer // nil if unused
	readIdleTimeout             time.Duration
	pingTimeout                 time.Duration
	readIdleTimer               http2timer // nil if unused

	// Owned by the writeFrameAsync goroutine:
	headerWriteBuf bytes.Buffer
	hpackEncoder   *hpack.Encoder

	// Used by startGracefulShutdown.
	shutdownOnce sync.Once
}

func ( *http2serverConn) () uint32 {
	 := .hs.MaxHeaderBytes
	if  <= 0 {
		 = DefaultMaxHeaderBytes
	}
	return uint32(http2adjustHTTP1MaxHeaderSize(int64()))
}

func ( *http2serverConn) () uint32 {
	.serveG.check()
	return .curClientStreams + .curPushedStreams
}

// stream represents a stream. This is the minimal metadata needed by
// the serve goroutine. Most of the actual stream state is owned by
// the http.Handler's goroutine in the responseWriter. Because the
// responseWriter's responseWriterState is recycled at the end of a
// handler, this struct intentionally has no pointer to the
// *responseWriter{,State} itself, as the Handler ending nils out the
// responseWriter's state field.
type http2stream struct {
	// immutable:
	sc        *http2serverConn
	id        uint32
	body      *http2pipe       // non-nil if expecting DATA frames
	cw        http2closeWaiter // closed wait stream transitions to closed state
	ctx       context.Context
	cancelCtx func()

	// owned by serverConn's serve loop:
	bodyBytes        int64        // body bytes seen so far
	declBodyBytes    int64        // or -1 if undeclared
	flow             http2outflow // limits writing from Handler to client
	inflow           http2inflow  // what the client is allowed to POST/etc to us
	state            http2streamState
	resetQueued      bool       // RST_STREAM queued for write; set by sc.resetStream
	gotTrailerHeader bool       // HEADER frame for trailers was seen
	wroteHeaders     bool       // whether we wrote headers (not status 100)
	readDeadline     http2timer // nil if unused
	writeDeadline    http2timer // nil if unused
	closeErr         error      // set before cw is closed

	trailer    Header // accumulated trailers
	reqTrailer Header // handler's Request.Trailer
}

func ( *http2serverConn) () *http2Framer { return .framer }

func ( *http2serverConn) () error { return .conn.Close() }

func ( *http2serverConn) () error { return .bw.Flush() }

func ( *http2serverConn) () (*hpack.Encoder, *bytes.Buffer) {
	return .hpackEncoder, &.headerWriteBuf
}

func ( *http2serverConn) ( uint32) (http2streamState, *http2stream) {
	.serveG.check()
	// http://tools.ietf.org/html/rfc7540#section-5.1
	if ,  := .streams[];  {
		return .state, 
	}
	// "The first use of a new stream identifier implicitly closes all
	// streams in the "idle" state that might have been initiated by
	// that peer with a lower-valued stream identifier. For example, if
	// a client sends a HEADERS frame on stream 7 without ever sending a
	// frame on stream 5, then stream 5 transitions to the "closed"
	// state when the first frame for stream 7 is sent or received."
	if %2 == 1 {
		if  <= .maxClientStreamID {
			return http2stateClosed, nil
		}
	} else {
		if  <= .maxPushPromiseID {
			return http2stateClosed, nil
		}
	}
	return http2stateIdle, nil
}

// setConnState calls the net/http ConnState hook for this connection, if configured.
// Note that the net/http package does StateNew and StateClosed for us.
// There is currently no plan for StateHijacked or hijacking HTTP/2 connections.
func ( *http2serverConn) ( ConnState) {
	if .hs.ConnState != nil {
		.hs.ConnState(.conn, )
	}
}

func ( *http2serverConn) ( string,  ...interface{}) {
	if http2VerboseLogs {
		.logf(, ...)
	}
}

func ( *http2serverConn) ( string,  ...interface{}) {
	if  := .hs.ErrorLog;  != nil {
		.Printf(, ...)
	} else {
		log.Printf(, ...)
	}
}

// errno returns v's underlying uintptr, else 0.
//
// TODO: remove this helper function once http2 can use build
// tags. See comment in isClosedConnError.
func http2errno( error) uintptr {
	if  := reflect.ValueOf(); .Kind() == reflect.Uintptr {
		return uintptr(.Uint())
	}
	return 0
}

// isClosedConnError reports whether err is an error from use of a closed
// network connection.
func http2isClosedConnError( error) bool {
	if  == nil {
		return false
	}

	if errors.Is(, net.ErrClosed) {
		return true
	}

	// TODO(bradfitz): x/tools/cmd/bundle doesn't really support
	// build tags, so I can't make an http2_windows.go file with
	// Windows-specific stuff. Fix that and move this, once we
	// have a way to bundle this into std's net/http somehow.
	if runtime.GOOS == "windows" {
		if ,  := .(*net.OpError);  && .Op == "read" {
			if ,  := .Err.(*os.SyscallError);  && .Syscall == "wsarecv" {
				const  = 10053
				const  = 10054
				if  := http2errno(.Err);  ==  ||  ==  {
					return true
				}
			}
		}
	}
	return false
}

func ( *http2serverConn) ( error,  string,  ...interface{}) {
	if  == nil {
		return
	}
	if  == io.EOF ||  == io.ErrUnexpectedEOF || http2isClosedConnError() ||  == http2errPrefaceTimeout {
		// Boring, expected errors.
		.vlogf(, ...)
	} else {
		.logf(, ...)
	}
}

// maxCachedCanonicalHeadersKeysSize is an arbitrarily-chosen limit on the size
// of the entries in the canonHeader cache.
// This should be larger than the size of unique, uncommon header keys likely to
// be sent by the peer, while not so high as to permit unreasonable memory usage
// if the peer sends an unbounded number of unique header keys.
const http2maxCachedCanonicalHeadersKeysSize = 2048

func ( *http2serverConn) ( string) string {
	.serveG.check()
	http2buildCommonHeaderMapsOnce()
	,  := http2commonCanonHeader[]
	if  {
		return 
	}
	,  = .canonHeader[]
	if  {
		return 
	}
	if .canonHeader == nil {
		.canonHeader = make(map[string]string)
	}
	 = CanonicalHeaderKey()
	 := 100 + len()*2 // 100 bytes of map overhead + key + value
	if .canonHeaderKeysSize+ <= http2maxCachedCanonicalHeadersKeysSize {
		.canonHeader[] = 
		.canonHeaderKeysSize += 
	}
	return 
}

type http2readFrameResult struct {
	f   http2Frame // valid until readMore is called
	err error

	// readMore should be called once the consumer no longer needs or
	// retains f. After readMore, f is invalid and more frames can be
	// read.
	readMore func()
}

// readFrames is the loop that reads incoming frames.
// It takes care to only read one frame at a time, blocking until the
// consumer is done with the frame.
// It's run on its own goroutine.
func ( *http2serverConn) () {
	.srv.markNewGoroutine()
	 := make(chan struct{})
	 := func() {  <- struct{}{} }
	for {
		,  := .framer.ReadFrame()
		select {
		case .readFrameCh <- http2readFrameResult{, , }:
		case <-.doneServing:
			return
		}
		select {
		case <-:
		case <-.doneServing:
			return
		}
		if http2terminalReadFrameError() {
			return
		}
	}
}

// frameWriteResult is the message passed from writeFrameAsync to the serve goroutine.
type http2frameWriteResult struct {
	_   http2incomparable
	wr  http2FrameWriteRequest // what was written (or attempted)
	err error                  // result of the writeFrame call
}

// writeFrameAsync runs in its own goroutine and writes a single frame
// and then reports when it's done.
// At most one goroutine can be running writeFrameAsync at a time per
// serverConn.
func ( *http2serverConn) ( http2FrameWriteRequest,  *http2writeData) {
	.srv.markNewGoroutine()
	var  error
	if  == nil {
		 = .write.writeFrame()
	} else {
		 = .framer.endWrite()
	}
	.wroteFrameCh <- http2frameWriteResult{wr: , err: }
}

func ( *http2serverConn) () {
	.serveG.check()
	for ,  := range .streams {
		.closeStream(, http2errClientDisconnected)
	}
}

func ( *http2serverConn) () {
	.serveG.check()
	if  := .shutdownTimer;  != nil {
		.Stop()
	}
}

func ( *http2serverConn) () {
	// Note: this is for serverConn.serve panicking, not http.Handler code.
	if http2testHookOnPanicMu != nil {
		http2testHookOnPanicMu.Lock()
		defer http2testHookOnPanicMu.Unlock()
	}
	if http2testHookOnPanic != nil {
		if  := recover();  != nil {
			if http2testHookOnPanic(, ) {
				panic()
			}
		}
	}
}

func ( *http2serverConn) ( http2http2Config) {
	.serveG.check()
	defer .notePanic()
	defer .conn.Close()
	defer .closeAllStreamsOnConnClose()
	defer .stopShutdownTimer()
	defer close(.doneServing) // unblocks handlers trying to send

	if http2VerboseLogs {
		.vlogf("http2: server connection from %v on %p", .conn.RemoteAddr(), .hs)
	}

	 := http2writeSettings{
		{http2SettingMaxFrameSize, .MaxReadFrameSize},
		{http2SettingMaxConcurrentStreams, .advMaxStreams},
		{http2SettingMaxHeaderListSize, .maxHeaderListSize()},
		{http2SettingHeaderTableSize, .MaxDecoderHeaderTableSize},
		{http2SettingInitialWindowSize, uint32(.initialStreamRecvWindowSize)},
	}
	if !http2disableExtendedConnectProtocol {
		 = append(, http2Setting{http2SettingEnableConnectProtocol, 1})
	}
	.writeFrame(http2FrameWriteRequest{
		write: ,
	})
	.unackedSettings++

	// Each connection starts with initialWindowSize inflow tokens.
	// If a higher value is configured, we add more tokens.
	if  := .MaxUploadBufferPerConnection - http2initialWindowSize;  > 0 {
		.sendWindowUpdate(nil, int())
	}

	if  := .readPreface();  != nil {
		.condlogf(, "http2: server: error reading preface from client %v: %v", .conn.RemoteAddr(), )
		return
	}
	// Now that we've got the preface, get us out of the
	// "StateNew" state. We can't go directly to idle, though.
	// Active means we read some data and anticipate a request. We'll
	// do another Active when we get a HEADERS frame.
	.setConnState(StateActive)
	.setConnState(StateIdle)

	if .srv.IdleTimeout > 0 {
		.idleTimer = .srv.afterFunc(.srv.IdleTimeout, .onIdleTimer)
		defer .idleTimer.Stop()
	}

	if .SendPingTimeout > 0 {
		.readIdleTimeout = .SendPingTimeout
		.readIdleTimer = .srv.afterFunc(.SendPingTimeout, .onReadIdleTimer)
		defer .readIdleTimer.Stop()
	}

	go .readFrames() // closed by defer sc.conn.Close above

	 := .srv.afterFunc(http2firstSettingsTimeout, .onSettingsTimer)
	defer .Stop()

	 := .srv.now()
	 := 0
	for {
		++
		select {
		case  := <-.wantWriteFrameCh:
			if ,  := .write.(http2StreamError);  {
				.resetStream()
				break
			}
			.writeFrame()
		case  := <-.wroteFrameCh:
			.wroteFrame()
		case  := <-.readFrameCh:
			 = .srv.now()
			// Process any written frames before reading new frames from the client since a
			// written frame could have triggered a new stream to be started.
			if .writingFrameAsync {
				select {
				case  := <-.wroteFrameCh:
					.wroteFrame()
				default:
				}
			}
			if !.processFrameFromReader() {
				return
			}
			.readMore()
			if  != nil {
				.Stop()
				 = nil
			}
		case  := <-.bodyReadCh:
			.noteBodyRead(.st, .n)
		case  := <-.serveMsgCh:
			switch v := .(type) {
			case func(int):
				() // for testing
			case *http2serverMessage:
				switch  {
				case http2settingsTimerMsg:
					.logf("timeout waiting for SETTINGS frames from %v", .conn.RemoteAddr())
					return
				case http2idleTimerMsg:
					.vlogf("connection is idle")
					.goAway(http2ErrCodeNo)
				case http2readIdleTimerMsg:
					.handlePingTimer()
				case http2shutdownTimerMsg:
					.vlogf("GOAWAY close timer fired; closing conn from %v", .conn.RemoteAddr())
					return
				case http2gracefulShutdownMsg:
					.startGracefulShutdownInternal()
				case http2handlerDoneMsg:
					.handlerDone()
				default:
					panic("unknown timer")
				}
			case *http2startPushRequest:
				.startPush()
			case func(*http2serverConn):
				()
			default:
				panic(fmt.Sprintf("unexpected type %T", ))
			}
		}

		// If the peer is causing us to generate a lot of control frames,
		// but not reading them from us, assume they are trying to make us
		// run out of memory.
		if .queuedControlFrames > http2maxQueuedControlFrames {
			.vlogf("http2: too many control frames in send queue, closing connection")
			return
		}

		// Start the shutdown timer after sending a GOAWAY. When sending GOAWAY
		// with no error code (graceful shutdown), don't start the timer until
		// all open streams have been completed.
		 := .inGoAway && !.needToSendGoAway && !.writingFrame
		 := .goAwayCode == http2ErrCodeNo && .curOpenStreams() == 0
		if  && .shutdownTimer == nil && (.goAwayCode != http2ErrCodeNo || ) {
			.shutDownIn(http2goAwayTimeout)
		}
	}
}

func ( *http2serverConn) ( time.Time) {
	if .pingSent {
		.vlogf("timeout waiting for PING response")
		.conn.Close()
		return
	}

	 := .Add(.readIdleTimeout)
	 := .srv.now()
	if .After() {
		// We received frames since arming the ping timer.
		// Reset it for the next possible timeout.
		.readIdleTimer.Reset(.Sub())
		return
	}

	.pingSent = true
	// Ignore crypto/rand.Read errors: It generally can't fail, and worse case if it does
	// is we send a PING frame containing 0s.
	_, _ = rand.Read(.sentPingData[:])
	.writeFrame(http2FrameWriteRequest{
		write: &http2writePing{data: .sentPingData},
	})
	.readIdleTimer.Reset(.pingTimeout)
}

type http2serverMessage int

// Message values sent to serveMsgCh.
var (
	http2settingsTimerMsg    = new(http2serverMessage)
	http2idleTimerMsg        = new(http2serverMessage)
	http2readIdleTimerMsg    = new(http2serverMessage)
	http2shutdownTimerMsg    = new(http2serverMessage)
	http2gracefulShutdownMsg = new(http2serverMessage)
	http2handlerDoneMsg      = new(http2serverMessage)
)

func ( *http2serverConn) () { .sendServeMsg(http2settingsTimerMsg) }

func ( *http2serverConn) () { .sendServeMsg(http2idleTimerMsg) }

func ( *http2serverConn) () { .sendServeMsg(http2readIdleTimerMsg) }

func ( *http2serverConn) () { .sendServeMsg(http2shutdownTimerMsg) }

func ( *http2serverConn) ( interface{}) {
	.serveG.checkNotOn() // NOT
	select {
	case .serveMsgCh <- :
	case <-.doneServing:
	}
}

var http2errPrefaceTimeout = errors.New("timeout waiting for client preface")

// readPreface reads the ClientPreface greeting from the peer or
// returns errPrefaceTimeout on timeout, or an error if the greeting
// is invalid.
func ( *http2serverConn) () error {
	if .sawClientPreface {
		return nil
	}
	 := make(chan error, 1)
	go func() {
		// Read the client preface
		 := make([]byte, len(http2ClientPreface))
		if ,  := io.ReadFull(.conn, );  != nil {
			 <- 
		} else if !bytes.Equal(, http2clientPreface) {
			 <- fmt.Errorf("bogus greeting %q", )
		} else {
			 <- nil
		}
	}()
	 := .srv.newTimer(http2prefaceTimeout) // TODO: configurable on *Server?
	defer .Stop()
	select {
	case <-.C():
		return http2errPrefaceTimeout
	case  := <-:
		if  == nil {
			if http2VerboseLogs {
				.vlogf("http2: server: client %v said hello", .conn.RemoteAddr())
			}
		}
		return 
	}
}

var http2errChanPool = sync.Pool{
	New: func() interface{} { return make(chan error, 1) },
}

var http2writeDataPool = sync.Pool{
	New: func() interface{} { return new(http2writeData) },
}

// writeDataFromHandler writes DATA response frames from a handler on
// the given stream.
func ( *http2serverConn) ( *http2stream,  []byte,  bool) error {
	 := http2errChanPool.Get().(chan error)
	 := http2writeDataPool.Get().(*http2writeData)
	* = http2writeData{.id, , }
	 := .writeFrameFromHandler(http2FrameWriteRequest{
		write:  ,
		stream: ,
		done:   ,
	})
	if  != nil {
		return 
	}
	var  bool // the frame write is done (successfully or not)
	select {
	case  = <-:
		 = true
	case <-.doneServing:
		return http2errClientDisconnected
	case <-.cw:
		// If both ch and stream.cw were ready (as might
		// happen on the final Write after an http.Handler
		// ends), prefer the write result. Otherwise this
		// might just be us successfully closing the stream.
		// The writeFrameAsync and serve goroutines guarantee
		// that the ch send will happen before the stream.cw
		// close.
		select {
		case  = <-:
			 = true
		default:
			return http2errStreamClosed
		}
	}
	http2errChanPool.Put()
	if  {
		http2writeDataPool.Put()
	}
	return 
}

// writeFrameFromHandler sends wr to sc.wantWriteFrameCh, but aborts
// if the connection has gone away.
//
// This must not be run from the serve goroutine itself, else it might
// deadlock writing to sc.wantWriteFrameCh (which is only mildly
// buffered and is read by serve itself). If you're on the serve
// goroutine, call writeFrame instead.
func ( *http2serverConn) ( http2FrameWriteRequest) error {
	.serveG.checkNotOn() // NOT
	select {
	case .wantWriteFrameCh <- :
		return nil
	case <-.doneServing:
		// Serve loop is gone.
		// Client has closed their connection to the server.
		return http2errClientDisconnected
	}
}

// writeFrame schedules a frame to write and sends it if there's nothing
// already being written.
//
// There is no pushback here (the serve goroutine never blocks). It's
// the http.Handlers that block, waiting for their previous frames to
// make it onto the wire
//
// If you're not on the serve goroutine, use writeFrameFromHandler instead.
func ( *http2serverConn) ( http2FrameWriteRequest) {
	.serveG.check()

	// If true, wr will not be written and wr.done will not be signaled.
	var  bool

	// We are not allowed to write frames on closed streams. RFC 7540 Section
	// 5.1.1 says: "An endpoint MUST NOT send frames other than PRIORITY on
	// a closed stream." Our server never sends PRIORITY, so that exception
	// does not apply.
	//
	// The serverConn might close an open stream while the stream's handler
	// is still running. For example, the server might close a stream when it
	// receives bad data from the client. If this happens, the handler might
	// attempt to write a frame after the stream has been closed (since the
	// handler hasn't yet been notified of the close). In this case, we simply
	// ignore the frame. The handler will notice that the stream is closed when
	// it waits for the frame to be written.
	//
	// As an exception to this rule, we allow sending RST_STREAM after close.
	// This allows us to immediately reject new streams without tracking any
	// state for those streams (except for the queued RST_STREAM frame). This
	// may result in duplicate RST_STREAMs in some cases, but the client should
	// ignore those.
	if .StreamID() != 0 {
		,  := .write.(http2StreamError)
		if ,  := .state(.StreamID());  == http2stateClosed && ! {
			 = true
		}
	}

	// Don't send a 100-continue response if we've already sent headers.
	// See golang.org/issue/14030.
	switch .write.(type) {
	case *http2writeResHeaders:
		.stream.wroteHeaders = true
	case http2write100ContinueHeadersFrame:
		if .stream.wroteHeaders {
			// We do not need to notify wr.done because this frame is
			// never written with wr.done != nil.
			if .done != nil {
				panic("wr.done != nil for write100ContinueHeadersFrame")
			}
			 = true
		}
	}

	if ! {
		if .isControl() {
			.queuedControlFrames++
			// For extra safety, detect wraparounds, which should not happen,
			// and pull the plug.
			if .queuedControlFrames < 0 {
				.conn.Close()
			}
		}
		.writeSched.Push()
	}
	.scheduleFrameWrite()
}

// startFrameWrite starts a goroutine to write wr (in a separate
// goroutine since that might block on the network), and updates the
// serve goroutine's state about the world, updated from info in wr.
func ( *http2serverConn) ( http2FrameWriteRequest) {
	.serveG.check()
	if .writingFrame {
		panic("internal error: can only be writing one frame at a time")
	}

	 := .stream
	if  != nil {
		switch .state {
		case http2stateHalfClosedLocal:
			switch .write.(type) {
			case http2StreamError, http2handlerPanicRST, http2writeWindowUpdate:
				// RFC 7540 Section 5.1 allows sending RST_STREAM, PRIORITY, and WINDOW_UPDATE
				// in this state. (We never send PRIORITY from the server, so that is not checked.)
			default:
				panic(fmt.Sprintf("internal error: attempt to send frame on a half-closed-local stream: %v", ))
			}
		case http2stateClosed:
			panic(fmt.Sprintf("internal error: attempt to send frame on a closed stream: %v", ))
		}
	}
	if ,  := .write.(*http2writePushPromise);  {
		var  error
		.promisedID,  = .allocatePromisedID()
		if  != nil {
			.writingFrameAsync = false
			.replyToWriter()
			return
		}
	}

	.writingFrame = true
	.needsFrameFlush = true
	if .write.staysWithinBuffer(.bw.Available()) {
		.writingFrameAsync = false
		 := .write.writeFrame()
		.wroteFrame(http2frameWriteResult{wr: , err: })
	} else if ,  := .write.(*http2writeData);  {
		// Encode the frame in the serve goroutine, to ensure we don't have
		// any lingering asynchronous references to data passed to Write.
		// See https://go.dev/issue/58446.
		.framer.startWriteDataPadded(.streamID, .endStream, .p, nil)
		.writingFrameAsync = true
		go .writeFrameAsync(, )
	} else {
		.writingFrameAsync = true
		go .writeFrameAsync(, nil)
	}
}

// errHandlerPanicked is the error given to any callers blocked in a read from
// Request.Body when the main goroutine panics. Since most handlers read in the
// main ServeHTTP goroutine, this will show up rarely.
var http2errHandlerPanicked = errors.New("http2: handler panicked")

// wroteFrame is called on the serve goroutine with the result of
// whatever happened on writeFrameAsync.
func ( *http2serverConn) ( http2frameWriteResult) {
	.serveG.check()
	if !.writingFrame {
		panic("internal error: expected to be already writing a frame")
	}
	.writingFrame = false
	.writingFrameAsync = false

	if .err != nil {
		.conn.Close()
	}

	 := .wr

	if http2writeEndsStream(.write) {
		 := .stream
		if  == nil {
			panic("internal error: expecting non-nil stream")
		}
		switch .state {
		case http2stateOpen:
			// Here we would go to stateHalfClosedLocal in
			// theory, but since our handler is done and
			// the net/http package provides no mechanism
			// for closing a ResponseWriter while still
			// reading data (see possible TODO at top of
			// this file), we go into closed state here
			// anyway, after telling the peer we're
			// hanging up on them. We'll transition to
			// stateClosed after the RST_STREAM frame is
			// written.
			.state = http2stateHalfClosedLocal
			// Section 8.1: a server MAY request that the client abort
			// transmission of a request without error by sending a
			// RST_STREAM with an error code of NO_ERROR after sending
			// a complete response.
			.resetStream(http2streamError(.id, http2ErrCodeNo))
		case http2stateHalfClosedRemote:
			.closeStream(, http2errHandlerComplete)
		}
	} else {
		switch v := .write.(type) {
		case http2StreamError:
			// st may be unknown if the RST_STREAM was generated to reject bad input.
			if ,  := .streams[.StreamID];  {
				.closeStream(, )
			}
		case http2handlerPanicRST:
			.closeStream(.stream, http2errHandlerPanicked)
		}
	}

	// Reply (if requested) to unblock the ServeHTTP goroutine.
	.replyToWriter(.err)

	.scheduleFrameWrite()
}

// scheduleFrameWrite tickles the frame writing scheduler.
//
// If a frame is already being written, nothing happens. This will be called again
// when the frame is done being written.
//
// If a frame isn't being written and we need to send one, the best frame
// to send is selected by writeSched.
//
// If a frame isn't being written and there's nothing else to send, we
// flush the write buffer.
func ( *http2serverConn) () {
	.serveG.check()
	if .writingFrame || .inFrameScheduleLoop {
		return
	}
	.inFrameScheduleLoop = true
	for !.writingFrameAsync {
		if .needToSendGoAway {
			.needToSendGoAway = false
			.startFrameWrite(http2FrameWriteRequest{
				write: &http2writeGoAway{
					maxStreamID: .maxClientStreamID,
					code:        .goAwayCode,
				},
			})
			continue
		}
		if .needToSendSettingsAck {
			.needToSendSettingsAck = false
			.startFrameWrite(http2FrameWriteRequest{write: http2writeSettingsAck{}})
			continue
		}
		if !.inGoAway || .goAwayCode == http2ErrCodeNo {
			if ,  := .writeSched.Pop();  {
				if .isControl() {
					.queuedControlFrames--
				}
				.startFrameWrite()
				continue
			}
		}
		if .needsFrameFlush {
			.startFrameWrite(http2FrameWriteRequest{write: http2flushFrameWriter{}})
			.needsFrameFlush = false // after startFrameWrite, since it sets this true
			continue
		}
		break
	}
	.inFrameScheduleLoop = false
}

// startGracefulShutdown gracefully shuts down a connection. This
// sends GOAWAY with ErrCodeNo to tell the client we're gracefully
// shutting down. The connection isn't closed until all current
// streams are done.
//
// startGracefulShutdown returns immediately; it does not wait until
// the connection has shut down.
func ( *http2serverConn) () {
	.serveG.checkNotOn() // NOT
	.shutdownOnce.Do(func() { .sendServeMsg(http2gracefulShutdownMsg) })
}

// After sending GOAWAY with an error code (non-graceful shutdown), the
// connection will close after goAwayTimeout.
//
// If we close the connection immediately after sending GOAWAY, there may
// be unsent data in our kernel receive buffer, which will cause the kernel
// to send a TCP RST on close() instead of a FIN. This RST will abort the
// connection immediately, whether or not the client had received the GOAWAY.
//
// Ideally we should delay for at least 1 RTT + epsilon so the client has
// a chance to read the GOAWAY and stop sending messages. Measuring RTT
// is hard, so we approximate with 1 second. See golang.org/issue/18701.
//
// This is a var so it can be shorter in tests, where all requests uses the
// loopback interface making the expected RTT very small.
//
// TODO: configurable?
var http2goAwayTimeout = 1 * time.Second

func ( *http2serverConn) () {
	.goAway(http2ErrCodeNo)
}

func ( *http2serverConn) ( http2ErrCode) {
	.serveG.check()
	if .inGoAway {
		if .goAwayCode == http2ErrCodeNo {
			.goAwayCode = 
		}
		return
	}
	.inGoAway = true
	.needToSendGoAway = true
	.goAwayCode = 
	.scheduleFrameWrite()
}

func ( *http2serverConn) ( time.Duration) {
	.serveG.check()
	.shutdownTimer = .srv.afterFunc(, .onShutdownTimer)
}

func ( *http2serverConn) ( http2StreamError) {
	.serveG.check()
	.writeFrame(http2FrameWriteRequest{write: })
	if ,  := .streams[.StreamID];  {
		.resetQueued = true
	}
}

// processFrameFromReader processes the serve loop's read from readFrameCh from the
// frame-reading goroutine.
// processFrameFromReader returns whether the connection should be kept open.
func ( *http2serverConn) ( http2readFrameResult) bool {
	.serveG.check()
	 := .err
	if  != nil {
		if  == http2ErrFrameTooLarge {
			.goAway(http2ErrCodeFrameSize)
			return true // goAway will close the loop
		}
		 :=  == io.EOF ||  == io.ErrUnexpectedEOF || http2isClosedConnError()
		if  {
			// TODO: could we also get into this state if
			// the peer does a half close
			// (e.g. CloseWrite) because they're done
			// sending frames but they're still wanting
			// our open replies?  Investigate.
			// TODO: add CloseWrite to crypto/tls.Conn first
			// so we have a way to test this? I suppose
			// just for testing we could have a non-TLS mode.
			return false
		}
	} else {
		 := .f
		if http2VerboseLogs {
			.vlogf("http2: server read frame %v", http2summarizeFrame())
		}
		 = .processFrame()
		if  == nil {
			return true
		}
	}

	switch ev := .(type) {
	case http2StreamError:
		.resetStream()
		return true
	case http2goAwayFlowError:
		.goAway(http2ErrCodeFlowControl)
		return true
	case http2ConnectionError:
		if .f != nil {
			if  := .f.Header().StreamID;  > .maxClientStreamID {
				.maxClientStreamID = 
			}
		}
		.logf("http2: server connection error from %v: %v", .conn.RemoteAddr(), )
		.goAway(http2ErrCode())
		return true // goAway will handle shutdown
	default:
		if .err != nil {
			.vlogf("http2: server closing client connection; error reading frame from client %s: %v", .conn.RemoteAddr(), )
		} else {
			.logf("http2: server closing client connection: %v", )
		}
		return false
	}
}

func ( *http2serverConn) ( http2Frame) error {
	.serveG.check()

	// First frame received must be SETTINGS.
	if !.sawFirstSettings {
		if ,  := .(*http2SettingsFrame); ! {
			return .countError("first_settings", http2ConnectionError(http2ErrCodeProtocol))
		}
		.sawFirstSettings = true
	}

	// Discard frames for streams initiated after the identified last
	// stream sent in a GOAWAY, or all frames after sending an error.
	// We still need to return connection-level flow control for DATA frames.
	// RFC 9113 Section 6.8.
	if .inGoAway && (.goAwayCode != http2ErrCodeNo || .Header().StreamID > .maxClientStreamID) {

		if ,  := .(*http2DataFrame);  {
			if !.inflow.take(.Length) {
				return .countError("data_flow", http2streamError(.Header().StreamID, http2ErrCodeFlowControl))
			}
			.sendWindowUpdate(nil, int(.Length)) // conn-level
		}
		return nil
	}

	switch f := .(type) {
	case *http2SettingsFrame:
		return .processSettings()
	case *http2MetaHeadersFrame:
		return .processHeaders()
	case *http2WindowUpdateFrame:
		return .processWindowUpdate()
	case *http2PingFrame:
		return .processPing()
	case *http2DataFrame:
		return .processData()
	case *http2RSTStreamFrame:
		return .processResetStream()
	case *http2PriorityFrame:
		return .processPriority()
	case *http2GoAwayFrame:
		return .processGoAway()
	case *http2PushPromiseFrame:
		// A client cannot push. Thus, servers MUST treat the receipt of a PUSH_PROMISE
		// frame as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
		return .countError("push_promise", http2ConnectionError(http2ErrCodeProtocol))
	default:
		.vlogf("http2: server ignoring frame: %v", .Header())
		return nil
	}
}

func ( *http2serverConn) ( *http2PingFrame) error {
	.serveG.check()
	if .IsAck() {
		if .pingSent && .sentPingData == .Data {
			// This is a response to a PING we sent.
			.pingSent = false
			.readIdleTimer.Reset(.readIdleTimeout)
		}
		// 6.7 PING: " An endpoint MUST NOT respond to PING frames
		// containing this flag."
		return nil
	}
	if .StreamID != 0 {
		// "PING frames are not associated with any individual
		// stream. If a PING frame is received with a stream
		// identifier field value other than 0x0, the recipient MUST
		// respond with a connection error (Section 5.4.1) of type
		// PROTOCOL_ERROR."
		return .countError("ping_on_stream", http2ConnectionError(http2ErrCodeProtocol))
	}
	.writeFrame(http2FrameWriteRequest{write: http2writePingAck{}})
	return nil
}

func ( *http2serverConn) ( *http2WindowUpdateFrame) error {
	.serveG.check()
	switch {
	case .StreamID != 0: // stream-level flow control
		,  := .state(.StreamID)
		if  == http2stateIdle {
			// Section 5.1: "Receiving any frame other than HEADERS
			// or PRIORITY on a stream in this state MUST be
			// treated as a connection error (Section 5.4.1) of
			// type PROTOCOL_ERROR."
			return .countError("stream_idle", http2ConnectionError(http2ErrCodeProtocol))
		}
		if  == nil {
			// "WINDOW_UPDATE can be sent by a peer that has sent a
			// frame bearing the END_STREAM flag. This means that a
			// receiver could receive a WINDOW_UPDATE frame on a "half
			// closed (remote)" or "closed" stream. A receiver MUST
			// NOT treat this as an error, see Section 5.1."
			return nil
		}
		if !.flow.add(int32(.Increment)) {
			return .countError("bad_flow", http2streamError(.StreamID, http2ErrCodeFlowControl))
		}
	default: // connection-level flow control
		if !.flow.add(int32(.Increment)) {
			return http2goAwayFlowError{}
		}
	}
	.scheduleFrameWrite()
	return nil
}

func ( *http2serverConn) ( *http2RSTStreamFrame) error {
	.serveG.check()

	,  := .state(.StreamID)
	if  == http2stateIdle {
		// 6.4 "RST_STREAM frames MUST NOT be sent for a
		// stream in the "idle" state. If a RST_STREAM frame
		// identifying an idle stream is received, the
		// recipient MUST treat this as a connection error
		// (Section 5.4.1) of type PROTOCOL_ERROR.
		return .countError("reset_idle_stream", http2ConnectionError(http2ErrCodeProtocol))
	}
	if  != nil {
		.cancelCtx()
		.closeStream(, http2streamError(.StreamID, .ErrCode))
	}
	return nil
}

func ( *http2serverConn) ( *http2stream,  error) {
	.serveG.check()
	if .state == http2stateIdle || .state == http2stateClosed {
		panic(fmt.Sprintf("invariant; can't close stream in state %v", .state))
	}
	.state = http2stateClosed
	if .readDeadline != nil {
		.readDeadline.Stop()
	}
	if .writeDeadline != nil {
		.writeDeadline.Stop()
	}
	if .isPushed() {
		.curPushedStreams--
	} else {
		.curClientStreams--
	}
	delete(.streams, .id)
	if len(.streams) == 0 {
		.setConnState(StateIdle)
		if .srv.IdleTimeout > 0 && .idleTimer != nil {
			.idleTimer.Reset(.srv.IdleTimeout)
		}
		if http2h1ServerKeepAlivesDisabled(.hs) {
			.startGracefulShutdownInternal()
		}
	}
	if  := .body;  != nil {
		// Return any buffered unread bytes worth of conn-level flow control.
		// See golang.org/issue/16481
		.sendWindowUpdate(nil, .Len())

		.CloseWithError()
	}
	if ,  := .(http2StreamError);  {
		if .Cause != nil {
			 = .Cause
		} else {
			 = http2errStreamClosed
		}
	}
	.closeErr = 
	.cancelCtx()
	.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc
	.writeSched.CloseStream(.id)
}

func ( *http2serverConn) ( *http2SettingsFrame) error {
	.serveG.check()
	if .IsAck() {
		.unackedSettings--
		if .unackedSettings < 0 {
			// Why is the peer ACKing settings we never sent?
			// The spec doesn't mention this case, but
			// hang up on them anyway.
			return .countError("ack_mystery", http2ConnectionError(http2ErrCodeProtocol))
		}
		return nil
	}
	if .NumSettings() > 100 || .HasDuplicates() {
		// This isn't actually in the spec, but hang up on
		// suspiciously large settings frames or those with
		// duplicate entries.
		return .countError("settings_big_or_dups", http2ConnectionError(http2ErrCodeProtocol))
	}
	if  := .ForeachSetting(.processSetting);  != nil {
		return 
	}
	// TODO: judging by RFC 7540, Section 6.5.3 each SETTINGS frame should be
	// acknowledged individually, even if multiple are received before the ACK.
	.needToSendSettingsAck = true
	.scheduleFrameWrite()
	return nil
}

func ( *http2serverConn) ( http2Setting) error {
	.serveG.check()
	if  := .Valid();  != nil {
		return 
	}
	if http2VerboseLogs {
		.vlogf("http2: server processing setting %v", )
	}
	switch .ID {
	case http2SettingHeaderTableSize:
		.hpackEncoder.SetMaxDynamicTableSize(.Val)
	case http2SettingEnablePush:
		.pushEnabled = .Val != 0
	case http2SettingMaxConcurrentStreams:
		.clientMaxStreams = .Val
	case http2SettingInitialWindowSize:
		return .processSettingInitialWindowSize(.Val)
	case http2SettingMaxFrameSize:
		.maxFrameSize = int32(.Val) // the maximum valid s.Val is < 2^31
	case http2SettingMaxHeaderListSize:
		.peerMaxHeaderListSize = .Val
	case http2SettingEnableConnectProtocol:
		// Receipt of this parameter by a server does not
		// have any impact
	default:
		// Unknown setting: "An endpoint that receives a SETTINGS
		// frame with any unknown or unsupported identifier MUST
		// ignore that setting."
		if http2VerboseLogs {
			.vlogf("http2: server ignoring unknown setting %v", )
		}
	}
	return nil
}

func ( *http2serverConn) ( uint32) error {
	.serveG.check()
	// Note: val already validated to be within range by
	// processSetting's Valid call.

	// "A SETTINGS frame can alter the initial flow control window
	// size for all current streams. When the value of
	// SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver MUST
	// adjust the size of all stream flow control windows that it
	// maintains by the difference between the new value and the
	// old value."
	 := .initialStreamSendWindowSize
	.initialStreamSendWindowSize = int32()
	 := int32() -  // may be negative
	for ,  := range .streams {
		if !.flow.add() {
			// 6.9.2 Initial Flow Control Window Size
			// "An endpoint MUST treat a change to
			// SETTINGS_INITIAL_WINDOW_SIZE that causes any flow
			// control window to exceed the maximum size as a
			// connection error (Section 5.4.1) of type
			// FLOW_CONTROL_ERROR."
			return .countError("setting_win_size", http2ConnectionError(http2ErrCodeFlowControl))
		}
	}
	return nil
}

func ( *http2serverConn) ( *http2DataFrame) error {
	.serveG.check()
	 := .Header().StreamID

	 := .Data()
	,  := .state()
	if  == 0 ||  == http2stateIdle {
		// Section 6.1: "DATA frames MUST be associated with a
		// stream. If a DATA frame is received whose stream
		// identifier field is 0x0, the recipient MUST respond
		// with a connection error (Section 5.4.1) of type
		// PROTOCOL_ERROR."
		//
		// Section 5.1: "Receiving any frame other than HEADERS
		// or PRIORITY on a stream in this state MUST be
		// treated as a connection error (Section 5.4.1) of
		// type PROTOCOL_ERROR."
		return .countError("data_on_idle", http2ConnectionError(http2ErrCodeProtocol))
	}

	// "If a DATA frame is received whose stream is not in "open"
	// or "half closed (local)" state, the recipient MUST respond
	// with a stream error (Section 5.4.2) of type STREAM_CLOSED."
	if  == nil ||  != http2stateOpen || .gotTrailerHeader || .resetQueued {
		// This includes sending a RST_STREAM if the stream is
		// in stateHalfClosedLocal (which currently means that
		// the http.Handler returned, so it's done reading &
		// done writing). Try to stop the client from sending
		// more DATA.

		// But still enforce their connection-level flow control,
		// and return any flow control bytes since we're not going
		// to consume them.
		if !.inflow.take(.Length) {
			return .countError("data_flow", http2streamError(, http2ErrCodeFlowControl))
		}
		.sendWindowUpdate(nil, int(.Length)) // conn-level

		if  != nil && .resetQueued {
			// Already have a stream error in flight. Don't send another.
			return nil
		}
		return .countError("closed", http2streamError(, http2ErrCodeStreamClosed))
	}
	if .body == nil {
		panic("internal error: should have a body in this state")
	}

	// Sender sending more than they'd declared?
	if .declBodyBytes != -1 && .bodyBytes+int64(len()) > .declBodyBytes {
		if !.inflow.take(.Length) {
			return .countError("data_flow", http2streamError(, http2ErrCodeFlowControl))
		}
		.sendWindowUpdate(nil, int(.Length)) // conn-level

		.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", .declBodyBytes))
		// RFC 7540, sec 8.1.2.6: A request or response is also malformed if the
		// value of a content-length header field does not equal the sum of the
		// DATA frame payload lengths that form the body.
		return .countError("send_too_much", http2streamError(, http2ErrCodeProtocol))
	}
	if .Length > 0 {
		// Check whether the client has flow control quota.
		if !http2takeInflows(&.inflow, &.inflow, .Length) {
			return .countError("flow_on_data_length", http2streamError(, http2ErrCodeFlowControl))
		}

		if len() > 0 {
			.bodyBytes += int64(len())
			,  := .body.Write()
			if  != nil {
				// The handler has closed the request body.
				// Return the connection-level flow control for the discarded data,
				// but not the stream-level flow control.
				.sendWindowUpdate(nil, int(.Length)-)
				return nil
			}
			if  != len() {
				panic("internal error: bad Writer")
			}
		}

		// Return any padded flow control now, since we won't
		// refund it later on body reads.
		// Call sendWindowUpdate even if there is no padding,
		// to return buffered flow control credit if the sent
		// window has shrunk.
		 := int32(.Length) - int32(len())
		.sendWindowUpdate32(nil, )
		.sendWindowUpdate32(, )
	}
	if .StreamEnded() {
		.endStream()
	}
	return nil
}

func ( *http2serverConn) ( *http2GoAwayFrame) error {
	.serveG.check()
	if .ErrCode != http2ErrCodeNo {
		.logf("http2: received GOAWAY %+v, starting graceful shutdown", )
	} else {
		.vlogf("http2: received GOAWAY %+v, starting graceful shutdown", )
	}
	.startGracefulShutdownInternal()
	// http://tools.ietf.org/html/rfc7540#section-6.8
	// We should not create any new streams, which means we should disable push.
	.pushEnabled = false
	return nil
}

// isPushed reports whether the stream is server-initiated.
func ( *http2stream) () bool {
	return .id%2 == 0
}

// endStream closes a Request.Body's pipe. It is called when a DATA
// frame says a request body is over (or after trailers).
func ( *http2stream) () {
	 := .sc
	.serveG.check()

	if .declBodyBytes != -1 && .declBodyBytes != .bodyBytes {
		.body.CloseWithError(fmt.Errorf("request declared a Content-Length of %d but only wrote %d bytes",
			.declBodyBytes, .bodyBytes))
	} else {
		.body.closeWithErrorAndCode(io.EOF, .copyTrailersToHandlerRequest)
		.body.CloseWithError(io.EOF)
	}
	.state = http2stateHalfClosedRemote
}

// copyTrailersToHandlerRequest is run in the Handler's goroutine in
// its Request.Body.Read just before it gets io.EOF.
func ( *http2stream) () {
	for ,  := range .trailer {
		if ,  := .reqTrailer[];  {
			// Only copy it over it was pre-declared.
			.reqTrailer[] = 
		}
	}
}

// onReadTimeout is run on its own goroutine (from time.AfterFunc)
// when the stream's ReadTimeout has fired.
func ( *http2stream) () {
	if .body != nil {
		// Wrap the ErrDeadlineExceeded to avoid callers depending on us
		// returning the bare error.
		.body.CloseWithError(fmt.Errorf("%w", os.ErrDeadlineExceeded))
	}
}

// onWriteTimeout is run on its own goroutine (from time.AfterFunc)
// when the stream's WriteTimeout has fired.
func ( *http2stream) () {
	.sc.writeFrameFromHandler(http2FrameWriteRequest{write: http2StreamError{
		StreamID: .id,
		Code:     http2ErrCodeInternal,
		Cause:    os.ErrDeadlineExceeded,
	}})
}

func ( *http2serverConn) ( *http2MetaHeadersFrame) error {
	.serveG.check()
	 := .StreamID
	// http://tools.ietf.org/html/rfc7540#section-5.1.1
	// Streams initiated by a client MUST use odd-numbered stream
	// identifiers. [...] An endpoint that receives an unexpected
	// stream identifier MUST respond with a connection error
	// (Section 5.4.1) of type PROTOCOL_ERROR.
	if %2 != 1 {
		return .countError("headers_even", http2ConnectionError(http2ErrCodeProtocol))
	}
	// A HEADERS frame can be used to create a new stream or
	// send a trailer for an open one. If we already have a stream
	// open, let it process its own HEADERS frame (trailers at this
	// point, if it's valid).
	if  := .streams[.StreamID];  != nil {
		if .resetQueued {
			// We're sending RST_STREAM to close the stream, so don't bother
			// processing this frame.
			return nil
		}
		// RFC 7540, sec 5.1: If an endpoint receives additional frames, other than
		// WINDOW_UPDATE, PRIORITY, or RST_STREAM, for a stream that is in
		// this state, it MUST respond with a stream error (Section 5.4.2) of
		// type STREAM_CLOSED.
		if .state == http2stateHalfClosedRemote {
			return .countError("headers_half_closed", http2streamError(, http2ErrCodeStreamClosed))
		}
		return .processTrailerHeaders()
	}

	// [...] The identifier of a newly established stream MUST be
	// numerically greater than all streams that the initiating
	// endpoint has opened or reserved. [...]  An endpoint that
	// receives an unexpected stream identifier MUST respond with
	// a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
	if  <= .maxClientStreamID {
		return .countError("stream_went_down", http2ConnectionError(http2ErrCodeProtocol))
	}
	.maxClientStreamID = 

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

	// http://tools.ietf.org/html/rfc7540#section-5.1.2
	// [...] Endpoints MUST NOT exceed the limit set by their peer. An
	// endpoint that receives a HEADERS frame that causes their
	// advertised concurrent stream limit to be exceeded MUST treat
	// this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR
	// or REFUSED_STREAM.
	if .curClientStreams+1 > .advMaxStreams {
		if .unackedSettings == 0 {
			// They should know better.
			return .countError("over_max_streams", http2streamError(, http2ErrCodeProtocol))
		}
		// Assume it's a network race, where they just haven't
		// received our last SETTINGS update. But actually
		// this can't happen yet, because we don't yet provide
		// a way for users to adjust server parameters at
		// runtime.
		return .countError("over_max_streams_race", http2streamError(, http2ErrCodeRefusedStream))
	}

	 := http2stateOpen
	if .StreamEnded() {
		 = http2stateHalfClosedRemote
	}
	 := .newStream(, 0, )

	if .HasPriority() {
		if  := .checkPriority(.StreamID, .Priority);  != nil {
			return 
		}
		.writeSched.AdjustStream(.id, .Priority)
	}

	, ,  := .newWriterAndRequest(, )
	if  != nil {
		return 
	}
	.reqTrailer = .Trailer
	if .reqTrailer != nil {
		.trailer = make(Header)
	}
	.body = .Body.(*http2requestBody).pipe // may be nil
	.declBodyBytes = .ContentLength

	 := .handler.ServeHTTP
	if .Truncated {
		// Their header list was too long. Send a 431 error.
		 = http2handleHeaderListTooLong
	} else if  := http2checkValidHTTP2RequestHeaders(.Header);  != nil {
		 = http2new400Handler()
	}

	// The net/http package sets the read deadline from the
	// http.Server.ReadTimeout during the TLS handshake, but then
	// passes the connection off to us with the deadline already
	// set. Disarm it here after the request headers are read,
	// similar to how the http1 server works. Here it's
	// technically more like the http1 Server's ReadHeaderTimeout
	// (in Go 1.8), though. That's a more sane option anyway.
	if .hs.ReadTimeout > 0 {
		.conn.SetReadDeadline(time.Time{})
		.readDeadline = .srv.afterFunc(.hs.ReadTimeout, .onReadTimeout)
	}

	return .scheduleHandler(, , , )
}

func ( *http2serverConn) ( *Request) {
	.serveG.check()
	 := uint32(1)
	.maxClientStreamID = 
	 := .newStream(, 0, http2stateHalfClosedRemote)
	.reqTrailer = .Trailer
	if .reqTrailer != nil {
		.trailer = make(Header)
	}
	 := .newResponseWriter(, )

	// Disable any read deadline set by the net/http package
	// prior to the upgrade.
	if .hs.ReadTimeout > 0 {
		.conn.SetReadDeadline(time.Time{})
	}

	// This is the first request on the connection,
	// so start the handler directly rather than going
	// through scheduleHandler.
	.curHandlers++
	go .runHandler(, , .handler.ServeHTTP)
}

func ( *http2stream) ( *http2MetaHeadersFrame) error {
	 := .sc
	.serveG.check()
	if .gotTrailerHeader {
		return .countError("dup_trailers", http2ConnectionError(http2ErrCodeProtocol))
	}
	.gotTrailerHeader = true
	if !.StreamEnded() {
		return .countError("trailers_not_ended", http2streamError(.id, http2ErrCodeProtocol))
	}

	if len(.PseudoFields()) > 0 {
		return .countError("trailers_pseudo", http2streamError(.id, http2ErrCodeProtocol))
	}
	if .trailer != nil {
		for ,  := range .RegularFields() {
			 := .canonicalHeader(.Name)
			if !httpguts.ValidTrailerHeader() {
				// TODO: send more details to the peer somehow. But http2 has
				// no way to send debug data at a stream level. Discuss with
				// HTTP folk.
				return .countError("trailers_bogus", http2streamError(.id, http2ErrCodeProtocol))
			}
			.trailer[] = append(.trailer[], .Value)
		}
	}
	.endStream()
	return nil
}

func ( *http2serverConn) ( uint32,  http2PriorityParam) error {
	if  == .StreamDep {
		// Section 5.3.1: "A stream cannot depend on itself. An endpoint MUST treat
		// this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR."
		// Section 5.3.3 says that a stream can depend on one of its dependencies,
		// so it's only self-dependencies that are forbidden.
		return .countError("priority", http2streamError(, http2ErrCodeProtocol))
	}
	return nil
}

func ( *http2serverConn) ( *http2PriorityFrame) error {
	if  := .checkPriority(.StreamID, .http2PriorityParam);  != nil {
		return 
	}
	.writeSched.AdjustStream(.StreamID, .http2PriorityParam)
	return nil
}

func ( *http2serverConn) (,  uint32,  http2streamState) *http2stream {
	.serveG.check()
	if  == 0 {
		panic("internal error: cannot create stream with id 0")
	}

	,  := context.WithCancel(.baseCtx)
	 := &http2stream{
		sc:        ,
		id:        ,
		state:     ,
		ctx:       ,
		cancelCtx: ,
	}
	.cw.Init()
	.flow.conn = &.flow // link to conn-level counter
	.flow.add(.initialStreamSendWindowSize)
	.inflow.init(.initialStreamRecvWindowSize)
	if .hs.WriteTimeout > 0 {
		.writeDeadline = .srv.afterFunc(.hs.WriteTimeout, .onWriteTimeout)
	}

	.streams[] = 
	.writeSched.OpenStream(.id, http2OpenStreamOptions{PusherID: })
	if .isPushed() {
		.curPushedStreams++
	} else {
		.curClientStreams++
	}
	if .curOpenStreams() == 1 {
		.setConnState(StateActive)
	}

	return 
}

func ( *http2serverConn) ( *http2stream,  *http2MetaHeadersFrame) (*http2responseWriter, *Request, error) {
	.serveG.check()

	 := http2requestParam{
		method:    .PseudoValue("method"),
		scheme:    .PseudoValue("scheme"),
		authority: .PseudoValue("authority"),
		path:      .PseudoValue("path"),
		protocol:  .PseudoValue("protocol"),
	}

	// extended connect is disabled, so we should not see :protocol
	if http2disableExtendedConnectProtocol && .protocol != "" {
		return nil, nil, .countError("bad_connect", http2streamError(.StreamID, http2ErrCodeProtocol))
	}

	 := .method == "CONNECT"
	if  {
		if .protocol == "" && (.path != "" || .scheme != "" || .authority == "") {
			return nil, nil, .countError("bad_connect", http2streamError(.StreamID, http2ErrCodeProtocol))
		}
	} else if .method == "" || .path == "" || (.scheme != "https" && .scheme != "http") {
		// See 8.1.2.6 Malformed Requests and Responses:
		//
		// Malformed requests or responses that are detected
		// MUST be treated as a stream error (Section 5.4.2)
		// of type PROTOCOL_ERROR."
		//
		// 8.1.2.3 Request Pseudo-Header Fields
		// "All HTTP/2 requests MUST include exactly one valid
		// value for the :method, :scheme, and :path
		// pseudo-header fields"
		return nil, nil, .countError("bad_path_method", http2streamError(.StreamID, http2ErrCodeProtocol))
	}

	.header = make(Header)
	for ,  := range .RegularFields() {
		.header.Add(.canonicalHeader(.Name), .Value)
	}
	if .authority == "" {
		.authority = .header.Get("Host")
	}
	if .protocol != "" {
		.header.Set(":protocol", .protocol)
	}

	, ,  := .newWriterAndRequestNoBody(, )
	if  != nil {
		return nil, nil, 
	}
	 := !.StreamEnded()
	if  {
		if ,  := .header["Content-Length"];  {
			if ,  := strconv.ParseUint([0], 10, 63);  == nil {
				.ContentLength = int64()
			} else {
				.ContentLength = 0
			}
		} else {
			.ContentLength = -1
		}
		.Body.(*http2requestBody).pipe = &http2pipe{
			b: &http2dataBuffer{expected: .ContentLength},
		}
	}
	return , , nil
}

type http2requestParam struct {
	method                  string
	scheme, authority, path string
	protocol                string
	header                  Header
}

func ( *http2serverConn) ( *http2stream,  http2requestParam) (*http2responseWriter, *Request, error) {
	.serveG.check()

	var  *tls.ConnectionState // nil if not scheme https
	if .scheme == "https" {
		 = .tlsState
	}

	 := httpguts.HeaderValuesContainsToken(.header["Expect"], "100-continue")
	if  {
		.header.Del("Expect")
	}
	// Merge Cookie headers into one "; "-delimited value.
	if  := .header["Cookie"]; len() > 1 {
		.header.Set("Cookie", strings.Join(, "; "))
	}

	// Setup Trailers
	var  Header
	for ,  := range .header["Trailer"] {
		for ,  := range strings.Split(, ",") {
			 = CanonicalHeaderKey(textproto.TrimString())
			switch  {
			case "Transfer-Encoding", "Trailer", "Content-Length":
				// Bogus. (copy of http1 rules)
				// Ignore.
			default:
				if  == nil {
					 = make(Header)
				}
				[] = nil
			}
		}
	}
	delete(.header, "Trailer")

	var  *url.URL
	var  string
	if .method == "CONNECT" && .protocol == "" {
		 = &url.URL{Host: .authority}
		 = .authority // mimic HTTP/1 server behavior
	} else {
		var  error
		,  = url.ParseRequestURI(.path)
		if  != nil {
			return nil, nil, .countError("bad_path", http2streamError(.id, http2ErrCodeProtocol))
		}
		 = .path
	}

	 := &http2requestBody{
		conn:          ,
		stream:        ,
		needsContinue: ,
	}
	 := &Request{
		Method:     .method,
		URL:        ,
		RemoteAddr: .remoteAddrStr,
		Header:     .header,
		RequestURI: ,
		Proto:      "HTTP/2.0",
		ProtoMajor: 2,
		ProtoMinor: 0,
		TLS:        ,
		Host:       .authority,
		Body:       ,
		Trailer:    ,
	}
	 = .WithContext(.ctx)

	 := .newResponseWriter(, )
	return , , nil
}

func ( *http2serverConn) ( *http2stream,  *Request) *http2responseWriter {
	 := http2responseWriterStatePool.Get().(*http2responseWriterState)
	 := .bw
	* = http2responseWriterState{} // zero all the fields
	.conn = 
	.bw = 
	.bw.Reset(http2chunkWriter{})
	.stream = 
	.req = 
	return &http2responseWriter{rws: }
}

type http2unstartedHandler struct {
	streamID uint32
	rw       *http2responseWriter
	req      *Request
	handler  func(ResponseWriter, *Request)
}

// scheduleHandler starts a handler goroutine,
// or schedules one to start as soon as an existing handler finishes.
func ( *http2serverConn) ( uint32,  *http2responseWriter,  *Request,  func(ResponseWriter, *Request)) error {
	.serveG.check()
	 := .advMaxStreams
	if .curHandlers <  {
		.curHandlers++
		go .runHandler(, , )
		return nil
	}
	if len(.unstartedHandlers) > int(4*.advMaxStreams) {
		return .countError("too_many_early_resets", http2ConnectionError(http2ErrCodeEnhanceYourCalm))
	}
	.unstartedHandlers = append(.unstartedHandlers, http2unstartedHandler{
		streamID: ,
		rw:       ,
		req:      ,
		handler:  ,
	})
	return nil
}

func ( *http2serverConn) () {
	.serveG.check()
	.curHandlers--
	 := 0
	 := .advMaxStreams
	for ;  < len(.unstartedHandlers); ++ {
		 := .unstartedHandlers[]
		if .streams[.streamID] == nil {
			// This stream was reset before its goroutine had a chance to start.
			continue
		}
		if .curHandlers >=  {
			break
		}
		.curHandlers++
		go .runHandler(.rw, .req, .handler)
		.unstartedHandlers[] = http2unstartedHandler{} // don't retain references
	}
	.unstartedHandlers = .unstartedHandlers[:]
	if len(.unstartedHandlers) == 0 {
		.unstartedHandlers = nil
	}
}

// Run on its own goroutine.
func ( *http2serverConn) ( *http2responseWriter,  *Request,  func(ResponseWriter, *Request)) {
	.srv.markNewGoroutine()
	defer .sendServeMsg(http2handlerDoneMsg)
	 := true
	defer func() {
		.rws.stream.cancelCtx()
		if .MultipartForm != nil {
			.MultipartForm.RemoveAll()
		}
		if  {
			 := recover()
			.writeFrameFromHandler(http2FrameWriteRequest{
				write:  http2handlerPanicRST{.rws.stream.id},
				stream: .rws.stream,
			})
			// Same as net/http:
			if  != nil &&  != ErrAbortHandler {
				const  = 64 << 10
				 := make([]byte, )
				 = [:runtime.Stack(, false)]
				.logf("http2: panic serving %v: %v\n%s", .conn.RemoteAddr(), , )
			}
			return
		}
		.handlerDone()
	}()
	(, )
	 = false
}

func http2handleHeaderListTooLong( ResponseWriter,  *Request) {
	// 10.5.1 Limits on Header Block Size:
	// .. "A server that receives a larger header block than it is
	// willing to handle can send an HTTP 431 (Request Header Fields Too
	// Large) status code"
	const  = 431 // only in Go 1.6+
	.WriteHeader()
	io.WriteString(, "<h1>HTTP Error 431</h1><p>Request Header Field(s) Too Large</p>")
}

// called from handler goroutines.
// h may be nil.
func ( *http2serverConn) ( *http2stream,  *http2writeResHeaders) error {
	.serveG.checkNotOn() // NOT on
	var  chan error
	if .h != nil {
		// If there's a header map (which we don't own), so we have to block on
		// waiting for this frame to be written, so an http.Flush mid-handler
		// writes out the correct value of keys, before a handler later potentially
		// mutates it.
		 = http2errChanPool.Get().(chan error)
	}
	if  := .writeFrameFromHandler(http2FrameWriteRequest{
		write:  ,
		stream: ,
		done:   ,
	});  != nil {
		return 
	}
	if  != nil {
		select {
		case  := <-:
			http2errChanPool.Put()
			return 
		case <-.doneServing:
			return http2errClientDisconnected
		case <-.cw:
			return http2errStreamClosed
		}
	}
	return nil
}

// called from handler goroutines.
func ( *http2serverConn) ( *http2stream) {
	.writeFrameFromHandler(http2FrameWriteRequest{
		write:  http2write100ContinueHeadersFrame{.id},
		stream: ,
	})
}

// A bodyReadMsg tells the server loop that the http.Handler read n
// bytes of the DATA from the client on the given stream.
type http2bodyReadMsg struct {
	st *http2stream
	n  int
}

// called from handler goroutines.
// Notes that the handler for the given stream ID read n bytes of its body
// and schedules flow control tokens to be sent.
func ( *http2serverConn) ( *http2stream,  int,  error) {
	.serveG.checkNotOn() // NOT on
	if  > 0 {
		select {
		case .bodyReadCh <- http2bodyReadMsg{, }:
		case <-.doneServing:
		}
	}
}

func ( *http2serverConn) ( *http2stream,  int) {
	.serveG.check()
	.sendWindowUpdate(nil, ) // conn-level
	if .state != http2stateHalfClosedRemote && .state != http2stateClosed {
		// Don't send this WINDOW_UPDATE if the stream is closed
		// remotely.
		.sendWindowUpdate(, )
	}
}

// st may be nil for conn-level
func ( *http2serverConn) ( *http2stream,  int32) {
	.sendWindowUpdate(, int())
}

// st may be nil for conn-level
func ( *http2serverConn) ( *http2stream,  int) {
	.serveG.check()
	var  uint32
	var  int32
	if  == nil {
		 = .inflow.add()
	} else {
		 = .id
		 = .inflow.add()
	}
	if  == 0 {
		return
	}
	.writeFrame(http2FrameWriteRequest{
		write:  http2writeWindowUpdate{streamID: , n: uint32()},
		stream: ,
	})
}

// requestBody is the Handler's Request.Body type.
// Read and Close may be called concurrently.
type http2requestBody struct {
	_             http2incomparable
	stream        *http2stream
	conn          *http2serverConn
	closeOnce     sync.Once  // for use by Close only
	sawEOF        bool       // for use by Read only
	pipe          *http2pipe // non-nil if we have an HTTP entity message body
	needsContinue bool       // need to send a 100-continue
}

func ( *http2requestBody) () error {
	.closeOnce.Do(func() {
		if .pipe != nil {
			.pipe.BreakWithError(http2errClosedBody)
		}
	})
	return nil
}

func ( *http2requestBody) ( []byte) ( int,  error) {
	if .needsContinue {
		.needsContinue = false
		.conn.write100ContinueHeaders(.stream)
	}
	if .pipe == nil || .sawEOF {
		return 0, io.EOF
	}
	,  = .pipe.Read()
	if  == io.EOF {
		.sawEOF = true
	}
	if .conn == nil && http2inTests {
		return
	}
	.conn.noteBodyReadFromHandler(.stream, , )
	return
}

// responseWriter is the http.ResponseWriter implementation. It's
// intentionally small (1 pointer wide) to minimize garbage. The
// responseWriterState pointer inside is zeroed at the end of a
// request (in handlerDone) and calls on the responseWriter thereafter
// simply crash (caller's mistake), but the much larger responseWriterState
// and buffers are reused between multiple requests.
type http2responseWriter struct {
	rws *http2responseWriterState
}

// Optional http.ResponseWriter interfaces implemented.
var (
	_ CloseNotifier     = (*http2responseWriter)(nil)
	_ Flusher           = (*http2responseWriter)(nil)
	_ http2stringWriter = (*http2responseWriter)(nil)
)

type http2responseWriterState struct {
	// immutable within a request:
	stream *http2stream
	req    *Request
	conn   *http2serverConn

	// TODO: adjust buffer writing sizes based on server config, frame size updates from peer, etc
	bw *bufio.Writer // writing to a chunkWriter{this *responseWriterState}

	// mutated by http.Handler goroutine:
	handlerHeader Header   // nil until called
	snapHeader    Header   // snapshot of handlerHeader at WriteHeader time
	trailers      []string // set in writeChunk
	status        int      // status code passed to WriteHeader
	wroteHeader   bool     // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
	sentHeader    bool     // have we sent the header frame?
	handlerDone   bool     // handler has finished

	sentContentLen int64 // non-zero if handler set a Content-Length header
	wroteBytes     int64

	closeNotifierMu sync.Mutex // guards closeNotifierCh
	closeNotifierCh chan bool  // nil until first used
}

type http2chunkWriter struct{ rws *http2responseWriterState }

func ( http2chunkWriter) ( []byte) ( int,  error) {
	,  = .rws.writeChunk()
	if  == http2errStreamClosed {
		// If writing failed because the stream has been closed,
		// return the reason it was closed.
		 = .rws.stream.closeErr
	}
	return , 
}

func ( *http2responseWriterState) () bool { return len(.trailers) > 0 }

func ( *http2responseWriterState) () bool {
	for ,  := range .trailers {
		if ,  := .handlerHeader[];  {
			return true
		}
	}
	return false
}

// declareTrailer is called for each Trailer header when the
// response header is written. It notes that a header will need to be
// written in the trailers at the end of the response.
func ( *http2responseWriterState) ( string) {
	 = CanonicalHeaderKey()
	if !httpguts.ValidTrailerHeader() {
		// Forbidden by RFC 7230, section 4.1.2.
		.conn.logf("ignoring invalid trailer %q", )
		return
	}
	if !http2strSliceContains(.trailers, ) {
		.trailers = append(.trailers, )
	}
}

// writeChunk writes chunks from the bufio.Writer. But because
// bufio.Writer may bypass its chunking, sometimes p may be
// arbitrarily large.
//
// writeChunk is also responsible (on the first chunk) for sending the
// HEADER response.
func ( *http2responseWriterState) ( []byte) ( int,  error) {
	if !.wroteHeader {
		.writeHeader(200)
	}

	if .handlerDone {
		.promoteUndeclaredTrailers()
	}

	 := .req.Method == "HEAD"
	if !.sentHeader {
		.sentHeader = true
		var ,  string
		if  = .snapHeader.Get("Content-Length");  != "" {
			.snapHeader.Del("Content-Length")
			if ,  := strconv.ParseUint(, 10, 63);  == nil {
				.sentContentLen = int64()
			} else {
				 = ""
			}
		}
		,  := .snapHeader["Content-Length"]
		if ! &&  == "" && .handlerDone && http2bodyAllowedForStatus(.status) && (len() > 0 || !) {
			 = strconv.Itoa(len())
		}
		,  := .snapHeader["Content-Type"]
		// If the Content-Encoding is non-blank, we shouldn't
		// sniff the body. See Issue golang.org/issue/31753.
		 := .snapHeader.Get("Content-Encoding")
		 := len() > 0
		if ! && ! && http2bodyAllowedForStatus(.status) && len() > 0 {
			 = DetectContentType()
		}
		var  string
		if ,  := .snapHeader["Date"]; ! {
			// TODO(bradfitz): be faster here, like net/http? measure.
			 = .conn.srv.now().UTC().Format(TimeFormat)
		}

		for ,  := range .snapHeader["Trailer"] {
			http2foreachHeaderElement(, .declareTrailer)
		}

		// "Connection" headers aren't allowed in HTTP/2 (RFC 7540, 8.1.2.2),
		// but respect "Connection" == "close" to mean sending a GOAWAY and tearing
		// down the TCP connection when idle, like we do for HTTP/1.
		// TODO: remove more Connection-specific header fields here, in addition
		// to "Connection".
		if ,  := .snapHeader["Connection"];  {
			 := .snapHeader.Get("Connection")
			delete(.snapHeader, "Connection")
			if  == "close" {
				.conn.startGracefulShutdown()
			}
		}

		 := (.handlerDone && !.hasTrailers() && len() == 0) || 
		 = .conn.writeHeaders(.stream, &http2writeResHeaders{
			streamID:      .stream.id,
			httpResCode:   .status,
			h:             .snapHeader,
			endStream:     ,
			contentType:   ,
			contentLength: ,
			date:          ,
		})
		if  != nil {
			return 0, 
		}
		if  {
			return 0, nil
		}
	}
	if  {
		return len(), nil
	}
	if len() == 0 && !.handlerDone {
		return 0, nil
	}

	// only send trailers if they have actually been defined by the
	// server handler.
	 := .hasNonemptyTrailers()
	 := .handlerDone && !
	if len() > 0 ||  {
		// only send a 0 byte DATA frame if we're ending the stream.
		if  := .conn.writeDataFromHandler(.stream, , );  != nil {
			return 0, 
		}
	}

	if .handlerDone &&  {
		 = .conn.writeHeaders(.stream, &http2writeResHeaders{
			streamID:  .stream.id,
			h:         .handlerHeader,
			trailers:  .trailers,
			endStream: true,
		})
		return len(), 
	}
	return len(), nil
}

// TrailerPrefix is a magic prefix for ResponseWriter.Header map keys
// that, if present, signals that the map entry is actually for
// the response trailers, and not the response headers. The prefix
// is stripped after the ServeHTTP call finishes and the values are
// sent in the trailers.
//
// This mechanism is intended only for trailers that are not known
// prior to the headers being written. If the set of trailers is fixed
// or known before the header is written, the normal Go trailers mechanism
// is preferred:
//
//	https://golang.org/pkg/net/http/#ResponseWriter
//	https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
const http2TrailerPrefix = "Trailer:"

// promoteUndeclaredTrailers permits http.Handlers to set trailers
// after the header has already been flushed. Because the Go
// ResponseWriter interface has no way to set Trailers (only the
// Header), and because we didn't want to expand the ResponseWriter
// interface, and because nobody used trailers, and because RFC 7230
// says you SHOULD (but not must) predeclare any trailers in the
// header, the official ResponseWriter rules said trailers in Go must
// be predeclared, and then we reuse the same ResponseWriter.Header()
// map to mean both Headers and Trailers. When it's time to write the
// Trailers, we pick out the fields of Headers that were declared as
// trailers. That worked for a while, until we found the first major
// user of Trailers in the wild: gRPC (using them only over http2),
// and gRPC libraries permit setting trailers mid-stream without
// predeclaring them. So: change of plans. We still permit the old
// way, but we also permit this hack: if a Header() key begins with
// "Trailer:", the suffix of that key is a Trailer. Because ':' is an
// invalid token byte anyway, there is no ambiguity. (And it's already
// filtered out) It's mildly hacky, but not terrible.
//
// This method runs after the Handler is done and promotes any Header
// fields to be trailers.
func ( *http2responseWriterState) () {
	for ,  := range .handlerHeader {
		if !strings.HasPrefix(, http2TrailerPrefix) {
			continue
		}
		 := strings.TrimPrefix(, http2TrailerPrefix)
		.declareTrailer()
		.handlerHeader[CanonicalHeaderKey()] = 
	}

	if len(.trailers) > 1 {
		 := http2sorterPool.Get().(*http2sorter)
		.SortStrings(.trailers)
		http2sorterPool.Put()
	}
}

func ( *http2responseWriter) ( time.Time) error {
	 := .rws.stream
	if !.IsZero() && .Before(.rws.conn.srv.now()) {
		// If we're setting a deadline in the past, reset the stream immediately
		// so writes after SetWriteDeadline returns will fail.
		.onReadTimeout()
		return nil
	}
	.rws.conn.sendServeMsg(func( *http2serverConn) {
		if .readDeadline != nil {
			if !.readDeadline.Stop() {
				// Deadline already exceeded, or stream has been closed.
				return
			}
		}
		if .IsZero() {
			.readDeadline = nil
		} else if .readDeadline == nil {
			.readDeadline = .srv.afterFunc(.Sub(.srv.now()), .onReadTimeout)
		} else {
			.readDeadline.Reset(.Sub(.srv.now()))
		}
	})
	return nil
}

func ( *http2responseWriter) ( time.Time) error {
	 := .rws.stream
	if !.IsZero() && .Before(.rws.conn.srv.now()) {
		// If we're setting a deadline in the past, reset the stream immediately
		// so writes after SetWriteDeadline returns will fail.
		.onWriteTimeout()
		return nil
	}
	.rws.conn.sendServeMsg(func( *http2serverConn) {
		if .writeDeadline != nil {
			if !.writeDeadline.Stop() {
				// Deadline already exceeded, or stream has been closed.
				return
			}
		}
		if .IsZero() {
			.writeDeadline = nil
		} else if .writeDeadline == nil {
			.writeDeadline = .srv.afterFunc(.Sub(.srv.now()), .onWriteTimeout)
		} else {
			.writeDeadline.Reset(.Sub(.srv.now()))
		}
	})
	return nil
}

func ( *http2responseWriter) () error {
	// We always support full duplex responses, so this is a no-op.
	return nil
}

func ( *http2responseWriter) () {
	.FlushError()
}

func ( *http2responseWriter) () error {
	 := .rws
	if  == nil {
		panic("Header called after Handler finished")
	}
	var  error
	if .bw.Buffered() > 0 {
		 = .bw.Flush()
	} else {
		// The bufio.Writer won't call chunkWriter.Write
		// (writeChunk with zero bytes), so we have to do it
		// ourselves to force the HTTP response header and/or
		// final DATA frame (with END_STREAM) to be sent.
		_,  = http2chunkWriter{}.Write(nil)
		if  == nil {
			select {
			case <-.stream.cw:
				 = .stream.closeErr
			default:
			}
		}
	}
	return 
}

func ( *http2responseWriter) () <-chan bool {
	 := .rws
	if  == nil {
		panic("CloseNotify called after Handler finished")
	}
	.closeNotifierMu.Lock()
	 := .closeNotifierCh
	if  == nil {
		 = make(chan bool, 1)
		.closeNotifierCh = 
		 := .stream.cw
		go func() {
			.Wait() // wait for close
			 <- true
		}()
	}
	.closeNotifierMu.Unlock()
	return 
}

func ( *http2responseWriter) () Header {
	 := .rws
	if  == nil {
		panic("Header called after Handler finished")
	}
	if .handlerHeader == nil {
		.handlerHeader = make(Header)
	}
	return .handlerHeader
}

// checkWriteHeaderCode is a copy of net/http's checkWriteHeaderCode.
func http2checkWriteHeaderCode( int) {
	// Issue 22880: require valid WriteHeader status codes.
	// For now we only enforce that it's three digits.
	// In the future we might block things over 599 (600 and above aren't defined
	// at http://httpwg.org/specs/rfc7231.html#status.codes).
	// But for now any three digits.
	//
	// We used to send "HTTP/1.1 000 0" on the wire in responses but there's
	// no equivalent bogus thing we can realistically send in HTTP/2,
	// so we'll consistently panic instead and help people find their bugs
	// early. (We can't return an error from WriteHeader even if we wanted to.)
	if  < 100 ||  > 999 {
		panic(fmt.Sprintf("invalid WriteHeader code %v", ))
	}
}

func ( *http2responseWriter) ( int) {
	 := .rws
	if  == nil {
		panic("WriteHeader called after Handler finished")
	}
	.writeHeader()
}

func ( *http2responseWriterState) ( int) {
	if .wroteHeader {
		return
	}

	http2checkWriteHeaderCode()

	// Handle informational headers
	if  >= 100 &&  <= 199 {
		// Per RFC 8297 we must not clear the current header map
		 := .handlerHeader

		,  := ["Content-Length"]
		,  := ["Transfer-Encoding"]
		if  ||  {
			 = .Clone()
			.Del("Content-Length")
			.Del("Transfer-Encoding")
		}

		.conn.writeHeaders(.stream, &http2writeResHeaders{
			streamID:    .stream.id,
			httpResCode: ,
			h:           ,
			endStream:   .handlerDone && !.hasTrailers(),
		})

		return
	}

	.wroteHeader = true
	.status = 
	if len(.handlerHeader) > 0 {
		.snapHeader = http2cloneHeader(.handlerHeader)
	}
}

func http2cloneHeader( Header) Header {
	 := make(Header, len())
	for ,  := range  {
		 := make([]string, len())
		copy(, )
		[] = 
	}
	return 
}

// The Life Of A Write is like this:
//
// * Handler calls w.Write or w.WriteString ->
// * -> rws.bw (*bufio.Writer) ->
// * (Handler might call Flush)
// * -> chunkWriter{rws}
// * -> responseWriterState.writeChunk(p []byte)
// * -> responseWriterState.writeChunk (most of the magic; see comment there)
func ( *http2responseWriter) ( []byte) ( int,  error) {
	return .write(len(), , "")
}

func ( *http2responseWriter) ( string) ( int,  error) {
	return .write(len(), nil, )
}

// either dataB or dataS is non-zero.
func ( *http2responseWriter) ( int,  []byte,  string) ( int,  error) {
	 := .rws
	if  == nil {
		panic("Write called after Handler finished")
	}
	if !.wroteHeader {
		.WriteHeader(200)
	}
	if !http2bodyAllowedForStatus(.status) {
		return 0, ErrBodyNotAllowed
	}
	.wroteBytes += int64(len()) + int64(len()) // only one can be set
	if .sentContentLen != 0 && .wroteBytes > .sentContentLen {
		// TODO: send a RST_STREAM
		return 0, errors.New("http2: handler wrote more than declared Content-Length")
	}

	if  != nil {
		return .bw.Write()
	} else {
		return .bw.WriteString()
	}
}

func ( *http2responseWriter) () {
	 := .rws
	.handlerDone = true
	.Flush()
	.rws = nil
	http2responseWriterStatePool.Put()
}

// Push errors.
var (
	http2ErrRecursivePush    = errors.New("http2: recursive push not allowed")
	http2ErrPushLimitReached = errors.New("http2: push would exceed peer's SETTINGS_MAX_CONCURRENT_STREAMS")
)

var _ Pusher = (*http2responseWriter)(nil)

func ( *http2responseWriter) ( string,  *PushOptions) error {
	 := .rws.stream
	 := .sc
	.serveG.checkNotOn()

	// No recursive pushes: "PUSH_PROMISE frames MUST only be sent on a peer-initiated stream."
	// http://tools.ietf.org/html/rfc7540#section-6.6
	if .isPushed() {
		return http2ErrRecursivePush
	}

	if  == nil {
		 = new(PushOptions)
	}

	// Default options.
	if .Method == "" {
		.Method = "GET"
	}
	if .Header == nil {
		.Header = Header{}
	}
	 := "http"
	if .rws.req.TLS != nil {
		 = "https"
	}

	// Validate the request.
	,  := url.Parse()
	if  != nil {
		return 
	}
	if .Scheme == "" {
		if !strings.HasPrefix(, "/") {
			return fmt.Errorf("target must be an absolute URL or an absolute path: %q", )
		}
		.Scheme = 
		.Host = .rws.req.Host
	} else {
		if .Scheme !=  {
			return fmt.Errorf("cannot push URL with scheme %q from request with scheme %q", .Scheme, )
		}
		if .Host == "" {
			return errors.New("URL must have a host")
		}
	}
	for  := range .Header {
		if strings.HasPrefix(, ":") {
			return fmt.Errorf("promised request headers cannot include pseudo header %q", )
		}
		// These headers are meaningful only if the request has a body,
		// but PUSH_PROMISE requests cannot have a body.
		// http://tools.ietf.org/html/rfc7540#section-8.2
		// Also disallow Host, since the promised URL must be absolute.
		if http2asciiEqualFold(, "content-length") ||
			http2asciiEqualFold(, "content-encoding") ||
			http2asciiEqualFold(, "trailer") ||
			http2asciiEqualFold(, "te") ||
			http2asciiEqualFold(, "expect") ||
			http2asciiEqualFold(, "host") {
			return fmt.Errorf("promised request headers cannot include %q", )
		}
	}
	if  := http2checkValidHTTP2RequestHeaders(.Header);  != nil {
		return 
	}

	// The RFC effectively limits promised requests to GET and HEAD:
	// "Promised requests MUST be cacheable [GET, HEAD, or POST], and MUST be safe [GET or HEAD]"
	// http://tools.ietf.org/html/rfc7540#section-8.2
	if .Method != "GET" && .Method != "HEAD" {
		return fmt.Errorf("method %q must be GET or HEAD", .Method)
	}

	 := &http2startPushRequest{
		parent: ,
		method: .Method,
		url:    ,
		header: http2cloneHeader(.Header),
		done:   http2errChanPool.Get().(chan error),
	}

	select {
	case <-.doneServing:
		return http2errClientDisconnected
	case <-.cw:
		return http2errStreamClosed
	case .serveMsgCh <- :
	}

	select {
	case <-.doneServing:
		return http2errClientDisconnected
	case <-.cw:
		return http2errStreamClosed
	case  := <-.done:
		http2errChanPool.Put(.done)
		return 
	}
}

type http2startPushRequest struct {
	parent *http2stream
	method string
	url    *url.URL
	header Header
	done   chan error
}

func ( *http2serverConn) ( *http2startPushRequest) {
	.serveG.check()

	// http://tools.ietf.org/html/rfc7540#section-6.6.
	// PUSH_PROMISE frames MUST only be sent on a peer-initiated stream that
	// is in either the "open" or "half-closed (remote)" state.
	if .parent.state != http2stateOpen && .parent.state != http2stateHalfClosedRemote {
		// responseWriter.Push checks that the stream is peer-initiated.
		.done <- http2errStreamClosed
		return
	}

	// http://tools.ietf.org/html/rfc7540#section-6.6.
	if !.pushEnabled {
		.done <- ErrNotSupported
		return
	}

	// PUSH_PROMISE frames must be sent in increasing order by stream ID, so
	// we allocate an ID for the promised stream lazily, when the PUSH_PROMISE
	// is written. Once the ID is allocated, we start the request handler.
	 := func() (uint32, error) {
		.serveG.check()

		// Check this again, just in case. Technically, we might have received
		// an updated SETTINGS by the time we got around to writing this frame.
		if !.pushEnabled {
			return 0, ErrNotSupported
		}
		// http://tools.ietf.org/html/rfc7540#section-6.5.2.
		if .curPushedStreams+1 > .clientMaxStreams {
			return 0, http2ErrPushLimitReached
		}

		// http://tools.ietf.org/html/rfc7540#section-5.1.1.
		// Streams initiated by the server MUST use even-numbered identifiers.
		// A server that is unable to establish a new stream identifier can send a GOAWAY
		// frame so that the client is forced to open a new connection for new streams.
		if .maxPushPromiseID+2 >= 1<<31 {
			.startGracefulShutdownInternal()
			return 0, http2ErrPushLimitReached
		}
		.maxPushPromiseID += 2
		 := .maxPushPromiseID

		// http://tools.ietf.org/html/rfc7540#section-8.2.
		// Strictly speaking, the new stream should start in "reserved (local)", then
		// transition to "half closed (remote)" after sending the initial HEADERS, but
		// we start in "half closed (remote)" for simplicity.
		// See further comments at the definition of stateHalfClosedRemote.
		 := .newStream(, .parent.id, http2stateHalfClosedRemote)
		, ,  := .newWriterAndRequestNoBody(, http2requestParam{
			method:    .method,
			scheme:    .url.Scheme,
			authority: .url.Host,
			path:      .url.RequestURI(),
			header:    http2cloneHeader(.header), // clone since handler runs concurrently with writing the PUSH_PROMISE
		})
		if  != nil {
			// Should not happen, since we've already validated msg.url.
			panic(fmt.Sprintf("newWriterAndRequestNoBody(%+v): %v", .url, ))
		}

		.curHandlers++
		go .runHandler(, , .handler.ServeHTTP)
		return , nil
	}

	.writeFrame(http2FrameWriteRequest{
		write: &http2writePushPromise{
			streamID:           .parent.id,
			method:             .method,
			url:                .url,
			h:                  .header,
			allocatePromisedID: ,
		},
		stream: .parent,
		done:   .done,
	})
}

// foreachHeaderElement splits v according to the "#rule" construction
// in RFC 7230 section 7 and calls fn for each non-empty element.
func http2foreachHeaderElement( string,  func(string)) {
	 = textproto.TrimString()
	if  == "" {
		return
	}
	if !strings.Contains(, ",") {
		()
		return
	}
	for ,  := range strings.Split(, ",") {
		if  = textproto.TrimString();  != "" {
			()
		}
	}
}

// From http://httpwg.org/specs/rfc7540.html#rfc.section.8.1.2.2
var http2connHeaders = []string{
	"Connection",
	"Keep-Alive",
	"Proxy-Connection",
	"Transfer-Encoding",
	"Upgrade",
}

// checkValidHTTP2RequestHeaders checks whether h is a valid HTTP/2 request,
// per RFC 7540 Section 8.1.2.2.
// The returned error is reported to users.
func http2checkValidHTTP2RequestHeaders( Header) error {
	for ,  := range http2connHeaders {
		if ,  := [];  {
			return fmt.Errorf("request header %q is not valid in HTTP/2", )
		}
	}
	 := ["Te"]
	if len() > 0 && (len() > 1 || ([0] != "trailers" && [0] != "")) {
		return errors.New(`request header "TE" may only be "trailers" in HTTP/2`)
	}
	return nil
}

func http2new400Handler( error) HandlerFunc {
	return func( ResponseWriter,  *Request) {
		Error(, .Error(), StatusBadRequest)
	}
}

// h1ServerKeepAlivesDisabled reports whether hs has its keep-alives
// disabled. See comments on h1ServerShutdownChan above for why
// the code is written this way.
func http2h1ServerKeepAlivesDisabled( *Server) bool {
	var  interface{} = 
	type  interface {
		() bool
	}
	if ,  := .();  {
		return !.()
	}
	return false
}

func ( *http2serverConn) ( string,  error) error {
	if  == nil || .srv == nil {
		return 
	}
	 := .countErrorFunc
	if  == nil {
		return 
	}
	var  string
	var  http2ErrCode
	switch e := .(type) {
	case http2ConnectionError:
		 = "conn"
		 = http2ErrCode()
	case http2StreamError:
		 = "stream"
		 = http2ErrCode(.Code)
	default:
		return 
	}
	 := http2errCodeName[]
	if  == "" {
		 = strconv.Itoa(int())
	}
	(fmt.Sprintf("%s_%s_%s", , , ))
	return 
}

// A timer is a time.Timer, as an interface which can be replaced in tests.
type http2timer = interface {
	C() <-chan time.Time
	Reset(d time.Duration) bool
	Stop() bool
}

// timeTimer adapts a time.Timer to the timer interface.
type http2timeTimer struct {
	*time.Timer
}

func ( http2timeTimer) () <-chan time.Time { return .Timer.C }

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

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

	http2defaultUserAgent = "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.
	http2initialMaxConcurrentStreams = 100

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

// Transport is an HTTP/2 Transport.
//
// A Transport internally caches connections to servers. It is safe
// for concurrent use by multiple goroutines.
type http2Transport 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 http2ClientConnPool

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

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

	*http2transportTestHooks
}

// 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 http2transportTestHooks struct {
	newclientconn func(*http2ClientConn)
	group         http2synctestGroupInterface
}

func ( *http2Transport) () {
	if  != nil && .http2transportTestHooks != nil {
		.http2transportTestHooks.group.Join()
	}
}

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

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

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

// afterFunc creates a new time.AfterFunc timer, or a synthetic timer in tests.
func ( *http2Transport) ( time.Duration,  func()) http2timer {
	if .http2transportTestHooks != nil {
		return .http2transportTestHooks.group.AfterFunc(, )
	}
	return http2timeTimer{time.AfterFunc(, )}
}

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

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

func ( *http2Transport) () 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 http2ConfigureTransport( *Transport) error {
	,  := http2ConfigureTransports()
	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 http2ConfigureTransports( *Transport) (*http2Transport, error) {
	return http2configureTransports()
}

func http2configureTransports( *Transport) (*http2Transport, error) {
	 := new(http2clientConnPool)
	 := &http2Transport{
		ConnPool: http2noDialClientConnPool{},
		t1:       ,
	}
	.t = 
	if  := http2registerHTTPSProtocol(, http2noDialH2RoundTripper{});  != nil {
		return nil, 
	}
	if .TLSClientConfig == nil {
		.TLSClientConfig = new(tls.Config)
	}
	if !http2strSliceContains(.TLSClientConfig.NextProtos, "h2") {
		.TLSClientConfig.NextProtos = append([]string{"h2"}, .TLSClientConfig.NextProtos...)
	}
	if !http2strSliceContains(.TLSClientConfig.NextProtos, "http/1.1") {
		.TLSClientConfig.NextProtos = append(.TLSClientConfig.NextProtos, "http/1.1")
	}
	 := func(,  string,  net.Conn) RoundTripper {
		 := http2authorityAddr(, )
		if ,  := .addConnIfNeeded(, , );  != nil {
			go .Close()
			return http2erringRoundTripper{}
		} 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 (*http2unencryptedTransport)()
		}
		return 
	}
	if .TLSNextProto == nil {
		.TLSNextProto = make(map[string]func(string, *tls.Conn) RoundTripper)
	}
	.TLSNextProto[http2NextProtoTLS] = func( string,  *tls.Conn) RoundTripper {
		return ("https", , )
	}
	// The "unencrypted_http2" TLSNextProto key is used to pass off non-TLS HTTP/2 conns.
	.TLSNextProto[http2nextProtoUnencryptedHTTP2] = func( string,  *tls.Conn) RoundTripper {
		,  := http2unencryptedNetConnFromTLSConn()
		if  != nil {
			go .Close()
			return http2erringRoundTripper{}
		}
		return ("http", , )
	}
	return , nil
}

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

func ( *http2unencryptedTransport) ( *Request) (*Response, error) {
	return (*http2Transport)().RoundTripOpt(, http2RoundTripOpt{allowHTTP: true})
}

func ( *http2Transport) () http2ClientConnPool {
	.connPoolOnce.Do(.initConnPool)
	return .connPoolOrDef
}

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

// ClientConn is the state of a single HTTP/2 client connection to an
// HTTP/2 server.
type http2ClientConn struct {
	t             *http2Transport
	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   http2timer

	mu               sync.Mutex   // guards following
	cond             *sync.Cond   // hold mu; broadcast on flow/closed changes
	flow             http2outflow // our conn-level flow control quota (cs.outflow is per stream)
	inflow           http2inflow  // 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
	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           *http2GoAwayFrame             // if non-nil, the GoAwayFrame we received
	goAwayDebug      string                        // goAway frame's debug data, retained as a string
	streams          map[uint32]*http2clientStream // 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   *http2Framer
	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 http2clientStream struct {
	cc *http2ClientConn

	// 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       http2pipe // 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            *Response     // set if respHeaderRecv is closed

	flow        http2outflow // guarded by cc.mu
	inflow      http2inflow  // 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    Header  // accumulated trailers
	resTrailer *Header // client's Response.Trailer
}

var http2got1xxFuncForTests 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 ( *http2clientStream) () func(int, textproto.MIMEHeader) error {
	if  := http2got1xxFuncForTests;  != nil {
		return 
	}
	return http2traceGot1xxResponseFunc(.trace)
}

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

func ( *http2clientStream) ( 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 ( *http2clientStream) () {
	 := .cc
	.mu.Lock()
	defer .mu.Unlock()
	if .reqBody != nil && .reqBodyClosed == nil {
		.closeReqBodyLocked()
		.cond.Broadcast()
	}
}

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

type http2stickyErrWriter struct {
	group   http2synctestGroupInterface
	conn    net.Conn
	timeout time.Duration
	err     *error
}

func ( http2stickyErrWriter) ( []byte) ( int,  error) {
	if *.err != nil {
		return 0, *.err
	}
	,  = http2writeWithByteTimeout(.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 http2noCachedConnError struct{}

func (http2noCachedConnError) () {}

func (http2noCachedConnError) () 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 http2isNoCachedConnError( error) bool {
	,  := .(interface{ () })
	return 
}

var http2ErrNoCachedConn error = http2noCachedConnError{}

// RoundTripOpt are options for the Transport.RoundTripOpt method.
type http2RoundTripOpt 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 ( *http2Transport) ( *Request) (*Response, error) {
	return .RoundTripOpt(, http2RoundTripOpt{})
}

// 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 http2authorityAddr( 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 ( *http2Transport) ( *Request,  http2RoundTripOpt) (*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")
	}

	 := http2authorityAddr(.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)
		http2traceGotConn(, , )
		,  := .RoundTrip()
		if  != nil &&  <= 6 {
			 := 
			if ,  = http2shouldRetryRequest(, );  == 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  == http2errClientConnNotEstablished {
			// 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 ( *http2Transport) () {
	if ,  := .connPool().(http2clientConnPoolIdleCloser);  {
		.closeIdleConnections()
	}
}

var (
	http2errClientConnClosed         = errors.New("http2: client conn is closed")
	http2errClientConnUnusable       = errors.New("http2: client conn not usable")
	http2errClientConnNotEstablished = errors.New("http2: client conn could not be established")
	http2errClientConnGotGoAway      = 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 http2shouldRetryRequest( *Request,  error) (*Request, error) {
	if !http2canRetryError() {
		return nil, 
	}
	// If the Body is nil (or http.NoBody), it's safe to reuse
	// this request and its Body.
	if .Body == nil || .Body == 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  == http2errClientConnUnusable {
		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 http2canRetryError( error) bool {
	if  == http2errClientConnUnusable ||  == http2errClientConnGotGoAway {
		return true
	}
	if ,  := .(http2StreamError);  {
		if .Code == http2ErrCodeProtocol && .Cause == http2errFromPeer {
			// See golang/go#47635, golang/go#42777
			return true
		}
		return .Code == http2ErrCodeRefusedStream
	}
	return false
}

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

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

func ( *http2Transport) ( 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;  != http2NextProtoTLS {
		return nil, fmt.Errorf("http2: unexpected ALPN protocol %q; want %q", , http2NextProtoTLS)
	}
	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 ( *http2Transport) () bool {
	return .t1 != nil && .t1.DisableKeepAlives
}

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

func ( *http2Transport) ( net.Conn) (*http2ClientConn, error) {
	return .newClientConn(, .disableKeepAlives())
}

func ( *http2Transport) ( net.Conn,  bool) (*http2ClientConn, error) {
	 := http2configFromTransport()
	 := &http2ClientConn{
		t:                           ,
		tconn:                       ,
		readerDone:                  make(chan struct{}),
		nextStreamID:                1,
		maxFrameSize:                16 << 10, // spec default
		initialWindowSize:           65535,    // spec default
		initialStreamRecvWindowSize: .MaxUploadBufferPerStream,
		maxConcurrentStreams:        http2initialMaxConcurrentStreams, // "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]*http2clientStream),
		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  http2synctestGroupInterface
	if .http2transportTestHooks != nil {
		.markNewGoroutine()
		.http2transportTestHooks.newclientconn()
		 = .tconn
		 = .group
	}
	if http2VerboseLogs {
		.vlogf("http2: Transport creating client conn %p to %v", , .RemoteAddr())
	}

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

	// TODO: adjust this writer size to account for frame size +
	// MTU + crypto/tls record padding.
	.bw = bufio.NewWriter(http2stickyErrWriter{
		group:   ,
		conn:    ,
		timeout: .WriteByteTimeout,
		err:     &.werr,
	})
	.br = bufio.NewReader()
	.fr = http2NewFramer(.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 = http2initialHeaderTableSize

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

	 := []http2Setting{
		{ID: http2SettingEnablePush, Val: 0},
		{ID: http2SettingInitialWindowSize, Val: uint32(.initialStreamRecvWindowSize)},
	}
	 = append(, http2Setting{ID: http2SettingMaxFrameSize, Val: .MaxReadFrameSize})
	if  := .maxHeaderListSize();  != 0 {
		 = append(, http2Setting{ID: http2SettingMaxHeaderListSize, Val: })
	}
	if  != http2initialHeaderTableSize {
		 = append(, http2Setting{ID: http2SettingHeaderTableSize, Val: })
	}

	.bw.Write(http2clientPreface)
	.fr.WriteSettings(...)
	.fr.WriteWindowUpdate(0, uint32(.MaxUploadBufferPerConnection))
	.inflow.init(.MaxUploadBufferPerConnection + http2initialWindowSize)
	.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 ( *http2ClientConn) () {
	 := .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 ( *http2ClientConn) () {
	.mu.Lock()
	defer .mu.Unlock()
	.doNotReuse = true
}

func ( *http2ClientConn) ( *http2GoAwayFrame) {
	.mu.Lock()
	defer .mu.Unlock()

	 := .goAway
	.goAway = 

	// Merge the previous and current GoAway error frames.
	if .goAwayDebug == "" {
		.goAwayDebug = string(.DebugData())
	}
	if  != nil && .ErrCode != http2ErrCodeNo {
		.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 != http2ErrCodeNo {
			// 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(http2errClientConnGotGoAway)
		}
	}
}

// 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 ( *http2ClientConn) () 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 ( *http2ClientConn) () bool {
	.mu.Lock()
	defer .mu.Unlock()
	if  := .idleStateLocked(); !.canTakeNewRequest {
		return false
	}
	.streamsReserved++
	return true
}

// ClientConnState describes the state of a ClientConn.
type http2ClientConnState 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 ( *http2ClientConn) () http2ClientConnState {
	.wmu.Lock()
	 := .maxConcurrentStreams
	if !.seenSettings {
		 = 0
	}
	.wmu.Unlock()

	.mu.Lock()
	defer .mu.Unlock()
	return http2ClientConnState{
		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 http2clientConnIdleState struct {
	canTakeNewRequest bool
}

func ( *http2ClientConn) () http2clientConnIdleState {
	.mu.Lock()
	defer .mu.Unlock()
	return .idleStateLocked()
}

func ( *http2ClientConn) () ( http2clientConnIdleState) {
	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).
	//
	// This avoids a situation where an error early in a connection's lifetime
	// goes unreported.
	if .nextStreamID == 1 && .streamsReserved == 0 && .closed {
		.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 ( *http2ClientConn) () int {
	return len(.streams) + .streamsReserved + .pendingResets
}

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

// tooIdleLocked reports whether this connection has been been sitting idle
// for too much wall time.
func ( *http2ClientConn) () 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 ( *http2ClientConn) () {
	.closeIfIdle()
}

func ( *http2ClientConn) () {
	 := 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 ( *http2ClientConn) () {
	,  := .tconn.(*tls.Conn)
	if ! {
		return
	}
	if  := .NetConn();  != nil {
		.Close()
	}
}

func ( *http2ClientConn) () {
	.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 http2VerboseLogs {
		.vlogf("http2: Transport closing idle conn %p (forSingleUse=%v, maxStream=%v)", , .singleUse, -2)
	}
	.closeConn()
}

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

var http2shutdownEnterWaitStateHook = func() {}

// Shutdown gracefully closes the client connection, waiting for running streams to complete.
func ( *http2ClientConn) ( 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()
		}
	}()
	http2shutdownEnterWaitStateHook()
	select {
	case <-:
		.closeConn()
		return nil
	case <-.Done():
		.mu.Lock()
		// Free the goroutine above
		 = true
		.cond.Broadcast()
		.mu.Unlock()
		return .Err()
	}
}

func ( *http2ClientConn) () 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(, http2ErrCodeNo, 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 ( *http2ClientConn) ( 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 ( *http2ClientConn) () 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 ( *http2ClientConn) () {
	 := 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 http2errRequestCanceled = errors.New("net/http: request canceled")

func http2commaSeparatedTrailers( *Request) (string, error) {
	 := make([]string, 0, len(.Trailer))
	for  := range .Trailer {
		 = http2canonicalHeader()
		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 ( *http2ClientConn) () 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 http2checkConnHeaders( *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] != "" && !http2asciiEqualFold([0], "close") && !http2asciiEqualFold([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 http2actualContentLength( *Request) int64 {
	if .Body == nil || .Body == NoBody {
		return 0
	}
	if .ContentLength != 0 {
		return .ContentLength
	}
	return -1
}

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

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

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

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

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

	go .doRequest(, )

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

	 := func() (*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 == http2noBody && http2actualContentLength() == 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( *http2clientStream,  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(http2errRequestCanceled)
			return nil, (, http2errRequestCanceled)
		}
	}
}

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

var http2errExtendedConnectNotSupported = 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 ( *http2clientStream) ( *Request,  func(*http2clientStream)) ( error) {
	 := .cc
	 := .ctx

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

	// 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 http2errRequestCanceled
		case <-.Done():
			return .Err()
		case <-.seenSettingsChan:
			if !.extendedConnectAllowed {
				return http2errExtendedConnectNotSupported
			}
		}
	}
	select {
	case .reqHeaderMu <- struct{}{}:
	case <-.reqCancel:
		return http2errRequestCanceled
	case <-.Done():
		return .Err()
	}

	.mu.Lock()
	if .idleTimer != nil {
		.idleTimer.Stop()
	}
	.decrStreamReservationsLocked()
	if  := .awaitOpenSlotForStreamLocked();  != nil {
		.mu.Unlock()
		<-.reqHeaderMu
		return 
	}
	.addStreamLocked() // assigns stream ID
	if http2isConnectionCloseRequest() {
		.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 {
			http2traceWait100Continue(.trace)
			 := time.NewTimer()
			select {
			case <-.C:
				 = nil
			case <-.on100:
				 = nil
			case <-.abort:
				 = .abortErr
			case <-.Done():
				 = .Err()
			case <-.reqCancel:
				 = http2errRequestCanceled
			}
			.Stop()
			if  != nil {
				http2traceWroteRequest(.trace, )
				return 
			}
		}

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

	http2traceWroteRequest(.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 http2errTimeout
		case <-:
			 = nil
			 = nil // keep waiting for END_STREAM
		case <-.abort:
			return .abortErr
		case <-.Done():
			return .Err()
		case <-.reqCancel:
			return http2errRequestCanceled
		}
	}
}

func ( *http2clientStream) ( *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 http2errRequestCanceled
	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,})
	,  := http2commaSeparatedTrailers()
	if  != nil {
		return 
	}
	 :=  != ""
	 := http2actualContentLength()
	 :=  != 0
	,  := .encodeHeaders(, .requestedGzip, , )
	if  != nil {
		return 
	}

	// Write the request.
	 := ! && !
	.sentHeaders = true
	 = .writeHeaders(.ID, , int(.maxFrameSize), )
	http2traceWroteHeaders(.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 ( *http2clientStream) ( 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 ,  := .(http2StreamError);  {
				if .Cause != http2errFromPeer {
					.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, http2ErrCodeCancel, , )
			}
		}
		.bufPipe.CloseWithError() // no-op if already closed
	} else {
		if .sentHeaders && !.sentEndStream {
			.writeStreamReset(.ID, http2ErrCodeNo, false, nil)
		}
		.bufPipe.CloseWithError(http2errRequestCanceled)
	}
	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 ( *http2ClientConn) ( *http2clientStream) 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 http2errClientConnNotEstablished
		}
		.lastActive = .t.now()
		if .closed || !.canTakeNewRequestLocked() {
			return http2errClientConnUnusable
		}
		.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 ( *http2ClientConn) ( 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(http2HeadersFrameParam{
				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
	http2errStopReqBodyWrite = errors.New("http2: aborting request body write")

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

	http2errReqBodyTooLong = 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 ( *http2clientStream) ( 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 http2bufPools [7]sync.Pool // of *[]byte

func http2bufPoolIndex( int) int {
	if  <= 16384 {
		return 0
	}
	 -= 1
	 := bits.Len(uint())
	 :=  - 14
	if  >= len(http2bufPools) {
		return len(http2bufPools) - 1
	}
	return 
}

func ( *http2clientStream) ( *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
	 := http2bufPoolIndex()
	if ,  := http2bufPools[].Get().(*[]byte);  && len(*) >=  {
		defer http2bufPools[].Put()
		 = *
	} else {
		 = make([]byte, )
		defer http2bufPools[].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 {
				 = http2errReqBodyTooLong
				return 
			}
		}
		if  != nil {
			.mu.Lock()
			 := .reqBodyClosed != nil
			.mu.Unlock()
			switch {
			case :
				return http2errStopReqBodyWrite
			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 ( *http2clientStream) ( int) ( int32,  error) {
	 := .cc
	 := .ctx
	.mu.Lock()
	defer .mu.Unlock()
	for {
		if .closed {
			return 0, http2errClientConnClosed
		}
		if .reqBodyClosed != nil {
			return 0, http2errStopReqBodyWrite
		}
		select {
		case <-.abort:
			return 0, .abortErr
		case <-.Done():
			return 0, .Err()
		case <-.reqCancel:
			return 0, http2errRequestCanceled
		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()
	}
}

func http2validateHeaders( Header) string {
	for ,  := range  {
		if !httpguts.ValidHeaderFieldName() &&  != ":protocol" {
			return fmt.Sprintf("name %q", )
		}
		for ,  := range  {
			if !httpguts.ValidHeaderFieldValue() {
				// Don't include the value in the error,
				// because it may be sensitive.
				return fmt.Sprintf("value for header %q", )
			}
		}
	}
	return ""
}

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

func http2isNormalConnect( *Request) bool {
	return .Method == "CONNECT" && .Header.Get(":protocol") == ""
}

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

	 := .Host
	if  == "" {
		 = .URL.Host
	}
	,  := httpguts.PunycodeHostPort()
	if  != nil {
		return nil, 
	}
	if !httpguts.ValidHostHeader() {
		return nil, errors.New("http2: invalid Host header")
	}

	var  string
	if !http2isNormalConnect() {
		 = .URL.RequestURI()
		if !http2validPseudoPath() {
			 := 
			 = strings.TrimPrefix(, .URL.Scheme+"://"+)
			if !http2validPseudoPath() {
				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+trailers 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)
	if  := http2validateHeaders(.Header);  != "" {
		return nil, fmt.Errorf("invalid HTTP header %s", )
	}
	if  := http2validateHeaders(.Trailer);  != "" {
		return nil, fmt.Errorf("invalid HTTP trailer %s", )
	}

	 := 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  == "" {
			 = MethodGet
		}
		(":method", )
		if !http2isNormalConnect() {
			(":path", )
			(":scheme", .URL.Scheme)
		}
		if  != "" {
			("trailer", )
		}

		var  bool
		for ,  := range .Header {
			if http2asciiEqualFold(, "host") || http2asciiEqualFold(, "content-length") {
				// Host is :authority, already sent.
				// Content-Length is automatic, set below.
				continue
			} else if http2asciiEqualFold(, "connection") ||
				http2asciiEqualFold(, "proxy-connection") ||
				http2asciiEqualFold(, "transfer-encoding") ||
				http2asciiEqualFold(, "upgrade") ||
				http2asciiEqualFold(, "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 http2asciiEqualFold(, "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 http2asciiEqualFold(, "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 http2shouldSendReqContentLength(.Method, ) {
			("content-length", strconv.FormatInt(, 10))
		}
		if  {
			("accept-encoding", "gzip")
		}
		if ! {
			("user-agent", http2defaultUserAgent)
		}
	}

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

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

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

	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 http2shouldSendReqContentLength( 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 ( *http2ClientConn) ( Header) ([]byte, error) {
	.hbuf.Reset()

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

	for ,  := range  {
		,  := http2lowerHeader()
		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 ( *http2ClientConn) (,  string) {
	if http2VerboseLogs {
		log.Printf("http2: Transport encoding header %q = %q", , )
	}
	.henc.WriteField(hpack.HeaderField{Name: , Value: })
}

type http2resAndError struct {
	_   http2incomparable
	res *Response
	err error
}

// requires cc.mu be held.
func ( *http2ClientConn) ( *http2clientStream) {
	.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 ( *http2ClientConn) ( 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 http2VerboseLogs {
			.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 http2clientConnReadLoop struct {
	_  http2incomparable
	cc *http2ClientConn
}

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

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

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

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

func ( *http2clientConnReadLoop) () {
	 := .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 && http2isEOFOrNetReadError() {
		 = http2GoAwayError{
			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.
	const  = 5 * time.Second
	 := .t.now().Sub(.lastActive)
	if atomic.LoadUint32(&.atomicReused) == 0 &&  <  {
		.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()
}

// countReadFrameError calls Transport.CountError with a string
// representing err.
func ( *http2ClientConn) ( error) {
	 := .t.CountError
	if  == nil ||  == nil {
		return
	}
	if ,  := .(http2ConnectionError);  {
		 := http2ErrCode()
		(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(, http2ErrFrameTooLarge) {
		("read_frame_too_large")
		return
	}
	("read_frame_other")
}

func ( *http2clientConnReadLoop) () error {
	 := .cc
	 := false
	 := .readIdleTimeout
	var  http2timer
	if  != 0 {
		 = .t.afterFunc(, .healthCheck)
	}
	for {
		,  := .fr.ReadFrame()
		if  != nil {
			.Reset()
		}
		if  != nil {
			.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", , , )
		}
		if ,  := .(http2StreamError);  {
			if  := .streamByID(.StreamID, http2notHeaderOrDataFrame);  != nil {
				if .Cause == nil {
					.Cause = .fr.errDetail
				}
				.endStreamError(, )
			}
			continue
		} else if  != nil {
			.countReadFrameError()
			return 
		}
		if http2VerboseLogs {
			.vlogf("http2: Transport received %s", http2summarizeFrame())
		}
		if ! {
			if ,  := .(*http2SettingsFrame); ! {
				.logf("protocol error: received %T before a SETTINGS frame", )
				return http2ConnectionError(http2ErrCodeProtocol)
			}
			 = true
		}

		switch f := .(type) {
		case *http2MetaHeadersFrame:
			 = .processHeaders()
		case *http2DataFrame:
			 = .processData()
		case *http2GoAwayFrame:
			 = .processGoAway()
		case *http2RSTStreamFrame:
			 = .processResetStream()
		case *http2SettingsFrame:
			 = .processSettings()
		case *http2PushPromiseFrame:
			 = .processPushPromise()
		case *http2WindowUpdateFrame:
			 = .processWindowUpdate()
		case *http2PingFrame:
			 = .processPing()
		default:
			.logf("Transport: unhandled response frame type %T", )
		}
		if  != nil {
			if http2VerboseLogs {
				.vlogf("http2: Transport conn %p received error from processing frame %v: %v", , http2summarizeFrame(), )
			}
			if !.seenSettings {
				close(.seenSettingsChan)
			}
			return 
		}
	}
}

func ( *http2clientConnReadLoop) ( *http2MetaHeadersFrame) error {
	 := .streamByID(.StreamID, http2headerOrDataFrame)
	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(, http2StreamError{
			StreamID: .StreamID,
			Code:     http2ErrCodeProtocol,
			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.
			http2traceFirstResponseByte(.trace)
		}
		.firstByte = true
	}
	if !.pastHeaders {
		.pastHeaders = true
	} else {
		return .processTrailers(, )
	}

	,  := .handleResponse(, )
	if  != nil {
		if ,  := .(http2ConnectionError);  {
			return 
		}
		// Any other error type is a stream error.
		.endStreamError(, http2StreamError{
			StreamID: .StreamID,
			Code:     http2ErrCodeProtocol,
			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 ( *http2clientConnReadLoop) ( *http2clientStream,  *http2MetaHeadersFrame) (*Response, error) {
	if .Truncated {
		return nil, http2errResponseHeaderListSize
	}

	 := .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(Header, len())
	 := &Response{
		Proto:      "HTTP/2.0",
		ProtoMajor: 2,
		Header:     ,
		StatusCode: ,
		Status:      + " " + StatusText(),
	}
	for ,  := range  {
		 := http2canonicalHeader(.Name)
		if  == "Trailer" {
			 := .Trailer
			if  == nil {
				 = make(Header)
				.Trailer = 
			}
			http2foreachHeaderElement(.Value, func( string) {
				[http2canonicalHeader()] = 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 http2VerboseLogs {
					log.Printf("http2: 1xx informational responses too large")
				}
				return nil, errors.New("header list too large")
			}
		}
		if  == 100 {
			http2traceGot100Continue(.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 = http2noBody
		return , nil
	}

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

	.bufPipe.setBuffer(&http2dataBuffer{expected: .ContentLength})
	.bytesRemain = .ContentLength
	.Body = http2transportResponseBody{}

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

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

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

	.endStream()
	return nil
}

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

func ( http2transportResponseBody) ( []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, http2mustUint31())
		}
		if  != 0 {
			.fr.WriteWindowUpdate(.ID, http2mustUint31())
		}
		.bw.Flush()
	}
	return
}

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

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

	.bufPipe.BreakWithError(http2errClosedResponseBody)
	.abortStream(http2errClosedResponseBody)

	 := .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 http2errRequestCanceled
	}
	return nil
}

func ( *http2clientConnReadLoop) ( *http2DataFrame) error {
	 := .cc
	 := .streamByID(.StreamID, http2headerOrDataFrame)
	 := .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 http2ConnectionError(http2ErrCodeProtocol)
		}
		// 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 http2ConnectionError(http2ErrCodeFlowControl)
			}
			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(, http2StreamError{
			StreamID: .StreamID,
			Code:     http2ErrCodeProtocol,
		})
		return nil
	}
	if !.pastHeaders {
		.logf("protocol error: received DATA before a HEADERS frame")
		.endStreamError(, http2StreamError{
			StreamID: .StreamID,
			Code:     http2ErrCodeProtocol,
		})
		return nil
	}
	if .Length > 0 {
		if .isHead && len() > 0 {
			.logf("protocol error: received DATA on a HEAD request")
			.endStreamError(, http2StreamError{
				StreamID: .StreamID,
				Code:     http2ErrCodeProtocol,
			})
			return nil
		}
		// Check connection-level flow control.
		.mu.Lock()
		if !http2takeInflows(&.inflow, &.inflow, .Length) {
			.mu.Unlock()
			return http2ConnectionError(http2ErrCodeFlowControl)
		}
		// 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 ( *http2clientConnReadLoop) ( *http2clientStream) {
	// 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 ( *http2clientConnReadLoop) ( *http2clientStream,  error) {
	.readAborted = true
	.abortStream()
}

// Constants passed to streamByID for documentation purposes.
const (
	http2headerOrDataFrame    = true
	http2notHeaderOrDataFrame = 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 ( *http2clientConnReadLoop) ( uint32,  bool) *http2clientStream {
	.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 ( *http2clientStream) () {
	for ,  := range .trailer {
		 := .resTrailer
		if * == nil {
			* = make(Header)
		}
		(*)[] = 
	}
}

func ( *http2clientConnReadLoop) ( *http2GoAwayFrame) 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 ( *http2clientConnReadLoop) ( *http2SettingsFrame) 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 ( *http2clientConnReadLoop) ( *http2SettingsFrame) error {
	 := .cc
	.mu.Lock()
	defer .mu.Unlock()

	if .IsAck() {
		if .wantSettingsAck {
			.wantSettingsAck = false
			return nil
		}
		return http2ConnectionError(http2ErrCodeProtocol)
	}

	var  bool
	 := .ForeachSetting(func( http2Setting) error {
		switch .ID {
		case http2SettingMaxFrameSize:
			.maxFrameSize = .Val
		case http2SettingMaxConcurrentStreams:
			.maxConcurrentStreams = .Val
			 = true
		case http2SettingMaxHeaderListSize:
			.peerMaxHeaderListSize = uint64(.Val)
		case http2SettingInitialWindowSize:
			// 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 http2ConnectionError(http2ErrCodeFlowControl)
			}

			// 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 http2SettingHeaderTableSize:
			.henc.SetMaxDynamicTableSize(.Val)
			.peerMaxHeaderTableSize = .Val
		case http2SettingEnableConnectProtocol:
			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 = http2defaultMaxConcurrentStreams
		}
		close(.seenSettingsChan)
		.seenSettings = true
	}

	return nil
}

func ( *http2clientConnReadLoop) ( *http2WindowUpdateFrame) error {
	 := .cc
	 := .streamByID(.StreamID, http2notHeaderOrDataFrame)
	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(, http2StreamError{
				StreamID: .StreamID,
				Code:     http2ErrCodeFlowControl,
			})
			return nil
		}

		return http2ConnectionError(http2ErrCodeFlowControl)
	}
	.cond.Broadcast()
	return nil
}

func ( *http2clientConnReadLoop) ( *http2RSTStreamFrame) error {
	 := .streamByID(.StreamID, http2notHeaderOrDataFrame)
	if  == nil {
		// TODO: return error if server tries to RST_STREAM an idle stream
		return nil
	}
	 := http2streamError(.ID, .ErrCode)
	.Cause = http2errFromPeer
	if .ErrCode == http2ErrCodeProtocol {
		.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 ( *http2ClientConn) ( 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 ( *http2clientConnReadLoop) ( *http2PingFrame) 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 ( *http2clientConnReadLoop) ( *http2PushPromiseFrame) 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 http2ConnectionError(http2ErrCodeProtocol)
}

// writeStreamReset sends a RST_STREAM frame.
// When ping is true, it also sends a PING frame with a random payload.
func ( *http2ClientConn) ( uint32,  http2ErrCode,  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 (
	http2errResponseHeaderListSize = errors.New("http2: response header list larger than advertised limit")
	http2errRequestHeaderListSize  = errors.New("http2: request header list larger than peer's advertised limit")
)

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

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

func ( *http2Transport) ( string,  ...interface{}) {
	if http2VerboseLogs {
		.logf(, ...)
	}
}

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

var http2noBody io.ReadCloser = http2noBodyReader{}

type http2noBodyReader struct{}

func (http2noBodyReader) () error { return nil }

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

type http2missingBody struct{}

func (http2missingBody) () error { return nil }

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

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

type http2erringRoundTripper struct{ err error }

func ( http2erringRoundTripper) () error { return .err }

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

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

func ( *http2gzipReader) ( []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 ( *http2gzipReader) () error {
	if  := .body.Close();  != nil {
		return 
	}
	.zerr = fs.ErrClosed
	return nil
}

type http2errorReader struct{ err error }

func ( http2errorReader) ( []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 http2isConnectionCloseRequest( *Request) bool {
	return .Close || httpguts.HeaderValuesContainsToken(.Header["Connection"], "close")
}

// registerHTTPSProtocol calls Transport.RegisterProtocol but
// converting panics into errors.
func http2registerHTTPSProtocol( *Transport,  http2noDialH2RoundTripper) ( 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 http2noDialH2RoundTripper struct{ *http2Transport }

func ( http2noDialH2RoundTripper) ( *Request) (*Response, error) {
	,  := .http2Transport.RoundTrip()
	if http2isNoCachedConnError() {
		return nil, ErrSkipAltProtocol
	}
	return , 
}

func ( *http2Transport) () 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 http2traceGetConn( *Request,  string) {
	 := httptrace.ContextClientTrace(.Context())
	if  == nil || .GetConn == nil {
		return
	}
	.GetConn()
}

func http2traceGotConn( *Request,  *http2ClientConn,  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 http2traceWroteHeaders( *httptrace.ClientTrace) {
	if  != nil && .WroteHeaders != nil {
		.WroteHeaders()
	}
}

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

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

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

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

func http2traceHasWroteHeaderField( *httptrace.ClientTrace) bool {
	return  != nil && .WroteHeaderField != nil
}

func http2traceWroteHeaderField( *httptrace.ClientTrace, ,  string) {
	if  != nil && .WroteHeaderField != nil {
		.WroteHeaderField(, []string{})
	}
}

func http2traceGot1xxResponseFunc( *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 ( *http2Transport) ( 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
}

const http2nextProtoUnencryptedHTTP2 = "unencrypted_http2"

// unencryptedNetConnFromTLSConn retrieves a net.Conn wrapped in a *tls.Conn.
//
// TLSNextProto functions accept a *tls.Conn.
//
// When passing an unencrypted HTTP/2 connection to a TLSNextProto function,
// we pass a *tls.Conn with an underlying net.Conn containing the unencrypted connection.
// To be extra careful about mistakes (accidentally dropping TLS encryption in a place
// where we want it), the tls.Conn contains a net.Conn with an UnencryptedNetConn method
// that returns the actual connection we want to use.
func http2unencryptedNetConnFromTLSConn( *tls.Conn) (net.Conn, error) {
	,  := .NetConn().(interface {
		() net.Conn
	})
	if ! {
		return nil, errors.New("http2: TLS conn unexpectedly found in unencrypted handoff")
	}
	return .(), nil
}

// writeFramer is implemented by any type that is used to write frames.
type http2writeFramer interface {
	writeFrame(http2writeContext) error

	// staysWithinBuffer reports whether this writer promises that
	// it will only write less than or equal to size bytes, and it
	// won't Flush the write context.
	staysWithinBuffer(size int) bool
}

// writeContext is the interface needed by the various frame writer
// types below. All the writeFrame methods below are scheduled via the
// frame writing scheduler (see writeScheduler in writesched.go).
//
// This interface is implemented by *serverConn.
//
// TODO: decide whether to a) use this in the client code (which didn't
// end up using this yet, because it has a simpler design, not
// currently implementing priorities), or b) delete this and
// make the server code a bit more concrete.
type http2writeContext interface {
	Framer() *http2Framer
	Flush() error
	CloseConn() error
	// HeaderEncoder returns an HPACK encoder that writes to the
	// returned buffer.
	HeaderEncoder() (*hpack.Encoder, *bytes.Buffer)
}

// writeEndsStream reports whether w writes a frame that will transition
// the stream to a half-closed local state. This returns false for RST_STREAM,
// which closes the entire stream (not just the local half).
func http2writeEndsStream( http2writeFramer) bool {
	switch v := .(type) {
	case *http2writeData:
		return .endStream
	case *http2writeResHeaders:
		return .endStream
	case nil:
		// This can only happen if the caller reuses w after it's
		// been intentionally nil'ed out to prevent use. Keep this
		// here to catch future refactoring breaking it.
		panic("writeEndsStream called on nil writeFramer")
	}
	return false
}

type http2flushFrameWriter struct{}

func (http2flushFrameWriter) ( http2writeContext) error {
	return .Flush()
}

func (http2flushFrameWriter) ( int) bool { return false }

type http2writeSettings []http2Setting

func ( http2writeSettings) ( int) bool {
	const  = 6 // uint16 + uint32
	return http2frameHeaderLen+*len() <= 

}

func ( http2writeSettings) ( http2writeContext) error {
	return .Framer().WriteSettings([]http2Setting()...)
}

type http2writeGoAway struct {
	maxStreamID uint32
	code        http2ErrCode
}

func ( *http2writeGoAway) ( http2writeContext) error {
	 := .Framer().WriteGoAway(.maxStreamID, .code, nil)
	.Flush() // ignore error: we're hanging up on them anyway
	return 
}

func (*http2writeGoAway) ( int) bool { return false } // flushes

type http2writeData struct {
	streamID  uint32
	p         []byte
	endStream bool
}

func ( *http2writeData) () string {
	return fmt.Sprintf("writeData(stream=%d, p=%d, endStream=%v)", .streamID, len(.p), .endStream)
}

func ( *http2writeData) ( http2writeContext) error {
	return .Framer().WriteData(.streamID, .endStream, .p)
}

func ( *http2writeData) ( int) bool {
	return http2frameHeaderLen+len(.p) <= 
}

// handlerPanicRST is the message sent from handler goroutines when
// the handler panics.
type http2handlerPanicRST struct {
	StreamID uint32
}

func ( http2handlerPanicRST) ( http2writeContext) error {
	return .Framer().WriteRSTStream(.StreamID, http2ErrCodeInternal)
}

func ( http2handlerPanicRST) ( int) bool { return http2frameHeaderLen+4 <=  }

func ( http2StreamError) ( http2writeContext) error {
	return .Framer().WriteRSTStream(.StreamID, .Code)
}

func ( http2StreamError) ( int) bool { return http2frameHeaderLen+4 <=  }

type http2writePing struct {
	data [8]byte
}

func ( http2writePing) ( http2writeContext) error {
	return .Framer().WritePing(false, .data)
}

func ( http2writePing) ( int) bool {
	return http2frameHeaderLen+len(.data) <= 
}

type http2writePingAck struct{ pf *http2PingFrame }

func ( http2writePingAck) ( http2writeContext) error {
	return .Framer().WritePing(true, .pf.Data)
}

func ( http2writePingAck) ( int) bool {
	return http2frameHeaderLen+len(.pf.Data) <= 
}

type http2writeSettingsAck struct{}

func (http2writeSettingsAck) ( http2writeContext) error {
	return .Framer().WriteSettingsAck()
}

func (http2writeSettingsAck) ( int) bool { return http2frameHeaderLen <=  }

// splitHeaderBlock splits headerBlock into fragments so that each fragment fits
// in a single frame, then calls fn for each fragment. firstFrag/lastFrag are true
// for the first/last fragment, respectively.
func http2splitHeaderBlock( http2writeContext,  []byte,  func( http2writeContext,  []byte, ,  bool) error) error {
	// For now we're lazy and just pick the minimum MAX_FRAME_SIZE
	// that all peers must support (16KB). Later we could care
	// more and send larger frames if the peer advertised it, but
	// there's little point. Most headers are small anyway (so we
	// generally won't have CONTINUATION frames), and extra frames
	// only waste 9 bytes anyway.
	const  = 16384

	 := true
	for len() > 0 {
		 := 
		if len() >  {
			 = [:]
		}
		 = [len():]
		if  := (, , , len() == 0);  != nil {
			return 
		}
		 = false
	}
	return nil
}

// writeResHeaders is a request to write a HEADERS and 0+ CONTINUATION frames
// for HTTP response headers or trailers from a server handler.
type http2writeResHeaders struct {
	streamID    uint32
	httpResCode int      // 0 means no ":status" line
	h           Header   // may be nil
	trailers    []string // if non-nil, which keys of h to write. nil means all.
	endStream   bool

	date          string
	contentType   string
	contentLength string
}

func http2encKV( *hpack.Encoder, ,  string) {
	if http2VerboseLogs {
		log.Printf("http2: server encoding header %q = %q", , )
	}
	.WriteField(hpack.HeaderField{Name: , Value: })
}

func ( *http2writeResHeaders) ( int) bool {
	// TODO: this is a common one. It'd be nice to return true
	// here and get into the fast path if we could be clever and
	// calculate the size fast enough, or at least a conservative
	// upper bound that usually fires. (Maybe if w.h and
	// w.trailers are nil, so we don't need to enumerate it.)
	// Otherwise I'm afraid that just calculating the length to
	// answer this question would be slower than the ~2µs benefit.
	return false
}

func ( *http2writeResHeaders) ( http2writeContext) error {
	,  := .HeaderEncoder()
	.Reset()

	if .httpResCode != 0 {
		http2encKV(, ":status", http2httpCodeString(.httpResCode))
	}

	http2encodeHeaders(, .h, .trailers)

	if .contentType != "" {
		http2encKV(, "content-type", .contentType)
	}
	if .contentLength != "" {
		http2encKV(, "content-length", .contentLength)
	}
	if .date != "" {
		http2encKV(, "date", .date)
	}

	 := .Bytes()
	if len() == 0 && .trailers == nil {
		panic("unexpected empty hpack")
	}

	return http2splitHeaderBlock(, , .writeHeaderBlock)
}

func ( *http2writeResHeaders) ( http2writeContext,  []byte, ,  bool) error {
	if  {
		return .Framer().WriteHeaders(http2HeadersFrameParam{
			StreamID:      .streamID,
			BlockFragment: ,
			EndStream:     .endStream,
			EndHeaders:    ,
		})
	} else {
		return .Framer().WriteContinuation(.streamID, , )
	}
}

// writePushPromise is a request to write a PUSH_PROMISE and 0+ CONTINUATION frames.
type http2writePushPromise struct {
	streamID uint32   // pusher stream
	method   string   // for :method
	url      *url.URL // for :scheme, :authority, :path
	h        Header

	// Creates an ID for a pushed stream. This runs on serveG just before
	// the frame is written. The returned ID is copied to promisedID.
	allocatePromisedID func() (uint32, error)
	promisedID         uint32
}

func ( *http2writePushPromise) ( int) bool {
	// TODO: see writeResHeaders.staysWithinBuffer
	return false
}

func ( *http2writePushPromise) ( http2writeContext) error {
	,  := .HeaderEncoder()
	.Reset()

	http2encKV(, ":method", .method)
	http2encKV(, ":scheme", .url.Scheme)
	http2encKV(, ":authority", .url.Host)
	http2encKV(, ":path", .url.RequestURI())
	http2encodeHeaders(, .h, nil)

	 := .Bytes()
	if len() == 0 {
		panic("unexpected empty hpack")
	}

	return http2splitHeaderBlock(, , .writeHeaderBlock)
}

func ( *http2writePushPromise) ( http2writeContext,  []byte, ,  bool) error {
	if  {
		return .Framer().WritePushPromise(http2PushPromiseParam{
			StreamID:      .streamID,
			PromiseID:     .promisedID,
			BlockFragment: ,
			EndHeaders:    ,
		})
	} else {
		return .Framer().WriteContinuation(.streamID, , )
	}
}

type http2write100ContinueHeadersFrame struct {
	streamID uint32
}

func ( http2write100ContinueHeadersFrame) ( http2writeContext) error {
	,  := .HeaderEncoder()
	.Reset()
	http2encKV(, ":status", "100")
	return .Framer().WriteHeaders(http2HeadersFrameParam{
		StreamID:      .streamID,
		BlockFragment: .Bytes(),
		EndStream:     false,
		EndHeaders:    true,
	})
}

func ( http2write100ContinueHeadersFrame) ( int) bool {
	// Sloppy but conservative:
	return 9+2*(len(":status")+len("100")) <= 
}

type http2writeWindowUpdate struct {
	streamID uint32 // or 0 for conn-level
	n        uint32
}

func ( http2writeWindowUpdate) ( int) bool { return http2frameHeaderLen+4 <=  }

func ( http2writeWindowUpdate) ( http2writeContext) error {
	return .Framer().WriteWindowUpdate(.streamID, .n)
}

// encodeHeaders encodes an http.Header. If keys is not nil, then (k, h[k])
// is encoded only if k is in keys.
func http2encodeHeaders( *hpack.Encoder,  Header,  []string) {
	if  == nil {
		 := http2sorterPool.Get().(*http2sorter)
		// Using defer here, since the returned keys from the
		// sorter.Keys method is only valid until the sorter
		// is returned:
		defer http2sorterPool.Put()
		 = .Keys()
	}
	for ,  := range  {
		 := []
		,  := http2lowerHeader()
		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
		}
		if !http2validWireHeaderFieldName() {
			// Skip it as backup paranoia. Per
			// golang.org/issue/14048, these should
			// already be rejected at a higher level.
			continue
		}
		 :=  == "transfer-encoding"
		for ,  := range  {
			if !httpguts.ValidHeaderFieldValue() {
				// TODO: return an error? golang.org/issue/14048
				// For now just omit it.
				continue
			}
			// TODO: more of "8.1.2.2 Connection-Specific Header Fields"
			if  &&  != "trailers" {
				continue
			}
			http2encKV(, , )
		}
	}
}

// WriteScheduler is the interface implemented by HTTP/2 write schedulers.
// Methods are never called concurrently.
type http2WriteScheduler interface {
	// OpenStream opens a new stream in the write scheduler.
	// It is illegal to call this with streamID=0 or with a streamID that is
	// already open -- the call may panic.
	OpenStream(streamID uint32, options http2OpenStreamOptions)

	// CloseStream closes a stream in the write scheduler. Any frames queued on
	// this stream should be discarded. It is illegal to call this on a stream
	// that is not open -- the call may panic.
	CloseStream(streamID uint32)

	// AdjustStream adjusts the priority of the given stream. This may be called
	// on a stream that has not yet been opened or has been closed. Note that
	// RFC 7540 allows PRIORITY frames to be sent on streams in any state. See:
	// https://tools.ietf.org/html/rfc7540#section-5.1
	AdjustStream(streamID uint32, priority http2PriorityParam)

	// Push queues a frame in the scheduler. In most cases, this will not be
	// called with wr.StreamID()!=0 unless that stream is currently open. The one
	// exception is RST_STREAM frames, which may be sent on idle or closed streams.
	Push(wr http2FrameWriteRequest)

	// Pop dequeues the next frame to write. Returns false if no frames can
	// be written. Frames with a given wr.StreamID() are Pop'd in the same
	// order they are Push'd, except RST_STREAM frames. No frames should be
	// discarded except by CloseStream.
	Pop() (wr http2FrameWriteRequest, ok bool)
}

// OpenStreamOptions specifies extra options for WriteScheduler.OpenStream.
type http2OpenStreamOptions struct {
	// PusherID is zero if the stream was initiated by the client. Otherwise,
	// PusherID names the stream that pushed the newly opened stream.
	PusherID uint32
}

// FrameWriteRequest is a request to write a frame.
type http2FrameWriteRequest struct {
	// write is the interface value that does the writing, once the
	// WriteScheduler has selected this frame to write. The write
	// functions are all defined in write.go.
	write http2writeFramer

	// stream is the stream on which this frame will be written.
	// nil for non-stream frames like PING and SETTINGS.
	// nil for RST_STREAM streams, which use the StreamError.StreamID field instead.
	stream *http2stream

	// done, if non-nil, must be a buffered channel with space for
	// 1 message and is sent the return value from write (or an
	// earlier error) when the frame has been written.
	done chan error
}

// StreamID returns the id of the stream this frame will be written to.
// 0 is used for non-stream frames such as PING and SETTINGS.
func ( http2FrameWriteRequest) () uint32 {
	if .stream == nil {
		if ,  := .write.(http2StreamError);  {
			// (*serverConn).resetStream doesn't set
			// stream because it doesn't necessarily have
			// one. So special case this type of write
			// message.
			return .StreamID
		}
		return 0
	}
	return .stream.id
}

// isControl reports whether wr is a control frame for MaxQueuedControlFrames
// purposes. That includes non-stream frames and RST_STREAM frames.
func ( http2FrameWriteRequest) () bool {
	return .stream == nil
}

// DataSize returns the number of flow control bytes that must be consumed
// to write this entire frame. This is 0 for non-DATA frames.
func ( http2FrameWriteRequest) () int {
	if ,  := .write.(*http2writeData);  {
		return len(.p)
	}
	return 0
}

// Consume consumes min(n, available) bytes from this frame, where available
// is the number of flow control bytes available on the stream. Consume returns
// 0, 1, or 2 frames, where the integer return value gives the number of frames
// returned.
//
// If flow control prevents consuming any bytes, this returns (_, _, 0). If
// the entire frame was consumed, this returns (wr, _, 1). Otherwise, this
// returns (consumed, rest, 2), where 'consumed' contains the consumed bytes and
// 'rest' contains the remaining bytes. The consumed bytes are deducted from the
// underlying stream's flow control budget.
func ( http2FrameWriteRequest) ( int32) (http2FrameWriteRequest, http2FrameWriteRequest, int) {
	var  http2FrameWriteRequest

	// Non-DATA frames are always consumed whole.
	,  := .write.(*http2writeData)
	if ! || len(.p) == 0 {
		return , , 1
	}

	// Might need to split after applying limits.
	 := .stream.flow.available()
	if  <  {
		 = 
	}
	if .stream.sc.maxFrameSize <  {
		 = .stream.sc.maxFrameSize
	}
	if  <= 0 {
		return , , 0
	}
	if len(.p) > int() {
		.stream.flow.take()
		 := http2FrameWriteRequest{
			stream: .stream,
			write: &http2writeData{
				streamID: .streamID,
				p:        .p[:],
				// Even if the original had endStream set, there
				// are bytes remaining because len(wd.p) > allowed,
				// so we know endStream is false.
				endStream: false,
			},
			// Our caller is blocking on the final DATA frame, not
			// this intermediate frame, so no need to wait.
			done: nil,
		}
		 := http2FrameWriteRequest{
			stream: .stream,
			write: &http2writeData{
				streamID:  .streamID,
				p:         .p[:],
				endStream: .endStream,
			},
			done: .done,
		}
		return , , 2
	}

	// The frame is consumed whole.
	// NB: This cast cannot overflow because allowed is <= math.MaxInt32.
	.stream.flow.take(int32(len(.p)))
	return , , 1
}

// String is for debugging only.
func ( http2FrameWriteRequest) () string {
	var  string
	if ,  := .write.(fmt.Stringer);  {
		 = .String()
	} else {
		 = fmt.Sprintf("%T", .write)
	}
	return fmt.Sprintf("[FrameWriteRequest stream=%d, ch=%v, writer=%v]", .StreamID(), .done != nil, )
}

// replyToWriter sends err to wr.done and panics if the send must block
// This does nothing if wr.done is nil.
func ( *http2FrameWriteRequest) ( error) {
	if .done == nil {
		return
	}
	select {
	case .done <- :
	default:
		panic(fmt.Sprintf("unbuffered done channel passed in for type %T", .write))
	}
	.write = nil // prevent use (assume it's tainted after wr.done send)
}

// writeQueue is used by implementations of WriteScheduler.
type http2writeQueue struct {
	s          []http2FrameWriteRequest
	prev, next *http2writeQueue
}

func ( *http2writeQueue) () bool { return len(.s) == 0 }

func ( *http2writeQueue) ( http2FrameWriteRequest) {
	.s = append(.s, )
}

func ( *http2writeQueue) () http2FrameWriteRequest {
	if len(.s) == 0 {
		panic("invalid use of queue")
	}
	 := .s[0]
	// TODO: less copy-happy queue.
	copy(.s, .s[1:])
	.s[len(.s)-1] = http2FrameWriteRequest{}
	.s = .s[:len(.s)-1]
	return 
}

// consume consumes up to n bytes from q.s[0]. If the frame is
// entirely consumed, it is removed from the queue. If the frame
// is partially consumed, the frame is kept with the consumed
// bytes removed. Returns true iff any bytes were consumed.
func ( *http2writeQueue) ( int32) (http2FrameWriteRequest, bool) {
	if len(.s) == 0 {
		return http2FrameWriteRequest{}, false
	}
	, ,  := .s[0].Consume()
	switch  {
	case 0:
		return http2FrameWriteRequest{}, false
	case 1:
		.shift()
	case 2:
		.s[0] = 
	}
	return , true
}

type http2writeQueuePool []*http2writeQueue

// put inserts an unused writeQueue into the pool.

// put inserts an unused writeQueue into the pool.
func ( *http2writeQueuePool) ( *http2writeQueue) {
	for  := range .s {
		.s[] = http2FrameWriteRequest{}
	}
	.s = .s[:0]
	* = append(*, )
}

// get returns an empty writeQueue.
func ( *http2writeQueuePool) () *http2writeQueue {
	 := len(*)
	if  == 0 {
		return new(http2writeQueue)
	}
	 :=  - 1
	 := (*)[]
	(*)[] = nil
	* = (*)[:]
	return 
}

// RFC 7540, Section 5.3.5: the default weight is 16.
const http2priorityDefaultWeight = 15 // 16 = 15 + 1

// PriorityWriteSchedulerConfig configures a priorityWriteScheduler.
type http2PriorityWriteSchedulerConfig struct {
	// MaxClosedNodesInTree controls the maximum number of closed streams to
	// retain in the priority tree. Setting this to zero saves a small amount
	// of memory at the cost of performance.
	//
	// See RFC 7540, Section 5.3.4:
	//   "It is possible for a stream to become closed while prioritization
	//   information ... is in transit. ... This potentially creates suboptimal
	//   prioritization, since the stream could be given a priority that is
	//   different from what is intended. To avoid these problems, an endpoint
	//   SHOULD retain stream prioritization state for a period after streams
	//   become closed. The longer state is retained, the lower the chance that
	//   streams are assigned incorrect or default priority values."
	MaxClosedNodesInTree int

	// MaxIdleNodesInTree controls the maximum number of idle streams to
	// retain in the priority tree. Setting this to zero saves a small amount
	// of memory at the cost of performance.
	//
	// See RFC 7540, Section 5.3.4:
	//   Similarly, streams that are in the "idle" state can be assigned
	//   priority or become a parent of other streams. This allows for the
	//   creation of a grouping node in the dependency tree, which enables
	//   more flexible expressions of priority. Idle streams begin with a
	//   default priority (Section 5.3.5).
	MaxIdleNodesInTree int

	// ThrottleOutOfOrderWrites enables write throttling to help ensure that
	// data is delivered in priority order. This works around a race where
	// stream B depends on stream A and both streams are about to call Write
	// to queue DATA frames. If B wins the race, a naive scheduler would eagerly
	// write as much data from B as possible, but this is suboptimal because A
	// is a higher-priority stream. With throttling enabled, we write a small
	// amount of data from B to minimize the amount of bandwidth that B can
	// steal from A.
	ThrottleOutOfOrderWrites bool
}

// NewPriorityWriteScheduler constructs a WriteScheduler that schedules
// frames by following HTTP/2 priorities as described in RFC 7540 Section 5.3.
// If cfg is nil, default options are used.
func http2NewPriorityWriteScheduler( *http2PriorityWriteSchedulerConfig) http2WriteScheduler {
	if  == nil {
		// For justification of these defaults, see:
		// https://docs.google.com/document/d/1oLhNg1skaWD4_DtaoCxdSRN5erEXrH-KnLrMwEpOtFY
		 = &http2PriorityWriteSchedulerConfig{
			MaxClosedNodesInTree:     10,
			MaxIdleNodesInTree:       10,
			ThrottleOutOfOrderWrites: false,
		}
	}

	 := &http2priorityWriteScheduler{
		nodes:                make(map[uint32]*http2priorityNode),
		maxClosedNodesInTree: .MaxClosedNodesInTree,
		maxIdleNodesInTree:   .MaxIdleNodesInTree,
		enableWriteThrottle:  .ThrottleOutOfOrderWrites,
	}
	.nodes[0] = &.root
	if .ThrottleOutOfOrderWrites {
		.writeThrottleLimit = 1024
	} else {
		.writeThrottleLimit = math.MaxInt32
	}
	return 
}

type http2priorityNodeState int

const (
	http2priorityNodeOpen http2priorityNodeState = iota
	http2priorityNodeClosed
	http2priorityNodeIdle
)

// priorityNode is a node in an HTTP/2 priority tree.
// Each node is associated with a single stream ID.
// See RFC 7540, Section 5.3.
type http2priorityNode struct {
	q            http2writeQueue        // queue of pending frames to write
	id           uint32                 // id of the stream, or 0 for the root of the tree
	weight       uint8                  // the actual weight is weight+1, so the value is in [1,256]
	state        http2priorityNodeState // open | closed | idle
	bytes        int64                  // number of bytes written by this node, or 0 if closed
	subtreeBytes int64                  // sum(node.bytes) of all nodes in this subtree

	// These links form the priority tree.
	parent     *http2priorityNode
	kids       *http2priorityNode // start of the kids list
	prev, next *http2priorityNode // doubly-linked list of siblings
}

func ( *http2priorityNode) ( *http2priorityNode) {
	if  ==  {
		panic("setParent to self")
	}
	if .parent ==  {
		return
	}
	// Unlink from current parent.
	if  := .parent;  != nil {
		if .prev == nil {
			.kids = .next
		} else {
			.prev.next = .next
		}
		if .next != nil {
			.next.prev = .prev
		}
	}
	// Link to new parent.
	// If parent=nil, remove n from the tree.
	// Always insert at the head of parent.kids (this is assumed by walkReadyInOrder).
	.parent = 
	if  == nil {
		.next = nil
		.prev = nil
	} else {
		.next = .kids
		.prev = nil
		if .next != nil {
			.next.prev = 
		}
		.kids = 
	}
}

func ( *http2priorityNode) ( int64) {
	.bytes += 
	for ;  != nil;  = .parent {
		.subtreeBytes += 
	}
}

// walkReadyInOrder iterates over the tree in priority order, calling f for each node
// with a non-empty write queue. When f returns true, this function returns true and the
// walk halts. tmp is used as scratch space for sorting.
//
// f(n, openParent) takes two arguments: the node to visit, n, and a bool that is true
// if any ancestor p of n is still open (ignoring the root node).
func ( *http2priorityNode) ( bool,  *[]*http2priorityNode,  func(*http2priorityNode, bool) bool) bool {
	if !.q.empty() && (, ) {
		return true
	}
	if .kids == nil {
		return false
	}

	// Don't consider the root "open" when updating openParent since
	// we can't send data frames on the root stream (only control frames).
	if .id != 0 {
		 =  || (.state == http2priorityNodeOpen)
	}

	// Common case: only one kid or all kids have the same weight.
	// Some clients don't use weights; other clients (like web browsers)
	// use mostly-linear priority trees.
	 := .kids.weight
	 := false
	for  := .kids.next;  != nil;  = .next {
		if .weight !=  {
			 = true
			break
		}
	}
	if ! {
		for  := .kids;  != nil;  = .next {
			if .(, , ) {
				return true
			}
		}
		return false
	}

	// Uncommon case: sort the child nodes. We remove the kids from the parent,
	// then re-insert after sorting so we can reuse tmp for future sort calls.
	* = (*)[:0]
	for .kids != nil {
		* = append(*, .kids)
		.kids.setParent(nil)
	}
	sort.Sort(http2sortPriorityNodeSiblings(*))
	for  := len(*) - 1;  >= 0; -- {
		(*)[].setParent() // setParent inserts at the head of n.kids
	}
	for  := .kids;  != nil;  = .next {
		if .(, , ) {
			return true
		}
	}
	return false
}

type http2sortPriorityNodeSiblings []*http2priorityNode

func ( http2sortPriorityNodeSiblings) () int { return len() }

func ( http2sortPriorityNodeSiblings) (,  int) { [], [] = [], [] }

func ( http2sortPriorityNodeSiblings) (,  int) bool {
	// Prefer the subtree that has sent fewer bytes relative to its weight.
	// See sections 5.3.2 and 5.3.4.
	,  := float64([].weight+1), float64([].subtreeBytes)
	,  := float64([].weight+1), float64([].subtreeBytes)
	if  == 0 &&  == 0 {
		return  >= 
	}
	if  == 0 {
		return false
	}
	return / <= /
}

type http2priorityWriteScheduler struct {
	// root is the root of the priority tree, where root.id = 0.
	// The root queues control frames that are not associated with any stream.
	root http2priorityNode

	// nodes maps stream ids to priority tree nodes.
	nodes map[uint32]*http2priorityNode

	// maxID is the maximum stream id in nodes.
	maxID uint32

	// lists of nodes that have been closed or are idle, but are kept in
	// the tree for improved prioritization. When the lengths exceed either
	// maxClosedNodesInTree or maxIdleNodesInTree, old nodes are discarded.
	closedNodes, idleNodes []*http2priorityNode

	// From the config.
	maxClosedNodesInTree int
	maxIdleNodesInTree   int
	writeThrottleLimit   int32
	enableWriteThrottle  bool

	// tmp is scratch space for priorityNode.walkReadyInOrder to reduce allocations.
	tmp []*http2priorityNode

	// pool of empty queues for reuse.
	queuePool http2writeQueuePool
}

func ( *http2priorityWriteScheduler) ( uint32,  http2OpenStreamOptions) {
	// The stream may be currently idle but cannot be opened or closed.
	if  := .nodes[];  != nil {
		if .state != http2priorityNodeIdle {
			panic(fmt.Sprintf("stream %d already opened", ))
		}
		.state = http2priorityNodeOpen
		return
	}

	// RFC 7540, Section 5.3.5:
	//  "All streams are initially assigned a non-exclusive dependency on stream 0x0.
	//  Pushed streams initially depend on their associated stream. In both cases,
	//  streams are assigned a default weight of 16."
	 := .nodes[.PusherID]
	if  == nil {
		 = &.root
	}
	 := &http2priorityNode{
		q:      *.queuePool.get(),
		id:     ,
		weight: http2priorityDefaultWeight,
		state:  http2priorityNodeOpen,
	}
	.setParent()
	.nodes[] = 
	if  > .maxID {
		.maxID = 
	}
}

func ( *http2priorityWriteScheduler) ( uint32) {
	if  == 0 {
		panic("violation of WriteScheduler interface: cannot close stream 0")
	}
	if .nodes[] == nil {
		panic(fmt.Sprintf("violation of WriteScheduler interface: unknown stream %d", ))
	}
	if .nodes[].state != http2priorityNodeOpen {
		panic(fmt.Sprintf("violation of WriteScheduler interface: stream %d already closed", ))
	}

	 := .nodes[]
	.state = http2priorityNodeClosed
	.addBytes(-.bytes)

	 := .q
	.queuePool.put(&)
	.q.s = nil
	if .maxClosedNodesInTree > 0 {
		.addClosedOrIdleNode(&.closedNodes, .maxClosedNodesInTree, )
	} else {
		.removeNode()
	}
}

func ( *http2priorityWriteScheduler) ( uint32,  http2PriorityParam) {
	if  == 0 {
		panic("adjustPriority on root")
	}

	// If streamID does not exist, there are two cases:
	// - A closed stream that has been removed (this will have ID <= maxID)
	// - An idle stream that is being used for "grouping" (this will have ID > maxID)
	 := .nodes[]
	if  == nil {
		if  <= .maxID || .maxIdleNodesInTree == 0 {
			return
		}
		.maxID = 
		 = &http2priorityNode{
			q:      *.queuePool.get(),
			id:     ,
			weight: http2priorityDefaultWeight,
			state:  http2priorityNodeIdle,
		}
		.setParent(&.root)
		.nodes[] = 
		.addClosedOrIdleNode(&.idleNodes, .maxIdleNodesInTree, )
	}

	// Section 5.3.1: A dependency on a stream that is not currently in the tree
	// results in that stream being given a default priority (Section 5.3.5).
	 := .nodes[.StreamDep]
	if  == nil {
		.setParent(&.root)
		.weight = http2priorityDefaultWeight
		return
	}

	// Ignore if the client tries to make a node its own parent.
	if  ==  {
		return
	}

	// Section 5.3.3:
	//   "If a stream is made dependent on one of its own dependencies, the
	//   formerly dependent stream is first moved to be dependent on the
	//   reprioritized stream's previous parent. The moved dependency retains
	//   its weight."
	//
	// That is: if parent depends on n, move parent to depend on n.parent.
	for  := .parent;  != nil;  = .parent {
		if  ==  {
			.setParent(.parent)
			break
		}
	}

	// Section 5.3.3: The exclusive flag causes the stream to become the sole
	// dependency of its parent stream, causing other dependencies to become
	// dependent on the exclusive stream.
	if .Exclusive {
		 := .kids
		for  != nil {
			 := .next
			if  !=  {
				.setParent()
			}
			 = 
		}
	}

	.setParent()
	.weight = .Weight
}

func ( *http2priorityWriteScheduler) ( http2FrameWriteRequest) {
	var  *http2priorityNode
	if .isControl() {
		 = &.root
	} else {
		 := .StreamID()
		 = .nodes[]
		if  == nil {
			// id is an idle or closed stream. wr should not be a HEADERS or
			// DATA frame. In other case, we push wr onto the root, rather
			// than creating a new priorityNode.
			if .DataSize() > 0 {
				panic("add DATA on non-open stream")
			}
			 = &.root
		}
	}
	.q.push()
}

func ( *http2priorityWriteScheduler) () ( http2FrameWriteRequest,  bool) {
	.root.walkReadyInOrder(false, &.tmp, func( *http2priorityNode,  bool) bool {
		 := int32(math.MaxInt32)
		if  {
			 = .writeThrottleLimit
		}
		,  = .q.consume()
		if ! {
			return false
		}
		.addBytes(int64(.DataSize()))
		// If B depends on A and B continuously has data available but A
		// does not, gradually increase the throttling limit to allow B to
		// steal more and more bandwidth from A.
		if  {
			.writeThrottleLimit += 1024
			if .writeThrottleLimit < 0 {
				.writeThrottleLimit = math.MaxInt32
			}
		} else if .enableWriteThrottle {
			.writeThrottleLimit = 1024
		}
		return true
	})
	return , 
}

func ( *http2priorityWriteScheduler) ( *[]*http2priorityNode,  int,  *http2priorityNode) {
	if  == 0 {
		return
	}
	if len(*) ==  {
		// Remove the oldest node, then shift left.
		.removeNode((*)[0])
		 := (*)[1:]
		copy(*, )
		* = (*)[:len()]
	}
	* = append(*, )
}

func ( *http2priorityWriteScheduler) ( *http2priorityNode) {
	for .kids != nil {
		.kids.setParent(.parent)
	}
	.setParent(nil)
	delete(.nodes, .id)
}

// NewRandomWriteScheduler constructs a WriteScheduler that ignores HTTP/2
// priorities. Control frames like SETTINGS and PING are written before DATA
// frames, but if no control frames are queued and multiple streams have queued
// HEADERS or DATA frames, Pop selects a ready stream arbitrarily.
func http2NewRandomWriteScheduler() http2WriteScheduler {
	return &http2randomWriteScheduler{sq: make(map[uint32]*http2writeQueue)}
}

type http2randomWriteScheduler struct {
	// zero are frames not associated with a specific stream.
	zero http2writeQueue

	// sq contains the stream-specific queues, keyed by stream ID.
	// When a stream is idle, closed, or emptied, it's deleted
	// from the map.
	sq map[uint32]*http2writeQueue

	// pool of empty queues for reuse.
	queuePool http2writeQueuePool
}

func ( *http2randomWriteScheduler) ( uint32,  http2OpenStreamOptions) {
	// no-op: idle streams are not tracked
}

func ( *http2randomWriteScheduler) ( uint32) {
	,  := .sq[]
	if ! {
		return
	}
	delete(.sq, )
	.queuePool.put()
}

func ( *http2randomWriteScheduler) ( uint32,  http2PriorityParam) {
	// no-op: priorities are ignored
}

func ( *http2randomWriteScheduler) ( http2FrameWriteRequest) {
	if .isControl() {
		.zero.push()
		return
	}
	 := .StreamID()
	,  := .sq[]
	if ! {
		 = .queuePool.get()
		.sq[] = 
	}
	.push()
}

func ( *http2randomWriteScheduler) () (http2FrameWriteRequest, bool) {
	// Control and RST_STREAM frames first.
	if !.zero.empty() {
		return .zero.shift(), true
	}
	// Iterate over all non-idle streams until finding one that can be consumed.
	for ,  := range .sq {
		if ,  := .consume(math.MaxInt32);  {
			if .empty() {
				delete(.sq, )
				.queuePool.put()
			}
			return , true
		}
	}
	return http2FrameWriteRequest{}, false
}

type http2roundRobinWriteScheduler struct {
	// control contains control frames (SETTINGS, PING, etc.).
	control http2writeQueue

	// streams maps stream ID to a queue.
	streams map[uint32]*http2writeQueue

	// stream queues are stored in a circular linked list.
	// head is the next stream to write, or nil if there are no streams open.
	head *http2writeQueue

	// pool of empty queues for reuse.
	queuePool http2writeQueuePool
}

// newRoundRobinWriteScheduler constructs a new write scheduler.
// The round robin scheduler priorizes control frames
// like SETTINGS and PING over DATA frames.
// When there are no control frames to send, it performs a round-robin
// selection from the ready streams.
func http2newRoundRobinWriteScheduler() http2WriteScheduler {
	 := &http2roundRobinWriteScheduler{
		streams: make(map[uint32]*http2writeQueue),
	}
	return 
}

func ( *http2roundRobinWriteScheduler) ( uint32,  http2OpenStreamOptions) {
	if .streams[] != nil {
		panic(fmt.Errorf("stream %d already opened", ))
	}
	 := .queuePool.get()
	.streams[] = 
	if .head == nil {
		.head = 
		.next = 
		.prev = 
	} else {
		// Queues are stored in a ring.
		// Insert the new stream before ws.head, putting it at the end of the list.
		.prev = .head.prev
		.next = .head
		.prev.next = 
		.next.prev = 
	}
}

func ( *http2roundRobinWriteScheduler) ( uint32) {
	 := .streams[]
	if  == nil {
		return
	}
	if .next ==  {
		// This was the only open stream.
		.head = nil
	} else {
		.prev.next = .next
		.next.prev = .prev
		if .head ==  {
			.head = .next
		}
	}
	delete(.streams, )
	.queuePool.put()
}

func ( *http2roundRobinWriteScheduler) ( uint32,  http2PriorityParam) {}

func ( *http2roundRobinWriteScheduler) ( http2FrameWriteRequest) {
	if .isControl() {
		.control.push()
		return
	}
	 := .streams[.StreamID()]
	if  == nil {
		// This is a closed stream.
		// wr should not be a HEADERS or DATA frame.
		// We push the request onto the control queue.
		if .DataSize() > 0 {
			panic("add DATA on non-open stream")
		}
		.control.push()
		return
	}
	.push()
}

func ( *http2roundRobinWriteScheduler) () (http2FrameWriteRequest, bool) {
	// Control and RST_STREAM frames first.
	if !.control.empty() {
		return .control.shift(), true
	}
	if .head == nil {
		return http2FrameWriteRequest{}, false
	}
	 := .head
	for {
		if ,  := .consume(math.MaxInt32);  {
			.head = .next
			return , true
		}
		 = .next
		if  == .head {
			break
		}
	}
	return http2FrameWriteRequest{}, false
}