+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.

package http

import (
	
	
	
	
	
	
	
	
	
	
	
	
	
	mathrand 
	
	
	
	
	
	
	
	
	
	
	
	
	

	
	
	
)
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
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
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
Unassigned uint16 = 0x00C6-FE
Unassigned uint16 = 0x01-55,*
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
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 ( 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(req *Request, addr string) (*http2ClientConn, error)
	MarkDead(*http2ClientConn)
}
clientConnPoolIdleCloser is the interface implemented by ClientConnPool implementations which can close their idle connections.
TODO: use singleflight for dialing and addConnCalls?
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 addConnIfNeede calls
}

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

const (
	http2dialOnMiss   = true
	http2noDialOnMiss = false
)
shouldTraceGetConn reports whether getClientConn should call any ClientTrace.GetConn hook associated with the http.Request. This complexity is needed to avoid double calls of the GetConn hook during the back-and-forth between net/http and x/net/http2 (when the net/http.Transport is upgraded to also speak http2), as well as support the case where x/net/http2 is being used directly.
If our Transport wasn't made via ConfigureTransport, always trace the GetConn hook if provided, because that means the http2 package is being used directly and it's the one dialing, as opposed to net/http.
	if ,  := .t.ConnPool.(http2noDialClientConnPool); ! {
		return true
Otherwise, only use the GetConn hook if this connection has been used previously for other requests. For fresh connections, the net/http package does the dialing.
	return !.freshConn
}

func ( *http2clientConnPool) ( *Request,  string,  bool) (*http2ClientConn, error) {
It gets its own connection.
		http2traceGetConn(, )
		const  = true
		,  := .t.dialClientConn(, )
		if  != nil {
			return nil, 
		}
		return , nil
	}
	.mu.Lock()
	for ,  := range .conns[] {
		if  := .idleState(); .canTakeNewRequest {
			if .shouldTraceGetConn() {
				http2traceGetConn(, )
			}
			.mu.Unlock()
			return , nil
		}
	}
	if ! {
		.mu.Unlock()
		return nil, http2ErrNoCachedConn
	}
	http2traceGetConn(, )
	 := .getStartDialLocked()
	.mu.Unlock()
	<-.done
	return .res, .err
}
dialCall is an in-flight Transport dial call to a host.
type http2dialCall struct {
	_    http2incomparable
	p    *http2clientConnPool
	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.
A dial is already in-flight. Don't start another.
		return 
	}
	 := &http2dialCall{p: , done: make(chan struct{})}
	if .dialing == nil {
		.dialing = make(map[string]*http2dialCall)
	}
	.dialing[] = 
	go .dial()
	return 
}
run in its own goroutine.
func ( *http2dialCall) ( string) {
	const  = false // shared conn
	.res, .err = .p.t.dialClientConn(, )
	close(.done)

	.p.mu.Lock()
	delete(.p.dialing, )
	if .err == nil {
		.p.addConnLocked(, .res)
	}
	.p.mu.Unlock()
}
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,  *tls.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,  *tls.Conn) {
	,  := .NewClientConn()

	 := .p
	.mu.Lock()
	if  != nil {
		.err = 
	} else {
		.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()
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 ( []*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.
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 (
	http2dataChunkSizeClasses = []int{
		1 << 10,
		2 << 10,
		4 << 10,
		8 << 10,
		16 << 10,
	}
	http2dataChunkPools = [...]sync.Pool{
		{New: func() interface{} { return make([]byte, 1<<10) }},
		{New: func() interface{} { return make([]byte, 2<<10) }},
		{New: func() interface{} { return make([]byte, 4<<10) }},
		{New: func() interface{} { return make([]byte, 8<<10) }},
		{New: func() interface{} { return make([]byte, 16<<10) }},
	}
)

func ( int64) []byte {
	 := 0
	for ;  < len(http2dataChunkSizeClasses)-1; ++ {
		if  <= int64(http2dataChunkSizeClasses[]) {
			break
		}
	}
	return http2dataChunkPools[].Get().([]byte)
}

func ( []byte) {
	for ,  := range http2dataChunkSizeClasses {
		if len() ==  {
			http2dataChunkPools[].Put()
			return
		}
	}
	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 += 
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()
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.
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
}

func ( 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 %q", string())
}

var (
	http2errMixPseudoHeaderTypes = errors.New("mix of request and response pseudo headers")
	http2errPseudoAfterRegular   = errors.New("pseudo header field after regular")
)
flow is the flow control window's size.
type http2flow struct {
	_ http2incomparable
n is the number of DATA bytes we're allowed to send. A flow is kept both on a conn and a per-stream.
conn points to the shared connection-level flow that is shared by all streams on that conn. It is nil for the flow that's on the conn directly.
	conn *http2flow
}

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

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

func ( *http2flow) ( 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 ( *http2flow) ( 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 http://http2.github.io/http2-spec/#rfc.section.11.2
Flags is a bitmask of HTTP/2 flags. The meaning of flags varies depending on the frame type.
Has reports whether f contains all (0 or more) flags in v.
func ( http2Flags) ( http2Flags) bool {
	return ( & ) == 
}
Frame-specific FrameHeader flag bits.
Settings Frame
Ping Frame
A FrameHeader is the 9 byte header of all HTTP/2 frames. See http://http2.github.io/http2-spec/#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).
Flags are the 1 byte of 8 potential bit flags per frame. They are specific to the frame type.
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.
StreamID is which stream this frame is for. Certain frames are not stream-specific, in which case this field is 0.
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 ( io.Reader) (http2FrameHeader, error) {
	 := http2fhBytes.Get().(*[]byte)
	defer http2fhBytes.Put()
	return http2readFrameHeader(*, )
}

func ( []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.
lastHeaderStream is non-zero if the last frame was an unfinished HEADERS/CONTINUATION.
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.
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.
ReadMetaHeaders if non-nil causes ReadFrame to merge HEADERS and CONTINUATION frames together and return MetaHeadersFrame instead.
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.
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
}

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

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)
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.
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.
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 ( 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.
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, , )
	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 http://http2.github.io/http2-spec/#rfc.section.6.1
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 ( *http2frameCache,  http2FrameHeader,  []byte) (http2Frame, error) {
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.
		return nil, http2connError{http2ErrCodeProtocol, "DATA frame with stream ID 0"}
	}
	 := .getDataFrame()
	.http2FrameHeader = 

	var  byte
	if .Flags.Has(http2FlagDataPadded) {
		var  error
		, ,  = http2readByte()
		if  != nil {
			return nil, 
		}
	}
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
		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 ( uint32) bool {
	return &(1<<31) == 0
}

func ( 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 !http2validStreamID() && !.AllowIllegalWrites {
		return http2errStreamID
	}
	if len() > 0 {
		if len() > 255 {
			return http2errPadLength
		}
		if !.AllowIllegalWrites {
			for ,  := range  {
"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 .endWrite()
}
A SettingsFrame conveys configuration parameters that affect how endpoints communicate, such as preferences and constraints on peer behavior. See http://http2.github.io/http2-spec/#SETTINGS
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.
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.
Expecting even number of 6 byte settings.
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.
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 http://http2.github.io/http2-spec/#rfc.section.6.7
type http2PingFrame struct {
	http2FrameHeader
	Data [8]byte
}

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

func ( *http2frameCache,  http2FrameHeader,  []byte) (http2Frame, error) {
	if len() != 8 {
		return nil, http2ConnectionError(http2ErrCodeFrameSize)
	}
	if .StreamID != 0 {
		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 http://http2.github.io/http2-spec/#rfc.section.6.8
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 ( *http2frameCache,  http2FrameHeader,  []byte) (http2Frame, error) {
	if .StreamID != 0 {
		return nil, http2ConnectionError(http2ErrCodeProtocol)
	}
	if len() < 8 {
		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.
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.
A WindowUpdateFrame is used to implement flow control. See http://http2.github.io/http2-spec/#rfc.section.6.9
type http2WindowUpdateFrame struct {
	http2FrameHeader
	Increment uint32 // never read with high bit set
}

func ( *http2frameCache,  http2FrameHeader,  []byte) (http2Frame, error) {
	if len() != 4 {
		return nil, http2ConnectionError(http2ErrCodeFrameSize)
	}
	 := binary.BigEndian.Uint32([:4]) & 0x7fffffff // mask off high reserved bit
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).
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.
"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.
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.
		return nil, http2connError{http2ErrCodeProtocol, "HEADERS frame with stream ID 0"}
	}
	var  uint8
	if .Flags.Has(http2FlagHeadersPadded) {
		if , ,  = http2readByte();  != nil {
			return
		}
	}
	if .Flags.Has(http2FlagHeadersPriority) {
		var  uint32
		, ,  = http2readUint32()
		if  != nil {
			return nil, 
		}
		.Priority.StreamDep =  & 0x7fffffff
		.Priority.Exclusive = ( != .Priority.StreamDep) // high bit was set
		, .Priority.Weight,  = http2readByte()
		if  != nil {
			return nil, 
		}
	}
	if len()-int() <= 0 {
		return nil, http2streamError(.StreamID, http2ErrCodeProtocol)
	}
	.headerFragBuf = [:len()-int()]
	return , nil
}
HeadersFrameParam are the parameters for writing a HEADERS frame.
StreamID is the required Stream ID to initiate.
BlockFragment is part (or all) of a Header Block.
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.
EndHeaders indicates that this frame contains an entire header block and is not followed by any CONTINUATION frames.
PadLength is the optional number of bytes of zeros to add to this frame.
Priority, if non-zero, includes stream priority information in the HEADER frame.
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.
A PriorityFrame specifies the sender-advised priority of a stream. See http://http2.github.io/http2-spec/#rfc.section.6.3
PriorityParam are the stream prioritzation parameters.
StreamDep is a 31-bit stream identifier for the stream that this stream depends on. Zero means no dependency.
Exclusive is whether the dependency is exclusive.
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 ( *http2frameCache,  http2FrameHeader,  []byte) (http2Frame, error) {
	if .StreamID == 0 {
		return nil, http2connError{http2ErrCodeProtocol, "PRIORITY frame with stream ID 0"}
	}
	if len() != 5 {
		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 http://http2.github.io/http2-spec/#rfc.section.6.4
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 http://http2.github.io/http2-spec/#rfc.section.6.10
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 http://http2.github.io/http2-spec/#rfc.section.6.6
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.
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 {
			return
		}
	}

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

like the DATA frame, error out if padding is longer than the body.
		return nil, http2ConnectionError(http2ErrCodeProtocol)
	}
	.headerFragBuf = [:len()-int()]
	return , nil
}
PushPromiseParam are the parameters for writing a PUSH_PROMISE frame.
StreamID is the required Stream ID to initiate.
PromiseID is the required Stream ID which this Push Promises
BlockFragment is part (or all) of a Header Block.
EndHeaders indicates that this frame contains an entire header block and is not followed by any CONTINUATION frames.
PadLength is the optional number of bytes of zeros to add to this frame.
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.
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 ( []byte) ( []byte,  byte,  error) {
	if len() == 0 {
		return nil, 0, io.ErrUnexpectedEOF
	}
	return [1:], [0], nil
}

func ( []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.
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.
Truncated is whether the max header list size limit was hit and Fields is incomplete. The hpack decoder state is still valid, however.
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":
			 = true
		case ":status":
			 = true
		default:
			return http2pseudoHeaderError(.Name)
Check for duplicates. This would be a bad algorithm, but N is 4. And this doesn't allocate.
		for ,  := range [:] {
			if .Name == .Name {
				return http2duplicatePseudoHeaderError(.Name)
			}
		}
	}
	if  &&  {
		return http2errMixPseudoHeaderTypes
	}
	return nil
}

func ( *http2Framer) () int {
	 := .maxHeaderListSize()
	if uint32(int()) ==  {
		return int()
They had a crazy big number for MaxHeaderBytes anyway, so give them unlimited header lengths:
	return 0
}
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) (*http2MetaHeadersFrame, 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) {
			 = http2headerFieldValueError(.Value)
		}
		 := strings.HasPrefix(.Name, ":")
		if  {
			if  {
				 = http2errPseudoAfterRegular
			}
		} else {
			 = true
			if !http2validWireHeaderFieldName(.Name) {
				 = http2headerFieldNameError(.Name)
			}
		}

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

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

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

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

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

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

	if  := .Close();  != nil {
		return nil, 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 ( 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()
}

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

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

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

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

type http2goroutineLock uint64

func () 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 () uint64 {
	 := http2littleBuf.Get().(*[]byte)
	defer http2littleBuf.Put()
	 := *
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 ( []byte,  int,  int) ( uint64,  error) {
	var ,  uint64

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

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

valid base; nothing to do

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 
		}

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

		 :=  + uint64()
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 ( 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 () {
	http2commonBuildOnce.Do(http2buildCommonHeaderMaps)
}

func () {
	 := []string{
		"accept",
		"accept-charset",
		"accept-encoding",
		"accept-language",
		"accept-ranges",
		"age",
		"access-control-allow-origin",
		"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",
		"proxy-authenticate",
		"proxy-authorization",
		"range",
		"referer",
		"refresh",
		"retry-after",
		"server",
		"set-cookie",
		"strict-transport-security",
		"trailer",
		"transfer-encoding",
		"user-agent",
		"vary",
		"via",
		"www-authenticate",
	}
	http2commonLowerHeader = make(map[string]string, len())
	http2commonCanonHeader = make(map[string]string, len())
	for ,  := range  {
		 := CanonicalHeaderKey()
		http2commonLowerHeader[] = 
		http2commonCanonHeader[] = 
	}
}

func ( string) string {
	http2buildCommonHeaderMapsOnce()
	if ,  := http2commonLowerHeader[];  {
		return 
	}
	return strings.ToLower()
}

var (
	http2VerboseLogs    bool
	http2logFrameWrites bool
	http2logFrameReads  bool
	http2inTests        bool
)

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

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 http://http2.github.io/http2-spec/#rfc.section.6.5.2
NextProtoTLS is the NPN/ALPN protocol negotiated during HTTP/2's TLS setup.
http://http2.github.io/http2-spec/#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.
Setting is a setting parameter: which setting it is, and its value.
ID is which setting is being set. See http://http2.github.io/http2-spec/#SettingValues
Val is the value.
	Val uint32
}

func ( http2Setting) () string {
	return fmt.Sprintf("[%v = %d]", .ID, .Val)
}
Valid reports whether the setting is valid.
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)
		}
	}
	return nil
}
A SettingID is an HTTP/2 setting as defined in http://http2.github.io/http2-spec/#iana-settings
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 ( string) bool {
	if len() == 0 {
		return false
	}
	for ,  := range  {
		if !httpguts.IsTokenRune() {
			return false
		}
		if 'A' <=  &&  <= 'Z' {
			return false
		}
	}
	return true
}

func ( 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 gate lets two goroutines coordinate their activities.
type http2gate chan struct{}

func ( http2gate) () {  <- struct{}{} }

func ( http2gate) () { <- }
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
	w  io.Writer     // immutable
	bw *bufio.Writer // non-nil when data is buffered
}

func ( io.Writer) *http2bufferedWriter {
	return &http2bufferedWriter{w: }
}
bufWriterPoolBufferSize is the size of bufio.Writer's buffers created using bufWriterPool. TODO: pick a less arbitrary value? this is a bit under (3 x typical 1500 byte MTU) at least. Other than that, not much thought went into it.
const 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(.w)
		.bw = 
	}
	return .bw.Write()
}

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

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

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

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")
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 {
		return 0, http2errClosedPipeWrite
	}
	if .breakErr != nil {
		.unread += len()
		return len(), nil // discard when there is no reader
	}
	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()
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{})
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?
	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.
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
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.
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.
PermitProhibitedCipherSuites, if true, permits the use of cipher suites prohibited by the HTTP/2 spec.
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.
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.
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.
NewWriteScheduler constructs a write scheduler for a connection. If nil, a default scheduler is chosen.
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.
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.
TODO: if anybody asks, add a Server field, and remember to define the behavior of negative values.
	return http2maxQueuedControlFrames
}

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 ( *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)
If they already provided a CipherSuite list, return an error if it has a bad order or is missing ECDHE_RSA_WITH_AES_128_GCM_SHA256 or ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
		 := false
		 := false
		for ,  := range .TLSConfig.CipherSuites {
			switch  {
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 http2isBadCipher() {
				 = true
			} else if  {
				return fmt.Errorf("http2: TLSConfig.CipherSuites index %d contains an HTTP/2-approved cipher suite (%#04x), but it comes after unapproved cipher suites. With this configuration, clients that don't support previous, approved cipher suites may be given an unapproved one and reject the connection.", , )
			}
		}
		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

	 := false
	for ,  := range .TLSConfig.NextProtos {
		if  == http2NextProtoTLS {
			 = true
			break
		}
	}
	if ! {
		.TLSConfig.NextProtos = append(.TLSConfig.NextProtos, http2NextProtoTLS)
	}

	if .TLSNextProto == nil {
		.TLSNextProto = map[string]func(*Server, *tls.Conn, Handler){}
	}
	 := func( *Server,  *tls.Conn,  Handler) {
		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: ,
		})
	}
	.TLSNextProto[http2NextProtoTLS] = 
	return nil
}
ServeConnOpts are options for the Server.ServeConn method.
Context is the base context to use. If nil, context.Background is used.
BaseConfig optionally sets the base configuration for values. If nil, defaults are used.
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
}

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) {
	,  := http2serverConnBaseContext(, )
	defer ()

	 := &http2serverConn{
		srv:                         ,
		hs:                          .baseConfig(),
		conn:                        ,
		baseCtx:                     ,
		remoteAddrStr:               .RemoteAddr().String(),
		bw:                          http2newBufferedWriter(),
		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,
		maxFrameSize:                http2initialMaxFrameSize,
		headerTableSize:             http2initialHeaderTableSize,
		serveG:                      http2newGoroutineLock(),
		pushEnabled:                 true,
	}

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

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

"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  := http2testHookGetServerConn;  != nil {
		()
	}
	.serve()
}

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

func ( *http2serverConn) ( http2ErrCode,  string) {
ignoring errors. hanging up anyway.
	.framer.WriteGoAway(0, , []byte())
	.bw.Flush()
	.conn.Close()
}

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             http2flow                   // conn-wide (not stream-specific) outbound flow control
	inflow           http2flow                   // conn-wide inbound flow control
	tlsState         *tls.ConnectionState        // shared by all handlers, like net/http
	remoteAddrStr    string
	writeSched       http2WriteScheduler
Everything following is owned by the serve loop; use serveG.check():
	serveG                      http2goroutineLock // used to verify funcs are on serve()
	pushEnabled                 bool
	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
	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
	initialStreamSendWindowSize int32
	maxFrameSize                int32
	headerTableSize             uint32
	peerMaxHeaderListSize       uint32            // zero means unknown (default)
	canonHeader                 map[string]string // http2-lower-case -> Go-Canonical-Case
	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
	goAwayCode                  http2ErrCode
	shutdownTimer               *time.Timer // nil until used
	idleTimer                   *time.Timer // nil if unused
Owned by the writeFrameAsync goroutine:
Used by startGracefulShutdown.
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 uint32( + *)
}

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.
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             http2flow // limits writing from Handler to client
	inflow           http2flow // 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)
	writeDeadline    *time.Timer // nil if unused

	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) {
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 ( 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 ( error) bool {
	if  == nil {
		return false
	}
TODO: remove this string search and be more like the Windows case below. That might involve modifying the standard library to return better error types.
	 := .Error()
	if strings.Contains(, "use of closed network connection") {
		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
	}
Boring, expected errors.
		.vlogf(, ...)
	} else {
		.logf(, ...)
	}
}

func ( *http2serverConn) ( string) string {
	.serveG.check()
	http2buildCommonHeaderMapsOnce()
	,  := http2commonCanonHeader[]
	if  {
		return 
	}
	,  = .canonHeader[]
	if  {
		return 
	}
	if .canonHeader == nil {
		.canonHeader = make(map[string]string)
	}
	 = CanonicalHeaderKey()
	.canonHeader[] = 
	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) () {
	 := make(http2gate)
	 := .Done
	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) {
	 := .write.writeFrame()
	.wroteFrameCh <- http2frameWriteResult{wr: , err: }
}

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

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

Note: this is for serverConn.serve panicking, not http.Handler code.
Each connection starts with intialWindowSize inflow tokens. If a higher value is configured, we add more tokens.
	if  := .srv.initialConnRecvWindowSize() - 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 = time.AfterFunc(.srv.IdleTimeout, .onIdleTimer)
		defer .idleTimer.Stop()
	}

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

	 := time.AfterFunc(http2firstSettingsTimeout, .onSettingsTimer)
	defer .Stop()

	 := 0
	for {
		++
		select {
		case  := <-.wantWriteFrameCh:
			if ,  := .write.(http2StreamError);  {
				.resetStream()
				break
			}
			.writeFrame()
		case  := <-.wroteFrameCh:
			.wroteFrame()
		case  := <-.readFrameCh:
			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 http2shutdownTimerMsg:
					.vlogf("GOAWAY close timer fired; closing conn from %v", .conn.RemoteAddr())
					return
				case http2gracefulShutdownMsg:
					.startGracefulShutdownInternal()
				default:
					panic("unknown timer")
				}
			case *http2startPushRequest:
				.startPush()
			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 > .srv.maxQueuedControlFrames() {
			.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) ( <-chan struct{},  chan struct{}) {
	select {
	case <-.doneServing:
	case <-:
		close()
	}
}

type http2serverMessage int
readPreface reads the ClientPreface greeting from the peer or returns errPrefaceTimeout on timeout, or an error if the greeting is invalid.
func ( *http2serverConn) () error {
	 := make(chan error, 1)
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
		}
	}()
	 := time.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
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.
Serve loop is gone. Client has closed their connection to the server.
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.
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.
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() {
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) {
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 {
		.writingFrameAsync = true
		go .writeFrameAsync()
	}
}
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

	 := .wr

	if http2writeEndsStream(.write) {
		 := .stream
		if  == nil {
			panic("internal error: expecting non-nil stream")
		}
		switch .state {
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.
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.
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.
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.
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.
After sending GOAWAY, 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?
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()
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:
		.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 http2ConnectionError(http2ErrCodeProtocol)
		}
		.sawFirstSettings = true
	}

	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()
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 http2ConnectionError(http2ErrCodeProtocol)
	default:
		.vlogf("http2: server ignoring frame: %v", .Header())
		return nil
	}
}

func ( *http2serverConn) ( *http2PingFrame) error {
	.serveG.check()
6.7 PING: " An endpoint MUST NOT respond to PING frames containing this flag."
		return nil
	}
"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 http2ConnectionError(http2ErrCodeProtocol)
	}
	if .inGoAway && .goAwayCode != http2ErrCodeNo {
		return nil
	}
	.writeFrame(http2FrameWriteRequest{write: http2writePingAck{}})
	return nil
}

func ( *http2serverConn) ( *http2WindowUpdateFrame) error {
	.serveG.check()
	switch {
	case .StreamID != 0: // stream-level flow control
		,  := .state(.StreamID)
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."
"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 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)
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 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 .writeDeadline != nil {
		.writeDeadline.Stop()
	}
	if .isPushed() {
		.curPushedStreams--
	} else {
		.curClientStreams--
	}
	delete(.streams, .id)
	if len(.streams) == 0 {
		.setConnState(StateIdle)
		if .srv.IdleTimeout != 0 {
			.idleTimer.Reset(.srv.IdleTimeout)
		}
		if http2h1ServerKeepAlivesDisabled(.hs) {
			.startGracefulShutdownInternal()
		}
	}
Return any buffered unread bytes worth of conn-level flow control. See golang.org/issue/16481
		.sendWindowUpdate(nil, .Len())

		.CloseWithError()
	}
	.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc
	.writeSched.CloseStream(.id)
}

func ( *http2serverConn) ( *http2SettingsFrame) error {
	.serveG.check()
	if .IsAck() {
		.unackedSettings--
Why is the peer ACKing settings we never sent? The spec doesn't mention this case, but hang up on them anyway.
This isn't actually in the spec, but hang up on suspiciously large settings frames or those with duplicate entries.
		return 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:
		.headerTableSize = .Val
		.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
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 {
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 {
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 http2ConnectionError(http2ErrCodeFlowControl)
		}
	}
	return nil
}

func ( *http2serverConn) ( *http2DataFrame) error {
	.serveG.check()
	if .inGoAway && .goAwayCode != http2ErrCodeNo {
		return nil
	}
	 := .Data()
"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."
	 := .Header().StreamID
	,  := .state()
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."
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.
Deduct the flow control from inflow, since we're going to immediately add it back in sendWindowUpdate, which also schedules sending the frames.
		.inflow.take(int32(.Length))
		.sendWindowUpdate(nil, int(.Length)) // conn-level

Already have a stream error in flight. Don't send another.
			return nil
		}
		return 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 {
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.
Check whether the client has flow control quota.
		if .inflow.available() < int32(.Length) {
			return http2streamError(, http2ErrCodeFlowControl)
		}
		.inflow.take(int32(.Length))

		if len() > 0 {
			,  := .body.Write()
			if  != nil {
				.sendWindowUpdate(nil, int(.Length)-)
				return http2streamError(, http2ErrCodeStreamClosed)
			}
			if  != len() {
				panic("internal error: bad Writer")
			}
			.bodyBytes += int64(len())
		}
Return any padded flow control now, since we won't refund it later on body reads.
		if  := int32(.Length) - int32(len());  > 0 {
			.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", )
	}
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 {
Only copy it over it was pre-declared.
			.reqTrailer[] = 
		}
	}
}
onWriteTimeout is run on its own goroutine (from time.AfterFunc) when the stream's WriteTimeout has fired.
Ignore.
		return nil
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.
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 {
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.
[...] 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.
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.
They should know better.
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 http2streamError(, http2ErrCodeRefusedStream)
	}

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

	if .HasPriority() {
		if  := http2checkPriority(.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
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{})
	}

	go .runHandler(, , )
	return nil
}

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

	if len(.PseudoFields()) > 0 {
		return http2streamError(.id, http2ErrCodeProtocol)
	}
	if .trailer != nil {
		for ,  := range .RegularFields() {
			 := .canonicalHeader(.Name)
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 http2streamError(.id, http2ErrCodeProtocol)
			}
			.trailer[] = append(.trailer[], .Value)
		}
	}
	.endStream()
	return nil
}

func ( uint32,  http2PriorityParam) error {
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 http2streamError(, http2ErrCodeProtocol)
	}
	return nil
}

func ( *http2serverConn) ( *http2PriorityFrame) error {
	if .inGoAway {
		return nil
	}
	if  := http2checkPriority(.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.conn = &.inflow // link to conn-level counter
	.inflow.add(.srv.initialStreamRecvWindowSize())
	if .hs.WriteTimeout != 0 {
		.writeDeadline = time.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"),
	}

	 := .method == "CONNECT"
	if  {
		if .path != "" || .scheme != "" || .authority == "" {
			return nil, nil, http2streamError(.StreamID, http2ErrCodeProtocol)
		}
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"
HEAD requests can't have bodies
		return nil, nil, http2streamError(.StreamID, http2ErrCodeProtocol)
	}

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

	, ,  := .newWriterAndRequestNoBody(, )
	if  != nil {
		return nil, nil, 
	}
	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
	header                  Header
}

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

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

	 := .header.Get("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  {
Bogus. (copy of http1 rules) Ignore.
			default:
				if  == nil {
					 = make(Header)
				}
				[] = nil
			}
		}
	}
	delete(.header, "Trailer")

	var  *url.URL
	var  string
	if .method == "CONNECT" {
		 = &url.URL{Host: .authority}
		 = .authority // mimic HTTP/1 server behavior
	} else {
		var  error
		,  = url.ParseRequestURI(.path)
		if  != nil {
			return nil, nil, 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)

	 := http2responseWriterStatePool.Get().(*http2responseWriterState)
	 := .bw
	* = http2responseWriterState{} // zero all the fields
	.conn = 
	.bw = 
	.bw.Reset(http2chunkWriter{})
	.stream = 
	.req = 
	.body = 

	 := &http2responseWriter{rws: }
	return , , nil
}
Run on its own goroutine.
func ( *http2serverConn) ( *http2responseWriter,  *Request,  func(ResponseWriter, *Request)) {
	 := true
	defer func() {
		.rws.stream.cancelCtx()
		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
}

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 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
}
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
Don't send this WINDOW_UPDATE if the stream is closed remotely.
		.sendWindowUpdate(, )
	}
}
st may be nil for conn-level
"The legal range for the increment to the flow control window is 1 to 2^31-1 (2,147,483,647) octets." A Go Read call on 64-bit machines could in theory read a larger Read than this. Very unlikely, but we handle it here rather than elsewhere for now.
	const  = 1<<31 - 1
	for  >=  {
		.sendWindowUpdate32(, )
		 -= 
	}
	.sendWindowUpdate32(, int32())
}
st may be nil for conn-level
func ( *http2serverConn) ( *http2stream,  int32) {
	.serveG.check()
	if  == 0 {
		return
	}
	if  < 0 {
		panic("negative update")
	}
	var  uint32
	if  != nil {
		 = .id
	}
	.writeFrame(http2FrameWriteRequest{
		write:  http2writeWindowUpdate{streamID: , n: uint32()},
		stream: ,
	})
	var  bool
	if  == nil {
		 = .inflow.add()
	} else {
		 = .inflow.add()
	}
	if ! {
		panic("internal error; sent too many window updates without decrements?")
	}
}
requestBody is the Handler's Request.Body type. Read and Close may be called concurrently.
type http2requestBody struct {
	_             http2incomparable
	stream        *http2stream
	conn          *http2serverConn
	closed        bool       // for use by Close only
	sawEOF        bool       // for use by Read only
	pipe          *http2pipe // non-nil if we have a HTTP entity message body
	needsContinue bool       // need to send a 100-continue
}

func ( *http2requestBody) () error {
	if .pipe != nil && !.closed {
		.pipe.BreakWithError(http2errClosedBody)
	}
	.closed = true
	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.
Optional http.ResponseWriter interfaces implemented.
immutable within a request:
	stream *http2stream
	req    *Request
	body   *http2requestBody // to close at end of request, if DATA frames didn't
	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
	dirty         bool     // a Write failed; don't reuse this responseWriterState

	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) { return .rws.writeChunk() }

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

	 := .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 {
				 = ""
			}
		}
		if  == "" && .handlerDone && http2bodyAllowedForStatus(.status) && (len() > 0 || !) {
			 = strconv.Itoa(len())
		}
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
TODO(bradfitz): be faster here, like net/http? measure.
			 = time.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 {
			.dirty = true
			return 0, 
		}
		if  {
			return 0, nil
		}
	}
	if  {
		return len(), nil
	}
	if len() == 0 && !.handlerDone {
		return 0, nil
	}

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

	if .handlerDone &&  {
		 = .conn.writeHeaders(.stream, &http2writeResHeaders{
			streamID:  .stream.id,
			h:         .handlerHeader,
			trailers:  .trailers,
			endStream: true,
		})
		if  != nil {
			.dirty = 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) () {
	 := .rws
	if  == nil {
		panic("Header called after Handler finished")
	}
	if .bw.Buffered() > 0 {
Ignore the error. The frame writer already knows.
			return
		}
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.
		.writeChunk(nil)
	}
}

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.
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) and we might block under 200 (once we have more mature 1xx support). 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 {
		http2checkWriteHeaderCode()
		.wroteHeader = true
		.status = 
		if len(.handlerHeader) > 0 {
			.snapHeader = http2cloneHeader(.handlerHeader)
		}
	}
}

func ( 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
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
	 := .dirty
	.handlerDone = true
	.Flush()
	.rws = nil
Only recycle the pool if all prior Write calls to the serverConn goroutine completed successfully. If they returned earlier due to resets from the peer there might still be write goroutines outstanding from the serverConn referencing the rws memory. See issue 20704.
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.
		switch strings.ToLower() {
		case "content-length", "content-encoding", "trailer", "te", "expect", "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.
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.
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.
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
		})
Should not happen, since we've already validated msg.url.
			panic(fmt.Sprintf("newWriterAndRequestNoBody(%+v): %v", .url, ))
		}

		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 ( 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 ( 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 ( 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 ( *Server) bool {
	var  interface{} = 
	type  interface {
		() bool
	}
	if ,  := .();  {
		return !.()
	}
	return false
}

transportDefaultConnFlow is how many connection-level flow control tokens we give the server at start-up, past the default 64k.
transportDefaultStreamFlow is how many stream-level flow control tokens we announce to the peer, and how many bytes we buffer per stream.
transportDefaultStreamMinRefresh is the minimum number of bytes we'll send a stream-level WINDOW_UPDATE for at a time.
Transport is an HTTP/2 Transport. A Transport internally caches connections to servers. It is safe for concurrent use by multiple goroutines.
DialTLS specifies an optional dial function for creating TLS connections for requests. If 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.
	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.
ConnPool optionally specifies an alternate connection pool to use. If nil, the default is used.
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.
AllowHTTP, if true, permits HTTP/2 requests using the insecure, plain-text "http" scheme. Note that this does not enable h2c support.
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.
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.
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.
PingTimeout is the timeout after which the connection will be closed if a response to Ping is not received. Defaults to 15s.
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
}

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

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

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

}
ConfigureTransport configures a net/http HTTP/1 Transport to use HTTP/2. It returns an error if t1 has already been HTTP/2-enabled. Use ConfigureTransports instead to configure the HTTP/2 Transport.
func ( *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 ( *Transport) (*http2Transport, error) {
	return http2configureTransports()
}

func ( *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,  *tls.Conn) RoundTripper {
		 := http2authorityAddr("https", )
		if ,  := .addConnIfNeeded(, , );  != nil {
			go .Close()
			return http2erringRoundTripper{}
Turns out we don't need this c. For example, two goroutines made requests to the same host at the same time, both kicking off TCP dials. (since protocol was unknown)
			go .Close()
		}
		return 
	}
	if  := .TLSNextProto; len() == 0 {
		.TLSNextProto = map[string]func(string, *tls.Conn) RoundTripper{
			"h2": ,
		}
	} else {
		["h2"] = 
	}
	return , nil
}

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
	reused    uint32               // whether conn is being reused; atomic
	singleUse bool                 // whether being used for a single http.Request
readLoop goroutine fields:
	readerDone chan struct{} // closed on error
	readerErr  error         // set before readerDone is closed

	idleTimeout time.Duration // or 0 for never
	idleTimer   *time.Timer

	mu              sync.Mutex // guards following
	cond            *sync.Cond // hold mu; broadcast on flow/closed changes
	flow            http2flow  // our conn-level flow control quota (cs.flow is per stream)
	inflow          http2flow  // peer's conn-level flow control
	closing         bool
	closed          bool
	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
	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
	bw              *bufio.Writer
	br              *bufio.Reader
	fr              *http2Framer
	lastActive      time.Time
Settings from peer: (also guarded by mu)
	maxFrameSize          uint32
	maxConcurrentStreams  uint32
	peerMaxHeaderListSize uint64
	initialWindowSize     uint32

	hbuf    bytes.Buffer // HPACK encoder writes into this
	henc    *hpack.Encoder
	freeBuf [][]byte

	wmu  sync.Mutex // held while writing; acquire AFTER mu if holding both
	werr error      // first write error that has occurred
}
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
	req           *Request
	trace         *httptrace.ClientTrace // or nil
	ID            uint32
	resc          chan http2resAndError
	bufPipe       http2pipe // buffered pipe with the flow-controlled response payload
	startedWrite  bool      // started request body write; guarded by cc.mu
	requestedGzip bool
	on100         func() // optional code to run if get a 100 continue response

	flow        http2flow // guarded by cc.mu
	inflow      http2flow // guarded by cc.mu
	bytesRemain int64     // -1 means unknown; owned by transportResponseBody.Read
	readErr     error     // sticky read error; owned by transportResponseBody.Read
	stopReqBody error     // if non-nil, stop writing req body; guarded by cc.mu
	didReset    bool      // whether we sent a RST_STREAM to the server; guarded by cc.mu

	peerReset chan struct{} // closed on peer reset
	resetErr  error         // populated before peerReset is closed

	done chan struct{} // closed when stream remove from cc.streams map; close calls guarded by cc.mu
owned by clientConnReadLoop:
	firstByte    bool  // got the first response byte
	pastHeaders  bool  // got first MetaHeadersFrame (actual headers)
	pastTrailers bool  // got optional second MetaHeadersFrame (trailers)
	num1xx       uint8 // number of 1xx responses seen

	trailer    Header  // accumulated trailers
	resTrailer *Header // client's Response.Trailer
}
awaitRequestCancel waits for the user to cancel a request or for the done channel to be signaled. A non-nil error is returned only if the request was canceled.
func ( *Request,  <-chan struct{}) error {
	 := .Context()
	if .Cancel == nil && .Done() == nil {
		return nil
	}
	select {
	case <-.Cancel:
		return http2errRequestCanceled
	case <-.Done():
		return .Err()
	case <-:
		return nil
	}
}

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.
awaitRequestCancel waits for the user to cancel a request, its context to expire, or for the request to be done (any way it might be removed from the cc.streams map: peer reset, successful completion, TCP connection breakage, etc). If the request is canceled, then cs will be canceled and closed.
func ( *http2clientStream) ( *Request) {
	if  := http2awaitRequestCancel(, .done);  != nil {
		.cancelStream()
		.bufPipe.CloseWithError()
	}
}

func ( *http2clientStream) () {
	 := .cc
	.mu.Lock()
	 := .didReset
	.didReset = true
	.mu.Unlock()

	if ! {
		.writeStreamReset(.ID, http2ErrCodeCancel, nil)
		.forgetStreamID(.ID)
	}
}
checkResetOrDone reports any error sent in a RST_STREAM frame by the server, or errStreamClosed if the stream is complete.
func ( *http2clientStream) () error {
	select {
	case <-.peerReset:
		return .resetErr
	case <-.done:
		return http2errStreamClosed
	default:
		return nil
	}
}

func ( *http2clientStream) () bool {
	 := .cc
	.mu.Lock()
	defer .mu.Unlock()
	return .startedWrite
}

func ( *http2clientStream) ( error) {
	if  == nil {
		panic("nil error")
	}
	 := .cc
	.mu.Lock()
	.stopReqBody = 
	.cond.Broadcast()
	.mu.Unlock()
}

type http2stickyErrWriter struct {
	w   io.Writer
	err *error
}

func ( http2stickyErrWriter) ( []byte) ( int,  error) {
	if *.err != nil {
		return 0, *.err
	}
	,  = .w.Write()
	*.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 ( error) bool {
	,  := .(interface{ () })
	return 
}

var http2ErrNoCachedConn error = http2noCachedConnError{}
RoundTripOpt are options for the Transport.RoundTripOpt method.
OnlyCachedConn controls whether RoundTripOpt may create a new TCP connection. If set true and no cached connection is available, RoundTripOpt will return ErrNoCachedConn.
authorityAddr returns a given authority (a host/IP, or host:port / ip:port) and returns a host:port. The port 443 is added if needed.
func ( string,  string) ( string) {
	, ,  := net.SplitHostPort()
	if  != nil { // authority didn't have a port
		 = "443"
		if  == "http" {
			 = "80"
		}
		 = 
	}
	if ,  := idna.ToASCII();  == nil {
		 = 
IPv6 address literal, without a port:
	if strings.HasPrefix(, "[") && strings.HasSuffix(, "]") {
		return  + ":" + 
	}
	return net.JoinHostPort(, )
}
RoundTripOpt is like RoundTrip, but takes options.
func ( *http2Transport) ( *Request,  http2RoundTripOpt) (*Response, error) {
	if !(.URL.Scheme == "https" || (.URL.Scheme == "http" && .AllowHTTP)) {
		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(&.reused, 0, 1)
		http2traceGotConn(, , )
		, ,  := .roundTrip()
		if  != nil &&  <= 6 {
After the first retry, do exponential backoff with 10% jitter.
				if  == 0 {
					continue
				}
				 := float64(uint(1) << (uint() - 1))
				 +=  * (0.1 * mathrand.Float64())
				select {
				case <-time.After(time.Second * time.Duration()):
					continue
				case <-.Context().Done():
					return nil, .Context().Err()
				}
			}
		}
		if  != nil {
			.vlogf("RoundTrip failure: %v", )
			return nil, 
		}
		return , nil
	}
}
CloseIdleConnections closes any connections which were previously connected from previous requests but are now sitting idle. It does not interrupt any connections currently in use.
func ( *http2Transport) () {
	if ,  := .connPool().(http2clientConnPoolIdleCloser);  {
		.closeIdleConnections()
	}
}

var (
	http2errClientConnClosed    = errors.New("http2: client conn is closed")
	http2errClientConnUnusable  = errors.New("http2: client conn not usable")
	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 ( *Request,  error,  bool) (*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.
TODO: consider a req.Body.Close here? or audit that all caller paths do?
		,  := .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. The "afterBodyWrite" means the bodyWrite process has started, which becomes true before the first Read.
	if ! {
		return , nil
	}

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

func ( error) bool {
	if  == http2errClientConnUnusable ||  == http2errClientConnGotGoAway {
		return true
	}
	if ,  := .(http2StreamError);  {
		return .Code == http2ErrCodeRefusedStream
	}
	return false
}

func ( *http2Transport) ( string,  bool) (*http2ClientConn, error) {
	, ,  := 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) () func(string, string, *tls.Config) (net.Conn, error) {
	if .DialTLS != nil {
		return .DialTLS
	}
	return .dialTLSDefault
}

func ( *http2Transport) (,  string,  *tls.Config) (net.Conn, error) {
	,  := tls.Dial(, , )
	if  != nil {
		return nil, 
	}
	if  := .Handshake();  != nil {
		return nil, 
	}
	if !.InsecureSkipVerify {
		if  := .VerifyHostname(.ServerName);  != 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) {
	 := &http2ClientConn{
		t:                     ,
		tconn:                 ,
		readerDone:            make(chan struct{}),
		nextStreamID:          1,
		maxFrameSize:          16 << 10,           // spec default
		initialWindowSize:     65535,              // spec default
		maxConcurrentStreams:  1000,               // "infinite", per spec. 1000 seems good enough.
		peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead.
		streams:               make(map[uint32]*http2clientStream),
		singleUse:             ,
		wantSettingsAck:       true,
		pings:                 make(map[[8]byte]chan struct{}),
	}
	if  := .idleConnTimeout();  != 0 {
		.idleTimeout = 
		.idleTimer = time.AfterFunc(, .onIdleTimeout)
	}
	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.
TODO: SetMaxDynamicTableSize, SetMaxDynamicTableSizeLimit on henc in response to SETTINGS frames?
	.henc = hpack.NewEncoder(&.hbuf)

	if .AllowHTTP {
		.nextStreamID = 3
	}

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

	 := []http2Setting{
		{ID: http2SettingEnablePush, Val: 0},
		{ID: http2SettingInitialWindowSize, Val: http2transportDefaultStreamFlow},
	}
	if  := .maxHeaderListSize();  != 0 {
		 = append(, http2Setting{ID: http2SettingMaxHeaderListSize, Val: })
	}

	.bw.Write(http2clientPreface)
	.fr.WriteSettings(...)
	.fr.WriteWindowUpdate(0, http2transportDefaultConnFlow)
	.inflow.add(http2transportDefaultConnFlow + http2initialWindowSize)
	.bw.Flush()
	if .werr != nil {
		.Close()
		return nil, .werr
	}

	go .readLoop()
	return , nil
}

func ( *http2ClientConn) () {
We don't need to periodically ping in the health check, because the readLoop of ClientConn will trigger the healthCheck again if there is no frame received.
	,  := context.WithTimeout(context.Background(), )
	defer ()
	 := .Ping()
	if  != nil {
		.closeForLostPing()
		.t.connPool().MarkDead()
		return
	}
}

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  >  {
			select {
			case .resc <- http2resAndError{err: http2errClientConnGotGoAway}:
			default:
			}
		}
	}
}
CanTakeNewRequest reports whether the connection can take a new request, meaning it has not been closed or received or sent a GOAWAY.
func ( *http2ClientConn) () bool {
	.mu.Lock()
	defer .mu.Unlock()
	return .canTakeNewRequestLocked()
}
clientConnIdleState describes the suitability of a client connection to initiate a new RoundTrip request.
type http2clientConnIdleState struct {
	canTakeNewRequest bool
	freshConn         bool // whether it's unused by any previous request
}

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

func ( *http2ClientConn) () ( http2clientConnIdleState) {
	if .singleUse && .nextStreamID > 1 {
		return
	}
	var  bool
We'll tell the caller we can take a new request to prevent the caller from dialing a new TCP connection, but then we'll block later before writing it.
		 = true
	} else {
		 = int64(len(.streams)+1) < int64(.maxConcurrentStreams)
	}

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

func ( *http2ClientConn) () bool {
	 := .idleStateLocked()
	return .canTakeNewRequest
}
tooIdleLocked reports whether this connection has been been sitting idle for too much wall time.
The Round(0) strips the monontonic clock reading so the times are compared based on their wall time. We don't want to reuse a connection that's been sitting idle during VM/laptop suspend if monotonic time was also frozen.
	return .idleTimeout != 0 && !.lastIdle.IsZero() && time.Since(.lastIdle.Round(0)) > .idleTimeout
}
onIdleTimeout is called from a time.AfterFunc goroutine. It will only be called when we're idle, but because we're coming from a new goroutine, there could be a new request coming in at the same time, so this simply calls the synchronized closeIfIdle to shut down this connection. The timer could just call closeIfIdle, but this is more clear.
func ( *http2ClientConn) () {
	.closeIfIdle()
}

func ( *http2ClientConn) () {
	.mu.Lock()
	if len(.streams) > 0 {
		.mu.Unlock()
		return
	}
	.closed = true
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)
	}
	.tconn.Close()
}

var http2shutdownEnterWaitStateHook = func() {}
Shutdown gracefully close 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 error, 1)
	 := false // guarded by cc.mu
	go func() {
		.mu.Lock()
		defer .mu.Unlock()
		for {
			if len(.streams) == 0 || .closed {
				.closed = true
				 <- .tconn.Close()
				break
			}
			if  {
				break
			}
			.cond.Wait()
		}
	}()
	http2shutdownEnterWaitStateHook()
	select {
	case  := <-:
		return 
	case <-.Done():
Free the goroutine above
		 = true
		.cond.Broadcast()
		.mu.Unlock()
		return .Err()
	}
}

func ( *http2ClientConn) () error {
	.mu.Lock()
	defer .mu.Unlock()
	.wmu.Lock()
	defer .wmu.Unlock()
GOAWAY sent already
		return nil
Send a graceful shutdown frame to server
	 := .nextStreamID
	if  := .fr.WriteGoAway(, http2ErrCodeNo, nil);  != nil {
		return 
	}
	if  := .bw.Flush();  != nil {
		return 
Prevent new requests
	.closing = true
	return nil
}
closes the client connection immediately. In-flight requests are interrupted. err is sent to streams.
func ( *http2ClientConn) ( error) error {
	.mu.Lock()
	defer .cond.Broadcast()
	defer .mu.Unlock()
	for ,  := range .streams {
		select {
		case .resc <- http2resAndError{err: }:
		default:
		}
		.bufPipe.CloseWithError()
		delete(.streams, )
	}
	.closed = true
	return .tconn.Close()
}
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")
	return .closeForError()
}
closes the client connection immediately. In-flight requests are interrupted.
func ( *http2ClientConn) () error {
	 := errors.New("http2: client connection lost")
	return .closeForError()
}

const http2maxAllocFrameSize = 512 << 10
frameBuffer returns a scratch buffer suitable for writing DATA frames. They're capped at the min of the peer's max frame size or 512KB (kinda arbitrarily), but definitely capped so we don't allocate 4GB bufers.
func ( *http2ClientConn) () []byte {
	.mu.Lock()
	 := .maxFrameSize
	if  > http2maxAllocFrameSize {
		 = http2maxAllocFrameSize
	}
	for ,  := range .freeBuf {
		if len() >= int() {
			.freeBuf[] = nil
			.mu.Unlock()
			return [:]
		}
	}
	.mu.Unlock()
	return make([]byte, )
}

func ( *http2ClientConn) ( []byte) {
	.mu.Lock()
	defer .mu.Unlock()
	const  = 4 // arbitrary; 4 concurrent requests per conn? investigate.
	if len(.freeBuf) <  {
		.freeBuf = append(.freeBuf, )
		return
	}
	for ,  := range .freeBuf {
		if  == nil {
			.freeBuf[] = 
			return
		}
forget about it.
}
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 ( *Request) (string, error) {
	 := make([]string, 0, len(.Trailer))
	for  := range .Trailer {
		 = CanonicalHeaderKey()
		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 ( *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] != "" && !strings.EqualFold([0], "close") && !strings.EqualFold([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 ( *Request) int64 {
	if .Body == nil || .Body == NoBody {
		return 0
	}
	if .ContentLength != 0 {
		return .ContentLength
	}
	return -1
}

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

func ( *http2ClientConn) ( *Request) ( *Response,  bool,  error) {
	if  := http2checkConnHeaders();  != nil {
		return nil, false, 
	}
	if .idleTimer != nil {
		.idleTimer.Stop()
	}

	,  := http2commaSeparatedTrailers()
	if  != nil {
		return nil, false, 
	}
	 :=  != ""

	.mu.Lock()
	if  := .awaitOpenSlotForRequest();  != nil {
		.mu.Unlock()
		return nil, false, 
	}

	 := .Body
	 := http2actualContentLength()
	 :=  != 0
TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
	var  bool
	if !.t.disableCompression() &&
		.Header.Get("Accept-Encoding") == "" &&
		.Header.Get("Range") == "" &&
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
		 = true
	}
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,})
	,  := .encodeHeaders(, , , )
	if  != nil {
		.mu.Unlock()
		return nil, false, 
	}

	 := .newStream()
	.req = 
	.trace = httptrace.ContextClientTrace(.Context())
	.requestedGzip = 
	 := .t.getBodyWriterState(, )
	.on100 = .on100

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

	.wmu.Lock()
	 := ! && !
	 := .writeHeaders(.ID, , int(.maxFrameSize), )
	.wmu.Unlock()
	http2traceWroteHeaders(.trace)
	.mu.Unlock()

	if  != nil {
		if  {
			.Body.Close() // per RoundTripper contract
			.cancel()
		}
Don't bother sending a RST_STREAM (our write already failed; no need to keep writing)
		http2traceWroteRequest(.trace, )
		return nil, false, 
	}

	var  <-chan time.Time
	if  {
		.scheduleBodyWrite()
	} else {
		http2traceWroteRequest(.trace, nil)
		if  := .responseHeaderTimeout();  != 0 {
			 := time.NewTimer()
			defer .Stop()
			 = .C
		}
	}

	 := .resc
	 := false
	 := .Context()

	 := func( http2resAndError) (*Response, bool, error) {
		 := .res
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.
			.cancel()
			.abortRequestBodyWrite(http2errStopReqBodyWrite)
			if  && ! {
				<-.resc
			}
		}
		if .err != nil {
			.forgetStreamID(.ID)
			return nil, .getStartedWrite(), .err
		}
		.Request = 
		.TLS = .tlsState
		return , false, nil
	}

	for {
		select {
		case  := <-:
			return ()
		case <-:
			if ! ||  {
				.writeStreamReset(.ID, http2ErrCodeCancel, nil)
			} else {
				.cancel()
				.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel)
				<-.resc
			}
			.forgetStreamID(.ID)
			return nil, .getStartedWrite(), http2errTimeout
		case <-.Done():
			if ! ||  {
				.writeStreamReset(.ID, http2ErrCodeCancel, nil)
			} else {
				.cancel()
				.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel)
				<-.resc
			}
			.forgetStreamID(.ID)
			return nil, .getStartedWrite(), .Err()
		case <-.Cancel:
			if ! ||  {
				.writeStreamReset(.ID, http2ErrCodeCancel, nil)
			} else {
				.cancel()
				.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel)
				<-.resc
			}
			.forgetStreamID(.ID)
			return nil, .getStartedWrite(), http2errRequestCanceled
processResetStream already removed the stream from the streams map; no need for forgetStreamID.
			return nil, .getStartedWrite(), .resetErr
		case  := <-.resc:
Prefer the read loop's response, if available. Issue 16102.
			select {
			case  := <-:
				return ()
			default:
			}
			if  != nil {
				.forgetStreamID(.ID)
				return nil, .getStartedWrite(), 
			}
			if  := .responseHeaderTimeout();  != 0 {
				 := time.NewTimer()
				defer .Stop()
				 = .C
			}
		}
	}
}
awaitOpenSlotForRequest waits until len(streams) < maxConcurrentStreams. Must hold cc.mu.
func ( *http2ClientConn) ( *Request) error {
	var  chan struct{}
	var  error // guarded by cc.mu
	for {
		.lastActive = time.Now()
		if .closed || !.canTakeNewRequestLocked() {
			if  != nil {
				close()
			}
			return http2errClientConnUnusable
		}
		.lastIdle = time.Time{}
		if int64(len(.streams))+1 <= int64(.maxConcurrentStreams) {
			if  != nil {
				close()
			}
			return nil
Unfortunately, we cannot wait on a condition variable and channel at the same time, so instead, we spin up a goroutine to check if the request is canceled while we wait for a slot to open in the connection.
		if  == nil {
			 = make(chan struct{})
			go func() {
				if  := http2awaitRequestCancel(, );  != nil {
					.mu.Lock()
					 = 
					.cond.Broadcast()
					.mu.Unlock()
				}
			}()
		}
		.pendingRequests++
		.cond.Wait()
		.pendingRequests--
		if  != nil {
			return 
		}
	}
}
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(, , )
		}
TODO(bradfitz): this Flush could potentially block (as could the WriteHeaders call(s) above), which means they wouldn't respond to Request.Cancel being readable. That's rare, but this should probably be in a goroutine.
	.bw.Flush()
	return .werr
}
internal error values; they don't escape to callers
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")
)

func ( *http2clientStream) ( io.Reader,  io.Closer) ( error) {
	 := .cc
	 := false // whether we sent the final DATA frame w/ END_STREAM
	 := .frameScratchBuffer()
	defer .putFrameScratchBuffer()

	defer func() {
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
		 := .Close()
		if  == nil {
			 = 
		}
	}()

	 := .req
	 := .Trailer != nil
	 := http2actualContentLength()
	 :=  != -1

	var  bool
	for ! {
		,  := .Read([:len()-1])
		if  {
			 -= int64()
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  int
				,  = .Read([:])
				 -= int64()
			}
			if  < 0 {
				 = http2errReqBodyTooLong
				.writeStreamReset(.ID, http2ErrCodeCancel, )
				return 
			}
		}
		if  == io.EOF {
			 = true
			 = nil
		} else if  != nil {
			.writeStreamReset(.ID, http2ErrCodeCancel, )
			return 
		}

		 := [:]
		for len() > 0 &&  == nil {
			var  int32
			,  = .awaitFlowControl(len())
			switch {
			case  == http2errStopReqBodyWrite:
				return 
			case  == http2errStopReqBodyWriteAndCancel:
				.writeStreamReset(.ID, http2ErrCodeCancel, nil)
				return 
			case  != nil:
				return 
			}
			.wmu.Lock()
			 := [:]
			 = [:]
			 =  && len() == 0 && !
			 = .fr.WriteData(.ID, , )
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 
		}
	}

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
	}

	var  []byte
	if  {
		.mu.Lock()
		,  = .encodeTrailers()
		.mu.Unlock()
		if  != nil {
			.writeStreamReset(.ID, http2ErrCodeInternal, )
			.forgetStreamID(.ID)
			return 
		}
	}

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

	.wmu.Lock()
	defer .wmu.Unlock()
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
	.mu.Lock()
	defer .mu.Unlock()
	for {
		if .closed {
			return 0, http2errClientConnClosed
		}
		if .stopReqBody != nil {
			return 0, .stopReqBody
		}
		if  := .checkResetOrDone();  != nil {
			return 0, 
		}
		if  := .flow.available();  > 0 {
			 := 
			if int() >  {

				 = int32() // can't truncate int; take is int32
			}
			if  > int32(.maxFrameSize) {
				 = int32(.maxFrameSize)
			}
			.flow.take()
			return , nil
		}
		.cond.Wait()
	}
}
requires cc.mu be held.
func ( *http2ClientConn) ( *Request,  bool,  string,  int64) ([]byte, error) {
	.hbuf.Reset()

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

	var  string
	if .Method != "CONNECT" {
		 = .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 and return an error before we potentially pollute our hpack state. (We want to be able to continue to reuse the hpack encoder for future requests)
	for ,  := range .Header {
		if !httpguts.ValidHeaderFieldName() {
			return nil, fmt.Errorf("invalid HTTP header name %q", )
		}
		for ,  := range  {
			if !httpguts.ValidHeaderFieldValue() {
				return nil, fmt.Errorf("invalid HTTP header value %q for header %q", , )
			}
		}
	}

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

		var  bool
		for ,  := range .Header {
Host is :authority, already sent. Content-Length is automatic, set below.
				continue
			} else if strings.EqualFold(, "connection") || strings.EqualFold(, "proxy-connection") ||
				strings.EqualFold(, "transfer-encoding") || strings.EqualFold(, "upgrade") ||
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
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
				}
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) {
		 = strings.ToLower()
		.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 ( 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.mu be held.
func ( *http2ClientConn) ( *Request) ([]byte, error) {
	.hbuf.Reset()

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

Transfer-Encoding, etc.. have already been filtered at the start of RoundTrip
		 := strings.ToLower()
		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 {
	 := &http2clientStream{
		cc:        ,
		ID:        .nextStreamID,
		resc:      make(chan http2resAndError, 1),
		peerReset: make(chan struct{}),
		done:      make(chan struct{}),
	}
	.flow.add(int32(.initialWindowSize))
	.flow.setConnFlow(&.flow)
	.inflow.add(http2transportDefaultStreamFlow)
	.inflow.setConnFlow(&.inflow)
	.nextStreamID += 2
	.streams[.ID] = 
	return 
}

func ( *http2ClientConn) ( uint32) {
	.streamByID(, true)
}

func ( *http2ClientConn) ( uint32,  bool) *http2clientStream {
	.mu.Lock()
	defer .mu.Unlock()
	 := .streams[]
	if  &&  != nil && !.closed {
		.lastActive = time.Now()
		delete(.streams, )
		if len(.streams) == 0 && .idleTimer != nil {
			.idleTimer.Reset(.idleTimeout)
			.lastIdle = time.Now()
		}
Wake up checkResetOrDone via clientStream.awaitFlowControl and wake up RoundTrip if there is a pending request.
		.cond.Broadcast()
	}
	return 
}
clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop.
readLoop runs in its own goroutine and reads and dispatches frames.
func ( *http2ClientConn) () {
	 := &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 ( error) bool {
	if  == io.EOF {
		return true
	}
	,  := .(*net.OpError)
	return  && .Op == "read"
}

func ( *http2clientConnReadLoop) () {
	 := .cc
	defer .tconn.Close()
	defer .t.connPool().MarkDead()
	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
	}
	for ,  := range .streams {
		.bufPipe.CloseWithError() // no-op if already closed
		select {
		case .resc <- http2resAndError{err: }:
		default:
		}
		close(.done)
	}
	.closed = true
	.cond.Broadcast()
	.mu.Unlock()
}

func ( *http2clientConnReadLoop) () error {
	 := .cc
	.closeWhenIdle = .t.disableKeepAlives() || .singleUse
	 := false // ever saw a HEADERS reply
	 := false
	 := .t.ReadIdleTimeout
	var  *time.Timer
	if  != 0 {
		 = time.AfterFunc(, .healthCheck)
		defer .Stop()
	}
	for {
		,  := .fr.ReadFrame()
		if  != nil {
			.Reset()
		}
		if  != nil {
			.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", , , )
		}
		if ,  := .(http2StreamError);  {
			if  := .streamByID(.StreamID, false);  != nil {
				.cc.writeStreamReset(.ID, .Code, )
				.cc.forgetStreamID(.ID)
				if .Cause == nil {
					.Cause = .fr.errDetail
				}
				.endStreamError(, )
			}
			continue
		} else if  != nil {
			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
		}
		 := false // whether frame might transition us to idle

		switch f := .(type) {
		case *http2MetaHeadersFrame:
			 = .processHeaders()
			 = true
			 = true
		case *http2DataFrame:
			 = .processData()
			 = true
		case *http2GoAwayFrame:
			 = .processGoAway()
			 = true
		case *http2RSTStreamFrame:
			 = .processResetStream()
			 = true
		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(), )
			}
			return 
		}
		if .closeWhenIdle &&  &&  {
			.closeIfIdle()
		}
	}
}

func ( *http2clientConnReadLoop) ( *http2MetaHeadersFrame) error {
	 := .cc
	 := .streamByID(.StreamID, false)
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
	}
Issue 20521: If the stream has ended, streamByID() causes clientStream.done to be closed, which causes the request's bodyWriter to be closed with an errStreamClosed, which may be received by clientConn.RoundTrip before the result of processing these headers. Deferring stream closure allows the header processing to occur first. clientConn.RoundTrip may still receive the bodyWriter error first, but the fix for issue 16102 prioritises any response. Issue 22413: If there is no request body, we should close the stream before writing to cs.resc so that the stream is closed immediately once RoundTrip returns.
		if .req.Body != nil {
			defer .forgetStreamID(.StreamID)
		} else {
			.forgetStreamID(.StreamID)
		}
	}
	if !.firstByte {
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.
		.cc.writeStreamReset(.StreamID, http2ErrCodeProtocol, )
		.forgetStreamID(.ID)
		.resc <- http2resAndError{err: }
		return nil // return nil from process* funcs to keep conn alive
	}
(nil, nil) special case. See handleResponse docs.
		return nil
	}
	.resTrailer = &.Trailer
	.resc <- http2resAndError{res: }
	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  {
		 := CanonicalHeaderKey(.Name)
		if  == "Trailer" {
			 := .Trailer
			if  == nil {
				 = make(Header)
				.Trailer = 
			}
			http2foreachHeaderElement(.Value, func( string) {
				[CanonicalHeaderKey()] = nil
			})
		} else {
			 := []
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 {
		.num1xx++
		const  = 5 // arbitrary bound on number of informational responses, same as net/http
		if .num1xx >  {
			return nil, errors.New("http2: too many 1xx informational responses")
		}
		if  := .get1xxTraceFunc();  != nil {
			if  := (, textproto.MIMEHeader());  != nil {
				return nil, 
			}
		}
		if  == 100 {
			http2traceGot100Continue(.trace)
			if .on100 != nil {
				.on100() // forces any write delay timer to fire
			}
		}
		.pastHeaders = false // do it all again
		return nil, nil
	}

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

	if  ||  {
		.Body = http2noBody
		return , nil
	}

	.bufPipe = http2pipe{b: &http2dataBuffer{expected: .ContentLength}}
	.bytesRemain = .ContentLength
	.Body = http2transportResponseBody{}
	go .awaitRequestCancel(.req)

	if .requestedGzip && .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 {
Too many HEADERS frames for this stream.
We expect that any headers for trailers also has END_STREAM.
No pseudo header fields are defined for trailers. TODO: ConnectionError might be overly harsh? Check.
		return http2ConnectionError(http2ErrCodeProtocol)
	}

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

	.endStream()
	return nil
}
transportResponseBody is the concrete type of Transport.RoundTrip's Response.Body. It is an io.ReadCloser. On Read, it reads from cs.body. On Close it sends RST_STREAM if EOF wasn't already seen.
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")
				.writeStreamReset(.ID, http2ErrCodeProtocol, )
			}
			.readErr = 
			return int(.bytesRemain), 
		}
		.bytesRemain -= int64()
		if  == io.EOF && .bytesRemain > 0 {
			 = io.ErrUnexpectedEOF
			.readErr = 
			return , 
		}
	}
No flow control tokens to send back.
		return
	}

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

Check the conn-level first, before the stream-level.
	if  := .inflow.available();  < http2transportDefaultConnFlow/2 {
		 = http2transportDefaultConnFlow - 
		.inflow.add()
	}
Consider any buffered body data (read from the conn but not consumed by the client) when computing flow control for this stream.
		 := int(.inflow.available()) + .bufPipe.Len()
		if  < http2transportDefaultStreamFlow-http2transportDefaultStreamMinRefresh {
			 = int32(http2transportDefaultStreamFlow - )
			.inflow.add()
		}
	}
	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.Err() == io.EOF
	 := .bufPipe.Len()

	if  > 0 || ! {
		.mu.Lock()
		.wmu.Lock()
		if ! {
			.fr.WriteRSTStream(.ID, http2ErrCodeCancel)
			.didReset = true
Return connection-level flow control.
		if  > 0 {
			.inflow.add(int32())
			.fr.WriteWindowUpdate(0, uint32())
		}
		.bw.Flush()
		.wmu.Unlock()
		.mu.Unlock()
	}

	.bufPipe.BreakWithError(http2errClosedResponseBody)
	.forgetStreamID(.ID)
	return nil
}

func ( *http2clientConnReadLoop) ( *http2DataFrame) error {
	 := .cc
	 := .streamByID(.StreamID, .StreamEnded())
	 := .Data()
	if  == nil {
		.mu.Lock()
		 := .nextStreamID
		.mu.Unlock()
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.add(int32(.Length))
			.mu.Unlock()

			.wmu.Lock()
			.fr.WriteWindowUpdate(0, uint32(.Length))
			.bw.Flush()
			.wmu.Unlock()
		}
		return nil
	}
	if !.firstByte {
		.logf("protocol error: received DATA before a HEADERS frame")
		.endStreamError(, http2StreamError{
			StreamID: .StreamID,
			Code:     http2ErrCodeProtocol,
		})
		return nil
	}
	if .Length > 0 {
		if .req.Method == "HEAD" && len() > 0 {
			.logf("protocol error: received DATA on a HEAD request")
			.endStreamError(, http2StreamError{
				StreamID: .StreamID,
				Code:     http2ErrCodeProtocol,
			})
			return nil
Check connection-level flow control.
Return any padded flow control now, since we won't refund it later on body reads.
		var  int
		if  := int(.Length) - len();  > 0 {
			 += 
Return len(data) now if the stream is already closed, since data will never be read.
		 := .didReset
		if  {
			 += len()
		}
		if  > 0 {
			.inflow.add(int32())
			.wmu.Lock()
			.fr.WriteWindowUpdate(0, uint32())
			if ! {
				.inflow.add(int32())
				.fr.WriteWindowUpdate(.ID, uint32())
			}
			.bw.Flush()
			.wmu.Unlock()
		}
		.mu.Unlock()

		if len() > 0 && ! {
			if ,  := .bufPipe.Write();  != nil {
				.endStreamError(, )
				return 
			}
		}
	}

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

TODO: check that any declared content-length matches, like server.go's (*stream).endStream method.
	.endStreamError(, nil)
}

func ( *http2clientConnReadLoop) ( *http2clientStream,  error) {
	var  func()
	if  == nil {
		 = io.EOF
		 = .copyTrailers
	}
	if http2isConnectionCloseRequest(.req) {
		.closeWhenIdle = true
	}
	.bufPipe.closeWithErrorAndCode(, )

	select {
	case .resc <- http2resAndError{err: }:
	default:
	}
}

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

func ( *http2clientConnReadLoop) ( *http2GoAwayFrame) error {
	 := .cc
	.t.connPool().MarkDead()
TODO: deal with GOAWAY more. particularly the error code
		.vlogf("transport got GOAWAY with error code = %v", .ErrCode)
	}
	.setGoAway()
	return nil
}

func ( *http2clientConnReadLoop) ( *http2SettingsFrame) error {
	 := .cc
	.mu.Lock()
	defer .mu.Unlock()

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

	 := .ForeachSetting(func( http2Setting) error {
		switch .ID {
		case http2SettingMaxFrameSize:
			.maxFrameSize = .Val
		case http2SettingMaxConcurrentStreams:
			.maxConcurrentStreams = .Val
		case http2SettingMaxHeaderListSize:
			.peerMaxHeaderListSize = uint64(.Val)
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.
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
TODO(bradfitz): handle more settings? SETTINGS_HEADER_TABLE_SIZE probably.
			.vlogf("Unhandled Setting: %v", )
		}
		return nil
	})
	if  != nil {
		return 
	}

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

	.fr.WriteSettingsAck()
	.bw.Flush()
	return .werr
}

func ( *http2clientConnReadLoop) ( *http2WindowUpdateFrame) error {
	 := .cc
	 := .streamByID(.StreamID, false)
	if .StreamID != 0 &&  == nil {
		return nil
	}

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

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

func ( *http2clientConnReadLoop) ( *http2RSTStreamFrame) error {
	 := .cc.streamByID(.StreamID, true)
TODO: return error if server tries to RST_STEAM an idle stream
		return nil
	}
	select {
Already reset. This is the only goroutine which closes this, so there isn't a race.
	default:
		 := http2streamError(.ID, .ErrCode)
		.resetErr = 
		close(.peerReset)
		.bufPipe.CloseWithError()
		.cc.cond.Broadcast() // wake up checkResetOrDone via clientStream.awaitFlowControl
	}
	return nil
}
Ping sends a PING frame to the server and waits for the ack.
Generate a random payload
	var  [8]byte
	for {
		if ,  := rand.Read([:]);  != nil {
			return 
		}
check for dup before insert
		if ,  := .pings[]; ! {
			.pings[] = 
			.mu.Unlock()
			break
		}
		.mu.Unlock()
	}
	.wmu.Lock()
	if  := .fr.WritePing(false, );  != nil {
		.wmu.Unlock()
		return 
	}
	if  := .bw.Flush();  != nil {
		.wmu.Unlock()
		return 
	}
	.wmu.Unlock()
	select {
	case <-:
		return nil
	case <-.Done():
		return .Err()
connection closed
		return .readerErr
	}
}

func ( *http2clientConnReadLoop) ( *http2PingFrame) error {
	if .IsAck() {
		 := .cc
		.mu.Lock()
If ack, notify listener if any
		if ,  := .pings[.Data];  {
			close()
			delete(.pings, .Data)
		}
		return nil
	}
	 := .cc
	.wmu.Lock()
	defer .wmu.Unlock()
	if  := .fr.WritePing(true, .Data);  != nil {
		return 
	}
	return .bw.Flush()
}

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."
TODO: map err to more interesting error codes, once the HTTP community comes up with some. But currently for RST_STREAM there's no equivalent to GOAWAY frame's debug data, and the error codes are all pretty vague ("cancel").
	.wmu.Lock()
	.fr.WriteRSTStream(, )
	.bw.Flush()
	.wmu.Unlock()
}

var (
	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 = ioutil.NopCloser(bytes.NewReader(nil))

func ( []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 {
	return .body.Close()
}

type http2errorReader struct{ err error }

func ( http2errorReader) ( []byte) (int, error) { return 0, .err }
bodyWriterState encapsulates various state around the Transport's writing of the request body, particularly regarding doing delayed writes of the body when the request contains "Expect: 100-continue".
type http2bodyWriterState struct {
	cs     *http2clientStream
	timer  *time.Timer   // if non-nil, we're doing a delayed write
	fnonce *sync.Once    // to call fn with
	fn     func()        // the code to run in the goroutine, writing the body
	resc   chan error    // result of fn's execution
	delay  time.Duration // how long we should delay a delayed write for
}

func ( *http2Transport) ( *http2clientStream,  io.Reader) ( http2bodyWriterState) {
	.cs = 
	if  == nil {
		return
	}
	 := make(chan error, 1)
	.resc = 
	.fn = func() {
		.cc.mu.Lock()
		.startedWrite = true
		.cc.mu.Unlock()
		 <- .writeRequestBody(, .req.Body)
	}
	.delay = .expectContinueTimeout()
	if .delay == 0 ||
		!httpguts.HeaderValuesContainsToken(
			.req.Header["Expect"],
			"100-continue") {
		return
	}
	.fnonce = new(sync.Once)
Arm the timer with a very large duration, which we'll intentionally lower later. It has to be large now because we need a handle to it before writing the headers, but the s.delay value is defined to not start until after the request headers were written.
	const  = 365 * 24 * time.Hour
	.timer = time.AfterFunc(, func() {
		.fnonce.Do(.fn)
	})
	return
}

func ( http2bodyWriterState) () {
	if .timer != nil {
		if .timer.Stop() {
			.resc <- nil
		}
	}
}

func ( http2bodyWriterState) () {
If we didn't do a delayed write, ignore the server's bogus 100 continue response.
		return
	}
	.timer.Stop()
	go func() { .fnonce.Do(.fn) }()
}
scheduleBodyWrite starts writing the body, either immediately (in the common case) or after the delay timeout. It should not be called until after the headers have been written.
We're not doing a delayed write (see getBodyWriterState), so just start the writing goroutine immediately.
		go .fn()
		return
	}
	http2traceWait100Continue(.cs.trace)
	if .timer.Stop() {
		.timer.Reset(.delay)
	}
}
isConnectionCloseRequest reports whether req should use its own connection for a single request and then close the connection.
func ( *Request) bool {
	return .Close || httpguts.HeaderValuesContainsToken(.Header["Connection"], "close")
}
registerHTTPSProtocol calls Transport.RegisterProtocol but converting panics into errors.
func ( *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 {
	if .t1 != nil {
		return .t1.IdleConnTimeout
	}
	return 0
}

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

func ( *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 = time.Now().Sub(.lastActive)
	}
	.mu.Unlock()

	.GotConn()
}

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

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

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

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

func ( *httptrace.ClientTrace) {
	if  != nil && .GotFirstResponseByte != nil {
		.GotFirstResponseByte()
	}
}
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
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 ( http2writeFramer) bool {
	switch v := .(type) {
	case *http2writeData:
		return .endStream
	case *http2writeResHeaders:
		return .endStream
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.
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.
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 ( *hpack.Encoder, ,  string) {
	if http2VerboseLogs {
		log.Printf("http2: server encoding header %q = %q", , )
	}
	.WriteField(hpack.HeaderField{Name: , Value: })
}

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.
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,
	})
}

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 ( *hpack.Encoder,  Header,  []string) {
	if  == nil {
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()
Skip it as backup paranoia. Per golang.org/issue/14048, these should already be rejected at a higher level.
			continue
		}
		 :=  == "transfer-encoding"
		for ,  := range  {
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.
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.
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. No frames should be discarded except by CloseStream.
	Pop() (wr http2FrameWriteRequest, ok bool)
}
OpenStreamOptions specifies extra options for WriteScheduler.OpenStream.
PusherID is zero if the stream was initiated by the client. Otherwise, PusherID names the stream that pushed the newly opened stream.
FrameWriteRequest is a request to write a frame.
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.
stream is the stream on which this frame will be written. nil for non-stream frames like PING and SETTINGS.
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 {
(*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.
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,
Even if the original had endStream set, there are bytes remaining because len(wd.p) > allowed, so we know endStream is 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
}

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")
	}
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.
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."
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).
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.
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.
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) { [], [] = [], [] }

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

root is the root of the priority tree, where root.id = 0. The root queues control frames that are not associated with any stream.
nodes maps stream ids to priority tree nodes.
maxID is the maximum stream id in nodes.
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.
tmp is scratch space for priorityNode.walkReadyInOrder to reduce allocations.
pool of empty queues for reuse.
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  := .StreamID();  == 0 {
		 = &.root
	} else {
		 = .nodes[]
id is an idle or closed stream. wr should not be a HEADERS or DATA frame. However, wr can be a RST_STREAM. In this case, we push wr onto the root, rather than creating a new priorityNode, since RST_STREAM is tiny and the stream's priority is unknown anyway. See issue #17919.
			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
		}
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
	}
Remove the oldest node, then shift left.
		.removeNode((*)[0])
		 := (*)[1:]
		copy(*, )
		* = (*)[:len()]
	}
	* = append(*, )
}

func ( *http2priorityWriteScheduler) ( *http2priorityNode) {
	for  := .kids;  != nil;  = .next {
		.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.
zero are frames not associated with a specific stream.
sq contains the stream-specific queues, keyed by stream ID. When a stream is idle, closed, or emptied, it's deleted from the map.
pool of empty queues for reuse.
no-op: idle streams are not tracked
}

func ( *http2randomWriteScheduler) ( uint32) {
	,  := .sq[]
	if ! {
		return
	}
	delete(.sq, )
	.queuePool.put()
}

no-op: priorities are ignored
}

func ( *http2randomWriteScheduler) ( http2FrameWriteRequest) {
	 := .StreamID()
	if  == 0 {
		.zero.push()
		return
	}
	,  := .sq[]
	if ! {
		 = .queuePool.get()
		.sq[] = 
	}
	.push()
}

Control 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