func checkALPN(clientProtos []string, serverProto string) error {
	if serverProto == "" {
		return nil
	}
	if len(clientProtos) == 0 {
		return errors.New("tls: server advertised unrequested ALPN extension")
	}
	for _, proto := range clientProtos {
		if proto == serverProto {
			return nil
		}
	}
	return errors.New("tls: server selected unadvertised ALPN protocol")
}
checkALPN ensure that the server's choice of ALPN protocol is compatible with
the protocols that we advertised in the Client Hello.
package tls13
import (
	"crypto/ecdsa"
	"crypto/ed25519"
	"crypto/rsa"
	"crypto/tls"
	"crypto/x509"
	"errors"
	"fmt"
	"io"
	"net"
	"strings"
	"time"
)
func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) {
	config := c.config
	if len(config.ServerName) == 0 && !config.InsecureSkipVerify {
		return nil, nil, errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config")
	}
	nextProtosLength := 0
	for _, proto := range config.NextProtos {
		if l := len(proto); l == 0 || l > 255 {
			return nil, nil, errors.New("tls: invalid NextProtos value")
		} else {
			nextProtosLength += 1 + l
		}
	}
	if nextProtosLength > 0xffff {
		return nil, nil, errors.New("tls: NextProtos values too large")
	}
	supportedVersions := configSupportedVersions(config)
	if len(supportedVersions) == 0 {
		return nil, nil, errors.New("tls: no supported versions satisfy MinVersion and MaxVersion")
	}
	clientHelloVersion := configMaxSupportedVersion(config)
	if clientHelloVersion > tls.VersionTLS12 {
		clientHelloVersion = tls.VersionTLS12
	}
	hello := &clientHelloMsg{
		vers:                         clientHelloVersion,
		compressionMethods:           []uint8{compressionNone},
		random:                       make([]byte, 32),
		ocspStapling:                 true,
		scts:                         true,
		serverName:                   hostnameInSNI(config.ServerName),
		supportedCurves:              configCurvePreferences(c.config),
		supportedPoints:              []uint8{pointFormatUncompressed},
		secureRenegotiationSupported: true,
		alpnProtocols:                config.NextProtos,
		supportedVersions:            supportedVersions,
		quicTransportParams:          c.quicTransportParams,
	}
	preferenceOrder := defaultCipherSuitesTLS13
	if !hasAESGCMHardwareSupport {
		preferenceOrder = defaultCipherSuitesTLS13NoAES
	}
	configCipherSuites := configCipherSuites(config)
	hello.cipherSuites = make([]uint16, 0, len(configCipherSuites))
	for _, suiteId := range preferenceOrder {
		suite := mutualCipherSuiteTLS13(configCipherSuites, suiteId)
		if suite == nil {
			continue
		}
		hello.cipherSuites = append(hello.cipherSuites, suiteId)
	}
	_, err := io.ReadFull(configRand(c.config), hello.random)
	if err != nil {
		return nil, nil, errors.New("tls: short read from Rand: " + err.Error())
	}
	if _, err := io.ReadFull(configRand(c.config), hello.sessionId); err != nil {
		return nil, nil, errors.New("tls: short read from Rand: " + err.Error())
	}
	if hello.vers >= tls.VersionTLS12 {
		hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms
	}
	var params ecdheParameters
	if hello.supportedVersions[0] == tls.VersionTLS13 {
		curveID := configCurvePreferences(c.config)[0]
		if _, ok := curveForCurveID(curveID); curveID != tls.X25519 && !ok {
			return nil, nil, errors.New("tls: CurvePreferences includes unsupported curve")
		}
		params, err = generateECDHEParameters(configRand(c.config), curveID)
		if err != nil {
			return nil, nil, err
		}
		hello.keyShares = []keyShare{{group: curveID, data: params.PublicKey()}}
	}
	return hello, params, nil
}
func (c *Conn) clientHandshake() (err error) {
	if c.config == nil {
		c.config = defaultConfig()
	}
	if c.clientHs != nil {
		return c.clientHs.handshake()
	}
	c.didResume = false
	hello, ecdheParams, err := c.makeClientHello()
	if err != nil {
		return err
	}
	c.serverName = hello.serverName
	cacheKey, session, earlySecret, binderKey := c.loadSession(hello)
	if cacheKey != "" && session != nil {
		defer func() {
			if err != nil && err != ErrWantRead {
				c.config.ClientSessionCache.(ClientSessionCache).PutClientSession(cacheKey, nil)
			}
		}()
	}
	if _, err := c.writeRecord(recordTypeHandshake, hello.marshal()); err != nil {
		return err
	}
	c.clientHs = &clientHandshakeStateTLS13{
		c:           c,
		hello:       hello,
		ecdheParams: ecdheParams,
		session:     session,
		earlySecret: earlySecret,
		binderKey:   binderKey,
	}
	return c.clientHs.handshake()
}
func (c *Conn) loadSession(hello *clientHelloMsg) (cacheKey string,
	session *ClientSessionState, earlySecret, binderKey []byte) {
	if c.config.SessionTicketsDisabled || c.config.ClientSessionCache == nil {
		return "", nil, nil, nil
	}
	sessionCache, ok := c.config.ClientSessionCache.(ClientSessionCache)
	if !ok {
		return "", nil, nil, nil
	}
	hello.ticketSupported = true
	if hello.supportedVersions[0] == tls.VersionTLS13 {
		hello.pskModes = []uint8{pskModeDHE}
	}
	if c.handshakes != 0 {
		return "", nil, nil, nil
	}
	cacheKey = clientSessionCacheKey(c.config)
	session, ok = sessionCache.GetClientSession(cacheKey)
	if !ok || session == nil {
		return cacheKey, nil, nil, nil
	}
	versOk := false
	for _, v := range hello.supportedVersions {
		if v == session.vers {
			versOk = true
			break
		}
	}
	if !versOk {
		return cacheKey, nil, nil, nil
	}
	if !c.config.InsecureSkipVerify {
		if len(session.verifiedChains) == 0 {
			return cacheKey, nil, nil, nil
		}
		serverCert := session.serverCertificates[0]
		if configTime(c.config).After(serverCert.NotAfter) {
			sessionCache.PutClientSession(cacheKey, nil)
			return cacheKey, nil, nil, nil
		}
		if err := serverCert.VerifyHostname(c.config.ServerName); err != nil {
			return cacheKey, nil, nil, nil
		}
	}
	if session.vers != tls.VersionTLS13 {
		return cacheKey, nil, nil, nil
	}
	if configTime(c.config).After(session.useBy) {
		sessionCache.PutClientSession(cacheKey, nil)
		return cacheKey, nil, nil, nil
	}
	cipherSuite := cipherSuiteTLS13ByID(session.cipherSuite)
	if cipherSuite == nil {
		return cacheKey, nil, nil, nil
	}
	cipherSuiteOk := false
	for _, offeredID := range hello.cipherSuites {
		offeredSuite := cipherSuiteTLS13ByID(offeredID)
		if offeredSuite != nil && offeredSuite.hash == cipherSuite.hash {
			cipherSuiteOk = true
			break
		}
	}
	if !cipherSuiteOk {
		return cacheKey, nil, nil, nil
	}
	ticketAge := uint32(configTime(c.config).Sub(session.receivedAt) / time.Millisecond)
	identity := pskIdentity{
		label:               session.sessionTicket,
		obfuscatedTicketAge: ticketAge + session.ageAdd,
	}
	hello.pskIdentities = []pskIdentity{identity}
	hello.pskBinders = [][]byte{make([]byte, cipherSuite.hash.Size())}
	psk := cipherSuite.expandLabel(session.masterSecret, "resumption",
		session.nonce, cipherSuite.hash.Size())
	earlySecret = cipherSuite.extract(psk, nil)
	binderKey = cipherSuite.deriveSecret(earlySecret, resumptionBinderLabel, nil)
	transcript := cipherSuite.hash.New()
	transcript.Write(hello.marshalWithoutBinders())
	pskBinders := [][]byte{cipherSuite.finishedHash(binderKey, transcript)}
	hello.updateBinders(pskBinders)
	return
}
func (c *Conn) pickTLSVersion(serverHello *serverHelloMsg) error {
	peerVersion := serverHello.vers
	if serverHello.supportedVersion != 0 {
		peerVersion = serverHello.supportedVersion
	}
	vers, ok := configMutualVersion(c.config, []uint16{peerVersion})
	if !ok {
		c.sendAlert(alertProtocolVersion)
		return fmt.Errorf("tls: server selected unsupported protocol version %x", peerVersion)
	}
	c.vers = vers
	c.haveVers = true
	return nil
}