mirror of
https://github.com/minio/minio.git
synced 2025-04-17 17:30:07 -04:00
Configure http2 with higher maxconcurrent streams (#7363)
This value is needed for Minio's internode communication, read the meaning of this value as per the HTTP 2.0 spec https://http2.github.io/http2-spec/#rfc.section.5.1.2
This commit is contained in:
parent
a0ee7be050
commit
233824bf92
@ -25,6 +25,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
humanize "github.com/dustin/go-humanize"
|
humanize "github.com/dustin/go-humanize"
|
||||||
|
"golang.org/x/net/http2"
|
||||||
|
|
||||||
"github.com/minio/minio-go/pkg/set"
|
"github.com/minio/minio-go/pkg/set"
|
||||||
"github.com/minio/minio/pkg/certs"
|
"github.com/minio/minio/pkg/certs"
|
||||||
)
|
)
|
||||||
@ -46,6 +48,9 @@ const (
|
|||||||
|
|
||||||
// DefaultMaxHeaderBytes - default maximum HTTP header size in bytes.
|
// DefaultMaxHeaderBytes - default maximum HTTP header size in bytes.
|
||||||
DefaultMaxHeaderBytes = 1 * humanize.MiByte
|
DefaultMaxHeaderBytes = 1 * humanize.MiByte
|
||||||
|
|
||||||
|
// DefaultHTTP2MaxConcurrentStreams - default value for HTTP 2.0 maximum concurrent streams allowed.
|
||||||
|
DefaultHTTP2MaxConcurrentStreams = 1024
|
||||||
)
|
)
|
||||||
|
|
||||||
// Server - extended http.Server supports multiple addresses to serve and enhanced connection handling.
|
// Server - extended http.Server supports multiple addresses to serve and enhanced connection handling.
|
||||||
@ -56,7 +61,7 @@ type Server struct {
|
|||||||
TCPKeepAliveTimeout time.Duration // timeout used for underneath TCP connection.
|
TCPKeepAliveTimeout time.Duration // timeout used for underneath TCP connection.
|
||||||
UpdateBytesReadFunc func(int) // function to be called to update bytes read in bufConn.
|
UpdateBytesReadFunc func(int) // function to be called to update bytes read in bufConn.
|
||||||
UpdateBytesWrittenFunc func(int) // function to be called to update bytes written in bufConn.
|
UpdateBytesWrittenFunc func(int) // function to be called to update bytes written in bufConn.
|
||||||
listenerMutex *sync.Mutex // to guard 'listener' field.
|
listenerMutex sync.Mutex // to guard 'listener' field.
|
||||||
listener *httpListener // HTTP listener for all 'Addrs' field.
|
listener *httpListener // HTTP listener for all 'Addrs' field.
|
||||||
inShutdown uint32 // indicates whether the server is in shutdown or not
|
inShutdown uint32 // indicates whether the server is in shutdown or not
|
||||||
requestCount int32 // counter holds no. of request in progress.
|
requestCount int32 // counter holds no. of request in progress.
|
||||||
@ -120,6 +125,11 @@ func (srv *Server) Start() (err error) {
|
|||||||
|
|
||||||
// Start servicing with listener.
|
// Start servicing with listener.
|
||||||
if tlsConfig != nil {
|
if tlsConfig != nil {
|
||||||
|
if err = http2.ConfigureServer(&srv.Server, &http2.Server{
|
||||||
|
MaxConcurrentStreams: DefaultHTTP2MaxConcurrentStreams,
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return srv.Server.Serve(tls.NewListener(listener, tlsConfig))
|
return srv.Server.Serve(tls.NewListener(listener, tlsConfig))
|
||||||
}
|
}
|
||||||
return srv.Server.Serve(listener)
|
return srv.Server.Serve(listener)
|
||||||
@ -202,7 +212,6 @@ func NewServer(addrs []string, handler http.Handler, getCert certs.GetCertificat
|
|||||||
Addrs: addrs,
|
Addrs: addrs,
|
||||||
ShutdownTimeout: DefaultShutdownTimeout,
|
ShutdownTimeout: DefaultShutdownTimeout,
|
||||||
TCPKeepAliveTimeout: DefaultTCPKeepAliveTimeout,
|
TCPKeepAliveTimeout: DefaultTCPKeepAliveTimeout,
|
||||||
listenerMutex: &sync.Mutex{},
|
|
||||||
}
|
}
|
||||||
httpServer.Handler = handler
|
httpServer.Handler = handler
|
||||||
httpServer.TLSConfig = tlsConfig
|
httpServer.TLSConfig = tlsConfig
|
||||||
|
@ -77,10 +77,6 @@ func TestNewServer(t *testing.T) {
|
|||||||
t.Fatalf("Case %v: server.TCPKeepAliveTimeout: expected: %v, got: %v", (i + 1), DefaultTCPKeepAliveTimeout, server.TCPKeepAliveTimeout)
|
t.Fatalf("Case %v: server.TCPKeepAliveTimeout: expected: %v, got: %v", (i + 1), DefaultTCPKeepAliveTimeout, server.TCPKeepAliveTimeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
if server.listenerMutex == nil {
|
|
||||||
t.Fatalf("Case %v: server.listenerMutex: expected: <non-nil>, got: <nil>", (i + 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
if server.ReadTimeout != DefaultReadTimeout {
|
if server.ReadTimeout != DefaultReadTimeout {
|
||||||
t.Fatalf("Case %v: server.ReadTimeout: expected: %v, got: %v", (i + 1), DefaultReadTimeout, server.ReadTimeout)
|
t.Fatalf("Case %v: server.ReadTimeout: expected: %v, got: %v", (i + 1), DefaultReadTimeout, server.ReadTimeout)
|
||||||
}
|
}
|
||||||
|
641
vendor/golang.org/x/net/http2/ciphers.go
generated
vendored
Normal file
641
vendor/golang.org/x/net/http2/ciphers.go
generated
vendored
Normal file
@ -0,0 +1,641 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
// A list of the possible cipher suite ids. Taken from
|
||||||
|
// https://www.iana.org/assignments/tls-parameters/tls-parameters.txt
|
||||||
|
|
||||||
|
const (
|
||||||
|
cipher_TLS_NULL_WITH_NULL_NULL uint16 = 0x0000
|
||||||
|
cipher_TLS_RSA_WITH_NULL_MD5 uint16 = 0x0001
|
||||||
|
cipher_TLS_RSA_WITH_NULL_SHA uint16 = 0x0002
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5 uint16 = 0x0003
|
||||||
|
cipher_TLS_RSA_WITH_RC4_128_MD5 uint16 = 0x0004
|
||||||
|
cipher_TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 uint16 = 0x0006
|
||||||
|
cipher_TLS_RSA_WITH_IDEA_CBC_SHA uint16 = 0x0007
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0008
|
||||||
|
cipher_TLS_RSA_WITH_DES_CBC_SHA uint16 = 0x0009
|
||||||
|
cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000A
|
||||||
|
cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x000B
|
||||||
|
cipher_TLS_DH_DSS_WITH_DES_CBC_SHA uint16 = 0x000C
|
||||||
|
cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0x000D
|
||||||
|
cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x000E
|
||||||
|
cipher_TLS_DH_RSA_WITH_DES_CBC_SHA uint16 = 0x000F
|
||||||
|
cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0010
|
||||||
|
cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0011
|
||||||
|
cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA uint16 = 0x0012
|
||||||
|
cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0x0013
|
||||||
|
cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0014
|
||||||
|
cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA uint16 = 0x0015
|
||||||
|
cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0016
|
||||||
|
cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 uint16 = 0x0017
|
||||||
|
cipher_TLS_DH_anon_WITH_RC4_128_MD5 uint16 = 0x0018
|
||||||
|
cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0019
|
||||||
|
cipher_TLS_DH_anon_WITH_DES_CBC_SHA uint16 = 0x001A
|
||||||
|
cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA uint16 = 0x001B
|
||||||
|
// Reserved uint16 = 0x001C-1D
|
||||||
|
cipher_TLS_KRB5_WITH_DES_CBC_SHA uint16 = 0x001E
|
||||||
|
cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA uint16 = 0x001F
|
||||||
|
cipher_TLS_KRB5_WITH_RC4_128_SHA uint16 = 0x0020
|
||||||
|
cipher_TLS_KRB5_WITH_IDEA_CBC_SHA uint16 = 0x0021
|
||||||
|
cipher_TLS_KRB5_WITH_DES_CBC_MD5 uint16 = 0x0022
|
||||||
|
cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5 uint16 = 0x0023
|
||||||
|
cipher_TLS_KRB5_WITH_RC4_128_MD5 uint16 = 0x0024
|
||||||
|
cipher_TLS_KRB5_WITH_IDEA_CBC_MD5 uint16 = 0x0025
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA uint16 = 0x0026
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA uint16 = 0x0027
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA uint16 = 0x0028
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 uint16 = 0x0029
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 uint16 = 0x002A
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5 uint16 = 0x002B
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA uint16 = 0x002C
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA uint16 = 0x002D
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA uint16 = 0x002E
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002F
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA uint16 = 0x0030
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0031
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA uint16 = 0x0032
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0033
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA uint16 = 0x0034
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA uint16 = 0x0036
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0037
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA uint16 = 0x0038
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0039
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA uint16 = 0x003A
|
||||||
|
cipher_TLS_RSA_WITH_NULL_SHA256 uint16 = 0x003B
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003C
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x003D
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 uint16 = 0x003E
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003F
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 uint16 = 0x0040
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0041
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0042
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0043
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0044
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0045
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0046
|
||||||
|
// Reserved uint16 = 0x0047-4F
|
||||||
|
// Reserved uint16 = 0x0050-58
|
||||||
|
// Reserved uint16 = 0x0059-5C
|
||||||
|
// Unassigned uint16 = 0x005D-5F
|
||||||
|
// Reserved uint16 = 0x0060-66
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x0067
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 uint16 = 0x0068
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x0069
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 uint16 = 0x006A
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x006B
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256 uint16 = 0x006C
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256 uint16 = 0x006D
|
||||||
|
// Unassigned uint16 = 0x006E-83
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0084
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0085
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0086
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0087
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0088
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0089
|
||||||
|
cipher_TLS_PSK_WITH_RC4_128_SHA uint16 = 0x008A
|
||||||
|
cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x008B
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CBC_SHA uint16 = 0x008C
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CBC_SHA uint16 = 0x008D
|
||||||
|
cipher_TLS_DHE_PSK_WITH_RC4_128_SHA uint16 = 0x008E
|
||||||
|
cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x008F
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0x0090
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0x0091
|
||||||
|
cipher_TLS_RSA_PSK_WITH_RC4_128_SHA uint16 = 0x0092
|
||||||
|
cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x0093
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA uint16 = 0x0094
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA uint16 = 0x0095
|
||||||
|
cipher_TLS_RSA_WITH_SEED_CBC_SHA uint16 = 0x0096
|
||||||
|
cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA uint16 = 0x0097
|
||||||
|
cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA uint16 = 0x0098
|
||||||
|
cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA uint16 = 0x0099
|
||||||
|
cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA uint16 = 0x009A
|
||||||
|
cipher_TLS_DH_anon_WITH_SEED_CBC_SHA uint16 = 0x009B
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009C
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009D
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009E
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009F
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x00A0
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x00A1
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 uint16 = 0x00A2
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 uint16 = 0x00A3
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256 uint16 = 0x00A4
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384 uint16 = 0x00A5
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256 uint16 = 0x00A6
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384 uint16 = 0x00A7
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00A8
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00A9
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00AA
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00AB
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00AC
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00AD
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00AE
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00AF
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA256 uint16 = 0x00B0
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA384 uint16 = 0x00B1
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00B2
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00B3
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA256 uint16 = 0x00B4
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA384 uint16 = 0x00B5
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00B6
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00B7
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA256 uint16 = 0x00B8
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA384 uint16 = 0x00B9
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BA
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BB
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BC
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BD
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BE
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BF
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C0
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C1
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C2
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C3
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C4
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C5
|
||||||
|
// Unassigned uint16 = 0x00C6-FE
|
||||||
|
cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV uint16 = 0x00FF
|
||||||
|
// Unassigned uint16 = 0x01-55,*
|
||||||
|
cipher_TLS_FALLBACK_SCSV uint16 = 0x5600
|
||||||
|
// Unassigned uint16 = 0x5601 - 0xC000
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA uint16 = 0xC001
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA uint16 = 0xC002
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC003
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xC004
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xC005
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA uint16 = 0xC006
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xC007
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC008
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xC009
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xC00A
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_NULL_SHA uint16 = 0xC00B
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA uint16 = 0xC00C
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC00D
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC00E
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC00F
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_NULL_SHA uint16 = 0xC010
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xC011
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC012
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC013
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC014
|
||||||
|
cipher_TLS_ECDH_anon_WITH_NULL_SHA uint16 = 0xC015
|
||||||
|
cipher_TLS_ECDH_anon_WITH_RC4_128_SHA uint16 = 0xC016
|
||||||
|
cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA uint16 = 0xC017
|
||||||
|
cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA uint16 = 0xC018
|
||||||
|
cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA uint16 = 0xC019
|
||||||
|
cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01A
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01B
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01C
|
||||||
|
cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA uint16 = 0xC01D
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC01E
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA uint16 = 0xC01F
|
||||||
|
cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA uint16 = 0xC020
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC021
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA uint16 = 0xC022
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC023
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC024
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC025
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC026
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC027
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC028
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC029
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC02A
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02B
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC02C
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02D
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC02E
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02F
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC030
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC031
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC032
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA uint16 = 0xC033
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0xC034
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0xC035
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0xC036
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0xC037
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0xC038
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA uint16 = 0xC039
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256 uint16 = 0xC03A
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384 uint16 = 0xC03B
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC03C
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC03D
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC03E
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC03F
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC040
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC041
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC042
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC043
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC044
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC045
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC046
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC047
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC048
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC049
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04A
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04B
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04C
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04D
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04E
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04F
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC050
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC051
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC052
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC053
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC054
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC055
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC056
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC057
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC058
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC059
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05A
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05B
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05C
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05D
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05E
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05F
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC060
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC061
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC062
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC063
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC064
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC065
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC066
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC067
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC068
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC069
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06A
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06B
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06C
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06D
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06E
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06F
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC070
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC071
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC072
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC073
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC074
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC075
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC076
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC077
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC078
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC079
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07A
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07B
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07C
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07D
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07E
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07F
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC080
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC081
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC082
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC083
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC084
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC085
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC086
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC087
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC088
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC089
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08A
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08B
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08C
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08D
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08E
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08F
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC090
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC091
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC092
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC093
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC094
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC095
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC096
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC097
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC098
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC099
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC09A
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC09B
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CCM uint16 = 0xC09C
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CCM uint16 = 0xC09D
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CCM uint16 = 0xC09E
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CCM uint16 = 0xC09F
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CCM_8 uint16 = 0xC0A0
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CCM_8 uint16 = 0xC0A1
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CCM_8 uint16 = 0xC0A2
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CCM_8 uint16 = 0xC0A3
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CCM uint16 = 0xC0A4
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CCM uint16 = 0xC0A5
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CCM uint16 = 0xC0A6
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CCM uint16 = 0xC0A7
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CCM_8 uint16 = 0xC0A8
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CCM_8 uint16 = 0xC0A9
|
||||||
|
cipher_TLS_PSK_DHE_WITH_AES_128_CCM_8 uint16 = 0xC0AA
|
||||||
|
cipher_TLS_PSK_DHE_WITH_AES_256_CCM_8 uint16 = 0xC0AB
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM uint16 = 0xC0AC
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CCM uint16 = 0xC0AD
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 uint16 = 0xC0AE
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 uint16 = 0xC0AF
|
||||||
|
// Unassigned uint16 = 0xC0B0-FF
|
||||||
|
// Unassigned uint16 = 0xC1-CB,*
|
||||||
|
// Unassigned uint16 = 0xCC00-A7
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCA8
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCA9
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAA
|
||||||
|
cipher_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAB
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAC
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAD
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAE
|
||||||
|
)
|
||||||
|
|
||||||
|
// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
|
||||||
|
// References:
|
||||||
|
// https://tools.ietf.org/html/rfc7540#appendix-A
|
||||||
|
// Reject cipher suites from Appendix A.
|
||||||
|
// "This list includes those cipher suites that do not
|
||||||
|
// offer an ephemeral key exchange and those that are
|
||||||
|
// based on the TLS null, stream or block cipher type"
|
||||||
|
func isBadCipher(cipher uint16) bool {
|
||||||
|
switch cipher {
|
||||||
|
case cipher_TLS_NULL_WITH_NULL_NULL,
|
||||||
|
cipher_TLS_RSA_WITH_NULL_MD5,
|
||||||
|
cipher_TLS_RSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5,
|
||||||
|
cipher_TLS_RSA_WITH_RC4_128_MD5,
|
||||||
|
cipher_TLS_RSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
|
||||||
|
cipher_TLS_RSA_WITH_IDEA_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5,
|
||||||
|
cipher_TLS_DH_anon_WITH_RC4_128_MD5,
|
||||||
|
cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_IDEA_CBC_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_DES_CBC_MD5,
|
||||||
|
cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5,
|
||||||
|
cipher_TLS_KRB5_WITH_RC4_128_MD5,
|
||||||
|
cipher_TLS_KRB5_WITH_IDEA_CBC_MD5,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5,
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_PSK_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA384,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CCM,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CCM,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CCM_8,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CCM_8,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CCM,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CCM,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CCM_8,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CCM_8:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
28
vendor/golang.org/x/net/http2/client_conn_pool.go
generated
vendored
28
vendor/golang.org/x/net/http2/client_conn_pool.go
generated
vendored
@ -52,9 +52,31 @@ const (
|
|||||||
noDialOnMiss = false
|
noDialOnMiss = 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.
|
||||||
|
func (p *clientConnPool) shouldTraceGetConn(st clientConnIdleState) bool {
|
||||||
|
// 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 _, ok := p.t.ConnPool.(noDialClientConnPool); !ok {
|
||||||
|
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 !st.freshConn
|
||||||
|
}
|
||||||
|
|
||||||
func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) {
|
func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) {
|
||||||
if isConnectionCloseRequest(req) && dialOnMiss {
|
if isConnectionCloseRequest(req) && dialOnMiss {
|
||||||
// It gets its own connection.
|
// It gets its own connection.
|
||||||
|
traceGetConn(req, addr)
|
||||||
const singleUse = true
|
const singleUse = true
|
||||||
cc, err := p.t.dialClientConn(addr, singleUse)
|
cc, err := p.t.dialClientConn(addr, singleUse)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -64,7 +86,10 @@ func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMis
|
|||||||
}
|
}
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
for _, cc := range p.conns[addr] {
|
for _, cc := range p.conns[addr] {
|
||||||
if cc.CanTakeNewRequest() {
|
if st := cc.idleState(); st.canTakeNewRequest {
|
||||||
|
if p.shouldTraceGetConn(st) {
|
||||||
|
traceGetConn(req, addr)
|
||||||
|
}
|
||||||
p.mu.Unlock()
|
p.mu.Unlock()
|
||||||
return cc, nil
|
return cc, nil
|
||||||
}
|
}
|
||||||
@ -73,6 +98,7 @@ func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMis
|
|||||||
p.mu.Unlock()
|
p.mu.Unlock()
|
||||||
return nil, ErrNoCachedConn
|
return nil, ErrNoCachedConn
|
||||||
}
|
}
|
||||||
|
traceGetConn(req, addr)
|
||||||
call := p.getStartDialLocked(addr)
|
call := p.getStartDialLocked(addr)
|
||||||
p.mu.Unlock()
|
p.mu.Unlock()
|
||||||
<-call.done
|
<-call.done
|
||||||
|
80
vendor/golang.org/x/net/http2/configure_transport.go
generated
vendored
80
vendor/golang.org/x/net/http2/configure_transport.go
generated
vendored
@ -1,80 +0,0 @@
|
|||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build go1.6
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func configureTransport(t1 *http.Transport) (*Transport, error) {
|
|
||||||
connPool := new(clientConnPool)
|
|
||||||
t2 := &Transport{
|
|
||||||
ConnPool: noDialClientConnPool{connPool},
|
|
||||||
t1: t1,
|
|
||||||
}
|
|
||||||
connPool.t = t2
|
|
||||||
if err := registerHTTPSProtocol(t1, noDialH2RoundTripper{t2}); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if t1.TLSClientConfig == nil {
|
|
||||||
t1.TLSClientConfig = new(tls.Config)
|
|
||||||
}
|
|
||||||
if !strSliceContains(t1.TLSClientConfig.NextProtos, "h2") {
|
|
||||||
t1.TLSClientConfig.NextProtos = append([]string{"h2"}, t1.TLSClientConfig.NextProtos...)
|
|
||||||
}
|
|
||||||
if !strSliceContains(t1.TLSClientConfig.NextProtos, "http/1.1") {
|
|
||||||
t1.TLSClientConfig.NextProtos = append(t1.TLSClientConfig.NextProtos, "http/1.1")
|
|
||||||
}
|
|
||||||
upgradeFn := func(authority string, c *tls.Conn) http.RoundTripper {
|
|
||||||
addr := authorityAddr("https", authority)
|
|
||||||
if used, err := connPool.addConnIfNeeded(addr, t2, c); err != nil {
|
|
||||||
go c.Close()
|
|
||||||
return erringRoundTripper{err}
|
|
||||||
} else if !used {
|
|
||||||
// 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 c.Close()
|
|
||||||
}
|
|
||||||
return t2
|
|
||||||
}
|
|
||||||
if m := t1.TLSNextProto; len(m) == 0 {
|
|
||||||
t1.TLSNextProto = map[string]func(string, *tls.Conn) http.RoundTripper{
|
|
||||||
"h2": upgradeFn,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
m["h2"] = upgradeFn
|
|
||||||
}
|
|
||||||
return t2, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// registerHTTPSProtocol calls Transport.RegisterProtocol but
|
|
||||||
// convering panics into errors.
|
|
||||||
func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error) {
|
|
||||||
defer func() {
|
|
||||||
if e := recover(); e != nil {
|
|
||||||
err = fmt.Errorf("%v", e)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
t.RegisterProtocol("https", rt)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// noDialH2RoundTripper is a RoundTripper which only tries to complete the request
|
|
||||||
// if there's already has a cached connection to the host.
|
|
||||||
type noDialH2RoundTripper struct{ t *Transport }
|
|
||||||
|
|
||||||
func (rt noDialH2RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
||||||
res, err := rt.t.RoundTrip(req)
|
|
||||||
if err == ErrNoCachedConn {
|
|
||||||
return nil, http.ErrSkipAltProtocol
|
|
||||||
}
|
|
||||||
return res, err
|
|
||||||
}
|
|
13
vendor/golang.org/x/net/http2/errors.go
generated
vendored
13
vendor/golang.org/x/net/http2/errors.go
generated
vendored
@ -87,13 +87,16 @@ type goAwayFlowError struct{}
|
|||||||
|
|
||||||
func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
|
func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
|
||||||
|
|
||||||
// connErrorReason wraps a ConnectionError with an informative error about why it occurs.
|
// 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
|
// Errors of this type are only returned by the frame parser functions
|
||||||
// and converted into ConnectionError(ErrCodeProtocol).
|
// and converted into ConnectionError(Code), after stashing away
|
||||||
|
// the Reason into the Framer's errDetail field, accessible via
|
||||||
|
// the (*Framer).ErrorDetail method.
|
||||||
type connError struct {
|
type connError struct {
|
||||||
Code ErrCode
|
Code ErrCode // the ConnectionError error code
|
||||||
Reason string
|
Reason string // additional reason
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e connError) Error() string {
|
func (e connError) Error() string {
|
||||||
|
10
vendor/golang.org/x/net/http2/flow.go
generated
vendored
10
vendor/golang.org/x/net/http2/flow.go
generated
vendored
@ -41,10 +41,10 @@ func (f *flow) take(n int32) {
|
|||||||
// add adds n bytes (positive or negative) to the flow control window.
|
// add adds n bytes (positive or negative) to the flow control window.
|
||||||
// It returns false if the sum would exceed 2^31-1.
|
// It returns false if the sum would exceed 2^31-1.
|
||||||
func (f *flow) add(n int32) bool {
|
func (f *flow) add(n int32) bool {
|
||||||
remain := (1<<31 - 1) - f.n
|
sum := f.n + n
|
||||||
if n > remain {
|
if (sum > n) == (f.n > 0) {
|
||||||
return false
|
f.n = sum
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
f.n += n
|
return false
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
71
vendor/golang.org/x/net/http2/frame.go
generated
vendored
71
vendor/golang.org/x/net/http2/frame.go
generated
vendored
@ -14,8 +14,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"golang.org/x/net/http/httpguts"
|
||||||
"golang.org/x/net/http2/hpack"
|
"golang.org/x/net/http2/hpack"
|
||||||
"golang.org/x/net/lex/httplex"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const frameHeaderLen = 9
|
const frameHeaderLen = 9
|
||||||
@ -643,7 +643,7 @@ func (f *Framer) WriteData(streamID uint32, endStream bool, data []byte) error {
|
|||||||
return f.WriteDataPadded(streamID, endStream, data, nil)
|
return f.WriteDataPadded(streamID, endStream, data, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteData writes a DATA frame with optional padding.
|
// WriteDataPadded writes a DATA frame with optional padding.
|
||||||
//
|
//
|
||||||
// If pad is nil, the padding bit is not sent.
|
// If pad is nil, the padding bit is not sent.
|
||||||
// The length of pad must not exceed 255 bytes.
|
// The length of pad must not exceed 255 bytes.
|
||||||
@ -733,32 +733,67 @@ func (f *SettingsFrame) IsAck() bool {
|
|||||||
return f.FrameHeader.Flags.Has(FlagSettingsAck)
|
return f.FrameHeader.Flags.Has(FlagSettingsAck)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *SettingsFrame) Value(s SettingID) (v uint32, ok bool) {
|
func (f *SettingsFrame) Value(id SettingID) (v uint32, ok bool) {
|
||||||
f.checkValid()
|
f.checkValid()
|
||||||
buf := f.p
|
for i := 0; i < f.NumSettings(); i++ {
|
||||||
for len(buf) > 0 {
|
if s := f.Setting(i); s.ID == id {
|
||||||
settingID := SettingID(binary.BigEndian.Uint16(buf[:2]))
|
return s.Val, true
|
||||||
if settingID == s {
|
|
||||||
return binary.BigEndian.Uint32(buf[2:6]), true
|
|
||||||
}
|
}
|
||||||
buf = buf[6:]
|
|
||||||
}
|
}
|
||||||
return 0, false
|
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 (f *SettingsFrame) Setting(i int) Setting {
|
||||||
|
buf := f.p
|
||||||
|
return Setting{
|
||||||
|
ID: SettingID(binary.BigEndian.Uint16(buf[i*6 : i*6+2])),
|
||||||
|
Val: binary.BigEndian.Uint32(buf[i*6+2 : i*6+6]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *SettingsFrame) NumSettings() int { return len(f.p) / 6 }
|
||||||
|
|
||||||
|
// HasDuplicates reports whether f contains any duplicate setting IDs.
|
||||||
|
func (f *SettingsFrame) HasDuplicates() bool {
|
||||||
|
num := f.NumSettings()
|
||||||
|
if num == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// If it's small enough (the common case), just do the n^2
|
||||||
|
// thing and avoid a map allocation.
|
||||||
|
if num < 10 {
|
||||||
|
for i := 0; i < num; i++ {
|
||||||
|
idi := f.Setting(i).ID
|
||||||
|
for j := i + 1; j < num; j++ {
|
||||||
|
idj := f.Setting(j).ID
|
||||||
|
if idi == idj {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
seen := map[SettingID]bool{}
|
||||||
|
for i := 0; i < num; i++ {
|
||||||
|
id := f.Setting(i).ID
|
||||||
|
if seen[id] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
seen[id] = true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// ForeachSetting runs fn for each setting.
|
// ForeachSetting runs fn for each setting.
|
||||||
// It stops and returns the first error.
|
// It stops and returns the first error.
|
||||||
func (f *SettingsFrame) ForeachSetting(fn func(Setting) error) error {
|
func (f *SettingsFrame) ForeachSetting(fn func(Setting) error) error {
|
||||||
f.checkValid()
|
f.checkValid()
|
||||||
buf := f.p
|
for i := 0; i < f.NumSettings(); i++ {
|
||||||
for len(buf) > 0 {
|
if err := fn(f.Setting(i)); err != nil {
|
||||||
if err := fn(Setting{
|
|
||||||
SettingID(binary.BigEndian.Uint16(buf[:2])),
|
|
||||||
binary.BigEndian.Uint32(buf[2:6]),
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
buf = buf[6:]
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -1442,7 +1477,7 @@ func (fr *Framer) maxHeaderStringLen() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// readMetaFrame returns 0 or more CONTINUATION frames from fr and
|
// readMetaFrame returns 0 or more CONTINUATION frames from fr and
|
||||||
// merge them into into the provided hf and returns a MetaHeadersFrame
|
// merge them into the provided hf and returns a MetaHeadersFrame
|
||||||
// with the decoded hpack values.
|
// with the decoded hpack values.
|
||||||
func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
|
func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
|
||||||
if fr.AllowIllegalReads {
|
if fr.AllowIllegalReads {
|
||||||
@ -1462,7 +1497,7 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
|
|||||||
if VerboseLogs && fr.logReads {
|
if VerboseLogs && fr.logReads {
|
||||||
fr.debugReadLoggerf("http2: decoded hpack field %+v", hf)
|
fr.debugReadLoggerf("http2: decoded hpack field %+v", hf)
|
||||||
}
|
}
|
||||||
if !httplex.ValidHeaderFieldValue(hf.Value) {
|
if !httpguts.ValidHeaderFieldValue(hf.Value) {
|
||||||
invalid = headerFieldValueError(hf.Value)
|
invalid = headerFieldValueError(hf.Value)
|
||||||
}
|
}
|
||||||
isPseudo := strings.HasPrefix(hf.Name, ":")
|
isPseudo := strings.HasPrefix(hf.Name, ":")
|
||||||
|
29
vendor/golang.org/x/net/http2/go111.go
generated
vendored
Normal file
29
vendor/golang.org/x/net/http2/go111.go
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.11
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http/httptrace"
|
||||||
|
"net/textproto"
|
||||||
|
)
|
||||||
|
|
||||||
|
func traceHasWroteHeaderField(trace *httptrace.ClientTrace) bool {
|
||||||
|
return trace != nil && trace.WroteHeaderField != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func traceWroteHeaderField(trace *httptrace.ClientTrace, k, v string) {
|
||||||
|
if trace != nil && trace.WroteHeaderField != nil {
|
||||||
|
trace.WroteHeaderField(k, []string{v})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func traceGot1xxResponseFunc(trace *httptrace.ClientTrace) func(int, textproto.MIMEHeader) error {
|
||||||
|
if trace != nil {
|
||||||
|
return trace.Got1xxResponse
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
43
vendor/golang.org/x/net/http2/go16.go
generated
vendored
43
vendor/golang.org/x/net/http2/go16.go
generated
vendored
@ -1,43 +0,0 @@
|
|||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build go1.6
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
|
|
||||||
return t1.ExpectContinueTimeout
|
|
||||||
}
|
|
||||||
|
|
||||||
// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
|
|
||||||
func isBadCipher(cipher uint16) bool {
|
|
||||||
switch cipher {
|
|
||||||
case tls.TLS_RSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
|
|
||||||
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
|
|
||||||
// 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"
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
106
vendor/golang.org/x/net/http2/go17.go
generated
vendored
106
vendor/golang.org/x/net/http2/go17.go
generated
vendored
@ -1,106 +0,0 @@
|
|||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build go1.7
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptrace"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type contextContext interface {
|
|
||||||
context.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx contextContext, cancel func()) {
|
|
||||||
ctx, cancel = context.WithCancel(context.Background())
|
|
||||||
ctx = context.WithValue(ctx, http.LocalAddrContextKey, c.LocalAddr())
|
|
||||||
if hs := opts.baseConfig(); hs != nil {
|
|
||||||
ctx = context.WithValue(ctx, http.ServerContextKey, hs)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func contextWithCancel(ctx contextContext) (_ contextContext, cancel func()) {
|
|
||||||
return context.WithCancel(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
func requestWithContext(req *http.Request, ctx contextContext) *http.Request {
|
|
||||||
return req.WithContext(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
type clientTrace httptrace.ClientTrace
|
|
||||||
|
|
||||||
func reqContext(r *http.Request) context.Context { return r.Context() }
|
|
||||||
|
|
||||||
func (t *Transport) idleConnTimeout() time.Duration {
|
|
||||||
if t.t1 != nil {
|
|
||||||
return t.t1.IdleConnTimeout
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func setResponseUncompressed(res *http.Response) { res.Uncompressed = true }
|
|
||||||
|
|
||||||
func traceGotConn(req *http.Request, cc *ClientConn) {
|
|
||||||
trace := httptrace.ContextClientTrace(req.Context())
|
|
||||||
if trace == nil || trace.GotConn == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ci := httptrace.GotConnInfo{Conn: cc.tconn}
|
|
||||||
cc.mu.Lock()
|
|
||||||
ci.Reused = cc.nextStreamID > 1
|
|
||||||
ci.WasIdle = len(cc.streams) == 0 && ci.Reused
|
|
||||||
if ci.WasIdle && !cc.lastActive.IsZero() {
|
|
||||||
ci.IdleTime = time.Now().Sub(cc.lastActive)
|
|
||||||
}
|
|
||||||
cc.mu.Unlock()
|
|
||||||
|
|
||||||
trace.GotConn(ci)
|
|
||||||
}
|
|
||||||
|
|
||||||
func traceWroteHeaders(trace *clientTrace) {
|
|
||||||
if trace != nil && trace.WroteHeaders != nil {
|
|
||||||
trace.WroteHeaders()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func traceGot100Continue(trace *clientTrace) {
|
|
||||||
if trace != nil && trace.Got100Continue != nil {
|
|
||||||
trace.Got100Continue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func traceWait100Continue(trace *clientTrace) {
|
|
||||||
if trace != nil && trace.Wait100Continue != nil {
|
|
||||||
trace.Wait100Continue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func traceWroteRequest(trace *clientTrace, err error) {
|
|
||||||
if trace != nil && trace.WroteRequest != nil {
|
|
||||||
trace.WroteRequest(httptrace.WroteRequestInfo{Err: err})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func traceFirstResponseByte(trace *clientTrace) {
|
|
||||||
if trace != nil && trace.GotFirstResponseByte != nil {
|
|
||||||
trace.GotFirstResponseByte()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func requestTrace(req *http.Request) *clientTrace {
|
|
||||||
trace := httptrace.ContextClientTrace(req.Context())
|
|
||||||
return (*clientTrace)(trace)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ping sends a PING frame to the server and waits for the ack.
|
|
||||||
func (cc *ClientConn) Ping(ctx context.Context) error {
|
|
||||||
return cc.ping(ctx)
|
|
||||||
}
|
|
36
vendor/golang.org/x/net/http2/go17_not18.go
generated
vendored
36
vendor/golang.org/x/net/http2/go17_not18.go
generated
vendored
@ -1,36 +0,0 @@
|
|||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build go1.7,!go1.8
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import "crypto/tls"
|
|
||||||
|
|
||||||
// temporary copy of Go 1.7's private tls.Config.clone:
|
|
||||||
func cloneTLSConfig(c *tls.Config) *tls.Config {
|
|
||||||
return &tls.Config{
|
|
||||||
Rand: c.Rand,
|
|
||||||
Time: c.Time,
|
|
||||||
Certificates: c.Certificates,
|
|
||||||
NameToCertificate: c.NameToCertificate,
|
|
||||||
GetCertificate: c.GetCertificate,
|
|
||||||
RootCAs: c.RootCAs,
|
|
||||||
NextProtos: c.NextProtos,
|
|
||||||
ServerName: c.ServerName,
|
|
||||||
ClientAuth: c.ClientAuth,
|
|
||||||
ClientCAs: c.ClientCAs,
|
|
||||||
InsecureSkipVerify: c.InsecureSkipVerify,
|
|
||||||
CipherSuites: c.CipherSuites,
|
|
||||||
PreferServerCipherSuites: c.PreferServerCipherSuites,
|
|
||||||
SessionTicketsDisabled: c.SessionTicketsDisabled,
|
|
||||||
SessionTicketKey: c.SessionTicketKey,
|
|
||||||
ClientSessionCache: c.ClientSessionCache,
|
|
||||||
MinVersion: c.MinVersion,
|
|
||||||
MaxVersion: c.MaxVersion,
|
|
||||||
CurvePreferences: c.CurvePreferences,
|
|
||||||
DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled,
|
|
||||||
Renegotiation: c.Renegotiation,
|
|
||||||
}
|
|
||||||
}
|
|
54
vendor/golang.org/x/net/http2/go18.go
generated
vendored
54
vendor/golang.org/x/net/http2/go18.go
generated
vendored
@ -1,54 +0,0 @@
|
|||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build go1.8
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func cloneTLSConfig(c *tls.Config) *tls.Config {
|
|
||||||
c2 := c.Clone()
|
|
||||||
c2.GetClientCertificate = c.GetClientCertificate // golang.org/issue/19264
|
|
||||||
return c2
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ http.Pusher = (*responseWriter)(nil)
|
|
||||||
|
|
||||||
// Push implements http.Pusher.
|
|
||||||
func (w *responseWriter) Push(target string, opts *http.PushOptions) error {
|
|
||||||
internalOpts := pushOptions{}
|
|
||||||
if opts != nil {
|
|
||||||
internalOpts.Method = opts.Method
|
|
||||||
internalOpts.Header = opts.Header
|
|
||||||
}
|
|
||||||
return w.push(target, internalOpts)
|
|
||||||
}
|
|
||||||
|
|
||||||
func configureServer18(h1 *http.Server, h2 *Server) error {
|
|
||||||
if h2.IdleTimeout == 0 {
|
|
||||||
if h1.IdleTimeout != 0 {
|
|
||||||
h2.IdleTimeout = h1.IdleTimeout
|
|
||||||
} else {
|
|
||||||
h2.IdleTimeout = h1.ReadTimeout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func shouldLogPanic(panicValue interface{}) bool {
|
|
||||||
return panicValue != nil && panicValue != http.ErrAbortHandler
|
|
||||||
}
|
|
||||||
|
|
||||||
func reqGetBody(req *http.Request) func() (io.ReadCloser, error) {
|
|
||||||
return req.GetBody
|
|
||||||
}
|
|
||||||
|
|
||||||
func reqBodyIsNoBody(body io.ReadCloser) bool {
|
|
||||||
return body == http.NoBody
|
|
||||||
}
|
|
20
vendor/golang.org/x/net/http2/headermap.go
generated
vendored
20
vendor/golang.org/x/net/http2/headermap.go
generated
vendored
@ -7,15 +7,21 @@ package http2
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
commonLowerHeader = map[string]string{} // Go-Canonical-Case -> lower-case
|
commonBuildOnce sync.Once
|
||||||
commonCanonHeader = map[string]string{} // lower-case -> Go-Canonical-Case
|
commonLowerHeader map[string]string // Go-Canonical-Case -> lower-case
|
||||||
|
commonCanonHeader map[string]string // lower-case -> Go-Canonical-Case
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func buildCommonHeaderMapsOnce() {
|
||||||
for _, v := range []string{
|
commonBuildOnce.Do(buildCommonHeaderMaps)
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildCommonHeaderMaps() {
|
||||||
|
common := []string{
|
||||||
"accept",
|
"accept",
|
||||||
"accept-charset",
|
"accept-charset",
|
||||||
"accept-encoding",
|
"accept-encoding",
|
||||||
@ -63,7 +69,10 @@ func init() {
|
|||||||
"vary",
|
"vary",
|
||||||
"via",
|
"via",
|
||||||
"www-authenticate",
|
"www-authenticate",
|
||||||
} {
|
}
|
||||||
|
commonLowerHeader = make(map[string]string, len(common))
|
||||||
|
commonCanonHeader = make(map[string]string, len(common))
|
||||||
|
for _, v := range common {
|
||||||
chk := http.CanonicalHeaderKey(v)
|
chk := http.CanonicalHeaderKey(v)
|
||||||
commonLowerHeader[chk] = v
|
commonLowerHeader[chk] = v
|
||||||
commonCanonHeader[v] = chk
|
commonCanonHeader[v] = chk
|
||||||
@ -71,6 +80,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func lowerHeader(v string) string {
|
func lowerHeader(v string) string {
|
||||||
|
buildCommonHeaderMapsOnce()
|
||||||
if s, ok := commonLowerHeader[v]; ok {
|
if s, ok := commonLowerHeader[v]; ok {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
33
vendor/golang.org/x/net/http2/http2.go
generated
vendored
33
vendor/golang.org/x/net/http2/http2.go
generated
vendored
@ -29,7 +29,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"golang.org/x/net/lex/httplex"
|
"golang.org/x/net/http/httpguts"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -179,7 +179,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// validWireHeaderFieldName reports whether v is a valid header field
|
// validWireHeaderFieldName reports whether v is a valid header field
|
||||||
// name (key). See httplex.ValidHeaderName for the base rules.
|
// name (key). See httpguts.ValidHeaderName for the base rules.
|
||||||
//
|
//
|
||||||
// Further, http2 says:
|
// Further, http2 says:
|
||||||
// "Just as in HTTP/1.x, header field names are strings of ASCII
|
// "Just as in HTTP/1.x, header field names are strings of ASCII
|
||||||
@ -191,7 +191,7 @@ func validWireHeaderFieldName(v string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, r := range v {
|
for _, r := range v {
|
||||||
if !httplex.IsTokenRune(r) {
|
if !httpguts.IsTokenRune(r) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if 'A' <= r && r <= 'Z' {
|
if 'A' <= r && r <= 'Z' {
|
||||||
@ -201,19 +201,12 @@ func validWireHeaderFieldName(v string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
var httpCodeStringCommon = map[int]string{} // n -> strconv.Itoa(n)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
for i := 100; i <= 999; i++ {
|
|
||||||
if v := http.StatusText(i); v != "" {
|
|
||||||
httpCodeStringCommon[i] = strconv.Itoa(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func httpCodeString(code int) string {
|
func httpCodeString(code int) string {
|
||||||
if s, ok := httpCodeStringCommon[code]; ok {
|
switch code {
|
||||||
return s
|
case 200:
|
||||||
|
return "200"
|
||||||
|
case 404:
|
||||||
|
return "404"
|
||||||
}
|
}
|
||||||
return strconv.Itoa(code)
|
return strconv.Itoa(code)
|
||||||
}
|
}
|
||||||
@ -312,7 +305,7 @@ func mustUint31(v int32) uint32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// bodyAllowedForStatus reports whether a given response status code
|
// bodyAllowedForStatus reports whether a given response status code
|
||||||
// permits a body. See RFC 2616, section 4.4.
|
// permits a body. See RFC 7230, section 3.3.
|
||||||
func bodyAllowedForStatus(status int) bool {
|
func bodyAllowedForStatus(status int) bool {
|
||||||
switch {
|
switch {
|
||||||
case status >= 100 && status <= 199:
|
case status >= 100 && status <= 199:
|
||||||
@ -376,12 +369,16 @@ func (s *sorter) SortStrings(ss []string) {
|
|||||||
// validPseudoPath reports whether v is a valid :path pseudo-header
|
// validPseudoPath reports whether v is a valid :path pseudo-header
|
||||||
// value. It must be either:
|
// value. It must be either:
|
||||||
//
|
//
|
||||||
// *) a non-empty string starting with '/', but not with with "//",
|
// *) a non-empty string starting with '/'
|
||||||
// *) the string '*', for OPTIONS requests.
|
// *) the string '*', for OPTIONS requests.
|
||||||
//
|
//
|
||||||
// For now this is only used a quick check for deciding when to clean
|
// For now this is only used a quick check for deciding when to clean
|
||||||
// up Opaque URLs before sending requests from the Transport.
|
// up Opaque URLs before sending requests from the Transport.
|
||||||
// See golang.org/issue/16847
|
// See golang.org/issue/16847
|
||||||
|
//
|
||||||
|
// We used to enforce that the path also didn't start with "//", but
|
||||||
|
// Google's GFE accepts such paths and Chrome sends them, so ignore
|
||||||
|
// that part of the spec. See golang.org/issue/19103.
|
||||||
func validPseudoPath(v string) bool {
|
func validPseudoPath(v string) bool {
|
||||||
return (len(v) > 0 && v[0] == '/' && (len(v) == 1 || v[1] != '/')) || v == "*"
|
return (len(v) > 0 && v[0] == '/') || v == "*"
|
||||||
}
|
}
|
||||||
|
20
vendor/golang.org/x/net/http2/not_go111.go
generated
vendored
Normal file
20
vendor/golang.org/x/net/http2/not_go111.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !go1.11
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http/httptrace"
|
||||||
|
"net/textproto"
|
||||||
|
)
|
||||||
|
|
||||||
|
func traceHasWroteHeaderField(trace *httptrace.ClientTrace) bool { return false }
|
||||||
|
|
||||||
|
func traceWroteHeaderField(trace *httptrace.ClientTrace, k, v string) {}
|
||||||
|
|
||||||
|
func traceGot1xxResponseFunc(trace *httptrace.ClientTrace) func(int, textproto.MIMEHeader) error {
|
||||||
|
return nil
|
||||||
|
}
|
46
vendor/golang.org/x/net/http2/not_go16.go
generated
vendored
46
vendor/golang.org/x/net/http2/not_go16.go
generated
vendored
@ -1,46 +0,0 @@
|
|||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build !go1.6
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func configureTransport(t1 *http.Transport) (*Transport, error) {
|
|
||||||
return nil, errTransportVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
|
|
||||||
return 0
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
|
|
||||||
func isBadCipher(cipher uint16) bool {
|
|
||||||
switch cipher {
|
|
||||||
case tls.TLS_RSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
|
|
||||||
// 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"
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
87
vendor/golang.org/x/net/http2/not_go17.go
generated
vendored
87
vendor/golang.org/x/net/http2/not_go17.go
generated
vendored
@ -1,87 +0,0 @@
|
|||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build !go1.7
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type contextContext interface {
|
|
||||||
Done() <-chan struct{}
|
|
||||||
Err() error
|
|
||||||
}
|
|
||||||
|
|
||||||
type fakeContext struct{}
|
|
||||||
|
|
||||||
func (fakeContext) Done() <-chan struct{} { return nil }
|
|
||||||
func (fakeContext) Err() error { panic("should not be called") }
|
|
||||||
|
|
||||||
func reqContext(r *http.Request) fakeContext {
|
|
||||||
return fakeContext{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setResponseUncompressed(res *http.Response) {
|
|
||||||
// Nothing.
|
|
||||||
}
|
|
||||||
|
|
||||||
type clientTrace struct{}
|
|
||||||
|
|
||||||
func requestTrace(*http.Request) *clientTrace { return nil }
|
|
||||||
func traceGotConn(*http.Request, *ClientConn) {}
|
|
||||||
func traceFirstResponseByte(*clientTrace) {}
|
|
||||||
func traceWroteHeaders(*clientTrace) {}
|
|
||||||
func traceWroteRequest(*clientTrace, error) {}
|
|
||||||
func traceGot100Continue(trace *clientTrace) {}
|
|
||||||
func traceWait100Continue(trace *clientTrace) {}
|
|
||||||
|
|
||||||
func nop() {}
|
|
||||||
|
|
||||||
func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx contextContext, cancel func()) {
|
|
||||||
return nil, nop
|
|
||||||
}
|
|
||||||
|
|
||||||
func contextWithCancel(ctx contextContext) (_ contextContext, cancel func()) {
|
|
||||||
return ctx, nop
|
|
||||||
}
|
|
||||||
|
|
||||||
func requestWithContext(req *http.Request, ctx contextContext) *http.Request {
|
|
||||||
return req
|
|
||||||
}
|
|
||||||
|
|
||||||
// temporary copy of Go 1.6's private tls.Config.clone:
|
|
||||||
func cloneTLSConfig(c *tls.Config) *tls.Config {
|
|
||||||
return &tls.Config{
|
|
||||||
Rand: c.Rand,
|
|
||||||
Time: c.Time,
|
|
||||||
Certificates: c.Certificates,
|
|
||||||
NameToCertificate: c.NameToCertificate,
|
|
||||||
GetCertificate: c.GetCertificate,
|
|
||||||
RootCAs: c.RootCAs,
|
|
||||||
NextProtos: c.NextProtos,
|
|
||||||
ServerName: c.ServerName,
|
|
||||||
ClientAuth: c.ClientAuth,
|
|
||||||
ClientCAs: c.ClientCAs,
|
|
||||||
InsecureSkipVerify: c.InsecureSkipVerify,
|
|
||||||
CipherSuites: c.CipherSuites,
|
|
||||||
PreferServerCipherSuites: c.PreferServerCipherSuites,
|
|
||||||
SessionTicketsDisabled: c.SessionTicketsDisabled,
|
|
||||||
SessionTicketKey: c.SessionTicketKey,
|
|
||||||
ClientSessionCache: c.ClientSessionCache,
|
|
||||||
MinVersion: c.MinVersion,
|
|
||||||
MaxVersion: c.MaxVersion,
|
|
||||||
CurvePreferences: c.CurvePreferences,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cc *ClientConn) Ping(ctx contextContext) error {
|
|
||||||
return cc.ping(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Transport) idleConnTimeout() time.Duration { return 0 }
|
|
27
vendor/golang.org/x/net/http2/not_go18.go
generated
vendored
27
vendor/golang.org/x/net/http2/not_go18.go
generated
vendored
@ -1,27 +0,0 @@
|
|||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build !go1.8
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func configureServer18(h1 *http.Server, h2 *Server) error {
|
|
||||||
// No IdleTimeout to sync prior to Go 1.8.
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func shouldLogPanic(panicValue interface{}) bool {
|
|
||||||
return panicValue != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func reqGetBody(req *http.Request) func() (io.ReadCloser, error) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func reqBodyIsNoBody(io.ReadCloser) bool { return false }
|
|
16
vendor/golang.org/x/net/http2/pipe.go
generated
vendored
16
vendor/golang.org/x/net/http2/pipe.go
generated
vendored
@ -15,8 +15,8 @@ import (
|
|||||||
// underlying buffer is an interface. (io.Pipe is always unbuffered)
|
// underlying buffer is an interface. (io.Pipe is always unbuffered)
|
||||||
type pipe struct {
|
type pipe struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
c sync.Cond // c.L lazily initialized to &p.mu
|
c sync.Cond // c.L lazily initialized to &p.mu
|
||||||
b pipeBuffer
|
b pipeBuffer // nil when done reading
|
||||||
err error // read error once empty. non-nil means closed.
|
err error // read error once empty. non-nil means closed.
|
||||||
breakErr error // immediate read error (caller doesn't see rest of b)
|
breakErr error // immediate read error (caller doesn't see rest of b)
|
||||||
donec chan struct{} // closed on error
|
donec chan struct{} // closed on error
|
||||||
@ -32,6 +32,9 @@ type pipeBuffer interface {
|
|||||||
func (p *pipe) Len() int {
|
func (p *pipe) Len() int {
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
defer p.mu.Unlock()
|
defer p.mu.Unlock()
|
||||||
|
if p.b == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
return p.b.Len()
|
return p.b.Len()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +50,7 @@ func (p *pipe) Read(d []byte) (n int, err error) {
|
|||||||
if p.breakErr != nil {
|
if p.breakErr != nil {
|
||||||
return 0, p.breakErr
|
return 0, p.breakErr
|
||||||
}
|
}
|
||||||
if p.b.Len() > 0 {
|
if p.b != nil && p.b.Len() > 0 {
|
||||||
return p.b.Read(d)
|
return p.b.Read(d)
|
||||||
}
|
}
|
||||||
if p.err != nil {
|
if p.err != nil {
|
||||||
@ -55,6 +58,7 @@ func (p *pipe) Read(d []byte) (n int, err error) {
|
|||||||
p.readFn() // e.g. copy trailers
|
p.readFn() // e.g. copy trailers
|
||||||
p.readFn = nil // not sticky like p.err
|
p.readFn = nil // not sticky like p.err
|
||||||
}
|
}
|
||||||
|
p.b = nil
|
||||||
return 0, p.err
|
return 0, p.err
|
||||||
}
|
}
|
||||||
p.c.Wait()
|
p.c.Wait()
|
||||||
@ -75,6 +79,9 @@ func (p *pipe) Write(d []byte) (n int, err error) {
|
|||||||
if p.err != nil {
|
if p.err != nil {
|
||||||
return 0, errClosedPipeWrite
|
return 0, errClosedPipeWrite
|
||||||
}
|
}
|
||||||
|
if p.breakErr != nil {
|
||||||
|
return len(d), nil // discard when there is no reader
|
||||||
|
}
|
||||||
return p.b.Write(d)
|
return p.b.Write(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,6 +116,9 @@ func (p *pipe) closeWithError(dst *error, err error, fn func()) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.readFn = fn
|
p.readFn = fn
|
||||||
|
if dst == &p.breakErr {
|
||||||
|
p.b = nil
|
||||||
|
}
|
||||||
*dst = err
|
*dst = err
|
||||||
p.closeDoneLocked()
|
p.closeDoneLocked()
|
||||||
}
|
}
|
||||||
|
427
vendor/golang.org/x/net/http2/server.go
generated
vendored
427
vendor/golang.org/x/net/http2/server.go
generated
vendored
@ -28,6 +28,7 @@ package http2
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -46,6 +47,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/http/httpguts"
|
||||||
"golang.org/x/net/http2/hpack"
|
"golang.org/x/net/http2/hpack"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -126,6 +128,11 @@ type Server struct {
|
|||||||
// NewWriteScheduler constructs a write scheduler for a connection.
|
// NewWriteScheduler constructs a write scheduler for a connection.
|
||||||
// If nil, a default scheduler is chosen.
|
// If nil, a default scheduler is chosen.
|
||||||
NewWriteScheduler func() WriteScheduler
|
NewWriteScheduler func() WriteScheduler
|
||||||
|
|
||||||
|
// Internal state. This is a pointer (rather than embedded directly)
|
||||||
|
// so that we don't embed a Mutex in this struct, which will make the
|
||||||
|
// struct non-copyable, which might break some callers.
|
||||||
|
state *serverInternalState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) initialConnRecvWindowSize() int32 {
|
func (s *Server) initialConnRecvWindowSize() int32 {
|
||||||
@ -156,6 +163,40 @@ func (s *Server) maxConcurrentStreams() uint32 {
|
|||||||
return defaultMaxStreams
|
return defaultMaxStreams
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type serverInternalState struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
activeConns map[*serverConn]struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *serverInternalState) registerConn(sc *serverConn) {
|
||||||
|
if s == nil {
|
||||||
|
return // if the Server was used without calling ConfigureServer
|
||||||
|
}
|
||||||
|
s.mu.Lock()
|
||||||
|
s.activeConns[sc] = struct{}{}
|
||||||
|
s.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *serverInternalState) unregisterConn(sc *serverConn) {
|
||||||
|
if s == nil {
|
||||||
|
return // if the Server was used without calling ConfigureServer
|
||||||
|
}
|
||||||
|
s.mu.Lock()
|
||||||
|
delete(s.activeConns, sc)
|
||||||
|
s.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *serverInternalState) startGracefulShutdown() {
|
||||||
|
if s == nil {
|
||||||
|
return // if the Server was used without calling ConfigureServer
|
||||||
|
}
|
||||||
|
s.mu.Lock()
|
||||||
|
for sc := range s.activeConns {
|
||||||
|
sc.startGracefulShutdown()
|
||||||
|
}
|
||||||
|
s.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
// ConfigureServer adds HTTP/2 support to a net/http Server.
|
// ConfigureServer adds HTTP/2 support to a net/http Server.
|
||||||
//
|
//
|
||||||
// The configuration conf may be nil.
|
// The configuration conf may be nil.
|
||||||
@ -168,21 +209,30 @@ func ConfigureServer(s *http.Server, conf *Server) error {
|
|||||||
if conf == nil {
|
if conf == nil {
|
||||||
conf = new(Server)
|
conf = new(Server)
|
||||||
}
|
}
|
||||||
if err := configureServer18(s, conf); err != nil {
|
conf.state = &serverInternalState{activeConns: make(map[*serverConn]struct{})}
|
||||||
return err
|
if h1, h2 := s, conf; h2.IdleTimeout == 0 {
|
||||||
|
if h1.IdleTimeout != 0 {
|
||||||
|
h2.IdleTimeout = h1.IdleTimeout
|
||||||
|
} else {
|
||||||
|
h2.IdleTimeout = h1.ReadTimeout
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
s.RegisterOnShutdown(conf.state.startGracefulShutdown)
|
||||||
|
|
||||||
if s.TLSConfig == nil {
|
if s.TLSConfig == nil {
|
||||||
s.TLSConfig = new(tls.Config)
|
s.TLSConfig = new(tls.Config)
|
||||||
} else if s.TLSConfig.CipherSuites != nil {
|
} else if s.TLSConfig.CipherSuites != nil {
|
||||||
// If they already provided a CipherSuite list, return
|
// If they already provided a CipherSuite list, return
|
||||||
// an error if it has a bad order or is missing
|
// an error if it has a bad order or is missing
|
||||||
// ECDHE_RSA_WITH_AES_128_GCM_SHA256.
|
// ECDHE_RSA_WITH_AES_128_GCM_SHA256 or ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
|
||||||
const requiredCipher = tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
|
|
||||||
haveRequired := false
|
haveRequired := false
|
||||||
sawBad := false
|
sawBad := false
|
||||||
for i, cs := range s.TLSConfig.CipherSuites {
|
for i, cs := range s.TLSConfig.CipherSuites {
|
||||||
if cs == requiredCipher {
|
switch cs {
|
||||||
|
case tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
// Alternative MTI cipher to not discourage ECDSA-only servers.
|
||||||
|
// See http://golang.org/cl/30721 for further information.
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
|
||||||
haveRequired = true
|
haveRequired = true
|
||||||
}
|
}
|
||||||
if isBadCipher(cs) {
|
if isBadCipher(cs) {
|
||||||
@ -192,7 +242,7 @@ func ConfigureServer(s *http.Server, conf *Server) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !haveRequired {
|
if !haveRequired {
|
||||||
return fmt.Errorf("http2: TLSConfig.CipherSuites is missing HTTP/2-required TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")
|
return fmt.Errorf("http2: TLSConfig.CipherSuites is missing an HTTP/2-required AES_128_GCM_SHA256 cipher.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,7 +342,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
|||||||
streams: make(map[uint32]*stream),
|
streams: make(map[uint32]*stream),
|
||||||
readFrameCh: make(chan readFrameResult),
|
readFrameCh: make(chan readFrameResult),
|
||||||
wantWriteFrameCh: make(chan FrameWriteRequest, 8),
|
wantWriteFrameCh: make(chan FrameWriteRequest, 8),
|
||||||
wantStartPushCh: make(chan startPushRequest, 8),
|
serveMsgCh: make(chan interface{}, 8),
|
||||||
wroteFrameCh: make(chan frameWriteResult, 1), // buffered; one send in writeFrameAsync
|
wroteFrameCh: make(chan frameWriteResult, 1), // buffered; one send in writeFrameAsync
|
||||||
bodyReadCh: make(chan bodyReadMsg), // buffering doesn't matter either way
|
bodyReadCh: make(chan bodyReadMsg), // buffering doesn't matter either way
|
||||||
doneServing: make(chan struct{}),
|
doneServing: make(chan struct{}),
|
||||||
@ -305,6 +355,9 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
|||||||
pushEnabled: true,
|
pushEnabled: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.state.registerConn(sc)
|
||||||
|
defer s.state.unregisterConn(sc)
|
||||||
|
|
||||||
// The net/http package sets the write deadline from the
|
// The net/http package sets the write deadline from the
|
||||||
// http.Server.WriteTimeout during the TLS handshake, but then
|
// http.Server.WriteTimeout during the TLS handshake, but then
|
||||||
// passes the connection off to us with the deadline already set.
|
// passes the connection off to us with the deadline already set.
|
||||||
@ -357,7 +410,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
|||||||
// addresses during development.
|
// addresses during development.
|
||||||
//
|
//
|
||||||
// TODO: optionally enforce? Or enforce at the time we receive
|
// TODO: optionally enforce? Or enforce at the time we receive
|
||||||
// a new request, and verify the the ServerName matches the :authority?
|
// a new request, and verify the ServerName matches the :authority?
|
||||||
// But that precludes proxy situations, perhaps.
|
// But that precludes proxy situations, perhaps.
|
||||||
//
|
//
|
||||||
// So for now, do nothing here again.
|
// So for now, do nothing here again.
|
||||||
@ -385,6 +438,15 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
|||||||
sc.serve()
|
sc.serve()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx context.Context, cancel func()) {
|
||||||
|
ctx, cancel = context.WithCancel(context.Background())
|
||||||
|
ctx = context.WithValue(ctx, http.LocalAddrContextKey, c.LocalAddr())
|
||||||
|
if hs := opts.baseConfig(); hs != nil {
|
||||||
|
ctx = context.WithValue(ctx, http.ServerContextKey, hs)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (sc *serverConn) rejectConn(err ErrCode, debug string) {
|
func (sc *serverConn) rejectConn(err ErrCode, debug string) {
|
||||||
sc.vlogf("http2: server rejecting conn: %v, %s", err, debug)
|
sc.vlogf("http2: server rejecting conn: %v, %s", err, debug)
|
||||||
// ignoring errors. hanging up anyway.
|
// ignoring errors. hanging up anyway.
|
||||||
@ -400,15 +462,14 @@ type serverConn struct {
|
|||||||
conn net.Conn
|
conn net.Conn
|
||||||
bw *bufferedWriter // writing to conn
|
bw *bufferedWriter // writing to conn
|
||||||
handler http.Handler
|
handler http.Handler
|
||||||
baseCtx contextContext
|
baseCtx context.Context
|
||||||
framer *Framer
|
framer *Framer
|
||||||
doneServing chan struct{} // closed when serverConn.serve ends
|
doneServing chan struct{} // closed when serverConn.serve ends
|
||||||
readFrameCh chan readFrameResult // written by serverConn.readFrames
|
readFrameCh chan readFrameResult // written by serverConn.readFrames
|
||||||
wantWriteFrameCh chan FrameWriteRequest // from handlers -> serve
|
wantWriteFrameCh chan FrameWriteRequest // from handlers -> serve
|
||||||
wantStartPushCh chan startPushRequest // from handlers -> serve
|
|
||||||
wroteFrameCh chan frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
|
wroteFrameCh chan frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
|
||||||
bodyReadCh chan bodyReadMsg // from handlers -> serve
|
bodyReadCh chan bodyReadMsg // from handlers -> serve
|
||||||
testHookCh chan func(int) // code to run on the serve loop
|
serveMsgCh chan interface{} // misc messages & code to send to / run on the serve loop
|
||||||
flow flow // conn-wide (not stream-specific) outbound flow control
|
flow flow // conn-wide (not stream-specific) outbound flow control
|
||||||
inflow flow // conn-wide inbound flow control
|
inflow flow // conn-wide inbound flow control
|
||||||
tlsState *tls.ConnectionState // shared by all handlers, like net/http
|
tlsState *tls.ConnectionState // shared by all handlers, like net/http
|
||||||
@ -440,14 +501,15 @@ type serverConn struct {
|
|||||||
inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop
|
inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop
|
||||||
needToSendGoAway bool // we need to schedule a GOAWAY frame write
|
needToSendGoAway bool // we need to schedule a GOAWAY frame write
|
||||||
goAwayCode ErrCode
|
goAwayCode ErrCode
|
||||||
shutdownTimerCh <-chan time.Time // nil until used
|
shutdownTimer *time.Timer // nil until used
|
||||||
shutdownTimer *time.Timer // nil until used
|
idleTimer *time.Timer // nil if unused
|
||||||
idleTimer *time.Timer // nil if unused
|
|
||||||
idleTimerCh <-chan time.Time // nil if unused
|
|
||||||
|
|
||||||
// Owned by the writeFrameAsync goroutine:
|
// Owned by the writeFrameAsync goroutine:
|
||||||
headerWriteBuf bytes.Buffer
|
headerWriteBuf bytes.Buffer
|
||||||
hpackEncoder *hpack.Encoder
|
hpackEncoder *hpack.Encoder
|
||||||
|
|
||||||
|
// Used by startGracefulShutdown.
|
||||||
|
shutdownOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *serverConn) maxHeaderListSize() uint32 {
|
func (sc *serverConn) maxHeaderListSize() uint32 {
|
||||||
@ -480,7 +542,7 @@ type stream struct {
|
|||||||
id uint32
|
id uint32
|
||||||
body *pipe // non-nil if expecting DATA frames
|
body *pipe // non-nil if expecting DATA frames
|
||||||
cw closeWaiter // closed wait stream transitions to closed state
|
cw closeWaiter // closed wait stream transitions to closed state
|
||||||
ctx contextContext
|
ctx context.Context
|
||||||
cancelCtx func()
|
cancelCtx func()
|
||||||
|
|
||||||
// owned by serverConn's serve loop:
|
// owned by serverConn's serve loop:
|
||||||
@ -603,7 +665,7 @@ func (sc *serverConn) condlogf(err error, format string, args ...interface{}) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err) {
|
if err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err) || err == errPrefaceTimeout {
|
||||||
// Boring, expected errors.
|
// Boring, expected errors.
|
||||||
sc.vlogf(format, args...)
|
sc.vlogf(format, args...)
|
||||||
} else {
|
} else {
|
||||||
@ -613,6 +675,7 @@ func (sc *serverConn) condlogf(err error, format string, args ...interface{}) {
|
|||||||
|
|
||||||
func (sc *serverConn) canonicalHeader(v string) string {
|
func (sc *serverConn) canonicalHeader(v string) string {
|
||||||
sc.serveG.check()
|
sc.serveG.check()
|
||||||
|
buildCommonHeaderMapsOnce()
|
||||||
cv, ok := commonCanonHeader[v]
|
cv, ok := commonCanonHeader[v]
|
||||||
if ok {
|
if ok {
|
||||||
return cv
|
return cv
|
||||||
@ -748,19 +811,15 @@ func (sc *serverConn) serve() {
|
|||||||
sc.setConnState(http.StateIdle)
|
sc.setConnState(http.StateIdle)
|
||||||
|
|
||||||
if sc.srv.IdleTimeout != 0 {
|
if sc.srv.IdleTimeout != 0 {
|
||||||
sc.idleTimer = time.NewTimer(sc.srv.IdleTimeout)
|
sc.idleTimer = time.AfterFunc(sc.srv.IdleTimeout, sc.onIdleTimer)
|
||||||
defer sc.idleTimer.Stop()
|
defer sc.idleTimer.Stop()
|
||||||
sc.idleTimerCh = sc.idleTimer.C
|
|
||||||
}
|
|
||||||
|
|
||||||
var gracefulShutdownCh <-chan struct{}
|
|
||||||
if sc.hs != nil {
|
|
||||||
gracefulShutdownCh = h1ServerShutdownChan(sc.hs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
go sc.readFrames() // closed by defer sc.conn.Close above
|
go sc.readFrames() // closed by defer sc.conn.Close above
|
||||||
|
|
||||||
settingsTimer := time.NewTimer(firstSettingsTimeout)
|
settingsTimer := time.AfterFunc(firstSettingsTimeout, sc.onSettingsTimer)
|
||||||
|
defer settingsTimer.Stop()
|
||||||
|
|
||||||
loopNum := 0
|
loopNum := 0
|
||||||
for {
|
for {
|
||||||
loopNum++
|
loopNum++
|
||||||
@ -771,8 +830,6 @@ func (sc *serverConn) serve() {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
sc.writeFrame(wr)
|
sc.writeFrame(wr)
|
||||||
case spr := <-sc.wantStartPushCh:
|
|
||||||
sc.startPush(spr)
|
|
||||||
case res := <-sc.wroteFrameCh:
|
case res := <-sc.wroteFrameCh:
|
||||||
sc.wroteFrame(res)
|
sc.wroteFrame(res)
|
||||||
case res := <-sc.readFrameCh:
|
case res := <-sc.readFrameCh:
|
||||||
@ -780,36 +837,85 @@ func (sc *serverConn) serve() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
res.readMore()
|
res.readMore()
|
||||||
if settingsTimer.C != nil {
|
if settingsTimer != nil {
|
||||||
settingsTimer.Stop()
|
settingsTimer.Stop()
|
||||||
settingsTimer.C = nil
|
settingsTimer = nil
|
||||||
}
|
}
|
||||||
case m := <-sc.bodyReadCh:
|
case m := <-sc.bodyReadCh:
|
||||||
sc.noteBodyRead(m.st, m.n)
|
sc.noteBodyRead(m.st, m.n)
|
||||||
case <-settingsTimer.C:
|
case msg := <-sc.serveMsgCh:
|
||||||
sc.logf("timeout waiting for SETTINGS frames from %v", sc.conn.RemoteAddr())
|
switch v := msg.(type) {
|
||||||
return
|
case func(int):
|
||||||
case <-gracefulShutdownCh:
|
v(loopNum) // for testing
|
||||||
gracefulShutdownCh = nil
|
case *serverMessage:
|
||||||
sc.startGracefulShutdown()
|
switch v {
|
||||||
case <-sc.shutdownTimerCh:
|
case settingsTimerMsg:
|
||||||
sc.vlogf("GOAWAY close timer fired; closing conn from %v", sc.conn.RemoteAddr())
|
sc.logf("timeout waiting for SETTINGS frames from %v", sc.conn.RemoteAddr())
|
||||||
return
|
return
|
||||||
case <-sc.idleTimerCh:
|
case idleTimerMsg:
|
||||||
sc.vlogf("connection is idle")
|
sc.vlogf("connection is idle")
|
||||||
sc.goAway(ErrCodeNo)
|
sc.goAway(ErrCodeNo)
|
||||||
case fn := <-sc.testHookCh:
|
case shutdownTimerMsg:
|
||||||
fn(loopNum)
|
sc.vlogf("GOAWAY close timer fired; closing conn from %v", sc.conn.RemoteAddr())
|
||||||
|
return
|
||||||
|
case gracefulShutdownMsg:
|
||||||
|
sc.startGracefulShutdownInternal()
|
||||||
|
default:
|
||||||
|
panic("unknown timer")
|
||||||
|
}
|
||||||
|
case *startPushRequest:
|
||||||
|
sc.startPush(v)
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unexpected type %T", v))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if sc.inGoAway && sc.curOpenStreams() == 0 && !sc.needToSendGoAway && !sc.writingFrame {
|
// Start the shutdown timer after sending a GOAWAY. When sending GOAWAY
|
||||||
return
|
// with no error code (graceful shutdown), don't start the timer until
|
||||||
|
// all open streams have been completed.
|
||||||
|
sentGoAway := sc.inGoAway && !sc.needToSendGoAway && !sc.writingFrame
|
||||||
|
gracefulShutdownComplete := sc.goAwayCode == ErrCodeNo && sc.curOpenStreams() == 0
|
||||||
|
if sentGoAway && sc.shutdownTimer == nil && (sc.goAwayCode != ErrCodeNo || gracefulShutdownComplete) {
|
||||||
|
sc.shutDownIn(goAwayTimeout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// readPreface reads the ClientPreface greeting from the peer
|
func (sc *serverConn) awaitGracefulShutdown(sharedCh <-chan struct{}, privateCh chan struct{}) {
|
||||||
// or returns an error on timeout or an invalid greeting.
|
select {
|
||||||
|
case <-sc.doneServing:
|
||||||
|
case <-sharedCh:
|
||||||
|
close(privateCh)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type serverMessage int
|
||||||
|
|
||||||
|
// Message values sent to serveMsgCh.
|
||||||
|
var (
|
||||||
|
settingsTimerMsg = new(serverMessage)
|
||||||
|
idleTimerMsg = new(serverMessage)
|
||||||
|
shutdownTimerMsg = new(serverMessage)
|
||||||
|
gracefulShutdownMsg = new(serverMessage)
|
||||||
|
)
|
||||||
|
|
||||||
|
func (sc *serverConn) onSettingsTimer() { sc.sendServeMsg(settingsTimerMsg) }
|
||||||
|
func (sc *serverConn) onIdleTimer() { sc.sendServeMsg(idleTimerMsg) }
|
||||||
|
func (sc *serverConn) onShutdownTimer() { sc.sendServeMsg(shutdownTimerMsg) }
|
||||||
|
|
||||||
|
func (sc *serverConn) sendServeMsg(msg interface{}) {
|
||||||
|
sc.serveG.checkNotOn() // NOT
|
||||||
|
select {
|
||||||
|
case sc.serveMsgCh <- msg:
|
||||||
|
case <-sc.doneServing:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var errPrefaceTimeout = errors.New("timeout waiting for client preface")
|
||||||
|
|
||||||
|
// readPreface reads the ClientPreface greeting from the peer or
|
||||||
|
// returns errPrefaceTimeout on timeout, or an error if the greeting
|
||||||
|
// is invalid.
|
||||||
func (sc *serverConn) readPreface() error {
|
func (sc *serverConn) readPreface() error {
|
||||||
errc := make(chan error, 1)
|
errc := make(chan error, 1)
|
||||||
go func() {
|
go func() {
|
||||||
@ -827,7 +933,7 @@ func (sc *serverConn) readPreface() error {
|
|||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
select {
|
select {
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
return errors.New("timeout waiting for client preface")
|
return errPrefaceTimeout
|
||||||
case err := <-errc:
|
case err := <-errc:
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if VerboseLogs {
|
if VerboseLogs {
|
||||||
@ -1016,7 +1122,7 @@ func (sc *serverConn) startFrameWrite(wr FrameWriteRequest) {
|
|||||||
|
|
||||||
// errHandlerPanicked is the error given to any callers blocked in a read from
|
// 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
|
// Request.Body when the main goroutine panics. Since most handlers read in the
|
||||||
// the main ServeHTTP goroutine, this will show up rarely.
|
// main ServeHTTP goroutine, this will show up rarely.
|
||||||
var errHandlerPanicked = errors.New("http2: handler panicked")
|
var errHandlerPanicked = errors.New("http2: handler panicked")
|
||||||
|
|
||||||
// wroteFrame is called on the serve goroutine with the result of
|
// wroteFrame is called on the serve goroutine with the result of
|
||||||
@ -1125,33 +1231,43 @@ func (sc *serverConn) scheduleFrameWrite() {
|
|||||||
sc.inFrameScheduleLoop = false
|
sc.inFrameScheduleLoop = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// startGracefulShutdown sends a GOAWAY with ErrCodeNo to tell the
|
// startGracefulShutdown gracefully shuts down a connection. This
|
||||||
// client we're gracefully shutting down. The connection isn't closed
|
// sends GOAWAY with ErrCodeNo to tell the client we're gracefully
|
||||||
// until all current streams are done.
|
// shutting down. The connection isn't closed until all current
|
||||||
|
// streams are done.
|
||||||
|
//
|
||||||
|
// startGracefulShutdown returns immediately; it does not wait until
|
||||||
|
// the connection has shut down.
|
||||||
func (sc *serverConn) startGracefulShutdown() {
|
func (sc *serverConn) startGracefulShutdown() {
|
||||||
sc.goAwayIn(ErrCodeNo, 0)
|
sc.serveG.checkNotOn() // NOT
|
||||||
|
sc.shutdownOnce.Do(func() { sc.sendServeMsg(gracefulShutdownMsg) })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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?
|
||||||
|
var goAwayTimeout = 1 * time.Second
|
||||||
|
|
||||||
|
func (sc *serverConn) startGracefulShutdownInternal() {
|
||||||
|
sc.goAway(ErrCodeNo)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *serverConn) goAway(code ErrCode) {
|
func (sc *serverConn) goAway(code ErrCode) {
|
||||||
sc.serveG.check()
|
|
||||||
var forceCloseIn time.Duration
|
|
||||||
if code != ErrCodeNo {
|
|
||||||
forceCloseIn = 250 * time.Millisecond
|
|
||||||
} else {
|
|
||||||
// TODO: configurable
|
|
||||||
forceCloseIn = 1 * time.Second
|
|
||||||
}
|
|
||||||
sc.goAwayIn(code, forceCloseIn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sc *serverConn) goAwayIn(code ErrCode, forceCloseIn time.Duration) {
|
|
||||||
sc.serveG.check()
|
sc.serveG.check()
|
||||||
if sc.inGoAway {
|
if sc.inGoAway {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if forceCloseIn != 0 {
|
|
||||||
sc.shutDownIn(forceCloseIn)
|
|
||||||
}
|
|
||||||
sc.inGoAway = true
|
sc.inGoAway = true
|
||||||
sc.needToSendGoAway = true
|
sc.needToSendGoAway = true
|
||||||
sc.goAwayCode = code
|
sc.goAwayCode = code
|
||||||
@ -1160,8 +1276,7 @@ func (sc *serverConn) goAwayIn(code ErrCode, forceCloseIn time.Duration) {
|
|||||||
|
|
||||||
func (sc *serverConn) shutDownIn(d time.Duration) {
|
func (sc *serverConn) shutDownIn(d time.Duration) {
|
||||||
sc.serveG.check()
|
sc.serveG.check()
|
||||||
sc.shutdownTimer = time.NewTimer(d)
|
sc.shutdownTimer = time.AfterFunc(d, sc.onShutdownTimer)
|
||||||
sc.shutdownTimerCh = sc.shutdownTimer.C
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *serverConn) resetStream(se StreamError) {
|
func (sc *serverConn) resetStream(se StreamError) {
|
||||||
@ -1359,7 +1474,7 @@ func (sc *serverConn) closeStream(st *stream, err error) {
|
|||||||
sc.idleTimer.Reset(sc.srv.IdleTimeout)
|
sc.idleTimer.Reset(sc.srv.IdleTimeout)
|
||||||
}
|
}
|
||||||
if h1ServerKeepAlivesDisabled(sc.hs) {
|
if h1ServerKeepAlivesDisabled(sc.hs) {
|
||||||
sc.startGracefulShutdown()
|
sc.startGracefulShutdownInternal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p := st.body; p != nil {
|
if p := st.body; p != nil {
|
||||||
@ -1385,6 +1500,12 @@ func (sc *serverConn) processSettings(f *SettingsFrame) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if f.NumSettings() > 100 || f.HasDuplicates() {
|
||||||
|
// This isn't actually in the spec, but hang up on
|
||||||
|
// suspiciously large settings frames or those with
|
||||||
|
// duplicate entries.
|
||||||
|
return ConnectionError(ErrCodeProtocol)
|
||||||
|
}
|
||||||
if err := f.ForeachSetting(sc.processSetting); err != nil {
|
if err := f.ForeachSetting(sc.processSetting); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1506,7 +1627,10 @@ func (sc *serverConn) processData(f *DataFrame) error {
|
|||||||
// Sender sending more than they'd declared?
|
// Sender sending more than they'd declared?
|
||||||
if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes {
|
if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes {
|
||||||
st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes))
|
st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes))
|
||||||
return streamError(id, ErrCodeStreamClosed)
|
// RFC 7540, sec 8.1.2.6: A request or response is also malformed if the
|
||||||
|
// value of a content-length header field does not equal the sum of the
|
||||||
|
// DATA frame payload lengths that form the body.
|
||||||
|
return streamError(id, ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
if f.Length > 0 {
|
if f.Length > 0 {
|
||||||
// Check whether the client has flow control quota.
|
// Check whether the client has flow control quota.
|
||||||
@ -1546,7 +1670,7 @@ func (sc *serverConn) processGoAway(f *GoAwayFrame) error {
|
|||||||
} else {
|
} else {
|
||||||
sc.vlogf("http2: received GOAWAY %+v, starting graceful shutdown", f)
|
sc.vlogf("http2: received GOAWAY %+v, starting graceful shutdown", f)
|
||||||
}
|
}
|
||||||
sc.startGracefulShutdown()
|
sc.startGracefulShutdownInternal()
|
||||||
// http://tools.ietf.org/html/rfc7540#section-6.8
|
// http://tools.ietf.org/html/rfc7540#section-6.8
|
||||||
// We should not create any new streams, which means we should disable push.
|
// We should not create any new streams, which means we should disable push.
|
||||||
sc.pushEnabled = false
|
sc.pushEnabled = false
|
||||||
@ -1616,6 +1740,13 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
|||||||
// processing this frame.
|
// processing this frame.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
// RFC 7540, sec 5.1: If an endpoint receives additional frames, other than
|
||||||
|
// WINDOW_UPDATE, PRIORITY, or RST_STREAM, for a stream that is in
|
||||||
|
// this state, it MUST respond with a stream error (Section 5.4.2) of
|
||||||
|
// type STREAM_CLOSED.
|
||||||
|
if st.state == stateHalfClosedRemote {
|
||||||
|
return streamError(id, ErrCodeStreamClosed)
|
||||||
|
}
|
||||||
return st.processTrailerHeaders(f)
|
return st.processTrailerHeaders(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1716,7 +1847,7 @@ func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
|
|||||||
if st.trailer != nil {
|
if st.trailer != nil {
|
||||||
for _, hf := range f.RegularFields() {
|
for _, hf := range f.RegularFields() {
|
||||||
key := sc.canonicalHeader(hf.Name)
|
key := sc.canonicalHeader(hf.Name)
|
||||||
if !ValidTrailerHeader(key) {
|
if !httpguts.ValidTrailerHeader(key) {
|
||||||
// TODO: send more details to the peer somehow. But http2 has
|
// TODO: send more details to the peer somehow. But http2 has
|
||||||
// no way to send debug data at a stream level. Discuss with
|
// no way to send debug data at a stream level. Discuss with
|
||||||
// HTTP folk.
|
// HTTP folk.
|
||||||
@ -1757,7 +1888,7 @@ func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream
|
|||||||
panic("internal error: cannot create stream with id 0")
|
panic("internal error: cannot create stream with id 0")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancelCtx := contextWithCancel(sc.baseCtx)
|
ctx, cancelCtx := context.WithCancel(sc.baseCtx)
|
||||||
st := &stream{
|
st := &stream{
|
||||||
sc: sc,
|
sc: sc,
|
||||||
id: id,
|
id: id,
|
||||||
@ -1923,7 +2054,7 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r
|
|||||||
Body: body,
|
Body: body,
|
||||||
Trailer: trailer,
|
Trailer: trailer,
|
||||||
}
|
}
|
||||||
req = requestWithContext(req, st.ctx)
|
req = req.WithContext(st.ctx)
|
||||||
|
|
||||||
rws := responseWriterStatePool.Get().(*responseWriterState)
|
rws := responseWriterStatePool.Get().(*responseWriterState)
|
||||||
bwSave := rws.bw
|
bwSave := rws.bw
|
||||||
@ -1951,7 +2082,7 @@ func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler
|
|||||||
stream: rw.rws.stream,
|
stream: rw.rws.stream,
|
||||||
})
|
})
|
||||||
// Same as net/http:
|
// Same as net/http:
|
||||||
if shouldLogPanic(e) {
|
if e != nil && e != http.ErrAbortHandler {
|
||||||
const size = 64 << 10
|
const size = 64 << 10
|
||||||
buf := make([]byte, size)
|
buf := make([]byte, size)
|
||||||
buf = buf[:runtime.Stack(buf, false)]
|
buf = buf[:runtime.Stack(buf, false)]
|
||||||
@ -2163,6 +2294,7 @@ type responseWriterState struct {
|
|||||||
wroteHeader bool // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
|
wroteHeader bool // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
|
||||||
sentHeader bool // have we sent the header frame?
|
sentHeader bool // have we sent the header frame?
|
||||||
handlerDone bool // handler has finished
|
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
|
sentContentLen int64 // non-zero if handler set a Content-Length header
|
||||||
wroteBytes int64
|
wroteBytes int64
|
||||||
@ -2182,8 +2314,8 @@ func (rws *responseWriterState) hasTrailers() bool { return len(rws.trailers) !=
|
|||||||
// written in the trailers at the end of the response.
|
// written in the trailers at the end of the response.
|
||||||
func (rws *responseWriterState) declareTrailer(k string) {
|
func (rws *responseWriterState) declareTrailer(k string) {
|
||||||
k = http.CanonicalHeaderKey(k)
|
k = http.CanonicalHeaderKey(k)
|
||||||
if !ValidTrailerHeader(k) {
|
if !httpguts.ValidTrailerHeader(k) {
|
||||||
// Forbidden by RFC 2616 14.40.
|
// Forbidden by RFC 7230, section 4.1.2.
|
||||||
rws.conn.logf("ignoring invalid trailer %q", k)
|
rws.conn.logf("ignoring invalid trailer %q", k)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -2220,7 +2352,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
|||||||
clen = strconv.Itoa(len(p))
|
clen = strconv.Itoa(len(p))
|
||||||
}
|
}
|
||||||
_, hasContentType := rws.snapHeader["Content-Type"]
|
_, hasContentType := rws.snapHeader["Content-Type"]
|
||||||
if !hasContentType && bodyAllowedForStatus(rws.status) {
|
if !hasContentType && bodyAllowedForStatus(rws.status) && len(p) > 0 {
|
||||||
ctype = http.DetectContentType(p)
|
ctype = http.DetectContentType(p)
|
||||||
}
|
}
|
||||||
var date string
|
var date string
|
||||||
@ -2233,6 +2365,19 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
|||||||
foreachHeaderElement(v, rws.declareTrailer)
|
foreachHeaderElement(v, rws.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 _, ok := rws.snapHeader["Connection"]; ok {
|
||||||
|
v := rws.snapHeader.Get("Connection")
|
||||||
|
delete(rws.snapHeader, "Connection")
|
||||||
|
if v == "close" {
|
||||||
|
rws.conn.startGracefulShutdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
endStream := (rws.handlerDone && !rws.hasTrailers() && len(p) == 0) || isHeadResp
|
endStream := (rws.handlerDone && !rws.hasTrailers() && len(p) == 0) || isHeadResp
|
||||||
err = rws.conn.writeHeaders(rws.stream, &writeResHeaders{
|
err = rws.conn.writeHeaders(rws.stream, &writeResHeaders{
|
||||||
streamID: rws.stream.id,
|
streamID: rws.stream.id,
|
||||||
@ -2244,6 +2389,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
|||||||
date: date,
|
date: date,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
rws.dirty = true
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if endStream {
|
if endStream {
|
||||||
@ -2265,6 +2411,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
|||||||
if len(p) > 0 || endStream {
|
if len(p) > 0 || endStream {
|
||||||
// only send a 0 byte DATA frame if we're ending the stream.
|
// only send a 0 byte DATA frame if we're ending the stream.
|
||||||
if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil {
|
if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil {
|
||||||
|
rws.dirty = true
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2276,6 +2423,9 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
|||||||
trailers: rws.trailers,
|
trailers: rws.trailers,
|
||||||
endStream: true,
|
endStream: true,
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
rws.dirty = true
|
||||||
|
}
|
||||||
return len(p), err
|
return len(p), err
|
||||||
}
|
}
|
||||||
return len(p), nil
|
return len(p), nil
|
||||||
@ -2299,7 +2449,7 @@ const TrailerPrefix = "Trailer:"
|
|||||||
// after the header has already been flushed. Because the Go
|
// after the header has already been flushed. Because the Go
|
||||||
// ResponseWriter interface has no way to set Trailers (only the
|
// ResponseWriter interface has no way to set Trailers (only the
|
||||||
// Header), and because we didn't want to expand the ResponseWriter
|
// Header), and because we didn't want to expand the ResponseWriter
|
||||||
// interface, and because nobody used trailers, and because RFC 2616
|
// interface, and because nobody used trailers, and because RFC 7230
|
||||||
// says you SHOULD (but not must) predeclare any trailers in the
|
// says you SHOULD (but not must) predeclare any trailers in the
|
||||||
// header, the official ResponseWriter rules said trailers in Go must
|
// header, the official ResponseWriter rules said trailers in Go must
|
||||||
// be predeclared, and then we reuse the same ResponseWriter.Header()
|
// be predeclared, and then we reuse the same ResponseWriter.Header()
|
||||||
@ -2383,6 +2533,24 @@ func (w *responseWriter) Header() http.Header {
|
|||||||
return rws.handlerHeader
|
return rws.handlerHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkWriteHeaderCode is a copy of net/http's checkWriteHeaderCode.
|
||||||
|
func checkWriteHeaderCode(code int) {
|
||||||
|
// Issue 22880: require valid WriteHeader status codes.
|
||||||
|
// For now we only enforce that it's three digits.
|
||||||
|
// In the future we might block things over 599 (600 and above aren't defined
|
||||||
|
// at http://httpwg.org/specs/rfc7231.html#status.codes)
|
||||||
|
// 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 code < 100 || code > 999 {
|
||||||
|
panic(fmt.Sprintf("invalid WriteHeader code %v", code))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (w *responseWriter) WriteHeader(code int) {
|
func (w *responseWriter) WriteHeader(code int) {
|
||||||
rws := w.rws
|
rws := w.rws
|
||||||
if rws == nil {
|
if rws == nil {
|
||||||
@ -2393,6 +2561,7 @@ func (w *responseWriter) WriteHeader(code int) {
|
|||||||
|
|
||||||
func (rws *responseWriterState) writeHeader(code int) {
|
func (rws *responseWriterState) writeHeader(code int) {
|
||||||
if !rws.wroteHeader {
|
if !rws.wroteHeader {
|
||||||
|
checkWriteHeaderCode(code)
|
||||||
rws.wroteHeader = true
|
rws.wroteHeader = true
|
||||||
rws.status = code
|
rws.status = code
|
||||||
if len(rws.handlerHeader) > 0 {
|
if len(rws.handlerHeader) > 0 {
|
||||||
@ -2415,7 +2584,7 @@ func cloneHeader(h http.Header) http.Header {
|
|||||||
//
|
//
|
||||||
// * Handler calls w.Write or w.WriteString ->
|
// * Handler calls w.Write or w.WriteString ->
|
||||||
// * -> rws.bw (*bufio.Writer) ->
|
// * -> rws.bw (*bufio.Writer) ->
|
||||||
// * (Handler migth call Flush)
|
// * (Handler might call Flush)
|
||||||
// * -> chunkWriter{rws}
|
// * -> chunkWriter{rws}
|
||||||
// * -> responseWriterState.writeChunk(p []byte)
|
// * -> responseWriterState.writeChunk(p []byte)
|
||||||
// * -> responseWriterState.writeChunk (most of the magic; see comment there)
|
// * -> responseWriterState.writeChunk (most of the magic; see comment there)
|
||||||
@ -2454,10 +2623,19 @@ func (w *responseWriter) write(lenData int, dataB []byte, dataS string) (n int,
|
|||||||
|
|
||||||
func (w *responseWriter) handlerDone() {
|
func (w *responseWriter) handlerDone() {
|
||||||
rws := w.rws
|
rws := w.rws
|
||||||
|
dirty := rws.dirty
|
||||||
rws.handlerDone = true
|
rws.handlerDone = true
|
||||||
w.Flush()
|
w.Flush()
|
||||||
w.rws = nil
|
w.rws = nil
|
||||||
responseWriterStatePool.Put(rws)
|
if !dirty {
|
||||||
|
// 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.
|
||||||
|
responseWriterStatePool.Put(rws)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push errors.
|
// Push errors.
|
||||||
@ -2466,14 +2644,9 @@ var (
|
|||||||
ErrPushLimitReached = errors.New("http2: push would exceed peer's SETTINGS_MAX_CONCURRENT_STREAMS")
|
ErrPushLimitReached = errors.New("http2: push would exceed peer's SETTINGS_MAX_CONCURRENT_STREAMS")
|
||||||
)
|
)
|
||||||
|
|
||||||
// pushOptions is the internal version of http.PushOptions, which we
|
var _ http.Pusher = (*responseWriter)(nil)
|
||||||
// cannot include here because it's only defined in Go 1.8 and later.
|
|
||||||
type pushOptions struct {
|
|
||||||
Method string
|
|
||||||
Header http.Header
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *responseWriter) push(target string, opts pushOptions) error {
|
func (w *responseWriter) Push(target string, opts *http.PushOptions) error {
|
||||||
st := w.rws.stream
|
st := w.rws.stream
|
||||||
sc := st.sc
|
sc := st.sc
|
||||||
sc.serveG.checkNotOn()
|
sc.serveG.checkNotOn()
|
||||||
@ -2484,6 +2657,10 @@ func (w *responseWriter) push(target string, opts pushOptions) error {
|
|||||||
return ErrRecursivePush
|
return ErrRecursivePush
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opts == nil {
|
||||||
|
opts = new(http.PushOptions)
|
||||||
|
}
|
||||||
|
|
||||||
// Default options.
|
// Default options.
|
||||||
if opts.Method == "" {
|
if opts.Method == "" {
|
||||||
opts.Method = "GET"
|
opts.Method = "GET"
|
||||||
@ -2539,7 +2716,7 @@ func (w *responseWriter) push(target string, opts pushOptions) error {
|
|||||||
return fmt.Errorf("method %q must be GET or HEAD", opts.Method)
|
return fmt.Errorf("method %q must be GET or HEAD", opts.Method)
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := startPushRequest{
|
msg := &startPushRequest{
|
||||||
parent: st,
|
parent: st,
|
||||||
method: opts.Method,
|
method: opts.Method,
|
||||||
url: u,
|
url: u,
|
||||||
@ -2552,7 +2729,7 @@ func (w *responseWriter) push(target string, opts pushOptions) error {
|
|||||||
return errClientDisconnected
|
return errClientDisconnected
|
||||||
case <-st.cw:
|
case <-st.cw:
|
||||||
return errStreamClosed
|
return errStreamClosed
|
||||||
case sc.wantStartPushCh <- msg:
|
case sc.serveMsgCh <- msg:
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
@ -2574,7 +2751,7 @@ type startPushRequest struct {
|
|||||||
done chan error
|
done chan error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *serverConn) startPush(msg startPushRequest) {
|
func (sc *serverConn) startPush(msg *startPushRequest) {
|
||||||
sc.serveG.check()
|
sc.serveG.check()
|
||||||
|
|
||||||
// http://tools.ietf.org/html/rfc7540#section-6.6.
|
// http://tools.ietf.org/html/rfc7540#section-6.6.
|
||||||
@ -2613,7 +2790,7 @@ func (sc *serverConn) startPush(msg startPushRequest) {
|
|||||||
// A server that is unable to establish a new stream identifier can send a GOAWAY
|
// 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.
|
// frame so that the client is forced to open a new connection for new streams.
|
||||||
if sc.maxPushPromiseID+2 >= 1<<31 {
|
if sc.maxPushPromiseID+2 >= 1<<31 {
|
||||||
sc.startGracefulShutdown()
|
sc.startGracefulShutdownInternal()
|
||||||
return 0, ErrPushLimitReached
|
return 0, ErrPushLimitReached
|
||||||
}
|
}
|
||||||
sc.maxPushPromiseID += 2
|
sc.maxPushPromiseID += 2
|
||||||
@ -2655,7 +2832,7 @@ func (sc *serverConn) startPush(msg startPushRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// foreachHeaderElement splits v according to the "#rule" construction
|
// foreachHeaderElement splits v according to the "#rule" construction
|
||||||
// in RFC 2616 section 2.1 and calls fn for each non-empty element.
|
// in RFC 7230 section 7 and calls fn for each non-empty element.
|
||||||
func foreachHeaderElement(v string, fn func(string)) {
|
func foreachHeaderElement(v string, fn func(string)) {
|
||||||
v = textproto.TrimString(v)
|
v = textproto.TrimString(v)
|
||||||
if v == "" {
|
if v == "" {
|
||||||
@ -2703,66 +2880,6 @@ func new400Handler(err error) http.HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidTrailerHeader reports whether name is a valid header field name to appear
|
|
||||||
// in trailers.
|
|
||||||
// See: http://tools.ietf.org/html/rfc7230#section-4.1.2
|
|
||||||
func ValidTrailerHeader(name string) bool {
|
|
||||||
name = http.CanonicalHeaderKey(name)
|
|
||||||
if strings.HasPrefix(name, "If-") || badTrailer[name] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
var badTrailer = map[string]bool{
|
|
||||||
"Authorization": true,
|
|
||||||
"Cache-Control": true,
|
|
||||||
"Connection": true,
|
|
||||||
"Content-Encoding": true,
|
|
||||||
"Content-Length": true,
|
|
||||||
"Content-Range": true,
|
|
||||||
"Content-Type": true,
|
|
||||||
"Expect": true,
|
|
||||||
"Host": true,
|
|
||||||
"Keep-Alive": true,
|
|
||||||
"Max-Forwards": true,
|
|
||||||
"Pragma": true,
|
|
||||||
"Proxy-Authenticate": true,
|
|
||||||
"Proxy-Authorization": true,
|
|
||||||
"Proxy-Connection": true,
|
|
||||||
"Range": true,
|
|
||||||
"Realm": true,
|
|
||||||
"Te": true,
|
|
||||||
"Trailer": true,
|
|
||||||
"Transfer-Encoding": true,
|
|
||||||
"Www-Authenticate": true,
|
|
||||||
}
|
|
||||||
|
|
||||||
// h1ServerShutdownChan returns a channel that will be closed when the
|
|
||||||
// provided *http.Server wants to shut down.
|
|
||||||
//
|
|
||||||
// This is a somewhat hacky way to get at http1 innards. It works
|
|
||||||
// when the http2 code is bundled into the net/http package in the
|
|
||||||
// standard library. The alternatives ended up making the cmd/go tool
|
|
||||||
// depend on http Servers. This is the lightest option for now.
|
|
||||||
// This is tested via the TestServeShutdown* tests in net/http.
|
|
||||||
func h1ServerShutdownChan(hs *http.Server) <-chan struct{} {
|
|
||||||
if fn := testh1ServerShutdownChan; fn != nil {
|
|
||||||
return fn(hs)
|
|
||||||
}
|
|
||||||
var x interface{} = hs
|
|
||||||
type I interface {
|
|
||||||
getDoneChan() <-chan struct{}
|
|
||||||
}
|
|
||||||
if hs, ok := x.(I); ok {
|
|
||||||
return hs.getDoneChan()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// optional test hook for h1ServerShutdownChan.
|
|
||||||
var testh1ServerShutdownChan func(hs *http.Server) <-chan struct{}
|
|
||||||
|
|
||||||
// h1ServerKeepAlivesDisabled reports whether hs has its keep-alives
|
// h1ServerKeepAlivesDisabled reports whether hs has its keep-alives
|
||||||
// disabled. See comments on h1ServerShutdownChan above for why
|
// disabled. See comments on h1ServerShutdownChan above for why
|
||||||
// the code is written this way.
|
// the code is written this way.
|
||||||
|
915
vendor/golang.org/x/net/http2/transport.go
generated
vendored
915
vendor/golang.org/x/net/http2/transport.go
generated
vendored
File diff suppressed because it is too large
Load Diff
15
vendor/golang.org/x/net/http2/write.go
generated
vendored
15
vendor/golang.org/x/net/http2/write.go
generated
vendored
@ -10,10 +10,9 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
|
||||||
|
|
||||||
|
"golang.org/x/net/http/httpguts"
|
||||||
"golang.org/x/net/http2/hpack"
|
"golang.org/x/net/http2/hpack"
|
||||||
"golang.org/x/net/lex/httplex"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// writeFramer is implemented by any type that is used to write frames.
|
// writeFramer is implemented by any type that is used to write frames.
|
||||||
@ -90,11 +89,7 @@ type writeGoAway struct {
|
|||||||
|
|
||||||
func (p *writeGoAway) writeFrame(ctx writeContext) error {
|
func (p *writeGoAway) writeFrame(ctx writeContext) error {
|
||||||
err := ctx.Framer().WriteGoAway(p.maxStreamID, p.code, nil)
|
err := ctx.Framer().WriteGoAway(p.maxStreamID, p.code, nil)
|
||||||
if p.code != 0 {
|
ctx.Flush() // ignore error: we're hanging up on them anyway
|
||||||
ctx.Flush() // ignore error: we're hanging up on them anyway
|
|
||||||
time.Sleep(50 * time.Millisecond)
|
|
||||||
ctx.CloseConn()
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +199,7 @@ func (w *writeResHeaders) staysWithinBuffer(max int) bool {
|
|||||||
// TODO: this is a common one. It'd be nice to return true
|
// 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
|
// here and get into the fast path if we could be clever and
|
||||||
// calculate the size fast enough, or at least a conservative
|
// calculate the size fast enough, or at least a conservative
|
||||||
// uppper bound that usually fires. (Maybe if w.h and
|
// upper bound that usually fires. (Maybe if w.h and
|
||||||
// w.trailers are nil, so we don't need to enumerate it.)
|
// w.trailers are nil, so we don't need to enumerate it.)
|
||||||
// Otherwise I'm afraid that just calculating the length to
|
// Otherwise I'm afraid that just calculating the length to
|
||||||
// answer this question would be slower than the ~2µs benefit.
|
// answer this question would be slower than the ~2µs benefit.
|
||||||
@ -334,7 +329,7 @@ func (wu writeWindowUpdate) writeFrame(ctx writeContext) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// encodeHeaders encodes an http.Header. If keys is not nil, then (k, h[k])
|
// encodeHeaders encodes an http.Header. If keys is not nil, then (k, h[k])
|
||||||
// is encoded only only if k is in keys.
|
// is encoded only if k is in keys.
|
||||||
func encodeHeaders(enc *hpack.Encoder, h http.Header, keys []string) {
|
func encodeHeaders(enc *hpack.Encoder, h http.Header, keys []string) {
|
||||||
if keys == nil {
|
if keys == nil {
|
||||||
sorter := sorterPool.Get().(*sorter)
|
sorter := sorterPool.Get().(*sorter)
|
||||||
@ -355,7 +350,7 @@ func encodeHeaders(enc *hpack.Encoder, h http.Header, keys []string) {
|
|||||||
}
|
}
|
||||||
isTE := k == "transfer-encoding"
|
isTE := k == "transfer-encoding"
|
||||||
for _, v := range vv {
|
for _, v := range vv {
|
||||||
if !httplex.ValidHeaderFieldValue(v) {
|
if !httpguts.ValidHeaderFieldValue(v) {
|
||||||
// TODO: return an error? golang.org/issue/14048
|
// TODO: return an error? golang.org/issue/14048
|
||||||
// For now just omit it.
|
// For now just omit it.
|
||||||
continue
|
continue
|
||||||
|
2
vendor/golang.org/x/net/http2/writesched_priority.go
generated
vendored
2
vendor/golang.org/x/net/http2/writesched_priority.go
generated
vendored
@ -53,7 +53,7 @@ type PriorityWriteSchedulerConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewPriorityWriteScheduler constructs a WriteScheduler that schedules
|
// NewPriorityWriteScheduler constructs a WriteScheduler that schedules
|
||||||
// frames by following HTTP/2 priorities as described in RFC 7340 Section 5.3.
|
// frames by following HTTP/2 priorities as described in RFC 7540 Section 5.3.
|
||||||
// If cfg is nil, default options are used.
|
// If cfg is nil, default options are used.
|
||||||
func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler {
|
func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler {
|
||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
|
351
vendor/golang.org/x/net/lex/httplex/httplex.go
generated
vendored
351
vendor/golang.org/x/net/lex/httplex/httplex.go
generated
vendored
@ -1,351 +0,0 @@
|
|||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package httplex contains rules around lexical matters of various
|
|
||||||
// HTTP-related specifications.
|
|
||||||
//
|
|
||||||
// This package is shared by the standard library (which vendors it)
|
|
||||||
// and x/net/http2. It comes with no API stability promise.
|
|
||||||
package httplex
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"strings"
|
|
||||||
"unicode/utf8"
|
|
||||||
|
|
||||||
"golang.org/x/net/idna"
|
|
||||||
)
|
|
||||||
|
|
||||||
var isTokenTable = [127]bool{
|
|
||||||
'!': true,
|
|
||||||
'#': true,
|
|
||||||
'$': true,
|
|
||||||
'%': true,
|
|
||||||
'&': true,
|
|
||||||
'\'': true,
|
|
||||||
'*': true,
|
|
||||||
'+': true,
|
|
||||||
'-': true,
|
|
||||||
'.': true,
|
|
||||||
'0': true,
|
|
||||||
'1': true,
|
|
||||||
'2': true,
|
|
||||||
'3': true,
|
|
||||||
'4': true,
|
|
||||||
'5': true,
|
|
||||||
'6': true,
|
|
||||||
'7': true,
|
|
||||||
'8': true,
|
|
||||||
'9': true,
|
|
||||||
'A': true,
|
|
||||||
'B': true,
|
|
||||||
'C': true,
|
|
||||||
'D': true,
|
|
||||||
'E': true,
|
|
||||||
'F': true,
|
|
||||||
'G': true,
|
|
||||||
'H': true,
|
|
||||||
'I': true,
|
|
||||||
'J': true,
|
|
||||||
'K': true,
|
|
||||||
'L': true,
|
|
||||||
'M': true,
|
|
||||||
'N': true,
|
|
||||||
'O': true,
|
|
||||||
'P': true,
|
|
||||||
'Q': true,
|
|
||||||
'R': true,
|
|
||||||
'S': true,
|
|
||||||
'T': true,
|
|
||||||
'U': true,
|
|
||||||
'W': true,
|
|
||||||
'V': true,
|
|
||||||
'X': true,
|
|
||||||
'Y': true,
|
|
||||||
'Z': true,
|
|
||||||
'^': true,
|
|
||||||
'_': true,
|
|
||||||
'`': true,
|
|
||||||
'a': true,
|
|
||||||
'b': true,
|
|
||||||
'c': true,
|
|
||||||
'd': true,
|
|
||||||
'e': true,
|
|
||||||
'f': true,
|
|
||||||
'g': true,
|
|
||||||
'h': true,
|
|
||||||
'i': true,
|
|
||||||
'j': true,
|
|
||||||
'k': true,
|
|
||||||
'l': true,
|
|
||||||
'm': true,
|
|
||||||
'n': true,
|
|
||||||
'o': true,
|
|
||||||
'p': true,
|
|
||||||
'q': true,
|
|
||||||
'r': true,
|
|
||||||
's': true,
|
|
||||||
't': true,
|
|
||||||
'u': true,
|
|
||||||
'v': true,
|
|
||||||
'w': true,
|
|
||||||
'x': true,
|
|
||||||
'y': true,
|
|
||||||
'z': true,
|
|
||||||
'|': true,
|
|
||||||
'~': true,
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsTokenRune(r rune) bool {
|
|
||||||
i := int(r)
|
|
||||||
return i < len(isTokenTable) && isTokenTable[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
func isNotToken(r rune) bool {
|
|
||||||
return !IsTokenRune(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HeaderValuesContainsToken reports whether any string in values
|
|
||||||
// contains the provided token, ASCII case-insensitively.
|
|
||||||
func HeaderValuesContainsToken(values []string, token string) bool {
|
|
||||||
for _, v := range values {
|
|
||||||
if headerValueContainsToken(v, token) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// isOWS reports whether b is an optional whitespace byte, as defined
|
|
||||||
// by RFC 7230 section 3.2.3.
|
|
||||||
func isOWS(b byte) bool { return b == ' ' || b == '\t' }
|
|
||||||
|
|
||||||
// trimOWS returns x with all optional whitespace removes from the
|
|
||||||
// beginning and end.
|
|
||||||
func trimOWS(x string) string {
|
|
||||||
// TODO: consider using strings.Trim(x, " \t") instead,
|
|
||||||
// if and when it's fast enough. See issue 10292.
|
|
||||||
// But this ASCII-only code will probably always beat UTF-8
|
|
||||||
// aware code.
|
|
||||||
for len(x) > 0 && isOWS(x[0]) {
|
|
||||||
x = x[1:]
|
|
||||||
}
|
|
||||||
for len(x) > 0 && isOWS(x[len(x)-1]) {
|
|
||||||
x = x[:len(x)-1]
|
|
||||||
}
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
// headerValueContainsToken reports whether v (assumed to be a
|
|
||||||
// 0#element, in the ABNF extension described in RFC 7230 section 7)
|
|
||||||
// contains token amongst its comma-separated tokens, ASCII
|
|
||||||
// case-insensitively.
|
|
||||||
func headerValueContainsToken(v string, token string) bool {
|
|
||||||
v = trimOWS(v)
|
|
||||||
if comma := strings.IndexByte(v, ','); comma != -1 {
|
|
||||||
return tokenEqual(trimOWS(v[:comma]), token) || headerValueContainsToken(v[comma+1:], token)
|
|
||||||
}
|
|
||||||
return tokenEqual(v, token)
|
|
||||||
}
|
|
||||||
|
|
||||||
// lowerASCII returns the ASCII lowercase version of b.
|
|
||||||
func lowerASCII(b byte) byte {
|
|
||||||
if 'A' <= b && b <= 'Z' {
|
|
||||||
return b + ('a' - 'A')
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// tokenEqual reports whether t1 and t2 are equal, ASCII case-insensitively.
|
|
||||||
func tokenEqual(t1, t2 string) bool {
|
|
||||||
if len(t1) != len(t2) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i, b := range t1 {
|
|
||||||
if b >= utf8.RuneSelf {
|
|
||||||
// No UTF-8 or non-ASCII allowed in tokens.
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if lowerASCII(byte(b)) != lowerASCII(t2[i]) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// isLWS reports whether b is linear white space, according
|
|
||||||
// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
|
|
||||||
// LWS = [CRLF] 1*( SP | HT )
|
|
||||||
func isLWS(b byte) bool { return b == ' ' || b == '\t' }
|
|
||||||
|
|
||||||
// isCTL reports whether b is a control byte, according
|
|
||||||
// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
|
|
||||||
// CTL = <any US-ASCII control character
|
|
||||||
// (octets 0 - 31) and DEL (127)>
|
|
||||||
func isCTL(b byte) bool {
|
|
||||||
const del = 0x7f // a CTL
|
|
||||||
return b < ' ' || b == del
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidHeaderFieldName reports whether v is a valid HTTP/1.x header name.
|
|
||||||
// HTTP/2 imposes the additional restriction that uppercase ASCII
|
|
||||||
// letters are not allowed.
|
|
||||||
//
|
|
||||||
// RFC 7230 says:
|
|
||||||
// header-field = field-name ":" OWS field-value OWS
|
|
||||||
// field-name = token
|
|
||||||
// token = 1*tchar
|
|
||||||
// tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
|
|
||||||
// "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
|
|
||||||
func ValidHeaderFieldName(v string) bool {
|
|
||||||
if len(v) == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for _, r := range v {
|
|
||||||
if !IsTokenRune(r) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidHostHeader reports whether h is a valid host header.
|
|
||||||
func ValidHostHeader(h string) bool {
|
|
||||||
// The latest spec is actually this:
|
|
||||||
//
|
|
||||||
// http://tools.ietf.org/html/rfc7230#section-5.4
|
|
||||||
// Host = uri-host [ ":" port ]
|
|
||||||
//
|
|
||||||
// Where uri-host is:
|
|
||||||
// http://tools.ietf.org/html/rfc3986#section-3.2.2
|
|
||||||
//
|
|
||||||
// But we're going to be much more lenient for now and just
|
|
||||||
// search for any byte that's not a valid byte in any of those
|
|
||||||
// expressions.
|
|
||||||
for i := 0; i < len(h); i++ {
|
|
||||||
if !validHostByte[h[i]] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// See the validHostHeader comment.
|
|
||||||
var validHostByte = [256]bool{
|
|
||||||
'0': true, '1': true, '2': true, '3': true, '4': true, '5': true, '6': true, '7': true,
|
|
||||||
'8': true, '9': true,
|
|
||||||
|
|
||||||
'a': true, 'b': true, 'c': true, 'd': true, 'e': true, 'f': true, 'g': true, 'h': true,
|
|
||||||
'i': true, 'j': true, 'k': true, 'l': true, 'm': true, 'n': true, 'o': true, 'p': true,
|
|
||||||
'q': true, 'r': true, 's': true, 't': true, 'u': true, 'v': true, 'w': true, 'x': true,
|
|
||||||
'y': true, 'z': true,
|
|
||||||
|
|
||||||
'A': true, 'B': true, 'C': true, 'D': true, 'E': true, 'F': true, 'G': true, 'H': true,
|
|
||||||
'I': true, 'J': true, 'K': true, 'L': true, 'M': true, 'N': true, 'O': true, 'P': true,
|
|
||||||
'Q': true, 'R': true, 'S': true, 'T': true, 'U': true, 'V': true, 'W': true, 'X': true,
|
|
||||||
'Y': true, 'Z': true,
|
|
||||||
|
|
||||||
'!': true, // sub-delims
|
|
||||||
'$': true, // sub-delims
|
|
||||||
'%': true, // pct-encoded (and used in IPv6 zones)
|
|
||||||
'&': true, // sub-delims
|
|
||||||
'(': true, // sub-delims
|
|
||||||
')': true, // sub-delims
|
|
||||||
'*': true, // sub-delims
|
|
||||||
'+': true, // sub-delims
|
|
||||||
',': true, // sub-delims
|
|
||||||
'-': true, // unreserved
|
|
||||||
'.': true, // unreserved
|
|
||||||
':': true, // IPv6address + Host expression's optional port
|
|
||||||
';': true, // sub-delims
|
|
||||||
'=': true, // sub-delims
|
|
||||||
'[': true,
|
|
||||||
'\'': true, // sub-delims
|
|
||||||
']': true,
|
|
||||||
'_': true, // unreserved
|
|
||||||
'~': true, // unreserved
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidHeaderFieldValue reports whether v is a valid "field-value" according to
|
|
||||||
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 :
|
|
||||||
//
|
|
||||||
// message-header = field-name ":" [ field-value ]
|
|
||||||
// field-value = *( field-content | LWS )
|
|
||||||
// field-content = <the OCTETs making up the field-value
|
|
||||||
// and consisting of either *TEXT or combinations
|
|
||||||
// of token, separators, and quoted-string>
|
|
||||||
//
|
|
||||||
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2 :
|
|
||||||
//
|
|
||||||
// TEXT = <any OCTET except CTLs,
|
|
||||||
// but including LWS>
|
|
||||||
// LWS = [CRLF] 1*( SP | HT )
|
|
||||||
// CTL = <any US-ASCII control character
|
|
||||||
// (octets 0 - 31) and DEL (127)>
|
|
||||||
//
|
|
||||||
// RFC 7230 says:
|
|
||||||
// field-value = *( field-content / obs-fold )
|
|
||||||
// obj-fold = N/A to http2, and deprecated
|
|
||||||
// field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
|
|
||||||
// field-vchar = VCHAR / obs-text
|
|
||||||
// obs-text = %x80-FF
|
|
||||||
// VCHAR = "any visible [USASCII] character"
|
|
||||||
//
|
|
||||||
// http2 further says: "Similarly, HTTP/2 allows header field values
|
|
||||||
// that are not valid. While most of the values that can be encoded
|
|
||||||
// will not alter header field parsing, carriage return (CR, ASCII
|
|
||||||
// 0xd), line feed (LF, ASCII 0xa), and the zero character (NUL, ASCII
|
|
||||||
// 0x0) might be exploited by an attacker if they are translated
|
|
||||||
// verbatim. Any request or response that contains a character not
|
|
||||||
// permitted in a header field value MUST be treated as malformed
|
|
||||||
// (Section 8.1.2.6). Valid characters are defined by the
|
|
||||||
// field-content ABNF rule in Section 3.2 of [RFC7230]."
|
|
||||||
//
|
|
||||||
// This function does not (yet?) properly handle the rejection of
|
|
||||||
// strings that begin or end with SP or HTAB.
|
|
||||||
func ValidHeaderFieldValue(v string) bool {
|
|
||||||
for i := 0; i < len(v); i++ {
|
|
||||||
b := v[i]
|
|
||||||
if isCTL(b) && !isLWS(b) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func isASCII(s string) bool {
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
if s[i] >= utf8.RuneSelf {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// PunycodeHostPort returns the IDNA Punycode version
|
|
||||||
// of the provided "host" or "host:port" string.
|
|
||||||
func PunycodeHostPort(v string) (string, error) {
|
|
||||||
if isASCII(v) {
|
|
||||||
return v, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
host, port, err := net.SplitHostPort(v)
|
|
||||||
if err != nil {
|
|
||||||
// The input 'v' argument was just a "host" argument,
|
|
||||||
// without a port. This error should not be returned
|
|
||||||
// to the caller.
|
|
||||||
host = v
|
|
||||||
port = ""
|
|
||||||
}
|
|
||||||
host, err = idna.ToASCII(host)
|
|
||||||
if err != nil {
|
|
||||||
// Non-UTF-8? Not representable in Punycode, in any
|
|
||||||
// case.
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if port == "" {
|
|
||||||
return host, nil
|
|
||||||
}
|
|
||||||
return net.JoinHostPort(host, port), nil
|
|
||||||
}
|
|
12
vendor/vendor.json
vendored
12
vendor/vendor.json
vendored
@ -1083,10 +1083,10 @@
|
|||||||
"revisionTime": "2018-05-30T06:29:46Z"
|
"revisionTime": "2018-05-30T06:29:46Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "Zh++JEDfXo0DKQtoKVfScwVdvww=",
|
"checksumSHA1": "pMsrfJZ8JwoPT2pBa1loXKhGODQ=",
|
||||||
"path": "golang.org/x/net/http2",
|
"path": "golang.org/x/net/http2",
|
||||||
"revision": "da118f7b8e5954f39d0d2130ab35d4bf0e3cb344",
|
"revision": "9f648a60d9775ef5c977e7669d1673a7a67bef33",
|
||||||
"revisionTime": "2017-04-23T14:02:46Z"
|
"revisionTime": "2019-03-13T06:50:29Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "CBoO1DFToP49Ezph60yZ4J4PBBs=",
|
"checksumSHA1": "CBoO1DFToP49Ezph60yZ4J4PBBs=",
|
||||||
@ -1112,12 +1112,6 @@
|
|||||||
"revision": "da118f7b8e5954f39d0d2130ab35d4bf0e3cb344",
|
"revision": "da118f7b8e5954f39d0d2130ab35d4bf0e3cb344",
|
||||||
"revisionTime": "2017-04-23T14:02:46Z"
|
"revisionTime": "2017-04-23T14:02:46Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"checksumSHA1": "3xyuaSNmClqG4YWC7g0isQIbUTc=",
|
|
||||||
"path": "golang.org/x/net/lex/httplex",
|
|
||||||
"revision": "da118f7b8e5954f39d0d2130ab35d4bf0e3cb344",
|
|
||||||
"revisionTime": "2017-04-23T14:02:46Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"checksumSHA1": "mCMW3hvbWFW1k5il9yyO7ELOdws=",
|
"checksumSHA1": "mCMW3hvbWFW1k5il9yyO7ELOdws=",
|
||||||
"path": "golang.org/x/net/proxy",
|
"path": "golang.org/x/net/proxy",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user