code: func (tc *clientTransportCredentials) ClientHandshake(ctx context.Context, addr string, rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) {
  	var err error
  	host := tc.hostOverride
  	if host == "" {
  		// IMPORTANT: Don't wrap the errors returned from this method. gRPC expects to be
  		// able to check err.Temporary to spot temporary errors and reconnect when they happen.
  		host, _, err = net.SplitHostPort(addr)
  		if err != nil {
  			return nil, nil, err
  		}
  	}
  	conn := tls.Client(rawConn, &tls.Config{
  		ServerName:   host,
  		RootCAs:      tc.roots,
  		Certificates: tc.clients,
  		MinVersion:   tls.VersionTLS12, // Override default of tls.VersionTLS10
  		MaxVersion:   tls.VersionTLS12, // Same as default in golang <= 1.6
  	})
  	errChan := make(chan error, 1)
  	go func() {
  		errChan <- conn.Handshake()
  	}()
  	select {
  	case <-ctx.Done():
  		return nil, nil, ctx.Err()
  	case err := <-errChan:
  		if err != nil {
  			_ = rawConn.Close()
  			return nil, nil, err
  		}
  		return conn, nil, nil
  	}
  }
docs: // ClientHandshake does the authentication handshake specified by the corresponding
  // authentication protocol on rawConn for clients. It returns the authenticated
  // connection and the corresponding auth information about the connection.
  // Implementations must use the provided context to implement timely cancellation.